cifs: Cut over to using netfslib
authorDavid Howells <dhowells@redhat.com>
Fri, 6 Oct 2023 17:29:59 +0000 (18:29 +0100)
committerDavid Howells <dhowells@redhat.com>
Wed, 1 May 2024 17:08:21 +0000 (18:08 +0100)
Make the cifs filesystem use netfslib to handle reading and writing on
behalf of cifs.  The changes include:

 (1) Various read_iter/write_iter type functions are turned into wrappers
     around netfslib API functions or are pointed directly at those
     functions:

cifs_file_direct{,_nobrl}_ops switch to use
netfs_unbuffered_read_iter and netfs_unbuffered_write_iter.

Large pieces of code that will be removed are #if'd out and will be removed
in subsequent patches.

[?] Why does cifs mark the page dirty in the destination buffer of a DIO
    read?  Should that happen automatically?  Does netfs need to do that?

Signed-off-by: David Howells <dhowells@redhat.com>
cc: Steve French <sfrench@samba.org>
cc: Shyam Prasad N <nspmangalore@gmail.com>
cc: Rohith Surabattula <rohiths.msft@gmail.com>
cc: Jeff Layton <jlayton@kernel.org>
cc: linux-cifs@vger.kernel.org
cc: netfs@lists.linux.dev
cc: linux-fsdevel@vger.kernel.org
cc: linux-mm@kvack.org

14 files changed:
fs/netfs/io.c
fs/smb/client/cifsfs.c
fs/smb/client/cifsfs.h
fs/smb/client/cifsglob.h
fs/smb/client/cifsproto.h
fs/smb/client/cifssmb.c
fs/smb/client/file.c
fs/smb/client/fscache.c
fs/smb/client/fscache.h
fs/smb/client/inode.c
fs/smb/client/smb2pdu.c
fs/smb/client/smb2proto.h
fs/smb/client/trace.h
fs/smb/client/transport.c

index 6cfecfcd02e14f372f4d3b8adde8da0f1eb30061..c93851b9836889e87257cd058eec8926201738b2 100644 (file)
@@ -213,8 +213,13 @@ static void netfs_rreq_assess_dio(struct netfs_io_request *rreq)
        unsigned int i;
        size_t transferred = 0;
 
