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

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

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

  1 /*
  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/malloc.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         if ((stat = nlm4svc_proc_test(rqstp, argp, &res)) == 0)
258                 stat = nlm4svc_callback(rqstp, NLMPROC_TEST_RES, &res);
259         return stat;
260 }
261 
262 static int
263 nlm4svc_proc_lock_msg(struct svc_rqst *rqstp, struct nlm_args *argp,
264                                              void            *resp)
265 {
266         struct nlm_res  res;
267         u32             stat;
268 
269         dprintk("lockd: LOCK_MSG      called\n");
270 
271         if ((stat = nlm4svc_proc_lock(rqstp, argp, &res)) == 0)
272                 stat = nlm4svc_callback(rqstp, NLMPROC_LOCK_RES, &res);
273         return stat;
274 }
275 
276 static int
277 nlm4svc_proc_cancel_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: CANCEL_MSG    called\n");
284 
285         if ((stat = nlm4svc_proc_cancel(rqstp, argp, &res)) == 0)
286                 stat = nlm4svc_callback(rqstp, NLMPROC_CANCEL_RES, &res);
287         return stat;
288 }
289 
290 static int
291 nlm4svc_proc_unlock_msg(struct svc_rqst *rqstp, struct nlm_args *argp,
292                                                void            *resp)
293 {
294         struct nlm_res  res;
295         u32             stat;
296 
297         dprintk("lockd: UNLOCK_MSG    called\n");
298 
299         if ((stat = nlm4svc_proc_unlock(rqstp, argp, &res)) == 0)
300                 stat = nlm4svc_callback(rqstp, NLMPROC_UNLOCK_RES, &res);
301         return stat;
302 }
303 
304 static int
305 nlm4svc_proc_granted_msg(struct svc_rqst *rqstp, struct nlm_args *argp,
306                                                 void            *resp)
307 {
308         struct nlm_res  res;
309         u32             stat;
310 
311         dprintk("lockd: GRANTED_MSG   called\n");
312 
313         if ((stat = nlm4svc_proc_granted(rqstp, argp, &res)) == 0)
314                 stat = nlm4svc_callback(rqstp, NLMPROC_GRANTED_RES, &res);
315         return stat;
316 }
317 
318 /*
319  * SHARE: create a DOS share or alter existing share.
320  */
321 static int
322 nlm4svc_proc_share(struct svc_rqst *rqstp, struct nlm_args *argp,
323                                           struct nlm_res  *resp)
324 {
325         struct nlm_host *host;
326         struct nlm_file *file;
327 
328         dprintk("lockd: SHARE         called\n");
329 
330         resp->cookie = argp->cookie;
331 
332         /* Don't accept new lock requests during grace period */
333         if (nlmsvc_grace_period && !argp->reclaim) {
334                 resp->status = nlm_lck_denied_grace_period;
335                 return rpc_success;
336         }
337 
338         /* Obtain client and file */
339         if ((resp->status = nlm4svc_retrieve_args(rqstp, argp, &host, &file)))
340                 return rpc_success;
341 
342         /* Now try to create the share */
343         resp->status = nlmsvc_share_file(host, file, argp);
344 
345         dprintk("lockd: SHARE         status %d\n", ntohl(resp->status));
346         nlm_release_host(host);
347         nlm_release_file(file);
348         return rpc_success;
349 }
350 
351 /*
352  * UNSHARE: Release a DOS share.
353  */
354 static int
355 nlm4svc_proc_unshare(struct svc_rqst *rqstp, struct nlm_args *argp,
356                                             struct nlm_res  *resp)
357 {
358         struct nlm_host *host;
359         struct nlm_file *file;
360 
361         dprintk("lockd: UNSHARE       called\n");
362 
363         resp->cookie = argp->cookie;
364 
365         /* Don't accept requests during grace period */
366         if (nlmsvc_grace_period) {
367                 resp->status = nlm_lck_denied_grace_period;
368                 return rpc_success;
369         }
370 
371         /* Obtain client and file */
372         if ((resp->status = nlm4svc_retrieve_args(rqstp, argp, &host, &file)))
373                 return rpc_success;
374 
375         /* Now try to lock the file */
376         resp->status = nlmsvc_unshare_file(host, file, argp);
377 
378         dprintk("lockd: UNSHARE       status %d\n", ntohl(resp->status));
379         nlm_release_host(host);
380         nlm_release_file(file);
381         return rpc_success;
382 }
383 
384 /*
385  * NM_LOCK: Create an unmonitored lock
386  */
387 static int
388 nlm4svc_proc_nm_lock(struct svc_rqst *rqstp, struct nlm_args *argp,
389                                             struct nlm_res  *resp)
390 {
391         dprintk("lockd: NM_LOCK       called\n");
392 
393         argp->monitor = 0;              /* just clean the monitor flag */
394         return nlm4svc_proc_lock(rqstp, argp, resp);
395 }
396 
397 /*
398  * FREE_ALL: Release all locks and shares held by client
399  */
400 static int
401 nlm4svc_proc_free_all(struct svc_rqst *rqstp, struct nlm_args *argp,
402                                              void            *resp)
403 {
404         struct nlm_host *host;
405 
406         /* Obtain client */
407         if (nlm4svc_retrieve_args(rqstp, argp, &host, NULL))
408                 return rpc_success;
409 
410         nlmsvc_free_host_resources(host);
411         nlm_release_host(host);
412         return rpc_success;
413 }
414 
415 /*
416  * SM_NOTIFY: private callback from statd (not part of official NLM proto)
417  */
418 static int
419 nlm4svc_proc_sm_notify(struct svc_rqst *rqstp, struct nlm_reboot *argp,
420                                               void              *resp)
421 {
422         struct sockaddr_in      saddr = rqstp->rq_addr;
423         struct nlm_host         *host;
424 
425         dprintk("lockd: SM_NOTIFY     called\n");
426         if (saddr.sin_addr.s_addr != htonl(INADDR_LOOPBACK)
427          || ntohs(saddr.sin_port) >= 1024) {
428                 printk(KERN_WARNING
429                         "lockd: rejected NSM callback from %08x:%d\n",
430                         ntohl(rqstp->rq_addr.sin_addr.s_addr),
431                         ntohs(rqstp->rq_addr.sin_port));
432                 return rpc_system_err;
433         }
434 
435         /* Obtain the host pointer for this NFS server and try to
436          * reclaim all locks we hold on this server.
437          */
438         saddr.sin_addr.s_addr = argp->addr;     
439         if ((host = nlm_lookup_host(NULL, &saddr, IPPROTO_UDP, 1)) != NULL) {
440                 nlmclnt_recovery(host, argp->state);
441                 nlm_release_host(host);
442         }
443 
444         /* If we run on an NFS server, delete all locks held by the client */
445         if (nlmsvc_ops != NULL) {
446                 struct svc_client       *clnt;
447                 saddr.sin_addr.s_addr = argp->addr;     
448                 if ((clnt = nlmsvc_ops->exp_getclient(&saddr)) != NULL 
449                  && (host = nlm_lookup_host(clnt, &saddr, 0, 0)) != NULL) {
450                         nlmsvc_free_host_resources(host);
451                 }
452                 nlm_release_host(host);
453         }
454 
455         return rpc_success;
456 }
457 
458 /*
459  * This is the generic lockd callback for async RPC calls
460  */
461 static u32
462 nlm4svc_callback(struct svc_rqst *rqstp, u32 proc, struct nlm_res *resp)
463 {
464         struct nlm_host *host;
465         struct nlm_rqst *call;
466 
467         if (!(call = nlmclnt_alloc_call()))
468                 return rpc_system_err;
469 
470         host = nlmclnt_lookup_host(&rqstp->rq_addr,
471                                 rqstp->rq_prot, rqstp->rq_vers);
472         if (!host) {
473                 kfree(call);
474                 return rpc_system_err;
475         }
476 
477         call->a_flags = RPC_TASK_ASYNC;
478         call->a_host  = host;
479         memcpy(&call->a_args, resp, sizeof(*resp));
480 
481         if (nlmsvc_async_call(call, proc, nlm4svc_callback_exit) < 0)
482                 goto error;
483 
484         return rpc_success;
485  error:
486         kfree(call);
487         nlm_release_host(host);
488         return rpc_system_err;
489 }
490 
491 static void
492 nlm4svc_callback_exit(struct rpc_task *task)
493 {
494         struct nlm_rqst *call = (struct nlm_rqst *) task->tk_calldata;
495 
496         if (task->tk_status < 0) {
497                 dprintk("lockd: %4d callback failed (errno = %d)\n",
498                                         task->tk_pid, -task->tk_status);
499         }
500         nlm_release_host(call->a_host);
501         kfree(call);
502 }
503 
504 /*
505  * NLM Server procedures.
506  */
507 
508 #define nlm4svc_encode_norep    nlm4svc_encode_void
509 #define nlm4svc_decode_norep    nlm4svc_decode_void
510 #define nlm4svc_decode_testres  nlm4svc_decode_void
511 #define nlm4svc_decode_lockres  nlm4svc_decode_void
512 #define nlm4svc_decode_unlockres        nlm4svc_decode_void
513 #define nlm4svc_decode_cancelres        nlm4svc_decode_void
514 #define nlm4svc_decode_grantedres       nlm4svc_decode_void
515 
516 #define nlm4svc_proc_none       nlm4svc_proc_null
517 #define nlm4svc_proc_test_res   nlm4svc_proc_null
518 #define nlm4svc_proc_lock_res   nlm4svc_proc_null
519 #define nlm4svc_proc_cancel_res nlm4svc_proc_null
520 #define nlm4svc_proc_unlock_res nlm4svc_proc_null
521 #define nlm4svc_proc_granted_res        nlm4svc_proc_null
522 
523 struct nlm_void                 { int dummy; };
524 
525 #define PROC(name, xargt, xrest, argt, rest)    \
526  { (svc_procfunc) nlm4svc_proc_##name,  \
527    (kxdrproc_t) nlm4svc_decode_##xargt, \
528    (kxdrproc_t) nlm4svc_encode_##xrest, \
529    NULL,                                \
530    sizeof(struct nlm_##argt),           \
531    sizeof(struct nlm_##rest),           \
532    0,                                   \
533    0                                    \
534  }
535 struct svc_procedure            nlmsvc_procedures4[] = {
536   PROC(null,            void,           void,           void,   void),
537   PROC(test,            testargs,       testres,        args,   res),
538   PROC(lock,            lockargs,       res,            args,   res),
539   PROC(cancel,          cancargs,       res,            args,   res),
540   PROC(unlock,          unlockargs,     res,            args,   res),
541   PROC(granted,         testargs,       res,            args,   res),
542   PROC(test_msg,        testargs,       norep,          args,   void),
543   PROC(lock_msg,        lockargs,       norep,          args,   void),
544   PROC(cancel_msg,      cancargs,       norep,          args,   void),
545   PROC(unlock_msg,      unlockargs,     norep,          args,   void),
546   PROC(granted_msg,     testargs,       norep,          args,   void),
547   PROC(test_res,        testres,        norep,          res,    void),
548   PROC(lock_res,        lockres,        norep,          res,    void),
549   PROC(cancel_res,      cancelres,      norep,          res,    void),
550   PROC(unlock_res,      unlockres,      norep,          res,    void),
551   PROC(granted_res,     grantedres,     norep,          res,    void),
552   PROC(none,            void,           void,           void,   void),
553   PROC(none,            void,           void,           void,   void),
554   PROC(none,            void,           void,           void,   void),
555   PROC(none,            void,           void,           void,   void),
556   PROC(share,           shareargs,      shareres,       args,   res),
557   PROC(unshare,         shareargs,      shareres,       args,   res),
558   PROC(nm_lock,         lockargs,       res,            args,   res),
559   PROC(free_all,        notify,         void,           args,   void),
560 
561   /* statd callback */
562   PROC(sm_notify,       reboot,         void,           reboot, void),
563 };
564 

~ [ 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.