aboutsummaryrefslogtreecommitdiffstats
path: root/fs/btrfs/ioctl.c
diff options
context:
space:
mode:
Diffstat (limited to 'fs/btrfs/ioctl.c')
-rw-r--r--fs/btrfs/ioctl.c36
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