aboutsummaryrefslogtreecommitdiffstats
path: root/fs/ocfs2/file.c
diff options
context:
space:
mode:
authorTao Ma <tao.ma@oracle.com>2008-08-18 05:38:44 -0400
committerMark Fasheh <mfasheh@suse.com>2008-10-13 16:57:58 -0400
commite7d4cb6bc19658646357eeff134645cd9bc3479f (patch)
tree4e24321e5c28fb90dffa1f396972fddb3c458e58 /fs/ocfs2/file.c
parent811f933df1e55615fd0bb4818f31e3868a8e6e23 (diff)
ocfs2: Abstract ocfs2_extent_tree in b-tree operations.
In the old extent tree operation, we take the hypothesis that we are using the ocfs2_extent_list in ocfs2_dinode as the tree root. As xattr will also use ocfs2_extent_list to store large value for a xattr entry, we refactor the tree operation so that xattr can use it directly. The refactoring includes 4 steps: 1. Abstract set/get of last_eb_blk and update_clusters since they may be stored in different location for dinode and xattr. 2. Add a new structure named ocfs2_extent_tree to indicate the extent tree the operation will work on. 3. Remove all the use of fe_bh and di, use root_bh and root_el in extent tree instead. So now all the fe_bh is replaced with et->root_bh, el with root_el accordingly. 4. Make ocfs2_lock_allocators generic. Now it is limited to be only used in file extend allocation. But the whole function is useful when we want to store large EAs. Note: This patch doesn't touch ocfs2_commit_truncate() since it is not used for anything other than truncate inode data btrees. Signed-off-by: Tao Ma <tao.ma@oracle.com> Signed-off-by: Mark Fasheh <mfasheh@suse.com>
Diffstat (limited to 'fs/ocfs2/file.c')
-rw-r--r--fs/ocfs2/file.c104
1 files changed, 13 insertions, 91 deletions
diff --git a/fs/ocfs2/file.c b/fs/ocfs2/file.c
index a31bba6c5575..f567cc53d9bc 100644
--- a/fs/ocfs2/file.c
+++ b/fs/ocfs2/file.c
@@ -521,7 +521,8 @@ int ocfs2_do_extend_allocation(struct ocfs2_super *osb,
521 if (mark_unwritten) 521 if (mark_unwritten)
522 flags = OCFS2_EXT_UNWRITTEN; 522 flags = OCFS2_EXT_UNWRITTEN;
523 523
524 free_extents = ocfs2_num_free_extents(osb, inode, fe_bh); 524 free_extents = ocfs2_num_free_extents(osb, inode, fe_bh,
525 OCFS2_DINODE_EXTENT);
525 if (free_extents < 0) { 526 if (free_extents < 0) {
526 status = free_extents; 527 status = free_extents;
527 mlog_errno(status); 528 mlog_errno(status);
@@ -570,7 +571,7 @@ int ocfs2_do_extend_allocation(struct ocfs2_super *osb,
570 num_bits, bit_off, (unsigned long long)OCFS2_I(inode)->ip_blkno); 571 num_bits, bit_off, (unsigned long long)OCFS2_I(inode)->ip_blkno);
571 status = ocfs2_insert_extent(osb, handle, inode, fe_bh, 572 status = ocfs2_insert_extent(osb, handle, inode, fe_bh,
572 *logical_offset, block, num_bits, 573 *logical_offset, block, num_bits,
573 flags, meta_ac); 574 flags, meta_ac, OCFS2_DINODE_EXTENT);
574 if (status < 0) { 575 if (status < 0) {
575 mlog_errno(status); 576 mlog_errno(status);
576 goto leave; 577 goto leave;
@@ -599,92 +600,6 @@ leave:
599 return status; 600 return status;
600} 601}
601 602
602/*
603 * For a given allocation, determine which allocators will need to be
604 * accessed, and lock them, reserving the appropriate number of bits.
605 *
606 * Sparse file systems call this from ocfs2_write_begin_nolock()
607 * and ocfs2_allocate_unwritten_extents().
608 *
609 * File systems which don't support holes call this from
610 * ocfs2_extend_allocation().
611 */
612int ocfs2_lock_allocators(struct inode *inode, struct buffer_head *di_bh,
613 u32 clusters_to_add, u32 extents_to_split,
614 struct ocfs2_alloc_context **data_ac,
615 struct ocfs2_alloc_context **meta_ac)
616{
617 int ret = 0, num_free_extents;
618 unsigned int max_recs_needed = clusters_to_add + 2 * extents_to_split;
619 struct ocfs2_super *osb = OCFS2_SB(inode->i_sb);
620 struct ocfs2_dinode *di = (struct ocfs2_dinode *)di_bh->b_data;
621
622 *meta_ac = NULL;
623 if (data_ac)
624 *data_ac = NULL;
625
626 BUG_ON(clusters_to_add != 0 && data_ac == NULL);
627
628 mlog(0, "extend inode %llu, i_size = %lld, di->i_clusters = %u, "
629 "clusters_to_add = %u, extents_to_split = %u\n",
630 (unsigned long long)OCFS2_I(inode)->ip_blkno, (long long)i_size_read(inode),
631 le32_to_cpu(di->i_clusters), clusters_to_add, extents_to_split);
632
633 num_free_extents = ocfs2_num_free_extents(osb, inode, di_bh);
634 if (num_free_extents < 0) {
635 ret = num_free_extents;
636 mlog_errno(ret);
637 goto out;
638 }
639
640 /*
641 * Sparse allocation file systems need to be more conservative
642 * with reserving room for expansion - the actual allocation
643 * happens while we've got a journal handle open so re-taking
644 * a cluster lock (because we ran out of room for another
645 * extent) will violate ordering rules.
646 *
647 * Most of the time we'll only be seeing this 1 cluster at a time
648 * anyway.
649 *
650 * Always lock for any unwritten extents - we might want to
651 * add blocks during a split.
652 */
653 if (!num_free_extents ||
654 (ocfs2_sparse_alloc(osb) && num_free_extents < max_recs_needed)) {
655 ret = ocfs2_reserve_new_metadata(osb, &di->id2.i_list, meta_ac);
656 if (ret < 0) {
657 if (ret != -ENOSPC)
658 mlog_errno(ret);
659 goto out;
660 }
661 }
662
663 if (clusters_to_add == 0)
664 goto out;
665
666 ret = ocfs2_reserve_clusters(osb, clusters_to_add, data_ac);
667 if (ret < 0) {
668 if (ret != -ENOSPC)
669 mlog_errno(ret);
670 goto out;
671 }
672
673out:
674 if (ret) {
675 if (*meta_ac) {
676 ocfs2_free_alloc_context(*meta_ac);
677 *meta_ac = NULL;
678 }
679
680 /*
681 * We cannot have an error and a non null *data_ac.
682 */
683 }
684
685 return ret;
686}
687
688static int __ocfs2_extend_allocation(struct inode *inode, u32 logical_start, 603static int __ocfs2_extend_allocation(struct inode *inode, u32 logical_start,
689 u32 clusters_to_add, int mark_unwritten) 604 u32 clusters_to_add, int mark_unwritten)
690{ 605{
@@ -725,7 +640,13 @@ static int __ocfs2_extend_allocation(struct inode *inode, u32 logical_start,
725restart_all: 640restart_all:
726 BUG_ON(le32_to_cpu(fe->i_clusters) != OCFS2_I(inode)->ip_clusters); 641 BUG_ON(le32_to_cpu(fe->i_clusters) != OCFS2_I(inode)->ip_clusters);
727 642
728 status = ocfs2_lock_allocators(inode, bh, clusters_to_add, 0, &data_ac, 643 mlog(0, "extend inode %llu, i_size = %lld, di->i_clusters = %u, "
644 "clusters_to_add = %u\n",
645 (unsigned long long)OCFS2_I(inode)->ip_blkno,
646 (long long)i_size_read(inode), le32_to_cpu(fe->i_clusters),
647 clusters_to_add);
648 status = ocfs2_lock_allocators(inode, bh, &fe->id2.i_list,
649 clusters_to_add, 0, &data_ac,
729 &meta_ac); 650 &meta_ac);
730 if (status) { 651 if (status) {
731 mlog_errno(status); 652 mlog_errno(status);
@@ -1397,7 +1318,8 @@ static int __ocfs2_remove_inode_range(struct inode *inode,
1397 struct ocfs2_alloc_context *meta_ac = NULL; 1318 struct ocfs2_alloc_context *meta_ac = NULL;
1398 struct ocfs2_dinode *di = (struct ocfs2_dinode *)di_bh->b_data; 1319 struct ocfs2_dinode *di = (struct ocfs2_dinode *)di_bh->b_data;
1399 1320
1400 ret = ocfs2_lock_allocators(inode, di_bh, 0, 1, NULL, &meta_ac); 1321 ret = ocfs2_lock_allocators(inode, di_bh, &di->id2.i_list,
1322 0, 1, NULL, &meta_ac);
1401 if (ret) { 1323 if (ret) {
1402 mlog_errno(ret); 1324 mlog_errno(ret);
1403 return ret; 1325 return ret;
@@ -1428,7 +1350,7 @@ static int __ocfs2_remove_inode_range(struct inode *inode,
1428 } 1350 }
1429 1351
1430 ret = ocfs2_remove_extent(inode, di_bh, cpos, len, handle, meta_ac, 1352 ret = ocfs2_remove_extent(inode, di_bh, cpos, len, handle, meta_ac,
1431 dealloc); 1353 dealloc, OCFS2_DINODE_EXTENT);
1432 if (ret) { 1354 if (ret) {
1433 mlog_errno(ret); 1355 mlog_errno(ret);
1434 goto out_commit; 1356 goto out_commit;