linux/fs/lockd/xdr4.c
<<
>>
Prefs
   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/nfs.h>
  13
  14#include <linux/sunrpc/xdr.h>
  15#include <linux/sunrpc/clnt.h>
  16#include <linux/sunrpc/svc.h>
  17#include <linux/sunrpc/stats.h>
  18#include <linux/lockd/lockd.h>
  19
  20#define NLMDBG_FACILITY         NLMDBG_XDR
  21
  22static inline loff_t
  23s64_to_loff_t(__s64 offset)
  24{
  25        return (loff_t)offset;
  26}
  27
  28
  29static inline s64
  30loff_t_to_s64(loff_t offset)
  31{
  32        s64 res;
  33        if (offset > NLM4_OFFSET_MAX)
  34                res = NLM4_OFFSET_MAX;
  35        else if (offset < -NLM4_OFFSET_MAX)
  36                res = -NLM4_OFFSET_MAX;
  37        else
  38                res = offset;
  39        return res;
  40}
  41
  42/*
  43 * XDR functions for basic NLM types
  44 */
  45static __be32 *
  46nlm4_decode_cookie(__be32 *p, struct nlm_cookie *c)
  47{
  48        unsigned int    len;
  49
  50        len = ntohl(*p++);
  51        
  52        if(len==0)
  53        {
  54                c->len=4;
  55                memset(c->data, 0, 4);  /* hockeypux brain damage */
  56        }
  57        else if(len<=NLM_MAXCOOKIELEN)
  58        {
  59                c->len=len;
  60                memcpy(c->data, p, len);
  61                p+=XDR_QUADLEN(len);
  62        }
  63        else 
  64        {
  65                dprintk("lockd: bad cookie size %d (only cookies under "
  66                        "%d bytes are supported.)\n",
  67                                len, NLM_MAXCOOKIELEN);
  68                return NULL;
  69        }
  70        return p;
  71}
  72
  73static __be32 *
  74nlm4_encode_cookie(__be32 *p, struct nlm_cookie *c)
  75{
  76        *p++ = htonl(c->len);
  77        memcpy(p, c->data, c->len);
  78        p+=XDR_QUADLEN(c->len);
  79        return p;
  80}
  81
  82static __be32 *
  83nlm4_decode_fh(__be32 *p, struct nfs_fh *f)
  84{
  85        memset(f->data, 0, sizeof(f->data));
  86        f->size = ntohl(*p++);
  87        if (f->size > NFS_MAXFHSIZE) {
  88                dprintk("lockd: bad fhandle size %d (should be <=%d)\n",
  89                        f->size, NFS_MAXFHSIZE);
  90                return NULL;
  91        }
  92        memcpy(f->data, p, f->size);
  93        return p + XDR_QUADLEN(f->size);
  94}
  95
  96/*
  97 * Encode and decode owner handle
  98 */
  99static __be32 *
 100nlm4_decode_oh(__be32 *p, struct xdr_netobj *oh)
 101{
 102        return xdr_decode_netobj(p, oh);
 103}
 104
 105static __be32 *
 106nlm4_decode_lock(__be32 *p, struct nlm_lock *lock)
 107{
 108        struct file_lock        *fl = &lock->fl;
 109        __u64                   len, start;
 110        __s64                   end;
 111
 112        if (!(p = xdr_decode_string_inplace(p, &lock->caller,
 113                                            &lock->len, NLM_MAXSTRLEN))
 114         || !(p = nlm4_decode_fh(p, &lock->fh))
 115         || !(p = nlm4_decode_oh(p, &lock->oh)))
 116                return NULL;
 117        lock->svid  = ntohl(*p++);
 118
 119        locks_init_lock(fl);
 120        fl->fl_owner = current->files;
 121        fl->fl_pid   = (pid_t)lock->svid;
 122        fl->fl_flags = FL_POSIX;
 123        fl->fl_type  = F_RDLCK;         /* as good as anything else */
 124        p = xdr_decode_hyper(p, &start);
 125        p = xdr_decode_hyper(p, &len);
 126        end = start + len - 1;
 127
 128        fl->fl_start = s64_to_loff_t(start);
 129
 130        if (len == 0 || end < 0)
 131                fl->fl_end = OFFSET_MAX;
 132        else
 133                fl->fl_end = s64_to_loff_t(end);
 134        return p;
 135}
 136
 137/*
 138 * Encode result of a TEST/TEST_MSG call
 139 */
 140static __be32 *
 141nlm4_encode_testres(__be32 *p, struct nlm_res *resp)
 142{
 143        s64             start, len;
 144
 145        dprintk("xdr: before encode_testres (p %p resp %p)\n", p, resp);
 146        if (!(p = nlm4_encode_cookie(p, &resp->cookie)))
 147                return NULL;
 148        *p++ = resp->status;
 149
 150        if (resp->status == nlm_lck_denied) {
 151                struct file_lock        *fl = &resp->lock.fl;
 152
 153                *p++ = (fl->fl_type == F_RDLCK)? xdr_zero : xdr_one;
 154                *p++ = htonl(resp->lock.svid);
 155
 156                /* Encode owner handle. */
 157                if (!(p = xdr_encode_netobj(p, &resp->lock.oh)))
 158                        return NULL;
 159
 160                start = loff_t_to_s64(fl->fl_start);
 161                if (fl->fl_end == OFFSET_MAX)
 162                        len = 0;
 163                else
 164                        len = loff_t_to_s64(fl->fl_end - fl->fl_start + 1);
 165                
 166                p = xdr_encode_hyper(p, start);
 167                p = xdr_encode_hyper(p, len);
 168                dprintk("xdr: encode_testres (status %u pid %d type %d start %Ld end %Ld)\n",
 169                        resp->status, (int)resp->lock.svid, fl->fl_type,
 170                        (long long)fl->fl_start,  (long long)fl->fl_end);
 171        }
 172
 173        dprintk("xdr: after encode_testres (p %p resp %p)\n", p, resp);
 174        return p;
 175}
 176
 177
 178/*
 179 * First, the server side XDR functions
 180 */
 181int
 182nlm4svc_decode_testargs(struct svc_rqst *rqstp, __be32 *p, nlm_args *argp)
 183{
 184        u32     exclusive;
 185
 186        if (!(p = nlm4_decode_cookie(p, &argp->cookie)))
 187                return 0;
 188
 189        exclusive = ntohl(*p++);
 190        if (!(p = nlm4_decode_lock(p, &argp->lock)))
 191                return 0;
 192        if (exclusive)
 193                argp->lock.fl.fl_type = F_WRLCK;
 194
 195        return xdr_argsize_check(rqstp, p);
 196}
 197
 198int
 199nlm4svc_encode_testres(struct svc_rqst *rqstp, __be32 *p, struct nlm_res *resp)
 200{
 201        if (!(p = nlm4_encode_testres(p, resp)))
 202                return 0;
 203        return xdr_ressize_check(rqstp, p);
 204}
 205
 206int
 207nlm4svc_decode_lockargs(struct svc_rqst *rqstp, __be32 *p, nlm_args *argp)
 208{
 209        u32     exclusive;
 210
 211        if (!(p = nlm4_decode_cookie(p, &argp->cookie)))
 212                return 0;
 213        argp->block  = ntohl(*p++);
 214        exclusive    = ntohl(*p++);
 215        if (!(p = nlm4_decode_lock(p, &argp->lock)))
 216                return 0;
 217        if (exclusive)
 218                argp->lock.fl.fl_type = F_WRLCK;
 219        argp->reclaim = ntohl(*p++);
 220        argp->state   = ntohl(*p++);
 221        argp->monitor = 1;              /* monitor client by default */
 222
 223        return xdr_argsize_check(rqstp, p);
 224}
 225
 226int
 227nlm4svc_decode_cancargs(struct svc_rqst *rqstp, __be32 *p, nlm_args *argp)
 228{
 229        u32     exclusive;
 230
 231        if (!(p = nlm4_decode_cookie(p, &argp->cookie)))
 232                return 0;
 233        argp->block = ntohl(*p++);
 234        exclusive = ntohl(*p++);
 235        if (!(p = nlm4_decode_lock(p, &argp->lock)))
 236                return 0;
 237        if (exclusive)
 238                argp->lock.fl.fl_type = F_WRLCK;
 239        return xdr_argsize_check(rqstp, p);
 240}
 241
 242int
 243nlm4svc_decode_unlockargs(struct svc_rqst *rqstp, __be32 *p, nlm_args *argp)
 244{
 245        if (!(p = nlm4_decode_cookie(p, &argp->cookie))
 246         || !(p = nlm4_decode_lock(p, &argp->lock)))
 247                return 0;
 248        argp->lock.fl.fl_type = F_UNLCK;
 249        return xdr_argsize_check(rqstp, p);
 250}
 251
 252int
 253nlm4svc_decode_shareargs(struct svc_rqst *rqstp, __be32 *p, nlm_args *argp)
 254{
 255        struct nlm_lock *lock = &argp->lock;
 256
 257        memset(lock, 0, sizeof(*lock));
 258        locks_init_lock(&lock->fl);
 259        lock->svid = ~(u32) 0;
 260        lock->fl.fl_pid = (pid_t)lock->svid;
 261
 262        if (!(p = nlm4_decode_cookie(p, &argp->cookie))
 263         || !(p = xdr_decode_string_inplace(p, &lock->caller,
 264                                            &lock->len, NLM_MAXSTRLEN))
 265         || !(p = nlm4_decode_fh(p, &lock->fh))
 266         || !(p = nlm4_decode_oh(p, &lock->oh)))
 267                return 0;
 268        argp->fsm_mode = ntohl(*p++);
 269        argp->fsm_access = ntohl(*p++);
 270        return xdr_argsize_check(rqstp, p);
 271}
 272
 273int
 274nlm4svc_encode_shareres(struct svc_rqst *rqstp, __be32 *p, struct nlm_res *resp)
 275{
 276        if (!(p = nlm4_encode_cookie(p, &resp->cookie)))
 277                return 0;
 278        *p++ = resp->status;
 279        *p++ = xdr_zero;                /* sequence argument */
 280        return xdr_ressize_check(rqstp, p);
 281}
 282
 283int
 284nlm4svc_encode_res(struct svc_rqst *rqstp, __be32 *p, struct nlm_res *resp)
 285{
 286        if (!(p = nlm4_encode_cookie(p, &resp->cookie)))
 287                return 0;
 288        *p++ = resp->status;
 289        return xdr_ressize_check(rqstp, p);
 290}
 291
 292int
 293nlm4svc_decode_notify(struct svc_rqst *rqstp, __be32 *p, struct nlm_args *argp)
 294{
 295        struct nlm_lock *lock = &argp->lock;
 296
 297        if (!(p = xdr_decode_string_inplace(p, &lock->caller,
 298                                            &lock->len, NLM_MAXSTRLEN)))
 299                return 0;
 300        argp->state = ntohl(*p++);
 301        return xdr_argsize_check(rqstp, p);
 302}
 303
 304int
 305nlm4svc_decode_reboot(struct svc_rqst *rqstp, __be32 *p, struct nlm_reboot *argp)
 306{
 307        if (!(p = xdr_decode_string_inplace(p, &argp->mon, &argp->len, SM_MAXSTRLEN)))
 308                return 0;
 309        argp->state = ntohl(*p++);
 310        memcpy(&argp->priv.data, p, sizeof(argp->priv.data));
 311        p += XDR_QUADLEN(SM_PRIV_SIZE);
 312        return xdr_argsize_check(rqstp, p);
 313}
 314
 315int
 316nlm4svc_decode_res(struct svc_rqst *rqstp, __be32 *p, struct nlm_res *resp)
 317{
 318        if (!(p = nlm4_decode_cookie(p, &resp->cookie)))
 319                return 0;
 320        resp->status = *p++;
 321        return xdr_argsize_check(rqstp, p);
 322}
 323
 324int
 325nlm4svc_decode_void(struct svc_rqst *rqstp, __be32 *p, void *dummy)
 326{
 327        return xdr_argsize_check(rqstp, p);
 328}
 329
 330int
 331nlm4svc_encode_void(struct svc_rqst *rqstp, __be32 *p, void *dummy)
 332{
 333        return xdr_ressize_check(rqstp, p);
 334}
 335