~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~ [ freetext search ] ~ [ file search ] ~

Linux Cross Reference
Linux/fs/lockd/svcproc.c

Version: ~ [ 2.4.0 ] ~
Architecture: ~ [ i386 ] ~ [ alpha ] ~ [ m68k ] ~ [ mips ] ~ [ ppc ] ~ [ sparc ] ~ [ sparc64 ] ~

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

~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~ [ freetext search ] ~ [ file search ] ~

This page was automatically generated by the LXR engine.
Visit the LXR main site for more information.