diff options
Diffstat (limited to 'fs/ocfs2/file.c')
-rw-r--r-- | fs/ocfs2/file.c | 30 |
1 files changed, 27 insertions, 3 deletions
diff --git a/fs/ocfs2/file.c b/fs/ocfs2/file.c index 4c7a4d8ed32c..3346e5b199d5 100644 --- a/fs/ocfs2/file.c +++ b/fs/ocfs2/file.c | |||
@@ -1422,12 +1422,14 @@ static int ocfs2_remove_inode_range(struct inode *inode, | |||
1422 | struct buffer_head *di_bh, u64 byte_start, | 1422 | struct buffer_head *di_bh, u64 byte_start, |
1423 | u64 byte_len) | 1423 | u64 byte_len) |
1424 | { | 1424 | { |
1425 | int ret = 0; | 1425 | int ret = 0, flags = 0; |
1426 | u32 trunc_start, trunc_len, cpos, phys_cpos, alloc_size; | 1426 | u32 trunc_start, trunc_len, cpos, phys_cpos, alloc_size; |
1427 | struct ocfs2_super *osb = OCFS2_SB(inode->i_sb); | 1427 | struct ocfs2_super *osb = OCFS2_SB(inode->i_sb); |
1428 | struct ocfs2_cached_dealloc_ctxt dealloc; | 1428 | struct ocfs2_cached_dealloc_ctxt dealloc; |
1429 | struct address_space *mapping = inode->i_mapping; | 1429 | struct address_space *mapping = inode->i_mapping; |
1430 | struct ocfs2_extent_tree et; | 1430 | struct ocfs2_extent_tree et; |
1431 | struct ocfs2_dinode *di = (struct ocfs2_dinode *)di_bh->b_data; | ||
1432 | u64 refcount_loc = le64_to_cpu(di->i_refcount_loc); | ||
1431 | 1433 | ||
1432 | ocfs2_init_dinode_extent_tree(&et, INODE_CACHE(inode), di_bh); | 1434 | ocfs2_init_dinode_extent_tree(&et, INODE_CACHE(inode), di_bh); |
1433 | ocfs2_init_dealloc_ctxt(&dealloc); | 1435 | ocfs2_init_dealloc_ctxt(&dealloc); |
@@ -1453,6 +1455,27 @@ static int ocfs2_remove_inode_range(struct inode *inode, | |||
1453 | goto out; | 1455 | goto out; |
1454 | } | 1456 | } |
1455 | 1457 | ||
1458 | /* | ||
1459 | * For reflinks, we may need to CoW 2 clusters which might be | ||
1460 | * partially zero'd later, if hole's start and end offset were | ||
1461 | * within one cluster(means is not exactly aligned to clustersize). | ||
1462 | */ | ||
1463 | |||
1464 | if (OCFS2_I(inode)->ip_dyn_features & OCFS2_HAS_REFCOUNT_FL) { | ||
1465 | |||
1466 | ret = ocfs2_cow_file_pos(inode, di_bh, byte_start); | ||
1467 | if (ret) { | ||
1468 | mlog_errno(ret); | ||
1469 | goto out; | ||
1470 | } | ||
1471 | |||
1472 | ret = ocfs2_cow_file_pos(inode, di_bh, byte_start + byte_len); | ||
1473 | if (ret) { | ||
1474 | mlog_errno(ret); | ||
1475 | goto out; | ||
1476 | } | ||
1477 | } | ||
1478 | |||
1456 | trunc_start = ocfs2_clusters_for_bytes(osb->sb, byte_start); | 1479 | trunc_start = ocfs2_clusters_for_bytes(osb->sb, byte_start); |
1457 | trunc_len = (byte_start + byte_len) >> osb->s_clustersize_bits; | 1480 | trunc_len = (byte_start + byte_len) >> osb->s_clustersize_bits; |
1458 | if (trunc_len >= trunc_start) | 1481 | if (trunc_len >= trunc_start) |
@@ -1474,7 +1497,7 @@ static int ocfs2_remove_inode_range(struct inode *inode, | |||
1474 | cpos = trunc_start; | 1497 | cpos = trunc_start; |
1475 | while (trunc_len) { | 1498 | while (trunc_len) { |
1476 | ret = ocfs2_get_clusters(inode, cpos, &phys_cpos, | 1499 | ret = ocfs2_get_clusters(inode, cpos, &phys_cpos, |
1477 | &alloc_size, NULL); | 1500 | &alloc_size, &flags); |
1478 | if (ret) { | 1501 | if (ret) { |
1479 | mlog_errno(ret); | 1502 | mlog_errno(ret); |
1480 | goto out; | 1503 | goto out; |
@@ -1487,7 +1510,8 @@ static int ocfs2_remove_inode_range(struct inode *inode, | |||
1487 | if (phys_cpos != 0) { | 1510 | if (phys_cpos != 0) { |
1488 | ret = ocfs2_remove_btree_range(inode, &et, cpos, | 1511 | ret = ocfs2_remove_btree_range(inode, &et, cpos, |
1489 | phys_cpos, alloc_size, | 1512 | phys_cpos, alloc_size, |
1490 | 0, &dealloc, 0); | 1513 | flags, &dealloc, |
1514 | refcount_loc); | ||
1491 | if (ret) { | 1515 | if (ret) { |
1492 | mlog_errno(ret); | 1516 | mlog_errno(ret); |
1493 | goto out; | 1517 | goto out; |