fix dead lock caused by ocfs2_defrag_extent
PATCH 1/1 fix dead lock caused by ocfs2_defrag_extent
ocfs2_defrag_extent may fall into dead lock.
ocfs2_ioctl_move_extents
ocfs2_ioctl_move_extents
ocfs2_move_extents
ocfs2_defrag_extent
ocfs2_lock_allocators_move_extents
ocfs2_reserve_clusters
inode_lock GLOBAL_BITMAP_SYSTEM_INODE
__ocfs2_flush_truncate_log
inode_lock GLOBAL_BITMAP_SYSTEM_INODE
As back trace shows above, ocfs2_reserve_clusters will call inode_lock against the global bitmap if local allocator has not sufficient cluters. Once global bitmap could meet the demand, ocfs2_reserve_cluster will return success with global bitmap locked.
After ocfs2_reserve_cluster, if truncate log is full, __ocfs2_flush_truncate_log will definitely fall into dead lock because it needs to inode_lock global bitmap, which has already been locked.
To fix this bug, we could remove from ocfs2_lock_allocators_move_extents the code which intends to lock global allocator, and put the removed code after __ocfs2_flush_truncate_log
The ocfs2_lock_allocators_move_extents has been refered by 2 places, one is here, the other does not need the data allocator context, which means this patch does not affect the caller so far.
--- fs/ocfs2/move_extents.c | 13 ++++++------- 1 file changed, 6 insertions(+), 7 deletions(-)
fs/ocfs2/move_extents.c +6 -7
@@ -192,13 +192,6 @@ static int ocfs2_lock_allocators_move_extents(struct inode *inode, goto out; } -if (data_ac) { - ret =ocfs2_reserve_clusters (osb, clusters_to_move, data_ac); -if (ret) { -mlog_errno (ret); - goto out; - } - } *credits +=ocfs2_calc_extend_credits (osb->sb, et->et_root_el);
@@ -283,6 +276,12 @@ static int ocfs2_defrag_extent(struct ocfs2_move_extents_context *context, } } + ret =ocfs2_reserve_clusters (osb, *len, &context->data_ac); +if (ret) { +mlog_errno (ret); + goto out_unlock_mutex; + } + handle =ocfs2_start_trans (osb, credits);if (IS_ERR (handle)) { ret =PTR_ERR (handle);
Signature · 1 line
2.13.7
Hi Larry,
Quoted 24 lines · Larry Chen
ocfs2_defrag_extentmay fall into dead lock.
ocfs2_ioctl_move_extents
ocfs2_ioctl_move_extents
ocfs2_move_extents
ocfs2_defrag_extent
ocfs2_lock_allocators_move_extents
ocfs2_reserve_clusters
inode_lockGLOBAL_BITMAP_SYSTEM_INODE
__ocfs2_flush_truncate_log
inode_lockGLOBAL_BITMAP_SYSTEM_INODEAs back trace shows above,
ocfs2_reserve_clusterswill callinode_lockagainst the global bitmap if local allocator has not sufficient cluters. Once global bitmap could meet the demand,ocfs2_reserve_clusterwill return success with global bitmap locked.After
ocfs2_reserve_cluster, if truncate log is full,__ocfs2_flush_truncate_logwill definitely fall into dead lock because it needs toinode_lockglobal bitmap, which has already been locked.
Quoted 8 lines
To fix this bug, we could remove from
ocfs2_lock_allocators_move_extentsthe code which intends to lock global allocator, and put the removed code after__ocfs2_flush_truncate_logThe
ocfs2_lock_allocators_move_extentshas been refered by 2 places, one is here, the other does not need the data allocator context, which means this patch does not affect the caller so far.
After this change, data_ac in ocfs2_lock_allocators_move_extents() is no longer used. So I'd prefer we also clean it up.
Thanks,
Joseph
Quoted 39 lines
Signed-off-by Larry Chen <[email protected]>--- fs/ocfs2/move_extents.c | 13 ++++++------- 1 file changed, 6 insertions(+), 7 deletions(-)fs/ocfs2/move_extents.c +6
-7@@ -192,13 +192,6 @@ static int ocfs2_lock_allocators_move_extents(struct inode *inode, goto out; } -if (data_ac) { - ret =ocfs2_reserve_clusters (osb, clusters_to_move, data_ac); -if (ret) { -mlog_errno (ret); - goto out; - } - } *credits +=ocfs2_calc_extend_credits (osb->sb, et->et_root_el);@@ -283,6 +276,12 @@ static int ocfs2_defrag_extent(struct ocfs2_move_extents_context *context, } } + ret =ocfs2_reserve_clusters (osb, *len, &context->data_ac); +if (ret) { +mlog_errno (ret); + goto out_unlock_mutex; + } + handle =ocfs2_start_trans (osb, credits);if (IS_ERR (handle)) { ret =PTR_ERR (handle);
PATCH 1/1 fix dead lock caused by ocfs2_defrag_extent
Hi Joseph,
Thanks for your review, I'll remove it later.
Thanks,
Larry
Quoted 81 lines · Joseph Qi
Hi Larry,
Quoted 24 lines · Larry Chen
ocfs2_defrag_extentmay fall into dead lock.
ocfs2_ioctl_move_extents
ocfs2_ioctl_move_extents
ocfs2_move_extents
ocfs2_defrag_extent
ocfs2_lock_allocators_move_extents
ocfs2_reserve_clusters
inode_lockGLOBAL_BITMAP_SYSTEM_INODE
__ocfs2_flush_truncate_log
inode_lockGLOBAL_BITMAP_SYSTEM_INODEAs back trace shows above,
ocfs2_reserve_clusterswill callinode_lockagainst the global bitmap if local allocator has not sufficient cluters. Once global bitmap could meet the demand,ocfs2_reserve_clusterwill return success with global bitmap locked.After
ocfs2_reserve_cluster, if truncate log is full,__ocfs2_flush_truncate_logwill definitely fall into dead lock because it needs toinode_lockglobal bitmap, which has already been locked.Quoted 8 lines
To fix this bug, we could remove from
ocfs2_lock_allocators_move_extentsthe code which intends to lock global allocator, and put the removed code after__ocfs2_flush_truncate_logThe
ocfs2_lock_allocators_move_extentshas been refered by 2 places, one is here, the other does not need the data allocator context, which means this patch does not affect the caller so far.After this change,
data_acinocfs2_lock_allocators_move_extents()is no longer used. So I'd prefer we also clean it up.Thanks,
JosephQuoted 39 lines
Signed-off-by Larry Chen <[email protected]>--- fs/ocfs2/move_extents.c | 13 ++++++------- 1 file changed, 6 insertions(+), 7 deletions(-)fs/ocfs2/move_extents.c +6
-7@@ -192,13 +192,6 @@ static int ocfs2_lock_allocators_move_extents(struct inode *inode, goto out; } -if (data_ac) { - ret =ocfs2_reserve_clusters (osb, clusters_to_move, data_ac); -if (ret) { -mlog_errno (ret); - goto out; - } - } *credits +=ocfs2_calc_extend_credits (osb->sb, et->et_root_el);@@ -283,6 +276,12 @@ static int ocfs2_defrag_extent(struct ocfs2_move_extents_context *context, } } + ret =ocfs2_reserve_clusters (osb, *len, &context->data_ac); +if (ret) { +mlog_errno (ret); + goto out_unlock_mutex; + } + handle =ocfs2_start_trans (osb, credits);if (IS_ERR (handle)) { ret =PTR_ERR (handle);
Hi Larry,
I'd like to propose another way to fix this issue, which might be easier. Actually, ocfs2_reserve_clusters() inside will flush truncate log if there is no enough clusters left.
So how about just remove __ocfs2_flush_truncate_log() in ocfs2_defrag_extent()?
Thanks,
Changwei
Quoted 70 lines · Larry Chen
ocfs2_defrag_extentmay fall into dead lock.
ocfs2_ioctl_move_extents
ocfs2_ioctl_move_extents
ocfs2_move_extents
ocfs2_defrag_extent
ocfs2_lock_allocators_move_extents
ocfs2_reserve_clusters
inode_lockGLOBAL_BITMAP_SYSTEM_INODE
__ocfs2_flush_truncate_log
inode_lockGLOBAL_BITMAP_SYSTEM_INODEAs back trace shows above,
ocfs2_reserve_clusterswill callinode_lockagainst the global bitmap if local allocator has not sufficient cluters. Once global bitmap could meet the demand,ocfs2_reserve_clusterwill return success with global bitmap locked.After
ocfs2_reserve_cluster, if truncate log is full,__ocfs2_flush_truncate_logwill definitely fall into dead lock because it needs toinode_lockglobal bitmap, which has already been locked.To fix this bug, we could remove from
ocfs2_lock_allocators_move_extentsthe code which intends to lock global allocator, and put the removed code after__ocfs2_flush_truncate_logThe
ocfs2_lock_allocators_move_extentshas been refered by 2 places, one is here, the other does not need the data allocator context, which means this patch does not affect the caller so far.Signed-off-by Larry Chen <[email protected]>--- fs/ocfs2/move_extents.c | 13 ++++++------- 1 file changed, 6 insertions(+), 7 deletions(-)fs/ocfs2/move_extents.c +6
-7@@ -192,13 +192,6 @@ static int ocfs2_lock_allocators_move_extents(struct inode *inode, goto out; } -if (data_ac) { - ret =ocfs2_reserve_clusters (osb, clusters_to_move, data_ac); -if (ret) { -mlog_errno (ret); - goto out; - } - } *credits +=ocfs2_calc_extend_credits (osb->sb, et->et_root_el);@@ -283,6 +276,12 @@ static int ocfs2_defrag_extent(struct ocfs2_move_extents_context *context, } } + ret =ocfs2_reserve_clusters (osb, *len, &context->data_ac); +if (ret) { +mlog_errno (ret); + goto out_unlock_mutex; + } + handle =ocfs2_start_trans (osb, credits);if (IS_ERR (handle)) { ret =PTR_ERR (handle);
A message that is not in the archive (sent off-list or not yet received): HK0PR06MB2561A612E5A95B60E7F8E22FD50A0@HK0PR06MB2561.apcprd06.prod.outlook.com
A message that is not in the archive (sent off-list or not yet received): [email protected]
PATCH 1/1 fix dead lock caused by ocfs2_defrag_extent
Hi Larry,
Sorry for this late reply.
Quoted 10 lines · Larry Chen
Hi Changwei,
I think there might be some logic error.
Imagine that we remove
__ocfs2_flush_truncate_log()inocfs2_defrag_extent().In
ocfs2_reserve_clustersmight skip freeing truncate log if there is enough clusters in local. Then__ocfs2_move_extentmight return error becauseocfs2_truncate_log_appendmight fail.
I think changing ocfs2 infrastructure methods like your way is not a good idea.
So how about this way?
->lock truncate log inode
->__ocfs2_flush_truncate_log() ->ocfs2_lock_allocators_move_extents()
->unlock truncate log inode
Thanks
Changwei
Quoted 94 lines
Thanks,
LarryQuoted 87 lines · Changwei Ge
Hi Larry,
I'd like to propose another way to fix this issue, which might be easier. :-)
Actually,ocfs2_reserve_clusters()inside will flush truncate log if there is no enough clusters left.
So how about just remove__ocfs2_flush_truncate_log()inocfs2_defrag_extent()?Thanks,
ChangweiQuoted 73 lines · Larry Chen
ocfs2_defrag_extentmay fall into dead lock.
ocfs2_ioctl_move_extents
???ocfs2_ioctl_move_extents
?????ocfs2_move_extents
???????ocfs2_defrag_extent
?????????ocfs2_lock_allocators_move_extents???????????
ocfs2_reserve_clusters?????????????inode_lockGLOBAL_BITMAP_SYSTEM_INODE?????
__ocfs2_flush_truncate_log?????????????inode_lockGLOBAL_BITMAP_SYSTEM_INODEAs back trace shows above,
ocfs2_reserve_clusterswill callinode_lockagainst the global bitmap if local allocator has not sufficient cluters.
Once global bitmap could meet the demand,ocfs2_reserve_clusterwill return success with global bitmap locked.After
ocfs2_reserve_cluster, if truncate log is full,__ocfs2_flush_truncate_logwill definitely fall into dead lock because it needs toinode_lockglobal bitmap, which has already been locked.To fix this bug, we could remove from
ocfs2_lock_allocators_move_extents
the code which intends to lock global allocator, and put the removed code after__ocfs2_flush_truncate_logThe
ocfs2_lock_allocators_move_extentshas been refered by 2 places, one
is here, the other does not need the data allocator context, which means
this patch does not affect the caller so far.Signed-off-by Larry Chen <[email protected]>---
??fs/ocfs2/move_extents.c| 13 ++++++------- ?? 1 file changed, 6 insertions(+), 7 deletions(-)fs/ocfs2/move_extents.c +0
-6@@ -192,13 +192,6 @@ static int ocfs2_lock_allocators_move_extents(struct inode *inode, ?????????? goto out; ?????? } ?? -??? if (data_ac) { -??????? ret = ocfs2_reserve_clusters(osb, clusters_to_move, data_ac); -??????? if (ret) { -??????????? mlog_errno(ret); -??????????? goto out; -??????? } -??? } ?? ?????? *credits += ocfs2_calc_extend_credits(osb->sb, et->et_root_el);?? @@ -283,6 +276,12 @@ static int ocfs2_defrag_extent(struct
ocfs2_move_extents_context*context,
?????????? }
?????? }
?? +??? ret =ocfs2_reserve_clusters(osb, *len, &context->data_ac); +??? if (ret) {
+???????mlog_errno(ret);
+??????? gotoout_unlock_mutex;
+??? }
+
?????? handle =ocfs2_start_trans(osb, credits);
?????? if (IS_ERR(handle)) {
?????????? ret =PTR_ERR(handle);
PATCH 1/1 fix dead lock caused by ocfs2_defrag_extent
Hi Changwei,
Maybe we need more investigation.
The following is your fix:
lock truncate log inode
__ocfs2_flush_truncate_log()
ocfs2_lock_allocators_move_extents()
unlock truncate log inode
The lock action will happen like following:lock(truncate_inode)
lock(sub allocat)
lock(local_alloc) or lock(global_bitmap)
I'm not sure if there is another code path that tries to get the same locks but in different order, which may causes dead locks.
Indeed ocfs2 involves too many locks, I would like to reduce the deadlock risk at max extent.
Another way is to add an new argument for __ocfs2_flush_truncate which indicates whether global bitmap is needed to be locked.
Thanks,
Larry
Quoted 122 lines · Changwei Ge
Hi Larry,
Sorry for this late reply.
Quoted 10 lines · Larry Chen
Hi Changwei,
I think there might be some logic error.
Imagine that we remove
__ocfs2_flush_truncate_log()inocfs2_defrag_extent().In
ocfs2_reserve_clustersmight skip freeing truncate log if there is enough clusters in local. Then__ocfs2_move_extentmight return error becauseocfs2_truncate_log_appendmight fail.I think changing ocfs2 infrastructure methods like your way is not a good idea.
So how about this way?
->lock truncate log inode
->__ocfs2_flush_truncate_log() ->ocfs2_lock_allocators_move_extents()
->unlock truncate log inodeThanks
ChangweiQuoted 94 lines
Thanks,
LarryQuoted 87 lines · Changwei Ge
Hi Larry,
I'd like to propose another way to fix this issue, which might be easier. :-)
Actually,ocfs2_reserve_clusters()inside will flush truncate log if there is no enough clusters left.
So how about just remove__ocfs2_flush_truncate_log()inocfs2_defrag_extent()?Thanks,
ChangweiQuoted 73 lines · Larry Chen
ocfs2_defrag_extentmay fall into dead lock.
ocfs2_ioctl_move_extents
???ocfs2_ioctl_move_extents
?????ocfs2_move_extents
???????ocfs2_defrag_extent
?????????ocfs2_lock_allocators_move_extents???????????
ocfs2_reserve_clusters?????????????inode_lockGLOBAL_BITMAP_SYSTEM_INODE?????
__ocfs2_flush_truncate_log?????????????inode_lockGLOBAL_BITMAP_SYSTEM_INODEAs back trace shows above,
ocfs2_reserve_clusterswill callinode_lockagainst the global bitmap if local allocator has not sufficient cluters.
Once global bitmap could meet the demand,ocfs2_reserve_clusterwill return success with global bitmap locked.After
ocfs2_reserve_cluster, if truncate log is full,__ocfs2_flush_truncate_logwill definitely fall into dead lock because it needs toinode_lockglobal bitmap, which has already been locked.To fix this bug, we could remove from
ocfs2_lock_allocators_move_extents
the code which intends to lock global allocator, and put the removed code after__ocfs2_flush_truncate_logThe
ocfs2_lock_allocators_move_extentshas been refered by 2 places, one
is here, the other does not need the data allocator context, which means
this patch does not affect the caller so far.Signed-off-by Larry Chen <[email protected]>--- ?? fs/ocfs2/move_extents.c | 13 ++++++-------?? 1 file changed, 6 insertions(+), 7 deletions(-)
fs/ocfs2/move_extents.c +0
-6@@ -192,13 +192,6 @@ static int ocfs2_lock_allocators_move_extents(struct inode *inode, ?????????? goto out; ?????? } ?? -??? if (data_ac) { -??????? ret = ocfs2_reserve_clusters(osb, clusters_to_move, data_ac); -??????? if (ret) { -??????????? mlog_errno(ret); -??????????? goto out; -??????? } -??? } ?? ?????? *credits += ocfs2_calc_extend_credits(osb->sb, et->et_root_el); ?? @@ -283,6 +276,12 @@ static int ocfs2_defrag_extent(struct
ocfs2_move_extents_context*context,
?????????? }
?????? }
?? +??? ret =ocfs2_reserve_clusters(osb, *len, &context->data_ac);
+??? if (ret) {
+???????mlog_errno(ret);
+??????? gotoout_unlock_mutex;
+??? }
+
?????? handle =ocfs2_start_trans(osb, credits);
?????? if (IS_ERR(handle)) {
?????????? ret =PTR_ERR(handle);
PATCH 1/1 fix dead lock caused by ocfs2_defrag_extent
Hi Larry,
Quoted 10 lines · Larry Chen
Hi Changwei,
Maybe we need more investigation.
The following is your fix:
lock truncate log inode
???__ocfs2_flush_truncate_log()
????ocfs2_lock_allocators_move_extents()
??????? unlock truncate log inode
Quoted 4 lines
The lock action will happen like following:
lock(truncate_inode)
????lock(sub allocat)
????lock(local_alloc) orlock(global_bitmap)
I don't think we have to worry much about mixed order? of cluster lock and inode mutex since cluster lock granted node will directly succeed instead of waiting for itself.
Quoted 9 lines
I'm not sure if there is another code path that tries to get the same locks but in different order, which may causes dead locks.
Indeed ocfs2 involves too many locks, I would like to reduce the deadlock risk at max extent.
Another way is to add an new argument for
__ocfs2_flush_truncatewhich indicates whether global bitmap is needed to be locked.
Sounds a feasible way :)
Thanks,
Changwei
Quoted 135 lines
Thanks,
LarryQuoted 124 lines · Changwei Ge
Hi Larry,
Sorry for this late reply.
Quoted 10 lines · Larry Chen
Hi Changwei,
I think there might be some logic error.
Imagine that we remove
__ocfs2_flush_truncate_log()inocfs2_defrag_extent().In
ocfs2_reserve_clustersmight skip freeing truncate log if there is enough clusters in local. Then__ocfs2_move_extentmight return error becauseocfs2_truncate_log_appendmight fail.I think changing ocfs2 infrastructure methods like your way is not a good idea.
So how about this way?
->lock truncate log inode
->__ocfs2_flush_truncate_log() ->ocfs2_lock_allocators_move_extents()
->unlock truncate log inodeThanks
ChangweiQuoted 96 lines
Thanks,
LarryQuoted 89 lines · Changwei Ge
Hi Larry,
I'd like to propose another way to fix this issue, which might be easier. :-)
Actually,ocfs2_reserve_clusters()inside will flush truncate log if there is no enough clusters left.
So how about just remove__ocfs2_flush_truncate_log()inocfs2_defrag_extent()?Thanks,
ChangweiQuoted 75 lines · Larry Chen
ocfs2_defrag_extentmay fall into dead lock.
ocfs2_ioctl_move_extents
????ocfs2_ioctl_move_extents
??????ocfs2_move_extents
????????ocfs2_defrag_extent
??????????ocfs2_lock_allocators_move_extents????????????
ocfs2_reserve_clusters??????????????inode_lockGLOBAL_BITMAP_SYSTEM_INODE??????
__ocfs2_flush_truncate_log??????????????inode_lockGLOBAL_BITMAP_SYSTEM_INODEAs back trace shows above,
ocfs2_reserve_clusterswill callinode_lock
against the global bitmap if local allocator has not sufficient cluters.
Once global bitmap could meet the demand,ocfs2_reserve_clusterwill return success with global bitmap locked.After
ocfs2_reserve_cluster, if truncate log is full,__ocfs2_flush_truncate_logwill definitely fall into dead lock because it needs toinode_lockglobal bitmap, which has already been locked.To fix this bug, we could remove from
ocfs2_lock_allocators_move_extents
the code which intends to lock global allocator, and put the removed code after__ocfs2_flush_truncate_logThe
ocfs2_lock_allocators_move_extentshas been refered by 2 places, one
is here, the other does not need the data allocator context, which means
this patch does not affect the caller so far.Signed-off-by Larry Chen <[email protected]>---
???fs/ocfs2/move_extents.c| 13 ++++++------- ??? 1 file changed, 6 insertions(+), 7 deletions(-)fs/ocfs2/move_extents.c +0
-6@@ -192,13 +192,6 @@ static int ocfs2_lock_allocators_move_extents(struct inode *inode, ??????????? goto out; ??????? } ??? -??? if (data_ac) { -??????? ret = ocfs2_reserve_clusters(osb, clusters_to_move, data_ac); -??????? if (ret) { -??????????? mlog_errno(ret); -??????????? goto out; -??????? } -??? } ??? ?????? *credits += ocfs2_calc_extend_credits(osb->sb,
et->et_root_el);
??? @@ -283,6 +276,12 @@ static int ocfs2_defrag_extent(structocfs2_move_extents_context*context,
??????????? }
??????? }
??? +??? ret =ocfs2_reserve_clusters(osb, *len, &context->data_ac); +??? if (ret) {
+???????mlog_errno(ret);
+??????? gotoout_unlock_mutex;
+??? }
+
??????? handle =ocfs2_start_trans(osb, credits);
??????? if (IS_ERR(handle)) {
??????????? ret =PTR_ERR(handle);
PATCH 1/1 fix dead lock caused by ocfs2_defrag_extent
Hi Changwei,
Quoted 14 lines · Changwei Ge
Hi Larry,
Quoted 10 lines · Larry Chen
Hi Changwei,
Maybe we need more investigation.
The following is your fix:
lock truncate log inode
???__ocfs2_flush_truncate_log()
????ocfs2_lock_allocators_move_extents()
??????? unlock truncate log inode
Quoted 12 lines
Quoted 4 lines
The lock action will happen like following:
lock(truncate_inode)
????lock(sub allocat)
????lock(local_alloc) orlock(global_bitmap)I don't think we have to worry much about mixed order? of cluster lock and inode mutex since cluster lock granted node will directly succeed instead of waiting for itself.
Quoted 3 lines
I'm not sure if there is another code path that tries to get the same locks but in different order, which may causes dead locks.
Yeah, I use lock to mean both inode_lock and ocfs2_inode_lock. As too many types of lock and inode locks are involved, I can not guarantee that there is no logic error.
Quoted 8 lines
Quoted 6 lines
Indeed ocfs2 involves too many locks, I would like to reduce the deadlock risk at max extent.
Another way is to add an new argument for
__ocfs2_flush_truncatewhich indicates whether global bitmap is needed to be locked.Sounds a feasible way :)
Haha, I also prefer this way :)
I'll send another patch and run test cases on my environment.
Thanks,
Larry
PATCH 1/1 fix dead lock caused by ocfs2_defrag_extent
Hi Changwei,
Quoted 6 lines
Quoted 5 lines
Quoted 3 lines
Another way is to add an new argument for
__ocfs2_flush_truncatewhich indicates whether global bitmap is needed to be locked.Sounds a feasible way :)
I tried this way, but it still causes dead lock. Here is the back trace. The root cause is that ocfs2 sometimes relies on work queue to flush truncate log.
The worker who process the work queue is ocfs2_truncate_log_worker, which directly call ocfs2_flush_truncate_log. And its lock order is truncate_log and then global bitmap, which conflicts with ocfs2_defrag_extent.
#0 [ffffb6c000a03c50] __schedule at ffffffff966c47bf
#1 [ffffb6c000a03ce0] schedule at ffffffff966c4e08
#2 [ffffb6c000a03ce8] rwsem_down_write_failed at ffffffff966c82b3 #3 [ffffb6c000a03d80] schedule at ffffffff966c4e08
#4 [ffffb6c000a03d88] call_rwsem_down_write_failed at ffffffff963a6e03 #5 [ffffb6c000a03dc8] down_write at ffffffff966c7410
try global bit map
#6 [ffffb6c000a03dd0] __ocfs2_flush_truncate_log at ffffffffc0749145
[ocfs2]
got truncate log
#7 [ffffb6c000a03e68] ocfs2_flush_truncate_log at ffffffffc0749afd [ocfs2] #8 [ffffb6c000a03e80] ocfs2_truncate_log_worker at ffffffffc0749b29
[ocfs2]
#9 [ffffb6c000a03e98] process_one_work at ffffffff9609e64a
#10 [ffffb6c000a03ed8] worker_thread at ffffffff9609e88b
#11 [ffffb6c000a03f10] kthread at ffffffff960a470a
#12 [ffffb6c000a03f50] ret_from_fork at ffffffff96800235
[<ffffffff963a6e03>] call_rwsem_down_write_failed+0x13/0x20
try truncate log
got global bm
[<ffffffffc07906f3>] ocfs2_defrag_extent+0x1d3/0x680 [ocfs2]
[<ffffffffc07919f9>] ocfs2_move_extents+0x329/0x740 [ocfs2]
[<ffffffffc0791f43>] ocfs2_ioctl_move_extents+0x133/0x2d0 [ocfs2]
[<ffffffffc0773a83>] ocfs2_ioctl+0x253/0x640 [ocfs2]
[<ffffffff96256480>] do_vfs_ioctl+0x90/0x5f0
[<ffffffff96256a54>] SyS_ioctl+0x74/0x80
[<ffffffff96003ae4>] do_syscall_64+0x74/0x140
[<ffffffff9680009a>] entry_SYSCALL_64_after_hwframe+0x3d/0xa2 [<ffffffffffffffff>] 0xffffffffffffffff