mirror of
https://github.com/Fishwaldo/Star64_linux.git
synced 2025-04-01 12:04:08 +00:00
btrfs: change extent-same to copy entire argument struct
btrfs_ioctl_file_extent_same() uses __put_user_unaligned() to copy some data back to it's argument struct. Unfortunately, not all architectures provide __put_user_unaligned(), so compiles break on them if btrfs is selected. Instead, just copy the whole struct in / out at the start and end of operations, respectively. Signed-off-by: Mark Fasheh <mfasheh@suse.de> Signed-off-by: Josef Bacik <jbacik@fusionio.com> Signed-off-by: Chris Mason <chris.mason@fusionio.com>
This commit is contained in:
parent
93fd63c2f0
commit
cbf8b8ca3e
1 changed files with 45 additions and 31 deletions
|
@ -2696,9 +2696,9 @@ out_unlock:
|
||||||
static long btrfs_ioctl_file_extent_same(struct file *file,
|
static long btrfs_ioctl_file_extent_same(struct file *file,
|
||||||
void __user *argp)
|
void __user *argp)
|
||||||
{
|
{
|
||||||
struct btrfs_ioctl_same_args *args = argp;
|
struct btrfs_ioctl_same_args tmp;
|
||||||
struct btrfs_ioctl_same_args same;
|
struct btrfs_ioctl_same_args *same;
|
||||||
struct btrfs_ioctl_same_extent_info info;
|
struct btrfs_ioctl_same_extent_info *info;
|
||||||
struct inode *src = file->f_dentry->d_inode;
|
struct inode *src = file->f_dentry->d_inode;
|
||||||
struct file *dst_file = NULL;
|
struct file *dst_file = NULL;
|
||||||
struct inode *dst;
|
struct inode *dst;
|
||||||
|
@ -2706,6 +2706,7 @@ static long btrfs_ioctl_file_extent_same(struct file *file,
|
||||||
u64 len;
|
u64 len;
|
||||||
int i;
|
int i;
|
||||||
int ret;
|
int ret;
|
||||||
|
unsigned long size;
|
||||||
u64 bs = BTRFS_I(src)->root->fs_info->sb->s_blocksize;
|
u64 bs = BTRFS_I(src)->root->fs_info->sb->s_blocksize;
|
||||||
bool is_admin = capable(CAP_SYS_ADMIN);
|
bool is_admin = capable(CAP_SYS_ADMIN);
|
||||||
|
|
||||||
|
@ -2716,15 +2717,30 @@ static long btrfs_ioctl_file_extent_same(struct file *file,
|
||||||
if (ret)
|
if (ret)
|
||||||
return ret;
|
return ret;
|
||||||
|
|
||||||
if (copy_from_user(&same,
|
if (copy_from_user(&tmp,
|
||||||
(struct btrfs_ioctl_same_args __user *)argp,
|
(struct btrfs_ioctl_same_args __user *)argp,
|
||||||
sizeof(same))) {
|
sizeof(tmp))) {
|
||||||
ret = -EFAULT;
|
ret = -EFAULT;
|
||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
|
|
||||||
off = same.logical_offset;
|
size = sizeof(tmp) +
|
||||||
len = same.length;
|
tmp.dest_count * sizeof(struct btrfs_ioctl_same_extent_info);
|
||||||
|
|
||||||
|
same = kmalloc(size, GFP_NOFS);
|
||||||
|
if (!same) {
|
||||||
|
ret = -EFAULT;
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (copy_from_user(same,
|
||||||
|
(struct btrfs_ioctl_same_args __user *)argp, size)) {
|
||||||
|
ret = -EFAULT;
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
|
||||||
|
off = same->logical_offset;
|
||||||
|
len = same->length;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Limit the total length we will dedupe for each operation.
|
* Limit the total length we will dedupe for each operation.
|
||||||
|
@ -2752,27 +2768,28 @@ static long btrfs_ioctl_file_extent_same(struct file *file,
|
||||||
if (!S_ISREG(src->i_mode))
|
if (!S_ISREG(src->i_mode))
|
||||||
goto out;
|
goto out;
|
||||||
|
|
||||||
|
/* pre-format output fields to sane values */
|
||||||
|
for (i = 0; i < same->dest_count; i++) {
|
||||||
|
same->info[i].bytes_deduped = 0ULL;
|
||||||
|
same->info[i].status = 0;
|
||||||
|
}
|
||||||
|
|
||||||
ret = 0;
|
ret = 0;
|
||||||
for (i = 0; i < same.dest_count; i++) {
|
for (i = 0; i < same->dest_count; i++) {
|
||||||
if (copy_from_user(&info, &args->info[i], sizeof(info))) {
|
info = &same->info[i];
|
||||||
ret = -EFAULT;
|
|
||||||
goto out;
|
|
||||||
}
|
|
||||||
|
|
||||||
info.bytes_deduped = 0;
|
dst_file = fget(info->fd);
|
||||||
|
|
||||||
dst_file = fget(info.fd);
|
|
||||||
if (!dst_file) {
|
if (!dst_file) {
|
||||||
info.status = -EBADF;
|
info->status = -EBADF;
|
||||||
goto next;
|
goto next;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!(is_admin || (dst_file->f_mode & FMODE_WRITE))) {
|
if (!(is_admin || (dst_file->f_mode & FMODE_WRITE))) {
|
||||||
info.status = -EINVAL;
|
info->status = -EINVAL;
|
||||||
goto next;
|
goto next;
|
||||||
}
|
}
|
||||||
|
|
||||||
info.status = -EXDEV;
|
info->status = -EXDEV;
|
||||||
if (file->f_path.mnt != dst_file->f_path.mnt)
|
if (file->f_path.mnt != dst_file->f_path.mnt)
|
||||||
goto next;
|
goto next;
|
||||||
|
|
||||||
|
@ -2781,32 +2798,29 @@ static long btrfs_ioctl_file_extent_same(struct file *file,
|
||||||
goto next;
|
goto next;
|
||||||
|
|
||||||
if (S_ISDIR(dst->i_mode)) {
|
if (S_ISDIR(dst->i_mode)) {
|
||||||
info.status = -EISDIR;
|
info->status = -EISDIR;
|
||||||
goto next;
|
goto next;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!S_ISREG(dst->i_mode)) {
|
if (!S_ISREG(dst->i_mode)) {
|
||||||
info.status = -EACCES;
|
info->status = -EACCES;
|
||||||
goto next;
|
goto next;
|
||||||
}
|
}
|
||||||
|
|
||||||
info.status = btrfs_extent_same(src, off, len, dst,
|
info->status = btrfs_extent_same(src, off, len, dst,
|
||||||
info.logical_offset);
|
info->logical_offset);
|
||||||
if (info.status == 0)
|
if (info->status == 0)
|
||||||
info.bytes_deduped += len;
|
info->bytes_deduped += len;
|
||||||
|
|
||||||
next:
|
next:
|
||||||
if (dst_file)
|
if (dst_file)
|
||||||
fput(dst_file);
|
fput(dst_file);
|
||||||
|
|
||||||
if (__put_user_unaligned(info.status, &args->info[i].status) ||
|
|
||||||
__put_user_unaligned(info.bytes_deduped,
|
|
||||||
&args->info[i].bytes_deduped)) {
|
|
||||||
ret = -EFAULT;
|
|
||||||
goto out;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ret = copy_to_user(argp, same, size);
|
||||||
|
if (ret)
|
||||||
|
ret = -EFAULT;
|
||||||
|
|
||||||
out:
|
out:
|
||||||
mnt_drop_write_file(file);
|
mnt_drop_write_file(file);
|
||||||
return ret;
|
return ret;
|
||||||
|
|
Loading…
Add table
Reference in a new issue