aboutsummaryrefslogtreecommitdiffstats
path: root/fs/nfs/nfs4xdr.c
diff options
context:
space:
mode:
Diffstat (limited to 'fs/nfs/nfs4xdr.c')
-rw-r--r--fs/nfs/nfs4xdr.c147
1 files changed, 90 insertions, 57 deletions
diff --git a/fs/nfs/nfs4xdr.c b/fs/nfs/nfs4xdr.c
index db1ed9c46ede..5a2d64927b35 100644
--- a/fs/nfs/nfs4xdr.c
+++ b/fs/nfs/nfs4xdr.c
@@ -110,7 +110,7 @@ static int nfs4_stat_to_errno(int);
110#define decode_savefh_maxsz (op_decode_hdr_maxsz) 110#define decode_savefh_maxsz (op_decode_hdr_maxsz)
111#define encode_restorefh_maxsz (op_encode_hdr_maxsz) 111#define encode_restorefh_maxsz (op_encode_hdr_maxsz)
112#define decode_restorefh_maxsz (op_decode_hdr_maxsz) 112#define decode_restorefh_maxsz (op_decode_hdr_maxsz)
113#define encode_fsinfo_maxsz (op_encode_hdr_maxsz + 2) 113#define encode_fsinfo_maxsz (encode_getattr_maxsz)
114#define decode_fsinfo_maxsz (op_decode_hdr_maxsz + 11) 114#define decode_fsinfo_maxsz (op_decode_hdr_maxsz + 11)
115#define encode_renew_maxsz (op_encode_hdr_maxsz + 3) 115#define encode_renew_maxsz (op_encode_hdr_maxsz + 3)
116#define decode_renew_maxsz (op_decode_hdr_maxsz) 116#define decode_renew_maxsz (op_decode_hdr_maxsz)
@@ -1191,8 +1191,8 @@ static int encode_readdir(struct xdr_stream *xdr, const struct nfs4_readdir_arg
1191 attrs[1] &= ~FATTR4_WORD1_MOUNTED_ON_FILEID; 1191 attrs[1] &= ~FATTR4_WORD1_MOUNTED_ON_FILEID;
1192 WRITE32(attrs[0] & readdir->bitmask[0]); 1192 WRITE32(attrs[0] & readdir->bitmask[0]);
1193 WRITE32(attrs[1] & readdir->bitmask[1]); 1193 WRITE32(attrs[1] & readdir->bitmask[1]);
1194 dprintk("%s: cookie = %Lu, verifier = 0x%x%x, bitmap = 0x%x%x\n", 1194 dprintk("%s: cookie = %Lu, verifier = %08x:%08x, bitmap = %08x:%08x\n",
1195 __FUNCTION__, 1195 __func__,
1196 (unsigned long long)readdir->cookie, 1196 (unsigned long long)readdir->cookie,
1197 ((u32 *)readdir->verifier.data)[0], 1197 ((u32 *)readdir->verifier.data)[0],
1198 ((u32 *)readdir->verifier.data)[1], 1198 ((u32 *)readdir->verifier.data)[1],
@@ -2241,7 +2241,7 @@ static int decode_op_hdr(struct xdr_stream *xdr, enum nfs_opnum4 expected)
2241 } 2241 }
2242 READ32(nfserr); 2242 READ32(nfserr);
2243 if (nfserr != NFS_OK) 2243 if (nfserr != NFS_OK)
2244 return -nfs4_stat_to_errno(nfserr); 2244 return nfs4_stat_to_errno(nfserr);
2245 return 0; 2245 return 0;
2246} 2246}
2247 2247
@@ -2291,7 +2291,7 @@ static int decode_attr_supported(struct xdr_stream *xdr, uint32_t *bitmap, uint3
2291 bitmap[0] &= ~FATTR4_WORD0_SUPPORTED_ATTRS; 2291 bitmap[0] &= ~FATTR4_WORD0_SUPPORTED_ATTRS;
2292 } else 2292 } else
2293 bitmask[0] = bitmask[1] = 0; 2293 bitmask[0] = bitmask[1] = 0;
2294 dprintk("%s: bitmask=0x%x%x\n", __FUNCTION__, bitmask[0], bitmask[1]); 2294 dprintk("%s: bitmask=%08x:%08x\n", __func__, bitmask[0], bitmask[1]);
2295 return 0; 2295 return 0;
2296} 2296}
2297 2297
@@ -3005,6 +3005,8 @@ static int decode_close(struct xdr_stream *xdr, struct nfs_closeres *res)
3005 int status; 3005 int status;
3006 3006
3007 status = decode_op_hdr(xdr, OP_CLOSE); 3007 status = decode_op_hdr(xdr, OP_CLOSE);
3008 if (status != -EIO)
3009 nfs_increment_open_seqid(status, res->seqid);
3008 if (status) 3010 if (status)
3009 return status; 3011 return status;
3010 READ_BUF(NFS4_STATEID_SIZE); 3012 READ_BUF(NFS4_STATEID_SIZE);
@@ -3296,11 +3298,17 @@ static int decode_lock(struct xdr_stream *xdr, struct nfs_lock_res *res)
3296 int status; 3298 int status;
3297 3299
3298 status = decode_op_hdr(xdr, OP_LOCK); 3300 status = decode_op_hdr(xdr, OP_LOCK);
3301 if (status == -EIO)
3302 goto out;
3299 if (status == 0) { 3303 if (status == 0) {
3300 READ_BUF(NFS4_STATEID_SIZE); 3304 READ_BUF(NFS4_STATEID_SIZE);
3301 COPYMEM(res->stateid.data, NFS4_STATEID_SIZE); 3305 COPYMEM(res->stateid.data, NFS4_STATEID_SIZE);
3302 } else if (status == -NFS4ERR_DENIED) 3306 } else if (status == -NFS4ERR_DENIED)
3303 return decode_lock_denied(xdr, NULL); 3307 status = decode_lock_denied(xdr, NULL);
3308 if (res->open_seqid != NULL)
3309 nfs_increment_open_seqid(status, res->open_seqid);
3310 nfs_increment_lock_seqid(status, res->lock_seqid);
3311out:
3304 return status; 3312 return status;
3305} 3313}
3306 3314
@@ -3319,6 +3327,8 @@ static int decode_locku(struct xdr_stream *xdr, struct nfs_locku_res *res)
3319 int status; 3327 int status;
3320 3328
3321 status = decode_op_hdr(xdr, OP_LOCKU); 3329 status = decode_op_hdr(xdr, OP_LOCKU);
3330 if (status != -EIO)
3331 nfs_increment_lock_seqid(status, res->seqid);
3322 if (status == 0) { 3332 if (status == 0) {
3323 READ_BUF(NFS4_STATEID_SIZE); 3333 READ_BUF(NFS4_STATEID_SIZE);
3324 COPYMEM(res->stateid.data, NFS4_STATEID_SIZE); 3334 COPYMEM(res->stateid.data, NFS4_STATEID_SIZE);
@@ -3384,6 +3394,8 @@ static int decode_open(struct xdr_stream *xdr, struct nfs_openres *res)
3384 int status; 3394 int status;
3385 3395
3386 status = decode_op_hdr(xdr, OP_OPEN); 3396 status = decode_op_hdr(xdr, OP_OPEN);
3397 if (status != -EIO)
3398 nfs_increment_open_seqid(status, res->seqid);
3387 if (status) 3399 if (status)
3388 return status; 3400 return status;
3389 READ_BUF(NFS4_STATEID_SIZE); 3401 READ_BUF(NFS4_STATEID_SIZE);
@@ -3416,6 +3428,8 @@ static int decode_open_confirm(struct xdr_stream *xdr, struct nfs_open_confirmre
3416 int status; 3428 int status;
3417 3429
3418 status = decode_op_hdr(xdr, OP_OPEN_CONFIRM); 3430 status = decode_op_hdr(xdr, OP_OPEN_CONFIRM);
3431 if (status != -EIO)
3432 nfs_increment_open_seqid(status, res->seqid);
3419 if (status) 3433 if (status)
3420 return status; 3434 return status;
3421 READ_BUF(NFS4_STATEID_SIZE); 3435 READ_BUF(NFS4_STATEID_SIZE);
@@ -3429,6 +3443,8 @@ static int decode_open_downgrade(struct xdr_stream *xdr, struct nfs_closeres *re
3429 int status; 3443 int status;
3430 3444
3431 status = decode_op_hdr(xdr, OP_OPEN_DOWNGRADE); 3445 status = decode_op_hdr(xdr, OP_OPEN_DOWNGRADE);
3446 if (status != -EIO)
3447 nfs_increment_open_seqid(status, res->seqid);
3432 if (status) 3448 if (status)
3433 return status; 3449 return status;
3434 READ_BUF(NFS4_STATEID_SIZE); 3450 READ_BUF(NFS4_STATEID_SIZE);
@@ -3481,7 +3497,7 @@ static int decode_readdir(struct xdr_stream *xdr, struct rpc_rqst *req, struct n
3481 size_t hdrlen; 3497 size_t hdrlen;
3482 u32 recvd, pglen = rcvbuf->page_len; 3498 u32 recvd, pglen = rcvbuf->page_len;
3483 __be32 *end, *entry, *p, *kaddr; 3499 __be32 *end, *entry, *p, *kaddr;
3484 unsigned int nr; 3500 unsigned int nr = 0;
3485 int status; 3501 int status;
3486 3502
3487 status = decode_op_hdr(xdr, OP_READDIR); 3503 status = decode_op_hdr(xdr, OP_READDIR);
@@ -3489,8 +3505,8 @@ static int decode_readdir(struct xdr_stream *xdr, struct rpc_rqst *req, struct n
3489 return status; 3505 return status;
3490 READ_BUF(8); 3506 READ_BUF(8);
3491 COPYMEM(readdir->verifier.data, 8); 3507 COPYMEM(readdir->verifier.data, 8);
3492 dprintk("%s: verifier = 0x%x%x\n", 3508 dprintk("%s: verifier = %08x:%08x\n",
3493 __FUNCTION__, 3509 __func__,
3494 ((u32 *)readdir->verifier.data)[0], 3510 ((u32 *)readdir->verifier.data)[0],
3495 ((u32 *)readdir->verifier.data)[1]); 3511 ((u32 *)readdir->verifier.data)[1]);
3496 3512
@@ -3505,7 +3521,12 @@ static int decode_readdir(struct xdr_stream *xdr, struct rpc_rqst *req, struct n
3505 kaddr = p = kmap_atomic(page, KM_USER0); 3521 kaddr = p = kmap_atomic(page, KM_USER0);
3506 end = p + ((pglen + readdir->pgbase) >> 2); 3522 end = p + ((pglen + readdir->pgbase) >> 2);
3507 entry = p; 3523 entry = p;
3508 for (nr = 0; *p++; nr++) { 3524
3525 /* Make sure the packet actually has a value_follows and EOF entry */
3526 if ((entry + 1) > end)
3527 goto short_pkt;
3528
3529 for (; *p++; nr++) {
3509 u32 len, attrlen, xlen; 3530 u32 len, attrlen, xlen;
3510 if (end - p < 3) 3531 if (end - p < 3)
3511 goto short_pkt; 3532 goto short_pkt;
@@ -3532,20 +3553,32 @@ static int decode_readdir(struct xdr_stream *xdr, struct rpc_rqst *req, struct n
3532 p += attrlen; /* attributes */ 3553 p += attrlen; /* attributes */
3533 entry = p; 3554 entry = p;
3534 } 3555 }
3535 if (!nr && (entry[0] != 0 || entry[1] == 0)) 3556 /*
3536 goto short_pkt; 3557 * Apparently some server sends responses that are a valid size, but
3558 * contain no entries, and have value_follows==0 and EOF==0. For
3559 * those, just set the EOF marker.
3560 */
3561 if (!nr && entry[1] == 0) {
3562 dprintk("NFS: readdir reply truncated!\n");
3563 entry[1] = 1;
3564 }
3537out: 3565out:
3538 kunmap_atomic(kaddr, KM_USER0); 3566 kunmap_atomic(kaddr, KM_USER0);
3539 return 0; 3567 return 0;
3540short_pkt: 3568short_pkt:
3569 /*
3570 * When we get a short packet there are 2 possibilities. We can
3571 * return an error, or fix up the response to look like a valid
3572 * response and return what we have so far. If there are no
3573 * entries and the packet was short, then return -EIO. If there
3574 * are valid entries in the response, return them and pretend that
3575 * the call was successful, but incomplete. The caller can retry the
3576 * readdir starting at the last cookie.
3577 */
3541 dprintk("%s: short packet at entry %d\n", __FUNCTION__, nr); 3578 dprintk("%s: short packet at entry %d\n", __FUNCTION__, nr);
3542 entry[0] = entry[1] = 0; 3579 entry[0] = entry[1] = 0;
3543 /* truncate listing ? */ 3580 if (nr)
3544 if (!nr) { 3581 goto out;
3545 dprintk("NFS: readdir reply truncated!\n");
3546 entry[1] = 1;
3547 }
3548 goto out;
3549err_unmap: 3582err_unmap:
3550 kunmap_atomic(kaddr, KM_USER0); 3583 kunmap_atomic(kaddr, KM_USER0);
3551 return -errno_NFSERR_IO; 3584 return -errno_NFSERR_IO;
@@ -3727,7 +3760,7 @@ static int decode_setclientid(struct xdr_stream *xdr, struct nfs_client *clp)
3727 READ_BUF(len); 3760 READ_BUF(len);
3728 return -NFSERR_CLID_INUSE; 3761 return -NFSERR_CLID_INUSE;
3729 } else 3762 } else
3730 return -nfs4_stat_to_errno(nfserr); 3763 return nfs4_stat_to_errno(nfserr);
3731 3764
3732 return 0; 3765 return 0;
3733} 3766}
@@ -4389,7 +4422,7 @@ static int nfs4_xdr_dec_fsinfo(struct rpc_rqst *req, __be32 *p, struct nfs_fsinf
4389 if (!status) 4422 if (!status)
4390 status = decode_fsinfo(&xdr, fsinfo); 4423 status = decode_fsinfo(&xdr, fsinfo);
4391 if (!status) 4424 if (!status)
4392 status = -nfs4_stat_to_errno(hdr.status); 4425 status = nfs4_stat_to_errno(hdr.status);
4393 return status; 4426 return status;
4394} 4427}
4395 4428
@@ -4479,7 +4512,7 @@ static int nfs4_xdr_dec_setclientid(struct rpc_rqst *req, __be32 *p,
4479 if (!status) 4512 if (!status)
4480 status = decode_setclientid(&xdr, clp); 4513 status = decode_setclientid(&xdr, clp);
4481 if (!status) 4514 if (!status)
4482 status = -nfs4_stat_to_errno(hdr.status); 4515 status = nfs4_stat_to_errno(hdr.status);
4483 return status; 4516 return status;
4484} 4517}
4485 4518
@@ -4501,7 +4534,7 @@ static int nfs4_xdr_dec_setclientid_confirm(struct rpc_rqst *req, __be32 *p, str
4501 if (!status) 4534 if (!status)
4502 status = decode_fsinfo(&xdr, fsinfo); 4535 status = decode_fsinfo(&xdr, fsinfo);
4503 if (!status) 4536 if (!status)
4504 status = -nfs4_stat_to_errno(hdr.status); 4537 status = nfs4_stat_to_errno(hdr.status);
4505 return status; 4538 return status;
4506} 4539}
4507 4540
@@ -4611,42 +4644,42 @@ static struct {
4611 int errno; 4644 int errno;
4612} nfs_errtbl[] = { 4645} nfs_errtbl[] = {
4613 { NFS4_OK, 0 }, 4646 { NFS4_OK, 0 },
4614 { NFS4ERR_PERM, EPERM }, 4647 { NFS4ERR_PERM, -EPERM },
4615 { NFS4ERR_NOENT, ENOENT }, 4648 { NFS4ERR_NOENT, -ENOENT },
4616 { NFS4ERR_IO, errno_NFSERR_IO }, 4649 { NFS4ERR_IO, -errno_NFSERR_IO},
4617 { NFS4ERR_NXIO, ENXIO }, 4650 { NFS4ERR_NXIO, -ENXIO },
4618 { NFS4ERR_ACCESS, EACCES }, 4651 { NFS4ERR_ACCESS, -EACCES },
4619 { NFS4ERR_EXIST, EEXIST }, 4652 { NFS4ERR_EXIST, -EEXIST },
4620 { NFS4ERR_XDEV, EXDEV }, 4653 { NFS4ERR_XDEV, -EXDEV },
4621 { NFS4ERR_NOTDIR, ENOTDIR }, 4654 { NFS4ERR_NOTDIR, -ENOTDIR },
4622 { NFS4ERR_ISDIR, EISDIR }, 4655 { NFS4ERR_ISDIR, -EISDIR },
4623 { NFS4ERR_INVAL, EINVAL }, 4656 { NFS4ERR_INVAL, -EINVAL },
4624 { NFS4ERR_FBIG, EFBIG }, 4657 { NFS4ERR_FBIG, -EFBIG },
4625 { NFS4ERR_NOSPC, ENOSPC }, 4658 { NFS4ERR_NOSPC, -ENOSPC },
4626 { NFS4ERR_ROFS, EROFS }, 4659 { NFS4ERR_ROFS, -EROFS },
4627 { NFS4ERR_MLINK, EMLINK }, 4660 { NFS4ERR_MLINK, -EMLINK },
4628 { NFS4ERR_NAMETOOLONG, ENAMETOOLONG }, 4661 { NFS4ERR_NAMETOOLONG, -ENAMETOOLONG },
4629 { NFS4ERR_NOTEMPTY, ENOTEMPTY }, 4662 { NFS4ERR_NOTEMPTY, -ENOTEMPTY },
4630 { NFS4ERR_DQUOT, EDQUOT }, 4663 { NFS4ERR_DQUOT, -EDQUOT },
4631 { NFS4ERR_STALE, ESTALE }, 4664 { NFS4ERR_STALE, -ESTALE },
4632 { NFS4ERR_BADHANDLE, EBADHANDLE }, 4665 { NFS4ERR_BADHANDLE, -EBADHANDLE },
4633 { NFS4ERR_BADOWNER, EINVAL }, 4666 { NFS4ERR_BADOWNER, -EINVAL },
4634 { NFS4ERR_BADNAME, EINVAL }, 4667 { NFS4ERR_BADNAME, -EINVAL },
4635 { NFS4ERR_BAD_COOKIE, EBADCOOKIE }, 4668 { NFS4ERR_BAD_COOKIE, -EBADCOOKIE },
4636 { NFS4ERR_NOTSUPP, ENOTSUPP }, 4669 { NFS4ERR_NOTSUPP, -ENOTSUPP },
4637 { NFS4ERR_TOOSMALL, ETOOSMALL }, 4670 { NFS4ERR_TOOSMALL, -ETOOSMALL },
4638 { NFS4ERR_SERVERFAULT, ESERVERFAULT }, 4671 { NFS4ERR_SERVERFAULT, -ESERVERFAULT },
4639 { NFS4ERR_BADTYPE, EBADTYPE }, 4672 { NFS4ERR_BADTYPE, -EBADTYPE },
4640 { NFS4ERR_LOCKED, EAGAIN }, 4673 { NFS4ERR_LOCKED, -EAGAIN },
4641 { NFS4ERR_RESOURCE, EREMOTEIO }, 4674 { NFS4ERR_RESOURCE, -EREMOTEIO },
4642 { NFS4ERR_SYMLINK, ELOOP }, 4675 { NFS4ERR_SYMLINK, -ELOOP },
4643 { NFS4ERR_OP_ILLEGAL, EOPNOTSUPP }, 4676 { NFS4ERR_OP_ILLEGAL, -EOPNOTSUPP },
4644 { NFS4ERR_DEADLOCK, EDEADLK }, 4677 { NFS4ERR_DEADLOCK, -EDEADLK },
4645 { NFS4ERR_WRONGSEC, EPERM }, /* FIXME: this needs 4678 { NFS4ERR_WRONGSEC, -EPERM }, /* FIXME: this needs
4646 * to be handled by a 4679 * to be handled by a
4647 * middle-layer. 4680 * middle-layer.
4648 */ 4681 */
4649 { -1, EIO } 4682 { -1, -EIO }
4650}; 4683};
4651 4684
4652/* 4685/*
@@ -4663,14 +4696,14 @@ nfs4_stat_to_errno(int stat)
4663 } 4696 }
4664 if (stat <= 10000 || stat > 10100) { 4697 if (stat <= 10000 || stat > 10100) {
4665 /* The server is looney tunes. */ 4698 /* The server is looney tunes. */
4666 return ESERVERFAULT; 4699 return -ESERVERFAULT;
4667 } 4700 }
4668 /* If we cannot translate the error, the recovery routines should 4701 /* If we cannot translate the error, the recovery routines should
4669 * handle it. 4702 * handle it.
4670 * Note: remaining NFSv4 error codes have values > 10000, so should 4703 * Note: remaining NFSv4 error codes have values > 10000, so should
4671 * not conflict with native Linux error codes. 4704 * not conflict with native Linux error codes.
4672 */ 4705 */
4673 return stat; 4706 return -stat;
4674} 4707}
4675 4708
4676#define PROC(proc, argtype, restype) \ 4709#define PROC(proc, argtype, restype) \