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

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

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

  1 /*
  2  * linux/fs/lockd/xdr4.c
  3  *
  4  * XDR support for lockd and the lock client.
  5  *
  6  * Copyright (C) 1995, 1996 Olaf Kirch <okir@monad.swb.de>
  7  * Copyright (C) 1999, Trond Myklebust <trond.myklebust@fys.uio.no>
  8  */
  9 
 10 #include <linux/types.h>
 11 #include <linux/sched.h>
 12 #include <linux/utsname.h>
 13 #include <linux/nfs.h>
 14 
 15 #include <linux/sunrpc/xdr.h>
 16 #include <linux/sunrpc/clnt.h>
 17 #include <linux/sunrpc/svc.h>
 18 #include <linux/sunrpc/stats.h>
 19 #include <linux/lockd/lockd.h>
 20 #include <linux/lockd/sm_inter.h>
 21 
 22 #define NLMDBG_FACILITY         NLMDBG_XDR
 23 
 24 static inline loff_t
 25 s64_to_loff_t(__s64 offset)
 26 {
 27         return (loff_t)offset;
 28 }
 29 
 30 
 31 static inline s64
 32 loff_t_to_s64(loff_t offset)
 33 {
 34         s64 res;
 35         if (offset > NLM4_OFFSET_MAX)
 36                 res = NLM4_OFFSET_MAX;
 37         else if (offset < -NLM4_OFFSET_MAX)
 38                 res = -NLM4_OFFSET_MAX;
 39         else
 40                 res = offset;
 41         return res;
 42 }
 43 
 44 /*
 45  * XDR functions for basic NLM types
 46  */
 47 static u32 *
 48 nlm4_decode_cookie(u32 *p, struct nlm_cookie *c)
 49 {
 50         unsigned int    len;
 51 
 52         len = ntohl(*p++);
 53         
 54         if(len==0)
 55         {
 56                 c->len=4;
 57                 memset(c->data, 0, 4);  /* hockeypux brain damage */
 58         }
 59         else if(len<=8)
 60         {
 61                 c->len=len;
 62                 memcpy(c->data, p, len);
 63                 p+=(len+3)>>2;
 64         }
 65         else 
 66         {
 67                 printk(KERN_NOTICE
 68                         "lockd: bad cookie size %d (only cookies under 8 bytes are supported.)\n", len);
 69                 return NULL;
 70         }
 71         return p;
 72 }
 73 
 74 static u32 *
 75 nlm4_encode_cookie(u32 *p, struct nlm_cookie *c)
 76 {
 77         *p++ = htonl(c->len);
 78         memcpy(p, c->data, c->len);
 79         p+=(c->len+3)>>2;
 80         return p;
 81 }
 82 
 83 static u32 *
 84 nlm4_decode_fh(u32 *p, struct nfs_fh *f)
 85 {
 86         memset(f->data, 0, sizeof(f->data));
 87         f->size = ntohl(*p++);
 88         if (f->size > NFS_MAXFHSIZE) {
 89                 printk(KERN_NOTICE
 90                         "lockd: bad fhandle size %d (should be <=%d)\n",
 91                         f->size, NFS_MAXFHSIZE);
 92                 return NULL;
 93         }
 94         memcpy(f->data, p, f->size);
 95         return p + XDR_QUADLEN(f->size);
 96 }
 97 
 98 static u32 *
 99 nlm4_encode_fh(u32 *p, struct nfs_fh *f)
