Skip to content

Commit

Permalink
Merge tag '6.9-rc-smb3-client-fixes-part1' of git://git.samba.org/sfr…
Browse files Browse the repository at this point in the history
…ench/cifs-2.6

Pull smb client updates from Steve French:

 - fix for folios/netfs data corruption in cifs_extend_writeback

 - additional tracepoint added

 - updates for special files and symlinks: improvements to allow
   selecting use of either WSL or NFS reparse point format on creating
   special files

 - allocation size improvement for cached files

 - minor cleanup patches

 - fix to allow changing the password on remount when password for the
   session is expired.

 - lease key related fixes: caching hardlinked files, deletes of
   deferred close files, and an important fix to better reuse lease keys
   for compound operations, which also can avoid lease break timeouts
   when low on credits

 - fix potential data corruption with write/readdir races

 - compression cleanups and a fix for compression headers

* tag '6.9-rc-smb3-client-fixes-part1' of git://git.samba.org/sfrench/cifs-2.6: (24 commits)
  cifs: update internal module version number for cifs.ko
  smb: common: simplify compression headers
  smb: common: fix fields sizes in compression_pattern_payload_v1
  smb: client: negotiate compression algorithms
  smb3: add dynamic trace point for ioctls
  cifs: Fix writeback data corruption
  smb: client: return reparse type in /proc/mounts
  smb: client: set correct d_type for reparse DFS/DFSR and mount point
  smb: client: parse uid, gid, mode and dev from WSL reparse points
  smb: client: introduce SMB2_OP_QUERY_WSL_EA
  smb: client: Fix a NULL vs IS_ERR() check in wsl_set_xattrs()
  smb: client: add support for WSL reparse points
  smb: client: reduce number of parameters in smb2_compound_op()
  smb: client: fix potential broken compound request
  smb: client: move most of reparse point handling code to common file
  smb: client: introduce reparse mount option
  smb: client: retry compound request without reusing lease
  smb: client: do not defer close open handles to deleted files
  smb: client: reuse file lease key in compound operations
  smb3: update allocation size more accurately on write completion
  ...
  • Loading branch information
Linus Torvalds committed Mar 13, 2024
2 parents 9d9539d + 3681fe1 commit 279d44c
Show file tree
Hide file tree
Showing 27 changed files with 1,565 additions and 707 deletions.
1 change: 1 addition & 0 deletions MAINTAINERS
Original file line number Diff line number Diff line change
Expand Up @@ -5255,6 +5255,7 @@ R: Paulo Alcantara <pc@manguebit.com> (DFS, global name space)
R: Ronnie Sahlberg <ronniesahlberg@gmail.com> (directory leases, sparse files)
R: Shyam Prasad N <sprasad@microsoft.com> (multichannel)
R: Tom Talpey <tom@talpey.com> (RDMA, smbdirect)
R: Bharath SM <bharathsm@microsoft.com> (deferred close, directory leases)
L: linux-cifs@vger.kernel.org
L: samba-technical@lists.samba.org (moderated for non-subscribers)
S: Supported
Expand Down
2 changes: 1 addition & 1 deletion fs/smb/client/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ cifs-y := trace.o cifsfs.o cifs_debug.o connect.o dir.o file.o \
smb2ops.o smb2maperror.o smb2transport.o \
smb2misc.o smb2pdu.o smb2inode.o smb2file.o cifsacl.o fs_context.o \
dns_resolve.o cifs_spnego_negtokeninit.asn1.o asn1.o \
namespace.o
namespace.o reparse.o

$(obj)/asn1.o: $(obj)/cifs_spnego_negtokeninit.asn1.h

Expand Down
34 changes: 28 additions & 6 deletions fs/smb/client/cifs_debug.c
Original file line number Diff line number Diff line change
Expand Up @@ -278,6 +278,24 @@ static int cifs_debug_files_proc_show(struct seq_file *m, void *v)
return 0;
}

static __always_inline const char *compression_alg_str(__le16 alg)
{
switch (alg) {
case SMB3_COMPRESS_NONE:
return "NONE";
case SMB3_COMPRESS_LZNT1:
return "LZNT1";
case SMB3_COMPRESS_LZ77:
return "LZ77";
case SMB3_COMPRESS_LZ77_HUFF:
return "LZ77-Huffman";
case SMB3_COMPRESS_PATTERN:
return "Pattern_V1";
default:
return "invalid";
}
}

