LCOV - code coverage report
Current view: top level - source4/ntvfs/posix - pvfs_wait.c (source / functions) Hit Total Coverage
Test: coverage report for master 2f515e9b Lines: 56 64 87.5 %
Date: 2024-04-21 15:09:00 Functions: 6 6 100.0 %

          Line data    Source code
       1             : /* 
       2             :    Unix SMB/CIFS implementation.
       3             : 
       4             :    POSIX NTVFS backend - async request wait routines
       5             : 
       6             :    Copyright (C) Andrew Tridgell 2004
       7             : 
       8             :    This program is free software; you can redistribute it and/or modify
       9             :    it under the terms of the GNU General Public License as published by
      10             :    the Free Software Foundation; either version 3 of the License, or
      11             :    (at your option) any later version.
      12             :    
      13             :    This program is distributed in the hope that it will be useful,
      14             :    but WITHOUT ANY WARRANTY; without even the implied warranty of
      15             :    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
      16             :    GNU General Public License for more details.
      17             :    
      18             :    You should have received a copy of the GNU General Public License
      19             :    along with this program.  If not, see <http://www.gnu.org/licenses/>.
      20             : */
      21             : 
      22             : #include "includes.h"
      23             : #include "lib/events/events.h"
      24             : #include "../lib/util/dlinklist.h"
      25             : #include "vfs_posix.h"
      26             : #include "samba/service_stream.h"
      27             : #include "lib/messaging/irpc.h"
      28             : 
      29             : /* the context for a single wait instance */
      30             : struct pvfs_wait {
      31             :         struct pvfs_wait *next, *prev;
      32             :         struct pvfs_state *pvfs;
      33             :         void (*handler)(void *, enum pvfs_wait_notice);
      34             :         void *private_data;
      35             :         int msg_type;
      36             :         struct imessaging_context *msg_ctx;
      37             :         struct tevent_context *ev;
      38             :         struct ntvfs_request *req;
      39             :         enum pvfs_wait_notice reason;
      40             : };
      41             : 
      42             : /*
      43             :   called from the ntvfs layer when we have requested setup of an async
      44             :   call.  this ensures that async calls runs with the right state of
      45             :   previous ntvfs handlers in the chain (such as security context)
      46             : */
      47        3449 : NTSTATUS pvfs_async_setup(struct ntvfs_module_context *ntvfs,
      48             :                           struct ntvfs_request *req, void *private_data)
      49             : {
      50        3449 :         struct pvfs_wait *pwait = talloc_get_type(private_data,
      51             :                                                   struct pvfs_wait);
      52        3449 :         pwait->handler(pwait->private_data, pwait->reason);
      53        3449 :         return NT_STATUS_OK;
      54             : }
      55             : 
      56             : /*
      57             :   receive a completion message for a wait
      58             : */
      59         122 : static void pvfs_wait_dispatch(struct imessaging_context *msg,
      60             :                                void *private_data,
      61             :                                uint32_t msg_type,
      62             :                                struct server_id src,
      63             :                                size_t num_fds,
      64             :                                int *fds,
      65             :                                DATA_BLOB *data)
      66             : {
      67         122 :         struct pvfs_wait *pwait = talloc_get_type(private_data,
      68             :                                                   struct pvfs_wait);
      69           0 :         struct ntvfs_request *req;
      70         122 :         void *p = NULL;
      71             : 
      72         122 :         if (num_fds != 0) {
      73           0 :                 DBG_WARNING("Received %zu fds, ignoring message\n", num_fds);
      74           0 :                 return;
      75             :         }
      76             : 
      77             :         /* we need to check that this one is for us. See
      78             :            imessaging_send_ptr() for the other side of this.
      79             :          */
      80         122 :         if (data->length == sizeof(void *)) {
      81           0 :                 void **pp;
      82         122 :                 pp = (void **)data->data;
      83         122 :                 p = *pp;
      84             :         }
      85         122 :         if (p == NULL || p != pwait->private_data) {
      86          19 :                 return;
      87             :         }
      88             : 
      89         103 :         pwait->reason = PVFS_WAIT_EVENT;
      90             : 
      91             :         /* the extra reference here is to ensure that the req
      92             :            structure is not destroyed when the async request reply is
      93             :            sent, which would cause problems with the other ntvfs
      94             :            modules above us */
      95         103 :         req = talloc_reference(msg, pwait->req);
      96         103 :         ntvfs_async_setup(pwait->req, pwait);
      97         103 :         talloc_unlink(msg, req);
      98             : }
      99             : 
     100             : 
     101             : /*
     102             :   receive a timeout on a message wait
     103             : */
     104        2849 : static void pvfs_wait_timeout(struct tevent_context *ev, 
     105             :                               struct tevent_timer *te, struct timeval t,
     106             :                               void *private_data)
     107             : {
     108        2849 :         struct pvfs_wait *pwait = talloc_get_type(private_data,
     109             :                                                   struct pvfs_wait);
     110        2849 :         struct ntvfs_request *req = pwait->req;
     111             : 
     112        2849 :         pwait->reason = PVFS_WAIT_TIMEOUT;
     113             : 
     114        2849 :         req = talloc_reference(ev, req);
     115        2849 :         if (req != NULL) {
     116        2849 :                 ntvfs_async_setup(req, pwait);
     117        2849 :                 talloc_unlink(ev, req);
     118             :         }
     119        2849 : }
     120             : 
     121             : 
     122             : /*
     123             :   destroy a pending wait
     124             :  */
     125        3555 : static int pvfs_wait_destructor(struct pvfs_wait *pwait)
     126             : {
     127        3555 :         if (pwait->msg_type != -1) {
     128        3026 :                 imessaging_deregister(pwait->msg_ctx, pwait->msg_type, pwait);
     129             :         }
     130        3555 :         DLIST_REMOVE(pwait->pvfs->wait_list, pwait);
     131        3555 :         return 0;
     132             : }
     133             : 
     134             : /*
     135             :   setup a request to wait on a message of type msg_type, with a
     136             :   timeout (given as an expiry time)
     137             : 
     138             :   the return value is a handle. To stop waiting talloc_free this
     139             :   handle.
     140             : 
     141             :   if msg_type == -1 then no message is registered, and it is assumed
     142             :   that the caller handles any messaging setup needed
     143             : */
     144        3555 : struct pvfs_wait *pvfs_wait_message(struct pvfs_state *pvfs,
     145             :                                     struct ntvfs_request *req,
     146             :                                     int msg_type,
     147             :                                     struct timeval end_time,
     148             :                                     void (*fn)(void *, enum pvfs_wait_notice),
     149             :                                     void *private_data)
     150             : {
     151           0 :         struct pvfs_wait *pwait;
     152             : 
     153        3555 :         pwait = talloc(pvfs, struct pvfs_wait);
     154        3555 :         if (pwait == NULL) {
     155           0 :                 return NULL;
     156             :         }
     157             : 
     158        3555 :         pwait->private_data = private_data;
     159        3555 :         pwait->handler = fn;
     160        3555 :         pwait->msg_ctx = pvfs->ntvfs->ctx->msg_ctx;
     161        3555 :         pwait->ev = pvfs->ntvfs->ctx->event_ctx;
     162        3555 :         pwait->msg_type = msg_type;
     163        3555 :         pwait->req = talloc_reference(pwait, req);
     164        3555 :         pwait->pvfs = pvfs;
     165             : 
     166        3555 :         if (!timeval_is_zero(&end_time)) {
     167             :                 /* setup a timer */
     168        3026 :                 tevent_add_timer(pwait->ev, pwait, end_time, pvfs_wait_timeout, pwait);
     169             :         }
     170             : 
     171             :         /* register with the messaging subsystem for this message
     172             :            type */
     173        3555 :         if (msg_type != -1) {
     174        3026 :                 imessaging_register(pwait->msg_ctx,
     175             :                                    pwait,
     176             :                                    msg_type,
     177             :                                    pvfs_wait_dispatch);
     178             :         }
     179             : 
     180             :         /* tell the main smb server layer that we will be replying 
     181             :            asynchronously */
     182        3555 :         req->async_states->state |= NTVFS_ASYNC_STATE_ASYNC;
     183             : 
     184        3555 :         DLIST_ADD(pvfs->wait_list, pwait);
     185             : 
     186             :         /* make sure we cleanup the timer and message handler */
     187        3555 :         talloc_set_destructor(pwait, pvfs_wait_destructor);
     188             : 
     189        3555 :         return pwait;
     190             : }
     191             : 
     192             : 
     193             : /*
     194             :   cancel an outstanding async request
     195             : */
     196         497 : NTSTATUS pvfs_cancel(struct ntvfs_module_context *ntvfs, struct ntvfs_request *req)
     197             : {
     198         497 :         struct pvfs_state *pvfs = talloc_get_type(ntvfs->private_data,
     199             :                                   struct pvfs_state);
     200           0 :         struct pvfs_wait *pwait;
     201             : 
     202         499 :         for (pwait=pvfs->wait_list;pwait;pwait=pwait->next) {
     203         499 :                 if (pwait->req == req) {
     204             :                         /* trigger a cancel on the request */
     205         497 :                         pwait->reason = PVFS_WAIT_CANCEL;
     206         497 :                         ntvfs_async_setup(pwait->req, pwait);
     207         497 :                         return NT_STATUS_OK;
     208             :                 }
     209             :         }
     210             : 
     211           0 :         return NT_STATUS_DOS(ERRDOS, ERRcancelviolation);
     212             : }

Generated by: LCOV version 1.14