summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDarrick J. Wong <djwong@kernel.org>2022-07-14 11:16:24 -0700
committerDarrick J. Wong <djwong@kernel.org>2022-11-09 19:08:16 -0800
commit3674a4e9e51129e31b954be0e4c02a0e3fca1e7e (patch)
tree3028aa9cd8fb5bff7469e8c9d9db4842bae48eef
parente936e495ae1b7cf83a33e9b530dfa903a30dfad6 (diff)
xfs: upgrade filesystem featuresdjwong-wtf_2022-11-09
Add the ability to upgrade *some* filesystem features. Note that you'll have to run online fsck immediately afterwards to build metadata! XXX DO NOT MERGE Signed-off-by: Darrick J. Wong <djwong@kernel.org>
-rw-r--r--fs/xfs/libxfs/xfs_fs.h1
-rw-r--r--fs/xfs/xfs_ioctl.c74
2 files changed, 75 insertions, 0 deletions
diff --git a/fs/xfs/libxfs/xfs_fs.h b/fs/xfs/libxfs/xfs_fs.h
index 48b1da71f70e..db290cda7e99 100644
--- a/fs/xfs/libxfs/xfs_fs.h
+++ b/fs/xfs/libxfs/xfs_fs.h
@@ -873,6 +873,7 @@ static inline size_t sizeof_xfs_scrub_vec(unsigned int nr)
#define XFS_IOC_UNRESVSP64 _IOW ('X', 43, struct xfs_flock64)
#define XFS_IOC_GETBMAPA _IOWR('X', 44, struct getbmap)
#define XFS_IOC_FSGETXATTRA _IOR ('X', 45, struct fsxattr)
+#define XFS_IOC_ADDFEATURE _IOR ('X', 46, __u64)
/* XFS_IOC_SETBIOSIZE ---- deprecated 46 */
/* XFS_IOC_GETBIOSIZE ---- deprecated 47 */
#define XFS_IOC_GETBMAPX _IOWR('X', 56, struct getbmap)
diff --git a/fs/xfs/xfs_ioctl.c b/fs/xfs/xfs_ioctl.c
index 7ff325d088ae..2e324c21eb2c 100644
--- a/fs/xfs/xfs_ioctl.c
+++ b/fs/xfs/xfs_ioctl.c
@@ -1953,6 +1953,78 @@ out:
return error;
}
+#define XFS_ADDFEATURE_SUPPORTED (XFS_FSOP_GEOM_FLAGS_INOBTCNT | \
+ XFS_FSOP_GEOM_FLAGS_BIGTIME)
+static int
+xfs_ioc_addfeature(
+ struct file *filp,
+ struct xfs_mount *mp,
+ __u64 __user *uflags)
+{
+ struct xfs_sb *sbp = &mp->m_sb;
+ struct block_device *bdev = xfs_buftarg_bdev(mp->m_ddev_targp);
+ __u64 flags;
+ bool dirty = false;
+ int error = 0;
+
+ if (!capable(CAP_SYS_ADMIN))
+ return -EPERM;
+
+ if (copy_from_user(&flags, uflags, sizeof(__u64)))
+ return -EFAULT;
+
+ if (flags & ~XFS_ADDFEATURE_SUPPORTED)
+ return -EINVAL;
+
+ error = mnt_want_write_file(filp);
+ if (error)
+ return error;
+
+ spin_lock(&mp->m_sb_lock);
+ if ((flags & XFS_FSOP_GEOM_FLAGS_BIGTIME) && !xfs_has_bigtime(mp)) {
+ xfs_info(mp, "Adding bigtime feature.");
+ sbp->sb_features_incompat |= XFS_SB_FEAT_INCOMPAT_BIGTIME;
+ mp->m_features |= XFS_FEAT_BIGTIME;
+ dirty = true;
+ }
+ if ((flags & XFS_FSOP_GEOM_FLAGS_INOBTCNT) &&
+ !xfs_has_inobtcounts(mp)) {
+ xfs_info(mp, "Adding inobtcount feature.");
+ sbp->sb_features_ro_compat |= XFS_SB_FEAT_RO_COMPAT_INOBTCNT;
+ mp->m_features |= XFS_FEAT_INOBTCNT;
+ dirty = true;
+ }
+ spin_unlock(&mp->m_sb_lock);
+
+ if (!dirty)
+ goto out;
+
+ /*
+ * Now we do several things to satisfy userspace.
+ * In addition to normal logging of the primary superblock, we also
+ * immediately write these changes to sector zero for the primary, then
+ * update all backup supers (as xfs_db does for a label change), then
+ * invalidate the block device page cache. This is so that any prior
+ * buffered reads from userspace (i.e. from blkid) are invalidated,
+ * and userspace will see the newly-written label.
+ */
+ error = xfs_sync_sb_buf(mp);
+ if (error)
+ goto out;
+ /*
+ * growfs also updates backup supers so lock against that.
+ */
+ mutex_lock(&mp->m_growlock);
+ error = xfs_update_secondary_sbs(mp);
+ mutex_unlock(&mp->m_growlock);
+
+ invalidate_bdev(bdev);
+
+out:
+ mnt_drop_write_file(filp);
+ return error;
+}
+
static inline int
xfs_fs_eofblocks_from_user(
struct xfs_fs_eofblocks *src,
@@ -2035,6 +2107,8 @@ xfs_file_ioctl(
return xfs_ioc_getlabel(mp, arg);
case FS_IOC_SETFSLABEL:
return xfs_ioc_setlabel(filp, mp, arg);
+ case XFS_IOC_ADDFEATURE:
+ return xfs_ioc_addfeature(filp, mp, arg);
case XFS_IOC_ALLOCSP:
case XFS_IOC_FREESP:
case XFS_IOC_ALLOCSP64: