}
 
 void
-cifs_writedata_release(struct kref *refcount)
+cifs_writedata_release(struct cifs_io_subrequest *wdata)
 {
-       struct cifs_writedata *wdata = container_of(refcount,
-                                       struct cifs_writedata, refcount);
+       if (wdata->uncached)
+               kref_put(&wdata->ctx->refcount, cifs_aio_ctx_release);
 #ifdef CONFIG_CIFS_SMB_DIRECT
        if (wdata->mr) {
                smbd_deregister_mr(wdata->mr);
  * possible that the page was redirtied so re-clean the page.
  */
 static void
-cifs_writev_requeue(struct cifs_writedata *wdata)
+cifs_writev_requeue(struct cifs_io_subrequest *wdata)
 {
        int rc = 0;
        struct inode *inode = d_inode(wdata->cfile->dentry);
 
        server = tlink_tcon(wdata->cfile->tlink)->ses->server;
        do {
-               struct cifs_writedata *wdata2;
+               struct cifs_io_subrequest *wdata2;
                unsigned int wsize, cur_len;
 
                wsize = server->ops->wp_retry_size(inode);
                wdata2->sync_mode = wdata->sync_mode;
                wdata2->offset  = fpos;
                wdata2->bytes   = cur_len;
-               wdata2->iter    = wdata->iter;
+               wdata2->iter = wdata->iter;
 
                iov_iter_advance(&wdata2->iter, fpos - wdata->offset);
                iov_iter_truncate(&wdata2->iter, wdata2->bytes);
                                rc = -EBADF;
                } else {
                        wdata2->pid = wdata2->cfile->pid;
-                       rc = server->ops->async_writev(wdata2,
-                                                      cifs_writedata_release);
+                       rc = server->ops->async_writev(wdata2);
                }
 
-               kref_put(&wdata2->refcount, cifs_writedata_release);
+               cifs_put_writedata(wdata2);
                if (rc) {
                        if (is_retryable_error(rc))
                                continue;
 
        if (rc != 0 && !is_retryable_error(rc))
                mapping_set_error(inode->i_mapping, rc);
-       kref_put(&wdata->refcount, cifs_writedata_release);
+       cifs_put_writedata(wdata);
 }
 
 void
 cifs_writev_complete(struct work_struct *work)
 {
-       struct cifs_writedata *wdata = container_of(work,
-                                               struct cifs_writedata, work);
+       struct cifs_io_subrequest *wdata = container_of(work,
+                                               struct cifs_io_subrequest, work);
        struct inode *inode = d_inode(wdata->cfile->dentry);
 
        if (wdata->result == 0) {
 
        if (wdata->result != -EAGAIN)
                mapping_set_error(inode->i_mapping, wdata->result);
-       kref_put(&wdata->refcount, cifs_writedata_release);
+       cifs_put_writedata(wdata);
 }
 
-struct cifs_writedata *cifs_writedata_alloc(work_func_t complete)
+struct cifs_io_subrequest *cifs_writedata_alloc(work_func_t complete)
 {
-       struct cifs_writedata *wdata;
+       struct cifs_io_subrequest *wdata;
 
        wdata = kzalloc(sizeof(*wdata), GFP_NOFS);
        if (wdata != NULL) {
-               kref_init(&wdata->refcount);
+               refcount_set(&wdata->subreq.ref, 1);
                INIT_LIST_HEAD(&wdata->list);
                init_completion(&wdata->done);
                INIT_WORK(&wdata->work, complete);
 {
        struct inode *inode = mapping->host;
        struct TCP_Server_Info *server;
-       struct cifs_writedata *wdata;
+       struct cifs_io_subrequest *wdata;
        struct cifs_sb_info *cifs_sb = CIFS_SB(inode->i_sb);
        struct cifs_credits credits_on_stack;
        struct cifs_credits *credits = &credits_on_stack;
                if (wdata->cfile->invalidHandle)
                        rc = -EAGAIN;
                else
-                       rc = wdata->server->ops->async_writev(wdata,
-                                                             cifs_writedata_release);
+                       rc = wdata->server->ops->async_writev(wdata);
                if (rc >= 0) {
-                       kref_put(&wdata->refcount, cifs_writedata_release);
+                       cifs_put_writedata(wdata);
                        goto err_close;
                }
        } else {
        }
 
 err_wdata:
-       kref_put(&wdata->refcount, cifs_writedata_release);
+       cifs_put_writedata(wdata);
 err_uncredit:
        add_credits_and_wake_if(server, credits, 0);
 err_close:
        return rc;
 }
 
-static void
-cifs_uncached_writedata_release(struct kref *refcount)
-{
-       struct cifs_writedata *wdata = container_of(refcount,
-                                       struct cifs_writedata, refcount);
-
-       kref_put(&wdata->ctx->refcount, cifs_aio_ctx_release);
-       cifs_writedata_release(refcount);
-}
-
 static void collect_uncached_write_data(struct cifs_aio_ctx *ctx);
 
 static void
 cifs_uncached_writev_complete(struct work_struct *work)
 {
-       struct cifs_writedata *wdata = container_of(work,
-                                       struct cifs_writedata, work);
+       struct cifs_io_subrequest *wdata = container_of(work,
+                                       struct cifs_io_subrequest, work);
        struct inode *inode = d_inode(wdata->cfile->dentry);
        struct cifsInodeInfo *cifsi = CIFS_I(inode);
 
        complete(&wdata->done);
        collect_uncached_write_data(wdata->ctx);
        /* the below call can possibly free the last ref to aio ctx */
-       kref_put(&wdata->refcount, cifs_uncached_writedata_release);
+       cifs_put_writedata(wdata);
 }
 
 static int
-cifs_resend_wdata(struct cifs_writedata *wdata, struct list_head *wdata_list,
+cifs_resend_wdata(struct cifs_io_subrequest *wdata, struct list_head *wdata_list,
        struct cifs_aio_ctx *ctx)
 {
        unsigned int wsize;
                                        wdata->mr = NULL;
                                }
 #endif
-                               rc = server->ops->async_writev(wdata,
-                                       cifs_uncached_writedata_release);
+                               rc = server->ops->async_writev(wdata);
                        }
                }
 
        } while (rc == -EAGAIN);
 
 fail:
-       kref_put(&wdata->refcount, cifs_uncached_writedata_release);
+       cifs_put_writedata(wdata);
        return rc;
 }
 
 {
        int rc = 0;
        size_t cur_len, max_len;
-       struct cifs_writedata *wdata;
+       struct cifs_io_subrequest *wdata;
        pid_t pid;
        struct TCP_Server_Info *server;
        unsigned int xid, max_segs = INT_MAX;
                        break;
                }
 
+               wdata->uncached = true;
                wdata->sync_mode = WB_SYNC_ALL;
                wdata->offset   = (__u64)fpos;
                wdata->cfile    = cifsFileInfo_get(open_file);
                        if (wdata->cfile->invalidHandle)
                                rc = -EAGAIN;
                        else
-                               rc = server->ops->async_writev(wdata,
-                                       cifs_uncached_writedata_release);
+                               rc = server->ops->async_writev(wdata);
                }
 
                if (rc) {
                        add_credits_and_wake_if(server, &wdata->credits, 0);
-                       kref_put(&wdata->refcount,
-                                cifs_uncached_writedata_release);
+                       cifs_put_writedata(wdata);
                        if (rc == -EAGAIN)
                                continue;
                        break;
 
 static void collect_uncached_write_data(struct cifs_aio_ctx *ctx)
 {
-       struct cifs_writedata *wdata, *tmp;
+       struct cifs_io_subrequest *wdata, *tmp;
        struct cifs_tcon *tcon;
        struct cifs_sb_info *cifs_sb;
        struct dentry *dentry = ctx->cfile->dentry;
                                                ctx->cfile, cifs_sb, &tmp_list,
                                                ctx);
 
-                                       kref_put(&wdata->refcount,
-                                               cifs_uncached_writedata_release);
+                                       cifs_put_writedata(wdata);
                                }
 
                                list_splice(&tmp_list, &ctx->list);
                        }
                }
                list_del_init(&wdata->list);
-               kref_put(&wdata->refcount, cifs_uncached_writedata_release);
+               cifs_put_writedata(wdata);
        }
 
        cifs_stats_bytes_written(tcon, ctx->total_len);