From nobody Thu Dec 18 18:17:18 2025 Received: from us-smtp-delivery-124.mimecast.com (us-smtp-delivery-124.mimecast.com [170.10.133.124]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 1AFBC194C81 for ; Tue, 30 Apr 2024 14:10:11 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=170.10.133.124 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1714486215; cv=none; b=lcE95DJ6XthaDFB2revaeX0nFEFVyFC9DUwIm5il45jP9o2awX8xf3lexMl/vR/BAEgcsnQXFgh4vOvWxs1jeDsRWSA0AFobZil6Fwn11xHNVWLESCslA90rWOTg2tTRscU4BLOLzyZIedJ5sV5SCMXa2fFrPV8Wkkggh9zwGrY= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1714486215; c=relaxed/simple; bh=jzbnRjFwDcW7vMi3vXBfsdQ2C37xOJPdHTzknyHtDmo=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=naJQ08BlildA6gWbc973FB17uEO9suCacXb+7+ZaQiLwOKnlUXYhaulkJ3Kgtfu1cHRqmCAfICEdK6sUfRGKeBtAeC4YjnDkIzpWoLpkottxYhm89neqIEDoY3N9dCh8Bf64o65Qr1ee3nJRxmUgWveNXYuhypTRhp8cWJAt4sQ= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=redhat.com; spf=pass smtp.mailfrom=redhat.com; dkim=pass (1024-bit key) header.d=redhat.com header.i=@redhat.com header.b=T3cKp1r9; arc=none smtp.client-ip=170.10.133.124 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=redhat.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=redhat.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (1024-bit key) header.d=redhat.com header.i=@redhat.com header.b="T3cKp1r9" DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1714486210; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=pEQftJ/7/eOOc06paPI302DotWs12CigmC6uGVPwDa4=; b=T3cKp1r9do30lEljdQQ0wMzHyK2BziSh1tHCvwsVU+LOfCWwYssWP+2aBJR07TEdGAJXdR QqHhreAVQYuaFd3CqZlW84x+OAsFIR8GXgrQrS2kkFNWZG2YHR8XK9fbkcE3xkH0J4rcLV oaG6lFkY3uwewfhTCCGpB92X4YB/kSA= Received: from mimecast-mx02.redhat.com (mimecast-mx02.redhat.com [66.187.233.88]) by relay.mimecast.com with ESMTP with STARTTLS (version=TLSv1.3, cipher=TLS_AES_256_GCM_SHA384) id us-mta-670-zh0IKt5UMFya9I2quWK4ww-1; Tue, 30 Apr 2024 10:10:06 -0400 X-MC-Unique: zh0IKt5UMFya9I2quWK4ww-1 Received: from smtp.corp.redhat.com (int-mx06.intmail.prod.int.rdu2.redhat.com [10.11.54.6]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (2048 bits) server-digest SHA256) (No client certificate requested) by mimecast-mx02.redhat.com (Postfix) with ESMTPS id BE0C981061A; Tue, 30 Apr 2024 14:10:05 +0000 (UTC) Received: from warthog.procyon.org.com (unknown [10.42.28.22]) by smtp.corp.redhat.com (Postfix) with ESMTP id 987192166B31; Tue, 30 Apr 2024 14:10:03 +0000 (UTC) From: David Howells To: Steve French Cc: David Howells , Jeff Layton , Matthew Wilcox , Paulo Alcantara , Shyam Prasad N , Tom Talpey , Christian Brauner , netfs@lists.linux.dev, linux-cifs@vger.kernel.org, linux-fsdevel@vger.kernel.org, linux-mm@kvack.org, linux-kernel@vger.kernel.org, Steve French , Shyam Prasad N , Rohith Surabattula Subject: [PATCH v7 12/16] cifs: Cut over to using netfslib Date: Tue, 30 Apr 2024 15:09:24 +0100 Message-ID: <20240430140930.262762-13-dhowells@redhat.com> In-Reply-To: <20240430140930.262762-1-dhowells@redhat.com> References: <20240430140930.262762-1-dhowells@redhat.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable X-Scanned-By: MIMEDefang 3.4.1 on 10.11.54.6 Content-Type: text/plain; charset="utf-8" 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 cc: Steve French cc: Shyam Prasad N cc: Rohith Surabattula cc: Jeff Layton cc: linux-cifs@vger.kernel.org cc: netfs@lists.linux.dev cc: linux-fsdevel@vger.kernel.org cc: linux-mm@kvack.org --- fs/netfs/io.c | 7 +- fs/smb/client/cifsfs.c | 8 +- fs/smb/client/cifsfs.h | 7 -- fs/smb/client/cifsglob.h | 5 +- fs/smb/client/cifsproto.h | 8 +- fs/smb/client/cifssmb.c | 54 +++++++------ fs/smb/client/file.c | 161 ++++++++++++++++++++------------------ fs/smb/client/fscache.c | 2 + fs/smb/client/fscache.h | 4 + fs/smb/client/inode.c | 19 ++++- fs/smb/client/smb2pdu.c | 117 ++++++++++++++++----------- fs/smb/client/smb2proto.h | 2 +- fs/smb/client/trace.h | 144 +++++++++++++++++++++++++++++----- fs/smb/client/transport.c | 3 + 14 files changed, 361 insertions(+), 180 deletions(-) diff --git a/fs/netfs/io.c b/fs/netfs/io.c index 6cfecfcd02e1..c93851b98368 100644 --- a/fs/netfs/io.c +++ b/fs/netfs/io.c @@ -213,8 +213,13 @@ static void netfs_rreq_assess_dio(struct netfs_io_requ= est *rreq) unsigned int i; size_t transferred =3D 0; =20 - for (i =3D 0; i < rreq->direct_bv_count; i++) + for (i =3D 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); + } =20 list_for_each_entry(subreq, &rreq->subrequests, rreq_link) { if (subreq->error || subreq->transferred =3D=3D 0) diff --git a/fs/smb/client/cifsfs.c b/fs/smb/client/cifsfs.c index 8f7165567be7..6e1698614745 100644 --- a/fs/smb/client/cifsfs.c +++ b/fs/smb/client/cifsfs.c @@ -1522,8 +1522,8 @@ const struct file_operations cifs_file_strict_ops =3D= { }; =20 const struct file_operations cifs_file_direct_ops =3D { - .read_iter =3D cifs_direct_readv, - .write_iter =3D cifs_direct_writev, + .read_iter =3D netfs_unbuffered_read_iter, + .write_iter =3D netfs_file_write_iter, .open =3D cifs_open, .release =3D cifs_close, .lock =3D cifs_lock, @@ -1578,8 +1578,8 @@ const struct file_operations cifs_file_strict_nobrl_o= ps =3D { }; =20 const struct file_operations cifs_file_direct_nobrl_ops =3D { - .read_iter =3D cifs_direct_readv, - .write_iter =3D cifs_direct_writev, + .read_iter =3D netfs_unbuffered_read_iter, + .write_iter =3D netfs_file_write_iter, .open =3D cifs_open, .release =3D cifs_close, .fsync =3D cifs_fsync, diff --git a/fs/smb/client/cifsfs.h b/fs/smb/client/cifsfs.h index 922c10d7cfdd..87310f05d397 100644 --- a/fs/smb/client/cifsfs.h +++ b/fs/smb/client/cifsfs.h @@ -94,11 +94,7 @@ extern const struct file_operations cifs_file_strict_nob= rl_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 *fro= m); extern ssize_t cifs_strict_writev(struct kiocb *iocb, struct iov_iter *fro= m); 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, str= uct 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, uns= igned int len); -extern void cifs_pages_write_failed(struct inode *inode, loff_t start, uns= igned int len); -extern void cifs_pages_write_redirty(struct inode *inode, loff_t start, un= signed int len); =20 /* Functions related to dir entries */ extern const struct dentry_operations cifs_dentry_ops; diff --git a/fs/smb/client/cifsglob.h b/fs/smb/client/cifsglob.h index 4e9033b2f191..983860bf5fbb 100644 --- a/fs/smb/client/cifsglob.h +++ b/fs/smb/client/cifsglob.h @@ -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; =20 - // 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 }; =20 /* diff --git a/fs/smb/client/cifsproto.h b/fs/smb/client/cifsproto.h index 103f264b42d7..d46ad86150cd 100644 --- a/fs/smb/client/cifsproto.h +++ b/fs/smb/client/cifsproto.h @@ -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, ss= ize_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 *c= tx); =20 +#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_s= ubrequest *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); =20 -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_su= brequest *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, diff --git a/fs/smb/client/cifssmb.c b/fs/smb/client/cifssmb.c index 99b75102ba6b..25e9ab947c17 100644 --- a/fs/smb/client/cifssmb.c +++ b/fs/smb/client/cifssmb.c @@ -1265,7 +1265,7 @@ static void cifs_readv_callback(struct mid_q_entry *mid) { struct cifs_io_subrequest *rdata =3D mid->callback_data; - struct cifs_tcon *tcon =3D tlink_tcon(rdata->cfile->tlink); + struct cifs_tcon *tcon =3D tlink_tcon(rdata->req->cfile->tlink); struct TCP_Server_Info *server =3D tcon->ses->server; struct smb_rqst rqst =3D { .rq_iov =3D rdata->iov, .rq_nvec =3D 2, @@ -1306,7 +1306,13 @@ cifs_readv_callback(struct mid_q_entry *mid) rdata->result =3D -EIO; } =20 - queue_work(cifsiod_wq, &rdata->work); + if (rdata->result =3D=3D 0 || rdata->result =3D=3D -EAGAIN) + iov_iter_advance(&rdata->subreq.io_iter, rdata->got_bytes); + rdata->credits.value =3D 0; + netfs_subreq_terminated(&rdata->subreq, + (rdata->result =3D=3D 0 || rdata->result =3D=3D -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 =3D NULL; int wct; - struct cifs_tcon *tcon =3D tlink_tcon(rdata->cfile->tlink); + struct cifs_tcon *tcon =3D tlink_tcon(rdata->req->cfile->tlink); struct smb_rqst rqst =3D { .rq_iov =3D rdata->iov, .rq_nvec =3D 2 }; =20 @@ -1343,7 +1349,7 @@ cifs_async_readv(struct cifs_io_subrequest *rdata) smb->hdr.PidHigh =3D cpu_to_le16((__u16)(rdata->pid >> 16)); =20 smb->AndXCommand =3D 0xFF; /* none */ - smb->Fid =3D rdata->cfile->fid.netfid; + smb->Fid =3D rdata->req->cfile->fid.netfid; smb->OffsetLow =3D cpu_to_le32(rdata->subreq.start & 0xFFFFFFFF); if (wct =3D=3D 12) smb->OffsetHigh =3D 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 =3D mid->callback_data; - struct cifs_tcon *tcon =3D tlink_tcon(wdata->cfile->tlink); - unsigned int written; + struct cifs_tcon *tcon =3D tlink_tcon(wdata->req->cfile->tlink); WRITE_RSP *smb =3D (WRITE_RSP *)mid->resp_buf; struct cifs_credits credits =3D { .value =3D 1, .instance =3D 0 }; + ssize_t result; + size_t written; =20 switch (mid->mid_state) { case MID_RESPONSE_RECEIVED: - wdata->result =3D cifs_check_receive(mid, tcon->ses->server, 0); - if (wdata->result !=3D 0) + result =3D cifs_check_receive(mid, tcon->ses->server, 0); + if (result !=3D 0) break; =20 written =3D le16_to_cpu(smb->CountHigh); @@ -1637,32 +1644,33 @@ cifs_writev_callback(struct mid_q_entry *mid) written &=3D 0xFFFF; =20 if (written < wdata->subreq.len) - wdata->result =3D -ENOSPC; + result =3D -ENOSPC; else - wdata->subreq.len =3D written; + result =3D written; break; case MID_REQUEST_SUBMITTED: case MID_RETRY_NEEDED: - wdata->result =3D -EAGAIN; + result =3D -EAGAIN; break; default: - wdata->result =3D -EIO; + result =3D -EIO; break; } =20 - queue_work(cifsiod_wq, &wdata->work); + wdata->credits.value =3D 0; + cifs_write_subrequest_terminated(wdata, result, true); release_mid(mid); add_credits(tcon->ses->server, &credits, 0); } =20 /* cifs_async_writev - send an async write, and set up mid to handle resul= t */ -int +void cifs_async_writev(struct cifs_io_subrequest *wdata) { int rc =3D -EACCES; WRITE_REQ *smb =3D NULL; int wct; - struct cifs_tcon *tcon =3D tlink_tcon(wdata->cfile->tlink); + struct cifs_tcon *tcon =3D tlink_tcon(wdata->req->cfile->tlink); struct kvec iov[2]; struct smb_rqst rqst =3D { }; =20 @@ -1672,7 +1680,8 @@ cifs_async_writev(struct cifs_io_subrequest *wdata) wct =3D 12; if (wdata->subreq.start >> 32 > 0) { /* can not handle big offset for old srv */ - return -EIO; + rc =3D -EIO; + goto out; } } =20 @@ -1684,7 +1693,7 @@ cifs_async_writev(struct cifs_io_subrequest *wdata) smb->hdr.PidHigh =3D cpu_to_le16((__u16)(wdata->pid >> 16)); =20 smb->AndXCommand =3D 0xFF; /* none */ - smb->Fid =3D wdata->cfile->fid.netfid; + smb->Fid =3D wdata->req->cfile->fid.netfid; smb->OffsetLow =3D cpu_to_le32(wdata->subreq.start & 0xFFFFFFFF); if (wct =3D=3D 14) smb->OffsetHigh =3D cpu_to_le32(wdata->subreq.start >> 32); @@ -1724,18 +1733,19 @@ cifs_async_writev(struct cifs_io_subrequest *wdata) iov[1].iov_len +=3D 4; /* pad bigger by four bytes */ } =20 - cifs_get_writedata(wdata); rc =3D cifs_call_async(tcon->ses->server, &rqst, NULL, cifs_writev_callback, NULL, wdata, 0, NULL); - + /* Can't touch wdata if rc =3D=3D 0 */ if (rc =3D=3D 0) cifs_stats_inc(&tcon->stats.cifs_stats.num_writes); - else - cifs_put_writedata(wdata); =20 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); + } } =20 int diff --git a/fs/smb/client/file.c b/fs/smb/client/file.c index c9c33b3a54f3..bb3adde9343e 100644 --- a/fs/smb/client/file.c +++ b/fs/smb/client/file.c @@ -119,7 +119,7 @@ static void cifs_issue_write(struct netfs_io_subrequest= *subreq) 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; } =20 @@ -352,6 +352,7 @@ const struct netfs_request_ops cifs_req_ops =3D { .issue_write =3D cifs_issue_write, }; =20 +#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 =20 rcu_read_unlock(); } +#endif // end netfslib remove 397 =20 /* * Mark as invalid, all open files on tree connections since they @@ -2522,20 +2524,23 @@ int cifs_lock(struct file *file, int cmd, struct fi= le_lock *flock) return rc; } =20 -/* - * 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, ss= ize_t result, + bool was_async) { - loff_t end_of_write =3D offset + bytes_written; + struct netfs_io_request *wreq =3D wdata->rreq; + loff_t new_server_eof; =20 - if (end_of_write > cifsi->netfs.remote_i_size) - netfs_resize_file(&cifsi->netfs, end_of_write, true); + if (result > 0) { + new_server_eof =3D wdata->subreq.start + wdata->subreq.transferred + res= ult; + + 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); } =20 +#if 0 // TODO remove 2483 static ssize_t cifs_write(struct cifsFileInfo *open_file, __u32 pid, const char *write_da= ta, 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 =20 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; } =20 +#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, =20 return rc; } +#endif // End netfs removal 2773 =20 +/* + * 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 @@ int cifs_strict_fsync(struct file *file, loff_t start= , loff_t end, return rc; } =20 +/* + * 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; } =20 +#if 0 // TODO remove 3594 static void collect_uncached_write_data(struct cifs_aio_ctx *ctx); =20 static void @@ -4037,6 +4052,7 @@ ssize_t cifs_user_writev(struct kiocb *iocb, struct i= ov_iter *from) { return __cifs_writev(iocb, from, false); } +#endif // TODO remove 3594 =20 static ssize_t cifs_writev(struct kiocb *iocb, struct iov_iter *from) @@ -4048,7 +4064,10 @@ cifs_writev(struct kiocb *iocb, struct iov_iter *fro= m) struct TCP_Server_Info *server =3D tlink_tcon(cfile->tlink)->ses->server; ssize_t rc; =20 - inode_lock(inode); + rc =3D 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 *fr= om) if (!cifs_find_lock_conflict(cfile, iocb->ki_pos, iov_iter_count(from), server->vals->exclusive_lock_type, 0, NULL, CIFS_WRITE_OP)) - rc =3D __generic_file_write_iter(iocb, from); + rc =3D netfs_buffered_write_iter_locked(iocb, from, NULL); else rc =3D -EACCES; out: up_read(&cinode->lock_sem); - inode_unlock(inode); - + netfs_end_io_write(inode); if (rc > 0) rc =3D generic_write_sync(iocb, rc); return rc; @@ -4091,9 +4109,9 @@ cifs_strict_writev(struct kiocb *iocb, struct iov_ite= r *from) =20 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) =3D=3D 0)) { - written =3D generic_file_write_iter(iocb, from); + (CIFS_UNIX_FCNTL_CAP & le64_to_cpu(tcon->fsUnixInfo.Capability)) && + ((cifs_sb->mnt_cifs_flags & CIFS_MOUNT_NOPOSIXBRL) =3D=3D 0)) { + written =3D netfs_file_write_iter(iocb, from); goto out; } written =3D cifs_writev(iocb, from); @@ -4105,7 +4123,7 @@ cifs_strict_writev(struct kiocb *iocb, struct iov_ite= r *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 =3D cifs_user_writev(iocb, from); + written =3D 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 @@ cifs_strict_writev(struct kiocb *iocb, struct iov_ite= r *from) return written; } =20 +#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 =20 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, st= ruct iov_iter *iter) struct inode *inode =3D file_inode(iocb->ki_filp); =20 if (iocb->ki_flags & IOCB_DIRECT) - return cifs_user_readv(iocb, iter); + return netfs_unbuffered_read_iter(iocb, iter); =20 rc =3D cifs_revalidate_mapping(inode); if (rc) return rc; =20 - return generic_file_read_iter(iocb, iter); + return netfs_file_read_iter(iocb, iter); } =20 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, stru= ct iov_iter *from) int rc; =20 if (iocb->ki_filp->f_flags & O_DIRECT) { - written =3D cifs_user_writev(iocb, from); + written =3D 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, st= ruct iov_iter *from) if (written) return written; =20 - written =3D generic_file_write_iter(iocb, from); - - if (CIFS_CACHE_WRITE(CIFS_I(inode))) - goto out; + written =3D netfs_file_write_iter(iocb, from); =20 - rc =3D 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 =3D filemap_fdatawrite(inode->i_mapping); + if (rc) + cifs_dbg(FYI, "cifs_file_write_iter: %d rc on %p inode\n", + rc, inode); + } =20 -out: cifs_put_writer(cinode); return written; } @@ -4638,12 +4657,15 @@ cifs_strict_readv(struct kiocb *iocb, struct iov_it= er *to) * pos+len-1. */ if (!CIFS_CACHE_READ(cinode)) - return cifs_user_readv(iocb, to); + return netfs_unbuffered_read_iter(iocb, to); =20 if (cap_unix(tcon->ses) && (CIFS_UNIX_FCNTL_CAP & le64_to_cpu(tcon->fsUnixInfo.Capability)) && - ((cifs_sb->mnt_cifs_flags & CIFS_MOUNT_NOPOSIXBRL) =3D=3D 0)) - return generic_file_read_iter(iocb, to); + ((cifs_sb->mnt_cifs_flags & CIFS_MOUNT_NOPOSIXBRL) =3D=3D 0)) { + if (iocb->ki_flags & IOCB_DIRECT) + return netfs_unbuffered_read_iter(iocb, to); + return netfs_buffered_read_iter(iocb, to); + } =20 /* * 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_it= er *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 =3D generic_file_read_iter(iocb, to); + 0, NULL, CIFS_READ_OP)) { + if (iocb->ki_flags & IOCB_DIRECT) + rc =3D netfs_unbuffered_read_iter(iocb, to); + else + rc =3D netfs_buffered_read_iter(iocb, to); + } up_read(&cinode->lock_sem); return rc; } =20 +#if 0 // TODO remove 4633 static ssize_t cifs_read(struct file *file, char *read_data, size_t read_size, loff_t *of= fset) { @@ -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 =20 -/* - * 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 =3D 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); } =20 static const struct vm_operations_struct cifs_file_vm_ops =3D { @@ -4817,6 +4826,7 @@ int cifs_file_mmap(struct file *file, struct vm_area_= struct *vma) return rc; } =20 +#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 =20 static int is_inode_writable(struct cifsInodeInfo *cifs_inode) { @@ -5149,6 +5160,7 @@ bool is_size_safe_to_change(struct cifsInodeInfo *cif= sInode, __u64 end_of_file, return true; } =20 +#if 0 // TODO remove 5152 static int cifs_write_begin(struct file *file, struct address_space *mappi= ng, 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 =20 void cifs_oplock_break(struct work_struct *work) { @@ -5334,6 +5347,7 @@ void cifs_oplock_break(struct work_struct *work) cifs_done_oplock_break(cinode); } =20 +#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 *i= ter) */ return -EINVAL; } +#endif // netfs end remove 5333 =20 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) } =20 const struct address_space_operations cifs_addr_ops =3D { - .read_folio =3D cifs_read_folio, - .readahead =3D cifs_readahead, - .writepages =3D cifs_writepages, - .write_begin =3D cifs_write_begin, - .write_end =3D cifs_write_end, - .dirty_folio =3D netfs_dirty_folio, - .release_folio =3D cifs_release_folio, - .direct_IO =3D cifs_direct_io, - .invalidate_folio =3D cifs_invalidate_folio, - .migrate_folio =3D filemap_migrate_folio, + .read_folio =3D netfs_read_folio, + .readahead =3D netfs_readahead, + .writepages =3D netfs_writepages, + .dirty_folio =3D netfs_dirty_folio, + .release_folio =3D netfs_release_folio, + .direct_IO =3D noop_direct_IO, + .invalidate_folio =3D netfs_invalidate_folio, + .migrate_folio =3D filemap_migrate_folio, /* * TODO: investigate and if useful we could add an is_dirty_writeback * helper if needed */ - .swap_activate =3D cifs_swap_activate, + .swap_activate =3D cifs_swap_activate, .swap_deactivate =3D cifs_swap_deactivate, }; =20 @@ -5438,12 +5451,10 @@ const struct address_space_operations cifs_addr_ops= =3D { * to leave cifs_readahead out of the address space operations. */ const struct address_space_operations cifs_addr_ops_smallbuf =3D { - .read_folio =3D cifs_read_folio, - .writepages =3D cifs_writepages, - .write_begin =3D cifs_write_begin, - .write_end =3D cifs_write_end, - .dirty_folio =3D netfs_dirty_folio, - .release_folio =3D cifs_release_folio, - .invalidate_folio =3D cifs_invalidate_folio, - .migrate_folio =3D filemap_migrate_folio, + .read_folio =3D netfs_read_folio, + .writepages =3D netfs_writepages, + .dirty_folio =3D netfs_dirty_folio, + .release_folio =3D netfs_release_folio, + .invalidate_folio =3D netfs_invalidate_folio, + .migrate_folio =3D filemap_migrate_folio, }; diff --git a/fs/smb/client/fscache.c b/fs/smb/client/fscache.c index 1a895e6243ee..b36c493f4c56 100644 --- a/fs/smb/client/fscache.c +++ b/fs/smb/client/fscache.c @@ -171,6 +171,7 @@ void cifs_fscache_release_inode_cookie(struct inode *in= ode) } } =20 +#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 diff --git a/fs/smb/client/fscache.h b/fs/smb/client/fscache.h index 1f2ea9f5cc9a..08b30f79d4cd 100644 --- a/fs/smb/client/fscache.h +++ b/fs/smb/client/fscache.h @@ -74,6 +74,7 @@ static inline void cifs_invalidate_cache(struct inode *in= ode, unsigned int flags i_size_read(inode), flags); } =20 +#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 ino= de *inode, if (cifs_inode_cookie(inode)) __cifs_readahead_to_fscache(inode, pos, len); } +#endif =20 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 fals= e; } =20 +#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) =20 static inline void cifs_readahead_to_fscache(struct inode *inode, loff_t pos, size_t len= ) {} +#endif =20 #endif /* CONFIG_CIFS_FSCACHE */ =20 diff --git a/fs/smb/client/inode.c b/fs/smb/client/inode.c index 033948d34c5a..5239c823de86 100644 --- a/fs/smb/client/inode.c +++ b/fs/smb/client/inode.c @@ -28,14 +28,29 @@ #include "cached_dir.h" #include "reparse.h" =20 +/* + * Set parameters for the netfs library + */ +static void cifs_set_netfs_context(struct inode *inode) +{ + struct cifsInodeInfo *cifs_i =3D CIFS_I(inode); + struct cifs_sb_info *cifs_sb =3D 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 =3D CIFS_SB(inode->i_sb); + struct netfs_inode *ictx =3D netfs_inode(inode); =20 switch (inode->i_mode & S_IFMT) { case S_IFREG: inode->i_op =3D &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 =3D &cifs_file_direct_nobrl_ops; else @@ -221,8 +236,10 @@ cifs_fattr_to_inode(struct inode *inode, struct cifs_f= attr *fattr, =20 if (fattr->cf_flags & CIFS_FATTR_JUNCTION) inode->i_flags |=3D 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; } =20 diff --git a/fs/smb/client/smb2pdu.c b/fs/smb/client/smb2pdu.c index b063f5e95f5d..993ac36c3d58 100644 --- a/fs/smb/client/smb2pdu.c +++ b/fs/smb/client/smb2pdu.c @@ -4421,10 +4421,12 @@ smb2_new_read_req(void **buf, unsigned int *total_l= en, req->Length =3D cpu_to_le32(io_parms->length); req->Offset =3D cpu_to_le64(io_parms->offset); =20 - 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 =3D mid->callback_data; - struct cifs_tcon *tcon =3D tlink_tcon(rdata->cfile->tlink); + struct cifs_tcon *tcon =3D tlink_tcon(rdata->req->cfile->tlink); struct TCP_Server_Info *server =3D rdata->server; struct smb2_hdr *shdr =3D (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; =20 - iov_iter_revert(&rqst.rq_iter, rdata->got_bytes); iov_iter_truncate(&rqst.rq_iter, rdata->got_bytes); rc =3D 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 !=3D -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); =20 - queue_work(cifsiod_wq, &rdata->work); + if (rdata->result =3D=3D -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 =3D 0; + } + if (rdata->result =3D=3D 0 || rdata->result =3D=3D -EAGAIN) + iov_iter_advance(&rdata->subreq.io_iter, rdata->got_bytes); + rdata->credits.value =3D 0; + netfs_subreq_terminated(&rdata->subreq, + (rdata->result =3D=3D 0 || rdata->result =3D=3D -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 =3D { .rq_iov =3D rdata->iov, .rq_nvec =3D 1 }; struct TCP_Server_Info *server; - struct cifs_tcon *tcon =3D tlink_tcon(rdata->cfile->tlink); + struct cifs_tcon *tcon =3D tlink_tcon(rdata->req->cfile->tlink); unsigned int total_len; int credit_request; =20 @@ -4591,12 +4608,12 @@ smb2_async_readv(struct cifs_io_subrequest *rdata) if (!rdata->server) rdata->server =3D cifs_pick_channel(tcon->ses); =20 - io_parms.tcon =3D tlink_tcon(rdata->cfile->tlink); + io_parms.tcon =3D tlink_tcon(rdata->req->cfile->tlink); io_parms.server =3D server =3D rdata->server; io_parms.offset =3D rdata->subreq.start; io_parms.length =3D rdata->subreq.len; - io_parms.persistent_fid =3D rdata->cfile->fid.persistent_fid; - io_parms.volatile_fid =3D rdata->cfile->fid.volatile_fid; + io_parms.persistent_fid =3D rdata->req->cfile->fid.persistent_fid; + io_parms.volatile_fid =3D rdata->req->cfile->fid.volatile_fid; io_parms.pid =3D rdata->pid; =20 rc =3D smb2_new_read_req( @@ -4630,15 +4647,15 @@ smb2_async_readv(struct cifs_io_subrequest *rdata) flags |=3D CIFS_HAS_CREDITS; } =20 - cifs_get_readdata(rdata); rc =3D 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_pa= rms *io_parms, if (rc !=3D -ENODATA) { cifs_stats_fail_inc(io_parms->tcon, SMB2_READ_HE); cifs_dbg(VFS, "Send error in read =3D %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 =3D=3D -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); =20 cifs_small_buf_release(req); =20 @@ -4738,11 +4756,12 @@ static void smb2_writev_callback(struct mid_q_entry *mid) { struct cifs_io_subrequest *wdata =3D mid->callback_data; - struct cifs_tcon *tcon =3D tlink_tcon(wdata->cfile->tlink); + struct cifs_tcon *tcon =3D tlink_tcon(wdata->req->cfile->tlink); struct TCP_Server_Info *server =3D wdata->server; - unsigned int written; struct smb2_write_rsp *rsp =3D (struct smb2_write_rsp *)mid->resp_buf; struct cifs_credits credits =3D { .value =3D 0, .instance =3D 0 }; + ssize_t result =3D 0; + size_t written; =20 WARN_ONCE(wdata->server !=3D mid->server, "wdata server %p !=3D mid server %p", @@ -4752,8 +4771,8 @@ smb2_writev_callback(struct mid_q_entry *mid) case MID_RESPONSE_RECEIVED: credits.value =3D le16_to_cpu(rsp->hdr.CreditRequest); credits.instance =3D server->reconnect_instance; - wdata->result =3D smb2_check_receive(mid, server, 0); - if (wdata->result !=3D 0) + result =3D smb2_check_receive(mid, server, 0); + if (result !=3D 0) break; =20 written =3D le32_to_cpu(rsp->DataLength); @@ -4770,17 +4789,18 @@ smb2_writev_callback(struct mid_q_entry *mid) wdata->result =3D -ENOSPC; else wdata->subreq.len =3D written; + iov_iter_advance(&wdata->subreq.io_iter, written); break; case MID_REQUEST_SUBMITTED: case MID_RETRY_NEEDED: - wdata->result =3D -EAGAIN; + result =3D -EAGAIN; break; case MID_RESPONSE_MALFORMED: credits.value =3D le16_to_cpu(rsp->hdr.CreditRequest); credits.instance =3D server->reconnect_instance; fallthrough; default: - wdata->result =3D -EIO; + result =3D -EIO; break; } #ifdef CONFIG_CIFS_SMB_DIRECT @@ -4796,10 +4816,10 @@ smb2_writev_callback(struct mid_q_entry *mid) wdata->mr =3D 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 =3D=3D -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); =20 - queue_work(cifsiod_wq, &wdata->work); + wdata->credits.value =3D 0; + cifs_write_subrequest_terminated(wdata, result ?: written, true); release_mid(mid); add_credits(server, &credits, 0); } =20 /* smb2_async_writev - send an async write, and set up mid to handle resul= t */ -int +void smb2_async_writev(struct cifs_io_subrequest *wdata) { int rc =3D -EACCES, flags =3D 0; struct smb2_write_req *req =3D NULL; struct smb2_hdr *shdr; - struct cifs_tcon *tcon =3D tlink_tcon(wdata->cfile->tlink); + struct cifs_tcon *tcon =3D tlink_tcon(wdata->req->cfile->tlink); struct TCP_Server_Info *server =3D wdata->server; struct kvec iov[1]; struct smb_rqst rqst =3D { }; - unsigned int total_len; + unsigned int total_len, xid =3D wdata->xid; struct cifs_io_parms _io_parms; struct cifs_io_parms *io_parms =3D NULL; int credit_request; @@ -4844,8 +4865,8 @@ smb2_async_writev(struct cifs_io_subrequest *wdata) .server =3D server, .offset =3D wdata->subreq.start, .length =3D wdata->subreq.len, - .persistent_fid =3D wdata->cfile->fid.persistent_fid, - .volatile_fid =3D wdata->cfile->fid.volatile_fid, + .persistent_fid =3D wdata->req->cfile->fid.persistent_fid, + .volatile_fid =3D wdata->req->cfile->fid.volatile_fid, .pid =3D wdata->pid, }; io_parms =3D &_io_parms; @@ -4853,7 +4874,7 @@ smb2_async_writev(struct cifs_io_subrequest *wdata) rc =3D smb2_plain_req_init(SMB2_WRITE, tcon, server, (void **) &req, &total_len); if (rc) - return rc; + goto out; =20 if (smb3_encryption_required(tcon)) flags |=3D CIFS_TRANSFORM_REQ; @@ -4871,7 +4892,7 @@ smb2_async_writev(struct cifs_io_subrequest *wdata) offsetof(struct smb2_write_req, Buffer)); req->RemainingBytes =3D 0; =20 - 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 |=3D CIFS_HAS_CREDITS; } =20 - cifs_get_writedata(wdata); rc =3D cifs_call_async(server, &rqst, NULL, smb2_writev_callback, NULL, wdata, flags, &wdata->credits); - + /* Can't touch wdata if rc =3D=3D 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); } =20 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); + } } =20 /* diff --git a/fs/smb/client/smb2proto.h b/fs/smb/client/smb2proto.h index c781eaa0cba8..b208232b12a2 100644 --- a/fs/smb/client/smb2proto.h +++ b/fs/smb/client/smb2proto.h @@ -213,7 +213,7 @@ extern int SMB2_get_srv_num(const unsigned int xid, str= uct 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_parm= s, 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_par= ms, unsigned int *nbytes, struct kvec *iov, int n_vec); extern int SMB2_echo(struct TCP_Server_Info *server); diff --git a/fs/smb/client/trace.h b/fs/smb/client/trace.h index 604e52876cd2..af97389e983e 100644 --- a/fs/smb/client/trace.h +++ b/fs/smb/client/trace.h @@ -85,6 +85,62 @@ smb3_tcon_ref_traces; =20 /* 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 =3D rreq_debug_id; + __entry->rreq_debug_index =3D rreq_debug_index; + __entry->xid =3D xid; + __entry->fid =3D fid; + __entry->tid =3D tid; + __entry->sesid =3D sesid; + __entry->offset =3D offset; + __entry->len =3D len; + __entry->rc =3D rc; + ), + TP_printk("\tR=3D%08x[%x] xid=3D%u sid=3D0x%llx tid=3D0x%x fid=3D0x%llx o= ffset=3D0x%llx len=3D0x%x rc=3D%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, le= n, 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) ) =20 -#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)) =20 -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); =20 =20 /* 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 =3D rreq_debug_id; + __entry->rreq_debug_index =3D rreq_debug_index; + __entry->xid =3D xid; + __entry->fid =3D fid; + __entry->tid =3D tid; + __entry->sesid =3D sesid; + __entry->offset =3D offset; + __entry->len =3D len; + ), + TP_printk("R=3D%08x[%x] xid=3D%u sid=3D0x%llx tid=3D0x%x fid=3D0x%llx off= set=3D0x%llx len=3D0x%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, le= n)) + +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) ) =20 -#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)) =20 -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); =20 /* For logging successful set EOF (truncate) */ DECLARE_EVENT_CLASS(smb3_eof_class, diff --git a/fs/smb/client/transport.c b/fs/smb/client/transport.c index 4c8af995c60b..012b9bd06995 100644 --- a/fs/smb/client/transport.c +++ b/fs/smb/client/transport.c @@ -1813,8 +1813,11 @@ cifs_readv_receive(struct TCP_Server_Info *server, s= truct mid_q_entry *mid) length =3D data_len; /* An RDMA read is already done. */ else #endif + { length =3D 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 +=3D length; server->total_read +=3D length;