root/fs/lockd/svcproc.c

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

DEFINITIONS

This source file includes following definitions.
  1. cast_to_nlm
  2. nlmsvc_retrieve_args
  3. nlmsvc_proc_null
  4. __nlmsvc_proc_test
  5. nlmsvc_proc_test
  6. __nlmsvc_proc_lock
  7. nlmsvc_proc_lock
  8. __nlmsvc_proc_cancel
  9. nlmsvc_proc_cancel
  10. __nlmsvc_proc_unlock
  11. nlmsvc_proc_unlock
  12. __nlmsvc_proc_granted
  13. nlmsvc_proc_granted
  14. nlmsvc_callback_exit
  15. nlmsvc_release_call
  16. nlmsvc_callback_release
  17. nlmsvc_callback
  18. nlmsvc_proc_test_msg
  19. nlmsvc_proc_lock_msg
  20. nlmsvc_proc_cancel_msg
  21. nlmsvc_proc_unlock_msg
  22. nlmsvc_proc_granted_msg
  23. nlmsvc_proc_share
  24. nlmsvc_proc_unshare
  25. nlmsvc_proc_nm_lock
  26. nlmsvc_proc_free_all
  27. nlmsvc_proc_sm_notify
  28. nlmsvc_proc_granted_res

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

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