OpenCores
URL https://opencores.org/ocsvn/or1k/or1k/trunk

Subversion Repositories or1k

[/] [or1k/] [trunk/] [linux/] [linux-2.4/] [fs/] [lockd/] [clntproc.c] - Blame information for rev 1765

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 1275 phoenix
/*
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
 
24
static int      nlmclnt_test(struct nlm_rqst *, struct file_lock *);
25
static int      nlmclnt_lock(struct nlm_rqst *, struct file_lock *);
26
static int      nlmclnt_unlock(struct nlm_rqst *, struct file_lock *);
27
static void     nlmclnt_unlock_callback(struct rpc_task *);
28
static void     nlmclnt_cancel_callback(struct rpc_task *);
29
static int      nlm_stat_to_errno(u32 stat);
30
 
31
/*
32
 * Cookie counter for NLM requests
33
 */
34
static u32      nlm_cookie = 0x1234;
35
 
36
static 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
 */
47
static inline void
48
nlmclnt_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
 */
67
int
68
nlmclnt_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
 
89
void
90
nlmclnt_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
 */
103
int
104
nlmclnt_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
 
191
done:
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
 */
200
static inline int
201
nlmclnt_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
 */
213
struct nlm_rqst *
214
nlmclnt_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
 */
236
int
237
nlmclnt_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
 */
319
int
320
nlmsvc_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
 
346
int
347
nlmclnt_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
 */
383
static int
384
nlmclnt_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
 
408
static
409
void nlmclnt_insert_lock_callback(struct file_lock *fl)
410
{
411
        nlm_get_host(fl->fl_u.nfs_fl.host);
412
}
413
static
414
void 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
 */
442
static int
443
nlmclnt_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
 */
479
int
480
nlmclnt_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
 */
522
static int
523
nlmclnt_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
 
551
static void
552
nlmclnt_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
 
571
die:
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
 */
586
int
587
nlmclnt_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
 
622
static void
623
nlmclnt_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
 
652
die:
653
        nlm_release_host(req->a_host);
654
        kfree(req);
655
        return;
656
 
657
retry_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
 */
666
static int
667
nlm_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
}

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.