RBD_DIFF_CB = CFUNCTYPE(c_int, c_uint64, c_size_t, c_int, c_void_p)
cb_holder = DiffIterateCB(iterate_cb)
cb = RBD_DIFF_CB(cb_holder.callback)
- ret = self.librbd.diff_iterate(self.image,
- c_char_p(from_snapshot),
- c_uint64(offset),
- c_uint64(length),
- cb,
- c_void_p(None))
+ ret = self.librbd.rbd_diff_iterate(self.image,
+ c_char_p(from_snapshot),
+ c_uint64(offset),
+ c_uint64(length),
+ cb,
+ c_void_p(None))
if ret < 0:
msg = 'error generating diff from snapshot %s' % from_snapshot
raise make_ex(ret, msg)
returned %d, but %d was the maximum number of bytes it could have \
written." % (self.name, ret, length))
+ def discard(self, offset, length):
+ """
+ Trim the range from the image. It will be logically filled
+ with zeroes.
+ """
+ ret = self.librbd.rbd_discard(self.image,
+ c_uint64(offset),
+ c_uint64(length))
+ if ret < 0:
+ msg = 'error discarding region %d~%d' % (offset, length)
+ raise make_ex(ret, msg)
+
+ def flush(self):
+ """
+ Block until all writes are fully flushed if caching is enabled.
+ """
+ ret = self.librbd.rbd_flush(self.image)
+ if ret < 0:
+ raise make_ex(ret, 'error flushing image')
+
+ def stripe_unit(self):
+ """
+ Returns the stripe unit used for the image.
+ """
+ ret = self.librbd.rbd_get_stripe_unit()
+ return ret.value
+
+ def stripe_count(self):
+ """
+ Returns the stripe count used for the image.
+ """
+ ret = self.librbd.rbd_get_stripe_count()
+ return ret.value
+
def flatten(self):
"""
Flatten clone image (copy all blocks from parent to child)
check_diff(self.image, 0, IMG_SIZE, None, [(0, 256, True)])
self.image.write('b' * 256, 256)
check_diff(self.image, 0, IMG_SIZE, None, [(0, 512, True)])
-
+ self.image.discard(128, 256)
+ check_diff(self.image, 0, IMG_SIZE, None, [(0, 512, True)])
-def check_diff(image, offset, length, from_snapshot, expected):
- cb_holder = DiffExtents()
- image.diff_iterate(0, IMG_SIZE, None, cb_holder.callback)
- eq(cb_holder.extents, expected)
+ self.image.create_snap('snap1')
+ self.image.discard(0, 1 << IMG_ORDER)
+ self.image.create_snap('snap2')
+ self.image.set_snap('snap2')
+ check_diff(self.image, 0, IMG_SIZE,
+ 'snap1', [(0, 512, False)])
+ self.image.remove_snap('snap1')
+ self.image.remove_snap('snap2')
-class DiffExtents(object):
- def __init__(self):
- self.extents = []
- def callback(self, offset, length, exists):
- self.extents.append((offset, length, exists))
+def check_diff(image, offset, length, from_snapshot, expected):
+ extents = []
+ def cb(offset, length, exists):
+ extents.append((offset, length, exists))
+ image.diff_iterate(0, IMG_SIZE, None, cb)
+ eq(extents, expected)
class TestClone(object):