diff options
Diffstat (limited to 'fs/nfs/nfs4xdr.c')
-rw-r--r-- | fs/nfs/nfs4xdr.c | 147 |
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); | ||
3311 | out: | ||
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 | } | ||
3537 | out: | 3565 | out: |
3538 | kunmap_atomic(kaddr, KM_USER0); | 3566 | kunmap_atomic(kaddr, KM_USER0); |
3539 | return 0; | 3567 | return 0; |
3540 | short_pkt: | 3568 | short_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; | ||
3549 | err_unmap: | 3582 | err_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) \ |