]> git-server-git.apps.pok.os.sepia.ceph.com Git - ceph.git/commitdiff
librbd: clip requests past end-of-image.
authorDan Mick <dan.mick@inktank.com>
Tue, 23 Oct 2012 04:15:51 +0000 (21:15 -0700)
committerDan Mick <dan.mick@inktank.com>
Sat, 27 Oct 2012 03:35:45 +0000 (20:35 -0700)
Rename check_io to clip_io, which can modify the passed-in length
to clamp it to the device size.  This is expected behavior for
block-device emulation.

Call clip_io in rbd_write(); need to return clipped length there,
even though aio_write() is calling clip_io() as well (for the
direct path).

Signed-off-by: Dan Mick <dan.mick@inktank.com>
Reviewed-by: Josh Durgin <josh.durgin@inktank.com>
src/librbd/internal.cc
src/librbd/internal.h
src/test/test_librbd.cc

index 982d147e69294c2813f66ef3c9356518a4de9708..ac4116f2bb9febaefbeb57cef6fb424040b80047 100644 (file)
@@ -2097,7 +2097,7 @@ reprotect_and_return_err:
     if (r < 0)
       return r;
 
-    r = check_io(ictx, off, len);
+    r = clip_io(ictx, off, &len);
     if (r < 0)
       return r;
 
@@ -2204,9 +2204,13 @@ reprotect_and_return_err:
     bool done;
     int ret;
 
+    int r = clip_io(ictx, off, &len);
+    if (r < 0)
+      return r;
+
     Context *ctx = new C_SafeCond(&mylock, &cond, &done, &ret);
     AioCompletion *c = aio_create_completion_internal(ctx, rbd_ctx_cb);
-    int r = aio_write(ictx, off, len, buf, c);
+    r = aio_write(ictx, off, len, buf, c);
     if (r < 0) {
       c->release();
       delete ctx;
@@ -2333,7 +2337,8 @@ reprotect_and_return_err:
     req->complete(rados_aio_get_return_value(c));
   }
 
-  int check_io(ImageCtx *ictx, uint64_t off, uint64_t len)
+  // validate extent against image size; clip to image size if necessary
+  int clip_io(ImageCtx *ictx, uint64_t off, uint64_t *len)
   {
     ictx->md_lock.Lock();
     ictx->snap_lock.Lock();
@@ -2345,8 +2350,14 @@ reprotect_and_return_err:
     if (!snap_exists)
       return -ENOENT;
 
-    if ((uint64_t)(off + len) > image_size)
+    // can't start past end
+    if (off >= image_size)
       return -EINVAL;
+
+    // clip requests that extend past end to just end
+    if ((off + *len) > image_size)
+      *len = image_size - off;
+
     return 0;
   }
 
@@ -2393,7 +2404,7 @@ reprotect_and_return_err:
     if (r < 0)
       return r;
 
-    r = check_io(ictx, off, len);
+    r = clip_io(ictx, off, &len);
     if (r < 0)
       return r;
 
@@ -2477,7 +2488,7 @@ reprotect_and_return_err:
     if (r < 0)
       return r;
 
-    r = check_io(ictx, off, len);
+    r = clip_io(ictx, off, &len);
     if (r < 0)
       return r;
 
@@ -2581,13 +2592,14 @@ reprotect_and_return_err:
     for (vector<pair<uint64_t,uint64_t> >::const_iterator p = image_extents.begin();
         p != image_extents.end();
         ++p) {
-      r = check_io(ictx, p->first, p->second);
+      size_t len = p->second;
+      r = clip_io(ictx, p->first, &len);
       if (r < 0)
        return r;
-      
+
       Striper::file_to_extents(ictx->cct, ictx->format_string, &ictx->layout,
-                              p->first, p->second, object_extents, buffer_ofs);
-      buffer_ofs += p->second;
+                              p->first, len, object_extents, buffer_ofs);
+      buffer_ofs += len;
     }
 
     int64_t ret;
index 566b0108fd384b0e7ceb57666b3ca0c9da7ac2d4..d8ca74d67082c8b4ac107dda54a9e97575f5e47e 100644 (file)
@@ -157,7 +157,7 @@ namespace librbd {
   std::string get_block_oid(const std::string &object_prefix, uint64_t num,
                            bool old_format);
   uint64_t oid_to_object_no(const string& oid, const string& object_prefix);
-  int check_io(ImageCtx *ictx, uint64_t off, uint64_t len);
+  int clip_io(ImageCtx *ictx, uint64_t off, uint64_t *len);
   int init_rbd_info(struct rbd_info *info);
   void init_rbd_header(struct rbd_obj_header_ondisk& ondisk,
                              uint64_t size, int *order, uint64_t bid);
index 620af80e6c9e6e0f2bfdb1ea3514cb8c3becddee..96dcfc2c9bd288f7c6b54a02216550955a9e18ad 100644 (file)
@@ -728,8 +728,14 @@ TEST(LibRBD, TestIO)
   rbd_image_info_t info;
   rbd_completion_t comp;
   ASSERT_EQ(0, rbd_stat(image, &info, sizeof(info)));
+  // can't read or write starting past end
   ASSERT_EQ(-EINVAL, rbd_write(image, info.size, 1, test_data));
   ASSERT_EQ(-EINVAL, rbd_read(image, info.size, 1, test_data));
+  // reading through end returns amount up to end
+  ASSERT_EQ(10, rbd_read(image, info.size - 10, 100, test_data));
+  // writing through end returns amount up to end
+  ASSERT_EQ(10, rbd_write(image, info.size - 10, 100, test_data));
+
   rbd_aio_create_completion(NULL, (rbd_callback_t) simple_read_cb, &comp);
   ASSERT_EQ(-EINVAL, rbd_aio_write(image, info.size, 1, test_data, comp));
   ASSERT_EQ(-EINVAL, rbd_aio_read(image, info.size, 1, test_data, comp));