xfs: convert bulkstat to new iwalk infrastructure
Create a new ibulk structure incore to help us deal with bulk inode stat state tracking and then convert the bulkstat code to use the new iwalk iterator. This disentangles inode walking from bulk stat control for simpler code and enables us to isolate the formatter functions to the ioctl handling code. Signed-off-by: Darrick J. Wong <darrick.wong@oracle.com> Reviewed-by: Brian Foster <bfoster@redhat.com>
This commit is contained in:
@@ -12,6 +12,7 @@
|
||||
#include "xfs_mount.h"
|
||||
#include "xfs_inode.h"
|
||||
#include "xfs_rtalloc.h"
|
||||
#include "xfs_iwalk.h"
|
||||
#include "xfs_itable.h"
|
||||
#include "xfs_error.h"
|
||||
#include "xfs_attr.h"
|
||||
@@ -712,16 +713,29 @@ out_unlock:
|
||||
return error;
|
||||
}
|
||||
|
||||
/* Return 0 on success or positive error */
|
||||
int
|
||||
xfs_bulkstat_one_fmt(
|
||||
struct xfs_ibulk *breq,
|
||||
const struct xfs_bstat *bstat)
|
||||
{
|
||||
if (copy_to_user(breq->ubuffer, bstat, sizeof(*bstat)))
|
||||
return -EFAULT;
|
||||
return xfs_ibulk_advance(breq, sizeof(struct xfs_bstat));
|
||||
}
|
||||
|
||||
STATIC int
|
||||
xfs_ioc_bulkstat(
|
||||
xfs_mount_t *mp,
|
||||
unsigned int cmd,
|
||||
void __user *arg)
|
||||
{
|
||||
xfs_fsop_bulkreq_t bulkreq;
|
||||
int count; /* # of records returned */
|
||||
xfs_ino_t inlast; /* last inode number */
|
||||
int done;
|
||||
struct xfs_fsop_bulkreq bulkreq;
|
||||
struct xfs_ibulk breq = {
|
||||
.mp = mp,
|
||||
.ocount = 0,
|
||||
};
|
||||
xfs_ino_t lastino;
|
||||
int error;
|
||||
|
||||
/* done = 1 if there are more stats to get and if bulkstat */
|
||||
@@ -736,35 +750,57 @@ xfs_ioc_bulkstat(
|
||||
if (copy_from_user(&bulkreq, arg, sizeof(xfs_fsop_bulkreq_t)))
|
||||
return -EFAULT;
|
||||
|
||||
if (copy_from_user(&inlast, bulkreq.lastip, sizeof(__s64)))
|
||||
if (copy_from_user(&lastino, bulkreq.lastip, sizeof(__s64)))
|
||||
return -EFAULT;
|
||||
|
||||
if ((count = bulkreq.icount) <= 0)
|
||||
if (bulkreq.icount <= 0)
|
||||
return -EINVAL;
|
||||
|
||||
if (bulkreq.ubuffer == NULL)
|
||||
return -EINVAL;
|
||||
|
||||
if (cmd == XFS_IOC_FSINUMBERS)
|
||||
error = xfs_inumbers(mp, &inlast, &count,
|
||||
breq.ubuffer = bulkreq.ubuffer;
|
||||
breq.icount = bulkreq.icount;
|
||||
|
||||
/*
|
||||
* FSBULKSTAT_SINGLE expects that *lastip contains the inode number
|
||||
* that we want to stat. However, FSINUMBERS and FSBULKSTAT expect
|
||||
* that *lastip contains either zero or the number of the last inode to
|
||||
* be examined by the previous call and return results starting with
|
||||
* the next inode after that. The new bulk request back end functions
|
||||
* take the inode to start with, so we have to compute the startino
|
||||
* parameter from lastino to maintain correct function. lastino == 0
|
||||
* is a special case because it has traditionally meant "first inode
|
||||
* in filesystem".
|
||||
*/
|
||||
if (cmd == XFS_IOC_FSINUMBERS) {
|
||||
int count = breq.icount;
|
||||
|
||||
breq.startino = lastino;
|
||||
error = xfs_inumbers(mp, &breq.startino, &count,
|
||||
bulkreq.ubuffer, xfs_inumbers_fmt);
|
||||
else if (cmd == XFS_IOC_FSBULKSTAT_SINGLE)
|
||||
error = xfs_bulkstat_one(mp, inlast, bulkreq.ubuffer,
|
||||
sizeof(xfs_bstat_t), NULL, &done);
|
||||
else /* XFS_IOC_FSBULKSTAT */
|
||||
error = xfs_bulkstat(mp, &inlast, &count, xfs_bulkstat_one,
|
||||
sizeof(xfs_bstat_t), bulkreq.ubuffer,
|
||||
&done);
|
||||
breq.ocount = count;
|
||||
lastino = breq.startino;
|
||||
} else if (cmd == XFS_IOC_FSBULKSTAT_SINGLE) {
|
||||
breq.startino = lastino;
|
||||
breq.icount = 1;
|
||||
error = xfs_bulkstat_one(&breq, xfs_bulkstat_one_fmt);
|
||||
lastino = breq.startino;
|
||||
} else { /* XFS_IOC_FSBULKSTAT */
|
||||
breq.startino = lastino ? lastino + 1 : 0;
|
||||
error = xfs_bulkstat(&breq, xfs_bulkstat_one_fmt);
|
||||
lastino = breq.startino - 1;
|
||||
}
|
||||
|
||||
if (error)
|
||||
return error;
|
||||
|
||||
if (bulkreq.lastip != NULL &&
|
||||
copy_to_user(bulkreq.lastip, &inlast, sizeof(xfs_ino_t)))
|
||||
copy_to_user(bulkreq.lastip, &lastino, sizeof(xfs_ino_t)))
|
||||
return -EFAULT;
|
||||
|
||||
if (bulkreq.ocount != NULL &&
|
||||
copy_to_user(bulkreq.ocount, &count, sizeof(count)))
|
||||
copy_to_user(bulkreq.ocount, &breq.ocount, sizeof(__s32)))
|
||||
return -EFAULT;
|
||||
|
||||
return 0;
|
||||
|
||||
Reference in New Issue
Block a user