[PATCH V3 10/16] xfsprogs: Enable bulkstat ioctl to support 64-bit extent counters

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



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_BULKSTAT_NREXT64 flag. If the ioctl call fails with
-EINVAL error, the commit falls back to invoking the bulkstat ioctl without
passing XFS_BULK_IREQ_BULKSTAT_NREXT64 flag.

Signed-off-by: Chandan Babu R <chandan.babu@xxxxxxxxxx>
---
 fsr/xfs_fsr.c      |  4 ++--
 io/bulkstat.c      |  3 ++-
 libfrog/bulkstat.c | 55 ++++++++++++++++++++++++++++++++++++++++++----
 libxfs/xfs_fs.h    | 19 +++++++++++-----
 4 files changed, 69 insertions(+), 12 deletions(-)

diff --git a/fsr/xfs_fsr.c b/fsr/xfs_fsr.c
index bb5d4a2c..1fb2e5e7 100644
--- a/fsr/xfs_fsr.c
+++ b/fsr/xfs_fsr.c
@@ -606,7 +606,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);
 }
 
 /*
@@ -670,7 +670,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 = open_handle(&file_fd, fshandlep, p,
diff --git a/io/bulkstat.c b/io/bulkstat.c
index 4ae27586..8a9cf902 100644
--- a/io/bulkstat.c
+++ b/io/bulkstat.c
@@ -49,7 +49,7 @@ dump_bulkstat(
 	printf("\tbs_extsize_blks = %"PRIu32"\n", bstat->bs_extsize_blks);
 
 	printf("\tbs_nlink = %"PRIu32"\n", bstat->bs_nlink);
-	printf("\tbs_extents = %"PRIu32"\n", bstat->bs_extents);
+	printf("\tbs_extents32 = %"PRIu32"\n", bstat->bs_extents32);
 	printf("\tbs_aextents = %"PRIu32"\n", bstat->bs_aextents);
 	printf("\tbs_version = %"PRIu16"\n", bstat->bs_version);
 	printf("\tbs_forkoff = %"PRIu16"\n", bstat->bs_forkoff);
@@ -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..9de614d3 100644
--- a/libfrog/bulkstat.c
+++ b/libfrog/bulkstat.c
@@ -48,12 +48,13 @@ xfrog_bulkstat_single5(
 	struct xfs_fd			*xfd,
 	uint64_t			ino,
 	unsigned int			flags,
+	uint64_t			bulkstat_flags,
 	struct xfs_bulkstat		*bulkstat)
 {
 	struct xfs_bulkstat_req		*req;
 	int				ret;
 
-	if (flags & ~(XFS_BULK_IREQ_SPECIAL))
+	if (flags & ~(XFS_BULK_IREQ_SPECIAL | XFS_BULK_IREQ_BULKSTAT))
 		return -EINVAL;
 
 	ret = xfrog_bulkstat_alloc_req(1, ino, &req);
@@ -61,6 +62,7 @@ xfrog_bulkstat_single5(
 		return ret;
 
 	req->hdr.flags = flags;
+	req->hdr.bulkstat_flags = bulkstat_flags;
 	ret = ioctl(xfd->fd, XFS_IOC_BULKSTAT, req);
 	if (ret) {
 		ret = -errno;
@@ -73,6 +75,13 @@ xfrog_bulkstat_single5(
 	}
 
 	memcpy(bulkstat, req->bulkstat, sizeof(struct xfs_bulkstat));
+
+	if (!(flags & XFS_BULK_IREQ_BULKSTAT) ||
+	    !(bulkstat_flags & XFS_BULK_IREQ_BULKSTAT_NREXT64)) {
+		bulkstat->bs_extents64 = bulkstat->bs_extents32;
+		bulkstat->bs_extents32 = 0;
+	}
+
 free:
 	free(req);
 	return ret;
@@ -121,7 +130,18 @@ xfrog_bulkstat_single(
 	if (xfd->flags & XFROG_FLAG_BULKSTAT_FORCE_V1)
 		goto try_v1;
 
-	error = xfrog_bulkstat_single5(xfd, ino, flags, bulkstat);
+	error = xfrog_bulkstat_single5(xfd, ino, flags | XFS_BULK_IREQ_BULKSTAT,
+			XFS_BULK_IREQ_BULKSTAT_NREXT64, bulkstat);
+	if (error == -EINVAL) {
+		/*
+		 * Older versions of XFS kernel driver return -EINVAL because
+		 * they don't recognize XFS_BULK_IREQ_BULKSTAT as a valid
+		 * flag. Try once again without passing XFS_BULK_IREQ_BULKSTAT
+		 * flag.
+		 */
+		error = xfrog_bulkstat_single5(xfd, ino, flags, 0, bulkstat);
+	}
+
 	if (error == 0 || (xfd->flags & XFROG_FLAG_BULKSTAT_FORCE_V5))
 		return error;
 
