aboutsummaryrefslogtreecommitdiffstats
path: root/fs
diff options
context:
space:
mode:
authorJoseph Qi <joseph.qi@huawei.com>2015-02-16 19:00:12 -0500
committerLinus Torvalds <torvalds@linux-foundation.org>2015-02-16 20:56:05 -0500
commit4813962beef7586f890a645a1bda77691da4b74a (patch)
tree75885da49ee8bc539aa41c6af8395a4f88c2a7d9 /fs
parent3a83b342c87e6d21290de8dc76ec20a67821261d (diff)
ocfs2: wait for orphan recovery first once append O_DIRECT write crash
If one node has crashed with orphan entry leftover, another node which do append O_DIRECT write to the same file will override the i_dio_orphaned_slot. Then the old entry won't be cleaned forever. If this case happens, we let it wait for orphan recovery first. Signed-off-by: Joseph Qi <joseph.qi@huawei.com> Cc: Weiwei Wang <wangww631@huawei.com> Cc: Joel Becker <jlbec@evilplan.org> Cc: Junxiao Bi <junxiao.bi@oracle.com> Cc: Mark Fasheh <mfasheh@suse.com> Cc: Xuejiufei <xuejiufei@huawei.com> Cc: alex chen <alex.chen@huawei.com> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Diffstat (limited to 'fs')
-rw-r--r--fs/ocfs2/inode.h2
-rw-r--r--fs/ocfs2/journal.c2
-rw-r--r--fs/ocfs2/namei.c37
-rw-r--r--fs/ocfs2/super.c2
4 files changed, 43 insertions, 0 deletions
diff --git a/fs/ocfs2/inode.h b/fs/ocfs2/inode.h
index ca3431ee7f24..5e86b247c821 100644
--- a/fs/ocfs2/inode.h
+++ b/fs/ocfs2/inode.h
@@ -81,6 +81,8 @@ struct ocfs2_inode_info
81 tid_t i_sync_tid; 81 tid_t i_sync_tid;
82 tid_t i_datasync_tid; 82 tid_t i_datasync_tid;
83 83
84 wait_queue_head_t append_dio_wq;
85
84 struct dquot *i_dquot[MAXQUOTAS]; 86 struct dquot *i_dquot[MAXQUOTAS];
85}; 87};
86 88
diff --git a/fs/ocfs2/journal.c b/fs/ocfs2/journal.c
index 9730f5350ef4..ff531928269e 100644
--- a/fs/ocfs2/journal.c
+++ b/fs/ocfs2/journal.c
@@ -2204,6 +2204,8 @@ static int ocfs2_recover_orphans(struct ocfs2_super *osb,
2204 ret = ocfs2_del_inode_from_orphan(osb, inode, 0, 0); 2204 ret = ocfs2_del_inode_from_orphan(osb, inode, 0, 0);
2205 if (ret) 2205 if (ret)
2206 mlog_errno(ret); 2206 mlog_errno(ret);
2207
2208 wake_up(&OCFS2_I(inode)->append_dio_wq);
2207 } /* else if ORPHAN_NO_NEED_TRUNCATE, do nothing */ 2209 } /* else if ORPHAN_NO_NEED_TRUNCATE, do nothing */
2208 2210
2209next: 2211next:
diff --git a/fs/ocfs2/namei.c b/fs/ocfs2/namei.c
index 7eec45d0d85f..b5c3a5ea3ee6 100644
--- a/fs/ocfs2/namei.c
+++ b/fs/ocfs2/namei.c
@@ -2577,6 +2577,27 @@ leave:
2577 return status; 2577 return status;
2578} 2578}
2579 2579
2580static int ocfs2_dio_orphan_recovered(struct inode *inode)
2581{
2582 int ret;
2583 struct buffer_head *di_bh = NULL;
2584 struct ocfs2_dinode *di = NULL;
2585
2586 ret = ocfs2_inode_lock(inode, &di_bh, 1);
2587 if (ret < 0) {
2588 mlog_errno(ret);
2589 return 0;
2590 }
2591
2592 di = (struct ocfs2_dinode *) di_bh->b_data;
2593 ret = !(di->i_flags & cpu_to_le32(OCFS2_DIO_ORPHANED_FL));
2594 ocfs2_inode_unlock(inode, 1);
2595 brelse(di_bh);
2596
2597 return ret;
2598}
2599
2600#define OCFS2_DIO_ORPHANED_FL_CHECK_INTERVAL 10000
2580int ocfs2_add_inode_to_orphan(struct ocfs2_super *osb, 2601int ocfs2_add_inode_to_orphan(struct ocfs2_super *osb,
2581 struct inode *inode) 2602 struct inode *inode)
2582{ 2603{
@@ -2586,13 +2607,29 @@ int ocfs2_add_inode_to_orphan(struct ocfs2_super *osb,
2586 struct buffer_head *di_bh = NULL; 2607 struct buffer_head *di_bh = NULL;
2587 int status = 0; 2608 int status = 0;
2588 handle_t *handle = NULL; 2609 handle_t *handle = NULL;
2610 struct ocfs2_dinode *di = NULL;
2589 2611
2612restart:
2590 status = ocfs2_inode_lock(inode, &di_bh, 1); 2613 status = ocfs2_inode_lock(inode, &di_bh, 1);
2591 if (status < 0) { 2614 if (status < 0) {
2592 mlog_errno(status); 2615 mlog_errno(status);
2593 goto bail; 2616 goto bail;
2594 } 2617 }
2595 2618
2619 di = (struct ocfs2_dinode *) di_bh->b_data;
2620 /*
2621 * Another append dio crashed?
2622 * If so, wait for recovery first.
2623 */
2624 if (unlikely(di->i_flags & cpu_to_le32(OCFS2_DIO_ORPHANED_FL))) {
2625 ocfs2_inode_unlock(inode, 1);
2626 brelse(di_bh);
2627 wait_event_interruptible_timeout(OCFS2_I(inode)->append_dio_wq,
2628 ocfs2_dio_orphan_recovered(inode),
2629 msecs_to_jiffies(OCFS2_DIO_ORPHANED_FL_CHECK_INTERVAL));
2630 goto restart;
2631 }
2632
2596 status = ocfs2_prepare_orphan_dir(osb, &orphan_dir_inode, 2633 status = ocfs2_prepare_orphan_dir(osb, &orphan_dir_inode,
2597 OCFS2_I(inode)->ip_blkno, 2634 OCFS2_I(inode)->ip_blkno,
2598 orphan_name, 2635 orphan_name,
diff --git a/fs/ocfs2/super.c b/fs/ocfs2/super.c
index 87a1f7679d9b..26675185b886 100644
--- a/fs/ocfs2/super.c
+++ b/fs/ocfs2/super.c
@@ -1746,6 +1746,8 @@ static void ocfs2_inode_init_once(void *data)
1746 ocfs2_lock_res_init_once(&oi->ip_inode_lockres); 1746 ocfs2_lock_res_init_once(&oi->ip_inode_lockres);
1747 ocfs2_lock_res_init_once(&oi->ip_open_lockres); 1747 ocfs2_lock_res_init_once(&oi->ip_open_lockres);
1748 1748
1749 init_waitqueue_head(&oi->append_dio_wq);
1750
1749 ocfs2_metadata_cache_init(INODE_CACHE(&oi->vfs_inode), 1751 ocfs2_metadata_cache_init(INODE_CACHE(&oi->vfs_inode),
1750 &ocfs2_inode_caching_ops); 1752 &ocfs2_inode_caching_ops);
1751 1753