LCOV - code coverage report
Current view: top level - source3/smbd - smb2_aio.c (source / functions) Hit Total Coverage
Test: coverage report for recycleplus df22b230 Lines: 161 241 66.8 %
Date: 2024-02-14 10:14:15 Functions: 10 13 76.9 %

          Line data    Source code
       1             : /*
       2             :    Unix SMB/Netbios implementation.
       3             :    Version 3.0
       4             :    async_io read handling using POSIX async io.
       5             :    Copyright (C) Jeremy Allison 2005.
       6             : 
       7             :    This program is free software; you can redistribute it and/or modify
       8             :    it under the terms of the GNU General Public License as published by
       9             :    the Free Software Foundation; either version 3 of the License, or
      10             :    (at your option) any later version.
      11             : 
      12             :    This program is distributed in the hope that it will be useful,
      13             :    but WITHOUT ANY WARRANTY; without even the implied warranty of
      14             :    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
      15             :    GNU General Public License for more details.
      16             : 
      17             :    You should have received a copy of the GNU General Public License
      18             :    along with this program.  If not, see <http://www.gnu.org/licenses/>.
      19             : */
      20             : 
      21             : #include "includes.h"
      22             : #include "smbd/smbd.h"
      23             : #include "smbd/globals.h"
      24             : #include "../lib/util/tevent_ntstatus.h"
      25             : #include "../lib/util/tevent_unix.h"
      26             : 
      27             : /****************************************************************************
      28             :  Accessor function to return write_through state.
      29             : *****************************************************************************/
      30             : 
      31           0 : bool aio_write_through_requested(struct aio_extra *aio_ex)
      32             : {
      33           0 :         return aio_ex->write_through;
      34             : }
      35             : 
      36             : /****************************************************************************
      37             :  Create the extended aio struct we must keep around for the lifetime
      38             :  of the aio call.
      39             : *****************************************************************************/
      40             : 
      41         802 : struct aio_extra *create_aio_extra(TALLOC_CTX *mem_ctx,
      42             :                                    files_struct *fsp,
      43             :                                    size_t buflen)
      44             : {
      45         802 :         struct aio_extra *aio_ex = talloc_zero(mem_ctx, struct aio_extra);
      46             : 
      47         802 :         if (!aio_ex) {
      48           0 :                 return NULL;
      49             :         }
      50             : 
      51             :         /* The output buffer stored in the aio_ex is the start of
      52             :            the smb return buffer. The buffer used in the acb
      53             :            is the start of the reply data portion of that buffer. */
      54             : 
      55         802 :         if (buflen) {
      56           0 :                 aio_ex->outbuf = data_blob_talloc(aio_ex, NULL, buflen);
      57           0 :                 if (!aio_ex->outbuf.data) {
      58           0 :                         TALLOC_FREE(aio_ex);
      59           0 :                         return NULL;
      60             :                 }
      61             :         }
      62         802 :         aio_ex->fsp = fsp;
      63         802 :         return aio_ex;
      64             : }
      65             : 
      66             : struct aio_req_fsp_link {
      67             : #ifdef DEVELOPER
      68             :         struct smbd_server_connection *sconn;
      69             : #endif
      70             :         files_struct *fsp;
      71             :         struct tevent_req *req;
      72             : };
      73             : 
      74       90219 : static int aio_del_req_from_fsp(struct aio_req_fsp_link *lnk)
      75             : {
      76             :         unsigned i;
      77       90219 :         files_struct *fsp = lnk->fsp;
      78       90219 :         struct tevent_req *req = lnk->req;
      79             : 
      80             : #ifdef DEVELOPER
      81       90219 :         struct files_struct *ifsp = NULL;
      82       90219 :         bool found = false;
      83             : 
      84             :         /*
      85             :          * When this is called, lnk->fsp must still exist
      86             :          * on the files list for this connection. Panic if not.
      87             :          */
      88      183413 :         for (ifsp = lnk->sconn->files; ifsp; ifsp = ifsp->next) {
      89       93194 :                 if (ifsp == fsp) {
      90       90219 :                         found = true;
      91             :                 }
      92             :         }
      93       90219 :         if (!found) {
      94           0 :                 smb_panic("orphaned lnk on fsp aio list.\n");
      95             :         }
      96             : #endif
      97             : 
      98       90328 :         for (i=0; i<fsp->num_aio_requests; i++) {
      99       90328 :                 if (fsp->aio_requests[i] == req) {
     100       90219 :                         break;
     101             :                 }
     102             :         }
     103       90219 :         if (i == fsp->num_aio_requests) {
     104           0 :                 DEBUG(1, ("req %p not found in fsp %p\n", req, fsp));
     105           0 :                 return 0;
     106             :         }
     107       90219 :         fsp->num_aio_requests -= 1;
     108       90219 :         fsp->aio_requests[i] = fsp->aio_requests[fsp->num_aio_requests];
     109             : 
     110       90219 :         if (fsp->num_aio_requests == 0) {
     111       90105 :                 TALLOC_FREE(fsp->aio_requests);
     112             :         }
     113       90219 :         return 0;
     114             : }
     115             : 
     116       90219 : bool aio_add_req_to_fsp(files_struct *fsp, struct tevent_req *req)
     117             : {
     118             :         size_t array_len;
     119             :         struct aio_req_fsp_link *lnk;
     120             : 
     121       90219 :         lnk = talloc(req, struct aio_req_fsp_link);
     122       90219 :         if (lnk == NULL) {
     123           0 :                 return false;
     124             :         }
     125             : 
     126       90219 :         array_len = talloc_array_length(fsp->aio_requests);
     127       90219 :         if (array_len <= fsp->num_aio_requests) {
     128             :                 struct tevent_req **tmp;
     129             : 
     130       90105 :                 if (fsp->num_aio_requests + 10 < 10) {
     131             :                         /* Integer wrap. */
     132           0 :                         TALLOC_FREE(lnk);
     133           0 :                         return false;
     134             :                 }
     135             : 
     136             :                 /*
     137             :                  * Allocate in blocks of 10 so we don't allocate
     138             :                  * on every aio request.
     139             :                  */
     140       90105 :                 tmp = talloc_realloc(
     141             :                         fsp, fsp->aio_requests, struct tevent_req *,
     142             :                         fsp->num_aio_requests+10);
     143       90105 :                 if (tmp == NULL) {
     144           0 :                         TALLOC_FREE(lnk);
     145           0 :                         return false;
     146             :                 }
     147       90105 :                 fsp->aio_requests = tmp;
     148             :         }
     149       90219 :         fsp->aio_requests[fsp->num_aio_requests] = req;
     150       90219 :         fsp->num_aio_requests += 1;
     151             : 
     152       90219 :         lnk->fsp = fsp;
     153       90219 :         lnk->req = req;
     154             : #ifdef DEVELOPER
     155       90219 :         lnk->sconn = fsp->conn->sconn;
     156             : #endif
     157       90219 :         talloc_set_destructor(lnk, aio_del_req_from_fsp);
     158             : 
     159       90219 :         return true;
     160             : }
     161             : 
     162             : struct pwrite_fsync_state {
     163             :         struct tevent_context *ev;
     164             :         files_struct *fsp;
     165             :         bool write_through;
     166             :         ssize_t nwritten;
     167             : };
     168             : 
     169             : static void pwrite_fsync_write_done(struct tevent_req *subreq);
     170             : static void pwrite_fsync_sync_done(struct tevent_req *subreq);
     171             : 
     172         426 : struct tevent_req *pwrite_fsync_send(TALLOC_CTX *mem_ctx,
     173             :                                      struct tevent_context *ev,
     174             :                                      struct files_struct *fsp,
     175             :                                      const void *data,
     176             :                                      size_t n, off_t offset,
     177             :                                      bool write_through)
     178             : {
     179             :         struct tevent_req *req, *subreq;
     180             :         struct pwrite_fsync_state *state;
     181             :         bool ok;
     182             : 
     183         426 :         req = tevent_req_create(mem_ctx, &state, struct pwrite_fsync_state);
     184         426 :         if (req == NULL) {
     185           0 :                 return NULL;
     186             :         }
     187         426 :         state->ev = ev;
     188         426 :         state->fsp = fsp;
     189         426 :         state->write_through = write_through;
     190             : 
     191         426 :         ok = vfs_valid_pwrite_range(offset, n);
     192         426 :         if (!ok) {
     193           0 :                 tevent_req_error(req, EINVAL);
     194           0 :                 return tevent_req_post(req, ev);
     195             :         }
     196             : 
     197         426 :         if (n == 0) {
     198           0 :                 tevent_req_done(req);
     199           0 :                 return tevent_req_post(req, ev);
     200             :         }
     201             : 
     202         426 :         subreq = SMB_VFS_PWRITE_SEND(state, ev, fsp, data, n, offset);
     203         426 :         if (tevent_req_nomem(subreq, req)) {
     204           0 :                 return tevent_req_post(req, ev);
     205             :         }
     206         426 :         tevent_req_set_callback(subreq, pwrite_fsync_write_done, req);
     207         426 :         return req;
     208             : }
     209             : 
     210         426 : static void pwrite_fsync_write_done(struct tevent_req *subreq)
     211             : {
     212         426 :         struct tevent_req *req = tevent_req_callback_data(
     213             :                 subreq, struct tevent_req);
     214         426 :         struct pwrite_fsync_state *state = tevent_req_data(
     215             :                 req, struct pwrite_fsync_state);
     216         426 :         connection_struct *conn = state->fsp->conn;
     217             :         bool do_sync;
     218             :         struct vfs_aio_state vfs_aio_state;
     219             : 
     220         426 :         state->nwritten = SMB_VFS_PWRITE_RECV(subreq, &vfs_aio_state);
     221         426 :         TALLOC_FREE(subreq);
     222         426 :         if (state->nwritten == -1) {
     223           0 :                 tevent_req_error(req, vfs_aio_state.error);
     224         426 :                 return;
     225             :         }
     226             : 
     227        1278 :         do_sync = (lp_strict_sync(SNUM(conn)) &&
     228         852 :                    (lp_sync_always(SNUM(conn)) || state->write_through));
     229         426 :         if (!do_sync) {
     230         426 :                 tevent_req_done(req);
     231         426 :                 return;
     232             :         }
     233             : 
     234           0 :         subreq = SMB_VFS_FSYNC_SEND(state, state->ev, state->fsp);
     235           0 :         if (tevent_req_nomem(subreq, req)) {
     236           0 :                 return;
     237             :         }
     238           0 :         tevent_req_set_callback(subreq, pwrite_fsync_sync_done, req);
     239             : }
     240             : 
     241           0 : static void pwrite_fsync_sync_done(struct tevent_req *subreq)
     242             : {
     243           0 :         struct tevent_req *req = tevent_req_callback_data(
     244             :                 subreq, struct tevent_req);
     245             :         int ret;
     246             :         struct vfs_aio_state vfs_aio_state;
     247             : 
     248           0 :         ret = SMB_VFS_FSYNC_RECV(subreq, &vfs_aio_state);
     249           0 :         TALLOC_FREE(subreq);
     250           0 :         if (ret == -1) {
     251           0 :                 tevent_req_error(req, vfs_aio_state.error);
     252           0 :                 return;
     253             :         }
     254           0 :         tevent_req_done(req);
     255             : }
     256             : 
     257         426 : ssize_t pwrite_fsync_recv(struct tevent_req *req, int *perr)
     258             : {
     259         426 :         struct pwrite_fsync_state *state = tevent_req_data(
     260             :                 req, struct pwrite_fsync_state);
     261             : 
     262         426 :         if (tevent_req_is_unix_error(req, perr)) {
     263           0 :                 return -1;
     264             :         }
     265         426 :         return state->nwritten;
     266             : }
     267             : 
     268           0 : bool cancel_smb2_aio(struct smb_request *smbreq)
     269             : {
     270           0 :         struct smbd_smb2_request *smb2req = smbreq->smb2req;
     271           0 :         struct aio_extra *aio_ex = NULL;
     272             : 
     273           0 :         if (smb2req) {
     274           0 :                 aio_ex = talloc_get_type(smbreq->async_priv,
     275             :                                          struct aio_extra);
     276             :         }
     277             : 
     278           0 :         if (aio_ex == NULL) {
     279           0 :                 return false;
     280             :         }
     281             : 
     282           0 :         if (aio_ex->fsp == NULL) {
     283           0 :                 return false;
     284             :         }
     285             : 
     286             :         /*
     287             :          * We let the aio request run and don't try to cancel it which means
     288             :          * processing of the SMB2 request must continue as normal, cf MS-SMB2
     289             :          * 3.3.5.16:
     290             :          *
     291             :          *   If the target request is not successfully canceled, processing of
     292             :          *   the target request MUST continue and no response is sent to the
     293             :          *   cancel request.
     294             :          */
     295             : 
     296           0 :         return false;
     297             : }
     298             : 
     299             : static void aio_pread_smb2_done(struct tevent_req *req);
     300             : 
     301             : /****************************************************************************
     302             :  Set up an aio request from a SMB2 read call.
     303             : *****************************************************************************/
     304             : 
     305         376 : NTSTATUS schedule_smb2_aio_read(connection_struct *conn,
     306             :                                 struct smb_request *smbreq,
     307             :                                 files_struct *fsp,
     308             :                                 TALLOC_CTX *ctx,
     309             :                                 DATA_BLOB *preadbuf,
     310             :                                 off_t startpos,
     311             :                                 size_t smb_maxcnt)
     312             : {
     313             :         struct aio_extra *aio_ex;
     314         376 :         size_t min_aio_read_size = lp_aio_read_size(SNUM(conn));
     315             :         struct tevent_req *req;
     316         376 :         bool is_compound = false;
     317         376 :         bool is_last_in_compound = false;
     318             :         bool ok;
     319             : 
     320         376 :         ok = vfs_valid_pread_range(startpos, smb_maxcnt);
     321         376 :         if (!ok) {
     322           0 :                 return NT_STATUS_INVALID_PARAMETER;
     323             :         }
     324             : 
     325         376 :         if (fsp_is_alternate_stream(fsp)) {
     326           0 :                 DEBUG(10, ("AIO on streams not yet supported\n"));
     327           0 :                 return NT_STATUS_RETRY;
     328             :         }
     329             : 
     330         376 :         if (fsp->op == NULL) {
     331             :                 /* No AIO on internal opens. */
     332           0 :                 return NT_STATUS_RETRY;
     333             :         }
     334             : 
     335         376 :         if ((!min_aio_read_size || (smb_maxcnt < min_aio_read_size))
     336           0 :             && !SMB_VFS_AIO_FORCE(fsp)) {
     337             :                 /* Too small a read for aio request. */
     338           0 :                 DEBUG(10,("smb2: read size (%u) too small "
     339             :                         "for minimum aio_read of %u\n",
     340             :                         (unsigned int)smb_maxcnt,
     341             :                         (unsigned int)min_aio_read_size ));
     342           0 :                 return NT_STATUS_RETRY;
     343             :         }
     344             : 
     345         376 :         is_compound = smbd_smb2_is_compound(smbreq->smb2req);
     346         376 :         is_last_in_compound = smbd_smb2_is_last_in_compound(smbreq->smb2req);
     347             : 
     348         376 :         if (is_compound && !is_last_in_compound) {
     349             :                 /*
     350             :                  * Only allow going async if this is the last
     351             :                  * request in a compound.
     352             :                  */
     353           0 :                 return NT_STATUS_RETRY;
     354             :         }
     355             : 
     356             :         /* Create the out buffer. */
     357         376 :         *preadbuf = data_blob_talloc(ctx, NULL, smb_maxcnt);
     358         376 :         if (preadbuf->data == NULL) {
     359           0 :                 return NT_STATUS_NO_MEMORY;
     360             :         }
     361             : 
     362         376 :         if (!(aio_ex = create_aio_extra(smbreq->smb2req, fsp, 0))) {
     363           0 :                 return NT_STATUS_NO_MEMORY;
     364             :         }
     365             : 
     366         376 :         init_strict_lock_struct(fsp,
     367         376 :                         fsp->op->global->open_persistent_id,
     368             :                         (uint64_t)startpos,
     369             :                         (uint64_t)smb_maxcnt,
     370             :                         READ_LOCK,
     371             :                         lp_posix_cifsu_locktype(fsp),
     372             :                         &aio_ex->lock);
     373             : 
     374             :         /* Take the lock until the AIO completes. */
     375         376 :         if (!SMB_VFS_STRICT_LOCK_CHECK(conn, fsp, &aio_ex->lock)) {
     376           0 :                 TALLOC_FREE(aio_ex);
     377           0 :                 return NT_STATUS_FILE_LOCK_CONFLICT;
     378             :         }
     379             : 
     380         376 :         aio_ex->nbyte = smb_maxcnt;
     381         376 :         aio_ex->offset = startpos;
     382             : 
     383         376 :         req = SMB_VFS_PREAD_SEND(aio_ex, fsp->conn->sconn->ev_ctx, fsp,
     384             :                                  preadbuf->data, smb_maxcnt, startpos);
     385         376 :         if (req == NULL) {
     386           0 :                 DEBUG(0, ("smb2: SMB_VFS_PREAD_SEND failed. "
     387             :                           "Error %s\n", strerror(errno)));
     388           0 :                 TALLOC_FREE(aio_ex);
     389           0 :                 return NT_STATUS_RETRY;
     390             :         }
     391         376 :         tevent_req_set_callback(req, aio_pread_smb2_done, aio_ex);
     392             : 
     393         376 :         if (!aio_add_req_to_fsp(fsp, req)) {
     394           0 :                 DEBUG(1, ("Could not add req to fsp\n"));
     395           0 :                 TALLOC_FREE(aio_ex);
     396           0 :                 return NT_STATUS_RETRY;
     397             :         }
     398             : 
     399             :         /* We don't need talloc_move here as both aio_ex and
     400             :          * smbreq are children of smbreq->smb2req. */
     401         376 :         aio_ex->smbreq = smbreq;
     402         376 :         smbreq->async_priv = aio_ex;
     403             : 
     404         376 :         DEBUG(10,("smb2: scheduled aio_read for file %s, "
     405             :                 "offset %.0f, len = %u (mid = %u)\n",
     406             :                 fsp_str_dbg(fsp), (double)startpos, (unsigned int)smb_maxcnt,
     407             :                 (unsigned int)aio_ex->smbreq->mid ));
     408             : 
     409         376 :         return NT_STATUS_OK;
     410             : }
     411             : 
     412         376 : static void aio_pread_smb2_done(struct tevent_req *req)
     413             : {
     414         376 :         struct aio_extra *aio_ex = tevent_req_callback_data(
     415             :                 req, struct aio_extra);
     416         376 :         struct tevent_req *subreq = aio_ex->smbreq->smb2req->subreq;
     417         376 :         files_struct *fsp = aio_ex->fsp;
     418             :         NTSTATUS status;
     419             :         ssize_t nread;
     420         376 :         struct vfs_aio_state vfs_aio_state = { 0 };
     421             : 
     422         376 :         nread = SMB_VFS_PREAD_RECV(req, &vfs_aio_state);
     423         376 :         TALLOC_FREE(req);
     424             : 
     425         376 :         DEBUG(10, ("pread_recv returned %d, err = %s\n", (int)nread,
     426             :                    (nread == -1) ? strerror(vfs_aio_state.error) : "no error"));
     427             : 
     428             :         /* Common error or success code processing for async or sync
     429             :            read returns. */
     430             : 
     431         376 :         status = smb2_read_complete(subreq, nread, vfs_aio_state.error);
     432             : 
     433         376 :         if (nread > 0) {
     434         376 :                 fh_set_pos(fsp->fh, aio_ex->offset + nread);
     435         376 :                 fh_set_position_information(fsp->fh,
     436         376 :                                                 fh_get_pos(fsp->fh));
     437             :         }
     438             : 
     439         376 :         DEBUG(10, ("smb2: scheduled aio_read completed "
     440             :                    "for file %s, offset %.0f, len = %u "
     441             :                    "(errcode = %d, NTSTATUS = %s)\n",
     442             :                    fsp_str_dbg(aio_ex->fsp),
     443             :                    (double)aio_ex->offset,
     444             :                    (unsigned int)nread,
     445             :                    vfs_aio_state.error, nt_errstr(status)));
     446             : 
     447         376 :         if (tevent_req_nterror(subreq, status)) {
     448           0 :                 return;
     449             :         }
     450         376 :         tevent_req_done(subreq);
     451             : }
     452             : 
     453             : static void aio_pwrite_smb2_done(struct tevent_req *req);
     454             : 
     455             : /****************************************************************************
     456             :  Set up an aio request from a SMB2write call.
     457             : *****************************************************************************/
     458             : 
     459         450 : NTSTATUS schedule_aio_smb2_write(connection_struct *conn,
     460             :                                 struct smb_request *smbreq,
     461             :                                 files_struct *fsp,
     462             :                                 uint64_t in_offset,
     463             :                                 DATA_BLOB in_data,
     464             :                                 bool write_through)
     465             : {
     466         450 :         struct aio_extra *aio_ex = NULL;
     467         450 :         size_t min_aio_write_size = lp_aio_write_size(SNUM(conn));
     468             :         struct tevent_req *req;
     469         450 :         bool is_compound = false;
     470         450 :         bool is_last_in_compound = false;
     471             : 
     472         450 :         if (fsp_is_alternate_stream(fsp)) {
     473             :                 /* No AIO on streams yet */
     474          24 :                 DEBUG(10, ("AIO on streams not yet supported\n"));
     475          24 :                 return NT_STATUS_RETRY;
     476             :         }
     477             : 
     478         426 :         if (fsp->op == NULL) {
     479             :                 /* No AIO on internal opens. */
     480           0 :                 return NT_STATUS_RETRY;
     481             :         }
     482             : 
     483         426 :         if ((!min_aio_write_size || (in_data.length < min_aio_write_size))
     484           0 :             && !SMB_VFS_AIO_FORCE(fsp)) {
     485             :                 /* Too small a write for aio request. */
     486           0 :                 DEBUG(10,("smb2: write size (%u) too "
     487             :                         "small for minimum aio_write of %u\n",
     488             :                         (unsigned int)in_data.length,
     489             :                         (unsigned int)min_aio_write_size ));
     490           0 :                 return NT_STATUS_RETRY;
     491             :         }
     492             : 
     493         426 :         is_compound = smbd_smb2_is_compound(smbreq->smb2req);
     494         426 :         is_last_in_compound = smbd_smb2_is_last_in_compound(smbreq->smb2req);
     495             : 
     496         426 :         if (is_compound && !is_last_in_compound) {
     497             :                 /*
     498             :                  * Only allow going async if this is the last
     499             :                  * request in a compound.
     500             :                  */
     501           0 :                 return NT_STATUS_RETRY;
     502             :         }
     503             : 
     504         426 :         if (smbreq->unread_bytes) {
     505             :                 /* Can't do async with recvfile. */
     506           0 :                 return NT_STATUS_RETRY;
     507             :         }
     508             : 
     509         426 :         if (!(aio_ex = create_aio_extra(smbreq->smb2req, fsp, 0))) {
     510           0 :                 return NT_STATUS_NO_MEMORY;
     511             :         }
     512             : 
     513         426 :         aio_ex->write_through = write_through;
     514             : 
     515         426 :         init_strict_lock_struct(fsp,
     516         426 :                         fsp->op->global->open_persistent_id,
     517             :                         in_offset,
     518         426 :                         (uint64_t)in_data.length,
     519             :                         WRITE_LOCK,
     520             :                         lp_posix_cifsu_locktype(fsp),
     521             :                         &aio_ex->lock);
     522             : 
     523             :         /* Take the lock until the AIO completes. */
     524         426 :         if (!SMB_VFS_STRICT_LOCK_CHECK(conn, fsp, &aio_ex->lock)) {
     525           0 :                 TALLOC_FREE(aio_ex);
     526           0 :                 return NT_STATUS_FILE_LOCK_CONFLICT;
     527             :         }
     528             : 
     529         426 :         aio_ex->nbyte = in_data.length;
     530         426 :         aio_ex->offset = in_offset;
     531             : 
     532         426 :         req = pwrite_fsync_send(aio_ex, fsp->conn->sconn->ev_ctx, fsp,
     533         426 :                                 in_data.data, in_data.length, in_offset,
     534             :                                 write_through);
     535         426 :         if (req == NULL) {
     536           0 :                 DEBUG(3, ("smb2: SMB_VFS_PWRITE_SEND failed. "
     537             :                           "Error %s\n", strerror(errno)));
     538           0 :                 TALLOC_FREE(aio_ex);
     539           0 :                 return NT_STATUS_RETRY;
     540             :         }
     541         426 :         tevent_req_set_callback(req, aio_pwrite_smb2_done, aio_ex);
     542             : 
     543         426 :         if (!aio_add_req_to_fsp(fsp, req)) {
     544           0 :                 DEBUG(1, ("Could not add req to fsp\n"));
     545           0 :                 TALLOC_FREE(aio_ex);
     546           0 :                 return NT_STATUS_RETRY;
     547             :         }
     548             : 
     549             :         /* We don't need talloc_move here as both aio_ex and
     550             :         * smbreq are children of smbreq->smb2req. */
     551         426 :         aio_ex->smbreq = smbreq;
     552         426 :         smbreq->async_priv = aio_ex;
     553             : 
     554             :         /* This should actually be improved to span the write. */
     555         426 :         contend_level2_oplocks_begin(fsp, LEVEL2_CONTEND_WRITE);
     556         426 :         contend_level2_oplocks_end(fsp, LEVEL2_CONTEND_WRITE);
     557             : 
     558             :         /*
     559             :          * We don't want to do write behind due to ownership
     560             :          * issues of the request structs. Maybe add it if I
     561             :          * figure those out. JRA.
     562             :          */
     563             : 
     564         426 :         DEBUG(10,("smb2: scheduled aio_write for file "
     565             :                 "%s, offset %.0f, len = %u (mid = %u)\n",
     566             :                 fsp_str_dbg(fsp),
     567             :                 (double)in_offset,
     568             :                 (unsigned int)in_data.length,
     569             :                 (unsigned int)aio_ex->smbreq->mid));
     570             : 
     571         426 :         return NT_STATUS_OK;
     572             : }
     573             : 
     574         426 : static void aio_pwrite_smb2_done(struct tevent_req *req)
     575             : {
     576         426 :         struct aio_extra *aio_ex = tevent_req_callback_data(
     577             :                 req, struct aio_extra);
     578         426 :         ssize_t numtowrite = aio_ex->nbyte;
     579         426 :         struct tevent_req *subreq = aio_ex->smbreq->smb2req->subreq;
     580         426 :         files_struct *fsp = aio_ex->fsp;
     581             :         NTSTATUS status;
     582             :         ssize_t nwritten;
     583         426 :         int err = 0;
     584             : 
     585         426 :         nwritten = pwrite_fsync_recv(req, &err);
     586         426 :         TALLOC_FREE(req);
     587             : 
     588         426 :         DEBUG(10, ("pwrite_recv returned %d, err = %s\n", (int)nwritten,
     589             :                    (nwritten == -1) ? strerror(err) : "no error"));
     590             : 
     591         426 :         mark_file_modified(fsp);
     592             : 
     593         426 :         status = smb2_write_complete_nosync(subreq, nwritten, err);
     594             : 
     595         426 :         DEBUG(10, ("smb2: scheduled aio_write completed "
     596             :                    "for file %s, offset %.0f, requested %u, "
     597             :                    "written = %u (errcode = %d, NTSTATUS = %s)\n",
     598             :                    fsp_str_dbg(fsp),
     599             :                    (double)aio_ex->offset,
     600             :                    (unsigned int)numtowrite,
     601             :                    (unsigned int)nwritten,
     602             :                    err, nt_errstr(status)));
     603             : 
     604         426 :         if (tevent_req_nterror(subreq, status)) {
     605           0 :                 return;
     606             :         }
     607         426 :         tevent_req_done(subreq);
     608             : }

Generated by: LCOV version 1.14