diff options
-rw-r--r-- | api/src/glfs-fops.c | 568 |
1 files changed, 362 insertions, 206 deletions
diff --git a/api/src/glfs-fops.c b/api/src/glfs-fops.c index 7e196e1eeb0..b8fe0498225 100644 --- a/api/src/glfs-fops.c +++ b/api/src/glfs-fops.c @@ -793,121 +793,66 @@ struct glfs_io { static int -glfs_io_async_cbk (int ret, call_frame_t *frame, void *data) +glfs_io_async_cbk (int op_ret, int op_errno, call_frame_t *frame, + void *cookie, struct iovec *iovec, int count) { - struct glfs_io *gio = data; - - /* If the fd is already closed then - * no need to do the callback */ - if (glfs_is_glfd_still_valid (gio->glfd)) { - gio->fn (gio->glfd, ret, gio->data); - } - - /* Since the async operation is complete - * release the ref taken during the start - * of async operation - */ - if (gio->glfd) - GF_REF_PUT (gio->glfd); - - GF_FREE (gio->iov); - GF_FREE (gio); - - return 0; -} - -ssize_t -pub_glfs_pwritev (struct glfs_fd *, const struct iovec *, int, off_t, int); - -int -pub_glfs_ftruncate (struct glfs_fd *, off_t); - -int -pub_glfs_fdatasync (struct glfs_fd *); - -int -pub_glfs_fsync (struct glfs_fd *glfd); - -int -pub_glfs_discard (struct glfs_fd *, off_t, size_t); - -int -pub_glfs_zerofill (struct glfs_fd *, off_t, off_t); - -static int -glfs_io_async_task (void *data) -{ - struct glfs_io *gio = data; - ssize_t ret = 0; - - switch (gio->op) { - case GF_FOP_WRITE: - ret = pub_glfs_pwritev (gio->glfd, gio->iov, gio->count, - gio->offset, gio->flags); - break; - case GF_FOP_FTRUNCATE: - ret = pub_glfs_ftruncate (gio->glfd, gio->offset); - break; - case GF_FOP_FSYNC: - if (gio->flags) - ret = pub_glfs_fdatasync (gio->glfd); - else - ret = pub_glfs_fsync (gio->glfd); - break; - case GF_FOP_DISCARD: - ret = pub_glfs_discard (gio->glfd, gio->offset, gio->count); - break; - case GF_FOP_ZEROFILL: - ret = pub_glfs_zerofill(gio->glfd, gio->offset, gio->count); - break; - } - - return (int) ret; -} - - -int -glfs_preadv_async_cbk (call_frame_t *frame, void *cookie, xlator_t *this, - int op_ret, int op_errno, struct iovec *iovec, - int count, struct iatt *stbuf, struct iobref *iobref, - dict_t *xdata) -{ - struct glfs_io *gio = NULL; - xlator_t *subvol = NULL; - struct glfs *fs = NULL; - struct glfs_fd *glfd = NULL; + struct glfs_io *gio = NULL; + xlator_t *subvol = NULL; + struct glfs *fs = NULL; + struct glfs_fd *glfd = NULL; + int ret = -1; + GF_VALIDATE_OR_GOTO ("gfapi", frame, inval); + GF_VALIDATE_OR_GOTO ("gfapi", cookie, inval); + GF_VALIDATE_OR_GOTO ("gfapi", iovec, inval); - gio = frame->local; - frame->local = NULL; - subvol = cookie; - glfd = gio->glfd; - fs = glfd->fs; + gio = frame->local; + frame->local = NULL; + subvol = cookie; + glfd = gio->glfd; + fs = glfd->fs; if (!glfs_is_glfd_still_valid (glfd)) goto err; - if (op_ret <= 0) - goto out; - - op_ret = iov_copy (gio->iov, gio->count, iovec, count); + if (op_ret <= 0) { + goto out; + } else if (gio->op == GF_FOP_READ) { + op_ret = iov_copy (gio->iov, gio->count, iovec, count); + glfd->offset = gio->offset + op_ret; + } else if (gio->op == GF_FOP_WRITE) { + glfd->offset = gio->offset + gio->iov->iov_len; + } - glfd->offset = gio->offset + op_ret; out: - errno = op_errno; - gio->fn (gio->glfd, op_ret, gio->data); + errno = op_errno; + gio->fn (gio->glfd, op_ret, gio->data); err: + fd_unref (glfd->fd); /* Since the async operation is complete * release the ref taken during the start * of async operation */ GF_REF_PUT (glfd); - GF_FREE (gio->iov); - GF_FREE (gio); - STACK_DESTROY (frame->root); - glfs_subvol_done (fs, subvol); + GF_FREE (gio->iov); + GF_FREE (gio); + STACK_DESTROY (frame->root); + glfs_subvol_done (fs, subvol); + + ret = 0; +inval: + return ret; +} + +static int +glfs_preadv_async_cbk (call_frame_t *frame, void *cookie, xlator_t *this, + int op_ret, int op_errno, struct iovec *iovec, + int count, struct iatt *stbuf, struct iobref *iobref, + dict_t *xdata) +{ + glfs_io_async_cbk (op_ret, op_errno, frame, cookie, iovec, count); return 0; } @@ -995,9 +940,6 @@ out: glfs_subvol_done (fs, subvol); } - if (fd) - fd_unref (fd); - __GLFS_EXIT_FS; return ret; @@ -1059,13 +1001,56 @@ pub_glfs_readv_async (struct glfs_fd *glfd, const struct iovec *iov, int count, GFAPI_SYMVER_PUBLIC_DEFAULT(glfs_readv_async, 3.4.0); +static int +glfs_buf_copy (xlator_t *subvol, const struct iovec *iovec_src, int iovcnt, + struct iobref **iobref, struct iobuf **iobuf, + struct iovec *iov_dst) +{ + size_t size = -1; + int ret = 0; + + size = iov_length (iovec_src, iovcnt); + + *iobuf = iobuf_get2 (subvol->ctx->iobuf_pool, size); + if (!(*iobuf)) { + ret = -1; + errno = ENOMEM; + goto out; + } + + *iobref = iobref_new (); + if (!(*iobref)) { + iobuf_unref (*iobuf); + errno = ENOMEM; + ret = -1; + goto out; + } + + ret = iobref_add (*iobref, *iobuf); + if (ret) { + iobuf_unref (*iobuf); + iobref_unref (*iobref); + errno = ENOMEM; + ret = -1; + goto out; + } + + iov_unload (iobuf_ptr (*iobuf), iovec_src, iovcnt); /* FIXME!!! */ + + iov_dst->iov_base = iobuf_ptr (*iobuf); + iov_dst->iov_len = size; + +out: + return ret; +} + + ssize_t pub_glfs_pwritev (struct glfs_fd *glfd, const struct iovec *iovec, int iovcnt, off_t offset, int flags) { xlator_t *subvol = NULL; int ret = -1; - size_t size = -1; struct iobref *iobref = NULL; struct iobuf *iobuf = NULL; struct iovec iov = {0, }; @@ -1090,50 +1075,24 @@ pub_glfs_pwritev (struct glfs_fd *glfd, const struct iovec *iovec, int iovcnt, goto out; } - size = iov_length (iovec, iovcnt); - - iobuf = iobuf_get2 (subvol->ctx->iobuf_pool, size); - if (!iobuf) { - ret = -1; - errno = ENOMEM; - goto out; - } - - iobref = iobref_new (); - if (!iobref) { - iobuf_unref (iobuf); - errno = ENOMEM; - ret = -1; - goto out; - } - - ret = iobref_add (iobref, iobuf); - if (ret) { - iobuf_unref (iobuf); - iobref_unref (iobref); - errno = ENOMEM; - ret = -1; - goto out; - } - - iov_unload (iobuf_ptr (iobuf), iovec, iovcnt); /* FIXME!!! */ - - iov.iov_base = iobuf_ptr (iobuf); - iov.iov_len = size; + ret = glfs_buf_copy (subvol, iovec, iovcnt, &iobref, &iobuf, &iov); + if (ret) + goto out; ret = syncop_writev (subvol, fd, &iov, 1, offset, iobref, flags, NULL, NULL); DECODE_SYNCOP_ERR (ret); - iobuf_unref (iobuf); - iobref_unref (iobref); - if (ret <= 0) goto out; - glfd->offset = (offset + size); + glfd->offset = (offset + iov.iov_len); out: + if (iobuf) + iobuf_unref (iobuf); + if (iobref) + iobref_unref (iobref); if (fd) fd_unref (fd); if (glfd) @@ -1201,6 +1160,17 @@ GFAPI_SYMVER_PUBLIC_DEFAULT(glfs_pwrite, 3.4.0); extern glfs_t *pub_glfs_from_glfd (glfs_fd_t *); + +static int +glfs_pwritev_async_cbk (call_frame_t *frame, void *cookie, xlator_t *this, + int op_ret, int op_errno, struct iatt *prebuf, + struct iatt *postbuf, dict_t *xdata) +{ + glfs_io_async_cbk (op_ret, op_errno, frame, cookie, NULL, 0); + + return 0; +} + int pub_glfs_pwritev_async (struct glfs_fd *glfd, const struct iovec *iovec, int count, off_t offset, int flags, glfs_io_cbk fn, @@ -1208,47 +1178,84 @@ pub_glfs_pwritev_async (struct glfs_fd *glfd, const struct iovec *iovec, { struct glfs_io *gio = NULL; int ret = -1; + call_frame_t *frame = NULL; + xlator_t *subvol = NULL; + fd_t *fd = NULL; + struct iobref *iobref = NULL; + struct iobuf *iobuf = NULL; DECLARE_OLD_THIS; __GLFS_ENTRY_VALIDATE_FD (glfd, invalid_fs); - gio = GF_CALLOC (1, sizeof (*gio), glfs_mt_glfs_io_t); - if (!gio) { - errno = ENOMEM; - goto out; - } - - gio->iov = iov_dup (iovec, count); - if (!gio->iov) { - GF_FREE (gio); - errno = ENOMEM; - goto out; - } - - gio->op = GF_FOP_WRITE; - gio->glfd = glfd; - gio->count = count; - gio->offset = offset; - gio->flags = flags; - gio->fn = fn; - gio->data = data; - /* Need to take explicit ref so that the fd * is not destroyed before the fop is complete */ GF_REF_GET (glfd); - ret = synctask_new (pub_glfs_from_glfd (glfd)->ctx->env, - glfs_io_async_task, glfs_io_async_cbk, - NULL, gio); + subvol = glfs_active_subvol (glfd->fs); + if (!subvol) { + errno = EIO; + goto out; + } - if (ret) { - GF_REF_PUT (glfd); - GF_FREE (gio->iov); - GF_FREE (gio); - } + fd = glfs_resolve_fd (glfd->fs, subvol, glfd); + if (!fd) { + errno = EBADFD; + goto out; + } + + gio = GF_CALLOC (1, sizeof (*gio), glfs_mt_glfs_io_t); + if (!gio) { + errno = ENOMEM; + goto out; + } + + gio->op = GF_FOP_WRITE; + gio->glfd = glfd; + gio->count = count; + gio->offset = offset; + gio->flags = flags; + gio->fn = fn; + gio->data = data; + gio->iov = GF_CALLOC (1, sizeof (*(gio->iov)), gf_common_mt_iovec); + if (!gio->iov) { + errno = ENOMEM; + goto out; + } + + ret = glfs_buf_copy (subvol, iovec, count, &iobref, &iobuf, gio->iov); + if (ret) + goto out; + frame = syncop_create_frame (THIS); + if (!frame) { + errno = ENOMEM; + goto out; + } + + frame->local = gio; + + STACK_WIND_COOKIE (frame, glfs_pwritev_async_cbk, subvol, subvol, + subvol->fops->writev, fd, gio->iov, + gio->count, offset, flags, iobref, NULL); + + ret = 0; out: + if (ret) { + if (glfd) + GF_REF_PUT (glfd); + GF_FREE (gio); + if (frame) + STACK_DESTROY (frame->root); + + glfs_subvol_done (glfd->fs, subvol); + } + + if (iobuf) + iobuf_unref (iobuf); + if (iobref) + iobref_unref (iobref); + __GLFS_EXIT_FS; invalid_fs: @@ -1352,6 +1359,16 @@ invalid_fs: GFAPI_SYMVER_PUBLIC_DEFAULT(glfs_fsync, 3.4.0); +static int +glfs_fsync_async_cbk (call_frame_t *frame, void *cookie, + xlator_t *this, int32_t op_ret, + int32_t op_errno, struct iatt *prebuf, + struct iatt *postbuf, dict_t *xdata) +{ + glfs_io_async_cbk (op_ret, op_errno, frame, cookie, NULL, 0); + + return 0; +} static int glfs_fsync_async_common (struct glfs_fd *glfd, glfs_io_cbk fn, void *data, @@ -1359,36 +1376,65 @@ glfs_fsync_async_common (struct glfs_fd *glfd, glfs_io_cbk fn, void *data, { struct glfs_io *gio = NULL; int ret = 0; - - gio = GF_CALLOC (1, sizeof (*gio), glfs_mt_glfs_io_t); - if (!gio) { - errno = ENOMEM; - return -1; - } + call_frame_t *frame = NULL; + xlator_t *subvol = NULL; + fd_t *fd = NULL; /* Need to take explicit ref so that the fd * is not destroyed before the fop is complete */ GF_REF_GET (glfd); + subvol = glfs_active_subvol (glfd->fs); + if (!subvol) { + ret = -1; + errno = EIO; + goto out; + } + + fd = glfs_resolve_fd (glfd->fs, subvol, glfd); + if (!fd) { + ret = -1; + errno = EBADFD; + goto out; + } + + frame = syncop_create_frame (THIS); + if (!frame) { + ret = -1; + errno = ENOMEM; + goto out; + } + + gio = GF_CALLOC (1, sizeof (*gio), glfs_mt_glfs_io_t); + if (!gio) { + errno = ENOMEM; + ret = -1; + goto out; + } + gio->op = GF_FOP_FSYNC; gio->glfd = glfd; gio->flags = dataonly; gio->fn = fn; gio->data = data; - ret = synctask_new (pub_glfs_from_glfd (glfd)->ctx->env, - glfs_io_async_task, glfs_io_async_cbk, - NULL, gio); + frame->local = gio; - if (ret) { - GF_REF_PUT (glfd); - GF_FREE (gio->iov); - GF_FREE (gio); - } + STACK_WIND_COOKIE (frame, glfs_fsync_async_cbk, subvol, subvol, + subvol->fops->fsync, fd, dataonly, NULL); - return ret; +out: + if (ret) { + if (glfd) + GF_REF_PUT (glfd); + GF_FREE (gio); + if (frame) + STACK_DESTROY (frame->root); + glfs_subvol_done (glfd->fs, subvol); + } + return ret; } @@ -1519,6 +1565,16 @@ invalid_fs: GFAPI_SYMVER_PUBLIC_DEFAULT(glfs_ftruncate, 3.4.0); +static int +glfs_ftruncate_async_cbk (call_frame_t *frame, void *cookie, xlator_t *this, + int32_t op_ret, int32_t op_errno, + struct iatt *prebuf, struct iatt *postbuf, + dict_t *xdata) +{ + glfs_io_async_cbk (op_ret, op_errno, frame, cookie, NULL, 0); + + return 0; +} int pub_glfs_ftruncate_async (struct glfs_fd *glfd, off_t offset, glfs_io_cbk fn, @@ -1526,10 +1582,36 @@ pub_glfs_ftruncate_async (struct glfs_fd *glfd, off_t offset, glfs_io_cbk fn, { struct glfs_io *gio = NULL; int ret = -1; + call_frame_t *frame = NULL; + xlator_t *subvol = NULL; + fd_t *fd = NULL; DECLARE_OLD_THIS; __GLFS_ENTRY_VALIDATE_FD (glfd, invalid_fs); + /* Need to take explicit ref so that the fd + * is not destroyed before the fop is complete + */ + GF_REF_GET (glfd); + + subvol = glfs_active_subvol (glfd->fs); + if (!subvol) { + errno = EIO; + goto out; + } + + fd = glfs_resolve_fd (glfd->fs, subvol, glfd); + if (!fd) { + errno = EBADFD; + goto out; + } + + frame = syncop_create_frame (THIS); + if (!frame) { + errno = ENOMEM; + goto out; + } + gio = GF_CALLOC (1, sizeof (*gio), glfs_mt_glfs_io_t); if (!gio) { errno = ENOMEM; @@ -1542,22 +1624,23 @@ pub_glfs_ftruncate_async (struct glfs_fd *glfd, off_t offset, glfs_io_cbk fn, gio->fn = fn; gio->data = data; - /* Need to take explicit ref so that the fd - * is not destroyed before the fop is complete - */ - GF_REF_GET (glfd); + frame->local = gio; - ret = synctask_new (pub_glfs_from_glfd (glfd)->ctx->env, - glfs_io_async_task, glfs_io_async_cbk, - NULL, gio); + STACK_WIND_COOKIE (frame, glfs_ftruncate_async_cbk, subvol, subvol, + subvol->fops->ftruncate, fd, offset, NULL); - if (ret) { - GF_REF_PUT (glfd); - GF_FREE (gio->iov); - GF_FREE (gio); - } + ret = 0; out: + if (ret) { + if (glfd) + GF_REF_PUT (glfd); + GF_FREE (gio); + if (frame) + STACK_DESTROY (frame->root); + glfs_subvol_done (glfd->fs, subvol); + } + __GLFS_EXIT_FS; invalid_fs: @@ -2338,6 +2421,16 @@ pub_glfs_seekdir (struct glfs_fd *fd, long offset) GFAPI_SYMVER_PUBLIC_DEFAULT(glfs_seekdir, 3.4.0); +static int +glfs_discard_async_cbk (call_frame_t *frame, void *cookie, + xlator_t *this, int32_t op_ret, + int32_t op_errno, struct iatt *preop_stbuf, + struct iatt *postop_stbuf, dict_t *xdata) +{ + glfs_io_async_cbk (op_ret, op_errno, frame, cookie, NULL, 0); + + return 0; +} int pub_glfs_discard_async (struct glfs_fd *glfd, off_t offset, size_t len, @@ -2345,6 +2438,9 @@ pub_glfs_discard_async (struct glfs_fd *glfd, off_t offset, size_t len, { struct glfs_io *gio = NULL; int ret = -1; + call_frame_t *frame = NULL; + xlator_t *subvol = NULL; + fd_t *fd = NULL; DECLARE_OLD_THIS; __GLFS_ENTRY_VALIDATE_FD (glfd, invalid_fs); @@ -2354,6 +2450,24 @@ pub_glfs_discard_async (struct glfs_fd *glfd, off_t offset, size_t len, */ GF_REF_GET (glfd); + subvol = glfs_active_subvol (glfd->fs); + if (!subvol) { + errno = EIO; + goto out; + } + + fd = glfs_resolve_fd (glfd->fs, subvol, glfd); + if (!fd) { + errno = EBADFD; + goto out; + } + + frame = syncop_create_frame (THIS); + if (!frame) { + errno = ENOMEM; + goto out; + } + gio = GF_CALLOC (1, sizeof (*gio), glfs_mt_glfs_io_t); if (!gio) { errno = ENOMEM; @@ -2367,17 +2481,22 @@ pub_glfs_discard_async (struct glfs_fd *glfd, off_t offset, size_t len, gio->fn = fn; gio->data = data; - ret = synctask_new (pub_glfs_from_glfd (glfd)->ctx->env, - glfs_io_async_task, glfs_io_async_cbk, - NULL, gio); + frame->local = gio; - if (ret) { - GF_REF_PUT (glfd); - GF_FREE (gio->iov); - GF_FREE (gio); - } + STACK_WIND_COOKIE (frame, glfs_discard_async_cbk, subvol, subvol, + subvol->fops->discard, fd, offset, len, NULL); + ret = 0; out: + if (ret) { + if (glfd) + GF_REF_PUT (glfd); + GF_FREE (gio); + if (frame) + STACK_DESTROY (frame->root); + glfs_subvol_done (glfd->fs, subvol); + } + __GLFS_EXIT_FS; invalid_fs: @@ -2387,12 +2506,27 @@ invalid_fs: GFAPI_SYMVER_PUBLIC_DEFAULT(glfs_discard_async, 3.5.0); +static int +glfs_zerofill_async_cbk (call_frame_t *frame, void *cookie, + xlator_t *this, int32_t op_ret, + int32_t op_errno, struct iatt *preop_stbuf, + struct iatt *postop_stbuf, dict_t *xdata) +{ + glfs_io_async_cbk (op_ret, op_errno, frame, cookie, NULL, 0); + + return 0; +} + + int pub_glfs_zerofill_async (struct glfs_fd *glfd, off_t offset, off_t len, glfs_io_cbk fn, void *data) { struct glfs_io *gio = NULL; int ret = -1; + call_frame_t *frame = NULL; + xlator_t *subvol = NULL; + fd_t *fd = NULL; DECLARE_OLD_THIS; __GLFS_ENTRY_VALIDATE_FD (glfd, invalid_fs); @@ -2402,6 +2536,24 @@ pub_glfs_zerofill_async (struct glfs_fd *glfd, off_t offset, off_t len, */ GF_REF_GET (glfd); + subvol = glfs_active_subvol (glfd->fs); + if (!subvol) { + errno = EIO; + goto out; + } + + fd = glfs_resolve_fd (glfd->fs, subvol, glfd); + if (!fd) { + errno = EBADFD; + goto out; + } + + frame = syncop_create_frame (THIS); + if (!frame) { + errno = ENOMEM; + goto out; + } + gio = GF_CALLOC (1, sizeof (*gio), glfs_mt_glfs_io_t); if (!gio) { errno = ENOMEM; @@ -2415,17 +2567,21 @@ pub_glfs_zerofill_async (struct glfs_fd *glfd, off_t offset, off_t len, gio->fn = fn; gio->data = data; - ret = synctask_new (pub_glfs_from_glfd (glfd)->ctx->env, - glfs_io_async_task, glfs_io_async_cbk, - NULL, gio); + frame->local = gio; + STACK_WIND_COOKIE (frame, glfs_zerofill_async_cbk, subvol, subvol, + subvol->fops->zerofill, fd, offset, len, NULL); + ret = 0; +out: if (ret) { - GF_REF_PUT (glfd); - GF_FREE (gio->iov); + if (glfd) + GF_REF_PUT (glfd); GF_FREE (gio); + if (frame) + STACK_DESTROY (frame->root); + glfs_subvol_done (glfd->fs, subvol); } -out: __GLFS_EXIT_FS; invalid_fs: |