namecache: fix for numlinks on remove
nfs41_name_cache_remove() needs to update the 'numlinks' attribute for other links, even if the file being removed is not found in the cache. to search for its attr cache entry, nfs41_name_cache_remove() now requires a fileid argument. nfs41_remove() only gets a pointer to the parent's filehandle, so it also needs the target fileid argument Signed-off-by: Casey Bodley <cbodley@citi.umich.edu>
This commit is contained in:
parent
06b025a89c
commit
f988c89bf4
7 changed files with 29 additions and 12 deletions
|
|
@ -1041,9 +1041,11 @@ int nfs41_name_cache_remove(
|
|||
IN struct nfs41_name_cache *cache,
|
||||
IN const char *path,
|
||||
IN const nfs41_component *name,
|
||||
IN uint64_t fileid,
|
||||
IN const change_info4 *cinfo)
|
||||
{
|
||||
struct name_cache_entry *parent, *target;
|
||||
struct attr_cache_entry *attributes = NULL;
|
||||
int status;
|
||||
|
||||
dprintf(NCLVL1, "--> nfs41_name_cache_remove('%s')\n", path);
|
||||
|
|
@ -1058,15 +1060,15 @@ int nfs41_name_cache_remove(
|
|||
status = name_cache_lookup(cache, 0, path,
|
||||
name->name + name->len, NULL, &parent, &target, NULL);
|
||||
if (status == ERROR_PATH_NOT_FOUND)
|
||||
goto out_unlock;
|
||||
goto out_attributes;
|
||||
|
||||
if (cinfo && name_cache_entry_changed(cache, parent, cinfo)) {
|
||||
name_cache_entry_invalidate(cache, parent);
|
||||
goto out_unlock;
|
||||
goto out_attributes;
|
||||
}
|
||||
|
||||
if (status == ERROR_FILE_NOT_FOUND)
|
||||
goto out_unlock;
|
||||
goto out_attributes;
|
||||
|
||||
if (target->attributes)
|
||||
target->attributes->numlinks--;
|
||||
|
|
@ -1080,6 +1082,14 @@ out_unlock:
|
|||
|
||||
dprintf(NCLVL1, "<-- nfs41_name_cache_remove() returning %d\n", status);
|
||||
return status;
|
||||
|
||||
out_attributes:
|
||||
/* in the presence of other links, we need to update numlinks
|
||||
* regardless of a failure to find the target entry */
|
||||
attributes = attr_cache_search(&cache->attributes, fileid);
|
||||
if (attributes)
|
||||
attributes->numlinks--;
|
||||
goto out_unlock;
|
||||
}
|
||||
|
||||
int nfs41_name_cache_rename(
|
||||
|
|
|
|||
|
|
@ -91,6 +91,7 @@ int nfs41_name_cache_remove(
|
|||
IN struct nfs41_name_cache *cache,
|
||||
IN const char *path,
|
||||
IN const nfs41_component *name,
|
||||
IN uint64_t fileid,
|
||||
IN const change_info4 *cinfo);
|
||||
|
||||
int nfs41_name_cache_rename(
|
||||
|
|
|
|||
|
|
@ -1140,7 +1140,8 @@ out:
|
|||
int nfs41_remove(
|
||||
IN nfs41_session *session,
|
||||
IN nfs41_path_fh *parent,
|
||||
IN const nfs41_component *target)
|
||||
IN const nfs41_component *target,
|
||||
IN uint64_t fileid)
|
||||
{
|
||||
int status;
|
||||
nfs41_compound compound;
|
||||
|
|
@ -1194,7 +1195,7 @@ int nfs41_remove(
|
|||
/* remove the target file from the cache */
|
||||
AcquireSRWLockShared(&parent->path->lock);
|
||||
nfs41_name_cache_remove(session_name_cache(session),
|
||||
parent->path->path, target, &remove_res.cinfo);
|
||||
parent->path->path, target, fileid, &remove_res.cinfo);
|
||||
ReleaseSRWLockShared(&parent->path->lock);
|
||||
|
||||
nfs41_superblock_space_changed(parent->fh.superblock);
|
||||
|
|
|
|||
|
|
@ -1147,7 +1147,8 @@ int nfs41_cached_getattr(
|
|||
int nfs41_remove(
|
||||
IN nfs41_session *session,
|
||||
IN nfs41_path_fh *parent,
|
||||
IN const nfs41_component *target);
|
||||
IN const nfs41_component *target,
|
||||
IN uint64_t fileid);
|
||||
|
||||
int nfs41_rename(
|
||||
IN nfs41_session *session,
|
||||
|
|
|
|||
|
|
@ -676,7 +676,8 @@ static void cancel_open(IN nfs41_upcall *upcall)
|
|||
/* break any delegations and truncate before REMOVE */
|
||||
nfs41_delegation_return(state->session, &state->file,
|
||||
OPEN_DELEGATE_WRITE, TRUE);
|
||||
status = nfs41_remove(state->session, &state->parent, name);
|
||||
status = nfs41_remove(state->session, &state->parent,
|
||||
name, state->file.fh.fileid);
|
||||
if (status)
|
||||
dprintf(1, "cancel_open: nfs41_remove() failed with %s\n",
|
||||
nfs_error_string(status));
|
||||
|
|
@ -735,7 +736,8 @@ static int handle_close(nfs41_upcall *upcall)
|
|||
OPEN_DELEGATE_WRITE, TRUE);
|
||||
|
||||
dprintf(1, "calling nfs41_remove for %s\n", name->name);
|
||||
rm_status = nfs41_remove(state->session, &state->parent, name);
|
||||
rm_status = nfs41_remove(state->session, &state->parent,
|
||||
name, state->file.fh.fileid);
|
||||
if (rm_status) {
|
||||
dprintf(1, "nfs41_remove() failed with error %s.\n",
|
||||
nfs_error_string(rm_status));
|
||||
|
|
|
|||
|
|
@ -141,7 +141,7 @@ static int handle_nfs41_remove(setattr_upcall_args *args)
|
|||
OPEN_DELEGATE_WRITE, TRUE);
|
||||
|
||||
status = nfs41_remove(state->session, &state->parent,
|
||||
&state->file.name);
|
||||
&state->file.name, state->file.fh.fileid);
|
||||
if (status)
|
||||
dprintf(1, "nfs41_remove() failed with error %s.\n",
|
||||
nfs_error_string(status));
|
||||
|
|
@ -401,7 +401,7 @@ static int handle_nfs41_link(setattr_upcall_args *args)
|
|||
|
||||
/* redo the lookup until it doesn't return REPARSE */
|
||||
status = nfs41_lookup(args->root, dst_session,
|
||||
&dst_path, &dst_dir, NULL, NULL, &dst_session);
|
||||
&dst_path, &dst_dir, &dst, NULL, &dst_session);
|
||||
}
|
||||
|
||||
/* get the components after lookup in case a referral changed its path */
|
||||
|
|
@ -434,7 +434,8 @@ static int handle_nfs41_link(setattr_upcall_args *args)
|
|||
|
||||
/* LINK will return NFS4ERR_EXIST if the target file exists,
|
||||
* so we have to remove it ourselves */
|
||||
status = nfs41_remove(state->session, &dst_dir, &dst_name);
|
||||
status = nfs41_remove(state->session,
|
||||
&dst_dir, &dst_name, dst.fh.fileid);
|
||||
if (status) {
|
||||
dprintf(1, "nfs41_remove() failed with error %s.\n",
|
||||
nfs_error_string(status));
|
||||
|
|
|
|||
|
|
@ -240,7 +240,8 @@ static int handle_symlink(nfs41_upcall *upcall)
|
|||
eprintf("handle_symlink: attempting to create a symlink when "
|
||||
"the file=%s was already created on open; sending REMOVE "
|
||||
"first\n", state->file.path->path);
|
||||
nfs41_remove(state->session, &state->parent, &state->file.name);
|
||||
nfs41_remove(state->session, &state->parent,
|
||||
&state->file.name, state->file.fh.fileid);
|
||||
}
|
||||
|
||||
/* create the symlink */
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue