s3/vfs: remove SMB_VFS_STRICT_UNLOCK
[samba.git] / source3 / smbd / aio.c
index e8be408eaa1279963b07ecc1264a736a0ab350ca..a9d6c0a5948bce5c954a2f81496927c0068a57de 100644 (file)
 #include "../lib/util/tevent_unix.h"
 #include "lib/tevent_wait.h"
 
+/****************************************************************************
+ Statics plus accessor functions.
+*****************************************************************************/
+
+static int outstanding_aio_calls;
+
+int get_outstanding_aio_calls(void)
+{
+       return outstanding_aio_calls;
+}
+
+void increment_outstanding_aio_calls(void)
+{
+       outstanding_aio_calls++;
+}
+
+void decrement_outstanding_aio_calls(void)
+{
+       outstanding_aio_calls--;
+}
+
 /****************************************************************************
  The buffer we keep around whilst an aio request is in process.
 *****************************************************************************/
@@ -50,7 +71,7 @@ bool aio_write_through_requested(struct aio_extra *aio_ex)
 
 static int aio_extra_destructor(struct aio_extra *aio_ex)
 {
-       outstanding_aio_calls--;
+       decrement_outstanding_aio_calls();
        return 0;
 }
 
@@ -82,7 +103,7 @@ static struct aio_extra *create_aio_extra(TALLOC_CTX *mem_ctx,
        }
        talloc_set_destructor(aio_ex, aio_extra_destructor);
        aio_ex->fsp = fsp;
-       outstanding_aio_calls++;
+       increment_outstanding_aio_calls();
        return aio_ex;
 }
 
@@ -115,7 +136,7 @@ static int aio_del_req_from_fsp(struct aio_req_fsp_link *lnk)
        return 0;
 }
 
-static bool aio_add_req_to_fsp(files_struct *fsp, struct tevent_req *req)
+bool aio_add_req_to_fsp(files_struct *fsp, struct tevent_req *req)
 {
        size_t array_len;
        struct aio_req_fsp_link *lnk;
@@ -186,17 +207,10 @@ NTSTATUS schedule_aio_read_and_X(connection_struct *conn,
                return NT_STATUS_RETRY;
        }
 
-       if (outstanding_aio_calls >= aio_pending_size) {
-               DEBUG(10,("schedule_aio_read_and_X: Already have %d aio "
-                         "activities outstanding.\n",
-                         outstanding_aio_calls ));
-               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;
+       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"));
@@ -206,6 +220,7 @@ NTSTATUS schedule_aio_read_and_X(connection_struct *conn,
        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,
@@ -221,12 +236,12 @@ NTSTATUS schedule_aio_read_and_X(connection_struct *conn,
        aio_ex->offset = startpos;
 
        req = SMB_VFS_PREAD_SEND(aio_ex, fsp->conn->sconn->ev_ctx,
-                                fsp, smb_buf(aio_ex->outbuf.data),
+                                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) ));
-               SMB_VFS_STRICT_UNLOCK(conn, fsp, &aio_ex->lock);
                TALLOC_FREE(aio_ex);
                return NT_STATUS_RETRY;
        }
@@ -234,7 +249,6 @@ NTSTATUS schedule_aio_read_and_X(connection_struct *conn,
 
        if (!aio_add_req_to_fsp(fsp, req)) {
                DEBUG(1, ("Could not add req to fsp\n"));
-               SMB_VFS_STRICT_UNLOCK(conn, fsp, &aio_ex->lock);
                TALLOC_FREE(aio_ex);
                return NT_STATUS_RETRY;
        }
@@ -256,15 +270,14 @@ static void aio_pread_smb1_done(struct tevent_req *req)
        files_struct *fsp = aio_ex->fsp;
        int outsize;
        char *outbuf = (char *)aio_ex->outbuf.data;
-       char *data = smb_buf(outbuf);
        ssize_t nread;
-       int err;
+       struct vfs_aio_state vfs_aio_state;
 
-       nread = SMB_VFS_PREAD_RECV(req, &err);
+       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(err) : "no error"));
+                  (nread == -1) ? strerror(vfs_aio_state.error) : "no error"));
 
        if (fsp == NULL) {
                DEBUG( 3, ("aio_pread_smb1_done: file closed whilst "
@@ -274,23 +287,15 @@ static void aio_pread_smb1_done(struct tevent_req *req)
                return;
        }
 
-       /* Unlock now we're done. */
-       SMB_VFS_STRICT_UNLOCK(fsp->conn, fsp, &aio_ex->lock);
-
        if (nread < 0) {
                DEBUG( 3, ("handle_aio_read_complete: file %s nread == %d. "
                           "Error = %s\n", fsp_str_dbg(fsp), (int)nread,
-                          strerror(err)));
+                          strerror(vfs_aio_state.error)));
 
-               ERROR_NT(map_nt_error_from_unix(err));
+               ERROR_NT(map_nt_error_from_unix(vfs_aio_state.error));
                outsize = srv_set_message(outbuf,0,0,true);
        } else {
-               outsize = srv_set_message(outbuf, 12, nread, False);
-               SSVAL(outbuf,smb_vwv2, 0xFFFF); /* Remaining - must be * -1. */
-               SSVAL(outbuf,smb_vwv5, nread);
-               SSVAL(outbuf,smb_vwv6, smb_offset(data,outbuf));
-               SSVAL(outbuf,smb_vwv7, ((nread >> 16) & 1));
-               SSVAL(smb_buf(outbuf), -2, nread);
+               outsize = setup_readX_header(outbuf, nread);
 
                aio_ex->fsp->fh->pos = aio_ex->offset + nread;
                aio_ex->fsp->fh->position_information = aio_ex->fsp->fh->pos;
@@ -302,7 +307,7 @@ static void aio_pread_smb1_done(struct tevent_req *req)
        }
        smb_setlen(outbuf, outsize - 4);
        show_msg(outbuf);
