* [PATCH 0/3] Should truncated READDIR replies return -EIO? @ 2008-02-22 19:49 Jeff Layton 2008-02-22 19:49 ` [PATCH 1/3] NFS: clean up short packet handling for NFSv2 readdir Jeff Layton 0 siblings, 1 reply; 6+ messages in thread From: Jeff Layton @ 2008-02-22 19:49 UTC (permalink / raw) To: Trond Myklebust; +Cc: linux-nfs, nfsv4 This patchset is a follow up to the discussion by the same title. I've broken them out by NFS version. I've only really tested the NFSv2 version of this patch against the buggy server I have, but it does work there as expected. The others have only had basic testing, but I didn't see any obvious breakage there. I don't see this patchset as particularly high priority, so 2.6.26 is probably reasonable. Signed-off-by: Jeff Layton <jlayton@redhat.com> ^ permalink raw reply [flat|nested] 6+ messages in thread
* [PATCH 1/3] NFS: clean up short packet handling for NFSv2 readdir 2008-02-22 19:49 [PATCH 0/3] Should truncated READDIR replies return -EIO? Jeff Layton @ 2008-02-22 19:49 ` Jeff Layton 2008-02-22 19:50 ` [PATCH 2/3] NFS: clean up short packet handling for NFSv3 readdir Jeff Layton 0 siblings, 1 reply; 6+ messages in thread From: Jeff Layton @ 2008-02-22 19:49 UTC (permalink / raw) To: Trond Myklebust; +Cc: linux-nfs, nfsv4 Currently, the NFS readdir decoders have a workaround for buggy servers that send an empty readdir response with the EOF bit unset. If the server sends a malformed response in some cases, this workaround kicks in and just returns an empty response rather than returning a proper error to the caller. This patch does 3 things: 1) have malformed responses with no entries return error (-EIO) 2) preserve existing workaround for servers that send empty responses with the EOF marker unset. 3) Add some comments to clarify the logic in nfs_xdr_readdirres(). Signed-off-by: Jeff Layton <jlayton@redhat.com> --- fs/nfs/nfs2xdr.c | 37 ++++++++++++++++++++++++++++--------- 1 files changed, 28 insertions(+), 9 deletions(-) diff --git a/fs/nfs/nfs2xdr.c b/fs/nfs/nfs2xdr.c index 1f7ea67..86a80b3 100644 --- a/fs/nfs/nfs2xdr.c +++ b/fs/nfs/nfs2xdr.c @@ -428,7 +428,7 @@ nfs_xdr_readdirres(struct rpc_rqst *req, __be32 *p, void *dummy) size_t hdrlen; unsigned int pglen, recvd; u32 len; - int status, nr; + int status, nr = 0; __be32 *end, *entry, *kaddr; if ((status = ntohl(*p++))) @@ -452,7 +452,12 @@ nfs_xdr_readdirres(struct rpc_rqst *req, __be32 *p, void *dummy) kaddr = p = kmap_atomic(*page, KM_USER0); end = (__be32 *)((char *)p + pglen); entry = p; - for (nr = 0; *p++; nr++) { + + /* Make sure the packet actually has a value_follows and EOF entry */ + if ((entry + 1) > end) + goto short_pkt; + + for (; *p++; nr++) { if (p + 2 > end) goto short_pkt; p++; /* fileid */ @@ -467,18 +472,32 @@ nfs_xdr_readdirres(struct rpc_rqst *req, __be32 *p, void *dummy) goto short_pkt; entry = p; } - if (!nr && (entry[0] != 0 || entry[1] == 0)) - goto short_pkt; + + /* + * Apparently some server sends responses that are a valid size, but + * contain no entries, and have value_follows==0 and EOF==0. For + * those, just set the EOF marker. + */ + if (!nr && entry[1] == 0) { + dprintk("NFS: readdir reply truncated!\n"); + entry[1] = 1; + } out: kunmap_atomic(kaddr, KM_USER0); return nr; short_pkt: + /* + * When we get a short packet there are 2 possibilities. We can + * return an error, or fix up the response to look like a valid + * response and return what we have so far. If there are no + * entries and the packet was short, then return -EIO. If there + * are valid entries in the response, return them and pretend that + * the call was successful, but incomplete. The caller can retry the + * readdir starting at the last cookie. + */ entry[0] = entry[1] = 0; - /* truncate listing ? */ - if (!nr) { - dprintk("NFS: readdir reply truncated!\n"); - entry[1] = 1; - } + if (!nr) + nr = -errno_NFSERR_IO; goto out; err_unmap: nr = -errno_NFSERR_IO; -- 1.5.4.1 ^ permalink raw reply related [flat|nested] 6+ messages in thread
* [PATCH 2/3] NFS: clean up short packet handling for NFSv3 readdir 2008-02-22 19:49 ` [PATCH 1/3] NFS: clean up short packet handling for NFSv2 readdir Jeff Layton @ 2008-02-22 19:50 ` Jeff Layton 2008-02-22 19:50 ` [PATCH 3/3] NFS: clean up short packet handling for NFSv4 readdir Jeff Layton 2008-02-22 21:11 ` [PATCH 2/3] NFS: clean up short packet handling for NFSv3 readdir Chuck Lever 0 siblings, 2 replies; 6+ messages in thread From: Jeff Layton @ 2008-02-22 19:50 UTC (permalink / raw) To: Trond Myklebust; +Cc: linux-nfs, nfsv4 Currently, the NFS readdir decoders have a workaround for buggy servers that send an empty readdir response with the EOF bit unset. If the server sends a malformed response in some cases, this workaround kicks in and just returns an empty response rather than returning a proper error to the caller. This patch does 3 things: 1) have malformed responses with no entries return error (-EIO) 2) preserve existing workaround for servers that send empty responses with the EOF marker unset. 3) Add some comments to clarify the logic in nfs3_xdr_readdirres(). Signed-off-by: Jeff Layton <jlayton@redhat.com> --- fs/nfs/nfs3xdr.c | 37 ++++++++++++++++++++++++++++--------- 1 files changed, 28 insertions(+), 9 deletions(-) diff --git a/fs/nfs/nfs3xdr.c b/fs/nfs/nfs3xdr.c index 3917e2f..fb03048 100644 --- a/fs/nfs/nfs3xdr.c +++ b/fs/nfs/nfs3xdr.c @@ -508,7 +508,7 @@ nfs3_xdr_readdirres(struct rpc_rqst *req, __be32 *p, struct nfs3_readdirres *res struct page **page; size_t hdrlen; u32 len, recvd, pglen; - int status, nr; + int status, nr = 0; __be32 *entry, *end, *kaddr; status = ntohl(*p++); @@ -542,7 +542,12 @@ nfs3_xdr_readdirres(struct rpc_rqst *req, __be32 *p, struct nfs3_readdirres *res kaddr = p = kmap_atomic(*page, KM_USER0); end = (__be32 *)((char *)p + pglen); entry = p; - for (nr = 0; *p++; nr++) { + + /* Make sure the packet actually has a value_follows and EOF entry */ + if ((entry + 1) > end) + goto short_pkt; + + for (; *p++; nr++) { if (p + 3 > end) goto short_pkt; p += 2; /* inode # */ @@ -581,18 +586,32 @@ nfs3_xdr_readdirres(struct rpc_rqst *req, __be32 *p, struct nfs3_readdirres *res goto short_pkt; entry = p; } - if (!nr && (entry[0] != 0 || entry[1] == 0)) - goto short_pkt; + + /* + * Apparently some server sends responses that are a valid size, but + * contain no entries, and have value_follows==0 and EOF==0. For + * those, just set the EOF marker. + */ + if (!nr && entry[1] == 0) { + dprintk("NFS: readdir reply truncated!\n"); + entry[1] = 1; + } out: kunmap_atomic(kaddr, KM_USER0); return nr; short_pkt: + /* + * When we get a short packet there are 2 possibilities. We can + * return an error, or fix up the response to look like a valid + * response and return what we have so far. If there are no + * entries and the packet was short, then return -EIO. If there + * are valid entries in the response, return them and pretend that + * the call was successful, but incomplete. The caller can retry the + * readdir starting at the last cookie. + */ entry[0] = entry[1] = 0; - /* truncate listing ? */ - if (!nr) { - dprintk("NFS: readdir reply truncated!\n"); - entry[1] = 1; - } + if (!nr) + nr = -errno_NFSERR_IO; goto out; err_unmap: nr = -errno_NFSERR_IO; -- 1.5.4.1 ^ permalink raw reply related [flat|nested] 6+ messages in thread
* [PATCH 3/3] NFS: clean up short packet handling for NFSv4 readdir 2008-02-22 19:50 ` [PATCH 2/3] NFS: clean up short packet handling for NFSv3 readdir Jeff Layton @ 2008-02-22 19:50 ` Jeff Layton 2008-02-22 21:11 ` [PATCH 2/3] NFS: clean up short packet handling for NFSv3 readdir Chuck Lever 1 sibling, 0 replies; 6+ messages in thread From: Jeff Layton @ 2008-02-22 19:50 UTC (permalink / raw) To: Trond Myklebust; +Cc: linux-nfs, nfsv4 Currently, the NFS readdir decoders have a workaround for buggy servers that send an empty readdir response with the EOF bit unset. If the server sends a malformed response in some cases, this workaround kicks in and just returns an empty response rather than returning a proper error to the caller. This patch does 3 things: 1) have malformed responses with no entries return error (-EIO) 2) preserve existing workaround for servers that send empty responses with the EOF marker unset. 3) Add some comments to clarify the logic in decode_readdir(). Signed-off-by: Jeff Layton <jlayton@redhat.com> --- fs/nfs/nfs4xdr.c | 37 +++++++++++++++++++++++++++---------- 1 files changed, 27 insertions(+), 10 deletions(-) diff --git a/fs/nfs/nfs4xdr.c b/fs/nfs/nfs4xdr.c index db1ed9c..6a203ba 100644 --- a/fs/nfs/nfs4xdr.c +++ b/fs/nfs/nfs4xdr.c @@ -3481,7 +3481,7 @@ static int decode_readdir(struct xdr_stream *xdr, struct rpc_rqst *req, struct n size_t hdrlen; u32 recvd, pglen = rcvbuf->page_len; __be32 *end, *entry, *p, *kaddr; - unsigned int nr; + unsigned int nr = 0; int status; status = decode_op_hdr(xdr, OP_READDIR); @@ -3505,7 +3505,12 @@ static int decode_readdir(struct xdr_stream *xdr, struct rpc_rqst *req, struct n kaddr = p = kmap_atomic(page, KM_USER0); end = p + ((pglen + readdir->pgbase) >> 2); entry = p; - for (nr = 0; *p++; nr++) { + + /* Make sure the packet actually has a value_follows and EOF entry */ + if ((entry + 1) > end) + goto short_pkt; + + for (; *p++; nr++) { u32 len, attrlen, xlen; if (end - p < 3) goto short_pkt; @@ -3532,20 +3537,32 @@ static int decode_readdir(struct xdr_stream *xdr, struct rpc_rqst *req, struct n p += attrlen; /* attributes */ entry = p; } - if (!nr && (entry[0] != 0 || entry[1] == 0)) - goto short_pkt; + /* + * Apparently some server sends responses that are a valid size, but + * contain no entries, and have value_follows==0 and EOF==0. For + * those, just set the EOF marker. + */ + if (!nr && entry[1] == 0) { + dprintk("NFS: readdir reply truncated!\n"); + entry[1] = 1; + } out: kunmap_atomic(kaddr, KM_USER0); return 0; short_pkt: + /* + * When we get a short packet there are 2 possibilities. We can + * return an error, or fix up the response to look like a valid + * response and return what we have so far. If there are no + * entries and the packet was short, then return -EIO. If there + * are valid entries in the response, return them and pretend that + * the call was successful, but incomplete. The caller can retry the + * readdir starting at the last cookie. + */ dprintk("%s: short packet at entry %d\n", __FUNCTION__, nr); entry[0] = entry[1] = 0; - /* truncate listing ? */ - if (!nr) { - dprintk("NFS: readdir reply truncated!\n"); - entry[1] = 1; - } - goto out; + if (nr) + goto out; err_unmap: kunmap_atomic(kaddr, KM_USER0); return -errno_NFSERR_IO; -- 1.5.4.1 ^ permalink raw reply related [flat|nested] 6+ messages in thread
* Re: [PATCH 2/3] NFS: clean up short packet handling for NFSv3 readdir 2008-02-22 19:50 ` [PATCH 2/3] NFS: clean up short packet handling for NFSv3 readdir Jeff Layton 2008-02-22 19:50 ` [PATCH 3/3] NFS: clean up short packet handling for NFSv4 readdir Jeff Layton @ 2008-02-22 21:11 ` Chuck Lever 2008-02-22 21:26 ` Jeff Layton 1 sibling, 1 reply; 6+ messages in thread From: Chuck Lever @ 2008-02-22 21:11 UTC (permalink / raw) To: Jeff Layton; +Cc: linux-nfs, nfsv4 [-- Attachment #1: Type: text/plain, Size: 3049 bytes --] Hi Jeff- For NFSv3, is the READDIRPLUS decoder affected as well? Jeff Layton wrote: > Currently, the NFS readdir decoders have a workaround for buggy servers > that send an empty readdir response with the EOF bit unset. If the > server sends a malformed response in some cases, this workaround kicks > in and just returns an empty response rather than returning a proper > error to the caller. > > This patch does 3 things: > > 1) have malformed responses with no entries return error (-EIO) > > 2) preserve existing workaround for servers that send empty > responses with the EOF marker unset. > > 3) Add some comments to clarify the logic in nfs3_xdr_readdirres(). > > Signed-off-by: Jeff Layton <jlayton@redhat.com> > --- > fs/nfs/nfs3xdr.c | 37 ++++++++++++++++++++++++++++--------- > 1 files changed, 28 insertions(+), 9 deletions(-) > > diff --git a/fs/nfs/nfs3xdr.c b/fs/nfs/nfs3xdr.c > index 3917e2f..fb03048 100644 > --- a/fs/nfs/nfs3xdr.c > +++ b/fs/nfs/nfs3xdr.c > @@ -508,7 +508,7 @@ nfs3_xdr_readdirres(struct rpc_rqst *req, __be32 *p, struct nfs3_readdirres *res > struct page **page; > size_t hdrlen; > u32 len, recvd, pglen; > - int status, nr; > + int status, nr = 0; > __be32 *entry, *end, *kaddr; > > status = ntohl(*p++); > @@ -542,7 +542,12 @@ nfs3_xdr_readdirres(struct rpc_rqst *req, __be32 *p, struct nfs3_readdirres *res > kaddr = p = kmap_atomic(*page, KM_USER0); > end = (__be32 *)((char *)p + pglen); > entry = p; > - for (nr = 0; *p++; nr++) { > + > + /* Make sure the packet actually has a value_follows and EOF entry */ > + if ((entry + 1) > end) > + goto short_pkt; > + > + for (; *p++; nr++) { > if (p + 3 > end) > goto short_pkt; > p += 2; /* inode # */ > @@ -581,18 +586,32 @@ nfs3_xdr_readdirres(struct rpc_rqst *req, __be32 *p, struct nfs3_readdirres *res > goto short_pkt; > entry = p; > } > - if (!nr && (entry[0] != 0 || entry[1] == 0)) > - goto short_pkt; > + > + /* > + * Apparently some server sends responses that are a valid size, but > + * contain no entries, and have value_follows==0 and EOF==0. For > + * those, just set the EOF marker. > + */ > + if (!nr && entry[1] == 0) { > + dprintk("NFS: readdir reply truncated!\n"); > + entry[1] = 1; > + } > out: > kunmap_atomic(kaddr, KM_USER0); > return nr; > short_pkt: > + /* > + * When we get a short packet there are 2 possibilities. We can > + * return an error, or fix up the response to look like a valid > + * response and return what we have so far. If there are no > + * entries and the packet was short, then return -EIO. If there > + * are valid entries in the response, return them and pretend that > + * the call was successful, but incomplete. The caller can retry the > + * readdir starting at the last cookie. > + */ > entry[0] = entry[1] = 0; > - /* truncate listing ? */ > - if (!nr) { > - dprintk("NFS: readdir reply truncated!\n"); > - entry[1] = 1; > - } > + if (!nr) > + nr = -errno_NFSERR_IO; > goto out; > err_unmap: > nr = -errno_NFSERR_IO; [-- Attachment #2: chuck_lever.vcf --] [-- Type: text/x-vcard, Size: 259 bytes --] begin:vcard fn:Chuck Lever n:Lever;Chuck org:Oracle Corporation;Corporate Architecture: Linux Projects Group adr:;;1015 Granger Avenue;Ann Arbor;MI;48104;USA title:Principal Member of Staff tel;work:+1 248 614 5091 x-mozilla-html:FALSE version:2.1 end:vcard [-- Attachment #3: Type: text/plain, Size: 138 bytes --] _______________________________________________ NFSv4 mailing list NFSv4@linux-nfs.org http://linux-nfs.org/cgi-bin/mailman/listinfo/nfsv4 ^ permalink raw reply [flat|nested] 6+ messages in thread
* Re: [PATCH 2/3] NFS: clean up short packet handling for NFSv3 readdir 2008-02-22 21:11 ` [PATCH 2/3] NFS: clean up short packet handling for NFSv3 readdir Chuck Lever @ 2008-02-22 21:26 ` Jeff Layton 0 siblings, 0 replies; 6+ messages in thread From: Jeff Layton @ 2008-02-22 21:26 UTC (permalink / raw) To: chuck.lever; +Cc: linux-nfs, nfsv4 On Fri, 22 Feb 2008 16:11:12 -0500 Chuck Lever <chuck.lever@oracle.com> wrote: > Hi Jeff- > > For NFSv3, is the READDIRPLUS decoder affected as well? > Yes. READDIR and READDIRPLUS use the same decoder routine, so this patch should also make short READDIRPLUS packets return an error using the same set of rules. > Jeff Layton wrote: > > Currently, the NFS readdir decoders have a workaround for buggy servers > > that send an empty readdir response with the EOF bit unset. If the > > server sends a malformed response in some cases, this workaround kicks > > in and just returns an empty response rather than returning a proper > > error to the caller. > > > > This patch does 3 things: > > > > 1) have malformed responses with no entries return error (-EIO) > > > > 2) preserve existing workaround for servers that send empty > > responses with the EOF marker unset. > > > > 3) Add some comments to clarify the logic in nfs3_xdr_readdirres(). > > > > Signed-off-by: Jeff Layton <jlayton@redhat.com> > > --- > > fs/nfs/nfs3xdr.c | 37 ++++++++++++++++++++++++++++--------- > > 1 files changed, 28 insertions(+), 9 deletions(-) > > > > diff --git a/fs/nfs/nfs3xdr.c b/fs/nfs/nfs3xdr.c > > index 3917e2f..fb03048 100644 > > --- a/fs/nfs/nfs3xdr.c > > +++ b/fs/nfs/nfs3xdr.c > > @@ -508,7 +508,7 @@ nfs3_xdr_readdirres(struct rpc_rqst *req, __be32 *p, struct nfs3_readdirres *res > > struct page **page; > > size_t hdrlen; > > u32 len, recvd, pglen; > > - int status, nr; > > + int status, nr = 0; > > __be32 *entry, *end, *kaddr; > > > > status = ntohl(*p++); > > @@ -542,7 +542,12 @@ nfs3_xdr_readdirres(struct rpc_rqst *req, __be32 *p, struct nfs3_readdirres *res > > kaddr = p = kmap_atomic(*page, KM_USER0); > > end = (__be32 *)((char *)p + pglen); > > entry = p; > > - for (nr = 0; *p++; nr++) { > > + > > + /* Make sure the packet actually has a value_follows and EOF entry */ > > + if ((entry + 1) > end) > > + goto short_pkt; > > + > > + for (; *p++; nr++) { > > if (p + 3 > end) > > goto short_pkt; > > p += 2; /* inode # */ > > @@ -581,18 +586,32 @@ nfs3_xdr_readdirres(struct rpc_rqst *req, __be32 *p, struct nfs3_readdirres *res > > goto short_pkt; > > entry = p; > > } > > - if (!nr && (entry[0] != 0 || entry[1] == 0)) > > - goto short_pkt; > > + > > + /* > > + * Apparently some server sends responses that are a valid size, but > > + * contain no entries, and have value_follows==0 and EOF==0. For > > + * those, just set the EOF marker. > > + */ > > + if (!nr && entry[1] == 0) { > > + dprintk("NFS: readdir reply truncated!\n"); > > + entry[1] = 1; > > + } > > out: > > kunmap_atomic(kaddr, KM_USER0); > > return nr; > > short_pkt: > > + /* > > + * When we get a short packet there are 2 possibilities. We can > > + * return an error, or fix up the response to look like a valid > > + * response and return what we have so far. If there are no > > + * entries and the packet was short, then return -EIO. If there > > + * are valid entries in the response, return them and pretend that > > + * the call was successful, but incomplete. The caller can retry the > > + * readdir starting at the last cookie. > > + */ > > entry[0] = entry[1] = 0; > > - /* truncate listing ? */ > > - if (!nr) { > > - dprintk("NFS: readdir reply truncated!\n"); > > - entry[1] = 1; > > - } > > + if (!nr) > > + nr = -errno_NFSERR_IO; > > goto out; > > err_unmap: > > nr = -errno_NFSERR_IO; -- Jeff Layton <jlayton@redhat.com> ^ permalink raw reply [flat|nested] 6+ messages in thread
end of thread, other threads:[~2008-02-22 21:26 UTC | newest] Thread overview: 6+ messages (download: mbox.gz follow: Atom feed -- links below jump to the message on this page -- 2008-02-22 19:49 [PATCH 0/3] Should truncated READDIR replies return -EIO? Jeff Layton 2008-02-22 19:49 ` [PATCH 1/3] NFS: clean up short packet handling for NFSv2 readdir Jeff Layton 2008-02-22 19:50 ` [PATCH 2/3] NFS: clean up short packet handling for NFSv3 readdir Jeff Layton 2008-02-22 19:50 ` [PATCH 3/3] NFS: clean up short packet handling for NFSv4 readdir Jeff Layton 2008-02-22 21:11 ` [PATCH 2/3] NFS: clean up short packet handling for NFSv3 readdir Chuck Lever 2008-02-22 21:26 ` Jeff Layton
This is a public inbox, see mirroring instructions for how to clone and mirror all data and code used for this inbox