All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH 00/17] mkfs: sanitise input parameters
@ 2015-06-19 11:01 Jan Ťulák
  2015-06-19 11:01 ` [PATCH 01/17] xfsprogs: use common code for multi-disk detection Jan Ťulák
                   ` (16 more replies)
  0 siblings, 17 replies; 51+ messages in thread
From: Jan Ťulák @ 2015-06-19 11:01 UTC (permalink / raw)
  To: xfs

Hi all,

I picked up this patch set Dave Chinner wrote back in 2013 to clean
mkfs a bit. It is just part of what I want to do, and still work in progress.
I updated it to the current codebase (for-next branch) and fixed issues
the original set was causing - currently, this set goes through
./check -n quick with the same result, as clean for-next branch.

Two changes against the original set are left in separate patches:
"mkfs: move spinodes crc check" is just a small cosmetic thing that doesn't
fit into the existing patches, but "mkfs fix: handling of files" is a fix
for the last patch from Dave about files. I put this fix standalone for now
to make sure the changes in it are reviewed. As I'm learning about xfs,
I could misunderstood something. :-)

Bellow is the original message from Dave:

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

Cheers,
Jan

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 Ťulák (2):
  mkfs fix: handling of files
  mkfs: move spinodes crc check

 include/Makefile    |    8 +-
 include/xfs_mkfs.h  |   73 ++
 libxfs/init.c       |    7 +
 libxfs/linux.c      |   11 +-
 man/man8/mkfs.xfs.8 |   26 +-
 mkfs/Makefile       |    2 +-
 mkfs/proto.c        |   56 +-
 mkfs/xfs_mkfs.c     | 1873 ++++++++++++++++++++++++++++++---------------------
 mkfs/xfs_mkfs.h     |   89 ---
 repair/xfs_repair.c |   45 +-
 10 files changed, 1305 insertions(+), 885 deletions(-)
 create mode 100644 include/xfs_mkfs.h
 delete mode 100644 mkfs/xfs_mkfs.h

-- 
2.1.0

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

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

* [PATCH 01/17] xfsprogs: use common code for multi-disk detection
  2015-06-19 11:01 [PATCH 00/17] mkfs: sanitise input parameters Jan Ťulák
@ 2015-06-19 11:01 ` Jan Ťulák
  2015-06-19 11:10   ` Christoph Hellwig
  2015-06-25 19:37   ` Brian Foster
  2015-06-19 11:01 ` [PATCH 02/17] mkfs: sanitise ftype parameter values Jan Ťulák
                   ` (15 subsequent siblings)
  16 siblings, 2 replies; 51+ messages in thread
From: Jan Ťulák @ 2015-06-19 11:01 UTC (permalink / raw)
  To: xfs; +Cc: Dave Chinner

From: Dave Chinner <dchinner@redhat.com>

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

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

Signed-off-by: Dave Chinner <dchinner@redhat.com>
Signed-off-by: Jan Ťulák <jtulak@redhat.com>
---
 include/Makefile    |  8 ++++-
 include/xfs_mkfs.h  | 98 +++++++++++++++++++++++++++++++++++++++++++++++++++++
 mkfs/Makefile       |  2 +-
 mkfs/xfs_mkfs.c     | 56 +++++++++++++++---------------
 mkfs/xfs_mkfs.h     | 89 ------------------------------------------------
 repair/xfs_repair.c | 45 ++++++++++++++++++++++--
 6 files changed, 178 insertions(+), 120 deletions(-)
 create mode 100644 include/xfs_mkfs.h
 delete mode 100644 mkfs/xfs_mkfs.h

diff --git a/include/Makefile b/include/Makefile
index 70e43a0..3269ec3 100644
--- a/include/Makefile
+++ b/include/Makefile
@@ -26,9 +26,15 @@ QAHFILES = libxfs.h libxlog.h \
 	xfs_inode.h \
 	xfs_log_recover.h \
 	xfs_metadump.h \
+	xfs_mkfs.h \
 	xfs_mount.h \
+	xfs_quota_defs.h \
+	xfs_sb.h \
+	xfs_shared.h \
 	xfs_trace.h \
-	xfs_trans.h
+	xfs_trans.h \
+	xfs_trans_resv.h \
+	xfs_trans_space.h
 
 HFILES = handle.h jdm.h xqm.h xfs.h
 HFILES += $(PKG_PLATFORM).h
diff --git a/include/xfs_mkfs.h b/include/xfs_mkfs.h
new file mode 100644
index 0000000..3388f6d
--- /dev/null
+++ b/include/xfs_mkfs.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_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))
+
+/*
+ * 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);
+
+#endif	/* __XFS_MKFS_H__ */
diff --git a/mkfs/Makefile b/mkfs/Makefile
index fd1f615..82326e0 100644
--- a/mkfs/Makefile
+++ b/mkfs/Makefile
@@ -8,7 +8,7 @@ include $(TOPDIR)/include/builddefs
 LTCOMMAND = mkfs.xfs
 FSTYP = fstyp
 
-HFILES = xfs_mkfs.h
+HFILES =
 CFILES = maxtrres.c proto.c xfs_mkfs.c
 
 ifeq ($(ENABLE_BLKID),yes)
diff --git a/mkfs/xfs_mkfs.c b/mkfs/xfs_mkfs.c
index 83f7749..d0de90d 100644
--- a/mkfs/xfs_mkfs.c
+++ b/mkfs/xfs_mkfs.c
@@ -24,7 +24,7 @@
 #include <disk/fstyp.h>
 #include <disk/volume.h>
 #endif
-#include "xfs_mkfs.h"
+#include <xfs/xfs_mkfs.h>
 
 /*
  * Device topology information.
@@ -688,43 +688,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 9df5f37..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);
-
-#endif	/* __XFS_MKFS_H__ */
diff --git a/repair/xfs_repair.c b/repair/xfs_repair.c
index 11a6069..7e2d7ff 100644
--- a/repair/xfs_repair.c
+++ b/repair/xfs_repair.c
@@ -19,6 +19,7 @@
 #include <xfs/libxfs.h>
 #include <xfs/libxlog.h>
 #include <sys/resource.h>
+#include <xfs/xfs_mkfs.h>
 #include "avl.h"
 #include "avl64.h"
 #include "globals.h"
@@ -526,6 +527,33 @@ _("sb realtime summary inode %" PRIu64 " %sinconsistent with calculated value %u
 
 }
 
+/*
+ * 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)
 {
@@ -644,9 +672,22 @@ 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 = glob_agcount;
+		ag_stride = min(glob_agcount, XFS_MULTIDISK_AGCOUNT / 2) - 1;
+	}
 
 	if (ag_stride) {
 		int max_threads = platform_nproc() * 8;
-- 
2.1.0

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

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

* [PATCH 02/17] mkfs: sanitise ftype parameter values.
  2015-06-19 11:01 [PATCH 00/17] mkfs: sanitise input parameters Jan Ťulák
  2015-06-19 11:01 ` [PATCH 01/17] xfsprogs: use common code for multi-disk detection Jan Ťulák
@ 2015-06-19 11:01 ` Jan Ťulák
  2015-06-25 19:37   ` Brian Foster
  2015-06-19 11:01 ` [PATCH 03/17] mkfs: Sanitise the superblock feature macros Jan Ťulák
                   ` (14 subsequent siblings)
  16 siblings, 1 reply; 51+ messages in thread
From: Jan Ťulák @ 2015-06-19 11:01 UTC (permalink / raw)
  To: xfs; +Cc: Dave Chinner

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 Ťulák <jtulak@redhat.com>
---
 mkfs/xfs_mkfs.c | 5 ++++-
 1 file changed, 4 insertions(+), 1 deletion(-)

diff --git a/mkfs/xfs_mkfs.c b/mkfs/xfs_mkfs.c
index d0de90d..1652903 100644
--- a/mkfs/xfs_mkfs.c
+++ b/mkfs/xfs_mkfs.c
@@ -1617,12 +1617,15 @@ _("cannot specify both crc and ftype\n"));
 						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.1.0

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

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

* [PATCH 03/17] mkfs: Sanitise the superblock feature macros
  2015-06-19 11:01 [PATCH 00/17] mkfs: sanitise input parameters Jan Ťulák
  2015-06-19 11:01 ` [PATCH 01/17] xfsprogs: use common code for multi-disk detection Jan Ťulák
  2015-06-19 11:01 ` [PATCH 02/17] mkfs: sanitise ftype parameter values Jan Ťulák
@ 2015-06-19 11:01 ` Jan Ťulák
  2015-06-25 19:38   ` Brian Foster
  2015-06-19 11:01 ` [PATCH 04/17] mkfs: validate all input values Jan Ťulák
                   ` (13 subsequent siblings)
  16 siblings, 1 reply; 51+ messages in thread
From: Jan Ťulák @ 2015-06-19 11:01 UTC (permalink / raw)
  To: xfs; +Cc: Dave Chinner

From: Dave Chinner <dchinner@redhat.com>

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

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

Signed-off-by: Dave Chinner <dchinner@redhat.com>
Signed-off-by: Jan Ťulák <jtulak@redhat.com>
---
 include/xfs_mkfs.h |  25 +----
 mkfs/xfs_mkfs.c    | 293 ++++++++++++++++++++++++++++++++---------------------
 2 files changed, 181 insertions(+), 137 deletions(-)

diff --git a/include/xfs_mkfs.h b/include/xfs_mkfs.h
index 3388f6d..3af9cb1 100644
--- a/include/xfs_mkfs.h
+++ b/include/xfs_mkfs.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 1652903..10276e4 100644
--- a/mkfs/xfs_mkfs.c
+++ b/mkfs/xfs_mkfs.c
@@ -903,6 +903,107 @@ 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,
@@ -914,8 +1015,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;
@@ -930,8 +1029,6 @@ main(
 	char			*dfile;
 	int			dirblocklog;
 	int			dirblocksize;
-	int			dirftype;
-	int			dirversion;
 	char			*dsize;
 	int			dsu;
 	int			dsw;
@@ -939,7 +1036,6 @@ main(
 	int			dswidth;
 	int			force_overwrite;
 	struct fsxattr		fsx;
-	int			iaflag;
 	int			ilflag;
 	int			imaxpct;
 	int			imflag;
@@ -981,7 +1077,6 @@ main(
 	int			nftype;
 	int			nsflag;
 	int			nvflag;
-	int			nci;
 	int			Nflag;
 	int			discard = 1;
 	char			*p;
@@ -1005,19 +1100,27 @@ 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,
+	};
 
 	progname = basename(argv[0]);
 	setlocale(LC_ALL, "");
 	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;
@@ -1026,26 +1129,18 @@ 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;
-	nftype = dirftype = 0;		/* 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));
@@ -1284,10 +1379,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)
+						break;
+					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')
@@ -1357,7 +1453,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')
@@ -1365,13 +1461,13 @@ 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)
+					sb_feat.spinodes = atoi(value);
+					if (sb_feat.spinodes < 0 || sb_feat.spinodes > 1)
 						illegal(value, "i spinodes");
 					break;
 				default:
@@ -1464,9 +1560,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:
@@ -1515,7 +1612,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);
@@ -1539,12 +1637,14 @@ main(
 					c = atoi(value);
 					if (c < 0 || c > 1)
 						illegal(value, "m crc");
-					crcs_enabled = c;
-					if (nftype && crcs_enabled) {
+					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')
@@ -1552,8 +1652,7 @@ _("cannot specify both crc and ftype\n"));
 					c = atoi(value);
 					if (c < 0 || c > 1)
 						illegal(value, "m finobt");
-					finobt = c;
-					finobtflag = true;
+					sb_feat.finobt = c;
 					break;
 				default:
 					unknown('m', value);
@@ -1603,12 +1702,14 @@ _("cannot specify both crc and ftype\n"));
 					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;
@@ -1620,12 +1721,12 @@ _("cannot specify both crc and ftype\n"));
 					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:
@@ -1774,7 +1875,7 @@ _("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);
@@ -1851,7 +1952,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;
 	}
 
 	/*
@@ -1859,7 +1960,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,
@@ -1869,28 +1970,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();
@@ -1898,7 +1999,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();
@@ -1912,17 +2013,17 @@ _("32 bit Project IDs always enabled on CRC enabled filesytems\n"));
 		 * tried to use crc=0,finobt=1, then issue a warning before
 		 * turning them off.
 		 */
-		if (finobt && finobtflag) {
+		if (sb_feat.finobt && sb_feat.finobtflag) {
 			fprintf(stderr,
 _("warning: finobt not supported without CRC support, disabled.\n"));
+			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) {
@@ -1972,11 +2073,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);
@@ -2106,10 +2207,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,
@@ -2424,12 +2525,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,
@@ -2441,9 +2542,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);
+				   sb_feat.log_version, lsunit);
 	ASSERT(min_logblocks);
 	min_logblocks = MAX(XFS_MIN_LOG_BLOCKS, min_logblocks);
 	if (!logsize && dblocks >= (1024*1024*1024) >> blocklog)
@@ -2521,25 +2622,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) {
 		/*
@@ -2591,14 +2675,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"
@@ -2611,13 +2687,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)
@@ -2660,17 +2739,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) {
@@ -2681,19 +2760,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);
@@ -2749,7 +2816,7 @@ _("size %s specified for log subvolume is too large, maximum is %lld blocks\n"),
 	libxfs_log_clear(mp->m_logdev_targp,
 		XFS_FSB_TO_DADDR(mp, logstart),
 		(xfs_extlen_t)XFS_FSB_TO_BB(mp, logblocks),
-		&sbp->sb_uuid, logversion, lsunit, XLOG_FMT);
+		&sbp->sb_uuid, sb_feat.log_version, lsunit, XLOG_FMT);
 
 	mp = libxfs_mount(mp, sbp, xi.ddev, xi.logdev, xi.rtdev, 0);
 	if (mp == NULL) {
@@ -2851,7 +2918,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);
 		}
@@ -2984,7 +3051,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)
 			continue;
 
 		buf = libxfs_getbuf(mp->m_ddev_targp,
-- 
2.1.0

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

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

* [PATCH 04/17] mkfs: validate all input values
  2015-06-19 11:01 [PATCH 00/17] mkfs: sanitise input parameters Jan Ťulák
                   ` (2 preceding siblings ...)
  2015-06-19 11:01 ` [PATCH 03/17] mkfs: Sanitise the superblock feature macros Jan Ťulák
@ 2015-06-19 11:01 ` Jan Ťulák
  2015-06-25 19:38   ` Brian Foster
  2015-06-19 11:01 ` [PATCH 05/17] mkfs: factor boolean option parsing Jan Ťulák
                   ` (12 subsequent siblings)
  16 siblings, 1 reply; 51+ messages in thread
From: Jan Ťulák @ 2015-06-19 11:01 UTC (permalink / raw)
  To: xfs; +Cc: Dave Chinner

From: Dave Chinner <dchinner@redhat.com>

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

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

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

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

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

Signed-off-by: Dave Chinner <dchinner@redhat.com>
Signed-off-by: Jan Ťulák <jtulak@redhat.com>
---
 include/xfs_mkfs.h  |   7 +-
 man/man8/mkfs.xfs.8 |  26 ++++++-
 mkfs/proto.c        |  36 ++++-----
 mkfs/xfs_mkfs.c     | 215 +++++++++++++++++++++++++++-------------------------
 4 files changed, 153 insertions(+), 131 deletions(-)

diff --git a/include/xfs_mkfs.h b/include/xfs_mkfs.h
index 3af9cb1..996b690 100644
--- a/include/xfs_mkfs.h
+++ b/include/xfs_mkfs.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 6260e0c..4456931 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
 XFS on Linux currently only supports pagesize or smaller blocks.
 .TP
 .BI \-m " global_metadata_options"
@@ -804,6 +818,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 45565b7..a2a61e0 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,
@@ -441,8 +430,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 = getnum(getstr(pp), 0, 0, false);
+	creds.cr_gid = getnum(getstr(pp), 0, 0, false);
 	xname.name = (uchar_t *)name;
 	xname.len = name ? strlen(name) : 0;
 	xname.type = 0;
@@ -467,7 +456,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,
@@ -491,8 +487,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) {
@@ -506,8 +502,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 10276e4..1a5e2f8 100644
--- a/mkfs/xfs_mkfs.c
+++ b/mkfs/xfs_mkfs.c
@@ -49,6 +49,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
  */
@@ -1004,6 +1007,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,
@@ -1123,8 +1148,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;
@@ -1167,7 +1192,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;
@@ -1181,8 +1206,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");
@@ -1205,8 +1230,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;
@@ -1216,14 +1240,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)
@@ -1251,13 +1277,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')
@@ -1267,13 +1289,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')
@@ -1283,8 +1301,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')
@@ -1294,13 +1314,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)
@@ -1325,7 +1341,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;
@@ -1339,8 +1355,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");
@@ -1380,7 +1396,7 @@ main(
 				case I_ALIGN:
 					if (!value || *value == '\0')
 						break;
-					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;
@@ -1396,7 +1412,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;
@@ -1407,7 +1423,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;
@@ -1423,7 +1439,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))
@@ -1441,7 +1457,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);
@@ -1450,7 +1466,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;
@@ -1458,7 +1474,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;
@@ -1488,7 +1504,9 @@ main(
 						respec('l', lopts, L_AGNUM);
 					if (ldflag)
 						conflict('l', lopts, L_AGNUM, L_DEV);
-					logagno = atoi(value);
+					logagno = getnum(value, 0, 0, false);
+					if (logagno < 0)
+						illegal(value, "l agno");
 					laflag = 1;
 					break;
 				case L_FILE:
@@ -1497,7 +1515,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)
@@ -1513,7 +1531,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;
@@ -1523,8 +1541,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:
@@ -1532,12 +1552,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:
@@ -1560,7 +1577,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;
@@ -1582,7 +1599,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;
@@ -1596,8 +1613,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");
@@ -1609,7 +1626,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
@@ -1634,7 +1651,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) {
@@ -1673,7 +1690,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;
@@ -1687,8 +1704,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");
@@ -1705,7 +1722,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");
@@ -1718,7 +1735,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) {
@@ -1764,7 +1781,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)
@@ -1808,7 +1825,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;
@@ -1825,8 +1842,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");
@@ -1882,6 +1899,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);
 
@@ -2055,7 +2081,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"),
@@ -2092,7 +2120,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"),
@@ -2114,7 +2144,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"),
@@ -2134,7 +2166,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"),
@@ -3240,28 +3274,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;
@@ -3272,17 +3289,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.1.0

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

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

* [PATCH 05/17] mkfs: factor boolean option parsing
  2015-06-19 11:01 [PATCH 00/17] mkfs: sanitise input parameters Jan Ťulák
                   ` (3 preceding siblings ...)
  2015-06-19 11:01 ` [PATCH 04/17] mkfs: validate all input values Jan Ťulák
@ 2015-06-19 11:01 ` Jan Ťulák
  2015-06-25 19:38   ` Brian Foster
  2015-06-19 11:01 ` [PATCH 06/17] mkfs: validate logarithmic parameters sanely Jan Ťulák
                   ` (11 subsequent siblings)
  16 siblings, 1 reply; 51+ messages in thread
From: Jan Ťulák @ 2015-06-19 11:01 UTC (permalink / raw)
  To: xfs; +Cc: Dave Chinner

From: Dave Chinner <dchinner@redhat.com>

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

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

Signed-off-by: Dave Chinner <dchinner@redhat.com>
Signed-off-by: Jan Ťulák <jtulak@redhat.com>
---
 mkfs/xfs_mkfs.c | 101 +++++++++++++++++++++++---------------------------------
 1 file changed, 42 insertions(+), 59 deletions(-)

diff --git a/mkfs/xfs_mkfs.c b/mkfs/xfs_mkfs.c
index 1a5e2f8..6b9e991 100644
--- a/mkfs/xfs_mkfs.c
+++ b/mkfs/xfs_mkfs.c
@@ -42,7 +42,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);
@@ -1028,6 +1028,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(
@@ -1247,11 +1262,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;
@@ -1394,12 +1406,8 @@ main(
 
 				switch (getsubopt(&p, (constpp)iopts, &value)) {
 				case I_ALIGN:
-					if (!value || *value == '\0')
-						break;
-					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')
@@ -1472,12 +1480,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')
@@ -1510,20 +1514,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)
@@ -1531,9 +1530,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:
@@ -1623,14 +1622,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);
@@ -1649,18 +1643,14 @@ 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", false);
+					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:
@@ -1731,19 +1721,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", false);
 					nftype = 1;
 					break;
 				default:
@@ -1779,11 +1765,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;
@@ -3228,8 +3211,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.1.0

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

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

* [PATCH 06/17] mkfs: validate logarithmic parameters sanely
  2015-06-19 11:01 [PATCH 00/17] mkfs: sanitise input parameters Jan Ťulák
                   ` (4 preceding siblings ...)
  2015-06-19 11:01 ` [PATCH 05/17] mkfs: factor boolean option parsing Jan Ťulák
@ 2015-06-19 11:01 ` Jan Ťulák
  2015-06-26 17:16   ` Brian Foster
  2015-06-19 11:01 ` [PATCH 07/17] mkfs: structify input parameter passing Jan Ťulák
                   ` (10 subsequent siblings)
  16 siblings, 1 reply; 51+ messages in thread
From: Jan Ťulák @ 2015-06-19 11:01 UTC (permalink / raw)
  To: xfs; +Cc: Dave Chinner

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

# 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 Ťulák <jtulak@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 6b9e991..6f0aa55 100644
--- a/mkfs/xfs_mkfs.c
+++ b/mkfs/xfs_mkfs.c
@@ -1044,6 +1044,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,
@@ -1200,16 +1221,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;
@@ -1346,16 +1367,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;
@@ -1420,9 +1441,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;
@@ -1591,16 +1614,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;
@@ -1673,16 +1696,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;
@@ -1801,16 +1824,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.1.0

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

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

* [PATCH 07/17] mkfs: structify input parameter passing
  2015-06-19 11:01 [PATCH 00/17] mkfs: sanitise input parameters Jan Ťulák
                   ` (5 preceding siblings ...)
  2015-06-19 11:01 ` [PATCH 06/17] mkfs: validate logarithmic parameters sanely Jan Ťulák
@ 2015-06-19 11:01 ` Jan Ťulák
  2015-06-26 17:16   ` Brian Foster
  2015-06-19 11:01 ` [PATCH 08/17] mkfs: getbool is redundant Jan Ťulák
                   ` (9 subsequent siblings)
  16 siblings, 1 reply; 51+ messages in thread
From: Jan Ťulák @ 2015-06-19 11:01 UTC (permalink / raw)
  To: xfs; +Cc: Dave Chinner

From: Dave Chinner <dchinner@redhat.com>

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

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

Signed-off-by: Dave Chinner <dchinner@redhat.com>
Signed-off-by: Jan Ťulák <jtulak@redhat.com>
---
 mkfs/xfs_mkfs.c | 602 ++++++++++++++++++++++++++++++++++++--------------------
 1 file changed, 392 insertions(+), 210 deletions(-)

diff --git a/mkfs/xfs_mkfs.c b/mkfs/xfs_mkfs.c
index 6f0aa55..d3d1e11 100644
--- a/mkfs/xfs_mkfs.c
+++ b/mkfs/xfs_mkfs.c
@@ -52,145 +52,322 @@ static int  ispow2(unsigned int i);
 static long long cvtnum(unsigned int blocksize,
 			unsigned int sectorsize, const char *s);
 
-/*
- * option tables for getsubopt calls
- */
-char *bopts[] = {
+#define MAX_SUBOPTS	16
+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];
+};
+
+const 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[] = {
+const 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[] = {
+
+const 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",
 #define I_SPINODES	7
 	"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,
+		},
+	},
 };
 
