0001
0002
0003
0004
0005
0006
0007
0008 #include <linux/fs.h>
0009 #include <linux/ext2_fs.h>
0010 #include <linux/magic.h>
0011 #include <linux/namei.h>
0012
0013 #include "cache.h"
0014 #include "xdr3.h"
0015 #include "vfs.h"
0016
0017 #define NFSDDBG_FACILITY NFSDDBG_PROC
0018
0019 static int nfs3_ftypes[] = {
0020 0,
0021 S_IFREG,
0022 S_IFDIR,
0023 S_IFBLK,
0024 S_IFCHR,
0025 S_IFLNK,
0026 S_IFSOCK,
0027 S_IFIFO,
0028 };
0029
0030
0031
0032
0033 static __be32
0034 nfsd3_proc_null(struct svc_rqst *rqstp)
0035 {
0036 return rpc_success;
0037 }
0038
0039
0040
0041
0042 static __be32
0043 nfsd3_proc_getattr(struct svc_rqst *rqstp)
0044 {
0045 struct nfsd_fhandle *argp = rqstp->rq_argp;
0046 struct nfsd3_attrstat *resp = rqstp->rq_resp;
0047
0048 dprintk("nfsd: GETATTR(3) %s\n",
0049 SVCFH_fmt(&argp->fh));
0050
0051 fh_copy(&resp->fh, &argp->fh);
0052 resp->status = fh_verify(rqstp, &resp->fh, 0,
0053 NFSD_MAY_NOP | NFSD_MAY_BYPASS_GSS_ON_ROOT);
0054 if (resp->status != nfs_ok)
0055 goto out;
0056
0057 resp->status = fh_getattr(&resp->fh, &resp->stat);
0058 out:
0059 return rpc_success;
0060 }
0061
0062
0063
0064
0065 static __be32
0066 nfsd3_proc_setattr(struct svc_rqst *rqstp)
0067 {
0068 struct nfsd3_sattrargs *argp = rqstp->rq_argp;
0069 struct nfsd3_attrstat *resp = rqstp->rq_resp;
0070 struct nfsd_attrs attrs = {
0071 .na_iattr = &argp->attrs,
0072 };
0073
0074 dprintk("nfsd: SETATTR(3) %s\n",
0075 SVCFH_fmt(&argp->fh));
0076
0077 fh_copy(&resp->fh, &argp->fh);
0078 resp->status = nfsd_setattr(rqstp, &resp->fh, &attrs,
0079 argp->check_guard, argp->guardtime);
0080 return rpc_success;
0081 }
0082
0083
0084
0085
0086 static __be32
0087 nfsd3_proc_lookup(struct svc_rqst *rqstp)
0088 {
0089 struct nfsd3_diropargs *argp = rqstp->rq_argp;
0090 struct nfsd3_diropres *resp = rqstp->rq_resp;
0091
0092 dprintk("nfsd: LOOKUP(3) %s %.*s\n",
0093 SVCFH_fmt(&argp->fh),
0094 argp->len,
0095 argp->name);
0096
0097 fh_copy(&resp->dirfh, &argp->fh);
0098 fh_init(&resp->fh, NFS3_FHSIZE);
0099
0100 resp->status = nfsd_lookup(rqstp, &resp->dirfh,
0101 argp->name, argp->len,
0102 &resp->fh);
0103 return rpc_success;
0104 }
0105
0106
0107
0108
0109 static __be32
0110 nfsd3_proc_access(struct svc_rqst *rqstp)
0111 {
0112 struct nfsd3_accessargs *argp = rqstp->rq_argp;
0113 struct nfsd3_accessres *resp = rqstp->rq_resp;
0114
0115 dprintk("nfsd: ACCESS(3) %s 0x%x\n",
0116 SVCFH_fmt(&argp->fh),
0117 argp->access);
0118
0119 fh_copy(&resp->fh, &argp->fh);
0120 resp->access = argp->access;
0121 resp->status = nfsd_access(rqstp, &resp->fh, &resp->access, NULL);
0122 return rpc_success;
0123 }
0124
0125
0126
0127
0128 static __be32
0129 nfsd3_proc_readlink(struct svc_rqst *rqstp)
0130 {
0131 struct nfsd_fhandle *argp = rqstp->rq_argp;
0132 struct nfsd3_readlinkres *resp = rqstp->rq_resp;
0133
0134 dprintk("nfsd: READLINK(3) %s\n", SVCFH_fmt(&argp->fh));
0135
0136
0137 fh_copy(&resp->fh, &argp->fh);
0138 resp->len = NFS3_MAXPATHLEN;
0139 resp->pages = rqstp->rq_next_page++;
0140 resp->status = nfsd_readlink(rqstp, &resp->fh,
0141 page_address(*resp->pages), &resp->len);
0142 return rpc_success;
0143 }
0144
0145
0146
0147
0148 static __be32
0149 nfsd3_proc_read(struct svc_rqst *rqstp)
0150 {
0151 struct nfsd3_readargs *argp = rqstp->rq_argp;
0152 struct nfsd3_readres *resp = rqstp->rq_resp;
0153 u32 max_blocksize = svc_max_payload(rqstp);
0154 unsigned int len;
0155 int v;
0156
0157 dprintk("nfsd: READ(3) %s %lu bytes at %Lu\n",
0158 SVCFH_fmt(&argp->fh),
0159 (unsigned long) argp->count,
0160 (unsigned long long) argp->offset);
0161
0162 argp->count = min_t(u32, argp->count, max_blocksize);
0163 if (argp->offset > (u64)OFFSET_MAX)
0164 argp->offset = (u64)OFFSET_MAX;
0165 if (argp->offset + argp->count > (u64)OFFSET_MAX)
0166 argp->count = (u64)OFFSET_MAX - argp->offset;
0167
0168 v = 0;
0169 len = argp->count;
0170 resp->pages = rqstp->rq_next_page;
0171 while (len > 0) {
0172 struct page *page = *(rqstp->rq_next_page++);
0173
0174 rqstp->rq_vec[v].iov_base = page_address(page);
0175 rqstp->rq_vec[v].iov_len = min_t(unsigned int, len, PAGE_SIZE);
0176 len -= rqstp->rq_vec[v].iov_len;
0177 v++;
0178 }
0179
0180
0181
0182
0183
0184 resp->count = argp->count;
0185 svc_reserve_auth(rqstp, ((1 + NFS3_POST_OP_ATTR_WORDS + 3)<<2) + resp->count +4);
0186
0187 fh_copy(&resp->fh, &argp->fh);
0188 resp->status = nfsd_read(rqstp, &resp->fh, argp->offset,
0189 rqstp->rq_vec, v, &resp->count, &resp->eof);
0190 return rpc_success;
0191 }
0192
0193
0194
0195
0196 static __be32
0197 nfsd3_proc_write(struct svc_rqst *rqstp)
0198 {
0199 struct nfsd3_writeargs *argp = rqstp->rq_argp;
0200 struct nfsd3_writeres *resp = rqstp->rq_resp;
0201 unsigned long cnt = argp->len;
0202 unsigned int nvecs;
0203
0204 dprintk("nfsd: WRITE(3) %s %d bytes at %Lu%s\n",
0205 SVCFH_fmt(&argp->fh),
0206 argp->len,
0207 (unsigned long long) argp->offset,
0208 argp->stable? " stable" : "");
0209
0210 resp->status = nfserr_fbig;
0211 if (argp->offset > (u64)OFFSET_MAX ||
0212 argp->offset + argp->len > (u64)OFFSET_MAX)
0213 return rpc_success;
0214
0215 fh_copy(&resp->fh, &argp->fh);
0216 resp->committed = argp->stable;
0217 nvecs = svc_fill_write_vector(rqstp, &argp->payload);
0218
0219 resp->status = nfsd_write(rqstp, &resp->fh, argp->offset,
0220 rqstp->rq_vec, nvecs, &cnt,
0221 resp->committed, resp->verf);
0222 resp->count = cnt;
0223 return rpc_success;
0224 }
0225
0226
0227
0228
0229
0230
0231
0232
0233 static __be32
0234 nfsd3_create_file(struct svc_rqst *rqstp, struct svc_fh *fhp,
0235 struct svc_fh *resfhp, struct nfsd3_createargs *argp)
0236 {
0237 struct iattr *iap = &argp->attrs;
0238 struct dentry *parent, *child;
0239 struct nfsd_attrs attrs = {
0240 .na_iattr = iap,
0241 };
0242 __u32 v_mtime, v_atime;
0243 struct inode *inode;
0244 __be32 status;
0245 int host_err;
0246
0247 if (isdotent(argp->name, argp->len))
0248 return nfserr_exist;
0249 if (!(iap->ia_valid & ATTR_MODE))
0250 iap->ia_mode = 0;
0251
0252 status = fh_verify(rqstp, fhp, S_IFDIR, NFSD_MAY_EXEC);
0253 if (status != nfs_ok)
0254 return status;
0255
0256 parent = fhp->fh_dentry;
0257 inode = d_inode(parent);
0258
0259 host_err = fh_want_write(fhp);
0260 if (host_err)
0261 return nfserrno(host_err);
0262
0263 inode_lock_nested(inode, I_MUTEX_PARENT);
0264
0265 child = lookup_one_len(argp->name, parent, argp->len);
0266 if (IS_ERR(child)) {
0267 status = nfserrno(PTR_ERR(child));
0268 goto out;
0269 }
0270
0271 if (d_really_is_negative(child)) {
0272 status = fh_verify(rqstp, fhp, S_IFDIR, NFSD_MAY_CREATE);
0273 if (status != nfs_ok)
0274 goto out;
0275 }
0276
0277 status = fh_compose(resfhp, fhp->fh_export, child, fhp);
0278 if (status != nfs_ok)
0279 goto out;
0280
0281 v_mtime = 0;
0282 v_atime = 0;
0283 if (argp->createmode == NFS3_CREATE_EXCLUSIVE) {
0284 u32 *verifier = (u32 *)argp->verf;
0285
0286
0287
0288
0289
0290
0291 v_mtime = verifier[0] & 0x7fffffff;
0292 v_atime = verifier[1] & 0x7fffffff;
0293 }
0294
0295 if (d_really_is_positive(child)) {
0296 status = nfs_ok;
0297
0298 switch (argp->createmode) {
0299 case NFS3_CREATE_UNCHECKED:
0300 if (!d_is_reg(child))
0301 break;
0302 iap->ia_valid &= ATTR_SIZE;
0303 goto set_attr;
0304 case NFS3_CREATE_GUARDED:
0305 status = nfserr_exist;
0306 break;
0307 case NFS3_CREATE_EXCLUSIVE:
0308 if (d_inode(child)->i_mtime.tv_sec == v_mtime &&
0309 d_inode(child)->i_atime.tv_sec == v_atime &&
0310 d_inode(child)->i_size == 0) {
0311 break;
0312 }
0313 status = nfserr_exist;
0314 }
0315 goto out;
0316 }
0317
0318 if (!IS_POSIXACL(inode))
0319 iap->ia_mode &= ~current_umask();
0320
0321 fh_fill_pre_attrs(fhp);
0322 host_err = vfs_create(&init_user_ns, inode, child, iap->ia_mode, true);
0323 if (host_err < 0) {
0324 status = nfserrno(host_err);
0325 goto out;
0326 }
0327 fh_fill_post_attrs(fhp);
0328
0329
0330 if ((iap->ia_valid & ATTR_SIZE) && (iap->ia_size == 0))
0331 iap->ia_valid &= ~ATTR_SIZE;
0332 if (argp->createmode == NFS3_CREATE_EXCLUSIVE) {
0333 iap->ia_valid = ATTR_MTIME | ATTR_ATIME |
0334 ATTR_MTIME_SET | ATTR_ATIME_SET;
0335 iap->ia_mtime.tv_sec = v_mtime;
0336 iap->ia_atime.tv_sec = v_atime;
0337 iap->ia_mtime.tv_nsec = 0;
0338 iap->ia_atime.tv_nsec = 0;
0339 }
0340
0341 set_attr:
0342 status = nfsd_create_setattr(rqstp, fhp, resfhp, &attrs);
0343
0344 out:
0345 inode_unlock(inode);
0346 if (child && !IS_ERR(child))
0347 dput(child);
0348 fh_drop_write(fhp);
0349 return status;
0350 }
0351
0352 static __be32
0353 nfsd3_proc_create(struct svc_rqst *rqstp)
0354 {
0355 struct nfsd3_createargs *argp = rqstp->rq_argp;
0356 struct nfsd3_diropres *resp = rqstp->rq_resp;
0357 svc_fh *dirfhp, *newfhp;
0358
0359 dprintk("nfsd: CREATE(3) %s %.*s\n",
0360 SVCFH_fmt(&argp->fh),
0361 argp->len,
0362 argp->name);
0363
0364 dirfhp = fh_copy(&resp->dirfh, &argp->fh);
0365 newfhp = fh_init(&resp->fh, NFS3_FHSIZE);
0366
0367 resp->status = nfsd3_create_file(rqstp, dirfhp, newfhp, argp);
0368 return rpc_success;
0369 }
0370
0371
0372
0373
0374 static __be32
0375 nfsd3_proc_mkdir(struct svc_rqst *rqstp)
0376 {
0377 struct nfsd3_createargs *argp = rqstp->rq_argp;
0378 struct nfsd3_diropres *resp = rqstp->rq_resp;
0379 struct nfsd_attrs attrs = {
0380 .na_iattr = &argp->attrs,
0381 };
0382
0383 dprintk("nfsd: MKDIR(3) %s %.*s\n",
0384 SVCFH_fmt(&argp->fh),
0385 argp->len,
0386 argp->name);
0387
0388 argp->attrs.ia_valid &= ~ATTR_SIZE;
0389 fh_copy(&resp->dirfh, &argp->fh);
0390 fh_init(&resp->fh, NFS3_FHSIZE);
0391 resp->status = nfsd_create(rqstp, &resp->dirfh, argp->name, argp->len,
0392 &attrs, S_IFDIR, 0, &resp->fh);
0393 return rpc_success;
0394 }
0395
0396 static __be32
0397 nfsd3_proc_symlink(struct svc_rqst *rqstp)
0398 {
0399 struct nfsd3_symlinkargs *argp = rqstp->rq_argp;
0400 struct nfsd3_diropres *resp = rqstp->rq_resp;
0401 struct nfsd_attrs attrs = {
0402 .na_iattr = &argp->attrs,
0403 };
0404
0405 if (argp->tlen == 0) {
0406 resp->status = nfserr_inval;
0407 goto out;
0408 }
0409 if (argp->tlen > NFS3_MAXPATHLEN) {
0410 resp->status = nfserr_nametoolong;
0411 goto out;
0412 }
0413
0414 argp->tname = svc_fill_symlink_pathname(rqstp, &argp->first,
0415 page_address(rqstp->rq_arg.pages[0]),
0416 argp->tlen);
0417 if (IS_ERR(argp->tname)) {
0418 resp->status = nfserrno(PTR_ERR(argp->tname));
0419 goto out;
0420 }
0421
0422 dprintk("nfsd: SYMLINK(3) %s %.*s -> %.*s\n",
0423 SVCFH_fmt(&argp->ffh),
0424 argp->flen, argp->fname,
0425 argp->tlen, argp->tname);
0426
0427 fh_copy(&resp->dirfh, &argp->ffh);
0428 fh_init(&resp->fh, NFS3_FHSIZE);
0429 resp->status = nfsd_symlink(rqstp, &resp->dirfh, argp->fname,
0430 argp->flen, argp->tname, &attrs, &resp->fh);
0431 kfree(argp->tname);
0432 out:
0433 return rpc_success;
0434 }
0435
0436
0437
0438
0439 static __be32
0440 nfsd3_proc_mknod(struct svc_rqst *rqstp)
0441 {
0442 struct nfsd3_mknodargs *argp = rqstp->rq_argp;
0443 struct nfsd3_diropres *resp = rqstp->rq_resp;
0444 struct nfsd_attrs attrs = {
0445 .na_iattr = &argp->attrs,
0446 };
0447 int type;
0448 dev_t rdev = 0;
0449
0450 dprintk("nfsd: MKNOD(3) %s %.*s\n",
0451 SVCFH_fmt(&argp->fh),
0452 argp->len,
0453 argp->name);
0454
0455 fh_copy(&resp->dirfh, &argp->fh);
0456 fh_init(&resp->fh, NFS3_FHSIZE);
0457
0458 if (argp->ftype == NF3CHR || argp->ftype == NF3BLK) {
0459 rdev = MKDEV(argp->major, argp->minor);
0460 if (MAJOR(rdev) != argp->major ||
0461 MINOR(rdev) != argp->minor) {
0462 resp->status = nfserr_inval;
0463 goto out;
0464 }
0465 } else if (argp->ftype != NF3SOCK && argp->ftype != NF3FIFO) {
0466 resp->status = nfserr_badtype;
0467 goto out;
0468 }
0469
0470 type = nfs3_ftypes[argp->ftype];
0471 resp->status = nfsd_create(rqstp, &resp->dirfh, argp->name, argp->len,
0472 &attrs, type, rdev, &resp->fh);
0473 out:
0474 return rpc_success;
0475 }
0476
0477
0478
0479
0480 static __be32
0481 nfsd3_proc_remove(struct svc_rqst *rqstp)
0482 {
0483 struct nfsd3_diropargs *argp = rqstp->rq_argp;
0484 struct nfsd3_attrstat *resp = rqstp->rq_resp;
0485
0486 dprintk("nfsd: REMOVE(3) %s %.*s\n",
0487 SVCFH_fmt(&argp->fh),
0488 argp->len,
0489 argp->name);
0490
0491
0492 fh_copy(&resp->fh, &argp->fh);
0493 resp->status = nfsd_unlink(rqstp, &resp->fh, -S_IFDIR,
0494 argp->name, argp->len);
0495 return rpc_success;
0496 }
0497
0498
0499
0500
0501 static __be32
0502 nfsd3_proc_rmdir(struct svc_rqst *rqstp)
0503 {
0504 struct nfsd3_diropargs *argp = rqstp->rq_argp;
0505 struct nfsd3_attrstat *resp = rqstp->rq_resp;
0506
0507 dprintk("nfsd: RMDIR(3) %s %.*s\n",
0508 SVCFH_fmt(&argp->fh),
0509 argp->len,
0510 argp->name);
0511
0512 fh_copy(&resp->fh, &argp->fh);
0513 resp->status = nfsd_unlink(rqstp, &resp->fh, S_IFDIR,
0514 argp->name, argp->len);
0515 return rpc_success;
0516 }
0517
0518 static __be32
0519 nfsd3_proc_rename(struct svc_rqst *rqstp)
0520 {
0521 struct nfsd3_renameargs *argp = rqstp->rq_argp;
0522 struct nfsd3_renameres *resp = rqstp->rq_resp;
0523
0524 dprintk("nfsd: RENAME(3) %s %.*s ->\n",
0525 SVCFH_fmt(&argp->ffh),
0526 argp->flen,
0527 argp->fname);
0528 dprintk("nfsd: -> %s %.*s\n",
0529 SVCFH_fmt(&argp->tfh),
0530 argp->tlen,
0531 argp->tname);
0532
0533 fh_copy(&resp->ffh, &argp->ffh);
0534 fh_copy(&resp->tfh, &argp->tfh);
0535 resp->status = nfsd_rename(rqstp, &resp->ffh, argp->fname, argp->flen,
0536 &resp->tfh, argp->tname, argp->tlen);
0537 return rpc_success;
0538 }
0539
0540 static __be32
0541 nfsd3_proc_link(struct svc_rqst *rqstp)
0542 {
0543 struct nfsd3_linkargs *argp = rqstp->rq_argp;
0544 struct nfsd3_linkres *resp = rqstp->rq_resp;
0545
0546 dprintk("nfsd: LINK(3) %s ->\n",
0547 SVCFH_fmt(&argp->ffh));
0548 dprintk("nfsd: -> %s %.*s\n",
0549 SVCFH_fmt(&argp->tfh),
0550 argp->tlen,
0551 argp->tname);
0552
0553 fh_copy(&resp->fh, &argp->ffh);
0554 fh_copy(&resp->tfh, &argp->tfh);
0555 resp->status = nfsd_link(rqstp, &resp->tfh, argp->tname, argp->tlen,
0556 &resp->fh);
0557 return rpc_success;
0558 }
0559
0560 static void nfsd3_init_dirlist_pages(struct svc_rqst *rqstp,
0561 struct nfsd3_readdirres *resp,
0562 u32 count)
0563 {
0564 struct xdr_buf *buf = &resp->dirlist;
0565 struct xdr_stream *xdr = &resp->xdr;
0566
0567 count = clamp(count, (u32)(XDR_UNIT * 2), svc_max_payload(rqstp));
0568
0569 memset(buf, 0, sizeof(*buf));
0570
0571
0572 buf->buflen = count - XDR_UNIT * 2;
0573 buf->pages = rqstp->rq_next_page;
0574 rqstp->rq_next_page += (buf->buflen + PAGE_SIZE - 1) >> PAGE_SHIFT;
0575
0576
0577
0578 xdr_set_scratch_buffer(xdr, NULL, 0);
0579 xdr->buf = buf;
0580 xdr->page_ptr = buf->pages;
0581 xdr->iov = NULL;
0582 xdr->p = page_address(*buf->pages);
0583 xdr->end = (void *)xdr->p + min_t(u32, buf->buflen, PAGE_SIZE);
0584 xdr->rqst = NULL;
0585 }
0586
0587
0588
0589
0590 static __be32
0591 nfsd3_proc_readdir(struct svc_rqst *rqstp)
0592 {
0593 struct nfsd3_readdirargs *argp = rqstp->rq_argp;
0594 struct nfsd3_readdirres *resp = rqstp->rq_resp;
0595 loff_t offset;
0596
0597 dprintk("nfsd: READDIR(3) %s %d bytes at %d\n",
0598 SVCFH_fmt(&argp->fh),
0599 argp->count, (u32) argp->cookie);
0600
0601 nfsd3_init_dirlist_pages(rqstp, resp, argp->count);
0602
0603 fh_copy(&resp->fh, &argp->fh);
0604 resp->common.err = nfs_ok;
0605 resp->cookie_offset = 0;
0606 resp->rqstp = rqstp;
0607 offset = argp->cookie;
0608 resp->status = nfsd_readdir(rqstp, &resp->fh, &offset,
0609 &resp->common, nfs3svc_encode_entry3);
0610 memcpy(resp->verf, argp->verf, 8);
0611 nfs3svc_encode_cookie3(resp, offset);
0612
0613
0614 rqstp->rq_next_page = resp->xdr.page_ptr + 1;
0615
0616 return rpc_success;
0617 }
0618
0619
0620
0621
0622
0623 static __be32
0624 nfsd3_proc_readdirplus(struct svc_rqst *rqstp)
0625 {
0626 struct nfsd3_readdirargs *argp = rqstp->rq_argp;
0627 struct nfsd3_readdirres *resp = rqstp->rq_resp;
0628 loff_t offset;
0629
0630 dprintk("nfsd: READDIR+(3) %s %d bytes at %d\n",
0631 SVCFH_fmt(&argp->fh),
0632 argp->count, (u32) argp->cookie);
0633
0634 nfsd3_init_dirlist_pages(rqstp, resp, argp->count);
0635
0636 fh_copy(&resp->fh, &argp->fh);
0637 resp->common.err = nfs_ok;
0638 resp->cookie_offset = 0;
0639 resp->rqstp = rqstp;
0640 offset = argp->cookie;
0641
0642 resp->status = fh_verify(rqstp, &resp->fh, S_IFDIR, NFSD_MAY_NOP);
0643 if (resp->status != nfs_ok)
0644 goto out;
0645
0646 if (resp->fh.fh_export->ex_flags & NFSEXP_NOREADDIRPLUS) {
0647 resp->status = nfserr_notsupp;
0648 goto out;
0649 }
0650
0651 resp->status = nfsd_readdir(rqstp, &resp->fh, &offset,
0652 &resp->common, nfs3svc_encode_entryplus3);
0653 memcpy(resp->verf, argp->verf, 8);
0654 nfs3svc_encode_cookie3(resp, offset);
0655
0656
0657 rqstp->rq_next_page = resp->xdr.page_ptr + 1;
0658
0659 out:
0660 return rpc_success;
0661 }
0662
0663
0664
0665
0666 static __be32
0667 nfsd3_proc_fsstat(struct svc_rqst *rqstp)
0668 {
0669 struct nfsd_fhandle *argp = rqstp->rq_argp;
0670 struct nfsd3_fsstatres *resp = rqstp->rq_resp;
0671
0672 dprintk("nfsd: FSSTAT(3) %s\n",
0673 SVCFH_fmt(&argp->fh));
0674
0675 resp->status = nfsd_statfs(rqstp, &argp->fh, &resp->stats, 0);
0676 fh_put(&argp->fh);
0677 return rpc_success;
0678 }
0679
0680
0681
0682
0683 static __be32
0684 nfsd3_proc_fsinfo(struct svc_rqst *rqstp)
0685 {
0686 struct nfsd_fhandle *argp = rqstp->rq_argp;
0687 struct nfsd3_fsinfores *resp = rqstp->rq_resp;
0688 u32 max_blocksize = svc_max_payload(rqstp);
0689
0690 dprintk("nfsd: FSINFO(3) %s\n",
0691 SVCFH_fmt(&argp->fh));
0692
0693 resp->f_rtmax = max_blocksize;
0694 resp->f_rtpref = max_blocksize;
0695 resp->f_rtmult = PAGE_SIZE;
0696 resp->f_wtmax = max_blocksize;
0697 resp->f_wtpref = max_blocksize;
0698 resp->f_wtmult = PAGE_SIZE;
0699 resp->f_dtpref = max_blocksize;
0700 resp->f_maxfilesize = ~(u32) 0;
0701 resp->f_properties = NFS3_FSF_DEFAULT;
0702
0703 resp->status = fh_verify(rqstp, &argp->fh, 0,
0704 NFSD_MAY_NOP | NFSD_MAY_BYPASS_GSS_ON_ROOT);
0705
0706
0707
0708
0709 if (resp->status == nfs_ok) {
0710 struct super_block *sb = argp->fh.fh_dentry->d_sb;
0711
0712
0713 if (sb->s_magic == MSDOS_SUPER_MAGIC) {
0714 resp->f_properties = NFS3_FSF_BILLYBOY;
0715 }
0716 resp->f_maxfilesize = sb->s_maxbytes;
0717 }
0718
0719 fh_put(&argp->fh);
0720 return rpc_success;
0721 }
0722
0723
0724
0725
0726 static __be32
0727 nfsd3_proc_pathconf(struct svc_rqst *rqstp)
0728 {
0729 struct nfsd_fhandle *argp = rqstp->rq_argp;
0730 struct nfsd3_pathconfres *resp = rqstp->rq_resp;
0731
0732 dprintk("nfsd: PATHCONF(3) %s\n",
0733 SVCFH_fmt(&argp->fh));
0734
0735
0736 resp->p_link_max = 255;
0737 resp->p_name_max = 255;
0738 resp->p_no_trunc = 0;
0739 resp->p_chown_restricted = 1;
0740 resp->p_case_insensitive = 0;
0741 resp->p_case_preserving = 1;
0742
0743 resp->status = fh_verify(rqstp, &argp->fh, 0, NFSD_MAY_NOP);
0744
0745 if (resp->status == nfs_ok) {
0746 struct super_block *sb = argp->fh.fh_dentry->d_sb;
0747
0748
0749 switch (sb->s_magic) {
0750 case EXT2_SUPER_MAGIC:
0751 resp->p_link_max = EXT2_LINK_MAX;
0752 resp->p_name_max = EXT2_NAME_LEN;
0753 break;
0754 case MSDOS_SUPER_MAGIC:
0755 resp->p_case_insensitive = 1;
0756 resp->p_case_preserving = 0;
0757 break;
0758 }
0759 }
0760
0761 fh_put(&argp->fh);
0762 return rpc_success;
0763 }
0764
0765
0766
0767
0768 static __be32
0769 nfsd3_proc_commit(struct svc_rqst *rqstp)
0770 {
0771 struct nfsd3_commitargs *argp = rqstp->rq_argp;
0772 struct nfsd3_commitres *resp = rqstp->rq_resp;
0773
0774 dprintk("nfsd: COMMIT(3) %s %u@%Lu\n",
0775 SVCFH_fmt(&argp->fh),
0776 argp->count,
0777 (unsigned long long) argp->offset);
0778
0779 fh_copy(&resp->fh, &argp->fh);
0780 resp->status = nfsd_commit(rqstp, &resp->fh, argp->offset,
0781 argp->count, resp->verf);
0782 return rpc_success;
0783 }
0784
0785
0786
0787
0788
0789
0790 #define nfs3svc_encode_attrstatres nfs3svc_encode_attrstat
0791 #define nfs3svc_encode_wccstatres nfs3svc_encode_wccstat
0792 #define nfsd3_mkdirargs nfsd3_createargs
0793 #define nfsd3_readdirplusargs nfsd3_readdirargs
0794 #define nfsd3_fhandleargs nfsd_fhandle
0795 #define nfsd3_attrstatres nfsd3_attrstat
0796 #define nfsd3_wccstatres nfsd3_attrstat
0797 #define nfsd3_createres nfsd3_diropres
0798
0799 #define ST 1
0800 #define FH 17
0801 #define AT 21
0802 #define pAT (1+AT)
0803 #define WC (7+pAT)
0804
0805 static const struct svc_procedure nfsd_procedures3[22] = {
0806 [NFS3PROC_NULL] = {
0807 .pc_func = nfsd3_proc_null,
0808 .pc_decode = nfssvc_decode_voidarg,
0809 .pc_encode = nfssvc_encode_voidres,
0810 .pc_argsize = sizeof(struct nfsd_voidargs),
0811 .pc_ressize = sizeof(struct nfsd_voidres),
0812 .pc_cachetype = RC_NOCACHE,
0813 .pc_xdrressize = ST,
0814 .pc_name = "NULL",
0815 },
0816 [NFS3PROC_GETATTR] = {
0817 .pc_func = nfsd3_proc_getattr,
0818 .pc_decode = nfs3svc_decode_fhandleargs,
0819 .pc_encode = nfs3svc_encode_getattrres,
0820 .pc_release = nfs3svc_release_fhandle,
0821 .pc_argsize = sizeof(struct nfsd_fhandle),
0822 .pc_ressize = sizeof(struct nfsd3_attrstatres),
0823 .pc_cachetype = RC_NOCACHE,
0824 .pc_xdrressize = ST+AT,
0825 .pc_name = "GETATTR",
0826 },
0827 [NFS3PROC_SETATTR] = {
0828 .pc_func = nfsd3_proc_setattr,
0829 .pc_decode = nfs3svc_decode_sattrargs,
0830 .pc_encode = nfs3svc_encode_wccstatres,
0831 .pc_release = nfs3svc_release_fhandle,
0832 .pc_argsize = sizeof(struct nfsd3_sattrargs),
0833 .pc_ressize = sizeof(struct nfsd3_wccstatres),
0834 .pc_cachetype = RC_REPLBUFF,
0835 .pc_xdrressize = ST+WC,
0836 .pc_name = "SETATTR",
0837 },
0838 [NFS3PROC_LOOKUP] = {
0839 .pc_func = nfsd3_proc_lookup,
0840 .pc_decode = nfs3svc_decode_diropargs,
0841 .pc_encode = nfs3svc_encode_lookupres,
0842 .pc_release = nfs3svc_release_fhandle2,
0843 .pc_argsize = sizeof(struct nfsd3_diropargs),
0844 .pc_ressize = sizeof(struct nfsd3_diropres),
0845 .pc_cachetype = RC_NOCACHE,
0846 .pc_xdrressize = ST+FH+pAT+pAT,
0847 .pc_name = "LOOKUP",
0848 },
0849 [NFS3PROC_ACCESS] = {
0850 .pc_func = nfsd3_proc_access,
0851 .pc_decode = nfs3svc_decode_accessargs,
0852 .pc_encode = nfs3svc_encode_accessres,
0853 .pc_release = nfs3svc_release_fhandle,
0854 .pc_argsize = sizeof(struct nfsd3_accessargs),
0855 .pc_ressize = sizeof(struct nfsd3_accessres),
0856 .pc_cachetype = RC_NOCACHE,
0857 .pc_xdrressize = ST+pAT+1,
0858 .pc_name = "ACCESS",
0859 },
0860 [NFS3PROC_READLINK] = {
0861 .pc_func = nfsd3_proc_readlink,
0862 .pc_decode = nfs3svc_decode_fhandleargs,
0863 .pc_encode = nfs3svc_encode_readlinkres,
0864 .pc_release = nfs3svc_release_fhandle,
0865 .pc_argsize = sizeof(struct nfsd_fhandle),
0866 .pc_ressize = sizeof(struct nfsd3_readlinkres),
0867 .pc_cachetype = RC_NOCACHE,
0868 .pc_xdrressize = ST+pAT+1+NFS3_MAXPATHLEN/4,
0869 .pc_name = "READLINK",
0870 },
0871 [NFS3PROC_READ] = {
0872 .pc_func = nfsd3_proc_read,
0873 .pc_decode = nfs3svc_decode_readargs,
0874 .pc_encode = nfs3svc_encode_readres,
0875 .pc_release = nfs3svc_release_fhandle,
0876 .pc_argsize = sizeof(struct nfsd3_readargs),
0877 .pc_ressize = sizeof(struct nfsd3_readres),
0878 .pc_cachetype = RC_NOCACHE,
0879 .pc_xdrressize = ST+pAT+4+NFSSVC_MAXBLKSIZE/4,
0880 .pc_name = "READ",
0881 },
0882 [NFS3PROC_WRITE] = {
0883 .pc_func = nfsd3_proc_write,
0884 .pc_decode = nfs3svc_decode_writeargs,
0885 .pc_encode = nfs3svc_encode_writeres,
0886 .pc_release = nfs3svc_release_fhandle,
0887 .pc_argsize = sizeof(struct nfsd3_writeargs),
0888 .pc_ressize = sizeof(struct nfsd3_writeres),
0889 .pc_cachetype = RC_REPLBUFF,
0890 .pc_xdrressize = ST+WC+4,
0891 .pc_name = "WRITE",
0892 },
0893 [NFS3PROC_CREATE] = {
0894 .pc_func = nfsd3_proc_create,
0895 .pc_decode = nfs3svc_decode_createargs,
0896 .pc_encode = nfs3svc_encode_createres,
0897 .pc_release = nfs3svc_release_fhandle2,
0898 .pc_argsize = sizeof(struct nfsd3_createargs),
0899 .pc_ressize = sizeof(struct nfsd3_createres),
0900 .pc_cachetype = RC_REPLBUFF,
0901 .pc_xdrressize = ST+(1+FH+pAT)+WC,
0902 .pc_name = "CREATE",
0903 },
0904 [NFS3PROC_MKDIR] = {
0905 .pc_func = nfsd3_proc_mkdir,
0906 .pc_decode = nfs3svc_decode_mkdirargs,
0907 .pc_encode = nfs3svc_encode_createres,
0908 .pc_release = nfs3svc_release_fhandle2,
0909 .pc_argsize = sizeof(struct nfsd3_mkdirargs),
0910 .pc_ressize = sizeof(struct nfsd3_createres),
0911 .pc_cachetype = RC_REPLBUFF,
0912 .pc_xdrressize = ST+(1+FH+pAT)+WC,
0913 .pc_name = "MKDIR",
0914 },
0915 [NFS3PROC_SYMLINK] = {
0916 .pc_func = nfsd3_proc_symlink,
0917 .pc_decode = nfs3svc_decode_symlinkargs,
0918 .pc_encode = nfs3svc_encode_createres,
0919 .pc_release = nfs3svc_release_fhandle2,
0920 .pc_argsize = sizeof(struct nfsd3_symlinkargs),
0921 .pc_ressize = sizeof(struct nfsd3_createres),
0922 .pc_cachetype = RC_REPLBUFF,
0923 .pc_xdrressize = ST+(1+FH+pAT)+WC,
0924 .pc_name = "SYMLINK",
0925 },
0926 [NFS3PROC_MKNOD] = {
0927 .pc_func = nfsd3_proc_mknod,
0928 .pc_decode = nfs3svc_decode_mknodargs,
0929 .pc_encode = nfs3svc_encode_createres,
0930 .pc_release = nfs3svc_release_fhandle2,
0931 .pc_argsize = sizeof(struct nfsd3_mknodargs),
0932 .pc_ressize = sizeof(struct nfsd3_createres),
0933 .pc_cachetype = RC_REPLBUFF,
0934 .pc_xdrressize = ST+(1+FH+pAT)+WC,
0935 .pc_name = "MKNOD",
0936 },
0937 [NFS3PROC_REMOVE] = {
0938 .pc_func = nfsd3_proc_remove,
0939 .pc_decode = nfs3svc_decode_diropargs,
0940 .pc_encode = nfs3svc_encode_wccstatres,
0941 .pc_release = nfs3svc_release_fhandle,
0942 .pc_argsize = sizeof(struct nfsd3_diropargs),
0943 .pc_ressize = sizeof(struct nfsd3_wccstatres),
0944 .pc_cachetype = RC_REPLBUFF,
0945 .pc_xdrressize = ST+WC,
0946 .pc_name = "REMOVE",
0947 },
0948 [NFS3PROC_RMDIR] = {
0949 .pc_func = nfsd3_proc_rmdir,
0950 .pc_decode = nfs3svc_decode_diropargs,
0951 .pc_encode = nfs3svc_encode_wccstatres,
0952 .pc_release = nfs3svc_release_fhandle,
0953 .pc_argsize = sizeof(struct nfsd3_diropargs),
0954 .pc_ressize = sizeof(struct nfsd3_wccstatres),
0955 .pc_cachetype = RC_REPLBUFF,
0956 .pc_xdrressize = ST+WC,
0957 .pc_name = "RMDIR",
0958 },
0959 [NFS3PROC_RENAME] = {
0960 .pc_func = nfsd3_proc_rename,
0961 .pc_decode = nfs3svc_decode_renameargs,
0962 .pc_encode = nfs3svc_encode_renameres,
0963 .pc_release = nfs3svc_release_fhandle2,
0964 .pc_argsize = sizeof(struct nfsd3_renameargs),
0965 .pc_ressize = sizeof(struct nfsd3_renameres),
0966 .pc_cachetype = RC_REPLBUFF,
0967 .pc_xdrressize = ST+WC+WC,
0968 .pc_name = "RENAME",
0969 },
0970 [NFS3PROC_LINK] = {
0971 .pc_func = nfsd3_proc_link,
0972 .pc_decode = nfs3svc_decode_linkargs,
0973 .pc_encode = nfs3svc_encode_linkres,
0974 .pc_release = nfs3svc_release_fhandle2,
0975 .pc_argsize = sizeof(struct nfsd3_linkargs),
0976 .pc_ressize = sizeof(struct nfsd3_linkres),
0977 .pc_cachetype = RC_REPLBUFF,
0978 .pc_xdrressize = ST+pAT+WC,
0979 .pc_name = "LINK",
0980 },
0981 [NFS3PROC_READDIR] = {
0982 .pc_func = nfsd3_proc_readdir,
0983 .pc_decode = nfs3svc_decode_readdirargs,
0984 .pc_encode = nfs3svc_encode_readdirres,
0985 .pc_release = nfs3svc_release_fhandle,
0986 .pc_argsize = sizeof(struct nfsd3_readdirargs),
0987 .pc_ressize = sizeof(struct nfsd3_readdirres),
0988 .pc_cachetype = RC_NOCACHE,
0989 .pc_name = "READDIR",
0990 },
0991 [NFS3PROC_READDIRPLUS] = {
0992 .pc_func = nfsd3_proc_readdirplus,
0993 .pc_decode = nfs3svc_decode_readdirplusargs,
0994 .pc_encode = nfs3svc_encode_readdirres,
0995 .pc_release = nfs3svc_release_fhandle,
0996 .pc_argsize = sizeof(struct nfsd3_readdirplusargs),
0997 .pc_ressize = sizeof(struct nfsd3_readdirres),
0998 .pc_cachetype = RC_NOCACHE,
0999 .pc_name = "READDIRPLUS",
1000 },
1001 [NFS3PROC_FSSTAT] = {
1002 .pc_func = nfsd3_proc_fsstat,
1003 .pc_decode = nfs3svc_decode_fhandleargs,
1004 .pc_encode = nfs3svc_encode_fsstatres,
1005 .pc_argsize = sizeof(struct nfsd3_fhandleargs),
1006 .pc_ressize = sizeof(struct nfsd3_fsstatres),
1007 .pc_cachetype = RC_NOCACHE,
1008 .pc_xdrressize = ST+pAT+2*6+1,
1009 .pc_name = "FSSTAT",
1010 },
1011 [NFS3PROC_FSINFO] = {
1012 .pc_func = nfsd3_proc_fsinfo,
1013 .pc_decode = nfs3svc_decode_fhandleargs,
1014 .pc_encode = nfs3svc_encode_fsinfores,
1015 .pc_argsize = sizeof(struct nfsd3_fhandleargs),
1016 .pc_ressize = sizeof(struct nfsd3_fsinfores),
1017 .pc_cachetype = RC_NOCACHE,
1018 .pc_xdrressize = ST+pAT+12,
1019 .pc_name = "FSINFO",
1020 },
1021 [NFS3PROC_PATHCONF] = {
1022 .pc_func = nfsd3_proc_pathconf,
1023 .pc_decode = nfs3svc_decode_fhandleargs,
1024 .pc_encode = nfs3svc_encode_pathconfres,
1025 .pc_argsize = sizeof(struct nfsd3_fhandleargs),
1026 .pc_ressize = sizeof(struct nfsd3_pathconfres),
1027 .pc_cachetype = RC_NOCACHE,
1028 .pc_xdrressize = ST+pAT+6,
1029 .pc_name = "PATHCONF",
1030 },
1031 [NFS3PROC_COMMIT] = {
1032 .pc_func = nfsd3_proc_commit,
1033 .pc_decode = nfs3svc_decode_commitargs,
1034 .pc_encode = nfs3svc_encode_commitres,
1035 .pc_release = nfs3svc_release_fhandle,
1036 .pc_argsize = sizeof(struct nfsd3_commitargs),
1037 .pc_ressize = sizeof(struct nfsd3_commitres),
1038 .pc_cachetype = RC_NOCACHE,
1039 .pc_xdrressize = ST+WC+2,
1040 .pc_name = "COMMIT",
1041 },
1042 };
1043
1044 static unsigned int nfsd_count3[ARRAY_SIZE(nfsd_procedures3)];
1045 const struct svc_version nfsd_version3 = {
1046 .vs_vers = 3,
1047 .vs_nproc = 22,
1048 .vs_proc = nfsd_procedures3,
1049 .vs_dispatch = nfsd_dispatch,
1050 .vs_count = nfsd_count3,
1051 .vs_xdrsize = NFS3_SVC_XDRSIZE,
1052 };