Whamcloud - gitweb
LU-11851 ldiskfs: reschedule for htree thread. 06/35006/2
authorYang Sheng <ys@whamcloud.com>
Fri, 1 Feb 2019 05:04:10 +0000 (13:04 +0800)
committerOleg Drokin <green@whamcloud.com>
Sat, 8 Jun 2019 02:37:50 +0000 (02:37 +0000)
Thread may be waken inproperly in htree code. This patch
reschedule thread to keep locking correct.

Lustre-change: https://review.whamcloud.com/34160
Lustre-commit: 892f62c7a20d87954744c6c8937960379a870992

Change-Id: I6a8d1bbc0470b2577ca80faa304eb06f7913c218
Signed-off-by: Yang Sheng <ys@whamcloud.com>
Reviewed-by: Andreas Dilger <adilger@whamcloud.com>
Reviewed-by: Wang Shilong <wshilong@ddn.com>
Signed-off-by: Minh Diep <mdiep@whamcloud.com>
Reviewed-on: https://review.whamcloud.com/35006
Tested-by: Jenkins
Tested-by: Maloo <maloo@whamcloud.com>
ldiskfs/kernel_patches/patches/rhel6.9/ext4-pdirop.patch
ldiskfs/kernel_patches/patches/rhel7.4/ext4-pdirop.patch
ldiskfs/kernel_patches/patches/sles12/ext4-pdirop.patch
ldiskfs/kernel_patches/patches/sles12sp2/ext4-pdirop.patch
ldiskfs/kernel_patches/patches/sles12sp3/ext4-pdirop.patch
ldiskfs/kernel_patches/patches/ubuntu14+16/ext4-pdirop-001.patch
ldiskfs/kernel_patches/patches/ubuntu14+16/ext4-pdirop.patch
ldiskfs/kernel_patches/patches/ubuntu18/ext4-pdirop.patch

index 581236e..b5fc2bb 100644 (file)
@@ -194,7 +194,7 @@ Index: linux-2.6.32-504.3.3.el6.x86_64/fs/ext4/htree_lock.c
 ===================================================================
 --- /dev/null
 +++ linux-2.6.32-504.3.3.el6.x86_64/fs/ext4/htree_lock.c
-@@ -0,0 +1,880 @@
+@@ -0,0 +1,891 @@
 +/*
 + * fs/ext4/htree_lock.c
 + *
@@ -836,12 +836,23 @@ Index: linux-2.6.32-504.3.3.el6.x86_64/fs/ext4/htree_lock.c
 +              lck->lk_task = current;
 +              list_add_tail(&lck->lk_blocked_list, &lhead->lh_blocked_list);
 +
++retry:
 +              set_current_state(TASK_UNINTERRUPTIBLE);
 +              htree_spin_unlock(lhead, HTREE_DEP_ROOT);
 +              /* wait to be given the lock */
 +              if (lck->lk_task != NULL)
 +                      schedule();
-+              /* granted, no doubt. wake up will set me RUNNING */
++              /* granted, no doubt. wake up will set me RUNNING.
++               * Since thread would be waken up accidentally,
++               * so we need check lock whether granted or not again. */
++              if (!list_empty(&lck->lk_blocked_list)) {
++                      htree_spin_lock(lhead, HTREE_DEP_ROOT);
++                      if (list_empty(&lck->lk_blocked_list)) {
++                              htree_spin_unlock(lhead, HTREE_DEP_ROOT);
++                              return 0;
++                      }
++                      goto retry;
++              }
 +              return 0; /* without lh_lock */
 +      }
 +      lhead->lh_ngranted[lck->lk_mode]++;
index 53428bd..d593221 100644 (file)
@@ -9,7 +9,7 @@ an entire ldiskfs directory. PDO project will remove this
 bottleneck by introducing a parallel locking mechanism for entire
 ldiskfs directories. This work will enable multiple application
 threads to simultaneously lookup, create and unlink in parallel.
-    
+
 This patch contains:
  - pdirops support for ldiskfs
  - integrate with osd-ldiskfs
@@ -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
-@@ -0,0 +1,880 @@
+@@ -0,0 +1,891 @@
 +/*
 + * fs/ext4/htree_lock.c
 + *
@@ -852,12 +852,23 @@ Index: linux-3.10.0-229.1.2.fc21.x86_64/fs/ext4/htree_lock.c
 +              lck->lk_task = current;
 +              list_add_tail(&lck->lk_blocked_list, &lhead->lh_blocked_list);
 +
++retry:
 +              set_current_state(TASK_UNINTERRUPTIBLE);
 +              htree_spin_unlock(lhead, HTREE_DEP_ROOT);
 +              /* wait to be given the lock */
 +              if (lck->lk_task != NULL)
 +                      schedule();
