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

Pull smb client fixes from Steve French:

- ctime caching fix (for setxattr)

- encryption fix

- DNS resolver mount fix

- debugging improvements

- multichannel fixes including cases where server stops or starts
supporting multichannel after mount

- reconnect fix

- minor cleanups

* tag '6.7-rc-smb3-client-fixes-part2' of git://git.samba.org/sfrench/cifs-2.6:
cifs: update internal module version number for cifs.ko
cifs: handle when server stops supporting multichannel
cifs: handle when server starts supporting multichannel
Missing field not being returned in ioctl CIFS_IOC_GET_MNT_INFO
smb3: allow dumping session and tcon id to improve stats analysis and debugging
smb: client: fix mount when dns_resolver key is not available
smb3: fix caching of ctime on setxattr
smb3: minor cleanup of session handling code
cifs: reconnect work should have reference on server struct
cifs: do not pass cifs_sb when trying to add channels
cifs: account for primary channel in the interface list
cifs: distribute channels across interfaces based on speed
cifs: handle cases where a channel is closed
smb3: more minor cleanups for session handling routines
smb3: minor RDMA cleanup
cifs: Fix encryption of cleared, but unset rq_iter data buffers

+23 -2
fs/smb/client/cifs_debug.c
··· 136 136 { 137 137 struct TCP_Server_Info *server = chan->server; 138 138 139 + if (!server) { 140 + seq_printf(m, "\n\n\t\tChannel: %d DISABLED", i+1); 141 + return; 142 + } 143 + 139 144 seq_printf(m, "\n\n\t\tChannel: %d ConnectionId: 0x%llx" 140 145 "\n\t\tNumber of credits: %d,%d,%d Dialect 0x%x" 141 146 "\n\t\tTCP status: %d Instance: %d" ··· 284 279 struct cifs_ses *ses; 285 280 struct cifs_tcon *tcon; 286 281 struct cifs_server_iface *iface; 282 + size_t iface_weight = 0, iface_min_speed = 0; 283 + struct cifs_server_iface *last_iface = NULL; 287 284 int c, i, j; 288 285 289 286 seq_puts(m, ··· 551 544 "\tLast updated: %lu seconds ago", 552 545 ses->iface_count, 553 546 (jiffies - ses->iface_last_update) / HZ); 547 + 548 + last_iface = list_last_entry(&ses->iface_list, 549 + struct cifs_server_iface, 550 + iface_head); 551 + iface_min_speed = last_iface->speed; 552 + 554 553 j = 0; 555 554 list_for_each_entry(iface, &ses->iface_list, 556 555 iface_head) { 557 556 seq_printf(m, "\n\t%d)", ++j); 558 557 cifs_dump_iface(m, iface); 558 + 559 + iface_weight = iface->speed / iface_min_speed; 560 + seq_printf(m, "\t\tWeight (cur,total): (%zu,%zu)" 561 + "\n\t\tAllocated channels: %u\n", 562 + iface->weight_fulfilled, 563 + iface_weight, 564 + iface->num_channels); 565 + 559 566 if (is_ses_using_iface(ses, iface)) 560 567 seq_puts(m, "\t\t[CONNECTED]\n"); 561 568 } ··· 767 746 size_t count, loff_t *ppos) \ 768 747 { \ 769 748 int rc; \ 770 - rc = kstrtoint_from_user(buffer, count, 10, & name); \ 749 + rc = kstrtoint_from_user(buffer, count, 10, &name); \ 771 750 if (rc) \ 772 751 return rc; \ 773 752 return count; \ 774 753 } \ 775 754 static int name##_proc_show(struct seq_file *m, void *v) \ 776 755 { \ 777 - seq_printf(m, "%d\n", name ); \ 756 + seq_printf(m, "%d\n", name); \ 778 757 return 0; \ 779 758 } \ 780 759 static int name##_open(struct inode *inode, struct file *file) \
+6
fs/smb/client/cifs_ioctl.h
··· 26 26 __u64 cifs_posix_caps; 27 27 } __packed; 28 28 29 + struct smb_mnt_tcon_info { 30 + __u32 tid; 31 + __u64 session_id; 32 + } __packed; 33 + 29 34 struct smb_snapshot_array { 30 35 __u32 number_of_snapshots; 31 36 __u32 number_of_snapshots_returned; ··· 113 108 #define CIFS_IOC_NOTIFY _IOW(CIFS_IOCTL_MAGIC, 9, struct smb3_notify) 114 109 #define CIFS_DUMP_FULL_KEY _IOWR(CIFS_IOCTL_MAGIC, 10, struct smb3_full_key_debug_info) 115 110 #define CIFS_IOC_NOTIFY_INFO _IOWR(CIFS_IOCTL_MAGIC, 11, struct smb3_notify_info) 111 + #define CIFS_IOC_GET_TCON_INFO _IOR(CIFS_IOCTL_MAGIC, 12, struct smb_mnt_tcon_info) 116 112 #define CIFS_IOC_SHUTDOWN _IOR('X', 125, __u32) 117 113 118 114 /*
+2 -2
fs/smb/client/cifsfs.h
··· 152 152 #endif /* CONFIG_CIFS_NFSD_EXPORT */ 153 153 154 154 /* when changing internal version - update following two lines at same time */ 155 - #define SMB3_PRODUCT_BUILD 45 156 - #define CIFS_VERSION "2.45" 155 + #define SMB3_PRODUCT_BUILD 46 156 + #define CIFS_VERSION "2.46" 157 157 #endif /* _CIFSFS_H */
+13 -3
fs/smb/client/cifsglob.h
··· 650 650 bool noautotune; /* do not autotune send buf sizes */ 651 651 bool nosharesock; 652 652 bool tcp_nodelay; 653 + bool terminate; 653 654 unsigned int credits; /* send no more requests at once */ 654 655 unsigned int max_credits; /* can override large 32000 default at mnt */ 655 656 unsigned int in_flight; /* number of requests on the wire to server */ ··· 970 969 struct list_head iface_head; 971 970 struct kref refcount; 972 971 size_t speed; 972 + size_t weight_fulfilled; 973 + unsigned int num_channels; 973 974 unsigned int rdma_capable : 1; 974 975 unsigned int rss_capable : 1; 975 976 unsigned int is_active : 1; /* unset if non existent */ ··· 1053 1050 spinlock_t chan_lock; 1054 1051 /* ========= begin: protected by chan_lock ======== */ 1055 1052 #define CIFS_MAX_CHANNELS 16 1053 + #define CIFS_INVAL_CHAN_INDEX (-1) 1056 1054 #define CIFS_ALL_CHANNELS_SET(ses) \ 1057 1055 ((1UL << (ses)->chan_count) - 1) 1058 1056 #define CIFS_ALL_CHANS_GOOD(ses) \ ··· 2147 2143 unsigned int len, skip; 2148 2144 unsigned int nents = 0; 2149 2145 unsigned long addr; 2146 + size_t data_size; 2150 2147 int i, j; 2151 2148 2152 2149 /* ··· 2163 2158 * rqst[1+].rq_iov[0+] data to be encrypted/decrypted 2164 2159 */ 2165 2160 for (i = 0; i < num_rqst; i++) { 2161 + data_size = iov_iter_count(&rqst[i].rq_iter); 2162 + 2166 2163 /* We really don't want a mixture of pinned and unpinned pages 2167 2164 * in the sglist. It's hard to keep track of which is what. 2168 2165 * Instead, we convert to a BVEC-type iterator higher up. 2169 2166 */ 2170 - if (WARN_ON_ONCE(user_backed_iter(&rqst[i].rq_iter))) 2167 + if (data_size && 2168 + WARN_ON_ONCE(user_backed_iter(&rqst[i].rq_iter))) 2171 2169 return -EIO; 2172 2170 2173 2171 /* We also don't want to have any extra refs or pins to clean 2174 2172 * up in the sglist. 2175 2173 */ 2176 - if (WARN_ON_ONCE(iov_iter_extract_will_pin(&rqst[i].rq_iter))) 2174 + if (data_size && 2175 + WARN_ON_ONCE(iov_iter_extract_will_pin(&rqst[i].rq_iter))) 2177 2176 return -EIO; 2178 2177 2179 2178 for (j = 0; j < rqst[i].rq_nvec; j++) { ··· 2193 2184 } 2194 2185 skip = 0; 2195 2186 } 2196 - nents += iov_iter_npages(&rqst[i].rq_iter, INT_MAX); 2187 + if (data_size) 2188 + nents += iov_iter_npages(&rqst[i].rq_iter, INT_MAX); 2197 2189 } 2198 2190 nents += DIV_ROUND_UP(offset_in_page(sig) + SMB2_SIGNATURE_SIZE, PAGE_SIZE); 2199 2191 return nents;
+5 -2
fs/smb/client/cifsproto.h
··· 132 132 struct smb_hdr *in_buf, 133 133 struct smb_hdr *out_buf, 134 134 int *bytes_returned); 135 + 135 136 void 136 137 cifs_signal_cifsd_for_reconnect(struct TCP_Server_Info *server, 137 138 bool all_channels); ··· 611 610 612 611 struct cifs_chan * 613 612 cifs_ses_find_chan(struct cifs_ses *ses, struct TCP_Server_Info *server); 614 - int cifs_try_adding_channels(struct cifs_sb_info *cifs_sb, struct cifs_ses *ses); 613 + int cifs_try_adding_channels(struct cifs_ses *ses); 615 614 bool is_server_using_iface(struct TCP_Server_Info *server, 616 615 struct cifs_server_iface *iface); 617 616 bool is_ses_using_iface(struct cifs_ses *ses, struct cifs_server_iface *iface); 618 617 void cifs_ses_mark_for_reconnect(struct cifs_ses *ses); 619 618 620 - unsigned int 619 + int 621 620 cifs_ses_get_chan_index(struct cifs_ses *ses, 622 621 struct TCP_Server_Info *server); 623 622 void ··· 641 640 bool 642 641 cifs_chan_is_iface_active(struct cifs_ses *ses, 643 642 struct TCP_Server_Info *server); 643 + void 644 + cifs_disable_secondary_channels(struct cifs_ses *ses); 644 645 int 645 646 cifs_chan_update_iface(struct cifs_ses *ses, struct TCP_Server_Info *server); 646 647 int
+40 -8
fs/smb/client/connect.c
··· 132 132 free_xid(xid); 133 133 134 134 if (rc) { 135 + if (rc == -EOPNOTSUPP) 136 + return; 137 + 135 138 cifs_dbg(FYI, "%s: failed to query server interfaces: %d\n", 136 139 __func__, rc); 137 140 } ··· 176 173 list_for_each_entry(ses, &pserver->smb_ses_list, smb_ses_list) { 177 174 spin_lock(&ses->chan_lock); 178 175 for (i = 0; i < ses->chan_count; i++) { 176 + if (!ses->chans[i].server) 177 + continue; 178 + 179 179 spin_lock(&ses->chans[i].server->srv_lock); 180 - ses->chans[i].server->tcpStatus = CifsNeedReconnect; 180 + if (ses->chans[i].server->tcpStatus != CifsExiting) 181 + ses->chans[i].server->tcpStatus = CifsNeedReconnect; 181 182 spin_unlock(&ses->chans[i].server->srv_lock); 182 183 } 183 184 spin_unlock(&ses->chan_lock); ··· 219 212 220 213 spin_lock(&cifs_tcp_ses_lock); 221 214 list_for_each_entry_safe(ses, nses, &pserver->smb_ses_list, smb_ses_list) { 215 + /* 216 + * if channel has been marked for termination, nothing to do 217 + * for the channel. in fact, we cannot find the channel for the 218 + * server. So safe to exit here 219 + */ 220 + if (server->terminate) 221 + break; 222 + 222 223 /* check if iface is still active */ 223 224 if (!cifs_chan_is_iface_active(ses, server)) 224 225 cifs_chan_update_iface(ses, server); ··· 261 246 spin_lock(&tcon->tc_lock); 262 247 tcon->status = TID_NEED_RECON; 263 248 spin_unlock(&tcon->tc_lock); 249 + 250 + cancel_delayed_work(&tcon->query_interfaces); 264 251 } 265 252 if (ses->tcon_ipc) { 266 253 ses->tcon_ipc->need_reconnect = true; ··· 402 385 spin_unlock(&server->srv_lock); 403 386 cifs_swn_reset_server_dstaddr(server); 404 387 cifs_server_unlock(server); 405 - mod_delayed_work(cifsiod_wq, &server->reconnect, 0); 388 + 389 + /* increase ref count which reconnect work will drop */ 390 + spin_lock(&cifs_tcp_ses_lock); 391 + server->srv_count++; 392 + spin_unlock(&cifs_tcp_ses_lock); 393 + if (mod_delayed_work(cifsiod_wq, &server->reconnect, 0)) 394 + cifs_put_tcp_session(server, false); 406 395 } 407 396 } while (server->tcpStatus == CifsNeedReconnect); 408 397 ··· 538 515 spin_unlock(&server->srv_lock); 539 516 cifs_swn_reset_server_dstaddr(server); 540 517 cifs_server_unlock(server); 541 - mod_delayed_work(cifsiod_wq, &server->reconnect, 0); 518 + 519 + /* increase ref count which reconnect work will drop */ 520 + spin_lock(&cifs_tcp_ses_lock); 521 + server->srv_count++; 522 + spin_unlock(&cifs_tcp_ses_lock); 523 + if (mod_delayed_work(cifsiod_wq, &server->reconnect, 0)) 524 + cifs_put_tcp_session(server, false); 542 525 } while (server->tcpStatus == CifsNeedReconnect); 543 526 544 527 mutex_lock(&server->refpath_lock); ··· 1626 1597 1627 1598 cancel_delayed_work_sync(&server->echo); 1628 1599 1629 - if (from_reconnect) 1600 + if (from_reconnect) { 1630 1601 /* 1631 1602 * Avoid deadlock here: reconnect work calls 1632 1603 * cifs_put_tcp_session() at its end. Need to be sure 1633 1604 * that reconnect work does nothing with server pointer after 1634 1605 * that step. 1635 1606 */ 1636 - cancel_delayed_work(&server->reconnect); 1637 - else 1638 - cancel_delayed_work_sync(&server->reconnect); 1607 + if (cancel_delayed_work(&server->reconnect)) 1608 + cifs_put_tcp_session(server, from_reconnect); 1609 + } else { 1610 + if (cancel_delayed_work_sync(&server->reconnect)) 1611 + cifs_put_tcp_session(server, from_reconnect); 1612 + } 1639 1613 1640 1614 spin_lock(&server->srv_lock); 1641 1615 server->tcpStatus = CifsExiting; ··· 3592 3560 ctx->prepath = NULL; 3593 3561 3594 3562 out: 3595 - cifs_try_adding_channels(cifs_sb, mnt_ctx.ses); 3563 + cifs_try_adding_channels(mnt_ctx.ses); 3596 3564 rc = mount_setup_tlink(cifs_sb, mnt_ctx.ses, mnt_ctx.tcon); 3597 3565 if (rc) 3598 3566 goto error;
+13 -5
fs/smb/client/dfs.c
··· 263 263 return rc; 264 264 } 265 265 266 - /* Resolve UNC hostname in @ctx->source and set ip addr in @ctx->dstaddr */ 266 + /* 267 + * If @ctx->dfs_automount, then update @ctx->dstaddr earlier with the DFS root 268 + * server from where we'll start following any referrals. Otherwise rely on the 269 + * value provided by mount(2) as the user might not have dns_resolver key set up 270 + * and therefore failing to upcall to resolve UNC hostname under @ctx->source. 271 + */ 267 272 static int update_fs_context_dstaddr(struct smb3_fs_context *ctx) 268 273 { 269 274 struct sockaddr *addr = (struct sockaddr *)&ctx->dstaddr; 270 - int rc; 275 + int rc = 0; 271 276 272 - rc = dns_resolve_server_name_to_ip(ctx->source, addr, NULL); 273 - if (!rc) 274 - cifs_set_port(addr, ctx->port); 277 + if (!ctx->nodfs && ctx->dfs_automount) { 278 + rc = dns_resolve_server_name_to_ip(ctx->source, addr, NULL); 279 + if (!rc) 280 + cifs_set_port(addr, ctx->port); 281 + ctx->dfs_automount = false; 282 + } 275 283 return rc; 276 284 } 277 285
+1
fs/smb/client/fs_context.h
··· 268 268 bool witness:1; /* use witness protocol */ 269 269 char *leaf_fullpath; 270 270 struct cifs_ses *dfs_root_ses; 271 + bool dfs_automount:1; /* set for dfs automount only */ 271 272 }; 272 273 273 274 extern const struct fs_parameter_spec smb3_fs_parameters[];
+26
fs/smb/client/ioctl.c
··· 117 117 return rc; 118 118 } 119 119 120 + static long smb_mnt_get_tcon_info(struct cifs_tcon *tcon, void __user *arg) 121 + { 122 + int rc = 0; 123 + struct smb_mnt_tcon_info tcon_inf; 124 + 125 + tcon_inf.tid = tcon->tid; 126 + tcon_inf.session_id = tcon->ses->Suid; 127 + 128 + if (copy_to_user(arg, &tcon_inf, sizeof(struct smb_mnt_tcon_info))) 129 + rc = -EFAULT; 130 + 131 + return rc; 132 + } 133 + 120 134 static long smb_mnt_get_fsinfo(unsigned int xid, struct cifs_tcon *tcon, 121 135 void __user *arg) 122 136 { ··· 143 129 144 130 fsinf->version = 1; 145 131 fsinf->protocol_id = tcon->ses->server->vals->protocol_id; 132 + fsinf->tcon_flags = tcon->Flags; 146 133 fsinf->device_characteristics = 147 134 le32_to_cpu(tcon->fsDevInfo.DeviceCharacteristics); 148 135 fsinf->device_type = le32_to_cpu(tcon->fsDevInfo.DeviceType); ··· 428 413 break; 429 414 tcon = tlink_tcon(pSMBFile->tlink); 430 415 rc = smb_mnt_get_fsinfo(xid, tcon, (void __user *)arg); 416 + break; 417 + case CIFS_IOC_GET_TCON_INFO: 418 + cifs_sb = CIFS_SB(inode->i_sb); 419 + tlink = cifs_sb_tlink(cifs_sb); 420 + if (IS_ERR(tlink)) { 421 + rc = PTR_ERR(tlink); 422 + break; 423 + } 424 + tcon = tlink_tcon(tlink); 425 + rc = smb_mnt_get_tcon_info(tcon, (void __user *)arg); 426 + cifs_put_tlink(tlink); 431 427 break; 432 428 case CIFS_ENUMERATE_SNAPSHOTS: 433 429 if (pSMBFile == NULL)
+15 -2
fs/smb/client/namespace.c
··· 117 117 return dev; 118 118 } 119 119 120 + static bool is_dfs_mount(struct dentry *dentry) 121 + { 122 + struct cifs_sb_info *cifs_sb = CIFS_SB(dentry->d_sb); 123 + struct cifs_tcon *tcon = cifs_sb_master_tcon(cifs_sb); 124 + bool ret; 125 + 126 + spin_lock(&tcon->tc_lock); 127 + ret = !!tcon->origin_fullpath; 128 + spin_unlock(&tcon->tc_lock); 129 + return ret; 130 + } 131 + 120 132 /* Return full path out of a dentry set for automount */ 121 133 static char *automount_fullpath(struct dentry *dentry, void *page) 122 134 { ··· 224 212 ctx->source = NULL; 225 213 goto out; 226 214 } 227 - cifs_dbg(FYI, "%s: ctx: source=%s UNC=%s prepath=%s\n", 228 - __func__, ctx->source, ctx->UNC, ctx->prepath); 215 + ctx->dfs_automount = is_dfs_mount(mntpt); 216 + cifs_dbg(FYI, "%s: ctx: source=%s UNC=%s prepath=%s dfs_automount=%d\n", 217 + __func__, ctx->source, ctx->UNC, ctx->prepath, ctx->dfs_automount); 229 218 230 219 mnt = fc_mount(fc); 231 220 out:
+211 -48
fs/smb/client/sess.c
··· 24 24 #include "fs_context.h" 25 25 26 26 static int 27 - cifs_ses_add_channel(struct cifs_sb_info *cifs_sb, struct cifs_ses *ses, 27 + cifs_ses_add_channel(struct cifs_ses *ses, 28 28 struct cifs_server_iface *iface); 29 29 30 30 bool ··· 69 69 70 70 /* channel helper functions. assumed that chan_lock is held by caller. */ 71 71 72 - unsigned int 72 + int 73 73 cifs_ses_get_chan_index(struct cifs_ses *ses, 74 74 struct TCP_Server_Info *server) 75 75 { ··· 85 85 cifs_dbg(VFS, "unable to get chan index for server: 0x%llx", 86 86 server->conn_id); 87 87 WARN_ON(1); 88 - return 0; 88 + return CIFS_INVAL_CHAN_INDEX; 89 89 } 90 90 91 91 void 92 92 cifs_chan_set_in_reconnect(struct cifs_ses *ses, 93 93 struct TCP_Server_Info *server) 94 94 { 95 - unsigned int chan_index = cifs_ses_get_chan_index(ses, server); 95 + int chan_index = cifs_ses_get_chan_index(ses, server); 96 + 97 + if (chan_index == CIFS_INVAL_CHAN_INDEX) 98 + return; 96 99 97 100 ses->chans[chan_index].in_reconnect = true; 98 101 } ··· 106 103 { 107 104 unsigned int chan_index = cifs_ses_get_chan_index(ses, server); 108 105 106 + if (chan_index == CIFS_INVAL_CHAN_INDEX) 107 + return; 108 + 109 109 ses->chans[chan_index].in_reconnect = false; 110 110 } 111 111 ··· 118 112 { 119 113 unsigned int chan_index = cifs_ses_get_chan_index(ses, server); 120 114 115 + if (chan_index == CIFS_INVAL_CHAN_INDEX) 116 + return true; /* err on the safer side */ 117 + 121 118 return CIFS_CHAN_IN_RECONNECT(ses, chan_index); 122 119 } 123 120 ··· 129 120 struct TCP_Server_Info *server) 130 121 { 131 122 unsigned int chan_index = cifs_ses_get_chan_index(ses, server); 123 + 124 + if (chan_index == CIFS_INVAL_CHAN_INDEX) 125 + return; 132 126 133 127 set_bit(chan_index, &ses->chans_need_reconnect); 134 128 cifs_dbg(FYI, "Set reconnect bitmask for chan %u; now 0x%lx\n", ··· 144 132 { 145 133 unsigned int chan_index = cifs_ses_get_chan_index(ses, server); 146 134 135 + if (chan_index == CIFS_INVAL_CHAN_INDEX) 136 + return; 137 + 147 138 clear_bit(chan_index, &ses->chans_need_reconnect); 148 139 cifs_dbg(FYI, "Cleared reconnect bitmask for chan %u; now 0x%lx\n", 149 140 chan_index, ses->chans_need_reconnect); ··· 158 143 { 159 144 unsigned int chan_index = cifs_ses_get_chan_index(ses, server); 160 145 146 + if (chan_index == CIFS_INVAL_CHAN_INDEX) 147 + return true; /* err on the safer side */ 148 + 161 149 return CIFS_CHAN_NEEDS_RECONNECT(ses, chan_index); 162 150 } 163 151 ··· 170 152 { 171 153 unsigned int chan_index = cifs_ses_get_chan_index(ses, server); 172 154 155 + if (chan_index == CIFS_INVAL_CHAN_INDEX) 156 + return true; /* err on the safer side */ 157 + 173 158 return ses->chans[chan_index].iface && 174 159 ses->chans[chan_index].iface->is_active; 175 160 } 176 161 177 162 /* returns number of channels added */ 178 - int cifs_try_adding_channels(struct cifs_sb_info *cifs_sb, struct cifs_ses *ses) 163 + int cifs_try_adding_channels(struct cifs_ses *ses) 179 164 { 180 165 struct TCP_Server_Info *server = ses->server; 181 166 int old_chan_count, new_chan_count; 182 167 int left; 183 168 int rc = 0; 184 169 int tries = 0; 170 + size_t iface_weight = 0, iface_min_speed = 0; 185 171 struct cifs_server_iface *iface = NULL, *niface = NULL; 172 + struct cifs_server_iface *last_iface = NULL; 186 173 187 174 spin_lock(&ses->chan_lock); 188 175 ··· 215 192 } 216 193 spin_unlock(&ses->chan_lock); 217 194 218 - /* 219 - * Keep connecting to same, fastest, iface for all channels as 220 - * long as its RSS. Try next fastest one if not RSS or channel 221 - * creation fails. 222 - */ 223 - spin_lock(&ses->iface_lock); 224 - iface = list_first_entry(&ses->iface_list, struct cifs_server_iface, 225 - iface_head); 226 - spin_unlock(&ses->iface_lock); 227 - 228 195 while (left > 0) { 229 196 230 197 tries++; 231 198 if (tries > 3*ses->chan_max) { 232 - cifs_dbg(FYI, "too many channel open attempts (%d channels left to open)\n", 199 + cifs_dbg(VFS, "too many channel open attempts (%d channels left to open)\n", 233 200 left); 234 201 break; 235 202 } ··· 227 214 spin_lock(&ses->iface_lock); 228 215 if (!ses->iface_count) { 229 216 spin_unlock(&ses->iface_lock); 217 + cifs_dbg(VFS, "server %s does not advertise interfaces\n", 218 + ses->server->hostname); 230 219 break; 231 220 } 232 221 222 + if (!iface) 223 + iface = list_first_entry(&ses->iface_list, struct cifs_server_iface, 224 + iface_head); 225 + last_iface = list_last_entry(&ses->iface_list, struct cifs_server_iface, 226 + iface_head); 227 + iface_min_speed = last_iface->speed; 228 + 233 229 list_for_each_entry_safe_from(iface, niface, &ses->iface_list, 234 230 iface_head) { 231 + /* do not mix rdma and non-rdma interfaces */ 232 + if (iface->rdma_capable != ses->server->rdma) 233 + continue; 234 + 235 235 /* skip ifaces that are unusable */ 236 236 if (!iface->is_active || 237 237 (is_ses_using_iface(ses, iface) && 238 - !iface->rss_capable)) { 238 + !iface->rss_capable)) 239 239 continue; 240 - } 240 + 241 + /* check if we already allocated enough channels */ 242 + iface_weight = iface->speed / iface_min_speed; 243 + 244 + if (iface->weight_fulfilled >= iface_weight) 245 + continue; 241 246 242 247 /* take ref before unlock */ 243 248 kref_get(&iface->refcount); 244 249 245 250 spin_unlock(&ses->iface_lock); 246 - rc = cifs_ses_add_channel(cifs_sb, ses, iface); 251 + rc = cifs_ses_add_channel(ses, iface); 247 252 spin_lock(&ses->iface_lock); 248 253 249 254 if (rc) { ··· 272 241 continue; 273 242 } 274 243 275 - cifs_dbg(FYI, "successfully opened new channel on iface:%pIS\n", 244 + iface->num_channels++; 245 + iface->weight_fulfilled++; 246 + cifs_dbg(VFS, "successfully opened new channel on iface:%pIS\n", 276 247 &iface->sockaddr); 277 248 break; 249 + } 250 + 251 + /* reached end of list. reset weight_fulfilled and start over */ 252 + if (list_entry_is_head(iface, &ses->iface_list, iface_head)) { 253 + list_for_each_entry(iface, &ses->iface_list, iface_head) 254 + iface->weight_fulfilled = 0; 255 + spin_unlock(&ses->iface_lock); 256 + iface = NULL; 257 + continue; 278 258 } 279 259 spin_unlock(&ses->iface_lock); 280 260 ··· 297 255 } 298 256 299 257 /* 258 + * called when multichannel is disabled by the server. 259 + * this always gets called from smb2_reconnect 260 + * and cannot get called in parallel threads. 261 + */ 262 + void 263 + cifs_disable_secondary_channels(struct cifs_ses *ses) 264 + { 265 + int i, chan_count; 266 + struct TCP_Server_Info *server; 267 + struct cifs_server_iface *iface; 268 + 269 + spin_lock(&ses->chan_lock); 270 + chan_count = ses->chan_count; 271 + if (chan_count == 1) 272 + goto done; 273 + 274 + ses->chan_count = 1; 275 + 276 + /* for all secondary channels reset the need reconnect bit */ 277 + ses->chans_need_reconnect &= 1; 278 + 279 + for (i = 1; i < chan_count; i++) { 280 + iface = ses->chans[i].iface; 281 + server = ses->chans[i].server; 282 + 283 + if (iface) { 284 + spin_lock(&ses->iface_lock); 285 + kref_put(&iface->refcount, release_iface); 286 + ses->chans[i].iface = NULL; 287 + iface->num_channels--; 288 + if (iface->weight_fulfilled) 289 + iface->weight_fulfilled--; 290 + spin_unlock(&ses->iface_lock); 291 + } 292 + 293 + spin_unlock(&ses->chan_lock); 294 + if (server && !server->terminate) { 295 + server->terminate = true; 296 + cifs_signal_cifsd_for_reconnect(server, false); 297 + } 298 + spin_lock(&ses->chan_lock); 299 + 300 + if (server) { 301 + ses->chans[i].server = NULL; 302 + cifs_put_tcp_session(server, false); 303 + } 304 + 305 + } 306 + 307 + done: 308 + spin_unlock(&ses->chan_lock); 309 + } 310 + 311 + /* 300 312 * update the iface for the channel if necessary. 301 313 * will return 0 when iface is updated, 1 if removed, 2 otherwise 302 314 * Must be called with chan_lock held. ··· 359 263 cifs_chan_update_iface(struct cifs_ses *ses, struct TCP_Server_Info *server) 360 264 { 361 265 unsigned int chan_index; 266 + size_t iface_weight = 0, iface_min_speed = 0; 362 267 struct cifs_server_iface *iface = NULL; 363 268 struct cifs_server_iface *old_iface = NULL; 269 + struct cifs_server_iface *last_iface = NULL; 270 + struct sockaddr_storage ss; 364 271 int rc = 0; 365 272 366 273 spin_lock(&ses->chan_lock); 367 274 chan_index = cifs_ses_get_chan_index(ses, server); 368 - if (!chan_index) { 275 + if (chan_index == CIFS_INVAL_CHAN_INDEX) { 369 276 spin_unlock(&ses->chan_lock); 370 277 return 0; 371 278 } ··· 382 283 } 383 284 spin_unlock(&ses->chan_lock); 384 285 286 + spin_lock(&server->srv_lock); 287 + ss = server->dstaddr; 288 + spin_unlock(&server->srv_lock); 289 + 385 290 spin_lock(&ses->iface_lock); 291 + if (!ses->iface_count) { 292 + spin_unlock(&ses->iface_lock); 293 + cifs_dbg(VFS, "server %s does not advertise interfaces\n", ses->server->hostname); 294 + return 0; 295 + } 296 + 297 + last_iface = list_last_entry(&ses->iface_list, struct cifs_server_iface, 298 + iface_head); 299 + iface_min_speed = last_iface->speed; 300 + 386 301 /* then look for a new one */ 387 302 list_for_each_entry(iface, &ses->iface_list, iface_head) { 303 + if (!chan_index) { 304 + /* if we're trying to get the updated iface for primary channel */ 305 + if (!cifs_match_ipaddr((struct sockaddr *) &ss, 306 + (struct sockaddr *) &iface->sockaddr)) 307 + continue; 308 + 309 + kref_get(&iface->refcount); 310 + break; 311 + } 312 + 313 + /* do not mix rdma and non-rdma interfaces */ 314 + if (iface->rdma_capable != server->rdma) 315 + continue; 316 + 388 317 if (!iface->is_active || 389 318 (is_ses_using_iface(ses, iface) && 390 319 !iface->rss_capable)) { 391 320 continue; 392 321 } 322 + 323 + /* check if we already allocated enough channels */ 324 + iface_weight = iface->speed / iface_min_speed; 325 + 326 + if (iface->weight_fulfilled >= iface_weight) 327 + continue; 328 + 393 329 kref_get(&iface->refcount); 394 330 break; 395 331 } ··· 435 301 cifs_dbg(FYI, "unable to find a suitable iface\n"); 436 302 } 437 303 304 + if (!chan_index && !iface) { 305 + cifs_dbg(FYI, "unable to get the interface matching: %pIS\n", 306 + &ss); 307 + spin_unlock(&ses->iface_lock); 308 + return 0; 309 + } 310 + 438 311 /* now drop the ref to the current iface */ 439 312 if (old_iface && iface) { 440 313 cifs_dbg(FYI, "replacing iface: %pIS with %pIS\n", 441 314 &old_iface->sockaddr, 442 315 &iface->sockaddr); 316 + 317 + old_iface->num_channels--; 318 + if (old_iface->weight_fulfilled) 319 + old_iface->weight_fulfilled--; 320 + iface->num_channels++; 321 + iface->weight_fulfilled++; 322 + 443 323 kref_put(&old_iface->refcount, release_iface); 444 324 } else if (old_iface) { 445 325 cifs_dbg(FYI, "releasing ref to iface: %pIS\n", 446 326 &old_iface->sockaddr); 327 + 328 + old_iface->num_channels--; 329 + if (old_iface->weight_fulfilled) 330 + old_iface->weight_fulfilled--; 331 + 447 332 kref_put(&old_iface->refcount, release_iface); 333 + } else if (!chan_index) { 334 + /* special case: update interface for primary channel */ 335 + cifs_dbg(FYI, "referencing primary channel iface: %pIS\n", 336 + &iface->sockaddr); 337 + iface->num_channels++; 338 + iface->weight_fulfilled++; 448 339 } else { 449 340 WARN_ON(!iface); 450 341 cifs_dbg(FYI, "adding new iface: %pIS\n", &iface->sockaddr); ··· 478 319 479 320 spin_lock(&ses->chan_lock); 480 321 chan_index = cifs_ses_get_chan_index(ses, server); 322 + if (chan_index == CIFS_INVAL_CHAN_INDEX) { 323 + spin_unlock(&ses->chan_lock); 324 + return 0; 325 + } 326 + 481 327 ses->chans[chan_index].iface = iface; 482 328 483 329 /* No iface is found. if secondary chan, drop connection */ ··· 518 354 } 519 355 520 356 static int 521 - cifs_ses_add_channel(struct cifs_sb_info *cifs_sb, struct cifs_ses *ses, 357 + cifs_ses_add_channel(struct cifs_ses *ses, 522 358 struct cifs_server_iface *iface) 523 359 { 524 360 struct TCP_Server_Info *chan_server; ··· 597 433 * This will be used for encoding/decoding user/domain/pw 598 434 * during sess setup auth. 599 435 */ 600 - ctx->local_nls = cifs_sb->local_nls; 436 + ctx->local_nls = ses->local_nls; 601 437 602 438 /* Use RDMA if possible */ 603 439 ctx->rdma = iface->rdma_capable; ··· 643 479 644 480 rc = cifs_negotiate_protocol(xid, ses, chan->server); 645 481 if (!rc) 646 - rc = cifs_setup_session(xid, ses, chan->server, cifs_sb->local_nls); 482 + rc = cifs_setup_session(xid, ses, chan->server, ses->local_nls); 647 483 648 484 mutex_unlock(&ses->session_mutex); 649 485 650 486 out: 651 487 if (rc && chan->server) { 652 - /* 653 - * we should avoid race with these delayed works before we 654 - * remove this channel 655 - */ 656 - cancel_delayed_work_sync(&chan->server->echo); 657 - cancel_delayed_work_sync(&chan->server->reconnect); 488 + cifs_put_tcp_session(chan->server, 0); 658 489 659 490 spin_lock(&ses->chan_lock); 491 + 660 492 /* we rely on all bits beyond chan_count to be clear */ 661 493 cifs_chan_clear_need_reconnect(ses, chan->server); 662 494 ses->chan_count--; ··· 662 502 */ 663 503 WARN_ON(ses->chan_count < 1); 664 504 spin_unlock(&ses->chan_lock); 665 - 666 - cifs_put_tcp_session(chan->server, 0); 667 505 } 668 506 669 507 kfree(ctx->UNC); ··· 693 535 694 536 /* Now no need to set SMBFLG_CASELESS or obsolete CANONICAL PATH */ 695 537 696 - /* BB verify whether signing required on neg or just on auth frame 697 - (and NTLM case) */ 538 + /* BB verify whether signing required on neg or just auth frame (and NTLM case) */ 698 539 699 540 capabilities = CAP_LARGE_FILES | CAP_NT_SMBS | CAP_LEVEL_II_OPLOCKS | 700 541 CAP_LARGE_WRITE_X | CAP_LARGE_READ_X; ··· 750 593 751 594 /* copy domain */ 752 595 if (ses->domainName == NULL) { 753 - /* Sending null domain better than using a bogus domain name (as 754 - we did briefly in 2.6.18) since server will use its default */ 596 + /* 597 + * Sending null domain better than using a bogus domain name (as 598 + * we did briefly in 2.6.18) since server will use its default 599 + */ 755 600 *bcc_ptr = 0; 756 601 *(bcc_ptr+1) = 0; 757 602 bytes_ret = 0; ··· 772 613 char *bcc_ptr = *pbcc_area; 773 614 int bytes_ret = 0; 774 615 775 - /* BB FIXME add check that strings total less 776 - than 335 or will need to send them as arrays */ 616 + /* BB FIXME add check that strings less than 335 or will need to send as arrays */ 777 617 778 618 /* copy user */ 779 619 if (ses->user_name == NULL) { ··· 817 659 if (WARN_ON_ONCE(len < 0)) 818 660 len = CIFS_MAX_DOMAINNAME_LEN - 1; 819 661 bcc_ptr += len; 820 - } /* else we will send a null domain name 821 - so the server will default to its own domain */ 662 + } /* else we send a null domain name so server will default to its own domain */ 822 663 *bcc_ptr = 0; 823 664 bcc_ptr++; 824 665 ··· 913 756 if (len > bleft) 914 757 return; 915 758 916 - /* No domain field in LANMAN case. Domain is 917 - returned by old servers in the SMB negprot response */ 918 - /* BB For newer servers which do not support Unicode, 919 - but thus do return domain here we could add parsing 920 - for it later, but it is not very important */ 759 + /* 760 + * No domain field in LANMAN case. Domain is 761 + * returned by old servers in the SMB negprot response 762 + * 763 + * BB For newer servers which do not support Unicode, 764 + * but thus do return domain here, we could add parsing 765 + * for it later, but it is not very important 766 + */ 921 767 cifs_dbg(FYI, "ascii: bytes left %d\n", bleft); 922 768 } 923 769 #endif /* CONFIG_CIFS_ALLOW_INSECURE_LEGACY */ ··· 976 816 ses->ntlmssp->server_flags = server_flags; 977 817 978 818 memcpy(ses->ntlmssp->cryptkey, pblob->Challenge, CIFS_CRYPTO_KEY_SIZE); 979 - /* In particular we can examine sign flags */ 980 - /* BB spec says that if AvId field of MsvAvTimestamp is populated then 981 - we must set the MIC field of the AUTHENTICATE_MESSAGE */ 819 + /* 820 + * In particular we can examine sign flags 821 + * 822 + * BB spec says that if AvId field of MsvAvTimestamp is populated then 823 + * we must set the MIC field of the AUTHENTICATE_MESSAGE 824 + */ 982 825 983 826 tioffset = le32_to_cpu(pblob->TargetInfoArray.BufferOffset); 984 827 tilen = le16_to_cpu(pblob->TargetInfoArray.Length);
+6
fs/smb/client/smb2ops.c
··· 756 756 unsigned int ret_data_len = 0; 757 757 struct network_interface_info_ioctl_rsp *out_buf = NULL; 758 758 struct cifs_ses *ses = tcon->ses; 759 + struct TCP_Server_Info *pserver; 759 760 760 761 /* do not query too frequently */ 761 762 if (ses->iface_last_update && ··· 780 779 rc = parse_server_interfaces(out_buf, ret_data_len, ses, in_mount); 781 780 if (rc) 782 781 goto out; 782 + 783 + /* check if iface is still active */ 784 + pserver = ses->chans[0].server; 785 + if (pserver && !cifs_chan_is_iface_active(ses, pserver)) 786 + cifs_chan_update_iface(ses, pserver); 783 787 784 788 out: 785 789 kfree(out_buf);
+118 -13
fs/smb/client/smb2pdu.c
··· 163 163 int rc = 0; 164 164 struct nls_table *nls_codepage = NULL; 165 165 struct cifs_ses *ses; 166 + int xid; 167 + struct TCP_Server_Info *pserver; 168 + unsigned int chan_index; 166 169 167 170 /* 168 171 * SMB2s NegProt, SessSetup, Logoff do not have tcon yet so ··· 226 223 return -EAGAIN; 227 224 } 228 225 } 226 + 227 + /* if server is marked for termination, cifsd will cleanup */ 228 + if (server->terminate) { 229 + spin_unlock(&server->srv_lock); 230 + return -EHOSTDOWN; 231 + } 229 232 spin_unlock(&server->srv_lock); 230 233 231 234 again: ··· 251 242 252 243 mutex_lock(&ses->session_mutex); 253 244 /* 245 + * if this is called by delayed work, and the channel has been disabled 246 + * in parallel, the delayed work can continue to execute in parallel 247 + * there's a chance that this channel may not exist anymore 248 + */ 249 + spin_lock(&server->srv_lock); 250 + if (server->tcpStatus == CifsExiting) { 251 + spin_unlock(&server->srv_lock); 252 + mutex_unlock(&ses->session_mutex); 253 + rc = -EHOSTDOWN; 254 + goto out; 255 + } 256 + 257 + /* 254 258 * Recheck after acquire mutex. If another thread is negotiating 255 259 * and the server never sends an answer the socket will be closed 256 260 * and tcpStatus set to reconnect. 257 261 */ 258 - spin_lock(&server->srv_lock); 259 262 if (server->tcpStatus == CifsNeedReconnect) { 260 263 spin_unlock(&server->srv_lock); 261 264 mutex_unlock(&ses->session_mutex); ··· 304 283 305 284 rc = cifs_negotiate_protocol(0, ses, server); 306 285 if (!rc) { 286 + /* 287 + * if server stopped supporting multichannel 288 + * and the first channel reconnected, disable all the others. 289 + */ 290 + if (ses->chan_count > 1 && 291 + !(server->capabilities & SMB2_GLOBAL_CAP_MULTI_CHANNEL)) { 292 + if (SERVER_IS_CHAN(server)) { 293 + cifs_dbg(VFS, "server %s does not support " \ 294 + "multichannel anymore. skipping secondary channel\n", 295 + ses->server->hostname); 296 + 297 + spin_lock(&ses->chan_lock); 298 + chan_index = cifs_ses_get_chan_index(ses, server); 299 + if (chan_index == CIFS_INVAL_CHAN_INDEX) { 300 + spin_unlock(&ses->chan_lock); 301 + goto skip_terminate; 302 + } 303 + 304 + ses->chans[chan_index].server = NULL; 305 + spin_unlock(&ses->chan_lock); 306 + 307 + /* 308 + * the above reference of server by channel 309 + * needs to be dropped without holding chan_lock 310 + * as cifs_put_tcp_session takes a higher lock 311 + * i.e. cifs_tcp_ses_lock 312 + */ 313 + cifs_put_tcp_session(server, 1); 314 + 315 + server->terminate = true; 316 + cifs_signal_cifsd_for_reconnect(server, false); 317 + 318 + /* mark primary server as needing reconnect */ 319 + pserver = server->primary_server; 320 + cifs_signal_cifsd_for_reconnect(pserver, false); 321 + 322 + skip_terminate: 323 + mutex_unlock(&ses->session_mutex); 324 + rc = -EHOSTDOWN; 325 + goto out; 326 + } else { 327 + cifs_server_dbg(VFS, "does not support " \ 328 + "multichannel anymore. disabling all other channels\n"); 329 + cifs_disable_secondary_channels(ses); 330 + } 331 + } 332 + 307 333 rc = cifs_setup_session(0, ses, server, nls_codepage); 308 334 if ((rc == -EACCES) && !tcon->retry) { 309 335 mutex_unlock(&ses->session_mutex); ··· 375 307 tcon->need_reopen_files = true; 376 308 377 309 rc = cifs_tree_connect(0, tcon, nls_codepage); 378 - mutex_unlock(&ses->session_mutex); 379 310 380 311 cifs_dbg(FYI, "reconnect tcon rc = %d\n", rc); 381 312 if (rc) { 382 313 /* If sess reconnected but tcon didn't, something strange ... */ 314 + mutex_unlock(&ses->session_mutex); 383 315 cifs_dbg(VFS, "reconnect tcon failed rc = %d\n", rc); 384 316 goto out; 385 317 } 386 318 319 + if (!rc && 320 + (server->capabilities & SMB2_GLOBAL_CAP_MULTI_CHANNEL)) { 321 + mutex_unlock(&ses->session_mutex); 322 + 323 + /* 324 + * query server network interfaces, in case they change 325 + */ 326 + xid = get_xid(); 327 + rc = SMB3_request_interfaces(xid, tcon, false); 328 + free_xid(xid); 329 + 330 + if (rc) 331 + cifs_dbg(FYI, "%s: failed to query server interfaces: %d\n", 332 + __func__, rc); 333 + 334 + if (ses->chan_max > ses->chan_count && 335 + !SERVER_IS_CHAN(server)) { 336 + if (ses->chan_count == 1) 337 + cifs_server_dbg(VFS, "supports multichannel now\n"); 338 + 339 + cifs_try_adding_channels(ses); 340 + } 341 + } else { 342 + mutex_unlock(&ses->session_mutex); 343 + } 344 + 387 345 if (smb2_command != SMB2_INTERNAL_CMD) 388 - mod_delayed_work(cifsiod_wq, &server->reconnect, 0); 346 + if (mod_delayed_work(cifsiod_wq, &server->reconnect, 0)) 347 + cifs_put_tcp_session(server, false); 389 348 390 349 atomic_inc(&tconInfoReconnectCount); 391 350 out: ··· 3903 3808 /* Prevent simultaneous reconnects that can corrupt tcon->rlist list */ 3904 3809 mutex_lock(&pserver->reconnect_mutex); 3905 3810 3811 + /* if the server is marked for termination, drop the ref count here */ 3812 + if (server->terminate) { 3813 + cifs_put_tcp_session(server, true); 3814 + mutex_unlock(&pserver->reconnect_mutex); 3815 + return; 3816 + } 3817 + 3906 3818 INIT_LIST_HEAD(&tmp_list); 3907 3819 INIT_LIST_HEAD(&tmp_ses_list); 3908 3820 cifs_dbg(FYI, "Reconnecting tcons and channels\n"); ··· 3954 3852 } 3955 3853 spin_unlock(&ses->chan_lock); 3956 3854 } 3957 - /* 3958 - * Get the reference to server struct to be sure that the last call of 3959 - * cifs_put_tcon() in the loop below won't release the server pointer. 3960 - */ 3961 - if (tcon_exist || ses_exist) 3962 - server->srv_count++; 3963 3855 3964 3856 spin_unlock(&cifs_tcp_ses_lock); 3965 3857 ··· 4001 3905 4002 3906 done: 4003 3907 cifs_dbg(FYI, "Reconnecting tcons and channels finished\n"); 4004 - if (resched) 3908 + if (resched) { 4005 3909 queue_delayed_work(cifsiod_wq, &server->reconnect, 2 * HZ); 3910 + mutex_unlock(&pserver->reconnect_mutex); 3911 + 3912 + /* no need to put tcp session as we're retrying */ 3913 + return; 3914 + } 4006 3915 mutex_unlock(&pserver->reconnect_mutex); 4007 3916 4008 3917 /* now we can safely release srv struct */ 4009 - if (tcon_exist || ses_exist) 4010 - cifs_put_tcp_session(server, 1); 3918 + cifs_put_tcp_session(server, true); 4011 3919 } 4012 3920 4013 3921 int ··· 4031 3931 server->ops->need_neg(server)) { 4032 3932 spin_unlock(&server->srv_lock); 4033 3933 /* No need to send echo on newly established connections */ 4034 - mod_delayed_work(cifsiod_wq, &server->reconnect, 0); 3934 + spin_lock(&cifs_tcp_ses_lock); 3935 + server->srv_count++; 3936 + spin_unlock(&cifs_tcp_ses_lock); 3937 + if (mod_delayed_work(cifsiod_wq, &server->reconnect, 0)) 3938 + cifs_put_tcp_session(server, false); 3939 + 4035 3940 return rc; 4036 3941 } 4037 3942 spin_unlock(&server->srv_lock);
+7 -1
fs/smb/client/smb2transport.c
··· 413 413 ses->ses_status == SES_GOOD); 414 414 415 415 chan_index = cifs_ses_get_chan_index(ses, server); 416 - /* TODO: introduce ref counting for channels when the can be freed */ 416 + if (chan_index == CIFS_INVAL_CHAN_INDEX) { 417 + spin_unlock(&ses->chan_lock); 418 + spin_unlock(&ses->ses_lock); 419 + 420 + return -EINVAL; 421 + } 422 + 417 423 spin_unlock(&ses->chan_lock); 418 424 spin_unlock(&ses->ses_lock); 419 425
+1 -1
fs/smb/client/transport.c
··· 1023 1023 spin_lock(&ses->chan_lock); 1024 1024 for (i = 0; i < ses->chan_count; i++) { 1025 1025 server = ses->chans[i].server; 1026 - if (!server) 1026 + if (!server || server->terminate) 1027 1027 continue; 1028 1028 1029 1029 /*
+4 -1
fs/smb/client/xattr.c
··· 150 150 if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_NO_XATTR) 151 151 goto out; 152 152 153 - if (pTcon->ses->server->ops->set_EA) 153 + if (pTcon->ses->server->ops->set_EA) { 154 154 rc = pTcon->ses->server->ops->set_EA(xid, pTcon, 155 155 full_path, name, value, (__u16)size, 156 156 cifs_sb->local_nls, cifs_sb); 157 + if (rc == 0) 158 + inode_set_ctime_current(inode); 159 + } 157 160 break; 158 161 159 162 case XATTR_CIFS_ACL: