aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDarrick J. Wong <darrick.wong@oracle.com>2017-09-21 17:00:01 -0500
committerEric Sandeen <sandeen@redhat.com>2017-09-21 17:00:01 -0500
commit06b80354bd17b2dfc9926acb342a51035ce7bbd4 (patch)
treed21d8397be2215da2794bc134702f813fc8d4bfa
parentf810b1bc920dcd79237fbbc45d93b378e782c57d (diff)
downloadxfsprogs-dev-06b80354bd17b2dfc9926acb342a51035ce7bbd4.tar.gz
mkfs: pass a custom cowextsize into the created filesystem
Create a -d option to mkfs.xfs that enables administrators to set the CoW extent size hint on the created files. [sandeen: Note, the switch to xfs_flags2diflags looks like a bugfix, but it's not - the flags set by mkfs up to this point just happened to line up without any translation.] Signed-off-by: Darrick J. Wong <darrick.wong@oracle.com> Reviewed-by: Eric Sandeen <sandeen@redhat.com> Signed-off-by: Eric Sandeen <sandeen@sandeen.net>
-rw-r--r--libxfs/util.c64
-rw-r--r--man/man8/mkfs.xfs.87
-rw-r--r--mkfs/xfs_mkfs.c20
3 files changed, 89 insertions, 2 deletions
diff --git a/libxfs/util.c b/libxfs/util.c
index 7938e31789..74b1bdb8c8 100644
--- a/libxfs/util.c
+++ b/libxfs/util.c
@@ -175,6 +175,64 @@ libxfs_trans_ichgtime(
}
}
+STATIC uint16_t
+xfs_flags2diflags(
+ struct xfs_inode *ip,
+ unsigned int xflags)
+{
+ /* can't set PREALLOC this way, just preserve it */
+ uint16_t di_flags =
+ (ip->i_d.di_flags & XFS_DIFLAG_PREALLOC);
+
+ if (xflags & FS_XFLAG_IMMUTABLE)
+ di_flags |= XFS_DIFLAG_IMMUTABLE;
+ if (xflags & FS_XFLAG_APPEND)
+ di_flags |= XFS_DIFLAG_APPEND;
+ if (xflags & FS_XFLAG_SYNC)
+ di_flags |= XFS_DIFLAG_SYNC;
+ if (xflags & FS_XFLAG_NOATIME)
+ di_flags |= XFS_DIFLAG_NOATIME;
+ if (xflags & FS_XFLAG_NODUMP)
+ di_flags |= XFS_DIFLAG_NODUMP;
+ if (xflags & FS_XFLAG_NODEFRAG)
+ di_flags |= XFS_DIFLAG_NODEFRAG;
+ if (xflags & FS_XFLAG_FILESTREAM)
+ di_flags |= XFS_DIFLAG_FILESTREAM;
+ if (S_ISDIR(VFS_I(ip)->i_mode)) {
+ if (xflags & FS_XFLAG_RTINHERIT)
+ di_flags |= XFS_DIFLAG_RTINHERIT;
+ if (xflags & FS_XFLAG_NOSYMLINKS)
+ di_flags |= XFS_DIFLAG_NOSYMLINKS;
+ if (xflags & FS_XFLAG_EXTSZINHERIT)
+ di_flags |= XFS_DIFLAG_EXTSZINHERIT;
+ if (xflags & FS_XFLAG_PROJINHERIT)
+ di_flags |= XFS_DIFLAG_PROJINHERIT;
+ } else if (S_ISREG(VFS_I(ip)->i_mode)) {
+ if (xflags & FS_XFLAG_REALTIME)
+ di_flags |= XFS_DIFLAG_REALTIME;
+ if (xflags & FS_XFLAG_EXTSIZE)
+ di_flags |= XFS_DIFLAG_EXTSIZE;
+ }
+
+ return di_flags;
+}
+
+STATIC uint64_t
+xfs_flags2diflags2(
+ struct xfs_inode *ip,
+ unsigned int xflags)
+{
+ uint64_t di_flags2 =
+ (ip->i_d.di_flags2 & XFS_DIFLAG2_REFLINK);
+
+ if (xflags & FS_XFLAG_DAX)
+ di_flags2 |= XFS_DIFLAG2_DAX;
+ if (xflags & FS_XFLAG_COWEXTSIZE)
+ di_flags2 |= XFS_DIFLAG2_COWEXTSIZE;
+
+ return di_flags2;
+}
+
/*
* Allocate an inode on disk and return a copy of its in-core version.
* Set mode, nlink, and rdev appropriately within the inode.
@@ -254,15 +312,17 @@ libxfs_ialloc(
ip->i_d.di_extsize = pip ? 0 : fsx->fsx_extsize;
ip->i_d.di_dmevmask = 0;
ip->i_d.di_dmstate = 0;
- ip->i_d.di_flags = pip ? 0 : fsx->fsx_xflags;
+ ip->i_d.di_flags = pip ? 0 : xfs_flags2diflags(ip, fsx->fsx_xflags);
if (ip->i_d.di_version == 3) {
ASSERT(ip->i_d.di_ino == ino);
ASSERT(uuid_equal(&ip->i_d.di_uuid, &mp->m_sb.sb_meta_uuid));
VFS_I(ip)->i_version = 1;
- ip->i_d.di_flags2 = 0;
+ ip->i_d.di_flags2 = pip ? 0 : xfs_flags2diflags2(ip,
+ fsx->fsx_xflags);
ip->i_d.di_crtime.t_sec = (int32_t)VFS_I(ip)->i_mtime.tv_sec;
ip->i_d.di_crtime.t_nsec = (int32_t)VFS_I(ip)->i_mtime.tv_nsec;
+ ip->i_d.di_cowextsize = pip ? 0 : fsx->fsx_cowextsize;
}
flags = XFS_ILOG_CORE;
diff --git a/man/man8/mkfs.xfs.8 b/man/man8/mkfs.xfs.8
index 33831c9a23..bbbe1c5346 100644
--- a/man/man8/mkfs.xfs.8
+++ b/man/man8/mkfs.xfs.8
@@ -279,6 +279,13 @@ and
.B agsize
suboptions are mutually exclusive.
.TP
+.BI cowextsize= value
+Set the copy-on-write extent size hint on all inodes created by
+.BR mkfs.xfs "."
+The value must be provided in units of filesystem blocks.
+If the value is zero, the default value (currently 32 blocks) will be used.
+Directories will pass on this hint to newly created children.
+.TP
.BI name= value
This can be used to specify the name of the special file containing
the filesystem. In this case, the log section must be specified as
diff --git a/mkfs/xfs_mkfs.c b/mkfs/xfs_mkfs.c
index e433033587..3058129409 100644
--- a/mkfs/xfs_mkfs.c
+++ b/mkfs/xfs_mkfs.c
@@ -187,6 +187,8 @@ struct opt_params dopts = {
"projinherit",
#define D_EXTSZINHERIT 14
"extszinherit",
+#define D_COWEXTSIZE 15
+ "cowextsize",
NULL
},
.subopt_params = {
@@ -303,6 +305,12 @@ struct opt_params dopts = {
.maxval = UINT_MAX,
.defaultval = SUBOPT_NEEDS_VAL,
},
+ { .index = D_COWEXTSIZE,
+ .conflicts = { LAST_CONFLICT },
+ .minval = 0,
+ .maxval = UINT_MAX,
+ .defaultval = SUBOPT_NEEDS_VAL,
+ },
},
};
@@ -1638,6 +1646,13 @@ main(
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);
}
@@ -2142,6 +2157,11 @@ _("reflink not supported without CRC support\n"));
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,