Message ID | 20200312085728.22187-1-tommi.t.rantala@nokia.com (mailing list archive) |
---|---|
State | Accepted |
Headers | show |
Series | xfs: fix regression in "cleanup xfs_dir2_block_getdents" | expand |
On Thu, Mar 12, 2020 at 10:57:28AM +0200, Tommi Rantala wrote: > Commit 263dde869bd09 ("xfs: cleanup xfs_dir2_block_getdents") introduced > a getdents regression, when it converted the pointer arithmetics to > offset calculations: offset is updated in the loop already for the next > iteration, but the updated offset value is used incorrectly in two > places, where we should have used the not-yet-updated value. > > This caused for example "git clean -ffdx" failures to cleanup certain > directory structures when running in a container. > > Fix the regression by making sure we use proper offset in the loop body. > Thanks to Christoph Hellwig for suggestion how to best fix the code. > > Cc: Christoph Hellwig <hch@lst.de> > Fixes: 263dde869bd09 ("xfs: cleanup xfs_dir2_block_getdents") > Signed-off-by: Tommi Rantala <tommi.t.rantala@nokia.com> Looks good, Reviewed-by: Christoph Hellwig <hch@lst.de>
On Thu, Mar 12, 2020 at 10:57:28AM +0200, Tommi Rantala wrote: > Commit 263dde869bd09 ("xfs: cleanup xfs_dir2_block_getdents") introduced > a getdents regression, when it converted the pointer arithmetics to > offset calculations: offset is updated in the loop already for the next > iteration, but the updated offset value is used incorrectly in two > places, where we should have used the not-yet-updated value. > > This caused for example "git clean -ffdx" failures to cleanup certain > directory structures when running in a container. > > Fix the regression by making sure we use proper offset in the loop body. > Thanks to Christoph Hellwig for suggestion how to best fix the code. > > Cc: Christoph Hellwig <hch@lst.de> > Fixes: 263dde869bd09 ("xfs: cleanup xfs_dir2_block_getdents") > Signed-off-by: Tommi Rantala <tommi.t.rantala@nokia.com> Looks ok, sorry I didn't catch this either... Reviewed-by: Darrick J. Wong <darrick.wong@oracle.com> How might we package this up as a fstest so we can actually do regression testing? --D > --- > fs/xfs/xfs_dir2_readdir.c | 12 +++++++----- > 1 file changed, 7 insertions(+), 5 deletions(-) > > diff --git a/fs/xfs/xfs_dir2_readdir.c b/fs/xfs/xfs_dir2_readdir.c > index 0d3b640cf1cc..871ec22c9aee 100644 > --- a/fs/xfs/xfs_dir2_readdir.c > +++ b/fs/xfs/xfs_dir2_readdir.c > @@ -147,7 +147,7 @@ xfs_dir2_block_getdents( > xfs_off_t cook; > struct xfs_da_geometry *geo = args->geo; > int lock_mode; > - unsigned int offset; > + unsigned int offset, next_offset; > unsigned int end; > > /* > @@ -173,9 +173,10 @@ xfs_dir2_block_getdents( > * Loop over the data portion of the block. > * Each object is a real entry (dep) or an unused one (dup). > */ > - offset = geo->data_entry_offset; > end = xfs_dir3_data_end_offset(geo, bp->b_addr); > - while (offset < end) { > + for (offset = geo->data_entry_offset; > + offset < end; > + offset = next_offset) { > struct xfs_dir2_data_unused *dup = bp->b_addr + offset; > struct xfs_dir2_data_entry *dep = bp->b_addr + offset; > uint8_t filetype; > @@ -184,14 +185,15 @@ xfs_dir2_block_getdents( > * Unused, skip it. > */ > if (be16_to_cpu(dup->freetag) == XFS_DIR2_DATA_FREE_TAG) { > - offset += be16_to_cpu(dup->length); > + next_offset = offset + be16_to_cpu(dup->length); > continue; > } > > /* > * Bump pointer for the next iteration. > */ > - offset += xfs_dir2_data_entsize(dp->i_mount, dep->namelen); > + next_offset = offset + > + xfs_dir2_data_entsize(dp->i_mount, dep->namelen); > > /* > * The entry is before the desired starting point, skip it. > -- > 2.21.1 >
On Thu, Mar 12, 2020 at 10:57:28AM +0200, Tommi Rantala wrote: > Commit 263dde869bd09 ("xfs: cleanup xfs_dir2_block_getdents") introduced > a getdents regression, when it converted the pointer arithmetics to > offset calculations: offset is updated in the loop already for the next > iteration, but the updated offset value is used incorrectly in two > places, where we should have used the not-yet-updated value. > > This caused for example "git clean -ffdx" failures to cleanup certain > directory structures when running in a container. > > Fix the regression by making sure we use proper offset in the loop body. > Thanks to Christoph Hellwig for suggestion how to best fix the code. > > Cc: Christoph Hellwig <hch@lst.de> > Fixes: 263dde869bd09 ("xfs: cleanup xfs_dir2_block_getdents") > Signed-off-by: Tommi Rantala <tommi.t.rantala@nokia.com> Needs a "cc: stable@kernel.org" tag, right? > --- > fs/xfs/xfs_dir2_readdir.c | 12 +++++++----- > 1 file changed, 7 insertions(+), 5 deletions(-) > > diff --git a/fs/xfs/xfs_dir2_readdir.c b/fs/xfs/xfs_dir2_readdir.c > index 0d3b640cf1cc..871ec22c9aee 100644 > --- a/fs/xfs/xfs_dir2_readdir.c > +++ b/fs/xfs/xfs_dir2_readdir.c > @@ -147,7 +147,7 @@ xfs_dir2_block_getdents( > xfs_off_t cook; > struct xfs_da_geometry *geo = args->geo; > int lock_mode; > - unsigned int offset; > + unsigned int offset, next_offset; > unsigned int end; > > /* > @@ -173,9 +173,10 @@ xfs_dir2_block_getdents( > * Loop over the data portion of the block. > * Each object is a real entry (dep) or an unused one (dup). > */ > - offset = geo->data_entry_offset; > end = xfs_dir3_data_end_offset(geo, bp->b_addr); > - while (offset < end) { > + for (offset = geo->data_entry_offset; > + offset < end; > + offset = next_offset) { > struct xfs_dir2_data_unused *dup = bp->b_addr + offset; > struct xfs_dir2_data_entry *dep = bp->b_addr + offset; > uint8_t filetype; > @@ -184,14 +185,15 @@ xfs_dir2_block_getdents( > * Unused, skip it. > */ > if (be16_to_cpu(dup->freetag) == XFS_DIR2_DATA_FREE_TAG) { > - offset += be16_to_cpu(dup->length); > + next_offset = offset + be16_to_cpu(dup->length); > continue; > } > > /* > * Bump pointer for the next iteration. > */ > - offset += xfs_dir2_data_entsize(dp->i_mount, dep->namelen); > + next_offset = offset + > + xfs_dir2_data_entsize(dp->i_mount, dep->namelen); Code looks fine, though. Reviewed-by: Dave Chinner <dchinner@redhat.com>
diff --git a/fs/xfs/xfs_dir2_readdir.c b/fs/xfs/xfs_dir2_readdir.c index 0d3b640cf1cc..871ec22c9aee 100644 --- a/fs/xfs/xfs_dir2_readdir.c +++ b/fs/xfs/xfs_dir2_readdir.c @@ -147,7 +147,7 @@ xfs_dir2_block_getdents( xfs_off_t cook; struct xfs_da_geometry *geo = args->geo; int lock_mode; - unsigned int offset; + unsigned int offset, next_offset; unsigned int end; /* @@ -173,9 +173,10 @@ xfs_dir2_block_getdents( * Loop over the data portion of the block. * Each object is a real entry (dep) or an unused one (dup). */ - offset = geo->data_entry_offset; end = xfs_dir3_data_end_offset(geo, bp->b_addr); - while (offset < end) { + for (offset = geo->data_entry_offset; + offset < end; + offset = next_offset) { struct xfs_dir2_data_unused *dup = bp->b_addr + offset; struct xfs_dir2_data_entry *dep = bp->b_addr + offset; uint8_t filetype; @@ -184,14 +185,15 @@ xfs_dir2_block_getdents( * Unused, skip it. */ if (be16_to_cpu(dup->freetag) == XFS_DIR2_DATA_FREE_TAG) { - offset += be16_to_cpu(dup->length); + next_offset = offset + be16_to_cpu(dup->length); continue; } /* * Bump pointer for the next iteration. */ - offset += xfs_dir2_data_entsize(dp->i_mount, dep->namelen); + next_offset = offset + + xfs_dir2_data_entsize(dp->i_mount, dep->namelen); /* * The entry is before the desired starting point, skip it.
Commit 263dde869bd09 ("xfs: cleanup xfs_dir2_block_getdents") introduced a getdents regression, when it converted the pointer arithmetics to offset calculations: offset is updated in the loop already for the next iteration, but the updated offset value is used incorrectly in two places, where we should have used the not-yet-updated value. This caused for example "git clean -ffdx" failures to cleanup certain directory structures when running in a container. Fix the regression by making sure we use proper offset in the loop body. Thanks to Christoph Hellwig for suggestion how to best fix the code. Cc: Christoph Hellwig <hch@lst.de> Fixes: 263dde869bd09 ("xfs: cleanup xfs_dir2_block_getdents") Signed-off-by: Tommi Rantala <tommi.t.rantala@nokia.com> --- fs/xfs/xfs_dir2_readdir.c | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-)