12a457
From ce2515d72f56c2975c59230a548090ee4b9f2085 Mon Sep 17 00:00:00 2001
12a457
From: Poornima G <pgurusid@redhat.com>
12a457
Date: Fri, 29 Apr 2016 12:24:24 -0400
12a457
Subject: [PATCH 136/139] gfapi: Fix a deadlock caused by graph switch while aio in progress
12a457
12a457
RCA:
12a457
Currently async nature is achieved by submitting a syncop operation to
12a457
synctask threads. Consider a scenario where the graph switch is triggered,
12a457
the next write fop checks for the next available graph and sets
12a457
fs->migration_in_progess and triggers the migration of fds and other
12a457
things, which can cause some syncop_lookup operation. While this fop (on
12a457
synctask thread) is waiting for syncop_lookup to return, lets say there
12a457
are another 17 write async calls submitted, all these writes are blocked
12a457
waiting for fs->migration_in_progress to be unset, hence all the 16
12a457
synctask threads are blocked waiting for fs->migration_in_progress to be
12a457
unset. Now the syncop_lookup returns, but there are no synctask threads to
12a457
process the lookup_cbk. If this syncop_lookup doesn't return,
12a457
then fs->migration_in_progress can not be unset by the first fop.
12a457
Thus causing a deadlock.
12a457
12a457
To fix this deadlock, changing all the async APIs to use STACK_WIND,
12a457
instead of syntask to achieve async nature. glfs_preadv_async is already
12a457
implemented using STACK_WIND, now changing all the other async APIs
12a457
also to do the same.
12a457
12a457
This patch as such will not reduce the performance of async IO, the only
12a457
thing that can affect is that, in case of write, the buf passed by
12a457
application is copied onto iobuf in the same thread wheras before it
12a457
was being copied in synctask thread.
12a457
12a457
Since, the syncop + graph switch logic (lock across fops) is not a good
12a457
candidate for synctask, changing the async APIs to use STACK_WIND
12a457
12a457
upstream master: http://review.gluster.org/14148
12a457
release 3.7: http://review.gluster.org/14223
12a457
12a457
Change-Id: Idf665cae0a8e27697fbfc5ec8d93a6d6bae3a4f1
12a457
BUG: 1328411
12a457
Signed-off-by: Poornima G <pgurusid@redhat.com>
12a457
Reviewed-on: https://code.engineering.redhat.com/gerrit/73812
12a457
Reviewed-by: Rajesh Joseph <rjoseph@redhat.com>
12a457
Tested-by: Rajesh Joseph <rjoseph@redhat.com>
12a457
---
12a457
 api/src/glfs-fops.c |  568 ++++++++++++++++++++++++++++++++-------------------
12a457
 1 files changed, 362 insertions(+), 206 deletions(-)
