mbox series

[0/7] xfs: Extend per-inode extent counters.

Message ID 20200606082745.15174-1-chandanrlinux@gmail.com (mailing list archive)
Headers show
Series xfs: Extend per-inode extent counters. | expand

Message

Chandan Babu R June 6, 2020, 8:27 a.m. UTC
The commit xfs: fix inode fork extent count overflow
(3f8a4f1d876d3e3e49e50b0396eaffcc4ba71b08) mentions that 10 billion
per-inode data fork extents should be possible to create. However the
corresponding on-disk field has an signed 32-bit type. Hence this
patchset extends the on-disk field to 64-bit length out of which only
the first 47-bits are valid.

Also, XFS has a per-inode xattr extent counter which is 16 bits
wide. A workload which
1. Creates 1 million 255-byte sized xattrs,
2. Deletes 50% of these xattrs in an alternating manner,
3. Tries to insert 400,000 new 255-byte sized xattrs
causes the following message to be printed on the console,

XFS (loop0): xfs_iflush_int: detected corrupt incore inode 131, total extents = -19916, nblocks = 102937, ptr ffff9ce33b098c00
XFS (loop0): xfs_do_force_shutdown(0x8) called from line 3739 of file fs/xfs/xfs_inode.c. Return address = ffffffffa4a94173

This indicates that we overflowed the 16-bits wide xattr extent
counter.

I have been informed that there are instances where a single file
has > 100 million hardlinks. With parent pointers being stored in xattr,
we will overflow the 16-bits wide xattr extent counter when large
number of hardlinks are created. Hence this patchset extends the
on-disk field to 32-bit length.

This patchset also includes the previously posted "Fix log reservation
calculation for xattr insert operation" patch as a bug fix. It
replaces the xattr set "mount" and "runtime" reservations with just
one static reservation. Hence we don't need the functionality to
calculate maximum sized 'xattr set' reservation separately anymore.

The patches can also be obtained from
https://github.com/chandanr/linux.git at branch xfs-extend-extent-counters.

Chandan Babu R (7):
  xfs: Fix log reservation calculation for xattr insert operation
  xfs: Check for per-inode extent count overflow
  xfs: Compute maximum height of directory BMBT separately
  xfs: Add "Use Dir BMBT height" argument to XFS_BM_MAXLEVELS()
  xfs: Use 2^27 as the maximum number of directory extents
  xfs: Extend data extent counter to 47 bits
  xfs: Extend attr extent counter to 32 bits

 fs/xfs/libxfs/xfs_attr.c        |  11 +--
 fs/xfs/libxfs/xfs_bmap.c        | 118 +++++++++++++++++++++++-------
 fs/xfs/libxfs/xfs_bmap.h        |   3 +-
 fs/xfs/libxfs/xfs_bmap_btree.h  |   4 +-
 fs/xfs/libxfs/xfs_format.h      |  49 ++++++++++---
 fs/xfs/libxfs/xfs_inode_buf.c   |  65 ++++++++++++++---
 fs/xfs/libxfs/xfs_inode_buf.h   |   2 +
 fs/xfs/libxfs/xfs_inode_fork.c  | 125 ++++++++++++++++++++++++++++++--
 fs/xfs/libxfs/xfs_inode_fork.h  |   2 +
 fs/xfs/libxfs/xfs_log_format.h  |   8 +-
 fs/xfs/libxfs/xfs_log_rlimit.c  |  29 --------
 fs/xfs/libxfs/xfs_trans_resv.c  |  75 +++++++++----------
 fs/xfs/libxfs/xfs_trans_resv.h  |   9 +--
 fs/xfs/libxfs/xfs_trans_space.h |  48 ++++++------
 fs/xfs/libxfs/xfs_types.h       |  11 ++-
 fs/xfs/scrub/inode.c            |  14 ++--
 fs/xfs/xfs_bmap_item.c          |   3 +-
 fs/xfs/xfs_inode.c              |  10 ++-
 fs/xfs/xfs_inode_item.c         |  10 ++-
 fs/xfs/xfs_inode_item_recover.c |  22 +++++-
 fs/xfs/xfs_mount.c              |   5 +-
 fs/xfs/xfs_mount.h              |   1 +
 fs/xfs/xfs_reflink.c            |   4 +-
 23 files changed, 451 insertions(+), 177 deletions(-)