-char	*lopts[] = {
+const 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[] = {
+const 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[] = {
+const 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[] = {
+const 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[] = {
+const struct opt_params mopts = {
+	.name = 'm',
+	.subopts = {
 #define	M_CRC		0
-	"crc",
+		"crc",
 #define M_FINOBT	1
-	"finobt",
-	NULL
+		"finobt",
+		NULL
+	},
+	.subopt_params = {
+		{ .index = M_CRC,
+		},
+	},
 };
 
 #define TERABYTES(count, blog)	((__uint64_t)(count) << (40 - (blog)))
@@ -1044,24 +1221,33 @@ getbool(
 	return c ? true : false;
 }
 
+static __attribute__((noreturn)) void
+illegal_option(
+	const char	*value,
+	const 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)
+	const 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);
 
 	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;
 }
 
@@ -1217,30 +1403,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);
@@ -1258,14 +1443,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");
@@ -1273,9 +1460,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)
@@ -1290,25 +1477,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)
@@ -1316,11 +1503,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)
@@ -1328,11 +1515,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);
@@ -1341,11 +1528,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)
@@ -1353,40 +1540,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);
@@ -1403,14 +1587,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;
@@ -1423,37 +1607,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");
@@ -1461,14 +1642,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 <
@@ -1479,15 +1660,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");
@@ -1496,7 +1677,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");
@@ -1521,16 +1702,18 @@ main(
 		case 'l':
 			p = optarg;
 			while (*p != '\0') {
+				char	**subopts = (char **)lopts.subopts;
 				char	*value;
 
-				switch (getsubopt(&p, (constpp)lopts, &value)) {
+				switch (getsubopt(&p, (constpp)subopts,
+						  &value)) {
 				case L_AGNUM:
 					if (!value || *value == '\0')
-						reqval('l', lopts, L_AGNUM);
+						reqval('l', subopts, L_AGNUM);
 					if (laflag)
-						respec('l', lopts, L_AGNUM);
+						respec('l', subopts, L_AGNUM);
 					if (ldflag)
-						conflict('l', lopts, L_AGNUM, L_DEV);
+						conflict('l', subopts, L_AGNUM, L_DEV);
 					logagno = getnum(value, 0, 0, false);
 					if (logagno < 0)
 						illegal(value, "l agno");
@@ -1538,7 +1721,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);
@@ -1547,12 +1730,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);
@@ -1560,9 +1743,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)
@@ -1571,9 +1754,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");
@@ -1582,13 +1765,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;
@@ -1596,9 +1779,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");
@@ -1607,33 +1790,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);
@@ -1662,9 +1842,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", false);
@@ -1678,7 +1860,7 @@ _("cannot specify both -m crc=1 and -n ftype\n"));
 					break;
 				case M_FINOBT:
 					if (!value || *value == '\0')
-						reqval('m', mopts, M_CRC);
+						reqval('m', (char**)mopts.subopts, M_CRC);
 					c = atoi(value);
 					if (c < 0 || c > 1)
 						illegal(value, "m finobt");
@@ -1692,30 +1874,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);
@@ -1728,9 +1909,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;
@@ -1745,7 +1926,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"));
@@ -1777,14 +1958,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:
@@ -1796,16 +1979,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:
@@ -1819,21 +2002,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;
@@ -1842,11 +2024,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.1.0

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

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

* [PATCH 08/17] mkfs: getbool is redundant
  2015-06-19 11:01 [PATCH 00/17] mkfs: sanitise input parameters Jan Ťulák
                   ` (6 preceding siblings ...)
  2015-06-19 11:01 ` [PATCH 07/17] mkfs: structify input parameter passing Jan Ťulák
@ 2015-06-19 11:01 ` Jan Ťulák
  2015-06-26 17:17   ` Brian Foster
  2015-06-19 11:01 ` [PATCH 09/17] mkfs: use getnum_checked for all ranged parameters Jan Ťulák
                   ` (8 subsequent siblings)
  16 siblings, 1 reply; 51+ messages in thread
From: Jan Ťulák @ 2015-06-19 11:01 UTC (permalink / raw)
  To: xfs; +Cc: Dave Chinner

From: Dave Chinner <dchinner@redhat.com>

getbool() can be replaced with getnum_checked with appropriate
min/max values set for the boolean variables.

Signed-off-by: Dave Chinner <dchinner@redhat.com>
Signed-off-by: Jan Ťulák <jtulak@redhat.com>
---
 mkfs/xfs_mkfs.c | 147 ++++++++++++++++++++++++++++++++++++++++----------------
 1 file changed, 106 insertions(+), 41 deletions(-)

diff --git a/mkfs/xfs_mkfs.c b/mkfs/xfs_mkfs.c
index d3d1e11..3803779 100644
--- a/mkfs/xfs_mkfs.c
+++ b/mkfs/xfs_mkfs.c
@@ -53,6 +53,7 @@ static long long cvtnum(unsigned int blocksize,
 			unsigned int sectorsize, const char *s);
 
 #define MAX_SUBOPTS	16
+#define SUBOPT_NEEDS_VAL	(-1LL)
 struct opt_params {
 	const char	name;
 	const char	*subopts[MAX_SUBOPTS];
@@ -60,6 +61,7 @@ struct opt_params {
 		int		index;
 		long long	minval;
 		long long	maxval;
+		long long	defaultval;
 	}		subopt_params[MAX_SUBOPTS];
 };
 
@@ -76,10 +78,12 @@ const 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,
 		},
 	},
 };
@@ -121,38 +125,55 @@ const 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,
+		  .defaultval = SUBOPT_NEEDS_VAL,
 		},
 		{ .index = D_RTINHERIT,
+		  .defaultval = SUBOPT_NEEDS_VAL,
 		},
 		{ .index = D_PROJINHERIT,
+		  .defaultval = SUBOPT_NEEDS_VAL,
 		},
 		{ .index = D_EXTSZINHERIT,
+		  .defaultval = SUBOPT_NEEDS_VAL,
 		},
 	},
 };
@@ -181,20 +202,31 @@ const 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,
 		},
 	},
 };
@@ -230,32 +262,50 @@ const 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,
 		},
 	},
 };
@@ -277,14 +327,20 @@ const 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 = 0,
 		},
 	},
 };
@@ -308,16 +364,22 @@ const 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,
+		  .defaultval = SUBOPT_NEEDS_VAL,
 		},
 		{ .index = R_NAME,
+		  .defaultval = SUBOPT_NEEDS_VAL,
 		},
 		{ .index = R_NOALIGN,
+		  .defaultval = SUBOPT_NEEDS_VAL,
 		},
 	},
 };
@@ -339,18 +401,22 @@ const 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,
 		},
 	},
 };
@@ -366,6 +432,9 @@ const struct opt_params mopts = {
 	},
 	.subopt_params = {
 		{ .index = M_CRC,
+		  .minval = 0,
+		  .maxval = 1,
+		  .defaultval = 0,
 		},
 	},
 };
@@ -1205,22 +1274,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,
@@ -1235,18 +1288,28 @@ illegal_option(
 
 static int
 getnum_checked(
-	const char	*str,
+	const char		*str,
 	const struct opt_params	*opts,
-	int		index)
+	int			index)
 {
-	long long	c;
+	const struct subopt_param *sp = &opts->subopt_params[index];
+	long long		c;
 
-	if (!str || *str == '\0')
+	if (sp->index != index) {
+		fprintf(stderr,
+	("Developer screwed up option parsing (%d/%d)! Please report!\n"),
+			sp->index, index);
 		reqval(opts->name, (char **)opts->subopts, index);
+	}
+
+	if (!str || *str == '\0') {
+		if (sp->defaultval == SUBOPT_NEEDS_VAL)
+			reqval(opts->name, (char **)opts->subopts, index);
+		return sp->defaultval;
+	}
 
 	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;
 }
