From 892f62c7a20d87954744c6c8937960379a870992 Mon Sep 17 00:00:00 2001 From: Yang Sheng Date: Fri, 1 Feb 2019 13:04:10 +0800 Subject: [PATCH 1/1] LU-11851 ldiskfs: reschedule for htree thread. Thread may be waken inproperly in htree code. This patch reschedule thread to keep locking correct. Change-Id: I6a8d1bbc0470b2577ca80faa304eb06f7913c218 Signed-off-by: Yang Sheng Reviewed-on: https://review.whamcloud.com/34160 Reviewed-by: Andreas Dilger Tested-by: Jenkins Reviewed-by: Wang Shilong Tested-by: Maloo Reviewed-by: Oleg Drokin --- .../kernel_patches/patches/rhel6.9/ext4-pdirop.patch | 15 +++++++++++++-- .../kernel_patches/patches/rhel7.4/ext4-pdirop.patch | 17 ++++++++++++++--- ldiskfs/kernel_patches/patches/sles12/ext4-pdirop.patch | 15 +++++++++++++-- .../kernel_patches/patches/sles12sp2/ext4-pdirop.patch | 15 +++++++++++++-- .../kernel_patches/patches/sles12sp3/ext4-pdirop.patch | 15 +++++++++++++-- .../patches/ubuntu14+16/ext4-pdirop-001.patch | 15 +++++++++++++-- .../patches/ubuntu14+16/ext4-pdirop.patch | 15 +++++++++++++-- .../kernel_patches/patches/ubuntu18/ext4-pdirop.patch | 15 +++++++++++++-- 8 files changed, 105 insertions(+), 17 deletions(-) diff --git a/ldiskfs/kernel_patches/patches/rhel6.9/ext4-pdirop.patch b/ldiskfs/kernel_patches/patches/rhel6.9/ext4-pdirop.patch index 581236e..b5fc2bb 100644 --- a/ldiskfs/kernel_patches/patches/rhel6.9/ext4-pdirop.patch +++ b/ldiskfs/kernel_patches/patches/rhel6.9/ext4-pdirop.patch @@ -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]++; diff --git a/ldiskfs/kernel_patches/patches/rhel7.4/ext4-pdirop.patch b/ldiskfs/kernel_patches/patches/rhel7.4/ext4-pdirop.patch index 72788c8..910a495 100644 --- a/ldiskfs/kernel_patches/patches/rhel7.4/ext4-pdirop.patch +++ b/ldiskfs/kernel_patches/patches/rhel7.4/ext4-pdirop.patch @@ -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]++; diff --git a/ldiskfs/kernel_patches/patches/sles12/ext4-pdirop.patch b/ldiskfs/kernel_patches/patches/sles12/ext4-pdirop.patch index 9476d2c..556453d 100644 --- a/ldiskfs/kernel_patches/patches/sles12/ext4-pdirop.patch +++ b/ldiskfs/kernel_patches/patches/sles12/ext4-pdirop.patch @@ -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]++; diff --git a/ldiskfs/kernel_patches/patches/sles12sp2/ext4-pdirop.patch b/ldiskfs/kernel_patches/patches/sles12sp2/ext4-pdirop.patch index 4090c03..d852f1d 100644 --- a/ldiskfs/kernel_patches/patches/sles12sp2/ext4-pdirop.patch +++ b/ldiskfs/kernel_patches/patches/sles12sp2/ext4-pdirop.patch @@ -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]++; diff --git a/ldiskfs/kernel_patches/patches/sles12sp3/ext4-pdirop.patch b/ldiskfs/kernel_patches/patches/sles12sp3/ext4-pdirop.patch index 9572de8..b48a22c 100644 --- a/ldiskfs/kernel_patches/patches/sles12sp3/ext4-pdirop.patch +++ b/ldiskfs/kernel_patches/patches/sles12sp3/ext4-pdirop.patch @@ -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]++; diff --git a/ldiskfs/kernel_patches/patches/ubuntu14+16/ext4-pdirop-001.patch b/ldiskfs/kernel_patches/patches/ubuntu14+16/ext4-pdirop-001.patch index aa0bf6e..e111d4b 100644 --- a/ldiskfs/kernel_patches/patches/ubuntu14+16/ext4-pdirop-001.patch +++ b/ldiskfs/kernel_patches/patches/ubuntu14+16/ext4-pdirop-001.patch @@ -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]++; diff --git a/ldiskfs/kernel_patches/patches/ubuntu14+16/ext4-pdirop.patch b/ldiskfs/kernel_patches/patches/ubuntu14+16/ext4-pdirop.patch index 71b2738..81ee180 100644 --- a/ldiskfs/kernel_patches/patches/ubuntu14+16/ext4-pdirop.patch +++ b/ldiskfs/kernel_patches/patches/ubuntu14+16/ext4-pdirop.patch @@ -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]++; diff --git a/ldiskfs/kernel_patches/patches/ubuntu18/ext4-pdirop.patch b/ldiskfs/kernel_patches/patches/ubuntu18/ext4-pdirop.patch index 4f93d37..8d2df2d 100644 --- a/ldiskfs/kernel_patches/patches/ubuntu18/ext4-pdirop.patch +++ b/ldiskfs/kernel_patches/patches/ubuntu18/ext4-pdirop.patch @@ -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]++; -- 1.8.3.1