diff options
Diffstat (limited to 'fs/nfsd/nfs3xdr.c')
-rw-r--r-- | fs/nfsd/nfs3xdr.c | 75 |
1 files changed, 36 insertions, 39 deletions
diff --git a/fs/nfsd/nfs3xdr.c b/fs/nfsd/nfs3xdr.c index 01d4ec1c88e0..edf926e1062f 100644 --- a/fs/nfsd/nfs3xdr.c +++ b/fs/nfsd/nfs3xdr.c | |||
@@ -814,17 +814,6 @@ encode_entry_baggage(struct nfsd3_readdirres *cd, __be32 *p, const char *name, | |||
814 | return p; | 814 | return p; |
815 | } | 815 | } |
816 | 816 | ||
817 | static __be32 * | ||
818 | encode_entryplus_baggage(struct nfsd3_readdirres *cd, __be32 *p, | ||
819 | struct svc_fh *fhp) | ||
820 | { | ||
821 | p = encode_post_op_attr(cd->rqstp, p, fhp); | ||
822 | *p++ = xdr_one; /* yes, a file handle follows */ | ||
823 | p = encode_fh(p, fhp); | ||
824 | fh_put(fhp); | ||
825 | return p; | ||
826 | } | ||
827 | |||
828 | static int | 817 | static int |
829 | compose_entry_fh(struct nfsd3_readdirres *cd, struct svc_fh *fhp, | 818 | compose_entry_fh(struct nfsd3_readdirres *cd, struct svc_fh *fhp, |
830 | const char *name, int namlen) | 819 | const char *name, int namlen) |
@@ -836,29 +825,54 @@ compose_entry_fh(struct nfsd3_readdirres *cd, struct svc_fh *fhp, | |||
836 | dparent = cd->fh.fh_dentry; | 825 | dparent = cd->fh.fh_dentry; |
837 | exp = cd->fh.fh_export; | 826 | exp = cd->fh.fh_export; |
838 | 827 | ||
839 | fh_init(fhp, NFS3_FHSIZE); | ||
840 | if (isdotent(name, namlen)) { | 828 | if (isdotent(name, namlen)) { |
841 | if (namlen == 2) { | 829 | if (namlen == 2) { |
842 | dchild = dget_parent(dparent); | 830 | dchild = dget_parent(dparent); |
843 | if (dchild == dparent) { | 831 | if (dchild == dparent) { |
844 | /* filesystem root - cannot return filehandle for ".." */ | 832 | /* filesystem root - cannot return filehandle for ".." */ |
845 | dput(dchild); | 833 | dput(dchild); |
846 | return 1; | 834 | return -ENOENT; |
847 | } | 835 | } |
848 | } else | 836 | } else |
849 | dchild = dget(dparent); | 837 | dchild = dget(dparent); |
850 | } else | 838 | } else |
851 | dchild = lookup_one_len(name, dparent, namlen); | 839 | dchild = lookup_one_len(name, dparent, namlen); |
852 | if (IS_ERR(dchild)) | 840 | if (IS_ERR(dchild)) |
853 | return 1; | 841 | return -ENOENT; |
854 | if (d_mountpoint(dchild) || | 842 | rv = -ENOENT; |
855 | fh_compose(fhp, exp, dchild, &cd->fh) != 0 || | 843 | if (d_mountpoint(dchild)) |
856 | !dchild->d_inode) | 844 | goto out; |
857 | rv = 1; | 845 | rv = fh_compose(fhp, exp, dchild, &cd->fh); |
846 | if (rv) | ||
847 | goto out; | ||
848 | if (!dchild->d_inode) | ||
849 | goto out; | ||
850 | rv = 0; | ||
851 | out: | ||
858 | dput(dchild); | 852 | dput(dchild); |
859 | return rv; | 853 | return rv; |
860 | } | 854 | } |
861 | 855 | ||
856 | __be32 *encode_entryplus_baggage(struct nfsd3_readdirres *cd, __be32 *p, const char *name, int namlen) | ||
857 | { | ||
858 | struct svc_fh fh; | ||
859 | int err; | ||
860 | |||
861 | fh_init(&fh, NFS3_FHSIZE); | ||
862 | err = compose_entry_fh(cd, &fh, name, namlen); | ||
863 | if (err) { | ||
864 | *p++ = 0; | ||
865 | *p++ = 0; | ||
866 | goto out; | ||
867 | } | ||
868 | p = encode_post_op_attr(cd->rqstp, p, &fh); | ||
869 | *p++ = xdr_one; /* yes, a file handle follows */ | ||
870 | p = encode_fh(p, &fh); | ||
871 | out: | ||
872 | fh_put(&fh); | ||
873 | return p; | ||
874 | } | ||
875 | |||
862 | /* | 876 | /* |
863 | * Encode a directory entry. This one works for both normal readdir | 877 | * Encode a directory entry. This one works for both normal readdir |
864 | * and readdirplus. | 878 | * and readdirplus. |
@@ -929,16 +943,8 @@ encode_entry(struct readdir_cd *ccd, const char *name, int namlen, | |||
929 | 943 | ||
930 | p = encode_entry_baggage(cd, p, name, namlen, ino); | 944 | p = encode_entry_baggage(cd, p, name, namlen, ino); |
931 | 945 | ||
932 | /* throw in readdirplus baggage */ | 946 | if (plus) |
933 | if (plus) { | 947 | p = encode_entryplus_baggage(cd, p, name, namlen); |
934 | struct svc_fh fh; | ||
935 | |||
936 | if (compose_entry_fh(cd, &fh, name, namlen) > 0) { | ||
937 | *p++ = 0; | ||
938 | *p++ = 0; | ||
939 | } else | ||
940 | p = encode_entryplus_baggage(cd, p, &fh); | ||
941 | } | ||
942 | num_entry_words = p - cd->buffer; | 948 | num_entry_words = p - cd->buffer; |
943 | } else if (cd->rqstp->rq_respages[pn+1] != NULL) { | 949 | } else if (cd->rqstp->rq_respages[pn+1] != NULL) { |
944 | /* temporarily encode entry into next page, then move back to | 950 | /* temporarily encode entry into next page, then move back to |
@@ -951,17 +957,8 @@ encode_entry(struct readdir_cd *ccd, const char *name, int namlen, | |||
951 | 957 | ||
952 | p1 = encode_entry_baggage(cd, p1, name, namlen, ino); | 958 | p1 = encode_entry_baggage(cd, p1, name, namlen, ino); |
953 | 959 | ||
954 | /* throw in readdirplus baggage */ | 960 | if (plus) |
955 | if (plus) { | 961 | p = encode_entryplus_baggage(cd, p1, name, namlen); |
956 | struct svc_fh fh; | ||
957 | |||
958 | if (compose_entry_fh(cd, &fh, name, namlen) > 0) { | ||
959 | /* zero out the filehandle */ | ||
960 | *p1++ = 0; | ||
961 | *p1++ = 0; | ||
962 | } else | ||
963 | p1 = encode_entryplus_baggage(cd, p1, &fh); | ||
964 | } | ||
965 | 962 | ||
966 | /* determine entry word length and lengths to go in pages */ | 963 | /* determine entry word length and lengths to go in pages */ |
967 | num_entry_words = p1 - tmp; | 964 | num_entry_words = p1 - tmp; |