summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJeremy Allison <jra@samba.org>2010-03-31 17:40:30 -0700
committerJeremy Allison <jra@samba.org>2010-03-31 17:40:30 -0700
commit6800fdbb81130b79c2e077e9a7fcbe2d5e0813cb (patch)
treed2fcafbd48c8e07b02765a0863e4de03fbf447d6
parentbb54089503907745a33a09cb27ead565d1205165 (diff)
downloadsamba-6800fdbb81130b79c2e077e9a7fcbe2d5e0813cb.tar.gz
samba-6800fdbb81130b79c2e077e9a7fcbe2d5e0813cb.tar.bz2
samba-6800fdbb81130b79c2e077e9a7fcbe2d5e0813cb.zip
Make smbd_lock_socket/smbd_unlock_socket recursive with a ref_count.
As these always call exit_server, make that part of the function. Use _internal functions for the echo client. Metze please check ! Jeremy.
-rw-r--r--source3/smbd/globals.h10
-rw-r--r--source3/smbd/process.c78
-rw-r--r--source3/smbd/reply.c17
-rw-r--r--source3/smbd/smb2_read.c8
-rw-r--r--source3/smbd/smb2_server.c2
-rw-r--r--source3/smbd/smb2_write.c9
6 files changed, 68 insertions, 56 deletions
diff --git a/source3/smbd/globals.h b/source3/smbd/globals.h
index 6e5262a991..3b58cb4ef3 100644
--- a/source3/smbd/globals.h
+++ b/source3/smbd/globals.h
@@ -153,8 +153,8 @@ struct smbd_smb2_tcon;
DATA_BLOB negprot_spnego(void);
-bool smbd_lock_socket(struct smbd_server_connection *sconn);
-bool smbd_unlock_socket(struct smbd_server_connection *sconn);
+void smbd_lock_socket(struct smbd_server_connection *sconn);
+void smbd_unlock_socket(struct smbd_server_connection *sconn);
NTSTATUS smb2_signing_sign_pdu(DATA_BLOB session_key,
struct iovec *vector,
@@ -452,6 +452,12 @@ struct smbd_server_connection {
* fde for the trusted_fd
*/
struct fd_event *trusted_fde;
+
+ /*
+ * Reference count for the fcntl lock to
+ * allow recursive locks.
+ */
+ int ref_count;
} echo_handler;
uint64_t num_requests;
diff --git a/source3/smbd/process.c b/source3/smbd/process.c
index dd120f9bd2..40c85d4a62 100644
--- a/source3/smbd/process.c
+++ b/source3/smbd/process.c
@@ -40,7 +40,7 @@ extern bool global_machine_password_needs_changing;
static void construct_reply_common(struct smb_request *req, const char *inbuf,
char *outbuf);
-bool smbd_lock_socket(struct smbd_server_connection *sconn)
+static bool smbd_lock_socket_internal(struct smbd_server_connection *sconn)
{
bool ok;
@@ -48,6 +48,12 @@ bool smbd_lock_socket(struct smbd_server_connection *sconn)
return true;
}
+ smbd_server_conn->smb1.echo_handler.ref_count++;
+
+ if (smbd_server_conn->smb1.echo_handler.ref_count > 1) {
+ return true;
+ }
+
DEBUG(10,("pid[%d] wait for socket lock\n", (int)sys_getpid()));
ok = fcntl_lock(smbd_server_conn->smb1.echo_handler.socket_lock_fd,
@@ -61,7 +67,14 @@ bool smbd_lock_socket(struct smbd_server_connection *sconn)
return true;
}
-bool smbd_unlock_socket(struct smbd_server_connection *sconn)
+void smbd_lock_socket(struct smbd_server_connection *sconn)
+{
+ if (!smbd_lock_socket_internal(sconn)) {
+ exit_server_cleanly("failed to lock socket");
+ }
+}
+
+static bool smbd_unlock_socket_internal(struct smbd_server_connection *sconn)
{
bool ok;
@@ -69,6 +82,12 @@ bool smbd_unlock_socket(struct smbd_server_connection *sconn)
return true;
}
+ smbd_server_conn->smb1.echo_handler.ref_count--;
+
+ if (smbd_server_conn->smb1.echo_handler.ref_count > 0) {
+ return true;
+ }
+
ok = fcntl_lock(smbd_server_conn->smb1.echo_handler.socket_lock_fd,
SMB_F_SETLKW, 0, 0, F_UNLCK);
if (!ok) {
@@ -80,6 +99,13 @@ bool smbd_unlock_socket(struct smbd_server_connection *sconn)
return true;
}
+void smbd_unlock_socket(struct smbd_server_connection *sconn)
+{
+ if (!smbd_unlock_socket_internal(sconn)) {
+ exit_server_cleanly("failed to unlock socket");
+ }
+}
+
/* Accessor function for smb_read_error for smbd functions. */
/****************************************************************************
@@ -95,12 +121,8 @@ bool srv_send_smb(int fd, char *buffer,
size_t nwritten=0;
ssize_t ret;
char *buf_out = buffer;
- bool ok;
- ok = smbd_lock_socket(smbd_server_conn);
- if (!ok) {
- exit_server_cleanly("failed to lock socket");
- }
+ smbd_lock_socket(smbd_server_conn);
if (do_signing) {
/* Sign the outgoing packet if required. */
@@ -132,11 +154,7 @@ bool srv_send_smb(int fd, char *buffer,
out:
SMB_PERFCOUNT_END(pcd);
- ok = smbd_unlock_socket(smbd_server_conn);
- if (!ok) {
- exit_server_cleanly("failed to unlock socket");
- }
-
+ smbd_unlock_socket(smbd_server_conn);
return true;
}
@@ -2174,22 +2192,14 @@ static void smbd_server_connection_read_handler(
NTSTATUS status;
uint32_t seqnum;
- bool ok;
-
bool from_client = (smbd_server_fd() == fd)?true:false;
if (from_client) {
- ok = smbd_lock_socket(conn);
- if (!ok) {
- exit_server_cleanly("failed to lock socket");
- }
+ smbd_lock_socket(conn);
if (!fd_is_readable(smbd_server_fd())) {
DEBUG(10,("the echo listener was faster\n"));
- ok = smbd_unlock_socket(conn);
- if (!ok) {
- exit_server_cleanly("failed to unlock");
- }
+ smbd_unlock_socket(conn);
return;
}
@@ -2201,10 +2211,7 @@ static void smbd_server_connection_read_handler(
&encrypted,
&inbuf_len, &seqnum,
false /* trusted channel */);
- ok = smbd_unlock_socket(conn);
- if (!ok) {
- exit_server_cleanly("failed to unlock");
- }
+ smbd_unlock_socket(conn);
} else {
/* TODO: make this completely nonblocking */
status = receive_smb_talloc(mem_ctx, fd,
@@ -2321,20 +2328,11 @@ static int client_get_tcp_info(struct sockaddr_storage *server,
*/
static bool keepalive_fn(const struct timeval *now, void *private_data)
{
- bool ok;
bool ret;
- ok = smbd_lock_socket(smbd_server_conn);
- if (!ok) {
- exit_server_cleanly("failed to lock socket");
- }
-
+ smbd_lock_socket(smbd_server_conn);
ret = send_keepalive(smbd_server_fd());
-
- ok = smbd_unlock_socket(smbd_server_conn);
- if (!ok) {
- exit_server_cleanly("failed to unlock socket");
- }
+ smbd_unlock_socket(smbd_server_conn);
if (!ret) {
DEBUG( 2, ( "Keepalive failed - exiting.\n" ) );
@@ -2574,7 +2572,7 @@ static void smbd_echo_reader(struct tevent_context *ev,
bool ok;
bool encrypted = false;
- ok = smbd_lock_socket(sconn);
+ ok = smbd_lock_socket_internal(sconn);
if (!ok) {
DEBUG(0, ("%s: failed to lock socket\n",
__location__));
@@ -2584,7 +2582,7 @@ static void smbd_echo_reader(struct tevent_context *ev,
if (!fd_is_readable(smbd_server_fd())) {
DEBUG(10,("echo_handler[%d] the parent smbd was faster\n",
(int)sys_getpid()));
- ok = smbd_unlock_socket(sconn);
+ ok = smbd_unlock_socket_internal(sconn);
if (!ok) {
DEBUG(1, ("%s: failed to unlock socket in\n",
__location__));
@@ -2618,7 +2616,7 @@ static void smbd_echo_reader(struct tevent_context *ev,
exit(1);
}
- ok = smbd_unlock_socket(sconn);
+ ok = smbd_unlock_socket_internal(sconn);
if (!ok) {
DEBUG(1, ("%s: failed to unlock socket in\n",
__location__));
diff --git a/source3/smbd/reply.c b/source3/smbd/reply.c
index c34e7f8b06..e2aca3793a 100644
--- a/source3/smbd/reply.c
+++ b/source3/smbd/reply.c
@@ -2895,22 +2895,15 @@ static void sendfile_short_send(files_struct *fsp,
static void reply_readbraw_error(void)
{
- bool ok;
char header[4];
SIVAL(header,0,0);
- ok = smbd_lock_socket(smbd_server_conn);
- if (!ok) {
- exit_server_cleanly("failed to lock socket");
- }
+ smbd_lock_socket(smbd_server_conn);
if (write_data(smbd_server_fd(),header,4) != 4) {
fail_readraw();
}
- ok = smbd_unlock_socket(smbd_server_conn);
- if (!ok) {
- exit_server_cleanly("failed to unlock socket");
- }
+ smbd_unlock_socket(smbd_server_conn);
}
/****************************************************************************
@@ -3462,10 +3455,6 @@ static void send_file_readX(connection_struct *conn, struct smb_request *req,
goto nosendfile_read;
}
- if (smbd_server_conn->smb1.echo_handler.trusted_fde) {
- goto nosendfile_read;
- }
-
#if defined(WITH_SENDFILE)
/*
* We can only use sendfile on a non-chained packet
@@ -3714,7 +3703,9 @@ void reply_read_and_X(struct smb_request *req)
goto out;
}
+ smbd_lock_socket(smbd_server_conn);
send_file_readX(conn, req, fsp, startpos, smb_maxcnt);
+ smbd_unlock_socket(smbd_server_conn);
out:
END_PROFILE(SMBreadX);
diff --git a/source3/smbd/smb2_read.c b/source3/smbd/smb2_read.c
index 3f316e0b71..674fa2b71f 100644
--- a/source3/smbd/smb2_read.c
+++ b/source3/smbd/smb2_read.c
@@ -275,6 +275,14 @@ static struct tevent_req *smbd_smb2_read_send(TALLOC_CTX *mem_ctx,
SMB_VFS_STRICT_UNLOCK(conn, fsp, &lock);
+ DEBUG(10,("smbd_smb2_read: file %s handle [0x%016llX] offset=%llu "
+ "len=%llu returned %lld\n",
+ fsp_str_dbg(fsp),
+ (unsigned long long)in_file_id_volatile,
+ (unsigned long long)in_offset,
+ (unsigned long long)in_length,
+ (long long)nread));
+
if (nread < 0) {
DEBUG(5,("smbd_smb2_read: read_file[%s] nread[%lld]\n",
fsp_str_dbg(fsp), (long long)nread));
diff --git a/source3/smbd/smb2_server.c b/source3/smbd/smb2_server.c
index 1d95d4be3f..c64f82f407 100644
--- a/source3/smbd/smb2_server.c
+++ b/source3/smbd/smb2_server.c
@@ -1566,7 +1566,7 @@ static void smbd_smb2_request_incoming(struct tevent_req *subreq)
return;
}
- status = smbd_smb2_request_setup_out(req, creds_requested);
+ status = smbd_smb2_request_setup_out(req, 5);
if (!NT_STATUS_IS_OK(status)) {
smbd_server_connection_terminate(sconn, nt_errstr(status));
return;
diff --git a/source3/smbd/smb2_write.c b/source3/smbd/smb2_write.c
index fa209fafc7..17d562affa 100644
--- a/source3/smbd/smb2_write.c
+++ b/source3/smbd/smb2_write.c
@@ -266,6 +266,15 @@ static struct tevent_req *smbd_smb2_write_send(TALLOC_CTX *mem_ctx,
in_offset,
in_data.length);
+
+ DEBUG(10,("smbd_smb2_write: file %s handle [0x%016llX] offset=%llu "
+ "len=%llu returned %lld\n",
+ fsp_str_dbg(fsp),
+ (unsigned long long)in_file_id_volatile,
+ (unsigned long long)in_offset,
+ (unsigned long long)in_data.length,
+ (long long)nwritten));
+
if (((nwritten == 0) && (in_data.length != 0)) || (nwritten < 0)) {
DEBUG(5,("smbd_smb2_write: write_file[%s] disk full\n",
fsp_str_dbg(fsp)));