]> git.ipfire.org Git - thirdparty/xfsprogs-dev.git/commitdiff
bump revision number.
authorNathan Scott <nathans@sgi.com>
Tue, 15 May 2001 03:43:23 +0000 (03:43 +0000)
committerNathan Scott <nathans@sgi.com>
Tue, 15 May 2001 03:43:23 +0000 (03:43 +0000)
VERSION
debian/changelog
doc/CHANGES
include/xfs_ag.h
include/xfs_mount.h
man/man8/mkfs.xfs.8
mkfs/xfs_mkfs.c

diff --git a/VERSION b/VERSION
index 1032e3915830adb0c1b0bd7eaf88159c6db0e0e2..ec9832e1395c153b8a89ea06211c03777f614d3b 100644 (file)
--- a/VERSION
+++ b/VERSION
@@ -3,5 +3,5 @@
 #
 PKG_MAJOR=1
 PKG_MINOR=2
-PKG_REVISION=5
+PKG_REVISION=6
 PKG_BUILD=0
index 0115958840522dff654b930ee93927aff418a1a4..4f57b023e9d43bfc067177f9aec9850562d31945 100644 (file)
@@ -1,3 +1,11 @@
+xfsprogs (1.2.6) unstable; urgency=low
+
+  * Merge support for -d agsize=/su=/sw= (AG, stripe unit/width size)
+  * Merge support for dynamic configuration of default log size
+  * Document these updates, and fix a couple of man page typos too
+
+ -- Nathan Scott <nathans@debian.org>  Tue, 15 May 2001 12:34:17 +1000
+
 xfsprogs (1.2.5) unstable; urgency=low
 
   * Fix missing Makefile include entries for LVM headers
index ab72efe87d3e050c8fb206be6e6c564e6cff8fc9..7ab9d4bcbb6430ae9983f2753e1333ed9f4a5b2d 100644 (file)
@@ -1,4 +1,9 @@
 
+xfsprogs-1.2.6 (15 May 2001)
+       - merge support for -d agsize=/su=/sw= (AG, stripe unit/width size)
+       - merge support for dynamic configuration of default log size
+       - document these and fix a couple of man page typos too
+
 xfsprogs-1.2.5 (07 May 2001)
        - fix missing Makefile include entries for LVM headers
        - configure script default man path now /usr/share/man
index 86e4095f80b9ff38c97178f0d3598110f998d497..be0ddcef159a8fd2274b29fcaf8eaa97dd53495b 100644 (file)
@@ -215,10 +215,18 @@ xfs_extlen_t xfs_ag_min_blocks(int bl);
 #define        XFS_AG_MIN_BLOCKS(bl)   ((xfs_extlen_t)(XFS_AG_MIN_BYTES >> bl))
 #endif
 #if XFS_WANT_FUNCS || (XFS_WANT_SPACE && XFSSO_XFS_AG_BEST_BLOCKS)
-xfs_extlen_t xfs_ag_best_blocks(int bl);
-#define        XFS_AG_BEST_BLOCKS(bl)          xfs_ag_best_blocks(bl)
+xfs_extlen_t xfs_ag_best_blocks(int bl, xfs_drfsbno_t blks);
+#define        XFS_AG_BEST_BLOCKS(bl,blks)     xfs_ag_best_blocks(bl,blks)
 #else
-#define        XFS_AG_BEST_BLOCKS(bl)  ((xfs_extlen_t)(XFS_AG_BEST_BYTES >> bl))
+/*--#define    XFS_AG_BEST_BLOCKS(bl)  ((xfs_extlen_t)(XFS_AG_BEST_BYTES >> bl))*/
+/*
+ * Best is XFS_AG_BEST_BLOCKS at and below 64 Gigabyte filesystems, and
+ * XFS_AG_MAX_BLOCKS above 64 Gigabytes.
+ */
+#define        XFS_AG_BEST_BLOCKS(bl,blks)     ((xfs_extlen_t)((1LL << (36 - bl)) >= \
+                                                       blks) ? \
+                                                       ((xfs_extlen_t)(XFS_AG_BEST_BYTES >> bl)) : \
+                                                       XFS_AG_MAX_BLOCKS(bl))
 #endif
 #if XFS_WANT_FUNCS || (XFS_WANT_SPACE && XFSSO_XFS_AG_MAX_BLOCKS)
 xfs_extlen_t xfs_ag_max_blocks(int bl);
