Import of kernel-5.14.0-687.38.1.el9_8

This commit is contained in:
almalinux-bot-kernel 2026-08-14 04:38:53 +00:00
parent d8f1f57754
commit 9a883d36ee
42 changed files with 848 additions and 525 deletions

View File

@ -12,7 +12,7 @@ RHEL_MINOR = 8
#
# Use this spot to avoid future merge conflicts.
# Do not trim this comment.
RHEL_RELEASE = 687.36.1
RHEL_RELEASE = 687.38.1
#
# ZSTREAM

View File

@ -697,9 +697,10 @@
#define MSR_AMD64_LBR_SELECT 0xc000010e
/* Zen4 */
#define MSR_ZEN4_BP_CFG 0xc001102e
#define MSR_ZEN4_BP_CFG 0xc001102e
#define MSR_ZEN4_BP_CFG_BP_SPEC_REDUCE_BIT 4
#define MSR_ZEN4_BP_CFG_SHARED_BTB_FIX_BIT 5
#define MSR_ZEN2_BP_CFG_BUG_FIX_BIT 33
/* Fam 19h MSRs */
#define MSR_F19H_UMC_PERF_CTL 0xc0010800

View File

@ -983,6 +983,9 @@ static void init_amd_zen2(struct cpuinfo_x86 *c)
init_spectral_chicken(c);
fix_erratum_1386(c);
zen2_zenbleed_check(c);
if (!cpu_has(c, X86_FEATURE_HYPERVISOR))
msr_set_bit(MSR_ZEN4_BP_CFG, MSR_ZEN2_BP_CFG_BUG_FIX_BIT);
}
static void init_amd_zen3(struct cpuinfo_x86 *c)

View File

@ -537,10 +537,13 @@ static void cxl_port_release(struct device *dev)
xa_destroy(&port->dports);
xa_destroy(&port->regions);
ida_free(&cxl_port_ida, port->id);
if (is_cxl_root(port))
if (is_cxl_root(port)) {
kfree(to_cxl_root(port));
else
} else {
put_device(dev->parent);
kfree(port);
}
}
static ssize_t decoders_committed_show(struct device *dev,
@ -708,6 +711,7 @@ static struct cxl_port *cxl_port_alloc(struct device *uport_dev,
struct cxl_port *iter;
dev->parent = &parent_port->dev;
get_device(dev->parent);
port->depth = parent_port->depth + 1;
port->parent_dport = parent_dport;

View File

@ -533,23 +533,16 @@ static void esw_update_vport_addr_list(struct mlx5_eswitch *esw,
struct mlx5_vport *vport, int list_type)
{
bool is_uc = list_type == MLX5_NVPRT_LIST_TYPE_UC;
u8 (*mac_list)[ETH_ALEN];
u8 (*mac_list)[ETH_ALEN] = NULL;
struct l2addr_node *node;
struct vport_addr *addr;
struct hlist_head *hash;
struct hlist_node *tmp;
int size;
int size = 0;
int err;
int hi;
int i;
size = is_uc ? MLX5_MAX_UC_PER_VPORT(esw->dev) :
MLX5_MAX_MC_PER_VPORT(esw->dev);
mac_list = kcalloc(size, ETH_ALEN, GFP_KERNEL);
if (!mac_list)
return;
hash = is_uc ? vport->uc_list : vport->mc_list;
for_each_l2hash_node(node, tmp, hash, hi) {
@ -561,7 +554,7 @@ static void esw_update_vport_addr_list(struct mlx5_eswitch *esw,
goto out;
err = mlx5_query_nic_vport_mac_list(esw->dev, vport->vport, list_type,
mac_list, &size);
&mac_list, &size);
if (err)
goto out;
esw_debug(esw->dev, "vport[%d] context update %s list size (%d)\n",

View File

@ -250,35 +250,63 @@ int mlx5_modify_nic_vport_mtu(struct mlx5_core_dev *mdev, u16 mtu)
}
EXPORT_SYMBOL_GPL(mlx5_modify_nic_vport_mtu);
static int mlx5_vport_max_mac_list_size(struct mlx5_core_dev *dev, u16 vport,
enum mlx5_list_type list_type)
{
void *query_ctx, *hca_caps;
int ret = 0;
if (!vport && !mlx5_core_is_ecpf(dev))
return list_type == MLX5_NVPRT_LIST_TYPE_UC ?
1 << MLX5_CAP_GEN(dev, log_max_current_uc_list) :
1 << MLX5_CAP_GEN(dev, log_max_current_mc_list);
query_ctx = kzalloc(MLX5_ST_SZ_BYTES(query_hca_cap_out), GFP_KERNEL);
if (!query_ctx)
return -ENOMEM;
ret = mlx5_vport_get_other_func_general_cap(dev, vport, query_ctx);
if (ret)
goto out;
hca_caps = MLX5_ADDR_OF(query_hca_cap_out, query_ctx, capability);
ret = list_type == MLX5_NVPRT_LIST_TYPE_UC ?
1 << MLX5_GET(cmd_hca_cap, hca_caps, log_max_current_uc_list) :
1 << MLX5_GET(cmd_hca_cap, hca_caps, log_max_current_mc_list);
out:
kfree(query_ctx);
return ret;
}
int mlx5_query_nic_vport_mac_list(struct mlx5_core_dev *dev,
u16 vport,
enum mlx5_list_type list_type,
u8 addr_list[][ETH_ALEN],
int *list_size)
u8 (**addr_list)[ETH_ALEN],
int *addr_list_size)
{
u32 in[MLX5_ST_SZ_DW(query_nic_vport_context_in)] = {0};
int allowed_list_size;
void *nic_vport_ctx;
int max_list_size;
int req_list_size;
int out_sz;
void *out;
int err;
int i;
req_list_size = *list_size;
if (!addr_list || !addr_list_size)
return -EINVAL;
max_list_size = list_type == MLX5_NVPRT_LIST_TYPE_UC ?
1 << MLX5_CAP_GEN(dev, log_max_current_uc_list) :
1 << MLX5_CAP_GEN(dev, log_max_current_mc_list);
*addr_list = NULL;
*addr_list_size = 0;
if (req_list_size > max_list_size) {
mlx5_core_warn(dev, "Requested list size (%d) > (%d) max_list_size\n",
req_list_size, max_list_size);
req_list_size = max_list_size;
}
max_list_size = mlx5_vport_max_mac_list_size(dev, vport, list_type);
if (max_list_size < 0)
return max_list_size;
out_sz = MLX5_ST_SZ_BYTES(query_nic_vport_context_out) +
req_list_size * MLX5_ST_SZ_BYTES(mac_address_layout);
max_list_size * MLX5_ST_SZ_BYTES(mac_address_layout);
out = kvzalloc(out_sz, GFP_KERNEL);
if (!out)
@ -297,16 +325,24 @@ int mlx5_query_nic_vport_mac_list(struct mlx5_core_dev *dev,
nic_vport_ctx = MLX5_ADDR_OF(query_nic_vport_context_out, out,
nic_vport_context);
req_list_size = MLX5_GET(nic_vport_context, nic_vport_ctx,
allowed_list_size);
allowed_list_size = MLX5_GET(nic_vport_context, nic_vport_ctx,
allowed_list_size);
if (!allowed_list_size)
goto out;
*list_size = req_list_size;
for (i = 0; i < req_list_size; i++) {
*addr_list = kcalloc(allowed_list_size, ETH_ALEN, GFP_KERNEL);
if (!*addr_list) {
err = -ENOMEM;
goto out;
}
for (i = 0; i < allowed_list_size; i++) {
u8 *mac_addr = MLX5_ADDR_OF(nic_vport_context,
nic_vport_ctx,
current_uc_mac_address[i]) + 2;
ether_addr_copy(addr_list[i], mac_addr);
ether_addr_copy((*addr_list)[i], mac_addr);
}
*addr_list_size = allowed_list_size;
out:
kvfree(out);
return err;

View File

@ -332,6 +332,13 @@ static int pkey_ioctl_verifyprotk(struct pkey_verifyprotk __user *uvp)
if (copy_from_user(&kvp, uvp, sizeof(kvp)))
return -EFAULT;
if (kvp.protkey.len > sizeof(kvp.protkey.protkey)) {
PKEY_DBF_ERR("%s protkey length %u exceeds protkey buffer size\n",
__func__, kvp.protkey.len);
memzero_explicit(&kvp, sizeof(kvp));
return -EINVAL;
}
keytype = pkey_aes_bitsize_to_keytype(8 * kvp.protkey.len);
if (!keytype) {
PKEY_DBF_ERR("%s unknown/unsupported protkey length %u\n",

View File

@ -257,6 +257,10 @@ static int pckmo_key2protkey(const u8 *key, u32 keylen,
goto out;
break;
}
if (t->len > *protkeylen) {
rc = -EINVAL;
goto out;
}
memcpy(protkey, t->protkey, t->len);
*protkeylen = t->len;
*protkeytype = t->keytype;

View File

@ -117,7 +117,7 @@ static const char *path_no_prefix(struct cifs_sb_info *cifs_sb,
if (!*path)
return path;
if ((cifs_sb->mnt_cifs_flags & CIFS_MOUNT_USE_PREFIX_PATH) &&
if ((cifs_sb_flags(cifs_sb) & CIFS_MOUNT_USE_PREFIX_PATH) &&
cifs_sb->prepath) {
len = strlen(cifs_sb->prepath) + 1;
if (unlikely(len > strlen(path)))

View File

@ -55,7 +55,7 @@ struct cifs_sb_info {
struct nls_table *local_nls;
struct smb3_fs_context *ctx;
atomic_t active;
unsigned int mnt_cifs_flags;
atomic_t mnt_cifs_flags;
struct delayed_work prune_tlinks;
struct rcu_head rcu;

View File

@ -122,11 +122,3 @@ struct smb3_notify_info {
#define CIFS_GOING_FLAGS_DEFAULT 0x0 /* going down */
#define CIFS_GOING_FLAGS_LOGFLUSH 0x1 /* flush log but not data */
#define CIFS_GOING_FLAGS_NOLOGFLUSH 0x2 /* don't flush log nor data */
static inline bool cifs_forced_shutdown(struct cifs_sb_info *sbi)
{
if (CIFS_MOUNT_SHUTDOWN & sbi->mnt_cifs_flags)
return true;
else
return false;
}

View File

@ -13,20 +13,6 @@
#include "cifsglob.h"
#include "cifs_debug.h"
int cifs_remap(struct cifs_sb_info *cifs_sb)
{
int map_type;
if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MAP_SFM_CHR)
map_type = SFM_MAP_UNI_RSVD;
else if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MAP_SPECIAL_CHR)
map_type = SFU_MAP_UNI_RSVD;
else
map_type = NO_MAP_UNI_RSVD;
return map_type;
}
/* Convert character using the SFU - "Services for Unix" remapping range */
static bool
convert_sfu_char(const __u16 src_char, char *target)

View File

@ -21,6 +21,7 @@
#include <asm/byteorder.h>
#include <linux/types.h>
#include <linux/nls.h>
#include "cifsglob.h"
#define UNIUPR_NOLOWER /* Example to not expand lower case tables */
@ -99,7 +100,6 @@ char *cifs_strndup_from_utf16(const char *src, const int maxlen,
const struct nls_table *codepage);
extern int cifsConvertToUTF16(__le16 *target, const char *source, int maxlen,
const struct nls_table *cp, int mapChars);
extern int cifs_remap(struct cifs_sb_info *cifs_sb);
extern __le16 *cifs_strndup_to_utf16(const char *src, const int maxlen,
int *utf16_len, const struct nls_table *cp,
int remap);
@ -398,4 +398,16 @@ UniStrlwr(register wchar_t *upin)
#endif
static inline int cifs_remap(const struct cifs_sb_info *cifs_sb)
{
unsigned int sbflags = cifs_sb_flags(cifs_sb);
if (sbflags & CIFS_MOUNT_MAP_SFM_CHR)
return SFM_MAP_UNI_RSVD;
if (sbflags & CIFS_MOUNT_MAP_SPECIAL_CHR)
return SFU_MAP_UNI_RSVD;
return NO_MAP_UNI_RSVD;
}
#endif /* _CIFS_UNICODE_H */

View File

@ -355,7 +355,7 @@ sid_to_id(struct cifs_sb_info *cifs_sb, struct smb_sid *psid,
return -EIO;
}
if ((cifs_sb->mnt_cifs_flags & CIFS_MOUNT_UID_FROM_ACL) ||
if ((cifs_sb_flags(cifs_sb) & CIFS_MOUNT_UID_FROM_ACL) ||
(cifs_sb_master_tcon(cifs_sb)->posix_extensions)) {
uint32_t unix_id;
bool is_group;
@ -1685,7 +1685,8 @@ id_mode_to_cifs_acl(struct inode *inode, const char *path, __u64 *pnmode,
struct smb_acl *dacl_ptr = NULL;
struct smb_ntsd *pntsd = NULL; /* acl obtained from server */
struct smb_ntsd *pnntsd = NULL; /* modified acl to be sent to server */
struct cifs_sb_info *cifs_sb = CIFS_SB(inode->i_sb);
struct cifs_sb_info *cifs_sb = CIFS_SB(inode);
unsigned int sbflags;
struct tcon_link *tlink;
struct smb_version_operations *ops;
bool mode_from_sid, id_from_sid;
@ -1716,15 +1717,9 @@ id_mode_to_cifs_acl(struct inode *inode, const char *path, __u64 *pnmode,
return rc;
}
if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MODE_FROM_SID)
mode_from_sid = true;
else
mode_from_sid = false;
if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_UID_FROM_ACL)
id_from_sid = true;
else
id_from_sid = false;
sbflags = cifs_sb_flags(cifs_sb);
mode_from_sid = sbflags & CIFS_MOUNT_MODE_FROM_SID;
id_from_sid = sbflags & CIFS_MOUNT_UID_FROM_ACL;
/* Potentially, five new ACEs can be added to the ACL for U,G,O mapping */
if (pnmode && *pnmode != NO_CHANGE_64) { /* chmod */

View File

@ -226,16 +226,18 @@ cifs_sb_deactive(struct super_block *sb)
static int
cifs_read_super(struct super_block *sb)
{
struct inode *inode;
struct cifs_sb_info *cifs_sb;
struct cifs_tcon *tcon;
unsigned int sbflags;
struct timespec64 ts;
struct inode *inode;
int rc = 0;
cifs_sb = CIFS_SB(sb);
tcon = cifs_sb_master_tcon(cifs_sb);
sbflags = cifs_sb_flags(cifs_sb);
if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_POSIXACL)
if (sbflags & CIFS_MOUNT_POSIXACL)
sb->s_flags |= SB_POSIXACL;
if (tcon->snapshot_time)
@ -311,7 +313,7 @@ cifs_read_super(struct super_block *sb)
}
#ifdef CONFIG_CIFS_NFSD_EXPORT
if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_SERVER_INUM) {
if (sbflags & CIFS_MOUNT_SERVER_INUM) {
cifs_dbg(FYI, "export ops supported\n");
sb->s_export_op = &cifs_export_ops;
}
@ -389,8 +391,7 @@ statfs_out:
static long cifs_fallocate(struct file *file, int mode, loff_t off, loff_t len)
{
struct cifs_sb_info *cifs_sb = CIFS_FILE_SB(file);
struct cifs_tcon *tcon = cifs_sb_master_tcon(cifs_sb);
struct cifs_tcon *tcon = cifs_sb_master_tcon(CIFS_SB(file));
struct TCP_Server_Info *server = tcon->ses->server;
struct inode *inode = file_inode(file);
int rc;
@ -416,11 +417,9 @@ out_unlock:
static int cifs_permission(struct mnt_idmap *idmap,
struct inode *inode, int mask)
{
struct cifs_sb_info *cifs_sb;
unsigned int sbflags = cifs_sb_flags(CIFS_SB(inode));
cifs_sb = CIFS_SB(inode->i_sb);
if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_NO_PERM) {
if (sbflags & CIFS_MOUNT_NO_PERM) {
if ((mask & MAY_EXEC) && !execute_ok(inode))
return -EACCES;
else
@ -449,6 +448,7 @@ cifs_alloc_inode(struct super_block *sb)
return NULL;
cifs_inode->cifsAttrs = ATTR_ARCHIVE; /* default */
cifs_inode->time = 0;
cifs_inode->time_last_write = 0;
/*
* Until the file is open and we have gotten oplock info back from the
* server, can not assume caching of file data or metadata.
@ -561,15 +561,17 @@ cifs_show_security(struct seq_file *s, struct cifs_ses *ses)
static void
cifs_show_cache_flavor(struct seq_file *s, struct cifs_sb_info *cifs_sb)
{
unsigned int sbflags = cifs_sb_flags(cifs_sb);
seq_puts(s, ",cache=");
if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_STRICT_IO)
if (sbflags & CIFS_MOUNT_STRICT_IO)
seq_puts(s, "strict");
else if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_DIRECT_IO)
else if (sbflags & CIFS_MOUNT_DIRECT_IO)
seq_puts(s, "none");
else if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_RW_CACHE)
else if (sbflags & CIFS_MOUNT_RW_CACHE)
seq_puts(s, "singleclient"); /* assume only one client access */
else if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_RO_CACHE)
else if (sbflags & CIFS_MOUNT_RO_CACHE)
seq_puts(s, "ro"); /* read only caching assumed */
else
seq_puts(s, "loose");
@ -630,6 +632,8 @@ cifs_show_options(struct seq_file *s, struct dentry *root)
struct cifs_sb_info *cifs_sb = CIFS_SB(root->d_sb);
struct cifs_tcon *tcon = cifs_sb_master_tcon(cifs_sb);
struct sockaddr *srcaddr;
unsigned int sbflags;
srcaddr = (struct sockaddr *)&tcon->ses->server->srcaddr;
seq_show_option(s, "vers", tcon->ses->server->vals->version_string);
@ -663,16 +667,17 @@ cifs_show_options(struct seq_file *s, struct dentry *root)
(int)(srcaddr->sa_family));
}
sbflags = cifs_sb_flags(cifs_sb);
seq_printf(s, ",uid=%u",
from_kuid_munged(&init_user_ns, cifs_sb->ctx->linux_uid));
if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_OVERR_UID)
if (sbflags & CIFS_MOUNT_OVERR_UID)
seq_puts(s, ",forceuid");
else
seq_puts(s, ",noforceuid");
seq_printf(s, ",gid=%u",
from_kgid_munged(&init_user_ns, cifs_sb->ctx->linux_gid));
if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_OVERR_GID)
if (sbflags & CIFS_MOUNT_OVERR_GID)
seq_puts(s, ",forcegid");
else
seq_puts(s, ",noforcegid");
@ -715,53 +720,53 @@ cifs_show_options(struct seq_file *s, struct dentry *root)
seq_puts(s, ",unix");
else
seq_puts(s, ",nounix");
if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_NO_DFS)
if (sbflags & CIFS_MOUNT_NO_DFS)
seq_puts(s, ",nodfs");
if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_POSIX_PATHS)
if (sbflags & CIFS_MOUNT_POSIX_PATHS)
seq_puts(s, ",posixpaths");
if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_SET_UID)
if (sbflags & CIFS_MOUNT_SET_UID)
seq_puts(s, ",setuids");
if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_UID_FROM_ACL)
if (sbflags & CIFS_MOUNT_UID_FROM_ACL)
seq_puts(s, ",idsfromsid");
if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_SERVER_INUM)
if (sbflags & CIFS_MOUNT_SERVER_INUM)
seq_puts(s, ",serverino");
if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_RWPIDFORWARD)
if (sbflags & CIFS_MOUNT_RWPIDFORWARD)
seq_puts(s, ",rwpidforward");
if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_NOPOSIXBRL)
if (sbflags & CIFS_MOUNT_NOPOSIXBRL)
seq_puts(s, ",forcemand");
if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_NO_XATTR)
if (sbflags & CIFS_MOUNT_NO_XATTR)
seq_puts(s, ",nouser_xattr");
if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MAP_SPECIAL_CHR)
if (sbflags & CIFS_MOUNT_MAP_SPECIAL_CHR)
seq_puts(s, ",mapchars");
if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MAP_SFM_CHR)
if (sbflags & CIFS_MOUNT_MAP_SFM_CHR)
seq_puts(s, ",mapposix");
if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_UNX_EMUL)
if (sbflags & CIFS_MOUNT_UNX_EMUL)
seq_puts(s, ",sfu");
if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_NO_BRL)
if (sbflags & CIFS_MOUNT_NO_BRL)
seq_puts(s, ",nobrl");
if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_NO_HANDLE_CACHE)
if (sbflags & CIFS_MOUNT_NO_HANDLE_CACHE)
seq_puts(s, ",nohandlecache");
if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MODE_FROM_SID)
if (sbflags & CIFS_MOUNT_MODE_FROM_SID)
seq_puts(s, ",modefromsid");
if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_CIFS_ACL)
if (sbflags & CIFS_MOUNT_CIFS_ACL)
seq_puts(s, ",cifsacl");
if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_DYNPERM)
if (sbflags & CIFS_MOUNT_DYNPERM)
seq_puts(s, ",dynperm");
if (root->d_sb->s_flags & SB_POSIXACL)
seq_puts(s, ",acl");
if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MF_SYMLINKS)
if (sbflags & CIFS_MOUNT_MF_SYMLINKS)
seq_puts(s, ",mfsymlinks");
if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_FSCACHE)
if (sbflags & CIFS_MOUNT_FSCACHE)
seq_puts(s, ",fsc");
if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_NOSSYNC)
if (sbflags & CIFS_MOUNT_NOSSYNC)
seq_puts(s, ",nostrictsync");
if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_NO_PERM)
if (sbflags & CIFS_MOUNT_NO_PERM)
seq_puts(s, ",noperm");
if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_CIFS_BACKUPUID)
if (sbflags & CIFS_MOUNT_CIFS_BACKUPUID)
seq_printf(s, ",backupuid=%u",
from_kuid_munged(&init_user_ns,
cifs_sb->ctx->backupuid));
if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_CIFS_BACKUPGID)
if (sbflags & CIFS_MOUNT_CIFS_BACKUPGID)
seq_printf(s, ",backupgid=%u",
from_kgid_munged(&init_user_ns,
cifs_sb->ctx->backupgid));
@ -903,10 +908,10 @@ static int cifs_write_inode(struct inode *inode, struct writeback_control *wbc)
static int cifs_drop_inode(struct inode *inode)
{
struct cifs_sb_info *cifs_sb = CIFS_SB(inode->i_sb);
unsigned int sbflags = cifs_sb_flags(CIFS_SB(inode));
/* no serverino => unconditional eviction */
return !(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_SERVER_INUM) ||
return !(sbflags & CIFS_MOUNT_SERVER_INUM) ||
generic_drop_inode(inode);
}
@ -944,7 +949,7 @@ cifs_get_root(struct smb3_fs_context *ctx, struct super_block *sb)
char *s, *p;
char sep;
if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_USE_PREFIX_PATH)
if (cifs_sb_flags(cifs_sb) & CIFS_MOUNT_USE_PREFIX_PATH)
return dget(sb->s_root);
full_path = cifs_build_path_to_root(ctx, cifs_sb,

View File

@ -1635,6 +1635,7 @@ struct cifsInodeInfo {
spinlock_t writers_lock;
unsigned int writers; /* Number of writers on this inode */
unsigned long time; /* jiffies of last update of inode */
unsigned long time_last_write; /* jiffies of last writable close or truncate */
u64 uniqueid; /* server inode number */
u64 createtime; /* creation time on server */
__u8 lease_key[SMB2_LEASE_KEY_SIZE]; /* lease key for this inode */
@ -1651,24 +1652,59 @@ CIFS_I(struct inode *inode)
return container_of(inode, struct cifsInodeInfo, netfs.inode);
}
static inline struct cifs_sb_info *
CIFS_SB(struct super_block *sb)
static inline void *cinode_to_fsinfo(struct cifsInodeInfo *cinode)
{
return cinode->netfs.inode.i_sb->s_fs_info;
}
static inline void *super_to_fsinfo(struct super_block *sb)
{
return sb->s_fs_info;
}
static inline struct cifs_sb_info *
CIFS_FILE_SB(struct file *file)
static inline void *inode_to_fsinfo(struct inode *inode)
{
return CIFS_SB(file_inode(file)->i_sb);
return inode->i_sb->s_fs_info;
}
static inline void *file_to_fsinfo(struct file *file)
{
return file_inode(file)->i_sb->s_fs_info;
}
static inline void *dentry_to_fsinfo(struct dentry *dentry)
{
return dentry->d_sb->s_fs_info;
}
static inline void *const_dentry_to_fsinfo(const struct dentry *dentry)
{
return dentry->d_sb->s_fs_info;
}
#define CIFS_SB(_ptr) \
((struct cifs_sb_info *) \
_Generic((_ptr), \
struct cifsInodeInfo * : cinode_to_fsinfo, \
const struct dentry * : const_dentry_to_fsinfo, \
struct super_block * : super_to_fsinfo, \
struct dentry * : dentry_to_fsinfo, \
struct inode * : inode_to_fsinfo, \
struct file * : file_to_fsinfo)(_ptr))
/*
* Use atomic_t for @cifs_sb->mnt_cifs_flags as it is currently accessed
* locklessly and may be changed concurrently by mount/remount and reconnect
* paths.
*/
static inline unsigned int cifs_sb_flags(const struct cifs_sb_info *cifs_sb)
{
return atomic_read(&cifs_sb->mnt_cifs_flags);
}
static inline char CIFS_DIR_SEP(const struct cifs_sb_info *cifs_sb)
{
if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_POSIX_PATHS)
return '/';
else
return '\\';
return (cifs_sb_flags(cifs_sb) & CIFS_MOUNT_POSIX_PATHS) ? '/' : '\\';
}
static inline void
@ -2448,9 +2484,8 @@ static inline bool __cifs_cache_state_check(struct cifsInodeInfo *cinode,
unsigned int oplock_flags,
unsigned int sb_flags)
{
struct cifs_sb_info *cifs_sb = CIFS_SB(cinode->netfs.inode.i_sb);
unsigned int sflags = cifs_sb_flags(CIFS_SB(cinode));
unsigned int oplock = READ_ONCE(cinode->oplock);
unsigned int sflags = cifs_sb->mnt_cifs_flags;
return (oplock & oplock_flags) || (sflags & sb_flags);
}
@ -2470,4 +2505,9 @@ static inline void cifs_reset_oplock(struct cifsInodeInfo *cinode)
WRITE_ONCE(cinode->oplock, 0);
}
static inline bool cifs_forced_shutdown(const struct cifs_sb_info *sbi)
{
return cifs_sb_flags(sbi) & CIFS_MOUNT_SHUTDOWN;
}
#endif /* _CIFS_GLOB_H */

