Make smbd_lock_socket/smbd_unlock_socket recursive with a ref_count.
authorJeremy Allison <jra@samba.org>
Thu, 1 Apr 2010 00:40:30 +0000 (17:40 -0700)
committerJeremy Allison <jra@samba.org>
Thu, 1 Apr 2010 00:40:30 +0000 (17:40 -0700)
As these always call exit_server, make that part of the function.
Use _internal functions for the echo client.

Metze please check !

Jeremy.

source3/smbd/globals.h
source3/smbd/process.c
source3/smbd/reply.c
source3/smbd/smb2_read.c
source3/smbd/smb2_server.c
source3/smbd/smb2_write.c

index 6e5262a9917bc7585dff9a79dab94d99c886a092..3b58cb4ef3a9211d424fa554172215c355ab3865 100644 (file)
@@ -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;
index dd120f9bd2785beb62556bdfe37c34d63ff6f45f..40c85d4a621cd9e8d5eece7cf12232e20127d15e 100644 (file)
@@ -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__));
index c34e7f8b067737cdd707b55f967727f142b7f4ab..e2aca3793a46b0773009b67dcd9bfaf878b4b6b0 100644 (file)
@@ -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);
index 3f316e0b71aad2f34555c4f96fc889145fa89192..674fa2b71f8ec2f45fa7b9bbaf0b5ff81f3ebb1d 100644 (file)
@@ -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));
index 1d95d4be3fc656bfe36cb14c799f3d17d38e56ed..c64f82f407ad67240798e484bd07d5b6a31d1baa 100644 (file)
@@ -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;
index fa209fafc73170c006f1de6a1ee718365ea096a7..17d562affa11971fba043fb39506255ef74df1f5 100644 (file)
@@ -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)));