aboutsummaryrefslogtreecommitdiffstats
path: root/fs/ocfs2/namei.c
diff options
context:
space:
mode:
authorJoseph Qi <joseph.qi@huawei.com>2015-06-24 19:54:59 -0400
committerLinus Torvalds <torvalds@linux-foundation.org>2015-06-24 20:49:39 -0400
commitcf1776a9e834400ed8e2fea48ffa6daa9da28446 (patch)
treeb1612f8a870a1305cf32cc339119a68635091e6e /fs/ocfs2/namei.c
parente327284abb8aee3206cef3b790a283fea213a174 (diff)
ocfs2: fix a tiny race when truncate dio orohaned entry
Once dio crashed it will leave an entry in orphan dir. And orphan scan will take care of the clean up. There is a tiny race case that the same entry will be truncated twice and then trigger the BUG in ocfs2_del_inode_from_orphan. Signed-off-by: Joseph Qi <joseph.qi@huawei.com> Cc: Mark Fasheh <mfasheh@suse.com> Cc: Joel Becker <jlbec@evilplan.org> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Diffstat (limited to 'fs/ocfs2/namei.c')
-rw-r--r--fs/ocfs2/namei.c22
1 files changed, 5 insertions, 17 deletions
diff --git a/fs/ocfs2/namei.c b/fs/ocfs2/namei.c
index 176fe6afd94e..08a7a5b70494 100644
--- a/fs/ocfs2/namei.c
+++ b/fs/ocfs2/namei.c
@@ -2670,30 +2670,22 @@ bail:
2670} 2670}
2671 2671
2672int ocfs2_del_inode_from_orphan(struct ocfs2_super *osb, 2672int ocfs2_del_inode_from_orphan(struct ocfs2_super *osb,
2673 struct inode *inode, int update_isize, 2673 struct inode *inode, struct buffer_head *di_bh,
2674 loff_t end) 2674 int update_isize, loff_t end)
2675{ 2675{
2676 struct inode *orphan_dir_inode = NULL; 2676 struct inode *orphan_dir_inode = NULL;
2677 struct buffer_head *orphan_dir_bh = NULL; 2677 struct buffer_head *orphan_dir_bh = NULL;
2678 struct buffer_head *di_bh = NULL; 2678 struct ocfs2_dinode *di = (struct ocfs2_dinode *)di_bh->b_data;
2679 struct ocfs2_dinode *di = NULL;
2680 handle_t *handle = NULL; 2679 handle_t *handle = NULL;
2681 int status = 0; 2680 int status = 0;
2682 2681
2683 status = ocfs2_inode_lock(inode, &di_bh, 1);
2684 if (status < 0) {
2685 mlog_errno(status);
2686 goto bail;
2687 }
2688 di = (struct ocfs2_dinode *) di_bh->b_data;
2689
2690 orphan_dir_inode = ocfs2_get_system_file_inode(osb, 2682 orphan_dir_inode = ocfs2_get_system_file_inode(osb,
2691 ORPHAN_DIR_SYSTEM_INODE, 2683 ORPHAN_DIR_SYSTEM_INODE,
2692 le16_to_cpu(di->i_dio_orphaned_slot)); 2684 le16_to_cpu(di->i_dio_orphaned_slot));
2693 if (!orphan_dir_inode) { 2685 if (!orphan_dir_inode) {
2694 status = -ENOENT; 2686 status = -ENOENT;
2695 mlog_errno(status); 2687 mlog_errno(status);
2696 goto bail_unlock_inode; 2688 goto bail;
2697 } 2689 }
2698 2690
2699 mutex_lock(&orphan_dir_inode->i_mutex); 2691 mutex_lock(&orphan_dir_inode->i_mutex);
@@ -2702,7 +2694,7 @@ int ocfs2_del_inode_from_orphan(struct ocfs2_super *osb,
2702 mutex_unlock(&orphan_dir_inode->i_mutex); 2694 mutex_unlock(&orphan_dir_inode->i_mutex);
2703 iput(orphan_dir_inode); 2695 iput(orphan_dir_inode);
2704 mlog_errno(status); 2696 mlog_errno(status);
2705 goto bail_unlock_inode; 2697 goto bail;
2706 } 2698 }
2707 2699
2708 handle = ocfs2_start_trans(osb, 2700 handle = ocfs2_start_trans(osb,
@@ -2749,10 +2741,6 @@ bail_unlock_orphan:
2749 brelse(orphan_dir_bh); 2741 brelse(orphan_dir_bh);
2750 iput(orphan_dir_inode); 2742 iput(orphan_dir_inode);
2751 2743
2752bail_unlock_inode:
2753 ocfs2_inode_unlock(inode, 1);
2754 brelse(di_bh);
2755
2756bail: 2744bail:
2757 return status; 2745 return status;
2758} 2746}