100 {
101         *p++ = htonl(f->size);
102         if (f->size) p[XDR_QUADLEN(f->size)-1] = 0; /* don't leak anything */
103         memcpy(p, f->data, f->size);
104         return p + XDR_QUADLEN(f->size);
105 }
106 
107 /*
108  * Encode and decode owner handle
109  */
110 static u32 *
111 nlm4_decode_oh(u32 *p, struct xdr_netobj *oh)
112 {
113         return xdr_decode_netobj(p, oh);
114 }
115 
116 static u32 *
117 nlm4_encode_oh(u32 *p, struct xdr_netobj *oh)
118 {
119         return xdr_encode_netobj(p, oh);
120 }
121 
122 static u32 *
123 nlm4_decode_lock(u32 *p, struct nlm_lock *lock)
124 {
125         struct file_lock        *fl = &lock->fl;
126         __s64                   len, start, end;
127         int                     tmp;
128 
129         if (!(p = xdr_decode_string(p, &lock->caller, &tmp, NLM_MAXSTRLEN))
130          || !(p = nlm4_decode_fh(p, &lock->fh))
131          || !(p = nlm4_decode_oh(p, &lock->oh)))
132                 return NULL;
133 
134         locks_init_lock(fl);
135         fl->fl_owner = current->files;
136         fl->fl_pid   = ntohl(*p++);
137         fl->fl_flags = FL_POSIX;
138         fl->fl_type  = F_RDLCK;         /* as good as anything else */
139         p = xdr_decode_hyper(p, &start);
140         p = xdr_decode_hyper(p, &len);
141         end = start + len - 1;
142 
143         fl->fl_start = s64_to_loff_t(start);
144 
145         if (len == 0 || end < 0)
146                 fl->fl_end = OFFSET_MAX;
147         else
148                 fl->fl_end = s64_to_loff_t(end);
149         return p;
150 }
151 
152 /*
153  * Encode a lock as part of an NLM call
154  */
155 static u32 *
156 nlm4_encode_lock(u32 *p, struct nlm_lock *lock)
157 {
158         struct file_lock        *fl = &lock->fl;
159         __s64                   start, len;
160 
161         if (!(p = xdr_encode_string(p, lock->caller))
162          || !(p = nlm4_encode_fh(p, &lock->fh))
163          || !(p = nlm4_encode_oh(p, &lock->oh)))
164                 return NULL;
165 
166         if (fl->fl_start > NLM4_OFFSET_MAX
167          || (fl->fl_end > NLM4_OFFSET_MAX && fl->fl_end != OFFSET_MAX))
168                 return NULL;
169 
170         *p++ = htonl(fl->fl_pid);
171 
172         start = loff_t_to_s64(fl->fl_start);
173         if (fl->fl_end == OFFSET_MAX)
174                 len = 0;
175         else
176                 len = loff_t_to_s64(fl->fl_end - fl->fl_start + 1);
177 
178         p = xdr_encode_hyper(p, start);
179         p = xdr_encode_hyper(p, len);
180 
181         return p;
182 }
183 
184 /*
185  * Encode result of a TEST/TEST_MSG call
186  */
187 static u32 *
188 nlm4_encode_testres(u32 *p, struct nlm_res *resp)
189 {
190         s64             start, len;
191 
192         dprintk("xdr: before encode_testres (p %p resp %p)\n", p, resp);
193         if (!(p = nlm4_encode_cookie(p, &resp->cookie)))
194                 return 0;
195         *p++ = resp->status;
196 
197         if (resp->status == nlm_lck_denied) {
198                 struct file_lock        *fl = &resp->lock.fl;
199 
200                 *p++ = (fl->fl_type == F_RDLCK)? xdr_zero : xdr_one;
201                 *p++ = htonl(fl->fl_pid);
202 
203                 /* Encode owner handle. */
204                 if (!(p = xdr_encode_netobj(p, &resp->lock.oh)))
205                         return 0;
206 
207                 start = loff_t_to_s64(fl->fl_start);
208                 if (fl->fl_end == OFFSET_MAX)
209                         len = 0;
210                 else
211                         len = loff_t_to_s64(fl->fl_end - fl->fl_start + 1);
212                 
213                 p = xdr_encode_hyper(p, start);
214                 p = xdr_encode_hyper(p, len);
215                 dprintk("xdr: encode_testres (status %d pid %d type %d start %Ld end %Ld)\n",
216                         resp->status, fl->fl_pid, fl->fl_type,
217                         (long long)fl->fl_start,  (long long)fl->fl_end);
218         }
219 
220         dprintk("xdr: after encode_testres (p %p resp %p)\n", p, resp);
221         return p;
222 }
223 
224 
225 /*
226  * Check buffer bounds after decoding arguments
227  */
228 static int
229 xdr_argsize_check(struct svc_rqst *rqstp, u32 *p)
230 {
231         struct svc_buf  *buf = &rqstp->rq_argbuf;
232 
233         return p - buf->base <= buf->buflen;
234 }
235 
236 static int
237 xdr_ressize_check(struct svc_rqst *rqstp, u32 *p)
238 {
239         struct svc_buf  *buf = &rqstp->rq_resbuf;
240 
241         buf->len = p - buf->base;
242         return (buf->len <= buf->buflen);
243 }
244 
245 /*
246  * First, the server side XDR functions
247  */
248 int
249 nlm4svc_decode_testargs(struct svc_rqst *rqstp, u32 *p, nlm_args *argp)
250 {
251         u32     exclusive;
252 
253         if (!(p = nlm4_decode_cookie(p, &argp->cookie)))
254                 return 0;
255 
256         exclusive = ntohl(*p++);
257         if (!(p = nlm4_decode_lock(p, &argp->lock)))
258                 return 0;
259         if (exclusive)
260                 argp->lock.fl.fl_type = F_WRLCK;
261 
262         return xdr_argsize_check(rqstp, p);
263 }
264 
265 int
266 nlm4svc_encode_testres(struct svc_rqst *rqstp, u32 *p, struct nlm_res *resp)
267 {
268         if (!(p = nlm4_encode_testres(p, resp)))
269                 return 0;
270         return xdr_ressize_check(rqstp, p);
271 }
272 
273 int
274 nlm4svc_decode_lockargs(struct svc_rqst *rqstp, u32 *p, nlm_args *argp)
275 {
276         u32     exclusive;
277 
278         if (!(p = nlm4_decode_cookie(p, &argp->cookie)))
279                 return 0;
280         argp->block  = ntohl(*p++);
281         exclusive    = ntohl(*p++);
282         if (!(p = nlm4_decode_lock(p, &argp->lock)))
283                 return 0;
284         if (exclusive)
285                 argp->lock.fl.fl_type = F_WRLCK;
286         argp->reclaim = ntohl(*p++);
287         argp->state   = ntohl(*p++);
288         argp->monitor = 1;              /* monitor client by default */
289 
290         return xdr_argsize_check(rqstp, p);
291 }
292 
293 int
294 nlm4svc_decode_cancargs(struct svc_rqst *rqstp, u32 *p, nlm_args *argp)
295 {
296         u32     exclusive;
297 
298         if (!(p = nlm4_decode_cookie(p, &argp->cookie)))
299                 return 0;
300         argp->block = ntohl(*p++);
301         exclusive = ntohl(*p++);
302         if (!(p = nlm4_decode_lock(p, &argp->lock)))
303                 return 0;
304         if (exclusive)
305                 argp->lock.fl.fl_type = F_WRLCK;
306         return xdr_argsize_check(rqstp, p);
307 }
308 
309 int
310 nlm4svc_decode_unlockargs(struct svc_rqst *rqstp, u32 *p, nlm_args *argp)
311 {
312         if (!(p = nlm4_decode_cookie(p, &argp->cookie))
313          || !(p = nlm4_decode_lock(p, &argp->lock)))
314                 return 0;
315         argp->lock.fl.fl_type = F_UNLCK;
316         return xdr_argsize_check(rqstp, p);
317 }
318 
319 int
320 nlm4svc_decode_shareargs(struct svc_rqst *rqstp, u32 *p, nlm_args *argp)
321 {
322         struct nlm_lock *lock = &argp->lock;
323         int             len;
324 
325         memset(lock, 0, sizeof(*lock));
326         locks_init_lock(&lock->fl);
327         lock->fl.fl_pid = ~(u32) 0;
328 
329         if (!(p = nlm4_decode_cookie(p, &argp->cookie))
330          || !(p = xdr_decode_string(p, &lock->caller, &len, NLM_MAXSTRLEN))
331          || !(p = nlm4_decode_fh(p, &lock->fh))
332          || !(p = nlm4_decode_oh(p, &lock->oh)))
333                 return 0;
334         argp->fsm_mode = ntohl(*p++);
335         argp->fsm_access = ntohl(*p++);
336         return xdr_argsize_check(rqstp, p);
337 }
338 
339 int
340 nlm4svc_encode_shareres(struct svc_rqst *rqstp, u32 *p, struct nlm_res *resp)
341 {
342         if (!(p = nlm4_encode_cookie(p, &resp->cookie)))
343                 return 0;
344         *p++ = resp->status;
345         *p++ = xdr_zero;                /* sequence argument */
346         return xdr_ressize_check(rqstp, p);
347 }
348 
349 int
350 nlm4svc_encode_res(struct svc_rqst *rqstp, u32 *p, struct nlm_res *resp)
351 {
352         if (!(p = nlm4_encode_cookie(p, &resp->cookie)))
353                 return 0;
354         *p++ = resp->status;
355         return xdr_ressize_check(rqstp, p);
356 }
357 
358 int
359 nlm4svc_decode_notify(struct svc_rqst *rqstp, u32 *p, struct nlm_args *argp)
360 {
361         struct nlm_lock *lock = &argp->lock;
362         int             len;
363 
364         if (!(p = xdr_decode_string(p, &lock->caller, &len, NLM_MAXSTRLEN)))
365                 return 0;
366         argp->state = ntohl(*p++);
367         return xdr_argsize_check(rqstp, p);
368 }
369 
370 int
371 nlm4svc_decode_reboot(struct svc_rqst *rqstp, u32 *p, struct nlm_reboot *argp)
372 {
373         if (!(p = xdr_decode_string(p, &argp->mon, &argp->len, SM_MAXSTRLEN)))
374                 return 0;
375         argp->state = ntohl(*p++);
376         argp->addr = ntohl(*p++);
377         return xdr_argsize_check(rqstp, p);
378 }
379 
380 int
381 nlm4svc_decode_res(struct svc_rqst *rqstp, u32 *p, struct nlm_res *resp)
382 {
383         if (!(p = nlm4_decode_cookie(p, &resp->cookie)))
384                 return 0;
385         resp->status = ntohl(*p++);
386         return xdr_argsize_check(rqstp, p);
387 }
388 
389 int
390 nlm4svc_decode_void(struct svc_rqst *rqstp, u32 *p, void *dummy)
391 {
392         return xdr_argsize_check(rqstp, p);
393 }
394 
395 int
396 nlm4svc_encode_void(struct svc_rqst *rqstp, u32 *p, void *dummy)
397 {
398         return xdr_ressize_check(rqstp, p);
399 }
400 
401 /*
402  * Now, the client side XDR functions
403  */
404 static int
405 nlm4clt_encode_void(struct rpc_rqst *req, u32 *p, void *ptr)
406 {
407         req->rq_slen = xdr_adjust_iovec(req->rq_svec, p);
408         return 0;
409 }
410 
411 static int
412 nlm4clt_decode_void(struct rpc_rqst *req, u32 *p, void *ptr)
413 {
414         return 0;
415 }
416 
417 static int
418 nlm4clt_encode_testargs(struct rpc_rqst *req, u32 *p, nlm_args *argp)
419 {
420         struct nlm_lock *lock = &argp->lock;
421 
422         if (!(p = nlm4_encode_cookie(p, &argp->cookie)))
423                 return -EIO;
424         *p++ = (lock->fl.fl_type == F_WRLCK)? xdr_one : xdr_zero;
425         if (!(p = nlm4_encode_lock(p, lock)))
426                 return -EIO;
427         req->rq_slen = xdr_adjust_iovec(req->rq_svec, p);
428         return 0;
429 }
430 
431 static int
432 nlm4clt_decode_testres(struct rpc_rqst *req, u32 *p, struct nlm_res *resp)
433 {
434         if (!(p = nlm4_decode_cookie(p, &resp->cookie)))
435                 return -EIO;
436         resp->status = ntohl(*p++);
437         if (resp->status == NLM_LCK_DENIED) {
438                 struct file_lock        *fl = &resp->lock.fl;
439                 u32                     excl;
440                 s64                     start, end, len;
441 
442                 memset(&resp->lock, 0, sizeof(resp->lock));
443                 locks_init_lock(fl);
444                 excl = ntohl(*p++);
445                 fl->fl_pid = ntohl(*p++);
446                 if (!(p = nlm4_decode_oh(p, &resp->lock.oh)))
447                         return -EIO;
448 
449                 fl->fl_flags = FL_POSIX;
450                 fl->fl_type  = excl? F_WRLCK : F_RDLCK;
451                 p = xdr_decode_hyper(p, &start);
452                 p = xdr_decode_hyper(p, &len);
453                 end = start + len - 1;
454 
455                 fl->fl_start = s64_to_loff_t(start);
456                 if (len == 0 || end < 0)
457                         fl->fl_end = OFFSET_MAX;
458                 else
459                         fl->fl_end = s64_to_loff_t(end);
460         }
461         return 0;
462 }
463 
464 
465 static int
466 nlm4clt_encode_lockargs(struct rpc_rqst *req, u32 *p, nlm_args *argp)
467 {
468         struct nlm_lock *lock = &argp->lock;
469 
470         if (!(p = nlm4_encode_cookie(p, &argp->cookie)))
471                 return -EIO;
472         *p++ = argp->block? xdr_one : xdr_zero;
473         *p++ = (lock->fl.fl_type == F_WRLCK)? xdr_one : xdr_zero;
474         if (!(p = nlm4_encode_lock(p, lock)))
475                 return -EIO;
476         *p++ = argp->reclaim? xdr_one : xdr_zero;
477         *p++ = htonl(argp->state);
478         req->rq_slen = xdr_adjust_iovec(req->rq_svec, p);
479         return 0;
480 }
481 
482 static int
483 nlm4clt_encode_cancargs(struct rpc_rqst *req, u32 *p, nlm_args *argp)
484 {
485         struct nlm_lock *lock = &argp->lock;
486 
487         if (!(p = nlm4_encode_cookie(p, &argp->cookie)))
488                 return -EIO;
489         *p++ = argp->block? xdr_one : xdr_zero;
490         *p++ = (lock->fl.fl_type == F_WRLCK)? xdr_one : xdr_zero;
491         if (!(p = nlm4_encode_lock(p, lock)))
492                 return -EIO;
493         req->rq_slen = xdr_adjust_iovec(req->rq_svec, p);
494         return 0;
495 }
496 
497 static int
498 nlm4clt_encode_unlockargs(struct rpc_rqst *req, u32 *p, nlm_args *argp)
499 {
500         struct nlm_lock *lock = &argp->lock;
501 
502         if (!(p = nlm4_encode_cookie(p, &argp->cookie)))
503                 return -EIO;
504         if (!(p = nlm4_encode_lock(p, lock)))
505                 return -EIO;
506         req->rq_slen = xdr_adjust_iovec(req->rq_svec, p);
507         return 0;
508 }
509 
510 static int
511 nlm4clt_encode_res(struct rpc_rqst *req, u32 *p, struct nlm_res *resp)
512 {
513         if (!(p = nlm4_encode_cookie(p, &resp->cookie)))
514                 return -EIO;
515         *p++ = resp->status;
516         req->rq_slen = xdr_adjust_iovec(req->rq_svec, p);
517         return 0;
518 }
519 
520 static int
521 nlm4clt_encode_testres(struct rpc_rqst *req, u32 *p, struct nlm_res *resp)
522 {
523         if (!(p = nlm4_encode_testres(p, resp)))
524                 return -EIO;
525         req->rq_slen = xdr_adjust_iovec(req->rq_svec, p);
526         return 0;
527 }
528 
529 static int
530 nlm4clt_decode_res(struct rpc_rqst *req, u32 *p, struct nlm_res *resp)
531 {
532         if (!(p = nlm4_decode_cookie(p, &resp->cookie)))
533                 return -EIO;
534         resp->status = ntohl(*p++);
535         return 0;
536 }
537 
538 /*
539  * Buffer requirements for NLM
540  */
541 #define NLM4_void_sz            0
542 #define NLM4_cookie_sz          3       /* 1 len , 2 data */
543 #define NLM4_caller_sz          1+XDR_QUADLEN(NLM_MAXSTRLEN)
544 #define NLM4_netobj_sz          1+XDR_QUADLEN(XDR_MAX_NETOBJ)
545 /* #define NLM4_owner_sz                1+XDR_QUADLEN(NLM4_MAXOWNER) */
546 #define NLM4_fhandle_sz         1+XDR_QUADLEN(NFS3_FHSIZE)
547 #define NLM4_lock_sz            5+NLM4_caller_sz+NLM4_netobj_sz+NLM4_fhandle_sz
548 #define NLM4_holder_sz          6+NLM4_netobj_sz
549 
550 #define NLM4_testargs_sz        NLM4_cookie_sz+1+NLM4_lock_sz
551 #define NLM4_lockargs_sz        NLM4_cookie_sz+4+NLM4_lock_sz
552 #define NLM4_cancargs_sz        NLM4_cookie_sz+2+NLM4_lock_sz
553 #define NLM4_unlockargs_sz      NLM4_cookie_sz+NLM4_lock_sz
554 
555 #define NLM4_testres_sz         NLM4_cookie_sz+1+NLM4_holder_sz
556 #define NLM4_res_sz             NLM4_cookie_sz+1
557 #define NLM4_norep_sz           0
558 
559 #ifndef MAX
560 # define MAX(a,b)               (((a) > (b))? (a) : (b))
561 #endif
562 
563 /*
564  * For NLM, a void procedure really returns nothing
565  */
566 #define nlm4clt_decode_norep    NULL
567 
568 #define PROC(proc, argtype, restype)                            \
569     { "nlm4_" #proc,                                            \
570       (kxdrproc_t) nlm4clt_encode_##argtype,                    \
571       (kxdrproc_t) nlm4clt_decode_##restype,                    \
572       MAX(NLM4_##argtype##_sz, NLM4_##restype##_sz) << 2,       \
573       0                                                         \
574     }
575 
576 static struct rpc_procinfo      nlm4_procedures[] = {
577     PROC(null,          void,           void),
578     PROC(test,          testargs,       testres),
579     PROC(lock,          lockargs,       res),
580     PROC(canc,          cancargs,       res),
581     PROC(unlock,        unlockargs,     res),
582     PROC(granted,       testargs,       res),
583     PROC(test_msg,      testargs,       norep),
584     PROC(lock_msg,      lockargs,       norep),
585     PROC(canc_msg,      cancargs,       norep),
586     PROC(unlock_msg,    unlockargs,     norep),
587     PROC(granted_msg,   testargs,       norep),
588     PROC(test_res,      testres,        norep),
589     PROC(lock_res,      res,            norep),
590     PROC(canc_res,      res,            norep),
591     PROC(unlock_res,    res,            norep),
592     PROC(granted_res,   res,            norep),
593     PROC(undef,         void,           void),
594     PROC(undef,         void,           void),
595     PROC(undef,         void,           void),
596     PROC(undef,         void,           void),
597 #ifdef NLMCLNT_SUPPORT_SHARES
598     PROC(share,         shareargs,      shareres),
599     PROC(unshare,       shareargs,      shareres),
600     PROC(nm_lock,       lockargs,       res),
601     PROC(free_all,      notify,         void),
602 #else
603     PROC(undef,         void,           void),
604     PROC(undef,         void,           void),
605     PROC(undef,         void,           void),
606     PROC(undef,         void,           void),
607 #endif
608 };
609 
610 struct rpc_version      nlm_version4 = {
611         4, 24, nlm4_procedures,
612 };
613 

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