]> git-server-git.apps.pok.os.sepia.ceph.com Git - ceph.git/commitdiff
librbd: use map-based stripe method to avoid fragmenting io
authorSage Weil <sage@inktank.com>
Mon, 8 Oct 2012 23:04:21 +0000 (16:04 -0700)
committerSage Weil <sage@inktank.com>
Mon, 15 Oct 2012 22:34:07 +0000 (15:34 -0700)
If we have multiple extents to read from the parent, accumulate the
resulting IO requests on a single map of ObjectExtents so that we can
merge adjacent IOs.  This helps with the copy-up when the parent and child
striping match, for example.

Signed-off-by: Sage Weil <sage@inktank.com>
src/librbd/internal.cc

index 713dc1b7af2c2ba2a54c6bb65267d4de4f8f7e30..857dcb0ba89db5aae98b64be66e011467af925fc 100644 (file)
@@ -2573,7 +2573,7 @@ reprotect_and_return_err:
     ictx->snap_lock.Unlock();
 
     // map
-    vector<ObjectExtent> extents;
+    map<object_t,vector<ObjectExtent> > object_extents;
 
     uint64_t buffer_ofs = 0;
     for (vector<pair<uint64_t,uint64_t> >::const_iterator p = image_extents.begin();
@@ -2584,7 +2584,7 @@ reprotect_and_return_err:
        return r;
       
       Striper::file_to_extents(ictx->cct, ictx->format_string, &ictx->layout,
-                            p->first, p->second, extents, buffer_ofs);
+                              p->first, p->second, object_extents, buffer_ofs);
       buffer_ofs += p->second;
     }
 
@@ -2596,36 +2596,38 @@ reprotect_and_return_err:
 
     c->get();
     c->init_time(ictx, AIO_TYPE_READ);
-    for (vector<ObjectExtent>::iterator p = extents.begin(); p != extents.end(); ++p) {
-      ldout(ictx->cct, 20) << " oid " << p->oid << " " << p->offset << "~" << p->length
-                          << " from " << p->buffer_extents << dendl;
-
-      C_AioRead *req_comp = new C_AioRead(ictx->cct, c);
-      AioRead *req = new AioRead(ictx, p->oid.name, 
-                                p->objectno, p->offset, p->length,
-                                p->buffer_extents,
-                                snap_id, true, req_comp);
-      req_comp->set_req(req);
-      c->add_request();
+    for (map<object_t,vector<ObjectExtent> >::iterator p = object_extents.begin(); p != object_extents.end(); ++p) {
+      for (vector<ObjectExtent>::iterator q = p->second.begin(); q != p->second.end(); ++q) {
+       ldout(ictx->cct, 20) << " oid " << q->oid << " " << q->offset << "~" << q->length
+                            << " from " << q->buffer_extents << dendl;
+
+       C_AioRead *req_comp = new C_AioRead(ictx->cct, c);
+       AioRead *req = new AioRead(ictx, q->oid.name, 
+                                  q->objectno, q->offset, q->length,
+                                  q->buffer_extents,
+                                  snap_id, true, req_comp);
+       req_comp->set_req(req);
+       c->add_request();
 
-      if (ictx->object_cacher) {
-       // cache has already handled possible reading from parent, so
-       // this AioRead is just used to pass data to the
-       // AioCompletion. The AioRead isn't being used as a
-       // completion, so wrap the completion in a C_CacheRead to
-       // delete it
-       C_CacheRead *cache_comp = new C_CacheRead(req_comp, req);
-       req->m_ext_map[p->offset] = p->length;
-       ictx->aio_read_from_cache(p->oid, &req->data(),
-                                 p->length, p->offset,
-                                 cache_comp);
-      } else {
-       r = req->send();
-       if (r < 0 && r == -ENOENT)
-         r = 0;
-       if (r < 0) {
-         ret = r;
-         goto done;
+       if (ictx->object_cacher) {
+         // cache has already handled possible reading from parent, so
+         // this AioRead is just used to pass data to the
+         // AioCompletion. The AioRead isn't being used as a
+         // completion, so wrap the completion in a C_CacheRead to
+         // delete it
+         C_CacheRead *cache_comp = new C_CacheRead(req_comp, req);
+         req->m_ext_map[q->offset] = q->length;
+         ictx->aio_read_from_cache(q->oid, &req->data(),
+                                   q->length, q->offset,
+                                   cache_comp);
+       } else {
+         r = req->send();
+         if (r < 0 && r == -ENOENT)
+           r = 0;
+         if (r < 0) {
+           ret = r;
+           goto done;
+         }
        }
       }
     }