diff options
Diffstat (limited to 'fs/btrfs/inode.c')
| -rw-r--r-- | fs/btrfs/inode.c | 73 |
1 files changed, 58 insertions, 15 deletions
diff --git a/fs/btrfs/inode.c b/fs/btrfs/inode.c index f6ab6f5e635a..d8bb0dbc4941 100644 --- a/fs/btrfs/inode.c +++ b/fs/btrfs/inode.c | |||
| @@ -830,7 +830,7 @@ static noinline int cow_file_range(struct inode *inode, | |||
| 830 | if (IS_ERR(trans)) { | 830 | if (IS_ERR(trans)) { |
| 831 | extent_clear_unlock_delalloc(inode, | 831 | extent_clear_unlock_delalloc(inode, |
| 832 | &BTRFS_I(inode)->io_tree, | 832 | &BTRFS_I(inode)->io_tree, |
| 833 | start, end, NULL, | 833 | start, end, locked_page, |
| 834 | EXTENT_CLEAR_UNLOCK_PAGE | | 834 | EXTENT_CLEAR_UNLOCK_PAGE | |
| 835 | EXTENT_CLEAR_UNLOCK | | 835 | EXTENT_CLEAR_UNLOCK | |
| 836 | EXTENT_CLEAR_DELALLOC | | 836 | EXTENT_CLEAR_DELALLOC | |
| @@ -963,7 +963,7 @@ out: | |||
| 963 | out_unlock: | 963 | out_unlock: |
| 964 | extent_clear_unlock_delalloc(inode, | 964 | extent_clear_unlock_delalloc(inode, |
| 965 | &BTRFS_I(inode)->io_tree, | 965 | &BTRFS_I(inode)->io_tree, |
| 966 | start, end, NULL, | 966 | start, end, locked_page, |
| 967 | EXTENT_CLEAR_UNLOCK_PAGE | | 967 | EXTENT_CLEAR_UNLOCK_PAGE | |
| 968 | EXTENT_CLEAR_UNLOCK | | 968 | EXTENT_CLEAR_UNLOCK | |
| 969 | EXTENT_CLEAR_DELALLOC | | 969 | EXTENT_CLEAR_DELALLOC | |
| @@ -986,8 +986,10 @@ static noinline void async_cow_start(struct btrfs_work *work) | |||
| 986 | compress_file_range(async_cow->inode, async_cow->locked_page, | 986 | compress_file_range(async_cow->inode, async_cow->locked_page, |
| 987 | async_cow->start, async_cow->end, async_cow, | 987 | async_cow->start, async_cow->end, async_cow, |
| 988 | &num_added); | 988 | &num_added); |
| 989 | if (num_added == 0) | 989 | if (num_added == 0) { |
| 990 | btrfs_add_delayed_iput(async_cow->inode); | ||
| 990 | async_cow->inode = NULL; | 991 | async_cow->inode = NULL; |
| 992 | } | ||
| 991 | } | 993 | } |
| 992 | 994 | ||
| 993 | /* | 995 | /* |
| @@ -1020,6 +1022,8 @@ static noinline void async_cow_free(struct btrfs_work *work) | |||
| 1020 | { | 1022 | { |
| 1021 | struct async_cow *async_cow; | 1023 | struct async_cow *async_cow; |
| 1022 | async_cow = container_of(work, struct async_cow, work); | 1024 | async_cow = container_of(work, struct async_cow, work); |
| 1025 | if (async_cow->inode) | ||
| 1026 | btrfs_add_delayed_iput(async_cow->inode); | ||
| 1023 | kfree(async_cow); | 1027 | kfree(async_cow); |
| 1024 | } | 1028 | } |
| 1025 | 1029 | ||
| @@ -1038,7 +1042,7 @@ static int cow_file_range_async(struct inode *inode, struct page *locked_page, | |||
| 1038 | while (start < end) { | 1042 | while (start < end) { |
| 1039 | async_cow = kmalloc(sizeof(*async_cow), GFP_NOFS); | 1043 | async_cow = kmalloc(sizeof(*async_cow), GFP_NOFS); |
| 1040 | BUG_ON(!async_cow); /* -ENOMEM */ | 1044 | BUG_ON(!async_cow); /* -ENOMEM */ |
| 1041 | async_cow->inode = inode; | 1045 | async_cow->inode = igrab(inode); |
| 1042 | async_cow->root = root; | 1046 | async_cow->root = root; |
| 1043 | async_cow->locked_page = locked_page; | 1047 | async_cow->locked_page = locked_page; |
| 1044 | async_cow->start = start; | 1048 | async_cow->start = start; |
| @@ -1136,8 +1140,18 @@ static noinline int run_delalloc_nocow(struct inode *inode, | |||
| 1136 | u64 ino = btrfs_ino(inode); | 1140 | u64 ino = btrfs_ino(inode); |
| 1137 | 1141 | ||
| 1138 | path = btrfs_alloc_path(); | 1142 | path = btrfs_alloc_path(); |
| 1139 | if (!path) | 1143 | if (!path) { |
| 1144 | extent_clear_unlock_delalloc(inode, | ||
| 1145 | &BTRFS_I(inode)->io_tree, | ||
| 1146 | start, end, locked_page, | ||
| 1147 | EXTENT_CLEAR_UNLOCK_PAGE | | ||
| 1148 | EXTENT_CLEAR_UNLOCK | | ||
| 1149 | EXTENT_CLEAR_DELALLOC | | ||
| 1150 | EXTENT_CLEAR_DIRTY | | ||
| 1151 | EXTENT_SET_WRITEBACK | | ||
| 1152 | EXTENT_END_WRITEBACK); | ||
| 1140 | return -ENOMEM; | 1153 | return -ENOMEM; |
| 1154 | } | ||
| 1141 | 1155 | ||
| 1142 | nolock = btrfs_is_free_space_inode(root, inode); | 1156 | nolock = btrfs_is_free_space_inode(root, inode); |
| 1143 | 1157 | ||
| @@ -1147,6 +1161,15 @@ static noinline int run_delalloc_nocow(struct inode *inode, | |||
| 1147 | trans = btrfs_join_transaction(root); | 1161 | trans = btrfs_join_transaction(root); |
| 1148 | 1162 | ||
| 1149 | if (IS_ERR(trans)) { | 1163 | if (IS_ERR(trans)) { |
| 1164 | extent_clear_unlock_delalloc(inode, | ||
| 1165 | &BTRFS_I(inode)->io_tree, | ||
| 1166 | start, end, locked_page, | ||
| 1167 | EXTENT_CLEAR_UNLOCK_PAGE | | ||
| 1168 | EXTENT_CLEAR_UNLOCK | | ||
| 1169 | EXTENT_CLEAR_DELALLOC | | ||
| 1170 | EXTENT_CLEAR_DIRTY | | ||
| 1171 | EXTENT_SET_WRITEBACK | | ||
| 1172 | EXTENT_END_WRITEBACK); | ||
| 1150 | btrfs_free_path(path); | 1173 | btrfs_free_path(path); |
| 1151 | return PTR_ERR(trans); | 1174 | return PTR_ERR(trans); |
| 1152 | } | 1175 | } |
| @@ -1327,8 +1350,11 @@ out_check: | |||
| 1327 | } | 1350 | } |
| 1328 | btrfs_release_path(path); | 1351 | btrfs_release_path(path); |
| 1329 | 1352 | ||
| 1330 | if (cur_offset <= end && cow_start == (u64)-1) | 1353 | if (cur_offset <= end && cow_start == (u64)-1) { |
| 1331 | cow_start = cur_offset; | 1354 | cow_start = cur_offset; |
| 1355 | cur_offset = end; | ||
| 1356 | } | ||
| 1357 | |||
| 1332 | if (cow_start != (u64)-1) { | 1358 | if (cow_start != (u64)-1) { |
| 1333 | ret = cow_file_range(inode, locked_page, cow_start, end, | 1359 | ret = cow_file_range(inode, locked_page, cow_start, end, |
| 1334 | page_started, nr_written, 1); | 1360 | page_started, nr_written, 1); |
| @@ -1347,6 +1373,17 @@ error: | |||
| 1347 | if (!ret) | 1373 | if (!ret) |
| 1348 | ret = err; | 1374 | ret = err; |
| 1349 | 1375 | ||
| 1376 | if (ret && cur_offset < end) | ||
| 1377 | extent_clear_unlock_delalloc(inode, | ||
| 1378 | &BTRFS_I(inode)->io_tree, | ||
| 1379 | cur_offset, end, locked_page, | ||
| 1380 | EXTENT_CLEAR_UNLOCK_PAGE | | ||
| 1381 | EXTENT_CLEAR_UNLOCK | | ||
| 1382 | EXTENT_CLEAR_DELALLOC | | ||
| 1383 | EXTENT_CLEAR_DIRTY | | ||
| 1384 | EXTENT_SET_WRITEBACK | | ||
| 1385 | EXTENT_END_WRITEBACK); | ||
| 1386 | |||
| 1350 | btrfs_free_path(path); | 1387 | btrfs_free_path(path); |
| 1351 | return ret; | 1388 | return ret; |
| 1352 | } | 1389 | } |
| @@ -1361,20 +1398,23 @@ static int run_delalloc_range(struct inode *inode, struct page *locked_page, | |||
| 1361 | int ret; | 1398 | int ret; |
| 1362 | struct btrfs_root *root = BTRFS_I(inode)->root; | 1399 | struct btrfs_root *root = BTRFS_I(inode)->root; |
| 1363 | 1400 | ||
| 1364 | if (BTRFS_I(inode)->flags & BTRFS_INODE_NODATACOW) | 1401 | if (BTRFS_I(inode)->flags & BTRFS_INODE_NODATACOW) { |
| 1365 | ret = run_delalloc_nocow(inode, locked_page, start, end, | 1402 | ret = run_delalloc_nocow(inode, locked_page, start, end, |
| 1366 | page_started, 1, nr_written); | 1403 | page_started, 1, nr_written); |
| 1367 | else if (BTRFS_I(inode)->flags & BTRFS_INODE_PREALLOC) | 1404 | } else if (BTRFS_I(inode)->flags & BTRFS_INODE_PREALLOC) { |
| 1368 | ret = run_delalloc_nocow(inode, locked_page, start, end, | 1405 | ret = run_delalloc_nocow(inode, locked_page, start, end, |
| 1369 | page_started, 0, nr_written); | 1406 | page_started, 0, nr_written); |
| 1370 | else if (!btrfs_test_opt(root, COMPRESS) && | 1407 | } else if (!btrfs_test_opt(root, COMPRESS) && |
| 1371 | !(BTRFS_I(inode)->force_compress) && | 1408 | !(BTRFS_I(inode)->force_compress) && |
| 1372 | !(BTRFS_I(inode)->flags & BTRFS_INODE_COMPRESS)) | 1409 | !(BTRFS_I(inode)->flags & BTRFS_INODE_COMPRESS)) { |
| 1373 | ret = cow_file_range(inode, locked_page, start, end, | 1410 | ret = cow_file_range(inode, locked_page, start, end, |
| 1374 | page_started, nr_written, 1); | 1411 | page_started, nr_written, 1); |
| 1375 | else | 1412 | } else { |
| 1413 | set_bit(BTRFS_INODE_HAS_ASYNC_EXTENT, | ||
| 1414 | &BTRFS_I(inode)->runtime_flags); | ||
| 1376 | ret = cow_file_range_async(inode, locked_page, start, end, | 1415 | ret = cow_file_range_async(inode, locked_page, start, end, |
| 1377 | page_started, nr_written); | 1416 | page_started, nr_written); |
| 1417 | } | ||
| 1378 | return ret; | 1418 | return ret; |
| 1379 | } | 1419 | } |
| 1380 | 1420 | ||
| @@ -7054,10 +7094,13 @@ static void fixup_inode_flags(struct inode *dir, struct inode *inode) | |||
| 7054 | else | 7094 | else |
| 7055 | b_inode->flags &= ~BTRFS_INODE_NODATACOW; | 7095 | b_inode->flags &= ~BTRFS_INODE_NODATACOW; |
| 7056 | 7096 | ||
| 7057 | if (b_dir->flags & BTRFS_INODE_COMPRESS) | 7097 | if (b_dir->flags & BTRFS_INODE_COMPRESS) { |
| 7058 | b_inode->flags |= BTRFS_INODE_COMPRESS; | 7098 | b_inode->flags |= BTRFS_INODE_COMPRESS; |
| 7059 | else | 7099 | b_inode->flags &= ~BTRFS_INODE_NOCOMPRESS; |
| 7060 | b_inode->flags &= ~BTRFS_INODE_COMPRESS; | 7100 | } else { |
| 7101 | b_inode->flags &= ~(BTRFS_INODE_COMPRESS | | ||
| 7102 | BTRFS_INODE_NOCOMPRESS); | ||
| 7103 | } | ||
| 7061 | } | 7104 | } |
| 7062 | 7105 | ||
| 7063 | static int btrfs_rename(struct inode *old_dir, struct dentry *old_dentry, | 7106 | static int btrfs_rename(struct inode *old_dir, struct dentry *old_dentry, |
