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

Subversion Repositories or1k

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

Details | Compare with Previous | View Log

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

powered by: WebSVN 2.1.0

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