This commit adds support to libfrog to enable reporting 64-bit extent counters to its users. In order to do so, bulkstat ioctl is now invoked with the newly introduced XFS_BULK_IREQ_NREXT64 flag if the underlying filesystem's geometry supports 64-bit extent counters. Reviewed-by: Darrick J. Wong <djwong@xxxxxxxxxx> Signed-off-by: Chandan Babu R <chandan.babu@xxxxxxxxxx> --- fsr/xfs_fsr.c | 4 ++-- io/bulkstat.c | 1 + libfrog/bulkstat.c | 29 +++++++++++++++++++++++++++-- man/man2/ioctl_xfs_bulkstat.2 | 10 +++++++++- 4 files changed, 39 insertions(+), 5 deletions(-) diff --git a/fsr/xfs_fsr.c b/fsr/xfs_fsr.c index 6cf8bfb7..ba02506d 100644 --- a/fsr/xfs_fsr.c +++ b/fsr/xfs_fsr.c @@ -590,7 +590,7 @@ cmp(const void *s1, const void *s2) (bs1->bs_version == XFS_BULKSTAT_VERSION_V5 && bs2->bs_version == XFS_BULKSTAT_VERSION_V5)); - return (bs2->bs_extents - bs1->bs_extents); + return (bs2->bs_extents64 - bs1->bs_extents64); } /* @@ -655,7 +655,7 @@ fsrfs(char *mntdir, xfs_ino_t startino, int targetrange) for (p = buf, endp = (buf + buflenout); p < endp ; p++) { /* Do some obvious checks now */ if (((p->bs_mode & S_IFMT) != S_IFREG) || - (p->bs_extents < 2)) + (p->bs_extents64 < 2)) continue; ret = -xfrog_bulkstat_v5_to_v1(&fsxfd, &bs1, p); diff --git a/io/bulkstat.c b/io/bulkstat.c index 41194200..a9ad87ca 100644 --- a/io/bulkstat.c +++ b/io/bulkstat.c @@ -57,6 +57,7 @@ dump_bulkstat( printf("\tbs_sick = 0x%"PRIx16"\n", bstat->bs_sick); printf("\tbs_checked = 0x%"PRIx16"\n", bstat->bs_checked); printf("\tbs_mode = 0%"PRIo16"\n", bstat->bs_mode); + printf("\tbs_extents64 = %"PRIu64"\n", bstat->bs_extents64); }; static void diff --git a/libfrog/bulkstat.c b/libfrog/bulkstat.c index 195f6ea0..0a90947f 100644 --- a/libfrog/bulkstat.c +++ b/libfrog/bulkstat.c @@ -56,6 +56,9 @@ xfrog_bulkstat_single5( if (flags & ~(XFS_BULK_IREQ_SPECIAL)) return -EINVAL; + if (xfd->fsgeom.flags & XFS_FSOP_GEOM_FLAGS_NREXT64) + flags |= XFS_BULK_IREQ_NREXT64; + ret = xfrog_bulkstat_alloc_req(1, ino, &req); if (ret) return ret; @@ -73,6 +76,12 @@ xfrog_bulkstat_single5( } memcpy(bulkstat, req->bulkstat, sizeof(struct xfs_bulkstat)); + + if (!(xfd->fsgeom.flags & XFS_FSOP_GEOM_FLAGS_NREXT64)) { + bulkstat->bs_extents64 = bulkstat->bs_extents; + bulkstat->bs_extents = 0; + } + free: free(req); return ret; @@ -129,6 +138,7 @@ xfrog_bulkstat_single( switch (error) { case -EOPNOTSUPP: case -ENOTTY: + assert(!(xfd->fsgeom.flags & XFS_FSOP_GEOM_FLAGS_NREXT64)); xfd->flags |= XFROG_FLAG_BULKSTAT_FORCE_V1; break; } @@ -259,10 +269,23 @@ xfrog_bulkstat5( struct xfs_bulkstat_req *req) { int ret; + int i; + + if (xfd->fsgeom.flags & XFS_FSOP_GEOM_FLAGS_NREXT64) + req->hdr.flags |= XFS_BULK_IREQ_NREXT64; ret = ioctl(xfd->fd, XFS_IOC_BULKSTAT, req); if (ret) return -errno; + + if (!(xfd->fsgeom.flags & XFS_FSOP_GEOM_FLAGS_NREXT64)) { + for (i = 0; i < req->hdr.ocount; i++) { + req->bulkstat[i].bs_extents64 = + req->bulkstat[i].bs_extents; + req->bulkstat[i].bs_extents = 0; + } + } + return 0; } @@ -316,6 +339,7 @@ xfrog_bulkstat( switch (error) { case -EOPNOTSUPP: case -ENOTTY: + assert(!(xfd->fsgeom.flags & XFS_FSOP_GEOM_FLAGS_NREXT64)); xfd->flags |= XFROG_FLAG_BULKSTAT_FORCE_V1; break; } @@ -342,6 +366,7 @@ xfrog_bulkstat_v5_to_v1( const struct xfs_bulkstat *bs5) { if (bs5->bs_aextents > UINT16_MAX || + bs5->bs_extents64 > INT32_MAX || cvt_off_fsb_to_b(xfd, bs5->bs_extsize_blks) > UINT32_MAX || cvt_off_fsb_to_b(xfd, bs5->bs_cowextsize_blks) > UINT32_MAX || time_too_big(bs5->bs_atime) || @@ -366,7 +391,7 @@ xfrog_bulkstat_v5_to_v1( bs1->bs_blocks = bs5->bs_blocks; bs1->bs_xflags = bs5->bs_xflags; bs1->bs_extsize = cvt_off_fsb_to_b(xfd, bs5->bs_extsize_blks); - bs1->bs_extents = bs5->bs_extents; + bs1->bs_extents = bs5->bs_extents64; bs1->bs_gen = bs5->bs_gen; bs1->bs_projid_lo = bs5->bs_projectid & 0xFFFF; bs1->bs_forkoff = bs5->bs_forkoff; @@ -407,7 +432,6 @@ xfrog_bulkstat_v1_to_v5( bs5->bs_blocks = bs1->bs_blocks; bs5->bs_xflags = bs1->bs_xflags; bs5->bs_extsize_blks = cvt_b_to_off_fsbt(xfd, bs1->bs_extsize); - bs5->bs_extents = bs1->bs_extents; bs5->bs_gen = bs1->bs_gen; bs5->bs_projectid = bstat_get_projid(bs1); bs5->bs_forkoff = bs1->bs_forkoff; @@ -415,6 +439,7 @@ xfrog_bulkstat_v1_to_v5( bs5->bs_checked = bs1->bs_checked; bs5->bs_cowextsize_blks = cvt_b_to_off_fsbt(xfd, bs1->bs_cowextsize); bs5->bs_aextents = bs1->bs_aextents; + bs5->bs_extents64 = bs1->bs_extents; } /* Allocate a bulkstat request. Returns zero or a negative error code. */ diff --git a/man/man2/ioctl_xfs_bulkstat.2 b/man/man2/ioctl_xfs_bulkstat.2 index cd0a9b06..3203ca0c 100644 --- a/man/man2/ioctl_xfs_bulkstat.2 +++ b/man/man2/ioctl_xfs_bulkstat.2 @@ -94,6 +94,13 @@ field. This flag may not be set at the same time as the .B XFS_BULK_IREQ_AGNO flag. +.TP +.B XFS_BULK_IREQ_NREXT64 +If this is set, data fork extent count is returned via bs_extents64 field and +0 is assigned to bs_extents. Otherwise, data fork extent count is returned +via bs_extents field and bs_extents64 is assigned a value of 0. In the second +case, bs_extents is set to (2^31 - 1) if data fork extent count is larger than +2^31. This flag may be set independently of whether other flags have been set. .RE .PP .I hdr.icount @@ -161,8 +168,9 @@ struct xfs_bulkstat { uint16_t bs_checked; uint16_t bs_mode; uint16_t bs_pad2; + uint64_t bs_extents64; - uint64_t bs_pad[7]; + uint64_t bs_pad[6]; }; .fi .in -- 2.35.1