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

Subversion Repositories or1k

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

Details | Compare with Previous | View Log

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

powered by: WebSVN 2.1.0

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