]> git.ipfire.org Git - thirdparty/kernel/stable-queue.git/commitdiff
5.15-stable patches
authorGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Tue, 30 Jul 2024 10:59:17 +0000 (12:59 +0200)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Tue, 30 Jul 2024 10:59:17 +0000 (12:59 +0200)
added patches:
rbd-don-t-assume-rbd_lock_state_locked-for-exclusive-mappings.patch
rbd-rename-rbd_lock_state_releasing-and-releasing_wait.patch

queue-5.15/rbd-don-t-assume-rbd_lock_state_locked-for-exclusive-mappings.patch [new file with mode: 0644]
queue-5.15/rbd-rename-rbd_lock_state_releasing-and-releasing_wait.patch [new file with mode: 0644]
queue-5.15/series

diff --git a/queue-5.15/rbd-don-t-assume-rbd_lock_state_locked-for-exclusive-mappings.patch b/queue-5.15/rbd-don-t-assume-rbd_lock_state_locked-for-exclusive-mappings.patch
new file mode 100644 (file)
index 0000000..1ab7eb7
--- /dev/null
@@ -0,0 +1,74 @@
+From 2237ceb71f89837ac47c5dce2aaa2c2b3a337a3c Mon Sep 17 00:00:00 2001
+From: Ilya Dryomov <idryomov@gmail.com>
+Date: Tue, 23 Jul 2024 18:07:59 +0200
+Subject: rbd: don't assume RBD_LOCK_STATE_LOCKED for exclusive mappings
+
+From: Ilya Dryomov <idryomov@gmail.com>
+
+commit 2237ceb71f89837ac47c5dce2aaa2c2b3a337a3c upstream.
+
+Every time a watch is reestablished after getting lost, we need to
+update the cookie which involves quiescing exclusive lock.  For this,
+we transition from RBD_LOCK_STATE_LOCKED to RBD_LOCK_STATE_QUIESCING
+roughly for the duration of rbd_reacquire_lock() call.  If the mapping
+is exclusive and I/O happens to arrive in this time window, it's failed
+with EROFS (later translated to EIO) based on the wrong assumption in
+rbd_img_exclusive_lock() -- "lock got released?" check there stopped
+making sense with commit a2b1da09793d ("rbd: lock should be quiesced on
+reacquire").
+
+To make it worse, any such I/O is added to the acquiring list before
+EROFS is returned and this sets up for violating rbd_lock_del_request()
+precondition that the request is either on the running list or not on
+any list at all -- see commit ded080c86b3f ("rbd: don't move requests
+to the running list on errors").  rbd_lock_del_request() ends up
+processing these requests as if they were on the running list which
+screws up quiescing_wait completion counter and ultimately leads to
+
+    rbd_assert(!completion_done(&rbd_dev->quiescing_wait));
+
+being triggered on the next watch error.
+
+Cc: stable@vger.kernel.org # 06ef84c4e9c4: rbd: rename RBD_LOCK_STATE_RELEASING and releasing_wait
+Cc: stable@vger.kernel.org
+Fixes: 637cd060537d ("rbd: new exclusive lock wait/wake code")
+Signed-off-by: Ilya Dryomov <idryomov@gmail.com>
+Reviewed-by: Dongsheng Yang <dongsheng.yang@easystack.cn>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/block/rbd.c |   10 +++++-----
+ 1 file changed, 5 insertions(+), 5 deletions(-)
+
+--- a/drivers/block/rbd.c
++++ b/drivers/block/rbd.c
+@@ -3459,6 +3459,7 @@ static void rbd_lock_del_request(struct
+       lockdep_assert_held(&rbd_dev->lock_rwsem);
+       spin_lock(&rbd_dev->lock_lists_lock);
+       if (!list_empty(&img_req->lock_item)) {
++              rbd_assert(!list_empty(&rbd_dev->running_list));
+               list_del_init(&img_req->lock_item);
+               need_wakeup = (rbd_dev->lock_state == RBD_LOCK_STATE_QUIESCING &&
+                              list_empty(&rbd_dev->running_list));
+@@ -3478,11 +3479,6 @@ static int rbd_img_exclusive_lock(struct
+       if (rbd_lock_add_request(img_req))
+               return 1;
+-      if (rbd_dev->opts->exclusive) {
+-              WARN_ON(1); /* lock got released? */
+-              return -EROFS;
+-      }
+-
+       /*
+        * Note the use of mod_delayed_work() in rbd_acquire_lock()
+        * and cancel_delayed_work() in wake_lock_waiters().
+@@ -4603,6 +4599,10 @@ static void rbd_reacquire_lock(struct rb
+                       rbd_warn(rbd_dev, "failed to update lock cookie: %d",
+                                ret);
++              if (rbd_dev->opts->exclusive)
++                      rbd_warn(rbd_dev,
++                           "temporarily releasing lock on exclusive mapping");
++
+               /*
+                * Lock cookie cannot be updated on older OSDs, so do
+                * a manual release and queue an acquire.
diff --git a/queue-5.15/rbd-rename-rbd_lock_state_releasing-and-releasing_wait.patch b/queue-5.15/rbd-rename-rbd_lock_state_releasing-and-releasing_wait.patch
new file mode 100644 (file)
index 0000000..0af0a39
--- /dev/null
@@ -0,0 +1,98 @@
+From f5c466a0fdb2d9f3650d2e3911b0735f17ba00cf Mon Sep 17 00:00:00 2001
+From: Ilya Dryomov <idryomov@gmail.com>
+Date: Tue, 23 Jul 2024 17:54:39 +0200
+Subject: rbd: rename RBD_LOCK_STATE_RELEASING and releasing_wait
+
+From: Ilya Dryomov <idryomov@gmail.com>
+
+commit f5c466a0fdb2d9f3650d2e3911b0735f17ba00cf upstream.
+
+... to RBD_LOCK_STATE_QUIESCING and quiescing_wait to recognize that
+this state and the associated completion are backing rbd_quiesce_lock(),
+which isn't specific to releasing the lock.
+
+While exclusive lock does get quiesced before it's released, it also
+gets quiesced before an attempt to update the cookie is made and there
+the lock is not released as long as ceph_cls_set_cookie() succeeds.
+
+Signed-off-by: Ilya Dryomov <idryomov@gmail.com>
+Reviewed-by: Dongsheng Yang <dongsheng.yang@easystack.cn>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/block/rbd.c |   20 ++++++++++----------
+ 1 file changed, 10 insertions(+), 10 deletions(-)
+
+--- a/drivers/block/rbd.c
++++ b/drivers/block/rbd.c
+@@ -362,7 +362,7 @@ enum rbd_watch_state {
+ enum rbd_lock_state {
+       RBD_LOCK_STATE_UNLOCKED,
+       RBD_LOCK_STATE_LOCKED,
+-      RBD_LOCK_STATE_RELEASING,
++      RBD_LOCK_STATE_QUIESCING,
+ };
+ /* WatchNotify::ClientId */
+@@ -422,7 +422,7 @@ struct rbd_device {
+       struct list_head        running_list;
+       struct completion       acquire_wait;
+       int                     acquire_err;
+-      struct completion       releasing_wait;
++      struct completion       quiescing_wait;
+       spinlock_t              object_map_lock;
+       u8                      *object_map;
+@@ -525,7 +525,7 @@ static bool __rbd_is_lock_owner(struct r
+       lockdep_assert_held(&rbd_dev->lock_rwsem);
+       return rbd_dev->lock_state == RBD_LOCK_STATE_LOCKED ||
+-             rbd_dev->lock_state == RBD_LOCK_STATE_RELEASING;
++             rbd_dev->lock_state == RBD_LOCK_STATE_QUIESCING;
+ }
+ static bool rbd_is_lock_owner(struct rbd_device *rbd_dev)
+@@ -3460,12 +3460,12 @@ static void rbd_lock_del_request(struct
+       spin_lock(&rbd_dev->lock_lists_lock);
+       if (!list_empty(&img_req->lock_item)) {
+               list_del_init(&img_req->lock_item);
+-              need_wakeup = (rbd_dev->lock_state == RBD_LOCK_STATE_RELEASING &&
++              need_wakeup = (rbd_dev->lock_state == RBD_LOCK_STATE_QUIESCING &&
+                              list_empty(&rbd_dev->running_list));
+       }
+       spin_unlock(&rbd_dev->lock_lists_lock);
+       if (need_wakeup)
+-              complete(&rbd_dev->releasing_wait);
++              complete(&rbd_dev->quiescing_wait);
+ }
+ static int rbd_img_exclusive_lock(struct rbd_img_request *img_req)
+@@ -4183,16 +4183,16 @@ static bool rbd_quiesce_lock(struct rbd_
+       /*
+        * Ensure that all in-flight IO is flushed.
+        */
+-      rbd_dev->lock_state = RBD_LOCK_STATE_RELEASING;
+-      rbd_assert(!completion_done(&rbd_dev->releasing_wait));
++      rbd_dev->lock_state = RBD_LOCK_STATE_QUIESCING;
++      rbd_assert(!completion_done(&rbd_dev->quiescing_wait));
+       if (list_empty(&rbd_dev->running_list))
+               return true;
+       up_write(&rbd_dev->lock_rwsem);
+-      wait_for_completion(&rbd_dev->releasing_wait);
++      wait_for_completion(&rbd_dev->quiescing_wait);
+       down_write(&rbd_dev->lock_rwsem);
+-      if (rbd_dev->lock_state != RBD_LOCK_STATE_RELEASING)
++      if (rbd_dev->lock_state != RBD_LOCK_STATE_QUIESCING)
+               return false;
+       rbd_assert(list_empty(&rbd_dev->running_list));
+@@ -5387,7 +5387,7 @@ static struct rbd_device *__rbd_dev_crea
+       INIT_LIST_HEAD(&rbd_dev->acquiring_list);
+       INIT_LIST_HEAD(&rbd_dev->running_list);
+       init_completion(&rbd_dev->acquire_wait);
+-      init_completion(&rbd_dev->releasing_wait);
++      init_completion(&rbd_dev->quiescing_wait);
+       spin_lock_init(&rbd_dev->object_map_lock);
index 4349b2ad08ef9728779ee01488e5f684a5161639..dc9362600ec343b3d3bc4d75134ff6fc48aa20f8 100644 (file)
@@ -251,3 +251,5 @@ mips-loongson64-remove-memory-node-for-builtin-dtb.patch
 mips-loongson64-reset-prioritise-firmware-service.patch
 mips-loongson64-test-register-availability-before-use.patch
 drm-panfrost-mark-simple_ondemand-governor-as-softdep.patch
+rbd-rename-rbd_lock_state_releasing-and-releasing_wait.patch
+rbd-don-t-assume-rbd_lock_state_locked-for-exclusive-mappings.patch