Whamcloud - gitweb
LU-13054 ldiskfs: htree_node wrongly granted 71/38371/4
authorYang Sheng <ys@whamcloud.com>
Sun, 26 Apr 2020 11:56:40 +0000 (19:56 +0800)
committerOleg Drokin <green@whamcloud.com>
Thu, 14 May 2020 05:38:53 +0000 (05:38 +0000)
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>
ldiskfs/kernel_patches/patches/rhel7.7/ext4-pdirop.patch

index 422d7e7..0ae29c9 100644 (file)
@@ -210,7 +210,7 @@ Index: 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
 ===================================================================
 --- /dev/null
 +++ linux-3.10.0-229.1.2.fc21.x86_64/fs/ext4/htree_lock.c
-@@ -0,0 +1,891 @@
+@@ -0,0 +1,895 @@
 +/*
 + * fs/ext4/htree_lock.c
 + *
 +/*
 + * fs/ext4/htree_lock.c
 + *
@@ -436,22 +436,25 @@ Index: linux-3.10.0-229.1.2.fc21.x86_64/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 */
 +}
 +
@@ -1012,10 +1015,11 @@ Index: linux-3.10.0-229.1.2.fc21.x86_64/fs/ext4/htree_lock.c
 +              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);