0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013 #include <linux/param.h>
0014 #include <linux/time.h>
0015 #include <linux/mm.h>
0016 #include <linux/errno.h>
0017 #include <linux/string.h>
0018 #include <linux/in.h>
0019 #include <linux/pagemap.h>
0020 #include <linux/proc_fs.h>
0021 #include <linux/sunrpc/clnt.h>
0022 #include <linux/nfs.h>
0023 #include <linux/nfs2.h>
0024 #include <linux/nfs_fs.h>
0025 #include "nfstrace.h"
0026 #include "internal.h"
0027
0028 #define NFSDBG_FACILITY NFSDBG_XDR
0029
0030
0031 #define errno_NFSERR_IO EIO
0032
0033
0034
0035
0036
0037 #define NFS_pagepad_sz (1)
0038 #define NFS_fhandle_sz (8)
0039 #define NFS_sattr_sz (8)
0040 #define NFS_filename_sz (1+(NFS2_MAXNAMLEN>>2))
0041 #define NFS_path_sz (1+(NFS2_MAXPATHLEN>>2))
0042 #define NFS_fattr_sz (17)
0043 #define NFS_info_sz (5)
0044 #define NFS_entry_sz (NFS_filename_sz+3)
0045
0046 #define NFS_diropargs_sz (NFS_fhandle_sz+NFS_filename_sz)
0047 #define NFS_removeargs_sz (NFS_fhandle_sz+NFS_filename_sz)
0048 #define NFS_sattrargs_sz (NFS_fhandle_sz+NFS_sattr_sz)
0049 #define NFS_readlinkargs_sz (NFS_fhandle_sz)
0050 #define NFS_readargs_sz (NFS_fhandle_sz+3)
0051 #define NFS_writeargs_sz (NFS_fhandle_sz+4)
0052 #define NFS_createargs_sz (NFS_diropargs_sz+NFS_sattr_sz)
0053 #define NFS_renameargs_sz (NFS_diropargs_sz+NFS_diropargs_sz)
0054 #define NFS_linkargs_sz (NFS_fhandle_sz+NFS_diropargs_sz)
0055 #define NFS_symlinkargs_sz (NFS_diropargs_sz+1+NFS_sattr_sz)
0056 #define NFS_readdirargs_sz (NFS_fhandle_sz+2)
0057
0058 #define NFS_attrstat_sz (1+NFS_fattr_sz)
0059 #define NFS_diropres_sz (1+NFS_fhandle_sz+NFS_fattr_sz)
0060 #define NFS_readlinkres_sz (2+NFS_pagepad_sz)
0061 #define NFS_readres_sz (1+NFS_fattr_sz+1+NFS_pagepad_sz)
0062 #define NFS_writeres_sz (NFS_attrstat_sz)
0063 #define NFS_stat_sz (1)
0064 #define NFS_readdirres_sz (1+NFS_pagepad_sz)
0065 #define NFS_statfsres_sz (1+NFS_info_sz)
0066
0067 static int nfs_stat_to_errno(enum nfs_stat);
0068
0069
0070
0071
0072
0073
0074
0075
0076
0077
0078
0079
0080 static struct user_namespace *rpc_userns(const struct rpc_clnt *clnt)
0081 {
0082 if (clnt && clnt->cl_cred)
0083 return clnt->cl_cred->user_ns;
0084 return &init_user_ns;
0085 }
0086
0087 static struct user_namespace *rpc_rqst_userns(const struct rpc_rqst *rqstp)
0088 {
0089 if (rqstp->rq_task)
0090 return rpc_userns(rqstp->rq_task->tk_client);
0091 return &init_user_ns;
0092 }
0093
0094
0095
0096
0097 static int decode_nfsdata(struct xdr_stream *xdr, struct nfs_pgio_res *result)
0098 {
0099 u32 recvd, count;
0100 __be32 *p;
0101
0102 p = xdr_inline_decode(xdr, 4);
0103 if (unlikely(!p))
0104 return -EIO;
0105 count = be32_to_cpup(p);
0106 recvd = xdr_read_pages(xdr, count);
0107 if (unlikely(count > recvd))
0108 goto out_cheating;
0109 out:
0110 result->eof = 0;
0111 result->count = count;
0112 return count;
0113 out_cheating:
0114 dprintk("NFS: server cheating in read result: "
0115 "count %u > recvd %u\n", count, recvd);
0116 count = recvd;
0117 goto out;
0118 }
0119
0120
0121
0122
0123
0124
0125
0126
0127
0128
0129
0130
0131
0132
0133
0134
0135
0136
0137
0138
0139
0140
0141
0142 static int decode_stat(struct xdr_stream *xdr, enum nfs_stat *status)
0143 {
0144 __be32 *p;
0145
0146 p = xdr_inline_decode(xdr, 4);
0147 if (unlikely(!p))
0148 return -EIO;
0149 if (unlikely(*p != cpu_to_be32(NFS_OK)))
0150 goto out_status;
0151 *status = 0;
0152 return 0;
0153 out_status:
0154 *status = be32_to_cpup(p);
0155 trace_nfs_xdr_status(xdr, (int)*status);
0156 return 0;
0157 }
0158
0159
0160
0161
0162
0163
0164
0165
0166
0167
0168
0169
0170
0171
0172 static __be32 *xdr_decode_ftype(__be32 *p, u32 *type)
0173 {
0174 *type = be32_to_cpup(p++);
0175 if (unlikely(*type > NF2FIFO))
0176 *type = NFBAD;
0177 return p;
0178 }
0179
0180
0181
0182
0183
0184
0185 static void encode_fhandle(struct xdr_stream *xdr, const struct nfs_fh *fh)
0186 {
0187 __be32 *p;
0188
0189 p = xdr_reserve_space(xdr, NFS2_FHSIZE);
0190 memcpy(p, fh->data, NFS2_FHSIZE);
0191 }
0192
0193 static int decode_fhandle(struct xdr_stream *xdr, struct nfs_fh *fh)
0194 {
0195 __be32 *p;
0196
0197 p = xdr_inline_decode(xdr, NFS2_FHSIZE);
0198 if (unlikely(!p))
0199 return -EIO;
0200 fh->size = NFS2_FHSIZE;
0201 memcpy(fh->data, p, NFS2_FHSIZE);
0202 return 0;
0203 }
0204
0205
0206
0207
0208
0209
0210
0211
0212
0213 static __be32 *xdr_encode_time(__be32 *p, const struct timespec64 *timep)
0214 {
0215 *p++ = cpu_to_be32((u32)timep->tv_sec);
0216 if (timep->tv_nsec != 0)
0217 *p++ = cpu_to_be32(timep->tv_nsec / NSEC_PER_USEC);
0218 else
0219 *p++ = cpu_to_be32(0);
0220 return p;
0221 }
0222
0223
0224
0225
0226
0227
0228
0229
0230 static __be32 *xdr_encode_current_server_time(__be32 *p,
0231 const struct timespec64 *timep)
0232 {
0233 *p++ = cpu_to_be32(timep->tv_sec);
0234 *p++ = cpu_to_be32(1000000);
0235 return p;
0236 }
0237
0238 static __be32 *xdr_decode_time(__be32 *p, struct timespec64 *timep)
0239 {
0240 timep->tv_sec = be32_to_cpup(p++);
0241 timep->tv_nsec = be32_to_cpup(p++) * NSEC_PER_USEC;
0242 return p;
0243 }
0244
0245
0246
0247
0248
0249
0250
0251
0252
0253
0254
0255
0256
0257
0258
0259
0260
0261
0262
0263
0264
0265
0266 static int decode_fattr(struct xdr_stream *xdr, struct nfs_fattr *fattr,
0267 struct user_namespace *userns)
0268 {
0269 u32 rdev, type;
0270 __be32 *p;
0271
0272 p = xdr_inline_decode(xdr, NFS_fattr_sz << 2);
0273 if (unlikely(!p))
0274 return -EIO;
0275
0276 fattr->valid |= NFS_ATTR_FATTR_V2;
0277
0278 p = xdr_decode_ftype(p, &type);
0279
0280 fattr->mode = be32_to_cpup(p++);
0281 fattr->nlink = be32_to_cpup(p++);
0282 fattr->uid = make_kuid(userns, be32_to_cpup(p++));
0283 if (!uid_valid(fattr->uid))
0284 goto out_uid;
0285 fattr->gid = make_kgid(userns, be32_to_cpup(p++));
0286 if (!gid_valid(fattr->gid))
0287 goto out_gid;
0288
0289 fattr->size = be32_to_cpup(p++);
0290 fattr->du.nfs2.blocksize = be32_to_cpup(p++);
0291
0292 rdev = be32_to_cpup(p++);
0293 fattr->rdev = new_decode_dev(rdev);
0294 if (type == (u32)NFCHR && rdev == (u32)NFS2_FIFO_DEV) {
0295 fattr->mode = (fattr->mode & ~S_IFMT) | S_IFIFO;
0296 fattr->rdev = 0;
0297 }
0298
0299 fattr->du.nfs2.blocks = be32_to_cpup(p++);
0300 fattr->fsid.major = be32_to_cpup(p++);
0301 fattr->fsid.minor = 0;
0302 fattr->fileid = be32_to_cpup(p++);
0303
0304 p = xdr_decode_time(p, &fattr->atime);
0305 p = xdr_decode_time(p, &fattr->mtime);
0306 xdr_decode_time(p, &fattr->ctime);
0307 fattr->change_attr = nfs_timespec_to_change_attr(&fattr->ctime);
0308
0309 return 0;
0310 out_uid:
0311 dprintk("NFS: returned invalid uid\n");
0312 return -EINVAL;
0313 out_gid:
0314 dprintk("NFS: returned invalid gid\n");
0315 return -EINVAL;
0316 }
0317
0318
0319
0320
0321
0322
0323
0324
0325
0326
0327
0328
0329
0330
0331 #define NFS2_SATTR_NOT_SET (0xffffffff)
0332
0333 static __be32 *xdr_time_not_set(__be32 *p)
0334 {
0335 *p++ = cpu_to_be32(NFS2_SATTR_NOT_SET);
0336 *p++ = cpu_to_be32(NFS2_SATTR_NOT_SET);
0337 return p;
0338 }
0339
0340 static void encode_sattr(struct xdr_stream *xdr, const struct iattr *attr,
0341 struct user_namespace *userns)
0342 {
0343 __be32 *p;
0344
0345 p = xdr_reserve_space(xdr, NFS_sattr_sz << 2);
0346
0347 if (attr->ia_valid & ATTR_MODE)
0348 *p++ = cpu_to_be32(attr->ia_mode);
0349 else
0350 *p++ = cpu_to_be32(NFS2_SATTR_NOT_SET);
0351 if (attr->ia_valid & ATTR_UID)
0352 *p++ = cpu_to_be32(from_kuid_munged(userns, attr->ia_uid));
0353 else
0354 *p++ = cpu_to_be32(NFS2_SATTR_NOT_SET);
0355 if (attr->ia_valid & ATTR_GID)
0356 *p++ = cpu_to_be32(from_kgid_munged(userns, attr->ia_gid));
0357 else
0358 *p++ = cpu_to_be32(NFS2_SATTR_NOT_SET);
0359 if (attr->ia_valid & ATTR_SIZE)
0360 *p++ = cpu_to_be32((u32)attr->ia_size);
0361 else
0362 *p++ = cpu_to_be32(NFS2_SATTR_NOT_SET);
0363
0364 if (attr->ia_valid & ATTR_ATIME_SET)
0365 p = xdr_encode_time(p, &attr->ia_atime);
0366 else if (attr->ia_valid & ATTR_ATIME)
0367 p = xdr_encode_current_server_time(p, &attr->ia_atime);
0368 else
0369 p = xdr_time_not_set(p);
0370 if (attr->ia_valid & ATTR_MTIME_SET)
0371 xdr_encode_time(p, &attr->ia_mtime);
0372 else if (attr->ia_valid & ATTR_MTIME)
0373 xdr_encode_current_server_time(p, &attr->ia_mtime);
0374 else
0375 xdr_time_not_set(p);
0376 }
0377
0378
0379
0380
0381
0382
0383 static void encode_filename(struct xdr_stream *xdr,
0384 const char *name, u32 length)
0385 {
0386 __be32 *p;
0387
0388 WARN_ON_ONCE(length > NFS2_MAXNAMLEN);
0389 p = xdr_reserve_space(xdr, 4 + length);
0390 xdr_encode_opaque(p, name, length);
0391 }
0392
0393 static int decode_filename_inline(struct xdr_stream *xdr,
0394 const char **name, u32 *length)
0395 {
0396 __be32 *p;
0397 u32 count;
0398
0399 p = xdr_inline_decode(xdr, 4);
0400 if (unlikely(!p))
0401 return -EIO;
0402 count = be32_to_cpup(p);
0403 if (count > NFS3_MAXNAMLEN)
0404 goto out_nametoolong;
0405 p = xdr_inline_decode(xdr, count);
0406 if (unlikely(!p))
0407 return -EIO;
0408 *name = (const char *)p;
0409 *length = count;
0410 return 0;
0411 out_nametoolong:
0412 dprintk("NFS: returned filename too long: %u\n", count);
0413 return -ENAMETOOLONG;
0414 }
0415
0416
0417
0418
0419
0420
0421 static void encode_path(struct xdr_stream *xdr, struct page **pages, u32 length)
0422 {
0423 __be32 *p;
0424
0425 p = xdr_reserve_space(xdr, 4);
0426 *p = cpu_to_be32(length);
0427 xdr_write_pages(xdr, pages, 0, length);
0428 }
0429
0430 static int decode_path(struct xdr_stream *xdr)
0431 {
0432 u32 length, recvd;
0433 __be32 *p;
0434
0435 p = xdr_inline_decode(xdr, 4);
0436 if (unlikely(!p))
0437 return -EIO;
0438 length = be32_to_cpup(p);
0439 if (unlikely(length >= xdr->buf->page_len || length > NFS_MAXPATHLEN))
0440 goto out_size;
0441 recvd = xdr_read_pages(xdr, length);
0442 if (unlikely(length > recvd))
0443 goto out_cheating;
0444 xdr_terminate_string(xdr->buf, length);
0445 return 0;
0446 out_size:
0447 dprintk("NFS: returned pathname too long: %u\n", length);
0448 return -ENAMETOOLONG;
0449 out_cheating:
0450 dprintk("NFS: server cheating in pathname result: "
0451 "length %u > received %u\n", length, recvd);
0452 return -EIO;
0453 }
0454
0455
0456
0457
0458
0459
0460
0461
0462
0463
0464
0465 static int decode_attrstat(struct xdr_stream *xdr, struct nfs_fattr *result,
0466 __u32 *op_status,
0467 struct user_namespace *userns)
0468 {
0469 enum nfs_stat status;
0470 int error;
0471
0472 error = decode_stat(xdr, &status);
0473 if (unlikely(error))
0474 goto out;
0475 if (op_status)
0476 *op_status = status;
0477 if (status != NFS_OK)
0478 goto out_default;
0479 error = decode_fattr(xdr, result, userns);
0480 out:
0481 return error;
0482 out_default:
0483 return nfs_stat_to_errno(status);
0484 }
0485
0486
0487
0488
0489
0490
0491
0492
0493
0494 static void encode_diropargs(struct xdr_stream *xdr, const struct nfs_fh *fh,
0495 const char *name, u32 length)
0496 {
0497 encode_fhandle(xdr, fh);
0498 encode_filename(xdr, name, length);
0499 }
0500
0501
0502
0503
0504
0505
0506
0507
0508
0509
0510
0511
0512
0513
0514 static int decode_diropok(struct xdr_stream *xdr, struct nfs_diropok *result,
0515 struct user_namespace *userns)
0516 {
0517 int error;
0518
0519 error = decode_fhandle(xdr, result->fh);
0520 if (unlikely(error))
0521 goto out;
0522 error = decode_fattr(xdr, result->fattr, userns);
0523 out:
0524 return error;
0525 }
0526
0527 static int decode_diropres(struct xdr_stream *xdr, struct nfs_diropok *result,
0528 struct user_namespace *userns)
0529 {
0530 enum nfs_stat status;
0531 int error;
0532
0533 error = decode_stat(xdr, &status);
0534 if (unlikely(error))
0535 goto out;
0536 if (status != NFS_OK)
0537 goto out_default;
0538 error = decode_diropok(xdr, result, userns);
0539 out:
0540 return error;
0541 out_default:
0542 return nfs_stat_to_errno(status);
0543 }
0544
0545
0546
0547
0548
0549
0550
0551
0552
0553 static void nfs2_xdr_enc_fhandle(struct rpc_rqst *req,
0554 struct xdr_stream *xdr,
0555 const void *data)
0556 {
0557 const struct nfs_fh *fh = data;
0558
0559 encode_fhandle(xdr, fh);
0560 }
0561
0562
0563
0564
0565
0566
0567
0568
0569
0570 static void nfs2_xdr_enc_sattrargs(struct rpc_rqst *req,
0571 struct xdr_stream *xdr,
0572 const void *data)
0573 {
0574 const struct nfs_sattrargs *args = data;
0575
0576 encode_fhandle(xdr, args->fh);
0577 encode_sattr(xdr, args->sattr, rpc_rqst_userns(req));
0578 }
0579
0580 static void nfs2_xdr_enc_diropargs(struct rpc_rqst *req,
0581 struct xdr_stream *xdr,
0582 const void *data)
0583 {
0584 const struct nfs_diropargs *args = data;
0585
0586 encode_diropargs(xdr, args->fh, args->name, args->len);
0587 }
0588
0589 static void nfs2_xdr_enc_readlinkargs(struct rpc_rqst *req,
0590 struct xdr_stream *xdr,
0591 const void *data)
0592 {
0593 const struct nfs_readlinkargs *args = data;
0594
0595 encode_fhandle(xdr, args->fh);
0596 rpc_prepare_reply_pages(req, args->pages, args->pgbase, args->pglen,
0597 NFS_readlinkres_sz - NFS_pagepad_sz);
0598 }
0599
0600
0601
0602
0603
0604
0605
0606
0607
0608
0609
0610 static void encode_readargs(struct xdr_stream *xdr,
0611 const struct nfs_pgio_args *args)
0612 {
0613 u32 offset = args->offset;
0614 u32 count = args->count;
0615 __be32 *p;
0616
0617 encode_fhandle(xdr, args->fh);
0618
0619 p = xdr_reserve_space(xdr, 4 + 4 + 4);
0620 *p++ = cpu_to_be32(offset);
0621 *p++ = cpu_to_be32(count);
0622 *p = cpu_to_be32(count);
0623 }
0624
0625 static void nfs2_xdr_enc_readargs(struct rpc_rqst *req,
0626 struct xdr_stream *xdr,
0627 const void *data)
0628 {
0629 const struct nfs_pgio_args *args = data;
0630
0631 encode_readargs(xdr, args);
0632 rpc_prepare_reply_pages(req, args->pages, args->pgbase, args->count,
0633 NFS_readres_sz - NFS_pagepad_sz);
0634 req->rq_rcv_buf.flags |= XDRBUF_READ;
0635 }
0636
0637
0638
0639
0640
0641
0642
0643
0644
0645
0646
0647
0648 static void encode_writeargs(struct xdr_stream *xdr,
0649 const struct nfs_pgio_args *args)
0650 {
0651 u32 offset = args->offset;
0652 u32 count = args->count;
0653 __be32 *p;
0654
0655 encode_fhandle(xdr, args->fh);
0656
0657 p = xdr_reserve_space(xdr, 4 + 4 + 4 + 4);
0658 *p++ = cpu_to_be32(offset);
0659 *p++ = cpu_to_be32(offset);
0660 *p++ = cpu_to_be32(count);
0661
0662
0663 *p = cpu_to_be32(count);
0664 xdr_write_pages(xdr, args->pages, args->pgbase, count);
0665 }
0666
0667 static void nfs2_xdr_enc_writeargs(struct rpc_rqst *req,
0668 struct xdr_stream *xdr,
0669 const void *data)
0670 {
0671 const struct nfs_pgio_args *args = data;
0672
0673 encode_writeargs(xdr, args);
0674 xdr->buf->flags |= XDRBUF_WRITE;
0675 }
0676
0677
0678
0679
0680
0681
0682
0683
0684
0685 static void nfs2_xdr_enc_createargs(struct rpc_rqst *req,
0686 struct xdr_stream *xdr,
0687 const void *data)
0688 {
0689 const struct nfs_createargs *args = data;
0690
0691 encode_diropargs(xdr, args->fh, args->name, args->len);
0692 encode_sattr(xdr, args->sattr, rpc_rqst_userns(req));
0693 }
0694
0695 static void nfs2_xdr_enc_removeargs(struct rpc_rqst *req,
0696 struct xdr_stream *xdr,
0697 const void *data)
0698 {
0699 const struct nfs_removeargs *args = data;
0700
0701 encode_diropargs(xdr, args->fh, args->name.name, args->name.len);
0702 }
0703
0704
0705
0706
0707
0708
0709
0710
0711
0712 static void nfs2_xdr_enc_renameargs(struct rpc_rqst *req,
0713 struct xdr_stream *xdr,
0714 const void *data)
0715 {
0716 const struct nfs_renameargs *args = data;
0717 const struct qstr *old = args->old_name;
0718 const struct qstr *new = args->new_name;
0719
0720 encode_diropargs(xdr, args->old_dir, old->name, old->len);
0721 encode_diropargs(xdr, args->new_dir, new->name, new->len);
0722 }
0723
0724
0725
0726
0727
0728
0729
0730
0731
0732 static void nfs2_xdr_enc_linkargs(struct rpc_rqst *req,
0733 struct xdr_stream *xdr,
0734 const void *data)
0735 {
0736 const struct nfs_linkargs *args = data;
0737
0738 encode_fhandle(xdr, args->fromfh);
0739 encode_diropargs(xdr, args->tofh, args->toname, args->tolen);
0740 }
0741
0742
0743
0744
0745
0746
0747
0748
0749
0750
0751 static void nfs2_xdr_enc_symlinkargs(struct rpc_rqst *req,
0752 struct xdr_stream *xdr,
0753 const void *data)
0754 {
0755 const struct nfs_symlinkargs *args = data;
0756
0757 encode_diropargs(xdr, args->fromfh, args->fromname, args->fromlen);
0758 encode_path(xdr, args->pages, args->pathlen);
0759 encode_sattr(xdr, args->sattr, rpc_rqst_userns(req));
0760 }
0761
0762
0763
0764
0765
0766
0767
0768
0769
0770
0771 static void encode_readdirargs(struct xdr_stream *xdr,
0772 const struct nfs_readdirargs *args)
0773 {
0774 __be32 *p;
0775
0776 encode_fhandle(xdr, args->fh);
0777
0778 p = xdr_reserve_space(xdr, 4 + 4);
0779 *p++ = cpu_to_be32(args->cookie);
0780 *p = cpu_to_be32(args->count);
0781 }
0782
0783 static void nfs2_xdr_enc_readdirargs(struct rpc_rqst *req,
0784 struct xdr_stream *xdr,
0785 const void *data)
0786 {
0787 const struct nfs_readdirargs *args = data;
0788
0789 encode_readdirargs(xdr, args);
0790 rpc_prepare_reply_pages(req, args->pages, 0, args->count,
0791 NFS_readdirres_sz - NFS_pagepad_sz);
0792 }
0793
0794
0795
0796
0797
0798
0799
0800
0801 static int nfs2_xdr_dec_stat(struct rpc_rqst *req, struct xdr_stream *xdr,
0802 void *__unused)
0803 {
0804 enum nfs_stat status;
0805 int error;
0806
0807 error = decode_stat(xdr, &status);
0808 if (unlikely(error))
0809 goto out;
0810 if (status != NFS_OK)
0811 goto out_default;
0812 out:
0813 return error;
0814 out_default:
0815 return nfs_stat_to_errno(status);
0816 }
0817
0818 static int nfs2_xdr_dec_attrstat(struct rpc_rqst *req, struct xdr_stream *xdr,
0819 void *result)
0820 {
0821 return decode_attrstat(xdr, result, NULL, rpc_rqst_userns(req));
0822 }
0823
0824 static int nfs2_xdr_dec_diropres(struct rpc_rqst *req, struct xdr_stream *xdr,
0825 void *result)
0826 {
0827 return decode_diropres(xdr, result, rpc_rqst_userns(req));
0828 }
0829
0830
0831
0832
0833
0834
0835
0836
0837
0838
0839
0840 static int nfs2_xdr_dec_readlinkres(struct rpc_rqst *req,
0841 struct xdr_stream *xdr, void *__unused)
0842 {
0843 enum nfs_stat status;
0844 int error;
0845
0846 error = decode_stat(xdr, &status);
0847 if (unlikely(error))
0848 goto out;
0849 if (status != NFS_OK)
0850 goto out_default;
0851 error = decode_path(xdr);
0852 out:
0853 return error;
0854 out_default:
0855 return nfs_stat_to_errno(status);
0856 }
0857
0858
0859
0860
0861
0862
0863
0864
0865
0866
0867
0868
0869 static int nfs2_xdr_dec_readres(struct rpc_rqst *req, struct xdr_stream *xdr,
0870 void *data)
0871 {
0872 struct nfs_pgio_res *result = data;
0873 enum nfs_stat status;
0874 int error;
0875
0876 error = decode_stat(xdr, &status);
0877 if (unlikely(error))
0878 goto out;
0879 result->op_status = status;
0880 if (status != NFS_OK)
0881 goto out_default;
0882 error = decode_fattr(xdr, result->fattr, rpc_rqst_userns(req));
0883 if (unlikely(error))
0884 goto out;
0885 error = decode_nfsdata(xdr, result);
0886 out:
0887 return error;
0888 out_default:
0889 return nfs_stat_to_errno(status);
0890 }
0891
0892 static int nfs2_xdr_dec_writeres(struct rpc_rqst *req, struct xdr_stream *xdr,
0893 void *data)
0894 {
0895 struct nfs_pgio_res *result = data;
0896
0897
0898 result->verf->committed = NFS_FILE_SYNC;
0899 return decode_attrstat(xdr, result->fattr, &result->op_status,
0900 rpc_rqst_userns(req));
0901 }
0902
0903
0904
0905
0906
0907
0908
0909
0910
0911
0912
0913
0914
0915
0916
0917
0918
0919
0920
0921
0922
0923
0924
0925
0926 int nfs2_decode_dirent(struct xdr_stream *xdr, struct nfs_entry *entry,
0927 bool plus)
0928 {
0929 __be32 *p;
0930 int error;
0931
0932 p = xdr_inline_decode(xdr, 4);
0933 if (unlikely(!p))
0934 return -EAGAIN;
0935 if (*p++ == xdr_zero) {
0936 p = xdr_inline_decode(xdr, 4);
0937 if (unlikely(!p))
0938 return -EAGAIN;
0939 if (*p++ == xdr_zero)
0940 return -EAGAIN;
0941 entry->eof = 1;
0942 return -EBADCOOKIE;
0943 }
0944
0945 p = xdr_inline_decode(xdr, 4);
0946 if (unlikely(!p))
0947 return -EAGAIN;
0948 entry->ino = be32_to_cpup(p);
0949
0950 error = decode_filename_inline(xdr, &entry->name, &entry->len);
0951 if (unlikely(error))
0952 return -EAGAIN;
0953
0954
0955
0956
0957
0958 p = xdr_inline_decode(xdr, 4);
0959 if (unlikely(!p))
0960 return -EAGAIN;
0961 entry->cookie = be32_to_cpup(p);
0962
0963 entry->d_type = DT_UNKNOWN;
0964
0965 return 0;
0966 }
0967
0968
0969
0970
0971
0972
0973
0974
0975
0976
0977
0978
0979
0980
0981
0982
0983
0984
0985 static int decode_readdirok(struct xdr_stream *xdr)
0986 {
0987 return xdr_read_pages(xdr, xdr->buf->page_len);
0988 }
0989
0990 static int nfs2_xdr_dec_readdirres(struct rpc_rqst *req,
0991 struct xdr_stream *xdr, void *__unused)
0992 {
0993 enum nfs_stat status;
0994 int error;
0995
0996 error = decode_stat(xdr, &status);
0997 if (unlikely(error))
0998 goto out;
0999 if (status != NFS_OK)
1000 goto out_default;
1001 error = decode_readdirok(xdr);
1002 out:
1003 return error;
1004 out_default:
1005 return nfs_stat_to_errno(status);
1006 }
1007
1008
1009
1010
1011
1012
1013
1014
1015
1016
1017
1018
1019
1020
1021
1022
1023
1024 static int decode_info(struct xdr_stream *xdr, struct nfs2_fsstat *result)
1025 {
1026 __be32 *p;
1027
1028 p = xdr_inline_decode(xdr, NFS_info_sz << 2);
1029 if (unlikely(!p))
1030 return -EIO;
1031 result->tsize = be32_to_cpup(p++);
1032 result->bsize = be32_to_cpup(p++);
1033 result->blocks = be32_to_cpup(p++);
1034 result->bfree = be32_to_cpup(p++);
1035 result->bavail = be32_to_cpup(p);
1036 return 0;
1037 }
1038
1039 static int nfs2_xdr_dec_statfsres(struct rpc_rqst *req, struct xdr_stream *xdr,
1040 void *result)
1041 {
1042 enum nfs_stat status;
1043 int error;
1044
1045 error = decode_stat(xdr, &status);
1046 if (unlikely(error))
1047 goto out;
1048 if (status != NFS_OK)
1049 goto out_default;
1050 error = decode_info(xdr, result);
1051 out:
1052 return error;
1053 out_default:
1054 return nfs_stat_to_errno(status);
1055 }
1056
1057
1058
1059
1060
1061
1062 static const struct {
1063 int stat;
1064 int errno;
1065 } nfs_errtbl[] = {
1066 { NFS_OK, 0 },
1067 { NFSERR_PERM, -EPERM },
1068 { NFSERR_NOENT, -ENOENT },
1069 { NFSERR_IO, -errno_NFSERR_IO},
1070 { NFSERR_NXIO, -ENXIO },
1071
1072 { NFSERR_ACCES, -EACCES },
1073 { NFSERR_EXIST, -EEXIST },
1074 { NFSERR_XDEV, -EXDEV },
1075 { NFSERR_NODEV, -ENODEV },
1076 { NFSERR_NOTDIR, -ENOTDIR },
1077 { NFSERR_ISDIR, -EISDIR },
1078 { NFSERR_INVAL, -EINVAL },
1079 { NFSERR_FBIG, -EFBIG },
1080 { NFSERR_NOSPC, -ENOSPC },
1081 { NFSERR_ROFS, -EROFS },
1082 { NFSERR_MLINK, -EMLINK },
1083 { NFSERR_NAMETOOLONG, -ENAMETOOLONG },
1084 { NFSERR_NOTEMPTY, -ENOTEMPTY },
1085 { NFSERR_DQUOT, -EDQUOT },
1086 { NFSERR_STALE, -ESTALE },
1087 { NFSERR_REMOTE, -EREMOTE },
1088 #ifdef EWFLUSH
1089 { NFSERR_WFLUSH, -EWFLUSH },
1090 #endif
1091 { NFSERR_BADHANDLE, -EBADHANDLE },
1092 { NFSERR_NOT_SYNC, -ENOTSYNC },
1093 { NFSERR_BAD_COOKIE, -EBADCOOKIE },
1094 { NFSERR_NOTSUPP, -ENOTSUPP },
1095 { NFSERR_TOOSMALL, -ETOOSMALL },
1096 { NFSERR_SERVERFAULT, -EREMOTEIO },
1097 { NFSERR_BADTYPE, -EBADTYPE },
1098 { NFSERR_JUKEBOX, -EJUKEBOX },
1099 { -1, -EIO }
1100 };
1101
1102
1103
1104
1105
1106
1107
1108
1109 static int nfs_stat_to_errno(enum nfs_stat status)
1110 {
1111 int i;
1112
1113 for (i = 0; nfs_errtbl[i].stat != -1; i++) {
1114 if (nfs_errtbl[i].stat == (int)status)
1115 return nfs_errtbl[i].errno;
1116 }
1117 dprintk("NFS: Unrecognized nfs status value: %u\n", status);
1118 return nfs_errtbl[i].errno;
1119 }
1120
1121 #define PROC(proc, argtype, restype, timer) \
1122 [NFSPROC_##proc] = { \
1123 .p_proc = NFSPROC_##proc, \
1124 .p_encode = nfs2_xdr_enc_##argtype, \
1125 .p_decode = nfs2_xdr_dec_##restype, \
1126 .p_arglen = NFS_##argtype##_sz, \
1127 .p_replen = NFS_##restype##_sz, \
1128 .p_timer = timer, \
1129 .p_statidx = NFSPROC_##proc, \
1130 .p_name = #proc, \
1131 }
1132 const struct rpc_procinfo nfs_procedures[] = {
1133 PROC(GETATTR, fhandle, attrstat, 1),
1134 PROC(SETATTR, sattrargs, attrstat, 0),
1135 PROC(LOOKUP, diropargs, diropres, 2),
1136 PROC(READLINK, readlinkargs, readlinkres, 3),
1137 PROC(READ, readargs, readres, 3),
1138 PROC(WRITE, writeargs, writeres, 4),
1139 PROC(CREATE, createargs, diropres, 0),
1140 PROC(REMOVE, removeargs, stat, 0),
1141 PROC(RENAME, renameargs, stat, 0),
1142 PROC(LINK, linkargs, stat, 0),
1143 PROC(SYMLINK, symlinkargs, stat, 0),
1144 PROC(MKDIR, createargs, diropres, 0),
1145 PROC(RMDIR, diropargs, stat, 0),
1146 PROC(READDIR, readdirargs, readdirres, 3),
1147 PROC(STATFS, fhandle, statfsres, 0),
1148 };
1149
1150 static unsigned int nfs_version2_counts[ARRAY_SIZE(nfs_procedures)];
1151 const struct rpc_version nfs_version2 = {
1152 .number = 2,
1153 .nrprocs = ARRAY_SIZE(nfs_procedures),
1154 .procs = nfs_procedures,
1155 .counts = nfs_version2_counts,
1156 };