diff options
author | alex chen <alex.chen@huawei.com> | 2015-02-10 17:09:02 -0500 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2015-02-10 17:30:29 -0500 |
commit | 15eba0fe3eeaeb1b80489c1ebb9d47d6d7003f57 (patch) | |
tree | 1e83f68ee33bc709a53c0f9a1fd4a4ab1d8ee612 /fs/ocfs2 | |
parent | 95671c63d5ef3b8794fc9a05d44f0162cc5db425 (diff) |
ocfs2: fix journal commit deadlock in ocfs2_convert_inline_data_to_extents
Similar to ocfs2_write_end_nolock() which is metioned at commit
136f49b91710 ("ocfs2: fix journal commit deadlock"), we should unlock
pages before ocfs2_commit_trans() in ocfs2_convert_inline_data_to_extents.
Otherwise, it will cause a deadlock with journal commit threads.
Signed-off-by: Alex Chen <alex.chen@huawei.com>
Reviewed-by: Joseph Qi <joseph.qi@huawei.com>
Cc: Joel Becker <jlbec@evilplan.org>
Cc: Mark Fasheh <mfasheh@suse.com>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Diffstat (limited to 'fs/ocfs2')
-rw-r--r-- | fs/ocfs2/alloc.c | 18 |
1 files changed, 9 insertions, 9 deletions
diff --git a/fs/ocfs2/alloc.c b/fs/ocfs2/alloc.c index fcae9ef1a328..044158bd22be 100644 --- a/fs/ocfs2/alloc.c +++ b/fs/ocfs2/alloc.c | |||
@@ -6873,7 +6873,7 @@ int ocfs2_convert_inline_data_to_extents(struct inode *inode, | |||
6873 | if (IS_ERR(handle)) { | 6873 | if (IS_ERR(handle)) { |
6874 | ret = PTR_ERR(handle); | 6874 | ret = PTR_ERR(handle); |
6875 | mlog_errno(ret); | 6875 | mlog_errno(ret); |
6876 | goto out_unlock; | 6876 | goto out; |
6877 | } | 6877 | } |
6878 | 6878 | ||
6879 | ret = ocfs2_journal_access_di(handle, INODE_CACHE(inode), di_bh, | 6879 | ret = ocfs2_journal_access_di(handle, INODE_CACHE(inode), di_bh, |
@@ -6931,7 +6931,7 @@ int ocfs2_convert_inline_data_to_extents(struct inode *inode, | |||
6931 | if (ret) { | 6931 | if (ret) { |
6932 | mlog_errno(ret); | 6932 | mlog_errno(ret); |
6933 | need_free = 1; | 6933 | need_free = 1; |
6934 | goto out_commit; | 6934 | goto out_unlock; |
6935 | } | 6935 | } |
6936 | 6936 | ||
6937 | page_end = PAGE_CACHE_SIZE; | 6937 | page_end = PAGE_CACHE_SIZE; |
@@ -6964,12 +6964,16 @@ int ocfs2_convert_inline_data_to_extents(struct inode *inode, | |||
6964 | if (ret) { | 6964 | if (ret) { |
6965 | mlog_errno(ret); | 6965 | mlog_errno(ret); |
6966 | need_free = 1; | 6966 | need_free = 1; |
6967 | goto out_commit; | 6967 | goto out_unlock; |
6968 | } | 6968 | } |
6969 | 6969 | ||
6970 | inode->i_blocks = ocfs2_inode_sector_count(inode); | 6970 | inode->i_blocks = ocfs2_inode_sector_count(inode); |
6971 | } | 6971 | } |
6972 | 6972 | ||
6973 | out_unlock: | ||
6974 | if (pages) | ||
6975 | ocfs2_unlock_and_free_pages(pages, num_pages); | ||
6976 | |||
6973 | out_commit: | 6977 | out_commit: |
6974 | if (ret < 0 && did_quota) | 6978 | if (ret < 0 && did_quota) |
6975 | dquot_free_space_nodirty(inode, | 6979 | dquot_free_space_nodirty(inode, |
@@ -6989,15 +6993,11 @@ out_commit: | |||
6989 | 6993 | ||
6990 | ocfs2_commit_trans(osb, handle); | 6994 | ocfs2_commit_trans(osb, handle); |
6991 | 6995 | ||
6992 | out_unlock: | 6996 | out: |
6993 | if (data_ac) | 6997 | if (data_ac) |
6994 | ocfs2_free_alloc_context(data_ac); | 6998 | ocfs2_free_alloc_context(data_ac); |
6995 | 6999 | if (pages) | |
6996 | out: | ||
6997 | if (pages) { | ||
6998 | ocfs2_unlock_and_free_pages(pages, num_pages); | ||
6999 | kfree(pages); | 7000 | kfree(pages); |
7000 | } | ||
7001 | 7001 | ||
7002 | return ret; | 7002 | return ret; |
7003 | } | 7003 | } |