-       for (i = 0; i < rreq->direct_bv_count; i++)
+       for (i = 0; i < rreq->direct_bv_count; i++) {
                flush_dcache_page(rreq->direct_bv[i].bv_page);
+               // TODO: cifs marks pages in the destination buffer
+               // dirty under some circumstances after a read.  Do we
+               // need to do that too?
+               set_page_dirty(rreq->direct_bv[i].bv_page);
+       }
 
        list_for_each_entry(subreq, &rreq->subrequests, rreq_link) {
                if (subreq->error || subreq->transferred == 0)
index 8f7165567be7f23994db7151d1f5a9bbefa192ec..6e1698614745b7c61bf23b17e6adaaa7ff68fbd8 100644 (file)
@@ -1522,8 +1522,8 @@ const struct file_operations cifs_file_strict_ops = {
 };
 
 const struct file_operations cifs_file_direct_ops = {
-       .read_iter = cifs_direct_readv,
-       .write_iter = cifs_direct_writev,
+       .read_iter = netfs_unbuffered_read_iter,
+       .write_iter = netfs_file_write_iter,
        .open = cifs_open,
        .release = cifs_close,
        .lock = cifs_lock,
@@ -1578,8 +1578,8 @@ const struct file_operations cifs_file_strict_nobrl_ops = {
 };
 
 const struct file_operations cifs_file_direct_nobrl_ops = {
-       .read_iter = cifs_direct_readv,
-       .write_iter = cifs_direct_writev,
+       .read_iter = netfs_unbuffered_read_iter,
+       .write_iter = netfs_file_write_iter,
        .open = cifs_open,
        .release = cifs_close,
        .fsync = cifs_fsync,
index 922c10d7cfdd8322abdd52b0fca1f2fc47c84bf4..87310f05d39765fa8fb692a0b13061febb8edd87 100644 (file)
@@ -94,11 +94,7 @@ extern const struct file_operations cifs_file_strict_nobrl_ops;
 extern int cifs_open(struct inode *inode, struct file *file);
 extern int cifs_close(struct inode *inode, struct file *file);
 extern int cifs_closedir(struct inode *inode, struct file *file);
-extern ssize_t cifs_user_readv(struct kiocb *iocb, struct iov_iter *to);
-extern ssize_t cifs_direct_readv(struct kiocb *iocb, struct iov_iter *to);
 extern ssize_t cifs_strict_readv(struct kiocb *iocb, struct iov_iter *to);
-extern ssize_t cifs_user_writev(struct kiocb *iocb, struct iov_iter *from);
-extern ssize_t cifs_direct_writev(struct kiocb *iocb, struct iov_iter *from);
 extern ssize_t cifs_strict_writev(struct kiocb *iocb, struct iov_iter *from);
 ssize_t cifs_file_write_iter(struct kiocb *iocb, struct iov_iter *from);
 ssize_t cifs_loose_read_iter(struct kiocb *iocb, struct iov_iter *iter);
@@ -112,9 +108,6 @@ extern int cifs_file_strict_mmap(struct file *file, struct vm_area_struct *vma);
 extern const struct file_operations cifs_dir_ops;
 extern int cifs_dir_open(struct inode *inode, struct file *file);
 extern int cifs_readdir(struct file *file, struct dir_context *ctx);
-extern void cifs_pages_written_back(struct inode *inode, loff_t start, unsigned int len);
-extern void cifs_pages_write_failed(struct inode *inode, loff_t start, unsigned int len);
-extern void cifs_pages_write_redirty(struct inode *inode, loff_t start, unsigned int len);
 
 /* Functions related to dir entries */
 extern const struct dentry_operations cifs_dentry_ops;
index 4e9033b2f1918d291793fd4fe4118b881ba13e58..983860bf5fbbc78e6bb424aa1304ce2932e90b7d 100644 (file)
@@ -451,7 +451,7 @@ struct smb_version_operations {
        /* async read from the server */
        int (*async_readv)(struct cifs_io_subrequest *);
        /* async write to the server */
-       int (*async_writev)(struct cifs_io_subrequest *);
+       void (*async_writev)(struct cifs_io_subrequest *);
        /* sync read from the server */
        int (*sync_read)(const unsigned int, struct cifs_fid *,
                         struct cifs_io_parms *, unsigned int *, char **,
@@ -1516,7 +1516,7 @@ struct cifs_io_subrequest {
 #endif
        struct cifs_credits             credits;
 
-       // TODO: Remove following elements
+#if 0 // TODO: Remove following elements
        struct list_head                list;
        struct completion               done;
        struct work_struct              work;
@@ -1526,6 +1526,7 @@ struct cifs_io_subrequest {
        enum writeback_sync_modes       sync_mode;
        bool                            uncached;
        struct bio_vec                  *bv;
+#endif
 };
 
 /*
index 103f264b42d781a13dae585161aa23813d491282..d46ad86150cd5fe935326b118e2acfd0443db50e 100644 (file)
@@ -148,6 +148,8 @@ extern bool is_size_safe_to_change(struct cifsInodeInfo *cifsInode, __u64 eof,
                                   bool from_readdir);
 extern void cifs_update_eof(struct cifsInodeInfo *cifsi, loff_t offset,
                            unsigned int bytes_written);
+void cifs_write_subrequest_terminated(struct cifs_io_subrequest *wdata, ssize_t result,
+                                     bool was_async);
 extern struct cifsFileInfo *find_writable_file(struct cifsInodeInfo *, int);
 extern int cifs_get_writable_file(struct cifsInodeInfo *cifs_inode,
                                  int flags,
@@ -599,6 +601,7 @@ void __cifs_put_smb_ses(struct cifs_ses *ses);
 extern struct cifs_ses *
 cifs_get_smb_ses(struct TCP_Server_Info *server, struct smb3_fs_context *ctx);
 
+#if 0 // TODO Remove
 void cifs_readdata_release(struct cifs_io_subrequest *rdata);
 static inline void cifs_get_readdata(struct cifs_io_subrequest *rdata)
 {
@@ -609,11 +612,13 @@ static inline void cifs_put_readdata(struct cifs_io_subrequest *rdata)
        if (refcount_dec_and_test(&rdata->subreq.ref))
                cifs_readdata_release(rdata);
 }
+#endif
 int cifs_async_readv(struct cifs_io_subrequest *rdata);
 int cifs_readv_receive(struct TCP_Server_Info *server, struct mid_q_entry *mid);
 
-int cifs_async_writev(struct cifs_io_subrequest *wdata);
+void cifs_async_writev(struct cifs_io_subrequest *wdata);
 void cifs_writev_complete(struct work_struct *work);
+#if 0 // TODO Remove
 struct cifs_io_subrequest *cifs_writedata_alloc(work_func_t complete);
 void cifs_writedata_release(struct cifs_io_subrequest *rdata);
 static inline void cifs_get_writedata(struct cifs_io_subrequest *wdata)
@@ -625,6 +630,7 @@ static inline void cifs_put_writedata(struct cifs_io_subrequest *wdata)
        if (refcount_dec_and_test(&wdata->subreq.ref))
                cifs_writedata_release(wdata);
 }
+#endif
 int cifs_query_mf_symlink(unsigned int xid, struct cifs_tcon *tcon,
                          struct cifs_sb_info *cifs_sb,
                          const unsigned char *path, char *pbuf,
index 99b75102ba6b225242ca74f7e2bc15784b9b524d..25e9ab947c1715a0dad0f65561cb051d30fb7345 100644 (file)
@@ -1265,7 +1265,7 @@ static void
 cifs_readv_callback(struct mid_q_entry *mid)
 {
        struct cifs_io_subrequest *rdata = mid->callback_data;
-       struct cifs_tcon *tcon = tlink_tcon(rdata->cfile->tlink);
+       struct cifs_tcon *tcon = tlink_tcon(rdata->req->cfile->tlink);
        struct TCP_Server_Info *server = tcon->ses->server;
        struct smb_rqst rqst = { .rq_iov = rdata->iov,
                                 .rq_nvec = 2,
@@ -1306,7 +1306,13 @@ cifs_readv_callback(struct mid_q_entry *mid)
                rdata->result = -EIO;
        }
 
-       queue_work(cifsiod_wq, &rdata->work);
+       if (rdata->result == 0 || rdata->result == -EAGAIN)
+               iov_iter_advance(&rdata->subreq.io_iter, rdata->got_bytes);
+       rdata->credits.value = 0;
+       netfs_subreq_terminated(&rdata->subreq,
+                               (rdata->result == 0 || rdata->result == -EAGAIN) ?
+                               rdata->got_bytes : rdata->result,
+                               false);
        release_mid(mid);
        add_credits(server, &credits, 0);
 }
@@ -1318,7 +1324,7 @@ cifs_async_readv(struct cifs_io_subrequest *rdata)
        int rc;
        READ_REQ *smb = NULL;
        int wct;
-       struct cifs_tcon *tcon = tlink_tcon(rdata->cfile->tlink);
+       struct cifs_tcon *tcon = tlink_tcon(rdata->req->cfile->tlink);
        struct smb_rqst rqst = { .rq_iov = rdata->iov,
                                 .rq_nvec = 2 };
 
@@ -1343,7 +1349,7 @@ cifs_async_readv(struct cifs_io_subrequest *rdata)
        smb->hdr.PidHigh = cpu_to_le16((__u16)(rdata->pid >> 16));
 
        smb->AndXCommand = 0xFF;        /* none */
-       smb->Fid = rdata->cfile->fid.netfid;
+       smb->Fid = rdata->req->cfile->fid.netfid;
        smb->OffsetLow = cpu_to_le32(rdata->subreq.start & 0xFFFFFFFF);
        if (wct == 12)
                smb->OffsetHigh = cpu_to_le32(rdata->subreq.start >> 32);
@@ -1613,15 +1619,16 @@ static void
 cifs_writev_callback(struct mid_q_entry *mid)
 {
        struct cifs_io_subrequest *wdata = mid->callback_data;
-       struct cifs_tcon *tcon = tlink_tcon(wdata->cfile->tlink);
-       unsigned int written;
+       struct cifs_tcon *tcon = tlink_tcon(wdata->req->cfile->tlink);
        WRITE_RSP *smb = (WRITE_RSP *)mid->resp_buf;
        struct cifs_credits credits = { .value = 1, .instance = 0 };
+       ssize_t result;
+       size_t written;
 
        switch (mid->mid_state) {
        case MID_RESPONSE_RECEIVED:
-               wdata->result = cifs_check_receive(mid, tcon->ses->server, 0);
-               if (wdata->result != 0)
+               result = cifs_check_receive(mid, tcon->ses->server, 0);
+               if (result != 0)
                        break;
 
                written = le16_to_cpu(smb->CountHigh);
@@ -1637,32 +1644,33 @@ cifs_writev_callback(struct mid_q_entry *mid)
                        written &= 0xFFFF;
 
                if (written < wdata->subreq.len)
-                       wdata->result = -ENOSPC;
+                       result = -ENOSPC;
                else
-                       wdata->subreq.len = written;
+                       result = written;
                break;
        case MID_REQUEST_SUBMITTED:
        case MID_RETRY_NEEDED:
-               wdata->result = -EAGAIN;
+               result = -EAGAIN;
                break;
        default:
-               wdata->result = -EIO;
+               result = -EIO;
                break;
        }
 
-       queue_work(cifsiod_wq, &wdata->work);
+       wdata->credits.value = 0;
+       cifs_write_subrequest_terminated(wdata, result, true);
        release_mid(mid);
        add_credits(tcon->ses->server, &credits, 0);
 }
 
 /* cifs_async_writev - send an async write, and set up mid to handle result */
-int
+void
 cifs_async_writev(struct cifs_io_subrequest *wdata)
 {
        int rc = -EACCES;
        WRITE_REQ *smb = NULL;
        int wct;
-       struct cifs_tcon *tcon = tlink_tcon(wdata->cfile->tlink);
+       struct cifs_tcon *tcon = tlink_tcon(wdata->req->cfile->tlink);
        struct kvec iov[2];
        struct smb_rqst rqst = { };
 
@@ -1672,7 +1680,8 @@ cifs_async_writev(struct cifs_io_subrequest *wdata)
                wct = 12;
                if (wdata->subreq.start >> 32 > 0) {
                        /* can not handle big offset for old srv */
-                       return -EIO;
+                       rc = -EIO;
+                       goto out;
                }
        }
 
@@ -1684,7 +1693,7 @@ cifs_async_writev(struct cifs_io_subrequest *wdata)
        smb->hdr.PidHigh = cpu_to_le16((__u16)(wdata->pid >> 16));
 
        smb->AndXCommand = 0xFF;        /* none */
-       smb->Fid = wdata->cfile->fid.netfid;
+       smb->Fid = wdata->req->cfile->fid.netfid;
        smb->OffsetLow = cpu_to_le32(wdata->subreq.start & 0xFFFFFFFF);
        if (wct == 14)
                smb->OffsetHigh = cpu_to_le32(wdata->subreq.start >> 32);
@@ -1724,18 +1733,19 @@ cifs_async_writev(struct cifs_io_subrequest *wdata)
                iov[1].iov_len += 4; /* pad bigger by four bytes */
        }
 
-       cifs_get_writedata(wdata);
        rc = cifs_call_async(tcon->ses->server, &rqst, NULL,
                             cifs_writev_callback, NULL, wdata, 0, NULL);
-
+       /* Can't touch wdata if rc == 0 */
        if (rc == 0)
                cifs_stats_inc(&tcon->stats.cifs_stats.num_writes);
-       else
-               cifs_put_writedata(wdata);
 
 async_writev_out:
        cifs_small_buf_release(smb);
-       return rc;
+out:
+       if (rc) {
+               add_credits_and_wake_if(wdata->server, &wdata->credits, 0);
+               cifs_write_subrequest_terminated(wdata, rc, false);
+       }
 }
 
 int
index c9c33b3a54f30549d9efaf4c948f36f874f62e02..bb3adde9343e5e129ed77073b5c7c79b9de19ffa 100644 (file)
@@ -119,7 +119,7 @@ fail:
        else
                trace_netfs_sreq(subreq, netfs_sreq_trace_fail);
        add_credits_and_wake_if(wdata->server, &wdata->credits, 0);
-       netfs_write_subrequest_terminated(wdata, rc, false);
+       cifs_write_subrequest_terminated(wdata, rc, false);
        goto out;
 }
 
@@ -352,6 +352,7 @@ const struct netfs_request_ops cifs_req_ops = {
        .issue_write            = cifs_issue_write,
 };
 
+#if 0 // TODO remove 397
 /*
  * Remove the dirty flags from a span of pages.
  */
@@ -476,6 +477,7 @@ void cifs_pages_write_redirty(struct inode *inode, loff_t start, unsigned int le
 
        rcu_read_unlock();
 }
+#endif // end netfslib remove 397
 
 /*
  * Mark as invalid, all open files on tree connections since they
@@ -2522,20 +2524,23 @@ int cifs_lock(struct file *file, int cmd, struct file_lock *flock)
        return rc;
 }
 
-/*
- * update the file size (if needed) after a write. Should be called with
- * the inode->i_lock held
- */
-void
-cifs_update_eof(struct cifsInodeInfo *cifsi, loff_t offset,
-                     unsigned int bytes_written)
+void cifs_write_subrequest_terminated(struct cifs_io_subrequest *wdata, ssize_t result,
+                                     bool was_async)
 {
-       loff_t end_of_write = offset + bytes_written;
+       struct netfs_io_request *wreq = wdata->rreq;
+       loff_t new_server_eof;
 
-       if (end_of_write > cifsi->netfs.remote_i_size)
-               netfs_resize_file(&cifsi->netfs, end_of_write, true);
+       if (result > 0) {
+               new_server_eof = wdata->subreq.start + wdata->subreq.transferred + result;
+
+               if (new_server_eof > netfs_inode(wreq->inode)->remote_i_size)
+                       netfs_resize_file(netfs_inode(wreq->inode), new_server_eof, true);
+       }
+
+       netfs_write_subrequest_terminated(&wdata->subreq, result, was_async);
 }
 
+#if 0 // TODO remove 2483
 static ssize_t
 cifs_write(struct cifsFileInfo *open_file, __u32 pid, const char *write_data,
           size_t write_size, loff_t *offset)
@@ -2619,6 +2624,7 @@ cifs_write(struct cifsFileInfo *open_file, __u32 pid, const char *write_data,
        free_xid(xid);
        return total_written;
 }
+#endif // end netfslib remove 2483
 
 struct cifsFileInfo *find_readable_file(struct cifsInodeInfo *cifs_inode,
                                        bool fsuid_only)
@@ -2824,6 +2830,7 @@ cifs_get_readable_path(struct cifs_tcon *tcon, const char *name,
        return -ENOENT;
 }
 
+#if 0 // TODO remove 2773
 void
 cifs_writedata_release(struct cifs_io_subrequest *wdata)
 {
@@ -3454,7 +3461,11 @@ static int cifs_write_end(struct file *file, struct address_space *mapping,
 
        return rc;
 }
+#endif // End netfs removal 2773
 
+/*
+ * Flush data on a strict file.
+ */
 int cifs_strict_fsync(struct file *file, loff_t start, loff_t end,
                      int datasync)
 {
@@ -3509,6 +3520,9 @@ strict_fsync_exit:
        return rc;
 }
 
+/*
+ * Flush data on a non-strict data.
+ */
 int cifs_fsync(struct file *file, loff_t start, loff_t end, int datasync)
 {
        unsigned int xid;
@@ -3575,6 +3589,7 @@ int cifs_flush(struct file *file, fl_owner_t id)
        return rc;
 }
 
+#if 0 // TODO remove 3594
 static void collect_uncached_write_data(struct cifs_aio_ctx *ctx);
 
 static void
@@ -4037,6 +4052,7 @@ ssize_t cifs_user_writev(struct kiocb *iocb, struct iov_iter *from)
 {
        return __cifs_writev(iocb, from, false);
 }
+#endif // TODO remove 3594
 
 static ssize_t
 cifs_writev(struct kiocb *iocb, struct iov_iter *from)
@@ -4048,7 +4064,10 @@ cifs_writev(struct kiocb *iocb, struct iov_iter *from)
        struct TCP_Server_Info *server = tlink_tcon(cfile->tlink)->ses->server;
        ssize_t rc;
 
-       inode_lock(inode);
+       rc = netfs_start_io_write(inode);
+       if (rc < 0)
+               return rc;
+
        /*
         * We need to hold the sem to be sure nobody modifies lock list
         * with a brlock that prevents writing.
@@ -4062,13 +4081,12 @@ cifs_writev(struct kiocb *iocb, struct iov_iter *from)
        if (!cifs_find_lock_conflict(cfile, iocb->ki_pos, iov_iter_count(from),
                                     server->vals->exclusive_lock_type, 0,
                                     NULL, CIFS_WRITE_OP))
-               rc = __generic_file_write_iter(iocb, from);
+               rc = netfs_buffered_write_iter_locked(iocb, from, NULL);
        else
                rc = -EACCES;
 out:
        up_read(&cinode->lock_sem);
-       inode_unlock(inode);
-
+       netfs_end_io_write(inode);
        if (rc > 0)
                rc = generic_write_sync(iocb, rc);
        return rc;
@@ -4091,9 +4109,9 @@ cifs_strict_writev(struct kiocb *iocb, struct iov_iter *from)
 
        if (CIFS_CACHE_WRITE(cinode)) {
                if (cap_unix(tcon->ses) &&
-               (CIFS_UNIX_FCNTL_CAP & le64_to_cpu(tcon->fsUnixInfo.Capability))
-                 && ((cifs_sb->mnt_cifs_flags & CIFS_MOUNT_NOPOSIXBRL) == 0)) {
-                       written = generic_file_write_iter(iocb, from);
+                   (CIFS_UNIX_FCNTL_CAP & le64_to_cpu(tcon->fsUnixInfo.Capability)) &&
+                   ((cifs_sb->mnt_cifs_flags & CIFS_MOUNT_NOPOSIXBRL) == 0)) {
+                       written = netfs_file_write_iter(iocb, from);
                        goto out;
                }
                written = cifs_writev(iocb, from);
@@ -4105,7 +4123,7 @@ cifs_strict_writev(struct kiocb *iocb, struct iov_iter *from)
         * affected pages because it may cause a error with mandatory locks on
         * these pages but not on the region from pos to ppos+len-1.
         */
-       written = cifs_user_writev(iocb, from);
+       written = netfs_file_write_iter(iocb, from);
        if (CIFS_CACHE_READ(cinode)) {
                /*
                 * We have read level caching and we have just sent a write
@@ -4124,6 +4142,7 @@ out:
        return written;
 }
 
+#if 0 // TODO remove 4143
 static struct cifs_io_subrequest *cifs_readdata_alloc(work_func_t complete)
 {
        struct cifs_io_subrequest *rdata;
@@ -4563,7 +4582,9 @@ ssize_t cifs_direct_readv(struct kiocb *iocb, struct iov_iter *to)
 ssize_t cifs_user_readv(struct kiocb *iocb, struct iov_iter *to)
 {
        return __cifs_readv(iocb, to, false);
+
 }
+#endif // end netfslib removal 4143
 
 ssize_t cifs_loose_read_iter(struct kiocb *iocb, struct iov_iter *iter)
 {
@@ -4571,13 +4592,13 @@ ssize_t cifs_loose_read_iter(struct kiocb *iocb, struct iov_iter *iter)
        struct inode *inode = file_inode(iocb->ki_filp);
 
        if (iocb->ki_flags & IOCB_DIRECT)
-               return cifs_user_readv(iocb, iter);
+               return netfs_unbuffered_read_iter(iocb, iter);
 
        rc = cifs_revalidate_mapping(inode);
        if (rc)
                return rc;
 
-       return generic_file_read_iter(iocb, iter);
+       return netfs_file_read_iter(iocb, iter);
 }
 
 ssize_t cifs_file_write_iter(struct kiocb *iocb, struct iov_iter *from)
@@ -4588,7 +4609,7 @@ ssize_t cifs_file_write_iter(struct kiocb *iocb, struct iov_iter *from)
        int rc;
 
        if (iocb->ki_filp->f_flags & O_DIRECT) {
-               written = cifs_user_writev(iocb, from);
+               written = netfs_unbuffered_write_iter(iocb, from);
                if (written > 0 && CIFS_CACHE_READ(cinode)) {
                        cifs_zap_mapping(inode);
                        cifs_dbg(FYI,
@@ -4603,17 +4624,15 @@ ssize_t cifs_file_write_iter(struct kiocb *iocb, struct iov_iter *from)
        if (written)
                return written;
 
-       written = generic_file_write_iter(iocb, from);
-
-       if (CIFS_CACHE_WRITE(CIFS_I(inode)))
-               goto out;
+       written = netfs_file_write_iter(iocb, from);
 
-       rc = filemap_fdatawrite(inode->i_mapping);
-       if (rc)
-               cifs_dbg(FYI, "cifs_file_write_iter: %d rc on %p inode\n",
-                        rc, inode);
+       if (!CIFS_CACHE_WRITE(CIFS_I(inode))) {
+               rc = filemap_fdatawrite(inode->i_mapping);
+               if (rc)
+                       cifs_dbg(FYI, "cifs_file_write_iter: %d rc on %p inode\n",
+                                rc, inode);
+       }
 
-out:
        cifs_put_writer(cinode);
        return written;
 }
@@ -4638,12 +4657,15 @@ cifs_strict_readv(struct kiocb *iocb, struct iov_iter *to)
         * pos+len-1.
         */
        if (!CIFS_CACHE_READ(cinode))
-               return cifs_user_readv(iocb, to);
+               return netfs_unbuffered_read_iter(iocb, to);
 
        if (cap_unix(tcon->ses) &&
            (CIFS_UNIX_FCNTL_CAP & le64_to_cpu(tcon->fsUnixInfo.Capability)) &&
-           ((cifs_sb->mnt_cifs_flags & CIFS_MOUNT_NOPOSIXBRL) == 0))
-               return generic_file_read_iter(iocb, to);
+           ((cifs_sb->mnt_cifs_flags & CIFS_MOUNT_NOPOSIXBRL) == 0)) {
+               if (iocb->ki_flags & IOCB_DIRECT)
+                       return netfs_unbuffered_read_iter(iocb, to);
+               return netfs_buffered_read_iter(iocb, to);
+       }
 
        /*
         * We need to hold the sem to be sure nobody modifies lock list
@@ -4652,12 +4674,17 @@ cifs_strict_readv(struct kiocb *iocb, struct iov_iter *to)
        down_read(&cinode->lock_sem);
        if (!cifs_find_lock_conflict(cfile, iocb->ki_pos, iov_iter_count(to),
                                     tcon->ses->server->vals->shared_lock_type,
-                                    0, NULL, CIFS_READ_OP))
-               rc = generic_file_read_iter(iocb, to);
+                                    0, NULL, CIFS_READ_OP)) {
+               if (iocb->ki_flags & IOCB_DIRECT)
+                       rc = netfs_unbuffered_read_iter(iocb, to);
+               else
+                       rc = netfs_buffered_read_iter(iocb, to);
+       }
        up_read(&cinode->lock_sem);
        return rc;
 }
 
+#if 0 // TODO remove 4633
 static ssize_t
 cifs_read(struct file *file, char *read_data, size_t read_size, loff_t *offset)
 {
@@ -4749,29 +4776,11 @@ cifs_read(struct file *file, char *read_data, size_t read_size, loff_t *offset)
        free_xid(xid);
        return total_read;
 }
+#endif // end netfslib remove 4633
 
-/*
- * If the page is mmap'ed into a process' page tables, then we need to make
- * sure that it doesn't change while being written back.
- */
 static vm_fault_t cifs_page_mkwrite(struct vm_fault *vmf)
 {
-       struct folio *folio = page_folio(vmf->page);
-
-       /* Wait for the folio to be written to the cache before we allow it to
-        * be modified.  We then assume the entire folio will need writing back.
-        */
-#ifdef CONFIG_CIFS_FSCACHE
-       if (folio_test_private_2(folio) && /* [DEPRECATED] */
-           folio_wait_private_2_killable(folio) < 0)
-               return VM_FAULT_RETRY;
-#endif
-
-       folio_wait_writeback(folio);
-
-       if (folio_lock_killable(folio) < 0)
-               return VM_FAULT_RETRY;
-       return VM_FAULT_LOCKED;
+       return netfs_page_mkwrite(vmf, NULL);
 }
 
 static const struct vm_operations_struct cifs_file_vm_ops = {
@@ -4817,6 +4826,7 @@ int cifs_file_mmap(struct file *file, struct vm_area_struct *vma)
        return rc;
 }
 
+#if 0 // TODO remove 4794
 /*
  * Unlock a bunch of folios in the pagecache.
  */
@@ -5101,6 +5111,7 @@ static int cifs_read_folio(struct file *file, struct folio *folio)
        free_xid(xid);
        return rc;
 }
+#endif // end netfslib remove 4794
 
 static int is_inode_writable(struct cifsInodeInfo *cifs_inode)
 {
@@ -5149,6 +5160,7 @@ bool is_size_safe_to_change(struct cifsInodeInfo *cifsInode, __u64 end_of_file,
                return true;
 }
 
+#if 0 // TODO remove 5152
 static int cifs_write_begin(struct file *file, struct address_space *mapping,
                        loff_t pos, unsigned len,
                        struct page **pagep, void **fsdata)
@@ -5244,6 +5256,7 @@ static void cifs_invalidate_folio(struct folio *folio, size_t offset,
 {
        folio_wait_private_2(folio); /* [DEPRECATED] */
 }
+#endif // end netfslib remove 5152
 
 void cifs_oplock_break(struct work_struct *work)
 {
@@ -5334,6 +5347,7 @@ out:
        cifs_done_oplock_break(cinode);
 }
 
+#if 0 // TODO remove 5333
 /*
  * The presence of cifs_direct_io() in the address space ops vector
  * allowes open() O_DIRECT flags which would have failed otherwise.
@@ -5352,6 +5366,7 @@ cifs_direct_io(struct kiocb *iocb, struct iov_iter *iter)
          */
         return -EINVAL;
 }
+#endif // netfs end remove 5333
 
 static int cifs_swap_activate(struct swap_info_struct *sis,
                              struct file *swap_file, sector_t *span)
@@ -5414,21 +5429,19 @@ static void cifs_swap_deactivate(struct file *file)
 }
 
 const struct address_space_operations cifs_addr_ops = {
-       .read_folio = cifs_read_folio,
-       .readahead = cifs_readahead,
-       .writepages = cifs_writepages,
-       .write_begin = cifs_write_begin,
-       .write_end = cifs_write_end,
-       .dirty_folio = netfs_dirty_folio,
-       .release_folio = cifs_release_folio,
-       .direct_IO = cifs_direct_io,
-       .invalidate_folio = cifs_invalidate_folio,
-       .migrate_folio = filemap_migrate_folio,
+       .read_folio     = netfs_read_folio,
+       .readahead      = netfs_readahead,
+       .writepages     = netfs_writepages,
+       .dirty_folio    = netfs_dirty_folio,
+       .release_folio  = netfs_release_folio,
+       .direct_IO      = noop_direct_IO,
+       .invalidate_folio = netfs_invalidate_folio,
+       .migrate_folio  = filemap_migrate_folio,
        /*
         * TODO: investigate and if useful we could add an is_dirty_writeback
         * helper if needed
         */
-       .swap_activate = cifs_swap_activate,
+       .swap_activate  = cifs_swap_activate,
        .swap_deactivate = cifs_swap_deactivate,
 };
 
@@ -5438,12 +5451,10 @@ const struct address_space_operations cifs_addr_ops = {
  * to leave cifs_readahead out of the address space operations.
  */
 const struct address_space_operations cifs_addr_ops_smallbuf = {
-       .read_folio = cifs_read_folio,
-       .writepages = cifs_writepages,
-       .write_begin = cifs_write_begin,
-       .write_end = cifs_write_end,
-       .dirty_folio = netfs_dirty_folio,
-       .release_folio = cifs_release_folio,
-       .invalidate_folio = cifs_invalidate_folio,
-       .migrate_folio = filemap_migrate_folio,
+       .read_folio     = netfs_read_folio,
+       .writepages     = netfs_writepages,
+       .dirty_folio    = netfs_dirty_folio,
+       .release_folio  = netfs_release_folio,
+       .invalidate_folio = netfs_invalidate_folio,
+       .migrate_folio  = filemap_migrate_folio,
 };
index 1a895e6243ee9aaf21fc8405893ce52ed14303a2..b36c493f4c563151c1526fb835051a90c48ae4c7 100644 (file)
@@ -171,6 +171,7 @@ void cifs_fscache_release_inode_cookie(struct inode *inode)
        }
 }
 
+#if 0 // TODO remove
 /*
  * Fallback page reading interface.
  */
@@ -279,3 +280,4 @@ int __cifs_fscache_query_occupancy(struct inode *inode,
        fscache_end_operation(&cres);
        return ret;
 }
+#endif
index 1f2ea9f5cc9a8a5f900a5a5367cf093d54f2f80d..08b30f79d4cdfa6a0018d027be739c72f9948f84 100644 (file)
@@ -74,6 +74,7 @@ static inline void cifs_invalidate_cache(struct inode *inode, unsigned int flags
                           i_size_read(inode), flags);
 }
 
+#if 0 // TODO remove
 extern int __cifs_fscache_query_occupancy(struct inode *inode,
                                          pgoff_t first, unsigned int nr_pages,
                                          pgoff_t *_data_first,
@@ -108,6 +109,7 @@ static inline void cifs_readahead_to_fscache(struct inode *inode,
        if (cifs_inode_cookie(inode))
                __cifs_readahead_to_fscache(inode, pos, len);
 }
+#endif
 
 static inline bool cifs_fscache_enabled(struct inode *inode)
 {
@@ -131,6 +133,7 @@ static inline struct fscache_cookie *cifs_inode_cookie(struct inode *inode) { re
 static inline void cifs_invalidate_cache(struct inode *inode, unsigned int flags) {}
 static inline bool cifs_fscache_enabled(struct inode *inode) { return false; }
 
+#if 0 // TODO remove
 static inline int cifs_fscache_query_occupancy(struct inode *inode,
                                               pgoff_t first, unsigned int nr_pages,
                                               pgoff_t *_data_first,
@@ -149,6 +152,7 @@ cifs_readpage_from_fscache(struct inode *inode, struct page *page)
 
 static inline
 void cifs_readahead_to_fscache(struct inode *inode, loff_t pos, size_t len) {}
+#endif
 
 #endif /* CONFIG_CIFS_FSCACHE */
 
index 033948d34c5a67568e7dd413632e30b0dfd426af..5239c823de8655943e6f27837370ae4b54b3d680 100644 (file)
 #include "cached_dir.h"
 #include "reparse.h"
 
+/*
+ * Set parameters for the netfs library
+ */
+static void cifs_set_netfs_context(struct inode *inode)
+{
+       struct cifsInodeInfo *cifs_i = CIFS_I(inode);
+       struct cifs_sb_info *cifs_sb = CIFS_SB(inode->i_sb);
+
+       netfs_inode_init(&cifs_i->netfs, &cifs_req_ops, true);
+       if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_STRICT_IO)
+               __set_bit(NETFS_ICTX_WRITETHROUGH, &cifs_i->netfs.flags);
+}
+
 static void cifs_set_ops(struct inode *inode)
 {
        struct cifs_sb_info *cifs_sb = CIFS_SB(inode->i_sb);
+       struct netfs_inode *ictx = netfs_inode(inode);
 
        switch (inode->i_mode & S_IFMT) {
        case S_IFREG:
                inode->i_op = &cifs_file_inode_ops;
                if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_DIRECT_IO) {
+                       set_bit(NETFS_ICTX_UNBUFFERED, &ictx->flags);
                        if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_NO_BRL)
                                inode->i_fop = &cifs_file_direct_nobrl_ops;
                        else
@@ -221,8 +236,10 @@ cifs_fattr_to_inode(struct inode *inode, struct cifs_fattr *fattr,
 
        if (fattr->cf_flags & CIFS_FATTR_JUNCTION)
                inode->i_flags |= S_AUTOMOUNT;
-       if (inode->i_state & I_NEW)
+       if (inode->i_state & I_NEW) {
+               cifs_set_netfs_context(inode);
                cifs_set_ops(inode);
+       }
        return 0;
 }
 
index b063f5e95f5dfe11829c7b170f37a952887fa8e0..993ac36c3d585ae7fa740300e60d27b481ebebe4 100644 (file)
@@ -4421,10 +4421,12 @@ smb2_new_read_req(void **buf, unsigned int *total_len,
        req->Length = cpu_to_le32(io_parms->length);
        req->Offset = cpu_to_le64(io_parms->offset);
 
-       trace_smb3_read_enter(0 /* xid */,
-                       io_parms->persistent_fid,
-                       io_parms->tcon->tid, io_parms->tcon->ses->Suid,
-                       io_parms->offset, io_parms->length);
+       trace_smb3_read_enter(rdata ? rdata->rreq->debug_id : 0,
+                             rdata ? rdata->subreq.debug_index : 0,
+                             rdata ? rdata->xid : 0,
+                             io_parms->persistent_fid,
+                             io_parms->tcon->tid, io_parms->tcon->ses->Suid,
+                             io_parms->offset, io_parms->length);
 #ifdef CONFIG_CIFS_SMB_DIRECT
        /*
         * If we want to do a RDMA write, fill in and append
@@ -4486,7 +4488,7 @@ static void
 smb2_readv_callback(struct mid_q_entry *mid)
 {
        struct cifs_io_subrequest *rdata = mid->callback_data;
-       struct cifs_tcon *tcon = tlink_tcon(rdata->cfile->tlink);
+       struct cifs_tcon *tcon = tlink_tcon(rdata->req->cfile->tlink);
        struct TCP_Server_Info *server = rdata->server;
        struct smb2_hdr *shdr =
                                (struct smb2_hdr *)rdata->iov[0].iov_base;
@@ -4514,7 +4516,6 @@ smb2_readv_callback(struct mid_q_entry *mid)
                if (server->sign && !mid->decrypted) {
                        int rc;
 
-                       iov_iter_revert(&rqst.rq_iter, rdata->got_bytes);
                        iov_iter_truncate(&rqst.rq_iter, rdata->got_bytes);
                        rc = smb2_verify_signature(&rqst, server);
                        if (rc)
@@ -4555,17 +4556,33 @@ smb2_readv_callback(struct mid_q_entry *mid)
 #endif
        if (rdata->result && rdata->result != -ENODATA) {
                cifs_stats_fail_inc(tcon, SMB2_READ_HE);
-               trace_smb3_read_err(0 /* xid */,
-                                   rdata->cfile->fid.persistent_fid,
+               trace_smb3_read_err(rdata->rreq->debug_id,
+                                   rdata->subreq.debug_index,
+                                   rdata->xid,
+                                   rdata->req->cfile->fid.persistent_fid,
                                    tcon->tid, tcon->ses->Suid, rdata->subreq.start,
                                    rdata->subreq.len, rdata->result);
        } else
-               trace_smb3_read_done(0 /* xid */,
-                                    rdata->cfile->fid.persistent_fid,
+               trace_smb3_read_done(rdata->rreq->debug_id,
+                                    rdata->subreq.debug_index,
+                                    rdata->xid,
+                                    rdata->req->cfile->fid.persistent_fid,
                                     tcon->tid, tcon->ses->Suid,
                                     rdata->subreq.start, rdata->got_bytes);
 
-       queue_work(cifsiod_wq, &rdata->work);
+       if (rdata->result == -ENODATA) {
+               /* We may have got an EOF error because fallocate
+                * failed to enlarge the file.
+                */
+               if (rdata->subreq.start < rdata->subreq.rreq->i_size)
+                       rdata->result = 0;
+       }
+       if (rdata->result == 0 || rdata->result == -EAGAIN)
+               iov_iter_advance(&rdata->subreq.io_iter, rdata->got_bytes);
+       rdata->credits.value = 0;
+       netfs_subreq_terminated(&rdata->subreq,
+                               (rdata->result == 0 || rdata->result == -EAGAIN) ?
+                               rdata->got_bytes : rdata->result, true);
        release_mid(mid);
        add_credits(server, &credits, 0);
 }
@@ -4581,7 +4598,7 @@ smb2_async_readv(struct cifs_io_subrequest *rdata)
        struct smb_rqst rqst = { .rq_iov = rdata->iov,
                                 .rq_nvec = 1 };
        struct TCP_Server_Info *server;
-       struct cifs_tcon *tcon = tlink_tcon(rdata->cfile->tlink);
+       struct cifs_tcon *tcon = tlink_tcon(rdata->req->cfile->tlink);
        unsigned int total_len;
        int credit_request;
 
@@ -4591,12 +4608,12 @@ smb2_async_readv(struct cifs_io_subrequest *rdata)
        if (!rdata->server)
                rdata->server = cifs_pick_channel(tcon->ses);
 
-       io_parms.tcon = tlink_tcon(rdata->cfile->tlink);
+       io_parms.tcon = tlink_tcon(rdata->req->cfile->tlink);
        io_parms.server = server = rdata->server;
        io_parms.offset = rdata->subreq.start;
        io_parms.length = rdata->subreq.len;
-       io_parms.persistent_fid = rdata->cfile->fid.persistent_fid;
-       io_parms.volatile_fid = rdata->cfile->fid.volatile_fid;
+       io_parms.persistent_fid = rdata->req->cfile->fid.persistent_fid;
+       io_parms.volatile_fid = rdata->req->cfile->fid.volatile_fid;
        io_parms.pid = rdata->pid;
 
        rc = smb2_new_read_req(
@@ -4630,15 +4647,15 @@ smb2_async_readv(struct cifs_io_subrequest *rdata)
                flags |= CIFS_HAS_CREDITS;
        }
 
-       cifs_get_readdata(rdata);
        rc = cifs_call_async(server, &rqst,
                             cifs_readv_receive, smb2_readv_callback,
                             smb3_handle_read_data, rdata, flags,
                             &rdata->credits);
        if (rc) {
-               cifs_put_readdata(rdata);
                cifs_stats_fail_inc(io_parms.tcon, SMB2_READ_HE);
-               trace_smb3_read_err(0 /* xid */, io_parms.persistent_fid,
+               trace_smb3_read_err(rdata->rreq->debug_id,
+                                   rdata->subreq.debug_index,
+                                   rdata->xid, io_parms.persistent_fid,
                                    io_parms.tcon->tid,
                                    io_parms.tcon->ses->Suid,
                                    io_parms.offset, io_parms.length, rc);
@@ -4689,22 +4706,23 @@ SMB2_read(const unsigned int xid, struct cifs_io_parms *io_parms,
                if (rc != -ENODATA) {
                        cifs_stats_fail_inc(io_parms->tcon, SMB2_READ_HE);
                        cifs_dbg(VFS, "Send error in read = %d\n", rc);
-                       trace_smb3_read_err(xid,
+                       trace_smb3_read_err(0, 0, xid,
                                            req->PersistentFileId,
                                            io_parms->tcon->tid, ses->Suid,
                                            io_parms->offset, io_parms->length,
                                            rc);
                } else
-                       trace_smb3_read_done(xid, req->PersistentFileId, io_parms->tcon->tid,
+                       trace_smb3_read_done(0, 0, xid,
+                                            req->PersistentFileId, io_parms->tcon->tid,
                                             ses->Suid, io_parms->offset, 0);
                free_rsp_buf(resp_buftype, rsp_iov.iov_base);
                cifs_small_buf_release(req);
                return rc == -ENODATA ? 0 : rc;
        } else
-               trace_smb3_read_done(xid,
-                                   req->PersistentFileId,
-                                   io_parms->tcon->tid, ses->Suid,
-                                   io_parms->offset, io_parms->length);
+               trace_smb3_read_done(0, 0, xid,
+                                    req->PersistentFileId,
+                                    io_parms->tcon->tid, ses->Suid,
+                                    io_parms->offset, io_parms->length);
 
        cifs_small_buf_release(req);
 
@@ -4738,11 +4756,12 @@ static void
 smb2_writev_callback(struct mid_q_entry *mid)
 {
        struct cifs_io_subrequest *wdata = mid->callback_data;
-       struct cifs_tcon *tcon = tlink_tcon(wdata->cfile->tlink);
+       struct cifs_tcon *tcon = tlink_tcon(wdata->req->cfile->tlink);
        struct TCP_Server_Info *server = wdata->server;
-       unsigned int written;
        struct smb2_write_rsp *rsp = (struct smb2_write_rsp *)mid->resp_buf;
        struct cifs_credits credits = { .value = 0, .instance = 0 };
+       ssize_t result = 0;
+       size_t written;
 
        WARN_ONCE(wdata->server != mid->server,
                  "wdata server %p != mid server %p",
@@ -4752,8 +4771,8 @@ smb2_writev_callback(struct mid_q_entry *mid)
        case MID_RESPONSE_RECEIVED:
                credits.value = le16_to_cpu(rsp->hdr.CreditRequest);
                credits.instance = server->reconnect_instance;
-               wdata->result = smb2_check_receive(mid, server, 0);
-               if (wdata->result != 0)
+               result = smb2_check_receive(mid, server, 0);
+               if (result != 0)
                        break;
 
                written = le32_to_cpu(rsp->DataLength);
@@ -4770,17 +4789,18 @@ smb2_writev_callback(struct mid_q_entry *mid)
                        wdata->result = -ENOSPC;
                else
                        wdata->subreq.len = written;
+               iov_iter_advance(&wdata->subreq.io_iter, written);
                break;
        case MID_REQUEST_SUBMITTED:
        case MID_RETRY_NEEDED:
-               wdata->result = -EAGAIN;
+               result = -EAGAIN;
                break;
        case MID_RESPONSE_MALFORMED:
                credits.value = le16_to_cpu(rsp->hdr.CreditRequest);
                credits.instance = server->reconnect_instance;
                fallthrough;
        default:
-               wdata->result = -EIO;
+               result = -EIO;
                break;
        }
 #ifdef CONFIG_CIFS_SMB_DIRECT
@@ -4796,10 +4816,10 @@ smb2_writev_callback(struct mid_q_entry *mid)
                wdata->mr = NULL;
        }
 #endif
-       if (wdata->result) {
+       if (result) {
                cifs_stats_fail_inc(tcon, SMB2_WRITE_HE);
-               trace_smb3_write_err(0 /* no xid */,
-                                    wdata->cfile->fid.persistent_fid,
+               trace_smb3_write_err(wdata->xid,
+                                    wdata->req->cfile->fid.persistent_fid,
                                     tcon->tid, tcon->ses->Suid, wdata->subreq.start,
                                     wdata->subreq.len, wdata->result);
                if (wdata->result == -ENOSPC)
@@ -4807,27 +4827,28 @@ smb2_writev_callback(struct mid_q_entry *mid)
                                     tcon->tree_name);
        } else
                trace_smb3_write_done(0 /* no xid */,
-                                     wdata->cfile->fid.persistent_fid,
+                                     wdata->req->cfile->fid.persistent_fid,
                                      tcon->tid, tcon->ses->Suid,
                                      wdata->subreq.start, wdata->subreq.len);
 
-       queue_work(cifsiod_wq, &wdata->work);
+       wdata->credits.value = 0;
+       cifs_write_subrequest_terminated(wdata, result ?: written, true);
        release_mid(mid);
        add_credits(server, &credits, 0);
 }
 
 /* smb2_async_writev - send an async write, and set up mid to handle result */
-int
+void
 smb2_async_writev(struct cifs_io_subrequest *wdata)
 {
        int rc = -EACCES, flags = 0;
        struct smb2_write_req *req = NULL;
        struct smb2_hdr *shdr;
-       struct cifs_tcon *tcon = tlink_tcon(wdata->cfile->tlink);
+       struct cifs_tcon *tcon = tlink_tcon(wdata->req->cfile->tlink);
        struct TCP_Server_Info *server = wdata->server;
        struct kvec iov[1];
        struct smb_rqst rqst = { };
-       unsigned int total_len;
+       unsigned int total_len, xid = wdata->xid;
        struct cifs_io_parms _io_parms;
        struct cifs_io_parms *io_parms = NULL;
        int credit_request;
@@ -4844,8 +4865,8 @@ smb2_async_writev(struct cifs_io_subrequest *wdata)
                .server = server,
                .offset = wdata->subreq.start,
                .length = wdata->subreq.len,
-               .persistent_fid = wdata->cfile->fid.persistent_fid,
-               .volatile_fid = wdata->cfile->fid.volatile_fid,
+               .persistent_fid = wdata->req->cfile->fid.persistent_fid,
+               .volatile_fid = wdata->req->cfile->fid.volatile_fid,
                .pid = wdata->pid,
        };
        io_parms = &_io_parms;
@@ -4853,7 +4874,7 @@ smb2_async_writev(struct cifs_io_subrequest *wdata)
        rc = smb2_plain_req_init(SMB2_WRITE, tcon, server,
                                 (void **) &req, &total_len);
        if (rc)
-               return rc;
+               goto out;
 
        if (smb3_encryption_required(tcon))
                flags |= CIFS_TRANSFORM_REQ;
@@ -4871,7 +4892,7 @@ smb2_async_writev(struct cifs_io_subrequest *wdata)
                                offsetof(struct smb2_write_req, Buffer));
        req->RemainingBytes = 0;
 
-       trace_smb3_write_enter(0 /* xid */,
+       trace_smb3_write_enter(wdata->xid,
                               io_parms->persistent_fid,
                               io_parms->tcon->tid,
                               io_parms->tcon->ses->Suid,
@@ -4952,25 +4973,27 @@ smb2_async_writev(struct cifs_io_subrequest *wdata)
                flags |= CIFS_HAS_CREDITS;
        }
 
-       cifs_get_writedata(wdata);
        rc = cifs_call_async(server, &rqst, NULL, smb2_writev_callback, NULL,
                             wdata, flags, &wdata->credits);
-
+       /* Can't touch wdata if rc == 0 */
        if (rc) {
-               trace_smb3_write_err(0 /* no xid */,
+               trace_smb3_write_err(xid,
                                     io_parms->persistent_fid,
                                     io_parms->tcon->tid,
                                     io_parms->tcon->ses->Suid,
                                     io_parms->offset,
                                     io_parms->length,
                                     rc);
-               cifs_put_writedata(wdata);
                cifs_stats_fail_inc(tcon, SMB2_WRITE_HE);
        }
 
 async_writev_out:
        cifs_small_buf_release(req);
-       return rc;
+out:
+       if (rc) {
+               add_credits_and_wake_if(wdata->server, &wdata->credits, 0);
+               cifs_write_subrequest_terminated(wdata, rc, true);
+       }
 }
 
 /*
index c781eaa0cba8c8176266086d09b8ecb1b1981aa6..b208232b12a24da69908d8f66085dac0b0d5d085 100644 (file)
@@ -213,7 +213,7 @@ extern int SMB2_get_srv_num(const unsigned int xid, struct cifs_tcon *tcon,
 extern int smb2_async_readv(struct cifs_io_subrequest *rdata);
 extern int SMB2_read(const unsigned int xid, struct cifs_io_parms *io_parms,
                     unsigned int *nbytes, char **buf, int *buf_type);
-extern int smb2_async_writev(struct cifs_io_subrequest *wdata);
+extern void smb2_async_writev(struct cifs_io_subrequest *wdata);
 extern int SMB2_write(const unsigned int xid, struct cifs_io_parms *io_parms,
                      unsigned int *nbytes, struct kvec *iov, int n_vec);
 extern int SMB2_echo(struct TCP_Server_Info *server);
index 604e52876cd2d98e9a86941b0c527dbe6d8abe6a..af97389e983e0651df680b504c41bcadeff7cb58 100644 (file)
@@ -85,6 +85,62 @@ smb3_tcon_ref_traces;
 
 /* For logging errors in read or write */
 DECLARE_EVENT_CLASS(smb3_rw_err_class,
+       TP_PROTO(unsigned int rreq_debug_id,
+                unsigned int rreq_debug_index,
+                unsigned int xid,
+                __u64  fid,
+                __u32  tid,
+                __u64  sesid,
+                __u64  offset,
+                __u32  len,
+                int    rc),
+       TP_ARGS(rreq_debug_id, rreq_debug_index,
+               xid, fid, tid, sesid, offset, len, rc),
+       TP_STRUCT__entry(
+               __field(unsigned int, rreq_debug_id)
+               __field(unsigned int, rreq_debug_index)
+               __field(unsigned int, xid)
+               __field(__u64, fid)
+               __field(__u32, tid)
+               __field(__u64, sesid)
+               __field(__u64, offset)
+               __field(__u32, len)
+               __field(int, rc)
+       ),
+       TP_fast_assign(
+               __entry->rreq_debug_id = rreq_debug_id;
+               __entry->rreq_debug_index = rreq_debug_index;
+               __entry->xid = xid;
+               __entry->fid = fid;
+               __entry->tid = tid;
+               __entry->sesid = sesid;
+               __entry->offset = offset;
+               __entry->len = len;
+               __entry->rc = rc;
+       ),
+       TP_printk("\tR=%08x[%x] xid=%u sid=0x%llx tid=0x%x fid=0x%llx offset=0x%llx len=0x%x rc=%d",
+                 __entry->rreq_debug_id, __entry->rreq_debug_index,
+                 __entry->xid, __entry->sesid, __entry->tid, __entry->fid,
+                 __entry->offset, __entry->len, __entry->rc)
+)
+
+#define DEFINE_SMB3_RW_ERR_EVENT(name)          \
+DEFINE_EVENT(smb3_rw_err_class, smb3_##name,    \
+       TP_PROTO(unsigned int rreq_debug_id,    \
+                unsigned int rreq_debug_index,         \
+                unsigned int xid,                      \
+                __u64  fid,                            \
+                __u32  tid,                            \
+                __u64  sesid,                          \
+                __u64  offset,                         \
+                __u32  len,                            \
+                int    rc),                            \
+       TP_ARGS(rreq_debug_id, rreq_debug_index, xid, fid, tid, sesid, offset, len, rc))
+
+DEFINE_SMB3_RW_ERR_EVENT(read_err);
+
+/* For logging errors in other file I/O ops */
+DECLARE_EVENT_CLASS(smb3_other_err_class,
        TP_PROTO(unsigned int xid,
                __u64   fid,
                __u32   tid,
@@ -116,8 +172,8 @@ DECLARE_EVENT_CLASS(smb3_rw_err_class,
                __entry->offset, __entry->len, __entry->rc)
 )
 
-#define DEFINE_SMB3_RW_ERR_EVENT(name)          \
-DEFINE_EVENT(smb3_rw_err_class, smb3_##name,    \
+#define DEFINE_SMB3_OTHER_ERR_EVENT(name)      \
+DEFINE_EVENT(smb3_other_err_class, smb3_##name, \
        TP_PROTO(unsigned int xid,              \
                __u64   fid,                    \
                __u32   tid,                    \
@@ -127,15 +183,67 @@ DEFINE_EVENT(smb3_rw_err_class, smb3_##name,    \
                int     rc),                    \
        TP_ARGS(xid, fid, tid, sesid, offset, len, rc))
 
-DEFINE_SMB3_RW_ERR_EVENT(write_err);
-DEFINE_SMB3_RW_ERR_EVENT(read_err);
-DEFINE_SMB3_RW_ERR_EVENT(query_dir_err);
-DEFINE_SMB3_RW_ERR_EVENT(zero_err);
-DEFINE_SMB3_RW_ERR_EVENT(falloc_err);
+DEFINE_SMB3_OTHER_ERR_EVENT(write_err);
+DEFINE_SMB3_OTHER_ERR_EVENT(query_dir_err);
+DEFINE_SMB3_OTHER_ERR_EVENT(zero_err);
+DEFINE_SMB3_OTHER_ERR_EVENT(falloc_err);
 
 
 /* For logging successful read or write */
 DECLARE_EVENT_CLASS(smb3_rw_done_class,
+       TP_PROTO(unsigned int rreq_debug_id,
+                unsigned int rreq_debug_index,
+                unsigned int xid,
+                __u64  fid,
+                __u32  tid,
+                __u64  sesid,
+                __u64  offset,
+                __u32  len),
+       TP_ARGS(rreq_debug_id, rreq_debug_index,
+               xid, fid, tid, sesid, offset, len),
+       TP_STRUCT__entry(
+               __field(unsigned int, rreq_debug_id)
+               __field(unsigned int, rreq_debug_index)
+               __field(unsigned int, xid)
+               __field(__u64, fid)
+               __field(__u32, tid)
+               __field(__u64, sesid)
+               __field(__u64, offset)
+               __field(__u32, len)
+       ),
+       TP_fast_assign(
+               __entry->rreq_debug_id = rreq_debug_id;
+               __entry->rreq_debug_index = rreq_debug_index;
+               __entry->xid = xid;
+               __entry->fid = fid;
+               __entry->tid = tid;
+               __entry->sesid = sesid;
+               __entry->offset = offset;
+               __entry->len = len;
+       ),
+       TP_printk("R=%08x[%x] xid=%u sid=0x%llx tid=0x%x fid=0x%llx offset=0x%llx len=0x%x",
+                 __entry->rreq_debug_id, __entry->rreq_debug_index,
+                 __entry->xid, __entry->sesid, __entry->tid, __entry->fid,
+                 __entry->offset, __entry->len)
+)
+
+#define DEFINE_SMB3_RW_DONE_EVENT(name)         \
+DEFINE_EVENT(smb3_rw_done_class, smb3_##name,   \
+       TP_PROTO(unsigned int rreq_debug_id,    \
+                unsigned int rreq_debug_index, \
+                unsigned int xid,              \
+               __u64   fid,                    \
+               __u32   tid,                    \
+               __u64   sesid,                  \
+               __u64   offset,                 \
+               __u32   len),                   \
+       TP_ARGS(rreq_debug_id, rreq_debug_index, xid, fid, tid, sesid, offset, len))
+
+DEFINE_SMB3_RW_DONE_EVENT(read_enter);
+DEFINE_SMB3_RW_DONE_EVENT(read_done);
+
+/* For logging successful other op */
+DECLARE_EVENT_CLASS(smb3_other_done_class,
        TP_PROTO(unsigned int xid,
                __u64   fid,
                __u32   tid,
@@ -164,8 +272,8 @@ DECLARE_EVENT_CLASS(smb3_rw_done_class,
                __entry->offset, __entry->len)
 )
 
-#define DEFINE_SMB3_RW_DONE_EVENT(name)         \
-DEFINE_EVENT(smb3_rw_done_class, smb3_##name,   \
+#define DEFINE_SMB3_OTHER_DONE_EVENT(name)         \
+DEFINE_EVENT(smb3_other_done_class, smb3_##name,   \
        TP_PROTO(unsigned int xid,              \
                __u64   fid,                    \
                __u32   tid,                    \
@@ -174,16 +282,14 @@ DEFINE_EVENT(smb3_rw_done_class, smb3_##name,   \
                __u32   len),                   \
        TP_ARGS(xid, fid, tid, sesid, offset, len))
 
-DEFINE_SMB3_RW_DONE_EVENT(write_enter);
-DEFINE_SMB3_RW_DONE_EVENT(read_enter);
-DEFINE_SMB3_RW_DONE_EVENT(query_dir_enter);
-DEFINE_SMB3_RW_DONE_EVENT(zero_enter);
-DEFINE_SMB3_RW_DONE_EVENT(falloc_enter);
-DEFINE_SMB3_RW_DONE_EVENT(write_done);
-DEFINE_SMB3_RW_DONE_EVENT(read_done);
-DEFINE_SMB3_RW_DONE_EVENT(query_dir_done);
-DEFINE_SMB3_RW_DONE_EVENT(zero_done);
-DEFINE_SMB3_RW_DONE_EVENT(falloc_done);
+DEFINE_SMB3_OTHER_DONE_EVENT(write_enter);
+DEFINE_SMB3_OTHER_DONE_EVENT(query_dir_enter);
+DEFINE_SMB3_OTHER_DONE_EVENT(zero_enter);
+DEFINE_SMB3_OTHER_DONE_EVENT(falloc_enter);
+DEFINE_SMB3_OTHER_DONE_EVENT(write_done);
+DEFINE_SMB3_OTHER_DONE_EVENT(query_dir_done);
+DEFINE_SMB3_OTHER_DONE_EVENT(zero_done);
+DEFINE_SMB3_OTHER_DONE_EVENT(falloc_done);
 
 /* For logging successful set EOF (truncate) */
 DECLARE_EVENT_CLASS(smb3_eof_class,
index 4c8af995c60b9b68884cc70d14f9130965d3be1e..012b9bd069952cec16bec71f03a594d53016450c 100644 (file)
@@ -1813,8 +1813,11 @@ cifs_readv_receive(struct TCP_Server_Info *server, struct mid_q_entry *mid)
                length = data_len; /* An RDMA read is already done. */
        else
 #endif
+       {
                length = cifs_read_iter_from_socket(server, &rdata->subreq.io_iter,
                                                    data_len);
+               iov_iter_revert(&rdata->subreq.io_iter, data_len);
+       }
        if (length > 0)
                rdata->got_bytes += length;
        server->total_read += length;