All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH 00/19] mkfs cleaning
@ 2016-03-24 11:15 jtulak
  2016-03-24 11:15 ` [PATCH 01/19] xfsprogs: use common code for multi-disk detection jtulak
                   ` (18 more replies)
  0 siblings, 19 replies; 84+ messages in thread
From: jtulak @ 2016-03-24 11:15 UTC (permalink / raw)
  To: xfs

From: Jan Tulak <jtulak@redhat.com>

Hi guys,
a new iteration of this patchset after a long time.

(Jump down to the quote of the original post from Dave who started this set.)

I tried to solve all the issues you mentioned the last time (thanks for them!)
and I went also through more intense testing. As far as I'm aware, the only
few occassions where xfstests currently fails with this patchset is because
I fixed some wrong/not ideal behaviour in the original code. It should be
clean also from Coverity's point of view.

Some tests which now fails and will need a change are xfs/078, 206, 216
and 217. See "[PATCH 15/19] mkfs: don't treat files as though they are block
devices" for more details

Each specific patch has a changelog of the things chaged in it since the last
version.

I hope that this patchset is getting into a reasonable form. While it doesn't
clean everything, it greately cleans some parts of mkfs and fixes some issues.


And to remind what this patchset is about, here is the original Dave's email.

> Hi folks,
>␣
> This is still a work in progress, but is compelte enough to get
> feedback on the general structure. The problem being solved here is
> that mkfs does a terrible job of input validation from the command
> line, has huge amounts of repeated code in the sub options
> processing loops and has many, many unnecessary variable for
> tracking simply things like whether a parameter was specified.
>␣
> This patchset introduces a parameter table structure that is used to
> define the parameters and their constraints. Things like minimum and
> maximum valid values, default values, conflicting options, etc are
> all contained within the table, so all the "policy" is found in a
> single place.
>␣
> This greatly reduces the complexity of the option parsing loop. It
> doesn't remove all the complexity (yet) because many of the options
> have special cases or more complex conflicts than I've yet added
> support for. The idea is, however, that all of the sub-option
> parameter setup will eventually end up being implemented as a
> generic loop as the parameter structure will hold all the
> information about in the input parameters.
>␣
> To get there, the parameter table still needs more work - it needs
> to hold the value/string for the parameter, and we need to reference
> those in the code.
>␣
> The flow on effect of this is that we can remove the many, many
> individual variables and start passing the option structures to
> functions rather than avoiding using functions because passing so
> many variables is messy and nasty. IOWs, it lays the groundwork for
> factoring xfs_mkfs.c into something more than a bunch of spagetti...
>␣
> Anyway, have a look and see what you think about progress so far.
>␣
> FWIW, the first patch is following up on the multi-disk discussion
> Christoph and I had, and the last patch in the series covers all the
> issues that arose with "-d file" and treating files like block
> devices....
>␣
> Cheers,
>␣
> Dave.


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
  xfsprogs: disable truncating of files
  mkfs: unit conversions are case insensitive
  mkfs: add optional 'reason' for illegal_option


 include/Makefile        |    5 +-
 include/xfs_multidisk.h |   73 ++
 libxfs/init.c           |   14 +-
 libxfs/linux.c          |   12 +-
 man/man8/mkfs.xfs.8     |   37 +-
 mkfs/Makefile           |    2 +-
 mkfs/maxtrres.c         |    2 +-
 mkfs/proto.c            |   58 +-
 mkfs/xfs_mkfs.c         | 2003 +++++++++++++++++++++++++++++------------------
 mkfs/xfs_mkfs.h         |   89 ---
 repair/xfs_repair.c     |   44 +-
 11 files changed, 1437 insertions(+), 902 deletions(-)
 create mode 100644 include/xfs_multidisk.h
 delete mode 100644 mkfs/xfs_mkfs.h

-- 
2.6.0

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

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

* [PATCH 01/19] xfsprogs: use common code for multi-disk detection
  2016-03-24 11:15 [PATCH 00/19] mkfs cleaning jtulak
@ 2016-03-24 11:15 ` jtulak
  2016-03-31 20:25   ` Eric Sandeen
  2016-03-24 11:15 ` [PATCH 02/19] mkfs: sanitise ftype parameter values jtulak
                   ` (17 subsequent siblings)
  18 siblings, 1 reply; 84+ messages in thread
From: jtulak @ 2016-03-24 11:15 UTC (permalink / raw)
  To: xfs

From: Dave Chinner <dchinner@redhat.com>

CHANGELOG:
o Remove nonexistent headers from LIBHFILES in include/Makefile
o Remove a useless assignment which was immediately overwritten
  on the next line.
o Rename include/xfs_mkfs.h global header to include/xfs_multidisk.h,
  because we need it just for multidisk configuration
o Fix AG count for size thresholds to keep consistency

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>
---
 include/Makefile        |  5 ++-
 include/xfs_multidisk.h | 98 +++++++++++++++++++++++++++++++++++++++++++++++++
 mkfs/Makefile           |  2 +-
 mkfs/maxtrres.c         |  2 +-
 mkfs/proto.c            |  2 +-
 mkfs/xfs_mkfs.c         | 56 ++++++++++++++--------------
 mkfs/xfs_mkfs.h         | 89 --------------------------------------------
 repair/xfs_repair.c     | 44 +++++++++++++++++++++-
 8 files changed, 176 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..4006a01
--- /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 avoid 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 21960d5..50d5e94 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..36e5b4f 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,45 @@ 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 between 128MB and 4TB in size
+	 * 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.6.0

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

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

* [PATCH 02/19] mkfs: sanitise ftype parameter values.
  2016-03-24 11:15 [PATCH 00/19] mkfs cleaning jtulak
  2016-03-24 11:15 ` [PATCH 01/19] xfsprogs: use common code for multi-disk detection jtulak
@ 2016-03-24 11:15 ` jtulak
  2016-03-24 16:33   ` Eric Sandeen
  2016-03-24 11:15 ` [PATCH 03/19] mkfs: Sanitise the superblock feature macros jtulak
                   ` (16 subsequent siblings)
  18 siblings, 1 reply; 84+ messages in thread
From: jtulak @ 2016-03-24 11:15 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>
Reviewed-by: Brian Foster <bfoster@redhat.com>
---
 mkfs/xfs_mkfs.c | 10 +++++++++-
 1 file changed, 9 insertions(+), 1 deletion(-)

diff --git a/mkfs/xfs_mkfs.c b/mkfs/xfs_mkfs.c
index 36e5b4f..979a860 100644
--- a/mkfs/xfs_mkfs.c
+++ b/mkfs/xfs_mkfs.c
@@ -1596,7 +1596,15 @@ 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");
+					if (crcs_enabled) {
+						fprintf(stderr,
+_("cannot specify both crc and ftype\n"));
+						usage();
+					}
+					dirftype = c;
 					nftype = 1;
 					break;
 				default:
-- 
2.6.0

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

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

* [PATCH 03/19] mkfs: Sanitise the superblock feature macros
  2016-03-24 11:15 [PATCH 00/19] mkfs cleaning jtulak
  2016-03-24 11:15 ` [PATCH 01/19] xfsprogs: use common code for multi-disk detection jtulak
  2016-03-24 11:15 ` [PATCH 02/19] mkfs: sanitise ftype parameter values jtulak
@ 2016-03-24 11:15 ` jtulak
  2016-04-01  2:05   ` Eric Sandeen
                     ` (2 more replies)
  2016-03-24 11:15 ` [PATCH 04/19] mkfs: validate all input values jtulak
                   ` (15 subsequent siblings)
  18 siblings, 3 replies; 84+ messages in thread
From: jtulak @ 2016-03-24 11:15 UTC (permalink / raw)
  To: xfs

From: Dave Chinner <dchinner@redhat.com>

UPDATE
o disable finobt when crc=0 no matter if user used -m finobt=X
o split line > 80 chars
o remove unused variable
o add omitted finobtflag
o change variables in spinodes case to look like surrounding code
o add I_ALIGN reqval

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>
---
 include/xfs_multidisk.h |  25 +---
 mkfs/xfs_mkfs.c         | 320 ++++++++++++++++++++++++++++++------------------
 2 files changed, 199 insertions(+), 146 deletions(-)

diff --git a/include/xfs_multidisk.h b/include/xfs_multidisk.h
index 4006a01..64d80e1 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 979a860..36bcb9f 100644
--- a/mkfs/xfs_mkfs.c
+++ b/mkfs/xfs_mkfs.c
@@ -879,6 +879,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,
@@ -890,8 +993,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;
@@ -906,8 +1007,6 @@ main(
 	char			*dfile;
 	int			dirblocklog;
 	int			dirblocksize;
-	int			dirftype;
-	int			dirversion;
 	char			*dsize;
 	int			dsu;
 	int			dsw;
@@ -915,7 +1014,6 @@ main(
 	int			dswidth;
 	int			force_overwrite;
 	struct fsxattr		fsx;
-	int			iaflag;
 	int			ilflag;
 	int			imaxpct;
 	int			imflag;
@@ -935,7 +1033,6 @@ main(
 	int			loginternal;
 	char			*logsize;
 	xfs_fsblock_t		logstart;
-	int			logversion;
 	int			lvflag;
 	int			lsflag;
 	int			lsuflag;
@@ -957,7 +1054,6 @@ main(
 	int			nftype;
 	int			nsflag;
 	int			nvflag;
-	int			nci;
 	int			Nflag;
 	int			discard = 1;
 	char			*p;
@@ -981,11 +1077,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]);
@@ -993,8 +1099,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;
@@ -1003,27 +1107,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));
@@ -1262,10 +1358,11 @@ main(
 				switch (getsubopt(&p, (constpp)iopts, &value)) {
 				case I_ALIGN:
 					if (!value || *value == '\0')
-						value = "1";
-					iaflag = atoi(value);
-					if (iaflag < 0 || iaflag > 1)
+						reqval('i', iopts, I_ALIGN);
+					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')
@@ -1335,7 +1432,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')
@@ -1343,14 +1440,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);
@@ -1442,9 +1540,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:
@@ -1493,7 +1592,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);
@@ -1517,7 +1617,14 @@ main(
 					c = atoi(value);
 					if (c < 0 || c > 1)
 						illegal(value, "m crc");
-					crcs_enabled = c;
+					if (c && nftype) {
+						fprintf(stderr,
+_("cannot specify both crc and ftype\n"));
+						usage();
+					}
+					sb_feat.crcs_enabled = c ? true : false;
+					if (c)
+						sb_feat.dirftype = true;
 					break;
 				case M_FINOBT:
 					if (!value || *value == '\0')
@@ -1525,8 +1632,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')
@@ -1582,12 +1689,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;
@@ -1599,12 +1708,12 @@ main(
 					c = atoi(value);
 					if (c < 0 || c > 1)
 						illegal(value, "n ftype");
-					if (crcs_enabled) {
+					if (sb_feat.crcs_enabled) {
 						fprintf(stderr,
 _("cannot specify both crc and ftype\n"));
 						usage();
 					}
-					dirftype = c;
+					sb_feat.dirftype = c ? true : false;
 					nftype = 1;
 					break;
 				default:
@@ -1753,13 +1862,13 @@ _("cannot specify both crc and ftype\n"));
 		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();
 	}
@@ -1824,7 +1933,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;
 	}
 
 	/*
@@ -1832,7 +1941,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,
@@ -1842,28 +1951,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();
@@ -1871,7 +1980,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();
@@ -1879,23 +1988,25 @@ _("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.
+		 * 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 a warning before turning
+		 * them off.
 		 */
-		if (finobt && finobtflag) {
-			fprintf(stderr,
-_("warning: finobt not supported without CRC support, disabled.\n"));
+		if (sb_feat.finobt){
+			if (sb_feat.finobtflag) {
+				fprintf(stderr,
+	_("warning: finobt not supported without CRC support, disabled.\n"));
+			}
+			sb_feat.finobt = 0;
 		}
-		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) {
@@ -1945,11 +2056,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);
@@ -2079,10 +2190,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,
@@ -2397,12 +2508,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,
@@ -2414,9 +2525,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)
@@ -2494,25 +2605,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) {
 		/*
@@ -2564,14 +2658,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"
@@ -2584,13 +2670,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)
@@ -2634,17 +2723,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) {
@@ -2655,19 +2744,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);
@@ -2723,8 +2800,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) {
@@ -2829,7 +2905,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);
 		}
@@ -2962,7 +3038,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.6.0

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

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

* [PATCH 04/19] mkfs: validate all input values
  2016-03-24 11:15 [PATCH 00/19] mkfs cleaning jtulak
                   ` (2 preceding siblings ...)
  2016-03-24 11:15 ` [PATCH 03/19] mkfs: Sanitise the superblock feature macros jtulak
@ 2016-03-24 11:15 ` jtulak
  2016-04-06 23:02   ` Eric Sandeen
  2016-03-24 11:15 ` [PATCH 05/19] mkfs: factor boolean option parsing jtulak
                   ` (14 subsequent siblings)
  18 siblings, 1 reply; 84+ messages in thread
From: jtulak @ 2016-03-24 11:15 UTC (permalink / raw)
  To: xfs

From: Dave Chinner <dchinner@redhat.com>

CHANGELOG
o Fix an unsigned < 0 comparison - save getnum result to another variable
  and test it, before converting it to unsigned logagno.

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>
---
 include/xfs_multidisk.h |   7 +-
 man/man8/mkfs.xfs.8     |  26 +++++-
 mkfs/proto.c            |  36 ++++----
 mkfs/xfs_mkfs.c         | 217 +++++++++++++++++++++++++-----------------------
 4 files changed, 155 insertions(+), 131 deletions(-)

diff --git a/include/xfs_multidisk.h b/include/xfs_multidisk.h
index 64d80e1..af35100 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 50d5e94..5930af8 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 36bcb9f..4811d77 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
  */
@@ -982,6 +985,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,
@@ -1101,8 +1126,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;
@@ -1146,7 +1171,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;
@@ -1160,8 +1185,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");
@@ -1184,8 +1209,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;
@@ -1195,14 +1219,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)
@@ -1230,13 +1256,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')
@@ -1246,13 +1268,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')
@@ -1262,8 +1280,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')
@@ -1273,13 +1293,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)
@@ -1304,7 +1320,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;
@@ -1318,8 +1334,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");
@@ -1359,7 +1375,7 @@ main(
 				case I_ALIGN:
 					if (!value || *value == '\0')
 						reqval('i', iopts, I_ALIGN);
-					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;
@@ -1375,7 +1391,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;
@@ -1386,7 +1402,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;
@@ -1402,7 +1418,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))
@@ -1420,7 +1436,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);
@@ -1429,7 +1445,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;
@@ -1437,7 +1453,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;
@@ -1459,6 +1475,7 @@ main(
 			p = optarg;
 			while (*p != '\0') {
 				char	*value;
+				long long tmp_num;
 
 				switch (getsubopt(&p, (constpp)lopts, &value)) {
 				case L_AGNUM:
@@ -1468,7 +1485,10 @@ main(
 						respec('l', lopts, L_AGNUM);
 					if (ldflag)
 						conflict('l', lopts, L_AGNUM, L_DEV);
-					logagno = atoi(value);
+					tmp_num = getnum(value, 0, 0, false);
+					if (tmp_num < 0)
+						illegal(value, "l agno");
+					logagno = (xfs_agnumber_t)tmp_num;
 					laflag = 1;
 					break;
 				case L_FILE:
@@ -1477,7 +1497,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)
@@ -1493,7 +1513,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;
@@ -1503,8 +1523,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:
@@ -1512,12 +1534,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:
@@ -1540,7 +1559,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;
@@ -1562,7 +1581,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;
@@ -1576,8 +1595,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");
@@ -1589,7 +1608,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
@@ -1614,7 +1633,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");
 					if (c && nftype) {
@@ -1660,7 +1679,7 @@ _("cannot specify both crc and ftype\n"));
 					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;
@@ -1674,8 +1693,8 @@ _("cannot specify both crc and ftype\n"));
 					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");
@@ -1692,7 +1711,7 @@ _("cannot specify both crc and ftype\n"));
 						/* ASCII CI mode */
 						sb_feat.nci = true;
 					} else {
-						c = atoi(value);
+						c = getnum(value, 0, 0, false);
 						if (c != 2)
 							illegal(value,
 								"n version");
@@ -1705,7 +1724,7 @@ _("cannot specify both crc and ftype\n"));
 						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");
 					if (sb_feat.crcs_enabled) {
@@ -1751,7 +1770,7 @@ _("cannot specify both crc and ftype\n"));
 				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)
@@ -1795,7 +1814,7 @@ _("cannot specify both crc and ftype\n"));
 					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;
@@ -1812,8 +1831,8 @@ _("cannot specify both crc and ftype\n"));
 					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");
@@ -1873,6 +1892,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);
 
@@ -2038,7 +2066,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"),
@@ -2075,7 +2105,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"),
@@ -2097,7 +2129,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"),
@@ -2117,7 +2151,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"),
@@ -3230,28 +3266,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;
@@ -3262,17 +3281,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.6.0

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

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

* [PATCH 05/19] mkfs: factor boolean option parsing
  2016-03-24 11:15 [PATCH 00/19] mkfs cleaning jtulak
                   ` (3 preceding siblings ...)
  2016-03-24 11:15 ` [PATCH 04/19] mkfs: validate all input values jtulak
@ 2016-03-24 11:15 ` jtulak
  2016-04-07  2:48   ` Eric Sandeen
  2016-03-24 11:15 ` [PATCH 06/19] mkfs: validate logarithmic parameters sanely jtulak
                   ` (13 subsequent siblings)
  18 siblings, 1 reply; 84+ messages in thread
From: jtulak @ 2016-03-24 11:15 UTC (permalink / raw)
  To: xfs

From: Dave Chinner <dchinner@redhat.com>

UPDATE:
- add a forgotten getbool update to FINOBT
- change -m crc and ftype to enable by specifying (instead of toggle off)

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>
---
 mkfs/xfs_mkfs.c | 109 +++++++++++++++++++++++---------------------------------
 1 file changed, 44 insertions(+), 65 deletions(-)

diff --git a/mkfs/xfs_mkfs.c b/mkfs/xfs_mkfs.c
index 4811d77..9394bd3 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);
@@ -1006,6 +1006,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(
@@ -1226,11 +1241,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;
@@ -1373,12 +1385,8 @@ main(

 				switch (getsubopt(&p, (constpp)iopts, &value)) {
 				case I_ALIGN:
-					if (!value || *value == '\0')
-						reqval('i', iopts, I_ALIGN);
-					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')
@@ -1451,12 +1459,8 @@ 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')
@@ -1492,20 +1496,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)
@@ -1513,9 +1512,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:
@@ -1605,14 +1604,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);
@@ -1631,28 +1625,20 @@ 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");
-					if (c && nftype) {
+					sb_feat.crcs_enabled = getbool(
+							value, "m crc", true);
+					if (sb_feat.crcs_enabled && nftype) {
 						fprintf(stderr,
-_("cannot specify both crc and ftype\n"));
+_("cannot specify both -m crc=1 and -n ftype\n"));
 						usage();
 					}
-					sb_feat.crcs_enabled = c ? true : false;
-					if (c)
+					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')
@@ -1720,19 +1706,15 @@ _("cannot specify both crc and ftype\n"));
 					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");
 					if (sb_feat.crcs_enabled) {
 						fprintf(stderr,
-_("cannot specify both crc and ftype\n"));
+_("cannot specify both -m crc=1 and -n ftype\n"));
 						usage();
 					}
-					sb_feat.dirftype = c ? true : false;
+					sb_feat.dirftype = getbool(value,
+							     "n ftype", true);
 					nftype = 1;
 					break;
 				default:
@@ -1768,11 +1750,8 @@ _("cannot specify both crc and ftype\n"));
 					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;
@@ -3220,8 +3199,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.6.0

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

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

* [PATCH 06/19] mkfs: validate logarithmic parameters sanely
  2016-03-24 11:15 [PATCH 00/19] mkfs cleaning jtulak
                   ` (4 preceding siblings ...)
  2016-03-24 11:15 ` [PATCH 05/19] mkfs: factor boolean option parsing jtulak
@ 2016-03-24 11:15 ` jtulak
  2016-04-07  2:52   ` Eric Sandeen
  2016-03-24 11:15 ` [PATCH 07/19] mkfs: structify input parameter passing jtulak
                   ` (12 subsequent siblings)
  18 siblings, 1 reply; 84+ messages in thread
From: jtulak @ 2016-03-24 11:15 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>
---
 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 9394bd3..dda076d 100644
--- a/mkfs/xfs_mkfs.c
+++ b/mkfs/xfs_mkfs.c
@@ -1022,6 +1022,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,
@@ -1179,16 +1200,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;
@@ -1325,16 +1346,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;
@@ -1399,9 +1420,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;
@@ -1573,16 +1596,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;
@@ -1658,16 +1681,16 @@ _("cannot specify both -m crc=1 and -n ftype\n"));
 
 				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;
@@ -1786,16 +1809,16 @@ _("cannot specify both -m crc=1 and -n ftype\n"));
 				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.6.0

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

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

* [PATCH 07/19] mkfs: structify input parameter passing
  2016-03-24 11:15 [PATCH 00/19] mkfs cleaning jtulak
                   ` (5 preceding siblings ...)
  2016-03-24 11:15 ` [PATCH 06/19] mkfs: validate logarithmic parameters sanely jtulak
@ 2016-03-24 11:15 ` jtulak
  2016-04-07  3:14   ` Eric Sandeen
  2016-03-24 11:15 ` [PATCH 08/19] mkfs: getbool is redundant jtulak
                   ` (11 subsequent siblings)
  18 siblings, 1 reply; 84+ messages in thread
From: jtulak @ 2016-03-24 11:15 UTC (permalink / raw)
  To: xfs

From: Dave Chinner <dchinner@redhat.com>

CHANGELOG:
o Add a description of the new opt_params structure.
o Fix indenting
o Add missing I_SPINODES to subopt_params
o Add a check for undefined minval/maxval into getnum_checked
o Drop "const" from struct opt_params - it would be removed in a later
  patch anyway

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>
---
 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 dda076d..6e29848 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 coresponding 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 either has
+ *     to supply your own validation, or refuse any value in the 'case
+ *     X_SOMETHING' block. If you forget to pass a min or max value here, 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)))
@@ -1022,24 +1236,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;
 }
 
@@ -1196,30 +1428,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);
@@ -1237,14 +1468,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");
@@ -1252,9 +1485,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)
@@ -1269,25 +1502,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)
@@ -1295,11 +1528,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)
@@ -1307,11 +1540,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);
@@ -1320,11 +1553,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)
@@ -1332,40 +1565,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);
@@ -1382,14 +1612,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;
@@ -1402,37 +1632,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");
@@ -1440,14 +1667,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 <
@@ -1458,15 +1685,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");
@@ -1475,7 +1702,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");
@@ -1501,17 +1728,19 @@ main(
 		case 'l':
 			p = optarg;
 			while (*p != '\0') {
+				char	**subopts = (char **)lopts.subopts;
 				char	*value;
 				long long tmp_num;
 
-				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);
 					tmp_num = getnum(value, 0, 0, false);
 					if (tmp_num < 0)
 						illegal(value, "l agno");
@@ -1520,7 +1749,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);
@@ -1529,12 +1758,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);
@@ -1542,9 +1771,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)
@@ -1553,9 +1782,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");
@@ -1564,13 +1793,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;
@@ -1578,9 +1807,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");
@@ -1589,33 +1818,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);
@@ -1644,9 +1870,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);
@@ -1665,7 +1893,7 @@ _("cannot specify both -m crc=1 and -n ftype\n"));
 					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;
@@ -1677,30 +1905,29 @@ _("cannot specify both -m crc=1 and -n ftype\n"));
 		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);
@@ -1713,9 +1940,9 @@ _("cannot specify both -m crc=1 and -n ftype\n"));
 					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;
@@ -1730,7 +1957,7 @@ _("cannot specify both -m crc=1 and -n ftype\n"));
 					break;
 				case N_FTYPE:
 					if (nftype)
-						respec('n', nopts, N_FTYPE);
+						respec('n', subopts, N_FTYPE);
 					if (sb_feat.crcs_enabled) {
 						fprintf(stderr,
 _("cannot specify both -m crc=1 and -n ftype\n"));
@@ -1762,14 +1989,16 @@ _("cannot specify both -m crc=1 and -n ftype\n"));
 		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:
@@ -1781,16 +2010,16 @@ _("cannot specify both -m crc=1 and -n ftype\n"));
 				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:
@@ -1804,21 +2033,20 @@ _("cannot specify both -m crc=1 and -n ftype\n"));
 		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;
@@ -1827,11 +2055,11 @@ _("cannot specify both -m crc=1 and -n ftype\n"));
 				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.6.0

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

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

* [PATCH 08/19] mkfs: getbool is redundant
  2016-03-24 11:15 [PATCH 00/19] mkfs cleaning jtulak
                   ` (6 preceding siblings ...)
  2016-03-24 11:15 ` [PATCH 07/19] mkfs: structify input parameter passing jtulak
@ 2016-03-24 11:15 ` jtulak
  2016-04-07 17:25   ` Eric Sandeen
  2016-03-24 11:15 ` [PATCH 09/19] mkfs: use getnum_checked for all ranged parameters jtulak
                   ` (10 subsequent siblings)
  18 siblings, 1 reply; 84+ messages in thread
From: jtulak @ 2016-03-24 11:15 UTC (permalink / raw)
  To: xfs

From: Dave Chinner <dchinner@redhat.com>

CHANGELOG:
o Add description of a new member of opt_params
o Fix in the subopts tables
o All boolean subopts should use getnum_checked
o Edit man8 page where it missed the information about optional value of a flag

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>
---
 man/man8/mkfs.xfs.8 |  11 ++-
 mkfs/xfs_mkfs.c     | 223 ++++++++++++++++++++++++++++++++++++----------------
 2 files changed, 164 insertions(+), 70 deletions(-)

diff --git a/man/man8/mkfs.xfs.8 b/man/man8/mkfs.xfs.8
index 8b068ef..5a2a20a 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, in a forward-compatible syntax.
 .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
diff --git a/mkfs/xfs_mkfs.c b/mkfs/xfs_mkfs.c
index 6e29848..0e2cfac 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,
 		},
 	},
 };
@@ -1220,22 +1313,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,
@@ -1250,17 +1327,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 (opts->subopt_params[index].minval == 0 &&
-	    opts->subopt_params[index].maxval == 0) {
+	if (!str || *str == '\0') {
+		if (sp->defaultval == SUBOPT_NEEDS_VAL)
+			reqval(opts->name, (char **)opts->subopts, index);
+		return sp->defaultval;
+	}
+
+	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"),
@@ -1269,8 +1356,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;
 }
@@ -1495,8 +1581,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;
@@ -1564,19 +1650,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)
@@ -1638,8 +1727,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)
@@ -1709,16 +1798,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:
-					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 =
+						getnum_checked(value, &iopts,
+								I_SPINODES);
 					break;
 				default:
 					unknown('i', value);
@@ -1748,11 +1835,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;
@@ -1765,8 +1852,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:
@@ -1853,9 +1940,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);
@@ -1876,8 +1963,9 @@ 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 && nftype) {
 						fprintf(stderr,
 _("cannot specify both -m crc=1 and -n ftype\n"));
@@ -1888,8 +1976,8 @@ _("cannot specify both -m crc=1 and -n ftype\n"));
 					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')