index 12c7528c4ae6100231205e2707692507c23ca4ee..f76fdcad2ed164f5b7f42a0e4c920b5dc1827cbc 100644 (file)
@@ -377,6 +377,7 @@ typedef struct xfs_mount {
 #define        XFS_WSYNC_READIO_LOG    15      /* 32K */
 #define        XFS_WSYNC_WRITEIO_LOG   14      /* 16K */
 
+#define xfs_force_shutdown(m,f) _xfs_force_shutdown(m,f,__FILE__,__LINE__);
 /* 
  * Flags sent to xfs_force_shutdown.
  */
@@ -478,7 +479,7 @@ int         xfs_mod_incore_sb_batch(xfs_mount_t *, xfs_mod_sb_t *, uint, int);
 int            xfs_readsb(xfs_mount_t *mp, dev_t);
 struct xfs_buf *xfs_getsb(xfs_mount_t *, int);
 void            xfs_freesb(xfs_mount_t *);
-void           xfs_force_shutdown(struct xfs_mount *, int);
+void           _xfs_force_shutdown(struct xfs_mount *, int, char *, int);
 int            xfs_syncsub(xfs_mount_t *, int, int, int *);
 void           xfs_xlatesb(void *, struct xfs_sb *, int, xfs_arch_t, __int64_t);
 extern struct vfsops xfs_vfsops;
index 4461bd95fd86133612eaad039116ee4c35fc33d8..fca06473a5e7cc0f0e746fb997f9f2ee048d7862 100644 (file)
@@ -54,6 +54,7 @@ If suffixed with \f3b\f1 then the size is converted by multiplying it
 by the filesystem's block size.
 If suffixed with \f3k\f1 then the size is converted by multiplying it by 1024.
 If suffixed with \f3m\f1 then the size is converted by multiplying it by
+1048576 (1024 * 1024).
 If suffixed with \f3g\f1 then the size is converted by multiplying it by
 1073741824 (1024 * 1024 * 1024).
 .TP
@@ -70,9 +71,9 @@ The block size is specified either as a base two logarithm value with
 .BR log= ,
 or in bytes with
 .BR size= .
-The default value is 4096 bytes (4 KB).  The minimum value for block
-size is 512; the maximum is 65536 (64 KB).  XFS on Linux currently
-only supports 4KB blocks.
+The default value is 4096 bytes (4 KB) on systems with a 4KB pagesize.
+The minimum value for block size is 512; the maximum is 65536 (64 KB).
+XFS on Linux currently only supports pagesize blocks.
 .TP
 .B \-d
 Data section options.
@@ -81,11 +82,14 @@ These options specify the location, size, and other parameters of the
 data section of the filesystem.
 The valid suboptions are:
 \f3agcount=\f1\f2value\f1,
+\f3agsize=\f1\f2value\f1,
 \f3file\f1[\f3=\f1\f2value\f1],
 \f3name=\f1\f2value\f1,
 \f3size=\f1\f2value\f1,
 \f3sunit=\f1\f2value\f1,
 \f3swidth=\f1\f2value\f1,
+\f3su=\f1\f2value\f1,
+\f3sw=\f1\f2value\f1,
 and
 \f3unwritten\f1[\f3=\f1\f2value\f1].
 .IP
@@ -108,6 +112,23 @@ to a very large number should be avoided, since this causes an unreasonable
 amount of CPU time to be used when the filesystem is close to full.
 .IP
 The
+.B agsize
+suboption is an alternative to using
+.B agcount.
+The argument provided to
+.B agsize
+is the desired size of the allocation group expressed in bytes
+(usually using the \f3m\f1 or \f3g\f1 suffixes).
+This value must be a multiple of the filesystem block size, and
+must be at least 16MB, and no more than 4GB, and may
+be automatically adjusted to properly align with the stripe geometry.
+The
+.B agcount
+suboption and the
+.B agsize
+suboption are mutually exclusive.
+.IP
+The
 .B name
 suboption can be used to specify the name of the special file containing
 the filesystem.
@@ -116,7 +137,6 @@ In this case, the log section must be specified as
 (with a size, see the
 .B \-l
 option below) and there can be no real-time section.
-Depending on the filesystem size, mkfs.xfs will try to 
 .IP
 The
 .B file
@@ -125,8 +145,7 @@ suboption is used to specify that the file given by the
 suboption is a regular file.
 The suboption value is either 0 or 1,
 with 1 signifying that the file is regular.
-This suboption is used only to make a filesystem image
-(for instance, a miniroot image).
+This suboption is used only to make a filesystem image.
 If the value is omitted then 1 is assumed.
 .IP
 The
@@ -141,17 +160,36 @@ less space than the size of the special file.
 The
 .B sunit
 suboption is used to specify the stripe unit for a RAID device or a
-logical volume.  The suboption value has to be specified in 512-byte
-block units.  This suboption ensures that data allocations will be
-stripe unit aligned when the current end of file is being extended and
-the file size is larger than 512KB.  Also inode allocations and the
-internal log will be stripe unit aligned.
+logical volume.
+The suboption value has to be specified in 512-byte block units.
+Use the
+.B su
+suboption to specify the stripe unit size in bytes.
+This suboption ensures that data allocations will be stripe unit aligned
+when the current end of file is being extended and the file size is larger
+than 512KB.
+Also inode allocations and the internal log will be stripe unit aligned.
+.IP
+The
+.B su
+suboption is an alternative to using
+.B sunit.
+The
+.B su
+suboption is used to specify the stripe unit for a RAID device or a
+striped logical volume.
+The suboption value has to be specified in bytes,
+(usually using the \f3m\f1 or \f3g\f1 suffixes).
+This value must be a multiple of the filesystem block size.
 .IP
 The
 .B swidth
 suboption is used to specify the stripe width for a RAID device or a
 striped logical volume.
 The suboption value has to be specified in 512-byte block units.
+Use the
+.B sw
+suboption to specify the stripe width size in bytes.
 This suboption is required if
 .B \-d sunit
 has been specified and it has to be a multiple of the 
@@ -161,8 +199,21 @@ The stripe width will be the preferred iosize returned in the
 .IR stat (2)
 system call.
 .IP
-When a filesystem is created on an LVM or an MD device, mkfs.xfs will
-automatically query the logical volume for appropriate 
+The
+.B sw
+suboption is an alternative to using
+.B swidth.
+The
+.B sw
+suboption is used to specify the stripe width for a RAID device or
+striped logical volume.
+The suboption value is expressed as a multiplier of the stripe unit,
+usually the same as the number of stripe members in the logical
+volume configuration, or data disks in a RAID device.
+.IP
+When a filesystem is created on a logical volume device,
+.I mkfs.xfs
+will automatically query the logical volume for appropriate 
 .B sunit
 and
 .B swidth
@@ -258,7 +309,9 @@ suboption is used to specify the size of the log section.
 .IP
 If the log is contained within the data section and 
 .B size
-isn't specified, mkfs will try to select a suitable log size depending
+isn't specified,
+.I mkfs.xfs
+will try to select a suitable log size depending
 on the size of the filesystem.  The actual logsize depends on the
 filesystem block size and the directory block size.
 .IP
index 7272293ad4744c857fa2762058ee7d18acd0632e..c201788580faf0d4b22a6157b5f5b6f04137d0aa 100644 (file)
@@ -84,6 +84,12 @@ char *dopts[] = {
        "swidth",
 #define D_UNWRITTEN    6
        "unwritten",
+#define D_AGSIZE       7
+       "agsize",
+#define D_SU           8
+       "su",
+#define D_SW           9
+       "sw",
        NULL
 };
 
@@ -352,6 +358,54 @@ get_subvol_stripe_wrapper(char *dfile, int type, int *sunit, int *swidth)
 }
 
 
