diff options
Diffstat (limited to 'fs/btrfs/inode.c')
-rw-r--r-- | fs/btrfs/inode.c | 36 |
1 files changed, 32 insertions, 4 deletions
diff --git a/fs/btrfs/inode.c b/fs/btrfs/inode.c index 06e9a4152b14..5f805bc944fa 100644 --- a/fs/btrfs/inode.c +++ b/fs/btrfs/inode.c | |||
@@ -394,6 +394,14 @@ static noinline int compress_file_range(struct inode *inode, | |||
394 | (start > 0 || end + 1 < BTRFS_I(inode)->disk_i_size)) | 394 | (start > 0 || end + 1 < BTRFS_I(inode)->disk_i_size)) |
395 | btrfs_add_inode_defrag(NULL, inode); | 395 | btrfs_add_inode_defrag(NULL, inode); |
396 | 396 | ||
397 | /* | ||
398 | * skip compression for a small file range(<=blocksize) that | ||
399 | * isn't an inline extent, since it dosen't save disk space at all. | ||
400 | */ | ||
401 | if ((end - start + 1) <= blocksize && | ||
402 | (start > 0 || end + 1 < BTRFS_I(inode)->disk_i_size)) | ||
403 | goto cleanup_and_bail_uncompressed; | ||
404 | |||
397 | actual_end = min_t(u64, isize, end + 1); | 405 | actual_end = min_t(u64, isize, end + 1); |
398 | again: | 406 | again: |
399 | will_compress = 0; | 407 | will_compress = 0; |
@@ -1271,6 +1279,15 @@ next_slot: | |||
1271 | disk_bytenr += cur_offset - found_key.offset; | 1279 | disk_bytenr += cur_offset - found_key.offset; |
1272 | num_bytes = min(end + 1, extent_end) - cur_offset; | 1280 | num_bytes = min(end + 1, extent_end) - cur_offset; |
1273 | /* | 1281 | /* |
1282 | * if there are pending snapshots for this root, | ||
1283 | * we fall into common COW way. | ||
1284 | */ | ||
1285 | if (!nolock) { | ||
1286 | err = btrfs_start_nocow_write(root); | ||
1287 | if (!err) | ||
1288 | goto out_check; | ||
1289 | } | ||
1290 | /* | ||
1274 | * force cow if csum exists in the range. | 1291 | * force cow if csum exists in the range. |
1275 | * this ensure that csum for a given extent are | 1292 | * this ensure that csum for a given extent are |
1276 | * either valid or do not exist. | 1293 | * either valid or do not exist. |
@@ -1289,6 +1306,8 @@ next_slot: | |||
1289 | out_check: | 1306 | out_check: |
1290 | if (extent_end <= start) { | 1307 | if (extent_end <= start) { |
1291 | path->slots[0]++; | 1308 | path->slots[0]++; |
1309 | if (!nolock && nocow) | ||
1310 | btrfs_end_nocow_write(root); | ||
1292 | goto next_slot; | 1311 | goto next_slot; |
1293 | } | 1312 | } |
1294 | if (!nocow) { | 1313 | if (!nocow) { |
@@ -1306,8 +1325,11 @@ out_check: | |||
1306 | ret = cow_file_range(inode, locked_page, | 1325 | ret = cow_file_range(inode, locked_page, |
1307 | cow_start, found_key.offset - 1, | 1326 | cow_start, found_key.offset - 1, |
1308 | page_started, nr_written, 1); | 1327 | page_started, nr_written, 1); |
1309 | if (ret) | 1328 | if (ret) { |
1329 | if (!nolock && nocow) | ||
1330 | btrfs_end_nocow_write(root); | ||
1310 | goto error; | 1331 | goto error; |
1332 | } | ||
1311 | cow_start = (u64)-1; | 1333 | cow_start = (u64)-1; |
1312 | } | 1334 | } |
1313 | 1335 | ||
@@ -1354,8 +1376,11 @@ out_check: | |||
1354 | BTRFS_DATA_RELOC_TREE_OBJECTID) { | 1376 | BTRFS_DATA_RELOC_TREE_OBJECTID) { |
1355 | ret = btrfs_reloc_clone_csums(inode, cur_offset, | 1377 | ret = btrfs_reloc_clone_csums(inode, cur_offset, |
1356 | num_bytes); | 1378 | num_bytes); |
1357 | if (ret) | 1379 | if (ret) { |
1380 | if (!nolock && nocow) | ||
1381 | btrfs_end_nocow_write(root); | ||
1358 | goto error; | 1382 | goto error; |
1383 | } | ||
1359 | } | 1384 | } |
1360 | 1385 | ||
1361 | extent_clear_unlock_delalloc(inode, cur_offset, | 1386 | extent_clear_unlock_delalloc(inode, cur_offset, |
@@ -1363,6 +1388,8 @@ out_check: | |||
1363 | locked_page, EXTENT_LOCKED | | 1388 | locked_page, EXTENT_LOCKED | |
1364 | EXTENT_DELALLOC, PAGE_UNLOCK | | 1389 | EXTENT_DELALLOC, PAGE_UNLOCK | |
1365 | PAGE_SET_PRIVATE2); | 1390 | PAGE_SET_PRIVATE2); |
1391 | if (!nolock && nocow) | ||
1392 | btrfs_end_nocow_write(root); | ||
1366 | cur_offset = extent_end; | 1393 | cur_offset = extent_end; |
1367 | if (cur_offset > end) | 1394 | if (cur_offset > end) |
1368 | break; | 1395 | break; |
@@ -8476,19 +8503,20 @@ static int __start_delalloc_inodes(struct btrfs_root *root, int delay_iput, | |||
8476 | else | 8503 | else |
8477 | iput(inode); | 8504 | iput(inode); |
8478 | ret = -ENOMEM; | 8505 | ret = -ENOMEM; |
8479 | break; | 8506 | goto out; |
8480 | } | 8507 | } |
8481 | list_add_tail(&work->list, &works); | 8508 | list_add_tail(&work->list, &works); |
8482 | btrfs_queue_work(root->fs_info->flush_workers, | 8509 | btrfs_queue_work(root->fs_info->flush_workers, |
8483 | &work->work); | 8510 | &work->work); |
8484 | ret++; | 8511 | ret++; |
8485 | if (nr != -1 && ret >= nr) | 8512 | if (nr != -1 && ret >= nr) |
8486 | break; | 8513 | goto out; |
8487 | cond_resched(); | 8514 | cond_resched(); |
8488 | spin_lock(&root->delalloc_lock); | 8515 | spin_lock(&root->delalloc_lock); |
8489 | } | 8516 | } |
8490 | spin_unlock(&root->delalloc_lock); | 8517 | spin_unlock(&root->delalloc_lock); |
8491 | 8518 | ||
8519 | out: | ||
8492 | list_for_each_entry_safe(work, next, &works, list) { | 8520 | list_for_each_entry_safe(work, next, &works, list) { |
8493 | list_del_init(&work->list); | 8521 | list_del_init(&work->list); |
8494 | btrfs_wait_and_free_delalloc_work(work); | 8522 | btrfs_wait_and_free_delalloc_work(work); |