hulk inclusion category: feature bugzilla: https://gitee.com/openeuler/kernel/issues/I9VTE3 CVE: NA
--------------------------------
Support FS_IOC_SETATOMIC ioctl, if filesystem and file could support atomic write, then enable file's atomic write function. Database like Mysql could use this ioctl check and enable file atomic write.
Signed-off-by: Long Li leo.lilong@huawei.com --- fs/xfs/xfs_ioctl.c | 47 +++++++++++++++++++++++++++++++++++++++++ include/uapi/linux/fs.h | 1 + 2 files changed, 48 insertions(+)
diff --git a/fs/xfs/xfs_ioctl.c b/fs/xfs/xfs_ioctl.c index e96ebea20991..595fe560f411 100644 --- a/fs/xfs/xfs_ioctl.c +++ b/fs/xfs/xfs_ioctl.c @@ -2112,6 +2112,28 @@ xfs_fs_eofblocks_from_user( return 0; }
+static int +xfs_ioc_set_atomic_write( + struct xfs_inode *ip) +{ + struct xfs_trans *tp; + int error; + + tp = xfs_ioctl_setattr_get_trans(ip, NULL); + if (IS_ERR(tp)) { + error = PTR_ERR(tp); + goto out; + } + + ip->i_d.di_flags2 |= XFS_DIFLAG2_ATOMICWRITES; + + xfs_trans_ichgtime(tp, ip, XFS_ICHGTIME_CHG); + xfs_trans_log_inode(tp, ip, XFS_ILOG_CORE); + error = xfs_trans_commit(tp); +out: + return error; +} + /* * Note: some of the ioctl's return positive numbers as a * byte count indicating success, such as readlink_by_handle. @@ -2139,6 +2161,31 @@ xfs_file_ioctl( return xfs_ioc_getlabel(mp, arg); case FS_IOC_SETFSLABEL: return xfs_ioc_setlabel(filp, mp, arg); + case FS_IOC_SETATOMIC: + if (!xfs_has_atomicwrites(mp)) + return -1; + if (!S_ISREG(inode->i_mode)) + return -1; + if (xfs_inode_atomicwrites(ip)) + return 0; + if (!xfs_inode_forcealign(ip)) + return -1; + + xfs_ilock(ip, XFS_IOLOCK_EXCL | XFS_MMAPLOCK_EXCL); + error = xfs_ioc_set_atomic_write(ip); + xfs_iunlock(ip, XFS_IOLOCK_EXCL | XFS_MMAPLOCK_EXCL); + if (error) { + xfs_alert(mp, "%s: set ino 0x%llx atomic write fail!", + __func__, XFS_I(inode)->i_ino); + return -1; + } else { + struct xfs_buftarg *target = xfs_inode_buftarg(ip); + + if ((filp->f_flags & O_DIRECT) && + bdev_can_atomic_write(target->bt_bdev)) + filp->f_mode |= FMODE_CAN_ATOMIC_WRITE; + return 0; + } case XFS_IOC_ALLOCSP: case XFS_IOC_FREESP: case XFS_IOC_ALLOCSP64: diff --git a/include/uapi/linux/fs.h b/include/uapi/linux/fs.h index ca8b6f6c479d..332b0709756b 100644 --- a/include/uapi/linux/fs.h +++ b/include/uapi/linux/fs.h @@ -217,6 +217,7 @@ struct fsxattr { #define FS_IOC_FSSETXATTR _IOW('X', 32, struct fsxattr) #define FS_IOC_GETFSLABEL _IOR(0x94, 49, char[FSLABEL_MAX]) #define FS_IOC_SETFSLABEL _IOW(0x94, 50, char[FSLABEL_MAX]) +#define FS_IOC_SETATOMIC _IOW(0x95, 2, uint)
/* * Inode flags (FS_IOC_GETFLAGS / FS_IOC_SETFLAGS)