forked from luck/tmp_suning_uos_patched
cifs: reduce number of referral requests in DFS link lookups
When looking up the DFS cache with a referral path that has more than two path components, and is a complete prefix of an existing cache entry, do not request another referral and just return the matched entry as specified in MS-DFSC 3.2.5.5 Receiving a Root Referral Request or Link Referral Request. 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
565674d613
commit
2e5de42445
|
@ -490,16 +490,7 @@ static int add_cache_entry(const char *path, unsigned int hash,
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
static struct cache_entry *__lookup_cache_entry(const char *path)
|
||||||
* Find a DFS cache entry in hash table and optionally check prefix path against
|
|
||||||
* @path.
|
|
||||||
* Use whole path components in the match.
|
|
||||||
* Must be called with htable_rw_lock held.
|
|
||||||
*
|
|
||||||
* Return ERR_PTR(-ENOENT) if the entry is not found.
|
|
||||||
*/
|
|
||||||
static struct cache_entry *lookup_cache_entry(const char *path,
|
|
||||||
unsigned int *hash)
|
|
||||||
{
|
{
|
||||||
struct cache_entry *ce;
|
struct cache_entry *ce;
|
||||||
unsigned int h;
|
unsigned int h;
|
||||||
|
@ -517,9 +508,75 @@ static struct cache_entry *lookup_cache_entry(const char *path,
|
||||||
|
|
||||||
if (!found)
|
if (!found)
|
||||||
ce = ERR_PTR(-ENOENT);
|
ce = ERR_PTR(-ENOENT);
|
||||||
|
return ce;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Find a DFS cache entry in hash table and optionally check prefix path against
|
||||||
|
* @path.
|
||||||
|
* Use whole path components in the match.
|
||||||
|
* Must be called with htable_rw_lock held.
|
||||||
|
*
|
||||||
|
* Return ERR_PTR(-ENOENT) if the entry is not found.
|
||||||
|
*/
|
||||||
|
static struct cache_entry *lookup_cache_entry(const char *path, unsigned int *hash)
|
||||||
|
{
|
||||||
|
struct cache_entry *ce = ERR_PTR(-ENOENT);
|
||||||
|
unsigned int h;
|
||||||
|
int cnt = 0;
|
||||||
|
char *npath;
|
||||||
|
char *s, *e;
|
||||||
|
char sep;
|
||||||
|
|
||||||
|
npath = kstrndup(path, strlen(path), GFP_KERNEL);
|
||||||
|
if (!npath)
|
||||||
|
return ERR_PTR(-ENOMEM);
|
||||||
|
|
||||||
|
s = npath;
|
||||||
|
sep = *npath;
|
||||||
|
while ((s = strchr(s, sep)) && ++cnt < 3)
|
||||||
|
s++;
|
||||||
|
|
||||||
|
if (cnt < 3) {
|
||||||
|
h = cache_entry_hash(path, strlen(path));
|
||||||
|
ce = __lookup_cache_entry(path);
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
/*
|
||||||
|
* Handle paths that have more than two path components and are a complete prefix of the DFS
|
||||||
|
* referral request path (@path).
|
||||||
|
*
|
||||||
|
* See MS-DFSC 3.2.5.5 "Receiving a Root Referral Request or Link Referral Request".
|
||||||
|
*/
|
||||||
|
h = cache_entry_hash(npath, strlen(npath));
|
||||||
|
e = npath + strlen(npath) - 1;
|
||||||
|
while (e > s) {
|
||||||
|
char tmp;
|
||||||
|
|
||||||
|
/* skip separators */
|
||||||
|
while (e > s && *e == sep)
|
||||||
|
e--;
|
||||||
|
if (e == s)
|
||||||
|
goto out;
|
||||||
|
|
||||||
|
tmp = *(e+1);
|
||||||
|
*(e+1) = 0;
|
||||||
|
|
||||||
|
ce = __lookup_cache_entry(npath);
|
||||||
|
if (!IS_ERR(ce)) {
|
||||||
|
h = cache_entry_hash(npath, strlen(npath));
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
*(e+1) = tmp;
|
||||||
|
/* backward until separator */
|
||||||
|
while (e > s && *e != sep)
|
||||||
|
e--;
|
||||||
|
}
|
||||||
|
out:
|
||||||
if (hash)
|
if (hash)
|
||||||
*hash = h;
|
*hash = h;
|
||||||
|
kfree(npath);
|
||||||
return ce;
|
return ce;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue
Block a user