diff options
Diffstat (limited to 'fs/btrfs/ioctl.c')
| -rw-r--r-- | fs/btrfs/ioctl.c | 36 |
1 files changed, 27 insertions, 9 deletions
diff --git a/fs/btrfs/ioctl.c b/fs/btrfs/ioctl.c index a506a22b522a..5fdb2abc4fa7 100644 --- a/fs/btrfs/ioctl.c +++ b/fs/btrfs/ioctl.c | |||
| @@ -203,7 +203,7 @@ static int btrfs_ioctl_setflags(struct file *file, void __user *arg) | |||
| 203 | 203 | ||
| 204 | 204 | ||
| 205 | trans = btrfs_join_transaction(root, 1); | 205 | trans = btrfs_join_transaction(root, 1); |
| 206 | BUG_ON(!trans); | 206 | BUG_ON(IS_ERR(trans)); |
| 207 | 207 | ||
| 208 | ret = btrfs_update_inode(trans, root, inode); | 208 | ret = btrfs_update_inode(trans, root, inode); |
| 209 | BUG_ON(ret); | 209 | BUG_ON(ret); |
| @@ -907,6 +907,10 @@ static noinline int btrfs_ioctl_resize(struct btrfs_root *root, | |||
| 907 | 907 | ||
| 908 | if (new_size > old_size) { | 908 | if (new_size > old_size) { |
| 909 | trans = btrfs_start_transaction(root, 0); | 909 | trans = btrfs_start_transaction(root, 0); |
| 910 | if (IS_ERR(trans)) { | ||
| 911 | ret = PTR_ERR(trans); | ||
| 912 | goto out_unlock; | ||
| 913 | } | ||
| 910 | ret = btrfs_grow_device(trans, device, new_size); | 914 | ret = btrfs_grow_device(trans, device, new_size); |
| 911 | btrfs_commit_transaction(trans, root); | 915 | btrfs_commit_transaction(trans, root); |
| 912 | } else { | 916 | } else { |
| @@ -1067,12 +1071,15 @@ static noinline int btrfs_ioctl_subvol_setflags(struct file *file, | |||
| 1067 | if (copy_from_user(&flags, arg, sizeof(flags))) | 1071 | if (copy_from_user(&flags, arg, sizeof(flags))) |
| 1068 | return -EFAULT; | 1072 | return -EFAULT; |
| 1069 | 1073 | ||
| 1070 | if (flags & ~BTRFS_SUBVOL_CREATE_ASYNC) | 1074 | if (flags & BTRFS_SUBVOL_CREATE_ASYNC) |
| 1071 | return -EINVAL; | 1075 | return -EINVAL; |
| 1072 | 1076 | ||
| 1073 | if (flags & ~BTRFS_SUBVOL_RDONLY) | 1077 | if (flags & ~BTRFS_SUBVOL_RDONLY) |
| 1074 | return -EOPNOTSUPP; | 1078 | return -EOPNOTSUPP; |
| 1075 | 1079 | ||
| 1080 | if (!is_owner_or_cap(inode)) | ||
| 1081 | return -EACCES; | ||
| 1082 | |||
| 1076 | down_write(&root->fs_info->subvol_sem); | 1083 | down_write(&root->fs_info->subvol_sem); |
| 1077 | 1084 | ||
| 1078 | /* nothing to do */ | 1085 | /* nothing to do */ |
| @@ -1093,7 +1100,7 @@ static noinline int btrfs_ioctl_subvol_setflags(struct file *file, | |||
| 1093 | goto out_reset; | 1100 | goto out_reset; |
| 1094 | } | 1101 | } |
| 1095 | 1102 | ||
| 1096 | ret = btrfs_update_root(trans, root, | 1103 | ret = btrfs_update_root(trans, root->fs_info->tree_root, |
| 1097 | &root->root_key, &root->root_item); | 1104 | &root->root_key, &root->root_item); |
| 1098 | 1105 | ||
| 1099 | btrfs_commit_transaction(trans, root); | 1106 | btrfs_commit_transaction(trans, root); |
| @@ -1898,7 +1905,10 @@ static noinline long btrfs_ioctl_clone(struct file *file, unsigned long srcfd, | |||
| 1898 | 1905 | ||
| 1899 | memcpy(&new_key, &key, sizeof(new_key)); | 1906 | memcpy(&new_key, &key, sizeof(new_key)); |
| 1900 | new_key.objectid = inode->i_ino; | 1907 | new_key.objectid = inode->i_ino; |
| 1901 | new_key.offset = key.offset + destoff - off; | 1908 | if (off <= key.offset) |
| 1909 | new_key.offset = key.offset + destoff - off; | ||
| 1910 | else | ||
| 1911 | new_key.offset = destoff; | ||
| 1902 | 1912 | ||
| 1903 | trans = btrfs_start_transaction(root, 1); | 1913 | trans = btrfs_start_transaction(root, 1); |
| 1904 | if (IS_ERR(trans)) { | 1914 | if (IS_ERR(trans)) { |
| @@ -2082,7 +2092,7 @@ static long btrfs_ioctl_trans_start(struct file *file) | |||
| 2082 | 2092 | ||
| 2083 | ret = -ENOMEM; | 2093 | ret = -ENOMEM; |
| 2084 | trans = btrfs_start_ioctl_transaction(root, 0); | 2094 | trans = btrfs_start_ioctl_transaction(root, 0); |
| 2085 | if (!trans) | 2095 | if (IS_ERR(trans)) |
| 2086 | goto out_drop; | 2096 | goto out_drop; |
| 2087 | 2097 | ||
| 2088 | file->private_data = trans; | 2098 | file->private_data = trans; |
| @@ -2138,9 +2148,9 @@ static long btrfs_ioctl_default_subvol(struct file *file, void __user *argp) | |||
| 2138 | path->leave_spinning = 1; | 2148 | path->leave_spinning = 1; |
| 2139 | 2149 | ||
| 2140 | trans = btrfs_start_transaction(root, 1); | 2150 | trans = btrfs_start_transaction(root, 1); |
| 2141 | if (!trans) { | 2151 | if (IS_ERR(trans)) { |
| 2142 | btrfs_free_path(path); | 2152 | btrfs_free_path(path); |
| 2143 | return -ENOMEM; | 2153 | return PTR_ERR(trans); |
| 2144 | } | 2154 | } |
| 2145 | 2155 | ||
| 2146 | dir_id = btrfs_super_root_dir(&root->fs_info->super_copy); | 2156 | dir_id = btrfs_super_root_dir(&root->fs_info->super_copy); |
| @@ -2201,7 +2211,7 @@ long btrfs_ioctl_space_info(struct btrfs_root *root, void __user *arg) | |||
| 2201 | int num_types = 4; | 2211 | int num_types = 4; |
| 2202 | int alloc_size; | 2212 | int alloc_size; |
| 2203 | int ret = 0; | 2213 | int ret = 0; |
| 2204 | int slot_count = 0; | 2214 | u64 slot_count = 0; |
| 2205 | int i, c; | 2215 | int i, c; |
| 2206 | 2216 | ||
| 2207 | if (copy_from_user(&space_args, | 2217 | if (copy_from_user(&space_args, |
| @@ -2240,7 +2250,7 @@ long btrfs_ioctl_space_info(struct btrfs_root *root, void __user *arg) | |||
| 2240 | goto out; | 2250 | goto out; |
| 2241 | } | 2251 | } |
| 2242 | 2252 | ||
| 2243 | slot_count = min_t(int, space_args.space_slots, slot_count); | 2253 | slot_count = min_t(u64, space_args.space_slots, slot_count); |
| 2244 | 2254 | ||
| 2245 | alloc_size = sizeof(*dest) * slot_count; | 2255 | alloc_size = sizeof(*dest) * slot_count; |
| 2246 | 2256 | ||
| @@ -2260,6 +2270,9 @@ long btrfs_ioctl_space_info(struct btrfs_root *root, void __user *arg) | |||
| 2260 | for (i = 0; i < num_types; i++) { | 2270 | for (i = 0; i < num_types; i++) { |
| 2261 | struct btrfs_space_info *tmp; | 2271 | struct btrfs_space_info *tmp; |
| 2262 | 2272 | ||
| 2273 | if (!slot_count) | ||
| 2274 | break; | ||
| 2275 | |||
| 2263 | info = NULL; | 2276 | info = NULL; |
| 2264 | rcu_read_lock(); | 2277 | rcu_read_lock(); |
| 2265 | list_for_each_entry_rcu(tmp, &root->fs_info->space_info, | 2278 | list_for_each_entry_rcu(tmp, &root->fs_info->space_info, |
| @@ -2281,7 +2294,10 @@ long btrfs_ioctl_space_info(struct btrfs_root *root, void __user *arg) | |||
| 2281 | memcpy(dest, &space, sizeof(space)); | 2294 | memcpy(dest, &space, sizeof(space)); |
| 2282 | dest++; | 2295 | dest++; |
| 2283 | space_args.total_spaces++; | 2296 | space_args.total_spaces++; |
| 2297 | slot_count--; | ||
| 2284 | } | 2298 | } |
| 2299 | if (!slot_count) | ||
| 2300 | break; | ||
| 2285 | } | 2301 | } |
| 2286 | up_read(&info->groups_sem); | 2302 | up_read(&info->groups_sem); |
| 2287 | } | 2303 | } |
| @@ -2334,6 +2350,8 @@ static noinline long btrfs_ioctl_start_sync(struct file *file, void __user *argp | |||
| 2334 | u64 transid; | 2350 | u64 transid; |
| 2335 | 2351 | ||
| 2336 | trans = btrfs_start_transaction(root, 0); | 2352 | trans = btrfs_start_transaction(root, 0); |
| 2353 | if (IS_ERR(trans)) | ||
| 2354 | return PTR_ERR(trans); | ||
| 2337 | transid = trans->transid; | 2355 | transid = trans->transid; |
| 2338 | btrfs_commit_transaction_async(trans, root, 0); | 2356 | btrfs_commit_transaction_async(trans, root, 0); |
| 2339 | 2357 | ||
