@@ -731,6 +731,7 @@ fsrfile(
xfs_ino_t ino)
{
struct xfs_fd fsxfd = XFS_FD_INIT_EMPTY;
+ struct xfs_bulkstat bulkstat;
struct xfs_bstat statbuf;
jdm_fshandle_t *fshandlep;
int fd = -1;
@@ -761,12 +762,13 @@ fsrfile(
goto out;
}
- error = xfrog_bulkstat_single(&fsxfd, ino, &statbuf);
+ error = xfrog_bulkstat_single(&fsxfd, ino, 0, &bulkstat);
if (error < 0) {
fsrprintf(_("unable to get bstat on %s: %s\n"),
fname, strerror(errno));
goto out;
}
+ xfrog_bulkstat_to_bstat(&fsxfd, &statbuf, &bulkstat);
fd = jdm_open(fshandlep, &statbuf, O_RDWR|O_DIRECT);
if (fd < 0) {
@@ -987,7 +989,7 @@ fsr_setup_attr_fork(
i = 0;
do {
- struct xfs_bstat tbstat;
+ struct xfs_bulkstat tbstat;
char name[64];
int ret;
@@ -996,7 +998,7 @@ fsr_setup_attr_fork(
* this to compare against the target and determine what we
* need to do.
*/
- ret = xfrog_bulkstat_single(&txfd, tstatbuf.st_ino, &tbstat);
+ ret = xfrog_bulkstat_single(&txfd, tstatbuf.st_ino, 0, &tbstat);
if (ret < 0) {
fsrprintf(_("unable to get bstat on temp file: %s\n"),
strerror(errno));
@@ -177,8 +177,8 @@ xfrog_daddr_to_agbno(
/* Bulkstat wrappers */
struct xfs_bstat;
-int xfrog_bulkstat_single(struct xfs_fd *xfd, uint64_t ino,
- struct xfs_bstat *ubuffer);
+int xfrog_bulkstat_single(struct xfs_fd *xfd, uint64_t ino, unsigned int flags,
+ struct xfs_bulkstat *bulkstat);
int xfrog_bulkstat(struct xfs_fd *xfd, struct xfs_bulkstat_req *req);
struct xfs_bulkstat_req *xfrog_bulkstat_alloc_req(uint32_t nr,
@@ -712,7 +712,7 @@ inode_f(
int argc,
char **argv)
{
- struct xfs_bstat bstat;
+ struct xfs_bulkstat bulkstat;
uint64_t result_ino = 0;
uint64_t userino = NULLFSINO;
char *p;
@@ -791,7 +791,7 @@ inode_f(
struct xfs_fd xfd = XFS_FD_INIT(file->fd);
/* get this inode */
- ret = xfrog_bulkstat_single(&xfd, userino, &bstat);
+ ret = xfrog_bulkstat_single(&xfd, userino, 0, &bulkstat);
if (ret && errno == EINVAL) {
/* Not in use */
result_ino = 0;
@@ -800,7 +800,7 @@ inode_f(
exitcode = 1;
return 0;
} else {
- result_ino = bstat.bs_ino;
+ result_ino = bulkstat.bs_ino;
}
}
@@ -27,6 +27,7 @@ swapext_f(
char **argv)
{
struct xfs_fd fxfd = XFS_FD_INIT(file->fd);
+ struct xfs_bulkstat bulkstat;
int fd;
int error;
struct xfs_swapext sx;
@@ -47,11 +48,12 @@ swapext_f(
goto out;
}
- error = xfrog_bulkstat_single(&fxfd, stat.st_ino, &sx.sx_stat);
+ error = xfrog_bulkstat_single(&fxfd, stat.st_ino, 0, &bulkstat);
if (error) {
perror("bulkstat");
goto out;
}
+ xfrog_bulkstat_to_bstat(&fxfd, &sx.sx_stat, &bulkstat);
sx.sx_version = XFS_SX_VERSION;
sx.sx_fdtarget = file->fd;
sx.sx_fdtmp = fd;
@@ -20,22 +20,102 @@ xfrog_bulkstat_prep_v1_emulation(
return 0;
}
-/* Bulkstat a single inode. */
+/* Bulkstat a single inode using v5 ioctl. */
+static int
+xfrog_bulkstat_single5(
+ struct xfs_fd *xfd,
+ uint64_t ino,
+ unsigned int flags,
+ struct xfs_bulkstat *bulkstat)
+{
+ struct xfs_bulkstat_req *req;
+ int ret;
+
+ if (flags & ~(XFS_BULK_IREQ_SPECIAL)) {
+ errno = EINVAL;
+ return -1;
+ }
+
+ req = xfrog_bulkstat_alloc_req(1, ino);
+ if (!req)
+ return -1;
+
+ req->hdr.flags = flags;
+ ret = ioctl(xfd->fd, XFS_IOC_BULKSTAT, req);
+ if (ret)
+ goto free;
+
+ if (req->hdr.ocount == 0) {
+ errno = ENOENT;
+ ret = -1;
+ goto free;
+ }
+
+ memcpy(bulkstat, req->bulkstat, sizeof(struct xfs_bulkstat));
+free:
+ free(req);
+ return ret;
+}
+
+/* Bulkstat a single inode using v1 ioctl. */
+static int
+xfrog_bulkstat_single1(
+ struct xfs_fd *xfd,
+ uint64_t ino,
+ unsigned int flags,
+ struct xfs_bulkstat *bulkstat)
+{
+ struct xfs_bstat bstat;
+ struct xfs_fsop_bulkreq bulkreq = { 0 };
+ int error;
+
+ if (flags) {
+ errno = EINVAL;
+ return -1;
+ }
+
+ error = xfrog_bulkstat_prep_v1_emulation(xfd);
+ if (error)
+ return error;
+
+ bulkreq.lastip = (__u64 *)&ino;
+ bulkreq.icount = 1;
+ bulkreq.ubuffer = &bstat;
+ error = ioctl(xfd->fd, XFS_IOC_FSBULKSTAT_SINGLE, &bulkreq);
+ if (error)
+ return error;
+
+ xfrog_bstat_to_bulkstat(xfd, bulkstat, &bstat);
+ return 0;
+}
+
+/* Bulkstat a single inode using v1 ioctl. */
int
xfrog_bulkstat_single(
- struct xfs_fd *xfd,
- uint64_t ino,
- struct xfs_bstat *ubuffer)
+ struct xfs_fd *xfd,
+ uint64_t ino,
+ unsigned int flags,
+ struct xfs_bulkstat *bulkstat)
{
- __u64 i = ino;
- struct xfs_fsop_bulkreq bulkreq = {
- .lastip = &i,
- .icount = 1,
- .ubuffer = ubuffer,
- .ocount = NULL,
- };
+ int error;
+
+ if (xfd->flags & XFROG_FLAG_BULKSTAT_FORCE_V1)
+ goto try_v1;
+
+ error = xfrog_bulkstat_single5(xfd, ino, flags, bulkstat);
+ if (error == 0 || (xfd->flags & XFROG_FLAG_BULKSTAT_FORCE_V5))
+ return 0;
- return ioctl(xfd->fd, XFS_IOC_FSBULKSTAT_SINGLE, &bulkreq);
+ /* If the v5 ioctl wasn't found, we punt to v1. */
+ switch (errno) {
+ case EOPNOTSUPP:
+ case ENOTTY:
+ xfd->flags |= XFROG_FLAG_BULKSTAT_FORCE_V1;
+ break;
+ }
+
+try_v1:
+ return xfrog_bulkstat_single1(xfd, ino, flags, bulkstat);
}
/*
@@ -56,8 +56,6 @@ xfs_iterate_inodes_range_check(
int error;
for (i = 0, bs = bstat; i < XFS_INODES_PER_CHUNK; i++) {
- struct xfs_bstat bs1;
-
if (!(inogrp->xi_allocmask & (1ULL << i)))
continue;
if (bs->bs_ino == inogrp->xi_startino + i) {
@@ -67,13 +65,11 @@ xfs_iterate_inodes_range_check(
/* Load the one inode. */
error = xfrog_bulkstat_single(&ctx->mnt,
- inogrp->xi_startino + i, &bs1);
- if (error || bs1.bs_ino != inogrp->xi_startino + i) {
+ inogrp->xi_startino + i, 0, bs);
+ if (error || bs->bs_ino != inogrp->xi_startino + i) {
memset(bs, 0, sizeof(struct xfs_bulkstat));
bs->bs_ino = inogrp->xi_startino + i;
bs->bs_blksize = ctx->mnt_sv.f_frsize;
- } else {
- xfrog_bstat_to_bulkstat(&ctx->mnt, bs, &bs1);
}
bs++;
}
@@ -208,7 +208,7 @@ report_inode_health(
unsigned long long ino,
const char *descr)
{
- struct xfs_bstat bs;
+ struct xfs_bulkstat bs;
char d[256];
int ret;
@@ -217,7 +217,7 @@ report_inode_health(
descr = d;
}
- ret = xfrog_bulkstat_single(&file->xfd, ino, &bs);
+ ret = xfrog_bulkstat_single(&file->xfd, ino, 0, &bs);
if (ret) {
perror(descr);
return 1;