]> git.ipfire.org Git - thirdparty/samba.git/commitdiff
smbd: Move schedule_aio_read_and_X to smb1_aio.c
authorDavid Mulder <dmulder@suse.com>
Fri, 11 Mar 2022 16:17:59 +0000 (09:17 -0700)
committerJeremy Allison <jra@samba.org>
Thu, 7 Apr 2022 17:37:29 +0000 (17:37 +0000)
Signed-off-by: David Mulder <dmulder@suse.com>
Reviewed-by: Jeremy Allison <jra@samba.org>
source3/smbd/aio.c
source3/smbd/globals.h
source3/smbd/proto.h
source3/smbd/smb1_aio.c [new file with mode: 0644]
source3/smbd/smb1_aio.h [new file with mode: 0644]
source3/smbd/smbd.h
source3/wscript_build

index 0aa2b2fdfccd4cba1ce4b85397427d9a114a8c60..6f908e9f183c4d8e222d289f12964e6876bb7e08 100644 (file)
 #include "../lib/util/tevent_ntstatus.h"
 #include "../lib/util/tevent_unix.h"
 
-/****************************************************************************
- The buffer we keep around whilst an aio request is in process.
-*****************************************************************************/
-
-struct aio_extra {
-       files_struct *fsp;
-       struct smb_request *smbreq;
-       DATA_BLOB outbuf;
-       struct lock_struct lock;
-       size_t nbyte;
-       off_t offset;
-       bool write_through;
-};
-
 /****************************************************************************
  Accessor function to return write_through state.
 *****************************************************************************/
@@ -52,9 +38,9 @@ bool aio_write_through_requested(struct aio_extra *aio_ex)
  of the aio call.
 *****************************************************************************/
 
-static struct aio_extra *create_aio_extra(TALLOC_CTX *mem_ctx,
-                                       files_struct *fsp,
-                                       size_t buflen)
+struct aio_extra *create_aio_extra(TALLOC_CTX *mem_ctx,
+                                  files_struct *fsp,
+                                  size_t buflen)
 {
        struct aio_extra *aio_ex = talloc_zero(mem_ctx, struct aio_extra);
 
@@ -149,176 +135,6 @@ bool aio_add_req_to_fsp(files_struct *fsp, struct tevent_req *req)
        return true;
 }
 