-       if (!srv_send_smb(aio_ex->smbreq->sconn, 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 "
@@ -360,18 +365,18 @@ static void pwrite_fsync_write_done(struct tevent_req *subreq)
        struct pwrite_fsync_state *state = tevent_req_data(
                req, struct pwrite_fsync_state);
        connection_struct *conn = state->fsp->conn;
-       int err;
        bool do_sync;
+       struct vfs_aio_state vfs_aio_state;
 
-       state->nwritten = SMB_VFS_PWRITE_RECV(subreq, &err);
+       state->nwritten = SMB_VFS_PWRITE_RECV(subreq, &vfs_aio_state);
        TALLOC_FREE(subreq);
        if (state->nwritten == -1) {
-               tevent_req_error(req, err);
+               tevent_req_error(req, vfs_aio_state.error);
                return;
        }
 
        do_sync = (lp_strict_sync(SNUM(conn)) &&
-                  (lp_syncalways(SNUM(conn)) || state->write_through));
+                  (lp_sync_always(SNUM(conn)) || state->write_through));
        if (!do_sync) {
                tevent_req_done(req);
                return;
@@ -388,12 +393,13 @@ static void pwrite_fsync_sync_done(struct tevent_req *subreq)
 {
        struct tevent_req *req = tevent_req_callback_data(
                subreq, struct tevent_req);
-       int ret, err;
+       int ret;
+       struct vfs_aio_state vfs_aio_state;
 
-       ret = SMB_VFS_FSYNC_RECV(subreq, &err);
+       ret = SMB_VFS_FSYNC_RECV(subreq, &vfs_aio_state);
        TALLOC_FREE(subreq);
        if (ret == -1) {
-               tevent_req_error(req, err);
+               tevent_req_error(req, vfs_aio_state.error);
                return;
        }
        tevent_req_done(req);
@@ -449,19 +455,6 @@ NTSTATUS schedule_aio_write_and_X(connection_struct *conn,
                return NT_STATUS_RETRY;
        }
 
-       if (outstanding_aio_calls >= aio_pending_size) {
-               DEBUG(3,("schedule_aio_write_and_X: Already have %d aio "
-                        "activities outstanding.\n",
-                         outstanding_aio_calls ));
-               DEBUG(10,("schedule_aio_write_and_X: failed to schedule "
-                         "aio_write for file %s, offset %.0f, len = %u "
-                         "(mid = %u)\n",
-                         fsp_str_dbg(fsp), (double)startpos,
-                         (unsigned int)numtowrite,
-                         (unsigned int)smbreq->mid ));
-               return NT_STATUS_RETRY;
-       }
-
        bufsize = smb_size + 6*2;
 
        if (!(aio_ex = create_aio_extra(NULL, fsp, bufsize))) {
@@ -493,7 +486,6 @@ NTSTATUS schedule_aio_write_and_X(connection_struct *conn,
        if (req == NULL) {
                DEBUG(3,("schedule_aio_wrote_and_X: aio_write failed. "
                         "Error %s\n", strerror(errno) ));
-               SMB_VFS_STRICT_UNLOCK(conn, fsp, &aio_ex->lock);
                TALLOC_FREE(aio_ex);
                return NT_STATUS_RETRY;
        }
@@ -501,7 +493,6 @@ NTSTATUS schedule_aio_write_and_X(connection_struct *conn,
 
        if (!aio_add_req_to_fsp(fsp, req)) {
                DEBUG(1, ("Could not add req to fsp\n"));
-               SMB_VFS_STRICT_UNLOCK(conn, fsp, &aio_ex->lock);
                TALLOC_FREE(aio_ex);
                return NT_STATUS_RETRY;
        }
@@ -512,14 +503,14 @@ NTSTATUS schedule_aio_write_and_X(connection_struct *conn,
        contend_level2_oplocks_begin(fsp, LEVEL2_CONTEND_WRITE);
        contend_level2_oplocks_end(fsp, LEVEL2_CONTEND_WRITE);
 
-       if (!aio_ex->write_through && !lp_syncalways(SNUM(fsp->conn))
+       if (!aio_ex->write_through && !lp_sync_always(SNUM(fsp->conn))
            && fsp->aio_write_behind) {
                /* Lie to the client and immediately claim we finished the
                 * write. */
                SSVAL(aio_ex->outbuf.data,smb_vwv2,numtowrite);
                 SSVAL(aio_ex->outbuf.data,smb_vwv4,(numtowrite>>16)&1);
                show_msg((char *)aio_ex->outbuf.data);
-               if (!srv_send_smb(aio_ex->smbreq->sconn,
+               if (!srv_send_smb(aio_ex->smbreq->xconn,
                                (char *)aio_ex->outbuf.data,
                                true, aio_ex->smbreq->seqnum+1,
                                IS_CONN_ENCRYPTED(fsp->conn),
@@ -535,7 +526,8 @@ NTSTATUS schedule_aio_write_and_X(connection_struct *conn,
                  "%s, offset %.0f, len = %u (mid = %u) "
                  "outstanding_aio_calls = %d\n",
                  fsp_str_dbg(fsp), (double)startpos, (unsigned int)numtowrite,
-                 (unsigned int)aio_ex->smbreq->mid, outstanding_aio_calls ));
+                 (unsigned int)aio_ex->smbreq->mid,
+                 get_outstanding_aio_calls() ));
 
        return NT_STATUS_OK;
 }
@@ -564,9 +556,6 @@ static void aio_pwrite_smb1_done(struct tevent_req *req)
                return;
        }
 
-       /* Unlock now we're done. */
-       SMB_VFS_STRICT_UNLOCK(fsp->conn, fsp, &aio_ex->lock);
-
        mark_file_modified(fsp);
 
        if (fsp->aio_write_behind) {
@@ -621,7 +610,7 @@ static void aio_pwrite_smb1_done(struct tevent_req *req)
        }
 
        show_msg(outbuf);
-       if (!srv_send_smb(aio_ex->smbreq->sconn, outbuf,
+       if (!srv_send_smb(aio_ex->smbreq->xconn, outbuf,
                          true, aio_ex->smbreq->seqnum+1,
                          IS_CONN_ENCRYPTED(fsp->conn),
                          NULL)) {
@@ -688,6 +677,11 @@ NTSTATUS schedule_smb2_aio_read(connection_struct *conn,
                return NT_STATUS_RETRY;
        }
 
+       if (fsp->op == NULL) {
+               /* No AIO on internal opens. */
+               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. */
@@ -703,13 +697,6 @@ NTSTATUS schedule_smb2_aio_read(connection_struct *conn,
                return NT_STATUS_RETRY;
        }
 
-       if (outstanding_aio_calls >= aio_pending_size) {
-               DEBUG(10,("smb2: Already have %d aio "
-                       "activities outstanding.\n",
-                       outstanding_aio_calls ));
-               return NT_STATUS_RETRY;
-       }
-
        /* Create the out buffer. */
        *preadbuf = data_blob_talloc(ctx, NULL, smb_maxcnt);
        if (preadbuf->data == NULL) {
@@ -720,7 +707,7 @@ NTSTATUS schedule_smb2_aio_read(connection_struct *conn,
                return NT_STATUS_NO_MEMORY;
        }
 
-       init_strict_lock_struct(fsp, (uint64_t)smbreq->smbpid,
+       init_strict_lock_struct(fsp, fsp->op->global->open_persistent_id,
                (uint64_t)startpos, (uint64_t)smb_maxcnt, READ_LOCK,
                &aio_ex->lock);
 
@@ -738,7 +725,6 @@ NTSTATUS schedule_smb2_aio_read(connection_struct *conn,
        if (req == NULL) {
                DEBUG(0, ("smb2: SMB_VFS_PREAD_SEND failed. "
                          "Error %s\n", strerror(errno)));
-               SMB_VFS_STRICT_UNLOCK(conn, fsp, &aio_ex->lock);
                TALLOC_FREE(aio_ex);
                return NT_STATUS_RETRY;
        }
@@ -746,7 +732,6 @@ NTSTATUS schedule_smb2_aio_read(connection_struct *conn,
 
        if (!aio_add_req_to_fsp(fsp, req)) {
                DEBUG(1, ("Could not add req to fsp\n"));
-               SMB_VFS_STRICT_UNLOCK(conn, fsp, &aio_ex->lock);
                TALLOC_FREE(aio_ex);
                return NT_STATUS_RETRY;
        }
@@ -772,29 +757,26 @@ static void aio_pread_smb2_done(struct tevent_req *req)
        files_struct *fsp = aio_ex->fsp;
        NTSTATUS status;
        ssize_t nread;
-       int err = 0;
+       struct vfs_aio_state vfs_aio_state = { 0 };
 
-       nread = SMB_VFS_PREAD_RECV(req, &err);
+       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(err) : "no error"));
+                  (nread == -1) ? strerror(vfs_aio_state.error) : "no error"));
 
        if (fsp == NULL) {
-               DEBUG( 3, ("aio_pread_smb2_done: file closed whilst "
-                          "aio outstanding (mid[%llu]).\n",
-                          (unsigned long long)aio_ex->smbreq->mid));
+               DEBUG(3, ("%s: request cancelled (mid[%ju])\n",
+                         __func__, (uintmax_t)aio_ex->smbreq->mid));
                TALLOC_FREE(aio_ex);
+               tevent_req_nterror(subreq, NT_STATUS_INTERNAL_ERROR);
                return;
        }
 
-       /* Unlock now we're done. */
-       SMB_VFS_STRICT_UNLOCK(fsp->conn, fsp, &aio_ex->lock);
-
        /* Common error or success code processing for async or sync
           read returns. */
 
-       status = smb2_read_complete(subreq, nread, err);
+       status = smb2_read_complete(subreq, nread, vfs_aio_state.error);
 
        if (nread > 0) {
                fsp->fh->pos = aio_ex->offset + nread;
@@ -807,7 +789,7 @@ static void aio_pread_smb2_done(struct tevent_req *req)
                   fsp_str_dbg(aio_ex->fsp),
                   (double)aio_ex->offset,
                   (unsigned int)nread,
-                  err, nt_errstr(status)));
+                  vfs_aio_state.error, nt_errstr(status)));
 
        if (!NT_STATUS_IS_OK(status)) {
                tevent_req_nterror(subreq, status);
@@ -839,6 +821,11 @@ NTSTATUS schedule_aio_smb2_write(connection_struct *conn,
                return NT_STATUS_RETRY;
        }
 
+       if (fsp->op == NULL) {
+               /* No AIO on internal opens. */
+               return NT_STATUS_RETRY;
+       }
+
        if ((!min_aio_write_size || (in_data.length < min_aio_write_size))
            && !SMB_VFS_AIO_FORCE(fsp)) {
                /* Too small a write for aio request. */
@@ -854,13 +841,6 @@ NTSTATUS schedule_aio_smb2_write(connection_struct *conn,
                return NT_STATUS_RETRY;
        }
 
-       if (outstanding_aio_calls >= aio_pending_size) {
-               DEBUG(3,("smb2: Already have %d aio "
-                       "activities outstanding.\n",
-                       outstanding_aio_calls ));
-               return NT_STATUS_RETRY;
-       }
-
        if (smbreq->unread_bytes) {
                /* Can't do async with recvfile. */
                return NT_STATUS_RETRY;
@@ -872,7 +852,7 @@ NTSTATUS schedule_aio_smb2_write(connection_struct *conn,
 
        aio_ex->write_through = write_through;
 
-       init_strict_lock_struct(fsp, (uint64_t)smbreq->smbpid,
+       init_strict_lock_struct(fsp, fsp->op->global->open_persistent_id,
                in_offset, (uint64_t)in_data.length, WRITE_LOCK,
                &aio_ex->lock);
 
@@ -891,7 +871,6 @@ NTSTATUS schedule_aio_smb2_write(connection_struct *conn,
        if (req == NULL) {
                DEBUG(3, ("smb2: SMB_VFS_PWRITE_SEND failed. "
                          "Error %s\n", strerror(errno)));
-               SMB_VFS_STRICT_UNLOCK(conn, fsp, &aio_ex->lock);
                TALLOC_FREE(aio_ex);
                return NT_STATUS_RETRY;
        }
@@ -899,7 +878,6 @@ NTSTATUS schedule_aio_smb2_write(connection_struct *conn,
 
        if (!aio_add_req_to_fsp(fsp, req)) {
                DEBUG(1, ("Could not add req to fsp\n"));
-               SMB_VFS_STRICT_UNLOCK(conn, fsp, &aio_ex->lock);
                TALLOC_FREE(aio_ex);
                return NT_STATUS_RETRY;
        }
@@ -926,7 +904,7 @@ NTSTATUS schedule_aio_smb2_write(connection_struct *conn,
                (double)in_offset,
                (unsigned int)in_data.length,
                (unsigned int)aio_ex->smbreq->mid,
-               outstanding_aio_calls ));
+               get_outstanding_aio_calls() ));
 
        return NT_STATUS_OK;
 }
@@ -949,15 +927,14 @@ static void aio_pwrite_smb2_done(struct tevent_req *req)
                   (nwritten == -1) ? strerror(err) : "no error"));
 
        if (fsp == NULL) {
-               DEBUG( 3, ("aio_pwrite_smb2_done: file closed whilst "
-                          "aio outstanding (mid[%llu]).\n",
-                          (unsigned long long)aio_ex->smbreq->mid));
+               DEBUG(3, ("%s: request cancelled (mid[%ju])\n",
+                         __func__, (uintmax_t)aio_ex->smbreq->mid));
                TALLOC_FREE(aio_ex);
+               tevent_req_nterror(subreq, NT_STATUS_INTERNAL_ERROR);
                return;
        }
 
-       /* Unlock now we're done. */
-       SMB_VFS_STRICT_UNLOCK(fsp->conn, fsp, &aio_ex->lock);
+       mark_file_modified(fsp);
 
         status = smb2_write_complete_nosync(subreq, nwritten, err);