diff options
author | Darrick J. Wong <djwong@kernel.org> | 2022-07-14 11:16:24 -0700 |
---|---|---|
committer | Darrick J. Wong <djwong@kernel.org> | 2022-10-14 14:17:29 -0700 |
commit | 98d77835159c86d4c31d9011be9ae2adbc805306 (patch) | |
tree | af3719ceb9622df32463f3d61fa3851a8e2af339 | |
parent | 329347290ff24672bc398056af8a2351c2a8d6e7 (diff) |
xfs: upgrade filesystem featuresdjwong-wtf_2022-10-14
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.h | 1 | ||||
-rw-r--r-- | fs/xfs/xfs_ioctl.c | 74 |
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: |