diff options
author | Joseph Qi <joseph.qi@huawei.com> | 2015-06-24 19:54:59 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2015-06-24 20:49:39 -0400 |
commit | cf1776a9e834400ed8e2fea48ffa6daa9da28446 (patch) | |
tree | b1612f8a870a1305cf32cc339119a68635091e6e /fs/ocfs2/namei.c | |
parent | e327284abb8aee3206cef3b790a283fea213a174 (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.c | 22 |
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 | ||
2672 | int ocfs2_del_inode_from_orphan(struct ocfs2_super *osb, | 2672 | int 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 | ||
2752 | bail_unlock_inode: | ||
2753 | ocfs2_inode_unlock(inode, 1); | ||
2754 | brelse(di_bh); | ||
2755 | |||
2756 | bail: | 2744 | bail: |
2757 | return status; | 2745 | return status; |
2758 | } | 2746 | } |