12a457
12a457
diff --git a/api/src/glfs-fops.c b/api/src/glfs-fops.c
12a457
index 7a3dffa..7dfab5b 100644
12a457
--- a/api/src/glfs-fops.c
12a457
+++ b/api/src/glfs-fops.c
12a457
@@ -732,121 +732,66 @@ struct glfs_io {
12a457
 
12a457
 
12a457
 static int
12a457
-glfs_io_async_cbk (int ret, call_frame_t *frame, void *data)
12a457
+glfs_io_async_cbk (int op_ret, int op_errno, call_frame_t *frame,
12a457
+                   void *cookie, struct iovec *iovec, int count)
12a457
 {
12a457
-	struct glfs_io  *gio = data;
12a457
-
12a457
-        /* If the fd is already closed then
12a457
-         * no need to do the callback */
12a457
-        if (glfs_is_glfd_still_valid (gio->glfd)) {
12a457
-                gio->fn (gio->glfd, ret, gio->data);
12a457
-        }
12a457
-
12a457
-        /* Since the async operation is complete
12a457
-         * release the ref taken during the start
12a457
-         * of async operation
12a457
-         */
12a457
-        if (gio->glfd)
12a457
-                GF_REF_PUT (gio->glfd);
12a457
-
12a457
-	GF_FREE (gio->iov);
12a457
-	GF_FREE (gio);
12a457
-
12a457
-	return 0;
12a457
-}
12a457
-
12a457
-ssize_t
12a457
-pub_glfs_pwritev (struct glfs_fd *, const struct iovec *, int, off_t, int);
12a457
-
12a457
-int
12a457
-pub_glfs_ftruncate (struct glfs_fd *, off_t);
12a457
-
12a457
-int
12a457
-pub_glfs_fdatasync (struct glfs_fd *);
12a457
-
12a457
-int
12a457
-pub_glfs_fsync (struct glfs_fd *glfd);
12a457
-
12a457
-int
12a457
-pub_glfs_discard (struct glfs_fd *, off_t, size_t);
12a457
-
12a457
-int
12a457
-pub_glfs_zerofill (struct glfs_fd *, off_t, off_t);
12a457
-
12a457
-static int
12a457
-glfs_io_async_task (void *data)
12a457
-{
12a457
-	struct glfs_io *gio = data;
12a457
-	ssize_t         ret = 0;
12a457
-
12a457
-	switch (gio->op) {
12a457
-	case GF_FOP_WRITE:
12a457
-		ret = pub_glfs_pwritev (gio->glfd, gio->iov, gio->count,
12a457
-				    gio->offset, gio->flags);
12a457
-		break;
12a457
-	case GF_FOP_FTRUNCATE:
12a457
-		ret = pub_glfs_ftruncate (gio->glfd, gio->offset);
12a457
-		break;
12a457
-	case GF_FOP_FSYNC:
12a457
-		if (gio->flags)
12a457
-			ret = pub_glfs_fdatasync (gio->glfd);
12a457
-		else
12a457
-			ret = pub_glfs_fsync (gio->glfd);
12a457
-		break;
12a457
-	case GF_FOP_DISCARD:
12a457
-		ret = pub_glfs_discard (gio->glfd, gio->offset, gio->count);
12a457
-		break;
12a457
-        case GF_FOP_ZEROFILL:
12a457
-                ret = pub_glfs_zerofill(gio->glfd, gio->offset, gio->count);
12a457
-                break;
12a457
-	}
12a457
-
12a457
-	return (int) ret;
12a457
-}
12a457
-
12a457
-
12a457
-int
12a457
-glfs_preadv_async_cbk (call_frame_t *frame, void *cookie, xlator_t *this,
12a457
-		       int op_ret, int op_errno, struct iovec *iovec,
12a457
-		       int count, struct iatt *stbuf, struct iobref *iobref,
12a457
-		       dict_t *xdata)
12a457
-{
12a457
-	struct glfs_io *gio = NULL;
12a457
-	xlator_t       *subvol = NULL;
12a457
-	struct glfs    *fs = NULL;
12a457
-	struct glfs_fd *glfd = NULL;
12a457
+        struct glfs_io *gio = NULL;
12a457
+        xlator_t       *subvol = NULL;
12a457
+        struct glfs    *fs = NULL;
12a457
+        struct glfs_fd *glfd = NULL;
12a457
+        int             ret  = -1;
12a457
 
12a457
+        GF_VALIDATE_OR_GOTO ("gfapi", frame, inval);
12a457
+        GF_VALIDATE_OR_GOTO ("gfapi", cookie, inval);
12a457
+        GF_VALIDATE_OR_GOTO ("gfapi", iovec, inval);
12a457
 
12a457
-	gio = frame->local;
12a457
-	frame->local = NULL;
12a457
-	subvol = cookie;
12a457
-	glfd = gio->glfd;
12a457
-	fs = glfd->fs;
12a457
+        gio = frame->local;
12a457
+        frame->local = NULL;
12a457
+        subvol = cookie;
12a457
+        glfd = gio->glfd;
12a457
+        fs = glfd->fs;
12a457
 
12a457
         if (!glfs_is_glfd_still_valid (glfd))
12a457
                 goto err;
12a457
 
12a457
-	if (op_ret <= 0)
12a457
-		goto out;
12a457
-
12a457
-	op_ret = iov_copy (gio->iov, gio->count, iovec, count);
12a457
+        if (op_ret <= 0) {
12a457
+                goto out;
12a457
+        } else if (gio->op == GF_FOP_READ) {
12a457
+                op_ret = iov_copy (gio->iov, gio->count, iovec, count);
12a457
+                glfd->offset = gio->offset + op_ret;
12a457
+        } else if (gio->op == GF_FOP_WRITE) {
12a457
+                glfd->offset = gio->offset + gio->iov->iov_len;
12a457
+        }
12a457
 
12a457
-	glfd->offset = gio->offset + op_ret;
12a457
 out:
12a457
-	errno = op_errno;
12a457
-	gio->fn (gio->glfd, op_ret, gio->data);
12a457
+        errno = op_errno;
12a457
+        gio->fn (gio->glfd, op_ret, gio->data);
12a457
 
12a457
 err:
12a457
+        fd_unref (glfd->fd);
12a457
         /* Since the async operation is complete
12a457
          * release the ref taken during the start
12a457
          * of async operation
12a457
          */
12a457
         GF_REF_PUT (glfd);
12a457
 
12a457
-	GF_FREE (gio->iov);
12a457
-	GF_FREE (gio);
12a457
-	STACK_DESTROY (frame->root);
12a457
-	glfs_subvol_done (fs, subvol);
12a457
+        GF_FREE (gio->iov);
12a457
+        GF_FREE (gio);
12a457
+        STACK_DESTROY (frame->root);
12a457
+        glfs_subvol_done (fs, subvol);
12a457
+
12a457
+        ret = 0;
12a457
+inval:
12a457
+        return ret;
12a457
+}
12a457
+
12a457
+static int
12a457
+glfs_preadv_async_cbk (call_frame_t *frame, void *cookie, xlator_t *this,
12a457
+                       int op_ret, int op_errno, struct iovec *iovec,
12a457
+                       int count, struct iatt *stbuf, struct iobref *iobref,
12a457
+                       dict_t *xdata)
12a457
+{
12a457
+        glfs_io_async_cbk (op_ret, op_errno, frame, cookie, iovec, count);
12a457
 
12a457
 	return 0;
12a457
 }
12a457
@@ -934,9 +879,6 @@ out:
12a457
 		glfs_subvol_done (fs, subvol);
12a457
 	}
