All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH 00/19 v2] mkfs cleaning
@ 2016-04-21  9:39 Jan Tulak
  2016-04-21  9:39 ` [PATCH 01/19] xfsprogs: use common code for multi-disk detection Jan Tulak
                   ` (21 more replies)
  0 siblings, 22 replies; 51+ messages in thread
From: Jan Tulak @ 2016-04-21  9:39 UTC (permalink / raw)
  To: xfs

Updated version. Most notable changes are dropping of
"xfsprogs: disable truncating of files", reverting 
"don't treat files as though they are block devices"
back to Dave's version, and adding a new patch
"mkfs: conflicting values with disabled crc should fail."


Dave Chinner (15):
  xfsprogs: use common code for multi-disk detection
  mkfs: sanitise ftype parameter values.
  mkfs: Sanitise the superblock feature macros
  mkfs: validate all input values
  mkfs: factor boolean option parsing
  mkfs: validate logarithmic parameters sanely
  mkfs: structify input parameter passing
  mkfs: getbool is redundant
  mkfs: use getnum_checked for all ranged parameters
  mkfs: add respecification detection to generic parsing
  mkfs: table based parsing for converted parameters
  mkfs: merge getnum
  mkfs: encode conflicts into parsing table
  mkfs: add string options to generic parsing
  mkfs: don't treat files as though they are block devices

Jan Tulak (4):
  mkfs: move spinodes crc check
  mkfs: unit conversions are case insensitive
  mkfs: add optional 'reason' for illegal_option
  mkfs: conflicting values with disabled crc should fail

 include/Makefile        |    5 +-
 include/xfs_multidisk.h |   73 ++
 libxfs/init.c           |    6 +
 libxfs/linux.c          |   11 +-
 man/man8/mkfs.xfs.8     |   45 +-
 mkfs/Makefile           |    2 +-
 mkfs/maxtrres.c         |    2 +-
 mkfs/proto.c            |   58 +-
 mkfs/xfs_mkfs.c         | 1983 +++++++++++++++++++++++++++++------------------
 mkfs/xfs_mkfs.h         |   89 ---
 repair/xfs_repair.c     |   44 +-
 11 files changed, 1417 insertions(+), 901 deletions(-)
 create mode 100644 include/xfs_multidisk.h
 delete mode 100644 mkfs/xfs_mkfs.h

-- 
2.5.0

_______________________________________________
xfs mailing list
xfs@oss.sgi.com
http://oss.sgi.com/mailman/listinfo/xfs

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

* [PATCH 01/19] xfsprogs: use common code for multi-disk detection
  2016-04-21  9:39 [PATCH 00/19 v2] mkfs cleaning Jan Tulak
@ 2016-04-21  9:39 ` Jan Tulak
  2016-04-21  9:39 ` [PATCH 02/19] mkfs: sanitise ftype parameter values Jan Tulak
                   ` (20 subsequent siblings)
  21 siblings, 0 replies; 51+ messages in thread
From: Jan Tulak @ 2016-04-21  9:39 UTC (permalink / raw)
  To: xfs

From: Dave Chinner <dchinner@redhat.com>

Both xfs_repair and mkfs.xfs need to agree on what is a "multidisk:
configuration - mkfs for determining the AG count of the filesystem,
repair for determining how to automatically parallelise it's
execution. This requires a bunch of common defines that both mkfs
and reapir need to share.

In fact, most of the defines in xfs_mkfs.h could be shared with
other programs (i.e. all the defaults mkfs uses) and so it is
simplest to move xfs_mkfs.h to the shared include directory and add
the new defines to it directly.

Signed-off-by: Dave Chinner <dchinner@redhat.com>
Signed-off-by: Jan Tulak <jtulak@redhat.com>
Reviewed-by: Eric Sandeen <sandeen@redhat.com>

---
CHANGELOG:
* Some comments made clear
---
 include/Makefile        |  5 ++-
 include/xfs_multidisk.h | 98 +++++++++++++++++++++++++++++++++++++++++++++++++
 mkfs/Makefile           |  2 +-
 mkfs/maxtrres.c         |  2 +-
 mkfs/proto.c            |  2 +-
 mkfs/xfs_mkfs.c         | 57 ++++++++++++++--------------
 mkfs/xfs_mkfs.h         | 89 --------------------------------------------
 repair/xfs_repair.c     | 44 +++++++++++++++++++++-
 8 files changed, 177 insertions(+), 122 deletions(-)
 create mode 100644 include/xfs_multidisk.h
 delete mode 100644 mkfs/xfs_mkfs.h

diff --git a/include/Makefile b/include/Makefile
index 6148756..5fb443a 100644
--- a/include/Makefile
+++ b/include/Makefile
@@ -33,13 +33,16 @@ LIBHFILES = libxfs.h \
 	xfs_log_recover.h \
 	xfs_metadump.h \
 	xfs_mount.h \
+	xfs_quota_defs.h \
+	xfs_sb.h \
+	xfs_shared.h \
 	xfs_trace.h \
 	xfs_trans.h \
 	command.h \
 	input.h \
 	path.h \
 	project.h \
-	platform_defs.h \
+	platform_defs.h
 
 HFILES = handle.h \
 	jdm.h \
diff --git a/include/xfs_multidisk.h b/include/xfs_multidisk.h
new file mode 100644
index 0000000..4b99992
--- /dev/null
+++ b/include/xfs_multidisk.h
@@ -0,0 +1,98 @@
+/*
+ * Copyright (c) 2000-2001,2004-2005 Silicon Graphics, Inc.
+ * All Rights Reserved.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it would be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write the Free Software Foundation,
+ * Inc.,  51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ */
+#ifndef __XFS_MULTIDISK_H__
+#define	__XFS_MULTIDISK_H__
+
+#define XFS_DFL_SB_VERSION_BITS \
+                (XFS_SB_VERSION_NLINKBIT | \
+                 XFS_SB_VERSION_EXTFLGBIT | \
+                 XFS_SB_VERSION_DIRV2BIT)
+
+#define XFS_SB_VERSION_MKFS(crc,ia,dia,log2,attr1,sflag,ci,more) (\
+	((crc)||(ia)||(dia)||(log2)||(attr1)||(sflag)||(ci)||(more)) ? \
+	(((crc) ? XFS_SB_VERSION_5 : XFS_SB_VERSION_4) |		\
+		((ia) ? XFS_SB_VERSION_ALIGNBIT : 0) |			\
+		((dia) ? XFS_SB_VERSION_DALIGNBIT : 0) |		\
+		((log2) ? XFS_SB_VERSION_LOGV2BIT : 0) |		\
+		((attr1) ? XFS_SB_VERSION_ATTRBIT : 0) |		\
+		((sflag) ? XFS_SB_VERSION_SECTORBIT : 0) |		\
+		((ci) ? XFS_SB_VERSION_BORGBIT : 0) |			\
+		((more) ? XFS_SB_VERSION_MOREBITSBIT : 0) |		\
+	        XFS_DFL_SB_VERSION_BITS |                               \
+	0 ) : XFS_SB_VERSION_1 )
+
+#define XFS_SB_VERSION2_MKFS(crc, lazycount, attr2, projid32bit, parent, \
+			     ftype) (\
+	((lazycount) ? XFS_SB_VERSION2_LAZYSBCOUNTBIT : 0) |		\
+	((attr2) ? XFS_SB_VERSION2_ATTR2BIT : 0) |			\
+	((projid32bit) ? XFS_SB_VERSION2_PROJID32BIT : 0) |		\
+	((parent) ? XFS_SB_VERSION2_PARENTBIT : 0) |			\
+	((crc) ? XFS_SB_VERSION2_CRCBIT : 0) |				\
+	((ftype) ? XFS_SB_VERSION2_FTYPE : 0) |				\
+	0 )
+
+#define	XFS_DFL_BLOCKSIZE_LOG	12		/* 4096 byte blocks */
+#define	XFS_DINODE_DFL_LOG	8		/* 256 byte inodes */
+#define	XFS_DINODE_DFL_CRC_LOG	9		/* 512 byte inodes for CRCs */
+#define	XFS_MIN_DATA_BLOCKS	100
+#define	XFS_MIN_INODE_PERBLOCK	2		/* min inodes per block */
+#define	XFS_DFL_IMAXIMUM_PCT	25		/* max % of space for inodes */
+#define	XFS_IFLAG_ALIGN		1		/* -i align defaults on */
+#define	XFS_MIN_REC_DIRSIZE	12		/* 4096 byte dirblocks (V2) */
+#define	XFS_DFL_DIR_VERSION	2		/* default directory version */
+#define	XFS_DFL_LOG_SIZE	1000		/* default log size, blocks */
+#define	XFS_DFL_LOG_FACTOR	5		/* default log size, factor */
+						/* with max trans reservation */
+#define XFS_MAX_INODE_SIG_BITS	32		/* most significant bits in an
+						 * inode number that we'll
+						 * accept w/o warnings
+						 */
+
+#define XFS_AG_BYTES(bblog)	((long long)BBSIZE << (bblog))
+#define	XFS_AG_MIN_BYTES	((XFS_AG_BYTES(15)))	/* 16 MB */
+#define XFS_AG_MIN_BLOCKS(blog)	((XFS_AG_BYTES(15)) >> (blog))
+#define XFS_AG_MAX_BLOCKS(blog)	((XFS_AG_BYTES(31) - 1) >> (blog))
+
+#define XFS_MAX_AGNUMBER	((xfs_agnumber_t)(NULLAGNUMBER - 1))
+
+/*
+ * These values define what we consider a "multi-disk" filesystem. That is, a
+ * filesystem that is likely to be made up of multiple devices, and hence have
+ * some level of parallelism available to it at the IO level.
+ */
+#define XFS_MULTIDISK_AGLOG		5	/* 32 AGs */
+#define XFS_NOMULTIDISK_AGLOG		2	/* 4 AGs */
+#define XFS_MULTIDISK_AGCOUNT		(1 << XFS_MULTIDISK_AGLOG)
+
+
+/* xfs_mkfs.c */
+extern int isdigits (char *str);
+extern long long cvtnum (unsigned int blocksize,
+			 unsigned int sectorsize, char *s);
+
+/* proto.c */
+extern char *setup_proto (char *fname);
+extern void parse_proto (xfs_mount_t *mp, struct fsxattr *fsx, char **pp);
+extern void res_failed (int err);
+
+/* maxtrres.c */
+extern int max_trans_res (int crcs_enabled, int dirversion,
+		int sectorlog, int blocklog, int inodelog, int dirblocklog,
+		int logversion, int log_sunit, int finobt);
+
+#endif	/* __XFS_MULTIDISK_H__ */
diff --git a/mkfs/Makefile b/mkfs/Makefile
index 570ab07..63ba4ec 100644
--- a/mkfs/Makefile
+++ b/mkfs/Makefile
@@ -7,7 +7,7 @@ include $(TOPDIR)/include/builddefs
 
 LTCOMMAND = mkfs.xfs
 
-HFILES = xfs_mkfs.h
+HFILES =
 CFILES = maxtrres.c proto.c xfs_mkfs.c
 
 LLDLIBS += $(LIBBLKID) $(LIBXFS) $(LIBUUID) $(LIBRT) $(LIBPTHREAD)
diff --git a/mkfs/maxtrres.c b/mkfs/maxtrres.c
index b97d020..f48a0f7 100644
--- a/mkfs/maxtrres.c
+++ b/mkfs/maxtrres.c
@@ -25,7 +25,7 @@
  */
 
 #include "libxfs.h"
-#include "xfs_mkfs.h"
+#include "xfs_multidisk.h"
 
 int
 max_trans_res(
diff --git a/mkfs/proto.c b/mkfs/proto.c
index d99e965..f3327d1 100644
--- a/mkfs/proto.c
+++ b/mkfs/proto.c
@@ -18,7 +18,7 @@
 
 #include "libxfs.h"
 #include <sys/stat.h>
-#include "xfs_mkfs.h"
+#include "xfs_multidisk.h"
 
 /*
  * Prototypes for internal functions.
diff --git a/mkfs/xfs_mkfs.c b/mkfs/xfs_mkfs.c
index 4c3a802..5527b87 100644
--- a/mkfs/xfs_mkfs.c
+++ b/mkfs/xfs_mkfs.c
@@ -21,7 +21,7 @@
 #ifdef ENABLE_BLKID
 #  include <blkid/blkid.h>
 #endif /* ENABLE_BLKID */
-#include "xfs_mkfs.h"
+#include "xfs_multidisk.h"
 
 /*
  * Device topology information.
@@ -664,43 +664,46 @@ calc_default_ag_geometry(
 	}
 
 	/*
-	 * For the remainder we choose an AG size based on the
-	 * number of data blocks available, trying to keep the
-	 * number of AGs relatively small (especially compared
-	 * to the original algorithm).  AG count is calculated
-	 * based on the preferred AG size, not vice-versa - the
-	 * count can be increased by growfs, so prefer to use
-	 * smaller counts at mkfs time.
-	 *
-	 * For a single underlying storage device between 128MB
-	 * and 4TB in size, just use 4 AGs, otherwise scale up
-	 * smoothly between min/max AG sizes.
+	 * For a single underlying storage device over 4TB in size
+	 * use the maximum AG size.  Between 128MB and 4TB, just use
+	 * 4 AGs and scale up smoothly between min/max AG sizes.
 	 */
-
-	if (!multidisk && dblocks >= MEGABYTES(128, blocklog)) {
+	if (!multidisk) {
 		if (dblocks >= TERABYTES(4, blocklog)) {
 			blocks = XFS_AG_MAX_BLOCKS(blocklog);
 			goto done;
+		} else if (dblocks >= MEGABYTES(128, blocklog)) {
+			shift = XFS_NOMULTIDISK_AGLOG;
+			goto calc_blocks;
 		}
-		shift = 2;
-	} else if (dblocks > GIGABYTES(512, blocklog))
-		shift = 5;
-	else if (dblocks > GIGABYTES(8, blocklog))
-		shift = 4;
-	else if (dblocks >= MEGABYTES(128, blocklog))
-		shift = 3;
-	else if (dblocks >= MEGABYTES(64, blocklog))
-		shift = 2;
-	else if (dblocks >= MEGABYTES(32, blocklog))
-		shift = 1;
-	else
-		shift = 0;
+	}
+
+	/*
+	 * For the multidisk configs we choose an AG count based on the number
+	 * of data blocks available, trying to keep the number of AGs higher
+	 * than the single disk configurations. This makes the assumption that
+	 * larger filesystems have more parallelism available to them.
+	 */
+	shift = XFS_MULTIDISK_AGLOG;
+	if (dblocks <= GIGABYTES(512, blocklog))
+		shift--;
+	if (dblocks <= GIGABYTES(8, blocklog))
+		shift--;
+	if (dblocks < MEGABYTES(128, blocklog))
+		shift--;
+	if (dblocks < MEGABYTES(64, blocklog))
+		shift--;
+	if (dblocks < MEGABYTES(32, blocklog))
+		shift--;
+
 	/*
 	 * If dblocks is not evenly divisible by the number of
 	 * desired AGs, round "blocks" up so we don't lose the
 	 * last bit of the filesystem. The same principle applies
 	 * to the AG count, so we don't lose the last AG!
 	 */
+calc_blocks:
+	ASSERT(shift >= 0 && shift <= XFS_MULTIDISK_AGLOG);
 	blocks = dblocks >> shift;
 	if (dblocks & xfs_mask32lo(shift)) {
 		if (blocks < XFS_AG_MAX_BLOCKS(blocklog))
diff --git a/mkfs/xfs_mkfs.h b/mkfs/xfs_mkfs.h
deleted file mode 100644
index 128068e..0000000
--- a/mkfs/xfs_mkfs.h
+++ /dev/null
@@ -1,89 +0,0 @@
-/*
- * Copyright (c) 2000-2001,2004-2005 Silicon Graphics, Inc.
- * All Rights Reserved.
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License as
- * published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it would be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write the Free Software Foundation,
- * Inc.,  51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
- */
-#ifndef __XFS_MKFS_H__
-#define	__XFS_MKFS_H__
-
-#define XFS_DFL_SB_VERSION_BITS \
-                (XFS_SB_VERSION_NLINKBIT | \
-                 XFS_SB_VERSION_EXTFLGBIT | \
-                 XFS_SB_VERSION_DIRV2BIT)
-
-#define XFS_SB_VERSION_MKFS(crc,ia,dia,log2,attr1,sflag,ci,more) (\
-	((crc)||(ia)||(dia)||(log2)||(attr1)||(sflag)||(ci)||(more)) ? \
-	(((crc) ? XFS_SB_VERSION_5 : XFS_SB_VERSION_4) |		\
-		((ia) ? XFS_SB_VERSION_ALIGNBIT : 0) |			\
-		((dia) ? XFS_SB_VERSION_DALIGNBIT : 0) |		\
-		((log2) ? XFS_SB_VERSION_LOGV2BIT : 0) |		\
-		((attr1) ? XFS_SB_VERSION_ATTRBIT : 0) |		\
-		((sflag) ? XFS_SB_VERSION_SECTORBIT : 0) |		\
-		((ci) ? XFS_SB_VERSION_BORGBIT : 0) |			\
-		((more) ? XFS_SB_VERSION_MOREBITSBIT : 0) |		\
-	        XFS_DFL_SB_VERSION_BITS |                               \
-	0 ) : XFS_SB_VERSION_1 )
-
-#define XFS_SB_VERSION2_MKFS(crc, lazycount, attr2, projid32bit, parent, \
-			     ftype) (\
-	((lazycount) ? XFS_SB_VERSION2_LAZYSBCOUNTBIT : 0) |		\
-	((attr2) ? XFS_SB_VERSION2_ATTR2BIT : 0) |			\
-	((projid32bit) ? XFS_SB_VERSION2_PROJID32BIT : 0) |		\
-	((parent) ? XFS_SB_VERSION2_PARENTBIT : 0) |			\
-	((crc) ? XFS_SB_VERSION2_CRCBIT : 0) |				\
-	((ftype) ? XFS_SB_VERSION2_FTYPE : 0) |				\
-	0 )
-
-#define	XFS_DFL_BLOCKSIZE_LOG	12		/* 4096 byte blocks */
-#define	XFS_DINODE_DFL_LOG	8		/* 256 byte inodes */
-#define	XFS_DINODE_DFL_CRC_LOG	9		/* 512 byte inodes for CRCs */
-#define	XFS_MIN_DATA_BLOCKS	100
-#define	XFS_MIN_INODE_PERBLOCK	2		/* min inodes per block */
-#define	XFS_DFL_IMAXIMUM_PCT	25		/* max % of space for inodes */
-#define	XFS_IFLAG_ALIGN		1		/* -i align defaults on */
-#define	XFS_MIN_REC_DIRSIZE	12		/* 4096 byte dirblocks (V2) */
-#define	XFS_DFL_DIR_VERSION	2		/* default directory version */
-#define	XFS_DFL_LOG_SIZE	1000		/* default log size, blocks */
-#define	XFS_DFL_LOG_FACTOR	5		/* default log size, factor */
-						/* with max trans reservation */
-#define XFS_MAX_INODE_SIG_BITS	32		/* most significant bits in an
-						 * inode number that we'll
-						 * accept w/o warnings
-						 */
-
-#define XFS_AG_BYTES(bblog)	((long long)BBSIZE << (bblog))
-#define	XFS_AG_MIN_BYTES	((XFS_AG_BYTES(15)))	/* 16 MB */
-#define XFS_AG_MIN_BLOCKS(blog)	((XFS_AG_BYTES(15)) >> (blog))
-#define XFS_AG_MAX_BLOCKS(blog)	((XFS_AG_BYTES(31) - 1) >> (blog))
-
-#define XFS_MAX_AGNUMBER	((xfs_agnumber_t)(NULLAGNUMBER - 1))
-
-
-/* xfs_mkfs.c */
-extern int isdigits (char *str);
-extern long long cvtnum (unsigned int blocksize,
-			 unsigned int sectorsize, char *s);
-
-/* proto.c */
-extern char *setup_proto (char *fname);
-extern void parse_proto (xfs_mount_t *mp, struct fsxattr *fsx, char **pp);
-extern void res_failed (int err);
-
-/* maxtrres.c */
-extern int max_trans_res (int crcs_enabled, int dirversion,
-		int sectorlog, int blocklog, int inodelog, int dirblocklog,
-		int logversion, int log_sunit, int finobt);
-
-#endif	/* __XFS_MKFS_H__ */
diff --git a/repair/xfs_repair.c b/repair/xfs_repair.c
index 5d5f3aa..9d91f2d 100644
--- a/repair/xfs_repair.c
+++ b/repair/xfs_repair.c
@@ -19,6 +19,7 @@
 #include "libxfs.h"
 #include "libxlog.h"
 #include <sys/resource.h>
+#include "xfs_multidisk.h"
 #include "avl.h"
 #include "avl64.h"
 #include "globals.h"
@@ -589,6 +590,33 @@ format_log_max_lsn(
 			 XLOG_FMT, new_cycle, true);
 }
 
+/*
+ * mkfs increases the AG count for "multidisk" configurations, we want
+ * to target these for an increase in thread count. Hence check the superlock
+ * geometry information to determine if mkfs considered this a multidisk
+ * configuration.
+ */
+static bool
+is_multidisk_filesystem(
+	struct xfs_mount	*mp)
+{
+	struct xfs_sb		*sbp = &mp->m_sb;
+
+	/* High agcount filesystems are always considered "multidisk" */
+	if (sbp->sb_agcount >= XFS_MULTIDISK_AGCOUNT)
+		return true;
+
+	/*
+	 * If it doesn't have a sunit/swidth, mkfs didn't consider it a
+	 * multi-disk array, so we don't either.
+	 */
+	if (!sbp->sb_unit)
+		return false;
+
+	ASSERT(sbp->sb_width);
+	return true;
+}
+
 int
 main(int argc, char **argv)
 {
@@ -729,9 +757,21 @@ main(int argc, char **argv)
 	 * threads/CPU as this is enough threads to saturate a CPU on fast
 	 * devices, yet few enough that it will saturate but won't overload slow
 	 * devices.
+	 *
+	 * Multidisk filesystems can handle more IO parallelism so we should try
+	 * to process multiple AGs at a time in such a configuration to try to
+	 * saturate the underlying storage and speed the repair process. Only do
+	 * this if prefetching is enabled.
 	 */
-	if (!ag_stride && glob_agcount >= 16 && do_prefetch)
-		ag_stride = 15;
+	if (!ag_stride && do_prefetch && is_multidisk_filesystem(mp)) {
+		/*
+		 * For small agcount multidisk systems, just double the
+		 * parallelism. For larger AG count filesystems (32 and above)
+		 * use more parallelism, and linearly increase the parallelism
+		 * with the number of AGs.
+		 */
+		ag_stride = min(glob_agcount, XFS_MULTIDISK_AGCOUNT / 2) - 1;
+	}
 
 	if (ag_stride) {
 		int max_threads = platform_nproc() * 8;
-- 
2.5.0

_______________________________________________
xfs mailing list
xfs@oss.sgi.com
http://oss.sgi.com/mailman/listinfo/xfs

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

* [PATCH 02/19] mkfs: sanitise ftype parameter values.
  2016-04-21  9:39 [PATCH 00/19 v2] mkfs cleaning Jan Tulak
  2016-04-21  9:39 ` [PATCH 01/19] xfsprogs: use common code for multi-disk detection Jan Tulak
@ 2016-04-21  9:39 ` Jan Tulak
  2016-04-21  9:39 ` [PATCH 03/19] mkfs: Sanitise the superblock feature macros Jan Tulak
                   ` (19 subsequent siblings)
  21 siblings, 0 replies; 51+ messages in thread
From: Jan Tulak @ 2016-04-21  9:39 UTC (permalink / raw)
  To: xfs

From: Dave Chinner <dchinner@redhat.com>

Because passing "-n ftype=2" should fail.

Signed-off-by: Dave Chinner <dchinner@redhat.com>
Signed-off-by: Jan Tulak <jtulak@redhat.com>

---
UPDATE:
* Remove a check for crc enabled with ftype - there is another one later on.
  As it was in the ftype handling, it failed if -m crc=0 was after ftype.
---
 mkfs/xfs_mkfs.c | 5 ++++-
 1 file changed, 4 insertions(+), 1 deletion(-)

diff --git a/mkfs/xfs_mkfs.c b/mkfs/xfs_mkfs.c
index 5527b87..4be14da 100644
--- a/mkfs/xfs_mkfs.c
+++ b/mkfs/xfs_mkfs.c
@@ -1597,7 +1597,10 @@ main(
 						reqval('n', nopts, N_FTYPE);
 					if (nftype)
 						respec('n', nopts, N_FTYPE);
-					dirftype = atoi(value);
+					c = atoi(value);
+					if (c < 0 || c > 1)
+						illegal(value, "n ftype");
+					dirftype = c;
 					nftype = 1;
 					break;
 				default:
-- 
2.5.0

_______________________________________________
xfs mailing list
xfs@oss.sgi.com
http://oss.sgi.com/mailman/listinfo/xfs

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

* [PATCH 03/19] mkfs: Sanitise the superblock feature macros
  2016-04-21  9:39 [PATCH 00/19 v2] mkfs cleaning Jan Tulak
  2016-04-21  9:39 ` [PATCH 01/19] xfsprogs: use common code for multi-disk detection Jan Tulak
  2016-04-21  9:39 ` [PATCH 02/19] mkfs: sanitise ftype parameter values Jan Tulak
@ 2016-04-21  9:39 ` Jan Tulak
  2016-05-02 23:06   ` Eric Sandeen
  2016-04-21  9:39 ` [PATCH 04/19] mkfs: validate all input values Jan Tulak
                   ` (18 subsequent siblings)
  21 siblings, 1 reply; 51+ messages in thread
From: Jan Tulak @ 2016-04-21  9:39 UTC (permalink / raw)
  To: xfs

From: Dave Chinner <dchinner@redhat.com>

They are horrible macros that simply obfuscate the code, so
let's factor the code and make them nice functions.

To do this, add a sb_feat_args structure that carries around the
variables rather than a strange assortment of variables. This means
all the default can be clearly defined in a structure
initialisation, and dependent feature bits are easy to check.

Signed-off-by: Dave Chinner <dchinner@redhat.com>
Signed-off-by: Jan Tulak <jtulak@redhat.com>

---
UPDATE
* if -m crc=0,finobt=1, simplify the condition
* remove a check for -m crc, -n ftype conflict causing a bug
* -i align should default to 1 is no value given
---
 include/xfs_multidisk.h |  25 +---
 mkfs/xfs_mkfs.c         | 295 +++++++++++++++++++++++++++++-------------------
 2 files changed, 183 insertions(+), 137 deletions(-)

diff --git a/include/xfs_multidisk.h b/include/xfs_multidisk.h
index 4b99992..11d6233 100644
--- a/include/xfs_multidisk.h
+++ b/include/xfs_multidisk.h
@@ -23,36 +23,13 @@
                  XFS_SB_VERSION_EXTFLGBIT | \
                  XFS_SB_VERSION_DIRV2BIT)
 
-#define XFS_SB_VERSION_MKFS(crc,ia,dia,log2,attr1,sflag,ci,more) (\
-	((crc)||(ia)||(dia)||(log2)||(attr1)||(sflag)||(ci)||(more)) ? \
-	(((crc) ? XFS_SB_VERSION_5 : XFS_SB_VERSION_4) |		\
-		((ia) ? XFS_SB_VERSION_ALIGNBIT : 0) |			\
-		((dia) ? XFS_SB_VERSION_DALIGNBIT : 0) |		\
-		((log2) ? XFS_SB_VERSION_LOGV2BIT : 0) |		\
-		((attr1) ? XFS_SB_VERSION_ATTRBIT : 0) |		\
-		((sflag) ? XFS_SB_VERSION_SECTORBIT : 0) |		\
-		((ci) ? XFS_SB_VERSION_BORGBIT : 0) |			\
-		((more) ? XFS_SB_VERSION_MOREBITSBIT : 0) |		\
-	        XFS_DFL_SB_VERSION_BITS |                               \
-	0 ) : XFS_SB_VERSION_1 )
-
-#define XFS_SB_VERSION2_MKFS(crc, lazycount, attr2, projid32bit, parent, \
-			     ftype) (\
-	((lazycount) ? XFS_SB_VERSION2_LAZYSBCOUNTBIT : 0) |		\
-	((attr2) ? XFS_SB_VERSION2_ATTR2BIT : 0) |			\
-	((projid32bit) ? XFS_SB_VERSION2_PROJID32BIT : 0) |		\
-	((parent) ? XFS_SB_VERSION2_PARENTBIT : 0) |			\
-	((crc) ? XFS_SB_VERSION2_CRCBIT : 0) |				\
-	((ftype) ? XFS_SB_VERSION2_FTYPE : 0) |				\
-	0 )
-
 #define	XFS_DFL_BLOCKSIZE_LOG	12		/* 4096 byte blocks */
 #define	XFS_DINODE_DFL_LOG	8		/* 256 byte inodes */
 #define	XFS_DINODE_DFL_CRC_LOG	9		/* 512 byte inodes for CRCs */
 #define	XFS_MIN_DATA_BLOCKS	100
 #define	XFS_MIN_INODE_PERBLOCK	2		/* min inodes per block */
 #define	XFS_DFL_IMAXIMUM_PCT	25		/* max % of space for inodes */
-#define	XFS_IFLAG_ALIGN		1		/* -i align defaults on */
+#define	XFS_IFLAG_ALIGN		true		/* -i align defaults on */
 #define	XFS_MIN_REC_DIRSIZE	12		/* 4096 byte dirblocks (V2) */
 #define	XFS_DFL_DIR_VERSION	2		/* default directory version */
 #define	XFS_DFL_LOG_SIZE	1000		/* default log size, blocks */
diff --git a/mkfs/xfs_mkfs.c b/mkfs/xfs_mkfs.c
index 4be14da..963545b 100644
--- a/mkfs/xfs_mkfs.c
+++ b/mkfs/xfs_mkfs.c
@@ -880,6 +880,109 @@ discard_blocks(dev_t dev, __uint64_t nsectors)
 		platform_discard_blocks(fd, 0, nsectors << 9);
 }
 
+struct sb_feat_args {
+	int	log_version;
+	int	attr_version;
+	int	dir_version;
+	int	spinodes;
+	int	finobt;
+	bool	finobtflag;
+	bool	inode_align;
+	bool	nci;
+	bool	lazy_sb_counters;
+	bool	projid16bit;
+	bool	crcs_enabled;
+	bool	dirftype;
+	bool	parent_pointers;
+};
+
+static void
+sb_set_features(
+	struct xfs_sb		*sbp,
+	struct sb_feat_args	*fp,
+	int			sectsize,
+	int			lsectsize,
+	int			dsunit)
+{
+
+	sbp->sb_versionnum = XFS_DFL_SB_VERSION_BITS;
+	if (fp->crcs_enabled)
+		sbp->sb_versionnum |= XFS_SB_VERSION_5;
+	else
+		sbp->sb_versionnum |= XFS_SB_VERSION_4;
+
+	if (fp->inode_align)
+		sbp->sb_versionnum |= XFS_SB_VERSION_ALIGNBIT;
+	if (dsunit)
+		sbp->sb_versionnum |= XFS_SB_VERSION_DALIGNBIT;
+	if (fp->log_version == 2)
+		sbp->sb_versionnum |= XFS_SB_VERSION_LOGV2BIT;
+	if (fp->attr_version == 1)
+		sbp->sb_versionnum |= XFS_SB_VERSION_ATTRBIT;
+	if (sectsize > BBSIZE || lsectsize > BBSIZE)
+		sbp->sb_versionnum |= XFS_SB_VERSION_SECTORBIT;
+	if (fp->nci)
+		sbp->sb_versionnum |= XFS_SB_VERSION_BORGBIT;
+
+
+	sbp->sb_features2 = 0;
+	if (fp->lazy_sb_counters)
+		sbp->sb_features2 |= XFS_SB_VERSION2_LAZYSBCOUNTBIT;
+	if (!fp->projid16bit)
+		sbp->sb_features2 |= XFS_SB_VERSION2_PROJID32BIT;
+	if (fp->parent_pointers)
+		sbp->sb_features2 |= XFS_SB_VERSION2_PARENTBIT;
+	if (fp->crcs_enabled)
+		sbp->sb_features2 |= XFS_SB_VERSION2_CRCBIT;
+	if (fp->attr_version == 2)
+		sbp->sb_features2 |= XFS_SB_VERSION2_ATTR2BIT;
+
+	/* v5 superblocks have their own feature bit for dirftype */
+	if (fp->dirftype && !fp->crcs_enabled)
+		sbp->sb_features2 |= XFS_SB_VERSION2_FTYPE;
+
+	/* update whether extended features are in use */
+	if (sbp->sb_features2 != 0)
+		sbp->sb_versionnum |= XFS_SB_VERSION_MOREBITSBIT;
+
+	/*
+	 * Due to a structure alignment issue, sb_features2 ended up in one
+	 * of two locations, the second "incorrect" location represented by
+	 * the sb_bad_features2 field. To avoid older kernels mounting
+	 * filesystems they shouldn't, set both field to the same value.
+	 */
+	sbp->sb_bad_features2 = sbp->sb_features2;
+
+	if (!fp->crcs_enabled)
+		return;
+
+	/* default features for v5 filesystems */
+	sbp->sb_features_compat = 0;
+	sbp->sb_features_ro_compat = 0;
+	sbp->sb_features_incompat = XFS_SB_FEAT_INCOMPAT_FTYPE;
+	sbp->sb_features_log_incompat = 0;
+
+	if (fp->finobt)
+		sbp->sb_features_ro_compat = XFS_SB_FEAT_RO_COMPAT_FINOBT;
+
+	/*
+	 * Sparse inode chunk support has two main inode alignment requirements.
+	 * First, sparse chunk alignment must match the cluster size. Second,
+	 * full chunk alignment must match the inode chunk size.
+	 *
+	 * Copy the already calculated/scaled inoalignmt to spino_align and
+	 * update the former to the full inode chunk size.
+	 */
+	if (fp->spinodes) {
+		sbp->sb_spino_align = sbp->sb_inoalignmt;
+		sbp->sb_inoalignmt = \
+			XFS_INODES_PER_CHUNK * \
+			sbp->sb_inodesize >> sbp->sb_blocklog;
+		sbp->sb_features_incompat |= XFS_SB_FEAT_INCOMPAT_SPINODES;
+	}
+
+}
+
 int
 main(
 	int			argc,
@@ -891,8 +994,6 @@ main(
 	xfs_agnumber_t		agno;
 	__uint64_t		agsize;
 	xfs_alloc_rec_t		*arec;
-	int			attrversion;
-	int			projid16bit;
 	struct xfs_btree_block	*block;
 	int			blflag;
 	int			blocklog;
@@ -907,8 +1008,6 @@ main(
 	char			*dfile;
 	int			dirblocklog;
 	int			dirblocksize;
-	int			dirftype;
-	int			dirversion;
 	char			*dsize;
 	int			dsu;
 	int			dsw;
@@ -916,7 +1015,6 @@ main(
 	int			dswidth;
 	int			force_overwrite;
 	struct fsxattr		fsx;
-	int			iaflag;
 	int			ilflag;
 	int			imaxpct;
 	int			imflag;
@@ -936,7 +1034,6 @@ main(
 	int			loginternal;
 	char			*logsize;
 	xfs_fsblock_t		logstart;
-	int			logversion;
 	int			lvflag;
 	int			lsflag;
 	int			lsuflag;
@@ -958,7 +1055,6 @@ main(
 	int			nftype;
 	int			nsflag;
 	int			nvflag;
-	int			nci;
 	int			Nflag;
 	int			discard = 1;
 	char			*p;
@@ -982,11 +1078,21 @@ main(
 	int			worst_freelist;
 	libxfs_init_t		xi;
 	struct fs_topology	ft;
-	int			lazy_sb_counters;
-	int			crcs_enabled;
-	int			finobt;
-	bool			finobtflag;
-	int			spinodes;
+	struct sb_feat_args	sb_feat = {
+		.finobt = 1,
+		.finobtflag = false,
+		.spinodes = 0,
+		.log_version = 2,
+		.attr_version = 2,
+		.dir_version = XFS_DFL_DIR_VERSION,
+		.inode_align = XFS_IFLAG_ALIGN,
+		.nci = false,
+		.lazy_sb_counters = true,
+		.projid16bit = false,
+		.crcs_enabled = true,
+		.dirftype = false,
+		.parent_pointers = false,
+	};
 
 	platform_uuid_generate(&uuid);
 	progname = basename(argv[0]);
@@ -994,8 +1100,6 @@ main(
 	bindtextdomain(PACKAGE, LOCALEDIR);
 	textdomain(PACKAGE);
 
-	attrversion = 2;
-	projid16bit = 0;
 	blflag = bsflag = slflag = ssflag = lslflag = lssflag = 0;
 	blocklog = blocksize = 0;
 	sectorlog = lsectorlog = XFS_MIN_SECTORSIZE_LOG;
@@ -1004,27 +1108,19 @@ main(
 	ilflag = imflag = ipflag = isflag = 0;
 	liflag = laflag = lsflag = lsuflag = lsunitflag = ldflag = lvflag = 0;
 	loginternal = 1;
-	logversion = 2;
 	logagno = logblocks = rtblocks = rtextblocks = 0;
-	Nflag = nlflag = nsflag = nvflag = nci = 0;
-	dirftype = 1;		/* inode type information in the dir */
+	sb_feat.dirftype = 1;		/* inode type information in the dir */
+	Nflag = nlflag = nsflag = nvflag = 0;
 	nftype = 0;
 	dirblocklog = dirblocksize = 0;
-	dirversion = XFS_DFL_DIR_VERSION;
 	qflag = 0;
 	imaxpct = inodelog = inopblock = isize = 0;
-	iaflag = XFS_IFLAG_ALIGN;
 	dfile = logfile = rtfile = NULL;
 	dsize = logsize = rtsize = rtextsize = protofile = NULL;
 	dsu = dsw = dsunit = dswidth = lalign = lsu = lsunit = 0;
 	nodsflag = norsflag = 0;
 	force_overwrite = 0;
 	worst_freelist = 0;
-	lazy_sb_counters = 1;
-	crcs_enabled = 1;
-	finobt = 1;
-	finobtflag = false;
-	spinodes = 0;
 	memset(&fsx, 0, sizeof(fsx));
 
 	memset(&xi, 0, sizeof(xi));
@@ -1264,9 +1360,10 @@ main(
 				case I_ALIGN:
 					if (!value || *value == '\0')
 						value = "1";
-					iaflag = atoi(value);
-					if (iaflag < 0 || iaflag > 1)
+					c = atoi(value);
+					if (c < 0 || c > 1)
 						illegal(value, "i align");
+					sb_feat.inode_align = c ? true : false;
 					break;
 				case I_LOG:
 					if (!value || *value == '\0')
@@ -1336,7 +1433,7 @@ main(
 					c = atoi(value);
 					if (c < 0 || c > 2)
 						illegal(value, "i attr");
-					attrversion = c;
+					sb_feat.attr_version = c;
 					break;
 				case I_PROJID32BIT:
 					if (!value || *value == '\0')
@@ -1344,14 +1441,15 @@ main(
 					c = atoi(value);
 					if (c < 0 || c > 1)
 						illegal(value, "i projid32bit");
-					projid16bit = c ? 0 : 1;
+					sb_feat.projid16bit = c ? false : true;
 					break;
 				case I_SPINODES:
 					if (!value || *value == '\0')
 						value = "1";
-					spinodes = atoi(value);
-					if (spinodes < 0 || spinodes > 1)
+					c = atoi(value);
+					if (c < 0 || c > 1)
 						illegal(value, "i spinodes");
+					sb_feat.spinodes = c;
 					break;
 				default:
 					unknown('i', value);
@@ -1443,9 +1541,10 @@ main(
 						reqval('l', lopts, L_VERSION);
 					if (lvflag)
 						respec('l', lopts, L_VERSION);
-					logversion = atoi(value);
-					if (logversion < 1 || logversion > 2)
+					c = atoi(value);
+					if (c < 1 || c > 2)
 						illegal(value, "l version");
+					sb_feat.log_version = c;
 					lvflag = 1;
 					break;
 				case L_SIZE:
@@ -1494,7 +1593,8 @@ main(
 					c = atoi(value);
 					if (c < 0 || c > 1)
 						illegal(value, "l lazy-count");
-					lazy_sb_counters = c;
+					sb_feat.lazy_sb_counters = c ? true
+								     : false;
 					break;
 				default:
 					unknown('l', value);
@@ -1518,7 +1618,9 @@ main(
 					c = atoi(value);
 					if (c < 0 || c > 1)
 						illegal(value, "m crc");
-					crcs_enabled = c;
+					sb_feat.crcs_enabled = c ? true : false;
+					if (c)
+						sb_feat.dirftype = true;
 					break;
 				case M_FINOBT:
 					if (!value || *value == '\0')
@@ -1526,8 +1628,8 @@ main(
 					c = atoi(value);
 					if (c < 0 || c > 1)
 						illegal(value, "m finobt");
-					finobt = c;
-					finobtflag = true;
+					sb_feat.finobtflag = true;
+					sb_feat.finobt = c;
 					break;
 				case M_UUID:
 					if (!value || *value == '\0')
@@ -1583,12 +1685,14 @@ main(
 					if (nvflag)
 						respec('n', nopts, N_VERSION);
 					if (!strcasecmp(value, "ci")) {
-						nci = 1; /* ASCII CI mode */
+						/* ASCII CI mode */
+						sb_feat.nci = true;
 					} else {
-						dirversion = atoi(value);
-						if (dirversion != 2)
+						c = atoi(value);
+						if (c != 2)
 							illegal(value,
 								"n version");
+						sb_feat.dir_version = c;
 					}
 					nvflag = 1;
 					break;
@@ -1600,7 +1704,7 @@ main(
 					c = atoi(value);
 					if (c < 0 || c > 1)
 						illegal(value, "n ftype");
-					dirftype = c;
+					sb_feat.dirftype = c ? true : false;
 					nftype = 1;
 					break;
 				default:
@@ -1749,13 +1853,13 @@ main(
 		fprintf(stderr, _("illegal block size %d\n"), blocksize);
 		usage();
 	}
-	if (crcs_enabled && blocksize < XFS_MIN_CRC_BLOCKSIZE) {
+	if (sb_feat.crcs_enabled && blocksize < XFS_MIN_CRC_BLOCKSIZE) {
 		fprintf(stderr,
 _("Minimum block size for CRC enabled filesystems is %d bytes.\n"),
 			XFS_MIN_CRC_BLOCKSIZE);
 		usage();
 	}
-	if (crcs_enabled && !dirftype) {
+	if (sb_feat.crcs_enabled && !sb_feat.dirftype) {
 		fprintf(stderr, _("cannot disable ftype with crcs enabled\n"));
 		usage();
 	}
@@ -1820,7 +1924,7 @@ _("block size %d cannot be smaller than logical sector size %d\n"),
 		usage();
 	} else if (lsectorsize > XFS_MIN_SECTORSIZE && !lsu && !lsunit) {
 		lsu = blocksize;
-		logversion = 2;
+		sb_feat.log_version = 2;
 	}
 
 	/*
@@ -1828,7 +1932,7 @@ _("block size %d cannot be smaller than logical sector size %d\n"),
 	 * no longer optional for CRC enabled filesystems.  Catch them up front
 	 * here before doing anything else.
 	 */
-	if (crcs_enabled) {
+	if (sb_feat.crcs_enabled) {
 		/* minimum inode size is 512 bytes, ipflag checked later */
 		if ((isflag || ilflag) && inodelog < XFS_DINODE_DFL_CRC_LOG) {
 			fprintf(stderr,
@@ -1838,28 +1942,28 @@ _("Minimum inode size for CRCs is %d bytes\n"),
 		}
 
 		/* inodes always aligned */
-		if (iaflag != 1) {
+		if (!sb_feat.inode_align) {
 			fprintf(stderr,
 _("Inodes always aligned for CRC enabled filesytems\n"));
 			usage();
 		}
 
 		/* lazy sb counters always on */
-		if (lazy_sb_counters != 1) {
+		if (!sb_feat.lazy_sb_counters) {
 			fprintf(stderr,
 _("Lazy superblock counted always enabled for CRC enabled filesytems\n"));
 			usage();
 		}
 
 		/* version 2 logs always on */
-		if (logversion != 2) {
+		if (sb_feat.log_version != 2) {
 			fprintf(stderr,
 _("V2 logs always enabled for CRC enabled filesytems\n"));
 			usage();
 		}
 
 		/* attr2 always on */
-		if (attrversion != 2) {
+		if (sb_feat.attr_version != 2) {
 			fprintf(stderr,
 _("V2 attribute format always enabled on CRC enabled filesytems\n"));
 			usage();
@@ -1867,7 +1971,7 @@ _("V2 attribute format always enabled on CRC enabled filesytems\n"));
 
 		/* 32 bit project quota always on */
 		/* attr2 always on */
-		if (projid16bit == 1) {
+		if (sb_feat.projid16bit) {
 			fprintf(stderr,
 _("32 bit Project IDs always enabled on CRC enabled filesytems\n"));
 			usage();
@@ -1881,17 +1985,17 @@ _("32 bit Project IDs always enabled on CRC enabled filesytems\n"));
 		 * tried to use crc=0,finobt=1, then issue a warning before
 		 * turning them off.
 		 */
-		if (finobt && finobtflag) {
+		if (sb_feat.finobt && sb_feat.finobtflag) {
 			fprintf(stderr,
 _("warning: finobt not supported without CRC support, disabled.\n"));
 		}
-		finobt = 0;
+		sb_feat.finobt = 0;
 	}
 
-	if (spinodes && !crcs_enabled) {
+	if (sb_feat.spinodes && !sb_feat.crcs_enabled) {
 		fprintf(stderr,
 _("warning: sparse inodes not supported without CRC support, disabled.\n"));
-		spinodes = 0;
+		sb_feat.spinodes = 0;
 	}
 
 	if (nsflag || nlflag) {
@@ -1941,11 +2045,11 @@ _("warning: sparse inodes not supported without CRC support, disabled.\n"));
 		inodelog = blocklog - libxfs_highbit32(inopblock);
 		isize = 1 << inodelog;
 	} else if (!ilflag && !isflag) {
-		inodelog = crcs_enabled ? XFS_DINODE_DFL_CRC_LOG
-					: XFS_DINODE_DFL_LOG;
+		inodelog = sb_feat.crcs_enabled ? XFS_DINODE_DFL_CRC_LOG
+						: XFS_DINODE_DFL_LOG;
 		isize = 1 << inodelog;
 	}
-	if (crcs_enabled && inodelog < XFS_DINODE_DFL_CRC_LOG) {
+	if (sb_feat.crcs_enabled && inodelog < XFS_DINODE_DFL_CRC_LOG) {
 		fprintf(stderr,
 		_("Minimum inode size for CRCs is %d bytes\n"),
 			1 << XFS_DINODE_DFL_CRC_LOG);
@@ -2075,10 +2179,10 @@ _("warning: sparse inodes not supported without CRC support, disabled.\n"));
 	}
 
 	/* if lsu or lsunit was specified, automatically use v2 logs */
-	if ((lsu || lsunit) && logversion == 1) {
+	if ((lsu || lsunit) && sb_feat.log_version == 1) {
 		fprintf(stderr,
 			_("log stripe unit specified, using v2 logs\n"));
-		logversion = 2;
+		sb_feat.log_version = 2;
 	}
 
 	calc_stripe_factors(dsu, dsw, sectorsize, lsu, lsectorsize,
@@ -2393,12 +2497,12 @@ an AG size that is one stripe unit smaller, for example %llu.\n"),
 		}
 		/* convert from 512 byte blocks to fs blocks */
 		lsunit = DTOBT(lsunit);
-	} else if (logversion == 2 && loginternal && dsunit) {
+	} else if (sb_feat.log_version == 2 && loginternal && dsunit) {
 		/* lsunit and dsunit now in fs blocks */
 		lsunit = dsunit;
 	}
 
-	if (logversion == 2 && (lsunit * blocksize) > 256 * 1024) {
+	if (sb_feat.log_version == 2 && (lsunit * blocksize) > 256 * 1024) {
 		/* Warn only if specified on commandline */
 		if (lsuflag || lsunitflag) {
 			fprintf(stderr,
@@ -2410,9 +2514,9 @@ an AG size that is one stripe unit smaller, for example %llu.\n"),
 		lsunit = (32 * 1024) >> blocklog;
 	}
 
-	min_logblocks = max_trans_res(crcs_enabled, dirversion,
+	min_logblocks = max_trans_res(sb_feat.crcs_enabled, sb_feat.dir_version,
 				   sectorlog, blocklog, inodelog, dirblocklog,
-				   logversion, lsunit, finobt);
+				   sb_feat.log_version, lsunit, sb_feat.finobt);
 	ASSERT(min_logblocks);
 	min_logblocks = MAX(XFS_MIN_LOG_BLOCKS, min_logblocks);
 	if (!logsize && dblocks >= (1024*1024*1024) >> blocklog)
@@ -2490,25 +2594,8 @@ _("size %s specified for log subvolume is too large, maximum is %lld blocks\n"),
 	 * sb_versionnum and finobt flags must be set before we use
 	 * XFS_PREALLOC_BLOCKS().
 	 */
-	sbp->sb_features2 = XFS_SB_VERSION2_MKFS(crcs_enabled, lazy_sb_counters,
-					attrversion == 2, !projid16bit, 0,
-					(!crcs_enabled && dirftype));
-	sbp->sb_versionnum = XFS_SB_VERSION_MKFS(crcs_enabled, iaflag,
-					dsunit != 0,
-					logversion == 2, attrversion == 1,
-					(sectorsize != BBSIZE ||
-							lsectorsize != BBSIZE),
-					nci, sbp->sb_features2 != 0);
-	/*
-	 * Due to a structure alignment issue, sb_features2 ended up in one
-	 * of two locations, the second "incorrect" location represented by
-	 * the sb_bad_features2 field. To avoid older kernels mounting
-	 * filesystems they shouldn't, set both field to the same value.
-	 */
-	sbp->sb_bad_features2 = sbp->sb_features2;
+	sb_set_features(&mp->m_sb, &sb_feat, sectorsize, lsectorsize, dsunit);
 
-	if (finobt)
-		sbp->sb_features_ro_compat = XFS_SB_FEAT_RO_COMPAT_FINOBT;
 
 	if (loginternal) {
 		/*
@@ -2560,14 +2647,6 @@ _("size %s specified for log subvolume is too large, maximum is %lld blocks\n"),
 	}
 	validate_log_size(logblocks, blocklog, min_logblocks);
 
-	/*
-	 * dirent filetype field always enabled on v5 superblocks
-	 */
-	if (crcs_enabled) {
-		sbp->sb_features_incompat = XFS_SB_FEAT_INCOMPAT_FTYPE;
-		dirftype = 1;
-	}
-
 	if (!qflag || Nflag) {
 		printf(_(
 		   "meta-data=%-22s isize=%-6d agcount=%lld, agsize=%lld blks\n"
@@ -2580,13 +2659,16 @@ _("size %s specified for log subvolume is too large, maximum is %lld blocks\n"),
 		   "         =%-22s sectsz=%-5u sunit=%d blks, lazy-count=%d\n"
 		   "realtime =%-22s extsz=%-6d blocks=%lld, rtextents=%lld\n"),
 			dfile, isize, (long long)agcount, (long long)agsize,
-			"", sectorsize, attrversion, !projid16bit,
-			"", crcs_enabled, finobt, spinodes,
+			"", sectorsize, sb_feat.attr_version,
+				    !sb_feat.projid16bit,
+			"", sb_feat.crcs_enabled, sb_feat.finobt, sb_feat.spinodes,
 			"", blocksize, (long long)dblocks, imaxpct,
 			"", dsunit, dswidth,
-			dirversion, dirblocksize, nci, dirftype,
+			sb_feat.dir_version, dirblocksize, sb_feat.nci,
+				sb_feat.dirftype,
 			logfile, 1 << blocklog, (long long)logblocks,
-			logversion, "", lsectorsize, lsunit, lazy_sb_counters,
+			sb_feat.log_version, "", lsectorsize, lsunit,
+				sb_feat.lazy_sb_counters,
 			rtfile, rtextblocks << blocklog,
 			(long long)rtblocks, (long long)rtextents);
 		if (Nflag)
@@ -2630,17 +2712,17 @@ _("size %s specified for log subvolume is too large, maximum is %lld blocks\n"),
 	sbp->sb_unit = dsunit;
 	sbp->sb_width = dswidth;
 	sbp->sb_dirblklog = dirblocklog - blocklog;
-	if (logversion == 2) {	/* This is stored in bytes */
+	if (sb_feat.log_version == 2) {	/* This is stored in bytes */
 		lsunit = (lsunit == 0) ? 1 : XFS_FSB_TO_B(mp, lsunit);
 		sbp->sb_logsunit = lsunit;
 	} else
 		sbp->sb_logsunit = 0;
-	if (iaflag) {
+	if (sb_feat.inode_align) {
 		int	cluster_size = XFS_INODE_BIG_CLUSTER_SIZE;
-		if (crcs_enabled)
+		if (sb_feat.crcs_enabled)
 			cluster_size *= isize / XFS_DINODE_MIN_SIZE;
 		sbp->sb_inoalignmt = cluster_size >> blocklog;
-		iaflag = sbp->sb_inoalignmt != 0;
+		sb_feat.inode_align = sbp->sb_inoalignmt != 0;
 	} else
 		sbp->sb_inoalignmt = 0;
 	if (lsectorsize != BBSIZE || sectorsize != BBSIZE) {
@@ -2651,19 +2733,7 @@ _("size %s specified for log subvolume is too large, maximum is %lld blocks\n"),
 		sbp->sb_logsectsize = 0;
 	}
 
-	/*
-	 * Sparse inode chunk support has two main inode alignment requirements.
-	 * First, sparse chunk alignment must match the cluster size. Second,
-	 * full chunk alignment must match the inode chunk size.
-	 *
-	 * Copy the already calculated/scaled inoalignmt to spino_align and
-	 * update the former to the full inode chunk size.
-	 */
-	if (spinodes) {
-		sbp->sb_spino_align = sbp->sb_inoalignmt;
-		sbp->sb_inoalignmt = XFS_INODES_PER_CHUNK * isize >> blocklog;
-		sbp->sb_features_incompat |= XFS_SB_FEAT_INCOMPAT_SPINODES;
-	}
+	sb_set_features(&mp->m_sb, &sb_feat, sectorsize, lsectorsize, dsunit);
 
 	if (force_overwrite)
 		zero_old_xfs_structures(&xi, sbp);
@@ -2719,8 +2789,7 @@ _("size %s specified for log subvolume is too large, maximum is %lld blocks\n"),
 	libxfs_log_clear(mp->m_logdev_targp, NULL,
 		XFS_FSB_TO_DADDR(mp, logstart),
 		(xfs_extlen_t)XFS_FSB_TO_BB(mp, logblocks),
-		&sbp->sb_uuid, logversion, lsunit, XLOG_FMT, XLOG_INIT_CYCLE,
-		false);
+		&sbp->sb_uuid, sb_feat.log_version, lsunit, XLOG_FMT, XLOG_INIT_CYCLE, false);
 
 	mp = libxfs_mount(mp, sbp, xi.ddev, xi.logdev, xi.rtdev, 0);
 	if (mp == NULL) {
@@ -2825,7 +2894,7 @@ _("size %s specified for log subvolume is too large, maximum is %lld blocks\n"),
 		agi->agi_count = 0;
 		agi->agi_root = cpu_to_be32(XFS_IBT_BLOCK(mp));
 		agi->agi_level = cpu_to_be32(1);
-		if (finobt) {
+		if (sb_feat.finobt) {
 			agi->agi_free_root = cpu_to_be32(XFS_FIBT_BLOCK(mp));
 			agi->agi_free_level = cpu_to_be32(1);
 		}
@@ -2958,7 +3027,7 @@ _("size %s specified for log subvolume is too large, maximum is %lld blocks\n"),
 		/*
 		 * Free INO btree root block
 		 */
-		if (!finobt) {
+		if (!sb_feat.finobt) {
 			xfs_perag_put(pag);
 			continue;
 		}
-- 
2.5.0

_______________________________________________
xfs mailing list
xfs@oss.sgi.com
http://oss.sgi.com/mailman/listinfo/xfs

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

* [PATCH 04/19] mkfs: validate all input values
  2016-04-21  9:39 [PATCH 00/19 v2] mkfs cleaning Jan Tulak
                   ` (2 preceding siblings ...)
  2016-04-21  9:39 ` [PATCH 03/19] mkfs: Sanitise the superblock feature macros Jan Tulak
@ 2016-04-21  9:39 ` Jan Tulak
  2016-04-21  9:39 ` [PATCH 05/19] mkfs: factor boolean option parsing Jan Tulak
                   ` (17 subsequent siblings)
  21 siblings, 0 replies; 51+ messages in thread
From: Jan Tulak @ 2016-04-21  9:39 UTC (permalink / raw)
  To: xfs

From: Dave Chinner <dchinner@redhat.com>

Right now, mkfs does a poor job of input validation of values. Many
parameters do not check for trailing garbage and so will pass
obviously invalid values as OK. Some don't even detect completely
invalid values, leaving it for other checks later on to fail due to
a bad value conversion - these tend to rely on atoi() implicitly
returning a sane value when it is passed garbage, and atoi gives no
guarantee of the return value when passed garbage.

Clean all this up by passing all strings that need to be converted
into values into a common function that is called regardless of
whether unit conversion is needed or not. Further, make sure every
conversion is checked for a valid result, and abort the moment an
invalid value is detected.

Get rid of the silly "isdigits(), cvtnum()" calls which don't use
any of the conversion capabilities of cvtnum() because we've already
ensured that there are no conversion units in the string via the
isdigits() call. These can simply be replaced by a standard
strtoll() call followed by checking for no trailing bytes.

Finally, the block size of the filesystem is not known until all
the options have been parsed and we can determine if the default is
to be used. This means any parameter that relies on using conversion
from filesystem block size (the "NNNb" format) requires the block
size to first be specified on the command line so it is known.

Similarly, we make the same rule for specifying counts in sectors.
This is a change from the existing behaviour that assumes sectors
are 512 bytes unless otherwise changed on the command line. This,
unfortunately, leads to complete silliness where you can specify the
sector size as a count of sectors. It also means that you can do
some conversions with 512 byte sector sizes, and others with
whatever was specified on the command line, meaning the mkfs
behaviour changes depending in where in the command line the sector
size is changed....

Signed-off-by: Dave Chinner <dchinner@redhat.com>
Signed-off-by: Jan Tulak <jtulak@redhat.com>

---
CHANGES:
* cast logagno to __int64_t for test, instead of long long
---
 include/xfs_multidisk.h |   7 +-
 man/man8/mkfs.xfs.8     |  26 +++++-
 mkfs/proto.c            |  36 ++++----
 mkfs/xfs_mkfs.c         | 215 +++++++++++++++++++++++++-----------------------
 4 files changed, 153 insertions(+), 131 deletions(-)

diff --git a/include/xfs_multidisk.h b/include/xfs_multidisk.h
index 11d6233..3e892d5 100644
--- a/include/xfs_multidisk.h
+++ b/include/xfs_multidisk.h
@@ -56,11 +56,8 @@
 #define XFS_NOMULTIDISK_AGLOG		2	/* 4 AGs */
 #define XFS_MULTIDISK_AGCOUNT		(1 << XFS_MULTIDISK_AGLOG)
 
-
-/* xfs_mkfs.c */
-extern int isdigits (char *str);
-extern long long cvtnum (unsigned int blocksize,
-			 unsigned int sectorsize, char *s);
+extern long long getnum(const char *str, unsigned int blocksize,
+			unsigned int sectorsize, bool convert);
 
 /* proto.c */
 extern char *setup_proto (char *fname);
diff --git a/man/man8/mkfs.xfs.8 b/man/man8/mkfs.xfs.8
index 980c7bc..8b068ef 100644
--- a/man/man8/mkfs.xfs.8
+++ b/man/man8/mkfs.xfs.8
@@ -64,11 +64,11 @@ SCSI disk, use:
 .PP
 The metadata log can be placed on another device to reduce the number
 of disk seeks.  To create a filesystem on the first partition on the
-first SCSI disk with a 10000 block log located on the first partition
+first SCSI disk with a 10MiB log located on the first partition
 on the second SCSI disk, use:
 .RS
 .HP
-.B mkfs.xfs\ \-l\ logdev=/dev/sdb1,size=10000b /dev/sda1
+.B mkfs.xfs\ \-l\ logdev=/dev/sdb1,size=10m /dev/sda1
 .RE
 .PP
 Each of the
@@ -78,9 +78,9 @@ suboptions if multiple suboptions apply to the same option.
 Equivalently, each main option can be given multiple times with
 different suboptions.
 For example,
-.B \-l internal,size=10000b
+.B \-l internal,size=10m
 and
-.B \-l internal \-l size=10000b
+.B \-l internal \-l size=10m
 are equivalent.
 .PP
 In the descriptions below, sizes are given in sectors, bytes, blocks,
@@ -109,6 +109,15 @@ option below).
 .HP
 .BR e "\ \-\ multiply by one exabyte (1,048,576 terabytes)."
 .PD
+.RE
+.PP
+When specifying parameters in units of sectors or filesystem blocks, the
+.B \-s
+option or the
+.B \-b
+option first needs to be added to the command line.
+Failure to specify the size of the units will result in illegal value errors
+when parameters are quantified in those units.
 .SH OPTIONS
 .TP
 .BI \-b " block_size_options"
@@ -126,6 +135,11 @@ or in bytes with
 .BR size= .
 The default value is 4096 bytes (4 KiB), the minimum is 512, and the
 maximum is 65536 (64 KiB).
+.IP
+To specify any options on the command line in units of filesystem blocks, this
+option must be specified first so that the filesystem block size is
+applied consistently to all options.
+.IP
 Although
 .B mkfs.xfs
 will accept any of these values and create a valid filesystem,
@@ -811,6 +825,10 @@ is 512 bytes. The minimum value for sector size is
 .I sector_size
 must be a power of 2 size and cannot be made larger than the
 filesystem block size.
+.IP
+To specify any options on the command line in units of sectors, this
+option must be specified first so that the sector size is
+applied consistently to all options.
 .TP
 .BI \-L " label"
 Set the filesystem
diff --git a/mkfs/proto.c b/mkfs/proto.c
index f3327d1..19943cb 100644
--- a/mkfs/proto.c
+++ b/mkfs/proto.c
@@ -23,7 +23,6 @@
 /*
  * Prototypes for internal functions.
  */
-static long getnum(char **pp);
 static char *getstr(char **pp);
 static void fail(char *msg, int i);
 static void getres(xfs_trans_t *tp, uint blocks);
@@ -78,8 +77,8 @@ setup_proto(
 	 * Skip past the stuff there for compatibility, a string and 2 numbers.
 	 */
 	(void)getstr(&buf);	/* boot image name */
-	(void)getnum(&buf);	/* block count */
-	(void)getnum(&buf);	/* inode count */
+	(void)getnum(getstr(&buf), 0, 0, false);	/* block count */
+	(void)getnum(getstr(&buf), 0, 0, false);	/* inode count */
 	close(fd);
 	return buf;
 
@@ -90,16 +89,6 @@ out_fail:
 	exit(1);
 }
 
-static long
-getnum(
-	char	**pp)
-{
-	char	*s;
-
-	s = getstr(pp);
-	return atol(s);
-}
-
 static void
 fail(
 	char	*msg,
@@ -440,8 +429,8 @@ parseproto(
 		val = val * 8 + mstr[i] - '0';
 	}
 	mode |= val;
-	creds.cr_uid = (int)getnum(pp);
-	creds.cr_gid = (int)getnum(pp);
+	creds.cr_uid = (int)getnum(getstr(pp), 0, 0, false);
+	creds.cr_gid = (int)getnum(getstr(pp), 0, 0, false);
 	xname.name = (unsigned char *)name;
 	xname.len = name ? strlen(name) : 0;
 	xname.type = 0;
@@ -466,7 +455,14 @@ parseproto(
 
 	case IF_RESERVED:			/* pre-allocated space only */
 		value = getstr(pp);
-		llen = cvtnum(mp->m_sb.sb_blocksize, mp->m_sb.sb_sectsize, value);
+		llen = getnum(value, mp->m_sb.sb_blocksize,
+			      mp->m_sb.sb_sectsize, true);
+		if (llen < 0) {
+			fprintf(stderr,
+				_("%s: Bad value %s for proto file %s\n"),
+				progname, value, name);
+			exit(1);
+		}
 		getres(tp, XFS_B_TO_FSB(mp, llen));
 
 		error = -libxfs_inode_alloc(&tp, pip, mode|S_IFREG, 1, 0,
@@ -490,8 +486,8 @@ parseproto(
 
 	case IF_BLOCK:
 		getres(tp, 0);
-		majdev = (int)getnum(pp);
-		mindev = (int)getnum(pp);
+		majdev = getnum(getstr(pp), 0, 0, false);
+		mindev = getnum(getstr(pp), 0, 0, false);
 		error = -libxfs_inode_alloc(&tp, pip, mode|S_IFBLK, 1,
 				IRIX_MKDEV(majdev, mindev), &creds, fsxp, &ip);
 		if (error) {
@@ -505,8 +501,8 @@ parseproto(
 
 	case IF_CHAR:
 		getres(tp, 0);
-		majdev = (int)getnum(pp);
-		mindev = (int)getnum(pp);
+		majdev = getnum(getstr(pp), 0, 0, false);
+		mindev = getnum(getstr(pp), 0, 0, false);
 		error = -libxfs_inode_alloc(&tp, pip, mode|S_IFCHR, 1,
 				IRIX_MKDEV(majdev, mindev), &creds, fsxp, &ip);
 		if (error)
diff --git a/mkfs/xfs_mkfs.c b/mkfs/xfs_mkfs.c
index 963545b..53a0ef3 100644
--- a/mkfs/xfs_mkfs.c
+++ b/mkfs/xfs_mkfs.c
@@ -45,6 +45,9 @@ static void respec(char opt, char *tab[], int idx);
 static void unknown(char opt, char *s);
 static int  ispow2(unsigned int i);
 
+static long long cvtnum(unsigned int blocksize,
+			unsigned int sectorsize, const char *s);
+
 /*
  * option tables for getsubopt calls
  */
@@ -983,6 +986,28 @@ sb_set_features(
 
 }
 
+long long
+getnum(
+	const char	*str,
+	unsigned int	blocksize,
+	unsigned int	sectorsize,
+	bool		convert)
+{
+	long long	i;
+	char		*sp;
+
+	if (convert)
+		return cvtnum(blocksize, sectorsize, str);
+
+	i = strtoll(str, &sp, 0);
+	if (i == 0 && sp == str)
+		return -1LL;
+	if (*sp != '\0')
+		return -1LL; /* trailing garbage */
+	return i;
+}
+
+
 int
 main(
 	int			argc,
@@ -1102,8 +1127,8 @@ main(
 
 	blflag = bsflag = slflag = ssflag = lslflag = lssflag = 0;
 	blocklog = blocksize = 0;
-	sectorlog = lsectorlog = XFS_MIN_SECTORSIZE_LOG;
-	sectorsize = lsectorsize = XFS_MIN_SECTORSIZE;
+	sectorlog = lsectorlog = 0;
+	sectorsize = lsectorsize = 0;
 	agsize = daflag = dasize = dblocks = 0;
 	ilflag = imflag = ipflag = isflag = 0;
 	liflag = laflag = lsflag = lsuflag = lsunitflag = ldflag = lvflag = 0;
@@ -1147,7 +1172,7 @@ main(
 					if (bsflag)
 						conflict('b', bopts, B_SIZE,
 							 B_LOG);
-					blocklog = atoi(value);
+					blocklog = getnum(value, 0, 0, false);
 					if (blocklog <= 0)
 						illegal(value, "b log");
 					blocksize = 1 << blocklog;
@@ -1161,8 +1186,8 @@ main(
 					if (blflag)
 						conflict('b', bopts, B_LOG,
 							 B_SIZE);
-					blocksize = cvtnum(
-						blocksize, sectorsize, value);
+					blocksize = getnum(value, blocksize,
+							sectorsize, true);
 					if (blocksize <= 0 ||
 					    !ispow2(blocksize))
 						illegal(value, "b size");
@@ -1185,8 +1210,7 @@ main(
 						reqval('d', dopts, D_AGCOUNT);
 					if (daflag)
 						respec('d', dopts, D_AGCOUNT);
-					agcount = (__uint64_t)
-						strtoul(value, NULL, 10);
+					agcount = getnum(value, 0, 0, false);
 					if ((__int64_t)agcount <= 0)
 						illegal(value, "d agcount");
 					daflag = 1;
@@ -1196,14 +1220,16 @@ main(
 						reqval('d', dopts, D_AGSIZE);
 					if (dasize)
 						respec('d', dopts, D_AGSIZE);
-					agsize = cvtnum(
-						blocksize, sectorsize, value);
+					agsize = getnum(value, blocksize,
+							sectorsize, true);
+					if ((__int64_t)agsize <= 0)
+						illegal(value, "d agsize");
 					dasize = 1;
 					break;
 				case D_FILE:
 					if (!value || *value == '\0')
 						value = "1";
-					xi.disfile = atoi(value);
+					xi.disfile = getnum(value, 0, 0, false);
 					if (xi.disfile < 0 || xi.disfile > 1)
 						illegal(value, "d file");
 					if (xi.disfile && !Nflag)
@@ -1231,13 +1257,9 @@ main(
 					if (nodsflag)
 						conflict('d', dopts, D_NOALIGN,
 							 D_SUNIT);
-					if (!isdigits(value)) {
-						fprintf(stderr,
-	_("%s: Specify data sunit in 512-byte blocks, no unit suffix\n"),
-							progname);
-						exit(1);
-					}
-					dsunit = cvtnum(0, 0, value);
+					dsunit = getnum(value, 0, 0, false);
+					if (dsunit < 0)
+						illegal(value, "d sunit");
 					break;
 				case D_SWIDTH:
 					if (!value || *value == '\0')
@@ -1247,13 +1269,9 @@ main(
 					if (nodsflag)
 						conflict('d', dopts, D_NOALIGN,
 							 D_SWIDTH);
-					if (!isdigits(value)) {
-						fprintf(stderr,
-	_("%s: Specify data swidth in 512-byte blocks, no unit suffix\n"),
-							progname);
-						exit(1);
-					}
-					dswidth = cvtnum(0, 0, value);
+					dswidth = getnum(value, 0, 0, false);
+					if (dswidth < 0)
+						illegal(value, "d swidth");
 					break;
 				case D_SU:
 					if (!value || *value == '\0')
@@ -1263,8 +1281,10 @@ main(
 					if (nodsflag)
 						conflict('d', dopts, D_NOALIGN,
 							 D_SU);
-					dsu = cvtnum(
-						blocksize, sectorsize, value);
+					dsu = getnum(value, blocksize,
+						     sectorsize, true);
+					if (dsu < 0)
+						illegal(value, "d su");
 					break;
 				case D_SW:
 					if (!value || *value == '\0')
@@ -1274,13 +1294,9 @@ main(
 					if (nodsflag)
 						conflict('d', dopts, D_NOALIGN,
 							 D_SW);
-					if (!isdigits(value)) {
-						fprintf(stderr,
-		_("%s: Specify data sw as multiple of su, no unit suffix\n"),
-							progname);
-						exit(1);
-					}
-					dsw = cvtnum(0, 0, value);
+					dsw = getnum(value, 0, 0, false);
+					if (dsw < 0)
+						illegal(value, "d sw");
 					break;
 				case D_NOALIGN:
 					if (dsu)
@@ -1305,7 +1321,7 @@ main(
 					if (ssflag)
 						conflict('d', dopts, D_SECTSIZE,
 							 D_SECTLOG);
-					sectorlog = atoi(value);
+					sectorlog = getnum(value, 0, 0, false);
 					if (sectorlog <= 0)
 						illegal(value, "d sectlog");
 					sectorsize = 1 << sectorlog;
@@ -1319,8 +1335,8 @@ main(
 					if (slflag)
 						conflict('d', dopts, D_SECTLOG,
 							 D_SECTSIZE);
-					sectorsize = cvtnum(
-						blocksize, sectorsize, value);
+					sectorsize = getnum(value, blocksize,
+							    sectorsize, true);
 					if (sectorsize <= 0 ||
 					    !ispow2(sectorsize))
 						illegal(value, "d sectsize");
@@ -1360,7 +1376,7 @@ main(
 				case I_ALIGN:
 					if (!value || *value == '\0')
 						value = "1";
-					c = atoi(value);
+					c = getnum(value, 0, 0, false);
 					if (c < 0 || c > 1)
 						illegal(value, "i align");
 					sb_feat.inode_align = c ? true : false;
@@ -1376,7 +1392,7 @@ main(
 					if (isflag)
 						conflict('i', iopts, I_SIZE,
 							 I_LOG);
-					inodelog = atoi(value);
+					inodelog = getnum(value, 0, 0, false);
 					if (inodelog <= 0)
 						illegal(value, "i log");
 					isize = 1 << inodelog;
@@ -1387,7 +1403,7 @@ main(
 						reqval('i', iopts, I_MAXPCT);
 					if (imflag)
 						respec('i', iopts, I_MAXPCT);
-					imaxpct = atoi(value);
+					imaxpct = getnum(value, 0, 0, false);
 					if (imaxpct < 0 || imaxpct > 100)
 						illegal(value, "i maxpct");
 					imflag = 1;
@@ -1403,7 +1419,7 @@ main(
 					if (isflag)
 						conflict('i', iopts, I_SIZE,
 							 I_PERBLOCK);
-					inopblock = atoi(value);
+					inopblock = getnum(value, 0, 0, false);
 					if (inopblock <
 						XFS_MIN_INODE_PERBLOCK ||
 					    !ispow2(inopblock))
@@ -1421,7 +1437,7 @@ main(
 							 I_SIZE);
 					if (isflag)
 						respec('i', iopts, I_SIZE);
-					isize = cvtnum(0, 0, value);
+					isize = getnum(value, 0, 0, true);
 					if (isize <= 0 || !ispow2(isize))
 						illegal(value, "i size");
 					inodelog = libxfs_highbit32(isize);
@@ -1430,7 +1446,7 @@ main(
 				case I_ATTR:
 					if (!value || *value == '\0')
 						reqval('i', iopts, I_ATTR);
-					c = atoi(value);
+					c = getnum(value, 0, 0, false);
 					if (c < 0 || c > 2)
 						illegal(value, "i attr");
 					sb_feat.attr_version = c;
@@ -1438,7 +1454,7 @@ main(
 				case I_PROJID32BIT:
 					if (!value || *value == '\0')
 						value = "0";
-					c = atoi(value);
+					c = getnum(value, 0, 0, false);
 					if (c < 0 || c > 1)
 						illegal(value, "i projid32bit");
 					sb_feat.projid16bit = c ? false : true;
@@ -1469,7 +1485,9 @@ main(
 						respec('l', lopts, L_AGNUM);
 					if (ldflag)
 						conflict('l', lopts, L_AGNUM, L_DEV);
-					logagno = atoi(value);
+					logagno = getnum(value, 0, 0, false);
+					if ((__int64_t)logagno < 0)
+						illegal(value, "l agno");
 					laflag = 1;
 					break;
 				case L_FILE:
@@ -1478,7 +1496,7 @@ main(
 					if (loginternal)
 						conflict('l', lopts, L_INTERNAL,
 							 L_FILE);
-					xi.lisfile = atoi(value);
+					xi.lisfile = getnum(value, 0, 0, false);
 					if (xi.lisfile < 0 || xi.lisfile > 1)
 						illegal(value, "l file");
 					if (xi.lisfile)
@@ -1494,7 +1512,7 @@ main(
 							 L_INTERNAL);
 					if (liflag)
 						respec('l', lopts, L_INTERNAL);
-					loginternal = atoi(value);
+					loginternal = getnum(value, 0, 0, false);
 					if (loginternal < 0 || loginternal > 1)
 						illegal(value, "l internal");
 					liflag = 1;
@@ -1504,8 +1522,10 @@ main(
 						reqval('l', lopts, L_SU);
 					if (lsu)
 						respec('l', lopts, L_SU);
-					lsu = cvtnum(
-						blocksize, sectorsize, value);
+					lsu = getnum(value, blocksize,
+						     sectorsize, true);
+					if (lsu < 0)
+						illegal(value, "l su");
 					lsuflag = 1;
 					break;
 				case L_SUNIT:
@@ -1513,12 +1533,9 @@ main(
 						reqval('l', lopts, L_SUNIT);
 					if (lsunit)
 						respec('l', lopts, L_SUNIT);
-					if (!isdigits(value)) {
-						fprintf(stderr,
-		_("Specify log sunit in 512-byte blocks, no size suffix\n"));
-						usage();
-					}
-					lsunit = cvtnum(0, 0, value);
+					lsunit = getnum(value, 0, 0, false);
+					if (lsunit < 0)
+						illegal(value, "l sunit");
 					lsunitflag = 1;
 					break;
 				case L_NAME:
@@ -1541,7 +1558,7 @@ main(
 						reqval('l', lopts, L_VERSION);
 					if (lvflag)
 						respec('l', lopts, L_VERSION);
-					c = atoi(value);
+					c = getnum(value, 0, 0, false);
 					if (c < 1 || c > 2)
 						illegal(value, "l version");
 					sb_feat.log_version = c;
@@ -1563,7 +1580,7 @@ main(
 					if (lssflag)
 						conflict('l', lopts, L_SECTSIZE,
 							 L_SECTLOG);
-					lsectorlog = atoi(value);
+					lsectorlog = getnum(value, 0, 0, false);
 					if (lsectorlog <= 0)
 						illegal(value, "l sectlog");
 					lsectorsize = 1 << lsectorlog;
@@ -1577,8 +1594,8 @@ main(
 					if (lslflag)
 						conflict('l', lopts, L_SECTLOG,
 							 L_SECTSIZE);
-					lsectorsize = cvtnum(
-						blocksize, sectorsize, value);
+					lsectorsize = getnum(value, blocksize,
+							     sectorsize, true);
 					if (lsectorsize <= 0 ||
 					    !ispow2(lsectorsize))
 						illegal(value, "l sectsize");
@@ -1590,7 +1607,7 @@ main(
 					if (!value || *value == '\0')
 						reqval('l', lopts,
 								L_LAZYSBCNTR);
-					c = atoi(value);
+					c = getnum(value, 0, 0, false);
 					if (c < 0 || c > 1)
 						illegal(value, "l lazy-count");
 					sb_feat.lazy_sb_counters = c ? true
@@ -1615,7 +1632,7 @@ main(
 				case M_CRC:
 					if (!value || *value == '\0')
 						reqval('m', mopts, M_CRC);
-					c = atoi(value);
+					c = getnum(value, 0, 0, false);
 					if (c < 0 || c > 1)
 						illegal(value, "m crc");
 					sb_feat.crcs_enabled = c ? true : false;
@@ -1656,7 +1673,7 @@ main(
 					if (nsflag)
 						conflict('n', nopts, N_SIZE,
 							 N_LOG);
-					dirblocklog = atoi(value);
+					dirblocklog = getnum(value, 0, 0, false);
 					if (dirblocklog <= 0)
 						illegal(value, "n log");
 					dirblocksize = 1 << dirblocklog;
@@ -1670,8 +1687,8 @@ main(
 					if (nlflag)
 						conflict('n', nopts, N_LOG,
 							 N_SIZE);
-					dirblocksize = cvtnum(
-						blocksize, sectorsize, value);
+					dirblocksize = getnum(value, blocksize,
+							      sectorsize, true);
 					if (dirblocksize <= 0 ||
 					    !ispow2(dirblocksize))
 						illegal(value, "n size");
@@ -1688,7 +1705,7 @@ main(
 						/* ASCII CI mode */
 						sb_feat.nci = true;
 					} else {
-						c = atoi(value);
+						c = getnum(value, 0, 0, false);
 						if (c != 2)
 							illegal(value,
 								"n version");
@@ -1701,7 +1718,7 @@ main(
 						reqval('n', nopts, N_FTYPE);
 					if (nftype)
 						respec('n', nopts, N_FTYPE);
-					c = atoi(value);
+					c = getnum(value, 0, 0, false);
 					if (c < 0 || c > 1)
 						illegal(value, "n ftype");
 					sb_feat.dirftype = c ? true : false;
@@ -1742,7 +1759,7 @@ main(
 				case R_FILE:
 					if (!value || *value == '\0')
 						value = "1";
-					xi.risfile = atoi(value);
+					xi.risfile = getnum(value, 0, 0, false);
 					if (xi.risfile < 0 || xi.risfile > 1)
 						illegal(value, "r file");
 					if (xi.risfile)
@@ -1786,7 +1803,7 @@ main(
 					if (ssflag || lssflag)
 						conflict('s', sopts, S_SECTSIZE,
 							 S_SECTLOG);
-					sectorlog = atoi(value);
+					sectorlog = getnum(value, 0, 0, false);
 					if (sectorlog <= 0)
 						illegal(value, "s sectlog");
 					lsectorlog = sectorlog;
@@ -1803,8 +1820,8 @@ main(
 					if (slflag || lslflag)
 						conflict('s', sopts, S_SECTLOG,
 							 S_SECTSIZE);
-					sectorsize = cvtnum(
-						blocksize, sectorsize, value);
+					sectorsize = getnum(value, blocksize,
+							    sectorsize, true);
 					if (sectorsize <= 0 ||
 					    !ispow2(sectorsize))
 						illegal(value, "s sectsize");
@@ -1864,6 +1881,15 @@ _("Minimum block size for CRC enabled filesystems is %d bytes.\n"),
 		usage();
 	}
 
+	if (!slflag && !ssflag) {
+		sectorlog = XFS_MIN_SECTORSIZE_LOG;
+		sectorsize = XFS_MIN_SECTORSIZE;
+	}
+	if (!lslflag && !lssflag) {
+		lsectorlog = sectorlog;
+		lsectorsize = sectorsize;
+	}
+
 	memset(&ft, 0, sizeof(ft));
 	get_topology(&xi, &ft, force_overwrite);
 
@@ -2027,7 +2053,9 @@ _("warning: sparse inodes not supported without CRC support, disabled.\n"));
 	if (dsize) {
 		__uint64_t dbytes;
 
-		dbytes = cvtnum(blocksize, sectorsize, dsize);
+		dbytes = getnum(dsize, blocksize, sectorsize, true);
+		if ((__int64_t)dbytes < 0)
+			illegal(dsize, "d size");
 		if (dbytes % XFS_MIN_BLOCKSIZE) {
 			fprintf(stderr,
 			_("illegal data length %lld, not a multiple of %d\n"),
@@ -2064,7 +2092,9 @@ _("warning: sparse inodes not supported without CRC support, disabled.\n"));
 	if (logsize) {
 		__uint64_t logbytes;
 
-		logbytes = cvtnum(blocksize, sectorsize, logsize);
+		logbytes = getnum(logsize, blocksize, sectorsize, true);
+		if ((__int64_t)logbytes < 0)
+			illegal(logsize, "l size");
 		if (logbytes % XFS_MIN_BLOCKSIZE) {
 			fprintf(stderr,
 			_("illegal log length %lld, not a multiple of %d\n"),
@@ -2086,7 +2116,9 @@ _("warning: sparse inodes not supported without CRC support, disabled.\n"));
 	if (rtsize) {
 		__uint64_t rtbytes;
 
-		rtbytes = cvtnum(blocksize, sectorsize, rtsize);
+		rtbytes = getnum(rtsize, blocksize, sectorsize, true);
+		if ((__int64_t)rtbytes < 0)
+			illegal(rtsize, "r size");
 		if (rtbytes % XFS_MIN_BLOCKSIZE) {
 			fprintf(stderr,
 			_("illegal rt length %lld, not a multiple of %d\n"),
@@ -2106,7 +2138,9 @@ _("warning: sparse inodes not supported without CRC support, disabled.\n"));
 	if (rtextsize) {
 		__uint64_t rtextbytes;
 
-		rtextbytes = cvtnum(blocksize, sectorsize, rtextsize);
+		rtextbytes = getnum(rtextsize, blocksize, sectorsize, true);
+		if ((__int64_t)rtextbytes < 0)
+			illegal(rtsize, "r extsize");
 		if (rtextbytes % blocksize) {
 			fprintf(stderr,
 		_("illegal rt extent size %lld, not a multiple of %d\n"),
@@ -3219,28 +3253,11 @@ unknown(
 	usage();
 }
 
-/*
- * isdigits -- returns 1 if string contains nothing but [0-9], 0 otherwise
- */
-int
-isdigits(
-	char		*str)
-{
-	int		i;
-	int		n = strlen(str);
-
-	for (i = 0; i < n; i++) {
-		if (!isdigit((int)str[i]))
-			return 0;
-	}
-	return 1;
-}
-
 long long
 cvtnum(
 	unsigned int	blocksize,
 	unsigned int	sectorsize,
-	char		*s)
+	const char	*s)
 {
 	long long	i;
 	char		*sp;
@@ -3251,17 +3268,11 @@ cvtnum(
 	if (*sp == '\0')
 		return i;
 
-	if (*sp == 'b' && sp[1] == '\0') {
-		if (blocksize)
-			return i * blocksize;
-		fprintf(stderr, _("blocksize not available yet.\n"));
-		usage();
-	}
-	if (*sp == 's' && sp[1] == '\0') {
-		if (sectorsize)
-			return i * sectorsize;
-		return i * BBSIZE;
-	}
+	if (*sp == 'b' && sp[1] == '\0')
+		return i * blocksize;
+	if (*sp == 's' && sp[1] == '\0')
+		return i * sectorsize;
+
 	if (*sp == 'k' && sp[1] == '\0')
 		return 1024LL * i;
 	if (*sp == 'm' && sp[1] == '\0')
-- 
2.5.0

_______________________________________________
xfs mailing list
xfs@oss.sgi.com
http://oss.sgi.com/mailman/listinfo/xfs

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

* [PATCH 05/19] mkfs: factor boolean option parsing
  2016-04-21  9:39 [PATCH 00/19 v2] mkfs cleaning Jan Tulak
                   ` (3 preceding siblings ...)
  2016-04-21  9:39 ` [PATCH 04/19] mkfs: validate all input values Jan Tulak
@ 2016-04-21  9:39 ` Jan Tulak
  2016-04-21  9:39 ` [PATCH 06/19] mkfs: validate logarithmic parameters sanely Jan Tulak
                   ` (16 subsequent siblings)
  21 siblings, 0 replies; 51+ messages in thread
From: Jan Tulak @ 2016-04-21  9:39 UTC (permalink / raw)
  To: xfs

From: Dave Chinner <dchinner@redhat.com>

Many of the options passed to mkfs have boolean options (0 or 1) and
all hand roll the same code and validity checks. Factor these out
into a common function.

Note that the lazy-count option is now changed to match other
booleans in that if you don't specify a value, it reverts to the
default value (on) rather than throwing an error.

Signed-off-by: Dave Chinner <dchinner@redhat.com>
Signed-off-by: Jan Tulak <jtulak@redhat.com>

---
CHANGES
* add getbool treatment to I_SPINODES
---
 mkfs/xfs_mkfs.c | 111 ++++++++++++++++++++++----------------------------------
 1 file changed, 43 insertions(+), 68 deletions(-)

diff --git a/mkfs/xfs_mkfs.c b/mkfs/xfs_mkfs.c
index 53a0ef3..94ae7e2 100644
--- a/mkfs/xfs_mkfs.c
+++ b/mkfs/xfs_mkfs.c
@@ -38,7 +38,7 @@ struct fs_topology {
  * Prototypes for internal functions.
  */
 static void conflict(char opt, char *tab[], int oldidx, int newidx);
-static void illegal(char *value, char *opt);
+static void illegal(const char *value, const char *opt);
 static __attribute__((noreturn)) void usage (void);
 static __attribute__((noreturn)) void reqval(char opt, char *tab[], int idx);
 static void respec(char opt, char *tab[], int idx);
@@ -1007,6 +1007,21 @@ getnum(
 	return i;
 }
 
+static bool
+getbool(
+	const char	*str,
+	const char	*illegal_str,
+	bool		default_val)
+{
+	long long	c;
+
+	if (!str || *str == '\0')
+		return default_val;
+	c = getnum(str, 0, 0, false);
+	if (c < 0 || c > 1)
+		illegal(str, illegal_str);
+	return c ? true : false;
+}
 
 int
 main(
@@ -1227,11 +1242,8 @@ main(
 					dasize = 1;
 					break;
 				case D_FILE:
-					if (!value || *value == '\0')
-						value = "1";
-					xi.disfile = getnum(value, 0, 0, false);
-					if (xi.disfile < 0 || xi.disfile > 1)
-						illegal(value, "d file");
+					xi.disfile = getbool(value, "d file",
+							     true);
 					if (xi.disfile && !Nflag)
 						xi.dcreat = 1;
 					break;
@@ -1374,12 +1386,8 @@ main(
 
 				switch (getsubopt(&p, (constpp)iopts, &value)) {
 				case I_ALIGN:
-					if (!value || *value == '\0')
-						value = "1";
-					c = getnum(value, 0, 0, false);
-					if (c < 0 || c > 1)
-						illegal(value, "i align");
-					sb_feat.inode_align = c ? true : false;
+					sb_feat.inode_align = getbool(
+							value, "i align", true);
 					break;
 				case I_LOG:
 					if (!value || *value == '\0')
@@ -1452,20 +1460,12 @@ main(
 					sb_feat.attr_version = c;
 					break;
 				case I_PROJID32BIT:
-					if (!value || *value == '\0')
-						value = "0";
-					c = getnum(value, 0, 0, false);
-					if (c < 0 || c > 1)
-						illegal(value, "i projid32bit");
-					sb_feat.projid16bit = c ? false : true;
+					sb_feat.projid16bit = !getbool(value,
+							"i projid32bit", false);
 					break;
 				case I_SPINODES:
-					if (!value || *value == '\0')
-						value = "1";
-					c = atoi(value);
-					if (c < 0 || c > 1)
-						illegal(value, "i spinodes");
-					sb_feat.spinodes = c;
+					sb_feat.spinodes = getbool(value,
+							"i spinodes", true);
 					break;
 				default:
 					unknown('i', value);
@@ -1491,20 +1491,15 @@ main(
 					laflag = 1;
 					break;
 				case L_FILE:
-					if (!value || *value == '\0')
-						value = "1";
 					if (loginternal)
 						conflict('l', lopts, L_INTERNAL,
 							 L_FILE);
-					xi.lisfile = getnum(value, 0, 0, false);
-					if (xi.lisfile < 0 || xi.lisfile > 1)
-						illegal(value, "l file");
+					xi.lisfile = getbool(value, "l file",
+							     true);
 					if (xi.lisfile)
 						xi.lcreat = 1;
 					break;
 				case L_INTERNAL:
-					if (!value || *value == '\0')
-						value = "1";
 					if (ldflag)
 						conflict('l', lopts, L_INTERNAL, L_DEV);
 					if (xi.lisfile)
@@ -1512,9 +1507,9 @@ main(
 							 L_INTERNAL);
 					if (liflag)
 						respec('l', lopts, L_INTERNAL);
-					loginternal = getnum(value, 0, 0, false);
-					if (loginternal < 0 || loginternal > 1)
-						illegal(value, "l internal");
+
+					loginternal = getbool(value,
+							"l internal", true);
 					liflag = 1;
 					break;
 				case L_SU:
@@ -1604,14 +1599,9 @@ main(
 					lssflag = 1;
 					break;
 				case L_LAZYSBCNTR:
-					if (!value || *value == '\0')
-						reqval('l', lopts,
-								L_LAZYSBCNTR);
-					c = getnum(value, 0, 0, false);
-					if (c < 0 || c > 1)
-						illegal(value, "l lazy-count");
-					sb_feat.lazy_sb_counters = c ? true
-								     : false;
+					sb_feat.lazy_sb_counters = getbool(
+							value, "l lazy-count",
+							true);
 					break;
 				default:
 					unknown('l', value);
@@ -1630,23 +1620,15 @@ main(
 
 				switch (getsubopt(&p, (constpp)mopts, &value)) {
 				case M_CRC:
-					if (!value || *value == '\0')
-						reqval('m', mopts, M_CRC);
-					c = getnum(value, 0, 0, false);
-					if (c < 0 || c > 1)
-						illegal(value, "m crc");
-					sb_feat.crcs_enabled = c ? true : false;
-					if (c)
+					sb_feat.crcs_enabled = getbool(
+							value, "m crc", true);
+					if (sb_feat.crcs_enabled)
 						sb_feat.dirftype = true;
 					break;
 				case M_FINOBT:
-					if (!value || *value == '\0')
-						reqval('m', mopts, M_CRC);
-					c = atoi(value);
-					if (c < 0 || c > 1)
-						illegal(value, "m finobt");
 					sb_feat.finobtflag = true;
-					sb_feat.finobt = c;
+					sb_feat.finobt = getbool(
+						value, "m finobt", true);
 					break;
 				case M_UUID:
 					if (!value || *value == '\0')
@@ -1714,14 +1696,10 @@ main(
 					nvflag = 1;
 					break;
 				case N_FTYPE:
-					if (!value || *value == '\0')
-						reqval('n', nopts, N_FTYPE);
 					if (nftype)
 						respec('n', nopts, N_FTYPE);
-					c = getnum(value, 0, 0, false);
-					if (c < 0 || c > 1)
-						illegal(value, "n ftype");
-					sb_feat.dirftype = c ? true : false;
+					sb_feat.dirftype = getbool(value,
+							     "n ftype", true);
 					nftype = 1;
 					break;
 				default:
@@ -1757,11 +1735,8 @@ main(
 					rtextsize = value;
 					break;
 				case R_FILE:
-					if (!value || *value == '\0')
-						value = "1";
-					xi.risfile = getnum(value, 0, 0, false);
-					if (xi.risfile < 0 || xi.risfile > 1)
-						illegal(value, "r file");
+					xi.risfile = getbool(value,
+							     "r file", true);
 					if (xi.risfile)
 						xi.rcreat = 1;
 					break;
@@ -3207,8 +3182,8 @@ conflict(
 
 static void
 illegal(
-	char		*value,
-	char		*opt)
+	const char	*value,
+	const char	*opt)
 {
 	fprintf(stderr, _("Illegal value %s for -%s option\n"), value, opt);
 	usage();
-- 
2.5.0

_______________________________________________
xfs mailing list
xfs@oss.sgi.com
http://oss.sgi.com/mailman/listinfo/xfs

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

* [PATCH 06/19] mkfs: validate logarithmic parameters sanely
  2016-04-21  9:39 [PATCH 00/19 v2] mkfs cleaning Jan Tulak
                   ` (4 preceding siblings ...)
  2016-04-21  9:39 ` [PATCH 05/19] mkfs: factor boolean option parsing Jan Tulak
@ 2016-04-21  9:39 ` Jan Tulak
  2016-04-21  9:39 ` [PATCH 07/19] mkfs: structify input parameter passing Jan Tulak
                   ` (15 subsequent siblings)
  21 siblings, 0 replies; 51+ messages in thread
From: Jan Tulak @ 2016-04-21  9:39 UTC (permalink / raw)
  To: xfs

From: Dave Chinner <dchinner@redhat.com>

Testing logarithmic paramters like "-n log=<num>" shows that we do a
terrible job of validating such input. e.g.:

.....
naming   =version 2              bsize=65536  ascii-ci=0 ftype=0
....

Yeah, I just asked for a block size of 2^456858480, and it didn't
get rejected. Great, isn't it?

So, factor out the parsing of logarithmic parameters, and pass in
the maximum valid value that they can take. These maximum values
might not be completely accurate (e.g. block/sector sizes will
affect the eventual valid maximum) but we can get rid of all the
overflows and stupidities before we get to fine-grained validity
checking later in mkfs once things like block and sector sizes have
been finalised.

Signed-off-by: Dave Chinner <dchinner@redhat.com>
Signed-off-by: Jan Tulak <jtulak@redhat.com>
Reviewed-by: Brian Foster <bfoster@redhat.com>
Reviewed-by: Eric Sandeen <sandeen@redhat.com>
---
 mkfs/xfs_mkfs.c | 79 +++++++++++++++++++++++++++++++++++++--------------------
 1 file changed, 51 insertions(+), 28 deletions(-)

diff --git a/mkfs/xfs_mkfs.c b/mkfs/xfs_mkfs.c
index 94ae7e2..09370d8 100644
--- a/mkfs/xfs_mkfs.c
+++ b/mkfs/xfs_mkfs.c
@@ -1023,6 +1023,27 @@ getbool(
 	return c ? true : false;
 }
 
+static int
+getnum_checked(
+	const char	*str,
+	long long	min_val,
+	long long	max_val,
+	const char	*illegal_str,
+	char		reqval_char,
+	char		*reqval_opts[],
+	int		reqval_optind)
+{
+	long long	c;
+
+	if (!str || *str == '\0')
+		reqval(reqval_char, reqval_opts, reqval_optind);
+
+	c = getnum(str, 0, 0, false);
+	if (c < min_val || c > max_val)
+		illegal(str, illegal_str);
+	return c;
+}
+
 int
 main(
 	int			argc,
@@ -1180,16 +1201,16 @@ main(
 
 				switch (getsubopt(&p, (constpp)bopts, &value)) {
 				case B_LOG:
-					if (!value || *value == '\0')
-						reqval('b', bopts, B_LOG);
 					if (blflag)
 						respec('b', bopts, B_LOG);
 					if (bsflag)
 						conflict('b', bopts, B_SIZE,
 							 B_LOG);
-					blocklog = getnum(value, 0, 0, false);
-					if (blocklog <= 0)
-						illegal(value, "b log");
+					blocklog = getnum_checked(value,
+							XFS_MIN_BLOCKSIZE_LOG,
+							XFS_MAX_BLOCKSIZE_LOG,
+							"b log", 'b', bopts,
+							B_LOG);
 					blocksize = 1 << blocklog;
 					blflag = 1;
 					break;
@@ -1326,16 +1347,16 @@ main(
 					nodsflag = 1;
 					break;
 				case D_SECTLOG:
-					if (!value || *value == '\0')
-						reqval('d', dopts, D_SECTLOG);
 					if (slflag)
 						respec('d', dopts, D_SECTLOG);
 					if (ssflag)
 						conflict('d', dopts, D_SECTSIZE,
 							 D_SECTLOG);
-					sectorlog = getnum(value, 0, 0, false);
-					if (sectorlog <= 0)
-						illegal(value, "d sectlog");
+					sectorlog = getnum_checked(value,
+							XFS_MIN_SECTORSIZE_LOG,
+							XFS_MAX_SECTORSIZE_LOG,
+							"d sectlog", 'd', dopts,
+							D_SECTLOG);
 					sectorsize = 1 << sectorlog;
 					slflag = 1;
 					break;
@@ -1400,9 +1421,11 @@ main(
 					if (isflag)
 						conflict('i', iopts, I_SIZE,
 							 I_LOG);
-					inodelog = getnum(value, 0, 0, false);
-					if (inodelog <= 0)
-						illegal(value, "i log");
+					inodelog = getnum_checked(value,
+							XFS_DINODE_MIN_LOG,
+							XFS_DINODE_MAX_LOG,
+							"i log", 'i', iopts,
+							I_LOG);
 					isize = 1 << inodelog;
 					ilflag = 1;
 					break;
@@ -1568,16 +1591,16 @@ main(
 					lsflag = 1;
 					break;
 				case L_SECTLOG:
-					if (!value || *value == '\0')
-						reqval('l', lopts, L_SECTLOG);
 					if (lslflag)
 						respec('l', lopts, L_SECTLOG);
 					if (lssflag)
 						conflict('l', lopts, L_SECTSIZE,
 							 L_SECTLOG);
-					lsectorlog = getnum(value, 0, 0, false);
-					if (lsectorlog <= 0)
-						illegal(value, "l sectlog");
+					lsectorlog = getnum_checked(value,
+							XFS_MIN_SECTORSIZE_LOG,
+							XFS_MAX_SECTORSIZE_LOG,
+							"l sectlog", 'l', lopts,
+							L_SECTLOG);
 					lsectorsize = 1 << lsectorlog;
 					lslflag = 1;
 					break;
@@ -1648,16 +1671,16 @@ main(
 
 				switch (getsubopt(&p, (constpp)nopts, &value)) {
 				case N_LOG:
-					if (!value || *value == '\0')
-						reqval('n', nopts, N_LOG);
 					if (nlflag)
 						respec('n', nopts, N_LOG);
 					if (nsflag)
 						conflict('n', nopts, N_SIZE,
 							 N_LOG);
-					dirblocklog = getnum(value, 0, 0, false);
-					if (dirblocklog <= 0)
-						illegal(value, "n log");
+					dirblocklog = getnum_checked(value,
+							XFS_MIN_REC_DIRSIZE,
+							XFS_MAX_BLOCKSIZE_LOG,
+							"n log", 'n', nopts,
+							N_LOG);
 					dirblocksize = 1 << dirblocklog;
 					nlflag = 1;
 					break;
@@ -1771,16 +1794,16 @@ main(
 				switch (getsubopt(&p, (constpp)sopts, &value)) {
 				case S_LOG:
 				case S_SECTLOG:
-					if (!value || *value == '\0')
-						reqval('s', sopts, S_SECTLOG);
 					if (slflag || lslflag)
 						respec('s', sopts, S_SECTLOG);
 					if (ssflag || lssflag)
 						conflict('s', sopts, S_SECTSIZE,
 							 S_SECTLOG);
-					sectorlog = getnum(value, 0, 0, false);
-					if (sectorlog <= 0)
-						illegal(value, "s sectlog");
+					sectorlog = getnum_checked(value,
+							XFS_MIN_SECTORSIZE_LOG,
+							XFS_MAX_SECTORSIZE_LOG,
+							"s sectlog", 's', sopts,
+							S_SECTLOG);
 					lsectorlog = sectorlog;
 					sectorsize = 1 << sectorlog;
 					lsectorsize = sectorsize;
-- 
2.5.0

_______________________________________________
xfs mailing list
xfs@oss.sgi.com
http://oss.sgi.com/mailman/listinfo/xfs

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

* [PATCH 07/19] mkfs: structify input parameter passing
  2016-04-21  9:39 [PATCH 00/19 v2] mkfs cleaning Jan Tulak
                   ` (5 preceding siblings ...)
  2016-04-21  9:39 ` [PATCH 06/19] mkfs: validate logarithmic parameters sanely Jan Tulak
@ 2016-04-21  9:39 ` Jan Tulak
  2016-04-21  9:39 ` [PATCH 08/19] mkfs: getbool is redundant Jan Tulak
                   ` (14 subsequent siblings)
  21 siblings, 0 replies; 51+ messages in thread
From: Jan Tulak @ 2016-04-21  9:39 UTC (permalink / raw)
  To: xfs

From: Dave Chinner <dchinner@redhat.com>

Passing large number of parameters around to number conversion
functions is painful. Add a structure to encapsulate the constant
parameters that are passed, and convert getnum_checked to use it.

This is the first real step towards a table driven option parser.

Signed-off-by: Dave Chinner <dchinner@redhat.com>
Signed-off-by: Jan Tulak <jtulak@redhat.com>

---
CHANGES
* comments
---
 mkfs/xfs_mkfs.c | 650 ++++++++++++++++++++++++++++++++++++++------------------
 1 file changed, 439 insertions(+), 211 deletions(-)

diff --git a/mkfs/xfs_mkfs.c b/mkfs/xfs_mkfs.c
index 09370d8..86cfb7b 100644
--- a/mkfs/xfs_mkfs.c
+++ b/mkfs/xfs_mkfs.c
@@ -48,147 +48,361 @@ static int  ispow2(unsigned int i);
 static long long cvtnum(unsigned int blocksize,
 			unsigned int sectorsize, const char *s);
 
+#define MAX_SUBOPTS	16
 /*
- * option tables for getsubopt calls
+ * Table for parsing mkfs parameters.
+ *
+ * Description of the structure members follows:
+ *
+ * name MANDATORY
+ *   Name is a single char, e.g., for '-d file', name is 'd'.
+ *
+ * subopts MANDATORY
+ *   Subopts is a list of strings naming suboptions. In the example above,
+ *   it would contain "file". The last entry of this list has to be NULL.
+ *
+ * subopt_params MANDATORY
+ *   This is a list of structs tied with subopts. For each entry in subopts,
+ *   a corresponding entry has to be defined:
+ *
+ * subopt_params struct:
+ *   index MANDATORY
+ *     This number, starting from zero, denotes which item in subopt_params
+ *     it is. The index has to be the same as is the order in subopts list,
+ *     so we can access the right item both in subopt_param and subopts.
+ *
+ *   minval, maxval OPTIONAL
+ *     These options are used for automatic range check and they have to be
+ *     always used together in pair. If you don't want to limit the max value,
+ *     use something like UINT_MAX. If no value is given, then you must either
+ *     supply your own validation, or refuse any value in the 'case
+ *     X_SOMETHING' block. If you forget to define the min and max value, but
+ *     call a standard function for validating user's value, it will cause an
+ *     error message notifying you about this issue.
+ *
+ *     (Said in another way, you can't have minval and maxval both equal
+ *     to zero. But if one value is different: minval=0 and maxval=1,
+ *     then it is OK.)
  */
-char *bopts[] = {
+struct opt_params {
+	const char	name;
+	const char	*subopts[MAX_SUBOPTS];
+	struct subopt_param {
+		int		index;
+		long long	minval;
+		long long	maxval;
+	}		subopt_params[MAX_SUBOPTS];
+};
+
+struct opt_params bopts = {
+	.name = 'b',
+	.subopts = {
 #define	B_LOG		0
-	"log",
+		"log",
 #define	B_SIZE		1
-	"size",
-	NULL
+		"size",
+		NULL
+	},
+	.subopt_params = {
+		{ .index = B_LOG,
+		  .minval = XFS_MIN_BLOCKSIZE_LOG,
+		  .maxval = XFS_MAX_BLOCKSIZE_LOG,
+		},
+		{ .index = B_SIZE,
+		  .minval = XFS_MIN_BLOCKSIZE,
+		  .maxval = XFS_MAX_BLOCKSIZE,
+		},
+	},
 };
 
-char	*dopts[] = {
+struct opt_params dopts = {
+	.name = 'd',
+	.subopts = {
 #define	D_AGCOUNT	0
-	"agcount",
+		"agcount",
 #define	D_FILE		1
-	"file",
+		"file",
 #define	D_NAME		2
-	"name",
+		"name",
 #define	D_SIZE		3
-	"size",
+		"size",
 #define D_SUNIT		4
-	"sunit",
+		"sunit",
 #define D_SWIDTH	5
-	"swidth",
+		"swidth",
 #define D_AGSIZE	6
-	"agsize",
+		"agsize",
 #define D_SU		7
-	"su",
+		"su",
 #define D_SW		8
-	"sw",
+		"sw",
 #define D_SECTLOG	9
-	"sectlog",
+		"sectlog",
 #define D_SECTSIZE	10
-	"sectsize",
+		"sectsize",
 #define D_NOALIGN	11
-	"noalign",
+		"noalign",
 #define D_RTINHERIT	12
-	"rtinherit",
+		"rtinherit",
 #define D_PROJINHERIT	13
-	"projinherit",
+		"projinherit",
 #define D_EXTSZINHERIT	14
-	"extszinherit",
-	NULL
+		"extszinherit",
+		NULL
+	},
+	.subopt_params = {
+		{ .index = D_AGCOUNT,
+		},
+		{ .index = D_FILE,
+		},
+		{ .index = D_NAME,
+		},
+		{ .index = D_SIZE,
+		},
+		{ .index = D_SUNIT,
+		},
+		{ .index = D_SWIDTH,
+		},
+		{ .index = D_AGSIZE,
+		},
+		{ .index = D_SU,
+		},
+		{ .index = D_SW,
+		},
+		{ .index = D_SECTLOG,
+		  .minval = XFS_MIN_SECTORSIZE_LOG,
+		  .maxval = XFS_MAX_SECTORSIZE_LOG,
+		},
+		{ .index = D_SECTSIZE,
+		  .minval = XFS_MIN_SECTORSIZE,
+		  .maxval = XFS_MAX_SECTORSIZE,
+		},
+		{ .index = D_NOALIGN,
+		},
+		{ .index = D_RTINHERIT,
+		},
+		{ .index = D_PROJINHERIT,
+		},
+		{ .index = D_EXTSZINHERIT,
+		},
+	},
 };
 
-char	*iopts[] = {
+
+struct opt_params iopts = {
+	.name = 'i',
+	.subopts = {
 #define	I_ALIGN		0
-	"align",
+		"align",
 #define	I_LOG		1
-	"log",
+		"log",
 #define	I_MAXPCT	2
-	"maxpct",
+		"maxpct",
 #define	I_PERBLOCK	3
-	"perblock",
+		"perblock",
 #define	I_SIZE		4
-	"size",
+		"size",
 #define	I_ATTR		5
-	"attr",
+		"attr",
 #define	I_PROJID32BIT	6
-	"projid32bit",
+		"projid32bit",
 #define I_SPINODES	7
-	"sparse",
-	NULL
+		"sparse",
+		NULL
+	},
+	.subopt_params = {
+		{ .index = I_ALIGN,
+		},
+		{ .index = I_LOG,
+		  .minval = XFS_DINODE_MIN_LOG,
+		  .maxval = XFS_DINODE_MAX_LOG,
+		},
+		{ .index = I_MAXPCT,
+		},
+		{ .index = I_PERBLOCK,
+		},
+		{ .index = I_SIZE,
+		},
+		{ .index = I_ATTR,
+		},
+		{ .index = I_PROJID32BIT,
+		},
+		{ .index = I_SPINODES,
+		},
+	},
 };
 
-char	*lopts[] = {
+struct opt_params lopts = {
+	.name = 'l',
+	.subopts = {
 #define	L_AGNUM		0
-	"agnum",
+		"agnum",
 #define	L_INTERNAL	1
-	"internal",
+		"internal",
 #define	L_SIZE		2
-	"size",
+		"size",
 #define L_VERSION	3
-	"version",
+		"version",
 #define L_SUNIT		4
-	"sunit",
+		"sunit",
 #define L_SU		5
-	"su",
+		"su",
 #define L_DEV		6
-	"logdev",
+		"logdev",
 #define	L_SECTLOG	7
-	"sectlog",
+		"sectlog",
 #define	L_SECTSIZE	8
-	"sectsize",
+		"sectsize",
 #define	L_FILE		9
-	"file",
+		"file",
 #define	L_NAME		10
-	"name",
+		"name",
 #define	L_LAZYSBCNTR	11
-	"lazy-count",
-	NULL
+		"lazy-count",
+		NULL
+	},
+	.subopt_params = {
+		{ .index = L_AGNUM,
+		},
+		{ .index = L_INTERNAL,
+		},
+		{ .index = L_SIZE,
+		},
+		{ .index = L_VERSION,
+		},
+		{ .index = L_SUNIT,
+		},
+		{ .index = L_SU,
+		},
+		{ .index = L_DEV,
+		},
+		{ .index = L_SECTLOG,
+		  .minval = XFS_MIN_SECTORSIZE_LOG,
+		  .maxval = XFS_MAX_SECTORSIZE_LOG,
+		},
+		{ .index = L_SECTSIZE,
+		  .minval = XFS_MIN_SECTORSIZE,
+		  .maxval = XFS_MAX_SECTORSIZE,
+		},
+		{ .index = L_FILE,
+		},
+		{ .index = L_NAME,
+		},
+		{ .index = L_LAZYSBCNTR,
+		},
+	},
 };
 
-char	*nopts[] = {
+struct opt_params nopts = {
+	.name = 'n',
+	.subopts = {
 #define	N_LOG		0
-	"log",
+		"log",
 #define	N_SIZE		1
-	"size",
+		"size",
 #define	N_VERSION	2
-	"version",
+		"version",
 #define	N_FTYPE		3
-	"ftype",
+		"ftype",
 	NULL,
+	},
+	.subopt_params = {
+		{ .index = N_LOG,
+		  .minval = XFS_MIN_REC_DIRSIZE,
+		  .maxval = XFS_MAX_BLOCKSIZE_LOG,
+		},
+		{ .index = N_SIZE,
+		  .minval = 1 << XFS_MIN_REC_DIRSIZE,
+		  .maxval = XFS_MAX_BLOCKSIZE,
+		},
+		{ .index = N_VERSION,
+		},
+		{ .index = N_FTYPE,
+		},
+	},
 };
 
-char	*ropts[] = {
+struct opt_params ropts = {
+	.name = 'r',
+	.subopts = {
 #define	R_EXTSIZE	0
-	"extsize",
+		"extsize",
 #define	R_SIZE		1
-	"size",
+		"size",
 #define	R_DEV		2
-	"rtdev",
+		"rtdev",
 #define	R_FILE		3
-	"file",
+		"file",
 #define	R_NAME		4
-	"name",
+		"name",
 #define R_NOALIGN	5
-	"noalign",
-	NULL
+		"noalign",
+		NULL
+	},
+	.subopt_params = {
+		{ .index = R_EXTSIZE,
+		},
+		{ .index = R_SIZE,
+		},
+		{ .index = R_DEV,
+		},
+		{ .index = R_FILE,
+		},
+		{ .index = R_NAME,
+		},
+		{ .index = R_NOALIGN,
+		},
+	},
 };
 
-char	*sopts[] = {
+struct opt_params sopts = {
+	.name = 's',
+	.subopts = {
 #define	S_LOG		0
-	"log",
+		"log",
 #define	S_SECTLOG	1
-	"sectlog",
+		"sectlog",
 #define	S_SIZE		2
-	"size",
+		"size",
 #define	S_SECTSIZE	3
-	"sectsize",
-	NULL
+		"sectsize",
+		NULL
+	},
+	.subopt_params = {
+		{ .index = S_LOG,
+		  .minval = XFS_MIN_SECTORSIZE_LOG,
+		  .maxval = XFS_MAX_SECTORSIZE_LOG,
+		},
+		{ .index = S_SECTLOG,
+		  .minval = XFS_MIN_SECTORSIZE_LOG,
+		  .maxval = XFS_MAX_SECTORSIZE_LOG,
+		},
+		{ .index = S_SIZE,
+		  .minval = XFS_MIN_SECTORSIZE,
+		  .maxval = XFS_MAX_SECTORSIZE,
+		},
+		{ .index = S_SECTSIZE,
+		  .minval = XFS_MIN_SECTORSIZE,
+		  .maxval = XFS_MAX_SECTORSIZE,
+		},
+	},
 };
 
-char	*mopts[] = {
+struct opt_params mopts = {
+	.name = 'm',
+	.subopts = {
 #define	M_CRC		0
-	"crc",
+		"crc",
 #define M_FINOBT	1
 	"finobt",
 #define M_UUID		2
-	"uuid",
-	NULL
+		"uuid",
+		NULL
+	},
+	.subopt_params = {
+		{ .index = M_CRC,
+		},
+	},
 };
 
 #define TERABYTES(count, blog)	((__uint64_t)(count) << (40 - (blog)))
@@ -1023,24 +1237,42 @@ getbool(
 	return c ? true : false;
 }
 
+static __attribute__((noreturn)) void
+illegal_option(
+	const char	*value,
+	struct opt_params	*opts,
+	int		index)
+{
+	fprintf(stderr,
+		_("Illegal value %s for -%c %s option\n"),
+		value, opts->name, opts->subopts[index]);
+	usage();
+}
+
 static int
 getnum_checked(
 	const char	*str,
-	long long	min_val,
-	long long	max_val,
-	const char	*illegal_str,
-	char		reqval_char,
-	char		*reqval_opts[],
-	int		reqval_optind)
+	struct opt_params	*opts,
+	int		index)
 {
 	long long	c;
 
 	if (!str || *str == '\0')
-		reqval(reqval_char, reqval_opts, reqval_optind);
+		reqval(opts->name, (char **)opts->subopts, index);
+
+	if (opts->subopt_params[index].minval == 0 &&
+	    opts->subopt_params[index].maxval == 0) {
+		fprintf(stderr,
+			_("Option -%c %s has undefined minval/maxval."
+			  "Can't verify value range. This is a bug.\n"),
+			opts->name, opts->subopts[index]);
+		exit(1);
+	}
 
 	c = getnum(str, 0, 0, false);
-	if (c < min_val || c > max_val)
-		illegal(str, illegal_str);
+	if (c < opts->subopt_params[index].minval ||
+	    c > opts->subopt_params[index].maxval)
+		illegal_option(str, opts, index);
 	return c;
 }
 
@@ -1197,30 +1429,29 @@ main(
 		case 'b':
 			p = optarg;
 			while (*p != '\0') {
+				char	**subopts = (char **)bopts.subopts;
 				char	*value;
 
-				switch (getsubopt(&p, (constpp)bopts, &value)) {
+				switch (getsubopt(&p, (constpp)subopts,
+						  &value)) {
 				case B_LOG:
 					if (blflag)
-						respec('b', bopts, B_LOG);
+						respec('b', subopts, B_LOG);
 					if (bsflag)
-						conflict('b', bopts, B_SIZE,
+						conflict('b', subopts, B_SIZE,
 							 B_LOG);
-					blocklog = getnum_checked(value,
-							XFS_MIN_BLOCKSIZE_LOG,
-							XFS_MAX_BLOCKSIZE_LOG,
-							"b log", 'b', bopts,
-							B_LOG);
+					blocklog = getnum_checked(value, &bopts,
+								  B_LOG);
 					blocksize = 1 << blocklog;
 					blflag = 1;
 					break;
 				case B_SIZE:
 					if (!value || *value == '\0')
-						reqval('b', bopts, B_SIZE);
+						reqval('b', subopts, B_SIZE);
 					if (bsflag)
-						respec('b', bopts, B_SIZE);
+						respec('b', subopts, B_SIZE);
 					if (blflag)
-						conflict('b', bopts, B_LOG,
+						conflict('b', subopts, B_LOG,
 							 B_SIZE);
 					blocksize = getnum(value, blocksize,
 							sectorsize, true);
@@ -1238,14 +1469,16 @@ main(
 		case 'd':
 			p = optarg;
 			while (*p != '\0') {
+				char	**subopts = (char **)dopts.subopts;
 				char	*value;
 
-				switch (getsubopt(&p, (constpp)dopts, &value)) {
+				switch (getsubopt(&p, (constpp)subopts,
+						  &value)) {
 				case D_AGCOUNT:
 					if (!value || *value == '\0')
-						reqval('d', dopts, D_AGCOUNT);
+						reqval('d', subopts, D_AGCOUNT);
 					if (daflag)
-						respec('d', dopts, D_AGCOUNT);
+						respec('d', subopts, D_AGCOUNT);
 					agcount = getnum(value, 0, 0, false);
 					if ((__int64_t)agcount <= 0)
 						illegal(value, "d agcount");
@@ -1253,9 +1486,9 @@ main(
 					break;
 				case D_AGSIZE:
 					if (!value || *value == '\0')
-						reqval('d', dopts, D_AGSIZE);
+						reqval('d', subopts, D_AGSIZE);
 					if (dasize)
-						respec('d', dopts, D_AGSIZE);
+						respec('d', subopts, D_AGSIZE);
 					agsize = getnum(value, blocksize,
 							sectorsize, true);
 					if ((__int64_t)agsize <= 0)
@@ -1270,25 +1503,25 @@ main(
 					break;
 				case D_NAME:
 					if (!value || *value == '\0')
-						reqval('d', dopts, D_NAME);
+						reqval('d', subopts, D_NAME);
 					if (xi.dname)
-						respec('d', dopts, D_NAME);
+						respec('d', subopts, D_NAME);
 					xi.dname = value;
 					break;
 				case D_SIZE:
 					if (!value || *value == '\0')
-						reqval('d', dopts, D_SIZE);
+						reqval('d', subopts, D_SIZE);
 					if (dsize)
-						respec('d', dopts, D_SIZE);
+						respec('d', subopts, D_SIZE);
 					dsize = value;
 					break;
 				case D_SUNIT:
 					if (!value || *value == '\0')
-						reqval('d', dopts, D_SUNIT);
+						reqval('d', subopts, D_SUNIT);
 					if (dsunit)
-						respec('d', dopts, D_SUNIT);
+						respec('d', subopts, D_SUNIT);
 					if (nodsflag)
-						conflict('d', dopts, D_NOALIGN,
+						conflict('d', subopts, D_NOALIGN,
 							 D_SUNIT);
 					dsunit = getnum(value, 0, 0, false);
 					if (dsunit < 0)
@@ -1296,11 +1529,11 @@ main(
 					break;
 				case D_SWIDTH:
 					if (!value || *value == '\0')
-						reqval('d', dopts, D_SWIDTH);
+						reqval('d', subopts, D_SWIDTH);
 					if (dswidth)
-						respec('d', dopts, D_SWIDTH);
+						respec('d', subopts, D_SWIDTH);
 					if (nodsflag)
-						conflict('d', dopts, D_NOALIGN,
+						conflict('d', subopts, D_NOALIGN,
 							 D_SWIDTH);
 					dswidth = getnum(value, 0, 0, false);
 					if (dswidth < 0)
@@ -1308,11 +1541,11 @@ main(
 					break;
 				case D_SU:
 					if (!value || *value == '\0')
-						reqval('d', dopts, D_SU);
+						reqval('d', subopts, D_SU);
 					if (dsu)
-						respec('d', dopts, D_SU);
+						respec('d', subopts, D_SU);
 					if (nodsflag)
-						conflict('d', dopts, D_NOALIGN,
+						conflict('d', subopts, D_NOALIGN,
 							 D_SU);
 					dsu = getnum(value, blocksize,
 						     sectorsize, true);
@@ -1321,11 +1554,11 @@ main(
 					break;
 				case D_SW:
 					if (!value || *value == '\0')
-						reqval('d', dopts, D_SW);
+						reqval('d', subopts, D_SW);
 					if (dsw)
-						respec('d', dopts, D_SW);
+						respec('d', subopts, D_SW);
 					if (nodsflag)
-						conflict('d', dopts, D_NOALIGN,
+						conflict('d', subopts, D_NOALIGN,
 							 D_SW);
 					dsw = getnum(value, 0, 0, false);
 					if (dsw < 0)
@@ -1333,40 +1566,37 @@ main(
 					break;
 				case D_NOALIGN:
 					if (dsu)
-						conflict('d', dopts, D_SU,
+						conflict('d', subopts, D_SU,
 							 D_NOALIGN);
 					if (dsunit)
-						conflict('d', dopts, D_SUNIT,
+						conflict('d', subopts, D_SUNIT,
 							 D_NOALIGN);
 					if (dsw)
-						conflict('d', dopts, D_SW,
+						conflict('d', subopts, D_SW,
 							 D_NOALIGN);
 					if (dswidth)
-						conflict('d', dopts, D_SWIDTH,
+						conflict('d', subopts, D_SWIDTH,
 							 D_NOALIGN);
 					nodsflag = 1;
 					break;
 				case D_SECTLOG:
 					if (slflag)
-						respec('d', dopts, D_SECTLOG);
+						respec('d', subopts, D_SECTLOG);
 					if (ssflag)
-						conflict('d', dopts, D_SECTSIZE,
+						conflict('d', subopts, D_SECTSIZE,
 							 D_SECTLOG);
-					sectorlog = getnum_checked(value,
-							XFS_MIN_SECTORSIZE_LOG,
-							XFS_MAX_SECTORSIZE_LOG,
-							"d sectlog", 'd', dopts,
-							D_SECTLOG);
+					sectorlog = getnum_checked(value, &dopts,
+								   D_SECTLOG);
 					sectorsize = 1 << sectorlog;
 					slflag = 1;
 					break;
 				case D_SECTSIZE:
 					if (!value || *value == '\0')
-						reqval('d', dopts, D_SECTSIZE);
+						reqval('d', subopts, D_SECTSIZE);
 					if (ssflag)
-						respec('d', dopts, D_SECTSIZE);
+						respec('d', subopts, D_SECTSIZE);
 					if (slflag)
-						conflict('d', dopts, D_SECTLOG,
+						conflict('d', subopts, D_SECTLOG,
 							 D_SECTSIZE);
 					sectorsize = getnum(value, blocksize,
 							    sectorsize, true);
@@ -1383,14 +1613,14 @@ main(
 					break;
 				case D_PROJINHERIT:
 					if (!value || *value == '\0')
-						reqval('d', dopts, D_PROJINHERIT);
+						reqval('d', subopts, D_PROJINHERIT);
 					fsx.fsx_projid = atoi(value);
 					fsx.fsx_xflags |= \
 						XFS_DIFLAG_PROJINHERIT;
 					break;
 				case D_EXTSZINHERIT:
 					if (!value || *value == '\0')
-						reqval('d', dopts, D_EXTSZINHERIT);
+						reqval('d', subopts, D_EXTSZINHERIT);
 					fsx.fsx_extsize = atoi(value);
 					fsx.fsx_xflags |= \
 						XFS_DIFLAG_EXTSZINHERIT;
@@ -1403,37 +1633,34 @@ main(
 		case 'i':
 			p = optarg;
 			while (*p != '\0') {
+				char	**subopts = (char **)iopts.subopts;
 				char	*value;
 
-				switch (getsubopt(&p, (constpp)iopts, &value)) {
+				switch (getsubopt(&p, (constpp)subopts,
+						  &value)) {
 				case I_ALIGN:
 					sb_feat.inode_align = getbool(
 							value, "i align", true);
 					break;
 				case I_LOG:
-					if (!value || *value == '\0')
-						reqval('i', iopts, I_LOG);
 					if (ilflag)
-						respec('i', iopts, I_LOG);
+						respec('i', subopts, I_LOG);
 					if (ipflag)
-						conflict('i', iopts, I_PERBLOCK,
+						conflict('i', subopts, I_PERBLOCK,
 							 I_LOG);
 					if (isflag)
-						conflict('i', iopts, I_SIZE,
+						conflict('i', subopts, I_SIZE,
 							 I_LOG);
-					inodelog = getnum_checked(value,
-							XFS_DINODE_MIN_LOG,
-							XFS_DINODE_MAX_LOG,
-							"i log", 'i', iopts,
-							I_LOG);
+					inodelog = getnum_checked(value, &iopts,
+								  I_LOG);
 					isize = 1 << inodelog;
 					ilflag = 1;
 					break;
 				case I_MAXPCT:
 					if (!value || *value == '\0')
-						reqval('i', iopts, I_MAXPCT);
+						reqval('i', subopts, I_MAXPCT);
 					if (imflag)
-						respec('i', iopts, I_MAXPCT);
+						respec('i', subopts, I_MAXPCT);
 					imaxpct = getnum(value, 0, 0, false);
 					if (imaxpct < 0 || imaxpct > 100)
 						illegal(value, "i maxpct");
@@ -1441,14 +1668,14 @@ main(
 					break;
 				case I_PERBLOCK:
 					if (!value || *value == '\0')
-						reqval('i', iopts, I_PERBLOCK);
+						reqval('i', subopts, I_PERBLOCK);
 					if (ilflag)
-						conflict('i', iopts, I_LOG,
+						conflict('i', subopts, I_LOG,
 							 I_PERBLOCK);
 					if (ipflag)
-						respec('i', iopts, I_PERBLOCK);
+						respec('i', subopts, I_PERBLOCK);
 					if (isflag)
-						conflict('i', iopts, I_SIZE,
+						conflict('i', subopts, I_SIZE,
 							 I_PERBLOCK);
 					inopblock = getnum(value, 0, 0, false);
 					if (inopblock <
@@ -1459,15 +1686,15 @@ main(
 					break;
 				case I_SIZE:
 					if (!value || *value == '\0')
-						reqval('i', iopts, I_SIZE);
+						reqval('i', subopts, I_SIZE);
 					if (ilflag)
-						conflict('i', iopts, I_LOG,
+						conflict('i', subopts, I_LOG,
 							 I_SIZE);
 					if (ipflag)
-						conflict('i', iopts, I_PERBLOCK,
+						conflict('i', subopts, I_PERBLOCK,
 							 I_SIZE);
 					if (isflag)
-						respec('i', iopts, I_SIZE);
+						respec('i', subopts, I_SIZE);
 					isize = getnum(value, 0, 0, true);
 					if (isize <= 0 || !ispow2(isize))
 						illegal(value, "i size");
@@ -1476,7 +1703,7 @@ main(
 					break;
 				case I_ATTR:
 					if (!value || *value == '\0')
-						reqval('i', iopts, I_ATTR);
+						reqval('i', subopts, I_ATTR);
 					c = getnum(value, 0, 0, false);
 					if (c < 0 || c > 2)
 						illegal(value, "i attr");
@@ -1498,16 +1725,18 @@ main(
 		case 'l':
 			p = optarg;
 			while (*p != '\0') {
+				char	**subopts = (char **)lopts.subopts;
 				char	*value;
 
-				switch (getsubopt(&p, (constpp)lopts, &value)) {
+				switch (getsubopt(&p, (constpp)subopts,
+						  &value)) {
 				case L_AGNUM:
 					if (!value || *value == '\0')
-						reqval('l', lopts, L_AGNUM);
+						reqval('l', subopts, L_AGNUM);
 					if (laflag)
-						respec('l', lopts, L_AGNUM);
+						respec('l', subopts, L_AGNUM);
 					if (ldflag)
-						conflict('l', lopts, L_AGNUM, L_DEV);
+						conflict('l', subopts, L_AGNUM, L_DEV);
 					logagno = getnum(value, 0, 0, false);
 					if ((__int64_t)logagno < 0)
 						illegal(value, "l agno");
@@ -1515,7 +1744,7 @@ main(
 					break;
 				case L_FILE:
 					if (loginternal)
-						conflict('l', lopts, L_INTERNAL,
+						conflict('l', subopts, L_INTERNAL,
 							 L_FILE);
 					xi.lisfile = getbool(value, "l file",
 							     true);
@@ -1524,12 +1753,12 @@ main(
 					break;
 				case L_INTERNAL:
 					if (ldflag)
-						conflict('l', lopts, L_INTERNAL, L_DEV);
+						conflict('l', subopts, L_INTERNAL, L_DEV);
 					if (xi.lisfile)
-						conflict('l', lopts, L_FILE,
+						conflict('l', subopts, L_FILE,
 							 L_INTERNAL);
 					if (liflag)
-						respec('l', lopts, L_INTERNAL);
+						respec('l', subopts, L_INTERNAL);
 
 					loginternal = getbool(value,
 							"l internal", true);
@@ -1537,9 +1766,9 @@ main(
 					break;
 				case L_SU:
 					if (!value || *value == '\0')
-						reqval('l', lopts, L_SU);
+						reqval('l', subopts, L_SU);
 					if (lsu)
-						respec('l', lopts, L_SU);
+						respec('l', subopts, L_SU);
 					lsu = getnum(value, blocksize,
 						     sectorsize, true);
 					if (lsu < 0)
@@ -1548,9 +1777,9 @@ main(
 					break;
 				case L_SUNIT:
 					if (!value || *value == '\0')
-						reqval('l', lopts, L_SUNIT);
+						reqval('l', subopts, L_SUNIT);
 					if (lsunit)
-						respec('l', lopts, L_SUNIT);
+						respec('l', subopts, L_SUNIT);
 					lsunit = getnum(value, 0, 0, false);
 					if (lsunit < 0)
 						illegal(value, "l sunit");
@@ -1559,13 +1788,13 @@ main(
 				case L_NAME:
 				case L_DEV:
 					if (laflag)
-						conflict('l', lopts, L_AGNUM, L_DEV);
+						conflict('l', subopts, L_AGNUM, L_DEV);
 					if (liflag)
-						conflict('l', lopts, L_INTERNAL, L_DEV);
+						conflict('l', subopts, L_INTERNAL, L_DEV);
 					if (!value || *value == '\0')
-						reqval('l', lopts, L_NAME);
+						reqval('l', subopts, L_NAME);
 					if (xi.logname)
-						respec('l', lopts, L_NAME);
+						respec('l', subopts, L_NAME);
 					ldflag = 1;
 					loginternal = 0;
 					logfile = value;
@@ -1573,9 +1802,9 @@ main(
 					break;
 				case L_VERSION:
 					if (!value || *value == '\0')
-						reqval('l', lopts, L_VERSION);
+						reqval('l', subopts, L_VERSION);
 					if (lvflag)
-						respec('l', lopts, L_VERSION);
+						respec('l', subopts, L_VERSION);
 					c = getnum(value, 0, 0, false);
 					if (c < 1 || c > 2)
 						illegal(value, "l version");
@@ -1584,33 +1813,30 @@ main(
 					break;
 				case L_SIZE:
 					if (!value || *value == '\0')
-						reqval('l', lopts, L_SIZE);
+						reqval('l', subopts, L_SIZE);
 					if (logsize)
-						respec('l', lopts, L_SIZE);
+						respec('l', subopts, L_SIZE);
 					logsize = value;
 					lsflag = 1;
 					break;
 				case L_SECTLOG:
 					if (lslflag)
-						respec('l', lopts, L_SECTLOG);
+						respec('l', subopts, L_SECTLOG);
 					if (lssflag)
-						conflict('l', lopts, L_SECTSIZE,
+						conflict('l', subopts, L_SECTSIZE,
 							 L_SECTLOG);
 					lsectorlog = getnum_checked(value,
-							XFS_MIN_SECTORSIZE_LOG,
-							XFS_MAX_SECTORSIZE_LOG,
-							"l sectlog", 'l', lopts,
-							L_SECTLOG);
+							&lopts, L_SECTLOG);
 					lsectorsize = 1 << lsectorlog;
 					lslflag = 1;
 					break;
 				case L_SECTSIZE:
 					if (!value || *value == '\0')
-						reqval('l', lopts, L_SECTSIZE);
+						reqval('l', subopts, L_SECTSIZE);
 					if (lssflag)
-						respec('l', lopts, L_SECTSIZE);
+						respec('l', subopts, L_SECTSIZE);
 					if (lslflag)
-						conflict('l', lopts, L_SECTLOG,
+						conflict('l', subopts, L_SECTLOG,
 							 L_SECTSIZE);
 					lsectorsize = getnum(value, blocksize,
 							     sectorsize, true);
@@ -1639,9 +1865,11 @@ main(
 		case 'm':
 			p = optarg;
 			while (*p != '\0') {
+				char	**subopts = (char **)mopts.subopts;
 				char	*value;
 
-				switch (getsubopt(&p, (constpp)mopts, &value)) {
+				switch (getsubopt(&p, (constpp)subopts,
+						  &value)) {
 				case M_CRC:
 					sb_feat.crcs_enabled = getbool(
 							value, "m crc", true);
@@ -1655,7 +1883,7 @@ main(
 					break;
 				case M_UUID:
 					if (!value || *value == '\0')
-						reqval('m', mopts, M_UUID);
+						reqval('m', subopts, M_UUID);
 					if (platform_uuid_parse(value, &uuid))
 						illegal(optarg, "m uuid");
 					break;
@@ -1667,30 +1895,29 @@ main(
 		case 'n':
 			p = optarg;
 			while (*p != '\0') {
+				char	**subopts = (char **)nopts.subopts;
 				char	*value;
 
-				switch (getsubopt(&p, (constpp)nopts, &value)) {
+				switch (getsubopt(&p, (constpp)subopts,
+						  &value)) {
 				case N_LOG:
 					if (nlflag)
-						respec('n', nopts, N_LOG);
+						respec('n', subopts, N_LOG);
 					if (nsflag)
-						conflict('n', nopts, N_SIZE,
+						conflict('n', subopts, N_SIZE,
 							 N_LOG);
 					dirblocklog = getnum_checked(value,
-							XFS_MIN_REC_DIRSIZE,
-							XFS_MAX_BLOCKSIZE_LOG,
-							"n log", 'n', nopts,
-							N_LOG);
+								&nopts, N_LOG);
 					dirblocksize = 1 << dirblocklog;
 					nlflag = 1;
 					break;
 				case N_SIZE:
 					if (!value || *value == '\0')
-						reqval('n', nopts, N_SIZE);
+						reqval('n', subopts, N_SIZE);
 					if (nsflag)
-						respec('n', nopts, N_SIZE);
+						respec('n', subopts, N_SIZE);
 					if (nlflag)
-						conflict('n', nopts, N_LOG,
+						conflict('n', subopts, N_LOG,
 							 N_SIZE);
 					dirblocksize = getnum(value, blocksize,
 							      sectorsize, true);
@@ -1703,9 +1930,9 @@ main(
 					break;
 				case N_VERSION:
 					if (!value || *value == '\0')
-						reqval('n', nopts, N_VERSION);
+						reqval('n', subopts, N_VERSION);
 					if (nvflag)
-						respec('n', nopts, N_VERSION);
+						respec('n', subopts, N_VERSION);
 					if (!strcasecmp(value, "ci")) {
 						/* ASCII CI mode */
 						sb_feat.nci = true;
@@ -1720,7 +1947,7 @@ main(
 					break;
 				case N_FTYPE:
 					if (nftype)
-						respec('n', nopts, N_FTYPE);
+						respec('n', subopts, N_FTYPE);
 					sb_feat.dirftype = getbool(value,
 							     "n ftype", true);
 					nftype = 1;
@@ -1747,14 +1974,16 @@ main(
 		case 'r':
 			p = optarg;
 			while (*p != '\0') {
+				char	**subopts = (char **)ropts.subopts;
 				char	*value;
 
-				switch (getsubopt(&p, (constpp)ropts, &value)) {
+				switch (getsubopt(&p, (constpp)subopts,
+						  &value)) {
 				case R_EXTSIZE:
 					if (!value || *value == '\0')
-						reqval('r', ropts, R_EXTSIZE);
+						reqval('r', subopts, R_EXTSIZE);
 					if (rtextsize)
-						respec('r', ropts, R_EXTSIZE);
+						respec('r', subopts, R_EXTSIZE);
 					rtextsize = value;
 					break;
 				case R_FILE:
@@ -1766,16 +1995,16 @@ main(
 				case R_NAME:
 				case R_DEV:
 					if (!value || *value == '\0')
-						reqval('r', ropts, R_NAME);
+						reqval('r', subopts, R_NAME);
 					if (xi.rtname)
-						respec('r', ropts, R_NAME);
+						respec('r', subopts, R_NAME);
 					xi.rtname = value;
 					break;
 				case R_SIZE:
 					if (!value || *value == '\0')
-						reqval('r', ropts, R_SIZE);
+						reqval('r', subopts, R_SIZE);
 					if (rtsize)
-						respec('r', ropts, R_SIZE);
+						respec('r', subopts, R_SIZE);
 					rtsize = value;
 					break;
 				case R_NOALIGN:
@@ -1789,21 +2018,20 @@ main(
 		case 's':
 			p = optarg;
 			while (*p != '\0') {
+				char	**subopts = (char **)sopts.subopts;
 				char	*value;
 
-				switch (getsubopt(&p, (constpp)sopts, &value)) {
+				switch (getsubopt(&p, (constpp)subopts,
+						  &value)) {
 				case S_LOG:
 				case S_SECTLOG:
 					if (slflag || lslflag)
-						respec('s', sopts, S_SECTLOG);
+						respec('s', subopts, S_SECTLOG);
 					if (ssflag || lssflag)
-						conflict('s', sopts, S_SECTSIZE,
-							 S_SECTLOG);
-					sectorlog = getnum_checked(value,
-							XFS_MIN_SECTORSIZE_LOG,
-							XFS_MAX_SECTORSIZE_LOG,
-							"s sectlog", 's', sopts,
-							S_SECTLOG);
+						conflict('s', subopts,
+							 S_SECTSIZE, S_SECTLOG);
+					sectorlog = getnum_checked(value, &sopts,
+								   S_SECTLOG);
 					lsectorlog = sectorlog;
 					sectorsize = 1 << sectorlog;
 					lsectorsize = sectorsize;
@@ -1812,11 +2040,11 @@ main(
 				case S_SIZE:
 				case S_SECTSIZE:
 					if (!value || *value == '\0')
-						reqval('s', sopts, S_SECTSIZE);
+						reqval('s', subopts, S_SECTSIZE);
 					if (ssflag || lssflag)
-						respec('s', sopts, S_SECTSIZE);
+						respec('s', subopts, S_SECTSIZE);
 					if (slflag || lslflag)
-						conflict('s', sopts, S_SECTLOG,
+						conflict('s', subopts, S_SECTLOG,
 							 S_SECTSIZE);
 					sectorsize = getnum(value, blocksize,
 							    sectorsize, true);
-- 
2.5.0

_______________________________________________
xfs mailing list
xfs@oss.sgi.com
http://oss.sgi.com/mailman/listinfo/xfs

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

* [PATCH 08/19] mkfs: getbool is redundant
  2016-04-21  9:39 [PATCH 00/19 v2] mkfs cleaning Jan Tulak
                   ` (6 preceding siblings ...)
  2016-04-21  9:39 ` [PATCH 07/19] mkfs: structify input parameter passing Jan Tulak
@ 2016-04-21  9:39 ` Jan Tulak
  2016-05-02 23:08   ` Eric Sandeen
  2016-04-21  9:39 ` [PATCH 09/19] mkfs: use getnum_checked for all ranged parameters Jan Tulak
                   ` (13 subsequent siblings)
  21 siblings, 1 reply; 51+ messages in thread
From: Jan Tulak @ 2016-04-21  9:39 UTC (permalink / raw)
  To: xfs

From: Dave Chinner <dchinner@redhat.com>

getbool() can be replaced with getnum_checked with appropriate
min/max values set for the boolean variables. Make boolean
arguments consistent - all accept 0 or 1 value now.

Signed-off-by: Dave Chinner <dchinner@redhat.com>
Signed-off-by: Jan Tulak <jtulak@redhat.com>

---
CHANGES:
* man page fixes
---
 man/man8/mkfs.xfs.8 |  19 +++--
 mkfs/xfs_mkfs.c     | 219 +++++++++++++++++++++++++++++++++++++---------------
 2 files changed, 169 insertions(+), 69 deletions(-)

diff --git a/man/man8/mkfs.xfs.8 b/man/man8/mkfs.xfs.8
index 8b068ef..be3d1a0 100644
--- a/man/man8/mkfs.xfs.8
+++ b/man/man8/mkfs.xfs.8
@@ -118,6 +118,9 @@ option or the
 option first needs to be added to the command line.
 Failure to specify the size of the units will result in illegal value errors
 when parameters are quantified in those units.
+.PP
+Many options allows for optional argument of value 0 or 1, to explicitly
+disable or enable the functionality.
 .SH OPTIONS
 .TP
 .BI \-b " block_size_options"
@@ -312,10 +315,12 @@ and
 .B swidth
 values.
 .TP
-.BI noalign
-This option disables automatic geometry detection and creates the filesystem
+.BI noalign[= value ]
+If the
+.I value
+is 1, this option disables automatic geometry detection and creates the filesystem
 without stripe geometry alignment even if the underlying storage device provides
-this information.
+this information. 0 disables this option, that is, enables automatic detection.
 .RE
 .TP
 .B \-f
@@ -805,9 +810,11 @@ This suboption is only needed if the real-time section of the
 filesystem should occupy less space than the size of the partition
 or logical volume containing the section.
 .TP
-.BI noalign
-This option disables stripe size detection, enforcing a realtime device with no
-stripe geometry.
+.BI noalign[= value ]
+If the
+.I value
+is 1, then the option disables stripe size detection, enforcing a realtime
+device with no stripe geometry. 0 will enable stripe size detection.
 .RE
 .TP
 .BI \-s " sector_size"
diff --git a/mkfs/xfs_mkfs.c b/mkfs/xfs_mkfs.c
index 86cfb7b..2f76b67 100644
--- a/mkfs/xfs_mkfs.c
+++ b/mkfs/xfs_mkfs.c
@@ -49,6 +49,7 @@ static long long cvtnum(unsigned int blocksize,
 			unsigned int sectorsize, const char *s);
 
 #define MAX_SUBOPTS	16
+#define SUBOPT_NEEDS_VAL	(-1LL)
 /*
  * Table for parsing mkfs parameters.
  *
@@ -83,6 +84,13 @@ static long long cvtnum(unsigned int blocksize,
  *     (Said in another way, you can't have minval and maxval both equal
  *     to zero. But if one value is different: minval=0 and maxval=1,
  *     then it is OK.)
+ *
+ *   defaultval MANDATORY
+ *     The value used if user specifies the subopt, but no value.
+ *     If the subopt accepts some values (-d file=[1|0]), then this
+ *     sets what is used with simple specifying the subopt (-d file).
+ *     A special SUBOPT_NEEDS_VAL can be used to require a user-given
+ *     value in any case.
  */
 struct opt_params {
 	const char	name;
@@ -91,6 +99,7 @@ struct opt_params {
 		int		index;
 		long long	minval;
 		long long	maxval;
+		long long	defaultval;
 	}		subopt_params[MAX_SUBOPTS];
 };
 
@@ -107,10 +116,12 @@ struct opt_params bopts = {
 		{ .index = B_LOG,
 		  .minval = XFS_MIN_BLOCKSIZE_LOG,
 		  .maxval = XFS_MAX_BLOCKSIZE_LOG,
+		  .defaultval = SUBOPT_NEEDS_VAL,
 		},
 		{ .index = B_SIZE,
 		  .minval = XFS_MIN_BLOCKSIZE,
 		  .maxval = XFS_MAX_BLOCKSIZE,
+		  .defaultval = SUBOPT_NEEDS_VAL,
 		},
 	},
 };
@@ -152,38 +163,57 @@ struct opt_params dopts = {
 	},
 	.subopt_params = {
 		{ .index = D_AGCOUNT,
+		  .defaultval = SUBOPT_NEEDS_VAL,
 		},
 		{ .index = D_FILE,
+		  .minval = 0,
+		  .maxval = 1,
+		  .defaultval = 1,
 		},
 		{ .index = D_NAME,
+		  .defaultval = SUBOPT_NEEDS_VAL,
 		},
 		{ .index = D_SIZE,
+		  .defaultval = SUBOPT_NEEDS_VAL,
 		},
 		{ .index = D_SUNIT,
+		  .defaultval = SUBOPT_NEEDS_VAL,
 		},
 		{ .index = D_SWIDTH,
+		  .defaultval = SUBOPT_NEEDS_VAL,
 		},
 		{ .index = D_AGSIZE,
+		  .defaultval = SUBOPT_NEEDS_VAL,
 		},
 		{ .index = D_SU,
+		  .defaultval = SUBOPT_NEEDS_VAL,
 		},
 		{ .index = D_SW,
+		  .defaultval = SUBOPT_NEEDS_VAL,
 		},
 		{ .index = D_SECTLOG,
 		  .minval = XFS_MIN_SECTORSIZE_LOG,
 		  .maxval = XFS_MAX_SECTORSIZE_LOG,
+		  .defaultval = SUBOPT_NEEDS_VAL,
 		},
 		{ .index = D_SECTSIZE,
 		  .minval = XFS_MIN_SECTORSIZE,
 		  .maxval = XFS_MAX_SECTORSIZE,
+		  .defaultval = SUBOPT_NEEDS_VAL,
 		},
 		{ .index = D_NOALIGN,
+		  .minval = 0,
+		  .maxval = 1,
+		  .defaultval = 1,
 		},
 		{ .index = D_RTINHERIT,
+		  .defaultval = SUBOPT_NEEDS_VAL,
 		},
 		{ .index = D_PROJINHERIT,
+		  .defaultval = SUBOPT_NEEDS_VAL,
 		},
 		{ .index = D_EXTSZINHERIT,
+		  .defaultval = SUBOPT_NEEDS_VAL,
 		},
 	},
 };
@@ -212,22 +242,36 @@ struct opt_params iopts = {
 	},
 	.subopt_params = {
 		{ .index = I_ALIGN,
+		  .minval = 0,
+		  .maxval = 1,
+		  .defaultval = 1,
 		},
 		{ .index = I_LOG,
 		  .minval = XFS_DINODE_MIN_LOG,
 		  .maxval = XFS_DINODE_MAX_LOG,
+		  .defaultval = SUBOPT_NEEDS_VAL,
 		},
 		{ .index = I_MAXPCT,
+		  .defaultval = SUBOPT_NEEDS_VAL,
 		},
 		{ .index = I_PERBLOCK,
+		  .defaultval = SUBOPT_NEEDS_VAL,
 		},
 		{ .index = I_SIZE,
+		  .defaultval = SUBOPT_NEEDS_VAL,
 		},
 		{ .index = I_ATTR,
+		  .defaultval = SUBOPT_NEEDS_VAL,
 		},
 		{ .index = I_PROJID32BIT,
+		  .minval = 0,
+		  .maxval = 1,
+		  .defaultval = 1,
 		},
 		{ .index = I_SPINODES,
+		  .minval = 0,
+		  .maxval = 1,
+		  .defaultval = 1,
 		},
 	},
 };
@@ -263,32 +307,50 @@ struct opt_params lopts = {
 	},
 	.subopt_params = {
 		{ .index = L_AGNUM,
+		  .defaultval = SUBOPT_NEEDS_VAL,
 		},
 		{ .index = L_INTERNAL,
+		  .minval = 0,
+		  .maxval = 1,
+		  .defaultval = 1,
 		},
 		{ .index = L_SIZE,
+		  .defaultval = SUBOPT_NEEDS_VAL,
 		},
 		{ .index = L_VERSION,
+		  .defaultval = SUBOPT_NEEDS_VAL,
 		},
 		{ .index = L_SUNIT,
+		  .defaultval = SUBOPT_NEEDS_VAL,
 		},
 		{ .index = L_SU,
+		  .defaultval = SUBOPT_NEEDS_VAL,
 		},
 		{ .index = L_DEV,
+		  .defaultval = SUBOPT_NEEDS_VAL,
 		},
 		{ .index = L_SECTLOG,
 		  .minval = XFS_MIN_SECTORSIZE_LOG,
 		  .maxval = XFS_MAX_SECTORSIZE_LOG,
+		  .defaultval = SUBOPT_NEEDS_VAL,
 		},
 		{ .index = L_SECTSIZE,
 		  .minval = XFS_MIN_SECTORSIZE,
 		  .maxval = XFS_MAX_SECTORSIZE,
+		  .defaultval = SUBOPT_NEEDS_VAL,
 		},
 		{ .index = L_FILE,
+		  .minval = 0,
+		  .maxval = 1,
+		  .defaultval = 1,
 		},
 		{ .index = L_NAME,
+		  .defaultval = SUBOPT_NEEDS_VAL,
 		},
 		{ .index = L_LAZYSBCNTR,
+		  .minval = 0,
+		  .maxval = 1,
+		  .defaultval = 1,
 		},
 	},
 };
@@ -310,14 +372,20 @@ struct opt_params nopts = {
 		{ .index = N_LOG,
 		  .minval = XFS_MIN_REC_DIRSIZE,
 		  .maxval = XFS_MAX_BLOCKSIZE_LOG,
+		  .defaultval = SUBOPT_NEEDS_VAL,
 		},
 		{ .index = N_SIZE,
 		  .minval = 1 << XFS_MIN_REC_DIRSIZE,
 		  .maxval = XFS_MAX_BLOCKSIZE,
+		  .defaultval = SUBOPT_NEEDS_VAL,
 		},
 		{ .index = N_VERSION,
+		  .defaultval = SUBOPT_NEEDS_VAL,
 		},
 		{ .index = N_FTYPE,
+		  .minval = 0,
+		  .maxval = 1,
+		  .defaultval = 1,
 		},
 	},
 };
@@ -341,16 +409,26 @@ struct opt_params ropts = {
 	},
 	.subopt_params = {
 		{ .index = R_EXTSIZE,
+		  .defaultval = SUBOPT_NEEDS_VAL,
 		},
 		{ .index = R_SIZE,
+		  .defaultval = SUBOPT_NEEDS_VAL,
 		},
 		{ .index = R_DEV,
+		  .defaultval = SUBOPT_NEEDS_VAL,
 		},
 		{ .index = R_FILE,
+		  .minval = 0,
+		  .maxval = 1,
+		  .defaultval = 1,
 		},
 		{ .index = R_NAME,
+		  .defaultval = SUBOPT_NEEDS_VAL,
 		},
 		{ .index = R_NOALIGN,
+		  .minval = 0,
+		  .maxval = 1,
+		  .defaultval = 1,
 		},
 	},
 };
@@ -372,18 +450,22 @@ struct opt_params sopts = {
 		{ .index = S_LOG,
 		  .minval = XFS_MIN_SECTORSIZE_LOG,
 		  .maxval = XFS_MAX_SECTORSIZE_LOG,
+		  .defaultval = SUBOPT_NEEDS_VAL,
 		},
 		{ .index = S_SECTLOG,
 		  .minval = XFS_MIN_SECTORSIZE_LOG,
 		  .maxval = XFS_MAX_SECTORSIZE_LOG,
+		  .defaultval = SUBOPT_NEEDS_VAL,
 		},
 		{ .index = S_SIZE,
 		  .minval = XFS_MIN_SECTORSIZE,
 		  .maxval = XFS_MAX_SECTORSIZE,
+		  .defaultval = SUBOPT_NEEDS_VAL,
 		},
 		{ .index = S_SECTSIZE,
 		  .minval = XFS_MIN_SECTORSIZE,
 		  .maxval = XFS_MAX_SECTORSIZE,
+		  .defaultval = SUBOPT_NEEDS_VAL,
 		},
 	},
 };
@@ -394,13 +476,24 @@ struct opt_params mopts = {
 #define	M_CRC		0
 		"crc",
 #define M_FINOBT	1
-	"finobt",
+		"finobt",
 #define M_UUID		2
 		"uuid",
 		NULL
 	},
 	.subopt_params = {
 		{ .index = M_CRC,
+		  .minval = 0,
+		  .maxval = 1,
+		  .defaultval = 1,
+		},
+		{ .index = M_FINOBT,
+		  .minval = 0,
+		  .maxval = 1,
+		  .defaultval = 1,
+		},
+		{ .index = M_UUID,
+		  .defaultval = SUBOPT_NEEDS_VAL,
 		},
 	},
 };
@@ -1221,22 +1314,6 @@ getnum(
 	return i;
 }
 
-static bool
-getbool(
-	const char	*str,
-	const char	*illegal_str,
-	bool		default_val)
-{
-	long long	c;
-
-	if (!str || *str == '\0')
-		return default_val;
-	c = getnum(str, 0, 0, false);
-	if (c < 0 || c > 1)
-		illegal(str, illegal_str);
-	return c ? true : false;
-}
-
 static __attribute__((noreturn)) void
 illegal_option(
 	const char	*value,
@@ -1251,17 +1328,27 @@ illegal_option(
 
 static int
 getnum_checked(
-	const char	*str,
+	const char		*str,
 	struct opt_params	*opts,
-	int		index)
+	int			index)
 {
-	long long	c;
+	const struct subopt_param *sp = &opts->subopt_params[index];
+	long long		c;
 
-	if (!str || *str == '\0')
+	if (sp->index != index) {
+		fprintf(stderr,
+	("Developer screwed up option parsing (%d/%d)! Please report!\n"),
+			sp->index, index);
 		reqval(opts->name, (char **)opts->subopts, index);
+	}
+
+	if (!str || *str == '\0') {
+		if (sp->defaultval == SUBOPT_NEEDS_VAL)
+			reqval(opts->name, (char **)opts->subopts, index);
+		return sp->defaultval;
+	}
 
-	if (opts->subopt_params[index].minval == 0 &&
-	    opts->subopt_params[index].maxval == 0) {
+	if (sp->minval == 0 && sp->maxval == 0) {
 		fprintf(stderr,
 			_("Option -%c %s has undefined minval/maxval."
 			  "Can't verify value range. This is a bug.\n"),
@@ -1270,8 +1357,7 @@ getnum_checked(
 	}
 
 	c = getnum(str, 0, 0, false);
-	if (c < opts->subopt_params[index].minval ||
-	    c > opts->subopt_params[index].maxval)
+	if (c < sp->minval || c > sp->maxval)
 		illegal_option(str, opts, index);
 	return c;
 }
@@ -1496,8 +1582,8 @@ main(
 					dasize = 1;
 					break;
 				case D_FILE:
-					xi.disfile = getbool(value, "d file",
-							     true);
+					xi.disfile = getnum_checked(value,
+								&dopts, D_FILE);
 					if (xi.disfile && !Nflag)
 						xi.dcreat = 1;
 					break;
@@ -1565,19 +1651,22 @@ main(
 						illegal(value, "d sw");
 					break;
 				case D_NOALIGN:
-					if (dsu)
-						conflict('d', subopts, D_SU,
-							 D_NOALIGN);
-					if (dsunit)
-						conflict('d', subopts, D_SUNIT,
-							 D_NOALIGN);
-					if (dsw)
-						conflict('d', subopts, D_SW,
-							 D_NOALIGN);
-					if (dswidth)
-						conflict('d', subopts, D_SWIDTH,
-							 D_NOALIGN);
-					nodsflag = 1;
+					nodsflag = getnum_checked(value,
+								&dopts, D_NOALIGN);
+					if (nodsflag) {
+						if (dsu)
+							conflict('d', subopts, D_SU,
+								D_NOALIGN);
+						if (dsunit)
+							conflict('d', subopts, D_SUNIT,
+								D_NOALIGN);
+						if (dsw)
+							conflict('d', subopts, D_SW,
+								D_NOALIGN);
+						if (dswidth)
+							conflict('d', subopts, D_SWIDTH,
+								D_NOALIGN);
+					}
 					break;
 				case D_SECTLOG:
 					if (slflag)
@@ -1639,8 +1728,8 @@ main(
 				switch (getsubopt(&p, (constpp)subopts,
 						  &value)) {
 				case I_ALIGN:
-					sb_feat.inode_align = getbool(
-							value, "i align", true);
+					sb_feat.inode_align = getnum_checked(
+							value, &iopts, I_ALIGN);
 					break;
 				case I_LOG:
 					if (ilflag)
@@ -1710,12 +1799,14 @@ main(
 					sb_feat.attr_version = c;
 					break;
 				case I_PROJID32BIT:
-					sb_feat.projid16bit = !getbool(value,
-							"i projid32bit", false);
+					sb_feat.projid16bit =
+						!getnum_checked(value, &iopts,
+								I_PROJID32BIT);
 					break;
 				case I_SPINODES:
-					sb_feat.spinodes = getbool(value,
-							"i spinodes", true);
+					sb_feat.spinodes =
+						getnum_checked(value, &iopts,
+								I_SPINODES);
 					break;
 				default:
 					unknown('i', value);
@@ -1743,11 +1834,11 @@ main(
 					laflag = 1;
 					break;
 				case L_FILE:
-					if (loginternal)
+					xi.lisfile = getnum_checked(value,
+								&lopts, L_FILE);
+					if (xi.lisfile && loginternal)
 						conflict('l', subopts, L_INTERNAL,
 							 L_FILE);
-					xi.lisfile = getbool(value, "l file",
-							     true);
 					if (xi.lisfile)
 						xi.lcreat = 1;
 					break;
@@ -1760,8 +1851,8 @@ main(
 					if (liflag)
 						respec('l', subopts, L_INTERNAL);
 
-					loginternal = getbool(value,
-							"l internal", true);
+					loginternal = getnum_checked(value,
+							&lopts, L_INTERNAL);
 					liflag = 1;
 					break;
 				case L_SU:
@@ -1848,9 +1939,9 @@ main(
 					lssflag = 1;
 					break;
 				case L_LAZYSBCNTR:
-					sb_feat.lazy_sb_counters = getbool(
-							value, "l lazy-count",
-							true);
+					sb_feat.lazy_sb_counters =
+						getnum_checked(value, &lopts,
+							       L_LAZYSBCNTR);
 					break;
 				default:
 					unknown('l', value);
@@ -1871,15 +1962,16 @@ main(
 				switch (getsubopt(&p, (constpp)subopts,
 						  &value)) {
 				case M_CRC:
-					sb_feat.crcs_enabled = getbool(
-							value, "m crc", true);
+					sb_feat.crcs_enabled =
+						getnum_checked(value, &mopts,
+							       M_CRC);
 					if (sb_feat.crcs_enabled)
 						sb_feat.dirftype = true;
 					break;
 				case M_FINOBT:
 					sb_feat.finobtflag = true;
-					sb_feat.finobt = getbool(
-						value, "m finobt", true);
+					sb_feat.finobt = getnum_checked(
+						value, &mopts, M_FINOBT);
 					break;
 				case M_UUID:
 					if (!value || *value == '\0')
@@ -1948,8 +2040,8 @@ main(
 				case N_FTYPE:
 					if (nftype)
 						respec('n', subopts, N_FTYPE);
-					sb_feat.dirftype = getbool(value,
-							     "n ftype", true);
+					sb_feat.dirftype = getnum_checked(value,
+								&nopts, N_FTYPE);
 					nftype = 1;
 					break;
 				default:
@@ -1987,8 +2079,8 @@ main(
 					rtextsize = value;
 					break;
 				case R_FILE:
-					xi.risfile = getbool(value,
-							     "r file", true);
+					xi.risfile = getnum_checked(value,
+								&ropts, R_FILE);
 					if (xi.risfile)
 						xi.rcreat = 1;
 					break;
@@ -2008,7 +2100,8 @@ main(
 					rtsize = value;
 					break;
 				case R_NOALIGN:
-					norsflag = 1;
+					norsflag = getnum_checked(value,
+								&ropts, R_NOALIGN);
 					break;
 				default:
 					unknown('r', value);
-- 
2.5.0

_______________________________________________
xfs mailing list
xfs@oss.sgi.com
http://oss.sgi.com/mailman/listinfo/xfs

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

* [PATCH 09/19] mkfs: use getnum_checked for all ranged parameters
  2016-04-21  9:39 [PATCH 00/19 v2] mkfs cleaning Jan Tulak
                   ` (7 preceding siblings ...)
  2016-04-21  9:39 ` [PATCH 08/19] mkfs: getbool is redundant Jan Tulak
@ 2016-04-21  9:39 ` Jan Tulak
  2016-04-21  9:39 ` [PATCH 10/19] mkfs: add respecification detection to generic parsing Jan Tulak
                   ` (12 subsequent siblings)
  21 siblings, 0 replies; 51+ messages in thread
From: Jan Tulak @ 2016-04-21  9:39 UTC (permalink / raw)
  To: xfs

From: Dave Chinner <dchinner@redhat.com>

Now that getnum_checked can handle min/max checking, use this for
all parameters that take straight numbers and don't require unit
conversions.

Signed-off-by: Dave Chinner <dchinner@redhat.com>
Signed-off-by: Jan Tulak <jtulak@redhat.com>
Reviewed-by: Eric Sandeen <sandeen@redhat.com>
---
 include/xfs_multidisk.h |   5 +-
 mkfs/xfs_mkfs.c         | 146 ++++++++++++++++++++++++------------------------
 2 files changed, 76 insertions(+), 75 deletions(-)

diff --git a/include/xfs_multidisk.h b/include/xfs_multidisk.h
index 3e892d5..ecc8f0a 100644
--- a/include/xfs_multidisk.h
+++ b/include/xfs_multidisk.h
@@ -42,8 +42,9 @@
 
 #define XFS_AG_BYTES(bblog)	((long long)BBSIZE << (bblog))
 #define	XFS_AG_MIN_BYTES	((XFS_AG_BYTES(15)))	/* 16 MB */
-#define XFS_AG_MIN_BLOCKS(blog)	((XFS_AG_BYTES(15)) >> (blog))
-#define XFS_AG_MAX_BLOCKS(blog)	((XFS_AG_BYTES(31) - 1) >> (blog))
+#define	XFS_AG_MAX_BYTES	((XFS_AG_BYTES(31)))	/* 1 TB */
+#define XFS_AG_MIN_BLOCKS(blog)	(XFS_AG_MIN_BYTES >> (blog))
+#define XFS_AG_MAX_BLOCKS(blog)	((XFS_AG_MAX_BYTES - 1) >> (blog))
 
 #define XFS_MAX_AGNUMBER	((xfs_agnumber_t)(NULLAGNUMBER - 1))
 
diff --git a/mkfs/xfs_mkfs.c b/mkfs/xfs_mkfs.c
index 2f76b67..f3d0165 100644
--- a/mkfs/xfs_mkfs.c
+++ b/mkfs/xfs_mkfs.c
@@ -163,6 +163,8 @@ struct opt_params dopts = {
 	},
 	.subopt_params = {
 		{ .index = D_AGCOUNT,
+		  .minval = 1,
+		  .maxval = XFS_MAX_AGNUMBER,
 		  .defaultval = SUBOPT_NEEDS_VAL,
 		},
 		{ .index = D_FILE,
@@ -177,18 +179,26 @@ struct opt_params dopts = {
 		  .defaultval = SUBOPT_NEEDS_VAL,
 		},
 		{ .index = D_SUNIT,
+		  .minval = 0,
+		  .maxval = UINT_MAX,
 		  .defaultval = SUBOPT_NEEDS_VAL,
 		},
 		{ .index = D_SWIDTH,
+		  .minval = 0,
+		  .maxval = UINT_MAX,
 		  .defaultval = SUBOPT_NEEDS_VAL,
 		},
 		{ .index = D_AGSIZE,
+		  .minval = XFS_AG_MIN_BYTES,
+		  .maxval = XFS_AG_MAX_BYTES,
 		  .defaultval = SUBOPT_NEEDS_VAL,
 		},
 		{ .index = D_SU,
 		  .defaultval = SUBOPT_NEEDS_VAL,
 		},
 		{ .index = D_SW,
+		  .minval = 0,
+		  .maxval = UINT_MAX,
 		  .defaultval = SUBOPT_NEEDS_VAL,
 		},
 		{ .index = D_SECTLOG,
@@ -207,12 +217,18 @@ struct opt_params dopts = {
 		  .defaultval = 1,
 		},
 		{ .index = D_RTINHERIT,
-		  .defaultval = SUBOPT_NEEDS_VAL,
+		  .minval = 1,
+		  .maxval = 1,
+		  .defaultval = 1,
 		},
 		{ .index = D_PROJINHERIT,
+		  .minval = 0,
+		  .maxval = UINT_MAX,
 		  .defaultval = SUBOPT_NEEDS_VAL,
 		},
 		{ .index = D_EXTSZINHERIT,
+		  .minval = 0,
+		  .maxval = UINT_MAX,
 		  .defaultval = SUBOPT_NEEDS_VAL,
 		},
 	},
@@ -252,15 +268,23 @@ struct opt_params iopts = {
 		  .defaultval = SUBOPT_NEEDS_VAL,
 		},
 		{ .index = I_MAXPCT,
+		  .minval = 0,
+		  .maxval = 100,
 		  .defaultval = SUBOPT_NEEDS_VAL,
 		},
 		{ .index = I_PERBLOCK,
+		  .minval = XFS_MIN_INODE_PERBLOCK,
+		  .maxval = XFS_MAX_BLOCKSIZE / XFS_DINODE_MIN_SIZE,
 		  .defaultval = SUBOPT_NEEDS_VAL,
 		},
 		{ .index = I_SIZE,
+		  .minval = XFS_DINODE_MIN_SIZE,
+		  .maxval = XFS_DINODE_MAX_SIZE,
 		  .defaultval = SUBOPT_NEEDS_VAL,
 		},
 		{ .index = I_ATTR,
+		  .minval = 0,
+		  .maxval = 2,
 		  .defaultval = SUBOPT_NEEDS_VAL,
 		},
 		{ .index = I_PROJID32BIT,
@@ -307,6 +331,8 @@ struct opt_params lopts = {
 	},
 	.subopt_params = {
 		{ .index = L_AGNUM,
+		  .minval = 0,
+		  .maxval = UINT_MAX,
 		  .defaultval = SUBOPT_NEEDS_VAL,
 		},
 		{ .index = L_INTERNAL,
@@ -318,9 +344,13 @@ struct opt_params lopts = {
 		  .defaultval = SUBOPT_NEEDS_VAL,
 		},
 		{ .index = L_VERSION,
+		  .minval = 1,
+		  .maxval = 2,
 		  .defaultval = SUBOPT_NEEDS_VAL,
 		},
 		{ .index = L_SUNIT,
+		  .minval = BTOBB(XLOG_MIN_RECORD_BSIZE),
+		  .maxval = BTOBB(XLOG_MAX_RECORD_BSIZE),
 		  .defaultval = SUBOPT_NEEDS_VAL,
 		},
 		{ .index = L_SU,
@@ -380,6 +410,8 @@ struct opt_params nopts = {
 		  .defaultval = SUBOPT_NEEDS_VAL,
 		},
 		{ .index = N_VERSION,
+		  .minval = 2,
+		  .maxval = 2,
 		  .defaultval = SUBOPT_NEEDS_VAL,
 		},
 		{ .index = N_FTYPE,
@@ -1561,13 +1593,11 @@ main(
 				switch (getsubopt(&p, (constpp)subopts,
 						  &value)) {
 				case D_AGCOUNT:
-					if (!value || *value == '\0')
-						reqval('d', subopts, D_AGCOUNT);
 					if (daflag)
 						respec('d', subopts, D_AGCOUNT);
-					agcount = getnum(value, 0, 0, false);
-					if ((__int64_t)agcount <= 0)
-						illegal(value, "d agcount");
+
+					agcount = getnum_checked(value, &dopts,
+								 D_AGCOUNT);
 					daflag = 1;
 					break;
 				case D_AGSIZE:
@@ -1602,28 +1632,22 @@ main(
 					dsize = value;
 					break;
 				case D_SUNIT:
-					if (!value || *value == '\0')
-						reqval('d', subopts, D_SUNIT);
 					if (dsunit)
 						respec('d', subopts, D_SUNIT);
 					if (nodsflag)
 						conflict('d', subopts, D_NOALIGN,
 							 D_SUNIT);
-					dsunit = getnum(value, 0, 0, false);
-					if (dsunit < 0)
-						illegal(value, "d sunit");
+					dsunit = getnum_checked(value, &dopts,
+								 D_SUNIT);
 					break;
 				case D_SWIDTH:
-					if (!value || *value == '\0')
-						reqval('d', subopts, D_SWIDTH);
 					if (dswidth)
 						respec('d', subopts, D_SWIDTH);
 					if (nodsflag)
 						conflict('d', subopts, D_NOALIGN,
 							 D_SWIDTH);
-					dswidth = getnum(value, 0, 0, false);
-					if (dswidth < 0)
-						illegal(value, "d swidth");
+					dswidth = getnum_checked(value, &dopts,
+								 D_SWIDTH);
 					break;
 				case D_SU:
 					if (!value || *value == '\0')
@@ -1639,16 +1663,13 @@ main(
 						illegal(value, "d su");
 					break;
 				case D_SW:
-					if (!value || *value == '\0')
-						reqval('d', subopts, D_SW);
 					if (dsw)
 						respec('d', subopts, D_SW);
 					if (nodsflag)
 						conflict('d', subopts, D_NOALIGN,
 							 D_SW);
-					dsw = getnum(value, 0, 0, false);
-					if (dsw < 0)
-						illegal(value, "d sw");
+					dsw = getnum_checked(value, &dopts,
+								 D_SW);
 					break;
 				case D_NOALIGN:
 					nodsflag = getnum_checked(value,
@@ -1697,21 +1718,22 @@ main(
 					ssflag = 1;
 					break;
 				case D_RTINHERIT:
-					fsx.fsx_xflags |= \
-						XFS_DIFLAG_RTINHERIT;
+					c = getnum_checked(value, &dopts,
+							   D_RTINHERIT);
+					if (c)
+						fsx.fsx_xflags |=
+							XFS_DIFLAG_RTINHERIT;
 					break;
 				case D_PROJINHERIT:
-					if (!value || *value == '\0')
-						reqval('d', subopts, D_PROJINHERIT);
-					fsx.fsx_projid = atoi(value);
-					fsx.fsx_xflags |= \
+					fsx.fsx_projid = getnum_checked(value,
+							&dopts, D_PROJINHERIT);
+					fsx.fsx_xflags |=
 						XFS_DIFLAG_PROJINHERIT;
 					break;
 				case D_EXTSZINHERIT:
-					if (!value || *value == '\0')
-						reqval('d', subopts, D_EXTSZINHERIT);
-					fsx.fsx_extsize = atoi(value);
-					fsx.fsx_xflags |= \
+					fsx.fsx_extsize = getnum_checked(value,
+							&dopts, D_EXTSZINHERIT);
+					fsx.fsx_xflags |=
 						XFS_DIFLAG_EXTSZINHERIT;
 					break;
 				default:
@@ -1746,18 +1768,13 @@ main(
 					ilflag = 1;
 					break;
 				case I_MAXPCT:
-					if (!value || *value == '\0')
-						reqval('i', subopts, I_MAXPCT);
 					if (imflag)
 						respec('i', subopts, I_MAXPCT);
-					imaxpct = getnum(value, 0, 0, false);
-					if (imaxpct < 0 || imaxpct > 100)
-						illegal(value, "i maxpct");
+					imaxpct = getnum_checked(
+							value, &iopts, I_MAXPCT);
 					imflag = 1;
 					break;
 				case I_PERBLOCK:
-					if (!value || *value == '\0')
-						reqval('i', subopts, I_PERBLOCK);
 					if (ilflag)
 						conflict('i', subopts, I_LOG,
 							 I_PERBLOCK);
@@ -1766,16 +1783,13 @@ main(
 					if (isflag)
 						conflict('i', subopts, I_SIZE,
 							 I_PERBLOCK);
-					inopblock = getnum(value, 0, 0, false);
-					if (inopblock <
-						XFS_MIN_INODE_PERBLOCK ||
-					    !ispow2(inopblock))
+					inopblock = getnum_checked(value, &iopts,
+								   I_PERBLOCK);
+					if (!ispow2(inopblock))
 						illegal(value, "i perblock");
 					ipflag = 1;
 					break;
 				case I_SIZE:
-					if (!value || *value == '\0')
-						reqval('i', subopts, I_SIZE);
 					if (ilflag)
 						conflict('i', subopts, I_LOG,
 							 I_SIZE);
@@ -1784,19 +1798,16 @@ main(
 							 I_SIZE);
 					if (isflag)
 						respec('i', subopts, I_SIZE);
-					isize = getnum(value, 0, 0, true);
-					if (isize <= 0 || !ispow2(isize))
+					isize = getnum_checked(value, &iopts,
+							       I_SIZE);
+					if (!ispow2(isize))
 						illegal(value, "i size");
 					inodelog = libxfs_highbit32(isize);
 					isflag = 1;
 					break;
 				case I_ATTR:
-					if (!value || *value == '\0')
-						reqval('i', subopts, I_ATTR);
-					c = getnum(value, 0, 0, false);
-					if (c < 0 || c > 2)
-						illegal(value, "i attr");
-					sb_feat.attr_version = c;
+					sb_feat.attr_version = getnum_checked(
+							value, &iopts, I_ATTR);
 					break;
 				case I_PROJID32BIT:
 					sb_feat.projid16bit =
@@ -1822,15 +1833,12 @@ main(
 				switch (getsubopt(&p, (constpp)subopts,
 						  &value)) {
 				case L_AGNUM:
-					if (!value || *value == '\0')
-						reqval('l', subopts, L_AGNUM);
 					if (laflag)
 						respec('l', subopts, L_AGNUM);
 					if (ldflag)
 						conflict('l', subopts, L_AGNUM, L_DEV);
-					logagno = getnum(value, 0, 0, false);
-					if ((__int64_t)logagno < 0)
-						illegal(value, "l agno");
+					logagno = getnum_checked(value, &lopts,
+								 L_AGNUM);
 					laflag = 1;
 					break;
 				case L_FILE:
@@ -1867,13 +1875,10 @@ main(
 					lsuflag = 1;
 					break;
 				case L_SUNIT:
-					if (!value || *value == '\0')
-						reqval('l', subopts, L_SUNIT);
 					if (lsunit)
 						respec('l', subopts, L_SUNIT);
-					lsunit = getnum(value, 0, 0, false);
-					if (lsunit < 0)
-						illegal(value, "l sunit");
+					lsunit = getnum_checked(value, &lopts,
+								 L_SUNIT);
 					lsunitflag = 1;
 					break;
 				case L_NAME:
@@ -1892,14 +1897,10 @@ main(
 					xi.logname = value;
 					break;
 				case L_VERSION:
-					if (!value || *value == '\0')
-						reqval('l', subopts, L_VERSION);
 					if (lvflag)
 						respec('l', subopts, L_VERSION);
-					c = getnum(value, 0, 0, false);
-					if (c < 1 || c > 2)
-						illegal(value, "l version");
-					sb_feat.log_version = c;
+					sb_feat.log_version = getnum_checked(
+						value, &lopts, L_VERSION);
 					lvflag = 1;
 					break;
 				case L_SIZE:
@@ -2029,11 +2030,10 @@ main(
 						/* ASCII CI mode */
 						sb_feat.nci = true;
 					} else {
-						c = getnum(value, 0, 0, false);
-						if (c != 2)
-							illegal(value,
-								"n version");
-						sb_feat.dir_version = c;
+						sb_feat.dir_version =
+							getnum_checked(value,
+								&nopts,
+								N_VERSION);
 					}
 					nvflag = 1;
 					break;
-- 
2.5.0

_______________________________________________
xfs mailing list
xfs@oss.sgi.com
http://oss.sgi.com/mailman/listinfo/xfs

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

* [PATCH 10/19] mkfs: add respecification detection to generic parsing
  2016-04-21  9:39 [PATCH 00/19 v2] mkfs cleaning Jan Tulak
                   ` (8 preceding siblings ...)
  2016-04-21  9:39 ` [PATCH 09/19] mkfs: use getnum_checked for all ranged parameters Jan Tulak
@ 2016-04-21  9:39 ` Jan Tulak
  2016-04-21  9:39 ` [PATCH 11/19] mkfs: table based parsing for converted parameters Jan Tulak
                   ` (11 subsequent siblings)
  21 siblings, 0 replies; 51+ messages in thread
From: Jan Tulak @ 2016-04-21  9:39 UTC (permalink / raw)
  To: xfs

From: Dave Chinner <dchinner@redhat.com>

Add flags to the generic input parameter tables so that
respecification can be detected in a generic manner.

Signed-off-by: Dave Chinner <dchinner@redhat.com>
Signed-off-by: Jan Tulak <jtulak@redhat.com>
Reviewed-by: Eric Sandeen <sandeen@redhat.com>

---
CHANGES:
* remove unused variable nftype (appeared after a change in some previous patch
removed a line using it and then this patch removed the last usage).
---
 mkfs/xfs_mkfs.c | 67 ++++++++++++++++-----------------------------------------
 1 file changed, 18 insertions(+), 49 deletions(-)

diff --git a/mkfs/xfs_mkfs.c b/mkfs/xfs_mkfs.c
index f3d0165..e45b72b 100644
--- a/mkfs/xfs_mkfs.c
+++ b/mkfs/xfs_mkfs.c
@@ -72,6 +72,10 @@ static long long cvtnum(unsigned int blocksize,
  *     it is. The index has to be the same as is the order in subopts list,
  *     so we can access the right item both in subopt_param and subopts.
  *
+ *   seen INTERNAL
+ *     Do not set this flag when definning a subopt. It is used to remeber that
+ *     this subopt was already seen, for example for conflicts detection.
+ *
  *   minval, maxval OPTIONAL
  *     These options are used for automatic range check and they have to be
  *     always used together in pair. If you don't want to limit the max value,
@@ -95,8 +99,10 @@ static long long cvtnum(unsigned int blocksize,
 struct opt_params {
 	const char	name;
 	const char	*subopts[MAX_SUBOPTS];
+
 	struct subopt_param {
 		int		index;
+		bool		seen;
 		long long	minval;
 		long long	maxval;
 		long long	defaultval;
@@ -1228,7 +1234,6 @@ struct sb_feat_args {
 	int	dir_version;
 	int	spinodes;
 	int	finobt;
-	bool	finobtflag;
 	bool	inode_align;
 	bool	nci;
 	bool	lazy_sb_counters;
@@ -1364,7 +1369,7 @@ getnum_checked(
 	struct opt_params	*opts,
 	int			index)
 {
-	const struct subopt_param *sp = &opts->subopt_params[index];
+	struct subopt_param *sp = &opts->subopt_params[index];
 	long long		c;
 
 	if (sp->index != index) {
@@ -1374,6 +1379,11 @@ getnum_checked(
 		reqval(opts->name, (char **)opts->subopts, index);
 	}
 
+	/* check for respecification of the option */
+	if (sp->seen)
+		respec(opts->name, (char **)opts->subopts, index);
+	sp->seen = true;
+
 	if (!str || *str == '\0') {
 		if (sp->defaultval == SUBOPT_NEEDS_VAL)
 			reqval(opts->name, (char **)opts->subopts, index);
@@ -1463,7 +1473,6 @@ main(
 	int			nodsflag;
 	int			norsflag;
 	xfs_alloc_rec_t		*nrec;
-	int			nftype;
 	int			nsflag;
 	int			nvflag;
 	int			Nflag;
@@ -1491,7 +1500,6 @@ main(
 	struct fs_topology	ft;
 	struct sb_feat_args	sb_feat = {
 		.finobt = 1,
-		.finobtflag = false,
 		.spinodes = 0,
 		.log_version = 2,
 		.attr_version = 2,
@@ -1522,7 +1530,6 @@ main(
 	logagno = logblocks = rtblocks = rtextblocks = 0;
 	sb_feat.dirftype = 1;		/* inode type information in the dir */
 	Nflag = nlflag = nsflag = nvflag = 0;
-	nftype = 0;
 	dirblocklog = dirblocksize = 0;
 	qflag = 0;
 	imaxpct = inodelog = inopblock = isize = 0;
@@ -1553,8 +1560,6 @@ main(
 				switch (getsubopt(&p, (constpp)subopts,
 						  &value)) {
 				case B_LOG:
-					if (blflag)
-						respec('b', subopts, B_LOG);
 					if (bsflag)
 						conflict('b', subopts, B_SIZE,
 							 B_LOG);
@@ -1593,9 +1598,6 @@ main(
 				switch (getsubopt(&p, (constpp)subopts,
 						  &value)) {
 				case D_AGCOUNT:
-					if (daflag)
-						respec('d', subopts, D_AGCOUNT);
-
 					agcount = getnum_checked(value, &dopts,
 								 D_AGCOUNT);
 					daflag = 1;
@@ -1632,8 +1634,6 @@ main(
 					dsize = value;
 					break;
 				case D_SUNIT:
-					if (dsunit)
-						respec('d', subopts, D_SUNIT);
 					if (nodsflag)
 						conflict('d', subopts, D_NOALIGN,
 							 D_SUNIT);
@@ -1641,8 +1641,6 @@ main(
 								 D_SUNIT);
 					break;
 				case D_SWIDTH:
-					if (dswidth)
-						respec('d', subopts, D_SWIDTH);
 					if (nodsflag)
 						conflict('d', subopts, D_NOALIGN,
 							 D_SWIDTH);
@@ -1663,8 +1661,6 @@ main(
 						illegal(value, "d su");
 					break;
 				case D_SW:
-					if (dsw)
-						respec('d', subopts, D_SW);
 					if (nodsflag)
 						conflict('d', subopts, D_NOALIGN,
 							 D_SW);
@@ -1690,8 +1686,6 @@ main(
 					}
 					break;
 				case D_SECTLOG:
-					if (slflag)
-						respec('d', subopts, D_SECTLOG);
 					if (ssflag)
 						conflict('d', subopts, D_SECTSIZE,
 							 D_SECTLOG);
@@ -1754,8 +1748,6 @@ main(
 							value, &iopts, I_ALIGN);
 					break;
 				case I_LOG:
-					if (ilflag)
-						respec('i', subopts, I_LOG);
 					if (ipflag)
 						conflict('i', subopts, I_PERBLOCK,
 							 I_LOG);
@@ -1768,18 +1760,14 @@ main(
 					ilflag = 1;
 					break;
 				case I_MAXPCT:
-					if (imflag)
-						respec('i', subopts, I_MAXPCT);
-					imaxpct = getnum_checked(
-							value, &iopts, I_MAXPCT);
+					imaxpct = getnum_checked(value, &iopts,
+								 I_MAXPCT);
 					imflag = 1;
 					break;
 				case I_PERBLOCK:
 					if (ilflag)
 						conflict('i', subopts, I_LOG,
 							 I_PERBLOCK);
-					if (ipflag)
-						respec('i', subopts, I_PERBLOCK);
 					if (isflag)
 						conflict('i', subopts, I_SIZE,
 							 I_PERBLOCK);
@@ -1796,8 +1784,6 @@ main(
 					if (ipflag)
 						conflict('i', subopts, I_PERBLOCK,
 							 I_SIZE);
-					if (isflag)
-						respec('i', subopts, I_SIZE);
 					isize = getnum_checked(value, &iopts,
 							       I_SIZE);
 					if (!ispow2(isize))
@@ -1833,8 +1819,6 @@ main(
 				switch (getsubopt(&p, (constpp)subopts,
 						  &value)) {
 				case L_AGNUM:
-					if (laflag)
-						respec('l', subopts, L_AGNUM);
 					if (ldflag)
 						conflict('l', subopts, L_AGNUM, L_DEV);
 					logagno = getnum_checked(value, &lopts,
@@ -1856,8 +1840,6 @@ main(
 					if (xi.lisfile)
 						conflict('l', subopts, L_FILE,
 							 L_INTERNAL);
-					if (liflag)
-						respec('l', subopts, L_INTERNAL);
 
 					loginternal = getnum_checked(value,
 							&lopts, L_INTERNAL);
@@ -1875,8 +1857,6 @@ main(
 					lsuflag = 1;
 					break;
 				case L_SUNIT:
-					if (lsunit)
-						respec('l', subopts, L_SUNIT);
 					lsunit = getnum_checked(value, &lopts,
 								 L_SUNIT);
 					lsunitflag = 1;
@@ -1897,10 +1877,9 @@ main(
 					xi.logname = value;
 					break;
 				case L_VERSION:
-					if (lvflag)
-						respec('l', subopts, L_VERSION);
-					sb_feat.log_version = getnum_checked(
-						value, &lopts, L_VERSION);
+					sb_feat.log_version =
+						getnum_checked(value, &lopts,
+							       L_VERSION);
 					lvflag = 1;
 					break;
 				case L_SIZE:
@@ -1912,8 +1891,6 @@ main(
 					lsflag = 1;
 					break;
 				case L_SECTLOG:
-					if (lslflag)
-						respec('l', subopts, L_SECTLOG);
 					if (lssflag)
 						conflict('l', subopts, L_SECTSIZE,
 							 L_SECTLOG);
@@ -1970,7 +1947,6 @@ main(
 						sb_feat.dirftype = true;
 					break;
 				case M_FINOBT:
-					sb_feat.finobtflag = true;
 					sb_feat.finobt = getnum_checked(
 						value, &mopts, M_FINOBT);
 					break;
@@ -1994,8 +1970,6 @@ main(
 				switch (getsubopt(&p, (constpp)subopts,
 						  &value)) {
 				case N_LOG:
-					if (nlflag)
-						respec('n', subopts, N_LOG);
 					if (nsflag)
 						conflict('n', subopts, N_SIZE,
 							 N_LOG);
@@ -2038,11 +2012,8 @@ main(
 					nvflag = 1;
 					break;
 				case N_FTYPE:
-					if (nftype)
-						respec('n', subopts, N_FTYPE);
 					sb_feat.dirftype = getnum_checked(value,
 								&nopts, N_FTYPE);
-					nftype = 1;
 					break;
 				default:
 					unknown('n', value);
@@ -2118,8 +2089,6 @@ main(
 						  &value)) {
 				case S_LOG:
 				case S_SECTLOG:
-					if (slflag || lslflag)
-						respec('s', subopts, S_SECTLOG);
 					if (ssflag || lssflag)
 						conflict('s', subopts,
 							 S_SECTSIZE, S_SECTLOG);
@@ -2330,7 +2299,7 @@ _("32 bit Project IDs always enabled on CRC enabled filesytems\n"));
 		 * tried to use crc=0,finobt=1, then issue a warning before
 		 * turning them off.
 		 */
-		if (sb_feat.finobt && sb_feat.finobtflag) {
+		if (sb_feat.finobt && mopts.subopt_params[M_FINOBT].seen) {
 			fprintf(stderr,
 _("warning: finobt not supported without CRC support, disabled.\n"));
 		}
-- 
2.5.0

_______________________________________________
xfs mailing list
xfs@oss.sgi.com
http://oss.sgi.com/mailman/listinfo/xfs

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

* [PATCH 11/19] mkfs: table based parsing for converted parameters
  2016-04-21  9:39 [PATCH 00/19 v2] mkfs cleaning Jan Tulak
                   ` (9 preceding siblings ...)
  2016-04-21  9:39 ` [PATCH 10/19] mkfs: add respecification detection to generic parsing Jan Tulak
@ 2016-04-21  9:39 ` Jan Tulak
  2016-05-02 23:09   ` Eric Sandeen
  2016-04-21  9:39 ` [PATCH 12/19] mkfs: merge getnum Jan Tulak
                   ` (10 subsequent siblings)
  21 siblings, 1 reply; 51+ messages in thread
From: Jan Tulak @ 2016-04-21  9:39 UTC (permalink / raw)
  To: xfs

From: Dave Chinner <dchinner@redhat.com>

All the parameters that can be passed as block or sector sizes need
to be passed the block and sector sizes that they should be using
for conversion. For parameter parsing, it is always the same two
variables, so to make things easy just declare them as global
variables so we can avoid needing to pass them to getnum_checked().

We also need to mark these parameters are requiring conversion so
that we don't need to pass this information manually to
getnum_checked(). Further, some of these options are required to
have a power of 2 value, so add optional checking for that as well.

Signed-off-by: Dave Chinner <dchinner@redhat.com>
Signed-off-by: Jan Tulak <jtulak@redhat.com>

Was reviewed, but one small change added...
 Reviewed-by: Eric Sandeen <sandeen@redhat.com>

---
CHANGES:
* L_SU minval changed from XLOG_MIN_RECORD_BSIZE to 0 to comply with
  tests generic/054 and 055 - is this a valid solution, or the tests
  should be fixed?
---
 mkfs/xfs_mkfs.c | 182 ++++++++++++++++++++++++--------------------------------
 1 file changed, 78 insertions(+), 104 deletions(-)

diff --git a/mkfs/xfs_mkfs.c b/mkfs/xfs_mkfs.c
index e45b72b..8551b09 100644
--- a/mkfs/xfs_mkfs.c
+++ b/mkfs/xfs_mkfs.c
@@ -48,6 +48,13 @@ static int  ispow2(unsigned int i);
 static long long cvtnum(unsigned int blocksize,
 			unsigned int sectorsize, const char *s);
 
+/*
+ * The configured block and sector sizes are defined as global variables so
+ * that they don't need to be passed to functions that require them.
+ */
+unsigned int		blocksize;
+unsigned int		sectorsize;
+
 #define MAX_SUBOPTS	16
 #define SUBOPT_NEEDS_VAL	(-1LL)
 /*
@@ -76,6 +83,15 @@ static long long cvtnum(unsigned int blocksize,
  *     Do not set this flag when definning a subopt. It is used to remeber that
  *     this subopt was already seen, for example for conflicts detection.
  *
+ *   convert OPTIONAL
+ *     A flag signalling whether the user-given value can use suffixes.
+ *     If you want to allow the use of user-friendly values like 13k, 42G,
+ *     set it to true.
+ *
+ *   is_power_2 OPTIONAL
+ *     An optional flag for subopts where the given value has to be a power
+ *     of two.
+ *
  *   minval, maxval OPTIONAL
  *     These options are used for automatic range check and they have to be
  *     always used together in pair. If you don't want to limit the max value,
@@ -103,6 +119,8 @@ struct opt_params {
 	struct subopt_param {
 		int		index;
 		bool		seen;
+		bool		convert;
+		bool		is_power_2;
 		long long	minval;
 		long long	maxval;
 		long long	defaultval;
@@ -125,6 +143,8 @@ struct opt_params bopts = {
 		  .defaultval = SUBOPT_NEEDS_VAL,
 		},
 		{ .index = B_SIZE,
+		  .convert = true,
+		  .is_power_2 = true,
 		  .minval = XFS_MIN_BLOCKSIZE,
 		  .maxval = XFS_MAX_BLOCKSIZE,
 		  .defaultval = SUBOPT_NEEDS_VAL,
@@ -182,6 +202,9 @@ struct opt_params dopts = {
 		  .defaultval = SUBOPT_NEEDS_VAL,
 		},
 		{ .index = D_SIZE,
+		  .convert = true,
+		  .minval = XFS_AG_MIN_BYTES,
+		  .maxval = LLONG_MAX,
 		  .defaultval = SUBOPT_NEEDS_VAL,
 		},
 		{ .index = D_SUNIT,
@@ -195,11 +218,15 @@ struct opt_params dopts = {
 		  .defaultval = SUBOPT_NEEDS_VAL,
 		},
 		{ .index = D_AGSIZE,
+		  .convert = true,
 		  .minval = XFS_AG_MIN_BYTES,
 		  .maxval = XFS_AG_MAX_BYTES,
 		  .defaultval = SUBOPT_NEEDS_VAL,
 		},
 		{ .index = D_SU,
+		  .convert = true,
+		  .minval = 0,
+		  .maxval = UINT_MAX,
 		  .defaultval = SUBOPT_NEEDS_VAL,
 		},
 		{ .index = D_SW,
@@ -213,6 +240,8 @@ struct opt_params dopts = {
 		  .defaultval = SUBOPT_NEEDS_VAL,
 		},
 		{ .index = D_SECTSIZE,
+		  .convert = true,
+		  .is_power_2 = true,
 		  .minval = XFS_MIN_SECTORSIZE,
 		  .maxval = XFS_MAX_SECTORSIZE,
 		  .defaultval = SUBOPT_NEEDS_VAL,
@@ -279,11 +308,13 @@ struct opt_params iopts = {
 		  .defaultval = SUBOPT_NEEDS_VAL,
 		},
 		{ .index = I_PERBLOCK,
+		  .is_power_2 = true,
 		  .minval = XFS_MIN_INODE_PERBLOCK,
 		  .maxval = XFS_MAX_BLOCKSIZE / XFS_DINODE_MIN_SIZE,
 		  .defaultval = SUBOPT_NEEDS_VAL,
 		},
 		{ .index = I_SIZE,
+		  .is_power_2 = true,
 		  .minval = XFS_DINODE_MIN_SIZE,
 		  .maxval = XFS_DINODE_MAX_SIZE,
 		  .defaultval = SUBOPT_NEEDS_VAL,
@@ -347,6 +378,9 @@ struct opt_params lopts = {
 		  .defaultval = 1,
 		},
 		{ .index = L_SIZE,
+		  .convert = true,
+		  .minval = 2 * 1024 * 1024LL,	/* XXX: XFS_MIN_LOG_BYTES */
+		  .maxval = XFS_MAX_LOG_BYTES,
 		  .defaultval = SUBOPT_NEEDS_VAL,
 		},
 		{ .index = L_VERSION,
@@ -360,6 +394,9 @@ struct opt_params lopts = {
 		  .defaultval = SUBOPT_NEEDS_VAL,
 		},
 		{ .index = L_SU,
+		  .convert = true,
+		  .minval = 0,
+		  .maxval = UINT_MAX,
 		  .defaultval = SUBOPT_NEEDS_VAL,
 		},
 		{ .index = L_DEV,
@@ -371,6 +408,8 @@ struct opt_params lopts = {
 		  .defaultval = SUBOPT_NEEDS_VAL,
 		},
 		{ .index = L_SECTSIZE,
+		  .convert = true,
+		  .is_power_2 = true,
 		  .minval = XFS_MIN_SECTORSIZE,
 		  .maxval = XFS_MAX_SECTORSIZE,
 		  .defaultval = SUBOPT_NEEDS_VAL,
@@ -411,6 +450,8 @@ struct opt_params nopts = {
 		  .defaultval = SUBOPT_NEEDS_VAL,
 		},
 		{ .index = N_SIZE,
+		  .convert = true,
+		  .is_power_2 = true,
 		  .minval = 1 << XFS_MIN_REC_DIRSIZE,
 		  .maxval = XFS_MAX_BLOCKSIZE,
 		  .defaultval = SUBOPT_NEEDS_VAL,
@@ -447,9 +488,15 @@ struct opt_params ropts = {
 	},
 	.subopt_params = {
 		{ .index = R_EXTSIZE,
+		  .convert = true,
+		  .minval = XFS_MIN_RTEXTSIZE,
+		  .maxval = XFS_MAX_RTEXTSIZE,
 		  .defaultval = SUBOPT_NEEDS_VAL,
 		},
 		{ .index = R_SIZE,
+		  .convert = true,
+		  .minval = 0,
+		  .maxval = LLONG_MAX,
 		  .defaultval = SUBOPT_NEEDS_VAL,
 		},
 		{ .index = R_DEV,
@@ -496,11 +543,15 @@ struct opt_params sopts = {
 		  .defaultval = SUBOPT_NEEDS_VAL,
 		},
 		{ .index = S_SIZE,
+		  .convert = true,
+		  .is_power_2 = true,
 		  .minval = XFS_MIN_SECTORSIZE,
 		  .maxval = XFS_MAX_SECTORSIZE,
 		  .defaultval = SUBOPT_NEEDS_VAL,
 		},
 		{ .index = S_SECTSIZE,
+		  .convert = true,
+		  .is_power_2 = true,
 		  .minval = XFS_MIN_SECTORSIZE,
 		  .maxval = XFS_MAX_SECTORSIZE,
 		  .defaultval = SUBOPT_NEEDS_VAL,
@@ -1333,15 +1384,15 @@ sb_set_features(
 long long
 getnum(
 	const char	*str,
-	unsigned int	blocksize,
-	unsigned int	sectorsize,
+	unsigned int	blksize,
+	unsigned int	sectsize,
 	bool		convert)
 {
 	long long	i;
 	char		*sp;
 
 	if (convert)
-		return cvtnum(blocksize, sectorsize, str);
+		return cvtnum(blksize, sectsize, str);
 
 	i = strtoll(str, &sp, 0);
 	if (i == 0 && sp == str)
@@ -1363,7 +1414,7 @@ illegal_option(
 	usage();
 }
 
-static int
+static long long
 getnum_checked(
 	const char		*str,
 	struct opt_params	*opts,
@@ -1398,9 +1449,11 @@ getnum_checked(
 		exit(1);
 	}
 
-	c = getnum(str, 0, 0, false);
+	c = getnum(str, blocksize, sectorsize, sp->convert);
 	if (c < sp->minval || c > sp->maxval)
 		illegal_option(str, opts, index);
+	if (sp->is_power_2 && !ispow2(c))
+		illegal_option(str, opts, index);
 	return c;
 }
 
@@ -1418,7 +1471,6 @@ main(
 	struct xfs_btree_block	*block;
 	int			blflag;
 	int			blocklog;
-	unsigned int		blocksize;
 	int			bsflag;
 	int			bsize;
 	xfs_buf_t		*buf;
@@ -1489,7 +1541,6 @@ main(
 	char			*rtsize;
 	xfs_sb_t		*sbp;
 	int			sectorlog;
-	unsigned int		sectorsize;
 	__uint64_t		sector_mask;
 	int			slflag;
 	int			ssflag;
@@ -1569,18 +1620,11 @@ main(
 					blflag = 1;
 					break;
 				case B_SIZE:
-					if (!value || *value == '\0')
-						reqval('b', subopts, B_SIZE);
-					if (bsflag)
-						respec('b', subopts, B_SIZE);
 					if (blflag)
 						conflict('b', subopts, B_LOG,
 							 B_SIZE);
-					blocksize = getnum(value, blocksize,
-							sectorsize, true);
-					if (blocksize <= 0 ||
-					    !ispow2(blocksize))
-						illegal(value, "b size");
+					blocksize = getnum_checked(value, &bopts,
+								  B_SIZE);
 					blocklog = libxfs_highbit32(blocksize);
 					bsflag = 1;
 					break;
@@ -1603,14 +1647,8 @@ main(
 					daflag = 1;
 					break;
 				case D_AGSIZE:
-					if (!value || *value == '\0')
-						reqval('d', subopts, D_AGSIZE);
-					if (dasize)
-						respec('d', subopts, D_AGSIZE);
-					agsize = getnum(value, blocksize,
-							sectorsize, true);
-					if ((__int64_t)agsize <= 0)
-						illegal(value, "d agsize");
+					agsize = getnum_checked(value, &dopts,
+								 D_AGSIZE);
 					dasize = 1;
 					break;
 				case D_FILE:
@@ -1648,17 +1686,11 @@ main(
 								 D_SWIDTH);
 					break;
 				case D_SU:
-					if (!value || *value == '\0')
-						reqval('d', subopts, D_SU);
-					if (dsu)
-						respec('d', subopts, D_SU);
 					if (nodsflag)
 						conflict('d', subopts, D_NOALIGN,
 							 D_SU);
-					dsu = getnum(value, blocksize,
-						     sectorsize, true);
-					if (dsu < 0)
-						illegal(value, "d su");
+					dsu = getnum_checked(value, &dopts,
+								 D_SU);
 					break;
 				case D_SW:
 					if (nodsflag)
@@ -1695,18 +1727,11 @@ main(
 					slflag = 1;
 					break;
 				case D_SECTSIZE:
-					if (!value || *value == '\0')
-						reqval('d', subopts, D_SECTSIZE);
-					if (ssflag)
-						respec('d', subopts, D_SECTSIZE);
 					if (slflag)
 						conflict('d', subopts, D_SECTLOG,
 							 D_SECTSIZE);
-					sectorsize = getnum(value, blocksize,
-							    sectorsize, true);
-					if (sectorsize <= 0 ||
-					    !ispow2(sectorsize))
-						illegal(value, "d sectsize");
+					sectorsize = getnum_checked(value,
+							&dopts, D_SECTSIZE);
 					sectorlog =
 						libxfs_highbit32(sectorsize);
 					ssflag = 1;
@@ -1773,8 +1798,6 @@ main(
 							 I_PERBLOCK);
 					inopblock = getnum_checked(value, &iopts,
 								   I_PERBLOCK);
-					if (!ispow2(inopblock))
-						illegal(value, "i perblock");
 					ipflag = 1;
 					break;
 				case I_SIZE:
@@ -1786,8 +1809,6 @@ main(
 							 I_SIZE);
 					isize = getnum_checked(value, &iopts,
 							       I_SIZE);
-					if (!ispow2(isize))
-						illegal(value, "i size");
 					inodelog = libxfs_highbit32(isize);
 					isflag = 1;
 					break;
@@ -1846,14 +1867,8 @@ main(
 					liflag = 1;
 					break;
 				case L_SU:
-					if (!value || *value == '\0')
-						reqval('l', subopts, L_SU);
-					if (lsu)
-						respec('l', subopts, L_SU);
-					lsu = getnum(value, blocksize,
-						     sectorsize, true);
-					if (lsu < 0)
-						illegal(value, "l su");
+					lsu = getnum_checked(value, &lopts,
+								 L_SU);
 					lsuflag = 1;
 					break;
 				case L_SUNIT:
@@ -1900,18 +1915,11 @@ main(
 					lslflag = 1;
 					break;
 				case L_SECTSIZE:
-					if (!value || *value == '\0')
-						reqval('l', subopts, L_SECTSIZE);
-					if (lssflag)
-						respec('l', subopts, L_SECTSIZE);
 					if (lslflag)
 						conflict('l', subopts, L_SECTLOG,
 							 L_SECTSIZE);
-					lsectorsize = getnum(value, blocksize,
-							     sectorsize, true);
-					if (lsectorsize <= 0 ||
-					    !ispow2(lsectorsize))
-						illegal(value, "l sectsize");
+					lsectorsize = getnum_checked(value,
+							&lopts, L_SECTSIZE);
 					lsectorlog =
 						libxfs_highbit32(lsectorsize);
 					lssflag = 1;
@@ -1979,18 +1987,11 @@ main(
 					nlflag = 1;
 					break;
 				case N_SIZE:
-					if (!value || *value == '\0')
-						reqval('n', subopts, N_SIZE);
-					if (nsflag)
-						respec('n', subopts, N_SIZE);
 					if (nlflag)
 						conflict('n', subopts, N_LOG,
 							 N_SIZE);
-					dirblocksize = getnum(value, blocksize,
-							      sectorsize, true);
-					if (dirblocksize <= 0 ||
-					    !ispow2(dirblocksize))
-						illegal(value, "n size");
+					dirblocksize = getnum_checked(value,
+								&nopts, N_SIZE);
 					dirblocklog =
 						libxfs_highbit32(dirblocksize);
 					nsflag = 1;
@@ -2101,18 +2102,11 @@ main(
 					break;
 				case S_SIZE:
 				case S_SECTSIZE:
-					if (!value || *value == '\0')
-						reqval('s', subopts, S_SECTSIZE);
-					if (ssflag || lssflag)
-						respec('s', subopts, S_SECTSIZE);
 					if (slflag || lslflag)
 						conflict('s', subopts, S_SECTLOG,
 							 S_SECTSIZE);
-					sectorsize = getnum(value, blocksize,
-							    sectorsize, true);
-					if (sectorsize <= 0 ||
-					    !ispow2(sectorsize))
-						illegal(value, "s sectsize");
+					sectorsize = getnum_checked(value,
+							&sopts, S_SECTSIZE);
 					lsectorsize = sectorsize;
 					sectorlog =
 						libxfs_highbit32(sectorsize);
@@ -2341,9 +2335,7 @@ _("warning: sparse inodes not supported without CRC support, disabled.\n"));
 	if (dsize) {
 		__uint64_t dbytes;
 
-		dbytes = getnum(dsize, blocksize, sectorsize, true);
-		if ((__int64_t)dbytes < 0)
-			illegal(dsize, "d size");
+		dbytes = getnum_checked(dsize, &dopts, D_SIZE);
 		if (dbytes % XFS_MIN_BLOCKSIZE) {
 			fprintf(stderr,
 			_("illegal data length %lld, not a multiple of %d\n"),
@@ -2380,9 +2372,7 @@ _("warning: sparse inodes not supported without CRC support, disabled.\n"));
 	if (logsize) {
 		__uint64_t logbytes;
 
-		logbytes = getnum(logsize, blocksize, sectorsize, true);
-		if ((__int64_t)logbytes < 0)
-			illegal(logsize, "l size");
+		logbytes = getnum_checked(logsize, &lopts, L_SIZE);
 		if (logbytes % XFS_MIN_BLOCKSIZE) {
 			fprintf(stderr,
 			_("illegal log length %lld, not a multiple of %d\n"),
@@ -2404,9 +2394,7 @@ _("warning: sparse inodes not supported without CRC support, disabled.\n"));
 	if (rtsize) {
 		__uint64_t rtbytes;
 
-		rtbytes = getnum(rtsize, blocksize, sectorsize, true);
-		if ((__int64_t)rtbytes < 0)
-			illegal(rtsize, "r size");
+		rtbytes = getnum_checked(rtsize, &ropts, R_SIZE);
 		if (rtbytes % XFS_MIN_BLOCKSIZE) {
 			fprintf(stderr,
 			_("illegal rt length %lld, not a multiple of %d\n"),
@@ -2426,27 +2414,13 @@ _("warning: sparse inodes not supported without CRC support, disabled.\n"));
 	if (rtextsize) {
 		__uint64_t rtextbytes;
 
-		rtextbytes = getnum(rtextsize, blocksize, sectorsize, true);
-		if ((__int64_t)rtextbytes < 0)
-			illegal(rtsize, "r extsize");
+		rtextbytes = getnum_checked(rtextsize, &ropts, R_EXTSIZE);
 		if (rtextbytes % blocksize) {
 			fprintf(stderr,
 		_("illegal rt extent size %lld, not a multiple of %d\n"),
 				(long long)rtextbytes, blocksize);
 			usage();
 		}
-		if (rtextbytes > XFS_MAX_RTEXTSIZE) {
-			fprintf(stderr,
-				_("rt extent size %s too large, maximum %d\n"),
-				rtextsize, XFS_MAX_RTEXTSIZE);
-			usage();
-		}
-		if (rtextbytes < XFS_MIN_RTEXTSIZE) {
-			fprintf(stderr,
-				_("rt extent size %s too small, minimum %d\n"),
-				rtextsize, XFS_MIN_RTEXTSIZE);
-			usage();
-		}
 		rtextblocks = (xfs_extlen_t)(rtextbytes >> blocklog);
 	} else {
 		/*
-- 
2.5.0

_______________________________________________
xfs mailing list
xfs@oss.sgi.com
http://oss.sgi.com/mailman/listinfo/xfs

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

* [PATCH 12/19] mkfs: merge getnum
  2016-04-21  9:39 [PATCH 00/19 v2] mkfs cleaning Jan Tulak
                   ` (10 preceding siblings ...)
  2016-04-21  9:39 ` [PATCH 11/19] mkfs: table based parsing for converted parameters Jan Tulak
@ 2016-04-21  9:39 ` Jan Tulak
  2016-04-21  9:39 ` [PATCH 13/19] mkfs: encode conflicts into parsing table Jan Tulak
                   ` (9 subsequent siblings)
  21 siblings, 0 replies; 51+ messages in thread
From: Jan Tulak @ 2016-04-21  9:39 UTC (permalink / raw)
  To: xfs

From: Dave Chinner <dchinner@redhat.com>

getnum() is now only called by getnum_checked(). Move the two
together into a single getnum() function and change all the callers
back to getnum().

Signed-off-by: Dave Chinner <dchinner@redhat.com>
Signed-off-by: Jan Tulak <jtulak@redhat.com>
Reviewed-by: Eric Sandeen <sandeen@redhat.com>
---
 include/xfs_multidisk.h |   4 +-
 mkfs/proto.c            |  20 +++++
 mkfs/xfs_mkfs.c         | 213 ++++++++++++++++++++++--------------------------
 3 files changed, 119 insertions(+), 118 deletions(-)

diff --git a/include/xfs_multidisk.h b/include/xfs_multidisk.h
index ecc8f0a..fe3e98f 100644
--- a/include/xfs_multidisk.h
+++ b/include/xfs_multidisk.h
@@ -57,8 +57,8 @@
 #define XFS_NOMULTIDISK_AGLOG		2	/* 4 AGs */
 #define XFS_MULTIDISK_AGCOUNT		(1 << XFS_MULTIDISK_AGLOG)
 
-extern long long getnum(const char *str, unsigned int blocksize,
-			unsigned int sectorsize, bool convert);
+extern long long cvtnum(unsigned int blksize, unsigned int sectsize,
+			const char *str);
 
 /* proto.c */
 extern char *setup_proto (char *fname);
diff --git a/mkfs/proto.c b/mkfs/proto.c
index 19943cb..09a9439 100644
--- a/mkfs/proto.c
+++ b/mkfs/proto.c
@@ -43,6 +43,26 @@ static long filesize(int fd);
 	((uint)(MKFS_BLOCKRES_INODE + XFS_DA_NODE_MAXDEPTH + \
 	(XFS_BM_MAXLEVELS(mp, XFS_DATA_FORK) - 1) + (rb)))
 
+static long long
+getnum(
+	const char	*str,
+	unsigned int	blksize,
+	unsigned int	sectsize,
+	bool		convert)
+{
+	long long	i;
+	char		*sp;
+
+	if (convert)
+		return cvtnum(blksize, sectsize, str);
+
+	i = strtoll(str, &sp, 0);
+	if (i == 0 && sp == str)
+		return -1LL;
+	if (*sp != '\0')
+		return -1LL; /* trailing garbage */
+	return i;
+}
 
 char *
 setup_proto(
diff --git a/mkfs/xfs_mkfs.c b/mkfs/xfs_mkfs.c
index 8551b09..a45dc7f 100644
--- a/mkfs/xfs_mkfs.c
+++ b/mkfs/xfs_mkfs.c
@@ -45,9 +45,6 @@ static void respec(char opt, char *tab[], int idx);
 static void unknown(char opt, char *s);
 static int  ispow2(unsigned int i);
 
-static long long cvtnum(unsigned int blocksize,
-			unsigned int sectorsize, const char *s);
-
 /*
  * The configured block and sector sizes are defined as global variables so
  * that they don't need to be passed to functions that require them.
@@ -1381,27 +1378,6 @@ sb_set_features(
 
 }
 
-long long
-getnum(
-	const char	*str,
-	unsigned int	blksize,
-	unsigned int	sectsize,
-	bool		convert)
-{
-	long long	i;
-	char		*sp;
-
-	if (convert)
-		return cvtnum(blksize, sectsize, str);
-
-	i = strtoll(str, &sp, 0);
-	if (i == 0 && sp == str)
-		return -1LL;
-	if (*sp != '\0')
-		return -1LL; /* trailing garbage */
-	return i;
-}
-
 static __attribute__((noreturn)) void
 illegal_option(
 	const char	*value,
@@ -1415,7 +1391,7 @@ illegal_option(
 }
 
 static long long
-getnum_checked(
+getnum(
 	const char		*str,
 	struct opt_params	*opts,
 	int			index)
@@ -1435,6 +1411,7 @@ getnum_checked(
 		respec(opts->name, (char **)opts->subopts, index);
 	sp->seen = true;
 
+	/* empty strings might just return a default value */
 	if (!str || *str == '\0') {
 		if (sp->defaultval == SUBOPT_NEEDS_VAL)
 			reqval(opts->name, (char **)opts->subopts, index);
@@ -1449,7 +1426,25 @@ getnum_checked(
 		exit(1);
 	}
 
-	c = getnum(str, blocksize, sectorsize, sp->convert);
+	/*
+	 * Some values are pure numbers, others can have suffixes that define
+	 * the units of the number. Those get passed to cvtnum(), otherwise we
+	 * convert it ourselves to guarantee there is no trailing garbage in the
+	 * number.
+	 */
+	if (sp->convert)
+		c = cvtnum(blocksize, sectorsize, str);
+	else {
+		char		*str_end;
+
+		c = strtoll(str, &str_end, 0);
+		if (c == 0 && str_end == str)
+			illegal_option(str, opts, index);
+		if (*str_end != '\0')
+			illegal_option(str, opts, index);
+	}
+
+	/* Validity check the result. */
 	if (c < sp->minval || c > sp->maxval)
 		illegal_option(str, opts, index);
 	if (sp->is_power_2 && !ispow2(c))
@@ -1614,8 +1609,7 @@ main(
 					if (bsflag)
 						conflict('b', subopts, B_SIZE,
 							 B_LOG);
-					blocklog = getnum_checked(value, &bopts,
-								  B_LOG);
+					blocklog = getnum(value, &bopts, B_LOG);
 					blocksize = 1 << blocklog;
 					blflag = 1;
 					break;
@@ -1623,8 +1617,8 @@ main(
 					if (blflag)
 						conflict('b', subopts, B_LOG,
 							 B_SIZE);
-					blocksize = getnum_checked(value, &bopts,
-								  B_SIZE);
+					blocksize = getnum(value, &bopts,
+							   B_SIZE);
 					blocklog = libxfs_highbit32(blocksize);
 					bsflag = 1;
 					break;
@@ -1642,18 +1636,17 @@ main(
 				switch (getsubopt(&p, (constpp)subopts,
 						  &value)) {
 				case D_AGCOUNT:
-					agcount = getnum_checked(value, &dopts,
-								 D_AGCOUNT);
+					agcount = getnum(value, &dopts,
+							 D_AGCOUNT);
 					daflag = 1;
 					break;
 				case D_AGSIZE:
-					agsize = getnum_checked(value, &dopts,
-								 D_AGSIZE);
+					agsize = getnum(value, &dopts, D_AGSIZE);
 					dasize = 1;
 					break;
 				case D_FILE:
-					xi.disfile = getnum_checked(value,
-								&dopts, D_FILE);
+					xi.disfile = getnum(value, &dopts,
+							    D_FILE);
 					if (xi.disfile && !Nflag)
 						xi.dcreat = 1;
 					break;
@@ -1675,33 +1668,30 @@ main(
 					if (nodsflag)
 						conflict('d', subopts, D_NOALIGN,
 							 D_SUNIT);
-					dsunit = getnum_checked(value, &dopts,
-								 D_SUNIT);
+					dsunit = getnum(value, &dopts, D_SUNIT);
 					break;
 				case D_SWIDTH:
 					if (nodsflag)
 						conflict('d', subopts, D_NOALIGN,
 							 D_SWIDTH);
-					dswidth = getnum_checked(value, &dopts,
-								 D_SWIDTH);
+					dswidth = getnum(value, &dopts,
+							 D_SWIDTH);
 					break;
 				case D_SU:
 					if (nodsflag)
 						conflict('d', subopts, D_NOALIGN,
 							 D_SU);
-					dsu = getnum_checked(value, &dopts,
-								 D_SU);
+					dsu = getnum(value, &dopts, D_SU);
 					break;
 				case D_SW:
 					if (nodsflag)
 						conflict('d', subopts, D_NOALIGN,
 							 D_SW);
-					dsw = getnum_checked(value, &dopts,
-								 D_SW);
+					dsw = getnum(value, &dopts, D_SW);
 					break;
 				case D_NOALIGN:
-					nodsflag = getnum_checked(value,
-								&dopts, D_NOALIGN);
+					nodsflag = getnum(value, &dopts,
+							 	D_NOALIGN);
 					if (nodsflag) {
 						if (dsu)
 							conflict('d', subopts, D_SU,
@@ -1721,8 +1711,8 @@ main(
 					if (ssflag)
 						conflict('d', subopts, D_SECTSIZE,
 							 D_SECTLOG);
-					sectorlog = getnum_checked(value, &dopts,
-								   D_SECTLOG);
+					sectorlog = getnum(value, &dopts,
+							   D_SECTLOG);
 					sectorsize = 1 << sectorlog;
 					slflag = 1;
 					break;
@@ -1730,28 +1720,27 @@ main(
 					if (slflag)
 						conflict('d', subopts, D_SECTLOG,
 							 D_SECTSIZE);
-					sectorsize = getnum_checked(value,
-							&dopts, D_SECTSIZE);
+					sectorsize = getnum(value, &dopts,
+							    D_SECTSIZE);
 					sectorlog =
 						libxfs_highbit32(sectorsize);
 					ssflag = 1;
 					break;
 				case D_RTINHERIT:
-					c = getnum_checked(value, &dopts,
-							   D_RTINHERIT);
+					c = getnum(value, &dopts, D_RTINHERIT);
 					if (c)
 						fsx.fsx_xflags |=
 							XFS_DIFLAG_RTINHERIT;
 					break;
 				case D_PROJINHERIT:
-					fsx.fsx_projid = getnum_checked(value,
-							&dopts, D_PROJINHERIT);
+					fsx.fsx_projid = getnum(value, &dopts,
+								D_PROJINHERIT);
 					fsx.fsx_xflags |=
 						XFS_DIFLAG_PROJINHERIT;
 					break;
 				case D_EXTSZINHERIT:
-					fsx.fsx_extsize = getnum_checked(value,
-							&dopts, D_EXTSZINHERIT);
+					fsx.fsx_extsize = getnum(value, &dopts,
+								 D_EXTSZINHERIT);
 					fsx.fsx_xflags |=
 						XFS_DIFLAG_EXTSZINHERIT;
 					break;
@@ -1769,8 +1758,8 @@ main(
 				switch (getsubopt(&p, (constpp)subopts,
 						  &value)) {
 				case I_ALIGN:
-					sb_feat.inode_align = getnum_checked(
-							value, &iopts, I_ALIGN);
+					sb_feat.inode_align = getnum(value,
+								&iopts, I_ALIGN);
 					break;
 				case I_LOG:
 					if (ipflag)
@@ -1779,14 +1768,13 @@ main(
 					if (isflag)
 						conflict('i', subopts, I_SIZE,
 							 I_LOG);
-					inodelog = getnum_checked(value, &iopts,
-								  I_LOG);
+					inodelog = getnum(value, &iopts, I_LOG);
 					isize = 1 << inodelog;
 					ilflag = 1;
 					break;
 				case I_MAXPCT:
-					imaxpct = getnum_checked(value, &iopts,
-								 I_MAXPCT);
+					imaxpct = getnum(value, &iopts,
+							 I_MAXPCT);
 					imflag = 1;
 					break;
 				case I_PERBLOCK:
@@ -1796,8 +1784,8 @@ main(
 					if (isflag)
 						conflict('i', subopts, I_SIZE,
 							 I_PERBLOCK);
-					inopblock = getnum_checked(value, &iopts,
-								   I_PERBLOCK);
+					inopblock = getnum(value, &iopts,
+							   I_PERBLOCK);
 					ipflag = 1;
 					break;
 				case I_SIZE:
@@ -1807,23 +1795,22 @@ main(
 					if (ipflag)
 						conflict('i', subopts, I_PERBLOCK,
 							 I_SIZE);
-					isize = getnum_checked(value, &iopts,
-							       I_SIZE);
+					isize = getnum(value, &iopts, I_SIZE);
 					inodelog = libxfs_highbit32(isize);
 					isflag = 1;
 					break;
 				case I_ATTR:
-					sb_feat.attr_version = getnum_checked(
-							value, &iopts, I_ATTR);
+					sb_feat.attr_version =
+						getnum(value, &iopts, I_ATTR);
 					break;
 				case I_PROJID32BIT:
 					sb_feat.projid16bit =
-						!getnum_checked(value, &iopts,
-								I_PROJID32BIT);
+						!getnum(value, &iopts,
+							I_PROJID32BIT);
 					break;
 				case I_SPINODES:
 					sb_feat.spinodes =
-						getnum_checked(value, &iopts,
+						getnum(value, &iopts,
 								I_SPINODES);
 					break;
 				default:
@@ -1842,13 +1829,12 @@ main(
 				case L_AGNUM:
 					if (ldflag)
 						conflict('l', subopts, L_AGNUM, L_DEV);
-					logagno = getnum_checked(value, &lopts,
-								 L_AGNUM);
+					logagno = getnum(value, &lopts, L_AGNUM);
 					laflag = 1;
 					break;
 				case L_FILE:
-					xi.lisfile = getnum_checked(value,
-								&lopts, L_FILE);
+					xi.lisfile = getnum(value, &lopts,
+							    L_FILE);
 					if (xi.lisfile && loginternal)
 						conflict('l', subopts, L_INTERNAL,
 							 L_FILE);
@@ -1862,18 +1848,16 @@ main(
 						conflict('l', subopts, L_FILE,
 							 L_INTERNAL);
 
-					loginternal = getnum_checked(value,
-							&lopts, L_INTERNAL);
+					loginternal = getnum(value, &lopts,
+							     L_INTERNAL);
 					liflag = 1;
 					break;
 				case L_SU:
-					lsu = getnum_checked(value, &lopts,
-								 L_SU);
+					lsu = getnum(value, &lopts, L_SU);
 					lsuflag = 1;
 					break;
 				case L_SUNIT:
-					lsunit = getnum_checked(value, &lopts,
-								 L_SUNIT);
+					lsunit = getnum(value, &lopts, L_SUNIT);
 					lsunitflag = 1;
 					break;
 				case L_NAME:
@@ -1893,8 +1877,7 @@ main(
 					break;
 				case L_VERSION:
 					sb_feat.log_version =
-						getnum_checked(value, &lopts,
-							       L_VERSION);
+						getnum(value, &lopts, L_VERSION);
 					lvflag = 1;
 					break;
 				case L_SIZE:
@@ -1909,8 +1892,8 @@ main(
 					if (lssflag)
 						conflict('l', subopts, L_SECTSIZE,
 							 L_SECTLOG);
-					lsectorlog = getnum_checked(value,
-							&lopts, L_SECTLOG);
+					lsectorlog = getnum(value, &lopts,
+							    L_SECTLOG);
 					lsectorsize = 1 << lsectorlog;
 					lslflag = 1;
 					break;
@@ -1918,15 +1901,15 @@ main(
 					if (lslflag)
 						conflict('l', subopts, L_SECTLOG,
 							 L_SECTSIZE);
-					lsectorsize = getnum_checked(value,
-							&lopts, L_SECTSIZE);
+					lsectorsize = getnum(value, &lopts,
+							     L_SECTSIZE);
 					lsectorlog =
 						libxfs_highbit32(lsectorsize);
 					lssflag = 1;
 					break;
 				case L_LAZYSBCNTR:
 					sb_feat.lazy_sb_counters =
-						getnum_checked(value, &lopts,
+							getnum(value, &lopts,
 							       L_LAZYSBCNTR);
 					break;
 				default:
@@ -1949,13 +1932,12 @@ main(
 						  &value)) {
 				case M_CRC:
 					sb_feat.crcs_enabled =
-						getnum_checked(value, &mopts,
-							       M_CRC);
+						getnum(value, &mopts, M_CRC);
 					if (sb_feat.crcs_enabled)
 						sb_feat.dirftype = true;
 					break;
 				case M_FINOBT:
-					sb_feat.finobt = getnum_checked(
+					sb_feat.finobt = getnum(
 						value, &mopts, M_FINOBT);
 					break;
 				case M_UUID:
@@ -1981,8 +1963,8 @@ main(
 					if (nsflag)
 						conflict('n', subopts, N_SIZE,
 							 N_LOG);
-					dirblocklog = getnum_checked(value,
-								&nopts, N_LOG);
+					dirblocklog = getnum(value, &nopts,
+							     N_LOG);
 					dirblocksize = 1 << dirblocklog;
 					nlflag = 1;
 					break;
@@ -1990,8 +1972,8 @@ main(
 					if (nlflag)
 						conflict('n', subopts, N_LOG,
 							 N_SIZE);
-					dirblocksize = getnum_checked(value,
-								&nopts, N_SIZE);
+					dirblocksize = getnum(value, &nopts,
+							      N_SIZE);
 					dirblocklog =
 						libxfs_highbit32(dirblocksize);
 					nsflag = 1;
@@ -2006,15 +1988,14 @@ main(
 						sb_feat.nci = true;
 					} else {
 						sb_feat.dir_version =
-							getnum_checked(value,
-								&nopts,
-								N_VERSION);
+							getnum(value, &nopts,
+							       N_VERSION);
 					}
 					nvflag = 1;
 					break;
 				case N_FTYPE:
-					sb_feat.dirftype = getnum_checked(value,
-								&nopts, N_FTYPE);
+					sb_feat.dirftype = getnum(value, &nopts,
+								  N_FTYPE);
 					break;
 				default:
 					unknown('n', value);
@@ -2051,8 +2032,8 @@ main(
 					rtextsize = value;
 					break;
 				case R_FILE:
-					xi.risfile = getnum_checked(value,
-								&ropts, R_FILE);
+					xi.risfile = getnum(value, &ropts,
+							    R_FILE);
 					if (xi.risfile)
 						xi.rcreat = 1;
 					break;
@@ -2072,8 +2053,8 @@ main(
 					rtsize = value;
 					break;
 				case R_NOALIGN:
-					norsflag = getnum_checked(value,
-								&ropts, R_NOALIGN);
+					norsflag = getnum(value, &ropts,
+								R_NOALIGN);
 					break;
 				default:
 					unknown('r', value);
@@ -2093,8 +2074,8 @@ main(
 					if (ssflag || lssflag)
 						conflict('s', subopts,
 							 S_SECTSIZE, S_SECTLOG);
-					sectorlog = getnum_checked(value, &sopts,
-								   S_SECTLOG);
+					sectorlog = getnum(value, &sopts,
+							   S_SECTLOG);
 					lsectorlog = sectorlog;
 					sectorsize = 1 << sectorlog;
 					lsectorsize = sectorsize;
@@ -2105,8 +2086,8 @@ main(
 					if (slflag || lslflag)
 						conflict('s', subopts, S_SECTLOG,
 							 S_SECTSIZE);
-					sectorsize = getnum_checked(value,
-							&sopts, S_SECTSIZE);
+					sectorsize = getnum(value, &sopts,
+							    S_SECTSIZE);
 					lsectorsize = sectorsize;
 					sectorlog =
 						libxfs_highbit32(sectorsize);
@@ -2335,7 +2316,7 @@ _("warning: sparse inodes not supported without CRC support, disabled.\n"));
 	if (dsize) {
 		__uint64_t dbytes;
 
-		dbytes = getnum_checked(dsize, &dopts, D_SIZE);
+		dbytes = getnum(dsize, &dopts, D_SIZE);
 		if (dbytes % XFS_MIN_BLOCKSIZE) {
 			fprintf(stderr,
 			_("illegal data length %lld, not a multiple of %d\n"),
@@ -2372,7 +2353,7 @@ _("warning: sparse inodes not supported without CRC support, disabled.\n"));
 	if (logsize) {
 		__uint64_t logbytes;
 
-		logbytes = getnum_checked(logsize, &lopts, L_SIZE);
+		logbytes = getnum(logsize, &lopts, L_SIZE);
 		if (logbytes % XFS_MIN_BLOCKSIZE) {
 			fprintf(stderr,
 			_("illegal log length %lld, not a multiple of %d\n"),
@@ -2394,7 +2375,7 @@ _("warning: sparse inodes not supported without CRC support, disabled.\n"));
 	if (rtsize) {
 		__uint64_t rtbytes;
 
-		rtbytes = getnum_checked(rtsize, &ropts, R_SIZE);
+		rtbytes = getnum(rtsize, &ropts, R_SIZE);
 		if (rtbytes % XFS_MIN_BLOCKSIZE) {
 			fprintf(stderr,
 			_("illegal rt length %lld, not a multiple of %d\n"),
@@ -2414,7 +2395,7 @@ _("warning: sparse inodes not supported without CRC support, disabled.\n"));
 	if (rtextsize) {
 		__uint64_t rtextbytes;
 
-		rtextbytes = getnum_checked(rtextsize, &ropts, R_EXTSIZE);
+		rtextbytes = getnum(rtextsize, &ropts, R_EXTSIZE);
 		if (rtextbytes % blocksize) {
 			fprintf(stderr,
 		_("illegal rt extent size %lld, not a multiple of %d\n"),
@@ -3517,8 +3498,8 @@ unknown(
 
 long long
 cvtnum(
-	unsigned int	blocksize,
-	unsigned int	sectorsize,
+	unsigned int	blksize,
+	unsigned int	sectsize,
 	const char	*s)
 {
 	long long	i;
@@ -3531,9 +3512,9 @@ cvtnum(
 		return i;
 
 	if (*sp == 'b' && sp[1] == '\0')
-		return i * blocksize;
+		return i * blksize;
 	if (*sp == 's' && sp[1] == '\0')
-		return i * sectorsize;
+		return i * sectsize;
 
 	if (*sp == 'k' && sp[1] == '\0')
 		return 1024LL * i;
-- 
2.5.0

_______________________________________________
xfs mailing list
xfs@oss.sgi.com
http://oss.sgi.com/mailman/listinfo/xfs

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

* [PATCH 13/19] mkfs: encode conflicts into parsing table
  2016-04-21  9:39 [PATCH 00/19 v2] mkfs cleaning Jan Tulak
                   ` (11 preceding siblings ...)
  2016-04-21  9:39 ` [PATCH 12/19] mkfs: merge getnum Jan Tulak
@ 2016-04-21  9:39 ` Jan Tulak
  2016-05-02 23:11   ` Eric Sandeen
  2016-05-03 23:39   ` Eric Sandeen
  2016-04-21  9:39 ` [PATCH 14/19] mkfs: add string options to generic parsing Jan Tulak
                   ` (8 subsequent siblings)
  21 siblings, 2 replies; 51+ messages in thread
From: Jan Tulak @ 2016-04-21  9:39 UTC (permalink / raw)
  To: xfs

From: Dave Chinner <dchinner@redhat.com>

Many options conflict, so we need to specify which options conflict
with each other in a generic manner. We already have a "seen"
variable used for respecification detection, so we can also use this
code conflict detection. Hence add a "conflicts" array to the sub
options parameter definition.

Signed-off-by: Dave Chinner <dchinner@redhat.com>
Signed-off-by: Jan Tulak <jtulak@redhat.com>
Reviewed-by: Eric Sandeen <sandeen@redhat.com>
---
 mkfs/xfs_mkfs.c | 258 +++++++++++++++++++++++++++++---------------------------
 1 file changed, 134 insertions(+), 124 deletions(-)

diff --git a/mkfs/xfs_mkfs.c b/mkfs/xfs_mkfs.c
index a45dc7f..83ccab5 100644
--- a/mkfs/xfs_mkfs.c
+++ b/mkfs/xfs_mkfs.c
@@ -54,6 +54,9 @@ unsigned int		sectorsize;
 
 #define MAX_SUBOPTS	16
 #define SUBOPT_NEEDS_VAL	(-1LL)
+#define MAX_CONFLICTS	8
+#define LAST_CONFLICT	(-1)
+
 /*
  * Table for parsing mkfs parameters.
  *
@@ -89,6 +92,11 @@ unsigned int		sectorsize;
  *     An optional flag for subopts where the given value has to be a power
  *     of two.
  *
+ *   conflicts MANDATORY
+ *     If your subopt is in a conflict with some other option, specify it.
+ *     Accepts the .index values of the conflicting subopts and the last
+ *     member of this list has to be LAST_CONFLICT.
+ *
  *   minval, maxval OPTIONAL
  *     These options are used for automatic range check and they have to be
  *     always used together in pair. If you don't want to limit the max value,
@@ -118,6 +126,7 @@ struct opt_params {
 		bool		seen;
 		bool		convert;
 		bool		is_power_2;
+		int		conflicts[MAX_CONFLICTS];
 		long long	minval;
 		long long	maxval;
 		long long	defaultval;
@@ -135,6 +144,8 @@ struct opt_params bopts = {
 	},
 	.subopt_params = {
 		{ .index = B_LOG,
+		  .conflicts = { B_SIZE,
+				 LAST_CONFLICT },
 		  .minval = XFS_MIN_BLOCKSIZE_LOG,
 		  .maxval = XFS_MAX_BLOCKSIZE_LOG,
 		  .defaultval = SUBOPT_NEEDS_VAL,
@@ -142,6 +153,8 @@ struct opt_params bopts = {
 		{ .index = B_SIZE,
 		  .convert = true,
 		  .is_power_2 = true,
+		  .conflicts = { B_LOG,
+				 LAST_CONFLICT },
 		  .minval = XFS_MIN_BLOCKSIZE,
 		  .maxval = XFS_MAX_BLOCKSIZE,
 		  .defaultval = SUBOPT_NEEDS_VAL,
@@ -186,57 +199,84 @@ struct opt_params dopts = {
 	},
 	.subopt_params = {
 		{ .index = D_AGCOUNT,
+		  .conflicts = { D_AGSIZE,
+				 LAST_CONFLICT },
 		  .minval = 1,
 		  .maxval = XFS_MAX_AGNUMBER,
 		  .defaultval = SUBOPT_NEEDS_VAL,
 		},
 		{ .index = D_FILE,
+		  .conflicts = { LAST_CONFLICT },
 		  .minval = 0,
 		  .maxval = 1,
 		  .defaultval = 1,
 		},
 		{ .index = D_NAME,
+		  .conflicts = { LAST_CONFLICT },
 		  .defaultval = SUBOPT_NEEDS_VAL,
 		},
 		{ .index = D_SIZE,
+		  .conflicts = { LAST_CONFLICT },
 		  .convert = true,
 		  .minval = XFS_AG_MIN_BYTES,
 		  .maxval = LLONG_MAX,
 		  .defaultval = SUBOPT_NEEDS_VAL,
 		},
 		{ .index = D_SUNIT,
+		  .conflicts = { D_NOALIGN,
+				 D_SU,
+				 D_SW,
+				 LAST_CONFLICT },
 		  .minval = 0,
 		  .maxval = UINT_MAX,
 		  .defaultval = SUBOPT_NEEDS_VAL,
 		},
 		{ .index = D_SWIDTH,
+		  .conflicts = { D_NOALIGN,
+				 D_SU,
+				 D_SW,
+				 LAST_CONFLICT },
 		  .minval = 0,
 		  .maxval = UINT_MAX,
 		  .defaultval = SUBOPT_NEEDS_VAL,
 		},
 		{ .index = D_AGSIZE,
+		  .conflicts = { D_AGCOUNT,
+				 LAST_CONFLICT },
 		  .convert = true,
 		  .minval = XFS_AG_MIN_BYTES,
 		  .maxval = XFS_AG_MAX_BYTES,
 		  .defaultval = SUBOPT_NEEDS_VAL,
 		},
 		{ .index = D_SU,
+		  .conflicts = { D_NOALIGN,
+				 D_SUNIT,
+				 D_SWIDTH,
+				 LAST_CONFLICT },
 		  .convert = true,
 		  .minval = 0,
 		  .maxval = UINT_MAX,
 		  .defaultval = SUBOPT_NEEDS_VAL,
 		},
 		{ .index = D_SW,
+		  .conflicts = { D_NOALIGN,
+				 D_SUNIT,
+				 D_SWIDTH,
+				 LAST_CONFLICT },
 		  .minval = 0,
 		  .maxval = UINT_MAX,
 		  .defaultval = SUBOPT_NEEDS_VAL,
 		},
 		{ .index = D_SECTLOG,
+		  .conflicts = { D_SECTSIZE,
+				 LAST_CONFLICT },
 		  .minval = XFS_MIN_SECTORSIZE_LOG,
 		  .maxval = XFS_MAX_SECTORSIZE_LOG,
 		  .defaultval = SUBOPT_NEEDS_VAL,
 		},
 		{ .index = D_SECTSIZE,
+		  .conflicts = { D_SECTLOG,
+				 LAST_CONFLICT },
 		  .convert = true,
 		  .is_power_2 = true,
 		  .minval = XFS_MIN_SECTORSIZE,
@@ -244,21 +284,29 @@ struct opt_params dopts = {
 		  .defaultval = SUBOPT_NEEDS_VAL,
 		},
 		{ .index = D_NOALIGN,
+		  .conflicts = { D_SU,
+				 D_SW,
+				 D_SUNIT,
+				 D_SWIDTH,
+				 LAST_CONFLICT },
 		  .minval = 0,
 		  .maxval = 1,
 		  .defaultval = 1,
 		},
 		{ .index = D_RTINHERIT,
+		  .conflicts = { LAST_CONFLICT },
 		  .minval = 1,
 		  .maxval = 1,
 		  .defaultval = 1,
 		},
 		{ .index = D_PROJINHERIT,
+		  .conflicts = { LAST_CONFLICT },
 		  .minval = 0,
 		  .maxval = UINT_MAX,
 		  .defaultval = SUBOPT_NEEDS_VAL,
 		},
 		{ .index = D_EXTSZINHERIT,
+		  .conflicts = { LAST_CONFLICT },
 		  .minval = 0,
 		  .maxval = UINT_MAX,
 		  .defaultval = SUBOPT_NEEDS_VAL,
@@ -290,43 +338,57 @@ struct opt_params iopts = {
 	},
 	.subopt_params = {
 		{ .index = I_ALIGN,
+		  .conflicts = { LAST_CONFLICT },
 		  .minval = 0,
 		  .maxval = 1,
 		  .defaultval = 1,
 		},
 		{ .index = I_LOG,
+		  .conflicts = { I_PERBLOCK,
+				 I_SIZE,
+				 LAST_CONFLICT },
 		  .minval = XFS_DINODE_MIN_LOG,
 		  .maxval = XFS_DINODE_MAX_LOG,
 		  .defaultval = SUBOPT_NEEDS_VAL,
 		},
 		{ .index = I_MAXPCT,
+		  .conflicts = { LAST_CONFLICT },
 		  .minval = 0,
 		  .maxval = 100,
 		  .defaultval = SUBOPT_NEEDS_VAL,
 		},
 		{ .index = I_PERBLOCK,
+		  .conflicts = { I_LOG,
+				 I_SIZE,
+				 LAST_CONFLICT },
 		  .is_power_2 = true,
 		  .minval = XFS_MIN_INODE_PERBLOCK,
 		  .maxval = XFS_MAX_BLOCKSIZE / XFS_DINODE_MIN_SIZE,
 		  .defaultval = SUBOPT_NEEDS_VAL,
 		},
 		{ .index = I_SIZE,
+		  .conflicts = { I_PERBLOCK,
+				 I_LOG,
+				 LAST_CONFLICT },
 		  .is_power_2 = true,
 		  .minval = XFS_DINODE_MIN_SIZE,
 		  .maxval = XFS_DINODE_MAX_SIZE,
 		  .defaultval = SUBOPT_NEEDS_VAL,
 		},
 		{ .index = I_ATTR,
+		  .conflicts = { LAST_CONFLICT },
 		  .minval = 0,
 		  .maxval = 2,
 		  .defaultval = SUBOPT_NEEDS_VAL,
 		},
 		{ .index = I_PROJID32BIT,
+		  .conflicts = { LAST_CONFLICT },
 		  .minval = 0,
 		  .maxval = 1,
 		  .defaultval = 1,
 		},
 		{ .index = I_SPINODES,
+		  .conflicts = { LAST_CONFLICT },
 		  .minval = 0,
 		  .maxval = 1,
 		  .defaultval = 1,
@@ -365,46 +427,64 @@ struct opt_params lopts = {
 	},
 	.subopt_params = {
 		{ .index = L_AGNUM,
+		  .conflicts = { L_DEV,
+				 LAST_CONFLICT },
 		  .minval = 0,
 		  .maxval = UINT_MAX,
 		  .defaultval = SUBOPT_NEEDS_VAL,
 		},
 		{ .index = L_INTERNAL,
+		  .conflicts = { L_FILE,
+				 L_DEV,
+				 LAST_CONFLICT },
 		  .minval = 0,
 		  .maxval = 1,
 		  .defaultval = 1,
 		},
 		{ .index = L_SIZE,
+		  .conflicts = { LAST_CONFLICT },
 		  .convert = true,
 		  .minval = 2 * 1024 * 1024LL,	/* XXX: XFS_MIN_LOG_BYTES */
 		  .maxval = XFS_MAX_LOG_BYTES,
 		  .defaultval = SUBOPT_NEEDS_VAL,
 		},
 		{ .index = L_VERSION,
+		  .conflicts = { LAST_CONFLICT },
 		  .minval = 1,
 		  .maxval = 2,
 		  .defaultval = SUBOPT_NEEDS_VAL,
 		},
 		{ .index = L_SUNIT,
+		  .conflicts = { L_SU,
+				 LAST_CONFLICT },
 		  .minval = BTOBB(XLOG_MIN_RECORD_BSIZE),
 		  .maxval = BTOBB(XLOG_MAX_RECORD_BSIZE),
 		  .defaultval = SUBOPT_NEEDS_VAL,
 		},
 		{ .index = L_SU,
+		  .conflicts = { L_SUNIT,
+				 LAST_CONFLICT },
 		  .convert = true,
 		  .minval = 0,
 		  .maxval = UINT_MAX,
 		  .defaultval = SUBOPT_NEEDS_VAL,
 		},
 		{ .index = L_DEV,
+		  .conflicts = { L_AGNUM,
+				 L_INTERNAL,
+				 LAST_CONFLICT },
 		  .defaultval = SUBOPT_NEEDS_VAL,
 		},
 		{ .index = L_SECTLOG,
+		  .conflicts = { L_SECTSIZE,
+				 LAST_CONFLICT },
 		  .minval = XFS_MIN_SECTORSIZE_LOG,
 		  .maxval = XFS_MAX_SECTORSIZE_LOG,
 		  .defaultval = SUBOPT_NEEDS_VAL,
 		},
 		{ .index = L_SECTSIZE,
+		  .conflicts = { L_SECTLOG,
+				 LAST_CONFLICT },
 		  .convert = true,
 		  .is_power_2 = true,
 		  .minval = XFS_MIN_SECTORSIZE,
@@ -412,14 +492,20 @@ struct opt_params lopts = {
 		  .defaultval = SUBOPT_NEEDS_VAL,
 		},
 		{ .index = L_FILE,
+		  .conflicts = { L_INTERNAL,
+				 LAST_CONFLICT },
 		  .minval = 0,
 		  .maxval = 1,
 		  .defaultval = 1,
 		},
 		{ .index = L_NAME,
+		  .conflicts = { L_AGNUM,
+				 L_INTERNAL,
+				 LAST_CONFLICT },
 		  .defaultval = SUBOPT_NEEDS_VAL,
 		},
 		{ .index = L_LAZYSBCNTR,
+		  .conflicts = { LAST_CONFLICT },
 		  .minval = 0,
 		  .maxval = 1,
 		  .defaultval = 1,
@@ -442,11 +528,15 @@ struct opt_params nopts = {
 	},
 	.subopt_params = {
 		{ .index = N_LOG,
+		  .conflicts = { N_SIZE,
+				 LAST_CONFLICT },
 		  .minval = XFS_MIN_REC_DIRSIZE,
 		  .maxval = XFS_MAX_BLOCKSIZE_LOG,
 		  .defaultval = SUBOPT_NEEDS_VAL,
 		},
 		{ .index = N_SIZE,
+		  .conflicts = { N_LOG,
+				 LAST_CONFLICT },
 		  .convert = true,
 		  .is_power_2 = true,
 		  .minval = 1 << XFS_MIN_REC_DIRSIZE,
@@ -454,11 +544,13 @@ struct opt_params nopts = {
 		  .defaultval = SUBOPT_NEEDS_VAL,
 		},
 		{ .index = N_VERSION,
+		  .conflicts = { LAST_CONFLICT },
 		  .minval = 2,
 		  .maxval = 2,
 		  .defaultval = SUBOPT_NEEDS_VAL,
 		},
 		{ .index = N_FTYPE,
+		  .conflicts = { LAST_CONFLICT },
 		  .minval = 0,
 		  .maxval = 1,
 		  .defaultval = 1,
@@ -485,32 +577,38 @@ struct opt_params ropts = {
 	},
 	.subopt_params = {
 		{ .index = R_EXTSIZE,
+		  .conflicts = { LAST_CONFLICT },
 		  .convert = true,
 		  .minval = XFS_MIN_RTEXTSIZE,
 		  .maxval = XFS_MAX_RTEXTSIZE,
 		  .defaultval = SUBOPT_NEEDS_VAL,
 		},
 		{ .index = R_SIZE,
+		  .conflicts = { LAST_CONFLICT },
 		  .convert = true,
 		  .minval = 0,
 		  .maxval = LLONG_MAX,
 		  .defaultval = SUBOPT_NEEDS_VAL,
 		},
 		{ .index = R_DEV,
+		  .conflicts = { LAST_CONFLICT },
 		  .defaultval = SUBOPT_NEEDS_VAL,
 		},
 		{ .index = R_FILE,
 		  .minval = 0,
 		  .maxval = 1,
 		  .defaultval = 1,
+		  .conflicts = { LAST_CONFLICT },
 		},
 		{ .index = R_NAME,
+		  .conflicts = { LAST_CONFLICT },
 		  .defaultval = SUBOPT_NEEDS_VAL,
 		},
 		{ .index = R_NOALIGN,
 		  .minval = 0,
 		  .maxval = 1,
 		  .defaultval = 1,
+		  .conflicts = { LAST_CONFLICT },
 		},
 	},
 };
@@ -530,16 +628,25 @@ struct opt_params sopts = {
 	},
 	.subopt_params = {
 		{ .index = S_LOG,
+		  .conflicts = { S_SIZE,
+				 S_SECTSIZE,
+				 LAST_CONFLICT },
 		  .minval = XFS_MIN_SECTORSIZE_LOG,
 		  .maxval = XFS_MAX_SECTORSIZE_LOG,
 		  .defaultval = SUBOPT_NEEDS_VAL,
 		},
 		{ .index = S_SECTLOG,
+		  .conflicts = { S_SIZE,
+				 S_SECTSIZE,
+				 LAST_CONFLICT },
 		  .minval = XFS_MIN_SECTORSIZE_LOG,
 		  .maxval = XFS_MAX_SECTORSIZE_LOG,
 		  .defaultval = SUBOPT_NEEDS_VAL,
 		},
 		{ .index = S_SIZE,
+		  .conflicts = { S_LOG,
+				 S_SECTLOG,
+				 LAST_CONFLICT },
 		  .convert = true,
 		  .is_power_2 = true,
 		  .minval = XFS_MIN_SECTORSIZE,
@@ -547,6 +654,9 @@ struct opt_params sopts = {
 		  .defaultval = SUBOPT_NEEDS_VAL,
 		},
 		{ .index = S_SECTSIZE,
+		  .conflicts = { S_LOG,
+				 S_SECTLOG,
+				 LAST_CONFLICT },
 		  .convert = true,
 		  .is_power_2 = true,
 		  .minval = XFS_MIN_SECTORSIZE,
@@ -569,16 +679,19 @@ struct opt_params mopts = {
 	},
 	.subopt_params = {
 		{ .index = M_CRC,
+		  .conflicts = { LAST_CONFLICT },
 		  .minval = 0,
 		  .maxval = 1,
 		  .defaultval = 1,
 		},
 		{ .index = M_FINOBT,
+		  .conflicts = { LAST_CONFLICT },
 		  .minval = 0,
 		  .maxval = 1,
 		  .defaultval = 1,
 		},
 		{ .index = M_UUID,
+		  .conflicts = { LAST_CONFLICT },
 		  .defaultval = SUBOPT_NEEDS_VAL,
 		},
 	},
@@ -620,30 +733,14 @@ calc_stripe_factors(
 	int		*lsunit)
 {
 	/* Handle data sunit/swidth options */
-	if (*dsunit || *dswidth) {
-		if (dsu || dsw) {
-			fprintf(stderr,
-				_("data su/sw must not be used in "
-				"conjunction with data sunit/swidth\n"));
-			usage();
-		}
-
-		if ((*dsunit && !*dswidth) || (!*dsunit && *dswidth)) {
-			fprintf(stderr,
-				_("both data sunit and data swidth options "
-				"must be specified\n"));
-			usage();
-		}
+	if ((*dsunit && !*dswidth) || (!*dsunit && *dswidth)) {
+		fprintf(stderr,
+			_("both data sunit and data swidth options "
+			"must be specified\n"));
+		usage();
 	}
 
 	if (dsu || dsw) {
-		if (*dsunit || *dswidth) {
-			fprintf(stderr,
-				_("data sunit/swidth must not be used in "
-				"conjunction with data su/sw\n"));
-			usage();
-		}
-
 		if ((dsu && !dsw) || (!dsu && dsw)) {
 			fprintf(stderr,
 				_("both data su and data sw options "
@@ -671,24 +768,8 @@ calc_stripe_factors(
 
 	/* Handle log sunit options */
 
-	if (*lsunit) {
-		if (lsu) {
-			fprintf(stderr,
-				_("log su should not be used in "
-				"conjunction with log sunit\n"));
-			usage();
-		}
-	}
-
-	if (lsu) {
-		if (*lsunit) {
-			fprintf(stderr,
-				_("log sunit should not be used in "
-				"conjunction with log su\n"));
-			usage();
-		}
+	if (lsu)
 		*lsunit = (int)BTOBBT(lsu);
-	}
 }
 
 /*
@@ -1411,6 +1492,17 @@ getnum(
 		respec(opts->name, (char **)opts->subopts, index);
 	sp->seen = true;
 
+	/* check for conflicts with the option */
+	for (c = 0; c < MAX_CONFLICTS; c++) {
+		int conflict_opt = sp->conflicts[c];
+
+		if (conflict_opt == LAST_CONFLICT)
+			break;
+		if (opts->subopt_params[conflict_opt].seen)
+			conflict(opts->name, (char **)opts->subopts,
+				 conflict_opt, index);
+	}
+
 	/* empty strings might just return a default value */
 	if (!str || *str == '\0') {
 		if (sp->defaultval == SUBOPT_NEEDS_VAL)
@@ -1606,17 +1698,11 @@ main(
 				switch (getsubopt(&p, (constpp)subopts,
 						  &value)) {
 				case B_LOG:
-					if (bsflag)
-						conflict('b', subopts, B_SIZE,
-							 B_LOG);
 					blocklog = getnum(value, &bopts, B_LOG);
 					blocksize = 1 << blocklog;
 					blflag = 1;
 					break;
 				case B_SIZE:
-					if (blflag)
-						conflict('b', subopts, B_LOG,
-							 B_SIZE);
 					blocksize = getnum(value, &bopts,
 							   B_SIZE);
 					blocklog = libxfs_highbit32(blocksize);
@@ -1665,61 +1751,29 @@ main(
 					dsize = value;
 					break;
 				case D_SUNIT:
-					if (nodsflag)
-						conflict('d', subopts, D_NOALIGN,
-							 D_SUNIT);
 					dsunit = getnum(value, &dopts, D_SUNIT);
 					break;
 				case D_SWIDTH:
-					if (nodsflag)
-						conflict('d', subopts, D_NOALIGN,
-							 D_SWIDTH);
 					dswidth = getnum(value, &dopts,
 							 D_SWIDTH);
 					break;
 				case D_SU:
-					if (nodsflag)
-						conflict('d', subopts, D_NOALIGN,
-							 D_SU);
 					dsu = getnum(value, &dopts, D_SU);
 					break;
 				case D_SW:
-					if (nodsflag)
-						conflict('d', subopts, D_NOALIGN,
-							 D_SW);
 					dsw = getnum(value, &dopts, D_SW);
 					break;
 				case D_NOALIGN:
 					nodsflag = getnum(value, &dopts,
-							 	D_NOALIGN);
-					if (nodsflag) {
-						if (dsu)
-							conflict('d', subopts, D_SU,
-								D_NOALIGN);
-						if (dsunit)
-							conflict('d', subopts, D_SUNIT,
-								D_NOALIGN);
-						if (dsw)
-							conflict('d', subopts, D_SW,
 								D_NOALIGN);
-						if (dswidth)
-							conflict('d', subopts, D_SWIDTH,
-								D_NOALIGN);
-					}
 					break;
 				case D_SECTLOG:
-					if (ssflag)
-						conflict('d', subopts, D_SECTSIZE,
-							 D_SECTLOG);
 					sectorlog = getnum(value, &dopts,
 							   D_SECTLOG);
 					sectorsize = 1 << sectorlog;
 					slflag = 1;
 					break;
 				case D_SECTSIZE:
-					if (slflag)
-						conflict('d', subopts, D_SECTLOG,
-							 D_SECTSIZE);
 					sectorsize = getnum(value, &dopts,
 							    D_SECTSIZE);
 					sectorlog =
@@ -1762,12 +1816,6 @@ main(
 								&iopts, I_ALIGN);
 					break;
 				case I_LOG:
-					if (ipflag)
-						conflict('i', subopts, I_PERBLOCK,
-							 I_LOG);
-					if (isflag)
-						conflict('i', subopts, I_SIZE,
-							 I_LOG);
 					inodelog = getnum(value, &iopts, I_LOG);
 					isize = 1 << inodelog;
 					ilflag = 1;
@@ -1778,23 +1826,11 @@ main(
 					imflag = 1;
 					break;
 				case I_PERBLOCK:
-					if (ilflag)
-						conflict('i', subopts, I_LOG,
-							 I_PERBLOCK);
-					if (isflag)
-						conflict('i', subopts, I_SIZE,
-							 I_PERBLOCK);
 					inopblock = getnum(value, &iopts,
 							   I_PERBLOCK);
 					ipflag = 1;
 					break;
 				case I_SIZE:
-					if (ilflag)
-						conflict('i', subopts, I_LOG,
-							 I_SIZE);
-					if (ipflag)
-						conflict('i', subopts, I_PERBLOCK,
-							 I_SIZE);
 					isize = getnum(value, &iopts, I_SIZE);
 					inodelog = libxfs_highbit32(isize);
 					isflag = 1;
@@ -1809,9 +1845,8 @@ main(
 							I_PROJID32BIT);
 					break;
 				case I_SPINODES:
-					sb_feat.spinodes =
-						getnum(value, &iopts,
-								I_SPINODES);
+					sb_feat.spinodes = getnum(value,
+							&iopts, I_SPINODES);
 					break;
 				default:
 					unknown('i', value);
@@ -1827,8 +1862,6 @@ main(
 				switch (getsubopt(&p, (constpp)subopts,
 						  &value)) {
 				case L_AGNUM:
-					if (ldflag)
-						conflict('l', subopts, L_AGNUM, L_DEV);
 					logagno = getnum(value, &lopts, L_AGNUM);
 					laflag = 1;
 					break;
@@ -1842,12 +1875,6 @@ main(
 						xi.lcreat = 1;
 					break;
 				case L_INTERNAL:
-					if (ldflag)
-						conflict('l', subopts, L_INTERNAL, L_DEV);
-					if (xi.lisfile)
-						conflict('l', subopts, L_FILE,
-							 L_INTERNAL);
-
 					loginternal = getnum(value, &lopts,
 							     L_INTERNAL);
 					liflag = 1;
@@ -1889,18 +1916,12 @@ main(
 					lsflag = 1;
 					break;
 				case L_SECTLOG:
-					if (lssflag)
-						conflict('l', subopts, L_SECTSIZE,
-							 L_SECTLOG);
 					lsectorlog = getnum(value, &lopts,
 							    L_SECTLOG);
 					lsectorsize = 1 << lsectorlog;
 					lslflag = 1;
 					break;
 				case L_SECTSIZE:
-					if (lslflag)
-						conflict('l', subopts, L_SECTLOG,
-							 L_SECTSIZE);
 					lsectorsize = getnum(value, &lopts,
 							     L_SECTSIZE);
 					lsectorlog =
@@ -1960,18 +1981,12 @@ main(
 				switch (getsubopt(&p, (constpp)subopts,
 						  &value)) {
 				case N_LOG:
-					if (nsflag)
-						conflict('n', subopts, N_SIZE,
-							 N_LOG);
 					dirblocklog = getnum(value, &nopts,
 							     N_LOG);
 					dirblocksize = 1 << dirblocklog;
 					nlflag = 1;
 					break;
 				case N_SIZE:
-					if (nlflag)
-						conflict('n', subopts, N_LOG,
-							 N_SIZE);
 					dirblocksize = getnum(value, &nopts,
 							      N_SIZE);
 					dirblocklog =
@@ -2071,7 +2086,7 @@ main(
 						  &value)) {
 				case S_LOG:
 				case S_SECTLOG:
-					if (ssflag || lssflag)
+					if (lssflag)
 						conflict('s', subopts,
 							 S_SECTSIZE, S_SECTLOG);
 					sectorlog = getnum(value, &sopts,
@@ -2083,7 +2098,7 @@ main(
 					break;
 				case S_SIZE:
 				case S_SECTSIZE:
-					if (slflag || lslflag)
+					if (lslflag)
 						conflict('s', subopts, S_SECTLOG,
 							 S_SECTSIZE);
 					sectorsize = getnum(value, &sopts,
@@ -2302,11 +2317,6 @@ _("warning: sparse inodes not supported without CRC support, disabled.\n"));
 		dirblocksize = 1 << dirblocklog;
 	}
 
-	if (daflag && dasize) {
-		fprintf(stderr,
-	_("both -d agcount= and agsize= specified, use one or the other\n"));
-		usage();
-	}
 
 	if (xi.disfile && (!dsize || !xi.dname)) {
 		fprintf(stderr,
-- 
2.5.0

_______________________________________________
xfs mailing list
xfs@oss.sgi.com
http://oss.sgi.com/mailman/listinfo/xfs

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

* [PATCH 14/19] mkfs: add string options to generic parsing
  2016-04-21  9:39 [PATCH 00/19 v2] mkfs cleaning Jan Tulak
                   ` (12 preceding siblings ...)
  2016-04-21  9:39 ` [PATCH 13/19] mkfs: encode conflicts into parsing table Jan Tulak
@ 2016-04-21  9:39 ` Jan Tulak
  2016-05-02 23:11   ` Eric Sandeen
  2016-04-21  9:39 ` [PATCH 15/19] mkfs: don't treat files as though they are block devices Jan Tulak
                   ` (7 subsequent siblings)
  21 siblings, 1 reply; 51+ messages in thread
From: Jan Tulak @ 2016-04-21  9:39 UTC (permalink / raw)
  To: xfs

From: Dave Chinner <dchinner@redhat.com>

So that string options are correctly detected for conflicts and
respecification, add a getstr() function that modifies the option
tables appropriately.

Signed-off-by: Dave Chinner <dchinner@redhat.com>
Signed-off-by: Jan Tulak <jtulak@redhat.com>
Reviewed-by: Eric Sandeen <sandeen@redhat.com>
---
 mkfs/xfs_mkfs.c | 143 ++++++++++++++++++++++++++++++--------------------------
 1 file changed, 78 insertions(+), 65 deletions(-)

diff --git a/mkfs/xfs_mkfs.c b/mkfs/xfs_mkfs.c
index 83ccab5..b1043fb 100644
--- a/mkfs/xfs_mkfs.c
+++ b/mkfs/xfs_mkfs.c
@@ -83,6 +83,10 @@ unsigned int		sectorsize;
  *     Do not set this flag when definning a subopt. It is used to remeber that
  *     this subopt was already seen, for example for conflicts detection.
  *
+ *   str_seen INTERNAL
+ *     Do not set. It is used internally for respecification, when some options
+ *     has to be parsed twice - at first as a string, then later as a number.
+ *
  *   convert OPTIONAL
  *     A flag signalling whether the user-given value can use suffixes.
  *     If you want to allow the use of user-friendly values like 13k, 42G,
@@ -124,6 +128,7 @@ struct opt_params {
 	struct subopt_param {
 		int		index;
 		bool		seen;
+		bool		str_seen;
 		bool		convert;
 		bool		is_power_2;
 		int		conflicts[MAX_CONFLICTS];
@@ -1471,14 +1476,17 @@ illegal_option(
 	usage();
 }
 
-static long long
-getnum(
-	const char		*str,
+/*
+ * Check for conflicts and option respecification.
+ */
+static void
+check_opt(
 	struct opt_params	*opts,
-	int			index)
+	int			index,
+	bool			str_seen)
 {
-	struct subopt_param *sp = &opts->subopt_params[index];
-	long long		c;
+	struct subopt_param	*sp = &opts->subopt_params[index];
+	int			i;
 
 	if (sp->index != index) {
 		fprintf(stderr,
@@ -1487,22 +1495,47 @@ getnum(
 		reqval(opts->name, (char **)opts->subopts, index);
 	}
 
-	/* check for respecification of the option */
-	if (sp->seen)
-		respec(opts->name, (char **)opts->subopts, index);
-	sp->seen = true;
+	/*
+	 * Check for respecification of the option. This is more complex than it
+	 * seems because some options are parsed twice - once as a string during
+	 * input parsing, then later the string is passed to getnum for
+	 * conversion into a number and bounds checking. Hence the two variables
+	 * used to track the different uses based on the @str parameter passed
+	 * to us.
+	 */
+	if (!str_seen) {
+		if (sp->seen)
+			respec(opts->name, (char **)opts->subopts, index);
+		sp->seen = true;
+	} else {
+		if (sp->str_seen)
+			respec(opts->name, (char **)opts->subopts, index);
+		sp->str_seen = true;
+	}
 
 	/* check for conflicts with the option */
-	for (c = 0; c < MAX_CONFLICTS; c++) {
-		int conflict_opt = sp->conflicts[c];
+	for (i = 0; i < MAX_CONFLICTS; i++) {
+		int conflict_opt = sp->conflicts[i];
 
 		if (conflict_opt == LAST_CONFLICT)
 			break;
-		if (opts->subopt_params[conflict_opt].seen)
+		if (opts->subopt_params[conflict_opt].seen ||
+			opts->subopt_params[conflict_opt].str_seen)
 			conflict(opts->name, (char **)opts->subopts,
 				 conflict_opt, index);
 	}
+}
 
+static long long
+getnum(
+	const char		*str,
+	struct opt_params	*opts,
+	int			index)
+{
+	struct subopt_param	*sp = &opts->subopt_params[index];
+	long long		c;
+
+	check_opt(opts, index, false);
 	/* empty strings might just return a default value */
 	if (!str || *str == '\0') {
 		if (sp->defaultval == SUBOPT_NEEDS_VAL)
@@ -1544,6 +1577,26 @@ getnum(
 	return c;
 }
 
+/*
+ * Option is a string - do all the option table work, and check there
+ * is actually an option string. Otherwise we don't do anything with the string
+ * here - validation will be done later when the string is converted to a value
+ * or used as a file/device path.
+ */
+static char *
+getstr(
+	char			*str,
+	struct opt_params	*opts,
+	int			index)
+{
+	check_opt(opts, index, true);
+
+	/* empty strings for string options are not valid */
+	if (!str || *str == '\0')
+		reqval(opts->name, (char **)opts->subopts, index);
+	return str;
+}
+
 int
 main(
 	int			argc,
@@ -1737,18 +1790,10 @@ main(
 						xi.dcreat = 1;
 					break;
 				case D_NAME:
-					if (!value || *value == '\0')
-						reqval('d', subopts, D_NAME);
-					if (xi.dname)
-						respec('d', subopts, D_NAME);
-					xi.dname = value;
+					xi.dname = getstr(value, &dopts, D_NAME);
 					break;
 				case D_SIZE:
-					if (!value || *value == '\0')
-						reqval('d', subopts, D_SIZE);
-					if (dsize)
-						respec('d', subopts, D_SIZE);
-					dsize = value;
+					dsize = getstr(value, &dopts, D_SIZE);
 					break;
 				case D_SUNIT:
 					dsunit = getnum(value, &dopts, D_SUNIT);
@@ -1889,18 +1934,10 @@ main(
 					break;
 				case L_NAME:
 				case L_DEV:
-					if (laflag)
-						conflict('l', subopts, L_AGNUM, L_DEV);
-					if (liflag)
-						conflict('l', subopts, L_INTERNAL, L_DEV);
-					if (!value || *value == '\0')
-						reqval('l', subopts, L_NAME);
-					if (xi.logname)
-						respec('l', subopts, L_NAME);
+					logfile = getstr(value, &lopts, L_NAME);
+					xi.logname = logfile;
 					ldflag = 1;
 					loginternal = 0;
-					logfile = value;
-					xi.logname = value;
 					break;
 				case L_VERSION:
 					sb_feat.log_version =
@@ -1908,12 +1945,7 @@ main(
 					lvflag = 1;
 					break;
 				case L_SIZE:
-					if (!value || *value == '\0')
-						reqval('l', subopts, L_SIZE);
-					if (logsize)
-						respec('l', subopts, L_SIZE);
-					logsize = value;
-					lsflag = 1;
+					logsize = getstr(value, &lopts, L_SIZE);
 					break;
 				case L_SECTLOG:
 					lsectorlog = getnum(value, &lopts,
@@ -1994,10 +2026,7 @@ main(
 					nsflag = 1;
 					break;
 				case N_VERSION:
-					if (!value || *value == '\0')
-						reqval('n', subopts, N_VERSION);
-					if (nvflag)
-						respec('n', subopts, N_VERSION);
+					value = getstr(value, &nopts, N_VERSION);
 					if (!strcasecmp(value, "ci")) {
 						/* ASCII CI mode */
 						sb_feat.nci = true;
@@ -2040,11 +2069,8 @@ main(
 				switch (getsubopt(&p, (constpp)subopts,
 						  &value)) {
 				case R_EXTSIZE:
-					if (!value || *value == '\0')
-						reqval('r', subopts, R_EXTSIZE);
-					if (rtextsize)
-						respec('r', subopts, R_EXTSIZE);
-					rtextsize = value;
+					rtextsize = getstr(value, &ropts,
+							   R_EXTSIZE);
 					break;
 				case R_FILE:
 					xi.risfile = getnum(value, &ropts,
@@ -2054,18 +2080,11 @@ main(
 					break;
 				case R_NAME:
 				case R_DEV:
-					if (!value || *value == '\0')
-						reqval('r', subopts, R_NAME);
-					if (xi.rtname)
-						respec('r', subopts, R_NAME);
-					xi.rtname = value;
+					xi.rtname = getstr(value, &ropts,
+							   R_NAME);
 					break;
 				case R_SIZE:
-					if (!value || *value == '\0')
-						reqval('r', subopts, R_SIZE);
-					if (rtsize)
-						respec('r', subopts, R_SIZE);
-					rtsize = value;
+					rtsize = getstr(value, &ropts, R_SIZE);
 					break;
 				case R_NOALIGN:
 					norsflag = getnum(value, &ropts,
@@ -2125,13 +2144,7 @@ main(
 		fprintf(stderr, _("extra arguments\n"));
 		usage();
 	} else if (argc - optind == 1) {
-		dfile = xi.volname = argv[optind];
-		if (xi.dname) {
-			fprintf(stderr,
-				_("cannot specify both %s and -d name=%s\n"),
-				xi.volname, xi.dname);
-			usage();
-		}
+		dfile = xi.volname = getstr(argv[optind], &dopts, D_NAME);
 	} else
 		dfile = xi.dname;
 
-- 
2.5.0

_______________________________________________
xfs mailing list
xfs@oss.sgi.com
http://oss.sgi.com/mailman/listinfo/xfs

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

* [PATCH 15/19] mkfs: don't treat files as though they are block devices
  2016-04-21  9:39 [PATCH 00/19 v2] mkfs cleaning Jan Tulak
                   ` (13 preceding siblings ...)
  2016-04-21  9:39 ` [PATCH 14/19] mkfs: add string options to generic parsing Jan Tulak
@ 2016-04-21  9:39 ` Jan Tulak
  2016-04-21 12:43   ` Jan Tulak
                     ` (2 more replies)
  2016-04-21  9:39 ` [PATCH 16/19] mkfs: move spinodes crc check Jan Tulak
                   ` (6 subsequent siblings)
  21 siblings, 3 replies; 51+ messages in thread
From: Jan Tulak @ 2016-04-21  9:39 UTC (permalink / raw)
  To: xfs

From: Dave Chinner <dchinner@redhat.com>

THIS PATCH HAS KNOWN ISSUES - it fails xfs/206 and xfs/216 tests, as it
shrinks a file instead just not using it entirely, when -d size is used.



If the device is actually a file, and "-d file" is not specified,
mkfs will try to treat it as a block device and get stuff wrong.
Image files don't necessarily have the same sector sizes as the
block device or filesystem underlying the image file, nor should we
be issuing discard ioctls on image files.

To fix this sanely, only require "-d file" if the device name is
invalid to trigger creation of the file. Otherwise, use stat() to
determine if the device is a file or block device and deal with that
appropriately by setting the "isfile" variables and turning off
direct IO. Then ensure that we check the "isfile" options before
doing things that are specific to block devices.

Other file/blockdev issues fixed:
	- use getstr to detect specifying the data device name
	  twice.
	- check file/size/name parameters before anything else.
	- overwrite checks need to be done before the image file is
	  opened and potentially truncated.
	- blkid_get_topology() should not be called for image files,
	  so warn when it is called that way.
	- zero_old_xfs_structures() emits a spurious error:
		"existing superblock read failed: Success"
	  when it is run on a truncated image file. Don't warn if we
	  see this problem on an image file.
	- Don't issue discards on image files.
	- Use fsync() for image files, not BLKFLSBUF in
	  platform_flush_device() for Linux.

Signed-off-by: Dave Chinner <dchinner@redhat.com>
Signed-off-by: Jan Tulak <jtulak@redhat.com>

---
* revert to Dave's original patch
* add missing platform_findsizes to libxfs init
---
 libxfs/init.c   |   6 ++
 libxfs/linux.c  |  11 +++-
 mkfs/xfs_mkfs.c | 168 +++++++++++++++++++++++++++++++++++++++-----------------
 3 files changed, 133 insertions(+), 52 deletions(-)

diff --git a/libxfs/init.c b/libxfs/init.c
index 8d747e8..da3485b 100644
--- a/libxfs/init.c
+++ b/libxfs/init.c
@@ -278,6 +278,8 @@ libxfs_init(libxfs_init_t *a)
 			a->ddev= libxfs_device_open(dname, a->dcreat, flags,
 						    a->setblksize);
 			a->dfd = libxfs_device_to_fd(a->ddev);
+			platform_findsizes(dname, a->dfd, &a->dsize,
+						&a->dbsize);
 		} else {
 			if (!check_open(dname, flags, &rawfile, &blockfile))
 				goto done;
@@ -297,6 +299,8 @@ libxfs_init(libxfs_init_t *a)
 			a->logdev = libxfs_device_open(logname,
 					a->lcreat, flags, a->setblksize);
 			a->logfd = libxfs_device_to_fd(a->logdev);
+			platform_findsizes(dname, a->logfd, &a->logBBsize,
+						&a->lbsize);
 		} else {
 			if (!check_open(logname, flags, &rawfile, &blockfile))
 				goto done;
@@ -316,6 +320,8 @@ libxfs_init(libxfs_init_t *a)
 			a->rtdev = libxfs_device_open(rtname,
 					a->rcreat, flags, a->setblksize);
 			a->rtfd = libxfs_device_to_fd(a->rtdev);
+			platform_findsizes(dname, a->rtfd, &a->rtsize,
+						&a->rtbsize);
 		} else {
 			if (!check_open(rtname, flags, &rawfile, &blockfile))
 				goto done;
diff --git a/libxfs/linux.c b/libxfs/linux.c
index f6ea1b2..c9f2baf 100644
--- a/libxfs/linux.c
+++ b/libxfs/linux.c
@@ -125,7 +125,16 @@ platform_set_blocksize(int fd, char *path, dev_t device, int blocksize, int fata
 void
 platform_flush_device(int fd, dev_t device)
 {
-	if (major(device) != RAMDISK_MAJOR)
+	struct stat64	st;
+	if (major(device) == RAMDISK_MAJOR)
+		return;
+
+	if (fstat64(fd, &st) < 0)
+		return;
+
+	if (S_ISREG(st.st_mode))
+		fsync(fd);
+	else
 		ioctl(fd, BLKFLSBUF, 0);
 }
 
diff --git a/mkfs/xfs_mkfs.c b/mkfs/xfs_mkfs.c
index b1043fb..be82ec5 100644
--- a/mkfs/xfs_mkfs.c
+++ b/mkfs/xfs_mkfs.c
@@ -787,7 +787,7 @@ calc_stripe_factors(
 #ifdef ENABLE_BLKID
 static int
 check_overwrite(
-	char		*device)
+	const char	*device)
 {
 	const char	*type;
 	blkid_probe	pr = NULL;
@@ -804,7 +804,7 @@ check_overwrite(
 	fd = open(device, O_RDONLY);
 	if (fd < 0)
 		goto out;
-	platform_findsizes(device, fd, &size, &bsz);
+	platform_findsizes((char *)device, fd, &size, &bsz);
 	close(fd);
 
 	/* nothing to overwrite on a 0-length device */
@@ -851,7 +851,6 @@ check_overwrite(
 			"according to blkid\n"), progname, device);
 	}
 	ret = 1;
-
 out:
 	if (pr)
 		blkid_free_probe(pr);
@@ -877,8 +876,12 @@ static void blkid_get_topology(
 	struct stat statbuf;
 
 	/* can't get topology info from a file */
-	if (!stat(device, &statbuf) && S_ISREG(statbuf.st_mode))
+	if (!stat(device, &statbuf) && S_ISREG(statbuf.st_mode)) {
+		fprintf(stderr,
+	_("%s: Warning: trying to probe topology of a file %s!\n"),
+			progname, device);
 		return;
+	}
 
 	pr = blkid_new_probe_from_filename(device);
 	if (!pr)
@@ -1016,6 +1019,79 @@ static void get_topology(
 }
 
 static void
+check_device_type(
+	const char	*name,
+	int		*isfile,
+	bool		no_size,
+	bool		no_name,
+	int		*create,
+	bool		force_overwrite,
+	const char	*optname)
+{
+	struct stat64 statbuf;
+
+	if (*isfile && (no_size || no_name)) {
+		fprintf(stderr,
+	_("if -%s file then -%s name and -%s size are required\n"),
+			optname, optname, optname);
+		usage();
+	}
+
+	if (name == NULL) {
+		usage();
+	}
+
+	if (stat64(name, &statbuf)) {
+		if (errno == ENOENT && *isfile) {
+			if (create)
+				*create = 1;
+			return;
+		}
+
+		fprintf(stderr,
+	_("Error accessing specified device %s: %s\n"),
+				name, strerror(errno));
+		usage();
+		return;
+	}
+
+	if (!force_overwrite && check_overwrite(name)) {
+		fprintf(stderr,
+	_("%s: Use the -f option to force overwrite.\n"),
+			progname);
+		exit(1);
+	}
+
+	/*
+	 * We only want to completely truncate and recreate an existing file if
+	 * we were specifically told it was a file. Set the create flag only in
+	 * this case to trigger that behaviour.
+	 */
+	if (S_ISREG(statbuf.st_mode)) {
+		if (!*isfile)
+			*isfile = 1;
+		else if (create)
+			*create = 1;
+		return;
+	}
+
+	if (S_ISBLK(statbuf.st_mode)) {
+		if (*isfile) {
+			fprintf(stderr,
+	_("specified \"-%s file\" on a block device %s\n"),
+				optname, name);
+			usage();
+		}
+		return;
+	}
+
+	fprintf(stderr,
+	_("specified device %s not a file or block device\n"),
+		name);
+	usage();
+}
+
+static void
 fixup_log_stripe_unit(
 	int		lsflag,
 	int		sunit,
@@ -1280,7 +1356,6 @@ zero_old_xfs_structures(
 	__uint32_t		bsize;
 	int			i;
 	xfs_off_t		off;
-	int			tmp;
 
 	/*
 	 * We open regular files with O_TRUNC|O_CREAT. Nothing to do here...
@@ -1300,15 +1375,18 @@ zero_old_xfs_structures(
 	}
 	memset(buf, 0, new_sb->sb_sectsize);
 
-	tmp = pread(xi->dfd, buf, new_sb->sb_sectsize, 0);
-	if (tmp < 0) {
-		fprintf(stderr, _("existing superblock read failed: %s\n"),
-			strerror(errno));
-		goto done;
-	}
-	if (tmp != new_sb->sb_sectsize) {
-		fprintf(stderr,
-	_("warning: could not read existing superblock, skip zeroing\n"));
+	/*
+	 * If we are creating an image file, it might be of zero length at this
+	 * point in time. Hence reading the existing superblock is going to
+	 * return zero bytes. It's not a failure we need to warn about in this
+	 * case.
+	 */
+	off = pread(xi->dfd, buf, new_sb->sb_sectsize, 0);
+	if (off != new_sb->sb_sectsize) {
+		if (!xi->disfile)
+			fprintf(stderr,
+	_("error reading existing superblock: %s\n"),
+				strerror(errno));
 		goto done;
 	}
 	libxfs_sb_from_disk(&sb, buf);
@@ -1786,8 +1864,6 @@ main(
 				case D_FILE:
 					xi.disfile = getnum(value, &dopts,
 							    D_FILE);
-					if (xi.disfile && !Nflag)
-						xi.dcreat = 1;
 					break;
 				case D_NAME:
 					xi.dname = getstr(value, &dopts, D_NAME);
@@ -1913,11 +1989,6 @@ main(
 				case L_FILE:
 					xi.lisfile = getnum(value, &lopts,
 							    L_FILE);
-					if (xi.lisfile && loginternal)
-						conflict('l', subopts, L_INTERNAL,
-							 L_FILE);
-					if (xi.lisfile)
-						xi.lcreat = 1;
 					break;
 				case L_INTERNAL:
 					loginternal = getnum(value, &lopts,
@@ -2075,8 +2146,6 @@ main(
 				case R_FILE:
 					xi.risfile = getnum(value, &ropts,
 							    R_FILE);
-					if (xi.risfile)
-						xi.rcreat = 1;
 					break;
 				case R_NAME:
 				case R_DEV:
@@ -2181,6 +2250,26 @@ _("Minimum block size for CRC enabled filesystems is %d bytes.\n"),
 		lsectorsize = sectorsize;
 	}
 
+	/*
+	 * Before anything else, verify that we are correctly operating on
+	 * files or block devices and set the control parameters correctly.
+	 * Explicitly disable direct IO for image files so we don't error out on
+	 * sector size mismatches between the new filesystem and the underlying
+	 * host filesystem.
+	 */
+	check_device_type(dfile, &xi.disfile, !dsize, !dfile,
+			  Nflag ? NULL : &xi.dcreat, force_overwrite, "d");
+	if (!loginternal)
+		check_device_type(xi.logname, &xi.lisfile, !logsize, !xi.logname,
+				  Nflag ? NULL : &xi.lcreat,
+				  force_overwrite, "l");
+	if (xi.rtname)
+		check_device_type(xi.rtname, &xi.risfile, !rtsize, !xi.rtname,
+				  Nflag ? NULL : &xi.rcreat,
+				  force_overwrite, "r");
+	if (xi.disfile || xi.lisfile || xi.risfile)
+		xi.isdirect = 0;
+
 	memset(&ft, 0, sizeof(ft));
 	get_topology(&xi, &ft, force_overwrite);
 
@@ -2331,11 +2420,6 @@ _("warning: sparse inodes not supported without CRC support, disabled.\n"));
 	}
 
 
-	if (xi.disfile && (!dsize || !xi.dname)) {
-		fprintf(stderr,
-	_("if -d file then -d name and -d size are required\n"));
-		usage();
-	}
 	if (dsize) {
 		__uint64_t dbytes;
 
@@ -2368,11 +2452,6 @@ _("warning: sparse inodes not supported without CRC support, disabled.\n"));
 		usage();
 	}
 
-	if (xi.lisfile && (!logsize || !xi.logname)) {
-		fprintf(stderr,
-		_("if -l file then -l name and -l size are required\n"));
-		usage();
-	}
 	if (logsize) {
 		__uint64_t logbytes;
 
@@ -2390,11 +2469,6 @@ _("warning: sparse inodes not supported without CRC support, disabled.\n"));
 				(long long)logbytes, blocksize,
 				(long long)(logblocks << blocklog));
 	}
-	if (xi.risfile && (!rtsize || !xi.rtname)) {
-		fprintf(stderr,
-		_("if -r file then -r name and -r size are required\n"));
-		usage();
-	}
 	if (rtsize) {
 		__uint64_t rtbytes;
 
@@ -2516,22 +2590,14 @@ _("warning: sparse inodes not supported without CRC support, disabled.\n"));
 	xi.rtsize &= sector_mask;
 	xi.logBBsize &= (__uint64_t)-1 << (MAX(lsectorlog, 10) - BBSHIFT);
 
-	if (!force_overwrite) {
-		if (check_overwrite(dfile) ||
-		    check_overwrite(logfile) ||
-		    check_overwrite(xi.rtname)) {
-			fprintf(stderr,
-			_("%s: Use the -f option to force overwrite.\n"),
-				progname);
-			exit(1);
-		}
-	}
 
+	/* don't do discards on print-only runs or on files */
 	if (discard && !Nflag) {
-		discard_blocks(xi.ddev, xi.dsize);
-		if (xi.rtdev)
+		if (!xi.disfile)
+			discard_blocks(xi.ddev, xi.dsize);
+		if (xi.rtdev && !xi.risfile)
 			discard_blocks(xi.rtdev, xi.rtsize);
-		if (xi.logdev && xi.logdev != xi.ddev)
+		if (xi.logdev && xi.logdev != xi.ddev && !xi.lisfile)
 			discard_blocks(xi.logdev, xi.logBBsize);
 	}
 
-- 
2.5.0

_______________________________________________
xfs mailing list
xfs@oss.sgi.com
http://oss.sgi.com/mailman/listinfo/xfs

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

* [PATCH 16/19] mkfs: move spinodes crc check
  2016-04-21  9:39 [PATCH 00/19 v2] mkfs cleaning Jan Tulak
                   ` (14 preceding siblings ...)
  2016-04-21  9:39 ` [PATCH 15/19] mkfs: don't treat files as though they are block devices Jan Tulak
@ 2016-04-21  9:39 ` Jan Tulak
  2016-04-21  9:39 ` [PATCH 17/19] mkfs: unit conversions are case insensitive Jan Tulak
                   ` (5 subsequent siblings)
  21 siblings, 0 replies; 51+ messages in thread
From: Jan Tulak @ 2016-04-21  9:39 UTC (permalink / raw)
  To: xfs

Spinodes crc check is now moved to be in the same way as finobt.

Signed-off-by: Jan Tulak <jtulak@redhat.com>
Reviewed-by: Brian Foster <bfoster@redhat.com>
---
 mkfs/xfs_mkfs.c | 11 ++++++-----
 1 file changed, 6 insertions(+), 5 deletions(-)

diff --git a/mkfs/xfs_mkfs.c b/mkfs/xfs_mkfs.c
index be82ec5..a6334bc 100644
--- a/mkfs/xfs_mkfs.c
+++ b/mkfs/xfs_mkfs.c
@@ -2389,19 +2389,20 @@ _("32 bit Project IDs always enabled on CRC enabled filesytems\n"));
 		 * explicitly turned them off then silently turn them off
 		 * to avoid an unnecessary warning. If the user explicitly
 		 * tried to use crc=0,finobt=1, then issue a warning before
-		 * turning them off.
+		 * turning them off. The same is also for sparse inodes.
 		 */
 		if (sb_feat.finobt && mopts.subopt_params[M_FINOBT].seen) {
 			fprintf(stderr,
 _("warning: finobt not supported without CRC support, disabled.\n"));
 		}
 		sb_feat.finobt = 0;
-	}
 
-	if (sb_feat.spinodes && !sb_feat.crcs_enabled) {
-		fprintf(stderr,
-_("warning: sparse inodes not supported without CRC support, disabled.\n"));
+		if (sb_feat.spinodes) {
+			fprintf(stderr,
+	_("warning: sparse inodes not supported without CRC support, disabled.\n"));
+		}
 		sb_feat.spinodes = 0;
+
 	}
 
 	if (nsflag || nlflag) {
-- 
2.5.0

_______________________________________________
xfs mailing list
xfs@oss.sgi.com
http://oss.sgi.com/mailman/listinfo/xfs

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

* [PATCH 17/19] mkfs: unit conversions are case insensitive
  2016-04-21  9:39 [PATCH 00/19 v2] mkfs cleaning Jan Tulak
                   ` (15 preceding siblings ...)
  2016-04-21  9:39 ` [PATCH 16/19] mkfs: move spinodes crc check Jan Tulak
@ 2016-04-21  9:39 ` Jan Tulak
  2016-04-21  9:39 ` [PATCH 18/19] mkfs: add optional 'reason' for illegal_option Jan Tulak
                   ` (4 subsequent siblings)
  21 siblings, 0 replies; 51+ messages in thread
From: Jan Tulak @ 2016-04-21  9:39 UTC (permalink / raw)
  To: xfs

Solves the question "Should I use 10g or 10G?"

Signed-off-by: Jan Tulak <jtulak@redhat.com>

---
CHANGES:
* use tolower instead of == 'p' || == 'P'
---
 mkfs/xfs_mkfs.c | 14 ++++++++------
 1 file changed, 8 insertions(+), 6 deletions(-)

diff --git a/mkfs/xfs_mkfs.c b/mkfs/xfs_mkfs.c
index a6334bc..a35c4a5 100644
--- a/mkfs/xfs_mkfs.c
+++ b/mkfs/xfs_mkfs.c
@@ -3594,8 +3594,10 @@ cvtnum(
 {
 	long long	i;
 	char		*sp;
+	int		c;
 
 	i = strtoll(s, &sp, 0);
+	c = tolower(*sp);
 	if (i == 0 && sp == s)
 		return -1LL;
 	if (*sp == '\0')
@@ -3606,17 +3608,17 @@ cvtnum(
 	if (*sp == 's' && sp[1] == '\0')
 		return i * sectsize;
 
-	if (*sp == 'k' && sp[1] == '\0')
+	if (c == 'k' && sp[1] == '\0')
 		return 1024LL * i;
-	if (*sp == 'm' && sp[1] == '\0')
+	if (c == 'm' && sp[1] == '\0')
 		return 1024LL * 1024LL * i;
-	if (*sp == 'g' && sp[1] == '\0')
+	if (c == 'g' && sp[1] == '\0')
 		return 1024LL * 1024LL * 1024LL * i;
-	if (*sp == 't' && sp[1] == '\0')
+	if (c == 't' && sp[1] == '\0')
 		return 1024LL * 1024LL * 1024LL * 1024LL * i;
-	if (*sp == 'p' && sp[1] == '\0')
+	if (c == 'p' && sp[1] == '\0')
 		return 1024LL * 1024LL * 1024LL * 1024LL * 1024LL * i;
-	if (*sp == 'e' && sp[1] == '\0')
+	if (c == 'e' && sp[1] == '\0')
 		return 1024LL * 1024LL * 1024LL * 1024LL * 1024LL * 1024LL * i;
 	return -1LL;
 }
-- 
2.5.0

_______________________________________________
xfs mailing list
xfs@oss.sgi.com
http://oss.sgi.com/mailman/listinfo/xfs

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

* [PATCH 18/19] mkfs: add optional 'reason' for illegal_option
  2016-04-21  9:39 [PATCH 00/19 v2] mkfs cleaning Jan Tulak
                   ` (16 preceding siblings ...)
  2016-04-21  9:39 ` [PATCH 17/19] mkfs: unit conversions are case insensitive Jan Tulak
@ 2016-04-21  9:39 ` Jan Tulak
  2016-04-21  9:39 ` [PATCH 19/19] mkfs: conflicting values with disabled crc should fail Jan Tulak
                   ` (3 subsequent siblings)
  21 siblings, 0 replies; 51+ messages in thread
From: Jan Tulak @ 2016-04-21  9:39 UTC (permalink / raw)
  To: xfs

Allow us to tell the user what exactly is wrong with the specified options.
For example, that the value is too small, instead of just generic "bad option."

Signed-off-by: Jan Tulak <jtulak@redhat.com>

---
CHANGES:
* code format (space)
* add translation _() to strings
---
 mkfs/xfs_mkfs.c | 27 ++++++++++++++++++---------
 1 file changed, 18 insertions(+), 9 deletions(-)

diff --git a/mkfs/xfs_mkfs.c b/mkfs/xfs_mkfs.c
index a35c4a5..c4cd5ba 100644
--- a/mkfs/xfs_mkfs.c
+++ b/mkfs/xfs_mkfs.c
@@ -1546,11 +1546,18 @@ static __attribute__((noreturn)) void
 illegal_option(
 	const char	*value,
 	struct opt_params	*opts,
-	int		index)
+	int		index,
+	const char *reason)
 {
-	fprintf(stderr,
-		_("Illegal value %s for -%c %s option\n"),
-		value, opts->name, opts->subopts[index]);
+	if (reason == NULL){
+		fprintf(stderr,
+			_("Illegal value %s for -%c %s option\n"),
+			value, opts->name, opts->subopts[index]);
+	} else {
+		fprintf(stderr,
+			_("Illegal value %s for -%c %s option: %s\n"),
+			value, opts->name, opts->subopts[index], reason);
+	}
 	usage();
 }
 
@@ -1642,16 +1649,18 @@ getnum(
 
 		c = strtoll(str, &str_end, 0);
 		if (c == 0 && str_end == str)
-			illegal_option(str, opts, index);
+			illegal_option(str, opts, index, NULL);
 		if (*str_end != '\0')
-			illegal_option(str, opts, index);
+			illegal_option(str, opts, index, NULL);
 	}
 
 	/* Validity check the result. */
-	if (c < sp->minval || c > sp->maxval)
-		illegal_option(str, opts, index);
+	if (c < sp->minval)
+		illegal_option(str, opts, index, _("value is too small"));
+	else if (c > sp->maxval)
+		illegal_option(str, opts, index, _("value is too large"));
 	if (sp->is_power_2 && !ispow2(c))
-		illegal_option(str, opts, index);
+		illegal_option(str, opts, index, _("value must be a power of 2"));
 	return c;
 }
 
-- 
2.5.0

_______________________________________________
xfs mailing list
xfs@oss.sgi.com
http://oss.sgi.com/mailman/listinfo/xfs

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

* [PATCH 19/19] mkfs: conflicting values with disabled crc should fail
  2016-04-21  9:39 [PATCH 00/19 v2] mkfs cleaning Jan Tulak
                   ` (17 preceding siblings ...)
  2016-04-21  9:39 ` [PATCH 18/19] mkfs: add optional 'reason' for illegal_option Jan Tulak
@ 2016-04-21  9:39 ` Jan Tulak
  2016-04-28  8:29   ` Jan Tulak
                   ` (2 subsequent siblings)
  21 siblings, 0 replies; 51+ messages in thread
From: Jan Tulak @ 2016-04-21  9:39 UTC (permalink / raw)
  To: xfs

If crc=0, then finobt=1 and spinodes=1 should both fail, instead of a warning.

Signed-off-by: Jan Tulak <jtulak@redhat.com>
---
 mkfs/xfs_mkfs.c | 17 ++++++++++-------
 1 file changed, 10 insertions(+), 7 deletions(-)

diff --git a/mkfs/xfs_mkfs.c b/mkfs/xfs_mkfs.c
index c4cd5ba..249e547 100644
--- a/mkfs/xfs_mkfs.c
+++ b/mkfs/xfs_mkfs.c
@@ -2394,21 +2394,24 @@ _("32 bit Project IDs always enabled on CRC enabled filesytems\n"));
 	} else {
 		/*
 		 * The kernel doesn't currently support crc=0,finobt=1
-		 * filesystems. If crcs are not enabled and the user has
-		 * explicitly turned them off then silently turn them off
-		 * to avoid an unnecessary warning. If the user explicitly
-		 * tried to use crc=0,finobt=1, then issue a warning before
-		 * turning them off. The same is also for sparse inodes.
+		 * filesystems. If crcs are not enabled and the user has not
+		 * explicitly turned finobt on, then silently turn it off to
+		 * avoid an unnecessary warning.
+		 * If the user explicitly tried to use crc=0,finobt=1,
+		 * then issue an error.
+		 * The same is also for sparse inodes.
 		 */
 		if (sb_feat.finobt && mopts.subopt_params[M_FINOBT].seen) {
 			fprintf(stderr,
-_("warning: finobt not supported without CRC support, disabled.\n"));
+_("finobt not supported without CRC support\n"));
+			usage();
 		}
 		sb_feat.finobt = 0;
 
 		if (sb_feat.spinodes) {
 			fprintf(stderr,
-	_("warning: sparse inodes not supported without CRC support, disabled.\n"));
+	_("sparse inodes not supported without CRC support\n"));
+			usage();
 		}
 		sb_feat.spinodes = 0;
 
-- 
2.5.0

_______________________________________________
xfs mailing list
xfs@oss.sgi.com
http://oss.sgi.com/mailman/listinfo/xfs

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

* Re: [PATCH 15/19] mkfs: don't treat files as though they are block devices
  2016-04-21  9:39 ` [PATCH 15/19] mkfs: don't treat files as though they are block devices Jan Tulak
@ 2016-04-21 12:43   ` Jan Tulak
  2016-04-21 20:13     ` Eric Sandeen
  2016-04-22  7:49   ` [PATCH 15/19 v2] " Jan Tulak
  2016-05-02 23:13   ` [PATCH 15/19] " Eric Sandeen
  2 siblings, 1 reply; 51+ messages in thread
From: Jan Tulak @ 2016-04-21 12:43 UTC (permalink / raw)
  To: xfs-oss


[-- Attachment #1.1: Type: text/plain, Size: 1150 bytes --]

On Thu, Apr 21, 2016 at 11:39 AM, Jan Tulak <jtulak@redhat.com> wrote:

> From: Dave Chinner <dchinner@redhat.com>
>
> THIS PATCH HAS KNOWN ISSUES - it fails xfs/206 and xfs/216 tests, as it
> shrinks a file instead just not using it entirely, when -d size is used.
>

​So the shrinking is happening here:
3127        /*
3128         * If the data area is a file, then grow it out to its final
size
3129         * so that the reads for the end of the device in the mount code
3130         * will succeed.
3131         */
3132        if (xi.disfile && ftruncate64(xi.dfd, dblocks * blocksize) < 0)
{​


Before the patch, xi.disfile was 0 and so it didn't shrink the file to the
size of the new FS.
Now, what is the correct solve to this? Tests are written for the old
behaviour, but this shrinking seems to be an intentional thing.
It seems that the FS works ok even when this truncating is not applied, so
I think that I should remove this chunk (or change it to xi.dcreate=1
only), and keep the old behaviour.

What do you think about it, guys?

Cheers,
Jan



-- 
Jan Tulak
jtulak@redhat.com / jan@tulak.me

[-- Attachment #1.2: Type: text/html, Size: 3210 bytes --]

[-- Attachment #2: Type: text/plain, Size: 121 bytes --]

_______________________________________________
xfs mailing list
xfs@oss.sgi.com
http://oss.sgi.com/mailman/listinfo/xfs

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

* Re: [PATCH 15/19] mkfs: don't treat files as though they are block devices
  2016-04-21 12:43   ` Jan Tulak
@ 2016-04-21 20:13     ` Eric Sandeen
  2016-04-22  7:46       ` Jan Tulak
  0 siblings, 1 reply; 51+ messages in thread
From: Eric Sandeen @ 2016-04-21 20:13 UTC (permalink / raw)
  To: xfs



On 4/21/16 8:43 AM, Jan Tulak wrote:
> On Thu, Apr 21, 2016 at 11:39 AM, Jan Tulak <jtulak@redhat.com <mailto:jtulak@redhat.com>>wrote:
> 
>     From: Dave Chinner <dchinner@redhat.com <mailto:dchinner@redhat.com>>
> 
>     THIS PATCH HAS KNOWN ISSUES - it fails xfs/206 and xfs/216 tests, as it
>     shrinks a file instead just not using it entirely, when -d size is used.
> 
> 
> ​So the shrinking is happening here:
> 3127        /*
> 3128         * If the data area is a file, then grow it out to its final size
> 3129         * so that the reads for the end of the device in the mount code
> 3130         * will succeed.
> 3131         */
> 3132        if (xi.disfile && ftruncate64(xi.dfd, dblocks * blocksize) < 0) {​
>  
> 
> Before the patch, xi.disfile was 0 and so it didn't shrink the file
> to the size of the new FS. Now, what is the correct solve to this?
> Tests are written for the old behaviour, but this shrinking seems to
> be an intentional thing. It seems that the FS works ok even when this
> truncating is not applied, so I think that I should remove this chunk
> (or change it to xi.dcreate=1 only), and keep the old behaviour.
> 
> What do you think about it, guys?

Can't remove it; that would break the other side of things, if you try
to mkfs.xfs -d size=2g on an existing 1g file... mount tries to do
IO to the last block, and if it's not truncated out, that will fail
(as the comment says).

I suppose the simple way to fix it is to only truncate up, never down.

i.e. truncate to max(dblocks * blocksize, st_size) or
if (xi.disfile && st_size <  dblocks * blocksize) { truncate ... }

-Eric



> Cheers,
> Jan
> 
> 
> 
> -- 
> Jan Tulak
> jtulak@redhat.com <mailto:jtulak@redhat.com> / jan@tulak.me <mailto:jan@tulak.me>
> 
> 
> _______________________________________________
> xfs mailing list
> xfs@oss.sgi.com
> http://oss.sgi.com/mailman/listinfo/xfs
> 

_______________________________________________
xfs mailing list
xfs@oss.sgi.com
http://oss.sgi.com/mailman/listinfo/xfs

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

* Re: [PATCH 15/19] mkfs: don't treat files as though they are block devices
  2016-04-21 20:13     ` Eric Sandeen
@ 2016-04-22  7:46       ` Jan Tulak
  0 siblings, 0 replies; 51+ messages in thread
From: Jan Tulak @ 2016-04-22  7:46 UTC (permalink / raw)
  To: Eric Sandeen; +Cc: xfs-oss


[-- Attachment #1.1: Type: text/plain, Size: 2086 bytes --]

On Thu, Apr 21, 2016 at 10:13 PM, Eric Sandeen <sandeen@sandeen.net> wrote:

>
>
> On 4/21/16 8:43 AM, Jan Tulak wrote:
> > On Thu, Apr 21, 2016 at 11:39 AM, Jan Tulak <jtulak@redhat.com <mailto:
> jtulak@redhat.com>>wrote:
> >
> >     From: Dave Chinner <dchinner@redhat.com <mailto:dchinner@redhat.com
> >>
> >
> >     THIS PATCH HAS KNOWN ISSUES - it fails xfs/206 and xfs/216 tests, as
> it
> >     shrinks a file instead just not using it entirely, when -d size is
> used.
> >
> >
> > ​So the shrinking is happening here:
> > 3127        /*
> > 3128         * If the data area is a file, then grow it out to its final
> size
> > 3129         * so that the reads for the end of the device in the mount
> code
> > 3130         * will succeed.
> > 3131         */
> > 3132        if (xi.disfile && ftruncate64(xi.dfd, dblocks * blocksize) <
> 0) {​
> >
> >
> > Before the patch, xi.disfile was 0 and so it didn't shrink the file
> > to the size of the new FS. Now, what is the correct solve to this?
> > Tests are written for the old behaviour, but this shrinking seems to
> > be an intentional thing. It seems that the FS works ok even when this
> > truncating is not applied, so I think that I should remove this chunk
> > (or change it to xi.dcreate=1 only), and keep the old behaviour.
> >
> > What do you think about it, guys?
>
> Can't remove it; that would break the other side of things, if you try
> to mkfs.xfs -d size=2g on an existing 1g file... mount tries to do
> IO to the last block, and if it's not truncated out, that will fail
> (as the comment says).
>
> I suppose the simple way to fix it is to only truncate up, never down.
>
> i.e. truncate to max(dblocks * blocksize, st_size) or
> if (xi.disfile && st_size <  dblocks * blocksize) { truncate ... }
>

All right, it seems that I should have read the man page, and not just
 look on the first sentence or two... <emoticon of me hitting a wall with
my head repeatedly>.

Now it works, thanks.

Jan


-- 
Jan Tulak
jtulak@redhat.com / jan@tulak.me

[-- Attachment #1.2: Type: text/html, Size: 3646 bytes --]

[-- Attachment #2: Type: text/plain, Size: 121 bytes --]

_______________________________________________
xfs mailing list
xfs@oss.sgi.com
http://oss.sgi.com/mailman/listinfo/xfs

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

* [PATCH 15/19 v2] mkfs: don't treat files as though they are block devices
  2016-04-21  9:39 ` [PATCH 15/19] mkfs: don't treat files as though they are block devices Jan Tulak
  2016-04-21 12:43   ` Jan Tulak
@ 2016-04-22  7:49   ` Jan Tulak
  2016-04-29 14:47     ` [PATCH 15/19 v3] " Jan Tulak
  2016-05-02 23:13   ` [PATCH 15/19] " Eric Sandeen
  2 siblings, 1 reply; 51+ messages in thread
From: Jan Tulak @ 2016-04-22  7:49 UTC (permalink / raw)
  To: xfs

From: Dave Chinner <dchinner@redhat.com>

If the device is actually a file, and "-d file" is not specified,
mkfs will try to treat it as a block device and get stuff wrong.
Image files don't necessarily have the same sector sizes as the
block device or filesystem underlying the image file, nor should we
be issuing discard ioctls on image files.

To fix this sanely, only require "-d file" if the device name is
invalid to trigger creation of the file. Otherwise, use stat() to
determine if the device is a file or block device and deal with that
appropriately by setting the "isfile" variables and turning off
direct IO. Then ensure that we check the "isfile" options before
doing things that are specific to block devices.

Other file/blockdev issues fixed:
	- use getstr to detect specifying the data device name
	  twice.
	- check file/size/name parameters before anything else.
	- overwrite checks need to be done before the image file is
	  opened and potentially truncated.
	- blkid_get_topology() should not be called for image files,
	  so warn when it is called that way.
	- zero_old_xfs_structures() emits a spurious error:
		"existing superblock read failed: Success"
	  when it is run on a truncated image file. Don't warn if we
	  see this problem on an image file.
	- Don't issue discards on image files.
	- Use fsync() for image files, not BLKFLSBUF in
	  platform_flush_device() for Linux.

Signed-off-by: Dave Chinner <dchinner@redhat.com>
Signed-off-by: Jan Tulak <jtulak@redhat.com>

---
CHANGES:
* call ftruncate64() only when the existing file needs to be enlarged

---
 libxfs/init.c   |   6 ++
 libxfs/linux.c  |  11 +++-
 mkfs/xfs_mkfs.c | 178 +++++++++++++++++++++++++++++++++++++++-----------------
 3 files changed, 139 insertions(+), 56 deletions(-)

diff --git a/libxfs/init.c b/libxfs/init.c
index 8d747e8..da3485b 100644
--- a/libxfs/init.c
+++ b/libxfs/init.c
@@ -278,6 +278,8 @@ libxfs_init(libxfs_init_t *a)
 			a->ddev= libxfs_device_open(dname, a->dcreat, flags,
 						    a->setblksize);
 			a->dfd = libxfs_device_to_fd(a->ddev);
+			platform_findsizes(dname, a->dfd, &a->dsize,
+						&a->dbsize);
 		} else {
 			if (!check_open(dname, flags, &rawfile, &blockfile))
 				goto done;
@@ -297,6 +299,8 @@ libxfs_init(libxfs_init_t *a)
 			a->logdev = libxfs_device_open(logname,
 					a->lcreat, flags, a->setblksize);
 			a->logfd = libxfs_device_to_fd(a->logdev);
+			platform_findsizes(dname, a->logfd, &a->logBBsize,
+						&a->lbsize);
 		} else {
 			if (!check_open(logname, flags, &rawfile, &blockfile))
 				goto done;
@@ -316,6 +320,8 @@ libxfs_init(libxfs_init_t *a)
 			a->rtdev = libxfs_device_open(rtname,
 					a->rcreat, flags, a->setblksize);
 			a->rtfd = libxfs_device_to_fd(a->rtdev);
+			platform_findsizes(dname, a->rtfd, &a->rtsize,
+						&a->rtbsize);
 		} else {
 			if (!check_open(rtname, flags, &rawfile, &blockfile))
 				goto done;
diff --git a/libxfs/linux.c b/libxfs/linux.c
index f6ea1b2..c9f2baf 100644
--- a/libxfs/linux.c
+++ b/libxfs/linux.c
@@ -125,7 +125,16 @@ platform_set_blocksize(int fd, char *path, dev_t device, int blocksize, int fata
 void
 platform_flush_device(int fd, dev_t device)
 {
-	if (major(device) != RAMDISK_MAJOR)
+	struct stat64	st;
+	if (major(device) == RAMDISK_MAJOR)
+		return;
+
+	if (fstat64(fd, &st) < 0)
+		return;
+
+	if (S_ISREG(st.st_mode))
+		fsync(fd);
+	else
 		ioctl(fd, BLKFLSBUF, 0);
 }
 
diff --git a/mkfs/xfs_mkfs.c b/mkfs/xfs_mkfs.c
index b1043fb..20b5eb1 100644
--- a/mkfs/xfs_mkfs.c
+++ b/mkfs/xfs_mkfs.c
@@ -787,7 +787,7 @@ calc_stripe_factors(
 #ifdef ENABLE_BLKID
 static int
 check_overwrite(
-	char		*device)
+	const char	*device)
 {
 	const char	*type;
 	blkid_probe	pr = NULL;
@@ -804,7 +804,7 @@ check_overwrite(
 	fd = open(device, O_RDONLY);
 	if (fd < 0)
 		goto out;
-	platform_findsizes(device, fd, &size, &bsz);
+	platform_findsizes((char *)device, fd, &size, &bsz);
 	close(fd);
 
 	/* nothing to overwrite on a 0-length device */
@@ -851,7 +851,6 @@ check_overwrite(
 			"according to blkid\n"), progname, device);
 	}
 	ret = 1;
-
 out:
 	if (pr)
 		blkid_free_probe(pr);
@@ -877,8 +876,12 @@ static void blkid_get_topology(
 	struct stat statbuf;
 
 	/* can't get topology info from a file */
-	if (!stat(device, &statbuf) && S_ISREG(statbuf.st_mode))
+	if (!stat(device, &statbuf) && S_ISREG(statbuf.st_mode)) {
+		fprintf(stderr,
+	_("%s: Warning: trying to probe topology of a file %s!\n"),
+			progname, device);
 		return;
+	}
 
 	pr = blkid_new_probe_from_filename(device);
 	if (!pr)
@@ -1016,6 +1019,79 @@ static void get_topology(
 }
 
 static void
+check_device_type(
+	const char	*name,
+	int		*isfile,
+	bool		no_size,
+	bool		no_name,
+	int		*create,
+	bool		force_overwrite,
+	const char	*optname)
+{
+	struct stat64 statbuf;
+
+	if (*isfile && (no_size || no_name)) {
+		fprintf(stderr,
+	_("if -%s file then -%s name and -%s size are required\n"),
+			optname, optname, optname);
+		usage();
+	}
+
+	if (name == NULL) {
+		usage();
+	}
+
+	if (stat64(name, &statbuf)) {
+		if (errno == ENOENT && *isfile) {
+			if (create)
+				*create = 1;
+			return;
+		}
+
+		fprintf(stderr,
+	_("Error accessing specified device %s: %s\n"),
+				name, strerror(errno));
+		usage();
+		return;
+	}
+
+	if (!force_overwrite && check_overwrite(name)) {
+		fprintf(stderr,
+	_("%s: Use the -f option to force overwrite.\n"),
+			progname);
+		exit(1);
+	}
+
+	/*
+	 * We only want to completely truncate and recreate an existing file if
+	 * we were specifically told it was a file. Set the create flag only in
+	 * this case to trigger that behaviour.
+	 */
+	if (S_ISREG(statbuf.st_mode)) {
+		if (!*isfile)
+			*isfile = 1;
+		else if (create)
+			*create = 1;
+		return;
+	}
+
+	if (S_ISBLK(statbuf.st_mode)) {
+		if (*isfile) {
+			fprintf(stderr,
+	_("specified \"-%s file\" on a block device %s\n"),
+				optname, name);
+			usage();
+		}
+		return;
+	}
+
+	fprintf(stderr,
+	_("specified device %s not a file or block device\n"),
+		name);
+	usage();
+}
+
+static void
 fixup_log_stripe_unit(
 	int		lsflag,
 	int		sunit,
@@ -1280,7 +1356,6 @@ zero_old_xfs_structures(
 	__uint32_t		bsize;
 	int			i;
 	xfs_off_t		off;
-	int			tmp;
 
 	/*
 	 * We open regular files with O_TRUNC|O_CREAT. Nothing to do here...
@@ -1300,15 +1375,18 @@ zero_old_xfs_structures(
 	}
 	memset(buf, 0, new_sb->sb_sectsize);
 
-	tmp = pread(xi->dfd, buf, new_sb->sb_sectsize, 0);
-	if (tmp < 0) {
-		fprintf(stderr, _("existing superblock read failed: %s\n"),
-			strerror(errno));
-		goto done;
-	}
-	if (tmp != new_sb->sb_sectsize) {
-		fprintf(stderr,
-	_("warning: could not read existing superblock, skip zeroing\n"));
+	/*
+	 * If we are creating an image file, it might be of zero length at this
+	 * point in time. Hence reading the existing superblock is going to
+	 * return zero bytes. It's not a failure we need to warn about in this
+	 * case.
+	 */
+	off = pread(xi->dfd, buf, new_sb->sb_sectsize, 0);
+	if (off != new_sb->sb_sectsize) {
+		if (!xi->disfile)
+			fprintf(stderr,
+	_("error reading existing superblock: %s\n"),
+				strerror(errno));
 		goto done;
 	}
 	libxfs_sb_from_disk(&sb, buf);
@@ -1786,8 +1864,6 @@ main(
 				case D_FILE:
 					xi.disfile = getnum(value, &dopts,
 							    D_FILE);
-					if (xi.disfile && !Nflag)
-						xi.dcreat = 1;
 					break;
 				case D_NAME:
 					xi.dname = getstr(value, &dopts, D_NAME);
@@ -1913,11 +1989,6 @@ main(
 				case L_FILE:
 					xi.lisfile = getnum(value, &lopts,
 							    L_FILE);
-					if (xi.lisfile && loginternal)
-						conflict('l', subopts, L_INTERNAL,
-							 L_FILE);
-					if (xi.lisfile)
-						xi.lcreat = 1;
 					break;
 				case L_INTERNAL:
 					loginternal = getnum(value, &lopts,
@@ -2075,8 +2146,6 @@ main(
 				case R_FILE:
 					xi.risfile = getnum(value, &ropts,
 							    R_FILE);
-					if (xi.risfile)
-						xi.rcreat = 1;
 					break;
 				case R_NAME:
 				case R_DEV:
@@ -2181,6 +2250,26 @@ _("Minimum block size for CRC enabled filesystems is %d bytes.\n"),
 		lsectorsize = sectorsize;
 	}
 
+	/*
+	 * Before anything else, verify that we are correctly operating on
+	 * files or block devices and set the control parameters correctly.
+	 * Explicitly disable direct IO for image files so we don't error out on
+	 * sector size mismatches between the new filesystem and the underlying
+	 * host filesystem.
+	 */
+	check_device_type(dfile, &xi.disfile, !dsize, !dfile,
+			  Nflag ? NULL : &xi.dcreat, force_overwrite, "d");
+	if (!loginternal)
+		check_device_type(xi.logname, &xi.lisfile, !logsize, !xi.logname,
+				  Nflag ? NULL : &xi.lcreat,
+				  force_overwrite, "l");
+	if (xi.rtname)
+		check_device_type(xi.rtname, &xi.risfile, !rtsize, !xi.rtname,
+				  Nflag ? NULL : &xi.rcreat,
+				  force_overwrite, "r");
+	if (xi.disfile || xi.lisfile || xi.risfile)
+		xi.isdirect = 0;
+
 	memset(&ft, 0, sizeof(ft));
 	get_topology(&xi, &ft, force_overwrite);
 
@@ -2331,11 +2420,6 @@ _("warning: sparse inodes not supported without CRC support, disabled.\n"));
 	}
 
 
-	if (xi.disfile && (!dsize || !xi.dname)) {
-		fprintf(stderr,
-	_("if -d file then -d name and -d size are required\n"));
-		usage();
-	}
 	if (dsize) {
 		__uint64_t dbytes;
 
@@ -2368,11 +2452,6 @@ _("warning: sparse inodes not supported without CRC support, disabled.\n"));
 		usage();
 	}
 
-	if (xi.lisfile && (!logsize || !xi.logname)) {
-		fprintf(stderr,
-		_("if -l file then -l name and -l size are required\n"));
-		usage();
-	}
 	if (logsize) {
 		__uint64_t logbytes;
 
@@ -2390,11 +2469,6 @@ _("warning: sparse inodes not supported without CRC support, disabled.\n"));
 				(long long)logbytes, blocksize,
 				(long long)(logblocks << blocklog));
 	}
-	if (xi.risfile && (!rtsize || !xi.rtname)) {
-		fprintf(stderr,
-		_("if -r file then -r name and -r size are required\n"));
-		usage();
-	}
 	if (rtsize) {
 		__uint64_t rtbytes;
 
@@ -2516,22 +2590,14 @@ _("warning: sparse inodes not supported without CRC support, disabled.\n"));
 	xi.rtsize &= sector_mask;
 	xi.logBBsize &= (__uint64_t)-1 << (MAX(lsectorlog, 10) - BBSHIFT);
 
-	if (!force_overwrite) {
-		if (check_overwrite(dfile) ||
-		    check_overwrite(logfile) ||
-		    check_overwrite(xi.rtname)) {
-			fprintf(stderr,
-			_("%s: Use the -f option to force overwrite.\n"),
-				progname);
-			exit(1);
-		}
-	}
 
+	/* don't do discards on print-only runs or on files */
 	if (discard && !Nflag) {
-		discard_blocks(xi.ddev, xi.dsize);
-		if (xi.rtdev)
+		if (!xi.disfile)
+			discard_blocks(xi.ddev, xi.dsize);
+		if (xi.rtdev && !xi.risfile)
 			discard_blocks(xi.rtdev, xi.rtsize);
-		if (xi.logdev && xi.logdev != xi.ddev)
+		if (xi.logdev && xi.logdev != xi.ddev && !xi.lisfile)
 			discard_blocks(xi.logdev, xi.logBBsize);
 	}
 
@@ -3063,10 +3129,12 @@ _("size %s specified for log subvolume is too large, maximum is %lld blocks\n"),
 	 * so that the reads for the end of the device in the mount code
 	 * will succeed.
 	 */
-	if (xi.disfile && ftruncate64(xi.dfd, dblocks * blocksize) < 0) {
-		fprintf(stderr, _("%s: Growing the data section failed\n"),
-			progname);
-		exit(1);
+	if (xi.disfile && xi.dsize*xi.dbsize <  dblocks * blocksize) {
+		if (ftruncate64(xi.dfd, dblocks * blocksize) < 0) {
+			fprintf(stderr, _("%s: Growing the data section failed\n"),
+				progname);
+			exit(1);
+		}
 	}
 
 	/*
-- 
2.5.0

_______________________________________________
xfs mailing list
xfs@oss.sgi.com
http://oss.sgi.com/mailman/listinfo/xfs

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

* [RFC PATCH] xfstests: Add mkfs input validation tests
  2016-04-21  9:39 [PATCH 00/19 v2] mkfs cleaning Jan Tulak
@ 2016-04-28  8:29   ` Jan Tulak
  2016-04-21  9:39 ` [PATCH 02/19] mkfs: sanitise ftype parameter values Jan Tulak
                     ` (20 subsequent siblings)
  21 siblings, 0 replies; 51+ messages in thread
From: Jan Tulak @ 2016-04-28  8:29 UTC (permalink / raw)
  To: fstests; +Cc: xfs

Test inputs for my mkfs-cleaning patchset. This test will fail with the old sphageti code mkfs, among others because the old code accepts incorrect values.



Signed-off-by: Dave Chinner <dchinner@redhat.com>
Signed-off-by: Jan Tulak <jtulak@redhat.com>
---

Hi guys,

I'm sending this patch although the mentioned patchset is not yet merged.
It might help you a bit with checking if there are any issues with
the patchset, as here it is clear, what options works and what not.

But because this test fails with how mkfs currently validates values
(and some other things), maybe the merging of this patch should wait
for the patchset.

Cheers,
Jan

 tests/xfs/400-input-validation     | 226 +++++++++++++++++++++++++++++++++++++
 tests/xfs/400-input-validation.out |   2 +
 tests/xfs/group                    |   1 +
 3 files changed, 229 insertions(+)
 create mode 100755 tests/xfs/400-input-validation
 create mode 100644 tests/xfs/400-input-validation.out

diff --git a/tests/xfs/400-input-validation b/tests/xfs/400-input-validation
new file mode 100755
index 0000000..4ded2ef
--- /dev/null
+++ b/tests/xfs/400-input-validation
@@ -0,0 +1,226 @@
+#! /bin/bash
+# FS QA Test No. xfs/401
+#
+# mkfs.xfs input validation test. Designed to break mkfs.xfs if it doesn't
+# filter garbage input or invalid option combinations correctly.
+#
+#-----------------------------------------------------------------------
+# Copyright (c) 2014 Red Hat, Inc.  All Rights Reserved.
+#
+# This program is free software; you can redistribute it and/or
+# modify it under the terms of the GNU General Public License as
+# published by the Free Software Foundation.
+#
+# This program is distributed in the hope that it would be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write the Free Software Foundation,
+# Inc.,  51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+#-----------------------------------------------------------------------
+#
+
+seq=`basename $0`
+seqres=$RESULT_DIR/$seq
+echo "QA output created by $seq"
+
+here=`pwd`
+tmp=/tmp/$$
+status=1        # failure is the default!
+trap "_cleanup; exit \$status" 0 1 2 3 15
+
+_cleanup()
+{
+    cd /
+    rm -f $tmp.*
+}
+
+# get standard environment, filters and checks
+. ./common/rc
+. ./common/filter
+
+# real QA test starts here
+
+# Modify as appropriate.
+_supported_fs xfs
+_supported_os Linux
+_require_scratch
+
+echo silence is golden
+
+# clear out any options to mkfs first. We want to test realtime and external log
+# devices if we can, but we also want to control them ourselves.
+logdev=$SCRATCH_LOGDEV
+rtdev=$SCRATCH_RTDEV
+
+MKFS_OPTIONS=
+SCRATCH_LOGDEV=
+SCRATCH_RTDEV=
+
+# limit the image size of the filesystem being created to something small
+fssize=$((4 * 1024 * 1024 * 1024))
+fsimg=$TEST_DIR/$seq.img
+
+do_mkfs_pass()
+{
+        echo >> $seqres.full
+        echo "pass expected $*" >> $seqres.full
+        $MKFS_XFS_PROG -f -N $* >> $seqres.full 2>&1
+        [ $? -ne 0 ] && echo "fail $*"
+}
+
+do_mkfs_fail()
+{
+        echo >> $seqres.full
+        echo "fail expected $*" >> $seqres.full
+        $MKFS_XFS_PROG -f -N $* >> $seqres.full 2>&1
+        [ $? -eq 0 ] && echo "pass $*"
+}
+
+do_mkfs_pass $SCRATCH_DEV
+
+# basic "should fail" options
+# logarithm based options are no longer valid
+# NOTE: umm, when it got invalid? It seems to be still supported...
+#do_mkfs_fail -s log=10 $SCRATCH_DEV
+#do_mkfs_fail -b log=10 $SCRATCH_DEV
+#do_mkfs_fail -n log=10 $SCRATCH_DEV
+#do_mkfs_fail -i log=10 $SCRATCH_DEV
+#do_mkfs_fail -d sectlog=10 $SCRATCH_DEV
+#do_mkfs_fail -l sectlog=10 $SCRATCH_DEV
+
+# specifying sector sizes in sectors or blocks or garbage
+do_mkfs_fail -s size=2s $SCRATCH_DEV
+do_mkfs_fail -d sectsize=2s $SCRATCH_DEV
+do_mkfs_fail -l sectsize=2s $SCRATCH_DEV
+do_mkfs_fail -s size=2b $SCRATCH_DEV
+do_mkfs_fail -d sectsize=2b $SCRATCH_DEV
+do_mkfs_fail -l sectsize=2b $SCRATCH_DEV
+
+do_mkfs_fail -s size=grot $SCRATCH_DEV
+do_mkfs_fail -s size=2yerk $SCRATCH_DEV
+do_mkfs_fail -d sectsize=blah $SCRATCH_DEV
+do_mkfs_fail -d sectsize=2foo $SCRATCH_DEV
+do_mkfs_fail -l sectsize=nggh $SCRATCH_DEV
+do_mkfs_fail -l sectsize=2nggh $SCRATCH_DEV
+
+# conflicting sector/block sizes
+do_mkfs_fail -s size=512 -d sectsize=1024 $SCRATCH_DEV
+do_mkfs_fail -s size=512 -l sectsize=1024 $SCRATCH_DEV
+do_mkfs_fail -d sectsize=2048 -l sectsize=1024 $SCRATCH_DEV
+
+do_mkfs_fail -b size=512 -s size=1024 $SCRATCH_DEV
+do_mkfs_fail -b size=512 -d sectsize=1024 $SCRATCH_DEV
+do_mkfs_fail -b size=512 -l sectsize=1024 $SCRATCH_DEV
+
+# specifying block sizes in sectors without specifying sector size
+# or in blocks or garbage
+do_mkfs_fail -b size=2s $SCRATCH_DEV
+do_mkfs_fail -b size=2b $SCRATCH_DEV
+do_mkfs_fail -b size=nfi $SCRATCH_DEV
+do_mkfs_fail -b size=4096nfi $SCRATCH_DEV
+do_mkfs_fail -n size=2s $SCRATCH_DEV
+do_mkfs_fail -n size=2b $SCRATCH_DEV
+do_mkfs_fail -n size=nfi $SCRATCH_DEV
+do_mkfs_fail -n size=4096nfi $SCRATCH_DEV
+
+# bad label length
+do_mkfs_fail -L thisiswaytoolong $SCRATCH_DEV
+
+# basic "should pass" data section tests
+do_mkfs_pass $SCRATCH_DEV
+do_mkfs_pass -d name=$SCRATCH_DEV
+do_mkfs_pass -d size=$fssize $SCRATCH_DEV
+do_mkfs_pass -d agcount=32 $SCRATCH_DEV
+do_mkfs_pass -d agsize=32m $SCRATCH_DEV
+do_mkfs_pass -d agsize=32M $SCRATCH_DEV
+do_mkfs_pass -d agsize=1g $SCRATCH_DEV
+do_mkfs_pass -d agsize=$((32 * 1024 * 1024)) $SCRATCH_DEV
+do_mkfs_pass -b size=4096 -d agsize=8192b $SCRATCH_DEV
+do_mkfs_pass -d sectsize=512,agsize=65536s $SCRATCH_DEV
+do_mkfs_pass -s size=512 -d agsize=65536s $SCRATCH_DEV
+do_mkfs_pass -d noalign $SCRATCH_DEV
+do_mkfs_pass -d sunit=0,swidth=0 $SCRATCH_DEV
+do_mkfs_pass -d sunit=8,swidth=8 $SCRATCH_DEV
+do_mkfs_pass -d sunit=8,swidth=64 $SCRATCH_DEV
+do_mkfs_pass -d su=0,sw=0 $SCRATCH_DEV
+do_mkfs_pass -d su=4096,sw=1 $SCRATCH_DEV
+do_mkfs_pass -d su=4k,sw=1 $SCRATCH_DEV
+do_mkfs_pass -d su=4K,sw=8 $SCRATCH_DEV
+do_mkfs_pass -b size=4096 -d su=1b,sw=8 $SCRATCH_DEV
+do_mkfs_pass -d sectsize=512,su=8s,sw=8 $SCRATCH_DEV
+do_mkfs_pass -s size=512 -d su=8s,sw=8 $SCRATCH_DEV
+
+# invalid data section tests
+do_mkfs_fail -d size=${fssize}b $SCRATCH_DEV
+do_mkfs_fail -d size=${fssize}s $SCRATCH_DEV
+do_mkfs_fail -d size=${fssize}yerk $SCRATCH_DEV
+do_mkfs_fail -d agsize=8192b $SCRATCH_DEV
+do_mkfs_fail -d agsize=65536s $SCRATCH_DEV
+do_mkfs_fail -d agsize=32Mbsdfsdo $SCRATCH_DEV
+do_mkfs_fail -d agsize=1GB $SCRATCH_DEV
+do_mkfs_fail -d agcount=1k $SCRATCH_DEV
+do_mkfs_fail -d agcount=6b $SCRATCH_DEV
+do_mkfs_fail -d agcount=32,agsize=32m $SCRATCH_DEV
+do_mkfs_fail -d sunit=0,swidth=64 $SCRATCH_DEV
+do_mkfs_fail -d sunit=64,swidth=0 $SCRATCH_DEV
+do_mkfs_fail -d sunit=64,swidth=64,noalign $SCRATCH_DEV
+do_mkfs_fail -d sunit=64k,swidth=64 $SCRATCH_DEV
+do_mkfs_fail -d sunit=64,swidth=64m $SCRATCH_DEV
+do_mkfs_fail -d su=0,sw=64 $SCRATCH_DEV
+do_mkfs_fail -d su=4096,sw=0 $SCRATCH_DEV
+do_mkfs_fail -d su=4096,sw=64,noalign $SCRATCH_DEV
+do_mkfs_fail -d su=4096,sw=64s $SCRATCH_DEV
+do_mkfs_fail -d su=4096s,sw=64 $SCRATCH_DEV
+do_mkfs_fail -d su=4096b,sw=64 $SCRATCH_DEV
+do_mkfs_fail -d su=4096garabge,sw=64 $SCRATCH_DEV
+do_mkfs_fail -d su=4096,sw=64,sunit=64,swidth=64 $SCRATCH_DEV
+
+# file section, should pass
+rm -f $fsimg
+$XFS_IO_PROG -f -c "truncate $fssize" $fsimg
+do_mkfs_pass -d size=$fssize,file,name=$fsimg
+do_mkfs_pass -d size=$fssize,file $fsimg
+do_mkfs_pass $fsimg
+do_mkfs_pass -d size=$((fssize)) $fsimg
+do_mkfs_pass -d size=$((fssize)),name=$fsimg
+do_mkfs_pass -d size=$((fssize/2)) $fsimg
+# again this one, to check that we didn't truncated the file
+do_mkfs_pass -d size=$((fssize)) $fsimg
+
+# invalid file section tests
+rm -f $fsimg
+$XFS_IO_PROG -f -c "truncate $fssize" $fsimg
+do_mkfs_fail -d file $fsimg
+do_mkfs_fail -d file,name=$fsimg
+
+# naming section tests
+do_mkfs_pass -n size=65536 $SCRATCH_DEV
+
+# boolean options
+$XFS_IO_PROG -f -c "truncate $fssize" $fsimg
+do_mkfs_pass -d file=1,size=$fssize $fsimg
+do_mkfs_pass -d file=0 $SCRATCH_DEV
+do_mkfs_fail -d file=1 $SCRATCH_DEV
+
+# Specific flag combinations where some bug appeared during development,
+# to catch the same issue if it re-appears. If there are multiple similar
+# checks, move them to a standalone block.
+
+
+do_mkfs_pass -m crc=1,finobt=1 $SCRATCH_DEV
+
+do_mkfs_pass -m crc=1 -n ftype=1 $SCRATCH_DEV
+do_mkfs_pass -m crc=0 -n ftype=1 $SCRATCH_DEV
+do_mkfs_fail -m crc=1 -n ftype=0 $SCRATCH_DEV
+do_mkfs_pass -m crc=0 -n ftype=0 $SCRATCH_DEV
+do_mkfs_pass -n ftype=1 -m crc=0 $SCRATCH_DEV
+
+
+# if user states crc=0,finobt=1, fail instead of warning
+do_mkfs_fail -m crc=0,finobt=1 $SCRATCH_DEV
+
+status=0
+exit
diff --git a/tests/xfs/400-input-validation.out b/tests/xfs/400-input-validation.out
new file mode 100644
index 0000000..7080553
--- /dev/null
+++ b/tests/xfs/400-input-validation.out
@@ -0,0 +1,2 @@
+QA output created by 400-input-validation
+silence is golden
diff --git a/tests/xfs/group b/tests/xfs/group
index f4c6816..b51ef2e 100644
--- a/tests/xfs/group
+++ b/tests/xfs/group
@@ -285,3 +285,4 @@
 303 auto quick quota
 304 auto quick quota
 305 auto quota
+400-input-validation auto quick mkfs
-- 
2.5.0


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

* [RFC PATCH] xfstests: Add mkfs input validation tests
@ 2016-04-28  8:29   ` Jan Tulak
  0 siblings, 0 replies; 51+ messages in thread
From: Jan Tulak @ 2016-04-28  8:29 UTC (permalink / raw)
  To: fstests; +Cc: xfs

Test inputs for my mkfs-cleaning patchset. This test will fail with the old sphageti code mkfs, among others because the old code accepts incorrect values.



Signed-off-by: Dave Chinner <dchinner@redhat.com>
Signed-off-by: Jan Tulak <jtulak@redhat.com>
---

Hi guys,

I'm sending this patch although the mentioned patchset is not yet merged.
It might help you a bit with checking if there are any issues with
the patchset, as here it is clear, what options works and what not.

But because this test fails with how mkfs currently validates values
(and some other things), maybe the merging of this patch should wait
for the patchset.

Cheers,
Jan

 tests/xfs/400-input-validation     | 226 +++++++++++++++++++++++++++++++++++++
 tests/xfs/400-input-validation.out |   2 +
 tests/xfs/group                    |   1 +
 3 files changed, 229 insertions(+)
 create mode 100755 tests/xfs/400-input-validation
 create mode 100644 tests/xfs/400-input-validation.out

diff --git a/tests/xfs/400-input-validation b/tests/xfs/400-input-validation
new file mode 100755
index 0000000..4ded2ef
--- /dev/null
+++ b/tests/xfs/400-input-validation
@@ -0,0 +1,226 @@
+#! /bin/bash
+# FS QA Test No. xfs/401
+#
+# mkfs.xfs input validation test. Designed to break mkfs.xfs if it doesn't
+# filter garbage input or invalid option combinations correctly.
+#
+#-----------------------------------------------------------------------
+# Copyright (c) 2014 Red Hat, Inc.  All Rights Reserved.
+#
+# This program is free software; you can redistribute it and/or
+# modify it under the terms of the GNU General Public License as
+# published by the Free Software Foundation.
+#
+# This program is distributed in the hope that it would be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write the Free Software Foundation,
+# Inc.,  51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+#-----------------------------------------------------------------------
+#
+
+seq=`basename $0`
+seqres=$RESULT_DIR/$seq
+echo "QA output created by $seq"
+
+here=`pwd`
+tmp=/tmp/$$
+status=1        # failure is the default!
+trap "_cleanup; exit \$status" 0 1 2 3 15
+
+_cleanup()
+{
+    cd /
+    rm -f $tmp.*
+}
+
+# get standard environment, filters and checks
+. ./common/rc
+. ./common/filter
+
+# real QA test starts here
+
+# Modify as appropriate.
+_supported_fs xfs
+_supported_os Linux
+_require_scratch
+
+echo silence is golden
+
+# clear out any options to mkfs first. We want to test realtime and external log
+# devices if we can, but we also want to control them ourselves.
+logdev=$SCRATCH_LOGDEV
+rtdev=$SCRATCH_RTDEV
+
+MKFS_OPTIONS=
+SCRATCH_LOGDEV=
+SCRATCH_RTDEV=
+
+# limit the image size of the filesystem being created to something small
+fssize=$((4 * 1024 * 1024 * 1024))
+fsimg=$TEST_DIR/$seq.img
+
+do_mkfs_pass()
+{
+        echo >> $seqres.full
+        echo "pass expected $*" >> $seqres.full
+        $MKFS_XFS_PROG -f -N $* >> $seqres.full 2>&1
+        [ $? -ne 0 ] && echo "fail $*"
+}
+
+do_mkfs_fail()
+{
+        echo >> $seqres.full
+        echo "fail expected $*" >> $seqres.full
+        $MKFS_XFS_PROG -f -N $* >> $seqres.full 2>&1
+        [ $? -eq 0 ] && echo "pass $*"
+}
+
+do_mkfs_pass $SCRATCH_DEV
+
+# basic "should fail" options
+# logarithm based options are no longer valid
+# NOTE: umm, when it got invalid? It seems to be still supported...
+#do_mkfs_fail -s log=10 $SCRATCH_DEV
+#do_mkfs_fail -b log=10 $SCRATCH_DEV
+#do_mkfs_fail -n log=10 $SCRATCH_DEV
+#do_mkfs_fail -i log=10 $SCRATCH_DEV
+#do_mkfs_fail -d sectlog=10 $SCRATCH_DEV
+#do_mkfs_fail -l sectlog=10 $SCRATCH_DEV
+
+# specifying sector sizes in sectors or blocks or garbage
+do_mkfs_fail -s size=2s $SCRATCH_DEV
+do_mkfs_fail -d sectsize=2s $SCRATCH_DEV
+do_mkfs_fail -l sectsize=2s $SCRATCH_DEV
+do_mkfs_fail -s size=2b $SCRATCH_DEV
+do_mkfs_fail -d sectsize=2b $SCRATCH_DEV
+do_mkfs_fail -l sectsize=2b $SCRATCH_DEV
+
+do_mkfs_fail -s size=grot $SCRATCH_DEV
+do_mkfs_fail -s size=2yerk $SCRATCH_DEV
+do_mkfs_fail -d sectsize=blah $SCRATCH_DEV
+do_mkfs_fail -d sectsize=2foo $SCRATCH_DEV
+do_mkfs_fail -l sectsize=nggh $SCRATCH_DEV
+do_mkfs_fail -l sectsize=2nggh $SCRATCH_DEV
+
+# conflicting sector/block sizes
+do_mkfs_fail -s size=512 -d sectsize=1024 $SCRATCH_DEV
+do_mkfs_fail -s size=512 -l sectsize=1024 $SCRATCH_DEV
+do_mkfs_fail -d sectsize=2048 -l sectsize=1024 $SCRATCH_DEV
+
+do_mkfs_fail -b size=512 -s size=1024 $SCRATCH_DEV
+do_mkfs_fail -b size=512 -d sectsize=1024 $SCRATCH_DEV
+do_mkfs_fail -b size=512 -l sectsize=1024 $SCRATCH_DEV
+
+# specifying block sizes in sectors without specifying sector size
+# or in blocks or garbage
+do_mkfs_fail -b size=2s $SCRATCH_DEV
+do_mkfs_fail -b size=2b $SCRATCH_DEV
+do_mkfs_fail -b size=nfi $SCRATCH_DEV
+do_mkfs_fail -b size=4096nfi $SCRATCH_DEV
+do_mkfs_fail -n size=2s $SCRATCH_DEV
+do_mkfs_fail -n size=2b $SCRATCH_DEV
+do_mkfs_fail -n size=nfi $SCRATCH_DEV
+do_mkfs_fail -n size=4096nfi $SCRATCH_DEV
+
+# bad label length
+do_mkfs_fail -L thisiswaytoolong $SCRATCH_DEV
+
+# basic "should pass" data section tests
+do_mkfs_pass $SCRATCH_DEV
+do_mkfs_pass -d name=$SCRATCH_DEV
+do_mkfs_pass -d size=$fssize $SCRATCH_DEV
+do_mkfs_pass -d agcount=32 $SCRATCH_DEV
+do_mkfs_pass -d agsize=32m $SCRATCH_DEV
+do_mkfs_pass -d agsize=32M $SCRATCH_DEV
+do_mkfs_pass -d agsize=1g $SCRATCH_DEV
+do_mkfs_pass -d agsize=$((32 * 1024 * 1024)) $SCRATCH_DEV
+do_mkfs_pass -b size=4096 -d agsize=8192b $SCRATCH_DEV
+do_mkfs_pass -d sectsize=512,agsize=65536s $SCRATCH_DEV
+do_mkfs_pass -s size=512 -d agsize=65536s $SCRATCH_DEV
+do_mkfs_pass -d noalign $SCRATCH_DEV
+do_mkfs_pass -d sunit=0,swidth=0 $SCRATCH_DEV
+do_mkfs_pass -d sunit=8,swidth=8 $SCRATCH_DEV
+do_mkfs_pass -d sunit=8,swidth=64 $SCRATCH_DEV
+do_mkfs_pass -d su=0,sw=0 $SCRATCH_DEV
+do_mkfs_pass -d su=4096,sw=1 $SCRATCH_DEV
+do_mkfs_pass -d su=4k,sw=1 $SCRATCH_DEV
+do_mkfs_pass -d su=4K,sw=8 $SCRATCH_DEV
+do_mkfs_pass -b size=4096 -d su=1b,sw=8 $SCRATCH_DEV
+do_mkfs_pass -d sectsize=512,su=8s,sw=8 $SCRATCH_DEV
+do_mkfs_pass -s size=512 -d su=8s,sw=8 $SCRATCH_DEV
+
+# invalid data section tests
+do_mkfs_fail -d size=${fssize}b $SCRATCH_DEV
+do_mkfs_fail -d size=${fssize}s $SCRATCH_DEV
+do_mkfs_fail -d size=${fssize}yerk $SCRATCH_DEV
+do_mkfs_fail -d agsize=8192b $SCRATCH_DEV
+do_mkfs_fail -d agsize=65536s $SCRATCH_DEV
+do_mkfs_fail -d agsize=32Mbsdfsdo $SCRATCH_DEV
+do_mkfs_fail -d agsize=1GB $SCRATCH_DEV
+do_mkfs_fail -d agcount=1k $SCRATCH_DEV
+do_mkfs_fail -d agcount=6b $SCRATCH_DEV
+do_mkfs_fail -d agcount=32,agsize=32m $SCRATCH_DEV
+do_mkfs_fail -d sunit=0,swidth=64 $SCRATCH_DEV
+do_mkfs_fail -d sunit=64,swidth=0 $SCRATCH_DEV
+do_mkfs_fail -d sunit=64,swidth=64,noalign $SCRATCH_DEV
+do_mkfs_fail -d sunit=64k,swidth=64 $SCRATCH_DEV
+do_mkfs_fail -d sunit=64,swidth=64m $SCRATCH_DEV
+do_mkfs_fail -d su=0,sw=64 $SCRATCH_DEV
+do_mkfs_fail -d su=4096,sw=0 $SCRATCH_DEV
+do_mkfs_fail -d su=4096,sw=64,noalign $SCRATCH_DEV
+do_mkfs_fail -d su=4096,sw=64s $SCRATCH_DEV
+do_mkfs_fail -d su=4096s,sw=64 $SCRATCH_DEV
+do_mkfs_fail -d su=4096b,sw=64 $SCRATCH_DEV
+do_mkfs_fail -d su=4096garabge,sw=64 $SCRATCH_DEV
+do_mkfs_fail -d su=4096,sw=64,sunit=64,swidth=64 $SCRATCH_DEV
+
+# file section, should pass
+rm -f $fsimg
+$XFS_IO_PROG -f -c "truncate $fssize" $fsimg
+do_mkfs_pass -d size=$fssize,file,name=$fsimg
+do_mkfs_pass -d size=$fssize,file $fsimg
+do_mkfs_pass $fsimg
+do_mkfs_pass -d size=$((fssize)) $fsimg
+do_mkfs_pass -d size=$((fssize)),name=$fsimg
+do_mkfs_pass -d size=$((fssize/2)) $fsimg
+# again this one, to check that we didn't truncated the file
+do_mkfs_pass -d size=$((fssize)) $fsimg
+
+# invalid file section tests
+rm -f $fsimg
+$XFS_IO_PROG -f -c "truncate $fssize" $fsimg
+do_mkfs_fail -d file $fsimg
+do_mkfs_fail -d file,name=$fsimg
+
+# naming section tests
+do_mkfs_pass -n size=65536 $SCRATCH_DEV
+
+# boolean options
+$XFS_IO_PROG -f -c "truncate $fssize" $fsimg
+do_mkfs_pass -d file=1,size=$fssize $fsimg
+do_mkfs_pass -d file=0 $SCRATCH_DEV
+do_mkfs_fail -d file=1 $SCRATCH_DEV
+
+# Specific flag combinations where some bug appeared during development,
+# to catch the same issue if it re-appears. If there are multiple similar
+# checks, move them to a standalone block.
+
+
+do_mkfs_pass -m crc=1,finobt=1 $SCRATCH_DEV
+
+do_mkfs_pass -m crc=1 -n ftype=1 $SCRATCH_DEV
+do_mkfs_pass -m crc=0 -n ftype=1 $SCRATCH_DEV
+do_mkfs_fail -m crc=1 -n ftype=0 $SCRATCH_DEV
+do_mkfs_pass -m crc=0 -n ftype=0 $SCRATCH_DEV
+do_mkfs_pass -n ftype=1 -m crc=0 $SCRATCH_DEV
+
+
+# if user states crc=0,finobt=1, fail instead of warning
+do_mkfs_fail -m crc=0,finobt=1 $SCRATCH_DEV
+
+status=0
+exit
diff --git a/tests/xfs/400-input-validation.out b/tests/xfs/400-input-validation.out
new file mode 100644
index 0000000..7080553
--- /dev/null
+++ b/tests/xfs/400-input-validation.out
@@ -0,0 +1,2 @@
+QA output created by 400-input-validation
+silence is golden
diff --git a/tests/xfs/group b/tests/xfs/group
index f4c6816..b51ef2e 100644
--- a/tests/xfs/group
+++ b/tests/xfs/group
@@ -285,3 +285,4 @@
 303 auto quick quota
 304 auto quick quota
 305 auto quota
+400-input-validation auto quick mkfs
-- 
2.5.0

_______________________________________________
xfs mailing list
xfs@oss.sgi.com
http://oss.sgi.com/mailman/listinfo/xfs

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

* Re: [RFC PATCH] xfstests: Add mkfs input validation tests
  2016-04-28  8:29   ` Jan Tulak
@ 2016-04-29  1:59     ` Dave Chinner
  -1 siblings, 0 replies; 51+ messages in thread
From: Dave Chinner @ 2016-04-29  1:59 UTC (permalink / raw)
  To: Jan Tulak; +Cc: fstests, xfs

On Thu, Apr 28, 2016 at 10:29:09AM +0200, Jan Tulak wrote:
> Test inputs for my mkfs-cleaning patchset. This test will fail with the old sphageti code mkfs, among others because the old code accepts incorrect values.
> 
> 
> 
> Signed-off-by: Dave Chinner <dchinner@redhat.com>
> Signed-off-by: Jan Tulak <jtulak@redhat.com>

Please don't strip the commit messages from patches you've picked up
from other people - it loses valuable information, as well as the
original author of the code. i.e. The original commit message was:


From: Dave Chinner <dchinner@redhat.com>

mkfs.xfs does not do a very good job of input validation. This test
is designed to exercise the input validation and test good/bad
combinations of options being set. It will not pass on a current
mkfs.xfs binary - it is designed to be the test case for a input
validation cleanup.

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

> ---
> 
> Hi guys,
> 
> I'm sending this patch although the mentioned patchset is not yet merged.
> It might help you a bit with checking if there are any issues with
> the patchset, as here it is clear, what options works and what not.

in which case, a "_require_xfs_mkfs_validation" rule should be
written to determine the version of mkfs being. e.g. by testing one
of the failure cases that the unfixed binary says is ok.
....
> +# basic "should fail" options
> +# logarithm based options are no longer valid
> +# NOTE: umm, when it got invalid? It seems to be still supported...
> +#do_mkfs_fail -s log=10 $SCRATCH_DEV
> +#do_mkfs_fail -b log=10 $SCRATCH_DEV
> +#do_mkfs_fail -n log=10 $SCRATCH_DEV
> +#do_mkfs_fail -i log=10 $SCRATCH_DEV
> +#do_mkfs_fail -d sectlog=10 $SCRATCH_DEV
> +#do_mkfs_fail -l sectlog=10 $SCRATCH_DEV

They were expected to fail because I was going to remove the log
options from mkfs as part of the cleanup series because they are
redundant and nobody uses them. i.e this test was written with what
I wanted as the end result of the mkfs input validation cleanup, not
an iteration of the current behaviour.

After all the data section tests, the new tests you've added all
seem to be pretty ad-hoc.  What I was fleshing out in this test was
a relatively complete set exercising each the different options mkfs
supports.

I'd only iterated data section options so far in this test. I'd just
started on the naming section tests, and had not added any but a
basic test. That needs to be iterated, as do the inode, log (both
internal and external), metadata and realtime options....


> +# invalid file section tests
> +rm -f $fsimg
> +$XFS_IO_PROG -f -c "truncate $fssize" $fsimg
> +do_mkfs_fail -d file $fsimg
> +do_mkfs_fail -d file,name=$fsimg

Why should these fail - size should not be required if the image
file already exists and is of sufficient size....

> +
> +# naming section tests
> +do_mkfs_pass -n size=65536 $SCRATCH_DEV
> +
> +# boolean options
> +$XFS_IO_PROG -f -c "truncate $fssize" $fsimg
> +do_mkfs_pass -d file=1,size=$fssize $fsimg
> +do_mkfs_pass -d file=0 $SCRATCH_DEV
> +do_mkfs_fail -d file=1 $SCRATCH_DEV

More image file tests, belong in the data section with the other
image file tests.

> +# Specific flag combinations where some bug appeared during development,
> +# to catch the same issue if it re-appears. If there are multiple similar
> +# checks, move them to a standalone block.
> +
> +
> +do_mkfs_pass -m crc=1,finobt=1 $SCRATCH_DEV

What about all the other invalid cases?

> +do_mkfs_pass -m crc=1 -n ftype=1 $SCRATCH_DEV
> +do_mkfs_pass -m crc=0 -n ftype=1 $SCRATCH_DEV
> +do_mkfs_fail -m crc=1 -n ftype=0 $SCRATCH_DEV
> +do_mkfs_pass -m crc=0 -n ftype=0 $SCRATCH_DEV
> +do_mkfs_pass -n ftype=1 -m crc=0 $SCRATCH_DEV

One of the cleanup requirements was that option parsing would not
be order sensitive, so I don't think you need to iterate parameters
in different orders. That would just blow out the test matrix
unnecessarily. Also, if you really need to repeat the same test but
with different orders, please place those tests sequentially in the
file so it's clear that they are duplicate/order swapped tests....

> +# if user states crc=0,finobt=1, fail instead of warning
> +do_mkfs_fail -m crc=0,finobt=1 $SCRATCH_DEV

Why is this separate to the other crc,finobt test? Please try to
keep the parameter checks in logical groupings....

Cheers,

Dave.
-- 
Dave Chinner
david@fromorbit.com

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

* Re: [RFC PATCH] xfstests: Add mkfs input validation tests
@ 2016-04-29  1:59     ` Dave Chinner
  0 siblings, 0 replies; 51+ messages in thread
From: Dave Chinner @ 2016-04-29  1:59 UTC (permalink / raw)
  To: Jan Tulak; +Cc: fstests, xfs

On Thu, Apr 28, 2016 at 10:29:09AM +0200, Jan Tulak wrote:
> Test inputs for my mkfs-cleaning patchset. This test will fail with the old sphageti code mkfs, among others because the old code accepts incorrect values.
> 
> 
> 
> Signed-off-by: Dave Chinner <dchinner@redhat.com>
> Signed-off-by: Jan Tulak <jtulak@redhat.com>

Please don't strip the commit messages from patches you've picked up
from other people - it loses valuable information, as well as the
original author of the code. i.e. The original commit message was:


From: Dave Chinner <dchinner@redhat.com>

mkfs.xfs does not do a very good job of input validation. This test
is designed to exercise the input validation and test good/bad
combinations of options being set. It will not pass on a current
mkfs.xfs binary - it is designed to be the test case for a input
validation cleanup.

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

> ---
> 
> Hi guys,
> 
> I'm sending this patch although the mentioned patchset is not yet merged.
> It might help you a bit with checking if there are any issues with
> the patchset, as here it is clear, what options works and what not.

in which case, a "_require_xfs_mkfs_validation" rule should be
written to determine the version of mkfs being. e.g. by testing one
of the failure cases that the unfixed binary says is ok.
....
> +# basic "should fail" options
> +# logarithm based options are no longer valid
> +# NOTE: umm, when it got invalid? It seems to be still supported...
> +#do_mkfs_fail -s log=10 $SCRATCH_DEV
> +#do_mkfs_fail -b log=10 $SCRATCH_DEV
> +#do_mkfs_fail -n log=10 $SCRATCH_DEV
> +#do_mkfs_fail -i log=10 $SCRATCH_DEV
> +#do_mkfs_fail -d sectlog=10 $SCRATCH_DEV
> +#do_mkfs_fail -l sectlog=10 $SCRATCH_DEV

They were expected to fail because I was going to remove the log
options from mkfs as part of the cleanup series because they are
redundant and nobody uses them. i.e this test was written with what
I wanted as the end result of the mkfs input validation cleanup, not
an iteration of the current behaviour.

After all the data section tests, the new tests you've added all
seem to be pretty ad-hoc.  What I was fleshing out in this test was
a relatively complete set exercising each the different options mkfs
supports.

I'd only iterated data section options so far in this test. I'd just
started on the naming section tests, and had not added any but a
basic test. That needs to be iterated, as do the inode, log (both
internal and external), metadata and realtime options....


> +# invalid file section tests
> +rm -f $fsimg
> +$XFS_IO_PROG -f -c "truncate $fssize" $fsimg
> +do_mkfs_fail -d file $fsimg
> +do_mkfs_fail -d file,name=$fsimg

Why should these fail - size should not be required if the image
file already exists and is of sufficient size....

> +
> +# naming section tests
> +do_mkfs_pass -n size=65536 $SCRATCH_DEV
> +
> +# boolean options
> +$XFS_IO_PROG -f -c "truncate $fssize" $fsimg
> +do_mkfs_pass -d file=1,size=$fssize $fsimg
> +do_mkfs_pass -d file=0 $SCRATCH_DEV
> +do_mkfs_fail -d file=1 $SCRATCH_DEV

More image file tests, belong in the data section with the other
image file tests.

> +# Specific flag combinations where some bug appeared during development,
> +# to catch the same issue if it re-appears. If there are multiple similar
> +# checks, move them to a standalone block.
> +
> +
> +do_mkfs_pass -m crc=1,finobt=1 $SCRATCH_DEV

What about all the other invalid cases?

> +do_mkfs_pass -m crc=1 -n ftype=1 $SCRATCH_DEV
> +do_mkfs_pass -m crc=0 -n ftype=1 $SCRATCH_DEV
> +do_mkfs_fail -m crc=1 -n ftype=0 $SCRATCH_DEV
> +do_mkfs_pass -m crc=0 -n ftype=0 $SCRATCH_DEV
> +do_mkfs_pass -n ftype=1 -m crc=0 $SCRATCH_DEV

One of the cleanup requirements was that option parsing would not
be order sensitive, so I don't think you need to iterate parameters
in different orders. That would just blow out the test matrix
unnecessarily. Also, if you really need to repeat the same test but
with different orders, please place those tests sequentially in the
file so it's clear that they are duplicate/order swapped tests....

> +# if user states crc=0,finobt=1, fail instead of warning
> +do_mkfs_fail -m crc=0,finobt=1 $SCRATCH_DEV

Why is this separate to the other crc,finobt test? Please try to
keep the parameter checks in logical groupings....

Cheers,

Dave.
-- 
Dave Chinner
david@fromorbit.com

_______________________________________________
xfs mailing list
xfs@oss.sgi.com
http://oss.sgi.com/mailman/listinfo/xfs

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

* Re: [RFC PATCH] xfstests: Add mkfs input validation tests
  2016-04-29  1:59     ` Dave Chinner
  (?)
@ 2016-04-29 14:42     ` Jan Tulak
  -1 siblings, 0 replies; 51+ messages in thread
From: Jan Tulak @ 2016-04-29 14:42 UTC (permalink / raw)
  To: Dave Chinner; +Cc: fstests, xfs-oss


[-- Attachment #1.1: Type: text/plain, Size: 5807 bytes --]

On Fri, Apr 29, 2016 at 3:59 AM, Dave Chinner <david@fromorbit.com> wrote:

> On Thu, Apr 28, 2016 at 10:29:09AM +0200, Jan Tulak wrote:
> > Test inputs for my mkfs-cleaning patchset. This test will fail with the
> old sphageti code mkfs, among others because the old code accepts incorrect
> values.
> >
> >
> >
> > Signed-off-by: Dave Chinner <dchinner@redhat.com>
> > Signed-off-by: Jan Tulak <jtulak@redhat.com>
>
> Please don't strip the commit messages from patches you've picked up
> from other people - it loses valuable information, as well as the
> original author of the code. i.e. The original commit message was:
>
> ​Sorry about that. I removed it mistakenly long time ago, and now, I
didn't realised I should copy yours instead of making my own.



>
> From: Dave Chinner <dchinner@redhat.com>
>
> mkfs.xfs does not do a very good job of input validation. This test
> is designed to exercise the input validation and test good/bad
> combinations of options being set. It will not pass on a current
> mkfs.xfs binary - it is designed to be the test case for a input
> validation cleanup.
>
> Signed-off-by: Dave Chinner <dchinner@redhat.com>
>
> > ---
> >
> > Hi guys,
> >
> > I'm sending this patch although the mentioned patchset is not yet merged.
> > It might help you a bit with checking if there are any issues with
> > the patchset, as here it is clear, what options works and what not.
>
> in which case, a "_require_xfs_mkfs_validation" rule should be
> written to determine the version of mkfs being. e.g. by testing one
> of the failure cases that the unfixed binary says is ok.
> ....
> > +# basic "should fail" options
> > +# logarithm based options are no longer valid
> > +# NOTE: umm, when it got invalid? It seems to be still supported...
> > +#do_mkfs_fail -s log=10 $SCRATCH_DEV
> > +#do_mkfs_fail -b log=10 $SCRATCH_DEV
> > +#do_mkfs_fail -n log=10 $SCRATCH_DEV
> > +#do_mkfs_fail -i log=10 $SCRATCH_DEV
> > +#do_mkfs_fail -d sectlog=10 $SCRATCH_DEV
> > +#do_mkfs_fail -l sectlog=10 $SCRATCH_DEV
>
> They were expected to fail because I was going to remove the log
> options from mkfs as part of the cleanup series because they are
> redundant and nobody uses them. i.e this test was written with what
> I wanted as the end result of the mkfs input validation cleanup, not
> an iteration of the current behaviour.
>
> After all the data section tests, the new tests you've added all
> seem to be pretty ad-hoc.  What I was fleshing out in this test was
> a relatively complete set exercising each the different options mkfs
> supports.
>
> I'd only iterated data section options so far in this test. I'd just
> started on the naming section tests, and had not added any but a
> basic test. That needs to be iterated, as do the inode, log (both
> internal and external), metadata and realtime options....
>
> ​I added many of the new lines when I found some issue, to prevent
regressions. But yeah, I will put it into an orderly fashion and iterate
through other things


>
> > +# invalid file section tests
> > +rm -f $fsimg
> > +$XFS_IO_PROG -f -c "truncate $fssize" $fsimg
> > +do_mkfs_fail -d file $fsimg
> > +do_mkfs_fail -d file,name=$fsimg
>
> Why should these fail - size should not be required if the image
> file already exists and is of sufficient size....
>

​Well, they should pass. I'm sending an updated patch to the set as well.


> > +
> > +# naming section tests
> > +do_mkfs_pass -n size=65536 $SCRATCH_DEV
> > +
> > +# boolean options
> > +$XFS_IO_PROG -f -c "truncate $fssize" $fsimg
> > +do_mkfs_pass -d file=1,size=$fssize $fsimg
> > +do_mkfs_pass -d file=0 $SCRATCH_DEV
> > +do_mkfs_fail -d file=1 $SCRATCH_DEV
>
> More image file tests, belong in the data section with the other
> image file tests.
> ​​
>

> > +# Specific flag combinations where some bug appeared during development,
> > +# to catch the same issue if it re-appears. If there are multiple
> similar
> > +# checks, move them to a standalone block.
> > +
> > +
> > +do_mkfs_pass -m crc=1,finobt=1 $SCRATCH_DEV
>
> What about all the other invalid cases?
>
> > +do_mkfs_pass -m crc=1 -n ftype=1 $SCRATCH_DEV
> > +do_mkfs_pass -m crc=0 -n ftype=1 $SCRATCH_DEV
> > +do_mkfs_fail -m crc=1 -n ftype=0 $SCRATCH_DEV
> > +do_mkfs_pass -m crc=0 -n ftype=0 $SCRATCH_DEV
> > +do_mkfs_pass -n ftype=1 -m crc=0 $SCRATCH_DEV
>
> One of the cleanup requirements was that option parsing would not
> be order sensitive, so I don't think you need to iterate parameters
> in different orders. That would just blow out the test matrix
> unnecessarily. Also, if you really need to repeat the same test but
> with different orders, please place those tests sequentially in the
> file so it's clear that they are duplicate/order swapped tests....
> ​
>

​I added it as a test that the order independency really works. This is one
case, where the original code was order-dependent... But maybe such test is
not necessary, as it should be so by design and there is no way to screw it
up for all options at once. ​



​So to sum all the email, I will make an updated version with more test
data. However, it will take me some time, because in few days, exams on my
university are starting, so I need to focus there and start learning.​ :-)

Thanks and cheers,
Jan


​
>
>
> > +# if user states crc=0,finobt=1, fail instead of warning
> > +do_mkfs_fail -m crc=0,finobt=1 $SCRATCH_DEV
>
> Why is this separate to the other crc,finobt test? Please try to
> keep the parameter checks in logical groupings....
>
> Cheers,
>
> Dave.
> --
> Dave Chinner
> david@fromorbit.com
>
​

-- 
Jan Tulak
jtulak@redhat.com / jan@tulak.me

[-- Attachment #1.2: Type: text/html, Size: 9483 bytes --]

[-- Attachment #2: Type: text/plain, Size: 121 bytes --]

_______________________________________________
xfs mailing list
xfs@oss.sgi.com
http://oss.sgi.com/mailman/listinfo/xfs

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

* [PATCH 15/19 v3] mkfs: don't treat files as though they are block devices
  2016-04-22  7:49   ` [PATCH 15/19 v2] " Jan Tulak
@ 2016-04-29 14:47     ` Jan Tulak
  2016-04-29 19:11       ` Eric Sandeen
  0 siblings, 1 reply; 51+ messages in thread
From: Jan Tulak @ 2016-04-29 14:47 UTC (permalink / raw)
  To: xfs

From: Dave Chinner <dchinner@redhat.com>

If the device is actually a file, and "-d file" is not specified,
mkfs will try to treat it as a block device and get stuff wrong.
Image files don't necessarily have the same sector sizes as the
block device or filesystem underlying the image file, nor should we
be issuing discard ioctls on image files.

To fix this sanely, only require "-d file" if the device name is
invalid to trigger creation of the file. Otherwise, use stat() to
determine if the device is a file or block device and deal with that
appropriately by setting the "isfile" variables and turning off
direct IO. Then ensure that we check the "isfile" options before
doing things that are specific to block devices.

Other file/blockdev issues fixed:
	- use getstr to detect specifying the data device name
	  twice.
	- check file/size/name parameters before anything else.
	- overwrite checks need to be done before the image file is
	  opened and potentially truncated.
	- blkid_get_topology() should not be called for image files,
	  so warn when it is called that way.
	- zero_old_xfs_structures() emits a spurious error:
		"existing superblock read failed: Success"
	  when it is run on a truncated image file. Don't warn if we
	  see this problem on an image file.
	- Don't issue discards on image files.
	- Use fsync() for image files, not BLKFLSBUF in
	  platform_flush_device() for Linux.

Signed-off-by: Dave Chinner <dchinner@redhat.com>
Signed-off-by: Jan Tulak <jtulak@redhat.com>

---
CHANGES:
* read image file size in advance of O_TRUNC in case of dfile&&dcreat
Signed-off-by: Jan Tulak <jtulak@redhat.com>
---
 libxfs/init.c   |  21 ++++++-
 libxfs/linux.c  |  11 +++-
 mkfs/xfs_mkfs.c | 182 ++++++++++++++++++++++++++++++++++++++------------------
 3 files changed, 154 insertions(+), 60 deletions(-)

diff --git a/libxfs/init.c b/libxfs/init.c
index 8d747e8..c7ae00d 100644
--- a/libxfs/init.c
+++ b/libxfs/init.c
@@ -253,8 +253,15 @@ libxfs_init(libxfs_init_t *a)
 	rtname = a->rtname;
 	a->dfd = a->logfd = a->rtfd = -1;
 	a->ddev = a->logdev = a->rtdev = 0;
-	a->dbsize = a->lbsize = a->rtbsize = 0;
-	a->dsize = a->logBBsize = a->logBBstart = a->rtsize = 0;
+	a->lbsize = a->rtbsize = 0;
+	a->logBBsize = a->logBBstart = a->rtsize = 0;
+
+	// We can reset dbsize only when it is not a file, or we won't
+	// truncate it. Otherwise, we loose the size of the file forever.
+	if (!a->disfile || !a->dcreat) {
+		a->dsize = 0;
+		a->dbsize = 0;
+	}
 
 	(void)getcwd(curdir,MAXPATHLEN);
 	needcd = 0;
@@ -278,6 +285,12 @@ libxfs_init(libxfs_init_t *a)
 			a->ddev= libxfs_device_open(dname, a->dcreat, flags,
 						    a->setblksize);
 			a->dfd = libxfs_device_to_fd(a->ddev);
+			// with dcreat, it would overwrite dsize with zero
+			// and lost the size
+			if (!a->dcreat) {
+				platform_findsizes(dname, a->dfd, &a->dsize,
+							&a->dbsize);
+			}
 		} else {
 			if (!check_open(dname, flags, &rawfile, &blockfile))
 				goto done;
@@ -297,6 +310,8 @@ libxfs_init(libxfs_init_t *a)
 			a->logdev = libxfs_device_open(logname,
 					a->lcreat, flags, a->setblksize);
 			a->logfd = libxfs_device_to_fd(a->logdev);
+			platform_findsizes(dname, a->logfd, &a->logBBsize,
+						&a->lbsize);
 		} else {
 			if (!check_open(logname, flags, &rawfile, &blockfile))
 				goto done;
@@ -316,6 +331,8 @@ libxfs_init(libxfs_init_t *a)
 			a->rtdev = libxfs_device_open(rtname,
 					a->rcreat, flags, a->setblksize);
 			a->rtfd = libxfs_device_to_fd(a->rtdev);
+			platform_findsizes(dname, a->rtfd, &a->rtsize,
+						&a->rtbsize);
 		} else {
 			if (!check_open(rtname, flags, &rawfile, &blockfile))
 				goto done;
diff --git a/libxfs/linux.c b/libxfs/linux.c
index f6ea1b2..c9f2baf 100644
--- a/libxfs/linux.c
+++ b/libxfs/linux.c
@@ -125,7 +125,16 @@ platform_set_blocksize(int fd, char *path, dev_t device, int blocksize, int fata
 void
 platform_flush_device(int fd, dev_t device)
 {
-	if (major(device) != RAMDISK_MAJOR)
+	struct stat64	st;
+	if (major(device) == RAMDISK_MAJOR)
+		return;
+
+	if (fstat64(fd, &st) < 0)
+		return;
+
+	if (S_ISREG(st.st_mode))
+		fsync(fd);
+	else
 		ioctl(fd, BLKFLSBUF, 0);
 }
 
diff --git a/mkfs/xfs_mkfs.c b/mkfs/xfs_mkfs.c
index b1043fb..f75b89c 100644
--- a/mkfs/xfs_mkfs.c
+++ b/mkfs/xfs_mkfs.c
@@ -787,7 +787,7 @@ calc_stripe_factors(
 #ifdef ENABLE_BLKID
 static int
 check_overwrite(
-	char		*device)
+	const char	*device)
 {
 	const char	*type;
 	blkid_probe	pr = NULL;
@@ -804,7 +804,7 @@ check_overwrite(
 	fd = open(device, O_RDONLY);
 	if (fd < 0)
 		goto out;
-	platform_findsizes(device, fd, &size, &bsz);
+	platform_findsizes((char *)device, fd, &size, &bsz);
 	close(fd);
 
 	/* nothing to overwrite on a 0-length device */
@@ -851,7 +851,6 @@ check_overwrite(
 			"according to blkid\n"), progname, device);
 	}
 	ret = 1;
-
 out:
 	if (pr)
 		blkid_free_probe(pr);
@@ -877,8 +876,12 @@ static void blkid_get_topology(
 	struct stat statbuf;
 
 	/* can't get topology info from a file */
-	if (!stat(device, &statbuf) && S_ISREG(statbuf.st_mode))
+	if (!stat(device, &statbuf) && S_ISREG(statbuf.st_mode)) {
+		fprintf(stderr,
+	_("%s: Warning: trying to probe topology of a file %s!\n"),
+			progname, device);
 		return;
+	}
 
 	pr = blkid_new_probe_from_filename(device);
 	if (!pr)
@@ -988,7 +991,6 @@ static void get_topology(
 	    (!stat(dfile, &statbuf) && S_ISREG(statbuf.st_mode))) {
 		int fd;
 		int flags = O_RDONLY;
-		long long dummy;
 
 		/* with xi->disfile we may not have the file yet! */
 		if (xi->disfile)
@@ -996,9 +998,10 @@ static void get_topology(
 
 		fd = open(dfile, flags, 0666);
 		if (fd >= 0) {
-			platform_findsizes(dfile, fd, &dummy, &ft->lsectorsize);
+			platform_findsizes(dfile, fd, &xi->dsize, &ft->lsectorsize);
 			close(fd);
 			ft->psectorsize = ft->lsectorsize;
+			xi->dbsize = ft->lsectorsize;	
 		} else
 			ft->psectorsize = ft->lsectorsize = BBSIZE;
 	} else {
@@ -1016,6 +1019,79 @@ static void get_topology(
 }
 
 static void
+check_device_type(
+	const char	*name,
+	int		*isfile,
+	bool		no_size,
+	bool		no_name,
+	int		*create,
+	bool		force_overwrite,
+	const char	*optname)
+{
+	struct stat64 statbuf;
+	/*
+	if (*isfile && (no_size || no_name)) {
+		fprintf(stderr,
+	_("if -%s file then -%s name and -%s size are required\n"),
+			optname, optname, optname);
+		usage();
+	}*/
+
+	if (name == NULL) {
+		usage();
+	}
+
+	if (stat64(name, &statbuf)) {
+		if (errno == ENOENT && *isfile) {
+			if (create)
+				*create = 1;
+			return;
+		}
+
+		fprintf(stderr,
+	_("Error accessing specified device %s: %s\n"),
+				name, strerror(errno));
+		usage();
+		return;
+	}
+
+	if (!force_overwrite && check_overwrite(name)) {
+		fprintf(stderr,
+	_("%s: Use the -f option to force overwrite.\n"),
+			progname);
+		exit(1);
+	}
+
+	/*
+	 * We only want to completely truncate and recreate an existing file if
+	 * we were specifically told it was a file. Set the create flag only in
+	 * this case to trigger that behaviour.
+	 */
+	if (S_ISREG(statbuf.st_mode)) {
+		if (!*isfile)
+			*isfile = 1;
+		else if (create)
+			*create = 1;
+		return;
+	}
+
+	if (S_ISBLK(statbuf.st_mode)) {
+		if (*isfile) {
+			fprintf(stderr,
+	_("specified \"-%s file\" on a block device %s\n"),
+				optname, name);
+			usage();
+		}
+		return;
+	}
+
+	fprintf(stderr,
+	_("specified device %s not a file or block device\n"),
+		name);
+	usage();
+}
+
+static void
 fixup_log_stripe_unit(
 	int		lsflag,
 	int		sunit,
@@ -1280,7 +1356,6 @@ zero_old_xfs_structures(
 	__uint32_t		bsize;
 	int			i;
 	xfs_off_t		off;
-	int			tmp;
 
 	/*
 	 * We open regular files with O_TRUNC|O_CREAT. Nothing to do here...
@@ -1300,15 +1375,18 @@ zero_old_xfs_structures(
 	}
 	memset(buf, 0, new_sb->sb_sectsize);
 
-	tmp = pread(xi->dfd, buf, new_sb->sb_sectsize, 0);
-	if (tmp < 0) {
-		fprintf(stderr, _("existing superblock read failed: %s\n"),
-			strerror(errno));
-		goto done;
-	}
-	if (tmp != new_sb->sb_sectsize) {
-		fprintf(stderr,
-	_("warning: could not read existing superblock, skip zeroing\n"));
+	/*
+	 * If we are creating an image file, it might be of zero length at this
+	 * point in time. Hence reading the existing superblock is going to
+	 * return zero bytes. It's not a failure we need to warn about in this
+	 * case.
+	 */
+	off = pread(xi->dfd, buf, new_sb->sb_sectsize, 0);
+	if (off != new_sb->sb_sectsize) {
+		if (!xi->disfile)
+			fprintf(stderr,
+	_("error reading existing superblock: %s\n"),
+				strerror(errno));
 		goto done;
 	}
 	libxfs_sb_from_disk(&sb, buf);
@@ -1786,8 +1864,6 @@ main(
 				case D_FILE:
 					xi.disfile = getnum(value, &dopts,
 							    D_FILE);
-					if (xi.disfile && !Nflag)
-						xi.dcreat = 1;
 					break;
 				case D_NAME:
 					xi.dname = getstr(value, &dopts, D_NAME);
@@ -1913,11 +1989,6 @@ main(
 				case L_FILE:
 					xi.lisfile = getnum(value, &lopts,
 							    L_FILE);
-					if (xi.lisfile && loginternal)
-						conflict('l', subopts, L_INTERNAL,
-							 L_FILE);
-					if (xi.lisfile)
-						xi.lcreat = 1;
 					break;
 				case L_INTERNAL:
 					loginternal = getnum(value, &lopts,
@@ -2075,8 +2146,6 @@ main(
 				case R_FILE:
 					xi.risfile = getnum(value, &ropts,
 							    R_FILE);
-					if (xi.risfile)
-						xi.rcreat = 1;
 					break;
 				case R_NAME:
 				case R_DEV:
@@ -2181,6 +2250,26 @@ _("Minimum block size for CRC enabled filesystems is %d bytes.\n"),
 		lsectorsize = sectorsize;
 	}
 
+	/*
+	 * Before anything else, verify that we are correctly operating on
+	 * files or block devices and set the control parameters correctly.
+	 * Explicitly disable direct IO for image files so we don't error out on
+	 * sector size mismatches between the new filesystem and the underlying
+	 * host filesystem.
+	 */
+	check_device_type(dfile, &xi.disfile, !dsize, !dfile,
+			  Nflag ? NULL : &xi.dcreat, force_overwrite, "d");
+	if (!loginternal)
+		check_device_type(xi.logname, &xi.lisfile, !logsize, !xi.logname,
+				  Nflag ? NULL : &xi.lcreat,
+				  force_overwrite, "l");
+	if (xi.rtname)
+		check_device_type(xi.rtname, &xi.risfile, !rtsize, !xi.rtname,
+				  Nflag ? NULL : &xi.rcreat,
+				  force_overwrite, "r");
+	if (xi.disfile || xi.lisfile || xi.risfile)
+		xi.isdirect = 0;
+
 	memset(&ft, 0, sizeof(ft));
 	get_topology(&xi, &ft, force_overwrite);
 
@@ -2331,11 +2420,6 @@ _("warning: sparse inodes not supported without CRC support, disabled.\n"));
 	}
 
 
-	if (xi.disfile && (!dsize || !xi.dname)) {
-		fprintf(stderr,
-	_("if -d file then -d name and -d size are required\n"));
-		usage();
-	}
 	if (dsize) {
 		__uint64_t dbytes;
 
@@ -2368,11 +2452,6 @@ _("warning: sparse inodes not supported without CRC support, disabled.\n"));
 		usage();
 	}
 
-	if (xi.lisfile && (!logsize || !xi.logname)) {
-		fprintf(stderr,
-		_("if -l file then -l name and -l size are required\n"));
-		usage();
-	}
 	if (logsize) {
 		__uint64_t logbytes;
 
@@ -2390,11 +2469,6 @@ _("warning: sparse inodes not supported without CRC support, disabled.\n"));
 				(long long)logbytes, blocksize,
 				(long long)(logblocks << blocklog));
 	}
-	if (xi.risfile && (!rtsize || !xi.rtname)) {
-		fprintf(stderr,
-		_("if -r file then -r name and -r size are required\n"));
-		usage();
-	}
 	if (rtsize) {
 		__uint64_t rtbytes;
 
@@ -2516,22 +2590,14 @@ _("warning: sparse inodes not supported without CRC support, disabled.\n"));
 	xi.rtsize &= sector_mask;
 	xi.logBBsize &= (__uint64_t)-1 << (MAX(lsectorlog, 10) - BBSHIFT);
 
-	if (!force_overwrite) {
-		if (check_overwrite(dfile) ||
-		    check_overwrite(logfile) ||
-		    check_overwrite(xi.rtname)) {
-			fprintf(stderr,
-			_("%s: Use the -f option to force overwrite.\n"),
-				progname);
-			exit(1);
-		}
-	}
 
+	/* don't do discards on print-only runs or on files */
 	if (discard && !Nflag) {
-		discard_blocks(xi.ddev, xi.dsize);
-		if (xi.rtdev)
+		if (!xi.disfile)
+			discard_blocks(xi.ddev, xi.dsize);
+		if (xi.rtdev && !xi.risfile)
 			discard_blocks(xi.rtdev, xi.rtsize);
-		if (xi.logdev && xi.logdev != xi.ddev)
+		if (xi.logdev && xi.logdev != xi.ddev && !xi.lisfile)
 			discard_blocks(xi.logdev, xi.logBBsize);
 	}
 
@@ -3063,10 +3129,12 @@ _("size %s specified for log subvolume is too large, maximum is %lld blocks\n"),
 	 * so that the reads for the end of the device in the mount code
 	 * will succeed.
 	 */
-	if (xi.disfile && ftruncate64(xi.dfd, dblocks * blocksize) < 0) {
-		fprintf(stderr, _("%s: Growing the data section failed\n"),
-			progname);
-		exit(1);
+	if (xi.disfile && xi.dsize*xi.dbsize <=  dblocks * blocksize) {
+		if (ftruncate64(xi.dfd, dblocks * blocksize) < 0) {
+			fprintf(stderr, _("%s: Growing the data section failed\n"),
+				progname);
+			exit(1);
+		}
 	}
 
 	/*
-- 
2.5.0

_______________________________________________
xfs mailing list
xfs@oss.sgi.com
http://oss.sgi.com/mailman/listinfo/xfs

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

* Re: [PATCH 15/19 v3] mkfs: don't treat files as though they are block devices
  2016-04-29 14:47     ` [PATCH 15/19 v3] " Jan Tulak
@ 2016-04-29 19:11       ` Eric Sandeen
  2016-05-03  9:59         ` Jan Tulak
  0 siblings, 1 reply; 51+ messages in thread
From: Eric Sandeen @ 2016-04-29 19:11 UTC (permalink / raw)
  To: xfs



On 4/29/16 9:47 AM, Jan Tulak wrote:
> From: Dave Chinner <dchinner@redhat.com>
> 
> If the device is actually a file, and "-d file" is not specified,
> mkfs will try to treat it as a block device and get stuff wrong.
> Image files don't necessarily have the same sector sizes as the
> block device or filesystem underlying the image file, nor should we
> be issuing discard ioctls on image files.
> 
> To fix this sanely, only require "-d file" if the device name is
> invalid to trigger creation of the file. Otherwise, use stat() to
> determine if the device is a file or block device and deal with that
> appropriately by setting the "isfile" variables and turning off
> direct IO. Then ensure that we check the "isfile" options before
> doing things that are specific to block devices.
> 
> Other file/blockdev issues fixed:
> 	- use getstr to detect specifying the data device name
> 	  twice.
> 	- check file/size/name parameters before anything else.
> 	- overwrite checks need to be done before the image file is
> 	  opened and potentially truncated.
> 	- blkid_get_topology() should not be called for image files,
> 	  so warn when it is called that way.
> 	- zero_old_xfs_structures() emits a spurious error:
> 		"existing superblock read failed: Success"
> 	  when it is run on a truncated image file. Don't warn if we
> 	  see this problem on an image file.
> 	- Don't issue discards on image files.
> 	- Use fsync() for image files, not BLKFLSBUF in
> 	  platform_flush_device() for Linux.
> 
> Signed-off-by: Dave Chinner <dchinner@redhat.com>
> Signed-off-by: Jan Tulak <jtulak@redhat.com>
> 
> ---
> CHANGES:
> * read image file size in advance of O_TRUNC in case of dfile&&dcreat
> Signed-off-by: Jan Tulak <jtulak@redhat.com>
> ---
>  libxfs/init.c   |  21 ++++++-
>  libxfs/linux.c  |  11 +++-
>  mkfs/xfs_mkfs.c | 182 ++++++++++++++++++++++++++++++++++++++------------------
>  3 files changed, 154 insertions(+), 60 deletions(-)
> 
> diff --git a/libxfs/init.c b/libxfs/init.c
> index 8d747e8..c7ae00d 100644
> --- a/libxfs/init.c
> +++ b/libxfs/init.c
> @@ -253,8 +253,15 @@ libxfs_init(libxfs_init_t *a)
>  	rtname = a->rtname;
>  	a->dfd = a->logfd = a->rtfd = -1;
>  	a->ddev = a->logdev = a->rtdev = 0;
> -	a->dbsize = a->lbsize = a->rtbsize = 0;
> -	a->dsize = a->logBBsize = a->logBBstart = a->rtsize = 0;
> +	a->lbsize = a->rtbsize = 0;
> +	a->logBBsize = a->logBBstart = a->rtsize = 0;
> +
> +	// We can reset dbsize only when it is not a file, or we won't
> +	// truncate it. Otherwise, we loose the size of the file forever.

please don't use c++ comments in xfsprogs, we use /* comments */

...

>  static void
> +check_device_type(
> +	const char	*name,
> +	int		*isfile,
> +	bool		no_size,
> +	bool		no_name,
> +	int		*create,
> +	bool		force_overwrite,
> +	const char	*optname)
> +{
> +	struct stat64 statbuf;
> +	/*
> +	if (*isfile && (no_size || no_name)) {
> +		fprintf(stderr,
> +	_("if -%s file then -%s name and -%s size are required\n"),
> +			optname, optname, optname);
> +		usage();
> +	}*/

What is this?

Jan, I'm just going to go back to the original patches posted in your V2 series,
and either give them Reviewed-by's, or send followup fix-up patches with a

Eric Sandeen <sandeen@redhat.com>: fixed up foo, bar, baz

tag and a Reviewed-by to go with it, I think that might be the fastest path to
finally getting this stuff merged.

Thanks,
-Eric

_______________________________________________
xfs mailing list
xfs@oss.sgi.com
http://oss.sgi.com/mailman/listinfo/xfs

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

* Re: [PATCH 00/19 v2] mkfs cleaning
  2016-04-21  9:39 [PATCH 00/19 v2] mkfs cleaning Jan Tulak
                   ` (19 preceding siblings ...)
  2016-04-28  8:29   ` Jan Tulak
@ 2016-05-02 23:05 ` Eric Sandeen
  2016-05-10  6:10 ` Dave Chinner
  21 siblings, 0 replies; 51+ messages in thread
From: Eric Sandeen @ 2016-05-02 23:05 UTC (permalink / raw)
  To: xfs

Ok, this is going to be the weirdest review ever.  ;)

For the first 15 (which match Dave's original 15):

Reviwed-by: Eric Sandeen <sandeen@redhat.com>

... with the several fixup patches I'm about to send.
Dave, I'll have short commitlog explanations of each
incremental patch, you can probably combine them
prior to application & commit.

Jan, if you have an issue with any of them, speak now.  :)

I'll do final review of 16->19 after we get through this 
batch.

Thanks,
-Eric

_______________________________________________
xfs mailing list
xfs@oss.sgi.com
http://oss.sgi.com/mailman/listinfo/xfs

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

* Re: [PATCH 03/19] mkfs: Sanitise the superblock feature macros
  2016-04-21  9:39 ` [PATCH 03/19] mkfs: Sanitise the superblock feature macros Jan Tulak
@ 2016-05-02 23:06   ` Eric Sandeen
  2016-05-04  0:48     ` Eric Sandeen
  0 siblings, 1 reply; 51+ messages in thread
From: Eric Sandeen @ 2016-05-02 23:06 UTC (permalink / raw)
  To: xfs

Patch 03/19 fixup:

sb_feat.dirftype should be initialized as true, not initialized
as false and then reset to 1 (sic - true)

Eric Sandeen <sandeen@redhat.com>: Properly initialize sb_feat.dirftype
---


diff --git a/mkfs/xfs_mkfs.c b/mkfs/xfs_mkfs.c
index 963545b..655b3c0 100644
--- a/mkfs/xfs_mkfs.c
+++ b/mkfs/xfs_mkfs.c
@@ -1090,7 +1090,7 @@ main(
 		.lazy_sb_counters = true,
 		.projid16bit = false,
 		.crcs_enabled = true,
-		.dirftype = false,
+		.dirftype = true,
 		.parent_pointers = false,
 	};
 
@@ -1109,7 +1109,6 @@ main(
 	liflag = laflag = lsflag = lsuflag = lsunitflag = ldflag = lvflag = 0;
 	loginternal = 1;
 	logagno = logblocks = rtblocks = rtextblocks = 0;
-	sb_feat.dirftype = 1;		/* inode type information in the dir */
 	Nflag = nlflag = nsflag = nvflag = 0;
 	nftype = 0;
 	dirblocklog = dirblocksize = 0;


_______________________________________________
xfs mailing list
xfs@oss.sgi.com
http://oss.sgi.com/mailman/listinfo/xfs

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

* Re: [PATCH 08/19] mkfs: getbool is redundant
  2016-04-21  9:39 ` [PATCH 08/19] mkfs: getbool is redundant Jan Tulak
@ 2016-05-02 23:08   ` Eric Sandeen
  0 siblings, 0 replies; 51+ messages in thread
From: Eric Sandeen @ 2016-05-02 23:08 UTC (permalink / raw)
  To: xfs

Remove manpage changes, tidy others

Tidy up the grammar a little in the boolean args description.

Remove extra text around the noalign option.

It's fine that the noalign option now takes an optional
boolean 0/1 argument, but I don't think we need to document
it in the manpage.  If someone happens to add "=1" and it works,
they'll just be pleasantly surprised.


Eric Sandeen <sandeen@redhat.com>: manpage tidiness
---

diff --git a/man/man8/mkfs.xfs.8 b/man/man8/mkfs.xfs.8
index be3d1a0..980b0e1 100644
--- a/man/man8/mkfs.xfs.8
+++ b/man/man8/mkfs.xfs.8
@@ -119,7 +119,7 @@ option first needs to be added to the command line.
 Failure to specify the size of the units will result in illegal value errors
 when parameters are quantified in those units.
 .PP
-Many options allows for optional argument of value 0 or 1, to explicitly
+Many feature options allow an optional argument of 0 or 1, to explicitly
 disable or enable the functionality.
 .SH OPTIONS
 .TP
@@ -315,12 +315,10 @@ and
 .B swidth
 values.
 .TP
-.BI noalign[= value ]
-If the
-.I value
-is 1, this option disables automatic geometry detection and creates the filesystem
+.BI noalign
+This option disables automatic geometry detection and creates the filesystem
 without stripe geometry alignment even if the underlying storage device provides
-this information. 0 disables this option, that is, enables automatic detection.
+this information.
 .RE
 .TP
 .B \-f
@@ -810,11 +808,9 @@ This suboption is only needed if the real-time section of the
 filesystem should occupy less space than the size of the partition
 or logical volume containing the section.
 .TP
-.BI noalign[= value ]
-If the
-.I value
-is 1, then the option disables stripe size detection, enforcing a realtime
-device with no stripe geometry. 0 will enable stripe size detection.
+.BI noalign
+This option disables stripe size detection, enforcing a realtime device with no
+stripe geometry.
 .RE
 .TP
 .BI \-s " sector_size"


_______________________________________________
xfs mailing list
xfs@oss.sgi.com
http://oss.sgi.com/mailman/listinfo/xfs

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

* Re: [PATCH 11/19] mkfs: table based parsing for converted parameters
  2016-04-21  9:39 ` [PATCH 11/19] mkfs: table based parsing for converted parameters Jan Tulak
@ 2016-05-02 23:09   ` Eric Sandeen
  0 siblings, 0 replies; 51+ messages in thread
From: Eric Sandeen @ 2016-05-02 23:09 UTC (permalink / raw)
  To: xfs

The kernel enforces a max of XLOG_MAX_RECORD_BSIZE,
and it should match the limits in L_SUNIT after all ...

Eric Sandeen <sandeen@redhat.com>: fix min/max for "-l su"
---

su and sunit are ultimately setting the same parameter; their
limits should be the same.
diff --git a/mkfs/xfs_mkfs.c b/mkfs/xfs_mkfs.c
index 0d28a84..3ffae42 100644
--- a/mkfs/xfs_mkfs.c
+++ b/mkfs/xfs_mkfs.c
@@ -395,8 +395,8 @@ struct opt_params lopts = {
 		},
 		{ .index = L_SU,
 		  .convert = true,
-		  .minval = 0,
-		  .maxval = UINT_MAX,
+		  .minval = XLOG_MIN_RECORD_BSIZE,
+		  .maxval = XLOG_MAX_RECORD_BSIZE,
 		  .defaultval = SUBOPT_NEEDS_VAL,
 		},
 		{ .index = L_DEV,


_______________________________________________
xfs mailing list
xfs@oss.sgi.com
http://oss.sgi.com/mailman/listinfo/xfs

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

* Re: [PATCH 13/19] mkfs: encode conflicts into parsing table
  2016-04-21  9:39 ` [PATCH 13/19] mkfs: encode conflicts into parsing table Jan Tulak
@ 2016-05-02 23:11   ` Eric Sandeen
  2016-05-03 23:39   ` Eric Sandeen
  1 sibling, 0 replies; 51+ messages in thread
From: Eric Sandeen @ 2016-05-02 23:11 UTC (permalink / raw)
  To: xfs

Remove now-encoded conflict under case L_FILE

The .conflicts handle this now, no need to keep it around.

Eric Sandeen <sandeen@redhat.com>: remove explicit L_FILE conflict

---
diff --git a/mkfs/xfs_mkfs.c b/mkfs/xfs_mkfs.c
index 03d3c06..cdc81a9 100644
--- a/mkfs/xfs_mkfs.c
+++ b/mkfs/xfs_mkfs.c
@@ -1867,9 +1867,6 @@ main(
 				case L_FILE:
 					xi.lisfile = getnum(value, &lopts,
 							    L_FILE);
-					if (xi.lisfile && loginternal)
-						conflict('l', subopts, L_INTERNAL,
-							 L_FILE);
 					if (xi.lisfile)
 						xi.lcreat = 1;
 					break;


_______________________________________________
xfs mailing list
xfs@oss.sgi.com
http://oss.sgi.com/mailman/listinfo/xfs

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

* Re: [PATCH 14/19] mkfs: add string options to generic parsing
  2016-04-21  9:39 ` [PATCH 14/19] mkfs: add string options to generic parsing Jan Tulak
@ 2016-05-02 23:11   ` Eric Sandeen
  0 siblings, 0 replies; 51+ messages in thread
From: Eric Sandeen @ 2016-05-02 23:11 UTC (permalink / raw)
  To: xfs

fix alignment on two-line logic statement; align 2nd line
with first conditional, not tabbed in.

Eric Sandeen <sandeen@redaht.com>: whitespace fixup

diff --git a/mkfs/xfs_mkfs.c b/mkfs/xfs_mkfs.c
index 4186e98..f14fdff 100644
--- a/mkfs/xfs_mkfs.c
+++ b/mkfs/xfs_mkfs.c
@@ -1520,7 +1520,7 @@ check_opt(
 		if (conflict_opt == LAST_CONFLICT)
 			break;
 		if (opts->subopt_params[conflict_opt].seen ||
-			opts->subopt_params[conflict_opt].str_seen)
+		    opts->subopt_params[conflict_opt].str_seen)
 			conflict(opts->name, (char **)opts->subopts,
 				 conflict_opt, index);
 	}


_______________________________________________
xfs mailing list
xfs@oss.sgi.com
http://oss.sgi.com/mailman/listinfo/xfs

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

* Re: [PATCH 15/19] mkfs: don't treat files as though they are block devices
  2016-04-21  9:39 ` [PATCH 15/19] mkfs: don't treat files as though they are block devices Jan Tulak
  2016-04-21 12:43   ` Jan Tulak
  2016-04-22  7:49   ` [PATCH 15/19 v2] " Jan Tulak
@ 2016-05-02 23:13   ` Eric Sandeen
  2 siblings, 0 replies; 51+ messages in thread
From: Eric Sandeen @ 2016-05-02 23:13 UTC (permalink / raw)
  To: xfs

Add const to other copy of check_overwrite
Move "no mkfs target" check to a higher, more obvious location
Do not truncate file unless it needs to be grown to full fs (as in
Jan's v2)

Eric Sandeen <sandeen@redhat.com>: move check for no mkfs target
Eric Sandeen <sandeen@redhat.com>: other minor fixes
---

diff --git a/mkfs/xfs_mkfs.c b/mkfs/xfs_mkfs.c
index ec24884..1643289 100644
--- a/mkfs/xfs_mkfs.c
+++ b/mkfs/xfs_mkfs.c
@@ -951,7 +951,7 @@ out_free_probe:
  access are not working!
 static int
 check_overwrite(
-	char		*device)
+	const char	*device)
 {
 	return 1;
 }
@@ -1037,10 +1037,6 @@ check_device_type(
 		usage();
 	}
 
-	if (name == NULL) {
-		usage();
-	}
-
 	if (stat64(name, &statbuf)) {
 		if (errno == ENOENT && *isfile) {
 			if (create)
@@ -2218,6 +2214,11 @@ main(
 	} else
 		dfile = xi.dname;
 
+	if (!dfile) {
+		fprintf(stderr, _("no device name given in argument list\n"));
+		usage();
+	}
+
 	/*
 	 * Blocksize and sectorsize first, other things depend on them
 	 * For RAID4/5/6 we want to align sector size and block size,
@@ -3127,13 +3128,15 @@ _("size %s specified for log subvolume is too large, maximum is %lld blocks\n"),
 
 	/*
 	 * If the data area is a file, then grow it out to its final size
-	 * so that the reads for the end of the device in the mount code
-	 * will succeed.
+	 * if needed so that the reads for the end of the device in the mount
+	 * code will succeed.
 	 */
-	if (xi.disfile && ftruncate64(xi.dfd, dblocks * blocksize) < 0) {
-		fprintf(stderr, _("%s: Growing the data section failed\n"),
-			progname);
-		exit(1);
+	if (xi.disfile && xi.dsize * xi.dbsize < dblocks * blocksize) {
+		if (ftruncate64(xi.dfd, dblocks * blocksize) < 0) {
+			fprintf(stderr, _("%s: Growing the data section failed\n"),
+				progname);
+			exit(1);
+		}
 	}
 
 	/*


_______________________________________________
xfs mailing list
xfs@oss.sgi.com
http://oss.sgi.com/mailman/listinfo/xfs

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

* Re: [PATCH 15/19 v3] mkfs: don't treat files as though they are block devices
  2016-04-29 19:11       ` Eric Sandeen
@ 2016-05-03  9:59         ` Jan Tulak
  0 siblings, 0 replies; 51+ messages in thread
From: Jan Tulak @ 2016-05-03  9:59 UTC (permalink / raw)
  To: Eric Sandeen; +Cc: xfs-oss


[-- Attachment #1.1: Type: text/plain, Size: 4435 bytes --]

On Fri, Apr 29, 2016 at 9:11 PM, Eric Sandeen <sandeen@sandeen.net> wrote:

>
>
> On 4/29/16 9:47 AM, Jan Tulak wrote:
> > From: Dave Chinner <dchinner@redhat.com>
> >
> > If the device is actually a file, and "-d file" is not specified,
> > mkfs will try to treat it as a block device and get stuff wrong.
> > Image files don't necessarily have the same sector sizes as the
> > block device or filesystem underlying the image file, nor should we
> > be issuing discard ioctls on image files.
> >
> > To fix this sanely, only require "-d file" if the device name is
> > invalid to trigger creation of the file. Otherwise, use stat() to
> > determine if the device is a file or block device and deal with that
> > appropriately by setting the "isfile" variables and turning off
> > direct IO. Then ensure that we check the "isfile" options before
> > doing things that are specific to block devices.
> >
> > Other file/blockdev issues fixed:
> >       - use getstr to detect specifying the data device name
> >         twice.
> >       - check file/size/name parameters before anything else.
> >       - overwrite checks need to be done before the image file is
> >         opened and potentially truncated.
> >       - blkid_get_topology() should not be called for image files,
> >         so warn when it is called that way.
> >       - zero_old_xfs_structures() emits a spurious error:
> >               "existing superblock read failed: Success"
> >         when it is run on a truncated image file. Don't warn if we
> >         see this problem on an image file.
> >       - Don't issue discards on image files.
> >       - Use fsync() for image files, not BLKFLSBUF in
> >         platform_flush_device() for Linux.
> >
> > Signed-off-by: Dave Chinner <dchinner@redhat.com>
> > Signed-off-by: Jan Tulak <jtulak@redhat.com>
> >
> > ---
> > CHANGES:
> > * read image file size in advance of O_TRUNC in case of dfile&&dcreat
> > Signed-off-by: Jan Tulak <jtulak@redhat.com>
> > ---
> >  libxfs/init.c   |  21 ++++++-
> >  libxfs/linux.c  |  11 +++-
> >  mkfs/xfs_mkfs.c | 182
> ++++++++++++++++++++++++++++++++++++++------------------
> >  3 files changed, 154 insertions(+), 60 deletions(-)
> >
> > diff --git a/libxfs/init.c b/libxfs/init.c
> > index 8d747e8..c7ae00d 100644
> > --- a/libxfs/init.c
> > +++ b/libxfs/init.c
> > @@ -253,8 +253,15 @@ libxfs_init(libxfs_init_t *a)
> >       rtname = a->rtname;
> >       a->dfd = a->logfd = a->rtfd = -1;
> >       a->ddev = a->logdev = a->rtdev = 0;
> > -     a->dbsize = a->lbsize = a->rtbsize = 0;
> > -     a->dsize = a->logBBsize = a->logBBstart = a->rtsize = 0;
> > +     a->lbsize = a->rtbsize = 0;
> > +     a->logBBsize = a->logBBstart = a->rtsize = 0;
> > +
> > +     // We can reset dbsize only when it is not a file, or we won't
> > +     // truncate it. Otherwise, we loose the size of the file forever.
>
> please don't use c++ comments in xfsprogs, we use /* comments */
>

Sorry. ​:-[ ​



>
> ...
>
> >  static void
> > +check_device_type(
> > +     const char      *name,
> > +     int             *isfile,
> > +     bool            no_size,
> > +     bool            no_name,
> > +     int             *create,
> > +     bool            force_overwrite,
> > +     const char      *optname)
> > +{
> > +     struct stat64 statbuf;
> > +     /*
> > +     if (*isfile && (no_size || no_name)) {
> > +             fprintf(stderr,
> > +     _("if -%s file then -%s name and -%s size are required\n"),
> > +                     optname, optname, optname);
> > +             usage();
> > +     }*/
>
> What is this?
>
> ​Again :-[
I commented it out during the development and then forgot to really delete
it.​



> Jan, I'm just going to go back to the original patches posted in your V2
> series,
> and either give them Reviewed-by's, or send followup fix-up patches with a
>
> Eric Sandeen <sandeen@redhat.com>: fixed up foo, bar, baz
>
> tag and a Reviewed-by to go with it, I think that might be the fastest
> path to
> finally getting this stuff merged.
>
>
​OK, whatever you think is the best. :-)​

Thanks,
Jan




> Thanks,
> -Eric
>
> _______________________________________________
> xfs mailing list
> xfs@oss.sgi.com
> http://oss.sgi.com/mailman/listinfo/xfs
>



-- 
Jan Tulak
jtulak@redhat.com / jan@tulak.me

[-- Attachment #1.2: Type: text/html, Size: 7546 bytes --]

[-- Attachment #2: Type: text/plain, Size: 121 bytes --]

_______________________________________________
xfs mailing list
xfs@oss.sgi.com
http://oss.sgi.com/mailman/listinfo/xfs

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

* Re: [PATCH 13/19] mkfs: encode conflicts into parsing table
  2016-04-21  9:39 ` [PATCH 13/19] mkfs: encode conflicts into parsing table Jan Tulak
  2016-05-02 23:11   ` Eric Sandeen
@ 2016-05-03 23:39   ` Eric Sandeen
  2016-05-04  0:47     ` Eric Sandeen
  1 sibling, 1 reply; 51+ messages in thread
From: Eric Sandeen @ 2016-05-03 23:39 UTC (permalink / raw)
  To: xfs

Sorry, updated fixup patch; missed removal of "\" chars:



Remove now-encoded conflict under case L_FILE

The .conflicts handle this now, no need to keep it around.



Remove unneccesary continuation chars "\"

Eric Sandeen <sandeen@redhat.com>: remove explicit L_FILE conflict
---

diff --git a/mkfs/xfs_mkfs.c b/mkfs/xfs_mkfs.c
index 963545b..e19181c 100644
--- a/mkfs/xfs_mkfs.c
+++ b/mkfs/xfs_mkfs.c
@@ -975,8 +975,7 @@ sb_set_features(
 	 */
 	if (fp->spinodes) {
 		sbp->sb_spino_align = sbp->sb_inoalignmt;
-		sbp->sb_inoalignmt = \
-			XFS_INODES_PER_CHUNK * \
+		sbp->sb_inoalignmt = XFS_INODES_PER_CHUNK *
 			sbp->sb_inodesize >> sbp->sb_blocklog;
 		sbp->sb_features_incompat |= XFS_SB_FEAT_INCOMPAT_SPINODES;
 	}
@@ -1090,7 +1089,7 @@ main(
 		.lazy_sb_counters = true,
 		.projid16bit = false,
 		.crcs_enabled = true,
-		.dirftype = false,
+		.dirftype = true,
 		.parent_pointers = false,
 	};
 
@@ -1109,7 +1108,6 @@ main(
 	liflag = laflag = lsflag = lsuflag = lsunitflag = ldflag = lvflag = 0;
 	loginternal = 1;
 	logagno = logblocks = rtblocks = rtextblocks = 0;
-	sb_feat.dirftype = 1;		/* inode type information in the dir */
 	Nflag = nlflag = nsflag = nvflag = 0;
 	nftype = 0;
 	dirblocklog = dirblocksize = 0;

_______________________________________________
xfs mailing list
xfs@oss.sgi.com
http://oss.sgi.com/mailman/listinfo/xfs

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

* Re: [PATCH 13/19] mkfs: encode conflicts into parsing table
  2016-05-03 23:39   ` Eric Sandeen
@ 2016-05-04  0:47     ` Eric Sandeen
  0 siblings, 0 replies; 51+ messages in thread
From: Eric Sandeen @ 2016-05-04  0:47 UTC (permalink / raw)
  To: xfs

Dammit, ignore this, it was supposed to be for 03/19.

I swear this patchset is cursed ;)

On 5/3/16 6:39 PM, Eric Sandeen wrote:
> Sorry, updated fixup patch; missed removal of "\" chars:
> 
> 
> 
> Remove now-encoded conflict under case L_FILE
> 
> The .conflicts handle this now, no need to keep it around.
> 

_______________________________________________
xfs mailing list
xfs@oss.sgi.com
http://oss.sgi.com/mailman/listinfo/xfs

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

* Re: [PATCH 03/19] mkfs: Sanitise the superblock feature macros
  2016-05-02 23:06   ` Eric Sandeen
@ 2016-05-04  0:48     ` Eric Sandeen
  0 siblings, 0 replies; 51+ messages in thread
From: Eric Sandeen @ 2016-05-04  0:48 UTC (permalink / raw)
  To: xfs

Patch 03/19 fixup V2:

sb_feat.dirftype should be initialized as true, not initialized
as false and then reset to 1 (sic - true)

V2: Remove unnecessary continuation chars "\"

Eric Sandeen <sandeen@redhat.com>: Properly initialize sb_feat.dirftype
---

diff --git a/mkfs/xfs_mkfs.c b/mkfs/xfs_mkfs.c
index 963545b..e19181c 100644
--- a/mkfs/xfs_mkfs.c
+++ b/mkfs/xfs_mkfs.c
@@ -975,8 +975,7 @@ sb_set_features(
 	 */
 	if (fp->spinodes) {
 		sbp->sb_spino_align = sbp->sb_inoalignmt;
-		sbp->sb_inoalignmt = \
-			XFS_INODES_PER_CHUNK * \
+		sbp->sb_inoalignmt = XFS_INODES_PER_CHUNK *
 			sbp->sb_inodesize >> sbp->sb_blocklog;
 		sbp->sb_features_incompat |= XFS_SB_FEAT_INCOMPAT_SPINODES;
 	}
@@ -1090,7 +1089,7 @@ main(
 		.lazy_sb_counters = true,
 		.projid16bit = false,
 		.crcs_enabled = true,
-		.dirftype = false,
+		.dirftype = true,
 		.parent_pointers = false,
 	};
 
@@ -1109,7 +1108,6 @@ main(
 	liflag = laflag = lsflag = lsuflag = lsunitflag = ldflag = lvflag = 0;
 	loginternal = 1;
 	logagno = logblocks = rtblocks = rtextblocks = 0;
-	sb_feat.dirftype = 1;		/* inode type information in the dir */
 	Nflag = nlflag = nsflag = nvflag = 0;
 	nftype = 0;
 	dirblocklog = dirblocksize = 0;

_______________________________________________
xfs mailing list
xfs@oss.sgi.com
http://oss.sgi.com/mailman/listinfo/xfs

_______________________________________________
xfs mailing list
xfs@oss.sgi.com
http://oss.sgi.com/mailman/listinfo/xfs

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

* Re: [PATCH 00/19 v2] mkfs cleaning
  2016-04-21  9:39 [PATCH 00/19 v2] mkfs cleaning Jan Tulak
                   ` (20 preceding siblings ...)
  2016-05-02 23:05 ` [PATCH 00/19 v2] mkfs cleaning Eric Sandeen
@ 2016-05-10  6:10 ` Dave Chinner
  2016-06-01 13:19   ` Jan Tulak
  21 siblings, 1 reply; 51+ messages in thread
From: Dave Chinner @ 2016-05-10  6:10 UTC (permalink / raw)
  To: Jan Tulak; +Cc: xfs

On Thu, Apr 21, 2016 at 11:39:34AM +0200, Jan Tulak wrote:
> Updated version. Most notable changes are dropping of
> "xfsprogs: disable truncating of files", reverting 
> "don't treat files as though they are block devices"
> back to Dave's version, and adding a new patch
> "mkfs: conflicting values with disabled crc should fail."

Looking at xfstests runs, new failures are:

generic/054 - 
generic/055 - both fail with:

+*** mkfs failed: -l version=2,su=4096 ***

and the .full file has this specific error:

Illegal value 4096 for -l su option. value is too small

indicating that we should be allowing (2^N * block size) log
stripe units to be set. This will be a limit configuration issue,
most likely needing fixing in mkfs.

xfs/096 6s ... - output mismatch (see /home/dave/src/xfstests-dev/results//xfs/xfs/096.out.bad)
    --- tests/xfs/096.out       2016-04-05 11:11:36.814382107 +1000
    +++ /home/dave/src/xfstests-dev/results//xfs/xfs/096.out.bad        2016-05-10 12:54:25.956199714 +1000
    @@ -2,18 +2,62 @@
     
     # su too big but must be a multiple of fs block size too
     --- mkfs=-l version=2,su=262656 ---
    -log stripe unit (262656) must be a multiple of the block size (4096)
    +Illegal value 262656 for -l su option. value is too large
    +Usage: mkfs.xfs
    +/* blocksize */            [-b log=n|size=num]
    ...
    (Run 'diff -u tests/xfs/096.out /home/dave/src/xfstests-dev/results//xfs/xfs/096.out.bad'  to see the entire diff)

This test is explicitly testing an invalid value, checking that it
falls back to a sane default. This patchset has changed the
behaviour, so the xfstest will need some rework to handle both old
and new mkfs behaviour.

Can you send patches to fix all these up?

Cheers,

Dave.
-- 
Dave Chinner
david@fromorbit.com

_______________________________________________
xfs mailing list
xfs@oss.sgi.com
http://oss.sgi.com/mailman/listinfo/xfs

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

* Re: [PATCH 00/19 v2] mkfs cleaning
  2016-05-10  6:10 ` Dave Chinner
@ 2016-06-01 13:19   ` Jan Tulak
  2016-06-03  0:53     ` Dave Chinner
  0 siblings, 1 reply; 51+ messages in thread
From: Jan Tulak @ 2016-06-01 13:19 UTC (permalink / raw)
  To: Dave Chinner; +Cc: Eric Sandeen, xfs-oss


[-- Attachment #1.1: Type: text/plain, Size: 2184 bytes --]

On Tue, May 10, 2016 at 8:10 AM, Dave Chinner <david@fromorbit.com> wrote:

>
> Looking at xfstests runs, new failures are:
>
> generic/054 -
> generic/055 - both fail with:
>
> +*** mkfs failed: -l version=2,su=4096 ***
>
> and the .full file has this specific error:
>
> Illegal value 4096 for -l su option. value is too small
>
> indicating that we should be allowing (2^N * block size) log
> stripe units to be set. This will be a limit configuration issue,
> most likely needing fixing in mkfs.
>

​I'm looking on it, but this issue was introduced by Eric's fix for
patch "mkfs:
table based parsing for converted parameters":

​> ​
The kernel enforces a max of XLOG_MAX_RECORD_BSIZE,
​> ​
and it should match the limits in L_SUNIT after all ...

And looking on fs/xfs/xfs_super.c, the MIN value is enforced too. So maybe
it is the test what needs fixing? Otherwise, I would put something
like XFS_MIN_SECTORSIZE there.

See http://lxr.free-electrons.com/source/fs/xfs/xfs_super.c#L435



>
> xfs/096 6s ... - output mismatch (see
> /home/dave/src/xfstests-dev/results//xfs/xfs/096.out.bad)
>     --- tests/xfs/096.out       2016-04-05 11:11:36.814382107 +1000
>     +++ /home/dave/src/xfstests-dev/results//xfs/xfs/096.out.bad
> 2016-05-10 12:54:25.956199714 +1000
>     @@ -2,18 +2,62 @@
>
>      # su too big but must be a multiple of fs block size too
>      --- mkfs=-l version=2,su=262656 ---
>     -log stripe unit (262656) must be a multiple of the block size (4096)
>     +Illegal value 262656 for -l su option. value is too large
>     +Usage: mkfs.xfs
>     +/* blocksize */            [-b log=n|size=num]
>     ...
>     (Run 'diff -u tests/xfs/096.out
> /home/dave/src/xfstests-dev/results//xfs/xfs/096.out.bad'  to see the
> entire diff)
>
> This test is explicitly testing an invalid value, checking that it
> falls back to a sane default. This patchset has changed the
> behaviour, so the xfstest will need some rework to handle both old
> and new mkfs behaviour.
>
> Can you send patches to fix all these up?
>

​Sure.

Jan
​



-- 
Jan Tulak
jtulak@redhat.com / jan@tulak.me

[-- Attachment #1.2: Type: text/html, Size: 4505 bytes --]

[-- Attachment #2: Type: text/plain, Size: 121 bytes --]

_______________________________________________
xfs mailing list
xfs@oss.sgi.com
http://oss.sgi.com/mailman/listinfo/xfs

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

* Re: [PATCH 00/19 v2] mkfs cleaning
  2016-06-01 13:19   ` Jan Tulak
@ 2016-06-03  0:53     ` Dave Chinner
  2016-06-03  9:20       ` Jan Tulak
  0 siblings, 1 reply; 51+ messages in thread
From: Dave Chinner @ 2016-06-03  0:53 UTC (permalink / raw)
  To: Jan Tulak; +Cc: Eric Sandeen, xfs-oss

On Wed, Jun 01, 2016 at 03:19:34PM +0200, Jan Tulak wrote:
> On Tue, May 10, 2016 at 8:10 AM, Dave Chinner <david@fromorbit.com> wrote:
> 
> >
> > Looking at xfstests runs, new failures are:
> >
> > generic/054 -
> > generic/055 - both fail with:
> >
> > +*** mkfs failed: -l version=2,su=4096 ***
> >
> > and the .full file has this specific error:
> >
> > Illegal value 4096 for -l su option. value is too small
> >
> > indicating that we should be allowing (2^N * block size) log
> > stripe units to be set. This will be a limit configuration issue,
> > most likely needing fixing in mkfs.
> >
> 
> ​I'm looking on it, but this issue was introduced by Eric's fix for
> patch "mkfs:
> table based parsing for converted parameters":
> 
> ​> ​
> The kernel enforces a max of XLOG_MAX_RECORD_BSIZE,
> ​> ​
> and it should match the limits in L_SUNIT after all ...

So nobody got it right, then.  i.e. Eric's changes made it the same
as what was in my original patchset, which means *I got it wrong*,
too.

Really, it's not at all important who made the incorrect change or
why it was wrong - it's easy very make mistakes or get complex
things wrong. What matters is that we identify the problem code, we
fix the problem, and we try not to make the same error again.
Mistakes are a learning opportunity for everyone, not just the
person who wrote or reviewed the code.

> And looking on fs/xfs/xfs_super.c, the MIN value is enforced too. So maybe
> it is the test what needs fixing? Otherwise, I would put something
> like XFS_MIN_SECTORSIZE there.
> 
> See http://lxr.free-electrons.com/source/fs/xfs/xfs_super.c#L435

mp->m_logbsize is the incore log buffer size and this is checking
that the iclogsize passed in as a mount option is within the valid
range (16k->256k). It is not checking stripe unit alignment limits.
We can write an iclogbuf at any sector offset in the log; the log
stripe unit is simply an alignment guide. i.e. a lsunit = 4096 is 8
sector alignment, so the iclogbuf when written is padded out to 8
sector boundaries so that log writes are always aligned and sized to
the log stripe unit.

The only actual limit on iclogbuf size vs lsunit is that the
iclogbuf size must be >= than the lsunit, which limits the lsunit
to XLOG_MAX_RECORD_BSIZE. i.e valid range for specifying lsunit on
the command line is 1 <= lsunit <= XLOG_MAX_RECORD_BSIZE.

Cheers,

Dave.
-- 
Dave Chinner
david@fromorbit.com

_______________________________________________
xfs mailing list
xfs@oss.sgi.com
http://oss.sgi.com/mailman/listinfo/xfs

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

* Re: [PATCH 00/19 v2] mkfs cleaning
  2016-06-03  0:53     ` Dave Chinner
@ 2016-06-03  9:20       ` Jan Tulak
  2016-06-03 12:09         ` Jan Tulak
  0 siblings, 1 reply; 51+ messages in thread
From: Jan Tulak @ 2016-06-03  9:20 UTC (permalink / raw)
  To: Dave Chinner; +Cc: Eric Sandeen, xfs-oss


[-- Attachment #1.1: Type: text/plain, Size: 3190 bytes --]

On Fri, Jun 3, 2016 at 2:53 AM, Dave Chinner <david@fromorbit.com> wrote:

> On Wed, Jun 01, 2016 at 03:19:34PM +0200, Jan Tulak wrote:
> > On Tue, May 10, 2016 at 8:10 AM, Dave Chinner <david@fromorbit.com>
> wrote:
> >
> > >
> > > Looking at xfstests runs, new failures are:
> > >
> > > generic/054 -
> > > generic/055 - both fail with:
> > >
> > > +*** mkfs failed: -l version=2,su=4096 ***
> > >
> > > and the .full file has this specific error:
> > >
> > > Illegal value 4096 for -l su option. value is too small
> > >
> > > indicating that we should be allowing (2^N * block size) log
> > > stripe units to be set. This will be a limit configuration issue,
> > > most likely needing fixing in mkfs.
> > >
> >
> > ​I'm looking on it, but this issue was introduced by Eric's fix for
> > patch "mkfs:
> > table based parsing for converted parameters":
> >
> > ​> ​
> > The kernel enforces a max of XLOG_MAX_RECORD_BSIZE,
> > ​> ​
> > and it should match the limits in L_SUNIT after all ...
>
> So nobody got it right, then.  i.e. Eric's changes made it the same
> as what was in my original patchset, which means *I got it wrong*,
> too.
>
> Really, it's not at all important who made the incorrect change or
> why it was wrong - it's easy very make mistakes or get complex
> things wrong. What matters is that we identify the problem code, we
> fix the problem, and we try not to make the same error again.
> Mistakes are a learning opportunity for everyone, not just the
> person who wrote or reviewed the code.
>
> ​Yeah, I was just trying to get together all the info. ​


> > And looking on fs/xfs/xfs_super.c, the MIN value is enforced too. So
> maybe
> > it is the test what needs fixing? Otherwise, I would put something
> > like XFS_MIN_SECTORSIZE there.
> >
> > See http://lxr.free-electrons.com/source/fs/xfs/xfs_super.c#L435
>
> mp->m_logbsize is the incore log buffer size and this is checking
> that the iclogsize passed in as a mount option is within the valid
> range (16k->256k). It is not checking stripe unit alignment limits.
> We can write an iclogbuf at any sector offset in the log; the log
> stripe unit is simply an alignment guide. i.e. a lsunit = 4096 is 8
> sector alignment, so the iclogbuf when written is padded out to 8
> sector boundaries so that log writes are always aligned and sized to
> the log stripe unit.
>
> The only actual limit on iclogbuf size vs lsunit is that the
> iclogbuf size must be >= than the lsunit, which limits the lsunit
> to XLOG_MAX_RECORD_BSIZE. i.e valid range for specifying lsunit on
> the command line is 1 <= lsunit <= XLOG_MAX_RECORD_BSIZE.
>

OK. Only, it seems we mixed lsu and lsunit. From manpage: lsunit is
specified in 512-bytes block units.

So the correct ranges for both lsunit and lsu should be:
1 <= lsunit <= BTOBB(XLOG_MAX_RECORD_BSIZE)
BBTOB(1) <= lsu <= XLOG_MAX_RECORD_BSIZE

Which will be further limited from the bottom by the physical block size,
but that check is already in place and working.

If this sounds ok, I will send the patch.

Cheers,
Jan


-- 
Jan Tulak
jtulak@redhat.com / jan@tulak.me

[-- Attachment #1.2: Type: text/html, Size: 5846 bytes --]

[-- Attachment #2: Type: text/plain, Size: 121 bytes --]

_______________________________________________
xfs mailing list
xfs@oss.sgi.com
http://oss.sgi.com/mailman/listinfo/xfs

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

* Re: [PATCH 00/19 v2] mkfs cleaning
  2016-06-03  9:20       ` Jan Tulak
@ 2016-06-03 12:09         ` Jan Tulak
  2016-06-04  0:32           ` Dave Chinner
  0 siblings, 1 reply; 51+ messages in thread
From: Jan Tulak @ 2016-06-03 12:09 UTC (permalink / raw)
  To: Dave Chinner; +Cc: Eric Sandeen, xfs-oss


[-- Attachment #1.1: Type: text/plain, Size: 1465 bytes --]

[
​snip all, another issue, unrelated to the lsunit one]​

>
​I realised one small glitch with conflicts watching in the code in
combination with flags. It is not regression, I think, because b​efore now,
it was not possible to do something like -l internal=0,logdev=something,
but now it should be possible.

The code checks only whether an option was seen, not its value, so it
does't know that we are in fact disabling something. I see two ways how to
do solve it. One is a custom conflict solving for these cases, putting some
if (flag1 && option2) somewhere once every argument and option is parsed.
But this goes against what the patchset did and moves it again out of the
option table...

The other way is to make a special case for flags in the conflicts-handling
code. Basically, I would extend the structure with something like:

{ .index = L_INTERNAL,
  .conflicts = { L_FILE,
        L_DEV,
        LAST_CONFLICT },
  .conflicts_ignore_on_false=true, // new item, shorter name to be found
  .minval = 0,
  .maxval = 1,
  .defaultval = 1,
},

And then, if a conflict is found, it checks the value and if the value is
false/zero, then ignore the conflict. A more generic code would allow for
any given value, but I think that this would be useful only for flags, so
"on_false" and possibly "on_true" would be enough.

​Any comments?

Thanks,
Jan​




-- 
Jan Tulak
jtulak@redhat.com / jan@tulak.me

[-- Attachment #1.2: Type: text/html, Size: 3775 bytes --]

[-- Attachment #2: Type: text/plain, Size: 121 bytes --]

_______________________________________________
xfs mailing list
xfs@oss.sgi.com
http://oss.sgi.com/mailman/listinfo/xfs

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

* Re: [PATCH 00/19 v2] mkfs cleaning
  2016-06-03 12:09         ` Jan Tulak
@ 2016-06-04  0:32           ` Dave Chinner
  2016-06-06  7:42             ` Jan Tulak
  0 siblings, 1 reply; 51+ messages in thread
From: Dave Chinner @ 2016-06-04  0:32 UTC (permalink / raw)
  To: Jan Tulak; +Cc: Eric Sandeen, xfs-oss

On Fri, Jun 03, 2016 at 02:09:19PM +0200, Jan Tulak wrote:
> [
> ​snip all, another issue, unrelated to the lsunit one]​
> 
> >
> ​I realised one small glitch with conflicts watching in the code in
> combination with flags. It is not regression, I think, because b​efore now,
> it was not possible to do something like -l internal=0,logdev=something,
> but now it should be possible.

I think that overly complicates things. My original intent for this
work was to simplify the interface and code, not make it more
elaborate to support configurations that are theoretically possible
but completely redundant.

i.e. '-l internal=0,logdev=something' is identical in function to
'-l logdev=something', so there is no need to specify internal=0.
AFAICT, therxp eis never a need to specify '-l internal=[0|1]'
because if '-l logdev=<foo>' is specified, it implies an external
log is being configured, and in every other case the log is
internal.

> The code checks only whether an option was seen, not its value, so it
> does't know that we are in fact disabling something. I see two ways how to
> do solve it. One is a custom conflict solving for these cases, putting some
> if (flag1 && option2) somewhere once every argument and option is parsed.
> But this goes against what the patchset did and moves it again out of the
> option table...
> 
> The other way is to make a special case for flags in the conflicts-handling
> code. Basically, I would extend the structure with something like:
> 
> { .index = L_INTERNAL,
>   .conflicts = { L_FILE,
>         L_DEV,
>         LAST_CONFLICT },
>   .conflicts_ignore_on_false=true, // new item, shorter name to be found

What happens when you have two conflicts, on which you want to
ignore on false, the other you want to ignore on true?  And where do
you draw the line? L_SU vs L_SUNIT conflict and throw an error only
when the values differ?

Cheers,

Dave.
-- 
Dave Chinner
david@fromorbit.com

_______________________________________________
xfs mailing list
xfs@oss.sgi.com
http://oss.sgi.com/mailman/listinfo/xfs

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

* Re: [PATCH 00/19 v2] mkfs cleaning
  2016-06-04  0:32           ` Dave Chinner
@ 2016-06-06  7:42             ` Jan Tulak
  0 siblings, 0 replies; 51+ messages in thread
From: Jan Tulak @ 2016-06-06  7:42 UTC (permalink / raw)
  To: Dave Chinner; +Cc: Eric Sandeen, xfs-oss


[-- Attachment #1.1: Type: text/plain, Size: 2236 bytes --]

On Sat, Jun 4, 2016 at 2:32 AM, Dave Chinner <david@fromorbit.com> wrote:

> On Fri, Jun 03, 2016 at 02:09:19PM +0200, Jan Tulak wrote:
> > [
> > ​snip all, another issue, unrelated to the lsunit one]​
> >
> > >
> > ​I realised one small glitch with conflicts watching in the code in
> > combination with flags. It is not regression, I think, because b​efore
> now,
> > it was not possible to do something like -l internal=0,logdev=something,
> > but now it should be possible.
>
> I think that overly complicates things. My original intent for this
> work was to simplify the interface and code, not make it more
> elaborate to support configurations that are theoretically possible
> but completely redundant.
>
> i.e. '-l internal=0,logdev=something' is identical in function to
> '-l logdev=something', so there is no need to specify internal=0.
> AFAICT, therxp eis never a need to specify '-l internal=[0|1]'
> because if '-l logdev=<foo>' is specified, it implies an external
> log is being configured, and in every other case the log is
> internal.
>
> > The code checks only whether an option was seen, not its value, so it
> > does't know that we are in fact disabling something. I see two ways how
> to
> > do solve it. One is a custom conflict solving for these cases, putting
> some
> > if (flag1 && option2) somewhere once every argument and option is parsed.
> > But this goes against what the patchset did and moves it again out of the
> > option table...
> >
> > The other way is to make a special case for flags in the
> conflicts-handling
> > code. Basically, I would extend the structure with something like:
> >
> > { .index = L_INTERNAL,
> >   .conflicts = { L_FILE,
> >         L_DEV,
> >         LAST_CONFLICT },
> >   .conflicts_ignore_on_false=true, // new item, shorter name to be found
>
> What happens when you have two conflicts, on which you want to
> ignore on false, the other you want to ignore on true?  And where do
> you draw the line? L_SU vs L_SUNIT conflict and throw an error only
> when the values differ?
>
>
​Yeah, that's true... let's call it feature then.

Cheers,
Jan​


-- 
Jan Tulak
jtulak@redhat.com / jan@tulak.me

[-- Attachment #1.2: Type: text/html, Size: 3769 bytes --]

[-- Attachment #2: Type: text/plain, Size: 121 bytes --]

_______________________________________________
xfs mailing list
xfs@oss.sgi.com
http://oss.sgi.com/mailman/listinfo/xfs

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

* Re: [PATCH 13/19] mkfs: encode conflicts into parsing table
  2016-03-24 11:15 ` [PATCH 13/19] mkfs: encode conflicts into parsing table jtulak
@ 2016-04-07 22:40   ` Eric Sandeen
  0 siblings, 0 replies; 51+ messages in thread
From: Eric Sandeen @ 2016-04-07 22:40 UTC (permalink / raw)
  To: xfs



On 3/24/16 6:15 AM, jtulak@redhat.com wrote:
> From: Dave Chinner <dchinner@redhat.com>
> 
> CHANGELOG:
> o Add .conflicts init where it was missing
> o Add explanation of a new member of opt_params struct.
> o A long line fix.
> 
> Many options conflict, so we need to specify which options conflict
> with each other in a generic manner. We already have a "seen"
> variable used for respecification detection, so we can also use this
> code conflict detection. Hence add a "conflicts" array to the sub
> options parameter definition.
> 
> Signed-off-by: Dave Chinner <dchinner@redhat.com>
> Signed-off-by: Jan Tulak <jtulak@redhat.com>

Reviewed-by: Eric Sandeen <sandeen@redhat.com>

> ---
>  mkfs/xfs_mkfs.c | 258 +++++++++++++++++++++++++++++---------------------------
>  1 file changed, 134 insertions(+), 124 deletions(-)
> 
> diff --git a/mkfs/xfs_mkfs.c b/mkfs/xfs_mkfs.c
> index 1f06110..d119580 100644
> --- a/mkfs/xfs_mkfs.c
> +++ b/mkfs/xfs_mkfs.c
> @@ -54,6 +54,9 @@ unsigned int		sectorsize;
>  
>  #define MAX_SUBOPTS	16
>  #define SUBOPT_NEEDS_VAL	(-1LL)
> +#define MAX_CONFLICTS	8
> +#define LAST_CONFLICT	(-1)
> +
>  /*
>   * Table for parsing mkfs parameters.
>   *
> @@ -89,6 +92,11 @@ unsigned int		sectorsize;
>   *     An optional flag for subopts where the given value has to be a power
>   *     of two.
>   *
> + *   conflicts MANDATORY
> + *     If your subopt is in a conflict with some other option, specify it.
> + *     Accepts the .index values of the conflicting subopts and the last
> + *     member of this list has to be LAST_CONFLICT.
> + *
>   *   minval, maxval OPTIONAL
>   *     These options are used for automatic range check and they have to be
>   *     always used together in pair. If you don't want to limit the max value,
> @@ -118,6 +126,7 @@ struct opt_params {
>  		bool		seen;
>  		bool		convert;
>  		bool		is_power_2;
> +		int		conflicts[MAX_CONFLICTS];
>  		long long	minval;
>  		long long	maxval;
>  		long long	defaultval;
> @@ -135,6 +144,8 @@ struct opt_params bopts = {
>  	},
>  	.subopt_params = {
>  		{ .index = B_LOG,
> +		  .conflicts = { B_SIZE,
> +				 LAST_CONFLICT },
>  		  .minval = XFS_MIN_BLOCKSIZE_LOG,
>  		  .maxval = XFS_MAX_BLOCKSIZE_LOG,
>  		  .defaultval = SUBOPT_NEEDS_VAL,
> @@ -142,6 +153,8 @@ struct opt_params bopts = {
>  		{ .index = B_SIZE,
>  		  .convert = true,
>  		  .is_power_2 = true,
> +		  .conflicts = { B_LOG,
> +				 LAST_CONFLICT },
>  		  .minval = XFS_MIN_BLOCKSIZE,
>  		  .maxval = XFS_MAX_BLOCKSIZE,
>  		  .defaultval = SUBOPT_NEEDS_VAL,
> @@ -186,57 +199,84 @@ struct opt_params dopts = {
>  	},
>  	.subopt_params = {
>  		{ .index = D_AGCOUNT,
> +		  .conflicts = { D_AGSIZE,
> +				 LAST_CONFLICT },
>  		  .minval = 1,
>  		  .maxval = XFS_MAX_AGNUMBER,
>  		  .defaultval = SUBOPT_NEEDS_VAL,
>  		},
>  		{ .index = D_FILE,
> +		  .conflicts = { LAST_CONFLICT },
>  		  .minval = 0,
>  		  .maxval = 1,
>  		  .defaultval = 1,
>  		},
>  		{ .index = D_NAME,
> +		  .conflicts = { LAST_CONFLICT },
>  		  .defaultval = SUBOPT_NEEDS_VAL,
>  		},
>  		{ .index = D_SIZE,
> +		  .conflicts = { LAST_CONFLICT },
>  		  .convert = true,
>  		  .minval = XFS_AG_MIN_BYTES,
>  		  .maxval = LLONG_MAX,
>  		  .defaultval = SUBOPT_NEEDS_VAL,
>  		},
>  		{ .index = D_SUNIT,
> +		  .conflicts = { D_NOALIGN,
> +				 D_SU,
> +				 D_SW,
> +				 LAST_CONFLICT },
>  		  .minval = 0,
>  		  .maxval = UINT_MAX,
>  		  .defaultval = SUBOPT_NEEDS_VAL,
>  		},
>  		{ .index = D_SWIDTH,
> +		  .conflicts = { D_NOALIGN,
> +				 D_SU,
> +				 D_SW,
> +				 LAST_CONFLICT },
>  		  .minval = 0,
>  		  .maxval = UINT_MAX,
>  		  .defaultval = SUBOPT_NEEDS_VAL,
>  		},
>  		{ .index = D_AGSIZE,
> +		  .conflicts = { D_AGCOUNT,
> +				 LAST_CONFLICT },
>  		  .convert = true,
>  		  .minval = XFS_AG_MIN_BYTES,
>  		  .maxval = XFS_AG_MAX_BYTES,
>  		  .defaultval = SUBOPT_NEEDS_VAL,
>  		},
>  		{ .index = D_SU,
> +		  .conflicts = { D_NOALIGN,
> +				 D_SUNIT,
> +				 D_SWIDTH,
> +				 LAST_CONFLICT },
>  		  .convert = true,
>  		  .minval = 0,
>  		  .maxval = UINT_MAX,
>  		  .defaultval = SUBOPT_NEEDS_VAL,
>  		},
>  		{ .index = D_SW,
> +		  .conflicts = { D_NOALIGN,
> +				 D_SUNIT,
> +				 D_SWIDTH,
> +				 LAST_CONFLICT },
>  		  .minval = 0,
>  		  .maxval = UINT_MAX,
>  		  .defaultval = SUBOPT_NEEDS_VAL,
>  		},
>  		{ .index = D_SECTLOG,
> +		  .conflicts = { D_SECTSIZE,
> +				 LAST_CONFLICT },
>  		  .minval = XFS_MIN_SECTORSIZE_LOG,
>  		  .maxval = XFS_MAX_SECTORSIZE_LOG,
>  		  .defaultval = SUBOPT_NEEDS_VAL,
>  		},
>  		{ .index = D_SECTSIZE,
> +		  .conflicts = { D_SECTLOG,
> +				 LAST_CONFLICT },
>  		  .convert = true,
>  		  .is_power_2 = true,
>  		  .minval = XFS_MIN_SECTORSIZE,
> @@ -244,21 +284,29 @@ struct opt_params dopts = {
>  		  .defaultval = SUBOPT_NEEDS_VAL,
>  		},
>  		{ .index = D_NOALIGN,
> +		  .conflicts = { D_SU,
> +				 D_SW,
> +				 D_SUNIT,
> +				 D_SWIDTH,
> +				 LAST_CONFLICT },
>  		  .minval = 0,
>  		  .maxval = 1,
>  		  .defaultval = 1,
>  		},
>  		{ .index = D_RTINHERIT,
> +		  .conflicts = { LAST_CONFLICT },
>  		  .minval = 1,
>  		  .maxval = 1,
>  		  .defaultval = 1,
>  		},
>  		{ .index = D_PROJINHERIT,
> +		  .conflicts = { LAST_CONFLICT },
>  		  .minval = 0,
>  		  .maxval = UINT_MAX,
>  		  .defaultval = SUBOPT_NEEDS_VAL,
>  		},
>  		{ .index = D_EXTSZINHERIT,
> +		  .conflicts = { LAST_CONFLICT },
>  		  .minval = 0,
>  		  .maxval = UINT_MAX,
>  		  .defaultval = SUBOPT_NEEDS_VAL,
> @@ -290,43 +338,57 @@ struct opt_params iopts = {
>  	},
>  	.subopt_params = {
>  		{ .index = I_ALIGN,
> +		  .conflicts = { LAST_CONFLICT },
>  		  .minval = 0,
>  		  .maxval = 1,
>  		  .defaultval = 1,
>  		},
>  		{ .index = I_LOG,
> +		  .conflicts = { I_PERBLOCK,
> +				 I_SIZE,
> +				 LAST_CONFLICT },
>  		  .minval = XFS_DINODE_MIN_LOG,
>  		  .maxval = XFS_DINODE_MAX_LOG,
>  		  .defaultval = SUBOPT_NEEDS_VAL,
>  		},
>  		{ .index = I_MAXPCT,
> +		  .conflicts = { LAST_CONFLICT },
>  		  .minval = 0,
>  		  .maxval = 100,
>  		  .defaultval = SUBOPT_NEEDS_VAL,
>  		},
>  		{ .index = I_PERBLOCK,
> +		  .conflicts = { I_LOG,
> +				 I_SIZE,
> +				 LAST_CONFLICT },
>  		  .is_power_2 = true,
>  		  .minval = XFS_MIN_INODE_PERBLOCK,
>  		  .maxval = XFS_MAX_BLOCKSIZE / XFS_DINODE_MIN_SIZE,
>  		  .defaultval = SUBOPT_NEEDS_VAL,
>  		},
>  		{ .index = I_SIZE,
> +		  .conflicts = { I_PERBLOCK,
> +				 I_LOG,
> +				 LAST_CONFLICT },
>  		  .is_power_2 = true,
>  		  .minval = XFS_DINODE_MIN_SIZE,
>  		  .maxval = XFS_DINODE_MAX_SIZE,
>  		  .defaultval = SUBOPT_NEEDS_VAL,
>  		},
>  		{ .index = I_ATTR,
> +		  .conflicts = { LAST_CONFLICT },
>  		  .minval = 0,
>  		  .maxval = 2,
>  		  .defaultval = SUBOPT_NEEDS_VAL,
>  		},
>  		{ .index = I_PROJID32BIT,
> +		  .conflicts = { LAST_CONFLICT },
>  		  .minval = 0,
>  		  .maxval = 1,
>  		  .defaultval = 1,
>  		},
>  		{ .index = I_SPINODES,
> +		  .conflicts = { LAST_CONFLICT },
>  		  .minval = 0,
>  		  .maxval = 1,
>  		  .defaultval = 1,
> @@ -365,46 +427,64 @@ struct opt_params lopts = {
>  	},
>  	.subopt_params = {
>  		{ .index = L_AGNUM,
> +		  .conflicts = { L_DEV,
> +				 LAST_CONFLICT },
>  		  .minval = 0,
>  		  .maxval = UINT_MAX,
>  		  .defaultval = SUBOPT_NEEDS_VAL,
>  		},
>  		{ .index = L_INTERNAL,
> +		  .conflicts = { L_FILE,
> +				 L_DEV,
> +				 LAST_CONFLICT },
>  		  .minval = 0,
>  		  .maxval = 1,
>  		  .defaultval = 1,
>  		},
>  		{ .index = L_SIZE,
> +		  .conflicts = { LAST_CONFLICT },
>  		  .convert = true,
>  		  .minval = 2 * 1024 * 1024LL,	/* XXX: XFS_MIN_LOG_BYTES */
>  		  .maxval = XFS_MAX_LOG_BYTES,
>  		  .defaultval = SUBOPT_NEEDS_VAL,
>  		},
>  		{ .index = L_VERSION,
> +		  .conflicts = { LAST_CONFLICT },
>  		  .minval = 1,
>  		  .maxval = 2,
>  		  .defaultval = SUBOPT_NEEDS_VAL,
>  		},
>  		{ .index = L_SUNIT,
> +		  .conflicts = { L_SU,
> +				 LAST_CONFLICT },
>  		  .minval = BTOBB(XLOG_MIN_RECORD_BSIZE),
>  		  .maxval = BTOBB(XLOG_MAX_RECORD_BSIZE),
>  		  .defaultval = SUBOPT_NEEDS_VAL,
>  		},
>  		{ .index = L_SU,
> +		  .conflicts = { L_SUNIT,
> +				 LAST_CONFLICT },
>  		  .convert = true,
>  		  .minval = XLOG_MIN_RECORD_BSIZE,
>  		  .maxval = UINT_MAX,
>  		  .defaultval = SUBOPT_NEEDS_VAL,
>  		},
>  		{ .index = L_DEV,
> +		  .conflicts = { L_AGNUM,
> +				 L_INTERNAL,
> +				 LAST_CONFLICT },
>  		  .defaultval = SUBOPT_NEEDS_VAL,
>  		},
>  		{ .index = L_SECTLOG,
> +		  .conflicts = { L_SECTSIZE,
> +				 LAST_CONFLICT },
>  		  .minval = XFS_MIN_SECTORSIZE_LOG,
>  		  .maxval = XFS_MAX_SECTORSIZE_LOG,
>  		  .defaultval = SUBOPT_NEEDS_VAL,
>  		},
>  		{ .index = L_SECTSIZE,
> +		  .conflicts = { L_SECTLOG,
> +				 LAST_CONFLICT },
>  		  .convert = true,
>  		  .is_power_2 = true,
>  		  .minval = XFS_MIN_SECTORSIZE,
> @@ -412,14 +492,20 @@ struct opt_params lopts = {
>  		  .defaultval = SUBOPT_NEEDS_VAL,
>  		},
>  		{ .index = L_FILE,
> +		  .conflicts = { L_INTERNAL,
> +				 LAST_CONFLICT },
>  		  .minval = 0,
>  		  .maxval = 1,
>  		  .defaultval = 1,
>  		},
>  		{ .index = L_NAME,
> +		  .conflicts = { L_AGNUM,
> +				 L_INTERNAL,
> +				 LAST_CONFLICT },
>  		  .defaultval = SUBOPT_NEEDS_VAL,
>  		},
>  		{ .index = L_LAZYSBCNTR,
> +		  .conflicts = { LAST_CONFLICT },
>  		  .minval = 0,
>  		  .maxval = 1,
>  		  .defaultval = 1,
> @@ -442,11 +528,15 @@ struct opt_params nopts = {
>  	},
>  	.subopt_params = {
>  		{ .index = N_LOG,
> +		  .conflicts = { N_SIZE,
> +				 LAST_CONFLICT },
>  		  .minval = XFS_MIN_REC_DIRSIZE,
>  		  .maxval = XFS_MAX_BLOCKSIZE_LOG,
>  		  .defaultval = SUBOPT_NEEDS_VAL,
>  		},
>  		{ .index = N_SIZE,
> +		  .conflicts = { N_LOG,
> +				 LAST_CONFLICT },
>  		  .convert = true,
>  		  .is_power_2 = true,
>  		  .minval = 1 << XFS_MIN_REC_DIRSIZE,
> @@ -454,11 +544,13 @@ struct opt_params nopts = {
>  		  .defaultval = SUBOPT_NEEDS_VAL,
>  		},
>  		{ .index = N_VERSION,
> +		  .conflicts = { LAST_CONFLICT },
>  		  .minval = 2,
>  		  .maxval = 2,
>  		  .defaultval = SUBOPT_NEEDS_VAL,
>  		},
>  		{ .index = N_FTYPE,
> +		  .conflicts = { LAST_CONFLICT },
>  		  .minval = 0,
>  		  .maxval = 1,
>  		  .defaultval = 1,
> @@ -485,32 +577,38 @@ struct opt_params ropts = {
>  	},
>  	.subopt_params = {
>  		{ .index = R_EXTSIZE,
> +		  .conflicts = { LAST_CONFLICT },
>  		  .convert = true,
>  		  .minval = XFS_MIN_RTEXTSIZE,
>  		  .maxval = XFS_MAX_RTEXTSIZE,
>  		  .defaultval = SUBOPT_NEEDS_VAL,
>  		},
>  		{ .index = R_SIZE,
> +		  .conflicts = { LAST_CONFLICT },
>  		  .convert = true,
>  		  .minval = 0,
>  		  .maxval = LLONG_MAX,
>  		  .defaultval = SUBOPT_NEEDS_VAL,
>  		},
>  		{ .index = R_DEV,
> +		  .conflicts = { LAST_CONFLICT },
>  		  .defaultval = SUBOPT_NEEDS_VAL,
>  		},
>  		{ .index = R_FILE,
>  		  .minval = 0,
>  		  .maxval = 1,
>  		  .defaultval = 1,
> +		  .conflicts = { LAST_CONFLICT },
>  		},
>  		{ .index = R_NAME,
> +		  .conflicts = { LAST_CONFLICT },
>  		  .defaultval = SUBOPT_NEEDS_VAL,
>  		},
>  		{ .index = R_NOALIGN,
>  		  .minval = 0,
>  		  .maxval = 1,
>  		  .defaultval = 1,
> +		  .conflicts = { LAST_CONFLICT },
>  		},
>  	},
>  };
> @@ -530,16 +628,25 @@ struct opt_params sopts = {
>  	},
>  	.subopt_params = {
>  		{ .index = S_LOG,
> +		  .conflicts = { S_SIZE,
> +				 S_SECTSIZE,
> +				 LAST_CONFLICT },
>  		  .minval = XFS_MIN_SECTORSIZE_LOG,
>  		  .maxval = XFS_MAX_SECTORSIZE_LOG,
>  		  .defaultval = SUBOPT_NEEDS_VAL,
>  		},
>  		{ .index = S_SECTLOG,
> +		  .conflicts = { S_SIZE,
> +				 S_SECTSIZE,
> +				 LAST_CONFLICT },
>  		  .minval = XFS_MIN_SECTORSIZE_LOG,
>  		  .maxval = XFS_MAX_SECTORSIZE_LOG,
>  		  .defaultval = SUBOPT_NEEDS_VAL,
>  		},
>  		{ .index = S_SIZE,
> +		  .conflicts = { S_LOG,
> +				 S_SECTLOG,
> +				 LAST_CONFLICT },
>  		  .convert = true,
>  		  .is_power_2 = true,
>  		  .minval = XFS_MIN_SECTORSIZE,
> @@ -547,6 +654,9 @@ struct opt_params sopts = {
>  		  .defaultval = SUBOPT_NEEDS_VAL,
>  		},
>  		{ .index = S_SECTSIZE,
> +		  .conflicts = { S_LOG,
> +				 S_SECTLOG,
> +				 LAST_CONFLICT },
>  		  .convert = true,
>  		  .is_power_2 = true,
>  		  .minval = XFS_MIN_SECTORSIZE,
> @@ -569,16 +679,19 @@ struct opt_params mopts = {
>  	},
>  	.subopt_params = {
>  		{ .index = M_CRC,
> +		  .conflicts = { LAST_CONFLICT },
>  		  .minval = 0,
>  		  .maxval = 1,
>  		  .defaultval = 1,
>  		},
>  		{ .index = M_FINOBT,
> +		  .conflicts = { LAST_CONFLICT },
>  		  .minval = 0,
>  		  .maxval = 1,
>  		  .defaultval = 1,
>  		},
>  		{ .index = M_UUID,
> +		  .conflicts = { LAST_CONFLICT },
>  		  .defaultval = SUBOPT_NEEDS_VAL,
>  		},
>  	},
> @@ -620,30 +733,14 @@ calc_stripe_factors(
>  	int		*lsunit)
>  {
>  	/* Handle data sunit/swidth options */
> -	if (*dsunit || *dswidth) {
> -		if (dsu || dsw) {
> -			fprintf(stderr,
> -				_("data su/sw must not be used in "
> -				"conjunction with data sunit/swidth\n"));
> -			usage();
> -		}
> -
> -		if ((*dsunit && !*dswidth) || (!*dsunit && *dswidth)) {
> -			fprintf(stderr,
> -				_("both data sunit and data swidth options "
> -				"must be specified\n"));
> -			usage();
> -		}
> +	if ((*dsunit && !*dswidth) || (!*dsunit && *dswidth)) {
> +		fprintf(stderr,
> +			_("both data sunit and data swidth options "
> +			"must be specified\n"));
> +		usage();
>  	}
>  
>  	if (dsu || dsw) {
> -		if (*dsunit || *dswidth) {
> -			fprintf(stderr,
> -				_("data sunit/swidth must not be used in "
> -				"conjunction with data su/sw\n"));
> -			usage();
> -		}
> -
>  		if ((dsu && !dsw) || (!dsu && dsw)) {
>  			fprintf(stderr,
>  				_("both data su and data sw options "
> @@ -671,24 +768,8 @@ calc_stripe_factors(
>  
>  	/* Handle log sunit options */
>  
> -	if (*lsunit) {
> -		if (lsu) {
> -			fprintf(stderr,
> -				_("log su should not be used in "
> -				"conjunction with log sunit\n"));
> -			usage();
> -		}
> -	}
> -
> -	if (lsu) {
> -		if (*lsunit) {
> -			fprintf(stderr,
> -				_("log sunit should not be used in "
> -				"conjunction with log su\n"));
> -			usage();
> -		}
> +	if (lsu)
>  		*lsunit = (int)BTOBBT(lsu);
> -	}
>  }
>  
>  /*
> @@ -1410,6 +1491,17 @@ getnum(
>  		respec(opts->name, (char **)opts->subopts, index);
>  	sp->seen = true;
>  
> +	/* check for conflicts with the option */
> +	for (c = 0; c < MAX_CONFLICTS; c++) {
> +		int conflict_opt = sp->conflicts[c];
> +
> +		if (conflict_opt == LAST_CONFLICT)
> +			break;
> +		if (opts->subopt_params[conflict_opt].seen)
> +			conflict(opts->name, (char **)opts->subopts,
> +				 conflict_opt, index);
> +	}
> +
>  	/* empty strings might just return a default value */
>  	if (!str || *str == '\0') {
>  		if (sp->defaultval == SUBOPT_NEEDS_VAL)
> @@ -1607,17 +1699,11 @@ main(
>  				switch (getsubopt(&p, (constpp)subopts,
>  						  &value)) {
>  				case B_LOG:
> -					if (bsflag)
> -						conflict('b', subopts, B_SIZE,
> -							 B_LOG);
>  					blocklog = getnum(value, &bopts, B_LOG);
>  					blocksize = 1 << blocklog;
>  					blflag = 1;
>  					break;
>  				case B_SIZE:
> -					if (blflag)
> -						conflict('b', subopts, B_LOG,
> -							 B_SIZE);
>  					blocksize = getnum(value, &bopts,
>  							   B_SIZE);
>  					blocklog = libxfs_highbit32(blocksize);
> @@ -1666,61 +1752,29 @@ main(
>  					dsize = value;
>  					break;
>  				case D_SUNIT:
> -					if (nodsflag)
> -						conflict('d', subopts, D_NOALIGN,
> -							 D_SUNIT);
>  					dsunit = getnum(value, &dopts, D_SUNIT);
>  					break;
>  				case D_SWIDTH:
> -					if (nodsflag)
> -						conflict('d', subopts, D_NOALIGN,
> -							 D_SWIDTH);
>  					dswidth = getnum(value, &dopts,
>  							 D_SWIDTH);
>  					break;
>  				case D_SU:
> -					if (nodsflag)
> -						conflict('d', subopts, D_NOALIGN,
> -							 D_SU);
>  					dsu = getnum(value, &dopts, D_SU);
>  					break;
>  				case D_SW:
> -					if (nodsflag)
> -						conflict('d', subopts, D_NOALIGN,
> -							 D_SW);
>  					dsw = getnum(value, &dopts, D_SW);
>  					break;
>  				case D_NOALIGN:
>  					nodsflag = getnum(value, &dopts,
> -							 	D_NOALIGN);
> -					if (nodsflag) {
> -						if (dsu)
> -							conflict('d', subopts, D_SU,
> -								D_NOALIGN);
> -						if (dsunit)
> -							conflict('d', subopts, D_SUNIT,
> -								D_NOALIGN);
> -						if (dsw)
> -							conflict('d', subopts, D_SW,
>  								D_NOALIGN);
> -						if (dswidth)
> -							conflict('d', subopts, D_SWIDTH,
> -								D_NOALIGN);
> -					}
>  					break;
>  				case D_SECTLOG:
> -					if (ssflag)
> -						conflict('d', subopts, D_SECTSIZE,
> -							 D_SECTLOG);
>  					sectorlog = getnum(value, &dopts,
>  							   D_SECTLOG);
>  					sectorsize = 1 << sectorlog;
>  					slflag = 1;
>  					break;
>  				case D_SECTSIZE:
> -					if (slflag)
> -						conflict('d', subopts, D_SECTLOG,
> -							 D_SECTSIZE);
>  					sectorsize = getnum(value, &dopts,
>  							    D_SECTSIZE);
>  					sectorlog =
> @@ -1763,12 +1817,6 @@ main(
>  								&iopts, I_ALIGN);
>  					break;
>  				case I_LOG:
> -					if (ipflag)
> -						conflict('i', subopts, I_PERBLOCK,
> -							 I_LOG);
> -					if (isflag)
> -						conflict('i', subopts, I_SIZE,
> -							 I_LOG);
>  					inodelog = getnum(value, &iopts, I_LOG);
>  					isize = 1 << inodelog;
>  					ilflag = 1;
> @@ -1779,23 +1827,11 @@ main(
>  					imflag = 1;
>  					break;
>  				case I_PERBLOCK:
> -					if (ilflag)
> -						conflict('i', subopts, I_LOG,
> -							 I_PERBLOCK);
> -					if (isflag)
> -						conflict('i', subopts, I_SIZE,
> -							 I_PERBLOCK);
>  					inopblock = getnum(value, &iopts,
>  							   I_PERBLOCK);
>  					ipflag = 1;
>  					break;
>  				case I_SIZE:
> -					if (ilflag)
> -						conflict('i', subopts, I_LOG,
> -							 I_SIZE);
> -					if (ipflag)
> -						conflict('i', subopts, I_PERBLOCK,
> -							 I_SIZE);
>  					isize = getnum(value, &iopts, I_SIZE);
>  					inodelog = libxfs_highbit32(isize);
>  					isflag = 1;
> @@ -1810,9 +1846,8 @@ main(
>  							I_PROJID32BIT);
>  					break;
>  				case I_SPINODES:
> -					sb_feat.spinodes =
> -						getnum(value, &iopts,
> -								I_SPINODES);
> +					sb_feat.spinodes = getnum(value,
> +							&iopts, I_SPINODES);
>  					break;
>  				default:
>  					unknown('i', value);
> @@ -1828,8 +1863,6 @@ main(
>  				switch (getsubopt(&p, (constpp)subopts,
>  						  &value)) {
>  				case L_AGNUM:
> -					if (ldflag)
> -						conflict('l', subopts, L_AGNUM, L_DEV);
>  					logagno = getnum(value, &lopts, L_AGNUM);
>  					laflag = 1;
>  					break;
> @@ -1843,12 +1876,6 @@ main(
>  						xi.lcreat = 1;
>  					break;
>  				case L_INTERNAL:
> -					if (ldflag)
> -						conflict('l', subopts, L_INTERNAL, L_DEV);
> -					if (xi.lisfile)
> -						conflict('l', subopts, L_FILE,
> -							 L_INTERNAL);
> -
>  					loginternal = getnum(value, &lopts,
>  							     L_INTERNAL);
>  					liflag = 1;
> @@ -1890,18 +1917,12 @@ main(
>  					lsflag = 1;
>  					break;
>  				case L_SECTLOG:
> -					if (lssflag)
> -						conflict('l', subopts, L_SECTSIZE,
> -							 L_SECTLOG);
>  					lsectorlog = getnum(value, &lopts,
>  							    L_SECTLOG);
>  					lsectorsize = 1 << lsectorlog;
>  					lslflag = 1;
>  					break;
>  				case L_SECTSIZE:
> -					if (lslflag)
> -						conflict('l', subopts, L_SECTLOG,
> -							 L_SECTSIZE);
>  					lsectorsize = getnum(value, &lopts,
>  							     L_SECTSIZE);
>  					lsectorlog =
> @@ -1966,18 +1987,12 @@ _("cannot specify both -m crc=1 and -n ftype\n"));
>  				switch (getsubopt(&p, (constpp)subopts,
>  						  &value)) {
>  				case N_LOG:
> -					if (nsflag)
> -						conflict('n', subopts, N_SIZE,
> -							 N_LOG);
>  					dirblocklog = getnum(value, &nopts,
>  							     N_LOG);
>  					dirblocksize = 1 << dirblocklog;
>  					nlflag = 1;
>  					break;
>  				case N_SIZE:
> -					if (nlflag)
> -						conflict('n', subopts, N_LOG,
> -							 N_SIZE);
>  					dirblocksize = getnum(value, &nopts,
>  							      N_SIZE);
>  					dirblocklog =
> @@ -2083,7 +2098,7 @@ _("cannot specify both -m crc=1 and -n ftype\n"));
>  						  &value)) {
>  				case S_LOG:
>  				case S_SECTLOG:
> -					if (ssflag || lssflag)
> +					if (lssflag)
>  						conflict('s', subopts,
>  							 S_SECTSIZE, S_SECTLOG);
>  					sectorlog = getnum(value, &sopts,
> @@ -2095,7 +2110,7 @@ _("cannot specify both -m crc=1 and -n ftype\n"));
>  					break;
>  				case S_SIZE:
>  				case S_SECTSIZE:
> -					if (slflag || lslflag)
> +					if (lslflag)
>  						conflict('s', subopts, S_SECTLOG,
>  							 S_SECTSIZE);
>  					sectorsize = getnum(value, &sopts,
> @@ -2316,11 +2331,6 @@ _("warning: sparse inodes not supported without CRC support, disabled.\n"));
>  		dirblocksize = 1 << dirblocklog;
>  	}
>  
> -	if (daflag && dasize) {
> -		fprintf(stderr,
> -	_("both -d agcount= and agsize= specified, use one or the other\n"));
> -		usage();
> -	}
>  
>  	if (xi.disfile && (!dsize || !xi.dname)) {
>  		fprintf(stderr,
> 

_______________________________________________
xfs mailing list
xfs@oss.sgi.com
http://oss.sgi.com/mailman/listinfo/xfs

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

* [PATCH 13/19] mkfs: encode conflicts into parsing table
  2016-03-24 11:15 [PATCH 00/19] " jtulak
@ 2016-03-24 11:15 ` jtulak
  2016-04-07 22:40   ` Eric Sandeen
  0 siblings, 1 reply; 51+ messages in thread
From: jtulak @ 2016-03-24 11:15 UTC (permalink / raw)
  To: xfs

From: Dave Chinner <dchinner@redhat.com>

CHANGELOG:
o Add .conflicts init where it was missing
o Add explanation of a new member of opt_params struct.
o A long line fix.

Many options conflict, so we need to specify which options conflict
with each other in a generic manner. We already have a "seen"
variable used for respecification detection, so we can also use this
code conflict detection. Hence add a "conflicts" array to the sub
options parameter definition.

Signed-off-by: Dave Chinner <dchinner@redhat.com>
Signed-off-by: Jan Tulak <jtulak@redhat.com>
---
 mkfs/xfs_mkfs.c | 258 +++++++++++++++++++++++++++++---------------------------
 1 file changed, 134 insertions(+), 124 deletions(-)

diff --git a/mkfs/xfs_mkfs.c b/mkfs/xfs_mkfs.c
index 1f06110..d119580 100644
--- a/mkfs/xfs_mkfs.c
+++ b/mkfs/xfs_mkfs.c
@@ -54,6 +54,9 @@ unsigned int		sectorsize;
 
 #define MAX_SUBOPTS	16
 #define SUBOPT_NEEDS_VAL	(-1LL)
+#define MAX_CONFLICTS	8
+#define LAST_CONFLICT	(-1)
+
 /*
  * Table for parsing mkfs parameters.
  *
@@ -89,6 +92,11 @@ unsigned int		sectorsize;
  *     An optional flag for subopts where the given value has to be a power
  *     of two.
  *
+ *   conflicts MANDATORY
+ *     If your subopt is in a conflict with some other option, specify it.
+ *     Accepts the .index values of the conflicting subopts and the last
+ *     member of this list has to be LAST_CONFLICT.
+ *
  *   minval, maxval OPTIONAL
  *     These options are used for automatic range check and they have to be
  *     always used together in pair. If you don't want to limit the max value,
@@ -118,6 +126,7 @@ struct opt_params {
 		bool		seen;
 		bool		convert;
 		bool		is_power_2;
+		int		conflicts[MAX_CONFLICTS];
 		long long	minval;
 		long long	maxval;
 		long long	defaultval;
@@ -135,6 +144,8 @@ struct opt_params bopts = {
 	},
 	.subopt_params = {
 		{ .index = B_LOG,
+		  .conflicts = { B_SIZE,
+				 LAST_CONFLICT },
 		  .minval = XFS_MIN_BLOCKSIZE_LOG,
 		  .maxval = XFS_MAX_BLOCKSIZE_LOG,
 		  .defaultval = SUBOPT_NEEDS_VAL,
@@ -142,6 +153,8 @@ struct opt_params bopts = {
 		{ .index = B_SIZE,
 		  .convert = true,
 		  .is_power_2 = true,
+		  .conflicts = { B_LOG,
+				 LAST_CONFLICT },
 		  .minval = XFS_MIN_BLOCKSIZE,
 		  .maxval = XFS_MAX_BLOCKSIZE,
 		  .defaultval = SUBOPT_NEEDS_VAL,
@@ -186,57 +199,84 @@ struct opt_params dopts = {
 	},
 	.subopt_params = {
 		{ .index = D_AGCOUNT,
+		  .conflicts = { D_AGSIZE,
+				 LAST_CONFLICT },
 		  .minval = 1,
 		  .maxval = XFS_MAX_AGNUMBER,
 		  .defaultval = SUBOPT_NEEDS_VAL,
 		},
 		{ .index = D_FILE,
+		  .conflicts = { LAST_CONFLICT },
 		  .minval = 0,
 		  .maxval = 1,
 		  .defaultval = 1,
 		},
 		{ .index = D_NAME,
+		  .conflicts = { LAST_CONFLICT },
 		  .defaultval = SUBOPT_NEEDS_VAL,
 		},
 		{ .index = D_SIZE,
+		  .conflicts = { LAST_CONFLICT },
 		  .convert = true,
 		  .minval = XFS_AG_MIN_BYTES,
 		  .maxval = LLONG_MAX,
 		  .defaultval = SUBOPT_NEEDS_VAL,
 		},
 		{ .index = D_SUNIT,
+		  .conflicts = { D_NOALIGN,
+				 D_SU,
+				 D_SW,
+				 LAST_CONFLICT },
 		  .minval = 0,
 		  .maxval = UINT_MAX,
 		  .defaultval = SUBOPT_NEEDS_VAL,
 		},
 		{ .index = D_SWIDTH,
+		  .conflicts = { D_NOALIGN,
+				 D_SU,
+				 D_SW,
+				 LAST_CONFLICT },
 		  .minval = 0,
 		  .maxval = UINT_MAX,
 		  .defaultval = SUBOPT_NEEDS_VAL,
 		},
 		{ .index = D_AGSIZE,
+		  .conflicts = { D_AGCOUNT,
+				 LAST_CONFLICT },
 		  .convert = true,
 		  .minval = XFS_AG_MIN_BYTES,
 		  .maxval = XFS_AG_MAX_BYTES,
 		  .defaultval = SUBOPT_NEEDS_VAL,
 		},
 		{ .index = D_SU,
+		  .conflicts = { D_NOALIGN,
+				 D_SUNIT,
+				 D_SWIDTH,
+				 LAST_CONFLICT },
 		  .convert = true,
 		  .minval = 0,
 		  .maxval = UINT_MAX,
 		  .defaultval = SUBOPT_NEEDS_VAL,
 		},
 		{ .index = D_SW,
+		  .conflicts = { D_NOALIGN,
+				 D_SUNIT,
+				 D_SWIDTH,
+				 LAST_CONFLICT },
 		  .minval = 0,
 		  .maxval = UINT_MAX,
 		  .defaultval = SUBOPT_NEEDS_VAL,
 		},
 		{ .index = D_SECTLOG,
+		  .conflicts = { D_SECTSIZE,
+				 LAST_CONFLICT },
 		  .minval = XFS_MIN_SECTORSIZE_LOG,
 		  .maxval = XFS_MAX_SECTORSIZE_LOG,
 		  .defaultval = SUBOPT_NEEDS_VAL,
 		},
 		{ .index = D_SECTSIZE,
+		  .conflicts = { D_SECTLOG,
+				 LAST_CONFLICT },
 		  .convert = true,
 		  .is_power_2 = true,
 		  .minval = XFS_MIN_SECTORSIZE,
@@ -244,21 +284,29 @@ struct opt_params dopts = {
 		  .defaultval = SUBOPT_NEEDS_VAL,
 		},
 		{ .index = D_NOALIGN,
+		  .conflicts = { D_SU,
+				 D_SW,
+				 D_SUNIT,
+				 D_SWIDTH,
+				 LAST_CONFLICT },
 		  .minval = 0,
 		  .maxval = 1,
 		  .defaultval = 1,
 		},
 		{ .index = D_RTINHERIT,
+		  .conflicts = { LAST_CONFLICT },
 		  .minval = 1,
 		  .maxval = 1,
 		  .defaultval = 1,
 		},
 		{ .index = D_PROJINHERIT,
+		  .conflicts = { LAST_CONFLICT },
 		  .minval = 0,
 		  .maxval = UINT_MAX,
 		  .defaultval = SUBOPT_NEEDS_VAL,
 		},
 		{ .index = D_EXTSZINHERIT,
+		  .conflicts = { LAST_CONFLICT },
 		  .minval = 0,
 		  .maxval = UINT_MAX,
 		  .defaultval = SUBOPT_NEEDS_VAL,
@@ -290,43 +338,57 @@ struct opt_params iopts = {
 	},
 	.subopt_params = {
 		{ .index = I_ALIGN,
+		  .conflicts = { LAST_CONFLICT },
 		  .minval = 0,
 		  .maxval = 1,
 		  .defaultval = 1,
 		},
 		{ .index = I_LOG,
+		  .conflicts = { I_PERBLOCK,
+				 I_SIZE,
+				 LAST_CONFLICT },
 		  .minval = XFS_DINODE_MIN_LOG,
 		  .maxval = XFS_DINODE_MAX_LOG,
 		  .defaultval = SUBOPT_NEEDS_VAL,
 		},
 		{ .index = I_MAXPCT,
+		  .conflicts = { LAST_CONFLICT },
 		  .minval = 0,
 		  .maxval = 100,
 		  .defaultval = SUBOPT_NEEDS_VAL,
 		},
 		{ .index = I_PERBLOCK,
+		  .conflicts = { I_LOG,
+				 I_SIZE,
+				 LAST_CONFLICT },
 		  .is_power_2 = true,
 		  .minval = XFS_MIN_INODE_PERBLOCK,
 		  .maxval = XFS_MAX_BLOCKSIZE / XFS_DINODE_MIN_SIZE,
 		  .defaultval = SUBOPT_NEEDS_VAL,
 		},
 		{ .index = I_SIZE,
+		  .conflicts = { I_PERBLOCK,
+				 I_LOG,
+				 LAST_CONFLICT },
 		  .is_power_2 = true,
 		  .minval = XFS_DINODE_MIN_SIZE,
 		  .maxval = XFS_DINODE_MAX_SIZE,
 		  .defaultval = SUBOPT_NEEDS_VAL,
 		},
 		{ .index = I_ATTR,
+		  .conflicts = { LAST_CONFLICT },
 		  .minval = 0,
 		  .maxval = 2,
 		  .defaultval = SUBOPT_NEEDS_VAL,
 		},
 		{ .index = I_PROJID32BIT,
+		  .conflicts = { LAST_CONFLICT },
 		  .minval = 0,
 		  .maxval = 1,
 		  .defaultval = 1,
 		},
 		{ .index = I_SPINODES,
+		  .conflicts = { LAST_CONFLICT },
 		  .minval = 0,
 		  .maxval = 1,
 		  .defaultval = 1,
@@ -365,46 +427,64 @@ struct opt_params lopts = {
 	},
 	.subopt_params = {
 		{ .index = L_AGNUM,
+		  .conflicts = { L_DEV,
+				 LAST_CONFLICT },
 		  .minval = 0,
 		  .maxval = UINT_MAX,
 		  .defaultval = SUBOPT_NEEDS_VAL,
 		},
 		{ .index = L_INTERNAL,
+		  .conflicts = { L_FILE,
+				 L_DEV,
+				 LAST_CONFLICT },
 		  .minval = 0,
 		  .maxval = 1,
 		  .defaultval = 1,
 		},
 		{ .index = L_SIZE,
+		  .conflicts = { LAST_CONFLICT },
 		  .convert = true,
 		  .minval = 2 * 1024 * 1024LL,	/* XXX: XFS_MIN_LOG_BYTES */
 		  .maxval = XFS_MAX_LOG_BYTES,
 		  .defaultval = SUBOPT_NEEDS_VAL,
 		},
 		{ .index = L_VERSION,
+		  .conflicts = { LAST_CONFLICT },
 		  .minval = 1,
 		  .maxval = 2,
 		  .defaultval = SUBOPT_NEEDS_VAL,
 		},
 		{ .index = L_SUNIT,
+		  .conflicts = { L_SU,
+				 LAST_CONFLICT },
 		  .minval = BTOBB(XLOG_MIN_RECORD_BSIZE),
 		  .maxval = BTOBB(XLOG_MAX_RECORD_BSIZE),
 		  .defaultval = SUBOPT_NEEDS_VAL,
 		},
 		{ .index = L_SU,
+		  .conflicts = { L_SUNIT,
+				 LAST_CONFLICT },
 		  .convert = true,
 		  .minval = XLOG_MIN_RECORD_BSIZE,
 		  .maxval = UINT_MAX,
 		  .defaultval = SUBOPT_NEEDS_VAL,
 		},
 		{ .index = L_DEV,
+		  .conflicts = { L_AGNUM,
+				 L_INTERNAL,
+				 LAST_CONFLICT },
 		  .defaultval = SUBOPT_NEEDS_VAL,
 		},
 		{ .index = L_SECTLOG,
+		  .conflicts = { L_SECTSIZE,
+				 LAST_CONFLICT },
 		  .minval = XFS_MIN_SECTORSIZE_LOG,
 		  .maxval = XFS_MAX_SECTORSIZE_LOG,
 		  .defaultval = SUBOPT_NEEDS_VAL,
 		},
 		{ .index = L_SECTSIZE,
+		  .conflicts = { L_SECTLOG,
+				 LAST_CONFLICT },
 		  .convert = true,
 		  .is_power_2 = true,
 		  .minval = XFS_MIN_SECTORSIZE,
@@ -412,14 +492,20 @@ struct opt_params lopts = {
 		  .defaultval = SUBOPT_NEEDS_VAL,
 		},
 		{ .index = L_FILE,
+		  .conflicts = { L_INTERNAL,
+				 LAST_CONFLICT },
 		  .minval = 0,
 		  .maxval = 1,
 		  .defaultval = 1,
 		},
 		{ .index = L_NAME,
+		  .conflicts = { L_AGNUM,
+				 L_INTERNAL,
+				 LAST_CONFLICT },
 		  .defaultval = SUBOPT_NEEDS_VAL,
 		},
 		{ .index = L_LAZYSBCNTR,
+		  .conflicts = { LAST_CONFLICT },
 		  .minval = 0,
 		  .maxval = 1,
 		  .defaultval = 1,
@@ -442,11 +528,15 @@ struct opt_params nopts = {
 	},
 	.subopt_params = {
 		{ .index = N_LOG,
+		  .conflicts = { N_SIZE,
+				 LAST_CONFLICT },
 		  .minval = XFS_MIN_REC_DIRSIZE,
 		  .maxval = XFS_MAX_BLOCKSIZE_LOG,
 		  .defaultval = SUBOPT_NEEDS_VAL,
 		},
 		{ .index = N_SIZE,
+		  .conflicts = { N_LOG,
+				 LAST_CONFLICT },
 		  .convert = true,
 		  .is_power_2 = true,
 		  .minval = 1 << XFS_MIN_REC_DIRSIZE,
@@ -454,11 +544,13 @@ struct opt_params nopts = {
 		  .defaultval = SUBOPT_NEEDS_VAL,
 		},
 		{ .index = N_VERSION,
+		  .conflicts = { LAST_CONFLICT },
 		  .minval = 2,
 		  .maxval = 2,
 		  .defaultval = SUBOPT_NEEDS_VAL,
 		},
 		{ .index = N_FTYPE,
+		  .conflicts = { LAST_CONFLICT },
 		  .minval = 0,
 		  .maxval = 1,
 		  .defaultval = 1,
@@ -485,32 +577,38 @@ struct opt_params ropts = {
 	},
 	.subopt_params = {
 		{ .index = R_EXTSIZE,
+		  .conflicts = { LAST_CONFLICT },
 		  .convert = true,
 		  .minval = XFS_MIN_RTEXTSIZE,
 		  .maxval = XFS_MAX_RTEXTSIZE,
 		  .defaultval = SUBOPT_NEEDS_VAL,
 		},
 		{ .index = R_SIZE,
+		  .conflicts = { LAST_CONFLICT },
 		  .convert = true,
 		  .minval = 0,
 		  .maxval = LLONG_MAX,
 		  .defaultval = SUBOPT_NEEDS_VAL,
 		},
 		{ .index = R_DEV,
+		  .conflicts = { LAST_CONFLICT },
 		  .defaultval = SUBOPT_NEEDS_VAL,
 		},
 		{ .index = R_FILE,
 		  .minval = 0,
 		  .maxval = 1,
 		  .defaultval = 1,
+		  .conflicts = { LAST_CONFLICT },
 		},
 		{ .index = R_NAME,
+		  .conflicts = { LAST_CONFLICT },
 		  .defaultval = SUBOPT_NEEDS_VAL,
 		},
 		{ .index = R_NOALIGN,
 		  .minval = 0,
 		  .maxval = 1,
 		  .defaultval = 1,
+		  .conflicts = { LAST_CONFLICT },
 		},
 	},
 };
@@ -530,16 +628,25 @@ struct opt_params sopts = {
 	},
 	.subopt_params = {
 		{ .index = S_LOG,
+		  .conflicts = { S_SIZE,
+				 S_SECTSIZE,
+				 LAST_CONFLICT },
 		  .minval = XFS_MIN_SECTORSIZE_LOG,
 		  .maxval = XFS_MAX_SECTORSIZE_LOG,
 		  .defaultval = SUBOPT_NEEDS_VAL,
 		},
 		{ .index = S_SECTLOG,
+		  .conflicts = { S_SIZE,
+				 S_SECTSIZE,
+				 LAST_CONFLICT },
 		  .minval = XFS_MIN_SECTORSIZE_LOG,
 		  .maxval = XFS_MAX_SECTORSIZE_LOG,
 		  .defaultval = SUBOPT_NEEDS_VAL,
 		},
 		{ .index = S_SIZE,
+		  .conflicts = { S_LOG,
+				 S_SECTLOG,
+				 LAST_CONFLICT },
 		  .convert = true,
 		  .is_power_2 = true,
 		  .minval = XFS_MIN_SECTORSIZE,
@@ -547,6 +654,9 @@ struct opt_params sopts = {
 		  .defaultval = SUBOPT_NEEDS_VAL,
 		},
 		{ .index = S_SECTSIZE,
+		  .conflicts = { S_LOG,
+				 S_SECTLOG,
+				 LAST_CONFLICT },
 		  .convert = true,
 		  .is_power_2 = true,
 		  .minval = XFS_MIN_SECTORSIZE,
@@ -569,16 +679,19 @@ struct opt_params mopts = {
 	},
 	.subopt_params = {
 		{ .index = M_CRC,
+		  .conflicts = { LAST_CONFLICT },
 		  .minval = 0,
 		  .maxval = 1,
 		  .defaultval = 1,
 		},
 		{ .index = M_FINOBT,
+		  .conflicts = { LAST_CONFLICT },
 		  .minval = 0,
 		  .maxval = 1,
 		  .defaultval = 1,
 		},
 		{ .index = M_UUID,
+		  .conflicts = { LAST_CONFLICT },
 		  .defaultval = SUBOPT_NEEDS_VAL,
 		},
 	},
@@ -620,30 +733,14 @@ calc_stripe_factors(
 	int		*lsunit)
 {
 	/* Handle data sunit/swidth options */
-	if (*dsunit || *dswidth) {
-		if (dsu || dsw) {
-			fprintf(stderr,
-				_("data su/sw must not be used in "
-				"conjunction with data sunit/swidth\n"));
-			usage();
-		}
-
-		if ((*dsunit && !*dswidth) || (!*dsunit && *dswidth)) {
-			fprintf(stderr,
-				_("both data sunit and data swidth options "
-				"must be specified\n"));
-			usage();
-		}
+	if ((*dsunit && !*dswidth) || (!*dsunit && *dswidth)) {
+		fprintf(stderr,
+			_("both data sunit and data swidth options "
+			"must be specified\n"));
+		usage();
 	}
 
 	if (dsu || dsw) {
-		if (*dsunit || *dswidth) {
-			fprintf(stderr,
-				_("data sunit/swidth must not be used in "
-				"conjunction with data su/sw\n"));
-			usage();
-		}
-
 		if ((dsu && !dsw) || (!dsu && dsw)) {
 			fprintf(stderr,
 				_("both data su and data sw options "
@@ -671,24 +768,8 @@ calc_stripe_factors(
 
 	/* Handle log sunit options */
 
-	if (*lsunit) {
-		if (lsu) {
-			fprintf(stderr,
-				_("log su should not be used in "
-				"conjunction with log sunit\n"));
-			usage();
-		}
-	}
-
-	if (lsu) {
-		if (*lsunit) {
-			fprintf(stderr,
-				_("log sunit should not be used in "
-				"conjunction with log su\n"));
-			usage();
-		}
+	if (lsu)
 		*lsunit = (int)BTOBBT(lsu);
-	}
 }
 
 /*
@@ -1410,6 +1491,17 @@ getnum(
 		respec(opts->name, (char **)opts->subopts, index);
 	sp->seen = true;
 
+	/* check for conflicts with the option */
+	for (c = 0; c < MAX_CONFLICTS; c++) {
+		int conflict_opt = sp->conflicts[c];
+
+		if (conflict_opt == LAST_CONFLICT)
+			break;
+		if (opts->subopt_params[conflict_opt].seen)
+			conflict(opts->name, (char **)opts->subopts,
+				 conflict_opt, index);
+	}
+
 	/* empty strings might just return a default value */
 	if (!str || *str == '\0') {
 		if (sp->defaultval == SUBOPT_NEEDS_VAL)
@@ -1607,17 +1699,11 @@ main(
 				switch (getsubopt(&p, (constpp)subopts,
 						  &value)) {
 				case B_LOG:
-					if (bsflag)
-						conflict('b', subopts, B_SIZE,
-							 B_LOG);
 					blocklog = getnum(value, &bopts, B_LOG);
 					blocksize = 1 << blocklog;
 					blflag = 1;
 					break;
 				case B_SIZE:
-					if (blflag)
-						conflict('b', subopts, B_LOG,
-							 B_SIZE);
 					blocksize = getnum(value, &bopts,
 							   B_SIZE);
 					blocklog = libxfs_highbit32(blocksize);
@@ -1666,61 +1752,29 @@ main(
 					dsize = value;
 					break;
 				case D_SUNIT:
-					if (nodsflag)
-						conflict('d', subopts, D_NOALIGN,
-							 D_SUNIT);
 					dsunit = getnum(value, &dopts, D_SUNIT);
 					break;
 				case D_SWIDTH:
-					if (nodsflag)
-						conflict('d', subopts, D_NOALIGN,
-							 D_SWIDTH);
 					dswidth = getnum(value, &dopts,
 							 D_SWIDTH);
 					break;
 				case D_SU:
-					if (nodsflag)
-						conflict('d', subopts, D_NOALIGN,
-							 D_SU);
 					dsu = getnum(value, &dopts, D_SU);
 					break;
 				case D_SW:
-					if (nodsflag)
-						conflict('d', subopts, D_NOALIGN,
-							 D_SW);
 					dsw = getnum(value, &dopts, D_SW);
 					break;
 				case D_NOALIGN:
 					nodsflag = getnum(value, &dopts,
-							 	D_NOALIGN);
-					if (nodsflag) {
-						if (dsu)
-							conflict('d', subopts, D_SU,
-								D_NOALIGN);
-						if (dsunit)
-							conflict('d', subopts, D_SUNIT,
-								D_NOALIGN);
-						if (dsw)
-							conflict('d', subopts, D_SW,
 								D_NOALIGN);
-						if (dswidth)
-							conflict('d', subopts, D_SWIDTH,
-								D_NOALIGN);
-					}
 					break;
 				case D_SECTLOG:
-					if (ssflag)
-						conflict('d', subopts, D_SECTSIZE,
-							 D_SECTLOG);
 					sectorlog = getnum(value, &dopts,
 							   D_SECTLOG);
 					sectorsize = 1 << sectorlog;
 					slflag = 1;
 					break;
 				case D_SECTSIZE:
-					if (slflag)
-						conflict('d', subopts, D_SECTLOG,
-							 D_SECTSIZE);
 					sectorsize = getnum(value, &dopts,
 							    D_SECTSIZE);
 					sectorlog =
@@ -1763,12 +1817,6 @@ main(
 								&iopts, I_ALIGN);
 					break;
 				case I_LOG:
-					if (ipflag)
-						conflict('i', subopts, I_PERBLOCK,
-							 I_LOG);
-					if (isflag)
-						conflict('i', subopts, I_SIZE,
-							 I_LOG);
 					inodelog = getnum(value, &iopts, I_LOG);
 					isize = 1 << inodelog;
 					ilflag = 1;
@@ -1779,23 +1827,11 @@ main(
 					imflag = 1;
 					break;
 				case I_PERBLOCK:
-					if (ilflag)
-						conflict('i', subopts, I_LOG,
-							 I_PERBLOCK);
-					if (isflag)
-						conflict('i', subopts, I_SIZE,
-							 I_PERBLOCK);
 					inopblock = getnum(value, &iopts,
 							   I_PERBLOCK);
 					ipflag = 1;
 					break;
 				case I_SIZE:
-					if (ilflag)
-						conflict('i', subopts, I_LOG,
-							 I_SIZE);
-					if (ipflag)
-						conflict('i', subopts, I_PERBLOCK,
-							 I_SIZE);
 					isize = getnum(value, &iopts, I_SIZE);
 					inodelog = libxfs_highbit32(isize);
 					isflag = 1;
@@ -1810,9 +1846,8 @@ main(
 							I_PROJID32BIT);
 					break;
 				case I_SPINODES:
-					sb_feat.spinodes =
-						getnum(value, &iopts,
-								I_SPINODES);
+					sb_feat.spinodes = getnum(value,
+							&iopts, I_SPINODES);
 					break;
 				default:
 					unknown('i', value);
@@ -1828,8 +1863,6 @@ main(
 				switch (getsubopt(&p, (constpp)subopts,
 						  &value)) {
 				case L_AGNUM:
-					if (ldflag)
-						conflict('l', subopts, L_AGNUM, L_DEV);
 					logagno = getnum(value, &lopts, L_AGNUM);
 					laflag = 1;
 					break;
@@ -1843,12 +1876,6 @@ main(
 						xi.lcreat = 1;
 					break;
 				case L_INTERNAL:
-					if (ldflag)
-						conflict('l', subopts, L_INTERNAL, L_DEV);
-					if (xi.lisfile)
-						conflict('l', subopts, L_FILE,
-							 L_INTERNAL);
-
 					loginternal = getnum(value, &lopts,
 							     L_INTERNAL);
 					liflag = 1;
@@ -1890,18 +1917,12 @@ main(
 					lsflag = 1;
 					break;
 				case L_SECTLOG:
-					if (lssflag)
-						conflict('l', subopts, L_SECTSIZE,
-							 L_SECTLOG);
 					lsectorlog = getnum(value, &lopts,
 							    L_SECTLOG);
 					lsectorsize = 1 << lsectorlog;
 					lslflag = 1;
 					break;
 				case L_SECTSIZE:
-					if (lslflag)
-						conflict('l', subopts, L_SECTLOG,
-							 L_SECTSIZE);
 					lsectorsize = getnum(value, &lopts,
 							     L_SECTSIZE);
 					lsectorlog =
@@ -1966,18 +1987,12 @@ _("cannot specify both -m crc=1 and -n ftype\n"));
 				switch (getsubopt(&p, (constpp)subopts,
 						  &value)) {
 				case N_LOG:
-					if (nsflag)
-						conflict('n', subopts, N_SIZE,
-							 N_LOG);
 					dirblocklog = getnum(value, &nopts,
 							     N_LOG);
 					dirblocksize = 1 << dirblocklog;
 					nlflag = 1;
 					break;
 				case N_SIZE:
-					if (nlflag)
-						conflict('n', subopts, N_LOG,
-							 N_SIZE);
 					dirblocksize = getnum(value, &nopts,
 							      N_SIZE);
 					dirblocklog =
@@ -2083,7 +2098,7 @@ _("cannot specify both -m crc=1 and -n ftype\n"));
 						  &value)) {
 				case S_LOG:
 				case S_SECTLOG:
-					if (ssflag || lssflag)
+					if (lssflag)
 						conflict('s', subopts,
 							 S_SECTSIZE, S_SECTLOG);
 					sectorlog = getnum(value, &sopts,
@@ -2095,7 +2110,7 @@ _("cannot specify both -m crc=1 and -n ftype\n"));
 					break;
 				case S_SIZE:
 				case S_SECTSIZE:
-					if (slflag || lslflag)
+					if (lslflag)
 						conflict('s', subopts, S_SECTLOG,
 							 S_SECTSIZE);
 					sectorsize = getnum(value, &sopts,
@@ -2316,11 +2331,6 @@ _("warning: sparse inodes not supported without CRC support, disabled.\n"));
 		dirblocksize = 1 << dirblocklog;
 	}
 
-	if (daflag && dasize) {
-		fprintf(stderr,
-	_("both -d agcount= and agsize= specified, use one or the other\n"));
-		usage();
-	}
 
 	if (xi.disfile && (!dsize || !xi.dname)) {
 		fprintf(stderr,
-- 
2.6.0

_______________________________________________
xfs mailing list
xfs@oss.sgi.com
http://oss.sgi.com/mailman/listinfo/xfs

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

end of thread, other threads:[~2016-06-06  7:43 UTC | newest]

Thread overview: 51+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2016-04-21  9:39 [PATCH 00/19 v2] mkfs cleaning Jan Tulak
2016-04-21  9:39 ` [PATCH 01/19] xfsprogs: use common code for multi-disk detection Jan Tulak
2016-04-21  9:39 ` [PATCH 02/19] mkfs: sanitise ftype parameter values Jan Tulak
2016-04-21  9:39 ` [PATCH 03/19] mkfs: Sanitise the superblock feature macros Jan Tulak
2016-05-02 23:06   ` Eric Sandeen
2016-05-04  0:48     ` Eric Sandeen
2016-04-21  9:39 ` [PATCH 04/19] mkfs: validate all input values Jan Tulak
2016-04-21  9:39 ` [PATCH 05/19] mkfs: factor boolean option parsing Jan Tulak
2016-04-21  9:39 ` [PATCH 06/19] mkfs: validate logarithmic parameters sanely Jan Tulak
2016-04-21  9:39 ` [PATCH 07/19] mkfs: structify input parameter passing Jan Tulak
2016-04-21  9:39 ` [PATCH 08/19] mkfs: getbool is redundant Jan Tulak
2016-05-02 23:08   ` Eric Sandeen
2016-04-21  9:39 ` [PATCH 09/19] mkfs: use getnum_checked for all ranged parameters Jan Tulak
2016-04-21  9:39 ` [PATCH 10/19] mkfs: add respecification detection to generic parsing Jan Tulak
2016-04-21  9:39 ` [PATCH 11/19] mkfs: table based parsing for converted parameters Jan Tulak
2016-05-02 23:09   ` Eric Sandeen
2016-04-21  9:39 ` [PATCH 12/19] mkfs: merge getnum Jan Tulak
2016-04-21  9:39 ` [PATCH 13/19] mkfs: encode conflicts into parsing table Jan Tulak
2016-05-02 23:11   ` Eric Sandeen
2016-05-03 23:39   ` Eric Sandeen
2016-05-04  0:47     ` Eric Sandeen
2016-04-21  9:39 ` [PATCH 14/19] mkfs: add string options to generic parsing Jan Tulak
2016-05-02 23:11   ` Eric Sandeen
2016-04-21  9:39 ` [PATCH 15/19] mkfs: don't treat files as though they are block devices Jan Tulak
2016-04-21 12:43   ` Jan Tulak
2016-04-21 20:13     ` Eric Sandeen
2016-04-22  7:46       ` Jan Tulak
2016-04-22  7:49   ` [PATCH 15/19 v2] " Jan Tulak
2016-04-29 14:47     ` [PATCH 15/19 v3] " Jan Tulak
2016-04-29 19:11       ` Eric Sandeen
2016-05-03  9:59         ` Jan Tulak
2016-05-02 23:13   ` [PATCH 15/19] " Eric Sandeen
2016-04-21  9:39 ` [PATCH 16/19] mkfs: move spinodes crc check Jan Tulak
2016-04-21  9:39 ` [PATCH 17/19] mkfs: unit conversions are case insensitive Jan Tulak
2016-04-21  9:39 ` [PATCH 18/19] mkfs: add optional 'reason' for illegal_option Jan Tulak
2016-04-21  9:39 ` [PATCH 19/19] mkfs: conflicting values with disabled crc should fail Jan Tulak
2016-04-28  8:29 ` [RFC PATCH] xfstests: Add mkfs input validation tests Jan Tulak
2016-04-28  8:29   ` Jan Tulak
2016-04-29  1:59   ` Dave Chinner
2016-04-29  1:59     ` Dave Chinner
2016-04-29 14:42     ` Jan Tulak
2016-05-02 23:05 ` [PATCH 00/19 v2] mkfs cleaning Eric Sandeen
2016-05-10  6:10 ` Dave Chinner
2016-06-01 13:19   ` Jan Tulak
2016-06-03  0:53     ` Dave Chinner
2016-06-03  9:20       ` Jan Tulak
2016-06-03 12:09         ` Jan Tulak
2016-06-04  0:32           ` Dave Chinner
2016-06-06  7:42             ` Jan Tulak
  -- strict thread matches above, loose matches on Subject: below --
2016-03-24 11:15 [PATCH 00/19] " jtulak
2016-03-24 11:15 ` [PATCH 13/19] mkfs: encode conflicts into parsing table jtulak
2016-04-07 22:40   ` Eric Sandeen

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.