All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH v6 0/9] xfs: introduce new BULKSTAT and INUMBERS ioctls
@ 2019-06-26 20:45 Darrick J. Wong
  2019-06-26 20:45 ` [PATCH 1/9] xfs: remove various bulk request typedef usage Darrick J. Wong
                   ` (8 more replies)
  0 siblings, 9 replies; 34+ messages in thread
From: Darrick J. Wong @ 2019-06-26 20:45 UTC (permalink / raw)
  To: darrick.wong; +Cc: linux-xfs, allison.henderson

Hi all,

Now that we've cleaned up the inode walking code, introduce new BULKSTAT
and INUMBERS ioctls.  The new ioctls will report V5 features such as
inode birth time and the ability to do per-AG BULKSTAT and INUMBERS.
The new structures fix the alignment and padding issues that plague the
old ioctls.  In xfsprogs, we will introduce some xfrog_* wrapper
functions that allow new utilities to run on old kernels by emulating
the new functionality.

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

kernel git tree:
https://git.kernel.org/cgit/linux/kernel/git/djwong/xfs-linux.git/log/?h=bulkstat-v5

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

fstests git tree:
https://git.kernel.org/cgit/linux/kernel/git/djwong/xfstests-dev.git/log/?h=bulkstat-v5

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

* [PATCH 1/9] xfs: remove various bulk request typedef usage
  2019-06-26 20:45 [PATCH v6 0/9] xfs: introduce new BULKSTAT and INUMBERS ioctls Darrick J. Wong
@ 2019-06-26 20:45 ` Darrick J. Wong
  2019-07-03 13:22   ` Brian Foster
  2019-06-26 20:45 ` [PATCH 2/9] xfs: rename bulkstat functions Darrick J. Wong
                   ` (7 subsequent siblings)
  8 siblings, 1 reply; 34+ messages in thread
From: Darrick J. Wong @ 2019-06-26 20:45 UTC (permalink / raw)
  To: darrick.wong; +Cc: linux-xfs, allison.henderson

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

Remove xfs_bstat_t, xfs_fsop_bulkreq_t, xfs_inogrp_t, and similarly
named compat typedefs.

Signed-off-by: Darrick J. Wong <darrick.wong@oracle.com>
Reviewed-by: Allison Collins <allison.henderson@oracle.com>
---
 fs/xfs/libxfs/xfs_fs.h |   16 ++++++++--------
 fs/xfs/xfs_ioctl.c     |    2 +-
 fs/xfs/xfs_ioctl32.c   |   11 +++++++----
 fs/xfs/xfs_ioctl32.h   |   14 +++++++-------
 4 files changed, 23 insertions(+), 20 deletions(-)


