mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git
synced 2024-08-21 16:29:59 +00:00
cifs: handle different charsets in dfs cache
Convert all dfs paths to dfs cache's local codepage (@cache_cp) and avoid mixing them with different charsets. Signed-off-by: Paulo Alcantara (SUSE) <pc@cjr.nz> Reviewed-by: Aurelien Aptel <aaptel@suse.com> Signed-off-by: Steve French <stfrench@microsoft.com>
This commit is contained in:
parent
c9f7110399
commit
c870a8e70e
5 changed files with 136 additions and 137 deletions
|
@ -72,9 +72,8 @@ struct cifs_sb_info {
|
||||||
char *prepath;
|
char *prepath;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Path initially provided by the mount call. We might connect
|
* Canonical DFS path initially provided by the mount call. We might connect to something
|
||||||
* to something different via DFS but we want to keep it to do
|
* different via DFS but we want to keep it to do failover properly.
|
||||||
* failover properly.
|
|
||||||
*/
|
*/
|
||||||
char *origin_fullpath; /* \\HOST\SHARE\[OPTIONAL PATH] */
|
char *origin_fullpath; /* \\HOST\SHARE\[OPTIONAL PATH] */
|
||||||
/* randomly generated 128-bit number for indexing dfs mount groups in referral cache */
|
/* randomly generated 128-bit number for indexing dfs mount groups in referral cache */
|
||||||
|
|
|
@ -1093,8 +1093,7 @@ struct cifs_tcon {
|
||||||
struct cached_fid crfid; /* Cached root fid */
|
struct cached_fid crfid; /* Cached root fid */
|
||||||
/* BB add field for back pointer to sb struct(s)? */
|
/* BB add field for back pointer to sb struct(s)? */
|
||||||
#ifdef CONFIG_CIFS_DFS_UPCALL
|
#ifdef CONFIG_CIFS_DFS_UPCALL
|
||||||
char *dfs_path;
|
char *dfs_path; /* canonical DFS path */
|
||||||
int remap:2;
|
|
||||||
struct list_head ulist; /* cache update list */
|
struct list_head ulist; /* cache update list */
|
||||||
#endif
|
#endif
|
||||||
};
|
};
|
||||||
|
|
|
@ -3010,8 +3010,7 @@ expand_dfs_referral(const unsigned int xid, struct cifs_ses *ses,
|
||||||
return rc;
|
return rc;
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline int get_next_dfs_tgt(const char *path,
|
static int get_next_dfs_tgt(struct dfs_cache_tgt_list *tgt_list,
|
||||||
struct dfs_cache_tgt_list *tgt_list,
|
|
||||||
struct dfs_cache_tgt_iterator **tgt_it)
|
struct dfs_cache_tgt_iterator **tgt_it)
|
||||||
{
|
{
|
||||||
if (!*tgt_it)
|
if (!*tgt_it)
|
||||||
|
@ -3052,6 +3051,7 @@ static int do_dfs_failover(const char *path, const char *full_path, struct cifs_
|
||||||
struct cifs_ses **ses, struct cifs_tcon **tcon)
|
struct cifs_ses **ses, struct cifs_tcon **tcon)
|
||||||
{
|
{
|
||||||
int rc;
|
int rc;
|
||||||
|
char *npath = NULL;
|
||||||
struct dfs_cache_tgt_list tgt_list = {0};
|
struct dfs_cache_tgt_list tgt_list = {0};
|
||||||
struct dfs_cache_tgt_iterator *tgt_it = NULL;
|
struct dfs_cache_tgt_iterator *tgt_it = NULL;
|
||||||
struct smb3_fs_context tmp_ctx = {NULL};
|
struct smb3_fs_context tmp_ctx = {NULL};
|
||||||
|
@ -3059,11 +3059,15 @@ static int do_dfs_failover(const char *path, const char *full_path, struct cifs_
|
||||||
if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_NO_DFS)
|
if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_NO_DFS)
|
||||||
return -EOPNOTSUPP;
|
return -EOPNOTSUPP;
|
||||||
|
|
||||||
cifs_dbg(FYI, "%s: path=%s full_path=%s\n", __func__, path, full_path);
|
npath = dfs_cache_canonical_path(path, cifs_sb->local_nls, cifs_remap(cifs_sb));
|
||||||
|
if (IS_ERR(npath))
|
||||||
|
return PTR_ERR(npath);
|
||||||
|
|
||||||
rc = dfs_cache_noreq_find(path, NULL, &tgt_list);
|
cifs_dbg(FYI, "%s: path=%s full_path=%s\n", __func__, npath, full_path);
|
||||||
|
|
||||||
|
rc = dfs_cache_noreq_find(npath, NULL, &tgt_list);
|
||||||
if (rc)
|
if (rc)
|
||||||
return rc;
|
goto out;
|
||||||
/*
|
/*
|
||||||
* We use a 'tmp_ctx' here because we need pass it down to the mount_{get,put} functions to
|
* We use a 'tmp_ctx' here because we need pass it down to the mount_{get,put} functions to
|
||||||
* test connection against new DFS targets.
|
* test connection against new DFS targets.
|
||||||
|
@ -3077,11 +3081,11 @@ static int do_dfs_failover(const char *path, const char *full_path, struct cifs_
|
||||||
char *fake_devname = NULL, *mdata = NULL;
|
char *fake_devname = NULL, *mdata = NULL;
|
||||||
|
|
||||||
/* Get next DFS target server - if any */
|
/* Get next DFS target server - if any */
|
||||||
rc = get_next_dfs_tgt(path, &tgt_list, &tgt_it);
|
rc = get_next_dfs_tgt(&tgt_list, &tgt_it);
|
||||||
if (rc)
|
if (rc)
|
||||||
break;
|
break;
|
||||||
|
|
||||||
rc = dfs_cache_get_tgt_referral(path, tgt_it, &ref);
|
rc = dfs_cache_get_tgt_referral(npath, tgt_it, &ref);
|
||||||
if (rc)
|
if (rc)
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
@ -3130,6 +3134,7 @@ static int do_dfs_failover(const char *path, const char *full_path, struct cifs_
|
||||||
}
|
}
|
||||||
|
|
||||||
out:
|
out:
|
||||||
|
kfree(npath);
|
||||||
smb3_cleanup_fs_context_contents(&tmp_ctx);
|
smb3_cleanup_fs_context_contents(&tmp_ctx);
|
||||||
dfs_cache_free_tgts(&tgt_list);
|
dfs_cache_free_tgts(&tgt_list);
|
||||||
return rc;
|
return rc;
|
||||||
|
@ -3287,11 +3292,6 @@ static void set_root_ses(struct cifs_sb_info *cifs_sb, const uuid_t *mount_id, s
|
||||||
if (ses) {
|
if (ses) {
|
||||||
spin_lock(&cifs_tcp_ses_lock);
|
spin_lock(&cifs_tcp_ses_lock);
|
||||||
ses->ses_count++;
|
ses->ses_count++;
|
||||||
cifs_dbg(FYI, "%s: new ses_count=%d\n", __func__, ses->ses_count);
|
|
||||||
if (ses->tcon_ipc) {
|
|
||||||
cifs_dbg(FYI, "%s: ipc tcon: %s\n", __func__, ses->tcon_ipc->treeName);
|
|
||||||
ses->tcon_ipc->remap = cifs_remap(cifs_sb);
|
|
||||||
}
|
|
||||||
spin_unlock(&cifs_tcp_ses_lock);
|
spin_unlock(&cifs_tcp_ses_lock);
|
||||||
dfs_cache_add_refsrv_session(mount_id, ses);
|
dfs_cache_add_refsrv_session(mount_id, ses);
|
||||||
}
|
}
|
||||||
|
@ -3343,17 +3343,25 @@ static int next_dfs_prepath(struct cifs_sb_info *cifs_sb, struct smb3_fs_context
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Check if resolved targets can handle any DFS referrals */
|
/* Check if resolved targets can handle any DFS referrals */
|
||||||
static int is_referral_server(const char *ref_path, struct cifs_tcon *tcon, bool *ref_server)
|
static int is_referral_server(const char *ref_path, struct cifs_sb_info *cifs_sb,
|
||||||
|
struct cifs_tcon *tcon, bool *ref_server)
|
||||||
{
|
{
|
||||||
int rc;
|
int rc;
|
||||||
struct dfs_info3_param ref = {0};
|
struct dfs_info3_param ref = {0};
|
||||||
|
|
||||||
|
cifs_dbg(FYI, "%s: ref_path=%s\n", __func__, ref_path);
|
||||||
|
|
||||||
if (is_tcon_dfs(tcon)) {
|
if (is_tcon_dfs(tcon)) {
|
||||||
*ref_server = true;
|
*ref_server = true;
|
||||||
} else {
|
} else {
|
||||||
cifs_dbg(FYI, "%s: ref_path=%s\n", __func__, ref_path);
|
char *npath;
|
||||||
|
|
||||||
rc = dfs_cache_noreq_find(ref_path, &ref, NULL);
|
npath = dfs_cache_canonical_path(ref_path, cifs_sb->local_nls, cifs_remap(cifs_sb));
|
||||||
|
if (IS_ERR(npath))
|
||||||
|
return PTR_ERR(npath);
|
||||||
|
|
||||||
|
rc = dfs_cache_noreq_find(npath, &ref, NULL);
|
||||||
|
kfree(npath);
|
||||||
if (rc) {
|
if (rc) {
|
||||||
cifs_dbg(VFS, "%s: dfs_cache_noreq_find: failed (rc=%d)\n", __func__, rc);
|
cifs_dbg(VFS, "%s: dfs_cache_noreq_find: failed (rc=%d)\n", __func__, rc);
|
||||||
return rc;
|
return rc;
|
||||||
|
@ -3443,7 +3451,7 @@ int cifs_mount(struct cifs_sb_info *cifs_sb, struct smb3_fs_context *ctx)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
/* Make sure that requests go through new root servers */
|
/* Make sure that requests go through new root servers */
|
||||||
rc = is_referral_server(ref_path + 1, tcon, &ref_server);
|
rc = is_referral_server(ref_path + 1, cifs_sb, tcon, &ref_server);
|
||||||
if (rc)
|
if (rc)
|
||||||
break;
|
break;
|
||||||
if (ref_server)
|
if (ref_server)
|
||||||
|
@ -3460,7 +3468,6 @@ int cifs_mount(struct cifs_sb_info *cifs_sb, struct smb3_fs_context *ctx)
|
||||||
goto error;
|
goto error;
|
||||||
|
|
||||||
kfree(ref_path);
|
kfree(ref_path);
|
||||||
ref_path = NULL;
|
|
||||||
/*
|
/*
|
||||||
* Store DFS full path in both superblock and tree connect structures.
|
* Store DFS full path in both superblock and tree connect structures.
|
||||||
*
|
*
|
||||||
|
@ -3469,15 +3476,25 @@ 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
|
* links, the prefix path is included in both and may be changed during reconnect. See
|
||||||
* cifs_tree_connect().
|
* cifs_tree_connect().
|
||||||
*/
|
*/
|
||||||
cifs_sb->origin_fullpath = kstrdup(full_path, GFP_KERNEL);
|
ref_path = dfs_cache_canonical_path(full_path, cifs_sb->local_nls, cifs_remap(cifs_sb));
|
||||||
if (!cifs_sb->origin_fullpath) {
|
kfree(full_path);
|
||||||
|
full_path = NULL;
|
||||||
|
|
||||||
|
if (IS_ERR(ref_path)) {
|
||||||
|
rc = PTR_ERR(ref_path);
|
||||||
|
ref_path = NULL;
|
||||||
|
goto error;
|
||||||
|
}
|
||||||
|
cifs_sb->origin_fullpath = ref_path;
|
||||||
|
|
||||||
|
ref_path = kstrdup(cifs_sb->origin_fullpath, GFP_KERNEL);
|
||||||
|
if (!ref_path) {
|
||||||
rc = -ENOMEM;
|
rc = -ENOMEM;
|
||||||
goto error;
|
goto error;
|
||||||
}
|
}
|
||||||
spin_lock(&cifs_tcp_ses_lock);
|
spin_lock(&cifs_tcp_ses_lock);
|
||||||
tcon->dfs_path = full_path;
|
tcon->dfs_path = ref_path;
|
||||||
full_path = NULL;
|
ref_path = NULL;
|
||||||
tcon->remap = cifs_remap(cifs_sb);
|
|
||||||
spin_unlock(&cifs_tcp_ses_lock);
|
spin_unlock(&cifs_tcp_ses_lock);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
|
|
@ -65,7 +65,7 @@ static struct workqueue_struct *dfscache_wq __read_mostly;
|
||||||
static int cache_ttl;
|
static int cache_ttl;
|
||||||
static DEFINE_SPINLOCK(cache_ttl_lock);
|
static DEFINE_SPINLOCK(cache_ttl_lock);
|
||||||
|
|
||||||
static struct nls_table *cache_nlsc;
|
static struct nls_table *cache_cp;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Number of entries in the cache
|
* Number of entries in the cache
|
||||||
|
@ -175,27 +175,45 @@ static void free_mount_group_list(void)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static int get_normalized_path(const char *path, const char **npath)
|
/**
|
||||||
|
* dfs_cache_canonical_path - get a canonical DFS path
|
||||||
|
*
|
||||||
|
* @path: DFS path
|
||||||
|
* @cp: codepage
|
||||||
|
* @remap: mapping type
|
||||||
|
*
|
||||||
|
* Return canonical path if success, otherwise error.
|
||||||
|
*/
|
||||||
|
char *dfs_cache_canonical_path(const char *path, const struct nls_table *cp, int remap)
|
||||||
{
|
{
|
||||||
|
char *tmp;
|
||||||
|
int plen = 0;
|
||||||
|
char *npath;
|
||||||
|
|
||||||
if (!path || strlen(path) < 3 || (*path != '\\' && *path != '/'))
|
if (!path || strlen(path) < 3 || (*path != '\\' && *path != '/'))
|
||||||
return -EINVAL;
|
return ERR_PTR(-EINVAL);
|
||||||
|
|
||||||
if (*path == '\\') {
|
if (unlikely(strcmp(cp->charset, cache_cp->charset))) {
|
||||||
*npath = path;
|
tmp = (char *)cifs_strndup_to_utf16(path, strlen(path), &plen, cp, remap);
|
||||||
} else {
|
if (!tmp) {
|
||||||
char *s = kstrdup(path, GFP_KERNEL);
|
cifs_dbg(VFS, "%s: failed to convert path to utf16\n", __func__);
|
||||||
if (!s)
|
return ERR_PTR(-EINVAL);
|
||||||
return -ENOMEM;
|
|
||||||
convert_delimiter(s, '\\');
|
|
||||||
*npath = s;
|
|
||||||
}
|
}
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
static inline void free_normalized_path(const char *path, const char *npath)
|
npath = cifs_strndup_from_utf16(tmp, plen, true, cache_cp);
|
||||||
{
|
kfree(tmp);
|
||||||
if (path != npath)
|
|
||||||
kfree(npath);
|
if (!npath) {
|
||||||
|
cifs_dbg(VFS, "%s: failed to convert path from utf16\n", __func__);
|
||||||
|
return ERR_PTR(-EINVAL);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
npath = kstrdup(path, GFP_KERNEL);
|
||||||
|
if (!npath)
|
||||||
|
return ERR_PTR(-ENOMEM);
|
||||||
|
}
|
||||||
|
convert_delimiter(npath, '\\');
|
||||||
|
return npath;
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline bool cache_entry_expired(const struct cache_entry *ce)
|
static inline bool cache_entry_expired(const struct cache_entry *ce)
|
||||||
|
@ -394,7 +412,9 @@ int dfs_cache_init(void)
|
||||||
INIT_HLIST_HEAD(&cache_htable[i]);
|
INIT_HLIST_HEAD(&cache_htable[i]);
|
||||||
|
|
||||||
atomic_set(&cache_count, 0);
|
atomic_set(&cache_count, 0);
|
||||||
cache_nlsc = load_nls_default();
|
cache_cp = load_nls("utf8");
|
||||||
|
if (!cache_cp)
|
||||||
|
cache_cp = load_nls_default();
|
||||||
|
|
||||||
cifs_dbg(FYI, "%s: initialized DFS referral cache\n", __func__);
|
cifs_dbg(FYI, "%s: initialized DFS referral cache\n", __func__);
|
||||||
return 0;
|
return 0;
|
||||||
|
@ -669,7 +689,7 @@ static struct cache_entry *lookup_cache_entry(const char *path, unsigned int *ha
|
||||||
void dfs_cache_destroy(void)
|
void dfs_cache_destroy(void)
|
||||||
{
|
{
|
||||||
cancel_delayed_work_sync(&refresh_task);
|
cancel_delayed_work_sync(&refresh_task);
|
||||||
unload_nls(cache_nlsc);
|
unload_nls(cache_cp);
|
||||||
free_mount_group_list();
|
free_mount_group_list();
|
||||||
flush_cache_ents();
|
flush_cache_ents();
|
||||||
kmem_cache_destroy(cache_slab);
|
kmem_cache_destroy(cache_slab);
|
||||||
|
@ -707,23 +727,21 @@ static int update_cache_entry_locked(const char *path, const struct dfs_info3_pa
|
||||||
return rc;
|
return rc;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int get_dfs_referral(const unsigned int xid, struct cifs_ses *ses,
|
static int get_dfs_referral(const unsigned int xid, struct cifs_ses *ses, const char *path,
|
||||||
const struct nls_table *nls_codepage, int remap,
|
struct dfs_info3_param **refs, int *numrefs)
|
||||||
const char *path, struct dfs_info3_param **refs,
|
|
||||||
int *numrefs)
|
|
||||||
{
|
{
|
||||||
cifs_dbg(FYI, "%s: get an DFS referral for %s\n", __func__, path);
|
cifs_dbg(FYI, "%s: get an DFS referral for %s\n", __func__, path);
|
||||||
|
|
||||||
if (!ses || !ses->server || !ses->server->ops->get_dfs_refer)
|
if (!ses || !ses->server || !ses->server->ops->get_dfs_refer)
|
||||||
return -EOPNOTSUPP;
|
return -EOPNOTSUPP;
|
||||||
if (unlikely(!nls_codepage))
|
if (unlikely(!cache_cp))
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
|
|
||||||
*refs = NULL;
|
*refs = NULL;
|
||||||
*numrefs = 0;
|
*numrefs = 0;
|
||||||
|
|
||||||
return ses->server->ops->get_dfs_refer(xid, ses, path, refs, numrefs,
|
return ses->server->ops->get_dfs_refer(xid, ses, path, refs, numrefs, cache_cp,
|
||||||
nls_codepage, remap);
|
NO_MAP_UNI_RSVD);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -735,8 +753,7 @@ static int get_dfs_referral(const unsigned int xid, struct cifs_ses *ses,
|
||||||
* For interlinks, cifs_mount() and expand_dfs_referral() are supposed to
|
* For interlinks, cifs_mount() and expand_dfs_referral() are supposed to
|
||||||
* handle them properly.
|
* handle them properly.
|
||||||
*/
|
*/
|
||||||
static int cache_refresh_path(const unsigned int xid, struct cifs_ses *ses,
|
static int cache_refresh_path(const unsigned int xid, struct cifs_ses *ses, const char *path)
|
||||||
const struct nls_table *nls_codepage, int remap, const char *path)
|
|
||||||
{
|
{
|
||||||
int rc;
|
int rc;
|
||||||
unsigned int hash;
|
unsigned int hash;
|
||||||
|
@ -764,8 +781,7 @@ static int cache_refresh_path(const unsigned int xid, struct cifs_ses *ses,
|
||||||
* Either the entry was not found, or it is expired.
|
* Either the entry was not found, or it is expired.
|
||||||
* Request a new DFS referral in order to create or update a cache entry.
|
* Request a new DFS referral in order to create or update a cache entry.
|
||||||
*/
|
*/
|
||||||
rc = get_dfs_referral(xid, ses, nls_codepage, remap, path,
|
rc = get_dfs_referral(xid, ses, path, &refs, &numrefs);
|
||||||
&refs, &numrefs);
|
|
||||||
if (rc)
|
if (rc)
|
||||||
goto out_unlock;
|
goto out_unlock;
|
||||||
|
|
||||||
|
@ -886,7 +902,7 @@ static int get_targets(struct cache_entry *ce, struct dfs_cache_tgt_list *tl)
|
||||||
* needs to be issued:
|
* needs to be issued:
|
||||||
* @xid: syscall xid
|
* @xid: syscall xid
|
||||||
* @ses: smb session to issue the request on
|
* @ses: smb session to issue the request on
|
||||||
* @nls_codepage: charset conversion
|
* @cp: codepage
|
||||||
* @remap: path character remapping type
|
* @remap: path character remapping type
|
||||||
* @path: path to lookup in DFS referral cache.
|
* @path: path to lookup in DFS referral cache.
|
||||||
*
|
*
|
||||||
|
@ -895,20 +911,19 @@ static int get_targets(struct cache_entry *ce, struct dfs_cache_tgt_list *tl)
|
||||||
*
|
*
|
||||||
* Return zero if the target was found, otherwise non-zero.
|
* Return zero if the target was found, otherwise non-zero.
|
||||||
*/
|
*/
|
||||||
int dfs_cache_find(const unsigned int xid, struct cifs_ses *ses,
|
int dfs_cache_find(const unsigned int xid, struct cifs_ses *ses, const struct nls_table *cp,
|
||||||
const struct nls_table *nls_codepage, int remap,
|
int remap, const char *path, struct dfs_info3_param *ref,
|
||||||
const char *path, struct dfs_info3_param *ref,
|
|
||||||
struct dfs_cache_tgt_list *tgt_list)
|
struct dfs_cache_tgt_list *tgt_list)
|
||||||
{
|
{
|
||||||
int rc;
|
int rc;
|
||||||
const char *npath;
|
const char *npath;
|
||||||
struct cache_entry *ce;
|
struct cache_entry *ce;
|
||||||
|
|
||||||
rc = get_normalized_path(path, &npath);
|
npath = dfs_cache_canonical_path(path, cp, remap);
|
||||||
if (rc)
|
if (IS_ERR(npath))
|
||||||
return rc;
|
return PTR_ERR(npath);
|
||||||
|
|
||||||
rc = cache_refresh_path(xid, ses, nls_codepage, remap, npath);
|
rc = cache_refresh_path(xid, ses, npath);
|
||||||
if (rc)
|
if (rc)
|
||||||
goto out_free_path;
|
goto out_free_path;
|
||||||
|
|
||||||
|
@ -931,7 +946,7 @@ int dfs_cache_find(const unsigned int xid, struct cifs_ses *ses,
|
||||||
up_read(&htable_rw_lock);
|
up_read(&htable_rw_lock);
|
||||||
|
|
||||||
out_free_path:
|
out_free_path:
|
||||||
free_normalized_path(path, npath);
|
kfree(npath);
|
||||||
return rc;
|
return rc;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -943,7 +958,7 @@ int dfs_cache_find(const unsigned int xid, struct cifs_ses *ses,
|
||||||
* expired, nor create a new cache entry if @path hasn't been found. It heavily
|
* expired, nor create a new cache entry if @path hasn't been found. It heavily
|
||||||
* relies on an existing cache entry.
|
* relies on an existing cache entry.
|
||||||
*
|
*
|
||||||
* @path: path to lookup in the DFS referral cache.
|
* @path: canonical DFS path to lookup in the DFS referral cache.
|
||||||
* @ref: when non-NULL, store single DFS referral result in it.
|
* @ref: when non-NULL, store single DFS referral result in it.
|
||||||
* @tgt_list: when non-NULL, store complete DFS target list in it.
|
* @tgt_list: when non-NULL, store complete DFS target list in it.
|
||||||
*
|
*
|
||||||
|
@ -955,18 +970,13 @@ int dfs_cache_noreq_find(const char *path, struct dfs_info3_param *ref,
|
||||||
struct dfs_cache_tgt_list *tgt_list)
|
struct dfs_cache_tgt_list *tgt_list)
|
||||||
{
|
{
|
||||||
int rc;
|
int rc;
|
||||||
const char *npath;
|
|
||||||
struct cache_entry *ce;
|
struct cache_entry *ce;
|
||||||
|
|
||||||
rc = get_normalized_path(path, &npath);
|
cifs_dbg(FYI, "%s: path: %s\n", __func__, path);
|
||||||
if (rc)
|
|
||||||
return rc;
|
|
||||||
|
|
||||||
cifs_dbg(FYI, "%s: path: %s\n", __func__, npath);
|
|
||||||
|
|
||||||
down_read(&htable_rw_lock);
|
down_read(&htable_rw_lock);
|
||||||
|
|
||||||
ce = lookup_cache_entry(npath, NULL);
|
ce = lookup_cache_entry(path, NULL);
|
||||||
if (IS_ERR(ce)) {
|
if (IS_ERR(ce)) {
|
||||||
rc = PTR_ERR(ce);
|
rc = PTR_ERR(ce);
|
||||||
goto out_unlock;
|
goto out_unlock;
|
||||||
|
@ -981,8 +991,6 @@ int dfs_cache_noreq_find(const char *path, struct dfs_info3_param *ref,
|
||||||
|
|
||||||
out_unlock:
|
out_unlock:
|
||||||
up_read(&htable_rw_lock);
|
up_read(&htable_rw_lock);
|
||||||
free_normalized_path(path, npath);
|
|
||||||
|
|
||||||
return rc;
|
return rc;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -997,16 +1005,15 @@ int dfs_cache_noreq_find(const char *path, struct dfs_info3_param *ref,
|
||||||
*
|
*
|
||||||
* @xid: syscall id
|
* @xid: syscall id
|
||||||
* @ses: smb session
|
* @ses: smb session
|
||||||
* @nls_codepage: charset conversion
|
* @cp: codepage
|
||||||
* @remap: type of character remapping for paths
|
* @remap: type of character remapping for paths
|
||||||
* @path: path to lookup in DFS referral cache.
|
* @path: path to lookup in DFS referral cache
|
||||||
* @it: DFS target iterator
|
* @it: DFS target iterator
|
||||||
*
|
*
|
||||||
* Return zero if the target hint was updated successfully, otherwise non-zero.
|
* Return zero if the target hint was updated successfully, otherwise non-zero.
|
||||||
*/
|
*/
|
||||||
int dfs_cache_update_tgthint(const unsigned int xid, struct cifs_ses *ses,
|
int dfs_cache_update_tgthint(const unsigned int xid, struct cifs_ses *ses,
|
||||||
const struct nls_table *nls_codepage, int remap,
|
const struct nls_table *cp, int remap, const char *path,
|
||||||
const char *path,
|
|
||||||
const struct dfs_cache_tgt_iterator *it)
|
const struct dfs_cache_tgt_iterator *it)
|
||||||
{
|
{
|
||||||
int rc;
|
int rc;
|
||||||
|
@ -1014,13 +1021,13 @@ int dfs_cache_update_tgthint(const unsigned int xid, struct cifs_ses *ses,
|
||||||
struct cache_entry *ce;
|
struct cache_entry *ce;
|
||||||
struct cache_dfs_tgt *t;
|
struct cache_dfs_tgt *t;
|
||||||
|
|
||||||
rc = get_normalized_path(path, &npath);
|
npath = dfs_cache_canonical_path(path, cp, remap);
|
||||||
if (rc)
|
if (IS_ERR(npath))
|
||||||
return rc;
|
return PTR_ERR(npath);
|
||||||
|
|
||||||
cifs_dbg(FYI, "%s: update target hint - path: %s\n", __func__, npath);
|
cifs_dbg(FYI, "%s: update target hint - path: %s\n", __func__, npath);
|
||||||
|
|
||||||
rc = cache_refresh_path(xid, ses, nls_codepage, remap, npath);
|
rc = cache_refresh_path(xid, ses, npath);
|
||||||
if (rc)
|
if (rc)
|
||||||
goto out_free_path;
|
goto out_free_path;
|
||||||
|
|
||||||
|
@ -1049,8 +1056,7 @@ int dfs_cache_update_tgthint(const unsigned int xid, struct cifs_ses *ses,
|
||||||
out_unlock:
|
out_unlock:
|
||||||
up_write(&htable_rw_lock);
|
up_write(&htable_rw_lock);
|
||||||
out_free_path:
|
out_free_path:
|
||||||
free_normalized_path(path, npath);
|
kfree(npath);
|
||||||
|
|
||||||
return rc;
|
return rc;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1062,32 +1068,26 @@ int dfs_cache_update_tgthint(const unsigned int xid, struct cifs_ses *ses,
|
||||||
* expired, nor create a new cache entry if @path hasn't been found. It heavily
|
* expired, nor create a new cache entry if @path hasn't been found. It heavily
|
||||||
* relies on an existing cache entry.
|
* relies on an existing cache entry.
|
||||||
*
|
*
|
||||||
* @path: path to lookup in DFS referral cache.
|
* @path: canonical DFS path to lookup in DFS referral cache.
|
||||||
* @it: target iterator which contains the target hint to update the cache
|
* @it: target iterator which contains the target hint to update the cache
|
||||||
* entry with.
|
* entry with.
|
||||||
*
|
*
|
||||||
* Return zero if the target hint was updated successfully, otherwise non-zero.
|
* Return zero if the target hint was updated successfully, otherwise non-zero.
|
||||||
*/
|
*/
|
||||||
int dfs_cache_noreq_update_tgthint(const char *path,
|
int dfs_cache_noreq_update_tgthint(const char *path, const struct dfs_cache_tgt_iterator *it)
|
||||||
const struct dfs_cache_tgt_iterator *it)
|
|
||||||
{
|
{
|
||||||
int rc;
|
int rc;
|
||||||
const char *npath;
|
|
||||||
struct cache_entry *ce;
|
struct cache_entry *ce;
|
||||||
struct cache_dfs_tgt *t;
|
struct cache_dfs_tgt *t;
|
||||||
|
|
||||||
if (!it)
|
if (!it)
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
|
|
||||||
rc = get_normalized_path(path, &npath);
|
cifs_dbg(FYI, "%s: path: %s\n", __func__, path);
|
||||||
if (rc)
|
|
||||||
return rc;
|
|
||||||
|
|
||||||
cifs_dbg(FYI, "%s: path: %s\n", __func__, npath);
|
|
||||||
|
|
||||||
down_write(&htable_rw_lock);
|
down_write(&htable_rw_lock);
|
||||||
|
|
||||||
ce = lookup_cache_entry(npath, NULL);
|
ce = lookup_cache_entry(path, NULL);
|
||||||
if (IS_ERR(ce)) {
|
if (IS_ERR(ce)) {
|
||||||
rc = PTR_ERR(ce);
|
rc = PTR_ERR(ce);
|
||||||
goto out_unlock;
|
goto out_unlock;
|
||||||
|
@ -1110,8 +1110,6 @@ int dfs_cache_noreq_update_tgthint(const char *path,
|
||||||
|
|
||||||
out_unlock:
|
out_unlock:
|
||||||
up_write(&htable_rw_lock);
|
up_write(&htable_rw_lock);
|
||||||
free_normalized_path(path, npath);
|
|
||||||
|
|
||||||
return rc;
|
return rc;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1119,32 +1117,26 @@ int dfs_cache_noreq_update_tgthint(const char *path,
|
||||||
* dfs_cache_get_tgt_referral - returns a DFS referral (@ref) from a given
|
* dfs_cache_get_tgt_referral - returns a DFS referral (@ref) from a given
|
||||||
* target iterator (@it).
|
* target iterator (@it).
|
||||||
*
|
*
|
||||||
* @path: path to lookup in DFS referral cache.
|
* @path: canonical DFS path to lookup in DFS referral cache.
|
||||||
* @it: DFS target iterator.
|
* @it: DFS target iterator.
|
||||||
* @ref: DFS referral pointer to set up the gathered information.
|
* @ref: DFS referral pointer to set up the gathered information.
|
||||||
*
|
*
|
||||||
* Return zero if the DFS referral was set up correctly, otherwise non-zero.
|
* Return zero if the DFS referral was set up correctly, otherwise non-zero.
|
||||||
*/
|
*/
|
||||||
int dfs_cache_get_tgt_referral(const char *path,
|
int dfs_cache_get_tgt_referral(const char *path, const struct dfs_cache_tgt_iterator *it,
|
||||||
const struct dfs_cache_tgt_iterator *it,
|
|
||||||
struct dfs_info3_param *ref)
|
struct dfs_info3_param *ref)
|
||||||
{
|
{
|
||||||
int rc;
|
int rc;
|
||||||
const char *npath;
|
|
||||||
struct cache_entry *ce;
|
struct cache_entry *ce;
|
||||||
|
|
||||||
if (!it || !ref)
|
if (!it || !ref)
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
|
|
||||||
rc = get_normalized_path(path, &npath);
|
cifs_dbg(FYI, "%s: path: %s\n", __func__, path);
|
||||||
if (rc)
|
|
||||||
return rc;
|
|
||||||
|
|
||||||
cifs_dbg(FYI, "%s: path: %s\n", __func__, npath);
|
|
||||||
|
|
||||||
down_read(&htable_rw_lock);
|
down_read(&htable_rw_lock);
|
||||||
|
|
||||||
ce = lookup_cache_entry(npath, NULL);
|
ce = lookup_cache_entry(path, NULL);
|
||||||
if (IS_ERR(ce)) {
|
if (IS_ERR(ce)) {
|
||||||
rc = PTR_ERR(ce);
|
rc = PTR_ERR(ce);
|
||||||
goto out_unlock;
|
goto out_unlock;
|
||||||
|
@ -1156,8 +1148,6 @@ int dfs_cache_get_tgt_referral(const char *path,
|
||||||
|
|
||||||
out_unlock:
|
out_unlock:
|
||||||
up_read(&htable_rw_lock);
|
up_read(&htable_rw_lock);
|
||||||
free_normalized_path(path, npath);
|
|
||||||
|
|
||||||
return rc;
|
return rc;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1219,8 +1209,8 @@ void dfs_cache_put_refsrv_sessions(const uuid_t *mount_id)
|
||||||
*
|
*
|
||||||
* Return zero if target was parsed correctly, otherwise non-zero.
|
* Return zero if target was parsed correctly, otherwise non-zero.
|
||||||
*/
|
*/
|
||||||
int dfs_cache_get_tgt_share(char *path, const struct dfs_cache_tgt_iterator *it,
|
int dfs_cache_get_tgt_share(char *path, const struct dfs_cache_tgt_iterator *it, char **share,
|
||||||
char **share, char **prefix)
|
char **prefix)
|
||||||
{
|
{
|
||||||
char *s, sep, *p;
|
char *s, sep, *p;
|
||||||
size_t len;
|
size_t len;
|
||||||
|
@ -1310,7 +1300,7 @@ static void refresh_mounts(struct cifs_ses **sessions)
|
||||||
ses = find_ipc_from_server_path(sessions, path);
|
ses = find_ipc_from_server_path(sessions, path);
|
||||||
if (!IS_ERR(ses)) {
|
if (!IS_ERR(ses)) {
|
||||||
xid = get_xid();
|
xid = get_xid();
|
||||||
cache_refresh_path(xid, ses, cache_nlsc, tcon->remap, path);
|
cache_refresh_path(xid, ses, path);
|
||||||
free_xid(xid);
|
free_xid(xid);
|
||||||
}
|
}
|
||||||
cifs_put_tcon(tcon);
|
cifs_put_tcon(tcon);
|
||||||
|
@ -1346,8 +1336,7 @@ static void refresh_cache(struct cifs_ses **sessions)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
xid = get_xid();
|
xid = get_xid();
|
||||||
rc = get_dfs_referral(xid, ses, cache_nlsc, NO_MAP_UNI_RSVD, ce->path,
|
rc = get_dfs_referral(xid, ses, ce->path, &refs, &numrefs);
|
||||||
&refs, &numrefs);
|
|
||||||
free_xid(xid);
|
free_xid(xid);
|
||||||
|
|
||||||
if (!rc)
|
if (!rc)
|
||||||
|
|
|
@ -24,31 +24,26 @@ struct dfs_cache_tgt_iterator {
|
||||||
struct list_head it_list;
|
struct list_head it_list;
|
||||||
};
|
};
|
||||||
|
|
||||||
extern int dfs_cache_init(void);
|
int dfs_cache_init(void);
|
||||||
extern void dfs_cache_destroy(void);
|
void dfs_cache_destroy(void);
|
||||||
extern const struct proc_ops dfscache_proc_ops;
|
extern const struct proc_ops dfscache_proc_ops;
|
||||||
|
|
||||||
extern int dfs_cache_find(const unsigned int xid, struct cifs_ses *ses,
|
int dfs_cache_find(const unsigned int xid, struct cifs_ses *ses, const struct nls_table *cp,
|
||||||
const struct nls_table *nls_codepage, int remap,
|
int remap, const char *path, struct dfs_info3_param *ref,
|
||||||
const char *path, struct dfs_info3_param *ref,
|
|
||||||
struct dfs_cache_tgt_list *tgt_list);
|
struct dfs_cache_tgt_list *tgt_list);
|
||||||
extern int dfs_cache_noreq_find(const char *path, struct dfs_info3_param *ref,
|
int dfs_cache_noreq_find(const char *path, struct dfs_info3_param *ref,
|
||||||
struct dfs_cache_tgt_list *tgt_list);
|
struct dfs_cache_tgt_list *tgt_list);
|
||||||
extern int dfs_cache_update_tgthint(const unsigned int xid,
|
int dfs_cache_update_tgthint(const unsigned int xid, struct cifs_ses *ses,
|
||||||
struct cifs_ses *ses,
|
const struct nls_table *cp, int remap, const char *path,
|
||||||
const struct nls_table *nls_codepage,
|
|
||||||
int remap, const char *path,
|
|
||||||
const struct dfs_cache_tgt_iterator *it);
|
const struct dfs_cache_tgt_iterator *it);
|
||||||
extern int
|
int dfs_cache_noreq_update_tgthint(const char *path, const struct dfs_cache_tgt_iterator *it);
|
||||||
dfs_cache_noreq_update_tgthint(const char *path,
|
int dfs_cache_get_tgt_referral(const char *path, const struct dfs_cache_tgt_iterator *it,
|
||||||
const struct dfs_cache_tgt_iterator *it);
|
|
||||||
extern int dfs_cache_get_tgt_referral(const char *path,
|
|
||||||
const struct dfs_cache_tgt_iterator *it,
|
|
||||||
struct dfs_info3_param *ref);
|
struct dfs_info3_param *ref);
|
||||||
extern int dfs_cache_get_tgt_share(char *path, const struct dfs_cache_tgt_iterator *it,
|
int dfs_cache_get_tgt_share(char *path, const struct dfs_cache_tgt_iterator *it, char **share,
|
||||||
char **share, char **prefix);
|
char **prefix);
|
||||||
void dfs_cache_put_refsrv_sessions(const uuid_t *mount_id);
|
void dfs_cache_put_refsrv_sessions(const uuid_t *mount_id);
|
||||||
void dfs_cache_add_refsrv_session(const uuid_t *mount_id, struct cifs_ses *ses);
|
void dfs_cache_add_refsrv_session(const uuid_t *mount_id, struct cifs_ses *ses);
|
||||||
|
char *dfs_cache_canonical_path(const char *path, const struct nls_table *cp, int remap);
|
||||||
|
|
||||||
static inline struct dfs_cache_tgt_iterator *
|
static inline struct dfs_cache_tgt_iterator *
|
||||||
dfs_cache_get_next_tgt(struct dfs_cache_tgt_list *tl,
|
dfs_cache_get_next_tgt(struct dfs_cache_tgt_list *tl,
|
||||||
|
|
Loading…
Reference in a new issue