This commit adds XFS_IOC_BULKSTAT_V6 to support 64-bit inode extent counters. The new field xfs_bulkstat->bs_extents64 is added to hold data extent count for filesystems supporting 64-bit data extent counters. However, the accessibility of this ioctl is deferred to a future commit which actually adds support for 64-bit data extent counter. Signed-off-by: Chandan Babu R <chandanrlinux@xxxxxxxxx> --- fs/xfs/libxfs/xfs_fs.h | 6 ++++-- fs/xfs/xfs_ioctl.c | 5 +++-- fs/xfs/xfs_itable.c | 26 +++++++++++++++++++++++--- 3 files changed, 30 insertions(+), 7 deletions(-) diff --git a/fs/xfs/libxfs/xfs_fs.h b/fs/xfs/libxfs/xfs_fs.h index d760a969599e..756be4ff5996 100644 --- a/fs/xfs/libxfs/xfs_fs.h +++ b/fs/xfs/libxfs/xfs_fs.h @@ -394,7 +394,7 @@ struct xfs_bulkstat { uint32_t bs_extsize_blks; /* extent size hint, blocks */ uint32_t bs_nlink; /* number of links */ - uint32_t bs_extents32; /* number of extents */ + uint32_t bs_extents32; /* number of extents; v5 only */ uint32_t bs_aextents; /* attribute number of extents */ uint16_t bs_version; /* structure version */ uint16_t bs_forkoff; /* inode fork offset in bytes */ @@ -403,12 +403,14 @@ struct xfs_bulkstat { uint16_t bs_checked; /* checked inode metadata */ uint16_t bs_mode; /* type and mode */ uint16_t bs_pad2; /* zeroed */ + uint64_t bs_extents64; /* number of extents; v6 only */ - uint64_t bs_pad[7]; /* zeroed */ + uint64_t bs_pad[6]; /* zeroed */ }; #define XFS_BULKSTAT_VERSION_V1 (1) #define XFS_BULKSTAT_VERSION_V5 (5) +#define XFS_BULKSTAT_VERSION_V6 (6) /* bs_sick flags */ #define XFS_BS_SICK_INODE (1 << 0) /* inode core */ diff --git a/fs/xfs/xfs_ioctl.c b/fs/xfs/xfs_ioctl.c index 85f45340cb16..19964b394dc4 100644 --- a/fs/xfs/xfs_ioctl.c +++ b/fs/xfs/xfs_ioctl.c @@ -826,7 +826,8 @@ xfs_bulkstat_fmt( struct xfs_ibulk *breq, const struct xfs_bulkstat *bstat) { - ASSERT(breq->version == XFS_BULKSTAT_VERSION_V5); + ASSERT(breq->version == XFS_BULKSTAT_VERSION_V5 || + breq->version == XFS_BULKSTAT_VERSION_V6); if (copy_to_user(breq->ubuffer, bstat, sizeof(struct xfs_bulkstat))) return -EFAULT; @@ -922,7 +923,7 @@ xfs_bulk_ireq_teardown( hdr->ocount = breq->ocount; } -/* Handle the v5 bulkstat ioctl. */ +/* Handle the v5/v6 bulkstat ioctl. */ STATIC int xfs_ioc_bulkstat( struct file *file, diff --git a/fs/xfs/xfs_itable.c b/fs/xfs/xfs_itable.c index f0daa65e61ff..8493870a0a87 100644 --- a/fs/xfs/xfs_itable.c +++ b/fs/xfs/xfs_itable.c @@ -74,6 +74,7 @@ xfs_bulkstat_one_int( struct xfs_inode *ip; /* incore inode pointer */ struct inode *inode; struct xfs_bulkstat *buf = bc->buf; + xfs_extnum_t nextents; int error = -EINVAL; error = xfs_iget(mp, tp, ino, @@ -95,7 +96,12 @@ xfs_bulkstat_one_int( buf->bs_gen = inode->i_generation; buf->bs_mode = inode->i_mode & S_IFMT; xfs_bulkstat_health(ip, buf); - buf->bs_version = XFS_BULKSTAT_VERSION_V5; + + if (bc->breq->version != XFS_BULKSTAT_VERSION_V6) + buf->bs_version = XFS_BULKSTAT_VERSION_V5; + else + buf->bs_version = XFS_BULKSTAT_VERSION_V6; + xfs_iunlock(ip, XFS_ILOCK_SHARED); xfs_irele(ip); @@ -134,11 +140,25 @@ xfs_bulkstat_one_int( buf->bs_xflags = xfs_ip2xflags(ip); buf->bs_extsize_blks = ip->i_extsize; - buf->bs_extents32 = xfs_ifork_nextents(&ip->i_df); + + nextents = xfs_ifork_nextents(&ip->i_df); + if (bc->breq->version != XFS_BULKSTAT_VERSION_V6) { + if (nextents > XFS_IFORK_EXTCNT_MAXS32) { + xfs_iunlock(ip, XFS_ILOCK_SHARED); + xfs_irele(ip); + error = -EINVAL; + goto out_advance; + } + buf->bs_extents32 = nextents; + buf->bs_version = XFS_BULKSTAT_VERSION_V5; + } else { + buf->bs_extents64 = nextents; + buf->bs_version = XFS_BULKSTAT_VERSION_V6; + } + xfs_bulkstat_health(ip, buf); buf->bs_aextents = xfs_ifork_nextents(ip->i_afp); buf->bs_forkoff = XFS_IFORK_BOFF(ip); - buf->bs_version = XFS_BULKSTAT_VERSION_V5; if (xfs_sb_version_has_v3inode(&mp->m_sb)) { buf->bs_btime = ip->i_crtime.tv_sec; -- 2.30.2