[PATCH 16/20] xfs_fsr: convert to bulkstat v5 ioctls

Darrick J. Wong
2023-12-31T22:31:14Z

Now that libhandle can, er, handle bulkstat information coming from the
v5 bulkstat ioctl, port xfs_fsr to use the new interfaces instead of
repeatedly converting things back and forth.

Signed-off-by: Darrick J. Wong <djwong@kernel.org>
---
fsr/xfs_fsr.c | 148 ++++++++++++++++++++++++++++++------------------------
libfrog/fsgeom.c | 45 ++++++++++++----
libfrog/fsgeom.h | 1
3 files changed, 117 insertions(+), 77 deletions(-)

diff --git a/fsr/xfs_fsr.c b/fsr/xfs_fsr.c
index ba02506d8e4..8e916faee94 100644
--- a/fsr/xfs_fsr.c
+++ b/fsr/xfs_fsr.c
@@ -65,10 +65,10 @@ static int pagesize;

void usage(int ret);
static int fsrfile(char *fname, xfs_ino_t ino);
-static int fsrfile_common( char *fname, char *tname, char *mnt,
- int fd, struct xfs_bstat *statp);
-static int packfile(char *fname, char *tname, int fd,
- struct xfs_bstat *statp, struct fsxattr *fsxp);
+static int fsrfile_common(char *fname, char *tname, char *mnt,
+ struct xfs_fd *file_fd, struct xfs_bulkstat *statp);
+static int packfile(char *fname, char *tname, struct xfs_fd *file_fd,
+ struct xfs_bulkstat *statp, struct fsxattr *fsxp);
static void fsrdir(char *dirname);
static int fsrfs(char *mntdir, xfs_ino_t ino, int targetrange);
static void initallfs(char *mtab);
@@ -80,7 +80,7 @@ int xfs_getrt(int fd, struct statvfs *sfbp);
char * gettmpname(char *fname);
char * getparent(char *fname);
int fsrprintf(const char *fmt, ...);
-int read_fd_bmap(int, struct xfs_bstat *, int *);
+int read_fd_bmap(int, struct xfs_bulkstat *, int *);
static void tmp_init(char *mnt);
static char * tmp_next(char *mnt);
static void tmp_close(char *mnt);
@@ -102,6 +102,26 @@ static int nfrags = 0; /* Debug option: Coerse into specific number
* of extents */
static int openopts = O_CREAT|O_EXCL|O_RDWR|O_DIRECT;