+static void
+calc_stripe_factors(int dsu, int dsw, int *dsunit, int *dswidth)
+{
+       if (*dsunit || *dswidth) {
+               if (dsu || dsw) {
+                       fprintf(stderr,
+       "su/sw should not be used in conjunction with sunit/swidth\n");
+                       usage();
+               }
+
+               if ((*dsunit && !*dswidth) || (!*dsunit && *dswidth)) {
+                       fprintf(stderr,
+       "both sunit and swidth options have to be specified\n");
+                       usage();
+               }
+       }
+
+       if (dsu || dsw) {
+               if (*dsunit || *dswidth) {
+                       fprintf(stderr,
+       "sunit/swidth should not be used in conjunction with su/sw\n");
+                       usage();
+               }
+
+               if ((dsu && !dsw) || (!dsu && dsw)) {
+                       fprintf(stderr,
+       "both su and sw options have to be specified\n");
+                       usage();
+               }
+
+               if (dsu % BBSIZE) {
+                       fprintf(stderr, "su must be a multiple of %d\n",
+                                                               BBSIZE);
+                       usage();
+               }
+
+               *dsunit  = (int)BTOBBT(dsu);
+               *dswidth = *dsunit * dsw;
+       }
+
+       if (*dsunit && (*dswidth % *dsunit != 0)) {
+               fprintf(stderr,
+       "stripe width (%d) has to be a multiple of the stripe unit (%d)\n",
+                       *dswidth, *dsunit);
+               usage();
+       }
+}
+
 static int
 get_default_blocksize(void)
 {
@@ -384,6 +438,7 @@ main(int argc, char **argv)
        xfs_buf_t               *buf;
        int                     c;
        int                     daflag;
+       int                     dasize;
        xfs_drfsbno_t           dblocks;
        char                    *dfile;
        int                     dirblocklog;
@@ -391,6 +446,8 @@ main(int argc, char **argv)
        int                     dirversion;
        int                     do_overlap_checks;
        char                    *dsize;
+       int                     dsu;
+       int                     dsw;
        int                     dsunit;
        int                     dswidth;
        int                     extent_flagging;
@@ -441,6 +498,7 @@ main(int argc, char **argv)
        xfs_sb_t                *sbp;
        int                     sectlog;
        __uint64_t              tmp_agsize;
+       __uint64_t              tmp_logblocks;
        uuid_t                  uuid;
        int                     worst_freelist;
        libxfs_init_t           xi;
@@ -450,6 +508,7 @@ main(int argc, char **argv)
        progname = basename(argv[0]);
        agcount = 8;
        blflag = bsflag = 0;
+       dasize = daflag = 0;
        blocksize = get_default_blocksize();
        blocklog = libxfs_highbit32(blocksize);
        agsize = daflag = dblocks = 0;
@@ -468,7 +527,7 @@ main(int argc, char **argv)
        dfile = logfile = rtfile = NULL;
        dsize = logsize = rtsize = rtextsize = protofile = NULL;
        opterr = 0;
-       dsunit = dswidth = nodsflag = lalign = 0;
+       dsu = dsw = dsunit = dswidth = nodsflag = lalign = 0;
        do_overlap_checks = 1;
        extent_flagging = 0;
        force_fs_overwrite = 0;
@@ -538,6 +597,18 @@ main(int argc, char **argv)
                                                illegal(value, "d agcount");
                                        daflag = 1;
                                        break;
+                               case D_AGSIZE:
+                                       if (!value)
+                                               reqval('d', dopts, D_AGSIZE);
+                                       if (dasize)
+                                               respec('d', dopts, D_AGSIZE);
+                                       if (blflag || bsflag)
+                                               agsize = cvtnum(blocksize,
+                                                               value);
+                                       else
+                                               agsize = cvtnum(0, value);
+                                       dasize = 1;
+                                       break;
                                case D_FILE:
                                        if (!value)
                                                value = "1";
@@ -566,14 +637,36 @@ main(int argc, char **argv)
                                                reqval('d', dopts, D_SUNIT);
                                        if (dsunit)
                                                respec('d', dopts, D_SUNIT);
-                                       dsunit = cvtnum(0, value);
+                                       if (blflag || bsflag)
+                                               dsunit = cvtnum(blocksize,
+                                                               value);
+                                       else
+                                               dsunit = cvtnum(0, value);
                                        break;
                                case D_SWIDTH:
                                        if (!value)
                                                reqval('d', dopts, D_SWIDTH);
                                        if (dswidth)
                                                respec('d', dopts, D_SWIDTH);
-                                       dswidth = cvtnum(0, value);
+                                       if (blflag || bsflag)
+                                               dswidth = cvtnum(blocksize,
+                                                                value);
+                                       else
+                                               dswidth = cvtnum(0, value);
+                                       break;
+                               case D_SU:
+                                       if (!value)
+                                               reqval('d', dopts, D_SU);
+                                       if (dsu)
+                                               respec('d', dopts, D_SU);
+                                       dsu = cvtnum(0, value);
+                                       break;
+                               case D_SW:
+                                       if (!value)
+                                               reqval('d', dopts, D_SW);
+                                       if (dsw)
+                                               respec('d', dopts, D_SW);
+                                       dsw = cvtnum(0, value);
                                        break;
                                case D_UNWRITTEN:
                                        if (!value)
@@ -927,6 +1020,13 @@ main(int argc, char **argv)
                }
                break;
        }
