40 cifs/smb3 changesets, including 4 for stable
-----BEGIN PGP SIGNATURE----- iQGzBAABCgAdFiEE6fsu8pdIjtWE/DpLiiy9cAdyT1EFAmCHFqEACgkQiiy9cAdy T1FLpQv9F3JpIUOCODcrUe7wn51R7Of38QU6YP1nu4df0SN40KXjIBiweTKF3W7v qtLHNtHCjmxiirlCRpmLO7rCwf59Y31UweQTQa47XosgZZWKfp8PhsUuRib2WDLa /Sw4SBlmVktg4hutxvTiWYW2AbAMZhfTP1SHt61BXItUwt9c2boTBfsqpF0PbYh/ 39AOlFgJ6HVYS4G1YLTQ29kNU/qNkFtY9M4PH4Km68tyL5MP14s35Ee1+cIxtuFT 0FGYXl+D3RhXxU/jN8YfdRBfG8AoA0xFEr59HhJnmaoCd9fa8f3PNBn1pX4KcPuS EhvymK6FfFZk25Y/bcrZhsbJ8eNtx3o7dy7MFNaKeHneFnVvKOAQTtqrRQrj+O2K byV1KgXy0SDaJTKMzPSZTldf42ZvQhCMS0Rd5cRt226gly0CVwMAMqwb8M/SaGVJ dus00y05XybVVApsj8/ZizZgtXTJDyFyfcc2MMx3aNIkg6sB74TwH1XE37U7al8n y64KPcMw =6NqG -----END PGP SIGNATURE----- Merge tag '5.12-rc-smb3-fixes-part1' of git://git.samba.org/sfrench/cifs-2.6 Pull cifs updates from Steve French: - improvements to root directory metadata caching - addition of new "rasize" mount parameter which can significantly increase read ahead performance (e.g. copy can be much faster, especially with multichannel) - addition of support for insert and collapse range - improvements to error handling in mount * tag '5.12-rc-smb3-fixes-part1' of git://git.samba.org/sfrench/cifs-2.6: (40 commits) cifs: update internal version number smb3: add rasize mount parameter to improve readahead performance smb3: limit noisy error cifs: fix leak in cifs_smb3_do_mount() ctx cifs: remove unnecessary copies of tcon->crfid.fid cifs: Return correct error code from smb2_get_enc_key cifs: fix out-of-bound memory access when calling smb3_notify() at mount point smb2: fix use-after-free in smb2_ioctl_query_info() cifs: export supported mount options via new mount_params /proc file cifs: log mount errors using cifs_errorf() cifs: add fs_context param to parsing helpers cifs: make fs_context error logging wrapper cifs: add FALLOC_FL_INSERT_RANGE support cifs: add support for FALLOC_FL_COLLAPSE_RANGE cifs: check the timestamp for the cached dirent when deciding on revalidate cifs: pass the dentry instead of the inode down to the revalidation check functions cifs: add a timestamp to track when the lease of the cached dir was taken cifs: add a function to get a cached dir based on its dentry cifs: Grab a reference for the dentry of the cached directory during the lifetime of the cache cifs: store a pointer to the root dentry in cifs_sb_info once we have completed mounting the share ...
This commit is contained in:
commit
2a19866b6e
@ -714,6 +714,7 @@ DebugData Displays information about active CIFS sessions and
|
||||
version.
|
||||
Stats Lists summary resource usage information as well as per
|
||||
share statistics.
|
||||
open_files List all the open file handles on all active SMB sessions.
|
||||
======================= =======================================================
|
||||
|
||||
Configuration pseudo-files:
|
||||
@ -794,6 +795,8 @@ LinuxExtensionsEnabled If set to one then the client will attempt to
|
||||
support and want to map the uid and gid fields
|
||||
to values supplied at mount (rather than the
|
||||
actual values, then set this to zero. (default 1)
|
||||
dfscache List the content of the DFS cache.
|
||||
If set to 0, the client will clear the cache.
|
||||
======================= =======================================================
|
||||
|
||||
These experimental features and tracing can be enabled by changing flags in
|
||||
|
@ -17,15 +17,14 @@
|
||||
#include "cifsproto.h"
|
||||
#include "cifs_debug.h"
|
||||
#include "cifsfs.h"
|
||||
#include "fs_context.h"
|
||||
#ifdef CONFIG_CIFS_DFS_UPCALL
|
||||
#include "dfs_cache.h"
|
||||
#endif
|
||||
#ifdef CONFIG_CIFS_SMB_DIRECT
|
||||
#include "smbdirect.h"
|
||||
#endif
|
||||
#ifdef CONFIG_CIFS_SWN_UPCALL
|
||||
#include "cifs_swn.h"
|
||||
#endif
|
||||
|
||||
void
|
||||
cifs_dump_mem(char *label, void *data, int length)
|
||||
@ -118,10 +117,8 @@ static void cifs_debug_tcon(struct seq_file *m, struct cifs_tcon *tcon)
|
||||
seq_printf(m, " POSIX Extensions");
|
||||
if (tcon->ses->server->ops->dump_share_caps)
|
||||
tcon->ses->server->ops->dump_share_caps(m, tcon);
|
||||
#ifdef CONFIG_CIFS_SWN_UPCALL
|
||||
if (tcon->use_witness)
|
||||
seq_puts(m, " Witness");
|
||||
#endif
|
||||
|
||||
if (tcon->need_reconnect)
|
||||
seq_puts(m, "\tDISCONNECTED ");
|
||||
@ -490,10 +487,8 @@ skip_rdma:
|
||||
|
||||
spin_unlock(&cifs_tcp_ses_lock);
|
||||
seq_putc(m, '\n');
|
||||
|
||||
#ifdef CONFIG_CIFS_SWN_UPCALL
|
||||
cifs_swn_dump(m);
|
||||
#endif
|
||||
|
||||
/* BB add code to dump additional info such as TCP session info now */
|
||||
return 0;
|
||||
}
|
||||
@ -702,6 +697,7 @@ static const struct proc_ops cifs_lookup_cache_proc_ops;
|
||||
static const struct proc_ops traceSMB_proc_ops;
|
||||
static const struct proc_ops cifs_security_flags_proc_ops;
|
||||
static const struct proc_ops cifs_linux_ext_proc_ops;
|
||||
static const struct proc_ops cifs_mount_params_proc_ops;
|
||||
|
||||
void
|
||||
cifs_proc_init(void)
|
||||
@ -726,6 +722,8 @@ cifs_proc_init(void)
|
||||
proc_create("LookupCacheEnabled", 0644, proc_fs_cifs,
|
||||
&cifs_lookup_cache_proc_ops);
|
||||
|
||||
proc_create("mount_params", 0444, proc_fs_cifs, &cifs_mount_params_proc_ops);
|
||||
|
||||
#ifdef CONFIG_CIFS_DFS_UPCALL
|
||||
proc_create("dfscache", 0644, proc_fs_cifs, &dfscache_proc_ops);
|
||||
#endif
|
||||
@ -764,6 +762,7 @@ cifs_proc_clean(void)
|
||||
remove_proc_entry("SecurityFlags", proc_fs_cifs);
|
||||
remove_proc_entry("LinuxExtensionsEnabled", proc_fs_cifs);
|
||||
remove_proc_entry("LookupCacheEnabled", proc_fs_cifs);
|
||||
remove_proc_entry("mount_params", proc_fs_cifs);
|
||||
|
||||
#ifdef CONFIG_CIFS_DFS_UPCALL
|
||||
remove_proc_entry("dfscache", proc_fs_cifs);
|
||||
@ -1023,6 +1022,51 @@ static const struct proc_ops cifs_security_flags_proc_ops = {
|
||||
.proc_release = single_release,
|
||||
.proc_write = cifs_security_flags_proc_write,
|
||||
};
|
||||
|
||||
/* To make it easier to debug, can help to show mount params */
|
||||
static int cifs_mount_params_proc_show(struct seq_file *m, void *v)
|
||||
{
|
||||
const struct fs_parameter_spec *p;
|
||||
const char *type;
|
||||
|
||||
for (p = smb3_fs_parameters; p->name; p++) {
|
||||
/* cannot use switch with pointers... */
|
||||
if (!p->type) {
|
||||
if (p->flags == fs_param_neg_with_no)
|
||||
type = "noflag";
|
||||
else
|
||||
type = "flag";
|
||||
} else if (p->type == fs_param_is_bool)
|
||||
type = "bool";
|
||||
else if (p->type == fs_param_is_u32)
|
||||
type = "u32";
|
||||
else if (p->type == fs_param_is_u64)
|
||||
type = "u64";
|
||||
else if (p->type == fs_param_is_string)
|
||||
type = "string";
|
||||
else
|
||||
type = "unknown";
|
||||
|
||||
seq_printf(m, "%s:%s\n", p->name, type);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int cifs_mount_params_proc_open(struct inode *inode, struct file *file)
|
||||
{
|
||||
return single_open(file, cifs_mount_params_proc_show, NULL);
|
||||
}
|
||||
|
||||
static const struct proc_ops cifs_mount_params_proc_ops = {
|
||||
.proc_open = cifs_mount_params_proc_open,
|
||||
.proc_read = seq_read,
|
||||
.proc_lseek = seq_lseek,
|
||||
.proc_release = single_release,
|
||||
/* No need for write for now */
|
||||
/* .proc_write = cifs_mount_params_proc_write, */
|
||||
};
|
||||
|
||||
#else
|
||||
inline void cifs_proc_init(void)
|
||||
{
|
||||
|
@ -270,7 +270,7 @@ static struct vfsmount *cifs_dfs_do_mount(struct dentry *mntpt,
|
||||
char *mountdata;
|
||||
char *devname;
|
||||
|
||||
devname = kstrndup(fullpath, strlen(fullpath), GFP_KERNEL);
|
||||
devname = kstrdup(fullpath, GFP_KERNEL);
|
||||
if (!devname)
|
||||
return ERR_PTR(-ENOMEM);
|
||||
|
||||
@ -302,6 +302,7 @@ static struct vfsmount *cifs_dfs_do_automount(struct dentry *mntpt)
|
||||
struct cifs_sb_info *cifs_sb;
|
||||
struct cifs_ses *ses;
|
||||
struct cifs_tcon *tcon;
|
||||
void *page;
|
||||
char *full_path, *root_path;
|
||||
unsigned int xid;
|
||||
int rc;
|
||||
@ -324,10 +325,13 @@ static struct vfsmount *cifs_dfs_do_automount(struct dentry *mntpt)
|
||||
goto cdda_exit;
|
||||
}
|
||||
|
||||
page = alloc_dentry_path();
|
||||
/* always use tree name prefix */
|
||||
full_path = build_path_from_dentry_optional_prefix(mntpt, true);
|
||||
if (full_path == NULL)
|
||||
goto cdda_exit;
|
||||
full_path = build_path_from_dentry_optional_prefix(mntpt, page, true);
|
||||
if (IS_ERR(full_path)) {
|
||||
mnt = ERR_CAST(full_path);
|
||||
goto free_full_path;
|
||||
}
|
||||
|
||||
convert_delimiter(full_path, '\\');
|
||||
|
||||
@ -385,7 +389,7 @@ static struct vfsmount *cifs_dfs_do_automount(struct dentry *mntpt)
|
||||
free_root_path:
|
||||
kfree(root_path);
|
||||
free_full_path:
|
||||
kfree(full_path);
|
||||
free_dentry_path(page);
|
||||
cdda_exit:
|
||||
cifs_dbg(FYI, "leaving %s\n" , __func__);
|
||||
return mnt;
|
||||
|
@ -81,5 +81,9 @@ struct cifs_sb_info {
|
||||
* (cifs_autodisable_serverino) in order to match new mounts.
|
||||
*/
|
||||
bool mnt_cifs_serverino_autodisabled;
|
||||
/*
|
||||
* Available once the mount has completed.
|
||||
*/
|
||||
struct dentry *root;
|
||||
};
|
||||
#endif /* _CIFS_FS_SB_H */
|
||||
|
@ -7,11 +7,13 @@
|
||||
|
||||
#ifndef _CIFS_SWN_H
|
||||
#define _CIFS_SWN_H
|
||||
#include "cifsglob.h"
|
||||
|
||||
struct cifs_tcon;
|
||||
struct sk_buff;
|
||||
struct genl_info;
|
||||
|
||||
#ifdef CONFIG_CIFS_SWN_UPCALL
|
||||
extern int cifs_swn_register(struct cifs_tcon *tcon);
|
||||
|
||||
extern int cifs_swn_unregister(struct cifs_tcon *tcon);
|
||||
@ -22,4 +24,29 @@ extern void cifs_swn_dump(struct seq_file *m);
|
||||
|
||||
extern void cifs_swn_check(void);
|
||||
|
||||
static inline bool cifs_swn_set_server_dstaddr(struct TCP_Server_Info *server)
|
||||
{
|
||||
if (server->use_swn_dstaddr) {
|
||||
server->dstaddr = server->swn_dstaddr;
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
static inline void cifs_swn_reset_server_dstaddr(struct TCP_Server_Info *server)
|
||||
{
|
||||
server->use_swn_dstaddr = false;
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
static inline int cifs_swn_register(struct cifs_tcon *tcon) { return 0; }
|
||||
static inline int cifs_swn_unregister(struct cifs_tcon *tcon) { return 0; }
|
||||
static inline int cifs_swn_notify(struct sk_buff *s, struct genl_info *i) { return 0; }
|
||||
static inline void cifs_swn_dump(struct seq_file *m) {}
|
||||
static inline void cifs_swn_check(void) {}
|
||||
static inline bool cifs_swn_set_server_dstaddr(struct TCP_Server_Info *server) { return false; }
|
||||
static inline void cifs_swn_reset_server_dstaddr(struct TCP_Server_Info *server) {}
|
||||
|
||||
#endif /* CONFIG_CIFS_SWN_UPCALL */
|
||||
#endif /* _CIFS_SWN_H */
|
||||
|
@ -1094,11 +1094,9 @@ static int set_chmod_dacl(struct cifs_acl *pdacl, struct cifs_acl *pndacl,
|
||||
struct cifs_ace *pnntace = NULL;
|
||||
char *nacl_base = NULL;
|
||||
u32 num_aces = 0;
|
||||
__u64 nmode;
|
||||
bool new_aces_set = false;
|
||||
|
||||
/* Assuming that pndacl and pnmode are never NULL */
|
||||
nmode = *pnmode;
|
||||
nacl_base = (char *)pndacl;
|
||||
nsize = sizeof(struct cifs_acl);
|
||||
|
||||
@ -1651,7 +1649,7 @@ id_mode_to_cifs_acl(struct inode *inode, const char *path, __u64 *pnmode,
|
||||
* Add three ACEs for owner, group, everyone getting rid of other ACEs
|
||||
* as chmod disables ACEs and set the security descriptor. Allocate
|
||||
* memory for the smb header, set security descriptor request security
|
||||
* descriptor parameters, and secuirty descriptor itself
|
||||
* descriptor parameters, and security descriptor itself
|
||||
*/
|
||||
nsecdesclen = max_t(u32, nsecdesclen, DEFAULT_SEC_DESC_LEN);
|
||||
pnntsd = kmalloc(nsecdesclen, GFP_KERNEL);
|
||||
|
@ -217,8 +217,11 @@ cifs_read_super(struct super_block *sb)
|
||||
rc = super_setup_bdi(sb);
|
||||
if (rc)
|
||||
goto out_no_root;
|
||||
/* tune readahead according to rsize */
|
||||
sb->s_bdi->ra_pages = cifs_sb->ctx->rsize / PAGE_SIZE;
|
||||
/* tune readahead according to rsize if readahead size not set on mount */
|
||||
if (cifs_sb->ctx->rasize)
|
||||
sb->s_bdi->ra_pages = cifs_sb->ctx->rasize / PAGE_SIZE;
|
||||
else
|
||||
sb->s_bdi->ra_pages = cifs_sb->ctx->rsize / PAGE_SIZE;
|
||||
|
||||
sb->s_blocksize = CIFS_MAX_MSGSIZE;
|
||||
sb->s_blocksize_bits = 14; /* default 2**14 = CIFS_MAX_MSGSIZE */
|
||||
@ -257,6 +260,29 @@ out_no_root:
|
||||
static void cifs_kill_sb(struct super_block *sb)
|
||||
{
|
||||
struct cifs_sb_info *cifs_sb = CIFS_SB(sb);
|
||||
struct cifs_tcon *tcon;
|
||||
struct cached_fid *cfid;
|
||||
|
||||
/*
|
||||
* We ned to release all dentries for the cached directories
|
||||
* before we kill the sb.
|
||||
*/
|
||||
if (cifs_sb->root) {
|
||||
dput(cifs_sb->root);
|
||||
cifs_sb->root = NULL;
|
||||
}
|
||||
tcon = cifs_sb_master_tcon(cifs_sb);
|
||||
if (tcon) {
|
||||
cfid = &tcon->crfid;
|
||||
mutex_lock(&cfid->fid_mutex);
|
||||
if (cfid->dentry) {
|
||||
|
||||
dput(cfid->dentry);
|
||||
cfid->dentry = NULL;
|
||||
}
|
||||
mutex_unlock(&cfid->fid_mutex);
|
||||
}
|
||||
|
||||
kill_anon_super(sb);
|
||||
cifs_umount(cifs_sb);
|
||||
}
|
||||
@ -626,6 +652,8 @@ cifs_show_options(struct seq_file *s, struct dentry *root)
|
||||
seq_printf(s, ",rsize=%u", cifs_sb->ctx->rsize);
|
||||
seq_printf(s, ",wsize=%u", cifs_sb->ctx->wsize);
|
||||
seq_printf(s, ",bsize=%u", cifs_sb->ctx->bsize);
|
||||
if (cifs_sb->ctx->rasize)
|
||||
seq_printf(s, ",rasize=%u", cifs_sb->ctx->rasize);
|
||||
if (tcon->ses->server->min_offload)
|
||||
seq_printf(s, ",esize=%u", tcon->ses->server->min_offload);
|
||||
seq_printf(s, ",echo_interval=%lu",
|
||||
@ -656,10 +684,8 @@ cifs_show_options(struct seq_file *s, struct dentry *root)
|
||||
seq_printf(s, ",multichannel,max_channels=%zu",
|
||||
tcon->ses->chan_max);
|
||||
|
||||
#ifdef CONFIG_CIFS_SWN_UPCALL
|
||||
if (tcon->use_witness)
|
||||
seq_puts(s, ",witness");
|
||||
#endif
|
||||
|
||||
return 0;
|
||||
}
|
||||
@ -834,6 +860,12 @@ cifs_smb3_do_mount(struct file_system_type *fs_type,
|
||||
goto out;
|
||||
}
|
||||
|
||||
/* cifs_setup_volume_info->smb3_parse_devname() redups UNC & prepath */
|
||||
kfree(cifs_sb->ctx->UNC);
|
||||
cifs_sb->ctx->UNC = NULL;
|
||||
kfree(cifs_sb->ctx->prepath);
|
||||
cifs_sb->ctx->prepath = NULL;
|
||||
|
||||
rc = cifs_setup_volume_info(cifs_sb->ctx, NULL, old_ctx->UNC);
|
||||
if (rc) {
|
||||
root = ERR_PTR(rc);
|
||||
@ -888,6 +920,9 @@ cifs_smb3_do_mount(struct file_system_type *fs_type,
|
||||
if (IS_ERR(root))
|
||||
goto out_super;
|
||||
|
||||
if (cifs_sb)
|
||||
cifs_sb->root = dget(root);
|
||||
|
||||
cifs_dbg(FYI, "dentry root is: %p\n", root);
|
||||
return root;
|
||||
|
||||
@ -1528,10 +1563,6 @@ init_cifs(void)
|
||||
int rc = 0;
|
||||
cifs_proc_init();
|
||||
INIT_LIST_HEAD(&cifs_tcp_ses_list);
|
||||
#ifdef CONFIG_CIFS_DNOTIFY_EXPERIMENTAL /* unused temporarily */
|
||||
INIT_LIST_HEAD(&GlobalDnotifyReqList);
|
||||
INIT_LIST_HEAD(&GlobalDnotifyRsp_Q);
|
||||
#endif /* was needed for dnotify, and will be needed for inotify when VFS fix */
|
||||
/*
|
||||
* Initialize Global counters
|
||||
*/
|
||||
|
@ -165,5 +165,5 @@ extern struct dentry *cifs_smb3_do_mount(struct file_system_type *fs_type,
|
||||
extern const struct export_operations cifs_export_ops;
|
||||
#endif /* CONFIG_CIFS_NFSD_EXPORT */
|
||||
|
||||
#define CIFS_VERSION "2.31"
|
||||
#define CIFS_VERSION "2.32"
|
||||
#endif /* _CIFSFS_H */
|
||||
|
@ -495,7 +495,7 @@ struct smb_version_operations {
|
||||
struct inode *inode,
|
||||
struct dentry *dentry,
|
||||
struct cifs_tcon *tcon,
|
||||
char *full_path,
|
||||
const char *full_path,
|
||||
umode_t mode,
|
||||
dev_t device_number);
|
||||
/* version specific fiemap implementation */
|
||||
@ -988,10 +988,12 @@ struct cached_fid {
|
||||
bool is_valid:1; /* Do we have a useable root fid */
|
||||
bool file_all_info_is_valid:1;
|
||||
bool has_lease:1;
|
||||
unsigned long time; /* jiffies of when lease was taken */
|
||||
struct kref refcount;
|
||||
struct cifs_fid *fid;
|
||||
struct mutex fid_mutex;
|
||||
struct cifs_tcon *tcon;
|
||||
struct dentry *dentry;
|
||||
struct work_struct lease_break;
|
||||
struct smb2_file_all_info file_all_info;
|
||||
};
|
||||
@ -1070,6 +1072,7 @@ struct cifs_tcon {
|
||||
bool use_resilient:1; /* use resilient instead of durable handles */
|
||||
bool use_persistent:1; /* use persistent instead of durable handles */
|
||||
bool no_lease:1; /* Do not request leases on files or directories */
|
||||
bool use_witness:1; /* use witness protocol */
|
||||
__le32 capabilities;
|
||||
__u32 share_flags;
|
||||
__u32 maximal_access;
|
||||
@ -1094,9 +1097,6 @@ struct cifs_tcon {
|
||||
int remap:2;
|
||||
struct list_head ulist; /* cache update list */
|
||||
#endif
|
||||
#ifdef CONFIG_CIFS_SWN_UPCALL
|
||||
bool use_witness:1; /* use witness protocol */
|
||||
#endif
|
||||
};
|
||||
|
||||
/*
|
||||
@ -1316,8 +1316,6 @@ struct cifs_readdata {
|
||||
struct page **pages;
|
||||
};
|
||||
|
||||
struct cifs_writedata;
|
||||
|
||||
/* asynchronous write support */
|
||||
struct cifs_writedata {
|
||||
struct kref refcount;
|
||||
@ -1796,9 +1794,8 @@ require use of the stronger protocol */
|
||||
*
|
||||
* Semaphores
|
||||
* ----------
|
||||
* sesSem operations on smb session
|
||||
* tconSem operations on tree connection
|
||||
* fh_sem file handle reconnection operations
|
||||
* cifsInodeInfo->lock_sem protects:
|
||||
* the list of locks held by the inode
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
@ -1829,13 +1826,6 @@ GLOBAL_EXTERN struct list_head cifs_tcp_ses_list;
|
||||
*/
|
||||
GLOBAL_EXTERN spinlock_t cifs_tcp_ses_lock;
|
||||
|
||||
#ifdef CONFIG_CIFS_DNOTIFY_EXPERIMENTAL /* unused temporarily */
|
||||
/* Outstanding dir notify requests */
|
||||
GLOBAL_EXTERN struct list_head GlobalDnotifyReqList;
|
||||
/* DirNotify response queue */
|
||||
GLOBAL_EXTERN struct list_head GlobalDnotifyRsp_Q;
|
||||
#endif /* was needed for dnotify, and will be needed for inotify when VFS fix */
|
||||
|
||||
/*
|
||||
* Global transaction id (XID) information
|
||||
*/
|
||||
@ -1879,19 +1869,9 @@ extern unsigned int cifs_min_small; /* min size of small buf pool */
|
||||
extern unsigned int cifs_max_pending; /* MAX requests at once to server*/
|
||||
extern bool disable_legacy_dialects; /* forbid vers=1.0 and vers=2.0 mounts */
|
||||
|
||||
GLOBAL_EXTERN struct rb_root uidtree;
|
||||
GLOBAL_EXTERN struct rb_root gidtree;
|
||||
GLOBAL_EXTERN spinlock_t siduidlock;
|
||||
GLOBAL_EXTERN spinlock_t sidgidlock;
|
||||
GLOBAL_EXTERN struct rb_root siduidtree;
|
||||
GLOBAL_EXTERN struct rb_root sidgidtree;
|
||||
GLOBAL_EXTERN spinlock_t uidsidlock;
|
||||
GLOBAL_EXTERN spinlock_t gidsidlock;
|
||||
|
||||
void cifs_oplock_break(struct work_struct *work);
|
||||
void cifs_queue_oplock_break(struct cifsFileInfo *cfile);
|
||||
|
||||
extern const struct slow_work_ops cifs_oplock_break_ops;
|
||||
extern struct workqueue_struct *cifsiod_wq;
|
||||
extern struct workqueue_struct *decrypt_wq;
|
||||
extern struct workqueue_struct *fileinfo_put_wq;
|
||||
|
@ -1903,7 +1903,7 @@ typedef struct smb_com_transaction2_fnext_req {
|
||||
__le16 InformationLevel;
|
||||
__u32 ResumeKey;
|
||||
__le16 SearchFlags;
|
||||
char ResumeFileName[1];
|
||||
char ResumeFileName[];
|
||||
} __attribute__((packed)) TRANSACTION2_FNEXT_REQ;
|
||||
|
||||
typedef struct smb_com_transaction2_fnext_rsp {
|
||||
|
@ -69,9 +69,20 @@ extern int init_cifs_idmap(void);
|
||||
extern void exit_cifs_idmap(void);
|
||||
extern int init_cifs_spnego(void);
|
||||
extern void exit_cifs_spnego(void);
|
||||
extern char *build_path_from_dentry(struct dentry *);
|
||||
extern const char *build_path_from_dentry(struct dentry *, void *);
|
||||
extern char *build_path_from_dentry_optional_prefix(struct dentry *direntry,
|
||||
bool prefix);
|
||||
void *page, bool prefix);
|
||||
static inline void *alloc_dentry_path(void)
|
||||
{
|
||||
return __getname();
|
||||
}
|
||||
|
||||
static inline void free_dentry_path(void *page)
|
||||
{
|
||||
if (page)
|
||||
__putname(page);
|
||||
}
|
||||
|
||||
extern char *cifs_build_path_to_root(struct smb3_fs_context *ctx,
|
||||
struct cifs_sb_info *cifs_sb,
|
||||
struct cifs_tcon *tcon,
|
||||
@ -184,7 +195,7 @@ extern struct cifsFileInfo *cifs_new_fileinfo(struct cifs_fid *fid,
|
||||
struct file *file,
|
||||
struct tcon_link *tlink,
|
||||
__u32 oplock);
|
||||
extern int cifs_posix_open(char *full_path, struct inode **inode,
|
||||
extern int cifs_posix_open(const char *full_path, struct inode **inode,
|
||||
struct super_block *sb, int mode,
|
||||
unsigned int f_flags, __u32 *oplock, __u16 *netfid,
|
||||
unsigned int xid);
|
||||
@ -207,7 +218,7 @@ extern int cifs_get_inode_info_unix(struct inode **pinode,
|
||||
const unsigned char *search_path,
|
||||
struct super_block *sb, unsigned int xid);
|
||||
extern int cifs_set_file_info(struct inode *inode, struct iattr *attrs,
|
||||
unsigned int xid, char *full_path, __u32 dosattr);
|
||||
unsigned int xid, const char *full_path, __u32 dosattr);
|
||||
extern int cifs_rename_pending_delete(const char *full_path,
|
||||
struct dentry *dentry,
|
||||
const unsigned int xid);
|
||||
@ -358,11 +369,6 @@ extern int CIFSSMBSetFileDisposition(const unsigned int xid,
|
||||
struct cifs_tcon *tcon,
|
||||
bool delete_file, __u16 fid,
|
||||
__u32 pid_of_opener);
|
||||
#if 0
|
||||
extern int CIFSSMBSetAttrLegacy(unsigned int xid, struct cifs_tcon *tcon,
|
||||
char *fileName, __u16 dos_attributes,
|
||||
const struct nls_table *nls_codepage);
|
||||
#endif /* possibly unneeded function */
|
||||
extern int CIFSSMBSetEOF(const unsigned int xid, struct cifs_tcon *tcon,
|
||||
const char *file_name, __u64 size,
|
||||
struct cifs_sb_info *cifs_sb, bool set_allocation);
|
||||
@ -504,12 +510,6 @@ extern int generate_smb311signingkey(struct cifs_ses *);
|
||||
extern int calc_lanman_hash(const char *password, const char *cryptkey,
|
||||
bool encrypt, char *lnm_session_key);
|
||||
#endif /* CIFS_WEAK_PW_HASH */
|
||||
#ifdef CONFIG_CIFS_DNOTIFY_EXPERIMENTAL /* unused temporarily */
|
||||
extern int CIFSSMBNotify(const unsigned int xid, struct cifs_tcon *tcon,
|
||||
const int notify_subdirs, const __u16 netfid,
|
||||
__u32 filter, struct file *file, int multishot,
|
||||
const struct nls_table *nls_codepage);
|
||||
#endif /* was needed for dnotify, and will be needed for inotify when VFS fix */
|
||||
extern int CIFSSMBCopy(unsigned int xid,
|
||||
struct cifs_tcon *source_tcon,
|
||||
const char *fromName,
|
||||
|
@ -114,7 +114,7 @@ cifs_mark_open_files_invalid(struct cifs_tcon *tcon)
|
||||
mutex_lock(&tcon->crfid.fid_mutex);
|
||||
tcon->crfid.is_valid = false;
|
||||
/* cached handle is not valid, so SMB2_CLOSE won't be sent below */
|
||||
close_shroot_lease_locked(&tcon->crfid);
|
||||
close_cached_dir_lease_locked(&tcon->crfid);
|
||||
memset(tcon->crfid.fid, 0, sizeof(struct cifs_fid));
|
||||
mutex_unlock(&tcon->crfid.fid_mutex);
|
||||
|
||||
@ -5917,56 +5917,6 @@ SetTimesRetry:
|
||||
return rc;
|
||||
}
|
||||
|
||||
/* Can not be used to set time stamps yet (due to old DOS time format) */
|
||||
/* Can be used to set attributes */
|
||||
#if 0 /* Possibly not needed - since it turns out that strangely NT4 has a bug
|
||||
handling it anyway and NT4 was what we thought it would be needed for
|
||||
Do not delete it until we prove whether needed for Win9x though */
|
||||
int
|
||||
CIFSSMBSetAttrLegacy(unsigned int xid, struct cifs_tcon *tcon, char *fileName,
|
||||
__u16 dos_attrs, const struct nls_table *nls_codepage)
|
||||
{
|
||||
SETATTR_REQ *pSMB = NULL;
|
||||
SETATTR_RSP *pSMBr = NULL;
|
||||
int rc = 0;
|
||||
int bytes_returned;
|
||||
int name_len;
|
||||
|
||||
cifs_dbg(FYI, "In SetAttrLegacy\n");
|
||||
|
||||
SetAttrLgcyRetry:
|
||||
rc = smb_init(SMB_COM_SETATTR, 8, tcon, (void **) &pSMB,
|
||||
(void **) &pSMBr);
|
||||
if (rc)
|
||||
return rc;
|
||||
|
||||
if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
|
||||
name_len =
|
||||
ConvertToUTF16((__le16 *) pSMB->fileName, fileName,
|
||||
PATH_MAX, nls_codepage);
|
||||
name_len++; /* trailing null */
|
||||
name_len *= 2;
|
||||
} else {
|
||||
name_len = copy_path_name(pSMB->fileName, fileName);
|
||||
}
|
||||
pSMB->attr = cpu_to_le16(dos_attrs);
|
||||
pSMB->BufferFormat = 0x04;
|
||||
inc_rfc1001_len(pSMB, name_len + 1);
|
||||
pSMB->ByteCount = cpu_to_le16(name_len + 1);
|
||||
rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
|
||||
(struct smb_hdr *) pSMBr, &bytes_returned, 0);
|
||||
if (rc)
|
||||
cifs_dbg(FYI, "Error in LegacySetAttr = %d\n", rc);
|
||||
|
||||
cifs_buf_release(pSMB);
|
||||
|
||||
if (rc == -EAGAIN)
|
||||
goto SetAttrLgcyRetry;
|
||||
|
||||
return rc;
|
||||
}
|
||||
#endif /* temporarily unneeded SetAttr legacy function */
|
||||
|
||||
static void
|
||||
cifs_fill_unix_set_info(FILE_UNIX_BASIC_INFO *data_offset,
|
||||
const struct cifs_unix_set_info_args *args)
|
||||
|
@ -62,9 +62,7 @@
|
||||
#include "dfs_cache.h"
|
||||
#endif
|
||||
#include "fs_context.h"
|
||||
#ifdef CONFIG_CIFS_SWN_UPCALL
|
||||
#include "cifs_swn.h"
|
||||
#endif
|
||||
|
||||
extern mempool_t *cifs_req_poolp;
|
||||
extern bool disable_legacy_dialects;
|
||||
@ -314,12 +312,8 @@ cifs_reconnect(struct TCP_Server_Info *server)
|
||||
|
||||
mutex_lock(&server->srv_mutex);
|
||||
|
||||
#ifdef CONFIG_CIFS_SWN_UPCALL
|
||||
if (server->use_swn_dstaddr) {
|
||||
server->dstaddr = server->swn_dstaddr;
|
||||
} else {
|
||||
#endif
|
||||
|
||||
if (!cifs_swn_set_server_dstaddr(server)) {
|
||||
#ifdef CONFIG_CIFS_DFS_UPCALL
|
||||
if (cifs_sb && cifs_sb->origin_fullpath)
|
||||
/*
|
||||
@ -344,9 +338,7 @@ cifs_reconnect(struct TCP_Server_Info *server)
|
||||
#endif
|
||||
|
||||
|
||||
#ifdef CONFIG_CIFS_SWN_UPCALL
|
||||
}
|
||||
#endif
|
||||
|
||||
if (cifs_rdma_enabled(server))
|
||||
rc = smbd_reconnect(server);
|
||||
@ -363,9 +355,7 @@ cifs_reconnect(struct TCP_Server_Info *server)
|
||||
if (server->tcpStatus != CifsExiting)
|
||||
server->tcpStatus = CifsNeedNegotiate;
|
||||
spin_unlock(&GlobalMid_Lock);
|
||||
#ifdef CONFIG_CIFS_SWN_UPCALL
|
||||
server->use_swn_dstaddr = false;
|
||||
#endif
|
||||
cifs_swn_reset_server_dstaddr(server);
|
||||
mutex_unlock(&server->srv_mutex);
|
||||
}
|
||||
} while (server->tcpStatus == CifsNeedReconnect);
|
||||
@ -430,10 +420,8 @@ cifs_echo_request(struct work_struct *work)
|
||||
cifs_dbg(FYI, "Unable to send echo request to server: %s\n",
|
||||
server->hostname);
|
||||
|
||||
#ifdef CONFIG_CIFS_SWN_UPCALL
|
||||
/* Check witness registrations */
|
||||
cifs_swn_check();
|
||||
#endif
|
||||
|
||||
requeue_echo:
|
||||
queue_delayed_work(cifsiod_wq, &server->echo, server->echo_interval);
|
||||
@ -1790,9 +1778,7 @@ cifs_set_cifscreds(struct smb3_fs_context *ctx, struct cifs_ses *ses)
|
||||
* for the request.
|
||||
*/
|
||||
if (is_domain && ses->domainName) {
|
||||
ctx->domainname = kstrndup(ses->domainName,
|
||||
strlen(ses->domainName),
|
||||
GFP_KERNEL);
|
||||
ctx->domainname = kstrdup(ses->domainName, GFP_KERNEL);
|
||||
if (!ctx->domainname) {
|
||||
cifs_dbg(FYI, "Unable to allocate %zd bytes for domain\n",
|
||||
len);
|
||||
@ -2009,7 +1995,6 @@ cifs_put_tcon(struct cifs_tcon *tcon)
|
||||
return;
|
||||
}
|
||||
|
||||
#ifdef CONFIG_CIFS_SWN_UPCALL
|
||||
if (tcon->use_witness) {
|
||||
int rc;
|
||||
|
||||
@ -2019,7 +2004,6 @@ cifs_put_tcon(struct cifs_tcon *tcon)
|
||||
__func__, rc);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
list_del_init(&tcon->tcon_list);
|
||||
spin_unlock(&cifs_tcp_ses_lock);
|
||||
@ -2181,9 +2165,9 @@ cifs_get_tcon(struct cifs_ses *ses, struct smb3_fs_context *ctx)
|
||||
}
|
||||
tcon->use_resilient = true;
|
||||
}
|
||||
#ifdef CONFIG_CIFS_SWN_UPCALL
|
||||
|
||||
tcon->use_witness = false;
|
||||
if (ctx->witness) {
|
||||
if (IS_ENABLED(CONFIG_CIFS_SWN_UPCALL) && ctx->witness) {
|
||||
if (ses->server->vals->protocol_id >= SMB30_PROT_ID) {
|
||||
if (tcon->capabilities & SMB2_SHARE_CAP_CLUSTER) {
|
||||
/*
|
||||
@ -2209,7 +2193,6 @@ cifs_get_tcon(struct cifs_ses *ses, struct smb3_fs_context *ctx)
|
||||
goto out_fail;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
/* If the user really knows what they are doing they can override */
|
||||
if (tcon->share_flags & SMB2_SHAREFLAG_NO_CACHING) {
|
||||
@ -3426,8 +3409,7 @@ int cifs_mount(struct cifs_sb_info *cifs_sb, struct smb3_fs_context *ctx)
|
||||
goto error;
|
||||
}
|
||||
/* Save mount options */
|
||||
mntdata = kstrndup(cifs_sb->ctx->mount_options,
|
||||
strlen(cifs_sb->ctx->mount_options), GFP_KERNEL);
|
||||
mntdata = kstrdup(cifs_sb->ctx->mount_options, GFP_KERNEL);
|
||||
if (!mntdata) {
|
||||
rc = -ENOMEM;
|
||||
goto error;
|
||||
@ -3500,7 +3482,7 @@ int cifs_mount(struct cifs_sb_info *cifs_sb, struct smb3_fs_context *ctx)
|
||||
* links, the prefix path is included in both and may be changed during reconnect. See
|
||||
* cifs_tree_connect().
|
||||
*/
|
||||
cifs_sb->origin_fullpath = kstrndup(full_path, strlen(full_path), GFP_KERNEL);
|
||||
cifs_sb->origin_fullpath = kstrdup(full_path, GFP_KERNEL);
|
||||
if (!cifs_sb->origin_fullpath) {
|
||||
rc = -ENOMEM;
|
||||
goto error;
|
||||
@ -3877,9 +3859,7 @@ cifs_construct_tcon(struct cifs_sb_info *cifs_sb, kuid_t fsuid)
|
||||
ctx->sectype = master_tcon->ses->sectype;
|
||||
ctx->sign = master_tcon->ses->sign;
|
||||
ctx->seal = master_tcon->seal;
|
||||
#ifdef CONFIG_CIFS_SWN_UPCALL
|
||||
ctx->witness = master_tcon->use_witness;
|
||||
#endif
|
||||
|
||||
rc = cifs_set_vol_auth(ctx, master_tcon->ses);
|
||||
if (rc) {
|
||||
|
@ -81,23 +81,24 @@ static void refresh_cache_worker(struct work_struct *work);
|
||||
|
||||
static DECLARE_DELAYED_WORK(refresh_task, refresh_cache_worker);
|
||||
|
||||
static int get_normalized_path(const char *path, char **npath)
|
||||
static int get_normalized_path(const char *path, const char **npath)
|
||||
{
|
||||
if (!path || strlen(path) < 3 || (*path != '\\' && *path != '/'))
|
||||
return -EINVAL;
|
||||
|
||||
if (*path == '\\') {
|
||||
*npath = (char *)path;
|
||||
*npath = path;
|
||||
} else {
|
||||
*npath = kstrndup(path, strlen(path), GFP_KERNEL);
|
||||
if (!*npath)
|
||||
char *s = kstrdup(path, GFP_KERNEL);
|
||||
if (!s)
|
||||
return -ENOMEM;
|
||||
convert_delimiter(*npath, '\\');
|
||||
convert_delimiter(s, '\\');
|
||||
*npath = s;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static inline void free_normalized_path(const char *path, char *npath)
|
||||
static inline void free_normalized_path(const char *path, const char *npath)
|
||||
{
|
||||
if (path != npath)
|
||||
kfree(npath);
|
||||
@ -358,7 +359,7 @@ static struct cache_dfs_tgt *alloc_target(const char *name, int path_consumed)
|
||||
t = kmalloc(sizeof(*t), GFP_ATOMIC);
|
||||
if (!t)
|
||||
return ERR_PTR(-ENOMEM);
|
||||
t->name = kstrndup(name, strlen(name), GFP_ATOMIC);
|
||||
t->name = kstrdup(name, GFP_ATOMIC);
|
||||
if (!t->name) {
|
||||
kfree(t);
|
||||
return ERR_PTR(-ENOMEM);
|
||||
@ -419,7 +420,7 @@ static struct cache_entry *alloc_cache_entry(const char *path,
|
||||
if (!ce)
|
||||
return ERR_PTR(-ENOMEM);
|
||||
|
||||
ce->path = kstrndup(path, strlen(path), GFP_KERNEL);
|
||||
ce->path = kstrdup(path, GFP_KERNEL);
|
||||
if (!ce->path) {
|
||||
kmem_cache_free(cache_slab, ce);
|
||||
return ERR_PTR(-ENOMEM);
|
||||
@ -531,7 +532,7 @@ static struct cache_entry *lookup_cache_entry(const char *path, unsigned int *ha
|
||||
char *s, *e;
|
||||
char sep;
|
||||
|
||||
npath = kstrndup(path, strlen(path), GFP_KERNEL);
|
||||
npath = kstrdup(path, GFP_KERNEL);
|
||||
if (!npath)
|
||||
return ERR_PTR(-ENOMEM);
|
||||
|
||||
@ -641,7 +642,7 @@ static int __update_cache_entry(const char *path,
|
||||
|
||||
if (ce->tgthint) {
|
||||
s = ce->tgthint->name;
|
||||
th = kstrndup(s, strlen(s), GFP_ATOMIC);
|
||||
th = kstrdup(s, GFP_ATOMIC);
|
||||
if (!th)
|
||||
return -ENOMEM;
|
||||
}
|
||||
@ -786,11 +787,11 @@ static int setup_referral(const char *path, struct cache_entry *ce,
|
||||
|
||||
memset(ref, 0, sizeof(*ref));
|
||||
|
||||
ref->path_name = kstrndup(path, strlen(path), GFP_ATOMIC);
|
||||
ref->path_name = kstrdup(path, GFP_ATOMIC);
|
||||
if (!ref->path_name)
|
||||
return -ENOMEM;
|
||||
|
||||
ref->node_name = kstrndup(target, strlen(target), GFP_ATOMIC);
|
||||
ref->node_name = kstrdup(target, GFP_ATOMIC);
|
||||
if (!ref->node_name) {
|
||||
rc = -ENOMEM;
|
||||
goto err_free_path;
|
||||
@ -828,7 +829,7 @@ static int get_targets(struct cache_entry *ce, struct dfs_cache_tgt_list *tl)
|
||||
goto err_free_it;
|
||||
}
|
||||
|
||||
it->it_name = kstrndup(t->name, strlen(t->name), GFP_ATOMIC);
|
||||
it->it_name = kstrdup(t->name, GFP_ATOMIC);
|
||||
if (!it->it_name) {
|
||||
kfree(it);
|
||||
rc = -ENOMEM;
|
||||
@ -882,7 +883,7 @@ int dfs_cache_find(const unsigned int xid, struct cifs_ses *ses,
|
||||
struct dfs_cache_tgt_list *tgt_list)
|
||||
{
|
||||
int rc;
|
||||
char *npath;
|
||||
const char *npath;
|
||||
struct cache_entry *ce;
|
||||
|
||||
rc = get_normalized_path(path, &npath);
|
||||
@ -936,7 +937,7 @@ int dfs_cache_noreq_find(const char *path, struct dfs_info3_param *ref,
|
||||
struct dfs_cache_tgt_list *tgt_list)
|
||||
{
|
||||
int rc;
|
||||
char *npath;
|
||||
const char *npath;
|
||||
struct cache_entry *ce;
|
||||
|
||||
rc = get_normalized_path(path, &npath);
|
||||
@ -991,7 +992,7 @@ int dfs_cache_update_tgthint(const unsigned int xid, struct cifs_ses *ses,
|
||||
const struct dfs_cache_tgt_iterator *it)
|
||||
{
|
||||
int rc;
|
||||
char *npath;
|
||||
const char *npath;
|
||||
struct cache_entry *ce;
|
||||
struct cache_dfs_tgt *t;
|
||||
|
||||
@ -1053,7 +1054,7 @@ int dfs_cache_noreq_update_tgthint(const char *path,
|
||||
const struct dfs_cache_tgt_iterator *it)
|
||||
{
|
||||
int rc;
|
||||
char *npath;
|
||||
const char *npath;
|
||||
struct cache_entry *ce;
|
||||
struct cache_dfs_tgt *t;
|
||||
|
||||
@ -1111,7 +1112,7 @@ int dfs_cache_get_tgt_referral(const char *path,
|
||||
struct dfs_info3_param *ref)
|
||||
{
|
||||
int rc;
|
||||
char *npath;
|
||||
const char *npath;
|
||||
struct cache_entry *ce;
|
||||
|
||||
if (!it || !ref)
|
||||
@ -1166,7 +1167,7 @@ int dfs_cache_add_vol(char *mntdata, struct smb3_fs_context *ctx, const char *fu
|
||||
if (!vi)
|
||||
return -ENOMEM;
|
||||
|
||||
vi->fullpath = kstrndup(fullpath, strlen(fullpath), GFP_KERNEL);
|
||||
vi->fullpath = kstrdup(fullpath, GFP_KERNEL);
|
||||
if (!vi->fullpath) {
|
||||
rc = -ENOMEM;
|
||||
goto err_free_vi;
|
||||
@ -1484,7 +1485,7 @@ static int refresh_tcon(struct vol_info *vi, struct cifs_tcon *tcon)
|
||||
{
|
||||
int rc = 0;
|
||||
unsigned int xid;
|
||||
char *path, *npath;
|
||||
const char *path, *npath;
|
||||
struct cache_entry *ce;
|
||||
struct cifs_ses *root_ses = NULL, *ses;
|
||||
struct dfs_info3_param *refs = NULL;
|
||||
|
150
fs/cifs/dir.c
150
fs/cifs/dir.c
@ -78,31 +78,31 @@ cifs_build_path_to_root(struct smb3_fs_context *ctx, struct cifs_sb_info *cifs_s
|
||||
}
|
||||
|
||||
/* Note: caller must free return buffer */
|
||||
char *
|
||||
build_path_from_dentry(struct dentry *direntry)
|
||||
const char *
|
||||
build_path_from_dentry(struct dentry *direntry, void *page)
|
||||
{
|
||||
struct cifs_sb_info *cifs_sb = CIFS_SB(direntry->d_sb);
|
||||
struct cifs_tcon *tcon = cifs_sb_master_tcon(cifs_sb);
|
||||
bool prefix = tcon->Flags & SMB_SHARE_IS_IN_DFS;
|
||||
|
||||
return build_path_from_dentry_optional_prefix(direntry,
|
||||
return build_path_from_dentry_optional_prefix(direntry, page,
|
||||
prefix);
|
||||
}
|
||||
|
||||
char *
|
||||
build_path_from_dentry_optional_prefix(struct dentry *direntry, bool prefix)
|
||||
build_path_from_dentry_optional_prefix(struct dentry *direntry, void *page,
|
||||
bool prefix)
|
||||
{
|
||||
struct dentry *temp;
|
||||
int namelen;
|
||||
int dfsplen;
|
||||
int pplen = 0;
|
||||
char *full_path;
|
||||
char dirsep;
|
||||
struct cifs_sb_info *cifs_sb = CIFS_SB(direntry->d_sb);
|
||||
struct cifs_tcon *tcon = cifs_sb_master_tcon(cifs_sb);
|
||||
unsigned seq;
|
||||
char dirsep = CIFS_DIR_SEP(cifs_sb);
|
||||
char *s;
|
||||
|
||||
if (unlikely(!page))
|
||||
return ERR_PTR(-ENOMEM);
|
||||
|
||||
dirsep = CIFS_DIR_SEP(cifs_sb);
|
||||
if (prefix)
|
||||
dfsplen = strnlen(tcon->treeName, MAX_TREE_SIZE + 1);
|
||||
else
|
||||
@ -111,86 +111,39 @@ build_path_from_dentry_optional_prefix(struct dentry *direntry, bool prefix)
|
||||
if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_USE_PREFIX_PATH)
|
||||
pplen = cifs_sb->prepath ? strlen(cifs_sb->prepath) + 1 : 0;
|
||||
|
||||
cifs_bp_rename_retry:
|
||||
namelen = dfsplen + pplen;
|
||||
seq = read_seqbegin(&rename_lock);
|
||||
rcu_read_lock();
|
||||
for (temp = direntry; !IS_ROOT(temp);) {
|
||||
namelen += (1 + temp->d_name.len);
|
||||
temp = temp->d_parent;
|
||||
if (temp == NULL) {
|
||||
cifs_dbg(VFS, "corrupt dentry\n");
|
||||
rcu_read_unlock();
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
rcu_read_unlock();
|
||||
|
||||
full_path = kmalloc(namelen+1, GFP_ATOMIC);
|
||||
if (full_path == NULL)
|
||||
return full_path;
|
||||
full_path[namelen] = 0; /* trailing null */
|
||||
rcu_read_lock();
|
||||
for (temp = direntry; !IS_ROOT(temp);) {
|
||||
spin_lock(&temp->d_lock);
|
||||
namelen -= 1 + temp->d_name.len;
|
||||
if (namelen < 0) {
|
||||
spin_unlock(&temp->d_lock);
|
||||
break;
|
||||
} else {
|
||||
full_path[namelen] = dirsep;
|
||||
strncpy(full_path + namelen + 1, temp->d_name.name,
|
||||
temp->d_name.len);
|
||||
cifs_dbg(FYI, "name: %s\n", full_path + namelen);
|
||||
}
|
||||
spin_unlock(&temp->d_lock);
|
||||
temp = temp->d_parent;
|
||||
if (temp == NULL) {
|
||||
cifs_dbg(VFS, "corrupt dentry\n");
|
||||
rcu_read_unlock();
|
||||
kfree(full_path);
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
rcu_read_unlock();
|
||||
if (namelen != dfsplen + pplen || read_seqretry(&rename_lock, seq)) {
|
||||
cifs_dbg(FYI, "did not end path lookup where expected. namelen=%ddfsplen=%d\n",
|
||||
namelen, dfsplen);
|
||||
/* presumably this is only possible if racing with a rename
|
||||
of one of the parent directories (we can not lock the dentries
|
||||
above us to prevent this, but retrying should be harmless) */
|
||||
kfree(full_path);
|
||||
goto cifs_bp_rename_retry;
|
||||
}
|
||||
/* DIR_SEP already set for byte 0 / vs \ but not for
|
||||
subsequent slashes in prepath which currently must
|
||||
be entered the right way - not sure if there is an alternative
|
||||
since the '\' is a valid posix character so we can not switch
|
||||
those safely to '/' if any are found in the middle of the prepath */
|
||||
/* BB test paths to Windows with '/' in the midst of prepath */
|
||||
|
||||
s = dentry_path_raw(direntry, page, PAGE_SIZE);
|
||||
if (IS_ERR(s))
|
||||
return s;
|
||||
if (!s[1]) // for root we want "", not "/"
|
||||
s++;
|
||||
if (s < (char *)page + pplen + dfsplen)
|
||||
return ERR_PTR(-ENAMETOOLONG);
|
||||
if (pplen) {
|
||||
int i;
|
||||
|
||||
cifs_dbg(FYI, "using cifs_sb prepath <%s>\n", cifs_sb->prepath);
|
||||
memcpy(full_path+dfsplen+1, cifs_sb->prepath, pplen-1);
|
||||
full_path[dfsplen] = dirsep;
|
||||
for (i = 0; i < pplen-1; i++)
|
||||
if (full_path[dfsplen+1+i] == '/')
|
||||
full_path[dfsplen+1+i] = CIFS_DIR_SEP(cifs_sb);
|
||||
s -= pplen;
|
||||
memcpy(s + 1, cifs_sb->prepath, pplen - 1);
|
||||
*s = '/';
|
||||
}
|
||||
if (dirsep != '/') {
|
||||
/* BB test paths to Windows with '/' in the midst of prepath */
|
||||
char *p;
|
||||
|
||||
for (p = s; *p; p++)
|
||||
if (*p == '/')
|
||||
*p = dirsep;
|
||||
}
|
||||
if (dfsplen) {
|
||||
strncpy(full_path, tcon->treeName, dfsplen);
|
||||
s -= dfsplen;
|
||||
memcpy(s, tcon->treeName, dfsplen);
|
||||
if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_POSIX_PATHS) {
|
||||
int i;
|
||||
for (i = 0; i < dfsplen; i++) {
|
||||
if (full_path[i] == '\\')
|
||||
full_path[i] = '/';
|
||||
if (s[i] == '\\')
|
||||
s[i] = '/';
|
||||
}
|
||||
}
|
||||
}
|
||||
return full_path;
|
||||
return s;
|
||||
}
|
||||
|
||||
/*
|
||||
@ -233,7 +186,8 @@ cifs_do_create(struct inode *inode, struct dentry *direntry, unsigned int xid,
|
||||
int desired_access;
|
||||
struct cifs_sb_info *cifs_sb = CIFS_SB(inode->i_sb);
|
||||
struct cifs_tcon *tcon = tlink_tcon(tlink);
|
||||
char *full_path = NULL;
|
||||
const char *full_path;
|
||||
void *page = alloc_dentry_path();
|
||||
FILE_ALL_INFO *buf = NULL;
|
||||
struct inode *newinode = NULL;
|
||||
int disposition;
|
||||
@ -244,9 +198,11 @@ cifs_do_create(struct inode *inode, struct dentry *direntry, unsigned int xid,
|
||||
if (tcon->ses->server->oplocks)
|
||||
*oplock = REQ_OPLOCK;
|
||||
|
||||
full_path = build_path_from_dentry(direntry);
|
||||
if (!full_path)
|
||||
return -ENOMEM;
|
||||
full_path = build_path_from_dentry(direntry, page);
|
||||
if (IS_ERR(full_path)) {
|
||||
free_dentry_path(page);
|
||||
return PTR_ERR(full_path);
|
||||
}
|
||||
|
||||
if (tcon->unix_ext && cap_unix(tcon->ses) && !tcon->broken_posix_open &&
|
||||
(CIFS_UNIX_POSIX_PATH_OPS_CAP &
|
||||
@ -448,7 +404,7 @@ cifs_create_set_dentry:
|
||||
|
||||
out:
|
||||
kfree(buf);
|
||||
kfree(full_path);
|
||||
free_dentry_path(page);
|
||||
return rc;
|
||||
|
||||
out_err:
|
||||
@ -619,7 +575,8 @@ int cifs_mknod(struct user_namespace *mnt_userns, struct inode *inode,
|
||||
struct cifs_sb_info *cifs_sb;
|
||||
struct tcon_link *tlink;
|
||||
struct cifs_tcon *tcon;
|
||||
char *full_path = NULL;
|
||||
const char *full_path;
|
||||
void *page;
|
||||
|
||||
if (!old_valid_dev(device_number))
|
||||
return -EINVAL;
|
||||
@ -629,13 +586,13 @@ int cifs_mknod(struct user_namespace *mnt_userns, struct inode *inode,
|
||||
if (IS_ERR(tlink))
|
||||
return PTR_ERR(tlink);
|
||||
|
||||
page = alloc_dentry_path();
|
||||
tcon = tlink_tcon(tlink);
|
||||
|
||||
xid = get_xid();
|
||||
|
||||
full_path = build_path_from_dentry(direntry);
|
||||
if (full_path == NULL) {
|
||||
rc = -ENOMEM;
|
||||
full_path = build_path_from_dentry(direntry, page);
|
||||
if (IS_ERR(full_path)) {
|
||||
rc = PTR_ERR(full_path);
|
||||
goto mknod_out;
|
||||
}
|
||||
|
||||
@ -644,7 +601,7 @@ int cifs_mknod(struct user_namespace *mnt_userns, struct inode *inode,
|
||||
device_number);
|
||||
|
||||
mknod_out:
|
||||
kfree(full_path);
|
||||
free_dentry_path(page);
|
||||
free_xid(xid);
|
||||
cifs_put_tlink(tlink);
|
||||
return rc;
|
||||
@ -660,7 +617,8 @@ cifs_lookup(struct inode *parent_dir_inode, struct dentry *direntry,
|
||||
struct tcon_link *tlink;
|
||||
struct cifs_tcon *pTcon;
|
||||
struct inode *newInode = NULL;
|
||||
char *full_path = NULL;
|
||||
const char *full_path;
|
||||
void *page;
|
||||
|
||||
xid = get_xid();
|
||||
|
||||
@ -687,11 +645,13 @@ cifs_lookup(struct inode *parent_dir_inode, struct dentry *direntry,
|
||||
/* can not grab the rename sem here since it would
|
||||
deadlock in the cases (beginning of sys_rename itself)
|
||||
in which we already have the sb rename sem */
|
||||
full_path = build_path_from_dentry(direntry);
|
||||
if (full_path == NULL) {
|
||||
page = alloc_dentry_path();
|
||||
full_path = build_path_from_dentry(direntry, page);
|
||||
if (IS_ERR(full_path)) {
|
||||
cifs_put_tlink(tlink);
|
||||
free_xid(xid);
|
||||
return ERR_PTR(-ENOMEM);
|
||||
free_dentry_path(page);
|
||||
return ERR_CAST(full_path);
|
||||
}
|
||||
|
||||
if (d_really_is_positive(direntry)) {
|
||||
@ -727,7 +687,7 @@ cifs_lookup(struct inode *parent_dir_inode, struct dentry *direntry,
|
||||
}
|
||||
newInode = ERR_PTR(rc);
|
||||
}
|
||||
kfree(full_path);
|
||||
free_dentry_path(page);
|
||||
cifs_put_tlink(tlink);
|
||||
free_xid(xid);
|
||||
return d_splice_alias(newInode, direntry);
|
||||
|
@ -112,7 +112,7 @@ static inline int cifs_get_disposition(unsigned int flags)
|
||||
return FILE_OPEN;
|
||||
}
|
||||
|
||||
int cifs_posix_open(char *full_path, struct inode **pinode,
|
||||
int cifs_posix_open(const char *full_path, struct inode **pinode,
|
||||
struct super_block *sb, int mode, unsigned int f_flags,
|
||||
__u32 *poplock, __u16 *pnetfid, unsigned int xid)
|
||||
{
|
||||
@ -175,7 +175,7 @@ posix_open_ret:
|
||||
}
|
||||
|
||||
static int
|
||||
cifs_nt_open(char *full_path, struct inode *inode, struct cifs_sb_info *cifs_sb,
|
||||
cifs_nt_open(const char *full_path, struct inode *inode, struct cifs_sb_info *cifs_sb,
|
||||
struct cifs_tcon *tcon, unsigned int f_flags, __u32 *oplock,
|
||||
struct cifs_fid *fid, unsigned int xid)
|
||||
{
|
||||
@ -530,7 +530,8 @@ int cifs_open(struct inode *inode, struct file *file)
|
||||
struct cifs_tcon *tcon;
|
||||
struct tcon_link *tlink;
|
||||
struct cifsFileInfo *cfile = NULL;
|
||||
char *full_path = NULL;
|
||||
void *page;
|
||||
const char *full_path;
|
||||
bool posix_open_ok = false;
|
||||
struct cifs_fid fid;
|
||||
struct cifs_pending_open open;
|
||||
@ -546,9 +547,10 @@ int cifs_open(struct inode *inode, struct file *file)
|
||||
tcon = tlink_tcon(tlink);
|
||||
server = tcon->ses->server;
|
||||
|
||||
full_path = build_path_from_dentry(file_dentry(file));
|
||||
if (full_path == NULL) {
|
||||
rc = -ENOMEM;
|
||||
page = alloc_dentry_path();
|
||||
full_path = build_path_from_dentry(file_dentry(file), page);
|
||||
if (IS_ERR(full_path)) {
|
||||
rc = PTR_ERR(full_path);
|
||||
goto out;
|
||||
}
|
||||
|
||||
@ -640,7 +642,7 @@ int cifs_open(struct inode *inode, struct file *file)
|
||||
}
|
||||
|
||||
out:
|
||||
kfree(full_path);
|
||||
free_dentry_path(page);
|
||||
free_xid(xid);
|
||||
cifs_put_tlink(tlink);
|
||||
return rc;
|
||||
@ -689,7 +691,8 @@ cifs_reopen_file(struct cifsFileInfo *cfile, bool can_flush)
|
||||
struct TCP_Server_Info *server;
|
||||
struct cifsInodeInfo *cinode;
|
||||
struct inode *inode;
|
||||
char *full_path = NULL;
|
||||
void *page;
|
||||
const char *full_path;
|
||||
int desired_access;
|
||||
int disposition = FILE_OPEN;
|
||||
int create_options = CREATE_NOT_DIR;
|
||||
@ -699,9 +702,8 @@ cifs_reopen_file(struct cifsFileInfo *cfile, bool can_flush)
|
||||
mutex_lock(&cfile->fh_mutex);
|
||||
if (!cfile->invalidHandle) {
|
||||
mutex_unlock(&cfile->fh_mutex);
|
||||
rc = 0;
|
||||
free_xid(xid);
|
||||
return rc;
|
||||
return 0;
|
||||
}
|
||||
|
||||
inode = d_inode(cfile->dentry);
|
||||
@ -715,12 +717,13 @@ cifs_reopen_file(struct cifsFileInfo *cfile, bool can_flush)
|
||||
* called and if the server was down that means we end up here, and we
|
||||
* can never tell if the caller already has the rename_sem.
|
||||
*/
|
||||
full_path = build_path_from_dentry(cfile->dentry);
|
||||
if (full_path == NULL) {
|
||||
rc = -ENOMEM;
|
||||
page = alloc_dentry_path();
|
||||
full_path = build_path_from_dentry(cfile->dentry, page);
|
||||
if (IS_ERR(full_path)) {
|
||||
mutex_unlock(&cfile->fh_mutex);
|
||||
free_dentry_path(page);
|
||||
free_xid(xid);
|
||||
return rc;
|
||||
return PTR_ERR(full_path);
|
||||
}
|
||||
|
||||
cifs_dbg(FYI, "inode = 0x%p file flags 0x%x for %s\n",
|
||||
@ -838,7 +841,7 @@ reopen_success:
|
||||
cifs_relock_file(cfile);
|
||||
|
||||
reopen_error_exit:
|
||||
kfree(full_path);
|
||||
free_dentry_path(page);
|
||||
free_xid(xid);
|
||||
return rc;
|
||||
}
|
||||
@ -2069,34 +2072,31 @@ cifs_get_writable_path(struct cifs_tcon *tcon, const char *name,
|
||||
int flags,
|
||||
struct cifsFileInfo **ret_file)
|
||||
{
|
||||
struct list_head *tmp;
|
||||
struct cifsFileInfo *cfile;
|
||||
struct cifsInodeInfo *cinode;
|
||||
char *full_path;
|
||||
void *page = alloc_dentry_path();
|
||||
|
||||
*ret_file = NULL;
|
||||
|
||||
spin_lock(&tcon->open_file_lock);
|
||||
list_for_each(tmp, &tcon->openFileList) {
|
||||
cfile = list_entry(tmp, struct cifsFileInfo,
|
||||
tlist);
|
||||
full_path = build_path_from_dentry(cfile->dentry);
|
||||
if (full_path == NULL) {
|
||||
list_for_each_entry(cfile, &tcon->openFileList, tlist) {
|
||||
struct cifsInodeInfo *cinode;
|
||||
const char *full_path = build_path_from_dentry(cfile->dentry, page);
|
||||
if (IS_ERR(full_path)) {
|
||||
spin_unlock(&tcon->open_file_lock);
|
||||
return -ENOMEM;
|
||||
free_dentry_path(page);
|
||||
return PTR_ERR(full_path);
|
||||
}
|
||||
if (strcmp(full_path, name)) {
|
||||
kfree(full_path);
|
||||
if (strcmp(full_path, name))
|
||||
continue;
|
||||
}
|
||||
|
||||
kfree(full_path);
|
||||
cinode = CIFS_I(d_inode(cfile->dentry));
|
||||
spin_unlock(&tcon->open_file_lock);
|
||||
free_dentry_path(page);
|
||||
return cifs_get_writable_file(cinode, flags, ret_file);
|
||||
}
|
||||
|
||||
spin_unlock(&tcon->open_file_lock);
|
||||
free_dentry_path(page);
|
||||
return -ENOENT;
|
||||
}
|
||||
|
||||
@ -2104,35 +2104,32 @@ int
|
||||
cifs_get_readable_path(struct cifs_tcon *tcon, const char *name,
|
||||
struct cifsFileInfo **ret_file)
|
||||
{
|
||||
struct list_head *tmp;
|
||||
struct cifsFileInfo *cfile;
|
||||
struct cifsInodeInfo *cinode;
|
||||
char *full_path;
|
||||
void *page = alloc_dentry_path();
|
||||
|
||||
*ret_file = NULL;
|
||||
|
||||
spin_lock(&tcon->open_file_lock);
|
||||
list_for_each(tmp, &tcon->openFileList) {
|
||||
cfile = list_entry(tmp, struct cifsFileInfo,
|
||||
tlist);
|
||||
full_path = build_path_from_dentry(cfile->dentry);
|
||||
if (full_path == NULL) {
|
||||
list_for_each_entry(cfile, &tcon->openFileList, tlist) {
|
||||
struct cifsInodeInfo *cinode;
|
||||
const char *full_path = build_path_from_dentry(cfile->dentry, page);
|
||||
if (IS_ERR(full_path)) {
|
||||
spin_unlock(&tcon->open_file_lock);
|
||||
return -ENOMEM;
|
||||
free_dentry_path(page);
|
||||
return PTR_ERR(full_path);
|
||||
}
|
||||
if (strcmp(full_path, name)) {
|
||||
kfree(full_path);
|
||||
if (strcmp(full_path, name))
|
||||
continue;
|
||||
}
|
||||
|
||||
kfree(full_path);
|
||||
cinode = CIFS_I(d_inode(cfile->dentry));
|
||||
spin_unlock(&tcon->open_file_lock);
|
||||
free_dentry_path(page);
|
||||
*ret_file = find_readable_file(cinode, 0);
|
||||
return *ret_file ? 0 : -ENOENT;
|
||||
}
|
||||
|
||||
spin_unlock(&tcon->open_file_lock);
|
||||
free_dentry_path(page);
|
||||
return -ENOENT;
|
||||
}
|
||||
|
||||
|
@ -137,6 +137,7 @@ const struct fs_parameter_spec smb3_fs_parameters[] = {
|
||||
fsparam_u32("min_enc_offload", Opt_min_enc_offload),
|
||||
fsparam_u32("esize", Opt_min_enc_offload),
|
||||
fsparam_u32("bsize", Opt_blocksize),
|
||||
fsparam_u32("rasize", Opt_rasize),
|
||||
fsparam_u32("rsize", Opt_rsize),
|
||||
fsparam_u32("wsize", Opt_wsize),
|
||||
fsparam_u32("actimeo", Opt_actimeo),
|
||||
@ -188,8 +189,8 @@ const struct fs_parameter_spec smb3_fs_parameters[] = {
|
||||
{}
|
||||
};
|
||||
|
||||
int
|
||||
cifs_parse_security_flavors(char *value, struct smb3_fs_context *ctx)
|
||||
static int
|
||||
cifs_parse_security_flavors(struct fs_context *fc, char *value, struct smb3_fs_context *ctx)
|
||||
{
|
||||
|
||||
substring_t args[MAX_OPT_ARGS];
|
||||
@ -203,7 +204,7 @@ cifs_parse_security_flavors(char *value, struct smb3_fs_context *ctx)
|
||||
|
||||
switch (match_token(value, cifs_secflavor_tokens, args)) {
|
||||
case Opt_sec_krb5p:
|
||||
cifs_dbg(VFS, "sec=krb5p is not supported!\n");
|
||||
cifs_errorf(fc, "sec=krb5p is not supported!\n");
|
||||
return 1;
|
||||
case Opt_sec_krb5i:
|
||||
ctx->sign = true;
|
||||
@ -238,7 +239,7 @@ cifs_parse_security_flavors(char *value, struct smb3_fs_context *ctx)
|
||||
ctx->nullauth = 1;
|
||||
break;
|
||||
default:
|
||||
cifs_dbg(VFS, "bad security option: %s\n", value);
|
||||
cifs_errorf(fc, "bad security option: %s\n", value);
|
||||
return 1;
|
||||
}
|
||||
|
||||
@ -254,8 +255,8 @@ static const match_table_t cifs_cacheflavor_tokens = {
|
||||
{ Opt_cache_err, NULL }
|
||||
};
|
||||
|
||||
int
|
||||
cifs_parse_cache_flavor(char *value, struct smb3_fs_context *ctx)
|
||||
static int
|
||||
cifs_parse_cache_flavor(struct fs_context *fc, char *value, struct smb3_fs_context *ctx)
|
||||
{
|
||||
substring_t args[MAX_OPT_ARGS];
|
||||
|
||||
@ -291,7 +292,7 @@ cifs_parse_cache_flavor(char *value, struct smb3_fs_context *ctx)
|
||||
ctx->cache_rw = true;
|
||||
break;
|
||||
default:
|
||||
cifs_dbg(VFS, "bad cache= option: %s\n", value);
|
||||
cifs_errorf(fc, "bad cache= option: %s\n", value);
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
@ -339,7 +340,7 @@ smb3_fs_context_dup(struct smb3_fs_context *new_ctx, struct smb3_fs_context *ctx
|
||||
}
|
||||
|
||||
static int
|
||||
cifs_parse_smb_version(char *value, struct smb3_fs_context *ctx, bool is_smb3)
|
||||
cifs_parse_smb_version(struct fs_context *fc, char *value, struct smb3_fs_context *ctx, bool is_smb3)
|
||||
{
|
||||
substring_t args[MAX_OPT_ARGS];
|
||||
|
||||
@ -347,24 +348,24 @@ cifs_parse_smb_version(char *value, struct smb3_fs_context *ctx, bool is_smb3)
|
||||
#ifdef CONFIG_CIFS_ALLOW_INSECURE_LEGACY
|
||||
case Smb_1:
|
||||
if (disable_legacy_dialects) {
|
||||
cifs_dbg(VFS, "mount with legacy dialect disabled\n");
|
||||
cifs_errorf(fc, "mount with legacy dialect disabled\n");
|
||||
return 1;
|
||||
}
|
||||
if (is_smb3) {
|
||||
cifs_dbg(VFS, "vers=1.0 (cifs) not permitted when mounting with smb3\n");
|
||||
cifs_errorf(fc, "vers=1.0 (cifs) not permitted when mounting with smb3\n");
|
||||
return 1;
|
||||
}
|
||||
cifs_dbg(VFS, "Use of the less secure dialect vers=1.0 is not recommended unless required for access to very old servers\n");
|
||||
cifs_errorf(fc, "Use of the less secure dialect vers=1.0 is not recommended unless required for access to very old servers\n");
|
||||
ctx->ops = &smb1_operations;
|
||||
ctx->vals = &smb1_values;
|
||||
break;
|
||||
case Smb_20:
|
||||
if (disable_legacy_dialects) {
|
||||
cifs_dbg(VFS, "mount with legacy dialect disabled\n");
|
||||
cifs_errorf(fc, "mount with legacy dialect disabled\n");
|
||||
return 1;
|
||||
}
|
||||
if (is_smb3) {
|
||||
cifs_dbg(VFS, "vers=2.0 not permitted when mounting with smb3\n");
|
||||
cifs_errorf(fc, "vers=2.0 not permitted when mounting with smb3\n");
|
||||
return 1;
|
||||
}
|
||||
ctx->ops = &smb20_operations;
|
||||
@ -372,10 +373,10 @@ cifs_parse_smb_version(char *value, struct smb3_fs_context *ctx, bool is_smb3)
|
||||
break;
|
||||
#else
|
||||
case Smb_1:
|
||||
cifs_dbg(VFS, "vers=1.0 (cifs) mount not permitted when legacy dialects disabled\n");
|
||||
cifs_errorf(fc, "vers=1.0 (cifs) mount not permitted when legacy dialects disabled\n");
|
||||
return 1;
|
||||
case Smb_20:
|
||||
cifs_dbg(VFS, "vers=2.0 mount not permitted when legacy dialects disabled\n");
|
||||
cifs_errorf(fc, "vers=2.0 mount not permitted when legacy dialects disabled\n");
|
||||
return 1;
|
||||
#endif /* CIFS_ALLOW_INSECURE_LEGACY */
|
||||
case Smb_21:
|
||||
@ -403,7 +404,7 @@ cifs_parse_smb_version(char *value, struct smb3_fs_context *ctx, bool is_smb3)
|
||||
ctx->vals = &smbdefault_values;
|
||||
break;
|
||||
default:
|
||||
cifs_dbg(VFS, "Unknown vers= option specified: %s\n", value);
|
||||
cifs_errorf(fc, "Unknown vers= option specified: %s\n", value);
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
@ -430,7 +431,7 @@ int smb3_parse_opt(const char *options, const char *key, char **val)
|
||||
if (nval == p)
|
||||
continue;
|
||||
*nval++ = 0;
|
||||
*val = kstrndup(nval, strlen(nval), GFP_KERNEL);
|
||||
*val = kstrdup(nval, GFP_KERNEL);
|
||||
rc = !*val ? -ENOMEM : 0;
|
||||
goto out;
|
||||
}
|
||||
@ -588,14 +589,14 @@ static int smb3_fs_context_validate(struct fs_context *fc)
|
||||
struct smb3_fs_context *ctx = smb3_fc2context(fc);
|
||||
|
||||
if (ctx->rdma && ctx->vals->protocol_id < SMB30_PROT_ID) {
|
||||
cifs_dbg(VFS, "SMB Direct requires Version >=3.0\n");
|
||||
cifs_errorf(fc, "SMB Direct requires Version >=3.0\n");
|
||||
return -EOPNOTSUPP;
|
||||
}
|
||||
|
||||
#ifndef CONFIG_KEYS
|
||||
/* Muliuser mounts require CONFIG_KEYS support */
|
||||
if (ctx->multiuser) {
|
||||
cifs_dbg(VFS, "Multiuser mounts require kernels with CONFIG_KEYS enabled\n");
|
||||
cifs_errorf(fc, "Multiuser mounts require kernels with CONFIG_KEYS enabled\n");
|
||||
return -1;
|
||||
}
|
||||
#endif
|
||||
@ -605,13 +606,13 @@ static int smb3_fs_context_validate(struct fs_context *fc)
|
||||
|
||||
|
||||
if (!ctx->UNC) {
|
||||
cifs_dbg(VFS, "CIFS mount error: No usable UNC path provided in device string!\n");
|
||||
cifs_errorf(fc, "CIFS mount error: No usable UNC path provided in device string!\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* make sure UNC has a share name */
|
||||
if (strlen(ctx->UNC) < 3 || !strchr(ctx->UNC + 3, '\\')) {
|
||||
cifs_dbg(VFS, "Malformed UNC. Unable to find share name.\n");
|
||||
cifs_errorf(fc, "Malformed UNC. Unable to find share name.\n");
|
||||
return -ENOENT;
|
||||
}
|
||||
|
||||
@ -684,49 +685,50 @@ static void smb3_fs_context_free(struct fs_context *fc)
|
||||
* Compare the old and new proposed context during reconfigure
|
||||
* and check if the changes are compatible.
|
||||
*/
|
||||
static int smb3_verify_reconfigure_ctx(struct smb3_fs_context *new_ctx,
|
||||
static int smb3_verify_reconfigure_ctx(struct fs_context *fc,
|
||||
struct smb3_fs_context *new_ctx,
|
||||
struct smb3_fs_context *old_ctx)
|
||||
{
|
||||
if (new_ctx->posix_paths != old_ctx->posix_paths) {
|
||||
cifs_dbg(VFS, "can not change posixpaths during remount\n");
|
||||
cifs_errorf(fc, "can not change posixpaths during remount\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
if (new_ctx->sectype != old_ctx->sectype) {
|
||||
cifs_dbg(VFS, "can not change sec during remount\n");
|
||||
cifs_errorf(fc, "can not change sec during remount\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
if (new_ctx->multiuser != old_ctx->multiuser) {
|
||||
cifs_dbg(VFS, "can not change multiuser during remount\n");
|
||||
cifs_errorf(fc, "can not change multiuser during remount\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
if (new_ctx->UNC &&
|
||||
(!old_ctx->UNC || strcmp(new_ctx->UNC, old_ctx->UNC))) {
|
||||
cifs_dbg(VFS, "can not change UNC during remount\n");
|
||||
cifs_errorf(fc, "can not change UNC during remount\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
if (new_ctx->username &&
|
||||
(!old_ctx->username || strcmp(new_ctx->username, old_ctx->username))) {
|
||||
cifs_dbg(VFS, "can not change username during remount\n");
|
||||
cifs_errorf(fc, "can not change username during remount\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
if (new_ctx->password &&
|
||||
(!old_ctx->password || strcmp(new_ctx->password, old_ctx->password))) {
|
||||
cifs_dbg(VFS, "can not change password during remount\n");
|
||||
cifs_errorf(fc, "can not change password during remount\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
if (new_ctx->domainname &&
|
||||
(!old_ctx->domainname || strcmp(new_ctx->domainname, old_ctx->domainname))) {
|
||||
cifs_dbg(VFS, "can not change domainname during remount\n");
|
||||
cifs_errorf(fc, "can not change domainname during remount\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
if (new_ctx->nodename &&
|
||||
(!old_ctx->nodename || strcmp(new_ctx->nodename, old_ctx->nodename))) {
|
||||
cifs_dbg(VFS, "can not change nodename during remount\n");
|
||||
cifs_errorf(fc, "can not change nodename during remount\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
if (new_ctx->iocharset &&
|
||||
(!old_ctx->iocharset || strcmp(new_ctx->iocharset, old_ctx->iocharset))) {
|
||||
cifs_dbg(VFS, "can not change iocharset during remount\n");
|
||||
cifs_errorf(fc, "can not change iocharset during remount\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
@ -747,7 +749,7 @@ static int smb3_reconfigure(struct fs_context *fc)
|
||||
struct cifs_sb_info *cifs_sb = CIFS_SB(root->d_sb);
|
||||
int rc;
|
||||
|
||||
rc = smb3_verify_reconfigure_ctx(ctx, cifs_sb->ctx);
|
||||
rc = smb3_verify_reconfigure_ctx(fc, ctx, cifs_sb->ctx);
|
||||
if (rc)
|
||||
return rc;
|
||||
|
||||
@ -933,13 +935,33 @@ static int smb3_fs_context_parse_param(struct fs_context *fc,
|
||||
*/
|
||||
if ((result.uint_32 < CIFS_MAX_MSGSIZE) ||
|
||||
(result.uint_32 > (4 * SMB3_DEFAULT_IOSIZE))) {
|
||||
cifs_dbg(VFS, "%s: Invalid blocksize\n",
|
||||
cifs_errorf(fc, "%s: Invalid blocksize\n",
|
||||
__func__);
|
||||
goto cifs_parse_mount_err;
|
||||
}
|
||||
ctx->bsize = result.uint_32;
|
||||
ctx->got_bsize = true;
|
||||
break;
|
||||
case Opt_rasize:
|
||||
/*
|
||||
* readahead size realistically should never need to be
|
||||
* less than 1M (CIFS_DEFAULT_IOSIZE) or greater than 32M
|
||||
* (perhaps an exception should be considered in the
|
||||
* for the case of a large number of channels
|
||||
* when multichannel is negotiated) since that would lead
|
||||
* to plenty of parallel I/O in flight to the server.
|
||||
* Note that smaller read ahead sizes would
|
||||
* hurt performance of common tools like cp and scp
|
||||
* which often trigger sequential i/o with read ahead
|
||||
*/
|
||||
if ((result.uint_32 > (8 * SMB3_DEFAULT_IOSIZE)) ||
|
||||
(result.uint_32 < CIFS_DEFAULT_IOSIZE)) {
|
||||
cifs_errorf(fc, "%s: Invalid rasize %d vs. %d\n",
|
||||
__func__, result.uint_32, SMB3_DEFAULT_IOSIZE);
|
||||
goto cifs_parse_mount_err;
|
||||
}
|
||||
ctx->rasize = result.uint_32;
|
||||
break;
|
||||
case Opt_rsize:
|
||||
ctx->rsize = result.uint_32;
|
||||
ctx->got_rsize = true;
|
||||
@ -951,25 +973,25 @@ static int smb3_fs_context_parse_param(struct fs_context *fc,
|
||||
case Opt_acregmax:
|
||||
ctx->acregmax = HZ * result.uint_32;
|
||||
if (ctx->acregmax > CIFS_MAX_ACTIMEO) {
|
||||
cifs_dbg(VFS, "acregmax too large\n");
|
||||
cifs_errorf(fc, "acregmax too large\n");
|
||||
goto cifs_parse_mount_err;
|
||||
}
|
||||
break;
|
||||
case Opt_acdirmax:
|
||||
ctx->acdirmax = HZ * result.uint_32;
|
||||
if (ctx->acdirmax > CIFS_MAX_ACTIMEO) {
|
||||
cifs_dbg(VFS, "acdirmax too large\n");
|
||||
cifs_errorf(fc, "acdirmax too large\n");
|
||||
goto cifs_parse_mount_err;
|
||||
}
|
||||
break;
|
||||
case Opt_actimeo:
|
||||
if (HZ * result.uint_32 > CIFS_MAX_ACTIMEO) {
|
||||
cifs_dbg(VFS, "timeout too large\n");
|
||||
cifs_errorf(fc, "timeout too large\n");
|
||||
goto cifs_parse_mount_err;
|
||||
}
|
||||
if ((ctx->acdirmax != CIFS_DEF_ACTIMEO) ||
|
||||
(ctx->acregmax != CIFS_DEF_ACTIMEO)) {
|
||||
cifs_dbg(VFS, "actimeo ignored since acregmax or acdirmax specified\n");
|
||||
cifs_errorf(fc, "actimeo ignored since acregmax or acdirmax specified\n");
|
||||
break;
|
||||
}
|
||||
ctx->acdirmax = ctx->acregmax = HZ * result.uint_32;
|
||||
@ -982,7 +1004,7 @@ static int smb3_fs_context_parse_param(struct fs_context *fc,
|
||||
break;
|
||||
case Opt_max_credits:
|
||||
if (result.uint_32 < 20 || result.uint_32 > 60000) {
|
||||
cifs_dbg(VFS, "%s: Invalid max_credits value\n",
|
||||
cifs_errorf(fc, "%s: Invalid max_credits value\n",
|
||||
__func__);
|
||||
goto cifs_parse_mount_err;
|
||||
}
|
||||
@ -990,7 +1012,7 @@ static int smb3_fs_context_parse_param(struct fs_context *fc,
|
||||
break;
|
||||
case Opt_max_channels:
|
||||
if (result.uint_32 < 1 || result.uint_32 > CIFS_MAX_CHANNELS) {
|
||||
cifs_dbg(VFS, "%s: Invalid max_channels value, needs to be 1-%d\n",
|
||||
cifs_errorf(fc, "%s: Invalid max_channels value, needs to be 1-%d\n",
|
||||
__func__, CIFS_MAX_CHANNELS);
|
||||
goto cifs_parse_mount_err;
|
||||
}
|
||||
@ -999,7 +1021,7 @@ static int smb3_fs_context_parse_param(struct fs_context *fc,
|
||||
case Opt_handletimeout:
|
||||
ctx->handle_timeout = result.uint_32;
|
||||
if (ctx->handle_timeout > SMB3_MAX_HANDLE_TIMEOUT) {
|
||||
cifs_dbg(VFS, "Invalid handle cache timeout, longer than 16 minutes\n");
|
||||
cifs_errorf(fc, "Invalid handle cache timeout, longer than 16 minutes\n");
|
||||
goto cifs_parse_mount_err;
|
||||
}
|
||||
break;
|
||||
@ -1010,23 +1032,23 @@ static int smb3_fs_context_parse_param(struct fs_context *fc,
|
||||
case 0:
|
||||
break;
|
||||
case -ENOMEM:
|
||||
cifs_dbg(VFS, "Unable to allocate memory for devname\n");
|
||||
cifs_errorf(fc, "Unable to allocate memory for devname\n");
|
||||
goto cifs_parse_mount_err;
|
||||
case -EINVAL:
|
||||
cifs_dbg(VFS, "Malformed UNC in devname\n");
|
||||
cifs_errorf(fc, "Malformed UNC in devname\n");
|
||||
goto cifs_parse_mount_err;
|
||||
default:
|
||||
cifs_dbg(VFS, "Unknown error parsing devname\n");
|
||||
cifs_errorf(fc, "Unknown error parsing devname\n");
|
||||
goto cifs_parse_mount_err;
|
||||
}
|
||||
ctx->source = kstrdup(param->string, GFP_KERNEL);
|
||||
if (ctx->source == NULL) {
|
||||
cifs_dbg(VFS, "OOM when copying UNC string\n");
|
||||
cifs_errorf(fc, "OOM when copying UNC string\n");
|
||||
goto cifs_parse_mount_err;
|
||||
}
|
||||
fc->source = kstrdup(param->string, GFP_KERNEL);
|
||||
if (fc->source == NULL) {
|
||||
cifs_dbg(VFS, "OOM when copying UNC string\n");
|
||||
cifs_errorf(fc, "OOM when copying UNC string\n");
|
||||
goto cifs_parse_mount_err;
|
||||
}
|
||||
break;
|
||||
@ -1046,7 +1068,7 @@ static int smb3_fs_context_parse_param(struct fs_context *fc,
|
||||
}
|
||||
ctx->username = kstrdup(param->string, GFP_KERNEL);
|
||||
if (ctx->username == NULL) {
|
||||
cifs_dbg(VFS, "OOM when copying username string\n");
|
||||
cifs_errorf(fc, "OOM when copying username string\n");
|
||||
goto cifs_parse_mount_err;
|
||||
}
|
||||
break;
|
||||
@ -1058,7 +1080,7 @@ static int smb3_fs_context_parse_param(struct fs_context *fc,
|
||||
|
||||
ctx->password = kstrdup(param->string, GFP_KERNEL);
|
||||
if (ctx->password == NULL) {
|
||||
cifs_dbg(VFS, "OOM when copying password string\n");
|
||||
cifs_errorf(fc, "OOM when copying password string\n");
|
||||
goto cifs_parse_mount_err;
|
||||
}
|
||||
break;
|
||||
@ -1085,7 +1107,7 @@ static int smb3_fs_context_parse_param(struct fs_context *fc,
|
||||
kfree(ctx->domainname);
|
||||
ctx->domainname = kstrdup(param->string, GFP_KERNEL);
|
||||
if (ctx->domainname == NULL) {
|
||||
cifs_dbg(VFS, "OOM when copying domainname string\n");
|
||||
cifs_errorf(fc, "OOM when copying domainname string\n");
|
||||
goto cifs_parse_mount_err;
|
||||
}
|
||||
cifs_dbg(FYI, "Domain name set\n");
|
||||
@ -1109,7 +1131,7 @@ static int smb3_fs_context_parse_param(struct fs_context *fc,
|
||||
kfree(ctx->iocharset);
|
||||
ctx->iocharset = kstrdup(param->string, GFP_KERNEL);
|
||||
if (ctx->iocharset == NULL) {
|
||||
cifs_dbg(VFS, "OOM when copying iocharset string\n");
|
||||
cifs_errorf(fc, "OOM when copying iocharset string\n");
|
||||
goto cifs_parse_mount_err;
|
||||
}
|
||||
}
|
||||
@ -1175,21 +1197,21 @@ static int smb3_fs_context_parse_param(struct fs_context *fc,
|
||||
goto cifs_parse_mount_err;
|
||||
case Opt_vers:
|
||||
/* protocol version (dialect) */
|
||||
if (cifs_parse_smb_version(param->string, ctx, is_smb3) != 0)
|
||||
if (cifs_parse_smb_version(fc, param->string, ctx, is_smb3) != 0)
|
||||
goto cifs_parse_mount_err;
|
||||
ctx->got_version = true;
|
||||
break;
|
||||
case Opt_sec:
|
||||
if (cifs_parse_security_flavors(param->string, ctx) != 0)
|
||||
if (cifs_parse_security_flavors(fc, param->string, ctx) != 0)
|
||||
goto cifs_parse_mount_err;
|
||||
break;
|
||||
case Opt_cache:
|
||||
if (cifs_parse_cache_flavor(param->string, ctx) != 0)
|
||||
if (cifs_parse_cache_flavor(fc, param->string, ctx) != 0)
|
||||
goto cifs_parse_mount_err;
|
||||
break;
|
||||
case Opt_witness:
|
||||
#ifndef CONFIG_CIFS_SWN_UPCALL
|
||||
cifs_dbg(VFS, "Witness support needs CONFIG_CIFS_SWN_UPCALL config option\n");
|
||||
cifs_errorf(fc, "Witness support needs CONFIG_CIFS_SWN_UPCALL config option\n");
|
||||
goto cifs_parse_mount_err;
|
||||
#endif
|
||||
ctx->witness = true;
|
||||
@ -1290,7 +1312,7 @@ static int smb3_fs_context_parse_param(struct fs_context *fc,
|
||||
break;
|
||||
case Opt_fsc:
|
||||
#ifndef CONFIG_CIFS_FSCACHE
|
||||
cifs_dbg(VFS, "FS-Cache support needs CONFIG_CIFS_FSCACHE kernel config option set\n");
|
||||
cifs_errorf(fc, "FS-Cache support needs CONFIG_CIFS_FSCACHE kernel config option set\n");
|
||||
goto cifs_parse_mount_err;
|
||||
#endif
|
||||
ctx->fsc = true;
|
||||
@ -1311,15 +1333,13 @@ static int smb3_fs_context_parse_param(struct fs_context *fc,
|
||||
if (result.negated) {
|
||||
ctx->nopersistent = true;
|
||||
if (ctx->persistent) {
|
||||
cifs_dbg(VFS,
|
||||
"persistenthandles mount options conflict\n");
|
||||
cifs_errorf(fc, "persistenthandles mount options conflict\n");
|
||||
goto cifs_parse_mount_err;
|
||||
}
|
||||
} else {
|
||||
ctx->persistent = true;
|
||||
if ((ctx->nopersistent) || (ctx->resilient)) {
|
||||
cifs_dbg(VFS,
|
||||
"persistenthandles mount options conflict\n");
|
||||
cifs_errorf(fc, "persistenthandles mount options conflict\n");
|
||||
goto cifs_parse_mount_err;
|
||||
}
|
||||
}
|
||||
@ -1330,8 +1350,7 @@ static int smb3_fs_context_parse_param(struct fs_context *fc,
|
||||
} else {
|
||||
ctx->resilient = true;
|
||||
if (ctx->persistent) {
|
||||
cifs_dbg(VFS,
|
||||
"persistenthandles mount options conflict\n");
|
||||
cifs_errorf(fc, "persistenthandles mount options conflict\n");
|
||||
goto cifs_parse_mount_err;
|
||||
}
|
||||
}
|
||||
@ -1379,7 +1398,9 @@ int smb3_init_fs_context(struct fs_context *fc)
|
||||
ctx->cred_uid = current_uid();
|
||||
ctx->linux_uid = current_uid();
|
||||
ctx->linux_gid = current_gid();
|
||||
ctx->bsize = 1024 * 1024; /* can improve cp performance significantly */
|
||||
/* By default 4MB read ahead size, 1MB block size */
|
||||
ctx->bsize = CIFS_DEFAULT_IOSIZE; /* can improve cp performance significantly */
|
||||
ctx->rasize = 0; /* 0 = use default (ie negotiated rsize) for read ahead pages */
|
||||
|
||||
/*
|
||||
* default to SFM style remapping of seven reserved characters
|
||||
|
@ -13,7 +13,12 @@
|
||||
#include <linux/parser.h>
|
||||
#include <linux/fs_parser.h>
|
||||
|
||||
#define cifs_invalf(fc, fmt, ...) invalf(fc, fmt, ## __VA_ARGS__)
|
||||
/* Log errors in fs_context (new mount api) but also in dmesg (old style) */
|
||||
#define cifs_errorf(fc, fmt, ...) \
|
||||
do { \
|
||||
errorf(fc, fmt, ## __VA_ARGS__); \
|
||||
cifs_dbg(VFS, fmt, ## __VA_ARGS__); \
|
||||
} while (0)
|
||||
|
||||
enum smb_version {
|
||||
Smb_1 = 1,
|
||||
@ -115,6 +120,7 @@ enum cifs_param {
|
||||
Opt_dirmode,
|
||||
Opt_min_enc_offload,
|
||||
Opt_blocksize,
|
||||
Opt_rasize,
|
||||
Opt_rsize,
|
||||
Opt_wsize,
|
||||
Opt_actimeo,
|
||||
@ -230,6 +236,7 @@ struct smb3_fs_context {
|
||||
/* reuse existing guid for multichannel */
|
||||
u8 client_guid[SMB2_CLIENT_GUID_SIZE];
|
||||
unsigned int bsize;
|
||||
unsigned int rasize;
|
||||
unsigned int rsize;
|
||||
unsigned int wsize;
|
||||
unsigned int min_offload;
|
||||
@ -257,10 +264,6 @@ struct smb3_fs_context {
|
||||
|
||||
extern const struct fs_parameter_spec smb3_fs_parameters[];
|
||||
|
||||
extern int cifs_parse_cache_flavor(char *value,
|
||||
struct smb3_fs_context *ctx);
|
||||
extern int cifs_parse_security_flavors(char *value,
|
||||
struct smb3_fs_context *ctx);
|
||||
extern int smb3_init_fs_context(struct fs_context *fc);
|
||||
extern void smb3_cleanup_fs_context_contents(struct smb3_fs_context *ctx);
|
||||
extern void smb3_cleanup_fs_context(struct smb3_fs_context *ctx);
|
||||
|
140
fs/cifs/inode.c
140
fs/cifs/inode.c
@ -1408,7 +1408,7 @@ out:
|
||||
|
||||
int
|
||||
cifs_set_file_info(struct inode *inode, struct iattr *attrs, unsigned int xid,
|
||||
char *full_path, __u32 dosattr)
|
||||
const char *full_path, __u32 dosattr)
|
||||
{
|
||||
bool set_time = false;
|
||||
struct cifs_sb_info *cifs_sb = CIFS_SB(inode->i_sb);
|
||||
@ -1609,7 +1609,8 @@ int cifs_unlink(struct inode *dir, struct dentry *dentry)
|
||||
{
|
||||
int rc = 0;
|
||||
unsigned int xid;
|
||||
char *full_path = NULL;
|
||||
const char *full_path;
|
||||
void *page;
|
||||
struct inode *inode = d_inode(dentry);
|
||||
struct cifsInodeInfo *cifs_inode;
|
||||
struct super_block *sb = dir->i_sb;
|
||||
@ -1629,6 +1630,7 @@ int cifs_unlink(struct inode *dir, struct dentry *dentry)
|
||||
server = tcon->ses->server;
|
||||
|
||||
xid = get_xid();
|
||||
page = alloc_dentry_path();
|
||||
|
||||
if (tcon->nodelete) {
|
||||
rc = -EACCES;
|
||||
@ -1637,9 +1639,9 @@ int cifs_unlink(struct inode *dir, struct dentry *dentry)
|
||||
|
||||
/* Unlink can be called from rename so we can not take the
|
||||
* sb->s_vfs_rename_mutex here */
|
||||
full_path = build_path_from_dentry(dentry);
|
||||
if (full_path == NULL) {
|
||||
rc = -ENOMEM;
|
||||
full_path = build_path_from_dentry(dentry, page);
|
||||
if (IS_ERR(full_path)) {
|
||||
rc = PTR_ERR(full_path);
|
||||
goto unlink_out;
|
||||
}
|
||||
|
||||
@ -1713,7 +1715,7 @@ out_reval:
|
||||
cifs_inode = CIFS_I(dir);
|
||||
CIFS_I(dir)->time = 0; /* force revalidate of dir as well */
|
||||
unlink_out:
|
||||
kfree(full_path);
|
||||
free_dentry_path(page);
|
||||
kfree(attrs);
|
||||
free_xid(xid);
|
||||
cifs_put_tlink(tlink);
|
||||
@ -1866,7 +1868,8 @@ int cifs_mkdir(struct user_namespace *mnt_userns, struct inode *inode,
|
||||
struct tcon_link *tlink;
|
||||
struct cifs_tcon *tcon;
|
||||
struct TCP_Server_Info *server;
|
||||
char *full_path;
|
||||
const char *full_path;
|
||||
void *page;
|
||||
|
||||
cifs_dbg(FYI, "In cifs_mkdir, mode = %04ho inode = 0x%p\n",
|
||||
mode, inode);
|
||||
@ -1879,9 +1882,10 @@ int cifs_mkdir(struct user_namespace *mnt_userns, struct inode *inode,
|
||||
|
||||
xid = get_xid();
|
||||
|
||||
full_path = build_path_from_dentry(direntry);
|
||||
if (full_path == NULL) {
|
||||
rc = -ENOMEM;
|
||||
page = alloc_dentry_path();
|
||||
full_path = build_path_from_dentry(direntry, page);
|
||||
if (IS_ERR(full_path)) {
|
||||
rc = PTR_ERR(full_path);
|
||||
goto mkdir_out;
|
||||
}
|
||||
|
||||
@ -1924,7 +1928,7 @@ mkdir_out:
|
||||
* attributes are invalid now.
|
||||
*/
|
||||
CIFS_I(inode)->time = 0;
|
||||
kfree(full_path);
|
||||
free_dentry_path(page);
|
||||
free_xid(xid);
|
||||
cifs_put_tlink(tlink);
|
||||
return rc;
|
||||
@ -1938,16 +1942,17 @@ int cifs_rmdir(struct inode *inode, struct dentry *direntry)
|
||||
struct tcon_link *tlink;
|
||||
struct cifs_tcon *tcon;
|
||||
struct TCP_Server_Info *server;
|
||||
char *full_path = NULL;
|
||||
const char *full_path;
|
||||
void *page = alloc_dentry_path();
|
||||
struct cifsInodeInfo *cifsInode;
|
||||
|
||||
cifs_dbg(FYI, "cifs_rmdir, inode = 0x%p\n", inode);
|
||||
|
||||
xid = get_xid();
|
||||
|
||||
full_path = build_path_from_dentry(direntry);
|
||||
if (full_path == NULL) {
|
||||
rc = -ENOMEM;
|
||||
full_path = build_path_from_dentry(direntry, page);
|
||||
if (IS_ERR(full_path)) {
|
||||
rc = PTR_ERR(full_path);
|
||||
goto rmdir_exit;
|
||||
}
|
||||
|
||||
@ -1997,7 +2002,7 @@ int cifs_rmdir(struct inode *inode, struct dentry *direntry)
|
||||
current_time(inode);
|
||||
|
||||
rmdir_exit:
|
||||
kfree(full_path);
|
||||
free_dentry_path(page);
|
||||
free_xid(xid);
|
||||
return rc;
|
||||
}
|
||||
@ -2072,8 +2077,8 @@ cifs_rename2(struct user_namespace *mnt_userns, struct inode *source_dir,
|
||||
struct dentry *source_dentry, struct inode *target_dir,
|
||||
struct dentry *target_dentry, unsigned int flags)
|
||||
{
|
||||
char *from_name = NULL;
|
||||
char *to_name = NULL;
|
||||
const char *from_name, *to_name;
|
||||
void *page1, *page2;
|
||||
struct cifs_sb_info *cifs_sb;
|
||||
struct tcon_link *tlink;
|
||||
struct cifs_tcon *tcon;
|
||||
@ -2091,21 +2096,19 @@ cifs_rename2(struct user_namespace *mnt_userns, struct inode *source_dir,
|
||||
return PTR_ERR(tlink);
|
||||
tcon = tlink_tcon(tlink);
|
||||
|
||||
page1 = alloc_dentry_path();
|
||||
page2 = alloc_dentry_path();
|
||||
xid = get_xid();
|
||||
|
||||
/*
|
||||
* we already have the rename sem so we do not need to
|
||||
* grab it again here to protect the path integrity
|
||||
*/
|
||||
from_name = build_path_from_dentry(source_dentry);
|
||||
if (from_name == NULL) {
|
||||
rc = -ENOMEM;
|
||||
from_name = build_path_from_dentry(source_dentry, page1);
|
||||
if (IS_ERR(from_name)) {
|
||||
rc = PTR_ERR(from_name);
|
||||
goto cifs_rename_exit;
|
||||
}
|
||||
|
||||
to_name = build_path_from_dentry(target_dentry);
|
||||
if (to_name == NULL) {
|
||||
rc = -ENOMEM;
|
||||
to_name = build_path_from_dentry(target_dentry, page2);
|
||||
if (IS_ERR(to_name)) {
|
||||
rc = PTR_ERR(to_name);
|
||||
goto cifs_rename_exit;
|
||||
}
|
||||
|
||||
@ -2177,18 +2180,21 @@ unlink_target:
|
||||
|
||||
cifs_rename_exit:
|
||||
kfree(info_buf_source);
|
||||
kfree(from_name);
|
||||
kfree(to_name);
|
||||
free_dentry_path(page2);
|
||||
free_dentry_path(page1);
|
||||
free_xid(xid);
|
||||
cifs_put_tlink(tlink);
|
||||
return rc;
|
||||
}
|
||||
|
||||
static bool
|
||||
cifs_inode_needs_reval(struct inode *inode)
|
||||
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_tcon *tcon = cifs_sb_master_tcon(cifs_sb);
|
||||
struct cached_fid *cfid = NULL;
|
||||
|
||||
if (cifs_i->time == 0)
|
||||
return true;
|
||||
@ -2199,6 +2205,16 @@ cifs_inode_needs_reval(struct inode *inode)
|
||||
if (!lookupCacheEnabled)
|
||||
return true;
|
||||
|
||||
if (!open_cached_dir_by_dentry(tcon, dentry->d_parent, &cfid)) {
|
||||
mutex_lock(&cfid->fid_mutex);
|
||||
if (cfid->time && cifs_i->time > cfid->time) {
|
||||
mutex_unlock(&cfid->fid_mutex);
|
||||
close_cached_dir(cfid);
|
||||
return false;
|
||||
}
|
||||
mutex_unlock(&cfid->fid_mutex);
|
||||
close_cached_dir(cfid);
|
||||
}
|
||||
/*
|
||||
* depending on inode type, check if attribute caching disabled for
|
||||
* files or directories
|
||||
@ -2297,10 +2313,10 @@ cifs_zap_mapping(struct inode *inode)
|
||||
int cifs_revalidate_file_attr(struct file *filp)
|
||||
{
|
||||
int rc = 0;
|
||||
struct inode *inode = file_inode(filp);
|
||||
struct dentry *dentry = file_dentry(filp);
|
||||
struct cifsFileInfo *cfile = (struct cifsFileInfo *) filp->private_data;
|
||||
|
||||
if (!cifs_inode_needs_reval(inode))
|
||||
if (!cifs_dentry_needs_reval(dentry))
|
||||
return rc;
|
||||
|
||||
if (tlink_tcon(cfile->tlink)->unix_ext)
|
||||
@ -2317,22 +2333,22 @@ int cifs_revalidate_dentry_attr(struct dentry *dentry)
|
||||
int rc = 0;
|
||||
struct inode *inode = d_inode(dentry);
|
||||
struct super_block *sb = dentry->d_sb;
|
||||
char *full_path = NULL;
|
||||
const char *full_path;
|
||||
void *page;
|
||||
int count = 0;
|
||||
|
||||
if (inode == NULL)
|
||||
return -ENOENT;
|
||||
|
||||
if (!cifs_inode_needs_reval(inode))
|
||||
if (!cifs_dentry_needs_reval(dentry))
|
||||
return rc;
|
||||
|
||||
xid = get_xid();
|
||||
|
||||
/* can not safely grab the rename sem here if rename calls revalidate
|
||||
since that would deadlock */
|
||||
full_path = build_path_from_dentry(dentry);
|
||||
if (full_path == NULL) {
|
||||
rc = -ENOMEM;
|
||||
page = alloc_dentry_path();
|
||||
full_path = build_path_from_dentry(dentry, page);
|
||||
if (IS_ERR(full_path)) {
|
||||
rc = PTR_ERR(full_path);
|
||||
goto out;
|
||||
}
|
||||
|
||||
@ -2351,7 +2367,7 @@ again:
|
||||
if (rc == -EAGAIN && count++ < 10)
|
||||
goto again;
|
||||
out:
|
||||
kfree(full_path);
|
||||
free_dentry_path(page);
|
||||
free_xid(xid);
|
||||
|
||||
return rc;
|
||||
@ -2522,7 +2538,7 @@ void cifs_setsize(struct inode *inode, loff_t offset)
|
||||
|
||||
static int
|
||||
cifs_set_file_size(struct inode *inode, struct iattr *attrs,
|
||||
unsigned int xid, char *full_path)
|
||||
unsigned int xid, const char *full_path)
|
||||
{
|
||||
int rc;
|
||||
struct cifsFileInfo *open_file;
|
||||
@ -2613,7 +2629,8 @@ cifs_setattr_unix(struct dentry *direntry, struct iattr *attrs)
|
||||
{
|
||||
int rc;
|
||||
unsigned int xid;
|
||||
char *full_path = NULL;
|
||||
const char *full_path;
|
||||
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);
|
||||
@ -2634,9 +2651,9 @@ cifs_setattr_unix(struct dentry *direntry, struct iattr *attrs)
|
||||
if (rc < 0)
|
||||
goto out;
|
||||
|
||||
full_path = build_path_from_dentry(direntry);
|
||||
if (full_path == NULL) {
|
||||
rc = -ENOMEM;
|
||||
full_path = build_path_from_dentry(direntry, page);
|
||||
if (IS_ERR(full_path)) {
|
||||
rc = PTR_ERR(full_path);
|
||||
goto out;
|
||||
}
|
||||
|
||||
@ -2748,7 +2765,7 @@ cifs_setattr_unix(struct dentry *direntry, struct iattr *attrs)
|
||||
cifsInode->time = 0;
|
||||
out:
|
||||
kfree(args);
|
||||
kfree(full_path);
|
||||
free_dentry_path(page);
|
||||
free_xid(xid);
|
||||
return rc;
|
||||
}
|
||||
@ -2764,7 +2781,8 @@ cifs_setattr_nounix(struct dentry *direntry, struct iattr *attrs)
|
||||
struct cifsInodeInfo *cifsInode = CIFS_I(inode);
|
||||
struct cifsFileInfo *wfile;
|
||||
struct cifs_tcon *tcon;
|
||||
char *full_path = NULL;
|
||||
const char *full_path;
|
||||
void *page = alloc_dentry_path();
|
||||
int rc = -EACCES;
|
||||
__u32 dosattr = 0;
|
||||
__u64 mode = NO_CHANGE_64;
|
||||
@ -2778,16 +2796,13 @@ cifs_setattr_nounix(struct dentry *direntry, struct iattr *attrs)
|
||||
attrs->ia_valid |= ATTR_FORCE;
|
||||
|
||||
rc = setattr_prepare(&init_user_ns, direntry, attrs);
|
||||
if (rc < 0) {
|
||||
free_xid(xid);
|
||||
return rc;
|
||||
}
|
||||
if (rc < 0)
|
||||
goto cifs_setattr_exit;
|
||||
|
||||
full_path = build_path_from_dentry(direntry);
|
||||
if (full_path == NULL) {
|
||||
rc = -ENOMEM;
|
||||
free_xid(xid);
|
||||
return rc;
|
||||
full_path = build_path_from_dentry(direntry, page);
|
||||
if (IS_ERR(full_path)) {
|
||||
rc = PTR_ERR(full_path);
|
||||
goto cifs_setattr_exit;
|
||||
}
|
||||
|
||||
/*
|
||||
@ -2937,8 +2952,8 @@ cifs_setattr_nounix(struct dentry *direntry, struct iattr *attrs)
|
||||
mark_inode_dirty(inode);
|
||||
|
||||
cifs_setattr_exit:
|
||||
kfree(full_path);
|
||||
free_xid(xid);
|
||||
free_dentry_path(page);
|
||||
return rc;
|
||||
}
|
||||
|
||||
@ -2961,12 +2976,3 @@ cifs_setattr(struct user_namespace *mnt_userns, struct dentry *direntry,
|
||||
/* BB: add cifs_setattr_legacy for really old servers */
|
||||
return rc;
|
||||
}
|
||||
|
||||
#if 0
|
||||
void cifs_delete_inode(struct inode *inode)
|
||||
{
|
||||
cifs_dbg(FYI, "In cifs_delete_inode, inode = 0x%p\n", inode);
|
||||
/* may have to add back in if and when safe distributed caching of
|
||||
directories added e.g. via FindNotify */
|
||||
}
|
||||
#endif
|
||||
|
@ -42,13 +42,16 @@ static long cifs_ioctl_query_info(unsigned int xid, struct file *filep,
|
||||
struct cifs_sb_info *cifs_sb = CIFS_SB(inode->i_sb);
|
||||
struct cifs_tcon *tcon = cifs_sb_master_tcon(cifs_sb);
|
||||
struct dentry *dentry = filep->f_path.dentry;
|
||||
unsigned char *path;
|
||||
const unsigned char *path;
|
||||
void *page = alloc_dentry_path();
|
||||
__le16 *utf16_path = NULL, root_path;
|
||||
int rc = 0;
|
||||
|
||||
path = build_path_from_dentry(dentry);
|
||||
if (path == NULL)
|
||||
return -ENOMEM;
|
||||
path = build_path_from_dentry(dentry, page);
|
||||
if (IS_ERR(path)) {
|
||||
free_dentry_path(page);
|
||||
return PTR_ERR(path);
|
||||
}
|
||||
|
||||
cifs_dbg(FYI, "%s %s\n", __func__, path);
|
||||
|
||||
@ -73,7 +76,7 @@ static long cifs_ioctl_query_info(unsigned int xid, struct file *filep,
|
||||
ici_exit:
|
||||
if (utf16_path != &root_path)
|
||||
kfree(utf16_path);
|
||||
kfree(path);
|
||||
free_dentry_path(page);
|
||||
return rc;
|
||||
}
|
||||
|
||||
|
@ -510,8 +510,8 @@ cifs_hardlink(struct dentry *old_file, struct inode *inode,
|
||||
{
|
||||
int rc = -EACCES;
|
||||
unsigned int xid;
|
||||
char *from_name = NULL;
|
||||
char *to_name = NULL;
|
||||
const char *from_name, *to_name;
|
||||
void *page1, *page2;
|
||||
struct cifs_sb_info *cifs_sb = CIFS_SB(inode->i_sb);
|
||||
struct tcon_link *tlink;
|
||||
struct cifs_tcon *tcon;
|
||||
@ -524,11 +524,17 @@ cifs_hardlink(struct dentry *old_file, struct inode *inode,
|
||||
tcon = tlink_tcon(tlink);
|
||||
|
||||
xid = get_xid();
|
||||
page1 = alloc_dentry_path();
|
||||
page2 = alloc_dentry_path();
|
||||
|
||||
from_name = build_path_from_dentry(old_file);
|
||||
to_name = build_path_from_dentry(direntry);
|
||||
if ((from_name == NULL) || (to_name == NULL)) {
|
||||
rc = -ENOMEM;
|
||||
from_name = build_path_from_dentry(old_file, page1);
|
||||
if (IS_ERR(from_name)) {
|
||||
rc = PTR_ERR(from_name);
|
||||
goto cifs_hl_exit;
|
||||
}
|
||||
to_name = build_path_from_dentry(direntry, page2);
|
||||
if (IS_ERR(to_name)) {
|
||||
rc = PTR_ERR(to_name);
|
||||
goto cifs_hl_exit;
|
||||
}
|
||||
|
||||
@ -587,8 +593,8 @@ cifs_hardlink(struct dentry *old_file, struct inode *inode,
|
||||
}
|
||||
|
||||
cifs_hl_exit:
|
||||
kfree(from_name);
|
||||
kfree(to_name);
|
||||
free_dentry_path(page1);
|
||||
free_dentry_path(page2);
|
||||
free_xid(xid);
|
||||
cifs_put_tlink(tlink);
|
||||
return rc;
|
||||
@ -600,7 +606,8 @@ cifs_get_link(struct dentry *direntry, struct inode *inode,
|
||||
{
|
||||
int rc = -ENOMEM;
|
||||
unsigned int xid;
|
||||
char *full_path = NULL;
|
||||
const char *full_path;
|
||||
void *page;
|
||||
char *target_path = NULL;
|
||||
struct cifs_sb_info *cifs_sb = CIFS_SB(inode->i_sb);
|
||||
struct tcon_link *tlink = NULL;
|
||||
@ -620,11 +627,13 @@ cifs_get_link(struct dentry *direntry, struct inode *inode,
|
||||
tcon = tlink_tcon(tlink);
|
||||
server = tcon->ses->server;
|
||||
|
||||
full_path = build_path_from_dentry(direntry);
|
||||
if (!full_path) {
|
||||
page = alloc_dentry_path();
|
||||
full_path = build_path_from_dentry(direntry, page);
|
||||
if (IS_ERR(full_path)) {
|
||||
free_xid(xid);
|
||||
cifs_put_tlink(tlink);
|
||||
return ERR_PTR(-ENOMEM);
|
||||
free_dentry_path(page);
|
||||
return ERR_CAST(full_path);
|
||||
}
|
||||
|
||||
cifs_dbg(FYI, "Full path: %s inode = 0x%p\n", full_path, inode);
|
||||
@ -649,7 +658,7 @@ cifs_get_link(struct dentry *direntry, struct inode *inode,
|
||||
&target_path, reparse_point);
|
||||
}
|
||||
|
||||
kfree(full_path);
|
||||
free_dentry_path(page);
|
||||
free_xid(xid);
|
||||
cifs_put_tlink(tlink);
|
||||
if (rc != 0) {
|
||||
@ -669,7 +678,8 @@ cifs_symlink(struct user_namespace *mnt_userns, struct inode *inode,
|
||||
struct cifs_sb_info *cifs_sb = CIFS_SB(inode->i_sb);
|
||||
struct tcon_link *tlink;
|
||||
struct cifs_tcon *pTcon;
|
||||
char *full_path = NULL;
|
||||
const char *full_path;
|
||||
void *page = alloc_dentry_path();
|
||||
struct inode *newinode = NULL;
|
||||
|
||||
xid = get_xid();
|
||||
@ -681,9 +691,9 @@ cifs_symlink(struct user_namespace *mnt_userns, struct inode *inode,
|
||||
}
|
||||
pTcon = tlink_tcon(tlink);
|
||||
|
||||
full_path = build_path_from_dentry(direntry);
|
||||
if (full_path == NULL) {
|
||||
rc = -ENOMEM;
|
||||
full_path = build_path_from_dentry(direntry, page);
|
||||
if (IS_ERR(full_path)) {
|
||||
rc = PTR_ERR(full_path);
|
||||
goto symlink_exit;
|
||||
}
|
||||
|
||||
@ -719,7 +729,7 @@ cifs_symlink(struct user_namespace *mnt_userns, struct inode *inode,
|
||||
}
|
||||
}
|
||||
symlink_exit:
|
||||
kfree(full_path);
|
||||
free_dentry_path(page);
|
||||
cifs_put_tlink(tlink);
|
||||
free_xid(xid);
|
||||
return rc;
|
||||
|
@ -1180,7 +1180,7 @@ int update_super_prepath(struct cifs_tcon *tcon, char *prefix)
|
||||
kfree(cifs_sb->prepath);
|
||||
|
||||
if (prefix && *prefix) {
|
||||
cifs_sb->prepath = kstrndup(prefix, strlen(prefix), GFP_ATOMIC);
|
||||
cifs_sb->prepath = kstrdup(prefix, GFP_ATOMIC);
|
||||
if (!cifs_sb->prepath) {
|
||||
rc = -ENOMEM;
|
||||
goto out;
|
||||
|
@ -384,7 +384,7 @@ int get_symlink_reparse_path(char *full_path, struct cifs_sb_info *cifs_sb,
|
||||
|
||||
static int
|
||||
initiate_cifs_search(const unsigned int xid, struct file *file,
|
||||
char *full_path)
|
||||
const char *full_path)
|
||||
{
|
||||
__u16 search_flags;
|
||||
int rc = 0;
|
||||
@ -704,7 +704,7 @@ static int cifs_save_resume_key(const char *current_entry,
|
||||
*/
|
||||
static int
|
||||
find_cifs_entry(const unsigned int xid, struct cifs_tcon *tcon, loff_t pos,
|
||||
struct file *file, char *full_path,
|
||||
struct file *file, const char *full_path,
|
||||
char **current_entry, int *num_to_ret)
|
||||
{
|
||||
__u16 search_flags;
|
||||
@ -942,13 +942,14 @@ int cifs_readdir(struct file *file, struct dir_context *ctx)
|
||||
char *tmp_buf = NULL;
|
||||
char *end_of_smb;
|
||||
unsigned int max_len;
|
||||
char *full_path = NULL;
|
||||
const char *full_path;
|
||||
void *page = alloc_dentry_path();
|
||||
|
||||
xid = get_xid();
|
||||
|
||||
full_path = build_path_from_dentry(file_dentry(file));
|
||||
if (full_path == NULL) {
|
||||
rc = -ENOMEM;
|
||||
full_path = build_path_from_dentry(file_dentry(file), page);
|
||||
if (IS_ERR(full_path)) {
|
||||
rc = PTR_ERR(full_path);
|
||||
goto rddir2_exit;
|
||||
}
|
||||
|
||||
@ -1043,7 +1044,7 @@ int cifs_readdir(struct file *file, struct dir_context *ctx)
|
||||
kfree(tmp_buf);
|
||||
|
||||
rddir2_exit:
|
||||
kfree(full_path);
|
||||
free_dentry_path(page);
|
||||
free_xid(xid);
|
||||
return rc;
|
||||
}
|
||||
|
@ -926,9 +926,7 @@ cifs_unix_dfs_readlink(const unsigned int xid, struct cifs_tcon *tcon,
|
||||
0);
|
||||
|
||||
if (!rc) {
|
||||
*symlinkinfo = kstrndup(referral.node_name,
|
||||
strlen(referral.node_name),
|
||||
GFP_KERNEL);
|
||||
*symlinkinfo = kstrdup(referral.node_name, GFP_KERNEL);
|
||||
free_dfs_info_param(&referral);
|
||||
if (!*symlinkinfo)
|
||||
rc = -ENOMEM;
|
||||
@ -1027,7 +1025,7 @@ cifs_can_echo(struct TCP_Server_Info *server)
|
||||
static int
|
||||
cifs_make_node(unsigned int xid, struct inode *inode,
|
||||
struct dentry *dentry, struct cifs_tcon *tcon,
|
||||
char *full_path, umode_t mode, dev_t dev)
|
||||
const char *full_path, umode_t mode, dev_t dev)
|
||||
{
|
||||
struct cifs_sb_info *cifs_sb = CIFS_SB(inode->i_sb);
|
||||
struct inode *newinode = NULL;
|
||||
|
@ -512,7 +512,6 @@ smb2_query_path_info(const unsigned int xid, struct cifs_tcon *tcon,
|
||||
int rc;
|
||||
struct smb2_file_all_info *smb2_data;
|
||||
__u32 create_options = 0;
|
||||
bool no_cached_open = tcon->nohandlecache;
|
||||
struct cifsFileInfo *cfile;
|
||||
struct cached_fid *cfid = NULL;
|
||||
|
||||
@ -525,11 +524,8 @@ smb2_query_path_info(const unsigned int xid, struct cifs_tcon *tcon,
|
||||
return -ENOMEM;
|
||||
|
||||
/* If it is a root and its handle is cached then use it */
|
||||
if (!strlen(full_path) && !no_cached_open) {
|
||||
rc = open_shroot(xid, tcon, cifs_sb, &cfid);
|
||||
if (rc)
|
||||
goto out;
|
||||
|
||||
rc = open_cached_dir(xid, tcon, full_path, cifs_sb, &cfid);
|
||||
if (!rc) {
|
||||
if (tcon->crfid.file_all_info_is_valid) {
|
||||
move_smb2_info_to_cifs(data,
|
||||
&tcon->crfid.file_all_info);
|
||||
@ -540,7 +536,7 @@ smb2_query_path_info(const unsigned int xid, struct cifs_tcon *tcon,
|
||||
if (!rc)
|
||||
move_smb2_info_to_cifs(data, smb2_data);
|
||||
}
|
||||
close_shroot(cfid);
|
||||
close_cached_dir(cfid);
|
||||
goto out;
|
||||
}
|
||||
|
||||
|
@ -667,6 +667,7 @@ smb2_is_valid_lease_break(char *buffer)
|
||||
!memcmp(rsp->LeaseKey,
|
||||
tcon->crfid.fid->lease_key,
|
||||
SMB2_LEASE_KEY_SIZE)) {
|
||||
tcon->crfid.time = 0;
|
||||
INIT_WORK(&tcon->crfid.lease_break,
|
||||
smb2_cached_lease_break);
|
||||
queue_work(cifsiod_wq,
|
||||
|
@ -690,17 +690,21 @@ smb2_close_cached_fid(struct kref *ref)
|
||||
cfid->is_valid = false;
|
||||
cfid->file_all_info_is_valid = false;
|
||||
cfid->has_lease = false;
|
||||
if (cfid->dentry) {
|
||||
dput(cfid->dentry);
|
||||
cfid->dentry = NULL;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void close_shroot(struct cached_fid *cfid)
|
||||
void close_cached_dir(struct cached_fid *cfid)
|
||||
{
|
||||
mutex_lock(&cfid->fid_mutex);
|
||||
kref_put(&cfid->refcount, smb2_close_cached_fid);
|
||||
mutex_unlock(&cfid->fid_mutex);
|
||||
}
|
||||
|
||||
void close_shroot_lease_locked(struct cached_fid *cfid)
|
||||
void close_cached_dir_lease_locked(struct cached_fid *cfid)
|
||||
{
|
||||
if (cfid->has_lease) {
|
||||
cfid->has_lease = false;
|
||||
@ -708,10 +712,10 @@ void close_shroot_lease_locked(struct cached_fid *cfid)
|
||||
}
|
||||
}
|
||||
|
||||
void close_shroot_lease(struct cached_fid *cfid)
|
||||
void close_cached_dir_lease(struct cached_fid *cfid)
|
||||
{
|
||||
mutex_lock(&cfid->fid_mutex);
|
||||
close_shroot_lease_locked(cfid);
|
||||
close_cached_dir_lease_locked(cfid);
|
||||
mutex_unlock(&cfid->fid_mutex);
|
||||
}
|
||||
|
||||
@ -721,13 +725,15 @@ smb2_cached_lease_break(struct work_struct *work)
|
||||
struct cached_fid *cfid = container_of(work,
|
||||
struct cached_fid, lease_break);
|
||||
|
||||
close_shroot_lease(cfid);
|
||||
close_cached_dir_lease(cfid);
|
||||
}
|
||||
|
||||
/*
|
||||
* Open the directory at the root of a share
|
||||
* Open the and cache a directory handle.
|
||||
* Only supported for the root handle.
|
||||
*/
|
||||
int open_shroot(unsigned int xid, struct cifs_tcon *tcon,
|
||||
int open_cached_dir(unsigned int xid, struct cifs_tcon *tcon,
|
||||
const char *path,
|
||||
struct cifs_sb_info *cifs_sb,
|
||||
struct cached_fid **cfid)
|
||||
{
|
||||
@ -745,6 +751,18 @@ int open_shroot(unsigned int xid, struct cifs_tcon *tcon,
|
||||
__le16 utf16_path = 0; /* Null - since an open of top of share */
|
||||
u8 oplock = SMB2_OPLOCK_LEVEL_II;
|
||||
struct cifs_fid *pfid;
|
||||
struct dentry *dentry;
|
||||
|
||||
if (tcon->nohandlecache)
|
||||
return -ENOTSUPP;
|
||||
|
||||
if (cifs_sb->root == NULL)
|
||||
return -ENOENT;
|
||||
|
||||
if (strlen(path))
|
||||
return -ENOENT;
|
||||
|
||||
dentry = cifs_sb->root;
|
||||
|
||||
mutex_lock(&tcon->crfid.fid_mutex);
|
||||
if (tcon->crfid.is_valid) {
|
||||
@ -830,11 +848,9 @@ int open_shroot(unsigned int xid, struct cifs_tcon *tcon,
|
||||
};
|
||||
|
||||
/*
|
||||
* caller expects this func to set pfid to a valid
|
||||
* cached root, so we copy the existing one and get a
|
||||
* reference.
|
||||
* caller expects this func to set the fid in crfid to valid
|
||||
* cached root, so increment the refcount.
|
||||
*/
|
||||
memcpy(pfid, tcon->crfid.fid, sizeof(*pfid));
|
||||
kref_get(&tcon->crfid.refcount);
|
||||
|
||||
mutex_unlock(&tcon->crfid.fid_mutex);
|
||||
@ -867,13 +883,18 @@ int open_shroot(unsigned int xid, struct cifs_tcon *tcon,
|
||||
oparms.fid->mid = le64_to_cpu(o_rsp->sync_hdr.MessageId);
|
||||
#endif /* CIFS_DEBUG2 */
|
||||
|
||||
memcpy(tcon->crfid.fid, pfid, sizeof(struct cifs_fid));
|
||||
tcon->crfid.tcon = tcon;
|
||||
tcon->crfid.is_valid = true;
|
||||
tcon->crfid.dentry = dentry;
|
||||
dget(dentry);
|
||||
kref_init(&tcon->crfid.refcount);
|
||||
|
||||
/* BB TBD check to see if oplock level check can be removed below */
|
||||
if (o_rsp->OplockLevel == SMB2_OPLOCK_LEVEL_LEASE) {
|
||||
/*
|
||||
* See commit 2f94a3125b87. Increment the refcount when we
|
||||
* get a lease for root, release it if lease break occurs
|
||||
*/
|
||||
kref_get(&tcon->crfid.refcount);
|
||||
tcon->crfid.has_lease = true;
|
||||
smb2_parse_contexts(server, o_rsp,
|
||||
@ -892,6 +913,8 @@ int open_shroot(unsigned int xid, struct cifs_tcon *tcon,
|
||||
&rsp_iov[1], sizeof(struct smb2_file_all_info),
|
||||
(char *)&tcon->crfid.file_all_info))
|
||||
tcon->crfid.file_all_info_is_valid = true;
|
||||
tcon->crfid.time = jiffies;
|
||||
|
||||
|
||||
oshr_exit:
|
||||
mutex_unlock(&tcon->crfid.fid_mutex);
|
||||
@ -905,6 +928,22 @@ oshr_free:
|
||||
return rc;
|
||||
}
|
||||
|
||||
int open_cached_dir_by_dentry(struct cifs_tcon *tcon,
|
||||
struct dentry *dentry,
|
||||
struct cached_fid **cfid)
|
||||
{
|
||||
mutex_lock(&tcon->crfid.fid_mutex);
|
||||
if (tcon->crfid.dentry == dentry) {
|
||||
cifs_dbg(FYI, "found a cached root file handle by dentry\n");
|
||||
*cfid = &tcon->crfid;
|
||||
kref_get(&tcon->crfid.refcount);
|
||||
mutex_unlock(&tcon->crfid.fid_mutex);
|
||||
return 0;
|
||||
}
|
||||
mutex_unlock(&tcon->crfid.fid_mutex);
|
||||
return -ENOENT;
|
||||
}
|
||||
|
||||
static void
|
||||
smb3_qfs_tcon(const unsigned int xid, struct cifs_tcon *tcon,
|
||||
struct cifs_sb_info *cifs_sb)
|
||||
@ -914,7 +953,6 @@ smb3_qfs_tcon(const unsigned int xid, struct cifs_tcon *tcon,
|
||||
u8 oplock = SMB2_OPLOCK_LEVEL_NONE;
|
||||
struct cifs_open_parms oparms;
|
||||
struct cifs_fid fid;
|
||||
bool no_cached_open = tcon->nohandlecache;
|
||||
struct cached_fid *cfid = NULL;
|
||||
|
||||
oparms.tcon = tcon;
|
||||
@ -924,14 +962,12 @@ smb3_qfs_tcon(const unsigned int xid, struct cifs_tcon *tcon,
|
||||
oparms.fid = &fid;
|
||||
oparms.reconnect = false;
|
||||
|
||||
if (no_cached_open) {
|
||||
rc = open_cached_dir(xid, tcon, "", cifs_sb, &cfid);
|
||||
if (rc == 0)
|
||||
memcpy(&fid, cfid->fid, sizeof(struct cifs_fid));
|
||||
else
|
||||
rc = SMB2_open(xid, &oparms, &srch_path, &oplock, NULL, NULL,
|
||||
NULL, NULL);
|
||||
} else {
|
||||
rc = open_shroot(xid, tcon, cifs_sb, &cfid);
|
||||
if (rc == 0)
|
||||
memcpy(&fid, cfid->fid, sizeof(struct cifs_fid));
|
||||
}
|
||||
if (rc)
|
||||
return;
|
||||
|
||||
@ -945,10 +981,10 @@ smb3_qfs_tcon(const unsigned int xid, struct cifs_tcon *tcon,
|
||||
FS_VOLUME_INFORMATION);
|
||||
SMB2_QFS_attr(xid, tcon, fid.persistent_fid, fid.volatile_fid,
|
||||
FS_SECTOR_SIZE_INFORMATION); /* SMB3 specific */
|
||||
if (no_cached_open)
|
||||
if (cfid == NULL)
|
||||
SMB2_close(xid, tcon, fid.persistent_fid, fid.volatile_fid);
|
||||
else
|
||||
close_shroot(cfid);
|
||||
close_cached_dir(cfid);
|
||||
}
|
||||
|
||||
static void
|
||||
@ -1531,7 +1567,10 @@ SMB2_request_res_key(const unsigned int xid, struct cifs_tcon *tcon,
|
||||
NULL, 0 /* no input */, CIFSMaxBufSize,
|
||||
(char **)&res_key, &ret_data_len);
|
||||
|
||||
if (rc) {
|
||||
if (rc == -EOPNOTSUPP) {
|
||||
pr_warn_once("Server share %s does not support copy range\n", tcon->treeName);
|
||||
goto req_res_key_exit;
|
||||
} else if (rc) {
|
||||
cifs_tcon_dbg(VFS, "refcpy ioctl error %d getting resume key\n", rc);
|
||||
goto req_res_key_exit;
|
||||
}
|
||||
@ -1763,18 +1802,14 @@ smb2_ioctl_query_info(const unsigned int xid,
|
||||
}
|
||||
|
||||
iqinf_exit:
|
||||
kfree(vars);
|
||||
kfree(buffer);
|
||||
SMB2_open_free(&rqst[0]);
|
||||
if (qi.flags & PASSTHRU_FSCTL)
|
||||
SMB2_ioctl_free(&rqst[1]);
|
||||
else
|
||||
SMB2_query_info_free(&rqst[1]);
|
||||
|
||||
SMB2_close_free(&rqst[2]);
|
||||
cifs_small_buf_release(rqst[0].rq_iov[0].iov_base);
|
||||
cifs_small_buf_release(rqst[1].rq_iov[0].iov_base);
|
||||
cifs_small_buf_release(rqst[2].rq_iov[0].iov_base);
|
||||
free_rsp_buf(resp_buftype[0], rsp_iov[0].iov_base);
|
||||
free_rsp_buf(resp_buftype[1], rsp_iov[1].iov_base);
|
||||
free_rsp_buf(resp_buftype[2], rsp_iov[2].iov_base);
|
||||
kfree(vars);
|
||||
kfree(buffer);
|
||||
return rc;
|
||||
|
||||
e_fault:
|
||||
@ -2217,22 +2252,23 @@ smb3_notify(const unsigned int xid, struct file *pfile,
|
||||
struct smb3_notify notify;
|
||||
struct dentry *dentry = pfile->f_path.dentry;
|
||||
struct inode *inode = file_inode(pfile);
|
||||
struct cifs_sb_info *cifs_sb;
|
||||
struct cifs_sb_info *cifs_sb = CIFS_SB(inode->i_sb);
|
||||
struct cifs_open_parms oparms;
|
||||
struct cifs_fid fid;
|
||||
struct cifs_tcon *tcon;
|
||||
unsigned char *path = NULL;
|
||||
const unsigned char *path;
|
||||
void *page = alloc_dentry_path();
|
||||
__le16 *utf16_path = NULL;
|
||||
u8 oplock = SMB2_OPLOCK_LEVEL_NONE;
|
||||
int rc = 0;
|
||||
|
||||
path = build_path_from_dentry(dentry);
|
||||
if (path == NULL)
|
||||
return -ENOMEM;
|
||||
path = build_path_from_dentry(dentry, page);
|
||||
if (IS_ERR(path)) {
|
||||
rc = PTR_ERR(path);
|
||||
goto notify_exit;
|
||||
}
|
||||
|
||||
cifs_sb = CIFS_SB(inode->i_sb);
|
||||
|
||||
utf16_path = cifs_convert_path_to_utf16(path + 1, cifs_sb);
|
||||
utf16_path = cifs_convert_path_to_utf16(path, cifs_sb);
|
||||
if (utf16_path == NULL) {
|
||||
rc = -ENOMEM;
|
||||
goto notify_exit;
|
||||
@ -2264,7 +2300,7 @@ smb3_notify(const unsigned int xid, struct file *pfile,
|
||||
cifs_dbg(FYI, "change notify for path %s rc %d\n", path, rc);
|
||||
|
||||
notify_exit:
|
||||
kfree(path);
|
||||
free_dentry_path(page);
|
||||
kfree(utf16_path);
|
||||
return rc;
|
||||
}
|
||||
@ -3652,6 +3688,77 @@ out:
|
||||
return rc;
|
||||
}
|
||||
|
||||
static long smb3_collapse_range(struct file *file, struct cifs_tcon *tcon,
|
||||
loff_t off, loff_t len)
|
||||
{
|
||||
int rc;
|
||||
unsigned int xid;
|
||||
struct cifsFileInfo *cfile = file->private_data;
|
||||
__le64 eof;
|
||||
|
||||
xid = get_xid();
|
||||
|
||||
if (off >= i_size_read(file->f_inode) ||
|
||||
off + len >= i_size_read(file->f_inode)) {
|
||||
rc = -EINVAL;
|
||||
goto out;
|
||||
}
|
||||
|
||||
rc = smb2_copychunk_range(xid, cfile, cfile, off + len,
|
||||
i_size_read(file->f_inode) - off - len, off);
|
||||
if (rc < 0)
|
||||
goto out;
|
||||
|
||||
eof = cpu_to_le64(i_size_read(file->f_inode) - len);
|
||||
rc = SMB2_set_eof(xid, tcon, cfile->fid.persistent_fid,
|
||||
cfile->fid.volatile_fid, cfile->pid, &eof);
|
||||
if (rc < 0)
|
||||
goto out;
|
||||
|
||||
rc = 0;
|
||||
out:
|
||||
free_xid(xid);
|
||||
return rc;
|
||||
}
|
||||
|
||||
static long smb3_insert_range(struct file *file, struct cifs_tcon *tcon,
|
||||
loff_t off, loff_t len)
|
||||
{
|
||||
int rc;
|
||||
unsigned int xid;
|
||||
struct cifsFileInfo *cfile = file->private_data;
|
||||
__le64 eof;
|
||||
__u64 count;
|
||||
|
||||
xid = get_xid();
|
||||
|
||||
if (off >= i_size_read(file->f_inode)) {
|
||||
rc = -EINVAL;
|
||||
goto out;
|
||||
}
|
||||
|
||||
count = i_size_read(file->f_inode) - off;
|
||||
eof = cpu_to_le64(i_size_read(file->f_inode) + len);
|
||||
|
||||
rc = SMB2_set_eof(xid, tcon, cfile->fid.persistent_fid,
|
||||
cfile->fid.volatile_fid, cfile->pid, &eof);
|
||||
if (rc < 0)
|
||||
goto out;
|
||||
|
||||
rc = smb2_copychunk_range(xid, cfile, cfile, off, count, off + len);
|
||||
if (rc < 0)
|
||||
goto out;
|
||||
|
||||
rc = smb3_zero_range(file, tcon, off, len, 1);
|
||||
if (rc < 0)
|
||||
goto out;
|
||||
|
||||
rc = 0;
|
||||
out:
|
||||
free_xid(xid);
|
||||
return rc;
|
||||
}
|
||||
|
||||
static loff_t smb3_llseek(struct file *file, struct cifs_tcon *tcon, loff_t offset, int whence)
|
||||
{
|
||||
struct cifsFileInfo *wrcfile, *cfile = file->private_data;
|
||||
@ -3823,6 +3930,10 @@ static long smb3_fallocate(struct file *file, struct cifs_tcon *tcon, int mode,
|
||||
return smb3_zero_range(file, tcon, off, len, false);
|
||||
} else if (mode == FALLOC_FL_KEEP_SIZE)
|
||||
return smb3_simple_falloc(file, tcon, off, len, true);
|
||||
else if (mode == FALLOC_FL_COLLAPSE_RANGE)
|
||||
return smb3_collapse_range(file, tcon, off, len);
|
||||
else if (mode == FALLOC_FL_INSERT_RANGE)
|
||||
return smb3_insert_range(file, tcon, off, len);
|
||||
else if (mode == 0)
|
||||
return smb3_simple_falloc(file, tcon, off, len, false);
|
||||
|
||||
@ -4178,7 +4289,7 @@ smb2_get_enc_key(struct TCP_Server_Info *server, __u64 ses_id, int enc, u8 *key)
|
||||
}
|
||||
spin_unlock(&cifs_tcp_ses_lock);
|
||||
|
||||
return 1;
|
||||
return -EAGAIN;
|
||||
}
|
||||
/*
|
||||
* Encrypt or decrypt @rqst message. @rqst[0] has the following format:
|
||||
@ -4968,7 +5079,7 @@ smb2_next_header(char *buf)
|
||||
static int
|
||||
smb2_make_node(unsigned int xid, struct inode *inode,
|
||||
struct dentry *dentry, struct cifs_tcon *tcon,
|
||||
char *full_path, umode_t mode, dev_t dev)
|
||||
const char *full_path, umode_t mode, dev_t dev)
|
||||
{
|
||||
struct cifs_sb_info *cifs_sb = CIFS_SB(inode->i_sb);
|
||||
int rc = -EPERM;
|
||||
|
@ -1857,7 +1857,7 @@ SMB2_tdis(const unsigned int xid, struct cifs_tcon *tcon)
|
||||
if ((tcon->need_reconnect) || (tcon->ses->need_reconnect))
|
||||
return 0;
|
||||
|
||||
close_shroot_lease(&tcon->crfid);
|
||||
close_cached_dir_lease(&tcon->crfid);
|
||||
|
||||
rc = smb2_plain_req_init(SMB2_TREE_DISCONNECT, tcon, ses->server,
|
||||
(void **) &req,
|
||||
|
@ -144,7 +144,7 @@ struct smb2_transform_hdr {
|
||||
} __packed;
|
||||
|
||||
/* See MS-SMB2 2.2.42 */
|
||||
struct smb2_compression_transform_hdr {
|
||||
struct smb2_compression_transform_hdr_unchained {
|
||||
__le32 ProtocolId; /* 0xFC 'S' 'M' 'B' */
|
||||
__le32 OriginalCompressedSegmentSize;
|
||||
__le16 CompressionAlgorithm;
|
||||
@ -160,10 +160,17 @@ struct compression_payload_header {
|
||||
__le16 CompressionAlgorithm;
|
||||
__le16 Flags;
|
||||
__le32 Length; /* length of compressed playload including field below if present */
|
||||
/* __le32 OriginalPayloadSize; */ /* optional */
|
||||
/* __le32 OriginalPayloadSize; */ /* optional, present when LZNT1, LZ77, LZ77+Huffman */
|
||||
} __packed;
|
||||
|
||||
/* See MS-SMB2 2.2.42.2 */
|
||||
struct smb2_compression_transform_hdr_chained {
|
||||
__le32 ProtocolId; /* 0xFC 'S' 'M' 'B' */
|
||||
__le32 OriginalCompressedSegmentSize;
|
||||
/* struct compression_payload_header[] */
|
||||
} __packed;
|
||||
|
||||
/* See MS-SMB2 2.2.42.2.2 */
|
||||
struct compression_pattern_payload_v1 {
|
||||
__le16 Pattern;
|
||||
__le16 Reserved1;
|
||||
@ -181,7 +188,11 @@ struct smb2_rdma_transform {
|
||||
__le32 Reserved2;
|
||||
} __packed;
|
||||
|
||||
struct smb2_rdma_encryption_transform {
|
||||
/* TransformType */
|
||||
#define SMB2_RDMA_TRANSFORM_TYPE_ENCRYPTION 0x0001
|
||||
#define SMB2_RDMA_TRANSFORM_TYPE_SIGNING 0x0002
|
||||
|
||||
struct smb2_rdma_crypto_transform {
|
||||
__le16 TransformType;
|
||||
__le16 SignatureLength;
|
||||
__le16 NonceLength;
|
||||
@ -409,13 +420,29 @@ struct smb2_netname_neg_context {
|
||||
} __packed;
|
||||
|
||||
/*
|
||||
* For rdma transform capabilities context see MS-SMB2 2.2.3.1.6
|
||||
* For smb2_transport_capabilities context see MS-SMB2 2.2.3.1.5
|
||||
* and 2.2.4.1.5
|
||||
*/
|
||||
|
||||
/* Flags */
|
||||
#define SMB2_ACCEPT_TRANSFORM_LEVEL_SECURITY 0x00000001
|
||||
|
||||
struct smb2_transport_capabilities_context {
|
||||
__le16 ContextType; /* 6 */
|
||||
__le16 DataLength;
|
||||
__u32 Reserved;
|
||||
__le32 Flags;
|
||||
} __packed;
|
||||
|
||||
/*
|
||||
* For rdma transform capabilities context see MS-SMB2 2.2.3.1.6
|
||||
* and 2.2.4.1.6
|
||||
*/
|
||||
|
||||
/* RDMA Transform IDs */
|
||||
#define SMB2_RDMA_TRANSFORM_NONE 0x0000
|
||||
#define SMB2_RDMA_TRANSFORM_ENCRYPTION 0x0001
|
||||
#define SMB2_RDMA_TRANSFORM_SIGNING 0x0002
|
||||
|
||||
struct smb2_rdma_transform_capabilities_context {
|
||||
__le16 ContextType; /* 7 */
|
||||
@ -427,6 +454,11 @@ struct smb2_rdma_transform_capabilities_context {
|
||||
__le16 RDMATransformIds[];
|
||||
} __packed;
|
||||
|
||||
/*
|
||||
* For signing capabilities context see MS-SMB2 2.2.3.1.7
|
||||
* and 2.2.4.1.7
|
||||
*/
|
||||
|
||||
/* Signing algorithms */
|
||||
#define SIGNING_ALG_HMAC_SHA256 0
|
||||
#define SIGNING_ALG_AES_CMAC 1
|
||||
@ -634,7 +666,8 @@ struct smb2_tree_connect_rsp {
|
||||
#define SHI1005_FLAGS_ENABLE_HASH_V2 0x00004000
|
||||
#define SHI1005_FLAGS_ENCRYPT_DATA 0x00008000
|
||||
#define SMB2_SHAREFLAG_IDENTITY_REMOTING 0x00040000 /* 3.1.1 */
|
||||
#define SHI1005_FLAGS_ALL 0x0004FF33
|
||||
#define SMB2_SHAREFLAG_COMPRESS_DATA 0x00100000 /* 3.1.1 */
|
||||
#define SHI1005_FLAGS_ALL 0x0014FF33
|
||||
|
||||
/* Possible share capabilities */
|
||||
#define SMB2_SHARE_CAP_DFS cpu_to_le32(0x00000008) /* all dialects */
|
||||
@ -1390,7 +1423,11 @@ struct smb2_lock_req {
|
||||
struct smb2_sync_hdr sync_hdr;
|
||||
__le16 StructureSize; /* Must be 48 */
|
||||
__le16 LockCount;
|
||||
__le32 Reserved;
|
||||
/*
|
||||
* The least significant four bits are the index, the other 28 bits are
|
||||
* the lock sequence number (0 to 64). See MS-SMB2 2.2.26
|
||||
*/
|
||||
__le32 LockSequenceNumber;
|
||||
__u64 PersistentFileId; /* opaque endianness */
|
||||
__u64 VolatileFileId; /* opaque endianness */
|
||||
/* Followed by at least one */
|
||||
|
@ -69,12 +69,16 @@ extern struct cifs_ses *smb2_find_smb_ses(struct TCP_Server_Info *server,
|
||||
extern int smb3_handle_read_data(struct TCP_Server_Info *server,
|
||||
struct mid_q_entry *mid);
|
||||
|
||||
extern int open_shroot(unsigned int xid, struct cifs_tcon *tcon,
|
||||
struct cifs_sb_info *cifs_sb,
|
||||
struct cached_fid **cfid);
|
||||
extern void close_shroot(struct cached_fid *cfid);
|
||||
extern void close_shroot_lease(struct cached_fid *cfid);
|
||||
extern void close_shroot_lease_locked(struct cached_fid *cfid);
|
||||
extern int open_cached_dir(unsigned int xid, struct cifs_tcon *tcon,
|
||||
const char *path,
|
||||
struct cifs_sb_info *cifs_sb,
|
||||
struct cached_fid **cfid);
|
||||
extern int open_cached_dir_by_dentry(struct cifs_tcon *tcon,
|
||||
struct dentry *dentry,
|
||||
struct cached_fid **cfid);
|
||||
extern void close_cached_dir(struct cached_fid *cfid);
|
||||
extern void close_cached_dir_lease(struct cached_fid *cfid);
|
||||
extern void close_cached_dir_lease_locked(struct cached_fid *cfid);
|
||||
extern void move_smb2_info_to_cifs(FILE_ALL_INFO *dst,
|
||||
struct smb2_file_all_info *src);
|
||||
extern int smb2_query_reparse_tag(const unsigned int xid, struct cifs_tcon *tcon,
|
||||
|
@ -50,7 +50,6 @@ char *extract_sharename(const char *unc)
|
||||
{
|
||||
const char *src;
|
||||
char *delim, *dst;
|
||||
int len;
|
||||
|
||||
/* skip double chars at the beginning */
|
||||
src = unc + 2;
|
||||
@ -60,10 +59,9 @@ char *extract_sharename(const char *unc)
|
||||
if (!delim)
|
||||
return ERR_PTR(-EINVAL);
|
||||
delim++;
|
||||
len = strlen(delim);
|
||||
|
||||
/* caller has to free the memory */
|
||||
dst = kstrndup(delim, len, GFP_KERNEL);
|
||||
dst = kstrdup(delim, GFP_KERNEL);
|
||||
if (!dst)
|
||||
return ERR_PTR(-ENOMEM);
|
||||
|
||||
|
@ -53,7 +53,7 @@ enum { XATTR_USER, XATTR_CIFS_ACL, XATTR_ACL_ACCESS, XATTR_ACL_DEFAULT,
|
||||
XATTR_CIFS_NTSD, XATTR_CIFS_NTSD_FULL };
|
||||
|
||||
static int cifs_attrib_set(unsigned int xid, struct cifs_tcon *pTcon,
|
||||
struct inode *inode, char *full_path,
|
||||
struct inode *inode, const char *full_path,
|
||||
const void *value, size_t size)
|
||||
{
|
||||
ssize_t rc = -EOPNOTSUPP;
|
||||
@ -77,7 +77,7 @@ static int cifs_attrib_set(unsigned int xid, struct cifs_tcon *pTcon,
|
||||
}
|
||||
|
||||
static int cifs_creation_time_set(unsigned int xid, struct cifs_tcon *pTcon,
|
||||
struct inode *inode, char *full_path,
|
||||
struct inode *inode, const char *full_path,
|
||||
const void *value, size_t size)
|
||||
{
|
||||
ssize_t rc = -EOPNOTSUPP;
|
||||
@ -112,7 +112,8 @@ static int cifs_xattr_set(const struct xattr_handler *handler,
|
||||
struct cifs_sb_info *cifs_sb = CIFS_SB(sb);
|
||||
struct tcon_link *tlink;
|
||||
struct cifs_tcon *pTcon;
|
||||
char *full_path;
|
||||
const char *full_path;
|
||||
void *page;
|
||||
|
||||
tlink = cifs_sb_tlink(cifs_sb);
|
||||
if (IS_ERR(tlink))
|
||||
@ -120,10 +121,11 @@ static int cifs_xattr_set(const struct xattr_handler *handler,
|
||||
pTcon = tlink_tcon(tlink);
|
||||
|
||||
xid = get_xid();
|
||||
page = alloc_dentry_path();
|
||||
|
||||
full_path = build_path_from_dentry(dentry);
|
||||
if (full_path == NULL) {
|
||||
rc = -ENOMEM;
|
||||
full_path = build_path_from_dentry(dentry, page);
|
||||
if (IS_ERR(full_path)) {
|
||||
rc = PTR_ERR(full_path);
|
||||
goto out;
|
||||
}
|
||||
/* return dos attributes as pseudo xattr */
|
||||
@ -235,7 +237,7 @@ static int cifs_xattr_set(const struct xattr_handler *handler,
|
||||
}
|
||||
|
||||
out:
|
||||
kfree(full_path);
|
||||
free_dentry_path(page);
|
||||
free_xid(xid);
|
||||
cifs_put_tlink(tlink);
|
||||
return rc;
|
||||
@ -297,7 +299,8 @@ static int cifs_xattr_get(const struct xattr_handler *handler,
|
||||
struct cifs_sb_info *cifs_sb = CIFS_SB(sb);
|
||||
struct tcon_link *tlink;
|
||||
struct cifs_tcon *pTcon;
|
||||
char *full_path;
|
||||
const char *full_path;
|
||||
void *page;
|
||||
|
||||
tlink = cifs_sb_tlink(cifs_sb);
|
||||
if (IS_ERR(tlink))
|
||||
@ -305,10 +308,11 @@ static int cifs_xattr_get(const struct xattr_handler *handler,
|
||||
pTcon = tlink_tcon(tlink);
|
||||
|
||||
xid = get_xid();
|
||||
page = alloc_dentry_path();
|
||||
|
||||
full_path = build_path_from_dentry(dentry);
|
||||
if (full_path == NULL) {
|
||||
rc = -ENOMEM;
|
||||
full_path = build_path_from_dentry(dentry, page);
|
||||
if (IS_ERR(full_path)) {
|
||||
rc = PTR_ERR(full_path);
|
||||
goto out;
|
||||
}
|
||||
|
||||
@ -401,7 +405,7 @@ static int cifs_xattr_get(const struct xattr_handler *handler,
|
||||
rc = -EOPNOTSUPP;
|
||||
|
||||
out:
|
||||
kfree(full_path);
|
||||
free_dentry_path(page);
|
||||
free_xid(xid);
|
||||
cifs_put_tlink(tlink);
|
||||
return rc;
|
||||
@ -414,7 +418,8 @@ ssize_t cifs_listxattr(struct dentry *direntry, char *data, size_t buf_size)
|
||||
struct cifs_sb_info *cifs_sb = CIFS_SB(direntry->d_sb);
|
||||
struct tcon_link *tlink;
|
||||
struct cifs_tcon *pTcon;
|
||||
char *full_path;
|
||||
const char *full_path;
|
||||
void *page;
|
||||
|
||||
if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_NO_XATTR)
|
||||
return -EOPNOTSUPP;
|
||||
@ -425,10 +430,11 @@ ssize_t cifs_listxattr(struct dentry *direntry, char *data, size_t buf_size)
|
||||
pTcon = tlink_tcon(tlink);
|
||||
|
||||
xid = get_xid();
|
||||
page = alloc_dentry_path();
|
||||
|
||||
full_path = build_path_from_dentry(direntry);
|
||||
if (full_path == NULL) {
|
||||
rc = -ENOMEM;
|
||||
full_path = build_path_from_dentry(direntry, page);
|
||||
if (IS_ERR(full_path)) {
|
||||
rc = PTR_ERR(full_path);
|
||||
goto list_ea_exit;
|
||||
}
|
||||
/* return dos attributes as pseudo xattr */
|
||||
@ -442,7 +448,7 @@ ssize_t cifs_listxattr(struct dentry *direntry, char *data, size_t buf_size)
|
||||
rc = pTcon->ses->server->ops->query_all_EAs(xid, pTcon,
|
||||
full_path, NULL, data, buf_size, cifs_sb);
|
||||
list_ea_exit:
|
||||
kfree(full_path);
|
||||
free_dentry_path(page);
|
||||
free_xid(xid);
|
||||
cifs_put_tlink(tlink);
|
||||
return rc;
|
||||
|
Loading…
Reference in New Issue
Block a user