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