-+              /* granted, no doubt. wake up will set me RUNNING */
++              /* granted, no doubt. wake up will set me RUNNING.
++               * Since thread would be waken up accidentally,
++               * so we need check lock whether granted or not again. */
++              if (!list_empty(&lck->lk_blocked_list)) {
++                      htree_spin_lock(lhead, HTREE_DEP_ROOT);
++                      if (list_empty(&lck->lk_blocked_list)) {
++                              htree_spin_unlock(lhead, HTREE_DEP_ROOT);
++                              return 0;
++                      }
++                      goto retry;
++              }
 +              return 0; /* without lh_lock */
 +      }
 +      lhead->lh_ngranted[lck->lk_mode]++;
index 6ae7e71..6f00c31 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
-@@ -0,0 +1,880 @@
+@@ -0,0 +1,891 @@
 +/*
 + * fs/ext4/htree_lock.c
 + *
@@ -852,12 +852,23 @@ Index: linux-3.10.0-229.1.2.fc21.x86_64/fs/ext4/htree_lock.c
 +              lck->lk_task = current;
 +              list_add_tail(&lck->lk_blocked_list, &lhead->lh_blocked_list);
 +
++retry:
 +              set_current_state(TASK_UNINTERRUPTIBLE);
 +              htree_spin_unlock(lhead, HTREE_DEP_ROOT);
 +              /* wait to be given the lock */
 +              if (lck->lk_task != NULL)
 +                      schedule();
-+              /* granted, no doubt. wake up will set me RUNNING */
++              /* granted, no doubt. wake up will set me RUNNING.
++               * Since thread would be waken up accidentally,
++               * so we need check lock whether granted or not again. */
++              if (!list_empty(&lck->lk_blocked_list)) {
++                      htree_spin_lock(lhead, HTREE_DEP_ROOT);
++                      if (list_empty(&lck->lk_blocked_list)) {
++                              htree_spin_unlock(lhead, HTREE_DEP_ROOT);
++                              return 0;
++                      }
++                      goto retry;
++              }
 +              return 0; /* without lh_lock */
 +      }
 +      lhead->lh_ngranted[lck->lk_mode]++;
index b757ba4..44177b4 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
-@@ -0,0 +1,880 @@
+@@ -0,0 +1,891 @@
 +/*
 + * fs/ext4/htree_lock.c
 + *
@@ -852,12 +852,23 @@ Index: linux-3.10.0-229.1.2.fc21.x86_64/fs/ext4/htree_lock.c
 +              lck->lk_task = current;
 +              list_add_tail(&lck->lk_blocked_list, &lhead->lh_blocked_list);
 +
++retry:
 +              set_current_state(TASK_UNINTERRUPTIBLE);
 +              htree_spin_unlock(lhead, HTREE_DEP_ROOT);
 +              /* wait to be given the lock */
 +              if (lck->lk_task != NULL)
 +                      schedule();
-+              /* granted, no doubt. wake up will set me RUNNING */
++              /* granted, no doubt. wake up will set me RUNNING.
++               * Since thread would be waken up accidentally,
++               * so we need check lock whether granted or not again. */
++              if (!list_empty(&lck->lk_blocked_list)) {
++                      htree_spin_lock(lhead, HTREE_DEP_ROOT);
++                      if (list_empty(&lck->lk_blocked_list)) {
++                              htree_spin_unlock(lhead, HTREE_DEP_ROOT);
++                              return 0;
++                      }
++                      goto retry;
++              }
 +              return 0; /* without lh_lock */
 +      }
 +      lhead->lh_ngranted[lck->lk_mode]++;
index a7480f5..73aa9ee 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
-@@ -0,0 +1,880 @@
+@@ -0,0 +1,891 @@
 +/*
 + * fs/ext4/htree_lock.c
 + *
@@ -852,12 +852,23 @@ Index: linux-3.10.0-229.1.2.fc21.x86_64/fs/ext4/htree_lock.c
 +              lck->lk_task = current;
 +              list_add_tail(&lck->lk_blocked_list, &lhead->lh_blocked_list);
 +
++retry:
 +              set_current_state(TASK_UNINTERRUPTIBLE);
 +              htree_spin_unlock(lhead, HTREE_DEP_ROOT);
 +              /* wait to be given the lock */
 +              if (lck->lk_task != NULL)
 +                      schedule();
-+              /* granted, no doubt. wake up will set me RUNNING */
++              /* granted, no doubt. wake up will set me RUNNING.
++               * Since thread would be waken up accidentally,
++               * so we need check lock whether granted or not again. */
++              if (!list_empty(&lck->lk_blocked_list)) {
++                      htree_spin_lock(lhead, HTREE_DEP_ROOT);
++                      if (list_empty(&lck->lk_blocked_list)) {
++                              htree_spin_unlock(lhead, HTREE_DEP_ROOT);
++                              return 0;
++                      }
++                      goto retry;
++              }
 +              return 0; /* without lh_lock */
 +      }
 +      lhead->lh_ngranted[lck->lk_mode]++;
