Commit 5437f30d authored by Linus Torvalds's avatar Linus Torvalds

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

Pull more smb client updates from Steve French:

 - fix for potential null pointer use in init cifs

 - additional dynamic trace points to improve debugging of some common
   scenarios

 - two SMB1 fixes (one addressing reconnect with POSIX extensions, one a
   mount parsing error)

* tag '6.11-rc-smb-client-fixes-part2' of git://git.samba.org/sfrench/cifs-2.6:
  smb3: add dynamic trace point for session setup key expired failures
  smb3: add four dynamic tracepoints for copy_file_range and reflink
  smb3: add dynamic tracepoint for reflink errors
  cifs: mount with "unix" mount option for SMB1 incorrectly handled
  cifs: fix reconnect with SMB1 UNIX Extensions
  cifs: fix potential null pointer use in destroy_workqueue in init_cifs error path
parents 6342649c b6f6a7aa
...@@ -1894,12 +1894,12 @@ init_cifs(void) ...@@ -1894,12 +1894,12 @@ init_cifs(void)
WQ_FREEZABLE|WQ_MEM_RECLAIM, 0); WQ_FREEZABLE|WQ_MEM_RECLAIM, 0);
if (!serverclose_wq) { if (!serverclose_wq) {
rc = -ENOMEM; rc = -ENOMEM;
goto out_destroy_serverclose_wq; goto out_destroy_deferredclose_wq;
} }
rc = cifs_init_inodecache(); rc = cifs_init_inodecache();
if (rc) if (rc)
goto out_destroy_deferredclose_wq; goto out_destroy_serverclose_wq;
rc = cifs_init_netfs(); rc = cifs_init_netfs();
if (rc) if (rc)
...@@ -1967,6 +1967,8 @@ init_cifs(void) ...@@ -1967,6 +1967,8 @@ init_cifs(void)
cifs_destroy_netfs(); cifs_destroy_netfs();
out_destroy_inodecache: out_destroy_inodecache:
cifs_destroy_inodecache(); cifs_destroy_inodecache();
out_destroy_serverclose_wq:
destroy_workqueue(serverclose_wq);
out_destroy_deferredclose_wq: out_destroy_deferredclose_wq:
destroy_workqueue(deferredclose_wq); destroy_workqueue(deferredclose_wq);
out_destroy_cifsoplockd_wq: out_destroy_cifsoplockd_wq:
...@@ -1977,8 +1979,6 @@ init_cifs(void) ...@@ -1977,8 +1979,6 @@ init_cifs(void)
destroy_workqueue(decrypt_wq); destroy_workqueue(decrypt_wq);
out_destroy_cifsiod_wq: out_destroy_cifsiod_wq:
destroy_workqueue(cifsiod_wq); destroy_workqueue(cifsiod_wq);
out_destroy_serverclose_wq:
destroy_workqueue(serverclose_wq);
out_clean_proc: out_clean_proc:
cifs_proc_clean(); cifs_proc_clean();
return rc; return rc;
......
...@@ -2614,6 +2614,13 @@ cifs_get_tcon(struct cifs_ses *ses, struct smb3_fs_context *ctx) ...@@ -2614,6 +2614,13 @@ cifs_get_tcon(struct cifs_ses *ses, struct smb3_fs_context *ctx)
cifs_dbg(VFS, "Server does not support mounting with posix SMB3.11 extensions\n"); cifs_dbg(VFS, "Server does not support mounting with posix SMB3.11 extensions\n");
rc = -EOPNOTSUPP; rc = -EOPNOTSUPP;
goto out_fail; goto out_fail;
} else if (ses->server->vals->protocol_id == SMB10_PROT_ID)
if (cap_unix(ses))
cifs_dbg(FYI, "Unix Extensions requested on SMB1 mount\n");
else {
cifs_dbg(VFS, "SMB1 Unix Extensions not supported by server\n");
rc = -EOPNOTSUPP;
goto out_fail;
} else { } else {
cifs_dbg(VFS, cifs_dbg(VFS,
"Check vers= mount option. SMB3.11 disabled but required for POSIX extensions\n"); "Check vers= mount option. SMB3.11 disabled but required for POSIX extensions\n");
...@@ -3686,6 +3693,7 @@ int cifs_mount(struct cifs_sb_info *cifs_sb, struct smb3_fs_context *ctx) ...@@ -3686,6 +3693,7 @@ int cifs_mount(struct cifs_sb_info *cifs_sb, struct smb3_fs_context *ctx)
} }
#endif #endif
#ifdef CONFIG_CIFS_ALLOW_INSECURE_LEGACY
/* /*
* Issue a TREE_CONNECT request. * Issue a TREE_CONNECT request.
*/ */
...@@ -3807,11 +3815,25 @@ CIFSTCon(const unsigned int xid, struct cifs_ses *ses, ...@@ -3807,11 +3815,25 @@ CIFSTCon(const unsigned int xid, struct cifs_ses *ses,
else else
tcon->Flags = 0; tcon->Flags = 0;
cifs_dbg(FYI, "Tcon flags: 0x%x\n", tcon->Flags); cifs_dbg(FYI, "Tcon flags: 0x%x\n", tcon->Flags);
}
/*
* reset_cifs_unix_caps calls QFSInfo which requires
* need_reconnect to be false, but we would not need to call
* reset_caps if this were not a reconnect case so must check
* need_reconnect flag here. The caller will also clear
* need_reconnect when tcon was successful but needed to be
* cleared earlier in the case of unix extensions reconnect
*/
if (tcon->need_reconnect && tcon->unix_ext) {
cifs_dbg(FYI, "resetting caps for %s\n", tcon->tree_name);
tcon->need_reconnect = false;
reset_cifs_unix_caps(xid, tcon, NULL, NULL);
}
}
cifs_buf_release(smb_buffer); cifs_buf_release(smb_buffer);
return rc; return rc;
} }
#endif /* CONFIG_CIFS_ALLOW_INSECURE_LEGACY */
static void delayed_free(struct rcu_head *p) static void delayed_free(struct rcu_head *p)
{ {
......
...@@ -1812,6 +1812,10 @@ smb2_copychunk_range(const unsigned int xid, ...@@ -1812,6 +1812,10 @@ smb2_copychunk_range(const unsigned int xid,
tcon = tlink_tcon(trgtfile->tlink); tcon = tlink_tcon(trgtfile->tlink);
trace_smb3_copychunk_enter(xid, srcfile->fid.volatile_fid,
trgtfile->fid.volatile_fid, tcon->tid,
tcon->ses->Suid, src_off, dest_off, len);
while (len > 0) { while (len > 0) {
pcchunk->SourceOffset = cpu_to_le64(src_off); pcchunk->SourceOffset = cpu_to_le64(src_off);
pcchunk->TargetOffset = cpu_to_le64(dest_off); pcchunk->TargetOffset = cpu_to_le64(dest_off);
...@@ -1863,6 +1867,9 @@ smb2_copychunk_range(const unsigned int xid, ...@@ -1863,6 +1867,9 @@ smb2_copychunk_range(const unsigned int xid,
le32_to_cpu(retbuf->ChunksWritten), le32_to_cpu(retbuf->ChunksWritten),
le32_to_cpu(retbuf->ChunkBytesWritten), le32_to_cpu(retbuf->ChunkBytesWritten),
bytes_written); bytes_written);
trace_smb3_copychunk_done(xid, srcfile->fid.volatile_fid,
trgtfile->fid.volatile_fid, tcon->tid,
tcon->ses->Suid, src_off, dest_off, len);
} else if (rc == -EINVAL) { } else if (rc == -EINVAL) {
if (ret_data_len != sizeof(struct copychunk_ioctl_rsp)) if (ret_data_len != sizeof(struct copychunk_ioctl_rsp))
goto cchunk_out; goto cchunk_out;
...@@ -2046,7 +2053,9 @@ smb2_duplicate_extents(const unsigned int xid, ...@@ -2046,7 +2053,9 @@ smb2_duplicate_extents(const unsigned int xid,
dup_ext_buf.ByteCount = cpu_to_le64(len); dup_ext_buf.ByteCount = cpu_to_le64(len);
cifs_dbg(FYI, "Duplicate extents: src off %lld dst off %lld len %lld\n", cifs_dbg(FYI, "Duplicate extents: src off %lld dst off %lld len %lld\n",
src_off, dest_off, len); src_off, dest_off, len);
trace_smb3_clone_enter(xid, srcfile->fid.volatile_fid,
trgtfile->fid.volatile_fid, tcon->tid,
tcon->ses->Suid, src_off, dest_off, len);
inode = d_inode(trgtfile->dentry); inode = d_inode(trgtfile->dentry);
if (inode->i_size < dest_off + len) { if (inode->i_size < dest_off + len) {
rc = smb2_set_file_size(xid, tcon, trgtfile, dest_off + len, false); rc = smb2_set_file_size(xid, tcon, trgtfile, dest_off + len, false);
...@@ -2075,6 +2084,15 @@ smb2_duplicate_extents(const unsigned int xid, ...@@ -2075,6 +2084,15 @@ smb2_duplicate_extents(const unsigned int xid,
cifs_dbg(FYI, "Non-zero response length in duplicate extents\n"); cifs_dbg(FYI, "Non-zero response length in duplicate extents\n");
duplicate_extents_out: duplicate_extents_out:
if (rc)
trace_smb3_clone_err(xid, srcfile->fid.volatile_fid,
trgtfile->fid.volatile_fid,
tcon->tid, tcon->ses->Suid, src_off,
dest_off, len, rc);
else
trace_smb3_clone_done(xid, srcfile->fid.volatile_fid,
trgtfile->fid.volatile_fid, tcon->tid,
tcon->ses->Suid, src_off, dest_off, len);
return rc; return rc;
} }
......
...@@ -1562,8 +1562,14 @@ SMB2_sess_sendreceive(struct SMB2_sess_data *sess_data) ...@@ -1562,8 +1562,14 @@ SMB2_sess_sendreceive(struct SMB2_sess_data *sess_data)
cifs_small_buf_release(sess_data->iov[0].iov_base); cifs_small_buf_release(sess_data->iov[0].iov_base);
if (rc == 0) if (rc == 0)
sess_data->ses->expired_pwd = false; sess_data->ses->expired_pwd = false;
else if ((rc == -EACCES) || (rc == -EKEYEXPIRED) || (rc == -EKEYREVOKED)) else if ((rc == -EACCES) || (rc == -EKEYEXPIRED) || (rc == -EKEYREVOKED)) {
if (sess_data->ses->expired_pwd == false)
trace_smb3_key_expired(sess_data->server->hostname,
sess_data->ses->user_name,
sess_data->server->conn_id,
&sess_data->server->dstaddr, rc);
sess_data->ses->expired_pwd = true; sess_data->ses->expired_pwd = true;
}
memcpy(&sess_data->iov[0], &rsp_iov, sizeof(struct kvec)); memcpy(&sess_data->iov[0], &rsp_iov, sizeof(struct kvec));
......
...@@ -206,6 +206,116 @@ DEFINE_SMB3_OTHER_ERR_EVENT(query_dir_err); ...@@ -206,6 +206,116 @@ DEFINE_SMB3_OTHER_ERR_EVENT(query_dir_err);
DEFINE_SMB3_OTHER_ERR_EVENT(zero_err); DEFINE_SMB3_OTHER_ERR_EVENT(zero_err);
DEFINE_SMB3_OTHER_ERR_EVENT(falloc_err); DEFINE_SMB3_OTHER_ERR_EVENT(falloc_err);
/*
* For logging errors in reflink and copy_range ops e.g. smb2_copychunk_range
* and smb2_duplicate_extents
*/
DECLARE_EVENT_CLASS(smb3_copy_range_err_class,
TP_PROTO(unsigned int xid,
__u64 src_fid,
__u64 target_fid,
__u32 tid,
__u64 sesid,
__u64 src_offset,
__u64 target_offset,
__u32 len,
int rc),
TP_ARGS(xid, src_fid, target_fid, tid, sesid, src_offset, target_offset, len, rc),
TP_STRUCT__entry(
__field(unsigned int, xid)
__field(__u64, src_fid)
__field(__u64, target_fid)
__field(__u32, tid)
__field(__u64, sesid)
__field(__u64, src_offset)
__field(__u64, target_offset)
__field(__u32, len)
__field(int, rc)
),
TP_fast_assign(
__entry->xid = xid;
__entry->src_fid = src_fid;
__entry->target_fid = target_fid;
__entry->tid = tid;
__entry->sesid = sesid;
__entry->src_offset = src_offset;
__entry->target_offset = target_offset;
__entry->len = len;
__entry->rc = rc;
),
TP_printk("\txid=%u sid=0x%llx tid=0x%x source fid=0x%llx source offset=0x%llx target fid=0x%llx target offset=0x%llx len=0x%x rc=%d",
__entry->xid, __entry->sesid, __entry->tid, __entry->target_fid,
__entry->src_offset, __entry->target_fid, __entry->target_offset, __entry->len, __entry->rc)
)
#define DEFINE_SMB3_COPY_RANGE_ERR_EVENT(name) \
DEFINE_EVENT(smb3_copy_range_err_class, smb3_##name, \
TP_PROTO(unsigned int xid, \
__u64 src_fid, \
__u64 target_fid, \
__u32 tid, \
__u64 sesid, \
__u64 src_offset, \
__u64 target_offset, \
__u32 len, \
int rc), \
TP_ARGS(xid, src_fid, target_fid, tid, sesid, src_offset, target_offset, len, rc))
DEFINE_SMB3_COPY_RANGE_ERR_EVENT(clone_err);
/* TODO: Add SMB3_COPY_RANGE_ERR_EVENT(copychunk_err) */
DECLARE_EVENT_CLASS(smb3_copy_range_done_class,
TP_PROTO(unsigned int xid,
__u64 src_fid,
__u64 target_fid,
__u32 tid,
__u64 sesid,
__u64 src_offset,
__u64 target_offset,
__u32 len),
TP_ARGS(xid, src_fid, target_fid, tid, sesid, src_offset, target_offset, len),
TP_STRUCT__entry(
__field(unsigned int, xid)
__field(__u64, src_fid)
__field(__u64, target_fid)
__field(__u32, tid)
__field(__u64, sesid)
__field(__u64, src_offset)
__field(__u64, target_offset)
__field(__u32, len)
),
TP_fast_assign(
__entry->xid = xid;
__entry->src_fid = src_fid;
__entry->target_fid = target_fid;
__entry->tid = tid;
__entry->sesid = sesid;
__entry->src_offset = src_offset;
__entry->target_offset = target_offset;
__entry->len = len;
),
TP_printk("\txid=%u sid=0x%llx tid=0x%x source fid=0x%llx source offset=0x%llx target fid=0x%llx target offset=0x%llx len=0x%x",
__entry->xid, __entry->sesid, __entry->tid, __entry->target_fid,
__entry->src_offset, __entry->target_fid, __entry->target_offset, __entry->len)
)
#define DEFINE_SMB3_COPY_RANGE_DONE_EVENT(name) \
DEFINE_EVENT(smb3_copy_range_done_class, smb3_##name, \
TP_PROTO(unsigned int xid, \
__u64 src_fid, \
__u64 target_fid, \
__u32 tid, \
__u64 sesid, \
__u64 src_offset, \
__u64 target_offset, \
__u32 len), \
TP_ARGS(xid, src_fid, target_fid, tid, sesid, src_offset, target_offset, len))
DEFINE_SMB3_COPY_RANGE_DONE_EVENT(copychunk_enter);
DEFINE_SMB3_COPY_RANGE_DONE_EVENT(clone_enter);
DEFINE_SMB3_COPY_RANGE_DONE_EVENT(copychunk_done);
DEFINE_SMB3_COPY_RANGE_DONE_EVENT(clone_done);
/* For logging successful read or write */ /* For logging successful read or write */
DECLARE_EVENT_CLASS(smb3_rw_done_class, DECLARE_EVENT_CLASS(smb3_rw_done_class,
...@@ -1171,6 +1281,46 @@ DEFINE_EVENT(smb3_connect_err_class, smb3_##name, \ ...@@ -1171,6 +1281,46 @@ DEFINE_EVENT(smb3_connect_err_class, smb3_##name, \
DEFINE_SMB3_CONNECT_ERR_EVENT(connect_err); DEFINE_SMB3_CONNECT_ERR_EVENT(connect_err);
DECLARE_EVENT_CLASS(smb3_sess_setup_err_class,
TP_PROTO(char *hostname, char *username, __u64 conn_id,
const struct __kernel_sockaddr_storage *dst_addr, int rc),
TP_ARGS(hostname, username, conn_id, dst_addr, rc),
TP_STRUCT__entry(
__string(hostname, hostname)
__string(username, username)
__field(__u64, conn_id)
__array(__u8, dst_addr, sizeof(struct sockaddr_storage))
__field(int, rc)
),
TP_fast_assign(
struct sockaddr_storage *pss = NULL;
__entry->conn_id = conn_id;
__entry->rc = rc;
pss = (struct sockaddr_storage *)__entry->dst_addr;
*pss = *dst_addr;
__assign_str(hostname);
__assign_str(username);
),
TP_printk("rc=%d user=%s conn_id=0x%llx server=%s addr=%pISpsfc",
__entry->rc,
__get_str(username),
__entry->conn_id,
__get_str(hostname),
__entry->dst_addr)
)
#define DEFINE_SMB3_SES_SETUP_ERR_EVENT(name) \
DEFINE_EVENT(smb3_sess_setup_err_class, smb3_##name, \
TP_PROTO(char *hostname, \
char *username, \
__u64 conn_id, \
const struct __kernel_sockaddr_storage *addr, \
int rc), \
TP_ARGS(hostname, username, conn_id, addr, rc))
DEFINE_SMB3_SES_SETUP_ERR_EVENT(key_expired);
DECLARE_EVENT_CLASS(smb3_reconnect_class, DECLARE_EVENT_CLASS(smb3_reconnect_class,
TP_PROTO(__u64 currmid, TP_PROTO(__u64 currmid,
__u64 conn_id, __u64 conn_id,
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment