* [PATCH 0/4] cifs: Miscellaneous fixes and a trace point
@ 2024-07-19 14:09 David Howells
2024-07-19 14:09 ` [PATCH 1/4] cifs: Fix server re-repick on subrequest retry David Howells
` (5 more replies)
0 siblings, 6 replies; 9+ messages in thread
From: David Howells @ 2024-07-19 14:09 UTC (permalink / raw)
To: Steve French
Cc: David Howells, Paulo Alcantara, Shyam Prasad N,
Rohith Surabattula, Jeff Layton, linux-cifs, linux-fsdevel
Hi Steve,
Here are four patches for cifs:
(1) Fix re-repick of a server upon subrequest retry.
(2) Fix some error code setting that got accidentally removed.
(3) Fix the handling of the zero_point after a DIO write. It always needs
to be bumped past the end of the DIO write.
(4) Add a tracepoint and some debugging to keep track of when we've ended
the ->in_flight contribution from an operation.
I've pushed the patches here also:
https://git.kernel.org/pub/scm/linux/kernel/git/dhowells/linux-fs.git/log/?h=cifs-fixes
David
David Howells (4):
cifs: Fix server re-repick on subrequest retry
cifs: Fix missing error code set
cifs: Fix setting of zero_point after DIO write
cifs: Add a tracepoint to track credits involved in R/W requests
fs/smb/client/cifsglob.h | 17 +++++++-----
fs/smb/client/file.c | 47 +++++++++++++++++++++++++++++----
fs/smb/client/smb1ops.c | 2 +-
fs/smb/client/smb2ops.c | 42 ++++++++++++++++++++++++++----
fs/smb/client/smb2pdu.c | 43 +++++++++++++++++++++++++-----
fs/smb/client/trace.h | 55 ++++++++++++++++++++++++++++++++++++++-
fs/smb/client/transport.c | 8 +++---
7 files changed, 184 insertions(+), 30 deletions(-)
^ permalink raw reply [flat|nested] 9+ messages in thread* [PATCH 1/4] cifs: Fix server re-repick on subrequest retry 2024-07-19 14:09 [PATCH 0/4] cifs: Miscellaneous fixes and a trace point David Howells @ 2024-07-19 14:09 ` David Howells 2024-07-19 14:27 ` Tom Talpey 2024-07-19 14:09 ` [PATCH 2/4] cifs: Fix missing error code set David Howells ` (4 subsequent siblings) 5 siblings, 1 reply; 9+ messages in thread From: David Howells @ 2024-07-19 14:09 UTC (permalink / raw) To: Steve French Cc: David Howells, Paulo Alcantara, Shyam Prasad N, Rohith Surabattula, Jeff Layton, linux-cifs, linux-fsdevel, Aurelien Aptel, netfs When a subrequest is marked for needing retry, netfs will call cifs_prepare_write() which will make cifs repick the server for the op before renegotiating credits; it then calls cifs_issue_write() which invokes smb2_async_writev() - which re-repicks the server. If a different server is then selected, this causes the increment of server->in_flight to happen against one record and the decrement to happen against another, leading to misaccounting. Fix this by just removing the repick code in smb2_async_writev(). As this is only called from netfslib-driven code, cifs_prepare_write() should always have been called first, and so server should never be NULL and the preparatory step is repeated in the event that we do a retry. The problem manifests as a warning looking something like: WARNING: CPU: 4 PID: 72896 at fs/smb/client/smb2ops.c:97 smb2_add_credits+0x3f0/0x9e0 [cifs] ... RIP: 0010:smb2_add_credits+0x3f0/0x9e0 [cifs] ... smb2_writev_callback+0x334/0x560 [cifs] cifs_demultiplex_thread+0x77a/0x11b0 [cifs] kthread+0x187/0x1d0 ret_from_fork+0x34/0x60 ret_from_fork_asm+0x1a/0x30 Which may be triggered by a number of different xfstests running against an Azure server in multichannel mode. generic/249 seems the most repeatable, but generic/215, generic/249 and generic/308 may also show it. Fixes: 3ee1a1fc3981 ("cifs: Cut over to using netfslib") Reported-by: Steve French <sfrench@samba.org> Signed-off-by: David Howells <dhowells@redhat.com> Reviewed-by: Paulo Alcantara (Red Hat) <pc@manguebit.com> cc: Jeff Layton <jlayton@kernel.org> cc: Aurelien Aptel <aaptel@suse.com> cc: linux-cifs@vger.kernel.org cc: netfs@lists.linux.dev cc: linux-fsdevel@vger.kernel.org --- fs/smb/client/smb2pdu.c | 3 --- 1 file changed, 3 deletions(-) diff --git a/fs/smb/client/smb2pdu.c b/fs/smb/client/smb2pdu.c index 2ae2dbb6202b..bb84a89e5905 100644 --- a/fs/smb/client/smb2pdu.c +++ b/fs/smb/client/smb2pdu.c @@ -4859,9 +4859,6 @@ smb2_async_writev(struct cifs_io_subrequest *wdata) struct cifs_io_parms *io_parms = NULL; int credit_request; - if (!wdata->server || test_bit(NETFS_SREQ_RETRYING, &wdata->subreq.flags)) - server = wdata->server = cifs_pick_channel(tcon->ses); - /* * in future we may get cifs_io_parms passed in from the caller, * but for now we construct it here... ^ permalink raw reply related [flat|nested] 9+ messages in thread
* Re: [PATCH 1/4] cifs: Fix server re-repick on subrequest retry 2024-07-19 14:09 ` [PATCH 1/4] cifs: Fix server re-repick on subrequest retry David Howells @ 2024-07-19 14:27 ` Tom Talpey 2024-07-19 15:45 ` Steve French 0 siblings, 1 reply; 9+ messages in thread From: Tom Talpey @ 2024-07-19 14:27 UTC (permalink / raw) To: David Howells, Steve French Cc: Paulo Alcantara, Shyam Prasad N, Rohith Surabattula, Jeff Layton, linux-cifs, linux-fsdevel, Aurelien Aptel, netfs On 7/19/2024 10:09 AM, David Howells wrote: > When a subrequest is marked for needing retry, netfs will call > cifs_prepare_write() which will make cifs repick the server for the op > before renegotiating credits; it then calls cifs_issue_write() which > invokes smb2_async_writev() - which re-repicks the server. > > If a different server is then selected, this causes the increment of > server->in_flight to happen against one record and the decrement to happen > against another, leading to misaccounting. > > Fix this by just removing the repick code in smb2_async_writev(). As this > is only called from netfslib-driven code, cifs_prepare_write() should > always have been called first, and so server should never be NULL and the > preparatory step is repeated in the event that we do a retry. > > The problem manifests as a warning looking something like: > > WARNING: CPU: 4 PID: 72896 at fs/smb/client/smb2ops.c:97 smb2_add_credits+0x3f0/0x9e0 [cifs] > ... > RIP: 0010:smb2_add_credits+0x3f0/0x9e0 [cifs] > ... > smb2_writev_callback+0x334/0x560 [cifs] > cifs_demultiplex_thread+0x77a/0x11b0 [cifs] > kthread+0x187/0x1d0 > ret_from_fork+0x34/0x60 > ret_from_fork_asm+0x1a/0x30 > > Which may be triggered by a number of different xfstests running against an > Azure server in multichannel mode. generic/249 seems the most repeatable, > but generic/215, generic/249 and generic/308 may also show it. Nice fix, and good explanation. So, is this the negative-credits issue we've been looking to fix? Or just one instance? I'm very curious why it manifested when testing with Azure Files. Do connection errors disappear with the fix, or do they still occur but are now recoverable? Feel free to add... Acked-by: Tom Talpey <tom@talpey.com> Tom. > Fixes: 3ee1a1fc3981 ("cifs: Cut over to using netfslib") > Reported-by: Steve French <sfrench@samba.org> > Signed-off-by: David Howells <dhowells@redhat.com> > Reviewed-by: Paulo Alcantara (Red Hat) <pc@manguebit.com> > cc: Jeff Layton <jlayton@kernel.org> > cc: Aurelien Aptel <aaptel@suse.com> > cc: linux-cifs@vger.kernel.org > cc: netfs@lists.linux.dev > cc: linux-fsdevel@vger.kernel.org > --- > fs/smb/client/smb2pdu.c | 3 --- > 1 file changed, 3 deletions(-) > > diff --git a/fs/smb/client/smb2pdu.c b/fs/smb/client/smb2pdu.c > index 2ae2dbb6202b..bb84a89e5905 100644 > --- a/fs/smb/client/smb2pdu.c > +++ b/fs/smb/client/smb2pdu.c > @@ -4859,9 +4859,6 @@ smb2_async_writev(struct cifs_io_subrequest *wdata) > struct cifs_io_parms *io_parms = NULL; > int credit_request; > > - if (!wdata->server || test_bit(NETFS_SREQ_RETRYING, &wdata->subreq.flags)) > - server = wdata->server = cifs_pick_channel(tcon->ses); > - > /* > * in future we may get cifs_io_parms passed in from the caller, > * but for now we construct it here... > > > ^ permalink raw reply [flat|nested] 9+ messages in thread
* Re: [PATCH 1/4] cifs: Fix server re-repick on subrequest retry 2024-07-19 14:27 ` Tom Talpey @ 2024-07-19 15:45 ` Steve French 0 siblings, 0 replies; 9+ messages in thread From: Steve French @ 2024-07-19 15:45 UTC (permalink / raw) To: Tom Talpey Cc: David Howells, Steve French, Paulo Alcantara, Shyam Prasad N, Rohith Surabattula, Jeff Layton, linux-cifs, linux-fsdevel, Aurelien Aptel, netfs On Fri, Jul 19, 2024 at 9:27 AM Tom Talpey <tom@talpey.com> wrote: > > On 7/19/2024 10:09 AM, David Howells wrote: > > When a subrequest is marked for needing retry, netfs will call > > cifs_prepare_write() which will make cifs repick the server for the op > > before renegotiating credits; it then calls cifs_issue_write() which > > invokes smb2_async_writev() - which re-repicks the server. > > > > If a different server is then selected, this causes the increment of > > server->in_flight to happen against one record and the decrement to happen > > against another, leading to misaccounting. > > > > Fix this by just removing the repick code in smb2_async_writev(). As this > > is only called from netfslib-driven code, cifs_prepare_write() should > > always have been called first, and so server should never be NULL and the > > preparatory step is repeated in the event that we do a retry. > > > > The problem manifests as a warning looking something like: > > > > WARNING: CPU: 4 PID: 72896 at fs/smb/client/smb2ops.c:97 smb2_add_credits+0x3f0/0x9e0 [cifs] > > ... > > RIP: 0010:smb2_add_credits+0x3f0/0x9e0 [cifs] > > ... > > smb2_writev_callback+0x334/0x560 [cifs] > > cifs_demultiplex_thread+0x77a/0x11b0 [cifs] > > kthread+0x187/0x1d0 > > ret_from_fork+0x34/0x60 > > ret_from_fork_asm+0x1a/0x30 > > > > Which may be triggered by a number of different xfstests running against an > > Azure server in multichannel mode. generic/249 seems the most repeatable, > > but generic/215, generic/249 and generic/308 may also show it. > > Nice fix, and good explanation. So, is this the negative-credits issue > we've been looking to fix? Or just one instance? Yes it fixes the only recent crediting issues that I had been seeing. > Feel free to add... > > Acked-by: Tom Talpey <tom@talpey.com> Done ^ permalink raw reply [flat|nested] 9+ messages in thread
* [PATCH 2/4] cifs: Fix missing error code set 2024-07-19 14:09 [PATCH 0/4] cifs: Miscellaneous fixes and a trace point David Howells 2024-07-19 14:09 ` [PATCH 1/4] cifs: Fix server re-repick on subrequest retry David Howells @ 2024-07-19 14:09 ` David Howells 2024-07-19 14:09 ` [PATCH 3/4] cifs: Fix setting of zero_point after DIO write David Howells ` (3 subsequent siblings) 5 siblings, 0 replies; 9+ messages in thread From: David Howells @ 2024-07-19 14:09 UTC (permalink / raw) To: Steve French Cc: David Howells, Paulo Alcantara, Shyam Prasad N, Rohith Surabattula, Jeff Layton, linux-cifs, linux-fsdevel, Steve French, netfs In cifs_strict_readv(), the default rc (-EACCES) is accidentally cleared by a successful return from netfs_start_io_direct(), such that if cifs_find_lock_conflict() fails, we don't return an error. Fix this by resetting the default error code. Fixes: 14b1cd25346b ("cifs: Fix locking in cifs_strict_readv()") Signed-off-by: David Howells <dhowells@redhat.com> Reviewed-by: Paulo Alcantara (Red Hat) <pc@manguebit.com> cc: Steve French <stfrench@microsoft.com> cc: Jeff Layton <jlayton@kernel.org> cc: linux-cifs@vger.kernel.org cc: netfs@lists.linux.dev cc: linux-fsdevel@vger.kernel.org --- fs/smb/client/file.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/fs/smb/client/file.c b/fs/smb/client/file.c index 1374635e89fa..6178c6d8097d 100644 --- a/fs/smb/client/file.c +++ b/fs/smb/client/file.c @@ -2877,6 +2877,7 @@ cifs_strict_readv(struct kiocb *iocb, struct iov_iter *to) rc = netfs_start_io_direct(inode); if (rc < 0) goto out; + rc = -EACCES; down_read(&cinode->lock_sem); if (!cifs_find_lock_conflict( cfile, iocb->ki_pos, iov_iter_count(to), @@ -2889,6 +2890,7 @@ cifs_strict_readv(struct kiocb *iocb, struct iov_iter *to) rc = netfs_start_io_read(inode); if (rc < 0) goto out; + rc = -EACCES; down_read(&cinode->lock_sem); if (!cifs_find_lock_conflict( cfile, iocb->ki_pos, iov_iter_count(to), ^ permalink raw reply related [flat|nested] 9+ messages in thread
* [PATCH 3/4] cifs: Fix setting of zero_point after DIO write 2024-07-19 14:09 [PATCH 0/4] cifs: Miscellaneous fixes and a trace point David Howells 2024-07-19 14:09 ` [PATCH 1/4] cifs: Fix server re-repick on subrequest retry David Howells 2024-07-19 14:09 ` [PATCH 2/4] cifs: Fix missing error code set David Howells @ 2024-07-19 14:09 ` David Howells 2024-07-19 14:09 ` [PATCH 4/4] cifs: Add a tracepoint to track credits involved in R/W requests David Howells ` (2 subsequent siblings) 5 siblings, 0 replies; 9+ messages in thread From: David Howells @ 2024-07-19 14:09 UTC (permalink / raw) To: Steve French Cc: David Howells, Paulo Alcantara, Shyam Prasad N, Rohith Surabattula, Jeff Layton, linux-cifs, linux-fsdevel, netfs At the moment, at the end of a DIO write, cifs calls netfs_resize_file() to adjust the size of the file if it needs it. This will reduce the zero_point (the point above which we assume a read will just return zeros) if it's more than the new i_size, but won't increase it. With DIO writes, however, we definitely want to increase it as we have clobbered the local pagecache and then written some data that's not available locally. Fix cifs to make the zero_point above the end of a DIO or unbuffered write. This fixes corruption seen occasionally with the generic/708 xfs-test. In that case, the read-back of some of the written data is being short-circuited and replaced with zeroes. Fixes: 3ee1a1fc3981 ("cifs: Cut over to using netfslib") Reported-by: Steve French <sfrench@samba.org> Signed-off-by: David Howells <dhowells@redhat.com> Reviewed-by: Paulo Alcantara (Red Hat) <pc@manguebit.com> cc: Jeff Layton <jlayton@kernel.org> cc: linux-cifs@vger.kernel.org cc: netfs@lists.linux.dev cc: linux-fsdevel@vger.kernel.org --- fs/smb/client/file.c | 15 ++++++++++----- 1 file changed, 10 insertions(+), 5 deletions(-) diff --git a/fs/smb/client/file.c b/fs/smb/client/file.c index 6178c6d8097d..72cc265bc471 100644 --- a/fs/smb/client/file.c +++ b/fs/smb/client/file.c @@ -2358,13 +2358,18 @@ void cifs_write_subrequest_terminated(struct cifs_io_subrequest *wdata, ssize_t bool was_async) { struct netfs_io_request *wreq = wdata->rreq; - loff_t new_server_eof; + struct netfs_inode *ictx = netfs_inode(wreq->inode); + loff_t wrend; 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); + wrend = wdata->subreq.start + wdata->subreq.transferred + result; + + if (wrend > ictx->zero_point && + (wdata->rreq->origin == NETFS_UNBUFFERED_WRITE || + wdata->rreq->origin == NETFS_DIO_WRITE)) + ictx->zero_point = wrend; + if (wrend > ictx->remote_i_size) + netfs_resize_file(ictx, wrend, true); } netfs_write_subrequest_terminated(&wdata->subreq, result, was_async); ^ permalink raw reply related [flat|nested] 9+ messages in thread
* [PATCH 4/4] cifs: Add a tracepoint to track credits involved in R/W requests 2024-07-19 14:09 [PATCH 0/4] cifs: Miscellaneous fixes and a trace point David Howells ` (2 preceding siblings ...) 2024-07-19 14:09 ` [PATCH 3/4] cifs: Fix setting of zero_point after DIO write David Howells @ 2024-07-19 14:09 ` David Howells 2024-07-19 14:26 ` [PATCH 0/4] cifs: Miscellaneous fixes and a trace point Steve French 2024-07-19 15:25 ` [PATCH 5/4] cifs: Fix missing fscache invalidation David Howells 5 siblings, 0 replies; 9+ messages in thread From: David Howells @ 2024-07-19 14:09 UTC (permalink / raw) To: Steve French Cc: David Howells, Paulo Alcantara, Shyam Prasad N, Rohith Surabattula, Jeff Layton, linux-cifs, linux-fsdevel, netfs Add a tracepoint to track the credit changes and server in_flight value involved in the lifetime of a R/W request, logging it against the request/subreq debugging ID. This requires the debugging IDs to be recorded in the cifs_credits struct. The tracepoint can be enabled with: echo 1 >/sys/kernel/debug/tracing/events/cifs/smb3_rw_credits/enable Also add a three-state flag to struct cifs_credits to note if we're interested in determining when the in_flight contribution ends and, if so, to track whether we've decremented the contribution yet. Signed-off-by: David Howells <dhowells@redhat.com> Reviewed-by: Paulo Alcantara (Red Hat) <pc@manguebit.com> cc: Steve French <sfrench@samba.org> cc: Jeff Layton <jlayton@kernel.org> cc: linux-cifs@vger.kernel.org cc: netfs@lists.linux.dev cc: linux-fsdevel@vger.kernel.org --- fs/smb/client/cifsglob.h | 17 +++++++----- fs/smb/client/file.c | 32 ++++++++++++++++++++++- fs/smb/client/smb1ops.c | 2 +- fs/smb/client/smb2ops.c | 42 ++++++++++++++++++++++++++---- fs/smb/client/smb2pdu.c | 40 +++++++++++++++++++++++++--- fs/smb/client/trace.h | 55 ++++++++++++++++++++++++++++++++++++++- fs/smb/client/transport.c | 8 +++--- 7 files changed, 173 insertions(+), 23 deletions(-) diff --git a/fs/smb/client/cifsglob.h b/fs/smb/client/cifsglob.h index a865941724c0..8e86fec7dcd2 100644 --- a/fs/smb/client/cifsglob.h +++ b/fs/smb/client/cifsglob.h @@ -290,7 +290,7 @@ struct smb_version_operations { int (*check_receive)(struct mid_q_entry *, struct TCP_Server_Info *, bool); void (*add_credits)(struct TCP_Server_Info *server, - const struct cifs_credits *credits, + struct cifs_credits *credits, const int optype); void (*set_credits)(struct TCP_Server_Info *, const int); int * (*get_credits_field)(struct TCP_Server_Info *, const int); @@ -550,8 +550,8 @@ struct smb_version_operations { size_t *, struct cifs_credits *); /* adjust previously taken mtu credits to request size */ int (*adjust_credits)(struct TCP_Server_Info *server, - struct cifs_credits *credits, - const unsigned int payload_size); + struct cifs_io_subrequest *subreq, + unsigned int /*enum smb3_rw_credits_trace*/ trace); /* check if we need to issue closedir */ bool (*dir_needs_close)(struct cifsFileInfo *); long (*fallocate)(struct file *, struct cifs_tcon *, int, loff_t, @@ -848,6 +848,9 @@ static inline void cifs_server_unlock(struct TCP_Server_Info *server) struct cifs_credits { unsigned int value; unsigned int instance; + unsigned int in_flight_check; + unsigned int rreq_debug_id; + unsigned int rreq_debug_index; }; static inline unsigned int @@ -873,7 +876,7 @@ has_credits(struct TCP_Server_Info *server, int *credits, int num_credits) } static inline void -add_credits(struct TCP_Server_Info *server, const struct cifs_credits *credits, +add_credits(struct TCP_Server_Info *server, struct cifs_credits *credits, const int optype) { server->ops->add_credits(server, credits, optype); @@ -897,11 +900,11 @@ set_credits(struct TCP_Server_Info *server, const int val) } static inline int -adjust_credits(struct TCP_Server_Info *server, struct cifs_credits *credits, - const unsigned int payload_size) +adjust_credits(struct TCP_Server_Info *server, struct cifs_io_subrequest *subreq, + unsigned int /* enum smb3_rw_credits_trace */ trace) { return server->ops->adjust_credits ? - server->ops->adjust_credits(server, credits, payload_size) : 0; + server->ops->adjust_credits(server, subreq, trace) : 0; } static inline __le64 diff --git a/fs/smb/client/file.c b/fs/smb/client/file.c index 72cc265bc471..f8d6ad88335e 100644 --- a/fs/smb/client/file.c +++ b/fs/smb/client/file.c @@ -80,6 +80,16 @@ static void cifs_prepare_write(struct netfs_io_subrequest *subreq) return netfs_prepare_write_failed(subreq); } + wdata->credits.rreq_debug_id = subreq->rreq->debug_id; + wdata->credits.rreq_debug_index = subreq->debug_index; + wdata->credits.in_flight_check = 1; + trace_smb3_rw_credits(wdata->rreq->debug_id, + wdata->subreq.debug_index, + wdata->credits.value, + server->credits, server->in_flight, + wdata->credits.value, + cifs_trace_rw_credits_write_prepare); + #ifdef CONFIG_CIFS_SMB_DIRECT if (server->smbd_conn) subreq->max_nr_segs = server->smbd_conn->max_frmr_depth; @@ -101,7 +111,7 @@ static void cifs_issue_write(struct netfs_io_subrequest *subreq) goto fail; } - rc = adjust_credits(wdata->server, &wdata->credits, wdata->subreq.len); + rc = adjust_credits(wdata->server, wdata, cifs_trace_rw_credits_issue_write_adjust); if (rc) goto fail; @@ -158,7 +168,18 @@ static bool cifs_clamp_length(struct netfs_io_subrequest *subreq) return false; } + rdata->credits.in_flight_check = 1; + rdata->credits.rreq_debug_id = rreq->debug_id; + rdata->credits.rreq_debug_index = subreq->debug_index; + + trace_smb3_rw_credits(rdata->rreq->debug_id, + rdata->subreq.debug_index, + rdata->credits.value, + server->credits, server->in_flight, 0, + cifs_trace_rw_credits_read_submit); + subreq->len = min_t(size_t, subreq->len, rsize); + #ifdef CONFIG_CIFS_SMB_DIRECT if (server->smbd_conn) subreq->max_nr_segs = server->smbd_conn->max_frmr_depth; @@ -289,6 +310,15 @@ static void cifs_free_subrequest(struct netfs_io_subrequest *subreq) #endif } + if (rdata->credits.value != 0) + trace_smb3_rw_credits(rdata->rreq->debug_id, + rdata->subreq.debug_index, + rdata->credits.value, + rdata->server ? rdata->server->credits : 0, + rdata->server ? rdata->server->in_flight : 0, + -rdata->credits.value, + cifs_trace_rw_credits_free_subreq); + add_credits_and_wake_if(rdata->server, &rdata->credits, 0); if (rdata->have_xid) free_xid(rdata->xid); diff --git a/fs/smb/client/smb1ops.c b/fs/smb/client/smb1ops.c index 212ec6f66ec6..e1f2feb56f45 100644 --- a/fs/smb/client/smb1ops.c +++ b/fs/smb/client/smb1ops.c @@ -108,7 +108,7 @@ cifs_find_mid(struct TCP_Server_Info *server, char *buffer) static void cifs_add_credits(struct TCP_Server_Info *server, - const struct cifs_credits *credits, const int optype) + struct cifs_credits *credits, const int optype) { spin_lock(&server->req_lock); server->credits += credits->value; diff --git a/fs/smb/client/smb2ops.c b/fs/smb/client/smb2ops.c index c8e536540895..7fe59235f090 100644 --- a/fs/smb/client/smb2ops.c +++ b/fs/smb/client/smb2ops.c @@ -66,7 +66,7 @@ change_conf(struct TCP_Server_Info *server) static void smb2_add_credits(struct TCP_Server_Info *server, - const struct cifs_credits *credits, const int optype) + struct cifs_credits *credits, const int optype) { int *val, rc = -1; int scredits, in_flight; @@ -94,7 +94,21 @@ smb2_add_credits(struct TCP_Server_Info *server, server->conn_id, server->hostname, *val, add, server->in_flight); } - WARN_ON_ONCE(server->in_flight == 0); + if (credits->in_flight_check > 1) { + pr_warn_once("rreq R=%08x[%x] Credits not in flight\n", + credits->rreq_debug_id, credits->rreq_debug_index); + } else { + credits->in_flight_check = 2; + } + if (WARN_ON_ONCE(server->in_flight == 0)) { + pr_warn_once("rreq R=%08x[%x] Zero in_flight\n", + credits->rreq_debug_id, credits->rreq_debug_index); + trace_smb3_rw_credits(credits->rreq_debug_id, + credits->rreq_debug_index, + credits->value, + server->credits, server->in_flight, 0, + cifs_trace_rw_credits_zero_in_flight); + } server->in_flight--; if (server->in_flight == 0 && ((optype & CIFS_OP_MASK) != CIFS_NEG_OP) && @@ -283,16 +297,23 @@ smb2_wait_mtu_credits(struct TCP_Server_Info *server, size_t size, static int smb2_adjust_credits(struct TCP_Server_Info *server, - struct cifs_credits *credits, - const unsigned int payload_size) + struct cifs_io_subrequest *subreq, + unsigned int /*enum smb3_rw_credits_trace*/ trace) { - int new_val = DIV_ROUND_UP(payload_size, SMB2_MAX_BUFFER_SIZE); + struct cifs_credits *credits = &subreq->credits; + int new_val = DIV_ROUND_UP(subreq->subreq.len, SMB2_MAX_BUFFER_SIZE); int scredits, in_flight; if (!credits->value || credits->value == new_val) return 0; if (credits->value < new_val) { + trace_smb3_rw_credits(subreq->rreq->debug_id, + subreq->subreq.debug_index, + credits->value, + server->credits, server->in_flight, + new_val - credits->value, + cifs_trace_rw_credits_no_adjust_up); trace_smb3_too_many_credits(server->CurrentMid, server->conn_id, server->hostname, 0, credits->value - new_val, 0); cifs_server_dbg(VFS, "request has less credits (%d) than required (%d)", @@ -308,6 +329,12 @@ smb2_adjust_credits(struct TCP_Server_Info *server, in_flight = server->in_flight; spin_unlock(&server->req_lock); + trace_smb3_rw_credits(subreq->rreq->debug_id, + subreq->subreq.debug_index, + credits->value, + server->credits, server->in_flight, + new_val - credits->value, + cifs_trace_rw_credits_old_session); trace_smb3_reconnect_detected(server->CurrentMid, server->conn_id, server->hostname, scredits, credits->value - new_val, in_flight); @@ -316,6 +343,11 @@ smb2_adjust_credits(struct TCP_Server_Info *server, return -EAGAIN; } + trace_smb3_rw_credits(subreq->rreq->debug_id, + subreq->subreq.debug_index, + credits->value, + server->credits, server->in_flight, + new_val - credits->value, trace); server->credits += credits->value - new_val; scredits = server->credits; in_flight = server->in_flight; diff --git a/fs/smb/client/smb2pdu.c b/fs/smb/client/smb2pdu.c index bb84a89e5905..9fc5b11c0b6c 100644 --- a/fs/smb/client/smb2pdu.c +++ b/fs/smb/client/smb2pdu.c @@ -4502,8 +4502,15 @@ smb2_readv_callback(struct mid_q_entry *mid) struct TCP_Server_Info *server = rdata->server; struct smb2_hdr *shdr = (struct smb2_hdr *)rdata->iov[0].iov_base; - struct cifs_credits credits = { .value = 0, .instance = 0 }; + struct cifs_credits credits = { + .value = 0, + .instance = 0, + .rreq_debug_id = rdata->rreq->debug_id, + .rreq_debug_index = rdata->subreq.debug_index, + }; struct smb_rqst rqst = { .rq_iov = &rdata->iov[1], .rq_nvec = 1 }; + unsigned int rreq_debug_id = rdata->rreq->debug_id; + unsigned int subreq_debug_index = rdata->subreq.debug_index; if (rdata->got_bytes) { rqst.rq_iter = rdata->subreq.io_iter; @@ -4587,10 +4594,16 @@ smb2_readv_callback(struct mid_q_entry *mid) if (rdata->subreq.start < rdata->subreq.rreq->i_size) rdata->result = 0; } + trace_smb3_rw_credits(rreq_debug_id, subreq_debug_index, rdata->credits.value, + server->credits, server->in_flight, + 0, cifs_trace_rw_credits_read_response_clear); rdata->credits.value = 0; INIT_WORK(&rdata->subreq.work, smb2_readv_worker); queue_work(cifsiod_wq, &rdata->subreq.work); release_mid(mid); + trace_smb3_rw_credits(rreq_debug_id, subreq_debug_index, 0, + server->credits, server->in_flight, + credits.value, cifs_trace_rw_credits_read_response_add); add_credits(server, &credits, 0); } @@ -4647,7 +4660,7 @@ smb2_async_readv(struct cifs_io_subrequest *rdata) min_t(int, server->max_credits - server->credits, credit_request)); - rc = adjust_credits(server, &rdata->credits, rdata->subreq.len); + rc = adjust_credits(server, rdata, cifs_trace_rw_credits_call_readv_adjust); if (rc) goto async_readv_out; @@ -4766,7 +4779,14 @@ smb2_writev_callback(struct mid_q_entry *mid) struct cifs_tcon *tcon = tlink_tcon(wdata->req->cfile->tlink); struct TCP_Server_Info *server = wdata->server; struct smb2_write_rsp *rsp = (struct smb2_write_rsp *)mid->resp_buf; - struct cifs_credits credits = { .value = 0, .instance = 0 }; + struct cifs_credits credits = { + .value = 0, + .instance = 0, + .rreq_debug_id = wdata->rreq->debug_id, + .rreq_debug_index = wdata->subreq.debug_index, + }; + unsigned int rreq_debug_id = wdata->rreq->debug_id; + unsigned int subreq_debug_index = wdata->subreq.debug_index; ssize_t result = 0; size_t written; @@ -4837,9 +4857,15 @@ smb2_writev_callback(struct mid_q_entry *mid) tcon->tid, tcon->ses->Suid, wdata->subreq.start, wdata->subreq.len); + trace_smb3_rw_credits(rreq_debug_id, subreq_debug_index, wdata->credits.value, + server->credits, server->in_flight, + 0, cifs_trace_rw_credits_write_response_clear); wdata->credits.value = 0; cifs_write_subrequest_terminated(wdata, result ?: written, true); release_mid(mid); + trace_smb3_rw_credits(rreq_debug_id, subreq_debug_index, 0, + server->credits, server->in_flight, + credits.value, cifs_trace_rw_credits_write_response_add); add_credits(server, &credits, 0); } @@ -4969,7 +4995,7 @@ smb2_async_writev(struct cifs_io_subrequest *wdata) min_t(int, server->max_credits - server->credits, credit_request)); - rc = adjust_credits(server, &wdata->credits, io_parms->length); + rc = adjust_credits(server, wdata, cifs_trace_rw_credits_call_writev_adjust); if (rc) goto async_writev_out; @@ -4994,6 +5020,12 @@ smb2_async_writev(struct cifs_io_subrequest *wdata) cifs_small_buf_release(req); out: if (rc) { + trace_smb3_rw_credits(wdata->rreq->debug_id, + wdata->subreq.debug_index, + wdata->credits.value, + server->credits, server->in_flight, + -(int)wdata->credits.value, + cifs_trace_rw_credits_write_response_clear); add_credits_and_wake_if(wdata->server, &wdata->credits, 0); cifs_write_subrequest_terminated(wdata, rc, true); } diff --git a/fs/smb/client/trace.h b/fs/smb/client/trace.h index 36d47ce59631..36d5295c2a6f 100644 --- a/fs/smb/client/trace.h +++ b/fs/smb/client/trace.h @@ -20,6 +20,22 @@ /* * Specify enums for tracing information. */ +#define smb3_rw_credits_traces \ + EM(cifs_trace_rw_credits_call_readv_adjust, "rd-call-adj") \ + EM(cifs_trace_rw_credits_call_writev_adjust, "wr-call-adj") \ + EM(cifs_trace_rw_credits_free_subreq, "free-subreq") \ + EM(cifs_trace_rw_credits_issue_read_adjust, "rd-issu-adj") \ + EM(cifs_trace_rw_credits_issue_write_adjust, "wr-issu-adj") \ + EM(cifs_trace_rw_credits_no_adjust_up, "no-adj-up ") \ + EM(cifs_trace_rw_credits_old_session, "old-session") \ + EM(cifs_trace_rw_credits_read_response_add, "rd-resp-add") \ + EM(cifs_trace_rw_credits_read_response_clear, "rd-resp-clr") \ + EM(cifs_trace_rw_credits_read_submit, "rd-submit ") \ + EM(cifs_trace_rw_credits_write_prepare, "wr-prepare ") \ + EM(cifs_trace_rw_credits_write_response_add, "wr-resp-add") \ + EM(cifs_trace_rw_credits_write_response_clear, "wr-resp-clr") \ + E_(cifs_trace_rw_credits_zero_in_flight, "ZERO-IN-FLT") + #define smb3_tcon_ref_traces \ EM(netfs_trace_tcon_ref_dec_dfs_refer, "DEC DfsRef") \ EM(netfs_trace_tcon_ref_free, "FRE ") \ @@ -59,7 +75,8 @@ #define EM(a, b) a, #define E_(a, b) a -enum smb3_tcon_ref_trace { smb3_tcon_ref_traces } __mode(byte); +enum smb3_rw_credits_trace { smb3_rw_credits_traces } __mode(byte); +enum smb3_tcon_ref_trace { smb3_tcon_ref_traces } __mode(byte); #undef EM #undef E_ @@ -71,6 +88,7 @@ enum smb3_tcon_ref_trace { smb3_tcon_ref_traces } __mode(byte); #define EM(a, b) TRACE_DEFINE_ENUM(a); #define E_(a, b) TRACE_DEFINE_ENUM(a); +smb3_rw_credits_traces; smb3_tcon_ref_traces; #undef EM @@ -1316,6 +1334,41 @@ TRACE_EVENT(smb3_tcon_ref, __entry->ref) ); +TRACE_EVENT(smb3_rw_credits, + TP_PROTO(unsigned int rreq_debug_id, + unsigned int subreq_debug_index, + unsigned int subreq_credits, + unsigned int server_credits, + int server_in_flight, + int credit_change, + enum smb3_rw_credits_trace trace), + TP_ARGS(rreq_debug_id, subreq_debug_index, subreq_credits, + server_credits, server_in_flight, credit_change, trace), + TP_STRUCT__entry( + __field(unsigned int, rreq_debug_id) + __field(unsigned int, subreq_debug_index) + __field(unsigned int, subreq_credits) + __field(unsigned int, server_credits) + __field(int, in_flight) + __field(int, credit_change) + __field(enum smb3_rw_credits_trace, trace) + ), + TP_fast_assign( + __entry->rreq_debug_id = rreq_debug_id; + __entry->subreq_debug_index = subreq_debug_index; + __entry->subreq_credits = subreq_credits; + __entry->server_credits = server_credits; + __entry->in_flight = server_in_flight; + __entry->credit_change = credit_change; + __entry->trace = trace; + ), + TP_printk("R=%08x[%x] %s cred=%u chg=%d pool=%u ifl=%d", + __entry->rreq_debug_id, __entry->subreq_debug_index, + __print_symbolic(__entry->trace, smb3_rw_credits_traces), + __entry->subreq_credits, __entry->credit_change, + __entry->server_credits, __entry->in_flight) + ); + #undef EM #undef E_ diff --git a/fs/smb/client/transport.c b/fs/smb/client/transport.c index 012b9bd06995..adfe0d058701 100644 --- a/fs/smb/client/transport.c +++ b/fs/smb/client/transport.c @@ -988,10 +988,10 @@ static void cifs_compound_callback(struct mid_q_entry *mid) { struct TCP_Server_Info *server = mid->server; - struct cifs_credits credits; - - credits.value = server->ops->get_credits(mid); - credits.instance = server->reconnect_instance; + struct cifs_credits credits = { + .value = server->ops->get_credits(mid), + .instance = server->reconnect_instance, + }; add_credits(server, &credits, mid->optype); ^ permalink raw reply related [flat|nested] 9+ messages in thread
* Re: [PATCH 0/4] cifs: Miscellaneous fixes and a trace point 2024-07-19 14:09 [PATCH 0/4] cifs: Miscellaneous fixes and a trace point David Howells ` (3 preceding siblings ...) 2024-07-19 14:09 ` [PATCH 4/4] cifs: Add a tracepoint to track credits involved in R/W requests David Howells @ 2024-07-19 14:26 ` Steve French 2024-07-19 15:25 ` [PATCH 5/4] cifs: Fix missing fscache invalidation David Howells 5 siblings, 0 replies; 9+ messages in thread From: Steve French @ 2024-07-19 14:26 UTC (permalink / raw) To: David Howells Cc: Steve French, Paulo Alcantara, Shyam Prasad N, Rohith Surabattula, Jeff Layton, linux-cifs, linux-fsdevel applied to cifs-2.6.git for-next and running regression tests on it now On Fri, Jul 19, 2024 at 9:09 AM David Howells <dhowells@redhat.com> wrote: > > Hi Steve, > > Here are four patches for cifs: > > (1) Fix re-repick of a server upon subrequest retry. > > (2) Fix some error code setting that got accidentally removed. > > (3) Fix the handling of the zero_point after a DIO write. It always needs > to be bumped past the end of the DIO write. > > (4) Add a tracepoint and some debugging to keep track of when we've ended > the ->in_flight contribution from an operation. > > I've pushed the patches here also: > > https://git.kernel.org/pub/scm/linux/kernel/git/dhowells/linux-fs.git/log/?h=cifs-fixes > > David > > David Howells (4): > cifs: Fix server re-repick on subrequest retry > cifs: Fix missing error code set > cifs: Fix setting of zero_point after DIO write > cifs: Add a tracepoint to track credits involved in R/W requests > > fs/smb/client/cifsglob.h | 17 +++++++----- > fs/smb/client/file.c | 47 +++++++++++++++++++++++++++++---- > fs/smb/client/smb1ops.c | 2 +- > fs/smb/client/smb2ops.c | 42 ++++++++++++++++++++++++++---- > fs/smb/client/smb2pdu.c | 43 +++++++++++++++++++++++++----- > fs/smb/client/trace.h | 55 ++++++++++++++++++++++++++++++++++++++- > fs/smb/client/transport.c | 8 +++--- > 7 files changed, 184 insertions(+), 30 deletions(-) > > -- Thanks, Steve ^ permalink raw reply [flat|nested] 9+ messages in thread
* Re: [PATCH 5/4] cifs: Fix missing fscache invalidation 2024-07-19 14:09 [PATCH 0/4] cifs: Miscellaneous fixes and a trace point David Howells ` (4 preceding siblings ...) 2024-07-19 14:26 ` [PATCH 0/4] cifs: Miscellaneous fixes and a trace point Steve French @ 2024-07-19 15:25 ` David Howells 5 siblings, 0 replies; 9+ messages in thread From: David Howells @ 2024-07-19 15:25 UTC (permalink / raw) To: Steve French Cc: dhowells, Paulo Alcantara, Shyam Prasad N, Rohith Surabattula, Jeff Layton, linux-cifs, linux-fsdevel A network filesystem needs to implement a netfslib hook to invalidate fscache if it's to be able to use the cache. Fix cifs to implement the cache invalidation hook. Signed-off-by: David Howells <dhowells@redhat.com> cc: Steve French <sfrench@samba.org> cc: Paulo Alcantara <pc@manguebit.com> cc: Jeff Layton <jlayton@kernel.org> cc: linux-cifs@vger.kernel.org cc: netfs@lists.linux.dev cc: linux-fsdevel@vger.kernel.org Fixes: 3ee1a1fc3981 ("cifs: Cut over to using netfslib") --- fs/smb/client/file.c | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/fs/smb/client/file.c b/fs/smb/client/file.c index f8d6ad88335e..b2405dd4d4d4 100644 --- a/fs/smb/client/file.c +++ b/fs/smb/client/file.c @@ -133,6 +133,11 @@ static void cifs_issue_write(struct netfs_io_subrequest *subreq) goto out; } +static void cifs_netfs_invalidate_cache(struct netfs_io_request *wreq) +{ + cifs_invalidate_cache(wreq->inode, 0); +} + /* * Split the read up according to how many credits we can get for each piece. * It's okay to sleep here if we need to wait for more credit to become @@ -337,6 +342,7 @@ const struct netfs_request_ops cifs_req_ops = { .begin_writeback = cifs_begin_writeback, .prepare_write = cifs_prepare_write, .issue_write = cifs_issue_write, + .invalidate_cache = cifs_netfs_invalidate_cache, }; /* ^ permalink raw reply related [flat|nested] 9+ messages in thread
end of thread, other threads:[~2024-07-19 15:45 UTC | newest] Thread overview: 9+ messages (download: mbox.gz follow: Atom feed -- links below jump to the message on this page -- 2024-07-19 14:09 [PATCH 0/4] cifs: Miscellaneous fixes and a trace point David Howells 2024-07-19 14:09 ` [PATCH 1/4] cifs: Fix server re-repick on subrequest retry David Howells 2024-07-19 14:27 ` Tom Talpey 2024-07-19 15:45 ` Steve French 2024-07-19 14:09 ` [PATCH 2/4] cifs: Fix missing error code set David Howells 2024-07-19 14:09 ` [PATCH 3/4] cifs: Fix setting of zero_point after DIO write David Howells 2024-07-19 14:09 ` [PATCH 4/4] cifs: Add a tracepoint to track credits involved in R/W requests David Howells 2024-07-19 14:26 ` [PATCH 0/4] cifs: Miscellaneous fixes and a trace point Steve French 2024-07-19 15:25 ` [PATCH 5/4] cifs: Fix missing fscache invalidation David Howells
This is a public inbox, see mirroring instructions for how to clone and mirror all data and code used for this inbox; as well as URLs for NNTP newsgroup(s).