From: Kotresh HR Date: Tue, 14 Apr 2020 07:27:17 +0000 (+0530) Subject: libcephfs/pybind: Add pwritev, preadv X-Git-Tag: v16.1.0~2070^2~3 X-Git-Url: http://git-server-git.apps.pok.os.sepia.ceph.com/?a=commitdiff_plain;h=2c5fc057cf779d34a0676eb676e4f45ff29663d5;p=ceph.git libcephfs/pybind: Add pwritev, preadv Fixes: https://tracker.ceph.com/issues/44171 Signed-off-by: Kotresh HR --- diff --git a/src/pybind/cephfs/cephfs.pyx b/src/pybind/cephfs/cephfs.pyx index 40ecd5659118..f88b960413ae 100644 --- a/src/pybind/cephfs/cephfs.pyx +++ b/src/pybind/cephfs/cephfs.pyx @@ -97,6 +97,11 @@ cdef extern from "time.h": time_t tv_sec long int tv_nsec +cdef extern from "": + 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 = malloc(len(buffers) * sizeof(iovec)) + cdef char *s = NULL + if iov == NULL: + raise MemoryError("malloc failed") + for i in xrange(len(buffers)): + s = buffers[i] + iov[i] = [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. diff --git a/src/test/pybind/test_cephfs.py b/src/test/pybind/test_cephfs.py index b135d5dfbc33..ee12c6404768 100644 --- a/src/test/pybind/test_cephfs.py +++ b/src/test/pybind/test_cephfs.py @@ -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')