* http://oss.sgi.com/projects/GenInfo/SGIGPLNoticeExplan/
*/
+#include <fstyp.h>
+#include <stdio.h>
+#include <volume.h>
+#include <mountinfo.h>
#include <libxfs.h>
-#include <fcntl.h>
-#include <errno.h>
+
#include "xfs_mkfs.h"
-#include "proto.h"
-#include "volume.h"
#include "maxtrres.h"
-#include "mountinfo.h"
-
-#if HAVE_LIBLVM
- #include "lvm_user.h"
-
- char *cmd; /* Not used. liblvm is broken */
- int opt_d; /* Same thing */
-#endif
-
-#include "md-int.h"
+#include "proto.h"
/*
* Prototypes for internal functions.
"swidth",
#define D_UNWRITTEN 6
"unwritten",
+#define D_AGSIZE 7
+ "agsize",
+#define D_SU 8
+ "su",
+#define D_SW 9
+ "sw",
NULL
};
(XFS_BM_MAXLEVELS(mp, XFS_DATA_FORK) - 1) + (rb)))
static void
-get_subvol_stripe_wrapper(char *dfile, int type, int *sunit, int *swidth)
+calc_stripe_factors(int dsu, int dsw, int *dsunit, int *dswidth)
{
- struct stat64 sb;
- struct md_array_info_s md;
-#if HAVE_LIBLVM
- lv_t *lv;
- char *vgname;
-#endif
-
- if (!dfile)
- return;
-
- if (stat64 (dfile, &sb)) {
- fprintf (stderr, "Could not stat %s\n", dfile);
- usage();
- }
-
- /* MD volume */
- if (sb.st_rdev >> 8 == MD_MAJOR) {
- int fd;
-
- /* Open device */
- fd = open (dfile, O_RDONLY);
- if (fd == -1)
- return;
-
- /* Is this thing on... */
- if (ioctl (fd, GET_ARRAY_INFO, &md)) {
- fprintf (stderr, "Error getting array info from %s\n",
- dfile);
+ if (*dsunit || *dswidth) {
+ if (dsu || dsw) {
+ fprintf(stderr,
+ "su/sw should not be used in conjunction with sunit/swidth\n");
usage();
}
- /* Check state */
- if (md.state) {
- fprintf (stderr, "MD array %s not in clean state\n",
- dfile);
+ if ((*dsunit && !*dswidth) || (!*dsunit && *dswidth)) {
+ fprintf(stderr,
+ "both sunit and swidth options have to be specified\n");
usage();
}
-
- /* Deduct a disk from stripe width on RAID4/5 */
- if (md.level == 4 || md.level == 5)
- md.nr_disks--;
-
- /* Update sizes */
- *sunit = md.chunk_size >> 9;
- *swidth = *sunit * md.nr_disks;
-
- return;
}
-#if HAVE_LIBLVM
- /* LVM volume */
- if (sb.st_rdev >> 8 == LVM_BLK_MAJOR) {
-
- /* Find volume group */
- if (! (vgname = vg_name_of_lv (dfile))) {
- fprintf (stderr, "Can't find volume group for %s\n",
- dfile);
- usage();
- }
-
- /* Logical volume */
- if (! lvm_tab_lv_check_exist (dfile)) {
- fprintf (stderr, "Logical volume %s doesn't exist!\n",
- dfile);
+ if (dsu || dsw) {
+ if (*dsunit || *dswidth) {
+ fprintf(stderr,
+ "sunit/swidth should not be used in conjunction with su/sw\n");
usage();
}
-
- /* Get status */
- if (lv_status_byname (vgname, dfile, &lv) < 0 || lv == NULL) {
- fprintf (stderr, "Could not get status info from %s\n",
- dfile);
+
+ if ((dsu && !dsw) || (!dsu && dsw)) {
+ fprintf(stderr,
+ "both su and sw options have to be specified\n");
usage();
}
-
- /* Check that data is consistent */
- if (lv_check_consistency (lv) < 0) {
- fprintf (stderr, "Logical volume %s is inconsistent\n",
- dfile);
+
+ if (dsu % BBSIZE) {
+ fprintf(stderr, "su must be a multiple of %d\n",
+ BBSIZE);
usage();
}
-
- /* Update sizes */
- *sunit = lv->lv_stripesize;
- *swidth = lv->lv_stripes * lv->lv_stripesize;
-
- return;
+
+ *dsunit = (int)BTOBBT(dsu);
+ *dswidth = *dsunit * dsw;
}
-#endif /* HAVE_LIBLVM */
-}
+ 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)
return (1 << XFS_DFL_BLOCKSIZE_LOG);
}
+static int
+check_overwrite(char *device)
+{
+ char *type;
+
+ if (device && *device) {
+ if ((type = fstype(device)) != NULL) {
+ fprintf(stderr,
+ "%s: %s appears to contain an existing filesystem (%s).\n",
+ progname, device, type);
+ return 1;
+ }
+ if ((type = pttype(device)) != NULL) {
+ fprintf(stderr,
+ "%s: %s appears to contain a partition table (%s).\n",
+ progname, device, type);
+ return 1;
+ }
+ }
+ return 0;
+}
+
int
main(int argc, char **argv)
xfs_buf_t *buf;
int c;
int daflag;
+ int dasize;
xfs_drfsbno_t dblocks;
char *dfile;
int dirblocklog;
int dirversion;
int do_overlap_checks;
char *dsize;
+ int dsu;
+ int dsw;
int dsunit;
int dswidth;
int extent_flagging;
- int force_fs_overwrite;
+ int force_overwrite;
int i;
int iaflag;
int ilflag;
int ipflag;
int isflag;
int isize;
+ char *label = NULL;
int laflag;
int lalign;
int ldflag;
xfs_sb_t *sbp;
int sectlog;
__uint64_t tmp_agsize;
+ __uint64_t tmp_logblocks;
uuid_t uuid;
int worst_freelist;
libxfs_init_t xi;
progname = basename(argv[0]);
agcount = 8;
blflag = bsflag = 0;
+ dasize = daflag = 0;
blocksize = get_default_blocksize();
blocklog = libxfs_highbit32(blocksize);
agsize = daflag = dblocks = 0;
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;
+ force_overwrite = 0;
worst_freelist = 0;
- while ((c = getopt(argc, argv, "b:d:i:l:n:p:qr:CfV")) != EOF) {
+ while ((c = getopt(argc, argv, "b:d:i:l:L:n:p:qr:CfV")) != EOF) {
switch (c) {
case 'C':
do_overlap_checks = 0;
break;
case 'f':
- force_fs_overwrite = 1;
+ force_overwrite = 1;
break;
case 'b':
p = optarg;
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";
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)
}
}
break;
+ case 'L':
+ if (strlen(optarg) > sizeof(sbp->sb_fname))
+ illegal(optarg, "L");
+ label = optarg;
+ break;
case 'n':
p = optarg;
while (*p != '\0') {
break;
case 'V':
printf("%s version %s\n", progname, VERSION);
- break;
+ exit(0);
case '?':
unknown(optopt, "");
}
}
break;
}
+
+ if (daflag && dasize) {
+ fprintf(stderr,
+ "both -d agcount= and agsize= specified, use one or the other\n");
+ usage();
+ }
+
if (!daflag)
agcount = 8;
if (dbytes % XFS_MIN_BLOCKSIZE) {
fprintf(stderr,
"illegal data length %lld, not a multiple of %d\n",
- dbytes, XFS_MIN_BLOCKSIZE);
+ (long long)dbytes, XFS_MIN_BLOCKSIZE);
usage();
}
dblocks = (xfs_drfsbno_t)(dbytes >> blocklog);
if (dbytes % blocksize)
fprintf(stderr,
"warning: data length %lld not a multiple of %d, truncated to %lld\n",
- dbytes, blocksize, dblocks << blocklog);
+ (long long)dbytes, blocksize,
+ (long long)(dblocks << blocklog));
}
if (ipflag) {
inodelog = blocklog - libxfs_highbit32(inopblock);
if (logbytes % XFS_MIN_BLOCKSIZE) {
fprintf(stderr,
"illegal log length %lld, not a multiple of %d\n",
- logbytes, XFS_MIN_BLOCKSIZE);
+ (long long)logbytes, XFS_MIN_BLOCKSIZE);
usage();
}
logblocks = (xfs_drfsbno_t)(logbytes >> blocklog);
if (logbytes % blocksize)
fprintf(stderr,
"warning: log length %lld not a multiple of %d, truncated to %lld\n",
- logbytes, blocksize, logblocks << blocklog);
+ (long long)logbytes, blocksize,
+ (long long)(logblocks << blocklog));
}
#ifdef HAVE_VOLUME_MANAGER
if (xi.risfile && (!rtsize || !xi.rtname)) {
if (rtbytes % XFS_MIN_BLOCKSIZE) {
fprintf(stderr,
"illegal rt length %lld, not a multiple of %d\n",
- rtbytes, XFS_MIN_BLOCKSIZE);
+ (long long)rtbytes, XFS_MIN_BLOCKSIZE);
usage();
}
rtblocks = (xfs_drfsbno_t)(rtbytes >> blocklog);
if (rtbytes % blocksize)
fprintf(stderr,
"warning: rt length %lld not a multiple of %d, truncated to %lld\n",
- rtbytes, blocksize, rtblocks << blocklog);
+ (long long)rtbytes, blocksize,
+ (long long)(rtblocks << blocklog));
}
/*
* If specified, check rt extent size against its constraints.
if (rtextbytes % blocksize) {
fprintf(stderr,
"illegal rt extent size %lld, not a multiple of %d\n",
- rtextbytes, blocksize);
+ (long long)rtextbytes, blocksize);
usage();
}
if (rtextbytes > XFS_MAX_RTEXTSIZE) {
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 */
}
/*
- * Check whether this partition contains a known filesystem.
+ * Ok, Linux only has a 1024-byte resolution on device _size_,
+ * and the sizes below are in basic 512-byte blocks,
+ * so if we have (size % 2), on any partition, we can't get
+ * to the last 512 bytes. Just chop it down by a block.
*/
- if (force_fs_overwrite == 0) {
- char *fstyp;
- int fsfound = 0;
+ xi.dsize -= (xi.dsize % 2);
+ xi.rtsize -= (xi.rtsize % 2);
+ xi.logBBsize -= (xi.logBBsize % 2);
- fstyp = (char *) mnt_known_fs_type (dfile);
-
- if (fstyp != NULL) {
+ if (!force_overwrite) {
+ if (check_overwrite(dfile) ||
+ check_overwrite(logfile) ||
+ check_overwrite(xi.rtname)) {
fprintf(stderr, "%s: "
- "%s appears to contain an existing filesystem (%s).\n",
- progname, dfile, fstyp);
- fsfound = 1;
- }
-
- if (logfile && *logfile) {
- fstyp = (char *) mnt_known_fs_type (logfile);
-
- if (fstyp != NULL) {
- fprintf(stderr, "%s: "
- "%s appears to contain an existing filesystem (%s).\n",
- progname, logfile, fstyp);
- fsfound = 1;
- }
- }
-
- if (xi.rtname && *xi.rtname) {
- fstyp = (char *) mnt_known_fs_type (xi.rtname);
-
- if (fstyp != NULL) {
- fprintf(stderr, "%s: "
- "%s appears to contain an existing filesystem (%s).\n",
- progname, xi.rtname, fstyp);
- fsfound = 1;
- }
- }
-
- if (fsfound) {
- fprintf(stderr, "%s: "
- "Use the -f option to force overwrite\n",
+ "Use the -f option to force overwrite.\n",
progname);
exit(1);
}
if (dsize && xi.dsize > 0 && dblocks > DTOBT(xi.dsize)) {
fprintf(stderr,
"size %s specified for data subvolume is too large, maximum is %lld blocks\n",
- dsize, DTOBT(xi.dsize));
+ dsize, (long long)DTOBT(xi.dsize));
usage();
} else if (!dsize && xi.dsize > 0)
dblocks = DTOBT(xi.dsize);
if (dblocks < XFS_MIN_DATA_BLOCKS) {
fprintf(stderr,
"size %lld of data subvolume is too small, minimum %d blocks\n",
- dblocks, XFS_MIN_DATA_BLOCKS);
+ (long long)dblocks, XFS_MIN_DATA_BLOCKS);
usage();
}
if (xi.logdev && loginternal) {
if (logsize && xi.logBBsize > 0 && logblocks > DTOBT(xi.logBBsize)) {
fprintf(stderr,
"size %s specified for log subvolume is too large, maximum is %lld blocks\n",
- logsize, DTOBT(xi.logBBsize));
+ logsize, (long long)DTOBT(xi.logBBsize));
usage();
} else if (!logsize && xi.logBBsize > 0)
logblocks = DTOBT(xi.logBBsize);
usage();
} else if (loginternal && logsize && logblocks >= dblocks) {
fprintf(stderr, "size %lld too large for internal log\n",
- logblocks);
+ (long long)logblocks);
usage();
} 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,
"log size %lld blocks too small, minimum size is %d blocks\n",
- logblocks, min_logblocks);
+ (long long)logblocks, min_logblocks);
usage();
}
if (logblocks > XFS_MAX_LOG_BLOCKS) {
fprintf(stderr,
"log size %lld blocks too large, maximum size is %d blocks\n",
- logblocks, XFS_MAX_LOG_BLOCKS);
+ (long long)logblocks, XFS_MAX_LOG_BLOCKS);
usage();
}
if ((logblocks << blocklog) > XFS_MAX_LOG_BYTES) {
fprintf(stderr,
"log size %lld bytes too large, maximum size is %d bytes\n",
- logblocks << blocklog, XFS_MAX_LOG_BYTES);
+ (long long)(logblocks << blocklog), XFS_MAX_LOG_BYTES);
usage();
}
if (rtsize && xi.rtsize > 0 && rtblocks > DTOBT(xi.rtsize)) {
fprintf(stderr,
"size %s specified for rt subvolume is too large, maximum is %lld blocks\n",
- rtsize, DTOBT(xi.rtsize));
+ rtsize, (long long)DTOBT(xi.rtsize));
usage();
} else if (!rtsize && xi.rtsize > 0)
rtblocks = DTOBT(xi.rtsize);
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",
- dblocks / XFS_AG_MIN_BLOCKS(blocklog) +
- (dblocks % XFS_AG_MIN_BLOCKS(blocklog) != 0));
+ (long long)
+ (dblocks / XFS_AG_MIN_BLOCKS(blocklog) +
+ (dblocks % XFS_AG_MIN_BLOCKS(blocklog) != 0)));
usage();
}
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",
- dblocks / XFS_AG_MAX_BLOCKS(blocklog) +
- (dblocks % XFS_AG_MAX_BLOCKS(blocklog) != 0));
+ (long long)
+ (dblocks / XFS_AG_MAX_BLOCKS(blocklog) +
+ (dblocks % XFS_AG_MAX_BLOCKS(blocklog) != 0)));
usage();
}
agsize = XFS_AG_MAX_BLOCKS(blocklog);
agcount = dblocks / agsize + (dblocks % agsize != 0);
- agsize = dblocks / agcount + (dblocks % agcount != 0);
}
+
+ /*
+ * If the last AG is too small, reduce the filesystem size
+ * and drop the blocks.
+ */
+ if ( dblocks % agsize != 0 &&
+ (dblocks % agsize < XFS_AG_MIN_BLOCKS(blocklog))) {
+ dblocks = (xfs_drfsbno_t)((agcount - 1) * agsize);
+ agcount--;
+ ASSERT(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 the last AG is too small, reduce the filesystem size
+ * and drop the blocks.
+ */
+ if ( dblocks % agsize != 0 &&
+ (dblocks % agsize < XFS_AG_MIN_BLOCKS(blocklog))) {
+ dblocks = (xfs_drfsbno_t)((agcount - 1) * agsize);
+ agcount--;
+ ASSERT(agcount != 0);
+ }
}
+
/*
* If agcount is too large, make it smaller.
*/
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.
fprintf(stderr, "%s: "
"Specified data stripe unit %d is not the same as the xlv stripe unit %d\n",
progname, dsunit, xlv_dsunit);
- exit(1);
}
if (xlv_dswidth && xlv_dswidth != dswidth) {
fprintf(stderr, "%s: "
-"Specified data stripe width (%d) is not the same as the xlv stripe width (%d)\n",
+"Specified data stripe width %d is not the same as the xlv stripe width %d\n",
progname, dswidth, xlv_dswidth);
- exit(1);
}
} else {
dsunit = xlv_dsunit;
*/
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",
- agsize, dsunit);
+ (long long)agsize, dsunit);
exit(1);
}
}
}
+ if ((agsize % dswidth) == 0) {
+ /* This is a non-optimal configuration because all AGs
+ * start on the same disk in the stripe. Decreasing
+ * the AG size by one sunit will guarantee that this
+ * does not happen
+ */
+ tmp_agsize = agsize - dsunit;
+ if (tmp_agsize < XFS_AG_MIN_BLOCKS(blocklog))
+ tmp_agsize = agsize + dsunit;
+ if (daflag || dasize) {
+ fprintf(stderr,
+"Warning: AG size is a multiple of stripe width. This can cause performance\n"
+"problems by aligning all AGs on the same disk. To avoid this, rerun mkfs with\n"
+"an AG size that is one stripe unit smaller, for example %lld\n",
+ tmp_agsize);
+ } else {
+ agsize = tmp_agsize;
+ agcount = dblocks/agsize + (dblocks % agsize != 0);
+ /*
+ * If the last AG is too small, reduce the
+ * filesystem size and drop the blocks.
+ */
+ if ( dblocks % agsize != 0 &&
+ (dblocks % agsize <
+ XFS_AG_MIN_BLOCKS(blocklog))) {
+ dblocks = (xfs_drfsbno_t)((agcount - 1) * agsize);
+ agcount--;
+ ASSERT(agcount != 0);
+ }
+ }
+ }
} else {
if (nodsflag)
dsunit = dswidth = 0;
protostring = setup_proto(protofile);
bsize = 1 << (blocklog - BBSHIFT);
- buf = libxfs_getbuf(xi.ddev, XFS_SB_DADDR, 1);
mp = &mbuf;
sbp = &mp->m_sb;
bzero(mp, sizeof(xfs_mount_t));
sbp->sb_agblklog = (__uint8_t)libxfs_log2_roundup((unsigned int)agsize);
mp->m_blkbb_log = sbp->sb_blocklog - BBSHIFT;
if (loginternal) {
+ /*
+ * Readjust the log size to fit within an AG if it was sized
+ * automaticly.
+ */
+ if (!logsize) {
+ logblocks = MIN(logblocks,
+ agsize - XFS_PREALLOC_BLOCKS(mp));
+ }
if (logblocks > agsize - XFS_PREALLOC_BLOCKS(mp)) {
fprintf(stderr,
"internal log size %lld too large, must fit in allocation group\n",
- logblocks);
+ (long long)logblocks);
usage();
}
if (laflag) {
if (logagno >= agcount) {
fprintf(stderr,
"log ag number %d too large, must be less than %lld\n",
- logagno, agcount);
+ logagno, (long long)agcount);
usage();
}
} else
*/
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 ((logblocks % dsunit) != 0) {
+ 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",
- logblocks, dsunit);
+ (long long)logblocks, dsunit);
usage();
- }
+ }
+ }
if (logblocks > agsize-XFS_FSB_TO_AGBNO(mp,logstart)) {
fprintf(stderr,
"Due to stripe alignment, the internal log size %lld is too large.\n"
"Must fit in allocation group\n",
- logblocks);
+ (long long)logblocks);
usage();
}
lalign = 1;
}
} else
logstart = 0;
+
+ if (label)
+ strncpy(sbp->sb_fname, label, sizeof(sbp->sb_fname));
sbp->sb_magicnum = XFS_SB_MAGIC;
sbp->sb_blocksize = blocksize;
sbp->sb_dblocks = dblocks;
sbp->sb_fdblocks = dblocks - agcount * XFS_PREALLOC_BLOCKS(mp) -
(loginternal ? logblocks : 0);
sbp->sb_frextents = 0; /* will do a free later */
- sbp->sb_uquotino = sbp->sb_pquotino = 0;
+ sbp->sb_uquotino = sbp->sb_gquotino = 0;
sbp->sb_qflags = 0;
sbp->sb_unit = dsunit;
sbp->sb_width = dswidth;
XFS_SB_VERSION_MKFS(iaflag, dsunit != 0, extent_flagging,
dirversion == 2);
+ /*
+ * Zero out the first 68k in on the device, to obliterate any old
+ * filesystem signatures out there. This should take care of
+ * swap (somewhere around the page size), jfs (32k),
+ * ext[2,3] and reiser (64k) - and hopefully all else.
+ */
+
+ buf = libxfs_getbuf(xi.ddev, 0, 136);
+ bzero(XFS_BUF_PTR(buf), 136*BBSIZE);
+ libxfs_writebuf(buf, 1);
+
+ /* OK, now write the superblock */
+ buf = libxfs_getbuf(xi.ddev, XFS_SB_DADDR, 1);
bzero(XFS_BUF_PTR(buf), BBSIZE);
libxfs_xlate_sb(XFS_BUF_PTR(buf), sbp, -1, ARCH_CONVERT,
XFS_SB_ALL_BITS);
"naming =version %-14d bsize=%-6d\n"
"log =%-22s bsize=%-6d blocks=%lld\n"
"realtime =%-22s extsz=%-6d blocks=%lld, rtextents=%lld\n",
- dfile, isize, agcount, agsize,
- "", blocksize, dblocks, sbp->sb_imax_pct,
+ dfile, isize, (long long)agcount, (long long)agsize,
+ "", blocksize, (long long)dblocks, sbp->sb_imax_pct,
"", dsunit, dswidth, extent_flagging,
dirversion, dirversion == 1 ? blocksize : dirblocksize,
- logfile, 1 << blocklog, logblocks,
- rtfile, rtextblocks << blocklog, rtblocks, rtextents);
+ logfile, 1 << blocklog, (long long)logblocks,
+ rtfile, rtextblocks << blocklog,
+ (long long)rtblocks, (long long)rtextents);
/*
* If the data area is a file, then grow it out to its final size
* so that the reads for the end of the device in the mount code
progname);
exit(1);
}
+
+ /*
+ * Zero out the last 64k on the device, to obliterate any
+ * old MD RAID (or other) metadata at the end of the device.
+ */
+ if (!xi.disfile) {
+ buf = libxfs_getbuf(xi.ddev, (xi.dsize - BTOBB(65536)),
+ BTOBB(65536));
+ bzero(XFS_BUF_PTR(buf), 65536);
+ libxfs_writebuf(buf, 1);
+ }
+
/*
* Zero the log if there is one.
*/
XLOG_FMT);
mp = libxfs_mount(mp, sbp, xi.ddev, xi.logdev, xi.rtdev, 1);
- if (!mp) {
- fprintf(stderr, "%s: mount initialization failed\n", progname);
+ if (mp == NULL) {
+ fprintf(stderr, "%s: filesystem failed to initialize\n", progname);
exit(1);
}
if (xi.logdev &&
XFS_MIN_LOG_FACTOR * max_trans_res(mp)) {
fprintf(stderr, "%s: log size (%lld) is too small for "
"transaction reservations\n",
- progname, logblocks);
+ progname, (long long)logblocks);
exit(1);
}
args.alignment = 1;
args.minalignslop = UINT_MAX;
args.pag = &mp->m_perag[agno];
- if (i = libxfs_trans_reserve(tp, worst_freelist, 0, 0, 0, 0))
+ if ((i = libxfs_trans_reserve(tp, worst_freelist, 0, 0, 0, 0)))
res_failed(i);
libxfs_alloc_fix_freelist(&args, 0);
libxfs_trans_commit(tp, 0, NULL);
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\
+/* label */ [-L label (maximum 12 characters)]\n\
/* prototype file */ [-p fname]\n\
/* quiet */ [-q]\n\
/* 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\
-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);
}