root/fs/lockd/svc4proc.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. nlm4svc_retrieve_args
  2. nlm4svc_proc_null
  3. __nlm4svc_proc_test
  4. nlm4svc_proc_test
  5. __nlm4svc_proc_lock
  6. nlm4svc_proc_lock
  7. __nlm4svc_proc_cancel
  8. nlm4svc_proc_cancel
  9. __nlm4svc_proc_unlock
  10. nlm4svc_proc_unlock
  11. __nlm4svc_proc_granted
  12. nlm4svc_proc_granted
  13. nlm4svc_callback_exit
  14. nlm4svc_callback_release
  15. nlm4svc_callback
  16. nlm4svc_proc_test_msg
  17. nlm4svc_proc_lock_msg
  18. nlm4svc_proc_cancel_msg
  19. nlm4svc_proc_unlock_msg
  20. nlm4svc_proc_granted_msg
  21. nlm4svc_proc_share
  22. nlm4svc_proc_unshare
  23. nlm4svc_proc_nm_lock
  24. nlm4svc_proc_free_all
  25. nlm4svc_proc_sm_notify
  26. nlm4svc_proc_granted_res

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

/* [<][>][^][v][top][bottom][index][help] */