diff options
author | NeilBrown <neilb@suse.de> | 2015-05-02 19:16:53 -0400 |
---|---|---|
committer | J. Bruce Fields <bfields@redhat.com> | 2015-05-07 11:47:00 -0400 |
commit | 43b0e7ea590b51052384ecedf4ad7c8d7898e8e7 (patch) | |
tree | 506113d48acf247d47ec07ee33b31c5332a00087 | |
parent | 72faedae8bc3504ee4252cebf14737a23677cb8f (diff) |
nfsd: stop READDIRPLUS returning inconsistent attributes
The NFSv3 READDIRPLUS gets some of the returned attributes from the
readdir, and some from an inode returned from a new lookup. The two
objects could be different thanks to intervening renames.
The attributes in READDIRPLUS are optional, so let's just skip them if
we notice this case.
Signed-off-by: NeilBrown <neilb@suse.de>
Signed-off-by: J. Bruce Fields <bfields@redhat.com>
-rw-r--r-- | fs/nfsd/nfs3xdr.c | 12 |
1 files changed, 7 insertions, 5 deletions
diff --git a/fs/nfsd/nfs3xdr.c b/fs/nfsd/nfs3xdr.c index e4b2b4322553..f6e7cbabac5a 100644 --- a/fs/nfsd/nfs3xdr.c +++ b/fs/nfsd/nfs3xdr.c | |||
@@ -805,7 +805,7 @@ encode_entry_baggage(struct nfsd3_readdirres *cd, __be32 *p, const char *name, | |||
805 | 805 | ||
806 | static __be32 | 806 | static __be32 |
807 | compose_entry_fh(struct nfsd3_readdirres *cd, struct svc_fh *fhp, | 807 | compose_entry_fh(struct nfsd3_readdirres *cd, struct svc_fh *fhp, |
808 | const char *name, int namlen) | 808 | const char *name, int namlen, u64 ino) |
809 | { | 809 | { |
810 | struct svc_export *exp; | 810 | struct svc_export *exp; |
811 | struct dentry *dparent, *dchild; | 811 | struct dentry *dparent, *dchild; |
@@ -830,19 +830,21 @@ compose_entry_fh(struct nfsd3_readdirres *cd, struct svc_fh *fhp, | |||
830 | goto out; | 830 | goto out; |
831 | if (d_really_is_negative(dchild)) | 831 | if (d_really_is_negative(dchild)) |
832 | goto out; | 832 | goto out; |
833 | if (dchild->d_inode->i_ino != ino) | ||
834 | goto out; | ||
833 | rv = fh_compose(fhp, exp, dchild, &cd->fh); | 835 | rv = fh_compose(fhp, exp, dchild, &cd->fh); |
834 | out: | 836 | out: |
835 | dput(dchild); | 837 | dput(dchild); |
836 | return rv; | 838 | return rv; |
837 | } | 839 | } |
838 | 840 | ||
839 | static __be32 *encode_entryplus_baggage(struct nfsd3_readdirres *cd, __be32 *p, const char *name, int namlen) | 841 | static __be32 *encode_entryplus_baggage(struct nfsd3_readdirres *cd, __be32 *p, const char *name, int namlen, u64 ino) |
840 | { | 842 | { |
841 | struct svc_fh *fh = &cd->scratch; | 843 | struct svc_fh *fh = &cd->scratch; |
842 | __be32 err; | 844 | __be32 err; |
843 | 845 | ||
844 | fh_init(fh, NFS3_FHSIZE); | 846 | fh_init(fh, NFS3_FHSIZE); |
845 | err = compose_entry_fh(cd, fh, name, namlen); | 847 | err = compose_entry_fh(cd, fh, name, namlen, ino); |
846 | if (err) { | 848 | if (err) { |
847 | *p++ = 0; | 849 | *p++ = 0; |
848 | *p++ = 0; | 850 | *p++ = 0; |
@@ -927,7 +929,7 @@ encode_entry(struct readdir_cd *ccd, const char *name, int namlen, | |||
927 | p = encode_entry_baggage(cd, p, name, namlen, ino); | 929 | p = encode_entry_baggage(cd, p, name, namlen, ino); |
928 | 930 | ||
929 | if (plus) | 931 | if (plus) |
930 | p = encode_entryplus_baggage(cd, p, name, namlen); | 932 | p = encode_entryplus_baggage(cd, p, name, namlen, ino); |
931 | num_entry_words = p - cd->buffer; | 933 | num_entry_words = p - cd->buffer; |
932 | } else if (*(page+1) != NULL) { | 934 | } else if (*(page+1) != NULL) { |
933 | /* temporarily encode entry into next page, then move back to | 935 | /* temporarily encode entry into next page, then move back to |
@@ -941,7 +943,7 @@ encode_entry(struct readdir_cd *ccd, const char *name, int namlen, | |||
941 | p1 = encode_entry_baggage(cd, p1, name, namlen, ino); | 943 | p1 = encode_entry_baggage(cd, p1, name, namlen, ino); |
942 | 944 | ||
943 | if (plus) | 945 | if (plus) |
944 | p1 = encode_entryplus_baggage(cd, p1, name, namlen); | 946 | p1 = encode_entryplus_baggage(cd, p1, name, namlen, ino); |
945 | 947 | ||
946 | /* determine entry word length and lengths to go in pages */ | 948 | /* determine entry word length and lengths to go in pages */ |
947 | num_entry_words = p1 - tmp; | 949 | num_entry_words = p1 - tmp; |