linux-xfs.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [PATCH v2 0/9] libxfrog: wrap version ioctl calls
@ 2019-08-30  4:20 Darrick J. Wong
  2019-08-30  4:20 ` [PATCH 1/9] libxfs: revert FSGEOMETRY v5 -> v4 hack Darrick J. Wong
                   ` (8 more replies)
  0 siblings, 9 replies; 31+ messages in thread
From: Darrick J. Wong @ 2019-08-30  4:20 UTC (permalink / raw)
  To: sandeen, darrick.wong; +Cc: linux-xfs

Hi all,

This series introduces into libfrog some wrapper functions for the XFS
geometry, bulkstat, and inumbers ioctls, then converts the tools to use
the new wrappers.  This is intended to smooth the transition to the new
v5 ioctls that were introduced in kernel 5.3 by providing standard
fallback code to the old ioctls on old kernels.

If you're going to start using this mess, you probably ought to just
pull from my git trees, which are linked below.

This is an extraordinary way to destroy everything.  Enjoy!
Comments and questions are, as always, welcome.

--D

xfsprogs git tree:
https://git.kernel.org/cgit/linux/kernel/git/djwong/xfsprogs-dev.git/log/?h=libfrog-refactor

^ permalink raw reply	[flat|nested] 31+ messages in thread

* [PATCH 1/9] libxfs: revert FSGEOMETRY v5 -> v4 hack
  2019-08-30  4:20 [PATCH v2 0/9] libxfrog: wrap version ioctl calls Darrick J. Wong
@ 2019-08-30  4:20 ` Darrick J. Wong
  2019-08-30 21:03   ` Allison Collins
  2019-09-02 22:49   ` Dave Chinner
  2019-08-30  4:20 ` [PATCH 2/9] xfsprogs: update spdx tags in LICENSES/ Darrick J. Wong
                   ` (7 subsequent siblings)
  8 siblings, 2 replies; 31+ messages in thread
From: Darrick J. Wong @ 2019-08-30  4:20 UTC (permalink / raw)
  To: sandeen, darrick.wong; +Cc: linux-xfs

From: Darrick J. Wong <darrick.wong@oracle.com>

Revert the #define redirection of XFS_IOC_FSGEOMETRY to the old V4
ioctl.

Signed-off-by: Darrick J. Wong <darrick.wong@oracle.com>
---
 libxfs/xfs_fs.h |    4 +---
 1 file changed, 1 insertion(+), 3 deletions(-)


diff --git a/libxfs/xfs_fs.h b/libxfs/xfs_fs.h
index 67fceffc..31ac6323 100644
--- a/libxfs/xfs_fs.h
+++ b/libxfs/xfs_fs.h
@@ -822,9 +822,7 @@ struct xfs_scrub_metadata {
 #define XFS_IOC_ATTRMULTI_BY_HANDLE  _IOW ('X', 123, struct xfs_fsop_attrmulti_handlereq)
 #define XFS_IOC_FSGEOMETRY_V4	     _IOR ('X', 124, struct xfs_fsop_geom_v4)
 #define XFS_IOC_GOINGDOWN	     _IOR ('X', 125, uint32_t)
-/* For compatibility, for now */
-/* #define XFS_IOC_FSGEOMETRY	     _IOR ('X', 126, struct xfs_fsop_geom_v5) */
-#define XFS_IOC_FSGEOMETRY XFS_IOC_FSGEOMETRY_V4
+#define XFS_IOC_FSGEOMETRY	     _IOR ('X', 126, struct xfs_fsop_geom)
 #define XFS_IOC_BULKSTAT	     _IOR ('X', 127, struct xfs_bulkstat_req)
 #define XFS_IOC_INUMBERS	     _IOR ('X', 128, struct xfs_inumbers_req)
 


^ permalink raw reply related	[flat|nested] 31+ messages in thread

* [PATCH 2/9] xfsprogs: update spdx tags in LICENSES/
  2019-08-30  4:20 [PATCH v2 0/9] libxfrog: wrap version ioctl calls Darrick J. Wong
  2019-08-30  4:20 ` [PATCH 1/9] libxfs: revert FSGEOMETRY v5 -> v4 hack Darrick J. Wong
@ 2019-08-30  4:20 ` Darrick J. Wong
  2019-08-30 21:03   ` Allison Collins
  2019-08-30  4:20 ` [PATCH 3/9] libfrog: refactor online geometry queries Darrick J. Wong
                   ` (6 subsequent siblings)
  8 siblings, 1 reply; 31+ messages in thread
From: Darrick J. Wong @ 2019-08-30  4:20 UTC (permalink / raw)
  To: sandeen, darrick.wong; +Cc: linux-xfs

From: Darrick J. Wong <darrick.wong@oracle.com>

Update the GPL related SPDX tags in LICENSES to reflect the SPDX 3.0
tagging formats.

Signed-off-by: Darrick J. Wong <darrick.wong@oracle.com>
---
 LICENSES/GPL-2.0 |    6 ++++++
 1 file changed, 6 insertions(+)


diff --git a/LICENSES/GPL-2.0 b/LICENSES/GPL-2.0
index b8db91d3..ff0812fd 100644
--- a/LICENSES/GPL-2.0
+++ b/LICENSES/GPL-2.0
@@ -1,5 +1,7 @@
 Valid-License-Identifier: GPL-2.0
+Valid-License-Identifier: GPL-2.0-only
 Valid-License-Identifier: GPL-2.0+
+Valid-License-Identifier: GPL-2.0-or-later
 SPDX-URL: https://spdx.org/licenses/GPL-2.0.html
 Usage-Guide:
   To use this license in source code, put one of the following SPDX
@@ -7,8 +9,12 @@ Usage-Guide:
   guidelines in the licensing rules documentation.
   For 'GNU General Public License (GPL) version 2 only' use:
     SPDX-License-Identifier: GPL-2.0
+  or
+    SPDX-License-Identifier: GPL-2.0-only
   For 'GNU General Public License (GPL) version 2 or any later version' use:
     SPDX-License-Identifier: GPL-2.0+
+  or
+    SPDX-License-Identifier: GPL-2.0-or-later
 License-Text:
 
 		    GNU GENERAL PUBLIC LICENSE


^ permalink raw reply related	[flat|nested] 31+ messages in thread

* [PATCH 3/9] libfrog: refactor online geometry queries
  2019-08-30  4:20 [PATCH v2 0/9] libxfrog: wrap version ioctl calls Darrick J. Wong
  2019-08-30  4:20 ` [PATCH 1/9] libxfs: revert FSGEOMETRY v5 -> v4 hack Darrick J. Wong
  2019-08-30  4:20 ` [PATCH 2/9] xfsprogs: update spdx tags in LICENSES/ Darrick J. Wong
@ 2019-08-30  4:20 ` Darrick J. Wong
  2019-08-30 21:03   ` Allison Collins
  2019-09-03 22:51   ` Dave Chinner
  2019-08-30  4:20 ` [PATCH 4/9] libfrog: introduce xfs_fd to wrap an fd to a file on an xfs filesystem Darrick J. Wong
                   ` (5 subsequent siblings)
  8 siblings, 2 replies; 31+ messages in thread
From: Darrick J. Wong @ 2019-08-30  4:20 UTC (permalink / raw)
  To: sandeen, darrick.wong; +Cc: linux-xfs

From: Darrick J. Wong <darrick.wong@oracle.com>

Refactor all the open-coded XFS_IOC_FSGEOMETRY queries into a single
helper that we can use to standardize behaviors across mixed xfslibs
versions.  This is the prelude to introducing a new FSGEOMETRY version
in 5.2 and needing to fix the (relatively few) client programs.

Signed-off-by: Darrick J. Wong <darrick.wong@oracle.com>
---
 Makefile            |    1 +
 fsr/xfs_fsr.c       |   28 ++++++----------------------
 growfs/xfs_growfs.c |   29 ++++++++++++-----------------
 include/xfrog.h     |   22 ++++++++++++++++++++++
 io/bmap.c           |    7 ++++---
 io/fsmap.c          |    5 +++--
 io/open.c           |   15 +++++++++++----
 io/stat.c           |    8 ++++++--
 libfrog/fsgeom.c    |   26 ++++++++++++++++++++++++++
 quota/free.c        |   10 ++++++----
 repair/xfs_repair.c |    8 +++++---
 rtcp/Makefile       |    3 +++
 rtcp/xfs_rtcp.c     |    9 +++++----
 scrub/common.h      |    2 ++
 scrub/phase1.c      |    5 +++--
 spaceman/file.c     |   12 ++++++++----
 spaceman/info.c     |   24 +++++++-----------------
 17 files changed, 130 insertions(+), 84 deletions(-)
 create mode 100644 include/xfrog.h


diff --git a/Makefile b/Makefile
index 9204bed8..0edc2700 100644
--- a/Makefile
+++ b/Makefile
@@ -107,6 +107,7 @@ copy: libxlog
 mkfs: libxcmd
 spaceman: libxcmd
 scrub: libhandle libxcmd
+rtcp: libfrog
 
 ifeq ($(HAVE_BUILDDEFS), yes)
 include $(BUILDRULES)
diff --git a/fsr/xfs_fsr.c b/fsr/xfs_fsr.c
index 1963a05e..4b239a30 100644
--- a/fsr/xfs_fsr.c
+++ b/fsr/xfs_fsr.c
@@ -11,6 +11,7 @@
 #include "xfs_bmap_btree.h"
 #include "xfs_attr_sf.h"
 #include "path.h"
+#include "xfrog.h"
 
 #include <fcntl.h>
 #include <errno.h>
@@ -83,9 +84,8 @@ int cmp(const void *, const void *);
 static void tmp_init(char *mnt);
 static char * tmp_next(char *mnt);
 static void tmp_close(char *mnt);
-int xfs_getgeom(int , struct xfs_fsop_geom_v1 * );
 
-static struct xfs_fsop_geom_v1 fsgeom;	/* geometry of active mounted system */
+static struct xfs_fsop_geom fsgeom;	/* geometry of active mounted system */
 
 #define NMOUNT 64
 static int numfs;
@@ -102,12 +102,6 @@ static int	nfrags = 0;	/* Debug option: Coerse into specific number
 				 * of extents */
 static int	openopts = O_CREAT|O_EXCL|O_RDWR|O_DIRECT;
 
-static int
-xfs_fsgeometry(int fd, struct xfs_fsop_geom_v1 *geom)
-{
-    return ioctl(fd, XFS_IOC_FSGEOMETRY_V1, geom);
-}
-
 static int
 xfs_bulkstat_single(int fd, xfs_ino_t *lastip, struct xfs_bstat *ubuffer)
 {
@@ -630,7 +624,8 @@ fsrfs(char *mntdir, xfs_ino_t startino, int targetrange)
 		return -1;
 	}
 
-	if (xfs_getgeom(fsfd, &fsgeom) < 0 ) {
+	ret = xfrog_geometry(fsfd, &fsgeom);
+	if (ret) {
 		fsrprintf(_("Skipping %s: could not get XFS geometry\n"),
 			  mntdir);
 		close(fsfd);
@@ -772,7 +767,8 @@ fsrfile(char *fname, xfs_ino_t ino)
 	}
 
 	/* Get the fs geometry */
-	if (xfs_getgeom(fsfd, &fsgeom) < 0 ) {
+	error = xfrog_geometry(fsfd, &fsgeom);
+	if (error) {
 		fsrprintf(_("Unable to get geom on fs for: %s\n"), fname);
 		goto out;
 	}
@@ -1612,18 +1608,6 @@ getnextents(int fd)
 	return(nextents);
 }
 
-/*
- * Get the fs geometry
- */
-int
-xfs_getgeom(int fd, struct xfs_fsop_geom_v1 *fsgeom)
-{
-	if (xfs_fsgeometry(fd, fsgeom) < 0) {
-		return -1;
-	}
-	return 0;
-}
-
 /*
  * Get xfs realtime space information
  */
diff --git a/growfs/xfs_growfs.c b/growfs/xfs_growfs.c
index 20089d2b..5c881375 100644
--- a/growfs/xfs_growfs.c
+++ b/growfs/xfs_growfs.c
@@ -7,6 +7,7 @@
 #include "libxfs.h"
 #include "path.h"
 #include "fsgeom.h"
+#include "xfrog.h"
 
 static void
 usage(void)
@@ -63,6 +64,7 @@ main(int argc, char **argv)
 	fs_path_t		*fs;	/* mount point information */
 	libxfs_init_t		xi;	/* libxfs structure */
 	char			rpath[PATH_MAX];
+	int			ret;
 
 	progname = basename(argv[0]);
 	setlocale(LC_ALL, "");
@@ -165,22 +167,14 @@ main(int argc, char **argv)
 	}
 
 	/* get the current filesystem size & geometry */
-	if (xfsctl(fname, ffd, XFS_IOC_FSGEOMETRY, &geo) < 0) {
-		/*
-		 * OK, new xfsctl barfed - back off and try earlier version
-		 * as we're probably running an older kernel version.
-		 * Only field added in the v2 geometry xfsctl is "logsunit"
-		 * so we'll zero that out for later display (as zero).
-		 */
-		geo.logsunit = 0;
-		if (xfsctl(fname, ffd, XFS_IOC_FSGEOMETRY_V1, &geo) < 0) {
-			fprintf(stderr, _(
-				"%s: cannot determine geometry of filesystem"
-				" mounted at %s: %s\n"),
-				progname, fname, strerror(errno));
-			exit(1);
-		}
+	ret = xfrog_geometry(ffd, &geo);
+	if (ret) {
+		fprintf(stderr,
+	_("%s: cannot determine geometry of filesystem mounted at %s: %s\n"),
+			progname, fname, strerror(ret));
+		exit(1);
 	}
+
 	isint = geo.logstart > 0;
 
 	/*
@@ -359,9 +353,10 @@ main(int argc, char **argv)
 		}
 	}
 
-	if (xfsctl(fname, ffd, XFS_IOC_FSGEOMETRY_V1, &ngeo) < 0) {
+	ret = xfrog_geometry(ffd, &ngeo);
+	if (ret) {
 		fprintf(stderr, _("%s: XFS_IOC_FSGEOMETRY xfsctl failed: %s\n"),
-			progname, strerror(errno));
+			progname, strerror(ret));
 		exit(1);
 	}
 	if (geo.datablocks != ngeo.datablocks)
diff --git a/include/xfrog.h b/include/xfrog.h
new file mode 100644
index 00000000..f3541193
--- /dev/null
+++ b/include/xfrog.h
@@ -0,0 +1,22 @@
+/* SPDX-License-Identifier: GPL-2.0-or-later */
+/*
+ * Copyright (c) 2019 Oracle, Inc.
+ * All Rights Reserved.
+ */
+#ifndef __XFROG_H__
+#define __XFROG_H__
+
+/*
+ * XFS Filesystem Random Online Gluecode
+ * =====================================
+ *
+ * These support functions wrap the more complex xfs ioctls so that xfs
+ * utilities can take advantage of them without having to deal with graceful
+ * degradation in the face of new ioctls.  They will also provide higher level
+ * abstractions when possible.
+ */
+
+struct xfs_fsop_geom;
+int xfrog_geometry(int fd, struct xfs_fsop_geom *fsgeo);
+
+#endif	/* __XFROG_H__ */
diff --git a/io/bmap.c b/io/bmap.c
index d408826a..8f792a09 100644
--- a/io/bmap.c
+++ b/io/bmap.c
@@ -9,6 +9,7 @@
 #include "input.h"
 #include "init.h"
 #include "io.h"
+#include "xfrog.h"
 
 static cmdinfo_t bmap_cmd;
 
@@ -105,11 +106,11 @@ bmap_f(
 		bmv_iflags &= ~(BMV_IF_PREALLOC|BMV_IF_NO_DMAPI_READ);
 
 	if (vflag) {
-		c = xfsctl(file->name, file->fd, XFS_IOC_FSGEOMETRY_V1, &fsgeo);
-		if (c < 0) {
+		c = xfrog_geometry(file->fd, &fsgeo);
+		if (c) {
 			fprintf(stderr,
 				_("%s: can't get geometry [\"%s\"]: %s\n"),
-				progname, file->name, strerror(errno));
+				progname, file->name, strerror(c));
 			exitcode = 1;
 			return 0;
 		}
diff --git a/io/fsmap.c b/io/fsmap.c
index 477c36fc..bf741e2a 100644
--- a/io/fsmap.c
+++ b/io/fsmap.c
@@ -9,6 +9,7 @@
 #include "path.h"
 #include "io.h"
 #include "input.h"
+#include "xfrog.h"
 
 static cmdinfo_t	fsmap_cmd;
 static dev_t		xfs_data_dev;
@@ -447,8 +448,8 @@ fsmap_f(
 	}
 
 	if (vflag) {
-		c = ioctl(file->fd, XFS_IOC_FSGEOMETRY, &fsgeo);
-		if (c < 0) {
+		c = xfrog_geometry(file->fd, &fsgeo);
+		if (c) {
 			fprintf(stderr,
 				_("%s: can't get geometry [\"%s\"]: %s\n"),
 				progname, file->name, strerror(errno));
diff --git a/io/open.c b/io/open.c
index c7f5248a..8b24a4f9 100644
--- a/io/open.c
+++ b/io/open.c
@@ -9,6 +9,7 @@
 #include "init.h"
 #include "io.h"
 #include "libxfs.h"
+#include "xfrog.h"
 
 #ifndef __O_TMPFILE
 #if defined __alpha__
@@ -118,10 +119,16 @@ openfile(
 	if (flags & IO_PATH) {
 		/* Can't call ioctl() on O_PATH fds */
 		memset(geom, 0, sizeof(*geom));
-	} else if (xfsctl(path, fd, XFS_IOC_FSGEOMETRY, geom) < 0) {
-		perror("XFS_IOC_FSGEOMETRY");
-		close(fd);
-		return -1;
+	} else {
+		int	ret;
+
+		ret = xfrog_geometry(fd, geom);
+		if (ret) {
+			errno = ret;
+			perror("XFS_IOC_FSGEOMETRY");
+			close(fd);
+			return -1;
+		}
 	}
 
 	if (!(flags & (IO_READONLY | IO_PATH)) && (flags & IO_REALTIME)) {
diff --git a/io/stat.c b/io/stat.c
index 37c0b2e8..865407b1 100644
--- a/io/stat.c
+++ b/io/stat.c
@@ -12,6 +12,7 @@
 #include "io.h"
 #include "statx.h"
 #include "libxfs.h"
+#include "xfrog.h"
 
 #include <fcntl.h>
 
@@ -178,6 +179,7 @@ statfs_f(
 	struct xfs_fsop_counts	fscounts;
 	struct xfs_fsop_geom	fsgeo;
 	struct statfs		st;
+	int			ret;
 
 	printf(_("fd.path = \"%s\"\n"), file->name);
 	if (platform_fstatfs(file->fd, &st) < 0) {
@@ -194,8 +196,10 @@ statfs_f(
 	}
 	if (file->flags & IO_FOREIGN)
 		return 0;
-	if ((xfsctl(file->name, file->fd, XFS_IOC_FSGEOMETRY_V1, &fsgeo)) < 0) {
-		perror("XFS_IOC_FSGEOMETRY_V1");
+	ret = xfrog_geometry(file->fd, &fsgeo);
+	if (ret) {
+		errno = ret;
+		perror("XFS_IOC_FSGEOMETRY");
 	} else {
 		printf(_("geom.bsize = %u\n"), fsgeo.blocksize);
 		printf(_("geom.agcount = %u\n"), fsgeo.agcount);
diff --git a/libfrog/fsgeom.c b/libfrog/fsgeom.c
index 8879d161..69d24774 100644
--- a/libfrog/fsgeom.c
+++ b/libfrog/fsgeom.c
@@ -4,6 +4,7 @@
  */
 #include "libxfs.h"
 #include "fsgeom.h"
+#include "xfrog.h"
 
 void
 xfs_report_geom(
@@ -67,3 +68,28 @@ xfs_report_geom(
 		geo->rtextsize * geo->blocksize, (unsigned long long)geo->rtblocks,
 			(unsigned long long)geo->rtextents);
 }
+
+/* Try to obtain the xfs geometry.  On error returns a positive error code. */
+int
+xfrog_geometry(
+	int			fd,
+	struct xfs_fsop_geom	*fsgeo)
+{
+	int			ret;
+
+	memset(fsgeo, 0, sizeof(*fsgeo));
+
+	ret = ioctl(fd, XFS_IOC_FSGEOMETRY, fsgeo);
+	if (!ret)
+		return 0;
+
+	ret = ioctl(fd, XFS_IOC_FSGEOMETRY_V4, fsgeo);
+	if (!ret)
+		return 0;
+
+	ret = ioctl(fd, XFS_IOC_FSGEOMETRY_V1, fsgeo);
+	if (!ret)
+		return 0;
+
+	return errno;
+}
diff --git a/quota/free.c b/quota/free.c
index 1d13006e..65cb1e21 100644
--- a/quota/free.c
+++ b/quota/free.c
@@ -8,6 +8,7 @@
 #include "command.h"
 #include "init.h"
 #include "quota.h"
+#include "xfrog.h"
 
 static cmdinfo_t free_cmd;
 
@@ -51,7 +52,7 @@ mount_free_space_data(
 	struct xfs_fsop_geom	fsgeo;
 	struct statfs		st;
 	uint64_t		logsize, count, free;
-	int			fd;
+	int			fd, ret;
 
 	if ((fd = open(mount->fs_dir, O_RDONLY)) < 0) {
 		exitcode = 1;
@@ -67,9 +68,10 @@ mount_free_space_data(
 	}
 
 	if (!(mount->fs_flags & FS_FOREIGN)) {
-		if ((xfsctl(mount->fs_dir, fd, XFS_IOC_FSGEOMETRY_V1,
-							&fsgeo)) < 0) {
-			perror("XFS_IOC_FSGEOMETRY_V1");
+		ret = xfrog_geometry(fd, &fsgeo);
+		if (ret) {
+			errno = ret;
+			perror("XFS_IOC_FSGEOMETRY");
 			close(fd);
 			return 0;
 		}
diff --git a/repair/xfs_repair.c b/repair/xfs_repair.c
index ce70e2de..32c9a96e 100644
--- a/repair/xfs_repair.c
+++ b/repair/xfs_repair.c
@@ -22,6 +22,7 @@
 #include "dinode.h"
 #include "slab.h"
 #include "rmap.h"
+#include "xfrog.h"
 
 /*
  * option tables for getsubopt calls
@@ -634,13 +635,14 @@ static void
 check_fs_vs_host_sectsize(
 	struct xfs_sb	*sb)
 {
-	int	fd;
+	int	fd, ret;
 	long	old_flags;
-	struct xfs_fsop_geom_v1 geom = { 0 };
+	struct xfs_fsop_geom	geom = { 0 };
 
 	fd = libxfs_device_to_fd(x.ddev);
 
-	if (ioctl(fd, XFS_IOC_FSGEOMETRY_V1, &geom) < 0) {
+	ret = xfrog_geometry(fd, &geom);
+	if (ret) {
 		do_log(_("Cannot get host filesystem geometry.\n"
 	"Repair may fail if there is a sector size mismatch between\n"
 	"the image and the host filesystem.\n"));
diff --git a/rtcp/Makefile b/rtcp/Makefile
index 808b5378..264b4f27 100644
--- a/rtcp/Makefile
+++ b/rtcp/Makefile
@@ -9,6 +9,9 @@ LTCOMMAND = xfs_rtcp
 CFILES = xfs_rtcp.c
 LLDFLAGS = -static
 
+LLDLIBS = $(LIBFROG)
+LTDEPENDENCIES = $(LIBFROG)
+
 default: depend $(LTCOMMAND)
 
 include $(BUILDRULES)
diff --git a/rtcp/xfs_rtcp.c b/rtcp/xfs_rtcp.c
index 1027c913..6d012dda 100644
--- a/rtcp/xfs_rtcp.c
+++ b/rtcp/xfs_rtcp.c
@@ -5,6 +5,7 @@
  */
 
 #include "libxfs.h"
+#include "xfrog.h"
 
 int rtcp(char *, char *, int);
 int xfsrtextsize(char *path);
@@ -368,8 +369,8 @@ rtcp( char *source, char *target, int fextsize)
 int
 xfsrtextsize( char *path)
 {
-	int fd, rval, rtextsize;
-	struct xfs_fsop_geom_v1 geo;
+	struct xfs_fsop_geom	geo;
+	int			fd, rval, rtextsize;
 
 	fd = open( path, O_RDONLY );
 	if ( fd < 0 ) {
@@ -377,9 +378,9 @@ xfsrtextsize( char *path)
 			progname, path, strerror(errno));
 		return -1;
 	}
-	rval = xfsctl( path, fd, XFS_IOC_FSGEOMETRY_V1, &geo );
+	rval = xfrog_geometry(fd, &geo);
 	close(fd);
-	if ( rval < 0 )
+	if (rval)
 		return -1;
 
 	rtextsize = geo.rtextsize * geo.blocksize;
diff --git a/scrub/common.h b/scrub/common.h
index e85a0333..33555891 100644
--- a/scrub/common.h
+++ b/scrub/common.h
@@ -28,6 +28,8 @@ void __str_out(struct scrub_ctx *ctx, const char *descr, enum error_level level,
 
 #define str_errno(ctx, str) \
 	__str_out(ctx, str, S_ERROR,	errno,	__FILE__, __LINE__, NULL)
+#define str_liberror(ctx, error, str) \
+	__str_out(ctx, str, S_ERROR,	error,	__FILE__, __LINE__, NULL)
 #define str_error(ctx, str, ...) \
 	__str_out(ctx, str, S_ERROR,	0,	__FILE__, __LINE__, __VA_ARGS__)
 #define str_warn(ctx, str, ...) \
diff --git a/scrub/phase1.c b/scrub/phase1.c
index 04a5f4a9..bdd23d26 100644
--- a/scrub/phase1.c
+++ b/scrub/phase1.c
@@ -26,6 +26,7 @@
 #include "disk.h"
 #include "scrub.h"
 #include "repair.h"
+#include "xfrog.h"
 
 /* Phase 1: Find filesystem geometry (and clean up after) */
 
@@ -129,9 +130,9 @@ _("Does not appear to be an XFS filesystem!"));
 	}
 
 	/* Retrieve XFS geometry. */
-	error = ioctl(ctx->mnt_fd, XFS_IOC_FSGEOMETRY, &ctx->geo);
+	error = xfrog_geometry(ctx->mnt_fd, &ctx->geo);
 	if (error) {
-		str_errno(ctx, ctx->mntpoint);
+		str_liberror(ctx, error, _("Retrieving XFS geometry"));
 		return false;
 	}
 
diff --git a/spaceman/file.c b/spaceman/file.c
index 7e33e07e..9dba1e58 100644
--- a/spaceman/file.c
+++ b/spaceman/file.c
@@ -6,6 +6,7 @@
  */
 
 #include "libxfs.h"
+#include "xfrog.h"
 #include <sys/mman.h>
 #include "command.h"
 #include "input.h"
@@ -48,7 +49,7 @@ openfile(
 	struct fs_path	*fs_path)
 {
 	struct fs_path	*fsp;
-	int		fd;
+	int		fd, ret;
 
 	fd = open(path, 0);
 	if (fd < 0) {
@@ -56,13 +57,16 @@ openfile(
 		return -1;
 	}
 
-	if (ioctl(fd, XFS_IOC_FSGEOMETRY, geom) < 0) {
-		if (errno == ENOTTY)
+	ret = xfrog_geometry(fd, geom);
+	if (ret) {
+		if (ret == ENOTTY)
 			fprintf(stderr,
 _("%s: Not on a mounted XFS filesystem.\n"),
 					path);
-		else
+		else {
+			errno = ret;
 			perror("XFS_IOC_FSGEOMETRY");
+		}
 		close(fd);
 		return -1;
 	}
diff --git a/spaceman/info.c b/spaceman/info.c
index 01d0744a..d32db6ab 100644
--- a/spaceman/info.c
+++ b/spaceman/info.c
@@ -4,6 +4,7 @@
  * Author: Darrick J. Wong <darrick.wong@oracle.com>
  */
 #include "libxfs.h"
+#include "xfrog.h"
 #include "command.h"
 #include "init.h"
 #include "path.h"
@@ -37,24 +38,13 @@ info_f(
 	}
 
 	/* get the current filesystem size & geometry */
-	error = ioctl(file->fd, XFS_IOC_FSGEOMETRY, &geo);
+	error = xfrog_geometry(file->fd, &geo);
 	if (error) {
-		/*
-		 * OK, new xfsctl barfed - back off and try earlier version
-		 * as we're probably running an older kernel version.
-		 * Only field added in the v2 geometry xfsctl is "logsunit"
-		 * so we'll zero that out for later display (as zero).
-		 */
-		geo.logsunit = 0;
-		error = ioctl(file->fd, XFS_IOC_FSGEOMETRY_V1, &geo);
-		if (error) {
-			fprintf(stderr, _(
-				"%s: cannot determine geometry of filesystem"
-				" mounted at %s: %s\n"),
-				progname, file->name, strerror(errno));
-			exitcode = 1;
-			return 0;
-		}
+		fprintf(stderr,
+	_("%s: cannot determine geometry of filesystem mounted at %s: %s\n"),
+			progname, file->name, strerror(error));
+		exitcode = 1;
+		return 0;
 	}
 
 	xfs_report_geom(&geo, file->fs_path.fs_name, file->fs_path.fs_log,


^ permalink raw reply related	[flat|nested] 31+ messages in thread

* [PATCH 4/9] libfrog: introduce xfs_fd to wrap an fd to a file on an xfs filesystem
  2019-08-30  4:20 [PATCH v2 0/9] libxfrog: wrap version ioctl calls Darrick J. Wong
                   ` (2 preceding siblings ...)
  2019-08-30  4:20 ` [PATCH 3/9] libfrog: refactor online geometry queries Darrick J. Wong
@ 2019-08-30  4:20 ` Darrick J. Wong
  2019-08-30 23:29   ` Allison Collins
  2019-09-03 22:53   ` Dave Chinner
  2019-08-30  4:20 ` [PATCH 5/9] libfrog: store more inode and block geometry in struct xfs_fd Darrick J. Wong
                   ` (4 subsequent siblings)
  8 siblings, 2 replies; 31+ messages in thread
From: Darrick J. Wong @ 2019-08-30  4:20 UTC (permalink / raw)
  To: sandeen, darrick.wong; +Cc: linux-xfs

From: Darrick J. Wong <darrick.wong@oracle.com>

Introduce a new "xfs_fd" context structure where we can store a file
descriptor and all the runtime fs context (geometry, which ioctls work,
etc.) that goes with it.  We're going to create wrappers for the
bulkstat and inumbers ioctls in subsequent patches; and when we
introduce the v5 bulkstat/inumbers ioctls we'll need all that context to
downgrade gracefully on old kernels.  Start the transition by adopting
xfs_fd natively in scrub.

Signed-off-by: Darrick J. Wong <darrick.wong@oracle.com>
---
 include/xfrog.h    |   20 ++++++++++++++++++++
 libfrog/fsgeom.c   |   32 ++++++++++++++++++++++++++++++++
 scrub/fscounters.c |   22 ++++++++++++----------
 scrub/inodes.c     |   10 +++++-----
 scrub/phase1.c     |   39 +++++++++++++++++++--------------------
 scrub/phase2.c     |    2 +-
 scrub/phase3.c     |    4 ++--
 scrub/phase4.c     |    8 ++++----
 scrub/phase5.c     |    2 +-
 scrub/phase6.c     |    6 +++---
 scrub/phase7.c     |    2 +-
 scrub/repair.c     |    4 ++--
 scrub/scrub.c      |   12 ++++++------
 scrub/spacemap.c   |   12 ++++++------
 scrub/vfs.c        |    2 +-
 scrub/xfs_scrub.h  |    7 ++++---
 16 files changed, 119 insertions(+), 65 deletions(-)


diff --git a/include/xfrog.h b/include/xfrog.h
index f3541193..766ee5d5 100644
--- a/include/xfrog.h
+++ b/include/xfrog.h
@@ -19,4 +19,24 @@
 struct xfs_fsop_geom;
 int xfrog_geometry(int fd, struct xfs_fsop_geom *fsgeo);
 
+/*
+ * Structure for recording whatever observations we want about the level of
+ * xfs runtime support for this fd.  Right now we only store the fd and fs
+ * geometry.
+ */
+struct xfs_fd {
+	/* ioctl file descriptor */
+	int			fd;
+
+	/* filesystem geometry */
+	struct xfs_fsop_geom	fsgeom;
+};
+
+/* Static initializers */
+#define XFS_FD_INIT(_fd)	{ .fd = (_fd), }
+#define XFS_FD_INIT_EMPTY	XFS_FD_INIT(-1)
+
+int xfd_prepare_geometry(struct xfs_fd *xfd);
+int xfd_close(struct xfs_fd *xfd);
+
 #endif	/* __XFROG_H__ */
diff --git a/libfrog/fsgeom.c b/libfrog/fsgeom.c
index 69d24774..694ccbd0 100644
--- a/libfrog/fsgeom.c
+++ b/libfrog/fsgeom.c
@@ -93,3 +93,35 @@ xfrog_geometry(
 
 	return errno;
 }
+
+/*
+ * Prepare xfs_fd structure for future ioctl operations by computing the xfs
+ * geometry for @xfd->fd.  Returns zero or a positive error code.
+ */
+int
+xfd_prepare_geometry(
+	struct xfs_fd		*xfd)
+{
+	return xfrog_geometry(xfd->fd, &xfd->fsgeom);
+}
+
+/*
+ * Release any resources associated with this xfs_fd structure.  Returns zero
+ * or a positive error code.
+ */
+int
+xfd_close(
+	struct xfs_fd		*xfd)
+{
+	int			ret = 0;
+
+	if (xfd->fd < 0)
+		return 0;
+
+	ret = close(xfd->fd);
+	xfd->fd = -1;
+	if (ret < 0)
+		return errno;
+
+	return 0;
+}
diff --git a/scrub/fscounters.c b/scrub/fscounters.c
index 9e93e2a6..f18d0e19 100644
--- a/scrub/fscounters.c
+++ b/scrub/fscounters.c
@@ -57,10 +57,10 @@ xfs_count_inodes_range(
 	igrpreq.ocount  = &igrplen;
 
 	igrp_ino = first_ino;
-	error = ioctl(ctx->mnt_fd, XFS_IOC_FSINUMBERS, &igrpreq);
+	error = ioctl(ctx->mnt.fd, XFS_IOC_FSINUMBERS, &igrpreq);
 	while (!error && igrplen && inogrp.xi_startino < last_ino) {
 		nr += inogrp.xi_alloccount;
-		error = ioctl(ctx->mnt_fd, XFS_IOC_FSINUMBERS, &igrpreq);
+		error = ioctl(ctx->mnt.fd, XFS_IOC_FSINUMBERS, &igrpreq);
 	}
 
 	if (error) {
@@ -113,7 +113,7 @@ xfs_count_all_inodes(
 	int			ret;
 
 	ci = calloc(1, sizeof(struct xfs_count_inodes) +
-			(ctx->geo.agcount * sizeof(uint64_t)));
+			(ctx->mnt.fsgeom.agcount * sizeof(uint64_t)));
 	if (!ci)
 		return false;
 	ci->moveon = true;
@@ -125,7 +125,7 @@ xfs_count_all_inodes(
 		str_info(ctx, ctx->mntpoint, _("Could not create workqueue."));
 		goto out_free;
 	}
-	for (agno = 0; agno < ctx->geo.agcount; agno++) {
+	for (agno = 0; agno < ctx->mnt.fsgeom.agcount; agno++) {
 		ret = workqueue_add(&wq, xfs_count_ag_inodes, agno, ci);
 		if (ret) {
 			moveon = false;
@@ -136,7 +136,7 @@ _("Could not queue AG %u icount work."), agno);
 	}
 	workqueue_destroy(&wq);
 
-	for (agno = 0; agno < ctx->geo.agcount; agno++)
+	for (agno = 0; agno < ctx->mnt.fsgeom.agcount; agno++)
 		*count += ci->counters[agno];
 	moveon = ci->moveon;
 
@@ -162,14 +162,14 @@ xfs_scan_estimate_blocks(
 	int				error;
 
 	/* Grab the fstatvfs counters, since it has to report accurately. */
-	error = fstatvfs(ctx->mnt_fd, &sfs);
+	error = fstatvfs(ctx->mnt.fd, &sfs);
 	if (error) {
 		str_errno(ctx, ctx->mntpoint);
 		return false;
 	}
 
 	/* Fetch the filesystem counters. */
-	error = ioctl(ctx->mnt_fd, XFS_IOC_FSCOUNTS, &fc);
+	error = ioctl(ctx->mnt.fd, XFS_IOC_FSCOUNTS, &fc);
 	if (error) {
 		str_errno(ctx, ctx->mntpoint);
 		return false;
@@ -179,14 +179,16 @@ xfs_scan_estimate_blocks(
 	 * XFS reserves some blocks to prevent hard ENOSPC, so add those
 	 * blocks back to the free data counts.
 	 */
-	error = ioctl(ctx->mnt_fd, XFS_IOC_GET_RESBLKS, &rb);
+	error = ioctl(ctx->mnt.fd, XFS_IOC_GET_RESBLKS, &rb);
 	if (error)
 		str_errno(ctx, ctx->mntpoint);
 	sfs.f_bfree += rb.resblks_avail;
 
-	*d_blocks = sfs.f_blocks + (ctx->geo.logstart ? ctx->geo.logblocks : 0);
+	*d_blocks = sfs.f_blocks;
+	if (ctx->mnt.fsgeom.logstart > 0)
+		*d_blocks += ctx->mnt.fsgeom.logblocks;
 	*d_bfree = sfs.f_bfree;
-	*r_blocks = ctx->geo.rtblocks;
+	*r_blocks = ctx->mnt.fsgeom.rtblocks;
 	*r_bfree = fc.freertx;
 	*f_files = sfs.f_files;
 	*f_free = sfs.f_ffree;
diff --git a/scrub/inodes.c b/scrub/inodes.c
index 442a5978..08f3d847 100644
--- a/scrub/inodes.c
+++ b/scrub/inodes.c
@@ -72,7 +72,7 @@ xfs_iterate_inodes_range_check(
 		/* Load the one inode. */
 		oneino = inogrp->xi_startino + i;
 		onereq.ubuffer = bs;
-		error = ioctl(ctx->mnt_fd, XFS_IOC_FSBULKSTAT_SINGLE,
+		error = ioctl(ctx->mnt.fd, XFS_IOC_FSBULKSTAT_SINGLE,
 				&onereq);
 		if (error || bs->bs_ino != inogrp->xi_startino + i) {
 			memset(bs, 0, sizeof(struct xfs_bstat));
@@ -134,7 +134,7 @@ xfs_iterate_inodes_range(
 
 	/* Find the inode chunk & alloc mask */
 	igrp_ino = first_ino;
-	error = ioctl(ctx->mnt_fd, XFS_IOC_FSINUMBERS, &igrpreq);
+	error = ioctl(ctx->mnt.fd, XFS_IOC_FSINUMBERS, &igrpreq);
 	while (!error && igrplen) {
 		/* Load the inodes. */
 		ino = inogrp.xi_startino - 1;
@@ -145,7 +145,7 @@ xfs_iterate_inodes_range(
 		 */
 		if (inogrp.xi_alloccount == 0)
 			goto igrp_retry;
-		error = ioctl(ctx->mnt_fd, XFS_IOC_FSBULKSTAT, &bulkreq);
+		error = ioctl(ctx->mnt.fd, XFS_IOC_FSBULKSTAT, &bulkreq);
 		if (error)
 			str_info(ctx, descr, "%s", strerror_r(errno,
 						buf, DESCR_BUFSZ));
@@ -190,7 +190,7 @@ _("Changed too many times during scan; giving up."));
 
 		stale_count = 0;
 igrp_retry:
-		error = ioctl(ctx->mnt_fd, XFS_IOC_FSINUMBERS, &igrpreq);
+		error = ioctl(ctx->mnt.fd, XFS_IOC_FSINUMBERS, &igrpreq);
 	}
 
 err:
@@ -260,7 +260,7 @@ xfs_scan_all_inodes(
 		return false;
 	}
 
-	for (agno = 0; agno < ctx->geo.agcount; agno++) {
+	for (agno = 0; agno < ctx->mnt.fsgeom.agcount; agno++) {
 		ret = workqueue_add(&wq, xfs_scan_ag_inodes, agno, &si);
 		if (ret) {
 			si.moveon = false;
diff --git a/scrub/phase1.c b/scrub/phase1.c
index bdd23d26..6d8293b2 100644
--- a/scrub/phase1.c
+++ b/scrub/phase1.c
@@ -39,7 +39,7 @@ xfs_shutdown_fs(
 
 	flag = XFS_FSOP_GOING_FLAGS_LOGFLUSH;
 	str_info(ctx, ctx->mntpoint, _("Shutting down filesystem!"));
-	if (ioctl(ctx->mnt_fd, XFS_IOC_GOINGDOWN, &flag))
+	if (ioctl(ctx->mnt.fd, XFS_IOC_GOINGDOWN, &flag))
 		str_errno(ctx, ctx->mntpoint);
 }
 
@@ -60,11 +60,9 @@ xfs_cleanup_fs(
 	if (ctx->datadev)
 		disk_close(ctx->datadev);
 	fshandle_destroy();
-	if (ctx->mnt_fd >= 0) {
-		error = close(ctx->mnt_fd);
-		if (error)
-			str_errno(ctx, _("closing mountpoint fd"));
-	}
+	error = xfd_close(&ctx->mnt);
+	if (error)
+		str_liberror(ctx, error, _("closing mountpoint fd"));
 	fs_table_destroy();
 
 	return true;
@@ -86,8 +84,8 @@ xfs_setup_fs(
 	 * CAP_SYS_ADMIN, which we probably need to do anything fancy
 	 * with the (XFS driver) kernel.
 	 */
-	ctx->mnt_fd = open(ctx->mntpoint, O_RDONLY | O_NOATIME | O_DIRECTORY);
-	if (ctx->mnt_fd < 0) {
+	ctx->mnt.fd = open(ctx->mntpoint, O_RDONLY | O_NOATIME | O_DIRECTORY);
+	if (ctx->mnt.fd < 0) {
 		if (errno == EPERM)
 			str_info(ctx, ctx->mntpoint,
 _("Must be root to run scrub."));
@@ -96,23 +94,23 @@ _("Must be root to run scrub."));
 		return false;
 	}
 
-	error = fstat(ctx->mnt_fd, &ctx->mnt_sb);
+	error = fstat(ctx->mnt.fd, &ctx->mnt_sb);
 	if (error) {
 		str_errno(ctx, ctx->mntpoint);
 		return false;
 	}
-	error = fstatvfs(ctx->mnt_fd, &ctx->mnt_sv);
+	error = fstatvfs(ctx->mnt.fd, &ctx->mnt_sv);
 	if (error) {
 		str_errno(ctx, ctx->mntpoint);
 		return false;
 	}
-	error = fstatfs(ctx->mnt_fd, &ctx->mnt_sf);
+	error = fstatfs(ctx->mnt.fd, &ctx->mnt_sf);
 	if (error) {
 		str_errno(ctx, ctx->mntpoint);
 		return false;
 	}
 
-	if (!platform_test_xfs_fd(ctx->mnt_fd)) {
+	if (!platform_test_xfs_fd(ctx->mnt.fd)) {
 		str_info(ctx, ctx->mntpoint,
 _("Does not appear to be an XFS filesystem!"));
 		return false;
@@ -123,27 +121,28 @@ _("Does not appear to be an XFS filesystem!"));
 	 * This seems to reduce the incidence of stale file handle
 	 * errors when we open things by handle.
 	 */
-	error = syncfs(ctx->mnt_fd);
+	error = syncfs(ctx->mnt.fd);
 	if (error) {
 		str_errno(ctx, ctx->mntpoint);
 		return false;
 	}
 
 	/* Retrieve XFS geometry. */
-	error = xfrog_geometry(ctx->mnt_fd, &ctx->geo);
+	error = xfd_prepare_geometry(&ctx->mnt);
 	if (error) {
 		str_liberror(ctx, error, _("Retrieving XFS geometry"));
 		return false;
 	}
 
-	if (!xfs_action_lists_alloc(ctx->geo.agcount, &ctx->action_lists)) {
+	if (!xfs_action_lists_alloc(ctx->mnt.fsgeom.agcount,
+				&ctx->action_lists)) {
 		str_error(ctx, ctx->mntpoint, _("Not enough memory."));
 		return false;
 	}
 
-	ctx->agblklog = log2_roundup(ctx->geo.agblocks);
-	ctx->blocklog = highbit32(ctx->geo.blocksize);
-	ctx->inodelog = highbit32(ctx->geo.inodesize);
+	ctx->agblklog = log2_roundup(ctx->mnt.fsgeom.agblocks);
+	ctx->blocklog = highbit32(ctx->mnt.fsgeom.blocksize);
+	ctx->inodelog = highbit32(ctx->mnt.fsgeom.inodesize);
 	ctx->inopblog = ctx->blocklog - ctx->inodelog;
 
 	error = path_to_fshandle(ctx->mntpoint, &ctx->fshandle,
@@ -171,12 +170,12 @@ _("Kernel metadata repair facility is not available.  Use -n to scrub."));
 	}
 
 	/* Did we find the log and rt devices, if they're present? */
-	if (ctx->geo.logstart == 0 && ctx->fsinfo.fs_log == NULL) {
+	if (ctx->mnt.fsgeom.logstart == 0 && ctx->fsinfo.fs_log == NULL) {
 		str_info(ctx, ctx->mntpoint,
 _("Unable to find log device path."));
 		return false;
 	}
-	if (ctx->geo.rtblocks && ctx->fsinfo.fs_rt == NULL) {
+	if (ctx->mnt.fsgeom.rtblocks && ctx->fsinfo.fs_rt == NULL) {
 		str_info(ctx, ctx->mntpoint,
 _("Unable to find realtime device path."));
 		return false;
diff --git a/scrub/phase2.c b/scrub/phase2.c
index 653f666c..a80da7fd 100644
--- a/scrub/phase2.c
+++ b/scrub/phase2.c
@@ -141,7 +141,7 @@ xfs_scan_metadata(
 	if (!moveon)
 		goto out;
 
-	for (agno = 0; moveon && agno < ctx->geo.agcount; agno++) {
+	for (agno = 0; moveon && agno < ctx->mnt.fsgeom.agcount; agno++) {
 		ret = workqueue_add(&wq, xfs_scan_ag_metadata, agno, &moveon);
 		if (ret) {
 			moveon = false;
diff --git a/scrub/phase3.c b/scrub/phase3.c
index 4963d675..a42d8213 100644
--- a/scrub/phase3.c
+++ b/scrub/phase3.c
@@ -33,7 +33,7 @@ xfs_scrub_fd(
 	struct xfs_bstat	*bs,
 	struct xfs_action_list	*alist)
 {
-	return fn(ctx, bs->bs_ino, bs->bs_gen, ctx->mnt_fd, alist);
+	return fn(ctx, bs->bs_ino, bs->bs_gen, ctx->mnt.fd, alist);
 }
 
 struct scrub_inode_ctx {
@@ -115,7 +115,7 @@ xfs_scrub_inode(
 	if (S_ISLNK(bstat->bs_mode)) {
 		/* Check symlink contents. */
 		moveon = xfs_scrub_symlink(ctx, bstat->bs_ino,
-				bstat->bs_gen, ctx->mnt_fd, &alist);
+				bstat->bs_gen, ctx->mnt.fd, &alist);
 	} else if (S_ISDIR(bstat->bs_mode)) {
 		/* Check the directory entries. */
 		moveon = xfs_scrub_fd(ctx, xfs_scrub_dir, bstat, &alist);
diff --git a/scrub/phase4.c b/scrub/phase4.c
index 79248326..49f00723 100644
--- a/scrub/phase4.c
+++ b/scrub/phase4.c
@@ -40,7 +40,7 @@ xfs_repair_ag(
 
 	/* Repair anything broken until we fail to make progress. */
 	do {
-		moveon = xfs_action_list_process(ctx, ctx->mnt_fd, alist, flags);
+		moveon = xfs_action_list_process(ctx, ctx->mnt.fd, alist, flags);
 		if (!moveon) {
 			*pmoveon = false;
 			return;
@@ -56,7 +56,7 @@ xfs_repair_ag(
 
 	/* Try once more, but this time complain if we can't fix things. */
 	flags |= ALP_COMPLAIN_IF_UNFIXED;
-	moveon = xfs_action_list_process(ctx, ctx->mnt_fd, alist, flags);
+	moveon = xfs_action_list_process(ctx, ctx->mnt.fd, alist, flags);
 	if (!moveon)
 		*pmoveon = false;
 }
@@ -77,7 +77,7 @@ xfs_process_action_items(
 		str_error(ctx, ctx->mntpoint, _("Could not create workqueue."));
 		return false;
 	}
-	for (agno = 0; agno < ctx->geo.agcount; agno++) {
+	for (agno = 0; agno < ctx->mnt.fsgeom.agcount; agno++) {
 		if (xfs_action_list_length(&ctx->action_lists[agno]) > 0) {
 			ret = workqueue_add(&wq, xfs_repair_ag, agno, &moveon);
 			if (ret) {
@@ -121,7 +121,7 @@ xfs_estimate_repair_work(
 	xfs_agnumber_t		agno;
 	size_t			need_fixing = 0;
 
-	for (agno = 0; agno < ctx->geo.agcount; agno++)
+	for (agno = 0; agno < ctx->mnt.fsgeom.agcount; agno++)
 		need_fixing += xfs_action_list_length(&ctx->action_lists[agno]);
 	need_fixing++;
 	*items = need_fixing;
diff --git a/scrub/phase5.c b/scrub/phase5.c
index 1743119d..748885d4 100644
--- a/scrub/phase5.c
+++ b/scrub/phase5.c
@@ -306,7 +306,7 @@ xfs_scrub_fs_label(
 		return false;
 
 	/* Retrieve label; quietly bail if we don't support that. */
-	error = ioctl(ctx->mnt_fd, FS_IOC_GETFSLABEL, &label);
+	error = ioctl(ctx->mnt.fd, FS_IOC_GETFSLABEL, &label);
 	if (error) {
 		if (errno != EOPNOTSUPP && errno != ENOTTY) {
 			moveon = false;
diff --git a/scrub/phase6.c b/scrub/phase6.c
index 66e6451c..e5a0b3c1 100644
--- a/scrub/phase6.c
+++ b/scrub/phase6.c
@@ -468,7 +468,7 @@ xfs_scan_blocks(
 	}
 
 	vs.rvp_data = read_verify_pool_init(ctx, ctx->datadev,
-			ctx->geo.blocksize, xfs_check_rmap_ioerr,
+			ctx->mnt.fsgeom.blocksize, xfs_check_rmap_ioerr,
 			scrub_nproc(ctx));
 	if (!vs.rvp_data) {
 		str_info(ctx, ctx->mntpoint,
@@ -477,7 +477,7 @@ _("Could not create data device media verifier."));
 	}
 	if (ctx->logdev) {
 		vs.rvp_log = read_verify_pool_init(ctx, ctx->logdev,
-				ctx->geo.blocksize, xfs_check_rmap_ioerr,
+				ctx->mnt.fsgeom.blocksize, xfs_check_rmap_ioerr,
 				scrub_nproc(ctx));
 		if (!vs.rvp_log) {
 			str_info(ctx, ctx->mntpoint,
@@ -487,7 +487,7 @@ _("Could not create data device media verifier."));
 	}
 	if (ctx->rtdev) {
 		vs.rvp_realtime = read_verify_pool_init(ctx, ctx->rtdev,
-				ctx->geo.blocksize, xfs_check_rmap_ioerr,
+				ctx->mnt.fsgeom.blocksize, xfs_check_rmap_ioerr,
 				scrub_nproc(ctx));
 		if (!vs.rvp_realtime) {
 			str_info(ctx, ctx->mntpoint,
diff --git a/scrub/phase7.c b/scrub/phase7.c
index 0c3202e4..13959ca8 100644
--- a/scrub/phase7.c
+++ b/scrub/phase7.c
@@ -111,7 +111,7 @@ xfs_scan_summary(
 	int			error;
 
 	/* Flush everything out to disk before we start counting. */
-	error = syncfs(ctx->mnt_fd);
+	error = syncfs(ctx->mnt.fd);
 	if (error) {
 		str_errno(ctx, ctx->mntpoint);
 		return false;
diff --git a/scrub/repair.c b/scrub/repair.c
index 4ed3c09a..45450d8c 100644
--- a/scrub/repair.c
+++ b/scrub/repair.c
@@ -262,7 +262,7 @@ xfs_action_list_defer(
 	xfs_agnumber_t			agno,
 	struct xfs_action_list		*alist)
 {
-	ASSERT(agno < ctx->geo.agcount);
+	ASSERT(agno < ctx->mnt.fsgeom.agcount);
 
 	xfs_action_list_splice(&ctx->action_lists[agno], alist);
 }
@@ -276,7 +276,7 @@ xfs_action_list_process_or_defer(
 {
 	bool				moveon;
 
-	moveon = xfs_action_list_process(ctx, ctx->mnt_fd, alist,
+	moveon = xfs_action_list_process(ctx, ctx->mnt.fd, alist,
 			ALP_REPAIR_ONLY | ALP_NOPROGRESS);
 	if (!moveon)
 		return moveon;
diff --git a/scrub/scrub.c b/scrub/scrub.c
index 0f0c9639..136ed529 100644
--- a/scrub/scrub.c
+++ b/scrub/scrub.c
@@ -363,7 +363,7 @@ xfs_scrub_metadata(
 		background_sleep();
 
 		/* Check the item. */
-		fix = xfs_check_metadata(ctx, ctx->mnt_fd, &meta, false);
+		fix = xfs_check_metadata(ctx, ctx->mnt.fd, &meta, false);
 		progress_add(1);
 		switch (fix) {
 		case CHECK_ABORT:
@@ -399,7 +399,7 @@ xfs_scrub_primary_super(
 	enum check_outcome		fix;
 
 	/* Check the item. */
-	fix = xfs_check_metadata(ctx, ctx->mnt_fd, &meta, false);
+	fix = xfs_check_metadata(ctx, ctx->mnt.fd, &meta, false);
 	switch (fix) {
 	case CHECK_ABORT:
 		return false;
@@ -460,7 +460,7 @@ xfs_scrub_estimate_ag_work(
 		switch (sc->type) {
 		case ST_AGHEADER:
 		case ST_PERAG:
-			estimate += ctx->geo.agcount;
+			estimate += ctx->mnt.fsgeom.agcount;
 			break;
 		case ST_FS:
 			estimate++;
@@ -605,9 +605,9 @@ __xfs_scrub_test(
 	if (debug_tweak_on("XFS_SCRUB_NO_KERNEL"))
 		return false;
 	if (debug_tweak_on("XFS_SCRUB_FORCE_REPAIR") && !injected) {
-		inject.fd = ctx->mnt_fd;
+		inject.fd = ctx->mnt.fd;
 		inject.errtag = XFS_ERRTAG_FORCE_SCRUB_REPAIR;
-		error = ioctl(ctx->mnt_fd, XFS_IOC_ERROR_INJECTION, &inject);
+		error = ioctl(ctx->mnt.fd, XFS_IOC_ERROR_INJECTION, &inject);
 		if (error == 0)
 			injected = true;
 	}
@@ -615,7 +615,7 @@ __xfs_scrub_test(
 	meta.sm_type = type;
 	if (repair)
 		meta.sm_flags |= XFS_SCRUB_IFLAG_REPAIR;
-	error = ioctl(ctx->mnt_fd, XFS_IOC_SCRUB_METADATA, &meta);
+	error = ioctl(ctx->mnt.fd, XFS_IOC_SCRUB_METADATA, &meta);
 	if (!error)
 		return true;
 	switch (errno) {
diff --git a/scrub/spacemap.c b/scrub/spacemap.c
index d547a041..c3621a3a 100644
--- a/scrub/spacemap.c
+++ b/scrub/spacemap.c
@@ -56,7 +56,7 @@ xfs_iterate_fsmap(
 	memcpy(head->fmh_keys, keys, sizeof(struct fsmap) * 2);
 	head->fmh_count = FSMAP_NR;
 
-	while ((error = ioctl(ctx->mnt_fd, FS_IOC_GETFSMAP, head)) == 0) {
+	while ((error = ioctl(ctx->mnt.fd, FS_IOC_GETFSMAP, head)) == 0) {
 		for (i = 0, p = head->fmh_recs;
 		     i < head->fmh_entries;
 		     i++, p++) {
@@ -107,8 +107,8 @@ xfs_scan_ag_blocks(
 	off64_t			bperag;
 	bool			moveon;
 
-	bperag = (off64_t)ctx->geo.agblocks *
-		 (off64_t)ctx->geo.blocksize;
+	bperag = (off64_t)ctx->mnt.fsgeom.agblocks *
+		 (off64_t)ctx->mnt.fsgeom.blocksize;
 
 	snprintf(descr, DESCR_BUFSZ, _("dev %d:%d AG %u fsmap"),
 				major(ctx->fsinfo.fs_datadev),
@@ -205,7 +205,7 @@ xfs_scan_all_spacemaps(
 	}
 	if (ctx->fsinfo.fs_rt) {
 		ret = workqueue_add(&wq, xfs_scan_rt_blocks,
-				ctx->geo.agcount + 1, &sbx);
+				ctx->mnt.fsgeom.agcount + 1, &sbx);
 		if (ret) {
 			sbx.moveon = false;
 			str_info(ctx, ctx->mntpoint,
@@ -215,7 +215,7 @@ _("Could not queue rtdev fsmap work."));
 	}
 	if (ctx->fsinfo.fs_log) {
 		ret = workqueue_add(&wq, xfs_scan_log_blocks,
-				ctx->geo.agcount + 2, &sbx);
+				ctx->mnt.fsgeom.agcount + 2, &sbx);
 		if (ret) {
 			sbx.moveon = false;
 			str_info(ctx, ctx->mntpoint,
@@ -223,7 +223,7 @@ _("Could not queue logdev fsmap work."));
 			goto out;
 		}
 	}
-	for (agno = 0; agno < ctx->geo.agcount; agno++) {
+	for (agno = 0; agno < ctx->mnt.fsgeom.agcount; agno++) {
 		ret = workqueue_add(&wq, xfs_scan_ag_blocks, agno, &sbx);
 		if (ret) {
 			sbx.moveon = false;
diff --git a/scrub/vfs.c b/scrub/vfs.c
index 8bcc4e79..7b0b5bcd 100644
--- a/scrub/vfs.c
+++ b/scrub/vfs.c
@@ -232,7 +232,7 @@ fstrim(
 	int			error;
 
 	range.len = ULLONG_MAX;
-	error = ioctl(ctx->mnt_fd, FITRIM, &range);
+	error = ioctl(ctx->mnt.fd, FITRIM, &range);
 	if (error && errno != EOPNOTSUPP && errno != ENOTTY)
 		perror(_("fstrim"));
 }
diff --git a/scrub/xfs_scrub.h b/scrub/xfs_scrub.h
index a459e4b5..28eae6fe 100644
--- a/scrub/xfs_scrub.h
+++ b/scrub/xfs_scrub.h
@@ -6,6 +6,8 @@
 #ifndef XFS_SCRUB_XFS_SCRUB_H_
 #define XFS_SCRUB_XFS_SCRUB_H_
 
+#include <xfrog.h>
+
 extern char *progname;
 
 #define _PATH_PROC_MOUNTS	"/proc/mounts"
@@ -53,14 +55,13 @@ struct scrub_ctx {
 	/* How does the user want us to react to errors? */
 	enum error_action	error_action;
 
-	/* fd to filesystem mount point */
-	int			mnt_fd;
+	/* xfrog context for the mount point */
+	struct xfs_fd		mnt;
 
 	/* Number of threads for metadata scrubbing */
 	unsigned int		nr_io_threads;
 
 	/* XFS specific geometry */
-	struct xfs_fsop_geom	geo;
 	struct fs_path		fsinfo;
 	unsigned int		agblklog;
 	unsigned int		blocklog;


^ permalink raw reply related	[flat|nested] 31+ messages in thread

* [PATCH 5/9] libfrog: store more inode and block geometry in struct xfs_fd
  2019-08-30  4:20 [PATCH v2 0/9] libxfrog: wrap version ioctl calls Darrick J. Wong
                   ` (3 preceding siblings ...)
  2019-08-30  4:20 ` [PATCH 4/9] libfrog: introduce xfs_fd to wrap an fd to a file on an xfs filesystem Darrick J. Wong
@ 2019-08-30  4:20 ` Darrick J. Wong
  2019-08-31  0:37   ` Allison Collins
  2019-08-30  4:21 ` [PATCH 6/9] libfrog: create online fs geometry converters Darrick J. Wong
                   ` (3 subsequent siblings)
  8 siblings, 1 reply; 31+ messages in thread
From: Darrick J. Wong @ 2019-08-30  4:20 UTC (permalink / raw)
  To: sandeen, darrick.wong; +Cc: linux-xfs, Dave Chinner

From: Darrick J. Wong <darrick.wong@oracle.com>

Move the extra AG geometry fields out of scrub and into the libfrog code
so that we can consolidate the geoemtry code in one place.

Signed-off-by: Darrick J. Wong <darrick.wong@oracle.com>
Reviewed-by: Dave Chinner <dchinner@redhat.com>
---
 include/xfrog.h    |   12 ++++++++++++
 libfrog/fsgeom.c   |   13 ++++++++++++-
 scrub/fscounters.c |    4 ++--
 scrub/inodes.c     |    4 ++--
 scrub/phase1.c     |    5 -----
 scrub/phase3.c     |    6 +++---
 scrub/phase5.c     |    4 ++--
 scrub/phase6.c     |    2 +-
 scrub/phase7.c     |    6 +++---
 scrub/xfs_scrub.h  |    4 ----
 10 files changed, 37 insertions(+), 23 deletions(-)


diff --git a/include/xfrog.h b/include/xfrog.h
index 766ee5d5..008cc155 100644
--- a/include/xfrog.h
+++ b/include/xfrog.h
@@ -30,6 +30,18 @@ struct xfs_fd {
 
 	/* filesystem geometry */
 	struct xfs_fsop_geom	fsgeom;
+
+	/* log2 of sb_agblocks (rounded up) */
+	unsigned int		agblklog;
+
+	/* log2 of sb_blocksize */
+	unsigned int		blocklog;
+
+	/* log2 of sb_inodesize */
+	unsigned int		inodelog;
+
+	/* log2 of sb_inopblock */
+	unsigned int		inopblog;
 };
 
 /* Static initializers */
diff --git a/libfrog/fsgeom.c b/libfrog/fsgeom.c
index 694ccbd0..b8873598 100644
--- a/libfrog/fsgeom.c
+++ b/libfrog/fsgeom.c
@@ -5,6 +5,7 @@
 #include "libxfs.h"
 #include "fsgeom.h"
 #include "xfrog.h"
+#include "libfrog.h"
 
 void
 xfs_report_geom(
@@ -102,7 +103,17 @@ int
 xfd_prepare_geometry(
 	struct xfs_fd		*xfd)
 {
-	return xfrog_geometry(xfd->fd, &xfd->fsgeom);
+	int			ret;
+
+	ret = xfrog_geometry(xfd->fd, &xfd->fsgeom);
+	if (ret)
+		return ret;
+
+	xfd->agblklog = log2_roundup(xfd->fsgeom.agblocks);
+	xfd->blocklog = highbit32(xfd->fsgeom.blocksize);
+	xfd->inodelog = highbit32(xfd->fsgeom.inodesize);
+	xfd->inopblog = xfd->blocklog - xfd->inodelog;
+	return 0;
 }
 
 /*
diff --git a/scrub/fscounters.c b/scrub/fscounters.c
index f18d0e19..ac898764 100644
--- a/scrub/fscounters.c
+++ b/scrub/fscounters.c
@@ -91,8 +91,8 @@ xfs_count_ag_inodes(
 				minor(ctx->fsinfo.fs_datadev),
 				agno);
 
-	ag_ino = (__u64)agno << (ctx->inopblog + ctx->agblklog);
-	next_ag_ino = (__u64)(agno + 1) << (ctx->inopblog + ctx->agblklog);
+	ag_ino = (__u64)agno << (ctx->mnt.inopblog + ctx->mnt.agblklog);
+	next_ag_ino = (__u64)(agno + 1) << (ctx->mnt.inopblog + ctx->mnt.agblklog);
 
 	moveon = xfs_count_inodes_range(ctx, descr, ag_ino, next_ag_ino - 1,
 			&ci->counters[agno]);
diff --git a/scrub/inodes.c b/scrub/inodes.c
index 08f3d847..873ad425 100644
--- a/scrub/inodes.c
+++ b/scrub/inodes.c
@@ -228,8 +228,8 @@ xfs_scan_ag_inodes(
 				minor(ctx->fsinfo.fs_datadev),
 				agno);
 
-	ag_ino = (__u64)agno << (ctx->inopblog + ctx->agblklog);
-	next_ag_ino = (__u64)(agno + 1) << (ctx->inopblog + ctx->agblklog);
+	ag_ino = (__u64)agno << (ctx->mnt.inopblog + ctx->mnt.agblklog);
+	next_ag_ino = (__u64)(agno + 1) << (ctx->mnt.inopblog + ctx->mnt.agblklog);
 
 	moveon = xfs_iterate_inodes_range(ctx, descr, ctx->fshandle, ag_ino,
 			next_ag_ino - 1, si->fn, si->arg);
diff --git a/scrub/phase1.c b/scrub/phase1.c
index 6d8293b2..cbdbd010 100644
--- a/scrub/phase1.c
+++ b/scrub/phase1.c
@@ -140,11 +140,6 @@ _("Does not appear to be an XFS filesystem!"));
 		return false;
 	}
 
-	ctx->agblklog = log2_roundup(ctx->mnt.fsgeom.agblocks);
-	ctx->blocklog = highbit32(ctx->mnt.fsgeom.blocksize);
-	ctx->inodelog = highbit32(ctx->mnt.fsgeom.inodesize);
-	ctx->inopblog = ctx->blocklog - ctx->inodelog;
-
 	error = path_to_fshandle(ctx->mntpoint, &ctx->fshandle,
 			&ctx->fshandle_len);
 	if (error) {
diff --git a/scrub/phase3.c b/scrub/phase3.c
index a42d8213..579e08c3 100644
--- a/scrub/phase3.c
+++ b/scrub/phase3.c
@@ -52,8 +52,8 @@ xfs_scrub_inode_vfs_error(
 	xfs_agino_t		agino;
 	int			old_errno = errno;
 
-	agno = bstat->bs_ino / (1ULL << (ctx->inopblog + ctx->agblklog));
-	agino = bstat->bs_ino % (1ULL << (ctx->inopblog + ctx->agblklog));
+	agno = bstat->bs_ino / (1ULL << (ctx->mnt.inopblog + ctx->mnt.agblklog));
+	agino = bstat->bs_ino % (1ULL << (ctx->mnt.inopblog + ctx->mnt.agblklog));
 	snprintf(descr, DESCR_BUFSZ, _("inode %"PRIu64" (%u/%u)"),
 			(uint64_t)bstat->bs_ino, agno, agino);
 	errno = old_errno;
@@ -77,7 +77,7 @@ xfs_scrub_inode(
 	int			error;
 
 	xfs_action_list_init(&alist);
-	agno = bstat->bs_ino / (1ULL << (ctx->inopblog + ctx->agblklog));
+	agno = bstat->bs_ino / (1ULL << (ctx->mnt.inopblog + ctx->mnt.agblklog));
 	background_sleep();
 
 	/* Try to open the inode to pin it. */
diff --git a/scrub/phase5.c b/scrub/phase5.c
index 748885d4..36ec27b3 100644
--- a/scrub/phase5.c
+++ b/scrub/phase5.c
@@ -239,8 +239,8 @@ xfs_scrub_connections(
 	int			fd = -1;
 	int			error;
 
-	agno = bstat->bs_ino / (1ULL << (ctx->inopblog + ctx->agblklog));
-	agino = bstat->bs_ino % (1ULL << (ctx->inopblog + ctx->agblklog));
+	agno = bstat->bs_ino / (1ULL << (ctx->mnt.inopblog + ctx->mnt.agblklog));
+	agino = bstat->bs_ino % (1ULL << (ctx->mnt.inopblog + ctx->mnt.agblklog));
 	snprintf(descr, DESCR_BUFSZ, _("inode %"PRIu64" (%u/%u)"),
 			(uint64_t)bstat->bs_ino, agno, agino);
 	background_sleep();
diff --git a/scrub/phase6.c b/scrub/phase6.c
index e5a0b3c1..48971270 100644
--- a/scrub/phase6.c
+++ b/scrub/phase6.c
@@ -547,7 +547,7 @@ xfs_estimate_verify_work(
 	if (!moveon)
 		return moveon;
 
-	*items = ((d_blocks - d_bfree) + (r_blocks - r_bfree)) << ctx->blocklog;
+	*items = ((d_blocks - d_bfree) + (r_blocks - r_bfree)) << ctx->mnt.blocklog;
 	*nr_threads = disk_heads(ctx->datadev);
 	*rshift = 20;
 	return moveon;
diff --git a/scrub/phase7.c b/scrub/phase7.c
index 13959ca8..41a77356 100644
--- a/scrub/phase7.c
+++ b/scrub/phase7.c
@@ -148,11 +148,11 @@ xfs_scan_summary(
 	 * filesystem treats them as "free", but since we scanned
 	 * them, we'll consider them used.
 	 */
-	d_bfree -= totalcount.agbytes >> ctx->blocklog;
+	d_bfree -= totalcount.agbytes >> ctx->mnt.blocklog;
 
 	/* Report on what we found. */
-	used_data = (d_blocks - d_bfree) << ctx->blocklog;
-	used_rt = (r_blocks - r_bfree) << ctx->blocklog;
+	used_data = (d_blocks - d_bfree) << ctx->mnt.blocklog;
+	used_rt = (r_blocks - r_bfree) << ctx->mnt.blocklog;
 	used_files = f_files - f_free;
 	stat_data = totalcount.dbytes;
 	stat_rt = totalcount.rbytes;
diff --git a/scrub/xfs_scrub.h b/scrub/xfs_scrub.h
index 28eae6fe..fb34c587 100644
--- a/scrub/xfs_scrub.h
+++ b/scrub/xfs_scrub.h
@@ -63,10 +63,6 @@ struct scrub_ctx {
 
 	/* XFS specific geometry */
 	struct fs_path		fsinfo;
-	unsigned int		agblklog;
-	unsigned int		blocklog;
-	unsigned int		inodelog;
-	unsigned int		inopblog;
 	void			*fshandle;
 	size_t			fshandle_len;
 


^ permalink raw reply related	[flat|nested] 31+ messages in thread

* [PATCH 6/9] libfrog: create online fs geometry converters
  2019-08-30  4:20 [PATCH v2 0/9] libxfrog: wrap version ioctl calls Darrick J. Wong
                   ` (4 preceding siblings ...)
  2019-08-30  4:20 ` [PATCH 5/9] libfrog: store more inode and block geometry in struct xfs_fd Darrick J. Wong
@ 2019-08-30  4:21 ` Darrick J. Wong
  2019-08-31  5:11   ` Allison Collins
  2019-09-03 22:55   ` Dave Chinner
  2019-08-30  4:21 ` [PATCH 7/9] libfrog: refactor open-coded bulkstat calls Darrick J. Wong
                   ` (2 subsequent siblings)
  8 siblings, 2 replies; 31+ messages in thread
From: Darrick J. Wong @ 2019-08-30  4:21 UTC (permalink / raw)
  To: sandeen, darrick.wong; +Cc: linux-xfs

From: Darrick J. Wong <darrick.wong@oracle.com>

Create helper functions to perform unit conversions against a runtime
filesystem, then remove the open-coded versions in scrub.

Signed-off-by: Darrick J. Wong <darrick.wong@oracle.com>
---
 include/xfrog.h    |   57 ++++++++++++++++++++++++++++++++++++++++++++++++++++
 libfrog/fsgeom.c   |    1 +
 scrub/fscounters.c |    4 ++--
 scrub/inodes.c     |    4 ++--
 scrub/phase3.c     |    6 +++--
 scrub/phase5.c     |    4 ++--
 scrub/phase6.c     |    3 ++-
 scrub/phase7.c     |    6 +++--
 8 files changed, 72 insertions(+), 13 deletions(-)


diff --git a/include/xfrog.h b/include/xfrog.h
index 008cc155..a08f6464 100644
--- a/include/xfrog.h
+++ b/include/xfrog.h
@@ -42,6 +42,9 @@ struct xfs_fd {
 
 	/* log2 of sb_inopblock */
 	unsigned int		inopblog;
+
+	/* bits for agino in inum */
+	unsigned int		aginolog;
 };
 
 /* Static initializers */
@@ -51,4 +54,58 @@ struct xfs_fd {
 int xfd_prepare_geometry(struct xfs_fd *xfd);
 int xfd_close(struct xfs_fd *xfd);
 
+/* Convert AG number and AG inode number into fs inode number. */
+static inline uint64_t
+cvt_agino_to_ino(
+	const struct xfs_fd	*xfd,
+	uint32_t		agno,
+	uint32_t		agino)
+{
+	return ((uint64_t)agno << xfd->aginolog) + agino;
+}
+
+/* Convert fs inode number into AG number. */
+static inline uint32_t
+cvt_ino_to_agno(
+	const struct xfs_fd	*xfd,
+	uint64_t		ino)
+{
+	return ino >> xfd->aginolog;
+}
+
+/* Convert fs inode number into AG inode number. */
+static inline uint32_t
+cvt_ino_to_agino(
+	const struct xfs_fd	*xfd,
+	uint64_t		ino)
+{
+	return ino & ((1ULL << xfd->aginolog) - 1);
+}
+
+/*
+ * Convert a linear fs block offset number into bytes.  This is the runtime
+ * equivalent of XFS_FSB_TO_B, which means that it is /not/ for segmented fsbno
+ * format (= agno | agbno) that we use internally for the data device.
+ */
+static inline uint64_t
+cvt_off_fsb_to_b(
+	const struct xfs_fd	*xfd,
+	uint64_t		fsb)
+{
+	return fsb << xfd->blocklog;
+}
+
+/*
+ * Convert bytes into a (rounded down) linear fs block offset number.  This is
+ * the runtime equivalent of XFS_B_TO_FSBT.  It does not produce segmented
+ * fsbno numbers (= agno | agbno).
+ */
+static inline uint64_t
+cvt_b_to_off_fsbt(
+	const struct xfs_fd	*xfd,
+	uint64_t		bytes)
+{
+	return bytes >> xfd->blocklog;
+}
+
 #endif	/* __XFROG_H__ */
diff --git a/libfrog/fsgeom.c b/libfrog/fsgeom.c
index b8873598..cf9323c1 100644
--- a/libfrog/fsgeom.c
+++ b/libfrog/fsgeom.c
@@ -113,6 +113,7 @@ xfd_prepare_geometry(
 	xfd->blocklog = highbit32(xfd->fsgeom.blocksize);
 	xfd->inodelog = highbit32(xfd->fsgeom.inodesize);
 	xfd->inopblog = xfd->blocklog - xfd->inodelog;
+	xfd->aginolog = xfd->agblklog + xfd->inopblog;
 	return 0;
 }
 
diff --git a/scrub/fscounters.c b/scrub/fscounters.c
index ac898764..ea6af156 100644
--- a/scrub/fscounters.c
+++ b/scrub/fscounters.c
@@ -91,8 +91,8 @@ xfs_count_ag_inodes(
 				minor(ctx->fsinfo.fs_datadev),
 				agno);
 
-	ag_ino = (__u64)agno << (ctx->mnt.inopblog + ctx->mnt.agblklog);
-	next_ag_ino = (__u64)(agno + 1) << (ctx->mnt.inopblog + ctx->mnt.agblklog);
+	ag_ino = cvt_agino_to_ino(&ctx->mnt, agno, 0);
+	next_ag_ino = cvt_agino_to_ino(&ctx->mnt, agno + 1, 0);
 
 	moveon = xfs_count_inodes_range(ctx, descr, ag_ino, next_ag_ino - 1,
 			&ci->counters[agno]);
diff --git a/scrub/inodes.c b/scrub/inodes.c
index 873ad425..700e5200 100644
--- a/scrub/inodes.c
+++ b/scrub/inodes.c
@@ -228,8 +228,8 @@ xfs_scan_ag_inodes(
 				minor(ctx->fsinfo.fs_datadev),
 				agno);
 
-	ag_ino = (__u64)agno << (ctx->mnt.inopblog + ctx->mnt.agblklog);
-	next_ag_ino = (__u64)(agno + 1) << (ctx->mnt.inopblog + ctx->mnt.agblklog);
+	ag_ino = cvt_agino_to_ino(&ctx->mnt, agno, 0);
+	next_ag_ino = cvt_agino_to_ino(&ctx->mnt, agno + 1, 0);
 
 	moveon = xfs_iterate_inodes_range(ctx, descr, ctx->fshandle, ag_ino,
 			next_ag_ino - 1, si->fn, si->arg);
diff --git a/scrub/phase3.c b/scrub/phase3.c
index 579e08c3..8c02f1cb 100644
--- a/scrub/phase3.c
+++ b/scrub/phase3.c
@@ -52,8 +52,8 @@ xfs_scrub_inode_vfs_error(
 	xfs_agino_t		agino;
 	int			old_errno = errno;
 
-	agno = bstat->bs_ino / (1ULL << (ctx->mnt.inopblog + ctx->mnt.agblklog));
-	agino = bstat->bs_ino % (1ULL << (ctx->mnt.inopblog + ctx->mnt.agblklog));
+	agno = cvt_ino_to_agno(&ctx->mnt, bstat->bs_ino);
+	agino = cvt_ino_to_agino(&ctx->mnt, bstat->bs_ino);
 	snprintf(descr, DESCR_BUFSZ, _("inode %"PRIu64" (%u/%u)"),
 			(uint64_t)bstat->bs_ino, agno, agino);
 	errno = old_errno;
@@ -77,7 +77,7 @@ xfs_scrub_inode(
 	int			error;
 
 	xfs_action_list_init(&alist);
-	agno = bstat->bs_ino / (1ULL << (ctx->mnt.inopblog + ctx->mnt.agblklog));
+	agno = cvt_ino_to_agno(&ctx->mnt, bstat->bs_ino);
 	background_sleep();
 
 	/* Try to open the inode to pin it. */
diff --git a/scrub/phase5.c b/scrub/phase5.c
index 36ec27b3..f3ee22e6 100644
--- a/scrub/phase5.c
+++ b/scrub/phase5.c
@@ -239,8 +239,8 @@ xfs_scrub_connections(
 	int			fd = -1;
 	int			error;
 
-	agno = bstat->bs_ino / (1ULL << (ctx->mnt.inopblog + ctx->mnt.agblklog));
-	agino = bstat->bs_ino % (1ULL << (ctx->mnt.inopblog + ctx->mnt.agblklog));
+	agno = cvt_ino_to_agno(&ctx->mnt, bstat->bs_ino);
+	agino = cvt_ino_to_agino(&ctx->mnt, bstat->bs_ino);
 	snprintf(descr, DESCR_BUFSZ, _("inode %"PRIu64" (%u/%u)"),
 			(uint64_t)bstat->bs_ino, agno, agino);
 	background_sleep();
diff --git a/scrub/phase6.c b/scrub/phase6.c
index 48971270..5628b926 100644
--- a/scrub/phase6.c
+++ b/scrub/phase6.c
@@ -547,7 +547,8 @@ xfs_estimate_verify_work(
 	if (!moveon)
 		return moveon;
 
-	*items = ((d_blocks - d_bfree) + (r_blocks - r_bfree)) << ctx->mnt.blocklog;
+	*items = cvt_off_fsb_to_b(&ctx->mnt,
+			(d_blocks - d_bfree) + (r_blocks - r_bfree));
 	*nr_threads = disk_heads(ctx->datadev);
 	*rshift = 20;
 	return moveon;
diff --git a/scrub/phase7.c b/scrub/phase7.c
index 41a77356..8a028e19 100644
--- a/scrub/phase7.c
+++ b/scrub/phase7.c
@@ -148,11 +148,11 @@ xfs_scan_summary(
 	 * filesystem treats them as "free", but since we scanned
 	 * them, we'll consider them used.
 	 */
-	d_bfree -= totalcount.agbytes >> ctx->mnt.blocklog;
+	d_bfree -= cvt_b_to_off_fsbt(&ctx->mnt, totalcount.agbytes);
 
 	/* Report on what we found. */
-	used_data = (d_blocks - d_bfree) << ctx->mnt.blocklog;
-	used_rt = (r_blocks - r_bfree) << ctx->mnt.blocklog;
+	used_data = cvt_off_fsb_to_b(&ctx->mnt, d_blocks - d_bfree);
+	used_rt = cvt_off_fsb_to_b(&ctx->mnt, r_blocks - r_bfree);
 	used_files = f_files - f_free;
 	stat_data = totalcount.dbytes;
 	stat_rt = totalcount.rbytes;


^ permalink raw reply related	[flat|nested] 31+ messages in thread

* [PATCH 7/9] libfrog: refactor open-coded bulkstat calls
  2019-08-30  4:20 [PATCH v2 0/9] libxfrog: wrap version ioctl calls Darrick J. Wong
                   ` (5 preceding siblings ...)
  2019-08-30  4:21 ` [PATCH 6/9] libfrog: create online fs geometry converters Darrick J. Wong
@ 2019-08-30  4:21 ` Darrick J. Wong
  2019-08-30 23:26   ` Darrick J. Wong
                     ` (2 more replies)
  2019-08-30  4:21 ` [PATCH 8/9] libfrog: create xfd_open function Darrick J. Wong
  2019-08-30  4:21 ` [PATCH 9/9] libfrog: refactor open-coded INUMBERS calls Darrick J. Wong
  8 siblings, 3 replies; 31+ messages in thread
From: Darrick J. Wong @ 2019-08-30  4:21 UTC (permalink / raw)
  To: sandeen, darrick.wong; +Cc: linux-xfs

From: Darrick J. Wong <darrick.wong@oracle.com>

Refactor the BULKSTAT_SINGLE and BULKSTAT ioctl callsites into helper
functions.

Signed-off-by: Darrick J. Wong <darrick.wong@oracle.com>
---
 fsr/xfs_fsr.c      |  110 ++++++++++++++++++++++------------------------------
 include/xfrog.h    |    7 +++
 io/open.c          |   72 +++++++++++++++++-----------------
 io/swapext.c       |   20 ++-------
 libfrog/Makefile   |    1 
 libfrog/bulkstat.c |   52 +++++++++++++++++++++++++
 quota/quot.c       |   33 ++++++++--------
 scrub/inodes.c     |   32 ++++-----------
 8 files changed, 172 insertions(+), 155 deletions(-)
 create mode 100644 libfrog/bulkstat.c


diff --git a/fsr/xfs_fsr.c b/fsr/xfs_fsr.c
index 4b239a30..36402252 100644
--- a/fsr/xfs_fsr.c
+++ b/fsr/xfs_fsr.c
@@ -102,31 +102,6 @@ static int	nfrags = 0;	/* Debug option: Coerse into specific number
 				 * of extents */
 static int	openopts = O_CREAT|O_EXCL|O_RDWR|O_DIRECT;
 
-static int
-xfs_bulkstat_single(int fd, xfs_ino_t *lastip, struct xfs_bstat *ubuffer)
-{
-    struct xfs_fsop_bulkreq  bulkreq;
-
-    bulkreq.lastip = (__u64 *)lastip;
-    bulkreq.icount = 1;
-    bulkreq.ubuffer = ubuffer;
-    bulkreq.ocount = NULL;
-    return ioctl(fd, XFS_IOC_FSBULKSTAT_SINGLE, &bulkreq);
-}
-
-static int
-xfs_bulkstat(int fd, xfs_ino_t *lastip, int icount,
-                    struct xfs_bstat *ubuffer, __s32 *ocount)
-{
-    struct xfs_fsop_bulkreq  bulkreq;
-
-    bulkreq.lastip = (__u64 *)lastip;
-    bulkreq.icount = icount;
-    bulkreq.ubuffer = ubuffer;
-    bulkreq.ocount = ocount;
-    return ioctl(fd, XFS_IOC_FSBULKSTAT, &bulkreq);
-}
-
 static int
 xfs_swapext(int fd, xfs_swapext_t *sx)
 {
@@ -596,11 +571,11 @@ fsrall_cleanup(int timeout)
 static int
 fsrfs(char *mntdir, xfs_ino_t startino, int targetrange)
 {
-
-	int	fsfd, fd;
+	struct xfs_fd	fsxfd = XFS_FD_INIT_EMPTY;
+	int	fd;
 	int	count = 0;
 	int	ret;
-	__s32	buflenout;
+	uint32_t buflenout;
 	struct xfs_bstat buf[GRABSZ];
 	char	fname[64];
 	char	*tname;
@@ -617,26 +592,27 @@ fsrfs(char *mntdir, xfs_ino_t startino, int targetrange)
 		return -1;
 	}
 
-	if ((fsfd = open(mntdir, O_RDONLY)) < 0) {
+	if ((fsxfd.fd = open(mntdir, O_RDONLY)) < 0) {
 		fsrprintf(_("unable to open: %s: %s\n"),
 		          mntdir, strerror( errno ));
 		free(fshandlep);
 		return -1;
 	}
 
-	ret = xfrog_geometry(fsfd, &fsgeom);
+	ret = xfd_prepare_geometry(&fsxfd);
 	if (ret) {
 		fsrprintf(_("Skipping %s: could not get XFS geometry\n"),
 			  mntdir);
-		close(fsfd);
+		xfd_close(&fsxfd);
 		free(fshandlep);
 		return -1;
 	}
+	memcpy(&fsgeom, &fsxfd.fsgeom, sizeof(fsgeom));
 
 	tmp_init(mntdir);
 
-	while ((ret = xfs_bulkstat(fsfd,
-				&lastino, GRABSZ, &buf[0], &buflenout)) == 0) {
+	while ((ret = xfrog_bulkstat(&fsxfd, &lastino, GRABSZ, &buf[0],
+				&buflenout)) == 0) {
 		struct xfs_bstat *p;
 		struct xfs_bstat *endp;
 
@@ -685,16 +661,16 @@ fsrfs(char *mntdir, xfs_ino_t startino, int targetrange)
 		}
 		if (endtime && endtime < time(NULL)) {
 			tmp_close(mntdir);
-			close(fsfd);
+			xfd_close(&fsxfd);
 			fsrall_cleanup(1);
 			exit(1);
 		}
 	}
-	if (ret < 0)
-		fsrprintf(_("%s: xfs_bulkstat: %s\n"), progname, strerror(errno));
+	if (ret)
+		fsrprintf(_("%s: bulkstat: %s\n"), progname, strerror(ret));
 out0:
 	tmp_close(mntdir);
-	close(fsfd);
+	xfd_close(&fsxfd);
 	free(fshandlep);
 	return 0;
 }
@@ -727,13 +703,16 @@ fsrdir(char *dirname)
  * an open on the file and passes this all to fsrfile_common.
  */
 static int
-fsrfile(char *fname, xfs_ino_t ino)
+fsrfile(
+	char			*fname,
+	xfs_ino_t		ino)
 {
-	struct xfs_bstat statbuf;
-	jdm_fshandle_t	*fshandlep;
-	int	fd = -1, fsfd = -1;
-	int	error = -1;
-	char	*tname;
+	struct xfs_fd		fsxfd = XFS_FD_INIT_EMPTY;
+	struct xfs_bstat	statbuf;
+	jdm_fshandle_t		*fshandlep;
+	int			fd = -1;
+	int			error = -1;
+	char			*tname;
 
 	fshandlep = jdm_getfshandle(getparent (fname) );
 	if (!fshandlep) {
@@ -746,16 +725,23 @@ fsrfile(char *fname, xfs_ino_t ino)
 	 * Need to open something on the same filesystem as the
 	 * file.  Open the parent.
 	 */
-	fsfd = open(getparent(fname), O_RDONLY);
-	if (fsfd < 0) {
+	fsxfd.fd = open(getparent(fname), O_RDONLY);
+	if (fsxfd.fd < 0) {
 		fsrprintf(_("unable to open sys handle for %s: %s\n"),
 			fname, strerror(errno));
 		goto out;
 	}
 
-	if ((xfs_bulkstat_single(fsfd, &ino, &statbuf)) < 0) {
+	error = xfd_prepare_geometry(&fsxfd);
+	if (error) {
+		fsrprintf(_("Unable to get geom on fs for: %s\n"), fname);
+		goto out;
+	}
+
+	error = xfrog_bulkstat_single(&fsxfd, ino, &statbuf);
+	if (error) {
 		fsrprintf(_("unable to get bstat on %s: %s\n"),
-			fname, strerror(errno));
+			fname, strerror(error));
 		goto out;
 	}
 
@@ -766,12 +752,8 @@ fsrfile(char *fname, xfs_ino_t ino)
 		goto out;
 	}
 
-	/* Get the fs geometry */
-	error = xfrog_geometry(fsfd, &fsgeom);
-	if (error) {
-		fsrprintf(_("Unable to get geom on fs for: %s\n"), fname);
-		goto out;
-	}
+	/* Stash the fs geometry for general use. */
+	memcpy(&fsgeom, &fsxfd.fsgeom, sizeof(fsgeom));
 
 	tname = gettmpname(fname);
 
@@ -779,8 +761,7 @@ fsrfile(char *fname, xfs_ino_t ino)
 		error = fsrfile_common(fname, tname, NULL, fd, &statbuf);
 
 out:
-	if (fsfd >= 0)
-		close(fsfd);
+	xfd_close(&fsxfd);
 	if (fd >= 0)
 		close(fd);
 	free(fshandlep);
@@ -947,6 +928,7 @@ fsr_setup_attr_fork(
 	struct xfs_bstat *bstatp)
 {
 #ifdef HAVE_FSETXATTR
+	struct xfs_fd	txfd = XFS_FD_INIT(tfd);
 	struct stat	tstatbuf;
 	int		i;
 	int		diff = 0;
@@ -964,7 +946,7 @@ fsr_setup_attr_fork(
 	if (!(fsgeom.flags & XFS_FSOP_GEOM_FLAGS_ATTR2) ||
 	    bstatp->bs_forkoff == 0) {
 		/* attr1 */
-		ret = fsetxattr(tfd, "user.X", "X", 1, XATTR_CREATE);
+		ret = fsetxattr(txfd.fd, "user.X", "X", 1, XATTR_CREATE);
 		if (ret) {
 			fsrprintf(_("could not set ATTR\n"));
 			return -1;
@@ -974,7 +956,7 @@ fsr_setup_attr_fork(
 
 	/* attr2 w/ fork offsets */
 
-	if (fstat(tfd, &tstatbuf) < 0) {
+	if (fstat(txfd.fd, &tstatbuf) < 0) {
 		fsrprintf(_("unable to stat temp file: %s\n"),
 					strerror(errno));
 		return -1;
@@ -983,18 +965,18 @@ fsr_setup_attr_fork(
 	i = 0;
 	do {
 		struct xfs_bstat tbstat;
-		xfs_ino_t	ino;
 		char		name[64];
+		int		ret;
 
 		/*
 		 * bulkstat the temp inode to see what the forkoff is.  Use
 		 * this to compare against the target and determine what we
 		 * need to do.
 		 */
-		ino = tstatbuf.st_ino;
-		if ((xfs_bulkstat_single(tfd, &ino, &tbstat)) < 0) {
+		ret = xfrog_bulkstat_single(&txfd, tstatbuf.st_ino, &tbstat);
+		if (ret) {
 			fsrprintf(_("unable to get bstat on temp file: %s\n"),
-						strerror(errno));
+						strerror(ret));
 			return -1;
 		}
 		if (dflag)
@@ -1014,7 +996,7 @@ fsr_setup_attr_fork(
 		 */
 		if (!tbstat.bs_forkoff) {
 			ASSERT(i == 0);
-			ret = fsetxattr(tfd, name, "XX", 2, XATTR_CREATE);
+			ret = fsetxattr(txfd.fd, name, "XX", 2, XATTR_CREATE);
 			if (ret) {
 				fsrprintf(_("could not set ATTR\n"));
 				return -1;
@@ -1050,7 +1032,7 @@ fsr_setup_attr_fork(
 			if (diff < 0) {
 				char val[2048];
 				memset(val, 'X', 2048);
-				if (fsetxattr(tfd, name, val, 2048, 0)) {
+				if (fsetxattr(txfd.fd, name, val, 2048, 0)) {
 					fsrprintf(_("big ATTR set failed\n"));
 					return -1;
 				}
@@ -1094,7 +1076,7 @@ fsr_setup_attr_fork(
 		}
 
 		/* we need to grow the attr fork, so create another attr */
-		ret = fsetxattr(tfd, name, "XX", 2, XATTR_CREATE);
+		ret = fsetxattr(txfd.fd, name, "XX", 2, XATTR_CREATE);
 		if (ret) {
 			fsrprintf(_("could not set ATTR\n"));
 			return -1;
diff --git a/include/xfrog.h b/include/xfrog.h
index a08f6464..7bda9810 100644
--- a/include/xfrog.h
+++ b/include/xfrog.h
@@ -108,4 +108,11 @@ cvt_b_to_off_fsbt(
 	return bytes >> xfd->blocklog;
 }
 
+/* Bulkstat wrappers */
+struct xfs_bstat;
+int xfrog_bulkstat_single(struct xfs_fd *xfd, uint64_t ino,
+		struct xfs_bstat *ubuffer);
+int xfrog_bulkstat(struct xfs_fd *xfd, uint64_t *lastino, uint32_t icount,
+		struct xfs_bstat *ubuffer, uint32_t *ocount);
+
 #endif	/* __XFROG_H__ */
diff --git a/io/open.c b/io/open.c
index 8b24a4f9..35e6131b 100644
--- a/io/open.c
+++ b/io/open.c
@@ -719,19 +719,18 @@ get_last_inode(void)
 
 static int
 inode_f(
-	  int			argc,
-	  char			**argv)
+	int			argc,
+	char			**argv)
 {
-	__s32			count = 0;
-	__u64			result_ino = 0;
-	__u64			userino = NULLFSINO;
+	struct xfs_bstat	bstat;
+	uint32_t		count = 0;
+	uint64_t		result_ino = 0;
+	uint64_t		userino = NULLFSINO;
 	char			*p;
 	int			c;
 	int			verbose = 0;
 	int			ret_next = 0;
-	int			cmd = 0;
-	struct xfs_fsop_bulkreq	bulkreq;
-	struct xfs_bstat	bstat;
+	int			ret;
 
 	while ((c = getopt(argc, argv, "nv")) != EOF) {
 		switch (c) {
@@ -773,35 +772,38 @@ inode_f(
 			exitcode = 1;
 			return 0;
 		}
+	} else if (ret_next) {
+		struct xfs_fd	xfd = XFS_FD_INIT(file->fd);
+
+		/* get next inode */
+		ret = xfrog_bulkstat(&xfd, &userino, 1, &bstat, &count);
+		if (ret) {
+			errno = ret;
+			perror("bulkstat");
+			exitcode = 1;
+			return 0;
+		}
+
+		/* The next inode in use, or 0 if none */
+		if (count)
+			result_ino = bstat.bs_ino;
+		else
+			result_ino = 0;
 	} else {
-		if (ret_next)	/* get next inode */
-			cmd = XFS_IOC_FSBULKSTAT;
-		else		/* get this inode */
-			cmd = XFS_IOC_FSBULKSTAT_SINGLE;
-
-		bulkreq.lastip = &userino;
-		bulkreq.icount = 1;
-		bulkreq.ubuffer = &bstat;
-		bulkreq.ocount = &count;
-
-		if (xfsctl(file->name, file->fd, cmd, &bulkreq)) {
-			if (!ret_next && errno == EINVAL) {
-				/* Not in use */
-				result_ino = 0;
-			} else {
-				perror("xfsctl");
-				exitcode = 1;
-				return 0;
-			}
-		} else if (ret_next) {
-			/* The next inode in use, or 0 if none */
-			if (*bulkreq.ocount)
-				result_ino = bstat.bs_ino;
-			else
-				result_ino = 0;
+		struct xfs_fd	xfd = XFS_FD_INIT(file->fd);
+
+		/* get this inode */
+		ret = xfrog_bulkstat_single(&xfd, userino, &bstat);
+		if (ret == EINVAL) {
+			/* Not in use */
+			result_ino = 0;
+		} else if (ret) {
+			errno = ret;
+			perror("bulkstat_single");
+			exitcode = 1;
+			return 0;
 		} else {
-			/* The inode we asked about */
-			result_ino = userino;
+			result_ino = bstat.bs_ino;
 		}
 	}
 
diff --git a/io/swapext.c b/io/swapext.c
index d360c221..fbf4fff5 100644
--- a/io/swapext.c
+++ b/io/swapext.c
@@ -8,6 +8,7 @@
 #include "input.h"
 #include "init.h"
 #include "io.h"
+#include "xfrog.h"
 
 static cmdinfo_t swapext_cmd;
 
@@ -20,26 +21,12 @@ swapext_help(void)
 "\n"));
 }
 
-static int
-xfs_bulkstat_single(
-	int			fd,
-	xfs_ino_t		*lastip,
-	struct xfs_bstat	*ubuffer)
-{
-	struct xfs_fsop_bulkreq	bulkreq;
-
-	bulkreq.lastip = (__u64 *)lastip;
-	bulkreq.icount = 1;
-	bulkreq.ubuffer = ubuffer;
-	bulkreq.ocount = NULL;
-	return ioctl(fd, XFS_IOC_FSBULKSTAT_SINGLE, &bulkreq);
-}
-
 static int
 swapext_f(
 	int			argc,
 	char			**argv)
 {
+	struct xfs_fd		fxfd = XFS_FD_INIT(file->fd);
 	int			fd;
 	int			error;
 	struct xfs_swapext	sx;
@@ -60,8 +47,9 @@ swapext_f(
 		goto out;
 	}
 
-	error = xfs_bulkstat_single(file->fd, &stat.st_ino, &sx.sx_stat);
+	error = xfrog_bulkstat_single(&fxfd, stat.st_ino, &sx.sx_stat);
 	if (error) {
+		errno = error;
 		perror("bulkstat");
 		goto out;
 	}
diff --git a/libfrog/Makefile b/libfrog/Makefile
index f5a0539b..05c6f701 100644
--- a/libfrog/Makefile
+++ b/libfrog/Makefile
@@ -13,6 +13,7 @@ LT_AGE = 0
 CFILES = \
 avl64.c \
 bitmap.c \
+bulkstat.c \
 convert.c \
 crc32.c \
 fsgeom.c \
diff --git a/libfrog/bulkstat.c b/libfrog/bulkstat.c
new file mode 100644
index 00000000..0e11ccea
--- /dev/null
+++ b/libfrog/bulkstat.c
@@ -0,0 +1,52 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Copyright (C) 2019 Oracle.  All Rights Reserved.
+ * Author: Darrick J. Wong <darrick.wong@oracle.com>
+ */
+#include "xfs.h"
+#include "xfrog.h"
+
+/* Bulkstat a single inode.  Returns zero or a positive error code. */
+int
+xfrog_bulkstat_single(
+	struct xfs_fd		*xfd,
+	uint64_t		ino,
+	struct xfs_bstat	*ubuffer)
+{
+	__u64			i = ino;
+	struct xfs_fsop_bulkreq	bulkreq = {
+		.lastip		= &i,
+		.icount		= 1,
+		.ubuffer	= ubuffer,
+		.ocount		= NULL,
+	};
+	int			ret;
+
+	ret = ioctl(xfd->fd, XFS_IOC_FSBULKSTAT_SINGLE, &bulkreq);
+	if (ret)
+		return errno;
+	return 0;
+}
+
+/* Bulkstat a bunch of inodes.  Returns zero or a positive error code. */
+int
+xfrog_bulkstat(
+	struct xfs_fd		*xfd,
+	uint64_t		*lastino,
+	uint32_t		icount,
+	struct xfs_bstat	*ubuffer,
+	uint32_t		*ocount)
+{
+	struct xfs_fsop_bulkreq	bulkreq = {
+		.lastip		= (__u64 *)lastino,
+		.icount		= icount,
+		.ubuffer	= ubuffer,
+		.ocount		= (__s32 *)ocount,
+	};
+	int			ret;
+
+	ret = ioctl(xfd->fd, XFS_IOC_FSBULKSTAT, &bulkreq);
+	if (ret)
+		return errno;
+	return 0;
+}
diff --git a/quota/quot.c b/quota/quot.c
index 6bc91171..1e970819 100644
--- a/quota/quot.c
+++ b/quota/quot.c
@@ -11,6 +11,7 @@
 #include <grp.h>
 #include "init.h"
 #include "quota.h"
+#include "xfrog.h"
 
 typedef struct du {
 	struct du	*next;
@@ -124,13 +125,13 @@ quot_bulkstat_add(
 static void
 quot_bulkstat_mount(
 	char			*fsdir,
-	uint			flags)
+	unsigned int		flags)
 {
-	struct xfs_fsop_bulkreq	bulkreq;
+	struct xfs_fd		fsxfd = XFS_FD_INIT_EMPTY;
 	struct xfs_bstat	*buf;
-	__u64			last = 0;
-	__s32			count;
-	int			i, sts, fsfd;
+	uint64_t		last = 0;
+	uint32_t		count;
+	int			i, sts;
 	du_t			**dp;
 
 	/*
@@ -145,8 +146,8 @@ quot_bulkstat_mount(
 			*dp = NULL;
 	ndu[0] = ndu[1] = ndu[2] = 0;
 
-	fsfd = open(fsdir, O_RDONLY);
-	if (fsfd < 0) {
+	fsxfd.fd = open(fsdir, O_RDONLY);
+	if (fsxfd.fd < 0) {
 		perror(fsdir);
 		return;
 	}
@@ -154,25 +155,23 @@ quot_bulkstat_mount(
 	buf = (struct xfs_bstat *)calloc(NBSTAT, sizeof(struct xfs_bstat));
 	if (!buf) {
 		perror("calloc");
-		close(fsfd);
+		xfd_close(&fsxfd);
 		return;
 	}
 
-	bulkreq.lastip = &last;
-	bulkreq.icount = NBSTAT;
-	bulkreq.ubuffer = buf;
-	bulkreq.ocount = &count;
-
-	while ((sts = xfsctl(fsdir, fsfd, XFS_IOC_FSBULKSTAT, &bulkreq)) == 0) {
+	while ((sts = xfrog_bulkstat(&fsxfd, &last, NBSTAT, buf,
+				&count)) == 0) {
 		if (count == 0)
 			break;
 		for (i = 0; i < count; i++)
 			quot_bulkstat_add(&buf[i], flags);
 	}
-	if (sts < 0)
-		perror("XFS_IOC_FSBULKSTAT"),
+	if (sts < 0) {
+		errno = sts;
+		perror("XFS_IOC_FSBULKSTAT");
+	}
 	free(buf);
-	close(fsfd);
+	xfd_close(&fsxfd);
 }
 
 static int
diff --git a/scrub/inodes.c b/scrub/inodes.c
index 700e5200..413037d8 100644
--- a/scrub/inodes.c
+++ b/scrub/inodes.c
@@ -17,6 +17,7 @@
 #include "xfs_scrub.h"
 #include "common.h"
 #include "inodes.h"
+#include "xfrog.h"
 
 /*
  * Iterate a range of inodes.
@@ -50,17 +51,10 @@ xfs_iterate_inodes_range_check(
 	struct xfs_inogrp	*inogrp,
 	struct xfs_bstat	*bstat)
 {
-	struct xfs_fsop_bulkreq	onereq = {NULL};
 	struct xfs_bstat	*bs;
-	__u64			oneino;
-	__s32			onelen = 0;
 	int			i;
 	int			error;
 
-	onereq.lastip  = &oneino;
-	onereq.icount  = 1;
-	onereq.ocount  = &onelen;
-
 	for (i = 0, bs = bstat; i < XFS_INODES_PER_CHUNK; i++) {
 		if (!(inogrp->xi_allocmask & (1ULL << i)))
 			continue;
@@ -70,10 +64,8 @@ xfs_iterate_inodes_range_check(
 		}
 
 		/* Load the one inode. */
-		oneino = inogrp->xi_startino + i;
-		onereq.ubuffer = bs;
-		error = ioctl(ctx->mnt.fd, XFS_IOC_FSBULKSTAT_SINGLE,
-				&onereq);
+		error = xfrog_bulkstat_single(&ctx->mnt,
+				inogrp->xi_startino + i, bs);
 		if (error || bs->bs_ino != inogrp->xi_startino + i) {
 			memset(bs, 0, sizeof(struct xfs_bstat));
 			bs->bs_ino = inogrp->xi_startino + i;
@@ -99,16 +91,14 @@ xfs_iterate_inodes_range(
 	void			*arg)
 {
 	struct xfs_fsop_bulkreq	igrpreq = {NULL};
-	struct xfs_fsop_bulkreq	bulkreq = {NULL};
 	struct xfs_handle	handle;
 	struct xfs_inogrp	inogrp;
 	struct xfs_bstat	bstat[XFS_INODES_PER_CHUNK];
 	char			idescr[DESCR_BUFSZ];
-	char			buf[DESCR_BUFSZ];
 	struct xfs_bstat	*bs;
 	__u64			igrp_ino;
-	__u64			ino;
-	__s32			bulklen = 0;
+	uint64_t		ino;
+	uint32_t		bulklen = 0;
 	__s32			igrplen = 0;
 	bool			moveon = true;
 	int			i;
@@ -117,10 +107,6 @@ xfs_iterate_inodes_range(
 
 
 	memset(bstat, 0, XFS_INODES_PER_CHUNK * sizeof(struct xfs_bstat));
-	bulkreq.lastip  = &ino;
-	bulkreq.icount  = XFS_INODES_PER_CHUNK;
-	bulkreq.ubuffer = &bstat;
-	bulkreq.ocount  = &bulklen;
 
 	igrpreq.lastip  = &igrp_ino;
 	igrpreq.icount  = 1;
@@ -138,17 +124,17 @@ xfs_iterate_inodes_range(
 	while (!error && igrplen) {
 		/* Load the inodes. */
 		ino = inogrp.xi_startino - 1;
-		bulkreq.icount = inogrp.xi_alloccount;
+
 		/*
 		 * We can have totally empty inode chunks on filesystems where
 		 * there are more than 64 inodes per block.  Skip these.
 		 */
 		if (inogrp.xi_alloccount == 0)
 			goto igrp_retry;
-		error = ioctl(ctx->mnt.fd, XFS_IOC_FSBULKSTAT, &bulkreq);
+		error = xfrog_bulkstat(&ctx->mnt, &ino, inogrp.xi_alloccount,
+				bstat, &bulklen);
 		if (error)
-			str_info(ctx, descr, "%s", strerror_r(errno,
-						buf, DESCR_BUFSZ));
+			str_liberror(ctx, error, descr);
 
 		xfs_iterate_inodes_range_check(ctx, &inogrp, bstat);
 


^ permalink raw reply related	[flat|nested] 31+ messages in thread

* [PATCH 8/9] libfrog: create xfd_open function
  2019-08-30  4:20 [PATCH v2 0/9] libxfrog: wrap version ioctl calls Darrick J. Wong
                   ` (6 preceding siblings ...)
  2019-08-30  4:21 ` [PATCH 7/9] libfrog: refactor open-coded bulkstat calls Darrick J. Wong
@ 2019-08-30  4:21 ` Darrick J. Wong
  2019-09-01 20:55   ` Allison Collins
  2019-09-03 23:01   ` Dave Chinner
  2019-08-30  4:21 ` [PATCH 9/9] libfrog: refactor open-coded INUMBERS calls Darrick J. Wong
  8 siblings, 2 replies; 31+ messages in thread
From: Darrick J. Wong @ 2019-08-30  4:21 UTC (permalink / raw)
  To: sandeen, darrick.wong; +Cc: linux-xfs

From: Darrick J. Wong <darrick.wong@oracle.com>

Create a helper to open a file and initialize the xfd structure.

Signed-off-by: Darrick J. Wong <darrick.wong@oracle.com>
---
 fsr/xfs_fsr.c    |   26 ++++++--------------------
 include/xfrog.h  |    1 +
 libfrog/fsgeom.c |   22 ++++++++++++++++++++++
 quota/quot.c     |    7 ++++---
 scrub/phase1.c   |   25 ++++++++-----------------
 5 files changed, 41 insertions(+), 40 deletions(-)


diff --git a/fsr/xfs_fsr.c b/fsr/xfs_fsr.c
index 36402252..e8d41aaf 100644
--- a/fsr/xfs_fsr.c
+++ b/fsr/xfs_fsr.c
@@ -592,18 +592,10 @@ fsrfs(char *mntdir, xfs_ino_t startino, int targetrange)
 		return -1;
 	}
 
-	if ((fsxfd.fd = open(mntdir, O_RDONLY)) < 0) {
-		fsrprintf(_("unable to open: %s: %s\n"),
-		          mntdir, strerror( errno ));
-		free(fshandlep);
-		return -1;
-	}
-
-	ret = xfd_prepare_geometry(&fsxfd);
+	ret = xfd_open(&fsxfd, mntdir, O_RDONLY);
 	if (ret) {
-		fsrprintf(_("Skipping %s: could not get XFS geometry\n"),
-			  mntdir);
-		xfd_close(&fsxfd);
+		fsrprintf(_("unable to open XFS file: %s: %s\n"),
+		          mntdir, strerror(ret));
 		free(fshandlep);
 		return -1;
 	}
@@ -725,16 +717,10 @@ fsrfile(
 	 * Need to open something on the same filesystem as the
 	 * file.  Open the parent.
 	 */
-	fsxfd.fd = open(getparent(fname), O_RDONLY);
-	if (fsxfd.fd < 0) {
-		fsrprintf(_("unable to open sys handle for %s: %s\n"),
-			fname, strerror(errno));
-		goto out;
-	}
-
-	error = xfd_prepare_geometry(&fsxfd);
+	error = xfd_open(&fsxfd, getparent(fname), O_RDONLY);
 	if (error) {
-		fsrprintf(_("Unable to get geom on fs for: %s\n"), fname);
+		fsrprintf(_("unable to open sys handle for XFS file %s: %s\n"),
+			fname, strerror(error));
 		goto out;
 	}
 
diff --git a/include/xfrog.h b/include/xfrog.h
index 7bda9810..3a49acc3 100644
--- a/include/xfrog.h
+++ b/include/xfrog.h
@@ -52,6 +52,7 @@ struct xfs_fd {
 #define XFS_FD_INIT_EMPTY	XFS_FD_INIT(-1)
 
 int xfd_prepare_geometry(struct xfs_fd *xfd);
+int xfd_open(struct xfs_fd *xfd, const char *pathname, int flags);
 int xfd_close(struct xfs_fd *xfd);
 
 /* Convert AG number and AG inode number into fs inode number. */
diff --git a/libfrog/fsgeom.c b/libfrog/fsgeom.c
index cf9323c1..47644dc3 100644
--- a/libfrog/fsgeom.c
+++ b/libfrog/fsgeom.c
@@ -117,6 +117,28 @@ xfd_prepare_geometry(
 	return 0;
 }
 
+/* Open a file on an XFS filesystem.  Returns zero or a positive error code. */
+int
+xfd_open(
+	struct xfs_fd		*xfd,
+	const char		*pathname,
+	int			flags)
+{
+	int			ret;
+
+	xfd->fd = open(pathname, O_RDONLY);
+	if (xfd->fd < 0)
+		return errno;
+
+	ret = xfd_prepare_geometry(xfd);
+	if (ret) {
+		xfd_close(xfd);
+		return ret;
+	}
+
+	return 0;
+}
+
 /*
  * Release any resources associated with this xfs_fd structure.  Returns zero
  * or a positive error code.
diff --git a/quota/quot.c b/quota/quot.c
index 1e970819..4614f684 100644
--- a/quota/quot.c
+++ b/quota/quot.c
@@ -131,7 +131,7 @@ quot_bulkstat_mount(
 	struct xfs_bstat	*buf;
 	uint64_t		last = 0;
 	uint32_t		count;
-	int			i, sts;
+	int			i, sts, ret;
 	du_t			**dp;
 
 	/*
@@ -146,8 +146,9 @@ quot_bulkstat_mount(
 			*dp = NULL;
 	ndu[0] = ndu[1] = ndu[2] = 0;
 
-	fsxfd.fd = open(fsdir, O_RDONLY);
-	if (fsxfd.fd < 0) {
+	ret = xfd_open(&fsxfd, fsdir, O_RDONLY);
+	if (ret) {
+		errno = ret;
 		perror(fsdir);
 		return;
 	}
diff --git a/scrub/phase1.c b/scrub/phase1.c
index cbdbd010..15e67e37 100644
--- a/scrub/phase1.c
+++ b/scrub/phase1.c
@@ -84,13 +84,17 @@ xfs_setup_fs(
 	 * CAP_SYS_ADMIN, which we probably need to do anything fancy
 	 * with the (XFS driver) kernel.
 	 */
-	ctx->mnt.fd = open(ctx->mntpoint, O_RDONLY | O_NOATIME | O_DIRECTORY);
-	if (ctx->mnt.fd < 0) {
-		if (errno == EPERM)
+	error = xfd_open(&ctx->mnt, ctx->mntpoint,
+			O_RDONLY | O_NOATIME | O_DIRECTORY);
+	if (error) {
+		if (error == EPERM)
 			str_info(ctx, ctx->mntpoint,
 _("Must be root to run scrub."));
+		else if (error == ENOTTY)
+			str_error(ctx, ctx->mntpoint,
+_("Not an XFS filesystem."));
 		else
-			str_errno(ctx, ctx->mntpoint);
+			str_liberror(ctx, error, ctx->mntpoint);
 		return false;
 	}
 
@@ -110,12 +114,6 @@ _("Must be root to run scrub."));
 		return false;
 	}
 
-	if (!platform_test_xfs_fd(ctx->mnt.fd)) {
-		str_info(ctx, ctx->mntpoint,
-_("Does not appear to be an XFS filesystem!"));
-		return false;
-	}
-
 	/*
 	 * Flush everything out to disk before we start checking.
 	 * This seems to reduce the incidence of stale file handle
@@ -127,13 +125,6 @@ _("Does not appear to be an XFS filesystem!"));
 		return false;
 	}
 
-	/* Retrieve XFS geometry. */
-	error = xfd_prepare_geometry(&ctx->mnt);
-	if (error) {
-		str_liberror(ctx, error, _("Retrieving XFS geometry"));
-		return false;
-	}
-
 	if (!xfs_action_lists_alloc(ctx->mnt.fsgeom.agcount,
 				&ctx->action_lists)) {
 		str_error(ctx, ctx->mntpoint, _("Not enough memory."));


^ permalink raw reply related	[flat|nested] 31+ messages in thread

* [PATCH 9/9] libfrog: refactor open-coded INUMBERS calls
  2019-08-30  4:20 [PATCH v2 0/9] libxfrog: wrap version ioctl calls Darrick J. Wong
                   ` (7 preceding siblings ...)
  2019-08-30  4:21 ` [PATCH 8/9] libfrog: create xfd_open function Darrick J. Wong
@ 2019-08-30  4:21 ` Darrick J. Wong
  2019-09-01 20:55   ` Allison Collins
  8 siblings, 1 reply; 31+ messages in thread
From: Darrick J. Wong @ 2019-08-30  4:21 UTC (permalink / raw)
  To: sandeen, darrick.wong; +Cc: linux-xfs, Dave Chinner

From: Darrick J. Wong <darrick.wong@oracle.com>

Refactor all the INUMBERS ioctl callsites into helper functions.

Signed-off-by: Darrick J. Wong <darrick.wong@oracle.com>
Reviewed-by: Dave Chinner <dchinner@redhat.com>
---
 include/xfrog.h    |    4 ++++
 io/imap.c          |   33 ++++++++++++++++-----------------
 io/open.c          |   24 ++++++++++++------------
 libfrog/bulkstat.c |   26 ++++++++++++++++++++++++++
 scrub/fscounters.c |   20 ++++++++------------
 scrub/inodes.c     |   17 ++++++-----------
 6 files changed, 72 insertions(+), 52 deletions(-)


diff --git a/include/xfrog.h b/include/xfrog.h
index 3a49acc3..d16481ce 100644
--- a/include/xfrog.h
+++ b/include/xfrog.h
@@ -116,4 +116,8 @@ int xfrog_bulkstat_single(struct xfs_fd *xfd, uint64_t ino,
 int xfrog_bulkstat(struct xfs_fd *xfd, uint64_t *lastino, uint32_t icount,
 		struct xfs_bstat *ubuffer, uint32_t *ocount);
 
+struct xfs_inogrp;
+int xfrog_inumbers(struct xfs_fd *xfd, uint64_t *lastino, uint32_t icount,
+		struct xfs_inogrp *ubuffer, uint32_t *ocount);
+
 #endif	/* __XFROG_H__ */
diff --git a/io/imap.c b/io/imap.c
index 9667289a..053ac28e 100644
--- a/io/imap.c
+++ b/io/imap.c
@@ -8,18 +8,20 @@
 #include "input.h"
 #include "init.h"
 #include "io.h"
+#include "xfrog.h"
 
 static cmdinfo_t imap_cmd;
 
 static int
 imap_f(int argc, char **argv)
 {
-	int		count;
-	int		nent;
-	int		i;
-	__u64		last = 0;
-	struct xfs_inogrp *t;
-	struct xfs_fsop_bulkreq bulkreq;
+	struct xfs_fd		xfd = XFS_FD_INIT(file->fd);
+	struct xfs_inogrp	*t;
+	uint64_t		last = 0;
+	uint32_t		count;
+	uint32_t		nent;
+	int			i;
+	int			error;
 
 	if (argc != 2)
 		nent = 1;
@@ -30,14 +32,8 @@ imap_f(int argc, char **argv)
 	if (!t)
 		return 0;
 
-	bulkreq.lastip  = &last;
-	bulkreq.icount  = nent;
-	bulkreq.ubuffer = (void *)t;
-	bulkreq.ocount  = &count;
-
-	while (xfsctl(file->name, file->fd, XFS_IOC_FSINUMBERS, &bulkreq) == 0) {
-		if (count == 0)
-			goto out_free;
+	while ((error = xfrog_inumbers(&xfd, &last, nent, t, &count)) == 0 &&
+	       count > 0) {
 		for (i = 0; i < count; i++) {
 			printf(_("ino %10llu count %2d mask %016llx\n"),
 				(unsigned long long)t[i].xi_startino,
@@ -45,9 +41,12 @@ imap_f(int argc, char **argv)
 				(unsigned long long)t[i].xi_allocmask);
 		}
 	}
-	perror("xfsctl(XFS_IOC_FSINUMBERS)");
-	exitcode = 1;
-out_free:
+
+	if (error) {
+		errno = error;
+		perror("xfsctl(XFS_IOC_FSINUMBERS)");
+		exitcode = 1;
+	}
 	free(t);
 	return 0;
 }
diff --git a/io/open.c b/io/open.c
index 35e6131b..c0d0f1e9 100644
--- a/io/open.c
+++ b/io/open.c
@@ -675,24 +675,24 @@ inode_help(void)
 "\n"));
 }
 
+#define IGROUP_NR	(1024)
 static __u64
 get_last_inode(void)
 {
-	__u64			lastip = 0;
-	__u64			lastgrp = 0;
-	__s32			ocount = 0;
+	struct xfs_fd		xfd = XFS_FD_INIT(file->fd);
+	uint64_t		lastip = 0;
+	uint32_t		lastgrp = 0;
+	uint32_t		ocount = 0;
 	__u64			last_ino;
-	struct xfs_inogrp	igroup[1024];
-	struct xfs_fsop_bulkreq	bulkreq;
-
-	bulkreq.lastip = &lastip;
-	bulkreq.ubuffer = &igroup;
-	bulkreq.icount = sizeof(igroup) / sizeof(struct xfs_inogrp);
-	bulkreq.ocount = &ocount;
+	struct xfs_inogrp	igroup[IGROUP_NR];
 
 	for (;;) {
-		if (xfsctl(file->name, file->fd, XFS_IOC_FSINUMBERS,
-				&bulkreq)) {
+		int		ret;
+
+		ret = xfrog_inumbers(&xfd, &lastip, IGROUP_NR, igroup,
+				&ocount);
+		if (ret) {
+			errno = ret;
 			perror("XFS_IOC_FSINUMBERS");
 			return 0;
 		}
diff --git a/libfrog/bulkstat.c b/libfrog/bulkstat.c
index 0e11ccea..18fffb20 100644
--- a/libfrog/bulkstat.c
+++ b/libfrog/bulkstat.c
@@ -50,3 +50,29 @@ xfrog_bulkstat(
 		return errno;
 	return 0;
 }
+
+/*
+ * Query inode allocation bitmask information.  Returns zero or a positive
+ * error code.
+ */
+int
+xfrog_inumbers(
+	struct xfs_fd		*xfd,
+	uint64_t		*lastino,
+	uint32_t		icount,
+	struct xfs_inogrp	*ubuffer,
+	uint32_t		*ocount)
+{
+	struct xfs_fsop_bulkreq	bulkreq = {
+		.lastip		= (__u64 *)lastino,
+		.icount		= icount,
+		.ubuffer	= ubuffer,
+		.ocount		= (__s32 *)ocount,
+	};
+	int			ret;
+
+	ret = ioctl(xfd->fd, XFS_IOC_FSINUMBERS, &bulkreq);
+	if (ret)
+		return errno;
+	return 0;
+}
diff --git a/scrub/fscounters.c b/scrub/fscounters.c
index ea6af156..3915822e 100644
--- a/scrub/fscounters.c
+++ b/scrub/fscounters.c
@@ -15,6 +15,7 @@
 #include "xfs_scrub.h"
 #include "common.h"
 #include "fscounters.h"
+#include "xfrog.h"
 
 /*
  * Filesystem counter collection routines.  We can count the number of
@@ -41,30 +42,25 @@ xfs_count_inodes_range(
 	uint64_t		last_ino,
 	uint64_t		*count)
 {
-	struct xfs_fsop_bulkreq	igrpreq = {NULL};
 	struct xfs_inogrp	inogrp;
-	__u64			igrp_ino;
+	uint64_t		igrp_ino;
 	uint64_t		nr = 0;
-	__s32			igrplen = 0;
+	uint32_t		igrplen = 0;
 	int			error;
 
 	ASSERT(!(first_ino & (XFS_INODES_PER_CHUNK - 1)));
 	ASSERT((last_ino & (XFS_INODES_PER_CHUNK - 1)));
 
-	igrpreq.lastip  = &igrp_ino;
-	igrpreq.icount  = 1;
-	igrpreq.ubuffer = &inogrp;
-	igrpreq.ocount  = &igrplen;
-
 	igrp_ino = first_ino;
-	error = ioctl(ctx->mnt.fd, XFS_IOC_FSINUMBERS, &igrpreq);
-	while (!error && igrplen && inogrp.xi_startino < last_ino) {
+	while (!(error = xfrog_inumbers(&ctx->mnt, &igrp_ino, 1, &inogrp,
+			&igrplen))) {
+		if (igrplen == 0 || inogrp.xi_startino >= last_ino)
+			break;
 		nr += inogrp.xi_alloccount;
-		error = ioctl(ctx->mnt.fd, XFS_IOC_FSINUMBERS, &igrpreq);
 	}
 
 	if (error) {
-		str_errno(ctx, descr);
+		str_liberror(ctx, error, descr);
 		return false;
 	}
 
diff --git a/scrub/inodes.c b/scrub/inodes.c
index 413037d8..acad9b16 100644
--- a/scrub/inodes.c
+++ b/scrub/inodes.c
@@ -90,16 +90,15 @@ xfs_iterate_inodes_range(
 	xfs_inode_iter_fn	fn,
 	void			*arg)
 {
-	struct xfs_fsop_bulkreq	igrpreq = {NULL};
 	struct xfs_handle	handle;
 	struct xfs_inogrp	inogrp;
 	struct xfs_bstat	bstat[XFS_INODES_PER_CHUNK];
 	char			idescr[DESCR_BUFSZ];
 	struct xfs_bstat	*bs;
-	__u64			igrp_ino;
+	uint64_t		igrp_ino;
 	uint64_t		ino;
 	uint32_t		bulklen = 0;
-	__s32			igrplen = 0;
+	uint32_t		igrplen = 0;
 	bool			moveon = true;
 	int			i;
 	int			error;
@@ -108,11 +107,6 @@ xfs_iterate_inodes_range(
 
 	memset(bstat, 0, XFS_INODES_PER_CHUNK * sizeof(struct xfs_bstat));
 
-	igrpreq.lastip  = &igrp_ino;
-	igrpreq.icount  = 1;
-	igrpreq.ubuffer = &inogrp;
-	igrpreq.ocount  = &igrplen;
-
 	memcpy(&handle.ha_fsid, fshandle, sizeof(handle.ha_fsid));
 	handle.ha_fid.fid_len = sizeof(xfs_fid_t) -
 			sizeof(handle.ha_fid.fid_len);
@@ -120,7 +114,7 @@ xfs_iterate_inodes_range(
 
 	/* Find the inode chunk & alloc mask */
 	igrp_ino = first_ino;
-	error = ioctl(ctx->mnt.fd, XFS_IOC_FSINUMBERS, &igrpreq);
+	error = xfrog_inumbers(&ctx->mnt, &igrp_ino, 1, &inogrp, &igrplen);
 	while (!error && igrplen) {
 		/* Load the inodes. */
 		ino = inogrp.xi_startino - 1;
@@ -176,12 +170,13 @@ _("Changed too many times during scan; giving up."));
 
 		stale_count = 0;
 igrp_retry:
-		error = ioctl(ctx->mnt.fd, XFS_IOC_FSINUMBERS, &igrpreq);
+		error = xfrog_inumbers(&ctx->mnt, &igrp_ino, 1, &inogrp,
+				&igrplen);
 	}
 
 err:
 	if (error) {
-		str_errno(ctx, descr);
+		str_liberror(ctx, error, descr);
 		moveon = false;
 	}
 out:


^ permalink raw reply related	[flat|nested] 31+ messages in thread

* Re: [PATCH 1/9] libxfs: revert FSGEOMETRY v5 -> v4 hack
  2019-08-30  4:20 ` [PATCH 1/9] libxfs: revert FSGEOMETRY v5 -> v4 hack Darrick J. Wong
@ 2019-08-30 21:03   ` Allison Collins
  2019-09-02 22:49   ` Dave Chinner
  1 sibling, 0 replies; 31+ messages in thread
From: Allison Collins @ 2019-08-30 21:03 UTC (permalink / raw)
  To: Darrick J. Wong, sandeen; +Cc: linux-xfs

On 8/29/19 9:20 PM, Darrick J. Wong wrote:
> From: Darrick J. Wong <darrick.wong@oracle.com>
> 
> Revert the #define redirection of XFS_IOC_FSGEOMETRY to the old V4
> ioctl.
> 
> Signed-off-by: Darrick J. Wong <darrick.wong@oracle.com>
> ---
>   libxfs/xfs_fs.h |    4 +---
>   1 file changed, 1 insertion(+), 3 deletions(-)
> 
> 
> diff --git a/libxfs/xfs_fs.h b/libxfs/xfs_fs.h
> index 67fceffc..31ac6323 100644
> --- a/libxfs/xfs_fs.h
> +++ b/libxfs/xfs_fs.h
> @@ -822,9 +822,7 @@ struct xfs_scrub_metadata {
>   #define XFS_IOC_ATTRMULTI_BY_HANDLE  _IOW ('X', 123, struct xfs_fsop_attrmulti_handlereq)
>   #define XFS_IOC_FSGEOMETRY_V4	     _IOR ('X', 124, struct xfs_fsop_geom_v4)
>   #define XFS_IOC_GOINGDOWN	     _IOR ('X', 125, uint32_t)
> -/* For compatibility, for now */
> -/* #define XFS_IOC_FSGEOMETRY	     _IOR ('X', 126, struct xfs_fsop_geom_v5) */
> -#define XFS_IOC_FSGEOMETRY XFS_IOC_FSGEOMETRY_V4
> +#define XFS_IOC_FSGEOMETRY	     _IOR ('X', 126, struct xfs_fsop_geom)
>   #define XFS_IOC_BULKSTAT	     _IOR ('X', 127, struct xfs_bulkstat_req)
>   #define XFS_IOC_INUMBERS	     _IOR ('X', 128, struct xfs_inumbers_req)
>   
> 
Ok, looks fine to me

Reviewed-by: Allison Collins <allison.henderson@oracle.com>

^ permalink raw reply	[flat|nested] 31+ messages in thread

* Re: [PATCH 2/9] xfsprogs: update spdx tags in LICENSES/
  2019-08-30  4:20 ` [PATCH 2/9] xfsprogs: update spdx tags in LICENSES/ Darrick J. Wong
@ 2019-08-30 21:03   ` Allison Collins
  0 siblings, 0 replies; 31+ messages in thread
From: Allison Collins @ 2019-08-30 21:03 UTC (permalink / raw)
  To: Darrick J. Wong, sandeen; +Cc: linux-xfs

On 8/29/19 9:20 PM, Darrick J. Wong wrote:
> From: Darrick J. Wong <darrick.wong@oracle.com>
> 
> Update the GPL related SPDX tags in LICENSES to reflect the SPDX 3.0
> tagging formats.
> 
> Signed-off-by: Darrick J. Wong <darrick.wong@oracle.com>
> ---
>   LICENSES/GPL-2.0 |    6 ++++++
>   1 file changed, 6 insertions(+)
> 
> 
> diff --git a/LICENSES/GPL-2.0 b/LICENSES/GPL-2.0
> index b8db91d3..ff0812fd 100644
> --- a/LICENSES/GPL-2.0
> +++ b/LICENSES/GPL-2.0
> @@ -1,5 +1,7 @@
>   Valid-License-Identifier: GPL-2.0
> +Valid-License-Identifier: GPL-2.0-only
>   Valid-License-Identifier: GPL-2.0+
> +Valid-License-Identifier: GPL-2.0-or-later
>   SPDX-URL: https://urldefense.proofpoint.com/v2/url?u=https-3A__spdx.org_licenses_GPL-2D2.0.html&d=DwICaQ&c=RoP1YumCXCgaWHvlZYR8PZh8Bv7qIrMUB65eapI_JnE&r=LHZQ8fHvy6wDKXGTWcm97burZH5sQKHRDMaY1UthQxc&m=yyH1nLyiAZtlQ8oRe73p1JKOpwh3hOylOYJJHf-fb-E&s=u5TL_q2un4FyVTyZCtV7gVqpRynFeNAyAB6R2fcd82I&e=
>   Usage-Guide:
>     To use this license in source code, put one of the following SPDX
> @@ -7,8 +9,12 @@ Usage-Guide:
>     guidelines in the licensing rules documentation.
>     For 'GNU General Public License (GPL) version 2 only' use:
>       SPDX-License-Identifier: GPL-2.0
> +  or
> +    SPDX-License-Identifier: GPL-2.0-only
>     For 'GNU General Public License (GPL) version 2 or any later version' use:
>       SPDX-License-Identifier: GPL-2.0+
> +  or
> +    SPDX-License-Identifier: GPL-2.0-or-later
>   License-Text:
>   
>   		    GNU GENERAL PUBLIC LICENSE
> 


Looks ok to me:
Reviewed-by: Allison Collins <allison.henderson@oracle.com>

^ permalink raw reply	[flat|nested] 31+ messages in thread

* Re: [PATCH 3/9] libfrog: refactor online geometry queries
  2019-08-30  4:20 ` [PATCH 3/9] libfrog: refactor online geometry queries Darrick J. Wong
@ 2019-08-30 21:03   ` Allison Collins
  2019-09-03 22:51   ` Dave Chinner
  1 sibling, 0 replies; 31+ messages in thread
From: Allison Collins @ 2019-08-30 21:03 UTC (permalink / raw)
  To: Darrick J. Wong, sandeen; +Cc: linux-xfs

On 8/29/19 9:20 PM, Darrick J. Wong wrote:
> From: Darrick J. Wong <darrick.wong@oracle.com>
> 
> Refactor all the open-coded XFS_IOC_FSGEOMETRY queries into a single
> helper that we can use to standardize behaviors across mixed xfslibs
> versions.  This is the prelude to introducing a new FSGEOMETRY version
> in 5.2 and needing to fix the (relatively few) client programs.
> 
> Signed-off-by: Darrick J. Wong <darrick.wong@oracle.com>

Looks good.  Mostly just lots of refactoring.  I think it looks a lot 
cleaner.

Reviewed-by: Allison Collins <allison.henderson@oracle.com>

> ---
>   Makefile            |    1 +
>   fsr/xfs_fsr.c       |   28 ++++++----------------------
>   growfs/xfs_growfs.c |   29 ++++++++++++-----------------
>   include/xfrog.h     |   22 ++++++++++++++++++++++
>   io/bmap.c           |    7 ++++---
>   io/fsmap.c          |    5 +++--
>   io/open.c           |   15 +++++++++++----
>   io/stat.c           |    8 ++++++--
>   libfrog/fsgeom.c    |   26 ++++++++++++++++++++++++++
>   quota/free.c        |   10 ++++++----
>   repair/xfs_repair.c |    8 +++++---
>   rtcp/Makefile       |    3 +++
>   rtcp/xfs_rtcp.c     |    9 +++++----
>   scrub/common.h      |    2 ++
>   scrub/phase1.c      |    5 +++--
>   spaceman/file.c     |   12 ++++++++----
>   spaceman/info.c     |   24 +++++++-----------------
>   17 files changed, 130 insertions(+), 84 deletions(-)
>   create mode 100644 include/xfrog.h
> 
> 
> diff --git a/Makefile b/Makefile
> index 9204bed8..0edc2700 100644
> --- a/Makefile
> +++ b/Makefile
> @@ -107,6 +107,7 @@ copy: libxlog
>   mkfs: libxcmd
>   spaceman: libxcmd
>   scrub: libhandle libxcmd
> +rtcp: libfrog
>   
>   ifeq ($(HAVE_BUILDDEFS), yes)
>   include $(BUILDRULES)
> diff --git a/fsr/xfs_fsr.c b/fsr/xfs_fsr.c
> index 1963a05e..4b239a30 100644
> --- a/fsr/xfs_fsr.c
> +++ b/fsr/xfs_fsr.c
> @@ -11,6 +11,7 @@
>   #include "xfs_bmap_btree.h"
>   #include "xfs_attr_sf.h"
>   #include "path.h"
> +#include "xfrog.h"
>   
>   #include <fcntl.h>
>   #include <errno.h>
> @@ -83,9 +84,8 @@ int cmp(const void *, const void *);
>   static void tmp_init(char *mnt);
>   static char * tmp_next(char *mnt);
>   static void tmp_close(char *mnt);
> -int xfs_getgeom(int , struct xfs_fsop_geom_v1 * );
>   
> -static struct xfs_fsop_geom_v1 fsgeom;	/* geometry of active mounted system */
> +static struct xfs_fsop_geom fsgeom;	/* geometry of active mounted system */
>   
>   #define NMOUNT 64
>   static int numfs;
> @@ -102,12 +102,6 @@ static int	nfrags = 0;	/* Debug option: Coerse into specific number
>   				 * of extents */
>   static int	openopts = O_CREAT|O_EXCL|O_RDWR|O_DIRECT;
>   
> -static int
> -xfs_fsgeometry(int fd, struct xfs_fsop_geom_v1 *geom)
> -{
> -    return ioctl(fd, XFS_IOC_FSGEOMETRY_V1, geom);
> -}
> -
>   static int
>   xfs_bulkstat_single(int fd, xfs_ino_t *lastip, struct xfs_bstat *ubuffer)
>   {
> @@ -630,7 +624,8 @@ fsrfs(char *mntdir, xfs_ino_t startino, int targetrange)
>   		return -1;
>   	}
>   
> -	if (xfs_getgeom(fsfd, &fsgeom) < 0 ) {
> +	ret = xfrog_geometry(fsfd, &fsgeom);
> +	if (ret) {
>   		fsrprintf(_("Skipping %s: could not get XFS geometry\n"),
>   			  mntdir);
>   		close(fsfd);
> @@ -772,7 +767,8 @@ fsrfile(char *fname, xfs_ino_t ino)
>   	}
>   
>   	/* Get the fs geometry */
> -	if (xfs_getgeom(fsfd, &fsgeom) < 0 ) {
> +	error = xfrog_geometry(fsfd, &fsgeom);
> +	if (error) {
>   		fsrprintf(_("Unable to get geom on fs for: %s\n"), fname);
>   		goto out;
>   	}
> @@ -1612,18 +1608,6 @@ getnextents(int fd)
>   	return(nextents);
>   }
>   
> -/*
> - * Get the fs geometry
> - */
> -int
> -xfs_getgeom(int fd, struct xfs_fsop_geom_v1 *fsgeom)
> -{
> -	if (xfs_fsgeometry(fd, fsgeom) < 0) {
> -		return -1;
> -	}
> -	return 0;
> -}
> -
>   /*
>    * Get xfs realtime space information
>    */
> diff --git a/growfs/xfs_growfs.c b/growfs/xfs_growfs.c
> index 20089d2b..5c881375 100644
> --- a/growfs/xfs_growfs.c
> +++ b/growfs/xfs_growfs.c
> @@ -7,6 +7,7 @@
>   #include "libxfs.h"
>   #include "path.h"
>   #include "fsgeom.h"
> +#include "xfrog.h"
>   
>   static void
>   usage(void)
> @@ -63,6 +64,7 @@ main(int argc, char **argv)
>   	fs_path_t		*fs;	/* mount point information */
>   	libxfs_init_t		xi;	/* libxfs structure */
>   	char			rpath[PATH_MAX];
> +	int			ret;
>   
>   	progname = basename(argv[0]);
>   	setlocale(LC_ALL, "");
> @@ -165,22 +167,14 @@ main(int argc, char **argv)
>   	}
>   
>   	/* get the current filesystem size & geometry */
> -	if (xfsctl(fname, ffd, XFS_IOC_FSGEOMETRY, &geo) < 0) {
> -		/*
> -		 * OK, new xfsctl barfed - back off and try earlier version
> -		 * as we're probably running an older kernel version.
> -		 * Only field added in the v2 geometry xfsctl is "logsunit"
> -		 * so we'll zero that out for later display (as zero).
> -		 */
> -		geo.logsunit = 0;
> -		if (xfsctl(fname, ffd, XFS_IOC_FSGEOMETRY_V1, &geo) < 0) {
> -			fprintf(stderr, _(
> -				"%s: cannot determine geometry of filesystem"
> -				" mounted at %s: %s\n"),
> -				progname, fname, strerror(errno));
> -			exit(1);
> -		}
> +	ret = xfrog_geometry(ffd, &geo);
> +	if (ret) {
> +		fprintf(stderr,
> +	_("%s: cannot determine geometry of filesystem mounted at %s: %s\n"),
> +			progname, fname, strerror(ret));
> +		exit(1);
>   	}
> +
>   	isint = geo.logstart > 0;
>   
>   	/*
> @@ -359,9 +353,10 @@ main(int argc, char **argv)
>   		}
>   	}
>   
> -	if (xfsctl(fname, ffd, XFS_IOC_FSGEOMETRY_V1, &ngeo) < 0) {
> +	ret = xfrog_geometry(ffd, &ngeo);
> +	if (ret) {
>   		fprintf(stderr, _("%s: XFS_IOC_FSGEOMETRY xfsctl failed: %s\n"),
> -			progname, strerror(errno));
> +			progname, strerror(ret));
>   		exit(1);
>   	}
>   	if (geo.datablocks != ngeo.datablocks)
> diff --git a/include/xfrog.h b/include/xfrog.h
> new file mode 100644
> index 00000000..f3541193
> --- /dev/null
> +++ b/include/xfrog.h
> @@ -0,0 +1,22 @@
> +/* SPDX-License-Identifier: GPL-2.0-or-later */
> +/*
> + * Copyright (c) 2019 Oracle, Inc.
> + * All Rights Reserved.
> + */
> +#ifndef __XFROG_H__
> +#define __XFROG_H__
> +
> +/*
> + * XFS Filesystem Random Online Gluecode
> + * =====================================
> + *
> + * These support functions wrap the more complex xfs ioctls so that xfs
> + * utilities can take advantage of them without having to deal with graceful
> + * degradation in the face of new ioctls.  They will also provide higher level
> + * abstractions when possible.
> + */
> +
> +struct xfs_fsop_geom;
> +int xfrog_geometry(int fd, struct xfs_fsop_geom *fsgeo);
> +
> +#endif	/* __XFROG_H__ */
> diff --git a/io/bmap.c b/io/bmap.c
> index d408826a..8f792a09 100644
> --- a/io/bmap.c
> +++ b/io/bmap.c
> @@ -9,6 +9,7 @@
>   #include "input.h"
>   #include "init.h"
>   #include "io.h"
> +#include "xfrog.h"
>   
>   static cmdinfo_t bmap_cmd;
>   
> @@ -105,11 +106,11 @@ bmap_f(
>   		bmv_iflags &= ~(BMV_IF_PREALLOC|BMV_IF_NO_DMAPI_READ);
>   
>   	if (vflag) {
> -		c = xfsctl(file->name, file->fd, XFS_IOC_FSGEOMETRY_V1, &fsgeo);
> -		if (c < 0) {
> +		c = xfrog_geometry(file->fd, &fsgeo);
> +		if (c) {
>   			fprintf(stderr,
>   				_("%s: can't get geometry [\"%s\"]: %s\n"),
> -				progname, file->name, strerror(errno));
> +				progname, file->name, strerror(c));
>   			exitcode = 1;
>   			return 0;
>   		}
> diff --git a/io/fsmap.c b/io/fsmap.c
> index 477c36fc..bf741e2a 100644
> --- a/io/fsmap.c
> +++ b/io/fsmap.c
> @@ -9,6 +9,7 @@
>   #include "path.h"
>   #include "io.h"
>   #include "input.h"
> +#include "xfrog.h"
>   
>   static cmdinfo_t	fsmap_cmd;
>   static dev_t		xfs_data_dev;
> @@ -447,8 +448,8 @@ fsmap_f(
>   	}
>   
>   	if (vflag) {
> -		c = ioctl(file->fd, XFS_IOC_FSGEOMETRY, &fsgeo);
> -		if (c < 0) {
> +		c = xfrog_geometry(file->fd, &fsgeo);
> +		if (c) {
>   			fprintf(stderr,
>   				_("%s: can't get geometry [\"%s\"]: %s\n"),
>   				progname, file->name, strerror(errno));
> diff --git a/io/open.c b/io/open.c
> index c7f5248a..8b24a4f9 100644
> --- a/io/open.c
> +++ b/io/open.c
> @@ -9,6 +9,7 @@
>   #include "init.h"
>   #include "io.h"
>   #include "libxfs.h"
> +#include "xfrog.h"
>   
>   #ifndef __O_TMPFILE
>   #if defined __alpha__
> @@ -118,10 +119,16 @@ openfile(
>   	if (flags & IO_PATH) {
>   		/* Can't call ioctl() on O_PATH fds */
>   		memset(geom, 0, sizeof(*geom));
> -	} else if (xfsctl(path, fd, XFS_IOC_FSGEOMETRY, geom) < 0) {
> -		perror("XFS_IOC_FSGEOMETRY");
> -		close(fd);
> -		return -1;
> +	} else {
> +		int	ret;
> +
> +		ret = xfrog_geometry(fd, geom);
> +		if (ret) {
> +			errno = ret;
> +			perror("XFS_IOC_FSGEOMETRY");
> +			close(fd);
> +			return -1;
> +		}
>   	}
>   
>   	if (!(flags & (IO_READONLY | IO_PATH)) && (flags & IO_REALTIME)) {
> diff --git a/io/stat.c b/io/stat.c
> index 37c0b2e8..865407b1 100644
> --- a/io/stat.c
> +++ b/io/stat.c
> @@ -12,6 +12,7 @@
>   #include "io.h"
>   #include "statx.h"
>   #include "libxfs.h"
> +#include "xfrog.h"
>   
>   #include <fcntl.h>
>   
> @@ -178,6 +179,7 @@ statfs_f(
>   	struct xfs_fsop_counts	fscounts;
>   	struct xfs_fsop_geom	fsgeo;
>   	struct statfs		st;
> +	int			ret;
>   
>   	printf(_("fd.path = \"%s\"\n"), file->name);
>   	if (platform_fstatfs(file->fd, &st) < 0) {
> @@ -194,8 +196,10 @@ statfs_f(
>   	}
>   	if (file->flags & IO_FOREIGN)
>   		return 0;
> -	if ((xfsctl(file->name, file->fd, XFS_IOC_FSGEOMETRY_V1, &fsgeo)) < 0) {
> -		perror("XFS_IOC_FSGEOMETRY_V1");
> +	ret = xfrog_geometry(file->fd, &fsgeo);
> +	if (ret) {
> +		errno = ret;
> +		perror("XFS_IOC_FSGEOMETRY");
>   	} else {
>   		printf(_("geom.bsize = %u\n"), fsgeo.blocksize);
>   		printf(_("geom.agcount = %u\n"), fsgeo.agcount);
> diff --git a/libfrog/fsgeom.c b/libfrog/fsgeom.c
> index 8879d161..69d24774 100644
> --- a/libfrog/fsgeom.c
> +++ b/libfrog/fsgeom.c
> @@ -4,6 +4,7 @@
>    */
>   #include "libxfs.h"
>   #include "fsgeom.h"
> +#include "xfrog.h"
>   
>   void
>   xfs_report_geom(
> @@ -67,3 +68,28 @@ xfs_report_geom(
>   		geo->rtextsize * geo->blocksize, (unsigned long long)geo->rtblocks,
>   			(unsigned long long)geo->rtextents);
>   }
> +
> +/* Try to obtain the xfs geometry.  On error returns a positive error code. */
> +int
> +xfrog_geometry(
> +	int			fd,
> +	struct xfs_fsop_geom	*fsgeo)
> +{
> +	int			ret;
> +
> +	memset(fsgeo, 0, sizeof(*fsgeo));
> +
> +	ret = ioctl(fd, XFS_IOC_FSGEOMETRY, fsgeo);
> +	if (!ret)
> +		return 0;
> +
> +	ret = ioctl(fd, XFS_IOC_FSGEOMETRY_V4, fsgeo);
> +	if (!ret)
> +		return 0;
> +
> +	ret = ioctl(fd, XFS_IOC_FSGEOMETRY_V1, fsgeo);
> +	if (!ret)
> +		return 0;
> +
> +	return errno;
> +}
> diff --git a/quota/free.c b/quota/free.c
> index 1d13006e..65cb1e21 100644
> --- a/quota/free.c
> +++ b/quota/free.c
> @@ -8,6 +8,7 @@
>   #include "command.h"
>   #include "init.h"
>   #include "quota.h"
> +#include "xfrog.h"
>   
>   static cmdinfo_t free_cmd;
>   
> @@ -51,7 +52,7 @@ mount_free_space_data(
>   	struct xfs_fsop_geom	fsgeo;
>   	struct statfs		st;
>   	uint64_t		logsize, count, free;
> -	int			fd;
> +	int			fd, ret;
>   
>   	if ((fd = open(mount->fs_dir, O_RDONLY)) < 0) {
>   		exitcode = 1;
> @@ -67,9 +68,10 @@ mount_free_space_data(
>   	}
>   
>   	if (!(mount->fs_flags & FS_FOREIGN)) {
> -		if ((xfsctl(mount->fs_dir, fd, XFS_IOC_FSGEOMETRY_V1,
> -							&fsgeo)) < 0) {
> -			perror("XFS_IOC_FSGEOMETRY_V1");
> +		ret = xfrog_geometry(fd, &fsgeo);
> +		if (ret) {
> +			errno = ret;
> +			perror("XFS_IOC_FSGEOMETRY");
>   			close(fd);
>   			return 0;
>   		}
> diff --git a/repair/xfs_repair.c b/repair/xfs_repair.c
> index ce70e2de..32c9a96e 100644
> --- a/repair/xfs_repair.c
> +++ b/repair/xfs_repair.c
> @@ -22,6 +22,7 @@
>   #include "dinode.h"
>   #include "slab.h"
>   #include "rmap.h"
> +#include "xfrog.h"
>   
>   /*
>    * option tables for getsubopt calls
> @@ -634,13 +635,14 @@ static void
>   check_fs_vs_host_sectsize(
>   	struct xfs_sb	*sb)
>   {
> -	int	fd;
> +	int	fd, ret;
>   	long	old_flags;
> -	struct xfs_fsop_geom_v1 geom = { 0 };
> +	struct xfs_fsop_geom	geom = { 0 };
>   
>   	fd = libxfs_device_to_fd(x.ddev);
>   
> -	if (ioctl(fd, XFS_IOC_FSGEOMETRY_V1, &geom) < 0) {
> +	ret = xfrog_geometry(fd, &geom);
> +	if (ret) {
>   		do_log(_("Cannot get host filesystem geometry.\n"
>   	"Repair may fail if there is a sector size mismatch between\n"
>   	"the image and the host filesystem.\n"));
> diff --git a/rtcp/Makefile b/rtcp/Makefile
> index 808b5378..264b4f27 100644
> --- a/rtcp/Makefile
> +++ b/rtcp/Makefile
> @@ -9,6 +9,9 @@ LTCOMMAND = xfs_rtcp
>   CFILES = xfs_rtcp.c
>   LLDFLAGS = -static
>   
> +LLDLIBS = $(LIBFROG)
> +LTDEPENDENCIES = $(LIBFROG)
> +
>   default: depend $(LTCOMMAND)
>   
>   include $(BUILDRULES)
> diff --git a/rtcp/xfs_rtcp.c b/rtcp/xfs_rtcp.c
> index 1027c913..6d012dda 100644
> --- a/rtcp/xfs_rtcp.c
> +++ b/rtcp/xfs_rtcp.c
> @@ -5,6 +5,7 @@
>    */
>   
>   #include "libxfs.h"
> +#include "xfrog.h"
>   
>   int rtcp(char *, char *, int);
>   int xfsrtextsize(char *path);
> @@ -368,8 +369,8 @@ rtcp( char *source, char *target, int fextsize)
>   int
>   xfsrtextsize( char *path)
>   {
> -	int fd, rval, rtextsize;
> -	struct xfs_fsop_geom_v1 geo;
> +	struct xfs_fsop_geom	geo;
> +	int			fd, rval, rtextsize;
>   
>   	fd = open( path, O_RDONLY );
>   	if ( fd < 0 ) {
> @@ -377,9 +378,9 @@ xfsrtextsize( char *path)
>   			progname, path, strerror(errno));
>   		return -1;
>   	}
> -	rval = xfsctl( path, fd, XFS_IOC_FSGEOMETRY_V1, &geo );
> +	rval = xfrog_geometry(fd, &geo);
>   	close(fd);
> -	if ( rval < 0 )
> +	if (rval)
>   		return -1;
>   
>   	rtextsize = geo.rtextsize * geo.blocksize;
> diff --git a/scrub/common.h b/scrub/common.h
> index e85a0333..33555891 100644
> --- a/scrub/common.h
> +++ b/scrub/common.h
> @@ -28,6 +28,8 @@ void __str_out(struct scrub_ctx *ctx, const char *descr, enum error_level level,
>   
>   #define str_errno(ctx, str) \
>   	__str_out(ctx, str, S_ERROR,	errno,	__FILE__, __LINE__, NULL)
> +#define str_liberror(ctx, error, str) \
> +	__str_out(ctx, str, S_ERROR,	error,	__FILE__, __LINE__, NULL)
>   #define str_error(ctx, str, ...) \
>   	__str_out(ctx, str, S_ERROR,	0,	__FILE__, __LINE__, __VA_ARGS__)
>   #define str_warn(ctx, str, ...) \
> diff --git a/scrub/phase1.c b/scrub/phase1.c
> index 04a5f4a9..bdd23d26 100644
> --- a/scrub/phase1.c
> +++ b/scrub/phase1.c
> @@ -26,6 +26,7 @@
>   #include "disk.h"
>   #include "scrub.h"
>   #include "repair.h"
> +#include "xfrog.h"
>   
>   /* Phase 1: Find filesystem geometry (and clean up after) */
>   
> @@ -129,9 +130,9 @@ _("Does not appear to be an XFS filesystem!"));
>   	}
>   
>   	/* Retrieve XFS geometry. */
> -	error = ioctl(ctx->mnt_fd, XFS_IOC_FSGEOMETRY, &ctx->geo);
> +	error = xfrog_geometry(ctx->mnt_fd, &ctx->geo);
>   	if (error) {
> -		str_errno(ctx, ctx->mntpoint);
> +		str_liberror(ctx, error, _("Retrieving XFS geometry"));
>   		return false;
>   	}
>   
> diff --git a/spaceman/file.c b/spaceman/file.c
> index 7e33e07e..9dba1e58 100644
> --- a/spaceman/file.c
> +++ b/spaceman/file.c
> @@ -6,6 +6,7 @@
>    */
>   
>   #include "libxfs.h"
> +#include "xfrog.h"
>   #include <sys/mman.h>
>   #include "command.h"
>   #include "input.h"
> @@ -48,7 +49,7 @@ openfile(
>   	struct fs_path	*fs_path)
>   {
>   	struct fs_path	*fsp;
> -	int		fd;
> +	int		fd, ret;
>   
>   	fd = open(path, 0);
>   	if (fd < 0) {
> @@ -56,13 +57,16 @@ openfile(
>   		return -1;
>   	}
>   
> -	if (ioctl(fd, XFS_IOC_FSGEOMETRY, geom) < 0) {
> -		if (errno == ENOTTY)
> +	ret = xfrog_geometry(fd, geom);
> +	if (ret) {
> +		if (ret == ENOTTY)
>   			fprintf(stderr,
>   _("%s: Not on a mounted XFS filesystem.\n"),
>   					path);
> -		else
> +		else {
> +			errno = ret;
>   			perror("XFS_IOC_FSGEOMETRY");
> +		}
>   		close(fd);
>   		return -1;
>   	}
> diff --git a/spaceman/info.c b/spaceman/info.c
> index 01d0744a..d32db6ab 100644
> --- a/spaceman/info.c
> +++ b/spaceman/info.c
> @@ -4,6 +4,7 @@
>    * Author: Darrick J. Wong <darrick.wong@oracle.com>
>    */
>   #include "libxfs.h"
> +#include "xfrog.h"
>   #include "command.h"
>   #include "init.h"
>   #include "path.h"
> @@ -37,24 +38,13 @@ info_f(
>   	}
>   
>   	/* get the current filesystem size & geometry */
> -	error = ioctl(file->fd, XFS_IOC_FSGEOMETRY, &geo);
> +	error = xfrog_geometry(file->fd, &geo);
>   	if (error) {
> -		/*
> -		 * OK, new xfsctl barfed - back off and try earlier version
> -		 * as we're probably running an older kernel version.
> -		 * Only field added in the v2 geometry xfsctl is "logsunit"
> -		 * so we'll zero that out for later display (as zero).
> -		 */
> -		geo.logsunit = 0;
> -		error = ioctl(file->fd, XFS_IOC_FSGEOMETRY_V1, &geo);
> -		if (error) {
> -			fprintf(stderr, _(
> -				"%s: cannot determine geometry of filesystem"
> -				" mounted at %s: %s\n"),
> -				progname, file->name, strerror(errno));
> -			exitcode = 1;
> -			return 0;
> -		}
> +		fprintf(stderr,
> +	_("%s: cannot determine geometry of filesystem mounted at %s: %s\n"),
> +			progname, file->name, strerror(error));
> +		exitcode = 1;
> +		return 0;
>   	}
>   
>   	xfs_report_geom(&geo, file->fs_path.fs_name, file->fs_path.fs_log,
> 

^ permalink raw reply	[flat|nested] 31+ messages in thread

* Re: [PATCH 7/9] libfrog: refactor open-coded bulkstat calls
  2019-08-30  4:21 ` [PATCH 7/9] libfrog: refactor open-coded bulkstat calls Darrick J. Wong
@ 2019-08-30 23:26   ` Darrick J. Wong
  2019-08-31  0:42   ` [PATCH v2 " Darrick J. Wong
  2019-09-01 20:55   ` [PATCH " Allison Collins
  2 siblings, 0 replies; 31+ messages in thread
From: Darrick J. Wong @ 2019-08-30 23:26 UTC (permalink / raw)
  To: sandeen; +Cc: linux-xfs

On Thu, Aug 29, 2019 at 09:21:09PM -0700, Darrick J. Wong wrote:
> From: Darrick J. Wong <darrick.wong@oracle.com>
> 
> Refactor the BULKSTAT_SINGLE and BULKSTAT ioctl callsites into helper
> functions.
> 
> Signed-off-by: Darrick J. Wong <darrick.wong@oracle.com>
> ---
>  fsr/xfs_fsr.c      |  110 ++++++++++++++++++++++------------------------------
>  include/xfrog.h    |    7 +++
>  io/open.c          |   72 +++++++++++++++++-----------------
>  io/swapext.c       |   20 ++-------
>  libfrog/Makefile   |    1 
>  libfrog/bulkstat.c |   52 +++++++++++++++++++++++++
>  quota/quot.c       |   33 ++++++++--------
>  scrub/inodes.c     |   32 ++++-----------
>  8 files changed, 172 insertions(+), 155 deletions(-)
>  create mode 100644 libfrog/bulkstat.c
> 
> 
> diff --git a/fsr/xfs_fsr.c b/fsr/xfs_fsr.c
> index 4b239a30..36402252 100644
> --- a/fsr/xfs_fsr.c
> +++ b/fsr/xfs_fsr.c
> @@ -102,31 +102,6 @@ static int	nfrags = 0;	/* Debug option: Coerse into specific number
>  				 * of extents */
>  static int	openopts = O_CREAT|O_EXCL|O_RDWR|O_DIRECT;
>  
> -static int
> -xfs_bulkstat_single(int fd, xfs_ino_t *lastip, struct xfs_bstat *ubuffer)
> -{
> -    struct xfs_fsop_bulkreq  bulkreq;
> -
> -    bulkreq.lastip = (__u64 *)lastip;
> -    bulkreq.icount = 1;
> -    bulkreq.ubuffer = ubuffer;
> -    bulkreq.ocount = NULL;
> -    return ioctl(fd, XFS_IOC_FSBULKSTAT_SINGLE, &bulkreq);
> -}
> -
> -static int
> -xfs_bulkstat(int fd, xfs_ino_t *lastip, int icount,
> -                    struct xfs_bstat *ubuffer, __s32 *ocount)
> -{
> -    struct xfs_fsop_bulkreq  bulkreq;
> -
> -    bulkreq.lastip = (__u64 *)lastip;
> -    bulkreq.icount = icount;
> -    bulkreq.ubuffer = ubuffer;
> -    bulkreq.ocount = ocount;
> -    return ioctl(fd, XFS_IOC_FSBULKSTAT, &bulkreq);
> -}
> -
>  static int
>  xfs_swapext(int fd, xfs_swapext_t *sx)
>  {
> @@ -596,11 +571,11 @@ fsrall_cleanup(int timeout)
>  static int
>  fsrfs(char *mntdir, xfs_ino_t startino, int targetrange)
>  {
> -
> -	int	fsfd, fd;
> +	struct xfs_fd	fsxfd = XFS_FD_INIT_EMPTY;
> +	int	fd;
>  	int	count = 0;
>  	int	ret;
> -	__s32	buflenout;
> +	uint32_t buflenout;
>  	struct xfs_bstat buf[GRABSZ];
>  	char	fname[64];
>  	char	*tname;
> @@ -617,26 +592,27 @@ fsrfs(char *mntdir, xfs_ino_t startino, int targetrange)
>  		return -1;
>  	}
>  
> -	if ((fsfd = open(mntdir, O_RDONLY)) < 0) {
> +	if ((fsxfd.fd = open(mntdir, O_RDONLY)) < 0) {
>  		fsrprintf(_("unable to open: %s: %s\n"),
>  		          mntdir, strerror( errno ));
>  		free(fshandlep);
>  		return -1;
>  	}
>  
> -	ret = xfrog_geometry(fsfd, &fsgeom);
> +	ret = xfd_prepare_geometry(&fsxfd);
>  	if (ret) {
>  		fsrprintf(_("Skipping %s: could not get XFS geometry\n"),
>  			  mntdir);
> -		close(fsfd);
> +		xfd_close(&fsxfd);
>  		free(fshandlep);
>  		return -1;
>  	}
> +	memcpy(&fsgeom, &fsxfd.fsgeom, sizeof(fsgeom));
>  
>  	tmp_init(mntdir);
>  
> -	while ((ret = xfs_bulkstat(fsfd,
> -				&lastino, GRABSZ, &buf[0], &buflenout)) == 0) {
> +	while ((ret = xfrog_bulkstat(&fsxfd, &lastino, GRABSZ, &buf[0],
> +				&buflenout)) == 0) {
>  		struct xfs_bstat *p;
>  		struct xfs_bstat *endp;
>  
> @@ -685,16 +661,16 @@ fsrfs(char *mntdir, xfs_ino_t startino, int targetrange)
>  		}
>  		if (endtime && endtime < time(NULL)) {
>  			tmp_close(mntdir);
> -			close(fsfd);
> +			xfd_close(&fsxfd);
>  			fsrall_cleanup(1);
>  			exit(1);
>  		}
>  	}
> -	if (ret < 0)
> -		fsrprintf(_("%s: xfs_bulkstat: %s\n"), progname, strerror(errno));
> +	if (ret)
> +		fsrprintf(_("%s: bulkstat: %s\n"), progname, strerror(ret));
>  out0:
>  	tmp_close(mntdir);
> -	close(fsfd);
> +	xfd_close(&fsxfd);
>  	free(fshandlep);
>  	return 0;
>  }
> @@ -727,13 +703,16 @@ fsrdir(char *dirname)
>   * an open on the file and passes this all to fsrfile_common.
>   */
>  static int
> -fsrfile(char *fname, xfs_ino_t ino)
> +fsrfile(
> +	char			*fname,
> +	xfs_ino_t		ino)
>  {
> -	struct xfs_bstat statbuf;
> -	jdm_fshandle_t	*fshandlep;
> -	int	fd = -1, fsfd = -1;
> -	int	error = -1;
> -	char	*tname;
> +	struct xfs_fd		fsxfd = XFS_FD_INIT_EMPTY;
> +	struct xfs_bstat	statbuf;
> +	jdm_fshandle_t		*fshandlep;
> +	int			fd = -1;
> +	int			error = -1;
> +	char			*tname;
>  
>  	fshandlep = jdm_getfshandle(getparent (fname) );
>  	if (!fshandlep) {
> @@ -746,16 +725,23 @@ fsrfile(char *fname, xfs_ino_t ino)
>  	 * Need to open something on the same filesystem as the
>  	 * file.  Open the parent.
>  	 */
> -	fsfd = open(getparent(fname), O_RDONLY);
> -	if (fsfd < 0) {
> +	fsxfd.fd = open(getparent(fname), O_RDONLY);
> +	if (fsxfd.fd < 0) {
>  		fsrprintf(_("unable to open sys handle for %s: %s\n"),
>  			fname, strerror(errno));
>  		goto out;
>  	}
>  
> -	if ((xfs_bulkstat_single(fsfd, &ino, &statbuf)) < 0) {
> +	error = xfd_prepare_geometry(&fsxfd);
> +	if (error) {
> +		fsrprintf(_("Unable to get geom on fs for: %s\n"), fname);
> +		goto out;
> +	}
> +
> +	error = xfrog_bulkstat_single(&fsxfd, ino, &statbuf);
> +	if (error) {
>  		fsrprintf(_("unable to get bstat on %s: %s\n"),
> -			fname, strerror(errno));
> +			fname, strerror(error));
>  		goto out;
>  	}
>  
> @@ -766,12 +752,8 @@ fsrfile(char *fname, xfs_ino_t ino)
>  		goto out;
>  	}
>  
> -	/* Get the fs geometry */
> -	error = xfrog_geometry(fsfd, &fsgeom);
> -	if (error) {
> -		fsrprintf(_("Unable to get geom on fs for: %s\n"), fname);
> -		goto out;
> -	}
> +	/* Stash the fs geometry for general use. */
> +	memcpy(&fsgeom, &fsxfd.fsgeom, sizeof(fsgeom));
>  
>  	tname = gettmpname(fname);
>  
> @@ -779,8 +761,7 @@ fsrfile(char *fname, xfs_ino_t ino)
>  		error = fsrfile_common(fname, tname, NULL, fd, &statbuf);
>  
>  out:
> -	if (fsfd >= 0)
> -		close(fsfd);
> +	xfd_close(&fsxfd);
>  	if (fd >= 0)
>  		close(fd);
>  	free(fshandlep);
> @@ -947,6 +928,7 @@ fsr_setup_attr_fork(
>  	struct xfs_bstat *bstatp)
>  {
>  #ifdef HAVE_FSETXATTR
> +	struct xfs_fd	txfd = XFS_FD_INIT(tfd);
>  	struct stat	tstatbuf;
>  	int		i;
>  	int		diff = 0;
> @@ -964,7 +946,7 @@ fsr_setup_attr_fork(
>  	if (!(fsgeom.flags & XFS_FSOP_GEOM_FLAGS_ATTR2) ||
>  	    bstatp->bs_forkoff == 0) {
>  		/* attr1 */
> -		ret = fsetxattr(tfd, "user.X", "X", 1, XATTR_CREATE);
> +		ret = fsetxattr(txfd.fd, "user.X", "X", 1, XATTR_CREATE);
>  		if (ret) {
>  			fsrprintf(_("could not set ATTR\n"));
>  			return -1;
> @@ -974,7 +956,7 @@ fsr_setup_attr_fork(
>  
>  	/* attr2 w/ fork offsets */
>  
> -	if (fstat(tfd, &tstatbuf) < 0) {
> +	if (fstat(txfd.fd, &tstatbuf) < 0) {
>  		fsrprintf(_("unable to stat temp file: %s\n"),
>  					strerror(errno));
>  		return -1;
> @@ -983,18 +965,18 @@ fsr_setup_attr_fork(
>  	i = 0;
>  	do {
>  		struct xfs_bstat tbstat;
> -		xfs_ino_t	ino;
>  		char		name[64];
> +		int		ret;
>  
>  		/*
>  		 * bulkstat the temp inode to see what the forkoff is.  Use
>  		 * this to compare against the target and determine what we
>  		 * need to do.
>  		 */
> -		ino = tstatbuf.st_ino;
> -		if ((xfs_bulkstat_single(tfd, &ino, &tbstat)) < 0) {
> +		ret = xfrog_bulkstat_single(&txfd, tstatbuf.st_ino, &tbstat);
> +		if (ret) {
>  			fsrprintf(_("unable to get bstat on temp file: %s\n"),
> -						strerror(errno));
> +						strerror(ret));
>  			return -1;
>  		}
>  		if (dflag)
> @@ -1014,7 +996,7 @@ fsr_setup_attr_fork(
>  		 */
>  		if (!tbstat.bs_forkoff) {
>  			ASSERT(i == 0);
> -			ret = fsetxattr(tfd, name, "XX", 2, XATTR_CREATE);
> +			ret = fsetxattr(txfd.fd, name, "XX", 2, XATTR_CREATE);
>  			if (ret) {
>  				fsrprintf(_("could not set ATTR\n"));
>  				return -1;
> @@ -1050,7 +1032,7 @@ fsr_setup_attr_fork(
>  			if (diff < 0) {
>  				char val[2048];
>  				memset(val, 'X', 2048);
> -				if (fsetxattr(tfd, name, val, 2048, 0)) {
> +				if (fsetxattr(txfd.fd, name, val, 2048, 0)) {
>  					fsrprintf(_("big ATTR set failed\n"));
>  					return -1;
>  				}
> @@ -1094,7 +1076,7 @@ fsr_setup_attr_fork(
>  		}
>  
>  		/* we need to grow the attr fork, so create another attr */
> -		ret = fsetxattr(tfd, name, "XX", 2, XATTR_CREATE);
> +		ret = fsetxattr(txfd.fd, name, "XX", 2, XATTR_CREATE);
>  		if (ret) {
>  			fsrprintf(_("could not set ATTR\n"));
>  			return -1;
> diff --git a/include/xfrog.h b/include/xfrog.h
> index a08f6464..7bda9810 100644
> --- a/include/xfrog.h
> +++ b/include/xfrog.h
> @@ -108,4 +108,11 @@ cvt_b_to_off_fsbt(
>  	return bytes >> xfd->blocklog;
>  }
>  
> +/* Bulkstat wrappers */
> +struct xfs_bstat;
> +int xfrog_bulkstat_single(struct xfs_fd *xfd, uint64_t ino,
> +		struct xfs_bstat *ubuffer);
> +int xfrog_bulkstat(struct xfs_fd *xfd, uint64_t *lastino, uint32_t icount,
> +		struct xfs_bstat *ubuffer, uint32_t *ocount);
> +
>  #endif	/* __XFROG_H__ */
> diff --git a/io/open.c b/io/open.c
> index 8b24a4f9..35e6131b 100644
> --- a/io/open.c
> +++ b/io/open.c
> @@ -719,19 +719,18 @@ get_last_inode(void)
>  
>  static int
>  inode_f(
> -	  int			argc,
> -	  char			**argv)
> +	int			argc,
> +	char			**argv)
>  {
> -	__s32			count = 0;
> -	__u64			result_ino = 0;
> -	__u64			userino = NULLFSINO;
> +	struct xfs_bstat	bstat;
> +	uint32_t		count = 0;
> +	uint64_t		result_ino = 0;
> +	uint64_t		userino = NULLFSINO;
>  	char			*p;
>  	int			c;
>  	int			verbose = 0;
>  	int			ret_next = 0;
> -	int			cmd = 0;
> -	struct xfs_fsop_bulkreq	bulkreq;
> -	struct xfs_bstat	bstat;
> +	int			ret;
>  
>  	while ((c = getopt(argc, argv, "nv")) != EOF) {
>  		switch (c) {
> @@ -773,35 +772,38 @@ inode_f(
>  			exitcode = 1;
>  			return 0;
>  		}
> +	} else if (ret_next) {
> +		struct xfs_fd	xfd = XFS_FD_INIT(file->fd);
> +
> +		/* get next inode */
> +		ret = xfrog_bulkstat(&xfd, &userino, 1, &bstat, &count);
> +		if (ret) {
> +			errno = ret;
> +			perror("bulkstat");
> +			exitcode = 1;
> +			return 0;
> +		}
> +
> +		/* The next inode in use, or 0 if none */
> +		if (count)
> +			result_ino = bstat.bs_ino;
> +		else
> +			result_ino = 0;
>  	} else {
> -		if (ret_next)	/* get next inode */
> -			cmd = XFS_IOC_FSBULKSTAT;
> -		else		/* get this inode */
> -			cmd = XFS_IOC_FSBULKSTAT_SINGLE;
> -
> -		bulkreq.lastip = &userino;
> -		bulkreq.icount = 1;
> -		bulkreq.ubuffer = &bstat;
> -		bulkreq.ocount = &count;
> -
> -		if (xfsctl(file->name, file->fd, cmd, &bulkreq)) {
> -			if (!ret_next && errno == EINVAL) {
> -				/* Not in use */
> -				result_ino = 0;
> -			} else {
> -				perror("xfsctl");
> -				exitcode = 1;
> -				return 0;
> -			}
> -		} else if (ret_next) {
> -			/* The next inode in use, or 0 if none */
> -			if (*bulkreq.ocount)
> -				result_ino = bstat.bs_ino;
> -			else
> -				result_ino = 0;
> +		struct xfs_fd	xfd = XFS_FD_INIT(file->fd);
> +
> +		/* get this inode */
> +		ret = xfrog_bulkstat_single(&xfd, userino, &bstat);
> +		if (ret == EINVAL) {
> +			/* Not in use */
> +			result_ino = 0;
> +		} else if (ret) {
> +			errno = ret;
> +			perror("bulkstat_single");
> +			exitcode = 1;
> +			return 0;
>  		} else {
> -			/* The inode we asked about */
> -			result_ino = userino;
> +			result_ino = bstat.bs_ino;
>  		}
>  	}
>  
> diff --git a/io/swapext.c b/io/swapext.c
> index d360c221..fbf4fff5 100644
> --- a/io/swapext.c
> +++ b/io/swapext.c
> @@ -8,6 +8,7 @@
>  #include "input.h"
>  #include "init.h"
>  #include "io.h"
> +#include "xfrog.h"
>  
>  static cmdinfo_t swapext_cmd;
>  
> @@ -20,26 +21,12 @@ swapext_help(void)
>  "\n"));
>  }
>  
> -static int
> -xfs_bulkstat_single(
> -	int			fd,
> -	xfs_ino_t		*lastip,
> -	struct xfs_bstat	*ubuffer)
> -{
> -	struct xfs_fsop_bulkreq	bulkreq;
> -
> -	bulkreq.lastip = (__u64 *)lastip;
> -	bulkreq.icount = 1;
> -	bulkreq.ubuffer = ubuffer;
> -	bulkreq.ocount = NULL;
> -	return ioctl(fd, XFS_IOC_FSBULKSTAT_SINGLE, &bulkreq);
> -}
> -
>  static int
>  swapext_f(
>  	int			argc,
>  	char			**argv)
>  {
> +	struct xfs_fd		fxfd = XFS_FD_INIT(file->fd);
>  	int			fd;
>  	int			error;
>  	struct xfs_swapext	sx;
> @@ -60,8 +47,9 @@ swapext_f(
>  		goto out;
>  	}
>  
> -	error = xfs_bulkstat_single(file->fd, &stat.st_ino, &sx.sx_stat);
> +	error = xfrog_bulkstat_single(&fxfd, stat.st_ino, &sx.sx_stat);
>  	if (error) {
> +		errno = error;
>  		perror("bulkstat");
>  		goto out;
>  	}
> diff --git a/libfrog/Makefile b/libfrog/Makefile
> index f5a0539b..05c6f701 100644
> --- a/libfrog/Makefile
> +++ b/libfrog/Makefile
> @@ -13,6 +13,7 @@ LT_AGE = 0
>  CFILES = \
>  avl64.c \
>  bitmap.c \
> +bulkstat.c \
>  convert.c \
>  crc32.c \
>  fsgeom.c \
> diff --git a/libfrog/bulkstat.c b/libfrog/bulkstat.c
> new file mode 100644
> index 00000000..0e11ccea
> --- /dev/null
> +++ b/libfrog/bulkstat.c
> @@ -0,0 +1,52 @@
> +// SPDX-License-Identifier: GPL-2.0+
> +/*
> + * Copyright (C) 2019 Oracle.  All Rights Reserved.
> + * Author: Darrick J. Wong <darrick.wong@oracle.com>
> + */
> +#include "xfs.h"
> +#include "xfrog.h"
> +
> +/* Bulkstat a single inode.  Returns zero or a positive error code. */
> +int
> +xfrog_bulkstat_single(
> +	struct xfs_fd		*xfd,
> +	uint64_t		ino,
> +	struct xfs_bstat	*ubuffer)
> +{
> +	__u64			i = ino;
> +	struct xfs_fsop_bulkreq	bulkreq = {
> +		.lastip		= &i,
> +		.icount		= 1,
> +		.ubuffer	= ubuffer,
> +		.ocount		= NULL,
> +	};
> +	int			ret;
> +
> +	ret = ioctl(xfd->fd, XFS_IOC_FSBULKSTAT_SINGLE, &bulkreq);
> +	if (ret)
> +		return errno;
> +	return 0;
> +}
> +
> +/* Bulkstat a bunch of inodes.  Returns zero or a positive error code. */
> +int
> +xfrog_bulkstat(
> +	struct xfs_fd		*xfd,
> +	uint64_t		*lastino,
> +	uint32_t		icount,
> +	struct xfs_bstat	*ubuffer,
> +	uint32_t		*ocount)
> +{
> +	struct xfs_fsop_bulkreq	bulkreq = {
> +		.lastip		= (__u64 *)lastino,
> +		.icount		= icount,
> +		.ubuffer	= ubuffer,
> +		.ocount		= (__s32 *)ocount,
> +	};
> +	int			ret;
> +
> +	ret = ioctl(xfd->fd, XFS_IOC_FSBULKSTAT, &bulkreq);
> +	if (ret)
> +		return errno;
> +	return 0;
> +}
> diff --git a/quota/quot.c b/quota/quot.c
> index 6bc91171..1e970819 100644
> --- a/quota/quot.c
> +++ b/quota/quot.c
> @@ -11,6 +11,7 @@
>  #include <grp.h>
>  #include "init.h"
>  #include "quota.h"
> +#include "xfrog.h"
>  
>  typedef struct du {
>  	struct du	*next;
> @@ -124,13 +125,13 @@ quot_bulkstat_add(
>  static void
>  quot_bulkstat_mount(
>  	char			*fsdir,
> -	uint			flags)
> +	unsigned int		flags)
>  {
> -	struct xfs_fsop_bulkreq	bulkreq;
> +	struct xfs_fd		fsxfd = XFS_FD_INIT_EMPTY;
>  	struct xfs_bstat	*buf;
> -	__u64			last = 0;
> -	__s32			count;
> -	int			i, sts, fsfd;
> +	uint64_t		last = 0;
> +	uint32_t		count;
> +	int			i, sts;
>  	du_t			**dp;
>  
>  	/*
> @@ -145,8 +146,8 @@ quot_bulkstat_mount(
>  			*dp = NULL;
>  	ndu[0] = ndu[1] = ndu[2] = 0;
>  
> -	fsfd = open(fsdir, O_RDONLY);
> -	if (fsfd < 0) {
> +	fsxfd.fd = open(fsdir, O_RDONLY);
> +	if (fsxfd.fd < 0) {
>  		perror(fsdir);
>  		return;
>  	}
> @@ -154,25 +155,23 @@ quot_bulkstat_mount(
>  	buf = (struct xfs_bstat *)calloc(NBSTAT, sizeof(struct xfs_bstat));
>  	if (!buf) {
>  		perror("calloc");
> -		close(fsfd);
> +		xfd_close(&fsxfd);
>  		return;
>  	}
>  
> -	bulkreq.lastip = &last;
> -	bulkreq.icount = NBSTAT;
> -	bulkreq.ubuffer = buf;
> -	bulkreq.ocount = &count;
> -
> -	while ((sts = xfsctl(fsdir, fsfd, XFS_IOC_FSBULKSTAT, &bulkreq)) == 0) {
> +	while ((sts = xfrog_bulkstat(&fsxfd, &last, NBSTAT, buf,
> +				&count)) == 0) {
>  		if (count == 0)
>  			break;
>  		for (i = 0; i < count; i++)
>  			quot_bulkstat_add(&buf[i], flags);
>  	}
> -	if (sts < 0)
> -		perror("XFS_IOC_FSBULKSTAT"),
> +	if (sts < 0) {
> +		errno = sts;
> +		perror("XFS_IOC_FSBULKSTAT");
> +	}
>  	free(buf);
> -	close(fsfd);
> +	xfd_close(&fsxfd);
>  }
>  
>  static int
> diff --git a/scrub/inodes.c b/scrub/inodes.c
> index 700e5200..413037d8 100644
> --- a/scrub/inodes.c
> +++ b/scrub/inodes.c
> @@ -17,6 +17,7 @@
>  #include "xfs_scrub.h"
>  #include "common.h"
>  #include "inodes.h"
> +#include "xfrog.h"
>  
>  /*
>   * Iterate a range of inodes.
> @@ -50,17 +51,10 @@ xfs_iterate_inodes_range_check(
>  	struct xfs_inogrp	*inogrp,
>  	struct xfs_bstat	*bstat)
>  {
> -	struct xfs_fsop_bulkreq	onereq = {NULL};
>  	struct xfs_bstat	*bs;
> -	__u64			oneino;
> -	__s32			onelen = 0;
>  	int			i;
>  	int			error;
>  
> -	onereq.lastip  = &oneino;
> -	onereq.icount  = 1;
> -	onereq.ocount  = &onelen;
> -
>  	for (i = 0, bs = bstat; i < XFS_INODES_PER_CHUNK; i++) {
>  		if (!(inogrp->xi_allocmask & (1ULL << i)))
>  			continue;
> @@ -70,10 +64,8 @@ xfs_iterate_inodes_range_check(
>  		}
>  
>  		/* Load the one inode. */
> -		oneino = inogrp->xi_startino + i;
> -		onereq.ubuffer = bs;
> -		error = ioctl(ctx->mnt.fd, XFS_IOC_FSBULKSTAT_SINGLE,
> -				&onereq);
> +		error = xfrog_bulkstat_single(&ctx->mnt,
> +				inogrp->xi_startino + i, bs);
>  		if (error || bs->bs_ino != inogrp->xi_startino + i) {
>  			memset(bs, 0, sizeof(struct xfs_bstat));
>  			bs->bs_ino = inogrp->xi_startino + i;
> @@ -99,16 +91,14 @@ xfs_iterate_inodes_range(
>  	void			*arg)
>  {
>  	struct xfs_fsop_bulkreq	igrpreq = {NULL};
> -	struct xfs_fsop_bulkreq	bulkreq = {NULL};
>  	struct xfs_handle	handle;
>  	struct xfs_inogrp	inogrp;
>  	struct xfs_bstat	bstat[XFS_INODES_PER_CHUNK];
>  	char			idescr[DESCR_BUFSZ];
> -	char			buf[DESCR_BUFSZ];
>  	struct xfs_bstat	*bs;
>  	__u64			igrp_ino;
> -	__u64			ino;
> -	__s32			bulklen = 0;
> +	uint64_t		ino;
> +	uint32_t		bulklen = 0;
>  	__s32			igrplen = 0;
>  	bool			moveon = true;
>  	int			i;
> @@ -117,10 +107,6 @@ xfs_iterate_inodes_range(
>  
>  
>  	memset(bstat, 0, XFS_INODES_PER_CHUNK * sizeof(struct xfs_bstat));
> -	bulkreq.lastip  = &ino;
> -	bulkreq.icount  = XFS_INODES_PER_CHUNK;
> -	bulkreq.ubuffer = &bstat;
> -	bulkreq.ocount  = &bulklen;
>  
>  	igrpreq.lastip  = &igrp_ino;
>  	igrpreq.icount  = 1;
> @@ -138,17 +124,17 @@ xfs_iterate_inodes_range(
>  	while (!error && igrplen) {
>  		/* Load the inodes. */
>  		ino = inogrp.xi_startino - 1;
> -		bulkreq.icount = inogrp.xi_alloccount;
> +
>  		/*
>  		 * We can have totally empty inode chunks on filesystems where
>  		 * there are more than 64 inodes per block.  Skip these.
>  		 */
>  		if (inogrp.xi_alloccount == 0)
>  			goto igrp_retry;
> -		error = ioctl(ctx->mnt.fd, XFS_IOC_FSBULKSTAT, &bulkreq);
> +		error = xfrog_bulkstat(&ctx->mnt, &ino, inogrp.xi_alloccount,
> +				bstat, &bulklen);
>  		if (error)
> -			str_info(ctx, descr, "%s", strerror_r(errno,
> -						buf, DESCR_BUFSZ));
> +			str_liberror(ctx, error, descr);

This converts an informational message to a runtime error, which causes
xfstests regression failures.  NAK.

--D

>  
>  		xfs_iterate_inodes_range_check(ctx, &inogrp, bstat);
>  
> 

^ permalink raw reply	[flat|nested] 31+ messages in thread

* Re: [PATCH 4/9] libfrog: introduce xfs_fd to wrap an fd to a file on an xfs filesystem
  2019-08-30  4:20 ` [PATCH 4/9] libfrog: introduce xfs_fd to wrap an fd to a file on an xfs filesystem Darrick J. Wong
@ 2019-08-30 23:29   ` Allison Collins
  2019-08-30 23:31     ` Darrick J. Wong
  2019-09-03 22:53   ` Dave Chinner
  1 sibling, 1 reply; 31+ messages in thread
From: Allison Collins @ 2019-08-30 23:29 UTC (permalink / raw)
  To: Darrick J. Wong, sandeen; +Cc: linux-xfs

On 8/29/19 9:20 PM, Darrick J. Wong wrote:
> From: Darrick J. Wong <darrick.wong@oracle.com>
> 
> Introduce a new "xfs_fd" context structure where we can store a file
> descriptor and all the runtime fs context (geometry, which ioctls work,
> etc.) that goes with it.  We're going to create wrappers for the
> bulkstat and inumbers ioctls in subsequent patches; and when we
> introduce the v5 bulkstat/inumbers ioctls we'll need all that context to
> downgrade gracefully on old kernels.  Start the transition by adopting
> xfs_fd natively in scrub.
> 
> Signed-off-by: Darrick J. Wong <darrick.wong@oracle.com>
> ---
>   include/xfrog.h    |   20 ++++++++++++++++++++
>   libfrog/fsgeom.c   |   32 ++++++++++++++++++++++++++++++++
>   scrub/fscounters.c |   22 ++++++++++++----------
>   scrub/inodes.c     |   10 +++++-----
>   scrub/phase1.c     |   39 +++++++++++++++++++--------------------
>   scrub/phase2.c     |    2 +-
>   scrub/phase3.c     |    4 ++--
>   scrub/phase4.c     |    8 ++++----
>   scrub/phase5.c     |    2 +-
>   scrub/phase6.c     |    6 +++---
>   scrub/phase7.c     |    2 +-
>   scrub/repair.c     |    4 ++--
>   scrub/scrub.c      |   12 ++++++------
>   scrub/spacemap.c   |   12 ++++++------
>   scrub/vfs.c        |    2 +-
>   scrub/xfs_scrub.h  |    7 ++++---
>   16 files changed, 119 insertions(+), 65 deletions(-)
> 
> 
> diff --git a/include/xfrog.h b/include/xfrog.h
> index f3541193..766ee5d5 100644
> --- a/include/xfrog.h
> +++ b/include/xfrog.h
> @@ -19,4 +19,24 @@
>   struct xfs_fsop_geom;
>   int xfrog_geometry(int fd, struct xfs_fsop_geom *fsgeo);
>   
> +/*
> + * Structure for recording whatever observations we want about the level of
> + * xfs runtime support for this fd.  Right now we only store the fd and fs
> + * geometry.
> + */
> +struct xfs_fd {
> +	/* ioctl file descriptor */
> +	int			fd;
> +
> +	/* filesystem geometry */
> +	struct xfs_fsop_geom	fsgeom;
> +};
> +
> +/* Static initializers */
> +#define XFS_FD_INIT(_fd)	{ .fd = (_fd), }
> +#define XFS_FD_INIT_EMPTY	XFS_FD_INIT(-1)
> +
> +int xfd_prepare_geometry(struct xfs_fd *xfd);
> +int xfd_close(struct xfs_fd *xfd);
> +
>   #endif	/* __XFROG_H__ */
> diff --git a/libfrog/fsgeom.c b/libfrog/fsgeom.c
> index 69d24774..694ccbd0 100644
> --- a/libfrog/fsgeom.c
> +++ b/libfrog/fsgeom.c
> @@ -93,3 +93,35 @@ xfrog_geometry(
>   
>   	return errno;
>   }
> +
> +/*
> + * Prepare xfs_fd structure for future ioctl operations by computing the xfs
> + * geometry for @xfd->fd.  Returns zero or a positive error code.
> + */
> +int
> +xfd_prepare_geometry(
> +	struct xfs_fd		*xfd)
> +{
> +	return xfrog_geometry(xfd->fd, &xfd->fsgeom);
> +}

Just a nit:  This little wrapper seems to only be used once and only has 
one line.  Unless there's plans to expand it later, it seems like it's 
not super necessary.

The rest looks ok, the new plumbing looks pretty straight forward.
Reviewed-by: Allison Collins <allison.henderson@oracle.com>

> +
> +/*
> + * Release any resources associated with this xfs_fd structure.  Returns zero
> + * or a positive error code.
> + */
> +int
> +xfd_close(
> +	struct xfs_fd		*xfd)
> +{
> +	int			ret = 0;
> +
> +	if (xfd->fd < 0)
> +		return 0;
> +
> +	ret = close(xfd->fd);
> +	xfd->fd = -1;
> +	if (ret < 0)
> +		return errno;
> +
> +	return 0;
> +}
> diff --git a/scrub/fscounters.c b/scrub/fscounters.c
> index 9e93e2a6..f18d0e19 100644
> --- a/scrub/fscounters.c
> +++ b/scrub/fscounters.c
> @@ -57,10 +57,10 @@ xfs_count_inodes_range(
>   	igrpreq.ocount  = &igrplen;
>   
>   	igrp_ino = first_ino;
> -	error = ioctl(ctx->mnt_fd, XFS_IOC_FSINUMBERS, &igrpreq);
> +	error = ioctl(ctx->mnt.fd, XFS_IOC_FSINUMBERS, &igrpreq);
>   	while (!error && igrplen && inogrp.xi_startino < last_ino) {
>   		nr += inogrp.xi_alloccount;
> -		error = ioctl(ctx->mnt_fd, XFS_IOC_FSINUMBERS, &igrpreq);
> +		error = ioctl(ctx->mnt.fd, XFS_IOC_FSINUMBERS, &igrpreq);
>   	}
>   
>   	if (error) {
> @@ -113,7 +113,7 @@ xfs_count_all_inodes(
>   	int			ret;
>   
>   	ci = calloc(1, sizeof(struct xfs_count_inodes) +
> -			(ctx->geo.agcount * sizeof(uint64_t)));
> +			(ctx->mnt.fsgeom.agcount * sizeof(uint64_t)));
>   	if (!ci)
>   		return false;
>   	ci->moveon = true;
> @@ -125,7 +125,7 @@ xfs_count_all_inodes(
>   		str_info(ctx, ctx->mntpoint, _("Could not create workqueue."));
>   		goto out_free;
>   	}
> -	for (agno = 0; agno < ctx->geo.agcount; agno++) {
> +	for (agno = 0; agno < ctx->mnt.fsgeom.agcount; agno++) {
>   		ret = workqueue_add(&wq, xfs_count_ag_inodes, agno, ci);
>   		if (ret) {
>   			moveon = false;
> @@ -136,7 +136,7 @@ _("Could not queue AG %u icount work."), agno);
>   	}
>   	workqueue_destroy(&wq);
>   
> -	for (agno = 0; agno < ctx->geo.agcount; agno++)
> +	for (agno = 0; agno < ctx->mnt.fsgeom.agcount; agno++)
>   		*count += ci->counters[agno];
>   	moveon = ci->moveon;
>   
> @@ -162,14 +162,14 @@ xfs_scan_estimate_blocks(
>   	int				error;
>   
>   	/* Grab the fstatvfs counters, since it has to report accurately. */
> -	error = fstatvfs(ctx->mnt_fd, &sfs);
> +	error = fstatvfs(ctx->mnt.fd, &sfs);
>   	if (error) {
>   		str_errno(ctx, ctx->mntpoint);
>   		return false;
>   	}
>   
>   	/* Fetch the filesystem counters. */
> -	error = ioctl(ctx->mnt_fd, XFS_IOC_FSCOUNTS, &fc);
> +	error = ioctl(ctx->mnt.fd, XFS_IOC_FSCOUNTS, &fc);
>   	if (error) {
>   		str_errno(ctx, ctx->mntpoint);
>   		return false;
> @@ -179,14 +179,16 @@ xfs_scan_estimate_blocks(
>   	 * XFS reserves some blocks to prevent hard ENOSPC, so add those
>   	 * blocks back to the free data counts.
>   	 */
> -	error = ioctl(ctx->mnt_fd, XFS_IOC_GET_RESBLKS, &rb);
> +	error = ioctl(ctx->mnt.fd, XFS_IOC_GET_RESBLKS, &rb);
>   	if (error)
>   		str_errno(ctx, ctx->mntpoint);
>   	sfs.f_bfree += rb.resblks_avail;
>   
> -	*d_blocks = sfs.f_blocks + (ctx->geo.logstart ? ctx->geo.logblocks : 0);
> +	*d_blocks = sfs.f_blocks;
> +	if (ctx->mnt.fsgeom.logstart > 0)
> +		*d_blocks += ctx->mnt.fsgeom.logblocks;
>   	*d_bfree = sfs.f_bfree;
> -	*r_blocks = ctx->geo.rtblocks;
> +	*r_blocks = ctx->mnt.fsgeom.rtblocks;
>   	*r_bfree = fc.freertx;
>   	*f_files = sfs.f_files;
>   	*f_free = sfs.f_ffree;
> diff --git a/scrub/inodes.c b/scrub/inodes.c
> index 442a5978..08f3d847 100644
> --- a/scrub/inodes.c
> +++ b/scrub/inodes.c
> @@ -72,7 +72,7 @@ xfs_iterate_inodes_range_check(
>   		/* Load the one inode. */
>   		oneino = inogrp->xi_startino + i;
>   		onereq.ubuffer = bs;
> -		error = ioctl(ctx->mnt_fd, XFS_IOC_FSBULKSTAT_SINGLE,
> +		error = ioctl(ctx->mnt.fd, XFS_IOC_FSBULKSTAT_SINGLE,
>   				&onereq);
>   		if (error || bs->bs_ino != inogrp->xi_startino + i) {
>   			memset(bs, 0, sizeof(struct xfs_bstat));
> @@ -134,7 +134,7 @@ xfs_iterate_inodes_range(
>   
>   	/* Find the inode chunk & alloc mask */
>   	igrp_ino = first_ino;
> -	error = ioctl(ctx->mnt_fd, XFS_IOC_FSINUMBERS, &igrpreq);
> +	error = ioctl(ctx->mnt.fd, XFS_IOC_FSINUMBERS, &igrpreq);
>   	while (!error && igrplen) {
>   		/* Load the inodes. */
>   		ino = inogrp.xi_startino - 1;
> @@ -145,7 +145,7 @@ xfs_iterate_inodes_range(
>   		 */
>   		if (inogrp.xi_alloccount == 0)
>   			goto igrp_retry;
> -		error = ioctl(ctx->mnt_fd, XFS_IOC_FSBULKSTAT, &bulkreq);
> +		error = ioctl(ctx->mnt.fd, XFS_IOC_FSBULKSTAT, &bulkreq);
>   		if (error)
>   			str_info(ctx, descr, "%s", strerror_r(errno,
>   						buf, DESCR_BUFSZ));
> @@ -190,7 +190,7 @@ _("Changed too many times during scan; giving up."));
>   
>   		stale_count = 0;
>   igrp_retry:
> -		error = ioctl(ctx->mnt_fd, XFS_IOC_FSINUMBERS, &igrpreq);
> +		error = ioctl(ctx->mnt.fd, XFS_IOC_FSINUMBERS, &igrpreq);
>   	}
>   
>   err:
> @@ -260,7 +260,7 @@ xfs_scan_all_inodes(
>   		return false;
>   	}
>   
> -	for (agno = 0; agno < ctx->geo.agcount; agno++) {
> +	for (agno = 0; agno < ctx->mnt.fsgeom.agcount; agno++) {
>   		ret = workqueue_add(&wq, xfs_scan_ag_inodes, agno, &si);
>   		if (ret) {
>   			si.moveon = false;
> diff --git a/scrub/phase1.c b/scrub/phase1.c
> index bdd23d26..6d8293b2 100644
> --- a/scrub/phase1.c
> +++ b/scrub/phase1.c
> @@ -39,7 +39,7 @@ xfs_shutdown_fs(
>   
>   	flag = XFS_FSOP_GOING_FLAGS_LOGFLUSH;
>   	str_info(ctx, ctx->mntpoint, _("Shutting down filesystem!"));
> -	if (ioctl(ctx->mnt_fd, XFS_IOC_GOINGDOWN, &flag))
> +	if (ioctl(ctx->mnt.fd, XFS_IOC_GOINGDOWN, &flag))
>   		str_errno(ctx, ctx->mntpoint);
>   }
>   
> @@ -60,11 +60,9 @@ xfs_cleanup_fs(
>   	if (ctx->datadev)
>   		disk_close(ctx->datadev);
>   	fshandle_destroy();
> -	if (ctx->mnt_fd >= 0) {
> -		error = close(ctx->mnt_fd);
> -		if (error)
> -			str_errno(ctx, _("closing mountpoint fd"));
> -	}
> +	error = xfd_close(&ctx->mnt);
> +	if (error)
> +		str_liberror(ctx, error, _("closing mountpoint fd"));
>   	fs_table_destroy();
>   
>   	return true;
> @@ -86,8 +84,8 @@ xfs_setup_fs(
>   	 * CAP_SYS_ADMIN, which we probably need to do anything fancy
>   	 * with the (XFS driver) kernel.
>   	 */
> -	ctx->mnt_fd = open(ctx->mntpoint, O_RDONLY | O_NOATIME | O_DIRECTORY);
> -	if (ctx->mnt_fd < 0) {
> +	ctx->mnt.fd = open(ctx->mntpoint, O_RDONLY | O_NOATIME | O_DIRECTORY);
> +	if (ctx->mnt.fd < 0) {
>   		if (errno == EPERM)
>   			str_info(ctx, ctx->mntpoint,
>   _("Must be root to run scrub."));
> @@ -96,23 +94,23 @@ _("Must be root to run scrub."));
>   		return false;
>   	}
>   
> -	error = fstat(ctx->mnt_fd, &ctx->mnt_sb);
> +	error = fstat(ctx->mnt.fd, &ctx->mnt_sb);
>   	if (error) {
>   		str_errno(ctx, ctx->mntpoint);
>   		return false;
>   	}
> -	error = fstatvfs(ctx->mnt_fd, &ctx->mnt_sv);
> +	error = fstatvfs(ctx->mnt.fd, &ctx->mnt_sv);
>   	if (error) {
>   		str_errno(ctx, ctx->mntpoint);
>   		return false;
>   	}
> -	error = fstatfs(ctx->mnt_fd, &ctx->mnt_sf);
> +	error = fstatfs(ctx->mnt.fd, &ctx->mnt_sf);
>   	if (error) {
>   		str_errno(ctx, ctx->mntpoint);
>   		return false;
>   	}
>   
> -	if (!platform_test_xfs_fd(ctx->mnt_fd)) {
> +	if (!platform_test_xfs_fd(ctx->mnt.fd)) {
>   		str_info(ctx, ctx->mntpoint,
>   _("Does not appear to be an XFS filesystem!"));
>   		return false;
> @@ -123,27 +121,28 @@ _("Does not appear to be an XFS filesystem!"));
>   	 * This seems to reduce the incidence of stale file handle
>   	 * errors when we open things by handle.
>   	 */
> -	error = syncfs(ctx->mnt_fd);
> +	error = syncfs(ctx->mnt.fd);
>   	if (error) {
>   		str_errno(ctx, ctx->mntpoint);
>   		return false;
>   	}
>   
>   	/* Retrieve XFS geometry. */
> -	error = xfrog_geometry(ctx->mnt_fd, &ctx->geo);
> +	error = xfd_prepare_geometry(&ctx->mnt);
>   	if (error) {
>   		str_liberror(ctx, error, _("Retrieving XFS geometry"));
>   		return false;
>   	}
>   
> -	if (!xfs_action_lists_alloc(ctx->geo.agcount, &ctx->action_lists)) {
> +	if (!xfs_action_lists_alloc(ctx->mnt.fsgeom.agcount,
> +				&ctx->action_lists)) {
>   		str_error(ctx, ctx->mntpoint, _("Not enough memory."));
>   		return false;
>   	}
>   
> -	ctx->agblklog = log2_roundup(ctx->geo.agblocks);
> -	ctx->blocklog = highbit32(ctx->geo.blocksize);
> -	ctx->inodelog = highbit32(ctx->geo.inodesize);
> +	ctx->agblklog = log2_roundup(ctx->mnt.fsgeom.agblocks);
> +	ctx->blocklog = highbit32(ctx->mnt.fsgeom.blocksize);
> +	ctx->inodelog = highbit32(ctx->mnt.fsgeom.inodesize);
>   	ctx->inopblog = ctx->blocklog - ctx->inodelog;
>   
>   	error = path_to_fshandle(ctx->mntpoint, &ctx->fshandle,
> @@ -171,12 +170,12 @@ _("Kernel metadata repair facility is not available.  Use -n to scrub."));
>   	}
>   
>   	/* Did we find the log and rt devices, if they're present? */
> -	if (ctx->geo.logstart == 0 && ctx->fsinfo.fs_log == NULL) {
> +	if (ctx->mnt.fsgeom.logstart == 0 && ctx->fsinfo.fs_log == NULL) {
>   		str_info(ctx, ctx->mntpoint,
>   _("Unable to find log device path."));
>   		return false;
>   	}
> -	if (ctx->geo.rtblocks && ctx->fsinfo.fs_rt == NULL) {
> +	if (ctx->mnt.fsgeom.rtblocks && ctx->fsinfo.fs_rt == NULL) {
>   		str_info(ctx, ctx->mntpoint,
>   _("Unable to find realtime device path."));
>   		return false;
> diff --git a/scrub/phase2.c b/scrub/phase2.c
> index 653f666c..a80da7fd 100644
> --- a/scrub/phase2.c
> +++ b/scrub/phase2.c
> @@ -141,7 +141,7 @@ xfs_scan_metadata(
>   	if (!moveon)
>   		goto out;
>   
> -	for (agno = 0; moveon && agno < ctx->geo.agcount; agno++) {
> +	for (agno = 0; moveon && agno < ctx->mnt.fsgeom.agcount; agno++) {
>   		ret = workqueue_add(&wq, xfs_scan_ag_metadata, agno, &moveon);
>   		if (ret) {
>   			moveon = false;
> diff --git a/scrub/phase3.c b/scrub/phase3.c
> index 4963d675..a42d8213 100644
> --- a/scrub/phase3.c
> +++ b/scrub/phase3.c
> @@ -33,7 +33,7 @@ xfs_scrub_fd(
>   	struct xfs_bstat	*bs,
>   	struct xfs_action_list	*alist)
>   {
> -	return fn(ctx, bs->bs_ino, bs->bs_gen, ctx->mnt_fd, alist);
> +	return fn(ctx, bs->bs_ino, bs->bs_gen, ctx->mnt.fd, alist);
>   }
>   
>   struct scrub_inode_ctx {
> @@ -115,7 +115,7 @@ xfs_scrub_inode(
>   	if (S_ISLNK(bstat->bs_mode)) {
>   		/* Check symlink contents. */
>   		moveon = xfs_scrub_symlink(ctx, bstat->bs_ino,
> -				bstat->bs_gen, ctx->mnt_fd, &alist);
> +				bstat->bs_gen, ctx->mnt.fd, &alist);
>   	} else if (S_ISDIR(bstat->bs_mode)) {
>   		/* Check the directory entries. */
>   		moveon = xfs_scrub_fd(ctx, xfs_scrub_dir, bstat, &alist);
> diff --git a/scrub/phase4.c b/scrub/phase4.c
> index 79248326..49f00723 100644
> --- a/scrub/phase4.c
> +++ b/scrub/phase4.c
> @@ -40,7 +40,7 @@ xfs_repair_ag(
>   
>   	/* Repair anything broken until we fail to make progress. */
>   	do {
> -		moveon = xfs_action_list_process(ctx, ctx->mnt_fd, alist, flags);
> +		moveon = xfs_action_list_process(ctx, ctx->mnt.fd, alist, flags);
>   		if (!moveon) {
>   			*pmoveon = false;
>   			return;
> @@ -56,7 +56,7 @@ xfs_repair_ag(
>   
>   	/* Try once more, but this time complain if we can't fix things. */
>   	flags |= ALP_COMPLAIN_IF_UNFIXED;
> -	moveon = xfs_action_list_process(ctx, ctx->mnt_fd, alist, flags);
> +	moveon = xfs_action_list_process(ctx, ctx->mnt.fd, alist, flags);
>   	if (!moveon)
>   		*pmoveon = false;
>   }
> @@ -77,7 +77,7 @@ xfs_process_action_items(
>   		str_error(ctx, ctx->mntpoint, _("Could not create workqueue."));
>   		return false;
>   	}
> -	for (agno = 0; agno < ctx->geo.agcount; agno++) {
> +	for (agno = 0; agno < ctx->mnt.fsgeom.agcount; agno++) {
>   		if (xfs_action_list_length(&ctx->action_lists[agno]) > 0) {
>   			ret = workqueue_add(&wq, xfs_repair_ag, agno, &moveon);
>   			if (ret) {
> @@ -121,7 +121,7 @@ xfs_estimate_repair_work(
>   	xfs_agnumber_t		agno;
>   	size_t			need_fixing = 0;
>   
> -	for (agno = 0; agno < ctx->geo.agcount; agno++)
> +	for (agno = 0; agno < ctx->mnt.fsgeom.agcount; agno++)
>   		need_fixing += xfs_action_list_length(&ctx->action_lists[agno]);
>   	need_fixing++;
>   	*items = need_fixing;
> diff --git a/scrub/phase5.c b/scrub/phase5.c
> index 1743119d..748885d4 100644
> --- a/scrub/phase5.c
> +++ b/scrub/phase5.c
> @@ -306,7 +306,7 @@ xfs_scrub_fs_label(
>   		return false;
>   
>   	/* Retrieve label; quietly bail if we don't support that. */
> -	error = ioctl(ctx->mnt_fd, FS_IOC_GETFSLABEL, &label);
> +	error = ioctl(ctx->mnt.fd, FS_IOC_GETFSLABEL, &label);
>   	if (error) {
>   		if (errno != EOPNOTSUPP && errno != ENOTTY) {
>   			moveon = false;
> diff --git a/scrub/phase6.c b/scrub/phase6.c
> index 66e6451c..e5a0b3c1 100644
> --- a/scrub/phase6.c
> +++ b/scrub/phase6.c
> @@ -468,7 +468,7 @@ xfs_scan_blocks(
>   	}
>   
>   	vs.rvp_data = read_verify_pool_init(ctx, ctx->datadev,
> -			ctx->geo.blocksize, xfs_check_rmap_ioerr,
> +			ctx->mnt.fsgeom.blocksize, xfs_check_rmap_ioerr,
>   			scrub_nproc(ctx));
>   	if (!vs.rvp_data) {
>   		str_info(ctx, ctx->mntpoint,
> @@ -477,7 +477,7 @@ _("Could not create data device media verifier."));
>   	}
>   	if (ctx->logdev) {
>   		vs.rvp_log = read_verify_pool_init(ctx, ctx->logdev,
> -				ctx->geo.blocksize, xfs_check_rmap_ioerr,
> +				ctx->mnt.fsgeom.blocksize, xfs_check_rmap_ioerr,
>   				scrub_nproc(ctx));
>   		if (!vs.rvp_log) {
>   			str_info(ctx, ctx->mntpoint,
> @@ -487,7 +487,7 @@ _("Could not create data device media verifier."));
>   	}
>   	if (ctx->rtdev) {
>   		vs.rvp_realtime = read_verify_pool_init(ctx, ctx->rtdev,
> -				ctx->geo.blocksize, xfs_check_rmap_ioerr,
> +				ctx->mnt.fsgeom.blocksize, xfs_check_rmap_ioerr,
>   				scrub_nproc(ctx));
>   		if (!vs.rvp_realtime) {
>   			str_info(ctx, ctx->mntpoint,
> diff --git a/scrub/phase7.c b/scrub/phase7.c
> index 0c3202e4..13959ca8 100644
> --- a/scrub/phase7.c
> +++ b/scrub/phase7.c
> @@ -111,7 +111,7 @@ xfs_scan_summary(
>   	int			error;
>   
>   	/* Flush everything out to disk before we start counting. */
> -	error = syncfs(ctx->mnt_fd);
> +	error = syncfs(ctx->mnt.fd);
>   	if (error) {
>   		str_errno(ctx, ctx->mntpoint);
>   		return false;
> diff --git a/scrub/repair.c b/scrub/repair.c
> index 4ed3c09a..45450d8c 100644
> --- a/scrub/repair.c
> +++ b/scrub/repair.c
> @@ -262,7 +262,7 @@ xfs_action_list_defer(
>   	xfs_agnumber_t			agno,
>   	struct xfs_action_list		*alist)
>   {
> -	ASSERT(agno < ctx->geo.agcount);
> +	ASSERT(agno < ctx->mnt.fsgeom.agcount);
>   
>   	xfs_action_list_splice(&ctx->action_lists[agno], alist);
>   }
> @@ -276,7 +276,7 @@ xfs_action_list_process_or_defer(
>   {
>   	bool				moveon;
>   
> -	moveon = xfs_action_list_process(ctx, ctx->mnt_fd, alist,
> +	moveon = xfs_action_list_process(ctx, ctx->mnt.fd, alist,
>   			ALP_REPAIR_ONLY | ALP_NOPROGRESS);
>   	if (!moveon)
>   		return moveon;
> diff --git a/scrub/scrub.c b/scrub/scrub.c
> index 0f0c9639..136ed529 100644
> --- a/scrub/scrub.c
> +++ b/scrub/scrub.c
> @@ -363,7 +363,7 @@ xfs_scrub_metadata(
>   		background_sleep();
>   
>   		/* Check the item. */
> -		fix = xfs_check_metadata(ctx, ctx->mnt_fd, &meta, false);
> +		fix = xfs_check_metadata(ctx, ctx->mnt.fd, &meta, false);
>   		progress_add(1);
>   		switch (fix) {
>   		case CHECK_ABORT:
> @@ -399,7 +399,7 @@ xfs_scrub_primary_super(
>   	enum check_outcome		fix;
>   
>   	/* Check the item. */
> -	fix = xfs_check_metadata(ctx, ctx->mnt_fd, &meta, false);
> +	fix = xfs_check_metadata(ctx, ctx->mnt.fd, &meta, false);
>   	switch (fix) {
>   	case CHECK_ABORT:
>   		return false;
> @@ -460,7 +460,7 @@ xfs_scrub_estimate_ag_work(
>   		switch (sc->type) {
>   		case ST_AGHEADER:
>   		case ST_PERAG:
> -			estimate += ctx->geo.agcount;
> +			estimate += ctx->mnt.fsgeom.agcount;
>   			break;
>   		case ST_FS:
>   			estimate++;
> @@ -605,9 +605,9 @@ __xfs_scrub_test(
>   	if (debug_tweak_on("XFS_SCRUB_NO_KERNEL"))
>   		return false;
>   	if (debug_tweak_on("XFS_SCRUB_FORCE_REPAIR") && !injected) {
> -		inject.fd = ctx->mnt_fd;
> +		inject.fd = ctx->mnt.fd;
>   		inject.errtag = XFS_ERRTAG_FORCE_SCRUB_REPAIR;
> -		error = ioctl(ctx->mnt_fd, XFS_IOC_ERROR_INJECTION, &inject);
> +		error = ioctl(ctx->mnt.fd, XFS_IOC_ERROR_INJECTION, &inject);
>   		if (error == 0)
>   			injected = true;
>   	}
> @@ -615,7 +615,7 @@ __xfs_scrub_test(
>   	meta.sm_type = type;
>   	if (repair)
>   		meta.sm_flags |= XFS_SCRUB_IFLAG_REPAIR;
> -	error = ioctl(ctx->mnt_fd, XFS_IOC_SCRUB_METADATA, &meta);
> +	error = ioctl(ctx->mnt.fd, XFS_IOC_SCRUB_METADATA, &meta);
>   	if (!error)
>   		return true;
>   	switch (errno) {
> diff --git a/scrub/spacemap.c b/scrub/spacemap.c
> index d547a041..c3621a3a 100644
> --- a/scrub/spacemap.c
> +++ b/scrub/spacemap.c
> @@ -56,7 +56,7 @@ xfs_iterate_fsmap(
>   	memcpy(head->fmh_keys, keys, sizeof(struct fsmap) * 2);
>   	head->fmh_count = FSMAP_NR;
>   
> -	while ((error = ioctl(ctx->mnt_fd, FS_IOC_GETFSMAP, head)) == 0) {
> +	while ((error = ioctl(ctx->mnt.fd, FS_IOC_GETFSMAP, head)) == 0) {
>   		for (i = 0, p = head->fmh_recs;
>   		     i < head->fmh_entries;
>   		     i++, p++) {
> @@ -107,8 +107,8 @@ xfs_scan_ag_blocks(
>   	off64_t			bperag;
>   	bool			moveon;
>   
> -	bperag = (off64_t)ctx->geo.agblocks *
> -		 (off64_t)ctx->geo.blocksize;
> +	bperag = (off64_t)ctx->mnt.fsgeom.agblocks *
> +		 (off64_t)ctx->mnt.fsgeom.blocksize;
>   
>   	snprintf(descr, DESCR_BUFSZ, _("dev %d:%d AG %u fsmap"),
>   				major(ctx->fsinfo.fs_datadev),
> @@ -205,7 +205,7 @@ xfs_scan_all_spacemaps(
>   	}
>   	if (ctx->fsinfo.fs_rt) {
>   		ret = workqueue_add(&wq, xfs_scan_rt_blocks,
> -				ctx->geo.agcount + 1, &sbx);
> +				ctx->mnt.fsgeom.agcount + 1, &sbx);
>   		if (ret) {
>   			sbx.moveon = false;
>   			str_info(ctx, ctx->mntpoint,
> @@ -215,7 +215,7 @@ _("Could not queue rtdev fsmap work."));
>   	}
>   	if (ctx->fsinfo.fs_log) {
>   		ret = workqueue_add(&wq, xfs_scan_log_blocks,
> -				ctx->geo.agcount + 2, &sbx);
> +				ctx->mnt.fsgeom.agcount + 2, &sbx);
>   		if (ret) {
>   			sbx.moveon = false;
>   			str_info(ctx, ctx->mntpoint,
> @@ -223,7 +223,7 @@ _("Could not queue logdev fsmap work."));
>   			goto out;
>   		}
>   	}
> -	for (agno = 0; agno < ctx->geo.agcount; agno++) {
> +	for (agno = 0; agno < ctx->mnt.fsgeom.agcount; agno++) {
>   		ret = workqueue_add(&wq, xfs_scan_ag_blocks, agno, &sbx);
>   		if (ret) {
>   			sbx.moveon = false;
> diff --git a/scrub/vfs.c b/scrub/vfs.c
> index 8bcc4e79..7b0b5bcd 100644
> --- a/scrub/vfs.c
> +++ b/scrub/vfs.c
> @@ -232,7 +232,7 @@ fstrim(
>   	int			error;
>   
>   	range.len = ULLONG_MAX;
> -	error = ioctl(ctx->mnt_fd, FITRIM, &range);
> +	error = ioctl(ctx->mnt.fd, FITRIM, &range);
>   	if (error && errno != EOPNOTSUPP && errno != ENOTTY)
>   		perror(_("fstrim"));
>   }
> diff --git a/scrub/xfs_scrub.h b/scrub/xfs_scrub.h
> index a459e4b5..28eae6fe 100644
> --- a/scrub/xfs_scrub.h
> +++ b/scrub/xfs_scrub.h
> @@ -6,6 +6,8 @@
>   #ifndef XFS_SCRUB_XFS_SCRUB_H_
>   #define XFS_SCRUB_XFS_SCRUB_H_
>   
> +#include <xfrog.h>
> +
>   extern char *progname;
>   
>   #define _PATH_PROC_MOUNTS	"/proc/mounts"
> @@ -53,14 +55,13 @@ struct scrub_ctx {
>   	/* How does the user want us to react to errors? */
>   	enum error_action	error_action;
>   
> -	/* fd to filesystem mount point */
> -	int			mnt_fd;
> +	/* xfrog context for the mount point */
> +	struct xfs_fd		mnt;
>   
>   	/* Number of threads for metadata scrubbing */
>   	unsigned int		nr_io_threads;
>   
>   	/* XFS specific geometry */
> -	struct xfs_fsop_geom	geo;
>   	struct fs_path		fsinfo;
>   	unsigned int		agblklog;
>   	unsigned int		blocklog;
> 

^ permalink raw reply	[flat|nested] 31+ messages in thread

* Re: [PATCH 4/9] libfrog: introduce xfs_fd to wrap an fd to a file on an xfs filesystem
  2019-08-30 23:29   ` Allison Collins
@ 2019-08-30 23:31     ` Darrick J. Wong
  0 siblings, 0 replies; 31+ messages in thread
From: Darrick J. Wong @ 2019-08-30 23:31 UTC (permalink / raw)
  To: Allison Collins; +Cc: sandeen, linux-xfs

On Fri, Aug 30, 2019 at 04:29:16PM -0700, Allison Collins wrote:
> On 8/29/19 9:20 PM, Darrick J. Wong wrote:
> > From: Darrick J. Wong <darrick.wong@oracle.com>
> > 
> > Introduce a new "xfs_fd" context structure where we can store a file
> > descriptor and all the runtime fs context (geometry, which ioctls work,
> > etc.) that goes with it.  We're going to create wrappers for the
> > bulkstat and inumbers ioctls in subsequent patches; and when we
> > introduce the v5 bulkstat/inumbers ioctls we'll need all that context to
> > downgrade gracefully on old kernels.  Start the transition by adopting
> > xfs_fd natively in scrub.
> > 
> > Signed-off-by: Darrick J. Wong <darrick.wong@oracle.com>
> > ---
> >   include/xfrog.h    |   20 ++++++++++++++++++++
> >   libfrog/fsgeom.c   |   32 ++++++++++++++++++++++++++++++++
> >   scrub/fscounters.c |   22 ++++++++++++----------
> >   scrub/inodes.c     |   10 +++++-----
> >   scrub/phase1.c     |   39 +++++++++++++++++++--------------------
> >   scrub/phase2.c     |    2 +-
> >   scrub/phase3.c     |    4 ++--
> >   scrub/phase4.c     |    8 ++++----
> >   scrub/phase5.c     |    2 +-
> >   scrub/phase6.c     |    6 +++---
> >   scrub/phase7.c     |    2 +-
> >   scrub/repair.c     |    4 ++--
> >   scrub/scrub.c      |   12 ++++++------
> >   scrub/spacemap.c   |   12 ++++++------
> >   scrub/vfs.c        |    2 +-
> >   scrub/xfs_scrub.h  |    7 ++++---
> >   16 files changed, 119 insertions(+), 65 deletions(-)
> > 
> > 
> > diff --git a/include/xfrog.h b/include/xfrog.h
> > index f3541193..766ee5d5 100644
> > --- a/include/xfrog.h
> > +++ b/include/xfrog.h
> > @@ -19,4 +19,24 @@
> >   struct xfs_fsop_geom;
> >   int xfrog_geometry(int fd, struct xfs_fsop_geom *fsgeo);
> > +/*
> > + * Structure for recording whatever observations we want about the level of
> > + * xfs runtime support for this fd.  Right now we only store the fd and fs
> > + * geometry.
> > + */
> > +struct xfs_fd {
> > +	/* ioctl file descriptor */
> > +	int			fd;
> > +
> > +	/* filesystem geometry */
> > +	struct xfs_fsop_geom	fsgeom;
> > +};
> > +
> > +/* Static initializers */
> > +#define XFS_FD_INIT(_fd)	{ .fd = (_fd), }
> > +#define XFS_FD_INIT_EMPTY	XFS_FD_INIT(-1)
> > +
> > +int xfd_prepare_geometry(struct xfs_fd *xfd);
> > +int xfd_close(struct xfs_fd *xfd);
> > +
> >   #endif	/* __XFROG_H__ */
> > diff --git a/libfrog/fsgeom.c b/libfrog/fsgeom.c
> > index 69d24774..694ccbd0 100644
> > --- a/libfrog/fsgeom.c
> > +++ b/libfrog/fsgeom.c
> > @@ -93,3 +93,35 @@ xfrog_geometry(
> >   	return errno;
> >   }
> > +
> > +/*
> > + * Prepare xfs_fd structure for future ioctl operations by computing the xfs
> > + * geometry for @xfd->fd.  Returns zero or a positive error code.
> > + */
> > +int
> > +xfd_prepare_geometry(
> > +	struct xfs_fd		*xfd)
> > +{
> > +	return xfrog_geometry(xfd->fd, &xfd->fsgeom);
> > +}
> 
> Just a nit:  This little wrapper seems to only be used once and only has one
> line.  Unless there's plans to expand it later, it seems like it's not super
> necessary.

Oh, there's lots of plans to use it later -- a few patches from now we
start adding conversion helpers for open xfs_fds.  Thanks for having a
look at these. :)

--D

> The rest looks ok, the new plumbing looks pretty straight forward.
> Reviewed-by: Allison Collins <allison.henderson@oracle.com>
> 
> > +
> > +/*
> > + * Release any resources associated with this xfs_fd structure.  Returns zero
> > + * or a positive error code.
> > + */
> > +int
> > +xfd_close(
> > +	struct xfs_fd		*xfd)
> > +{
> > +	int			ret = 0;
> > +
> > +	if (xfd->fd < 0)
> > +		return 0;
> > +
> > +	ret = close(xfd->fd);
> > +	xfd->fd = -1;
> > +	if (ret < 0)
> > +		return errno;
> > +
> > +	return 0;
> > +}
> > diff --git a/scrub/fscounters.c b/scrub/fscounters.c
> > index 9e93e2a6..f18d0e19 100644
> > --- a/scrub/fscounters.c
> > +++ b/scrub/fscounters.c
> > @@ -57,10 +57,10 @@ xfs_count_inodes_range(
> >   	igrpreq.ocount  = &igrplen;
> >   	igrp_ino = first_ino;
> > -	error = ioctl(ctx->mnt_fd, XFS_IOC_FSINUMBERS, &igrpreq);
> > +	error = ioctl(ctx->mnt.fd, XFS_IOC_FSINUMBERS, &igrpreq);
> >   	while (!error && igrplen && inogrp.xi_startino < last_ino) {
> >   		nr += inogrp.xi_alloccount;
> > -		error = ioctl(ctx->mnt_fd, XFS_IOC_FSINUMBERS, &igrpreq);
> > +		error = ioctl(ctx->mnt.fd, XFS_IOC_FSINUMBERS, &igrpreq);
> >   	}
> >   	if (error) {
> > @@ -113,7 +113,7 @@ xfs_count_all_inodes(
> >   	int			ret;
> >   	ci = calloc(1, sizeof(struct xfs_count_inodes) +
> > -			(ctx->geo.agcount * sizeof(uint64_t)));
> > +			(ctx->mnt.fsgeom.agcount * sizeof(uint64_t)));
> >   	if (!ci)
> >   		return false;
> >   	ci->moveon = true;
> > @@ -125,7 +125,7 @@ xfs_count_all_inodes(
> >   		str_info(ctx, ctx->mntpoint, _("Could not create workqueue."));
> >   		goto out_free;
> >   	}
> > -	for (agno = 0; agno < ctx->geo.agcount; agno++) {
> > +	for (agno = 0; agno < ctx->mnt.fsgeom.agcount; agno++) {
> >   		ret = workqueue_add(&wq, xfs_count_ag_inodes, agno, ci);
> >   		if (ret) {
> >   			moveon = false;
> > @@ -136,7 +136,7 @@ _("Could not queue AG %u icount work."), agno);
> >   	}
> >   	workqueue_destroy(&wq);
> > -	for (agno = 0; agno < ctx->geo.agcount; agno++)
> > +	for (agno = 0; agno < ctx->mnt.fsgeom.agcount; agno++)
> >   		*count += ci->counters[agno];
> >   	moveon = ci->moveon;
> > @@ -162,14 +162,14 @@ xfs_scan_estimate_blocks(
> >   	int				error;
> >   	/* Grab the fstatvfs counters, since it has to report accurately. */
> > -	error = fstatvfs(ctx->mnt_fd, &sfs);
> > +	error = fstatvfs(ctx->mnt.fd, &sfs);
> >   	if (error) {
> >   		str_errno(ctx, ctx->mntpoint);
> >   		return false;
> >   	}
> >   	/* Fetch the filesystem counters. */
> > -	error = ioctl(ctx->mnt_fd, XFS_IOC_FSCOUNTS, &fc);
> > +	error = ioctl(ctx->mnt.fd, XFS_IOC_FSCOUNTS, &fc);
> >   	if (error) {
> >   		str_errno(ctx, ctx->mntpoint);
> >   		return false;
> > @@ -179,14 +179,16 @@ xfs_scan_estimate_blocks(
> >   	 * XFS reserves some blocks to prevent hard ENOSPC, so add those
> >   	 * blocks back to the free data counts.
> >   	 */
> > -	error = ioctl(ctx->mnt_fd, XFS_IOC_GET_RESBLKS, &rb);
> > +	error = ioctl(ctx->mnt.fd, XFS_IOC_GET_RESBLKS, &rb);
> >   	if (error)
> >   		str_errno(ctx, ctx->mntpoint);
> >   	sfs.f_bfree += rb.resblks_avail;
> > -	*d_blocks = sfs.f_blocks + (ctx->geo.logstart ? ctx->geo.logblocks : 0);
> > +	*d_blocks = sfs.f_blocks;
> > +	if (ctx->mnt.fsgeom.logstart > 0)
> > +		*d_blocks += ctx->mnt.fsgeom.logblocks;
> >   	*d_bfree = sfs.f_bfree;
> > -	*r_blocks = ctx->geo.rtblocks;
> > +	*r_blocks = ctx->mnt.fsgeom.rtblocks;
> >   	*r_bfree = fc.freertx;
> >   	*f_files = sfs.f_files;
> >   	*f_free = sfs.f_ffree;
> > diff --git a/scrub/inodes.c b/scrub/inodes.c
> > index 442a5978..08f3d847 100644
> > --- a/scrub/inodes.c
> > +++ b/scrub/inodes.c
> > @@ -72,7 +72,7 @@ xfs_iterate_inodes_range_check(
> >   		/* Load the one inode. */
> >   		oneino = inogrp->xi_startino + i;
> >   		onereq.ubuffer = bs;
> > -		error = ioctl(ctx->mnt_fd, XFS_IOC_FSBULKSTAT_SINGLE,
> > +		error = ioctl(ctx->mnt.fd, XFS_IOC_FSBULKSTAT_SINGLE,
> >   				&onereq);
> >   		if (error || bs->bs_ino != inogrp->xi_startino + i) {
> >   			memset(bs, 0, sizeof(struct xfs_bstat));
> > @@ -134,7 +134,7 @@ xfs_iterate_inodes_range(
> >   	/* Find the inode chunk & alloc mask */
> >   	igrp_ino = first_ino;
> > -	error = ioctl(ctx->mnt_fd, XFS_IOC_FSINUMBERS, &igrpreq);
> > +	error = ioctl(ctx->mnt.fd, XFS_IOC_FSINUMBERS, &igrpreq);
> >   	while (!error && igrplen) {
> >   		/* Load the inodes. */
> >   		ino = inogrp.xi_startino - 1;
> > @@ -145,7 +145,7 @@ xfs_iterate_inodes_range(
> >   		 */
> >   		if (inogrp.xi_alloccount == 0)
> >   			goto igrp_retry;
> > -		error = ioctl(ctx->mnt_fd, XFS_IOC_FSBULKSTAT, &bulkreq);
> > +		error = ioctl(ctx->mnt.fd, XFS_IOC_FSBULKSTAT, &bulkreq);
> >   		if (error)
> >   			str_info(ctx, descr, "%s", strerror_r(errno,
> >   						buf, DESCR_BUFSZ));
> > @@ -190,7 +190,7 @@ _("Changed too many times during scan; giving up."));
> >   		stale_count = 0;
> >   igrp_retry:
> > -		error = ioctl(ctx->mnt_fd, XFS_IOC_FSINUMBERS, &igrpreq);
> > +		error = ioctl(ctx->mnt.fd, XFS_IOC_FSINUMBERS, &igrpreq);
> >   	}
> >   err:
> > @@ -260,7 +260,7 @@ xfs_scan_all_inodes(
> >   		return false;
> >   	}
> > -	for (agno = 0; agno < ctx->geo.agcount; agno++) {
> > +	for (agno = 0; agno < ctx->mnt.fsgeom.agcount; agno++) {
> >   		ret = workqueue_add(&wq, xfs_scan_ag_inodes, agno, &si);
> >   		if (ret) {
> >   			si.moveon = false;
> > diff --git a/scrub/phase1.c b/scrub/phase1.c
> > index bdd23d26..6d8293b2 100644
> > --- a/scrub/phase1.c
> > +++ b/scrub/phase1.c
> > @@ -39,7 +39,7 @@ xfs_shutdown_fs(
> >   	flag = XFS_FSOP_GOING_FLAGS_LOGFLUSH;
> >   	str_info(ctx, ctx->mntpoint, _("Shutting down filesystem!"));
> > -	if (ioctl(ctx->mnt_fd, XFS_IOC_GOINGDOWN, &flag))
> > +	if (ioctl(ctx->mnt.fd, XFS_IOC_GOINGDOWN, &flag))
> >   		str_errno(ctx, ctx->mntpoint);
> >   }
> > @@ -60,11 +60,9 @@ xfs_cleanup_fs(
> >   	if (ctx->datadev)
> >   		disk_close(ctx->datadev);
> >   	fshandle_destroy();
> > -	if (ctx->mnt_fd >= 0) {
> > -		error = close(ctx->mnt_fd);
> > -		if (error)
> > -			str_errno(ctx, _("closing mountpoint fd"));
> > -	}
> > +	error = xfd_close(&ctx->mnt);
> > +	if (error)
> > +		str_liberror(ctx, error, _("closing mountpoint fd"));
> >   	fs_table_destroy();
> >   	return true;
> > @@ -86,8 +84,8 @@ xfs_setup_fs(
> >   	 * CAP_SYS_ADMIN, which we probably need to do anything fancy
> >   	 * with the (XFS driver) kernel.
> >   	 */
> > -	ctx->mnt_fd = open(ctx->mntpoint, O_RDONLY | O_NOATIME | O_DIRECTORY);
> > -	if (ctx->mnt_fd < 0) {
> > +	ctx->mnt.fd = open(ctx->mntpoint, O_RDONLY | O_NOATIME | O_DIRECTORY);
> > +	if (ctx->mnt.fd < 0) {
> >   		if (errno == EPERM)
> >   			str_info(ctx, ctx->mntpoint,
> >   _("Must be root to run scrub."));
> > @@ -96,23 +94,23 @@ _("Must be root to run scrub."));
> >   		return false;
> >   	}
> > -	error = fstat(ctx->mnt_fd, &ctx->mnt_sb);
> > +	error = fstat(ctx->mnt.fd, &ctx->mnt_sb);
> >   	if (error) {
> >   		str_errno(ctx, ctx->mntpoint);
> >   		return false;
> >   	}
> > -	error = fstatvfs(ctx->mnt_fd, &ctx->mnt_sv);
> > +	error = fstatvfs(ctx->mnt.fd, &ctx->mnt_sv);
> >   	if (error) {
> >   		str_errno(ctx, ctx->mntpoint);
> >   		return false;
> >   	}
> > -	error = fstatfs(ctx->mnt_fd, &ctx->mnt_sf);
> > +	error = fstatfs(ctx->mnt.fd, &ctx->mnt_sf);
> >   	if (error) {
> >   		str_errno(ctx, ctx->mntpoint);
> >   		return false;
> >   	}
> > -	if (!platform_test_xfs_fd(ctx->mnt_fd)) {
> > +	if (!platform_test_xfs_fd(ctx->mnt.fd)) {
> >   		str_info(ctx, ctx->mntpoint,
> >   _("Does not appear to be an XFS filesystem!"));
> >   		return false;
> > @@ -123,27 +121,28 @@ _("Does not appear to be an XFS filesystem!"));
> >   	 * This seems to reduce the incidence of stale file handle
> >   	 * errors when we open things by handle.
> >   	 */
> > -	error = syncfs(ctx->mnt_fd);
> > +	error = syncfs(ctx->mnt.fd);
> >   	if (error) {
> >   		str_errno(ctx, ctx->mntpoint);
> >   		return false;
> >   	}
> >   	/* Retrieve XFS geometry. */
> > -	error = xfrog_geometry(ctx->mnt_fd, &ctx->geo);
> > +	error = xfd_prepare_geometry(&ctx->mnt);
> >   	if (error) {
> >   		str_liberror(ctx, error, _("Retrieving XFS geometry"));
> >   		return false;
> >   	}
> > -	if (!xfs_action_lists_alloc(ctx->geo.agcount, &ctx->action_lists)) {
> > +	if (!xfs_action_lists_alloc(ctx->mnt.fsgeom.agcount,
> > +				&ctx->action_lists)) {
> >   		str_error(ctx, ctx->mntpoint, _("Not enough memory."));
> >   		return false;
> >   	}
> > -	ctx->agblklog = log2_roundup(ctx->geo.agblocks);
> > -	ctx->blocklog = highbit32(ctx->geo.blocksize);
> > -	ctx->inodelog = highbit32(ctx->geo.inodesize);
> > +	ctx->agblklog = log2_roundup(ctx->mnt.fsgeom.agblocks);
> > +	ctx->blocklog = highbit32(ctx->mnt.fsgeom.blocksize);
> > +	ctx->inodelog = highbit32(ctx->mnt.fsgeom.inodesize);
> >   	ctx->inopblog = ctx->blocklog - ctx->inodelog;
> >   	error = path_to_fshandle(ctx->mntpoint, &ctx->fshandle,
> > @@ -171,12 +170,12 @@ _("Kernel metadata repair facility is not available.  Use -n to scrub."));
> >   	}
> >   	/* Did we find the log and rt devices, if they're present? */
> > -	if (ctx->geo.logstart == 0 && ctx->fsinfo.fs_log == NULL) {
> > +	if (ctx->mnt.fsgeom.logstart == 0 && ctx->fsinfo.fs_log == NULL) {
> >   		str_info(ctx, ctx->mntpoint,
> >   _("Unable to find log device path."));
> >   		return false;
> >   	}
> > -	if (ctx->geo.rtblocks && ctx->fsinfo.fs_rt == NULL) {
> > +	if (ctx->mnt.fsgeom.rtblocks && ctx->fsinfo.fs_rt == NULL) {
> >   		str_info(ctx, ctx->mntpoint,
> >   _("Unable to find realtime device path."));
> >   		return false;
> > diff --git a/scrub/phase2.c b/scrub/phase2.c
> > index 653f666c..a80da7fd 100644
> > --- a/scrub/phase2.c
> > +++ b/scrub/phase2.c
> > @@ -141,7 +141,7 @@ xfs_scan_metadata(
> >   	if (!moveon)
> >   		goto out;
> > -	for (agno = 0; moveon && agno < ctx->geo.agcount; agno++) {
> > +	for (agno = 0; moveon && agno < ctx->mnt.fsgeom.agcount; agno++) {
> >   		ret = workqueue_add(&wq, xfs_scan_ag_metadata, agno, &moveon);
> >   		if (ret) {
> >   			moveon = false;
> > diff --git a/scrub/phase3.c b/scrub/phase3.c
> > index 4963d675..a42d8213 100644
> > --- a/scrub/phase3.c
> > +++ b/scrub/phase3.c
> > @@ -33,7 +33,7 @@ xfs_scrub_fd(
> >   	struct xfs_bstat	*bs,
> >   	struct xfs_action_list	*alist)
> >   {
> > -	return fn(ctx, bs->bs_ino, bs->bs_gen, ctx->mnt_fd, alist);
> > +	return fn(ctx, bs->bs_ino, bs->bs_gen, ctx->mnt.fd, alist);
> >   }
> >   struct scrub_inode_ctx {
> > @@ -115,7 +115,7 @@ xfs_scrub_inode(
> >   	if (S_ISLNK(bstat->bs_mode)) {
> >   		/* Check symlink contents. */
> >   		moveon = xfs_scrub_symlink(ctx, bstat->bs_ino,
> > -				bstat->bs_gen, ctx->mnt_fd, &alist);
> > +				bstat->bs_gen, ctx->mnt.fd, &alist);
> >   	} else if (S_ISDIR(bstat->bs_mode)) {
> >   		/* Check the directory entries. */
> >   		moveon = xfs_scrub_fd(ctx, xfs_scrub_dir, bstat, &alist);
> > diff --git a/scrub/phase4.c b/scrub/phase4.c
> > index 79248326..49f00723 100644
> > --- a/scrub/phase4.c
> > +++ b/scrub/phase4.c
> > @@ -40,7 +40,7 @@ xfs_repair_ag(
> >   	/* Repair anything broken until we fail to make progress. */
> >   	do {
> > -		moveon = xfs_action_list_process(ctx, ctx->mnt_fd, alist, flags);
> > +		moveon = xfs_action_list_process(ctx, ctx->mnt.fd, alist, flags);
> >   		if (!moveon) {
> >   			*pmoveon = false;
> >   			return;
> > @@ -56,7 +56,7 @@ xfs_repair_ag(
> >   	/* Try once more, but this time complain if we can't fix things. */
> >   	flags |= ALP_COMPLAIN_IF_UNFIXED;
> > -	moveon = xfs_action_list_process(ctx, ctx->mnt_fd, alist, flags);
> > +	moveon = xfs_action_list_process(ctx, ctx->mnt.fd, alist, flags);
> >   	if (!moveon)
> >   		*pmoveon = false;
> >   }
> > @@ -77,7 +77,7 @@ xfs_process_action_items(
> >   		str_error(ctx, ctx->mntpoint, _("Could not create workqueue."));
> >   		return false;
> >   	}
> > -	for (agno = 0; agno < ctx->geo.agcount; agno++) {
> > +	for (agno = 0; agno < ctx->mnt.fsgeom.agcount; agno++) {
> >   		if (xfs_action_list_length(&ctx->action_lists[agno]) > 0) {
> >   			ret = workqueue_add(&wq, xfs_repair_ag, agno, &moveon);
> >   			if (ret) {
> > @@ -121,7 +121,7 @@ xfs_estimate_repair_work(
> >   	xfs_agnumber_t		agno;
> >   	size_t			need_fixing = 0;
> > -	for (agno = 0; agno < ctx->geo.agcount; agno++)
> > +	for (agno = 0; agno < ctx->mnt.fsgeom.agcount; agno++)
> >   		need_fixing += xfs_action_list_length(&ctx->action_lists[agno]);
> >   	need_fixing++;
> >   	*items = need_fixing;
> > diff --git a/scrub/phase5.c b/scrub/phase5.c
> > index 1743119d..748885d4 100644
> > --- a/scrub/phase5.c
> > +++ b/scrub/phase5.c
> > @@ -306,7 +306,7 @@ xfs_scrub_fs_label(
> >   		return false;
> >   	/* Retrieve label; quietly bail if we don't support that. */
> > -	error = ioctl(ctx->mnt_fd, FS_IOC_GETFSLABEL, &label);
> > +	error = ioctl(ctx->mnt.fd, FS_IOC_GETFSLABEL, &label);
> >   	if (error) {
> >   		if (errno != EOPNOTSUPP && errno != ENOTTY) {
> >   			moveon = false;
> > diff --git a/scrub/phase6.c b/scrub/phase6.c
> > index 66e6451c..e5a0b3c1 100644
> > --- a/scrub/phase6.c
> > +++ b/scrub/phase6.c
> > @@ -468,7 +468,7 @@ xfs_scan_blocks(
> >   	}
> >   	vs.rvp_data = read_verify_pool_init(ctx, ctx->datadev,
> > -			ctx->geo.blocksize, xfs_check_rmap_ioerr,
> > +			ctx->mnt.fsgeom.blocksize, xfs_check_rmap_ioerr,
> >   			scrub_nproc(ctx));
> >   	if (!vs.rvp_data) {
> >   		str_info(ctx, ctx->mntpoint,
> > @@ -477,7 +477,7 @@ _("Could not create data device media verifier."));
> >   	}
> >   	if (ctx->logdev) {
> >   		vs.rvp_log = read_verify_pool_init(ctx, ctx->logdev,
> > -				ctx->geo.blocksize, xfs_check_rmap_ioerr,
> > +				ctx->mnt.fsgeom.blocksize, xfs_check_rmap_ioerr,
> >   				scrub_nproc(ctx));
> >   		if (!vs.rvp_log) {
> >   			str_info(ctx, ctx->mntpoint,
> > @@ -487,7 +487,7 @@ _("Could not create data device media verifier."));
> >   	}
> >   	if (ctx->rtdev) {
> >   		vs.rvp_realtime = read_verify_pool_init(ctx, ctx->rtdev,
> > -				ctx->geo.blocksize, xfs_check_rmap_ioerr,
> > +				ctx->mnt.fsgeom.blocksize, xfs_check_rmap_ioerr,
> >   				scrub_nproc(ctx));
> >   		if (!vs.rvp_realtime) {
> >   			str_info(ctx, ctx->mntpoint,
> > diff --git a/scrub/phase7.c b/scrub/phase7.c
> > index 0c3202e4..13959ca8 100644
> > --- a/scrub/phase7.c
> > +++ b/scrub/phase7.c
> > @@ -111,7 +111,7 @@ xfs_scan_summary(
> >   	int			error;
> >   	/* Flush everything out to disk before we start counting. */
> > -	error = syncfs(ctx->mnt_fd);
> > +	error = syncfs(ctx->mnt.fd);
> >   	if (error) {
> >   		str_errno(ctx, ctx->mntpoint);
> >   		return false;
> > diff --git a/scrub/repair.c b/scrub/repair.c
> > index 4ed3c09a..45450d8c 100644
> > --- a/scrub/repair.c
> > +++ b/scrub/repair.c
> > @@ -262,7 +262,7 @@ xfs_action_list_defer(
> >   	xfs_agnumber_t			agno,
> >   	struct xfs_action_list		*alist)
> >   {
> > -	ASSERT(agno < ctx->geo.agcount);
> > +	ASSERT(agno < ctx->mnt.fsgeom.agcount);
> >   	xfs_action_list_splice(&ctx->action_lists[agno], alist);
> >   }
> > @@ -276,7 +276,7 @@ xfs_action_list_process_or_defer(
> >   {
> >   	bool				moveon;
> > -	moveon = xfs_action_list_process(ctx, ctx->mnt_fd, alist,
> > +	moveon = xfs_action_list_process(ctx, ctx->mnt.fd, alist,
> >   			ALP_REPAIR_ONLY | ALP_NOPROGRESS);
> >   	if (!moveon)
> >   		return moveon;
> > diff --git a/scrub/scrub.c b/scrub/scrub.c
> > index 0f0c9639..136ed529 100644
> > --- a/scrub/scrub.c
> > +++ b/scrub/scrub.c
> > @@ -363,7 +363,7 @@ xfs_scrub_metadata(
> >   		background_sleep();
> >   		/* Check the item. */
> > -		fix = xfs_check_metadata(ctx, ctx->mnt_fd, &meta, false);
> > +		fix = xfs_check_metadata(ctx, ctx->mnt.fd, &meta, false);
> >   		progress_add(1);
> >   		switch (fix) {
> >   		case CHECK_ABORT:
> > @@ -399,7 +399,7 @@ xfs_scrub_primary_super(
> >   	enum check_outcome		fix;
> >   	/* Check the item. */
> > -	fix = xfs_check_metadata(ctx, ctx->mnt_fd, &meta, false);
> > +	fix = xfs_check_metadata(ctx, ctx->mnt.fd, &meta, false);
> >   	switch (fix) {
> >   	case CHECK_ABORT:
> >   		return false;
> > @@ -460,7 +460,7 @@ xfs_scrub_estimate_ag_work(
> >   		switch (sc->type) {
> >   		case ST_AGHEADER:
> >   		case ST_PERAG:
> > -			estimate += ctx->geo.agcount;
> > +			estimate += ctx->mnt.fsgeom.agcount;
> >   			break;
> >   		case ST_FS:
> >   			estimate++;
> > @@ -605,9 +605,9 @@ __xfs_scrub_test(
> >   	if (debug_tweak_on("XFS_SCRUB_NO_KERNEL"))
> >   		return false;
> >   	if (debug_tweak_on("XFS_SCRUB_FORCE_REPAIR") && !injected) {
> > -		inject.fd = ctx->mnt_fd;
> > +		inject.fd = ctx->mnt.fd;
> >   		inject.errtag = XFS_ERRTAG_FORCE_SCRUB_REPAIR;
> > -		error = ioctl(ctx->mnt_fd, XFS_IOC_ERROR_INJECTION, &inject);
> > +		error = ioctl(ctx->mnt.fd, XFS_IOC_ERROR_INJECTION, &inject);
> >   		if (error == 0)
> >   			injected = true;
> >   	}
> > @@ -615,7 +615,7 @@ __xfs_scrub_test(
> >   	meta.sm_type = type;
> >   	if (repair)
> >   		meta.sm_flags |= XFS_SCRUB_IFLAG_REPAIR;
> > -	error = ioctl(ctx->mnt_fd, XFS_IOC_SCRUB_METADATA, &meta);
> > +	error = ioctl(ctx->mnt.fd, XFS_IOC_SCRUB_METADATA, &meta);
> >   	if (!error)
> >   		return true;
> >   	switch (errno) {
> > diff --git a/scrub/spacemap.c b/scrub/spacemap.c
> > index d547a041..c3621a3a 100644
> > --- a/scrub/spacemap.c
> > +++ b/scrub/spacemap.c
> > @@ -56,7 +56,7 @@ xfs_iterate_fsmap(
> >   	memcpy(head->fmh_keys, keys, sizeof(struct fsmap) * 2);
> >   	head->fmh_count = FSMAP_NR;
> > -	while ((error = ioctl(ctx->mnt_fd, FS_IOC_GETFSMAP, head)) == 0) {
> > +	while ((error = ioctl(ctx->mnt.fd, FS_IOC_GETFSMAP, head)) == 0) {
> >   		for (i = 0, p = head->fmh_recs;
> >   		     i < head->fmh_entries;
> >   		     i++, p++) {
> > @@ -107,8 +107,8 @@ xfs_scan_ag_blocks(
> >   	off64_t			bperag;
> >   	bool			moveon;
> > -	bperag = (off64_t)ctx->geo.agblocks *
> > -		 (off64_t)ctx->geo.blocksize;
> > +	bperag = (off64_t)ctx->mnt.fsgeom.agblocks *
> > +		 (off64_t)ctx->mnt.fsgeom.blocksize;
> >   	snprintf(descr, DESCR_BUFSZ, _("dev %d:%d AG %u fsmap"),
> >   				major(ctx->fsinfo.fs_datadev),
> > @@ -205,7 +205,7 @@ xfs_scan_all_spacemaps(
> >   	}
> >   	if (ctx->fsinfo.fs_rt) {
> >   		ret = workqueue_add(&wq, xfs_scan_rt_blocks,
> > -				ctx->geo.agcount + 1, &sbx);
> > +				ctx->mnt.fsgeom.agcount + 1, &sbx);
> >   		if (ret) {
> >   			sbx.moveon = false;
> >   			str_info(ctx, ctx->mntpoint,
> > @@ -215,7 +215,7 @@ _("Could not queue rtdev fsmap work."));
> >   	}
> >   	if (ctx->fsinfo.fs_log) {
> >   		ret = workqueue_add(&wq, xfs_scan_log_blocks,
> > -				ctx->geo.agcount + 2, &sbx);
> > +				ctx->mnt.fsgeom.agcount + 2, &sbx);
> >   		if (ret) {
> >   			sbx.moveon = false;
> >   			str_info(ctx, ctx->mntpoint,
> > @@ -223,7 +223,7 @@ _("Could not queue logdev fsmap work."));
> >   			goto out;
> >   		}
> >   	}
> > -	for (agno = 0; agno < ctx->geo.agcount; agno++) {
> > +	for (agno = 0; agno < ctx->mnt.fsgeom.agcount; agno++) {
> >   		ret = workqueue_add(&wq, xfs_scan_ag_blocks, agno, &sbx);
> >   		if (ret) {
> >   			sbx.moveon = false;
> > diff --git a/scrub/vfs.c b/scrub/vfs.c
> > index 8bcc4e79..7b0b5bcd 100644
> > --- a/scrub/vfs.c
> > +++ b/scrub/vfs.c
> > @@ -232,7 +232,7 @@ fstrim(
> >   	int			error;
> >   	range.len = ULLONG_MAX;
> > -	error = ioctl(ctx->mnt_fd, FITRIM, &range);
> > +	error = ioctl(ctx->mnt.fd, FITRIM, &range);
> >   	if (error && errno != EOPNOTSUPP && errno != ENOTTY)
> >   		perror(_("fstrim"));
> >   }
> > diff --git a/scrub/xfs_scrub.h b/scrub/xfs_scrub.h
> > index a459e4b5..28eae6fe 100644
> > --- a/scrub/xfs_scrub.h
> > +++ b/scrub/xfs_scrub.h
> > @@ -6,6 +6,8 @@
> >   #ifndef XFS_SCRUB_XFS_SCRUB_H_
> >   #define XFS_SCRUB_XFS_SCRUB_H_
> > +#include <xfrog.h>
> > +
> >   extern char *progname;
> >   #define _PATH_PROC_MOUNTS	"/proc/mounts"
> > @@ -53,14 +55,13 @@ struct scrub_ctx {
> >   	/* How does the user want us to react to errors? */
> >   	enum error_action	error_action;
> > -	/* fd to filesystem mount point */
> > -	int			mnt_fd;
> > +	/* xfrog context for the mount point */
> > +	struct xfs_fd		mnt;
> >   	/* Number of threads for metadata scrubbing */
> >   	unsigned int		nr_io_threads;
> >   	/* XFS specific geometry */
> > -	struct xfs_fsop_geom	geo;
> >   	struct fs_path		fsinfo;
> >   	unsigned int		agblklog;
> >   	unsigned int		blocklog;
> > 

^ permalink raw reply	[flat|nested] 31+ messages in thread

* Re: [PATCH 5/9] libfrog: store more inode and block geometry in struct xfs_fd
  2019-08-30  4:20 ` [PATCH 5/9] libfrog: store more inode and block geometry in struct xfs_fd Darrick J. Wong
@ 2019-08-31  0:37   ` Allison Collins
  0 siblings, 0 replies; 31+ messages in thread
From: Allison Collins @ 2019-08-31  0:37 UTC (permalink / raw)
  To: Darrick J. Wong, sandeen; +Cc: linux-xfs, Dave Chinner

On 8/29/19 9:20 PM, Darrick J. Wong wrote:
> From: Darrick J. Wong <darrick.wong@oracle.com>
> 
> Move the extra AG geometry fields out of scrub and into the libfrog code
> so that we can consolidate the geoemtry code in one place.
> 
> Signed-off-by: Darrick J. Wong <darrick.wong@oracle.com>
> Reviewed-by: Dave Chinner <dchinner@redhat.com>
Alrighty, looks good.  I'm seeing how the helpers are getting expanded 
:-)  You can add my review:

Reviewed-by: Allison Collins <allison.henderson@oracle.com>

> ---
>   include/xfrog.h    |   12 ++++++++++++
>   libfrog/fsgeom.c   |   13 ++++++++++++-
>   scrub/fscounters.c |    4 ++--
>   scrub/inodes.c     |    4 ++--
>   scrub/phase1.c     |    5 -----
>   scrub/phase3.c     |    6 +++---
>   scrub/phase5.c     |    4 ++--
>   scrub/phase6.c     |    2 +-
>   scrub/phase7.c     |    6 +++---
>   scrub/xfs_scrub.h  |    4 ----
>   10 files changed, 37 insertions(+), 23 deletions(-)
> 
> 
> diff --git a/include/xfrog.h b/include/xfrog.h
> index 766ee5d5..008cc155 100644
> --- a/include/xfrog.h
> +++ b/include/xfrog.h
> @@ -30,6 +30,18 @@ struct xfs_fd {
>   
>   	/* filesystem geometry */
>   	struct xfs_fsop_geom	fsgeom;
> +
> +	/* log2 of sb_agblocks (rounded up) */
> +	unsigned int		agblklog;
> +
> +	/* log2 of sb_blocksize */
> +	unsigned int		blocklog;
> +
> +	/* log2 of sb_inodesize */
> +	unsigned int		inodelog;
> +
> +	/* log2 of sb_inopblock */
> +	unsigned int		inopblog;
>   };
>   
>   /* Static initializers */
> diff --git a/libfrog/fsgeom.c b/libfrog/fsgeom.c
> index 694ccbd0..b8873598 100644
> --- a/libfrog/fsgeom.c
> +++ b/libfrog/fsgeom.c
> @@ -5,6 +5,7 @@
>   #include "libxfs.h"
>   #include "fsgeom.h"
>   #include "xfrog.h"
> +#include "libfrog.h"
>   
>   void
>   xfs_report_geom(
> @@ -102,7 +103,17 @@ int
>   xfd_prepare_geometry(
>   	struct xfs_fd		*xfd)
>   {
> -	return xfrog_geometry(xfd->fd, &xfd->fsgeom);
> +	int			ret;
> +
> +	ret = xfrog_geometry(xfd->fd, &xfd->fsgeom);
> +	if (ret)
> +		return ret;
> +
> +	xfd->agblklog = log2_roundup(xfd->fsgeom.agblocks);
> +	xfd->blocklog = highbit32(xfd->fsgeom.blocksize);
> +	xfd->inodelog = highbit32(xfd->fsgeom.inodesize);
> +	xfd->inopblog = xfd->blocklog - xfd->inodelog;
> +	return 0;
>   }
>   
>   /*
> diff --git a/scrub/fscounters.c b/scrub/fscounters.c
> index f18d0e19..ac898764 100644
> --- a/scrub/fscounters.c
> +++ b/scrub/fscounters.c
> @@ -91,8 +91,8 @@ xfs_count_ag_inodes(
>   				minor(ctx->fsinfo.fs_datadev),
>   				agno);
>   
> -	ag_ino = (__u64)agno << (ctx->inopblog + ctx->agblklog);
> -	next_ag_ino = (__u64)(agno + 1) << (ctx->inopblog + ctx->agblklog);
> +	ag_ino = (__u64)agno << (ctx->mnt.inopblog + ctx->mnt.agblklog);
> +	next_ag_ino = (__u64)(agno + 1) << (ctx->mnt.inopblog + ctx->mnt.agblklog);
>   
>   	moveon = xfs_count_inodes_range(ctx, descr, ag_ino, next_ag_ino - 1,
>   			&ci->counters[agno]);
> diff --git a/scrub/inodes.c b/scrub/inodes.c
> index 08f3d847..873ad425 100644
> --- a/scrub/inodes.c
> +++ b/scrub/inodes.c
> @@ -228,8 +228,8 @@ xfs_scan_ag_inodes(
>   				minor(ctx->fsinfo.fs_datadev),
>   				agno);
>   
> -	ag_ino = (__u64)agno << (ctx->inopblog + ctx->agblklog);
> -	next_ag_ino = (__u64)(agno + 1) << (ctx->inopblog + ctx->agblklog);
> +	ag_ino = (__u64)agno << (ctx->mnt.inopblog + ctx->mnt.agblklog);
> +	next_ag_ino = (__u64)(agno + 1) << (ctx->mnt.inopblog + ctx->mnt.agblklog);
>   
>   	moveon = xfs_iterate_inodes_range(ctx, descr, ctx->fshandle, ag_ino,
>   			next_ag_ino - 1, si->fn, si->arg);
> diff --git a/scrub/phase1.c b/scrub/phase1.c
> index 6d8293b2..cbdbd010 100644
> --- a/scrub/phase1.c
> +++ b/scrub/phase1.c
> @@ -140,11 +140,6 @@ _("Does not appear to be an XFS filesystem!"));
>   		return false;
>   	}
>   
> -	ctx->agblklog = log2_roundup(ctx->mnt.fsgeom.agblocks);
> -	ctx->blocklog = highbit32(ctx->mnt.fsgeom.blocksize);
> -	ctx->inodelog = highbit32(ctx->mnt.fsgeom.inodesize);
> -	ctx->inopblog = ctx->blocklog - ctx->inodelog;
> -
>   	error = path_to_fshandle(ctx->mntpoint, &ctx->fshandle,
>   			&ctx->fshandle_len);
>   	if (error) {
> diff --git a/scrub/phase3.c b/scrub/phase3.c
> index a42d8213..579e08c3 100644
> --- a/scrub/phase3.c
> +++ b/scrub/phase3.c
> @@ -52,8 +52,8 @@ xfs_scrub_inode_vfs_error(
>   	xfs_agino_t		agino;
>   	int			old_errno = errno;
>   
> -	agno = bstat->bs_ino / (1ULL << (ctx->inopblog + ctx->agblklog));
> -	agino = bstat->bs_ino % (1ULL << (ctx->inopblog + ctx->agblklog));
> +	agno = bstat->bs_ino / (1ULL << (ctx->mnt.inopblog + ctx->mnt.agblklog));
> +	agino = bstat->bs_ino % (1ULL << (ctx->mnt.inopblog + ctx->mnt.agblklog));
>   	snprintf(descr, DESCR_BUFSZ, _("inode %"PRIu64" (%u/%u)"),
>   			(uint64_t)bstat->bs_ino, agno, agino);
>   	errno = old_errno;
> @@ -77,7 +77,7 @@ xfs_scrub_inode(
>   	int			error;
>   
>   	xfs_action_list_init(&alist);
> -	agno = bstat->bs_ino / (1ULL << (ctx->inopblog + ctx->agblklog));
> +	agno = bstat->bs_ino / (1ULL << (ctx->mnt.inopblog + ctx->mnt.agblklog));
>   	background_sleep();
>   
>   	/* Try to open the inode to pin it. */
> diff --git a/scrub/phase5.c b/scrub/phase5.c
> index 748885d4..36ec27b3 100644
> --- a/scrub/phase5.c
> +++ b/scrub/phase5.c
> @@ -239,8 +239,8 @@ xfs_scrub_connections(
>   	int			fd = -1;
>   	int			error;
>   
> -	agno = bstat->bs_ino / (1ULL << (ctx->inopblog + ctx->agblklog));
> -	agino = bstat->bs_ino % (1ULL << (ctx->inopblog + ctx->agblklog));
> +	agno = bstat->bs_ino / (1ULL << (ctx->mnt.inopblog + ctx->mnt.agblklog));
> +	agino = bstat->bs_ino % (1ULL << (ctx->mnt.inopblog + ctx->mnt.agblklog));
>   	snprintf(descr, DESCR_BUFSZ, _("inode %"PRIu64" (%u/%u)"),
>   			(uint64_t)bstat->bs_ino, agno, agino);
>   	background_sleep();
> diff --git a/scrub/phase6.c b/scrub/phase6.c
> index e5a0b3c1..48971270 100644
> --- a/scrub/phase6.c
> +++ b/scrub/phase6.c
> @@ -547,7 +547,7 @@ xfs_estimate_verify_work(
>   	if (!moveon)
>   		return moveon;
>   
> -	*items = ((d_blocks - d_bfree) + (r_blocks - r_bfree)) << ctx->blocklog;
> +	*items = ((d_blocks - d_bfree) + (r_blocks - r_bfree)) << ctx->mnt.blocklog;
>   	*nr_threads = disk_heads(ctx->datadev);
>   	*rshift = 20;
>   	return moveon;
> diff --git a/scrub/phase7.c b/scrub/phase7.c
> index 13959ca8..41a77356 100644
> --- a/scrub/phase7.c
> +++ b/scrub/phase7.c
> @@ -148,11 +148,11 @@ xfs_scan_summary(
>   	 * filesystem treats them as "free", but since we scanned
>   	 * them, we'll consider them used.
>   	 */
> -	d_bfree -= totalcount.agbytes >> ctx->blocklog;
> +	d_bfree -= totalcount.agbytes >> ctx->mnt.blocklog;
>   
>   	/* Report on what we found. */
> -	used_data = (d_blocks - d_bfree) << ctx->blocklog;
> -	used_rt = (r_blocks - r_bfree) << ctx->blocklog;
> +	used_data = (d_blocks - d_bfree) << ctx->mnt.blocklog;
> +	used_rt = (r_blocks - r_bfree) << ctx->mnt.blocklog;
>   	used_files = f_files - f_free;
>   	stat_data = totalcount.dbytes;
>   	stat_rt = totalcount.rbytes;
> diff --git a/scrub/xfs_scrub.h b/scrub/xfs_scrub.h
> index 28eae6fe..fb34c587 100644
> --- a/scrub/xfs_scrub.h
> +++ b/scrub/xfs_scrub.h
> @@ -63,10 +63,6 @@ struct scrub_ctx {
>   
>   	/* XFS specific geometry */
>   	struct fs_path		fsinfo;
> -	unsigned int		agblklog;
> -	unsigned int		blocklog;
> -	unsigned int		inodelog;
> -	unsigned int		inopblog;
>   	void			*fshandle;
>   	size_t			fshandle_len;
>   
> 

^ permalink raw reply	[flat|nested] 31+ messages in thread

* [PATCH v2 7/9] libfrog: refactor open-coded bulkstat calls
  2019-08-30  4:21 ` [PATCH 7/9] libfrog: refactor open-coded bulkstat calls Darrick J. Wong
  2019-08-30 23:26   ` Darrick J. Wong
@ 2019-08-31  0:42   ` Darrick J. Wong
  2019-09-03 22:57     ` Dave Chinner
  2019-09-01 20:55   ` [PATCH " Allison Collins
  2 siblings, 1 reply; 31+ messages in thread
From: Darrick J. Wong @ 2019-08-31  0:42 UTC (permalink / raw)
  To: sandeen; +Cc: linux-xfs

From: Darrick J. Wong <darrick.wong@oracle.com>

Refactor the BULKSTAT_SINGLE and BULKSTAT ioctl callsites into helper
functions.

Signed-off-by: Darrick J. Wong <darrick.wong@oracle.com>
---
 fsr/xfs_fsr.c      |  110 ++++++++++++++++++++++------------------------------
 include/xfrog.h    |    7 +++
 io/open.c          |   72 +++++++++++++++++-----------------
 io/swapext.c       |   20 ++-------
 libfrog/Makefile   |    1 
 libfrog/bulkstat.c |   52 +++++++++++++++++++++++++
 quota/quot.c       |   33 ++++++++--------
 scrub/inodes.c     |   38 +++++++-----------
 8 files changed, 177 insertions(+), 156 deletions(-)
 create mode 100644 libfrog/bulkstat.c

diff --git a/fsr/xfs_fsr.c b/fsr/xfs_fsr.c
index 4b239a30..36402252 100644
--- a/fsr/xfs_fsr.c
+++ b/fsr/xfs_fsr.c
@@ -102,31 +102,6 @@ static int	nfrags = 0;	/* Debug option: Coerse into specific number
 				 * of extents */
 static int	openopts = O_CREAT|O_EXCL|O_RDWR|O_DIRECT;
 
-static int
-xfs_bulkstat_single(int fd, xfs_ino_t *lastip, struct xfs_bstat *ubuffer)
-{
-    struct xfs_fsop_bulkreq  bulkreq;
-
-    bulkreq.lastip = (__u64 *)lastip;
-    bulkreq.icount = 1;
-    bulkreq.ubuffer = ubuffer;
-    bulkreq.ocount = NULL;
-    return ioctl(fd, XFS_IOC_FSBULKSTAT_SINGLE, &bulkreq);
-}
-
-static int
-xfs_bulkstat(int fd, xfs_ino_t *lastip, int icount,
-                    struct xfs_bstat *ubuffer, __s32 *ocount)
-{
-    struct xfs_fsop_bulkreq  bulkreq;
-
-    bulkreq.lastip = (__u64 *)lastip;
-    bulkreq.icount = icount;
-    bulkreq.ubuffer = ubuffer;
-    bulkreq.ocount = ocount;
-    return ioctl(fd, XFS_IOC_FSBULKSTAT, &bulkreq);
-}
-
 static int
 xfs_swapext(int fd, xfs_swapext_t *sx)
 {
@@ -596,11 +571,11 @@ fsrall_cleanup(int timeout)
 static int
 fsrfs(char *mntdir, xfs_ino_t startino, int targetrange)
 {
-
-	int	fsfd, fd;
+	struct xfs_fd	fsxfd = XFS_FD_INIT_EMPTY;
+	int	fd;
 	int	count = 0;
 	int	ret;
-	__s32	buflenout;
+	uint32_t buflenout;
 	struct xfs_bstat buf[GRABSZ];
 	char	fname[64];
 	char	*tname;
@@ -617,26 +592,27 @@ fsrfs(char *mntdir, xfs_ino_t startino, int targetrange)
 		return -1;
 	}
 
-	if ((fsfd = open(mntdir, O_RDONLY)) < 0) {
+	if ((fsxfd.fd = open(mntdir, O_RDONLY)) < 0) {
 		fsrprintf(_("unable to open: %s: %s\n"),
 		          mntdir, strerror( errno ));
 		free(fshandlep);
 		return -1;
 	}
 
-	ret = xfrog_geometry(fsfd, &fsgeom);
+	ret = xfd_prepare_geometry(&fsxfd);
 	if (ret) {
 		fsrprintf(_("Skipping %s: could not get XFS geometry\n"),
 			  mntdir);
-		close(fsfd);
+		xfd_close(&fsxfd);
 		free(fshandlep);
 		return -1;
 	}
+	memcpy(&fsgeom, &fsxfd.fsgeom, sizeof(fsgeom));
 
 	tmp_init(mntdir);
 
-	while ((ret = xfs_bulkstat(fsfd,
-				&lastino, GRABSZ, &buf[0], &buflenout)) == 0) {
+	while ((ret = xfrog_bulkstat(&fsxfd, &lastino, GRABSZ, &buf[0],
+				&buflenout)) == 0) {
 		struct xfs_bstat *p;
 		struct xfs_bstat *endp;
 
@@ -685,16 +661,16 @@ fsrfs(char *mntdir, xfs_ino_t startino, int targetrange)
 		}
 		if (endtime && endtime < time(NULL)) {
 			tmp_close(mntdir);
-			close(fsfd);
+			xfd_close(&fsxfd);
 			fsrall_cleanup(1);
 			exit(1);
 		}
 	}
-	if (ret < 0)
-		fsrprintf(_("%s: xfs_bulkstat: %s\n"), progname, strerror(errno));
+	if (ret)
+		fsrprintf(_("%s: bulkstat: %s\n"), progname, strerror(ret));
 out0:
 	tmp_close(mntdir);
-	close(fsfd);
+	xfd_close(&fsxfd);
 	free(fshandlep);
 	return 0;
 }
@@ -727,13 +703,16 @@ fsrdir(char *dirname)
  * an open on the file and passes this all to fsrfile_common.
  */
 static int
-fsrfile(char *fname, xfs_ino_t ino)
+fsrfile(
+	char			*fname,
+	xfs_ino_t		ino)
 {
-	struct xfs_bstat statbuf;
-	jdm_fshandle_t	*fshandlep;
-	int	fd = -1, fsfd = -1;
-	int	error = -1;
-	char	*tname;
+	struct xfs_fd		fsxfd = XFS_FD_INIT_EMPTY;
+	struct xfs_bstat	statbuf;
+	jdm_fshandle_t		*fshandlep;
+	int			fd = -1;
+	int			error = -1;
+	char			*tname;
 
 	fshandlep = jdm_getfshandle(getparent (fname) );
 	if (!fshandlep) {
@@ -746,16 +725,23 @@ fsrfile(char *fname, xfs_ino_t ino)
 	 * Need to open something on the same filesystem as the
 	 * file.  Open the parent.
 	 */
-	fsfd = open(getparent(fname), O_RDONLY);
-	if (fsfd < 0) {
+	fsxfd.fd = open(getparent(fname), O_RDONLY);
+	if (fsxfd.fd < 0) {
 		fsrprintf(_("unable to open sys handle for %s: %s\n"),
 			fname, strerror(errno));
 		goto out;
 	}
 
-	if ((xfs_bulkstat_single(fsfd, &ino, &statbuf)) < 0) {
+	error = xfd_prepare_geometry(&fsxfd);
+	if (error) {
+		fsrprintf(_("Unable to get geom on fs for: %s\n"), fname);
+		goto out;
+	}
+
+	error = xfrog_bulkstat_single(&fsxfd, ino, &statbuf);
+	if (error) {
 		fsrprintf(_("unable to get bstat on %s: %s\n"),
-			fname, strerror(errno));
+			fname, strerror(error));
 		goto out;
 	}
 
@@ -766,12 +752,8 @@ fsrfile(char *fname, xfs_ino_t ino)
 		goto out;
 	}
 
-	/* Get the fs geometry */
-	error = xfrog_geometry(fsfd, &fsgeom);
-	if (error) {
-		fsrprintf(_("Unable to get geom on fs for: %s\n"), fname);
-		goto out;
-	}
+	/* Stash the fs geometry for general use. */
+	memcpy(&fsgeom, &fsxfd.fsgeom, sizeof(fsgeom));
 
 	tname = gettmpname(fname);
 
@@ -779,8 +761,7 @@ fsrfile(char *fname, xfs_ino_t ino)
 		error = fsrfile_common(fname, tname, NULL, fd, &statbuf);
 
 out:
-	if (fsfd >= 0)
-		close(fsfd);
+	xfd_close(&fsxfd);
 	if (fd >= 0)
 		close(fd);
 	free(fshandlep);
@@ -947,6 +928,7 @@ fsr_setup_attr_fork(
 	struct xfs_bstat *bstatp)
 {
 #ifdef HAVE_FSETXATTR
+	struct xfs_fd	txfd = XFS_FD_INIT(tfd);
 	struct stat	tstatbuf;
 	int		i;
 	int		diff = 0;
@@ -964,7 +946,7 @@ fsr_setup_attr_fork(
 	if (!(fsgeom.flags & XFS_FSOP_GEOM_FLAGS_ATTR2) ||
 	    bstatp->bs_forkoff == 0) {
 		/* attr1 */
-		ret = fsetxattr(tfd, "user.X", "X", 1, XATTR_CREATE);
+		ret = fsetxattr(txfd.fd, "user.X", "X", 1, XATTR_CREATE);
 		if (ret) {
 			fsrprintf(_("could not set ATTR\n"));
 			return -1;
@@ -974,7 +956,7 @@ fsr_setup_attr_fork(
 
 	/* attr2 w/ fork offsets */
 
-	if (fstat(tfd, &tstatbuf) < 0) {
+	if (fstat(txfd.fd, &tstatbuf) < 0) {
 		fsrprintf(_("unable to stat temp file: %s\n"),
 					strerror(errno));
 		return -1;
@@ -983,18 +965,18 @@ fsr_setup_attr_fork(
 	i = 0;
 	do {
 		struct xfs_bstat tbstat;
-		xfs_ino_t	ino;
 		char		name[64];
+		int		ret;
 
 		/*
 		 * bulkstat the temp inode to see what the forkoff is.  Use
 		 * this to compare against the target and determine what we
 		 * need to do.
 		 */
-		ino = tstatbuf.st_ino;
-		if ((xfs_bulkstat_single(tfd, &ino, &tbstat)) < 0) {
+		ret = xfrog_bulkstat_single(&txfd, tstatbuf.st_ino, &tbstat);
+		if (ret) {
 			fsrprintf(_("unable to get bstat on temp file: %s\n"),
-						strerror(errno));
+						strerror(ret));
 			return -1;
 		}
 		if (dflag)
@@ -1014,7 +996,7 @@ fsr_setup_attr_fork(
 		 */
 		if (!tbstat.bs_forkoff) {
 			ASSERT(i == 0);
-			ret = fsetxattr(tfd, name, "XX", 2, XATTR_CREATE);
+			ret = fsetxattr(txfd.fd, name, "XX", 2, XATTR_CREATE);
 			if (ret) {
 				fsrprintf(_("could not set ATTR\n"));
 				return -1;
@@ -1050,7 +1032,7 @@ fsr_setup_attr_fork(
 			if (diff < 0) {
 				char val[2048];
 				memset(val, 'X', 2048);
-				if (fsetxattr(tfd, name, val, 2048, 0)) {
+				if (fsetxattr(txfd.fd, name, val, 2048, 0)) {
 					fsrprintf(_("big ATTR set failed\n"));
 					return -1;
 				}
@@ -1094,7 +1076,7 @@ fsr_setup_attr_fork(
 		}
 
 		/* we need to grow the attr fork, so create another attr */
-		ret = fsetxattr(tfd, name, "XX", 2, XATTR_CREATE);
+		ret = fsetxattr(txfd.fd, name, "XX", 2, XATTR_CREATE);
 		if (ret) {
 			fsrprintf(_("could not set ATTR\n"));
 			return -1;
diff --git a/include/xfrog.h b/include/xfrog.h
index a08f6464..7bda9810 100644
--- a/include/xfrog.h
+++ b/include/xfrog.h
@@ -108,4 +108,11 @@ cvt_b_to_off_fsbt(
 	return bytes >> xfd->blocklog;
 }
 
+/* Bulkstat wrappers */
+struct xfs_bstat;
+int xfrog_bulkstat_single(struct xfs_fd *xfd, uint64_t ino,
+		struct xfs_bstat *ubuffer);
+int xfrog_bulkstat(struct xfs_fd *xfd, uint64_t *lastino, uint32_t icount,
+		struct xfs_bstat *ubuffer, uint32_t *ocount);
+
 #endif	/* __XFROG_H__ */
diff --git a/io/open.c b/io/open.c
index 8b24a4f9..35e6131b 100644
--- a/io/open.c
+++ b/io/open.c
@@ -719,19 +719,18 @@ get_last_inode(void)
 
 static int
 inode_f(
-	  int			argc,
-	  char			**argv)
+	int			argc,
+	char			**argv)
 {
-	__s32			count = 0;
-	__u64			result_ino = 0;
-	__u64			userino = NULLFSINO;
+	struct xfs_bstat	bstat;
+	uint32_t		count = 0;
+	uint64_t		result_ino = 0;
+	uint64_t		userino = NULLFSINO;
 	char			*p;
 	int			c;
 	int			verbose = 0;
 	int			ret_next = 0;
-	int			cmd = 0;
-	struct xfs_fsop_bulkreq	bulkreq;
-	struct xfs_bstat	bstat;
+	int			ret;
 
 	while ((c = getopt(argc, argv, "nv")) != EOF) {
 		switch (c) {
@@ -773,35 +772,38 @@ inode_f(
 			exitcode = 1;
 			return 0;
 		}
+	} else if (ret_next) {
+		struct xfs_fd	xfd = XFS_FD_INIT(file->fd);
+
+		/* get next inode */
+		ret = xfrog_bulkstat(&xfd, &userino, 1, &bstat, &count);
+		if (ret) {
+			errno = ret;
+			perror("bulkstat");
+			exitcode = 1;
+			return 0;
+		}
+
+		/* The next inode in use, or 0 if none */
+		if (count)
+			result_ino = bstat.bs_ino;
+		else
+			result_ino = 0;
 	} else {
-		if (ret_next)	/* get next inode */
-			cmd = XFS_IOC_FSBULKSTAT;
-		else		/* get this inode */
-			cmd = XFS_IOC_FSBULKSTAT_SINGLE;
-
-		bulkreq.lastip = &userino;
-		bulkreq.icount = 1;
-		bulkreq.ubuffer = &bstat;
-		bulkreq.ocount = &count;
-
-		if (xfsctl(file->name, file->fd, cmd, &bulkreq)) {
-			if (!ret_next && errno == EINVAL) {
-				/* Not in use */
-				result_ino = 0;
-			} else {
-				perror("xfsctl");
-				exitcode = 1;
-				return 0;
-			}
-		} else if (ret_next) {
-			/* The next inode in use, or 0 if none */
-			if (*bulkreq.ocount)
-				result_ino = bstat.bs_ino;
-			else
-				result_ino = 0;
+		struct xfs_fd	xfd = XFS_FD_INIT(file->fd);
+
+		/* get this inode */
+		ret = xfrog_bulkstat_single(&xfd, userino, &bstat);
+		if (ret == EINVAL) {
+			/* Not in use */
+			result_ino = 0;
+		} else if (ret) {
+			errno = ret;
+			perror("bulkstat_single");
+			exitcode = 1;
+			return 0;
 		} else {
-			/* The inode we asked about */
-			result_ino = userino;
+			result_ino = bstat.bs_ino;
 		}
 	}
 
diff --git a/io/swapext.c b/io/swapext.c
index d360c221..fbf4fff5 100644
--- a/io/swapext.c
+++ b/io/swapext.c
@@ -8,6 +8,7 @@
 #include "input.h"
 #include "init.h"
 #include "io.h"
+#include "xfrog.h"
 
 static cmdinfo_t swapext_cmd;
 
@@ -20,26 +21,12 @@ swapext_help(void)
 "\n"));
 }
 
-static int
-xfs_bulkstat_single(
-	int			fd,
-	xfs_ino_t		*lastip,
-	struct xfs_bstat	*ubuffer)
-{
-	struct xfs_fsop_bulkreq	bulkreq;
-
-	bulkreq.lastip = (__u64 *)lastip;
-	bulkreq.icount = 1;
-	bulkreq.ubuffer = ubuffer;
-	bulkreq.ocount = NULL;
-	return ioctl(fd, XFS_IOC_FSBULKSTAT_SINGLE, &bulkreq);
-}
-
 static int
 swapext_f(
 	int			argc,
 	char			**argv)
 {
+	struct xfs_fd		fxfd = XFS_FD_INIT(file->fd);
 	int			fd;
 	int			error;
 	struct xfs_swapext	sx;
@@ -60,8 +47,9 @@ swapext_f(
 		goto out;
 	}
 
-	error = xfs_bulkstat_single(file->fd, &stat.st_ino, &sx.sx_stat);
+	error = xfrog_bulkstat_single(&fxfd, stat.st_ino, &sx.sx_stat);
 	if (error) {
+		errno = error;
 		perror("bulkstat");
 		goto out;
 	}
diff --git a/libfrog/Makefile b/libfrog/Makefile
index f5a0539b..05c6f701 100644
--- a/libfrog/Makefile
+++ b/libfrog/Makefile
@@ -13,6 +13,7 @@ LT_AGE = 0
 CFILES = \
 avl64.c \
 bitmap.c \
+bulkstat.c \
 convert.c \
 crc32.c \
 fsgeom.c \
diff --git a/libfrog/bulkstat.c b/libfrog/bulkstat.c
new file mode 100644
index 00000000..0e11ccea
--- /dev/null
+++ b/libfrog/bulkstat.c
@@ -0,0 +1,52 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Copyright (C) 2019 Oracle.  All Rights Reserved.
+ * Author: Darrick J. Wong <darrick.wong@oracle.com>
+ */
+#include "xfs.h"
+#include "xfrog.h"
+
+/* Bulkstat a single inode.  Returns zero or a positive error code. */
+int
+xfrog_bulkstat_single(
+	struct xfs_fd		*xfd,
+	uint64_t		ino,
+	struct xfs_bstat	*ubuffer)
+{
+	__u64			i = ino;
+	struct xfs_fsop_bulkreq	bulkreq = {
+		.lastip		= &i,
+		.icount		= 1,
+		.ubuffer	= ubuffer,
+		.ocount		= NULL,
+	};
+	int			ret;
+
+	ret = ioctl(xfd->fd, XFS_IOC_FSBULKSTAT_SINGLE, &bulkreq);
+	if (ret)
+		return errno;
+	return 0;
+}
+
+/* Bulkstat a bunch of inodes.  Returns zero or a positive error code. */
+int
+xfrog_bulkstat(
+	struct xfs_fd		*xfd,
+	uint64_t		*lastino,
+	uint32_t		icount,
+	struct xfs_bstat	*ubuffer,
+	uint32_t		*ocount)
+{
+	struct xfs_fsop_bulkreq	bulkreq = {
+		.lastip		= (__u64 *)lastino,
+		.icount		= icount,
+		.ubuffer	= ubuffer,
+		.ocount		= (__s32 *)ocount,
+	};
+	int			ret;
+
+	ret = ioctl(xfd->fd, XFS_IOC_FSBULKSTAT, &bulkreq);
+	if (ret)
+		return errno;
+	return 0;
+}
diff --git a/quota/quot.c b/quota/quot.c
index 6bc91171..1e970819 100644
--- a/quota/quot.c
+++ b/quota/quot.c
@@ -11,6 +11,7 @@
 #include <grp.h>
 #include "init.h"
 #include "quota.h"
+#include "xfrog.h"
 
 typedef struct du {
 	struct du	*next;
@@ -124,13 +125,13 @@ quot_bulkstat_add(
 static void
 quot_bulkstat_mount(
 	char			*fsdir,
-	uint			flags)
+	unsigned int		flags)
 {
-	struct xfs_fsop_bulkreq	bulkreq;
+	struct xfs_fd		fsxfd = XFS_FD_INIT_EMPTY;
 	struct xfs_bstat	*buf;
-	__u64			last = 0;
-	__s32			count;
-	int			i, sts, fsfd;
+	uint64_t		last = 0;
+	uint32_t		count;
+	int			i, sts;
 	du_t			**dp;
 
 	/*
@@ -145,8 +146,8 @@ quot_bulkstat_mount(
 			*dp = NULL;
 	ndu[0] = ndu[1] = ndu[2] = 0;
 
-	fsfd = open(fsdir, O_RDONLY);
-	if (fsfd < 0) {
+	fsxfd.fd = open(fsdir, O_RDONLY);
+	if (fsxfd.fd < 0) {
 		perror(fsdir);
 		return;
 	}
@@ -154,25 +155,23 @@ quot_bulkstat_mount(
 	buf = (struct xfs_bstat *)calloc(NBSTAT, sizeof(struct xfs_bstat));
 	if (!buf) {
 		perror("calloc");
-		close(fsfd);
+		xfd_close(&fsxfd);
 		return;
 	}
 
-	bulkreq.lastip = &last;
-	bulkreq.icount = NBSTAT;
-	bulkreq.ubuffer = buf;
-	bulkreq.ocount = &count;
-
-	while ((sts = xfsctl(fsdir, fsfd, XFS_IOC_FSBULKSTAT, &bulkreq)) == 0) {
+	while ((sts = xfrog_bulkstat(&fsxfd, &last, NBSTAT, buf,
+				&count)) == 0) {
 		if (count == 0)
 			break;
 		for (i = 0; i < count; i++)
 			quot_bulkstat_add(&buf[i], flags);
 	}
-	if (sts < 0)
-		perror("XFS_IOC_FSBULKSTAT"),
+	if (sts < 0) {
+		errno = sts;
+		perror("XFS_IOC_FSBULKSTAT");
+	}
 	free(buf);
-	close(fsfd);
+	xfd_close(&fsxfd);
 }
 
 static int
diff --git a/scrub/inodes.c b/scrub/inodes.c
index 700e5200..f5cbaa5b 100644
--- a/scrub/inodes.c
+++ b/scrub/inodes.c
@@ -17,6 +17,7 @@
 #include "xfs_scrub.h"
 #include "common.h"
 #include "inodes.h"
+#include "xfrog.h"
 
 /*
  * Iterate a range of inodes.
@@ -50,17 +51,10 @@ xfs_iterate_inodes_range_check(
 	struct xfs_inogrp	*inogrp,
 	struct xfs_bstat	*bstat)
 {
-	struct xfs_fsop_bulkreq	onereq = {NULL};
 	struct xfs_bstat	*bs;
-	__u64			oneino;
-	__s32			onelen = 0;
 	int			i;
 	int			error;
 
-	onereq.lastip  = &oneino;
-	onereq.icount  = 1;
-	onereq.ocount  = &onelen;
-
 	for (i = 0, bs = bstat; i < XFS_INODES_PER_CHUNK; i++) {
 		if (!(inogrp->xi_allocmask & (1ULL << i)))
 			continue;
@@ -70,10 +64,8 @@ xfs_iterate_inodes_range_check(
 		}
 
 		/* Load the one inode. */
-		oneino = inogrp->xi_startino + i;
-		onereq.ubuffer = bs;
-		error = ioctl(ctx->mnt.fd, XFS_IOC_FSBULKSTAT_SINGLE,
-				&onereq);
+		error = xfrog_bulkstat_single(&ctx->mnt,
+				inogrp->xi_startino + i, bs);
 		if (error || bs->bs_ino != inogrp->xi_startino + i) {
 			memset(bs, 0, sizeof(struct xfs_bstat));
 			bs->bs_ino = inogrp->xi_startino + i;
@@ -99,16 +91,14 @@ xfs_iterate_inodes_range(
 	void			*arg)
 {
 	struct xfs_fsop_bulkreq	igrpreq = {NULL};
-	struct xfs_fsop_bulkreq	bulkreq = {NULL};
 	struct xfs_handle	handle;
 	struct xfs_inogrp	inogrp;
 	struct xfs_bstat	bstat[XFS_INODES_PER_CHUNK];
 	char			idescr[DESCR_BUFSZ];
-	char			buf[DESCR_BUFSZ];
 	struct xfs_bstat	*bs;
 	__u64			igrp_ino;
-	__u64			ino;
-	__s32			bulklen = 0;
+	uint64_t		ino;
+	uint32_t		bulklen = 0;
 	__s32			igrplen = 0;
 	bool			moveon = true;
 	int			i;
@@ -117,10 +107,6 @@ xfs_iterate_inodes_range(
 
 
 	memset(bstat, 0, XFS_INODES_PER_CHUNK * sizeof(struct xfs_bstat));
-	bulkreq.lastip  = &ino;
-	bulkreq.icount  = XFS_INODES_PER_CHUNK;
-	bulkreq.ubuffer = &bstat;
-	bulkreq.ocount  = &bulklen;
 
 	igrpreq.lastip  = &igrp_ino;
 	igrpreq.icount  = 1;
@@ -138,17 +124,21 @@ xfs_iterate_inodes_range(
 	while (!error && igrplen) {
 		/* Load the inodes. */
 		ino = inogrp.xi_startino - 1;
-		bulkreq.icount = inogrp.xi_alloccount;
+
 		/*
 		 * We can have totally empty inode chunks on filesystems where
 		 * there are more than 64 inodes per block.  Skip these.
 		 */
 		if (inogrp.xi_alloccount == 0)
 			goto igrp_retry;
-		error = ioctl(ctx->mnt.fd, XFS_IOC_FSBULKSTAT, &bulkreq);
-		if (error)
-			str_info(ctx, descr, "%s", strerror_r(errno,
-						buf, DESCR_BUFSZ));
+		error = xfrog_bulkstat(&ctx->mnt, &ino, inogrp.xi_alloccount,
+				bstat, &bulklen);
+		if (error) {
+			char	errbuf[DESCR_BUFSZ];
+
+			str_info(ctx, descr, "%s", strerror_r(error,
+						errbuf, DESCR_BUFSZ));
+		}
 
 		xfs_iterate_inodes_range_check(ctx, &inogrp, bstat);
 

^ permalink raw reply related	[flat|nested] 31+ messages in thread

* Re: [PATCH 6/9] libfrog: create online fs geometry converters
  2019-08-30  4:21 ` [PATCH 6/9] libfrog: create online fs geometry converters Darrick J. Wong
@ 2019-08-31  5:11   ` Allison Collins
  2019-09-03 22:55   ` Dave Chinner
  1 sibling, 0 replies; 31+ messages in thread
From: Allison Collins @ 2019-08-31  5:11 UTC (permalink / raw)
  To: Darrick J. Wong, sandeen; +Cc: linux-xfs

On 8/29/19 9:21 PM, Darrick J. Wong wrote:
> From: Darrick J. Wong <darrick.wong@oracle.com>
> 
> Create helper functions to perform unit conversions against a runtime
> filesystem, then remove the open-coded versions in scrub.
> 
> Signed-off-by: Darrick J. Wong <darrick.wong@oracle.com>
Looks good.  I think the helpers make the logic more readable.

Reviewed-by: Allison Collins <allison.henderson@oracle.com>

> ---
>   include/xfrog.h    |   57 ++++++++++++++++++++++++++++++++++++++++++++++++++++
>   libfrog/fsgeom.c   |    1 +
>   scrub/fscounters.c |    4 ++--
>   scrub/inodes.c     |    4 ++--
>   scrub/phase3.c     |    6 +++--
>   scrub/phase5.c     |    4 ++--
>   scrub/phase6.c     |    3 ++-
>   scrub/phase7.c     |    6 +++--
>   8 files changed, 72 insertions(+), 13 deletions(-)
> 
> 
> diff --git a/include/xfrog.h b/include/xfrog.h
> index 008cc155..a08f6464 100644
> --- a/include/xfrog.h
> +++ b/include/xfrog.h
> @@ -42,6 +42,9 @@ struct xfs_fd {
>   
>   	/* log2 of sb_inopblock */
>   	unsigned int		inopblog;
> +
> +	/* bits for agino in inum */
> +	unsigned int		aginolog;
>   };
>   
>   /* Static initializers */
> @@ -51,4 +54,58 @@ struct xfs_fd {
>   int xfd_prepare_geometry(struct xfs_fd *xfd);
>   int xfd_close(struct xfs_fd *xfd);
>   
> +/* Convert AG number and AG inode number into fs inode number. */
> +static inline uint64_t
> +cvt_agino_to_ino(
> +	const struct xfs_fd	*xfd,
> +	uint32_t		agno,
> +	uint32_t		agino)
> +{
> +	return ((uint64_t)agno << xfd->aginolog) + agino;
> +}
> +
> +/* Convert fs inode number into AG number. */
> +static inline uint32_t
> +cvt_ino_to_agno(
> +	const struct xfs_fd	*xfd,
> +	uint64_t		ino)
> +{
> +	return ino >> xfd->aginolog;
> +}
> +
> +/* Convert fs inode number into AG inode number. */
> +static inline uint32_t
> +cvt_ino_to_agino(
> +	const struct xfs_fd	*xfd,
> +	uint64_t		ino)
> +{
> +	return ino & ((1ULL << xfd->aginolog) - 1);
> +}
> +
> +/*
> + * Convert a linear fs block offset number into bytes.  This is the runtime
> + * equivalent of XFS_FSB_TO_B, which means that it is /not/ for segmented fsbno
> + * format (= agno | agbno) that we use internally for the data device.
> + */
> +static inline uint64_t
> +cvt_off_fsb_to_b(
> +	const struct xfs_fd	*xfd,
> +	uint64_t		fsb)
> +{
> +	return fsb << xfd->blocklog;
> +}
> +
> +/*
> + * Convert bytes into a (rounded down) linear fs block offset number.  This is
> + * the runtime equivalent of XFS_B_TO_FSBT.  It does not produce segmented
> + * fsbno numbers (= agno | agbno).
> + */
> +static inline uint64_t
> +cvt_b_to_off_fsbt(
> +	const struct xfs_fd	*xfd,
> +	uint64_t		bytes)
> +{
> +	return bytes >> xfd->blocklog;
> +}
> +
>   #endif	/* __XFROG_H__ */
> diff --git a/libfrog/fsgeom.c b/libfrog/fsgeom.c
> index b8873598..cf9323c1 100644
> --- a/libfrog/fsgeom.c
> +++ b/libfrog/fsgeom.c
> @@ -113,6 +113,7 @@ xfd_prepare_geometry(
>   	xfd->blocklog = highbit32(xfd->fsgeom.blocksize);
>   	xfd->inodelog = highbit32(xfd->fsgeom.inodesize);
>   	xfd->inopblog = xfd->blocklog - xfd->inodelog;
> +	xfd->aginolog = xfd->agblklog + xfd->inopblog;
>   	return 0;
>   }
>   
> diff --git a/scrub/fscounters.c b/scrub/fscounters.c
> index ac898764..ea6af156 100644
> --- a/scrub/fscounters.c
> +++ b/scrub/fscounters.c
> @@ -91,8 +91,8 @@ xfs_count_ag_inodes(
>   				minor(ctx->fsinfo.fs_datadev),
>   				agno);
>   
> -	ag_ino = (__u64)agno << (ctx->mnt.inopblog + ctx->mnt.agblklog);
> -	next_ag_ino = (__u64)(agno + 1) << (ctx->mnt.inopblog + ctx->mnt.agblklog);
> +	ag_ino = cvt_agino_to_ino(&ctx->mnt, agno, 0);
> +	next_ag_ino = cvt_agino_to_ino(&ctx->mnt, agno + 1, 0);
>   
>   	moveon = xfs_count_inodes_range(ctx, descr, ag_ino, next_ag_ino - 1,
>   			&ci->counters[agno]);
> diff --git a/scrub/inodes.c b/scrub/inodes.c
> index 873ad425..700e5200 100644
> --- a/scrub/inodes.c
> +++ b/scrub/inodes.c
> @@ -228,8 +228,8 @@ xfs_scan_ag_inodes(
>   				minor(ctx->fsinfo.fs_datadev),
>   				agno);
>   
> -	ag_ino = (__u64)agno << (ctx->mnt.inopblog + ctx->mnt.agblklog);
> -	next_ag_ino = (__u64)(agno + 1) << (ctx->mnt.inopblog + ctx->mnt.agblklog);
> +	ag_ino = cvt_agino_to_ino(&ctx->mnt, agno, 0);
> +	next_ag_ino = cvt_agino_to_ino(&ctx->mnt, agno + 1, 0);
>   
>   	moveon = xfs_iterate_inodes_range(ctx, descr, ctx->fshandle, ag_ino,
>   			next_ag_ino - 1, si->fn, si->arg);
> diff --git a/scrub/phase3.c b/scrub/phase3.c
> index 579e08c3..8c02f1cb 100644
> --- a/scrub/phase3.c
> +++ b/scrub/phase3.c
> @@ -52,8 +52,8 @@ xfs_scrub_inode_vfs_error(
>   	xfs_agino_t		agino;
>   	int			old_errno = errno;
>   
> -	agno = bstat->bs_ino / (1ULL << (ctx->mnt.inopblog + ctx->mnt.agblklog));
> -	agino = bstat->bs_ino % (1ULL << (ctx->mnt.inopblog + ctx->mnt.agblklog));
> +	agno = cvt_ino_to_agno(&ctx->mnt, bstat->bs_ino);
> +	agino = cvt_ino_to_agino(&ctx->mnt, bstat->bs_ino);
>   	snprintf(descr, DESCR_BUFSZ, _("inode %"PRIu64" (%u/%u)"),
>   			(uint64_t)bstat->bs_ino, agno, agino);
>   	errno = old_errno;
> @@ -77,7 +77,7 @@ xfs_scrub_inode(
>   	int			error;
>   
>   	xfs_action_list_init(&alist);
> -	agno = bstat->bs_ino / (1ULL << (ctx->mnt.inopblog + ctx->mnt.agblklog));
> +	agno = cvt_ino_to_agno(&ctx->mnt, bstat->bs_ino);
>   	background_sleep();
>   
>   	/* Try to open the inode to pin it. */
> diff --git a/scrub/phase5.c b/scrub/phase5.c
> index 36ec27b3..f3ee22e6 100644
> --- a/scrub/phase5.c
> +++ b/scrub/phase5.c
> @@ -239,8 +239,8 @@ xfs_scrub_connections(
>   	int			fd = -1;
>   	int			error;
>   
> -	agno = bstat->bs_ino / (1ULL << (ctx->mnt.inopblog + ctx->mnt.agblklog));
> -	agino = bstat->bs_ino % (1ULL << (ctx->mnt.inopblog + ctx->mnt.agblklog));
> +	agno = cvt_ino_to_agno(&ctx->mnt, bstat->bs_ino);
> +	agino = cvt_ino_to_agino(&ctx->mnt, bstat->bs_ino);
>   	snprintf(descr, DESCR_BUFSZ, _("inode %"PRIu64" (%u/%u)"),
>   			(uint64_t)bstat->bs_ino, agno, agino);
>   	background_sleep();
> diff --git a/scrub/phase6.c b/scrub/phase6.c
> index 48971270..5628b926 100644
> --- a/scrub/phase6.c
> +++ b/scrub/phase6.c
> @@ -547,7 +547,8 @@ xfs_estimate_verify_work(
>   	if (!moveon)
>   		return moveon;
>   
> -	*items = ((d_blocks - d_bfree) + (r_blocks - r_bfree)) << ctx->mnt.blocklog;
> +	*items = cvt_off_fsb_to_b(&ctx->mnt,
> +			(d_blocks - d_bfree) + (r_blocks - r_bfree));
>   	*nr_threads = disk_heads(ctx->datadev);
>   	*rshift = 20;
>   	return moveon;
> diff --git a/scrub/phase7.c b/scrub/phase7.c
> index 41a77356..8a028e19 100644
> --- a/scrub/phase7.c
> +++ b/scrub/phase7.c
> @@ -148,11 +148,11 @@ xfs_scan_summary(
>   	 * filesystem treats them as "free", but since we scanned
>   	 * them, we'll consider them used.
>   	 */
> -	d_bfree -= totalcount.agbytes >> ctx->mnt.blocklog;
> +	d_bfree -= cvt_b_to_off_fsbt(&ctx->mnt, totalcount.agbytes);
>   
>   	/* Report on what we found. */
> -	used_data = (d_blocks - d_bfree) << ctx->mnt.blocklog;
> -	used_rt = (r_blocks - r_bfree) << ctx->mnt.blocklog;
> +	used_data = cvt_off_fsb_to_b(&ctx->mnt, d_blocks - d_bfree);
> +	used_rt = cvt_off_fsb_to_b(&ctx->mnt, r_blocks - r_bfree);
>   	used_files = f_files - f_free;
>   	stat_data = totalcount.dbytes;
>   	stat_rt = totalcount.rbytes;
> 

^ permalink raw reply	[flat|nested] 31+ messages in thread

* Re: [PATCH 7/9] libfrog: refactor open-coded bulkstat calls
  2019-08-30  4:21 ` [PATCH 7/9] libfrog: refactor open-coded bulkstat calls Darrick J. Wong
  2019-08-30 23:26   ` Darrick J. Wong
  2019-08-31  0:42   ` [PATCH v2 " Darrick J. Wong
@ 2019-09-01 20:55   ` Allison Collins
  2019-09-01 21:05     ` Darrick J. Wong
  2 siblings, 1 reply; 31+ messages in thread
From: Allison Collins @ 2019-09-01 20:55 UTC (permalink / raw)
  To: Darrick J. Wong, sandeen; +Cc: linux-xfs

On 8/29/19 9:21 PM, Darrick J. Wong wrote:
> From: Darrick J. Wong <darrick.wong@oracle.com>
> 
> Refactor the BULKSTAT_SINGLE and BULKSTAT ioctl callsites into helper
> functions.
> 
> Signed-off-by: Darrick J. Wong <darrick.wong@oracle.com>
> ---
>   fsr/xfs_fsr.c      |  110 ++++++++++++++++++++++------------------------------
>   include/xfrog.h    |    7 +++
>   io/open.c          |   72 +++++++++++++++++-----------------
>   io/swapext.c       |   20 ++-------
>   libfrog/Makefile   |    1
>   libfrog/bulkstat.c |   52 +++++++++++++++++++++++++
>   quota/quot.c       |   33 ++++++++--------
>   scrub/inodes.c     |   32 ++++-----------
>   8 files changed, 172 insertions(+), 155 deletions(-)
>   create mode 100644 libfrog/bulkstat.c
> 
> 
> diff --git a/fsr/xfs_fsr.c b/fsr/xfs_fsr.c
> index 4b239a30..36402252 100644
> --- a/fsr/xfs_fsr.c
> +++ b/fsr/xfs_fsr.c
> @@ -102,31 +102,6 @@ static int	nfrags = 0;	/* Debug option: Coerse into specific number
>   				 * of extents */
>   static int	openopts = O_CREAT|O_EXCL|O_RDWR|O_DIRECT;
>   
> -static int
> -xfs_bulkstat_single(int fd, xfs_ino_t *lastip, struct xfs_bstat *ubuffer)
> -{
> -    struct xfs_fsop_bulkreq  bulkreq;
> -
> -    bulkreq.lastip = (__u64 *)lastip;
> -    bulkreq.icount = 1;
> -    bulkreq.ubuffer = ubuffer;
> -    bulkreq.ocount = NULL;
> -    return ioctl(fd, XFS_IOC_FSBULKSTAT_SINGLE, &bulkreq);
> -}
> -
> -static int
> -xfs_bulkstat(int fd, xfs_ino_t *lastip, int icount,
> -                    struct xfs_bstat *ubuffer, __s32 *ocount)
> -{
> -    struct xfs_fsop_bulkreq  bulkreq;
> -
> -    bulkreq.lastip = (__u64 *)lastip;
> -    bulkreq.icount = icount;
> -    bulkreq.ubuffer = ubuffer;
> -    bulkreq.ocount = ocount;
> -    return ioctl(fd, XFS_IOC_FSBULKSTAT, &bulkreq);
> -}
> -
>   static int
>   xfs_swapext(int fd, xfs_swapext_t *sx)
>   {
> @@ -596,11 +571,11 @@ fsrall_cleanup(int timeout)
>   static int
>   fsrfs(char *mntdir, xfs_ino_t startino, int targetrange)
>   {
> -
> -	int	fsfd, fd;
> +	struct xfs_fd	fsxfd = XFS_FD_INIT_EMPTY;
> +	int	fd;
>   	int	count = 0;
>   	int	ret;
> -	__s32	buflenout;
> +	uint32_t buflenout;
>   	struct xfs_bstat buf[GRABSZ];
>   	char	fname[64];
>   	char	*tname;
> @@ -617,26 +592,27 @@ fsrfs(char *mntdir, xfs_ino_t startino, int targetrange)
>   		return -1;
>   	}
>   
> -	if ((fsfd = open(mntdir, O_RDONLY)) < 0) {
> +	if ((fsxfd.fd = open(mntdir, O_RDONLY)) < 0) {
>   		fsrprintf(_("unable to open: %s: %s\n"),
>   		          mntdir, strerror( errno ));
>   		free(fshandlep);
>   		return -1;
>   	}
>   
> -	ret = xfrog_geometry(fsfd, &fsgeom);
> +	ret = xfd_prepare_geometry(&fsxfd);
>   	if (ret) {
>   		fsrprintf(_("Skipping %s: could not get XFS geometry\n"),
>   			  mntdir);
> -		close(fsfd);
> +		xfd_close(&fsxfd);
>   		free(fshandlep);
>   		return -1;
>   	}
> +	memcpy(&fsgeom, &fsxfd.fsgeom, sizeof(fsgeom));
>   
>   	tmp_init(mntdir);
>   
> -	while ((ret = xfs_bulkstat(fsfd,
> -				&lastino, GRABSZ, &buf[0], &buflenout)) == 0) {
> +	while ((ret = xfrog_bulkstat(&fsxfd, &lastino, GRABSZ, &buf[0],
> +				&buflenout)) == 0) {
>   		struct xfs_bstat *p;
>   		struct xfs_bstat *endp;
>   
> @@ -685,16 +661,16 @@ fsrfs(char *mntdir, xfs_ino_t startino, int targetrange)
>   		}
>   		if (endtime && endtime < time(NULL)) {
>   			tmp_close(mntdir);
> -			close(fsfd);
> +			xfd_close(&fsxfd);
>   			fsrall_cleanup(1);
>   			exit(1);
>   		}
>   	}
> -	if (ret < 0)
> -		fsrprintf(_("%s: xfs_bulkstat: %s\n"), progname, strerror(errno));
> +	if (ret)
> +		fsrprintf(_("%s: bulkstat: %s\n"), progname, strerror(ret));
>   out0:
>   	tmp_close(mntdir);
> -	close(fsfd);
> +	xfd_close(&fsxfd);
>   	free(fshandlep);
>   	return 0;
>   }
> @@ -727,13 +703,16 @@ fsrdir(char *dirname)
>    * an open on the file and passes this all to fsrfile_common.
>    */
>   static int
> -fsrfile(char *fname, xfs_ino_t ino)
> +fsrfile(
> +	char			*fname,
> +	xfs_ino_t		ino)
>   {
> -	struct xfs_bstat statbuf;
> -	jdm_fshandle_t	*fshandlep;
> -	int	fd = -1, fsfd = -1;
> -	int	error = -1;
> -	char	*tname;
> +	struct xfs_fd		fsxfd = XFS_FD_INIT_EMPTY;
> +	struct xfs_bstat	statbuf;
> +	jdm_fshandle_t		*fshandlep;
> +	int			fd = -1;
> +	int			error = -1;
> +	char			*tname;
>   
>   	fshandlep = jdm_getfshandle(getparent (fname) );
>   	if (!fshandlep) {
> @@ -746,16 +725,23 @@ fsrfile(char *fname, xfs_ino_t ino)
>   	 * Need to open something on the same filesystem as the
>   	 * file.  Open the parent.
>   	 */
> -	fsfd = open(getparent(fname), O_RDONLY);
> -	if (fsfd < 0) {
> +	fsxfd.fd = open(getparent(fname), O_RDONLY);
> +	if (fsxfd.fd < 0) {
>   		fsrprintf(_("unable to open sys handle for %s: %s\n"),
>   			fname, strerror(errno));
>   		goto out;
>   	}
>   
> -	if ((xfs_bulkstat_single(fsfd, &ino, &statbuf)) < 0) {
> +	error = xfd_prepare_geometry(&fsxfd);
> +	if (error) {
> +		fsrprintf(_("Unable to get geom on fs for: %s\n"), fname);
> +		goto out;
> +	}
> +
> +	error = xfrog_bulkstat_single(&fsxfd, ino, &statbuf);
> +	if (error) {
>   		fsrprintf(_("unable to get bstat on %s: %s\n"),
> -			fname, strerror(errno));
> +			fname, strerror(error));
>   		goto out;
>   	}
>   
> @@ -766,12 +752,8 @@ fsrfile(char *fname, xfs_ino_t ino)
>   		goto out;
>   	}
>   
> -	/* Get the fs geometry */
> -	error = xfrog_geometry(fsfd, &fsgeom);
> -	if (error) {
> -		fsrprintf(_("Unable to get geom on fs for: %s\n"), fname);
> -		goto out;
> -	}
> +	/* Stash the fs geometry for general use. */
> +	memcpy(&fsgeom, &fsxfd.fsgeom, sizeof(fsgeom));

Just a nit: Why the memcpy here instead of making a general use pointer?

Otherwise looks like a lot of good clean up
Reviewed-by: Allison Collins <allison.henderson@oracle.com>

>   
>   	tname = gettmpname(fname);
>   
> @@ -779,8 +761,7 @@ fsrfile(char *fname, xfs_ino_t ino)
>   		error = fsrfile_common(fname, tname, NULL, fd, &statbuf);
>   
>   out:
> -	if (fsfd >= 0)
> -		close(fsfd);
> +	xfd_close(&fsxfd);
>   	if (fd >= 0)
>   		close(fd);
>   	free(fshandlep);
> @@ -947,6 +928,7 @@ fsr_setup_attr_fork(
>   	struct xfs_bstat *bstatp)
>   {
>   #ifdef HAVE_FSETXATTR
> +	struct xfs_fd	txfd = XFS_FD_INIT(tfd);
>   	struct stat	tstatbuf;
>   	int		i;
>   	int		diff = 0;
> @@ -964,7 +946,7 @@ fsr_setup_attr_fork(
>   	if (!(fsgeom.flags & XFS_FSOP_GEOM_FLAGS_ATTR2) ||
>   	    bstatp->bs_forkoff == 0) {
>   		/* attr1 */
> -		ret = fsetxattr(tfd, "user.X", "X", 1, XATTR_CREATE);
> +		ret = fsetxattr(txfd.fd, "user.X", "X", 1, XATTR_CREATE);
>   		if (ret) {
>   			fsrprintf(_("could not set ATTR\n"));
>   			return -1;
> @@ -974,7 +956,7 @@ fsr_setup_attr_fork(
>   
>   	/* attr2 w/ fork offsets */
>   
> -	if (fstat(tfd, &tstatbuf) < 0) {
> +	if (fstat(txfd.fd, &tstatbuf) < 0) {
>   		fsrprintf(_("unable to stat temp file: %s\n"),
>   					strerror(errno));
>   		return -1;
> @@ -983,18 +965,18 @@ fsr_setup_attr_fork(
>   	i = 0;
>   	do {
>   		struct xfs_bstat tbstat;
> -		xfs_ino_t	ino;
>   		char		name[64];
> +		int		ret;
>   
>   		/*
>   		 * bulkstat the temp inode to see what the forkoff is.  Use
>   		 * this to compare against the target and determine what we
>   		 * need to do.
>   		 */
> -		ino = tstatbuf.st_ino;
> -		if ((xfs_bulkstat_single(tfd, &ino, &tbstat)) < 0) {
> +		ret = xfrog_bulkstat_single(&txfd, tstatbuf.st_ino, &tbstat);
> +		if (ret) {
>   			fsrprintf(_("unable to get bstat on temp file: %s\n"),
> -						strerror(errno));
> +						strerror(ret));
>   			return -1;
>   		}
>   		if (dflag)
> @@ -1014,7 +996,7 @@ fsr_setup_attr_fork(
>   		 */
>   		if (!tbstat.bs_forkoff) {
>   			ASSERT(i == 0);
> -			ret = fsetxattr(tfd, name, "XX", 2, XATTR_CREATE);
> +			ret = fsetxattr(txfd.fd, name, "XX", 2, XATTR_CREATE);
>   			if (ret) {
>   				fsrprintf(_("could not set ATTR\n"));
>   				return -1;
> @@ -1050,7 +1032,7 @@ fsr_setup_attr_fork(
>   			if (diff < 0) {
>   				char val[2048];
>   				memset(val, 'X', 2048);
> -				if (fsetxattr(tfd, name, val, 2048, 0)) {
> +				if (fsetxattr(txfd.fd, name, val, 2048, 0)) {
>   					fsrprintf(_("big ATTR set failed\n"));
>   					return -1;
>   				}
> @@ -1094,7 +1076,7 @@ fsr_setup_attr_fork(
>   		}
>   
>   		/* we need to grow the attr fork, so create another attr */
> -		ret = fsetxattr(tfd, name, "XX", 2, XATTR_CREATE);
> +		ret = fsetxattr(txfd.fd, name, "XX", 2, XATTR_CREATE);
>   		if (ret) {
>   			fsrprintf(_("could not set ATTR\n"));
>   			return -1;
> diff --git a/include/xfrog.h b/include/xfrog.h
> index a08f6464..7bda9810 100644
> --- a/include/xfrog.h
> +++ b/include/xfrog.h
> @@ -108,4 +108,11 @@ cvt_b_to_off_fsbt(
>   	return bytes >> xfd->blocklog;
>   }
>   
> +/* Bulkstat wrappers */
> +struct xfs_bstat;
> +int xfrog_bulkstat_single(struct xfs_fd *xfd, uint64_t ino,
> +		struct xfs_bstat *ubuffer);
> +int xfrog_bulkstat(struct xfs_fd *xfd, uint64_t *lastino, uint32_t icount,
> +		struct xfs_bstat *ubuffer, uint32_t *ocount);
> +
>   #endif	/* __XFROG_H__ */
> diff --git a/io/open.c b/io/open.c
> index 8b24a4f9..35e6131b 100644
> --- a/io/open.c
> +++ b/io/open.c
> @@ -719,19 +719,18 @@ get_last_inode(void)
>   
>   static int
>   inode_f(
> -	  int			argc,
> -	  char			**argv)
> +	int			argc,
> +	char			**argv)
>   {
> -	__s32			count = 0;
> -	__u64			result_ino = 0;
> -	__u64			userino = NULLFSINO;
> +	struct xfs_bstat	bstat;
> +	uint32_t		count = 0;
> +	uint64_t		result_ino = 0;
> +	uint64_t		userino = NULLFSINO;
>   	char			*p;
>   	int			c;
>   	int			verbose = 0;
>   	int			ret_next = 0;
> -	int			cmd = 0;
> -	struct xfs_fsop_bulkreq	bulkreq;
> -	struct xfs_bstat	bstat;
> +	int			ret;
>   
>   	while ((c = getopt(argc, argv, "nv")) != EOF) {
>   		switch (c) {
> @@ -773,35 +772,38 @@ inode_f(
>   			exitcode = 1;
>   			return 0;
>   		}
> +	} else if (ret_next) {
> +		struct xfs_fd	xfd = XFS_FD_INIT(file->fd);
> +
> +		/* get next inode */
> +		ret = xfrog_bulkstat(&xfd, &userino, 1, &bstat, &count);
> +		if (ret) {
> +			errno = ret;
> +			perror("bulkstat");
> +			exitcode = 1;
> +			return 0;
> +		}
> +
> +		/* The next inode in use, or 0 if none */
> +		if (count)
> +			result_ino = bstat.bs_ino;
> +		else
> +			result_ino = 0;
>   	} else {
> -		if (ret_next)	/* get next inode */
> -			cmd = XFS_IOC_FSBULKSTAT;
> -		else		/* get this inode */
> -			cmd = XFS_IOC_FSBULKSTAT_SINGLE;
> -
> -		bulkreq.lastip = &userino;
> -		bulkreq.icount = 1;
> -		bulkreq.ubuffer = &bstat;
> -		bulkreq.ocount = &count;
> -
> -		if (xfsctl(file->name, file->fd, cmd, &bulkreq)) {
> -			if (!ret_next && errno == EINVAL) {
> -				/* Not in use */
> -				result_ino = 0;
> -			} else {
> -				perror("xfsctl");
> -				exitcode = 1;
> -				return 0;
> -			}
> -		} else if (ret_next) {
> -			/* The next inode in use, or 0 if none */
> -			if (*bulkreq.ocount)
> -				result_ino = bstat.bs_ino;
> -			else
> -				result_ino = 0;
> +		struct xfs_fd	xfd = XFS_FD_INIT(file->fd);
> +
> +		/* get this inode */
> +		ret = xfrog_bulkstat_single(&xfd, userino, &bstat);
> +		if (ret == EINVAL) {
> +			/* Not in use */
> +			result_ino = 0;
> +		} else if (ret) {
> +			errno = ret;
> +			perror("bulkstat_single");
> +			exitcode = 1;
> +			return 0;
>   		} else {
> -			/* The inode we asked about */
> -			result_ino = userino;
> +			result_ino = bstat.bs_ino;
>   		}
>   	}
>   
> diff --git a/io/swapext.c b/io/swapext.c
> index d360c221..fbf4fff5 100644
> --- a/io/swapext.c
> +++ b/io/swapext.c
> @@ -8,6 +8,7 @@
>   #include "input.h"
>   #include "init.h"
>   #include "io.h"
> +#include "xfrog.h"
>   
>   static cmdinfo_t swapext_cmd;
>   
> @@ -20,26 +21,12 @@ swapext_help(void)
>   "\n"));
>   }
>   
> -static int
> -xfs_bulkstat_single(
> -	int			fd,
> -	xfs_ino_t		*lastip,
> -	struct xfs_bstat	*ubuffer)
> -{
> -	struct xfs_fsop_bulkreq	bulkreq;
> -
> -	bulkreq.lastip = (__u64 *)lastip;
> -	bulkreq.icount = 1;
> -	bulkreq.ubuffer = ubuffer;
> -	bulkreq.ocount = NULL;
> -	return ioctl(fd, XFS_IOC_FSBULKSTAT_SINGLE, &bulkreq);
> -}
> -
>   static int
>   swapext_f(
>   	int			argc,
>   	char			**argv)
>   {
> +	struct xfs_fd		fxfd = XFS_FD_INIT(file->fd);
>   	int			fd;
>   	int			error;
>   	struct xfs_swapext	sx;
> @@ -60,8 +47,9 @@ swapext_f(
>   		goto out;
>   	}
>   
> -	error = xfs_bulkstat_single(file->fd, &stat.st_ino, &sx.sx_stat);
> +	error = xfrog_bulkstat_single(&fxfd, stat.st_ino, &sx.sx_stat);
>   	if (error) {
> +		errno = error;
>   		perror("bulkstat");
>   		goto out;
>   	}
> diff --git a/libfrog/Makefile b/libfrog/Makefile
> index f5a0539b..05c6f701 100644
> --- a/libfrog/Makefile
> +++ b/libfrog/Makefile
> @@ -13,6 +13,7 @@ LT_AGE = 0
>   CFILES = \
>   avl64.c \
>   bitmap.c \
> +bulkstat.c \
>   convert.c \
>   crc32.c \
>   fsgeom.c \
> diff --git a/libfrog/bulkstat.c b/libfrog/bulkstat.c
> new file mode 100644
> index 00000000..0e11ccea
> --- /dev/null
> +++ b/libfrog/bulkstat.c
> @@ -0,0 +1,52 @@
> +// SPDX-License-Identifier: GPL-2.0+
> +/*
> + * Copyright (C) 2019 Oracle.  All Rights Reserved.
> + * Author: Darrick J. Wong <darrick.wong@oracle.com>
> + */
> +#include "xfs.h"
> +#include "xfrog.h"
> +
> +/* Bulkstat a single inode.  Returns zero or a positive error code. */
> +int
> +xfrog_bulkstat_single(
> +	struct xfs_fd		*xfd,
> +	uint64_t		ino,
> +	struct xfs_bstat	*ubuffer)
> +{
> +	__u64			i = ino;
> +	struct xfs_fsop_bulkreq	bulkreq = {
> +		.lastip		= &i,
> +		.icount		= 1,
> +		.ubuffer	= ubuffer,
> +		.ocount		= NULL,
> +	};
> +	int			ret;
> +
> +	ret = ioctl(xfd->fd, XFS_IOC_FSBULKSTAT_SINGLE, &bulkreq);
> +	if (ret)
> +		return errno;
> +	return 0;
> +}
> +
> +/* Bulkstat a bunch of inodes.  Returns zero or a positive error code. */
> +int
> +xfrog_bulkstat(
> +	struct xfs_fd		*xfd,
> +	uint64_t		*lastino,
> +	uint32_t		icount,
> +	struct xfs_bstat	*ubuffer,
> +	uint32_t		*ocount)
> +{
> +	struct xfs_fsop_bulkreq	bulkreq = {
> +		.lastip		= (__u64 *)lastino,
> +		.icount		= icount,
> +		.ubuffer	= ubuffer,
> +		.ocount		= (__s32 *)ocount,
> +	};
> +	int			ret;
> +
> +	ret = ioctl(xfd->fd, XFS_IOC_FSBULKSTAT, &bulkreq);
> +	if (ret)
> +		return errno;
> +	return 0;
> +}
> diff --git a/quota/quot.c b/quota/quot.c
> index 6bc91171..1e970819 100644
> --- a/quota/quot.c
> +++ b/quota/quot.c
> @@ -11,6 +11,7 @@
>   #include <grp.h>
>   #include "init.h"
>   #include "quota.h"
> +#include "xfrog.h"
>   
>   typedef struct du {
>   	struct du	*next;
> @@ -124,13 +125,13 @@ quot_bulkstat_add(
>   static void
>   quot_bulkstat_mount(
>   	char			*fsdir,
> -	uint			flags)
> +	unsigned int		flags)
>   {
> -	struct xfs_fsop_bulkreq	bulkreq;
> +	struct xfs_fd		fsxfd = XFS_FD_INIT_EMPTY;
>   	struct xfs_bstat	*buf;
> -	__u64			last = 0;
> -	__s32			count;
> -	int			i, sts, fsfd;
> +	uint64_t		last = 0;
> +	uint32_t		count;
> +	int			i, sts;
>   	du_t			**dp;
>   
>   	/*
> @@ -145,8 +146,8 @@ quot_bulkstat_mount(
>   			*dp = NULL;
>   	ndu[0] = ndu[1] = ndu[2] = 0;
>   
> -	fsfd = open(fsdir, O_RDONLY);
> -	if (fsfd < 0) {
> +	fsxfd.fd = open(fsdir, O_RDONLY);
> +	if (fsxfd.fd < 0) {
>   		perror(fsdir);
>   		return;
>   	}
> @@ -154,25 +155,23 @@ quot_bulkstat_mount(
>   	buf = (struct xfs_bstat *)calloc(NBSTAT, sizeof(struct xfs_bstat));
>   	if (!buf) {
>   		perror("calloc");
> -		close(fsfd);
> +		xfd_close(&fsxfd);
>   		return;
>   	}
>   
> -	bulkreq.lastip = &last;
> -	bulkreq.icount = NBSTAT;
> -	bulkreq.ubuffer = buf;
> -	bulkreq.ocount = &count;
> -
> -	while ((sts = xfsctl(fsdir, fsfd, XFS_IOC_FSBULKSTAT, &bulkreq)) == 0) {
> +	while ((sts = xfrog_bulkstat(&fsxfd, &last, NBSTAT, buf,
> +				&count)) == 0) {
>   		if (count == 0)
>   			break;
>   		for (i = 0; i < count; i++)
>   			quot_bulkstat_add(&buf[i], flags);
>   	}
> -	if (sts < 0)
> -		perror("XFS_IOC_FSBULKSTAT"),
> +	if (sts < 0) {
> +		errno = sts;
> +		perror("XFS_IOC_FSBULKSTAT");
> +	}
>   	free(buf);
> -	close(fsfd);
> +	xfd_close(&fsxfd);
>   }
>   
>   static int
> diff --git a/scrub/inodes.c b/scrub/inodes.c
> index 700e5200..413037d8 100644
> --- a/scrub/inodes.c
> +++ b/scrub/inodes.c
> @@ -17,6 +17,7 @@
>   #include "xfs_scrub.h"
>   #include "common.h"
>   #include "inodes.h"
> +#include "xfrog.h"
>   
>   /*
>    * Iterate a range of inodes.
> @@ -50,17 +51,10 @@ xfs_iterate_inodes_range_check(
>   	struct xfs_inogrp	*inogrp,
>   	struct xfs_bstat	*bstat)
>   {
> -	struct xfs_fsop_bulkreq	onereq = {NULL};
>   	struct xfs_bstat	*bs;
> -	__u64			oneino;
> -	__s32			onelen = 0;
>   	int			i;
>   	int			error;
>   
> -	onereq.lastip  = &oneino;
> -	onereq.icount  = 1;
> -	onereq.ocount  = &onelen;
> -
>   	for (i = 0, bs = bstat; i < XFS_INODES_PER_CHUNK; i++) {
>   		if (!(inogrp->xi_allocmask & (1ULL << i)))
>   			continue;
> @@ -70,10 +64,8 @@ xfs_iterate_inodes_range_check(
>   		}
>   
>   		/* Load the one inode. */
> -		oneino = inogrp->xi_startino + i;
> -		onereq.ubuffer = bs;
> -		error = ioctl(ctx->mnt.fd, XFS_IOC_FSBULKSTAT_SINGLE,
> -				&onereq);
> +		error = xfrog_bulkstat_single(&ctx->mnt,
> +				inogrp->xi_startino + i, bs);
>   		if (error || bs->bs_ino != inogrp->xi_startino + i) {
>   			memset(bs, 0, sizeof(struct xfs_bstat));
>   			bs->bs_ino = inogrp->xi_startino + i;
> @@ -99,16 +91,14 @@ xfs_iterate_inodes_range(
>   	void			*arg)
>   {
>   	struct xfs_fsop_bulkreq	igrpreq = {NULL};
> -	struct xfs_fsop_bulkreq	bulkreq = {NULL};
>   	struct xfs_handle	handle;
>   	struct xfs_inogrp	inogrp;
>   	struct xfs_bstat	bstat[XFS_INODES_PER_CHUNK];
>   	char			idescr[DESCR_BUFSZ];
> -	char			buf[DESCR_BUFSZ];
>   	struct xfs_bstat	*bs;
>   	__u64			igrp_ino;
> -	__u64			ino;
> -	__s32			bulklen = 0;
> +	uint64_t		ino;
> +	uint32_t		bulklen = 0;
>   	__s32			igrplen = 0;
>   	bool			moveon = true;
>   	int			i;
> @@ -117,10 +107,6 @@ xfs_iterate_inodes_range(
>   
>   
>   	memset(bstat, 0, XFS_INODES_PER_CHUNK * sizeof(struct xfs_bstat));
> -	bulkreq.lastip  = &ino;
> -	bulkreq.icount  = XFS_INODES_PER_CHUNK;
> -	bulkreq.ubuffer = &bstat;
> -	bulkreq.ocount  = &bulklen;
>   
>   	igrpreq.lastip  = &igrp_ino;
>   	igrpreq.icount  = 1;
> @@ -138,17 +124,17 @@ xfs_iterate_inodes_range(
>   	while (!error && igrplen) {
>   		/* Load the inodes. */
>   		ino = inogrp.xi_startino - 1;
> -		bulkreq.icount = inogrp.xi_alloccount;
> +
>   		/*
>   		 * We can have totally empty inode chunks on filesystems where
>   		 * there are more than 64 inodes per block.  Skip these.
>   		 */
>   		if (inogrp.xi_alloccount == 0)
>   			goto igrp_retry;
> -		error = ioctl(ctx->mnt.fd, XFS_IOC_FSBULKSTAT, &bulkreq);
> +		error = xfrog_bulkstat(&ctx->mnt, &ino, inogrp.xi_alloccount,
> +				bstat, &bulklen);
>   		if (error)
> -			str_info(ctx, descr, "%s", strerror_r(errno,
> -						buf, DESCR_BUFSZ));
> +			str_liberror(ctx, error, descr);
>   
>   		xfs_iterate_inodes_range_check(ctx, &inogrp, bstat);
>   
> 

^ permalink raw reply	[flat|nested] 31+ messages in thread

* Re: [PATCH 8/9] libfrog: create xfd_open function
  2019-08-30  4:21 ` [PATCH 8/9] libfrog: create xfd_open function Darrick J. Wong
@ 2019-09-01 20:55   ` Allison Collins
  2019-09-03 23:01   ` Dave Chinner
  1 sibling, 0 replies; 31+ messages in thread
From: Allison Collins @ 2019-09-01 20:55 UTC (permalink / raw)
  To: Darrick J. Wong, sandeen; +Cc: linux-xfs

On 8/29/19 9:21 PM, Darrick J. Wong wrote:
> From: Darrick J. Wong <darrick.wong@oracle.com>
> 
> Create a helper to open a file and initialize the xfd structure.
> 
> Signed-off-by: Darrick J. Wong <darrick.wong@oracle.com>

Looks good
Reviewed-by: Allison Collins <allison.henderson@oracle.com>

> ---
>   fsr/xfs_fsr.c    |   26 ++++++--------------------
>   include/xfrog.h  |    1 +
>   libfrog/fsgeom.c |   22 ++++++++++++++++++++++
>   quota/quot.c     |    7 ++++---
>   scrub/phase1.c   |   25 ++++++++-----------------
>   5 files changed, 41 insertions(+), 40 deletions(-)
> 
> 
> diff --git a/fsr/xfs_fsr.c b/fsr/xfs_fsr.c
> index 36402252..e8d41aaf 100644
> --- a/fsr/xfs_fsr.c
> +++ b/fsr/xfs_fsr.c
> @@ -592,18 +592,10 @@ fsrfs(char *mntdir, xfs_ino_t startino, int targetrange)
>   		return -1;
>   	}
>   
> -	if ((fsxfd.fd = open(mntdir, O_RDONLY)) < 0) {
> -		fsrprintf(_("unable to open: %s: %s\n"),
> -		          mntdir, strerror( errno ));
> -		free(fshandlep);
> -		return -1;
> -	}
> -
> -	ret = xfd_prepare_geometry(&fsxfd);
> +	ret = xfd_open(&fsxfd, mntdir, O_RDONLY);
>   	if (ret) {
> -		fsrprintf(_("Skipping %s: could not get XFS geometry\n"),
> -			  mntdir);
> -		xfd_close(&fsxfd);
> +		fsrprintf(_("unable to open XFS file: %s: %s\n"),
> +		          mntdir, strerror(ret));
>   		free(fshandlep);
>   		return -1;
>   	}
> @@ -725,16 +717,10 @@ fsrfile(
>   	 * Need to open something on the same filesystem as the
>   	 * file.  Open the parent.
>   	 */
> -	fsxfd.fd = open(getparent(fname), O_RDONLY);
> -	if (fsxfd.fd < 0) {
> -		fsrprintf(_("unable to open sys handle for %s: %s\n"),
> -			fname, strerror(errno));
> -		goto out;
> -	}
> -
> -	error = xfd_prepare_geometry(&fsxfd);
> +	error = xfd_open(&fsxfd, getparent(fname), O_RDONLY);
>   	if (error) {
> -		fsrprintf(_("Unable to get geom on fs for: %s\n"), fname);
> +		fsrprintf(_("unable to open sys handle for XFS file %s: %s\n"),
> +			fname, strerror(error));
>   		goto out;
>   	}
>   
> diff --git a/include/xfrog.h b/include/xfrog.h
> index 7bda9810..3a49acc3 100644
> --- a/include/xfrog.h
> +++ b/include/xfrog.h
> @@ -52,6 +52,7 @@ struct xfs_fd {
>   #define XFS_FD_INIT_EMPTY	XFS_FD_INIT(-1)
>   
>   int xfd_prepare_geometry(struct xfs_fd *xfd);
> +int xfd_open(struct xfs_fd *xfd, const char *pathname, int flags);
>   int xfd_close(struct xfs_fd *xfd);
>   
>   /* Convert AG number and AG inode number into fs inode number. */
> diff --git a/libfrog/fsgeom.c b/libfrog/fsgeom.c
> index cf9323c1..47644dc3 100644
> --- a/libfrog/fsgeom.c
> +++ b/libfrog/fsgeom.c
> @@ -117,6 +117,28 @@ xfd_prepare_geometry(
>   	return 0;
>   }
>   
> +/* Open a file on an XFS filesystem.  Returns zero or a positive error code. */
> +int
> +xfd_open(
> +	struct xfs_fd		*xfd,
> +	const char		*pathname,
> +	int			flags)
> +{
> +	int			ret;
> +
> +	xfd->fd = open(pathname, O_RDONLY);
> +	if (xfd->fd < 0)
> +		return errno;
> +
> +	ret = xfd_prepare_geometry(xfd);
> +	if (ret) {
> +		xfd_close(xfd);
> +		return ret;
> +	}
> +
> +	return 0;
> +}
> +
>   /*
>    * Release any resources associated with this xfs_fd structure.  Returns zero
>    * or a positive error code.
> diff --git a/quota/quot.c b/quota/quot.c
> index 1e970819..4614f684 100644
> --- a/quota/quot.c
> +++ b/quota/quot.c
> @@ -131,7 +131,7 @@ quot_bulkstat_mount(
>   	struct xfs_bstat	*buf;
>   	uint64_t		last = 0;
>   	uint32_t		count;
> -	int			i, sts;
> +	int			i, sts, ret;
>   	du_t			**dp;
>   
>   	/*
> @@ -146,8 +146,9 @@ quot_bulkstat_mount(
>   			*dp = NULL;
>   	ndu[0] = ndu[1] = ndu[2] = 0;
>   
> -	fsxfd.fd = open(fsdir, O_RDONLY);
> -	if (fsxfd.fd < 0) {
> +	ret = xfd_open(&fsxfd, fsdir, O_RDONLY);
> +	if (ret) {
> +		errno = ret;
>   		perror(fsdir);
>   		return;
>   	}
> diff --git a/scrub/phase1.c b/scrub/phase1.c
> index cbdbd010..15e67e37 100644
> --- a/scrub/phase1.c
> +++ b/scrub/phase1.c
> @@ -84,13 +84,17 @@ xfs_setup_fs(
>   	 * CAP_SYS_ADMIN, which we probably need to do anything fancy
>   	 * with the (XFS driver) kernel.
>   	 */
> -	ctx->mnt.fd = open(ctx->mntpoint, O_RDONLY | O_NOATIME | O_DIRECTORY);
> -	if (ctx->mnt.fd < 0) {
> -		if (errno == EPERM)
> +	error = xfd_open(&ctx->mnt, ctx->mntpoint,
> +			O_RDONLY | O_NOATIME | O_DIRECTORY);
> +	if (error) {
> +		if (error == EPERM)
>   			str_info(ctx, ctx->mntpoint,
>   _("Must be root to run scrub."));
> +		else if (error == ENOTTY)
> +			str_error(ctx, ctx->mntpoint,
> +_("Not an XFS filesystem."));
>   		else
> -			str_errno(ctx, ctx->mntpoint);
> +			str_liberror(ctx, error, ctx->mntpoint);
>   		return false;
>   	}
>   
> @@ -110,12 +114,6 @@ _("Must be root to run scrub."));
>   		return false;
>   	}
>   
> -	if (!platform_test_xfs_fd(ctx->mnt.fd)) {
> -		str_info(ctx, ctx->mntpoint,
> -_("Does not appear to be an XFS filesystem!"));
> -		return false;
> -	}
> -
>   	/*
>   	 * Flush everything out to disk before we start checking.
>   	 * This seems to reduce the incidence of stale file handle
> @@ -127,13 +125,6 @@ _("Does not appear to be an XFS filesystem!"));
>   		return false;
>   	}
>   
> -	/* Retrieve XFS geometry. */
> -	error = xfd_prepare_geometry(&ctx->mnt);
> -	if (error) {
> -		str_liberror(ctx, error, _("Retrieving XFS geometry"));
> -		return false;
> -	}
> -
>   	if (!xfs_action_lists_alloc(ctx->mnt.fsgeom.agcount,
>   				&ctx->action_lists)) {
>   		str_error(ctx, ctx->mntpoint, _("Not enough memory."));
> 

^ permalink raw reply	[flat|nested] 31+ messages in thread

* Re: [PATCH 9/9] libfrog: refactor open-coded INUMBERS calls
  2019-08-30  4:21 ` [PATCH 9/9] libfrog: refactor open-coded INUMBERS calls Darrick J. Wong
@ 2019-09-01 20:55   ` Allison Collins
  0 siblings, 0 replies; 31+ messages in thread
From: Allison Collins @ 2019-09-01 20:55 UTC (permalink / raw)
  To: Darrick J. Wong, sandeen; +Cc: linux-xfs, Dave Chinner

On 8/29/19 9:21 PM, Darrick J. Wong wrote:
> From: Darrick J. Wong <darrick.wong@oracle.com>
> 
> Refactor all the INUMBERS ioctl callsites into helper functions.
> 
> Signed-off-by: Darrick J. Wong <darrick.wong@oracle.com>
> Reviewed-by: Dave Chinner <dchinner@redhat.com>
Looks good!  I think it looks a lot cleaner.  Thanks!

Reviewed-by: Allison Collins <allison.henderson@oracle.com>

> ---
>   include/xfrog.h    |    4 ++++
>   io/imap.c          |   33 ++++++++++++++++-----------------
>   io/open.c          |   24 ++++++++++++------------
>   libfrog/bulkstat.c |   26 ++++++++++++++++++++++++++
>   scrub/fscounters.c |   20 ++++++++------------
>   scrub/inodes.c     |   17 ++++++-----------
>   6 files changed, 72 insertions(+), 52 deletions(-)
> 
> 
> diff --git a/include/xfrog.h b/include/xfrog.h
> index 3a49acc3..d16481ce 100644
> --- a/include/xfrog.h
> +++ b/include/xfrog.h
> @@ -116,4 +116,8 @@ int xfrog_bulkstat_single(struct xfs_fd *xfd, uint64_t ino,
>   int xfrog_bulkstat(struct xfs_fd *xfd, uint64_t *lastino, uint32_t icount,
>   		struct xfs_bstat *ubuffer, uint32_t *ocount);
>   
> +struct xfs_inogrp;
> +int xfrog_inumbers(struct xfs_fd *xfd, uint64_t *lastino, uint32_t icount,
> +		struct xfs_inogrp *ubuffer, uint32_t *ocount);
> +
>   #endif	/* __XFROG_H__ */
> diff --git a/io/imap.c b/io/imap.c
> index 9667289a..053ac28e 100644
> --- a/io/imap.c
> +++ b/io/imap.c
> @@ -8,18 +8,20 @@
>   #include "input.h"
>   #include "init.h"
>   #include "io.h"
> +#include "xfrog.h"
>   
>   static cmdinfo_t imap_cmd;
>   
>   static int
>   imap_f(int argc, char **argv)
>   {
> -	int		count;
> -	int		nent;
> -	int		i;
> -	__u64		last = 0;
> -	struct xfs_inogrp *t;
> -	struct xfs_fsop_bulkreq bulkreq;
> +	struct xfs_fd		xfd = XFS_FD_INIT(file->fd);
> +	struct xfs_inogrp	*t;
> +	uint64_t		last = 0;
> +	uint32_t		count;
> +	uint32_t		nent;
> +	int			i;
> +	int			error;
>   
>   	if (argc != 2)
>   		nent = 1;
> @@ -30,14 +32,8 @@ imap_f(int argc, char **argv)
>   	if (!t)
>   		return 0;
>   
> -	bulkreq.lastip  = &last;
> -	bulkreq.icount  = nent;
> -	bulkreq.ubuffer = (void *)t;
> -	bulkreq.ocount  = &count;
> -
> -	while (xfsctl(file->name, file->fd, XFS_IOC_FSINUMBERS, &bulkreq) == 0) {
> -		if (count == 0)
> -			goto out_free;
> +	while ((error = xfrog_inumbers(&xfd, &last, nent, t, &count)) == 0 &&
> +	       count > 0) {
>   		for (i = 0; i < count; i++) {
>   			printf(_("ino %10llu count %2d mask %016llx\n"),
>   				(unsigned long long)t[i].xi_startino,
> @@ -45,9 +41,12 @@ imap_f(int argc, char **argv)
>   				(unsigned long long)t[i].xi_allocmask);
>   		}
>   	}
> -	perror("xfsctl(XFS_IOC_FSINUMBERS)");
> -	exitcode = 1;
> -out_free:
> +
> +	if (error) {
> +		errno = error;
> +		perror("xfsctl(XFS_IOC_FSINUMBERS)");
> +		exitcode = 1;
> +	}
>   	free(t);
>   	return 0;
>   }
> diff --git a/io/open.c b/io/open.c
> index 35e6131b..c0d0f1e9 100644
> --- a/io/open.c
> +++ b/io/open.c
> @@ -675,24 +675,24 @@ inode_help(void)
>   "\n"));
>   }
>   
> +#define IGROUP_NR	(1024)
>   static __u64
>   get_last_inode(void)
>   {
> -	__u64			lastip = 0;
> -	__u64			lastgrp = 0;
> -	__s32			ocount = 0;
> +	struct xfs_fd		xfd = XFS_FD_INIT(file->fd);
> +	uint64_t		lastip = 0;
> +	uint32_t		lastgrp = 0;
> +	uint32_t		ocount = 0;
>   	__u64			last_ino;
> -	struct xfs_inogrp	igroup[1024];
> -	struct xfs_fsop_bulkreq	bulkreq;
> -
> -	bulkreq.lastip = &lastip;
> -	bulkreq.ubuffer = &igroup;
> -	bulkreq.icount = sizeof(igroup) / sizeof(struct xfs_inogrp);
> -	bulkreq.ocount = &ocount;
> +	struct xfs_inogrp	igroup[IGROUP_NR];
>   
>   	for (;;) {
> -		if (xfsctl(file->name, file->fd, XFS_IOC_FSINUMBERS,
> -				&bulkreq)) {
> +		int		ret;
> +
> +		ret = xfrog_inumbers(&xfd, &lastip, IGROUP_NR, igroup,
> +				&ocount);
> +		if (ret) {
> +			errno = ret;
>   			perror("XFS_IOC_FSINUMBERS");
>   			return 0;
>   		}
> diff --git a/libfrog/bulkstat.c b/libfrog/bulkstat.c
> index 0e11ccea..18fffb20 100644
> --- a/libfrog/bulkstat.c
> +++ b/libfrog/bulkstat.c
> @@ -50,3 +50,29 @@ xfrog_bulkstat(
>   		return errno;
>   	return 0;
>   }
> +
> +/*
> + * Query inode allocation bitmask information.  Returns zero or a positive
> + * error code.
> + */
> +int
> +xfrog_inumbers(
> +	struct xfs_fd		*xfd,
> +	uint64_t		*lastino,
> +	uint32_t		icount,
> +	struct xfs_inogrp	*ubuffer,
> +	uint32_t		*ocount)
> +{
> +	struct xfs_fsop_bulkreq	bulkreq = {
> +		.lastip		= (__u64 *)lastino,
> +		.icount		= icount,
> +		.ubuffer	= ubuffer,
> +		.ocount		= (__s32 *)ocount,
> +	};
> +	int			ret;
> +
> +	ret = ioctl(xfd->fd, XFS_IOC_FSINUMBERS, &bulkreq);
> +	if (ret)
> +		return errno;
> +	return 0;
> +}
> diff --git a/scrub/fscounters.c b/scrub/fscounters.c
> index ea6af156..3915822e 100644
> --- a/scrub/fscounters.c
> +++ b/scrub/fscounters.c
> @@ -15,6 +15,7 @@
>   #include "xfs_scrub.h"
>   #include "common.h"
>   #include "fscounters.h"
> +#include "xfrog.h"
>   
>   /*
>    * Filesystem counter collection routines.  We can count the number of
> @@ -41,30 +42,25 @@ xfs_count_inodes_range(
>   	uint64_t		last_ino,
>   	uint64_t		*count)
>   {
> -	struct xfs_fsop_bulkreq	igrpreq = {NULL};
>   	struct xfs_inogrp	inogrp;
> -	__u64			igrp_ino;
> +	uint64_t		igrp_ino;
>   	uint64_t		nr = 0;
> -	__s32			igrplen = 0;
> +	uint32_t		igrplen = 0;
>   	int			error;
>   
>   	ASSERT(!(first_ino & (XFS_INODES_PER_CHUNK - 1)));
>   	ASSERT((last_ino & (XFS_INODES_PER_CHUNK - 1)));
>   
> -	igrpreq.lastip  = &igrp_ino;
> -	igrpreq.icount  = 1;
> -	igrpreq.ubuffer = &inogrp;
> -	igrpreq.ocount  = &igrplen;
> -
>   	igrp_ino = first_ino;
> -	error = ioctl(ctx->mnt.fd, XFS_IOC_FSINUMBERS, &igrpreq);
> -	while (!error && igrplen && inogrp.xi_startino < last_ino) {
> +	while (!(error = xfrog_inumbers(&ctx->mnt, &igrp_ino, 1, &inogrp,
> +			&igrplen))) {
> +		if (igrplen == 0 || inogrp.xi_startino >= last_ino)
> +			break;
>   		nr += inogrp.xi_alloccount;
> -		error = ioctl(ctx->mnt.fd, XFS_IOC_FSINUMBERS, &igrpreq);
>   	}
>   
>   	if (error) {
> -		str_errno(ctx, descr);
> +		str_liberror(ctx, error, descr);
>   		return false;
>   	}
>   
> diff --git a/scrub/inodes.c b/scrub/inodes.c
> index 413037d8..acad9b16 100644
> --- a/scrub/inodes.c
> +++ b/scrub/inodes.c
> @@ -90,16 +90,15 @@ xfs_iterate_inodes_range(
>   	xfs_inode_iter_fn	fn,
>   	void			*arg)
>   {
> -	struct xfs_fsop_bulkreq	igrpreq = {NULL};
>   	struct xfs_handle	handle;
>   	struct xfs_inogrp	inogrp;
>   	struct xfs_bstat	bstat[XFS_INODES_PER_CHUNK];
>   	char			idescr[DESCR_BUFSZ];
>   	struct xfs_bstat	*bs;
> -	__u64			igrp_ino;
> +	uint64_t		igrp_ino;
>   	uint64_t		ino;
>   	uint32_t		bulklen = 0;
> -	__s32			igrplen = 0;
> +	uint32_t		igrplen = 0;
>   	bool			moveon = true;
>   	int			i;
>   	int			error;
> @@ -108,11 +107,6 @@ xfs_iterate_inodes_range(
>   
>   	memset(bstat, 0, XFS_INODES_PER_CHUNK * sizeof(struct xfs_bstat));
>   
> -	igrpreq.lastip  = &igrp_ino;
> -	igrpreq.icount  = 1;
> -	igrpreq.ubuffer = &inogrp;
> -	igrpreq.ocount  = &igrplen;
> -
>   	memcpy(&handle.ha_fsid, fshandle, sizeof(handle.ha_fsid));
>   	handle.ha_fid.fid_len = sizeof(xfs_fid_t) -
>   			sizeof(handle.ha_fid.fid_len);
> @@ -120,7 +114,7 @@ xfs_iterate_inodes_range(
>   
>   	/* Find the inode chunk & alloc mask */
>   	igrp_ino = first_ino;
> -	error = ioctl(ctx->mnt.fd, XFS_IOC_FSINUMBERS, &igrpreq);
> +	error = xfrog_inumbers(&ctx->mnt, &igrp_ino, 1, &inogrp, &igrplen);
>   	while (!error && igrplen) {
>   		/* Load the inodes. */
>   		ino = inogrp.xi_startino - 1;
> @@ -176,12 +170,13 @@ _("Changed too many times during scan; giving up."));
>   
>   		stale_count = 0;
>   igrp_retry:
> -		error = ioctl(ctx->mnt.fd, XFS_IOC_FSINUMBERS, &igrpreq);
> +		error = xfrog_inumbers(&ctx->mnt, &igrp_ino, 1, &inogrp,
> +				&igrplen);
>   	}
>   
>   err:
>   	if (error) {
> -		str_errno(ctx, descr);
> +		str_liberror(ctx, error, descr);
>   		moveon = false;
>   	}
>   out:
> 

^ permalink raw reply	[flat|nested] 31+ messages in thread

* Re: [PATCH 7/9] libfrog: refactor open-coded bulkstat calls
  2019-09-01 20:55   ` [PATCH " Allison Collins
@ 2019-09-01 21:05     ` Darrick J. Wong
  0 siblings, 0 replies; 31+ messages in thread
From: Darrick J. Wong @ 2019-09-01 21:05 UTC (permalink / raw)
  To: Allison Collins; +Cc: sandeen, linux-xfs

On Sun, Sep 01, 2019 at 01:55:04PM -0700, Allison Collins wrote:
> On 8/29/19 9:21 PM, Darrick J. Wong wrote:
> > From: Darrick J. Wong <darrick.wong@oracle.com>
> > 
> > Refactor the BULKSTAT_SINGLE and BULKSTAT ioctl callsites into helper
> > functions.
> > 
> > Signed-off-by: Darrick J. Wong <darrick.wong@oracle.com>
> > ---
> >   fsr/xfs_fsr.c      |  110 ++++++++++++++++++++++------------------------------
> >   include/xfrog.h    |    7 +++
> >   io/open.c          |   72 +++++++++++++++++-----------------
> >   io/swapext.c       |   20 ++-------
> >   libfrog/Makefile   |    1
> >   libfrog/bulkstat.c |   52 +++++++++++++++++++++++++
> >   quota/quot.c       |   33 ++++++++--------
> >   scrub/inodes.c     |   32 ++++-----------
> >   8 files changed, 172 insertions(+), 155 deletions(-)
> >   create mode 100644 libfrog/bulkstat.c
> > 
> > 
> > diff --git a/fsr/xfs_fsr.c b/fsr/xfs_fsr.c
> > index 4b239a30..36402252 100644
> > --- a/fsr/xfs_fsr.c
> > +++ b/fsr/xfs_fsr.c
> > @@ -102,31 +102,6 @@ static int	nfrags = 0;	/* Debug option: Coerse into specific number
> >   				 * of extents */
> >   static int	openopts = O_CREAT|O_EXCL|O_RDWR|O_DIRECT;
> > -static int
> > -xfs_bulkstat_single(int fd, xfs_ino_t *lastip, struct xfs_bstat *ubuffer)
> > -{
> > -    struct xfs_fsop_bulkreq  bulkreq;
> > -
> > -    bulkreq.lastip = (__u64 *)lastip;
> > -    bulkreq.icount = 1;
> > -    bulkreq.ubuffer = ubuffer;
> > -    bulkreq.ocount = NULL;
> > -    return ioctl(fd, XFS_IOC_FSBULKSTAT_SINGLE, &bulkreq);
> > -}
> > -
> > -static int
> > -xfs_bulkstat(int fd, xfs_ino_t *lastip, int icount,
> > -                    struct xfs_bstat *ubuffer, __s32 *ocount)
> > -{
> > -    struct xfs_fsop_bulkreq  bulkreq;
> > -
> > -    bulkreq.lastip = (__u64 *)lastip;
> > -    bulkreq.icount = icount;
> > -    bulkreq.ubuffer = ubuffer;
> > -    bulkreq.ocount = ocount;
> > -    return ioctl(fd, XFS_IOC_FSBULKSTAT, &bulkreq);
> > -}
> > -
> >   static int
> >   xfs_swapext(int fd, xfs_swapext_t *sx)
> >   {
> > @@ -596,11 +571,11 @@ fsrall_cleanup(int timeout)
> >   static int
> >   fsrfs(char *mntdir, xfs_ino_t startino, int targetrange)
> >   {
> > -
> > -	int	fsfd, fd;
> > +	struct xfs_fd	fsxfd = XFS_FD_INIT_EMPTY;
> > +	int	fd;
> >   	int	count = 0;
> >   	int	ret;
> > -	__s32	buflenout;
> > +	uint32_t buflenout;
> >   	struct xfs_bstat buf[GRABSZ];
> >   	char	fname[64];
> >   	char	*tname;
> > @@ -617,26 +592,27 @@ fsrfs(char *mntdir, xfs_ino_t startino, int targetrange)
> >   		return -1;
> >   	}
> > -	if ((fsfd = open(mntdir, O_RDONLY)) < 0) {
> > +	if ((fsxfd.fd = open(mntdir, O_RDONLY)) < 0) {
> >   		fsrprintf(_("unable to open: %s: %s\n"),
> >   		          mntdir, strerror( errno ));
> >   		free(fshandlep);
> >   		return -1;
> >   	}
> > -	ret = xfrog_geometry(fsfd, &fsgeom);
> > +	ret = xfd_prepare_geometry(&fsxfd);
> >   	if (ret) {
> >   		fsrprintf(_("Skipping %s: could not get XFS geometry\n"),
> >   			  mntdir);
> > -		close(fsfd);
> > +		xfd_close(&fsxfd);
> >   		free(fshandlep);
> >   		return -1;
> >   	}
> > +	memcpy(&fsgeom, &fsxfd.fsgeom, sizeof(fsgeom));
> >   	tmp_init(mntdir);
> > -	while ((ret = xfs_bulkstat(fsfd,
> > -				&lastino, GRABSZ, &buf[0], &buflenout)) == 0) {
> > +	while ((ret = xfrog_bulkstat(&fsxfd, &lastino, GRABSZ, &buf[0],
> > +				&buflenout)) == 0) {
> >   		struct xfs_bstat *p;
> >   		struct xfs_bstat *endp;
> > @@ -685,16 +661,16 @@ fsrfs(char *mntdir, xfs_ino_t startino, int targetrange)
> >   		}
> >   		if (endtime && endtime < time(NULL)) {
> >   			tmp_close(mntdir);
> > -			close(fsfd);
> > +			xfd_close(&fsxfd);
> >   			fsrall_cleanup(1);
> >   			exit(1);
> >   		}
> >   	}
> > -	if (ret < 0)
> > -		fsrprintf(_("%s: xfs_bulkstat: %s\n"), progname, strerror(errno));
> > +	if (ret)
> > +		fsrprintf(_("%s: bulkstat: %s\n"), progname, strerror(ret));
> >   out0:
> >   	tmp_close(mntdir);
> > -	close(fsfd);
> > +	xfd_close(&fsxfd);
> >   	free(fshandlep);
> >   	return 0;
> >   }
> > @@ -727,13 +703,16 @@ fsrdir(char *dirname)
> >    * an open on the file and passes this all to fsrfile_common.
> >    */
> >   static int
> > -fsrfile(char *fname, xfs_ino_t ino)
> > +fsrfile(
> > +	char			*fname,
> > +	xfs_ino_t		ino)
> >   {
> > -	struct xfs_bstat statbuf;
> > -	jdm_fshandle_t	*fshandlep;
> > -	int	fd = -1, fsfd = -1;
> > -	int	error = -1;
> > -	char	*tname;
> > +	struct xfs_fd		fsxfd = XFS_FD_INIT_EMPTY;
> > +	struct xfs_bstat	statbuf;
> > +	jdm_fshandle_t		*fshandlep;
> > +	int			fd = -1;
> > +	int			error = -1;
> > +	char			*tname;
> >   	fshandlep = jdm_getfshandle(getparent (fname) );
> >   	if (!fshandlep) {
> > @@ -746,16 +725,23 @@ fsrfile(char *fname, xfs_ino_t ino)
> >   	 * Need to open something on the same filesystem as the
> >   	 * file.  Open the parent.
> >   	 */
> > -	fsfd = open(getparent(fname), O_RDONLY);
> > -	if (fsfd < 0) {
> > +	fsxfd.fd = open(getparent(fname), O_RDONLY);
> > +	if (fsxfd.fd < 0) {
> >   		fsrprintf(_("unable to open sys handle for %s: %s\n"),
> >   			fname, strerror(errno));
> >   		goto out;
> >   	}
> > -	if ((xfs_bulkstat_single(fsfd, &ino, &statbuf)) < 0) {
> > +	error = xfd_prepare_geometry(&fsxfd);
> > +	if (error) {
> > +		fsrprintf(_("Unable to get geom on fs for: %s\n"), fname);
> > +		goto out;
> > +	}
> > +
> > +	error = xfrog_bulkstat_single(&fsxfd, ino, &statbuf);
> > +	if (error) {
> >   		fsrprintf(_("unable to get bstat on %s: %s\n"),
> > -			fname, strerror(errno));
> > +			fname, strerror(error));
> >   		goto out;
> >   	}
> > @@ -766,12 +752,8 @@ fsrfile(char *fname, xfs_ino_t ino)
> >   		goto out;
> >   	}
> > -	/* Get the fs geometry */
> > -	error = xfrog_geometry(fsfd, &fsgeom);
> > -	if (error) {
> > -		fsrprintf(_("Unable to get geom on fs for: %s\n"), fname);
> > -		goto out;
> > -	}
> > +	/* Stash the fs geometry for general use. */
> > +	memcpy(&fsgeom, &fsxfd.fsgeom, sizeof(fsgeom));
> 
> Just a nit: Why the memcpy here instead of making a general use pointer?

Doing the minimum required to patch up fsr. :)

I'm not really sure why fsr keeps a (global) fs geometry structure but
drops the fd.  I /think/ it's the case that it'll at least maintain an
open handle to the fs to prevent it from going away completely, but
cleaning up fsr to pass around *xfs_fd might make sense once we get
through the current 101 patches.

--D

> Otherwise looks like a lot of good clean up
> Reviewed-by: Allison Collins <allison.henderson@oracle.com>
> 
> >   	tname = gettmpname(fname);
> > @@ -779,8 +761,7 @@ fsrfile(char *fname, xfs_ino_t ino)
> >   		error = fsrfile_common(fname, tname, NULL, fd, &statbuf);
> >   out:
> > -	if (fsfd >= 0)
> > -		close(fsfd);
> > +	xfd_close(&fsxfd);
> >   	if (fd >= 0)
> >   		close(fd);
> >   	free(fshandlep);
> > @@ -947,6 +928,7 @@ fsr_setup_attr_fork(
> >   	struct xfs_bstat *bstatp)
> >   {
> >   #ifdef HAVE_FSETXATTR
> > +	struct xfs_fd	txfd = XFS_FD_INIT(tfd);
> >   	struct stat	tstatbuf;
> >   	int		i;
> >   	int		diff = 0;
> > @@ -964,7 +946,7 @@ fsr_setup_attr_fork(
> >   	if (!(fsgeom.flags & XFS_FSOP_GEOM_FLAGS_ATTR2) ||
> >   	    bstatp->bs_forkoff == 0) {
> >   		/* attr1 */
> > -		ret = fsetxattr(tfd, "user.X", "X", 1, XATTR_CREATE);
> > +		ret = fsetxattr(txfd.fd, "user.X", "X", 1, XATTR_CREATE);
> >   		if (ret) {
> >   			fsrprintf(_("could not set ATTR\n"));
> >   			return -1;
> > @@ -974,7 +956,7 @@ fsr_setup_attr_fork(
> >   	/* attr2 w/ fork offsets */
> > -	if (fstat(tfd, &tstatbuf) < 0) {
> > +	if (fstat(txfd.fd, &tstatbuf) < 0) {
> >   		fsrprintf(_("unable to stat temp file: %s\n"),
> >   					strerror(errno));
> >   		return -1;
> > @@ -983,18 +965,18 @@ fsr_setup_attr_fork(
> >   	i = 0;
> >   	do {
> >   		struct xfs_bstat tbstat;
> > -		xfs_ino_t	ino;
> >   		char		name[64];
> > +		int		ret;
> >   		/*
> >   		 * bulkstat the temp inode to see what the forkoff is.  Use
> >   		 * this to compare against the target and determine what we
> >   		 * need to do.
> >   		 */
> > -		ino = tstatbuf.st_ino;
> > -		if ((xfs_bulkstat_single(tfd, &ino, &tbstat)) < 0) {
> > +		ret = xfrog_bulkstat_single(&txfd, tstatbuf.st_ino, &tbstat);
> > +		if (ret) {
> >   			fsrprintf(_("unable to get bstat on temp file: %s\n"),
> > -						strerror(errno));
> > +						strerror(ret));
> >   			return -1;
> >   		}
> >   		if (dflag)
> > @@ -1014,7 +996,7 @@ fsr_setup_attr_fork(
> >   		 */
> >   		if (!tbstat.bs_forkoff) {
> >   			ASSERT(i == 0);
> > -			ret = fsetxattr(tfd, name, "XX", 2, XATTR_CREATE);
> > +			ret = fsetxattr(txfd.fd, name, "XX", 2, XATTR_CREATE);
> >   			if (ret) {
> >   				fsrprintf(_("could not set ATTR\n"));
> >   				return -1;
> > @@ -1050,7 +1032,7 @@ fsr_setup_attr_fork(
> >   			if (diff < 0) {
> >   				char val[2048];
> >   				memset(val, 'X', 2048);
> > -				if (fsetxattr(tfd, name, val, 2048, 0)) {
> > +				if (fsetxattr(txfd.fd, name, val, 2048, 0)) {
> >   					fsrprintf(_("big ATTR set failed\n"));
> >   					return -1;
> >   				}
> > @@ -1094,7 +1076,7 @@ fsr_setup_attr_fork(
> >   		}
> >   		/* we need to grow the attr fork, so create another attr */
> > -		ret = fsetxattr(tfd, name, "XX", 2, XATTR_CREATE);
> > +		ret = fsetxattr(txfd.fd, name, "XX", 2, XATTR_CREATE);
> >   		if (ret) {
> >   			fsrprintf(_("could not set ATTR\n"));
> >   			return -1;
> > diff --git a/include/xfrog.h b/include/xfrog.h
> > index a08f6464..7bda9810 100644
> > --- a/include/xfrog.h
> > +++ b/include/xfrog.h
> > @@ -108,4 +108,11 @@ cvt_b_to_off_fsbt(
> >   	return bytes >> xfd->blocklog;
> >   }
> > +/* Bulkstat wrappers */
> > +struct xfs_bstat;
> > +int xfrog_bulkstat_single(struct xfs_fd *xfd, uint64_t ino,
> > +		struct xfs_bstat *ubuffer);
> > +int xfrog_bulkstat(struct xfs_fd *xfd, uint64_t *lastino, uint32_t icount,
> > +		struct xfs_bstat *ubuffer, uint32_t *ocount);
> > +
> >   #endif	/* __XFROG_H__ */
> > diff --git a/io/open.c b/io/open.c
> > index 8b24a4f9..35e6131b 100644
> > --- a/io/open.c
> > +++ b/io/open.c
> > @@ -719,19 +719,18 @@ get_last_inode(void)
> >   static int
> >   inode_f(
> > -	  int			argc,
> > -	  char			**argv)
> > +	int			argc,
> > +	char			**argv)
> >   {
> > -	__s32			count = 0;
> > -	__u64			result_ino = 0;
> > -	__u64			userino = NULLFSINO;
> > +	struct xfs_bstat	bstat;
> > +	uint32_t		count = 0;
> > +	uint64_t		result_ino = 0;
> > +	uint64_t		userino = NULLFSINO;
> >   	char			*p;
> >   	int			c;
> >   	int			verbose = 0;
> >   	int			ret_next = 0;
> > -	int			cmd = 0;
> > -	struct xfs_fsop_bulkreq	bulkreq;
> > -	struct xfs_bstat	bstat;
> > +	int			ret;
> >   	while ((c = getopt(argc, argv, "nv")) != EOF) {
> >   		switch (c) {
> > @@ -773,35 +772,38 @@ inode_f(
> >   			exitcode = 1;
> >   			return 0;
> >   		}
> > +	} else if (ret_next) {
> > +		struct xfs_fd	xfd = XFS_FD_INIT(file->fd);
> > +
> > +		/* get next inode */
> > +		ret = xfrog_bulkstat(&xfd, &userino, 1, &bstat, &count);
> > +		if (ret) {
> > +			errno = ret;
> > +			perror("bulkstat");
> > +			exitcode = 1;
> > +			return 0;
> > +		}
> > +
> > +		/* The next inode in use, or 0 if none */
> > +		if (count)
> > +			result_ino = bstat.bs_ino;
> > +		else
> > +			result_ino = 0;
> >   	} else {
> > -		if (ret_next)	/* get next inode */
> > -			cmd = XFS_IOC_FSBULKSTAT;
> > -		else		/* get this inode */
> > -			cmd = XFS_IOC_FSBULKSTAT_SINGLE;
> > -
> > -		bulkreq.lastip = &userino;
> > -		bulkreq.icount = 1;
> > -		bulkreq.ubuffer = &bstat;
> > -		bulkreq.ocount = &count;
> > -
> > -		if (xfsctl(file->name, file->fd, cmd, &bulkreq)) {
> > -			if (!ret_next && errno == EINVAL) {
> > -				/* Not in use */
> > -				result_ino = 0;
> > -			} else {
> > -				perror("xfsctl");
> > -				exitcode = 1;
> > -				return 0;
> > -			}
> > -		} else if (ret_next) {
> > -			/* The next inode in use, or 0 if none */
> > -			if (*bulkreq.ocount)
> > -				result_ino = bstat.bs_ino;
> > -			else
> > -				result_ino = 0;
> > +		struct xfs_fd	xfd = XFS_FD_INIT(file->fd);
> > +
> > +		/* get this inode */
> > +		ret = xfrog_bulkstat_single(&xfd, userino, &bstat);
> > +		if (ret == EINVAL) {
> > +			/* Not in use */
> > +			result_ino = 0;
> > +		} else if (ret) {
> > +			errno = ret;
> > +			perror("bulkstat_single");
> > +			exitcode = 1;
> > +			return 0;
> >   		} else {
> > -			/* The inode we asked about */
> > -			result_ino = userino;
> > +			result_ino = bstat.bs_ino;
> >   		}
> >   	}
> > diff --git a/io/swapext.c b/io/swapext.c
> > index d360c221..fbf4fff5 100644
> > --- a/io/swapext.c
> > +++ b/io/swapext.c
> > @@ -8,6 +8,7 @@
> >   #include "input.h"
> >   #include "init.h"
> >   #include "io.h"
> > +#include "xfrog.h"
> >   static cmdinfo_t swapext_cmd;
> > @@ -20,26 +21,12 @@ swapext_help(void)
> >   "\n"));
> >   }
> > -static int
> > -xfs_bulkstat_single(
> > -	int			fd,
> > -	xfs_ino_t		*lastip,
> > -	struct xfs_bstat	*ubuffer)
> > -{
> > -	struct xfs_fsop_bulkreq	bulkreq;
> > -
> > -	bulkreq.lastip = (__u64 *)lastip;
> > -	bulkreq.icount = 1;
> > -	bulkreq.ubuffer = ubuffer;
> > -	bulkreq.ocount = NULL;
> > -	return ioctl(fd, XFS_IOC_FSBULKSTAT_SINGLE, &bulkreq);
> > -}
> > -
> >   static int
> >   swapext_f(
> >   	int			argc,
> >   	char			**argv)
> >   {
> > +	struct xfs_fd		fxfd = XFS_FD_INIT(file->fd);
> >   	int			fd;
> >   	int			error;
> >   	struct xfs_swapext	sx;
> > @@ -60,8 +47,9 @@ swapext_f(
> >   		goto out;
> >   	}
> > -	error = xfs_bulkstat_single(file->fd, &stat.st_ino, &sx.sx_stat);
> > +	error = xfrog_bulkstat_single(&fxfd, stat.st_ino, &sx.sx_stat);
> >   	if (error) {
> > +		errno = error;
> >   		perror("bulkstat");
> >   		goto out;
> >   	}
> > diff --git a/libfrog/Makefile b/libfrog/Makefile
> > index f5a0539b..05c6f701 100644
> > --- a/libfrog/Makefile
> > +++ b/libfrog/Makefile
> > @@ -13,6 +13,7 @@ LT_AGE = 0
> >   CFILES = \
> >   avl64.c \
> >   bitmap.c \
> > +bulkstat.c \
> >   convert.c \
> >   crc32.c \
> >   fsgeom.c \
> > diff --git a/libfrog/bulkstat.c b/libfrog/bulkstat.c
> > new file mode 100644
> > index 00000000..0e11ccea
> > --- /dev/null
> > +++ b/libfrog/bulkstat.c
> > @@ -0,0 +1,52 @@
> > +// SPDX-License-Identifier: GPL-2.0+
> > +/*
> > + * Copyright (C) 2019 Oracle.  All Rights Reserved.
> > + * Author: Darrick J. Wong <darrick.wong@oracle.com>
> > + */
> > +#include "xfs.h"
> > +#include "xfrog.h"
> > +
> > +/* Bulkstat a single inode.  Returns zero or a positive error code. */
> > +int
> > +xfrog_bulkstat_single(
> > +	struct xfs_fd		*xfd,
> > +	uint64_t		ino,
> > +	struct xfs_bstat	*ubuffer)
> > +{
> > +	__u64			i = ino;
> > +	struct xfs_fsop_bulkreq	bulkreq = {
> > +		.lastip		= &i,
> > +		.icount		= 1,
> > +		.ubuffer	= ubuffer,
> > +		.ocount		= NULL,
> > +	};
> > +	int			ret;
> > +
> > +	ret = ioctl(xfd->fd, XFS_IOC_FSBULKSTAT_SINGLE, &bulkreq);
> > +	if (ret)
> > +		return errno;
> > +	return 0;
> > +}
> > +
> > +/* Bulkstat a bunch of inodes.  Returns zero or a positive error code. */
> > +int
> > +xfrog_bulkstat(
> > +	struct xfs_fd		*xfd,
> > +	uint64_t		*lastino,
> > +	uint32_t		icount,
> > +	struct xfs_bstat	*ubuffer,
> > +	uint32_t		*ocount)
> > +{
> > +	struct xfs_fsop_bulkreq	bulkreq = {
> > +		.lastip		= (__u64 *)lastino,
> > +		.icount		= icount,
> > +		.ubuffer	= ubuffer,
> > +		.ocount		= (__s32 *)ocount,
> > +	};
> > +	int			ret;
> > +
> > +	ret = ioctl(xfd->fd, XFS_IOC_FSBULKSTAT, &bulkreq);
> > +	if (ret)
> > +		return errno;
> > +	return 0;
> > +}
> > diff --git a/quota/quot.c b/quota/quot.c
> > index 6bc91171..1e970819 100644
> > --- a/quota/quot.c
> > +++ b/quota/quot.c
> > @@ -11,6 +11,7 @@
> >   #include <grp.h>
> >   #include "init.h"
> >   #include "quota.h"
> > +#include "xfrog.h"
> >   typedef struct du {
> >   	struct du	*next;
> > @@ -124,13 +125,13 @@ quot_bulkstat_add(
> >   static void
> >   quot_bulkstat_mount(
> >   	char			*fsdir,
> > -	uint			flags)
> > +	unsigned int		flags)
> >   {
> > -	struct xfs_fsop_bulkreq	bulkreq;
> > +	struct xfs_fd		fsxfd = XFS_FD_INIT_EMPTY;
> >   	struct xfs_bstat	*buf;
> > -	__u64			last = 0;
> > -	__s32			count;
> > -	int			i, sts, fsfd;
> > +	uint64_t		last = 0;
> > +	uint32_t		count;
> > +	int			i, sts;
> >   	du_t			**dp;
> >   	/*
> > @@ -145,8 +146,8 @@ quot_bulkstat_mount(
> >   			*dp = NULL;
> >   	ndu[0] = ndu[1] = ndu[2] = 0;
> > -	fsfd = open(fsdir, O_RDONLY);
> > -	if (fsfd < 0) {
> > +	fsxfd.fd = open(fsdir, O_RDONLY);
> > +	if (fsxfd.fd < 0) {
> >   		perror(fsdir);
> >   		return;
> >   	}
> > @@ -154,25 +155,23 @@ quot_bulkstat_mount(
> >   	buf = (struct xfs_bstat *)calloc(NBSTAT, sizeof(struct xfs_bstat));
> >   	if (!buf) {
> >   		perror("calloc");
> > -		close(fsfd);
> > +		xfd_close(&fsxfd);
> >   		return;
> >   	}
> > -	bulkreq.lastip = &last;
> > -	bulkreq.icount = NBSTAT;
> > -	bulkreq.ubuffer = buf;
> > -	bulkreq.ocount = &count;
> > -
> > -	while ((sts = xfsctl(fsdir, fsfd, XFS_IOC_FSBULKSTAT, &bulkreq)) == 0) {
> > +	while ((sts = xfrog_bulkstat(&fsxfd, &last, NBSTAT, buf,
> > +				&count)) == 0) {
> >   		if (count == 0)
> >   			break;
> >   		for (i = 0; i < count; i++)
> >   			quot_bulkstat_add(&buf[i], flags);
> >   	}
> > -	if (sts < 0)
> > -		perror("XFS_IOC_FSBULKSTAT"),
> > +	if (sts < 0) {
> > +		errno = sts;
> > +		perror("XFS_IOC_FSBULKSTAT");
> > +	}
> >   	free(buf);
> > -	close(fsfd);
> > +	xfd_close(&fsxfd);
> >   }
> >   static int
> > diff --git a/scrub/inodes.c b/scrub/inodes.c
> > index 700e5200..413037d8 100644
> > --- a/scrub/inodes.c
> > +++ b/scrub/inodes.c
> > @@ -17,6 +17,7 @@
> >   #include "xfs_scrub.h"
> >   #include "common.h"
> >   #include "inodes.h"
> > +#include "xfrog.h"
> >   /*
> >    * Iterate a range of inodes.
> > @@ -50,17 +51,10 @@ xfs_iterate_inodes_range_check(
> >   	struct xfs_inogrp	*inogrp,
> >   	struct xfs_bstat	*bstat)
> >   {
> > -	struct xfs_fsop_bulkreq	onereq = {NULL};
> >   	struct xfs_bstat	*bs;
> > -	__u64			oneino;
> > -	__s32			onelen = 0;
> >   	int			i;
> >   	int			error;
> > -	onereq.lastip  = &oneino;
> > -	onereq.icount  = 1;
> > -	onereq.ocount  = &onelen;
> > -
> >   	for (i = 0, bs = bstat; i < XFS_INODES_PER_CHUNK; i++) {
> >   		if (!(inogrp->xi_allocmask & (1ULL << i)))
> >   			continue;
> > @@ -70,10 +64,8 @@ xfs_iterate_inodes_range_check(
> >   		}
> >   		/* Load the one inode. */
> > -		oneino = inogrp->xi_startino + i;
> > -		onereq.ubuffer = bs;
> > -		error = ioctl(ctx->mnt.fd, XFS_IOC_FSBULKSTAT_SINGLE,
> > -				&onereq);
> > +		error = xfrog_bulkstat_single(&ctx->mnt,
> > +				inogrp->xi_startino + i, bs);
> >   		if (error || bs->bs_ino != inogrp->xi_startino + i) {
> >   			memset(bs, 0, sizeof(struct xfs_bstat));
> >   			bs->bs_ino = inogrp->xi_startino + i;
> > @@ -99,16 +91,14 @@ xfs_iterate_inodes_range(
> >   	void			*arg)
> >   {
> >   	struct xfs_fsop_bulkreq	igrpreq = {NULL};
> > -	struct xfs_fsop_bulkreq	bulkreq = {NULL};
> >   	struct xfs_handle	handle;
> >   	struct xfs_inogrp	inogrp;
> >   	struct xfs_bstat	bstat[XFS_INODES_PER_CHUNK];
> >   	char			idescr[DESCR_BUFSZ];
> > -	char			buf[DESCR_BUFSZ];
> >   	struct xfs_bstat	*bs;
> >   	__u64			igrp_ino;
> > -	__u64			ino;
> > -	__s32			bulklen = 0;
> > +	uint64_t		ino;
> > +	uint32_t		bulklen = 0;
> >   	__s32			igrplen = 0;
> >   	bool			moveon = true;
> >   	int			i;
> > @@ -117,10 +107,6 @@ xfs_iterate_inodes_range(
> >   	memset(bstat, 0, XFS_INODES_PER_CHUNK * sizeof(struct xfs_bstat));
> > -	bulkreq.lastip  = &ino;
> > -	bulkreq.icount  = XFS_INODES_PER_CHUNK;
> > -	bulkreq.ubuffer = &bstat;
> > -	bulkreq.ocount  = &bulklen;
> >   	igrpreq.lastip  = &igrp_ino;
> >   	igrpreq.icount  = 1;
> > @@ -138,17 +124,17 @@ xfs_iterate_inodes_range(
> >   	while (!error && igrplen) {
> >   		/* Load the inodes. */
> >   		ino = inogrp.xi_startino - 1;
> > -		bulkreq.icount = inogrp.xi_alloccount;
> > +
> >   		/*
> >   		 * We can have totally empty inode chunks on filesystems where
> >   		 * there are more than 64 inodes per block.  Skip these.
> >   		 */
> >   		if (inogrp.xi_alloccount == 0)
> >   			goto igrp_retry;
> > -		error = ioctl(ctx->mnt.fd, XFS_IOC_FSBULKSTAT, &bulkreq);
> > +		error = xfrog_bulkstat(&ctx->mnt, &ino, inogrp.xi_alloccount,
> > +				bstat, &bulklen);
> >   		if (error)
> > -			str_info(ctx, descr, "%s", strerror_r(errno,
> > -						buf, DESCR_BUFSZ));
> > +			str_liberror(ctx, error, descr);
> >   		xfs_iterate_inodes_range_check(ctx, &inogrp, bstat);
> > 

^ permalink raw reply	[flat|nested] 31+ messages in thread

* Re: [PATCH 1/9] libxfs: revert FSGEOMETRY v5 -> v4 hack
  2019-08-30  4:20 ` [PATCH 1/9] libxfs: revert FSGEOMETRY v5 -> v4 hack Darrick J. Wong
  2019-08-30 21:03   ` Allison Collins
@ 2019-09-02 22:49   ` Dave Chinner
  2019-09-03  6:14     ` Christoph Hellwig
  1 sibling, 1 reply; 31+ messages in thread
From: Dave Chinner @ 2019-09-02 22:49 UTC (permalink / raw)
  To: Darrick J. Wong; +Cc: sandeen, linux-xfs

On Thu, Aug 29, 2019 at 09:20:27PM -0700, Darrick J. Wong wrote:
> From: Darrick J. Wong <darrick.wong@oracle.com>
> 
> Revert the #define redirection of XFS_IOC_FSGEOMETRY to the old V4
> ioctl.
> 
> Signed-off-by: Darrick J. Wong <darrick.wong@oracle.com>
> ---
>  libxfs/xfs_fs.h |    4 +---
>  1 file changed, 1 insertion(+), 3 deletions(-)
> 
> 
> diff --git a/libxfs/xfs_fs.h b/libxfs/xfs_fs.h
> index 67fceffc..31ac6323 100644
> --- a/libxfs/xfs_fs.h
> +++ b/libxfs/xfs_fs.h
> @@ -822,9 +822,7 @@ struct xfs_scrub_metadata {
>  #define XFS_IOC_ATTRMULTI_BY_HANDLE  _IOW ('X', 123, struct xfs_fsop_attrmulti_handlereq)
>  #define XFS_IOC_FSGEOMETRY_V4	     _IOR ('X', 124, struct xfs_fsop_geom_v4)
>  #define XFS_IOC_GOINGDOWN	     _IOR ('X', 125, uint32_t)
> -/* For compatibility, for now */
> -/* #define XFS_IOC_FSGEOMETRY	     _IOR ('X', 126, struct xfs_fsop_geom_v5) */
> -#define XFS_IOC_FSGEOMETRY XFS_IOC_FSGEOMETRY_V4
> +#define XFS_IOC_FSGEOMETRY	     _IOR ('X', 126, struct xfs_fsop_geom)
>  #define XFS_IOC_BULKSTAT	     _IOR ('X', 127, struct xfs_bulkstat_req)
>  #define XFS_IOC_INUMBERS	     _IOR ('X', 128, struct xfs_inumbers_req)

Looks fine, but can we change the order of this patch in the series
until after all the geometry callers have been converted to use the
common function with fallback from v5 to v4 calls?

Reviewed-by: Dave Chinner <dchinner@redhat.com>

-- 
Dave Chinner
david@fromorbit.com

^ permalink raw reply	[flat|nested] 31+ messages in thread

* Re: [PATCH 1/9] libxfs: revert FSGEOMETRY v5 -> v4 hack
  2019-09-02 22:49   ` Dave Chinner
@ 2019-09-03  6:14     ` Christoph Hellwig
  0 siblings, 0 replies; 31+ messages in thread
From: Christoph Hellwig @ 2019-09-03  6:14 UTC (permalink / raw)
  To: Dave Chinner; +Cc: Darrick J. Wong, sandeen, linux-xfs

On Tue, Sep 03, 2019 at 08:49:52AM +1000, Dave Chinner wrote:
> On Thu, Aug 29, 2019 at 09:20:27PM -0700, Darrick J. Wong wrote:
> > From: Darrick J. Wong <darrick.wong@oracle.com>
> > 
> > Revert the #define redirection of XFS_IOC_FSGEOMETRY to the old V4
> > ioctl.
> > 
> > Signed-off-by: Darrick J. Wong <darrick.wong@oracle.com>
> > ---
> >  libxfs/xfs_fs.h |    4 +---
> >  1 file changed, 1 insertion(+), 3 deletions(-)
> > 
> > 
> > diff --git a/libxfs/xfs_fs.h b/libxfs/xfs_fs.h
> > index 67fceffc..31ac6323 100644
> > --- a/libxfs/xfs_fs.h
> > +++ b/libxfs/xfs_fs.h
> > @@ -822,9 +822,7 @@ struct xfs_scrub_metadata {
> >  #define XFS_IOC_ATTRMULTI_BY_HANDLE  _IOW ('X', 123, struct xfs_fsop_attrmulti_handlereq)
> >  #define XFS_IOC_FSGEOMETRY_V4	     _IOR ('X', 124, struct xfs_fsop_geom_v4)
> >  #define XFS_IOC_GOINGDOWN	     _IOR ('X', 125, uint32_t)
> > -/* For compatibility, for now */
> > -/* #define XFS_IOC_FSGEOMETRY	     _IOR ('X', 126, struct xfs_fsop_geom_v5) */
> > -#define XFS_IOC_FSGEOMETRY XFS_IOC_FSGEOMETRY_V4
> > +#define XFS_IOC_FSGEOMETRY	     _IOR ('X', 126, struct xfs_fsop_geom)
> >  #define XFS_IOC_BULKSTAT	     _IOR ('X', 127, struct xfs_bulkstat_req)
> >  #define XFS_IOC_INUMBERS	     _IOR ('X', 128, struct xfs_inumbers_req)
> 
> Looks fine, but can we change the order of this patch in the series
> until after all the geometry callers have been converted to use the
> common function with fallback from v5 to v4 calls?
> 
> Reviewed-by: Dave Chinner <dchinner@redhat.com>

I don't really remember this history here, but can we please avoid
using XFS_IOC_FSGEOMETRY for what I assume is the v4 structure, and just
version all of them instead?

^ permalink raw reply	[flat|nested] 31+ messages in thread

* Re: [PATCH 3/9] libfrog: refactor online geometry queries
  2019-08-30  4:20 ` [PATCH 3/9] libfrog: refactor online geometry queries Darrick J. Wong
  2019-08-30 21:03   ` Allison Collins
@ 2019-09-03 22:51   ` Dave Chinner
  1 sibling, 0 replies; 31+ messages in thread
From: Dave Chinner @ 2019-09-03 22:51 UTC (permalink / raw)
  To: Darrick J. Wong; +Cc: sandeen, linux-xfs

On Thu, Aug 29, 2019 at 09:20:41PM -0700, Darrick J. Wong wrote:
> From: Darrick J. Wong <darrick.wong@oracle.com>
> 
> Refactor all the open-coded XFS_IOC_FSGEOMETRY queries into a single
> helper that we can use to standardize behaviors across mixed xfslibs
> versions.  This is the prelude to introducing a new FSGEOMETRY version
> in 5.2 and needing to fix the (relatively few) client programs.
> 
> Signed-off-by: Darrick J. Wong <darrick.wong@oracle.com>

Looks ok.

Reviewed-by: Dave Chinner <dchinner@redhat.com>
-- 
Dave Chinner
david@fromorbit.com

^ permalink raw reply	[flat|nested] 31+ messages in thread

* Re: [PATCH 4/9] libfrog: introduce xfs_fd to wrap an fd to a file on an xfs filesystem
  2019-08-30  4:20 ` [PATCH 4/9] libfrog: introduce xfs_fd to wrap an fd to a file on an xfs filesystem Darrick J. Wong
  2019-08-30 23:29   ` Allison Collins
@ 2019-09-03 22:53   ` Dave Chinner
  1 sibling, 0 replies; 31+ messages in thread
From: Dave Chinner @ 2019-09-03 22:53 UTC (permalink / raw)
  To: Darrick J. Wong; +Cc: sandeen, linux-xfs

On Thu, Aug 29, 2019 at 09:20:47PM -0700, Darrick J. Wong wrote:
> From: Darrick J. Wong <darrick.wong@oracle.com>
> 
> Introduce a new "xfs_fd" context structure where we can store a file
> descriptor and all the runtime fs context (geometry, which ioctls work,
> etc.) that goes with it.  We're going to create wrappers for the
> bulkstat and inumbers ioctls in subsequent patches; and when we
> introduce the v5 bulkstat/inumbers ioctls we'll need all that context to
> downgrade gracefully on old kernels.  Start the transition by adopting
> xfs_fd natively in scrub.
> 
> Signed-off-by: Darrick J. Wong <darrick.wong@oracle.com>

Definitely more readable than the previous version.:)

Reviewed-by: Dave Chinner <dchinner@redhat.com>

-- 
Dave Chinner
david@fromorbit.com

^ permalink raw reply	[flat|nested] 31+ messages in thread

* Re: [PATCH 6/9] libfrog: create online fs geometry converters
  2019-08-30  4:21 ` [PATCH 6/9] libfrog: create online fs geometry converters Darrick J. Wong
  2019-08-31  5:11   ` Allison Collins
@ 2019-09-03 22:55   ` Dave Chinner
  1 sibling, 0 replies; 31+ messages in thread
From: Dave Chinner @ 2019-09-03 22:55 UTC (permalink / raw)
  To: Darrick J. Wong; +Cc: sandeen, linux-xfs

On Thu, Aug 29, 2019 at 09:21:03PM -0700, Darrick J. Wong wrote:
> From: Darrick J. Wong <darrick.wong@oracle.com>
> 
> Create helper functions to perform unit conversions against a runtime
> filesystem, then remove the open-coded versions in scrub.
> 
> Signed-off-by: Darrick J. Wong <darrick.wong@oracle.com>

Looks good. Gives us a clear API for these conversions now.

Reviewed-by: Dave Chinner <dchinner@redhat.com>

-- 
Dave Chinner
david@fromorbit.com

^ permalink raw reply	[flat|nested] 31+ messages in thread

* Re: [PATCH v2 7/9] libfrog: refactor open-coded bulkstat calls
  2019-08-31  0:42   ` [PATCH v2 " Darrick J. Wong
@ 2019-09-03 22:57     ` Dave Chinner
  0 siblings, 0 replies; 31+ messages in thread
From: Dave Chinner @ 2019-09-03 22:57 UTC (permalink / raw)
  To: Darrick J. Wong; +Cc: sandeen, linux-xfs

On Fri, Aug 30, 2019 at 05:42:06PM -0700, Darrick J. Wong wrote:
> From: Darrick J. Wong <darrick.wong@oracle.com>
> 
> Refactor the BULKSTAT_SINGLE and BULKSTAT ioctl callsites into helper
> functions.
> 
> Signed-off-by: Darrick J. Wong <darrick.wong@oracle.com>

Nice to get this all under the one set of functions :)

Reviewed-by: Dave Chinner <dchinner@redhat.com>
-- 
Dave Chinner
david@fromorbit.com

^ permalink raw reply	[flat|nested] 31+ messages in thread

* Re: [PATCH 8/9] libfrog: create xfd_open function
  2019-08-30  4:21 ` [PATCH 8/9] libfrog: create xfd_open function Darrick J. Wong
  2019-09-01 20:55   ` Allison Collins
@ 2019-09-03 23:01   ` Dave Chinner
  2019-09-03 23:37     ` Darrick J. Wong
  1 sibling, 1 reply; 31+ messages in thread
From: Dave Chinner @ 2019-09-03 23:01 UTC (permalink / raw)
  To: Darrick J. Wong; +Cc: sandeen, linux-xfs

On Thu, Aug 29, 2019 at 09:21:15PM -0700, Darrick J. Wong wrote:
> From: Darrick J. Wong <darrick.wong@oracle.com>
> 
> Create a helper to open a file and initialize the xfd structure.
> 
> Signed-off-by: Darrick J. Wong <darrick.wong@oracle.com>
....

>  
> +/* Open a file on an XFS filesystem.  Returns zero or a positive error code. */
> +int
> +xfd_open(
> +	struct xfs_fd		*xfd,
> +	const char		*pathname,
> +	int			flags)
> +{
> +	int			ret;
> +
> +	xfd->fd = open(pathname, O_RDONLY);

open(pathname, flags)

And, to handle all future uses, shouldn't it also pass a mode?
Though I think that can be done as a separate patch when we need
O_RDWR for open....

Otherwise it looks ok.

Cheers,

Dave.
-- 
Dave Chinner
david@fromorbit.com

^ permalink raw reply	[flat|nested] 31+ messages in thread

* Re: [PATCH 8/9] libfrog: create xfd_open function
  2019-09-03 23:01   ` Dave Chinner
@ 2019-09-03 23:37     ` Darrick J. Wong
  0 siblings, 0 replies; 31+ messages in thread
From: Darrick J. Wong @ 2019-09-03 23:37 UTC (permalink / raw)
  To: Dave Chinner; +Cc: sandeen, linux-xfs

On Wed, Sep 04, 2019 at 09:01:21AM +1000, Dave Chinner wrote:
> On Thu, Aug 29, 2019 at 09:21:15PM -0700, Darrick J. Wong wrote:
> > From: Darrick J. Wong <darrick.wong@oracle.com>
> > 
> > Create a helper to open a file and initialize the xfd structure.
> > 
> > Signed-off-by: Darrick J. Wong <darrick.wong@oracle.com>
> ....
> 
> >  
> > +/* Open a file on an XFS filesystem.  Returns zero or a positive error code. */
> > +int
> > +xfd_open(
> > +	struct xfs_fd		*xfd,
> > +	const char		*pathname,
> > +	int			flags)
> > +{
> > +	int			ret;
> > +
> > +	xfd->fd = open(pathname, O_RDONLY);
> 
> open(pathname, flags)

Will fix, good catch!

> And, to handle all future uses, shouldn't it also pass a mode?
> Though I think that can be done as a separate patch when we need
> O_RDWR for open....

<nod> Let's fix that when someone needs it, seeing as libfrog is an
internal static library anyway. :)

--D

> Otherwise it looks ok.
> 
> Cheers,
> 
> Dave.
> -- 
> Dave Chinner
> david@fromorbit.com

^ permalink raw reply	[flat|nested] 31+ messages in thread

end of thread, other threads:[~2019-09-03 23:37 UTC | newest]

Thread overview: 31+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2019-08-30  4:20 [PATCH v2 0/9] libxfrog: wrap version ioctl calls Darrick J. Wong
2019-08-30  4:20 ` [PATCH 1/9] libxfs: revert FSGEOMETRY v5 -> v4 hack Darrick J. Wong
2019-08-30 21:03   ` Allison Collins
2019-09-02 22:49   ` Dave Chinner
2019-09-03  6:14     ` Christoph Hellwig
2019-08-30  4:20 ` [PATCH 2/9] xfsprogs: update spdx tags in LICENSES/ Darrick J. Wong
2019-08-30 21:03   ` Allison Collins
2019-08-30  4:20 ` [PATCH 3/9] libfrog: refactor online geometry queries Darrick J. Wong
2019-08-30 21:03   ` Allison Collins
2019-09-03 22:51   ` Dave Chinner
2019-08-30  4:20 ` [PATCH 4/9] libfrog: introduce xfs_fd to wrap an fd to a file on an xfs filesystem Darrick J. Wong
2019-08-30 23:29   ` Allison Collins
2019-08-30 23:31     ` Darrick J. Wong
2019-09-03 22:53   ` Dave Chinner
2019-08-30  4:20 ` [PATCH 5/9] libfrog: store more inode and block geometry in struct xfs_fd Darrick J. Wong
2019-08-31  0:37   ` Allison Collins
2019-08-30  4:21 ` [PATCH 6/9] libfrog: create online fs geometry converters Darrick J. Wong
2019-08-31  5:11   ` Allison Collins
2019-09-03 22:55   ` Dave Chinner
2019-08-30  4:21 ` [PATCH 7/9] libfrog: refactor open-coded bulkstat calls Darrick J. Wong
2019-08-30 23:26   ` Darrick J. Wong
2019-08-31  0:42   ` [PATCH v2 " Darrick J. Wong
2019-09-03 22:57     ` Dave Chinner
2019-09-01 20:55   ` [PATCH " Allison Collins
2019-09-01 21:05     ` Darrick J. Wong
2019-08-30  4:21 ` [PATCH 8/9] libfrog: create xfd_open function Darrick J. Wong
2019-09-01 20:55   ` Allison Collins
2019-09-03 23:01   ` Dave Chinner
2019-09-03 23:37     ` Darrick J. Wong
2019-08-30  4:21 ` [PATCH 9/9] libfrog: refactor open-coded INUMBERS calls Darrick J. Wong
2019-09-01 20:55   ` Allison Collins

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).