Comments

Darrick J. Wong June 8, 2020, 5:31 p.m. UTC | #1
On Sat, Jun 06, 2020 at 01:57:38PM +0530, Chandan Babu R wrote:
> The commit xfs: fix inode fork extent count overflow
> (3f8a4f1d876d3e3e49e50b0396eaffcc4ba71b08) mentions that 10 billion
> per-inode data fork extents should be possible to create. However the
> corresponding on-disk field has an signed 32-bit type. Hence this
> patchset extends the on-disk field to 64-bit length out of which only
> the first 47-bits are valid.
> 
> Also, XFS has a per-inode xattr extent counter which is 16 bits
> wide. A workload which
> 1. Creates 1 million 255-byte sized xattrs,
> 2. Deletes 50% of these xattrs in an alternating manner,
> 3. Tries to insert 400,000 new 255-byte sized xattrs
> causes the following message to be printed on the console,
> 
> XFS (loop0): xfs_iflush_int: detected corrupt incore inode 131, total extents = -19916, nblocks = 102937, ptr ffff9ce33b098c00
> XFS (loop0): xfs_do_force_shutdown(0x8) called from line 3739 of file fs/xfs/xfs_inode.c. Return address = ffffffffa4a94173
> 
> This indicates that we overflowed the 16-bits wide xattr extent
> counter.
> 
> I have been informed that there are instances where a single file
> has > 100 million hardlinks. With parent pointers being stored in xattr,
> we will overflow the 16-bits wide xattr extent counter when large
> number of hardlinks are created. Hence this patchset extends the
> on-disk field to 32-bit length.
> 
> This patchset also includes the previously posted "Fix log reservation
> calculation for xattr insert operation" patch as a bug fix. It
> replaces the xattr set "mount" and "runtime" reservations with just
> one static reservation. Hence we don't need the functionality to
> calculate maximum sized 'xattr set' reservation separately anymore.
> 
> The patches can also be obtained from
> https://github.com/chandanr/linux.git at branch xfs-extend-extent-counters.
> 
> Chandan Babu R (7):
>   xfs: Fix log reservation calculation for xattr insert operation

What happened to that whole patchset with struct xfs_attr_set_resv
and whatnot?  Did all that get condensed down to this single patch?

--D