@@ -1963,8 +2051,8 @@ _("cannot specify both -m crc=1 and -n ftype\n"));
 _("cannot specify both -m crc=1 and -n ftype\n"));
 						usage();
 					}
-					sb_feat.dirftype = getbool(value,
-							     "n ftype", true);
+					sb_feat.dirftype = getnum_checked(value,
+								&nopts, N_FTYPE);
 					nftype = 1;
 					break;
 				default:
@@ -2002,8 +2090,8 @@ _("cannot specify both -m crc=1 and -n ftype\n"));
 					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;
@@ -2023,7 +2111,8 @@ _("cannot specify both -m crc=1 and -n ftype\n"));
 					rtsize = value;
 					break;
 				case R_NOALIGN:
-					norsflag = 1;
+					norsflag = getnum_checked(value,
+								&ropts, R_NOALIGN);
 					break;
 				default:
 					unknown('r', value);
-- 
2.6.0

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

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

* [PATCH 09/19] mkfs: use getnum_checked for all ranged parameters
  2016-03-24 11:15 [PATCH 00/19] mkfs cleaning jtulak
                   ` (7 preceding siblings ...)
  2016-03-24 11:15 ` [PATCH 08/19] mkfs: getbool is redundant jtulak
@ 2016-03-24 11:15 ` jtulak
  2016-04-07 19:02   ` Eric Sandeen
  2016-03-24 11:15 ` [PATCH 10/19] mkfs: add respecification detection to generic parsing jtulak
                   ` (9 subsequent siblings)
  18 siblings, 1 reply; 84+ messages in thread
From: jtulak @ 2016-03-24 11:15 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>
---
 include/xfs_multidisk.h |   5 +-
 mkfs/xfs_mkfs.c         | 148 ++++++++++++++++++++++++------------------------
 2 files changed, 76 insertions(+), 77 deletions(-)

diff --git a/include/xfs_multidisk.h b/include/xfs_multidisk.h
index af35100..8e81d90 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 0e2cfac..021d682 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,
@@ -1560,13 +1592,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:
@@ -1601,28 +1631,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')
@@ -1638,16 +1662,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,
@@ -1696,21 +1717,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:
@@ -1745,18 +1767,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);
@@ -1765,16 +1782,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);
@@ -1783,19 +1797,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 =
@@ -1817,21 +1828,16 @@ main(
 			while (*p != '\0') {
 				char	**subopts = (char **)lopts.subopts;
 				char	*value;
-				long long tmp_num;
 
 				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);
-					tmp_num = getnum(value, 0, 0, false);
-					if (tmp_num < 0)
-						illegal(value, "l agno");
-					logagno = (xfs_agnumber_t)tmp_num;
+					logagno = getnum_checked(value, &lopts,
+								 L_AGNUM);
 					laflag = 1;
 					break;
 				case L_FILE:
@@ -1868,13 +1874,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:
@@ -1893,14 +1896,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:
@@ -2035,11 +2034,10 @@ _("cannot specify both -m crc=1 and -n ftype\n"));
 						/* 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.6.0

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

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

* [PATCH 10/19] mkfs: add respecification detection to generic parsing
  2016-03-24 11:15 [PATCH 00/19] mkfs cleaning jtulak
                   ` (8 preceding siblings ...)
  2016-03-24 11:15 ` [PATCH 09/19] mkfs: use getnum_checked for all ranged parameters jtulak
@ 2016-03-24 11:15 ` jtulak
  2016-04-07 19:06   ` Eric Sandeen
  2016-03-24 11:15 ` [PATCH 11/19] mkfs: table based parsing for converted parameters jtulak
                   ` (8 subsequent siblings)
  18 siblings, 1 reply; 84+ messages in thread
From: jtulak @ 2016-03-24 11:15 UTC (permalink / raw)
  To: xfs

From: Dave Chinner <dchinner@redhat.com>

CHANGE:
o Add description of new members in opt_params struct.
o Drop "const" from struct opt_params - a previous patch was changed to
  not create it as const.

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>
---
 mkfs/xfs_mkfs.c | 64 ++++++++++++++++-----------------------------------------
 1 file changed, 18 insertions(+), 46 deletions(-)

diff --git a/mkfs/xfs_mkfs.c b/mkfs/xfs_mkfs.c
index 021d682..a8dd304 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;
@@ -1227,7 +1233,6 @@ struct sb_feat_args {
 	int	dir_version;
 	int	spinodes;
 	int	finobt;
-	bool	finobtflag;
 	bool	inode_align;
 	bool	nci;
 	bool	lazy_sb_counters;
@@ -1363,7 +1368,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) {
@@ -1373,6 +1378,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);
@@ -1490,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,
@@ -1552,8 +1561,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);
@@ -1592,9 +1599,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;
@@ -1631,8 +1635,6 @@ main(
 					dsize = value;
 					break;
 				case D_SUNIT:
-					if (dsunit)
-						respec('d', subopts, D_SUNIT);
 					if (nodsflag)
 						conflict('d', subopts, D_NOALIGN,
 							 D_SUNIT);
@@ -1640,8 +1642,6 @@ main(
 								 D_SUNIT);
 					break;
 				case D_SWIDTH:
-					if (dswidth)
-						respec('d', subopts, D_SWIDTH);
 					if (nodsflag)
 						conflict('d', subopts, D_NOALIGN,
 							 D_SWIDTH);
@@ -1662,8 +1662,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);
@@ -1689,8 +1687,6 @@ main(
 					}
 					break;
 				case D_SECTLOG:
-					if (slflag)
-						respec('d', subopts, D_SECTLOG);
 					if (ssflag)
 						conflict('d', subopts, D_SECTSIZE,
 							 D_SECTLOG);
@@ -1753,8 +1749,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);
@@ -1767,18 +1761,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);
@@ -1795,8 +1785,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))
@@ -1832,8 +1820,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,
@@ -1855,8 +1841,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);
@@ -1874,8 +1858,6 @@ main(
 					lsuflag = 1;
 					break;
 				case L_SUNIT:
-					if (lsunit)
-						respec('l', subopts, L_SUNIT);
 					lsunit = getnum_checked(value, &lopts,
 								 L_SUNIT);
 					lsunitflag = 1;
@@ -1896,10 +1878,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:
@@ -1911,8 +1892,6 @@ main(
 					lsflag = 1;
 					break;
 				case L_SECTLOG:
-					if (lslflag)
-						respec('l', subopts, L_SECTLOG);
 					if (lssflag)
 						conflict('l', subopts, L_SECTSIZE,
 							 L_SECTLOG);
@@ -1974,7 +1953,6 @@ _("cannot specify both -m crc=1 and -n ftype\n"));
 						sb_feat.dirftype = true;
 					break;
 				case M_FINOBT:
-					sb_feat.finobtflag = true;
 					sb_feat.finobt = getnum_checked(
 						value, &mopts, M_FINOBT);
 					break;
@@ -1998,8 +1976,6 @@ _("cannot specify both -m crc=1 and -n ftype\n"));
 				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);
@@ -2042,8 +2018,6 @@ _("cannot specify both -m crc=1 and -n ftype\n"));
 					nvflag = 1;
 					break;
 				case N_FTYPE:
-					if (nftype)
-						respec('n', subopts, N_FTYPE);
 					if (sb_feat.crcs_enabled) {
 						fprintf(stderr,
 _("cannot specify both -m crc=1 and -n ftype\n"));
@@ -2127,8 +2101,6 @@ _("cannot specify both -m crc=1 and -n ftype\n"));
 						  &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);
@@ -2340,7 +2312,7 @@ _("32 bit Project IDs always enabled on CRC enabled filesytems\n"));
 		 * them off.
 		 */
 		if (sb_feat.finobt){
-			if (sb_feat.finobtflag) {
+			if (mopts.subopt_params[M_FINOBT].seen) {
 				fprintf(stderr,
 	_("warning: finobt not supported without CRC support, disabled.\n"));
 			}
-- 
2.6.0

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

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

* [PATCH 11/19] mkfs: table based parsing for converted parameters
  2016-03-24 11:15 [PATCH 00/19] mkfs cleaning jtulak
                   ` (9 preceding siblings ...)
  2016-03-24 11:15 ` [PATCH 10/19] mkfs: add respecification detection to generic parsing jtulak
@ 2016-03-24 11:15 ` jtulak
  2016-04-07 19:08   ` Eric Sandeen
  2016-03-24 11:15 ` [PATCH 12/19] mkfs: merge getnum jtulak
                   ` (7 subsequent siblings)
  18 siblings, 1 reply; 84+ messages in thread
From: jtulak @ 2016-03-24 11:15 UTC (permalink / raw)
  To: xfs

From: Dave Chinner <dchinner@redhat.com>

CHANGE:
o Change getnum_checked type to long long to prevent int overflow
o Add description of new members in opt_params struct.
o L_SU maxval was a wrong number, fix it

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>
---
 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 a8dd304..acf420f 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 = XLOG_MIN_RECORD_BSIZE,
+		  .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,
@@ -1332,15 +1383,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)
@@ -1362,7 +1413,7 @@ illegal_option(
 	usage();
 }
 
-static int
+static long long
 getnum_checked(
 	const char		*str,
 	struct opt_params	*opts,
@@ -1397,9 +1448,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;
 }
 
@@ -1417,7 +1470,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;
@@ -1570,18 +1621,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;
@@ -1604,14 +1648,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:
@@ -1649,17 +1687,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)
@@ -1696,18 +1728,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;
@@ -1774,8 +1799,6 @@ main(
 							 I_PERBLOCK);
 					inopblock = getnum_checked(value, &iopts,
 								   I_PERBLOCK);
-					if (!ispow2(inopblock))
-						illegal(value, "i perblock");
 					ipflag = 1;
 					break;
 				case I_SIZE:
@@ -1787,8 +1810,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;
@@ -1847,14 +1868,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:
@@ -1901,18 +1916,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;
@@ -1985,18 +1993,11 @@ _("cannot specify both -m crc=1 and -n ftype\n"));
 					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;
@@ -2113,18 +2114,11 @@ _("cannot specify both -m crc=1 and -n ftype\n"));
 					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);
@@ -2355,9 +2349,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"),
@@ -2394,9 +2386,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"),
@@ -2418,9 +2408,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"),
@@ -2440,27 +2428,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.6.0

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

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

* [PATCH 12/19] mkfs: merge getnum
  2016-03-24 11:15 [PATCH 00/19] mkfs cleaning jtulak
                   ` (10 preceding siblings ...)
  2016-03-24 11:15 ` [PATCH 11/19] mkfs: table based parsing for converted parameters jtulak
@ 2016-03-24 11:15 ` jtulak
  2016-04-07 19:14   ` Eric Sandeen
  2016-03-24 11:15 ` [PATCH 13/19] mkfs: encode conflicts into parsing table jtulak
                   ` (6 subsequent siblings)
  18 siblings, 1 reply; 84+ messages in thread
From: jtulak @ 2016-03-24 11:15 UTC (permalink / raw)
  To: xfs

From: Dave Chinner <dchinner@redhat.com>

CHANGELOG
o rename a variable to don't collide with existing local variable (and
  to have a better meaning: sp -> str_end for detecting trailing garbage)

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>
---
 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 8e81d90..850a322 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 5930af8..3d3a8dc 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 acf420f..1f06110 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.
@@ -1380,27 +1377,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,
@@ -1414,7 +1390,7 @@ illegal_option(
 }
 
 static long long
-getnum_checked(
+getnum(
 	const char		*str,
 	struct opt_params	*opts,
 	int			index)
@@ -1434,6 +1410,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);
@@ -1448,7 +1425,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))
@@ -1615,8 +1610,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;
@@ -1624,8 +1618,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;
@@ -1643,18 +1637,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;
@@ -1676,33 +1669,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,
@@ -1722,8 +1712,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;
@@ -1731,28 +1721,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;
@@ -1770,8 +1759,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)
@@ -1780,14 +1769,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:
@@ -1797,8 +1785,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:
@@ -1808,23 +1796,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:
@@ -1843,13 +1830,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);
@@ -1863,18 +1849,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:
@@ -1894,8 +1878,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:
@@ -1910,8 +1893,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;
@@ -1919,15 +1902,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:
@@ -1950,8 +1933,7 @@ 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 && nftype) {
 						fprintf(stderr,
 _("cannot specify both -m crc=1 and -n ftype\n"));
@@ -1961,7 +1943,7 @@ _("cannot specify both -m crc=1 and -n ftype\n"));
 						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:
@@ -1987,8 +1969,8 @@ _("cannot specify both -m crc=1 and -n ftype\n"));
 					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;
@@ -1996,8 +1978,8 @@ _("cannot specify both -m crc=1 and -n ftype\n"));
 					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;
@@ -2012,9 +1994,8 @@ _("cannot specify both -m crc=1 and -n ftype\n"));
 						sb_feat.nci = true;
 					} else {
 						sb_feat.dir_version =
-							getnum_checked(value,
-								&nopts,
-								N_VERSION);
+							getnum(value, &nopts,
+							       N_VERSION);
 					}
 					nvflag = 1;
 					break;
@@ -2024,8 +2005,8 @@ _("cannot specify both -m crc=1 and -n ftype\n"));
 _("cannot specify both -m crc=1 and -n ftype\n"));
 						usage();
 					}
-					sb_feat.dirftype = getnum_checked(value,
-								&nopts, N_FTYPE);
+					sb_feat.dirftype = getnum(value, &nopts,
+								  N_FTYPE);
 					nftype = 1;
 					break;
 				default:
@@ -2063,8 +2044,8 @@ _("cannot specify both -m crc=1 and -n ftype\n"));
 					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;
@@ -2084,8 +2065,8 @@ _("cannot specify both -m crc=1 and -n ftype\n"));
 					rtsize = value;
 					break;
 				case R_NOALIGN:
-					norsflag = getnum_checked(value,
-								&ropts, R_NOALIGN);
+					norsflag = getnum(value, &ropts,
+								R_NOALIGN);
 					break;
 				default:
 					unknown('r', value);
@@ -2105,8 +2086,8 @@ _("cannot specify both -m crc=1 and -n ftype\n"));
 					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;
@@ -2117,8 +2098,8 @@ _("cannot specify both -m crc=1 and -n ftype\n"));
 					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);
@@ -2349,7 +2330,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"),
@@ -2386,7 +2367,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"),
@@ -2408,7 +2389,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"),
@@ -2428,7 +2409,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"),
@@ -3531,8 +3512,8 @@ unknown(
 
 long long
 cvtnum(
-	unsigned int	blocksize,
-	unsigned int	sectorsize,
+	unsigned int	blksize,
+	unsigned int	sectsize,
 	const char	*s)
 {
 	long long	i;
@@ -3545,9 +3526,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.6.0

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

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

* [PATCH 13/19] mkfs: encode conflicts into parsing table
  2016-03-24 11:15 [PATCH 00/19] mkfs cleaning jtulak
                   ` (11 preceding siblings ...)
  2016-03-24 11:15 ` [PATCH 12/19] mkfs: merge getnum jtulak
@ 2016-03-24 11:15 ` jtulak
  2016-04-07 22:40   ` Eric Sandeen
  2016-03-24 11:15 ` [PATCH 14/19] mkfs: add string options to generic parsing jtulak
                   ` (5 subsequent siblings)
  18 siblings, 1 reply; 84+ 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] 84+ messages in thread

* [PATCH 14/19] mkfs: add string options to generic parsing
  2016-03-24 11:15 [PATCH 00/19] mkfs cleaning jtulak
                   ` (12 preceding siblings ...)
  2016-03-24 11:15 ` [PATCH 13/19] mkfs: encode conflicts into parsing table jtulak
@ 2016-03-24 11:15 ` jtulak
  2016-04-07 22:49   ` Eric Sandeen
  2016-03-24 11:15 ` [PATCH 15/19] mkfs: don't treat files as though they are block devices jtulak
                   ` (4 subsequent siblings)
  18 siblings, 1 reply; 84+ messages in thread
From: jtulak @ 2016-03-24 11:15 UTC (permalink / raw)
  To: xfs

From: Dave Chinner <dchinner@redhat.com>

CHANGELOG:
o Remove unused argument of check_opt.
o Add a comment to explain a new member of opt_params struct.
o A stray chunk moved from the following patch to this one.

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>
---
 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 d119580..9261ed5 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];
@@ -1470,14 +1475,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,
@@ -1486,22 +1494,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)
@@ -1543,6 +1576,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,
@@ -1738,18 +1791,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);
@@ -1890,18 +1935,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 =
@@ -1909,12 +1946,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,
@@ -2000,10 +2032,7 @@ _("cannot specify both -m crc=1 and -n ftype\n"));
 					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;
@@ -2052,11 +2081,8 @@ _("cannot specify both -m crc=1 and -n ftype\n"));
 				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,
@@ -2066,18 +2092,11 @@ _("cannot specify both -m crc=1 and -n ftype\n"));
 					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,
@@ -2137,13 +2156,7 @@ _("cannot specify both -m crc=1 and -n ftype\n"));
 		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.6.0

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

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

* [PATCH 15/19] mkfs: don't treat files as though they are block devices
  2016-03-24 11:15 [PATCH 00/19] mkfs cleaning jtulak
                   ` (13 preceding siblings ...)
  2016-03-24 11:15 ` [PATCH 14/19] mkfs: add string options to generic parsing jtulak
@ 2016-03-24 11:15 ` jtulak
  2016-04-08  0:25   ` Eric Sandeen
  2016-03-24 11:15 ` [PATCH 16/19] mkfs: move spinodes crc check jtulak
                   ` (3 subsequent siblings)
  18 siblings, 1 reply; 84+ messages in thread
From: jtulak @ 2016-03-24 11:15 UTC (permalink / raw)
  To: xfs

From: Dave Chinner <dchinner@redhat.com>

CHANGELOG
o Fix where xi.dname was incorrectly used instead of dfile
o Variable alignment (tabs)
o Added error handling for stat/statfs in init.c
o Remove a duplicate pread in zero_old_xfs_structures and for the
remaining call, save the return value in a more meaningful variable.
o A chunk moved to previous patch.

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.  Also, as direct IO
is disabled for files, use statfs() for getting host FS blocksize,
not platform_findsizes().

These changes, however, can cause some tests to fail when the test
partition on which the file is created has blocksize bigger than 512.
Before, the underlying fs was ignored. Now, an attempt to create
a fs in a file with blocksize 512 on a 4096 underlying partition will
fail.

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>
---
 libxfs/init.c   |  12 ++++
 libxfs/linux.c  |  12 +++-
 mkfs/xfs_mkfs.c | 181 ++++++++++++++++++++++++++++++++++++++------------------
 3 files changed, 147 insertions(+), 58 deletions(-)

diff --git a/libxfs/init.c b/libxfs/init.c
index 8d747e8..268136f 100644
--- a/libxfs/init.c
+++ b/libxfs/init.c
@@ -246,6 +246,9 @@ libxfs_init(libxfs_init_t *a)
 	char		rtpath[25];
 	int		rval = 0;
 	int		flags;
+	struct		stat st;
+	struct		statfs stfs;
+	int		statres;
 
 	dpath[0] = logpath[0] = rtpath[0] = '\0';
 	dname = a->dname;
@@ -278,6 +281,15 @@ 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);
+			statres = stat(dname, &st);
+			statres += statfs(dname, &stfs);
+			if(statres){
+				fprintf(stderr, _("%s: stat failed.\n"),
+					progname);
+				goto done;
+			}
+			a->dsize = st.st_size/BBSIZE;
+			a->dbsize = stfs.f_bsize;
 		} else {
 			if (!check_open(dname, flags, &rawfile, &blockfile))
 				goto done;
diff --git a/libxfs/linux.c b/libxfs/linux.c
index f6ea1b2..adb8ff1 100644
--- a/libxfs/linux.c
+++ b/libxfs/linux.c
@@ -18,6 +18,7 @@
 
 #define ustat __kernel_ustat
 #include <mntent.h>
+#include <sys/vfs.h>
 #include <sys/stat.h>
 #undef ustat
 #include <sys/ustat.h>
@@ -125,7 +126,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 9261ed5..7bd9fd5 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)
@@ -976,35 +979,35 @@ static void get_topology(
 	struct fs_topology	*ft,
 	int			force_overwrite)
 {
-	struct stat statbuf;
 	char *dfile = xi->volname ? xi->volname : xi->dname;
+	struct stat statbuf;
+	struct statfs statfsbuf;
 
 	/*
-	 * If our target is a regular file, use platform_findsizes
-	 * to try to obtain the underlying filesystem's requirements
-	 * for direct IO; we'll set our sector size to that if possible.
+	 * If our target is a regular file, use statfs
+	 * to try to obtain the underlying filesystem's blocksize.
 	 */
 	if (xi->disfile ||
-	    (!stat(dfile, &statbuf) && S_ISREG(statbuf.st_mode))) {
+		(!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)
 			flags |= O_CREAT;
 
 		fd = open(dfile, flags, 0666);
+
 		if (fd >= 0) {
-			platform_findsizes(dfile, fd, &dummy, &ft->lsectorsize);
+			fstatfs(fd, &statfsbuf);
+			ft->lsectorsize = statfsbuf.f_bsize;
 			close(fd);
-			ft->psectorsize = ft->lsectorsize;
 		} else
 			ft->psectorsize = ft->lsectorsize = BBSIZE;
 	} else {
 		blkid_get_topology(dfile, &ft->dsunit, &ft->dswidth,
-				   &ft->lsectorsize, &ft->psectorsize,
-				   force_overwrite);
+					&ft->lsectorsize, &ft->psectorsize,
+					force_overwrite);
 	}
 
 	if (xi->rtname && !xi->risfile) {
@@ -1016,6 +1019,75 @@ 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 (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,
@@ -1279,7 +1351,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...
@@ -1299,15 +1370,23 @@ zero_old_xfs_structures(
 	}
 	memset(buf, 0, new_sb->sb_sectsize);
 
-	tmp = pread(xi->dfd, buf, new_sb->sb_sectsize, 0);
-	if (tmp < 0) {
+	off = pread(xi->dfd, buf, new_sb->sb_sectsize, 0);
+	if (off < 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.
+	 */
+	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);
@@ -1787,8 +1866,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);
@@ -1914,11 +1991,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,
@@ -2087,8 +2159,6 @@ _("cannot specify both -m crc=1 and -n ftype\n"));
 				case R_FILE:
 					xi.risfile = getnum(value, &ropts,
 							    R_FILE);
-					if (xi.risfile)
-						xi.rcreat = 1;
 					break;
 				case R_NAME:
 				case R_DEV:
@@ -2193,6 +2263,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);
 
@@ -2345,11 +2435,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;
 
@@ -2382,11 +2467,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;
 
@@ -2404,11 +2484,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;
 
@@ -2530,22 +2605,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.6.0

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

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

* [PATCH 16/19] mkfs: move spinodes crc check
  2016-03-24 11:15 [PATCH 00/19] mkfs cleaning jtulak
                   ` (14 preceding siblings ...)
  2016-03-24 11:15 ` [PATCH 15/19] mkfs: don't treat files as though they are block devices jtulak
@ 2016-03-24 11:15 ` jtulak
  2016-03-24 11:15 ` [PATCH 17/19] xfsprogs: disable truncating of files jtulak
                   ` (2 subsequent siblings)
  18 siblings, 0 replies; 84+ messages in thread
From: jtulak @ 2016-03-24 11:15 UTC (permalink / raw)
  To: xfs

From: Jan Tulak <jtulak@redhat.com>

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 7bd9fd5..9a6ae2c 100644
--- a/mkfs/xfs_mkfs.c
+++ b/mkfs/xfs_mkfs.c
@@ -2411,12 +2411,13 @@ _("32 bit Project IDs always enabled on CRC enabled filesytems\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"));
-		sb_feat.spinodes = 0;
+		if (sb_feat.spinodes) {
+			fprintf(stderr,
+	_("warning: sparse inodes not supported without CRC support, disabled.\n"));
+			sb_feat.spinodes = 0;
+		}
+
 	}

 	if (nsflag || nlflag) {
--
2.6.0

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

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

* [PATCH 17/19] xfsprogs: disable truncating of files
  2016-03-24 11:15 [PATCH 00/19] mkfs cleaning jtulak
                   ` (15 preceding siblings ...)
  2016-03-24 11:15 ` [PATCH 16/19] mkfs: move spinodes crc check jtulak
@ 2016-03-24 11:15 ` jtulak
  2016-04-06 21:42   ` Eric Sandeen
  2016-04-08  0:09   ` Dave Chinner
  2016-03-24 11:15 ` [PATCH 18/19] mkfs: unit conversions are case insensitive jtulak
  2016-03-24 11:15 ` [PATCH 19/19] mkfs: add optional 'reason' for illegal_option jtulak
  18 siblings, 2 replies; 84+ messages in thread
From: jtulak @ 2016-03-24 11:15 UTC (permalink / raw)
  To: xfs

From: Jan Tulak <jtulak@redhat.com>

Unify mkfs.xfs behaviour a bit and never truncate files. If the user
is trying to mkfs an existing file, we don't want to destroy anything
he did with the file before (sparse file, allocations...)

Signed-off-by: Jan Tulak <jtulak@redhat.com>
---
 libxfs/init.c   |  2 +-
 mkfs/xfs_mkfs.c | 18 +++++++++++-------
 2 files changed, 12 insertions(+), 8 deletions(-)

diff --git a/libxfs/init.c b/libxfs/init.c
index 268136f..5f4b6c4 100644
--- a/libxfs/init.c
+++ b/libxfs/init.c
@@ -112,7 +112,7 @@ libxfs_device_open(char *path, int creat, int xflags, int setblksize)
 
 retry:
 	flags = (readonly ? O_RDONLY : O_RDWR) | \
-		(creat ? (O_CREAT|O_TRUNC) : 0) | \
+		(creat ? O_CREAT : 0) | \
 		(dio ? O_DIRECT : 0) | \
 		(excl ? O_EXCL : 0);
 
