]> git.apps.os.sepia.ceph.com Git - ceph.git/commitdiff
librbd: prevent concurrent image refreshes
authorJason Dillaman <dillaman@redhat.com>
Tue, 14 Jul 2015 13:06:59 +0000 (09:06 -0400)
committerJason Dillaman <dillaman@redhat.com>
Fri, 13 Nov 2015 01:17:54 +0000 (20:17 -0500)
With multiple concurrent AIO requests, it's possible for multiple
image refreshes to be scheduled.

Signed-off-by: Jason Dillaman <dillaman@redhat.com>
src/librbd/ImageCtx.cc
src/librbd/ImageCtx.h
src/librbd/internal.cc

index f371658d757223cade00962487a90cfc6d2de20a..d93e149b24a827b8073d1049b9fc2161ff4590bd 100644 (file)
@@ -88,7 +88,7 @@ public:
       readahead(),
       total_bytes_read(0), copyup_finisher(NULL),
       object_map(*this), aio_work_queue(NULL), op_work_queue(NULL),
-      asok_hook(new LibrbdAdminSocketHook(this))
+      refresh_in_progress(false), asok_hook(new LibrbdAdminSocketHook(this))
   {
     md_ctx.dup(p);
     data_ctx.dup(p);
index 4fd1112e112d992ef6c09842744c08ea797fda1c..9e21e45493c32946dc810255768b5216170ced13 100644 (file)
@@ -136,6 +136,9 @@ namespace librbd {
     AioImageRequestWQ *aio_work_queue;
     ContextWQ *op_work_queue;
 
+    Cond refresh_cond;
+    bool refresh_in_progress;
+
     // Configuration
     static const string METADATA_CONF_PREFIX;
     bool non_blocking_aio;
index a0c76070737da042281ebaf0976624542b6274f2..763cee170dad00b6129506ef9ccea0dc7968fd18 100644 (file)
@@ -2463,17 +2463,34 @@ reprotect_and_return_err:
     CephContext *cct = ictx->cct;
     ldout(cct, 20) << "ictx_check " << ictx << dendl;
 
-    ictx->refresh_lock.Lock();
-    bool needs_refresh = ictx->last_refresh != ictx->refresh_seq;
-    ictx->refresh_lock.Unlock();
+    bool needs_refresh = false;
+    int refresh_seq;
+    {
+      Mutex::Locker refresh_locker(ictx->refresh_lock);
+      while (ictx->refresh_in_progress) {
+        ictx->refresh_cond.Wait(ictx->refresh_lock);
+      }
+
+      if (ictx->last_refresh != ictx->refresh_seq) {
+        ictx->refresh_in_progress = true;
+        needs_refresh = true;
+        refresh_seq = ictx->refresh_seq;
+      }
+    }
 
     if (needs_refresh) {
       int r = ictx_refresh(ictx);
+
+      Mutex::Locker refresh_locker(ictx->refresh_lock);
+      ictx->refresh_in_progress = false;
+      ictx->refresh_cond.Signal();
+
       if (r < 0) {
        lderr(cct) << "Error re-reading rbd header: " << cpp_strerror(-r)
                   << dendl;
         return r;
       }
+      ictx->last_refresh = refresh_seq;
     }
     return 0;
   }
@@ -2524,10 +2541,6 @@ reprotect_and_return_err:
 
     ldout(cct, 20) << "ictx_refresh " << ictx << dendl;
 
-    ictx->refresh_lock.Lock();
-    int refresh_seq = ictx->refresh_seq;
-    ictx->refresh_lock.Unlock();
-
     ::SnapContext new_snapc;
     bool new_snap = false;
     vector<string> snap_names;
@@ -2701,11 +2714,6 @@ reprotect_and_return_err:
     if (new_snap) {
       _flush(ictx);
     }
-
-    ictx->refresh_lock.Lock();
-    ictx->last_refresh = refresh_seq;
-    ictx->refresh_lock.Unlock();
-
     return 0;
   }