name cache: rename leaves behind a negative entry
as before, we move the src entry from src_parent to dst_parent. but instead of unlinking the destination entry if it exists, we recycle it as a negative entry where src used to be. if the destination entry doesn't exist, we create a new one for this negative entry if the dst_parent entry is invalidated by the change_info, we just leave the original src entry in place and make it negative Signed-off-by: Casey Bodley <cbodley@umich.edu>
This commit is contained in:
parent
bc81c3f6f5
commit
765bc0284b
1 changed files with 44 additions and 32 deletions
|
|
@ -708,27 +708,6 @@ out_err:
|
||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void name_cache_rename(
|
|
||||||
IN struct nfs41_name_cache *cache,
|
|
||||||
IN struct name_cache_entry *src_dir,
|
|
||||||
IN struct name_cache_entry *src,
|
|
||||||
IN struct name_cache_entry *dst_dir,
|
|
||||||
IN const nfs41_component *component,
|
|
||||||
OUT struct name_cache_entry **dst_out)
|
|
||||||
{
|
|
||||||
struct name_cache_entry *existing;
|
|
||||||
|
|
||||||
name_cache_remove(src, src_dir);
|
|
||||||
|
|
||||||
name_cache_entry_rename(src, component);
|
|
||||||
|
|
||||||
existing = name_cache_search(cache, dst_dir, component);
|
|
||||||
if (existing)
|
|
||||||
name_cache_unlink(cache, existing);
|
|
||||||
|
|
||||||
name_cache_insert(src, dst_dir);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/* public name cache interface, declared in name_cache.h */
|
/* public name cache interface, declared in name_cache.h */
|
||||||
|
|
||||||
|
|
@ -1020,7 +999,7 @@ int nfs41_name_cache_rename(
|
||||||
IN const nfs41_component *dst_name,
|
IN const nfs41_component *dst_name,
|
||||||
IN const change_info4 *dst_cinfo)
|
IN const change_info4 *dst_cinfo)
|
||||||
{
|
{
|
||||||
struct name_cache_entry *src_parent, *target;
|
struct name_cache_entry *src_parent, *src;
|
||||||
struct name_cache_entry *dst_parent;
|
struct name_cache_entry *dst_parent;
|
||||||
int status = NO_ERROR;
|
int status = NO_ERROR;
|
||||||
|
|
||||||
|
|
@ -1034,13 +1013,14 @@ int nfs41_name_cache_rename(
|
||||||
goto out_unlock;
|
goto out_unlock;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* get src_parent and target */
|
/* look up src_parent and src */
|
||||||
status = name_cache_lookup(cache, 0, src_path,
|
status = name_cache_lookup(cache, 0, src_path,
|
||||||
src_name->name + src_name->len, NULL, &src_parent, &target, NULL);
|
src_name->name + src_name->len, NULL, &src_parent, &src, NULL);
|
||||||
if (status)
|
/* we can't create the dst entry without valid attributes */
|
||||||
|
if (status || src->attributes == NULL)
|
||||||
goto out_unlock;
|
goto out_unlock;
|
||||||
|
|
||||||
/* get dst_parent */
|
/* look up dst_parent */
|
||||||
status = name_cache_lookup(cache, 0, dst_path,
|
status = name_cache_lookup(cache, 0, dst_path,
|
||||||
dst_name->name, NULL, NULL, &dst_parent, NULL);
|
dst_name->name, NULL, NULL, &dst_parent, NULL);
|
||||||
if (status) {
|
if (status) {
|
||||||
|
|
@ -1049,15 +1029,47 @@ int nfs41_name_cache_rename(
|
||||||
}
|
}
|
||||||
|
|
||||||
if (name_cache_entry_changed(cache, dst_parent, dst_cinfo)) {
|
if (name_cache_entry_changed(cache, dst_parent, dst_cinfo)) {
|
||||||
name_cache_unlink(cache, target);
|
|
||||||
name_cache_entry_invalidate(cache, dst_parent);
|
name_cache_entry_invalidate(cache, dst_parent);
|
||||||
} else
|
/* if dst_parent and src_parent are both gone,
|
||||||
name_cache_rename(cache, src_parent, target,
|
* we no longer have an entry to rename */
|
||||||
dst_parent, dst_name, &target);
|
if (dst_parent == src_parent)
|
||||||
|
goto out_unlock;
|
||||||
|
} else {
|
||||||
|
struct name_cache_entry *existing;
|
||||||
|
existing = name_cache_search(cache, dst_parent, dst_name);
|
||||||
|
if (existing) {
|
||||||
|
/* remove the existing entry, but don't unlink it yet;
|
||||||
|
* we may reuse it for a negative entry */
|
||||||
|
name_cache_remove(existing, dst_parent);
|
||||||
|
}
|
||||||
|
|
||||||
if (dst_parent != src_parent
|
/* move the src entry under dst_parent */
|
||||||
&& name_cache_entry_changed(cache, src_parent, src_cinfo))
|
name_cache_remove(src, src_parent);
|
||||||
|
name_cache_entry_rename(src, dst_name);
|
||||||
|
name_cache_insert(src, dst_parent);
|
||||||
|
|
||||||
|
if (existing) {
|
||||||
|
/* recycle 'existing' as the negative entry 'src' */
|
||||||
|
name_cache_entry_rename(existing, src_name);
|
||||||
|
name_cache_insert(existing, src_parent);
|
||||||
|
}
|
||||||
|
src = existing;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (name_cache_entry_changed(cache, src_parent, src_cinfo)) {
|
||||||
name_cache_entry_invalidate(cache, src_parent);
|
name_cache_entry_invalidate(cache, src_parent);
|
||||||
|
goto out_unlock;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* leave a negative entry where the file used to be */
|
||||||
|
if (src == NULL) {
|
||||||
|
/* src was moved, create a new entry in its place */
|
||||||
|
status = name_cache_find_or_create(cache, src_parent, src_name, &src);
|
||||||
|
if (status)
|
||||||
|
goto out_unlock;
|
||||||
|
}
|
||||||
|
name_cache_entry_update(cache, src, NULL, NULL);
|
||||||
|
name_cache_unlink_children_recursive(cache, src);
|
||||||
|
|
||||||
out_unlock:
|
out_unlock:
|
||||||
ReleaseSRWLockExclusive(&cache->lock);
|
ReleaseSRWLockExclusive(&cache->lock);
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue