]> git-server-git.apps.pok.os.sepia.ceph.com Git - ceph.git/commitdiff
mgr/rbd_support: fix recursive locking on CreateSnapshotRequests lock
authorRamana Raja <rraja@redhat.com>
Thu, 26 Oct 2023 17:18:52 +0000 (13:18 -0400)
committerRamana Raja <rraja@redhat.com>
Wed, 1 Nov 2023 12:47:50 +0000 (08:47 -0400)
The MirrorSnapshotScheduleHandler's run thread issues asynchronous
create snapshot requests using a CreateSnapshotRequests instance. When
the thread invokes a CreateSnapshotRequests instance's get_ioctx(),
the instance's class variable lock is acquired. With the class
variable lock held, the garbage collection of a CreateSnapshotRequests
instance may race in the thread. The thread would then call
CreateSnapshotRequests __del__() that tries to acquire the class
variable lock that the thread already holds. Fix this
recursive deadlock by converting the CreateSnapshotRequests lock from
a class variable to an instance variable. There is no need to share
the lock across CreateSnapshotRequests instances.

Also convert MirrorSnapshotScheduleHandler, PerfHandler and
TrashPurgeScheduleHandler class variables to instance variables
that don't need to be shared across the instances.

Fixes: https://tracker.ceph.com/issues/62994
Signed-off-by: Ramana Raja <rraja@redhat.com>
Co-Authored-By: Ilya Dryomov <idryomov@gmail.com>
(cherry picked from commit 4452bc22d1c6c8499cf55d6e39090adf7ae1dcbf)

src/pybind/mgr/rbd_support/mirror_snapshot_schedule.py
src/pybind/mgr/rbd_support/perf.py
src/pybind/mgr/rbd_support/trash_purge_schedule.py

index b502ebbe34bfe268c340d4a06d317b406f5b34fa..58cb3ce9e1fc855e6c8f666df649bb758aef981f 100644 (file)
@@ -32,10 +32,9 @@ class ImageSpec(NamedTuple):
 
 class CreateSnapshotRequests:
 
-    lock = Lock()
-    condition = Condition(lock)
-
     def __init__(self, handler: Any) -> None:
+        self.lock = Lock()
+        self.condition = Condition(self.lock)
         self.handler = handler
         self.rados = handler.module.rados
         self.log = handler.log
@@ -332,10 +331,9 @@ class MirrorSnapshotScheduleHandler:
     SCHEDULE_OID = "rbd_mirror_snapshot_schedule"
     REFRESH_DELAY_SECONDS = 60.0
 
-    lock = Lock()
-    condition = Condition(lock)
-
     def __init__(self, module: Any) -> None:
+        self.lock = Lock()
+        self.condition = Condition(self.lock)
         self.module = module
         self.log = module.log
         self.last_refresh_images = datetime(1970, 1, 1)
index 68cbbd3b5f48b42fa0fd61f4f05ae327965744df..20815721de50ff9d6913d9968b54661f033aef78 100644 (file)
@@ -65,15 +65,6 @@ ExtractDataFuncT = Callable[[int, Optional[RawImageCounterT], SumImageCounterT],
 
 
 class PerfHandler:
-    user_queries: Dict[PoolKeyT, Dict[str, Any]] = {}
-    image_cache: Dict[str, str] = {}
-
-    lock = Lock()
-    query_condition = Condition(lock)
-    refresh_condition = Condition(lock)
-
-    image_name_cache: Dict[Tuple[int, str], Dict[str, str]] = {}
-    image_name_refresh_time = datetime.fromtimestamp(0)
 
     @classmethod
     def prepare_regex(cls, value: Any) -> str:
@@ -114,6 +105,16 @@ class PerfHandler:
                 and (pool_key[0] == search_key[0] or not search_key[0]))
 
     def __init__(self, module: Any) -> None:
+        self.user_queries: Dict[PoolKeyT, Dict[str, Any]] = {}
+        self.image_cache: Dict[str, str] = {}
+
+        self.lock = Lock()
+        self.query_condition = Condition(self.lock)
+        self.refresh_condition = Condition(self.lock)
+
+        self.image_name_cache: Dict[Tuple[int, str], Dict[str, str]] = {}
+        self.image_name_refresh_time = datetime.fromtimestamp(0)
+
         self.module = module
         self.log = module.log
 
index b5ff9f125ab0e054b051be6f37bbafa028fecae2..ad599af3b4c0fa53f2b61d88bbd7fa49b8dced49 100644 (file)
@@ -18,10 +18,9 @@ class TrashPurgeScheduleHandler:
     SCHEDULE_OID = "rbd_trash_purge_schedule"
     REFRESH_DELAY_SECONDS = 60.0
 
-    lock = Lock()
-    condition = Condition(lock)
-
     def __init__(self, module: Any) -> None:
+        self.lock = Lock()
+        self.condition = Condition(self.lock)
         self.module = module
         self.log = module.log
         self.last_refresh_pools = datetime(1970, 1, 1)