On Thu, 21 Aug 2014 11:09:29 -0500 Christoph Hellwig <hch@xxxxxx> wrote: > When we do non-page sized reads we can underflow the extent_length variable > and read incorrect data. Fix the extent_length calculation and change to > defensive <= checks for the extent length in the read and write path. > > Signed-off-by: Christoph Hellwig <hch@xxxxxx> Hi Christoph, I was reviewing this patch for possible backport. As 'extent_length' is sector_t, it is unsigned (either u64 or unsigned long). So comparing "<= 0" has the same effect as comparing "== 0". So the new checks are not "defensive". That doesn't mean they are wrong, but they could be misleading... There may be nothing that needs to be done here, but I thought I should let you know. NeilBrown > --- > fs/nfs/blocklayout/blocklayout.c | 7 ++++--- > 1 file changed, 4 insertions(+), 3 deletions(-) > > diff --git a/fs/nfs/blocklayout/blocklayout.c b/fs/nfs/blocklayout/blocklayout.c > index 5427ae7..87a633d 100644 > --- a/fs/nfs/blocklayout/blocklayout.c > +++ b/fs/nfs/blocklayout/blocklayout.c > @@ -272,7 +272,7 @@ bl_read_pagelist(struct nfs_pgio_header *hdr) > isect = (sector_t) (f_offset >> SECTOR_SHIFT); > /* Code assumes extents are page-aligned */ > for (i = pg_index; i < hdr->page_array.npages; i++) { > - if (!extent_length) { > + if (extent_length <= 0) { > /* We've used up the previous extent */ > bl_put_extent(be); > bl_put_extent(cow_read); > @@ -303,6 +303,7 @@ bl_read_pagelist(struct nfs_pgio_header *hdr) > f_offset += pg_len; > bytes_left -= pg_len; > isect += (pg_offset >> SECTOR_SHIFT); > + extent_length -= (pg_offset >> SECTOR_SHIFT); > } else { > pg_offset = 0; > pg_len = PAGE_CACHE_SIZE; > @@ -333,7 +334,7 @@ bl_read_pagelist(struct nfs_pgio_header *hdr) > } > } > isect += (pg_len >> SECTOR_SHIFT); > - extent_length -= PAGE_CACHE_SECTORS; > + extent_length -= (pg_len >> SECTOR_SHIFT); > } > if ((isect << SECTOR_SHIFT) >= header->inode->i_size) { > hdr->res.eof = 1; > @@ -797,7 +798,7 @@ next_page: > /* Middle pages */ > pg_index = header->args.pgbase >> PAGE_CACHE_SHIFT; > for (i = pg_index; i < header->page_array.npages; i++) { > - if (!extent_length) { > + if (extent_length <= 0) { > /* We've used up the previous extent */ > bl_put_extent(be); > bl_put_extent(cow_read);
Attachment:
pgphq7m1IQyFh.pgp
Description: OpenPGP digital signature