+/*
+ * Open a file on an XFS filesystem from file handle components and fs geometry
+ * data. Returns zero or a negative error code.
+ */
+static int
+open_handle(
+ struct xfs_fd *xfd,
+ jdm_fshandle_t *fshandle,
+ struct xfs_bulkstat *bulkstat,
+ struct xfs_fsop_geom *fsgeom,
+ int flags)
+{
+ xfd->fd = jdm_open_v5(fshandle, bulkstat, flags);
+ if (xfd->fd < 0)
+ return errno;
+
+ xfd_install_geometry(xfd, fsgeom);
+ return 0;
+}
+
static int
xfs_swapext(int fd, xfs_swapext_t *sx)
{
@@ -600,7 +620,6 @@ static int
fsrfs(char *mntdir, xfs_ino_t startino, int targetrange)
{
struct xfs_fd fsxfd = XFS_FD_INIT_EMPTY;
- int fd;
int count = 0;
int ret;
char fname[64];
@@ -638,10 +657,10 @@ fsrfs(char *mntdir, xfs_ino_t startino, int targetrange)
}

while ((ret = -xfrog_bulkstat(&fsxfd, breq) == 0)) {
- struct xfs_bstat bs1;
struct xfs_bulkstat *buf = breq->bulkstat;
struct xfs_bulkstat *p;
struct xfs_bulkstat *endp;
+ struct xfs_fd file_fd = XFS_FD_INIT_EMPTY;
uint32_t buflenout = breq->hdr.ocount;

if (buflenout == 0)
@@ -658,15 +677,9 @@ fsrfs(char *mntdir, xfs_ino_t startino, int targetrange)
(p->bs_extents64 < 2))
continue;

- ret = -xfrog_bulkstat_v5_to_v1(&fsxfd, &bs1, p);
+ ret = open_handle(&file_fd, fshandlep, p,
+ &fsxfd.fsgeom, O_RDWR | O_DIRECT);
if (ret) {
- fsrprintf(_("bstat conversion error: %s\n"),
- strerror(ret));
- continue;
- }
-
- fd = jdm_open(fshandlep, &bs1, O_RDWR | O_DIRECT);
- if (fd < 0) {
/* This probably means the file was
* removed while in progress of handling
* it. Just quietly ignore this file.
@@ -683,11 +696,12 @@ fsrfs(char *mntdir, xfs_ino_t startino, int targetrange)
/* Get a tmp file name */
tname = tmp_next(mntdir);

- ret = fsrfile_common(fname, tname, mntdir, fd, &bs1);
+ ret = fsrfile_common(fname, tname, mntdir, &file_fd,
+ p);

leftoffino = p->bs_ino;

- close(fd);
+ xfd_close(&file_fd);

if (ret == 0) {
if (--count <= 0)
@@ -735,9 +749,8 @@ fsrfile(
{
struct xfs_fd fsxfd = XFS_FD_INIT_EMPTY;
struct xfs_bulkstat bulkstat;
- struct xfs_bstat statbuf;
+ struct xfs_fd file_fd = XFS_FD_INIT_EMPTY;
jdm_fshandle_t *fshandlep;
- int fd = -1;
int error = -1;
char *tname;

@@ -765,17 +778,12 @@ fsrfile(
fname, strerror(error));
goto out;
}
- error = -xfrog_bulkstat_v5_to_v1(&fsxfd, &statbuf, &bulkstat);
- if (error) {
- fsrprintf(_("bstat conversion error on %s: %s\n"),
- fname, strerror(error));
- goto out;
- }

- fd = jdm_open(fshandlep, &statbuf, O_RDWR|O_DIRECT);
- if (fd < 0) {
+ error = open_handle(&file_fd, fshandlep, &bulkstat, &fsxfd.fsgeom,
+ O_RDWR | O_DIRECT);
+ if (error) {
fsrprintf(_("unable to open handle %s: %s\n"),
- fname, strerror(errno));
+ fname, strerror(error));
goto out;
}

@@ -783,14 +791,13 @@ fsrfile(
memcpy(&fsgeom, &fsxfd.fsgeom, sizeof(fsgeom));

tname = gettmpname(fname);
-
if (tname)
- error = fsrfile_common(fname, tname, NULL, fd, &statbuf);
+ error = fsrfile_common(fname, tname, NULL, &file_fd,
+ &bulkstat);

out:
xfd_close(&fsxfd);
- if (fd >= 0)
- close(fd);
+ xfd_close(&file_fd);
free(fshandlep);

return error;
@@ -816,8 +823,8 @@ fsrfile_common(
char *fname,
char *tname,
char *fsname,
- int fd,
- struct xfs_bstat *statp)
+ struct xfs_fd *file_fd,
+ struct xfs_bulkstat *statp)
{
int error;
struct statvfs vfss;
@@ -827,7 +834,7 @@ fsrfile_common(
if (vflag)
fsrprintf("%s\n", fname);

- if (fsync(fd) < 0) {
+ if (fsync(file_fd->fd) < 0) {
fsrprintf(_("sync failed: %s: %s\n"), fname, strerror(errno));
return -1;
}
@@ -851,7 +858,7 @@ fsrfile_common(
fl.l_whence = SEEK_SET;
fl.l_start = (off_t)0;
fl.l_len = 0;
- if ((fcntl(fd, F_GETLK, &fl)) < 0 ) {
+ if ((fcntl(file_fd->fd, F_GETLK, &fl)) < 0 ) {
if (vflag)
fsrprintf(_("locking check failed: %s\n"),
fname);
@@ -869,7 +876,7 @@ fsrfile_common(
/*
* Check if there is room to copy the file.
*
- * Note that xfs_bstat.bs_blksize returns the filesystem blocksize,
+ * Note that xfs_bulkstat.bs_blksize returns the filesystem blocksize,
* not the optimal I/O size as struct stat.
*/
if (statvfs(fsname ? fsname : fname, &vfss) < 0) {
@@ -886,7 +893,7 @@ fsrfile_common(
return 1;
}

- if ((ioctl(fd, FS_IOC_FSGETXATTR, &fsx)) < 0) {
+ if ((ioctl(file_fd->fd, FS_IOC_FSGETXATTR, &fsx)) < 0) {
fsrprintf(_("failed to get inode attrs: %s\n"), fname);
return(-1);
}
@@ -902,7 +909,7 @@ fsrfile_common(
return(0);
}
if (fsx.fsx_xflags & FS_XFLAG_REALTIME) {
- if (xfs_getrt(fd, &vfss) < 0) {
+ if (xfs_getrt(file_fd->fd, &vfss) < 0) {
fsrprintf(_("cannot get realtime geometry for: %s\n"),
fname);
return(-1);
@@ -928,7 +935,7 @@ fsrfile_common(
* file we're defragging, in packfile().
*/

- if ((error = packfile(fname, tname, fd, statp, &fsx)))
+ if ((error = packfile(fname, tname, file_fd, statp, &fsx)))
return error;
return -1; /* no error */
}
@@ -952,7 +959,7 @@ static int
fsr_setup_attr_fork(
int fd,
int tfd,
- struct xfs_bstat *bstatp)
+ struct xfs_bulkstat *bstatp)
{
#ifdef HAVE_FSETXATTR
struct xfs_fd txfd = XFS_FD_INIT(tfd);
@@ -1136,23 +1143,28 @@ fsr_setup_attr_fork(
* 1: No change / No Error
*/
static int
-packfile(char *fname, char *tname, int fd,
- struct xfs_bstat *statp, struct fsxattr *fsxp)
+packfile(
+ char *fname,
+ char *tname,
+ struct xfs_fd *file_fd,
+ struct xfs_bulkstat *statp,
+ struct fsxattr *fsxp)
{
- int tfd = -1;
- int srval;
- int retval = -1; /* Failure is the default */
- int nextents, extent, cur_nextents, new_nextents;
- unsigned blksz_dio;
- unsigned dio_min;
- struct dioattr dio;
- static xfs_swapext_t sx;
- struct xfs_flock64 space;
- off64_t cnt, pos;
- void *fbuf = NULL;
- int ct, wc, wc_b4;
- char ffname[SMBUFSZ];
- int ffd = -1;
+ int tfd = -1;
+ int srval;
+ int retval = -1; /* Failure is the default */
+ int nextents, extent, cur_nextents, new_nextents;
+ unsigned blksz_dio;
+ unsigned dio_min;
+ struct dioattr dio;
+ static xfs_swapext_t sx;
+ struct xfs_flock64 space;
+ off64_t cnt, pos;
+ void *fbuf = NULL;
+ int ct, wc, wc_b4;
+ char ffname[SMBUFSZ];
+ int ffd = -1;
+ int error;

/*
* Work out the extent map - nextents will be set to the
@@ -1160,7 +1172,7 @@ packfile(char *fname, char *tname, int fd,
* into account holes), cur_nextents is the current number
* of extents.
*/
- nextents = read_fd_bmap(fd, statp, &cur_nextents);
+ nextents = read_fd_bmap(file_fd->fd, statp, &cur_nextents);

if (cur_nextents == 1 || cur_nextents <= nextents) {
if (vflag)
@@ -1183,7 +1195,7 @@ packfile(char *fname, char *tname, int fd,
unlink(tname);

/* Setup extended attributes */
- if (fsr_setup_attr_fork(fd, tfd, statp) != 0) {
+ if (fsr_setup_attr_fork(file_fd->fd, tfd, statp) != 0) {
fsrprintf(_("failed to set ATTR fork on tmp: %s:\n"), tname);
goto out;
}
@@ -1301,7 +1313,7 @@ packfile(char *fname, char *tname, int fd,
tname, strerror(errno));
goto out;
}
- if (lseek(fd, outmap[extent].bmv_length, SEEK_CUR) < 0) {
+ if (lseek(file_fd->fd, outmap[extent].bmv_length, SEEK_CUR) < 0) {
fsrprintf(_("could not lseek in file: %s : %s\n"),
fname, strerror(errno));
goto out;
@@ -1321,7 +1333,7 @@ packfile(char *fname, char *tname, int fd,
ct = min(cnt + dio_min - (cnt % dio_min),
blksz_dio);
}
- ct = read(fd, fbuf, ct);
+ ct = read(file_fd->fd, fbuf, ct);
if (ct == 0) {
/* EOF, stop trying to read */
extent = nextents;
@@ -1392,9 +1404,15 @@ packfile(char *fname, char *tname, int fd,
goto out;
}

- sx.sx_stat = *statp; /* struct copy */
+ error = -xfrog_bulkstat_v5_to_v1(file_fd, &sx.sx_stat, statp);
+ if (error) {
+ fsrprintf(_("bstat conversion error on %s: %s\n"),
+ fname, strerror(error));
+ goto out;
+ }
+
sx.sx_version = XFS_SX_VERSION;
- sx.sx_fdtarget = fd;
+ sx.sx_fdtarget = file_fd->fd;
sx.sx_fdtmp = tfd;
sx.sx_offset = 0;
sx.sx_length = statp->bs_size;
@@ -1408,7 +1426,7 @@ packfile(char *fname, char *tname, int fd,
}

/* Swap the extents */
- srval = xfs_swapext(fd, &sx);
+ srval = xfs_swapext(file_fd->fd, &sx);
if (srval < 0) {
if (errno == ENOTSUP) {
if (vflag || dflag)
@@ -1504,7 +1522,7 @@ getparent(char *fname)
#define MAPSIZE 128
#define OUTMAP_SIZE_INCREMENT MAPSIZE

-int read_fd_bmap(int fd, struct xfs_bstat *sin, int *cur_nextents)
+int read_fd_bmap(int fd, struct xfs_bulkstat *sin, int *cur_nextents)
{
int i, cnt;
struct getbmap map[MAPSIZE];
diff --git a/libfrog/fsgeom.c b/libfrog/fsgeom.c
index 3e7f0797d8b..6980d3ffab6 100644
--- a/libfrog/fsgeom.c
+++ b/libfrog/fsgeom.c
@@ -102,29 +102,50 @@ xfrog_geometry(
return -errno;
}

-/*
- * Prepare xfs_fd structure for future ioctl operations by computing the xfs
- * geometry for @xfd->fd. Returns zero or a negative error code.
- */
-int
-xfd_prepare_geometry(
+/* Compute conversion factors of an xfs_fd structure. */
+static void
+xfd_compute_conversion_factors(
struct xfs_fd *xfd)
{
- 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;
xfd->aginolog = xfd->agblklog + xfd->inopblog;
xfd->blkbb_log = xfd->blocklog - BBSHIFT;
+}
+
+/*
+ * Prepare xfs_fd structure for future ioctl operations by computing the xfs
+ * geometry for @xfd->fd. Returns zero or a negative error code.
+ */
+int
+xfd_prepare_geometry(
+ struct xfs_fd *xfd)
+{
+ int ret;
+
+ ret = xfrog_geometry(xfd->fd, &xfd->fsgeom);
+ if (ret)
+ return ret;
+
+ xfd_compute_conversion_factors(xfd);
return 0;
}

+/*
+ * Prepare xfs_fd structure for future ioctl operations by computing the xfs
+ * geometry for @xfd->fd. Returns zero or a negative error code.
+ */
+void
+xfd_install_geometry(
+ struct xfs_fd *xfd,
+ struct xfs_fsop_geom *fsgeom)
+{
+ memcpy(&xfd->fsgeom, fsgeom, sizeof(*fsgeom));
+ xfd_compute_conversion_factors(xfd);
+}
+
/* Open a file on an XFS filesystem. Returns zero or a negative error code. */
int
xfd_open(
diff --git a/libfrog/fsgeom.h b/libfrog/fsgeom.h
index 2ff748caaf4..7e002c5137a 100644
--- a/libfrog/fsgeom.h
+++ b/libfrog/fsgeom.h
@@ -61,6 +61,7 @@ struct xfs_fd {
#define XFS_FD_INIT_EMPTY XFS_FD_INIT(-1)

int xfd_prepare_geometry(struct xfs_fd *xfd);
+void xfd_install_geometry(struct xfs_fd *xfd, struct xfs_fsop_geom *fsgeom);
int xfd_open(struct xfs_fd *xfd, const char *pathname, int flags);
int xfd_close(struct xfs_fd *xfd);