diff options
Diffstat (limited to 'fs/xfs/xfs_ioctl.c')
-rw-r--r-- | fs/xfs/xfs_ioctl.c | 72 |
1 files changed, 70 insertions, 2 deletions
diff --git a/fs/xfs/xfs_ioctl.c b/fs/xfs/xfs_ioctl.c index 557c7b8b2425..efb216de5f69 100644 --- a/fs/xfs/xfs_ioctl.c +++ b/fs/xfs/xfs_ioctl.c @@ -35,7 +35,6 @@ #include "xfs_bmap.h" #include "xfs_bmap_util.h" #include "xfs_buf_item.h" -#include "xfs_dfrag.h" #include "xfs_fsops.h" #include "xfs_discard.h" #include "xfs_quota.h" @@ -1363,6 +1362,75 @@ xfs_ioc_getbmapx( return 0; } +int +xfs_ioc_swapext( + xfs_swapext_t *sxp) +{ + xfs_inode_t *ip, *tip; + struct fd f, tmp; + int error = 0; + + /* Pull information for the target fd */ + f = fdget((int)sxp->sx_fdtarget); + if (!f.file) { + error = XFS_ERROR(EINVAL); + goto out; + } + + if (!(f.file->f_mode & FMODE_WRITE) || + !(f.file->f_mode & FMODE_READ) || + (f.file->f_flags & O_APPEND)) { + error = XFS_ERROR(EBADF); + goto out_put_file; + } + + tmp = fdget((int)sxp->sx_fdtmp); + if (!tmp.file) { + error = XFS_ERROR(EINVAL); + goto out_put_file; + } + + if (!(tmp.file->f_mode & FMODE_WRITE) || + !(tmp.file->f_mode & FMODE_READ) || + (tmp.file->f_flags & O_APPEND)) { + error = XFS_ERROR(EBADF); + goto out_put_tmp_file; + } + + if (IS_SWAPFILE(file_inode(f.file)) || + IS_SWAPFILE(file_inode(tmp.file))) { + error = XFS_ERROR(EINVAL); + goto out_put_tmp_file; + } + + ip = XFS_I(file_inode(f.file)); + tip = XFS_I(file_inode(tmp.file)); + + if (ip->i_mount != tip->i_mount) { + error = XFS_ERROR(EINVAL); + goto out_put_tmp_file; + } + + if (ip->i_ino == tip->i_ino) { + error = XFS_ERROR(EINVAL); + goto out_put_tmp_file; + } + + if (XFS_FORCED_SHUTDOWN(ip->i_mount)) { + error = XFS_ERROR(EIO); + goto out_put_tmp_file; + } + + error = xfs_swap_extents(ip, tip, sxp); + + out_put_tmp_file: + fdput(tmp); + out_put_file: + fdput(f); + out: + return error; +} + /* * Note: some of the ioctl's return positive numbers as a * byte count indicating success, such as readlink_by_handle. @@ -1507,7 +1575,7 @@ xfs_file_ioctl( error = mnt_want_write_file(filp); if (error) return error; - error = xfs_swapext(&sxp); + error = xfs_ioc_swapext(&sxp); mnt_drop_write_file(filp); return -error; } |