diff options
Diffstat (limited to 'fs/btrfs')
-rw-r--r-- | fs/btrfs/acl.c | 70 | ||||
-rw-r--r-- | fs/btrfs/ctree.h | 11 | ||||
-rw-r--r-- | fs/btrfs/delayed-inode.h | 2 | ||||
-rw-r--r-- | fs/btrfs/disk-io.c | 15 | ||||
-rw-r--r-- | fs/btrfs/extent-tree.c | 12 | ||||
-rw-r--r-- | fs/btrfs/extent_io.c | 1 | ||||
-rw-r--r-- | fs/btrfs/file.c | 173 | ||||
-rw-r--r-- | fs/btrfs/inode.c | 88 | ||||
-rw-r--r-- | fs/btrfs/ioctl.c | 16 |
9 files changed, 269 insertions, 119 deletions
diff --git a/fs/btrfs/acl.c b/fs/btrfs/acl.c index b206d4c2720b..eb159aaa5a11 100644 --- a/fs/btrfs/acl.c +++ b/fs/btrfs/acl.c | |||
@@ -28,7 +28,7 @@ | |||
28 | #include "btrfs_inode.h" | 28 | #include "btrfs_inode.h" |
29 | #include "xattr.h" | 29 | #include "xattr.h" |
30 | 30 | ||
31 | static struct posix_acl *btrfs_get_acl(struct inode *inode, int type) | 31 | struct posix_acl *btrfs_get_acl(struct inode *inode, int type) |
32 | { | 32 | { |
33 | int size; | 33 | int size; |
34 | const char *name; | 34 | const char *name; |
@@ -109,7 +109,6 @@ static int btrfs_set_acl(struct btrfs_trans_handle *trans, | |||
109 | int ret, size = 0; | 109 | int ret, size = 0; |
110 | const char *name; | 110 | const char *name; |
111 | char *value = NULL; | 111 | char *value = NULL; |
112 | mode_t mode; | ||
113 | 112 | ||
114 | if (acl) { | 113 | if (acl) { |
115 | ret = posix_acl_valid(acl); | 114 | ret = posix_acl_valid(acl); |
@@ -120,13 +119,11 @@ static int btrfs_set_acl(struct btrfs_trans_handle *trans, | |||
120 | 119 | ||
121 | switch (type) { | 120 | switch (type) { |
122 | case ACL_TYPE_ACCESS: | 121 | case ACL_TYPE_ACCESS: |
123 | mode = inode->i_mode; | ||
124 | name = POSIX_ACL_XATTR_ACCESS; | 122 | name = POSIX_ACL_XATTR_ACCESS; |
125 | if (acl) { | 123 | if (acl) { |
126 | ret = posix_acl_equiv_mode(acl, &mode); | 124 | ret = posix_acl_equiv_mode(acl, &inode->i_mode); |
127 | if (ret < 0) | 125 | if (ret < 0) |
128 | return ret; | 126 | return ret; |
129 | inode->i_mode = mode; | ||
130 | } | 127 | } |
131 | ret = 0; | 128 | ret = 0; |
132 | break; | 129 | break; |
@@ -193,28 +190,6 @@ out: | |||
193 | return ret; | 190 | return ret; |
194 | } | 191 | } |
195 | 192 | ||
196 | int btrfs_check_acl(struct inode *inode, int mask, unsigned int flags) | ||
197 | { | ||
198 | int error = -EAGAIN; | ||
199 | |||
200 | if (flags & IPERM_FLAG_RCU) { | ||
201 | if (!negative_cached_acl(inode, ACL_TYPE_ACCESS)) | ||
202 | error = -ECHILD; | ||
203 | |||
204 | } else { | ||
205 | struct posix_acl *acl; | ||
206 | acl = btrfs_get_acl(inode, ACL_TYPE_ACCESS); | ||
207 | if (IS_ERR(acl)) | ||
208 | return PTR_ERR(acl); | ||
209 | if (acl) { | ||
210 | error = posix_acl_permission(inode, acl, mask); | ||
211 | posix_acl_release(acl); | ||
212 | } | ||
213 | } | ||
214 | |||
215 | return error; | ||
216 | } | ||
217 | |||
218 | /* | 193 | /* |
219 | * btrfs_init_acl is already generally called under fs_mutex, so the locking | 194 | * btrfs_init_acl is already generally called under fs_mutex, so the locking |
220 | * stuff has been fixed to work with that. If the locking stuff changes, we | 195 | * stuff has been fixed to work with that. If the locking stuff changes, we |
@@ -242,31 +217,20 @@ int btrfs_init_acl(struct btrfs_trans_handle *trans, | |||
242 | } | 217 | } |
243 | 218 | ||
244 | if (IS_POSIXACL(dir) && acl) { | 219 | if (IS_POSIXACL(dir) && acl) { |
245 | struct posix_acl *clone; | ||
246 | mode_t mode; | ||
247 | |||
248 | if (S_ISDIR(inode->i_mode)) { | 220 | if (S_ISDIR(inode->i_mode)) { |
249 | ret = btrfs_set_acl(trans, inode, acl, | 221 | ret = btrfs_set_acl(trans, inode, acl, |
250 | ACL_TYPE_DEFAULT); | 222 | ACL_TYPE_DEFAULT); |
251 | if (ret) | 223 | if (ret) |
252 | goto failed; | 224 | goto failed; |
253 | } | 225 | } |
254 | clone = posix_acl_clone(acl, GFP_NOFS); | 226 | ret = posix_acl_create(&acl, GFP_NOFS, &inode->i_mode); |
255 | ret = -ENOMEM; | 227 | if (ret < 0) |
256 | if (!clone) | 228 | return ret; |
257 | goto failed; | 229 | |
258 | 230 | if (ret > 0) { | |
259 | mode = inode->i_mode; | 231 | /* we need an acl */ |
260 | ret = posix_acl_create_masq(clone, &mode); | 232 | ret = btrfs_set_acl(trans, inode, acl, ACL_TYPE_ACCESS); |
261 | if (ret >= 0) { | ||
262 | inode->i_mode = mode; | ||
263 | if (ret > 0) { | ||
264 | /* we need an acl */ | ||
265 | ret = btrfs_set_acl(trans, inode, clone, | ||
266 | ACL_TYPE_ACCESS); | ||
267 | } | ||
268 | } | 233 | } |
269 | posix_acl_release(clone); | ||
270 | } | 234 | } |
271 | failed: | 235 | failed: |
272 | posix_acl_release(acl); | 236 | posix_acl_release(acl); |
@@ -276,7 +240,7 @@ failed: | |||
276 | 240 | ||
277 | int btrfs_acl_chmod(struct inode *inode) | 241 | int btrfs_acl_chmod(struct inode *inode) |
278 | { | 242 | { |
279 | struct posix_acl *acl, *clone; | 243 | struct posix_acl *acl; |
280 | int ret = 0; | 244 | int ret = 0; |
281 | 245 | ||
282 | if (S_ISLNK(inode->i_mode)) | 246 | if (S_ISLNK(inode->i_mode)) |
@@ -289,17 +253,11 @@ int btrfs_acl_chmod(struct inode *inode) | |||
289 | if (IS_ERR_OR_NULL(acl)) | 253 | if (IS_ERR_OR_NULL(acl)) |
290 | return PTR_ERR(acl); | 254 | return PTR_ERR(acl); |
291 | 255 | ||
292 | clone = posix_acl_clone(acl, GFP_KERNEL); | 256 | ret = posix_acl_chmod(&acl, GFP_KERNEL, inode->i_mode); |
257 | if (ret) | ||
258 | return ret; | ||
259 | ret = btrfs_set_acl(NULL, inode, acl, ACL_TYPE_ACCESS); | ||
293 | posix_acl_release(acl); | 260 | posix_acl_release(acl); |
294 | if (!clone) | ||
295 | return -ENOMEM; | ||
296 | |||
297 | ret = posix_acl_chmod_masq(clone, inode->i_mode); | ||
298 | if (!ret) | ||
299 | ret = btrfs_set_acl(NULL, inode, clone, ACL_TYPE_ACCESS); | ||
300 | |||
301 | posix_acl_release(clone); | ||
302 | |||
303 | return ret; | 261 | return ret; |
304 | } | 262 | } |
305 | 263 | ||
diff --git a/fs/btrfs/ctree.h b/fs/btrfs/ctree.h index 8b99c79ad1a7..03912c5c6f49 100644 --- a/fs/btrfs/ctree.h +++ b/fs/btrfs/ctree.h | |||
@@ -1224,7 +1224,7 @@ struct btrfs_root { | |||
1224 | * right now this just gets used so that a root has its own devid | 1224 | * right now this just gets used so that a root has its own devid |
1225 | * for stat. It may be used for more later | 1225 | * for stat. It may be used for more later |
1226 | */ | 1226 | */ |
1227 | struct super_block anon_super; | 1227 | dev_t anon_dev; |
1228 | }; | 1228 | }; |
1229 | 1229 | ||
1230 | struct btrfs_ioctl_defrag_range_args { | 1230 | struct btrfs_ioctl_defrag_range_args { |
@@ -2510,6 +2510,9 @@ int btrfs_csum_truncate(struct btrfs_trans_handle *trans, | |||
2510 | int btrfs_lookup_csums_range(struct btrfs_root *root, u64 start, u64 end, | 2510 | int btrfs_lookup_csums_range(struct btrfs_root *root, u64 start, u64 end, |
2511 | struct list_head *list, int search_commit); | 2511 | struct list_head *list, int search_commit); |
2512 | /* inode.c */ | 2512 | /* inode.c */ |
2513 | struct extent_map *btrfs_get_extent_fiemap(struct inode *inode, struct page *page, | ||
2514 | size_t pg_offset, u64 start, u64 len, | ||
2515 | int create); | ||
2513 | 2516 | ||
2514 | /* RHEL and EL kernels have a patch that renames PG_checked to FsMisc */ | 2517 | /* RHEL and EL kernels have a patch that renames PG_checked to FsMisc */ |
2515 | #if defined(ClearPageFsMisc) && !defined(ClearPageChecked) | 2518 | #if defined(ClearPageFsMisc) && !defined(ClearPageChecked) |
@@ -2607,7 +2610,7 @@ int btrfs_defrag_file(struct inode *inode, struct file *file, | |||
2607 | int btrfs_add_inode_defrag(struct btrfs_trans_handle *trans, | 2610 | int btrfs_add_inode_defrag(struct btrfs_trans_handle *trans, |
2608 | struct inode *inode); | 2611 | struct inode *inode); |
2609 | int btrfs_run_defrag_inodes(struct btrfs_fs_info *fs_info); | 2612 | int btrfs_run_defrag_inodes(struct btrfs_fs_info *fs_info); |
2610 | int btrfs_sync_file(struct file *file, int datasync); | 2613 | int btrfs_sync_file(struct file *file, loff_t start, loff_t end, int datasync); |
2611 | int btrfs_drop_extent_cache(struct inode *inode, u64 start, u64 end, | 2614 | int btrfs_drop_extent_cache(struct inode *inode, u64 start, u64 end, |
2612 | int skip_pinned); | 2615 | int skip_pinned); |
2613 | extern const struct file_operations btrfs_file_operations; | 2616 | extern const struct file_operations btrfs_file_operations; |
@@ -2647,12 +2650,12 @@ do { \ | |||
2647 | 2650 | ||
2648 | /* acl.c */ | 2651 | /* acl.c */ |
2649 | #ifdef CONFIG_BTRFS_FS_POSIX_ACL | 2652 | #ifdef CONFIG_BTRFS_FS_POSIX_ACL |
2650 | int btrfs_check_acl(struct inode *inode, int mask, unsigned int flags); | 2653 | struct posix_acl *btrfs_get_acl(struct inode *inode, int type); |
2651 | int btrfs_init_acl(struct btrfs_trans_handle *trans, | 2654 | int btrfs_init_acl(struct btrfs_trans_handle *trans, |
2652 | struct inode *inode, struct inode *dir); | 2655 | struct inode *inode, struct inode *dir); |
2653 | int btrfs_acl_chmod(struct inode *inode); | 2656 | int btrfs_acl_chmod(struct inode *inode); |
2654 | #else | 2657 | #else |
2655 | #define btrfs_check_acl NULL | 2658 | #define btrfs_get_acl NULL |
2656 | static inline int btrfs_init_acl(struct btrfs_trans_handle *trans, | 2659 | static inline int btrfs_init_acl(struct btrfs_trans_handle *trans, |
2657 | struct inode *inode, struct inode *dir) | 2660 | struct inode *inode, struct inode *dir) |
2658 | { | 2661 | { |
diff --git a/fs/btrfs/delayed-inode.h b/fs/btrfs/delayed-inode.h index 8d27af4bd8b9..7083d08b2a21 100644 --- a/fs/btrfs/delayed-inode.h +++ b/fs/btrfs/delayed-inode.h | |||
@@ -25,7 +25,7 @@ | |||
25 | #include <linux/mutex.h> | 25 | #include <linux/mutex.h> |
26 | #include <linux/list.h> | 26 | #include <linux/list.h> |
27 | #include <linux/wait.h> | 27 | #include <linux/wait.h> |
28 | #include <asm/atomic.h> | 28 | #include <linux/atomic.h> |
29 | 29 | ||
30 | #include "ctree.h" | 30 | #include "ctree.h" |
31 | 31 | ||
diff --git a/fs/btrfs/disk-io.c b/fs/btrfs/disk-io.c index 94ecac33cf2d..07b3ac662e19 100644 --- a/fs/btrfs/disk-io.c +++ b/fs/btrfs/disk-io.c | |||
@@ -1111,12 +1111,7 @@ static int __setup_root(u32 nodesize, u32 leafsize, u32 sectorsize, | |||
1111 | init_completion(&root->kobj_unregister); | 1111 | init_completion(&root->kobj_unregister); |
1112 | root->defrag_running = 0; | 1112 | root->defrag_running = 0; |
1113 | root->root_key.objectid = objectid; | 1113 | root->root_key.objectid = objectid; |
1114 | root->anon_super.s_root = NULL; | 1114 | root->anon_dev = 0; |
1115 | root->anon_super.s_dev = 0; | ||
1116 | INIT_LIST_HEAD(&root->anon_super.s_list); | ||
1117 | INIT_LIST_HEAD(&root->anon_super.s_instances); | ||
1118 | init_rwsem(&root->anon_super.s_umount); | ||
1119 | |||
1120 | return 0; | 1115 | return 0; |
1121 | } | 1116 | } |
1122 | 1117 | ||
@@ -1345,7 +1340,7 @@ again: | |||
1345 | spin_lock_init(&root->cache_lock); | 1340 | spin_lock_init(&root->cache_lock); |
1346 | init_waitqueue_head(&root->cache_wait); | 1341 | init_waitqueue_head(&root->cache_wait); |
1347 | 1342 | ||
1348 | ret = set_anon_super(&root->anon_super, NULL); | 1343 | ret = get_anon_bdev(&root->anon_dev); |
1349 | if (ret) | 1344 | if (ret) |
1350 | goto fail; | 1345 | goto fail; |
1351 | 1346 | ||
@@ -2432,10 +2427,8 @@ static void free_fs_root(struct btrfs_root *root) | |||
2432 | { | 2427 | { |
2433 | iput(root->cache_inode); | 2428 | iput(root->cache_inode); |
2434 | WARN_ON(!RB_EMPTY_ROOT(&root->inode_tree)); | 2429 | WARN_ON(!RB_EMPTY_ROOT(&root->inode_tree)); |
2435 | if (root->anon_super.s_dev) { | 2430 | if (root->anon_dev) |
2436 | down_write(&root->anon_super.s_umount); | 2431 | free_anon_bdev(root->anon_dev); |
2437 | kill_anon_super(&root->anon_super); | ||
2438 | } | ||
2439 | free_extent_buffer(root->node); | 2432 | free_extent_buffer(root->node); |
2440 | free_extent_buffer(root->commit_root); | 2433 | free_extent_buffer(root->commit_root); |
2441 | kfree(root->free_ino_ctl); | 2434 | kfree(root->free_ino_ctl); |
diff --git a/fs/btrfs/extent-tree.c b/fs/btrfs/extent-tree.c index 80d6148f60ac..f5be06a2462f 100644 --- a/fs/btrfs/extent-tree.c +++ b/fs/btrfs/extent-tree.c | |||
@@ -6735,9 +6735,9 @@ int btrfs_can_relocate(struct btrfs_root *root, u64 bytenr) | |||
6735 | struct btrfs_fs_devices *fs_devices = root->fs_info->fs_devices; | 6735 | struct btrfs_fs_devices *fs_devices = root->fs_info->fs_devices; |
6736 | struct btrfs_device *device; | 6736 | struct btrfs_device *device; |
6737 | u64 min_free; | 6737 | u64 min_free; |
6738 | u64 dev_min = 1; | ||
6739 | u64 dev_nr = 0; | ||
6738 | int index; | 6740 | int index; |
6739 | int dev_nr = 0; | ||
6740 | int dev_min = 1; | ||
6741 | int full = 0; | 6741 | int full = 0; |
6742 | int ret = 0; | 6742 | int ret = 0; |
6743 | 6743 | ||
@@ -6796,14 +6796,16 @@ int btrfs_can_relocate(struct btrfs_root *root, u64 bytenr) | |||
6796 | index = get_block_group_index(block_group); | 6796 | index = get_block_group_index(block_group); |
6797 | if (index == 0) { | 6797 | if (index == 0) { |
6798 | dev_min = 4; | 6798 | dev_min = 4; |
6799 | min_free /= 2; | 6799 | /* Divide by 2 */ |
6800 | min_free >>= 1; | ||
6800 | } else if (index == 1) { | 6801 | } else if (index == 1) { |
6801 | dev_min = 2; | 6802 | dev_min = 2; |
6802 | } else if (index == 2) { | 6803 | } else if (index == 2) { |
6803 | min_free *= 2; | 6804 | /* Multiply by 2 */ |
6805 | min_free <<= 1; | ||
6804 | } else if (index == 3) { | 6806 | } else if (index == 3) { |
6805 | dev_min = fs_devices->rw_devices; | 6807 | dev_min = fs_devices->rw_devices; |
6806 | min_free /= dev_min; | 6808 | do_div(min_free, dev_min); |
6807 | } | 6809 | } |
6808 | 6810 | ||
6809 | mutex_lock(&root->fs_info->chunk_mutex); | 6811 | mutex_lock(&root->fs_info->chunk_mutex); |
diff --git a/fs/btrfs/extent_io.c b/fs/btrfs/extent_io.c index 8491712b1dad..d418164a35f1 100644 --- a/fs/btrfs/extent_io.c +++ b/fs/btrfs/extent_io.c | |||
@@ -2535,7 +2535,6 @@ int extent_write_locked_range(struct extent_io_tree *tree, struct inode *inode, | |||
2535 | }; | 2535 | }; |
2536 | struct writeback_control wbc_writepages = { | 2536 | struct writeback_control wbc_writepages = { |
2537 | .sync_mode = mode, | 2537 | .sync_mode = mode, |
2538 | .older_than_this = NULL, | ||
2539 | .nr_to_write = nr_pages * 2, | 2538 | .nr_to_write = nr_pages * 2, |
2540 | .range_start = start, | 2539 | .range_start = start, |
2541 | .range_end = end + 1, | 2540 | .range_end = end + 1, |
diff --git a/fs/btrfs/file.c b/fs/btrfs/file.c index 98d95bb5f253..3c3abff731a7 100644 --- a/fs/btrfs/file.c +++ b/fs/btrfs/file.c | |||
@@ -1458,7 +1458,7 @@ int btrfs_release_file(struct inode *inode, struct file *filp) | |||
1458 | * important optimization for directories because holding the mutex prevents | 1458 | * important optimization for directories because holding the mutex prevents |
1459 | * new operations on the dir while we write to disk. | 1459 | * new operations on the dir while we write to disk. |
1460 | */ | 1460 | */ |
1461 | int btrfs_sync_file(struct file *file, int datasync) | 1461 | int btrfs_sync_file(struct file *file, loff_t start, loff_t end, int datasync) |
1462 | { | 1462 | { |
1463 | struct dentry *dentry = file->f_path.dentry; | 1463 | struct dentry *dentry = file->f_path.dentry; |
1464 | struct inode *inode = dentry->d_inode; | 1464 | struct inode *inode = dentry->d_inode; |
@@ -1468,9 +1468,13 @@ int btrfs_sync_file(struct file *file, int datasync) | |||
1468 | 1468 | ||
1469 | trace_btrfs_sync_file(file, datasync); | 1469 | trace_btrfs_sync_file(file, datasync); |
1470 | 1470 | ||
1471 | ret = filemap_write_and_wait_range(inode->i_mapping, start, end); | ||
1472 | if (ret) | ||
1473 | return ret; | ||
1474 | mutex_lock(&inode->i_mutex); | ||
1475 | |||
1471 | /* we wait first, since the writeback may change the inode */ | 1476 | /* we wait first, since the writeback may change the inode */ |
1472 | root->log_batch++; | 1477 | root->log_batch++; |
1473 | /* the VFS called filemap_fdatawrite for us */ | ||
1474 | btrfs_wait_ordered_range(inode, 0, (u64)-1); | 1478 | btrfs_wait_ordered_range(inode, 0, (u64)-1); |
1475 | root->log_batch++; | 1479 | root->log_batch++; |
1476 | 1480 | ||
@@ -1478,8 +1482,10 @@ int btrfs_sync_file(struct file *file, int datasync) | |||
1478 | * check the transaction that last modified this inode | 1482 | * check the transaction that last modified this inode |
1479 | * and see if its already been committed | 1483 | * and see if its already been committed |
1480 | */ | 1484 | */ |
1481 | if (!BTRFS_I(inode)->last_trans) | 1485 | if (!BTRFS_I(inode)->last_trans) { |
1486 | mutex_unlock(&inode->i_mutex); | ||
1482 | goto out; | 1487 | goto out; |
1488 | } | ||
1483 | 1489 | ||
1484 | /* | 1490 | /* |
1485 | * if the last transaction that changed this file was before | 1491 | * if the last transaction that changed this file was before |
@@ -1490,6 +1496,7 @@ int btrfs_sync_file(struct file *file, int datasync) | |||
1490 | if (BTRFS_I(inode)->last_trans <= | 1496 | if (BTRFS_I(inode)->last_trans <= |
1491 | root->fs_info->last_trans_committed) { | 1497 | root->fs_info->last_trans_committed) { |
1492 | BTRFS_I(inode)->last_trans = 0; | 1498 | BTRFS_I(inode)->last_trans = 0; |
1499 | mutex_unlock(&inode->i_mutex); | ||
1493 | goto out; | 1500 | goto out; |
1494 | } | 1501 | } |
1495 | 1502 | ||
@@ -1502,12 +1509,15 @@ int btrfs_sync_file(struct file *file, int datasync) | |||
1502 | trans = btrfs_start_transaction(root, 0); | 1509 | trans = btrfs_start_transaction(root, 0); |
1503 | if (IS_ERR(trans)) { | 1510 | if (IS_ERR(trans)) { |
1504 | ret = PTR_ERR(trans); | 1511 | ret = PTR_ERR(trans); |
1512 | mutex_unlock(&inode->i_mutex); | ||
1505 | goto out; | 1513 | goto out; |
1506 | } | 1514 | } |
1507 | 1515 | ||
1508 | ret = btrfs_log_dentry_safe(trans, root, dentry); | 1516 | ret = btrfs_log_dentry_safe(trans, root, dentry); |
1509 | if (ret < 0) | 1517 | if (ret < 0) { |
1518 | mutex_unlock(&inode->i_mutex); | ||
1510 | goto out; | 1519 | goto out; |
1520 | } | ||
1511 | 1521 | ||
1512 | /* we've logged all the items and now have a consistent | 1522 | /* we've logged all the items and now have a consistent |
1513 | * version of the file in the log. It is possible that | 1523 | * version of the file in the log. It is possible that |
@@ -1519,7 +1529,7 @@ int btrfs_sync_file(struct file *file, int datasync) | |||
1519 | * file again, but that will end up using the synchronization | 1529 | * file again, but that will end up using the synchronization |
1520 | * inside btrfs_sync_log to keep things safe. | 1530 | * inside btrfs_sync_log to keep things safe. |
1521 | */ | 1531 | */ |
1522 | mutex_unlock(&dentry->d_inode->i_mutex); | 1532 | mutex_unlock(&inode->i_mutex); |
1523 | 1533 | ||
1524 | if (ret != BTRFS_NO_LOG_SYNC) { | 1534 | if (ret != BTRFS_NO_LOG_SYNC) { |
1525 | if (ret > 0) { | 1535 | if (ret > 0) { |
@@ -1534,7 +1544,6 @@ int btrfs_sync_file(struct file *file, int datasync) | |||
1534 | } else { | 1544 | } else { |
1535 | ret = btrfs_end_transaction(trans, root); | 1545 | ret = btrfs_end_transaction(trans, root); |
1536 | } | 1546 | } |
1537 | mutex_lock(&dentry->d_inode->i_mutex); | ||
1538 | out: | 1547 | out: |
1539 | return ret > 0 ? -EIO : ret; | 1548 | return ret > 0 ? -EIO : ret; |
1540 | } | 1549 | } |
@@ -1684,8 +1693,158 @@ out: | |||
1684 | return ret; | 1693 | return ret; |
1685 | } | 1694 | } |
1686 | 1695 | ||
1696 | static int find_desired_extent(struct inode *inode, loff_t *offset, int origin) | ||
1697 | { | ||
1698 | struct btrfs_root *root = BTRFS_I(inode)->root; | ||
1699 | struct extent_map *em; | ||
1700 | struct extent_state *cached_state = NULL; | ||
1701 | u64 lockstart = *offset; | ||
1702 | u64 lockend = i_size_read(inode); | ||
1703 | u64 start = *offset; | ||
1704 | u64 orig_start = *offset; | ||
1705 | u64 len = i_size_read(inode); | ||
1706 | u64 last_end = 0; | ||
1707 | int ret = 0; | ||
1708 | |||
1709 | lockend = max_t(u64, root->sectorsize, lockend); | ||
1710 | if (lockend <= lockstart) | ||
1711 | lockend = lockstart + root->sectorsize; | ||
1712 | |||
1713 | len = lockend - lockstart + 1; | ||
1714 | |||
1715 | len = max_t(u64, len, root->sectorsize); | ||
1716 | if (inode->i_size == 0) | ||
1717 | return -ENXIO; | ||
1718 | |||
1719 | lock_extent_bits(&BTRFS_I(inode)->io_tree, lockstart, lockend, 0, | ||
1720 | &cached_state, GFP_NOFS); | ||
1721 | |||
1722 | /* | ||
1723 | * Delalloc is such a pain. If we have a hole and we have pending | ||
1724 | * delalloc for a portion of the hole we will get back a hole that | ||
1725 | * exists for the entire range since it hasn't been actually written | ||
1726 | * yet. So to take care of this case we need to look for an extent just | ||
1727 | * before the position we want in case there is outstanding delalloc | ||
1728 | * going on here. | ||
1729 | */ | ||
1730 | if (origin == SEEK_HOLE && start != 0) { | ||
1731 | if (start <= root->sectorsize) | ||
1732 | em = btrfs_get_extent_fiemap(inode, NULL, 0, 0, | ||
1733 | root->sectorsize, 0); | ||
1734 | else | ||
1735 | em = btrfs_get_extent_fiemap(inode, NULL, 0, | ||
1736 | start - root->sectorsize, | ||
1737 | root->sectorsize, 0); | ||
1738 | if (IS_ERR(em)) { | ||
1739 | ret = -ENXIO; | ||
1740 | goto out; | ||
1741 | } | ||
1742 | last_end = em->start + em->len; | ||
1743 | if (em->block_start == EXTENT_MAP_DELALLOC) | ||
1744 | last_end = min_t(u64, last_end, inode->i_size); | ||
1745 | free_extent_map(em); | ||
1746 | } | ||
1747 | |||
1748 | while (1) { | ||
1749 | em = btrfs_get_extent_fiemap(inode, NULL, 0, start, len, 0); | ||
1750 | if (IS_ERR(em)) { | ||
1751 | ret = -ENXIO; | ||
1752 | break; | ||
1753 | } | ||
1754 | |||
1755 | if (em->block_start == EXTENT_MAP_HOLE) { | ||
1756 | if (test_bit(EXTENT_FLAG_VACANCY, &em->flags)) { | ||
1757 | if (last_end <= orig_start) { | ||
1758 | free_extent_map(em); | ||
1759 | ret = -ENXIO; | ||
1760 | break; | ||
1761 | } | ||
1762 | } | ||
1763 | |||
1764 | if (origin == SEEK_HOLE) { | ||
1765 | *offset = start; | ||
1766 | free_extent_map(em); | ||
1767 | break; | ||
1768 | } | ||
1769 | } else { | ||
1770 | if (origin == SEEK_DATA) { | ||
1771 | if (em->block_start == EXTENT_MAP_DELALLOC) { | ||
1772 | if (start >= inode->i_size) { | ||
1773 | free_extent_map(em); | ||
1774 | ret = -ENXIO; | ||
1775 | break; | ||
1776 | } | ||
1777 | } | ||
1778 | |||
1779 | *offset = start; | ||
1780 | free_extent_map(em); | ||
1781 | break; | ||
1782 | } | ||
1783 | } | ||
1784 | |||
1785 | start = em->start + em->len; | ||
1786 | last_end = em->start + em->len; | ||
1787 | |||
1788 | if (em->block_start == EXTENT_MAP_DELALLOC) | ||
1789 | last_end = min_t(u64, last_end, inode->i_size); | ||
1790 | |||
1791 | if (test_bit(EXTENT_FLAG_VACANCY, &em->flags)) { | ||
1792 | free_extent_map(em); | ||
1793 | ret = -ENXIO; | ||
1794 | break; | ||
1795 | } | ||
1796 | free_extent_map(em); | ||
1797 | cond_resched(); | ||
1798 | } | ||
1799 | if (!ret) | ||
1800 | *offset = min(*offset, inode->i_size); | ||
1801 | out: | ||
1802 | unlock_extent_cached(&BTRFS_I(inode)->io_tree, lockstart, lockend, | ||
1803 | &cached_state, GFP_NOFS); | ||
1804 | return ret; | ||
1805 | } | ||
1806 | |||
1807 | static loff_t btrfs_file_llseek(struct file *file, loff_t offset, int origin) | ||
1808 | { | ||
1809 | struct inode *inode = file->f_mapping->host; | ||
1810 | int ret; | ||
1811 | |||
1812 | mutex_lock(&inode->i_mutex); | ||
1813 | switch (origin) { | ||
1814 | case SEEK_END: | ||
1815 | case SEEK_CUR: | ||
1816 | offset = generic_file_llseek_unlocked(file, offset, origin); | ||
1817 | goto out; | ||
1818 | case SEEK_DATA: | ||
1819 | case SEEK_HOLE: | ||
1820 | ret = find_desired_extent(inode, &offset, origin); | ||
1821 | if (ret) { | ||
1822 | mutex_unlock(&inode->i_mutex); | ||
1823 | return ret; | ||
1824 | } | ||
1825 | } | ||
1826 | |||
1827 | if (offset < 0 && !(file->f_mode & FMODE_UNSIGNED_OFFSET)) { | ||
1828 | ret = -EINVAL; | ||
1829 | goto out; | ||
1830 | } | ||
1831 | if (offset > inode->i_sb->s_maxbytes) { | ||
1832 | ret = -EINVAL; | ||
1833 | goto out; | ||
1834 | } | ||
1835 | |||
1836 | /* Special lock needed here? */ | ||
1837 | if (offset != file->f_pos) { | ||
1838 | file->f_pos = offset; | ||
1839 | file->f_version = 0; | ||
1840 | } | ||
1841 | out: | ||
1842 | mutex_unlock(&inode->i_mutex); | ||
1843 | return offset; | ||
1844 | } | ||
1845 | |||
1687 | const struct file_operations btrfs_file_operations = { | 1846 | const struct file_operations btrfs_file_operations = { |
1688 | .llseek = generic_file_llseek, | 1847 | .llseek = btrfs_file_llseek, |
1689 | .read = do_sync_read, | 1848 | .read = do_sync_read, |
1690 | .write = do_sync_write, | 1849 | .write = do_sync_write, |
1691 | .aio_read = generic_file_aio_read, | 1850 | .aio_read = generic_file_aio_read, |
diff --git a/fs/btrfs/inode.c b/fs/btrfs/inode.c index b94c0da3b43f..4d14de6d121b 100644 --- a/fs/btrfs/inode.c +++ b/fs/btrfs/inode.c | |||
@@ -4009,12 +4009,19 @@ struct inode *btrfs_lookup_dentry(struct inode *dir, struct dentry *dentry) | |||
4009 | struct btrfs_root *sub_root = root; | 4009 | struct btrfs_root *sub_root = root; |
4010 | struct btrfs_key location; | 4010 | struct btrfs_key location; |
4011 | int index; | 4011 | int index; |
4012 | int ret; | 4012 | int ret = 0; |
4013 | 4013 | ||
4014 | if (dentry->d_name.len > BTRFS_NAME_LEN) | 4014 | if (dentry->d_name.len > BTRFS_NAME_LEN) |
4015 | return ERR_PTR(-ENAMETOOLONG); | 4015 | return ERR_PTR(-ENAMETOOLONG); |
4016 | 4016 | ||
4017 | ret = btrfs_inode_by_name(dir, dentry, &location); | 4017 | if (unlikely(d_need_lookup(dentry))) { |
4018 | memcpy(&location, dentry->d_fsdata, sizeof(struct btrfs_key)); | ||
4019 | kfree(dentry->d_fsdata); | ||
4020 | dentry->d_fsdata = NULL; | ||
4021 | d_clear_need_lookup(dentry); | ||
4022 | } else { | ||
4023 | ret = btrfs_inode_by_name(dir, dentry, &location); | ||
4024 | } | ||
4018 | 4025 | ||
4019 | if (ret < 0) | 4026 | if (ret < 0) |
4020 | return ERR_PTR(ret); | 4027 | return ERR_PTR(ret); |
@@ -4069,16 +4076,16 @@ static int btrfs_dentry_delete(const struct dentry *dentry) | |||
4069 | return 0; | 4076 | return 0; |
4070 | } | 4077 | } |
4071 | 4078 | ||
4079 | static void btrfs_dentry_release(struct dentry *dentry) | ||
4080 | { | ||
4081 | if (dentry->d_fsdata) | ||
4082 | kfree(dentry->d_fsdata); | ||
4083 | } | ||
4084 | |||
4072 | static struct dentry *btrfs_lookup(struct inode *dir, struct dentry *dentry, | 4085 | static struct dentry *btrfs_lookup(struct inode *dir, struct dentry *dentry, |
4073 | struct nameidata *nd) | 4086 | struct nameidata *nd) |
4074 | { | 4087 | { |
4075 | struct inode *inode; | 4088 | return d_splice_alias(btrfs_lookup_dentry(dir, dentry), dentry); |
4076 | |||
4077 | inode = btrfs_lookup_dentry(dir, dentry); | ||
4078 | if (IS_ERR(inode)) | ||
4079 | return ERR_CAST(inode); | ||
4080 | |||
4081 | return d_splice_alias(inode, dentry); | ||
4082 | } | 4089 | } |
4083 | 4090 | ||
4084 | unsigned char btrfs_filetype_table[] = { | 4091 | unsigned char btrfs_filetype_table[] = { |
@@ -4097,6 +4104,7 @@ static int btrfs_real_readdir(struct file *filp, void *dirent, | |||
4097 | struct btrfs_path *path; | 4104 | struct btrfs_path *path; |
4098 | struct list_head ins_list; | 4105 | struct list_head ins_list; |
4099 | struct list_head del_list; | 4106 | struct list_head del_list; |
4107 | struct qstr q; | ||
4100 | int ret; | 4108 | int ret; |
4101 | struct extent_buffer *leaf; | 4109 | struct extent_buffer *leaf; |
4102 | int slot; | 4110 | int slot; |
@@ -4186,6 +4194,7 @@ static int btrfs_real_readdir(struct file *filp, void *dirent, | |||
4186 | 4194 | ||
4187 | while (di_cur < di_total) { | 4195 | while (di_cur < di_total) { |
4188 | struct btrfs_key location; | 4196 | struct btrfs_key location; |
4197 | struct dentry *tmp; | ||
4189 | 4198 | ||
4190 | if (verify_dir_item(root, leaf, di)) | 4199 | if (verify_dir_item(root, leaf, di)) |
4191 | break; | 4200 | break; |
@@ -4206,6 +4215,33 @@ static int btrfs_real_readdir(struct file *filp, void *dirent, | |||
4206 | d_type = btrfs_filetype_table[btrfs_dir_type(leaf, di)]; | 4215 | d_type = btrfs_filetype_table[btrfs_dir_type(leaf, di)]; |
4207 | btrfs_dir_item_key_to_cpu(leaf, di, &location); | 4216 | btrfs_dir_item_key_to_cpu(leaf, di, &location); |
4208 | 4217 | ||
4218 | q.name = name_ptr; | ||
4219 | q.len = name_len; | ||
4220 | q.hash = full_name_hash(q.name, q.len); | ||
4221 | tmp = d_lookup(filp->f_dentry, &q); | ||
4222 | if (!tmp) { | ||
4223 | struct btrfs_key *newkey; | ||
4224 | |||
4225 | newkey = kzalloc(sizeof(struct btrfs_key), | ||
4226 | GFP_NOFS); | ||
4227 | if (!newkey) | ||
4228 | goto no_dentry; | ||
4229 | tmp = d_alloc(filp->f_dentry, &q); | ||
4230 | if (!tmp) { | ||
4231 | kfree(newkey); | ||
4232 | dput(tmp); | ||
4233 | goto no_dentry; | ||
4234 | } | ||
4235 | memcpy(newkey, &location, | ||
4236 | sizeof(struct btrfs_key)); | ||
4237 | tmp->d_fsdata = newkey; | ||
4238 | tmp->d_flags |= DCACHE_NEED_LOOKUP; | ||
4239 | d_rehash(tmp); | ||
4240 | dput(tmp); | ||
4241 | } else { | ||
4242 | dput(tmp); | ||
4243 | } | ||
4244 | no_dentry: | ||
4209 | /* is this a reference to our own snapshot? If so | 4245 | /* is this a reference to our own snapshot? If so |
4210 | * skip it | 4246 | * skip it |
4211 | */ | 4247 | */ |
@@ -4467,7 +4503,7 @@ static struct inode *btrfs_new_inode(struct btrfs_trans_handle *trans, | |||
4467 | inode->i_generation = BTRFS_I(inode)->generation; | 4503 | inode->i_generation = BTRFS_I(inode)->generation; |
4468 | btrfs_set_inode_space_info(root, inode); | 4504 | btrfs_set_inode_space_info(root, inode); |
4469 | 4505 | ||
4470 | if (mode & S_IFDIR) | 4506 | if (S_ISDIR(mode)) |
4471 | owner = 0; | 4507 | owner = 0; |
4472 | else | 4508 | else |
4473 | owner = 1; | 4509 | owner = 1; |
@@ -4512,7 +4548,7 @@ static struct inode *btrfs_new_inode(struct btrfs_trans_handle *trans, | |||
4512 | 4548 | ||
4513 | btrfs_inherit_iflags(inode, dir); | 4549 | btrfs_inherit_iflags(inode, dir); |
4514 | 4550 | ||
4515 | if ((mode & S_IFREG)) { | 4551 | if (S_ISREG(mode)) { |
4516 | if (btrfs_test_opt(root, NODATASUM)) | 4552 | if (btrfs_test_opt(root, NODATASUM)) |
4517 | BTRFS_I(inode)->flags |= BTRFS_INODE_NODATASUM; | 4553 | BTRFS_I(inode)->flags |= BTRFS_INODE_NODATASUM; |
4518 | if (btrfs_test_opt(root, NODATACOW) || | 4554 | if (btrfs_test_opt(root, NODATACOW) || |
@@ -4766,11 +4802,10 @@ static int btrfs_link(struct dentry *old_dentry, struct inode *dir, | |||
4766 | if (err) { | 4802 | if (err) { |
4767 | drop_inode = 1; | 4803 | drop_inode = 1; |
4768 | } else { | 4804 | } else { |
4769 | struct dentry *parent = dget_parent(dentry); | 4805 | struct dentry *parent = dentry->d_parent; |
4770 | err = btrfs_update_inode(trans, root, inode); | 4806 | err = btrfs_update_inode(trans, root, inode); |
4771 | BUG_ON(err); | 4807 | BUG_ON(err); |
4772 | btrfs_log_new_name(trans, inode, NULL, parent); | 4808 | btrfs_log_new_name(trans, inode, NULL, parent); |
4773 | dput(parent); | ||
4774 | } | 4809 | } |
4775 | 4810 | ||
4776 | nr = trans->blocks_used; | 4811 | nr = trans->blocks_used; |
@@ -6882,7 +6917,7 @@ static int btrfs_getattr(struct vfsmount *mnt, | |||
6882 | { | 6917 | { |
6883 | struct inode *inode = dentry->d_inode; | 6918 | struct inode *inode = dentry->d_inode; |
6884 | generic_fillattr(inode, stat); | 6919 | generic_fillattr(inode, stat); |
6885 | stat->dev = BTRFS_I(inode)->root->anon_super.s_dev; | 6920 | stat->dev = BTRFS_I(inode)->root->anon_dev; |
6886 | stat->blksize = PAGE_CACHE_SIZE; | 6921 | stat->blksize = PAGE_CACHE_SIZE; |
6887 | stat->blocks = (inode_get_bytes(inode) + | 6922 | stat->blocks = (inode_get_bytes(inode) + |
6888 | BTRFS_I(inode)->delalloc_bytes) >> 9; | 6923 | BTRFS_I(inode)->delalloc_bytes) >> 9; |
@@ -7050,9 +7085,8 @@ static int btrfs_rename(struct inode *old_dir, struct dentry *old_dentry, | |||
7050 | BUG_ON(ret); | 7085 | BUG_ON(ret); |
7051 | 7086 | ||
7052 | if (old_ino != BTRFS_FIRST_FREE_OBJECTID) { | 7087 | if (old_ino != BTRFS_FIRST_FREE_OBJECTID) { |
7053 | struct dentry *parent = dget_parent(new_dentry); | 7088 | struct dentry *parent = new_dentry->d_parent; |
7054 | btrfs_log_new_name(trans, old_inode, old_dir, parent); | 7089 | btrfs_log_new_name(trans, old_inode, old_dir, parent); |
7055 | dput(parent); | ||
7056 | btrfs_end_log_trans(root); | 7090 | btrfs_end_log_trans(root); |
7057 | } | 7091 | } |
7058 | out_fail: | 7092 | out_fail: |
@@ -7317,15 +7351,19 @@ static int btrfs_set_page_dirty(struct page *page) | |||
7317 | return __set_page_dirty_nobuffers(page); | 7351 | return __set_page_dirty_nobuffers(page); |
7318 | } | 7352 | } |
7319 | 7353 | ||
7320 | static int btrfs_permission(struct inode *inode, int mask, unsigned int flags) | 7354 | static int btrfs_permission(struct inode *inode, int mask) |
7321 | { | 7355 | { |
7322 | struct btrfs_root *root = BTRFS_I(inode)->root; | 7356 | struct btrfs_root *root = BTRFS_I(inode)->root; |
7357 | umode_t mode = inode->i_mode; | ||
7323 | 7358 | ||
7324 | if (btrfs_root_readonly(root) && (mask & MAY_WRITE)) | 7359 | if (mask & MAY_WRITE && |
7325 | return -EROFS; | 7360 | (S_ISREG(mode) || S_ISDIR(mode) || S_ISLNK(mode))) { |
7326 | if ((BTRFS_I(inode)->flags & BTRFS_INODE_READONLY) && (mask & MAY_WRITE)) | 7361 | if (btrfs_root_readonly(root)) |
7327 | return -EACCES; | 7362 | return -EROFS; |
7328 | return generic_permission(inode, mask, flags, btrfs_check_acl); | 7363 | if (BTRFS_I(inode)->flags & BTRFS_INODE_READONLY) |
7364 | return -EACCES; | ||
7365 | } | ||
7366 | return generic_permission(inode, mask); | ||
7329 | } | 7367 | } |
7330 | 7368 | ||
7331 | static const struct inode_operations btrfs_dir_inode_operations = { | 7369 | static const struct inode_operations btrfs_dir_inode_operations = { |
@@ -7345,10 +7383,12 @@ static const struct inode_operations btrfs_dir_inode_operations = { | |||
7345 | .listxattr = btrfs_listxattr, | 7383 | .listxattr = btrfs_listxattr, |
7346 | .removexattr = btrfs_removexattr, | 7384 | .removexattr = btrfs_removexattr, |
7347 | .permission = btrfs_permission, | 7385 | .permission = btrfs_permission, |
7386 | .get_acl = btrfs_get_acl, | ||
7348 | }; | 7387 | }; |
7349 | static const struct inode_operations btrfs_dir_ro_inode_operations = { | 7388 | static const struct inode_operations btrfs_dir_ro_inode_operations = { |
7350 | .lookup = btrfs_lookup, | 7389 | .lookup = btrfs_lookup, |
7351 | .permission = btrfs_permission, | 7390 | .permission = btrfs_permission, |
7391 | .get_acl = btrfs_get_acl, | ||
7352 | }; | 7392 | }; |
7353 | 7393 | ||
7354 | static const struct file_operations btrfs_dir_file_operations = { | 7394 | static const struct file_operations btrfs_dir_file_operations = { |
@@ -7417,6 +7457,7 @@ static const struct inode_operations btrfs_file_inode_operations = { | |||
7417 | .removexattr = btrfs_removexattr, | 7457 | .removexattr = btrfs_removexattr, |
7418 | .permission = btrfs_permission, | 7458 | .permission = btrfs_permission, |
7419 | .fiemap = btrfs_fiemap, | 7459 | .fiemap = btrfs_fiemap, |
7460 | .get_acl = btrfs_get_acl, | ||
7420 | }; | 7461 | }; |
7421 | static const struct inode_operations btrfs_special_inode_operations = { | 7462 | static const struct inode_operations btrfs_special_inode_operations = { |
7422 | .getattr = btrfs_getattr, | 7463 | .getattr = btrfs_getattr, |
@@ -7426,6 +7467,7 @@ static const struct inode_operations btrfs_special_inode_operations = { | |||
7426 | .getxattr = btrfs_getxattr, | 7467 | .getxattr = btrfs_getxattr, |
7427 | .listxattr = btrfs_listxattr, | 7468 | .listxattr = btrfs_listxattr, |
7428 | .removexattr = btrfs_removexattr, | 7469 | .removexattr = btrfs_removexattr, |
7470 | .get_acl = btrfs_get_acl, | ||
7429 | }; | 7471 | }; |
7430 | static const struct inode_operations btrfs_symlink_inode_operations = { | 7472 | static const struct inode_operations btrfs_symlink_inode_operations = { |
7431 | .readlink = generic_readlink, | 7473 | .readlink = generic_readlink, |
@@ -7437,8 +7479,10 @@ static const struct inode_operations btrfs_symlink_inode_operations = { | |||
7437 | .getxattr = btrfs_getxattr, | 7479 | .getxattr = btrfs_getxattr, |
7438 | .listxattr = btrfs_listxattr, | 7480 | .listxattr = btrfs_listxattr, |
7439 | .removexattr = btrfs_removexattr, | 7481 | .removexattr = btrfs_removexattr, |
7482 | .get_acl = btrfs_get_acl, | ||
7440 | }; | 7483 | }; |
7441 | 7484 | ||
7442 | const struct dentry_operations btrfs_dentry_operations = { | 7485 | const struct dentry_operations btrfs_dentry_operations = { |
7443 | .d_delete = btrfs_dentry_delete, | 7486 | .d_delete = btrfs_dentry_delete, |
7487 | .d_release = btrfs_dentry_release, | ||
7444 | }; | 7488 | }; |
diff --git a/fs/btrfs/ioctl.c b/fs/btrfs/ioctl.c index 63b4de1626d2..3351b1b24574 100644 --- a/fs/btrfs/ioctl.c +++ b/fs/btrfs/ioctl.c | |||
@@ -323,7 +323,7 @@ static noinline int create_subvol(struct btrfs_root *root, | |||
323 | struct btrfs_inode_item *inode_item; | 323 | struct btrfs_inode_item *inode_item; |
324 | struct extent_buffer *leaf; | 324 | struct extent_buffer *leaf; |
325 | struct btrfs_root *new_root; | 325 | struct btrfs_root *new_root; |
326 | struct dentry *parent = dget_parent(dentry); | 326 | struct dentry *parent = dentry->d_parent; |
327 | struct inode *dir; | 327 | struct inode *dir; |
328 | int ret; | 328 | int ret; |
329 | int err; | 329 | int err; |
@@ -332,10 +332,8 @@ static noinline int create_subvol(struct btrfs_root *root, | |||
332 | u64 index = 0; | 332 | u64 index = 0; |
333 | 333 | ||
334 | ret = btrfs_find_free_objectid(root->fs_info->tree_root, &objectid); | 334 | ret = btrfs_find_free_objectid(root->fs_info->tree_root, &objectid); |
335 | if (ret) { | 335 | if (ret) |
336 | dput(parent); | ||
337 | return ret; | 336 | return ret; |
338 | } | ||
339 | 337 | ||
340 | dir = parent->d_inode; | 338 | dir = parent->d_inode; |
341 | 339 | ||
@@ -346,10 +344,8 @@ static noinline int create_subvol(struct btrfs_root *root, | |||
346 | * 2 - dir items | 344 | * 2 - dir items |
347 | */ | 345 | */ |
348 | trans = btrfs_start_transaction(root, 6); | 346 | trans = btrfs_start_transaction(root, 6); |
349 | if (IS_ERR(trans)) { | 347 | if (IS_ERR(trans)) |
350 | dput(parent); | ||
351 | return PTR_ERR(trans); | 348 | return PTR_ERR(trans); |
352 | } | ||
353 | 349 | ||
354 | leaf = btrfs_alloc_free_block(trans, root, root->leafsize, | 350 | leaf = btrfs_alloc_free_block(trans, root, root->leafsize, |
355 | 0, objectid, NULL, 0, 0, 0); | 351 | 0, objectid, NULL, 0, 0, 0); |
@@ -439,7 +435,6 @@ static noinline int create_subvol(struct btrfs_root *root, | |||
439 | 435 | ||
440 | d_instantiate(dentry, btrfs_lookup_dentry(dir, dentry)); | 436 | d_instantiate(dentry, btrfs_lookup_dentry(dir, dentry)); |
441 | fail: | 437 | fail: |
442 | dput(parent); | ||
443 | if (async_transid) { | 438 | if (async_transid) { |
444 | *async_transid = trans->transid; | 439 | *async_transid = trans->transid; |
445 | err = btrfs_commit_transaction_async(trans, root, 1); | 440 | err = btrfs_commit_transaction_async(trans, root, 1); |
@@ -456,7 +451,6 @@ static int create_snapshot(struct btrfs_root *root, struct dentry *dentry, | |||
456 | bool readonly) | 451 | bool readonly) |
457 | { | 452 | { |
458 | struct inode *inode; | 453 | struct inode *inode; |
459 | struct dentry *parent; | ||
460 | struct btrfs_pending_snapshot *pending_snapshot; | 454 | struct btrfs_pending_snapshot *pending_snapshot; |
461 | struct btrfs_trans_handle *trans; | 455 | struct btrfs_trans_handle *trans; |
462 | int ret; | 456 | int ret; |
@@ -504,9 +498,7 @@ static int create_snapshot(struct btrfs_root *root, struct dentry *dentry, | |||
504 | if (ret) | 498 | if (ret) |
505 | goto fail; | 499 | goto fail; |
506 | 500 | ||
507 | parent = dget_parent(dentry); | 501 | inode = btrfs_lookup_dentry(dentry->d_parent->d_inode, dentry); |
508 | inode = btrfs_lookup_dentry(parent->d_inode, dentry); | ||
509 | dput(parent); | ||
510 | if (IS_ERR(inode)) { | 502 | if (IS_ERR(inode)) { |
511 | ret = PTR_ERR(inode); | 503 | ret = PTR_ERR(inode); |
512 | goto fail; | 504 | goto fail; |