diff options
Diffstat (limited to 'api/src/glfs-fops.c')
| -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:  | 