-static void aio_pread_smb1_done(struct tevent_req *req);
-
-/****************************************************************************
- Set up an aio request from a SMBreadX call.
-*****************************************************************************/
-
-NTSTATUS schedule_aio_read_and_X(connection_struct *conn,
-                            struct smb_request *smbreq,
-                            files_struct *fsp, off_t startpos,
-                            size_t smb_maxcnt)
-{
-       struct aio_extra *aio_ex;
-       size_t bufsize;
-       size_t min_aio_read_size = lp_aio_read_size(SNUM(conn));
-       struct tevent_req *req;
-       bool ok;
-
-       ok = vfs_valid_pread_range(startpos, smb_maxcnt);
-       if (!ok) {
-               return NT_STATUS_INVALID_PARAMETER;
-       }
-
-       if (fsp_is_alternate_stream(fsp)) {
-               DEBUG(10, ("AIO on streams not yet supported\n"));
-               return NT_STATUS_RETRY;
-       }
-
-       if ((!min_aio_read_size || (smb_maxcnt < min_aio_read_size))
-           && !SMB_VFS_AIO_FORCE(fsp)) {
-               /* Too small a read for aio request. */
-               DEBUG(10,("schedule_aio_read_and_X: read size (%u) too small "
-                         "for minimum aio_read of %u\n",
-                         (unsigned int)smb_maxcnt,
-                         (unsigned int)min_aio_read_size ));
-               return NT_STATUS_RETRY;
-       }
-
-       /* Only do this on non-chained and non-chaining reads */
-        if (req_is_in_chain(smbreq)) {
-               return NT_STATUS_RETRY;
-       }
-
-       /* The following is safe from integer wrap as we've already checked
-          smb_maxcnt is 128k or less. Wct is 12 for read replies */
-
-       bufsize = smb_size + 12 * 2 + smb_maxcnt + 1 /* padding byte */;
-
-       if ((aio_ex = create_aio_extra(NULL, fsp, bufsize)) == NULL) {
-               DEBUG(10,("schedule_aio_read_and_X: malloc fail.\n"));
-               return NT_STATUS_NO_MEMORY;
-       }
-
-       construct_reply_common_req(smbreq, (char *)aio_ex->outbuf.data);
-       srv_set_message((char *)aio_ex->outbuf.data, 12, 0, True);
-       SCVAL(aio_ex->outbuf.data,smb_vwv0,0xFF); /* Never a chained reply. */
-       SCVAL(smb_buf(aio_ex->outbuf.data), 0, 0); /* padding byte */
-
-       init_strict_lock_struct(fsp,
-                       (uint64_t)smbreq->smbpid,
-                       (uint64_t)startpos,
-                       (uint64_t)smb_maxcnt,
-                       READ_LOCK,
-                       lp_posix_cifsu_locktype(fsp),
-                       &aio_ex->lock);
-
-       /* Take the lock until the AIO completes. */
-       if (!SMB_VFS_STRICT_LOCK_CHECK(conn, fsp, &aio_ex->lock)) {
-               TALLOC_FREE(aio_ex);
-               return NT_STATUS_FILE_LOCK_CONFLICT;
-       }
-
-       aio_ex->nbyte = smb_maxcnt;
-       aio_ex->offset = startpos;
-
-       req = SMB_VFS_PREAD_SEND(aio_ex, fsp->conn->sconn->ev_ctx,
-                                fsp,
-                                smb_buf(aio_ex->outbuf.data) + 1 /* pad */,
-                                smb_maxcnt, startpos);
-       if (req == NULL) {
-               DEBUG(0,("schedule_aio_read_and_X: aio_read failed. "
-                        "Error %s\n", strerror(errno) ));
-               TALLOC_FREE(aio_ex);
-               return NT_STATUS_RETRY;
-       }
-       tevent_req_set_callback(req, aio_pread_smb1_done, aio_ex);
-
-       if (!aio_add_req_to_fsp(fsp, req)) {
-               DEBUG(1, ("Could not add req to fsp\n"));
-               TALLOC_FREE(aio_ex);
-               return NT_STATUS_RETRY;
-       }
-
-       aio_ex->smbreq = talloc_move(aio_ex, &smbreq);
-
-       DEBUG(10,("schedule_aio_read_and_X: scheduled aio_read for file %s, "
-                 "offset %.0f, len = %u (mid = %u)\n",
-                 fsp_str_dbg(fsp), (double)startpos, (unsigned int)smb_maxcnt,
-                 (unsigned int)aio_ex->smbreq->mid ));
-
-       return NT_STATUS_OK;
-}
-
-static void aio_pread_smb1_done(struct tevent_req *req)
-{
-       struct aio_extra *aio_ex = tevent_req_callback_data(
-               req, struct aio_extra);
-       files_struct *fsp = aio_ex->fsp;
-       size_t outsize;
-       char *outbuf = (char *)aio_ex->outbuf.data;
-       ssize_t nread;
-       struct vfs_aio_state vfs_aio_state;
-
-       nread = SMB_VFS_PREAD_RECV(req, &vfs_aio_state);
-       TALLOC_FREE(req);
-
-       DEBUG(10, ("pread_recv returned %d, err = %s\n", (int)nread,
-                  (nread == -1) ? strerror(vfs_aio_state.error) : "no error"));
-
-       if (fsp == NULL) {
-               DEBUG( 3, ("aio_pread_smb1_done: file closed whilst "
-                          "aio outstanding (mid[%llu]).\n",
-                          (unsigned long long)aio_ex->smbreq->mid));
-               TALLOC_FREE(aio_ex);
-               return;
-       }
-
-       if (nread < 0) {
-               DEBUG( 3, ("handle_aio_read_complete: file %s nread == %d. "
-                          "Error = %s\n", fsp_str_dbg(fsp), (int)nread,
-                          strerror(vfs_aio_state.error)));
-
-               ERROR_NT(map_nt_error_from_unix(vfs_aio_state.error));
-               outsize = srv_set_message(outbuf,0,0,true);
-       } else {
-               outsize = setup_readX_header(outbuf, nread);
-
-               fh_set_pos(aio_ex->fsp->fh, aio_ex->offset + nread);
-               fh_set_position_information(aio_ex->fsp->fh,
-                                           fh_get_pos(aio_ex->fsp->fh));
-
-               DEBUG( 3, ("handle_aio_read_complete file %s max=%d "
-                          "nread=%d\n", fsp_str_dbg(fsp),
-                          (int)aio_ex->nbyte, (int)nread ) );
-
-       }
-
-       if (outsize <= 4) {
-               DBG_INFO("Invalid outsize (%zu)\n", outsize);
-               TALLOC_FREE(aio_ex);
-               return;
-       }
-       outsize -= 4;
-       _smb_setlen_large(outbuf, outsize);
-
-       show_msg(outbuf);
-       if (!srv_send_smb(aio_ex->smbreq->xconn, outbuf,
-                         true, aio_ex->smbreq->seqnum+1,
-                         IS_CONN_ENCRYPTED(fsp->conn), NULL)) {
-               exit_server_cleanly("handle_aio_read_complete: srv_send_smb "
-                                   "failed.");
-       }
-
-       DEBUG(10, ("handle_aio_read_complete: scheduled aio_read completed "
-                  "for file %s, offset %.0f, len = %u\n",
-                  fsp_str_dbg(fsp), (double)aio_ex->offset,
-                  (unsigned int)nread));
-
-       TALLOC_FREE(aio_ex);
-}
-
 struct pwrite_fsync_state {
        struct tevent_context *ev;
        files_struct *fsp;
index 70cb1d0327a0c4fe28f1bd917679ddc7441271d6..223a512182b1cc377d1b13294dae16b8d470045b 100644 (file)
@@ -914,4 +914,18 @@ extern struct smbXsrv_client *global_smbXsrv_client;
 
 void smbd_init_globals(void);
 
+/****************************************************************************
+ The buffer we keep around whilst an aio request is in process.
+*****************************************************************************/
+
+struct aio_extra {
+       files_struct *fsp;
+       struct smb_request *smbreq;
+       DATA_BLOB outbuf;
+       struct lock_struct lock;
+       size_t nbyte;
+       off_t offset;
+       bool write_through;
+};
+
 #endif /* _SOURCE3_SMBD_GLOBALS_H_ */
index acb6a63f7fa504a43b0e3b79a54f7541aae9bb80..94229a45b8f60f12515e3a7d252570d9292d0824 100644 (file)
@@ -70,10 +70,6 @@ void smb1_srv_set_signing(struct smbXsrv_connection *conn,
 
 struct aio_extra;
 bool aio_write_through_requested(struct aio_extra *aio_ex);
-NTSTATUS schedule_aio_read_and_X(connection_struct *conn,
-                            struct smb_request *req,
-                            files_struct *fsp, off_t startpos,
-                            size_t smb_maxcnt);
 NTSTATUS schedule_aio_write_and_X(connection_struct *conn,
                              struct smb_request *req,
                              files_struct *fsp, const char *data,
@@ -94,6 +90,9 @@ NTSTATUS schedule_aio_smb2_write(connection_struct *conn,
                                bool write_through);
 bool cancel_smb2_aio(struct smb_request *smbreq);
 bool aio_add_req_to_fsp(files_struct *fsp, struct tevent_req *req);
+struct aio_extra *create_aio_extra(TALLOC_CTX *mem_ctx,
+                                  files_struct *fsp,
+                                  size_t buflen);
 
 /* The following definitions come from smbd/blocking.c  */
 
diff --git a/source3/smbd/smb1_aio.c b/source3/smbd/smb1_aio.c
new file mode 100644 (file)
index 0000000..f11f239
--- /dev/null
@@ -0,0 +1,195 @@
+/*
+   Unix SMB/Netbios implementation.
+   Version 3.0
+   async_io read handling using POSIX async io.
+   Copyright (C) Jeremy Allison 2005.
+
+   This program is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 3 of the License, or
+   (at your option) any later version.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program.  If not, see <http://www.gnu.org/licenses/>.
+*/
+
+#include "includes.h"
+#include "smbd/smbd.h"
+#include "smbd/globals.h"
+#include "../lib/util/tevent_ntstatus.h"
+#include "../lib/util/tevent_unix.h"
+
+static void aio_pread_smb1_done(struct tevent_req *req);
+
+/****************************************************************************
+ Set up an aio request from a SMBreadX call.
+*****************************************************************************/
+
+NTSTATUS schedule_aio_read_and_X(connection_struct *conn,
+                            struct smb_request *smbreq,
+                            files_struct *fsp, off_t startpos,
+                            size_t smb_maxcnt)
+{
+       struct aio_extra *aio_ex;
+       size_t bufsize;
+       size_t min_aio_read_size = lp_aio_read_size(SNUM(conn));
+       struct tevent_req *req;
+       bool ok;
+
+       ok = vfs_valid_pread_range(startpos, smb_maxcnt);
+       if (!ok) {
+               return NT_STATUS_INVALID_PARAMETER;
+       }
+
+       if (fsp_is_alternate_stream(fsp)) {
+               DEBUG(10, ("AIO on streams not yet supported\n"));
+               return NT_STATUS_RETRY;
+       }
+
+       if ((!min_aio_read_size || (smb_maxcnt < min_aio_read_size))
+           && !SMB_VFS_AIO_FORCE(fsp)) {
+               /* Too small a read for aio request. */
+               DEBUG(10,("schedule_aio_read_and_X: read size (%u) too small "
+                         "for minimum aio_read of %u\n",
+                         (unsigned int)smb_maxcnt,
+                         (unsigned int)min_aio_read_size ));
+               return NT_STATUS_RETRY;
+       }
+
+       /* Only do this on non-chained and non-chaining reads */
+        if (req_is_in_chain(smbreq)) {
+               return NT_STATUS_RETRY;
+       }
+
+       /* The following is safe from integer wrap as we've already checked
+          smb_maxcnt is 128k or less. Wct is 12 for read replies */
+
+       bufsize = smb_size + 12 * 2 + smb_maxcnt + 1 /* padding byte */;
+
+       if ((aio_ex = create_aio_extra(NULL, fsp, bufsize)) == NULL) {
+               DEBUG(10,("schedule_aio_read_and_X: malloc fail.\n"));
+               return NT_STATUS_NO_MEMORY;
+       }
+
+       construct_reply_common_req(smbreq, (char *)aio_ex->outbuf.data);
+       srv_set_message((char *)aio_ex->outbuf.data, 12, 0, True);
+       SCVAL(aio_ex->outbuf.data,smb_vwv0,0xFF); /* Never a chained reply. */
+       SCVAL(smb_buf(aio_ex->outbuf.data), 0, 0); /* padding byte */
+
+       init_strict_lock_struct(fsp,
+                       (uint64_t)smbreq->smbpid,
+                       (uint64_t)startpos,
+                       (uint64_t)smb_maxcnt,
+                       READ_LOCK,
+                       lp_posix_cifsu_locktype(fsp),
+                       &aio_ex->lock);
+
+       /* Take the lock until the AIO completes. */
+       if (!SMB_VFS_STRICT_LOCK_CHECK(conn, fsp, &aio_ex->lock)) {
+               TALLOC_FREE(aio_ex);
+               return NT_STATUS_FILE_LOCK_CONFLICT;
+       }
+
+       aio_ex->nbyte = smb_maxcnt;
+       aio_ex->offset = startpos;
+
+       req = SMB_VFS_PREAD_SEND(aio_ex, fsp->conn->sconn->ev_ctx,
+                                fsp,
+                                smb_buf(aio_ex->outbuf.data) + 1 /* pad */,
+                                smb_maxcnt, startpos);
+       if (req == NULL) {
+               DEBUG(0,("schedule_aio_read_and_X: aio_read failed. "
+                        "Error %s\n", strerror(errno) ));
+               TALLOC_FREE(aio_ex);
+               return NT_STATUS_RETRY;
+       }
+       tevent_req_set_callback(req, aio_pread_smb1_done, aio_ex);
+
+       if (!aio_add_req_to_fsp(fsp, req)) {
+               DEBUG(1, ("Could not add req to fsp\n"));
+               TALLOC_FREE(aio_ex);
+               return NT_STATUS_RETRY;
+       }
+
+       aio_ex->smbreq = talloc_move(aio_ex, &smbreq);
+
+       DEBUG(10,("schedule_aio_read_and_X: scheduled aio_read for file %s, "
+                 "offset %.0f, len = %u (mid = %u)\n",
+                 fsp_str_dbg(fsp), (double)startpos, (unsigned int)smb_maxcnt,
+                 (unsigned int)aio_ex->smbreq->mid ));
+
+       return NT_STATUS_OK;
+}
+
+static void aio_pread_smb1_done(struct tevent_req *req)
+{
+       struct aio_extra *aio_ex = tevent_req_callback_data(
+               req, struct aio_extra);
+       files_struct *fsp = aio_ex->fsp;
+       size_t outsize;
+       char *outbuf = (char *)aio_ex->outbuf.data;
+       ssize_t nread;
+       struct vfs_aio_state vfs_aio_state;
+
+       nread = SMB_VFS_PREAD_RECV(req, &vfs_aio_state);
+       TALLOC_FREE(req);
+
+       DEBUG(10, ("pread_recv returned %d, err = %s\n", (int)nread,
+                  (nread == -1) ? strerror(vfs_aio_state.error) : "no error"));
+
+       if (fsp == NULL) {
+               DEBUG( 3, ("aio_pread_smb1_done: file closed whilst "
+                          "aio outstanding (mid[%llu]).\n",
+                          (unsigned long long)aio_ex->smbreq->mid));
+               TALLOC_FREE(aio_ex);
+               return;
+       }
+
+       if (nread < 0) {
+               DEBUG( 3, ("handle_aio_read_complete: file %s nread == %d. "
+                          "Error = %s\n", fsp_str_dbg(fsp), (int)nread,
+                          strerror(vfs_aio_state.error)));
+
+               ERROR_NT(map_nt_error_from_unix(vfs_aio_state.error));
+               outsize = srv_set_message(outbuf,0,0,true);
+       } else {
+               outsize = setup_readX_header(outbuf, nread);
+
+               fh_set_pos(aio_ex->fsp->fh, aio_ex->offset + nread);
+               fh_set_position_information(aio_ex->fsp->fh,
+                                           fh_get_pos(aio_ex->fsp->fh));
+
+               DEBUG( 3, ("handle_aio_read_complete file %s max=%d "
+                          "nread=%d\n", fsp_str_dbg(fsp),
+                          (int)aio_ex->nbyte, (int)nread ) );
+
+       }
+
+       if (outsize <= 4) {
+               DBG_INFO("Invalid outsize (%zu)\n", outsize);
+               TALLOC_FREE(aio_ex);
+               return;
+       }
+       outsize -= 4;
+       _smb_setlen_large(outbuf, outsize);
+
+       show_msg(outbuf);
+       if (!srv_send_smb(aio_ex->smbreq->xconn, outbuf,
+                         true, aio_ex->smbreq->seqnum+1,
+                         IS_CONN_ENCRYPTED(fsp->conn), NULL)) {
+               exit_server_cleanly("handle_aio_read_complete: srv_send_smb "
+                                   "failed.");
+       }
+
+       DEBUG(10, ("handle_aio_read_complete: scheduled aio_read completed "
+                  "for file %s, offset %.0f, len = %u\n",
+                  fsp_str_dbg(fsp), (double)aio_ex->offset,
+                  (unsigned int)nread));
+
+       TALLOC_FREE(aio_ex);
+}
diff --git a/source3/smbd/smb1_aio.h b/source3/smbd/smb1_aio.h
new file mode 100644 (file)
index 0000000..ecd0278
--- /dev/null
@@ -0,0 +1,24 @@
+/*
+   Unix SMB/Netbios implementation.
+   Version 3.0
+   async_io read handling using POSIX async io.
+   Copyright (C) Jeremy Allison 2005.
+
+   This program is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 3 of the License, or
+   (at your option) any later version.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program.  If not, see <http://www.gnu.org/licenses/>.
+*/
+
+NTSTATUS schedule_aio_read_and_X(connection_struct *conn,
+                            struct smb_request *req,
+                            files_struct *fsp, off_t startpos,
+                            size_t smb_maxcnt);
index 3feecb2a17c283930b18945f4df377896d729c0c..dcd0d2f96fc9bfae960f6d0a62e93261137ff89c 100644 (file)
@@ -30,6 +30,7 @@ struct dptr_struct;
 #include "smbd/smb1_message.h"
 #include "smbd/smb1_sesssetup.h"
 #include "smbd/smb1_lanman.h"
+#include "smbd/smb1_aio.h"
 #endif
 
 struct trans_state {
index 3ba48d3c0d1a18a4f3fa9823db3139a02f006520..2e30ddefc60d1607b89e771697baab87e1ea84c3 100644 (file)
@@ -603,6 +603,7 @@ if bld.CONFIG_SET('WITH_SMB1SERVER'):
                    smbd/smb1_sesssetup.c
                    smbd/smb1_lanman.c
                    smbd/smb1_utils.c
+                   smbd/smb1_aio.c
     '''
 else:
     SMB1_SOURCES = ''