linux-old/fs/lockd/clntproc.c
<<
>>
Prefs
   1/*
   2 * linux/fs/lockd/clntproc.c
   3 *
   4 * RPC procedures for the client side NLM implementation
   5 *
   6 * Copyright (C) 1996, Olaf Kirch <okir@monad.swb.de>
   7 */
   8
   9#include <linux/config.h>
  10#include <linux/types.h>
  11#include <linux/errno.h>
  12#include <linux/fs.h>
  13#include <linux/nfs_fs.h>
  14#include <linux/utsname.h>
  15#include <linux/smp_lock.h>
  16#include <linux/sunrpc/clnt.h>
  17#include <linux/sunrpc/svc.h>
  18#include <linux/lockd/lockd.h>
  19#include <linux/lockd/sm_inter.h>
  20
  21#define NLMDBG_FACILITY         NLMDBG_CLIENT
  22#define NLMCLNT_GRACE_WAIT      (5*HZ)
  23
  24static int      nlmclnt_test(struct nlm_rqst *, struct file_lock *);
  25static int      nlmclnt_lock(struct nlm_rqst *, struct file_lock *);
  26static int      nlmclnt_unlock(struct nlm_rqst *, struct file_lock *);
  27static void     nlmclnt_unlock_callback(struct rpc_task *);
  28static void     nlmclnt_cancel_callback(struct rpc_task *);
  29static int      nlm_stat_to_errno(u32 stat);
  30
  31/*
  32 * Cookie counter for NLM requests
  33 */
  34static u32      nlm_cookie = 0x1234;
  35
  36static inline void nlmclnt_next_cookie(struct nlm_cookie *c)
  37{
  38        memcpy(c->data, &nlm_cookie, 4);
  39        memset(c->data+4, 0, 4);
  40        c->len=4;
  41        nlm_cookie++;
  42}
  43
  44/*
  45 * Initialize arguments for TEST/LOCK/UNLOCK/CANCEL calls
  46 */
  47static inline void
  48nlmclnt_setlockargs(struct nlm_rqst *req, struct file_lock *fl)
  49{
  50        struct nlm_args *argp = &req->a_args;
  51        struct nlm_lock *lock = &argp->lock;
  52
  53        nlmclnt_next_cookie(&argp->cookie);
  54        argp->state   = nsm_local_state;
  55        memcpy(&lock->fh, NFS_FH(fl->fl_file->f_dentry->d_inode), sizeof(struct nfs_fh));
  56        lock->caller  = system_utsname.nodename;
  57        lock->oh.data = req->a_owner;
  58        lock->oh.len  = sprintf(req->a_owner, "%d@%s",
  59                                current->pid, system_utsname.nodename);
  60        locks_copy_lock(&lock->fl, fl);
  61}
  62
  63/*
  64 * Initialize arguments for GRANTED call. The nlm_rqst structure
  65 * has been cleared already.
  66 */
  67int
  68nlmclnt_setgrantargs(struct nlm_rqst *call, struct nlm_lock *lock)
  69{
  70        locks_copy_lock(&call->a_args.lock.fl, &lock->fl);
  71        memcpy(&call->a_args.lock.fh, &lock->fh, sizeof(call->a_args.lock.fh));
  72        call->a_args.lock.caller = system_utsname.nodename;
  73        call->a_args.lock.oh.len = lock->oh.len;
  74
  75        /* set default data area */
  76        call->a_args.lock.oh.data = call->a_owner;
  77
  78        if (lock->oh.len > NLMCLNT_OHSIZE) {
  79                void *data = kmalloc(lock->oh.len, GFP_KERNEL);
  80                if (!data)
  81                        return 0;
  82                call->a_args.lock.oh.data = (u8 *) data;
  83        }
  84
  85        memcpy(call->a_args.lock.oh.data, lock->oh.data, lock->oh.len);
  86        return 1;
  87}
  88
  89void
  90nlmclnt_freegrantargs(struct nlm_rqst *call)
  91{
  92        /*
  93         * Check whether we allocated memory for the owner.
  94         */
  95        if (call->a_args.lock.oh.data != (u8 *) call->a_owner) {
  96                kfree(call->a_args.lock.oh.data);
  97        }
  98}
  99
 100/*
 101 * This is the main entry point for the NLM client.
 102 */
 103int
 104nlmclnt_proc(struct inode *inode, int cmd, struct file_lock *fl)
 105{
 106        struct nfs_server       *nfssrv = NFS_SERVER(inode);
 107        struct nlm_host         *host;
 108        struct nlm_rqst         reqst, *call = &reqst;
 109        sigset_t                oldset;
 110        unsigned long           flags;
 111        int                     status, proto, vers;
 112
 113        vers = (NFS_PROTO(inode)->version == 3) ? 4 : 1;
 114        if (NFS_PROTO(inode)->version > 3) {
 115                printk(KERN_NOTICE "NFSv4 file locking not implemented!\n");
 116                return -ENOLCK;
 117        }
 118
 119        /* Retrieve transport protocol from NFS client */
 120        proto = NFS_CLIENT(inode)->cl_xprt->prot;
 121
 122        if (!(host = nlmclnt_lookup_host(NFS_ADDR(inode), proto, vers)))
 123                return -ENOLCK;
 124
 125        /* Create RPC client handle if not there, and copy soft
 126         * and intr flags from NFS client. */
 127        if (host->h_rpcclnt == NULL) {
 128                struct rpc_clnt *clnt;
 129
 130                /* Bind an rpc client to this host handle (does not
 131                 * perform a portmapper lookup) */
 132                if (!(clnt = nlm_bind_host(host))) {
 133                        status = -ENOLCK;
 134                        goto done;
 135                }
 136                clnt->cl_softrtry = nfssrv->client->cl_softrtry;
 137                clnt->cl_intr     = nfssrv->client->cl_intr;
 138                clnt->cl_chatty   = nfssrv->client->cl_chatty;
 139        }
 140
 141        /* Keep the old signal mask */
 142        spin_lock_irqsave(&current->sigmask_lock, flags);
 143        oldset = current->blocked;
 144
 145        /* If we're cleaning up locks because the process is exiting,
 146         * perform the RPC call asynchronously. */
 147        if ((IS_SETLK(cmd) || IS_SETLKW(cmd))
 148            && fl->fl_type == F_UNLCK
 149            && (current->flags & PF_EXITING)) {
 150                sigfillset(&current->blocked);  /* Mask all signals */
 151                recalc_sigpending(current);
 152                spin_unlock_irqrestore(&current->sigmask_lock, flags);
 153
 154                call = nlmclnt_alloc_call();
 155                if (!call) {
 156                        status = -ENOMEM;
 157                        goto out_restore;
 158                }
 159                call->a_flags = RPC_TASK_ASYNC;
 160        } else {
 161                spin_unlock_irqrestore(&current->sigmask_lock, flags);
 162                memset(call, 0, sizeof(*call));
 163                locks_init_lock(&call->a_args.lock.fl);
 164                locks_init_lock(&call->a_res.lock.fl);
 165        }
 166        call->a_host = host;
 167
 168        /* Set up the argument struct */
 169        nlmclnt_setlockargs(call, fl);
 170
 171        if (IS_SETLK(cmd) || IS_SETLKW(cmd)) {
 172                if (fl->fl_type != F_UNLCK) {
 173                        call->a_args.block = IS_SETLKW(cmd) ? 1 : 0;
 174                        status = nlmclnt_lock(call, fl);
 175                } else
 176                        status = nlmclnt_unlock(call, fl);
 177        } else if (IS_GETLK(cmd))
 178                status = nlmclnt_test(call, fl);
 179        else
 180                status = -EINVAL;
 181
 182        if (status < 0 && (call->a_flags & RPC_TASK_ASYNC))
 183                kfree(call);
 184
 185 out_restore:
 186        spin_lock_irqsave(&current->sigmask_lock, flags);
 187        current->blocked = oldset;
 188        recalc_sigpending(current);
 189        spin_unlock_irqrestore(&current->sigmask_lock, flags);
 190
 191done:
 192        dprintk("lockd: clnt proc returns %d\n", status);
 193        nlm_release_host(host);
 194        return status;
 195}
 196
 197/*
 198 * Wait while server is in grace period
 199 */
 200static inline int
 201nlmclnt_grace_wait(struct nlm_host *host)
 202{
 203        if (!host->h_reclaiming)
 204                interruptible_sleep_on_timeout(&host->h_gracewait, 10*HZ);
 205        else
 206                interruptible_sleep_on(&host->h_gracewait);
 207        return signalled()? -ERESTARTSYS : 0;
 208}
 209
 210/*
 211 * Allocate an NLM RPC call struct
 212 */
 213struct nlm_rqst *
 214nlmclnt_alloc_call(void)
 215{
 216        struct nlm_rqst *call;
 217
 218        while (!signalled()) {
 219                call = (struct nlm_rqst *) kmalloc(sizeof(struct nlm_rqst), GFP_KERNEL);
 220                if (call) {
 221                        memset(call, 0, sizeof(*call));
 222                        locks_init_lock(&call->a_args.lock.fl);
 223                        locks_init_lock(&call->a_res.lock.fl);
 224                        return call;
 225                }
 226                printk("nlmclnt_alloc_call: failed, waiting for memory\n");
 227                current->state = TASK_INTERRUPTIBLE;
 228                schedule_timeout(5*HZ);
 229        }
 230        return NULL;
 231}
 232
 233/*
 234 * Generic NLM call
 235 */
 236int
 237nlmclnt_call(struct nlm_rqst *req, u32 proc)
 238{
 239        struct nlm_host *host = req->a_host;
 240        struct rpc_clnt *clnt;
 241        struct nlm_args *argp = &req->a_args;
 242        struct nlm_res  *resp = &req->a_res;
 243        struct file     *filp = argp->lock.fl.fl_file;
 244        struct rpc_message msg;
 245        int             status;
 246
 247        dprintk("lockd: call procedure %s on %s\n",
 248                        nlm_procname(proc), host->h_name);
 249
 250        msg.rpc_proc = proc;
 251        msg.rpc_argp = argp;
 252        msg.rpc_resp = resp;
 253        if (filp)
 254                msg.rpc_cred = nfs_file_cred(filp);
 255        else
 256                msg.rpc_cred = NULL;
 257
 258        do {
 259                if (host->h_reclaiming && !argp->reclaim) {
 260                        interruptible_sleep_on(&host->h_gracewait);
 261                        continue;
 262                }
 263
 264                /* If we have no RPC client yet, create one. */
 265                if ((clnt = nlm_bind_host(host)) == NULL)
 266                        return -ENOLCK;
 267
 268                /* Perform the RPC call. If an error occurs, try again */
 269                if ((status = rpc_call_sync(clnt, &msg, 0)) < 0) {
 270                        dprintk("lockd: rpc_call returned error %d\n", -status);
 271                        switch (status) {
 272                        case -EPROTONOSUPPORT:
 273                                status = -EINVAL;
 274                                break;
 275                        case -ECONNREFUSED:
 276                        case -ETIMEDOUT:
 277                        case -ENOTCONN:
 278                                nlm_rebind_host(host);
 279                                status = -EAGAIN;
 280                                break;
 281                        case -ERESTARTSYS:
 282                                return signalled () ? -EINTR : status;
 283                        default:
 284                                break;
 285                        }
 286                        break;
 287                } else
 288                if (resp->status == NLM_LCK_DENIED_GRACE_PERIOD) {
 289                        dprintk("lockd: server in grace period\n");
 290                        if (argp->reclaim) {
 291                                printk(KERN_WARNING
 292                                     "lockd: spurious grace period reject?!\n");
 293                                return -ENOLCK;
 294                        }
 295                } else {
 296                        dprintk("lockd: server returns status %d\n", resp->status);
 297                        return 0;       /* Okay, call complete */
 298                }
 299
 300                /* Back off a little and try again */
 301                interruptible_sleep_on_timeout(&host->h_gracewait, 15*HZ);
 302
 303                /* When the lock requested by F_SETLKW isn't available,
 304                   we will wait until the request can be satisfied. If
 305                   a signal is received during wait, we should return
 306                   -EINTR. */
 307                if (signalled ()) {
 308                        status = -EINTR;
 309                        break;
 310                }
 311        } while (1);
 312
 313        return status;
 314}
 315
 316/*
 317 * Generic NLM call, async version.
 318 */
 319int
 320nlmsvc_async_call(struct nlm_rqst *req, u32 proc, rpc_action callback)
 321{
 322        struct nlm_host *host = req->a_host;
 323        struct rpc_clnt *clnt;
 324        struct nlm_args *argp = &req->a_args;
 325        struct nlm_res  *resp = &req->a_res;
 326        struct rpc_message msg;
 327        int             status;
 328
 329        dprintk("lockd: call procedure %s on %s (async)\n",
 330                        nlm_procname(proc), host->h_name);
 331
 332        /* If we have no RPC client yet, create one. */
 333        if ((clnt = nlm_bind_host(host)) == NULL)
 334                return -ENOLCK;
 335
 336        /* bootstrap and kick off the async RPC call */
 337        msg.rpc_proc = proc;
 338        msg.rpc_argp = argp;
 339        msg.rpc_resp =resp;
 340        msg.rpc_cred = NULL;    
 341        status = rpc_call_async(clnt, &msg, RPC_TASK_ASYNC, callback, req);
 342
 343        return status;
 344}
 345
 346int
 347nlmclnt_async_call(struct nlm_rqst *req, u32 proc, rpc_action callback)
 348{
 349        struct nlm_host *host = req->a_host;
 350        struct rpc_clnt *clnt;
 351        struct nlm_args *argp = &req->a_args;
 352        struct nlm_res  *resp = &req->a_res;
 353        struct file     *file = argp->lock.fl.fl_file;
 354        struct rpc_message msg;
 355        int             status;
 356
 357        dprintk("lockd: call procedure %s on %s (async)\n",
 358                        nlm_procname(proc), host->h_name);
 359
 360        /* If we have no RPC client yet, create one. */
 361        if ((clnt = nlm_bind_host(host)) == NULL)
 362                return -ENOLCK;
 363
 364        /* bootstrap and kick off the async RPC call */
 365        msg.rpc_proc = proc;
 366        msg.rpc_argp = argp;
 367        msg.rpc_resp =resp;
 368        if (file)
 369                msg.rpc_cred = nfs_file_cred(file);
 370        else
 371                msg.rpc_cred = NULL;
 372        /* Increment host refcount */
 373        nlm_get_host(host);
 374        status = rpc_call_async(clnt, &msg, RPC_TASK_ASYNC, callback, req);
 375        if (status < 0)
 376                nlm_release_host(host);
 377        return status;
 378}
 379
 380/*
 381 * TEST for the presence of a conflicting lock
 382 */
 383static int
 384nlmclnt_test(struct nlm_rqst *req, struct file_lock *fl)
 385{
 386        int     status;
 387
 388        if ((status = nlmclnt_call(req, NLMPROC_TEST)) < 0)
 389                return status;
 390
 391        status = req->a_res.status;
 392        if (status == NLM_LCK_GRANTED) {
 393                fl->fl_type = F_UNLCK;
 394        } if (status == NLM_LCK_DENIED) {
 395                /*
 396                 * Report the conflicting lock back to the application.
 397                 * FIXME: Is it OK to report the pid back as well?
 398                 */
 399                locks_copy_lock(fl, &req->a_res.lock.fl);
 400                /* fl->fl_pid = 0; */
 401        } else {
 402                return nlm_stat_to_errno(req->a_res.status);
 403        }
 404
 405        return 0;
 406}
 407
 408static
 409void nlmclnt_insert_lock_callback(struct file_lock *fl)
 410{
 411        nlm_get_host(fl->fl_u.nfs_fl.host);
 412}
 413static
 414void nlmclnt_remove_lock_callback(struct file_lock *fl)
 415{
 416        if (fl->fl_u.nfs_fl.host) {
 417                nlm_release_host(fl->fl_u.nfs_fl.host);
 418                fl->fl_u.nfs_fl.host = NULL;
 419        }
 420}
 421
 422/*
 423 * LOCK: Try to create a lock
 424 *
 425 *                      Programmer Harassment Alert
 426 *
 427 * When given a blocking lock request in a sync RPC call, the HPUX lockd
 428 * will faithfully return LCK_BLOCKED but never cares to notify us when
 429 * the lock could be granted. This way, our local process could hang
 430 * around forever waiting for the callback.
 431 *
 432 *  Solution A: Implement busy-waiting
 433 *  Solution B: Use the async version of the call (NLM_LOCK_{MSG,RES})
 434 *
 435 * For now I am implementing solution A, because I hate the idea of
 436 * re-implementing lockd for a third time in two months. The async
 437 * calls shouldn't be too hard to do, however.
 438 *
 439 * This is one of the lovely things about standards in the NFS area:
 440 * they're so soft and squishy you can't really blame HP for doing this.
 441 */
 442static int
 443nlmclnt_lock(struct nlm_rqst *req, struct file_lock *fl)
 444{
 445        struct nlm_host *host = req->a_host;
 446        struct nlm_res  *resp = &req->a_res;
 447        int             status;
 448
 449        if (!host->h_monitored && nsm_monitor(host) < 0) {
 450                printk(KERN_NOTICE "lockd: failed to monitor %s\n",
 451                                        host->h_name);
 452                return -ENOLCK;
 453        }
 454
 455        do {
 456                if ((status = nlmclnt_call(req, NLMPROC_LOCK)) >= 0) {
 457                        if (resp->status != NLM_LCK_BLOCKED)
 458                                break;
 459                        status = nlmclnt_block(host, fl, &resp->status);
 460                }
 461                if (status < 0)
 462                        return status;
 463        } while (resp->status == NLM_LCK_BLOCKED && req->a_args.block);
 464
 465        if (resp->status == NLM_LCK_GRANTED) {
 466                fl->fl_u.nfs_fl.state = host->h_state;
 467                fl->fl_u.nfs_fl.flags |= NFS_LCK_GRANTED;
 468                fl->fl_u.nfs_fl.host = host;
 469                fl->fl_insert = nlmclnt_insert_lock_callback;
 470                fl->fl_remove = nlmclnt_remove_lock_callback;
 471        }
 472
 473        return nlm_stat_to_errno(resp->status);
 474}
 475
 476/*
 477 * RECLAIM: Try to reclaim a lock
 478 */
 479int
 480nlmclnt_reclaim(struct nlm_host *host, struct file_lock *fl)
 481{
 482        struct nlm_rqst reqst, *req;
 483        int             status;
 484
 485        req = &reqst;
 486        memset(req, 0, sizeof(*req));
 487        locks_init_lock(&req->a_args.lock.fl);
 488        locks_init_lock(&req->a_res.lock.fl);
 489        req->a_host  = host;
 490        req->a_flags = 0;
 491
 492        /* Set up the argument struct */
 493        nlmclnt_setlockargs(req, fl);
 494        req->a_args.reclaim = 1;
 495
 496        if ((status = nlmclnt_call(req, NLMPROC_LOCK)) >= 0
 497         && req->a_res.status == NLM_LCK_GRANTED)
 498                return 0;
 499
 500        printk(KERN_WARNING "lockd: failed to reclaim lock for pid %d "
 501                                "(errno %d, status %d)\n", fl->fl_pid,
 502                                status, req->a_res.status);
 503
 504        /*
 505         * FIXME: This is a serious failure. We can
 506         *
 507         *  a.  Ignore the problem
 508         *  b.  Send the owning process some signal (Linux doesn't have
 509         *      SIGLOST, though...)
 510         *  c.  Retry the operation
 511         *
 512         * Until someone comes up with a simple implementation
 513         * for b or c, I'll choose option a.
 514         */
 515
 516        return -ENOLCK;
 517}
 518
 519/*
 520 * UNLOCK: remove an existing lock
 521 */
 522static int
 523nlmclnt_unlock(struct nlm_rqst *req, struct file_lock *fl)
 524{
 525        struct nlm_res  *resp = &req->a_res;
 526        int             status;
 527
 528        /* Clean the GRANTED flag now so the lock doesn't get
 529         * reclaimed while we're stuck in the unlock call. */
 530        fl->fl_u.nfs_fl.flags &= ~NFS_LCK_GRANTED;
 531
 532        if (req->a_flags & RPC_TASK_ASYNC) {
 533                return nlmclnt_async_call(req, NLMPROC_UNLOCK,
 534                                        nlmclnt_unlock_callback);
 535        }
 536
 537        if ((status = nlmclnt_call(req, NLMPROC_UNLOCK)) < 0)
 538                return status;
 539
 540        if (resp->status == NLM_LCK_GRANTED)
 541                return 0;
 542
 543        if (resp->status != NLM_LCK_DENIED_NOLOCKS)
 544                printk("lockd: unexpected unlock status: %d\n", resp->status);
 545
 546        /* What to do now? I'm out of my depth... */
 547
 548        return -ENOLCK;
 549}
 550
 551static void
 552nlmclnt_unlock_callback(struct rpc_task *task)
 553{
 554        struct nlm_rqst *req = (struct nlm_rqst *) task->tk_calldata;
 555        int             status = req->a_res.status;
 556
 557        if (RPC_ASSASSINATED(task))
 558                goto die;
 559
 560        if (task->tk_status < 0) {
 561                dprintk("lockd: unlock failed (err = %d)\n", -task->tk_status);
 562                goto retry_rebind;
 563        }
 564        if (status == NLM_LCK_DENIED_GRACE_PERIOD) {
 565                rpc_delay(task, NLMCLNT_GRACE_WAIT);
 566                goto retry_unlock;
 567        }
 568        if (status != NLM_LCK_GRANTED)
 569                printk(KERN_WARNING "lockd: unexpected unlock status: %d\n", status);
 570
 571die:
 572        nlm_release_host(req->a_host);
 573        kfree(req);
 574        return;
 575 retry_rebind:
 576        nlm_rebind_host(req->a_host);
 577 retry_unlock:
 578        rpc_restart_call(task);
 579}
 580
 581/*
 582 * Cancel a blocked lock request.
 583 * We always use an async RPC call for this in order not to hang a
 584 * process that has been Ctrl-C'ed.
 585 */
 586int
 587nlmclnt_cancel(struct nlm_host *host, struct file_lock *fl)
 588{
 589        struct nlm_rqst *req;
 590        unsigned long   flags;
 591        sigset_t        oldset;
 592        int             status;
 593
 594        /* Block all signals while setting up call */
 595        spin_lock_irqsave(&current->sigmask_lock, flags);
 596        oldset = current->blocked;
 597        sigfillset(&current->blocked);
 598        recalc_sigpending(current);
 599        spin_unlock_irqrestore(&current->sigmask_lock, flags);
 600
 601        req = nlmclnt_alloc_call();
 602        if (!req)
 603                return -ENOMEM;
 604        req->a_host  = host;
 605        req->a_flags = RPC_TASK_ASYNC;
 606
 607        nlmclnt_setlockargs(req, fl);
 608
 609        status = nlmclnt_async_call(req, NLMPROC_CANCEL,
 610                                        nlmclnt_cancel_callback);
 611        if (status < 0)
 612                kfree(req);
 613
 614        spin_lock_irqsave(&current->sigmask_lock, flags);
 615        current->blocked = oldset;
 616        recalc_sigpending(current);
 617        spin_unlock_irqrestore(&current->sigmask_lock, flags);
 618
 619        return status;
 620}
 621
 622static void
 623nlmclnt_cancel_callback(struct rpc_task *task)
 624{
 625        struct nlm_rqst *req = (struct nlm_rqst *) task->tk_calldata;
 626
 627        if (RPC_ASSASSINATED(task))
 628                goto die;
 629
 630        if (task->tk_status < 0) {
 631                dprintk("lockd: CANCEL call error %d, retrying.\n",
 632                                        task->tk_status);
 633                goto retry_cancel;
 634        }
 635
 636        dprintk("lockd: cancel status %d (task %d)\n",
 637                        req->a_res.status, task->tk_pid);
 638
 639        switch (req->a_res.status) {
 640        case NLM_LCK_GRANTED:
 641        case NLM_LCK_DENIED_GRACE_PERIOD:
 642                /* Everything's good */
 643                break;
 644        case NLM_LCK_DENIED_NOLOCKS:
 645                dprintk("lockd: CANCEL failed (server has no locks)\n");
 646                goto retry_cancel;
 647        default:
 648                printk(KERN_NOTICE "lockd: weird return %d for CANCEL call\n",
 649                        req->a_res.status);
 650        }
 651
 652die:
 653        nlm_release_host(req->a_host);
 654        kfree(req);
 655        return;
 656
 657retry_cancel:
 658        nlm_rebind_host(req->a_host);
 659        rpc_restart_call(task);
 660        rpc_delay(task, 30 * HZ);
 661}
 662
 663/*
 664 * Convert an NLM status code to a generic kernel errno
 665 */
 666static int
 667nlm_stat_to_errno(u32 status)
 668{
 669        switch(status) {
 670        case NLM_LCK_GRANTED:
 671                return 0;
 672        case NLM_LCK_DENIED:
 673                return -EAGAIN;
 674        case NLM_LCK_DENIED_NOLOCKS:
 675        case NLM_LCK_DENIED_GRACE_PERIOD:
 676                return -ENOLCK;
 677        case NLM_LCK_BLOCKED:
 678                printk(KERN_NOTICE "lockd: unexpected status NLM_BLOCKED\n");
 679                return -ENOLCK;
 680#ifdef CONFIG_LOCKD_V4
 681        case NLM_DEADLCK:
 682                return -EDEADLK;
 683        case NLM_ROFS:
 684                return -EROFS;
 685        case NLM_STALE_FH:
 686                return -ESTALE;
 687        case NLM_FBIG:
 688                return -EOVERFLOW;
 689        case NLM_FAILED:
 690                return -ENOLCK;
 691#endif
 692        }
 693        printk(KERN_NOTICE "lockd: unexpected server status %d\n", status);
 694        return -ENOLCK;
 695}
 696
lxr.linux.no kindly hosted by Redpill Linpro AS, provider of Linux consulting and operations services since 1995.