The Design and Implementation of the FreeBSD Operating System, Second Edition
Now available: The Design and Implementation of the FreeBSD Operating System (Second Edition)


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]

FreeBSD/Linux Kernel Cross Reference
sys/fs/lockd/svc4proc.c

Version: -  FREEBSD  -  FREEBSD-13-STABLE  -  FREEBSD-13-0  -  FREEBSD-12-STABLE  -  FREEBSD-12-0  -  FREEBSD-11-STABLE  -  FREEBSD-11-0  -  FREEBSD-10-STABLE  -  FREEBSD-10-0  -  FREEBSD-9-STABLE  -  FREEBSD-9-0  -  FREEBSD-8-STABLE  -  FREEBSD-8-0  -  FREEBSD-7-STABLE  -  FREEBSD-7-0  -  FREEBSD-6-STABLE  -  FREEBSD-6-0  -  FREEBSD-5-STABLE  -  FREEBSD-5-0  -  FREEBSD-4-STABLE  -  FREEBSD-3-STABLE  -  FREEBSD22  -  l41  -  OPENBSD  -  linux-2.6  -  MK84  -  PLAN9  -  xnu-8792 
SearchContext: -  none  -  3  -  10 

    1 /*
    2  * linux/fs/lockd/svc4proc.c
    3  *
    4  * Lockd server procedures. We don't implement the NLM_*_RES 
    5  * procedures because we don't use the async procedures.
    6  *
    7  * Copyright (C) 1996, Olaf Kirch <okir@monad.swb.de>
    8  */
    9 
   10 #include <linux/types.h>
   11 #include <linux/sched.h>
   12 #include <linux/slab.h>
   13 #include <linux/in.h>
   14 #include <linux/sunrpc/svc.h>
   15 #include <linux/sunrpc/clnt.h>
   16 #include <linux/nfsd/nfsd.h>
   17 #include <linux/lockd/lockd.h>
   18 #include <linux/lockd/share.h>
   19 #include <linux/lockd/sm_inter.h>
   20 
   21 
   22 #define NLMDBG_FACILITY         NLMDBG_CLIENT
   23 
   24 static u32      nlm4svc_callback(struct svc_rqst *, u32, struct nlm_res *);
   25 static void     nlm4svc_callback_exit(struct rpc_task *);
   26 
   27 /*
   28  * Obtain client and file from arguments
   29  */
   30 static u32
   31 nlm4svc_retrieve_args(struct svc_rqst *rqstp, struct nlm_args *argp,
   32                         struct nlm_host **hostp, struct nlm_file **filp)
   33 {
   34         struct nlm_host         *host = NULL;
   35         struct nlm_file         *file = NULL;
   36         struct nlm_lock         *lock = &argp->lock;
   37         u32                     error = 0;
   38 
   39         /* nfsd callbacks must have been installed for this procedure */
   40         if (!nlmsvc_ops)
   41                 return nlm_lck_denied_nolocks;
   42 
   43         /* Obtain handle for client host */
   44         if (rqstp->rq_client == NULL) {
   45                 printk(KERN_NOTICE
   46                         "lockd: unauthenticated request from (%08x:%d)\n",
   47                         ntohl(rqstp->rq_addr.sin_addr.s_addr),
   48                         ntohs(rqstp->rq_addr.sin_port));
   49                 return nlm_lck_denied_nolocks;
   50         }
   51 
   52         /* Obtain host handle */
   53         if (!(host = nlmsvc_lookup_host(rqstp))
   54          || (argp->monitor && !host->h_monitored && nsm_monitor(host) < 0))
   55                 goto no_locks;
   56         *hostp = host;
   57 
   58         /* Obtain file pointer. Not used by FREE_ALL call. */
   59         if (filp != NULL) {
   60                 if ((error = nlm_lookup_file(rqstp, &file, &lock->fh)) != 0)
   61                         goto no_locks;
   62                 *filp = file;
   63 
   64                 /* Set up the missing parts of the file_lock structure */
   65                 lock->fl.fl_file  = &file->f_file;
   66                 lock->fl.fl_owner = (fl_owner_t) host;
   67         }
   68 
   69         return 0;
   70 
   71 no_locks:
   72         if (host)
   73                 nlm_release_host(host);
   74         if (error)
   75                 return error;   
   76         return nlm_lck_denied_nolocks;
   77 }
   78 
   79 /*
   80  * NULL: Test for presence of service
   81  */
   82 static int
   83 nlm4svc_proc_null(struct svc_rqst *rqstp, void *argp, void *resp)
   84 {
   85         dprintk("lockd: NULL          called\n");
   86         return rpc_success;
   87 }
   88 
   89 /*
   90  * TEST: Check for conflicting lock
   91  */
   92 static int
   93 nlm4svc_proc_test(struct svc_rqst *rqstp, struct nlm_args *argp,
   94                                          struct nlm_res  *resp)
   95 {
   96         struct nlm_host *host;
   97         struct nlm_file *file;
   98 
   99         dprintk("lockd: TEST4        called\n");
  100         resp->cookie = argp->cookie;
  101 
  102         /* Don't accept test requests during grace period */
  103         if (nlmsvc_grace_period) {
  104                 resp->status = nlm_lck_denied_grace_period;
  105                 return rpc_success;
  106         }
  107 
  108         /* Obtain client and file */
  109         if ((resp->status = nlm4svc_retrieve_args(rqstp, argp, &host, &file)))
  110                 return rpc_success;
  111 
  112         /* Now check for conflicting locks */
  113         resp->status = nlmsvc_testlock(file, &argp->lock, &resp->lock);
  114 
  115         dprintk("lockd: TEST4          status %d\n", ntohl(resp->status));
  116         nlm_release_host(host);
  117         nlm_release_file(file);
  118         return rpc_success;
  119 }
  120 
  121 static int
  122 nlm4svc_proc_lock(struct svc_rqst *rqstp, struct nlm_args *argp,
  123                                          struct nlm_res  *resp)
  124 {
  125         struct nlm_host *host;
  126         struct nlm_file *file;
  127 
  128         dprintk("lockd: LOCK          called\n");
  129 
  130         resp->cookie = argp->cookie;
  131 
  132         /* Don't accept new lock requests during grace period */
  133         if (nlmsvc_grace_period && !argp->reclaim) {
  134                 resp->status = nlm_lck_denied_grace_period;
  135                 return rpc_success;
  136         }
  137 
  138         /* Obtain client and file */
  139         if ((resp->status = nlm4svc_retrieve_args(rqstp, argp, &host, &file)))
  140                 return rpc_success;
  141 
  142 #if 0
  143         /* If supplied state doesn't match current state, we assume it's
  144          * an old request that time-warped somehow. Any error return would
  145          * do in this case because it's irrelevant anyway.
  146          *
  147          * NB: We don't retrieve the remote host's state yet.
  148          */
  149         if (host->h_nsmstate && host->h_nsmstate != argp->state) {
  150                 resp->status = nlm_lck_denied_nolocks;
  151         } else
  152 #endif
  153 
  154         /* Now try to lock the file */
  155         resp->status = nlmsvc_lock(rqstp, file, &argp->lock,
  156                                         argp->block, &argp->cookie);
  157 
  158         dprintk("lockd: LOCK          status %d\n", ntohl(resp->status));
  159         nlm_release_host(host);
  160         nlm_release_file(file);
  161         return rpc_success;
  162 }
  163 
  164 static int
  165 nlm4svc_proc_cancel(struct svc_rqst *rqstp, struct nlm_args *argp,
  166                                            struct nlm_res  *resp)
  167 {
  168         struct nlm_host *host;
  169         struct nlm_file *file;
  170 
  171         dprintk("lockd: CANCEL        called\n");
  172 
  173         resp->cookie = argp->cookie;
  174 
  175         /* Don't accept requests during grace period */
  176         if (nlmsvc_grace_period) {
  177                 resp->status = nlm_lck_denied_grace_period;
  178                 return rpc_success;
  179         }
  180 
  181         /* Obtain client and file */
  182         if ((resp->status = nlm4svc_retrieve_args(rqstp, argp, &host, &file)))
  183                 return rpc_success;
  184 
  185         /* Try to cancel request. */
  186         resp->status = nlmsvc_cancel_blocked(file, &argp->lock);
  187 
  188         dprintk("lockd: CANCEL        status %d\n", ntohl(resp->status));
  189         nlm_release_host(host);
  190         nlm_release_file(file);
  191         return rpc_success;
  192 }
  193 
  194 /*
  195  * UNLOCK: release a lock
  196  */
  197 static int
  198 nlm4svc_proc_unlock(struct svc_rqst *rqstp, struct nlm_args *argp,
  199                                            struct nlm_res  *resp)
  200 {
  201         struct nlm_host *host;
  202         struct nlm_file *file;
  203 
  204         dprintk("lockd: UNLOCK        called\n");
  205 
  206         resp->cookie = argp->cookie;
  207 
  208         /* Don't accept new lock requests during grace period */
  209         if (nlmsvc_grace_period) {
  210                 resp->status = nlm_lck_denied_grace_period;
  211                 return rpc_success;
  212         }
  213 
  214         /* Obtain client and file */
  215         if ((resp->status = nlm4svc_retrieve_args(rqstp, argp, &host, &file)))
  216                 return rpc_success;
  217 
  218         /* Now try to remove the lock */
  219         resp->status = nlmsvc_unlock(file, &argp->lock);
  220 
  221         dprintk("lockd: UNLOCK        status %d\n", ntohl(resp->status));
  222         nlm_release_host(host);
  223         nlm_release_file(file);
  224         return rpc_success;
  225 }
  226 
  227 /*
  228  * GRANTED: A server calls us to tell that a process' lock request
  229  * was granted
  230  */
  231 static int
  232 nlm4svc_proc_granted(struct svc_rqst *rqstp, struct nlm_args *argp,
  233                                             struct nlm_res  *resp)
  234 {
  235         resp->cookie = argp->cookie;
  236 
  237         dprintk("lockd: GRANTED       called\n");
  238         resp->status = nlmclnt_grant(&argp->lock);
  239         dprintk("lockd: GRANTED       status %d\n", ntohl(resp->status));
  240         return rpc_success;
  241 }
  242 
  243 /*
  244  * `Async' versions of the above service routines. They aren't really,
  245  * because we send the callback before the reply proper. I hope this
  246  * doesn't break any clients.
  247  */
  248 static int
  249 nlm4svc_proc_test_msg(struct svc_rqst *rqstp, struct nlm_args *argp,
  250                                              void            *resp)
  251 {
  252         struct nlm_res  res;
  253         u32             stat;
  254 
  255         dprintk("lockd: TEST_MSG      called\n");
  256 
  257         memset(&res, 0, sizeof(res));
  258 
  259         if ((stat = nlm4svc_proc_test(rqstp, argp, &res)) == 0)
  260                 stat = nlm4svc_callback(rqstp, NLMPROC_TEST_RES, &res);
  261         return stat;
  262 }
  263 
  264 static int
  265 nlm4svc_proc_lock_msg(struct svc_rqst *rqstp, struct nlm_args *argp,
  266                                              void            *resp)
  267 {
  268         struct nlm_res  res;
  269         u32             stat;
  270 
  271         dprintk("lockd: LOCK_MSG      called\n");
  272 
  273         if ((stat = nlm4svc_proc_lock(rqstp, argp, &res)) == 0)
  274                 stat = nlm4svc_callback(rqstp, NLMPROC_LOCK_RES, &res);
  275         return stat;
  276 }
  277 
  278 static int
  279 nlm4svc_proc_cancel_msg(struct svc_rqst *rqstp, struct nlm_args *argp,
  280                                                void            *resp)
  281 {
  282         struct nlm_res  res;
  283         u32             stat;
  284 
  285         dprintk("lockd: CANCEL_MSG    called\n");
  286 
  287         if ((stat = nlm4svc_proc_cancel(rqstp, argp, &res)) == 0)
  288                 stat = nlm4svc_callback(rqstp, NLMPROC_CANCEL_RES, &res);
  289         return stat;
  290 }
  291 
  292 static int
  293 nlm4svc_proc_unlock_msg(struct svc_rqst *rqstp, struct nlm_args *argp,
  294                                                void            *resp)
  295 {
  296         struct nlm_res  res;
  297         u32             stat;
  298 
  299         dprintk("lockd: UNLOCK_MSG    called\n");
  300 
  301         if ((stat = nlm4svc_proc_unlock(rqstp, argp, &res)) == 0)
  302                 stat = nlm4svc_callback(rqstp, NLMPROC_UNLOCK_RES, &res);
  303         return stat;
  304 }
  305 
  306 static int
  307 nlm4svc_proc_granted_msg(struct svc_rqst *rqstp, struct nlm_args *argp,
  308                                                 void            *resp)
  309 {
  310         struct nlm_res  res;
  311         u32             stat;
  312 
  313         dprintk("lockd: GRANTED_MSG   called\n");
  314 
  315         if ((stat = nlm4svc_proc_granted(rqstp, argp, &res)) == 0)
  316                 stat = nlm4svc_callback(rqstp, NLMPROC_GRANTED_RES, &res);
  317         return stat;
  318 }
  319 
  320 /*
  321  * SHARE: create a DOS share or alter existing share.
  322  */
  323 static int
  324 nlm4svc_proc_share(struct svc_rqst *rqstp, struct nlm_args *argp,
  325                                           struct nlm_res  *resp)
  326 {
  327         struct nlm_host *host;
  328         struct nlm_file *file;
  329 
  330         dprintk("lockd: SHARE         called\n");
  331 
  332         resp->cookie = argp->cookie;
  333 
  334         /* Don't accept new lock requests during grace period */
  335         if (nlmsvc_grace_period && !argp->reclaim) {
  336                 resp->status = nlm_lck_denied_grace_period;
  337                 return rpc_success;
  338         }
  339 
  340         /* Obtain client and file */
  341         if ((resp->status = nlm4svc_retrieve_args(rqstp, argp, &host, &file)))
  342                 return rpc_success;
  343 
  344         /* Now try to create the share */
  345         resp->status = nlmsvc_share_file(host, file, argp);
  346 
  347         dprintk("lockd: SHARE         status %d\n", ntohl(resp->status));
  348         nlm_release_host(host);
  349         nlm_release_file(file);
  350         return rpc_success;
  351 }
  352 
  353 /*
  354  * UNSHARE: Release a DOS share.
  355  */
  356 static int
  357 nlm4svc_proc_unshare(struct svc_rqst *rqstp, struct nlm_args *argp,
  358                                             struct nlm_res  *resp)
  359 {
  360         struct nlm_host *host;
  361         struct nlm_file *file;
  362 
  363         dprintk("lockd: UNSHARE       called\n");
  364 
  365         resp->cookie = argp->cookie;
  366 
  367         /* Don't accept requests during grace period */
  368         if (nlmsvc_grace_period) {
  369                 resp->status = nlm_lck_denied_grace_period;
  370                 return rpc_success;
  371         }
  372 
  373         /* Obtain client and file */
  374         if ((resp->status = nlm4svc_retrieve_args(rqstp, argp, &host, &file)))
  375                 return rpc_success;
  376 
  377         /* Now try to lock the file */
  378         resp->status = nlmsvc_unshare_file(host, file, argp);
  379 
  380         dprintk("lockd: UNSHARE       status %d\n", ntohl(resp->status));
  381         nlm_release_host(host);
  382         nlm_release_file(file);
  383         return rpc_success;
  384 }
  385 
  386 /*
  387  * NM_LOCK: Create an unmonitored lock
  388  */
  389 static int
  390 nlm4svc_proc_nm_lock(struct svc_rqst *rqstp, struct nlm_args *argp,
  391                                             struct nlm_res  *resp)
  392 {
  393         dprintk("lockd: NM_LOCK       called\n");
  394 
  395         argp->monitor = 0;              /* just clean the monitor flag */
  396         return nlm4svc_proc_lock(rqstp, argp, resp);
  397 }
  398 
  399 /*
  400  * FREE_ALL: Release all locks and shares held by client
  401  */
  402 static int
  403 nlm4svc_proc_free_all(struct svc_rqst *rqstp, struct nlm_args *argp,
  404                                              void            *resp)
  405 {
  406         struct nlm_host *host;
  407 
  408         /* Obtain client */
  409         if (nlm4svc_retrieve_args(rqstp, argp, &host, NULL))
  410                 return rpc_success;
  411 
  412         nlmsvc_free_host_resources(host);
  413         nlm_release_host(host);
  414         return rpc_success;
  415 }
  416 
  417 /*
  418  * SM_NOTIFY: private callback from statd (not part of official NLM proto)
  419  */
  420 static int
  421 nlm4svc_proc_sm_notify(struct svc_rqst *rqstp, struct nlm_reboot *argp,
  422                                               void              *resp)
  423 {
  424         struct sockaddr_in      saddr = rqstp->rq_addr;
  425         int                     vers = rqstp->rq_vers;
  426         int                     prot = rqstp->rq_prot;
  427         struct nlm_host         *host;
  428 
  429         dprintk("lockd: SM_NOTIFY     called\n");
  430         if (saddr.sin_addr.s_addr != htonl(INADDR_LOOPBACK)
  431          || ntohs(saddr.sin_port) >= 1024) {
  432                 printk(KERN_WARNING
  433                         "lockd: rejected NSM callback from %08x:%d\n",
  434                         ntohl(rqstp->rq_addr.sin_addr.s_addr),
  435                         ntohs(rqstp->rq_addr.sin_port));
  436                 return rpc_system_err;
  437         }
  438 
  439         /* Obtain the host pointer for this NFS server and try to
  440          * reclaim all locks we hold on this server.
  441          */
  442         saddr.sin_addr.s_addr = argp->addr;
  443         if ((host = nlmclnt_lookup_host(&saddr, prot, vers)) != NULL) {
  444                 nlmclnt_recovery(host, argp->state);
  445                 nlm_release_host(host);
  446         }
  447 
  448         /* If we run on an NFS server, delete all locks held by the client */
  449         if (nlmsvc_ops != NULL) {
  450                 struct svc_client       *clnt;
  451                 saddr.sin_addr.s_addr = argp->addr;
  452                 nlmsvc_ops->exp_readlock();
  453                 if ((clnt = nlmsvc_ops->exp_getclient(&saddr)) != NULL 
  454                  && (host = nlm_lookup_host(clnt, &saddr, 0, 0)) != NULL) {
  455                         nlmsvc_free_host_resources(host);
  456                 }
  457                 nlm_release_host(host);
  458                 nlmsvc_ops->exp_unlock();
  459         }
  460 
  461         return rpc_success;
  462 }
  463 
  464 /*
  465  * client sent a GRANTED_RES, let's remove the associated block
  466  */
  467 static int
  468 nlm4svc_proc_granted_res(struct svc_rqst *rqstp, struct nlm_res  *argp,
  469                                                 void            *resp)
  470 {
  471         if (!nlmsvc_ops)
  472                 return rpc_success;
  473 
  474         dprintk("lockd: GRANTED_RES   called\n");
  475 
  476         nlmsvc_grant_reply(&argp->cookie, argp->status);
  477         return rpc_success;
  478 }
  479 
  480 
  481 
  482 /*
  483  * This is the generic lockd callback for async RPC calls
  484  */
  485 static u32
  486 nlm4svc_callback(struct svc_rqst *rqstp, u32 proc, struct nlm_res *resp)
  487 {
  488         struct nlm_host *host;
  489         struct nlm_rqst *call;
  490 
  491         if (!(call = nlmclnt_alloc_call()))
  492                 return rpc_system_err;
  493 
  494         host = nlmclnt_lookup_host(&rqstp->rq_addr,
  495                                 rqstp->rq_prot, rqstp->rq_vers);
  496         if (!host) {
  497                 kfree(call);
  498                 return rpc_system_err;
  499         }
  500 
  501         call->a_flags = RPC_TASK_ASYNC;
  502         call->a_host  = host;
  503         memcpy(&call->a_args, resp, sizeof(*resp));
  504 
  505         if (nlmsvc_async_call(call, proc, nlm4svc_callback_exit) < 0)
  506                 goto error;
  507 
  508         return rpc_success;
  509  error:
  510         kfree(call);
  511         nlm_release_host(host);
  512         return rpc_system_err;
  513 }
  514 
  515 static void
  516 nlm4svc_callback_exit(struct rpc_task *task)
  517 {
  518         struct nlm_rqst *call = (struct nlm_rqst *) task->tk_calldata;
  519 
  520         if (task->tk_status < 0) {
  521                 dprintk("lockd: %4d callback failed (errno = %d)\n",
  522                                         task->tk_pid, -task->tk_status);
  523         }
  524         nlm_release_host(call->a_host);
  525         kfree(call);
  526 }
  527 
  528 /*
  529  * NLM Server procedures.
  530  */
  531 
  532 #define nlm4svc_encode_norep    nlm4svc_encode_void
  533 #define nlm4svc_decode_norep    nlm4svc_decode_void
  534 #define nlm4svc_decode_testres  nlm4svc_decode_void
  535 #define nlm4svc_decode_lockres  nlm4svc_decode_void
  536 #define nlm4svc_decode_unlockres        nlm4svc_decode_void
  537 #define nlm4svc_decode_cancelres        nlm4svc_decode_void
  538 #define nlm4svc_decode_grantedres       nlm4svc_decode_void
  539 
  540 #define nlm4svc_proc_none       nlm4svc_proc_null
  541 #define nlm4svc_proc_test_res   nlm4svc_proc_null
  542 #define nlm4svc_proc_lock_res   nlm4svc_proc_null
  543 #define nlm4svc_proc_cancel_res nlm4svc_proc_null
  544 #define nlm4svc_proc_unlock_res nlm4svc_proc_null
  545 
  546 struct nlm_void                 { int dummy; };
  547 
  548 #define PROC(name, xargt, xrest, argt, rest, respsize)  \
  549  { (svc_procfunc) nlm4svc_proc_##name,  \
  550    (kxdrproc_t) nlm4svc_decode_##xargt, \
  551    (kxdrproc_t) nlm4svc_encode_##xrest, \
  552    NULL,                                \
  553    sizeof(struct nlm_##argt),           \
  554    sizeof(struct nlm_##rest),           \
  555    0,                                   \
  556    0,                                   \
  557    respsize,                            \
  558  }
  559 #define Ck      (1+8)   /* cookie */
  560 #define No      (1+1024/4)      /* netobj */
  561 #define St      1       /* status */
  562 #define Rg      4       /* range (offset + length) */
  563 struct svc_procedure            nlmsvc_procedures4[] = {
  564   PROC(null,            void,           void,           void,   void, 1),
  565   PROC(test,            testargs,       testres,        args,   res, Ck+St+2+No+Rg),
  566   PROC(lock,            lockargs,       res,            args,   res, Ck+St),
  567   PROC(cancel,          cancargs,       res,            args,   res, Ck+St),
  568   PROC(unlock,          unlockargs,     res,            args,   res, Ck+St),
  569   PROC(granted,         testargs,       res,            args,   res, Ck+St),
  570   PROC(test_msg,        testargs,       norep,          args,   void, 1),
  571   PROC(lock_msg,        lockargs,       norep,          args,   void, 1),
  572   PROC(cancel_msg,      cancargs,       norep,          args,   void, 1),
  573   PROC(unlock_msg,      unlockargs,     norep,          args,   void, 1),
  574   PROC(granted_msg,     testargs,       norep,          args,   void, 1),
  575   PROC(test_res,        testres,        norep,          res,    void, 1),
  576   PROC(lock_res,        lockres,        norep,          res,    void, 1),
  577   PROC(cancel_res,      cancelres,      norep,          res,    void, 1),
  578   PROC(unlock_res,      unlockres,      norep,          res,    void, 1),
  579   PROC(granted_res,     res,            norep,          res,    void, 1),
  580   /* statd callback */
  581   PROC(sm_notify,       reboot,         void,           reboot, void, 1),
  582   PROC(none,            void,           void,           void,   void, 0),
  583   PROC(none,            void,           void,           void,   void, 0),
  584   PROC(none,            void,           void,           void,   void, 0),
  585   PROC(share,           shareargs,      shareres,       args,   res, Ck+St+1),
  586   PROC(unshare,         shareargs,      shareres,       args,   res, Ck+St+1),
  587   PROC(nm_lock,         lockargs,       res,            args,   res, Ck+St),
  588   PROC(free_all,        notify,         void,           args,   void, 1),
  589 
  590 };

Cache object: 46266b13027fd0cfc2b00837659ae7de


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]


This page is part of the FreeBSD/Linux Linux Kernel Cross-Reference, and was automatically generated using a modified version of the LXR engine.