diff options
author | Joseph Qi <joseph.qi@huawei.com> | 2015-09-04 15:44:40 -0700 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2015-09-04 16:54:41 -0700 |
commit | ad694821224634d46b6571f0161e85ac2e397396 (patch) | |
tree | 0aba23e4b8889402d1d1c1e96a62e790574c96ec /fs/ocfs2/inode.c | |
parent | f57a22ddecd6f26040a67e2c12880f98f88b6e00 (diff) | |
download | lwn-ad694821224634d46b6571f0161e85ac2e397396.tar.gz lwn-ad694821224634d46b6571f0161e85ac2e397396.zip |
ocfs2: fix race between crashed dio and rm
There is a race case between crashed dio and rm, which will lead to
OCFS2_VALID_FL not set read-only.
N1 N2
------------------------------------------------------------------------
dd with direct flag
rm file
crashed with an dio entry left
in orphan dir
clear OCFS2_VALID_FL in
ocfs2_remove_inode
recover N1 and read the corrupted inode,
and set filesystem read-only
So we skip the inode deletion this time and wait for dio entry recovered
first.
Signed-off-by: Joseph Qi <joseph.qi@huawei.com>
Reviewed-by: Mark Fasheh <mfasheh@suse.de>
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/inode.c')
-rw-r--r-- | fs/ocfs2/inode.c | 9 |
1 files changed, 9 insertions, 0 deletions
diff --git a/fs/ocfs2/inode.c b/fs/ocfs2/inode.c index 7868f7e7c455..fe4b3f7db245 100644 --- a/fs/ocfs2/inode.c +++ b/fs/ocfs2/inode.c @@ -971,6 +971,7 @@ static void ocfs2_delete_inode(struct inode *inode) int wipe, status; sigset_t oldset; struct buffer_head *di_bh = NULL; + struct ocfs2_dinode *di = NULL; trace_ocfs2_delete_inode(inode->i_ino, (unsigned long long)OCFS2_I(inode)->ip_blkno, @@ -1025,6 +1026,14 @@ static void ocfs2_delete_inode(struct inode *inode) goto bail_unlock_nfs_sync; } + di = (struct ocfs2_dinode *)di_bh->b_data; + /* Skip inode deletion and wait for dio orphan entry recovered + * first */ + if (unlikely(di->i_flags & cpu_to_le32(OCFS2_DIO_ORPHANED_FL))) { + ocfs2_cleanup_delete_inode(inode, 0); + goto bail_unlock_inode; + } + /* Query the cluster. This will be the final decision made * before we go ahead and wipe the inode. */ status = ocfs2_query_inode_wipe(inode, di_bh, &wipe); |