@@ -259,10 +279,21 @@ xfrog_bulkstat5(
 	struct xfs_bulkstat_req	*req)
 {
 	int			ret;
+	int			i;
 
 	ret = ioctl(xfd->fd, XFS_IOC_BULKSTAT, req);
 	if (ret)
 		return -errno;
+
+	if (!(req->hdr.flags & XFS_BULK_IREQ_BULKSTAT) ||
+	    !(req->hdr.bulkstat_flags & XFS_BULK_IREQ_BULKSTAT_NREXT64)) {
+		for (i = 0; i < req->hdr.ocount; i++) {
+			req->bulkstat[i].bs_extents64 =
+				req->bulkstat[i].bs_extents32;
+			req->bulkstat[i].bs_extents32 = 0;
+		}
+	}
+
 	return 0;
 }
 
@@ -308,7 +339,22 @@ xfrog_bulkstat(
 	if (xfd->flags & XFROG_FLAG_BULKSTAT_FORCE_V1)
 		goto try_v1;
 
+	req->hdr.flags |= XFS_BULK_IREQ_BULKSTAT;
+	req->hdr.bulkstat_flags |= XFS_BULK_IREQ_BULKSTAT_NREXT64;
+
 	error = xfrog_bulkstat5(xfd, req);
+	if (error == -EINVAL) {
+		/*
+		 * Older versions of XFS kernel driver return -EINVAL because
+		 * they don't recognize XFS_BULK_IREQ_BULKSTAT as a valid
+		 * flag. Try once again without passing XFS_BULK_IREQ_BULKSTAT
+		 * flag.
+		 */
+		req->hdr.flags &= ~XFS_BULK_IREQ_BULKSTAT;
+		req->hdr.bulkstat_flags &= ~XFS_BULK_IREQ_BULKSTAT_NREXT64;
+		error = xfrog_bulkstat5(xfd, req);
+	}
+
 	if (error == 0 || (xfd->flags & XFROG_FLAG_BULKSTAT_FORCE_V5))
 		return error;
 
@@ -342,6 +388,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 +413,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 +454,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 +461,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/libxfs/xfs_fs.h b/libxfs/xfs_fs.h
index 2594fb64..b7690691 100644
--- a/libxfs/xfs_fs.h
+++ b/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_extents;	/* number of extents		*/
+	uint32_t	bs_extents32;	/* 32-bit data fork extent counter */
 	uint32_t	bs_aextents;	/* attribute number of extents	*/
 	uint16_t	bs_version;	/* structure version		*/
 	uint16_t	bs_forkoff;	/* inode fork offset in bytes	*/
@@ -403,8 +403,9 @@ 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;	/* 64-bit data fork extent counter */
 
-	uint64_t	bs_pad[7];	/* zeroed			*/
+	uint64_t	bs_pad[6];	/* zeroed			*/
 };
 
 #define XFS_BULKSTAT_VERSION_V1	(1)
@@ -469,7 +470,8 @@ struct xfs_bulk_ireq {
 	uint32_t	icount;		/* I: count of entries in buffer */
 	uint32_t	ocount;		/* O: count of entries filled out */
 	uint32_t	agno;		/* I: see comment for IREQ_AGNO	*/
-	uint64_t	reserved[5];	/* must be zero			*/
+	uint64_t	bulkstat_flags; /* I: Bulkstat operation flags */
+	uint64_t	reserved[4];	/* must be zero			*/
 };
 
 /*
@@ -492,9 +494,16 @@ struct xfs_bulk_ireq {
  */
 #define XFS_BULK_IREQ_METADIR	(1 << 2)
 
-#define XFS_BULK_IREQ_FLAGS_ALL	(XFS_BULK_IREQ_AGNO | \
+#define XFS_BULK_IREQ_BULKSTAT	(1 << 3)
+
+#define XFS_BULK_IREQ_FLAGS_ALL	(XFS_BULK_IREQ_AGNO |	 \
 				 XFS_BULK_IREQ_SPECIAL | \
-				 XFS_BULK_IREQ_METADIR)
+				 XFS_BULK_IREQ_METADIR | \
+				 XFS_BULK_IREQ_BULKSTAT)
+
+#define XFS_BULK_IREQ_BULKSTAT_NREXT64 (1 << 0)
+
+#define XFS_BULK_IREQ_BULKSTAT_FLAGS_ALL (XFS_BULK_IREQ_BULKSTAT_NREXT64)
 
 /* Operate on the root directory inode. */
 #define XFS_BULK_IREQ_SPECIAL_ROOT	(1)
-- 
2.30.2




[Index of Archives]     [XFS Filesystem Development (older mail)]     [Linux Filesystem Development]     [Linux Audio Users]     [Yosemite Trails]     [Linux Kernel]     [Linux RAID]     [Linux SCSI]


  Powered by Linux