The Design and Implementation of the FreeBSD Operating System, Second Edition
Now available: The Design and Implementation of the FreeBSD Operating System (Second Edition)


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]

FreeBSD/Linux Kernel Cross Reference
sys/fs/nfsd/nfs3xdr.c

Version: -  FREEBSD  -  FREEBSD-13-STABLE  -  FREEBSD-13-0  -  FREEBSD-12-STABLE  -  FREEBSD-12-0  -  FREEBSD-11-STABLE  -  FREEBSD-11-0  -  FREEBSD-10-STABLE  -  FREEBSD-10-0  -  FREEBSD-9-STABLE  -  FREEBSD-9-0  -  FREEBSD-8-STABLE  -  FREEBSD-8-0  -  FREEBSD-7-STABLE  -  FREEBSD-7-0  -  FREEBSD-6-STABLE  -  FREEBSD-6-0  -  FREEBSD-5-STABLE  -  FREEBSD-5-0  -  FREEBSD-4-STABLE  -  FREEBSD-3-STABLE  -  FREEBSD22  -  l41  -  OPENBSD  -  linux-2.6  -  MK84  -  PLAN9  -  xnu-8792 
SearchContext: -  none  -  3  -  10 

    1 /*
    2  * linux/fs/nfsd/nfs3xdr.c
    3  *
    4  * XDR support for nfsd/protocol version 3.
    5  *
    6  * Copyright (C) 1995, 1996, 1997 Olaf Kirch <okir@monad.swb.de>
    7  */
    8 
    9 #include <linux/types.h>
   10 #include <linux/sched.h>
   11 #include <linux/nfs3.h>
   12 
   13 #include <linux/sunrpc/xdr.h>
   14 #include <linux/sunrpc/svc.h>
   15 #include <linux/nfsd/nfsd.h>
   16 #include <linux/nfsd/xdr3.h>
   17 
   18 #define NFSDDBG_FACILITY                NFSDDBG_XDR
   19 
   20 #ifdef NFSD_OPTIMIZE_SPACE
   21 # define inline
   22 #endif
   23 
   24 
   25 /*
   26  * Mapping of S_IF* types to NFS file types
   27  */
   28 static u32      nfs3_ftypes[] = {
   29         NF3NON,  NF3FIFO, NF3CHR, NF3BAD,
   30         NF3DIR,  NF3BAD,  NF3BLK, NF3BAD,
   31         NF3REG,  NF3BAD,  NF3LNK, NF3BAD,
   32         NF3SOCK, NF3BAD,  NF3LNK, NF3BAD,
   33 };
   34 
   35 /*
   36  * XDR functions for basic NFS types
   37  */
   38 static inline u32 *
   39 encode_time3(u32 *p, time_t secs)
   40 {
   41         *p++ = htonl((u32) secs); *p++ = 0;
   42         return p;
   43 }
   44 
   45 static inline u32 *
   46 decode_time3(u32 *p, time_t *secp)
   47 {
   48         *secp = ntohl(*p++);
   49         return p + 1;
   50 }
   51 
   52 static inline u32 *
   53 decode_fh(u32 *p, struct svc_fh *fhp)
   54 {
   55         unsigned int size;
   56         fh_init(fhp, NFS3_FHSIZE);
   57         size = ntohl(*p++);
   58         if (size > NFS3_FHSIZE)
   59                 return NULL;
   60 
   61         memcpy(&fhp->fh_handle.fh_base, p, size);
   62         fhp->fh_handle.fh_size = size;
   63         return p + XDR_QUADLEN(size);
   64 }
   65 
   66 static inline u32 *
   67 encode_fh(u32 *p, struct svc_fh *fhp)
   68 {
   69         int size = fhp->fh_handle.fh_size;
   70         *p++ = htonl(size);
   71         if (size) p[XDR_QUADLEN(size)-1]=0;
   72         memcpy(p, &fhp->fh_handle.fh_base, size);
   73         return p + XDR_QUADLEN(size);
   74 }
   75 
   76 /*
   77  * Decode a file name and make sure that the path contains
   78  * no slashes or null bytes.
   79  */
   80 static inline u32 *
   81 decode_filename(u32 *p, char **namp, int *lenp)
   82 {
   83         char            *name;
   84         int             i;
   85 
   86         if ((p = xdr_decode_string_inplace(p, namp, lenp, NFS3_MAXNAMLEN)) != NULL) {
   87                 for (i = 0, name = *namp; i < *lenp; i++, name++) {
   88                         if (*name == '\0' || *name == '/')
   89                                 return NULL;
   90                 }
   91         }
   92 
   93         return p;
   94 }
   95 
   96 static inline u32 *
   97 decode_pathname(u32 *p, char **namp, int *lenp)
   98 {
   99         char            *name;
  100         int             i;
  101 
  102         if ((p = xdr_decode_string(p, namp, lenp, NFS3_MAXPATHLEN)) != NULL) {
  103                 for (i = 0, name = *namp; i < *lenp; i++, name++) {
  104                         if (*name == '\0')
  105                                 return NULL;
  106                 }
  107         }
  108 
  109         return p;
  110 }
  111 
  112 static inline u32 *
  113 decode_sattr3(u32 *p, struct iattr *iap)
  114 {
  115         u32     tmp;
  116 
  117         iap->ia_valid = 0;
  118 
  119         if (*p++) {
  120                 iap->ia_valid |= ATTR_MODE;
  121                 iap->ia_mode = ntohl(*p++);
  122         }
  123         if (*p++) {
  124                 iap->ia_valid |= ATTR_UID;
  125                 iap->ia_uid = ntohl(*p++);
  126         }
  127         if (*p++) {
  128                 iap->ia_valid |= ATTR_GID;
  129                 iap->ia_gid = ntohl(*p++);
  130         }
  131         if (*p++) {
  132                 u64     newsize;
  133 
  134                 iap->ia_valid |= ATTR_SIZE;
  135                 p = xdr_decode_hyper(p, &newsize);
  136                 if (newsize <= NFS_OFFSET_MAX)
  137                         iap->ia_size = newsize;
  138                 else
  139                         iap->ia_size = NFS_OFFSET_MAX;
  140         }
  141         if ((tmp = ntohl(*p++)) == 1) { /* set to server time */
  142                 iap->ia_valid |= ATTR_ATIME;
  143         } else if (tmp == 2) {          /* set to client time */
  144                 iap->ia_valid |= ATTR_ATIME | ATTR_ATIME_SET;
  145                 iap->ia_atime = ntohl(*p++), p++;
  146         }
  147         if ((tmp = ntohl(*p++)) == 1) { /* set to server time */
  148                 iap->ia_valid |= ATTR_MTIME;
  149         } else if (tmp == 2) {          /* set to client time */
  150                 iap->ia_valid |= ATTR_MTIME | ATTR_MTIME_SET;
  151                 iap->ia_mtime = ntohl(*p++), p++;
  152         }
  153         return p;
  154 }
  155 
  156 static inline u32 *
  157 encode_fattr3(struct svc_rqst *rqstp, u32 *p, struct svc_fh *fhp)
  158 {
  159         struct inode    *inode = fhp->fh_dentry->d_inode;
  160 
  161         *p++ = htonl(nfs3_ftypes[(inode->i_mode & S_IFMT) >> 12]);
  162         *p++ = htonl((u32) inode->i_mode);
  163         *p++ = htonl((u32) inode->i_nlink);
  164         *p++ = htonl((u32) nfsd_ruid(rqstp, inode->i_uid));
  165         *p++ = htonl((u32) nfsd_rgid(rqstp, inode->i_gid));
  166         if (S_ISLNK(inode->i_mode) && inode->i_size > NFS3_MAXPATHLEN) {
  167                 p = xdr_encode_hyper(p, (u64) NFS3_MAXPATHLEN);
  168         } else {
  169                 p = xdr_encode_hyper(p, (u64) inode->i_size);
  170         }
  171         if (inode->i_blksize == 0 && inode->i_blocks == 0)
  172                 /* Minix file system(?) i_size is (hopefully) close enough */
  173                 p = xdr_encode_hyper(p, (u64)(inode->i_size +511)& ~511);
  174         else
  175                 p = xdr_encode_hyper(p, ((u64)inode->i_blocks) << 9);
  176         *p++ = htonl((u32) MAJOR(inode->i_rdev));
  177         *p++ = htonl((u32) MINOR(inode->i_rdev));
  178         if (rqstp->rq_reffh->fh_version == 1
  179             && rqstp->rq_reffh->fh_fsid_type == 1
  180             && (fhp->fh_export->ex_flags & NFSEXP_FSID))
  181                 p = xdr_encode_hyper(p, (u64) fhp->fh_export->ex_fsid);
  182         else
  183                 p = xdr_encode_hyper(p, (u64) inode->i_dev);
  184         p = xdr_encode_hyper(p, (u64) inode->i_ino);
  185         p = encode_time3(p, inode->i_atime);
  186         p = encode_time3(p, lease_get_mtime(inode));
  187         p = encode_time3(p, inode->i_ctime);
  188 
  189         return p;
  190 }
  191 
  192 static inline u32 *
  193 encode_saved_post_attr(struct svc_rqst *rqstp, u32 *p, struct svc_fh *fhp)
  194 {
  195         struct inode    *inode = fhp->fh_dentry->d_inode;
  196 
  197         /* Attributes to follow */
  198         *p++ = xdr_one;
  199 
  200         *p++ = htonl(nfs3_ftypes[(fhp->fh_post_mode & S_IFMT) >> 12]);
  201         *p++ = htonl((u32) fhp->fh_post_mode);
  202         *p++ = htonl((u32) fhp->fh_post_nlink);
  203         *p++ = htonl((u32) nfsd_ruid(rqstp, fhp->fh_post_uid));
  204         *p++ = htonl((u32) nfsd_rgid(rqstp, fhp->fh_post_gid));
  205         if (S_ISLNK(fhp->fh_post_mode) && fhp->fh_post_size > NFS3_MAXPATHLEN) {
  206                 p = xdr_encode_hyper(p, (u64) NFS3_MAXPATHLEN);
  207         } else {
  208                 p = xdr_encode_hyper(p, (u64) fhp->fh_post_size);
  209         }
  210         p = xdr_encode_hyper(p, ((u64)fhp->fh_post_blocks) << 9);
  211         *p++ = htonl((u32) MAJOR(fhp->fh_post_rdev));
  212         *p++ = htonl((u32) MINOR(fhp->fh_post_rdev));
  213         if (rqstp->rq_reffh->fh_version == 1
  214             && rqstp->rq_reffh->fh_fsid_type == 1
  215             && (fhp->fh_export->ex_flags & NFSEXP_FSID))
  216                 p = xdr_encode_hyper(p, (u64) fhp->fh_export->ex_fsid);
  217         else
  218                 p = xdr_encode_hyper(p, (u64) inode->i_dev);
  219         p = xdr_encode_hyper(p, (u64) inode->i_ino);
  220         p = encode_time3(p, fhp->fh_post_atime);
  221         p = encode_time3(p, fhp->fh_post_mtime);
  222         p = encode_time3(p, fhp->fh_post_ctime);
  223 
  224         return p;
  225 }
  226 
  227 /*
  228  * Encode post-operation attributes.
  229  * The inode may be NULL if the call failed because of a stale file
  230  * handle. In this case, no attributes are returned.
  231  */
  232 static u32 *
  233 encode_post_op_attr(struct svc_rqst *rqstp, u32 *p, struct svc_fh *fhp)
  234 {
  235         struct dentry *dentry = fhp->fh_dentry;
  236         if (dentry && dentry->d_inode != NULL) {
  237                 *p++ = xdr_one;         /* attributes follow */
  238                 return encode_fattr3(rqstp, p, fhp);
  239         }
  240         *p++ = xdr_zero;
  241         return p;
  242 }
  243 
  244 /*
  245  * Enocde weak cache consistency data
  246  */
  247 static u32 *
  248 encode_wcc_data(struct svc_rqst *rqstp, u32 *p, struct svc_fh *fhp)
  249 {
  250         struct dentry   *dentry = fhp->fh_dentry;
  251 
  252         if (dentry && dentry->d_inode && fhp->fh_post_saved) {
  253                 if (fhp->fh_pre_saved) {
  254                         *p++ = xdr_one;
  255                         p = xdr_encode_hyper(p, (u64) fhp->fh_pre_size);
  256                         p = encode_time3(p, fhp->fh_pre_mtime);
  257                         p = encode_time3(p, fhp->fh_pre_ctime);
  258                 } else {
  259                         *p++ = xdr_zero;
  260                 }
  261                 return encode_saved_post_attr(rqstp, p, fhp);
  262         }
  263         /* no pre- or post-attrs */
  264         *p++ = xdr_zero;
  265         return encode_post_op_attr(rqstp, p, fhp);
  266 }
  267 
  268 /*
  269  * Check buffer bounds after decoding arguments
  270  */
  271 static inline int
  272 xdr_argsize_check(struct svc_rqst *rqstp, u32 *p)
  273 {
  274         struct svc_buf  *buf = &rqstp->rq_argbuf;
  275 
  276         return p - buf->base <= buf->buflen;
  277 }
  278 
  279 static inline int
  280 xdr_ressize_check(struct svc_rqst *rqstp, u32 *p)
  281 {
  282         struct svc_buf  *buf = &rqstp->rq_resbuf;
  283 
  284         buf->len = p - buf->base;
  285         dprintk("nfsd: ressize_check p %p base %p len %d\n",
  286                         p, buf->base, buf->buflen);
  287         return (buf->len <= buf->buflen);
  288 }
  289 
  290 /*
  291  * XDR decode functions
  292  */
  293 int
  294 nfs3svc_decode_fhandle(struct svc_rqst *rqstp, u32 *p, struct svc_fh *fhp)
  295 {
  296         if (!(p = decode_fh(p, fhp)))
  297                 return 0;
  298         return xdr_argsize_check(rqstp, p);
  299 }
  300 
  301 int
  302 nfs3svc_decode_sattrargs(struct svc_rqst *rqstp, u32 *p,
  303                                         struct nfsd3_sattrargs *args)
  304 {
  305         if (!(p = decode_fh(p, &args->fh))
  306          || !(p = decode_sattr3(p, &args->attrs)))
  307                 return 0;
  308 
  309         if ((args->check_guard = ntohl(*p++)) != 0)
  310                 p = decode_time3(p, &args->guardtime);
  311 
  312         return xdr_argsize_check(rqstp, p);
  313 }
  314 
  315 int
  316 nfs3svc_decode_diropargs(struct svc_rqst *rqstp, u32 *p,
  317                                         struct nfsd3_diropargs *args)
  318 {
  319         if (!(p = decode_fh(p, &args->fh))
  320          || !(p = decode_filename(p, &args->name, &args->len)))
  321                 return 0;
  322 
  323         return xdr_argsize_check(rqstp, p);
  324 }
  325 
  326 int
  327 nfs3svc_decode_accessargs(struct svc_rqst *rqstp, u32 *p,
  328                                         struct nfsd3_accessargs *args)
  329 {
  330         if (!(p = decode_fh(p, &args->fh)))
  331                 return 0;
  332         args->access = ntohl(*p++);
  333 
  334         return xdr_argsize_check(rqstp, p);
  335 }
  336 
  337 int
  338 nfs3svc_decode_readargs(struct svc_rqst *rqstp, u32 *p,
  339                                         struct nfsd3_readargs *args)
  340 {
  341         if (!(p = decode_fh(p, &args->fh))
  342          || !(p = xdr_decode_hyper(p, &args->offset)))
  343                 return 0;
  344 
  345         args->count = ntohl(*p++);
  346         return xdr_argsize_check(rqstp, p);
  347 }
  348 
  349 int
  350 nfs3svc_decode_writeargs(struct svc_rqst *rqstp, u32 *p,
  351                                         struct nfsd3_writeargs *args)
  352 {
  353         if (!(p = decode_fh(p, &args->fh))
  354          || !(p = xdr_decode_hyper(p, &args->offset)))
  355                 return 0;
  356 
  357         args->count = ntohl(*p++);
  358         args->stable = ntohl(*p++);
  359         args->len = ntohl(*p++);
  360         args->data = (char *) p;
  361         p += XDR_QUADLEN(args->len);
  362 
  363         return xdr_argsize_check(rqstp, p);
  364 }
  365 
  366 int
  367 nfs3svc_decode_createargs(struct svc_rqst *rqstp, u32 *p,
  368                                         struct nfsd3_createargs *args)
  369 {
  370         if (!(p = decode_fh(p, &args->fh))
  371          || !(p = decode_filename(p, &args->name, &args->len)))
  372                 return 0;
  373 
  374         switch (args->createmode = ntohl(*p++)) {
  375         case NFS3_CREATE_UNCHECKED:
  376         case NFS3_CREATE_GUARDED:
  377                 if (!(p = decode_sattr3(p, &args->attrs)))
  378                         return 0;
  379                 break;
  380         case NFS3_CREATE_EXCLUSIVE:
  381                 args->verf = p;
  382                 p += 2;
  383                 break;
  384         default:
  385                 return 0;
  386         }
  387 
  388         return xdr_argsize_check(rqstp, p);
  389 }
  390 int
  391 nfs3svc_decode_mkdirargs(struct svc_rqst *rqstp, u32 *p,
  392                                         struct nfsd3_createargs *args)
  393 {
  394         if (!(p = decode_fh(p, &args->fh))
  395          || !(p = decode_filename(p, &args->name, &args->len))
  396          || !(p = decode_sattr3(p, &args->attrs)))
  397                 return 0;
  398 
  399         return xdr_argsize_check(rqstp, p);
  400 }
  401 
  402 int
  403 nfs3svc_decode_symlinkargs(struct svc_rqst *rqstp, u32 *p,
  404                                         struct nfsd3_symlinkargs *args)
  405 {
  406         if (!(p = decode_fh(p, &args->ffh))
  407          || !(p = decode_filename(p, &args->fname, &args->flen))
  408          || !(p = decode_sattr3(p, &args->attrs))
  409          || !(p = decode_pathname(p, &args->tname, &args->tlen)))
  410                 return 0;
  411 
  412         return xdr_argsize_check(rqstp, p);
  413 }
  414 
  415 int
  416 nfs3svc_decode_mknodargs(struct svc_rqst *rqstp, u32 *p,
  417                                         struct nfsd3_mknodargs *args)
  418 {
  419         if (!(p = decode_fh(p, &args->fh))
  420          || !(p = decode_filename(p, &args->name, &args->len)))
  421                 return 0;
  422 
  423         args->ftype = ntohl(*p++);
  424 
  425         if (args->ftype == NF3BLK  || args->ftype == NF3CHR
  426          || args->ftype == NF3SOCK || args->ftype == NF3FIFO) {
  427                 if (!(p = decode_sattr3(p, &args->attrs)))
  428                         return 0;
  429         }
  430 
  431         if (args->ftype == NF3BLK || args->ftype == NF3CHR) {
  432                 args->major = ntohl(*p++);
  433                 args->minor = ntohl(*p++);
  434         }
  435 
  436         return xdr_argsize_check(rqstp, p);
  437 }
  438 
  439 int
  440 nfs3svc_decode_renameargs(struct svc_rqst *rqstp, u32 *p,
  441                                         struct nfsd3_renameargs *args)
  442 {
  443         if (!(p = decode_fh(p, &args->ffh))
  444          || !(p = decode_filename(p, &args->fname, &args->flen))
  445          || !(p = decode_fh(p, &args->tfh))
  446          || !(p = decode_filename(p, &args->tname, &args->tlen)))
  447                 return 0;
  448 
  449         return xdr_argsize_check(rqstp, p);
  450 }
  451 
  452 int
  453 nfs3svc_decode_linkargs(struct svc_rqst *rqstp, u32 *p,
  454                                         struct nfsd3_linkargs *args)
  455 {
  456         if (!(p = decode_fh(p, &args->ffh))
  457          || !(p = decode_fh(p, &args->tfh))
  458          || !(p = decode_filename(p, &args->tname, &args->tlen)))
  459                 return 0;
  460 
  461         return xdr_argsize_check(rqstp, p);
  462 }
  463 
  464 int
  465 nfs3svc_decode_readdirargs(struct svc_rqst *rqstp, u32 *p,
  466                                         struct nfsd3_readdirargs *args)
  467 {
  468         if (!(p = decode_fh(p, &args->fh)))
  469                 return 0;
  470         p = xdr_decode_hyper(p, &args->cookie);
  471         args->verf   = p; p += 2;
  472         args->dircount = ~0;
  473         args->count  = ntohl(*p++);
  474 
  475         return xdr_argsize_check(rqstp, p);
  476 }
  477 
  478 int
  479 nfs3svc_decode_readdirplusargs(struct svc_rqst *rqstp, u32 *p,
  480                                         struct nfsd3_readdirargs *args)
  481 {
  482         if (!(p = decode_fh(p, &args->fh)))
  483                 return 0;
  484         p = xdr_decode_hyper(p, &args->cookie);
  485         args->verf     = p; p += 2;
  486         args->dircount = ntohl(*p++);
  487         args->count    = ntohl(*p++);
  488 
  489         return xdr_argsize_check(rqstp, p);
  490 }
  491 
  492 int
  493 nfs3svc_decode_commitargs(struct svc_rqst *rqstp, u32 *p,
  494                                         struct nfsd3_commitargs *args)
  495 {
  496         if (!(p = decode_fh(p, &args->fh)))
  497                 return 0;
  498         p = xdr_decode_hyper(p, &args->offset);
  499         args->count = ntohl(*p++);
  500 
  501         return xdr_argsize_check(rqstp, p);
  502 }
  503 
  504 /*
  505  * XDR encode functions
  506  */
  507 /*
  508  * There must be an encoding function for void results so svc_process
  509  * will work properly.
  510  */
  511 int
  512 nfs3svc_encode_voidres(struct svc_rqst *rqstp, u32 *p, void *dummy)
  513 {
  514         return xdr_ressize_check(rqstp, p);
  515 }
  516 
  517 /* GETATTR */
  518 int
  519 nfs3svc_encode_attrstat(struct svc_rqst *rqstp, u32 *p,
  520                                         struct nfsd3_attrstat *resp)
  521 {
  522         if (resp->status == 0)
  523                 p = encode_fattr3(rqstp, p, &resp->fh);
  524         return xdr_ressize_check(rqstp, p);
  525 }
  526 
  527 /* SETATTR, REMOVE, RMDIR */
  528 int
  529 nfs3svc_encode_wccstat(struct svc_rqst *rqstp, u32 *p,
  530                                         struct nfsd3_attrstat *resp)
  531 {
  532         p = encode_wcc_data(rqstp, p, &resp->fh);
  533         return xdr_ressize_check(rqstp, p);
  534 }
  535 
  536 /* LOOKUP */
  537 int
  538 nfs3svc_encode_diropres(struct svc_rqst *rqstp, u32 *p,
  539                                         struct nfsd3_diropres *resp)
  540 {
  541         if (resp->status == 0) {
  542                 p = encode_fh(p, &resp->fh);
  543                 p = encode_post_op_attr(rqstp, p, &resp->fh);
  544         }
  545         p = encode_post_op_attr(rqstp, p, &resp->dirfh);
  546         return xdr_ressize_check(rqstp, p);
  547 }
  548 
  549 /* ACCESS */
  550 int
  551 nfs3svc_encode_accessres(struct svc_rqst *rqstp, u32 *p,
  552                                         struct nfsd3_accessres *resp)
  553 {
  554         p = encode_post_op_attr(rqstp, p, &resp->fh);
  555         if (resp->status == 0)
  556                 *p++ = htonl(resp->access);
  557         return xdr_ressize_check(rqstp, p);
  558 }
  559 
  560 /* READLINK */
  561 int
  562 nfs3svc_encode_readlinkres(struct svc_rqst *rqstp, u32 *p,
  563                                         struct nfsd3_readlinkres *resp)
  564 {
  565         p = encode_post_op_attr(rqstp, p, &resp->fh);
  566         if (resp->status == 0) {
  567                 *p++ = htonl(resp->len);
  568                 p += XDR_QUADLEN(resp->len);
  569         }
  570         return xdr_ressize_check(rqstp, p);
  571 }
  572 
  573 /* READ */
  574 int
  575 nfs3svc_encode_readres(struct svc_rqst *rqstp, u32 *p,
  576                                         struct nfsd3_readres *resp)
  577 {
  578         p = encode_post_op_attr(rqstp, p, &resp->fh);
  579         if (resp->status == 0) {
  580                 *p++ = htonl(resp->count);
  581                 *p++ = htonl(resp->eof);
  582                 *p++ = htonl(resp->count);      /* xdr opaque count */
  583                 p += XDR_QUADLEN(resp->count);
  584         }
  585         return xdr_ressize_check(rqstp, p);
  586 }
  587 
  588 /* WRITE */
  589 int
  590 nfs3svc_encode_writeres(struct svc_rqst *rqstp, u32 *p,
  591                                         struct nfsd3_writeres *resp)
  592 {
  593         p = encode_wcc_data(rqstp, p, &resp->fh);
  594         if (resp->status == 0) {
  595                 *p++ = htonl(resp->count);
  596                 *p++ = htonl(resp->committed);
  597                 *p++ = htonl(nfssvc_boot.tv_sec);
  598                 *p++ = htonl(nfssvc_boot.tv_usec);
  599         }
  600         return xdr_ressize_check(rqstp, p);
  601 }
  602 
  603 /* CREATE, MKDIR, SYMLINK, MKNOD */
  604 int
  605 nfs3svc_encode_createres(struct svc_rqst *rqstp, u32 *p,
  606                                         struct nfsd3_diropres *resp)
  607 {
  608         if (resp->status == 0) {
  609                 *p++ = xdr_one;
  610                 p = encode_fh(p, &resp->fh);
  611                 p = encode_post_op_attr(rqstp, p, &resp->fh);
  612         }
  613         p = encode_wcc_data(rqstp, p, &resp->dirfh);
  614         return xdr_ressize_check(rqstp, p);
  615 }
  616 
  617 /* RENAME */
  618 int
  619 nfs3svc_encode_renameres(struct svc_rqst *rqstp, u32 *p,
  620                                         struct nfsd3_renameres *resp)
  621 {
  622         p = encode_wcc_data(rqstp, p, &resp->ffh);
  623         p = encode_wcc_data(rqstp, p, &resp->tfh);
  624         return xdr_ressize_check(rqstp, p);
  625 }
  626 
  627 /* LINK */
  628 int
  629 nfs3svc_encode_linkres(struct svc_rqst *rqstp, u32 *p,
  630                                         struct nfsd3_linkres *resp)
  631 {
  632         p = encode_post_op_attr(rqstp, p, &resp->fh);
  633         p = encode_wcc_data(rqstp, p, &resp->tfh);
  634         return xdr_ressize_check(rqstp, p);
  635 }
  636 
  637 /* READDIR */
  638 int
  639 nfs3svc_encode_readdirres(struct svc_rqst *rqstp, u32 *p,
  640                                         struct nfsd3_readdirres *resp)
  641 {
  642         p = encode_post_op_attr(rqstp, p, &resp->fh);
  643         if (resp->status == 0) {
  644                 /* stupid readdir cookie */
  645                 memcpy(p, resp->verf, 8); p += 2;
  646                 p += XDR_QUADLEN(resp->count);
  647         }
  648 
  649         return xdr_ressize_check(rqstp, p);
  650 }
  651 
  652 /*
  653  * Encode a directory entry. This one works for both normal readdir
  654  * and readdirplus.
  655  * The normal readdir reply requires 2 (fileid) + 1 (stringlen)
  656  * + string + 2 (cookie) + 1 (next) words, i.e. 6 + strlen.
  657  * 
  658  * The readdirplus baggage is 1+21 words for post_op_attr, plus the
  659  * file handle.
  660  */
  661 
  662 #define NFS3_ENTRY_BAGGAGE      (2 + 1 + 2 + 1)
  663 #define NFS3_ENTRYPLUS_BAGGAGE  (1 + 21 + 1 + (NFS3_FHSIZE >> 2))
  664 static int
  665 encode_entry(struct readdir_cd *cd, const char *name,
  666              int namlen, off_t offset, ino_t ino, unsigned int d_type, int plus)
  667 {
  668         u32             *p = cd->buffer;
  669         int             buflen, slen, elen;
  670 
  671         if (cd->offset)
  672                 xdr_encode_hyper(cd->offset, (u64) offset);
  673 
  674         /* nfsd_readdir calls us with name == 0 when it wants us to
  675          * set the last offset entry. */
  676         if (name == 0)
  677                 return 0;
  678 
  679         /*
  680         dprintk("encode_entry(%.*s @%ld%s)\n",
  681                 namlen, name, (long) offset, plus? " plus" : "");
  682          */
  683 
  684         /* truncate filename if too long */
  685         if (namlen > NFS3_MAXNAMLEN)
  686                 namlen = NFS3_MAXNAMLEN;
  687 
  688         slen = XDR_QUADLEN(namlen);
  689         elen = slen + NFS3_ENTRY_BAGGAGE
  690                 + (plus? NFS3_ENTRYPLUS_BAGGAGE : 0);
  691         if ((buflen = cd->buflen - elen) < 0) {
  692                 cd->eob = 1;
  693                 return -EINVAL;
  694         }
  695         *p++ = xdr_one;                          /* mark entry present */
  696         p    = xdr_encode_hyper(p, ino);         /* file id */
  697         p    = xdr_encode_array(p, name, namlen);/* name length & name */
  698 
  699         cd->offset = p;                 /* remember pointer */
  700         p = xdr_encode_hyper(p, NFS_OFFSET_MAX);        /* offset of next entry */
  701 
  702         /* throw in readdirplus baggage */
  703         if (plus) {
  704                 struct svc_fh   fh;
  705                 struct svc_export       *exp;
  706                 struct dentry           *dparent, *dchild;
  707 
  708                 dparent = cd->dirfh->fh_dentry;
  709                 exp  = cd->dirfh->fh_export;
  710 
  711                 fh_init(&fh, NFS3_FHSIZE);
  712                 if (isdotent(name, namlen)) {
  713                         dchild = dparent;
  714                         if (namlen == 2)
  715                                 dchild = dchild->d_parent;
  716                         dchild = dget(dchild);
  717                 } else
  718                         dchild = lookup_one_len(name, dparent,namlen);
  719                 if (IS_ERR(dchild))
  720                         goto noexec;
  721                 if (fh_compose(&fh, exp, dchild, cd->dirfh) != 0 || !dchild->d_inode)
  722                         goto noexec;
  723                 p = encode_post_op_attr(cd->rqstp, p, &fh);
  724                 *p++ = xdr_one; /* yes, a file handle follows */
  725                 p = encode_fh(p, &fh);
  726                 fh_put(&fh);
  727         }
  728 
  729 out:
  730         cd->buflen = buflen;
  731         cd->buffer = p;
  732         return 0;
  733 
  734 noexec:
  735         *p++ = 0;
  736         *p++ = 0;
  737         goto out;
  738 }
  739 
  740 int
  741 nfs3svc_encode_entry(struct readdir_cd *cd, const char *name,
  742                      int namlen, loff_t offset, ino_t ino, unsigned int d_type)
  743 {
  744         return encode_entry(cd, name, namlen, offset, ino, d_type, 0);
  745 }
  746 
  747 int
  748 nfs3svc_encode_entry_plus(struct readdir_cd *cd, const char *name,
  749                           int namlen, loff_t offset, ino_t ino, unsigned int d_type)
  750 {
  751         return encode_entry(cd, name, namlen, offset, ino, d_type, 1);
  752 }
  753 
  754 /* FSSTAT */
  755 int
  756 nfs3svc_encode_fsstatres(struct svc_rqst *rqstp, u32 *p,
  757                                         struct nfsd3_fsstatres *resp)
  758 {
  759         struct statfs   *s = &resp->stats;
  760         u64             bs = s->f_bsize;
  761 
  762         *p++ = xdr_zero;        /* no post_op_attr */
  763 
  764         if (resp->status == 0) {
  765                 p = xdr_encode_hyper(p, bs * s->f_blocks);      /* total bytes */
  766                 p = xdr_encode_hyper(p, bs * s->f_bfree);       /* free bytes */
  767                 p = xdr_encode_hyper(p, bs * s->f_bavail);      /* user available bytes */
  768                 p = xdr_encode_hyper(p, s->f_files);    /* total inodes */
  769                 p = xdr_encode_hyper(p, s->f_ffree);    /* free inodes */
  770                 p = xdr_encode_hyper(p, s->f_ffree);    /* user available inodes */
  771                 *p++ = htonl(resp->invarsec);   /* mean unchanged time */
  772         }
  773         return xdr_ressize_check(rqstp, p);
  774 }
  775 
  776 /* FSINFO */
  777 int
  778 nfs3svc_encode_fsinfores(struct svc_rqst *rqstp, u32 *p,
  779                                         struct nfsd3_fsinfores *resp)
  780 {
  781         *p++ = xdr_zero;        /* no post_op_attr */
  782 
  783         if (resp->status == 0) {
  784                 *p++ = htonl(resp->f_rtmax);
  785                 *p++ = htonl(resp->f_rtpref);
  786                 *p++ = htonl(resp->f_rtmult);
  787                 *p++ = htonl(resp->f_wtmax);
  788                 *p++ = htonl(resp->f_wtpref);
  789                 *p++ = htonl(resp->f_wtmult);
  790                 *p++ = htonl(resp->f_dtpref);
  791                 p = xdr_encode_hyper(p, resp->f_maxfilesize);
  792                 *p++ = xdr_one;
  793                 *p++ = xdr_zero;
  794                 *p++ = htonl(resp->f_properties);
  795         }
  796 
  797         return xdr_ressize_check(rqstp, p);
  798 }
  799 
  800 /* PATHCONF */
  801 int
  802 nfs3svc_encode_pathconfres(struct svc_rqst *rqstp, u32 *p,
  803                                         struct nfsd3_pathconfres *resp)
  804 {
  805         *p++ = xdr_zero;        /* no post_op_attr */
  806 
  807         if (resp->status == 0) {
  808                 *p++ = htonl(resp->p_link_max);
  809                 *p++ = htonl(resp->p_name_max);
  810                 *p++ = htonl(resp->p_no_trunc);
  811                 *p++ = htonl(resp->p_chown_restricted);
  812                 *p++ = htonl(resp->p_case_insensitive);
  813                 *p++ = htonl(resp->p_case_preserving);
  814         }
  815 
  816         return xdr_ressize_check(rqstp, p);
  817 }
  818 
  819 /* COMMIT */
  820 int
  821 nfs3svc_encode_commitres(struct svc_rqst *rqstp, u32 *p,
  822                                         struct nfsd3_commitres *resp)
  823 {
  824         p = encode_wcc_data(rqstp, p, &resp->fh);
  825         /* Write verifier */
  826         if (resp->status == 0) {
  827                 *p++ = htonl(nfssvc_boot.tv_sec);
  828                 *p++ = htonl(nfssvc_boot.tv_usec);
  829         }
  830         return xdr_ressize_check(rqstp, p);
  831 }
  832 
  833 /*
  834  * XDR release functions
  835  */
  836 int
  837 nfs3svc_release_fhandle(struct svc_rqst *rqstp, u32 *p,
  838                                         struct nfsd3_attrstat *resp)
  839 {
  840         fh_put(&resp->fh);
  841         return 1;
  842 }
  843 
  844 int
  845 nfs3svc_release_fhandle2(struct svc_rqst *rqstp, u32 *p,
  846                                         struct nfsd3_fhandle_pair *resp)
  847 {
  848         fh_put(&resp->fh1);
  849         fh_put(&resp->fh2);
  850         return 1;
  851 }

Cache object: 7c14ad4501b69655fc8763f338ee04b6


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]


This page is part of the FreeBSD/Linux Linux Kernel Cross-Reference, and was automatically generated using a modified version of the LXR engine.