root/fs/nfsd/nfs3proc.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. nfsd3_proc_null
  2. nfsd3_proc_getattr
  3. nfsd3_proc_setattr
  4. nfsd3_proc_lookup
  5. nfsd3_proc_access
  6. nfsd3_proc_readlink
  7. nfsd3_proc_read
  8. nfsd3_proc_write
  9. nfsd3_proc_create
  10. nfsd3_proc_mkdir
  11. nfsd3_proc_symlink
  12. nfsd3_proc_mknod
  13. nfsd3_proc_remove
  14. nfsd3_proc_rmdir
  15. nfsd3_proc_rename
  16. nfsd3_proc_link
  17. nfsd3_proc_readdir
  18. nfsd3_proc_readdirplus
  19. nfsd3_proc_fsstat
  20. nfsd3_proc_fsinfo
  21. nfsd3_proc_pathconf
  22. nfsd3_proc_commit

   1 // SPDX-License-Identifier: GPL-2.0
   2 /*
   3  * Process version 3 NFS requests.
   4  *
   5  * Copyright (C) 1996, 1997, 1998 Olaf Kirch <okir@monad.swb.de>
   6  */
   7 
   8 #include <linux/fs.h>
   9 #include <linux/ext2_fs.h>
  10 #include <linux/magic.h>
  11 
  12 #include "cache.h"
  13 #include "xdr3.h"
  14 #include "vfs.h"
  15 
  16 #define NFSDDBG_FACILITY                NFSDDBG_PROC
  17 
  18 #define RETURN_STATUS(st)       { resp->status = (st); return (st); }
  19 
  20 static int      nfs3_ftypes[] = {
  21         0,                      /* NF3NON */
  22         S_IFREG,                /* NF3REG */
  23         S_IFDIR,                /* NF3DIR */
  24         S_IFBLK,                /* NF3BLK */
  25         S_IFCHR,                /* NF3CHR */
  26         S_IFLNK,                /* NF3LNK */
  27         S_IFSOCK,               /* NF3SOCK */
  28         S_IFIFO,                /* NF3FIFO */
  29 };
  30 
  31 /*
  32  * NULL call.
  33  */
  34 static __be32
  35 nfsd3_proc_null(struct svc_rqst *rqstp)
  36 {
  37         return nfs_ok;
  38 }
  39 
  40 /*
  41  * Get a file's attributes
  42  */
  43 static __be32
  44 nfsd3_proc_getattr(struct svc_rqst *rqstp)
  45 {
  46         struct nfsd_fhandle *argp = rqstp->rq_argp;
  47         struct nfsd3_attrstat *resp = rqstp->rq_resp;
  48         __be32  nfserr;
  49 
  50         dprintk("nfsd: GETATTR(3)  %s\n",
  51                 SVCFH_fmt(&argp->fh));
  52 
  53         fh_copy(&resp->fh, &argp->fh);
  54         nfserr = fh_verify(rqstp, &resp->fh, 0,
  55                         NFSD_MAY_NOP | NFSD_MAY_BYPASS_GSS_ON_ROOT);
  56         if (nfserr)
  57                 RETURN_STATUS(nfserr);
  58 
  59         nfserr = fh_getattr(&resp->fh, &resp->stat);
  60 
  61         RETURN_STATUS(nfserr);
  62 }
  63 
  64 /*
  65  * Set a file's attributes
  66  */
  67 static __be32
  68 nfsd3_proc_setattr(struct svc_rqst *rqstp)
  69 {
  70         struct nfsd3_sattrargs *argp = rqstp->rq_argp;
  71         struct nfsd3_attrstat *resp = rqstp->rq_resp;
  72         __be32  nfserr;
  73 
  74         dprintk("nfsd: SETATTR(3)  %s\n",
  75                                 SVCFH_fmt(&argp->fh));
  76 
  77         fh_copy(&resp->fh, &argp->fh);
  78         nfserr = nfsd_setattr(rqstp, &resp->fh, &argp->attrs,
  79                               argp->check_guard, argp->guardtime);
  80         RETURN_STATUS(nfserr);
  81 }
  82 
  83 /*
  84  * Look up a path name component
  85  */
  86 static __be32
  87 nfsd3_proc_lookup(struct svc_rqst *rqstp)
  88 {
  89         struct nfsd3_diropargs *argp = rqstp->rq_argp;
  90         struct nfsd3_diropres  *resp = rqstp->rq_resp;
  91         __be32  nfserr;
  92 
  93         dprintk("nfsd: LOOKUP(3)   %s %.*s\n",
  94                                 SVCFH_fmt(&argp->fh),
  95                                 argp->len,
  96                                 argp->name);
  97 
  98         fh_copy(&resp->dirfh, &argp->fh);
  99         fh_init(&resp->fh, NFS3_FHSIZE);
 100 
 101         nfserr = nfsd_lookup(rqstp, &resp->dirfh,
 102                                     argp->name,
 103                                     argp->len,
 104                                     &resp->fh);
 105         RETURN_STATUS(nfserr);
 106 }
 107 
 108 /*
 109  * Check file access
 110  */
 111 static __be32
 112 nfsd3_proc_access(struct svc_rqst *rqstp)
 113 {
 114         struct nfsd3_accessargs *argp = rqstp->rq_argp;
 115         struct nfsd3_accessres *resp = rqstp->rq_resp;
 116         __be32  nfserr;
 117 
 118         dprintk("nfsd: ACCESS(3)   %s 0x%x\n",
 119                                 SVCFH_fmt(&argp->fh),
 120                                 argp->access);
 121 
 122         fh_copy(&resp->fh, &argp->fh);
 123         resp->access = argp->access;
 124         nfserr = nfsd_access(rqstp, &resp->fh, &resp->access, NULL);
 125         RETURN_STATUS(nfserr);
 126 }
 127 
 128 /*
 129  * Read a symlink.
 130  */
 131 static __be32
 132 nfsd3_proc_readlink(struct svc_rqst *rqstp)
 133 {
 134         struct nfsd3_readlinkargs *argp = rqstp->rq_argp;
 135         struct nfsd3_readlinkres *resp = rqstp->rq_resp;
 136         __be32 nfserr;
 137 
 138         dprintk("nfsd: READLINK(3) %s\n", SVCFH_fmt(&argp->fh));
 139 
 140         /* Read the symlink. */
 141         fh_copy(&resp->fh, &argp->fh);
 142         resp->len = NFS3_MAXPATHLEN;
 143         nfserr = nfsd_readlink(rqstp, &resp->fh, argp->buffer, &resp->len);
 144         RETURN_STATUS(nfserr);
 145 }
 146 
 147 /*
 148  * Read a portion of a file.
 149  */
 150 static __be32
 151 nfsd3_proc_read(struct svc_rqst *rqstp)
 152 {
 153         struct nfsd3_readargs *argp = rqstp->rq_argp;
 154         struct nfsd3_readres *resp = rqstp->rq_resp;
 155         __be32  nfserr;
 156         u32     max_blocksize = svc_max_payload(rqstp);
 157         unsigned long cnt = min(argp->count, max_blocksize);
 158 
 159         dprintk("nfsd: READ(3) %s %lu bytes at %Lu\n",
 160                                 SVCFH_fmt(&argp->fh),
 161                                 (unsigned long) argp->count,
 162                                 (unsigned long long) argp->offset);
 163 
 164         /* Obtain buffer pointer for payload.
 165          * 1 (status) + 22 (post_op_attr) + 1 (count) + 1 (eof)
 166          * + 1 (xdr opaque byte count) = 26
 167          */
 168         resp->count = cnt;
 169         svc_reserve_auth(rqstp, ((1 + NFS3_POST_OP_ATTR_WORDS + 3)<<2) + resp->count +4);
 170 
 171         fh_copy(&resp->fh, &argp->fh);
 172         nfserr = nfsd_read(rqstp, &resp->fh,
 173                                   argp->offset,
 174                                   rqstp->rq_vec, argp->vlen,
 175                                   &resp->count,
 176                                   &resp->eof);
 177         RETURN_STATUS(nfserr);
 178 }
 179 
 180 /*
 181  * Write data to a file
 182  */
 183 static __be32
 184 nfsd3_proc_write(struct svc_rqst *rqstp)
 185 {
 186         struct nfsd3_writeargs *argp = rqstp->rq_argp;
 187         struct nfsd3_writeres *resp = rqstp->rq_resp;
 188         __be32  nfserr;
 189         unsigned long cnt = argp->len;
 190         unsigned int nvecs;
 191 
 192         dprintk("nfsd: WRITE(3)    %s %d bytes at %Lu%s\n",
 193                                 SVCFH_fmt(&argp->fh),
 194                                 argp->len,
 195                                 (unsigned long long) argp->offset,
 196                                 argp->stable? " stable" : "");
 197 
 198         fh_copy(&resp->fh, &argp->fh);
 199         resp->committed = argp->stable;
 200         nvecs = svc_fill_write_vector(rqstp, rqstp->rq_arg.pages,
 201                                       &argp->first, cnt);
 202         if (!nvecs)
 203                 RETURN_STATUS(nfserr_io);
 204         nfserr = nfsd_write(rqstp, &resp->fh, argp->offset,
 205                             rqstp->rq_vec, nvecs, &cnt,
 206                             resp->committed);
 207         resp->count = cnt;
 208         RETURN_STATUS(nfserr);
 209 }
 210 
 211 /*
 212  * With NFSv3, CREATE processing is a lot easier than with NFSv2.
 213  * At least in theory; we'll see how it fares in practice when the
 214  * first reports about SunOS compatibility problems start to pour in...
 215  */
 216 static __be32
 217 nfsd3_proc_create(struct svc_rqst *rqstp)
 218 {
 219         struct nfsd3_createargs *argp = rqstp->rq_argp;
 220         struct nfsd3_diropres *resp = rqstp->rq_resp;
 221         svc_fh          *dirfhp, *newfhp = NULL;
 222         struct iattr    *attr;
 223         __be32          nfserr;
 224 
 225         dprintk("nfsd: CREATE(3)   %s %.*s\n",
 226                                 SVCFH_fmt(&argp->fh),
 227                                 argp->len,
 228                                 argp->name);
 229 
 230         dirfhp = fh_copy(&resp->dirfh, &argp->fh);
 231         newfhp = fh_init(&resp->fh, NFS3_FHSIZE);
 232         attr   = &argp->attrs;
 233 
 234         /* Unfudge the mode bits */
 235         attr->ia_mode &= ~S_IFMT;
 236         if (!(attr->ia_valid & ATTR_MODE)) { 
 237                 attr->ia_valid |= ATTR_MODE;
 238                 attr->ia_mode = S_IFREG;
 239         } else {
 240                 attr->ia_mode = (attr->ia_mode & ~S_IFMT) | S_IFREG;
 241         }
 242 
 243         /* Now create the file and set attributes */
 244         nfserr = do_nfsd_create(rqstp, dirfhp, argp->name, argp->len,
 245                                 attr, newfhp,
 246                                 argp->createmode, (u32 *)argp->verf, NULL, NULL);
 247 
 248         RETURN_STATUS(nfserr);
 249 }
 250 
 251 /*
 252  * Make directory. This operation is not idempotent.
 253  */
 254 static __be32
 255 nfsd3_proc_mkdir(struct svc_rqst *rqstp)
 256 {
 257         struct nfsd3_createargs *argp = rqstp->rq_argp;
 258         struct nfsd3_diropres *resp = rqstp->rq_resp;
 259         __be32  nfserr;
 260 
 261         dprintk("nfsd: MKDIR(3)    %s %.*s\n",
 262                                 SVCFH_fmt(&argp->fh),
 263                                 argp->len,
 264                                 argp->name);
 265 
 266         argp->attrs.ia_valid &= ~ATTR_SIZE;
 267         fh_copy(&resp->dirfh, &argp->fh);
 268         fh_init(&resp->fh, NFS3_FHSIZE);
 269         nfserr = nfsd_create(rqstp, &resp->dirfh, argp->name, argp->len,
 270                                     &argp->attrs, S_IFDIR, 0, &resp->fh);
 271         fh_unlock(&resp->dirfh);
 272         RETURN_STATUS(nfserr);
 273 }
 274 
 275 static __be32
 276 nfsd3_proc_symlink(struct svc_rqst *rqstp)
 277 {
 278         struct nfsd3_symlinkargs *argp = rqstp->rq_argp;
 279         struct nfsd3_diropres *resp = rqstp->rq_resp;
 280         __be32  nfserr;
 281 
 282         if (argp->tlen == 0)
 283                 RETURN_STATUS(nfserr_inval);
 284         if (argp->tlen > NFS3_MAXPATHLEN)
 285                 RETURN_STATUS(nfserr_nametoolong);
 286 
 287         argp->tname = svc_fill_symlink_pathname(rqstp, &argp->first,
 288                                                 page_address(rqstp->rq_arg.pages[0]),
 289                                                 argp->tlen);
 290         if (IS_ERR(argp->tname))
 291                 RETURN_STATUS(nfserrno(PTR_ERR(argp->tname)));
 292 
 293         dprintk("nfsd: SYMLINK(3)  %s %.*s -> %.*s\n",
 294                                 SVCFH_fmt(&argp->ffh),
 295                                 argp->flen, argp->fname,
 296                                 argp->tlen, argp->tname);
 297 
 298         fh_copy(&resp->dirfh, &argp->ffh);
 299         fh_init(&resp->fh, NFS3_FHSIZE);
 300         nfserr = nfsd_symlink(rqstp, &resp->dirfh, argp->fname, argp->flen,
 301                                                    argp->tname, &resp->fh);
 302         kfree(argp->tname);
 303         RETURN_STATUS(nfserr);
 304 }
 305 
 306 /*
 307  * Make socket/fifo/device.
 308  */
 309 static __be32
 310 nfsd3_proc_mknod(struct svc_rqst *rqstp)
 311 {
 312         struct nfsd3_mknodargs *argp = rqstp->rq_argp;
 313         struct nfsd3_diropres  *resp = rqstp->rq_resp;
 314         __be32  nfserr;
 315         int type;
 316         dev_t   rdev = 0;
 317 
 318         dprintk("nfsd: MKNOD(3)    %s %.*s\n",
 319                                 SVCFH_fmt(&argp->fh),
 320                                 argp->len,
 321                                 argp->name);
 322 
 323         fh_copy(&resp->dirfh, &argp->fh);
 324         fh_init(&resp->fh, NFS3_FHSIZE);
 325 
 326         if (argp->ftype == 0 || argp->ftype >= NF3BAD)
 327                 RETURN_STATUS(nfserr_inval);
 328         if (argp->ftype == NF3CHR || argp->ftype == NF3BLK) {
 329                 rdev = MKDEV(argp->major, argp->minor);
 330                 if (MAJOR(rdev) != argp->major ||
 331                     MINOR(rdev) != argp->minor)
 332                         RETURN_STATUS(nfserr_inval);
 333         } else
 334                 if (argp->ftype != NF3SOCK && argp->ftype != NF3FIFO)
 335                         RETURN_STATUS(nfserr_inval);
 336 
 337         type = nfs3_ftypes[argp->ftype];
 338         nfserr = nfsd_create(rqstp, &resp->dirfh, argp->name, argp->len,
 339                                     &argp->attrs, type, rdev, &resp->fh);
 340         fh_unlock(&resp->dirfh);
 341         RETURN_STATUS(nfserr);
 342 }
 343 
 344 /*
 345  * Remove file/fifo/socket etc.
 346  */
 347 static __be32
 348 nfsd3_proc_remove(struct svc_rqst *rqstp)
 349 {
 350         struct nfsd3_diropargs *argp = rqstp->rq_argp;
 351         struct nfsd3_attrstat *resp = rqstp->rq_resp;
 352         __be32  nfserr;
 353 
 354         dprintk("nfsd: REMOVE(3)   %s %.*s\n",
 355                                 SVCFH_fmt(&argp->fh),
 356                                 argp->len,
 357                                 argp->name);
 358 
 359         /* Unlink. -S_IFDIR means file must not be a directory */
 360         fh_copy(&resp->fh, &argp->fh);
 361         nfserr = nfsd_unlink(rqstp, &resp->fh, -S_IFDIR, argp->name, argp->len);
 362         fh_unlock(&resp->fh);
 363         RETURN_STATUS(nfserr);
 364 }
 365 
 366 /*
 367  * Remove a directory
 368  */
 369 static __be32
 370 nfsd3_proc_rmdir(struct svc_rqst *rqstp)
 371 {
 372         struct nfsd3_diropargs *argp = rqstp->rq_argp;
 373         struct nfsd3_attrstat *resp = rqstp->rq_resp;
 374         __be32  nfserr;
 375 
 376         dprintk("nfsd: RMDIR(3)    %s %.*s\n",
 377                                 SVCFH_fmt(&argp->fh),
 378                                 argp->len,
 379                                 argp->name);
 380 
 381         fh_copy(&resp->fh, &argp->fh);
 382         nfserr = nfsd_unlink(rqstp, &resp->fh, S_IFDIR, argp->name, argp->len);
 383         fh_unlock(&resp->fh);
 384         RETURN_STATUS(nfserr);
 385 }
 386 
 387 static __be32
 388 nfsd3_proc_rename(struct svc_rqst *rqstp)
 389 {
 390         struct nfsd3_renameargs *argp = rqstp->rq_argp;
 391         struct nfsd3_renameres *resp = rqstp->rq_resp;
 392         __be32  nfserr;
 393 
 394         dprintk("nfsd: RENAME(3)   %s %.*s ->\n",
 395                                 SVCFH_fmt(&argp->ffh),
 396                                 argp->flen,
 397                                 argp->fname);
 398         dprintk("nfsd: -> %s %.*s\n",
 399                                 SVCFH_fmt(&argp->tfh),
 400                                 argp->tlen,
 401                                 argp->tname);
 402 
 403         fh_copy(&resp->ffh, &argp->ffh);
 404         fh_copy(&resp->tfh, &argp->tfh);
 405         nfserr = nfsd_rename(rqstp, &resp->ffh, argp->fname, argp->flen,
 406                                     &resp->tfh, argp->tname, argp->tlen);
 407         RETURN_STATUS(nfserr);
 408 }
 409 
 410 static __be32
 411 nfsd3_proc_link(struct svc_rqst *rqstp)
 412 {
 413         struct nfsd3_linkargs *argp = rqstp->rq_argp;
 414         struct nfsd3_linkres  *resp = rqstp->rq_resp;
 415         __be32  nfserr;
 416 
 417         dprintk("nfsd: LINK(3)     %s ->\n",
 418                                 SVCFH_fmt(&argp->ffh));
 419         dprintk("nfsd:   -> %s %.*s\n",
 420                                 SVCFH_fmt(&argp->tfh),
 421                                 argp->tlen,
 422                                 argp->tname);
 423 
 424         fh_copy(&resp->fh,  &argp->ffh);
 425         fh_copy(&resp->tfh, &argp->tfh);
 426         nfserr = nfsd_link(rqstp, &resp->tfh, argp->tname, argp->tlen,
 427                                   &resp->fh);
 428         RETURN_STATUS(nfserr);
 429 }
 430 
 431 /*
 432  * Read a portion of a directory.
 433  */
 434 static __be32
 435 nfsd3_proc_readdir(struct svc_rqst *rqstp)
 436 {
 437         struct nfsd3_readdirargs *argp = rqstp->rq_argp;
 438         struct nfsd3_readdirres  *resp = rqstp->rq_resp;
 439         __be32          nfserr;
 440         int             count = 0;
 441         struct page     **p;
 442         caddr_t         page_addr = NULL;
 443 
 444         dprintk("nfsd: READDIR(3)  %s %d bytes at %d\n",
 445                                 SVCFH_fmt(&argp->fh),
 446                                 argp->count, (u32) argp->cookie);
 447 
 448         /* Make sure we've room for the NULL ptr & eof flag, and shrink to
 449          * client read size */
 450         count = (argp->count >> 2) - 2;
 451 
 452         /* Read directory and encode entries on the fly */
 453         fh_copy(&resp->fh, &argp->fh);
 454 
 455         resp->buflen = count;
 456         resp->common.err = nfs_ok;
 457         resp->buffer = argp->buffer;
 458         resp->rqstp = rqstp;
 459         nfserr = nfsd_readdir(rqstp, &resp->fh, (loff_t*) &argp->cookie, 
 460                                         &resp->common, nfs3svc_encode_entry);
 461         memcpy(resp->verf, argp->verf, 8);
 462         count = 0;
 463         for (p = rqstp->rq_respages + 1; p < rqstp->rq_next_page; p++) {
 464                 page_addr = page_address(*p);
 465 
 466                 if (((caddr_t)resp->buffer >= page_addr) &&
 467                     ((caddr_t)resp->buffer < page_addr + PAGE_SIZE)) {
 468                         count += (caddr_t)resp->buffer - page_addr;
 469                         break;
 470                 }
 471                 count += PAGE_SIZE;
 472         }
 473         resp->count = count >> 2;
 474         if (resp->offset) {
 475                 loff_t offset = argp->cookie;
 476 
 477                 if (unlikely(resp->offset1)) {
 478                         /* we ended up with offset on a page boundary */
 479                         *resp->offset = htonl(offset >> 32);
 480                         *resp->offset1 = htonl(offset & 0xffffffff);
 481                         resp->offset1 = NULL;
 482                 } else {
 483                         xdr_encode_hyper(resp->offset, offset);
 484                 }
 485                 resp->offset = NULL;
 486         }
 487 
 488         RETURN_STATUS(nfserr);
 489 }
 490 
 491 /*
 492  * Read a portion of a directory, including file handles and attrs.
 493  * For now, we choose to ignore the dircount parameter.
 494  */
 495 static __be32
 496 nfsd3_proc_readdirplus(struct svc_rqst *rqstp)
 497 {
 498         struct nfsd3_readdirargs *argp = rqstp->rq_argp;
 499         struct nfsd3_readdirres  *resp = rqstp->rq_resp;
 500         __be32  nfserr;
 501         int     count = 0;
 502         loff_t  offset;
 503         struct page **p;
 504         caddr_t page_addr = NULL;
 505 
 506         dprintk("nfsd: READDIR+(3) %s %d bytes at %d\n",
 507                                 SVCFH_fmt(&argp->fh),
 508                                 argp->count, (u32) argp->cookie);
 509 
 510         /* Convert byte count to number of words (i.e. >> 2),
 511          * and reserve room for the NULL ptr & eof flag (-2 words) */
 512         resp->count = (argp->count >> 2) - 2;
 513 
 514         /* Read directory and encode entries on the fly */
 515         fh_copy(&resp->fh, &argp->fh);
 516 
 517         resp->common.err = nfs_ok;
 518         resp->buffer = argp->buffer;
 519         resp->buflen = resp->count;
 520         resp->rqstp = rqstp;
 521         offset = argp->cookie;
 522 
 523         nfserr = fh_verify(rqstp, &resp->fh, S_IFDIR, NFSD_MAY_NOP);
 524         if (nfserr)
 525                 RETURN_STATUS(nfserr);
 526 
 527         if (resp->fh.fh_export->ex_flags & NFSEXP_NOREADDIRPLUS)
 528                 RETURN_STATUS(nfserr_notsupp);
 529 
 530         nfserr = nfsd_readdir(rqstp, &resp->fh,
 531                                      &offset,
 532                                      &resp->common,
 533                                      nfs3svc_encode_entry_plus);
 534         memcpy(resp->verf, argp->verf, 8);
 535         for (p = rqstp->rq_respages + 1; p < rqstp->rq_next_page; p++) {
 536                 page_addr = page_address(*p);
 537 
 538                 if (((caddr_t)resp->buffer >= page_addr) &&
 539                     ((caddr_t)resp->buffer < page_addr + PAGE_SIZE)) {
 540                         count += (caddr_t)resp->buffer - page_addr;
 541                         break;
 542                 }
 543                 count += PAGE_SIZE;
 544         }
 545         resp->count = count >> 2;
 546         if (resp->offset) {
 547                 if (unlikely(resp->offset1)) {
 548                         /* we ended up with offset on a page boundary */
 549                         *resp->offset = htonl(offset >> 32);
 550                         *resp->offset1 = htonl(offset & 0xffffffff);
 551                         resp->offset1 = NULL;
 552                 } else {
 553                         xdr_encode_hyper(resp->offset, offset);
 554                 }
 555                 resp->offset = NULL;
 556         }
 557 
 558         RETURN_STATUS(nfserr);
 559 }
 560 
 561 /*
 562  * Get file system stats
 563  */
 564 static __be32
 565 nfsd3_proc_fsstat(struct svc_rqst *rqstp)
 566 {
 567         struct nfsd_fhandle *argp = rqstp->rq_argp;
 568         struct nfsd3_fsstatres *resp = rqstp->rq_resp;
 569         __be32  nfserr;
 570 
 571         dprintk("nfsd: FSSTAT(3)   %s\n",
 572                                 SVCFH_fmt(&argp->fh));
 573 
 574         nfserr = nfsd_statfs(rqstp, &argp->fh, &resp->stats, 0);
 575         fh_put(&argp->fh);
 576         RETURN_STATUS(nfserr);
 577 }
 578 
 579 /*
 580  * Get file system info
 581  */
 582 static __be32
 583 nfsd3_proc_fsinfo(struct svc_rqst *rqstp)
 584 {
 585         struct nfsd_fhandle *argp = rqstp->rq_argp;
 586         struct nfsd3_fsinfores *resp = rqstp->rq_resp;
 587         __be32  nfserr;
 588         u32     max_blocksize = svc_max_payload(rqstp);
 589 
 590         dprintk("nfsd: FSINFO(3)   %s\n",
 591                                 SVCFH_fmt(&argp->fh));
 592 
 593         resp->f_rtmax  = max_blocksize;
 594         resp->f_rtpref = max_blocksize;
 595         resp->f_rtmult = PAGE_SIZE;
 596         resp->f_wtmax  = max_blocksize;
 597         resp->f_wtpref = max_blocksize;
 598         resp->f_wtmult = PAGE_SIZE;
 599         resp->f_dtpref = max_blocksize;
 600         resp->f_maxfilesize = ~(u32) 0;
 601         resp->f_properties = NFS3_FSF_DEFAULT;
 602 
 603         nfserr = fh_verify(rqstp, &argp->fh, 0,
 604                         NFSD_MAY_NOP | NFSD_MAY_BYPASS_GSS_ON_ROOT);
 605 
 606         /* Check special features of the file system. May request
 607          * different read/write sizes for file systems known to have
 608          * problems with large blocks */
 609         if (nfserr == 0) {
 610                 struct super_block *sb = argp->fh.fh_dentry->d_sb;
 611 
 612                 /* Note that we don't care for remote fs's here */
 613                 if (sb->s_magic == MSDOS_SUPER_MAGIC) {
 614                         resp->f_properties = NFS3_FSF_BILLYBOY;
 615                 }
 616                 resp->f_maxfilesize = sb->s_maxbytes;
 617         }
 618 
 619         fh_put(&argp->fh);
 620         RETURN_STATUS(nfserr);
 621 }
 622 
 623 /*
 624  * Get pathconf info for the specified file
 625  */
 626 static __be32
 627 nfsd3_proc_pathconf(struct svc_rqst *rqstp)
 628 {
 629         struct nfsd_fhandle *argp = rqstp->rq_argp;
 630         struct nfsd3_pathconfres *resp = rqstp->rq_resp;
 631         __be32  nfserr;
 632 
 633         dprintk("nfsd: PATHCONF(3) %s\n",
 634                                 SVCFH_fmt(&argp->fh));
 635 
 636         /* Set default pathconf */
 637         resp->p_link_max = 255;         /* at least */
 638         resp->p_name_max = 255;         /* at least */
 639         resp->p_no_trunc = 0;
 640         resp->p_chown_restricted = 1;
 641         resp->p_case_insensitive = 0;
 642         resp->p_case_preserving = 1;
 643 
 644         nfserr = fh_verify(rqstp, &argp->fh, 0, NFSD_MAY_NOP);
 645 
 646         if (nfserr == 0) {
 647                 struct super_block *sb = argp->fh.fh_dentry->d_sb;
 648 
 649                 /* Note that we don't care for remote fs's here */
 650                 switch (sb->s_magic) {
 651                 case EXT2_SUPER_MAGIC:
 652                         resp->p_link_max = EXT2_LINK_MAX;
 653                         resp->p_name_max = EXT2_NAME_LEN;
 654                         break;
 655                 case MSDOS_SUPER_MAGIC:
 656                         resp->p_case_insensitive = 1;
 657                         resp->p_case_preserving  = 0;
 658                         break;
 659                 }
 660         }
 661 
 662         fh_put(&argp->fh);
 663         RETURN_STATUS(nfserr);
 664 }
 665 
 666 
 667 /*
 668  * Commit a file (range) to stable storage.
 669  */
 670 static __be32
 671 nfsd3_proc_commit(struct svc_rqst *rqstp)
 672 {
 673         struct nfsd3_commitargs *argp = rqstp->rq_argp;
 674         struct nfsd3_commitres *resp = rqstp->rq_resp;
 675         __be32  nfserr;
 676 
 677         dprintk("nfsd: COMMIT(3)   %s %u@%Lu\n",
 678                                 SVCFH_fmt(&argp->fh),
 679                                 argp->count,
 680                                 (unsigned long long) argp->offset);
 681 
 682         if (argp->offset > NFS_OFFSET_MAX)
 683                 RETURN_STATUS(nfserr_inval);
 684 
 685         fh_copy(&resp->fh, &argp->fh);
 686         nfserr = nfsd_commit(rqstp, &resp->fh, argp->offset, argp->count);
 687 
 688         RETURN_STATUS(nfserr);
 689 }
 690 
 691 
 692 /*
 693  * NFSv3 Server procedures.
 694  * Only the results of non-idempotent operations are cached.
 695  */
 696 #define nfs3svc_decode_fhandleargs      nfs3svc_decode_fhandle
 697 #define nfs3svc_encode_attrstatres      nfs3svc_encode_attrstat
 698 #define nfs3svc_encode_wccstatres       nfs3svc_encode_wccstat
 699 #define nfsd3_mkdirargs                 nfsd3_createargs
 700 #define nfsd3_readdirplusargs           nfsd3_readdirargs
 701 #define nfsd3_fhandleargs               nfsd_fhandle
 702 #define nfsd3_fhandleres                nfsd3_attrstat
 703 #define nfsd3_attrstatres               nfsd3_attrstat
 704 #define nfsd3_wccstatres                nfsd3_attrstat
 705 #define nfsd3_createres                 nfsd3_diropres
 706 #define nfsd3_voidres                   nfsd3_voidargs
 707 struct nfsd3_voidargs { int dummy; };
 708 
 709 #define ST 1            /* status*/
 710 #define FH 17           /* filehandle with length */
 711 #define AT 21           /* attributes */
 712 #define pAT (1+AT)      /* post attributes - conditional */
 713 #define WC (7+pAT)      /* WCC attributes */
 714 
 715 static const struct svc_procedure nfsd_procedures3[22] = {
 716         [NFS3PROC_NULL] = {
 717                 .pc_func = nfsd3_proc_null,
 718                 .pc_encode = nfs3svc_encode_voidres,
 719                 .pc_argsize = sizeof(struct nfsd3_voidargs),
 720                 .pc_ressize = sizeof(struct nfsd3_voidres),
 721                 .pc_cachetype = RC_NOCACHE,
 722                 .pc_xdrressize = ST,
 723         },
 724         [NFS3PROC_GETATTR] = {
 725                 .pc_func = nfsd3_proc_getattr,
 726                 .pc_decode = nfs3svc_decode_fhandleargs,
 727                 .pc_encode = nfs3svc_encode_attrstatres,
 728                 .pc_release = nfs3svc_release_fhandle,
 729                 .pc_argsize = sizeof(struct nfsd3_fhandleargs),
 730                 .pc_ressize = sizeof(struct nfsd3_attrstatres),
 731                 .pc_cachetype = RC_NOCACHE,
 732                 .pc_xdrressize = ST+AT,
 733         },
 734         [NFS3PROC_SETATTR] = {
 735                 .pc_func = nfsd3_proc_setattr,
 736                 .pc_decode = nfs3svc_decode_sattrargs,
 737                 .pc_encode = nfs3svc_encode_wccstatres,
 738                 .pc_release = nfs3svc_release_fhandle,
 739                 .pc_argsize = sizeof(struct nfsd3_sattrargs),
 740                 .pc_ressize = sizeof(struct nfsd3_wccstatres),
 741                 .pc_cachetype = RC_REPLBUFF,
 742                 .pc_xdrressize = ST+WC,
 743         },
 744         [NFS3PROC_LOOKUP] = {
 745                 .pc_func = nfsd3_proc_lookup,
 746                 .pc_decode = nfs3svc_decode_diropargs,
 747                 .pc_encode = nfs3svc_encode_diropres,
 748                 .pc_release = nfs3svc_release_fhandle2,
 749                 .pc_argsize = sizeof(struct nfsd3_diropargs),
 750                 .pc_ressize = sizeof(struct nfsd3_diropres),
 751                 .pc_cachetype = RC_NOCACHE,
 752                 .pc_xdrressize = ST+FH+pAT+pAT,
 753         },
 754         [NFS3PROC_ACCESS] = {
 755                 .pc_func = nfsd3_proc_access,
 756                 .pc_decode = nfs3svc_decode_accessargs,
 757                 .pc_encode = nfs3svc_encode_accessres,
 758                 .pc_release = nfs3svc_release_fhandle,
 759                 .pc_argsize = sizeof(struct nfsd3_accessargs),
 760                 .pc_ressize = sizeof(struct nfsd3_accessres),
 761                 .pc_cachetype = RC_NOCACHE,
 762                 .pc_xdrressize = ST+pAT+1,
 763         },
 764         [NFS3PROC_READLINK] = {
 765                 .pc_func = nfsd3_proc_readlink,
 766                 .pc_decode = nfs3svc_decode_readlinkargs,
 767                 .pc_encode = nfs3svc_encode_readlinkres,
 768                 .pc_release = nfs3svc_release_fhandle,
 769                 .pc_argsize = sizeof(struct nfsd3_readlinkargs),
 770                 .pc_ressize = sizeof(struct nfsd3_readlinkres),
 771                 .pc_cachetype = RC_NOCACHE,
 772                 .pc_xdrressize = ST+pAT+1+NFS3_MAXPATHLEN/4,
 773         },
 774         [NFS3PROC_READ] = {
 775                 .pc_func = nfsd3_proc_read,
 776                 .pc_decode = nfs3svc_decode_readargs,
 777                 .pc_encode = nfs3svc_encode_readres,
 778                 .pc_release = nfs3svc_release_fhandle,
 779                 .pc_argsize = sizeof(struct nfsd3_readargs),
 780                 .pc_ressize = sizeof(struct nfsd3_readres),
 781                 .pc_cachetype = RC_NOCACHE,
 782                 .pc_xdrressize = ST+pAT+4+NFSSVC_MAXBLKSIZE/4,
 783         },
 784         [NFS3PROC_WRITE] = {
 785                 .pc_func = nfsd3_proc_write,
 786                 .pc_decode = nfs3svc_decode_writeargs,
 787                 .pc_encode = nfs3svc_encode_writeres,
 788                 .pc_release = nfs3svc_release_fhandle,
 789                 .pc_argsize = sizeof(struct nfsd3_writeargs),
 790                 .pc_ressize = sizeof(struct nfsd3_writeres),
 791                 .pc_cachetype = RC_REPLBUFF,
 792                 .pc_xdrressize = ST+WC+4,
 793         },
 794         [NFS3PROC_CREATE] = {
 795                 .pc_func = nfsd3_proc_create,
 796                 .pc_decode = nfs3svc_decode_createargs,
 797                 .pc_encode = nfs3svc_encode_createres,
 798                 .pc_release = nfs3svc_release_fhandle2,
 799                 .pc_argsize = sizeof(struct nfsd3_createargs),
 800                 .pc_ressize = sizeof(struct nfsd3_createres),
 801                 .pc_cachetype = RC_REPLBUFF,
 802                 .pc_xdrressize = ST+(1+FH+pAT)+WC,
 803         },
 804         [NFS3PROC_MKDIR] = {
 805                 .pc_func = nfsd3_proc_mkdir,
 806                 .pc_decode = nfs3svc_decode_mkdirargs,
 807                 .pc_encode = nfs3svc_encode_createres,
 808                 .pc_release = nfs3svc_release_fhandle2,
 809                 .pc_argsize = sizeof(struct nfsd3_mkdirargs),
 810                 .pc_ressize = sizeof(struct nfsd3_createres),
 811                 .pc_cachetype = RC_REPLBUFF,
 812                 .pc_xdrressize = ST+(1+FH+pAT)+WC,
 813         },
 814         [NFS3PROC_SYMLINK] = {
 815                 .pc_func = nfsd3_proc_symlink,
 816                 .pc_decode = nfs3svc_decode_symlinkargs,
 817                 .pc_encode = nfs3svc_encode_createres,
 818                 .pc_release = nfs3svc_release_fhandle2,
 819                 .pc_argsize = sizeof(struct nfsd3_symlinkargs),
 820                 .pc_ressize = sizeof(struct nfsd3_createres),
 821                 .pc_cachetype = RC_REPLBUFF,
 822                 .pc_xdrressize = ST+(1+FH+pAT)+WC,
 823         },
 824         [NFS3PROC_MKNOD] = {
 825                 .pc_func = nfsd3_proc_mknod,
 826                 .pc_decode = nfs3svc_decode_mknodargs,
 827                 .pc_encode = nfs3svc_encode_createres,
 828                 .pc_release = nfs3svc_release_fhandle2,
 829                 .pc_argsize = sizeof(struct nfsd3_mknodargs),
 830                 .pc_ressize = sizeof(struct nfsd3_createres),
 831                 .pc_cachetype = RC_REPLBUFF,
 832                 .pc_xdrressize = ST+(1+FH+pAT)+WC,
 833         },
 834         [NFS3PROC_REMOVE] = {
 835                 .pc_func = nfsd3_proc_remove,
 836                 .pc_decode = nfs3svc_decode_diropargs,
 837                 .pc_encode = nfs3svc_encode_wccstatres,
 838                 .pc_release = nfs3svc_release_fhandle,
 839                 .pc_argsize = sizeof(struct nfsd3_diropargs),
 840                 .pc_ressize = sizeof(struct nfsd3_wccstatres),
 841                 .pc_cachetype = RC_REPLBUFF,
 842                 .pc_xdrressize = ST+WC,
 843         },
 844         [NFS3PROC_RMDIR] = {
 845                 .pc_func = nfsd3_proc_rmdir,
 846                 .pc_decode = nfs3svc_decode_diropargs,
 847                 .pc_encode = nfs3svc_encode_wccstatres,
 848                 .pc_release = nfs3svc_release_fhandle,
 849                 .pc_argsize = sizeof(struct nfsd3_diropargs),
 850                 .pc_ressize = sizeof(struct nfsd3_wccstatres),
 851                 .pc_cachetype = RC_REPLBUFF,
 852                 .pc_xdrressize = ST+WC,
 853         },
 854         [NFS3PROC_RENAME] = {
 855                 .pc_func = nfsd3_proc_rename,
 856                 .pc_decode = nfs3svc_decode_renameargs,
 857                 .pc_encode = nfs3svc_encode_renameres,
 858                 .pc_release = nfs3svc_release_fhandle2,
 859                 .pc_argsize = sizeof(struct nfsd3_renameargs),
 860                 .pc_ressize = sizeof(struct nfsd3_renameres),
 861                 .pc_cachetype = RC_REPLBUFF,
 862                 .pc_xdrressize = ST+WC+WC,
 863         },
 864         [NFS3PROC_LINK] = {
 865                 .pc_func = nfsd3_proc_link,
 866                 .pc_decode = nfs3svc_decode_linkargs,
 867                 .pc_encode = nfs3svc_encode_linkres,
 868                 .pc_release = nfs3svc_release_fhandle2,
 869                 .pc_argsize = sizeof(struct nfsd3_linkargs),
 870                 .pc_ressize = sizeof(struct nfsd3_linkres),
 871                 .pc_cachetype = RC_REPLBUFF,
 872                 .pc_xdrressize = ST+pAT+WC,
 873         },
 874         [NFS3PROC_READDIR] = {
 875                 .pc_func = nfsd3_proc_readdir,
 876                 .pc_decode = nfs3svc_decode_readdirargs,
 877                 .pc_encode = nfs3svc_encode_readdirres,
 878                 .pc_release = nfs3svc_release_fhandle,
 879                 .pc_argsize = sizeof(struct nfsd3_readdirargs),
 880                 .pc_ressize = sizeof(struct nfsd3_readdirres),
 881                 .pc_cachetype = RC_NOCACHE,
 882         },
 883         [NFS3PROC_READDIRPLUS] = {
 884                 .pc_func = nfsd3_proc_readdirplus,
 885                 .pc_decode = nfs3svc_decode_readdirplusargs,
 886                 .pc_encode = nfs3svc_encode_readdirres,
 887                 .pc_release = nfs3svc_release_fhandle,
 888                 .pc_argsize = sizeof(struct nfsd3_readdirplusargs),
 889                 .pc_ressize = sizeof(struct nfsd3_readdirres),
 890                 .pc_cachetype = RC_NOCACHE,
 891         },
 892         [NFS3PROC_FSSTAT] = {
 893                 .pc_func = nfsd3_proc_fsstat,
 894                 .pc_decode = nfs3svc_decode_fhandleargs,
 895                 .pc_encode = nfs3svc_encode_fsstatres,
 896                 .pc_argsize = sizeof(struct nfsd3_fhandleargs),
 897                 .pc_ressize = sizeof(struct nfsd3_fsstatres),
 898                 .pc_cachetype = RC_NOCACHE,
 899                 .pc_xdrressize = ST+pAT+2*6+1,
 900         },
 901         [NFS3PROC_FSINFO] = {
 902                 .pc_func = nfsd3_proc_fsinfo,
 903                 .pc_decode = nfs3svc_decode_fhandleargs,
 904                 .pc_encode = nfs3svc_encode_fsinfores,
 905                 .pc_argsize = sizeof(struct nfsd3_fhandleargs),
 906                 .pc_ressize = sizeof(struct nfsd3_fsinfores),
 907                 .pc_cachetype = RC_NOCACHE,
 908                 .pc_xdrressize = ST+pAT+12,
 909         },
 910         [NFS3PROC_PATHCONF] = {
 911                 .pc_func = nfsd3_proc_pathconf,
 912                 .pc_decode = nfs3svc_decode_fhandleargs,
 913                 .pc_encode = nfs3svc_encode_pathconfres,
 914                 .pc_argsize = sizeof(struct nfsd3_fhandleargs),
 915                 .pc_ressize = sizeof(struct nfsd3_pathconfres),
 916                 .pc_cachetype = RC_NOCACHE,
 917                 .pc_xdrressize = ST+pAT+6,
 918         },
 919         [NFS3PROC_COMMIT] = {
 920                 .pc_func = nfsd3_proc_commit,
 921                 .pc_decode = nfs3svc_decode_commitargs,
 922                 .pc_encode = nfs3svc_encode_commitres,
 923                 .pc_release = nfs3svc_release_fhandle,
 924                 .pc_argsize = sizeof(struct nfsd3_commitargs),
 925                 .pc_ressize = sizeof(struct nfsd3_commitres),
 926                 .pc_cachetype = RC_NOCACHE,
 927                 .pc_xdrressize = ST+WC+2,
 928         },
 929 };
 930 
 931 static unsigned int nfsd_count3[ARRAY_SIZE(nfsd_procedures3)];
 932 const struct svc_version nfsd_version3 = {
 933         .vs_vers        = 3,
 934         .vs_nproc       = 22,
 935         .vs_proc        = nfsd_procedures3,
 936         .vs_dispatch    = nfsd_dispatch,
 937         .vs_count       = nfsd_count3,
 938         .vs_xdrsize     = NFS3_SVC_XDRSIZE,
 939 };

/* [<][>][^][v][top][bottom][index][help] */