#include "libxfs.h"
#include <ctype.h>
-#ifdef ENABLE_BLKID
-# include <blkid/blkid.h>
-#endif /* ENABLE_BLKID */
#include "xfs_multidisk.h"
-
-/*
- * Device topology information.
- */
-struct fs_topology {
- int dsunit; /* stripe unit - data subvolume */
- int dswidth; /* stripe width - data subvolume */
- int rtswidth; /* stripe width - rt subvolume */
- int lsectorsize; /* logical sector size &*/
- int psectorsize; /* physical sector size */
-};
+#include "libxcmd.h"
/*
* Prototypes for internal functions.
"projinherit",
#define D_EXTSZINHERIT 14
"extszinherit",
+#define D_COWEXTSIZE 15
+ "cowextsize",
NULL
},
.subopt_params = {
.maxval = UINT_MAX,
.defaultval = SUBOPT_NEEDS_VAL,
},
+ { .index = D_COWEXTSIZE,
+ .conflicts = { LAST_CONFLICT },
+ .minval = 0,
+ .maxval = UINT_MAX,
+ .defaultval = SUBOPT_NEEDS_VAL,
+ },
},
};
{ .index = L_SUNIT,
.conflicts = { L_SU,
LAST_CONFLICT },
- .minval = BTOBB(XLOG_MIN_RECORD_BSIZE),
+ .minval = 1,
.maxval = BTOBB(XLOG_MAX_RECORD_BSIZE),
.defaultval = SUBOPT_NEEDS_VAL,
},
.conflicts = { L_SUNIT,
LAST_CONFLICT },
.convert = true,
- .minval = XLOG_MIN_RECORD_BSIZE,
+ .minval = BBTOB(1),
.maxval = XLOG_MAX_RECORD_BSIZE,
.defaultval = SUBOPT_NEEDS_VAL,
},
"finobt",
#define M_UUID 2
"uuid",
+#define M_RMAPBT 3
+ "rmapbt",
+#define M_REFLINK 4
+ "reflink",
NULL
},
.subopt_params = {
.conflicts = { LAST_CONFLICT },
.defaultval = SUBOPT_NEEDS_VAL,
},
+ { .index = M_RMAPBT,
+ .conflicts = { LAST_CONFLICT },
+ .minval = 0,
+ .maxval = 1,
+ .defaultval = 1,
+ },
+ { .index = M_REFLINK,
+ .conflicts = { LAST_CONFLICT },
+ .minval = 0,
+ .maxval = 1,
+ .defaultval = 1,
+ },
},
};
-#define TERABYTES(count, blog) ((__uint64_t)(count) << (40 - (blog)))
-#define GIGABYTES(count, blog) ((__uint64_t)(count) << (30 - (blog)))
-#define MEGABYTES(count, blog) ((__uint64_t)(count) << (20 - (blog)))
+#define TERABYTES(count, blog) ((uint64_t)(count) << (40 - (blog)))
+#define GIGABYTES(count, blog) ((uint64_t)(count) << (30 - (blog)))
+#define MEGABYTES(count, blog) ((uint64_t)(count) << (20 - (blog)))
/*
* Use this macro before we have superblock and mount structure
*/
#define WHACK_SIZE (128 * 1024)
+/*
+ * Convert lsu to lsunit for 512 bytes blocks and check validity of the values.
+ */
static void
calc_stripe_factors(
int dsu,
if (lsu)
*lsunit = (int)BTOBBT(lsu);
-}
-
-/*
- * Check for existing filesystem or partition table on device.
- * Returns:
- * 1 for existing fs or partition
- * 0 for nothing found
- * -1 for internal error
- */
-#ifdef ENABLE_BLKID
-static int
-check_overwrite(
- const char *device)
-{
- const char *type;
- blkid_probe pr = NULL;
- int ret;
- int fd;
- long long size;
- int bsz;
-
- if (!device || !*device)
- return 0;
-
- ret = -1; /* will reset on success of all setup calls */
-
- fd = open(device, O_RDONLY);
- if (fd < 0)
- goto out;
- platform_findsizes((char *)device, fd, &size, &bsz);
- close(fd);
-
- /* nothing to overwrite on a 0-length device */
- if (size == 0) {
- ret = 0;
- goto out;
- }
-
- pr = blkid_new_probe_from_filename(device);
- if (!pr)
- goto out;
-
- ret = blkid_probe_enable_partitions(pr, 1);
- if (ret < 0)
- goto out;
-
- ret = blkid_do_fullprobe(pr);
- if (ret < 0)
- goto out;
-
- /*
- * Blkid returns 1 for nothing found and 0 when it finds a signature,
- * but we want the exact opposite, so reverse the return value here.
- *
- * In addition print some useful diagnostics about what actually is
- * on the device.
- */
- if (ret) {
- ret = 0;
- goto out;
- }
-
- if (!blkid_probe_lookup_value(pr, "TYPE", &type, NULL)) {
- fprintf(stderr,
- _("%s: %s appears to contain an existing "
- "filesystem (%s).\n"), progname, device, type);
- } else if (!blkid_probe_lookup_value(pr, "PTTYPE", &type, NULL)) {
- fprintf(stderr,
- _("%s: %s appears to contain a partition "
- "table (%s).\n"), progname, device, type);
- } else {
- fprintf(stderr,
- _("%s: %s appears to contain something weird "
- "according to blkid\n"), progname, device);
- }
- ret = 1;
-out:
- if (pr)
- blkid_free_probe(pr);
- if (ret == -1)
- fprintf(stderr,
- _("%s: probe of %s failed, cannot detect "
- "existing filesystem.\n"), progname, device);
- return ret;
-}
-
-static void blkid_get_topology(
- const char *device,
- int *sunit,
- int *swidth,
- int *lsectorsize,
- int *psectorsize,
- int force_overwrite)
-{
-
- blkid_topology tp;
- blkid_probe pr;
- unsigned long val;
- struct stat statbuf;
- /* can't get topology info from a file */
- if (!stat(device, &statbuf) && S_ISREG(statbuf.st_mode)) {
+ /* verify if lsu/lsunit is a multiple block size */
+ if (lsu % blocksize != 0) {
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)
- return;
-
- tp = blkid_probe_get_topology(pr);
- if (!tp)
- goto out_free_probe;
-
- val = blkid_topology_get_logical_sector_size(tp);
- *lsectorsize = val;
- val = blkid_topology_get_physical_sector_size(tp);
- *psectorsize = val;
- val = blkid_topology_get_minimum_io_size(tp);
- *sunit = val;
- val = blkid_topology_get_optimal_io_size(tp);
- *swidth = val;
-
- /*
- * If the reported values are the same as the physical sector size
- * do not bother to report anything. It will only cause warnings
- * if people specify larger stripe units or widths manually.
- */
- if (*sunit == *psectorsize || *swidth == *psectorsize) {
- *sunit = 0;
- *swidth = 0;
+_("log stripe unit (%d) must be a multiple of the block size (%d)\n"),
+ lsu, blocksize);
+ exit(1);
}
-
- /*
- * Blkid reports the information in terms of bytes, but we want it in
- * terms of 512 bytes blocks (only to convert it to bytes later..)
- */
- *sunit = *sunit >> 9;
- *swidth = *swidth >> 9;
-
- if (blkid_topology_get_alignment_offset(tp) != 0) {
+ if ((BBTOB(*lsunit) % blocksize != 0)) {
fprintf(stderr,
- _("warning: device is not properly aligned %s\n"),
- device);
-
- if (!force_overwrite) {
- fprintf(stderr,
- _("Use -f to force usage of a misaligned device\n"));
-
- exit(EXIT_FAILURE);
- }
- /* Do not use physical sector size if the device is misaligned */
- *psectorsize = *lsectorsize;
- }
-
- blkid_free_probe(pr);
- return;
-
-out_free_probe:
- blkid_free_probe(pr);
- fprintf(stderr,
- _("warning: unable to probe device topology for device %s\n"),
- device);
-}
-#else /* ifdef ENABLE_BLKID */
-/*
- * Without blkid, we can't do a good check for signatures.
- * So instead of some messy attempts, just disable any checks
- * and always return 'nothing found'.
- */
-# warning BLKID is disabled, so signature detection and block device\
- access are not working!
-static int
-check_overwrite(
- const char *device)
-{
- return 1;
-}
-
-static void blkid_get_topology(
- const char *device,
- int *sunit,
- int *swidth,
- int *lsectorsize,
- int *psectorsize,
- int force_overwrite)
-{
- /*
- * Shouldn't make any difference (no blkid = no block device access),
- * but make sure this dummy replacement returns with at least some
- * sanity.
- */
- *lsectorsize = *psectorsize = 512;
-}
-
-#endif /* ENABLE_BLKID */
-
-static void get_topology(
- libxfs_init_t *xi,
- struct fs_topology *ft,
- int force_overwrite)
-{
- struct stat statbuf;
- char *dfile = xi->volname ? xi->volname : xi->dname;
-
- /*
- * If our target is a regular file, use platform_findsizes
- * to try to obtain the underlying filesystem's requirements
- * for direct IO; we'll set our sector size to that if possible.
- */
- if (xi->disfile ||
- (!stat(dfile, &statbuf) && S_ISREG(statbuf.st_mode))) {
- int fd;
- int flags = O_RDONLY;
- long long dummy;
-
- /* with xi->disfile we may not have the file yet! */
- if (xi->disfile)
- flags |= O_CREAT;
-
- fd = open(dfile, flags, 0666);
- if (fd >= 0) {
- platform_findsizes(dfile, fd, &dummy, &ft->lsectorsize);
- close(fd);
- ft->psectorsize = ft->lsectorsize;
- } else
- ft->psectorsize = ft->lsectorsize = BBSIZE;
- } else {
- blkid_get_topology(dfile, &ft->dsunit, &ft->dswidth,
- &ft->lsectorsize, &ft->psectorsize,
- force_overwrite);
- }
-
- if (xi->rtname && !xi->risfile) {
- int sunit, lsectorsize, psectorsize;
-
- blkid_get_topology(xi->rtname, &sunit, &ft->rtswidth,
- &lsectorsize, &psectorsize, force_overwrite);
+_("log stripe unit (%d) must be a multiple of the block size (%d)\n"),
+ BBTOB(*lsunit), blocksize);
+ exit(1);
}
}
bool force_overwrite,
const char *optname)
{
- struct stat64 statbuf;
+ struct stat statbuf;
if (*isfile && (no_size || no_name)) {
fprintf(stderr,
usage();
}
- if (stat64(name, &statbuf)) {
+ if (stat(name, &statbuf)) {
if (errno == ENOENT && *isfile) {
if (create)
*create = 1;
xfs_rfsblock_t *logblocks,
int blocklog)
{
- __uint64_t tmp_logblocks;
+ uint64_t tmp_logblocks;
/*
* Make sure that the log size is a multiple of the stripe unit
xfs_mount_t *mp,
int lsflag,
xfs_fsblock_t logstart,
- __uint64_t agsize,
+ uint64_t agsize,
int sunit,
xfs_rfsblock_t *logblocks,
int blocklog,
}
void
-validate_log_size(__uint64_t logblocks, int blocklog, int min_logblocks)
+validate_log_size(uint64_t logblocks, int blocklog, int min_logblocks)
{
if (logblocks < min_logblocks) {
fprintf(stderr,
static int
calc_default_imaxpct(
int blocklog,
- __uint64_t dblocks)
+ uint64_t dblocks)
{
/*
* This returns the % of the disk space that is used for
return 1;
}
-
-void
-calc_default_ag_geometry(
- int blocklog,
- __uint64_t dblocks,
- int multidisk,
- __uint64_t *agsize,
- __uint64_t *agcount)
-{
- __uint64_t blocks = 0;
- int shift = 0;
-
- /*
- * First handle the high extreme - the point at which we will
- * always use the maximum AG size.
- *
- * This applies regardless of storage configuration.
- */
- if (dblocks >= TERABYTES(32, blocklog)) {
- blocks = XFS_AG_MAX_BLOCKS(blocklog);
- goto done;
- }
-
- /*
- * For a single underlying storage device over 4TB in size
- * use the maximum AG size. Between 128MB and 4TB, just use
- * 4 AGs and scale up smoothly between min/max AG sizes.
- */
- if (!multidisk) {
- 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;
- }
- }
-
- /*
- * 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))
- blocks++;
- }
-done:
- *agsize = blocks;
- *agcount = dblocks / blocks + (dblocks % blocks != 0);
-}
-
static void
validate_ag_geometry(
int blocklog,
- __uint64_t dblocks,
- __uint64_t agsize,
- __uint64_t agcount)
+ uint64_t dblocks,
+ uint64_t agsize,
+ uint64_t agcount)
{
if (agsize < XFS_AG_MIN_BLOCKS(blocklog)) {
fprintf(stderr,
{
void *buf;
xfs_sb_t sb;
- __uint32_t bsize;
+ uint32_t bsize;
int i;
xfs_off_t off;
i != sb.sb_blocklog)
goto done;
- if (sb.sb_dblocks > ((__uint64_t)sb.sb_agcount * sb.sb_agblocks) ||
- sb.sb_dblocks < ((__uint64_t)(sb.sb_agcount - 1) *
+ if (sb.sb_dblocks > ((uint64_t)sb.sb_agcount * sb.sb_agblocks) ||
+ sb.sb_dblocks < ((uint64_t)(sb.sb_agcount - 1) *
sb.sb_agblocks + XFS_MIN_AG_BLOCKS))
goto done;
off = 0;
for (i = 1; i < sb.sb_agcount; i++) {
off += sb.sb_agblocks;
- if (pwrite64(xi->dfd, buf, new_sb->sb_sectsize,
+ if (pwrite(xi->dfd, buf, new_sb->sb_sectsize,
off << sb.sb_blocklog) == -1)
break;
}
}
static void
-discard_blocks(dev_t dev, __uint64_t nsectors)
+discard_blocks(dev_t dev, uint64_t nsectors)
{
int fd;
bool crcs_enabled;
bool dirftype;
bool parent_pointers;
+ bool rmapbt;
+ bool reflink;
};
static void
if (fp->finobt)
sbp->sb_features_ro_compat = XFS_SB_FEAT_RO_COMPAT_FINOBT;
+ if (fp->rmapbt)
+ sbp->sb_features_ro_compat |= XFS_SB_FEAT_RO_COMPAT_RMAPBT;
+ if (fp->reflink)
+ sbp->sb_features_ro_compat |= XFS_SB_FEAT_RO_COMPAT_REFLINK;
/*
* Sparse inode chunk support has two main inode alignment requirements.
if (sp->index != index) {
fprintf(stderr,
- ("Developer screwed up option parsing (%d/%d)! Please report!\n"),
+ _("Developer screwed up option parsing (%d/%d)! Please report!\n"),
sp->index, index);
reqval(opts->name, (char **)opts->subopts, index);
}
int argc,
char **argv)
{
- __uint64_t agcount;
+ uint64_t agcount;
xfs_agf_t *agf;
xfs_agi_t *agi;
xfs_agnumber_t agno;
- __uint64_t agsize;
+ uint64_t agsize;
xfs_alloc_rec_t *arec;
struct xfs_btree_block *block;
int blflag;
int dsw;
int dsunit;
int dswidth;
+ int dsflag;
int force_overwrite;
struct fsxattr fsx;
int ilflag;
char *rtsize;
xfs_sb_t *sbp;
int sectorlog;
- __uint64_t sector_mask;
+ uint64_t sector_mask;
int slflag;
int ssflag;
- __uint64_t tmp_agsize;
+ uint64_t tmp_agsize;
uuid_t uuid;
int worst_freelist;
libxfs_init_t xi;
.crcs_enabled = true,
.dirftype = true,
.parent_pointers = false,
+ .rmapbt = false,
+ .reflink = false,
};
platform_uuid_generate(&uuid);
dfile = logfile = rtfile = NULL;
dsize = logsize = rtsize = rtextsize = protofile = NULL;
dsu = dsw = dsunit = dswidth = lalign = lsu = lsunit = 0;
- nodsflag = norsflag = 0;
+ dsflag = nodsflag = norsflag = 0;
force_overwrite = 0;
worst_freelist = 0;
memset(&fsx, 0, sizeof(fsx));
char **subopts = (char **)bopts.subopts;
char *value;
- switch (getsubopt(&p, (constpp)subopts,
- &value)) {
+ switch (getsubopt(&p, subopts, &value)) {
case B_LOG:
blocklog = getnum(value, &bopts, B_LOG);
blocksize = 1 << blocklog;
char **subopts = (char **)dopts.subopts;
char *value;
- switch (getsubopt(&p, (constpp)subopts,
- &value)) {
+ switch (getsubopt(&p, subopts, &value)) {
case D_AGCOUNT:
agcount = getnum(value, &dopts,
D_AGCOUNT);
break;
case D_SUNIT:
dsunit = getnum(value, &dopts, D_SUNIT);
+ dsflag = 1;
break;
case D_SWIDTH:
dswidth = getnum(value, &dopts,
D_SWIDTH);
+ dsflag = 1;
break;
case D_SU:
dsu = getnum(value, &dopts, D_SU);
+ dsflag = 1;
break;
case D_SW:
dsw = getnum(value, &dopts, D_SW);
+ dsflag = 1;
break;
case D_NOALIGN:
nodsflag = getnum(value, &dopts,
fsx.fsx_xflags |=
XFS_DIFLAG_EXTSZINHERIT;
break;
+ case D_COWEXTSIZE:
+ fsx.fsx_cowextsize = getnum(value,
+ &dopts,
+ D_COWEXTSIZE);
+ fsx.fsx_xflags |=
+ FS_XFLAG_COWEXTSIZE;
+ break;
default:
unknown('d', value);
}
char **subopts = (char **)iopts.subopts;
char *value;
- switch (getsubopt(&p, (constpp)subopts,
- &value)) {
+ switch (getsubopt(&p, subopts, &value)) {
case I_ALIGN:
sb_feat.inode_align = getnum(value,
&iopts, I_ALIGN);
char **subopts = (char **)lopts.subopts;
char *value;
- switch (getsubopt(&p, (constpp)subopts,
- &value)) {
+ switch (getsubopt(&p, subopts, &value)) {
case L_AGNUM:
logagno = getnum(value, &lopts, L_AGNUM);
laflag = 1;
char **subopts = (char **)mopts.subopts;
char *value;
- switch (getsubopt(&p, (constpp)subopts,
- &value)) {
+ switch (getsubopt(&p, subopts, &value)) {
case M_CRC:
sb_feat.crcs_enabled =
getnum(value, &mopts, M_CRC);
if (platform_uuid_parse(value, &uuid))
illegal(optarg, "m uuid");
break;
+ case M_RMAPBT:
+ sb_feat.rmapbt = getnum(
+ value, &mopts, M_RMAPBT);
+ break;
+ case M_REFLINK:
+ sb_feat.reflink = getnum(
+ value, &mopts, M_REFLINK);
+ break;
default:
unknown('m', value);
}
char **subopts = (char **)nopts.subopts;
char *value;
- switch (getsubopt(&p, (constpp)subopts,
- &value)) {
+ switch (getsubopt(&p, subopts, &value)) {
case N_LOG:
dirblocklog = getnum(value, &nopts,
N_LOG);
char **subopts = (char **)ropts.subopts;
char *value;
- switch (getsubopt(&p, (constpp)subopts,
- &value)) {
+ switch (getsubopt(&p, subopts, &value)) {
case R_EXTSIZE:
rtextsize = getstr(value, &ropts,
R_EXTSIZE);
char **subopts = (char **)sopts.subopts;
char *value;
- switch (getsubopt(&p, (constpp)subopts,
- &value)) {
+ switch (getsubopt(&p, subopts, &value)) {
case S_LOG:
case S_SECTLOG:
if (lssflag)
} else {
/*
* The kernel doesn't currently support crc=0,finobt=1
- * filesystems. If crcs are not enabled and the user has
- * explicitly turned them off then silently turn them off
- * to avoid an unnecessary warning. If the user explicitly
- * tried to use crc=0,finobt=1, then issue a warning before
- * turning them off. The same is also for sparse inodes.
+ * filesystems. If crcs are not enabled and the user has not
+ * explicitly turned finobt on, then silently turn it off to
+ * avoid an unnecessary warning.
+ * If the user explicitly tried to use crc=0,finobt=1,
+ * then issue an error.
+ * The same is also for sparse inodes.
*/
if (sb_feat.finobt && mopts.subopt_params[M_FINOBT].seen) {
fprintf(stderr,
-_("warning: finobt not supported without CRC support, disabled.\n"));
+_("finobt not supported without CRC support\n"));
+ usage();
}
sb_feat.finobt = 0;
if (sb_feat.spinodes) {
fprintf(stderr,
- _("warning: sparse inodes not supported without CRC support, disabled.\n"));
+_("sparse inodes not supported without CRC support\n"));
+ usage();
}
sb_feat.spinodes = 0;
+ if (sb_feat.rmapbt) {
+ fprintf(stderr,
+_("rmapbt not supported without CRC support\n"));
+ usage();
+ }
+ sb_feat.rmapbt = false;
+
+ if (sb_feat.reflink) {
+ fprintf(stderr,
+_("reflink not supported without CRC support\n"));
+ usage();
+ }
+ sb_feat.reflink = false;
+ }
+
+ if ((fsx.fsx_xflags & FS_XFLAG_COWEXTSIZE) && !sb_feat.reflink) {
+ fprintf(stderr,
+_("cowextsize not supported without reflink support\n"));
+ usage();
+ }
+
+ if (sb_feat.rmapbt && xi.rtname) {
+ fprintf(stderr,
+_("rmapbt not supported with realtime devices\n"));
+ usage();
+ sb_feat.rmapbt = false;
}
if (nsflag || nlflag) {
if (dsize) {
- __uint64_t dbytes;
+ uint64_t dbytes;
dbytes = getnum(dsize, &dopts, D_SIZE);
if (dbytes % XFS_MIN_BLOCKSIZE) {
}
if (logsize) {
- __uint64_t logbytes;
+ uint64_t logbytes;
logbytes = getnum(logsize, &lopts, L_SIZE);
if (logbytes % XFS_MIN_BLOCKSIZE) {
(long long)(logblocks << blocklog));
}
if (rtsize) {
- __uint64_t rtbytes;
+ uint64_t rtbytes;
rtbytes = getnum(rtsize, &ropts, R_SIZE);
if (rtbytes % XFS_MIN_BLOCKSIZE) {
* If specified, check rt extent size against its constraints.
*/
if (rtextsize) {
- __uint64_t rtextbytes;
+ uint64_t rtextbytes;
rtextbytes = getnum(rtextsize, &ropts, R_EXTSIZE);
if (rtextbytes % blocksize) {
* and the underlying volume is striped, then set rtextblocks
* to the stripe width.
*/
- __uint64_t rswidth;
- __uint64_t rtextbytes;
+ uint64_t rswidth;
+ uint64_t rtextbytes;
if (!norsflag && !xi.risfile && !(!rtsize && xi.disfile))
rswidth = ft.rtswidth;
calc_stripe_factors(dsu, dsw, sectorsize, lsu, lsectorsize,
&dsunit, &dswidth, &lsunit);
+ /* If sunit & swidth were manually specified as 0, same as noalign */
+ if (dsflag && !dsunit && !dswidth)
+ nodsflag = 1;
+
xi.setblksize = sectorsize;
/*
* multiple of the sector size, or 1024, whichever is larger.
*/
- sector_mask = (__uint64_t)-1 << (MAX(sectorlog, 10) - BBSHIFT);
+ sector_mask = (uint64_t)-1 << (MAX(sectorlog, 10) - BBSHIFT);
xi.dsize &= sector_mask;
xi.rtsize &= sector_mask;
- xi.logBBsize &= (__uint64_t)-1 << (MAX(lsectorlog, 10) - BBSHIFT);
+ xi.logBBsize &= (uint64_t)-1 << (MAX(lsectorlog, 10) - BBSHIFT);
/* don't do discards on print-only runs or on files */
}
}
}
- if (dswidth && ((agsize % dswidth) == 0) && (agcount > 1)) {
+ if (dswidth && ((agsize % dswidth) == 0)
+ && (dswidth != dsunit)
+ && (agcount > 1)) {
/* This is a non-optimal configuration because all AGs
* start on the same disk in the stripe. Changing
* the AG size by one sunit will guarantee that this
*/
if (lsunit) {
- if ((BBTOB(lsunit) % blocksize != 0)) {
- fprintf(stderr,
- _("log stripe unit (%d) must be a multiple of the block size (%d)\n"),
- BBTOB(lsunit), blocksize);
- exit(1);
- }
/* convert from 512 byte blocks to fs blocks */
lsunit = DTOBT(lsunit);
} else if (sb_feat.log_version == 2 && loginternal && dsunit) {
lsunit = (32 * 1024) >> blocklog;
}
- min_logblocks = max_trans_res(sb_feat.crcs_enabled, sb_feat.dir_version,
+ min_logblocks = max_trans_res(agsize,
+ sb_feat.crcs_enabled, sb_feat.dir_version,
sectorlog, blocklog, inodelog, dirblocklog,
- sb_feat.log_version, lsunit, sb_feat.finobt);
+ sb_feat.log_version, lsunit, sb_feat.finobt,
+ sb_feat.rmapbt, sb_feat.reflink,
+ sb_feat.inode_align);
ASSERT(min_logblocks);
min_logblocks = MAX(XFS_MIN_LOG_BLOCKS, min_logblocks);
if (!logsize && dblocks >= (1024*1024*1024) >> blocklog)
mp = &mbuf;
sbp = &mp->m_sb;
memset(mp, 0, sizeof(xfs_mount_t));
- sbp->sb_blocklog = (__uint8_t)blocklog;
- sbp->sb_sectlog = (__uint8_t)sectorlog;
- sbp->sb_agblklog = (__uint8_t)libxfs_log2_roundup((unsigned int)agsize);
+ sbp->sb_blocklog = (uint8_t)blocklog;
+ sbp->sb_sectlog = (uint8_t)sectorlog;
+ sbp->sb_agblklog = (uint8_t)libxfs_log2_roundup((unsigned int)agsize);
sbp->sb_agblocks = (xfs_agblock_t)agsize;
mp->m_blkbb_log = sbp->sb_blocklog - BBSHIFT;
mp->m_sectbb_log = sbp->sb_sectlog - BBSHIFT;
/*
- * sb_versionnum and finobt flags must be set before we use
- * XFS_PREALLOC_BLOCKS().
+ * sb_versionnum, finobt and rmapbt flags must be set before we use
+ * libxfs_prealloc_blocks().
*/
sb_set_features(&mp->m_sb, &sb_feat, sectorsize, lsectorsize, dsunit);
*/
if (!logsize) {
logblocks = MIN(logblocks,
- XFS_ALLOC_AG_MAX_USABLE(mp));
+ libxfs_alloc_ag_max_usable(mp));
/* revalidate the log size is valid if we changed it */
validate_log_size(logblocks, blocklog, min_logblocks);
}
- if (logblocks > agsize - XFS_PREALLOC_BLOCKS(mp)) {
+ if (logblocks > agsize - libxfs_prealloc_blocks(mp)) {
fprintf(stderr,
_("internal log size %lld too large, must fit in allocation group\n"),
(long long)logblocks);
} else
logagno = (xfs_agnumber_t)(agcount / 2);
- logstart = XFS_AGB_TO_FSB(mp, logagno, XFS_PREALLOC_BLOCKS(mp));
+ logstart = XFS_AGB_TO_FSB(mp, logagno, libxfs_prealloc_blocks(mp));
/*
* Align the logstart at stripe unit boundary.
*/
printf(_(
"meta-data=%-22s isize=%-6d agcount=%lld, agsize=%lld blks\n"
" =%-22s sectsz=%-5u attr=%u, projid32bit=%u\n"
- " =%-22s crc=%-8u finobt=%u, sparse=%u\n"
+ " =%-22s crc=%-8u finobt=%u, sparse=%u, rmapbt=%u, reflink=%u\n"
"data =%-22s bsize=%-6u blocks=%llu, imaxpct=%u\n"
" =%-22s sunit=%-6u swidth=%u blks\n"
"naming =version %-14u bsize=%-6u ascii-ci=%d ftype=%d\n"
"", sectorsize, sb_feat.attr_version,
!sb_feat.projid16bit,
"", sb_feat.crcs_enabled, sb_feat.finobt, sb_feat.spinodes,
+ sb_feat.rmapbt, sb_feat.reflink,
"", blocksize, (long long)dblocks, imaxpct,
"", dsunit, dswidth,
sb_feat.dir_version, dirblocksize, sb_feat.nci,
sbp->sb_agcount = (xfs_agnumber_t)agcount;
sbp->sb_rbmblocks = nbmblocks;
sbp->sb_logblocks = (xfs_extlen_t)logblocks;
- sbp->sb_sectsize = (__uint16_t)sectorsize;
- sbp->sb_inodesize = (__uint16_t)isize;
- sbp->sb_inopblock = (__uint16_t)(blocksize / isize);
- sbp->sb_sectlog = (__uint8_t)sectorlog;
- sbp->sb_inodelog = (__uint8_t)inodelog;
- sbp->sb_inopblog = (__uint8_t)(blocklog - inodelog);
+ sbp->sb_sectsize = (uint16_t)sectorsize;
+ sbp->sb_inodesize = (uint16_t)isize;
+ sbp->sb_inopblock = (uint16_t)(blocksize / isize);
+ sbp->sb_sectlog = (uint8_t)sectorlog;
+ sbp->sb_inodelog = (uint8_t)inodelog;
+ sbp->sb_inopblog = (uint8_t)(blocklog - inodelog);
sbp->sb_rextslog =
- (__uint8_t)(rtextents ?
+ (uint8_t)(rtextents ?
libxfs_highbit32((unsigned int)rtextents) : 0);
sbp->sb_inprogress = 1; /* mkfs is in progress */
sbp->sb_imax_pct = imaxpct;
sbp->sb_icount = 0;
sbp->sb_ifree = 0;
- sbp->sb_fdblocks = dblocks - agcount * XFS_PREALLOC_BLOCKS(mp) -
+ sbp->sb_fdblocks = dblocks - agcount * libxfs_prealloc_blocks(mp) -
(loginternal ? logblocks : 0);
sbp->sb_frextents = 0; /* will do a free later */
sbp->sb_uquotino = sbp->sb_gquotino = sbp->sb_pquotino = 0;
} else
sbp->sb_inoalignmt = 0;
if (lsectorsize != BBSIZE || sectorsize != BBSIZE) {
- sbp->sb_logsectlog = (__uint8_t)lsectorlog;
- sbp->sb_logsectsize = (__uint16_t)lsectorsize;
+ sbp->sb_logsectlog = (uint8_t)lsectorlog;
+ sbp->sb_logsectsize = (uint16_t)lsectorsize;
} else {
sbp->sb_logsectlog = 0;
sbp->sb_logsectsize = 0;
* code will succeed.
*/
if (xi.disfile && xi.dsize * xi.dbsize < dblocks * blocksize) {
- if (ftruncate64(xi.dfd, dblocks * blocksize) < 0) {
+ if (ftruncate(xi.dfd, dblocks * blocksize) < 0) {
fprintf(stderr,
_("%s: Growing the data section failed\n"),
progname);
for (agno = 0; agno < agcount; agno++) {
struct xfs_agfl *agfl;
int bucket;
- struct xfs_perag *pag = xfs_perag_get(mp, agno);
+ struct xfs_perag *pag = libxfs_perag_get(mp, agno);
/*
* Superblock.
agf->agf_levels[XFS_BTNUM_CNTi] = cpu_to_be32(1);
pag->pagf_levels[XFS_BTNUM_BNOi] = 1;
pag->pagf_levels[XFS_BTNUM_CNTi] = 1;
+ if (xfs_sb_version_hasrmapbt(&mp->m_sb)) {
+ agf->agf_roots[XFS_BTNUM_RMAPi] =
+ cpu_to_be32(XFS_RMAP_BLOCK(mp));
+ agf->agf_levels[XFS_BTNUM_RMAPi] = cpu_to_be32(1);
+ agf->agf_rmap_blocks = cpu_to_be32(1);
+ }
+ if (xfs_sb_version_hasreflink(&mp->m_sb)) {
+ agf->agf_refcount_root = cpu_to_be32(
+ libxfs_refc_block(mp));
+ agf->agf_refcount_level = cpu_to_be32(1);
+ agf->agf_refcount_blocks = cpu_to_be32(1);
+ }
agf->agf_flfirst = 0;
agf->agf_fllast = cpu_to_be32(XFS_AGFL_SIZE(mp) - 1);
agf->agf_flcount = 0;
- nbmblocks = (xfs_extlen_t)(agsize - XFS_PREALLOC_BLOCKS(mp));
+ nbmblocks = (xfs_extlen_t)(agsize - libxfs_prealloc_blocks(mp));
agf->agf_freeblks = cpu_to_be32(nbmblocks);
agf->agf_longest = cpu_to_be32(nbmblocks);
if (xfs_sb_version_hascrc(&mp->m_sb))
agf->agf_longest = cpu_to_be32(agsize -
XFS_FSB_TO_AGBNO(mp, logstart) - logblocks);
}
- if (xfs_alloc_min_freelist(mp, pag) > worst_freelist)
- worst_freelist = xfs_alloc_min_freelist(mp, pag);
+ if (libxfs_alloc_min_freelist(mp, pag) > worst_freelist)
+ worst_freelist = libxfs_alloc_min_freelist(mp, pag);
libxfs_writebuf(buf, LIBXFS_EXIT_ON_FAILURE);
/*
buf->b_ops = &xfs_allocbt_buf_ops;
block = XFS_BUF_TO_BLOCK(buf);
memset(block, 0, blocksize);
- if (xfs_sb_version_hascrc(&mp->m_sb))
- xfs_btree_init_block(mp, buf, XFS_ABTB_CRC_MAGIC, 0, 1,
- agno, XFS_BTREE_CRC_BLOCKS);
- else
- xfs_btree_init_block(mp, buf, XFS_ABTB_MAGIC, 0, 1,
- agno, 0);
+ libxfs_btree_init_block(mp, buf, XFS_BTNUM_BNO, 0, 1, agno, 0);
arec = XFS_ALLOC_REC_ADDR(mp, block, 1);
- arec->ar_startblock = cpu_to_be32(XFS_PREALLOC_BLOCKS(mp));
+ arec->ar_startblock = cpu_to_be32(libxfs_prealloc_blocks(mp));
if (loginternal && agno == logagno) {
if (lalign) {
/*
buf->b_ops = &xfs_allocbt_buf_ops;
block = XFS_BUF_TO_BLOCK(buf);
memset(block, 0, blocksize);
- if (xfs_sb_version_hascrc(&mp->m_sb))
- xfs_btree_init_block(mp, buf, XFS_ABTC_CRC_MAGIC, 0, 1,
- agno, XFS_BTREE_CRC_BLOCKS);
- else
- xfs_btree_init_block(mp, buf, XFS_ABTC_MAGIC, 0, 1,
- agno, 0);
+ libxfs_btree_init_block(mp, buf, XFS_BTNUM_CNT, 0, 1, agno, 0);
arec = XFS_ALLOC_REC_ADDR(mp, block, 1);
- arec->ar_startblock = cpu_to_be32(XFS_PREALLOC_BLOCKS(mp));
+ arec->ar_startblock = cpu_to_be32(libxfs_prealloc_blocks(mp));
if (loginternal && agno == logagno) {
if (lalign) {
arec->ar_blockcount = cpu_to_be32(
libxfs_writebuf(buf, LIBXFS_EXIT_ON_FAILURE);
+ /*
+ * refcount btree root block
+ */
+ if (xfs_sb_version_hasreflink(&mp->m_sb)) {
+ buf = libxfs_getbuf(mp->m_ddev_targp,
+ XFS_AGB_TO_DADDR(mp, agno,
+ libxfs_refc_block(mp)),
+ bsize);
+ buf->b_ops = &xfs_refcountbt_buf_ops;
+
+ block = XFS_BUF_TO_BLOCK(buf);
+ memset(block, 0, blocksize);
+ libxfs_btree_init_block(mp, buf, XFS_BTNUM_REFC, 0,
+ 0, agno, 0);
+
+ libxfs_writebuf(buf, LIBXFS_EXIT_ON_FAILURE);
+ }
+
/*
* INO btree root block
*/
buf->b_ops = &xfs_inobt_buf_ops;
block = XFS_BUF_TO_BLOCK(buf);
memset(block, 0, blocksize);
- if (xfs_sb_version_hascrc(&mp->m_sb))
- xfs_btree_init_block(mp, buf, XFS_IBT_CRC_MAGIC, 0, 0,
- agno, XFS_BTREE_CRC_BLOCKS);
- else
- xfs_btree_init_block(mp, buf, XFS_IBT_MAGIC, 0, 0,
- agno, 0);
+ libxfs_btree_init_block(mp, buf, XFS_BTNUM_INO, 0, 0, agno, 0);
libxfs_writebuf(buf, LIBXFS_EXIT_ON_FAILURE);
/*
* Free INO btree root block
*/
- if (!sb_feat.finobt) {
- xfs_perag_put(pag);
- continue;
+ if (sb_feat.finobt) {
+ buf = libxfs_getbuf(mp->m_ddev_targp,
+ XFS_AGB_TO_DADDR(mp, agno, XFS_FIBT_BLOCK(mp)),
+ bsize);
+ buf->b_ops = &xfs_inobt_buf_ops;
+ block = XFS_BUF_TO_BLOCK(buf);
+ memset(block, 0, blocksize);
+ libxfs_btree_init_block(mp, buf, XFS_BTNUM_FINO, 0, 0, agno, 0);
+ libxfs_writebuf(buf, LIBXFS_EXIT_ON_FAILURE);
}
- buf = libxfs_getbuf(mp->m_ddev_targp,
- XFS_AGB_TO_DADDR(mp, agno, XFS_FIBT_BLOCK(mp)),
+ /* RMAP btree root block */
+ if (xfs_sb_version_hasrmapbt(&mp->m_sb)) {
+ struct xfs_rmap_rec *rrec;
+
+ buf = libxfs_getbuf(mp->m_ddev_targp,
+ XFS_AGB_TO_DADDR(mp, agno, XFS_RMAP_BLOCK(mp)),
bsize);
- buf->b_ops = &xfs_inobt_buf_ops;
- block = XFS_BUF_TO_BLOCK(buf);
- memset(block, 0, blocksize);
- if (xfs_sb_version_hascrc(&mp->m_sb))
- xfs_btree_init_block(mp, buf, XFS_FIBT_CRC_MAGIC, 0, 0,
- agno, XFS_BTREE_CRC_BLOCKS);
- else
- xfs_btree_init_block(mp, buf, XFS_FIBT_MAGIC, 0, 0,
- agno, 0);
- libxfs_writebuf(buf, LIBXFS_EXIT_ON_FAILURE);
- xfs_perag_put(pag);
+ buf->b_ops = &xfs_rmapbt_buf_ops;
+ block = XFS_BUF_TO_BLOCK(buf);
+ memset(block, 0, blocksize);
+
+ libxfs_btree_init_block(mp, buf, XFS_BTNUM_RMAP, 0, 0, agno, 0);
+
+ /*
+ * mark the AG header regions as static metadata
+ * The BNO btree block is the first block after the
+ * headers, so it's location defines the size of region
+ * the static metadata consumes.
+ */
+ rrec = XFS_RMAP_REC_ADDR(block, 1);
+ rrec->rm_startblock = 0;
+ rrec->rm_blockcount = cpu_to_be32(XFS_BNO_BLOCK(mp));
+ rrec->rm_owner = cpu_to_be64(XFS_RMAP_OWN_FS);
+ rrec->rm_offset = 0;
+ be16_add_cpu(&block->bb_numrecs, 1);
+
+ /* account freespace btree root blocks */
+ rrec = XFS_RMAP_REC_ADDR(block, 2);
+ rrec->rm_startblock = cpu_to_be32(XFS_BNO_BLOCK(mp));
+ rrec->rm_blockcount = cpu_to_be32(2);
+ rrec->rm_owner = cpu_to_be64(XFS_RMAP_OWN_AG);
+ rrec->rm_offset = 0;
+ be16_add_cpu(&block->bb_numrecs, 1);
+
+ /* account inode btree root blocks */
+ rrec = XFS_RMAP_REC_ADDR(block, 3);
+ rrec->rm_startblock = cpu_to_be32(XFS_IBT_BLOCK(mp));
+ rrec->rm_blockcount = cpu_to_be32(XFS_RMAP_BLOCK(mp) -
+ XFS_IBT_BLOCK(mp));
+ rrec->rm_owner = cpu_to_be64(XFS_RMAP_OWN_INOBT);
+ rrec->rm_offset = 0;
+ be16_add_cpu(&block->bb_numrecs, 1);
+
+ /* account for rmap btree root */
+ rrec = XFS_RMAP_REC_ADDR(block, 4);
+ rrec->rm_startblock = cpu_to_be32(XFS_RMAP_BLOCK(mp));
+ rrec->rm_blockcount = cpu_to_be32(1);
+ rrec->rm_owner = cpu_to_be64(XFS_RMAP_OWN_AG);
+ rrec->rm_offset = 0;
+ be16_add_cpu(&block->bb_numrecs, 1);
+
+ /* account for refcount btree root */
+ if (xfs_sb_version_hasreflink(&mp->m_sb)) {
+ rrec = XFS_RMAP_REC_ADDR(block, 5);
+ rrec->rm_startblock = cpu_to_be32(
+ libxfs_refc_block(mp));
+ rrec->rm_blockcount = cpu_to_be32(1);
+ rrec->rm_owner = cpu_to_be64(XFS_RMAP_OWN_REFC);
+ rrec->rm_offset = 0;
+ be16_add_cpu(&block->bb_numrecs, 1);
+ }
+
+ /* account for the log space */
+ if (loginternal && agno == logagno) {
+ rrec = XFS_RMAP_REC_ADDR(block,
+ be16_to_cpu(block->bb_numrecs) + 1);
+ rrec->rm_startblock = cpu_to_be32(
+ XFS_FSB_TO_AGBNO(mp, logstart));
+ rrec->rm_blockcount = cpu_to_be32(logblocks);
+ rrec->rm_owner = cpu_to_be64(XFS_RMAP_OWN_LOG);
+ rrec->rm_offset = 0;
+ be16_add_cpu(&block->bb_numrecs, 1);
+ }
+
+ libxfs_writebuf(buf, LIBXFS_EXIT_ON_FAILURE);
+ }
+
+ libxfs_perag_put(pag);
}
/*
xfs_trans_t *tp;
struct xfs_trans_res tres = {0};
+ c = libxfs_trans_alloc(mp, &tres, worst_freelist, 0, 0, &tp);
+ if (c)
+ res_failed(c);
+
memset(&args, 0, sizeof(args));
- args.tp = tp = libxfs_trans_alloc(mp, 0);
+ args.tp = tp;
args.mp = mp;
args.agno = agno;
args.alignment = 1;
- args.pag = xfs_perag_get(mp,agno);
- c = -libxfs_trans_reserve(tp, &tres, worst_freelist, 0);
- if (c)
- res_failed(c);
+ args.pag = libxfs_perag_get(mp,agno);
libxfs_alloc_fix_freelist(&args, 0);
- xfs_perag_put(args.pag);
+ libxfs_perag_put(args.pag);
libxfs_trans_commit(tp);
}
if (sp[1] != '\0')
return -1LL;
- if (*sp == 'b')
- return i * blksize;
- if (*sp == 's')
- return i * sectsize;
+ if (*sp == 'b') {
+ if (!blksize) {
+ fprintf(stderr,
+_("Blocksize must be provided prior to using 'b' suffix.\n"));
+ usage();
+ } else {
+ return i * blksize;
+ }
+ }
+ if (*sp == 's') {
+ if (!sectsize) {
+ fprintf(stderr,
+_("Sectorsize must be specified prior to using 's' suffix.\n"));
+ usage();
+ } else {
+ return i * sectsize;
+ }
+ }
c = tolower(*sp);
switch (c) {
case 'e':
i *= 1024LL;
+ /* fall through */
case 'p':
i *= 1024LL;
+ /* fall through */
case 't':
i *= 1024LL;
+ /* fall through */
case 'g':
i *= 1024LL;
+ /* fall through */
case 'm':
i *= 1024LL;
+ /* fall through */
case 'k':
return i * 1024LL;
default:
{
fprintf(stderr, _("Usage: %s\n\
/* blocksize */ [-b log=n|size=num]\n\
-/* metadata */ [-m crc=0|1,finobt=0|1,uuid=xxx]\n\
+/* metadata */ [-m crc=0|1,finobt=0|1,uuid=xxx,rmapbt=0|1,reflink=0|1]\n\
/* data subvol */ [-d agcount=n,agsize=n,file,name=xxx,size=num,\n\
(sunit=value,swidth=value|su=num,sw=num|noalign),\n\
sectlog=n|sectsize=num\n\