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

Subversion Repositories test_project

[/] [test_project/] [trunk/] [linux_sd_driver/] [fs/] [lockd/] [svcproc.c] - Blame information for rev 62

Details | Compare with Previous | View Log

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

powered by: WebSVN 2.1.0

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