s3:smb2_server: propagate NTSTATUS from smb2_sendfile_send_data() to smbd_smb2_flush_...
authorStefan Metzmacher <metze@samba.org>
Fri, 11 Jul 2014 00:25:00 +0000 (02:25 +0200)
committerMichael Adam <obnox@samba.org>
Wed, 6 Aug 2014 07:51:14 +0000 (09:51 +0200)
Calling exit_server() from within a destructor is a bit ugly...

This will result in smbd_server_connection_terminate() instead of
directly calling exit_server(), which will be useful for multi-channel in
future.

Signed-off-by: Stefan Metzmacher <metze@samba.org>
Reviewed-by: Volker Lendecke <vl@samba.org>
Reviewed-by: Michael Adam <obnox@samba.org>
source3/smbd/globals.h
source3/smbd/smb2_read.c
source3/smbd/smb2_server.c

index 8a9af6c5319832e1b262f013393ec77fe90e3c37..079976eefb5d84be021461723580a0ef46d4f0a5 100644 (file)
@@ -615,6 +615,7 @@ struct smbd_smb2_send_queue {
        struct smbd_smb2_send_queue *prev, *next;
 
        DATA_BLOB *sendfile_header;
+       NTSTATUS *sendfile_status;
        struct iovec *vector;
        int count;
 
index 0d08114a2750dd4fe619920f8de9ca2c53e8e965..470e496631e8707833f5d55ee72e6a8534c2934a 100644 (file)
@@ -186,6 +186,7 @@ static int smb2_sendfile_send_data(struct smbd_smb2_read_state *state)
        uint64_t in_offset = state->in_offset;
        files_struct *fsp = state->fsp;
        const DATA_BLOB *hdr = state->smb2req->queue_entry.sendfile_header;
+       NTSTATUS *pstatus = state->smb2req->queue_entry.sendfile_status;
        struct smbXsrv_connection *xconn = state->smb2req->xconn;
        ssize_t nread;
        ssize_t ret;
@@ -225,8 +226,8 @@ static int smb2_sendfile_send_data(struct smbd_smb2_read_state *state)
                                         "Terminating\n",
                                         fsp_str_dbg(fsp), strerror(saved_errno),
                                         smbXsrv_connection_dbg(xconn)));
-                               exit_server_cleanly("smb2_sendfile_send_data: "
-                                       "fake_sendfile failed");
+                               *pstatus = map_nt_error_from_unix_common(saved_errno);
+                               return 0;
                        }
                        goto out;
                }
@@ -235,7 +236,8 @@ static int smb2_sendfile_send_data(struct smbd_smb2_read_state *state)
                         "%s (%s) for client %s. Terminating\n",
                         fsp_str_dbg(fsp), strerror(saved_errno),
                         smbXsrv_connection_dbg(xconn)));
-               exit_server_cleanly("smb2_sendfile_send_data: sendfile failed");
+               *pstatus = map_nt_error_from_unix_common(saved_errno);
+               return 0;
        } else if (nread == 0) {
                /*
                 * Some sendfile implementations return 0 to indicate
@@ -265,7 +267,8 @@ normal_read:
                         "%s (%s) for client %s. Terminating\n",
                         fsp_str_dbg(fsp), strerror(saved_errno),
                         smbXsrv_connection_dbg(xconn)));
-               exit_server_cleanly("smb2_sendfile_send_data: write_data failed");
+               *pstatus = map_nt_error_from_unix_common(saved_errno);
+               return 0;
        }
        nread = fake_sendfile(xconn, fsp, in_offset, in_length);
        if (nread == -1) {
@@ -275,8 +278,8 @@ normal_read:
                         "Terminating\n",
                         fsp_str_dbg(fsp), strerror(saved_errno),
                         smbXsrv_connection_dbg(xconn)));
-               exit_server_cleanly("smb2_sendfile_send_data: "
-                       "fake_sendfile failed");
+               *pstatus = map_nt_error_from_unix_common(saved_errno);
+               return 0;
        }
 
   out:
@@ -292,8 +295,8 @@ normal_read:
                                 __func__,
                                 fsp_str_dbg(fsp), strerror(saved_errno),
                                 smbXsrv_connection_dbg(xconn)));
-                       exit_server_cleanly("smb2_sendfile_send_data: "
-                               "sendfile_short_send failed");
+                       *pstatus = map_nt_error_from_unix_common(saved_errno);
+                       return 0;
                }
        }
 
@@ -305,6 +308,8 @@ normal_read:
                                &lock);
 
        SMB_VFS_STRICT_UNLOCK(fsp->conn, fsp, &lock);
+
+       *pstatus = NT_STATUS_OK;
        return 0;
 }
 
index d9e6a7644d5984335570b4d04ba971e5b7383876..984d4406aa2d7b5c9132653be2d75ca25aaafe27 100644 (file)
@@ -3115,6 +3115,7 @@ static NTSTATUS smbd_smb2_flush_send_queue(struct smbXsrv_connection *xconn)
                struct smbd_smb2_send_queue *e = xconn->smb2.send_queue;
 
                if (e->sendfile_header != NULL) {
+                       NTSTATUS status = NT_STATUS_INTERNAL_ERROR;
                        size_t size = 0;
                        size_t i = 0;
                        uint8_t *buf;
@@ -3142,6 +3143,7 @@ static NTSTATUS smbd_smb2_flush_send_queue(struct smbXsrv_connection *xconn)
 
                        e->sendfile_header->data = buf;
                        e->sendfile_header->length = size;
+                       e->sendfile_status = &status;
                        e->count = 0;
 
                        xconn->smb2.send_queue_len--;
@@ -3151,6 +3153,10 @@ static NTSTATUS smbd_smb2_flush_send_queue(struct smbXsrv_connection *xconn)
                         * the destructor.
                         */
                        talloc_free(e->mem_ctx);
+
+                       if (!NT_STATUS_IS_OK(status)) {
+                               return status;
+                       }
                        continue;
                }