diff options
author | Li Dongyang <lidongyang@novell.com> | 2010-04-22 04:11:19 -0400 |
---|---|---|
committer | Mark Fasheh <mfasheh@suse.com> | 2010-04-23 14:03:49 -0400 |
commit | d4cd1871cff68e188dadcf6d1280762522b643eb (patch) | |
tree | cf3a6426342378956f4d797066ec060eb3939083 /fs/ocfs2/inode.c | |
parent | d5a30458a90597915977f06e79406b664a41b8ac (diff) |
ocfs2: add OCFS2_INODE_SKIP_ORPHAN_DIR flag and honor it in the inode wipe code
Currently in the error path of ocfs2_symlink and ocfs2_mknod, we just call
iput with the inode we failed with, but the inode wipe code will complain
because we don't add the inode to orphan dir. One solution would be to lock
the orphan dir during the entire transaction, but that's too heavy for a
rare error path. Instead, we add a flag, OCFS2_INODE_SKIP_ORPHAN_DIR which
tells the inode wipe code that it won't find this inode in the orphan dir.
[ Merge fixes and comment style cleanups -Mark ]
Signed-off-by: Li Dongyang <lidongyang@novell.com>
Signed-off-by: Mark Fasheh <mfasheh@suse.com>
Diffstat (limited to 'fs/ocfs2/inode.c')
-rw-r--r-- | fs/ocfs2/inode.c | 65 |
1 files changed, 36 insertions, 29 deletions
diff --git a/fs/ocfs2/inode.c b/fs/ocfs2/inode.c index 07cc8bb68b6d..26399202be7d 100644 --- a/fs/ocfs2/inode.c +++ b/fs/ocfs2/inode.c | |||
@@ -639,11 +639,13 @@ static int ocfs2_remove_inode(struct inode *inode, | |||
639 | goto bail_unlock; | 639 | goto bail_unlock; |
640 | } | 640 | } |
641 | 641 | ||
642 | status = ocfs2_orphan_del(osb, handle, orphan_dir_inode, inode, | 642 | if (!(OCFS2_I(inode)->ip_flags & OCFS2_INODE_SKIP_ORPHAN_DIR)) { |
643 | orphan_dir_bh); | 643 | status = ocfs2_orphan_del(osb, handle, orphan_dir_inode, inode, |
644 | if (status < 0) { | 644 | orphan_dir_bh); |
645 | mlog_errno(status); | 645 | if (status < 0) { |
646 | goto bail_commit; | 646 | mlog_errno(status); |
647 | goto bail_commit; | ||
648 | } | ||
647 | } | 649 | } |
648 | 650 | ||
649 | /* set the inodes dtime */ | 651 | /* set the inodes dtime */ |
@@ -726,34 +728,35 @@ static int ocfs2_wipe_inode(struct inode *inode, | |||
726 | struct inode *orphan_dir_inode = NULL; | 728 | struct inode *orphan_dir_inode = NULL; |
727 | struct buffer_head *orphan_dir_bh = NULL; | 729 | struct buffer_head *orphan_dir_bh = NULL; |
728 | struct ocfs2_super *osb = OCFS2_SB(inode->i_sb); | 730 | struct ocfs2_super *osb = OCFS2_SB(inode->i_sb); |
729 | struct ocfs2_dinode *di; | 731 | struct ocfs2_dinode *di = (struct ocfs2_dinode *) di_bh->b_data; |
730 | 732 | ||
731 | di = (struct ocfs2_dinode *) di_bh->b_data; | 733 | if (!(OCFS2_I(inode)->ip_flags & OCFS2_INODE_SKIP_ORPHAN_DIR)) { |
732 | orphaned_slot = le16_to_cpu(di->i_orphaned_slot); | 734 | orphaned_slot = le16_to_cpu(di->i_orphaned_slot); |
733 | 735 | ||
734 | status = ocfs2_check_orphan_recovery_state(osb, orphaned_slot); | 736 | status = ocfs2_check_orphan_recovery_state(osb, orphaned_slot); |
735 | if (status) | 737 | if (status) |
736 | return status; | 738 | return status; |
737 | 739 | ||
738 | orphan_dir_inode = ocfs2_get_system_file_inode(osb, | 740 | orphan_dir_inode = ocfs2_get_system_file_inode(osb, |
739 | ORPHAN_DIR_SYSTEM_INODE, | 741 | ORPHAN_DIR_SYSTEM_INODE, |
740 | orphaned_slot); | 742 | orphaned_slot); |
741 | if (!orphan_dir_inode) { | 743 | if (!orphan_dir_inode) { |
742 | status = -EEXIST; | 744 | status = -EEXIST; |
743 | mlog_errno(status); | 745 | mlog_errno(status); |
744 | goto bail; | 746 | goto bail; |
745 | } | 747 | } |
746 | 748 | ||
747 | /* Lock the orphan dir. The lock will be held for the entire | 749 | /* Lock the orphan dir. The lock will be held for the entire |
748 | * delete_inode operation. We do this now to avoid races with | 750 | * delete_inode operation. We do this now to avoid races with |
749 | * recovery completion on other nodes. */ | 751 | * recovery completion on other nodes. */ |
750 | mutex_lock(&orphan_dir_inode->i_mutex); | 752 | mutex_lock(&orphan_dir_inode->i_mutex); |
751 | status = ocfs2_inode_lock(orphan_dir_inode, &orphan_dir_bh, 1); | 753 | status = ocfs2_inode_lock(orphan_dir_inode, &orphan_dir_bh, 1); |
752 | if (status < 0) { | 754 | if (status < 0) { |
753 | mutex_unlock(&orphan_dir_inode->i_mutex); | 755 | mutex_unlock(&orphan_dir_inode->i_mutex); |
754 | 756 | ||
755 | mlog_errno(status); | 757 | mlog_errno(status); |
756 | goto bail; | 758 | goto bail; |
759 | } | ||
757 | } | 760 | } |
758 | 761 | ||
759 | /* we do this while holding the orphan dir lock because we | 762 | /* we do this while holding the orphan dir lock because we |
@@ -794,6 +797,9 @@ static int ocfs2_wipe_inode(struct inode *inode, | |||
794 | mlog_errno(status); | 797 | mlog_errno(status); |
795 | 798 | ||
796 | bail_unlock_dir: | 799 | bail_unlock_dir: |
800 | if (OCFS2_I(inode)->ip_flags & OCFS2_INODE_SKIP_ORPHAN_DIR) | ||
801 | return status; | ||
802 | |||
797 | ocfs2_inode_unlock(orphan_dir_inode, 1); | 803 | ocfs2_inode_unlock(orphan_dir_inode, 1); |
798 | mutex_unlock(&orphan_dir_inode->i_mutex); | 804 | mutex_unlock(&orphan_dir_inode->i_mutex); |
799 | brelse(orphan_dir_bh); | 805 | brelse(orphan_dir_bh); |
@@ -889,7 +895,8 @@ static int ocfs2_query_inode_wipe(struct inode *inode, | |||
889 | 895 | ||
890 | /* Do some basic inode verification... */ | 896 | /* Do some basic inode verification... */ |
891 | di = (struct ocfs2_dinode *) di_bh->b_data; | 897 | di = (struct ocfs2_dinode *) di_bh->b_data; |
892 | if (!(di->i_flags & cpu_to_le32(OCFS2_ORPHANED_FL))) { | 898 | if (!(di->i_flags & cpu_to_le32(OCFS2_ORPHANED_FL)) && |
899 | !(oi->ip_flags & OCFS2_INODE_SKIP_ORPHAN_DIR)) { | ||
893 | /* | 900 | /* |
894 | * Inodes in the orphan dir must have ORPHANED_FL. The only | 901 | * Inodes in the orphan dir must have ORPHANED_FL. The only |
895 | * inodes that come back out of the orphan dir are reflink | 902 | * inodes that come back out of the orphan dir are reflink |