diff --git a/mkfs/xfs_mkfs.c b/mkfs/xfs_mkfs.c
index 9a6ae2c..2bb3b35 100644
--- a/mkfs/xfs_mkfs.c
+++ b/mkfs/xfs_mkfs.c
@@ -1029,15 +1029,19 @@ check_device_type(
 	const char	*optname)
 {
 	struct stat64 statbuf;
+	int statres;
 
-	if (*isfile && (no_size || no_name)) {
+	statres = stat64(name, &statbuf);
+
+	if (*isfile && statres != 0 && (no_size || no_name)) {
 		fprintf(stderr,
-	_("if -%s file then -%s name and -%s size are required\n"),
-			optname, optname, optname);
+			_("if -%s file and the file does not exists, " \
+			"then -%s name and -%s size are required\n"),
+					optname, optname, optname);
 		usage();
 	}
 
-	if (stat64(name, &statbuf)) {
+	if (statres) {
 		if (errno == ENOENT && *isfile) {
 			if (create)
 				*create = 1;
@@ -1059,9 +1063,9 @@ check_device_type(
 	}
 
 	/*
-	 * 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.
+	 * We only want to create a file only if we were specifically told
+	 * we want a file. Set the create flag only in this case to trigger
+	 * that behaviour.
 	 */
 	if (S_ISREG(statbuf.st_mode)) {
 		if (!*isfile)
-- 
2.6.0

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

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

* [PATCH 18/19] mkfs: unit conversions are case insensitive
  2016-03-24 11:15 [PATCH 00/19] mkfs cleaning jtulak
                   ` (16 preceding siblings ...)
  2016-03-24 11:15 ` [PATCH 17/19] xfsprogs: disable truncating of files jtulak
@ 2016-03-24 11:15 ` jtulak
  2016-04-06 21:10   ` Eric Sandeen
  2016-03-24 11:15 ` [PATCH 19/19] mkfs: add optional 'reason' for illegal_option jtulak
  18 siblings, 1 reply; 84+ messages in thread
From: jtulak @ 2016-03-24 11:15 UTC (permalink / raw)
  To: xfs

From: Jan Tulak <jtulak@redhat.com>

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

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

diff --git a/mkfs/xfs_mkfs.c b/mkfs/xfs_mkfs.c
index 2bb3b35..680c6c4 100644
--- a/mkfs/xfs_mkfs.c
+++ b/mkfs/xfs_mkfs.c
@@ -3625,17 +3625,17 @@ cvtnum(
 	if (*sp == 's' && sp[1] == '\0')
 		return i * sectsize;
 
-	if (*sp == 'k' && sp[1] == '\0')
+	if ((*sp == 'k'  || *sp == 'K' ) && sp[1] == '\0')
 		return 1024LL * i;
-	if (*sp == 'm' && sp[1] == '\0')
+	if ((*sp == 'm'  || *sp == 'M' ) && sp[1] == '\0')
 		return 1024LL * 1024LL * i;
-	if (*sp == 'g' && sp[1] == '\0')
+	if ((*sp == 'g'  || *sp == 'G' ) && sp[1] == '\0')
 		return 1024LL * 1024LL * 1024LL * i;
-	if (*sp == 't' && sp[1] == '\0')
+	if ((*sp == 't'  || *sp == 'T' ) && sp[1] == '\0')
 		return 1024LL * 1024LL * 1024LL * 1024LL * i;
-	if (*sp == 'p' && sp[1] == '\0')
+	if ((*sp == 'p'  || *sp == 'P' ) && sp[1] == '\0')
 		return 1024LL * 1024LL * 1024LL * 1024LL * 1024LL * i;
-	if (*sp == 'e' && sp[1] == '\0')
+	if ((*sp == 'e'  || *sp == 'E' ) && sp[1] == '\0')
 		return 1024LL * 1024LL * 1024LL * 1024LL * 1024LL * 1024LL * i;
 	return -1LL;
 }
-- 
2.6.0

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

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

* [PATCH 19/19] mkfs: add optional 'reason' for illegal_option
  2016-03-24 11:15 [PATCH 00/19] mkfs cleaning jtulak
                   ` (17 preceding siblings ...)
  2016-03-24 11:15 ` [PATCH 18/19] mkfs: unit conversions are case insensitive jtulak
@ 2016-03-24 11:15 ` jtulak
  2016-04-06 22:23   ` Eric Sandeen
  18 siblings, 1 reply; 84+ messages in thread
From: jtulak @ 2016-03-24 11:15 UTC (permalink / raw)
  To: xfs

From: Jan Tulak <jtulak@redhat.com>

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

Signed-off-by: Jan Tulak <jtulak@redhat.com>
---
 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 680c6c4..76e193d 100644
--- a/mkfs/xfs_mkfs.c
+++ b/mkfs/xfs_mkfs.c
@@ -1550,11 +1550,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();
 }

@@ -1646,16 +1653,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 has to be power of 2");
 	return c;
 }

--
2.6.0

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

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

* Re: [PATCH 02/19] mkfs: sanitise ftype parameter values.
  2016-03-24 11:15 ` [PATCH 02/19] mkfs: sanitise ftype parameter values jtulak
@ 2016-03-24 16:33   ` Eric Sandeen
  2016-03-29 16:11     ` Jan Tulak
  0 siblings, 1 reply; 84+ messages in thread
From: Eric Sandeen @ 2016-03-24 16:33 UTC (permalink / raw)
  To: xfs



On 3/24/16 6:15 AM, jtulak@redhat.com wrote:
> From: Dave Chinner <dchinner@redhat.com>
> 
> Because passing "-n ftype=2" should fail.

but passing crc=1 ftype=1 shouldn't fail, should it?
Seems like it will here.

-Eric

> Signed-off-by: Dave Chinner <dchinner@redhat.com>
> Signed-off-by: Jan Tulak <jtulak@redhat.com>
> Reviewed-by: Brian Foster <bfoster@redhat.com>
> ---
>  mkfs/xfs_mkfs.c | 10 +++++++++-
>  1 file changed, 9 insertions(+), 1 deletion(-)
> 
> diff --git a/mkfs/xfs_mkfs.c b/mkfs/xfs_mkfs.c
> index 36e5b4f..979a860 100644
> --- a/mkfs/xfs_mkfs.c
> +++ b/mkfs/xfs_mkfs.c
> @@ -1596,7 +1596,15 @@ 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");
> +					if (crcs_enabled) {
> +						fprintf(stderr,
> +_("cannot specify both crc and ftype\n"));
> +						usage();
> +					}
> +					dirftype = c;
>  					nftype = 1;
>  					break;
>  				default:
> 

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

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

* Re: [PATCH 02/19] mkfs: sanitise ftype parameter values.
  2016-03-24 16:33   ` Eric Sandeen
@ 2016-03-29 16:11     ` Jan Tulak
  2016-03-29 16:17       ` Eric Sandeen
  0 siblings, 1 reply; 84+ messages in thread
From: Jan Tulak @ 2016-03-29 16:11 UTC (permalink / raw)
  To: Eric Sandeen; +Cc: xfs-oss


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

On Thu, Mar 24, 2016 at 5:33 PM, Eric Sandeen <sandeen@sandeen.net> wrote:

>
>
> On 3/24/16 6:15 AM, jtulak@redhat.com wrote:
> > From: Dave Chinner <dchinner@redhat.com>
> >
> > Because passing "-n ftype=2" should fail.
>
> but passing crc=1 ftype=1 shouldn't fail, should it?
> Seems like it will here.
>

​From man page:
When  CRCs are enabled via -m crc=1, the ftype functionality is always
enabled. This feature can not be
​
turned off for such filesystem configurations.​


​So I think it should not be possible to enter both crc and ftype at the
same time - which is the current behaviour. It feels strange a bit to allow
ftype=1 (which does nothing with crc=1), but fail on ftype=0​

​Jan​


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

[-- Attachment #1.2: Type: text/html, Size: 2352 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] 84+ messages in thread

* Re: [PATCH 02/19] mkfs: sanitise ftype parameter values.
  2016-03-29 16:11     ` Jan Tulak
@ 2016-03-29 16:17       ` Eric Sandeen
  2016-03-29 16:20         ` Jan Tulak
  2016-03-29 17:14         ` Jan Tulak
  0 siblings, 2 replies; 84+ messages in thread
From: Eric Sandeen @ 2016-03-29 16:17 UTC (permalink / raw)
  To: Jan Tulak; +Cc: xfs-oss



On 3/29/16 11:11 AM, Jan Tulak wrote:
> On Thu, Mar 24, 2016 at 5:33 PM, Eric Sandeen <sandeen@sandeen.net <mailto:sandeen@sandeen.net>>wrote:
> 
> 
> 
>     On 3/24/16 6:15 AM, jtulak@redhat.com <mailto:jtulak@redhat.com> wrote:
>     > From: Dave Chinner <dchinner@redhat.com <mailto:dchinner@redhat.com>>
>     >
>     > Because passing "-n ftype=2" should fail.
> 
>     but passing crc=1 ftype=1 shouldn't fail, should it?
>     Seems like it will here.
> 
> 
> ​From man page:
> When  CRCs are enabled via -m crc=1, the ftype functionality is always enabled. This feature can not be
> ​ 
> turned off for such filesystem configurations.​
>  
> 
> ​So I think it should not be possible to enter both crc and ftype at
> the same time - which is the current behaviour. It feels strange a
> bit to allow ftype=1 (which does nothing with crc=1), but fail on
> ftype=0​

My point is that -m crc=1 -d ftype=1 simply restates the defaults.
Why should that combination fail?

And -m crc=0 -d ftype=0 is also perfectly acceptable.

In fact, -m crc=1 -d ftype=0 is the only one of the 4 combinations
which is not ok, but AFAICT your patch fails the other 3 as well.

-Eric

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

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

* Re: [PATCH 02/19] mkfs: sanitise ftype parameter values.
  2016-03-29 16:17       ` Eric Sandeen
@ 2016-03-29 16:20         ` Jan Tulak
  2016-03-29 17:14         ` Jan Tulak
  1 sibling, 0 replies; 84+ messages in thread
From: Jan Tulak @ 2016-03-29 16:20 UTC (permalink / raw)
  To: Eric Sandeen; +Cc: xfs-oss


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

On Tue, Mar 29, 2016 at 6:17 PM, Eric Sandeen <sandeen@sandeen.net> wrote:

>
>
> On 3/29/16 11:11 AM, Jan Tulak wrote:
> > On Thu, Mar 24, 2016 at 5:33 PM, Eric Sandeen <sandeen@sandeen.net
> <mailto:sandeen@sandeen.net>>wrote:
> >
> >
> >
> >     On 3/24/16 6:15 AM, jtulak@redhat.com <mailto:jtulak@redhat.com>
> wrote:
> >     > From: Dave Chinner <dchinner@redhat.com <mailto:
> dchinner@redhat.com>>
> >     >
> >     > Because passing "-n ftype=2" should fail.
> >
> >     but passing crc=1 ftype=1 shouldn't fail, should it?
> >     Seems like it will here.
> >
> >
> > ​From man page:
> > When  CRCs are enabled via -m crc=1, the ftype functionality is always
> enabled. This feature can not be
> > ​
> > turned off for such filesystem configurations.​
> >
> >
> > ​So I think it should not be possible to enter both crc and ftype at
> > the same time - which is the current behaviour. It feels strange a
> > bit to allow ftype=1 (which does nothing with crc=1), but fail on
> > ftype=0​
>
> My point is that -m crc=1 -d ftype=1 simply restates the defaults.
> Why should that combination fail?
>
> And -m crc=0 -d ftype=0 is also perfectly acceptable.
>
> In fact, -m crc=1 -d ftype=0 is the only one of the 4 combinations
> which is not ok, but AFAICT your patch fails the other 3 as well.
>

​True... I'm adding it into a test and will send an update.

Jan
​

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

[-- Attachment #1.2: Type: text/html, Size: 2963 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] 84+ messages in thread

* Re: [PATCH 02/19] mkfs: sanitise ftype parameter values.
  2016-03-29 16:17       ` Eric Sandeen
  2016-03-29 16:20         ` Jan Tulak
@ 2016-03-29 17:14         ` Jan Tulak
  1 sibling, 0 replies; 84+ messages in thread
From: Jan Tulak @ 2016-03-29 17:14 UTC (permalink / raw)
  To: Eric Sandeen; +Cc: xfs-oss


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

On Tue, Mar 29, 2016 at 6:17 PM, Eric Sandeen <sandeen@sandeen.net> wrote:

>
>
> On 3/29/16 11:11 AM, Jan Tulak wrote:
> > On Thu, Mar 24, 2016 at 5:33 PM, Eric Sandeen <sandeen@sandeen.net
> <mailto:sandeen@sandeen.net>>wrote:
> >
> >
> >
> >     On 3/24/16 6:15 AM, jtulak@redhat.com <mailto:jtulak@redhat.com>
> wrote:
> >     > From: Dave Chinner <dchinner@redhat.com <mailto:
> dchinner@redhat.com>>
> >     >
> >     > Because passing "-n ftype=2" should fail.
> >
> >     but passing crc=1 ftype=1 shouldn't fail, should it?
> >     Seems like it will here.
> >
> >
> > ​From man page:
> > When  CRCs are enabled via -m crc=1, the ftype functionality is always
> enabled. This feature can not be
> > ​
> > turned off for such filesystem configurations.​
> >
> >
> > ​So I think it should not be possible to enter both crc and ftype at
> > the same time - which is the current behaviour. It feels strange a
> > bit to allow ftype=1 (which does nothing with crc=1), but fail on
> > ftype=0​
>
> My point is that -m crc=1 -d ftype=1 simply restates the defaults.
> Why should that combination fail?
>
> And -m crc=0 -d ftype=0 is also perfectly acceptable.
>
> In fact, -m crc=1 -d ftype=0 is the only one of the 4 combinations
> which is not ok, but AFAICT your patch fails the other 3 as well.
>

​I removed the entire crc check - there is another one later in the code,
so this was 1) redundant, 2) wrong, because it depended on whether -m crc=0
was before or after -n ftype (if after, default crc value was used for the
check).

However, it causes lots of conflicts on the following patches, so I will
send it later, once there are more changes...

Cheers, and thanks for catching it.

Jan

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

[-- Attachment #1.2: Type: text/html, Size: 3750 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] 84+ messages in thread

* Re: [PATCH 01/19] xfsprogs: use common code for multi-disk detection
  2016-03-24 11:15 ` [PATCH 01/19] xfsprogs: use common code for multi-disk detection jtulak
@ 2016-03-31 20:25   ` Eric Sandeen
  2016-04-06  9:05     ` Jan Tulak
  0 siblings, 1 reply; 84+ messages in thread
From: Eric Sandeen @ 2016-03-31 20:25 UTC (permalink / raw)
  To: xfs

On 3/24/16 6:15 AM, jtulak@redhat.com wrote:
> From: Dave Chinner <dchinner@redhat.com>
> 
> CHANGELOG:
> o Remove nonexistent headers from LIBHFILES in include/Makefile
> o Remove a useless assignment which was immediately overwritten
>   on the next line.
> o Rename include/xfs_mkfs.h global header to include/xfs_multidisk.h,
>   because we need it just for multidisk configuration
> o Fix AG count for size thresholds to keep consistency
> 
> 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.

Minor comment stuff below, otherwise seems ok.

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

and feel free to add that if you make the suggested changes, too.

> diff --git a/include/xfs_multidisk.h b/include/xfs_multidisk.h
> new file mode 100644
> index 0000000..4006a01
> --- /dev/null
> +++ b/include/xfs_multidisk.h


<big snip this is mostly just a file rename, but...>

> +/*
> + * 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 avoid to it at the IO level.

"avoid to it?"  Maybe "available to it?"

...

> @@ -664,43 +664,45 @@ 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 between 128MB and 4TB in size
> +	 * just use 4 AGs and scale up smoothly between min/max AG sizes.

I guess a comment about the *first* >= 4T case might make this more
clear; it's a little odd to document only 1 of the 2 cases below.

Maybe:

+	 * 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/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;
> 

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

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

* Re: [PATCH 03/19] mkfs: Sanitise the superblock feature macros
  2016-03-24 11:15 ` [PATCH 03/19] mkfs: Sanitise the superblock feature macros jtulak
@ 2016-04-01  2:05   ` Eric Sandeen
  2016-04-06  9:12     ` Jan Tulak
  2016-04-07  0:12   ` Eric Sandeen
  2016-04-07  1:43   ` Eric Sandeen
  2 siblings, 1 reply; 84+ messages in thread
From: Eric Sandeen @ 2016-04-01  2:05 UTC (permalink / raw)
  To: xfs

On 3/24/16 6:15 AM, jtulak@redhat.com wrote:
> From: Dave Chinner <dchinner@redhat.com>
> 
> UPDATE
> o disable finobt when crc=0 no matter if user used -m finobt=X
> o split line > 80 chars
> o remove unused variable
> o add omitted finobtflag
> o change variables in spinodes case to look like surrounding code
> o add I_ALIGN reqval

Just FYI - generally, the patch changelog goes below the "---"
so it doesn't end up as part of the changelog in git.

...

(sorry for being late to the review party btw...)

>  	} 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.
> +		 * 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 a warning before turning
> +		 * them off.
>  		 */
> -		if (finobt && finobtflag) {
> -			fprintf(stderr,
> -_("warning: finobt not supported without CRC support, disabled.\n"));
> +		if (sb_feat.finobt){
> +			if (sb_feat.finobtflag) {
> +				fprintf(stderr,
> +	_("warning: finobt not supported without CRC support, disabled.\n"));
> +			}
> +			sb_feat.finobt = 0;
>  		}
> -		finobt = 0;
>  	}

Is there any other case in mkfs where options are automatically disabled?
I don't think so .. I'd just prefer a failure here, not a fix-up, even
with the warning.  But I guess that's how it was before, so probably
not something to change in this patch.  So never mind.  :)

But, do we need the extra indentation?

		if (sb_feat.finobt && sb_feat.finobtflag) {
			fprintf(stderr,
_("warning: finobt not supported without CRC support, disabled.\n"));
		}
		sb_feat.finobt = 0;

would suffice as before, no? Meh.  Not a big deal I guess....

> @@ -2962,7 +3038,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){
                                    ^ please fix whitespace :)

>  			xfs_perag_put(pag);
>  			continue;
>  		}
> 

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

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

* Re: [PATCH 01/19] xfsprogs: use common code for multi-disk detection
  2016-03-31 20:25   ` Eric Sandeen
@ 2016-04-06  9:05     ` Jan Tulak
  0 siblings, 0 replies; 84+ messages in thread
From: Jan Tulak @ 2016-04-06  9:05 UTC (permalink / raw)
  To: Eric Sandeen; +Cc: xfs-oss


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

On Thu, Mar 31, 2016 at 10:25 PM, Eric Sandeen <sandeen@sandeen.net> wrote:
>
>
> Minor comment stuff below, otherwise seems ok.
>
> Reviewed-by: Eric Sandeen <sandeen@redhat.com>
>
> and feel free to add that if you make the suggested changes, too.
>

​Changed, thanks. :-)​


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

[-- Attachment #1.2: Type: text/html, Size: 1137 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] 84+ messages in thread

* Re: [PATCH 03/19] mkfs: Sanitise the superblock feature macros
  2016-04-01  2:05   ` Eric Sandeen
@ 2016-04-06  9:12     ` Jan Tulak
  2016-04-06 21:01       ` Dave Chinner
  0 siblings, 1 reply; 84+ messages in thread
From: Jan Tulak @ 2016-04-06  9:12 UTC (permalink / raw)
  To: Eric Sandeen; +Cc: xfs-oss


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

On Fri, Apr 1, 2016 at 4:05 AM, Eric Sandeen <sandeen@sandeen.net> wrote:

> On 3/24/16 6:15 AM, jtulak@redhat.com wrote:
>


> Just FYI - generally, the patch changelog goes below the "---"
> so it doesn't end up as part of the changelog in git.
>
> ​Good idea, next time it should be there.​


> >       } 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.
> > +              * 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 a warning before
> turning
> > +              * them off.
> >                */
> > -             if (finobt && finobtflag) {
> > -                     fprintf(stderr,
> > -_("warning: finobt not supported without CRC support, disabled.\n"));
> > +             if (sb_feat.finobt){
> > +                     if (sb_feat.finobtflag) {
> > +                             fprintf(stderr,
> > +     _("warning: finobt not supported without CRC support,
> disabled.\n"));
> > +                     }
> > +                     sb_feat.finobt = 0;
> >               }
> > -             finobt = 0;
> >       }
>
> Is there any other case in mkfs where options are automatically disabled?
> I don't think so .. I'd just prefer a failure here, not a fix-up, even
> with the warning.  But I guess that's how it was before, so probably
> not something to change in this patch.  So never mind.  :)
>
> ​Well, it was so, but as I'm trying to get rid of inconsistencies, I
changed it to a failure if both crc=0 and finobt=1 are explicitly used.



> But, do we need the extra indentation?
>
>                 if (sb_feat.finobt && sb_feat.finobtflag) {
>                         fprintf(stderr,
> _("warning: finobt not supported without CRC support, disabled.\n"));
>                 }
>                 sb_feat.finobt = 0;
>
> would suffice as before, no? Meh.  Not a big deal I guess....
>

​Changed. Honestly, I don't like the strings starting at the beginning of
the line, because it breaks the indentation flow, but the rest of the code
uses this style, so I should stick to it.​



> > @@ -2962,7 +3038,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){
>                                     ^ please fix whitespace :)
>

​Done.

Thank you for the review. I will wait a little longer if someone spots
something more, before sending an updated patchset.​ :-)

​Cheers,
Jan​


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

[-- Attachment #1.2: Type: text/html, Size: 5962 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] 84+ messages in thread

* Re: [PATCH 03/19] mkfs: Sanitise the superblock feature macros
  2016-04-06  9:12     ` Jan Tulak
@ 2016-04-06 21:01       ` Dave Chinner
  2016-04-07 11:53         ` Jan Tulak
  0 siblings, 1 reply; 84+ messages in thread
From: Dave Chinner @ 2016-04-06 21:01 UTC (permalink / raw)
  To: Jan Tulak; +Cc: Eric Sandeen, xfs-oss

On Wed, Apr 06, 2016 at 11:12:21AM +0200, Jan Tulak wrote:
> On Fri, Apr 1, 2016 at 4:05 AM, Eric Sandeen <sandeen@sandeen.net> wrote:
> > On 3/24/16 6:15 AM, jtulak@redhat.com wrote:
> >                 if (sb_feat.finobt && sb_feat.finobtflag) {
> >                         fprintf(stderr,
> > _("warning: finobt not supported without CRC support, disabled.\n"));
> >                 }
> >                 sb_feat.finobt = 0;
> >
> > would suffice as before, no? Meh.  Not a big deal I guess....
> >
> 
> ​Changed. Honestly, I don't like the strings starting at the beginning of
> the line, because it breaks the indentation flow, but the rest of the code
> uses this style, so I should stick to it.​

There's good reason for doing this - it makes it easy to grep the
source code for a specific error that has been emitted. Indentation
is useful for demonstrating logic flow, but it's harmful when it
results in strings you might want to find being split up over
multiple lines.

> Thank you for the review. I will wait a little longer if someone spots
> something more, before sending an updated patchset.​ :-)

Just send it - I almost got to pulling in this version and
fixing the various comments directly myself yesterday....

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] 84+ messages in thread

* Re: [PATCH 18/19] mkfs: unit conversions are case insensitive
  2016-03-24 11:15 ` [PATCH 18/19] mkfs: unit conversions are case insensitive jtulak
@ 2016-04-06 21:10   ` Eric Sandeen
  2016-04-07 10:50     ` Jan Tulak
  0 siblings, 1 reply; 84+ messages in thread
From: Eric Sandeen @ 2016-04-06 21:10 UTC (permalink / raw)
  To: xfs

On 3/24/16 6:15 AM, jtulak@redhat.com wrote:
> From: Jan Tulak <jtulak@redhat.com>
> 
> Solves the question "Should I use 10g or 10G?"

Might be nicer to do it like the cvtnum in libxcmd:

        c = tolower(*sp);
        switch (c) {
        case 'b':
                return i * blocksize;
...

(hm, why do we have 3 copies of cvtnum?)
 
> Signed-off-by: Jan Tulak <jtulak@redhat.com>
> ---
>  mkfs/xfs_mkfs.c | 12 ++++++------
>  1 file changed, 6 insertions(+), 6 deletions(-)
> 
> diff --git a/mkfs/xfs_mkfs.c b/mkfs/xfs_mkfs.c
> index 2bb3b35..680c6c4 100644
> --- a/mkfs/xfs_mkfs.c
> +++ b/mkfs/xfs_mkfs.c
> @@ -3625,17 +3625,17 @@ cvtnum(
>  	if (*sp == 's' && sp[1] == '\0')
>  		return i * sectsize;
>  
> -	if (*sp == 'k' && sp[1] == '\0')
> +	if ((*sp == 'k'  || *sp == 'K' ) && sp[1] == '\0')
                        ^ 1 space is enough, no?

I guess doing it this way doesn't really bother me, but
the whitespace is messy and if you're here anyway,
tolower() might be simpler.

-Eric

>  		return 1024LL * i;
> -	if (*sp == 'm' && sp[1] == '\0')
> +	if ((*sp == 'm'  || *sp == 'M' ) && sp[1] == '\0')
>  		return 1024LL * 1024LL * i;
> -	if (*sp == 'g' && sp[1] == '\0')
> +	if ((*sp == 'g'  || *sp == 'G' ) && sp[1] == '\0')
>  		return 1024LL * 1024LL * 1024LL * i;
> -	if (*sp == 't' && sp[1] == '\0')
> +	if ((*sp == 't'  || *sp == 'T' ) && sp[1] == '\0')
>  		return 1024LL * 1024LL * 1024LL * 1024LL * i;
> -	if (*sp == 'p' && sp[1] == '\0')
> +	if ((*sp == 'p'  || *sp == 'P' ) && sp[1] == '\0')
>  		return 1024LL * 1024LL * 1024LL * 1024LL * 1024LL * i;
> -	if (*sp == 'e' && sp[1] == '\0')
> +	if ((*sp == 'e'  || *sp == 'E' ) && sp[1] == '\0')
>  		return 1024LL * 1024LL * 1024LL * 1024LL * 1024LL * 1024LL * i;
>  	return -1LL;
>  }
> 

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

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

* Re: [PATCH 17/19] xfsprogs: disable truncating of files
  2016-03-24 11:15 ` [PATCH 17/19] xfsprogs: disable truncating of files jtulak
@ 2016-04-06 21:42   ` Eric Sandeen
  2016-04-07  9:41     ` Jan Tulak
  2016-04-08  0:09   ` Dave Chinner
  1 sibling, 1 reply; 84+ messages in thread
From: Eric Sandeen @ 2016-04-06 21:42 UTC (permalink / raw)
  To: xfs

On 3/24/16 6:15 AM, jtulak@redhat.com wrote:
> From: Jan Tulak <jtulak@redhat.com>
> 
> Unify mkfs.xfs behaviour a bit and never truncate files. If the user
> is trying to mkfs an existing file, we don't want to destroy anything
> he did with the file before (sparse file, allocations...)

Hm, I guess so ...  What motivated this change?  I see that it
changes behavior, but I'm not sure what it unifies or fixes - 
can you explain more?

a bit more below.
 
> Signed-off-by: Jan Tulak <jtulak@redhat.com>
> ---
>  libxfs/init.c   |  2 +-
>  mkfs/xfs_mkfs.c | 18 +++++++++++-------
>  2 files changed, 12 insertions(+), 8 deletions(-)
> 
> diff --git a/libxfs/init.c b/libxfs/init.c
> index 268136f..5f4b6c4 100644
> --- a/libxfs/init.c
> +++ b/libxfs/init.c
> @@ -112,7 +112,7 @@ libxfs_device_open(char *path, int creat, int xflags, int setblksize)
>  
>  retry:
>  	flags = (readonly ? O_RDONLY : O_RDWR) | \
> -		(creat ? (O_CREAT|O_TRUNC) : 0) | \
> +		(creat ? O_CREAT : 0) | \
>  		(dio ? O_DIRECT : 0) | \
>  		(excl ? O_EXCL : 0);
>  
> diff --git a/mkfs/xfs_mkfs.c b/mkfs/xfs_mkfs.c
> index 9a6ae2c..2bb3b35 100644
> --- a/mkfs/xfs_mkfs.c
> +++ b/mkfs/xfs_mkfs.c
> @@ -1029,15 +1029,19 @@ check_device_type(
>  	const char	*optname)
>  {
>  	struct stat64 statbuf;
> +	int statres;
>  
> -	if (*isfile && (no_size || no_name)) {
> +	statres = stat64(name, &statbuf);
> +
> +	if (*isfile && statres != 0 && (no_size || no_name)) {

statres !=0 doesn't imply ENOENT; it could be EACCES
or several other errors.  You'd need to check errno to know
for sure.

>  		fprintf(stderr,
> -	_("if -%s file then -%s name and -%s size are required\n"),
> -			optname, optname, optname);
> +			_("if -%s file and the file does not exists, " \

don't need a "\" there, and should read "does not exist"

> +			"then -%s name and -%s size are required\n"),

Better, just tab it out if possible, though it's a long line... perhaps:

_("-%s file requires -%s name and -%s size for file creation\n");

or something like that.

> +					optname, optname, optname);
>  		usage();
>  	}
>  
> -	if (stat64(name, &statbuf)) {
> +	if (statres) {
>  		if (errno == ENOENT && *isfile) {
>  			if (create)
>  				*create = 1;
> @@ -1059,9 +1063,9 @@ check_device_type(
>  	}
>  
>  	/*
> -	 * 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.
> +	 * We only want to create a file only if we were specifically told
> +	 * we want a file. Set the create flag only in this case to trigger
> +	 * that behaviour.

+	 * We only want to create a file if we were specifically told it is a
+	 * file. Set the create flag only in this case to trigger that behaviour.

>  	 */
>  	if (S_ISREG(statbuf.st_mode)) {
>  		if (!*isfile)
> 

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

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

* Re: [PATCH 19/19] mkfs: add optional 'reason' for illegal_option
  2016-03-24 11:15 ` [PATCH 19/19] mkfs: add optional 'reason' for illegal_option jtulak
@ 2016-04-06 22:23   ` Eric Sandeen
  0 siblings, 0 replies; 84+ messages in thread
From: Eric Sandeen @ 2016-04-06 22:23 UTC (permalink / raw)
  To: xfs

On 3/24/16 6:15 AM, jtulak@redhat.com wrote:
> From: Jan Tulak <jtulak@redhat.com>
> 
> Allow us to tell the user what exactly is wrong with his options.

"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>
> ---
>  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 680c6c4..76e193d 100644
> --- a/mkfs/xfs_mkfs.c
> +++ b/mkfs/xfs_mkfs.c
> @@ -1550,11 +1550,18 @@ static __attribute__((noreturn)) void
>  illegal_option(
>  	const char	*value,
>  	struct opt_params	*opts,
> -	int		index)
> +	int		index,
> +	const char *reason)
                   ^ tab that out to match.
>  {
> -	fprintf(stderr,
> -		_("Illegal value %s for -%c %s option\n"),
> -		value, opts->name, opts->subopts[index]);
> +	if(reason == NULL){
          ^space          ^space
> +		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();
>  }
> 
> @@ -1646,16 +1653,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 has to be power of 2");

                                                 "value must be a power of 2"


The "reason" strings should be translatable strings too, right? :  _(" ... ")

-Eric

>  	return c;
>  }
> 
> --
> 2.6.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	[flat|nested] 84+ messages in thread

* Re: [PATCH 04/19] mkfs: validate all input values
  2016-03-24 11:15 ` [PATCH 04/19] mkfs: validate all input values jtulak
@ 2016-04-06 23:02   ` Eric Sandeen
  2016-04-07 11:15     ` Jan Tulak
  0 siblings, 1 reply; 84+ messages in thread
From: Eric Sandeen @ 2016-04-06 23:02 UTC (permalink / raw)
  To: xfs

On 3/24/16 6:15 AM, jtulak@redhat.com wrote:
> From: Dave Chinner <dchinner@redhat.com>
> 
> CHANGELOG
> o Fix an unsigned < 0 comparison - save getnum result to another variable
>   and test it, before converting it to unsigned logagno.

...

> @@ -1468,7 +1485,10 @@ main(
>  						respec('l', lopts, L_AGNUM);
>  					if (ldflag)
>  						conflict('l', lopts, L_AGNUM, L_DEV);
> -					logagno = atoi(value);
> +					tmp_num = getnum(value, 0, 0, false);
> +					if (tmp_num < 0)
> +						illegal(value, "l agno");
> +					logagno = (xfs_agnumber_t)tmp_num;
>  					laflag = 1;
>  					break;
>  				case L_FILE:

Why not cast to (__int64_t) like other variables do?  i.e.


+					logagno = getnum(value, 0, 0, false);
+					if ((__int64_t)logagno < 0)
+						illegal(value, "l agno");

or am I missing something?

Thanks,
-Eric

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

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

* Re: [PATCH 03/19] mkfs: Sanitise the superblock feature macros
  2016-03-24 11:15 ` [PATCH 03/19] mkfs: Sanitise the superblock feature macros jtulak
  2016-04-01  2:05   ` Eric Sandeen
@ 2016-04-07  0:12   ` Eric Sandeen
  2016-04-07  1:43   ` Eric Sandeen
  2 siblings, 0 replies; 84+ messages in thread
From: Eric Sandeen @ 2016-04-07  0:12 UTC (permalink / raw)
  To: xfs

On 3/24/16 6:15 AM, jtulak@redhat.com wrote:
> @@ -1262,10 +1358,11 @@ main(
>  				switch (getsubopt(&p, (constpp)iopts, &value)) {
>  				case I_ALIGN:
>  					if (!value || *value == '\0')
> -						value = "1";
> -					iaflag = atoi(value);
> -					if (iaflag < 0 || iaflag > 1)
> +						reqval('i', iopts, I_ALIGN);
> +					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')


Hm, this seems wrong, as well - per the man page:

"If the value is omitted, 1 is assumed."

but this change with the reqval() removes that, doesn't it?  Why?
(it's fixed later, but there is no reason to break it mid-series...)

Before this patch:

# mkfs/mkfs.xfs -dfile,name=fsfile,size=1g -i align
meta-data=fsfile                 isize=512    agcount=4, agsize=65536 blks
         =                       sectsz=512   attr=2, projid32bit=1
         =                       crc=1        finobt=1, sparse=0
data     =                       bsize=4096   blocks=262144, imaxpct=25
         =                       sunit=0      swidth=0 blks
naming   =version 2              bsize=4096   ascii-ci=0 ftype=1
log      =internal log           bsize=4096   blocks=2560, version=2
         =                       sectsz=512   sunit=0 blks, lazy-count=1
realtime =none                   extsz=4096   blocks=0, rtextents=0


After this patch:

# mkfs/mkfs.xfs -dfile,name=fsfile,size=1g -i align
-i align option requires a value
Usage: mkfs.xfs
/* blocksize */		[-b log=n|size=num]
/* metadata */		[-m crc=0|1,finobt=0|1,uuid=xxx]
/* data subvol */	[-d agcount=n,agsize=n,file,name=xxx,size=num,
			    (sunit=value,swidth=value|su=num,sw=num|noalign),
			    sectlog=n|sectsize=num
...


-Eric

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

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

* Re: [PATCH 03/19] mkfs: Sanitise the superblock feature macros
  2016-03-24 11:15 ` [PATCH 03/19] mkfs: Sanitise the superblock feature macros jtulak
  2016-04-01  2:05   ` Eric Sandeen
  2016-04-07  0:12   ` Eric Sandeen
@ 2016-04-07  1:43   ` Eric Sandeen
  2016-04-07 13:09     ` Jan Tulak
  2 siblings, 1 reply; 84+ messages in thread
From: Eric Sandeen @ 2016-04-07  1:43 UTC (permalink / raw)
  To: xfs

On 3/24/16 6:15 AM, jtulak@redhat.com wrote:
> From: Dave Chinner <dchinner@redhat.com>
> 
> UPDATE
> o disable finobt when crc=0 no matter if user used -m finobt=X
> o split line > 80 chars
> o remove unused variable
> o add omitted finobtflag
> o change variables in spinodes case to look like surrounding code
> o add I_ALIGN reqval
> 
> 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.

sorry for multiple passes. More comments below.

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

> diff --git a/mkfs/xfs_mkfs.c b/mkfs/xfs_mkfs.c
> index 979a860..36bcb9f 100644
> --- a/mkfs/xfs_mkfs.c
> +++ b/mkfs/xfs_mkfs.c

...

> @@ -981,11 +1077,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,


should we really have "finobtflag" in this structure?
This structure should only carry feature selections, not feature
specification flags I think.  Why is this the only such flag
in the structure?

Pretty sure finobtflag should stay a variable for now
just like lvflag (which goes with log_version).

> +		.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]);

...

> @@ -1517,7 +1617,14 @@ main(
>  					c = atoi(value);
>  					if (c < 0 || c > 1)
>  						illegal(value, "m crc");
> -					crcs_enabled = c;
> +					if (c && nftype) {
> +						fprintf(stderr,
> +_("cannot specify both crc and ftype\n"));
> +						usage();

hm, why is conflict checking added?  It's not what the commit says
the patch does.

It also regresses the bug I fixed in 

commit b990de8ba4e2df2bc76a140799d3ddb4a0eac4ce
Author: Eric Sandeen <sandeen@sandeen.net>
Date:   Tue Aug 18 17:53:17 2015 +1000

    mkfs.xfs: fix ftype-vs-crc option combination testing

with this patch, it is broken again:

# mkfs/mkfs.xfs -m crc=0 -n ftype=1 -dfile,name=fsfile,size=16g
<success>
 # mkfs/mkfs.xfs -n ftype=1 -m crc=0 -dfile,name=fsfile,size=16g
cannot specify both crc and ftype
Usage: mkfs.xfs
...


> +					}
> +					sb_feat.crcs_enabled = c ? true : false;
> +					if (c)
> +						sb_feat.dirftype = true;
>  					break;
>  				case M_FINOBT:
>  					if (!value || *value == '\0')
> @@ -1525,8 +1632,8 @@ main(
>  					c = atoi(value);
>  					if (c < 0 || c > 1)
>  						illegal(value, "m finobt");
> -					finobt = c;
> -					finobtflag = true;
> +					sb_feat.finobtflag = true;

yep this should just stay "finobtflag" I think.

> +					sb_feat.finobt = c;
>  					break;
>  				case M_UUID:
>  					if (!value || *value == '\0')
...

> @@ -1879,23 +1988,25 @@ _("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.
> +		 * 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 a warning before turning
> +		 * them off.
>  		 */
> -		if (finobt && finobtflag) {
> -			fprintf(stderr,
> -_("warning: finobt not supported without CRC support, disabled.\n"));
> +		if (sb_feat.finobt){
> +			if (sb_feat.finobtflag) {
> +				fprintf(stderr,
> +	_("warning: finobt not supported without CRC support, disabled.\n"));
> +			}
> +			sb_feat.finobt = 0;

like I mentioned, just this, I think (assuming we like the silent turning
off, but that would be a different patch):

-               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;
        }


>  		}
> -		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) {

-Eric

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

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

* Re: [PATCH 05/19] mkfs: factor boolean option parsing
  2016-03-24 11:15 ` [PATCH 05/19] mkfs: factor boolean option parsing jtulak
@ 2016-04-07  2:48   ` Eric Sandeen
  0 siblings, 0 replies; 84+ messages in thread
From: Eric Sandeen @ 2016-04-07  2:48 UTC (permalink / raw)
  To: xfs

On 3/24/16 6:15 AM, jtulak@redhat.com wrote:
> From: Dave Chinner <dchinner@redhat.com>
> 
> UPDATE:
> - add a forgotten getbool update to FINOBT
> - change -m crc and ftype to enable by specifying (instead of toggle off)
> 
> 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>
> ---
>  mkfs/xfs_mkfs.c | 109 +++++++++++++++++++++++---------------------------------
>  1 file changed, 44 insertions(+), 65 deletions(-)
> 
> diff --git a/mkfs/xfs_mkfs.c b/mkfs/xfs_mkfs.c
> index 4811d77..9394bd3 100644
> --- a/mkfs/xfs_mkfs.c
> +++ b/mkfs/xfs_mkfs.c

...

> @@ -1451,12 +1459,8 @@ 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')

I_SPINODES now needs the getbool() treatment as well.

...

> @@ -1631,28 +1625,20 @@ 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");
> -					if (c && nftype) {
> +					sb_feat.crcs_enabled = getbool(
> +							value, "m crc", true);
> +					if (sb_feat.crcs_enabled && nftype) {
>  						fprintf(stderr,
> -_("cannot specify both crc and ftype\n"));
> +_("cannot specify both -m crc=1 and -n ftype\n"));
>  						usage();
>  					}
> -					sb_feat.crcs_enabled = c ? true : false;
> -					if (c)
> +					if (sb_feat.crcs_enabled)
>  						sb_feat.dirftype = true;
>  					break;
>  				case M_FINOBT:
> -					if (!value || *value == '\0')
> -						reqval('m', mopts, M_CRC);

                                                                   ^^^ whoops ;)
Well that bug goes away now ;)

> -					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')

Other than SPINODES this one looks ok to me.

-Eric

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

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

* Re: [PATCH 06/19] mkfs: validate logarithmic parameters sanely
  2016-03-24 11:15 ` [PATCH 06/19] mkfs: validate logarithmic parameters sanely jtulak
@ 2016-04-07  2:52   ` Eric Sandeen
  0 siblings, 0 replies; 84+ messages in thread
From: Eric Sandeen @ 2016-04-07  2:52 UTC (permalink / raw)
  To: xfs



On 3/24/16 6:15 AM, jtulak@redhat.com wrote:
> 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.:

<<<<<  >>>>>>>

This lost pat of Dave's original commit log, which said:

# mkfs.xfs -f -n log=456858480 /dev/vda

> .....
> 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>

otherwise,

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 9394bd3..dda076d 100644
> --- a/mkfs/xfs_mkfs.c
> +++ b/mkfs/xfs_mkfs.c
> @@ -1022,6 +1022,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,
> @@ -1179,16 +1200,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;
> @@ -1325,16 +1346,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;
> @@ -1399,9 +1420,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;
> @@ -1573,16 +1596,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;
> @@ -1658,16 +1681,16 @@ _("cannot specify both -m crc=1 and -n ftype\n"));
>  
>  				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;
> @@ -1786,16 +1809,16 @@ _("cannot specify both -m crc=1 and -n ftype\n"));
>  				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;
> 

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

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

* Re: [PATCH 07/19] mkfs: structify input parameter passing
  2016-03-24 11:15 ` [PATCH 07/19] mkfs: structify input parameter passing jtulak
@ 2016-04-07  3:14   ` Eric Sandeen
  2016-04-07 11:43     ` Jan Tulak
  0 siblings, 1 reply; 84+ messages in thread
From: Eric Sandeen @ 2016-04-07  3:14 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 a description of the new opt_params structure.
> o Fix indenting
> o Add missing I_SPINODES to subopt_params
> o Add a check for undefined minval/maxval into getnum_checked
> o Drop "const" from struct opt_params - it would be removed in a later
>   patch anyway
> 
> 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.

All the code looks ok, nitpicks on docs below.

> Signed-off-by: Dave Chinner <dchinner@redhat.com>
> Signed-off-by: Jan Tulak <jtulak@redhat.com>
> ---
>  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 dda076d..6e29848 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 coresponding entry has to be defined:

"corresponding"

> + *
> + * 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 either has

then you must either supply your own validation, or ...

> + *     to supply your own validation, or refuse any value in the 'case
> + *     X_SOMETHING' block. If you forget to pass a min or max value here, but

forget to define a min and max value (?)

> + *     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.)

I think that makes sense ... by the time I got to the end of this I was a
little confused.  ;)

So you don't have to define min/max, but if you call getnum_checked(), then
min & max are required, and they can't both be zero - is that correct?

Thanks,
-Eric

>   */
> -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)))
> @@ -1022,24 +1236,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;
>  }
>  
> @@ -1196,30 +1428,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);
> @@ -1237,14 +1468,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");
> @@ -1252,9 +1485,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)
> @@ -1269,25 +1502,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)
> @@ -1295,11 +1528,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)
> @@ -1307,11 +1540,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);
> @@ -1320,11 +1553,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)
> @@ -1332,40 +1565,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);
> @@ -1382,14 +1612,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;
> @@ -1402,37 +1632,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");
> @@ -1440,14 +1667,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 <
> @@ -1458,15 +1685,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");
> @@ -1475,7 +1702,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");
> @@ -1501,17 +1728,19 @@ main(
>  		case 'l':
>  			p = optarg;
>  			while (*p != '\0') {
> +				char	**subopts = (char **)lopts.subopts;
>  				char	*value;
>  				long long tmp_num;
>  
> -				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);
>  					tmp_num = getnum(value, 0, 0, false);
>  					if (tmp_num < 0)
>  						illegal(value, "l agno");
> @@ -1520,7 +1749,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);
> @@ -1529,12 +1758,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);
> @@ -1542,9 +1771,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)
> @@ -1553,9 +1782,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");
> @@ -1564,13 +1793,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;
> @@ -1578,9 +1807,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");
> @@ -1589,33 +1818,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);
> @@ -1644,9 +1870,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);
> @@ -1665,7 +1893,7 @@ _("cannot specify both -m crc=1 and -n ftype\n"));
>  					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;
> @@ -1677,30 +1905,29 @@ _("cannot specify both -m crc=1 and -n ftype\n"));
>  		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);
> @@ -1713,9 +1940,9 @@ _("cannot specify both -m crc=1 and -n ftype\n"));
>  					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;
> @@ -1730,7 +1957,7 @@ _("cannot specify both -m crc=1 and -n ftype\n"));
>  					break;
>  				case N_FTYPE:
>  					if (nftype)
> -						respec('n', nopts, N_FTYPE);
> +						respec('n', subopts, N_FTYPE);
>  					if (sb_feat.crcs_enabled) {
>  						fprintf(stderr,
>  _("cannot specify both -m crc=1 and -n ftype\n"));
> @@ -1762,14 +1989,16 @@ _("cannot specify both -m crc=1 and -n ftype\n"));
>  		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:
> @@ -1781,16 +2010,16 @@ _("cannot specify both -m crc=1 and -n ftype\n"));
>  				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:
> @@ -1804,21 +2033,20 @@ _("cannot specify both -m crc=1 and -n ftype\n"));
>  		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;
> @@ -1827,11 +2055,11 @@ _("cannot specify both -m crc=1 and -n ftype\n"));
>  				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);
> 

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

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

* Re: [PATCH 17/19] xfsprogs: disable truncating of files
  2016-04-06 21:42   ` Eric Sandeen
@ 2016-04-07  9:41     ` Jan Tulak
  0 siblings, 0 replies; 84+ messages in thread
From: Jan Tulak @ 2016-04-07  9:41 UTC (permalink / raw)
  To: Eric Sandeen; +Cc: xfs-oss


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

On Wed, Apr 6, 2016 at 11:42 PM, Eric Sandeen <sandeen@sandeen.net> wrote:

> On 3/24/16 6:15 AM, jtulak@redhat.com wrote:
> > From: Jan Tulak <jtulak@redhat.com>
> >
> > Unify mkfs.xfs behaviour a bit and never truncate files. If the user
> > is trying to mkfs an existing file, we don't want to destroy anything
> > he did with the file before (sparse file, allocations...)
>
> Hm, I guess so ...  What motivated this change?  I see that it
> changes behavior, but I'm not sure what it unifies or fixes -
> can you explain more?
>
> Both, I think. The non-truncating is a new change, a fix of undesired side
effects, where user lost his changes to the file, like sparse file... The
rest should be unifying the behavior w.r.t. mkfs arguments. Do you think
that the O_TRUNC change should be a separate patch?


> > +     if (*isfile && statres != 0 && (no_size || no_name)) {
>
> statres !=0 doesn't imply ENOENT; it could be EACCES
> or several other errors.  You'd need to check errno to know
> for sure.
>
> ​Well, then I need to print two errors. One if the file doesn't exists,
but additional arguments will fix it, and one for other cases, where I will
print the specific error...

​Cheers,
Jan​



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

[-- Attachment #1.2: Type: text/html, Size: 2872 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] 84+ messages in thread

* Re: [PATCH 18/19] mkfs: unit conversions are case insensitive
  2016-04-06 21:10   ` Eric Sandeen
@ 2016-04-07 10:50     ` Jan Tulak
  2016-04-08  0:41       ` Eric Sandeen
  0 siblings, 1 reply; 84+ messages in thread
From: Jan Tulak @ 2016-04-07 10:50 UTC (permalink / raw)
  To: Eric Sandeen; +Cc: xfs-oss


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

On Wed, Apr 6, 2016 at 11:10 PM, Eric Sandeen <sandeen@sandeen.net> wrote:

> On 3/24/16 6:15 AM, jtulak@redhat.com wrote:
> > From: Jan Tulak <jtulak@redhat.com>
> >
> > Solves the question "Should I use 10g or 10G?"
>
> Might be nicer to do it like the cvtnum in libxcmd:
>
>         c = tolower(*sp);
>         switch (c) {
>         case 'b':
>                 return i * blocksize;
> ...
>
​Yeah, changed.
​


>
> (hm, why do we have 3 copies of cvtnum?)
>

​Where? ​
 ​

​$ pwd
​/some/path/xfsprogs-dev

$ grep -r "cvtnum(size_t" . |grep -v "^Binary"
​./include/input.h:extern long long cvtnum(size_t blocksize, size_t
sectorsize, char *s);
./io/init.h:extern void init_cvtnum(size_t *blocksize, size_t *sectsize);

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

[-- Attachment #1.2: Type: text/html, Size: 2779 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] 84+ messages in thread

* Re: [PATCH 04/19] mkfs: validate all input values
  2016-04-06 23:02   ` Eric Sandeen
@ 2016-04-07 11:15     ` Jan Tulak
  0 siblings, 0 replies; 84+ messages in thread
From: Jan Tulak @ 2016-04-07 11:15 UTC (permalink / raw)
  To: Eric Sandeen; +Cc: xfs-oss


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

On Thu, Apr 7, 2016 at 1:02 AM, Eric Sandeen <sandeen@sandeen.net> wrote:

> On 3/24/16 6:15 AM, jtulak@redhat.com wrote:
> > From: Dave Chinner <dchinner@redhat.com>
> >
> > CHANGELOG
> > o Fix an unsigned < 0 comparison - save getnum result to another variable
> >   and test it, before converting it to unsigned logagno.
>
> ...
>
> > @@ -1468,7 +1485,10 @@ main(
> >                                               respec('l', lopts,
> L_AGNUM);
> >                                       if (ldflag)
> >                                               conflict('l', lopts,
> L_AGNUM, L_DEV);
> > -                                     logagno = atoi(value);
> > +                                     tmp_num = getnum(value, 0, 0,
> false);
> > +                                     if (tmp_num < 0)
> > +                                             illegal(value, "l agno");
> > +                                     logagno = (xfs_agnumber_t)tmp_num;
> >                                       laflag = 1;
> >                                       break;
> >                               case L_FILE:
>
> Why not cast to (__int64_t) like other variables do?  i.e.
>
>
> +                                       logagno = getnum(value, 0, 0,
> false);
> +                                       if ((__int64_t)logagno < 0)
> +                                               illegal(value, "l agno");
>
> or am I missing something?
>
> Nothing I'm aware of. Replaced.



> 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: 3488 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] 84+ messages in thread

* Re: [PATCH 07/19] mkfs: structify input parameter passing
  2016-04-07  3:14   ` Eric Sandeen
@ 2016-04-07 11:43     ` Jan Tulak
  0 siblings, 0 replies; 84+ messages in thread
From: Jan Tulak @ 2016-04-07 11:43 UTC (permalink / raw)
  To: Eric Sandeen; +Cc: xfs-oss


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

On Thu, Apr 7, 2016 at 5:14 AM, Eric Sandeen <sandeen@sandeen.net> wrote:

>
> > + *   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
> either has
>
> then you must either supply your own validation, or ...
>
> > + *     to supply your own validation, or refuse any value in the 'case
> > + *     X_SOMETHING' block. If you forget to pass a min or max value
> here, but
>
> forget to define a min and max value (?)
>
> > + *     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.)
>
> I think that makes sense ... by the time I got to the end of this I was a
> little confused.  ;)
>
> So you don't have to define min/max, but if you call getnum_checked(), then
> min & max are required, and they can't both be zero - is that correct?
>

​Yes. I couldn't find any usecase, where an option would accept only single
hardcoded value (0, in this case) as an argument, and nothing else, because
then it doesn't need the argument at all...
​

And because forgetting the min/maxval is easy (I know it first hand :-) ),
I added the check for minval==0 && maxval == 0 to raise an error if you
call getnum_checked() for this option.

​Cheers,​

​Jan​

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

[-- Attachment #1.2: Type: text/html, Size: 3346 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] 84+ messages in thread

* Re: [PATCH 03/19] mkfs: Sanitise the superblock feature macros
  2016-04-06 21:01       ` Dave Chinner
@ 2016-04-07 11:53         ` Jan Tulak
  0 siblings, 0 replies; 84+ messages in thread
From: Jan Tulak @ 2016-04-07 11:53 UTC (permalink / raw)
  To: Dave Chinner; +Cc: xfs-oss


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

On Wed, Apr 6, 2016 at 11:01 PM, Dave Chinner <david@fromorbit.com> wrote:

> On Wed, Apr 06, 2016 at 11:12:21AM +0200, Jan Tulak wrote:
> > On Fri, Apr 1, 2016 at 4:05 AM, Eric Sandeen <sandeen@sandeen.net>
> wrote:
> > > On 3/24/16 6:15 AM, jtulak@redhat.com wrote:
> > >                 if (sb_feat.finobt && sb_feat.finobtflag) {
> > >                         fprintf(stderr,
> > > _("warning: finobt not supported without CRC support, disabled.\n"));
> > >                 }
> > >                 sb_feat.finobt = 0;
> > >
> > > would suffice as before, no? Meh.  Not a big deal I guess....
> > >
> >
> > ​Changed. Honestly, I don't like the strings starting at the beginning of
> > the line, because it breaks the indentation flow, but the rest of the
> code
> > uses this style, so I should stick to it.​
>
> There's good reason for doing this - it makes it easy to grep the
> source code for a specific error that has been emitted. Indentation
> is useful for demonstrating logic flow, but it's harmful when it
> results in strings you might want to find being split up over
> multiple lines.
>

​Mmm, yeah, a valid point. It is caused by the 80 chars limit, but there
are reasons for that too​...


> > Thank you for the review. I will wait a little longer if someone spots
> > something more, before sending an updated patchset.​ :-)
>
> Just send it - I almost got to pulling in this version and
> fixing the various comments directly myself yesterday....
>

​OK. I will fix what Eric submitted in the mean time, test it to be sure I
didn't broke anything and send.

Cheers,
Jan


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

[-- Attachment #1.2: Type: text/html, Size: 3445 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] 84+ messages in thread

* Re: [PATCH 03/19] mkfs: Sanitise the superblock feature macros
  2016-04-07  1:43   ` Eric Sandeen
@ 2016-04-07 13:09     ` Jan Tulak
  2016-04-07 13:18       ` Eric Sandeen
  0 siblings, 1 reply; 84+ messages in thread
From: Jan Tulak @ 2016-04-07 13:09 UTC (permalink / raw)
  To: Eric Sandeen; +Cc: xfs-oss


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

​​

On Thu, Apr 7, 2016 at 2:12 AM, Eric Sandeen <sandeen@sandeen.net> wrote:

> On 3/24/16 6:15 AM, jtulak@redhat.com wrote:
> > @@ -1262,10 +1358,11 @@ main(
> >                               switch (getsubopt(&p, (constpp)iopts,
> &value)) {
> >                               case I_ALIGN:
> >                                       if (!value || *value == '\0')
> > -                                             value = "1";
> > -                                     iaflag = atoi(value);
> > -                                     if (iaflag < 0 || iaflag > 1)
> > +                                             reqval('i', iopts,
> I_ALIGN);
> > +                                     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')
>
>
> Hm, this seems wrong, as well - per the man page:
>
> "If the value is omitted, 1 is assumed."
>
> but this change with the reqval() removes that, doesn't it?  Why?
> (it's fixed later, but there is no reason to break it mid-series...)

​
Changed back to default 1. ​As for the origin of the change, most likely a
copy&paste from some other place, where wasn't a default value, or it was
there since I took over the patchset.

On Thu, Apr 7, 2016 at 3:43 AM, Eric Sandeen <sandeen@sandeen.net> wrote:
>
> > @@ -981,11 +1077,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,
>
>
> should we really have "finobtflag" in this structure?
> This structure should only carry feature selections, not feature
> specification flags I think.  Why is this the only such flag
> in the structure?
>
> Pretty sure finobtflag should stay a variable for now
> just like lvflag (which goes with log_version).
>
>
​It might be right to move it out​, but the flag is removed few patches
later entirely. Is it worth of the work? I would say nah, let it die where
it is. :-)



> ...
>
> > @@ -1517,7 +1617,14 @@ main(
> >                                       c = atoi(value);
> >                                       if (c < 0 || c > 1)
> >                                               illegal(value, "m crc");
> > -                                     crcs_enabled = c;
> > +                                     if (c && nftype) {
> > +                                             fprintf(stderr,
> > +_("cannot specify both crc and ftype\n"));
> > +                                             usage();
>
> hm, why is conflict checking added?  It's not what the commit says
> the patch does.
>
> It also regresses the bug I fixed in
>
> commit b990de8ba4e2df2bc76a140799d3ddb4a0eac4ce
> Author: Eric Sandeen <sandeen@sandeen.net>
> Date:   Tue Aug 18 17:53:17 2015 +1000
>
>     mkfs.xfs: fix ftype-vs-crc option combination testing
>
> with this patch, it is broken again:
>
> # mkfs/mkfs.xfs -m crc=0 -n ftype=1 -dfile,name=fsfile,size=16g
> <success>
>  # mkfs/mkfs.xfs -n ftype=1 -m crc=0 -dfile,name=fsfile,size=16g
> cannot specify both crc and ftype
> Usage: mkfs.xfs
> ...
>
> ​Because the patch is much older than your fix, and at the time it was
created, it is possible that there wasn't any such check... I would call it
the risk of necromancy. :-)​

Anyway, I already fixed this issue in this cycle, and added the the ftype,
crc order into a test checking for options sanity. Just I didn't submitted
the change yet.

...
>
> > @@ -1879,23 +1988,25 @@ _("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.
> > +              * 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 a warning before
> turning
> > +              * them off.
> >                */
> > -             if (finobt && finobtflag) {
> > -                     fprintf(stderr,
> > -_("warning: finobt not supported without CRC support, disabled.\n"));
> > +             if (sb_feat.finobt){
> > +                     if (sb_feat.finobtflag) {
> > +                             fprintf(stderr,
> > +     _("warning: finobt not supported without CRC support,
> disabled.\n"));
> > +                     }
> > +                     sb_feat.finobt = 0;
>
> like I mentioned, just this, I think (assuming we like the silent turning
> off, but that would be a different patch):
>

​Merging the conditions is indeed cleaner.

And I will change it to failure, if the conflicting options are given
explicitly. Just a small patch adding "usage();" and removing "warning"...​

Cheers,
Jan

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

[-- Attachment #1.2: Type: text/html, Size: 10018 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] 84+ messages in thread

* Re: [PATCH 03/19] mkfs: Sanitise the superblock feature macros
  2016-04-07 13:09     ` Jan Tulak
@ 2016-04-07 13:18       ` Eric Sandeen
  2016-04-07 13:27         ` Jan Tulak
  0 siblings, 1 reply; 84+ messages in thread
From: Eric Sandeen @ 2016-04-07 13:18 UTC (permalink / raw)
  To: Jan Tulak; +Cc: xfs-oss

On 4/7/16 8:09 AM, Jan Tulak wrote:
> 
...

> On Thu, Apr 7, 2016 at 3:43 AM, Eric Sandeen <sandeen@sandeen.net <mailto:sandeen@sandeen.net>> wrote:
> 
>     > @@ -981,11 +1077,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,
> 
> 
>     should we really have "finobtflag" in this structure?
>     This structure should only carry feature selections, not feature
>     specification flags I think.  Why is this the only such flag
>     in the structure?
> 
>     Pretty sure finobtflag should stay a variable for now
>     just like lvflag (which goes with log_version).
> 
>  
> ​It might be right to move it out​, but the flag is removed few
> patches later entirely. Is it worth of the work? I would say nah, let
> it die where it is. :-)

Given that it doesn't seem to be a bug, I guess that might be ok,
but in general introducing incorrect things and fixing them later
in the series is strongly discouraged...

>  
> 
>     ...
> 
>     > @@ -1517,7 +1617,14 @@ main(
>     >                                       c = atoi(value);
>     >                                       if (c < 0 || c > 1)
>     >                                               illegal(value, "m crc");
>     > -                                     crcs_enabled = c;
>     > +                                     if (c && nftype) {
>     > +                                             fprintf(stderr,
>     > +_("cannot specify both crc and ftype\n"));
>     > +                                             usage();
> 
>     hm, why is conflict checking added?  It's not what the commit says
>     the patch does.
> 
>     It also regresses the bug I fixed in
> 
>     commit b990de8ba4e2df2bc76a140799d3ddb4a0eac4ce
>     Author: Eric Sandeen <sandeen@sandeen.net <mailto:sandeen@sandeen.net>>
>     Date:   Tue Aug 18 17:53:17 2015 +1000
> 
>         mkfs.xfs: fix ftype-vs-crc option combination testing
> 
>     with this patch, it is broken again:
> 
>     # mkfs/mkfs.xfs -m crc=0 -n ftype=1 -dfile,name=fsfile,size=16g
>     <success>
>      # mkfs/mkfs.xfs -n ftype=1 -m crc=0 -dfile,name=fsfile,size=16g
>     cannot specify both crc and ftype
>     Usage: mkfs.xfs
>     ...
> 
> ​Because the patch is much older than your fix, and at the time it
> was created, it is possible that there wasn't any such check... I
> would call it the risk of necromancy. :-)​

Most likely a forward-port or merge error I think.

> Anyway, I already fixed this issue in this cycle, and added the the
> ftype, crc order into a test checking for options sanity. Just I
> didn't submitted the change yet.

Ok, so it is fixed in your new version of this patch?

> 
>     ...
> 
>     > @@ -1879,23 +1988,25 @@ _("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.
>     > +              * 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 a warning before turning
>     > +              * them off.
>     >                */
>     > -             if (finobt && finobtflag) {
>     > -                     fprintf(stderr,
>     > -_("warning: finobt not supported without CRC support, disabled.\n"));
>     > +             if (sb_feat.finobt){
>     > +                     if (sb_feat.finobtflag) {
>     > +                             fprintf(stderr,
>     > +     _("warning: finobt not supported without CRC support, disabled.\n"));
>     > +                     }
>     > +                     sb_feat.finobt = 0;
> 
>     like I mentioned, just this, I think (assuming we like the silent turning
>     off, but that would be a different patch):
> 
>  
> ​Merging the conditions is indeed cleaner.
> 
> And I will change it to failure, if the conflicting options are given
> explicitly. Just a small patch adding "usage();" and removing
> "warning"...​

Ok, so for this patch, nothing but the mechanical change matching all the others,
right?  If there is any change in behavior to be done, that should be a different patch.

-Eric

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

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

* Re: [PATCH 03/19] mkfs: Sanitise the superblock feature macros
  2016-04-07 13:18       ` Eric Sandeen
@ 2016-04-07 13:27         ` Jan Tulak
  0 siblings, 0 replies; 84+ messages in thread
From: Jan Tulak @ 2016-04-07 13:27 UTC (permalink / raw)
  To: Eric Sandeen; +Cc: xfs-oss


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

On Thu, Apr 7, 2016 at 3:18 PM, Eric Sandeen <sandeen@sandeen.net> wrote:

> On 4/7/16 8:09 AM, Jan Tulak wrote:
> >
> ...
>
> > On Thu, Apr 7, 2016 at 3:43 AM, Eric Sandeen <sandeen@sandeen.net
> <mailto:sandeen@sandeen.net>> wrote:
> >
> >     > @@ -981,11 +1077,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,
> >
> >
> >     should we really have "finobtflag" in this structure?
> >     This structure should only carry feature selections, not feature
> >     specification flags I think.  Why is this the only such flag
> >     in the structure?
> >
> >     Pretty sure finobtflag should stay a variable for now
> >     just like lvflag (which goes with log_version).
> >
> >
> > ​It might be right to move it out​, but the flag is removed few
> > patches later entirely. Is it worth of the work? I would say nah, let
> > it die where it is. :-)
>
> Given that it doesn't seem to be a bug, I guess that might be ok,
> but in general introducing incorrect things and fixing them later
> in the series is strongly discouraged...
>
> >
> >
> >     ...
> >
> >     > @@ -1517,7 +1617,14 @@ main(
> >     >                                       c = atoi(value);
> >     >                                       if (c < 0 || c > 1)
> >     >                                               illegal(value, "m
> crc");
> >     > -                                     crcs_enabled = c;
> >     > +                                     if (c && nftype) {
> >     > +                                             fprintf(stderr,
> >     > +_("cannot specify both crc and ftype\n"));
> >     > +                                             usage();
> >
> >     hm, why is conflict checking added?  It's not what the commit says
> >     the patch does.
> >
> >     It also regresses the bug I fixed in
> >
> >     commit b990de8ba4e2df2bc76a140799d3ddb4a0eac4ce
> >     Author: Eric Sandeen <sandeen@sandeen.net <mailto:
> sandeen@sandeen.net>>
> >     Date:   Tue Aug 18 17:53:17 2015 +1000
> >
> >         mkfs.xfs: fix ftype-vs-crc option combination testing
> >
> >     with this patch, it is broken again:
> >
> >     # mkfs/mkfs.xfs -m crc=0 -n ftype=1 -dfile,name=fsfile,size=16g
> >     <success>
> >      # mkfs/mkfs.xfs -n ftype=1 -m crc=0 -dfile,name=fsfile,size=16g
> >     cannot specify both crc and ftype
> >     Usage: mkfs.xfs
> >     ...
> >
> > ​Because the patch is much older than your fix, and at the time it
> > was created, it is possible that there wasn't any such check... I
> > would call it the risk of necromancy. :-)​
>
> Most likely a forward-port or merge error I think.
>
> > Anyway, I already fixed this issue in this cycle, and added the the
> > ftype, crc order into a test checking for options sanity. Just I
> > didn't submitted the change yet.
>
> Ok, so it is fixed in your new version of this patch?
>

​Yes.
​


>
> >
> >     ...
> >
> >     > @@ -1879,23 +1988,25 @@ _("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.
> >     > +              * 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 a warning
> before turning
> >     > +              * them off.
> >     >                */
> >     > -             if (finobt && finobtflag) {
> >     > -                     fprintf(stderr,
> >     > -_("warning: finobt not supported without CRC support,
> disabled.\n"));
> >     > +             if (sb_feat.finobt){
> >     > +                     if (sb_feat.finobtflag) {
> >     > +                             fprintf(stderr,
> >     > +     _("warning: finobt not supported without CRC support,
> disabled.\n"));
> >     > +                     }
> >     > +                     sb_feat.finobt = 0;
> >
> >     like I mentioned, just this, I think (assuming we like the silent
> turning
> >     off, but that would be a different patch):
> >
> >
> > ​Merging the conditions is indeed cleaner.
> >
> > And I will change it to failure, if the conflicting options are given
> > explicitly. Just a small patch adding "usage();" and removing
> > "warning"...​
>
> Ok, so for this patch, nothing but the mechanical change matching all the
> others,
> right?  If there is any change in behavior to be done, that should be a
> different patch.
>

​Exactly.
​


>
> -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: 9247 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] 84+ messages in thread

* Re: [PATCH 08/19] mkfs: getbool is redundant
  2016-03-24 11:15 ` [PATCH 08/19] mkfs: getbool is redundant jtulak
@ 2016-04-07 17:25   ` Eric Sandeen
  2016-04-08 10:30     ` Jan Tulak
  0 siblings, 1 reply; 84+ messages in thread
From: Eric Sandeen @ 2016-04-07 17:25 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 description of a new member of opt_params
> o Fix in the subopts tables
> o All boolean subopts should use getnum_checked
> o Edit man8 page where it missed the information about optional value of a flag
> 
> 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>
> ---
>  man/man8/mkfs.xfs.8 |  11 ++-
>  mkfs/xfs_mkfs.c     | 223 ++++++++++++++++++++++++++++++++++++----------------
>  2 files changed, 164 insertions(+), 70 deletions(-)
> 
> diff --git a/man/man8/mkfs.xfs.8 b/man/man8/mkfs.xfs.8
> index 8b068ef..5a2a20a 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

"Many options allow for an optional argument of 0 or 1, ..."

> +disable or enable the functionality, in a forward-compatible syntax.

What does "forward-compatible syntax" mean?  I'm not sure that clarifies
anything for the reader.

Otherwise this looks ok to me; Dave explained that it is intentional to
make every single option accept a value, whether it is now
boolean or a numeric value, so there is no such thing as a bare "--flag"
anymore; such flags are always "--flag [0|1]" now, right?

> @@ -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

The realtime section of the manpage needs this same fixup now too, I guess.

Thanks,
-Eric

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

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

* Re: [PATCH 09/19] mkfs: use getnum_checked for all ranged parameters
  2016-03-24 11:15 ` [PATCH 09/19] mkfs: use getnum_checked for all ranged parameters jtulak
@ 2016-04-07 19:02   ` Eric Sandeen
  2016-04-08 10:47     ` Jan Tulak
  0 siblings, 1 reply; 84+ messages in thread
From: Eric Sandeen @ 2016-04-07 19:02 UTC (permalink / raw)
  To: xfs



On 3/24/16 6:15 AM, jtulak@redhat.com wrote:
> 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>

Looks ok.

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

> ---
>  include/xfs_multidisk.h |   5 +-
>  mkfs/xfs_mkfs.c         | 148 ++++++++++++++++++++++++------------------------
>  2 files changed, 76 insertions(+), 77 deletions(-)
> 
> diff --git a/include/xfs_multidisk.h b/include/xfs_multidisk.h
> index af35100..8e81d90 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 0e2cfac..021d682 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,
> @@ -1560,13 +1592,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:
> @@ -1601,28 +1631,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')
> @@ -1638,16 +1662,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,
> @@ -1696,21 +1717,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:
> @@ -1745,18 +1767,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);
> @@ -1765,16 +1782,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);
> @@ -1783,19 +1797,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 =
> @@ -1817,21 +1828,16 @@ main(
>  			while (*p != '\0') {
>  				char	**subopts = (char **)lopts.subopts;
>  				char	*value;
> -				long long tmp_num;
>  
>  				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);
> -					tmp_num = getnum(value, 0, 0, false);
> -					if (tmp_num < 0)
> -						illegal(value, "l agno");
> -					logagno = (xfs_agnumber_t)tmp_num;
> +					logagno = getnum_checked(value, &lopts,
> +								 L_AGNUM);
>  					laflag = 1;
>  					break;
>  				case L_FILE:
> @@ -1868,13 +1874,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:
> @@ -1893,14 +1896,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:
> @@ -2035,11 +2034,10 @@ _("cannot specify both -m crc=1 and -n ftype\n"));
>  						/* 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;
> 

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

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

* Re: [PATCH 10/19] mkfs: add respecification detection to generic parsing
  2016-03-24 11:15 ` [PATCH 10/19] mkfs: add respecification detection to generic parsing jtulak
@ 2016-04-07 19:06   ` Eric Sandeen
  0 siblings, 0 replies; 84+ messages in thread
From: Eric Sandeen @ 2016-04-07 19:06 UTC (permalink / raw)
  To: xfs

On 3/24/16 6:15 AM, jtulak@redhat.com wrote:
> From: Dave Chinner <dchinner@redhat.com>
> 
> CHANGE:
> o Add description of new members in opt_params struct.
> o Drop "const" from struct opt_params - a previous patch was changed to
>   not create it as const.
> 
> 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>

> ---
>  mkfs/xfs_mkfs.c | 64 ++++++++++++++++-----------------------------------------
>  1 file changed, 18 insertions(+), 46 deletions(-)
> 
> diff --git a/mkfs/xfs_mkfs.c b/mkfs/xfs_mkfs.c
> index 021d682..a8dd304 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;
> @@ -1227,7 +1233,6 @@ struct sb_feat_args {
>  	int	dir_version;
>  	int	spinodes;
>  	int	finobt;
> -	bool	finobtflag;
>  	bool	inode_align;
>  	bool	nci;
>  	bool	lazy_sb_counters;
> @@ -1363,7 +1368,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) {
> @@ -1373,6 +1378,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);
> @@ -1490,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,
> @@ -1552,8 +1561,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);
> @@ -1592,9 +1599,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;
> @@ -1631,8 +1635,6 @@ main(
>  					dsize = value;
>  					break;
>  				case D_SUNIT:
> -					if (dsunit)
> -						respec('d', subopts, D_SUNIT);
>  					if (nodsflag)
>  						conflict('d', subopts, D_NOALIGN,
>  							 D_SUNIT);
> @@ -1640,8 +1642,6 @@ main(
>  								 D_SUNIT);
>  					break;
>  				case D_SWIDTH:
> -					if (dswidth)
> -						respec('d', subopts, D_SWIDTH);
>  					if (nodsflag)
>  						conflict('d', subopts, D_NOALIGN,
>  							 D_SWIDTH);
> @@ -1662,8 +1662,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);
> @@ -1689,8 +1687,6 @@ main(
>  					}
>  					break;
>  				case D_SECTLOG:
> -					if (slflag)
> -						respec('d', subopts, D_SECTLOG);
>  					if (ssflag)
>  						conflict('d', subopts, D_SECTSIZE,
>  							 D_SECTLOG);
> @@ -1753,8 +1749,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);
> @@ -1767,18 +1761,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);
> @@ -1795,8 +1785,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))
> @@ -1832,8 +1820,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,
> @@ -1855,8 +1841,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);
> @@ -1874,8 +1858,6 @@ main(
>  					lsuflag = 1;
>  					break;
>  				case L_SUNIT:
> -					if (lsunit)
> -						respec('l', subopts, L_SUNIT);
>  					lsunit = getnum_checked(value, &lopts,
>  								 L_SUNIT);
>  					lsunitflag = 1;
> @@ -1896,10 +1878,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:
> @@ -1911,8 +1892,6 @@ main(
>  					lsflag = 1;
>  					break;
>  				case L_SECTLOG:
> -					if (lslflag)
> -						respec('l', subopts, L_SECTLOG);
>  					if (lssflag)
>  						conflict('l', subopts, L_SECTSIZE,
>  							 L_SECTLOG);
> @@ -1974,7 +1953,6 @@ _("cannot specify both -m crc=1 and -n ftype\n"));
>  						sb_feat.dirftype = true;
>  					break;
>  				case M_FINOBT:
> -					sb_feat.finobtflag = true;
>  					sb_feat.finobt = getnum_checked(
>  						value, &mopts, M_FINOBT);
>  					break;
> @@ -1998,8 +1976,6 @@ _("cannot specify both -m crc=1 and -n ftype\n"));
>  				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);
> @@ -2042,8 +2018,6 @@ _("cannot specify both -m crc=1 and -n ftype\n"));
>  					nvflag = 1;
>  					break;
>  				case N_FTYPE:
> -					if (nftype)
> -						respec('n', subopts, N_FTYPE);
>  					if (sb_feat.crcs_enabled) {
>  						fprintf(stderr,
>  _("cannot specify both -m crc=1 and -n ftype\n"));
> @@ -2127,8 +2101,6 @@ _("cannot specify both -m crc=1 and -n ftype\n"));
>  						  &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);
> @@ -2340,7 +2312,7 @@ _("32 bit Project IDs always enabled on CRC enabled filesytems\n"));
>  		 * them off.
>  		 */
>  		if (sb_feat.finobt){
> -			if (sb_feat.finobtflag) {
> +			if (mopts.subopt_params[M_FINOBT].seen) {
>  				fprintf(stderr,
>  	_("warning: finobt not supported without CRC support, disabled.\n"));
>  			}
> 

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

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

* Re: [PATCH 11/19] mkfs: table based parsing for converted parameters
  2016-03-24 11:15 ` [PATCH 11/19] mkfs: table based parsing for converted parameters jtulak
@ 2016-04-07 19:08   ` Eric Sandeen
  0 siblings, 0 replies; 84+ messages in thread
From: Eric Sandeen @ 2016-04-07 19:08 UTC (permalink / raw)
  To: xfs



On 3/24/16 6:15 AM, jtulak@redhat.com wrote:
> From: Dave Chinner <dchinner@redhat.com>
> 
> CHANGE:
> o Change getnum_checked type to long long to prevent int overflow
> o Add description of new members in opt_params struct.
> o L_SU maxval was a wrong number, fix it
> 
> 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>

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

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

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

* Re: [PATCH 12/19] mkfs: merge getnum
  2016-03-24 11:15 ` [PATCH 12/19] mkfs: merge getnum jtulak
@ 2016-04-07 19:14   ` Eric Sandeen
  0 siblings, 0 replies; 84+ messages in thread
From: Eric Sandeen @ 2016-04-07 19:14 UTC (permalink / raw)
  To: xfs

On 3/24/16 6:15 AM, jtulak@redhat.com wrote:
> From: Dave Chinner <dchinner@redhat.com>
> 
> CHANGELOG
> o rename a variable to don't collide with existing local variable (and
>   to have a better meaning: sp -> str_end for detecting trailing garbage)
> 
> 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>

This doesn't address hch's & brian's comments about 2 getnums in mkfs
now, but they are both static; at this point let's just get this patchset
moving & we can fix that later.

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 8e81d90..850a322 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 5930af8..3d3a8dc 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 acf420f..1f06110 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.
> @@ -1380,27 +1377,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,
> @@ -1414,7 +1390,7 @@ illegal_option(
>  }
>  
>  static long long
> -getnum_checked(
> +getnum(
>  	const char		*str,
>  	struct opt_params	*opts,
>  	int			index)
> @@ -1434,6 +1410,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);
> @@ -1448,7 +1425,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))
> @@ -1615,8 +1610,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;
> @@ -1624,8 +1618,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;
> @@ -1643,18 +1637,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;
> @@ -1676,33 +1669,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,
> @@ -1722,8 +1712,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;
> @@ -1731,28 +1721,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;
> @@ -1770,8 +1759,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)
> @@ -1780,14 +1769,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:
> @@ -1797,8 +1785,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:
> @@ -1808,23 +1796,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:
> @@ -1843,13 +1830,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);
> @@ -1863,18 +1849,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:
> @@ -1894,8 +1878,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:
> @@ -1910,8 +1893,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;
> @@ -1919,15 +1902,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:
> @@ -1950,8 +1933,7 @@ 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 && nftype) {
>  						fprintf(stderr,
>  _("cannot specify both -m crc=1 and -n ftype\n"));
> @@ -1961,7 +1943,7 @@ _("cannot specify both -m crc=1 and -n ftype\n"));
>  						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:
> @@ -1987,8 +1969,8 @@ _("cannot specify both -m crc=1 and -n ftype\n"));
>  					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;
> @@ -1996,8 +1978,8 @@ _("cannot specify both -m crc=1 and -n ftype\n"));
>  					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;
> @@ -2012,9 +1994,8 @@ _("cannot specify both -m crc=1 and -n ftype\n"));
>  						sb_feat.nci = true;
>  					} else {
>  						sb_feat.dir_version =
> -							getnum_checked(value,
> -								&nopts,
> -								N_VERSION);
> +							getnum(value, &nopts,
> +							       N_VERSION);
>  					}
>  					nvflag = 1;
>  					break;
> @@ -2024,8 +2005,8 @@ _("cannot specify both -m crc=1 and -n ftype\n"));
>  _("cannot specify both -m crc=1 and -n ftype\n"));
>  						usage();
>  					}
> -					sb_feat.dirftype = getnum_checked(value,
> -								&nopts, N_FTYPE);
> +					sb_feat.dirftype = getnum(value, &nopts,
> +								  N_FTYPE);
>  					nftype = 1;
>  					break;
>  				default:
> @@ -2063,8 +2044,8 @@ _("cannot specify both -m crc=1 and -n ftype\n"));
>  					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;
> @@ -2084,8 +2065,8 @@ _("cannot specify both -m crc=1 and -n ftype\n"));
>  					rtsize = value;
>  					break;
>  				case R_NOALIGN:
> -					norsflag = getnum_checked(value,
> -								&ropts, R_NOALIGN);
> +					norsflag = getnum(value, &ropts,
> +								R_NOALIGN);
>  					break;
>  				default:
>  					unknown('r', value);
> @@ -2105,8 +2086,8 @@ _("cannot specify both -m crc=1 and -n ftype\n"));
>  					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;
> @@ -2117,8 +2098,8 @@ _("cannot specify both -m crc=1 and -n ftype\n"));
>  					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);
> @@ -2349,7 +2330,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"),
> @@ -2386,7 +2367,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"),
> @@ -2408,7 +2389,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"),
> @@ -2428,7 +2409,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"),
> @@ -3531,8 +3512,8 @@ unknown(
>  
>  long long
>  cvtnum(
> -	unsigned int	blocksize,
> -	unsigned int	sectorsize,
> +	unsigned int	blksize,
> +	unsigned int	sectsize,
>  	const char	*s)
>  {
>  	long long	i;
> @@ -3545,9 +3526,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;
> 

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

^ permalink raw reply	[flat|nested] 84+ 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; 84+ 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] 84+ messages in thread

* Re: [PATCH 14/19] mkfs: add string options to generic parsing
  2016-03-24 11:15 ` [PATCH 14/19] mkfs: add string options to generic parsing jtulak
@ 2016-04-07 22:49   ` Eric Sandeen
  0 siblings, 0 replies; 84+ messages in thread
From: Eric Sandeen @ 2016-04-07 22:49 UTC (permalink / raw)
  To: xfs



On 3/24/16 6:15 AM, jtulak@redhat.com wrote:
> From: Dave Chinner <dchinner@redhat.com>
> 
> CHANGELOG:
> o Remove unused argument of check_opt.
> o Add a comment to explain a new member of opt_params struct.
> o A stray chunk moved from the following patch to this one.
> 
> 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 d119580..9261ed5 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];
> @@ -1470,14 +1475,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,
> @@ -1486,22 +1494,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)
> @@ -1543,6 +1576,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,
> @@ -1738,18 +1791,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);
> @@ -1890,18 +1935,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 =
> @@ -1909,12 +1946,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,
> @@ -2000,10 +2032,7 @@ _("cannot specify both -m crc=1 and -n ftype\n"));
>  					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;
> @@ -2052,11 +2081,8 @@ _("cannot specify both -m crc=1 and -n ftype\n"));
>  				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,
> @@ -2066,18 +2092,11 @@ _("cannot specify both -m crc=1 and -n ftype\n"));
>  					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,
> @@ -2137,13 +2156,7 @@ _("cannot specify both -m crc=1 and -n ftype\n"));
>  		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;
>  
> 

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

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

* Re: [PATCH 17/19] xfsprogs: disable truncating of files
  2016-03-24 11:15 ` [PATCH 17/19] xfsprogs: disable truncating of files jtulak
  2016-04-06 21:42   ` Eric Sandeen
@ 2016-04-08  0:09   ` Dave Chinner
  2016-04-08 10:06     ` Jan Tulak
  1 sibling, 1 reply; 84+ messages in thread
From: Dave Chinner @ 2016-04-08  0:09 UTC (permalink / raw)
  To: jtulak; +Cc: xfs

On Thu, Mar 24, 2016 at 12:15:34PM +0100, jtulak@redhat.com wrote:
> From: Jan Tulak <jtulak@redhat.com>
> 
> Unify mkfs.xfs behaviour a bit and never truncate files. If the user
> is trying to mkfs an existing file, we don't want to destroy anything
> he did with the file before (sparse file, allocations...)

Why not? We do that with discard-by-default to block devices,
O_TRUNC is exactly the same situation with a file - we completely
re-initialise the file from a known state if mkfs has been asked to
create the file.


> @@ -1059,9 +1063,9 @@ check_device_type(
>  	}
>  
>  	/*
> -	 * 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.
> +	 * We only want to create a file only if we were specifically told
> +	 * we want a file. Set the create flag only in this case to trigger
> +	 * that behaviour.
>  	 */
>  	if (S_ISREG(statbuf.st_mode)) {
>  		if (!*isfile)

i.e. this situation.

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] 84+ messages in thread

* Re: [PATCH 15/19] mkfs: don't treat files as though they are block devices
  2016-03-24 11:15 ` [PATCH 15/19] mkfs: don't treat files as though they are block devices jtulak
@ 2016-04-08  0:25   ` Eric Sandeen
  2016-04-08  0:32     ` Eric Sandeen
  2016-04-08 14:58     ` Jan Tulak
  0 siblings, 2 replies; 84+ messages in thread
From: Eric Sandeen @ 2016-04-08  0:25 UTC (permalink / raw)
  To: xfs



On 3/24/16 6:15 AM, jtulak@redhat.com wrote:
> From: Dave Chinner <dchinner@redhat.com>
> 
> CHANGELOG
> o Fix where xi.dname was incorrectly used instead of dfile
> o Variable alignment (tabs)
> o Added error handling for stat/statfs in init.c
> o Remove a duplicate pread in zero_old_xfs_structures and for the
> remaining call, save the return value in a more meaningful variable.
> o A chunk moved to previous patch.
> 
> 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.  Also, as direct IO
> is disabled for files, use statfs() for getting host FS blocksize,
> not platform_findsizes().
> 
> These changes, however, can cause some tests to fail when the test
> partition on which the file is created has blocksize bigger than 512.
> Before, the underlying fs was ignored. Now, an attempt to create
> a fs in a file with blocksize 512 on a 4096 underlying partition will
> fail.
> 
> 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.

This one causes at least one interesting issue:

#mkfs/mkfs.xfs
Error accessing specified device (null): Bad address
Usage: mkfs.xfs
...

because:

        check_device_type(dfile, &xi.disfile, !dsize, !dfile,
                          Nflag ? NULL : &xi.dcreat, force_overwrite, "d");

so "dfile" can be NULL, but that function immediately tries to stat it.

> Signed-off-by: Dave Chinner <dchinner@redhat.com>
> Signed-off-by: Jan Tulak <jtulak@redhat.com>
> ---
>  libxfs/init.c   |  12 ++++
>  libxfs/linux.c  |  12 +++-
>  mkfs/xfs_mkfs.c | 181 ++++++++++++++++++++++++++++++++++++++------------------
>  3 files changed, 147 insertions(+), 58 deletions(-)
> 
> diff --git a/libxfs/init.c b/libxfs/init.c
> index 8d747e8..268136f 100644
> --- a/libxfs/init.c
> +++ b/libxfs/init.c
> @@ -246,6 +246,9 @@ libxfs_init(libxfs_init_t *a)
>  	char		rtpath[25];
>  	int		rval = 0;
>  	int		flags;
> +	struct		stat st;
> +	struct		statfs stfs;
> +	int		statres;
>  
>  	dpath[0] = logpath[0] = rtpath[0] = '\0';
>  	dname = a->dname;
> @@ -278,6 +281,15 @@ 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);
> +			statres = stat(dname, &st);
> +			statres += statfs(dname, &stfs);
> +			if(statres){
			  ^space   ^space
> +				fprintf(stderr, _("%s: stat failed.\n"),
> +					progname);
> +				goto done;
> +			}
> +			a->dsize = st.st_size/BBSIZE;
> +			a->dbsize = stfs.f_bsize;

ok so for a file you choose ->dsize to be file size in 512-sector units,
and ->dbsize to be the fs block size.

This is all under if (a->disfile); if we didn't actually specify "-dfile"
but it *is* a file, then we get to platform_findsizes() - which handles
files.  And handles them differently.   Hm but you removed that (see below)
and added more stat() calls...?

What is the reason for adding these stats at this point?

(and if there's a reason, why only for ->disfile but not ->lisfile?)

>  		} else {
>  			if (!check_open(dname, flags, &rawfile, &blockfile))
>  				goto done;
> diff --git a/libxfs/linux.c b/libxfs/linux.c
> index f6ea1b2..adb8ff1 100644
> --- a/libxfs/linux.c
> +++ b/libxfs/linux.c
> @@ -18,6 +18,7 @@
>  
>  #define ustat __kernel_ustat
>  #include <mntent.h>
> +#include <sys/vfs.h>
>  #include <sys/stat.h>
>  #undef ustat
>  #include <sys/ustat.h>
> @@ -125,7 +126,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 9261ed5..7bd9fd5 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)
> @@ -976,35 +979,35 @@ static void get_topology(
>  	struct fs_topology	*ft,
>  	int			force_overwrite)
>  {
> -	struct stat statbuf;
>  	char *dfile = xi->volname ? xi->volname : xi->dname;
> +	struct stat statbuf;
> +	struct statfs statfsbuf;
>  
>  	/*
> -	 * If our target is a regular file, use platform_findsizes
> -	 * to try to obtain the underlying filesystem's requirements
> -	 * for direct IO; we'll set our sector size to that if possible.
> +	 * If our target is a regular file, use statfs
> +	 * to try to obtain the underlying filesystem's blocksize.
>  	 */
>  	if (xi->disfile ||
> -	    (!stat(dfile, &statbuf) && S_ISREG(statbuf.st_mode))) {
> +		(!stat(dfile, &statbuf) && S_ISREG(statbuf.st_mode))) {

dave pointed out that this indentation "fix" is incorrect, the line is fine as
it is; it's part of the same conditional; it shouldn't be tabbed into the code
block under the conditional.

>  		int fd;
>  		int flags = O_RDONLY;
> -		long long dummy;
>  
>  		/* with xi->disfile we may not have the file yet! */
>  		if (xi->disfile)
>  			flags |= O_CREAT;
>  
>  		fd = open(dfile, flags, 0666);
> +
>  		if (fd >= 0) {
> -			platform_findsizes(dfile, fd, &dummy, &ft->lsectorsize);
> +			fstatfs(fd, &statfsbuf);

no error checking on fstatfs, but...

> +			ft->lsectorsize = statfsbuf.f_bsize;

Ok, platform_findsizes already explicitly handled regular files, and tries to
find out via an xfs ioctl what the minimum DIO size is, and uses that for 
the sector size for the filesystem in the iamge.

Now you stat & get the blocksize, and use that instead, but it's likely
to be different:

i.e. before:

# mkfs/mkfs.xfs -f fsfile
meta-data=fsfile                 isize=512    agcount=4, agsize=65536 blks
         =                       sectsz=512   attr=2, projid32bit=1

after:

# mkfs/mkfs.xfs -f fsfile
meta-data=fsfile                 isize=512    agcount=4, agsize=65536 blks
         =                       sectsz=4096  attr=2, projid32bit=1

and also, now:

# mkfs/mkfs.xfs -f -dfile,name=fsfile,size=1g -b size=2048
block size 2048 cannot be smaller than logical sector size 4096

What prompted you to make this change, was there some other problem you
needed to fix?

>  			close(fd);
> -			ft->psectorsize = ft->lsectorsize;

hm, now psectorsize isn't set at all?

>  		} else
>  			ft->psectorsize = ft->lsectorsize = BBSIZE;
>  	} else {
>  		blkid_get_topology(dfile, &ft->dsunit, &ft->dswidth,
> -				   &ft->lsectorsize, &ft->psectorsize,
> -				   force_overwrite);
> +					&ft->lsectorsize, &ft->psectorsize,
> +					force_overwrite);

please don't change these lines, they line up w/ the function opening paren as
they should.

>  	}
>  
>  	if (xi->rtname && !xi->risfile) {
> @@ -1016,6 +1019,75 @@ 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 (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,
> @@ -1279,7 +1351,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...
> @@ -1299,15 +1370,23 @@ zero_old_xfs_structures(
>  	}
>  	memset(buf, 0, new_sb->sb_sectsize);
>  
> -	tmp = pread(xi->dfd, buf, new_sb->sb_sectsize, 0);
> -	if (tmp < 0) {
> +	off = pread(xi->dfd, buf, new_sb->sb_sectsize, 0);
> +	if (off < 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.
> +	 */

except you already did "if (off < 0) fail" above this.

Ok, at this point I think it might be best to revert to Dave's original version.

If there were specific problems you were trying to address, can you point them out?

Thanks,
-Eric

> +	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);
> @@ -1787,8 +1866,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);
> @@ -1914,11 +1991,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,
> @@ -2087,8 +2159,6 @@ _("cannot specify both -m crc=1 and -n ftype\n"));
>  				case R_FILE:
>  					xi.risfile = getnum(value, &ropts,
>  							    R_FILE);
> -					if (xi.risfile)
> -						xi.rcreat = 1;
>  					break;
>  				case R_NAME:
>  				case R_DEV:
> @@ -2193,6 +2263,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);
>  
> @@ -2345,11 +2435,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;
>  
> @@ -2382,11 +2467,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;
>  
> @@ -2404,11 +2484,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;
>  
> @@ -2530,22 +2605,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);
>  	}
>  
> 

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

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

* Re: [PATCH 15/19] mkfs: don't treat files as though they are block devices
  2016-04-08  0:25   ` Eric Sandeen
@ 2016-04-08  0:32     ` Eric Sandeen
  2016-04-08 14:58     ` Jan Tulak
  1 sibling, 0 replies; 84+ messages in thread
From: Eric Sandeen @ 2016-04-08  0:32 UTC (permalink / raw)
  To: xfs



On 4/7/16 7:25 PM, Eric Sandeen wrote:
>> @@ -1299,15 +1370,23 @@ zero_old_xfs_structures(
>> >  	}
>> >  	memset(buf, 0, new_sb->sb_sectsize);
>> >  
>> > -	tmp = pread(xi->dfd, buf, new_sb->sb_sectsize, 0);
>> > -	if (tmp < 0) {
>> > +	off = pread(xi->dfd, buf, new_sb->sb_sectsize, 0);
>> > +	if (off < 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.
>> > +	 */
> except you already did "if (off < 0) fail" above this.

(oh, right, < 0 is different than == 0, sorry; so that part is ok)

Possibly better as:

if (off < 0 || (tmp != new_sb->sb_sectsize && !xi->disfile))
	fprintf("error reading existing superblock ...")

I still think this patch might need a reset though :)

Thanks,
-Eric

> Ok, at this point I think it might be best to revert to Dave's original version.
> 
> If there were specific problems you were trying to address, can you point them out?
> 
> Thanks,
> -Eric
> 

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

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

* Re: [PATCH 18/19] mkfs: unit conversions are case insensitive
  2016-04-07 10:50     ` Jan Tulak
@ 2016-04-08  0:41       ` Eric Sandeen
  2016-04-08  1:03         ` Dave Chinner
  0 siblings, 1 reply; 84+ messages in thread
From: Eric Sandeen @ 2016-04-08  0:41 UTC (permalink / raw)
  To: xfs



On 4/7/16 5:50 AM, Jan Tulak wrote:
> On Wed, Apr 6, 2016 at 11:10 PM, Eric Sandeen <sandeen@sandeen.net <mailto:sandeen@sandeen.net>>wrote:
> 
>     On 3/24/16 6:15 AM, jtulak@redhat.com <mailto:jtulak@redhat.com> wrote:
>     > From: Jan Tulak <jtulak@redhat.com <mailto:jtulak@redhat.com>>
>     >
>     > Solves the question "Should I use 10g or 10G?"
> 
>     Might be nicer to do it like the cvtnum in libxcmd:
> 
>             c = tolower(*sp);
>             switch (c) {
>             case 'b':
>                     return i * blocksize;
>     ...
> 
> ​Yeah, changed.
> ​
>  
> 
> 
>     (hm, why do we have 3 copies of cvtnum?)
> 
> 
> ​Where? ​
>  ​
> 
> ​$ pwd
> ​/some/path/xfsprogs-dev
> 
> $ grep -r "cvtnum(size_t" . |grep -v "^Binary"
> ​./include/input.h:extern long long cvtnum(size_t blocksize, size_t sectorsize, char *s);
> ./io/init.h:extern void init_cvtnum(size_t *blocksize, size_t *sectsize);

  File              	Line
0 estimate/xfs_estimate.c   29 cvtnum(char *s)
1 libxcmd/input.c          147 cvtnum(
2 mkfs/xfs_mkfs.c         3618 cvtnum(

-Eric

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

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

* Re: [PATCH 18/19] mkfs: unit conversions are case insensitive
  2016-04-08  0:41       ` Eric Sandeen
@ 2016-04-08  1:03         ` Dave Chinner
  2016-04-08  9:08           ` Jan Tulak
  0 siblings, 1 reply; 84+ messages in thread
From: Dave Chinner @ 2016-04-08  1:03 UTC (permalink / raw)
  To: Eric Sandeen; +Cc: xfs

On Thu, Apr 07, 2016 at 07:41:58PM -0500, Eric Sandeen wrote:
> On 4/7/16 5:50 AM, Jan Tulak wrote:
> > On Wed, Apr 6, 2016 at 11:10 PM, Eric Sandeen <sandeen@sandeen.net <mailto:sandeen@sandeen.net>>wrote:
> >     (hm, why do we have 3 copies of cvtnum?)
> > 
> > 
> > ​Where? ​
> >  ​
> > 
> > ​$ pwd
> > ​/some/path/xfsprogs-dev
> > 
> > $ grep -r "cvtnum(size_t" . |grep -v "^Binary"
> > ​./include/input.h:extern long long cvtnum(size_t blocksize, size_t sectorsize, char *s);
> > ./io/init.h:extern void init_cvtnum(size_t *blocksize, size_t *sectsize);
> 
>   File              	Line
> 0 estimate/xfs_estimate.c   29 cvtnum(char *s)
> 1 libxcmd/input.c          147 cvtnum(
> 2 mkfs/xfs_mkfs.c         3618 cvtnum(

FWIW, here's why we put the function name at the start of the line,
rather than the way that it is typically done in the kernel code
(i.e. after the return type specification):

$ git grep ^cvtnum
estimate/xfs_estimate.c:cvtnum(char *s)
libxcmd/input.c:cvtnum(
mkfs/xfs_mkfs.c:cvtnum(

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] 84+ messages in thread

* Re: [PATCH 18/19] mkfs: unit conversions are case insensitive
  2016-04-08  1:03         ` Dave Chinner
@ 2016-04-08  9:08           ` Jan Tulak
  2016-04-08 15:51             ` Eric Sandeen
  0 siblings, 1 reply; 84+ messages in thread
From: Jan Tulak @ 2016-04-08  9:08 UTC (permalink / raw)
  To: Dave Chinner; +Cc: Eric Sandeen, xfs-oss


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

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

> On Thu, Apr 07, 2016 at 07:41:58PM -0500, Eric Sandeen wrote:
> > On 4/7/16 5:50 AM, Jan Tulak wrote:
> > > On Wed, Apr 6, 2016 at 11:10 PM, Eric Sandeen <sandeen@sandeen.net
> <mailto:sandeen@sandeen.net>>wrote:
> > >     (hm, why do we have 3 copies of cvtnum?)
> > >
> > >
> > > ​Where? ​
> > >  ​
> > >
> > > ​$ pwd
> > > ​/some/path/xfsprogs-dev
> > >
> > > $ grep -r "cvtnum(size_t" . |grep -v "^Binary"
> > > ​./include/input.h:extern long long cvtnum(size_t blocksize, size_t
> sectorsize, char *s);
> > > ./io/init.h:extern void init_cvtnum(size_t *blocksize, size_t
> *sectsize);
> >
> >   File                Line
> > 0 estimate/xfs_estimate.c   29 cvtnum(char *s)
> > 1 libxcmd/input.c          147 cvtnum(
> > 2 mkfs/xfs_mkfs.c         3618 cvtnum(
>
> FWIW, here's why we put the function name at the start of the line,
> rather than the way that it is typically done in the kernel code
> (i.e. after the return type specification):
>
> $ git grep ^cvtnum
> estimate/xfs_estimate.c:cvtnum(char *s)
> libxcmd/input.c:cvtnum(
> mkfs/xfs_mkfs.c:cvtnum(
>
>
​Ah, I see. A nice trick. :-)

It might be good to merge the three functions, but I think it can wait for
when this patchset is done - or there is always going to be something more
to add...

Thanks,
Jan ​

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

[-- Attachment #1.2: Type: text/html, Size: 3155 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] 84+ messages in thread

* Re: [PATCH 17/19] xfsprogs: disable truncating of files
  2016-04-08  0:09   ` Dave Chinner
@ 2016-04-08 10:06     ` Jan Tulak
  2016-04-08 23:08       ` Dave Chinner
  0 siblings, 1 reply; 84+ messages in thread
From: Jan Tulak @ 2016-04-08 10:06 UTC (permalink / raw)
  To: Dave Chinner; +Cc: xfs-oss


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

On Fri, Apr 8, 2016 at 2:09 AM, Dave Chinner <david@fromorbit.com> wrote:

> On Thu, Mar 24, 2016 at 12:15:34PM +0100, jtulak@redhat.com wrote:
> > From: Jan Tulak <jtulak@redhat.com>
> >
> > Unify mkfs.xfs behaviour a bit and never truncate files. If the user
> > is trying to mkfs an existing file, we don't want to destroy anything
> > he did with the file before (sparse file, allocations...)
>
> Why not? We do that with discard-by-default to block devices,
> O_TRUNC is exactly the same situation with a file - we completely
> re-initialise the file from a known state if mkfs has been asked to
> create the file.
>
> ​But AFAIK, we don't zero-out entire spindle devices, we don't ask if the
drive skips some blocks (i.e. because they are bad),​ and we don't care
about what an underlaying layer (like LVM) did with the block device. From
this point of view, we shouldn't care about the file either.

I can be missing something, though.


> > @@ -1059,9 +1063,9 @@ check_device_type(
> >       }
> >
> >       /*
> > -      * 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.
> > +      * We only want to create a file only if we were specifically told
> > +      * we want a file. Set the create flag only in this case to trigger
> > +      * that behaviour.
> >        */
> >       if (S_ISREG(statbuf.st_mode)) {
> >               if (!*isfile)
>
> i.e. this situation.
>
> Cheers,
>
> Dave.
> --
> Dave Chinner
> david@fromorbit.com
>



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

[-- Attachment #1.2: Type: text/html, Size: 3252 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] 84+ messages in thread

* Re: [PATCH 08/19] mkfs: getbool is redundant
  2016-04-07 17:25   ` Eric Sandeen
@ 2016-04-08 10:30     ` Jan Tulak
  2016-04-08 17:41       ` Eric Sandeen
  0 siblings, 1 reply; 84+ messages in thread
From: Jan Tulak @ 2016-04-08 10:30 UTC (permalink / raw)
  To: Eric Sandeen; +Cc: xfs-oss


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

On Thu, Apr 7, 2016 at 7:25 PM, Eric Sandeen <sandeen@sandeen.net> wrote:

>
>
> "Many options allow for an optional argument of 0 or 1, ..."
>
> > +disable or enable the functionality, in a forward-compatible syntax.
>
> What does "forward-compatible syntax" mean?  I'm not sure that clarifies
> anything for the reader.
>
> ​Yeah, I should reformulate it, I think. The meaning is that it won't
matter what the defaults are now, or will be in the future. E.g., if you
had a script creating a fs without crc before, when it was disabled by
default, and we changed the default, you are now creating with the crc. But
if you give it -m crc=0, then no matter what the default is, you have it
always disabled.

How about changing the line to "Boolean options allows for optional
argument of value 0 or 1, to explicitly disable or enable the
functionality," and dropping the forward-compatible part?



> Otherwise this looks ok to me; Dave explained that it is intentional to
> make every single option accept a value, whether it is now
> boolean or a numeric value, so there is no such thing as a bare "--flag"
> anymore; such flags are always "--flag [0|1]" now, right?
>

​For options inside of -m, -d and such, yes. Top-level flags, that is -f,
-q, -N, -K and -V, are still only flags, but these don't change the FS
attributes. They are something different from the other. Still, I wonder
whether they should accept [0|1] too...

​


>
> > @@ -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
>
> The realtime section of the manpage needs this same fixup now too, I guess.
>
> Done​



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

​Thanks,
Jan​


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

[-- Attachment #1.2: Type: text/html, Size: 4952 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] 84+ messages in thread

* Re: [PATCH 09/19] mkfs: use getnum_checked for all ranged parameters
  2016-04-07 19:02   ` Eric Sandeen
@ 2016-04-08 10:47     ` Jan Tulak
  2016-04-08 15:52       ` Eric Sandeen
  0 siblings, 1 reply; 84+ messages in thread
From: Jan Tulak @ 2016-04-08 10:47 UTC (permalink / raw)
  To: Eric Sandeen; +Cc: xfs-oss


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

On Thu, Apr 7, 2016 at 9:02 PM, Eric Sandeen <sandeen@sandeen.net> wrote:

>
>
> On 3/24/16 6:15 AM, jtulak@redhat.com wrote:
> > 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>
>
> Looks ok.
>
> Signed-off-by: Eric Sandeen <sandeen@redhat.com>
>

​Or Reviewed-by? :-)

​Thanks,
Jan​

​


>
> > ---
> >  include/xfs_multidisk.h |   5 +-
> >  mkfs/xfs_mkfs.c         | 148
> ++++++++++++++++++++++++------------------------
> >  2 files changed, 76 insertions(+), 77 deletions(-)
> >
> > diff --git a/include/xfs_multidisk.h b/include/xfs_multidisk.h
> > index af35100..8e81d90 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 0e2cfac..021d682 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,
> > @@ -1560,13 +1592,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:
> > @@ -1601,28 +1631,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')
> > @@ -1638,16 +1662,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,
> > @@ -1696,21 +1717,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:
> > @@ -1745,18 +1767,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);
> > @@ -1765,16 +1782,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);
> > @@ -1783,19 +1797,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 =
> > @@ -1817,21 +1828,16 @@ main(
> >                       while (*p != '\0') {
> >                               char    **subopts = (char **)lopts.subopts;
> >                               char    *value;
> > -                             long long tmp_num;
> >
> >                               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);
> > -                                     tmp_num = getnum(value, 0, 0,
> false);
> > -                                     if (tmp_num < 0)
> > -                                             illegal(value, "l agno");
> > -                                     logagno = (xfs_agnumber_t)tmp_num;
> > +                                     logagno = getnum_checked(value,
> &lopts,
> > +                                                              L_AGNUM);
> >                                       laflag = 1;
> >                                       break;
> >                               case L_FILE:
> > @@ -1868,13 +1874,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:
> > @@ -1893,14 +1896,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:
> > @@ -2035,11 +2034,10 @@ _("cannot specify both -m crc=1 and -n
> ftype\n"));
> >                                               /* 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;
> >
>
> _______________________________________________
> 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: 32374 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] 84+ messages in thread

* Re: [PATCH 15/19] mkfs: don't treat files as though they are block devices
  2016-04-08  0:25   ` Eric Sandeen
  2016-04-08  0:32     ` Eric Sandeen
@ 2016-04-08 14:58     ` Jan Tulak
  2016-04-08 15:50       ` Eric Sandeen
                         ` (2 more replies)
  1 sibling, 3 replies; 84+ messages in thread
From: Jan Tulak @ 2016-04-08 14:58 UTC (permalink / raw)
  To: Eric Sandeen; +Cc: xfs-oss


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

On Fri, Apr 8, 2016 at 2:25 AM, Eric Sandeen <sandeen@sandeen.net> wrote:

> On 3/24/16 6:15 AM, jtulak@redhat.com wrote:
> > From: Dave Chinner <dchinner@redhat.com>
> >
> > CHANGELOG
> > o Fix where xi.dname was incorrectly used instead of dfile
> > o Variable alignment (tabs)
> > o Added error handling for stat/statfs in init.c
> > o Remove a duplicate pread in zero_old_xfs_structures and for the
> > remaining call, save the return value in a more meaningful variable.
> > o A chunk moved to previous patch.
> >
> > 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.  Also, as direct IO
> > is disabled for files, use statfs() for getting host FS blocksize,
> > not platform_findsizes().
> >
> > These changes, however, can cause some tests to fail when the test
> > partition on which the file is created has blocksize bigger than 512.
> > Before, the underlying fs was ignored. Now, an attempt to create
> > a fs in a file with blocksize 512 on a 4096 underlying partition will
> > fail.
> >
> > 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.
>
> This one causes at least one interesting issue:
>
> #mkfs/mkfs.xfs
> Error accessing specified device (null): Bad address
> Usage: mkfs.xfs
> ...
>
> because:
>
>         check_device_type(dfile, &xi.disfile, !dsize, !dfile,
>                           Nflag ? NULL : &xi.dcreat, force_overwrite, "d");
>
> so "dfile" can be NULL, but that function immediately tries to stat it.
>

​A simple if NULL, then usage() should take care of this...


> > Signed-off-by: Dave Chinner <dchinner@redhat.com>
> > Signed-off-by: Jan Tulak <jtulak@redhat.com>
> > ---
> >  libxfs/init.c   |  12 ++++
> >  libxfs/linux.c  |  12 +++-
> >  mkfs/xfs_mkfs.c | 181
> ++++++++++++++++++++++++++++++++++++++------------------
> >  3 files changed, 147 insertions(+), 58 deletions(-)
> >
> > diff --git a/libxfs/init.c b/libxfs/init.c
> > index 8d747e8..268136f 100644
> > --- a/libxfs/init.c
> > +++ b/libxfs/init.c
> > @@ -246,6 +246,9 @@ libxfs_init(libxfs_init_t *a)
> >       char            rtpath[25];
> >       int             rval = 0;
> >       int             flags;
> > +     struct          stat st;
> > +     struct          statfs stfs;
> > +     int             statres;
> >
> >       dpath[0] = logpath[0] = rtpath[0] = '\0';
> >       dname = a->dname;
> > @@ -278,6 +281,15 @@ 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);
> > +                     statres = stat(dname, &st);
> > +                     statres += statfs(dname, &stfs);
> > +                     if(statres){
>                           ^space   ^space
> > +                             fprintf(stderr, _("%s: stat failed.\n"),
> > +                                     progname);
> > +                             goto done;
> > +                     }
> > +                     a->dsize = st.st_size/BBSIZE;
> > +                     a->dbsize = stfs.f_bsize;
>
> ok so for a file you choose ->dsize to be file size in 512-sector units,
> and ->dbsize to be the fs block size.
>
> This is all under if (a->disfile); if we didn't actually specify "-dfile"
> but it *is* a file, then we get to platform_findsizes() - which handles
> files.  And handles them differently.


​No, a->disfile is set to 1 implicitly if the target is a file
in check_device_type():
1070        if (S_ISREG(statbuf.st_mode)) {
1071               if (!*isfile)
1072                      *isfile = 1;




> Hm but you removed that (see below)
> and added more stat() calls...?
>
> What is the reason for adding these stats at this point?
>
​What is removed? Where exactly? Or it should be "above"?
> +                     statres = stat(dname, &st);
> +                     statres += statfs(dname, &stfs);
This is to get dsize and dbsize values for the file.

(and if there's a reason, why only for ->disfile but not ->lisfile?)
>
​Because I forgot or didn't noticed. :-) Adding to lisfile and rtfile too.
​


>
> >               } else {
> >                       if (!check_open(dname, flags, &rawfile,
> &blockfile))
> >                               goto done;
> > diff --git a/libxfs/linux.c b/libxfs/linux.c
> > index f6ea1b2..adb8ff1 100644
> > --- a/libxfs/linux.c
> > +++ b/libxfs/linux.c
> > @@ -18,6 +18,7 @@
> >
> >  #define ustat __kernel_ustat
> >  #include <mntent.h>
> > +#include <sys/vfs.h>
> >  #include <sys/stat.h>
> >  #undef ustat
> >  #include <sys/ustat.h>
> > @@ -125,7 +126,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 9261ed5..7bd9fd5 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)
> > @@ -976,35 +979,35 @@ static void get_topology(
> >       struct fs_topology      *ft,
> >       int                     force_overwrite)
> >  {
> > -     struct stat statbuf;
> >       char *dfile = xi->volname ? xi->volname : xi->dname;
> > +     struct stat statbuf;
> > +     struct statfs statfsbuf;
> >
> >       /*
> > -      * If our target is a regular file, use platform_findsizes
> > -      * to try to obtain the underlying filesystem's requirements
> > -      * for direct IO; we'll set our sector size to that if possible.
> > +      * If our target is a regular file, use statfs
> > +      * to try to obtain the underlying filesystem's blocksize.
> >        */
> >       if (xi->disfile ||
> > -         (!stat(dfile, &statbuf) && S_ISREG(statbuf.st_mode))) {
> > +             (!stat(dfile, &statbuf) && S_ISREG(statbuf.st_mode))) {
>
> dave pointed out that this indentation "fix" is incorrect, the line is
> fine as
> it is; it's part of the same conditional; it shouldn't be tabbed into the
> code
> block under the conditional.
>

​I'm removing this change.



> >               int fd;
> >               int flags = O_RDONLY;
> > -             long long dummy;
> >
> >               /* with xi->disfile we may not have the file yet! */
> >               if (xi->disfile)
> >                       flags |= O_CREAT;
> >
> >               fd = open(dfile, flags, 0666);
> > +
> >               if (fd >= 0) {
> > -                     platform_findsizes(dfile, fd, &dummy,
> &ft->lsectorsize);
> > +                     fstatfs(fd, &statfsbuf);
>
> no error checking on fstatfs, but...
>
​Added.​


>
> > +                     ft->lsectorsize = statfsbuf.f_bsize;
>
> Ok, platform_findsizes already explicitly handled regular files, and tries
> to
> find out via an xfs ioctl what the minimum DIO size is, and uses that for
> the sector size for the filesystem in the iamge.


> Now you stat & get the blocksize, and use that instead, but it's likely
> to be different:
>
> i.e. before:
>
> # mkfs/mkfs.xfs -f fsfile
> meta-data=fsfile                 isize=512    agcount=4, agsize=65536 blks
>          =                       sectsz=512   attr=2, projid32bit=1
>
> after:
>
> # mkfs/mkfs.xfs -f fsfile
> meta-data=fsfile                 isize=512    agcount=4, agsize=65536 blks
>          =                       sectsz=4096  attr=2, projid32bit=1
>
> and also, now:
>
> # mkfs/mkfs.xfs -f -dfile,name=fsfile,size=1g -b size=2048
> block size 2048 cannot be smaller than logical sector size 4096
>
> What prompted you to make this change, was there some other problem you
> needed to fix?
>

​But DIO is disabled for the files, per the commit message:
[...] and turning off
direct IO. Then ensure that we check the "isfile" options before
doing things that are specific to block devices.  Also, as direct IO
is disabled for files, use statfs() for getting host FS blocksize,
not platform_findsizes().​

So we have to use whatever the underlying fs tells us, not what the
physical device has, right?

​Rather, I wonder if there is any reason to keep the platform_findsizes
part about regular files - it shouldn't get into the branch ever.



>
> >                       close(fd);
> > -                     ft->psectorsize = ft->lsectorsize;
>
> hm, now psectorsize isn't set at all?
>

​This looks like a bug, I think the assignment should stay here.
​


>
> >               } else
> >                       ft->psectorsize = ft->lsectorsize = BBSIZE;
> >       } else {
> >               blkid_get_topology(dfile, &ft->dsunit, &ft->dswidth,
> > -                                &ft->lsectorsize, &ft->psectorsize,
> > -                                force_overwrite);
> > +                                     &ft->lsectorsize, &ft->psectorsize,
> > +                                     force_overwrite);
>
> please don't change these lines, they line up w/ the function opening
> paren as
> they should.
>
> ​Sure. ​



> >       }
> >
> >       if (xi->rtname && !xi->risfile) {
> > @@ -1016,6 +1019,75 @@ 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 (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,
> > @@ -1279,7 +1351,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...
> > @@ -1299,15 +1370,23 @@ zero_old_xfs_structures(
> >       }
> >       memset(buf, 0, new_sb->sb_sectsize);
> >
> > -     tmp = pread(xi->dfd, buf, new_sb->sb_sectsize, 0);
> > -     if (tmp < 0) {
> > +     off = pread(xi->dfd, buf, new_sb->sb_sectsize, 0);
> > +     if (off < 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.
> > +      */
>
> except you already did "if (off < 0) fail" above this.
>
> Ok, at this point I think it might be best to revert to Dave's original
> version.
>
> If there were specific problems you were trying to address, can you point
> them out?
>
> Thanks,
> -Eric
>
> ​(inserting your next email)​


>
> On 4/7/16 7:25 PM, Eric Sandeen wrote:
> >> @@ -1299,15 +1370,23 @@ zero_old_xfs_structures(
> >> >    }
> >> >    memset(buf, 0, new_sb->sb_sectsize);
> >> >
> >> > -  tmp = pread(xi->dfd, buf, new_sb->sb_sectsize, 0);
> >> > -  if (tmp < 0) {
> >> > +  off = pread(xi->dfd, buf, new_sb->sb_sectsize, 0);
> >> > +  if (off < 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.
> >> > +   */
> > except you already did "if (off < 0) fail" above this.
>
> (oh, right, < 0 is different than == 0, sorry; so that part is ok)
>
> Possibly better as:
>
> if (off < 0 || (tmp != new_sb->sb_sectsize && !xi->disfile))
>         fprintf("error reading existing superblock ...")
>
​OK, better to be sure. :-)
​


>
>
> I still think this patch might need a reset though :)
>
> Thanks,
> -Eric
>
> > Ok, at this point I think it might be best to revert to Dave's original
> version.
> >
> > If there were specific problems you were trying to address, can you
> point them out?
>

​On few places, the original patch looked as if files had direct IO still
enabled​ (using platform_findsize...), and I think it was causing some
failures - fixing issues is why I did most of the changes.

I will revert to the original version and see what exactly fails. But with
being Friday late afternoon, the results will be available the next week
(Wednesday and further, all my courses at university are stuffed in
Mon/Tue).

Cheers,
Jan


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

[-- Attachment #1.2: Type: text/html, Size: 30507 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] 84+ messages in thread

* Re: [PATCH 15/19] mkfs: don't treat files as though they are block devices
  2016-04-08 14:58     ` Jan Tulak
@ 2016-04-08 15:50       ` Eric Sandeen
  2016-04-08 15:56         ` Jan Tulak
  2016-04-09  4:12       ` Eric Sandeen
  2016-04-14  9:49       ` Jan Tulak
  2 siblings, 1 reply; 84+ messages in thread
From: Eric Sandeen @ 2016-04-08 15:50 UTC (permalink / raw)
  To: Jan Tulak; +Cc: xfs-oss

On 4/8/16 9:58 AM, Jan Tulak wrote:
>     Ok, platform_findsizes already explicitly handled regular files, and tries to
>     find out via an xfs ioctl what the minimum DIO size is, and uses that for
>     the sector size for the filesystem in the iamge. 
> 
> 
>     Now you stat & get the blocksize, and use that instead, but it's likely
>     to be different:
> 
>     i.e. before:
> 
>     # mkfs/mkfs.xfs -f fsfile
>     meta-data=fsfile                 isize=512    agcount=4, agsize=65536 blks
>              =                       sectsz=512   attr=2, projid32bit=1
> 
>     after:
> 
>     # mkfs/mkfs.xfs -f fsfile
>     meta-data=fsfile                 isize=512    agcount=4, agsize=65536 blks
>              =                       sectsz=4096  attr=2, projid32bit=1
> 
>     and also, now:
> 
>     # mkfs/mkfs.xfs -f -dfile,name=fsfile,size=1g -b size=2048
>     block size 2048 cannot be smaller than logical sector size 4096
> 
>     What prompted you to make this change, was there some other problem you
>     needed to fix?
> 
> 
> ​But DIO is disabled for the files, per the commit message:
> [...] and turning off
> direct IO. Then ensure that we check the "isfile" options before
> doing things that are specific to block devices.  Also, as direct IO
> is disabled for files, use statfs() for getting host FS blocksize,
> not platform_findsizes().​

But doing DIO to the file during mkfs isn't the issue I'm talking about;
For example a vm image hosted in a file will have direct IO done to it
when it is in use, and filesystem block size is not the controlling
factor there.

With your change, we can no longer make i.e. a 2k fs image hosted on a 4k
fs.  i.e. your change regresses this commit:

commit 98dd72d3b239050138cf9eb9373c83743878a7d2
Author: Eric Sandeen <sandeen@sandeen.net>
Date:   Fri Dec 18 12:15:25 2015 +1100

    mkfs: get sector size from host fs d_miniosz when mkfs'ing file
    
    Now that we allow logical-sector-sized DIOs even if our xfs
    filesystem is set to physical-sector-sized "sectors," we can
    allow the creation of filesystem images with block and sector
    sizes down to the host device's logical sector size, rather
    than the filesystem's sector size.
    
    So in platform_findsizes(), change our query of the filesystem
    to an XFS_IOC_DIOINFO query, and use the returned d_miniosz for
    sector size in the S_IFREG case.
    
    This allows the creation of i.e. a 2k block sized image on
    an xfs filesystem w/ 4k sector size created on a 4k/512
    block device, which would otherwise fail today.
    
    Signed-off-by: Eric Sandeen <sandeen@redhat.com>
    Reviewed-by: Dave Chinner <dchinner@redhat.com>
    Signed-off-by: Dave Chinner <david@fromorbit.com>


> So we have to use whatever the underlying fs tells us, not what the physical device has, right?

Well, tells us about what?  XFS can tell us its block size, but also can
tell us about minimum size and alignment required for direct IO, which is
more relevant to a filesystem image than the filesystem's block size.

> ​ Rather, I wonder if there is any reason to keep the
> platform_findsizes part about regular files - it shouldn't get into
> the branch ever.

In general, having a wrapper which finds sizes of a target, regardless of
platform, device, or file, makes sense to me rather than having stat calls
in various other places...

-Eric

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

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

* Re: [PATCH 18/19] mkfs: unit conversions are case insensitive
  2016-04-08  9:08           ` Jan Tulak
@ 2016-04-08 15:51             ` Eric Sandeen
  0 siblings, 0 replies; 84+ messages in thread
From: Eric Sandeen @ 2016-04-08 15:51 UTC (permalink / raw)
  To: xfs

On 4/8/16 4:08 AM, Jan Tulak wrote:
> On Fri, Apr 8, 2016 at 3:03 AM, Dave Chinner <david@fromorbit.com <mailto:david@fromorbit.com>>wrote:
> 

...

>     $ git grep ^cvtnum
>     estimate/xfs_estimate.c:cvtnum(char *s)
>     libxcmd/input.c:cvtnum(
>     mkfs/xfs_mkfs.c:cvtnum(
> 
> 
> ​Ah, I see. A nice trick. :-)
> 
> It might be good to merge the three functions, but I think it can
> wait for when this patchset is done - or there is always going to be
> something more to add...

Yeah, sorry, that was a tangent.  Just something to clean up some day.

-Eric

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

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

* Re: [PATCH 09/19] mkfs: use getnum_checked for all ranged parameters
  2016-04-08 10:47     ` Jan Tulak
@ 2016-04-08 15:52       ` Eric Sandeen
  0 siblings, 0 replies; 84+ messages in thread
From: Eric Sandeen @ 2016-04-08 15:52 UTC (permalink / raw)
  To: xfs



On 4/8/16 5:47 AM, Jan Tulak wrote:
> On Thu, Apr 7, 2016 at 9:02 PM, Eric Sandeen <sandeen@sandeen.net <mailto:sandeen@sandeen.net>>wrote:
> 
> 
> 
>     On 3/24/16 6:15 AM, jtulak@redhat.com <mailto:jtulak@redhat.com> wrote:
>     > From: Dave Chinner <dchinner@redhat.com <mailto: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 <mailto:dchinner@redhat.com>>
>     > Signed-off-by: Jan Tulak <jtulak@redhat.com <mailto:jtulak@redhat.com>>
> 
>     Looks ok.
> 
>     Signed-off-by: Eric Sandeen <sandeen@redhat.com <mailto:sandeen@redhat.com>>
> 
> 
> ​Or Reviewed-by? :-)

Yes, that :)

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

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

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

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


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

On Fri, Apr 8, 2016 at 5:50 PM, Eric Sandeen <sandeen@sandeen.net> wrote:

> On 4/8/16 9:58 AM, Jan Tulak wrote:
> >     Ok, platform_findsizes already explicitly handled regular files, and
> tries to
> >     find out via an xfs ioctl what the minimum DIO size is, and uses
> that for
> >     the sector size for the filesystem in the iamge.
> >
> >
> >     Now you stat & get the blocksize, and use that instead, but it's
> likely
> >     to be different:
> >
> >     i.e. before:
> >
> >     # mkfs/mkfs.xfs -f fsfile
> >     meta-data=fsfile                 isize=512    agcount=4,
> agsize=65536 blks
> >              =                       sectsz=512   attr=2, projid32bit=1
> >
> >     after:
> >
> >     # mkfs/mkfs.xfs -f fsfile
> >     meta-data=fsfile                 isize=512    agcount=4,
> agsize=65536 blks
> >              =                       sectsz=4096  attr=2, projid32bit=1
> >
> >     and also, now:
> >
> >     # mkfs/mkfs.xfs -f -dfile,name=fsfile,size=1g -b size=2048
> >     block size 2048 cannot be smaller than logical sector size 4096
> >
> >     What prompted you to make this change, was there some other problem
> you
> >     needed to fix?
> >
> >
> > ​But DIO is disabled for the files, per the commit message:
> > [...] and turning off
> > direct IO. Then ensure that we check the "isfile" options before
> > doing things that are specific to block devices.  Also, as direct IO
> > is disabled for files, use statfs() for getting host FS blocksize,
> > not platform_findsizes().​
>
> But doing DIO to the file during mkfs isn't the issue I'm talking about;
> For example a vm image hosted in a file will have direct IO done to it
> when it is in use, and filesystem block size is not the controlling
> factor there.
>
> With your change, we can no longer make i.e. a 2k fs image hosted on a 4k
> fs.  i.e. your change regresses this commit:
>
> commit 98dd72d3b239050138cf9eb9373c83743878a7d2
> Author: Eric Sandeen <sandeen@sandeen.net>
> Date:   Fri Dec 18 12:15:25 2015 +1100
>
>     mkfs: get sector size from host fs d_miniosz when mkfs'ing file
>
>     Now that we allow logical-sector-sized DIOs even if our xfs
>     filesystem is set to physical-sector-sized "sectors," we can
>     allow the creation of filesystem images with block and sector
>     sizes down to the host device's logical sector size, rather
>     than the filesystem's sector size.
>
>     So in platform_findsizes(), change our query of the filesystem
>     to an XFS_IOC_DIOINFO query, and use the returned d_miniosz for
>     sector size in the S_IFREG case.
>
>     This allows the creation of i.e. a 2k block sized image on
>     an xfs filesystem w/ 4k sector size created on a 4k/512
>     block device, which would otherwise fail today.
>
>     Signed-off-by: Eric Sandeen <sandeen@redhat.com>
>     Reviewed-by: Dave Chinner <dchinner@redhat.com>
>     Signed-off-by: Dave Chinner <david@fromorbit.com>
>
>
> > So we have to use whatever the underlying fs tells us, not what the
> physical device has, right?
>
> Well, tells us about what?  XFS can tell us its block size, but also can
> tell us about minimum size and alignment required for direct IO, which is
> more relevant to a filesystem image than the filesystem's block size.
>
> > ​ Rather, I wonder if there is any reason to keep the
> > platform_findsizes part about regular files - it shouldn't get into
> > the branch ever.
>
> In general, having a wrapper which finds sizes of a target, regardless of
> platform, device, or file, makes sense to me rather than having stat calls
> in various other places...
>
> -Eric
>

It seems I misunderstood some things about what ​happens/what should happen
with files. :-)
I will see what happens with the tests, what difference in the results is
with this patch in the original version.

​Cheers,
Jan​



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

[-- Attachment #1.2: Type: text/html, Size: 5967 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] 84+ messages in thread

* Re: [PATCH 08/19] mkfs: getbool is redundant
  2016-04-08 10:30     ` Jan Tulak
@ 2016-04-08 17:41       ` Eric Sandeen
  0 siblings, 0 replies; 84+ messages in thread
From: Eric Sandeen @ 2016-04-08 17:41 UTC (permalink / raw)
  To: xfs



On 4/8/16 5:30 AM, Jan Tulak wrote:
> On Thu, Apr 7, 2016 at 7:25 PM, Eric Sandeen <sandeen@sandeen.net <mailto:sandeen@sandeen.net>>wrote:
> 
> 
> 
>     "Many options allow for an optional argument of 0 or 1, ..."
> 
>     > +disable or enable the functionality, in a forward-compatible syntax.
> 
>     What does "forward-compatible syntax" mean?  I'm not sure that clarifies
>     anything for the reader.
> 
> ​Yeah, I should reformulate it, I think. The meaning is that it won't
> matter what the defaults are now, or will be in the future. E.g., if
> you had a script creating a fs without crc before, when it was
> disabled by default, and we changed the default, you are now creating
> with the crc. But if you give it -m crc=0, then no matter what the
> default is, you have it always disabled.

Ok, I see.

> How about changing the line to "Boolean options allows for optional
> argument of value 0 or 1, to explicitly disable or enable the
> functionality," and dropping the forward-compatible part?

I think just:

Many options accept an optional argument of value 0 or 1, to explicitly
disable or enable the functionality.

would suffice.

>  
> 
>     Otherwise this looks ok to me; Dave explained that it is intentional to
>     make every single option accept a value, whether it is now
>     boolean or a numeric value, so there is no such thing as a bare "--flag"
>     anymore; such flags are always "--flag [0|1]" now, right?
> 
> 
> ​For options inside of -m, -d and such, yes. Top-level flags, that is
> -f, -q, -N, -K and -V, are still only flags, but these don't change
> the FS attributes. They are something different from the other.
> Still, I wonder whether they should accept [0|1] too...

Eh, not right now ;)

Thanks,
-Eric

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

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

* Re: [PATCH 17/19] xfsprogs: disable truncating of files
  2016-04-08 10:06     ` Jan Tulak
@ 2016-04-08 23:08       ` Dave Chinner
  2016-04-13 15:08         ` Jan Tulak
  0 siblings, 1 reply; 84+ messages in thread
From: Dave Chinner @ 2016-04-08 23:08 UTC (permalink / raw)
  To: Jan Tulak; +Cc: xfs-oss

On Fri, Apr 08, 2016 at 12:06:35PM +0200, Jan Tulak wrote:
> On Fri, Apr 8, 2016 at 2:09 AM, Dave Chinner <david@fromorbit.com> wrote:
> 
> > On Thu, Mar 24, 2016 at 12:15:34PM +0100, jtulak@redhat.com wrote:
> > > From: Jan Tulak <jtulak@redhat.com>
> > >
> > > Unify mkfs.xfs behaviour a bit and never truncate files. If the user
> > > is trying to mkfs an existing file, we don't want to destroy anything
> > > he did with the file before (sparse file, allocations...)
> >
> > Why not? We do that with discard-by-default to block devices,
> > O_TRUNC is exactly the same situation with a file - we completely
> > re-initialise the file from a known state if mkfs has been asked to
> > create the file.
> >
> But AFAIK, we don't zero-out entire spindle devices,

Unless the controller above them supports discard or whatever
implementation the storage protocol uses (e.g. UNMAP or WRITE_SAME).
e.g, the "spindle devices" often are big raid arrays that are using
thin provisioning, compression and dedupe internally, so running
discard on them does make a significant difference to their
behaviour.

> we don't ask if the drive skips some blocks (i.e. because they are bad),

That's irrelevant to the issue at hand.

> and we don't care
> about what an underlaying layer (like LVM) did with the block device.

Actually, we do, because users care about their storage stack doing
sane management operations automatically.

That's why we issued a discard - it tells the underlying devices to
re-initialise the storage on this device *if they care about such
things*. Stuff like thinly provisioned devices rely on mkfs
behaviour like this to recycle used storage efficiently and
transparently. The user expects things to "just work" and this is
one of those things that makes it "just work".

> From
> this point of view, we shouldn't care about the file either.
> 
> I can be missing something, though.

I think you're missing the fact that we don't know what the
*underlying storage* cares about, so we need to tell them in some
way that a device or image file is being re-initialised from
scratch. Whether that is by truncating the image file (so the
filesytem can issue discards on the now unused space) or by issuing
discard ioctls ourselves, it really doesn't matter. The key point is
that we have a mechanism that allows us to notify the underlying
storage of the "this is re-initialised storage" intent of mkfs.

So from that perspective, the O_TRUNC behaviour should remain.

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] 84+ messages in thread

* Re: [PATCH 15/19] mkfs: don't treat files as though they are block devices
  2016-04-08 14:58     ` Jan Tulak
  2016-04-08 15:50       ` Eric Sandeen
@ 2016-04-09  4:12       ` Eric Sandeen
  2016-04-13 15:43         ` Jan Tulak
  2016-04-14  9:49       ` Jan Tulak
  2 siblings, 1 reply; 84+ messages in thread
From: Eric Sandeen @ 2016-04-09  4:12 UTC (permalink / raw)
  To: xfs



On 4/8/16 9:58 AM, Jan Tulak wrote:
>     This one causes at least one interesting issue:
> 
>     #mkfs/mkfs.xfs
>     Error accessing specified device (null): Bad address
>     Usage: mkfs.xfs
>     ...
> 
>     because:
> 
>             check_device_type(dfile, &xi.disfile, !dsize, !dfile,
>                               Nflag ? NULL : &xi.dcreat, force_overwrite, "d");
> 
>     so "dfile" can be NULL, but that function immediately tries to stat it.
> 
> 
> ​A simple if NULL, then usage() should take care of this...

Well, think hard about that.  If dfile == NULL and bails with usage(), then
what is the point of having !dfile as a function argument?

Validation of having a target specified as either -dfile= or as the last argument
should probably happen before the call to check_device_type.

-Eric

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

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

* Re: [PATCH 17/19] xfsprogs: disable truncating of files
  2016-04-08 23:08       ` Dave Chinner
@ 2016-04-13 15:08         ` Jan Tulak
  2016-04-13 16:17           ` Eric Sandeen
  0 siblings, 1 reply; 84+ messages in thread
From: Jan Tulak @ 2016-04-13 15:08 UTC (permalink / raw)
  To: Dave Chinner; +Cc: xfs-oss


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

On Sat, Apr 9, 2016 at 1:08 AM, Dave Chinner <david@fromorbit.com> wrote:

> On Fri, Apr 08, 2016 at 12:06:35PM +0200, Jan Tulak wrote:
> > On Fri, Apr 8, 2016 at 2:09 AM, Dave Chinner <david@fromorbit.com>
> wrote:
> >
> > > On Thu, Mar 24, 2016 at 12:15:34PM +0100, jtulak@redhat.com wrote:
> > > > From: Jan Tulak <jtulak@redhat.com>
> > > >
> > > > Unify mkfs.xfs behaviour a bit and never truncate files. If the user
> > > > is trying to mkfs an existing file, we don't want to destroy anything
> > > > he did with the file before (sparse file, allocations...)
> > >
> > > Why not? We do that with discard-by-default to block devices,
> > > O_TRUNC is exactly the same situation with a file - we completely
> > > re-initialise the file from a known state if mkfs has been asked to
> > > create the file.
> > >
> > But AFAIK, we don't zero-out entire spindle devices,
>
> Unless the controller above them supports discard or whatever
> implementation the storage protocol uses (e.g. UNMAP or WRITE_SAME).
> e.g, the "spindle devices" often are big raid arrays that are using
> thin provisioning, compression and dedupe internally, so running
> discard on them does make a significant difference to their
> behaviour.
>
> > we don't ask if the drive skips some blocks (i.e. because they are bad),
>
> That's irrelevant to the issue at hand.
>
> > and we don't care
> > about what an underlaying layer (like LVM) did with the block device.
>
> Actually, we do, because users care about their storage stack doing
> sane management operations automatically.
>
> That's why we issued a discard - it tells the underlying devices to
> re-initialise the storage on this device *if they care about such
> things*. Stuff like thinly provisioned devices rely on mkfs
> behaviour like this to recycle used storage efficiently and
> transparently. The user expects things to "just work" and this is
> one of those things that makes it "just work".
>
> > From
> > this point of view, we shouldn't care about the file either.
> >
> > I can be missing something, though.
>
> I think you're missing the fact that we don't know what the
> *underlying storage* cares about, so we need to tell them in some
> way that a device or image file is being re-initialised from
> scratch. Whether that is by truncating the image file (so the
> filesytem can issue discards on the now unused space) or by issuing
> discard ioctls ourselves, it really doesn't matter. The key point is
> that we have a mechanism that allows us to notify the underlying
> storage of the "this is re-initialised storage" intent of mkfs.
>
> So from that perspective, the O_TRUNC behaviour should remain.
>
> Cheers,
>
> Dave.
> --
> Dave Chinner
> david@fromorbit.com
>

All right​, I will keep the O_TRUNC there. However, should it truncate the
file every time, or should we offer a way how to avoid the file truncating?
Until now, mkfs behaved differently based on whether -d file was given, or
not. Your explanation suggests that we should truncate every time, right?


​Cheers,
Jan​



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

[-- Attachment #1.2: Type: text/html, Size: 4758 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] 84+ messages in thread

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


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

On Sat, Apr 9, 2016 at 6:12 AM, Eric Sandeen <sandeen@sandeen.net> wrote:

>
>
> On 4/8/16 9:58 AM, Jan Tulak wrote:
> >     This one causes at least one interesting issue:
> >
> >     #mkfs/mkfs.xfs
> >     Error accessing specified device (null): Bad address
> >     Usage: mkfs.xfs
> >     ...
> >
> >     because:
> >
> >             check_device_type(dfile, &xi.disfile, !dsize, !dfile,
> >                               Nflag ? NULL : &xi.dcreat,
> force_overwrite, "d");
> >
> >     so "dfile" can be NULL, but that function immediately tries to stat
> it.
> >
> >
> > ​A simple if NULL, then usage() should take care of this...
>
> Well, think hard about that.  If dfile == NULL and bails with usage(), then
> what is the point of having !dfile as a function argument?
>
> Validation of having a target specified as either -dfile= or as the last
> argument
> should probably happen before the call to check_device_type.
>
>
But what about this?

case D_NAME:
      xi.dname = getstr(value, &dopts, D_     NAME);

[...]

if (argc - optind > 1) {
      [print error]
} else if (argc - optind == 1) {
       dfile = xi.volname = getstr(argv[optind], &dopts, D_NAME);
} else
       dfile = xi.dname;​

}

[
​... until the first occurence of dfile]

check_device_type(dfile, &xi.disfile, !dsize, !dfile,
         Nflag ? NULL : &xi.dcreat, force_overwrite, "d");
​
​so if there is -d name= and nothing at the end, then dfile contains D_NAME
value. If there is a path at the end, then, then no matter about -d name,
we have dfile filled with something. So I can't find a way how to have
dfile == NULL without omitting both a path as the last argument, and
-dname...

The no_name (!dfile) argument is in check_device_type() for a single reason
- raising error on
if (*isfile && (no_size || no_name))

But !string is true only when string==NULL. For an empty string: !"" is 0.
So I don't see the reason for no_name argument at all - it seems to
confuse, and in current use can be replaced with test to NULL, or !name.

DTTO for xi.logname/xi.rtname.

​Cheers,
Jan​

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

[-- Attachment #1.2: Type: text/html, Size: 5920 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] 84+ messages in thread

* Re: [PATCH 17/19] xfsprogs: disable truncating of files
  2016-04-13 15:08         ` Jan Tulak
@ 2016-04-13 16:17           ` Eric Sandeen
  2016-04-13 16:23             ` Jan Tulak
  2016-04-13 21:37             ` Dave Chinner
  0 siblings, 2 replies; 84+ messages in thread
From: Eric Sandeen @ 2016-04-13 16:17 UTC (permalink / raw)
  To: xfs

On 4/13/16 10:08 AM, Jan Tulak wrote:

...

> All right​, I will keep the O_TRUNC there. However, should it
> truncate the file every time, or should we offer a way how to avoid
> the file truncating? Until now, mkfs behaved differently based on
> whether -d file was given, or not. Your explanation suggests that we
> should truncate every time, right?

There are probably valid reasons to keep size as well as to truncate;
it's not immediately clear to me how we should handle it.

Honestly, at this point, in the interest of getting the other fixes in,
I think I might rather see the truncating behavior unchanged from what
we have today; we can tackle that as a separate problem at a later date.

What do you think?

-Eric

> 
> ​Cheers,
> Jan​

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

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

* Re: [PATCH 17/19] xfsprogs: disable truncating of files
  2016-04-13 16:17           ` Eric Sandeen
@ 2016-04-13 16:23             ` Jan Tulak
  2016-04-13 16:25               ` Eric Sandeen
  2016-04-13 21:37             ` Dave Chinner
  1 sibling, 1 reply; 84+ messages in thread
From: Jan Tulak @ 2016-04-13 16:23 UTC (permalink / raw)
  To: Eric Sandeen; +Cc: xfs-oss


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

On Wed, Apr 13, 2016 at 6:17 PM, Eric Sandeen <sandeen@sandeen.net> wrote:

> On 4/13/16 10:08 AM, Jan Tulak wrote:
>
> ...
>
> > All right​, I will keep the O_TRUNC there. However, should it
> > truncate the file every time, or should we offer a way how to avoid
> > the file truncating? Until now, mkfs behaved differently based on
> > whether -d file was given, or not. Your explanation suggests that we
> > should truncate every time, right?
>
> There are probably valid reasons to keep size as well as to truncate;
> it's not immediately clear to me how we should handle it.
>
> Honestly, at this point, in the interest of getting the other fixes in,
> I think I might rather see the truncating behavior unchanged from what
> we have today; we can tackle that as a separate problem at a later date.
>
> What do you think?
>
> ​For keeping the size, the easiest way might be to implicitly set xi.dsize
(or whatever) to the current size. Of course, after a check for -d
file,name,size combo. AFAIK (without looking to the code, I'm just ending
for today and in the middle of shutting everything down :-) ), we ​do the
truncation after the combo check. So this should be no big issue... I will
look on this tomorrow, to know better.

Cheers,
Jan



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

[-- Attachment #1.2: Type: text/html, Size: 2731 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] 84+ messages in thread

* Re: [PATCH 17/19] xfsprogs: disable truncating of files
  2016-04-13 16:23             ` Jan Tulak
@ 2016-04-13 16:25               ` Eric Sandeen
  0 siblings, 0 replies; 84+ messages in thread
From: Eric Sandeen @ 2016-04-13 16:25 UTC (permalink / raw)
  To: Jan Tulak; +Cc: xfs-oss



On 4/13/16 11:23 AM, Jan Tulak wrote:
> 
> 
> On Wed, Apr 13, 2016 at 6:17 PM, Eric Sandeen <sandeen@sandeen.net <mailto:sandeen@sandeen.net>> wrote:
> 
>     On 4/13/16 10:08 AM, Jan Tulak wrote:
> 
>     ...
> 
>     > All right​, I will keep the O_TRUNC there. However, should it
>     > truncate the file every time, or should we offer a way how to avoid
>     > the file truncating? Until now, mkfs behaved differently based on
>     > whether -d file was given, or not. Your explanation suggests that we
>     > should truncate every time, right?
> 
>     There are probably valid reasons to keep size as well as to truncate;
>     it's not immediately clear to me how we should handle it.
> 
>     Honestly, at this point, in the interest of getting the other fixes in,
>     I think I might rather see the truncating behavior unchanged from what
>     we have today; we can tackle that as a separate problem at a later date.
> 
>     What do you think?
> 
> ​For keeping the size, the easiest way might be to implicitly set
> xi.dsize (or whatever) to the current size. Of course, after a check
> for -d file,name,size combo. AFAIK (without looking to the code, I'm
> just ending for today and in the middle of shutting everything down
> :-) ), we ​do the truncation after the combo check. So this should be
> no big issue... I will look on this tomorrow, to know better.

I'm just saying; let's not change current behavior without good reason.
If it requires a lot of discussion, let's keep current behavior in all
cases for now, so that we can move the larger patchset forward.

Thanks,
-Eric

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

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

* Re: [PATCH 17/19] xfsprogs: disable truncating of files
  2016-04-13 16:17           ` Eric Sandeen
  2016-04-13 16:23             ` Jan Tulak
@ 2016-04-13 21:37             ` Dave Chinner
  2016-04-14 12:31               ` Jan Tulak
  1 sibling, 1 reply; 84+ messages in thread
From: Dave Chinner @ 2016-04-13 21:37 UTC (permalink / raw)
  To: Eric Sandeen; +Cc: xfs

On Wed, Apr 13, 2016 at 11:17:45AM -0500, Eric Sandeen wrote:
> On 4/13/16 10:08 AM, Jan Tulak wrote:
> 
> ...
> 
> > All right​, I will keep the O_TRUNC there. However, should it
> > truncate the file every time, or should we offer a way how to avoid
> > the file truncating? Until now, mkfs behaved differently based on
> > whether -d file was given, or not. Your explanation suggests that we
> > should truncate every time, right?
> 
> There are probably valid reasons to keep size as well as to truncate;
> it's not immediately clear to me how we should handle it.

That's easy: don't specify -dfile or -dsize, and instead let mkfs
detect that it is file automatically. Because it's not given a size,
or that it's supposed to be a file, it should not attempt to change
the "device" in any way.

When block devices grow fallocate support, we can unify the discard
behaviour to be a hole punch, and then it will work identically on
devices and files treated this way.

> Honestly, at this point, in the interest of getting the other fixes in,
> I think I might rather see the truncating behavior unchanged from what
> we have today; we can tackle that as a separate problem at a later date.

Yup, don't change it in this patch series.

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] 84+ messages in thread

* Re: [PATCH 15/19] mkfs: don't treat files as though they are block devices
  2016-04-08 14:58     ` Jan Tulak
  2016-04-08 15:50       ` Eric Sandeen
  2016-04-09  4:12       ` Eric Sandeen
@ 2016-04-14  9:49       ` Jan Tulak
  2016-04-20  9:51         ` Jan Tulak
  2 siblings, 1 reply; 84+ messages in thread
From: Jan Tulak @ 2016-04-14  9:49 UTC (permalink / raw)
  To: Eric Sandeen; +Cc: xfs-oss


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

On Fri, Apr 8, 2016 at 4:58 PM, Jan Tulak <jtulak@redhat.com> wrote:

> On Fri, Apr 8, 2016 at 2:25 AM, Eric Sandeen <sandeen@sandeen.net> wrote:
>
>
[
>> ​snip]​
>>
>> I still think this patch might need a reset though :)
>>
>> Thanks,
>> -Eric
>>
>>
> ​On few places, the original patch looked as if files had direct IO still
> enabled​ (using platform_findsize...), and I think it was causing some
> failures - fixing issues is why I did most of the changes.
>
> I will revert to the original version and see what exactly fails. But with
> being Friday late afternoon, the results will be available the next week
> (Wednesday and further, all my courses at university are stuffed in
> Mon/Tue).
>
>
​All right. So I run the tests on the set with both this and the original
version of this patch and there is no change in results. Here and there
some tests failed on one run, but on other runs they are ok and I can't get
them to fail again (namely, xfs/033, 073 and 085 did this).

It looks like whatever the issues were to start the changes, they are
already resolved. Thus, I will send the original patch in the next batch.


Cheers,
​Jan​



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

[-- Attachment #1.2: Type: text/html, Size: 4148 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] 84+ messages in thread

* Re: [PATCH 17/19] xfsprogs: disable truncating of files
  2016-04-13 21:37             ` Dave Chinner
@ 2016-04-14 12:31               ` Jan Tulak
  0 siblings, 0 replies; 84+ messages in thread
From: Jan Tulak @ 2016-04-14 12:31 UTC (permalink / raw)
  To: Dave Chinner; +Cc: Eric Sandeen, xfs-oss


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

On Wed, Apr 13, 2016 at 11:37 PM, Dave Chinner <david@fromorbit.com> wrote:

> On Wed, Apr 13, 2016 at 11:17:45AM -0500, Eric Sandeen wrote:
> > On 4/13/16 10:08 AM, Jan Tulak wrote:
> >
> > ...
> >
> > > All right​, I will keep the O_TRUNC there. However, should it
> > > truncate the file every time, or should we offer a way how to avoid
> > > the file truncating? Until now, mkfs behaved differently based on
> > > whether -d file was given, or not. Your explanation suggests that we
> > > should truncate every time, right?
> >
> > There are probably valid reasons to keep size as well as to truncate;
> > it's not immediately clear to me how we should handle it.
>
> That's easy: don't specify -dfile or -dsize, and instead let mkfs
> detect that it is file automatically. Because it's not given a size,
> or that it's supposed to be a file, it should not attempt to change
> the "device" in any way.
>
> When block devices grow fallocate support, we can unify the discard
> behaviour to be a hole punch, and then it will work identically on
> devices and files treated this way.
>
> > Honestly, at this point, in the interest of getting the other fixes in,
> > I think I might rather see the truncating behavior unchanged from what
> > we have today; we can tackle that as a separate problem at a later date.
>
> Yup, don't change it in this patch series.
>
>
Looking on this patch again, I think that it can be removed entirely. After
reverting the O_CREATE part, the only thing it does is differentiating
error messages between files and block devices, which is not worth of a
patch.

Cheers,
Jan

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

[-- Attachment #1.2: Type: text/html, Size: 3083 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] 84+ messages in thread

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


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

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

> On Fri, Apr 8, 2016 at 4:58 PM, Jan Tulak <jtulak@redhat.com> wrote:
>
>> On Fri, Apr 8, 2016 at 2:25 AM, Eric Sandeen <sandeen@sandeen.net> wrote:
>>
>>
> [
>>> ​snip]​
>>>
>>> I still think this patch might need a reset though :)
>>>
>>> Thanks,
>>> -Eric
>>>
>>>
>> ​On few places, the original patch looked as if files had direct IO still
>> enabled​ (using platform_findsize...), and I think it was causing some
>> failures - fixing issues is why I did most of the changes.
>>
>> I will revert to the original version and see what exactly fails. But
>> with being Friday late afternoon, the results will be available the next
>> week (Wednesday and further, all my courses at university are stuffed in
>> Mon/Tue).
>>
>>
> ​All right. So I run the tests on the set with both this and the original
> version of this patch and there is no change in results. Here and there
> some tests failed on one run, but on other runs they are ok and I can't get
> them to fail again (namely, xfs/033, 073 and 085 did this).
>
> It looks like whatever the issues were to start the changes, they are
> already resolved. Thus, I will send the original patch in the next batch.
>
>
> ​I'm taking it back, one tests fails, most likely it happened when I
removed patch 17 - xfsprogs: disable truncating of files.
If I do "mkfs.xfs $file", it doesn't know the old size to recreate it. I'm
working on a change for this patch to fix this issue, but I'm not entirely
certain how to proceed. The right place to get the size seems to be
get_topology(). I could save it into xi.dsize, but then libxfs_init()
zeroes it.

So I think that I might rather convert the measured size do char *dsize and
pretend that it is an user-given value. But this looks to me more like a
hack. On the other side, any other way would require further changes in the
code to convert the char* to int as soon as possible - which does not
belong to this patch...

Diff of the change:

@@ -999,7 +999,7 @@ 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;
                } else
@@ -2273,6 +2273,18 @@ _("Minimum block size for CRC enabled filesystems is
%d bytes.\n"),
        memset(&ft, 0, sizeof(ft));
        get_topology(&xi, &ft, force_overwrite);

+       /*
+        * If it is an existing file and we have no info about it
+        * like in case of "mkfs.xfs some-file", we need to save the size
+        * of the file to somewhere where it can be read later.
+        */
+       if (xi.disfile && !xi.dcreat && xi.dsize) {
+               long long num = xi.dsize * ft.lsectorsize;
+               int length = snprintf(NULL, 0,"%lld", num);
+               dsize = calloc( length + 1 ,sizeof(char));
+               sprintf(dsize, "%lld", num);
+       }
+
        if (!ssflag) {
                /*
                 * Unless specified manually on the command line use the

So, what do you think about this?

Thanks,
Jan

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

[-- Attachment #1.2: Type: text/html, Size: 10179 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] 84+ messages in thread

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


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

On Wed, Apr 20, 2016 at 11:51 AM, Jan Tulak <jtulak@redhat.com> wrote:

> On Thu, Apr 14, 2016 at 11:49 AM, Jan Tulak <jtulak@redhat.com> wrote:
>
>> On Fri, Apr 8, 2016 at 4:58 PM, Jan Tulak <jtulak@redhat.com> wrote:
>>
>>> On Fri, Apr 8, 2016 at 2:25 AM, Eric Sandeen <sandeen@sandeen.net>
>>> wrote:
>>>
>> [
>>>> ​snip]​
>>>>
>>>> I still think this patch might need a reset though :)
>>>>
>>>> Thanks,
>>>> -Eric
>>>>
>>>>
>>> ​On few places, the original patch looked as if files had direct IO
>>> still enabled​ (using platform_findsize...), and I think it was causing
>>> some failures - fixing issues is why I did most of the changes.
>>>
>>> I will revert to the original version and see what exactly fails. But
>>> with being Friday late afternoon, the results will be available the next
>>> week (Wednesday and further, all my courses at university are stuffed in
>>> Mon/Tue).
>>>
>>>
>> ​All right. So I run the tests on the set with both this and the original
>> version of this patch and there is no change in results. Here and there
>> some tests failed on one run, but on other runs they are ok and I can't get
>> them to fail again (namely, xfs/033, 073 and 085 did this).
>>
>> It looks like whatever the issues were to start the changes, they are
>> already resolved. Thus, I will send the original patch in the next batch.
>>
>>
>> ​I'm taking it back, one tests fails, most likely it happened when I
> removed patch 17 - xfsprogs: disable truncating of files.
> If I do "mkfs.xfs $file", it doesn't know the old size to recreate it. I'm
> working on a change for this patch to fix this issue, but I'm not entirely
> certain how to proceed. The right place to get the size seems to be
> get_topology(). I could save it into xi.dsize, but then libxfs_init()
> zeroes it.
>
> So I think that I might rather convert the measured size do char *dsize
> and pretend that it is an user-given value. But this looks to me more like
> a hack. On the other side, any other way would require further changes in
> the code to convert the char* to int as soon as possible - which does not
> belong to this patch...
>
> Diff of the change:
>
> @@ -999,7 +999,7 @@ 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;
>                 } else
> @@ -2273,6 +2273,18 @@ _("Minimum block size for CRC enabled filesystems
> is %d bytes.\n"),
>         memset(&ft, 0, sizeof(ft));
>         get_topology(&xi, &ft, force_overwrite);
>
> +       /*
> +        * If it is an existing file and we have no info about it
> +        * like in case of "mkfs.xfs some-file", we need to save the size
> +        * of the file to somewhere where it can be read later.
> +        */
> +       if (xi.disfile && !xi.dcreat && xi.dsize) {
> +               long long num = xi.dsize * ft.lsectorsize;
> +               int length = snprintf(NULL, 0,"%lld", num);
> +               dsize = calloc( length + 1 ,sizeof(char));
> +               sprintf(dsize, "%lld", num);
> +       }
> +
>         if (!ssflag) {
>                 /*
>                  * Unless specified manually on the command line use the
>
> So, what do you think about this?
>
> ​
And before anyone will reply, I found that putting a platform_findsizes​
into libxfs_init will fix it too. Which is nice, especially because for
block devices, the findsizes is already used there. So ignore the previous
hack. :-)

Cheers,
Jan


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

[-- Attachment #1.2: Type: text/html, Size: 10358 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] 84+ messages in thread

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

On 4/20/16 9:17 AM, Jan Tulak wrote:
> ​I'm taking it back, one tests fails, most likely it happened when I
> removed patch 17 - xfsprogs: disable truncating of files. If I do
> "mkfs.xfs $file", it doesn't know the old size to recreate it. I'm
> working on a change for this patch to fix this issue, but I'm not
> entirely certain how to proceed. The right place to get the size
> seems to be get_topology(). I could save it into xi.dsize, but then
> libxfs_init() zeroes it.
> 
> So I think that I might rather convert the measured size do char
> *dsize and pretend that it is an user-given value. But this looks to
> me more like a hack. On the other side, any other way would require
> further changes in the code to convert the char* to int as soon as
> possible - which does not belong to this patch...
...

> So, what do you think about this?
> 
> ​ And before anyone will reply, I found that putting a
> platform_findsizes​ into libxfs_init will fix it too. Which is nice,
> especially because for block devices, the findsizes is already used
> there. So ignore the previous hack. :-)

Huh - if I take your original patchset and simply remove patch 17,
I don't get any problems with "mkfs.xfs file" for an existing file,
it seems to work fine here.  So it might be something else...

-Eric

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

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

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


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

On Wed, Apr 20, 2016 at 6:53 PM, Eric Sandeen <sandeen@sandeen.net> wrote:

> On 4/20/16 9:17 AM, Jan Tulak wrote:
> > ​I'm taking it back, one tests fails, most likely it happened when I
> > removed patch 17 - xfsprogs: disable truncating of files. If I do
> > "mkfs.xfs $file", it doesn't know the old size to recreate it. I'm
> > working on a change for this patch to fix this issue, but I'm not
> > entirely certain how to proceed. The right place to get the size
> > seems to be get_topology(). I could save it into xi.dsize, but then
> > libxfs_init() zeroes it.
> >
> > So I think that I might rather convert the measured size do char
> > *dsize and pretend that it is an user-given value. But this looks to
> > me more like a hack. On the other side, any other way would require
> > further changes in the code to convert the char* to int as soon as
> > possible - which does not belong to this patch...
> ...
>
> > So, what do you think about this?
> >
> > ​ And before anyone will reply, I found that putting a
> > platform_findsizes​ into libxfs_init will fix it too. Which is nice,
> > especially because for block devices, the findsizes is already used
> > there. So ignore the previous hack. :-)
>
> Huh - if I take your original patchset and simply remove patch 17,
>
​and revert this patch to the Dave's version.
​


> I don't get any problems with "mkfs.xfs file" for an existing file,
> it seems to work fine here.  So it might be something else...
>

​I bisected it and the issue was really caused by this patch in Dave's
version. But luckily, the fix is as simple as:

@@ -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;​

​(and dtto for log/rt variants).​

I'm going to send for review what I have, and work on the remaining issues
in the meantime.

Unless I find something else, the last thing to fix is that it changes the
size of the file on -d size=xxx, even when O_TRUNCATE is not used (that is,
no -d file is specified). Old behaviour was to keep the file size and just
don't use the entire file. This affects xfs/206 and xfs/216.

Jan


>
> -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: 6131 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] 84+ 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
@ 2016-04-21  9:39 ` Jan Tulak
  0 siblings, 0 replies; 84+ 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] 84+ messages in thread

end of thread, other threads:[~2016-04-21  9:40 UTC | newest]

Thread overview: 84+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2016-03-24 11:15 [PATCH 00/19] mkfs cleaning jtulak
2016-03-24 11:15 ` [PATCH 01/19] xfsprogs: use common code for multi-disk detection jtulak
2016-03-31 20:25   ` Eric Sandeen
2016-04-06  9:05     ` Jan Tulak
2016-03-24 11:15 ` [PATCH 02/19] mkfs: sanitise ftype parameter values jtulak
2016-03-24 16:33   ` Eric Sandeen
2016-03-29 16:11     ` Jan Tulak
2016-03-29 16:17       ` Eric Sandeen
2016-03-29 16:20         ` Jan Tulak
2016-03-29 17:14         ` Jan Tulak
2016-03-24 11:15 ` [PATCH 03/19] mkfs: Sanitise the superblock feature macros jtulak
2016-04-01  2:05   ` Eric Sandeen
2016-04-06  9:12     ` Jan Tulak
2016-04-06 21:01       ` Dave Chinner
2016-04-07 11:53         ` Jan Tulak
2016-04-07  0:12   ` Eric Sandeen
2016-04-07  1:43   ` Eric Sandeen
2016-04-07 13:09     ` Jan Tulak
2016-04-07 13:18       ` Eric Sandeen
2016-04-07 13:27         ` Jan Tulak
2016-03-24 11:15 ` [PATCH 04/19] mkfs: validate all input values jtulak
2016-04-06 23:02   ` Eric Sandeen
2016-04-07 11:15     ` Jan Tulak
2016-03-24 11:15 ` [PATCH 05/19] mkfs: factor boolean option parsing jtulak
2016-04-07  2:48   ` Eric Sandeen
2016-03-24 11:15 ` [PATCH 06/19] mkfs: validate logarithmic parameters sanely jtulak
2016-04-07  2:52   ` Eric Sandeen
2016-03-24 11:15 ` [PATCH 07/19] mkfs: structify input parameter passing jtulak
2016-04-07  3:14   ` Eric Sandeen
2016-04-07 11:43     ` Jan Tulak
2016-03-24 11:15 ` [PATCH 08/19] mkfs: getbool is redundant jtulak
2016-04-07 17:25   ` Eric Sandeen
2016-04-08 10:30     ` Jan Tulak
2016-04-08 17:41       ` Eric Sandeen
2016-03-24 11:15 ` [PATCH 09/19] mkfs: use getnum_checked for all ranged parameters jtulak
2016-04-07 19:02   ` Eric Sandeen
2016-04-08 10:47     ` Jan Tulak
2016-04-08 15:52       ` Eric Sandeen
2016-03-24 11:15 ` [PATCH 10/19] mkfs: add respecification detection to generic parsing jtulak
2016-04-07 19:06   ` Eric Sandeen
2016-03-24 11:15 ` [PATCH 11/19] mkfs: table based parsing for converted parameters jtulak
2016-04-07 19:08   ` Eric Sandeen
2016-03-24 11:15 ` [PATCH 12/19] mkfs: merge getnum jtulak
2016-04-07 19:14   ` Eric Sandeen
2016-03-24 11:15 ` [PATCH 13/19] mkfs: encode conflicts into parsing table jtulak
2016-04-07 22:40   ` Eric Sandeen
2016-03-24 11:15 ` [PATCH 14/19] mkfs: add string options to generic parsing jtulak
2016-04-07 22:49   ` Eric Sandeen
2016-03-24 11:15 ` [PATCH 15/19] mkfs: don't treat files as though they are block devices jtulak
2016-04-08  0:25   ` Eric Sandeen
2016-04-08  0:32     ` Eric Sandeen
2016-04-08 14:58     ` Jan Tulak
2016-04-08 15:50       ` Eric Sandeen
2016-04-08 15:56         ` Jan Tulak
2016-04-09  4:12       ` Eric Sandeen
2016-04-13 15:43         ` Jan Tulak
2016-04-14  9:49       ` Jan Tulak
2016-04-20  9:51         ` Jan Tulak
2016-04-20 13:17           ` Jan Tulak
2016-04-20 16:53             ` Eric Sandeen
2016-04-21  9:22               ` Jan Tulak
2016-03-24 11:15 ` [PATCH 16/19] mkfs: move spinodes crc check jtulak
2016-03-24 11:15 ` [PATCH 17/19] xfsprogs: disable truncating of files jtulak
2016-04-06 21:42   ` Eric Sandeen
2016-04-07  9:41     ` Jan Tulak
2016-04-08  0:09   ` Dave Chinner
2016-04-08 10:06     ` Jan Tulak
2016-04-08 23:08       ` Dave Chinner
2016-04-13 15:08         ` Jan Tulak
2016-04-13 16:17           ` Eric Sandeen
2016-04-13 16:23             ` Jan Tulak
2016-04-13 16:25               ` Eric Sandeen
2016-04-13 21:37             ` Dave Chinner
2016-04-14 12:31               ` Jan Tulak
2016-03-24 11:15 ` [PATCH 18/19] mkfs: unit conversions are case insensitive jtulak
2016-04-06 21:10   ` Eric Sandeen
2016-04-07 10:50     ` Jan Tulak
2016-04-08  0:41       ` Eric Sandeen
2016-04-08  1:03         ` Dave Chinner
2016-04-08  9:08           ` Jan Tulak
2016-04-08 15:51             ` Eric Sandeen
2016-03-24 11:15 ` [PATCH 19/19] mkfs: add optional 'reason' for illegal_option jtulak
2016-04-06 22:23   ` Eric Sandeen
2016-04-21  9:39 [PATCH 00/19 v2] mkfs cleaning Jan Tulak
2016-04-21  9:39 ` [PATCH 09/19] mkfs: use getnum_checked for all ranged parameters Jan Tulak

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.