The thread was waken up accidently. So need check
whether the lock granted or not after wake up.
Also fix issue that major always set to 0 since
hbit initialize incorrect. The performace should be
impacted especial operate in big directory.
kernel BUG at lustre/ldiskfs/htree_lock.c:429!
Call Trace:
htree_node_release_all+0x5a/0x80 [ldiskfs]
htree_unlock+0x22/0x70 [ldiskfs]
osd_index_ea_delete+0x30e/0xb10 [osd_ldiskfs]
lod_sub_delete+0x1c8/0x460 [lod]
lod_delete+0x24/0x30 [lod]
__mdd_index_delete_only+0x194/0x250 [mdd]
__mdd_index_delete+0x46/0x290 [mdd]
mdd_unlink+0x5f8/0xaa0 [mdd]
mdo_unlink+0x46/0x48 [mdt]
mdt_reint_unlink+0xbed/0x14b0 [mdt]
Signed-off-by: Yang Sheng <ys@whamcloud.com>
Change-Id: I5972961bc78b349214c6756642717d126f0c4b26
Reviewed-on: https://review.whamcloud.com/38371
Tested-by: jenkins <devops@whamcloud.com>
Reviewed-by: Andreas Dilger <adilger@whamcloud.com>
Tested-by: Maloo <maloo@whamcloud.com>
Reviewed-by: Jian Yu <yujian@whamcloud.com>
Reviewed-by: Oleg Drokin <green@whamcloud.com>
===================================================================
--- /dev/null
+++ linux-3.10.0-229.1.2.fc21.x86_64/fs/ext4/htree_lock.c
===================================================================
--- /dev/null
+++ linux-3.10.0-229.1.2.fc21.x86_64/fs/ext4/htree_lock.c
+/*
+ * fs/ext4/htree_lock.c
+ *
+/*
+ * fs/ext4/htree_lock.c
+ *
+ }
+
+ newlk->lk_task = current;
+ }
+
+ newlk->lk_task = current;
-+ set_current_state(TASK_UNINTERRUPTIBLE);
+ /* conflict, attach it on blocked list of curlk */
+ list_add_tail(&newln->ln_blocked_list, &curln->ln_blocked_list);
+ list_add(&newln->ln_alive_list, &curln->ln_alive_list);
+ ln_block_inc(dep, newln->ln_mode);
+
+ /* conflict, attach it on blocked list of curlk */
+ list_add_tail(&newln->ln_blocked_list, &curln->ln_blocked_list);
+ list_add(&newln->ln_alive_list, &curln->ln_alive_list);
+ ln_block_inc(dep, newln->ln_mode);
+
++retry:
++ set_current_state(TASK_UNINTERRUPTIBLE);
+ htree_spin_unlock(newlk->lk_head, dep);
+ /* wait to be given the lock */
+ if (newlk->lk_task != NULL)
+ schedule();
+ /* granted, no doubt, wake up will set me RUNNING */
+ htree_spin_unlock(newlk->lk_head, dep);
+ /* wait to be given the lock */
+ if (newlk->lk_task != NULL)
+ schedule();
+ /* granted, no doubt, wake up will set me RUNNING */
-+ if (event == NULL || htree_key_event_ignore(child, newln))
-+ return 0; /* granted without lh_lock */
-+
+ htree_spin_lock(newlk->lk_head, dep);
+ htree_spin_lock(newlk->lk_head, dep);
-+ htree_key_event_enqueue(child, newln, dep, event);
++ /* Need to check lock really granted, thread maybe awaken wrongly */
++ if (list_empty(&newln->ln_granted_list) && htree_key_list_empty(newln))
++ goto retry;
++ if (event && !htree_key_event_ignore(child, newln))
++ htree_key_event_enqueue(child, newln, dep, event);
++
+ return 1; /* still hold lh_lock */
+}
+
+ return 1; /* still hold lh_lock */
+}
+
+ return NULL;
+
+ if (hbits < HTREE_HBITS_MIN)
+ return NULL;
+
+ if (hbits < HTREE_HBITS_MIN)
-+ lhead->lh_hbits = HTREE_HBITS_MIN;
++ hbits = HTREE_HBITS_MIN;
+ else if (hbits > HTREE_HBITS_MAX)
+ else if (hbits > HTREE_HBITS_MAX)
-+ lhead->lh_hbits = HTREE_HBITS_MAX;
++ hbits = HTREE_HBITS_MAX;
++ lhead->lh_hbits = hbits;
+ lhead->lh_lock = 0;
+ lhead->lh_depth = depth;
+ INIT_LIST_HEAD(&lhead->lh_blocked_list);
+ lhead->lh_lock = 0;
+ lhead->lh_depth = depth;
+ INIT_LIST_HEAD(&lhead->lh_blocked_list);