index ad8800f..3089abd 100644 (file)
@@ -126,7 +126,7 @@ new file mode 100644
 index 0000000..99e7375
 --- /dev/null
 +++ b/fs/ext4/htree_lock.c
-@@ -0,0 +1,880 @@
+@@ -0,0 +1,891 @@
 +/*
 + * fs/ext4/htree_lock.c
 + *
@@ -768,12 +768,23 @@ index 0000000..99e7375
 +              lck->lk_task = current;
 +              list_add_tail(&lck->lk_blocked_list, &lhead->lh_blocked_list);
 +
++retry:
 +              set_current_state(TASK_UNINTERRUPTIBLE);
 +              htree_spin_unlock(lhead, HTREE_DEP_ROOT);
 +              /* wait to be given the lock */
 +              if (lck->lk_task != NULL)
 +                      schedule();
-+              /* granted, no doubt. wake up will set me RUNNING */
++              /* granted, no doubt. wake up will set me RUNNING.
++               * Since thread would be waken up accidentally,
++               * so we need check lock whether granted or not again. */
++              if (!list_empty(&lck->lk_blocked_list)) {
++                      htree_spin_lock(lhead, HTREE_DEP_ROOT);
++                      if (list_empty(&lck->lk_blocked_list)) {
++                              htree_spin_unlock(lhead, HTREE_DEP_ROOT);
++                              return 0;
++                      }
++                      goto retry;
++              }
 +              return 0; /* without lh_lock */
 +      }
 +      lhead->lh_ngranted[lck->lk_mode]++;
index 508e396..408f56e 100644 (file)
@@ -126,7 +126,7 @@ new file mode 100644
 index 0000000..99e7375
 --- /dev/null
 +++ b/fs/ext4/htree_lock.c
-@@ -0,0 +1,880 @@
+@@ -0,0 +1,891 @@
 +/*
 + * fs/ext4/htree_lock.c
 + *
@@ -768,12 +768,23 @@ index 0000000..99e7375
 +              lck->lk_task = current;
 +              list_add_tail(&lck->lk_blocked_list, &lhead->lh_blocked_list);
 +
++retry:
 +              set_current_state(TASK_UNINTERRUPTIBLE);
 +              htree_spin_unlock(lhead, HTREE_DEP_ROOT);
 +              /* wait to be given the lock */
 +              if (lck->lk_task != NULL)
 +                      schedule();
-+              /* granted, no doubt. wake up will set me RUNNING */
++              /* granted, no doubt. wake up will set me RUNNING.
++               * Since thread would be waken up accidentally,
++               * so we need check lock whether granted or not again. */
++              if (!list_empty(&lck->lk_blocked_list)) {
++                      htree_spin_lock(lhead, HTREE_DEP_ROOT);
++                      if (list_empty(&lck->lk_blocked_list)) {
++                              htree_spin_unlock(lhead, HTREE_DEP_ROOT);
++                              return 0;
++                      }
++                      goto retry;
++              }
 +              return 0; /* without lh_lock */
 +      }
 +      lhead->lh_ngranted[lck->lk_mode]++;
index 4f93d37..8d2df2d 100644 (file)
@@ -142,7 +142,7 @@ Index: linux-4.15.0/fs/ext4/htree_lock.c
 ===================================================================
 --- /dev/null
 +++ linux-4.15.0/fs/ext4/htree_lock.c
-@@ -0,0 +1,880 @@
+@@ -0,0 +1,891 @@
 +/*
 + * fs/ext4/htree_lock.c
 + *
@@ -784,12 +784,23 @@ Index: linux-4.15.0/fs/ext4/htree_lock.c
 +              lck->lk_task = current;
 +              list_add_tail(&lck->lk_blocked_list, &lhead->lh_blocked_list);
 +
++retry:
 +              set_current_state(TASK_UNINTERRUPTIBLE);
 +              htree_spin_unlock(lhead, HTREE_DEP_ROOT);
 +              /* wait to be given the lock */
 +              if (lck->lk_task != NULL)
 +                      schedule();
-+              /* granted, no doubt. wake up will set me RUNNING */
++              /* granted, no doubt. wake up will set me RUNNING.
++               * Since thread would be waken up accidentally,
++               * so we need check lock whether granted or not again. */
++              if (!list_empty(&lck->lk_blocked_list)) {
++                      htree_spin_lock(lhead, HTREE_DEP_ROOT);
++                      if (list_empty(&lck->lk_blocked_list)) {
++                              htree_spin_unlock(lhead, HTREE_DEP_ROOT);
++                              return 0;
++                      }
++                      goto retry;
++              }
 +              return 0; /* without lh_lock */
 +      }
 +      lhead->lh_ngranted[lck->lk_mode]++;