Merge tag '6.11-rc-part1-smb3-client-fixes' of git://git.samba.org/sfrench/cifs-2.6

Pull smb client fixes from Steve French:
"Six smb3 client fixes, most for stable including important netfs fixes:

- various netfs related fixes for cifs addressing some regressions in
6.10 (e.g. generic/708 and some multichannel crediting related
issues)

- fix for a noisy log message on copy_file_range

- add trace point for read/write credits"

* tag '6.11-rc-part1-smb3-client-fixes' of git://git.samba.org/sfrench/cifs-2.6:
cifs: Fix missing fscache invalidation
cifs: Add a tracepoint to track credits involved in R/W requests
cifs: Fix setting of zero_point after DIO write
cifs: Fix missing error code set
cifs: Fix server re-repick on subrequest retry
cifs: fix noisy message on copy_file_range

+191 -31
+1 -1
fs/smb/client/cifsfs.c
··· 1359 1359 target_tcon = tlink_tcon(smb_file_target->tlink); 1360 1360 1361 1361 if (src_tcon->ses != target_tcon->ses) { 1362 - cifs_dbg(VFS, "source and target of copy not on same server\n"); 1362 + cifs_dbg(FYI, "source and target of copy not on same server\n"); 1363 1363 goto out; 1364 1364 } 1365 1365
+10 -7
fs/smb/client/cifsglob.h
··· 290 290 int (*check_receive)(struct mid_q_entry *, struct TCP_Server_Info *, 291 291 bool); 292 292 void (*add_credits)(struct TCP_Server_Info *server, 293 - const struct cifs_credits *credits, 293 + struct cifs_credits *credits, 294 294 const int optype); 295 295 void (*set_credits)(struct TCP_Server_Info *, const int); 296 296 int * (*get_credits_field)(struct TCP_Server_Info *, const int); ··· 550 550 size_t *, struct cifs_credits *); 551 551 /* adjust previously taken mtu credits to request size */ 552 552 int (*adjust_credits)(struct TCP_Server_Info *server, 553 - struct cifs_credits *credits, 554 - const unsigned int payload_size); 553 + struct cifs_io_subrequest *subreq, 554 + unsigned int /*enum smb3_rw_credits_trace*/ trace); 555 555 /* check if we need to issue closedir */ 556 556 bool (*dir_needs_close)(struct cifsFileInfo *); 557 557 long (*fallocate)(struct file *, struct cifs_tcon *, int, loff_t, ··· 848 848 struct cifs_credits { 849 849 unsigned int value; 850 850 unsigned int instance; 851 + unsigned int in_flight_check; 852 + unsigned int rreq_debug_id; 853 + unsigned int rreq_debug_index; 851 854 }; 852 855 853 856 static inline unsigned int ··· 876 873 } 877 874 878 875 static inline void 879 - add_credits(struct TCP_Server_Info *server, const struct cifs_credits *credits, 876 + add_credits(struct TCP_Server_Info *server, struct cifs_credits *credits, 880 877 const int optype) 881 878 { 882 879 server->ops->add_credits(server, credits, optype); ··· 900 897 } 901 898 902 899 static inline int 903 - adjust_credits(struct TCP_Server_Info *server, struct cifs_credits *credits, 904 - const unsigned int payload_size) 900 + adjust_credits(struct TCP_Server_Info *server, struct cifs_io_subrequest *subreq, 901 + unsigned int /* enum smb3_rw_credits_trace */ trace) 905 902 { 906 903 return server->ops->adjust_credits ? 907 - server->ops->adjust_credits(server, credits, payload_size) : 0; 904 + server->ops->adjust_credits(server, subreq, trace) : 0; 908 905 } 909 906 910 907 static inline __le64
+48 -5
fs/smb/client/file.c
··· 80 80 return netfs_prepare_write_failed(subreq); 81 81 } 82 82 83 + wdata->credits.rreq_debug_id = subreq->rreq->debug_id; 84 + wdata->credits.rreq_debug_index = subreq->debug_index; 85 + wdata->credits.in_flight_check = 1; 86 + trace_smb3_rw_credits(wdata->rreq->debug_id, 87 + wdata->subreq.debug_index, 88 + wdata->credits.value, 89 + server->credits, server->in_flight, 90 + wdata->credits.value, 91 + cifs_trace_rw_credits_write_prepare); 92 + 83 93 #ifdef CONFIG_CIFS_SMB_DIRECT 84 94 if (server->smbd_conn) 85 95 subreq->max_nr_segs = server->smbd_conn->max_frmr_depth; ··· 111 101 goto fail; 112 102 } 113 103 114 - rc = adjust_credits(wdata->server, &wdata->credits, wdata->subreq.len); 104 + rc = adjust_credits(wdata->server, wdata, cifs_trace_rw_credits_issue_write_adjust); 115 105 if (rc) 116 106 goto fail; 117 107 ··· 131 121 add_credits_and_wake_if(wdata->server, &wdata->credits, 0); 132 122 cifs_write_subrequest_terminated(wdata, rc, false); 133 123 goto out; 124 + } 125 + 126 + static void cifs_netfs_invalidate_cache(struct netfs_io_request *wreq) 127 + { 128 + cifs_invalidate_cache(wreq->inode, 0); 134 129 } 135 130 136 131 /* ··· 173 158 return false; 174 159 } 175 160 161 + rdata->credits.in_flight_check = 1; 162 + rdata->credits.rreq_debug_id = rreq->debug_id; 163 + rdata->credits.rreq_debug_index = subreq->debug_index; 164 + 165 + trace_smb3_rw_credits(rdata->rreq->debug_id, 166 + rdata->subreq.debug_index, 167 + rdata->credits.value, 168 + server->credits, server->in_flight, 0, 169 + cifs_trace_rw_credits_read_submit); 170 + 176 171 subreq->len = min_t(size_t, subreq->len, rsize); 172 + 177 173 #ifdef CONFIG_CIFS_SMB_DIRECT 178 174 if (server->smbd_conn) 179 175 subreq->max_nr_segs = server->smbd_conn->max_frmr_depth; ··· 315 289 #endif 316 290 } 317 291 292 + if (rdata->credits.value != 0) 293 + trace_smb3_rw_credits(rdata->rreq->debug_id, 294 + rdata->subreq.debug_index, 295 + rdata->credits.value, 296 + rdata->server ? rdata->server->credits : 0, 297 + rdata->server ? rdata->server->in_flight : 0, 298 + -rdata->credits.value, 299 + cifs_trace_rw_credits_free_subreq); 300 + 318 301 add_credits_and_wake_if(rdata->server, &rdata->credits, 0); 319 302 if (rdata->have_xid) 320 303 free_xid(rdata->xid); ··· 342 307 .begin_writeback = cifs_begin_writeback, 343 308 .prepare_write = cifs_prepare_write, 344 309 .issue_write = cifs_issue_write, 310 + .invalidate_cache = cifs_netfs_invalidate_cache, 345 311 }; 346 312 347 313 /* ··· 2394 2358 bool was_async) 2395 2359 { 2396 2360 struct netfs_io_request *wreq = wdata->rreq; 2397 - loff_t new_server_eof; 2361 + struct netfs_inode *ictx = netfs_inode(wreq->inode); 2362 + loff_t wrend; 2398 2363 2399 2364 if (result > 0) { 2400 - new_server_eof = wdata->subreq.start + wdata->subreq.transferred + result; 2365 + wrend = wdata->subreq.start + wdata->subreq.transferred + result; 2401 2366 2402 - if (new_server_eof > netfs_inode(wreq->inode)->remote_i_size) 2403 - netfs_resize_file(netfs_inode(wreq->inode), new_server_eof, true); 2367 + if (wrend > ictx->zero_point && 2368 + (wdata->rreq->origin == NETFS_UNBUFFERED_WRITE || 2369 + wdata->rreq->origin == NETFS_DIO_WRITE)) 2370 + ictx->zero_point = wrend; 2371 + if (wrend > ictx->remote_i_size) 2372 + netfs_resize_file(ictx, wrend, true); 2404 2373 } 2405 2374 2406 2375 netfs_write_subrequest_terminated(&wdata->subreq, result, was_async); ··· 2918 2877 rc = netfs_start_io_direct(inode); 2919 2878 if (rc < 0) 2920 2879 goto out; 2880 + rc = -EACCES; 2921 2881 down_read(&cinode->lock_sem); 2922 2882 if (!cifs_find_lock_conflict( 2923 2883 cfile, iocb->ki_pos, iov_iter_count(to), ··· 2931 2889 rc = netfs_start_io_read(inode); 2932 2890 if (rc < 0) 2933 2891 goto out; 2892 + rc = -EACCES; 2934 2893 down_read(&cinode->lock_sem); 2935 2894 if (!cifs_find_lock_conflict( 2936 2895 cfile, iocb->ki_pos, iov_iter_count(to),
+1 -1
fs/smb/client/smb1ops.c
··· 108 108 109 109 static void 110 110 cifs_add_credits(struct TCP_Server_Info *server, 111 - const struct cifs_credits *credits, const int optype) 111 + struct cifs_credits *credits, const int optype) 112 112 { 113 113 spin_lock(&server->req_lock); 114 114 server->credits += credits->value;
+37 -5
fs/smb/client/smb2ops.c
··· 66 66 67 67 static void 68 68 smb2_add_credits(struct TCP_Server_Info *server, 69 - const struct cifs_credits *credits, const int optype) 69 + struct cifs_credits *credits, const int optype) 70 70 { 71 71 int *val, rc = -1; 72 72 int scredits, in_flight; ··· 94 94 server->conn_id, server->hostname, *val, 95 95 add, server->in_flight); 96 96 } 97 - WARN_ON_ONCE(server->in_flight == 0); 97 + if (credits->in_flight_check > 1) { 98 + pr_warn_once("rreq R=%08x[%x] Credits not in flight\n", 99 + credits->rreq_debug_id, credits->rreq_debug_index); 100 + } else { 101 + credits->in_flight_check = 2; 102 + } 103 + if (WARN_ON_ONCE(server->in_flight == 0)) { 104 + pr_warn_once("rreq R=%08x[%x] Zero in_flight\n", 105 + credits->rreq_debug_id, credits->rreq_debug_index); 106 + trace_smb3_rw_credits(credits->rreq_debug_id, 107 + credits->rreq_debug_index, 108 + credits->value, 109 + server->credits, server->in_flight, 0, 110 + cifs_trace_rw_credits_zero_in_flight); 111 + } 98 112 server->in_flight--; 99 113 if (server->in_flight == 0 && 100 114 ((optype & CIFS_OP_MASK) != CIFS_NEG_OP) && ··· 297 283 298 284 static int 299 285 smb2_adjust_credits(struct TCP_Server_Info *server, 300 - struct cifs_credits *credits, 301 - const unsigned int payload_size) 286 + struct cifs_io_subrequest *subreq, 287 + unsigned int /*enum smb3_rw_credits_trace*/ trace) 302 288 { 303 - int new_val = DIV_ROUND_UP(payload_size, SMB2_MAX_BUFFER_SIZE); 289 + struct cifs_credits *credits = &subreq->credits; 290 + int new_val = DIV_ROUND_UP(subreq->subreq.len, SMB2_MAX_BUFFER_SIZE); 304 291 int scredits, in_flight; 305 292 306 293 if (!credits->value || credits->value == new_val) 307 294 return 0; 308 295 309 296 if (credits->value < new_val) { 297 + trace_smb3_rw_credits(subreq->rreq->debug_id, 298 + subreq->subreq.debug_index, 299 + credits->value, 300 + server->credits, server->in_flight, 301 + new_val - credits->value, 302 + cifs_trace_rw_credits_no_adjust_up); 310 303 trace_smb3_too_many_credits(server->CurrentMid, 311 304 server->conn_id, server->hostname, 0, credits->value - new_val, 0); 312 305 cifs_server_dbg(VFS, "request has less credits (%d) than required (%d)", ··· 329 308 in_flight = server->in_flight; 330 309 spin_unlock(&server->req_lock); 331 310 311 + trace_smb3_rw_credits(subreq->rreq->debug_id, 312 + subreq->subreq.debug_index, 313 + credits->value, 314 + server->credits, server->in_flight, 315 + new_val - credits->value, 316 + cifs_trace_rw_credits_old_session); 332 317 trace_smb3_reconnect_detected(server->CurrentMid, 333 318 server->conn_id, server->hostname, scredits, 334 319 credits->value - new_val, in_flight); ··· 343 316 return -EAGAIN; 344 317 } 345 318 319 + trace_smb3_rw_credits(subreq->rreq->debug_id, 320 + subreq->subreq.debug_index, 321 + credits->value, 322 + server->credits, server->in_flight, 323 + new_val - credits->value, trace); 346 324 server->credits += credits->value - new_val; 347 325 scredits = server->credits; 348 326 in_flight = server->in_flight;
+36 -7
fs/smb/client/smb2pdu.c
··· 4502 4502 struct TCP_Server_Info *server = rdata->server; 4503 4503 struct smb2_hdr *shdr = 4504 4504 (struct smb2_hdr *)rdata->iov[0].iov_base; 4505 - struct cifs_credits credits = { .value = 0, .instance = 0 }; 4505 + struct cifs_credits credits = { 4506 + .value = 0, 4507 + .instance = 0, 4508 + .rreq_debug_id = rdata->rreq->debug_id, 4509 + .rreq_debug_index = rdata->subreq.debug_index, 4510 + }; 4506 4511 struct smb_rqst rqst = { .rq_iov = &rdata->iov[1], .rq_nvec = 1 }; 4512 + unsigned int rreq_debug_id = rdata->rreq->debug_id; 4513 + unsigned int subreq_debug_index = rdata->subreq.debug_index; 4507 4514 4508 4515 if (rdata->got_bytes) { 4509 4516 rqst.rq_iter = rdata->subreq.io_iter; ··· 4594 4587 if (rdata->subreq.start < rdata->subreq.rreq->i_size) 4595 4588 rdata->result = 0; 4596 4589 } 4590 + trace_smb3_rw_credits(rreq_debug_id, subreq_debug_index, rdata->credits.value, 4591 + server->credits, server->in_flight, 4592 + 0, cifs_trace_rw_credits_read_response_clear); 4597 4593 rdata->credits.value = 0; 4598 4594 INIT_WORK(&rdata->subreq.work, smb2_readv_worker); 4599 4595 queue_work(cifsiod_wq, &rdata->subreq.work); 4600 4596 release_mid(mid); 4597 + trace_smb3_rw_credits(rreq_debug_id, subreq_debug_index, 0, 4598 + server->credits, server->in_flight, 4599 + credits.value, cifs_trace_rw_credits_read_response_add); 4601 4600 add_credits(server, &credits, 0); 4602 4601 } 4603 4602 ··· 4660 4647 min_t(int, server->max_credits - 4661 4648 server->credits, credit_request)); 4662 4649 4663 - rc = adjust_credits(server, &rdata->credits, rdata->subreq.len); 4650 + rc = adjust_credits(server, rdata, cifs_trace_rw_credits_call_readv_adjust); 4664 4651 if (rc) 4665 4652 goto async_readv_out; 4666 4653 ··· 4779 4766 struct cifs_tcon *tcon = tlink_tcon(wdata->req->cfile->tlink); 4780 4767 struct TCP_Server_Info *server = wdata->server; 4781 4768 struct smb2_write_rsp *rsp = (struct smb2_write_rsp *)mid->resp_buf; 4782 - struct cifs_credits credits = { .value = 0, .instance = 0 }; 4769 + struct cifs_credits credits = { 4770 + .value = 0, 4771 + .instance = 0, 4772 + .rreq_debug_id = wdata->rreq->debug_id, 4773 + .rreq_debug_index = wdata->subreq.debug_index, 4774 + }; 4775 + unsigned int rreq_debug_id = wdata->rreq->debug_id; 4776 + unsigned int subreq_debug_index = wdata->subreq.debug_index; 4783 4777 ssize_t result = 0; 4784 4778 size_t written; 4785 4779 ··· 4857 4837 tcon->tid, tcon->ses->Suid, 4858 4838 wdata->subreq.start, wdata->subreq.len); 4859 4839 4840 + trace_smb3_rw_credits(rreq_debug_id, subreq_debug_index, wdata->credits.value, 4841 + server->credits, server->in_flight, 4842 + 0, cifs_trace_rw_credits_write_response_clear); 4860 4843 wdata->credits.value = 0; 4861 4844 cifs_write_subrequest_terminated(wdata, result ?: written, true); 4862 4845 release_mid(mid); 4846 + trace_smb3_rw_credits(rreq_debug_id, subreq_debug_index, 0, 4847 + server->credits, server->in_flight, 4848 + credits.value, cifs_trace_rw_credits_write_response_add); 4863 4849 add_credits(server, &credits, 0); 4864 4850 } 4865 4851 ··· 4884 4858 struct cifs_io_parms _io_parms; 4885 4859 struct cifs_io_parms *io_parms = NULL; 4886 4860 int credit_request; 4887 - 4888 - if (!wdata->server || test_bit(NETFS_SREQ_RETRYING, &wdata->subreq.flags)) 4889 - server = wdata->server = cifs_pick_channel(tcon->ses); 4890 4861 4891 4862 /* 4892 4863 * in future we may get cifs_io_parms passed in from the caller, ··· 4995 4972 min_t(int, server->max_credits - 4996 4973 server->credits, credit_request)); 4997 4974 4998 - rc = adjust_credits(server, &wdata->credits, io_parms->length); 4975 + rc = adjust_credits(server, wdata, cifs_trace_rw_credits_call_writev_adjust); 4999 4976 if (rc) 5000 4977 goto async_writev_out; 5001 4978 ··· 5020 4997 cifs_small_buf_release(req); 5021 4998 out: 5022 4999 if (rc) { 5000 + trace_smb3_rw_credits(wdata->rreq->debug_id, 5001 + wdata->subreq.debug_index, 5002 + wdata->credits.value, 5003 + server->credits, server->in_flight, 5004 + -(int)wdata->credits.value, 5005 + cifs_trace_rw_credits_write_response_clear); 5023 5006 add_credits_and_wake_if(wdata->server, &wdata->credits, 0); 5024 5007 cifs_write_subrequest_terminated(wdata, rc, true); 5025 5008 }
+54 -1
fs/smb/client/trace.h
··· 20 20 /* 21 21 * Specify enums for tracing information. 22 22 */ 23 + #define smb3_rw_credits_traces \ 24 + EM(cifs_trace_rw_credits_call_readv_adjust, "rd-call-adj") \ 25 + EM(cifs_trace_rw_credits_call_writev_adjust, "wr-call-adj") \ 26 + EM(cifs_trace_rw_credits_free_subreq, "free-subreq") \ 27 + EM(cifs_trace_rw_credits_issue_read_adjust, "rd-issu-adj") \ 28 + EM(cifs_trace_rw_credits_issue_write_adjust, "wr-issu-adj") \ 29 + EM(cifs_trace_rw_credits_no_adjust_up, "no-adj-up ") \ 30 + EM(cifs_trace_rw_credits_old_session, "old-session") \ 31 + EM(cifs_trace_rw_credits_read_response_add, "rd-resp-add") \ 32 + EM(cifs_trace_rw_credits_read_response_clear, "rd-resp-clr") \ 33 + EM(cifs_trace_rw_credits_read_submit, "rd-submit ") \ 34 + EM(cifs_trace_rw_credits_write_prepare, "wr-prepare ") \ 35 + EM(cifs_trace_rw_credits_write_response_add, "wr-resp-add") \ 36 + EM(cifs_trace_rw_credits_write_response_clear, "wr-resp-clr") \ 37 + E_(cifs_trace_rw_credits_zero_in_flight, "ZERO-IN-FLT") 38 + 23 39 #define smb3_tcon_ref_traces \ 24 40 EM(netfs_trace_tcon_ref_dec_dfs_refer, "DEC DfsRef") \ 25 41 EM(netfs_trace_tcon_ref_free, "FRE ") \ ··· 75 59 #define EM(a, b) a, 76 60 #define E_(a, b) a 77 61 78 - enum smb3_tcon_ref_trace { smb3_tcon_ref_traces } __mode(byte); 62 + enum smb3_rw_credits_trace { smb3_rw_credits_traces } __mode(byte); 63 + enum smb3_tcon_ref_trace { smb3_tcon_ref_traces } __mode(byte); 79 64 80 65 #undef EM 81 66 #undef E_ ··· 88 71 #define EM(a, b) TRACE_DEFINE_ENUM(a); 89 72 #define E_(a, b) TRACE_DEFINE_ENUM(a); 90 73 74 + smb3_rw_credits_traces; 91 75 smb3_tcon_ref_traces; 92 76 93 77 #undef EM ··· 1332 1314 __entry->tcon, 1333 1315 __print_symbolic(__entry->trace, smb3_tcon_ref_traces), 1334 1316 __entry->ref) 1317 + ); 1318 + 1319 + TRACE_EVENT(smb3_rw_credits, 1320 + TP_PROTO(unsigned int rreq_debug_id, 1321 + unsigned int subreq_debug_index, 1322 + unsigned int subreq_credits, 1323 + unsigned int server_credits, 1324 + int server_in_flight, 1325 + int credit_change, 1326 + enum smb3_rw_credits_trace trace), 1327 + TP_ARGS(rreq_debug_id, subreq_debug_index, subreq_credits, 1328 + server_credits, server_in_flight, credit_change, trace), 1329 + TP_STRUCT__entry( 1330 + __field(unsigned int, rreq_debug_id) 1331 + __field(unsigned int, subreq_debug_index) 1332 + __field(unsigned int, subreq_credits) 1333 + __field(unsigned int, server_credits) 1334 + __field(int, in_flight) 1335 + __field(int, credit_change) 1336 + __field(enum smb3_rw_credits_trace, trace) 1337 + ), 1338 + TP_fast_assign( 1339 + __entry->rreq_debug_id = rreq_debug_id; 1340 + __entry->subreq_debug_index = subreq_debug_index; 1341 + __entry->subreq_credits = subreq_credits; 1342 + __entry->server_credits = server_credits; 1343 + __entry->in_flight = server_in_flight; 1344 + __entry->credit_change = credit_change; 1345 + __entry->trace = trace; 1346 + ), 1347 + TP_printk("R=%08x[%x] %s cred=%u chg=%d pool=%u ifl=%d", 1348 + __entry->rreq_debug_id, __entry->subreq_debug_index, 1349 + __print_symbolic(__entry->trace, smb3_rw_credits_traces), 1350 + __entry->subreq_credits, __entry->credit_change, 1351 + __entry->server_credits, __entry->in_flight) 1335 1352 ); 1336 1353 1337 1354
+4 -4
fs/smb/client/transport.c
··· 988 988 cifs_compound_callback(struct mid_q_entry *mid) 989 989 { 990 990 struct TCP_Server_Info *server = mid->server; 991 - struct cifs_credits credits; 992 - 993 - credits.value = server->ops->get_credits(mid); 994 - credits.instance = server->reconnect_instance; 991 + struct cifs_credits credits = { 992 + .value = server->ops->get_credits(mid), 993 + .instance = server->reconnect_instance, 994 + }; 995 995 996 996 add_credits(server, &credits, mid->optype); 997 997