>   xfs: Check for per-inode extent count overflow
>   xfs: Compute maximum height of directory BMBT separately
>   xfs: Add "Use Dir BMBT height" argument to XFS_BM_MAXLEVELS()
>   xfs: Use 2^27 as the maximum number of directory extents
>   xfs: Extend data extent counter to 47 bits
>   xfs: Extend attr extent counter to 32 bits
> 
>  fs/xfs/libxfs/xfs_attr.c        |  11 +--
>  fs/xfs/libxfs/xfs_bmap.c        | 118 +++++++++++++++++++++++-------
>  fs/xfs/libxfs/xfs_bmap.h        |   3 +-
>  fs/xfs/libxfs/xfs_bmap_btree.h  |   4 +-
>  fs/xfs/libxfs/xfs_format.h      |  49 ++++++++++---
>  fs/xfs/libxfs/xfs_inode_buf.c   |  65 ++++++++++++++---
>  fs/xfs/libxfs/xfs_inode_buf.h   |   2 +
>  fs/xfs/libxfs/xfs_inode_fork.c  | 125 ++++++++++++++++++++++++++++++--
>  fs/xfs/libxfs/xfs_inode_fork.h  |   2 +
>  fs/xfs/libxfs/xfs_log_format.h  |   8 +-
>  fs/xfs/libxfs/xfs_log_rlimit.c  |  29 --------
>  fs/xfs/libxfs/xfs_trans_resv.c  |  75 +++++++++----------
>  fs/xfs/libxfs/xfs_trans_resv.h  |   9 +--
>  fs/xfs/libxfs/xfs_trans_space.h |  48 ++++++------
>  fs/xfs/libxfs/xfs_types.h       |  11 ++-
>  fs/xfs/scrub/inode.c            |  14 ++--
>  fs/xfs/xfs_bmap_item.c          |   3 +-
>  fs/xfs/xfs_inode.c              |  10 ++-
>  fs/xfs/xfs_inode_item.c         |  10 ++-
>  fs/xfs/xfs_inode_item_recover.c |  22 +++++-
>  fs/xfs/xfs_mount.c              |   5 +-
>  fs/xfs/xfs_mount.h              |   1 +
>  fs/xfs/xfs_reflink.c            |   4 +-
>  23 files changed, 451 insertions(+), 177 deletions(-)
> 
> -- 
> 2.20.1
>
Chandan Babu R June 9, 2020, 2:22 p.m. UTC | #2
On Monday 8 June 2020 11:01:03 PM IST Darrick J. Wong wrote:
> On Sat, Jun 06, 2020 at 01:57:38PM +0530, Chandan Babu R wrote:
> > The commit xfs: fix inode fork extent count overflow
> > (3f8a4f1d876d3e3e49e50b0396eaffcc4ba71b08) mentions that 10 billion
> > per-inode data fork extents should be possible to create. However the
> > corresponding on-disk field has an signed 32-bit type. Hence this
> > patchset extends the on-disk field to 64-bit length out of which only
> > the first 47-bits are valid.
> > 
> > Also, XFS has a per-inode xattr extent counter which is 16 bits
> > wide. A workload which
> > 1. Creates 1 million 255-byte sized xattrs,
> > 2. Deletes 50% of these xattrs in an alternating manner,
> > 3. Tries to insert 400,000 new 255-byte sized xattrs
> > causes the following message to be printed on the console,
> > 
> > XFS (loop0): xfs_iflush_int: detected corrupt incore inode 131, total extents = -19916, nblocks = 102937, ptr ffff9ce33b098c00
> > XFS (loop0): xfs_do_force_shutdown(0x8) called from line 3739 of file fs/xfs/xfs_inode.c. Return address = ffffffffa4a94173
> > 
> > This indicates that we overflowed the 16-bits wide xattr extent
> > counter.
> > 
> > I have been informed that there are instances where a single file
> > has > 100 million hardlinks. With parent pointers being stored in xattr,
> > we will overflow the 16-bits wide xattr extent counter when large
> > number of hardlinks are created. Hence this patchset extends the
> > on-disk field to 32-bit length.
> > 
> > This patchset also includes the previously posted "Fix log reservation
> > calculation for xattr insert operation" patch as a bug fix. It
> > replaces the xattr set "mount" and "runtime" reservations with just
> > one static reservation. Hence we don't need the functionality to
> > calculate maximum sized 'xattr set' reservation separately anymore.
> > 
> > The patches can also be obtained from
> > https://github.com/chandanr/linux.git at branch xfs-extend-extent-counters.
> > 
> > Chandan Babu R (7):
> >   xfs: Fix log reservation calculation for xattr insert operation
> 
> What happened to that whole patchset with struct xfs_attr_set_resv
> and whatnot?  Did all that get condensed down to this single patch?

Yes, with the new method, we have just one static log reservation rather than
having "mount" and "runtime" reservations for the xattr set operation. The
single static log reservation takes into account the worst case
possible. i.e.
- Double split of the Dabtree for large local xattrs.
- Bmbt blocks required for mapping the contents of a maximum sized
  (i.e. XATTR_SIZE_MAX bytes in size) remote attribute.