diff options
author | Trond Myklebust <Trond.Myklebust@netapp.com> | 2008-04-24 14:01:02 -0400 |
---|---|---|
committer | Trond Myklebust <Trond.Myklebust@netapp.com> | 2008-04-24 14:01:02 -0400 |
commit | 233607dbbc823caf685e778cabc49fb7f679900b (patch) | |
tree | 13840137ee10788061cbec60fcfe8ea4c274558e /fs/nfs/nfs3xdr.c | |
parent | 3dc5063786b273f1aee545844f6bd4e9651ebffe (diff) | |
parent | b48633bd086d21f4a2a5bea96c7e6c7ba58eb60c (diff) |
Merge branch 'devel'
Diffstat (limited to 'fs/nfs/nfs3xdr.c')
-rw-r--r-- | fs/nfs/nfs3xdr.c | 71 |
1 files changed, 45 insertions, 26 deletions
diff --git a/fs/nfs/nfs3xdr.c b/fs/nfs/nfs3xdr.c index 3917e2fa4e40..11cdddec1432 100644 --- a/fs/nfs/nfs3xdr.c +++ b/fs/nfs/nfs3xdr.c | |||
@@ -508,14 +508,14 @@ nfs3_xdr_readdirres(struct rpc_rqst *req, __be32 *p, struct nfs3_readdirres *res | |||
508 | struct page **page; | 508 | struct page **page; |
509 | size_t hdrlen; | 509 | size_t hdrlen; |
510 | u32 len, recvd, pglen; | 510 | u32 len, recvd, pglen; |
511 | int status, nr; | 511 | int status, nr = 0; |
512 | __be32 *entry, *end, *kaddr; | 512 | __be32 *entry, *end, *kaddr; |
513 | 513 | ||
514 | status = ntohl(*p++); | 514 | status = ntohl(*p++); |
515 | /* Decode post_op_attrs */ | 515 | /* Decode post_op_attrs */ |
516 | p = xdr_decode_post_op_attr(p, res->dir_attr); | 516 | p = xdr_decode_post_op_attr(p, res->dir_attr); |
517 | if (status) | 517 | if (status) |
518 | return -nfs_stat_to_errno(status); | 518 | return nfs_stat_to_errno(status); |
519 | /* Decode verifier cookie */ | 519 | /* Decode verifier cookie */ |
520 | if (res->verf) { | 520 | if (res->verf) { |
521 | res->verf[0] = *p++; | 521 | res->verf[0] = *p++; |
@@ -542,7 +542,12 @@ nfs3_xdr_readdirres(struct rpc_rqst *req, __be32 *p, struct nfs3_readdirres *res | |||
542 | kaddr = p = kmap_atomic(*page, KM_USER0); | 542 | kaddr = p = kmap_atomic(*page, KM_USER0); |
543 | end = (__be32 *)((char *)p + pglen); | 543 | end = (__be32 *)((char *)p + pglen); |
544 | entry = p; | 544 | entry = p; |
545 | for (nr = 0; *p++; nr++) { | 545 | |
546 | /* Make sure the packet actually has a value_follows and EOF entry */ | ||
547 | if ((entry + 1) > end) | ||
548 | goto short_pkt; | ||
549 | |||
550 | for (; *p++; nr++) { | ||
546 | if (p + 3 > end) | 551 | if (p + 3 > end) |
547 | goto short_pkt; | 552 | goto short_pkt; |
548 | p += 2; /* inode # */ | 553 | p += 2; /* inode # */ |
@@ -581,18 +586,32 @@ nfs3_xdr_readdirres(struct rpc_rqst *req, __be32 *p, struct nfs3_readdirres *res | |||
581 | goto short_pkt; | 586 | goto short_pkt; |
582 | entry = p; | 587 | entry = p; |
583 | } | 588 | } |
584 | if (!nr && (entry[0] != 0 || entry[1] == 0)) | 589 | |
585 | goto short_pkt; | 590 | /* |
591 | * Apparently some server sends responses that are a valid size, but | ||
592 | * contain no entries, and have value_follows==0 and EOF==0. For | ||
593 | * those, just set the EOF marker. | ||
594 | */ | ||
595 | if (!nr && entry[1] == 0) { | ||
596 | dprintk("NFS: readdir reply truncated!\n"); | ||
597 | entry[1] = 1; | ||
598 | } | ||
586 | out: | 599 | out: |
587 | kunmap_atomic(kaddr, KM_USER0); | 600 | kunmap_atomic(kaddr, KM_USER0); |
588 | return nr; | 601 | return nr; |
589 | short_pkt: | 602 | short_pkt: |
603 | /* | ||
604 | * When we get a short packet there are 2 possibilities. We can | ||
605 | * return an error, or fix up the response to look like a valid | ||
606 | * response and return what we have so far. If there are no | ||
607 | * entries and the packet was short, then return -EIO. If there | ||
608 | * are valid entries in the response, return them and pretend that | ||
609 | * the call was successful, but incomplete. The caller can retry the | ||
610 | * readdir starting at the last cookie. | ||
611 | */ | ||
590 | entry[0] = entry[1] = 0; | 612 | entry[0] = entry[1] = 0; |
591 | /* truncate listing ? */ | 613 | if (!nr) |
592 | if (!nr) { | 614 | nr = -errno_NFSERR_IO; |
593 | dprintk("NFS: readdir reply truncated!\n"); | ||
594 | entry[1] = 1; | ||
595 | } | ||
596 | goto out; | 615 | goto out; |
597 | err_unmap: | 616 | err_unmap: |
598 | nr = -errno_NFSERR_IO; | 617 | nr = -errno_NFSERR_IO; |
@@ -732,7 +751,7 @@ nfs3_xdr_attrstat(struct rpc_rqst *req, __be32 *p, struct nfs_fattr *fattr) | |||
732 | int status; | 751 | int status; |
733 | 752 | ||
734 | if ((status = ntohl(*p++))) | 753 | if ((status = ntohl(*p++))) |
735 | return -nfs_stat_to_errno(status); | 754 | return nfs_stat_to_errno(status); |
736 | xdr_decode_fattr(p, fattr); | 755 | xdr_decode_fattr(p, fattr); |
737 | return 0; | 756 | return 0; |
738 | } | 757 | } |
@@ -747,7 +766,7 @@ nfs3_xdr_wccstat(struct rpc_rqst *req, __be32 *p, struct nfs_fattr *fattr) | |||
747 | int status; | 766 | int status; |
748 | 767 | ||
749 | if ((status = ntohl(*p++))) | 768 | if ((status = ntohl(*p++))) |
750 | status = -nfs_stat_to_errno(status); | 769 | status = nfs_stat_to_errno(status); |
751 | xdr_decode_wcc_data(p, fattr); | 770 | xdr_decode_wcc_data(p, fattr); |
752 | return status; | 771 | return status; |
753 | } | 772 | } |
@@ -767,7 +786,7 @@ nfs3_xdr_lookupres(struct rpc_rqst *req, __be32 *p, struct nfs3_diropres *res) | |||
767 | int status; | 786 | int status; |
768 | 787 | ||
769 | if ((status = ntohl(*p++))) { | 788 | if ((status = ntohl(*p++))) { |
770 | status = -nfs_stat_to_errno(status); | 789 | status = nfs_stat_to_errno(status); |
771 | } else { | 790 | } else { |
772 | if (!(p = xdr_decode_fhandle(p, res->fh))) | 791 | if (!(p = xdr_decode_fhandle(p, res->fh))) |
773 | return -errno_NFSERR_IO; | 792 | return -errno_NFSERR_IO; |
@@ -787,7 +806,7 @@ nfs3_xdr_accessres(struct rpc_rqst *req, __be32 *p, struct nfs3_accessres *res) | |||
787 | 806 | ||
788 | p = xdr_decode_post_op_attr(p, res->fattr); | 807 | p = xdr_decode_post_op_attr(p, res->fattr); |
789 | if (status) | 808 | if (status) |
790 | return -nfs_stat_to_errno(status); | 809 | return nfs_stat_to_errno(status); |
791 | res->access = ntohl(*p++); | 810 | res->access = ntohl(*p++); |
792 | return 0; | 811 | return 0; |
793 | } | 812 | } |
@@ -824,7 +843,7 @@ nfs3_xdr_readlinkres(struct rpc_rqst *req, __be32 *p, struct nfs_fattr *fattr) | |||
824 | p = xdr_decode_post_op_attr(p, fattr); | 843 | p = xdr_decode_post_op_attr(p, fattr); |
825 | 844 | ||
826 | if (status != 0) | 845 | if (status != 0) |
827 | return -nfs_stat_to_errno(status); | 846 | return nfs_stat_to_errno(status); |
828 | 847 | ||
829 | /* Convert length of symlink */ | 848 | /* Convert length of symlink */ |
830 | len = ntohl(*p++); | 849 | len = ntohl(*p++); |
@@ -872,7 +891,7 @@ nfs3_xdr_readres(struct rpc_rqst *req, __be32 *p, struct nfs_readres *res) | |||
872 | p = xdr_decode_post_op_attr(p, res->fattr); | 891 | p = xdr_decode_post_op_attr(p, res->fattr); |
873 | 892 | ||
874 | if (status != 0) | 893 | if (status != 0) |
875 | return -nfs_stat_to_errno(status); | 894 | return nfs_stat_to_errno(status); |
876 | 895 | ||
877 | /* Decode reply count and EOF flag. NFSv3 is somewhat redundant | 896 | /* Decode reply count and EOF flag. NFSv3 is somewhat redundant |
878 | * in that it puts the count both in the res struct and in the | 897 | * in that it puts the count both in the res struct and in the |
@@ -922,7 +941,7 @@ nfs3_xdr_writeres(struct rpc_rqst *req, __be32 *p, struct nfs_writeres *res) | |||
922 | p = xdr_decode_wcc_data(p, res->fattr); | 941 | p = xdr_decode_wcc_data(p, res->fattr); |
923 | 942 | ||
924 | if (status != 0) | 943 | if (status != 0) |
925 | return -nfs_stat_to_errno(status); | 944 | return nfs_stat_to_errno(status); |
926 | 945 | ||
927 | res->count = ntohl(*p++); | 946 | res->count = ntohl(*p++); |
928 | res->verf->committed = (enum nfs3_stable_how)ntohl(*p++); | 947 | res->verf->committed = (enum nfs3_stable_how)ntohl(*p++); |
@@ -953,7 +972,7 @@ nfs3_xdr_createres(struct rpc_rqst *req, __be32 *p, struct nfs3_diropres *res) | |||
953 | res->fattr->valid = 0; | 972 | res->fattr->valid = 0; |
954 | } | 973 | } |
955 | } else { | 974 | } else { |
956 | status = -nfs_stat_to_errno(status); | 975 | status = nfs_stat_to_errno(status); |
957 | } | 976 | } |
958 | p = xdr_decode_wcc_data(p, res->dir_attr); | 977 | p = xdr_decode_wcc_data(p, res->dir_attr); |
959 | return status; | 978 | return status; |
@@ -968,7 +987,7 @@ nfs3_xdr_renameres(struct rpc_rqst *req, __be32 *p, struct nfs3_renameres *res) | |||
968 | int status; | 987 | int status; |
969 | 988 | ||
970 | if ((status = ntohl(*p++)) != 0) | 989 | if ((status = ntohl(*p++)) != 0) |
971 | status = -nfs_stat_to_errno(status); | 990 | status = nfs_stat_to_errno(status); |
972 | p = xdr_decode_wcc_data(p, res->fromattr); | 991 | p = xdr_decode_wcc_data(p, res->fromattr); |
973 | p = xdr_decode_wcc_data(p, res->toattr); | 992 | p = xdr_decode_wcc_data(p, res->toattr); |
974 | return status; | 993 | return status; |
@@ -983,7 +1002,7 @@ nfs3_xdr_linkres(struct rpc_rqst *req, __be32 *p, struct nfs3_linkres *res) | |||
983 | int status; | 1002 | int status; |
984 | 1003 | ||
985 | if ((status = ntohl(*p++)) != 0) | 1004 | if ((status = ntohl(*p++)) != 0) |
986 | status = -nfs_stat_to_errno(status); | 1005 | status = nfs_stat_to_errno(status); |
987 | p = xdr_decode_post_op_attr(p, res->fattr); | 1006 | p = xdr_decode_post_op_attr(p, res->fattr); |
988 | p = xdr_decode_wcc_data(p, res->dir_attr); | 1007 | p = xdr_decode_wcc_data(p, res->dir_attr); |
989 | return status; | 1008 | return status; |
@@ -1001,7 +1020,7 @@ nfs3_xdr_fsstatres(struct rpc_rqst *req, __be32 *p, struct nfs_fsstat *res) | |||
1001 | 1020 | ||
1002 | p = xdr_decode_post_op_attr(p, res->fattr); | 1021 | p = xdr_decode_post_op_attr(p, res->fattr); |
1003 | if (status != 0) | 1022 | if (status != 0) |
1004 | return -nfs_stat_to_errno(status); | 1023 | return nfs_stat_to_errno(status); |
1005 | 1024 | ||
1006 | p = xdr_decode_hyper(p, &res->tbytes); | 1025 | p = xdr_decode_hyper(p, &res->tbytes); |
1007 | p = xdr_decode_hyper(p, &res->fbytes); | 1026 | p = xdr_decode_hyper(p, &res->fbytes); |
@@ -1026,7 +1045,7 @@ nfs3_xdr_fsinfores(struct rpc_rqst *req, __be32 *p, struct nfs_fsinfo *res) | |||
1026 | 1045 | ||
1027 | p = xdr_decode_post_op_attr(p, res->fattr); | 1046 | p = xdr_decode_post_op_attr(p, res->fattr); |
1028 | if (status != 0) | 1047 | if (status != 0) |
1029 | return -nfs_stat_to_errno(status); | 1048 | return nfs_stat_to_errno(status); |
1030 | 1049 | ||
1031 | res->rtmax = ntohl(*p++); | 1050 | res->rtmax = ntohl(*p++); |
1032 | res->rtpref = ntohl(*p++); | 1051 | res->rtpref = ntohl(*p++); |
@@ -1054,7 +1073,7 @@ nfs3_xdr_pathconfres(struct rpc_rqst *req, __be32 *p, struct nfs_pathconf *res) | |||
1054 | 1073 | ||
1055 | p = xdr_decode_post_op_attr(p, res->fattr); | 1074 | p = xdr_decode_post_op_attr(p, res->fattr); |
1056 | if (status != 0) | 1075 | if (status != 0) |
1057 | return -nfs_stat_to_errno(status); | 1076 | return nfs_stat_to_errno(status); |
1058 | res->max_link = ntohl(*p++); | 1077 | res->max_link = ntohl(*p++); |
1059 | res->max_namelen = ntohl(*p++); | 1078 | res->max_namelen = ntohl(*p++); |
1060 | 1079 | ||
@@ -1073,7 +1092,7 @@ nfs3_xdr_commitres(struct rpc_rqst *req, __be32 *p, struct nfs_writeres *res) | |||
1073 | status = ntohl(*p++); | 1092 | status = ntohl(*p++); |
1074 | p = xdr_decode_wcc_data(p, res->fattr); | 1093 | p = xdr_decode_wcc_data(p, res->fattr); |
1075 | if (status != 0) | 1094 | if (status != 0) |
1076 | return -nfs_stat_to_errno(status); | 1095 | return nfs_stat_to_errno(status); |
1077 | 1096 | ||
1078 | res->verf->verifier[0] = *p++; | 1097 | res->verf->verifier[0] = *p++; |
1079 | res->verf->verifier[1] = *p++; | 1098 | res->verf->verifier[1] = *p++; |
@@ -1095,7 +1114,7 @@ nfs3_xdr_getaclres(struct rpc_rqst *req, __be32 *p, | |||
1095 | int err, base; | 1114 | int err, base; |
1096 | 1115 | ||
1097 | if (status != 0) | 1116 | if (status != 0) |
1098 | return -nfs_stat_to_errno(status); | 1117 | return nfs_stat_to_errno(status); |
1099 | p = xdr_decode_post_op_attr(p, res->fattr); | 1118 | p = xdr_decode_post_op_attr(p, res->fattr); |
1100 | res->mask = ntohl(*p++); | 1119 | res->mask = ntohl(*p++); |
1101 | if (res->mask & ~(NFS_ACL|NFS_ACLCNT|NFS_DFACL|NFS_DFACLCNT)) | 1120 | if (res->mask & ~(NFS_ACL|NFS_ACLCNT|NFS_DFACL|NFS_DFACLCNT)) |
@@ -1122,7 +1141,7 @@ nfs3_xdr_setaclres(struct rpc_rqst *req, __be32 *p, struct nfs_fattr *fattr) | |||
1122 | int status = ntohl(*p++); | 1141 | int status = ntohl(*p++); |
1123 | 1142 | ||
1124 | if (status) | 1143 | if (status) |
1125 | return -nfs_stat_to_errno(status); | 1144 | return nfs_stat_to_errno(status); |
1126 | xdr_decode_post_op_attr(p, fattr); | 1145 | xdr_decode_post_op_attr(p, fattr); |
1127 | return 0; | 1146 | return 0; |
1128 | } | 1147 | } |