diff --git a/fs/xfs/libxfs/xfs_fs.h b/fs/xfs/libxfs/xfs_fs.h
index e7382c780ed7..ef0dce229fa4 100644
--- a/fs/xfs/libxfs/xfs_fs.h
+++ b/fs/xfs/libxfs/xfs_fs.h
@@ -97,7 +97,7 @@ struct getbmapx {
  * For use by backup and restore programs to set the XFS on-disk inode
  * fields di_dmevmask and di_dmstate.  These must be set to exactly and
  * only values previously obtained via xfs_bulkstat!  (Specifically the
- * xfs_bstat_t fields bs_dmevmask and bs_dmstate.)
+ * struct xfs_bstat fields bs_dmevmask and bs_dmstate.)
  */
 #ifndef HAVE_FSDMIDATA
 struct fsdmidata {
@@ -328,7 +328,7 @@ typedef struct xfs_bstime {
 	__s32		tv_nsec;	/* and nanoseconds	*/
 } xfs_bstime_t;
 
-typedef struct xfs_bstat {
+struct xfs_bstat {
 	__u64		bs_ino;		/* inode number			*/
 	__u16		bs_mode;	/* type and mode		*/
 	__u16		bs_nlink;	/* number of links		*/
@@ -356,7 +356,7 @@ typedef struct xfs_bstat {
 	__u32		bs_dmevmask;	/* DMIG event mask		*/
 	__u16		bs_dmstate;	/* DMIG state info		*/
 	__u16		bs_aextents;	/* attribute number of extents	*/
-} xfs_bstat_t;
+};
 
 /* bs_sick flags */
 #define XFS_BS_SICK_INODE	(1 << 0)  /* inode core */
@@ -382,22 +382,22 @@ bstat_get_projid(struct xfs_bstat *bs)
 /*
  * The user-level BulkStat Request interface structure.
  */
-typedef struct xfs_fsop_bulkreq {
+struct xfs_fsop_bulkreq {
 	__u64		__user *lastip;	/* last inode # pointer		*/
 	__s32		icount;		/* count of entries in buffer	*/
 	void		__user *ubuffer;/* user buffer for inode desc.	*/
 	__s32		__user *ocount;	/* output count pointer		*/
-} xfs_fsop_bulkreq_t;
+};
 
 
 /*
  * Structures returned from xfs_inumbers routine (XFS_IOC_FSINUMBERS).
  */
-typedef struct xfs_inogrp {
+struct xfs_inogrp {
 	__u64		xi_startino;	/* starting inode number	*/
 	__s32		xi_alloccount;	/* # bits set in allocmask	*/
 	__u64		xi_allocmask;	/* mask of allocated inodes	*/
-} xfs_inogrp_t;
+};
 
 
 /*
@@ -529,7 +529,7 @@ typedef struct xfs_swapext
 	xfs_off_t	sx_offset;	/* offset into file */
 	xfs_off_t	sx_length;	/* leng from offset */
 	char		sx_pad[16];	/* pad space, unused */
-	xfs_bstat_t	sx_stat;	/* stat of target b4 copy */
+	struct xfs_bstat sx_stat;	/* stat of target b4 copy */
 } xfs_swapext_t;
 
 /*
diff --git a/fs/xfs/xfs_ioctl.c b/fs/xfs/xfs_ioctl.c
index 04b661ff0799..34b38d8e8dc9 100644
--- a/fs/xfs/xfs_ioctl.c
+++ b/fs/xfs/xfs_ioctl.c
@@ -766,7 +766,7 @@ xfs_ioc_bulkstat(
 	if (XFS_FORCED_SHUTDOWN(mp))
 		return -EIO;
 
-	if (copy_from_user(&bulkreq, arg, sizeof(xfs_fsop_bulkreq_t)))
+	if (copy_from_user(&bulkreq, arg, sizeof(struct xfs_fsop_bulkreq)))
 		return -EFAULT;
 
 	if (copy_from_user(&lastino, bulkreq.lastip, sizeof(__s64)))
diff --git a/fs/xfs/xfs_ioctl32.c b/fs/xfs/xfs_ioctl32.c
index f3949684c49c..d7c5153e1b61 100644
--- a/fs/xfs/xfs_ioctl32.c
+++ b/fs/xfs/xfs_ioctl32.c
@@ -118,11 +118,14 @@ xfs_ioctl32_bstime_copyin(
 	return 0;
 }
 
-/* xfs_bstat_t has differing alignment on intel, & bstime_t sizes everywhere */
+/*
+ * struct xfs_bstat has differing alignment on intel, & bstime_t sizes
+ * everywhere
+ */
 STATIC int
 xfs_ioctl32_bstat_copyin(
-	xfs_bstat_t		*bstat,
-	compat_xfs_bstat_t	__user *bstat32)
+	struct xfs_bstat		*bstat,
+	struct compat_xfs_bstat	__user	*bstat32)
 {
 	if (get_user(bstat->bs_ino,	&bstat32->bs_ino)	||
 	    get_user(bstat->bs_mode,	&bstat32->bs_mode)	||
@@ -206,7 +209,7 @@ STATIC int
 xfs_compat_ioc_bulkstat(
 	xfs_mount_t		  *mp,
 	unsigned int		  cmd,
-	compat_xfs_fsop_bulkreq_t __user *p32)
+	struct compat_xfs_fsop_bulkreq __user *p32)
 {
 	u32			addr;
 	struct xfs_fsop_bulkreq	bulkreq;
diff --git a/fs/xfs/xfs_ioctl32.h b/fs/xfs/xfs_ioctl32.h
index d28fa824284a..7985344d3aa6 100644
--- a/fs/xfs/xfs_ioctl32.h
+++ b/fs/xfs/xfs_ioctl32.h
@@ -36,7 +36,7 @@ typedef struct compat_xfs_bstime {
 	__s32		tv_nsec;	/* and nanoseconds	*/
 } compat_xfs_bstime_t;
 
-typedef struct compat_xfs_bstat {
+struct compat_xfs_bstat {
 	__u64		bs_ino;		/* inode number			*/
 	__u16		bs_mode;	/* type and mode		*/
 	__u16		bs_nlink;	/* number of links		*/
@@ -61,14 +61,14 @@ typedef struct compat_xfs_bstat {
 	__u32		bs_dmevmask;	/* DMIG event mask		*/
 	__u16		bs_dmstate;	/* DMIG state info		*/
 	__u16		bs_aextents;	/* attribute number of extents	*/
-} __compat_packed compat_xfs_bstat_t;
+} __compat_packed;
 
-typedef struct compat_xfs_fsop_bulkreq {
+struct compat_xfs_fsop_bulkreq {
 	compat_uptr_t	lastip;		/* last inode # pointer		*/
 	__s32		icount;		/* count of entries in buffer	*/
 	compat_uptr_t	ubuffer;	/* user buffer for inode desc.	*/
 	compat_uptr_t	ocount;		/* output count pointer		*/
-} compat_xfs_fsop_bulkreq_t;
+};
 
 #define XFS_IOC_FSBULKSTAT_32 \
 	_IOWR('X', 101, struct compat_xfs_fsop_bulkreq)
@@ -106,7 +106,7 @@ typedef struct compat_xfs_swapext {
 	xfs_off_t		sx_offset;	/* offset into file */
 	xfs_off_t		sx_length;	/* leng from offset */
 	char			sx_pad[16];	/* pad space, unused */
-	compat_xfs_bstat_t	sx_stat;	/* stat of target b4 copy */
+	struct compat_xfs_bstat	sx_stat;	/* stat of target b4 copy */
 } __compat_packed compat_xfs_swapext_t;
 
 #define XFS_IOC_SWAPEXT_32	_IOWR('X', 109, struct compat_xfs_swapext)
@@ -201,11 +201,11 @@ typedef struct compat_xfs_fsop_geom_v1 {
 #define XFS_IOC_FSGEOMETRY_V1_32  \
 	_IOR('X', 100, struct compat_xfs_fsop_geom_v1)
 
-typedef struct compat_xfs_inogrp {
+struct compat_xfs_inogrp {
 	__u64		xi_startino;	/* starting inode number	*/
 	__s32		xi_alloccount;	/* # bits set in allocmask	*/
 	__u64		xi_allocmask;	/* mask of allocated inodes	*/
-} __attribute__((packed)) compat_xfs_inogrp_t;
+} __attribute__((packed));
 
 /* These growfs input structures have padding on the end, so must translate */
 typedef struct compat_xfs_growfs_data {

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

* [PATCH 2/9] xfs: rename bulkstat functions
  2019-06-26 20:45 [PATCH v6 0/9] xfs: introduce new BULKSTAT and INUMBERS ioctls Darrick J. Wong
  2019-06-26 20:45 ` [PATCH 1/9] xfs: remove various bulk request typedef usage Darrick J. Wong
@ 2019-06-26 20:45 ` Darrick J. Wong
  2019-07-03 13:22   ` Brian Foster
  2019-06-26 20:45 ` [PATCH 3/9] xfs: introduce new v5 bulkstat structure Darrick J. Wong
                   ` (6 subsequent siblings)
  8 siblings, 1 reply; 34+ messages in thread
From: Darrick J. Wong @ 2019-06-26 20:45 UTC (permalink / raw)
  To: darrick.wong; +Cc: linux-xfs, allison.henderson

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

Rename the bulkstat functions to 'fsbulkstat' so that they match the
ioctl names.  We will be introducing a new set of bulkstat/inumbers
ioctls soon, and it will be important to keep the names straight.

Signed-off-by: Darrick J. Wong <darrick.wong@oracle.com>
Reviewed-by: Allison Collins <allison.henderson@oracle.com>
---
 fs/xfs/xfs_ioctl.c   |   14 +++++++-------
 fs/xfs/xfs_ioctl.h   |    5 +++--
 fs/xfs/xfs_ioctl32.c |   18 +++++++++---------
 3 files changed, 19 insertions(+), 18 deletions(-)


diff --git a/fs/xfs/xfs_ioctl.c b/fs/xfs/xfs_ioctl.c
index 34b38d8e8dc9..5e0476003763 100644
--- a/fs/xfs/xfs_ioctl.c
+++ b/fs/xfs/xfs_ioctl.c
@@ -724,7 +724,7 @@ xfs_ioc_space(
 
 /* Return 0 on success or positive error */
 int
-xfs_bulkstat_one_fmt(
+xfs_fsbulkstat_one_fmt(
 	struct xfs_ibulk	*breq,
 	const struct xfs_bstat	*bstat)
 {
@@ -734,7 +734,7 @@ xfs_bulkstat_one_fmt(
 }
 
 int
-xfs_inumbers_fmt(
+xfs_fsinumbers_fmt(
 	struct xfs_ibulk	*breq,
 	const struct xfs_inogrp	*igrp)
 {
@@ -744,7 +744,7 @@ xfs_inumbers_fmt(
 }
 
 STATIC int
-xfs_ioc_bulkstat(
+xfs_ioc_fsbulkstat(
 	xfs_mount_t		*mp,
 	unsigned int		cmd,
 	void			__user *arg)
@@ -794,16 +794,16 @@ xfs_ioc_bulkstat(
 	 */
 	if (cmd == XFS_IOC_FSINUMBERS) {
 		breq.startino = lastino ? lastino + 1 : 0;
-		error = xfs_inumbers(&breq, xfs_inumbers_fmt);
+		error = xfs_inumbers(&breq, xfs_fsinumbers_fmt);
 		lastino = breq.startino - 1;
 	} else if (cmd == XFS_IOC_FSBULKSTAT_SINGLE) {
 		breq.startino = lastino;
 		breq.icount = 1;
-		error = xfs_bulkstat_one(&breq, xfs_bulkstat_one_fmt);
+		error = xfs_bulkstat_one(&breq, xfs_fsbulkstat_one_fmt);
 		lastino = breq.startino;
 	} else {	/* XFS_IOC_FSBULKSTAT */
 		breq.startino = lastino ? lastino + 1 : 0;
-		error = xfs_bulkstat(&breq, xfs_bulkstat_one_fmt);
+		error = xfs_bulkstat(&breq, xfs_fsbulkstat_one_fmt);
 		lastino = breq.startino - 1;
 	}
 
@@ -1983,7 +1983,7 @@ xfs_file_ioctl(
 	case XFS_IOC_FSBULKSTAT_SINGLE:
 	case XFS_IOC_FSBULKSTAT:
 	case XFS_IOC_FSINUMBERS:
-		return xfs_ioc_bulkstat(mp, cmd, arg);
+		return xfs_ioc_fsbulkstat(mp, cmd, arg);
 
 	case XFS_IOC_FSGEOMETRY_V1:
 		return xfs_ioc_fsgeometry(mp, arg, 3);
diff --git a/fs/xfs/xfs_ioctl.h b/fs/xfs/xfs_ioctl.h
index fb303eaa8863..cb34bc821201 100644
--- a/fs/xfs/xfs_ioctl.h
+++ b/fs/xfs/xfs_ioctl.h
@@ -81,7 +81,8 @@ struct xfs_ibulk;
 struct xfs_bstat;
 struct xfs_inogrp;
 
-int xfs_bulkstat_one_fmt(struct xfs_ibulk *breq, const struct xfs_bstat *bstat);
-int xfs_inumbers_fmt(struct xfs_ibulk *breq, const struct xfs_inogrp *igrp);
+int xfs_fsbulkstat_one_fmt(struct xfs_ibulk *breq,
+			   const struct xfs_bstat *bstat);
+int xfs_fsinumbers_fmt(struct xfs_ibulk *breq, const struct xfs_inogrp *igrp);
 
 #endif
diff --git a/fs/xfs/xfs_ioctl32.c b/fs/xfs/xfs_ioctl32.c
index d7c5153e1b61..9e5cf3988d3e 100644
--- a/fs/xfs/xfs_ioctl32.c
+++ b/fs/xfs/xfs_ioctl32.c
@@ -86,7 +86,7 @@ xfs_compat_growfs_rt_copyin(
 }
 
 STATIC int
-xfs_inumbers_fmt_compat(
+xfs_fsinumbers_fmt_compat(
 	struct xfs_ibulk	*breq,
 	const struct xfs_inogrp	*igrp)
 {
@@ -101,7 +101,7 @@ xfs_inumbers_fmt_compat(
 }
 
 #else
-#define xfs_inumbers_fmt_compat xfs_inumbers_fmt
+#define xfs_fsinumbers_fmt_compat xfs_fsinumbers_fmt
 #endif	/* BROKEN_X86_ALIGNMENT */
 
 STATIC int
@@ -171,7 +171,7 @@ xfs_bstime_store_compat(
 
 /* Return 0 on success or positive error (to xfs_bulkstat()) */
 STATIC int
-xfs_bulkstat_one_fmt_compat(
+xfs_fsbulkstat_one_fmt_compat(
 	struct xfs_ibulk	*breq,
 	const struct xfs_bstat	*buffer)
 {
@@ -206,7 +206,7 @@ xfs_bulkstat_one_fmt_compat(
 
 /* copied from xfs_ioctl.c */
 STATIC int
-xfs_compat_ioc_bulkstat(
+xfs_compat_ioc_fsbulkstat(
 	xfs_mount_t		  *mp,
 	unsigned int		  cmd,
 	struct compat_xfs_fsop_bulkreq __user *p32)
@@ -226,8 +226,8 @@ xfs_compat_ioc_bulkstat(
 	 * to userpace memory via bulkreq.ubuffer.  Normally the compat
 	 * functions and structure size are the correct ones to use ...
 	 */
-	inumbers_fmt_pf		inumbers_func = xfs_inumbers_fmt_compat;
-	bulkstat_one_fmt_pf	bs_one_func = xfs_bulkstat_one_fmt_compat;
+	inumbers_fmt_pf		inumbers_func = xfs_fsinumbers_fmt_compat;
+	bulkstat_one_fmt_pf	bs_one_func = xfs_fsbulkstat_one_fmt_compat;
 
 #ifdef CONFIG_X86_X32
 	if (in_x32_syscall()) {
@@ -239,8 +239,8 @@ xfs_compat_ioc_bulkstat(
 		 * the data written out in compat layout will not match what
 		 * x32 userspace expects.
 		 */
-		inumbers_func = xfs_inumbers_fmt;
-		bs_one_func = xfs_bulkstat_one_fmt;
+		inumbers_func = xfs_fsinumbers_fmt;
+		bs_one_func = xfs_fsbulkstat_one_fmt;
 	}
 #endif
 
@@ -669,7 +669,7 @@ xfs_file_compat_ioctl(
 	case XFS_IOC_FSBULKSTAT_32:
 	case XFS_IOC_FSBULKSTAT_SINGLE_32:
 	case XFS_IOC_FSINUMBERS_32:
-		return xfs_compat_ioc_bulkstat(mp, cmd, arg);
+		return xfs_compat_ioc_fsbulkstat(mp, cmd, arg);
 	case XFS_IOC_FD_TO_HANDLE_32:
 	case XFS_IOC_PATH_TO_HANDLE_32:
 	case XFS_IOC_PATH_TO_FSHANDLE_32: {

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

* [PATCH 3/9] xfs: introduce new v5 bulkstat structure
  2019-06-26 20:45 [PATCH v6 0/9] xfs: introduce new BULKSTAT and INUMBERS ioctls Darrick J. Wong
  2019-06-26 20:45 ` [PATCH 1/9] xfs: remove various bulk request typedef usage Darrick J. Wong
  2019-06-26 20:45 ` [PATCH 2/9] xfs: rename bulkstat functions Darrick J. Wong
@ 2019-06-26 20:45 ` Darrick J. Wong
  2019-07-03 13:23   ` Brian Foster
  2019-07-03 15:32   ` [PATCH v2 " Darrick J. Wong
  2019-06-26 20:45 ` [PATCH 4/9] xfs: introduce v5 inode group structure Darrick J. Wong
                   ` (5 subsequent siblings)
  8 siblings, 2 replies; 34+ messages in thread
From: Darrick J. Wong @ 2019-06-26 20:45 UTC (permalink / raw)
  To: darrick.wong; +Cc: linux-xfs, allison.henderson

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

Introduce a new version of the in-core bulkstat structure that supports
our new v5 format features.  This structure also fills the gaps in the
previous structure.  We leave wiring up the ioctls for the next patch.

Signed-off-by: Darrick J. Wong <darrick.wong@oracle.com>
Reviewed-by: Allison Collins <allison.henderson@oracle.com>
---
 fs/xfs/libxfs/xfs_fs.h     |   48 ++++++++++++++++++++++++++++
 fs/xfs/libxfs/xfs_health.h |    2 +
 fs/xfs/xfs_health.c        |    2 +
 fs/xfs/xfs_ioctl.c         |    9 ++++-
 fs/xfs/xfs_ioctl.h         |    2 +
 fs/xfs/xfs_ioctl32.c       |   10 ++++--
 fs/xfs/xfs_itable.c        |   75 +++++++++++++++++++++++++++++++++-----------
 fs/xfs/xfs_itable.h        |    4 ++
 fs/xfs/xfs_ondisk.h        |    2 +
 9 files changed, 124 insertions(+), 30 deletions(-)


diff --git a/fs/xfs/libxfs/xfs_fs.h b/fs/xfs/libxfs/xfs_fs.h
index ef0dce229fa4..132e364eb141 100644
--- a/fs/xfs/libxfs/xfs_fs.h
+++ b/fs/xfs/libxfs/xfs_fs.h
@@ -358,6 +358,52 @@ struct xfs_bstat {
 	__u16		bs_aextents;	/* attribute number of extents	*/
 };
 
+/* New bulkstat structure that reports v5 features and fixes padding issues */
+struct xfs_bulkstat {
+	uint64_t	bs_ino;		/* inode number			*/
+	uint64_t	bs_size;	/* file size			*/
+
+	uint64_t	bs_blocks;	/* number of blocks		*/
+	uint64_t	bs_xflags;	/* extended flags		*/
+
+	uint64_t	bs_atime;	/* access time, seconds		*/
+	uint64_t	bs_mtime;	/* modify time, seconds		*/
+
+	uint64_t	bs_ctime;	/* inode change time, seconds	*/
+	uint64_t	bs_btime;	/* creation time, seconds	*/
+
+	uint32_t	bs_gen;		/* generation count		*/
+	uint32_t	bs_uid;		/* user id			*/
+	uint32_t	bs_gid;		/* group id			*/
+	uint32_t	bs_projectid;	/* project id			*/
+
+	uint32_t	bs_atime_nsec;	/* access time, nanoseconds	*/
+	uint32_t	bs_mtime_nsec;	/* modify time, nanoseconds	*/
+	uint32_t	bs_ctime_nsec;	/* inode change time, nanoseconds */
+	uint32_t	bs_btime_nsec;	/* creation time, nanoseconds	*/
+
+	uint32_t	bs_blksize;	/* block size			*/
+	uint32_t	bs_rdev;	/* device value			*/
+	uint32_t	bs_cowextsize_blks; /* cow extent size hint, blocks */
+	uint32_t	bs_extsize_blks; /* extent size hint, blocks	*/
+
+	uint32_t	bs_nlink;	/* number of links		*/
+	uint32_t	bs_extents;	/* number of extents		*/
+	uint32_t	bs_aextents;	/* attribute number of extents	*/
+	uint16_t	bs_version;	/* structure version		*/
+	uint16_t	bs_forkoff;	/* inode fork offset in bytes	*/
+
+	uint16_t	bs_sick;	/* sick inode metadata		*/
+	uint16_t	bs_checked;	/* checked inode metadata	*/
+	uint16_t	bs_mode;	/* type and mode		*/
+	uint16_t	bs_pad2;	/* zeroed			*/
+
+	uint64_t	bs_pad[7];	/* zeroed			*/
+};
+
+#define XFS_BULKSTAT_VERSION_V1	(1)
+#define XFS_BULKSTAT_VERSION_V5	(5)
+
 /* bs_sick flags */
 #define XFS_BS_SICK_INODE	(1 << 0)  /* inode core */
 #define XFS_BS_SICK_BMBTD	(1 << 1)  /* data fork */
@@ -374,7 +420,7 @@ struct xfs_bstat {
  * to retain compatibility with "old" filesystems).
  */
 static inline uint32_t
-bstat_get_projid(struct xfs_bstat *bs)
+bstat_get_projid(const struct xfs_bstat *bs)
 {
 	return (uint32_t)bs->bs_projid_hi << 16 | bs->bs_projid_lo;
 }
diff --git a/fs/xfs/libxfs/xfs_health.h b/fs/xfs/libxfs/xfs_health.h
index 49ddfeac19f2..272005ac8c88 100644
--- a/fs/xfs/libxfs/xfs_health.h
+++ b/fs/xfs/libxfs/xfs_health.h
@@ -185,6 +185,6 @@ xfs_inode_is_healthy(struct xfs_inode *ip)
 
 void xfs_fsop_geom_health(struct xfs_mount *mp, struct xfs_fsop_geom *geo);
 void xfs_ag_geom_health(struct xfs_perag *pag, struct xfs_ag_geometry *ageo);
-void xfs_bulkstat_health(struct xfs_inode *ip, struct xfs_bstat *bs);
+void xfs_bulkstat_health(struct xfs_inode *ip, struct xfs_bulkstat *bs);
 
 #endif	/* __XFS_HEALTH_H__ */
diff --git a/fs/xfs/xfs_health.c b/fs/xfs/xfs_health.c
index 4c4929f9e7bf..e8ba6034b0db 100644
--- a/fs/xfs/xfs_health.c
+++ b/fs/xfs/xfs_health.c
@@ -373,7 +373,7 @@ static const struct ioctl_sick_map ino_map[] = {
 void
 xfs_bulkstat_health(
 	struct xfs_inode		*ip,
-	struct xfs_bstat		*bs)
+	struct xfs_bulkstat		*bs)
 {
 	const struct ioctl_sick_map	*m;
 	unsigned int			sick;
diff --git a/fs/xfs/xfs_ioctl.c b/fs/xfs/xfs_ioctl.c
index 5e0476003763..0b8c631d53dd 100644
--- a/fs/xfs/xfs_ioctl.c
+++ b/fs/xfs/xfs_ioctl.c
@@ -725,10 +725,13 @@ xfs_ioc_space(
 /* Return 0 on success or positive error */
 int
 xfs_fsbulkstat_one_fmt(
-	struct xfs_ibulk	*breq,
-	const struct xfs_bstat	*bstat)
+	struct xfs_ibulk		*breq,
+	const struct xfs_bulkstat	*bstat)
 {
-	if (copy_to_user(breq->ubuffer, bstat, sizeof(*bstat)))
+	struct xfs_bstat		bs1;
+
+	xfs_bulkstat_to_bstat(breq->mp, &bs1, bstat);
+	if (copy_to_user(breq->ubuffer, &bs1, sizeof(bs1)))
 		return -EFAULT;
 	return xfs_ibulk_advance(breq, sizeof(struct xfs_bstat));
 }
diff --git a/fs/xfs/xfs_ioctl.h b/fs/xfs/xfs_ioctl.h
index cb34bc821201..514d3028a134 100644
--- a/fs/xfs/xfs_ioctl.h
+++ b/fs/xfs/xfs_ioctl.h
@@ -82,7 +82,7 @@ struct xfs_bstat;
 struct xfs_inogrp;
 
 int xfs_fsbulkstat_one_fmt(struct xfs_ibulk *breq,
-			   const struct xfs_bstat *bstat);
+			   const struct xfs_bulkstat *bstat);
 int xfs_fsinumbers_fmt(struct xfs_ibulk *breq, const struct xfs_inogrp *igrp);
 
 #endif
diff --git a/fs/xfs/xfs_ioctl32.c b/fs/xfs/xfs_ioctl32.c
index 9e5cf3988d3e..a97612927f9e 100644
--- a/fs/xfs/xfs_ioctl32.c
+++ b/fs/xfs/xfs_ioctl32.c
@@ -172,10 +172,14 @@ xfs_bstime_store_compat(
 /* Return 0 on success or positive error (to xfs_bulkstat()) */
 STATIC int
 xfs_fsbulkstat_one_fmt_compat(
-	struct xfs_ibulk	*breq,
-	const struct xfs_bstat	*buffer)
+	struct xfs_ibulk		*breq,
+	const struct xfs_bulkstat	*bstat)
 {
-	struct compat_xfs_bstat	__user *p32 = breq->ubuffer;
+	struct compat_xfs_bstat	__user	*p32 = breq->ubuffer;
+	struct xfs_bstat		bs1;
+	struct xfs_bstat		*buffer = &bs1;
+
+	xfs_bulkstat_to_bstat(breq->mp, &bs1, bstat);
 
 	if (put_user(buffer->bs_ino,	  &p32->bs_ino)		||
 	    put_user(buffer->bs_mode,	  &p32->bs_mode)	||
diff --git a/fs/xfs/xfs_itable.c b/fs/xfs/xfs_itable.c
index 45f0618efb8d..50c2bb8e13c4 100644
--- a/fs/xfs/xfs_itable.c
+++ b/fs/xfs/xfs_itable.c
@@ -25,7 +25,7 @@
  * Bulk Stat
  * =========
  *
- * Use the inode walking functions to fill out struct xfs_bstat for every
+ * Use the inode walking functions to fill out struct xfs_bulkstat for every
  * allocated inode, then pass the stat information to some externally provided
  * iteration function.
  */
@@ -33,7 +33,7 @@
 struct xfs_bstat_chunk {
 	bulkstat_one_fmt_pf	formatter;
 	struct xfs_ibulk	*breq;
-	struct xfs_bstat	*buf;
+	struct xfs_bulkstat	*buf;
 };
 
 /*
@@ -62,7 +62,7 @@ xfs_bulkstat_one_int(
 	struct xfs_icdinode	*dic;		/* dinode core info pointer */
 	struct xfs_inode	*ip;		/* incore inode pointer */
 	struct inode		*inode;
-	struct xfs_bstat	*buf = bc->buf;
+	struct xfs_bulkstat	*buf = bc->buf;
 	int			error = -EINVAL;
 
 	if (xfs_internal_inum(mp, ino))
@@ -85,37 +85,35 @@ xfs_bulkstat_one_int(
 	/* xfs_iget returns the following without needing
 	 * further change.
 	 */
-	buf->bs_projid_lo = dic->di_projid_lo;
-	buf->bs_projid_hi = dic->di_projid_hi;
+	buf->bs_projectid = xfs_get_projid(ip);
 	buf->bs_ino = ino;
 	buf->bs_uid = dic->di_uid;
 	buf->bs_gid = dic->di_gid;
 	buf->bs_size = dic->di_size;
 
 	buf->bs_nlink = inode->i_nlink;
-	buf->bs_atime.tv_sec = inode->i_atime.tv_sec;
-	buf->bs_atime.tv_nsec = inode->i_atime.tv_nsec;
-	buf->bs_mtime.tv_sec = inode->i_mtime.tv_sec;
-	buf->bs_mtime.tv_nsec = inode->i_mtime.tv_nsec;
-	buf->bs_ctime.tv_sec = inode->i_ctime.tv_sec;
-	buf->bs_ctime.tv_nsec = inode->i_ctime.tv_nsec;
+	buf->bs_atime = inode->i_atime.tv_sec;
+	buf->bs_atime_nsec = inode->i_atime.tv_nsec;
+	buf->bs_mtime = inode->i_mtime.tv_sec;
+	buf->bs_mtime_nsec = inode->i_mtime.tv_nsec;
+	buf->bs_ctime = inode->i_ctime.tv_sec;
+	buf->bs_ctime_nsec = inode->i_ctime.tv_nsec;
+	buf->bs_btime = dic->di_crtime.t_sec;
+	buf->bs_btime_nsec = dic->di_crtime.t_nsec;
 	buf->bs_gen = inode->i_generation;
 	buf->bs_mode = inode->i_mode;
 
 	buf->bs_xflags = xfs_ip2xflags(ip);
-	buf->bs_extsize = dic->di_extsize << mp->m_sb.sb_blocklog;
+	buf->bs_extsize_blks = dic->di_extsize;
 	buf->bs_extents = dic->di_nextents;
-	memset(buf->bs_pad, 0, sizeof(buf->bs_pad));
 	xfs_bulkstat_health(ip, buf);
-	buf->bs_dmevmask = dic->di_dmevmask;
-	buf->bs_dmstate = dic->di_dmstate;
 	buf->bs_aextents = dic->di_anextents;
 	buf->bs_forkoff = XFS_IFORK_BOFF(ip);
+	buf->bs_version = XFS_BULKSTAT_VERSION_V5;
 
 	if (dic->di_version == 3) {
 		if (dic->di_flags2 & XFS_DIFLAG2_COWEXTSIZE)
-			buf->bs_cowextsize = dic->di_cowextsize <<
-					mp->m_sb.sb_blocklog;
+			buf->bs_cowextsize_blks = dic->di_cowextsize;
 	}
 
 	switch (dic->di_format) {
@@ -171,7 +169,8 @@ xfs_bulkstat_one(
 
 	ASSERT(breq->icount == 1);
 
-	bc.buf = kmem_zalloc(sizeof(struct xfs_bstat), KM_SLEEP | KM_MAYFAIL);
+	bc.buf = kmem_zalloc(sizeof(struct xfs_bulkstat),
+			KM_SLEEP | KM_MAYFAIL);
 	if (!bc.buf)
 		return -ENOMEM;
 
@@ -244,7 +243,8 @@ xfs_bulkstat(
 	if (xfs_bulkstat_already_done(breq->mp, breq->startino))
 		return 0;
 
-	bc.buf = kmem_zalloc(sizeof(struct xfs_bstat), KM_SLEEP | KM_MAYFAIL);
+	bc.buf = kmem_zalloc(sizeof(struct xfs_bulkstat),
+			KM_SLEEP | KM_MAYFAIL);
 	if (!bc.buf)
 		return -ENOMEM;
 
@@ -266,6 +266,43 @@ xfs_bulkstat(
 	return error;
 }
 
+/* Convert bulkstat (v5) to bstat (v1). */
+void
+xfs_bulkstat_to_bstat(
+	struct xfs_mount		*mp,
+	struct xfs_bstat		*bs1,
+	const struct xfs_bulkstat	*bstat)
+{
+	bs1->bs_ino = bstat->bs_ino;
+	bs1->bs_mode = bstat->bs_mode;
+	bs1->bs_nlink = bstat->bs_nlink;
+	bs1->bs_uid = bstat->bs_uid;
+	bs1->bs_gid = bstat->bs_gid;
+	bs1->bs_rdev = bstat->bs_rdev;
+	bs1->bs_blksize = bstat->bs_blksize;
+	bs1->bs_size = bstat->bs_size;
+	bs1->bs_atime.tv_sec = bstat->bs_atime;
+	bs1->bs_mtime.tv_sec = bstat->bs_mtime;
+	bs1->bs_ctime.tv_sec = bstat->bs_ctime;
+	bs1->bs_atime.tv_nsec = bstat->bs_atime_nsec;
+	bs1->bs_mtime.tv_nsec = bstat->bs_mtime_nsec;
+	bs1->bs_ctime.tv_nsec = bstat->bs_ctime_nsec;
+	bs1->bs_blocks = bstat->bs_blocks;
+	bs1->bs_xflags = bstat->bs_xflags;
+	bs1->bs_extsize = bstat->bs_extsize_blks << mp->m_sb.sb_blocklog;
+	bs1->bs_extents = bstat->bs_extents;
+	bs1->bs_gen = bstat->bs_gen;
+	bs1->bs_projid_lo = bstat->bs_projectid & 0xFFFF;
+	bs1->bs_forkoff = bstat->bs_forkoff;
+	bs1->bs_projid_hi = bstat->bs_projectid >> 16;
+	bs1->bs_sick = bstat->bs_sick;
+	bs1->bs_checked = bstat->bs_checked;
+	bs1->bs_cowextsize = bstat->bs_cowextsize_blks << mp->m_sb.sb_blocklog;
+	bs1->bs_dmevmask = 0;
+	bs1->bs_dmstate = 0;
+	bs1->bs_aextents = bstat->bs_aextents;
+}
+
 struct xfs_inumbers_chunk {
 	inumbers_fmt_pf		formatter;
 	struct xfs_ibulk	*breq;
diff --git a/fs/xfs/xfs_itable.h b/fs/xfs/xfs_itable.h
index cfd3c93226f3..60e259192056 100644
--- a/fs/xfs/xfs_itable.h
+++ b/fs/xfs/xfs_itable.h
@@ -38,10 +38,12 @@ xfs_ibulk_advance(
  */
 
 typedef int (*bulkstat_one_fmt_pf)(struct xfs_ibulk *breq,
-		const struct xfs_bstat *bstat);
+		const struct xfs_bulkstat *bstat);
 
 int xfs_bulkstat_one(struct xfs_ibulk *breq, bulkstat_one_fmt_pf formatter);
 int xfs_bulkstat(struct xfs_ibulk *breq, bulkstat_one_fmt_pf formatter);
+void xfs_bulkstat_to_bstat(struct xfs_mount *mp, struct xfs_bstat *bs1,
+		const struct xfs_bulkstat *bstat);
 
 typedef int (*inumbers_fmt_pf)(struct xfs_ibulk *breq,
 		const struct xfs_inogrp *igrp);
diff --git a/fs/xfs/xfs_ondisk.h b/fs/xfs/xfs_ondisk.h
index c8ba98fae30a..0b4cdda68524 100644
--- a/fs/xfs/xfs_ondisk.h
+++ b/fs/xfs/xfs_ondisk.h
@@ -146,6 +146,8 @@ xfs_check_ondisk_structs(void)
 	XFS_CHECK_OFFSET(struct xfs_dir3_data_hdr, hdr.magic,	0);
 	XFS_CHECK_OFFSET(struct xfs_dir3_free, hdr.hdr.magic,	0);
 	XFS_CHECK_OFFSET(struct xfs_attr3_leafblock, hdr.info.hdr, 0);
+
+	XFS_CHECK_STRUCT_SIZE(struct xfs_bulkstat,		192);
 }
 
 #endif /* __XFS_ONDISK_H */

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

* [PATCH 4/9] xfs: introduce v5 inode group structure
  2019-06-26 20:45 [PATCH v6 0/9] xfs: introduce new BULKSTAT and INUMBERS ioctls Darrick J. Wong
                   ` (2 preceding siblings ...)
  2019-06-26 20:45 ` [PATCH 3/9] xfs: introduce new v5 bulkstat structure Darrick J. Wong
@ 2019-06-26 20:45 ` Darrick J. Wong
  2019-07-03 13:23   ` Brian Foster
  2019-06-26 20:46 ` [PATCH 5/9] xfs: wire up new v5 bulkstat ioctls Darrick J. Wong
                   ` (4 subsequent siblings)
  8 siblings, 1 reply; 34+ messages in thread
From: Darrick J. Wong @ 2019-06-26 20:45 UTC (permalink / raw)
  To: darrick.wong; +Cc: linux-xfs, allison.henderson

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

Introduce a new "v5" inode group structure that fixes the alignment
and padding problems of the existing structure.

Signed-off-by: Darrick J. Wong <darrick.wong@oracle.com>
---
 fs/xfs/libxfs/xfs_fs.h |   11 +++++++++++
 fs/xfs/xfs_ioctl.c     |    9 ++++++---
 fs/xfs/xfs_ioctl.h     |    2 +-
 fs/xfs/xfs_ioctl32.c   |   10 +++++++---
 fs/xfs/xfs_itable.c    |   14 +++++++++++++-
 fs/xfs/xfs_itable.h    |    4 +++-
 fs/xfs/xfs_ondisk.h    |    1 +
 7 files changed, 42 insertions(+), 9 deletions(-)


diff --git a/fs/xfs/libxfs/xfs_fs.h b/fs/xfs/libxfs/xfs_fs.h
index 132e364eb141..8b8fe78511fb 100644
--- a/fs/xfs/libxfs/xfs_fs.h
+++ b/fs/xfs/libxfs/xfs_fs.h
@@ -445,6 +445,17 @@ struct xfs_inogrp {
 	__u64		xi_allocmask;	/* mask of allocated inodes	*/
 };
 
+/* New inumbers structure that reports v5 features and fixes padding issues */
+struct xfs_inumbers {
+	uint64_t	xi_startino;	/* starting inode number	*/
+	uint64_t	xi_allocmask;	/* mask of allocated inodes	*/
+	uint8_t		xi_alloccount;	/* # bits set in allocmask	*/
+	uint8_t		xi_version;	/* version			*/
+	uint8_t		xi_padding[6];	/* zero				*/
+};
+
+#define XFS_INUMBERS_VERSION_V1	(1)
+#define XFS_INUMBERS_VERSION_V5	(5)
 
 /*
  * Error injection.
diff --git a/fs/xfs/xfs_ioctl.c b/fs/xfs/xfs_ioctl.c
index 0b8c631d53dd..47580762e154 100644
--- a/fs/xfs/xfs_ioctl.c
+++ b/fs/xfs/xfs_ioctl.c
@@ -738,10 +738,13 @@ xfs_fsbulkstat_one_fmt(
 
 int
 xfs_fsinumbers_fmt(
-	struct xfs_ibulk	*breq,
-	const struct xfs_inogrp	*igrp)
+	struct xfs_ibulk		*breq,
+	const struct xfs_inumbers	*igrp)
 {
-	if (copy_to_user(breq->ubuffer, igrp, sizeof(*igrp)))
+	struct xfs_inogrp		ig1;
+
+	xfs_inumbers_to_inogrp(&ig1, igrp);
+	if (copy_to_user(breq->ubuffer, &ig1, sizeof(struct xfs_inogrp)))
 		return -EFAULT;
 	return xfs_ibulk_advance(breq, sizeof(struct xfs_inogrp));
 }
diff --git a/fs/xfs/xfs_ioctl.h b/fs/xfs/xfs_ioctl.h
index 514d3028a134..654c0bb1bcf8 100644
--- a/fs/xfs/xfs_ioctl.h
+++ b/fs/xfs/xfs_ioctl.h
@@ -83,6 +83,6 @@ struct xfs_inogrp;
 
 int xfs_fsbulkstat_one_fmt(struct xfs_ibulk *breq,
 			   const struct xfs_bulkstat *bstat);
-int xfs_fsinumbers_fmt(struct xfs_ibulk *breq, const struct xfs_inogrp *igrp);
+int xfs_fsinumbers_fmt(struct xfs_ibulk *breq, const struct xfs_inumbers *igrp);
 
 #endif
diff --git a/fs/xfs/xfs_ioctl32.c b/fs/xfs/xfs_ioctl32.c
index a97612927f9e..41485e2ed431 100644
--- a/fs/xfs/xfs_ioctl32.c
+++ b/fs/xfs/xfs_ioctl32.c
@@ -87,10 +87,14 @@ xfs_compat_growfs_rt_copyin(
 
 STATIC int
 xfs_fsinumbers_fmt_compat(
-	struct xfs_ibulk	*breq,
-	const struct xfs_inogrp	*igrp)
+	struct xfs_ibulk		*breq,
+	const struct xfs_inumbers	*ig)
 {
-	struct compat_xfs_inogrp __user *p32 = breq->ubuffer;
+	struct compat_xfs_inogrp __user	*p32 = breq->ubuffer;
+	struct xfs_inogrp		ig1;
+	struct xfs_inogrp		*igrp = &ig1;
+
+	xfs_inumbers_to_inogrp(&ig1, ig);
 
 	if (put_user(igrp->xi_startino,   &p32->xi_startino) ||
 	    put_user(igrp->xi_alloccount, &p32->xi_alloccount) ||
diff --git a/fs/xfs/xfs_itable.c b/fs/xfs/xfs_itable.c
index 50c2bb8e13c4..745b04f59132 100644
--- a/fs/xfs/xfs_itable.c
+++ b/fs/xfs/xfs_itable.c
@@ -331,10 +331,11 @@ xfs_inumbers_walk(
 	const struct xfs_inobt_rec_incore *irec,
 	void			*data)
 {
-	struct xfs_inogrp	inogrp = {
+	struct xfs_inumbers	inogrp = {
 		.xi_startino	= XFS_AGINO_TO_INO(mp, agno, irec->ir_startino),
 		.xi_alloccount	= irec->ir_count - irec->ir_freecount,
 		.xi_allocmask	= ~irec->ir_free,
+		.xi_version	= XFS_INUMBERS_VERSION_V5,
 	};
 	struct xfs_inumbers_chunk *ic = data;
 	xfs_agino_t		agino;
@@ -381,3 +382,14 @@ xfs_inumbers(
 
 	return error;
 }
+
+/* Convert an inumbers (v5) struct to a inogrp (v1) struct. */
+void
+xfs_inumbers_to_inogrp(
+	struct xfs_inogrp		*ig1,
+	const struct xfs_inumbers	*ig)
+{
+	ig1->xi_startino = ig->xi_startino;
+	ig1->xi_alloccount = ig->xi_alloccount;
+	ig1->xi_allocmask = ig->xi_allocmask;
+}
diff --git a/fs/xfs/xfs_itable.h b/fs/xfs/xfs_itable.h
index 60e259192056..fa9fb9104c7f 100644
--- a/fs/xfs/xfs_itable.h
+++ b/fs/xfs/xfs_itable.h
@@ -46,8 +46,10 @@ void xfs_bulkstat_to_bstat(struct xfs_mount *mp, struct xfs_bstat *bs1,
 		const struct xfs_bulkstat *bstat);
 
 typedef int (*inumbers_fmt_pf)(struct xfs_ibulk *breq,
-		const struct xfs_inogrp *igrp);
+		const struct xfs_inumbers *igrp);
 
 int xfs_inumbers(struct xfs_ibulk *breq, inumbers_fmt_pf formatter);
+void xfs_inumbers_to_inogrp(struct xfs_inogrp *ig1,
+		const struct xfs_inumbers *ig);
 
 #endif	/* __XFS_ITABLE_H__ */
diff --git a/fs/xfs/xfs_ondisk.h b/fs/xfs/xfs_ondisk.h
index 0b4cdda68524..d8f941b4d51c 100644
--- a/fs/xfs/xfs_ondisk.h
+++ b/fs/xfs/xfs_ondisk.h
@@ -148,6 +148,7 @@ xfs_check_ondisk_structs(void)
 	XFS_CHECK_OFFSET(struct xfs_attr3_leafblock, hdr.info.hdr, 0);
 
 	XFS_CHECK_STRUCT_SIZE(struct xfs_bulkstat,		192);
+	XFS_CHECK_STRUCT_SIZE(struct xfs_inumbers,		24);
 }
 
 #endif /* __XFS_ONDISK_H */

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

* [PATCH 5/9] xfs: wire up new v5 bulkstat ioctls
  2019-06-26 20:45 [PATCH v6 0/9] xfs: introduce new BULKSTAT and INUMBERS ioctls Darrick J. Wong
                   ` (3 preceding siblings ...)
  2019-06-26 20:45 ` [PATCH 4/9] xfs: introduce v5 inode group structure Darrick J. Wong
@ 2019-06-26 20:46 ` Darrick J. Wong
  2019-07-03 13:24   ` Brian Foster
  2019-06-26 20:46 ` [PATCH 6/9] xfs: wire up the new v5 bulkstat_single ioctl Darrick J. Wong
                   ` (3 subsequent siblings)
  8 siblings, 1 reply; 34+ messages in thread
From: Darrick J. Wong @ 2019-06-26 20:46 UTC (permalink / raw)
  To: darrick.wong; +Cc: linux-xfs, allison.henderson

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

Wire up the new v5 BULKSTAT ioctl and rename the old one to V1.

Signed-off-by: Darrick J. Wong <darrick.wong@oracle.com>
---
 fs/xfs/libxfs/xfs_fs.h |   24 +++++++++++-
 fs/xfs/xfs_ioctl.c     |   98 ++++++++++++++++++++++++++++++++++++++++++++++++
 fs/xfs/xfs_ioctl32.c   |    1 
 fs/xfs/xfs_ondisk.h    |    1 
 4 files changed, 123 insertions(+), 1 deletion(-)


diff --git a/fs/xfs/libxfs/xfs_fs.h b/fs/xfs/libxfs/xfs_fs.h
index 8b8fe78511fb..960f3542e207 100644
--- a/fs/xfs/libxfs/xfs_fs.h
+++ b/fs/xfs/libxfs/xfs_fs.h
@@ -435,7 +435,6 @@ struct xfs_fsop_bulkreq {
 	__s32		__user *ocount;	/* output count pointer		*/
 };
 
-
 /*
  * Structures returned from xfs_inumbers routine (XFS_IOC_FSINUMBERS).
  */
@@ -457,6 +456,28 @@ struct xfs_inumbers {
 #define XFS_INUMBERS_VERSION_V1	(1)
 #define XFS_INUMBERS_VERSION_V5	(5)
 
+/* Header for bulk inode requests. */
+struct xfs_bulk_ireq {
+	uint64_t	ino;		/* I/O: start with this inode	*/
+	uint32_t	flags;		/* I/O: operation flags		*/
+	uint32_t	icount;		/* I: count of entries in buffer */
+	uint32_t	ocount;		/* O: count of entries filled out */
+	uint32_t	reserved32;	/* must be zero			*/
+	uint64_t	reserved[5];	/* must be zero			*/
+};
+
+#define XFS_BULK_IREQ_FLAGS_ALL	(0)
+
+/*
+ * ioctl structures for v5 bulkstat and inumbers requests
+ */
+struct xfs_bulkstat_req {
+	struct xfs_bulk_ireq	hdr;
+	struct xfs_bulkstat	bulkstat[];
+};
+#define XFS_BULKSTAT_REQ_SIZE(nr)	(sizeof(struct xfs_bulkstat_req) + \
+					 (nr) * sizeof(struct xfs_bulkstat))
+
 /*
  * Error injection.
  */
@@ -758,6 +779,7 @@ struct xfs_scrub_metadata {
 #define XFS_IOC_FSGEOMETRY_V4	     _IOR ('X', 124, struct xfs_fsop_geom_v4)
 #define XFS_IOC_GOINGDOWN	     _IOR ('X', 125, uint32_t)
 #define XFS_IOC_FSGEOMETRY	     _IOR ('X', 126, struct xfs_fsop_geom)
+#define XFS_IOC_BULKSTAT	     _IOR ('X', 127, struct xfs_bulkstat_req)
 /*	XFS_IOC_GETFSUUID ---------- deprecated 140	 */
 
 
diff --git a/fs/xfs/xfs_ioctl.c b/fs/xfs/xfs_ioctl.c
index 47580762e154..cf6a38c2a3ed 100644
--- a/fs/xfs/xfs_ioctl.c
+++ b/fs/xfs/xfs_ioctl.c
@@ -827,6 +827,101 @@ xfs_ioc_fsbulkstat(
 	return 0;
 }
 
+/* Return 0 on success or positive error */
+static int
+xfs_bulkstat_fmt(
+	struct xfs_ibulk		*breq,
+	const struct xfs_bulkstat	*bstat)
+{
+	if (copy_to_user(breq->ubuffer, bstat, sizeof(struct xfs_bulkstat)))
+		return -EFAULT;
+	return xfs_ibulk_advance(breq, sizeof(struct xfs_bulkstat));
+}
+
+/*
+ * Check the incoming bulk request @hdr from userspace and initialize the
+ * internal @breq bulk request appropriately.  Returns 0 if the bulk request
+ * should proceed; XFS_ITER_ABORT if there's nothing to do; or the usual
+ * negative error code.
+ */
+static int
+xfs_bulk_ireq_setup(
+	struct xfs_mount	*mp,
+	struct xfs_bulk_ireq	*hdr,
+	struct xfs_ibulk	*breq,
+	void __user		*ubuffer)
+{
+	if (hdr->icount == 0 ||
+	    (hdr->flags & ~XFS_BULK_IREQ_FLAGS_ALL) ||
+	    hdr->reserved32 ||
+	    memchr_inv(hdr->reserved, 0, sizeof(hdr->reserved)))
+		return -EINVAL;
+
+	breq->startino = hdr->ino;
+	breq->ubuffer = ubuffer;
+	breq->icount = hdr->icount;
+	breq->ocount = 0;
+
+	/* Asking for an inode past the end of the FS?  We're done! */
+	if (XFS_INO_TO_AGNO(mp, breq->startino) >= mp->m_sb.sb_agcount)
+		return XFS_ITER_ABORT;
+
+	return 0;
+}
+
+/*
+ * Update the userspace bulk request @hdr to reflect the end state of the
+ * internal bulk request @breq.
+ */
+static void
+xfs_bulk_ireq_teardown(
+	struct xfs_bulk_ireq	*hdr,
+	struct xfs_ibulk	*breq)
+{
+	hdr->ino = breq->startino;
+	hdr->ocount = breq->ocount;
+}
+
+/* Handle the v5 bulkstat ioctl. */
+STATIC int
+xfs_ioc_bulkstat(
+	struct xfs_mount		*mp,
+	unsigned int			cmd,
+	struct xfs_bulkstat_req __user	*arg)
+{
+	struct xfs_bulk_ireq		hdr;
+	struct xfs_ibulk		breq = {
+		.mp			= mp,
+	};
+	int				error;
+
+	if (!capable(CAP_SYS_ADMIN))
+		return -EPERM;
+
+	if (XFS_FORCED_SHUTDOWN(mp))
+		return -EIO;
+
+	if (copy_from_user(&hdr, &arg->hdr, sizeof(hdr)))
+		return -EFAULT;
+
+	error = xfs_bulk_ireq_setup(mp, &hdr, &breq, arg->bulkstat);
+	if (error == XFS_ITER_ABORT)
+		goto out_teardown;
+	if (error < 0)
+		return error;
+
+	error = xfs_bulkstat(&breq, xfs_bulkstat_fmt);
+	if (error)
+		return error;
+
+out_teardown:
+	xfs_bulk_ireq_teardown(&hdr, &breq);
+	if (copy_to_user(&arg->hdr, &hdr, sizeof(hdr)))
+		return -EFAULT;
+
+	return 0;
+}
+
 STATIC int
 xfs_ioc_fsgeometry(
 	struct xfs_mount	*mp,
@@ -1991,6 +2086,9 @@ xfs_file_ioctl(
 	case XFS_IOC_FSINUMBERS:
 		return xfs_ioc_fsbulkstat(mp, cmd, arg);
 
+	case XFS_IOC_BULKSTAT:
+		return xfs_ioc_bulkstat(mp, cmd, arg);
+
 	case XFS_IOC_FSGEOMETRY_V1:
 		return xfs_ioc_fsgeometry(mp, arg, 3);
 	case XFS_IOC_FSGEOMETRY_V4:
diff --git a/fs/xfs/xfs_ioctl32.c b/fs/xfs/xfs_ioctl32.c
index 41485e2ed431..df107adbdbf3 100644
--- a/fs/xfs/xfs_ioctl32.c
+++ b/fs/xfs/xfs_ioctl32.c
@@ -580,6 +580,7 @@ xfs_file_compat_ioctl(
 	case XFS_IOC_ERROR_CLEARALL:
 	case FS_IOC_GETFSMAP:
 	case XFS_IOC_SCRUB_METADATA:
+	case XFS_IOC_BULKSTAT:
 		return xfs_file_ioctl(filp, cmd, p);
 #if !defined(BROKEN_X86_ALIGNMENT) || defined(CONFIG_X86_X32)
 	/*
diff --git a/fs/xfs/xfs_ondisk.h b/fs/xfs/xfs_ondisk.h
index d8f941b4d51c..954484c6eb96 100644
--- a/fs/xfs/xfs_ondisk.h
+++ b/fs/xfs/xfs_ondisk.h
@@ -149,6 +149,7 @@ xfs_check_ondisk_structs(void)
 
 	XFS_CHECK_STRUCT_SIZE(struct xfs_bulkstat,		192);
 	XFS_CHECK_STRUCT_SIZE(struct xfs_inumbers,		24);
+	XFS_CHECK_STRUCT_SIZE(struct xfs_bulkstat_req,		64);
 }
 
 #endif /* __XFS_ONDISK_H */

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

* [PATCH 6/9] xfs: wire up the new v5 bulkstat_single ioctl
  2019-06-26 20:45 [PATCH v6 0/9] xfs: introduce new BULKSTAT and INUMBERS ioctls Darrick J. Wong
                   ` (4 preceding siblings ...)
  2019-06-26 20:46 ` [PATCH 5/9] xfs: wire up new v5 bulkstat ioctls Darrick J. Wong
@ 2019-06-26 20:46 ` Darrick J. Wong
  2019-07-03 13:24   ` Brian Foster
  2019-06-26 20:46 ` [PATCH 7/9] xfs: wire up the v5 INUMBERS ioctl Darrick J. Wong
                   ` (2 subsequent siblings)
  8 siblings, 1 reply; 34+ messages in thread
From: Darrick J. Wong @ 2019-06-26 20:46 UTC (permalink / raw)
  To: darrick.wong; +Cc: linux-xfs, allison.henderson

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

Wire up the V5 BULKSTAT_SINGLE ioctl and rename the old one V1.

Signed-off-by: Darrick J. Wong <darrick.wong@oracle.com>
---
 fs/xfs/libxfs/xfs_fs.h |   16 ++++++++++
 fs/xfs/xfs_ioctl.c     |   79 ++++++++++++++++++++++++++++++++++++++++++++++++
 fs/xfs/xfs_ioctl32.c   |    1 +
 fs/xfs/xfs_ondisk.h    |    1 +
 4 files changed, 97 insertions(+)


diff --git a/fs/xfs/libxfs/xfs_fs.h b/fs/xfs/libxfs/xfs_fs.h
index 960f3542e207..95d0411dae9b 100644
--- a/fs/xfs/libxfs/xfs_fs.h
+++ b/fs/xfs/libxfs/xfs_fs.h
@@ -468,6 +468,16 @@ struct xfs_bulk_ireq {
 
 #define XFS_BULK_IREQ_FLAGS_ALL	(0)
 
+/* Header for a single inode request. */
+struct xfs_ireq {
+	uint64_t	ino;		/* I/O: start with this inode	*/
+	uint32_t	flags;		/* I/O: operation flags		*/
+	uint32_t	reserved32;	/* must be zero			*/
+	uint64_t	reserved[2];	/* must be zero			*/
+};
+
+#define XFS_IREQ_FLAGS_ALL	(0)
+
 /*
  * ioctl structures for v5 bulkstat and inumbers requests
  */
@@ -478,6 +488,11 @@ struct xfs_bulkstat_req {
 #define XFS_BULKSTAT_REQ_SIZE(nr)	(sizeof(struct xfs_bulkstat_req) + \
 					 (nr) * sizeof(struct xfs_bulkstat))
 
+struct xfs_bulkstat_single_req {
+	struct xfs_ireq		hdr;
+	struct xfs_bulkstat	bulkstat;
+};
+
 /*
  * Error injection.
  */
@@ -780,6 +795,7 @@ struct xfs_scrub_metadata {
 #define XFS_IOC_GOINGDOWN	     _IOR ('X', 125, uint32_t)
 #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_BULKSTAT_SINGLE	     _IOR ('X', 128, struct xfs_bulkstat_single_req)
 /*	XFS_IOC_GETFSUUID ---------- deprecated 140	 */
 
 
diff --git a/fs/xfs/xfs_ioctl.c b/fs/xfs/xfs_ioctl.c
index cf6a38c2a3ed..2c821fa601a4 100644
--- a/fs/xfs/xfs_ioctl.c
+++ b/fs/xfs/xfs_ioctl.c
@@ -922,6 +922,83 @@ xfs_ioc_bulkstat(
 	return 0;
 }
 
+/*
+ * Check the incoming singleton request @hdr from userspace and initialize the
+ * internal @breq bulk request appropriately.  Returns 0 if the bulk request
+ * should proceed; or the usual negative error code.
+ */
+static int
+xfs_ireq_setup(
+	struct xfs_mount	*mp,
+	struct xfs_ireq		*hdr,
+	struct xfs_ibulk	*breq,
+	void __user		*ubuffer)
+{
+	if ((hdr->flags & ~XFS_IREQ_FLAGS_ALL) ||
+	    hdr->reserved32 ||
+	    memchr_inv(hdr->reserved, 0, sizeof(hdr->reserved)))
+		return -EINVAL;
+
+	if (XFS_INO_TO_AGNO(mp, hdr->ino) >= mp->m_sb.sb_agcount)
+		return -EINVAL;
+
+	breq->ubuffer = ubuffer;
+	breq->icount = 1;
+	breq->startino = hdr->ino;
+	return 0;
+}
+
+/*
+ * Update the userspace singleton request @hdr to reflect the end state of the
+ * internal bulk request @breq.  If @error is negative then we return just
+ * that; otherwise we copy the state so that userspace can discover what
+ * happened.
+ */
+static void
+xfs_ireq_teardown(
+	struct xfs_ireq		*hdr,
+	struct xfs_ibulk	*breq)
+{
+	hdr->ino = breq->startino;
+}
+
+/* Handle the v5 bulkstat_single ioctl. */
+STATIC int
+xfs_ioc_bulkstat_single(
+	struct xfs_mount	*mp,
+	unsigned int		cmd,
+	struct xfs_bulkstat_single_req __user *arg)
+{
+	struct xfs_ireq		hdr;
+	struct xfs_ibulk	breq = {
+		.mp		= mp,
+	};
+	int			error;
+
+	if (!capable(CAP_SYS_ADMIN))
+		return -EPERM;
+
+	if (XFS_FORCED_SHUTDOWN(mp))
+		return -EIO;
+
+	if (copy_from_user(&hdr, &arg->hdr, sizeof(hdr)))
+		return -EFAULT;
+
+	error = xfs_ireq_setup(mp, &hdr, &breq, &arg->bulkstat);
+	if (error)
+		return error;
+
+	error = xfs_bulkstat_one(&breq, xfs_bulkstat_fmt);
+	if (error)
+		return error;
+
+	xfs_ireq_teardown(&hdr, &breq);
+	if (copy_to_user(&arg->hdr, &hdr, sizeof(hdr)))
+		return -EFAULT;
+
+	return 0;
+}
+
 STATIC int
 xfs_ioc_fsgeometry(
 	struct xfs_mount	*mp,
@@ -2088,6 +2165,8 @@ xfs_file_ioctl(
 
 	case XFS_IOC_BULKSTAT:
 		return xfs_ioc_bulkstat(mp, cmd, arg);
+	case XFS_IOC_BULKSTAT_SINGLE:
+		return xfs_ioc_bulkstat_single(mp, cmd, arg);
 
 	case XFS_IOC_FSGEOMETRY_V1:
 		return xfs_ioc_fsgeometry(mp, arg, 3);
diff --git a/fs/xfs/xfs_ioctl32.c b/fs/xfs/xfs_ioctl32.c
index df107adbdbf3..6fa0f41dbae5 100644
--- a/fs/xfs/xfs_ioctl32.c
+++ b/fs/xfs/xfs_ioctl32.c
@@ -581,6 +581,7 @@ xfs_file_compat_ioctl(
 	case FS_IOC_GETFSMAP:
 	case XFS_IOC_SCRUB_METADATA:
 	case XFS_IOC_BULKSTAT:
+	case XFS_IOC_BULKSTAT_SINGLE:
 		return xfs_file_ioctl(filp, cmd, p);
 #if !defined(BROKEN_X86_ALIGNMENT) || defined(CONFIG_X86_X32)
 	/*
diff --git a/fs/xfs/xfs_ondisk.h b/fs/xfs/xfs_ondisk.h
index 954484c6eb96..fa1252657b08 100644
--- a/fs/xfs/xfs_ondisk.h
+++ b/fs/xfs/xfs_ondisk.h
@@ -150,6 +150,7 @@ xfs_check_ondisk_structs(void)
 	XFS_CHECK_STRUCT_SIZE(struct xfs_bulkstat,		192);
 	XFS_CHECK_STRUCT_SIZE(struct xfs_inumbers,		24);
 	XFS_CHECK_STRUCT_SIZE(struct xfs_bulkstat_req,		64);
+	XFS_CHECK_STRUCT_SIZE(struct xfs_bulkstat_single_req,	224);
 }
 
 #endif /* __XFS_ONDISK_H */

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

* [PATCH 7/9] xfs: wire up the v5 INUMBERS ioctl
  2019-06-26 20:45 [PATCH v6 0/9] xfs: introduce new BULKSTAT and INUMBERS ioctls Darrick J. Wong
                   ` (5 preceding siblings ...)
  2019-06-26 20:46 ` [PATCH 6/9] xfs: wire up the new v5 bulkstat_single ioctl Darrick J. Wong
@ 2019-06-26 20:46 ` Darrick J. Wong
  2019-07-03 13:24   ` Brian Foster
  2019-06-26 20:46 ` [PATCH 8/9] xfs: specify AG in bulk req Darrick J. Wong
  2019-06-26 20:46 ` [PATCH 9/9] xfs: allow bulkstat_single of special inodes Darrick J. Wong
  8 siblings, 1 reply; 34+ messages in thread
From: Darrick J. Wong @ 2019-06-26 20:46 UTC (permalink / raw)
  To: darrick.wong; +Cc: linux-xfs, allison.henderson

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

Wire up the v5 INUMBERS ioctl and rename the old one to v1.

Signed-off-by: Darrick J. Wong <darrick.wong@oracle.com>
---
 fs/xfs/libxfs/xfs_fs.h |    8 +++++++
 fs/xfs/xfs_ioctl.c     |   52 ++++++++++++++++++++++++++++++++++++++++++++++++
 fs/xfs/xfs_ioctl32.c   |    1 +
 fs/xfs/xfs_ondisk.h    |    1 +
 4 files changed, 62 insertions(+)


diff --git a/fs/xfs/libxfs/xfs_fs.h b/fs/xfs/libxfs/xfs_fs.h
index 95d0411dae9b..f9f35139d4b7 100644
--- a/fs/xfs/libxfs/xfs_fs.h
+++ b/fs/xfs/libxfs/xfs_fs.h
@@ -493,6 +493,13 @@ struct xfs_bulkstat_single_req {
 	struct xfs_bulkstat	bulkstat;
 };
 
+struct xfs_inumbers_req {
+	struct xfs_bulk_ireq	hdr;
+	struct xfs_inumbers	inumbers[];
+};
+#define XFS_INUMBERS_REQ_SIZE(nr)	(sizeof(struct xfs_inumbers_req) + \
+					 (nr) * sizeof(struct xfs_inumbers))
+
 /*
  * Error injection.
  */
@@ -796,6 +803,7 @@ struct xfs_scrub_metadata {
 #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_BULKSTAT_SINGLE	     _IOR ('X', 128, struct xfs_bulkstat_single_req)
+#define XFS_IOC_INUMBERS	     _IOR ('X', 129, struct xfs_inumbers_req)
 /*	XFS_IOC_GETFSUUID ---------- deprecated 140	 */
 
 
diff --git a/fs/xfs/xfs_ioctl.c b/fs/xfs/xfs_ioctl.c
index 2c821fa601a4..2ac5e100b147 100644
--- a/fs/xfs/xfs_ioctl.c
+++ b/fs/xfs/xfs_ioctl.c
@@ -999,6 +999,56 @@ xfs_ioc_bulkstat_single(
 	return 0;
 }
 
+STATIC int
+xfs_inumbers_fmt(
+	struct xfs_ibulk		*breq,
+	const struct xfs_inumbers	*igrp)
+{
+	if (copy_to_user(breq->ubuffer, igrp, sizeof(struct xfs_inumbers)))
+		return -EFAULT;
+	return xfs_ibulk_advance(breq, sizeof(struct xfs_inumbers));
+}
+
+/* Handle the v5 inumbers ioctl. */
+STATIC int
+xfs_ioc_inumbers(
+	struct xfs_mount		*mp,
+	unsigned int			cmd,
+	struct xfs_inumbers_req __user	*arg)
+{
+	struct xfs_bulk_ireq		hdr;
+	struct xfs_ibulk		breq = {
+		.mp			= mp,
+	};
+	int				error;
+
+	if (!capable(CAP_SYS_ADMIN))
+		return -EPERM;
+
+	if (XFS_FORCED_SHUTDOWN(mp))
+		return -EIO;
+
+	if (copy_from_user(&hdr, &arg->hdr, sizeof(hdr)))
+		return -EFAULT;
+
+	error = xfs_bulk_ireq_setup(mp, &hdr, &breq, arg->inumbers);
+	if (error == XFS_ITER_ABORT)
+		goto out_teardown;
+	if (error < 0)
+		return error;
+
+	error = xfs_inumbers(&breq, xfs_inumbers_fmt);
+	if (error)
+		return error;
+
+out_teardown:
+	xfs_bulk_ireq_teardown(&hdr, &breq);
+	if (copy_to_user(&arg->hdr, &hdr, sizeof(hdr)))
+		return -EFAULT;
+
+	return 0;
+}
+
 STATIC int
 xfs_ioc_fsgeometry(
 	struct xfs_mount	*mp,
@@ -2167,6 +2217,8 @@ xfs_file_ioctl(
 		return xfs_ioc_bulkstat(mp, cmd, arg);
 	case XFS_IOC_BULKSTAT_SINGLE:
 		return xfs_ioc_bulkstat_single(mp, cmd, arg);
+	case XFS_IOC_INUMBERS:
+		return xfs_ioc_inumbers(mp, cmd, arg);
 
 	case XFS_IOC_FSGEOMETRY_V1:
 		return xfs_ioc_fsgeometry(mp, arg, 3);
diff --git a/fs/xfs/xfs_ioctl32.c b/fs/xfs/xfs_ioctl32.c
index 6fa0f41dbae5..093d9bf4bbcf 100644
--- a/fs/xfs/xfs_ioctl32.c
+++ b/fs/xfs/xfs_ioctl32.c
@@ -582,6 +582,7 @@ xfs_file_compat_ioctl(
 	case XFS_IOC_SCRUB_METADATA:
 	case XFS_IOC_BULKSTAT:
 	case XFS_IOC_BULKSTAT_SINGLE:
+	case XFS_IOC_INUMBERS:
 		return xfs_file_ioctl(filp, cmd, p);
 #if !defined(BROKEN_X86_ALIGNMENT) || defined(CONFIG_X86_X32)
 	/*
diff --git a/fs/xfs/xfs_ondisk.h b/fs/xfs/xfs_ondisk.h
index fa1252657b08..e390e65d2438 100644
--- a/fs/xfs/xfs_ondisk.h
+++ b/fs/xfs/xfs_ondisk.h
@@ -151,6 +151,7 @@ xfs_check_ondisk_structs(void)
 	XFS_CHECK_STRUCT_SIZE(struct xfs_inumbers,		24);
 	XFS_CHECK_STRUCT_SIZE(struct xfs_bulkstat_req,		64);
 	XFS_CHECK_STRUCT_SIZE(struct xfs_bulkstat_single_req,	224);
+	XFS_CHECK_STRUCT_SIZE(struct xfs_inumbers_req,		64);
 }
 
 #endif /* __XFS_ONDISK_H */

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

* [PATCH 8/9] xfs: specify AG in bulk req
  2019-06-26 20:45 [PATCH v6 0/9] xfs: introduce new BULKSTAT and INUMBERS ioctls Darrick J. Wong
                   ` (6 preceding siblings ...)
  2019-06-26 20:46 ` [PATCH 7/9] xfs: wire up the v5 INUMBERS ioctl Darrick J. Wong
@ 2019-06-26 20:46 ` Darrick J. Wong
  2019-07-03 13:25   ` Brian Foster
  2019-06-26 20:46 ` [PATCH 9/9] xfs: allow bulkstat_single of special inodes Darrick J. Wong
  8 siblings, 1 reply; 34+ messages in thread
From: Darrick J. Wong @ 2019-06-26 20:46 UTC (permalink / raw)
  To: darrick.wong; +Cc: linux-xfs, allison.henderson

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

Add a new xfs_bulk_ireq flag to constrain the iteration to a single AG.
If the passed-in startino value is zero then we start with the first
inode in the AG that the user passes in; otherwise, we iterate only
within the same AG as the passed-in inode.

Signed-off-by: Darrick J. Wong <darrick.wong@oracle.com>
Reviewed-by: Allison Collins <allison.henderson@oracle.com>
---
 fs/xfs/libxfs/xfs_fs.h |   10 ++++++++--
 fs/xfs/xfs_ioctl.c     |   25 ++++++++++++++++++++++++-
 fs/xfs/xfs_itable.c    |    6 +++---
 fs/xfs/xfs_itable.h    |    4 ++++
 fs/xfs/xfs_iwalk.c     |   12 ++++++++++++
 fs/xfs/xfs_iwalk.h     |   22 +++++++++++++++++-----
 fs/xfs/xfs_qm.c        |    3 ++-
 7 files changed, 70 insertions(+), 12 deletions(-)


diff --git a/fs/xfs/libxfs/xfs_fs.h b/fs/xfs/libxfs/xfs_fs.h
index f9f35139d4b7..77c06850ac52 100644
--- a/fs/xfs/libxfs/xfs_fs.h
+++ b/fs/xfs/libxfs/xfs_fs.h
@@ -462,11 +462,17 @@ struct xfs_bulk_ireq {
 	uint32_t	flags;		/* I/O: operation flags		*/
 	uint32_t	icount;		/* I: count of entries in buffer */
 	uint32_t	ocount;		/* O: count of entries filled out */
-	uint32_t	reserved32;	/* must be zero			*/
+	uint32_t	agno;		/* I: see comment for IREQ_AGNO	*/
 	uint64_t	reserved[5];	/* must be zero			*/
 };
 
-#define XFS_BULK_IREQ_FLAGS_ALL	(0)
+/*
+ * Only return results from the specified @agno.  If @ino is zero, start
+ * with the first inode of @agno.
+ */
+#define XFS_BULK_IREQ_AGNO	(1 << 0)
+
+#define XFS_BULK_IREQ_FLAGS_ALL	(XFS_BULK_IREQ_AGNO)
 
 /* Header for a single inode request. */
 struct xfs_ireq {
diff --git a/fs/xfs/xfs_ioctl.c b/fs/xfs/xfs_ioctl.c
index 2ac5e100b147..f71341cd8340 100644
--- a/fs/xfs/xfs_ioctl.c
+++ b/fs/xfs/xfs_ioctl.c
@@ -853,7 +853,6 @@ xfs_bulk_ireq_setup(
 {
 	if (hdr->icount == 0 ||
 	    (hdr->flags & ~XFS_BULK_IREQ_FLAGS_ALL) ||
-	    hdr->reserved32 ||
 	    memchr_inv(hdr->reserved, 0, sizeof(hdr->reserved)))
 		return -EINVAL;
 
@@ -861,6 +860,29 @@ xfs_bulk_ireq_setup(
 	breq->ubuffer = ubuffer;
 	breq->icount = hdr->icount;
 	breq->ocount = 0;
+	breq->flags = 0;
+
+	/*
+	 * The IREQ_AGNO flag means that we only want results from a given AG.
+	 * If @hdr->ino is zero, we start iterating in that AG.  If @hdr->ino is
+	 * beyond the specified AG then we return no results.
+	 */
+	if (hdr->flags & XFS_BULK_IREQ_AGNO) {
+		if (hdr->agno >= mp->m_sb.sb_agcount)
+			return -EINVAL;
+
+		if (breq->startino == 0)
+			breq->startino = XFS_AGINO_TO_INO(mp, hdr->agno, 0);
+		else if (XFS_INO_TO_AGNO(mp, breq->startino) < hdr->agno)
+			return -EINVAL;
+
+		breq->flags |= XFS_IBULK_SAME_AG;
+
+		/* Asking for an inode past the end of the AG?  We're done! */
+		if (XFS_INO_TO_AGNO(mp, breq->startino) > hdr->agno)
+			return XFS_ITER_ABORT;
+	} else if (hdr->agno)
+		return -EINVAL;
 
 	/* Asking for an inode past the end of the FS?  We're done! */
 	if (XFS_INO_TO_AGNO(mp, breq->startino) >= mp->m_sb.sb_agcount)
@@ -945,6 +967,7 @@ xfs_ireq_setup(
 	breq->ubuffer = ubuffer;
 	breq->icount = 1;
 	breq->startino = hdr->ino;
+	breq->flags = 0;
 	return 0;
 }
 
diff --git a/fs/xfs/xfs_itable.c b/fs/xfs/xfs_itable.c
index 745b04f59132..f92a1508a2bd 100644
--- a/fs/xfs/xfs_itable.c
+++ b/fs/xfs/xfs_itable.c
@@ -248,8 +248,8 @@ xfs_bulkstat(
 	if (!bc.buf)
 		return -ENOMEM;
 
-	error = xfs_iwalk(breq->mp, NULL, breq->startino, xfs_bulkstat_iwalk,
-			breq->icount, &bc);
+	error = xfs_iwalk(breq->mp, NULL, breq->startino, breq->flags,
+			xfs_bulkstat_iwalk, breq->icount, &bc);
 
 	kmem_free(bc.buf);
 
@@ -367,7 +367,7 @@ xfs_inumbers(
 	if (xfs_bulkstat_already_done(breq->mp, breq->startino))
 		return 0;
 
-	error = xfs_inobt_walk(breq->mp, NULL, breq->startino,
+	error = xfs_inobt_walk(breq->mp, NULL, breq->startino, breq->flags,
 			xfs_inumbers_walk, breq->icount, &ic);
 
 	/*
diff --git a/fs/xfs/xfs_itable.h b/fs/xfs/xfs_itable.h
index fa9fb9104c7f..e90c1fc5b981 100644
--- a/fs/xfs/xfs_itable.h
+++ b/fs/xfs/xfs_itable.h
@@ -12,8 +12,12 @@ struct xfs_ibulk {
 	xfs_ino_t		startino; /* start with this inode */
 	unsigned int		icount;   /* number of elements in ubuffer */
 	unsigned int		ocount;   /* number of records returned */
+	unsigned int		flags;    /* see XFS_IBULK_FLAG_* */
 };
 
+/* Only iterate within the same AG as startino */
+#define XFS_IBULK_SAME_AG	(XFS_IWALK_SAME_AG)
+
 /* Return value that means we want to abort the walk. */
 #define XFS_IBULK_ABORT		(XFS_IWALK_ABORT)
 
diff --git a/fs/xfs/xfs_iwalk.c b/fs/xfs/xfs_iwalk.c
index 80c139aed264..d21d9fe71f3d 100644
--- a/fs/xfs/xfs_iwalk.c
+++ b/fs/xfs/xfs_iwalk.c
@@ -519,6 +519,7 @@ xfs_iwalk(
 	struct xfs_mount	*mp,
 	struct xfs_trans	*tp,
 	xfs_ino_t		startino,
+	unsigned int		flags,
 	xfs_iwalk_fn		iwalk_fn,
 	unsigned int		inode_records,
 	void			*data)
@@ -538,6 +539,7 @@ xfs_iwalk(
 	int			error;
 
 	ASSERT(agno < mp->m_sb.sb_agcount);
+	ASSERT(!(flags & ~XFS_IWALK_FLAGS_ALL));
 
 	error = xfs_iwalk_alloc(&iwag);
 	if (error)
@@ -548,6 +550,8 @@ xfs_iwalk(
 		if (error)
 			break;
 		iwag.startino = XFS_AGINO_TO_INO(mp, agno + 1, 0);
+		if (flags & XFS_INOBT_WALK_SAME_AG)
+			break;
 	}
 
 	xfs_iwalk_free(&iwag);
@@ -586,6 +590,7 @@ int
 xfs_iwalk_threaded(
 	struct xfs_mount	*mp,
 	xfs_ino_t		startino,
+	unsigned int		flags,
 	xfs_iwalk_fn		iwalk_fn,
 	unsigned int		inode_records,
 	bool			polled,
@@ -597,6 +602,7 @@ xfs_iwalk_threaded(
 	int			error;
 
 	ASSERT(agno < mp->m_sb.sb_agcount);
+	ASSERT(!(flags & ~XFS_IWALK_FLAGS_ALL));
 
 	nr_threads = xfs_pwork_guess_datadev_parallelism(mp);
 	error = xfs_pwork_init(mp, &pctl, xfs_iwalk_ag_work, "xfs_iwalk",
@@ -618,6 +624,8 @@ xfs_iwalk_threaded(
 		iwag->sz_recs = xfs_iwalk_prefetch(inode_records);
 		xfs_pwork_queue(&pctl, &iwag->pwork);
 		startino = XFS_AGINO_TO_INO(mp, agno + 1, 0);
+		if (flags & XFS_INOBT_WALK_SAME_AG)
+			break;
 	}
 
 	if (polled)
@@ -674,6 +682,7 @@ xfs_inobt_walk(
 	struct xfs_mount	*mp,
 	struct xfs_trans	*tp,
 	xfs_ino_t		startino,
+	unsigned int		flags,
 	xfs_inobt_walk_fn	inobt_walk_fn,
 	unsigned int		inobt_records,
 	void			*data)
@@ -691,6 +700,7 @@ xfs_inobt_walk(
 	int			error;
 
 	ASSERT(agno < mp->m_sb.sb_agcount);
+	ASSERT(!(flags & ~XFS_INOBT_WALK_FLAGS_ALL));
 
 	error = xfs_iwalk_alloc(&iwag);
 	if (error)
@@ -701,6 +711,8 @@ xfs_inobt_walk(
 		if (error)
 			break;
 		iwag.startino = XFS_AGINO_TO_INO(mp, agno + 1, 0);
+		if (flags & XFS_INOBT_WALK_SAME_AG)
+			break;
 	}
 
 	xfs_iwalk_free(&iwag);
diff --git a/fs/xfs/xfs_iwalk.h b/fs/xfs/xfs_iwalk.h
index 67462861680c..6c960e10ed4d 100644
--- a/fs/xfs/xfs_iwalk.h
+++ b/fs/xfs/xfs_iwalk.h
@@ -14,10 +14,16 @@ typedef int (*xfs_iwalk_fn)(struct xfs_mount *mp, struct xfs_trans *tp,
 #define XFS_IWALK_ABORT		(XFS_ITER_ABORT)
 
 int xfs_iwalk(struct xfs_mount *mp, struct xfs_trans *tp, xfs_ino_t startino,
-		xfs_iwalk_fn iwalk_fn, unsigned int inode_records, void *data);
+		unsigned int flags, xfs_iwalk_fn iwalk_fn,
+		unsigned int inode_records, void *data);
 int xfs_iwalk_threaded(struct xfs_mount *mp, xfs_ino_t startino,
-		xfs_iwalk_fn iwalk_fn, unsigned int inode_records, bool poll,
-		void *data);
+		unsigned int flags, xfs_iwalk_fn iwalk_fn,
+		unsigned int inode_records, bool poll, void *data);
+
+/* Only iterate inodes within the same AG as @startino. */
+#define XFS_IWALK_SAME_AG	(0x1)
+
+#define XFS_IWALK_FLAGS_ALL	(XFS_IWALK_SAME_AG)
 
 /* Walk all inode btree records in the filesystem starting from @startino. */
 typedef int (*xfs_inobt_walk_fn)(struct xfs_mount *mp, struct xfs_trans *tp,
@@ -28,7 +34,13 @@ typedef int (*xfs_inobt_walk_fn)(struct xfs_mount *mp, struct xfs_trans *tp,
 #define XFS_INOBT_WALK_ABORT	(XFS_IWALK_ABORT)
 
 int xfs_inobt_walk(struct xfs_mount *mp, struct xfs_trans *tp,
-		xfs_ino_t startino, xfs_inobt_walk_fn inobt_walk_fn,
-		unsigned int inobt_records, void *data);
+		xfs_ino_t startino, unsigned int flags,
+		xfs_inobt_walk_fn inobt_walk_fn, unsigned int inobt_records,
+		void *data);
+
+/* Only iterate inobt records within the same AG as @startino. */
+#define XFS_INOBT_WALK_SAME_AG	(XFS_IWALK_SAME_AG)
+
+#define XFS_INOBT_WALK_FLAGS_ALL (XFS_INOBT_WALK_SAME_AG)
 
 #endif /* __XFS_IWALK_H__ */
diff --git a/fs/xfs/xfs_qm.c b/fs/xfs/xfs_qm.c
index 8bb902125403..a526c28662ae 100644
--- a/fs/xfs/xfs_qm.c
+++ b/fs/xfs/xfs_qm.c
@@ -1304,7 +1304,8 @@ xfs_qm_quotacheck(
 		flags |= XFS_PQUOTA_CHKD;
 	}
 
-	error = xfs_iwalk_threaded(mp, 0, xfs_qm_dqusage_adjust, 0, true, NULL);
+	error = xfs_iwalk_threaded(mp, 0, 0, xfs_qm_dqusage_adjust, 0, true,
+			NULL);
 	if (error)
 		goto error_return;
 

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

* [PATCH 9/9] xfs: allow bulkstat_single of special inodes
  2019-06-26 20:45 [PATCH v6 0/9] xfs: introduce new BULKSTAT and INUMBERS ioctls Darrick J. Wong
                   ` (7 preceding siblings ...)
  2019-06-26 20:46 ` [PATCH 8/9] xfs: specify AG in bulk req Darrick J. Wong
@ 2019-06-26 20:46 ` Darrick J. Wong
  2019-07-03 13:25   ` Brian Foster
                     ` (2 more replies)
  8 siblings, 3 replies; 34+ messages in thread
From: Darrick J. Wong @ 2019-06-26 20:46 UTC (permalink / raw)
  To: darrick.wong; +Cc: linux-xfs, allison.henderson

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

Create a new ireq flag (for single bulkstats) that enables userspace to
ask us for a special inode number instead of interpreting @ino as a
literal inode number.  This enables us to query the root inode easily.

Signed-off-by: Darrick J. Wong <darrick.wong@oracle.com>
Reviewed-by: Allison Collins <allison.henderson@oracle.com>
---
 fs/xfs/libxfs/xfs_fs.h |   11 ++++++++++-
 fs/xfs/xfs_ioctl.c     |   10 ++++++++++
 2 files changed, 20 insertions(+), 1 deletion(-)


diff --git a/fs/xfs/libxfs/xfs_fs.h b/fs/xfs/libxfs/xfs_fs.h
index 77c06850ac52..1489bce07d66 100644
--- a/fs/xfs/libxfs/xfs_fs.h
+++ b/fs/xfs/libxfs/xfs_fs.h
@@ -482,7 +482,16 @@ struct xfs_ireq {
 	uint64_t	reserved[2];	/* must be zero			*/
 };
 
-#define XFS_IREQ_FLAGS_ALL	(0)
+/*
+ * The @ino value is a special value, not a literal inode number.  See the
+ * XFS_IREQ_SPECIAL_* values below.
+ */
+#define XFS_IREQ_SPECIAL	(1 << 0)
+
+#define XFS_IREQ_FLAGS_ALL	(XFS_IREQ_SPECIAL)
+
+/* Operate on the root directory inode. */
+#define XFS_IREQ_SPECIAL_ROOT	(1)
 
 /*
  * ioctl structures for v5 bulkstat and inumbers requests
diff --git a/fs/xfs/xfs_ioctl.c b/fs/xfs/xfs_ioctl.c
index f71341cd8340..3bb5f980fabf 100644
--- a/fs/xfs/xfs_ioctl.c
+++ b/fs/xfs/xfs_ioctl.c
@@ -961,6 +961,16 @@ xfs_ireq_setup(
 	    memchr_inv(hdr->reserved, 0, sizeof(hdr->reserved)))
 		return -EINVAL;
 
+	if (hdr->flags & XFS_IREQ_SPECIAL) {
+		switch (hdr->ino) {
+		case XFS_IREQ_SPECIAL_ROOT:
+			hdr->ino = mp->m_sb.sb_rootino;
+			break;
+		default:
+			return -EINVAL;
+		}
+	}
+
 	if (XFS_INO_TO_AGNO(mp, hdr->ino) >= mp->m_sb.sb_agcount)
 		return -EINVAL;
 

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

* Re: [PATCH 1/9] xfs: remove various bulk request typedef usage
  2019-06-26 20:45 ` [PATCH 1/9] xfs: remove various bulk request typedef usage Darrick J. Wong
@ 2019-07-03 13:22   ` Brian Foster
  0 siblings, 0 replies; 34+ messages in thread
From: Brian Foster @ 2019-07-03 13:22 UTC (permalink / raw)
  To: Darrick J. Wong; +Cc: linux-xfs, allison.henderson

On Wed, Jun 26, 2019 at 01:45:39PM -0700, Darrick J. Wong wrote:
> From: Darrick J. Wong <darrick.wong@oracle.com>
> 
> Remove xfs_bstat_t, xfs_fsop_bulkreq_t, xfs_inogrp_t, and similarly
> named compat typedefs.
> 
> Signed-off-by: Darrick J. Wong <darrick.wong@oracle.com>
> Reviewed-by: Allison Collins <allison.henderson@oracle.com>
> ---

Reviewed-by: Brian Foster <bfoster@redhat.com>

>  fs/xfs/libxfs/xfs_fs.h |   16 ++++++++--------
>  fs/xfs/xfs_ioctl.c     |    2 +-
>  fs/xfs/xfs_ioctl32.c   |   11 +++++++----
>  fs/xfs/xfs_ioctl32.h   |   14 +++++++-------
>  4 files changed, 23 insertions(+), 20 deletions(-)
> 
> 
> diff --git a/fs/xfs/libxfs/xfs_fs.h b/fs/xfs/libxfs/xfs_fs.h
> index e7382c780ed7..ef0dce229fa4 100644
> --- a/fs/xfs/libxfs/xfs_fs.h
> +++ b/fs/xfs/libxfs/xfs_fs.h
> @@ -97,7 +97,7 @@ struct getbmapx {
>   * For use by backup and restore programs to set the XFS on-disk inode
>   * fields di_dmevmask and di_dmstate.  These must be set to exactly and
>   * only values previously obtained via xfs_bulkstat!  (Specifically the
> - * xfs_bstat_t fields bs_dmevmask and bs_dmstate.)
> + * struct xfs_bstat fields bs_dmevmask and bs_dmstate.)
>   */
>  #ifndef HAVE_FSDMIDATA
>  struct fsdmidata {
> @@ -328,7 +328,7 @@ typedef struct xfs_bstime {
>  	__s32		tv_nsec;	/* and nanoseconds	*/
>  } xfs_bstime_t;
>  
> -typedef struct xfs_bstat {
> +struct xfs_bstat {
>  	__u64		bs_ino;		/* inode number			*/
>  	__u16		bs_mode;	/* type and mode		*/
>  	__u16		bs_nlink;	/* number of links		*/
> @@ -356,7 +356,7 @@ typedef struct xfs_bstat {
>  	__u32		bs_dmevmask;	/* DMIG event mask		*/
>  	__u16		bs_dmstate;	/* DMIG state info		*/
>  	__u16		bs_aextents;	/* attribute number of extents	*/
> -} xfs_bstat_t;
> +};
>  
>  /* bs_sick flags */
>  #define XFS_BS_SICK_INODE	(1 << 0)  /* inode core */
> @@ -382,22 +382,22 @@ bstat_get_projid(struct xfs_bstat *bs)
>  /*
>   * The user-level BulkStat Request interface structure.
>   */
> -typedef struct xfs_fsop_bulkreq {
> +struct xfs_fsop_bulkreq {
>  	__u64		__user *lastip;	/* last inode # pointer		*/
>  	__s32		icount;		/* count of entries in buffer	*/
>  	void		__user *ubuffer;/* user buffer for inode desc.	*/
>  	__s32		__user *ocount;	/* output count pointer		*/
> -} xfs_fsop_bulkreq_t;
> +};
>  
>  
>  /*
>   * Structures returned from xfs_inumbers routine (XFS_IOC_FSINUMBERS).
>   */
> -typedef struct xfs_inogrp {
> +struct xfs_inogrp {
>  	__u64		xi_startino;	/* starting inode number	*/
>  	__s32		xi_alloccount;	/* # bits set in allocmask	*/
>  	__u64		xi_allocmask;	/* mask of allocated inodes	*/
> -} xfs_inogrp_t;
> +};
>  
>  
>  /*
> @@ -529,7 +529,7 @@ typedef struct xfs_swapext
>  	xfs_off_t	sx_offset;	/* offset into file */
>  	xfs_off_t	sx_length;	/* leng from offset */
>  	char		sx_pad[16];	/* pad space, unused */
> -	xfs_bstat_t	sx_stat;	/* stat of target b4 copy */
> +	struct xfs_bstat sx_stat;	/* stat of target b4 copy */
>  } xfs_swapext_t;
>  
>  /*
> diff --git a/fs/xfs/xfs_ioctl.c b/fs/xfs/xfs_ioctl.c
> index 04b661ff0799..34b38d8e8dc9 100644
> --- a/fs/xfs/xfs_ioctl.c
> +++ b/fs/xfs/xfs_ioctl.c
> @@ -766,7 +766,7 @@ xfs_ioc_bulkstat(
>  	if (XFS_FORCED_SHUTDOWN(mp))
>  		return -EIO;
>  
> -	if (copy_from_user(&bulkreq, arg, sizeof(xfs_fsop_bulkreq_t)))
> +	if (copy_from_user(&bulkreq, arg, sizeof(struct xfs_fsop_bulkreq)))
>  		return -EFAULT;
>  
>  	if (copy_from_user(&lastino, bulkreq.lastip, sizeof(__s64)))
> diff --git a/fs/xfs/xfs_ioctl32.c b/fs/xfs/xfs_ioctl32.c
> index f3949684c49c..d7c5153e1b61 100644
> --- a/fs/xfs/xfs_ioctl32.c
> +++ b/fs/xfs/xfs_ioctl32.c
> @@ -118,11 +118,14 @@ xfs_ioctl32_bstime_copyin(
>  	return 0;
>  }
>  
> -/* xfs_bstat_t has differing alignment on intel, & bstime_t sizes everywhere */
> +/*
> + * struct xfs_bstat has differing alignment on intel, & bstime_t sizes
> + * everywhere
> + */
>  STATIC int
>  xfs_ioctl32_bstat_copyin(
> -	xfs_bstat_t		*bstat,
> -	compat_xfs_bstat_t	__user *bstat32)
> +	struct xfs_bstat		*bstat,
> +	struct compat_xfs_bstat	__user	*bstat32)
>  {
>  	if (get_user(bstat->bs_ino,	&bstat32->bs_ino)	||
>  	    get_user(bstat->bs_mode,	&bstat32->bs_mode)	||
> @@ -206,7 +209,7 @@ STATIC int
>  xfs_compat_ioc_bulkstat(
>  	xfs_mount_t		  *mp,
>  	unsigned int		  cmd,
> -	compat_xfs_fsop_bulkreq_t __user *p32)
> +	struct compat_xfs_fsop_bulkreq __user *p32)
>  {
>  	u32			addr;
>  	struct xfs_fsop_bulkreq	bulkreq;
> diff --git a/fs/xfs/xfs_ioctl32.h b/fs/xfs/xfs_ioctl32.h
> index d28fa824284a..7985344d3aa6 100644
> --- a/fs/xfs/xfs_ioctl32.h
> +++ b/fs/xfs/xfs_ioctl32.h
> @@ -36,7 +36,7 @@ typedef struct compat_xfs_bstime {
>  	__s32		tv_nsec;	/* and nanoseconds	*/
>  } compat_xfs_bstime_t;
>  
> -typedef struct compat_xfs_bstat {
> +struct compat_xfs_bstat {
>  	__u64		bs_ino;		/* inode number			*/
>  	__u16		bs_mode;	/* type and mode		*/
>  	__u16		bs_nlink;	/* number of links		*/
> @@ -61,14 +61,14 @@ typedef struct compat_xfs_bstat {
>  	__u32		bs_dmevmask;	/* DMIG event mask		*/
>  	__u16		bs_dmstate;	/* DMIG state info		*/
>  	__u16		bs_aextents;	/* attribute number of extents	*/
> -} __compat_packed compat_xfs_bstat_t;
> +} __compat_packed;
>  
> -typedef struct compat_xfs_fsop_bulkreq {
> +struct compat_xfs_fsop_bulkreq {
>  	compat_uptr_t	lastip;		/* last inode # pointer		*/
>  	__s32		icount;		/* count of entries in buffer	*/
>  	compat_uptr_t	ubuffer;	/* user buffer for inode desc.	*/
>  	compat_uptr_t	ocount;		/* output count pointer		*/
> -} compat_xfs_fsop_bulkreq_t;
> +};
>  
>  #define XFS_IOC_FSBULKSTAT_32 \
>  	_IOWR('X', 101, struct compat_xfs_fsop_bulkreq)
> @@ -106,7 +106,7 @@ typedef struct compat_xfs_swapext {
>  	xfs_off_t		sx_offset;	/* offset into file */
>  	xfs_off_t		sx_length;	/* leng from offset */
>  	char			sx_pad[16];	/* pad space, unused */
> -	compat_xfs_bstat_t	sx_stat;	/* stat of target b4 copy */
> +	struct compat_xfs_bstat	sx_stat;	/* stat of target b4 copy */
>  } __compat_packed compat_xfs_swapext_t;
>  
>  #define XFS_IOC_SWAPEXT_32	_IOWR('X', 109, struct compat_xfs_swapext)
> @@ -201,11 +201,11 @@ typedef struct compat_xfs_fsop_geom_v1 {
>  #define XFS_IOC_FSGEOMETRY_V1_32  \
>  	_IOR('X', 100, struct compat_xfs_fsop_geom_v1)
>  
> -typedef struct compat_xfs_inogrp {
> +struct compat_xfs_inogrp {
>  	__u64		xi_startino;	/* starting inode number	*/
>  	__s32		xi_alloccount;	/* # bits set in allocmask	*/
>  	__u64		xi_allocmask;	/* mask of allocated inodes	*/
> -} __attribute__((packed)) compat_xfs_inogrp_t;
> +} __attribute__((packed));
>  
>  /* These growfs input structures have padding on the end, so must translate */
>  typedef struct compat_xfs_growfs_data {
> 

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

* Re: [PATCH 2/9] xfs: rename bulkstat functions
  2019-06-26 20:45 ` [PATCH 2/9] xfs: rename bulkstat functions Darrick J. Wong
@ 2019-07-03 13:22   ` Brian Foster
  0 siblings, 0 replies; 34+ messages in thread
From: Brian Foster @ 2019-07-03 13:22 UTC (permalink / raw)
  To: Darrick J. Wong; +Cc: linux-xfs, allison.henderson

On Wed, Jun 26, 2019 at 01:45:45PM -0700, Darrick J. Wong wrote:
> From: Darrick J. Wong <darrick.wong@oracle.com>
> 
> Rename the bulkstat functions to 'fsbulkstat' so that they match the
> ioctl names.  We will be introducing a new set of bulkstat/inumbers
> ioctls soon, and it will be important to keep the names straight.
> 
> Signed-off-by: Darrick J. Wong <darrick.wong@oracle.com>
> Reviewed-by: Allison Collins <allison.henderson@oracle.com>
> ---

Reviewed-by: Brian Foster <bfoster@redhat.com>

>  fs/xfs/xfs_ioctl.c   |   14 +++++++-------
>  fs/xfs/xfs_ioctl.h   |    5 +++--
>  fs/xfs/xfs_ioctl32.c |   18 +++++++++---------
>  3 files changed, 19 insertions(+), 18 deletions(-)
> 
> 
> diff --git a/fs/xfs/xfs_ioctl.c b/fs/xfs/xfs_ioctl.c
> index 34b38d8e8dc9..5e0476003763 100644
> --- a/fs/xfs/xfs_ioctl.c
> +++ b/fs/xfs/xfs_ioctl.c
> @@ -724,7 +724,7 @@ xfs_ioc_space(
>  
>  /* Return 0 on success or positive error */
>  int
> -xfs_bulkstat_one_fmt(
> +xfs_fsbulkstat_one_fmt(
>  	struct xfs_ibulk	*breq,
>  	const struct xfs_bstat	*bstat)
>  {
> @@ -734,7 +734,7 @@ xfs_bulkstat_one_fmt(
>  }
>  
>  int
> -xfs_inumbers_fmt(
> +xfs_fsinumbers_fmt(
>  	struct xfs_ibulk	*breq,
>  	const struct xfs_inogrp	*igrp)
>  {
> @@ -744,7 +744,7 @@ xfs_inumbers_fmt(
>  }
>  
>  STATIC int
> -xfs_ioc_bulkstat(
> +xfs_ioc_fsbulkstat(
>  	xfs_mount_t		*mp,
>  	unsigned int		cmd,
>  	void			__user *arg)
> @@ -794,16 +794,16 @@ xfs_ioc_bulkstat(
>  	 */
>  	if (cmd == XFS_IOC_FSINUMBERS) {
>  		breq.startino = lastino ? lastino + 1 : 0;
> -		error = xfs_inumbers(&breq, xfs_inumbers_fmt);
> +		error = xfs_inumbers(&breq, xfs_fsinumbers_fmt);
>  		lastino = breq.startino - 1;
>  	} else if (cmd == XFS_IOC_FSBULKSTAT_SINGLE) {
>  		breq.startino = lastino;
>  		breq.icount = 1;
> -		error = xfs_bulkstat_one(&breq, xfs_bulkstat_one_fmt);
> +		error = xfs_bulkstat_one(&breq, xfs_fsbulkstat_one_fmt);
>  		lastino = breq.startino;
>  	} else {	/* XFS_IOC_FSBULKSTAT */
>  		breq.startino = lastino ? lastino + 1 : 0;
> -		error = xfs_bulkstat(&breq, xfs_bulkstat_one_fmt);
> +		error = xfs_bulkstat(&breq, xfs_fsbulkstat_one_fmt);
>  		lastino = breq.startino - 1;
>  	}
>  
> @@ -1983,7 +1983,7 @@ xfs_file_ioctl(
>  	case XFS_IOC_FSBULKSTAT_SINGLE:
>  	case XFS_IOC_FSBULKSTAT:
>  	case XFS_IOC_FSINUMBERS:
> -		return xfs_ioc_bulkstat(mp, cmd, arg);
> +		return xfs_ioc_fsbulkstat(mp, cmd, arg);
>  
>  	case XFS_IOC_FSGEOMETRY_V1:
>  		return xfs_ioc_fsgeometry(mp, arg, 3);
> diff --git a/fs/xfs/xfs_ioctl.h b/fs/xfs/xfs_ioctl.h
> index fb303eaa8863..cb34bc821201 100644
> --- a/fs/xfs/xfs_ioctl.h
> +++ b/fs/xfs/xfs_ioctl.h
> @@ -81,7 +81,8 @@ struct xfs_ibulk;
>  struct xfs_bstat;
>  struct xfs_inogrp;
>  
> -int xfs_bulkstat_one_fmt(struct xfs_ibulk *breq, const struct xfs_bstat *bstat);
> -int xfs_inumbers_fmt(struct xfs_ibulk *breq, const struct xfs_inogrp *igrp);
> +int xfs_fsbulkstat_one_fmt(struct xfs_ibulk *breq,
> +			   const struct xfs_bstat *bstat);
> +int xfs_fsinumbers_fmt(struct xfs_ibulk *breq, const struct xfs_inogrp *igrp);
>  
>  #endif
> diff --git a/fs/xfs/xfs_ioctl32.c b/fs/xfs/xfs_ioctl32.c
> index d7c5153e1b61..9e5cf3988d3e 100644
> --- a/fs/xfs/xfs_ioctl32.c
> +++ b/fs/xfs/xfs_ioctl32.c
> @@ -86,7 +86,7 @@ xfs_compat_growfs_rt_copyin(
>  }
>  
>  STATIC int
> -xfs_inumbers_fmt_compat(
> +xfs_fsinumbers_fmt_compat(
>  	struct xfs_ibulk	*breq,
>  	const struct xfs_inogrp	*igrp)
>  {
> @@ -101,7 +101,7 @@ xfs_inumbers_fmt_compat(
>  }
>  
>  #else
> -#define xfs_inumbers_fmt_compat xfs_inumbers_fmt
> +#define xfs_fsinumbers_fmt_compat xfs_fsinumbers_fmt
>  #endif	/* BROKEN_X86_ALIGNMENT */
>  
>  STATIC int
> @@ -171,7 +171,7 @@ xfs_bstime_store_compat(
>  
>  /* Return 0 on success or positive error (to xfs_bulkstat()) */
>  STATIC int
> -xfs_bulkstat_one_fmt_compat(
> +xfs_fsbulkstat_one_fmt_compat(
>  	struct xfs_ibulk	*breq,
>  	const struct xfs_bstat	*buffer)
>  {
> @@ -206,7 +206,7 @@ xfs_bulkstat_one_fmt_compat(
>  
>  /* copied from xfs_ioctl.c */
>  STATIC int
> -xfs_compat_ioc_bulkstat(
> +xfs_compat_ioc_fsbulkstat(
>  	xfs_mount_t		  *mp,
>  	unsigned int		  cmd,
>  	struct compat_xfs_fsop_bulkreq __user *p32)
> @@ -226,8 +226,8 @@ xfs_compat_ioc_bulkstat(
>  	 * to userpace memory via bulkreq.ubuffer.  Normally the compat
>  	 * functions and structure size are the correct ones to use ...
>  	 */
> -	inumbers_fmt_pf		inumbers_func = xfs_inumbers_fmt_compat;
> -	bulkstat_one_fmt_pf	bs_one_func = xfs_bulkstat_one_fmt_compat;
> +	inumbers_fmt_pf		inumbers_func = xfs_fsinumbers_fmt_compat;
> +	bulkstat_one_fmt_pf	bs_one_func = xfs_fsbulkstat_one_fmt_compat;
>  
>  #ifdef CONFIG_X86_X32
>  	if (in_x32_syscall()) {
> @@ -239,8 +239,8 @@ xfs_compat_ioc_bulkstat(
>  		 * the data written out in compat layout will not match what
>  		 * x32 userspace expects.
>  		 */
> -		inumbers_func = xfs_inumbers_fmt;
> -		bs_one_func = xfs_bulkstat_one_fmt;
> +		inumbers_func = xfs_fsinumbers_fmt;
> +		bs_one_func = xfs_fsbulkstat_one_fmt;
>  	}
>  #endif
>  
> @@ -669,7 +669,7 @@ xfs_file_compat_ioctl(
>  	case XFS_IOC_FSBULKSTAT_32:
>  	case XFS_IOC_FSBULKSTAT_SINGLE_32:
>  	case XFS_IOC_FSINUMBERS_32:
> -		return xfs_compat_ioc_bulkstat(mp, cmd, arg);
> +		return xfs_compat_ioc_fsbulkstat(mp, cmd, arg);
>  	case XFS_IOC_FD_TO_HANDLE_32:
>  	case XFS_IOC_PATH_TO_HANDLE_32:
>  	case XFS_IOC_PATH_TO_FSHANDLE_32: {
> 

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

* Re: [PATCH 3/9] xfs: introduce new v5 bulkstat structure
  2019-06-26 20:45 ` [PATCH 3/9] xfs: introduce new v5 bulkstat structure Darrick J. Wong
@ 2019-07-03 13:23   ` Brian Foster
  2019-07-03 14:42     ` Darrick J. Wong
  2019-07-03 15:32   ` [PATCH v2 " Darrick J. Wong
  1 sibling, 1 reply; 34+ messages in thread
From: Brian Foster @ 2019-07-03 13:23 UTC (permalink / raw)
  To: Darrick J. Wong; +Cc: linux-xfs, allison.henderson

On Wed, Jun 26, 2019 at 01:45:52PM -0700, Darrick J. Wong wrote:
> From: Darrick J. Wong <darrick.wong@oracle.com>
> 
> Introduce a new version of the in-core bulkstat structure that supports
> our new v5 format features.  This structure also fills the gaps in the
> previous structure.  We leave wiring up the ioctls for the next patch.
> 
> Signed-off-by: Darrick J. Wong <darrick.wong@oracle.com>
> Reviewed-by: Allison Collins <allison.henderson@oracle.com>
> ---
>  fs/xfs/libxfs/xfs_fs.h     |   48 ++++++++++++++++++++++++++++
>  fs/xfs/libxfs/xfs_health.h |    2 +
>  fs/xfs/xfs_health.c        |    2 +
>  fs/xfs/xfs_ioctl.c         |    9 ++++-
>  fs/xfs/xfs_ioctl.h         |    2 +
>  fs/xfs/xfs_ioctl32.c       |   10 ++++--
>  fs/xfs/xfs_itable.c        |   75 +++++++++++++++++++++++++++++++++-----------
>  fs/xfs/xfs_itable.h        |    4 ++
>  fs/xfs/xfs_ondisk.h        |    2 +
>  9 files changed, 124 insertions(+), 30 deletions(-)
> 
> 
...
> diff --git a/fs/xfs/xfs_itable.c b/fs/xfs/xfs_itable.c
> index 45f0618efb8d..50c2bb8e13c4 100644
> --- a/fs/xfs/xfs_itable.c
> +++ b/fs/xfs/xfs_itable.c
...
> @@ -266,6 +266,43 @@ xfs_bulkstat(
>  	return error;
>  }
>  
> +/* Convert bulkstat (v5) to bstat (v1). */
> +void
> +xfs_bulkstat_to_bstat(
> +	struct xfs_mount		*mp,
> +	struct xfs_bstat		*bs1,
> +	const struct xfs_bulkstat	*bstat)
> +{
> +	bs1->bs_ino = bstat->bs_ino;
> +	bs1->bs_mode = bstat->bs_mode;
> +	bs1->bs_nlink = bstat->bs_nlink;
> +	bs1->bs_uid = bstat->bs_uid;
> +	bs1->bs_gid = bstat->bs_gid;
> +	bs1->bs_rdev = bstat->bs_rdev;
> +	bs1->bs_blksize = bstat->bs_blksize;
> +	bs1->bs_size = bstat->bs_size;
> +	bs1->bs_atime.tv_sec = bstat->bs_atime;
> +	bs1->bs_mtime.tv_sec = bstat->bs_mtime;
> +	bs1->bs_ctime.tv_sec = bstat->bs_ctime;
> +	bs1->bs_atime.tv_nsec = bstat->bs_atime_nsec;
> +	bs1->bs_mtime.tv_nsec = bstat->bs_mtime_nsec;
> +	bs1->bs_ctime.tv_nsec = bstat->bs_ctime_nsec;
> +	bs1->bs_blocks = bstat->bs_blocks;
> +	bs1->bs_xflags = bstat->bs_xflags;
> +	bs1->bs_extsize = bstat->bs_extsize_blks << mp->m_sb.sb_blocklog;
> +	bs1->bs_extents = bstat->bs_extents;
> +	bs1->bs_gen = bstat->bs_gen;
> +	bs1->bs_projid_lo = bstat->bs_projectid & 0xFFFF;
> +	bs1->bs_forkoff = bstat->bs_forkoff;
> +	bs1->bs_projid_hi = bstat->bs_projectid >> 16;
> +	bs1->bs_sick = bstat->bs_sick;
> +	bs1->bs_checked = bstat->bs_checked;
> +	bs1->bs_cowextsize = bstat->bs_cowextsize_blks << mp->m_sb.sb_blocklog;
> +	bs1->bs_dmevmask = 0;
> +	bs1->bs_dmstate = 0;

Any particular reason these fields are now stubbed out?
Deprecated/unused? It looks like we at least still have a mechanism to
set these values, but I have no idea if there are any users (or what
they're for for that matter :P).

Also, should we zero the padding space in bs1 here? It looks like the
callers allocate bs1 on the stack without any initialization, do the
conversion and immediately copy to userspace.

Brian

> +	bs1->bs_aextents = bstat->bs_aextents;
> +}
> +
>  struct xfs_inumbers_chunk {
>  	inumbers_fmt_pf		formatter;
>  	struct xfs_ibulk	*breq;
> diff --git a/fs/xfs/xfs_itable.h b/fs/xfs/xfs_itable.h
> index cfd3c93226f3..60e259192056 100644
> --- a/fs/xfs/xfs_itable.h
> +++ b/fs/xfs/xfs_itable.h
> @@ -38,10 +38,12 @@ xfs_ibulk_advance(
>   */
>  
>  typedef int (*bulkstat_one_fmt_pf)(struct xfs_ibulk *breq,
> -		const struct xfs_bstat *bstat);
> +		const struct xfs_bulkstat *bstat);
>  
>  int xfs_bulkstat_one(struct xfs_ibulk *breq, bulkstat_one_fmt_pf formatter);
>  int xfs_bulkstat(struct xfs_ibulk *breq, bulkstat_one_fmt_pf formatter);
> +void xfs_bulkstat_to_bstat(struct xfs_mount *mp, struct xfs_bstat *bs1,
> +		const struct xfs_bulkstat *bstat);
>  
>  typedef int (*inumbers_fmt_pf)(struct xfs_ibulk *breq,
>  		const struct xfs_inogrp *igrp);
> diff --git a/fs/xfs/xfs_ondisk.h b/fs/xfs/xfs_ondisk.h
> index c8ba98fae30a..0b4cdda68524 100644
> --- a/fs/xfs/xfs_ondisk.h
> +++ b/fs/xfs/xfs_ondisk.h
> @@ -146,6 +146,8 @@ xfs_check_ondisk_structs(void)
>  	XFS_CHECK_OFFSET(struct xfs_dir3_data_hdr, hdr.magic,	0);
>  	XFS_CHECK_OFFSET(struct xfs_dir3_free, hdr.hdr.magic,	0);
>  	XFS_CHECK_OFFSET(struct xfs_attr3_leafblock, hdr.info.hdr, 0);
> +
> +	XFS_CHECK_STRUCT_SIZE(struct xfs_bulkstat,		192);
>  }
>  
>  #endif /* __XFS_ONDISK_H */
> 

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

* Re: [PATCH 4/9] xfs: introduce v5 inode group structure
  2019-06-26 20:45 ` [PATCH 4/9] xfs: introduce v5 inode group structure Darrick J. Wong
@ 2019-07-03 13:23   ` Brian Foster
  0 siblings, 0 replies; 34+ messages in thread
From: Brian Foster @ 2019-07-03 13:23 UTC (permalink / raw)
  To: Darrick J. Wong; +Cc: linux-xfs, allison.henderson

On Wed, Jun 26, 2019 at 01:45:58PM -0700, Darrick J. Wong wrote:
> From: Darrick J. Wong <darrick.wong@oracle.com>
> 
> Introduce a new "v5" inode group structure that fixes the alignment
> and padding problems of the existing structure.
> 
> Signed-off-by: Darrick J. Wong <darrick.wong@oracle.com>
> ---

Reviewed-by: Brian Foster <bfoster@redhat.com>

>  fs/xfs/libxfs/xfs_fs.h |   11 +++++++++++
>  fs/xfs/xfs_ioctl.c     |    9 ++++++---
>  fs/xfs/xfs_ioctl.h     |    2 +-
>  fs/xfs/xfs_ioctl32.c   |   10 +++++++---
>  fs/xfs/xfs_itable.c    |   14 +++++++++++++-
>  fs/xfs/xfs_itable.h    |    4 +++-
>  fs/xfs/xfs_ondisk.h    |    1 +
>  7 files changed, 42 insertions(+), 9 deletions(-)
> 
> 
> diff --git a/fs/xfs/libxfs/xfs_fs.h b/fs/xfs/libxfs/xfs_fs.h
> index 132e364eb141..8b8fe78511fb 100644
> --- a/fs/xfs/libxfs/xfs_fs.h
> +++ b/fs/xfs/libxfs/xfs_fs.h
> @@ -445,6 +445,17 @@ struct xfs_inogrp {
>  	__u64		xi_allocmask;	/* mask of allocated inodes	*/
>  };
>  
> +/* New inumbers structure that reports v5 features and fixes padding issues */
> +struct xfs_inumbers {
> +	uint64_t	xi_startino;	/* starting inode number	*/
> +	uint64_t	xi_allocmask;	/* mask of allocated inodes	*/
> +	uint8_t		xi_alloccount;	/* # bits set in allocmask	*/
> +	uint8_t		xi_version;	/* version			*/
> +	uint8_t		xi_padding[6];	/* zero				*/
> +};
> +
> +#define XFS_INUMBERS_VERSION_V1	(1)
> +#define XFS_INUMBERS_VERSION_V5	(5)
>  
>  /*
>   * Error injection.
> diff --git a/fs/xfs/xfs_ioctl.c b/fs/xfs/xfs_ioctl.c
> index 0b8c631d53dd..47580762e154 100644
> --- a/fs/xfs/xfs_ioctl.c
> +++ b/fs/xfs/xfs_ioctl.c
> @@ -738,10 +738,13 @@ xfs_fsbulkstat_one_fmt(
>  
>  int
>  xfs_fsinumbers_fmt(
> -	struct xfs_ibulk	*breq,
> -	const struct xfs_inogrp	*igrp)
> +	struct xfs_ibulk		*breq,
> +	const struct xfs_inumbers	*igrp)
>  {
> -	if (copy_to_user(breq->ubuffer, igrp, sizeof(*igrp)))
> +	struct xfs_inogrp		ig1;
> +
> +	xfs_inumbers_to_inogrp(&ig1, igrp);
> +	if (copy_to_user(breq->ubuffer, &ig1, sizeof(struct xfs_inogrp)))
>  		return -EFAULT;
>  	return xfs_ibulk_advance(breq, sizeof(struct xfs_inogrp));
>  }
> diff --git a/fs/xfs/xfs_ioctl.h b/fs/xfs/xfs_ioctl.h
> index 514d3028a134..654c0bb1bcf8 100644
> --- a/fs/xfs/xfs_ioctl.h
> +++ b/fs/xfs/xfs_ioctl.h
> @@ -83,6 +83,6 @@ struct xfs_inogrp;
>  
>  int xfs_fsbulkstat_one_fmt(struct xfs_ibulk *breq,
>  			   const struct xfs_bulkstat *bstat);
> -int xfs_fsinumbers_fmt(struct xfs_ibulk *breq, const struct xfs_inogrp *igrp);
> +int xfs_fsinumbers_fmt(struct xfs_ibulk *breq, const struct xfs_inumbers *igrp);
>  
>  #endif
> diff --git a/fs/xfs/xfs_ioctl32.c b/fs/xfs/xfs_ioctl32.c
> index a97612927f9e..41485e2ed431 100644
> --- a/fs/xfs/xfs_ioctl32.c
> +++ b/fs/xfs/xfs_ioctl32.c
> @@ -87,10 +87,14 @@ xfs_compat_growfs_rt_copyin(
>  
>  STATIC int
>  xfs_fsinumbers_fmt_compat(
> -	struct xfs_ibulk	*breq,
> -	const struct xfs_inogrp	*igrp)
> +	struct xfs_ibulk		*breq,
> +	const struct xfs_inumbers	*ig)
>  {
> -	struct compat_xfs_inogrp __user *p32 = breq->ubuffer;
> +	struct compat_xfs_inogrp __user	*p32 = breq->ubuffer;
> +	struct xfs_inogrp		ig1;
> +	struct xfs_inogrp		*igrp = &ig1;
> +
> +	xfs_inumbers_to_inogrp(&ig1, ig);
>  
>  	if (put_user(igrp->xi_startino,   &p32->xi_startino) ||
>  	    put_user(igrp->xi_alloccount, &p32->xi_alloccount) ||
> diff --git a/fs/xfs/xfs_itable.c b/fs/xfs/xfs_itable.c
> index 50c2bb8e13c4..745b04f59132 100644
> --- a/fs/xfs/xfs_itable.c
> +++ b/fs/xfs/xfs_itable.c
> @@ -331,10 +331,11 @@ xfs_inumbers_walk(
>  	const struct xfs_inobt_rec_incore *irec,
>  	void			*data)
>  {
> -	struct xfs_inogrp	inogrp = {
> +	struct xfs_inumbers	inogrp = {
>  		.xi_startino	= XFS_AGINO_TO_INO(mp, agno, irec->ir_startino),
>  		.xi_alloccount	= irec->ir_count - irec->ir_freecount,
>  		.xi_allocmask	= ~irec->ir_free,
> +		.xi_version	= XFS_INUMBERS_VERSION_V5,
>  	};
>  	struct xfs_inumbers_chunk *ic = data;
>  	xfs_agino_t		agino;
> @@ -381,3 +382,14 @@ xfs_inumbers(
>  
>  	return error;
>  }
> +
> +/* Convert an inumbers (v5) struct to a inogrp (v1) struct. */
> +void
> +xfs_inumbers_to_inogrp(
> +	struct xfs_inogrp		*ig1,
> +	const struct xfs_inumbers	*ig)
> +{
> +	ig1->xi_startino = ig->xi_startino;
> +	ig1->xi_alloccount = ig->xi_alloccount;
> +	ig1->xi_allocmask = ig->xi_allocmask;
> +}
> diff --git a/fs/xfs/xfs_itable.h b/fs/xfs/xfs_itable.h
> index 60e259192056..fa9fb9104c7f 100644
> --- a/fs/xfs/xfs_itable.h
> +++ b/fs/xfs/xfs_itable.h
> @@ -46,8 +46,10 @@ void xfs_bulkstat_to_bstat(struct xfs_mount *mp, struct xfs_bstat *bs1,
>  		const struct xfs_bulkstat *bstat);
>  
>  typedef int (*inumbers_fmt_pf)(struct xfs_ibulk *breq,
> -		const struct xfs_inogrp *igrp);
> +		const struct xfs_inumbers *igrp);
>  
>  int xfs_inumbers(struct xfs_ibulk *breq, inumbers_fmt_pf formatter);
> +void xfs_inumbers_to_inogrp(struct xfs_inogrp *ig1,
> +		const struct xfs_inumbers *ig);
>  
>  #endif	/* __XFS_ITABLE_H__ */
> diff --git a/fs/xfs/xfs_ondisk.h b/fs/xfs/xfs_ondisk.h
> index 0b4cdda68524..d8f941b4d51c 100644
> --- a/fs/xfs/xfs_ondisk.h
> +++ b/fs/xfs/xfs_ondisk.h
> @@ -148,6 +148,7 @@ xfs_check_ondisk_structs(void)
>  	XFS_CHECK_OFFSET(struct xfs_attr3_leafblock, hdr.info.hdr, 0);
>  
>  	XFS_CHECK_STRUCT_SIZE(struct xfs_bulkstat,		192);
> +	XFS_CHECK_STRUCT_SIZE(struct xfs_inumbers,		24);
>  }
>  
>  #endif /* __XFS_ONDISK_H */
> 

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

* Re: [PATCH 5/9] xfs: wire up new v5 bulkstat ioctls
  2019-06-26 20:46 ` [PATCH 5/9] xfs: wire up new v5 bulkstat ioctls Darrick J. Wong
@ 2019-07-03 13:24   ` Brian Foster
  0 siblings, 0 replies; 34+ messages in thread
From: Brian Foster @ 2019-07-03 13:24 UTC (permalink / raw)
  To: Darrick J. Wong; +Cc: linux-xfs, allison.henderson

On Wed, Jun 26, 2019 at 01:46:06PM -0700, Darrick J. Wong wrote:
> From: Darrick J. Wong <darrick.wong@oracle.com>
> 
> Wire up the new v5 BULKSTAT ioctl and rename the old one to V1.
> 
> Signed-off-by: Darrick J. Wong <darrick.wong@oracle.com>
> ---

I don't see any renaming in this patch (or the subsequent that mention
it).. that aside:

Reviewed-by: Brian Foster <bfoster@redhat.com>

>  fs/xfs/libxfs/xfs_fs.h |   24 +++++++++++-
>  fs/xfs/xfs_ioctl.c     |   98 ++++++++++++++++++++++++++++++++++++++++++++++++
>  fs/xfs/xfs_ioctl32.c   |    1 
>  fs/xfs/xfs_ondisk.h    |    1 
>  4 files changed, 123 insertions(+), 1 deletion(-)
> 
> 
> diff --git a/fs/xfs/libxfs/xfs_fs.h b/fs/xfs/libxfs/xfs_fs.h
> index 8b8fe78511fb..960f3542e207 100644
> --- a/fs/xfs/libxfs/xfs_fs.h
> +++ b/fs/xfs/libxfs/xfs_fs.h
> @@ -435,7 +435,6 @@ struct xfs_fsop_bulkreq {
>  	__s32		__user *ocount;	/* output count pointer		*/
>  };
>  
> -
>  /*
>   * Structures returned from xfs_inumbers routine (XFS_IOC_FSINUMBERS).
>   */
> @@ -457,6 +456,28 @@ struct xfs_inumbers {
>  #define XFS_INUMBERS_VERSION_V1	(1)
>  #define XFS_INUMBERS_VERSION_V5	(5)
>  
> +/* Header for bulk inode requests. */
> +struct xfs_bulk_ireq {
> +	uint64_t	ino;		/* I/O: start with this inode	*/
> +	uint32_t	flags;		/* I/O: operation flags		*/
> +	uint32_t	icount;		/* I: count of entries in buffer */
> +	uint32_t	ocount;		/* O: count of entries filled out */
> +	uint32_t	reserved32;	/* must be zero			*/
> +	uint64_t	reserved[5];	/* must be zero			*/
> +};
> +
> +#define XFS_BULK_IREQ_FLAGS_ALL	(0)
> +
> +/*
> + * ioctl structures for v5 bulkstat and inumbers requests
> + */
> +struct xfs_bulkstat_req {
> +	struct xfs_bulk_ireq	hdr;
> +	struct xfs_bulkstat	bulkstat[];
> +};
> +#define XFS_BULKSTAT_REQ_SIZE(nr)	(sizeof(struct xfs_bulkstat_req) + \
> +					 (nr) * sizeof(struct xfs_bulkstat))
> +
>  /*
>   * Error injection.
>   */
> @@ -758,6 +779,7 @@ struct xfs_scrub_metadata {
>  #define XFS_IOC_FSGEOMETRY_V4	     _IOR ('X', 124, struct xfs_fsop_geom_v4)
>  #define XFS_IOC_GOINGDOWN	     _IOR ('X', 125, uint32_t)
>  #define XFS_IOC_FSGEOMETRY	     _IOR ('X', 126, struct xfs_fsop_geom)
> +#define XFS_IOC_BULKSTAT	     _IOR ('X', 127, struct xfs_bulkstat_req)
>  /*	XFS_IOC_GETFSUUID ---------- deprecated 140	 */
>  
>  
> diff --git a/fs/xfs/xfs_ioctl.c b/fs/xfs/xfs_ioctl.c
> index 47580762e154..cf6a38c2a3ed 100644
> --- a/fs/xfs/xfs_ioctl.c
> +++ b/fs/xfs/xfs_ioctl.c
> @@ -827,6 +827,101 @@ xfs_ioc_fsbulkstat(
>  	return 0;
>  }
>  
> +/* Return 0 on success or positive error */
> +static int
> +xfs_bulkstat_fmt(
> +	struct xfs_ibulk		*breq,
> +	const struct xfs_bulkstat	*bstat)
> +{
> +	if (copy_to_user(breq->ubuffer, bstat, sizeof(struct xfs_bulkstat)))
> +		return -EFAULT;
> +	return xfs_ibulk_advance(breq, sizeof(struct xfs_bulkstat));
> +}
> +
> +/*
> + * Check the incoming bulk request @hdr from userspace and initialize the
> + * internal @breq bulk request appropriately.  Returns 0 if the bulk request
> + * should proceed; XFS_ITER_ABORT if there's nothing to do; or the usual
> + * negative error code.
> + */
> +static int
> +xfs_bulk_ireq_setup(
> +	struct xfs_mount	*mp,
> +	struct xfs_bulk_ireq	*hdr,
> +	struct xfs_ibulk	*breq,
> +	void __user		*ubuffer)
> +{
> +	if (hdr->icount == 0 ||
> +	    (hdr->flags & ~XFS_BULK_IREQ_FLAGS_ALL) ||
> +	    hdr->reserved32 ||
> +	    memchr_inv(hdr->reserved, 0, sizeof(hdr->reserved)))
> +		return -EINVAL;
> +
> +	breq->startino = hdr->ino;
> +	breq->ubuffer = ubuffer;
> +	breq->icount = hdr->icount;
> +	breq->ocount = 0;
> +
> +	/* Asking for an inode past the end of the FS?  We're done! */
> +	if (XFS_INO_TO_AGNO(mp, breq->startino) >= mp->m_sb.sb_agcount)
> +		return XFS_ITER_ABORT;
> +
> +	return 0;
> +}
> +
> +/*
> + * Update the userspace bulk request @hdr to reflect the end state of the
> + * internal bulk request @breq.
> + */
> +static void
> +xfs_bulk_ireq_teardown(
> +	struct xfs_bulk_ireq	*hdr,
> +	struct xfs_ibulk	*breq)
> +{
> +	hdr->ino = breq->startino;
> +	hdr->ocount = breq->ocount;
> +}
> +
> +/* Handle the v5 bulkstat ioctl. */
> +STATIC int
> +xfs_ioc_bulkstat(
> +	struct xfs_mount		*mp,
> +	unsigned int			cmd,
> +	struct xfs_bulkstat_req __user	*arg)
> +{
> +	struct xfs_bulk_ireq		hdr;
> +	struct xfs_ibulk		breq = {
> +		.mp			= mp,
> +	};
> +	int				error;
> +
> +	if (!capable(CAP_SYS_ADMIN))
> +		return -EPERM;
> +
> +	if (XFS_FORCED_SHUTDOWN(mp))
> +		return -EIO;
> +
> +	if (copy_from_user(&hdr, &arg->hdr, sizeof(hdr)))
> +		return -EFAULT;
> +
> +	error = xfs_bulk_ireq_setup(mp, &hdr, &breq, arg->bulkstat);
> +	if (error == XFS_ITER_ABORT)
> +		goto out_teardown;
> +	if (error < 0)
> +		return error;
> +
> +	error = xfs_bulkstat(&breq, xfs_bulkstat_fmt);
> +	if (error)
> +		return error;
> +
> +out_teardown:
> +	xfs_bulk_ireq_teardown(&hdr, &breq);
> +	if (copy_to_user(&arg->hdr, &hdr, sizeof(hdr)))
> +		return -EFAULT;
> +
> +	return 0;
> +}
> +
>  STATIC int
>  xfs_ioc_fsgeometry(
>  	struct xfs_mount	*mp,
> @@ -1991,6 +2086,9 @@ xfs_file_ioctl(
>  	case XFS_IOC_FSINUMBERS:
>  		return xfs_ioc_fsbulkstat(mp, cmd, arg);
>  
> +	case XFS_IOC_BULKSTAT:
> +		return xfs_ioc_bulkstat(mp, cmd, arg);
> +
>  	case XFS_IOC_FSGEOMETRY_V1:
>  		return xfs_ioc_fsgeometry(mp, arg, 3);
>  	case XFS_IOC_FSGEOMETRY_V4:
> diff --git a/fs/xfs/xfs_ioctl32.c b/fs/xfs/xfs_ioctl32.c
> index 41485e2ed431..df107adbdbf3 100644
> --- a/fs/xfs/xfs_ioctl32.c
> +++ b/fs/xfs/xfs_ioctl32.c
> @@ -580,6 +580,7 @@ xfs_file_compat_ioctl(
>  	case XFS_IOC_ERROR_CLEARALL:
>  	case FS_IOC_GETFSMAP:
>  	case XFS_IOC_SCRUB_METADATA:
> +	case XFS_IOC_BULKSTAT:
>  		return xfs_file_ioctl(filp, cmd, p);
>  #if !defined(BROKEN_X86_ALIGNMENT) || defined(CONFIG_X86_X32)
>  	/*
> diff --git a/fs/xfs/xfs_ondisk.h b/fs/xfs/xfs_ondisk.h
> index d8f941b4d51c..954484c6eb96 100644
> --- a/fs/xfs/xfs_ondisk.h
> +++ b/fs/xfs/xfs_ondisk.h
> @@ -149,6 +149,7 @@ xfs_check_ondisk_structs(void)
>  
>  	XFS_CHECK_STRUCT_SIZE(struct xfs_bulkstat,		192);
>  	XFS_CHECK_STRUCT_SIZE(struct xfs_inumbers,		24);
> +	XFS_CHECK_STRUCT_SIZE(struct xfs_bulkstat_req,		64);
>  }
>  
>  #endif /* __XFS_ONDISK_H */
> 

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

* Re: [PATCH 6/9] xfs: wire up the new v5 bulkstat_single ioctl
  2019-06-26 20:46 ` [PATCH 6/9] xfs: wire up the new v5 bulkstat_single ioctl Darrick J. Wong
@ 2019-07-03 13:24   ` Brian Foster
  2019-07-03 14:52     ` Darrick J. Wong
  0 siblings, 1 reply; 34+ messages in thread
From: Brian Foster @ 2019-07-03 13:24 UTC (permalink / raw)
  To: Darrick J. Wong; +Cc: linux-xfs, allison.henderson

On Wed, Jun 26, 2019 at 01:46:13PM -0700, Darrick J. Wong wrote:
> From: Darrick J. Wong <darrick.wong@oracle.com>
> 
> Wire up the V5 BULKSTAT_SINGLE ioctl and rename the old one V1.
> 
> Signed-off-by: Darrick J. Wong <darrick.wong@oracle.com>
> ---
>  fs/xfs/libxfs/xfs_fs.h |   16 ++++++++++
>  fs/xfs/xfs_ioctl.c     |   79 ++++++++++++++++++++++++++++++++++++++++++++++++
>  fs/xfs/xfs_ioctl32.c   |    1 +
>  fs/xfs/xfs_ondisk.h    |    1 +
>  4 files changed, 97 insertions(+)
> 
> 
> diff --git a/fs/xfs/libxfs/xfs_fs.h b/fs/xfs/libxfs/xfs_fs.h
> index 960f3542e207..95d0411dae9b 100644
> --- a/fs/xfs/libxfs/xfs_fs.h
> +++ b/fs/xfs/libxfs/xfs_fs.h
> @@ -468,6 +468,16 @@ struct xfs_bulk_ireq {
>  
>  #define XFS_BULK_IREQ_FLAGS_ALL	(0)
>  
> +/* Header for a single inode request. */
> +struct xfs_ireq {
> +	uint64_t	ino;		/* I/O: start with this inode	*/
> +	uint32_t	flags;		/* I/O: operation flags		*/
> +	uint32_t	reserved32;	/* must be zero			*/
> +	uint64_t	reserved[2];	/* must be zero			*/
> +};
> +
> +#define XFS_IREQ_FLAGS_ALL	(0)
> +
>  /*
>   * ioctl structures for v5 bulkstat and inumbers requests
>   */
> @@ -478,6 +488,11 @@ struct xfs_bulkstat_req {
>  #define XFS_BULKSTAT_REQ_SIZE(nr)	(sizeof(struct xfs_bulkstat_req) + \
>  					 (nr) * sizeof(struct xfs_bulkstat))
>  
> +struct xfs_bulkstat_single_req {
> +	struct xfs_ireq		hdr;
> +	struct xfs_bulkstat	bulkstat;
> +};
> +

What's the reasoning for separate data structures when the single
command is basically a subset of standard bulkstat (similar to the older
interface)?

Brian

>  /*
>   * Error injection.
>   */
> @@ -780,6 +795,7 @@ struct xfs_scrub_metadata {
>  #define XFS_IOC_GOINGDOWN	     _IOR ('X', 125, uint32_t)
>  #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_BULKSTAT_SINGLE	     _IOR ('X', 128, struct xfs_bulkstat_single_req)
>  /*	XFS_IOC_GETFSUUID ---------- deprecated 140	 */
>  
>  
> diff --git a/fs/xfs/xfs_ioctl.c b/fs/xfs/xfs_ioctl.c
> index cf6a38c2a3ed..2c821fa601a4 100644
> --- a/fs/xfs/xfs_ioctl.c
> +++ b/fs/xfs/xfs_ioctl.c
> @@ -922,6 +922,83 @@ xfs_ioc_bulkstat(
>  	return 0;
>  }
>  
> +/*
> + * Check the incoming singleton request @hdr from userspace and initialize the
> + * internal @breq bulk request appropriately.  Returns 0 if the bulk request
> + * should proceed; or the usual negative error code.
> + */
> +static int
> +xfs_ireq_setup(
> +	struct xfs_mount	*mp,
> +	struct xfs_ireq		*hdr,
> +	struct xfs_ibulk	*breq,
> +	void __user		*ubuffer)
> +{
> +	if ((hdr->flags & ~XFS_IREQ_FLAGS_ALL) ||
> +	    hdr->reserved32 ||
> +	    memchr_inv(hdr->reserved, 0, sizeof(hdr->reserved)))
> +		return -EINVAL;
> +
> +	if (XFS_INO_TO_AGNO(mp, hdr->ino) >= mp->m_sb.sb_agcount)
> +		return -EINVAL;
> +
> +	breq->ubuffer = ubuffer;
> +	breq->icount = 1;
> +	breq->startino = hdr->ino;
> +	return 0;
> +}
> +
> +/*
> + * Update the userspace singleton request @hdr to reflect the end state of the
> + * internal bulk request @breq.  If @error is negative then we return just
> + * that; otherwise we copy the state so that userspace can discover what
> + * happened.
> + */
> +static void
> +xfs_ireq_teardown(
> +	struct xfs_ireq		*hdr,
> +	struct xfs_ibulk	*breq)
> +{
> +	hdr->ino = breq->startino;
> +}
> +
> +/* Handle the v5 bulkstat_single ioctl. */
> +STATIC int
> +xfs_ioc_bulkstat_single(
> +	struct xfs_mount	*mp,
> +	unsigned int		cmd,
> +	struct xfs_bulkstat_single_req __user *arg)
> +{
> +	struct xfs_ireq		hdr;
> +	struct xfs_ibulk	breq = {
> +		.mp		= mp,
> +	};
> +	int			error;
> +
> +	if (!capable(CAP_SYS_ADMIN))
> +		return -EPERM;
> +
> +	if (XFS_FORCED_SHUTDOWN(mp))
> +		return -EIO;
> +
> +	if (copy_from_user(&hdr, &arg->hdr, sizeof(hdr)))
> +		return -EFAULT;
> +
> +	error = xfs_ireq_setup(mp, &hdr, &breq, &arg->bulkstat);
> +	if (error)
> +		return error;
> +
> +	error = xfs_bulkstat_one(&breq, xfs_bulkstat_fmt);
> +	if (error)
> +		return error;
> +
> +	xfs_ireq_teardown(&hdr, &breq);
> +	if (copy_to_user(&arg->hdr, &hdr, sizeof(hdr)))
> +		return -EFAULT;
> +
> +	return 0;
> +}
> +
>  STATIC int
>  xfs_ioc_fsgeometry(
>  	struct xfs_mount	*mp,
> @@ -2088,6 +2165,8 @@ xfs_file_ioctl(
>  
>  	case XFS_IOC_BULKSTAT:
>  		return xfs_ioc_bulkstat(mp, cmd, arg);
> +	case XFS_IOC_BULKSTAT_SINGLE:
> +		return xfs_ioc_bulkstat_single(mp, cmd, arg);
>  
>  	case XFS_IOC_FSGEOMETRY_V1:
>  		return xfs_ioc_fsgeometry(mp, arg, 3);
> diff --git a/fs/xfs/xfs_ioctl32.c b/fs/xfs/xfs_ioctl32.c
> index df107adbdbf3..6fa0f41dbae5 100644
> --- a/fs/xfs/xfs_ioctl32.c
> +++ b/fs/xfs/xfs_ioctl32.c
> @@ -581,6 +581,7 @@ xfs_file_compat_ioctl(
>  	case FS_IOC_GETFSMAP:
>  	case XFS_IOC_SCRUB_METADATA:
>  	case XFS_IOC_BULKSTAT:
> +	case XFS_IOC_BULKSTAT_SINGLE:
>  		return xfs_file_ioctl(filp, cmd, p);
>  #if !defined(BROKEN_X86_ALIGNMENT) || defined(CONFIG_X86_X32)
>  	/*
> diff --git a/fs/xfs/xfs_ondisk.h b/fs/xfs/xfs_ondisk.h
> index 954484c6eb96..fa1252657b08 100644
> --- a/fs/xfs/xfs_ondisk.h
> +++ b/fs/xfs/xfs_ondisk.h
> @@ -150,6 +150,7 @@ xfs_check_ondisk_structs(void)
>  	XFS_CHECK_STRUCT_SIZE(struct xfs_bulkstat,		192);
>  	XFS_CHECK_STRUCT_SIZE(struct xfs_inumbers,		24);
>  	XFS_CHECK_STRUCT_SIZE(struct xfs_bulkstat_req,		64);
> +	XFS_CHECK_STRUCT_SIZE(struct xfs_bulkstat_single_req,	224);
>  }
>  
>  #endif /* __XFS_ONDISK_H */
> 

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

* Re: [PATCH 7/9] xfs: wire up the v5 INUMBERS ioctl
  2019-06-26 20:46 ` [PATCH 7/9] xfs: wire up the v5 INUMBERS ioctl Darrick J. Wong
@ 2019-07-03 13:24   ` Brian Foster
  0 siblings, 0 replies; 34+ messages in thread
From: Brian Foster @ 2019-07-03 13:24 UTC (permalink / raw)
  To: Darrick J. Wong; +Cc: linux-xfs, allison.henderson

On Wed, Jun 26, 2019 at 01:46:19PM -0700, Darrick J. Wong wrote:
> From: Darrick J. Wong <darrick.wong@oracle.com>
> 
> Wire up the v5 INUMBERS ioctl and rename the old one to v1.
> 
> Signed-off-by: Darrick J. Wong <darrick.wong@oracle.com>
> ---

Reviewed-by: Brian Foster <bfoster@redhat.com>

>  fs/xfs/libxfs/xfs_fs.h |    8 +++++++
>  fs/xfs/xfs_ioctl.c     |   52 ++++++++++++++++++++++++++++++++++++++++++++++++
>  fs/xfs/xfs_ioctl32.c   |    1 +
>  fs/xfs/xfs_ondisk.h    |    1 +
>  4 files changed, 62 insertions(+)
> 
> 
> diff --git a/fs/xfs/libxfs/xfs_fs.h b/fs/xfs/libxfs/xfs_fs.h
> index 95d0411dae9b..f9f35139d4b7 100644
> --- a/fs/xfs/libxfs/xfs_fs.h
> +++ b/fs/xfs/libxfs/xfs_fs.h
> @@ -493,6 +493,13 @@ struct xfs_bulkstat_single_req {
>  	struct xfs_bulkstat	bulkstat;
>  };
>  
> +struct xfs_inumbers_req {
> +	struct xfs_bulk_ireq	hdr;
> +	struct xfs_inumbers	inumbers[];
> +};
> +#define XFS_INUMBERS_REQ_SIZE(nr)	(sizeof(struct xfs_inumbers_req) + \
> +					 (nr) * sizeof(struct xfs_inumbers))
> +
>  /*
>   * Error injection.
>   */
> @@ -796,6 +803,7 @@ struct xfs_scrub_metadata {
>  #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_BULKSTAT_SINGLE	     _IOR ('X', 128, struct xfs_bulkstat_single_req)
> +#define XFS_IOC_INUMBERS	     _IOR ('X', 129, struct xfs_inumbers_req)
>  /*	XFS_IOC_GETFSUUID ---------- deprecated 140	 */
>  
>  
> diff --git a/fs/xfs/xfs_ioctl.c b/fs/xfs/xfs_ioctl.c
> index 2c821fa601a4..2ac5e100b147 100644
> --- a/fs/xfs/xfs_ioctl.c
> +++ b/fs/xfs/xfs_ioctl.c
> @@ -999,6 +999,56 @@ xfs_ioc_bulkstat_single(
>  	return 0;
>  }
>  
> +STATIC int
> +xfs_inumbers_fmt(
> +	struct xfs_ibulk		*breq,
> +	const struct xfs_inumbers	*igrp)
> +{
> +	if (copy_to_user(breq->ubuffer, igrp, sizeof(struct xfs_inumbers)))
> +		return -EFAULT;
> +	return xfs_ibulk_advance(breq, sizeof(struct xfs_inumbers));
> +}
> +
> +/* Handle the v5 inumbers ioctl. */
> +STATIC int
> +xfs_ioc_inumbers(
> +	struct xfs_mount		*mp,
> +	unsigned int			cmd,
> +	struct xfs_inumbers_req __user	*arg)
> +{
> +	struct xfs_bulk_ireq		hdr;
> +	struct xfs_ibulk		breq = {
> +		.mp			= mp,
> +	};
> +	int				error;
> +
> +	if (!capable(CAP_SYS_ADMIN))
> +		return -EPERM;
> +
> +	if (XFS_FORCED_SHUTDOWN(mp))
> +		return -EIO;
> +
> +	if (copy_from_user(&hdr, &arg->hdr, sizeof(hdr)))
> +		return -EFAULT;
> +
> +	error = xfs_bulk_ireq_setup(mp, &hdr, &breq, arg->inumbers);
> +	if (error == XFS_ITER_ABORT)
> +		goto out_teardown;
> +	if (error < 0)
> +		return error;
> +
> +	error = xfs_inumbers(&breq, xfs_inumbers_fmt);
> +	if (error)
> +		return error;
> +
> +out_teardown:
> +	xfs_bulk_ireq_teardown(&hdr, &breq);
> +	if (copy_to_user(&arg->hdr, &hdr, sizeof(hdr)))
> +		return -EFAULT;
> +
> +	return 0;
> +}
> +
>  STATIC int
>  xfs_ioc_fsgeometry(
>  	struct xfs_mount	*mp,
> @@ -2167,6 +2217,8 @@ xfs_file_ioctl(
>  		return xfs_ioc_bulkstat(mp, cmd, arg);
>  	case XFS_IOC_BULKSTAT_SINGLE:
>  		return xfs_ioc_bulkstat_single(mp, cmd, arg);
> +	case XFS_IOC_INUMBERS:
> +		return xfs_ioc_inumbers(mp, cmd, arg);
>  
>  	case XFS_IOC_FSGEOMETRY_V1:
>  		return xfs_ioc_fsgeometry(mp, arg, 3);
> diff --git a/fs/xfs/xfs_ioctl32.c b/fs/xfs/xfs_ioctl32.c
> index 6fa0f41dbae5..093d9bf4bbcf 100644
> --- a/fs/xfs/xfs_ioctl32.c
> +++ b/fs/xfs/xfs_ioctl32.c
> @@ -582,6 +582,7 @@ xfs_file_compat_ioctl(
>  	case XFS_IOC_SCRUB_METADATA:
>  	case XFS_IOC_BULKSTAT:
>  	case XFS_IOC_BULKSTAT_SINGLE:
> +	case XFS_IOC_INUMBERS:
>  		return xfs_file_ioctl(filp, cmd, p);
>  #if !defined(BROKEN_X86_ALIGNMENT) || defined(CONFIG_X86_X32)
>  	/*
> diff --git a/fs/xfs/xfs_ondisk.h b/fs/xfs/xfs_ondisk.h
> index fa1252657b08..e390e65d2438 100644
> --- a/fs/xfs/xfs_ondisk.h
> +++ b/fs/xfs/xfs_ondisk.h
> @@ -151,6 +151,7 @@ xfs_check_ondisk_structs(void)
>  	XFS_CHECK_STRUCT_SIZE(struct xfs_inumbers,		24);
>  	XFS_CHECK_STRUCT_SIZE(struct xfs_bulkstat_req,		64);
>  	XFS_CHECK_STRUCT_SIZE(struct xfs_bulkstat_single_req,	224);
> +	XFS_CHECK_STRUCT_SIZE(struct xfs_inumbers_req,		64);
>  }
>  
>  #endif /* __XFS_ONDISK_H */
> 

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

* Re: [PATCH 8/9] xfs: specify AG in bulk req
  2019-06-26 20:46 ` [PATCH 8/9] xfs: specify AG in bulk req Darrick J. Wong
@ 2019-07-03 13:25   ` Brian Foster
  0 siblings, 0 replies; 34+ messages in thread
From: Brian Foster @ 2019-07-03 13:25 UTC (permalink / raw)
  To: Darrick J. Wong; +Cc: linux-xfs, allison.henderson

On Wed, Jun 26, 2019 at 01:46:25PM -0700, Darrick J. Wong wrote:
> From: Darrick J. Wong <darrick.wong@oracle.com>
> 
> Add a new xfs_bulk_ireq flag to constrain the iteration to a single AG.
> If the passed-in startino value is zero then we start with the first
> inode in the AG that the user passes in; otherwise, we iterate only
> within the same AG as the passed-in inode.
> 
> Signed-off-by: Darrick J. Wong <darrick.wong@oracle.com>
> Reviewed-by: Allison Collins <allison.henderson@oracle.com>
> ---

Reviewed-by: Brian Foster <bfoster@redhat.com>

>  fs/xfs/libxfs/xfs_fs.h |   10 ++++++++--
>  fs/xfs/xfs_ioctl.c     |   25 ++++++++++++++++++++++++-
>  fs/xfs/xfs_itable.c    |    6 +++---
>  fs/xfs/xfs_itable.h    |    4 ++++
>  fs/xfs/xfs_iwalk.c     |   12 ++++++++++++
>  fs/xfs/xfs_iwalk.h     |   22 +++++++++++++++++-----
>  fs/xfs/xfs_qm.c        |    3 ++-
>  7 files changed, 70 insertions(+), 12 deletions(-)
> 
> 
> diff --git a/fs/xfs/libxfs/xfs_fs.h b/fs/xfs/libxfs/xfs_fs.h
> index f9f35139d4b7..77c06850ac52 100644
> --- a/fs/xfs/libxfs/xfs_fs.h
> +++ b/fs/xfs/libxfs/xfs_fs.h
> @@ -462,11 +462,17 @@ struct xfs_bulk_ireq {
>  	uint32_t	flags;		/* I/O: operation flags		*/
>  	uint32_t	icount;		/* I: count of entries in buffer */
>  	uint32_t	ocount;		/* O: count of entries filled out */
> -	uint32_t	reserved32;	/* must be zero			*/
> +	uint32_t	agno;		/* I: see comment for IREQ_AGNO	*/
>  	uint64_t	reserved[5];	/* must be zero			*/
>  };
>  
> -#define XFS_BULK_IREQ_FLAGS_ALL	(0)
> +/*
> + * Only return results from the specified @agno.  If @ino is zero, start
> + * with the first inode of @agno.
> + */
> +#define XFS_BULK_IREQ_AGNO	(1 << 0)
> +
> +#define XFS_BULK_IREQ_FLAGS_ALL	(XFS_BULK_IREQ_AGNO)
>  
>  /* Header for a single inode request. */
>  struct xfs_ireq {
> diff --git a/fs/xfs/xfs_ioctl.c b/fs/xfs/xfs_ioctl.c
> index 2ac5e100b147..f71341cd8340 100644
> --- a/fs/xfs/xfs_ioctl.c
> +++ b/fs/xfs/xfs_ioctl.c
> @@ -853,7 +853,6 @@ xfs_bulk_ireq_setup(
>  {
>  	if (hdr->icount == 0 ||
>  	    (hdr->flags & ~XFS_BULK_IREQ_FLAGS_ALL) ||
> -	    hdr->reserved32 ||
>  	    memchr_inv(hdr->reserved, 0, sizeof(hdr->reserved)))
>  		return -EINVAL;
>  
> @@ -861,6 +860,29 @@ xfs_bulk_ireq_setup(
>  	breq->ubuffer = ubuffer;
>  	breq->icount = hdr->icount;
>  	breq->ocount = 0;
> +	breq->flags = 0;
> +
> +	/*
> +	 * The IREQ_AGNO flag means that we only want results from a given AG.
> +	 * If @hdr->ino is zero, we start iterating in that AG.  If @hdr->ino is
> +	 * beyond the specified AG then we return no results.
> +	 */
> +	if (hdr->flags & XFS_BULK_IREQ_AGNO) {
> +		if (hdr->agno >= mp->m_sb.sb_agcount)
> +			return -EINVAL;
> +
> +		if (breq->startino == 0)
> +			breq->startino = XFS_AGINO_TO_INO(mp, hdr->agno, 0);
> +		else if (XFS_INO_TO_AGNO(mp, breq->startino) < hdr->agno)
> +			return -EINVAL;
> +
> +		breq->flags |= XFS_IBULK_SAME_AG;
> +
> +		/* Asking for an inode past the end of the AG?  We're done! */
> +		if (XFS_INO_TO_AGNO(mp, breq->startino) > hdr->agno)
> +			return XFS_ITER_ABORT;
> +	} else if (hdr->agno)
> +		return -EINVAL;
>  
>  	/* Asking for an inode past the end of the FS?  We're done! */
>  	if (XFS_INO_TO_AGNO(mp, breq->startino) >= mp->m_sb.sb_agcount)
> @@ -945,6 +967,7 @@ xfs_ireq_setup(
>  	breq->ubuffer = ubuffer;
>  	breq->icount = 1;
>  	breq->startino = hdr->ino;
> +	breq->flags = 0;
>  	return 0;
>  }
>  
> diff --git a/fs/xfs/xfs_itable.c b/fs/xfs/xfs_itable.c
> index 745b04f59132..f92a1508a2bd 100644
> --- a/fs/xfs/xfs_itable.c
> +++ b/fs/xfs/xfs_itable.c
> @@ -248,8 +248,8 @@ xfs_bulkstat(
>  	if (!bc.buf)
>  		return -ENOMEM;
>  
> -	error = xfs_iwalk(breq->mp, NULL, breq->startino, xfs_bulkstat_iwalk,
> -			breq->icount, &bc);
> +	error = xfs_iwalk(breq->mp, NULL, breq->startino, breq->flags,
> +			xfs_bulkstat_iwalk, breq->icount, &bc);
>  
>  	kmem_free(bc.buf);
>  
> @@ -367,7 +367,7 @@ xfs_inumbers(
>  	if (xfs_bulkstat_already_done(breq->mp, breq->startino))
>  		return 0;
>  
> -	error = xfs_inobt_walk(breq->mp, NULL, breq->startino,
> +	error = xfs_inobt_walk(breq->mp, NULL, breq->startino, breq->flags,
>  			xfs_inumbers_walk, breq->icount, &ic);
>  
>  	/*
> diff --git a/fs/xfs/xfs_itable.h b/fs/xfs/xfs_itable.h
> index fa9fb9104c7f..e90c1fc5b981 100644
> --- a/fs/xfs/xfs_itable.h
> +++ b/fs/xfs/xfs_itable.h
> @@ -12,8 +12,12 @@ struct xfs_ibulk {
>  	xfs_ino_t		startino; /* start with this inode */
>  	unsigned int		icount;   /* number of elements in ubuffer */
>  	unsigned int		ocount;   /* number of records returned */
> +	unsigned int		flags;    /* see XFS_IBULK_FLAG_* */
>  };
>  
> +/* Only iterate within the same AG as startino */
> +#define XFS_IBULK_SAME_AG	(XFS_IWALK_SAME_AG)
> +
>  /* Return value that means we want to abort the walk. */
>  #define XFS_IBULK_ABORT		(XFS_IWALK_ABORT)
>  
> diff --git a/fs/xfs/xfs_iwalk.c b/fs/xfs/xfs_iwalk.c
> index 80c139aed264..d21d9fe71f3d 100644
> --- a/fs/xfs/xfs_iwalk.c
> +++ b/fs/xfs/xfs_iwalk.c
> @@ -519,6 +519,7 @@ xfs_iwalk(
>  	struct xfs_mount	*mp,
>  	struct xfs_trans	*tp,
>  	xfs_ino_t		startino,
> +	unsigned int		flags,
>  	xfs_iwalk_fn		iwalk_fn,
>  	unsigned int		inode_records,
>  	void			*data)
> @@ -538,6 +539,7 @@ xfs_iwalk(
>  	int			error;
>  
>  	ASSERT(agno < mp->m_sb.sb_agcount);
> +	ASSERT(!(flags & ~XFS_IWALK_FLAGS_ALL));
>  
>  	error = xfs_iwalk_alloc(&iwag);
>  	if (error)
> @@ -548,6 +550,8 @@ xfs_iwalk(
>  		if (error)
>  			break;
>  		iwag.startino = XFS_AGINO_TO_INO(mp, agno + 1, 0);
> +		if (flags & XFS_INOBT_WALK_SAME_AG)
> +			break;
>  	}
>  
>  	xfs_iwalk_free(&iwag);
> @@ -586,6 +590,7 @@ int
>  xfs_iwalk_threaded(
>  	struct xfs_mount	*mp,
>  	xfs_ino_t		startino,
> +	unsigned int		flags,
>  	xfs_iwalk_fn		iwalk_fn,
>  	unsigned int		inode_records,
>  	bool			polled,
> @@ -597,6 +602,7 @@ xfs_iwalk_threaded(
>  	int			error;
>  
>  	ASSERT(agno < mp->m_sb.sb_agcount);
> +	ASSERT(!(flags & ~XFS_IWALK_FLAGS_ALL));
>  
>  	nr_threads = xfs_pwork_guess_datadev_parallelism(mp);
>  	error = xfs_pwork_init(mp, &pctl, xfs_iwalk_ag_work, "xfs_iwalk",
> @@ -618,6 +624,8 @@ xfs_iwalk_threaded(
>  		iwag->sz_recs = xfs_iwalk_prefetch(inode_records);
>  		xfs_pwork_queue(&pctl, &iwag->pwork);
>  		startino = XFS_AGINO_TO_INO(mp, agno + 1, 0);
> +		if (flags & XFS_INOBT_WALK_SAME_AG)
> +			break;
>  	}
>  
>  	if (polled)
> @@ -674,6 +682,7 @@ xfs_inobt_walk(
>  	struct xfs_mount	*mp,
>  	struct xfs_trans	*tp,
>  	xfs_ino_t		startino,
> +	unsigned int		flags,
>  	xfs_inobt_walk_fn	inobt_walk_fn,
>  	unsigned int		inobt_records,
>  	void			*data)
> @@ -691,6 +700,7 @@ xfs_inobt_walk(
>  	int			error;
>  
>  	ASSERT(agno < mp->m_sb.sb_agcount);
> +	ASSERT(!(flags & ~XFS_INOBT_WALK_FLAGS_ALL));
>  
>  	error = xfs_iwalk_alloc(&iwag);
>  	if (error)
> @@ -701,6 +711,8 @@ xfs_inobt_walk(
>  		if (error)
>  			break;
>  		iwag.startino = XFS_AGINO_TO_INO(mp, agno + 1, 0);
> +		if (flags & XFS_INOBT_WALK_SAME_AG)
> +			break;
>  	}
>  
>  	xfs_iwalk_free(&iwag);
> diff --git a/fs/xfs/xfs_iwalk.h b/fs/xfs/xfs_iwalk.h
> index 67462861680c..6c960e10ed4d 100644
> --- a/fs/xfs/xfs_iwalk.h
> +++ b/fs/xfs/xfs_iwalk.h
> @@ -14,10 +14,16 @@ typedef int (*xfs_iwalk_fn)(struct xfs_mount *mp, struct xfs_trans *tp,
>  #define XFS_IWALK_ABORT		(XFS_ITER_ABORT)
>  
>  int xfs_iwalk(struct xfs_mount *mp, struct xfs_trans *tp, xfs_ino_t startino,
> -		xfs_iwalk_fn iwalk_fn, unsigned int inode_records, void *data);
> +		unsigned int flags, xfs_iwalk_fn iwalk_fn,
> +		unsigned int inode_records, void *data);
>  int xfs_iwalk_threaded(struct xfs_mount *mp, xfs_ino_t startino,
> -		xfs_iwalk_fn iwalk_fn, unsigned int inode_records, bool poll,
> -		void *data);
> +		unsigned int flags, xfs_iwalk_fn iwalk_fn,
> +		unsigned int inode_records, bool poll, void *data);
> +
> +/* Only iterate inodes within the same AG as @startino. */
> +#define XFS_IWALK_SAME_AG	(0x1)
> +
> +#define XFS_IWALK_FLAGS_ALL	(XFS_IWALK_SAME_AG)
>  
>  /* Walk all inode btree records in the filesystem starting from @startino. */
>  typedef int (*xfs_inobt_walk_fn)(struct xfs_mount *mp, struct xfs_trans *tp,
> @@ -28,7 +34,13 @@ typedef int (*xfs_inobt_walk_fn)(struct xfs_mount *mp, struct xfs_trans *tp,
>  #define XFS_INOBT_WALK_ABORT	(XFS_IWALK_ABORT)
>  
>  int xfs_inobt_walk(struct xfs_mount *mp, struct xfs_trans *tp,
> -		xfs_ino_t startino, xfs_inobt_walk_fn inobt_walk_fn,
> -		unsigned int inobt_records, void *data);
> +		xfs_ino_t startino, unsigned int flags,
> +		xfs_inobt_walk_fn inobt_walk_fn, unsigned int inobt_records,
> +		void *data);
> +
> +/* Only iterate inobt records within the same AG as @startino. */
> +#define XFS_INOBT_WALK_SAME_AG	(XFS_IWALK_SAME_AG)
> +
> +#define XFS_INOBT_WALK_FLAGS_ALL (XFS_INOBT_WALK_SAME_AG)
>  
>  #endif /* __XFS_IWALK_H__ */
> diff --git a/fs/xfs/xfs_qm.c b/fs/xfs/xfs_qm.c
> index 8bb902125403..a526c28662ae 100644
> --- a/fs/xfs/xfs_qm.c
> +++ b/fs/xfs/xfs_qm.c
> @@ -1304,7 +1304,8 @@ xfs_qm_quotacheck(
>  		flags |= XFS_PQUOTA_CHKD;
>  	}
>  
> -	error = xfs_iwalk_threaded(mp, 0, xfs_qm_dqusage_adjust, 0, true, NULL);
> +	error = xfs_iwalk_threaded(mp, 0, 0, xfs_qm_dqusage_adjust, 0, true,
> +			NULL);
>  	if (error)
>  		goto error_return;
>  
> 

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

* Re: [PATCH 9/9] xfs: allow bulkstat_single of special inodes
  2019-06-26 20:46 ` [PATCH 9/9] xfs: allow bulkstat_single of special inodes Darrick J. Wong
@ 2019-07-03 13:25   ` Brian Foster
  2019-07-03 15:09     ` Darrick J. Wong
  2019-07-03 15:34   ` [PATCH v2 " Darrick J. Wong
  2019-07-04  6:51   ` [PATCH v3 " Darrick J. Wong
  2 siblings, 1 reply; 34+ messages in thread
From: Brian Foster @ 2019-07-03 13:25 UTC (permalink / raw)
  To: Darrick J. Wong; +Cc: linux-xfs, allison.henderson

On Wed, Jun 26, 2019 at 01:46:31PM -0700, Darrick J. Wong wrote:
> From: Darrick J. Wong <darrick.wong@oracle.com>
> 
> Create a new ireq flag (for single bulkstats) that enables userspace to
> ask us for a special inode number instead of interpreting @ino as a
> literal inode number.  This enables us to query the root inode easily.
> 

Seems reasonable, though what's the use case for this? A brief
description in the commit log would be helpful.

> Signed-off-by: Darrick J. Wong <darrick.wong@oracle.com>
> Reviewed-by: Allison Collins <allison.henderson@oracle.com>
> ---
>  fs/xfs/libxfs/xfs_fs.h |   11 ++++++++++-
>  fs/xfs/xfs_ioctl.c     |   10 ++++++++++
>  2 files changed, 20 insertions(+), 1 deletion(-)
> 
> 
> diff --git a/fs/xfs/libxfs/xfs_fs.h b/fs/xfs/libxfs/xfs_fs.h
> index 77c06850ac52..1489bce07d66 100644
> --- a/fs/xfs/libxfs/xfs_fs.h
> +++ b/fs/xfs/libxfs/xfs_fs.h
> @@ -482,7 +482,16 @@ struct xfs_ireq {
>  	uint64_t	reserved[2];	/* must be zero			*/
>  };
>  
> -#define XFS_IREQ_FLAGS_ALL	(0)
> +/*
> + * The @ino value is a special value, not a literal inode number.  See the
> + * XFS_IREQ_SPECIAL_* values below.
> + */
> +#define XFS_IREQ_SPECIAL	(1 << 0)
> +
> +#define XFS_IREQ_FLAGS_ALL	(XFS_IREQ_SPECIAL)
> +
> +/* Operate on the root directory inode. */
> +#define XFS_IREQ_SPECIAL_ROOT	(1)
>  
>  /*
>   * ioctl structures for v5 bulkstat and inumbers requests
> diff --git a/fs/xfs/xfs_ioctl.c b/fs/xfs/xfs_ioctl.c
> index f71341cd8340..3bb5f980fabf 100644
> --- a/fs/xfs/xfs_ioctl.c
> +++ b/fs/xfs/xfs_ioctl.c
> @@ -961,6 +961,16 @@ xfs_ireq_setup(
>  	    memchr_inv(hdr->reserved, 0, sizeof(hdr->reserved)))
>  		return -EINVAL;
>  
> +	if (hdr->flags & XFS_IREQ_SPECIAL) {
> +		switch (hdr->ino) {
> +		case XFS_IREQ_SPECIAL_ROOT:
> +			hdr->ino = mp->m_sb.sb_rootino;
> +			break;

Do you envision other ->ino magic values? I'm curious about the need for
the special flag along with a magic inode value as opposed to just a
"root dir" flag or some such.

Brian

> +		default:
> +			return -EINVAL;
> +		}
> +	}
> +
>  	if (XFS_INO_TO_AGNO(mp, hdr->ino) >= mp->m_sb.sb_agcount)
>  		return -EINVAL;
>  
> 

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

* Re: [PATCH 3/9] xfs: introduce new v5 bulkstat structure
  2019-07-03 13:23   ` Brian Foster
@ 2019-07-03 14:42     ` Darrick J. Wong
  0 siblings, 0 replies; 34+ messages in thread
From: Darrick J. Wong @ 2019-07-03 14:42 UTC (permalink / raw)
  To: Brian Foster; +Cc: linux-xfs, allison.henderson

On Wed, Jul 03, 2019 at 09:23:46AM -0400, Brian Foster wrote:
> On Wed, Jun 26, 2019 at 01:45:52PM -0700, Darrick J. Wong wrote:
> > From: Darrick J. Wong <darrick.wong@oracle.com>
> > 
> > Introduce a new version of the in-core bulkstat structure that supports
> > our new v5 format features.  This structure also fills the gaps in the
> > previous structure.  We leave wiring up the ioctls for the next patch.
> > 
> > Signed-off-by: Darrick J. Wong <darrick.wong@oracle.com>
> > Reviewed-by: Allison Collins <allison.henderson@oracle.com>
> > ---
> >  fs/xfs/libxfs/xfs_fs.h     |   48 ++++++++++++++++++++++++++++
> >  fs/xfs/libxfs/xfs_health.h |    2 +
> >  fs/xfs/xfs_health.c        |    2 +
> >  fs/xfs/xfs_ioctl.c         |    9 ++++-
> >  fs/xfs/xfs_ioctl.h         |    2 +
> >  fs/xfs/xfs_ioctl32.c       |   10 ++++--
> >  fs/xfs/xfs_itable.c        |   75 +++++++++++++++++++++++++++++++++-----------
> >  fs/xfs/xfs_itable.h        |    4 ++
> >  fs/xfs/xfs_ondisk.h        |    2 +
> >  9 files changed, 124 insertions(+), 30 deletions(-)
> > 
> > 
> ...
> > diff --git a/fs/xfs/xfs_itable.c b/fs/xfs/xfs_itable.c
> > index 45f0618efb8d..50c2bb8e13c4 100644
> > --- a/fs/xfs/xfs_itable.c
> > +++ b/fs/xfs/xfs_itable.c
> ...
> > @@ -266,6 +266,43 @@ xfs_bulkstat(
> >  	return error;
> >  }
> >  
> > +/* Convert bulkstat (v5) to bstat (v1). */
> > +void
> > +xfs_bulkstat_to_bstat(
> > +	struct xfs_mount		*mp,
> > +	struct xfs_bstat		*bs1,
> > +	const struct xfs_bulkstat	*bstat)
> > +{
> > +	bs1->bs_ino = bstat->bs_ino;
> > +	bs1->bs_mode = bstat->bs_mode;
> > +	bs1->bs_nlink = bstat->bs_nlink;
> > +	bs1->bs_uid = bstat->bs_uid;
> > +	bs1->bs_gid = bstat->bs_gid;
> > +	bs1->bs_rdev = bstat->bs_rdev;
> > +	bs1->bs_blksize = bstat->bs_blksize;
> > +	bs1->bs_size = bstat->bs_size;
> > +	bs1->bs_atime.tv_sec = bstat->bs_atime;
> > +	bs1->bs_mtime.tv_sec = bstat->bs_mtime;
> > +	bs1->bs_ctime.tv_sec = bstat->bs_ctime;
> > +	bs1->bs_atime.tv_nsec = bstat->bs_atime_nsec;
> > +	bs1->bs_mtime.tv_nsec = bstat->bs_mtime_nsec;
> > +	bs1->bs_ctime.tv_nsec = bstat->bs_ctime_nsec;
> > +	bs1->bs_blocks = bstat->bs_blocks;
> > +	bs1->bs_xflags = bstat->bs_xflags;
> > +	bs1->bs_extsize = bstat->bs_extsize_blks << mp->m_sb.sb_blocklog;
> > +	bs1->bs_extents = bstat->bs_extents;
> > +	bs1->bs_gen = bstat->bs_gen;
> > +	bs1->bs_projid_lo = bstat->bs_projectid & 0xFFFF;
> > +	bs1->bs_forkoff = bstat->bs_forkoff;
> > +	bs1->bs_projid_hi = bstat->bs_projectid >> 16;
> > +	bs1->bs_sick = bstat->bs_sick;
> > +	bs1->bs_checked = bstat->bs_checked;
> > +	bs1->bs_cowextsize = bstat->bs_cowextsize_blks << mp->m_sb.sb_blocklog;
> > +	bs1->bs_dmevmask = 0;
> > +	bs1->bs_dmstate = 0;
> 
> Any particular reason these fields are now stubbed out?
> Deprecated/unused? It looks like we at least still have a mechanism to
> set these values, but I have no idea if there are any users (or what
> they're for for that matter :P).

Those fields were for DMAPI hierarchal storage management, but upstream
XFS has never supported it so I didn't see much point in adding them
back.  If we do decide to support it there's plenty of space in the v5
structure.

> Also, should we zero the padding space in bs1 here? It looks like the
> callers allocate bs1 on the stack without any initialization, do the
> conversion and immediately copy to userspace.

Yes, we shouldn't be leaking unset memory contents here.  I'll change
the conversion functions to memset since the same problem happens in
userspace.

--D

> Brian
> 
> > +	bs1->bs_aextents = bstat->bs_aextents;
> > +}
> > +
> >  struct xfs_inumbers_chunk {
> >  	inumbers_fmt_pf		formatter;
> >  	struct xfs_ibulk	*breq;
> > diff --git a/fs/xfs/xfs_itable.h b/fs/xfs/xfs_itable.h
> > index cfd3c93226f3..60e259192056 100644
> > --- a/fs/xfs/xfs_itable.h
> > +++ b/fs/xfs/xfs_itable.h
> > @@ -38,10 +38,12 @@ xfs_ibulk_advance(
> >   */
> >  
> >  typedef int (*bulkstat_one_fmt_pf)(struct xfs_ibulk *breq,
> > -		const struct xfs_bstat *bstat);
> > +		const struct xfs_bulkstat *bstat);
> >  
> >  int xfs_bulkstat_one(struct xfs_ibulk *breq, bulkstat_one_fmt_pf formatter);
> >  int xfs_bulkstat(struct xfs_ibulk *breq, bulkstat_one_fmt_pf formatter);
> > +void xfs_bulkstat_to_bstat(struct xfs_mount *mp, struct xfs_bstat *bs1,
> > +		const struct xfs_bulkstat *bstat);
> >  
> >  typedef int (*inumbers_fmt_pf)(struct xfs_ibulk *breq,
> >  		const struct xfs_inogrp *igrp);
> > diff --git a/fs/xfs/xfs_ondisk.h b/fs/xfs/xfs_ondisk.h
> > index c8ba98fae30a..0b4cdda68524 100644
> > --- a/fs/xfs/xfs_ondisk.h
> > +++ b/fs/xfs/xfs_ondisk.h
> > @@ -146,6 +146,8 @@ xfs_check_ondisk_structs(void)
> >  	XFS_CHECK_OFFSET(struct xfs_dir3_data_hdr, hdr.magic,	0);
> >  	XFS_CHECK_OFFSET(struct xfs_dir3_free, hdr.hdr.magic,	0);
> >  	XFS_CHECK_OFFSET(struct xfs_attr3_leafblock, hdr.info.hdr, 0);
> > +
> > +	XFS_CHECK_STRUCT_SIZE(struct xfs_bulkstat,		192);
> >  }
> >  
> >  #endif /* __XFS_ONDISK_H */
> > 

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

* Re: [PATCH 6/9] xfs: wire up the new v5 bulkstat_single ioctl
  2019-07-03 13:24   ` Brian Foster
@ 2019-07-03 14:52     ` Darrick J. Wong
  2019-07-03 16:11       ` Brian Foster
  0 siblings, 1 reply; 34+ messages in thread
From: Darrick J. Wong @ 2019-07-03 14:52 UTC (permalink / raw)
  To: Brian Foster; +Cc: linux-xfs, allison.henderson

On Wed, Jul 03, 2019 at 09:24:41AM -0400, Brian Foster wrote:
> On Wed, Jun 26, 2019 at 01:46:13PM -0700, Darrick J. Wong wrote:
> > From: Darrick J. Wong <darrick.wong@oracle.com>
> > 
> > Wire up the V5 BULKSTAT_SINGLE ioctl and rename the old one V1.
> > 
> > Signed-off-by: Darrick J. Wong <darrick.wong@oracle.com>
> > ---
> >  fs/xfs/libxfs/xfs_fs.h |   16 ++++++++++
> >  fs/xfs/xfs_ioctl.c     |   79 ++++++++++++++++++++++++++++++++++++++++++++++++
> >  fs/xfs/xfs_ioctl32.c   |    1 +
> >  fs/xfs/xfs_ondisk.h    |    1 +
> >  4 files changed, 97 insertions(+)
> > 
> > 
> > diff --git a/fs/xfs/libxfs/xfs_fs.h b/fs/xfs/libxfs/xfs_fs.h
> > index 960f3542e207..95d0411dae9b 100644
> > --- a/fs/xfs/libxfs/xfs_fs.h
> > +++ b/fs/xfs/libxfs/xfs_fs.h
> > @@ -468,6 +468,16 @@ struct xfs_bulk_ireq {
> >  
> >  #define XFS_BULK_IREQ_FLAGS_ALL	(0)
> >  
> > +/* Header for a single inode request. */
> > +struct xfs_ireq {
> > +	uint64_t	ino;		/* I/O: start with this inode	*/
> > +	uint32_t	flags;		/* I/O: operation flags		*/
> > +	uint32_t	reserved32;	/* must be zero			*/
> > +	uint64_t	reserved[2];	/* must be zero			*/
> > +};
> > +
> > +#define XFS_IREQ_FLAGS_ALL	(0)
> > +
> >  /*
> >   * ioctl structures for v5 bulkstat and inumbers requests
> >   */
> > @@ -478,6 +488,11 @@ struct xfs_bulkstat_req {
> >  #define XFS_BULKSTAT_REQ_SIZE(nr)	(sizeof(struct xfs_bulkstat_req) + \
> >  					 (nr) * sizeof(struct xfs_bulkstat))
> >  
> > +struct xfs_bulkstat_single_req {
> > +	struct xfs_ireq		hdr;
> > +	struct xfs_bulkstat	bulkstat;
> > +};
> > +
> 
> What's the reasoning for separate data structures when the single
> command is basically a subset of standard bulkstat (similar to the older
> interface)?

I split them up to avoid having irrelevant bulk_req fields (specifically
icount and ocount) cluttering up the single_req header.  In patch 9 the
bulkstat single command grows the ability to request the root inode to
fix xfsdump's inability to correctly guess the root directory.

--D

> Brian
> 
> >  /*
> >   * Error injection.
> >   */
> > @@ -780,6 +795,7 @@ struct xfs_scrub_metadata {
> >  #define XFS_IOC_GOINGDOWN	     _IOR ('X', 125, uint32_t)
> >  #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_BULKSTAT_SINGLE	     _IOR ('X', 128, struct xfs_bulkstat_single_req)
> >  /*	XFS_IOC_GETFSUUID ---------- deprecated 140	 */
> >  
> >  
> > diff --git a/fs/xfs/xfs_ioctl.c b/fs/xfs/xfs_ioctl.c
> > index cf6a38c2a3ed..2c821fa601a4 100644
> > --- a/fs/xfs/xfs_ioctl.c
> > +++ b/fs/xfs/xfs_ioctl.c
> > @@ -922,6 +922,83 @@ xfs_ioc_bulkstat(
> >  	return 0;
> >  }
> >  
> > +/*
> > + * Check the incoming singleton request @hdr from userspace and initialize the
> > + * internal @breq bulk request appropriately.  Returns 0 if the bulk request
> > + * should proceed; or the usual negative error code.
> > + */
> > +static int
> > +xfs_ireq_setup(
> > +	struct xfs_mount	*mp,
> > +	struct xfs_ireq		*hdr,
> > +	struct xfs_ibulk	*breq,
> > +	void __user		*ubuffer)
> > +{
> > +	if ((hdr->flags & ~XFS_IREQ_FLAGS_ALL) ||
> > +	    hdr->reserved32 ||
> > +	    memchr_inv(hdr->reserved, 0, sizeof(hdr->reserved)))
> > +		return -EINVAL;
> > +
> > +	if (XFS_INO_TO_AGNO(mp, hdr->ino) >= mp->m_sb.sb_agcount)
> > +		return -EINVAL;
> > +
> > +	breq->ubuffer = ubuffer;
> > +	breq->icount = 1;
> > +	breq->startino = hdr->ino;
> > +	return 0;
> > +}
> > +
> > +/*
> > + * Update the userspace singleton request @hdr to reflect the end state of the
> > + * internal bulk request @breq.  If @error is negative then we return just
> > + * that; otherwise we copy the state so that userspace can discover what
> > + * happened.
> > + */
> > +static void
> > +xfs_ireq_teardown(
> > +	struct xfs_ireq		*hdr,
> > +	struct xfs_ibulk	*breq)
> > +{
> > +	hdr->ino = breq->startino;
> > +}
> > +
> > +/* Handle the v5 bulkstat_single ioctl. */
> > +STATIC int
> > +xfs_ioc_bulkstat_single(
> > +	struct xfs_mount	*mp,
> > +	unsigned int		cmd,
> > +	struct xfs_bulkstat_single_req __user *arg)
> > +{
> > +	struct xfs_ireq		hdr;
> > +	struct xfs_ibulk	breq = {
> > +		.mp		= mp,
> > +	};
> > +	int			error;
> > +
> > +	if (!capable(CAP_SYS_ADMIN))
> > +		return -EPERM;
> > +
> > +	if (XFS_FORCED_SHUTDOWN(mp))
> > +		return -EIO;
> > +
> > +	if (copy_from_user(&hdr, &arg->hdr, sizeof(hdr)))
> > +		return -EFAULT;
> > +
> > +	error = xfs_ireq_setup(mp, &hdr, &breq, &arg->bulkstat);
> > +	if (error)
> > +		return error;
> > +
> > +	error = xfs_bulkstat_one(&breq, xfs_bulkstat_fmt);
> > +	if (error)
> > +		return error;
> > +
> > +	xfs_ireq_teardown(&hdr, &breq);
> > +	if (copy_to_user(&arg->hdr, &hdr, sizeof(hdr)))
> > +		return -EFAULT;
> > +
> > +	return 0;
> > +}
> > +
> >  STATIC int
> >  xfs_ioc_fsgeometry(
> >  	struct xfs_mount	*mp,
> > @@ -2088,6 +2165,8 @@ xfs_file_ioctl(
> >  
> >  	case XFS_IOC_BULKSTAT:
> >  		return xfs_ioc_bulkstat(mp, cmd, arg);
> > +	case XFS_IOC_BULKSTAT_SINGLE:
> > +		return xfs_ioc_bulkstat_single(mp, cmd, arg);
> >  
> >  	case XFS_IOC_FSGEOMETRY_V1:
> >  		return xfs_ioc_fsgeometry(mp, arg, 3);
> > diff --git a/fs/xfs/xfs_ioctl32.c b/fs/xfs/xfs_ioctl32.c
> > index df107adbdbf3..6fa0f41dbae5 100644
> > --- a/fs/xfs/xfs_ioctl32.c
> > +++ b/fs/xfs/xfs_ioctl32.c
> > @@ -581,6 +581,7 @@ xfs_file_compat_ioctl(
> >  	case FS_IOC_GETFSMAP:
> >  	case XFS_IOC_SCRUB_METADATA:
> >  	case XFS_IOC_BULKSTAT:
> > +	case XFS_IOC_BULKSTAT_SINGLE:
> >  		return xfs_file_ioctl(filp, cmd, p);
> >  #if !defined(BROKEN_X86_ALIGNMENT) || defined(CONFIG_X86_X32)
> >  	/*
> > diff --git a/fs/xfs/xfs_ondisk.h b/fs/xfs/xfs_ondisk.h
> > index 954484c6eb96..fa1252657b08 100644
> > --- a/fs/xfs/xfs_ondisk.h
> > +++ b/fs/xfs/xfs_ondisk.h
> > @@ -150,6 +150,7 @@ xfs_check_ondisk_structs(void)
> >  	XFS_CHECK_STRUCT_SIZE(struct xfs_bulkstat,		192);
> >  	XFS_CHECK_STRUCT_SIZE(struct xfs_inumbers,		24);
> >  	XFS_CHECK_STRUCT_SIZE(struct xfs_bulkstat_req,		64);
> > +	XFS_CHECK_STRUCT_SIZE(struct xfs_bulkstat_single_req,	224);
> >  }
> >  
> >  #endif /* __XFS_ONDISK_H */
> > 

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

* Re: [PATCH 9/9] xfs: allow bulkstat_single of special inodes
  2019-07-03 13:25   ` Brian Foster
@ 2019-07-03 15:09     ` Darrick J. Wong
  0 siblings, 0 replies; 34+ messages in thread
From: Darrick J. Wong @ 2019-07-03 15:09 UTC (permalink / raw)
  To: Brian Foster; +Cc: linux-xfs, allison.henderson

On Wed, Jul 03, 2019 at 09:25:25AM -0400, Brian Foster wrote:
> On Wed, Jun 26, 2019 at 01:46:31PM -0700, Darrick J. Wong wrote:
> > From: Darrick J. Wong <darrick.wong@oracle.com>
> > 
> > Create a new ireq flag (for single bulkstats) that enables userspace to
> > ask us for a special inode number instead of interpreting @ino as a
> > literal inode number.  This enables us to query the root inode easily.
> > 
> 
> Seems reasonable, though what's the use case for this? A brief
> description in the commit log would be helpful.

I will add:

"The reason for adding the ability to query specifically the root
directory inode is that certain programs (xfsdump and xfsrestore) want
to confirm when they've been pointed to the root directory.  The
userspace code assumes the root directory is always the first result
from calling bulkstat with lastino == 0, but this isn't true if the
(initial btree roots + initial AGFL + inode alignment padding) is itself
long enough to be allocated to new inodes if all of those blocks should
happen to be free at the same time.  Rather than make userspace guess
at internal filesystem state, we provide a direct query."

> > Signed-off-by: Darrick J. Wong <darrick.wong@oracle.com>
> > Reviewed-by: Allison Collins <allison.henderson@oracle.com>
> > ---
> >  fs/xfs/libxfs/xfs_fs.h |   11 ++++++++++-
> >  fs/xfs/xfs_ioctl.c     |   10 ++++++++++
> >  2 files changed, 20 insertions(+), 1 deletion(-)
> > 
> > 
> > diff --git a/fs/xfs/libxfs/xfs_fs.h b/fs/xfs/libxfs/xfs_fs.h
> > index 77c06850ac52..1489bce07d66 100644
> > --- a/fs/xfs/libxfs/xfs_fs.h
> > +++ b/fs/xfs/libxfs/xfs_fs.h
> > @@ -482,7 +482,16 @@ struct xfs_ireq {
> >  	uint64_t	reserved[2];	/* must be zero			*/
> >  };
> >  
> > -#define XFS_IREQ_FLAGS_ALL	(0)
> > +/*
> > + * The @ino value is a special value, not a literal inode number.  See the
> > + * XFS_IREQ_SPECIAL_* values below.
> > + */
> > +#define XFS_IREQ_SPECIAL	(1 << 0)
> > +
> > +#define XFS_IREQ_FLAGS_ALL	(XFS_IREQ_SPECIAL)
> > +
> > +/* Operate on the root directory inode. */
> > +#define XFS_IREQ_SPECIAL_ROOT	(1)
> >  
> >  /*
> >   * ioctl structures for v5 bulkstat and inumbers requests
> > diff --git a/fs/xfs/xfs_ioctl.c b/fs/xfs/xfs_ioctl.c
> > index f71341cd8340..3bb5f980fabf 100644
> > --- a/fs/xfs/xfs_ioctl.c
> > +++ b/fs/xfs/xfs_ioctl.c
> > @@ -961,6 +961,16 @@ xfs_ireq_setup(
> >  	    memchr_inv(hdr->reserved, 0, sizeof(hdr->reserved)))
> >  		return -EINVAL;
> >  
> > +	if (hdr->flags & XFS_IREQ_SPECIAL) {
> > +		switch (hdr->ino) {
> > +		case XFS_IREQ_SPECIAL_ROOT:
> > +			hdr->ino = mp->m_sb.sb_rootino;
> > +			break;
> 
> Do you envision other ->ino magic values? I'm curious about the need for
> the special flag along with a magic inode value as opposed to just a
> "root dir" flag or some such.

I was thinking about a "return bulkstat of the fd" flag too, though I
haven't really come up with a use case for it yet.  Further on, if we
ever see Dave's subvolumes patchset again, we might want to be able to
query the ino/gen of the subvolumes root dir so that we can open a file
handle to it.

Basically the flag enables us to have 2^64 magic values instead of ~30.
We're probably never going to use that many but might as well reserve
the space for future flexibility.

--D

> Brian
> 
> > +		default:
> > +			return -EINVAL;
> > +		}
> > +	}
> > +
> >  	if (XFS_INO_TO_AGNO(mp, hdr->ino) >= mp->m_sb.sb_agcount)
> >  		return -EINVAL;
> >  
> > 

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

* [PATCH v2 3/9] xfs: introduce new v5 bulkstat structure
  2019-06-26 20:45 ` [PATCH 3/9] xfs: introduce new v5 bulkstat structure Darrick J. Wong
  2019-07-03 13:23   ` Brian Foster
@ 2019-07-03 15:32   ` Darrick J. Wong
  2019-07-03 16:31     ` Brian Foster
  1 sibling, 1 reply; 34+ messages in thread
From: Darrick J. Wong @ 2019-07-03 15:32 UTC (permalink / raw)
  To: linux-xfs, allison.henderson, Brian Foster

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

Introduce a new version of the in-core bulkstat structure that supports
our new v5 format features.  This structure also fills the gaps in the
previous structure.  We leave wiring up the ioctls for the next patch.

Signed-off-by: Darrick J. Wong <darrick.wong@oracle.com>
Reviewed-by: Allison Collins <allison.henderson@oracle.com>
---
v2: memset the v1 structure when converting from v5
---
 fs/xfs/libxfs/xfs_fs.h     |   48 +++++++++++++++++++++++++++-
 fs/xfs/libxfs/xfs_health.h |    2 +
 fs/xfs/xfs_health.c        |    2 +
 fs/xfs/xfs_ioctl.c         |    9 +++--
 fs/xfs/xfs_ioctl.h         |    2 +
 fs/xfs/xfs_ioctl32.c       |   10 ++++--
 fs/xfs/xfs_itable.c        |   76 +++++++++++++++++++++++++++++++++-----------
 fs/xfs/xfs_itable.h        |    4 ++
 fs/xfs/xfs_ondisk.h        |    2 +
 9 files changed, 125 insertions(+), 30 deletions(-)

diff --git a/fs/xfs/libxfs/xfs_fs.h b/fs/xfs/libxfs/xfs_fs.h
index ef0dce229fa4..132e364eb141 100644
--- a/fs/xfs/libxfs/xfs_fs.h
+++ b/fs/xfs/libxfs/xfs_fs.h
@@ -358,6 +358,52 @@ struct xfs_bstat {
 	__u16		bs_aextents;	/* attribute number of extents	*/
 };
 
+/* New bulkstat structure that reports v5 features and fixes padding issues */
+struct xfs_bulkstat {
+	uint64_t	bs_ino;		/* inode number			*/
+	uint64_t	bs_size;	/* file size			*/
+
+	uint64_t	bs_blocks;	/* number of blocks		*/
+	uint64_t	bs_xflags;	/* extended flags		*/
+
+	uint64_t	bs_atime;	/* access time, seconds		*/
+	uint64_t	bs_mtime;	/* modify time, seconds		*/
+
+	uint64_t	bs_ctime;	/* inode change time, seconds	*/
+	uint64_t	bs_btime;	/* creation time, seconds	*/
+
+	uint32_t	bs_gen;		/* generation count		*/
+	uint32_t	bs_uid;		/* user id			*/
+	uint32_t	bs_gid;		/* group id			*/
+	uint32_t	bs_projectid;	/* project id			*/
+
+	uint32_t	bs_atime_nsec;	/* access time, nanoseconds	*/
+	uint32_t	bs_mtime_nsec;	/* modify time, nanoseconds	*/
+	uint32_t	bs_ctime_nsec;	/* inode change time, nanoseconds */
+	uint32_t	bs_btime_nsec;	/* creation time, nanoseconds	*/
+
+	uint32_t	bs_blksize;	/* block size			*/
+	uint32_t	bs_rdev;	/* device value			*/
+	uint32_t	bs_cowextsize_blks; /* cow extent size hint, blocks */
+	uint32_t	bs_extsize_blks; /* extent size hint, blocks	*/
+
+	uint32_t	bs_nlink;	/* number of links		*/
+	uint32_t	bs_extents;	/* number of extents		*/
+	uint32_t	bs_aextents;	/* attribute number of extents	*/
+	uint16_t	bs_version;	/* structure version		*/
+	uint16_t	bs_forkoff;	/* inode fork offset in bytes	*/
+
+	uint16_t	bs_sick;	/* sick inode metadata		*/
+	uint16_t	bs_checked;	/* checked inode metadata	*/
+	uint16_t	bs_mode;	/* type and mode		*/
+	uint16_t	bs_pad2;	/* zeroed			*/
+
+	uint64_t	bs_pad[7];	/* zeroed			*/
+};
+
+#define XFS_BULKSTAT_VERSION_V1	(1)
+#define XFS_BULKSTAT_VERSION_V5	(5)
+
 /* bs_sick flags */
 #define XFS_BS_SICK_INODE	(1 << 0)  /* inode core */
 #define XFS_BS_SICK_BMBTD	(1 << 1)  /* data fork */
@@ -374,7 +420,7 @@ struct xfs_bstat {
  * to retain compatibility with "old" filesystems).
  */
 static inline uint32_t
-bstat_get_projid(struct xfs_bstat *bs)
+bstat_get_projid(const struct xfs_bstat *bs)
 {
 	return (uint32_t)bs->bs_projid_hi << 16 | bs->bs_projid_lo;
 }
diff --git a/fs/xfs/libxfs/xfs_health.h b/fs/xfs/libxfs/xfs_health.h
index 49ddfeac19f2..272005ac8c88 100644
--- a/fs/xfs/libxfs/xfs_health.h
+++ b/fs/xfs/libxfs/xfs_health.h
@@ -185,6 +185,6 @@ xfs_inode_is_healthy(struct xfs_inode *ip)
 
 void xfs_fsop_geom_health(struct xfs_mount *mp, struct xfs_fsop_geom *geo);
 void xfs_ag_geom_health(struct xfs_perag *pag, struct xfs_ag_geometry *ageo);
-void xfs_bulkstat_health(struct xfs_inode *ip, struct xfs_bstat *bs);
+void xfs_bulkstat_health(struct xfs_inode *ip, struct xfs_bulkstat *bs);
 
 #endif	/* __XFS_HEALTH_H__ */
diff --git a/fs/xfs/xfs_health.c b/fs/xfs/xfs_health.c
index ca66c314a928..8e0cb05a7142 100644
--- a/fs/xfs/xfs_health.c
+++ b/fs/xfs/xfs_health.c
@@ -369,7 +369,7 @@ static const struct ioctl_sick_map ino_map[] = {
 void
 xfs_bulkstat_health(
 	struct xfs_inode		*ip,
-	struct xfs_bstat		*bs)
+	struct xfs_bulkstat		*bs)
 {
 	const struct ioctl_sick_map	*m;
 	unsigned int			sick;
diff --git a/fs/xfs/xfs_ioctl.c b/fs/xfs/xfs_ioctl.c
index 0bfee8a05454..9f1984c31ba2 100644
--- a/fs/xfs/xfs_ioctl.c
+++ b/fs/xfs/xfs_ioctl.c
@@ -716,10 +716,13 @@ xfs_ioc_space(
 /* Return 0 on success or positive error */
 int
 xfs_fsbulkstat_one_fmt(
-	struct xfs_ibulk	*breq,
-	const struct xfs_bstat	*bstat)
+	struct xfs_ibulk		*breq,
+	const struct xfs_bulkstat	*bstat)
 {
-	if (copy_to_user(breq->ubuffer, bstat, sizeof(*bstat)))
+	struct xfs_bstat		bs1;
+
+	xfs_bulkstat_to_bstat(breq->mp, &bs1, bstat);
+	if (copy_to_user(breq->ubuffer, &bs1, sizeof(bs1)))
 		return -EFAULT;
 	return xfs_ibulk_advance(breq, sizeof(struct xfs_bstat));
 }
diff --git a/fs/xfs/xfs_ioctl.h b/fs/xfs/xfs_ioctl.h
index cb34bc821201..514d3028a134 100644
--- a/fs/xfs/xfs_ioctl.h
+++ b/fs/xfs/xfs_ioctl.h
@@ -82,7 +82,7 @@ struct xfs_bstat;
 struct xfs_inogrp;
 
 int xfs_fsbulkstat_one_fmt(struct xfs_ibulk *breq,
-			   const struct xfs_bstat *bstat);
+			   const struct xfs_bulkstat *bstat);
 int xfs_fsinumbers_fmt(struct xfs_ibulk *breq, const struct xfs_inogrp *igrp);
 
 #endif
diff --git a/fs/xfs/xfs_ioctl32.c b/fs/xfs/xfs_ioctl32.c
index 084b44a026a7..ed8e012dabbb 100644
--- a/fs/xfs/xfs_ioctl32.c
+++ b/fs/xfs/xfs_ioctl32.c
@@ -166,10 +166,14 @@ xfs_bstime_store_compat(
 /* Return 0 on success or positive error (to xfs_bulkstat()) */
 STATIC int
 xfs_fsbulkstat_one_fmt_compat(
-	struct xfs_ibulk	*breq,
-	const struct xfs_bstat	*buffer)
+	struct xfs_ibulk		*breq,
+	const struct xfs_bulkstat	*bstat)
 {
-	struct compat_xfs_bstat	__user *p32 = breq->ubuffer;
+	struct compat_xfs_bstat	__user	*p32 = breq->ubuffer;
+	struct xfs_bstat		bs1;
+	struct xfs_bstat		*buffer = &bs1;
+
+	xfs_bulkstat_to_bstat(breq->mp, &bs1, bstat);
 
 	if (put_user(buffer->bs_ino,	  &p32->bs_ino)		||
 	    put_user(buffer->bs_mode,	  &p32->bs_mode)	||
diff --git a/fs/xfs/xfs_itable.c b/fs/xfs/xfs_itable.c
index 8be4f8edbcad..5d406915144d 100644
--- a/fs/xfs/xfs_itable.c
+++ b/fs/xfs/xfs_itable.c
@@ -24,7 +24,7 @@
  * Bulk Stat
  * =========
  *
- * Use the inode walking functions to fill out struct xfs_bstat for every
+ * Use the inode walking functions to fill out struct xfs_bulkstat for every
  * allocated inode, then pass the stat information to some externally provided
  * iteration function.
  */
@@ -32,7 +32,7 @@
 struct xfs_bstat_chunk {
 	bulkstat_one_fmt_pf	formatter;
 	struct xfs_ibulk	*breq;
-	struct xfs_bstat	*buf;
+	struct xfs_bulkstat	*buf;
 };
 
 /*
@@ -61,7 +61,7 @@ xfs_bulkstat_one_int(
 	struct xfs_icdinode	*dic;		/* dinode core info pointer */
 	struct xfs_inode	*ip;		/* incore inode pointer */
 	struct inode		*inode;
-	struct xfs_bstat	*buf = bc->buf;
+	struct xfs_bulkstat	*buf = bc->buf;
 	int			error = -EINVAL;
 
 	if (xfs_internal_inum(mp, ino))
@@ -84,37 +84,35 @@ xfs_bulkstat_one_int(
 	/* xfs_iget returns the following without needing
 	 * further change.
 	 */
-	buf->bs_projid_lo = dic->di_projid_lo;
-	buf->bs_projid_hi = dic->di_projid_hi;
+	buf->bs_projectid = xfs_get_projid(ip);
 	buf->bs_ino = ino;
 	buf->bs_uid = dic->di_uid;
 	buf->bs_gid = dic->di_gid;
 	buf->bs_size = dic->di_size;
 
 	buf->bs_nlink = inode->i_nlink;
-	buf->bs_atime.tv_sec = inode->i_atime.tv_sec;
-	buf->bs_atime.tv_nsec = inode->i_atime.tv_nsec;
-	buf->bs_mtime.tv_sec = inode->i_mtime.tv_sec;
-	buf->bs_mtime.tv_nsec = inode->i_mtime.tv_nsec;
-	buf->bs_ctime.tv_sec = inode->i_ctime.tv_sec;
-	buf->bs_ctime.tv_nsec = inode->i_ctime.tv_nsec;
+	buf->bs_atime = inode->i_atime.tv_sec;
+	buf->bs_atime_nsec = inode->i_atime.tv_nsec;
+	buf->bs_mtime = inode->i_mtime.tv_sec;
+	buf->bs_mtime_nsec = inode->i_mtime.tv_nsec;
+	buf->bs_ctime = inode->i_ctime.tv_sec;
+	buf->bs_ctime_nsec = inode->i_ctime.tv_nsec;
+	buf->bs_btime = dic->di_crtime.t_sec;
+	buf->bs_btime_nsec = dic->di_crtime.t_nsec;
 	buf->bs_gen = inode->i_generation;
 	buf->bs_mode = inode->i_mode;
 
 	buf->bs_xflags = xfs_ip2xflags(ip);
-	buf->bs_extsize = dic->di_extsize << mp->m_sb.sb_blocklog;
+	buf->bs_extsize_blks = dic->di_extsize;
 	buf->bs_extents = dic->di_nextents;
-	memset(buf->bs_pad, 0, sizeof(buf->bs_pad));
 	xfs_bulkstat_health(ip, buf);
-	buf->bs_dmevmask = dic->di_dmevmask;
-	buf->bs_dmstate = dic->di_dmstate;
 	buf->bs_aextents = dic->di_anextents;
 	buf->bs_forkoff = XFS_IFORK_BOFF(ip);
+	buf->bs_version = XFS_BULKSTAT_VERSION_V5;
 
 	if (dic->di_version == 3) {
 		if (dic->di_flags2 & XFS_DIFLAG2_COWEXTSIZE)
-			buf->bs_cowextsize = dic->di_cowextsize <<
-					mp->m_sb.sb_blocklog;
+			buf->bs_cowextsize_blks = dic->di_cowextsize;
 	}
 
 	switch (dic->di_format) {
@@ -170,7 +168,8 @@ xfs_bulkstat_one(
 
 	ASSERT(breq->icount == 1);
 
-	bc.buf = kmem_zalloc(sizeof(struct xfs_bstat), KM_SLEEP | KM_MAYFAIL);
+	bc.buf = kmem_zalloc(sizeof(struct xfs_bulkstat),
+			KM_SLEEP | KM_MAYFAIL);
 	if (!bc.buf)
 		return -ENOMEM;
 
@@ -243,7 +242,8 @@ xfs_bulkstat(
 	if (xfs_bulkstat_already_done(breq->mp, breq->startino))
 		return 0;
 
-	bc.buf = kmem_zalloc(sizeof(struct xfs_bstat), KM_SLEEP | KM_MAYFAIL);
+	bc.buf = kmem_zalloc(sizeof(struct xfs_bulkstat),
+			KM_SLEEP | KM_MAYFAIL);
 	if (!bc.buf)
 		return -ENOMEM;
 
@@ -265,6 +265,44 @@ xfs_bulkstat(
 	return error;
 }
 
+/* Convert bulkstat (v5) to bstat (v1). */
+void
+xfs_bulkstat_to_bstat(
+	struct xfs_mount		*mp,
+	struct xfs_bstat		*bs1,
+	const struct xfs_bulkstat	*bstat)
+{
+	memset(bs1, 0, sizeof(struct xfs_bstat));
+	bs1->bs_ino = bstat->bs_ino;
+	bs1->bs_mode = bstat->bs_mode;
+	bs1->bs_nlink = bstat->bs_nlink;
+	bs1->bs_uid = bstat->bs_uid;
+	bs1->bs_gid = bstat->bs_gid;
+	bs1->bs_rdev = bstat->bs_rdev;
+	bs1->bs_blksize = bstat->bs_blksize;
+	bs1->bs_size = bstat->bs_size;
+	bs1->bs_atime.tv_sec = bstat->bs_atime;
+	bs1->bs_mtime.tv_sec = bstat->bs_mtime;
+	bs1->bs_ctime.tv_sec = bstat->bs_ctime;
+	bs1->bs_atime.tv_nsec = bstat->bs_atime_nsec;
+	bs1->bs_mtime.tv_nsec = bstat->bs_mtime_nsec;
+	bs1->bs_ctime.tv_nsec = bstat->bs_ctime_nsec;
+	bs1->bs_blocks = bstat->bs_blocks;
+	bs1->bs_xflags = bstat->bs_xflags;
+	bs1->bs_extsize = XFS_FSB_TO_B(mp, bstat->bs_extsize_blks);
+	bs1->bs_extents = bstat->bs_extents;
+	bs1->bs_gen = bstat->bs_gen;
+	bs1->bs_projid_lo = bstat->bs_projectid & 0xFFFF;
+	bs1->bs_forkoff = bstat->bs_forkoff;
+	bs1->bs_projid_hi = bstat->bs_projectid >> 16;
+	bs1->bs_sick = bstat->bs_sick;
+	bs1->bs_checked = bstat->bs_checked;
+	bs1->bs_cowextsize = XFS_FSB_TO_B(mp, bstat->bs_cowextsize_blks);
+	bs1->bs_dmevmask = 0;
+	bs1->bs_dmstate = 0;
+	bs1->bs_aextents = bstat->bs_aextents;
+}
+
 struct xfs_inumbers_chunk {
 	inumbers_fmt_pf		formatter;
 	struct xfs_ibulk	*breq;
diff --git a/fs/xfs/xfs_itable.h b/fs/xfs/xfs_itable.h
index cfd3c93226f3..60e259192056 100644
--- a/fs/xfs/xfs_itable.h
+++ b/fs/xfs/xfs_itable.h
@@ -38,10 +38,12 @@ xfs_ibulk_advance(
  */
 
 typedef int (*bulkstat_one_fmt_pf)(struct xfs_ibulk *breq,
-		const struct xfs_bstat *bstat);
+		const struct xfs_bulkstat *bstat);
 
 int xfs_bulkstat_one(struct xfs_ibulk *breq, bulkstat_one_fmt_pf formatter);
 int xfs_bulkstat(struct xfs_ibulk *breq, bulkstat_one_fmt_pf formatter);
+void xfs_bulkstat_to_bstat(struct xfs_mount *mp, struct xfs_bstat *bs1,
+		const struct xfs_bulkstat *bstat);
 
 typedef int (*inumbers_fmt_pf)(struct xfs_ibulk *breq,
 		const struct xfs_inogrp *igrp);
diff --git a/fs/xfs/xfs_ondisk.h b/fs/xfs/xfs_ondisk.h
index c8ba98fae30a..0b4cdda68524 100644
--- a/fs/xfs/xfs_ondisk.h
+++ b/fs/xfs/xfs_ondisk.h
@@ -146,6 +146,8 @@ xfs_check_ondisk_structs(void)
 	XFS_CHECK_OFFSET(struct xfs_dir3_data_hdr, hdr.magic,	0);
 	XFS_CHECK_OFFSET(struct xfs_dir3_free, hdr.hdr.magic,	0);
 	XFS_CHECK_OFFSET(struct xfs_attr3_leafblock, hdr.info.hdr, 0);
+
+	XFS_CHECK_STRUCT_SIZE(struct xfs_bulkstat,		192);
 }
 
 #endif /* __XFS_ONDISK_H */

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

* [PATCH v2 9/9] xfs: allow bulkstat_single of special inodes
  2019-06-26 20:46 ` [PATCH 9/9] xfs: allow bulkstat_single of special inodes Darrick J. Wong
  2019-07-03 13:25   ` Brian Foster
@ 2019-07-03 15:34   ` Darrick J. Wong
  2019-07-03 16:32     ` Brian Foster
  2019-07-04  6:51   ` [PATCH v3 " Darrick J. Wong
  2 siblings, 1 reply; 34+ messages in thread
From: Darrick J. Wong @ 2019-07-03 15:34 UTC (permalink / raw)
  To: linux-xfs, allison.henderson, Brian Foster

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

Create a new ireq flag (for single bulkstats) that enables userspace to
ask us for a special inode number instead of interpreting @ino as a
literal inode number.  This enables us to query the root inode easily.

The reason for adding the ability to query specifically the root
directory inode is that certain programs (xfsdump and xfsrestore) want
to confirm when they've been pointed to the root directory.  The
userspace code assumes the root directory is always the first result
from calling bulkstat with lastino == 0, but this isn't true if the
(initial btree roots + initial AGFL + inode alignment padding) is itself
long enough to be allocated to new inodes if all of those blocks should
happen to be free at the same time.  Rather than make userspace guess
at internal filesystem state, we provide a direct query.

Signed-off-by: Darrick J. Wong <darrick.wong@oracle.com>
Reviewed-by: Allison Collins <allison.henderson@oracle.com>
---
v2: elaborate on why we are adding this new ireq flag
---
 fs/xfs/libxfs/xfs_fs.h |   11 ++++++++++-
 fs/xfs/xfs_ioctl.c     |   10 ++++++++++
 2 files changed, 20 insertions(+), 1 deletion(-)

diff --git a/fs/xfs/libxfs/xfs_fs.h b/fs/xfs/libxfs/xfs_fs.h
index 77c06850ac52..1489bce07d66 100644
--- a/fs/xfs/libxfs/xfs_fs.h
+++ b/fs/xfs/libxfs/xfs_fs.h
@@ -482,7 +482,16 @@ struct xfs_ireq {
 	uint64_t	reserved[2];	/* must be zero			*/
 };
 
-#define XFS_IREQ_FLAGS_ALL	(0)
+/*
+ * The @ino value is a special value, not a literal inode number.  See the
+ * XFS_IREQ_SPECIAL_* values below.
+ */
+#define XFS_IREQ_SPECIAL	(1 << 0)
+
+#define XFS_IREQ_FLAGS_ALL	(XFS_IREQ_SPECIAL)
+
+/* Operate on the root directory inode. */
+#define XFS_IREQ_SPECIAL_ROOT	(1)
 
 /*
  * ioctl structures for v5 bulkstat and inumbers requests
diff --git a/fs/xfs/xfs_ioctl.c b/fs/xfs/xfs_ioctl.c
index ba9a99b7860f..11ccfc5611bf 100644
--- a/fs/xfs/xfs_ioctl.c
+++ b/fs/xfs/xfs_ioctl.c
@@ -952,6 +952,16 @@ xfs_ireq_setup(
 	    memchr_inv(hdr->reserved, 0, sizeof(hdr->reserved)))
 		return -EINVAL;
 
+	if (hdr->flags & XFS_IREQ_SPECIAL) {
+		switch (hdr->ino) {
+		case XFS_IREQ_SPECIAL_ROOT:
+			hdr->ino = mp->m_sb.sb_rootino;
+			break;
+		default:
+			return -EINVAL;
+		}
+	}
+
 	if (XFS_INO_TO_AGNO(mp, hdr->ino) >= mp->m_sb.sb_agcount)
 		return -EINVAL;
 

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

* Re: [PATCH 6/9] xfs: wire up the new v5 bulkstat_single ioctl
  2019-07-03 14:52     ` Darrick J. Wong
@ 2019-07-03 16:11       ` Brian Foster
  2019-07-03 20:01         ` Darrick J. Wong
  0 siblings, 1 reply; 34+ messages in thread
From: Brian Foster @ 2019-07-03 16:11 UTC (permalink / raw)
  To: Darrick J. Wong; +Cc: linux-xfs, allison.henderson

On Wed, Jul 03, 2019 at 07:52:56AM -0700, Darrick J. Wong wrote:
> On Wed, Jul 03, 2019 at 09:24:41AM -0400, Brian Foster wrote:
> > On Wed, Jun 26, 2019 at 01:46:13PM -0700, Darrick J. Wong wrote:
> > > From: Darrick J. Wong <darrick.wong@oracle.com>
> > > 
> > > Wire up the V5 BULKSTAT_SINGLE ioctl and rename the old one V1.
> > > 
> > > Signed-off-by: Darrick J. Wong <darrick.wong@oracle.com>
> > > ---
> > >  fs/xfs/libxfs/xfs_fs.h |   16 ++++++++++
> > >  fs/xfs/xfs_ioctl.c     |   79 ++++++++++++++++++++++++++++++++++++++++++++++++
> > >  fs/xfs/xfs_ioctl32.c   |    1 +
> > >  fs/xfs/xfs_ondisk.h    |    1 +
> > >  4 files changed, 97 insertions(+)
> > > 
> > > 
> > > diff --git a/fs/xfs/libxfs/xfs_fs.h b/fs/xfs/libxfs/xfs_fs.h
> > > index 960f3542e207..95d0411dae9b 100644
> > > --- a/fs/xfs/libxfs/xfs_fs.h
> > > +++ b/fs/xfs/libxfs/xfs_fs.h
> > > @@ -468,6 +468,16 @@ struct xfs_bulk_ireq {
> > >  
> > >  #define XFS_BULK_IREQ_FLAGS_ALL	(0)
> > >  
> > > +/* Header for a single inode request. */
> > > +struct xfs_ireq {
> > > +	uint64_t	ino;		/* I/O: start with this inode	*/
> > > +	uint32_t	flags;		/* I/O: operation flags		*/
> > > +	uint32_t	reserved32;	/* must be zero			*/
> > > +	uint64_t	reserved[2];	/* must be zero			*/
> > > +};
> > > +
> > > +#define XFS_IREQ_FLAGS_ALL	(0)
> > > +
> > >  /*
> > >   * ioctl structures for v5 bulkstat and inumbers requests
> > >   */
> > > @@ -478,6 +488,11 @@ struct xfs_bulkstat_req {
> > >  #define XFS_BULKSTAT_REQ_SIZE(nr)	(sizeof(struct xfs_bulkstat_req) + \
> > >  					 (nr) * sizeof(struct xfs_bulkstat))
> > >  
> > > +struct xfs_bulkstat_single_req {
> > > +	struct xfs_ireq		hdr;
> > > +	struct xfs_bulkstat	bulkstat;
> > > +};
> > > +
> > 
> > What's the reasoning for separate data structures when the single
> > command is basically a subset of standard bulkstat (similar to the older
> > interface)?
> 
> I split them up to avoid having irrelevant bulk_req fields (specifically
> icount and ocount) cluttering up the single_req header.  In patch 9 the
> bulkstat single command grows the ability to request the root inode to
> fix xfsdump's inability to correctly guess the root directory.
> 

Ok, figured as much once I got to the magic inode flag patch. It's
probably reasonable either way, the tradeoff to this approach is the
extra boilerplate code associated with processing the separate data
structure.

Thinking about it a bit more.. what was the purpose of the separate
BULKSTAT_SINGLE command in the first place? AFAICT it just toggles the
hacky ->lastip semantic. If we've addressed that with an entirely new
data structure, do we need the separate ioctl at all anymore?

Brian

> --D
> 
> > Brian
> > 
> > >  /*
> > >   * Error injection.
> > >   */
> > > @@ -780,6 +795,7 @@ struct xfs_scrub_metadata {
> > >  #define XFS_IOC_GOINGDOWN	     _IOR ('X', 125, uint32_t)
> > >  #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_BULKSTAT_SINGLE	     _IOR ('X', 128, struct xfs_bulkstat_single_req)
> > >  /*	XFS_IOC_GETFSUUID ---------- deprecated 140	 */
> > >  
> > >  
> > > diff --git a/fs/xfs/xfs_ioctl.c b/fs/xfs/xfs_ioctl.c
> > > index cf6a38c2a3ed..2c821fa601a4 100644
> > > --- a/fs/xfs/xfs_ioctl.c
> > > +++ b/fs/xfs/xfs_ioctl.c
> > > @@ -922,6 +922,83 @@ xfs_ioc_bulkstat(
> > >  	return 0;
> > >  }
> > >  
> > > +/*
> > > + * Check the incoming singleton request @hdr from userspace and initialize the
> > > + * internal @breq bulk request appropriately.  Returns 0 if the bulk request
> > > + * should proceed; or the usual negative error code.
> > > + */
> > > +static int
> > > +xfs_ireq_setup(
> > > +	struct xfs_mount	*mp,
> > > +	struct xfs_ireq		*hdr,
> > > +	struct xfs_ibulk	*breq,
> > > +	void __user		*ubuffer)
> > > +{
> > > +	if ((hdr->flags & ~XFS_IREQ_FLAGS_ALL) ||
> > > +	    hdr->reserved32 ||
> > > +	    memchr_inv(hdr->reserved, 0, sizeof(hdr->reserved)))
> > > +		return -EINVAL;
> > > +
> > > +	if (XFS_INO_TO_AGNO(mp, hdr->ino) >= mp->m_sb.sb_agcount)
> > > +		return -EINVAL;
> > > +
> > > +	breq->ubuffer = ubuffer;
> > > +	breq->icount = 1;
> > > +	breq->startino = hdr->ino;
> > > +	return 0;
> > > +}
> > > +
> > > +/*
> > > + * Update the userspace singleton request @hdr to reflect the end state of the
> > > + * internal bulk request @breq.  If @error is negative then we return just
> > > + * that; otherwise we copy the state so that userspace can discover what
> > > + * happened.
> > > + */
> > > +static void
> > > +xfs_ireq_teardown(
> > > +	struct xfs_ireq		*hdr,
> > > +	struct xfs_ibulk	*breq)
> > > +{
> > > +	hdr->ino = breq->startino;
> > > +}
> > > +
> > > +/* Handle the v5 bulkstat_single ioctl. */
> > > +STATIC int
> > > +xfs_ioc_bulkstat_single(
> > > +	struct xfs_mount	*mp,
> > > +	unsigned int		cmd,
> > > +	struct xfs_bulkstat_single_req __user *arg)
> > > +{
> > > +	struct xfs_ireq		hdr;
> > > +	struct xfs_ibulk	breq = {
> > > +		.mp		= mp,
> > > +	};
> > > +	int			error;
> > > +
> > > +	if (!capable(CAP_SYS_ADMIN))
> > > +		return -EPERM;
> > > +
> > > +	if (XFS_FORCED_SHUTDOWN(mp))
> > > +		return -EIO;
> > > +
> > > +	if (copy_from_user(&hdr, &arg->hdr, sizeof(hdr)))
> > > +		return -EFAULT;
> > > +
> > > +	error = xfs_ireq_setup(mp, &hdr, &breq, &arg->bulkstat);
> > > +	if (error)
> > > +		return error;
> > > +
> > > +	error = xfs_bulkstat_one(&breq, xfs_bulkstat_fmt);
> > > +	if (error)
> > > +		return error;
> > > +
> > > +	xfs_ireq_teardown(&hdr, &breq);
> > > +	if (copy_to_user(&arg->hdr, &hdr, sizeof(hdr)))
> > > +		return -EFAULT;
> > > +
> > > +	return 0;
> > > +}
> > > +
> > >  STATIC int
> > >  xfs_ioc_fsgeometry(
> > >  	struct xfs_mount	*mp,
> > > @@ -2088,6 +2165,8 @@ xfs_file_ioctl(
> > >  
> > >  	case XFS_IOC_BULKSTAT:
> > >  		return xfs_ioc_bulkstat(mp, cmd, arg);
> > > +	case XFS_IOC_BULKSTAT_SINGLE:
> > > +		return xfs_ioc_bulkstat_single(mp, cmd, arg);
> > >  
> > >  	case XFS_IOC_FSGEOMETRY_V1:
> > >  		return xfs_ioc_fsgeometry(mp, arg, 3);
> > > diff --git a/fs/xfs/xfs_ioctl32.c b/fs/xfs/xfs_ioctl32.c
> > > index df107adbdbf3..6fa0f41dbae5 100644
> > > --- a/fs/xfs/xfs_ioctl32.c
> > > +++ b/fs/xfs/xfs_ioctl32.c
> > > @@ -581,6 +581,7 @@ xfs_file_compat_ioctl(
> > >  	case FS_IOC_GETFSMAP:
> > >  	case XFS_IOC_SCRUB_METADATA:
> > >  	case XFS_IOC_BULKSTAT:
> > > +	case XFS_IOC_BULKSTAT_SINGLE:
> > >  		return xfs_file_ioctl(filp, cmd, p);
> > >  #if !defined(BROKEN_X86_ALIGNMENT) || defined(CONFIG_X86_X32)
> > >  	/*
> > > diff --git a/fs/xfs/xfs_ondisk.h b/fs/xfs/xfs_ondisk.h
> > > index 954484c6eb96..fa1252657b08 100644
> > > --- a/fs/xfs/xfs_ondisk.h
> > > +++ b/fs/xfs/xfs_ondisk.h
> > > @@ -150,6 +150,7 @@ xfs_check_ondisk_structs(void)
> > >  	XFS_CHECK_STRUCT_SIZE(struct xfs_bulkstat,		192);
> > >  	XFS_CHECK_STRUCT_SIZE(struct xfs_inumbers,		24);
> > >  	XFS_CHECK_STRUCT_SIZE(struct xfs_bulkstat_req,		64);
> > > +	XFS_CHECK_STRUCT_SIZE(struct xfs_bulkstat_single_req,	224);
> > >  }
> > >  
> > >  #endif /* __XFS_ONDISK_H */
> > > 

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

* Re: [PATCH v2 3/9] xfs: introduce new v5 bulkstat structure
  2019-07-03 15:32   ` [PATCH v2 " Darrick J. Wong
@ 2019-07-03 16:31     ` Brian Foster
  0 siblings, 0 replies; 34+ messages in thread
From: Brian Foster @ 2019-07-03 16:31 UTC (permalink / raw)
  To: Darrick J. Wong; +Cc: linux-xfs, allison.henderson

On Wed, Jul 03, 2019 at 08:32:46AM -0700, Darrick J. Wong wrote:
> From: Darrick J. Wong <darrick.wong@oracle.com>
> 
> Introduce a new version of the in-core bulkstat structure that supports
> our new v5 format features.  This structure also fills the gaps in the
> previous structure.  We leave wiring up the ioctls for the next patch.
> 
> Signed-off-by: Darrick J. Wong <darrick.wong@oracle.com>
> Reviewed-by: Allison Collins <allison.henderson@oracle.com>
> ---
> v2: memset the v1 structure when converting from v5
> ---

Reviewed-by: Brian Foster <bfoster@redhat.com>

>  fs/xfs/libxfs/xfs_fs.h     |   48 +++++++++++++++++++++++++++-
>  fs/xfs/libxfs/xfs_health.h |    2 +
>  fs/xfs/xfs_health.c        |    2 +
>  fs/xfs/xfs_ioctl.c         |    9 +++--
>  fs/xfs/xfs_ioctl.h         |    2 +
>  fs/xfs/xfs_ioctl32.c       |   10 ++++--
>  fs/xfs/xfs_itable.c        |   76 +++++++++++++++++++++++++++++++++-----------
>  fs/xfs/xfs_itable.h        |    4 ++
>  fs/xfs/xfs_ondisk.h        |    2 +
>  9 files changed, 125 insertions(+), 30 deletions(-)
> 
> diff --git a/fs/xfs/libxfs/xfs_fs.h b/fs/xfs/libxfs/xfs_fs.h
> index ef0dce229fa4..132e364eb141 100644
> --- a/fs/xfs/libxfs/xfs_fs.h
> +++ b/fs/xfs/libxfs/xfs_fs.h
> @@ -358,6 +358,52 @@ struct xfs_bstat {
>  	__u16		bs_aextents;	/* attribute number of extents	*/
>  };
>  
> +/* New bulkstat structure that reports v5 features and fixes padding issues */
> +struct xfs_bulkstat {
> +	uint64_t	bs_ino;		/* inode number			*/
> +	uint64_t	bs_size;	/* file size			*/
> +
> +	uint64_t	bs_blocks;	/* number of blocks		*/
> +	uint64_t	bs_xflags;	/* extended flags		*/
> +
> +	uint64_t	bs_atime;	/* access time, seconds		*/
> +	uint64_t	bs_mtime;	/* modify time, seconds		*/
> +
> +	uint64_t	bs_ctime;	/* inode change time, seconds	*/
> +	uint64_t	bs_btime;	/* creation time, seconds	*/
> +
> +	uint32_t	bs_gen;		/* generation count		*/
> +	uint32_t	bs_uid;		/* user id			*/
> +	uint32_t	bs_gid;		/* group id			*/
> +	uint32_t	bs_projectid;	/* project id			*/
> +
> +	uint32_t	bs_atime_nsec;	/* access time, nanoseconds	*/
> +	uint32_t	bs_mtime_nsec;	/* modify time, nanoseconds	*/
> +	uint32_t	bs_ctime_nsec;	/* inode change time, nanoseconds */
> +	uint32_t	bs_btime_nsec;	/* creation time, nanoseconds	*/
> +
> +	uint32_t	bs_blksize;	/* block size			*/
> +	uint32_t	bs_rdev;	/* device value			*/
> +	uint32_t	bs_cowextsize_blks; /* cow extent size hint, blocks */
> +	uint32_t	bs_extsize_blks; /* extent size hint, blocks	*/
> +
> +	uint32_t	bs_nlink;	/* number of links		*/
> +	uint32_t	bs_extents;	/* number of extents		*/
> +	uint32_t	bs_aextents;	/* attribute number of extents	*/
> +	uint16_t	bs_version;	/* structure version		*/
> +	uint16_t	bs_forkoff;	/* inode fork offset in bytes	*/
> +
> +	uint16_t	bs_sick;	/* sick inode metadata		*/
> +	uint16_t	bs_checked;	/* checked inode metadata	*/
> +	uint16_t	bs_mode;	/* type and mode		*/
> +	uint16_t	bs_pad2;	/* zeroed			*/
> +
> +	uint64_t	bs_pad[7];	/* zeroed			*/
> +};
> +
> +#define XFS_BULKSTAT_VERSION_V1	(1)
> +#define XFS_BULKSTAT_VERSION_V5	(5)
> +
>  /* bs_sick flags */
>  #define XFS_BS_SICK_INODE	(1 << 0)  /* inode core */
>  #define XFS_BS_SICK_BMBTD	(1 << 1)  /* data fork */
> @@ -374,7 +420,7 @@ struct xfs_bstat {
>   * to retain compatibility with "old" filesystems).
>   */
>  static inline uint32_t
> -bstat_get_projid(struct xfs_bstat *bs)
> +bstat_get_projid(const struct xfs_bstat *bs)
>  {
>  	return (uint32_t)bs->bs_projid_hi << 16 | bs->bs_projid_lo;
>  }
> diff --git a/fs/xfs/libxfs/xfs_health.h b/fs/xfs/libxfs/xfs_health.h
> index 49ddfeac19f2..272005ac8c88 100644
> --- a/fs/xfs/libxfs/xfs_health.h
> +++ b/fs/xfs/libxfs/xfs_health.h
> @@ -185,6 +185,6 @@ xfs_inode_is_healthy(struct xfs_inode *ip)
>  
>  void xfs_fsop_geom_health(struct xfs_mount *mp, struct xfs_fsop_geom *geo);
>  void xfs_ag_geom_health(struct xfs_perag *pag, struct xfs_ag_geometry *ageo);
> -void xfs_bulkstat_health(struct xfs_inode *ip, struct xfs_bstat *bs);
> +void xfs_bulkstat_health(struct xfs_inode *ip, struct xfs_bulkstat *bs);
>  
>  #endif	/* __XFS_HEALTH_H__ */
> diff --git a/fs/xfs/xfs_health.c b/fs/xfs/xfs_health.c
> index ca66c314a928..8e0cb05a7142 100644
> --- a/fs/xfs/xfs_health.c
> +++ b/fs/xfs/xfs_health.c
> @@ -369,7 +369,7 @@ static const struct ioctl_sick_map ino_map[] = {
>  void
>  xfs_bulkstat_health(
>  	struct xfs_inode		*ip,
> -	struct xfs_bstat		*bs)
> +	struct xfs_bulkstat		*bs)
>  {
>  	const struct ioctl_sick_map	*m;
>  	unsigned int			sick;
> diff --git a/fs/xfs/xfs_ioctl.c b/fs/xfs/xfs_ioctl.c
> index 0bfee8a05454..9f1984c31ba2 100644
> --- a/fs/xfs/xfs_ioctl.c
> +++ b/fs/xfs/xfs_ioctl.c
> @@ -716,10 +716,13 @@ xfs_ioc_space(
>  /* Return 0 on success or positive error */
>  int
>  xfs_fsbulkstat_one_fmt(
> -	struct xfs_ibulk	*breq,
> -	const struct xfs_bstat	*bstat)
> +	struct xfs_ibulk		*breq,
> +	const struct xfs_bulkstat	*bstat)
>  {
> -	if (copy_to_user(breq->ubuffer, bstat, sizeof(*bstat)))
> +	struct xfs_bstat		bs1;
> +
> +	xfs_bulkstat_to_bstat(breq->mp, &bs1, bstat);
> +	if (copy_to_user(breq->ubuffer, &bs1, sizeof(bs1)))
>  		return -EFAULT;
>  	return xfs_ibulk_advance(breq, sizeof(struct xfs_bstat));
>  }
> diff --git a/fs/xfs/xfs_ioctl.h b/fs/xfs/xfs_ioctl.h
> index cb34bc821201..514d3028a134 100644
> --- a/fs/xfs/xfs_ioctl.h
> +++ b/fs/xfs/xfs_ioctl.h
> @@ -82,7 +82,7 @@ struct xfs_bstat;
>  struct xfs_inogrp;
>  
>  int xfs_fsbulkstat_one_fmt(struct xfs_ibulk *breq,
> -			   const struct xfs_bstat *bstat);
> +			   const struct xfs_bulkstat *bstat);
>  int xfs_fsinumbers_fmt(struct xfs_ibulk *breq, const struct xfs_inogrp *igrp);
>  
>  #endif
> diff --git a/fs/xfs/xfs_ioctl32.c b/fs/xfs/xfs_ioctl32.c
> index 084b44a026a7..ed8e012dabbb 100644
> --- a/fs/xfs/xfs_ioctl32.c
> +++ b/fs/xfs/xfs_ioctl32.c
> @@ -166,10 +166,14 @@ xfs_bstime_store_compat(
>  /* Return 0 on success or positive error (to xfs_bulkstat()) */
>  STATIC int
>  xfs_fsbulkstat_one_fmt_compat(
> -	struct xfs_ibulk	*breq,
> -	const struct xfs_bstat	*buffer)
> +	struct xfs_ibulk		*breq,
> +	const struct xfs_bulkstat	*bstat)
>  {
> -	struct compat_xfs_bstat	__user *p32 = breq->ubuffer;
> +	struct compat_xfs_bstat	__user	*p32 = breq->ubuffer;
> +	struct xfs_bstat		bs1;
> +	struct xfs_bstat		*buffer = &bs1;
> +
> +	xfs_bulkstat_to_bstat(breq->mp, &bs1, bstat);
>  
>  	if (put_user(buffer->bs_ino,	  &p32->bs_ino)		||
>  	    put_user(buffer->bs_mode,	  &p32->bs_mode)	||
> diff --git a/fs/xfs/xfs_itable.c b/fs/xfs/xfs_itable.c
> index 8be4f8edbcad..5d406915144d 100644
> --- a/fs/xfs/xfs_itable.c
> +++ b/fs/xfs/xfs_itable.c
> @@ -24,7 +24,7 @@
>   * Bulk Stat
>   * =========
>   *
> - * Use the inode walking functions to fill out struct xfs_bstat for every
> + * Use the inode walking functions to fill out struct xfs_bulkstat for every
>   * allocated inode, then pass the stat information to some externally provided
>   * iteration function.
>   */
> @@ -32,7 +32,7 @@
>  struct xfs_bstat_chunk {
>  	bulkstat_one_fmt_pf	formatter;
>  	struct xfs_ibulk	*breq;
> -	struct xfs_bstat	*buf;
> +	struct xfs_bulkstat	*buf;
>  };
>  
>  /*
> @@ -61,7 +61,7 @@ xfs_bulkstat_one_int(
>  	struct xfs_icdinode	*dic;		/* dinode core info pointer */
>  	struct xfs_inode	*ip;		/* incore inode pointer */
>  	struct inode		*inode;
> -	struct xfs_bstat	*buf = bc->buf;
> +	struct xfs_bulkstat	*buf = bc->buf;
>  	int			error = -EINVAL;
>  
>  	if (xfs_internal_inum(mp, ino))
> @@ -84,37 +84,35 @@ xfs_bulkstat_one_int(
>  	/* xfs_iget returns the following without needing
>  	 * further change.
>  	 */
> -	buf->bs_projid_lo = dic->di_projid_lo;
> -	buf->bs_projid_hi = dic->di_projid_hi;
> +	buf->bs_projectid = xfs_get_projid(ip);
>  	buf->bs_ino = ino;
>  	buf->bs_uid = dic->di_uid;
>  	buf->bs_gid = dic->di_gid;
>  	buf->bs_size = dic->di_size;
>  
>  	buf->bs_nlink = inode->i_nlink;
> -	buf->bs_atime.tv_sec = inode->i_atime.tv_sec;
> -	buf->bs_atime.tv_nsec = inode->i_atime.tv_nsec;
> -	buf->bs_mtime.tv_sec = inode->i_mtime.tv_sec;
> -	buf->bs_mtime.tv_nsec = inode->i_mtime.tv_nsec;
> -	buf->bs_ctime.tv_sec = inode->i_ctime.tv_sec;
> -	buf->bs_ctime.tv_nsec = inode->i_ctime.tv_nsec;
> +	buf->bs_atime = inode->i_atime.tv_sec;
> +	buf->bs_atime_nsec = inode->i_atime.tv_nsec;
> +	buf->bs_mtime = inode->i_mtime.tv_sec;
> +	buf->bs_mtime_nsec = inode->i_mtime.tv_nsec;
> +	buf->bs_ctime = inode->i_ctime.tv_sec;
> +	buf->bs_ctime_nsec = inode->i_ctime.tv_nsec;
> +	buf->bs_btime = dic->di_crtime.t_sec;
> +	buf->bs_btime_nsec = dic->di_crtime.t_nsec;
>  	buf->bs_gen = inode->i_generation;
>  	buf->bs_mode = inode->i_mode;
>  
>  	buf->bs_xflags = xfs_ip2xflags(ip);
> -	buf->bs_extsize = dic->di_extsize << mp->m_sb.sb_blocklog;
> +	buf->bs_extsize_blks = dic->di_extsize;
>  	buf->bs_extents = dic->di_nextents;
> -	memset(buf->bs_pad, 0, sizeof(buf->bs_pad));
>  	xfs_bulkstat_health(ip, buf);
> -	buf->bs_dmevmask = dic->di_dmevmask;
> -	buf->bs_dmstate = dic->di_dmstate;
>  	buf->bs_aextents = dic->di_anextents;
>  	buf->bs_forkoff = XFS_IFORK_BOFF(ip);
> +	buf->bs_version = XFS_BULKSTAT_VERSION_V5;
>  
>  	if (dic->di_version == 3) {
>  		if (dic->di_flags2 & XFS_DIFLAG2_COWEXTSIZE)
> -			buf->bs_cowextsize = dic->di_cowextsize <<
> -					mp->m_sb.sb_blocklog;
> +			buf->bs_cowextsize_blks = dic->di_cowextsize;
>  	}
>  
>  	switch (dic->di_format) {
> @@ -170,7 +168,8 @@ xfs_bulkstat_one(
>  
>  	ASSERT(breq->icount == 1);
>  
> -	bc.buf = kmem_zalloc(sizeof(struct xfs_bstat), KM_SLEEP | KM_MAYFAIL);
> +	bc.buf = kmem_zalloc(sizeof(struct xfs_bulkstat),
> +			KM_SLEEP | KM_MAYFAIL);
>  	if (!bc.buf)
>  		return -ENOMEM;
>  
> @@ -243,7 +242,8 @@ xfs_bulkstat(
>  	if (xfs_bulkstat_already_done(breq->mp, breq->startino))
>  		return 0;
>  
> -	bc.buf = kmem_zalloc(sizeof(struct xfs_bstat), KM_SLEEP | KM_MAYFAIL);
> +	bc.buf = kmem_zalloc(sizeof(struct xfs_bulkstat),
> +			KM_SLEEP | KM_MAYFAIL);
>  	if (!bc.buf)
>  		return -ENOMEM;
>  
> @@ -265,6 +265,44 @@ xfs_bulkstat(
>  	return error;
>  }
>  
> +/* Convert bulkstat (v5) to bstat (v1). */
> +void
> +xfs_bulkstat_to_bstat(
> +	struct xfs_mount		*mp,
> +	struct xfs_bstat		*bs1,
> +	const struct xfs_bulkstat	*bstat)
> +{
> +	memset(bs1, 0, sizeof(struct xfs_bstat));
> +	bs1->bs_ino = bstat->bs_ino;
> +	bs1->bs_mode = bstat->bs_mode;
> +	bs1->bs_nlink = bstat->bs_nlink;
> +	bs1->bs_uid = bstat->bs_uid;
> +	bs1->bs_gid = bstat->bs_gid;
> +	bs1->bs_rdev = bstat->bs_rdev;
> +	bs1->bs_blksize = bstat->bs_blksize;
> +	bs1->bs_size = bstat->bs_size;
> +	bs1->bs_atime.tv_sec = bstat->bs_atime;
> +	bs1->bs_mtime.tv_sec = bstat->bs_mtime;
> +	bs1->bs_ctime.tv_sec = bstat->bs_ctime;
> +	bs1->bs_atime.tv_nsec = bstat->bs_atime_nsec;
> +	bs1->bs_mtime.tv_nsec = bstat->bs_mtime_nsec;
> +	bs1->bs_ctime.tv_nsec = bstat->bs_ctime_nsec;
> +	bs1->bs_blocks = bstat->bs_blocks;
> +	bs1->bs_xflags = bstat->bs_xflags;
> +	bs1->bs_extsize = XFS_FSB_TO_B(mp, bstat->bs_extsize_blks);
> +	bs1->bs_extents = bstat->bs_extents;
> +	bs1->bs_gen = bstat->bs_gen;
> +	bs1->bs_projid_lo = bstat->bs_projectid & 0xFFFF;
> +	bs1->bs_forkoff = bstat->bs_forkoff;
> +	bs1->bs_projid_hi = bstat->bs_projectid >> 16;
> +	bs1->bs_sick = bstat->bs_sick;
> +	bs1->bs_checked = bstat->bs_checked;
> +	bs1->bs_cowextsize = XFS_FSB_TO_B(mp, bstat->bs_cowextsize_blks);
> +	bs1->bs_dmevmask = 0;
> +	bs1->bs_dmstate = 0;
> +	bs1->bs_aextents = bstat->bs_aextents;
> +}
> +
>  struct xfs_inumbers_chunk {
>  	inumbers_fmt_pf		formatter;
>  	struct xfs_ibulk	*breq;
> diff --git a/fs/xfs/xfs_itable.h b/fs/xfs/xfs_itable.h
> index cfd3c93226f3..60e259192056 100644
> --- a/fs/xfs/xfs_itable.h
> +++ b/fs/xfs/xfs_itable.h
> @@ -38,10 +38,12 @@ xfs_ibulk_advance(
>   */
>  
>  typedef int (*bulkstat_one_fmt_pf)(struct xfs_ibulk *breq,
> -		const struct xfs_bstat *bstat);
> +		const struct xfs_bulkstat *bstat);
>  
>  int xfs_bulkstat_one(struct xfs_ibulk *breq, bulkstat_one_fmt_pf formatter);
>  int xfs_bulkstat(struct xfs_ibulk *breq, bulkstat_one_fmt_pf formatter);
> +void xfs_bulkstat_to_bstat(struct xfs_mount *mp, struct xfs_bstat *bs1,
> +		const struct xfs_bulkstat *bstat);
>  
>  typedef int (*inumbers_fmt_pf)(struct xfs_ibulk *breq,
>  		const struct xfs_inogrp *igrp);
> diff --git a/fs/xfs/xfs_ondisk.h b/fs/xfs/xfs_ondisk.h
> index c8ba98fae30a..0b4cdda68524 100644
> --- a/fs/xfs/xfs_ondisk.h
> +++ b/fs/xfs/xfs_ondisk.h
> @@ -146,6 +146,8 @@ xfs_check_ondisk_structs(void)
>  	XFS_CHECK_OFFSET(struct xfs_dir3_data_hdr, hdr.magic,	0);
>  	XFS_CHECK_OFFSET(struct xfs_dir3_free, hdr.hdr.magic,	0);
>  	XFS_CHECK_OFFSET(struct xfs_attr3_leafblock, hdr.info.hdr, 0);
> +
> +	XFS_CHECK_STRUCT_SIZE(struct xfs_bulkstat,		192);
>  }
>  
>  #endif /* __XFS_ONDISK_H */

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

* Re: [PATCH v2 9/9] xfs: allow bulkstat_single of special inodes
  2019-07-03 15:34   ` [PATCH v2 " Darrick J. Wong
@ 2019-07-03 16:32     ` Brian Foster
  0 siblings, 0 replies; 34+ messages in thread
From: Brian Foster @ 2019-07-03 16:32 UTC (permalink / raw)
  To: Darrick J. Wong; +Cc: linux-xfs, allison.henderson

On Wed, Jul 03, 2019 at 08:34:54AM -0700, Darrick J. Wong wrote:
> From: Darrick J. Wong <darrick.wong@oracle.com>
> 
> Create a new ireq flag (for single bulkstats) that enables userspace to
> ask us for a special inode number instead of interpreting @ino as a
> literal inode number.  This enables us to query the root inode easily.
> 
> The reason for adding the ability to query specifically the root
> directory inode is that certain programs (xfsdump and xfsrestore) want
> to confirm when they've been pointed to the root directory.  The
> userspace code assumes the root directory is always the first result
> from calling bulkstat with lastino == 0, but this isn't true if the
> (initial btree roots + initial AGFL + inode alignment padding) is itself
> long enough to be allocated to new inodes if all of those blocks should
> happen to be free at the same time.  Rather than make userspace guess
> at internal filesystem state, we provide a direct query.
> 
> Signed-off-by: Darrick J. Wong <darrick.wong@oracle.com>
> Reviewed-by: Allison Collins <allison.henderson@oracle.com>
> ---
> v2: elaborate on why we are adding this new ireq flag
> ---

Reviewed-by: Brian Foster <bfoster@redhat.com>

>  fs/xfs/libxfs/xfs_fs.h |   11 ++++++++++-
>  fs/xfs/xfs_ioctl.c     |   10 ++++++++++
>  2 files changed, 20 insertions(+), 1 deletion(-)
> 
> diff --git a/fs/xfs/libxfs/xfs_fs.h b/fs/xfs/libxfs/xfs_fs.h
> index 77c06850ac52..1489bce07d66 100644
> --- a/fs/xfs/libxfs/xfs_fs.h
> +++ b/fs/xfs/libxfs/xfs_fs.h
> @@ -482,7 +482,16 @@ struct xfs_ireq {
>  	uint64_t	reserved[2];	/* must be zero			*/
>  };
>  
> -#define XFS_IREQ_FLAGS_ALL	(0)
> +/*
> + * The @ino value is a special value, not a literal inode number.  See the
> + * XFS_IREQ_SPECIAL_* values below.
> + */
> +#define XFS_IREQ_SPECIAL	(1 << 0)
> +
> +#define XFS_IREQ_FLAGS_ALL	(XFS_IREQ_SPECIAL)
> +
> +/* Operate on the root directory inode. */
> +#define XFS_IREQ_SPECIAL_ROOT	(1)
>  
>  /*
>   * ioctl structures for v5 bulkstat and inumbers requests
> diff --git a/fs/xfs/xfs_ioctl.c b/fs/xfs/xfs_ioctl.c
> index ba9a99b7860f..11ccfc5611bf 100644
> --- a/fs/xfs/xfs_ioctl.c
> +++ b/fs/xfs/xfs_ioctl.c
> @@ -952,6 +952,16 @@ xfs_ireq_setup(
>  	    memchr_inv(hdr->reserved, 0, sizeof(hdr->reserved)))
>  		return -EINVAL;
>  
> +	if (hdr->flags & XFS_IREQ_SPECIAL) {
> +		switch (hdr->ino) {
> +		case XFS_IREQ_SPECIAL_ROOT:
> +			hdr->ino = mp->m_sb.sb_rootino;
> +			break;
> +		default:
> +			return -EINVAL;
> +		}
> +	}
> +
>  	if (XFS_INO_TO_AGNO(mp, hdr->ino) >= mp->m_sb.sb_agcount)
>  		return -EINVAL;
>  

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

* Re: [PATCH 6/9] xfs: wire up the new v5 bulkstat_single ioctl
  2019-07-03 16:11       ` Brian Foster
@ 2019-07-03 20:01         ` Darrick J. Wong
  2019-07-05 11:05           ` Brian Foster
  0 siblings, 1 reply; 34+ messages in thread
From: Darrick J. Wong @ 2019-07-03 20:01 UTC (permalink / raw)
  To: Brian Foster; +Cc: linux-xfs, allison.henderson

On Wed, Jul 03, 2019 at 12:11:36PM -0400, Brian Foster wrote:
> On Wed, Jul 03, 2019 at 07:52:56AM -0700, Darrick J. Wong wrote:
> > On Wed, Jul 03, 2019 at 09:24:41AM -0400, Brian Foster wrote:
> > > On Wed, Jun 26, 2019 at 01:46:13PM -0700, Darrick J. Wong wrote:
> > > > From: Darrick J. Wong <darrick.wong@oracle.com>
> > > > 
> > > > Wire up the V5 BULKSTAT_SINGLE ioctl and rename the old one V1.
> > > > 
> > > > Signed-off-by: Darrick J. Wong <darrick.wong@oracle.com>
> > > > ---
> > > >  fs/xfs/libxfs/xfs_fs.h |   16 ++++++++++
> > > >  fs/xfs/xfs_ioctl.c     |   79 ++++++++++++++++++++++++++++++++++++++++++++++++
> > > >  fs/xfs/xfs_ioctl32.c   |    1 +
> > > >  fs/xfs/xfs_ondisk.h    |    1 +
> > > >  4 files changed, 97 insertions(+)
> > > > 
> > > > 
> > > > diff --git a/fs/xfs/libxfs/xfs_fs.h b/fs/xfs/libxfs/xfs_fs.h
> > > > index 960f3542e207..95d0411dae9b 100644
> > > > --- a/fs/xfs/libxfs/xfs_fs.h
> > > > +++ b/fs/xfs/libxfs/xfs_fs.h
> > > > @@ -468,6 +468,16 @@ struct xfs_bulk_ireq {
> > > >  
> > > >  #define XFS_BULK_IREQ_FLAGS_ALL	(0)
> > > >  
> > > > +/* Header for a single inode request. */
> > > > +struct xfs_ireq {
> > > > +	uint64_t	ino;		/* I/O: start with this inode	*/
> > > > +	uint32_t	flags;		/* I/O: operation flags		*/
> > > > +	uint32_t	reserved32;	/* must be zero			*/
> > > > +	uint64_t	reserved[2];	/* must be zero			*/
> > > > +};
> > > > +
> > > > +#define XFS_IREQ_FLAGS_ALL	(0)
> > > > +
> > > >  /*
> > > >   * ioctl structures for v5 bulkstat and inumbers requests
> > > >   */
> > > > @@ -478,6 +488,11 @@ struct xfs_bulkstat_req {
> > > >  #define XFS_BULKSTAT_REQ_SIZE(nr)	(sizeof(struct xfs_bulkstat_req) + \
> > > >  					 (nr) * sizeof(struct xfs_bulkstat))
> > > >  
> > > > +struct xfs_bulkstat_single_req {
> > > > +	struct xfs_ireq		hdr;
> > > > +	struct xfs_bulkstat	bulkstat;
> > > > +};
> > > > +
> > > 
> > > What's the reasoning for separate data structures when the single
> > > command is basically a subset of standard bulkstat (similar to the older
> > > interface)?
> > 
> > I split them up to avoid having irrelevant bulk_req fields (specifically
> > icount and ocount) cluttering up the single_req header.  In patch 9 the
> > bulkstat single command grows the ability to request the root inode to
> > fix xfsdump's inability to correctly guess the root directory.
> > 
> 
> Ok, figured as much once I got to the magic inode flag patch. It's
> probably reasonable either way, the tradeoff to this approach is the
> extra boilerplate code associated with processing the separate data
> structure.

<nod>

> Thinking about it a bit more.. what was the purpose of the separate
> BULKSTAT_SINGLE command in the first place? AFAICT it just toggles the
> hacky ->lastip semantic. If we've addressed that with an entirely new
> data structure, do we need the separate ioctl at all anymore?

At the moment, somewhat simpler setup in userspace:

	struct xfs_bulkstat_single_req b = { 0 };
	int ret;

	b.hdr.ino = some_ino;
	ret = ioctl(fd, XFS_IOC_BULKSTAT_SINGLE, &b);
	if (ret)
		abort();

	printf("%d\n", b.bulkstat.bs_ino);

vs. a single-inode bulkstat:

	struct xfs_bulkstat_req *b;
	int ret;

	b = calloc(1, XFS_BULKSTAT_REQ_SIZE(1));
	if (!b)
		abort();

	b->hdr.ino = some_ino;
	ret = ioctl(fd, XFS_IOC_BULKSTAT, b);
	if (ret)
		abort();

	if (b->hdr.ocount)
		printf("%d\n", b->bulkstat[0].bs_ino);

	free(b);

AFAICT, the main advantages are (1) replacing the heap allocation with a
stack allocation and (2) not cluttering the regular bulkstat with the
"just grab this one symbolic inode" interface.  We could very well just
drop this one, particularly since I'm in the process of wrapping most of
the ioctl invocation complexity in libfrog wrapper functions anyway...

--D

> Brian
> 
> > --D
> > 
> > > Brian
> > > 
> > > >  /*
> > > >   * Error injection.
> > > >   */
> > > > @@ -780,6 +795,7 @@ struct xfs_scrub_metadata {
> > > >  #define XFS_IOC_GOINGDOWN	     _IOR ('X', 125, uint32_t)
> > > >  #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_BULKSTAT_SINGLE	     _IOR ('X', 128, struct xfs_bulkstat_single_req)
> > > >  /*	XFS_IOC_GETFSUUID ---------- deprecated 140	 */
> > > >  
> > > >  
> > > > diff --git a/fs/xfs/xfs_ioctl.c b/fs/xfs/xfs_ioctl.c
> > > > index cf6a38c2a3ed..2c821fa601a4 100644
> > > > --- a/fs/xfs/xfs_ioctl.c
> > > > +++ b/fs/xfs/xfs_ioctl.c
> > > > @@ -922,6 +922,83 @@ xfs_ioc_bulkstat(
> > > >  	return 0;
> > > >  }
> > > >  
> > > > +/*
> > > > + * Check the incoming singleton request @hdr from userspace and initialize the
> > > > + * internal @breq bulk request appropriately.  Returns 0 if the bulk request
> > > > + * should proceed; or the usual negative error code.
> > > > + */
> > > > +static int
> > > > +xfs_ireq_setup(
> > > > +	struct xfs_mount	*mp,
> > > > +	struct xfs_ireq		*hdr,
> > > > +	struct xfs_ibulk	*breq,
> > > > +	void __user		*ubuffer)
> > > > +{
> > > > +	if ((hdr->flags & ~XFS_IREQ_FLAGS_ALL) ||
> > > > +	    hdr->reserved32 ||
> > > > +	    memchr_inv(hdr->reserved, 0, sizeof(hdr->reserved)))
> > > > +		return -EINVAL;
> > > > +
> > > > +	if (XFS_INO_TO_AGNO(mp, hdr->ino) >= mp->m_sb.sb_agcount)
> > > > +		return -EINVAL;
> > > > +
> > > > +	breq->ubuffer = ubuffer;
> > > > +	breq->icount = 1;
> > > > +	breq->startino = hdr->ino;
> > > > +	return 0;
> > > > +}
> > > > +
> > > > +/*
> > > > + * Update the userspace singleton request @hdr to reflect the end state of the
> > > > + * internal bulk request @breq.  If @error is negative then we return just
> > > > + * that; otherwise we copy the state so that userspace can discover what
> > > > + * happened.
> > > > + */
> > > > +static void
> > > > +xfs_ireq_teardown(
> > > > +	struct xfs_ireq		*hdr,
> > > > +	struct xfs_ibulk	*breq)
> > > > +{
> > > > +	hdr->ino = breq->startino;
> > > > +}
> > > > +
> > > > +/* Handle the v5 bulkstat_single ioctl. */
> > > > +STATIC int
> > > > +xfs_ioc_bulkstat_single(
> > > > +	struct xfs_mount	*mp,
> > > > +	unsigned int		cmd,
> > > > +	struct xfs_bulkstat_single_req __user *arg)
> > > > +{
> > > > +	struct xfs_ireq		hdr;
> > > > +	struct xfs_ibulk	breq = {
> > > > +		.mp		= mp,
> > > > +	};
> > > > +	int			error;
> > > > +
> > > > +	if (!capable(CAP_SYS_ADMIN))
> > > > +		return -EPERM;
> > > > +
> > > > +	if (XFS_FORCED_SHUTDOWN(mp))
> > > > +		return -EIO;
> > > > +
> > > > +	if (copy_from_user(&hdr, &arg->hdr, sizeof(hdr)))
> > > > +		return -EFAULT;
> > > > +
> > > > +	error = xfs_ireq_setup(mp, &hdr, &breq, &arg->bulkstat);
> > > > +	if (error)
> > > > +		return error;
> > > > +
> > > > +	error = xfs_bulkstat_one(&breq, xfs_bulkstat_fmt);
> > > > +	if (error)
> > > > +		return error;
> > > > +
> > > > +	xfs_ireq_teardown(&hdr, &breq);
> > > > +	if (copy_to_user(&arg->hdr, &hdr, sizeof(hdr)))
> > > > +		return -EFAULT;
> > > > +
> > > > +	return 0;
> > > > +}
> > > > +
> > > >  STATIC int
> > > >  xfs_ioc_fsgeometry(
> > > >  	struct xfs_mount	*mp,
> > > > @@ -2088,6 +2165,8 @@ xfs_file_ioctl(
> > > >  
> > > >  	case XFS_IOC_BULKSTAT:
> > > >  		return xfs_ioc_bulkstat(mp, cmd, arg);
> > > > +	case XFS_IOC_BULKSTAT_SINGLE:
> > > > +		return xfs_ioc_bulkstat_single(mp, cmd, arg);
> > > >  
> > > >  	case XFS_IOC_FSGEOMETRY_V1:
> > > >  		return xfs_ioc_fsgeometry(mp, arg, 3);
> > > > diff --git a/fs/xfs/xfs_ioctl32.c b/fs/xfs/xfs_ioctl32.c
> > > > index df107adbdbf3..6fa0f41dbae5 100644
> > > > --- a/fs/xfs/xfs_ioctl32.c
> > > > +++ b/fs/xfs/xfs_ioctl32.c
> > > > @@ -581,6 +581,7 @@ xfs_file_compat_ioctl(
> > > >  	case FS_IOC_GETFSMAP:
> > > >  	case XFS_IOC_SCRUB_METADATA:
> > > >  	case XFS_IOC_BULKSTAT:
> > > > +	case XFS_IOC_BULKSTAT_SINGLE:
> > > >  		return xfs_file_ioctl(filp, cmd, p);
> > > >  #if !defined(BROKEN_X86_ALIGNMENT) || defined(CONFIG_X86_X32)
> > > >  	/*
> > > > diff --git a/fs/xfs/xfs_ondisk.h b/fs/xfs/xfs_ondisk.h
> > > > index 954484c6eb96..fa1252657b08 100644
> > > > --- a/fs/xfs/xfs_ondisk.h
> > > > +++ b/fs/xfs/xfs_ondisk.h
> > > > @@ -150,6 +150,7 @@ xfs_check_ondisk_structs(void)
> > > >  	XFS_CHECK_STRUCT_SIZE(struct xfs_bulkstat,		192);
> > > >  	XFS_CHECK_STRUCT_SIZE(struct xfs_inumbers,		24);
> > > >  	XFS_CHECK_STRUCT_SIZE(struct xfs_bulkstat_req,		64);
> > > > +	XFS_CHECK_STRUCT_SIZE(struct xfs_bulkstat_single_req,	224);
> > > >  }
> > > >  
> > > >  #endif /* __XFS_ONDISK_H */
> > > > 

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

* [PATCH v3 9/9] xfs: allow bulkstat_single of special inodes
  2019-06-26 20:46 ` [PATCH 9/9] xfs: allow bulkstat_single of special inodes Darrick J. Wong
  2019-07-03 13:25   ` Brian Foster
  2019-07-03 15:34   ` [PATCH v2 " Darrick J. Wong
@ 2019-07-04  6:51   ` Darrick J. Wong
  2 siblings, 0 replies; 34+ messages in thread
From: Darrick J. Wong @ 2019-07-04  6:51 UTC (permalink / raw)
  To: linux-xfs, allison.henderson

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

Create a new bulk ireq flag that enables userspace to ask us for a
special inode number instead of interpreting @ino as a literal inode
number.  This enables us to query the root inode easily.

The reason for adding the ability to query specifically the root
directory inode is that certain programs (xfsdump and xfsrestore) want
to confirm when they've been pointed to the root directory.  The
userspace code assumes the root directory is always the first result
from calling bulkstat with lastino == 0, but this isn't true if the
(initial btree roots + initial AGFL + inode alignment padding) is itself
long enough to be allocated to new inodes if all of those blocks should
happen to be free at the same time.  Rather than make userspace guess
at internal filesystem state, we provide a direct query.

Signed-off-by: Darrick J. Wong <darrick.wong@oracle.com>
Reviewed-by: Allison Collins <allison.henderson@oracle.com>
Reviewed-by: Brian Foster <bfoster@redhat.com>
---
v3: attach to the bulkstat ioctl having dropped bulkstat_single
v2: elaborate on why we are adding this new ireq flag
---
 fs/xfs/libxfs/xfs_fs.h |   13 ++++++++++++-
 fs/xfs/xfs_ioctl.c     |   19 +++++++++++++++++++
 2 files changed, 31 insertions(+), 1 deletion(-)

diff --git a/fs/xfs/libxfs/xfs_fs.h b/fs/xfs/libxfs/xfs_fs.h
index d7b3b712b279..52d03a3a02a4 100644
--- a/fs/xfs/libxfs/xfs_fs.h
+++ b/fs/xfs/libxfs/xfs_fs.h
@@ -472,7 +472,18 @@ struct xfs_bulk_ireq {
  */
 #define XFS_BULK_IREQ_AGNO	(1 << 0)
 
-#define XFS_BULK_IREQ_FLAGS_ALL	(XFS_BULK_IREQ_AGNO)
+/*
+ * Return bulkstat information for a single inode, where @ino value is a
+ * special value, not a literal inode number.  See the XFS_BULK_IREQ_SPECIAL_*
+ * values below.  Not compatible with XFS_BULK_IREQ_AGNO.
+ */
+#define XFS_BULK_IREQ_SPECIAL	(1 << 1)
+
+#define XFS_BULK_IREQ_FLAGS_ALL	(XFS_BULK_IREQ_AGNO | \
+				 XFS_BULK_IREQ_SPECIAL)
+
+/* Operate on the root directory inode. */
+#define XFS_BULK_IREQ_SPECIAL_ROOT	(1)
 
 /*
  * ioctl structures for v5 bulkstat and inumbers requests
diff --git a/fs/xfs/xfs_ioctl.c b/fs/xfs/xfs_ioctl.c
index e1e1d9d6c16d..6bf04e71325b 100644
--- a/fs/xfs/xfs_ioctl.c
+++ b/fs/xfs/xfs_ioctl.c
@@ -853,6 +853,25 @@ xfs_bulk_ireq_setup(
 	breq->ocount = 0;
 	breq->flags = 0;
 
+	/*
+	 * The @ino parameter is a special value, so we must look it up here.
+	 * We're not allowed to have IREQ_AGNO, and we only return one inode
+	 * worth of data.
+	 */
+	if (hdr->flags & XFS_BULK_IREQ_SPECIAL) {
+		if (hdr->flags & XFS_BULK_IREQ_AGNO)
+			return -EINVAL;
+
+		switch (hdr->ino) {
+		case XFS_BULK_IREQ_SPECIAL_ROOT:
+			hdr->ino = mp->m_sb.sb_rootino;
+			break;
+		default:
+			return -EINVAL;
+		}
+		breq->icount = 1;
+	}
+
 	/*
 	 * The IREQ_AGNO flag means that we only want results from a given AG.
 	 * If @hdr->ino is zero, we start iterating in that AG.  If @hdr->ino is

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

* Re: [PATCH 6/9] xfs: wire up the new v5 bulkstat_single ioctl
  2019-07-03 20:01         ` Darrick J. Wong
@ 2019-07-05 11:05           ` Brian Foster
  2019-07-05 16:26             ` Darrick J. Wong
  0 siblings, 1 reply; 34+ messages in thread
From: Brian Foster @ 2019-07-05 11:05 UTC (permalink / raw)
  To: Darrick J. Wong; +Cc: linux-xfs, allison.henderson

On Wed, Jul 03, 2019 at 01:01:43PM -0700, Darrick J. Wong wrote:
> On Wed, Jul 03, 2019 at 12:11:36PM -0400, Brian Foster wrote:
> > On Wed, Jul 03, 2019 at 07:52:56AM -0700, Darrick J. Wong wrote:
> > > On Wed, Jul 03, 2019 at 09:24:41AM -0400, Brian Foster wrote:
> > > > On Wed, Jun 26, 2019 at 01:46:13PM -0700, Darrick J. Wong wrote:
> > > > > From: Darrick J. Wong <darrick.wong@oracle.com>
> > > > > 
> > > > > Wire up the V5 BULKSTAT_SINGLE ioctl and rename the old one V1.
> > > > > 
> > > > > Signed-off-by: Darrick J. Wong <darrick.wong@oracle.com>
> > > > > ---
> > > > >  fs/xfs/libxfs/xfs_fs.h |   16 ++++++++++
> > > > >  fs/xfs/xfs_ioctl.c     |   79 ++++++++++++++++++++++++++++++++++++++++++++++++
> > > > >  fs/xfs/xfs_ioctl32.c   |    1 +
> > > > >  fs/xfs/xfs_ondisk.h    |    1 +
> > > > >  4 files changed, 97 insertions(+)
> > > > > 
> > > > > 
> > > > > diff --git a/fs/xfs/libxfs/xfs_fs.h b/fs/xfs/libxfs/xfs_fs.h
> > > > > index 960f3542e207..95d0411dae9b 100644
> > > > > --- a/fs/xfs/libxfs/xfs_fs.h
> > > > > +++ b/fs/xfs/libxfs/xfs_fs.h
> > > > > @@ -468,6 +468,16 @@ struct xfs_bulk_ireq {
> > > > >  
> > > > >  #define XFS_BULK_IREQ_FLAGS_ALL	(0)
> > > > >  
> > > > > +/* Header for a single inode request. */
> > > > > +struct xfs_ireq {
> > > > > +	uint64_t	ino;		/* I/O: start with this inode	*/
> > > > > +	uint32_t	flags;		/* I/O: operation flags		*/
> > > > > +	uint32_t	reserved32;	/* must be zero			*/
> > > > > +	uint64_t	reserved[2];	/* must be zero			*/
> > > > > +};
> > > > > +
> > > > > +#define XFS_IREQ_FLAGS_ALL	(0)
> > > > > +
> > > > >  /*
> > > > >   * ioctl structures for v5 bulkstat and inumbers requests
> > > > >   */
> > > > > @@ -478,6 +488,11 @@ struct xfs_bulkstat_req {
> > > > >  #define XFS_BULKSTAT_REQ_SIZE(nr)	(sizeof(struct xfs_bulkstat_req) + \
> > > > >  					 (nr) * sizeof(struct xfs_bulkstat))
> > > > >  
> > > > > +struct xfs_bulkstat_single_req {
> > > > > +	struct xfs_ireq		hdr;
> > > > > +	struct xfs_bulkstat	bulkstat;
> > > > > +};
> > > > > +
> > > > 
> > > > What's the reasoning for separate data structures when the single
> > > > command is basically a subset of standard bulkstat (similar to the older
> > > > interface)?
> > > 
> > > I split them up to avoid having irrelevant bulk_req fields (specifically
> > > icount and ocount) cluttering up the single_req header.  In patch 9 the
> > > bulkstat single command grows the ability to request the root inode to
> > > fix xfsdump's inability to correctly guess the root directory.
> > > 
> > 
> > Ok, figured as much once I got to the magic inode flag patch. It's
> > probably reasonable either way, the tradeoff to this approach is the
> > extra boilerplate code associated with processing the separate data
> > structure.
> 
> <nod>
> 
> > Thinking about it a bit more.. what was the purpose of the separate
> > BULKSTAT_SINGLE command in the first place? AFAICT it just toggles the
> > hacky ->lastip semantic. If we've addressed that with an entirely new
> > data structure, do we need the separate ioctl at all anymore?
> 
> At the moment, somewhat simpler setup in userspace:
> 
> 	struct xfs_bulkstat_single_req b = { 0 };
> 	int ret;
> 
> 	b.hdr.ino = some_ino;
> 	ret = ioctl(fd, XFS_IOC_BULKSTAT_SINGLE, &b);
> 	if (ret)
> 		abort();
> 
> 	printf("%d\n", b.bulkstat.bs_ino);
> 
> vs. a single-inode bulkstat:
> 
> 	struct xfs_bulkstat_req *b;
> 	int ret;
> 
> 	b = calloc(1, XFS_BULKSTAT_REQ_SIZE(1));
> 	if (!b)
> 		abort();
> 
> 	b->hdr.ino = some_ino;
> 	ret = ioctl(fd, XFS_IOC_BULKSTAT, b);
> 	if (ret)
> 		abort();
> 
> 	if (b->hdr.ocount)
> 		printf("%d\n", b->bulkstat[0].bs_ino);
> 
> 	free(b);
> 
> AFAICT, the main advantages are (1) replacing the heap allocation with a
> stack allocation and (2) not cluttering the regular bulkstat with the
> "just grab this one symbolic inode" interface.  We could very well just
> drop this one, particularly since I'm in the process of wrapping most of
> the ioctl invocation complexity in libfrog wrapper functions anyway...
> 

That seems preferable to me. I'm not that invested in the semantics
between bulkstat and bulkstat_single, but if the only reason we
originally had the latter as a separate ioctl was to deal with the
->lastip interface wart then I think it would be unfortunate to
unnecessarily carry that mess forward through another generation of the
interface that doesn't have the original problem. Userspace should be
able to easily abstract the single case.

Brian

> --D
> 
> > Brian
> > 
> > > --D
> > > 
> > > > Brian
> > > > 
> > > > >  /*
> > > > >   * Error injection.
> > > > >   */
> > > > > @@ -780,6 +795,7 @@ struct xfs_scrub_metadata {
> > > > >  #define XFS_IOC_GOINGDOWN	     _IOR ('X', 125, uint32_t)
> > > > >  #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_BULKSTAT_SINGLE	     _IOR ('X', 128, struct xfs_bulkstat_single_req)
> > > > >  /*	XFS_IOC_GETFSUUID ---------- deprecated 140	 */
> > > > >  
> > > > >  
> > > > > diff --git a/fs/xfs/xfs_ioctl.c b/fs/xfs/xfs_ioctl.c
> > > > > index cf6a38c2a3ed..2c821fa601a4 100644
> > > > > --- a/fs/xfs/xfs_ioctl.c
> > > > > +++ b/fs/xfs/xfs_ioctl.c
> > > > > @@ -922,6 +922,83 @@ xfs_ioc_bulkstat(
> > > > >  	return 0;
> > > > >  }
> > > > >  
> > > > > +/*
> > > > > + * Check the incoming singleton request @hdr from userspace and initialize the
> > > > > + * internal @breq bulk request appropriately.  Returns 0 if the bulk request
> > > > > + * should proceed; or the usual negative error code.
> > > > > + */
> > > > > +static int
> > > > > +xfs_ireq_setup(
> > > > > +	struct xfs_mount	*mp,
> > > > > +	struct xfs_ireq		*hdr,
> > > > > +	struct xfs_ibulk	*breq,
> > > > > +	void __user		*ubuffer)
> > > > > +{
> > > > > +	if ((hdr->flags & ~XFS_IREQ_FLAGS_ALL) ||
> > > > > +	    hdr->reserved32 ||
> > > > > +	    memchr_inv(hdr->reserved, 0, sizeof(hdr->reserved)))
> > > > > +		return -EINVAL;
> > > > > +
> > > > > +	if (XFS_INO_TO_AGNO(mp, hdr->ino) >= mp->m_sb.sb_agcount)
> > > > > +		return -EINVAL;
> > > > > +
> > > > > +	breq->ubuffer = ubuffer;
> > > > > +	breq->icount = 1;
> > > > > +	breq->startino = hdr->ino;
> > > > > +	return 0;
> > > > > +}
> > > > > +
> > > > > +/*
> > > > > + * Update the userspace singleton request @hdr to reflect the end state of the
> > > > > + * internal bulk request @breq.  If @error is negative then we return just
> > > > > + * that; otherwise we copy the state so that userspace can discover what
> > > > > + * happened.
> > > > > + */
> > > > > +static void
> > > > > +xfs_ireq_teardown(
> > > > > +	struct xfs_ireq		*hdr,
> > > > > +	struct xfs_ibulk	*breq)
> > > > > +{
> > > > > +	hdr->ino = breq->startino;
> > > > > +}
> > > > > +
> > > > > +/* Handle the v5 bulkstat_single ioctl. */
> > > > > +STATIC int
> > > > > +xfs_ioc_bulkstat_single(
> > > > > +	struct xfs_mount	*mp,
> > > > > +	unsigned int		cmd,
> > > > > +	struct xfs_bulkstat_single_req __user *arg)
> > > > > +{
> > > > > +	struct xfs_ireq		hdr;
> > > > > +	struct xfs_ibulk	breq = {
> > > > > +		.mp		= mp,
> > > > > +	};
> > > > > +	int			error;
> > > > > +
> > > > > +	if (!capable(CAP_SYS_ADMIN))
> > > > > +		return -EPERM;
> > > > > +
> > > > > +	if (XFS_FORCED_SHUTDOWN(mp))
> > > > > +		return -EIO;
> > > > > +
> > > > > +	if (copy_from_user(&hdr, &arg->hdr, sizeof(hdr)))
> > > > > +		return -EFAULT;
> > > > > +
> > > > > +	error = xfs_ireq_setup(mp, &hdr, &breq, &arg->bulkstat);
> > > > > +	if (error)
> > > > > +		return error;
> > > > > +
> > > > > +	error = xfs_bulkstat_one(&breq, xfs_bulkstat_fmt);
> > > > > +	if (error)
> > > > > +		return error;
> > > > > +
> > > > > +	xfs_ireq_teardown(&hdr, &breq);
> > > > > +	if (copy_to_user(&arg->hdr, &hdr, sizeof(hdr)))
> > > > > +		return -EFAULT;
> > > > > +
> > > > > +	return 0;
> > > > > +}
> > > > > +
> > > > >  STATIC int
> > > > >  xfs_ioc_fsgeometry(
> > > > >  	struct xfs_mount	*mp,
> > > > > @@ -2088,6 +2165,8 @@ xfs_file_ioctl(
> > > > >  
> > > > >  	case XFS_IOC_BULKSTAT:
> > > > >  		return xfs_ioc_bulkstat(mp, cmd, arg);
> > > > > +	case XFS_IOC_BULKSTAT_SINGLE:
> > > > > +		return xfs_ioc_bulkstat_single(mp, cmd, arg);
> > > > >  
> > > > >  	case XFS_IOC_FSGEOMETRY_V1:
> > > > >  		return xfs_ioc_fsgeometry(mp, arg, 3);
> > > > > diff --git a/fs/xfs/xfs_ioctl32.c b/fs/xfs/xfs_ioctl32.c
> > > > > index df107adbdbf3..6fa0f41dbae5 100644
> > > > > --- a/fs/xfs/xfs_ioctl32.c
> > > > > +++ b/fs/xfs/xfs_ioctl32.c
> > > > > @@ -581,6 +581,7 @@ xfs_file_compat_ioctl(
> > > > >  	case FS_IOC_GETFSMAP:
> > > > >  	case XFS_IOC_SCRUB_METADATA:
> > > > >  	case XFS_IOC_BULKSTAT:
> > > > > +	case XFS_IOC_BULKSTAT_SINGLE:
> > > > >  		return xfs_file_ioctl(filp, cmd, p);
> > > > >  #if !defined(BROKEN_X86_ALIGNMENT) || defined(CONFIG_X86_X32)
> > > > >  	/*
> > > > > diff --git a/fs/xfs/xfs_ondisk.h b/fs/xfs/xfs_ondisk.h
> > > > > index 954484c6eb96..fa1252657b08 100644
> > > > > --- a/fs/xfs/xfs_ondisk.h
> > > > > +++ b/fs/xfs/xfs_ondisk.h
> > > > > @@ -150,6 +150,7 @@ xfs_check_ondisk_structs(void)
> > > > >  	XFS_CHECK_STRUCT_SIZE(struct xfs_bulkstat,		192);
> > > > >  	XFS_CHECK_STRUCT_SIZE(struct xfs_inumbers,		24);
> > > > >  	XFS_CHECK_STRUCT_SIZE(struct xfs_bulkstat_req,		64);
> > > > > +	XFS_CHECK_STRUCT_SIZE(struct xfs_bulkstat_single_req,	224);
> > > > >  }
> > > > >  
> > > > >  #endif /* __XFS_ONDISK_H */
> > > > > 

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

* Re: [PATCH 6/9] xfs: wire up the new v5 bulkstat_single ioctl
  2019-07-05 11:05           ` Brian Foster
@ 2019-07-05 16:26             ` Darrick J. Wong
  0 siblings, 0 replies; 34+ messages in thread
From: Darrick J. Wong @ 2019-07-05 16:26 UTC (permalink / raw)
  To: Brian Foster; +Cc: linux-xfs, allison.henderson

On Fri, Jul 05, 2019 at 07:05:33AM -0400, Brian Foster wrote:
> On Wed, Jul 03, 2019 at 01:01:43PM -0700, Darrick J. Wong wrote:
> > On Wed, Jul 03, 2019 at 12:11:36PM -0400, Brian Foster wrote:
> > > On Wed, Jul 03, 2019 at 07:52:56AM -0700, Darrick J. Wong wrote:
> > > > On Wed, Jul 03, 2019 at 09:24:41AM -0400, Brian Foster wrote:
> > > > > On Wed, Jun 26, 2019 at 01:46:13PM -0700, Darrick J. Wong wrote:
> > > > > > From: Darrick J. Wong <darrick.wong@oracle.com>
> > > > > > 
> > > > > > Wire up the V5 BULKSTAT_SINGLE ioctl and rename the old one V1.
> > > > > > 
> > > > > > Signed-off-by: Darrick J. Wong <darrick.wong@oracle.com>
> > > > > > ---
> > > > > >  fs/xfs/libxfs/xfs_fs.h |   16 ++++++++++
> > > > > >  fs/xfs/xfs_ioctl.c     |   79 ++++++++++++++++++++++++++++++++++++++++++++++++
> > > > > >  fs/xfs/xfs_ioctl32.c   |    1 +
> > > > > >  fs/xfs/xfs_ondisk.h    |    1 +
> > > > > >  4 files changed, 97 insertions(+)
> > > > > > 
> > > > > > 
> > > > > > diff --git a/fs/xfs/libxfs/xfs_fs.h b/fs/xfs/libxfs/xfs_fs.h
> > > > > > index 960f3542e207..95d0411dae9b 100644
> > > > > > --- a/fs/xfs/libxfs/xfs_fs.h
> > > > > > +++ b/fs/xfs/libxfs/xfs_fs.h
> > > > > > @@ -468,6 +468,16 @@ struct xfs_bulk_ireq {
> > > > > >  
> > > > > >  #define XFS_BULK_IREQ_FLAGS_ALL	(0)
> > > > > >  
> > > > > > +/* Header for a single inode request. */
> > > > > > +struct xfs_ireq {
> > > > > > +	uint64_t	ino;		/* I/O: start with this inode	*/
> > > > > > +	uint32_t	flags;		/* I/O: operation flags		*/
> > > > > > +	uint32_t	reserved32;	/* must be zero			*/
> > > > > > +	uint64_t	reserved[2];	/* must be zero			*/
> > > > > > +};
> > > > > > +
> > > > > > +#define XFS_IREQ_FLAGS_ALL	(0)
> > > > > > +
> > > > > >  /*
> > > > > >   * ioctl structures for v5 bulkstat and inumbers requests
> > > > > >   */
> > > > > > @@ -478,6 +488,11 @@ struct xfs_bulkstat_req {
> > > > > >  #define XFS_BULKSTAT_REQ_SIZE(nr)	(sizeof(struct xfs_bulkstat_req) + \
> > > > > >  					 (nr) * sizeof(struct xfs_bulkstat))
> > > > > >  
> > > > > > +struct xfs_bulkstat_single_req {
> > > > > > +	struct xfs_ireq		hdr;
> > > > > > +	struct xfs_bulkstat	bulkstat;
> > > > > > +};
> > > > > > +
> > > > > 
> > > > > What's the reasoning for separate data structures when the single
> > > > > command is basically a subset of standard bulkstat (similar to the older
> > > > > interface)?
> > > > 
> > > > I split them up to avoid having irrelevant bulk_req fields (specifically
> > > > icount and ocount) cluttering up the single_req header.  In patch 9 the
> > > > bulkstat single command grows the ability to request the root inode to
> > > > fix xfsdump's inability to correctly guess the root directory.
> > > > 
> > > 
> > > Ok, figured as much once I got to the magic inode flag patch. It's
> > > probably reasonable either way, the tradeoff to this approach is the
> > > extra boilerplate code associated with processing the separate data
> > > structure.
> > 
> > <nod>
> > 
> > > Thinking about it a bit more.. what was the purpose of the separate
> > > BULKSTAT_SINGLE command in the first place? AFAICT it just toggles the
> > > hacky ->lastip semantic. If we've addressed that with an entirely new
> > > data structure, do we need the separate ioctl at all anymore?
> > 
> > At the moment, somewhat simpler setup in userspace:
> > 
> > 	struct xfs_bulkstat_single_req b = { 0 };
> > 	int ret;
> > 
> > 	b.hdr.ino = some_ino;
> > 	ret = ioctl(fd, XFS_IOC_BULKSTAT_SINGLE, &b);
> > 	if (ret)
> > 		abort();
> > 
> > 	printf("%d\n", b.bulkstat.bs_ino);
> > 
> > vs. a single-inode bulkstat:
> > 
> > 	struct xfs_bulkstat_req *b;
> > 	int ret;
> > 
> > 	b = calloc(1, XFS_BULKSTAT_REQ_SIZE(1));
> > 	if (!b)
> > 		abort();
> > 
> > 	b->hdr.ino = some_ino;
> > 	ret = ioctl(fd, XFS_IOC_BULKSTAT, b);
> > 	if (ret)
> > 		abort();
> > 
> > 	if (b->hdr.ocount)
> > 		printf("%d\n", b->bulkstat[0].bs_ino);
> > 
> > 	free(b);
> > 
> > AFAICT, the main advantages are (1) replacing the heap allocation with a
> > stack allocation and (2) not cluttering the regular bulkstat with the
> > "just grab this one symbolic inode" interface.  We could very well just
> > drop this one, particularly since I'm in the process of wrapping most of
> > the ioctl invocation complexity in libfrog wrapper functions anyway...
> > 
> 
> That seems preferable to me. I'm not that invested in the semantics
> between bulkstat and bulkstat_single, but if the only reason we
> originally had the latter as a separate ioctl was to deal with the
> ->lastip interface wart then I think it would be unfortunate to
> unnecessarily carry that mess forward through another generation of the
> interface that doesn't have the original problem. Userspace should be
> able to easily abstract the single case.

Indeed, it was trivially easy to rewrite the xfrog_bulkstat_single
wrapper. :)

--D

> Brian
> 
> > --D
> > 
> > > Brian
> > > 
> > > > --D
> > > > 
> > > > > Brian
> > > > > 
> > > > > >  /*
> > > > > >   * Error injection.
> > > > > >   */
> > > > > > @@ -780,6 +795,7 @@ struct xfs_scrub_metadata {
> > > > > >  #define XFS_IOC_GOINGDOWN	     _IOR ('X', 125, uint32_t)
> > > > > >  #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_BULKSTAT_SINGLE	     _IOR ('X', 128, struct xfs_bulkstat_single_req)
> > > > > >  /*	XFS_IOC_GETFSUUID ---------- deprecated 140	 */
> > > > > >  
> > > > > >  
> > > > > > diff --git a/fs/xfs/xfs_ioctl.c b/fs/xfs/xfs_ioctl.c
> > > > > > index cf6a38c2a3ed..2c821fa601a4 100644
> > > > > > --- a/fs/xfs/xfs_ioctl.c
> > > > > > +++ b/fs/xfs/xfs_ioctl.c
> > > > > > @@ -922,6 +922,83 @@ xfs_ioc_bulkstat(
> > > > > >  	return 0;
> > > > > >  }
> > > > > >  
> > > > > > +/*
> > > > > > + * Check the incoming singleton request @hdr from userspace and initialize the
> > > > > > + * internal @breq bulk request appropriately.  Returns 0 if the bulk request
> > > > > > + * should proceed; or the usual negative error code.
> > > > > > + */
> > > > > > +static int
> > > > > > +xfs_ireq_setup(
> > > > > > +	struct xfs_mount	*mp,
> > > > > > +	struct xfs_ireq		*hdr,
> > > > > > +	struct xfs_ibulk	*breq,
> > > > > > +	void __user		*ubuffer)
> > > > > > +{
> > > > > > +	if ((hdr->flags & ~XFS_IREQ_FLAGS_ALL) ||
> > > > > > +	    hdr->reserved32 ||
> > > > > > +	    memchr_inv(hdr->reserved, 0, sizeof(hdr->reserved)))
> > > > > > +		return -EINVAL;
> > > > > > +
> > > > > > +	if (XFS_INO_TO_AGNO(mp, hdr->ino) >= mp->m_sb.sb_agcount)
> > > > > > +		return -EINVAL;
> > > > > > +
> > > > > > +	breq->ubuffer = ubuffer;
> > > > > > +	breq->icount = 1;
> > > > > > +	breq->startino = hdr->ino;
> > > > > > +	return 0;
> > > > > > +}
> > > > > > +
> > > > > > +/*
> > > > > > + * Update the userspace singleton request @hdr to reflect the end state of the
> > > > > > + * internal bulk request @breq.  If @error is negative then we return just
> > > > > > + * that; otherwise we copy the state so that userspace can discover what
> > > > > > + * happened.
> > > > > > + */
> > > > > > +static void
> > > > > > +xfs_ireq_teardown(
> > > > > > +	struct xfs_ireq		*hdr,
> > > > > > +	struct xfs_ibulk	*breq)
> > > > > > +{
> > > > > > +	hdr->ino = breq->startino;
> > > > > > +}
> > > > > > +
> > > > > > +/* Handle the v5 bulkstat_single ioctl. */
> > > > > > +STATIC int
> > > > > > +xfs_ioc_bulkstat_single(
> > > > > > +	struct xfs_mount	*mp,
> > > > > > +	unsigned int		cmd,
> > > > > > +	struct xfs_bulkstat_single_req __user *arg)
> > > > > > +{
> > > > > > +	struct xfs_ireq		hdr;
> > > > > > +	struct xfs_ibulk	breq = {
> > > > > > +		.mp		= mp,
> > > > > > +	};
> > > > > > +	int			error;
> > > > > > +
> > > > > > +	if (!capable(CAP_SYS_ADMIN))
> > > > > > +		return -EPERM;
> > > > > > +
> > > > > > +	if (XFS_FORCED_SHUTDOWN(mp))
> > > > > > +		return -EIO;
> > > > > > +
> > > > > > +	if (copy_from_user(&hdr, &arg->hdr, sizeof(hdr)))
> > > > > > +		return -EFAULT;
> > > > > > +
> > > > > > +	error = xfs_ireq_setup(mp, &hdr, &breq, &arg->bulkstat);
> > > > > > +	if (error)
> > > > > > +		return error;
> > > > > > +
> > > > > > +	error = xfs_bulkstat_one(&breq, xfs_bulkstat_fmt);
> > > > > > +	if (error)
> > > > > > +		return error;
> > > > > > +
> > > > > > +	xfs_ireq_teardown(&hdr, &breq);
> > > > > > +	if (copy_to_user(&arg->hdr, &hdr, sizeof(hdr)))
> > > > > > +		return -EFAULT;
> > > > > > +
> > > > > > +	return 0;
> > > > > > +}
> > > > > > +
> > > > > >  STATIC int
> > > > > >  xfs_ioc_fsgeometry(
> > > > > >  	struct xfs_mount	*mp,
> > > > > > @@ -2088,6 +2165,8 @@ xfs_file_ioctl(
> > > > > >  
> > > > > >  	case XFS_IOC_BULKSTAT:
> > > > > >  		return xfs_ioc_bulkstat(mp, cmd, arg);
> > > > > > +	case XFS_IOC_BULKSTAT_SINGLE:
> > > > > > +		return xfs_ioc_bulkstat_single(mp, cmd, arg);
> > > > > >  
> > > > > >  	case XFS_IOC_FSGEOMETRY_V1:
> > > > > >  		return xfs_ioc_fsgeometry(mp, arg, 3);
> > > > > > diff --git a/fs/xfs/xfs_ioctl32.c b/fs/xfs/xfs_ioctl32.c
> > > > > > index df107adbdbf3..6fa0f41dbae5 100644
> > > > > > --- a/fs/xfs/xfs_ioctl32.c
> > > > > > +++ b/fs/xfs/xfs_ioctl32.c
> > > > > > @@ -581,6 +581,7 @@ xfs_file_compat_ioctl(
> > > > > >  	case FS_IOC_GETFSMAP:
> > > > > >  	case XFS_IOC_SCRUB_METADATA:
> > > > > >  	case XFS_IOC_BULKSTAT:
> > > > > > +	case XFS_IOC_BULKSTAT_SINGLE:
> > > > > >  		return xfs_file_ioctl(filp, cmd, p);
> > > > > >  #if !defined(BROKEN_X86_ALIGNMENT) || defined(CONFIG_X86_X32)
> > > > > >  	/*
> > > > > > diff --git a/fs/xfs/xfs_ondisk.h b/fs/xfs/xfs_ondisk.h
> > > > > > index 954484c6eb96..fa1252657b08 100644
> > > > > > --- a/fs/xfs/xfs_ondisk.h
> > > > > > +++ b/fs/xfs/xfs_ondisk.h
> > > > > > @@ -150,6 +150,7 @@ xfs_check_ondisk_structs(void)
> > > > > >  	XFS_CHECK_STRUCT_SIZE(struct xfs_bulkstat,		192);
> > > > > >  	XFS_CHECK_STRUCT_SIZE(struct xfs_inumbers,		24);
> > > > > >  	XFS_CHECK_STRUCT_SIZE(struct xfs_bulkstat_req,		64);
> > > > > > +	XFS_CHECK_STRUCT_SIZE(struct xfs_bulkstat_single_req,	224);
> > > > > >  }
> > > > > >  
> > > > > >  #endif /* __XFS_ONDISK_H */
> > > > > > 

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

* [PATCH 6/9] xfs: wire up the new v5 bulkstat_single ioctl
  2019-06-12  6:49 [PATCH v5 0/9] xfs: introduce new BULKSTAT and INUMBERS ioctls Darrick J. Wong
@ 2019-06-12  6:49 ` Darrick J. Wong
  0 siblings, 0 replies; 34+ messages in thread
From: Darrick J. Wong @ 2019-06-12  6:49 UTC (permalink / raw)
  To: darrick.wong; +Cc: linux-xfs, allison.henderson

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

Wire up the V5 BULKSTAT_SINGLE ioctl and rename the old one V1.

Signed-off-by: Darrick J. Wong <darrick.wong@oracle.com>
---
 fs/xfs/libxfs/xfs_fs.h |   16 ++++++++++
 fs/xfs/xfs_ioctl.c     |   79 ++++++++++++++++++++++++++++++++++++++++++++++++
 fs/xfs/xfs_ioctl32.c   |    1 +
 fs/xfs/xfs_ondisk.h    |    1 +
 4 files changed, 97 insertions(+)


diff --git a/fs/xfs/libxfs/xfs_fs.h b/fs/xfs/libxfs/xfs_fs.h
index 960f3542e207..95d0411dae9b 100644
--- a/fs/xfs/libxfs/xfs_fs.h
+++ b/fs/xfs/libxfs/xfs_fs.h
@@ -468,6 +468,16 @@ struct xfs_bulk_ireq {
 
 #define XFS_BULK_IREQ_FLAGS_ALL	(0)
 
+/* Header for a single inode request. */
+struct xfs_ireq {
+	uint64_t	ino;		/* I/O: start with this inode	*/
+	uint32_t	flags;		/* I/O: operation flags		*/
+	uint32_t	reserved32;	/* must be zero			*/
+	uint64_t	reserved[2];	/* must be zero			*/
+};
+
+#define XFS_IREQ_FLAGS_ALL	(0)
+
 /*
  * ioctl structures for v5 bulkstat and inumbers requests
  */
@@ -478,6 +488,11 @@ struct xfs_bulkstat_req {
 #define XFS_BULKSTAT_REQ_SIZE(nr)	(sizeof(struct xfs_bulkstat_req) + \
 					 (nr) * sizeof(struct xfs_bulkstat))
 
+struct xfs_bulkstat_single_req {
+	struct xfs_ireq		hdr;
+	struct xfs_bulkstat	bulkstat;
+};
+
 /*
  * Error injection.
  */
@@ -780,6 +795,7 @@ struct xfs_scrub_metadata {
 #define XFS_IOC_GOINGDOWN	     _IOR ('X', 125, uint32_t)
 #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_BULKSTAT_SINGLE	     _IOR ('X', 128, struct xfs_bulkstat_single_req)
 /*	XFS_IOC_GETFSUUID ---------- deprecated 140	 */
 
 
diff --git a/fs/xfs/xfs_ioctl.c b/fs/xfs/xfs_ioctl.c
index cf6a38c2a3ed..2c821fa601a4 100644
--- a/fs/xfs/xfs_ioctl.c
+++ b/fs/xfs/xfs_ioctl.c
@@ -922,6 +922,83 @@ xfs_ioc_bulkstat(
 	return 0;
 }
 
+/*
+ * Check the incoming singleton request @hdr from userspace and initialize the
+ * internal @breq bulk request appropriately.  Returns 0 if the bulk request
+ * should proceed; or the usual negative error code.
+ */
+static int
+xfs_ireq_setup(
+	struct xfs_mount	*mp,
+	struct xfs_ireq		*hdr,
+	struct xfs_ibulk	*breq,
+	void __user		*ubuffer)
+{
+	if ((hdr->flags & ~XFS_IREQ_FLAGS_ALL) ||
+	    hdr->reserved32 ||
+	    memchr_inv(hdr->reserved, 0, sizeof(hdr->reserved)))
+		return -EINVAL;
+
+	if (XFS_INO_TO_AGNO(mp, hdr->ino) >= mp->m_sb.sb_agcount)
+		return -EINVAL;
+
+	breq->ubuffer = ubuffer;
+	breq->icount = 1;
+	breq->startino = hdr->ino;
+	return 0;
+}
+
+/*
+ * Update the userspace singleton request @hdr to reflect the end state of the
+ * internal bulk request @breq.  If @error is negative then we return just
+ * that; otherwise we copy the state so that userspace can discover what
+ * happened.
+ */
+static void
+xfs_ireq_teardown(
+	struct xfs_ireq		*hdr,
+	struct xfs_ibulk	*breq)
+{
+	hdr->ino = breq->startino;
+}
+
+/* Handle the v5 bulkstat_single ioctl. */
+STATIC int
+xfs_ioc_bulkstat_single(
+	struct xfs_mount	*mp,
+	unsigned int		cmd,
+	struct xfs_bulkstat_single_req __user *arg)
+{
+	struct xfs_ireq		hdr;
+	struct xfs_ibulk	breq = {
+		.mp		= mp,
+	};
+	int			error;
+
+	if (!capable(CAP_SYS_ADMIN))
+		return -EPERM;
+
+	if (XFS_FORCED_SHUTDOWN(mp))
+		return -EIO;
+
+	if (copy_from_user(&hdr, &arg->hdr, sizeof(hdr)))
+		return -EFAULT;
+
+	error = xfs_ireq_setup(mp, &hdr, &breq, &arg->bulkstat);
+	if (error)
+		return error;
+
+	error = xfs_bulkstat_one(&breq, xfs_bulkstat_fmt);
+	if (error)
+		return error;
+
+	xfs_ireq_teardown(&hdr, &breq);
+	if (copy_to_user(&arg->hdr, &hdr, sizeof(hdr)))
+		return -EFAULT;
+
+	return 0;
+}
+
 STATIC int
 xfs_ioc_fsgeometry(
 	struct xfs_mount	*mp,
@@ -2088,6 +2165,8 @@ xfs_file_ioctl(
 
 	case XFS_IOC_BULKSTAT:
 		return xfs_ioc_bulkstat(mp, cmd, arg);
+	case XFS_IOC_BULKSTAT_SINGLE:
+		return xfs_ioc_bulkstat_single(mp, cmd, arg);
 
 	case XFS_IOC_FSGEOMETRY_V1:
 		return xfs_ioc_fsgeometry(mp, arg, 3);
diff --git a/fs/xfs/xfs_ioctl32.c b/fs/xfs/xfs_ioctl32.c
index 95cae33c961f..4152f68bfb5f 100644
--- a/fs/xfs/xfs_ioctl32.c
+++ b/fs/xfs/xfs_ioctl32.c
@@ -582,6 +582,7 @@ xfs_file_compat_ioctl(
 	case FS_IOC_GETFSMAP:
 	case XFS_IOC_SCRUB_METADATA:
 	case XFS_IOC_BULKSTAT:
+	case XFS_IOC_BULKSTAT_SINGLE:
 		return xfs_file_ioctl(filp, cmd, p);
 #if !defined(BROKEN_X86_ALIGNMENT) || defined(CONFIG_X86_X32)
 	/*
diff --git a/fs/xfs/xfs_ondisk.h b/fs/xfs/xfs_ondisk.h
index 954484c6eb96..fa1252657b08 100644
--- a/fs/xfs/xfs_ondisk.h
+++ b/fs/xfs/xfs_ondisk.h
@@ -150,6 +150,7 @@ xfs_check_ondisk_structs(void)
 	XFS_CHECK_STRUCT_SIZE(struct xfs_bulkstat,		192);
 	XFS_CHECK_STRUCT_SIZE(struct xfs_inumbers,		24);
 	XFS_CHECK_STRUCT_SIZE(struct xfs_bulkstat_req,		64);
+	XFS_CHECK_STRUCT_SIZE(struct xfs_bulkstat_single_req,	224);
 }
 
 #endif /* __XFS_ONDISK_H */

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

* Re: [PATCH 6/9] xfs: wire up the new v5 bulkstat_single ioctl
  2019-05-29 22:28 ` [PATCH 6/9] xfs: wire up the new v5 bulkstat_single ioctl Darrick J. Wong
@ 2019-06-05 22:30   ` Allison Collins
  0 siblings, 0 replies; 34+ messages in thread
From: Allison Collins @ 2019-06-05 22:30 UTC (permalink / raw)
  To: Darrick J. Wong; +Cc: linux-xfs



On 5/29/19 3:28 PM, Darrick J. Wong wrote:
> From: Darrick J. Wong <darrick.wong@oracle.com>
> 
> Wire up the V5 BULKSTAT_SINGLE ioctl and rename the old one V1.
> 
> Signed-off-by: Darrick J. Wong <darrick.wong@oracle.com>
> ---
>   fs/xfs/libxfs/xfs_fs.h |   16 +++++++++
>   fs/xfs/xfs_ioctl.c     |   85 ++++++++++++++++++++++++++++++++++++++++++++++++
>   fs/xfs/xfs_ioctl32.c   |    1 +
>   fs/xfs/xfs_ondisk.h    |    1 +
>   4 files changed, 103 insertions(+)
> 
> 
> diff --git a/fs/xfs/libxfs/xfs_fs.h b/fs/xfs/libxfs/xfs_fs.h
> index 960f3542e207..95d0411dae9b 100644
> --- a/fs/xfs/libxfs/xfs_fs.h
> +++ b/fs/xfs/libxfs/xfs_fs.h
> @@ -468,6 +468,16 @@ struct xfs_bulk_ireq {
>   
>   #define XFS_BULK_IREQ_FLAGS_ALL	(0)
>   
> +/* Header for a single inode request. */
> +struct xfs_ireq {
> +	uint64_t	ino;		/* I/O: start with this inode	*/
> +	uint32_t	flags;		/* I/O: operation flags		*/
> +	uint32_t	reserved32;	/* must be zero			*/
> +	uint64_t	reserved[2];	/* must be zero			*/
> +};
> +
> +#define XFS_IREQ_FLAGS_ALL	(0)
> +
>   /*
>    * ioctl structures for v5 bulkstat and inumbers requests
>    */
> @@ -478,6 +488,11 @@ struct xfs_bulkstat_req {
>   #define XFS_BULKSTAT_REQ_SIZE(nr)	(sizeof(struct xfs_bulkstat_req) + \
>   					 (nr) * sizeof(struct xfs_bulkstat))
>   
> +struct xfs_bulkstat_single_req {
> +	struct xfs_ireq		hdr;
> +	struct xfs_bulkstat	bulkstat;
> +};
> +
>   /*
>    * Error injection.
>    */
> @@ -780,6 +795,7 @@ struct xfs_scrub_metadata {
>   #define XFS_IOC_GOINGDOWN	     _IOR ('X', 125, uint32_t)
>   #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_BULKSTAT_SINGLE	     _IOR ('X', 128, struct xfs_bulkstat_single_req)
>   /*	XFS_IOC_GETFSUUID ---------- deprecated 140	 */
>   
>   
> diff --git a/fs/xfs/xfs_ioctl.c b/fs/xfs/xfs_ioctl.c
> index f6724c75ba97..f6971eb9561e 100644
> --- a/fs/xfs/xfs_ioctl.c
> +++ b/fs/xfs/xfs_ioctl.c
> @@ -923,6 +923,89 @@ xfs_ioc_bulkstat(
>   	return 0;
>   }
>   
> +/*
> + * Check the incoming singleton request @hdr from userspace and initialize the
> + * internal @breq bulk request appropriately.  Returns 0 if the bulk request
> + * should proceed; or the usual negative error code.
> + */
> +static int
> +xfs_ireq_setup(
> +	struct xfs_mount	*mp,
> +	struct xfs_ireq		*hdr,
> +	struct xfs_ibulk	*breq,
> +	void __user		*ubuffer)
> +{
> +	if ((hdr->flags & ~XFS_IREQ_FLAGS_ALL) ||
> +	    hdr->reserved32 ||
> +	    memchr_inv(hdr->reserved, 0, sizeof(hdr->reserved)))
> +		return -EINVAL;
> +
> +	if (XFS_INO_TO_AGNO(mp, hdr->ino) >= mp->m_sb.sb_agcount)
> +		return -EINVAL;
> +
> +	breq->ubuffer = ubuffer;
> +	breq->icount = 1;
> +	breq->startino = hdr->ino;
> +	return 0;
> +}
> +
> +/*
> + * Update the userspace singleton request @hdr to reflect the end state of the
> + * internal bulk request @breq.  If @error is negative then we return just
> + * that; otherwise we copy the state so that userspace can discover what
> + * happened.
> + */
> +static int
> +xfs_ireq_teardown(
> +	struct xfs_ireq		*hdr,
> +	struct xfs_ibulk	*breq,
> +	int			error)
> +{
> +	if (error < 0)
> +		return error;
Similar nit about the error code here too.  This function is so small, 
it might make sense to just factor it up into the calling function, 
sense I don't see it used else where in the set.  I suppose it's good to 
keep things consistent too though, it seem to be the pattern that the 
other ioctls use.

I think the rest is ok though

Allison

> +
> +	hdr->ino = breq->startino;
> +	return 0;
> +}
> +
> +/* Handle the v5 bulkstat_single ioctl. */
> +STATIC int
> +xfs_ioc_bulkstat_single(
> +	struct xfs_mount	*mp,
> +	unsigned int		cmd,
> +	struct xfs_bulkstat_single_req __user *arg)
> +{
> +	struct xfs_ireq		hdr;
> +	struct xfs_ibulk	breq = {
> +		.mp		= mp,
> +	};
> +	int			error;
> +
> +	if (!capable(CAP_SYS_ADMIN))
> +		return -EPERM;
> +
> +	if (XFS_FORCED_SHUTDOWN(mp))
> +		return -EIO;
> +
> +	if (copy_from_user(&hdr, &arg->hdr, sizeof(hdr)))
> +		return -EFAULT;
> +
> +	error = xfs_ireq_setup(mp, &hdr, &breq, &arg->bulkstat);
> +	if (error)
> +		return error;
> +
> +	error = xfs_bulkstat_one(&breq, xfs_bulkstat_fmt);
> +
> +	error = xfs_ireq_teardown(&hdr, &breq, error);
> +	if (error)
> +		return error;
> +
> +	if (copy_to_user(&arg->hdr, &hdr, sizeof(hdr)))
> +		return -EFAULT;
> +
> +	return 0;
> +}
> +
>   STATIC int
>   xfs_ioc_fsgeometry(
>   	struct xfs_mount	*mp,
> @@ -2089,6 +2172,8 @@ xfs_file_ioctl(
>   
>   	case XFS_IOC_BULKSTAT:
>   		return xfs_ioc_bulkstat(mp, cmd, arg);
> +	case XFS_IOC_BULKSTAT_SINGLE:
> +		return xfs_ioc_bulkstat_single(mp, cmd, arg);
>   
>   	case XFS_IOC_FSGEOMETRY_V1:
>   		return xfs_ioc_fsgeometry(mp, arg, 3);
> diff --git a/fs/xfs/xfs_ioctl32.c b/fs/xfs/xfs_ioctl32.c
> index 84c342be4536..08a90e3459d1 100644
> --- a/fs/xfs/xfs_ioctl32.c
> +++ b/fs/xfs/xfs_ioctl32.c
> @@ -577,6 +577,7 @@ xfs_file_compat_ioctl(
>   	case FS_IOC_GETFSMAP:
>   	case XFS_IOC_SCRUB_METADATA:
>   	case XFS_IOC_BULKSTAT:
> +	case XFS_IOC_BULKSTAT_SINGLE:
>   		return xfs_file_ioctl(filp, cmd, p);
>   #if !defined(BROKEN_X86_ALIGNMENT) || defined(CONFIG_X86_X32)
>   	/*
> diff --git a/fs/xfs/xfs_ondisk.h b/fs/xfs/xfs_ondisk.h
> index 954484c6eb96..fa1252657b08 100644
> --- a/fs/xfs/xfs_ondisk.h
> +++ b/fs/xfs/xfs_ondisk.h
> @@ -150,6 +150,7 @@ xfs_check_ondisk_structs(void)
>   	XFS_CHECK_STRUCT_SIZE(struct xfs_bulkstat,		192);
>   	XFS_CHECK_STRUCT_SIZE(struct xfs_inumbers,		24);
>   	XFS_CHECK_STRUCT_SIZE(struct xfs_bulkstat_req,		64);
> +	XFS_CHECK_STRUCT_SIZE(struct xfs_bulkstat_single_req,	224);
>   }
>   
>   #endif /* __XFS_ONDISK_H */
> 

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

* [PATCH 6/9] xfs: wire up the new v5 bulkstat_single ioctl
  2019-05-29 22:27 [PATCH 0/9] xfs: introduce new BULKSTAT and INUMBERS ioctls Darrick J. Wong
@ 2019-05-29 22:28 ` Darrick J. Wong
  2019-06-05 22:30   ` Allison Collins
  0 siblings, 1 reply; 34+ messages in thread
From: Darrick J. Wong @ 2019-05-29 22:28 UTC (permalink / raw)
  To: darrick.wong; +Cc: linux-xfs

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

Wire up the V5 BULKSTAT_SINGLE ioctl and rename the old one V1.

Signed-off-by: Darrick J. Wong <darrick.wong@oracle.com>
---
 fs/xfs/libxfs/xfs_fs.h |   16 +++++++++
 fs/xfs/xfs_ioctl.c     |   85 ++++++++++++++++++++++++++++++++++++++++++++++++
 fs/xfs/xfs_ioctl32.c   |    1 +
 fs/xfs/xfs_ondisk.h    |    1 +
 4 files changed, 103 insertions(+)


diff --git a/fs/xfs/libxfs/xfs_fs.h b/fs/xfs/libxfs/xfs_fs.h
index 960f3542e207..95d0411dae9b 100644
--- a/fs/xfs/libxfs/xfs_fs.h
+++ b/fs/xfs/libxfs/xfs_fs.h
@@ -468,6 +468,16 @@ struct xfs_bulk_ireq {
 
 #define XFS_BULK_IREQ_FLAGS_ALL	(0)
 
+/* Header for a single inode request. */
+struct xfs_ireq {
+	uint64_t	ino;		/* I/O: start with this inode	*/
+	uint32_t	flags;		/* I/O: operation flags		*/
+	uint32_t	reserved32;	/* must be zero			*/
+	uint64_t	reserved[2];	/* must be zero			*/
+};
+
+#define XFS_IREQ_FLAGS_ALL	(0)
+
 /*
  * ioctl structures for v5 bulkstat and inumbers requests
  */
@@ -478,6 +488,11 @@ struct xfs_bulkstat_req {
 #define XFS_BULKSTAT_REQ_SIZE(nr)	(sizeof(struct xfs_bulkstat_req) + \
 					 (nr) * sizeof(struct xfs_bulkstat))
 
+struct xfs_bulkstat_single_req {
+	struct xfs_ireq		hdr;
+	struct xfs_bulkstat	bulkstat;
+};
+
 /*
  * Error injection.
  */
@@ -780,6 +795,7 @@ struct xfs_scrub_metadata {
 #define XFS_IOC_GOINGDOWN	     _IOR ('X', 125, uint32_t)
 #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_BULKSTAT_SINGLE	     _IOR ('X', 128, struct xfs_bulkstat_single_req)
 /*	XFS_IOC_GETFSUUID ---------- deprecated 140	 */
 
 
diff --git a/fs/xfs/xfs_ioctl.c b/fs/xfs/xfs_ioctl.c
index f6724c75ba97..f6971eb9561e 100644
--- a/fs/xfs/xfs_ioctl.c
+++ b/fs/xfs/xfs_ioctl.c
@@ -923,6 +923,89 @@ xfs_ioc_bulkstat(
 	return 0;
 }
 
+/*
+ * Check the incoming singleton request @hdr from userspace and initialize the
+ * internal @breq bulk request appropriately.  Returns 0 if the bulk request
+ * should proceed; or the usual negative error code.
+ */
+static int
+xfs_ireq_setup(
+	struct xfs_mount	*mp,
+	struct xfs_ireq		*hdr,
+	struct xfs_ibulk	*breq,
+	void __user		*ubuffer)
+{
+	if ((hdr->flags & ~XFS_IREQ_FLAGS_ALL) ||
+	    hdr->reserved32 ||
+	    memchr_inv(hdr->reserved, 0, sizeof(hdr->reserved)))
+		return -EINVAL;
+
+	if (XFS_INO_TO_AGNO(mp, hdr->ino) >= mp->m_sb.sb_agcount)
+		return -EINVAL;
+
+	breq->ubuffer = ubuffer;
+	breq->icount = 1;
+	breq->startino = hdr->ino;
+	return 0;
+}
+
+/*
+ * Update the userspace singleton request @hdr to reflect the end state of the
+ * internal bulk request @breq.  If @error is negative then we return just
+ * that; otherwise we copy the state so that userspace can discover what
+ * happened.
+ */
+static int
+xfs_ireq_teardown(
+	struct xfs_ireq		*hdr,
+	struct xfs_ibulk	*breq,
+	int			error)
+{
+	if (error < 0)
+		return error;
+
+	hdr->ino = breq->startino;
+	return 0;
+}
+
+/* Handle the v5 bulkstat_single ioctl. */
+STATIC int
+xfs_ioc_bulkstat_single(
+	struct xfs_mount	*mp,
+	unsigned int		cmd,
+	struct xfs_bulkstat_single_req __user *arg)
+{
+	struct xfs_ireq		hdr;
+	struct xfs_ibulk	breq = {
+		.mp		= mp,
+	};
+	int			error;
+
+	if (!capable(CAP_SYS_ADMIN))
+		return -EPERM;
+
+	if (XFS_FORCED_SHUTDOWN(mp))
+		return -EIO;
+
+	if (copy_from_user(&hdr, &arg->hdr, sizeof(hdr)))
+		return -EFAULT;
+
+	error = xfs_ireq_setup(mp, &hdr, &breq, &arg->bulkstat);
+	if (error)
+		return error;
+
+	error = xfs_bulkstat_one(&breq, xfs_bulkstat_fmt);
+
+	error = xfs_ireq_teardown(&hdr, &breq, error);
+	if (error)
+		return error;
+
+	if (copy_to_user(&arg->hdr, &hdr, sizeof(hdr)))
+		return -EFAULT;
+
+	return 0;
+}
+
 STATIC int
 xfs_ioc_fsgeometry(
 	struct xfs_mount	*mp,
@@ -2089,6 +2172,8 @@ xfs_file_ioctl(
 
 	case XFS_IOC_BULKSTAT:
 		return xfs_ioc_bulkstat(mp, cmd, arg);
+	case XFS_IOC_BULKSTAT_SINGLE:
+		return xfs_ioc_bulkstat_single(mp, cmd, arg);
 
 	case XFS_IOC_FSGEOMETRY_V1:
 		return xfs_ioc_fsgeometry(mp, arg, 3);
diff --git a/fs/xfs/xfs_ioctl32.c b/fs/xfs/xfs_ioctl32.c
index 84c342be4536..08a90e3459d1 100644
--- a/fs/xfs/xfs_ioctl32.c
+++ b/fs/xfs/xfs_ioctl32.c
@@ -577,6 +577,7 @@ xfs_file_compat_ioctl(
 	case FS_IOC_GETFSMAP:
 	case XFS_IOC_SCRUB_METADATA:
 	case XFS_IOC_BULKSTAT:
+	case XFS_IOC_BULKSTAT_SINGLE:
 		return xfs_file_ioctl(filp, cmd, p);
 #if !defined(BROKEN_X86_ALIGNMENT) || defined(CONFIG_X86_X32)
 	/*
diff --git a/fs/xfs/xfs_ondisk.h b/fs/xfs/xfs_ondisk.h
index 954484c6eb96..fa1252657b08 100644
--- a/fs/xfs/xfs_ondisk.h
+++ b/fs/xfs/xfs_ondisk.h
@@ -150,6 +150,7 @@ xfs_check_ondisk_structs(void)
 	XFS_CHECK_STRUCT_SIZE(struct xfs_bulkstat,		192);
 	XFS_CHECK_STRUCT_SIZE(struct xfs_inumbers,		24);
 	XFS_CHECK_STRUCT_SIZE(struct xfs_bulkstat_req,		64);
+	XFS_CHECK_STRUCT_SIZE(struct xfs_bulkstat_single_req,	224);
 }
 
 #endif /* __XFS_ONDISK_H */

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

end of thread, other threads:[~2019-07-05 16:26 UTC | newest]

Thread overview: 34+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2019-06-26 20:45 [PATCH v6 0/9] xfs: introduce new BULKSTAT and INUMBERS ioctls Darrick J. Wong
2019-06-26 20:45 ` [PATCH 1/9] xfs: remove various bulk request typedef usage Darrick J. Wong
2019-07-03 13:22   ` Brian Foster
2019-06-26 20:45 ` [PATCH 2/9] xfs: rename bulkstat functions Darrick J. Wong
2019-07-03 13:22   ` Brian Foster
2019-06-26 20:45 ` [PATCH 3/9] xfs: introduce new v5 bulkstat structure Darrick J. Wong
2019-07-03 13:23   ` Brian Foster
2019-07-03 14:42     ` Darrick J. Wong
2019-07-03 15:32   ` [PATCH v2 " Darrick J. Wong
2019-07-03 16:31     ` Brian Foster
2019-06-26 20:45 ` [PATCH 4/9] xfs: introduce v5 inode group structure Darrick J. Wong
2019-07-03 13:23   ` Brian Foster
2019-06-26 20:46 ` [PATCH 5/9] xfs: wire up new v5 bulkstat ioctls Darrick J. Wong
2019-07-03 13:24   ` Brian Foster
2019-06-26 20:46 ` [PATCH 6/9] xfs: wire up the new v5 bulkstat_single ioctl Darrick J. Wong
2019-07-03 13:24   ` Brian Foster
2019-07-03 14:52     ` Darrick J. Wong
2019-07-03 16:11       ` Brian Foster
2019-07-03 20:01         ` Darrick J. Wong
2019-07-05 11:05           ` Brian Foster
2019-07-05 16:26             ` Darrick J. Wong
2019-06-26 20:46 ` [PATCH 7/9] xfs: wire up the v5 INUMBERS ioctl Darrick J. Wong
2019-07-03 13:24   ` Brian Foster
2019-06-26 20:46 ` [PATCH 8/9] xfs: specify AG in bulk req Darrick J. Wong
2019-07-03 13:25   ` Brian Foster
2019-06-26 20:46 ` [PATCH 9/9] xfs: allow bulkstat_single of special inodes Darrick J. Wong
2019-07-03 13:25   ` Brian Foster
2019-07-03 15:09     ` Darrick J. Wong
2019-07-03 15:34   ` [PATCH v2 " Darrick J. Wong
2019-07-03 16:32     ` Brian Foster
2019-07-04  6:51   ` [PATCH v3 " Darrick J. Wong
  -- strict thread matches above, loose matches on Subject: below --
2019-06-12  6:49 [PATCH v5 0/9] xfs: introduce new BULKSTAT and INUMBERS ioctls Darrick J. Wong
2019-06-12  6:49 ` [PATCH 6/9] xfs: wire up the new v5 bulkstat_single ioctl Darrick J. Wong
2019-05-29 22:27 [PATCH 0/9] xfs: introduce new BULKSTAT and INUMBERS ioctls Darrick J. Wong
2019-05-29 22:28 ` [PATCH 6/9] xfs: wire up the new v5 bulkstat_single ioctl Darrick J. Wong
2019-06-05 22:30   ` Allison Collins

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.