Re: [Qemu-block] [PATCH v3 4/9] file-posix: Implement bdrv_co_copy_range

2018-05-11 Thread Fam Zheng
On Thu, 05/10 09:50, Stefan Hajnoczi wrote:
> On Wed, May 09, 2018 at 10:58:10PM +0800, Fam Zheng wrote:
> > +static off_t copy_file_range(int in_fd, off_t *in_off, int out_fd,
> > + off_t *out_off, size_t len, unsigned int 
> > flags)
> > +{
> > +#ifdef __NR_copy_file_range
> > +return syscall(__NR_copy_file_range, in_fd, in_off, out_fd,
> > +   out_off, len, flags);
> > +#else
> > +errno = ENOSYS;
> > +return -1;
> > +#endif
> > +}
> > +
> > +static ssize_t handle_aiocb_copy_range(RawPosixAIOData *aiocb)
> > +{
> > +uint64_t bytes = aiocb->aio_nbytes;
> > +off_t in_off = aiocb->aio_offset;
> > +off_t out_off = aiocb->aio_offset2;
> > +
> > +while (bytes) {
> > +ssize_t ret = copy_file_range(aiocb->aio_fildes, _off,
> > +  aiocb->aio_fd2, _off,
> > +  bytes, 0);
> > +if (ret == -EINTR) {
> > +continue;
> > +}
> > +if (ret < 0) {
> > +return -errno;
> 
> Convert ENOSYS to ENOTSUP?

Sounds good.



Re: [Qemu-block] [PATCH v3 4/9] file-posix: Implement bdrv_co_copy_range

2018-05-10 Thread Stefan Hajnoczi
On Wed, May 09, 2018 at 10:58:10PM +0800, Fam Zheng wrote:
> +static off_t copy_file_range(int in_fd, off_t *in_off, int out_fd,
> + off_t *out_off, size_t len, unsigned int flags)
> +{
> +#ifdef __NR_copy_file_range
> +return syscall(__NR_copy_file_range, in_fd, in_off, out_fd,
> +   out_off, len, flags);
> +#else
> +errno = ENOSYS;
> +return -1;
> +#endif
> +}
> +
> +static ssize_t handle_aiocb_copy_range(RawPosixAIOData *aiocb)
> +{
> +uint64_t bytes = aiocb->aio_nbytes;
> +off_t in_off = aiocb->aio_offset;
> +off_t out_off = aiocb->aio_offset2;
> +
> +while (bytes) {
> +ssize_t ret = copy_file_range(aiocb->aio_fildes, _off,
> +  aiocb->aio_fd2, _off,
> +  bytes, 0);
> +if (ret == -EINTR) {
> +continue;
> +}
> +if (ret < 0) {
> +return -errno;

Convert ENOSYS to ENOTSUP?

Reviewed-by: Stefan Hajnoczi 


signature.asc
Description: PGP signature


[Qemu-block] [PATCH v3 4/9] file-posix: Implement bdrv_co_copy_range

2018-05-09 Thread Fam Zheng
With copy_file_range(2), we can implement the bdrv_co_copy_range
semantics.

Signed-off-by: Fam Zheng 
---
 block/file-posix.c  | 94 +++--
 include/block/raw-aio.h | 10 --
 2 files changed, 99 insertions(+), 5 deletions(-)

diff --git a/block/file-posix.c b/block/file-posix.c
index 3794c0007a..138bf28747 100644
--- a/block/file-posix.c
+++ b/block/file-posix.c
@@ -59,6 +59,7 @@
 #ifdef __linux__
 #include 
 #include 
+#include 
 #include 
 #include 
 #include 
@@ -185,6 +186,8 @@ typedef struct RawPosixAIOData {
 #define aio_ioctl_cmd   aio_nbytes /* for QEMU_AIO_IOCTL */
 off_t aio_offset;
 int aio_type;
+int aio_fd2;
+off_t aio_offset2;
 } RawPosixAIOData;
 
 #if defined(__FreeBSD__) || defined(__FreeBSD_kernel__)
@@ -1421,6 +1424,43 @@ static ssize_t handle_aiocb_write_zeroes(RawPosixAIOData 
*aiocb)
 return -ENOTSUP;
 }
 
+static off_t copy_file_range(int in_fd, off_t *in_off, int out_fd,
+ off_t *out_off, size_t len, unsigned int flags)
+{
+#ifdef __NR_copy_file_range
+return syscall(__NR_copy_file_range, in_fd, in_off, out_fd,
+   out_off, len, flags);
+#else
+errno = ENOSYS;
+return -1;
+#endif
+}
+
+static ssize_t handle_aiocb_copy_range(RawPosixAIOData *aiocb)
+{
+uint64_t bytes = aiocb->aio_nbytes;
+off_t in_off = aiocb->aio_offset;
+off_t out_off = aiocb->aio_offset2;
+
+while (bytes) {
+ssize_t ret = copy_file_range(aiocb->aio_fildes, _off,
+  aiocb->aio_fd2, _off,
+  bytes, 0);
+if (ret == -EINTR) {
+continue;
+}
+if (ret < 0) {
+return -errno;
+}
+if (!ret) {
+/* No progress (e.g. when beyond EOF), fall back to buffer I/O. */
+return -ENOTSUP;
+}
+bytes -= ret;
+}
+return 0;
+}
+
 static ssize_t handle_aiocb_discard(RawPosixAIOData *aiocb)
 {
 int ret = -EOPNOTSUPP;
@@ -1501,6 +1541,9 @@ static int aio_worker(void *arg)
 case QEMU_AIO_WRITE_ZEROES:
 ret = handle_aiocb_write_zeroes(aiocb);
 break;
+case QEMU_AIO_COPY_RANGE:
+ret = handle_aiocb_copy_range(aiocb);
+break;
 default:
 fprintf(stderr, "invalid aio request (0x%x)\n", aiocb->aio_type);
 ret = -EINVAL;
@@ -1511,9 +1554,10 @@ static int aio_worker(void *arg)
 return ret;
 }
 
-static int paio_submit_co(BlockDriverState *bs, int fd,
-  int64_t offset, QEMUIOVector *qiov,
-  int bytes, int type)
+static int paio_submit_co_full(BlockDriverState *bs, int fd,
+   int64_t offset, int fd2, int64_t offset2,
+   QEMUIOVector *qiov,
+   int bytes, int type)
 {
 RawPosixAIOData *acb = g_new(RawPosixAIOData, 1);
 ThreadPool *pool;
@@ -1521,6 +1565,8 @@ static int paio_submit_co(BlockDriverState *bs, int fd,
 acb->bs = bs;
 acb->aio_type = type;
 acb->aio_fildes = fd;
+acb->aio_fd2 = fd2;
+acb->aio_offset2 = offset2;
 
 acb->aio_nbytes = bytes;
 acb->aio_offset = offset;
@@ -1536,6 +1582,13 @@ static int paio_submit_co(BlockDriverState *bs, int fd,
 return thread_pool_submit_co(pool, aio_worker, acb);
 }
 
+static inline int paio_submit_co(BlockDriverState *bs, int fd,
+ int64_t offset, QEMUIOVector *qiov,
+ int bytes, int type)
+{
+return paio_submit_co_full(bs, fd, offset, -1, 0, qiov, bytes, type);
+}
+
 static BlockAIOCB *paio_submit(BlockDriverState *bs, int fd,
 int64_t offset, QEMUIOVector *qiov, int bytes,
 BlockCompletionFunc *cb, void *opaque, int type)
@@ -2312,6 +2365,35 @@ static void raw_abort_perm_update(BlockDriverState *bs)
 raw_handle_perm_lock(bs, RAW_PL_ABORT, 0, 0, NULL);
 }
 
+static int coroutine_fn raw_co_copy_range_from(BlockDriverState *bs,
+  BdrvChild *src, uint64_t src_offset,
+  BdrvChild *dst, uint64_t dst_offset,
+  uint64_t bytes, BdrvRequestFlags flags)
+{
+return bdrv_co_copy_range_to(src, src_offset, dst, dst_offset, bytes, 
flags);
+}
+
+static int coroutine_fn raw_co_copy_range_to(BlockDriverState *bs,
+ BdrvChild *src, uint64_t 
src_offset,
+ BdrvChild *dst, uint64_t 
dst_offset,
+ uint64_t bytes, BdrvRequestFlags 
flags)
+{
+BDRVRawState *s = bs->opaque;
+BDRVRawState *src_s;
+
+assert(dst->bs == bs);
+if (src->bs->drv->bdrv_co_copy_range_to != raw_co_copy_range_to) {
+return -ENOTSUP;
+}
+
+src_s = src->opaque;
+if (fd_open(bs) < 0 || fd_open(bs) < 0) {
+return -EIO;
+