aboutsummaryrefslogtreecommitdiffstats
path: root/fs/ocfs2/file.c
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2010-05-21 10:20:17 -0400
committerLinus Torvalds <torvalds@linux-foundation.org>2010-05-21 10:20:17 -0400
commit03e62303cf56e87337115f14842321043df2b4bb (patch)
tree3024495955beccddbae347d99613bcdd33801ee4 /fs/ocfs2/file.c
parent33cf23b0a535475aead57707cb9f4fe135a93544 (diff)
parent18d3a98f3c1b0e27ce026afa4d1ef042f2903726 (diff)
Merge branch 'upstream-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/jlbec/ocfs2
* 'upstream-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/jlbec/ocfs2: (47 commits) ocfs2: Silence a gcc warning. ocfs2: Don't retry xattr set in case value extension fails. ocfs2:dlm: avoid dlm->ast_lock lockres->spinlock dependency break ocfs2: Reset xattr value size after xa_cleanup_value_truncate(). fs/ocfs2/dlm: Use kstrdup fs/ocfs2/dlm: Drop memory allocation cast Ocfs2: Optimize punching-hole code. Ocfs2: Make ocfs2_find_cpos_for_left_leaf() public. Ocfs2: Fix hole punching to correctly do CoW during cluster zeroing. Ocfs2: Optimize ocfs2 truncate to use ocfs2_remove_btree_range() instead. ocfs2: Block signals for mkdir/link/symlink/O_CREAT. ocfs2: Wrap signal blocking in void functions. ocfs2/dlm: Increase o2dlm lockres hash size ocfs2: Make ocfs2_extend_trans() really extend. ocfs2/trivial: Code cleanup for allocation reservation. ocfs2: make ocfs2_adjust_resv_from_alloc simple. ocfs2: Make nointr a default mount option ocfs2/dlm: Make o2dlm domain join/leave messages KERN_NOTICE o2net: log socket state changes ocfs2: print node # when tcp fails ...
Diffstat (limited to 'fs/ocfs2/file.c')
-rw-r--r--fs/ocfs2/file.c215
1 files changed, 170 insertions, 45 deletions
diff --git a/fs/ocfs2/file.c b/fs/ocfs2/file.c
index a5fbd9cea968..f74f1400eccd 100644
--- a/fs/ocfs2/file.c
+++ b/fs/ocfs2/file.c
@@ -278,10 +278,7 @@ int ocfs2_update_inode_atime(struct inode *inode,
278 inode->i_atime = CURRENT_TIME; 278 inode->i_atime = CURRENT_TIME;
279 di->i_atime = cpu_to_le64(inode->i_atime.tv_sec); 279 di->i_atime = cpu_to_le64(inode->i_atime.tv_sec);
280 di->i_atime_nsec = cpu_to_le32(inode->i_atime.tv_nsec); 280 di->i_atime_nsec = cpu_to_le32(inode->i_atime.tv_nsec);
281 281 ocfs2_journal_dirty(handle, bh);
282 ret = ocfs2_journal_dirty(handle, bh);
283 if (ret < 0)
284 mlog_errno(ret);
285 282
286out_commit: 283out_commit:
287 ocfs2_commit_trans(OCFS2_SB(inode->i_sb), handle); 284 ocfs2_commit_trans(OCFS2_SB(inode->i_sb), handle);
@@ -430,9 +427,7 @@ static int ocfs2_orphan_for_truncate(struct ocfs2_super *osb,
430 di->i_ctime = di->i_mtime = cpu_to_le64(inode->i_ctime.tv_sec); 427 di->i_ctime = di->i_mtime = cpu_to_le64(inode->i_ctime.tv_sec);
431 di->i_ctime_nsec = di->i_mtime_nsec = cpu_to_le32(inode->i_ctime.tv_nsec); 428 di->i_ctime_nsec = di->i_mtime_nsec = cpu_to_le32(inode->i_ctime.tv_nsec);
432 429
433 status = ocfs2_journal_dirty(handle, fe_bh); 430 ocfs2_journal_dirty(handle, fe_bh);
434 if (status < 0)
435 mlog_errno(status);
436 431
437out_commit: 432out_commit:
438 ocfs2_commit_trans(osb, handle); 433 ocfs2_commit_trans(osb, handle);
@@ -449,7 +444,6 @@ static int ocfs2_truncate_file(struct inode *inode,
449 int status = 0; 444 int status = 0;
450 struct ocfs2_dinode *fe = NULL; 445 struct ocfs2_dinode *fe = NULL;
451 struct ocfs2_super *osb = OCFS2_SB(inode->i_sb); 446 struct ocfs2_super *osb = OCFS2_SB(inode->i_sb);
452 struct ocfs2_truncate_context *tc = NULL;
453 447
454 mlog_entry("(inode = %llu, new_i_size = %llu\n", 448 mlog_entry("(inode = %llu, new_i_size = %llu\n",
455 (unsigned long long)OCFS2_I(inode)->ip_blkno, 449 (unsigned long long)OCFS2_I(inode)->ip_blkno,
@@ -488,6 +482,9 @@ static int ocfs2_truncate_file(struct inode *inode,
488 482
489 down_write(&OCFS2_I(inode)->ip_alloc_sem); 483 down_write(&OCFS2_I(inode)->ip_alloc_sem);
490 484
485 ocfs2_resv_discard(&osb->osb_la_resmap,
486 &OCFS2_I(inode)->ip_la_data_resv);
487
491 /* 488 /*
492 * The inode lock forced other nodes to sync and drop their 489 * The inode lock forced other nodes to sync and drop their
493 * pages, which (correctly) happens even if we have a truncate 490 * pages, which (correctly) happens even if we have a truncate
@@ -517,13 +514,7 @@ static int ocfs2_truncate_file(struct inode *inode,
517 goto bail_unlock_sem; 514 goto bail_unlock_sem;
518 } 515 }
519 516
520 status = ocfs2_prepare_truncate(osb, inode, di_bh, &tc); 517 status = ocfs2_commit_truncate(osb, inode, di_bh);
521 if (status < 0) {
522 mlog_errno(status);
523 goto bail_unlock_sem;
524 }
525
526 status = ocfs2_commit_truncate(osb, inode, di_bh, tc);
527 if (status < 0) { 518 if (status < 0) {
528 mlog_errno(status); 519 mlog_errno(status);
529 goto bail_unlock_sem; 520 goto bail_unlock_sem;
@@ -666,11 +657,7 @@ restarted_transaction:
666 goto leave; 657 goto leave;
667 } 658 }
668 659
669 status = ocfs2_journal_dirty(handle, bh); 660 ocfs2_journal_dirty(handle, bh);
670 if (status < 0) {
671 mlog_errno(status);
672 goto leave;
673 }
674 661
675 spin_lock(&OCFS2_I(inode)->ip_lock); 662 spin_lock(&OCFS2_I(inode)->ip_lock);
676 clusters_to_add -= (OCFS2_I(inode)->ip_clusters - prev_clusters); 663 clusters_to_add -= (OCFS2_I(inode)->ip_clusters - prev_clusters);
@@ -1195,9 +1182,7 @@ static int __ocfs2_write_remove_suid(struct inode *inode,
1195 di = (struct ocfs2_dinode *) bh->b_data; 1182 di = (struct ocfs2_dinode *) bh->b_data;
1196 di->i_mode = cpu_to_le16(inode->i_mode); 1183 di->i_mode = cpu_to_le16(inode->i_mode);
1197 1184
1198 ret = ocfs2_journal_dirty(handle, bh); 1185 ocfs2_journal_dirty(handle, bh);
1199 if (ret < 0)
1200 mlog_errno(ret);
1201 1186
1202out_trans: 1187out_trans:
1203 ocfs2_commit_trans(osb, handle); 1188 ocfs2_commit_trans(osb, handle);
@@ -1434,16 +1419,90 @@ out:
1434 return ret; 1419 return ret;
1435} 1420}
1436 1421
1422static int ocfs2_find_rec(struct ocfs2_extent_list *el, u32 pos)
1423{
1424 int i;
1425 struct ocfs2_extent_rec *rec = NULL;
1426
1427 for (i = le16_to_cpu(el->l_next_free_rec) - 1; i >= 0; i--) {
1428
1429 rec = &el->l_recs[i];
1430
1431 if (le32_to_cpu(rec->e_cpos) < pos)
1432 break;
1433 }
1434
1435 return i;
1436}
1437
1438/*
1439 * Helper to calculate the punching pos and length in one run, we handle the
1440 * following three cases in order:
1441 *
1442 * - remove the entire record
1443 * - remove a partial record
1444 * - no record needs to be removed (hole-punching completed)
1445*/
1446static void ocfs2_calc_trunc_pos(struct inode *inode,
1447 struct ocfs2_extent_list *el,
1448 struct ocfs2_extent_rec *rec,
1449 u32 trunc_start, u32 *trunc_cpos,
1450 u32 *trunc_len, u32 *trunc_end,
1451 u64 *blkno, int *done)
1452{
1453 int ret = 0;
1454 u32 coff, range;
1455
1456 range = le32_to_cpu(rec->e_cpos) + ocfs2_rec_clusters(el, rec);
1457
1458 if (le32_to_cpu(rec->e_cpos) >= trunc_start) {
1459 *trunc_cpos = le32_to_cpu(rec->e_cpos);
1460 /*
1461 * Skip holes if any.
1462 */
1463 if (range < *trunc_end)
1464 *trunc_end = range;
1465 *trunc_len = *trunc_end - le32_to_cpu(rec->e_cpos);
1466 *blkno = le64_to_cpu(rec->e_blkno);
1467 *trunc_end = le32_to_cpu(rec->e_cpos);
1468 } else if (range > trunc_start) {
1469 *trunc_cpos = trunc_start;
1470 *trunc_len = *trunc_end - trunc_start;
1471 coff = trunc_start - le32_to_cpu(rec->e_cpos);
1472 *blkno = le64_to_cpu(rec->e_blkno) +
1473 ocfs2_clusters_to_blocks(inode->i_sb, coff);
1474 *trunc_end = trunc_start;
1475 } else {
1476 /*
1477 * It may have two following possibilities:
1478 *
1479 * - last record has been removed
1480 * - trunc_start was within a hole
1481 *
1482 * both two cases mean the completion of hole punching.
1483 */
1484 ret = 1;
1485 }
1486
1487 *done = ret;
1488}
1489
1437static int ocfs2_remove_inode_range(struct inode *inode, 1490static int ocfs2_remove_inode_range(struct inode *inode,
1438 struct buffer_head *di_bh, u64 byte_start, 1491 struct buffer_head *di_bh, u64 byte_start,
1439 u64 byte_len) 1492 u64 byte_len)
1440{ 1493{
1441 int ret = 0; 1494 int ret = 0, flags = 0, done = 0, i;
1442 u32 trunc_start, trunc_len, cpos, phys_cpos, alloc_size; 1495 u32 trunc_start, trunc_len, trunc_end, trunc_cpos, phys_cpos;
1496 u32 cluster_in_el;
1443 struct ocfs2_super *osb = OCFS2_SB(inode->i_sb); 1497 struct ocfs2_super *osb = OCFS2_SB(inode->i_sb);
1444 struct ocfs2_cached_dealloc_ctxt dealloc; 1498 struct ocfs2_cached_dealloc_ctxt dealloc;
1445 struct address_space *mapping = inode->i_mapping; 1499 struct address_space *mapping = inode->i_mapping;
1446 struct ocfs2_extent_tree et; 1500 struct ocfs2_extent_tree et;
1501 struct ocfs2_path *path = NULL;
1502 struct ocfs2_extent_list *el = NULL;
1503 struct ocfs2_extent_rec *rec = NULL;
1504 struct ocfs2_dinode *di = (struct ocfs2_dinode *)di_bh->b_data;
1505 u64 blkno, refcount_loc = le64_to_cpu(di->i_refcount_loc);
1447 1506
1448 ocfs2_init_dinode_extent_tree(&et, INODE_CACHE(inode), di_bh); 1507 ocfs2_init_dinode_extent_tree(&et, INODE_CACHE(inode), di_bh);
1449 ocfs2_init_dealloc_ctxt(&dealloc); 1508 ocfs2_init_dealloc_ctxt(&dealloc);
@@ -1469,17 +1528,35 @@ static int ocfs2_remove_inode_range(struct inode *inode,
1469 goto out; 1528 goto out;
1470 } 1529 }
1471 1530
1531 /*
1532 * For reflinks, we may need to CoW 2 clusters which might be
1533 * partially zero'd later, if hole's start and end offset were
1534 * within one cluster(means is not exactly aligned to clustersize).
1535 */
1536
1537 if (OCFS2_I(inode)->ip_dyn_features & OCFS2_HAS_REFCOUNT_FL) {
1538
1539 ret = ocfs2_cow_file_pos(inode, di_bh, byte_start);
1540 if (ret) {
1541 mlog_errno(ret);
1542 goto out;
1543 }
1544
1545 ret = ocfs2_cow_file_pos(inode, di_bh, byte_start + byte_len);
1546 if (ret) {
1547 mlog_errno(ret);
1548 goto out;
1549 }
1550 }
1551
1472 trunc_start = ocfs2_clusters_for_bytes(osb->sb, byte_start); 1552 trunc_start = ocfs2_clusters_for_bytes(osb->sb, byte_start);
1473 trunc_len = (byte_start + byte_len) >> osb->s_clustersize_bits; 1553 trunc_end = (byte_start + byte_len) >> osb->s_clustersize_bits;
1474 if (trunc_len >= trunc_start) 1554 cluster_in_el = trunc_end;
1475 trunc_len -= trunc_start;
1476 else
1477 trunc_len = 0;
1478 1555
1479 mlog(0, "Inode: %llu, start: %llu, len: %llu, cstart: %u, clen: %u\n", 1556 mlog(0, "Inode: %llu, start: %llu, len: %llu, cstart: %u, cend: %u\n",
1480 (unsigned long long)OCFS2_I(inode)->ip_blkno, 1557 (unsigned long long)OCFS2_I(inode)->ip_blkno,
1481 (unsigned long long)byte_start, 1558 (unsigned long long)byte_start,
1482 (unsigned long long)byte_len, trunc_start, trunc_len); 1559 (unsigned long long)byte_len, trunc_start, trunc_end);
1483 1560
1484 ret = ocfs2_zero_partial_clusters(inode, byte_start, byte_len); 1561 ret = ocfs2_zero_partial_clusters(inode, byte_start, byte_len);
1485 if (ret) { 1562 if (ret) {
@@ -1487,31 +1564,79 @@ static int ocfs2_remove_inode_range(struct inode *inode,
1487 goto out; 1564 goto out;
1488 } 1565 }
1489 1566
1490 cpos = trunc_start; 1567 path = ocfs2_new_path_from_et(&et);
1491 while (trunc_len) { 1568 if (!path) {
1492 ret = ocfs2_get_clusters(inode, cpos, &phys_cpos, 1569 ret = -ENOMEM;
1493 &alloc_size, NULL); 1570 mlog_errno(ret);
1571 goto out;
1572 }
1573
1574 while (trunc_end > trunc_start) {
1575
1576 ret = ocfs2_find_path(INODE_CACHE(inode), path,
1577 cluster_in_el);
1494 if (ret) { 1578 if (ret) {
1495 mlog_errno(ret); 1579 mlog_errno(ret);
1496 goto out; 1580 goto out;
1497 } 1581 }
1498 1582
1499 if (alloc_size > trunc_len) 1583 el = path_leaf_el(path);
1500 alloc_size = trunc_len;
1501 1584
1502 /* Only do work for non-holes */ 1585 i = ocfs2_find_rec(el, trunc_end);
1503 if (phys_cpos != 0) { 1586 /*
1504 ret = ocfs2_remove_btree_range(inode, &et, cpos, 1587 * Need to go to previous extent block.
1505 phys_cpos, alloc_size, 1588 */
1506 &dealloc); 1589 if (i < 0) {
1590 if (path->p_tree_depth == 0)
1591 break;
1592
1593 ret = ocfs2_find_cpos_for_left_leaf(inode->i_sb,
1594 path,
1595 &cluster_in_el);
1507 if (ret) { 1596 if (ret) {
1508 mlog_errno(ret); 1597 mlog_errno(ret);
1509 goto out; 1598 goto out;
1510 } 1599 }
1600
1601 /*
1602 * We've reached the leftmost extent block,
1603 * it's safe to leave.
1604 */
1605 if (cluster_in_el == 0)
1606 break;
1607
1608 /*
1609 * The 'pos' searched for previous extent block is
1610 * always one cluster less than actual trunc_end.
1611 */
1612 trunc_end = cluster_in_el + 1;
1613
1614 ocfs2_reinit_path(path, 1);
1615
1616 continue;
1617
1618 } else
1619 rec = &el->l_recs[i];
1620
1621 ocfs2_calc_trunc_pos(inode, el, rec, trunc_start, &trunc_cpos,
1622 &trunc_len, &trunc_end, &blkno, &done);
1623 if (done)
1624 break;
1625
1626 flags = rec->e_flags;
1627 phys_cpos = ocfs2_blocks_to_clusters(inode->i_sb, blkno);
1628
1629 ret = ocfs2_remove_btree_range(inode, &et, trunc_cpos,
1630 phys_cpos, trunc_len, flags,
1631 &dealloc, refcount_loc);
1632 if (ret < 0) {
1633 mlog_errno(ret);
1634 goto out;
1511 } 1635 }
1512 1636
1513 cpos += alloc_size; 1637 cluster_in_el = trunc_end;
1514 trunc_len -= alloc_size; 1638
1639 ocfs2_reinit_path(path, 1);
1515 } 1640 }
1516 1641
1517 ocfs2_truncate_cluster_pages(inode, byte_start, byte_len); 1642 ocfs2_truncate_cluster_pages(inode, byte_start, byte_len);