+
+       if (daflag && dasize) {
+               fprintf(stderr,
+       "both -d agcount= and agsize= specified, use one or the other\n");
+               usage();
+       }
+
        if (!daflag)
                agcount = 8;
 
@@ -1083,18 +1183,7 @@ main(int argc, char **argv)
                usage();
        }
 
-       if ((dsunit && !dswidth) || (!dsunit && dswidth)) {
-               fprintf(stderr,
-"both sunit and swidth options have to be specified\n");
-               usage();
-       }
-
-       if (dsunit && dswidth % dsunit != 0) {
-               fprintf(stderr,
-"mount: stripe width (%d) has to be a multiple of the stripe unit (%d)\n",
-                       dswidth, dsunit);
-               return 1;
-       }
+       calc_stripe_factors(dsu, dsw, &dsunit, &dswidth);
 
        /* other global variables */
        sectlog = 9;            /* i.e. 512 bytes */
@@ -1266,9 +1355,21 @@ main(int argc, char **argv)
        } else if (!loginternal && !xi.logdev)
                logblocks = 0;
        else if (loginternal && !logsize) {
-               logblocks = MAX(XFS_DFL_LOG_SIZE, i * XFS_DFL_LOG_FACTOR);
-                logblocks = MAX(logblocks, dblocks / 8192); 
+               /*
+                * logblocks grows from min_logblocks to XFS_MAX_LOG_BLOCKS
+                * at 1TB
+                *
+                * 8192 = 1TB / MAX_LOG_BYTES
+                */
+               logblocks = (dblocks << blocklog) / 8192;
+               logblocks = logblocks >> blocklog;
+               logblocks = MAX(min_logblocks, logblocks);
+                logblocks = MAX(logblocks,
+                               MAX(XFS_DFL_LOG_SIZE, i * XFS_DFL_LOG_FACTOR));
                 logblocks = MIN(logblocks, XFS_MAX_LOG_BLOCKS); 
+               if ((logblocks << blocklog) > XFS_MAX_LOG_BYTES) {
+                       logblocks = XFS_MAX_LOG_BYTES >> blocklog;
+               }
         } 
        if (logblocks < min_logblocks) {
                fprintf(stderr,
@@ -1307,16 +1408,62 @@ main(int argc, char **argv)
                rtextents = rtblocks = 0;
                nbmblocks = 0;
        }
-       agsize = dblocks / agcount + (dblocks % agcount != 0);
+
+       if (dasize) {
+               /*
+                * If the specified agsize isn't a multiple of fs blks,
+                * complain.
+                */
+               if (agsize % blocksize) {
+                       fprintf(stderr,
+                       "agsize (%lld) not a multiple of fs blk size (%d)\n",
+                               (long long)agsize, blocksize);
+                       usage();
+               }
+
+               agsize /= blocksize;
+
+               /*
+                * If the specified agsize is too small, or too large,
+                * complain.
+                */
+               if (agsize < XFS_AG_MIN_BLOCKS(blocklog)) {
+                       fprintf(stderr,
+                       "agsize (%lldb) too small, need at least %lld blocks\n",
+                               (long long)agsize,
+                               (long long)XFS_AG_MIN_BLOCKS(blocklog));
+                       usage();
+               }
+
+               if (agsize > XFS_AG_MAX_BLOCKS(blocklog)) {
+                       fprintf(stderr,
+                       "agsize (%lldb) too big, maximum is %lld blocks\n",
+                               (long long)agsize,
+                               (long long)XFS_AG_MAX_BLOCKS(blocklog));
+                       usage();
+               }
+
+               if (agsize > dblocks)  {
+                       fprintf(stderr,
+                       "agsize (%lldb) too big, data area is %lld blocks\n",
+                               (long long)agsize, (long long)dblocks);
+                       usage();
+               }
+
+               agcount = dblocks / agsize + (dblocks % agsize != 0);
+       } else {
+               agsize = dblocks / agcount + (dblocks % agcount != 0);
+       }
 
        /*
-        * If the ag size is too small, complain if agcount was specified,
-        * and fix it otherwise.
+        * If the ag size is too small, complain if agcount/agsize was
+        * specified, and fix it otherwise.
         */
        if (agsize < XFS_AG_MIN_BLOCKS(blocklog)) {
-               if (daflag) {
+               if (daflag || dasize) {
                        fprintf(stderr,
-                               "too many allocation groups for size\n");
+                               "too many allocation groups for size = %lld\n",
+                               (long long)agsize);
                        fprintf(stderr, "need at most %lld allocation groups\n",
                                (long long)
                                (dblocks / XFS_AG_MIN_BLOCKS(blocklog) +
@@ -1326,18 +1473,20 @@ main(int argc, char **argv)
                agsize = XFS_AG_MIN_BLOCKS(blocklog);
                if (dblocks < agsize)
                        agcount = 1;
-               else {
+               else
                        agcount = dblocks / agsize;
-                       agsize = dblocks / agcount + (dblocks % agcount != 0);
-               }
+
+               agsize = dblocks / agcount + (dblocks % agcount != 0);
        }
+
        /*
-        * If the ag size is too large, complain if agcount was specified,
-        * and fix it otherwise.
+        * If the ag size is too large, complain if agcount/agsize was
+        * specified, and fix it otherwise.
         */
        else if (agsize > XFS_AG_MAX_BLOCKS(blocklog)) {
-               if (daflag) {
-                       fprintf(stderr, "too few allocation groups for size\n");
+               if (daflag || dasize) {
+                       fprintf(stderr, "too few allocation groups for size = %lld\n",
+                               (long long)agsize);
                        fprintf(stderr,
                                "need at least %lld allocation groups\n",
                                (long long)
@@ -1347,16 +1496,15 @@ main(int argc, char **argv)
                }
                agsize = XFS_AG_MAX_BLOCKS(blocklog);
                agcount = dblocks / agsize + (dblocks % agsize != 0);
-               agsize = dblocks / agcount + (dblocks % agcount != 0);
        }
        /*
         * If agcount was not specified, and agsize is larger than
         * we'd like, make it the size we want.
         */
-       if (!daflag && agsize > XFS_AG_BEST_BLOCKS(blocklog)) {
-               agsize = XFS_AG_BEST_BLOCKS(blocklog);
+       if (!daflag && !dasize &&
+           (agsize > XFS_AG_BEST_BLOCKS(blocklog, dblocks))) {
+               agsize = XFS_AG_BEST_BLOCKS(blocklog, dblocks);
                agcount = dblocks / agsize + (dblocks % agsize != 0);
-               agsize = dblocks / agcount + (dblocks % agcount != 0);
        }
        /*
         * If agcount is too large, make it smaller.
@@ -1364,6 +1512,13 @@ main(int argc, char **argv)
        if (agcount > XFS_MAX_AGNUMBER + 1) {
                agcount = XFS_MAX_AGNUMBER + 1;
                agsize = dblocks / agcount + (dblocks % agcount != 0);
+
+               if (dasize || daflag)
+                       fprintf(stderr,
+               "agsize set to %lld, agcount %lld > max (%lld)\n",
+                               (long long)agsize, (long long)agcount,
+                               (long long)XFS_MAX_AGNUMBER+1);
+
                if (agsize > XFS_AG_MAX_BLOCKS(blocklog)) {
                        /*
                         * We're confused.
@@ -1414,21 +1569,31 @@ main(int argc, char **argv)
                 */
                if ((agsize % dsunit) != 0) {
                        /*
-                        * round up to stripe unit boundary. Also make sure 
+                        * Round up to stripe unit boundary. Also make sure 
                         * that agsize is still larger than 
                         * XFS_AG_MIN_BLOCKS(blocklog)
                         */
                        tmp_agsize = ((agsize + (dsunit - 1))/ dsunit) * dsunit;
+                       /*
+                        * Round down to stripe unit boundary if rounding up
+                        * created an AG size that is larger than the AG max.
+                        */
+                       if (tmp_agsize > XFS_AG_MAX_BLOCKS(blocklog))
+                               tmp_agsize = ((agsize) / dsunit) * dsunit;
                        if ((tmp_agsize >= XFS_AG_MIN_BLOCKS(blocklog)) &&
                            (tmp_agsize <= XFS_AG_MAX_BLOCKS(blocklog)) &&
                            !daflag) {
                                agsize = tmp_agsize;
                                agcount = dblocks/agsize + 
                                                (dblocks % agsize != 0);
+                               if (dasize || daflag)
+                                       fprintf(stderr,
+                                       "agsize rounded to %lld, swidth = %d\n",
+                                               (long long)agsize, dswidth);
                        } else {
-                               if (nodsflag)
+                               if (nodsflag) {
                                        dsunit = dswidth = 0;
-                               else { 
+                               else { 
                                        fprintf(stderr,
 "Allocation group size %lld is not a multiple of the stripe unit %d\n",
                                                (long long)agsize, dsunit);
@@ -1479,16 +1644,24 @@ main(int argc, char **argv)
                 */
                if (dsunit && ((logstart % dsunit) != 0)) {
                        logstart = ((logstart + (dsunit - 1))/dsunit) * dsunit;
-
                        /* 
                         * Make sure that the log size is a multiple of the
                         * stripe unit
                         */
                        if ((logblocks % dsunit) != 0) {
-                           if (!lsflag) 
-                               logblocks = ((logblocks + (dsunit - 1))
-                                                       /dsunit) * dsunit;
-                           else {
+                           if (!lsflag) {
+                               tmp_logblocks = ((logblocks + (dsunit - 1))
+                                                       / dsunit) * dsunit;
+                               /*
+                                * If the log is too large, round down
+                                * instead of round up
+                                */
+                               if ((tmp_logblocks > XFS_MAX_LOG_BLOCKS) ||
+                                   ((tmp_logblocks << blocklog) > XFS_MAX_LOG_BYTES)) {
+                                       tmp_logblocks = (logblocks / dsunit) * dsunit;
+                               }
+                               logblocks = tmp_logblocks;
+                           } else {
                                fprintf(stderr,
        "internal log size %lld is not a multiple of the stripe unit %d\n", 
                                        (long long)logblocks, dsunit);
@@ -1507,6 +1680,7 @@ main(int argc, char **argv)
                }
        } else
                logstart = 0;
+
        if (label)
                strncpy(sbp->sb_fname, label, sizeof(sbp->sb_fname));
        sbp->sb_magicnum = XFS_SB_MAGIC;
@@ -1985,7 +2159,8 @@ usage(void)
        fprintf(stderr, "Usage: %s\n\
 /* blocksize */                [-b log=n|size=num]\n\
 /* data subvol */      [-d agcount=n,agsize=n,file,name=xxx,size=num,\n\
-                           sunit=value,swidth=value,unwritten=0|1]\n\
+                           sunit=value,swidth=value,unwritten=0|1,\n\
+                           su=value,sw=value]\n\
 /* inode size */       [-i log=n|perblock=n|size=num,maxpct=n]\n\
 /* log subvol */       [-l agnum=n,internal,size=num,logdev=xxx]\n\
 /* naming */           [-n log=n|size=num|version=n]\n\
@@ -1995,11 +2170,13 @@ usage(void)
 /* version */          [-V]\n\
 /* realtime subvol */  [-r extsize=num,size=num,rtdev=xxx]\n\
                        devicename\n\
-devicename is required unless -d name=xxx is given\n\
-internal 1000 block log is default unless overridden or using a volume\n\
-manager with log\n\
-num is xxx (bytes), or xxxb (blocks), or xxxk (xxx KB), or xxxm (xxx MB)\n\
-value is xxx (512 blocks)\n",
+<devicename> is required unless -d name=xxx is given.\n\
+Internal log by default, size is scaled from 1,000 blocks to 32,768 blocks\n\
+based on the filesystem size.  Default log reaches its largest size at 1TB.\n\
+This can be overridden with the -l options or using a volume manager with a\n\
+log subvolume.\n\
+<num> is xxx (bytes), or xxxb (blocks), or xxxk (xxx KB), or xxxm (xxx MB)\n\
+<value> is xxx (512 blocks).\n",
                progname);
        exit(1);
 }