]> git-server-git.apps.pok.os.sepia.ceph.com Git - ceph.git/commitdiff
libcephfs/pybind: Add pwritev, preadv
authorKotresh HR <khiremat@redhat.com>
Tue, 14 Apr 2020 07:27:17 +0000 (12:57 +0530)
committerKotresh HR <khiremat@redhat.com>
Thu, 21 May 2020 11:31:28 +0000 (17:01 +0530)
Fixes: https://tracker.ceph.com/issues/44171
Signed-off-by: Kotresh HR <khiremat@redhat.com>
src/pybind/cephfs/cephfs.pyx
src/test/pybind/test_cephfs.py

index 40ecd565911859474877a60cb1d118c9a5cbc8d2..f88b960413aeb8ec048fb78036b0f2435937583b 100644 (file)
@@ -97,6 +97,11 @@ cdef extern from "time.h":
         time_t      tv_sec
         long int    tv_nsec
 
+cdef extern from "<sys/uio.h>":
+    cdef struct iovec:
+        void *iov_base
+        size_t iov_len
+
 cdef extern from "sys/types.h":
     ctypedef unsigned long mode_t
     ctypedef unsigned long dev_t
@@ -188,7 +193,9 @@ cdef extern from "cephfs/libcephfs.h" nogil:
     int ceph_flistxattr(ceph_mount_info *cmount, int fd, char *list, size_t size)
     int ceph_llistxattr(ceph_mount_info *cmount, const char *path, char *list, size_t size)
     int ceph_write(ceph_mount_info *cmount, int fd, const char *buf, int64_t size, int64_t offset)
+    int ceph_pwritev(ceph_mount_info *cmount, int fd, iovec *iov, int iovcnt, int64_t offset)
     int ceph_read(ceph_mount_info *cmount, int fd, char *buf, int64_t size, int64_t offset)
+    int ceph_preadv(ceph_mount_info *cmount, int fd, iovec *iov, int iovcnt, int64_t offset)
     int ceph_flock(ceph_mount_info *cmount, int fd, int operation, uint64_t owner)
     int ceph_mknod(ceph_mount_info *cmount, const char *path, mode_t mode, dev_t rdev)
     int ceph_close(ceph_mount_info *cmount, int fd)
@@ -533,6 +540,17 @@ cdef void* realloc_chk(void* ptr, size_t size) except NULL:
     return ret
 
 
+cdef iovec * to_iovec(buffers) except NULL:
+    cdef iovec *iov = <iovec *>malloc(len(buffers) * sizeof(iovec))
+    cdef char *s = NULL
+    if iov == NULL:
+        raise MemoryError("malloc failed")
+    for i in xrange(len(buffers)):
+        s = <char*>buffers[i]
+        iov[i] = [<void*>s, len(buffers[i])]
+    return iov
+
+
 cdef class LibCephFS(object):
     """libcephfs python wrapper"""
 
@@ -1367,6 +1385,40 @@ cdef class LibCephFS(object):
             # itself and set ret_s to NULL, hence XDECREF).
             ref.Py_XDECREF(ret_s)
 
+    def preadv(self, fd, buffers, offset):
+        """
+        Write data to a file.
+
+        :param fd: the file descriptor of the open file to read from
+        :param buffers: the list of byte object to read from the file
+        :param offset: the offset of the file read from.  If this value is negative, the
+                       function reads from the current offset of the file descriptor.
+        """
+        self.require_state("mounted")
+        if not isinstance(fd, int):
+            raise TypeError('fd must be an int')
+        if not isinstance(buffers, list):
+            raise TypeError('buffers must be a list')
+        for buf in buffers:
+            if not isinstance(buf, bytearray):
+                raise TypeError('buffers must be a list of bytes')
+        if not isinstance(offset, int):
+            raise TypeError('offset must be an int')
+
+        cdef:
+            int _fd = fd
+            int _iovcnt = len(buffers)
+            int64_t _offset = offset
+            iovec *_iov = to_iovec(buffers)
+        try:
+            with nogil:
+                ret = ceph_preadv(self.cluster, _fd, _iov, _iovcnt, _offset)
+            if ret < 0:
+                raise make_ex(ret, "error in preadv")
+            return ret
+        finally:
+            free(_iov)
+
     def write(self, fd, buf, offset):
         """
         Write data to a file.
@@ -1397,6 +1449,40 @@ cdef class LibCephFS(object):
             raise make_ex(ret, "error in write")
         return ret
 
+    def pwritev(self, fd, buffers, offset):
+        """
+        Write data to a file.
+
+        :param fd: the file descriptor of the open file to write to
+        :param buffers: the list of byte object to write to the file
+        :param offset: the offset of the file write into.  If this value is negative, the
+                       function writes to the current offset of the file descriptor.
+        """
+        self.require_state("mounted")
+        if not isinstance(fd, int):
+            raise TypeError('fd must be an int')
+        if not isinstance(buffers, list):
+            raise TypeError('buffers must be a list')
+        for buf in buffers:
+            if not isinstance(buf, bytes):
+                raise TypeError('buffers must be a list of bytes')
+        if not isinstance(offset, int):
+            raise TypeError('offset must be an int')
+
+        cdef:
+            int _fd = fd
+            int _iovcnt = len(buffers)
+            int64_t _offset = offset
+            iovec *_iov = to_iovec(buffers)
+        try:
+            with nogil:
+                ret = ceph_pwritev(self.cluster, _fd, _iov, _iovcnt, _offset)
+            if ret < 0:
+                raise make_ex(ret, "error in pwritev")
+            return ret
+        finally:
+            free(_iov)
+
     def flock(self, fd, operation, owner):
         """
         Apply or remove an advisory lock.
index b135d5dfbc338623df35900f2b1c294aae958048..ee12c6404768bb2e530d4620e5442dfc62319b55 100644 (file)
@@ -629,3 +629,14 @@ def test_readdirops():
     for i in dirs:
         cephfs.rmdir(i)
     cephfs.closedir(handler)
+
+def test_preadv_pwritev():
+    fd = cephfs.open(b'file-1', 'w', 0o755)
+    cephfs.pwritev(fd, [b"asdf", b"zxcvb"], 0)
+    cephfs.close(fd)
+    fd = cephfs.open(b'file-1', 'r', 0o755)
+    buf = [bytearray(i) for i in [4, 5]]
+    cephfs.preadv(fd, buf, 0)
+    assert_equal([b"asdf", b"zxcvb"], list(buf))
+    cephfs.close(fd)
+    cephfs.unlink(b'file-1')