static int cifs_debug_data_proc_show(struct seq_file *m, void *v)
{
struct mid_q_entry *mid_entry;
Expand Down Expand Up @@ -423,12 +441,6 @@ static int cifs_debug_data_proc_show(struct seq_file *m, void *v)
server->echo_credits,
server->oplock_credits,
server->dialect);
if (server->compress_algorithm == SMB3_COMPRESS_LZNT1)
seq_printf(m, " COMPRESS_LZNT1");
else if (server->compress_algorithm == SMB3_COMPRESS_LZ77)
seq_printf(m, " COMPRESS_LZ77");
else if (server->compress_algorithm == SMB3_COMPRESS_LZ77_HUFF)
seq_printf(m, " COMPRESS_LZ77_HUFF");
if (server->sign)
seq_printf(m, " signed");
if (server->posix_ext_supported)
Expand Down Expand Up @@ -460,6 +472,14 @@ static int cifs_debug_data_proc_show(struct seq_file *m, void *v)
server->leaf_fullpath);
}

seq_puts(m, "\nCompression: ");
if (!server->compression.requested)
seq_puts(m, "disabled on mount");
else if (server->compression.enabled)
seq_printf(m, "enabled (%s)", compression_alg_str(server->compression.alg));
else
seq_puts(m, "disabled (not supported by this server)");

seq_printf(m, "\n\n\tSessions: ");
i = 0;
list_for_each_entry(ses, &server->smb_ses_list, smb_ses_list) {
Expand Down Expand Up @@ -488,6 +508,8 @@ static int cifs_debug_data_proc_show(struct seq_file *m, void *v)
ses->ses_count, ses->serverOS, ses->serverNOS,
ses->capabilities, ses->ses_status);
}
if (ses->expired_pwd)
seq_puts(m, "password no longer valid ");
spin_unlock(&ses->ses_lock);

seq_printf(m, "\n\tSecurity type: %s ",
Expand Down
2 changes: 2 additions & 0 deletions fs/smb/client/cifsfs.c
Original file line number Diff line number Diff line change
Expand Up @@ -673,6 +673,8 @@ cifs_show_options(struct seq_file *s, struct dentry *root)
seq_printf(s, ",backupgid=%u",
from_kgid_munged(&init_user_ns,
cifs_sb->ctx->backupgid));
seq_show_option(s, "reparse",
cifs_reparse_type_str(cifs_sb->ctx->reparse_type));

seq_printf(s, ",rsize=%u", cifs_sb->ctx->rsize);
seq_printf(s, ",wsize=%u", cifs_sb->ctx->wsize);
Expand Down
4 changes: 2 additions & 2 deletions fs/smb/client/cifsfs.h
Original file line number Diff line number Diff line change
Expand Up @@ -152,6 +152,6 @@ extern const struct export_operations cifs_export_ops;
#endif /* CONFIG_CIFS_NFSD_EXPORT */

/* when changing internal version - update following two lines at same time */
#define SMB3_PRODUCT_BUILD 47
#define CIFS_VERSION "2.47"
#define SMB3_PRODUCT_BUILD 48
#define CIFS_VERSION "2.48"
#endif /* _CIFSFS_H */
61 changes: 45 additions & 16 deletions fs/smb/client/cifsglob.h
Original file line number Diff line number Diff line change
Expand Up @@ -153,6 +153,24 @@ enum securityEnum {
Kerberos, /* Kerberos via SPNEGO */
};

enum cifs_reparse_type {
CIFS_REPARSE_TYPE_NFS,
CIFS_REPARSE_TYPE_WSL,
CIFS_REPARSE_TYPE_DEFAULT = CIFS_REPARSE_TYPE_NFS,
};

static inline const char *cifs_reparse_type_str(enum cifs_reparse_type type)
{
switch (type) {
case CIFS_REPARSE_TYPE_NFS:
return "nfs";
case CIFS_REPARSE_TYPE_WSL:
return "wsl";
default:
return "unknown";
}
}

struct session_key {
unsigned int len;
char *response;
Expand Down Expand Up @@ -208,6 +226,10 @@ struct cifs_open_info_data {
struct reparse_posix_data *posix;
};
} reparse;
struct {
__u8 eas[SMB2_WSL_MAX_QUERY_EA_RESP_SIZE];
unsigned int eas_len;
} wsl;
char *symlink_target;
struct cifs_sid posix_owner;
struct cifs_sid posix_group;
Expand All @@ -217,19 +239,6 @@ struct cifs_open_info_data {
};
};

static inline bool cifs_open_data_reparse(struct cifs_open_info_data *data)
{
struct smb2_file_all_info *fi = &data->fi;
u32 attrs = le32_to_cpu(fi->Attributes);
bool ret;

ret = data->reparse_point || (attrs & ATTR_REPARSE);
if (ret)
attrs |= ATTR_REPARSE;
fi->Attributes = cpu_to_le32(attrs);
return ret;
}