@@ -1470,8 +1533,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;
@@ -1613,8 +1676,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)
@@ -1684,8 +1747,9 @@ 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')
@@ -1723,8 +1787,8 @@ main(
 					if (loginternal)
 						conflict('l', subopts, L_INTERNAL,
 							 L_FILE);
-					xi.lisfile = getbool(value, "l file",
-							     true);
+					xi.lisfile = getnum_checked(value,
+								&lopts, L_FILE);
 					if (xi.lisfile)
 						xi.lcreat = 1;
 					break;
@@ -1737,8 +1801,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:
@@ -1825,9 +1889,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);
@@ -1848,8 +1912,9 @@ main(
 				switch (getsubopt(&p, (constpp)subopts,
 						  &value)) {
 				case M_CRC:
-					sb_feat.crcs_enabled = getbool(
-							value, "m crc", false);
+					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"));
@@ -1932,8 +1997,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", false);
+					sb_feat.dirftype = getnum_checked(value,
+								&nopts, N_FTYPE);
 					nftype = 1;
 					break;
 				default:
@@ -1971,8 +2036,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;
-- 
2.1.0

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

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

* [PATCH 09/17] mkfs: use getnum_checked for all ranged parameters
  2015-06-19 11:01 [PATCH 00/17] mkfs: sanitise input parameters Jan Ťulák
                   ` (7 preceding siblings ...)
  2015-06-19 11:01 ` [PATCH 08/17] mkfs: getbool is redundant Jan Ťulák
@ 2015-06-19 11:01 ` Jan Ťulák
  2015-06-26 17:17   ` Brian Foster
  2015-06-19 11:01 ` [PATCH 10/17] mkfs: add respecification detection to generic parsing Jan Ťulák
                   ` (7 subsequent siblings)
  16 siblings, 1 reply; 51+ messages in thread
From: Jan Ťulák @ 2015-06-19 11:01 UTC (permalink / raw)
  To: xfs; +Cc: Dave Chinner

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 Ťulák <jtulak@redhat.com>
---
 include/xfs_mkfs.h |   5 +-
 mkfs/xfs_mkfs.c    | 152 +++++++++++++++++++++++++++--------------------------
 2 files changed, 81 insertions(+), 76 deletions(-)

diff --git a/include/xfs_mkfs.h b/include/xfs_mkfs.h
index 996b690..f5639b0 100644
--- a/include/xfs_mkfs.h
+++ b/include/xfs_mkfs.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 3803779..332c491 100644
--- a/mkfs/xfs_mkfs.c
+++ b/mkfs/xfs_mkfs.c
@@ -125,6 +125,8 @@ const struct opt_params dopts = {
 	},
 	.subopt_params = {
 		{ .index = D_AGCOUNT,
+		  .minval = 1,
+		  .maxval = XFS_MAX_AGNUMBER,
 		  .defaultval = SUBOPT_NEEDS_VAL,
 		},
 		{ .index = D_FILE,
@@ -139,18 +141,26 @@ const 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,
@@ -164,15 +174,23 @@ const struct opt_params dopts = {
 		  .defaultval = SUBOPT_NEEDS_VAL,
 		},
 		{ .index = D_NOALIGN,
-		  .defaultval = SUBOPT_NEEDS_VAL,
+		  .minval = 1,
+		  .maxval = 1,
+		  .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,
 		},
 	},
@@ -212,15 +230,23 @@ const 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,
@@ -262,6 +288,8 @@ const struct opt_params lopts = {
 	},
 	.subopt_params = {
 		{ .index = L_AGNUM,
+		  .minval = 0,
+		  .maxval = UINT_MAX,
 		  .defaultval = SUBOPT_NEEDS_VAL,
 		},
 		{ .index = L_INTERNAL,
@@ -273,9 +301,13 @@ const 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,
@@ -335,6 +367,8 @@ const struct opt_params nopts = {
 		  .defaultval = SUBOPT_NEEDS_VAL,
 		},
 		{ .index = N_VERSION,
+		  .minval = 2,
+		  .maxval = 2,
 		  .defaultval = SUBOPT_NEEDS_VAL,
 		},
 		{ .index = N_FTYPE,
@@ -1512,13 +1546,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:
@@ -1553,28 +1585,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')
@@ -1590,16 +1616,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:
 					if (dsu)
@@ -1645,21 +1668,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:
@@ -1694,18 +1718,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);
@@ -1714,16 +1733,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);
@@ -1732,19 +1748,17 @@ 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 =
@@ -1772,15 +1786,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 (logagno < 0)
-						illegal(value, "l agno");
+					logagno = getnum_checked(value, &lopts,
+								 L_AGNUM);
 					laflag = 1;
 					break;
 				case L_FILE:
@@ -1817,13 +1828,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:
@@ -1842,14 +1850,11 @@ 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:
@@ -1981,11 +1986,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.1.0

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

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

* [PATCH 10/17] mkfs: add respecification detection to generic parsing
  2015-06-19 11:01 [PATCH 00/17] mkfs: sanitise input parameters Jan Ťulák
                   ` (8 preceding siblings ...)
  2015-06-19 11:01 ` [PATCH 09/17] mkfs: use getnum_checked for all ranged parameters Jan Ťulák
@ 2015-06-19 11:01 ` Jan Ťulák
  2015-06-26 17:17   ` Brian Foster
  2015-06-19 11:02 ` [PATCH 11/17] mkfs: table based parsing for converted parameters Jan Ťulák
                   ` (6 subsequent siblings)
  16 siblings, 1 reply; 51+ messages in thread
From: Jan Ťulák @ 2015-06-19 11:01 UTC (permalink / raw)
  To: xfs; +Cc: Dave Chinner

From: Dave Chinner <dchinner@redhat.com>

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

Signed-off-by: Dave Chinner <dchinner@redhat.com>
Signed-off-by: Jan Ťulák <jtulak@redhat.com>
---
 mkfs/xfs_mkfs.c | 68 +++++++++++++++------------------------------------------
 1 file changed, 18 insertions(+), 50 deletions(-)

diff --git a/mkfs/xfs_mkfs.c b/mkfs/xfs_mkfs.c
index 332c491..0bd8998 100644
--- a/mkfs/xfs_mkfs.c
+++ b/mkfs/xfs_mkfs.c
@@ -57,15 +57,17 @@ 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;
 	}		subopt_params[MAX_SUBOPTS];
 };
 
-const struct opt_params bopts = {
+struct opt_params bopts = {
 	.name = 'b',
 	.subopts = {
 #define	B_LOG		0
@@ -88,7 +90,7 @@ const struct opt_params bopts = {
 	},
 };
 
-const struct opt_params dopts = {
+struct opt_params dopts = {
 	.name = 'd',
 	.subopts = {
 #define	D_AGCOUNT	0
@@ -197,7 +199,7 @@ const struct opt_params dopts = {
 };
 
 
-const struct opt_params iopts = {
+struct opt_params iopts = {
 	.name = 'i',
 	.subopts = {
 #define	I_ALIGN		0
@@ -257,7 +259,7 @@ const struct opt_params iopts = {
 	},
 };
 
-const struct opt_params lopts = {
+struct opt_params lopts = {
 	.name = 'l',
 	.subopts = {
 #define	L_AGNUM		0
@@ -342,7 +344,7 @@ const struct opt_params lopts = {
 	},
 };
 
-const struct opt_params nopts = {
+struct opt_params nopts = {
 	.name = 'n',
 	.subopts = {
 #define	N_LOG		0
@@ -379,7 +381,7 @@ const struct opt_params nopts = {
 	},
 };
 
-const struct opt_params ropts = {
+struct opt_params ropts = {
 	.name = 'r',
 	.subopts = {
 #define	R_EXTSIZE	0
@@ -418,7 +420,7 @@ const struct opt_params ropts = {
 	},
 };
 
-const struct opt_params sopts = {
+struct opt_params sopts = {
 	.name = 's',
 	.subopts = {
 #define	S_LOG		0
@@ -455,7 +457,7 @@ const struct opt_params sopts = {
 	},
 };
 
-const struct opt_params mopts = {
+struct opt_params mopts = {
 	.name = 'm',
 	.subopts = {
 #define	M_CRC		0
@@ -1192,7 +1194,6 @@ struct sb_feat_args {
 	int	dir_version;
 	int	spinodes;
 	int	finobt;
-	bool	finobtflag;
 	bool	inode_align;
 	bool	nci;
 	bool	lazy_sb_counters;
@@ -1323,10 +1324,10 @@ illegal_option(
 static int
 getnum_checked(
 	const char		*str,
-	const struct opt_params	*opts,
+	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) {
@@ -1336,6 +1337,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);
@@ -1446,7 +1452,6 @@ main(
 	struct fs_topology	ft;
 	struct sb_feat_args	sb_feat = {
 		.finobt = 1,
-		.finobtflag = false,
 		.spinodes = 0,
 		.log_version = 2,
 		.attr_version = 2,
@@ -1506,8 +1511,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);
@@ -1546,9 +1549,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;
@@ -1585,8 +1585,6 @@ main(
 					dsize = value;
 					break;
 				case D_SUNIT:
-					if (dsunit)
-						respec('d', subopts, D_SUNIT);
 					if (nodsflag)
 						conflict('d', subopts, D_NOALIGN,
 							 D_SUNIT);
@@ -1594,8 +1592,6 @@ main(
 								 D_SUNIT);
 					break;
 				case D_SWIDTH:
-					if (dswidth)
-						respec('d', subopts, D_SWIDTH);
 					if (nodsflag)
 						conflict('d', subopts, D_NOALIGN,
 							 D_SWIDTH);
@@ -1616,8 +1612,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);
@@ -1640,8 +1634,6 @@ main(
 					nodsflag = 1;
 					break;
 				case D_SECTLOG:
-					if (slflag)
-						respec('d', subopts, D_SECTLOG);
 					if (ssflag)
 						conflict('d', subopts, D_SECTSIZE,
 							 D_SECTLOG);
@@ -1704,8 +1696,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);
@@ -1718,8 +1708,6 @@ main(
 					ilflag = 1;
 					break;
 				case I_MAXPCT:
-					if (imflag)
-						respec('i', subopts, I_MAXPCT);
 					imaxpct = getnum_checked(value, &iopts,
 								 I_MAXPCT);
 					imflag = 1;
@@ -1728,8 +1716,6 @@ main(
 					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);
@@ -1746,8 +1732,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))
@@ -1786,8 +1770,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,
@@ -1809,8 +1791,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);
@@ -1828,8 +1808,6 @@ main(
 					lsuflag = 1;
 					break;
 				case L_SUNIT:
-					if (lsunit)
-						respec('l', subopts, L_SUNIT);
 					lsunit = getnum_checked(value, &lopts,
 								 L_SUNIT);
 					lsunitflag = 1;
@@ -1850,8 +1828,6 @@ 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);
@@ -1866,8 +1842,6 @@ main(
 					lsflag = 1;
 					break;
 				case L_SECTLOG:
-					if (lslflag)
-						respec('l', subopts, L_SECTLOG);
 					if (lssflag)
 						conflict('l', subopts, L_SECTSIZE,
 							 L_SECTLOG);
@@ -1950,8 +1924,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);
@@ -1994,8 +1966,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"));
@@ -2078,8 +2048,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);
@@ -2296,7 +2264,7 @@ _("32 bit Project IDs always enabled on CRC enabled filesytems\n"));
 		 * tried to use crc=0,finobt=1, then issue a warning before
 		 * turning them off.
 		 */
-		if (sb_feat.finobt && sb_feat.finobtflag) {
+		if (sb_feat.finobt && mopts.subopt_params[M_FINOBT].seen) {
 			fprintf(stderr,
 _("warning: finobt not supported without CRC support, disabled.\n"));
 			sb_feat.finobt = 0;
-- 
2.1.0

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

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

* [PATCH 11/17] mkfs: table based parsing for converted parameters
  2015-06-19 11:01 [PATCH 00/17] mkfs: sanitise input parameters Jan Ťulák
                   ` (9 preceding siblings ...)
  2015-06-19 11:01 ` [PATCH 10/17] mkfs: add respecification detection to generic parsing Jan Ťulák
@ 2015-06-19 11:02 ` Jan Ťulák
  2015-06-26 17:17   ` Brian Foster
  2015-06-19 11:02 ` [PATCH 12/17] mkfs: merge getnum Jan Ťulák
                   ` (5 subsequent siblings)
  16 siblings, 1 reply; 51+ messages in thread
From: Jan Ťulák @ 2015-06-19 11:02 UTC (permalink / raw)
  To: xfs; +Cc: Dave Chinner

From: Dave Chinner <dchinner@redhat.com>

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

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

Signed-off-by: Dave Chinner <dchinner@redhat.com>
Signed-off-by: Jan Ťulák <jtulak@redhat.com>
---
 mkfs/xfs_mkfs.c | 171 ++++++++++++++++++++++----------------------------------
 1 file changed, 68 insertions(+), 103 deletions(-)

diff --git a/mkfs/xfs_mkfs.c b/mkfs/xfs_mkfs.c
index 0bd8998..4fc1f34 100644
--- a/mkfs/xfs_mkfs.c
+++ b/mkfs/xfs_mkfs.c
@@ -52,6 +52,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)
 struct opt_params {
@@ -61,6 +68,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;
@@ -83,6 +92,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,
@@ -140,6 +151,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,
@@ -153,11 +167,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,
@@ -171,6 +189,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,
@@ -237,11 +257,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,
@@ -300,6 +322,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,
@@ -313,6 +338,9 @@ struct opt_params lopts = {
 		  .defaultval = SUBOPT_NEEDS_VAL,
 		},
 		{ .index = L_SU,
+		  .convert = true,
+		  .minval = XLOG_MIN_RECORD_BSIZE,
+		  .maxval = XLOG_MAX_RECORD_BSIZE,
 		  .defaultval = SUBOPT_NEEDS_VAL,
 		},
 		{ .index = L_DEV,
@@ -324,6 +352,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,
@@ -364,6 +394,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,
@@ -400,9 +432,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,
@@ -445,11 +483,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,
@@ -1291,15 +1333,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)
@@ -1348,9 +1390,11 @@ getnum_checked(
 		return sp->defaultval;
 	}
 
-	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;
 }
 
@@ -1368,7 +1412,6 @@ main(
 	struct xfs_btree_block	*block;
 	int			blflag;
 	int			blocklog;
-	unsigned int		blocksize;
 	int			bsflag;
 	int			bsize;
 	xfs_buf_t		*buf;
@@ -1441,7 +1484,6 @@ main(
 	char			*rtsize;
 	xfs_sb_t		*sbp;
 	int			sectorlog;
-	unsigned int		sectorsize;
 	__uint64_t		sector_mask;
 	int			slflag;
 	int			ssflag;
@@ -1520,18 +1562,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;
@@ -1554,14 +1589,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:
@@ -1599,17 +1628,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)
@@ -1643,18 +1666,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;
@@ -1721,8 +1737,6 @@ main(
 							 I_PERBLOCK);
 					inopblock = getnum_checked(value, &iopts,
 								   I_PERBLOCK);
-					if (!ispow2(inopblock))
-						illegal(value, "i perblock");
 					ipflag = 1;
 					break;
 				case I_SIZE:
@@ -1734,8 +1748,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;
@@ -1797,14 +1809,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:
@@ -1851,18 +1857,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;
@@ -1933,18 +1932,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;
@@ -2060,18 +2052,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);
@@ -2306,9 +2291,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"),
@@ -2345,9 +2328,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"),
@@ -2369,9 +2350,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"),
@@ -2391,27 +2370,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.1.0

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

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

* [PATCH 12/17] mkfs: merge getnum
  2015-06-19 11:01 [PATCH 00/17] mkfs: sanitise input parameters Jan Ťulák
                   ` (10 preceding siblings ...)
  2015-06-19 11:02 ` [PATCH 11/17] mkfs: table based parsing for converted parameters Jan Ťulák
@ 2015-06-19 11:02 ` Jan Ťulák
  2015-06-26 17:17   ` Brian Foster
  2015-06-19 11:02 ` [PATCH 13/17] mkfs: encode conflicts into parsing table Jan Ťulák
                   ` (4 subsequent siblings)
  16 siblings, 1 reply; 51+ messages in thread
From: Jan Ťulák @ 2015-06-19 11:02 UTC (permalink / raw)
  To: xfs; +Cc: Dave Chinner

From: Dave Chinner <dchinner@redhat.com>

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

Signed-off-by: Dave Chinner <dchinner@redhat.com>
Signed-off-by: Jan Ťulák <jtulak@redhat.com>
---
 include/xfs_mkfs.h |   4 +-
 mkfs/proto.c       |  20 ++++++
 mkfs/xfs_mkfs.c    | 202 ++++++++++++++++++++++++-----------------------------
 3 files changed, 113 insertions(+), 113 deletions(-)

diff --git a/include/xfs_mkfs.h b/include/xfs_mkfs.h
index f5639b0..a4312e1 100644
--- a/include/xfs_mkfs.h
+++ b/include/xfs_mkfs.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 a2a61e0..1e763a0 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 4fc1f34..e52fd4e 100644
--- a/mkfs/xfs_mkfs.c
+++ b/mkfs/xfs_mkfs.c
@@ -49,9 +49,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.
@@ -1330,27 +1327,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,
@@ -1363,8 +1339,8 @@ illegal_option(
 	usage();
 }
 
-static int
-getnum_checked(
+static long long
+getnum(
 	const char		*str,
 	struct opt_params	*opts,
 	int			index)
@@ -1384,13 +1360,32 @@ 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);
 		return sp->defaultval;
 	}
 
-	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		*sp;
+
+		c = strtoll(str, &sp, 0);
+		if (c == 0 && sp == str)
+			illegal_option(str, opts, index);
+		if (*sp != '\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))
@@ -1556,8 +1551,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;
@@ -1565,8 +1559,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;
@@ -1584,18 +1578,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;
@@ -1617,29 +1610,26 @@ 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:
 					if (dsu)
@@ -1660,8 +1650,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;
@@ -1669,28 +1659,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;
@@ -1708,8 +1697,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)
@@ -1718,14 +1707,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:
@@ -1735,8 +1723,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:
@@ -1746,20 +1734,18 @@ 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);
+						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:
 					if (!value || *value == '\0')
@@ -1784,16 +1770,15 @@ 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:
 					if (loginternal)
 						conflict('l', subopts, L_INTERNAL,
 							 L_FILE);
-					xi.lisfile = getnum_checked(value,
-								&lopts, L_FILE);
+					xi.lisfile = getnum(value, &lopts,
+							    L_FILE);
 					if (xi.lisfile)
 						xi.lcreat = 1;
 					break;
@@ -1804,18 +1789,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:
@@ -1835,8 +1818,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:
@@ -1851,8 +1833,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;
@@ -1860,15 +1842,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:
@@ -1891,8 +1873,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"));
@@ -1926,8 +1907,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;
@@ -1935,8 +1916,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;
@@ -1951,9 +1932,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;
@@ -1963,8 +1943,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:
@@ -2002,8 +1982,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;
@@ -2043,8 +2023,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;
@@ -2055,8 +2035,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);
@@ -2291,7 +2271,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"),
@@ -2328,7 +2308,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"),
@@ -2350,7 +2330,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"),
@@ -2370,7 +2350,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"),
@@ -3466,8 +3446,8 @@ unknown(
 
 long long
 cvtnum(
-	unsigned int	blocksize,
-	unsigned int	sectorsize,
+	unsigned int	blksize,
+	unsigned int	sectsize,
 	const char	*s)
 {
 	long long	i;
@@ -3480,9 +3460,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.1.0

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

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

* [PATCH 13/17] mkfs: encode conflicts into parsing table
  2015-06-19 11:01 [PATCH 00/17] mkfs: sanitise input parameters Jan Ťulák
                   ` (11 preceding siblings ...)
  2015-06-19 11:02 ` [PATCH 12/17] mkfs: merge getnum Jan Ťulák
@ 2015-06-19 11:02 ` Jan Ťulák
  2015-06-26 17:17   ` Brian Foster
  2015-06-19 11:02 ` [PATCH 14/17] mkfs: add string options to generic parsing Jan Ťulák
                   ` (3 subsequent siblings)
  16 siblings, 1 reply; 51+ messages in thread
From: Jan Ťulák @ 2015-06-19 11:02 UTC (permalink / raw)
  To: xfs; +Cc: Dave Chinner

From: Dave Chinner <dchinner@redhat.com>

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

Signed-off-by: Dave Chinner <dchinner@redhat.com>
Signed-off-by: Jan Ťulák <jtulak@redhat.com>
---
 mkfs/xfs_mkfs.c | 248 ++++++++++++++++++++++++++++----------------------------
 1 file changed, 125 insertions(+), 123 deletions(-)

diff --git a/mkfs/xfs_mkfs.c b/mkfs/xfs_mkfs.c
index e52fd4e..1d80188 100644
--- a/mkfs/xfs_mkfs.c
+++ b/mkfs/xfs_mkfs.c
@@ -58,6 +58,9 @@ unsigned int		sectorsize;
 
 #define MAX_SUBOPTS	16
 #define SUBOPT_NEEDS_VAL	(-1LL)
+
+#define MAX_CONFLICTS	8
+#define LAST_CONFLICT	(-1)
 struct opt_params {
 	const char	name;
 	const char	*subopts[MAX_SUBOPTS];
@@ -67,6 +70,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;
@@ -84,6 +88,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,
@@ -91,6 +97,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,
@@ -135,57 +143,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,
@@ -193,21 +228,29 @@ struct opt_params dopts = {
 		  .defaultval = SUBOPT_NEEDS_VAL,
 		},
 		{ .index = D_NOALIGN,
+		  .conflicts = { D_SU,
+				 D_SW,
+				 D_SUNIT,
+				 D_SWIDTH,
+				 LAST_CONFLICT },
 		  .minval = 1,
 		  .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,
@@ -239,38 +282,51 @@ 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,
@@ -309,46 +365,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 = XLOG_MAX_RECORD_BSIZE,
 		  .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,
@@ -356,14 +430,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,
@@ -386,11 +466,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,
@@ -398,11 +482,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 = 0,
@@ -429,27 +515,33 @@ 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,
+		  .conflicts = { LAST_CONFLICT },
 		  .defaultval = SUBOPT_NEEDS_VAL,
 		},
 		{ .index = R_NAME,
+		  .conflicts = { LAST_CONFLICT },
 		  .defaultval = SUBOPT_NEEDS_VAL,
 		},
 		{ .index = R_NOALIGN,
+		  .conflicts = { LAST_CONFLICT },
 		  .defaultval = SUBOPT_NEEDS_VAL,
 		},
 	},
@@ -470,16 +562,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,
@@ -487,6 +588,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,
@@ -507,6 +611,7 @@ struct opt_params mopts = {
 	},
 	.subopt_params = {
 		{ .index = M_CRC,
+		  .conflicts = { LAST_CONFLICT },
 		  .minval = 0,
 		  .maxval = 1,
 		  .defaultval = 0,
@@ -550,30 +655,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 "
@@ -601,24 +690,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);
-	}
 }
 
 #ifdef ENABLE_BLKID
@@ -1360,6 +1433,16 @@ 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)
@@ -1548,17 +1631,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);
@@ -1607,58 +1684,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:
-					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(value, &dopts,
+							  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 =
@@ -1701,12 +1749,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;
@@ -1717,23 +1759,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;
@@ -1768,27 +1798,16 @@ 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;
 				case L_FILE:
-					if (loginternal)
-						conflict('l', subopts, L_INTERNAL,
-							 L_FILE);
 					xi.lisfile = getnum(value, &lopts,
 							    L_FILE);
 					if (xi.lisfile)
 						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;
@@ -1830,18 +1849,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 =
@@ -1904,18 +1917,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 =
@@ -2020,7 +2027,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,
@@ -2032,7 +2039,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,
@@ -2257,11 +2264,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.1.0

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

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

* [PATCH 14/17] mkfs: add string options to generic parsing
  2015-06-19 11:01 [PATCH 00/17] mkfs: sanitise input parameters Jan Ťulák
                   ` (12 preceding siblings ...)
  2015-06-19 11:02 ` [PATCH 13/17] mkfs: encode conflicts into parsing table Jan Ťulák
@ 2015-06-19 11:02 ` Jan Ťulák
  2015-06-26 19:32   ` Brian Foster
  2015-06-19 11:02 ` [PATCH 15/17] mkfs: don't treat files as though they are block devices Jan Ťulák
                   ` (2 subsequent siblings)
  16 siblings, 1 reply; 51+ messages in thread
From: Jan Ťulák @ 2015-06-19 11:02 UTC (permalink / raw)
  To: xfs; +Cc: Dave Chinner

From: Dave Chinner <dchinner@redhat.com>

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

Signed-off-by: Dave Chinner <dchinner@redhat.com>
Signed-off-by: Jan Ťulák <jtulak@redhat.com>
---
 mkfs/xfs_mkfs.c | 127 +++++++++++++++++++++++++++++++-------------------------
 1 file changed, 70 insertions(+), 57 deletions(-)

diff --git a/mkfs/xfs_mkfs.c b/mkfs/xfs_mkfs.c
index 1d80188..6bfa73c 100644
--- a/mkfs/xfs_mkfs.c
+++ b/mkfs/xfs_mkfs.c
@@ -68,6 +68,7 @@ struct opt_params {
 	struct subopt_param {
 		int		index;
 		bool		seen;
+		bool		str_seen;
 		bool		convert;
 		bool		is_power_2;
 		int		conflicts[MAX_CONFLICTS];
@@ -1412,14 +1413,15 @@ illegal_option(
 	usage();
 }
 
-static long long
-getnum(
+static void
+check_opt(
 	const char		*str,
 	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,
@@ -1428,21 +1430,46 @@ 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(str, opts, index, false);
 	/* empty strings might just return a default value */
 	if (!str || *str == '\0') {
 		if (sp->defaultval == SUBOPT_NEEDS_VAL)
@@ -1476,6 +1503,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(str, 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,
@@ -1670,18 +1717,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);
@@ -1822,18 +1861,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 =
@@ -1841,12 +1872,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,
@@ -1930,10 +1956,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;
@@ -1982,11 +2005,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,
@@ -1996,18 +2016,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 = 1;
-- 
2.1.0

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

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

* [PATCH 15/17] mkfs: don't treat files as though they are block devices
  2015-06-19 11:01 [PATCH 00/17] mkfs: sanitise input parameters Jan Ťulák
                   ` (13 preceding siblings ...)
  2015-06-19 11:02 ` [PATCH 14/17] mkfs: add string options to generic parsing Jan Ťulák
@ 2015-06-19 11:02 ` Jan Ťulák
  2015-06-26 19:32   ` Brian Foster
  2015-06-19 11:02 ` [PATCH 16/17] mkfs fix: handling of files Jan Ťulák
  2015-06-19 11:02 ` [PATCH 17/17] mkfs: move spinodes crc check Jan Ťulák
  16 siblings, 1 reply; 51+ messages in thread
From: Jan Ťulák @ 2015-06-19 11:02 UTC (permalink / raw)
  To: xfs; +Cc: Dave Chinner

From: Dave Chinner <dchinner@redhat.com>

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

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

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

Signed-off-by: Dave Chinner <dchinner@redhat.com>
Signed-off-by: Jan Ťulák <jtulak@redhat.com>
---
 libxfs/init.c   |   4 ++
 libxfs/linux.c  |  11 +++-
 mkfs/xfs_mkfs.c | 164 +++++++++++++++++++++++++++++++++++++++-----------------
 3 files changed, 129 insertions(+), 50 deletions(-)

diff --git a/libxfs/init.c b/libxfs/init.c
index 6f404aa..ed97043 100644
--- a/libxfs/init.c
+++ b/libxfs/init.c
@@ -246,6 +246,7 @@ libxfs_init(libxfs_init_t *a)
 	char		rtpath[25];
 	int		rval = 0;
 	int		flags;
+	struct stat st;
 
 	dpath[0] = logpath[0] = rtpath[0] = '\0';
 	dname = a->dname;
@@ -278,6 +279,9 @@ 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);
+			stat(dname, &st);
+			a->dsize = st.st_size;
+			a->dbsize = st.st_blksize;
 		} else {
 			if (!check_open(dname, flags, &rawfile, &blockfile))
 				goto done;
diff --git a/libxfs/linux.c b/libxfs/linux.c
index 885016a..49d430c 100644
--- a/libxfs/linux.c
+++ b/libxfs/linux.c
@@ -125,7 +125,16 @@ platform_set_blocksize(int fd, char *path, dev_t device, int blocksize, int fata
 void
 platform_flush_device(int fd, dev_t device)
 {
-	if (major(device) != RAMDISK_MAJOR)
+	struct stat64	st;
+	if (major(device) == RAMDISK_MAJOR)
+		return;
+
+	if (fstat64(fd, &st) < 0)
+		return;
+
+	if (S_ISREG(st.st_mode))
+		fsync(fd);
+	else
 		ioctl(fd, BLKFLSBUF, 0);
 }
 
diff --git a/mkfs/xfs_mkfs.c b/mkfs/xfs_mkfs.c
index 6bfa73c..ce64230 100644
--- a/mkfs/xfs_mkfs.c
+++ b/mkfs/xfs_mkfs.c
@@ -705,7 +705,7 @@ calc_stripe_factors(
  */
 static int
 check_overwrite(
-	char		*device)
+	const char	*device)
 {
 	const char	*type;
 	blkid_probe	pr = NULL;
@@ -722,7 +722,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 */
@@ -769,7 +769,6 @@ check_overwrite(
 			"according to blkid\n"), progname, device);
 	}
 	ret = 1;
-
 out:
 	if (pr)
 		blkid_free_probe(pr);
@@ -795,8 +794,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)
@@ -899,7 +902,7 @@ static void get_topology(
 #else /* ENABLE_BLKID */
 static int
 check_overwrite(
-	char		*device)
+	const char	*device)
 {
 	char		*type;
 
@@ -956,6 +959,75 @@ static void get_topology(
 #endif /* ENABLE_BLKID */
 
 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,
@@ -1245,9 +1317,18 @@ zero_old_xfs_structures(
 			strerror(errno));
 		goto done;
 	}
-	if (tmp != new_sb->sb_sectsize) {
-		fprintf(stderr,
-	_("warning: could not read existing superblock, skip zeroing\n"));
+	/*
+	 * If we are creating an image file, it might be of zero length at this
+	 * point in time. Hence reading the existing superblock is going to
+	 * return zero bytes. It's not a failure we need to warn about in this
+	 * case.
+	 */
+	off = pread(xi->dfd, buf, new_sb->sb_sectsize, 0);
+	if (off != new_sb->sb_sectsize) {
+		if (!xi->disfile)
+			fprintf(stderr,
+	_("error reading existing superblock: %s\n"),
+				strerror(errno));
 		goto done;
 	}
 	libxfs_sb_from_disk(&sb, buf);
@@ -1713,8 +1794,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);
@@ -1843,8 +1922,6 @@ main(
 				case L_FILE:
 					xi.lisfile = getnum(value, &lopts,
 							    L_FILE);
-					if (xi.lisfile)
-						xi.lcreat = 1;
 					break;
 				case L_INTERNAL:
 					loginternal = getnum(value, &lopts,
@@ -2011,8 +2088,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:
@@ -2079,13 +2154,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;
 
@@ -2118,6 +2187,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, !xi.dname,
+			  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);
 
@@ -2278,11 +2367,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;
 
@@ -2315,11 +2399,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;
 
@@ -2337,11 +2416,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;
 
@@ -2463,22 +2537,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.1.0

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

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

* [PATCH 16/17] mkfs fix: handling of files
  2015-06-19 11:01 [PATCH 00/17] mkfs: sanitise input parameters Jan Ťulák
                   ` (14 preceding siblings ...)
  2015-06-19 11:02 ` [PATCH 15/17] mkfs: don't treat files as though they are block devices Jan Ťulák
@ 2015-06-19 11:02 ` Jan Ťulák
  2015-06-26 19:32   ` Brian Foster
  2015-06-19 11:02 ` [PATCH 17/17] mkfs: move spinodes crc check Jan Ťulák
  16 siblings, 1 reply; 51+ messages in thread
From: Jan Ťulák @ 2015-06-19 11:02 UTC (permalink / raw)
  To: xfs

If mkfs is making a FS in a file, then the new FS should take host FS blocksize
as sectorsize. This patch is ensuring it by using statfs() instead of stat()
and platform_findsizes().

Signed-off-by: Jan Ťulák <jtulak@redhat.com>
---
 libxfs/init.c   |  7 +++++--
 mkfs/xfs_mkfs.c | 54 +++++++++++++++++++++++++++++-------------------------
 2 files changed, 34 insertions(+), 27 deletions(-)

diff --git a/libxfs/init.c b/libxfs/init.c
index ed97043..02d152c 100644
--- a/libxfs/init.c
+++ b/libxfs/init.c
@@ -17,6 +17,7 @@
  */
 
 #include <sys/stat.h>
+#include <sys/vfs.h>
 #include "init.h"
 
 #include "libxfs_priv.h"
@@ -247,6 +248,7 @@ libxfs_init(libxfs_init_t *a)
 	int		rval = 0;
 	int		flags;
 	struct stat st;
+	struct statfs stfs;
 
 	dpath[0] = logpath[0] = rtpath[0] = '\0';
 	dname = a->dname;
@@ -280,8 +282,9 @@ libxfs_init(libxfs_init_t *a)
 						    a->setblksize);
 			a->dfd = libxfs_device_to_fd(a->ddev);
 			stat(dname, &st);
-			a->dsize = st.st_size;
-			a->dbsize = st.st_blksize;
+			statfs(dname, &stfs);
+			a->dsize = st.st_size/BBSIZE;
+			a->dbsize = stfs.f_bsize;
 		} else {
 			if (!check_open(dname, flags, &rawfile, &blockfile))
 				goto done;
diff --git a/mkfs/xfs_mkfs.c b/mkfs/xfs_mkfs.c
index ce64230..2e455db 100644
--- a/mkfs/xfs_mkfs.c
+++ b/mkfs/xfs_mkfs.c
@@ -18,6 +18,7 @@
 
 #include <xfs/libxfs.h>
 #include <ctype.h>
+#include <sys/vfs.h>
 #ifdef ENABLE_BLKID
 #include <blkid/blkid.h>
 #else
@@ -865,31 +866,23 @@ static void get_topology(
 	struct fs_topology	*ft,
 	int			force_overwrite)
 {
-	if (!xi->disfile) {
-		char *dfile = xi->volname ? xi->volname : xi->dname;
-		struct stat statbuf;
+	char *dfile = xi->volname ? xi->volname : xi->dname;
+	struct stat statbuf;
+	struct statfs statfsbuf;
 
-		/*
-		 * If our target is a regular file, and xi->disfile isn't
-		 * set (i.e. no "-d file" invocation), 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 (!stat(dfile, &statbuf) && S_ISREG(statbuf.st_mode)) {
-			int fd;
-			long long dummy;
-
-			fd = open(dfile, O_RDONLY);
-			if (fd >= 0) {
-				platform_findsizes(dfile, fd, &dummy,
-						   &ft->lsectorsize);
-				close(fd);
-			}
-		} else {
-			blkid_get_topology(dfile, &ft->dsunit, &ft->dswidth,
-					   &ft->lsectorsize, &ft->psectorsize,
-					   force_overwrite);
-		}
+	/*
+	 * 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))) {
+
+		statfs(dfile, &statfsbuf);
+		ft->lsectorsize = statfsbuf.f_bsize;
+	} else {
+		blkid_get_topology(dfile, &ft->dsunit, &ft->dswidth,
+					&ft->lsectorsize, &ft->psectorsize,
+					force_overwrite);
 	}
 
 	if (xi->rtname && !xi->risfile) {
@@ -930,9 +923,20 @@ static void get_topology(
 {
 
 	char *dfile = xi->volname ? xi->volname : xi->dname;
+	struct stat statbuf;
+	struct statfs statfsbuf;
 	int bsz = BBSIZE;
 
-	if (!xi->disfile) {
+	/*
+	 * 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))) {
+
+		statfs(dfile, &statfsbuf);
+		bsz = statfsbuf.f_bsize;
+	} else {
 		int fd;
 		long long dummy;
 
-- 
2.1.0

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

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

* [PATCH 17/17] mkfs: move spinodes crc check
  2015-06-19 11:01 [PATCH 00/17] mkfs: sanitise input parameters Jan Ťulák
                   ` (15 preceding siblings ...)
  2015-06-19 11:02 ` [PATCH 16/17] mkfs fix: handling of files Jan Ťulák
@ 2015-06-19 11:02 ` Jan Ťulák
  2015-06-26 19:32   ` Brian Foster
  16 siblings, 1 reply; 51+ messages in thread
From: Jan Ťulák @ 2015-06-19 11:02 UTC (permalink / raw)
  To: xfs

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

Signed-off-by: Jan Ťulák <jtulak@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 2e455db..653fc5b 100644
--- a/mkfs/xfs_mkfs.c
+++ b/mkfs/xfs_mkfs.c
@@ -2347,12 +2347,13 @@ _("32 bit Project IDs always enabled on CRC enabled filesytems\n"));
 _("warning: finobt not supported without CRC support, disabled.\n"));
 			sb_feat.finobt = 0;
 		}
-	}
 
-	if (sb_feat.spinodes && !sb_feat.crcs_enabled) {
-		fprintf(stderr,
-_("warning: sparse inodes not supported without CRC support, disabled.\n"));
-		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.1.0

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

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

* Re: [PATCH 01/17] xfsprogs: use common code for multi-disk detection
  2015-06-19 11:01 ` [PATCH 01/17] xfsprogs: use common code for multi-disk detection Jan Ťulák
@ 2015-06-19 11:10   ` Christoph Hellwig
  2015-06-19 11:51     ` Jan Tulak
  2015-06-25 19:37   ` Brian Foster
  1 sibling, 1 reply; 51+ messages in thread
From: Christoph Hellwig @ 2015-06-19 11:10 UTC (permalink / raw)
  To: Jan ??ul??k; +Cc: Dave Chinner, xfs

> index 70e43a0..3269ec3 100644
> --- a/include/Makefile
> +++ b/include/Makefile
> @@ -26,9 +26,15 @@ QAHFILES = libxfs.h libxlog.h \
>  	xfs_inode.h \
>  	xfs_log_recover.h \
>  	xfs_metadump.h \
> +	xfs_mkfs.h \
>  	xfs_mount.h \
> +	xfs_quota_defs.h \
> +	xfs_sb.h \
> +	xfs_shared.h \
>  	xfs_trace.h \
> -	xfs_trans.h
> +	xfs_trans.h \
> +	xfs_trans_resv.h \
> +	xfs_trans_space.h

These shouldn't be added to the headers installed by make install-qa.

(which I'm going to send a patch to remove once Dave applied the
build fix, btw)

Also I'm not sure xfs_mkfs.h really is a good name for a global header.

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

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

* Re: [PATCH 01/17] xfsprogs: use common code for multi-disk detection
  2015-06-19 11:10   ` Christoph Hellwig
@ 2015-06-19 11:51     ` Jan Tulak
  0 siblings, 0 replies; 51+ messages in thread
From: Jan Tulak @ 2015-06-19 11:51 UTC (permalink / raw)
  To: Christoph Hellwig; +Cc: xfs, Dave Chinner



----- Original Message -----
> From: "Christoph Hellwig" <hch@infradead.org>
> To: "Jan ??ul??k" <jtulak@redhat.com>
> Cc: "Dave Chinner" <dchinner@redhat.com>, xfs@oss.sgi.com
> Sent: Friday, June 19, 2015 1:10:22 PM
> Subject: Re: [PATCH 01/17] xfsprogs: use common code for multi-disk detection
> 
> > index 70e43a0..3269ec3 100644
> > --- a/include/Makefile
> > +++ b/include/Makefile
> > @@ -26,9 +26,15 @@ QAHFILES = libxfs.h libxlog.h \
> >  	xfs_inode.h \
> >  	xfs_log_recover.h \
> >  	xfs_metadump.h \
> > +	xfs_mkfs.h \
> >  	xfs_mount.h \
> > +	xfs_quota_defs.h \
> > +	xfs_sb.h \
> > +	xfs_shared.h \
> >  	xfs_trace.h \
> > -	xfs_trans.h
> > +	xfs_trans.h \
> > +	xfs_trans_resv.h \
> > +	xfs_trans_space.h
> 
> These shouldn't be added to the headers installed by make install-qa.
> 
> (which I'm going to send a patch to remove once Dave applied the
> build fix, btw)
> 
OK, noted.

> Also I'm not sure xfs_mkfs.h really is a good name for a global header.

I don't see any issue with it, but if there is a reason for a different name, I can change it. :-)

Cheers,
Jan

-- 
Jan Tulak
jtulak@redhat.com

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

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

* Re: [PATCH 01/17] xfsprogs: use common code for multi-disk detection
  2015-06-19 11:01 ` [PATCH 01/17] xfsprogs: use common code for multi-disk detection Jan Ťulák
  2015-06-19 11:10   ` Christoph Hellwig
@ 2015-06-25 19:37   ` Brian Foster
  2015-07-02 12:47     ` Jan Tulak
  1 sibling, 1 reply; 51+ messages in thread
From: Brian Foster @ 2015-06-25 19:37 UTC (permalink / raw)
  To: Jan Ťulák; +Cc: Dave Chinner, xfs

On Fri, Jun 19, 2015 at 01:01:50PM +0200, Jan Ťulák wrote:
> From: Dave Chinner <dchinner@redhat.com>
> 
> Both xfs_repair and mkfs.xfs need to agree on what is a "multidisk:
> configuration - mkfs for determining the AG count of the filesystem,
> repair for determining how to automatically parallelise it's
> execution. This requires a bunch of common defines that both mkfs
> and reapir need to share.
> 
> In fact, most of the defines in xfs_mkfs.h could be shared with
> other programs (i.e. all the defaults mkfs uses) and so it is
> simplest to move xfs_mkfs.h to the shared include directory and add
> the new defines to it directly.
> 
> Signed-off-by: Dave Chinner <dchinner@redhat.com>
> Signed-off-by: Jan Ťulák <jtulak@redhat.com>
> ---
>  include/Makefile    |  8 ++++-
>  include/xfs_mkfs.h  | 98 +++++++++++++++++++++++++++++++++++++++++++++++++++++
>  mkfs/Makefile       |  2 +-
>  mkfs/xfs_mkfs.c     | 56 +++++++++++++++---------------
>  mkfs/xfs_mkfs.h     | 89 ------------------------------------------------
>  repair/xfs_repair.c | 45 ++++++++++++++++++++++--
>  6 files changed, 178 insertions(+), 120 deletions(-)
>  create mode 100644 include/xfs_mkfs.h
>  delete mode 100644 mkfs/xfs_mkfs.h
> 
> diff --git a/include/Makefile b/include/Makefile
> index 70e43a0..3269ec3 100644
> --- a/include/Makefile
> +++ b/include/Makefile
> @@ -26,9 +26,15 @@ QAHFILES = libxfs.h libxlog.h \
>  	xfs_inode.h \
>  	xfs_log_recover.h \
>  	xfs_metadump.h \
> +	xfs_mkfs.h \
>  	xfs_mount.h \
> +	xfs_quota_defs.h \
> +	xfs_sb.h \
> +	xfs_shared.h \
>  	xfs_trace.h \
> -	xfs_trans.h
> +	xfs_trans.h \
> +	xfs_trans_resv.h \
> +	xfs_trans_space.h
>  
>  HFILES = handle.h jdm.h xqm.h xfs.h
>  HFILES += $(PKG_PLATFORM).h
> diff --git a/include/xfs_mkfs.h b/include/xfs_mkfs.h
> new file mode 100644
> index 0000000..3388f6d
> --- /dev/null
> +++ b/include/xfs_mkfs.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_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))
> +
> +/*
> + * 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);
> +
> +#endif	/* __XFS_MKFS_H__ */
> diff --git a/mkfs/Makefile b/mkfs/Makefile
> index fd1f615..82326e0 100644
> --- a/mkfs/Makefile
> +++ b/mkfs/Makefile
> @@ -8,7 +8,7 @@ include $(TOPDIR)/include/builddefs
>  LTCOMMAND = mkfs.xfs
>  FSTYP = fstyp
>  
> -HFILES = xfs_mkfs.h
> +HFILES =
>  CFILES = maxtrres.c proto.c xfs_mkfs.c
>  
>  ifeq ($(ENABLE_BLKID),yes)
> diff --git a/mkfs/xfs_mkfs.c b/mkfs/xfs_mkfs.c
> index 83f7749..d0de90d 100644
> --- a/mkfs/xfs_mkfs.c
> +++ b/mkfs/xfs_mkfs.c
> @@ -24,7 +24,7 @@
>  #include <disk/fstyp.h>
>  #include <disk/volume.h>
>  #endif
> -#include "xfs_mkfs.h"
> +#include <xfs/xfs_mkfs.h>
>  
>  /*
>   * Device topology information.
> @@ -688,43 +688,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--;
> +

Intended change in behavior of the defaults for fs' that match these
size thresholds (the 512g and 8g ones anyways)? For example, in the old
code a 512GB fs gets a shift of 4 while the same fs gets shift = 5 in
the new code.

Brian

>  	/*
>  	 * 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 9df5f37..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);
> -
> -#endif	/* __XFS_MKFS_H__ */
> diff --git a/repair/xfs_repair.c b/repair/xfs_repair.c
> index 11a6069..7e2d7ff 100644
> --- a/repair/xfs_repair.c
> +++ b/repair/xfs_repair.c
> @@ -19,6 +19,7 @@
>  #include <xfs/libxfs.h>
>  #include <xfs/libxlog.h>
>  #include <sys/resource.h>
> +#include <xfs/xfs_mkfs.h>
>  #include "avl.h"
>  #include "avl64.h"
>  #include "globals.h"
> @@ -526,6 +527,33 @@ _("sb realtime summary inode %" PRIu64 " %sinconsistent with calculated value %u
>  
>  }
>  
> +/*
> + * 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)
>  {
> @@ -644,9 +672,22 @@ 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 = glob_agcount;
> +		ag_stride = min(glob_agcount, XFS_MULTIDISK_AGCOUNT / 2) - 1;
> +	}
>  
>  	if (ag_stride) {
>  		int max_threads = platform_nproc() * 8;
> -- 
> 2.1.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] 51+ messages in thread

* Re: [PATCH 02/17] mkfs: sanitise ftype parameter values.
  2015-06-19 11:01 ` [PATCH 02/17] mkfs: sanitise ftype parameter values Jan Ťulák
@ 2015-06-25 19:37   ` Brian Foster
  0 siblings, 0 replies; 51+ messages in thread
From: Brian Foster @ 2015-06-25 19:37 UTC (permalink / raw)
  To: Jan Ťulák; +Cc: Dave Chinner, xfs

On Fri, Jun 19, 2015 at 01:01:51PM +0200, Jan Ťulák wrote:
> 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 Ťulák <jtulak@redhat.com>
> ---

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

>  mkfs/xfs_mkfs.c | 5 ++++-
>  1 file changed, 4 insertions(+), 1 deletion(-)
> 
> diff --git a/mkfs/xfs_mkfs.c b/mkfs/xfs_mkfs.c
> index d0de90d..1652903 100644
> --- a/mkfs/xfs_mkfs.c
> +++ b/mkfs/xfs_mkfs.c
> @@ -1617,12 +1617,15 @@ _("cannot specify both crc and ftype\n"));
>  						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.1.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] 51+ messages in thread

* Re: [PATCH 03/17] mkfs: Sanitise the superblock feature macros
  2015-06-19 11:01 ` [PATCH 03/17] mkfs: Sanitise the superblock feature macros Jan Ťulák
@ 2015-06-25 19:38   ` Brian Foster
  2015-07-03  9:53     ` Jan Tulak
  0 siblings, 1 reply; 51+ messages in thread
From: Brian Foster @ 2015-06-25 19:38 UTC (permalink / raw)
  To: Jan Ťulák; +Cc: Dave Chinner, xfs

On Fri, Jun 19, 2015 at 01:01:52PM +0200, Jan Ťulák wrote:
> From: Dave Chinner <dchinner@redhat.com>
> 
> They are horrible macros that simply obfuscate the code, so
> let's factor the code and make them nice functions.
> 
> To do this, add a sb_feat_args structure that carries around the
> variables rather than a strange assortment of variables. This means
> all the default can be clearly defined in a structure
> initialisation, and dependent feature bits are easy to check.
> 
> Signed-off-by: Dave Chinner <dchinner@redhat.com>
> Signed-off-by: Jan Ťulák <jtulak@redhat.com>
> ---
>  include/xfs_mkfs.h |  25 +----
>  mkfs/xfs_mkfs.c    | 293 ++++++++++++++++++++++++++++++++---------------------
>  2 files changed, 181 insertions(+), 137 deletions(-)
> 
> diff --git a/include/xfs_mkfs.h b/include/xfs_mkfs.h
> index 3388f6d..3af9cb1 100644
> --- a/include/xfs_mkfs.h
> +++ b/include/xfs_mkfs.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 1652903..10276e4 100644
> --- a/mkfs/xfs_mkfs.c
> +++ b/mkfs/xfs_mkfs.c
> @@ -903,6 +903,107 @@ 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;

Line above exceeds 80 chars.

> +		sbp->sb_features_incompat |= XFS_SB_FEAT_INCOMPAT_SPINODES;
> +	}
> +
> +}
> +
>  int
>  main(
>  	int			argc,
> @@ -914,8 +1015,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;
> @@ -930,8 +1029,6 @@ main(
>  	char			*dfile;
>  	int			dirblocklog;
>  	int			dirblocksize;
> -	int			dirftype;
> -	int			dirversion;
>  	char			*dsize;
>  	int			dsu;
>  	int			dsw;
> @@ -939,7 +1036,6 @@ main(
>  	int			dswidth;
>  	int			force_overwrite;
>  	struct fsxattr		fsx;
> -	int			iaflag;
>  	int			ilflag;
>  	int			imaxpct;
>  	int			imflag;
> @@ -981,7 +1077,6 @@ main(
>  	int			nftype;
>  	int			nsflag;
>  	int			nvflag;
> -	int			nci;
>  	int			Nflag;
>  	int			discard = 1;
>  	char			*p;
> @@ -1005,19 +1100,27 @@ 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,
> +	};
>  

FYI...

Building mkfs
    [CC]     xfs_mkfs.o
xfs_mkfs.c: In function ‘main’:
xfs_mkfs.c:1058:8: warning: unused variable ‘logversion’ [-Wunused-variable]
  int   logversion;
        ^

>  	progname = basename(argv[0]);
>  	setlocale(LC_ALL, "");
>  	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;
> @@ -1026,26 +1129,18 @@ 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;
> -	nftype = dirftype = 0;		/* 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));
> @@ -1284,10 +1379,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)
> +						break;

reqval() ?

> +					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')
> @@ -1357,7 +1453,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')
> @@ -1365,13 +1461,13 @@ 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)
> +					sb_feat.spinodes = atoi(value);
> +					if (sb_feat.spinodes < 0 || sb_feat.spinodes > 1)

Why not use 'c' here like everywhere else?

>  						illegal(value, "i spinodes");
>  					break;
>  				default:
> @@ -1464,9 +1560,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:
> @@ -1515,7 +1612,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);
> @@ -1539,12 +1637,14 @@ main(
>  					c = atoi(value);
>  					if (c < 0 || c > 1)
>  						illegal(value, "m crc");
> -					crcs_enabled = c;
> -					if (nftype && crcs_enabled) {
> +					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')
> @@ -1552,8 +1652,7 @@ _("cannot specify both crc and ftype\n"));
>  					c = atoi(value);
>  					if (c < 0 || c > 1)
>  						illegal(value, "m finobt");
> -					finobt = c;
> -					finobtflag = true;
> +					sb_feat.finobt = c;

What happened to finobtflag (see below)?

>  					break;
>  				default:
>  					unknown('m', value);
> @@ -1603,12 +1702,14 @@ _("cannot specify both crc and ftype\n"));
>  					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;
> @@ -1620,12 +1721,12 @@ _("cannot specify both crc and ftype\n"));
>  					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:
> @@ -1774,7 +1875,7 @@ _("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);
> @@ -1851,7 +1952,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;
>  	}
>  
>  	/*
> @@ -1859,7 +1960,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,
> @@ -1869,28 +1970,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();
> @@ -1898,7 +1999,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();
> @@ -1912,17 +2013,17 @@ _("32 bit Project IDs always enabled on CRC enabled filesytems\n"));
>  		 * tried to use crc=0,finobt=1, then issue a warning before
>  		 * turning them off.
>  		 */
> -		if (finobt && finobtflag) {
> +		if (sb_feat.finobt && sb_feat.finobtflag) {

Since the code above drops finobtflag, I don't think we'll ever hit
this. Indeed, I can now create a crc=0,finobt=1 fs, which shouldn't
happen.

Brian

>  			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) {
> @@ -1972,11 +2073,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);
> @@ -2106,10 +2207,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,
> @@ -2424,12 +2525,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,
> @@ -2441,9 +2542,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);
> +				   sb_feat.log_version, lsunit);
>  	ASSERT(min_logblocks);
>  	min_logblocks = MAX(XFS_MIN_LOG_BLOCKS, min_logblocks);
>  	if (!logsize && dblocks >= (1024*1024*1024) >> blocklog)
> @@ -2521,25 +2622,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) {
>  		/*
> @@ -2591,14 +2675,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"
> @@ -2611,13 +2687,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)
> @@ -2660,17 +2739,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) {
> @@ -2681,19 +2760,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);
> @@ -2749,7 +2816,7 @@ _("size %s specified for log subvolume is too large, maximum is %lld blocks\n"),
>  	libxfs_log_clear(mp->m_logdev_targp,
>  		XFS_FSB_TO_DADDR(mp, logstart),
>  		(xfs_extlen_t)XFS_FSB_TO_BB(mp, logblocks),
> -		&sbp->sb_uuid, logversion, lsunit, XLOG_FMT);
> +		&sbp->sb_uuid, sb_feat.log_version, lsunit, XLOG_FMT);
>  
>  	mp = libxfs_mount(mp, sbp, xi.ddev, xi.logdev, xi.rtdev, 0);
>  	if (mp == NULL) {
> @@ -2851,7 +2918,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);
>  		}
> @@ -2984,7 +3051,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)
>  			continue;
>  
>  		buf = libxfs_getbuf(mp->m_ddev_targp,
> -- 
> 2.1.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] 51+ messages in thread

* Re: [PATCH 04/17] mkfs: validate all input values
  2015-06-19 11:01 ` [PATCH 04/17] mkfs: validate all input values Jan Ťulák
@ 2015-06-25 19:38   ` Brian Foster
  0 siblings, 0 replies; 51+ messages in thread
From: Brian Foster @ 2015-06-25 19:38 UTC (permalink / raw)
  To: Jan Ťulák; +Cc: Dave Chinner, xfs

On Fri, Jun 19, 2015 at 01:01:53PM +0200, Jan Ťulák wrote:
> From: Dave Chinner <dchinner@redhat.com>
> 
> Right now, mkfs does a poor job of input validation of values. Many
> parameters do not check for trailing garbage and so will pass
> obviously invalid values as OK. Some don't even detect completely
> invalid values, leaving it for other checks later on to fail due to
> a bad value conversion - these tend to rely on atoi() implicitly
> returning a sane value when it is passed garbage, and atoi gives no
> guarantee of the return value when passed garbage.
> 
> Clean all this up by passing all strings that need to be converted
> into values into a common function that is called regardless of
> whether unit conversion is needed or not. Further, make sure every
> conversion is checked for a valid result, and abort the moment an
> invalid value is detected.
> 
> Get rid of the silly "isdigits(), cvtnum()" calls which don't use
> any of the conversion capabilities of cvtnum() because we've already
> ensured that there are no conversion units in the string via the
> isdigits() call. These can simply be replaced by a standard
> strtoll() call followed by checking for no trailing bytes.
> 
> Finally, the block size of the filesystem is not known until all
> the options have been parsed and we can determine if the default is
> to be used. This means any parameter that relies on using conversion
> from filesystem block size (the "NNNb" format) requires the block
> size to first be specified on the command line so it is known.
> 
> Similarly, we make the same rule for specifying counts in sectors.
> This is a change from the existing behaviour that assumes sectors
> are 512 bytes unless otherwise changed on the command line. This,
> unfortunately, leads to complete silliness where you can specify the
> sector size as a count of sectors. It also means that you can do
> some conversions with 512 byte sector sizes, and others with
> whatever was specified on the command line, meaning the mkfs
> behaviour changes depending in where in the command line the sector
> size is changed....
> 
> Signed-off-by: Dave Chinner <dchinner@redhat.com>
> Signed-off-by: Jan Ťulák <jtulak@redhat.com>
> ---

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

>  include/xfs_mkfs.h  |   7 +-
>  man/man8/mkfs.xfs.8 |  26 ++++++-
>  mkfs/proto.c        |  36 ++++-----
>  mkfs/xfs_mkfs.c     | 215 +++++++++++++++++++++++++++-------------------------
>  4 files changed, 153 insertions(+), 131 deletions(-)
> 
> diff --git a/include/xfs_mkfs.h b/include/xfs_mkfs.h
> index 3af9cb1..996b690 100644
> --- a/include/xfs_mkfs.h
> +++ b/include/xfs_mkfs.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 6260e0c..4456931 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
>  XFS on Linux currently only supports pagesize or smaller blocks.
>  .TP
>  .BI \-m " global_metadata_options"
> @@ -804,6 +818,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 45565b7..a2a61e0 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,
> @@ -441,8 +430,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 = getnum(getstr(pp), 0, 0, false);
> +	creds.cr_gid = getnum(getstr(pp), 0, 0, false);
>  	xname.name = (uchar_t *)name;
>  	xname.len = name ? strlen(name) : 0;
>  	xname.type = 0;
> @@ -467,7 +456,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,
> @@ -491,8 +487,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) {
> @@ -506,8 +502,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 10276e4..1a5e2f8 100644
> --- a/mkfs/xfs_mkfs.c
> +++ b/mkfs/xfs_mkfs.c
> @@ -49,6 +49,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
>   */
> @@ -1004,6 +1007,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,
> @@ -1123,8 +1148,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;
> @@ -1167,7 +1192,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;
> @@ -1181,8 +1206,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");
> @@ -1205,8 +1230,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;
> @@ -1216,14 +1240,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)
> @@ -1251,13 +1277,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')
> @@ -1267,13 +1289,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')
> @@ -1283,8 +1301,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')
> @@ -1294,13 +1314,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)
> @@ -1325,7 +1341,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;
> @@ -1339,8 +1355,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");
> @@ -1380,7 +1396,7 @@ main(
>  				case I_ALIGN:
>  					if (!value || *value == '\0')
>  						break;
> -					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;
> @@ -1396,7 +1412,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;
> @@ -1407,7 +1423,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;
> @@ -1423,7 +1439,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))
> @@ -1441,7 +1457,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);
> @@ -1450,7 +1466,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;
> @@ -1458,7 +1474,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;
> @@ -1488,7 +1504,9 @@ main(
>  						respec('l', lopts, L_AGNUM);
>  					if (ldflag)
>  						conflict('l', lopts, L_AGNUM, L_DEV);
> -					logagno = atoi(value);
> +					logagno = getnum(value, 0, 0, false);
> +					if (logagno < 0)
> +						illegal(value, "l agno");
>  					laflag = 1;
>  					break;
>  				case L_FILE:
> @@ -1497,7 +1515,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)
> @@ -1513,7 +1531,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;
> @@ -1523,8 +1541,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:
> @@ -1532,12 +1552,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:
> @@ -1560,7 +1577,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;
> @@ -1582,7 +1599,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;
> @@ -1596,8 +1613,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");
> @@ -1609,7 +1626,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
> @@ -1634,7 +1651,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) {
> @@ -1673,7 +1690,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;
> @@ -1687,8 +1704,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");
> @@ -1705,7 +1722,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");
> @@ -1718,7 +1735,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) {
> @@ -1764,7 +1781,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)
> @@ -1808,7 +1825,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;
> @@ -1825,8 +1842,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");
> @@ -1882,6 +1899,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);
>  
> @@ -2055,7 +2081,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"),
> @@ -2092,7 +2120,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"),
> @@ -2114,7 +2144,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"),
> @@ -2134,7 +2166,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"),
> @@ -3240,28 +3274,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;
> @@ -3272,17 +3289,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.1.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] 51+ messages in thread

* Re: [PATCH 05/17] mkfs: factor boolean option parsing
  2015-06-19 11:01 ` [PATCH 05/17] mkfs: factor boolean option parsing Jan Ťulák
@ 2015-06-25 19:38   ` Brian Foster
  0 siblings, 0 replies; 51+ messages in thread
From: Brian Foster @ 2015-06-25 19:38 UTC (permalink / raw)
  To: Jan Ťulák; +Cc: Dave Chinner, xfs

On Fri, Jun 19, 2015 at 01:01:54PM +0200, Jan Ťulák wrote:
> From: Dave Chinner <dchinner@redhat.com>
> 
> Many of the options passed to mkfs have boolean options (0 or 1) and
> all hand roll the same code and validity checks. Factor these out
> into a common function.
> 
> Note that the lazy-count option is now changed to match other
> booleans in that if you don't specify a value, it reverts to the
> default value (on) rather than throwing an error. Similarly the -m
> crc and -n ftype options default to off rather than throwing an
> error.
> 
> Signed-off-by: Dave Chinner <dchinner@redhat.com>
> Signed-off-by: Jan Ťulák <jtulak@redhat.com>
> ---
>  mkfs/xfs_mkfs.c | 101 +++++++++++++++++++++++---------------------------------
>  1 file changed, 42 insertions(+), 59 deletions(-)
> 
> diff --git a/mkfs/xfs_mkfs.c b/mkfs/xfs_mkfs.c
> index 1a5e2f8..6b9e991 100644
> --- a/mkfs/xfs_mkfs.c
> +++ b/mkfs/xfs_mkfs.c
> @@ -42,7 +42,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);
> @@ -1028,6 +1028,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(
> @@ -1247,11 +1262,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;
> @@ -1394,12 +1406,8 @@ main(
>  
>  				switch (getsubopt(&p, (constpp)iopts, &value)) {
>  				case I_ALIGN:
> -					if (!value || *value == '\0')
> -						break;
> -					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')
> @@ -1472,12 +1480,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')
> @@ -1510,20 +1514,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)
> @@ -1531,9 +1530,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:
> @@ -1623,14 +1622,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);
> @@ -1649,18 +1643,14 @@ 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", false);

Hmm... so I know we have crc on by default now, but it seems a little
weird to me for '-m crc' to turn it off.

> +					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:

No getbool() update for finobt?

> @@ -1731,19 +1721,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", false);

Similar weirdness here, IMO. Using '-m crc -n ftype' gives an fs without
either. The toggling behavior is consistent I suppose, but it seems
really nonintuitive to me. I would expect the act of specifying
something as an implicit request to enable, regardless of the
application specific defaults (that do change once in a while).

Brian

>  					nftype = 1;
>  					break;
>  				default:
> @@ -1779,11 +1765,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;
> @@ -3228,8 +3211,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.1.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] 51+ messages in thread

* Re: [PATCH 06/17] mkfs: validate logarithmic parameters sanely
  2015-06-19 11:01 ` [PATCH 06/17] mkfs: validate logarithmic parameters sanely Jan Ťulák
@ 2015-06-26 17:16   ` Brian Foster
  0 siblings, 0 replies; 51+ messages in thread
From: Brian Foster @ 2015-06-26 17:16 UTC (permalink / raw)
  To: Jan Ťulák; +Cc: Dave Chinner, xfs

On Fri, Jun 19, 2015 at 01:01:55PM +0200, Jan Ťulák 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.:
> 
> # 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 Ťulák <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 6b9e991..6f0aa55 100644
> --- a/mkfs/xfs_mkfs.c
> +++ b/mkfs/xfs_mkfs.c
> @@ -1044,6 +1044,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,
> @@ -1200,16 +1221,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;
> @@ -1346,16 +1367,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;
> @@ -1420,9 +1441,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;
> @@ -1591,16 +1614,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;
> @@ -1673,16 +1696,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;
> @@ -1801,16 +1824,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.1.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] 51+ messages in thread

* Re: [PATCH 07/17] mkfs: structify input parameter passing
  2015-06-19 11:01 ` [PATCH 07/17] mkfs: structify input parameter passing Jan Ťulák
@ 2015-06-26 17:16   ` Brian Foster
  0 siblings, 0 replies; 51+ messages in thread
From: Brian Foster @ 2015-06-26 17:16 UTC (permalink / raw)
  To: Jan Ťulák; +Cc: Dave Chinner, xfs

On Fri, Jun 19, 2015 at 01:01:56PM +0200, Jan Ťulák wrote:
> From: Dave Chinner <dchinner@redhat.com>
> 
> Passing large number of parameters around to number conversion
> functions is painful. Add a structure to encapsulate the constant
> parameters that are passed, and convert getnum_checked to use it.
> 
> This is the first real step towards a table driven option parser.
> 
> Signed-off-by: Dave Chinner <dchinner@redhat.com>
> Signed-off-by: Jan Ťulák <jtulak@redhat.com>
> ---
>  mkfs/xfs_mkfs.c | 602 ++++++++++++++++++++++++++++++++++++--------------------
>  1 file changed, 392 insertions(+), 210 deletions(-)
> 
> diff --git a/mkfs/xfs_mkfs.c b/mkfs/xfs_mkfs.c
> index 6f0aa55..d3d1e11 100644
> --- a/mkfs/xfs_mkfs.c
> +++ b/mkfs/xfs_mkfs.c
> @@ -52,145 +52,322 @@ static int  ispow2(unsigned int i);
>  static long long cvtnum(unsigned int blocksize,
>  			unsigned int sectorsize, const char *s);
>  
...
>  
> -char	*iopts[] = {
> +
> +const 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",
>  #define I_SPINODES	7
>  	"sparse",
>  	NULL

Nit... the last few strings in the above aren't aligned properly. Looks
like they weren't touched, so perhaps just an artifact of forward
porting the series.

> +	},
> +	.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,
> +		},

Missing I_SPINODES here.

> +	},
>  };
>  
...
> +
>  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)
> +	const 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);
>  
>  	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);

Some kind of error, assert or updated logic to ensure minval and maxval
are specified would be nice here so failures to use the correct
validation function (or to specify the values) are more obvious.

>  	return c;
>  }
>  
...
> @@ -1662,9 +1842,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", false);
> @@ -1678,7 +1860,7 @@ _("cannot specify both -m crc=1 and -n ftype\n"));
>  					break;
>  				case M_FINOBT:
>  					if (!value || *value == '\0')
> -						reqval('m', mopts, M_CRC);
> +						reqval('m', (char**)mopts.subopts, M_CRC);

Can probably use subopts here..?

Brian

>  					c = atoi(value);
>  					if (c < 0 || c > 1)
>  						illegal(value, "m finobt");
> @@ -1692,30 +1874,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);
> @@ -1728,9 +1909,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;
> @@ -1745,7 +1926,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"));
> @@ -1777,14 +1958,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:
> @@ -1796,16 +1979,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:
> @@ -1819,21 +2002,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;
> @@ -1842,11 +2024,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.1.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] 51+ messages in thread

* Re: [PATCH 08/17] mkfs: getbool is redundant
  2015-06-19 11:01 ` [PATCH 08/17] mkfs: getbool is redundant Jan Ťulák
@ 2015-06-26 17:17   ` Brian Foster
  2015-06-30  1:32     ` Dave Chinner
  0 siblings, 1 reply; 51+ messages in thread
From: Brian Foster @ 2015-06-26 17:17 UTC (permalink / raw)
  To: Jan Ťulák; +Cc: Dave Chinner, xfs

On Fri, Jun 19, 2015 at 01:01:57PM +0200, Jan Ťulák wrote:
> From: Dave Chinner <dchinner@redhat.com>
> 
> getbool() can be replaced with getnum_checked with appropriate
> min/max values set for the boolean variables.
> 
> Signed-off-by: Dave Chinner <dchinner@redhat.com>
> Signed-off-by: Jan Ťulák <jtulak@redhat.com>
> ---
>  mkfs/xfs_mkfs.c | 147 ++++++++++++++++++++++++++++++++++++++++----------------
>  1 file changed, 106 insertions(+), 41 deletions(-)
> 
> diff --git a/mkfs/xfs_mkfs.c b/mkfs/xfs_mkfs.c
> index d3d1e11..3803779 100644
> --- a/mkfs/xfs_mkfs.c
> +++ b/mkfs/xfs_mkfs.c
> @@ -53,6 +53,7 @@ static long long cvtnum(unsigned int blocksize,
>  			unsigned int sectorsize, const char *s);
>  
>  #define MAX_SUBOPTS	16
> +#define SUBOPT_NEEDS_VAL	(-1LL)
>  struct opt_params {
>  	const char	name;
>  	const char	*subopts[MAX_SUBOPTS];
> @@ -60,6 +61,7 @@ struct opt_params {
>  		int		index;
>  		long long	minval;
>  		long long	maxval;
> +		long long	defaultval;
>  	}		subopt_params[MAX_SUBOPTS];
>  };
>  
> @@ -76,10 +78,12 @@ const 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,
>  		},
>  	},
>  };
> @@ -121,38 +125,55 @@ const 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,
> +		  .defaultval = SUBOPT_NEEDS_VAL,
>  		},
>  		{ .index = D_RTINHERIT,
> +		  .defaultval = SUBOPT_NEEDS_VAL,
>  		},

I don't think the above two require values.

>  		{ .index = D_PROJINHERIT,
> +		  .defaultval = SUBOPT_NEEDS_VAL,
>  		},
>  		{ .index = D_EXTSZINHERIT,
> +		  .defaultval = SUBOPT_NEEDS_VAL,
>  		},
>  	},
>  };
> @@ -181,20 +202,31 @@ const 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,

Need to handle sparse here too once it's added to the previous patch.

>  		},
>  	},
>  };
> @@ -230,32 +262,50 @@ const 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,
>  		},
>  	},
>  };
> @@ -277,14 +327,20 @@ const 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 = 0,
>  		},
>  	},
>  };
> @@ -308,16 +364,22 @@ const 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,
> +		  .defaultval = SUBOPT_NEEDS_VAL,

This should have min/max/default similar to D_FILE, yes?

>  		},
>  		{ .index = R_NAME,
> +		  .defaultval = SUBOPT_NEEDS_VAL,
>  		},
>  		{ .index = R_NOALIGN,
> +		  .defaultval = SUBOPT_NEEDS_VAL,

Not sure about this one, either. There's no value according to the man
page.

>  		},
>  	},
>  };
> @@ -339,18 +401,22 @@ const 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,
>  		},
>  	},
>  };
> @@ -366,6 +432,9 @@ const struct opt_params mopts = {
>  	},
>  	.subopt_params = {
>  		{ .index = M_CRC,
> +		  .minval = 0,
> +		  .maxval = 1,
> +		  .defaultval = 0,
>  		},
>  	},

How about M_FINOBT?

Brian

>  };
> @@ -1205,22 +1274,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,
> @@ -1235,18 +1288,28 @@ illegal_option(
>  
>  static int
>  getnum_checked(
> -	const char	*str,
> +	const char		*str,
>  	const struct opt_params	*opts,
> -	int		index)
> +	int			index)
>  {
> -	long long	c;
> +	const struct subopt_param *sp = &opts->subopt_params[index];
> +	long long		c;
>  
> -	if (!str || *str == '\0')
> +	if (sp->index != index) {
> +		fprintf(stderr,
> +	("Developer screwed up option parsing (%d/%d)! Please report!\n"),
> +			sp->index, index);
>  		reqval(opts->name, (char **)opts->subopts, index);
> +	}
> +
> +	if (!str || *str == '\0') {
> +		if (sp->defaultval == SUBOPT_NEEDS_VAL)
> +			reqval(opts->name, (char **)opts->subopts, index);
> +		return sp->defaultval;
> +	}
>  
>  	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;
>  }
> @@ -1470,8 +1533,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;
> @@ -1613,8 +1676,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)
> @@ -1684,8 +1747,9 @@ 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')
> @@ -1723,8 +1787,8 @@ main(
>  					if (loginternal)
>  						conflict('l', subopts, L_INTERNAL,
>  							 L_FILE);
> -					xi.lisfile = getbool(value, "l file",
> -							     true);
> +					xi.lisfile = getnum_checked(value,
> +								&lopts, L_FILE);
>  					if (xi.lisfile)
>  						xi.lcreat = 1;
>  					break;
> @@ -1737,8 +1801,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:
> @@ -1825,9 +1889,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);
> @@ -1848,8 +1912,9 @@ main(
>  				switch (getsubopt(&p, (constpp)subopts,
>  						  &value)) {
>  				case M_CRC:
> -					sb_feat.crcs_enabled = getbool(
> -							value, "m crc", false);
> +					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"));
> @@ -1932,8 +1997,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", false);
> +					sb_feat.dirftype = getnum_checked(value,
> +								&nopts, N_FTYPE);
>  					nftype = 1;
>  					break;
>  				default:
> @@ -1971,8 +2036,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;
> -- 
> 2.1.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] 51+ messages in thread

* Re: [PATCH 09/17] mkfs: use getnum_checked for all ranged parameters
  2015-06-19 11:01 ` [PATCH 09/17] mkfs: use getnum_checked for all ranged parameters Jan Ťulák
@ 2015-06-26 17:17   ` Brian Foster
  0 siblings, 0 replies; 51+ messages in thread
From: Brian Foster @ 2015-06-26 17:17 UTC (permalink / raw)
  To: Jan Ťulák; +Cc: Dave Chinner, xfs

On Fri, Jun 19, 2015 at 01:01:58PM +0200, Jan Ťulák 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 Ťulák <jtulak@redhat.com>
> ---

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

>  include/xfs_mkfs.h |   5 +-
>  mkfs/xfs_mkfs.c    | 152 +++++++++++++++++++++++++++--------------------------
>  2 files changed, 81 insertions(+), 76 deletions(-)
> 
> diff --git a/include/xfs_mkfs.h b/include/xfs_mkfs.h
> index 996b690..f5639b0 100644
> --- a/include/xfs_mkfs.h
> +++ b/include/xfs_mkfs.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 3803779..332c491 100644
> --- a/mkfs/xfs_mkfs.c
> +++ b/mkfs/xfs_mkfs.c
> @@ -125,6 +125,8 @@ const struct opt_params dopts = {
>  	},
>  	.subopt_params = {
>  		{ .index = D_AGCOUNT,
> +		  .minval = 1,
> +		  .maxval = XFS_MAX_AGNUMBER,
>  		  .defaultval = SUBOPT_NEEDS_VAL,
>  		},
>  		{ .index = D_FILE,
> @@ -139,18 +141,26 @@ const 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,
> @@ -164,15 +174,23 @@ const struct opt_params dopts = {
>  		  .defaultval = SUBOPT_NEEDS_VAL,
>  		},
>  		{ .index = D_NOALIGN,
> -		  .defaultval = SUBOPT_NEEDS_VAL,
> +		  .minval = 1,
> +		  .maxval = 1,
> +		  .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,
>  		},
>  	},
> @@ -212,15 +230,23 @@ const 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,
> @@ -262,6 +288,8 @@ const struct opt_params lopts = {
>  	},
>  	.subopt_params = {
>  		{ .index = L_AGNUM,
> +		  .minval = 0,
> +		  .maxval = UINT_MAX,
>  		  .defaultval = SUBOPT_NEEDS_VAL,
>  		},
>  		{ .index = L_INTERNAL,
> @@ -273,9 +301,13 @@ const 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,
> @@ -335,6 +367,8 @@ const struct opt_params nopts = {
>  		  .defaultval = SUBOPT_NEEDS_VAL,
>  		},
>  		{ .index = N_VERSION,
> +		  .minval = 2,
> +		  .maxval = 2,
>  		  .defaultval = SUBOPT_NEEDS_VAL,
>  		},
>  		{ .index = N_FTYPE,
> @@ -1512,13 +1546,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:
> @@ -1553,28 +1585,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')
> @@ -1590,16 +1616,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:
>  					if (dsu)
> @@ -1645,21 +1668,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:
> @@ -1694,18 +1718,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);
> @@ -1714,16 +1733,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);
> @@ -1732,19 +1748,17 @@ 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 =
> @@ -1772,15 +1786,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 (logagno < 0)
> -						illegal(value, "l agno");
> +					logagno = getnum_checked(value, &lopts,
> +								 L_AGNUM);
>  					laflag = 1;
>  					break;
>  				case L_FILE:
> @@ -1817,13 +1828,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:
> @@ -1842,14 +1850,11 @@ 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:
> @@ -1981,11 +1986,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.1.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] 51+ messages in thread

* Re: [PATCH 10/17] mkfs: add respecification detection to generic parsing
  2015-06-19 11:01 ` [PATCH 10/17] mkfs: add respecification detection to generic parsing Jan Ťulák
@ 2015-06-26 17:17   ` Brian Foster
  0 siblings, 0 replies; 51+ messages in thread
From: Brian Foster @ 2015-06-26 17:17 UTC (permalink / raw)
  To: Jan Ťulák; +Cc: Dave Chinner, xfs

On Fri, Jun 19, 2015 at 01:01:59PM +0200, Jan Ťulák wrote:
> From: Dave Chinner <dchinner@redhat.com>
> 
> Add flags to the generic input parameter tables so that
> respecification can be detected in a generic manner.
> 
> Signed-off-by: Dave Chinner <dchinner@redhat.com>
> Signed-off-by: Jan Ťulák <jtulak@redhat.com>
> ---
>  mkfs/xfs_mkfs.c | 68 +++++++++++++++------------------------------------------
>  1 file changed, 18 insertions(+), 50 deletions(-)
> 
> diff --git a/mkfs/xfs_mkfs.c b/mkfs/xfs_mkfs.c
> index 332c491..0bd8998 100644
> --- a/mkfs/xfs_mkfs.c
> +++ b/mkfs/xfs_mkfs.c
> @@ -57,15 +57,17 @@ 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;
>  	}		subopt_params[MAX_SUBOPTS];
>  };
>  
> -const struct opt_params bopts = {
> +struct opt_params bopts = {
>  	.name = 'b',
>  	.subopts = {
>  #define	B_LOG		0
> @@ -88,7 +90,7 @@ const struct opt_params bopts = {
>  	},
>  };
>  
> -const struct opt_params dopts = {
> +struct opt_params dopts = {
>  	.name = 'd',
>  	.subopts = {
>  #define	D_AGCOUNT	0
> @@ -197,7 +199,7 @@ const struct opt_params dopts = {
>  };
>  
>  
> -const struct opt_params iopts = {
> +struct opt_params iopts = {
>  	.name = 'i',
>  	.subopts = {
>  #define	I_ALIGN		0
> @@ -257,7 +259,7 @@ const struct opt_params iopts = {
>  	},
>  };
>  
> -const struct opt_params lopts = {
> +struct opt_params lopts = {
>  	.name = 'l',
>  	.subopts = {
>  #define	L_AGNUM		0
> @@ -342,7 +344,7 @@ const struct opt_params lopts = {
>  	},
>  };
>  
> -const struct opt_params nopts = {
> +struct opt_params nopts = {
>  	.name = 'n',
>  	.subopts = {
>  #define	N_LOG		0
> @@ -379,7 +381,7 @@ const struct opt_params nopts = {
>  	},
>  };
>  
> -const struct opt_params ropts = {
> +struct opt_params ropts = {
>  	.name = 'r',
>  	.subopts = {
>  #define	R_EXTSIZE	0
> @@ -418,7 +420,7 @@ const struct opt_params ropts = {
>  	},
>  };
>  
> -const struct opt_params sopts = {
> +struct opt_params sopts = {

It would be nice to avoid all this noise by dropping the const
specifiers from the earlier patch. Otherwise, looks fine:

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

>  	.name = 's',
>  	.subopts = {
>  #define	S_LOG		0
> @@ -455,7 +457,7 @@ const struct opt_params sopts = {
>  	},
>  };
>  
> -const struct opt_params mopts = {
> +struct opt_params mopts = {
>  	.name = 'm',
>  	.subopts = {
>  #define	M_CRC		0
> @@ -1192,7 +1194,6 @@ struct sb_feat_args {
>  	int	dir_version;
>  	int	spinodes;
>  	int	finobt;
> -	bool	finobtflag;
>  	bool	inode_align;
>  	bool	nci;
>  	bool	lazy_sb_counters;
> @@ -1323,10 +1324,10 @@ illegal_option(
>  static int
>  getnum_checked(
>  	const char		*str,
> -	const struct opt_params	*opts,
> +	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) {
> @@ -1336,6 +1337,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);
> @@ -1446,7 +1452,6 @@ main(
>  	struct fs_topology	ft;
>  	struct sb_feat_args	sb_feat = {
>  		.finobt = 1,
> -		.finobtflag = false,
>  		.spinodes = 0,
>  		.log_version = 2,
>  		.attr_version = 2,
> @@ -1506,8 +1511,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);
> @@ -1546,9 +1549,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;
> @@ -1585,8 +1585,6 @@ main(
>  					dsize = value;
>  					break;
>  				case D_SUNIT:
> -					if (dsunit)
> -						respec('d', subopts, D_SUNIT);
>  					if (nodsflag)
>  						conflict('d', subopts, D_NOALIGN,
>  							 D_SUNIT);
> @@ -1594,8 +1592,6 @@ main(
>  								 D_SUNIT);
>  					break;
>  				case D_SWIDTH:
> -					if (dswidth)
> -						respec('d', subopts, D_SWIDTH);
>  					if (nodsflag)
>  						conflict('d', subopts, D_NOALIGN,
>  							 D_SWIDTH);
> @@ -1616,8 +1612,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);
> @@ -1640,8 +1634,6 @@ main(
>  					nodsflag = 1;
>  					break;
>  				case D_SECTLOG:
> -					if (slflag)
> -						respec('d', subopts, D_SECTLOG);
>  					if (ssflag)
>  						conflict('d', subopts, D_SECTSIZE,
>  							 D_SECTLOG);
> @@ -1704,8 +1696,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);
> @@ -1718,8 +1708,6 @@ main(
>  					ilflag = 1;
>  					break;
>  				case I_MAXPCT:
> -					if (imflag)
> -						respec('i', subopts, I_MAXPCT);
>  					imaxpct = getnum_checked(value, &iopts,
>  								 I_MAXPCT);
>  					imflag = 1;
> @@ -1728,8 +1716,6 @@ main(
>  					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);
> @@ -1746,8 +1732,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))
> @@ -1786,8 +1770,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,
> @@ -1809,8 +1791,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);
> @@ -1828,8 +1808,6 @@ main(
>  					lsuflag = 1;
>  					break;
>  				case L_SUNIT:
> -					if (lsunit)
> -						respec('l', subopts, L_SUNIT);
>  					lsunit = getnum_checked(value, &lopts,
>  								 L_SUNIT);
>  					lsunitflag = 1;
> @@ -1850,8 +1828,6 @@ 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);
> @@ -1866,8 +1842,6 @@ main(
>  					lsflag = 1;
>  					break;
>  				case L_SECTLOG:
> -					if (lslflag)
> -						respec('l', subopts, L_SECTLOG);
>  					if (lssflag)
>  						conflict('l', subopts, L_SECTSIZE,
>  							 L_SECTLOG);
> @@ -1950,8 +1924,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);
> @@ -1994,8 +1966,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"));
> @@ -2078,8 +2048,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);
> @@ -2296,7 +2264,7 @@ _("32 bit Project IDs always enabled on CRC enabled filesytems\n"));
>  		 * tried to use crc=0,finobt=1, then issue a warning before
>  		 * turning them off.
>  		 */
> -		if (sb_feat.finobt && sb_feat.finobtflag) {
> +		if (sb_feat.finobt && mopts.subopt_params[M_FINOBT].seen) {
>  			fprintf(stderr,
>  _("warning: finobt not supported without CRC support, disabled.\n"));
>  			sb_feat.finobt = 0;
> -- 
> 2.1.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] 51+ messages in thread

* Re: [PATCH 11/17] mkfs: table based parsing for converted parameters
  2015-06-19 11:02 ` [PATCH 11/17] mkfs: table based parsing for converted parameters Jan Ťulák
@ 2015-06-26 17:17   ` Brian Foster
  0 siblings, 0 replies; 51+ messages in thread
From: Brian Foster @ 2015-06-26 17:17 UTC (permalink / raw)
  To: Jan Ťulák; +Cc: Dave Chinner, xfs

On Fri, Jun 19, 2015 at 01:02:00PM +0200, Jan Ťulák wrote:
> From: Dave Chinner <dchinner@redhat.com>
> 
> All the parameters that can be passed as block or sector sizes need
> to be passed the block and sector sizes that they should be using
> for conversion. For parameter parsing, it is always the same two
> variables, so to make things easy just declare them as global
> variables so we can avoid needing to pass them to getnum_checked().
> 
> We also need to mark these parameters are requiring conversion so
> that we don't need to pass this information manually to
> getnum_checked(). Further, some of these options are required to
> have a power of 2 value, so add optional checking for that as well.
> 
> Signed-off-by: Dave Chinner <dchinner@redhat.com>
> Signed-off-by: Jan Ťulák <jtulak@redhat.com>
> ---

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

>  mkfs/xfs_mkfs.c | 171 ++++++++++++++++++++++----------------------------------
>  1 file changed, 68 insertions(+), 103 deletions(-)
> 
> diff --git a/mkfs/xfs_mkfs.c b/mkfs/xfs_mkfs.c
> index 0bd8998..4fc1f34 100644
> --- a/mkfs/xfs_mkfs.c
> +++ b/mkfs/xfs_mkfs.c
> @@ -52,6 +52,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)
>  struct opt_params {
> @@ -61,6 +68,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;
> @@ -83,6 +92,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,
> @@ -140,6 +151,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,
> @@ -153,11 +167,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,
> @@ -171,6 +189,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,
> @@ -237,11 +257,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,
> @@ -300,6 +322,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,
> @@ -313,6 +338,9 @@ struct opt_params lopts = {
>  		  .defaultval = SUBOPT_NEEDS_VAL,
>  		},
>  		{ .index = L_SU,
> +		  .convert = true,
> +		  .minval = XLOG_MIN_RECORD_BSIZE,
> +		  .maxval = XLOG_MAX_RECORD_BSIZE,
>  		  .defaultval = SUBOPT_NEEDS_VAL,
>  		},
>  		{ .index = L_DEV,
> @@ -324,6 +352,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,
> @@ -364,6 +394,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,
> @@ -400,9 +432,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,
> @@ -445,11 +483,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,
> @@ -1291,15 +1333,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)
> @@ -1348,9 +1390,11 @@ getnum_checked(
>  		return sp->defaultval;
>  	}
>  
> -	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;
>  }
>  
> @@ -1368,7 +1412,6 @@ main(
>  	struct xfs_btree_block	*block;
>  	int			blflag;
>  	int			blocklog;
> -	unsigned int		blocksize;
>  	int			bsflag;
>  	int			bsize;
>  	xfs_buf_t		*buf;
> @@ -1441,7 +1484,6 @@ main(
>  	char			*rtsize;
>  	xfs_sb_t		*sbp;
>  	int			sectorlog;
> -	unsigned int		sectorsize;
>  	__uint64_t		sector_mask;
>  	int			slflag;
>  	int			ssflag;
> @@ -1520,18 +1562,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;
> @@ -1554,14 +1589,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:
> @@ -1599,17 +1628,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)
> @@ -1643,18 +1666,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;
> @@ -1721,8 +1737,6 @@ main(
>  							 I_PERBLOCK);
>  					inopblock = getnum_checked(value, &iopts,
>  								   I_PERBLOCK);
> -					if (!ispow2(inopblock))
> -						illegal(value, "i perblock");
>  					ipflag = 1;
>  					break;
>  				case I_SIZE:
> @@ -1734,8 +1748,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;
> @@ -1797,14 +1809,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:
> @@ -1851,18 +1857,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;
> @@ -1933,18 +1932,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;
> @@ -2060,18 +2052,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);
> @@ -2306,9 +2291,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"),
> @@ -2345,9 +2328,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"),
> @@ -2369,9 +2350,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"),
> @@ -2391,27 +2370,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.1.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] 51+ messages in thread

* Re: [PATCH 12/17] mkfs: merge getnum
  2015-06-19 11:02 ` [PATCH 12/17] mkfs: merge getnum Jan Ťulák
@ 2015-06-26 17:17   ` Brian Foster
  0 siblings, 0 replies; 51+ messages in thread
From: Brian Foster @ 2015-06-26 17:17 UTC (permalink / raw)
  To: Jan Ťulák; +Cc: Dave Chinner, xfs

On Fri, Jun 19, 2015 at 01:02:01PM +0200, Jan Ťulák wrote:
> From: Dave Chinner <dchinner@redhat.com>
> 
> getnum() is now only called by getnum_checked(). Move the two
> together into a single getnum() function and change all the callers
> back to getnum().
> 
> Signed-off-by: Dave Chinner <dchinner@redhat.com>
> Signed-off-by: Jan Ťulák <jtulak@redhat.com>
> ---
>  include/xfs_mkfs.h |   4 +-
>  mkfs/proto.c       |  20 ++++++
>  mkfs/xfs_mkfs.c    | 202 ++++++++++++++++++++++++-----------------------------
>  3 files changed, 113 insertions(+), 113 deletions(-)
> 
> diff --git a/include/xfs_mkfs.h b/include/xfs_mkfs.h
> index f5639b0..a4312e1 100644
> --- a/include/xfs_mkfs.h
> +++ b/include/xfs_mkfs.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 a2a61e0..1e763a0 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 4fc1f34..e52fd4e 100644
> --- a/mkfs/xfs_mkfs.c
> +++ b/mkfs/xfs_mkfs.c
> @@ -49,9 +49,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.
> @@ -1330,27 +1327,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,
> @@ -1363,8 +1339,8 @@ illegal_option(
>  	usage();
>  }
>  
> -static int
> -getnum_checked(
> +static long long
> +getnum(
>  	const char		*str,
>  	struct opt_params	*opts,
>  	int			index)
> @@ -1384,13 +1360,32 @@ 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);
>  		return sp->defaultval;
>  	}
>  
> -	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		*sp;
> +
> +		c = strtoll(str, &sp, 0);
> +		if (c == 0 && sp == str)
> +			illegal_option(str, opts, index);
> +		if (*sp != '\0')
> +			illegal_option(str, opts, index);
> +	}
> +

Hrm, why not continue to reuse this code? E.g., give the getnum() from
proto.c a better name and call that. Otherwise, this seems fine.

Brian

> +	/* Validity check the result. */
>  	if (c < sp->minval || c > sp->maxval)
>  		illegal_option(str, opts, index);
>  	if (sp->is_power_2 && !ispow2(c))
> @@ -1556,8 +1551,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;
> @@ -1565,8 +1559,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;
> @@ -1584,18 +1578,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;
> @@ -1617,29 +1610,26 @@ 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:
>  					if (dsu)
> @@ -1660,8 +1650,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;
> @@ -1669,28 +1659,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;
> @@ -1708,8 +1697,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)
> @@ -1718,14 +1707,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:
> @@ -1735,8 +1723,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:
> @@ -1746,20 +1734,18 @@ 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);
> +						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:
>  					if (!value || *value == '\0')
> @@ -1784,16 +1770,15 @@ 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:
>  					if (loginternal)
>  						conflict('l', subopts, L_INTERNAL,
>  							 L_FILE);
> -					xi.lisfile = getnum_checked(value,
> -								&lopts, L_FILE);
> +					xi.lisfile = getnum(value, &lopts,
> +							    L_FILE);
>  					if (xi.lisfile)
>  						xi.lcreat = 1;
>  					break;
> @@ -1804,18 +1789,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:
> @@ -1835,8 +1818,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:
> @@ -1851,8 +1833,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;
> @@ -1860,15 +1842,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:
> @@ -1891,8 +1873,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"));
> @@ -1926,8 +1907,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;
> @@ -1935,8 +1916,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;
> @@ -1951,9 +1932,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;
> @@ -1963,8 +1943,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:
> @@ -2002,8 +1982,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;
> @@ -2043,8 +2023,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;
> @@ -2055,8 +2035,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);
> @@ -2291,7 +2271,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"),
> @@ -2328,7 +2308,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"),
> @@ -2350,7 +2330,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"),
> @@ -2370,7 +2350,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"),
> @@ -3466,8 +3446,8 @@ unknown(
>  
>  long long
>  cvtnum(
> -	unsigned int	blocksize,
> -	unsigned int	sectorsize,
> +	unsigned int	blksize,
> +	unsigned int	sectsize,
>  	const char	*s)
>  {
>  	long long	i;
> @@ -3480,9 +3460,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.1.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] 51+ messages in thread

* Re: [PATCH 13/17] mkfs: encode conflicts into parsing table
  2015-06-19 11:02 ` [PATCH 13/17] mkfs: encode conflicts into parsing table Jan Ťulák
@ 2015-06-26 17:17   ` Brian Foster
  2015-06-30  3:57     ` Dave Chinner
  0 siblings, 1 reply; 51+ messages in thread
From: Brian Foster @ 2015-06-26 17:17 UTC (permalink / raw)
  To: Jan Ťulák; +Cc: Dave Chinner, xfs

On Fri, Jun 19, 2015 at 01:02:02PM +0200, Jan Ťulák wrote:
> From: Dave Chinner <dchinner@redhat.com>
> 
> Many options conflict, so we need to specify which options conflict
> with each other in a generic manner. We already have a "seen"
> variable used for respecification detection, so we can also use this
> code conflict detection. Hence add a "conflicts" array to the sub
> options parameter definition.
> 
> Signed-off-by: Dave Chinner <dchinner@redhat.com>
> Signed-off-by: Jan Ťulák <jtulak@redhat.com>
> ---
>  mkfs/xfs_mkfs.c | 248 ++++++++++++++++++++++++++++----------------------------
>  1 file changed, 125 insertions(+), 123 deletions(-)
> 
> diff --git a/mkfs/xfs_mkfs.c b/mkfs/xfs_mkfs.c
> index e52fd4e..1d80188 100644
> --- a/mkfs/xfs_mkfs.c
> +++ b/mkfs/xfs_mkfs.c
> @@ -58,6 +58,9 @@ unsigned int		sectorsize;
>  
>  #define MAX_SUBOPTS	16
>  #define SUBOPT_NEEDS_VAL	(-1LL)
> +
> +#define MAX_CONFLICTS	8
> +#define LAST_CONFLICT	(-1)
>  struct opt_params {
>  	const char	name;
>  	const char	*subopts[MAX_SUBOPTS];
...
>  #ifdef ENABLE_BLKID
> @@ -1360,6 +1433,16 @@ 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);

Long line.

> +	}
> +
>  	/* empty strings might just return a default value */
>  	if (!str || *str == '\0') {
>  		if (sp->defaultval == SUBOPT_NEEDS_VAL)
...
> @@ -2020,7 +2027,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,
> @@ -2032,7 +2039,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);

Hmm.. so is the limitation here that we can't do generic conflict
detection across different option structs? If so, I suppose that's not
the end of the world. The cleanup is still well worth it. I wonder if we
still need to set lslflag/lssflag in either of the above cases, though.
It seems like the generic detection should handle it..?

Also, I'd expect some documentation somewhere up where the option struct
is defined to clearly state any such rules.

Brian

>  					sectorsize = getnum(value, &sopts,
> @@ -2257,11 +2264,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.1.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] 51+ messages in thread

* Re: [PATCH 14/17] mkfs: add string options to generic parsing
  2015-06-19 11:02 ` [PATCH 14/17] mkfs: add string options to generic parsing Jan Ťulák
@ 2015-06-26 19:32   ` Brian Foster
  0 siblings, 0 replies; 51+ messages in thread
From: Brian Foster @ 2015-06-26 19:32 UTC (permalink / raw)
  To: Jan Ťulák; +Cc: Dave Chinner, xfs

On Fri, Jun 19, 2015 at 01:02:03PM +0200, Jan Ťulák wrote:
> From: Dave Chinner <dchinner@redhat.com>
> 
> So that string options are correctly detected for conflicts and
> respecification, add a getstr() function that modifies the option
> tables appropriately.
> 
> Signed-off-by: Dave Chinner <dchinner@redhat.com>
> Signed-off-by: Jan Ťulák <jtulak@redhat.com>
> ---

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

>  mkfs/xfs_mkfs.c | 127 +++++++++++++++++++++++++++++++-------------------------
>  1 file changed, 70 insertions(+), 57 deletions(-)
> 
> diff --git a/mkfs/xfs_mkfs.c b/mkfs/xfs_mkfs.c
> index 1d80188..6bfa73c 100644
> --- a/mkfs/xfs_mkfs.c
> +++ b/mkfs/xfs_mkfs.c
> @@ -68,6 +68,7 @@ struct opt_params {
>  	struct subopt_param {
>  		int		index;
>  		bool		seen;
> +		bool		str_seen;
>  		bool		convert;
>  		bool		is_power_2;
>  		int		conflicts[MAX_CONFLICTS];
> @@ -1412,14 +1413,15 @@ illegal_option(
>  	usage();
>  }
>  
> -static long long
> -getnum(
> +static void
> +check_opt(
>  	const char		*str,
>  	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,
> @@ -1428,21 +1430,46 @@ 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(str, opts, index, false);
>  	/* empty strings might just return a default value */
>  	if (!str || *str == '\0') {
>  		if (sp->defaultval == SUBOPT_NEEDS_VAL)
> @@ -1476,6 +1503,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(str, 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,
> @@ -1670,18 +1717,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);
> @@ -1822,18 +1861,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 =
> @@ -1841,12 +1872,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,
> @@ -1930,10 +1956,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;
> @@ -1982,11 +2005,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,
> @@ -1996,18 +2016,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 = 1;
> -- 
> 2.1.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] 51+ messages in thread

* Re: [PATCH 15/17] mkfs: don't treat files as though they are block devices
  2015-06-19 11:02 ` [PATCH 15/17] mkfs: don't treat files as though they are block devices Jan Ťulák
@ 2015-06-26 19:32   ` Brian Foster
  0 siblings, 0 replies; 51+ messages in thread
From: Brian Foster @ 2015-06-26 19:32 UTC (permalink / raw)
  To: Jan Ťulák; +Cc: Dave Chinner, xfs

On Fri, Jun 19, 2015 at 01:02:04PM +0200, Jan Ťulák wrote:
> From: Dave Chinner <dchinner@redhat.com>
> 
> If the device is actually a file, and "-d file" is not specified,
> mkfs will try to treat it as a block device and get stuff wrong.
> Image files don't necessarily have the same sector sizes as the
> block device or filesystem underlying the image file, nor should we
> be issuing discard ioctls on image files.
> 
> To fix this sanely, only require "-d file" if the device name is
> invalid to trigger creation of the file. Otherwise, use stat() to
> determine if the device is a file or block device and deal with that
> appropriately by setting the "isfile" variables and turning off
> direct IO. Then ensure that we check the "isfile" options before
> doing things that are specific to block devices.
> 
> Other file/blockdev issues fixed:
> 	- use getstr to detect specifying the data device name
> 	  twice.
> 	- check file/size/name parameters before anything else.
> 	- overwrite checks need to be done before the image file is
> 	  opened and potentially truncated.
> 	- blkid_get_topology() should not be called for image files,
> 	  so warn when it is called that way.
> 	- zero_old_xfs_structures() emits a spurious error:
> 		"existing superblock read failed: Success"
> 	  when it is run on a truncated image file. Don't warn if we
> 	  see this problem on an image file.
> 	- Don't issue discards on image files.
> 	- Use fsync() for image files, not BLKFLSBUF in
> 	  platform_flush_device() for Linux.
> 
> Signed-off-by: Dave Chinner <dchinner@redhat.com>
> Signed-off-by: Jan Ťulák <jtulak@redhat.com>
> ---
>  libxfs/init.c   |   4 ++
>  libxfs/linux.c  |  11 +++-
>  mkfs/xfs_mkfs.c | 164 +++++++++++++++++++++++++++++++++++++++-----------------
>  3 files changed, 129 insertions(+), 50 deletions(-)
> 
> diff --git a/libxfs/init.c b/libxfs/init.c
> index 6f404aa..ed97043 100644
> --- a/libxfs/init.c
> +++ b/libxfs/init.c
> @@ -246,6 +246,7 @@ libxfs_init(libxfs_init_t *a)
>  	char		rtpath[25];
>  	int		rval = 0;
>  	int		flags;
> +	struct stat st;

Variable alignment.

>  
>  	dpath[0] = logpath[0] = rtpath[0] = '\0';
>  	dname = a->dname;
> @@ -278,6 +279,9 @@ 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);
> +			stat(dname, &st);
> +			a->dsize = st.st_size;
> +			a->dbsize = st.st_blksize;

Error handling?

>  		} else {
>  			if (!check_open(dname, flags, &rawfile, &blockfile))
>  				goto done;
> diff --git a/libxfs/linux.c b/libxfs/linux.c
> index 885016a..49d430c 100644
> --- a/libxfs/linux.c
> +++ b/libxfs/linux.c
> @@ -125,7 +125,16 @@ platform_set_blocksize(int fd, char *path, dev_t device, int blocksize, int fata
>  void
>  platform_flush_device(int fd, dev_t device)
>  {
> -	if (major(device) != RAMDISK_MAJOR)
> +	struct stat64	st;
> +	if (major(device) == RAMDISK_MAJOR)
> +		return;
> +
> +	if (fstat64(fd, &st) < 0)
> +		return;
> +
> +	if (S_ISREG(st.st_mode))
> +		fsync(fd);
> +	else
>  		ioctl(fd, BLKFLSBUF, 0);
>  }
>  
> diff --git a/mkfs/xfs_mkfs.c b/mkfs/xfs_mkfs.c
> index 6bfa73c..ce64230 100644
> --- a/mkfs/xfs_mkfs.c
> +++ b/mkfs/xfs_mkfs.c
> @@ -705,7 +705,7 @@ calc_stripe_factors(
>   */
>  static int
>  check_overwrite(
> -	char		*device)
> +	const char	*device)
>  {
>  	const char	*type;
>  	blkid_probe	pr = NULL;
> @@ -722,7 +722,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 */
> @@ -769,7 +769,6 @@ check_overwrite(
>  			"according to blkid\n"), progname, device);
>  	}
>  	ret = 1;
> -
>  out:
>  	if (pr)
>  		blkid_free_probe(pr);
> @@ -795,8 +794,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)
> @@ -899,7 +902,7 @@ static void get_topology(
>  #else /* ENABLE_BLKID */
>  static int
>  check_overwrite(
> -	char		*device)
> +	const char	*device)
>  {
>  	char		*type;
>  
> @@ -956,6 +959,75 @@ static void get_topology(
>  #endif /* ENABLE_BLKID */
>  
>  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,
> @@ -1245,9 +1317,18 @@ zero_old_xfs_structures(
>  			strerror(errno));
>  		goto done;
>  	}
> -	if (tmp != new_sb->sb_sectsize) {
> -		fprintf(stderr,
> -	_("warning: could not read existing superblock, skip zeroing\n"));
> +	/*
> +	 * If we are creating an image file, it might be of zero length at this
> +	 * point in time. Hence reading the existing superblock is going to
> +	 * return zero bytes. It's not a failure we need to warn about in this
> +	 * case.
> +	 */
> +	off = pread(xi->dfd, buf, new_sb->sb_sectsize, 0);
> +	if (off != new_sb->sb_sectsize) {
> +		if (!xi->disfile)
> +			fprintf(stderr,
> +	_("error reading existing superblock: %s\n"),
> +				strerror(errno));

This appears to be duplicate code. See the immediately previous pread()
in zero_old_xfs_structures().

>  		goto done;
>  	}
>  	libxfs_sb_from_disk(&sb, buf);
> @@ -1713,8 +1794,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);
> @@ -1843,8 +1922,6 @@ main(
>  				case L_FILE:
>  					xi.lisfile = getnum(value, &lopts,
>  							    L_FILE);
> -					if (xi.lisfile)
> -						xi.lcreat = 1;
>  					break;
>  				case L_INTERNAL:
>  					loginternal = getnum(value, &lopts,
> @@ -2011,8 +2088,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:
> @@ -2079,13 +2154,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);

Shouldn't this be part of the previous patch?

Brian

>  	} else
>  		dfile = xi.dname;
>  
> @@ -2118,6 +2187,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, !xi.dname,
> +			  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);
>  
> @@ -2278,11 +2367,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;
>  
> @@ -2315,11 +2399,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;
>  
> @@ -2337,11 +2416,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;
>  
> @@ -2463,22 +2537,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.1.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] 51+ messages in thread

* Re: [PATCH 16/17] mkfs fix: handling of files
  2015-06-19 11:02 ` [PATCH 16/17] mkfs fix: handling of files Jan Ťulák
@ 2015-06-26 19:32   ` Brian Foster
  0 siblings, 0 replies; 51+ messages in thread
From: Brian Foster @ 2015-06-26 19:32 UTC (permalink / raw)
  To: Jan Ťulák; +Cc: xfs

On Fri, Jun 19, 2015 at 01:02:05PM +0200, Jan Ťulák wrote:
> If mkfs is making a FS in a file, then the new FS should take host FS blocksize
> as sectorsize. This patch is ensuring it by using statfs() instead of stat()
> and platform_findsizes().
> 
> Signed-off-by: Jan Ťulák <jtulak@redhat.com>
> ---
>  libxfs/init.c   |  7 +++++--
>  mkfs/xfs_mkfs.c | 54 +++++++++++++++++++++++++++++-------------------------
>  2 files changed, 34 insertions(+), 27 deletions(-)
> 
> diff --git a/libxfs/init.c b/libxfs/init.c
> index ed97043..02d152c 100644
> --- a/libxfs/init.c
> +++ b/libxfs/init.c
> @@ -17,6 +17,7 @@
>   */
>  
>  #include <sys/stat.h>
> +#include <sys/vfs.h>
>  #include "init.h"
>  
>  #include "libxfs_priv.h"
> @@ -247,6 +248,7 @@ libxfs_init(libxfs_init_t *a)
>  	int		rval = 0;
>  	int		flags;
>  	struct stat st;
> +	struct statfs stfs;
>  
>  	dpath[0] = logpath[0] = rtpath[0] = '\0';
>  	dname = a->dname;
> @@ -280,8 +282,9 @@ libxfs_init(libxfs_init_t *a)
>  						    a->setblksize);
>  			a->dfd = libxfs_device_to_fd(a->ddev);
>  			stat(dname, &st);
> -			a->dsize = st.st_size;
> -			a->dbsize = st.st_blksize;
> +			statfs(dname, &stfs);
> +			a->dsize = st.st_size/BBSIZE;

Ok, if this should be in basic blocks, can we fix it in the previous
patch where the code was introduced? Otherwise this seems Ok.

Brian

> +			a->dbsize = stfs.f_bsize;
>  		} else {
>  			if (!check_open(dname, flags, &rawfile, &blockfile))
>  				goto done;
> diff --git a/mkfs/xfs_mkfs.c b/mkfs/xfs_mkfs.c
> index ce64230..2e455db 100644
> --- a/mkfs/xfs_mkfs.c
> +++ b/mkfs/xfs_mkfs.c
> @@ -18,6 +18,7 @@
>  
>  #include <xfs/libxfs.h>
>  #include <ctype.h>
> +#include <sys/vfs.h>
>  #ifdef ENABLE_BLKID
>  #include <blkid/blkid.h>
>  #else
> @@ -865,31 +866,23 @@ static void get_topology(
>  	struct fs_topology	*ft,
>  	int			force_overwrite)
>  {
> -	if (!xi->disfile) {
> -		char *dfile = xi->volname ? xi->volname : xi->dname;
> -		struct stat statbuf;
> +	char *dfile = xi->volname ? xi->volname : xi->dname;
> +	struct stat statbuf;
> +	struct statfs statfsbuf;
>  
> -		/*
> -		 * If our target is a regular file, and xi->disfile isn't
> -		 * set (i.e. no "-d file" invocation), 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 (!stat(dfile, &statbuf) && S_ISREG(statbuf.st_mode)) {
> -			int fd;
> -			long long dummy;
> -
> -			fd = open(dfile, O_RDONLY);
> -			if (fd >= 0) {
> -				platform_findsizes(dfile, fd, &dummy,
> -						   &ft->lsectorsize);
> -				close(fd);
> -			}
> -		} else {
> -			blkid_get_topology(dfile, &ft->dsunit, &ft->dswidth,
> -					   &ft->lsectorsize, &ft->psectorsize,
> -					   force_overwrite);
> -		}
> +	/*
> +	 * 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))) {
> +
> +		statfs(dfile, &statfsbuf);
> +		ft->lsectorsize = statfsbuf.f_bsize;
> +	} else {
> +		blkid_get_topology(dfile, &ft->dsunit, &ft->dswidth,
> +					&ft->lsectorsize, &ft->psectorsize,
> +					force_overwrite);
>  	}
>  
>  	if (xi->rtname && !xi->risfile) {
> @@ -930,9 +923,20 @@ static void get_topology(
>  {
>  
>  	char *dfile = xi->volname ? xi->volname : xi->dname;
> +	struct stat statbuf;
> +	struct statfs statfsbuf;
>  	int bsz = BBSIZE;
>  
> -	if (!xi->disfile) {
> +	/*
> +	 * 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))) {
> +
> +		statfs(dfile, &statfsbuf);
> +		bsz = statfsbuf.f_bsize;
> +	} else {
>  		int fd;
>  		long long dummy;
>  
> -- 
> 2.1.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] 51+ messages in thread

* Re: [PATCH 17/17] mkfs: move spinodes crc check
  2015-06-19 11:02 ` [PATCH 17/17] mkfs: move spinodes crc check Jan Ťulák
@ 2015-06-26 19:32   ` Brian Foster
  0 siblings, 0 replies; 51+ messages in thread
From: Brian Foster @ 2015-06-26 19:32 UTC (permalink / raw)
  To: Jan Ťulák; +Cc: xfs

On Fri, Jun 19, 2015 at 01:02:06PM +0200, Jan Ťulák wrote:
> Spinodes crc check is now moved to be in the same way as finobt.
> 
> Signed-off-by: Jan Ťulák <jtulak@redhat.com>
> ---

Seems fine:

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 2e455db..653fc5b 100644
> --- a/mkfs/xfs_mkfs.c
> +++ b/mkfs/xfs_mkfs.c
> @@ -2347,12 +2347,13 @@ _("32 bit Project IDs always enabled on CRC enabled filesytems\n"));
>  _("warning: finobt not supported without CRC support, disabled.\n"));
>  			sb_feat.finobt = 0;
>  		}
> -	}
>  
> -	if (sb_feat.spinodes && !sb_feat.crcs_enabled) {
> -		fprintf(stderr,
> -_("warning: sparse inodes not supported without CRC support, disabled.\n"));
> -		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.1.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] 51+ messages in thread

* Re: [PATCH 08/17] mkfs: getbool is redundant
  2015-06-26 17:17   ` Brian Foster
@ 2015-06-30  1:32     ` Dave Chinner
  0 siblings, 0 replies; 51+ messages in thread
From: Dave Chinner @ 2015-06-30  1:32 UTC (permalink / raw)
  To: Brian Foster; +Cc: xfs, Dave Chinner, Jan Ťulák

On Fri, Jun 26, 2015 at 01:17:01PM -0400, Brian Foster wrote:
> On Fri, Jun 19, 2015 at 01:01:57PM +0200, Jan Ťulák wrote:
> > From: Dave Chinner <dchinner@redhat.com>
> > 
> > getbool() can be replaced with getnum_checked with appropriate
> > min/max values set for the boolean variables.
> > 
> > Signed-off-by: Dave Chinner <dchinner@redhat.com>
> > Signed-off-by: Jan Ťulák <jtulak@redhat.com>
....
> >  		},
> >  		{ .index = R_NAME,
> > +		  .defaultval = SUBOPT_NEEDS_VAL,
> >  		},
> >  		{ .index = R_NOALIGN,
> > +		  .defaultval = SUBOPT_NEEDS_VAL,
> 
> Not sure about this one, either. There's no value according to the man
> page.

Keep in mind one of the reasons for doing this cleanup is to make
all the options consistent in their handling. i.e. all boolean
options will take a 0 or 1 value, regardless of whether they
currently require it or not.

i.e. this patchset changes the mkfs CLI interface to fix
inconsistencies that have crept in over the years....

Cheers,

Dave.
-- 
Dave Chinner
david@fromorbit.com

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

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

* Re: [PATCH 13/17] mkfs: encode conflicts into parsing table
  2015-06-26 17:17   ` Brian Foster
@ 2015-06-30  3:57     ` Dave Chinner
  2015-06-30 11:27       ` Brian Foster
  0 siblings, 1 reply; 51+ messages in thread
From: Dave Chinner @ 2015-06-30  3:57 UTC (permalink / raw)
  To: Brian Foster; +Cc: xfs, Dave Chinner, Jan Ťulák

On Fri, Jun 26, 2015 at 01:17:31PM -0400, Brian Foster wrote:
> On Fri, Jun 19, 2015 at 01:02:02PM +0200, Jan Ťulák wrote:
> > From: Dave Chinner <dchinner@redhat.com>
> > 
> > Many options conflict, so we need to specify which options conflict
> > with each other in a generic manner. We already have a "seen"
> > variable used for respecification detection, so we can also use this
> > code conflict detection. Hence add a "conflicts" array to the sub
> > options parameter definition.
.....
> > @@ -2020,7 +2027,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,
> > @@ -2032,7 +2039,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);
> 
> Hmm.. so is the limitation here that we can't do generic conflict
> detection across different option structs? If so, I suppose that's not
> the end of the world. The cleanup is still well worth it.

I just never got around to coding it in a generic fashion - I didn't
finish the entire patchset back when I originally wrote it....

> I wonder if we
> still need to set lslflag/lssflag in either of the above cases, though.
> It seems like the generic detection should handle it..?

In the end it would look at the relevant ->seen flag to determine
if there was a cross-option-struct conflict. Essentially, the
conflict definition needs to define conflicts via a {group, option}
tuple rather than just the {option} it uses now...

-Dave.
-- 
Dave Chinner
david@fromorbit.com

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

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

* Re: [PATCH 13/17] mkfs: encode conflicts into parsing table
  2015-06-30  3:57     ` Dave Chinner
@ 2015-06-30 11:27       ` Brian Foster
  2015-07-01  8:30         ` Jan Tulak
  0 siblings, 1 reply; 51+ messages in thread
From: Brian Foster @ 2015-06-30 11:27 UTC (permalink / raw)
  To: Dave Chinner; +Cc: Jan Ťulák, Dave Chinner, xfs

On Tue, Jun 30, 2015 at 01:57:36PM +1000, Dave Chinner wrote:
> On Fri, Jun 26, 2015 at 01:17:31PM -0400, Brian Foster wrote:
> > On Fri, Jun 19, 2015 at 01:02:02PM +0200, Jan Ťulák wrote:
> > > From: Dave Chinner <dchinner@redhat.com>
> > > 
> > > Many options conflict, so we need to specify which options conflict
> > > with each other in a generic manner. We already have a "seen"
> > > variable used for respecification detection, so we can also use this
> > > code conflict detection. Hence add a "conflicts" array to the sub
> > > options parameter definition.
> .....
> > > @@ -2020,7 +2027,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,
> > > @@ -2032,7 +2039,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);
> > 
> > Hmm.. so is the limitation here that we can't do generic conflict
> > detection across different option structs? If so, I suppose that's not
> > the end of the world. The cleanup is still well worth it.
> 
> I just never got around to coding it in a generic fashion - I didn't
> finish the entire patchset back when I originally wrote it....
> 

Ok. Well I don't know if Jan is up for adding that or what. :) I
wouldn't be against getting this in as is so it isn't held off longer.
It still needs a comment though. ;)

> > I wonder if we
> > still need to set lslflag/lssflag in either of the above cases, though.
> > It seems like the generic detection should handle it..?
> 
> In the end it would look at the relevant ->seen flag to determine
> if there was a cross-option-struct conflict. Essentially, the
> conflict definition needs to define conflicts via a {group, option}
> tuple rather than just the {option} it uses now...
> 

Sure. Not a huge deal, but to be clear my comment here was with respect
to the fact that we set lslflag and lssflag in those two
S_SECTLOG/S_SECTSIZE blocks. I suspect we still need the flag for the
L_SECT* conflict, but it looks like the generic code now handles the
conflict within the 's' group of options. In other words, we have
duplicate handling of the S_SECTLOG/S_SECTSIZE conflict after this
patch.

Brian

> -Dave.
> -- 
> Dave Chinner
> david@fromorbit.com
> 
> _______________________________________________
> xfs mailing list
> xfs@oss.sgi.com
> http://oss.sgi.com/mailman/listinfo/xfs

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

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

* Re: [PATCH 13/17] mkfs: encode conflicts into parsing table
  2015-06-30 11:27       ` Brian Foster
@ 2015-07-01  8:30         ` Jan Tulak
  0 siblings, 0 replies; 51+ messages in thread
From: Jan Tulak @ 2015-07-01  8:30 UTC (permalink / raw)
  To: Brian Foster; +Cc: xfs, Dave Chinner



----- Original Message -----
> From: "Brian Foster" <bfoster@redhat.com>
> To: "Dave Chinner" <david@fromorbit.com>
> Cc: "Jan Ťulák" <jtulak@redhat.com>, "Dave Chinner" <dchinner@redhat.com>, xfs@oss.sgi.com
> Sent: Tuesday, June 30, 2015 1:27:40 PM
> Subject: Re: [PATCH 13/17] mkfs: encode conflicts into parsing table
> 
> On Tue, Jun 30, 2015 at 01:57:36PM +1000, Dave Chinner wrote:
> > On Fri, Jun 26, 2015 at 01:17:31PM -0400, Brian Foster wrote:
> > > On Fri, Jun 19, 2015 at 01:02:02PM +0200, Jan Ťulák wrote:
> > > > From: Dave Chinner <dchinner@redhat.com>
> > > > 
> > > > Many options conflict, so we need to specify which options conflict
> > > > with each other in a generic manner. We already have a "seen"
> > > > variable used for respecification detection, so we can also use this
> > > > code conflict detection. Hence add a "conflicts" array to the sub
> > > > options parameter definition.
> > .....
> > > > @@ -2020,7 +2027,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,
> > > > @@ -2032,7 +2039,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);
> > > 
> > > Hmm.. so is the limitation here that we can't do generic conflict
> > > detection across different option structs? If so, I suppose that's not
> > > the end of the world. The cleanup is still well worth it.
> > 
> > I just never got around to coding it in a generic fashion - I didn't
> > finish the entire patchset back when I originally wrote it....
> > 
> 
> Ok. Well I don't know if Jan is up for adding that or what. :) I
> wouldn't be against getting this in as is so it isn't held off longer.
> It still needs a comment though. ;)
> 
> > > I wonder if we
> > > still need to set lslflag/lssflag in either of the above cases, though.
> > > It seems like the generic detection should handle it..?
> > 
> > In the end it would look at the relevant ->seen flag to determine
> > if there was a cross-option-struct conflict. Essentially, the
> > conflict definition needs to define conflicts via a {group, option}
> > tuple rather than just the {option} it uses now...
> > 
> 
> Sure. Not a huge deal, but to be clear my comment here was with respect
> to the fact that we set lslflag and lssflag in those two
> S_SECTLOG/S_SECTSIZE blocks. I suspect we still need the flag for the
> L_SECT* conflict, but it looks like the generic code now handles the
> conflict within the 's' group of options. In other words, we have
> duplicate handling of the S_SECTLOG/S_SECTSIZE conflict after this
> patch.
> 
> Brian
> 

I'm for making it all in the generic code, if you are asking that. :-) 
Thanks for pointing out the possible duplicate handling, I will check it. (And thanks for all the others notices, too. :-))

> > -Dave.
> > --
> > Dave Chinner
> > david@fromorbit.com
> > 
-- 
Jan Tulak
jtulak@redhat.com

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

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

* Re: [PATCH 01/17] xfsprogs: use common code for multi-disk detection
  2015-06-25 19:37   ` Brian Foster
@ 2015-07-02 12:47     ` Jan Tulak
  2015-07-02 14:14       ` Brian Foster
  0 siblings, 1 reply; 51+ messages in thread
From: Jan Tulak @ 2015-07-02 12:47 UTC (permalink / raw)
  To: Brian Foster; +Cc: xfs, Dave Chinner



----- Original Message -----
> From: "Brian Foster" <bfoster@redhat.com>
> To: "Jan Ťulák" <jtulak@redhat.com>
> Cc: "Dave Chinner" <dchinner@redhat.com>, xfs@oss.sgi.com
> Sent: Thursday, June 25, 2015 9:37:48 PM
> Subject: Re: [PATCH 01/17] xfsprogs: use common code for multi-disk detection
> 
> On Fri, Jun 19, 2015 at 01:01:50PM +0200, Jan Ťulák wrote:
> > From: Dave Chinner <dchinner@redhat.com>
> > 
> > Both xfs_repair and mkfs.xfs need to agree on what is a "multidisk:
> > configuration - mkfs for determining the AG count of the filesystem,
> > repair for determining how to automatically parallelise it's
> > execution. This requires a bunch of common defines that both mkfs
> > and reapir need to share.
> > 
> > In fact, most of the defines in xfs_mkfs.h could be shared with
> > other programs (i.e. all the defaults mkfs uses) and so it is
> > simplest to move xfs_mkfs.h to the shared include directory and add
> > the new defines to it directly.
> > 
> > Signed-off-by: Dave Chinner <dchinner@redhat.com>
> > Signed-off-by: Jan Ťulák <jtulak@redhat.com>
> > ---
> >  include/Makefile    |  8 ++++-
> >  include/xfs_mkfs.h  | 98
> >  +++++++++++++++++++++++++++++++++++++++++++++++++++++
> >  mkfs/Makefile       |  2 +-
> >  mkfs/xfs_mkfs.c     | 56 +++++++++++++++---------------
> >  mkfs/xfs_mkfs.h     | 89 ------------------------------------------------
> >  repair/xfs_repair.c | 45 ++++++++++++++++++++++--
> >  6 files changed, 178 insertions(+), 120 deletions(-)
> >  create mode 100644 include/xfs_mkfs.h
> >  delete mode 100644 mkfs/xfs_mkfs.h
> > 
> > diff --git a/include/Makefile b/include/Makefile
> > index 70e43a0..3269ec3 100644
> > --- a/include/Makefile
> > +++ b/include/Makefile
> > @@ -26,9 +26,15 @@ QAHFILES = libxfs.h libxlog.h \
> >  	xfs_inode.h \
> >  	xfs_log_recover.h \
> >  	xfs_metadump.h \
> > +	xfs_mkfs.h \
> >  	xfs_mount.h \
> > +	xfs_quota_defs.h \
> > +	xfs_sb.h \
> > +	xfs_shared.h \
> >  	xfs_trace.h \
> > -	xfs_trans.h
> > +	xfs_trans.h \
> > +	xfs_trans_resv.h \
> > +	xfs_trans_space.h
> >  
> >  HFILES = handle.h jdm.h xqm.h xfs.h
> >  HFILES += $(PKG_PLATFORM).h
> > diff --git a/include/xfs_mkfs.h b/include/xfs_mkfs.h
> > new file mode 100644
> > index 0000000..3388f6d
> > --- /dev/null
> > +++ b/include/xfs_mkfs.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_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))
> > +
> > +/*
> > + * 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);
> > +
> > +#endif	/* __XFS_MKFS_H__ */
> > diff --git a/mkfs/Makefile b/mkfs/Makefile
> > index fd1f615..82326e0 100644
> > --- a/mkfs/Makefile
> > +++ b/mkfs/Makefile
> > @@ -8,7 +8,7 @@ include $(TOPDIR)/include/builddefs
> >  LTCOMMAND = mkfs.xfs
> >  FSTYP = fstyp
> >  
> > -HFILES = xfs_mkfs.h
> > +HFILES =
> >  CFILES = maxtrres.c proto.c xfs_mkfs.c
> >  
> >  ifeq ($(ENABLE_BLKID),yes)
> > diff --git a/mkfs/xfs_mkfs.c b/mkfs/xfs_mkfs.c
> > index 83f7749..d0de90d 100644
> > --- a/mkfs/xfs_mkfs.c
> > +++ b/mkfs/xfs_mkfs.c
> > @@ -24,7 +24,7 @@
> >  #include <disk/fstyp.h>
> >  #include <disk/volume.h>
> >  #endif
> > -#include "xfs_mkfs.h"
> > +#include <xfs/xfs_mkfs.h>
> >  
> >  /*
> >   * Device topology information.
> > @@ -688,43 +688,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--;
> > +
> 
> Intended change in behavior of the defaults for fs' that match these
> size thresholds (the 512g and 8g ones anyways)? For example, in the old
> code a 512GB fs gets a shift of 4 while the same fs gets shift = 5 in
> the new code.
> 
> Brian

When I look on the code, where did you got the 4 vs 5? In the old code, for 512GB and bigger is assigned shift=5 directly. In the new one, shift is set to XFS_MULTIDISK_AGLOG which is 5, and then, if the disk is smaller than 512GB, it decrements the value. But unless I'm missing something, the multidisk configuration is not changing anything, there is just a different syntax.

Cheers,
Jan
-- 
Jan Tulak
jtulak@redhat.com

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

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

* Re: [PATCH 01/17] xfsprogs: use common code for multi-disk detection
  2015-07-02 12:47     ` Jan Tulak
@ 2015-07-02 14:14       ` Brian Foster
  2015-07-02 23:05         ` Dave Chinner
  2015-07-03 10:06         ` Jan Tulak
  0 siblings, 2 replies; 51+ messages in thread
From: Brian Foster @ 2015-07-02 14:14 UTC (permalink / raw)
  To: Jan Tulak; +Cc: xfs, Dave Chinner

On Thu, Jul 02, 2015 at 08:47:53AM -0400, Jan Tulak wrote:
> 
> 
> ----- Original Message -----
> > From: "Brian Foster" <bfoster@redhat.com>
> > To: "Jan Ťulák" <jtulak@redhat.com>
> > Cc: "Dave Chinner" <dchinner@redhat.com>, xfs@oss.sgi.com
> > Sent: Thursday, June 25, 2015 9:37:48 PM
> > Subject: Re: [PATCH 01/17] xfsprogs: use common code for multi-disk detection
> > 
> > On Fri, Jun 19, 2015 at 01:01:50PM +0200, Jan Ťulák wrote:
> > > From: Dave Chinner <dchinner@redhat.com>
> > > 
> > > Both xfs_repair and mkfs.xfs need to agree on what is a "multidisk:
> > > configuration - mkfs for determining the AG count of the filesystem,
> > > repair for determining how to automatically parallelise it's
> > > execution. This requires a bunch of common defines that both mkfs
> > > and reapir need to share.
> > > 
> > > In fact, most of the defines in xfs_mkfs.h could be shared with
> > > other programs (i.e. all the defaults mkfs uses) and so it is
> > > simplest to move xfs_mkfs.h to the shared include directory and add
> > > the new defines to it directly.
> > > 
> > > Signed-off-by: Dave Chinner <dchinner@redhat.com>
> > > Signed-off-by: Jan Ťulák <jtulak@redhat.com>
> > > ---
> > >  include/Makefile    |  8 ++++-
> > >  include/xfs_mkfs.h  | 98
> > >  +++++++++++++++++++++++++++++++++++++++++++++++++++++
> > >  mkfs/Makefile       |  2 +-
> > >  mkfs/xfs_mkfs.c     | 56 +++++++++++++++---------------
> > >  mkfs/xfs_mkfs.h     | 89 ------------------------------------------------
> > >  repair/xfs_repair.c | 45 ++++++++++++++++++++++--
> > >  6 files changed, 178 insertions(+), 120 deletions(-)
> > >  create mode 100644 include/xfs_mkfs.h
> > >  delete mode 100644 mkfs/xfs_mkfs.h
> > > 
> > > diff --git a/include/Makefile b/include/Makefile
> > > index 70e43a0..3269ec3 100644
> > > --- a/include/Makefile
> > > +++ b/include/Makefile
> > > @@ -26,9 +26,15 @@ QAHFILES = libxfs.h libxlog.h \
> > >  	xfs_inode.h \
> > >  	xfs_log_recover.h \
> > >  	xfs_metadump.h \
> > > +	xfs_mkfs.h \
> > >  	xfs_mount.h \
> > > +	xfs_quota_defs.h \
> > > +	xfs_sb.h \
> > > +	xfs_shared.h \
> > >  	xfs_trace.h \
> > > -	xfs_trans.h
> > > +	xfs_trans.h \
> > > +	xfs_trans_resv.h \
> > > +	xfs_trans_space.h
> > >  
> > >  HFILES = handle.h jdm.h xqm.h xfs.h
> > >  HFILES += $(PKG_PLATFORM).h
> > > diff --git a/include/xfs_mkfs.h b/include/xfs_mkfs.h
> > > new file mode 100644
> > > index 0000000..3388f6d
> > > --- /dev/null
> > > +++ b/include/xfs_mkfs.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_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))
> > > +
> > > +/*
> > > + * 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);
> > > +
> > > +#endif	/* __XFS_MKFS_H__ */
> > > diff --git a/mkfs/Makefile b/mkfs/Makefile
> > > index fd1f615..82326e0 100644
> > > --- a/mkfs/Makefile
> > > +++ b/mkfs/Makefile
> > > @@ -8,7 +8,7 @@ include $(TOPDIR)/include/builddefs
> > >  LTCOMMAND = mkfs.xfs
> > >  FSTYP = fstyp
> > >  
> > > -HFILES = xfs_mkfs.h
> > > +HFILES =
> > >  CFILES = maxtrres.c proto.c xfs_mkfs.c
> > >  
> > >  ifeq ($(ENABLE_BLKID),yes)
> > > diff --git a/mkfs/xfs_mkfs.c b/mkfs/xfs_mkfs.c
> > > index 83f7749..d0de90d 100644
> > > --- a/mkfs/xfs_mkfs.c
> > > +++ b/mkfs/xfs_mkfs.c
> > > @@ -24,7 +24,7 @@
> > >  #include <disk/fstyp.h>
> > >  #include <disk/volume.h>
> > >  #endif
> > > -#include "xfs_mkfs.h"
> > > +#include <xfs/xfs_mkfs.h>
> > >  
> > >  /*
> > >   * Device topology information.
> > > @@ -688,43 +688,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--;
> > > +
> > 
> > Intended change in behavior of the defaults for fs' that match these
> > size thresholds (the 512g and 8g ones anyways)? For example, in the old
> > code a 512GB fs gets a shift of 4 while the same fs gets shift = 5 in
> > the new code.
> > 
> > Brian
> 
> When I look on the code, where did you got the 4 vs 5? In the old code, for 512GB and bigger is assigned shift=5 directly. In the new one, shift is set to XFS_MULTIDISK_AGLOG which is 5, and then, if the disk is smaller than 512GB, it decrements the value. But unless I'm missing something, the multidisk configuration is not changing anything, there is just a different syntax.
> 

I was referring to the multidisk case. The old code looks like this:

        if (!multidisk && dblocks >= MEGABYTES(128, blocklog)) {
		...
        } else if (dblocks > GIGABYTES(512, blocklog))
                shift = 5;
        else if (dblocks > GIGABYTES(8, blocklog))
                shift = 4;

... which means if multidisk && dblocks == 512GB, then shift is set to
4. With the new code, we set XFS_MULTIDISK_AGLOG as you noted and then
execute:

	if (dblocks < GIGABYTES(512, blocklog))
		shift--;
	...

... which will not decrement shift if dblocks == 512GB (i.e., shift is
5).

If you're still not convinced, create an exact sized 512GB file, mkfs it
(with the su/sw options set for multidisk) with and without this change
and observe agcount. :)

Brian

> Cheers,
> Jan
> -- 
> Jan Tulak
> jtulak@redhat.com

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

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

* Re: [PATCH 01/17] xfsprogs: use common code for multi-disk detection
  2015-07-02 14:14       ` Brian Foster
@ 2015-07-02 23:05         ` Dave Chinner
  2015-07-03 13:22           ` Brian Foster
  2015-07-08 16:14           ` Jan Tulak
  2015-07-03 10:06         ` Jan Tulak
  1 sibling, 2 replies; 51+ messages in thread
From: Dave Chinner @ 2015-07-02 23:05 UTC (permalink / raw)
  To: Brian Foster; +Cc: xfs, Dave Chinner, Jan Tulak

On Thu, Jul 02, 2015 at 10:14:04AM -0400, Brian Foster wrote:
> On Thu, Jul 02, 2015 at 08:47:53AM -0400, Jan Tulak wrote:

[snip ~250 lines]

[ add note about mailing list etiquette w.r.t. trimming the quoted
context to just what is being discussed so that readers don't have to
scroll through several screens of irrelevant text just to find the
discussion. ]

> If you're still not convinced, create an exact sized 512GB file, mkfs it
> (with the su/sw options set for multidisk) with and without this change
> and observe agcount. :)

At one point during development of this patch set I started writing
an xfstest to validate that mkfs did all the right input validation
things and set parameters appropriately so that we didn't
inadvertently change behaviour. I never really finished it off (like
the patch set), but I've attached it below to give an idea of where
I was going with it. It was based on validating the input and CLI
parameters for the new code, so is guaranteed to fail on an existing
mkfs binary.

It's probably a good idea to also validate that things like agcount
scale as we expect them to...

Cheers,

Dave.
-- 
Dave Chinner
david@fromorbit.com


xfs: add new xfs.mkfs input validation test

From: Dave Chinner <dchinner@redhat.com>

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

Signed-off-by: Dave Chinner <dchinner@redhat.com>
---
 tests/xfs/401     | 194 ++++++++++++++++++++++++++++++++++++++++++++++++++++++
 tests/xfs/401.out |   2 +
 tests/xfs/group   |   1 +
 3 files changed, 197 insertions(+)

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

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

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

* Re: [PATCH 03/17] mkfs: Sanitise the superblock feature macros
  2015-06-25 19:38   ` Brian Foster
@ 2015-07-03  9:53     ` Jan Tulak
  2015-07-03 13:24       ` Brian Foster
  0 siblings, 1 reply; 51+ messages in thread
From: Jan Tulak @ 2015-07-03  9:53 UTC (permalink / raw)
  To: Brian Foster; +Cc: xfs, Dave Chinner



----- Original Message -----
> From: "Brian Foster" <bfoster@redhat.com>
> > @@ -1912,17 +2013,17 @@ _("32 bit Project IDs always enabled on CRC enabled
> > filesytems\n"));
> >  		 * tried to use crc=0,finobt=1, then issue a warning before
> >  		 * turning them off.
> >  		 */
> > -		if (finobt && finobtflag) {
> > +		if (sb_feat.finobt && sb_feat.finobtflag) {
> 
> Since the code above drops finobtflag, I don't think we'll ever hit
> this. Indeed, I can now create a crc=0,finobt=1 fs, which shouldn't
> happen.
> 
> Brian
> 

Finobtflag is dropped by a later patch in the set entirely. After all patches, the line is:

	if (sb_feat.finobt && mopts.subopt_params[M_FINOBT].seen)

Which indeed works as it should:

mkfs.xfs -f -m crc=0,finobt=1 /dev/vdb2
warning: finobt not supported without CRC support, disabled.

Cheers,
Jan

-- 
Jan Tulak
jtulak@redhat.com

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

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

* Re: [PATCH 01/17] xfsprogs: use common code for multi-disk detection
  2015-07-02 14:14       ` Brian Foster
  2015-07-02 23:05         ` Dave Chinner
@ 2015-07-03 10:06         ` Jan Tulak
  1 sibling, 0 replies; 51+ messages in thread
From: Jan Tulak @ 2015-07-03 10:06 UTC (permalink / raw)
  To: Brian Foster; +Cc: Dave Chinner, xfs



----- Original Message -----
> From: "Brian Foster" <bfoster@redhat.com>
> On Thu, Jul 02, 2015 at 08:47:53AM -0400, Jan Tulak wrote:
> >
> > When I look on the code, where did you got the 4 vs 5? In the old code, for
> > 512GB and bigger is assigned shift=5 directly. In the new one, shift is
> > set to XFS_MULTIDISK_AGLOG which is 5, and then, if the disk is smaller
> > than 512GB, it decrements the value. But unless I'm missing something, the
> > multidisk configuration is not changing anything, there is just a
> > different syntax.
> > 
> 
> I was referring to the multidisk case. The old code looks like this:
> 
>         if (!multidisk && dblocks >= MEGABYTES(128, blocklog)) {
> 		...
>         } else if (dblocks > GIGABYTES(512, blocklog))
>                 shift = 5;
>         else if (dblocks > GIGABYTES(8, blocklog))
>                 shift = 4;
> 
> ... which means if multidisk && dblocks == 512GB, then shift is set to
> 4. With the new code, we set XFS_MULTIDISK_AGLOG as you noted and then
> execute:
> 
> 	if (dblocks < GIGABYTES(512, blocklog))
> 		shift--;
> 	...
> 
> ... which will not decrement shift if dblocks == 512GB (i.e., shift is
> 5).
> 
> If you're still not convinced, create an exact sized 512GB file, mkfs it
> (with the su/sw options set for multidisk) with and without this change
> and observe agcount. :)
> 
> Brian
> 

Ah, mea culpa, I didn't thought about what happens when the size is exactly 512 GB when I wrote the reply. :-) You are right, I'll fix it.

Jan

-- 
Jan Tulak
jtulak@redhat.com

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

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

* Re: [PATCH 01/17] xfsprogs: use common code for multi-disk detection
  2015-07-02 23:05         ` Dave Chinner
@ 2015-07-03 13:22           ` Brian Foster
  2015-07-08 16:14           ` Jan Tulak
  1 sibling, 0 replies; 51+ messages in thread
From: Brian Foster @ 2015-07-03 13:22 UTC (permalink / raw)
  To: Dave Chinner; +Cc: xfs, Dave Chinner, Jan Tulak

On Fri, Jul 03, 2015 at 09:05:20AM +1000, Dave Chinner wrote:
> On Thu, Jul 02, 2015 at 10:14:04AM -0400, Brian Foster wrote:
> > On Thu, Jul 02, 2015 at 08:47:53AM -0400, Jan Tulak wrote:
> 
> [snip ~250 lines]
> 
> [ add note about mailing list etiquette w.r.t. trimming the quoted
> context to just what is being discussed so that readers don't have to
> scroll through several screens of irrelevant text just to find the
> discussion. ]
> 
> > If you're still not convinced, create an exact sized 512GB file, mkfs it
> > (with the su/sw options set for multidisk) with and without this change
> > and observe agcount. :)
> 
> At one point during development of this patch set I started writing
> an xfstest to validate that mkfs did all the right input validation
> things and set parameters appropriately so that we didn't
> inadvertently change behaviour. I never really finished it off (like
> the patch set), but I've attached it below to give an idea of where
> I was going with it. It was based on validating the input and CLI
> parameters for the new code, so is guaranteed to fail on an existing
> mkfs binary.
> 
> It's probably a good idea to also validate that things like agcount
> scale as we expect them to...
> 

Yeah, good idea. This is probably something we should get in following
this series.  I shouldn't be too hard to teach this to expect certain
format values (agcount, agsize, etc.). We might be able to get away with
just matching the mkfs output to expected output on fixed size
filesystems.

Brian

> Cheers,
> 
> Dave.
> -- 
> Dave Chinner
> david@fromorbit.com
> 
> 
> xfs: add new xfs.mkfs input validation test
> 
> From: Dave Chinner <dchinner@redhat.com>
> 
> mkfs.xfs does not do a very good job of input validation. This test
> is designed to exercise the input validation and test good/bad
> combinations of options being set. It will not pass on a current
> mkfs.xfs binary - it is designed to be the test case for a input
> validation cleanup.
> 
> Signed-off-by: Dave Chinner <dchinner@redhat.com>
> ---
>  tests/xfs/401     | 194 ++++++++++++++++++++++++++++++++++++++++++++++++++++++
>  tests/xfs/401.out |   2 +
>  tests/xfs/group   |   1 +
>  3 files changed, 197 insertions(+)
> 
> diff --git a/tests/xfs/401 b/tests/xfs/401
> new file mode 100644
> index 0000000..48de395
> --- /dev/null
> +++ b/tests/xfs/401
> @@ -0,0 +1,194 @@
> +#! /bin/bash
> +# FS QA Test No. xfs/401
> +#
> +# mkfs.xfs input validation test. Designed to break mkfs.xfs if it doesn't
> +# filter garbage input or invalid option combinations correctly.
> +#
> +#-----------------------------------------------------------------------
> +# Copyright (c) 2014 Red Hat, Inc.  All Rights Reserved.
> +#
> +# This program is free software; you can redistribute it and/or
> +# modify it under the terms of the GNU General Public License as
> +# published by the Free Software Foundation.
> +#
> +# This program is distributed in the hope that it would be useful,
> +# but WITHOUT ANY WARRANTY; without even the implied warranty of
> +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
> +# GNU General Public License for more details.
> +#
> +# You should have received a copy of the GNU General Public License
> +# along with this program; if not, write the Free Software Foundation,
> +# Inc.,  51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
> +#-----------------------------------------------------------------------
> +#
> +
> +seq=`basename $0`
> +seqres=$RESULT_DIR/$seq
> +echo "QA output created by $res"
> +
> +here=`pwd`
> +tmp=/tmp/$$
> +status=1	# failure is the default!
> +trap "_cleanup; exit $status" 0 1 2 3 15
> +
> +_cleanup()
> +{
> +    cd /
> +    rm -f $tmp.*
> +}
> +
> +# get standard environment, filters and checks
> +. ./common/rc
> +. ./common/filter
> +
> +# real QA test starts here
> +
> +# Modify as appropriate.
> +_supported_fs xfs
> +_supported_os Linux
> +_require_scratch
> +
> +echo silence is golden
> +
> +# clear out any options to mkfs first. We want to test realtime and external log
> +# devices if we can, but we also want to control them ourselves.
> +logdev=$SCRATCH_LOGDEV
> +rtdev=$SCRATCH_RTDEV
> +
> +MKFS_OPTIONS=
> +SCRATCH_LOGDEV=
> +SCRATCH_RTDEV=
> +
> +# limit the image size of the filesystem being created to something small
> +fssize=$((4 * 1024 * 1024 * 1024))
> +fsimg=$TEST_DIR/$seq.img
> +
> +do_mkfs_pass()
> +{
> +	echo >> $seqres.full
> +	echo "pass expected $*" >> $seqres.full
> +	$MKFS_XFS_PROG -f -N $* >> $seqres.full 2>&1
> +	[ $? -ne 0 ] && echo "fail $*"
> +}
> +
> +do_mkfs_fail()
> +{
> +	echo >> $seqres.full
> +	echo "fail expected $*" >> $seqres.full
> +	$MKFS_XFS_PROG -f -N $* >> $seqres.full 2>&1
> +	[ $? -eq 0 ] && echo "pass $*"
> +}
> +
> +do_mkfs_pass $SCRATCH_DEV
> +
> +# basic "should fail" options
> +# logarithm based options are no longer valid
> +do_mkfs_fail -s log=9 $SCRATCH_DEV
> +do_mkfs_fail -b log=9 $SCRATCH_DEV
> +do_mkfs_fail -n log=9 $SCRATCH_DEV
> +do_mkfs_fail -i log=9 $SCRATCH_DEV
> +do_mkfs_fail -d sectlog=9 $SCRATCH_DEV
> +do_mkfs_fail -l sectlog=9 $SCRATCH_DEV
> +
> +# specifying sector sizes in sectors or blocks or garbage
> +do_mkfs_fail -s size=2s $SCRATCH_DEV
> +do_mkfs_fail -d sectsize=2s $SCRATCH_DEV
> +do_mkfs_fail -l sectsize=2s $SCRATCH_DEV
> +do_mkfs_fail -s size=2b $SCRATCH_DEV
> +do_mkfs_fail -d sectsize=2b $SCRATCH_DEV
> +do_mkfs_fail -l sectsize=2b $SCRATCH_DEV
> +
> +do_mkfs_fail -s size=grot $SCRATCH_DEV
> +do_mkfs_fail -s size=2yerk $SCRATCH_DEV
> +do_mkfs_fail -d sectsize=blah $SCRATCH_DEV
> +do_mkfs_fail -d sectsize=2foo $SCRATCH_DEV
> +do_mkfs_fail -l sectsize=nggh $SCRATCH_DEV
> +do_mkfs_fail -l sectsize=2nggh $SCRATCH_DEV
> +
> +# conflicting sector/block sizes
> +do_mkfs_fail -s size=512 -d sectsize=1024 $SCRATCH_DEV
> +do_mkfs_fail -s size=512 -l sectsize=1024 $SCRATCH_DEV
> +do_mkfs_fail -d sectsize=2048 -l sectsize=1024 $SCRATCH_DEV
> +
> +do_mkfs_fail -b size=512 -s size=1024 $SCRATCH_DEV
> +do_mkfs_fail -b size=512 -d sectsize=1024 $SCRATCH_DEV
> +do_mkfs_fail -b size=512 -l sectsize=1024 $SCRATCH_DEV
> +
> +# specifying block sizes in sectors without specifying sector size
> +# or in blocks or garbage
> +do_mkfs_fail -b size=2s $SCRATCH_DEV
> +do_mkfs_fail -b size=2b $SCRATCH_DEV
> +do_mkfs_fail -b size=nfi $SCRATCH_DEV
> +do_mkfs_fail -b size=4096nfi $SCRATCH_DEV
> +do_mkfs_fail -n size=2s $SCRATCH_DEV
> +do_mkfs_fail -n size=2b $SCRATCH_DEV
> +do_mkfs_fail -n size=nfi $SCRATCH_DEV
> +do_mkfs_fail -n size=4096nfi $SCRATCH_DEV
> +
> +# bad label length
> +do_mkfs_fail -L thisiswaytoolong $SCRATCH_DEV
> +
> +# basic "should pass" data section tests
> +do_mkfs_pass $SCRATCH_DEV
> +do_mkfs_pass -d name=$SCRATCH_DEV
> +do_mkfs_pass -d size=$fssize $SCRATCH_DEV
> +do_mkfs_pass -d agcount=32 $SCRATCH_DEV
> +do_mkfs_pass -d agsize=32m $SCRATCH_DEV
> +do_mkfs_pass -d agsize=32M $SCRATCH_DEV
> +do_mkfs_pass -d agsize=1g $SCRATCH_DEV
> +do_mkfs_pass -d agsize=$((32 * 1024 * 1024)) $SCRATCH_DEV
> +do_mkfs_pass -b size=4096 -d agsize=8192b $SCRATCH_DEV
> +do_mkfs_pass -d sectsize=512,agsize=65536s $SCRATCH_DEV
> +do_mkfs_pass -s size=512 -d agsize=65536s $SCRATCH_DEV
> +do_mkfs_pass -d noalign $SCRATCH_DEV
> +do_mkfs_pass -d sunit=0,swidth=0 $SCRATCH_DEV
> +do_mkfs_pass -d sunit=8,swidth=8 $SCRATCH_DEV
> +do_mkfs_pass -d sunit=8,swidth=64 $SCRATCH_DEV
> +do_mkfs_pass -d su=0,sw=0 $SCRATCH_DEV
> +do_mkfs_pass -d su=4096,sw=1 $SCRATCH_DEV
> +do_mkfs_pass -d su=4k,sw=1 $SCRATCH_DEV
> +do_mkfs_pass -d su=4K,sw=8 $SCRATCH_DEV
> +do_mkfs_pass -b size=4096 -d su=1b,sw=8 $SCRATCH_DEV
> +do_mkfs_pass -d sectsize=512,su=8s,sw=8 $SCRATCH_DEV
> +do_mkfs_pass -s size=512 -d su=8s,sw=8 $SCRATCH_DEV
> +
> +rm -f $fsimg
> +$XFS_IO_PROG -f -c "truncate $fssize" $fsimg
> +do_mkfs_pass -d file $fsimg
> +do_mkfs_pass -d file,name=$fsimg
> +rm -f $fsimg
> +do_mkfs_pass -d size=$fssize,file $fsimg
> +rm -f $fsimg
> +do_mkfs_pass -d size=$fssize,file,name=$fsimg
> +do_mkfs_pass -d file,name=$fsimg
> +
> +# invalid data section tests
> +do_mkfs_fail -d size=${fssize}b $SCRATCH_DEV
> +do_mkfs_fail -d size=${fssize}s $SCRATCH_DEV
> +do_mkfs_fail -d size=${fssize}yerk $SCRATCH_DEV
> +do_mkfs_fail -d agsize=8192b $SCRATCH_DEV
> +do_mkfs_fail -d agsize=65536s $SCRATCH_DEV
> +do_mkfs_fail -d agsize=32Mbsdfsdo $SCRATCH_DEV
> +do_mkfs_fail -d agsize=1GB $SCRATCH_DEV
> +do_mkfs_fail -d agcount=1k $SCRATCH_DEV
> +do_mkfs_fail -d agcount=6b $SCRATCH_DEV
> +do_mkfs_fail -d agcount=32,agsize=32m $SCRATCH_DEV
> +do_mkfs_fail -d sunit=0,swidth=64 $SCRATCH_DEV
> +do_mkfs_fail -d sunit=64,swidth=0 $SCRATCH_DEV
> +do_mkfs_fail -d sunit=64,swidth=64,noalign $SCRATCH_DEV
> +do_mkfs_fail -d sunit=64k,swidth=64 $SCRATCH_DEV
> +do_mkfs_fail -d sunit=64,swidth=64m $SCRATCH_DEV
> +do_mkfs_fail -d su=0,sw=64 $SCRATCH_DEV
> +do_mkfs_fail -d su=4096,sw=0 $SCRATCH_DEV
> +do_mkfs_fail -d su=4096,sw=64,noalign $SCRATCH_DEV
> +do_mkfs_fail -d su=4096,sw=64s $SCRATCH_DEV
> +do_mkfs_fail -d su=4096s,sw=64 $SCRATCH_DEV
> +do_mkfs_fail -d su=4096b,sw=64 $SCRATCH_DEV
> +do_mkfs_fail -d su=4096garabge,sw=64 $SCRATCH_DEV
> +do_mkfs_fail -d su=4096,sw=64,sunit=64,swidth=64 $SCRATCH_DEV
> +
> +# naming section tests
> +do_mkfs_pass -n size=65536 $SCRATCH_DEV
> +
> +status=0
> +exit
> diff --git a/tests/xfs/401.out b/tests/xfs/401.out
> new file mode 100644
> index 0000000..aaf601b
> --- /dev/null
> +++ b/tests/xfs/401.out
> @@ -0,0 +1,2 @@
> +QA output created by 401
> +silence is golden
> diff --git a/tests/xfs/group b/tests/xfs/group
> index ba34650..cfee785 100644
> --- a/tests/xfs/group
> +++ b/tests/xfs/group
> @@ -189,3 +189,4 @@
>  304 auto quick quota
>  305 auto quota
>  306 auto stress log metadata repair
> +401 mkfs auto quick

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

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

* Re: [PATCH 03/17] mkfs: Sanitise the superblock feature macros
  2015-07-03  9:53     ` Jan Tulak
@ 2015-07-03 13:24       ` Brian Foster
  0 siblings, 0 replies; 51+ messages in thread
From: Brian Foster @ 2015-07-03 13:24 UTC (permalink / raw)
  To: Jan Tulak; +Cc: xfs, Dave Chinner

On Fri, Jul 03, 2015 at 05:53:27AM -0400, Jan Tulak wrote:
> 
> 
> ----- Original Message -----
> > From: "Brian Foster" <bfoster@redhat.com>
> > > @@ -1912,17 +2013,17 @@ _("32 bit Project IDs always enabled on CRC enabled
> > > filesytems\n"));
> > >  		 * tried to use crc=0,finobt=1, then issue a warning before
> > >  		 * turning them off.
> > >  		 */
> > > -		if (finobt && finobtflag) {
> > > +		if (sb_feat.finobt && sb_feat.finobtflag) {
> > 
> > Since the code above drops finobtflag, I don't think we'll ever hit
> > this. Indeed, I can now create a crc=0,finobt=1 fs, which shouldn't
> > happen.
> > 
> > Brian
> > 
> 
> Finobtflag is dropped by a later patch in the set entirely. After all patches, the line is:
> 
> 	if (sb_feat.finobt && mopts.subopt_params[M_FINOBT].seen)
> 
> Which indeed works as it should:
> 
> mkfs.xfs -f -m crc=0,finobt=1 /dev/vdb2
> warning: finobt not supported without CRC support, disabled.
> 

Ok, fair enough. That said, I'm not a huge fan of letting broken patches
through just because things are fixed up in a subsequent patch. For one,
it makes review difficult and kind of removes incentive to review
individual patches rather than just the end result. In general, that's
problematic for things like future bisects or if you consider a
subsequent patch might be reverted down the line after all this context
is lost, re-exposing a previously known problem.

This particular instance is not a big deal. It requires the user to do
something wrong and we wouldn't mount the fs anyways. I'm just pointing
this out because IIRC there were a couple of instances of this "break in
one patch, fix in another" pattern in this series. In most cases, the
right thing to do is fix up the broken patch. ;)

Brian

> Cheers,
> Jan
> 
> -- 
> Jan Tulak
> jtulak@redhat.com

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

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

* Re: [PATCH 01/17] xfsprogs: use common code for multi-disk detection
  2015-07-02 23:05         ` Dave Chinner
  2015-07-03 13:22           ` Brian Foster
@ 2015-07-08 16:14           ` Jan Tulak
  2015-07-09  0:45             ` Dave Chinner
  1 sibling, 1 reply; 51+ messages in thread
From: Jan Tulak @ 2015-07-08 16:14 UTC (permalink / raw)
  To: Dave Chinner; +Cc: Brian Foster, Dave Chinner, xfs



----- Original Message -----
> From: "Dave Chinner" <david@fromorbit.com>

> At one point during development of this patch set I started writing
> an xfstest to validate that mkfs did all the right input validation
> things and set parameters appropriately so that we didn't
> inadvertently change behaviour. I never really finished it off (like
> the patch set), but I've attached it below to give an idea of where
> I was going with it. It was based on validating the input and CLI
> parameters for the new code, so is guaranteed to fail on an existing
> mkfs binary.


I'm using and extending it, but I'm not sure about some tests, whether it is a change from current behaviour, or if it is rather an issue in the test.

> +
> +# basic "should fail" options
> +# logarithm based options are no longer valid
> +do_mkfs_fail -s log=9 $SCRATCH_DEV

There are some changes in logarithm input (mkfs: validate logarithmic parameters sanely), but it is still supported in the patches. Is there some issue, why to remove them?
Otherwise, it should rather test for (in)valid input for log=xxx, right?

> +rm -f $fsimg
> +$XFS_IO_PROG -f -c "truncate $fssize" $fsimg
> +do_mkfs_pass -d file $fsimg
> +do_mkfs_pass -d file,name=$fsimg
> +rm -f $fsimg
> +do_mkfs_pass -d size=$fssize,file $fsimg
> +rm -f $fsimg
> +do_mkfs_pass -d size=$fssize,file,name=$fsimg
> +do_mkfs_pass -d file,name=$fsimg

Should all these inputs really pass? What is the expected behaviour for example on -d file,name=$fsimg if the file exists, and what if there is no such file? 

Cheers,
Jan

-- 
Jan Tulak
jtulak@redhat.com

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

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

* Re: [PATCH 01/17] xfsprogs: use common code for multi-disk detection
  2015-07-08 16:14           ` Jan Tulak
@ 2015-07-09  0:45             ` Dave Chinner
  2015-07-09  8:24               ` Jan Tulak
  0 siblings, 1 reply; 51+ messages in thread
From: Dave Chinner @ 2015-07-09  0:45 UTC (permalink / raw)
  To: Jan Tulak; +Cc: Brian Foster, Dave Chinner, xfs

[Please line wrap your responses at 68-72 columns]

On Wed, Jul 08, 2015 at 12:14:56PM -0400, Jan Tulak wrote:
> ----- Original Message -----
> > From: "Dave Chinner" <david@fromorbit.com>
> 
> > At one point during development of this patch set I started writing
> > an xfstest to validate that mkfs did all the right input validation
> > things and set parameters appropriately so that we didn't
> > inadvertently change behaviour. I never really finished it off (like
> > the patch set), but I've attached it below to give an idea of where
> > I was going with it. It was based on validating the input and CLI
> > parameters for the new code, so is guaranteed to fail on an existing
> > mkfs binary.
> 
> I'm using and extending it, but I'm not sure about some tests,
> whether it is a change from current behaviour, or if it is rather
> an issue in the test.

Remember, the point of the patchset was to sanitise and clean up the
CLI interface, not just the code. i.e. the CLI will change, not just
the code.

> > +
> > +# basic "should fail" options
> > +# logarithm based options are no longer valid
> > +do_mkfs_fail -s log=9 $SCRATCH_DEV
> 
> There are some changes in logarithm input (mkfs: validate
> logarithmic parameters sanely), but it is still supported in the
> patches. Is there some issue, why to remove them?

They are redundant and almost nobody uses them. The size options are
what people use, and even they have so many different units that it
confuses people...

> Otherwise, it should rather test for (in)valid input for log=xxx, right?

No, it's indicative of the fact I wanted to remove the log scale
options for variables.  As I've said before - I didn't ever finish
the patchset off.

Essentially, once all the options are in a table, we only want to
look in one place for things like ag size, fs size, log size, block
sizes etc. Right now the table has multiple entries or multiple
global variables for these things and we have to work out which is
valid and correct and handle conflicts and incompatibilities, etc.
We don't *need* that complexity to specify sizes of things, so
getting rid of the rarely used redundant options makes a lot of
sense as it simplifies the code and the user interface without
reducing functionality...

> > +rm -f $fsimg
> > +$XFS_IO_PROG -f -c "truncate $fssize" $fsimg
> > +do_mkfs_pass -d file $fsimg
> > +do_mkfs_pass -d file,name=$fsimg
> > +rm -f $fsimg
> > +do_mkfs_pass -d size=$fssize,file $fsimg
> > +rm -f $fsimg
> > +do_mkfs_pass -d size=$fssize,file,name=$fsimg
> > +do_mkfs_pass -d file,name=$fsimg
> 
> Should all these inputs really pass?

Yes, they should, because ....

> What is the expected
> behaviour for example on -d file,name=$fsimg if the file exists,
> and what if there is no such file? 

....in all cases the file either:

	a) exists and is of non-zero size and hence defines the
	   size of the filesystem to be created,
	b) does not exist but the size of the filesystem to be
	   created is specified on the CLI allowing us to create
	   the image file correctly.

We should only fail to create the image file if it doesn't exist
and we haven't been given enough information to calculate the size
of the filesystem via CLI parameters.

Cheers,

Dave.
-- 
Dave Chinner
david@fromorbit.com

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

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

* Re: [PATCH 01/17] xfsprogs: use common code for multi-disk detection
  2015-07-09  0:45             ` Dave Chinner
@ 2015-07-09  8:24               ` Jan Tulak
  0 siblings, 0 replies; 51+ messages in thread
From: Jan Tulak @ 2015-07-09  8:24 UTC (permalink / raw)
  To: Dave Chinner; +Cc: Brian Foster, xfs, Dave Chinner

OK, thanks for clarifying. :-)

Jan

----- Original Message -----
> From: "Dave Chinner" <david@fromorbit.com>
> To: "Jan Tulak" <jtulak@redhat.com>
> Cc: "Brian Foster" <bfoster@redhat.com>, "Dave Chinner" <dchinner@redhat.com>, xfs@oss.sgi.com
> Sent: Thursday, July 9, 2015 2:45:43 AM
> Subject: Re: [PATCH 01/17] xfsprogs: use common code for multi-disk detection
> 
> [Please line wrap your responses at 68-72 columns]
> 
> On Wed, Jul 08, 2015 at 12:14:56PM -0400, Jan Tulak wrote:
> > ----- Original Message -----
> > > From: "Dave Chinner" <david@fromorbit.com>
> > 
> > > At one point during development of this patch set I started writing
> > > an xfstest to validate that mkfs did all the right input validation
> > > things and set parameters appropriately so that we didn't
> > > inadvertently change behaviour. I never really finished it off (like
> > > the patch set), but I've attached it below to give an idea of where
> > > I was going with it. It was based on validating the input and CLI
> > > parameters for the new code, so is guaranteed to fail on an existing
> > > mkfs binary.
> > 
> > I'm using and extending it, but I'm not sure about some tests,
> > whether it is a change from current behaviour, or if it is rather
> > an issue in the test.
> 
> Remember, the point of the patchset was to sanitise and clean up the
> CLI interface, not just the code. i.e. the CLI will change, not just
> the code.
> 
> > > +
> > > +# basic "should fail" options
> > > +# logarithm based options are no longer valid
> > > +do_mkfs_fail -s log=9 $SCRATCH_DEV
> > 
> > There are some changes in logarithm input (mkfs: validate
> > logarithmic parameters sanely), but it is still supported in the
> > patches. Is there some issue, why to remove them?
> 
> They are redundant and almost nobody uses them. The size options are
> what people use, and even they have so many different units that it
> confuses people...
> 
> > Otherwise, it should rather test for (in)valid input for log=xxx, right?
> 
> No, it's indicative of the fact I wanted to remove the log scale
> options for variables.  As I've said before - I didn't ever finish
> the patchset off.
> 
> Essentially, once all the options are in a table, we only want to
> look in one place for things like ag size, fs size, log size, block
> sizes etc. Right now the table has multiple entries or multiple
> global variables for these things and we have to work out which is
> valid and correct and handle conflicts and incompatibilities, etc.
> We don't *need* that complexity to specify sizes of things, so
> getting rid of the rarely used redundant options makes a lot of
> sense as it simplifies the code and the user interface without
> reducing functionality...
> 
> > > +rm -f $fsimg
> > > +$XFS_IO_PROG -f -c "truncate $fssize" $fsimg
> > > +do_mkfs_pass -d file $fsimg
> > > +do_mkfs_pass -d file,name=$fsimg
> > > +rm -f $fsimg
> > > +do_mkfs_pass -d size=$fssize,file $fsimg
> > > +rm -f $fsimg
> > > +do_mkfs_pass -d size=$fssize,file,name=$fsimg
> > > +do_mkfs_pass -d file,name=$fsimg
> > 
> > Should all these inputs really pass?
> 
> Yes, they should, because ....
> 
> > What is the expected
> > behaviour for example on -d file,name=$fsimg if the file exists,
> > and what if there is no such file?
> 
> ....in all cases the file either:
> 
> 	a) exists and is of non-zero size and hence defines the
> 	   size of the filesystem to be created,
> 	b) does not exist but the size of the filesystem to be
> 	   created is specified on the CLI allowing us to create
> 	   the image file correctly.
> 
> We should only fail to create the image file if it doesn't exist
> and we haven't been given enough information to calculate the size
> of the filesystem via CLI parameters.
> 
> Cheers,
> 
> Dave.
> --
> Dave Chinner
> david@fromorbit.com
> 
> _______________________________________________
> xfs mailing list
> xfs@oss.sgi.com
> http://oss.sgi.com/mailman/listinfo/xfs
> 

-- 
Jan Tulak
jtulak@redhat.com

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

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

end of thread, other threads:[~2015-07-09  8:24 UTC | newest]

Thread overview: 51+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2015-06-19 11:01 [PATCH 00/17] mkfs: sanitise input parameters Jan Ťulák
2015-06-19 11:01 ` [PATCH 01/17] xfsprogs: use common code for multi-disk detection Jan Ťulák
2015-06-19 11:10   ` Christoph Hellwig
2015-06-19 11:51     ` Jan Tulak
2015-06-25 19:37   ` Brian Foster
2015-07-02 12:47     ` Jan Tulak
2015-07-02 14:14       ` Brian Foster
2015-07-02 23:05         ` Dave Chinner
2015-07-03 13:22           ` Brian Foster
2015-07-08 16:14           ` Jan Tulak
2015-07-09  0:45             ` Dave Chinner
2015-07-09  8:24               ` Jan Tulak
2015-07-03 10:06         ` Jan Tulak
2015-06-19 11:01 ` [PATCH 02/17] mkfs: sanitise ftype parameter values Jan Ťulák
2015-06-25 19:37   ` Brian Foster
2015-06-19 11:01 ` [PATCH 03/17] mkfs: Sanitise the superblock feature macros Jan Ťulák
2015-06-25 19:38   ` Brian Foster
2015-07-03  9:53     ` Jan Tulak
2015-07-03 13:24       ` Brian Foster
2015-06-19 11:01 ` [PATCH 04/17] mkfs: validate all input values Jan Ťulák
2015-06-25 19:38   ` Brian Foster
2015-06-19 11:01 ` [PATCH 05/17] mkfs: factor boolean option parsing Jan Ťulák
2015-06-25 19:38   ` Brian Foster
2015-06-19 11:01 ` [PATCH 06/17] mkfs: validate logarithmic parameters sanely Jan Ťulák
2015-06-26 17:16   ` Brian Foster
2015-06-19 11:01 ` [PATCH 07/17] mkfs: structify input parameter passing Jan Ťulák
2015-06-26 17:16   ` Brian Foster
2015-06-19 11:01 ` [PATCH 08/17] mkfs: getbool is redundant Jan Ťulák
2015-06-26 17:17   ` Brian Foster
2015-06-30  1:32     ` Dave Chinner
2015-06-19 11:01 ` [PATCH 09/17] mkfs: use getnum_checked for all ranged parameters Jan Ťulák
2015-06-26 17:17   ` Brian Foster
2015-06-19 11:01 ` [PATCH 10/17] mkfs: add respecification detection to generic parsing Jan Ťulák
2015-06-26 17:17   ` Brian Foster
2015-06-19 11:02 ` [PATCH 11/17] mkfs: table based parsing for converted parameters Jan Ťulák
2015-06-26 17:17   ` Brian Foster
2015-06-19 11:02 ` [PATCH 12/17] mkfs: merge getnum Jan Ťulák
2015-06-26 17:17   ` Brian Foster
2015-06-19 11:02 ` [PATCH 13/17] mkfs: encode conflicts into parsing table Jan Ťulák
2015-06-26 17:17   ` Brian Foster
2015-06-30  3:57     ` Dave Chinner
2015-06-30 11:27       ` Brian Foster
2015-07-01  8:30         ` Jan Tulak
2015-06-19 11:02 ` [PATCH 14/17] mkfs: add string options to generic parsing Jan Ťulák
2015-06-26 19:32   ` Brian Foster
2015-06-19 11:02 ` [PATCH 15/17] mkfs: don't treat files as though they are block devices Jan Ťulák
2015-06-26 19:32   ` Brian Foster
2015-06-19 11:02 ` [PATCH 16/17] mkfs fix: handling of files Jan Ťulák
2015-06-26 19:32   ` Brian Foster
2015-06-19 11:02 ` [PATCH 17/17] mkfs: move spinodes crc check Jan Ťulák
2015-06-26 19:32   ` Brian Foster

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.