Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

Merge tag 'smb3-client-fixes-6.3-rc3' of git://git.samba.org/sfrench/cifs-2.6

Pull cifs client fixes from Steve French:
"Twelve cifs/smb3 client fixes (most also for stable)

- forced umount fix

- fix for two perf regressions

- reconnect fixes

- small debugging improvements

- multichannel fixes"

* tag 'smb3-client-fixes-6.3-rc3' of git://git.samba.org/sfrench/cifs-2.6:
smb3: fix unusable share after force unmount failure
cifs: fix dentry lookups in directory handle cache
smb3: lower default deferred close timeout to address perf regression
cifs: fix missing unload_nls() in smb2_reconnect()
cifs: avoid race conditions with parallel reconnects
cifs: append path to open_enter trace event
cifs: print session id while listing open files
cifs: dump pending mids for all channels in DebugData
cifs: empty interface list when server doesn't support query interfaces
cifs: do not poll server interfaces too regularly
cifs: lock chan_lock outside match_session
cifs: check only tcon status on tcon related functions

+222 -93
+35 -2
fs/cifs/cached_dir.c
··· 99 99 return dentry; 100 100 } 101 101 102 + static const char *path_no_prefix(struct cifs_sb_info *cifs_sb, 103 + const char *path) 104 + { 105 + size_t len = 0; 106 + 107 + if (!*path) 108 + return path; 109 + 110 + if ((cifs_sb->mnt_cifs_flags & CIFS_MOUNT_USE_PREFIX_PATH) && 111 + cifs_sb->prepath) { 112 + len = strlen(cifs_sb->prepath) + 1; 113 + if (unlikely(len > strlen(path))) 114 + return ERR_PTR(-EINVAL); 115 + } 116 + return path + len; 117 + } 118 + 102 119 /* 103 120 * Open the and cache a directory handle. 104 121 * If error then *cfid is not initialized. ··· 142 125 struct dentry *dentry = NULL; 143 126 struct cached_fid *cfid; 144 127 struct cached_fids *cfids; 128 + const char *npath; 145 129 146 130 if (tcon == NULL || tcon->cfids == NULL || tcon->nohandlecache || 147 131 is_smb1_server(tcon->ses->server)) ··· 179 161 } 180 162 181 163 /* 164 + * Skip any prefix paths in @path as lookup_positive_unlocked() ends up 165 + * calling ->lookup() which already adds those through 166 + * build_path_from_dentry(). Also, do it earlier as we might reconnect 167 + * below when trying to send compounded request and then potentially 168 + * having a different prefix path (e.g. after DFS failover). 169 + */ 170 + npath = path_no_prefix(cifs_sb, path); 171 + if (IS_ERR(npath)) { 172 + rc = PTR_ERR(npath); 173 + kfree(utf16_path); 174 + return rc; 175 + } 176 + 177 + /* 182 178 * We do not hold the lock for the open because in case 183 179 * SMB2_open needs to reconnect. 184 180 * This is safe because no other thread will be able to get a ref ··· 216 184 217 185 oparms = (struct cifs_open_parms) { 218 186 .tcon = tcon, 187 + .path = path, 219 188 .create_options = cifs_create_options(cifs_sb, CREATE_NOT_FILE), 220 189 .desired_access = FILE_READ_ATTRIBUTES, 221 190 .disposition = FILE_OPEN, ··· 284 251 (char *)&cfid->file_all_info)) 285 252 cfid->file_all_info_is_valid = true; 286 253 287 - if (!path[0]) 254 + if (!npath[0]) 288 255 dentry = dget(cifs_sb->root); 289 256 else { 290 - dentry = path_to_dentry(cifs_sb, path); 257 + dentry = path_to_dentry(cifs_sb, npath); 291 258 if (IS_ERR(dentry)) { 292 259 rc = -ENOENT; 293 260 goto oshr_free;
+30 -16
fs/cifs/cifs_debug.c
··· 176 176 177 177 seq_puts(m, "# Version:1\n"); 178 178 seq_puts(m, "# Format:\n"); 179 - seq_puts(m, "# <tree id> <persistent fid> <flags> <count> <pid> <uid>"); 179 + seq_puts(m, "# <tree id> <ses id> <persistent fid> <flags> <count> <pid> <uid>"); 180 180 #ifdef CONFIG_CIFS_DEBUG2 181 181 seq_printf(m, " <filename> <mid>\n"); 182 182 #else ··· 189 189 spin_lock(&tcon->open_file_lock); 190 190 list_for_each_entry(cfile, &tcon->openFileList, tlist) { 191 191 seq_printf(m, 192 - "0x%x 0x%llx 0x%x %d %d %d %pd", 192 + "0x%x 0x%llx 0x%llx 0x%x %d %d %d %pd", 193 193 tcon->tid, 194 + ses->Suid, 194 195 cfile->fid.persistent_fid, 195 196 cfile->f_flags, 196 197 cfile->count, ··· 217 216 { 218 217 struct mid_q_entry *mid_entry; 219 218 struct TCP_Server_Info *server; 219 + struct TCP_Server_Info *chan_server; 220 220 struct cifs_ses *ses; 221 221 struct cifs_tcon *tcon; 222 222 struct cifs_server_iface *iface; ··· 476 474 seq_puts(m, "\t\t[CONNECTED]\n"); 477 475 } 478 476 spin_unlock(&ses->iface_lock); 477 + 478 + seq_puts(m, "\n\n\tMIDs: "); 479 + spin_lock(&ses->chan_lock); 480 + for (j = 0; j < ses->chan_count; j++) { 481 + chan_server = ses->chans[j].server; 482 + if (!chan_server) 483 + continue; 484 + 485 + if (list_empty(&chan_server->pending_mid_q)) 486 + continue; 487 + 488 + seq_printf(m, "\n\tServer ConnectionId: 0x%llx", 489 + chan_server->conn_id); 490 + spin_lock(&chan_server->mid_lock); 491 + list_for_each_entry(mid_entry, &chan_server->pending_mid_q, qhead) { 492 + seq_printf(m, "\n\t\tState: %d com: %d pid: %d cbdata: %p mid %llu", 493 + mid_entry->mid_state, 494 + le16_to_cpu(mid_entry->command), 495 + mid_entry->pid, 496 + mid_entry->callback_data, 497 + mid_entry->mid); 498 + } 499 + spin_unlock(&chan_server->mid_lock); 500 + } 501 + spin_unlock(&ses->chan_lock); 502 + seq_puts(m, "\n--\n"); 479 503 } 480 504 if (i == 0) 481 505 seq_printf(m, "\n\t\t[NONE]"); 482 - 483 - seq_puts(m, "\n\n\tMIDs: "); 484 - spin_lock(&server->mid_lock); 485 - list_for_each_entry(mid_entry, &server->pending_mid_q, qhead) { 486 - seq_printf(m, "\n\tState: %d com: %d pid:" 487 - " %d cbdata: %p mid %llu\n", 488 - mid_entry->mid_state, 489 - le16_to_cpu(mid_entry->command), 490 - mid_entry->pid, 491 - mid_entry->callback_data, 492 - mid_entry->mid); 493 - } 494 - spin_unlock(&server->mid_lock); 495 - seq_printf(m, "\n--\n"); 496 506 } 497 507 if (c == 0) 498 508 seq_printf(m, "\n\t[NONE]");
+6 -3
fs/cifs/cifsfs.c
··· 731 731 spin_lock(&tcon->tc_lock); 732 732 if ((tcon->tc_count > 1) || (tcon->status == TID_EXITING)) { 733 733 /* we have other mounts to same share or we have 734 - already tried to force umount this and woken up 734 + already tried to umount this and woken up 735 735 all waiting network requests, nothing to do */ 736 736 spin_unlock(&tcon->tc_lock); 737 737 spin_unlock(&cifs_tcp_ses_lock); 738 738 return; 739 - } else if (tcon->tc_count == 1) 740 - tcon->status = TID_EXITING; 739 + } 740 + /* 741 + * can not set tcon->status to TID_EXITING yet since we don't know if umount -f will 742 + * fail later (e.g. due to open files). TID_EXITING will be set just before tdis req sent 743 + */ 741 744 spin_unlock(&tcon->tc_lock); 742 745 spin_unlock(&cifs_tcp_ses_lock); 743 746
+2 -4
fs/cifs/cifssmb.c
··· 86 86 87 87 /* 88 88 * only tree disconnect, open, and write, (and ulogoff which does not 89 - * have tcon) are allowed as we start force umount 89 + * have tcon) are allowed as we start umount 90 90 */ 91 91 spin_lock(&tcon->tc_lock); 92 92 if (tcon->status == TID_EXITING) { 93 - if (smb_command != SMB_COM_WRITE_ANDX && 94 - smb_command != SMB_COM_OPEN_ANDX && 95 - smb_command != SMB_COM_TREE_DISCONNECT) { 93 + if (smb_command != SMB_COM_TREE_DISCONNECT) { 96 94 spin_unlock(&tcon->tc_lock); 97 95 cifs_dbg(FYI, "can not send cmd %d while umounting\n", 98 96 smb_command);
+52 -22
fs/cifs/connect.c
··· 212 212 cifs_chan_update_iface(ses, server); 213 213 214 214 spin_lock(&ses->chan_lock); 215 - if (!mark_smb_session && cifs_chan_needs_reconnect(ses, server)) 216 - goto next_session; 215 + if (!mark_smb_session && cifs_chan_needs_reconnect(ses, server)) { 216 + spin_unlock(&ses->chan_lock); 217 + continue; 218 + } 217 219 218 220 if (mark_smb_session) 219 221 CIFS_SET_ALL_CHANS_NEED_RECONNECT(ses); 220 222 else 221 223 cifs_chan_set_need_reconnect(ses, server); 222 224 223 - /* If all channels need reconnect, then tcon needs reconnect */ 224 - if (!mark_smb_session && !CIFS_ALL_CHANS_NEED_RECONNECT(ses)) 225 - goto next_session; 225 + cifs_dbg(FYI, "%s: channel connect bitmap: 0x%lx\n", 226 + __func__, ses->chans_need_reconnect); 226 227 228 + /* If all channels need reconnect, then tcon needs reconnect */ 229 + if (!mark_smb_session && !CIFS_ALL_CHANS_NEED_RECONNECT(ses)) { 230 + spin_unlock(&ses->chan_lock); 231 + continue; 232 + } 233 + spin_unlock(&ses->chan_lock); 234 + 235 + spin_lock(&ses->ses_lock); 227 236 ses->ses_status = SES_NEED_RECON; 237 + spin_unlock(&ses->ses_lock); 228 238 229 239 list_for_each_entry(tcon, &ses->tcon_list, tcon_list) { 230 240 tcon->need_reconnect = true; 241 + spin_lock(&tcon->tc_lock); 231 242 tcon->status = TID_NEED_RECON; 243 + spin_unlock(&tcon->tc_lock); 232 244 } 233 245 if (ses->tcon_ipc) { 234 246 ses->tcon_ipc->need_reconnect = true; 247 + spin_lock(&ses->tcon_ipc->tc_lock); 235 248 ses->tcon_ipc->status = TID_NEED_RECON; 249 + spin_unlock(&ses->tcon_ipc->tc_lock); 236 250 } 237 - 238 - next_session: 239 - spin_unlock(&ses->chan_lock); 240 251 } 241 252 spin_unlock(&cifs_tcp_ses_lock); 242 253 } ··· 1732 1721 return ERR_PTR(rc); 1733 1722 } 1734 1723 1735 - /* this function must be called with ses_lock held */ 1724 + /* this function must be called with ses_lock and chan_lock held */ 1736 1725 static int match_session(struct cifs_ses *ses, struct smb3_fs_context *ctx) 1737 1726 { 1738 1727 if (ctx->sectype != Unspecified && ··· 1743 1732 * If an existing session is limited to less channels than 1744 1733 * requested, it should not be reused 1745 1734 */ 1746 - spin_lock(&ses->chan_lock); 1747 - if (ses->chan_max < ctx->max_channels) { 1748 - spin_unlock(&ses->chan_lock); 1735 + if (ses->chan_max < ctx->max_channels) 1749 1736 return 0; 1750 - } 1751 - spin_unlock(&ses->chan_lock); 1752 1737 1753 1738 switch (ses->sectype) { 1754 1739 case Kerberos: ··· 1872 1865 spin_unlock(&ses->ses_lock); 1873 1866 continue; 1874 1867 } 1868 + spin_lock(&ses->chan_lock); 1875 1869 if (!match_session(ses, ctx)) { 1870 + spin_unlock(&ses->chan_lock); 1876 1871 spin_unlock(&ses->ses_lock); 1877 1872 continue; 1878 1873 } 1874 + spin_unlock(&ses->chan_lock); 1879 1875 spin_unlock(&ses->ses_lock); 1880 1876 1881 1877 ++ses->ses_count; ··· 2324 2314 WARN_ON(tcon->tc_count < 0); 2325 2315 2326 2316 list_del_init(&tcon->tcon_list); 2317 + tcon->status = TID_EXITING; 2327 2318 spin_unlock(&tcon->tc_lock); 2328 2319 spin_unlock(&cifs_tcp_ses_lock); 2329 2320 ··· 2704 2693 2705 2694 spin_lock(&tcp_srv->srv_lock); 2706 2695 spin_lock(&ses->ses_lock); 2696 + spin_lock(&ses->chan_lock); 2707 2697 spin_lock(&tcon->tc_lock); 2708 2698 if (!match_server(tcp_srv, ctx, dfs_super_cmp) || 2709 2699 !match_session(ses, ctx) || ··· 2717 2705 rc = compare_mount_options(sb, mnt_data); 2718 2706 out: 2719 2707 spin_unlock(&tcon->tc_lock); 2708 + spin_unlock(&ses->chan_lock); 2720 2709 spin_unlock(&ses->ses_lock); 2721 2710 spin_unlock(&tcp_srv->srv_lock); 2722 2711 ··· 3665 3652 3666 3653 /* only send once per connect */ 3667 3654 spin_lock(&server->srv_lock); 3668 - if (!server->ops->need_neg(server) || 3655 + if (server->tcpStatus != CifsGood && 3656 + server->tcpStatus != CifsNew && 3669 3657 server->tcpStatus != CifsNeedNegotiate) { 3658 + spin_unlock(&server->srv_lock); 3659 + return -EHOSTDOWN; 3660 + } 3661 + 3662 + if (!server->ops->need_neg(server) && 3663 + server->tcpStatus == CifsGood) { 3670 3664 spin_unlock(&server->srv_lock); 3671 3665 return 0; 3672 3666 } 3667 + 3673 3668 server->tcpStatus = CifsInNegotiate; 3674 3669 spin_unlock(&server->srv_lock); 3675 3670 ··· 3711 3690 bool is_binding = false; 3712 3691 3713 3692 spin_lock(&ses->ses_lock); 3693 + cifs_dbg(FYI, "%s: channel connect bitmap: 0x%lx\n", 3694 + __func__, ses->chans_need_reconnect); 3695 + 3714 3696 if (ses->ses_status != SES_GOOD && 3715 3697 ses->ses_status != SES_NEW && 3716 3698 ses->ses_status != SES_NEED_RECON) { 3717 3699 spin_unlock(&ses->ses_lock); 3718 - return 0; 3700 + return -EHOSTDOWN; 3719 3701 } 3720 3702 3721 3703 /* only send once per connect */ 3722 3704 spin_lock(&ses->chan_lock); 3723 - if (CIFS_ALL_CHANS_GOOD(ses) || 3724 - cifs_chan_in_reconnect(ses, server)) { 3705 + if (CIFS_ALL_CHANS_GOOD(ses)) { 3706 + if (ses->ses_status == SES_NEED_RECON) 3707 + ses->ses_status = SES_GOOD; 3725 3708 spin_unlock(&ses->chan_lock); 3726 3709 spin_unlock(&ses->ses_lock); 3727 3710 return 0; 3728 3711 } 3729 - is_binding = !CIFS_ALL_CHANS_NEED_RECONNECT(ses); 3712 + 3730 3713 cifs_chan_set_in_reconnect(ses, server); 3714 + is_binding = !CIFS_ALL_CHANS_NEED_RECONNECT(ses); 3731 3715 spin_unlock(&ses->chan_lock); 3732 3716 3733 3717 if (!is_binding) ··· 4062 4036 4063 4037 /* only send once per connect */ 4064 4038 spin_lock(&tcon->tc_lock); 4065 - if (tcon->ses->ses_status != SES_GOOD || 4066 - (tcon->status != TID_NEW && 4067 - tcon->status != TID_NEED_TCON)) { 4039 + if (tcon->status != TID_NEW && 4040 + tcon->status != TID_NEED_TCON) { 4041 + spin_unlock(&tcon->tc_lock); 4042 + return -EHOSTDOWN; 4043 + } 4044 + 4045 + if (tcon->status == TID_GOOD) { 4068 4046 spin_unlock(&tcon->tc_lock); 4069 4047 return 0; 4070 4048 }
+7 -3
fs/cifs/dfs.c
··· 502 502 503 503 /* only send once per connect */ 504 504 spin_lock(&tcon->tc_lock); 505 - if (tcon->ses->ses_status != SES_GOOD || 506 - (tcon->status != TID_NEW && 507 - tcon->status != TID_NEED_TCON)) { 505 + if (tcon->status != TID_NEW && 506 + tcon->status != TID_NEED_TCON) { 507 + spin_unlock(&tcon->tc_lock); 508 + return -EHOSTDOWN; 509 + } 510 + 511 + if (tcon->status == TID_GOOD) { 508 512 spin_unlock(&tcon->tc_lock); 509 513 return 0; 510 514 }
+1 -1
fs/cifs/dfs_cache.c
··· 1191 1191 } 1192 1192 1193 1193 spin_lock(&ipc->tc_lock); 1194 - if (ses->ses_status != SES_GOOD || ipc->status != TID_GOOD) { 1194 + if (ipc->status != TID_GOOD) { 1195 1195 spin_unlock(&ipc->tc_lock); 1196 1196 cifs_dbg(FYI, "%s: skip cache refresh due to disconnected ipc\n", __func__); 1197 1197 goto out;
+4 -4
fs/cifs/file.c
··· 174 174 struct list_head *tmp1; 175 175 176 176 /* only send once per connect */ 177 - spin_lock(&tcon->ses->ses_lock); 178 - if ((tcon->ses->ses_status != SES_GOOD) || (tcon->status != TID_NEED_RECON)) { 179 - spin_unlock(&tcon->ses->ses_lock); 177 + spin_lock(&tcon->tc_lock); 178 + if (tcon->status != TID_NEED_RECON) { 179 + spin_unlock(&tcon->tc_lock); 180 180 return; 181 181 } 182 182 tcon->status = TID_IN_FILES_INVALIDATE; 183 - spin_unlock(&tcon->ses->ses_lock); 183 + spin_unlock(&tcon->tc_lock); 184 184 185 185 /* list all files open on tree connection and mark them invalid */ 186 186 spin_lock(&tcon->open_file_lock);
+1 -1
fs/cifs/fs_context.h
··· 286 286 * max deferred close timeout (jiffies) - 2^30 287 287 */ 288 288 #define SMB3_MAX_DCLOSETIMEO (1 << 30) 289 - #define SMB3_DEF_DCLOSETIMEO (5 * HZ) /* Can increase later, other clients use larger */ 289 + #define SMB3_DEF_DCLOSETIMEO (1 * HZ) /* even 1 sec enough to help eg open/write/close/open/read */ 290 290 #endif
+2
fs/cifs/link.c
··· 360 360 oparms = (struct cifs_open_parms) { 361 361 .tcon = tcon, 362 362 .cifs_sb = cifs_sb, 363 + .path = path, 363 364 .desired_access = GENERIC_READ, 364 365 .create_options = cifs_create_options(cifs_sb, CREATE_NOT_DIR), 365 366 .disposition = FILE_OPEN, ··· 428 427 oparms = (struct cifs_open_parms) { 429 428 .tcon = tcon, 430 429 .cifs_sb = cifs_sb, 430 + .path = path, 431 431 .desired_access = GENERIC_WRITE, 432 432 .create_options = cifs_create_options(cifs_sb, CREATE_NOT_DIR), 433 433 .disposition = FILE_CREATE,
+1
fs/cifs/smb2inode.c
··· 107 107 108 108 vars->oparms = (struct cifs_open_parms) { 109 109 .tcon = tcon, 110 + .path = full_path, 110 111 .desired_access = desired_access, 111 112 .disposition = create_disposition, 112 113 .create_options = cifs_create_options(cifs_sb, create_options),
+26 -1
fs/cifs/smb2ops.c
··· 530 530 p = buf; 531 531 532 532 spin_lock(&ses->iface_lock); 533 + /* do not query too frequently, this time with lock held */ 534 + if (ses->iface_last_update && 535 + time_before(jiffies, ses->iface_last_update + 536 + (SMB_INTERFACE_POLL_INTERVAL * HZ))) { 537 + spin_unlock(&ses->iface_lock); 538 + return 0; 539 + } 540 + 533 541 /* 534 542 * Go through iface_list and do kref_put to remove 535 543 * any unused ifaces. ifaces in use will be removed ··· 704 696 struct network_interface_info_ioctl_rsp *out_buf = NULL; 705 697 struct cifs_ses *ses = tcon->ses; 706 698 699 + /* do not query too frequently */ 700 + if (ses->iface_last_update && 701 + time_before(jiffies, ses->iface_last_update + 702 + (SMB_INTERFACE_POLL_INTERVAL * HZ))) 703 + return 0; 704 + 707 705 rc = SMB2_ioctl(xid, tcon, NO_FILE_ID, NO_FILE_ID, 708 706 FSCTL_QUERY_NETWORK_INTERFACE_INFO, 709 707 NULL /* no data input */, 0 /* no data input */, ··· 717 703 if (rc == -EOPNOTSUPP) { 718 704 cifs_dbg(FYI, 719 705 "server does not support query network interfaces\n"); 720 - goto out; 706 + ret_data_len = 0; 721 707 } else if (rc != 0) { 722 708 cifs_tcon_dbg(VFS, "error %d on ioctl to get interface list\n", rc); 723 709 goto out; ··· 745 731 746 732 oparms = (struct cifs_open_parms) { 747 733 .tcon = tcon, 734 + .path = "", 748 735 .desired_access = FILE_READ_ATTRIBUTES, 749 736 .disposition = FILE_OPEN, 750 737 .create_options = cifs_create_options(cifs_sb, 0), ··· 789 774 790 775 oparms = (struct cifs_open_parms) { 791 776 .tcon = tcon, 777 + .path = "", 792 778 .desired_access = FILE_READ_ATTRIBUTES, 793 779 .disposition = FILE_OPEN, 794 780 .create_options = cifs_create_options(cifs_sb, 0), ··· 837 821 838 822 oparms = (struct cifs_open_parms) { 839 823 .tcon = tcon, 824 + .path = full_path, 840 825 .desired_access = FILE_READ_ATTRIBUTES, 841 826 .disposition = FILE_OPEN, 842 827 .create_options = cifs_create_options(cifs_sb, 0), ··· 1122 1105 1123 1106 oparms = (struct cifs_open_parms) { 1124 1107 .tcon = tcon, 1108 + .path = path, 1125 1109 .desired_access = FILE_WRITE_EA, 1126 1110 .disposition = FILE_OPEN, 1127 1111 .create_options = cifs_create_options(cifs_sb, 0), ··· 2114 2096 tcon = cifs_sb_master_tcon(cifs_sb); 2115 2097 oparms = (struct cifs_open_parms) { 2116 2098 .tcon = tcon, 2099 + .path = path, 2117 2100 .desired_access = FILE_READ_ATTRIBUTES | FILE_READ_DATA, 2118 2101 .disposition = FILE_OPEN, 2119 2102 .create_options = cifs_create_options(cifs_sb, 0), ··· 2187 2168 2188 2169 oparms = (struct cifs_open_parms) { 2189 2170 .tcon = tcon, 2171 + .path = path, 2190 2172 .desired_access = FILE_READ_ATTRIBUTES | FILE_READ_DATA, 2191 2173 .disposition = FILE_OPEN, 2192 2174 .create_options = cifs_create_options(cifs_sb, 0), ··· 2520 2500 2521 2501 oparms = (struct cifs_open_parms) { 2522 2502 .tcon = tcon, 2503 + .path = path, 2523 2504 .desired_access = desired_access, 2524 2505 .disposition = FILE_OPEN, 2525 2506 .create_options = cifs_create_options(cifs_sb, 0), ··· 2655 2634 2656 2635 oparms = (struct cifs_open_parms) { 2657 2636 .tcon = tcon, 2637 + .path = "", 2658 2638 .desired_access = FILE_READ_ATTRIBUTES, 2659 2639 .disposition = FILE_OPEN, 2660 2640 .create_options = cifs_create_options(cifs_sb, 0), ··· 2950 2928 2951 2929 oparms = (struct cifs_open_parms) { 2952 2930 .tcon = tcon, 2931 + .path = full_path, 2953 2932 .desired_access = FILE_READ_ATTRIBUTES, 2954 2933 .disposition = FILE_OPEN, 2955 2934 .create_options = cifs_create_options(cifs_sb, create_options), ··· 3091 3068 3092 3069 oparms = (struct cifs_open_parms) { 3093 3070 .tcon = tcon, 3071 + .path = full_path, 3094 3072 .desired_access = FILE_READ_ATTRIBUTES, 3095 3073 .disposition = FILE_OPEN, 3096 3074 .create_options = cifs_create_options(cifs_sb, OPEN_REPARSE_POINT), ··· 3232 3208 3233 3209 oparms = (struct cifs_open_parms) { 3234 3210 .tcon = tcon, 3211 + .path = path, 3235 3212 .desired_access = READ_CONTROL, 3236 3213 .disposition = FILE_OPEN, 3237 3214 /*
+33 -29
fs/cifs/smb2pdu.c
··· 144 144 struct TCP_Server_Info *server) 145 145 { 146 146 int rc = 0; 147 - struct nls_table *nls_codepage; 147 + struct nls_table *nls_codepage = NULL; 148 148 struct cifs_ses *ses; 149 149 150 150 /* ··· 165 165 spin_lock(&tcon->tc_lock); 166 166 if (tcon->status == TID_EXITING) { 167 167 /* 168 - * only tree disconnect, open, and write, 169 - * (and ulogoff which does not have tcon) 170 - * are allowed as we start force umount. 168 + * only tree disconnect allowed when disconnecting ... 171 169 */ 172 - if ((smb2_command != SMB2_WRITE) && 173 - (smb2_command != SMB2_CREATE) && 174 - (smb2_command != SMB2_TREE_DISCONNECT)) { 170 + if (smb2_command != SMB2_TREE_DISCONNECT) { 175 171 spin_unlock(&tcon->tc_lock); 176 172 cifs_dbg(FYI, "can not send cmd %d while umounting\n", 177 173 smb2_command); ··· 199 203 } 200 204 spin_unlock(&server->srv_lock); 201 205 206 + again: 202 207 rc = cifs_wait_for_server_reconnect(server, tcon->retry); 203 208 if (rc) 204 209 return rc; ··· 216 219 tcon->ses->chans_need_reconnect, 217 220 tcon->need_reconnect); 218 221 219 - nls_codepage = load_nls_default(); 220 - 222 + mutex_lock(&ses->session_mutex); 221 223 /* 222 224 * Recheck after acquire mutex. If another thread is negotiating 223 225 * and the server never sends an answer the socket will be closed ··· 225 229 spin_lock(&server->srv_lock); 226 230 if (server->tcpStatus == CifsNeedReconnect) { 227 231 spin_unlock(&server->srv_lock); 232 + mutex_unlock(&ses->session_mutex); 233 + 234 + if (tcon->retry) 235 + goto again; 236 + 228 237 rc = -EHOSTDOWN; 229 238 goto out; 230 239 } 231 240 spin_unlock(&server->srv_lock); 232 241 242 + nls_codepage = load_nls_default(); 243 + 233 244 /* 234 245 * need to prevent multiple threads trying to simultaneously 235 246 * reconnect the same SMB session 236 247 */ 248 + spin_lock(&ses->ses_lock); 237 249 spin_lock(&ses->chan_lock); 238 - if (!cifs_chan_needs_reconnect(ses, server)) { 250 + if (!cifs_chan_needs_reconnect(ses, server) && 251 + ses->ses_status == SES_GOOD) { 239 252 spin_unlock(&ses->chan_lock); 240 - 253 + spin_unlock(&ses->ses_lock); 241 254 /* this means that we only need to tree connect */ 242 255 if (tcon->need_reconnect) 243 256 goto skip_sess_setup; 244 257 258 + mutex_unlock(&ses->session_mutex); 245 259 goto out; 246 260 } 247 261 spin_unlock(&ses->chan_lock); 262 + spin_unlock(&ses->ses_lock); 248 263 249 - mutex_lock(&ses->session_mutex); 250 264 rc = cifs_negotiate_protocol(0, ses, server); 251 265 if (!rc) { 252 266 rc = cifs_setup_session(0, ses, server, nls_codepage); ··· 272 266 mutex_unlock(&ses->session_mutex); 273 267 goto out; 274 268 } 275 - mutex_unlock(&ses->session_mutex); 276 269 277 270 skip_sess_setup: 278 - mutex_lock(&ses->session_mutex); 279 271 if (!tcon->need_reconnect) { 280 272 mutex_unlock(&ses->session_mutex); 281 273 goto out; ··· 288 284 cifs_dbg(FYI, "reconnect tcon rc = %d\n", rc); 289 285 if (rc) { 290 286 /* If sess reconnected but tcon didn't, something strange ... */ 291 - pr_warn_once("reconnect tcon failed rc = %d\n", rc); 287 + cifs_dbg(VFS, "reconnect tcon failed rc = %d\n", rc); 292 288 goto out; 293 289 } 294 290 ··· 1260 1256 if (rc) 1261 1257 return rc; 1262 1258 1263 - spin_lock(&ses->chan_lock); 1264 - is_binding = !CIFS_ALL_CHANS_NEED_RECONNECT(ses); 1265 - spin_unlock(&ses->chan_lock); 1259 + spin_lock(&ses->ses_lock); 1260 + is_binding = (ses->ses_status == SES_GOOD); 1261 + spin_unlock(&ses->ses_lock); 1266 1262 1267 1263 if (is_binding) { 1268 1264 req->hdr.SessionId = cpu_to_le64(ses->Suid); ··· 1420 1416 goto out_put_spnego_key; 1421 1417 } 1422 1418 1423 - spin_lock(&ses->chan_lock); 1424 - is_binding = !CIFS_ALL_CHANS_NEED_RECONNECT(ses); 1425 - spin_unlock(&ses->chan_lock); 1419 + spin_lock(&ses->ses_lock); 1420 + is_binding = (ses->ses_status == SES_GOOD); 1421 + spin_unlock(&ses->ses_lock); 1426 1422 1427 1423 /* keep session key if binding */ 1428 1424 if (!is_binding) { ··· 1546 1542 1547 1543 cifs_dbg(FYI, "rawntlmssp session setup challenge phase\n"); 1548 1544 1549 - spin_lock(&ses->chan_lock); 1550 - is_binding = !CIFS_ALL_CHANS_NEED_RECONNECT(ses); 1551 - spin_unlock(&ses->chan_lock); 1545 + spin_lock(&ses->ses_lock); 1546 + is_binding = (ses->ses_status == SES_GOOD); 1547 + spin_unlock(&ses->ses_lock); 1552 1548 1553 1549 /* keep existing ses id and flags if binding */ 1554 1550 if (!is_binding) { ··· 1614 1610 1615 1611 rsp = (struct smb2_sess_setup_rsp *)sess_data->iov[0].iov_base; 1616 1612 1617 - spin_lock(&ses->chan_lock); 1618 - is_binding = !CIFS_ALL_CHANS_NEED_RECONNECT(ses); 1619 - spin_unlock(&ses->chan_lock); 1613 + spin_lock(&ses->ses_lock); 1614 + is_binding = (ses->ses_status == SES_GOOD); 1615 + spin_unlock(&ses->ses_lock); 1620 1616 1621 1617 /* keep existing ses id and flags if binding */ 1622 1618 if (!is_binding) { ··· 2709 2705 rqst.rq_nvec = n_iov; 2710 2706 2711 2707 /* no need to inc num_remote_opens because we close it just below */ 2712 - trace_smb3_posix_mkdir_enter(xid, tcon->tid, ses->Suid, CREATE_NOT_FILE, 2708 + trace_smb3_posix_mkdir_enter(xid, tcon->tid, ses->Suid, full_path, CREATE_NOT_FILE, 2713 2709 FILE_WRITE_ATTRIBUTES); 2714 2710 /* resource #4: response buffer */ 2715 2711 rc = cifs_send_recv(xid, ses, server, ··· 2977 2973 if (rc) 2978 2974 goto creat_exit; 2979 2975 2980 - trace_smb3_open_enter(xid, tcon->tid, tcon->ses->Suid, 2976 + trace_smb3_open_enter(xid, tcon->tid, tcon->ses->Suid, oparms->path, 2981 2977 oparms->create_options, oparms->desired_access); 2982 2978 2983 2979 rc = cifs_send_recv(xid, ses, server,
+14 -3
fs/cifs/smb2transport.c
··· 81 81 struct cifs_ses *ses = NULL; 82 82 int i; 83 83 int rc = 0; 84 + bool is_binding = false; 84 85 85 86 spin_lock(&cifs_tcp_ses_lock); 86 87 ··· 98 97 goto out; 99 98 100 99 found: 100 + spin_lock(&ses->ses_lock); 101 101 spin_lock(&ses->chan_lock); 102 - if (cifs_chan_needs_reconnect(ses, server) && 103 - !CIFS_ALL_CHANS_NEED_RECONNECT(ses)) { 102 + 103 + is_binding = (cifs_chan_needs_reconnect(ses, server) && 104 + ses->ses_status == SES_GOOD); 105 + if (is_binding) { 104 106 /* 105 107 * If we are in the process of binding a new channel 106 108 * to an existing session, use the master connection ··· 111 107 */ 112 108 memcpy(key, ses->smb3signingkey, SMB3_SIGN_KEY_SIZE); 113 109 spin_unlock(&ses->chan_lock); 110 + spin_unlock(&ses->ses_lock); 114 111 goto out; 115 112 } 116 113 ··· 124 119 if (chan->server == server) { 125 120 memcpy(key, chan->signkey, SMB3_SIGN_KEY_SIZE); 126 121 spin_unlock(&ses->chan_lock); 122 + spin_unlock(&ses->ses_lock); 127 123 goto out; 128 124 } 129 125 } 130 126 spin_unlock(&ses->chan_lock); 127 + spin_unlock(&ses->ses_lock); 131 128 132 129 cifs_dbg(VFS, 133 130 "%s: Could not find channel signing key for session 0x%llx\n", ··· 399 392 bool is_binding = false; 400 393 int chan_index = 0; 401 394 395 + spin_lock(&ses->ses_lock); 402 396 spin_lock(&ses->chan_lock); 403 - is_binding = !CIFS_ALL_CHANS_NEED_RECONNECT(ses); 397 + is_binding = (cifs_chan_needs_reconnect(ses, server) && 398 + ses->ses_status == SES_GOOD); 399 + 404 400 chan_index = cifs_ses_get_chan_index(ses, server); 405 401 /* TODO: introduce ref counting for channels when the can be freed */ 406 402 spin_unlock(&ses->chan_lock); 403 + spin_unlock(&ses->ses_lock); 407 404 408 405 /* 409 406 * All channels use the same encryption/decryption keys but
+8 -4
fs/cifs/trace.h
··· 701 701 TP_PROTO(unsigned int xid, 702 702 __u32 tid, 703 703 __u64 sesid, 704 + const char *full_path, 704 705 int create_options, 705 706 int desired_access), 706 - TP_ARGS(xid, tid, sesid, create_options, desired_access), 707 + TP_ARGS(xid, tid, sesid, full_path, create_options, desired_access), 707 708 TP_STRUCT__entry( 708 709 __field(unsigned int, xid) 709 710 __field(__u32, tid) 710 711 __field(__u64, sesid) 712 + __string(path, full_path) 711 713 __field(int, create_options) 712 714 __field(int, desired_access) 713 715 ), ··· 717 715 __entry->xid = xid; 718 716 __entry->tid = tid; 719 717 __entry->sesid = sesid; 718 + __assign_str(path, full_path); 720 719 __entry->create_options = create_options; 721 720 __entry->desired_access = desired_access; 722 721 ), 723 - TP_printk("xid=%u sid=0x%llx tid=0x%x cr_opts=0x%x des_access=0x%x", 724 - __entry->xid, __entry->sesid, __entry->tid, 722 + TP_printk("xid=%u sid=0x%llx tid=0x%x path=%s cr_opts=0x%x des_access=0x%x", 723 + __entry->xid, __entry->sesid, __entry->tid, __get_str(path), 725 724 __entry->create_options, __entry->desired_access) 726 725 ) 727 726 ··· 731 728 TP_PROTO(unsigned int xid, \ 732 729 __u32 tid, \ 733 730 __u64 sesid, \ 731 + const char *full_path, \ 734 732 int create_options, \ 735 733 int desired_access), \ 736 - TP_ARGS(xid, tid, sesid, create_options, desired_access)) 734 + TP_ARGS(xid, tid, sesid, full_path, create_options, desired_access)) 737 735 738 736 DEFINE_SMB3_OPEN_ENTER_EVENT(open_enter); 739 737 DEFINE_SMB3_OPEN_ENTER_EVENT(posix_mkdir_enter);