/*
*****************************************************************
* Except the CIFS PDUs themselves all the
Expand Down Expand Up @@ -371,7 +380,8 @@ struct smb_version_operations {
struct cifs_open_info_data *data);
/* set size by path */
int (*set_path_size)(const unsigned int, struct cifs_tcon *,
const char *, __u64, struct cifs_sb_info *, bool);
const char *, __u64, struct cifs_sb_info *, bool,
struct dentry *);
/* set size by file handle */
int (*set_file_size)(const unsigned int, struct cifs_tcon *,
struct cifsFileInfo *, __u64, bool);
Expand Down Expand Up @@ -401,7 +411,7 @@ struct smb_version_operations {
struct cifs_sb_info *);
/* unlink file */
int (*unlink)(const unsigned int, struct cifs_tcon *, const char *,
struct cifs_sb_info *);
struct cifs_sb_info *, struct dentry *);
/* open, rename and delete file */
int (*rename_pending_delete)(const char *, struct dentry *,
const unsigned int);
Expand Down Expand Up @@ -759,7 +769,11 @@ struct TCP_Server_Info {
unsigned int max_write;
unsigned int min_offload;
unsigned int retrans;
__le16 compress_algorithm;
struct {
bool requested; /* "compress" mount option set*/
bool enabled; /* actually negotiated with server */
__le16 alg; /* preferred alg negotiated with server */
} compression;
__u16 signing_algorithm;
__le16 cipher_type;
/* save initital negprot hash */
Expand Down Expand Up @@ -1066,6 +1080,7 @@ struct cifs_ses {
enum securityEnum sectype; /* what security flavor was specified? */
bool sign; /* is signing required? */
bool domainAuto:1;
bool expired_pwd; /* track if access denied or expired pwd so can know if need to update */
unsigned int flags;
__u16 session_flags;
__u8 smb3signingkey[SMB3_SIGN_KEY_SIZE];
Expand Down Expand Up @@ -1379,6 +1394,7 @@ struct cifs_open_parms {
umode_t mode;
bool reconnect:1;
bool replay:1; /* indicates that this open is for a replay */
struct kvec *ea_cctx;
};

struct cifs_fid {
Expand Down Expand Up @@ -1420,6 +1436,7 @@ struct cifsFileInfo {
bool invalidHandle:1; /* file closed via session abend */
bool swapfile:1;
bool oplock_break_cancelled:1;
bool status_file_deleted:1; /* file has been deleted */
unsigned int oplock_epoch; /* epoch from the lease break */
__u32 oplock_level; /* oplock/lease level from the lease break */
int count;
Expand Down Expand Up @@ -2277,6 +2294,17 @@ static inline void cifs_sg_set_buf(struct sg_table *sgtable,
}
}

#define CIFS_OPARMS(_cifs_sb, _tcon, _path, _da, _cd, _co, _mode) \
((struct cifs_open_parms) { \
.tcon = _tcon, \
.path = _path, \
.desired_access = (_da), \
.disposition = (_cd), \
.create_options = cifs_create_options(_cifs_sb, (_co)), \
.mode = (_mode), \
.cifs_sb = _cifs_sb, \
})

struct smb2_compound_vars {
struct cifs_open_parms oparms;
struct kvec rsp_iov[MAX_COMPOUND];
Expand All @@ -2288,6 +2316,7 @@ struct smb2_compound_vars {
struct kvec close_iov;
struct smb2_file_rename_info rename_info;
struct smb2_file_link_info link_info;
struct kvec ea_iov;
};

#endif /* _CIFS_GLOB_H */
20 changes: 12 additions & 8 deletions fs/smb/client/cifsproto.h
Original file line number Diff line number Diff line change
Expand Up @@ -144,7 +144,8 @@ extern int cifs_reconnect(struct TCP_Server_Info *server,
extern int checkSMB(char *buf, unsigned int len, struct TCP_Server_Info *srvr);
extern bool is_valid_oplock_break(char *, struct TCP_Server_Info *);
extern bool backup_cred(struct cifs_sb_info *);
extern bool is_size_safe_to_change(struct cifsInodeInfo *, __u64 eof);
extern bool is_size_safe_to_change(struct cifsInodeInfo *cifsInode, __u64 eof,
bool from_readdir);
extern void cifs_update_eof(struct cifsInodeInfo *cifsi, loff_t offset,
unsigned int bytes_written);
extern struct cifsFileInfo *find_writable_file(struct cifsInodeInfo *, int);
Expand Down Expand Up @@ -201,17 +202,14 @@ extern void cifs_unix_basic_to_fattr(struct cifs_fattr *fattr,
struct cifs_sb_info *cifs_sb);
extern void cifs_dir_info_to_fattr(struct cifs_fattr *, FILE_DIRECTORY_INFO *,
struct cifs_sb_info *);
extern int cifs_fattr_to_inode(struct inode *inode, struct cifs_fattr *fattr);
extern int cifs_fattr_to_inode(struct inode *inode, struct cifs_fattr *fattr,
bool from_readdir);
extern struct inode *cifs_iget(struct super_block *sb,
struct cifs_fattr *fattr);

int cifs_get_inode_info(struct inode **inode, const char *full_path,
struct cifs_open_info_data *data, struct super_block *sb, int xid,
const struct cifs_fid *fid);
bool cifs_reparse_point_to_fattr(struct cifs_sb_info *cifs_sb,
struct cifs_fattr *fattr,
struct cifs_open_info_data *data);

extern int smb311_posix_get_inode_info(struct inode **inode,
const char *full_path,
struct cifs_open_info_data *data,
Expand Down Expand Up @@ -296,6 +294,10 @@ extern void cifs_close_all_deferred_files(struct cifs_tcon *cifs_tcon);

extern void cifs_close_deferred_file_under_dentry(struct cifs_tcon *cifs_tcon,
const char *path);

extern void cifs_mark_open_handles_for_deleted_file(struct inode *inode,
const char *path);

extern struct TCP_Server_Info *
cifs_get_tcp_session(struct smb3_fs_context *ctx,
struct TCP_Server_Info *primary_server);
Expand Down Expand Up @@ -402,7 +404,8 @@ extern int CIFSSMBSetFileDisposition(const unsigned int xid,
__u32 pid_of_opener);
extern int CIFSSMBSetEOF(const unsigned int xid, struct cifs_tcon *tcon,
const char *file_name, __u64 size,
struct cifs_sb_info *cifs_sb, bool set_allocation);
struct cifs_sb_info *cifs_sb, bool set_allocation,
struct dentry *dentry);
extern int CIFSSMBSetFileSize(const unsigned int xid, struct cifs_tcon *tcon,
struct cifsFileInfo *cfile, __u64 size,
bool set_allocation);
Expand Down Expand Up @@ -438,7 +441,8 @@ extern int CIFSPOSIXDelFile(const unsigned int xid, struct cifs_tcon *tcon,
const struct nls_table *nls_codepage,
int remap_special_chars);
extern int CIFSSMBDelFile(const unsigned int xid, struct cifs_tcon *tcon,
const char *name, struct cifs_sb_info *cifs_sb);
const char *name, struct cifs_sb_info *cifs_sb,
struct dentry *dentry);
int CIFSSMBRename(const unsigned int xid, struct cifs_tcon *tcon,
struct dentry *source_dentry,
const char *from_name, const char *to_name,
Expand Down
4 changes: 2 additions & 2 deletions fs/smb/client/cifssmb.c
Original file line number Diff line number Diff line change
Expand Up @@ -738,7 +738,7 @@ CIFSPOSIXDelFile(const unsigned int xid, struct cifs_tcon *tcon,

int
CIFSSMBDelFile(const unsigned int xid, struct cifs_tcon *tcon, const char *name,
struct cifs_sb_info *cifs_sb)
struct cifs_sb_info *cifs_sb, struct dentry *dentry)
{
DELETE_FILE_REQ *pSMB = NULL;
DELETE_FILE_RSP *pSMBr = NULL;
Expand Down Expand Up @@ -4993,7 +4993,7 @@ CIFSSMBQFSPosixInfo(const unsigned int xid, struct cifs_tcon *tcon,
int
CIFSSMBSetEOF(const unsigned int xid, struct cifs_tcon *tcon,
const char *file_name, __u64 size, struct cifs_sb_info *cifs_sb,
bool set_allocation)
bool set_allocation, struct dentry *dentry)
{
struct smb_com_transaction2_spi_req *pSMB = NULL;
struct smb_com_transaction2_spi_rsp *pSMBr = NULL;
Expand Down
4 changes: 3 additions & 1 deletion fs/smb/client/connect.c
Original file line number Diff line number Diff line change
Expand Up @@ -1736,7 +1736,7 @@ cifs_get_tcp_session(struct smb3_fs_context *ctx,
tcp_ses->channel_sequence_num = 0; /* only tracked for primary channel */
tcp_ses->reconnect_instance = 1;
tcp_ses->lstrp = jiffies;
tcp_ses->compress_algorithm = cpu_to_le16(ctx->compression);
tcp_ses->compression.requested = ctx->compress;
spin_lock_init(&tcp_ses->req_lock);
spin_lock_init(&tcp_ses->srv_lock);
spin_lock_init(&tcp_ses->mid_lock);
Expand Down Expand Up @@ -2803,6 +2803,8 @@ compare_mount_options(struct super_block *sb, struct cifs_mnt_data *mnt_data)
return 0;
if (old->ctx->closetimeo != new->ctx->closetimeo)
return 0;
if (old->ctx->reparse_type != new->ctx->reparse_type)
return 0;

return 1;
}
Expand Down
Loading

0 comments on commit 279d44c

Please sign in to comment.