From: Jason Dillaman Date: Tue, 30 Jun 2020 15:20:31 +0000 (-0400) Subject: pybind/rbd: add new write_zeroes/aio_write_zeroes API methods X-Git-Tag: v15.2.5~100^2~1 X-Git-Url: http://git-server-git.apps.pok.os.sepia.ceph.com/?a=commitdiff_plain;h=6a884184b680b89e2b46ad001651e07e58514eb0;p=ceph.git pybind/rbd: add new write_zeroes/aio_write_zeroes API methods Signed-off-by: Jason Dillaman (cherry picked from commit c27d744a339d3644b756ee496445909f63c8903e) --- diff --git a/src/pybind/rbd/rbd.pyx b/src/pybind/rbd/rbd.pyx index 72cfda55650b..72da0ee9fbb3 100644 --- a/src/pybind/rbd/rbd.pyx +++ b/src/pybind/rbd/rbd.pyx @@ -500,6 +500,8 @@ cdef extern from "rbd/librbd.h" nogil: ssize_t rbd_write2(rbd_image_t image, uint64_t ofs, size_t len, const char *buf, int op_flags) int rbd_discard(rbd_image_t image, uint64_t ofs, uint64_t len) + int rbd_write_zeroes(rbd_image_t image, uint64_t ofs, uint64_t len, + int zero_flags, int op_flags) int rbd_copy3(rbd_image_t src, rados_ioctx_t dest_io_ctx, const char *destname, rbd_image_options_t dest_opts) int rbd_deep_copy(rbd_image_t src, rados_ioctx_t dest_io_ctx, @@ -622,6 +624,8 @@ cdef extern from "rbd/librbd.h" nogil: char *buf, rbd_completion_t c, int op_flags) int rbd_aio_discard(rbd_image_t image, uint64_t off, uint64_t len, rbd_completion_t c) + int rbd_aio_write_zeroes(rbd_image_t image, uint64_t off, uint64_t len, + rbd_completion_t c, int zero_flags, int op_flags) int rbd_aio_create_completion(void *cb_arg, rbd_callback_t complete_cb, rbd_completion_t *c) @@ -4403,6 +4407,23 @@ written." % (self.name, ret, length)) msg = 'error discarding region %d~%d' % (offset, length) raise make_ex(ret, msg) + @requires_not_closed + def write_zeroes(self, offset, length, zero_flags = 0): + """ + Zero the range from the image. By default it will attempt to + discard/unmap as much space as possible but any unaligned + extent segments will still be zeroed. + """ + cdef: + uint64_t _offset = offset, _length = length + int _zero_flags = zero_flags + with nogil: + ret = rbd_write_zeroes(self.image, _offset, _length, + _zero_flags, 0) + if ret < 0: + msg = 'error zeroing region %d~%d' % (offset, length) + raise make_ex(ret, msg) + @requires_not_closed def flush(self): """ @@ -5087,6 +5108,34 @@ written." % (self.name, ret, length)) return completion + @requires_not_closed + def aio_write_zeroes(self, offset, length, oncomplete, zero_flags = 0): + """ + Asynchronously Zero the range from the image. By default it will attempt + to discard/unmap as much space as possible but any unaligned extent + segments will still be zeroed. + """ + cdef: + uint64_t _offset = offset + size_t _length = length + int _zero_flags = zero_flags + Completion completion + + completion = self.__get_completion(oncomplete) + try: + completion.__persist() + with nogil: + ret = rbd_aio_write_zeroes(self.image, _offset, _length, + completion.rbd_comp, _zero_flags, 0) + if ret < 0: + raise make_ex(ret, 'error zeroing %s %ld~%ld' % + (self.name, offset, length)) + except: + completion.__unpersist() + raise + + return completion + @requires_not_closed def aio_flush(self, oncomplete): """ diff --git a/src/test/pybind/test_rbd.py b/src/test/pybind/test_rbd.py index ebec25652b58..428466c16f80 100644 --- a/src/test/pybind/test_rbd.py +++ b/src/test/pybind/test_rbd.py @@ -601,6 +601,12 @@ class TestImage(object): self.image.write(data, 0, LIBRADOS_OP_FLAG_FADVISE_DONTNEED) self.image.write(data, 0, LIBRADOS_OP_FLAG_FADVISE_NOCACHE) + def test_write_zeroes(self): + data = rand_data(256) + self.image.write(data, 0) + self.image.write_zeroes(0, 256) + eq(self.image.read(256, 256), b'\0' * 256) + def test_read(self): data = self.image.read(0, 20) eq(data, b'\0' * 20) @@ -1192,6 +1198,20 @@ class TestImage(object): eq(sys.getrefcount(comp), 2) eq(self.image.read(256, 256), b'\0' * 256) + def test_aio_write_zeroes(self): + retval = [None] + def cb(comp): + retval[0] = comp.get_return_value() + + data = rand_data(256) + self.image.write(data, 0) + comp = self.image.aio_write_zeroes(0, 256, cb) + comp.wait_for_complete_and_cb() + eq(retval[0], 0) + eq(comp.get_return_value(), 0) + eq(sys.getrefcount(comp), 2) + eq(self.image.read(256, 256), b'\0' * 256) + def test_aio_flush(self): retval = [None] def cb(comp):