12a457
 
12a457
-	if (fd)
12a457
-		fd_unref (fd);
12a457
-
12a457
         __GLFS_EXIT_FS;
12a457
 
12a457
 	return ret;
12a457
@@ -998,13 +940,56 @@ pub_glfs_readv_async (struct glfs_fd *glfd, const struct iovec *iov, int count,
12a457
 GFAPI_SYMVER_PUBLIC_DEFAULT(glfs_readv_async, 3.4.0);
12a457
 
12a457
 
12a457
+static int
12a457
+glfs_buf_copy (xlator_t *subvol, const struct iovec *iovec_src, int iovcnt,
12a457
+               struct iobref **iobref, struct iobuf **iobuf,
12a457
+               struct iovec *iov_dst)
12a457
+{
12a457
+        size_t         size = -1;
12a457
+        int            ret  = 0;
12a457
+
12a457
+        size = iov_length (iovec_src, iovcnt);
12a457
+
12a457
+        *iobuf = iobuf_get2 (subvol->ctx->iobuf_pool, size);
12a457
+        if (!(*iobuf)) {
12a457
+                ret = -1;
12a457
+                errno = ENOMEM;
12a457
+                goto out;
12a457
+        }
12a457
+
12a457
+        *iobref = iobref_new ();
12a457
+        if (!(*iobref)) {
12a457
+                iobuf_unref (*iobuf);
12a457
+                errno = ENOMEM;
12a457
+                ret = -1;
12a457
+                goto out;
12a457
+        }
12a457
+
12a457
+        ret = iobref_add (*iobref, *iobuf);
12a457
+        if (ret) {
12a457
+                iobuf_unref (*iobuf);
12a457
+                iobref_unref (*iobref);
12a457
+                errno = ENOMEM;
12a457
+                ret = -1;
12a457
+                goto out;
12a457
+        }
12a457
+
12a457
+        iov_unload (iobuf_ptr (*iobuf), iovec_src, iovcnt);  /* FIXME!!! */
12a457
+
12a457
+        iov_dst->iov_base = iobuf_ptr (*iobuf);
12a457
+        iov_dst->iov_len = size;
12a457
+
12a457
+out:
12a457
+        return ret;
12a457
+}
12a457
+
12a457
+
12a457
 ssize_t
12a457
 pub_glfs_pwritev (struct glfs_fd *glfd, const struct iovec *iovec, int iovcnt,
12a457
                   off_t offset, int flags)
12a457
 {
12a457
 	xlator_t       *subvol = NULL;
12a457
 	int             ret = -1;
12a457
-	size_t          size = -1;
12a457
 	struct iobref  *iobref = NULL;
12a457
 	struct iobuf   *iobuf = NULL;
12a457
 	struct iovec    iov = {0, };
12a457
@@ -1029,50 +1014,24 @@ pub_glfs_pwritev (struct glfs_fd *glfd, const struct iovec *iovec, int iovcnt,
12a457
 		goto out;
12a457
 	}
12a457
 
12a457
-	size = iov_length (iovec, iovcnt);
12a457
-
12a457
-	iobuf = iobuf_get2 (subvol->ctx->iobuf_pool, size);
12a457
-	if (!iobuf) {
12a457
-		ret = -1;
12a457
-		errno = ENOMEM;
12a457
-		goto out;
12a457
-	}
12a457
-
12a457
-	iobref = iobref_new ();
12a457
-	if (!iobref) {
12a457
-		iobuf_unref (iobuf);
12a457
-		errno = ENOMEM;
12a457
-		ret = -1;
12a457
-		goto out;
12a457
-	}
12a457
-
12a457
-	ret = iobref_add (iobref, iobuf);
12a457
-	if (ret) {
12a457
-		iobuf_unref (iobuf);
12a457
-		iobref_unref (iobref);
12a457
-		errno = ENOMEM;
12a457
-		ret = -1;
12a457
-		goto out;
12a457
-	}
12a457
-
12a457
-	iov_unload (iobuf_ptr (iobuf), iovec, iovcnt);  /* FIXME!!! */
12a457
-
12a457
-	iov.iov_base = iobuf_ptr (iobuf);
12a457
-	iov.iov_len = size;
12a457
+        ret = glfs_buf_copy (subvol, iovec, iovcnt, &iobref, &iobuf, &iov;;
12a457
+        if (ret)
12a457
+                goto out;
12a457
 
12a457
 	ret = syncop_writev (subvol, fd, &iov, 1, offset, iobref, flags, NULL,
12a457
                              NULL);
12a457
         DECODE_SYNCOP_ERR (ret);
12a457
 
12a457
-	iobuf_unref (iobuf);
12a457
-	iobref_unref (iobref);
12a457
-
12a457
 	if (ret <= 0)
12a457
 		goto out;
12a457
 
12a457
-	glfd->offset = (offset + size);
12a457
+	glfd->offset = (offset + iov.iov_len);
12a457
 
12a457
 out:
12a457
+        if (iobuf)
12a457
+                iobuf_unref (iobuf);
12a457
+        if (iobref)
12a457
+                iobref_unref (iobref);
12a457
 	if (fd)
12a457
 		fd_unref (fd);
12a457
         if (glfd)
12a457
@@ -1140,6 +1099,17 @@ GFAPI_SYMVER_PUBLIC_DEFAULT(glfs_pwrite, 3.4.0);
12a457
 
12a457
 extern glfs_t *pub_glfs_from_glfd (glfs_fd_t *);
12a457
 
12a457
+
12a457
+static int
12a457
+glfs_pwritev_async_cbk (call_frame_t *frame, void *cookie, xlator_t *this,
12a457
+                        int op_ret, int op_errno, struct iatt *prebuf,
12a457
+                        struct iatt *postbuf, dict_t *xdata)
12a457
+{
12a457
+        glfs_io_async_cbk (op_ret, op_errno, frame, cookie, NULL, 0);
12a457
+
12a457
+        return 0;
12a457
+}
12a457
+
12a457
 int
12a457
 pub_glfs_pwritev_async (struct glfs_fd *glfd, const struct iovec *iovec,
12a457
                         int count, off_t offset, int flags, glfs_io_cbk fn,
12a457
@@ -1147,47 +1117,84 @@ pub_glfs_pwritev_async (struct glfs_fd *glfd, const struct iovec *iovec,
12a457
 {
12a457
 	struct glfs_io *gio = NULL;
12a457
 	int             ret = -1;
12a457
+        call_frame_t   *frame = NULL;
12a457
+        xlator_t       *subvol = NULL;
12a457
+        fd_t           *fd = NULL;
12a457
+        struct iobref  *iobref = NULL;
12a457
+        struct iobuf   *iobuf = NULL;
12a457
 
12a457
         DECLARE_OLD_THIS;
12a457
         __GLFS_ENTRY_VALIDATE_FD (glfd, invalid_fs);
12a457
 
12a457
-	gio = GF_CALLOC (1, sizeof (*gio), glfs_mt_glfs_io_t);
12a457
-	if (!gio) {
12a457
-		errno = ENOMEM;
12a457
-		goto out;
12a457
-	}
12a457
-
12a457
-	gio->iov = iov_dup (iovec, count);
12a457
-	if (!gio->iov) {
12a457
-		GF_FREE (gio);
12a457
-		errno = ENOMEM;
12a457
-		goto out;
12a457
-	}
12a457
-
12a457
-	gio->op     = GF_FOP_WRITE;
12a457
-	gio->glfd   = glfd;
12a457
-	gio->count  = count;
12a457
-	gio->offset = offset;
12a457
-	gio->flags  = flags;
12a457
-	gio->fn     = fn;
12a457
-	gio->data   = data;
12a457
-
12a457
         /* Need to take explicit ref so that the fd
12a457
          * is not destroyed before the fop is complete
12a457
          */
12a457
         GF_REF_GET (glfd);
12a457
 
12a457
-	ret = synctask_new (pub_glfs_from_glfd (glfd)->ctx->env,
12a457
-			    glfs_io_async_task, glfs_io_async_cbk,
12a457
-			    NULL, gio);
12a457
+        subvol = glfs_active_subvol (glfd->fs);
12a457
+        if (!subvol) {
12a457
+                errno = EIO;
12a457
+                goto out;
12a457
+        }
12a457
 
12a457
-	if (ret) {
12a457
-                GF_REF_PUT (glfd);
12a457
-		GF_FREE (gio->iov);
12a457
-		GF_FREE (gio);
12a457
-	}
12a457
+        fd = glfs_resolve_fd (glfd->fs, subvol, glfd);
12a457
+        if (!fd) {
12a457
+                errno = EBADFD;
12a457
+                goto out;
12a457
+        }
12a457
+
12a457
+        gio = GF_CALLOC (1, sizeof (*gio), glfs_mt_glfs_io_t);
12a457
+        if (!gio) {
12a457
+                errno = ENOMEM;
12a457
+                goto out;
12a457
+        }
12a457
+
12a457
+        gio->op     = GF_FOP_WRITE;
12a457
+        gio->glfd   = glfd;
12a457
+        gio->count  = count;
12a457
+        gio->offset = offset;
12a457
+        gio->flags  = flags;
12a457
+        gio->fn     = fn;
12a457
+        gio->data   = data;
12a457
+        gio->iov = GF_CALLOC (1, sizeof (*(gio->iov)), gf_common_mt_iovec);
12a457
+        if (!gio->iov) {
12a457
+                errno = ENOMEM;
12a457
+                goto out;
12a457
+        }
12a457
+
12a457
+        ret = glfs_buf_copy (subvol, iovec, count, &iobref, &iobuf, gio->iov);
12a457
+        if (ret)
12a457
+                goto out;
12a457
 
12a457
+        frame = syncop_create_frame (THIS);
12a457
+        if (!frame) {
12a457
+                errno = ENOMEM;
12a457
+                goto out;
12a457
+        }
12a457
+
12a457
+        frame->local = gio;
12a457
+
12a457
+        STACK_WIND_COOKIE (frame, glfs_pwritev_async_cbk, subvol, subvol,
12a457
+                           subvol->fops->writev, fd, gio->iov,
12a457
+                           gio->count, offset, flags, iobref, NULL);
12a457
+
12a457
+        ret = 0;
12a457
 out:
12a457
+        if (ret) {
12a457
+                if (glfd)
12a457
+                        GF_REF_PUT (glfd);
12a457
+                GF_FREE (gio);
12a457
+                if (frame)
12a457
+                        STACK_DESTROY (frame->root);
12a457
+
12a457
+                glfs_subvol_done (glfd->fs, subvol);
12a457
+        }
12a457
+
12a457
+        if (iobuf)
12a457
+                iobuf_unref (iobuf);
12a457
+        if (iobref)
12a457
+                iobref_unref (iobref);
12a457
+
12a457
         __GLFS_EXIT_FS;
12a457
 
12a457
 invalid_fs:
12a457
@@ -1291,6 +1298,16 @@ invalid_fs:
12a457
 
12a457
 GFAPI_SYMVER_PUBLIC_DEFAULT(glfs_fsync, 3.4.0);
12a457
 
12a457
+static int
12a457
+glfs_fsync_async_cbk (call_frame_t *frame, void *cookie,
12a457
+                      xlator_t *this, int32_t op_ret,
12a457
+                      int32_t op_errno, struct iatt *prebuf,
12a457
+                      struct iatt *postbuf, dict_t *xdata)
12a457
+{
12a457
+        glfs_io_async_cbk (op_ret, op_errno, frame, cookie, NULL, 0);
12a457
+
12a457
+        return 0;
12a457
+}
12a457
 
12a457
 static int
12a457
 glfs_fsync_async_common (struct glfs_fd *glfd, glfs_io_cbk fn, void *data,
12a457
@@ -1298,36 +1315,65 @@ glfs_fsync_async_common (struct glfs_fd *glfd, glfs_io_cbk fn, void *data,
12a457
 {
12a457
 	struct glfs_io *gio = NULL;
12a457
 	int             ret = 0;
12a457
-
12a457
-	gio = GF_CALLOC (1, sizeof (*gio), glfs_mt_glfs_io_t);
12a457
-	if (!gio) {
12a457
-		errno = ENOMEM;
12a457
-		return -1;
12a457
-	}
12a457
+        call_frame_t   *frame = NULL;
12a457
+        xlator_t       *subvol = NULL;
12a457
+        fd_t           *fd = NULL;
12a457
 
12a457
         /* Need to take explicit ref so that the fd
12a457
          * is not destroyed before the fop is complete
12a457
          */
12a457
         GF_REF_GET (glfd);
12a457
 
12a457
+        subvol = glfs_active_subvol (glfd->fs);
12a457
+        if (!subvol) {
12a457
+                ret = -1;
12a457
+                errno = EIO;
12a457
+                goto out;
12a457
+        }
12a457
+
12a457
+        fd = glfs_resolve_fd (glfd->fs, subvol, glfd);
12a457
+        if (!fd) {
12a457
+                ret = -1;
12a457
+                errno = EBADFD;
12a457
+                goto out;
12a457
+        }
12a457
+
12a457
+        frame = syncop_create_frame (THIS);
12a457
+        if (!frame) {
12a457
+                ret = -1;
12a457
+                errno = ENOMEM;
12a457
+                goto out;
12a457
+        }
12a457
+
12a457
+        gio = GF_CALLOC (1, sizeof (*gio), glfs_mt_glfs_io_t);
12a457
+        if (!gio) {
12a457
+                errno = ENOMEM;
12a457
+                ret = -1;
12a457
+                goto out;
12a457
+        }
12a457
+
12a457
 	gio->op     = GF_FOP_FSYNC;
12a457
 	gio->glfd   = glfd;
12a457
 	gio->flags  = dataonly;
12a457
 	gio->fn     = fn;
12a457
 	gio->data   = data;
12a457
 
12a457
-	ret = synctask_new (pub_glfs_from_glfd (glfd)->ctx->env,
12a457
-			    glfs_io_async_task, glfs_io_async_cbk,
12a457
-			    NULL, gio);
12a457
+        frame->local = gio;
12a457
 
12a457
-	if (ret) {
12a457
-                GF_REF_PUT (glfd);
12a457
-		GF_FREE (gio->iov);
12a457
-		GF_FREE (gio);
12a457
-	}
12a457
+        STACK_WIND_COOKIE (frame, glfs_fsync_async_cbk, subvol, subvol,
12a457
+                           subvol->fops->fsync, fd, dataonly, NULL);
12a457
 
12a457
-	return ret;
12a457
+out:
12a457
+        if (ret) {
12a457
+                if (glfd)
12a457
+                        GF_REF_PUT (glfd);
12a457
+                GF_FREE (gio);
12a457
+                if (frame)
12a457
+                        STACK_DESTROY (frame->root);
12a457
+                glfs_subvol_done (glfd->fs, subvol);
12a457
+        }
12a457
 
12a457
+        return ret;
12a457
 }
12a457
 
12a457
 
12a457
@@ -1458,6 +1504,16 @@ invalid_fs:
12a457
 
12a457
 GFAPI_SYMVER_PUBLIC_DEFAULT(glfs_ftruncate, 3.4.0);
12a457
 
12a457
+static int
12a457
+glfs_ftruncate_async_cbk (call_frame_t *frame, void *cookie, xlator_t *this,
12a457
+                          int32_t op_ret, int32_t op_errno,
12a457
+                          struct iatt *prebuf, struct iatt *postbuf,
12a457
+                          dict_t *xdata)
12a457
+{
12a457
+        glfs_io_async_cbk (op_ret, op_errno, frame, cookie, NULL, 0);
12a457
+
12a457
+        return 0;
12a457
+}
12a457
 
12a457
 int
12a457
 pub_glfs_ftruncate_async (struct glfs_fd *glfd, off_t offset, glfs_io_cbk fn,
12a457
@@ -1465,10 +1521,36 @@ pub_glfs_ftruncate_async (struct glfs_fd *glfd, off_t offset, glfs_io_cbk fn,
12a457
 {
12a457
 	struct glfs_io *gio = NULL;
12a457
 	int             ret = -1;
12a457
+        call_frame_t   *frame = NULL;
12a457
+        xlator_t       *subvol = NULL;
12a457
+        fd_t           *fd = NULL;
12a457
 
12a457
         DECLARE_OLD_THIS;
12a457
         __GLFS_ENTRY_VALIDATE_FD (glfd, invalid_fs);
12a457
 
12a457
+        /* Need to take explicit ref so that the fd
12a457
+         * is not destroyed before the fop is complete
12a457
+         */
12a457
+        GF_REF_GET (glfd);
12a457
+
12a457
+        subvol = glfs_active_subvol (glfd->fs);
12a457
+        if (!subvol) {
12a457
+                errno = EIO;
12a457
+                goto out;
12a457
+        }
12a457
+
12a457
+        fd = glfs_resolve_fd (glfd->fs, subvol, glfd);
12a457
+        if (!fd) {
12a457
+                errno = EBADFD;
12a457
+                goto out;
12a457
+        }
12a457
+
12a457
+        frame = syncop_create_frame (THIS);
12a457
+        if (!frame) {
12a457
+                errno = ENOMEM;
12a457
+                goto out;
12a457
+        }
12a457
+
12a457
 	gio = GF_CALLOC (1, sizeof (*gio), glfs_mt_glfs_io_t);
12a457
 	if (!gio) {
12a457
 		errno = ENOMEM;
12a457
@@ -1481,22 +1563,23 @@ pub_glfs_ftruncate_async (struct glfs_fd *glfd, off_t offset, glfs_io_cbk fn,
12a457
 	gio->fn     = fn;
12a457
 	gio->data   = data;
12a457
 
12a457
-        /* Need to take explicit ref so that the fd
12a457
-         * is not destroyed before the fop is complete
12a457
-         */
12a457
-        GF_REF_GET (glfd);
12a457
+        frame->local = gio;
12a457
 
12a457
-	ret = synctask_new (pub_glfs_from_glfd (glfd)->ctx->env,
12a457
-			    glfs_io_async_task, glfs_io_async_cbk,
12a457
-			    NULL, gio);
12a457
+        STACK_WIND_COOKIE (frame, glfs_ftruncate_async_cbk, subvol, subvol,
12a457
+                           subvol->fops->ftruncate, fd, offset, NULL);
12a457
 
12a457
-	if (ret) {
12a457
-                GF_REF_PUT (glfd);
12a457
-		GF_FREE (gio->iov);
12a457
-		GF_FREE (gio);
12a457
-	}
12a457
+        ret = 0;
12a457
 
12a457
 out:
12a457
+        if (ret) {
12a457
+                if (glfd)
12a457
+                        GF_REF_PUT (glfd);
12a457
+                GF_FREE (gio);
12a457
+                if (frame)
12a457
+                        STACK_DESTROY (frame->root);
12a457
+                glfs_subvol_done (glfd->fs, subvol);
12a457
+        }
12a457
+
12a457
         __GLFS_EXIT_FS;
12a457
 
12a457
 invalid_fs:
12a457
@@ -2277,6 +2360,16 @@ pub_glfs_seekdir (struct glfs_fd *fd, long offset)
12a457
 
12a457
 GFAPI_SYMVER_PUBLIC_DEFAULT(glfs_seekdir, 3.4.0);
12a457
 
12a457
+static int
12a457
+glfs_discard_async_cbk (call_frame_t *frame, void *cookie,
12a457
+                        xlator_t *this, int32_t op_ret,
12a457
+                        int32_t op_errno, struct iatt *preop_stbuf,
12a457
+                        struct iatt *postop_stbuf, dict_t *xdata)
12a457
+{
12a457
+        glfs_io_async_cbk (op_ret, op_errno, frame, cookie, NULL, 0);
12a457
+
12a457
+        return 0;
12a457
+}
12a457
 
12a457
 int
12a457
 pub_glfs_discard_async (struct glfs_fd *glfd, off_t offset, size_t len,
12a457
@@ -2284,6 +2377,9 @@ pub_glfs_discard_async (struct glfs_fd *glfd, off_t offset, size_t len,
12a457
 {
12a457
 	struct glfs_io *gio = NULL;
12a457
 	int             ret = -1;
12a457
+        call_frame_t   *frame = NULL;
12a457
+        xlator_t       *subvol = NULL;
12a457
+        fd_t           *fd = NULL;
12a457
 
12a457
         DECLARE_OLD_THIS;
12a457
         __GLFS_ENTRY_VALIDATE_FD (glfd, invalid_fs);
12a457
@@ -2293,6 +2389,24 @@ pub_glfs_discard_async (struct glfs_fd *glfd, off_t offset, size_t len,
12a457
          */
12a457
         GF_REF_GET (glfd);
12a457
 
12a457
+        subvol = glfs_active_subvol (glfd->fs);
12a457
+        if (!subvol) {
12a457
+                errno = EIO;
12a457
+                goto out;
12a457
+        }
12a457
+
12a457
+        fd = glfs_resolve_fd (glfd->fs, subvol, glfd);
12a457
+        if (!fd) {
12a457
+                errno = EBADFD;
12a457
+                goto out;
12a457
+        }
12a457
+
12a457
+        frame = syncop_create_frame (THIS);
12a457
+        if (!frame) {
12a457
+                errno = ENOMEM;
12a457
+                goto out;
12a457
+        }
12a457
+
12a457
 	gio = GF_CALLOC (1, sizeof (*gio), glfs_mt_glfs_io_t);
12a457
 	if (!gio) {
12a457
 		errno = ENOMEM;
12a457
@@ -2306,17 +2420,22 @@ pub_glfs_discard_async (struct glfs_fd *glfd, off_t offset, size_t len,
12a457
 	gio->fn     = fn;
12a457
 	gio->data   = data;
12a457
 
12a457
-	ret = synctask_new (pub_glfs_from_glfd (glfd)->ctx->env,
12a457
-			    glfs_io_async_task, glfs_io_async_cbk,
12a457
-			    NULL, gio);
12a457
+        frame->local = gio;
12a457
 
12a457
-	if (ret) {
12a457
-                GF_REF_PUT (glfd);
12a457
-		GF_FREE (gio->iov);
12a457
-		GF_FREE (gio);
12a457
-	}
12a457
+        STACK_WIND_COOKIE (frame, glfs_discard_async_cbk, subvol, subvol,
12a457
+                           subvol->fops->discard, fd, offset, len, NULL);
12a457
 
12a457
+        ret = 0;
12a457
 out:
12a457
+        if (ret) {
12a457
+                if (glfd)
12a457
+                        GF_REF_PUT (glfd);
12a457
+                GF_FREE (gio);
12a457
+                if (frame)
12a457
+                        STACK_DESTROY (frame->root);
12a457
+                glfs_subvol_done (glfd->fs, subvol);
12a457
+        }
12a457
+
12a457
         __GLFS_EXIT_FS;
12a457
 
12a457
 invalid_fs:
12a457
@@ -2326,12 +2445,27 @@ invalid_fs:
12a457
 GFAPI_SYMVER_PUBLIC_DEFAULT(glfs_discard_async, 3.5.0);
12a457
 
12a457
 
12a457
+static int
12a457
+glfs_zerofill_async_cbk (call_frame_t *frame, void *cookie,
12a457
+                         xlator_t *this, int32_t op_ret,
12a457
+                         int32_t op_errno, struct iatt *preop_stbuf,
12a457
+                         struct iatt *postop_stbuf, dict_t *xdata)
12a457
+{
12a457
+        glfs_io_async_cbk (op_ret, op_errno, frame, cookie, NULL, 0);
12a457
+
12a457
+        return 0;
12a457
+}
12a457
+
12a457
+
12a457
 int
12a457
 pub_glfs_zerofill_async (struct glfs_fd *glfd, off_t offset, off_t len,
12a457
                          glfs_io_cbk fn, void *data)
12a457
 {
12a457
         struct glfs_io *gio  = NULL;
12a457
         int             ret  = -1;
12a457
+        call_frame_t   *frame = NULL;
12a457
+        xlator_t       *subvol = NULL;
12a457
+        fd_t           *fd = NULL;
12a457
 
12a457
         DECLARE_OLD_THIS;
12a457
         __GLFS_ENTRY_VALIDATE_FD (glfd, invalid_fs);
12a457
@@ -2341,6 +2475,24 @@ pub_glfs_zerofill_async (struct glfs_fd *glfd, off_t offset, off_t len,
12a457
          */
12a457
         GF_REF_GET (glfd);
12a457
 
12a457
+        subvol = glfs_active_subvol (glfd->fs);
12a457
+        if (!subvol) {
12a457
+                errno = EIO;
12a457
+                goto out;
12a457
+        }
12a457
+
12a457
+        fd = glfs_resolve_fd (glfd->fs, subvol, glfd);
12a457
+        if (!fd) {
12a457
+                errno = EBADFD;
12a457
+                goto out;
12a457
+        }
12a457
+
12a457
+        frame = syncop_create_frame (THIS);
12a457
+        if (!frame) {
12a457
+                errno = ENOMEM;
12a457
+                goto out;
12a457
+        }
12a457
+
12a457
         gio = GF_CALLOC (1, sizeof (*gio), glfs_mt_glfs_io_t);
12a457
         if (!gio) {
12a457
                 errno = ENOMEM;
12a457
@@ -2354,17 +2506,21 @@ pub_glfs_zerofill_async (struct glfs_fd *glfd, off_t offset, off_t len,
12a457
         gio->fn     = fn;
12a457
         gio->data   = data;
12a457
 
12a457
-        ret = synctask_new (pub_glfs_from_glfd (glfd)->ctx->env,
12a457
-                            glfs_io_async_task, glfs_io_async_cbk,
12a457
-                            NULL, gio);
12a457
+        frame->local = gio;
12a457
 
12a457
+        STACK_WIND_COOKIE (frame, glfs_zerofill_async_cbk, subvol, subvol,
12a457
+                           subvol->fops->zerofill, fd, offset, len, NULL);
12a457
+        ret = 0;
12a457
+out:
12a457
         if (ret) {
12a457
-                GF_REF_PUT (glfd);
12a457
-                GF_FREE (gio->iov);
12a457
+                if (glfd)
12a457
+                        GF_REF_PUT (glfd);
12a457
                 GF_FREE (gio);
12a457
+                if (frame)
12a457
+                        STACK_DESTROY (frame->root);
12a457
+                glfs_subvol_done (glfd->fs, subvol);
12a457
         }
12a457
 
12a457
-out:
12a457
         __GLFS_EXIT_FS;
12a457
 
12a457
 invalid_fs:
12a457
-- 
12a457
1.7.1
12a457