View File

@ -2918,8 +2918,8 @@ compare_mount_options(struct super_block *sb, struct cifs_mnt_data *mnt_data)
{
struct cifs_sb_info *old = CIFS_SB(sb);
struct cifs_sb_info *new = mnt_data->cifs_sb;
unsigned int oldflags = old->mnt_cifs_flags & CIFS_MOUNT_MASK;
unsigned int newflags = new->mnt_cifs_flags & CIFS_MOUNT_MASK;
unsigned int oldflags = cifs_sb_flags(old) & CIFS_MOUNT_MASK;
unsigned int newflags = cifs_sb_flags(new) & CIFS_MOUNT_MASK;
if ((sb->s_flags & CIFS_MS_MASK) != (mnt_data->flags & CIFS_MS_MASK))
return 0;
@ -2974,9 +2974,9 @@ static int match_prepath(struct super_block *sb,
struct smb3_fs_context *ctx = mnt_data->ctx;
struct cifs_sb_info *old = CIFS_SB(sb);
struct cifs_sb_info *new = mnt_data->cifs_sb;
bool old_set = (old->mnt_cifs_flags & CIFS_MOUNT_USE_PREFIX_PATH) &&
bool old_set = (cifs_sb_flags(old) & CIFS_MOUNT_USE_PREFIX_PATH) &&
old->prepath;
bool new_set = (new->mnt_cifs_flags & CIFS_MOUNT_USE_PREFIX_PATH) &&
bool new_set = (cifs_sb_flags(new) & CIFS_MOUNT_USE_PREFIX_PATH) &&
new->prepath;
if (tcon->origin_fullpath &&
@ -3007,7 +3007,7 @@ cifs_match_super(struct super_block *sb, void *data)
cifs_sb = CIFS_SB(sb);
/* We do not want to use a superblock that has been shutdown */
if (CIFS_MOUNT_SHUTDOWN & cifs_sb->mnt_cifs_flags) {
if (cifs_forced_shutdown(cifs_sb)) {
spin_unlock(&cifs_tcp_ses_lock);
return 0;
}
@ -3534,18 +3534,20 @@ void reset_cifs_unix_caps(unsigned int xid, struct cifs_tcon *tcon,
cap &= ~CIFS_UNIX_POSIX_ACL_CAP;
else if (CIFS_UNIX_POSIX_ACL_CAP & cap) {
cifs_dbg(FYI, "negotiated posix acl support\n");
if (cifs_sb)
cifs_sb->mnt_cifs_flags |=
CIFS_MOUNT_POSIXACL;
if (cifs_sb) {
atomic_or(CIFS_MOUNT_POSIXACL,
&cifs_sb->mnt_cifs_flags);
}
}
if (ctx && ctx->posix_paths == 0)
cap &= ~CIFS_UNIX_POSIX_PATHNAMES_CAP;
else if (cap & CIFS_UNIX_POSIX_PATHNAMES_CAP) {
cifs_dbg(FYI, "negotiate posix pathnames\n");
if (cifs_sb)
cifs_sb->mnt_cifs_flags |=
CIFS_MOUNT_POSIX_PATHS;
if (cifs_sb) {
atomic_or(CIFS_MOUNT_POSIX_PATHS,
&cifs_sb->mnt_cifs_flags);
}
}
cifs_dbg(FYI, "Negotiate caps 0x%x\n", (int)cap);
@ -3583,6 +3585,8 @@ void reset_cifs_unix_caps(unsigned int xid, struct cifs_tcon *tcon,
int cifs_setup_cifs_sb(struct cifs_sb_info *cifs_sb)
{
struct smb3_fs_context *ctx = cifs_sb->ctx;
unsigned int sbflags;
int rc = 0;
INIT_DELAYED_WORK(&cifs_sb->prune_tlinks, cifs_prune_tlinks);
INIT_LIST_HEAD(&cifs_sb->tcon_sb_link);
@ -3607,17 +3611,16 @@ int cifs_setup_cifs_sb(struct cifs_sb_info *cifs_sb)
}
ctx->local_nls = cifs_sb->local_nls;
smb3_update_mnt_flags(cifs_sb);
sbflags = smb3_update_mnt_flags(cifs_sb);
if (ctx->direct_io)
cifs_dbg(FYI, "mounting share using direct i/o\n");
if (ctx->cache_ro) {
cifs_dbg(VFS, "mounting share with read only caching. Ensure that the share will not be modified while in use.\n");
cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_RO_CACHE;
sbflags |= CIFS_MOUNT_RO_CACHE;
} else if (ctx->cache_rw) {
cifs_dbg(VFS, "mounting share in single client RW caching mode. Ensure that no other systems will be accessing the share.\n");
cifs_sb->mnt_cifs_flags |= (CIFS_MOUNT_RO_CACHE |
CIFS_MOUNT_RW_CACHE);
sbflags |= CIFS_MOUNT_RO_CACHE | CIFS_MOUNT_RW_CACHE;
}
if ((ctx->cifs_acl) && (ctx->dynperm))
@ -3626,16 +3629,19 @@ int cifs_setup_cifs_sb(struct cifs_sb_info *cifs_sb)
if (ctx->prepath) {
cifs_sb->prepath = kstrdup(ctx->prepath, GFP_KERNEL);
if (cifs_sb->prepath == NULL)
return -ENOMEM;
cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_USE_PREFIX_PATH;
rc = -ENOMEM;
else
sbflags |= CIFS_MOUNT_USE_PREFIX_PATH;
}
return 0;
atomic_set(&cifs_sb->mnt_cifs_flags, sbflags);
return rc;
}
/* Release all succeed connections */
void cifs_mount_put_conns(struct cifs_mount_ctx *mnt_ctx)
{
struct cifs_sb_info *cifs_sb = mnt_ctx->cifs_sb;
int rc = 0;
if (mnt_ctx->tcon)
@ -3647,7 +3653,7 @@ void cifs_mount_put_conns(struct cifs_mount_ctx *mnt_ctx)
mnt_ctx->ses = NULL;
mnt_ctx->tcon = NULL;
mnt_ctx->server = NULL;
mnt_ctx->cifs_sb->mnt_cifs_flags &= ~CIFS_MOUNT_POSIX_PATHS;
atomic_andnot(CIFS_MOUNT_POSIX_PATHS, &cifs_sb->mnt_cifs_flags);
free_xid(mnt_ctx->xid);
}
@ -3701,15 +3707,18 @@ out:
int cifs_mount_get_tcon(struct cifs_mount_ctx *mnt_ctx)
{
struct TCP_Server_Info *server;
struct cifs_tcon *tcon = NULL;
struct cifs_sb_info *cifs_sb;
struct smb3_fs_context *ctx;
struct cifs_tcon *tcon = NULL;
unsigned int sbflags;
int rc = 0;
if (WARN_ON_ONCE(!mnt_ctx || !mnt_ctx->server || !mnt_ctx->ses || !mnt_ctx->fs_ctx ||
!mnt_ctx->cifs_sb)) {
rc = -EINVAL;
goto out;
if (WARN_ON_ONCE(!mnt_ctx))
return -EINVAL;
if (WARN_ON_ONCE(!mnt_ctx->server || !mnt_ctx->ses ||
!mnt_ctx->fs_ctx || !mnt_ctx->cifs_sb)) {
mnt_ctx->tcon = NULL;
return -EINVAL;
}
server = mnt_ctx->server;
ctx = mnt_ctx->fs_ctx;
@ -3728,9 +3737,10 @@ int cifs_mount_get_tcon(struct cifs_mount_ctx *mnt_ctx)
* path (i.e., do not remap / and \ and do not map any special characters)
*/
if (tcon->posix_extensions) {
cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_POSIX_PATHS;
cifs_sb->mnt_cifs_flags &= ~(CIFS_MOUNT_MAP_SFM_CHR |
CIFS_MOUNT_MAP_SPECIAL_CHR);
atomic_or(CIFS_MOUNT_POSIX_PATHS, &cifs_sb->mnt_cifs_flags);
atomic_andnot(CIFS_MOUNT_MAP_SFM_CHR |
CIFS_MOUNT_MAP_SPECIAL_CHR,
&cifs_sb->mnt_cifs_flags);
}
#ifdef CONFIG_CIFS_ALLOW_INSECURE_LEGACY
@ -3754,15 +3764,15 @@ int cifs_mount_get_tcon(struct cifs_mount_ctx *mnt_ctx)
#endif /* CONFIG_CIFS_ALLOW_INSECURE_LEGACY */
tcon->unix_ext = 0; /* server does not support them */
sbflags = cifs_sb_flags(cifs_sb);
/* do not care if a following call succeed - informational */
if (!tcon->pipe && server->ops->qfs_tcon) {
server->ops->qfs_tcon(mnt_ctx->xid, tcon, cifs_sb);
if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_RO_CACHE) {
if (sbflags & CIFS_MOUNT_RO_CACHE) {
if (tcon->fsDevInfo.DeviceCharacteristics &
cpu_to_le32(FILE_READ_ONLY_DEVICE))
cifs_dbg(VFS, "mounted to read only share\n");
else if ((cifs_sb->mnt_cifs_flags &
CIFS_MOUNT_RW_CACHE) == 0)
else if (!(sbflags & CIFS_MOUNT_RW_CACHE))
cifs_dbg(VFS, "read only mount of RW share\n");
/* no need to log a RW mount of a typical RW share */
}
@ -3774,7 +3784,7 @@ int cifs_mount_get_tcon(struct cifs_mount_ctx *mnt_ctx)
* Inside cifs_fscache_get_super_cookie it checks
* that we do not get super cookie twice.
*/
if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_FSCACHE)
if (sbflags & CIFS_MOUNT_FSCACHE)
cifs_fscache_get_super_cookie(tcon);
out:
@ -3897,7 +3907,8 @@ int cifs_is_path_remote(struct cifs_mount_ctx *mnt_ctx)
cifs_sb, full_path, tcon->Flags & SMB_SHARE_IS_IN_DFS);
if (rc != 0) {
cifs_server_dbg(VFS, "cannot query dirs between root and final path, enabling CIFS_MOUNT_USE_PREFIX_PATH\n");
cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_USE_PREFIX_PATH;
atomic_or(CIFS_MOUNT_USE_PREFIX_PATH,
&cifs_sb->mnt_cifs_flags);
rc = 0;
}
}
@ -3928,7 +3939,7 @@ int cifs_mount(struct cifs_sb_info *cifs_sb, struct smb3_fs_context *ctx)
* Force the use of prefix path to support failover on DFS paths that resolve to targets
* that have different prefix paths.
*/
cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_USE_PREFIX_PATH;
atomic_or(CIFS_MOUNT_USE_PREFIX_PATH, &cifs_sb->mnt_cifs_flags);
kfree(cifs_sb->prepath);
cifs_sb->prepath = ctx->prepath;
ctx->prepath = NULL;
@ -4548,7 +4559,7 @@ cifs_sb_tlink(struct cifs_sb_info *cifs_sb)
kuid_t fsuid = current_fsuid();
int err;
if (!(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MULTIUSER))
if (!(cifs_sb_flags(cifs_sb) & CIFS_MOUNT_MULTIUSER))
return cifs_get_tlink(cifs_sb_master_tlink(cifs_sb));
spin_lock(&cifs_sb->tlink_tree_lock);

View File

@ -1333,7 +1333,7 @@ int dfs_cache_remount_fs(struct cifs_sb_info *cifs_sb)
* Force the use of prefix path to support failover on DFS paths that resolve to targets
* that have different prefix paths.
*/
cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_USE_PREFIX_PATH;
atomic_or(CIFS_MOUNT_USE_PREFIX_PATH, &cifs_sb->mnt_cifs_flags);
refresh_tcon_referral(tcon, true);
return 0;

View File

@ -83,10 +83,11 @@ char *__build_path_from_dentry_optional_prefix(struct dentry *direntry, void *pa
const char *tree, int tree_len,
bool prefix)
{
int dfsplen;
int pplen = 0;
struct cifs_sb_info *cifs_sb = CIFS_SB(direntry->d_sb);
struct cifs_sb_info *cifs_sb = CIFS_SB(direntry);
unsigned int sbflags = cifs_sb_flags(cifs_sb);
char dirsep = CIFS_DIR_SEP(cifs_sb);
int pplen = 0;
int dfsplen;
char *s;
if (unlikely(!page))
@ -97,7 +98,7 @@ char *__build_path_from_dentry_optional_prefix(struct dentry *direntry, void *pa
else
dfsplen = 0;
if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_USE_PREFIX_PATH)
if (sbflags & CIFS_MOUNT_USE_PREFIX_PATH)
pplen = cifs_sb->prepath ? strlen(cifs_sb->prepath) + 1 : 0;
s = dentry_path_raw(direntry, page, PATH_MAX);
@ -124,7 +125,7 @@ char *__build_path_from_dentry_optional_prefix(struct dentry *direntry, void *pa
if (dfsplen) {
s -= dfsplen;
memcpy(s, tree, dfsplen);
if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_POSIX_PATHS) {
if (sbflags & CIFS_MOUNT_POSIX_PATHS) {
int i;
for (i = 0; i < dfsplen; i++) {
if (s[i] == '\\')
@ -153,7 +154,7 @@ char *build_path_from_dentry_optional_prefix(struct dentry *direntry, void *page
static int
check_name(struct dentry *direntry, struct cifs_tcon *tcon)
{
struct cifs_sb_info *cifs_sb = CIFS_SB(direntry->d_sb);
struct cifs_sb_info *cifs_sb = CIFS_SB(direntry);
int i;
if (unlikely(tcon->fsAttrInfo.MaxPathNameComponentLength &&
@ -161,7 +162,7 @@ check_name(struct dentry *direntry, struct cifs_tcon *tcon)
le32_to_cpu(tcon->fsAttrInfo.MaxPathNameComponentLength)))
return -ENAMETOOLONG;
if (!(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_POSIX_PATHS)) {
if (!(cifs_sb_flags(cifs_sb) & CIFS_MOUNT_POSIX_PATHS)) {
for (i = 0; i < direntry->d_name.len; i++) {
if (direntry->d_name.name[i] == '\\') {
cifs_dbg(FYI, "Invalid file name\n");
@ -182,11 +183,12 @@ static int cifs_do_create(struct inode *inode, struct dentry *direntry, unsigned
int rc = -ENOENT;
int create_options = CREATE_NOT_DIR;
int desired_access;
struct cifs_sb_info *cifs_sb = CIFS_SB(inode->i_sb);
struct cifs_sb_info *cifs_sb = CIFS_SB(inode);
struct cifs_tcon *tcon = tlink_tcon(tlink);
const char *full_path;
void *page = alloc_dentry_path();
struct inode *newinode = NULL;
unsigned int sbflags = cifs_sb_flags(cifs_sb);
int disposition;
struct TCP_Server_Info *server = tcon->ses->server;
struct cifs_open_parms oparms;
@ -375,7 +377,7 @@ retry_open:
.device = 0,
};
if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_SET_UID) {
if (sbflags & CIFS_MOUNT_SET_UID) {
args.uid = current_fsuid();
if (inode->i_mode & S_ISGID)
args.gid = inode->i_gid;
@ -412,9 +414,9 @@ cifs_create_get_file_info:
if (server->ops->set_lease_key)
server->ops->set_lease_key(newinode, fid);
if ((*oplock & CIFS_CREATE_ACTION) && S_ISREG(newinode->i_mode)) {
if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_DYNPERM)
if (sbflags & CIFS_MOUNT_DYNPERM)
newinode->i_mode = mode;
if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_SET_UID) {
if (sbflags & CIFS_MOUNT_SET_UID) {
newinode->i_uid = current_fsuid();
if (inode->i_mode & S_ISGID)
newinode->i_gid = inode->i_gid;
@ -459,18 +461,20 @@ int
cifs_atomic_open(struct inode *inode, struct dentry *direntry,
struct file *file, unsigned int oflags, umode_t mode)
{
int rc;
unsigned int xid;
struct cifs_sb_info *cifs_sb = CIFS_SB(inode);
struct cifs_open_info_data buf = {};
struct TCP_Server_Info *server;
struct cifsFileInfo *file_info;
struct cifs_pending_open open;
struct cifs_fid fid = {};
struct tcon_link *tlink;
struct cifs_tcon *tcon;
struct TCP_Server_Info *server;
struct cifs_fid fid = {};
struct cifs_pending_open open;
unsigned int sbflags;
unsigned int xid;
__u32 oplock;
struct cifsFileInfo *file_info;
struct cifs_open_info_data buf = {};
int rc;
if (unlikely(cifs_forced_shutdown(CIFS_SB(inode->i_sb))))
if (unlikely(cifs_forced_shutdown(cifs_sb)))
return -EIO;
/*
@ -506,7 +510,7 @@ cifs_atomic_open(struct inode *inode, struct dentry *direntry,
cifs_dbg(FYI, "parent inode = 0x%p name is: %pd and dentry = 0x%p\n",
inode, direntry, direntry);
tlink = cifs_sb_tlink(CIFS_SB(inode->i_sb));
tlink = cifs_sb_tlink(cifs_sb);
if (IS_ERR(tlink)) {
rc = PTR_ERR(tlink);
goto out_free_xid;
@ -543,13 +547,13 @@ cifs_atomic_open(struct inode *inode, struct dentry *direntry,
goto out;
}
if (file->f_flags & O_DIRECT &&
CIFS_SB(inode->i_sb)->mnt_cifs_flags & CIFS_MOUNT_STRICT_IO) {
if (CIFS_SB(inode->i_sb)->mnt_cifs_flags & CIFS_MOUNT_NO_BRL)
sbflags = cifs_sb_flags(cifs_sb);
if ((file->f_flags & O_DIRECT) && (sbflags & CIFS_MOUNT_STRICT_IO)) {
if (sbflags & CIFS_MOUNT_NO_BRL)
file->f_op = &cifs_file_direct_nobrl_ops;
else
file->f_op = &cifs_file_direct_ops;
}
}
file_info = cifs_new_fileinfo(&fid, file, tlink, oplock, buf.symlink_target);
if (file_info == NULL) {

View File

@ -581,11 +581,19 @@ void _cifsFileInfo_put(struct cifsFileInfo *cifs_file,
* close because it may cause a error when we open this file
* again and get at least level II oplock.
*/
if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_STRICT_IO)
if (cifs_sb_flags(cifs_sb) & CIFS_MOUNT_STRICT_IO)
set_bit(CIFS_INO_INVALID_MAPPING, &cifsi->flags);
cifs_set_oplock_level(cifsi, 0);
}
if (OPEN_FMODE(cifs_file->f_flags) & FMODE_WRITE) {
/* Stamp while open_file_lock is held; covers all close paths
* including background I/O. Pairs with smp_load_acquire() in
* is_size_safe_to_change().
*/
smp_store_release(&cifsi->time_last_write, jiffies);
}
spin_unlock(&cifsi->open_file_lock);
spin_unlock(&tcon->open_file_lock);
@ -630,11 +638,11 @@ void _cifsFileInfo_put(struct cifsFileInfo *cifs_file,
int cifs_file_flush(const unsigned int xid, struct inode *inode,
struct cifsFileInfo *cfile)
{
struct cifs_sb_info *cifs_sb = CIFS_SB(inode->i_sb);
struct cifs_sb_info *cifs_sb = CIFS_SB(inode);
struct cifs_tcon *tcon;
int rc;
if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_NOSSYNC)
if (cifs_sb_flags(cifs_sb) & CIFS_MOUNT_NOSSYNC)
return 0;
if (cfile && (OPEN_FMODE(cfile->f_flags) & FMODE_WRITE)) {
@ -690,24 +698,24 @@ static int cifs_do_truncate(const unsigned int xid, struct dentry *dentry)
int cifs_open(struct inode *inode, struct file *file)
{
struct cifs_sb_info *cifs_sb = CIFS_SB(inode);
struct cifs_open_info_data data = {};
struct cifsFileInfo *cfile = NULL;
struct TCP_Server_Info *server;
struct cifs_pending_open open;
bool posix_open_ok = false;
struct cifs_fid fid = {};
struct tcon_link *tlink;
struct cifs_tcon *tcon;
const char *full_path;
unsigned int sbflags;
int rc = -EACCES;
unsigned int xid;
__u32 oplock;
struct cifs_sb_info *cifs_sb;
struct TCP_Server_Info *server;
struct cifs_tcon *tcon;
struct tcon_link *tlink;
struct cifsFileInfo *cfile = NULL;
void *page;
const char *full_path;
bool posix_open_ok = false;
struct cifs_fid fid = {};
struct cifs_pending_open open;
struct cifs_open_info_data data = {};
xid = get_xid();
cifs_sb = CIFS_SB(inode->i_sb);
if (unlikely(cifs_forced_shutdown(cifs_sb))) {
free_xid(xid);
return -EIO;
@ -731,9 +739,9 @@ int cifs_open(struct inode *inode, struct file *file)
cifs_dbg(FYI, "inode = 0x%p file flags are 0x%x for %s\n",
inode, file->f_flags, full_path);
if (file->f_flags & O_DIRECT &&
cifs_sb->mnt_cifs_flags & CIFS_MOUNT_STRICT_IO) {
if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_NO_BRL)
sbflags = cifs_sb_flags(cifs_sb);
if ((file->f_flags & O_DIRECT) && (sbflags & CIFS_MOUNT_STRICT_IO)) {
if (sbflags & CIFS_MOUNT_NO_BRL)
file->f_op = &cifs_file_direct_nobrl_ops;
else
file->f_op = &cifs_file_direct_ops;
@ -884,7 +892,7 @@ cifs_relock_file(struct cifsFileInfo *cfile)
struct cifs_tcon *tcon = tlink_tcon(cfile->tlink);
int rc = 0;
#ifdef CONFIG_CIFS_ALLOW_INSECURE_LEGACY
struct cifs_sb_info *cifs_sb = CIFS_SB(cfile->dentry->d_sb);
struct cifs_sb_info *cifs_sb = CIFS_SB(cinode);
#endif /* CONFIG_CIFS_ALLOW_INSECURE_LEGACY */
down_read_nested(&cinode->lock_sem, SINGLE_DEPTH_NESTING);
@ -897,7 +905,7 @@ cifs_relock_file(struct cifsFileInfo *cfile)
#ifdef CONFIG_CIFS_ALLOW_INSECURE_LEGACY
if (cap_unix(tcon->ses) &&
(CIFS_UNIX_FCNTL_CAP & le64_to_cpu(tcon->fsUnixInfo.Capability)) &&
((cifs_sb->mnt_cifs_flags & CIFS_MOUNT_NOPOSIXBRL) == 0))
((cifs_sb_flags(cifs_sb) & CIFS_MOUNT_NOPOSIXBRL) == 0))
rc = cifs_push_posix_locks(cfile);
else
#endif /* CONFIG_CIFS_ALLOW_INSECURE_LEGACY */
@ -1100,11 +1108,12 @@ void smb2_deferred_work_close(struct work_struct *work)
{
struct cifsFileInfo *cfile = container_of(work,
struct cifsFileInfo, deferred.work);
struct cifsInodeInfo *cinode = CIFS_I(d_inode(cfile->dentry));
spin_lock(&CIFS_I(d_inode(cfile->dentry))->deferred_lock);
spin_lock(&cinode->deferred_lock);
cifs_del_deferred_close(cfile);
cfile->deferred_close_scheduled = false;
spin_unlock(&CIFS_I(d_inode(cfile->dentry))->deferred_lock);
spin_unlock(&cinode->deferred_lock);
_cifsFileInfo_put(cfile, true, false);
}
@ -1683,7 +1692,7 @@ cifs_push_locks(struct cifsFileInfo *cfile)
struct cifs_tcon *tcon = tlink_tcon(cfile->tlink);
int rc = 0;
#ifdef CONFIG_CIFS_ALLOW_INSECURE_LEGACY
struct cifs_sb_info *cifs_sb = CIFS_SB(cfile->dentry->d_sb);
struct cifs_sb_info *cifs_sb = CIFS_SB(cinode);
#endif /* CONFIG_CIFS_ALLOW_INSECURE_LEGACY */
/* we are going to update can_cache_brlcks here - need a write access */
@ -1696,7 +1705,7 @@ cifs_push_locks(struct cifsFileInfo *cfile)
#ifdef CONFIG_CIFS_ALLOW_INSECURE_LEGACY
if (cap_unix(tcon->ses) &&
(CIFS_UNIX_FCNTL_CAP & le64_to_cpu(tcon->fsUnixInfo.Capability)) &&
((cifs_sb->mnt_cifs_flags & CIFS_MOUNT_NOPOSIXBRL) == 0))
((cifs_sb_flags(cifs_sb) & CIFS_MOUNT_NOPOSIXBRL) == 0))
rc = cifs_push_posix_locks(cfile);
else
#endif /* CONFIG_CIFS_ALLOW_INSECURE_LEGACY */
@ -2099,11 +2108,11 @@ int cifs_flock(struct file *file, int cmd, struct file_lock *fl)
cifs_read_flock(fl, &type, &lock, &unlock, &wait_flag,
tcon->ses->server);
cifs_sb = CIFS_FILE_SB(file);
cifs_sb = CIFS_SB(file);
if (cap_unix(tcon->ses) &&
(CIFS_UNIX_FCNTL_CAP & le64_to_cpu(tcon->fsUnixInfo.Capability)) &&
((cifs_sb->mnt_cifs_flags & CIFS_MOUNT_NOPOSIXBRL) == 0))
((cifs_sb_flags(cifs_sb) & CIFS_MOUNT_NOPOSIXBRL) == 0))
posix_lck = true;
if (!lock && !unlock) {
@ -2126,14 +2135,14 @@ int cifs_flock(struct file *file, int cmd, struct file_lock *fl)
int cifs_lock(struct file *file, int cmd, struct file_lock *flock)
{
int rc, xid;
struct cifs_sb_info *cifs_sb = CIFS_SB(file);
struct cifsFileInfo *cfile;
int lock = 0, unlock = 0;
bool wait_flag = false;
bool posix_lck = false;
struct cifs_sb_info *cifs_sb;
struct cifs_tcon *tcon;
struct cifsFileInfo *cfile;
__u32 type;
int rc, xid;
rc = -EACCES;
xid = get_xid();
@ -2147,12 +2156,11 @@ int cifs_lock(struct file *file, int cmd, struct file_lock *flock)
cifs_read_flock(flock, &type, &lock, &unlock, &wait_flag,
tcon->ses->server);
cifs_sb = CIFS_FILE_SB(file);
set_bit(CIFS_INO_CLOSE_ON_LOCK, &CIFS_I(d_inode(cfile->dentry))->flags);
if (cap_unix(tcon->ses) &&
(CIFS_UNIX_FCNTL_CAP & le64_to_cpu(tcon->fsUnixInfo.Capability)) &&
((cifs_sb->mnt_cifs_flags & CIFS_MOUNT_NOPOSIXBRL) == 0))
((cifs_sb_flags(cifs_sb) & CIFS_MOUNT_NOPOSIXBRL) == 0))
posix_lck = true;
/*
* BB add code here to normalize offset and length to account for
@ -2280,11 +2288,11 @@ cifs_write(struct cifsFileInfo *open_file, __u32 pid, const char *write_data,
struct cifsFileInfo *find_readable_file(struct cifsInodeInfo *cifs_inode,
bool fsuid_only)
{
struct cifs_sb_info *cifs_sb = CIFS_SB(cifs_inode);
struct cifsFileInfo *open_file = NULL;
struct cifs_sb_info *cifs_sb = CIFS_SB(cifs_inode->netfs.inode.i_sb);
/* only filter by fsuid on multiuser mounts */
if (!(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MULTIUSER))
if (!(cifs_sb_flags(cifs_sb) & CIFS_MOUNT_MULTIUSER))
fsuid_only = false;
spin_lock(&cifs_inode->open_file_lock);
@ -2337,10 +2345,10 @@ cifs_get_writable_file(struct cifsInodeInfo *cifs_inode, int flags,
return rc;
}
cifs_sb = CIFS_SB(cifs_inode->netfs.inode.i_sb);
cifs_sb = CIFS_SB(cifs_inode);
/* only filter by fsuid on multiuser mounts */
if (!(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MULTIUSER))
if (!(cifs_sb_flags(cifs_sb) & CIFS_MOUNT_MULTIUSER))
fsuid_only = false;
spin_lock(&cifs_inode->open_file_lock);
@ -3125,10 +3133,10 @@ static int cifs_write_end(struct file *file, struct address_space *mapping,
int rc;
struct inode *inode = mapping->host;
struct cifsFileInfo *cfile = file->private_data;
struct cifs_sb_info *cifs_sb = CIFS_SB(cfile->dentry->d_sb);
struct cifs_sb_info *cifs_sb = CIFS_SB(cfile->dentry);
__u32 pid;
if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_RWPIDFORWARD)
if (cifs_sb_flags(cifs_sb) & CIFS_MOUNT_RWPIDFORWARD)
pid = cfile->pid;
else
pid = current->tgid;
@ -3225,7 +3233,7 @@ int cifs_fsync(struct file *file, loff_t start, loff_t end, int datasync)
struct TCP_Server_Info *server;
struct cifsFileInfo *smbfile = file->private_data;
struct inode *inode = file_inode(file);
struct cifs_sb_info *cifs_sb = CIFS_FILE_SB(file);
struct cifs_sb_info *cifs_sb = CIFS_SB(file);
rc = file_write_and_wait_range(file, start, end);
if (rc) {
@ -3239,7 +3247,7 @@ int cifs_fsync(struct file *file, loff_t start, loff_t end, int datasync)
file, datasync);
tcon = tlink_tcon(smbfile->tlink);
if (!(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_NOSSYNC)) {
if (!(cifs_sb_flags(cifs_sb) & CIFS_MOUNT_NOSSYNC)) {
server = tcon->ses->server;
if (server->ops->flush == NULL) {
rc = -ENOSYS;
@ -3490,7 +3498,7 @@ cifs_write_from_iter(loff_t offset, size_t len, struct iov_iter *from,
size_t start;
unsigned int xid;
if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_RWPIDFORWARD)
if (cifs_sb_flags(cifs_sb) & CIFS_MOUNT_RWPIDFORWARD)
pid = open_file->pid;
else
pid = current->tgid;
@ -3753,7 +3761,7 @@ static ssize_t __cifs_writev(
if (rc <= 0)
return rc;
cifs_sb = CIFS_FILE_SB(file);
cifs_sb = CIFS_SB(file);
cfile = file->private_data;
tcon = tlink_tcon(cfile->tlink);
@ -3851,7 +3859,7 @@ cifs_writev(struct kiocb *iocb, struct iov_iter *from)
struct inode *inode = file->f_mapping->host;
struct cifsInodeInfo *cinode = CIFS_I(inode);
struct TCP_Server_Info *server = tlink_tcon(cfile->tlink)->ses->server;
struct cifs_sb_info *cifs_sb = CIFS_SB(inode->i_sb);
struct cifs_sb_info *cifs_sb = CIFS_SB(inode);
ssize_t rc;
inode_lock(inode);
@ -3865,7 +3873,7 @@ cifs_writev(struct kiocb *iocb, struct iov_iter *from)
if (rc <= 0)
goto out;
if ((cifs_sb->mnt_cifs_flags & CIFS_MOUNT_NOPOSIXBRL) &&
if ((cifs_sb_flags(cifs_sb) & CIFS_MOUNT_NOPOSIXBRL) &&
(cifs_find_lock_conflict(cfile, iocb->ki_pos, iov_iter_count(from),
server->vals->exclusive_lock_type, 0,
NULL, CIFS_WRITE_OP))) {
@ -3889,7 +3897,7 @@ cifs_strict_writev(struct kiocb *iocb, struct iov_iter *from)
{
struct inode *inode = file_inode(iocb->ki_filp);
struct cifsInodeInfo *cinode = CIFS_I(inode);
struct cifs_sb_info *cifs_sb = CIFS_SB(inode->i_sb);
struct cifs_sb_info *cifs_sb = CIFS_SB(inode);
struct cifsFileInfo *cfile = (struct cifsFileInfo *)
iocb->ki_filp->private_data;
struct cifs_tcon *tcon = tlink_tcon(cfile->tlink);
@ -3902,7 +3910,7 @@ cifs_strict_writev(struct kiocb *iocb, struct iov_iter *from)
if (CIFS_CACHE_WRITE(cinode)) {
if (cap_unix(tcon->ses) &&
(CIFS_UNIX_FCNTL_CAP & le64_to_cpu(tcon->fsUnixInfo.Capability))
&& ((cifs_sb->mnt_cifs_flags & CIFS_MOUNT_NOPOSIXBRL) == 0)) {
&& ((cifs_sb_flags(cifs_sb) & CIFS_MOUNT_NOPOSIXBRL) == 0)) {
written = generic_file_write_iter(iocb, from);
goto out;
}
@ -4239,7 +4247,7 @@ cifs_send_async_read(loff_t offset, size_t len, struct cifsFileInfo *open_file,
server = cifs_pick_channel(tlink_tcon(open_file->tlink)->ses);
if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_RWPIDFORWARD)
if (cifs_sb_flags(cifs_sb) & CIFS_MOUNT_RWPIDFORWARD)
pid = open_file->pid;
else
pid = current->tgid;
@ -4496,7 +4504,7 @@ static ssize_t __cifs_readv(
if (!len)
return 0;
cifs_sb = CIFS_FILE_SB(file);
cifs_sb = CIFS_SB(file);
cfile = file->private_data;
tcon = tlink_tcon(cfile->tlink);
@ -4597,7 +4605,7 @@ cifs_strict_readv(struct kiocb *iocb, struct iov_iter *to)
{
struct inode *inode = file_inode(iocb->ki_filp);
struct cifsInodeInfo *cinode = CIFS_I(inode);
struct cifs_sb_info *cifs_sb = CIFS_SB(inode->i_sb);
struct cifs_sb_info *cifs_sb = CIFS_SB(inode);
struct cifsFileInfo *cfile = (struct cifsFileInfo *)
iocb->ki_filp->private_data;
struct cifs_tcon *tcon = tlink_tcon(cfile->tlink);
@ -4614,7 +4622,7 @@ cifs_strict_readv(struct kiocb *iocb, struct iov_iter *to)
if (!CIFS_CACHE_READ(cinode))
return cifs_user_readv(iocb, to);
if ((cifs_sb->mnt_cifs_flags & CIFS_MOUNT_NOPOSIXBRL) == 0)
if ((cifs_sb_flags(cifs_sb) & CIFS_MOUNT_NOPOSIXBRL) == 0)
return generic_file_read_iter(iocb, to);
/*
@ -4649,7 +4657,7 @@ cifs_read(struct file *file, char *read_data, size_t read_size, loff_t *offset)
__u32 pid;
xid = get_xid();
cifs_sb = CIFS_FILE_SB(file);
cifs_sb = CIFS_SB(file);
/* FIXME: set up handlers for larger reads and/or convert to async */
rsize = min_t(unsigned int, cifs_sb->ctx->rsize, CIFSMaxBufSize);
@ -4668,7 +4676,7 @@ cifs_read(struct file *file, char *read_data, size_t read_size, loff_t *offset)
return -ENOSYS;
}
if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_RWPIDFORWARD)
if (cifs_sb_flags(cifs_sb) & CIFS_MOUNT_RWPIDFORWARD)
pid = open_file->pid;
else
pid = current->tgid;
@ -4924,7 +4932,7 @@ static void cifs_readahead(struct readahead_control *ractl)
{
int rc;
struct cifsFileInfo *open_file = ractl->file->private_data;
struct cifs_sb_info *cifs_sb = CIFS_FILE_SB(ractl->file);
struct cifs_sb_info *cifs_sb = CIFS_SB(ractl->file);
struct TCP_Server_Info *server;
pid_t pid;
unsigned int xid, nr_pages, last_batch_size = 0, cache_nr_pages = 0;
@ -4935,7 +4943,7 @@ static void cifs_readahead(struct readahead_control *ractl)
xid = get_xid();
if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_RWPIDFORWARD)
if (cifs_sb_flags(cifs_sb) & CIFS_MOUNT_RWPIDFORWARD)
pid = open_file->pid;
else
pid = current->tgid;
@ -5181,16 +5189,28 @@ static int is_inode_writable(struct cifsInodeInfo *cifs_inode)
bool is_size_safe_to_change(struct cifsInodeInfo *cifsInode, __u64 end_of_file,
bool from_readdir)
{
struct cifs_sb_info *cifs_sb;
unsigned long tlw;
if (!cifsInode)
return true;
cifs_sb = CIFS_SB(cifsInode);
if (is_inode_writable(cifsInode) ||
((cifsInode->oplock & CIFS_CACHE_RW_FLG) != 0 && from_readdir)) {
/* This inode is open for write at least once */
struct cifs_sb_info *cifs_sb;
cifs_sb = CIFS_SB(cifsInode->netfs.inode.i_sb);
if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_DIRECT_IO) {
/*
* Readdir data is unreliable when we have writable handles or
* an exclusive lease -- never allow it to change i_size, even
* on direct-IO mounts where the server's directory metadata
* can still lag behind the actual file state.
*/
if (from_readdir)
return false;
if (cifs_sb_flags(cifs_sb) & CIFS_MOUNT_DIRECT_IO) {
/* since no page cache to corrupt on directio
we can change size safely */
return true;
@ -5200,8 +5220,40 @@ bool is_size_safe_to_change(struct cifsInodeInfo *cifsInode, __u64 end_of_file,
return true;
return false;
} else
return true;
}
/*
* No writable handles open. Check whether we are within the attribute
* cache validity window of a recent local modification.
*
* For the close() path: _cifsFileInfo_put() stamps time_last_write
* (via smp_store_release()) before releasing open_file_lock. That
* spin_unlock() is a store-release that pairs with the spin_lock()
* (load-acquire) in is_inode_writable() above, so if
* is_inode_writable() returned false the smp_load_acquire() below is
* guaranteed to observe any time_last_write update from a concurrent
* close(), covering all close paths including background I/O.
*
* For the setattr/truncate paths: those callers use smp_store_release()
* directly; the smp_load_acquire() below pairs with that store. There
* is no shared lock between setattr and readdir, so this relies on
* acquire-release semantics alone. The store propagation latency on
* weakly-ordered architectures (nanoseconds) is negligible relative to
* the acregmax window (seconds) and the readdir RPC round-trip
* (milliseconds), making this a sound design choice in practice.
*
* time_last_write == 0 means the inode has never been written locally;
* skip the window check to avoid false positives near boot time when
* jiffies is still close to INITIAL_JIFFIES on 32-bit systems.
*/
if (from_readdir) {
/* Pairs with smp_store_release() in _cifsFileInfo_put() and setattr. */
tlw = smp_load_acquire(&cifsInode->time_last_write);
if (tlw && time_before(jiffies, tlw + cifs_sb->ctx->acregmax))
return false;
}
return true;
}
static int cifs_write_begin(struct file *file, struct address_space *mapping,
@ -5355,7 +5407,7 @@ void cifs_oplock_break(struct work_struct *work)
server = tcon->ses->server;
scoped_guard(spinlock, &cinode->open_file_lock) {
unsigned int sbflags = cifs_sb->mnt_cifs_flags;
unsigned int sbflags = cifs_sb_flags(cifs_sb);
server->ops->downgrade_oplock(server, cinode, cfile->oplock_level,
cfile->oplock_epoch, &purge_cache);

View File

@ -2084,161 +2084,160 @@ smb3_cleanup_fs_context(struct smb3_fs_context *ctx)
kfree(ctx);
}
void smb3_update_mnt_flags(struct cifs_sb_info *cifs_sb)
unsigned int smb3_update_mnt_flags(struct cifs_sb_info *cifs_sb)
{
unsigned int sbflags = cifs_sb_flags(cifs_sb);
struct smb3_fs_context *ctx = cifs_sb->ctx;
if (ctx->nodfs)
cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_NO_DFS;
sbflags |= CIFS_MOUNT_NO_DFS;
else
cifs_sb->mnt_cifs_flags &= ~CIFS_MOUNT_NO_DFS;
sbflags &= ~CIFS_MOUNT_NO_DFS;
if (ctx->noperm)
cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_NO_PERM;
sbflags |= CIFS_MOUNT_NO_PERM;
else
cifs_sb->mnt_cifs_flags &= ~CIFS_MOUNT_NO_PERM;
sbflags &= ~CIFS_MOUNT_NO_PERM;
if (ctx->setuids)
cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_SET_UID;
sbflags |= CIFS_MOUNT_SET_UID;
else
cifs_sb->mnt_cifs_flags &= ~CIFS_MOUNT_SET_UID;
sbflags &= ~CIFS_MOUNT_SET_UID;
if (ctx->setuidfromacl)
cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_UID_FROM_ACL;
sbflags |= CIFS_MOUNT_UID_FROM_ACL;
else
cifs_sb->mnt_cifs_flags &= ~CIFS_MOUNT_UID_FROM_ACL;
sbflags &= ~CIFS_MOUNT_UID_FROM_ACL;
if (ctx->server_ino)
cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_SERVER_INUM;
sbflags |= CIFS_MOUNT_SERVER_INUM;
else
cifs_sb->mnt_cifs_flags &= ~CIFS_MOUNT_SERVER_INUM;
sbflags &= ~CIFS_MOUNT_SERVER_INUM;
if (ctx->remap)
cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_MAP_SFM_CHR;
sbflags |= CIFS_MOUNT_MAP_SFM_CHR;
else
cifs_sb->mnt_cifs_flags &= ~CIFS_MOUNT_MAP_SFM_CHR;
sbflags &= ~CIFS_MOUNT_MAP_SFM_CHR;
if (ctx->sfu_remap)
cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_MAP_SPECIAL_CHR;
sbflags |= CIFS_MOUNT_MAP_SPECIAL_CHR;
else
cifs_sb->mnt_cifs_flags &= ~CIFS_MOUNT_MAP_SPECIAL_CHR;
sbflags &= ~CIFS_MOUNT_MAP_SPECIAL_CHR;
if (ctx->no_xattr)
cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_NO_XATTR;
sbflags |= CIFS_MOUNT_NO_XATTR;
else
cifs_sb->mnt_cifs_flags &= ~CIFS_MOUNT_NO_XATTR;
sbflags &= ~CIFS_MOUNT_NO_XATTR;
if (ctx->sfu_emul)
cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_UNX_EMUL;
sbflags |= CIFS_MOUNT_UNX_EMUL;
else
cifs_sb->mnt_cifs_flags &= ~CIFS_MOUNT_UNX_EMUL;
sbflags &= ~CIFS_MOUNT_UNX_EMUL;
if (ctx->nobrl)
cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_NO_BRL;
sbflags |= CIFS_MOUNT_NO_BRL;
else
cifs_sb->mnt_cifs_flags &= ~CIFS_MOUNT_NO_BRL;
sbflags &= ~CIFS_MOUNT_NO_BRL;
if (ctx->nohandlecache)
cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_NO_HANDLE_CACHE;
sbflags |= CIFS_MOUNT_NO_HANDLE_CACHE;
else
cifs_sb->mnt_cifs_flags &= ~CIFS_MOUNT_NO_HANDLE_CACHE;
sbflags &= ~CIFS_MOUNT_NO_HANDLE_CACHE;
if (ctx->nostrictsync)
cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_NOSSYNC;
sbflags |= CIFS_MOUNT_NOSSYNC;
else
cifs_sb->mnt_cifs_flags &= ~CIFS_MOUNT_NOSSYNC;
sbflags &= ~CIFS_MOUNT_NOSSYNC;
if (ctx->mand_lock)
cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_NOPOSIXBRL;
sbflags |= CIFS_MOUNT_NOPOSIXBRL;
else
cifs_sb->mnt_cifs_flags &= ~CIFS_MOUNT_NOPOSIXBRL;
sbflags &= ~CIFS_MOUNT_NOPOSIXBRL;
if (ctx->rwpidforward)
cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_RWPIDFORWARD;
sbflags |= CIFS_MOUNT_RWPIDFORWARD;
else
cifs_sb->mnt_cifs_flags &= ~CIFS_MOUNT_RWPIDFORWARD;
sbflags &= ~CIFS_MOUNT_RWPIDFORWARD;
if (ctx->mode_ace)
cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_MODE_FROM_SID;
sbflags |= CIFS_MOUNT_MODE_FROM_SID;
else
cifs_sb->mnt_cifs_flags &= ~CIFS_MOUNT_MODE_FROM_SID;
sbflags &= ~CIFS_MOUNT_MODE_FROM_SID;
if (ctx->cifs_acl)
cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_CIFS_ACL;
sbflags |= CIFS_MOUNT_CIFS_ACL;
else
cifs_sb->mnt_cifs_flags &= ~CIFS_MOUNT_CIFS_ACL;
sbflags &= ~CIFS_MOUNT_CIFS_ACL;
if (ctx->backupuid_specified)
cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_CIFS_BACKUPUID;
sbflags |= CIFS_MOUNT_CIFS_BACKUPUID;
else
cifs_sb->mnt_cifs_flags &= ~CIFS_MOUNT_CIFS_BACKUPUID;
sbflags &= ~CIFS_MOUNT_CIFS_BACKUPUID;
if (ctx->backupgid_specified)
cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_CIFS_BACKUPGID;
sbflags |= CIFS_MOUNT_CIFS_BACKUPGID;
else
cifs_sb->mnt_cifs_flags &= ~CIFS_MOUNT_CIFS_BACKUPGID;
sbflags &= ~CIFS_MOUNT_CIFS_BACKUPGID;
if (ctx->override_uid)
cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_OVERR_UID;
sbflags |= CIFS_MOUNT_OVERR_UID;
else
cifs_sb->mnt_cifs_flags &= ~CIFS_MOUNT_OVERR_UID;
sbflags &= ~CIFS_MOUNT_OVERR_UID;
if (ctx->override_gid)
cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_OVERR_GID;
sbflags |= CIFS_MOUNT_OVERR_GID;
else
cifs_sb->mnt_cifs_flags &= ~CIFS_MOUNT_OVERR_GID;
sbflags &= ~CIFS_MOUNT_OVERR_GID;
if (ctx->dynperm)
cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_DYNPERM;
sbflags |= CIFS_MOUNT_DYNPERM;
else
cifs_sb->mnt_cifs_flags &= ~CIFS_MOUNT_DYNPERM;
sbflags &= ~CIFS_MOUNT_DYNPERM;
if (ctx->fsc)
cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_FSCACHE;
sbflags |= CIFS_MOUNT_FSCACHE;
else
cifs_sb->mnt_cifs_flags &= ~CIFS_MOUNT_FSCACHE;
sbflags &= ~CIFS_MOUNT_FSCACHE;
if (ctx->multiuser)
cifs_sb->mnt_cifs_flags |= (CIFS_MOUNT_MULTIUSER |
CIFS_MOUNT_NO_PERM);
sbflags |= CIFS_MOUNT_MULTIUSER | CIFS_MOUNT_NO_PERM;
else
cifs_sb->mnt_cifs_flags &= ~CIFS_MOUNT_MULTIUSER;
sbflags &= ~CIFS_MOUNT_MULTIUSER;
if (ctx->strict_io)
cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_STRICT_IO;
sbflags |= CIFS_MOUNT_STRICT_IO;
else
cifs_sb->mnt_cifs_flags &= ~CIFS_MOUNT_STRICT_IO;
sbflags &= ~CIFS_MOUNT_STRICT_IO;
if (ctx->direct_io)
cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_DIRECT_IO;
sbflags |= CIFS_MOUNT_DIRECT_IO;
else
cifs_sb->mnt_cifs_flags &= ~CIFS_MOUNT_DIRECT_IO;
sbflags &= ~CIFS_MOUNT_DIRECT_IO;
if (ctx->mfsymlinks)
cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_MF_SYMLINKS;
sbflags |= CIFS_MOUNT_MF_SYMLINKS;
else
cifs_sb->mnt_cifs_flags &= ~CIFS_MOUNT_MF_SYMLINKS;
if (ctx->mfsymlinks) {
if (ctx->sfu_emul) {
/*
* Our SFU ("Services for Unix") emulation allows now
* creating new and reading existing SFU symlinks.
* Older Linux kernel versions were not able to neither
* read existing nor create new SFU symlinks. But
* creating and reading SFU style mknod and FIFOs was
* supported for long time. When "mfsymlinks" and
* "sfu" are both enabled at the same time, it allows
* reading both types of symlinks, but will only create
* them with mfsymlinks format. This allows better
* Apple compatibility, compatibility with older Linux
* kernel clients (probably better for Samba too)
* while still recognizing old Windows style symlinks.
*/
cifs_dbg(VFS, "mount options mfsymlinks and sfu both enabled\n");
}
}
cifs_sb->mnt_cifs_flags &= ~CIFS_MOUNT_SHUTDOWN;
sbflags &= ~CIFS_MOUNT_MF_SYMLINKS;
return;
if (ctx->mfsymlinks && ctx->sfu_emul) {
/*
* Our SFU ("Services for Unix") emulation allows now
* creating new and reading existing SFU symlinks.
* Older Linux kernel versions were not able to neither
* read existing nor create new SFU symlinks. But
* creating and reading SFU style mknod and FIFOs was
* supported for long time. When "mfsymlinks" and
* "sfu" are both enabled at the same time, it allows
* reading both types of symlinks, but will only create
* them with mfsymlinks format. This allows better
* Apple compatibility, compatibility with older Linux
* kernel clients (probably better for Samba too)
* while still recognizing old Windows style symlinks.
*/
cifs_dbg(VFS, "mount options mfsymlinks and sfu both enabled\n");
}
sbflags &= ~CIFS_MOUNT_SHUTDOWN;
atomic_set(&cifs_sb->mnt_cifs_flags, sbflags);
return sbflags;
}

View File

@ -372,7 +372,7 @@ static inline struct smb3_fs_context *smb3_fc2context(const struct fs_context *f
extern int smb3_fs_context_dup(struct smb3_fs_context *new_ctx, struct smb3_fs_context *ctx);
extern int smb3_sync_session_ctx_passwords(struct cifs_sb_info *cifs_sb, struct cifs_ses *ses);
extern void smb3_update_mnt_flags(struct cifs_sb_info *cifs_sb);
unsigned int smb3_update_mnt_flags(struct cifs_sb_info *cifs_sb);
/*
* max deferred close timeout (jiffies) - 2^30

View File

@ -30,30 +30,31 @@
static void cifs_set_ops(struct inode *inode)
{
struct cifs_sb_info *cifs_sb = CIFS_SB(inode->i_sb);
struct cifs_sb_info *cifs_sb = CIFS_SB(inode);
struct cifs_tcon *tcon = cifs_sb_master_tcon(cifs_sb);
unsigned int sbflags = cifs_sb_flags(cifs_sb);
switch (inode->i_mode & S_IFMT) {
case S_IFREG:
inode->i_op = &cifs_file_inode_ops;
if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_DIRECT_IO) {
if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_NO_BRL)
if (sbflags & CIFS_MOUNT_DIRECT_IO) {
if (sbflags & CIFS_MOUNT_NO_BRL)
inode->i_fop = &cifs_file_direct_nobrl_ops;
else
inode->i_fop = &cifs_file_direct_ops;
} else if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_STRICT_IO) {
if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_NO_BRL)
} else if (sbflags & CIFS_MOUNT_STRICT_IO) {
if (sbflags & CIFS_MOUNT_NO_BRL)
inode->i_fop = &cifs_file_strict_nobrl_ops;
else
inode->i_fop = &cifs_file_strict_ops;
} else if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_NO_BRL)
} else if (sbflags & CIFS_MOUNT_NO_BRL)
inode->i_fop = &cifs_file_nobrl_ops;
else { /* not direct, send byte range locks */
inode->i_fop = &cifs_file_ops;
}
/* check if server can support readahead */
if (cifs_sb_master_tcon(cifs_sb)->ses->server->max_read <
PAGE_SIZE + MAX_CIFS_HDR_SIZE)
if (tcon->ses->server->max_read < PAGE_SIZE + MAX_CIFS_HDR_SIZE)
inode->i_data.a_ops = &cifs_addr_ops_smallbuf;
else
inode->i_data.a_ops = &cifs_addr_ops;
@ -178,7 +179,7 @@ cifs_fattr_to_inode(struct inode *inode, struct cifs_fattr *fattr,
/* if dynperm is set, don't clobber existing mode */
if (inode->i_state & I_NEW ||
!(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_DYNPERM))
!(cifs_sb_flags(cifs_sb) & CIFS_MOUNT_DYNPERM))
inode->i_mode = fattr->cf_mode;
cifs_i->cifsAttrs = fattr->cf_cifsattrs;
@ -208,6 +209,8 @@ cifs_fattr_to_inode(struct inode *inode, struct cifs_fattr *fattr,
* calculating num blocks.
*/
inode->i_blocks = (512 - 1 + fattr->cf_bytes) >> 9;
} else if (from_readdir && i_size_read(inode) != fattr->cf_eof) {
cifs_i->time = 0;
}
if (S_ISLNK(fattr->cf_mode) && fattr->cf_symlink_target) {
@ -229,10 +232,8 @@ cifs_fill_uniqueid(struct super_block *sb, struct cifs_fattr *fattr)
{
struct cifs_sb_info *cifs_sb = CIFS_SB(sb);
if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_SERVER_INUM)
return;
fattr->cf_uniqueid = iunique(sb, ROOT_I);
if (!(cifs_sb_flags(cifs_sb) & CIFS_MOUNT_SERVER_INUM))
fattr->cf_uniqueid = iunique(sb, ROOT_I);
}
/* Fill a cifs_fattr struct with info from FILE_UNIX_BASIC_INFO. */
@ -240,6 +241,8 @@ void
cifs_unix_basic_to_fattr(struct cifs_fattr *fattr, FILE_UNIX_BASIC_INFO *info,
struct cifs_sb_info *cifs_sb)
{
unsigned int sbflags;
memset(fattr, 0, sizeof(*fattr));
fattr->cf_uniqueid = le64_to_cpu(info->UniqueId);
fattr->cf_bytes = le64_to_cpu(info->NumOfBytes);
@ -298,8 +301,9 @@ cifs_unix_basic_to_fattr(struct cifs_fattr *fattr, FILE_UNIX_BASIC_INFO *info,
break;
}
sbflags = cifs_sb_flags(cifs_sb);
fattr->cf_uid = cifs_sb->ctx->linux_uid;
if (!(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_OVERR_UID)) {
if (!(sbflags & CIFS_MOUNT_OVERR_UID)) {
u64 id = le64_to_cpu(info->Uid);
if (id < ((uid_t)-1)) {
kuid_t uid = make_kuid(&init_user_ns, id);
@ -309,7 +313,7 @@ cifs_unix_basic_to_fattr(struct cifs_fattr *fattr, FILE_UNIX_BASIC_INFO *info,
}
fattr->cf_gid = cifs_sb->ctx->linux_gid;
if (!(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_OVERR_GID)) {
if (!(sbflags & CIFS_MOUNT_OVERR_GID)) {
u64 id = le64_to_cpu(info->Gid);
if (id < ((gid_t)-1)) {
kgid_t gid = make_kgid(&init_user_ns, id);
@ -363,7 +367,7 @@ static int update_inode_info(struct super_block *sb,
*
* If file type or uniqueid is different, return error.
*/
if (unlikely((cifs_sb->mnt_cifs_flags & CIFS_MOUNT_SERVER_INUM) &&
if (unlikely((cifs_sb_flags(cifs_sb) & CIFS_MOUNT_SERVER_INUM) &&
CIFS_I(*inode)->uniqueid != fattr->cf_uniqueid)) {
CIFS_I(*inode)->time = 0; /* force reval */
return -ESTALE;
@ -449,7 +453,7 @@ static int cifs_get_unix_fattr(const unsigned char *full_path,
cifs_fill_uniqueid(sb, fattr);
/* check for Minshall+French symlinks */
if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MF_SYMLINKS) {
if (cifs_sb_flags(cifs_sb) & CIFS_MOUNT_MF_SYMLINKS) {
tmprc = check_mf_symlink(xid, tcon, cifs_sb, fattr, full_path);
cifs_dbg(FYI, "check_mf_symlink: %d\n", tmprc);
}
@ -1062,7 +1066,7 @@ cifs_backup_query_path_info(int xid,
else if ((tcon->ses->capabilities &
tcon->ses->server->vals->cap_nt_find) == 0)
info.info_level = SMB_FIND_FILE_INFO_STANDARD;
else if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_SERVER_INUM)
else if (cifs_sb_flags(cifs_sb) & CIFS_MOUNT_SERVER_INUM)
info.info_level = SMB_FIND_FILE_ID_FULL_DIR_INFO;
else /* no srvino useful for fallback to some netapp */
info.info_level = SMB_FIND_FILE_DIRECTORY_INFO;
@ -1090,7 +1094,7 @@ static void cifs_set_fattr_ino(int xid, struct cifs_tcon *tcon, struct super_blo
struct TCP_Server_Info *server = tcon->ses->server;
int rc;
if (!(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_SERVER_INUM)) {
if (!(cifs_sb_flags(cifs_sb) & CIFS_MOUNT_SERVER_INUM)) {
if (*inode)
fattr->cf_uniqueid = CIFS_I(*inode)->uniqueid;
else
@ -1244,14 +1248,15 @@ static int cifs_get_fattr(struct cifs_open_info_data *data,
struct inode **inode,
const char *full_path)
{
struct cifs_open_info_data tmp_data = {};
struct cifs_tcon *tcon;
struct TCP_Server_Info *server;
struct tcon_link *tlink;
struct cifs_sb_info *cifs_sb = CIFS_SB(sb);
struct cifs_open_info_data tmp_data = {};
void *smb1_backup_rsp_buf = NULL;
int rc = 0;
struct TCP_Server_Info *server;
struct cifs_tcon *tcon;
struct tcon_link *tlink;
unsigned int sbflags;
int tmprc = 0;
int rc = 0;
tlink = cifs_sb_tlink(cifs_sb);
if (IS_ERR(tlink))
@ -1351,16 +1356,17 @@ static int cifs_get_fattr(struct cifs_open_info_data *data,
#ifdef CONFIG_CIFS_ALLOW_INSECURE_LEGACY
handle_mnt_opt:
#endif /* CONFIG_CIFS_ALLOW_INSECURE_LEGACY */
sbflags = cifs_sb_flags(cifs_sb);
/* query for SFU type info if supported and needed */
if ((fattr->cf_cifsattrs & ATTR_SYSTEM) &&
(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_UNX_EMUL)) {
(sbflags & CIFS_MOUNT_UNX_EMUL)) {
tmprc = cifs_sfu_type(fattr, full_path, cifs_sb, xid);
if (tmprc)
cifs_dbg(FYI, "cifs_sfu_type failed: %d\n", tmprc);
}
/* fill in 0777 bits from ACL */
if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MODE_FROM_SID) {
if (sbflags & CIFS_MOUNT_MODE_FROM_SID) {
rc = cifs_acl_to_fattr(cifs_sb, fattr, *inode,
true, full_path, fid);
if (rc == -EREMOTE)
@ -1370,7 +1376,7 @@ handle_mnt_opt:
__func__, rc);
goto out;
}
} else if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_CIFS_ACL) {
} else if (sbflags & CIFS_MOUNT_CIFS_ACL) {
rc = cifs_acl_to_fattr(cifs_sb, fattr, *inode,
false, full_path, fid);
if (rc == -EREMOTE)
@ -1380,7 +1386,7 @@ handle_mnt_opt:
__func__, rc);
goto out;
}
} else if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_UNX_EMUL)
} else if (sbflags & CIFS_MOUNT_UNX_EMUL)
/* fill in remaining high mode bits e.g. SUID, VTX */
cifs_sfu_mode(fattr, full_path, cifs_sb, xid);
else if (!(tcon->posix_extensions))
@ -1390,7 +1396,7 @@ handle_mnt_opt:
/* check for Minshall+French symlinks */
if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MF_SYMLINKS) {
if (sbflags & CIFS_MOUNT_MF_SYMLINKS) {
tmprc = check_mf_symlink(xid, tcon, cifs_sb, fattr, full_path);
cifs_dbg(FYI, "check_mf_symlink: %d\n", tmprc);
}
@ -1490,7 +1496,7 @@ static int smb311_posix_get_fattr(struct cifs_open_info_data *data,
* 3. Tweak fattr based on mount options
*/
/* check for Minshall+French symlinks */
if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MF_SYMLINKS) {
if (cifs_sb_flags(cifs_sb) & CIFS_MOUNT_MF_SYMLINKS) {
tmprc = check_mf_symlink(xid, tcon, cifs_sb, fattr, full_path);
cifs_dbg(FYI, "check_mf_symlink: %d\n", tmprc);
}
@ -1641,7 +1647,7 @@ struct inode *cifs_root_iget(struct super_block *sb)
int len;
int rc;
if ((cifs_sb->mnt_cifs_flags & CIFS_MOUNT_USE_PREFIX_PATH)
if ((cifs_sb_flags(cifs_sb) & CIFS_MOUNT_USE_PREFIX_PATH)
&& cifs_sb->prepath) {
len = strlen(cifs_sb->prepath);
path = kzalloc(len + 2 /* leading sep + null */, GFP_KERNEL);
@ -2078,8 +2084,9 @@ cifs_mkdir_qinfo(struct inode *parent, struct dentry *dentry, umode_t mode,
const char *full_path, struct cifs_sb_info *cifs_sb,
struct cifs_tcon *tcon, const unsigned int xid)
{
int rc = 0;
struct inode *inode = NULL;
unsigned int sbflags;
int rc = 0;
if (tcon->posix_extensions) {
rc = smb311_posix_get_inode_info(&inode, full_path,
@ -2119,6 +2126,7 @@ cifs_mkdir_qinfo(struct inode *parent, struct dentry *dentry, umode_t mode,
if (parent->i_mode & S_ISGID)
mode |= S_ISGID;
sbflags = cifs_sb_flags(cifs_sb);
#ifdef CONFIG_CIFS_ALLOW_INSECURE_LEGACY
if (tcon->unix_ext) {
struct cifs_unix_set_info_args args = {
@ -2128,7 +2136,7 @@ cifs_mkdir_qinfo(struct inode *parent, struct dentry *dentry, umode_t mode,
.mtime = NO_CHANGE_64,
.device = 0,
};
if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_SET_UID) {
if (sbflags & CIFS_MOUNT_SET_UID) {
args.uid = current_fsuid();
if (parent->i_mode & S_ISGID)
args.gid = parent->i_gid;
@ -2146,14 +2154,14 @@ cifs_mkdir_qinfo(struct inode *parent, struct dentry *dentry, umode_t mode,
{
#endif /* CONFIG_CIFS_ALLOW_INSECURE_LEGACY */
struct TCP_Server_Info *server = tcon->ses->server;
if (!(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_CIFS_ACL) &&
if (!(sbflags & CIFS_MOUNT_CIFS_ACL) &&
(mode & S_IWUGO) == 0 && server->ops->mkdir_setinfo)
server->ops->mkdir_setinfo(inode, full_path, cifs_sb,
tcon, xid);
if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_DYNPERM)
if (sbflags & CIFS_MOUNT_DYNPERM)
inode->i_mode = (mode | S_IFDIR);
if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_SET_UID) {
if (sbflags & CIFS_MOUNT_SET_UID) {
inode->i_uid = current_fsuid();
if (inode->i_mode & S_ISGID)
inode->i_gid = parent->i_gid;
@ -2668,7 +2676,7 @@ cifs_dentry_needs_reval(struct dentry *dentry)
{
struct inode *inode = d_inode(dentry);
struct cifsInodeInfo *cifs_i = CIFS_I(inode);
struct cifs_sb_info *cifs_sb = CIFS_SB(inode->i_sb);
struct cifs_sb_info *cifs_sb = CIFS_SB(inode);
struct cifs_tcon *tcon = cifs_sb_master_tcon(cifs_sb);
struct cached_fid *cfid = NULL;
@ -2709,7 +2717,7 @@ cifs_dentry_needs_reval(struct dentry *dentry)
}
/* hardlinked files w/ noserverino get "special" treatment */
if (!(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_SERVER_INUM) &&
if (!(cifs_sb_flags(cifs_sb) & CIFS_MOUNT_SERVER_INUM) &&
S_ISREG(inode->i_mode) && inode->i_nlink != 1)
return true;
@ -2752,9 +2760,9 @@ cifs_wait_bit_killable(struct wait_bit_key *key, int mode)
int
cifs_revalidate_mapping(struct inode *inode)
{
int rc;
struct cifs_sb_info *cifs_sb = CIFS_SB(inode);
unsigned long *flags = &CIFS_I(inode)->flags;
struct cifs_sb_info *cifs_sb = CIFS_SB(inode->i_sb);
int rc;
/* swapfiles are not supposed to be shared */
if (IS_SWAPFILE(inode))
@ -2767,7 +2775,7 @@ cifs_revalidate_mapping(struct inode *inode)
if (test_and_clear_bit(CIFS_INO_INVALID_MAPPING, flags)) {
/* for cache=singleclient, do not invalidate */
if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_RW_CACHE)
if (cifs_sb_flags(cifs_sb) & CIFS_MOUNT_RW_CACHE)
goto skip_invalidate;
rc = cifs_invalidate_mapping(inode);
@ -2887,10 +2895,11 @@ int cifs_revalidate_dentry(struct dentry *dentry)
int cifs_getattr(struct mnt_idmap *idmap, const struct path *path,
struct kstat *stat, u32 request_mask, unsigned int flags)
{
struct dentry *dentry = path->dentry;
struct cifs_sb_info *cifs_sb = CIFS_SB(dentry->d_sb);
struct cifs_sb_info *cifs_sb = CIFS_SB(path->dentry);
struct cifs_tcon *tcon = cifs_sb_master_tcon(cifs_sb);
struct dentry *dentry = path->dentry;
struct inode *inode = d_inode(dentry);
unsigned int sbflags;
int rc;
if (unlikely(cifs_forced_shutdown(CIFS_SB(inode->i_sb))))
@ -2947,12 +2956,13 @@ int cifs_getattr(struct mnt_idmap *idmap, const struct path *path,
* enabled, and the admin hasn't overridden them, set the ownership
* to the fsuid/fsgid of the current process.
*/
if ((cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MULTIUSER) &&
!(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_CIFS_ACL) &&
sbflags = cifs_sb_flags(cifs_sb);
if ((sbflags & CIFS_MOUNT_MULTIUSER) &&
!(sbflags & CIFS_MOUNT_CIFS_ACL) &&
!tcon->unix_ext) {
if (!(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_OVERR_UID))
if (!(sbflags & CIFS_MOUNT_OVERR_UID))
stat->uid = current_fsuid();
if (!(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_OVERR_GID))
if (!(sbflags & CIFS_MOUNT_OVERR_GID))
stat->gid = current_fsgid();
}
return 0;
@ -3096,7 +3106,7 @@ cifs_setattr_unix(struct dentry *direntry, struct iattr *attrs)
void *page = alloc_dentry_path();
struct inode *inode = d_inode(direntry);
struct cifsInodeInfo *cifsInode = CIFS_I(inode);
struct cifs_sb_info *cifs_sb = CIFS_SB(inode->i_sb);
struct cifs_sb_info *cifs_sb = CIFS_SB(inode);
struct tcon_link *tlink;
struct cifs_tcon *pTcon;
struct cifs_unix_set_info_args *args = NULL;
@ -3107,7 +3117,7 @@ cifs_setattr_unix(struct dentry *direntry, struct iattr *attrs)
xid = get_xid();
if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_NO_PERM)
if (cifs_sb_flags(cifs_sb) & CIFS_MOUNT_NO_PERM)
attrs->ia_valid |= ATTR_FORCE;
rc = setattr_prepare(&nop_mnt_idmap, direntry, attrs);
@ -3144,6 +3154,17 @@ cifs_setattr_unix(struct dentry *direntry, struct iattr *attrs)
rc = 0;
if (attrs->ia_valid & ATTR_SIZE) {
if (attrs->ia_size != i_size_read(inode)) {
/* Stamp before RPC. On failure the stamp remains: restoring a
* stale snapshot could silently erase a concurrent
* _cifsFileInfo_put() close stamp. readdir is suppressed
* until the stamp expires; stat() bypasses this via the
* from_readdir=false path in is_size_safe_to_change() and
* always returns an authoritative QUERY_INFO result.
* Pairs with smp_load_acquire() in is_size_safe_to_change().
*/
smp_store_release(&cifsInode->time_last_write, jiffies);
}
rc = cifs_file_set_size(xid, direntry, full_path,
open_file, attrs->ia_size);
if (rc != 0)
@ -3260,26 +3281,26 @@ out:
static int
cifs_setattr_nounix(struct dentry *direntry, struct iattr *attrs)
{
unsigned int xid;
struct inode *inode = d_inode(direntry);
struct cifsInodeInfo *cifsInode = CIFS_I(inode);
struct cifs_sb_info *cifs_sb = CIFS_SB(inode);
unsigned int sbflags = cifs_sb_flags(cifs_sb);
struct cifsFileInfo *cfile = NULL;
void *page = alloc_dentry_path();
__u64 mode = NO_CHANGE_64;
kuid_t uid = INVALID_UID;
kgid_t gid = INVALID_GID;
struct inode *inode = d_inode(direntry);
struct cifs_sb_info *cifs_sb = CIFS_SB(inode->i_sb);
struct cifsInodeInfo *cifsInode = CIFS_I(inode);
struct cifsFileInfo *cfile = NULL;
const char *full_path;
void *page = alloc_dentry_path();
int rc = -EACCES;
__u32 dosattr = 0;
__u64 mode = NO_CHANGE_64;
bool posix = cifs_sb_master_tcon(cifs_sb)->posix_extensions;
int rc = -EACCES;
unsigned int xid;
xid = get_xid();
cifs_dbg(FYI, "setattr on file %pd attrs->ia_valid 0x%x\n",
direntry, attrs->ia_valid);
if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_NO_PERM)
if (sbflags & CIFS_MOUNT_NO_PERM)
attrs->ia_valid |= ATTR_FORCE;
rc = setattr_prepare(&nop_mnt_idmap, direntry, attrs);
@ -3322,6 +3343,17 @@ cifs_setattr_nounix(struct dentry *direntry, struct iattr *attrs)
}
if (attrs->ia_valid & ATTR_SIZE) {
if (attrs->ia_size != i_size_read(inode)) {
/* Stamp before RPC. On failure the stamp remains: restoring a
* stale snapshot could silently erase a concurrent
* _cifsFileInfo_put() close stamp. readdir is suppressed
* until the stamp expires; stat() bypasses this via the
* from_readdir=false path in is_size_safe_to_change() and
* always returns an authoritative QUERY_INFO result.
* Pairs with smp_load_acquire() in is_size_safe_to_change().
*/
smp_store_release(&cifsInode->time_last_write, jiffies);
}
rc = cifs_file_set_size(xid, direntry, full_path,
cfile, attrs->ia_size);
if (rc != 0)
@ -3340,8 +3372,7 @@ cifs_setattr_nounix(struct dentry *direntry, struct iattr *attrs)
if (attrs->ia_valid & ATTR_GID)
gid = attrs->ia_gid;
if ((cifs_sb->mnt_cifs_flags & CIFS_MOUNT_CIFS_ACL) ||
(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MODE_FROM_SID)) {
if (sbflags & (CIFS_MOUNT_CIFS_ACL | CIFS_MOUNT_MODE_FROM_SID)) {
if (uid_valid(uid) || gid_valid(gid)) {
mode = NO_CHANGE_64;
rc = id_mode_to_cifs_acl(inode, full_path, &mode,
@ -3352,9 +3383,9 @@ cifs_setattr_nounix(struct dentry *direntry, struct iattr *attrs)
goto cifs_setattr_exit;
}
}
} else
if (!(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_SET_UID))
} else if (!(sbflags & CIFS_MOUNT_SET_UID)) {
attrs->ia_valid &= ~(ATTR_UID | ATTR_GID);
}
/* skip mode change if it's just for clearing setuid/setgid */
if (attrs->ia_valid & (ATTR_KILL_SUID|ATTR_KILL_SGID))
@ -3363,9 +3394,8 @@ cifs_setattr_nounix(struct dentry *direntry, struct iattr *attrs)
if (attrs->ia_valid & ATTR_MODE) {
mode = attrs->ia_mode;
rc = 0;
if ((cifs_sb->mnt_cifs_flags & CIFS_MOUNT_CIFS_ACL) ||
(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MODE_FROM_SID) ||
posix) {
if ((sbflags & (CIFS_MOUNT_CIFS_ACL | CIFS_MOUNT_MODE_FROM_SID)) ||
cifs_sb_master_tcon(cifs_sb)->posix_extensions) {
rc = id_mode_to_cifs_acl(inode, full_path, &mode,
INVALID_UID, INVALID_GID);
if (rc) {
@ -3387,7 +3417,7 @@ cifs_setattr_nounix(struct dentry *direntry, struct iattr *attrs)
dosattr = cifsInode->cifsAttrs | ATTR_READONLY;
/* fix up mode if we're not using dynperm */
if ((cifs_sb->mnt_cifs_flags & CIFS_MOUNT_DYNPERM) == 0)
if ((sbflags & CIFS_MOUNT_DYNPERM) == 0)
attrs->ia_mode = inode->i_mode & ~S_IWUGO;
} else if ((mode & S_IWUGO) &&
(cifsInode->cifsAttrs & ATTR_READONLY)) {
@ -3398,7 +3428,7 @@ cifs_setattr_nounix(struct dentry *direntry, struct iattr *attrs)
dosattr |= ATTR_NORMAL;
/* reset local inode permissions to normal */
if (!(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_DYNPERM)) {
if (!(sbflags & CIFS_MOUNT_DYNPERM)) {
attrs->ia_mode &= ~(S_IALLUGO);
if (S_ISDIR(inode->i_mode))
attrs->ia_mode |=
@ -3407,7 +3437,7 @@ cifs_setattr_nounix(struct dentry *direntry, struct iattr *attrs)
attrs->ia_mode |=
cifs_sb->ctx->file_mode;
}
} else if (!(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_DYNPERM)) {
} else if (!(sbflags & CIFS_MOUNT_DYNPERM)) {
/* ignore mode change - ATTR_READONLY hasn't changed */
attrs->ia_valid &= ~ATTR_MODE;
}

View File

@ -220,7 +220,7 @@ static int cifs_shutdown(struct super_block *sb, unsigned long arg)
*/
case CIFS_GOING_FLAGS_LOGFLUSH:
case CIFS_GOING_FLAGS_NOLOGFLUSH:
sbi->mnt_cifs_flags |= CIFS_MOUNT_SHUTDOWN;
atomic_or(CIFS_MOUNT_SHUTDOWN, &sbi->mnt_cifs_flags);
goto shutdown_good;
default:
rc = -EINVAL;

View File

@ -568,14 +568,15 @@ int
cifs_symlink(struct mnt_idmap *idmap, struct inode *inode,
struct dentry *direntry, const char *symname)
{
int rc = -EOPNOTSUPP;
unsigned int xid;
struct cifs_sb_info *cifs_sb = CIFS_SB(inode->i_sb);
struct cifs_sb_info *cifs_sb = CIFS_SB(inode);
struct inode *newinode = NULL;
struct tcon_link *tlink;
struct cifs_tcon *pTcon;
const char *full_path;
int rc = -EOPNOTSUPP;
unsigned int sbflags;
unsigned int xid;
void *page;
struct inode *newinode = NULL;
if (unlikely(cifs_forced_shutdown(cifs_sb)))
return -EIO;
@ -604,6 +605,7 @@ cifs_symlink(struct mnt_idmap *idmap, struct inode *inode,
cifs_dbg(FYI, "symname is %s\n", symname);
/* BB what if DFS and this volume is on different share? BB */
sbflags = cifs_sb_flags(cifs_sb);
rc = -EOPNOTSUPP;
switch (cifs_symlink_type(cifs_sb)) {
case CIFS_SYMLINK_TYPE_UNIX:
@ -618,14 +620,14 @@ cifs_symlink(struct mnt_idmap *idmap, struct inode *inode,
break;
case CIFS_SYMLINK_TYPE_MFSYMLINKS:
if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MF_SYMLINKS) {
if (sbflags & CIFS_MOUNT_MF_SYMLINKS) {
rc = create_mf_symlink(xid, pTcon, cifs_sb,
full_path, symname);
}
break;
case CIFS_SYMLINK_TYPE_SFU:
if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_UNX_EMUL) {
if (sbflags & CIFS_MOUNT_UNX_EMUL) {
rc = __cifs_sfu_make_node(xid, inode, direntry, pTcon,
full_path, S_IFLNK,
0, symname);

View File

@ -561,13 +561,15 @@ dump_smb(void *buf, int smb_buf_length)
void
cifs_autodisable_serverino(struct cifs_sb_info *cifs_sb)
{
if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_SERVER_INUM) {
unsigned int sbflags = cifs_sb_flags(cifs_sb);
if (sbflags & CIFS_MOUNT_SERVER_INUM) {
struct cifs_tcon *tcon = NULL;
if (cifs_sb->master_tlink)
tcon = cifs_sb_master_tcon(cifs_sb);
cifs_sb->mnt_cifs_flags &= ~CIFS_MOUNT_SERVER_INUM;
atomic_andnot(CIFS_MOUNT_SERVER_INUM, &cifs_sb->mnt_cifs_flags);
cifs_sb->mnt_cifs_serverino_autodisabled = true;
cifs_dbg(VFS, "Autodisabling the use of server inode numbers on %s\n",
tcon ? tcon->tree_name : "new server");
@ -668,11 +670,13 @@ void cifs_done_oplock_break(struct cifsInodeInfo *cinode)
bool
backup_cred(struct cifs_sb_info *cifs_sb)
{
if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_CIFS_BACKUPUID) {
unsigned int sbflags = cifs_sb_flags(cifs_sb);
if (sbflags & CIFS_MOUNT_CIFS_BACKUPUID) {
if (uid_eq(cifs_sb->ctx->backupuid, current_fsuid()))
return true;
}
if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_CIFS_BACKUPGID) {
if (sbflags & CIFS_MOUNT_CIFS_BACKUPGID) {
if (in_group_p(cifs_sb->ctx->backupgid))
return true;
}
@ -770,7 +774,7 @@ cifs_del_deferred_close(struct cifsFileInfo *cfile)
void
cifs_close_deferred_file(struct cifsInodeInfo *cifs_inode)
{
struct cifsFileInfo *cfile = NULL;
struct cifsFileInfo *cfile = NULL, *failed_cfile = NULL;
struct file_list *tmp_list, *tmp_next_list;
LIST_HEAD(file_head);
@ -786,8 +790,10 @@ cifs_close_deferred_file(struct cifsInodeInfo *cifs_inode)
spin_unlock(&cifs_inode->deferred_lock);
tmp_list = kmalloc(sizeof(struct file_list), GFP_ATOMIC);
if (tmp_list == NULL)
if (tmp_list == NULL) {
failed_cfile = cfile;
break;
}
tmp_list->cfile = cfile;
list_add_tail(&tmp_list->list, &file_head);
}
@ -795,6 +801,9 @@ cifs_close_deferred_file(struct cifsInodeInfo *cifs_inode)
}
spin_unlock(&cifs_inode->open_file_lock);
if (failed_cfile)
_cifsFileInfo_put(failed_cfile, false, false);
list_for_each_entry_safe(tmp_list, tmp_next_list, &file_head, list) {
_cifsFileInfo_put(tmp_list->cfile, false, false);
list_del(&tmp_list->list);
@ -805,7 +814,7 @@ cifs_close_deferred_file(struct cifsInodeInfo *cifs_inode)
void
cifs_close_all_deferred_files(struct cifs_tcon *tcon)
{
struct cifsFileInfo *cfile;
struct cifsFileInfo *cfile, *failed_cfile = NULL;
struct file_list *tmp_list, *tmp_next_list;
LIST_HEAD(file_head);
@ -818,8 +827,10 @@ cifs_close_all_deferred_files(struct cifs_tcon *tcon)
spin_unlock(&CIFS_I(d_inode(cfile->dentry))->deferred_lock);
tmp_list = kmalloc(sizeof(struct file_list), GFP_ATOMIC);
if (tmp_list == NULL)
if (tmp_list == NULL) {
failed_cfile = cfile;
break;
}
tmp_list->cfile = cfile;
list_add_tail(&tmp_list->list, &file_head);
}
@ -827,6 +838,9 @@ cifs_close_all_deferred_files(struct cifs_tcon *tcon)
}
spin_unlock(&tcon->open_file_lock);
if (failed_cfile)
_cifsFileInfo_put(failed_cfile, true, false);
list_for_each_entry_safe(tmp_list, tmp_next_list, &file_head, list) {
_cifsFileInfo_put(tmp_list->cfile, true, false);
list_del(&tmp_list->list);
@ -838,7 +852,7 @@ void cifs_close_deferred_file_under_dentry(struct cifs_tcon *tcon,
struct dentry *dentry)
{
struct file_list *tmp_list, *tmp_next_list;
struct cifsFileInfo *cfile;
struct cifsFileInfo *cfile, *failed_cfile = NULL;
LIST_HEAD(file_head);
spin_lock(&tcon->open_file_lock);
@ -851,14 +865,19 @@ void cifs_close_deferred_file_under_dentry(struct cifs_tcon *tcon,
spin_unlock(&CIFS_I(d_inode(cfile->dentry))->deferred_lock);
tmp_list = kmalloc(sizeof(struct file_list), GFP_ATOMIC);
if (tmp_list == NULL)
if (tmp_list == NULL) {
failed_cfile = cfile;
break;
}
tmp_list->cfile = cfile;
list_add_tail(&tmp_list->list, &file_head);
}
}
spin_unlock(&tcon->open_file_lock);
if (failed_cfile)
_cifsFileInfo_put(failed_cfile, true, false);
list_for_each_entry_safe(tmp_list, tmp_next_list, &file_head, list) {
_cifsFileInfo_put(tmp_list->cfile, true, false);
list_del(&tmp_list->list);
@ -1395,7 +1414,7 @@ int cifs_update_super_prepath(struct cifs_sb_info *cifs_sb, char *prefix)
convert_delimiter(cifs_sb->prepath, CIFS_DIR_SEP(cifs_sb));
}
cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_USE_PREFIX_PATH;
atomic_or(CIFS_MOUNT_USE_PREFIX_PATH, &cifs_sb->mnt_cifs_flags);
return 0;
}
@ -1424,7 +1443,7 @@ int cifs_inval_name_dfs_link_error(const unsigned int xid,
* look up or tcon is not DFS.
*/
if (strlen(full_path) < 2 || !cifs_sb ||
(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_NO_DFS) ||
(cifs_sb_flags(cifs_sb) & CIFS_MOUNT_NO_DFS) ||
!is_tcon_dfs(tcon))
return 0;

View File

@ -121,7 +121,7 @@ retry:
* want to clobber the existing one with the one that
* the readdir code created.
*/
if (!(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_SERVER_INUM))
if (!(cifs_sb_flags(cifs_sb) & CIFS_MOUNT_SERVER_INUM))
fattr->cf_uniqueid = CIFS_I(inode)->uniqueid;
/*
@ -177,6 +177,7 @@ cifs_fill_common_info(struct cifs_fattr *fattr, struct cifs_sb_info *cifs_sb)
struct cifs_open_info_data data = {
.reparse = { .tag = fattr->cf_cifstag, },
};
unsigned int sbflags;
fattr->cf_uid = cifs_sb->ctx->linux_uid;
fattr->cf_gid = cifs_sb->ctx->linux_gid;
@ -215,12 +216,12 @@ out_reparse:
* may look wrong since the inodes may not have timed out by the time
* "ls" does a stat() call on them.
*/
if ((cifs_sb->mnt_cifs_flags & CIFS_MOUNT_CIFS_ACL) ||
(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MODE_FROM_SID))
sbflags = cifs_sb_flags(cifs_sb);
if (sbflags & (CIFS_MOUNT_CIFS_ACL | CIFS_MOUNT_MODE_FROM_SID))
fattr->cf_flags |= CIFS_FATTR_NEED_REVAL;
if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_UNX_EMUL &&
fattr->cf_cifsattrs & ATTR_SYSTEM) {
if ((sbflags & CIFS_MOUNT_UNX_EMUL) &&
(fattr->cf_cifsattrs & ATTR_SYSTEM)) {
if (fattr->cf_eof == 0) {
fattr->cf_mode &= ~S_IFMT;
fattr->cf_mode |= S_IFIFO;
@ -345,13 +346,14 @@ static int
_initiate_cifs_search(const unsigned int xid, struct file *file,
const char *full_path)
{
struct cifs_sb_info *cifs_sb = CIFS_SB(file);
struct tcon_link *tlink = NULL;
struct TCP_Server_Info *server;
struct cifsFileInfo *cifsFile;
struct cifs_tcon *tcon;
unsigned int sbflags;
__u16 search_flags;
int rc = 0;
struct cifsFileInfo *cifsFile;
struct cifs_sb_info *cifs_sb = CIFS_FILE_SB(file);
struct tcon_link *tlink = NULL;
struct cifs_tcon *tcon;
struct TCP_Server_Info *server;
if (file->private_data == NULL) {
tlink = cifs_sb_tlink(cifs_sb);
@ -385,6 +387,7 @@ _initiate_cifs_search(const unsigned int xid, struct file *file,
cifs_dbg(FYI, "Full path: %s start at: %lld\n", full_path, file->f_pos);
ffirst_retry:
sbflags = cifs_sb_flags(cifs_sb);
/* test for Unix extensions */
/* but now check for them on the share/mount not on the SMB session */
/* if (cap_unix(tcon->ses) { */
@ -395,7 +398,7 @@ ffirst_retry:
else if ((tcon->ses->capabilities &
tcon->ses->server->vals->cap_nt_find) == 0) {
cifsFile->srch_inf.info_level = SMB_FIND_FILE_INFO_STANDARD;
} else if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_SERVER_INUM) {
} else if (sbflags & CIFS_MOUNT_SERVER_INUM) {
cifsFile->srch_inf.info_level = SMB_FIND_FILE_ID_FULL_DIR_INFO;
} else /* not srvinos - BB fixme add check for backlevel? */ {
cifsFile->srch_inf.info_level = SMB_FIND_FILE_FULL_DIRECTORY_INFO;
@ -411,8 +414,7 @@ ffirst_retry:
if (rc == 0) {
cifsFile->invalidHandle = false;
} else if ((rc == -EOPNOTSUPP) &&
(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_SERVER_INUM)) {
} else if (rc == -EOPNOTSUPP && (sbflags & CIFS_MOUNT_SERVER_INUM)) {
cifs_autodisable_serverino(cifs_sb);
goto ffirst_retry;
}
@ -690,7 +692,7 @@ find_cifs_entry(const unsigned int xid, struct cifs_tcon *tcon, loff_t pos,
loff_t first_entry_in_buffer;
loff_t index_to_find = pos;
struct cifsFileInfo *cfile = file->private_data;
struct cifs_sb_info *cifs_sb = CIFS_FILE_SB(file);
struct cifs_sb_info *cifs_sb = CIFS_SB(file);
struct TCP_Server_Info *server = tcon->ses->server;
/* check if index in the buffer */
@ -955,6 +957,7 @@ static int cifs_filldir(char *find_entry, struct file *file,
struct cifs_sb_info *cifs_sb = CIFS_SB(sb);
struct cifs_dirent de = { NULL, };
struct cifs_fattr fattr;
unsigned int sbflags;
struct qstr name;
int rc = 0;
@ -1019,15 +1022,15 @@ static int cifs_filldir(char *find_entry, struct file *file,
break;
}
if (de.ino && (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_SERVER_INUM)) {
sbflags = cifs_sb_flags(cifs_sb);
if (de.ino && (sbflags & CIFS_MOUNT_SERVER_INUM)) {
fattr.cf_uniqueid = de.ino;
} else {
fattr.cf_uniqueid = iunique(sb, ROOT_I);
cifs_autodisable_serverino(cifs_sb);
}
if ((cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MF_SYMLINKS) &&
couldbe_mf_symlink(&fattr))
if ((sbflags & CIFS_MOUNT_MF_SYMLINKS) && couldbe_mf_symlink(&fattr))
/*
* trying to get the type and mode can be slow,
* so just call those regular files for now, and mark
@ -1058,7 +1061,7 @@ int cifs_readdir(struct file *file, struct dir_context *ctx)
const char *full_path;
void *page = alloc_dentry_path();
struct cached_fid *cfid = NULL;
struct cifs_sb_info *cifs_sb = CIFS_FILE_SB(file);
struct cifs_sb_info *cifs_sb = CIFS_SB(file);
xid = get_xid();

View File

@ -55,17 +55,18 @@ static int create_native_symlink(const unsigned int xid, struct inode *inode,
const char *full_path, const char *symname)
{
struct reparse_symlink_data_buffer *buf = NULL;
struct cifs_open_info_data data = {};
struct cifs_sb_info *cifs_sb = CIFS_SB(inode->i_sb);
struct cifs_sb_info *cifs_sb = CIFS_SB(inode);
const char *symroot = cifs_sb->ctx->symlinkroot;
struct inode *new;
struct kvec iov;
__le16 *path = NULL;
bool directory;
char *symlink_target = NULL;
char *sym = NULL;
struct cifs_open_info_data data = {};
char sep = CIFS_DIR_SEP(cifs_sb);
char *symlink_target = NULL;
u16 len, plen, poff, slen;
unsigned int sbflags;
__le16 *path = NULL;
struct inode *new;
char *sym = NULL;
struct kvec iov;
bool directory;
int rc = 0;
if (strlen(symname) > REPARSE_SYM_PATH_MAX)
@ -83,8 +84,8 @@ static int create_native_symlink(const unsigned int xid, struct inode *inode,
.symlink_target = symlink_target,
};
if (!(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_POSIX_PATHS) &&
symroot && symname[0] == '/') {
sbflags = cifs_sb_flags(cifs_sb);
if (!(sbflags & CIFS_MOUNT_POSIX_PATHS) && symroot && symname[0] == '/') {
/*
* This is a request to create an absolute symlink on the server
* which does not support POSIX paths, and expects symlink in
@ -164,7 +165,7 @@ static int create_native_symlink(const unsigned int xid, struct inode *inode,
* mask these characters in NT object prefix by '_' and then change
* them back.
*/
if (!(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_POSIX_PATHS) && symname[0] == '/')
if (!(sbflags & CIFS_MOUNT_POSIX_PATHS) && symname[0] == '/')
sym[0] = sym[1] = sym[2] = sym[5] = '_';
path = cifs_convert_path_to_utf16(sym, cifs_sb);
@ -173,7 +174,7 @@ static int create_native_symlink(const unsigned int xid, struct inode *inode,
goto out;
}
if (!(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_POSIX_PATHS) && symname[0] == '/') {
if (!(sbflags & CIFS_MOUNT_POSIX_PATHS) && symname[0] == '/') {
sym[0] = '\\';
sym[1] = sym[2] = '?';
sym[5] = ':';
@ -197,7 +198,7 @@ static int create_native_symlink(const unsigned int xid, struct inode *inode,
slen = 2 * UniStrnlen((wchar_t *)path, REPARSE_SYM_PATH_MAX);
poff = 0;
plen = slen;
if (!(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_POSIX_PATHS) && symname[0] == '/') {
if (!(sbflags & CIFS_MOUNT_POSIX_PATHS) && symname[0] == '/') {
/*
* For absolute NT symlinks skip leading "\\??\\" in PrintName as
* PrintName is user visible location in DOS/Win32 format (not in NT format).
@ -822,7 +823,7 @@ int smb2_parse_native_symlink(char **target, const char *buf, unsigned int len,
goto out;
}
if (!(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_POSIX_PATHS) &&
if (!(cifs_sb_flags(cifs_sb) & CIFS_MOUNT_POSIX_PATHS) &&
symroot && !relative) {
/*
* This is an absolute symlink from the server which does not

View File

@ -32,7 +32,7 @@ static inline kuid_t wsl_make_kuid(struct cifs_sb_info *cifs_sb,
{
u32 uid = le32_to_cpu(*(__le32 *)ptr);
if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_OVERR_UID)
if (cifs_sb_flags(cifs_sb) & CIFS_MOUNT_OVERR_UID)
return cifs_sb->ctx->linux_uid;
return make_kuid(current_user_ns(), uid);
}
@ -42,7 +42,7 @@ static inline kgid_t wsl_make_kgid(struct cifs_sb_info *cifs_sb,
{
u32 gid = le32_to_cpu(*(__le32 *)ptr);
if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_OVERR_GID)
if (cifs_sb_flags(cifs_sb) & CIFS_MOUNT_OVERR_GID)
return cifs_sb->ctx->linux_gid;
return make_kgid(current_user_ns(), gid);
}

View File

@ -1211,7 +1211,7 @@ static int cifs_oplock_response(struct cifs_tcon *tcon, __u64 persistent_fid,
__u64 volatile_fid, __u16 net_fid,
struct cifsInodeInfo *cinode, unsigned int oplock)
{
unsigned int sbflags = CIFS_SB(cinode->netfs.inode.i_sb)->mnt_cifs_flags;
unsigned int sbflags = cifs_sb_flags(CIFS_SB(cinode));
__u8 op;
op = !!((oplock & CIFS_CACHE_READ_FLG) || (sbflags & CIFS_MOUNT_RO_CACHE));
@ -1346,7 +1346,8 @@ cifs_make_node(unsigned int xid, struct inode *inode,
struct dentry *dentry, struct cifs_tcon *tcon,
const char *full_path, umode_t mode, dev_t dev)
{
struct cifs_sb_info *cifs_sb = CIFS_SB(inode->i_sb);
struct cifs_sb_info *cifs_sb = CIFS_SB(inode);
unsigned int sbflags = cifs_sb_flags(cifs_sb);
struct inode *newinode = NULL;
int rc;
@ -1362,7 +1363,7 @@ cifs_make_node(unsigned int xid, struct inode *inode,
.mtime = NO_CHANGE_64,
.device = dev,
};
if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_SET_UID) {
if (sbflags & CIFS_MOUNT_SET_UID) {
args.uid = current_fsuid();
args.gid = current_fsgid();
} else {
@ -1381,7 +1382,7 @@ cifs_make_node(unsigned int xid, struct inode *inode,
if (rc == 0)
d_instantiate(dentry, newinode);
return rc;
} else if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_UNX_EMUL) {
} else if (sbflags & CIFS_MOUNT_UNX_EMUL) {
/*
* Check if mounted with mount parm 'sfu' mount parm.
* SFU emulation should work with all servers

View File

@ -74,7 +74,7 @@ int smb2_fix_symlink_target_type(char **target, bool directory, struct cifs_sb_i
* POSIX server does not distinguish between symlinks to file and
* symlink directory. So nothing is needed to fix on the client side.
*/
if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_POSIX_PATHS)
if (cifs_sb_flags(cifs_sb) & CIFS_MOUNT_POSIX_PATHS)
return 0;
if (!*target)

View File

@ -454,17 +454,8 @@ calc_size_exit:
__le16 *
cifs_convert_path_to_utf16(const char *from, struct cifs_sb_info *cifs_sb)
{
int len;
const char *start_of_path;
__le16 *to;
int map_type;
if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MAP_SFM_CHR)
map_type = SFM_MAP_UNI_RSVD;
else if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MAP_SPECIAL_CHR)
map_type = SFU_MAP_UNI_RSVD;
else
map_type = NO_MAP_UNI_RSVD;
int len;
/* Windows doesn't allow paths beginning with \ */
if (from[0] == '\\')
@ -478,14 +469,13 @@ cifs_convert_path_to_utf16(const char *from, struct cifs_sb_info *cifs_sb)
} else
start_of_path = from;
to = cifs_strndup_to_utf16(start_of_path, PATH_MAX, &len,
cifs_sb->local_nls, map_type);
return to;
return cifs_strndup_to_utf16(start_of_path, PATH_MAX, &len,
cifs_sb->local_nls, cifs_remap(cifs_sb));
}
__le32 smb2_get_lease_state(struct cifsInodeInfo *cinode, unsigned int oplock)
{
unsigned int sbflags = CIFS_SB(cinode->netfs.inode.i_sb)->mnt_cifs_flags;
unsigned int sbflags = cifs_sb_flags(CIFS_SB(cinode));
__le32 lease = 0;
if ((oplock & CIFS_CACHE_WRITE_FLG) || (sbflags & CIFS_MOUNT_RW_CACHE))

View File

@ -951,7 +951,7 @@ smb2_is_path_accessible(const unsigned int xid, struct cifs_tcon *tcon,
rc = -EREMOTE;
}
if (rc == -EREMOTE && IS_ENABLED(CONFIG_CIFS_DFS_UPCALL) &&
(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_NO_DFS))
(cifs_sb_flags(cifs_sb) & CIFS_MOUNT_NO_DFS))
rc = -EOPNOTSUPP;
goto out;
}
@ -2637,7 +2637,7 @@ static int smb2_oplock_response(struct cifs_tcon *tcon, __u64 persistent_fid,
__u64 volatile_fid, __u16 net_fid,
struct cifsInodeInfo *cinode, unsigned int oplock)
{
unsigned int sbflags = CIFS_SB(cinode->netfs.inode.i_sb)->mnt_cifs_flags;
unsigned int sbflags = cifs_sb_flags(CIFS_SB(cinode));
__u8 op;
if (tcon->ses->server->capabilities & SMB2_GLOBAL_CAP_LEASING)
@ -5312,7 +5312,7 @@ static int smb2_make_node(unsigned int xid, struct inode *inode,
struct dentry *dentry, struct cifs_tcon *tcon,
const char *full_path, umode_t mode, dev_t dev)
{
struct cifs_sb_info *cifs_sb = CIFS_SB(inode->i_sb);
unsigned int sbflags = cifs_sb_flags(CIFS_SB(inode));
int rc = -EOPNOTSUPP;
/*
@ -5321,7 +5321,7 @@ static int smb2_make_node(unsigned int xid, struct inode *inode,
* supports block and char device, socket & fifo,
* and was used by default in earlier versions of Windows
*/
if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_UNX_EMUL) {
if (sbflags & CIFS_MOUNT_UNX_EMUL) {
rc = cifs_sfu_make_node(xid, inode, dentry, tcon,
full_path, mode, dev);
} else if (CIFS_REPARSE_SUPPORT(tcon)) {

View File

@ -3144,22 +3144,19 @@ SMB2_open_init(struct cifs_tcon *tcon, struct TCP_Server_Info *server,
}
if ((oparms->disposition != FILE_OPEN) && (oparms->cifs_sb)) {
unsigned int sbflags = cifs_sb_flags(oparms->cifs_sb);
bool set_mode;
bool set_owner;
if ((oparms->cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MODE_FROM_SID) &&
(oparms->mode != ACL_NO_MODE))
if ((sbflags & CIFS_MOUNT_MODE_FROM_SID) &&
oparms->mode != ACL_NO_MODE) {
set_mode = true;
else {
} else {
set_mode = false;
oparms->mode = ACL_NO_MODE;
}
if (oparms->cifs_sb->mnt_cifs_flags & CIFS_MOUNT_UID_FROM_ACL)
set_owner = true;
else
set_owner = false;
set_owner = sbflags & CIFS_MOUNT_UID_FROM_ACL;
if (set_owner | set_mode) {
cifs_dbg(FYI, "add sd with mode 0x%x\n", oparms->mode);
rc = add_sd_context(iov, &n_iov, oparms->mode, set_owner);

View File

@ -150,7 +150,7 @@ static int cifs_xattr_set(const struct xattr_handler *handler,
break;
}
if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_NO_XATTR)
if (cifs_sb_flags(cifs_sb) & CIFS_MOUNT_NO_XATTR)
goto out;
if (pTcon->ses->server->ops->set_EA) {
@ -310,7 +310,7 @@ static int cifs_xattr_get(const struct xattr_handler *handler,
break;
}
if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_NO_XATTR)
if (cifs_sb_flags(cifs_sb) & CIFS_MOUNT_NO_XATTR)
goto out;
if (pTcon->ses->server->ops->query_all_EAs)
@ -399,7 +399,7 @@ ssize_t cifs_listxattr(struct dentry *direntry, char *data, size_t buf_size)
if (unlikely(cifs_forced_shutdown(cifs_sb)))
return -EIO;
if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_NO_XATTR)
if (cifs_sb_flags(cifs_sb) & CIFS_MOUNT_NO_XATTR)
return -EOPNOTSUPP;
tlink = cifs_sb_tlink(cifs_sb);

View File

@ -96,8 +96,8 @@ int mlx5_query_hca_vport_node_guid(struct mlx5_core_dev *dev,
int mlx5_query_nic_vport_mac_list(struct mlx5_core_dev *dev,
u16 vport,
enum mlx5_list_type list_type,
u8 addr_list[][ETH_ALEN],
int *list_size);
u8 (**mac_list)[ETH_ALEN],
int *mac_list_size);
int mlx5_modify_nic_vport_mac_list(struct mlx5_core_dev *dev,
enum mlx5_list_type list_type,
u8 addr_list[][ETH_ALEN],

View File

@ -1,3 +1,3 @@
sbat,1,SBAT Version,sbat,1,https://github.com/rhboot/shim/blob/main/SBAT.md
kernel.rhel,1,Red Hat,kernel-core,5.14.0-687.36.1.el9.x86_64,mailto:secalert@redhat.com
kernel.almalinux,1,AlmaLinux,kernel-core,5.14.0-687.36.1.el9.x86_64,mailto:security@almalinux.org
kernel.rhel,1,Red Hat,kernel-core,5.14.0-687.38.1.el9.x86_64,mailto:secalert@redhat.com
kernel.almalinux,1,AlmaLinux,kernel-core,5.14.0-687.38.1.el9.x86_64,mailto:security@almalinux.org

View File

@ -3782,15 +3782,17 @@ static inline void slab_post_alloc_hook(struct kmem_cache *s,
flags &= gfp_allowed_mask;
/*
* For kmalloc object, the allocated memory size(object_size) is likely
* larger than the requested size(orig_size). If redzone check is
* enabled for the extra space, don't zero it, as it will be redzoned
* soon. The redzone operation for this extra space could be seen as a
* replacement of current poisoning under certain debug option, and
* won't break other sanity checks.
* For kmalloc object, the allocated size (object_size) can be larger
* than the requested size (orig_size). We however need to zero the
* whole object_size to handle possible later krealloc() with
*__GFP_ZERO properly.
*
* But if we keep track of the requested size, krealloc() uses that
* information. Additionally if red zoning is enabled, the extra space
* is also red zone, so we should not overwrite it. So limit zeroing to
* orig_size if we track it.
*/
if (kmem_cache_debug_flags(s, SLAB_STORE_USER | SLAB_RED_ZONE) &&
(s->flags & SLAB_KMALLOC))
if (slub_debug_orig_size(s))
zero_size = orig_size;
/*

View File

@ -2504,13 +2504,56 @@ static inline int add_nested_action_start(struct sw_flow_actions **sfa,
return used;
}
static inline void add_nested_action_end(struct sw_flow_actions *sfa,
int st_offset)
static inline int add_nested_action_end(struct sw_flow_actions *sfa,
int st_offset)
{
struct nlattr *a = (struct nlattr *) ((unsigned char *)sfa->actions +
st_offset);
struct nlattr *a;
u32 attr_len;
a->nla_len = sfa->actions_len - st_offset;
if (WARN_ON_ONCE(st_offset < 0 ||
(u32)st_offset > sfa->actions_len))
return -EINVAL;
attr_len = sfa->actions_len - (u32)st_offset;
if (WARN_ON_ONCE(attr_len < NLA_HDRLEN))
return -EINVAL;
if (attr_len > U16_MAX)
return -EMSGSIZE;
a = (struct nlattr *)((u8 *)sfa->actions + st_offset);
a->nla_len = attr_len;
return 0;
}
/* Free the generated action-list tail at @start and truncate it.
* If @nested, @start points to its containing nlattr header.
*/
static void ovs_nla_trim(struct sw_flow_actions *sfa, int start, bool nested)
{
const struct nlattr *actions;
u32 len;
if (start < 0)
return;
if (WARN_ON_ONCE((u32)start > sfa->actions_len))
return;
actions = (const struct nlattr *)((u8 *)sfa->actions + start);
len = sfa->actions_len - (u32)start;
if (nested) {
if (len < NLA_HDRLEN)
goto out;
actions = (const struct nlattr *)((u8 *)actions + NLA_HDRLEN);
len -= NLA_HDRLEN;
}
ovs_nla_free_nested_actions(actions, len);
out:
sfa->actions_len = start;
}
static int __ovs_nla_copy_actions(struct net *net, const struct nlattr *attr,
@ -2530,6 +2573,7 @@ static int validate_and_copy_sample(struct net *net, const struct nlattr *attr,
const struct nlattr *attrs[OVS_SAMPLE_ATTR_MAX + 1];
const struct nlattr *probability, *actions;
const struct nlattr *a;
int actions_start;
int rem, start, err;
struct sample_arg arg;
@ -2573,18 +2617,27 @@ static int validate_and_copy_sample(struct net *net, const struct nlattr *attr,
err = ovs_nla_add_action(sfa, OVS_SAMPLE_ATTR_ARG, &arg, sizeof(arg),
log);
if (err)
return err;
goto err;
actions_start = (*sfa)->actions_len;
err = __ovs_nla_copy_actions(net, actions, key, sfa,
eth_type, vlan_tci, mpls_label_count, log,
depth + 1);
if (err)
return err;
goto err_free;
add_nested_action_end(*sfa, start);
err = add_nested_action_end(*sfa, start);
if (err)
goto err_free;
return 0;
err_free:
ovs_nla_trim(*sfa, actions_start, false);
err:
(*sfa)->actions_len = start;
return err;
}
static int validate_and_copy_dec_ttl(struct net *net,
@ -2632,18 +2685,31 @@ static int validate_and_copy_dec_ttl(struct net *net,
return start;
action_start = add_nested_action_start(sfa, OVS_DEC_TTL_ATTR_ACTION, log);
if (action_start < 0)
return action_start;
if (action_start < 0) {
err = action_start;
goto err;
}
err = __ovs_nla_copy_actions(net, actions, key, sfa, eth_type,
vlan_tci, mpls_label_count, log,
depth + 1);
if (err)
return err;
goto err_free;
add_nested_action_end(*sfa, action_start);
add_nested_action_end(*sfa, start);
err = add_nested_action_end(*sfa, action_start);
if (err)
goto err_free;
err = add_nested_action_end(*sfa, start);
if (err)
goto err_free;
return 0;
err_free:
ovs_nla_trim(*sfa, action_start, true);
err:
(*sfa)->actions_len = start;
return err;
}
static int validate_and_copy_clone(struct net *net,
@ -2654,6 +2720,7 @@ static int validate_and_copy_clone(struct net *net,
u32 mpls_label_count, bool log, bool last,
u32 depth)
{
int actions_start;
int start, err;
u32 exec;
@ -2669,17 +2736,26 @@ static int validate_and_copy_clone(struct net *net,
err = ovs_nla_add_action(sfa, OVS_CLONE_ATTR_EXEC, &exec,
sizeof(exec), log);
if (err)
return err;
goto err;
actions_start = (*sfa)->actions_len;
err = __ovs_nla_copy_actions(net, attr, key, sfa,
eth_type, vlan_tci, mpls_label_count, log,
depth + 1);
if (err)
return err;
goto err_free;
add_nested_action_end(*sfa, start);
err = add_nested_action_end(*sfa, start);
if (err)
goto err_free;
return 0;
err_free:
ovs_nla_trim(*sfa, actions_start, false);
err:
(*sfa)->actions_len = start;
return err;
}
void ovs_match_init(struct sw_flow_match *match,
@ -2771,20 +2847,20 @@ static int validate_and_copy_set_tun(const struct nlattr *attr,
tun_dst = metadata_dst_alloc(key.tun_opts_len, METADATA_IP_TUNNEL,
GFP_KERNEL);
if (!tun_dst)
return -ENOMEM;
if (!tun_dst) {
err = -ENOMEM;
goto err;
}
err = dst_cache_init(&tun_dst->u.tun_info.dst_cache, GFP_KERNEL);
if (err) {
dst_release((struct dst_entry *)tun_dst);
return err;
}
if (err)
goto err_free_tun_dst;
a = __add_action(sfa, OVS_KEY_ATTR_TUNNEL_INFO, NULL,
sizeof(*ovs_tun), log);
if (IS_ERR(a)) {
dst_release((struct dst_entry *)tun_dst);
return PTR_ERR(a);
err = PTR_ERR(a);
goto err_free_tun_dst;
}
ovs_tun = nla_data(a);
@ -2805,8 +2881,16 @@ static int validate_and_copy_set_tun(const struct nlattr *attr,
ip_tunnel_info_opts_set(tun_info,
TUN_METADATA_OPTS(&key, key.tun_opts_len),
key.tun_opts_len, dst_opt_type);
add_nested_action_end(*sfa, start);
err = add_nested_action_end(*sfa, start);
if (WARN_ON_ONCE(err))
goto err_free_tun_dst;
return 0;
err_free_tun_dst:
dst_release((struct dst_entry *)tun_dst);
err:
(*sfa)->actions_len = start;
return err;
}
@ -2981,7 +3065,7 @@ static int validate_set(const struct nlattr *a,
/* Convert non-masked non-tunnel set actions to masked set actions. */
if (!masked && key_type != OVS_KEY_ATTR_TUNNEL) {
int start, len = key_len * 2;
int err, start, len = key_len * 2;
struct nlattr *at;
*skip_copy = true;
@ -2993,8 +3077,11 @@ static int validate_set(const struct nlattr *a,
return start;
at = __add_action(sfa, key_type, NULL, len, log);
if (IS_ERR(at))
return PTR_ERR(at);
if (IS_ERR(at)) {
err = PTR_ERR(at);
(*sfa)->actions_len = start;
return err;
}
memcpy(nla_data(at), nla_data(ovs_key), key_len); /* Key. */
memset(nla_data(at) + key_len, 0xff, key_len); /* Mask. */
@ -3004,7 +3091,11 @@ static int validate_set(const struct nlattr *a,
mask->ipv6_label &= htonl(0x000FFFFF);
}
add_nested_action_end(*sfa, start);
err = add_nested_action_end(*sfa, start);
if (WARN_ON_ONCE(err)) {
(*sfa)->actions_len = start;
return err;
}
}
return 0;
@ -3050,7 +3141,8 @@ static int validate_and_copy_check_pkt_len(struct net *net,
const struct nlattr *acts_if_greater, *acts_if_lesser_eq;
struct nlattr *a[OVS_CHECK_PKT_LEN_ATTR_MAX + 1];
struct check_pkt_len_arg arg;
int nested_acts_start;
int greater_acts_start = -1;
int lesser_acts_start = -1;
int start, err;
err = nla_parse_deprecated_strict(a, OVS_CHECK_PKT_LEN_ATTR_MAX,
@ -3085,37 +3177,58 @@ static int validate_and_copy_check_pkt_len(struct net *net,
err = ovs_nla_add_action(sfa, OVS_CHECK_PKT_LEN_ATTR_ARG, &arg,
sizeof(arg), log);
if (err)
return err;
goto err_free;
nested_acts_start = add_nested_action_start(sfa,
OVS_CHECK_PKT_LEN_ATTR_ACTIONS_IF_LESS_EQUAL, log);
if (nested_acts_start < 0)
return nested_acts_start;
lesser_acts_start =
add_nested_action_start(sfa,
OVS_CHECK_PKT_LEN_ATTR_ACTIONS_IF_LESS_EQUAL,
log);
if (lesser_acts_start < 0) {
err = lesser_acts_start;
goto err_free;
}
err = __ovs_nla_copy_actions(net, acts_if_lesser_eq, key, sfa,
eth_type, vlan_tci, mpls_label_count, log,
depth + 1);
if (err)
return err;
goto err_free;
add_nested_action_end(*sfa, nested_acts_start);
err = add_nested_action_end(*sfa, lesser_acts_start);
if (err)
goto err_free;
nested_acts_start = add_nested_action_start(sfa,
OVS_CHECK_PKT_LEN_ATTR_ACTIONS_IF_GREATER, log);
if (nested_acts_start < 0)
return nested_acts_start;
greater_acts_start =
add_nested_action_start(sfa,
OVS_CHECK_PKT_LEN_ATTR_ACTIONS_IF_GREATER,
log);
if (greater_acts_start < 0) {
err = greater_acts_start;
goto err_free;
}
err = __ovs_nla_copy_actions(net, acts_if_greater, key, sfa,
eth_type, vlan_tci, mpls_label_count, log,
depth + 1);
if (err)
return err;
goto err_free;
add_nested_action_end(*sfa, nested_acts_start);
add_nested_action_end(*sfa, start);
err = add_nested_action_end(*sfa, greater_acts_start);
if (err)
goto err_free;
err = add_nested_action_end(*sfa, start);
if (err)
goto err_free;
return 0;
err_free:
ovs_nla_trim(*sfa, greater_acts_start, true);
ovs_nla_trim(*sfa, lesser_acts_start, true);
ovs_nla_trim(*sfa, start, false);
return err;
}
static int validate_psample(const struct nlattr *attr)

View File

@ -1,3 +1,23 @@
* Mon Aug 10 2026 CKI KWF Bot <cki-ci-bot+kwf-gitlab-com@redhat.com> [5.14.0-687.38.1.el9_8]
- cifs: fix time_last_write stamp placement in setattr/truncate paths (Paulo Alcantara) [RHEL-192999]
- cifs: consolidate time_last_write stamp into _cifsFileInfo_put() (Paulo Alcantara) [RHEL-192999]
- cifs: fix cifsFileInfo leak on kmalloc failure in deferred close drain paths (Paulo Alcantara) [RHEL-192999]
- cifs: prevent readdir from changing file size due to stale directory metadata (Paulo Alcantara) [RHEL-192999]
- smb: client: fix dir separator in SMB1 UNIX mounts (Paulo Alcantara) [RHEL-192999]
- smb: client: fix sbflags initialization (Paulo Alcantara) [RHEL-192999]
- smb: client: use atomic_t for mnt_cifs_flags (Paulo Alcantara) [RHEL-192999]
- mm/slab: do not limit zeroing to orig_size when only red zoning is enabled (Rafael Aquini) [RHEL-223404] {CVE-2026-64368}
Resolves: RHEL-192999, RHEL-223404
* Fri Aug 07 2026 CKI KWF Bot <cki-ci-bot+kwf-gitlab-com@redhat.com> [5.14.0-687.37.1.el9_8]
- s390/pkey: Check length in pkey_pckmo handler implementation (Ramesh Chhetri) [RHEL-215578]
- s390/pkey: Check length in PKEY_VERIFYPROTK ioctl (Ramesh Chhetri) [RHEL-215580]
- net: openvswitch: reject oversized nested action attrs (CKI Backport Bot) [RHEL-222495] {CVE-2026-64531}
- cxl/port: Fix use after free of parent_port in cxl_detach_ep() (Myron Stowe) [RHEL-180691] {CVE-2026-31530}
- net/mlx5: Fix slab-out-of-bounds in mlx5_query_nic_vport_mac_list (CKI Backport Bot) [RHEL-213036]
- x86/CPU/AMD: Prevent improper isolation of shared resources in Zen2's op cache (Dennis Chen) [RHEL-188790] {CVE-2025-54518}
Resolves: RHEL-180691, RHEL-188790, RHEL-213036, RHEL-215578, RHEL-215580, RHEL-222495
* Wed Aug 05 2026 CKI KWF Bot <cki-ci-bot+kwf-gitlab-com@redhat.com> [5.14.0-687.36.1.el9_8]
- powerpc/powernv/iommu: iommu incorrectly bypass DMA APIs (Mamatha Inamdar) [RHEL-215575]
- powerpc/iommu: bypass DMA APIs for coherent allocations for pre-mapped memory (Mamatha Inamdar) [RHEL-215575]

View File

@ -686,8 +686,9 @@
#define MSR_AMD64_LBR_SELECT 0xc000010e
/* Zen4 */
#define MSR_ZEN4_BP_CFG 0xc001102e
#define MSR_ZEN4_BP_CFG 0xc001102e
#define MSR_ZEN4_BP_CFG_SHARED_BTB_FIX_BIT 5
#define MSR_ZEN2_BP_CFG_BUG_FIX_BIT 33
/* Fam 19h MSRs */
#define MSR_F19H_UMC_PERF_CTL 0xc0010800