namecache: fix for negative entries on rename
this addresses two error cases: 1) when the src entry is negative or does not exist: the dst entry could be negative or point to something else, so it needs to be removed 2) when the dst_parent entry is negative or does not exist: src needs to be made a negative entry Signed-off-by: Casey Bodley <cbodley@citi.umich.edu>
This commit is contained in:
parent
68252b6522
commit
7f82baf13f
1 changed files with 21 additions and 8 deletions
|
|
@ -1115,18 +1115,31 @@ int nfs41_name_cache_rename(
|
||||||
goto out_unlock;
|
goto out_unlock;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* look up dst_parent */
|
||||||
|
status = name_cache_lookup(cache, 0, dst_path,
|
||||||
|
dst_name->name, NULL, NULL, &dst_parent, NULL);
|
||||||
|
/* we can't create the dst entry without a parent */
|
||||||
|
if (status || dst_parent->attributes == NULL) {
|
||||||
|
/* if src exists, make it negative */
|
||||||
|
status = name_cache_lookup(cache, 0, src_path,
|
||||||
|
src_name->name + src_name->len, NULL, NULL, &src, NULL);
|
||||||
|
if (status == NO_ERROR) {
|
||||||
|
name_cache_entry_update(cache, src, NULL, NULL, OPEN_DELEGATE_NONE);
|
||||||
|
name_cache_unlink_children_recursive(cache, src);
|
||||||
|
}
|
||||||
|
status = ERROR_PATH_NOT_FOUND;
|
||||||
|
goto out_unlock;
|
||||||
|
}
|
||||||
|
|
||||||
/* look up src_parent and src */
|
/* 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, &src, NULL);
|
src_name->name + src_name->len, NULL, &src_parent, &src, NULL);
|
||||||
/* we can't create the dst entry without valid attributes */
|
/* we can't create the dst entry without valid attributes */
|
||||||
if (status || src->attributes == NULL)
|
if (status || src->attributes == NULL) {
|
||||||
goto out_unlock;
|
/* remove dst if it exists */
|
||||||
|
struct name_cache_entry *dst;
|
||||||
/* look up dst_parent */
|
dst = name_cache_search(cache, dst_parent, dst_name);
|
||||||
status = name_cache_lookup(cache, 0, dst_path,
|
if (dst) name_cache_unlink(cache, dst);
|
||||||
dst_name->name, NULL, NULL, &dst_parent, NULL);
|
|
||||||
if (status) {
|
|
||||||
status = ERROR_PATH_NOT_FOUND;
|
|
||||||
goto out_unlock;
|
goto out_unlock;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue