0001
0002
0003
0004
0005
0006
0007
0008 #include <linux/namei.h>
0009
0010 #include "cache.h"
0011 #include "xdr.h"
0012 #include "vfs.h"
0013
0014 #define NFSDDBG_FACILITY NFSDDBG_PROC
0015
0016 static __be32
0017 nfsd_proc_null(struct svc_rqst *rqstp)
0018 {
0019 return rpc_success;
0020 }
0021
0022
0023
0024
0025
0026 static __be32
0027 nfsd_proc_getattr(struct svc_rqst *rqstp)
0028 {
0029 struct nfsd_fhandle *argp = rqstp->rq_argp;
0030 struct nfsd_attrstat *resp = rqstp->rq_resp;
0031
0032 dprintk("nfsd: GETATTR %s\n", SVCFH_fmt(&argp->fh));
0033
0034 fh_copy(&resp->fh, &argp->fh);
0035 resp->status = fh_verify(rqstp, &resp->fh, 0,
0036 NFSD_MAY_NOP | NFSD_MAY_BYPASS_GSS_ON_ROOT);
0037 if (resp->status != nfs_ok)
0038 goto out;
0039 resp->status = fh_getattr(&resp->fh, &resp->stat);
0040 out:
0041 return rpc_success;
0042 }
0043
0044
0045
0046
0047
0048 static __be32
0049 nfsd_proc_setattr(struct svc_rqst *rqstp)
0050 {
0051 struct nfsd_sattrargs *argp = rqstp->rq_argp;
0052 struct nfsd_attrstat *resp = rqstp->rq_resp;
0053 struct iattr *iap = &argp->attrs;
0054 struct nfsd_attrs attrs = {
0055 .na_iattr = iap,
0056 };
0057 struct svc_fh *fhp;
0058
0059 dprintk("nfsd: SETATTR %s, valid=%x, size=%ld\n",
0060 SVCFH_fmt(&argp->fh),
0061 argp->attrs.ia_valid, (long) argp->attrs.ia_size);
0062
0063 fhp = fh_copy(&resp->fh, &argp->fh);
0064
0065
0066
0067
0068
0069
0070
0071
0072
0073
0074
0075
0076 #define BOTH_TIME_SET (ATTR_ATIME_SET | ATTR_MTIME_SET)
0077 #define MAX_TOUCH_TIME_ERROR (30*60)
0078 if ((iap->ia_valid & BOTH_TIME_SET) == BOTH_TIME_SET &&
0079 iap->ia_mtime.tv_sec == iap->ia_atime.tv_sec) {
0080
0081
0082
0083
0084
0085
0086
0087 time64_t delta = iap->ia_atime.tv_sec - ktime_get_real_seconds();
0088
0089 resp->status = fh_verify(rqstp, fhp, 0, NFSD_MAY_NOP);
0090 if (resp->status != nfs_ok)
0091 goto out;
0092
0093 if (delta < 0)
0094 delta = -delta;
0095 if (delta < MAX_TOUCH_TIME_ERROR &&
0096 setattr_prepare(&init_user_ns, fhp->fh_dentry, iap) != 0) {
0097
0098
0099
0100
0101
0102 iap->ia_valid &= ~BOTH_TIME_SET;
0103 }
0104 }
0105
0106 resp->status = nfsd_setattr(rqstp, fhp, &attrs, 0, (time64_t)0);
0107 if (resp->status != nfs_ok)
0108 goto out;
0109
0110 resp->status = fh_getattr(&resp->fh, &resp->stat);
0111 out:
0112 return rpc_success;
0113 }
0114
0115
0116 static __be32
0117 nfsd_proc_root(struct svc_rqst *rqstp)
0118 {
0119 return rpc_success;
0120 }
0121
0122
0123
0124
0125
0126
0127
0128 static __be32
0129 nfsd_proc_lookup(struct svc_rqst *rqstp)
0130 {
0131 struct nfsd_diropargs *argp = rqstp->rq_argp;
0132 struct nfsd_diropres *resp = rqstp->rq_resp;
0133
0134 dprintk("nfsd: LOOKUP %s %.*s\n",
0135 SVCFH_fmt(&argp->fh), argp->len, argp->name);
0136
0137 fh_init(&resp->fh, NFS_FHSIZE);
0138 resp->status = nfsd_lookup(rqstp, &argp->fh, argp->name, argp->len,
0139 &resp->fh);
0140 fh_put(&argp->fh);
0141 if (resp->status != nfs_ok)
0142 goto out;
0143
0144 resp->status = fh_getattr(&resp->fh, &resp->stat);
0145 out:
0146 return rpc_success;
0147 }
0148
0149
0150
0151
0152 static __be32
0153 nfsd_proc_readlink(struct svc_rqst *rqstp)
0154 {
0155 struct nfsd_fhandle *argp = rqstp->rq_argp;
0156 struct nfsd_readlinkres *resp = rqstp->rq_resp;
0157
0158 dprintk("nfsd: READLINK %s\n", SVCFH_fmt(&argp->fh));
0159
0160
0161 resp->len = NFS_MAXPATHLEN;
0162 resp->page = *(rqstp->rq_next_page++);
0163 resp->status = nfsd_readlink(rqstp, &argp->fh,
0164 page_address(resp->page), &resp->len);
0165
0166 fh_put(&argp->fh);
0167 return rpc_success;
0168 }
0169
0170
0171
0172
0173
0174 static __be32
0175 nfsd_proc_read(struct svc_rqst *rqstp)
0176 {
0177 struct nfsd_readargs *argp = rqstp->rq_argp;
0178 struct nfsd_readres *resp = rqstp->rq_resp;
0179 unsigned int len;
0180 u32 eof;
0181 int v;
0182
0183 dprintk("nfsd: READ %s %d bytes at %d\n",
0184 SVCFH_fmt(&argp->fh),
0185 argp->count, argp->offset);
0186
0187 argp->count = min_t(u32, argp->count, NFSSVC_MAXBLKSIZE_V2);
0188
0189 v = 0;
0190 len = argp->count;
0191 resp->pages = rqstp->rq_next_page;
0192 while (len > 0) {
0193 struct page *page = *(rqstp->rq_next_page++);
0194
0195 rqstp->rq_vec[v].iov_base = page_address(page);
0196 rqstp->rq_vec[v].iov_len = min_t(unsigned int, len, PAGE_SIZE);
0197 len -= rqstp->rq_vec[v].iov_len;
0198 v++;
0199 }
0200
0201
0202
0203
0204 svc_reserve_auth(rqstp, (19<<2) + argp->count + 4);
0205
0206 resp->count = argp->count;
0207 fh_copy(&resp->fh, &argp->fh);
0208 resp->status = nfsd_read(rqstp, &resp->fh, argp->offset,
0209 rqstp->rq_vec, v, &resp->count, &eof);
0210 if (resp->status == nfs_ok)
0211 resp->status = fh_getattr(&resp->fh, &resp->stat);
0212 else if (resp->status == nfserr_jukebox)
0213 return rpc_drop_reply;
0214 return rpc_success;
0215 }
0216
0217
0218 static __be32
0219 nfsd_proc_writecache(struct svc_rqst *rqstp)
0220 {
0221 return rpc_success;
0222 }
0223
0224
0225
0226
0227
0228 static __be32
0229 nfsd_proc_write(struct svc_rqst *rqstp)
0230 {
0231 struct nfsd_writeargs *argp = rqstp->rq_argp;
0232 struct nfsd_attrstat *resp = rqstp->rq_resp;
0233 unsigned long cnt = argp->len;
0234 unsigned int nvecs;
0235
0236 dprintk("nfsd: WRITE %s %u bytes at %d\n",
0237 SVCFH_fmt(&argp->fh),
0238 argp->len, argp->offset);
0239
0240 nvecs = svc_fill_write_vector(rqstp, &argp->payload);
0241
0242 resp->status = nfsd_write(rqstp, fh_copy(&resp->fh, &argp->fh),
0243 argp->offset, rqstp->rq_vec, nvecs,
0244 &cnt, NFS_DATA_SYNC, NULL);
0245 if (resp->status == nfs_ok)
0246 resp->status = fh_getattr(&resp->fh, &resp->stat);
0247 else if (resp->status == nfserr_jukebox)
0248 return rpc_drop_reply;
0249 return rpc_success;
0250 }
0251
0252
0253
0254
0255
0256
0257
0258 static __be32
0259 nfsd_proc_create(struct svc_rqst *rqstp)
0260 {
0261 struct nfsd_createargs *argp = rqstp->rq_argp;
0262 struct nfsd_diropres *resp = rqstp->rq_resp;
0263 svc_fh *dirfhp = &argp->fh;
0264 svc_fh *newfhp = &resp->fh;
0265 struct iattr *attr = &argp->attrs;
0266 struct nfsd_attrs attrs = {
0267 .na_iattr = attr,
0268 };
0269 struct inode *inode;
0270 struct dentry *dchild;
0271 int type, mode;
0272 int hosterr;
0273 dev_t rdev = 0, wanted = new_decode_dev(attr->ia_size);
0274
0275 dprintk("nfsd: CREATE %s %.*s\n",
0276 SVCFH_fmt(dirfhp), argp->len, argp->name);
0277
0278
0279 resp->status = fh_verify(rqstp, dirfhp, S_IFDIR, NFSD_MAY_EXEC);
0280 if (resp->status != nfs_ok)
0281 goto done;
0282
0283
0284
0285 resp->status = nfserr_exist;
0286 if (isdotent(argp->name, argp->len))
0287 goto done;
0288 hosterr = fh_want_write(dirfhp);
0289 if (hosterr) {
0290 resp->status = nfserrno(hosterr);
0291 goto done;
0292 }
0293
0294 inode_lock_nested(dirfhp->fh_dentry->d_inode, I_MUTEX_PARENT);
0295 dchild = lookup_one_len(argp->name, dirfhp->fh_dentry, argp->len);
0296 if (IS_ERR(dchild)) {
0297 resp->status = nfserrno(PTR_ERR(dchild));
0298 goto out_unlock;
0299 }
0300 fh_init(newfhp, NFS_FHSIZE);
0301 resp->status = fh_compose(newfhp, dirfhp->fh_export, dchild, dirfhp);
0302 if (!resp->status && d_really_is_negative(dchild))
0303 resp->status = nfserr_noent;
0304 dput(dchild);
0305 if (resp->status) {
0306 if (resp->status != nfserr_noent)
0307 goto out_unlock;
0308
0309
0310
0311
0312 resp->status = nfserr_acces;
0313 if (!newfhp->fh_dentry) {
0314 printk(KERN_WARNING
0315 "nfsd_proc_create: file handle not verified\n");
0316 goto out_unlock;
0317 }
0318 }
0319
0320 inode = d_inode(newfhp->fh_dentry);
0321
0322
0323 if (attr->ia_valid & ATTR_MODE) {
0324 type = attr->ia_mode & S_IFMT;
0325 mode = attr->ia_mode & ~S_IFMT;
0326 if (!type) {
0327
0328
0329 if (inode) {
0330 type = inode->i_mode & S_IFMT;
0331 switch(type) {
0332 case S_IFCHR:
0333 case S_IFBLK:
0334
0335 rdev = inode->i_rdev;
0336 attr->ia_valid |= ATTR_SIZE;
0337
0338 fallthrough;
0339 case S_IFIFO:
0340
0341
0342
0343
0344
0345 resp->status = nfsd_permission(rqstp,
0346 newfhp->fh_export,
0347 newfhp->fh_dentry,
0348 NFSD_MAY_WRITE|NFSD_MAY_LOCAL_ACCESS);
0349 if (resp->status && resp->status != nfserr_rofs)
0350 goto out_unlock;
0351 }
0352 } else
0353 type = S_IFREG;
0354 }
0355 } else if (inode) {
0356 type = inode->i_mode & S_IFMT;
0357 mode = inode->i_mode & ~S_IFMT;
0358 } else {
0359 type = S_IFREG;
0360 mode = 0;
0361 }
0362
0363 attr->ia_valid |= ATTR_MODE;
0364 attr->ia_mode = mode;
0365
0366
0367
0368
0369 if (type != S_IFREG) {
0370 if (type != S_IFBLK && type != S_IFCHR) {
0371 rdev = 0;
0372 } else if (type == S_IFCHR && !(attr->ia_valid & ATTR_SIZE)) {
0373
0374 type = S_IFIFO;
0375 } else {
0376
0377 if (!rdev)
0378 rdev = wanted;
0379 }
0380
0381
0382 attr->ia_valid &= ~ATTR_SIZE;
0383
0384
0385 resp->status = nfserr_exist;
0386 if (inode && inode_wrong_type(inode, type))
0387 goto out_unlock;
0388 }
0389
0390 resp->status = nfs_ok;
0391 if (!inode) {
0392
0393 resp->status = nfsd_create_locked(rqstp, dirfhp, argp->name,
0394 argp->len, &attrs, type, rdev,
0395 newfhp);
0396 } else if (type == S_IFREG) {
0397 dprintk("nfsd: existing %s, valid=%x, size=%ld\n",
0398 argp->name, attr->ia_valid, (long) attr->ia_size);
0399
0400
0401
0402
0403 attr->ia_valid &= ATTR_SIZE;
0404 if (attr->ia_valid)
0405 resp->status = nfsd_setattr(rqstp, newfhp, &attrs, 0,
0406 (time64_t)0);
0407 }
0408
0409 out_unlock:
0410 inode_unlock(dirfhp->fh_dentry->d_inode);
0411 fh_drop_write(dirfhp);
0412 done:
0413 fh_put(dirfhp);
0414 if (resp->status != nfs_ok)
0415 goto out;
0416 resp->status = fh_getattr(&resp->fh, &resp->stat);
0417 out:
0418 return rpc_success;
0419 }
0420
0421 static __be32
0422 nfsd_proc_remove(struct svc_rqst *rqstp)
0423 {
0424 struct nfsd_diropargs *argp = rqstp->rq_argp;
0425 struct nfsd_stat *resp = rqstp->rq_resp;
0426
0427 dprintk("nfsd: REMOVE %s %.*s\n", SVCFH_fmt(&argp->fh),
0428 argp->len, argp->name);
0429
0430
0431 resp->status = nfsd_unlink(rqstp, &argp->fh, -S_IFDIR,
0432 argp->name, argp->len);
0433 fh_put(&argp->fh);
0434 return rpc_success;
0435 }
0436
0437 static __be32
0438 nfsd_proc_rename(struct svc_rqst *rqstp)
0439 {
0440 struct nfsd_renameargs *argp = rqstp->rq_argp;
0441 struct nfsd_stat *resp = rqstp->rq_resp;
0442
0443 dprintk("nfsd: RENAME %s %.*s -> \n",
0444 SVCFH_fmt(&argp->ffh), argp->flen, argp->fname);
0445 dprintk("nfsd: -> %s %.*s\n",
0446 SVCFH_fmt(&argp->tfh), argp->tlen, argp->tname);
0447
0448 resp->status = nfsd_rename(rqstp, &argp->ffh, argp->fname, argp->flen,
0449 &argp->tfh, argp->tname, argp->tlen);
0450 fh_put(&argp->ffh);
0451 fh_put(&argp->tfh);
0452 return rpc_success;
0453 }
0454
0455 static __be32
0456 nfsd_proc_link(struct svc_rqst *rqstp)
0457 {
0458 struct nfsd_linkargs *argp = rqstp->rq_argp;
0459 struct nfsd_stat *resp = rqstp->rq_resp;
0460
0461 dprintk("nfsd: LINK %s ->\n",
0462 SVCFH_fmt(&argp->ffh));
0463 dprintk("nfsd: %s %.*s\n",
0464 SVCFH_fmt(&argp->tfh),
0465 argp->tlen,
0466 argp->tname);
0467
0468 resp->status = nfsd_link(rqstp, &argp->tfh, argp->tname, argp->tlen,
0469 &argp->ffh);
0470 fh_put(&argp->ffh);
0471 fh_put(&argp->tfh);
0472 return rpc_success;
0473 }
0474
0475 static __be32
0476 nfsd_proc_symlink(struct svc_rqst *rqstp)
0477 {
0478 struct nfsd_symlinkargs *argp = rqstp->rq_argp;
0479 struct nfsd_stat *resp = rqstp->rq_resp;
0480 struct nfsd_attrs attrs = {
0481 .na_iattr = &argp->attrs,
0482 };
0483 struct svc_fh newfh;
0484
0485 if (argp->tlen > NFS_MAXPATHLEN) {
0486 resp->status = nfserr_nametoolong;
0487 goto out;
0488 }
0489
0490 argp->tname = svc_fill_symlink_pathname(rqstp, &argp->first,
0491 page_address(rqstp->rq_arg.pages[0]),
0492 argp->tlen);
0493 if (IS_ERR(argp->tname)) {
0494 resp->status = nfserrno(PTR_ERR(argp->tname));
0495 goto out;
0496 }
0497
0498 dprintk("nfsd: SYMLINK %s %.*s -> %.*s\n",
0499 SVCFH_fmt(&argp->ffh), argp->flen, argp->fname,
0500 argp->tlen, argp->tname);
0501
0502 fh_init(&newfh, NFS_FHSIZE);
0503 resp->status = nfsd_symlink(rqstp, &argp->ffh, argp->fname, argp->flen,
0504 argp->tname, &attrs, &newfh);
0505
0506 kfree(argp->tname);
0507 fh_put(&argp->ffh);
0508 fh_put(&newfh);
0509 out:
0510 return rpc_success;
0511 }
0512
0513
0514
0515
0516
0517 static __be32
0518 nfsd_proc_mkdir(struct svc_rqst *rqstp)
0519 {
0520 struct nfsd_createargs *argp = rqstp->rq_argp;
0521 struct nfsd_diropres *resp = rqstp->rq_resp;
0522 struct nfsd_attrs attrs = {
0523 .na_iattr = &argp->attrs,
0524 };
0525
0526 dprintk("nfsd: MKDIR %s %.*s\n", SVCFH_fmt(&argp->fh), argp->len, argp->name);
0527
0528 if (resp->fh.fh_dentry) {
0529 printk(KERN_WARNING
0530 "nfsd_proc_mkdir: response already verified??\n");
0531 }
0532
0533 argp->attrs.ia_valid &= ~ATTR_SIZE;
0534 fh_init(&resp->fh, NFS_FHSIZE);
0535 resp->status = nfsd_create(rqstp, &argp->fh, argp->name, argp->len,
0536 &attrs, S_IFDIR, 0, &resp->fh);
0537 fh_put(&argp->fh);
0538 if (resp->status != nfs_ok)
0539 goto out;
0540
0541 resp->status = fh_getattr(&resp->fh, &resp->stat);
0542 out:
0543 return rpc_success;
0544 }
0545
0546
0547
0548
0549 static __be32
0550 nfsd_proc_rmdir(struct svc_rqst *rqstp)
0551 {
0552 struct nfsd_diropargs *argp = rqstp->rq_argp;
0553 struct nfsd_stat *resp = rqstp->rq_resp;
0554
0555 dprintk("nfsd: RMDIR %s %.*s\n", SVCFH_fmt(&argp->fh), argp->len, argp->name);
0556
0557 resp->status = nfsd_unlink(rqstp, &argp->fh, S_IFDIR,
0558 argp->name, argp->len);
0559 fh_put(&argp->fh);
0560 return rpc_success;
0561 }
0562
0563 static void nfsd_init_dirlist_pages(struct svc_rqst *rqstp,
0564 struct nfsd_readdirres *resp,
0565 u32 count)
0566 {
0567 struct xdr_buf *buf = &resp->dirlist;
0568 struct xdr_stream *xdr = &resp->xdr;
0569
0570 count = clamp(count, (u32)(XDR_UNIT * 2), svc_max_payload(rqstp));
0571
0572 memset(buf, 0, sizeof(*buf));
0573
0574
0575 buf->buflen = count - XDR_UNIT * 2;
0576 buf->pages = rqstp->rq_next_page;
0577 rqstp->rq_next_page++;
0578
0579
0580
0581 xdr_set_scratch_buffer(xdr, NULL, 0);
0582 xdr->buf = buf;
0583 xdr->page_ptr = buf->pages;
0584 xdr->iov = NULL;
0585 xdr->p = page_address(*buf->pages);
0586 xdr->end = (void *)xdr->p + min_t(u32, buf->buflen, PAGE_SIZE);
0587 xdr->rqst = NULL;
0588 }
0589
0590
0591
0592
0593 static __be32
0594 nfsd_proc_readdir(struct svc_rqst *rqstp)
0595 {
0596 struct nfsd_readdirargs *argp = rqstp->rq_argp;
0597 struct nfsd_readdirres *resp = rqstp->rq_resp;
0598 loff_t offset;
0599
0600 dprintk("nfsd: READDIR %s %d bytes at %d\n",
0601 SVCFH_fmt(&argp->fh),
0602 argp->count, argp->cookie);
0603
0604 nfsd_init_dirlist_pages(rqstp, resp, argp->count);
0605
0606 resp->common.err = nfs_ok;
0607 resp->cookie_offset = 0;
0608 offset = argp->cookie;
0609 resp->status = nfsd_readdir(rqstp, &argp->fh, &offset,
0610 &resp->common, nfssvc_encode_entry);
0611 nfssvc_encode_nfscookie(resp, offset);
0612
0613 fh_put(&argp->fh);
0614 return rpc_success;
0615 }
0616
0617
0618
0619
0620 static __be32
0621 nfsd_proc_statfs(struct svc_rqst *rqstp)
0622 {
0623 struct nfsd_fhandle *argp = rqstp->rq_argp;
0624 struct nfsd_statfsres *resp = rqstp->rq_resp;
0625
0626 dprintk("nfsd: STATFS %s\n", SVCFH_fmt(&argp->fh));
0627
0628 resp->status = nfsd_statfs(rqstp, &argp->fh, &resp->stats,
0629 NFSD_MAY_BYPASS_GSS_ON_ROOT);
0630 fh_put(&argp->fh);
0631 return rpc_success;
0632 }
0633
0634
0635
0636
0637
0638
0639 #define ST 1
0640 #define FH 8
0641 #define AT 18
0642
0643 static const struct svc_procedure nfsd_procedures2[18] = {
0644 [NFSPROC_NULL] = {
0645 .pc_func = nfsd_proc_null,
0646 .pc_decode = nfssvc_decode_voidarg,
0647 .pc_encode = nfssvc_encode_voidres,
0648 .pc_argsize = sizeof(struct nfsd_voidargs),
0649 .pc_ressize = sizeof(struct nfsd_voidres),
0650 .pc_cachetype = RC_NOCACHE,
0651 .pc_xdrressize = 0,
0652 .pc_name = "NULL",
0653 },
0654 [NFSPROC_GETATTR] = {
0655 .pc_func = nfsd_proc_getattr,
0656 .pc_decode = nfssvc_decode_fhandleargs,
0657 .pc_encode = nfssvc_encode_attrstatres,
0658 .pc_release = nfssvc_release_attrstat,
0659 .pc_argsize = sizeof(struct nfsd_fhandle),
0660 .pc_ressize = sizeof(struct nfsd_attrstat),
0661 .pc_cachetype = RC_NOCACHE,
0662 .pc_xdrressize = ST+AT,
0663 .pc_name = "GETATTR",
0664 },
0665 [NFSPROC_SETATTR] = {
0666 .pc_func = nfsd_proc_setattr,
0667 .pc_decode = nfssvc_decode_sattrargs,
0668 .pc_encode = nfssvc_encode_attrstatres,
0669 .pc_release = nfssvc_release_attrstat,
0670 .pc_argsize = sizeof(struct nfsd_sattrargs),
0671 .pc_ressize = sizeof(struct nfsd_attrstat),
0672 .pc_cachetype = RC_REPLBUFF,
0673 .pc_xdrressize = ST+AT,
0674 .pc_name = "SETATTR",
0675 },
0676 [NFSPROC_ROOT] = {
0677 .pc_func = nfsd_proc_root,
0678 .pc_decode = nfssvc_decode_voidarg,
0679 .pc_encode = nfssvc_encode_voidres,
0680 .pc_argsize = sizeof(struct nfsd_voidargs),
0681 .pc_ressize = sizeof(struct nfsd_voidres),
0682 .pc_cachetype = RC_NOCACHE,
0683 .pc_xdrressize = 0,
0684 .pc_name = "ROOT",
0685 },
0686 [NFSPROC_LOOKUP] = {
0687 .pc_func = nfsd_proc_lookup,
0688 .pc_decode = nfssvc_decode_diropargs,
0689 .pc_encode = nfssvc_encode_diropres,
0690 .pc_release = nfssvc_release_diropres,
0691 .pc_argsize = sizeof(struct nfsd_diropargs),
0692 .pc_ressize = sizeof(struct nfsd_diropres),
0693 .pc_cachetype = RC_NOCACHE,
0694 .pc_xdrressize = ST+FH+AT,
0695 .pc_name = "LOOKUP",
0696 },
0697 [NFSPROC_READLINK] = {
0698 .pc_func = nfsd_proc_readlink,
0699 .pc_decode = nfssvc_decode_fhandleargs,
0700 .pc_encode = nfssvc_encode_readlinkres,
0701 .pc_argsize = sizeof(struct nfsd_fhandle),
0702 .pc_ressize = sizeof(struct nfsd_readlinkres),
0703 .pc_cachetype = RC_NOCACHE,
0704 .pc_xdrressize = ST+1+NFS_MAXPATHLEN/4,
0705 .pc_name = "READLINK",
0706 },
0707 [NFSPROC_READ] = {
0708 .pc_func = nfsd_proc_read,
0709 .pc_decode = nfssvc_decode_readargs,
0710 .pc_encode = nfssvc_encode_readres,
0711 .pc_release = nfssvc_release_readres,
0712 .pc_argsize = sizeof(struct nfsd_readargs),
0713 .pc_ressize = sizeof(struct nfsd_readres),
0714 .pc_cachetype = RC_NOCACHE,
0715 .pc_xdrressize = ST+AT+1+NFSSVC_MAXBLKSIZE_V2/4,
0716 .pc_name = "READ",
0717 },
0718 [NFSPROC_WRITECACHE] = {
0719 .pc_func = nfsd_proc_writecache,
0720 .pc_decode = nfssvc_decode_voidarg,
0721 .pc_encode = nfssvc_encode_voidres,
0722 .pc_argsize = sizeof(struct nfsd_voidargs),
0723 .pc_ressize = sizeof(struct nfsd_voidres),
0724 .pc_cachetype = RC_NOCACHE,
0725 .pc_xdrressize = 0,
0726 .pc_name = "WRITECACHE",
0727 },
0728 [NFSPROC_WRITE] = {
0729 .pc_func = nfsd_proc_write,
0730 .pc_decode = nfssvc_decode_writeargs,
0731 .pc_encode = nfssvc_encode_attrstatres,
0732 .pc_release = nfssvc_release_attrstat,
0733 .pc_argsize = sizeof(struct nfsd_writeargs),
0734 .pc_ressize = sizeof(struct nfsd_attrstat),
0735 .pc_cachetype = RC_REPLBUFF,
0736 .pc_xdrressize = ST+AT,
0737 .pc_name = "WRITE",
0738 },
0739 [NFSPROC_CREATE] = {
0740 .pc_func = nfsd_proc_create,
0741 .pc_decode = nfssvc_decode_createargs,
0742 .pc_encode = nfssvc_encode_diropres,
0743 .pc_release = nfssvc_release_diropres,
0744 .pc_argsize = sizeof(struct nfsd_createargs),
0745 .pc_ressize = sizeof(struct nfsd_diropres),
0746 .pc_cachetype = RC_REPLBUFF,
0747 .pc_xdrressize = ST+FH+AT,
0748 .pc_name = "CREATE",
0749 },
0750 [NFSPROC_REMOVE] = {
0751 .pc_func = nfsd_proc_remove,
0752 .pc_decode = nfssvc_decode_diropargs,
0753 .pc_encode = nfssvc_encode_statres,
0754 .pc_argsize = sizeof(struct nfsd_diropargs),
0755 .pc_ressize = sizeof(struct nfsd_stat),
0756 .pc_cachetype = RC_REPLSTAT,
0757 .pc_xdrressize = ST,
0758 .pc_name = "REMOVE",
0759 },
0760 [NFSPROC_RENAME] = {
0761 .pc_func = nfsd_proc_rename,
0762 .pc_decode = nfssvc_decode_renameargs,
0763 .pc_encode = nfssvc_encode_statres,
0764 .pc_argsize = sizeof(struct nfsd_renameargs),
0765 .pc_ressize = sizeof(struct nfsd_stat),
0766 .pc_cachetype = RC_REPLSTAT,
0767 .pc_xdrressize = ST,
0768 .pc_name = "RENAME",
0769 },
0770 [NFSPROC_LINK] = {
0771 .pc_func = nfsd_proc_link,
0772 .pc_decode = nfssvc_decode_linkargs,
0773 .pc_encode = nfssvc_encode_statres,
0774 .pc_argsize = sizeof(struct nfsd_linkargs),
0775 .pc_ressize = sizeof(struct nfsd_stat),
0776 .pc_cachetype = RC_REPLSTAT,
0777 .pc_xdrressize = ST,
0778 .pc_name = "LINK",
0779 },
0780 [NFSPROC_SYMLINK] = {
0781 .pc_func = nfsd_proc_symlink,
0782 .pc_decode = nfssvc_decode_symlinkargs,
0783 .pc_encode = nfssvc_encode_statres,
0784 .pc_argsize = sizeof(struct nfsd_symlinkargs),
0785 .pc_ressize = sizeof(struct nfsd_stat),
0786 .pc_cachetype = RC_REPLSTAT,
0787 .pc_xdrressize = ST,
0788 .pc_name = "SYMLINK",
0789 },
0790 [NFSPROC_MKDIR] = {
0791 .pc_func = nfsd_proc_mkdir,
0792 .pc_decode = nfssvc_decode_createargs,
0793 .pc_encode = nfssvc_encode_diropres,
0794 .pc_release = nfssvc_release_diropres,
0795 .pc_argsize = sizeof(struct nfsd_createargs),
0796 .pc_ressize = sizeof(struct nfsd_diropres),
0797 .pc_cachetype = RC_REPLBUFF,
0798 .pc_xdrressize = ST+FH+AT,
0799 .pc_name = "MKDIR",
0800 },
0801 [NFSPROC_RMDIR] = {
0802 .pc_func = nfsd_proc_rmdir,
0803 .pc_decode = nfssvc_decode_diropargs,
0804 .pc_encode = nfssvc_encode_statres,
0805 .pc_argsize = sizeof(struct nfsd_diropargs),
0806 .pc_ressize = sizeof(struct nfsd_stat),
0807 .pc_cachetype = RC_REPLSTAT,
0808 .pc_xdrressize = ST,
0809 .pc_name = "RMDIR",
0810 },
0811 [NFSPROC_READDIR] = {
0812 .pc_func = nfsd_proc_readdir,
0813 .pc_decode = nfssvc_decode_readdirargs,
0814 .pc_encode = nfssvc_encode_readdirres,
0815 .pc_argsize = sizeof(struct nfsd_readdirargs),
0816 .pc_ressize = sizeof(struct nfsd_readdirres),
0817 .pc_cachetype = RC_NOCACHE,
0818 .pc_name = "READDIR",
0819 },
0820 [NFSPROC_STATFS] = {
0821 .pc_func = nfsd_proc_statfs,
0822 .pc_decode = nfssvc_decode_fhandleargs,
0823 .pc_encode = nfssvc_encode_statfsres,
0824 .pc_argsize = sizeof(struct nfsd_fhandle),
0825 .pc_ressize = sizeof(struct nfsd_statfsres),
0826 .pc_cachetype = RC_NOCACHE,
0827 .pc_xdrressize = ST+5,
0828 .pc_name = "STATFS",
0829 },
0830 };
0831
0832
0833 static unsigned int nfsd_count2[ARRAY_SIZE(nfsd_procedures2)];
0834 const struct svc_version nfsd_version2 = {
0835 .vs_vers = 2,
0836 .vs_nproc = 18,
0837 .vs_proc = nfsd_procedures2,
0838 .vs_count = nfsd_count2,
0839 .vs_dispatch = nfsd_dispatch,
0840 .vs_xdrsize = NFS2_SVC_XDRSIZE,
0841 };
0842
0843
0844
0845
0846 __be32
0847 nfserrno (int errno)
0848 {
0849 static struct {
0850 __be32 nfserr;
0851 int syserr;
0852 } nfs_errtbl[] = {
0853 { nfs_ok, 0 },
0854 { nfserr_perm, -EPERM },
0855 { nfserr_noent, -ENOENT },
0856 { nfserr_io, -EIO },
0857 { nfserr_nxio, -ENXIO },
0858 { nfserr_fbig, -E2BIG },
0859 { nfserr_stale, -EBADF },
0860 { nfserr_acces, -EACCES },
0861 { nfserr_exist, -EEXIST },
0862 { nfserr_xdev, -EXDEV },
0863 { nfserr_mlink, -EMLINK },
0864 { nfserr_nodev, -ENODEV },
0865 { nfserr_notdir, -ENOTDIR },
0866 { nfserr_isdir, -EISDIR },
0867 { nfserr_inval, -EINVAL },
0868 { nfserr_fbig, -EFBIG },
0869 { nfserr_nospc, -ENOSPC },
0870 { nfserr_rofs, -EROFS },
0871 { nfserr_mlink, -EMLINK },
0872 { nfserr_nametoolong, -ENAMETOOLONG },
0873 { nfserr_notempty, -ENOTEMPTY },
0874 #ifdef EDQUOT
0875 { nfserr_dquot, -EDQUOT },
0876 #endif
0877 { nfserr_stale, -ESTALE },
0878 { nfserr_jukebox, -ETIMEDOUT },
0879 { nfserr_jukebox, -ERESTARTSYS },
0880 { nfserr_jukebox, -EAGAIN },
0881 { nfserr_jukebox, -EWOULDBLOCK },
0882 { nfserr_jukebox, -ENOMEM },
0883 { nfserr_io, -ETXTBSY },
0884 { nfserr_notsupp, -EOPNOTSUPP },
0885 { nfserr_toosmall, -ETOOSMALL },
0886 { nfserr_serverfault, -ESERVERFAULT },
0887 { nfserr_serverfault, -ENFILE },
0888 { nfserr_io, -EREMOTEIO },
0889 { nfserr_stale, -EOPENSTALE },
0890 { nfserr_io, -EUCLEAN },
0891 { nfserr_perm, -ENOKEY },
0892 { nfserr_no_grace, -ENOGRACE},
0893 };
0894 int i;
0895
0896 for (i = 0; i < ARRAY_SIZE(nfs_errtbl); i++) {
0897 if (nfs_errtbl[i].syserr == errno)
0898 return nfs_errtbl[i].nfserr;
0899 }
0900 WARN_ONCE(1, "nfsd: non-standard errno: %d\n", errno);
0901 return nfserr_io;
0902 }
0903