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:
Casey Bodley 2011-11-04 10:17:17 -04:00 committed by unknown
parent 06b025a89c
commit f988c89bf4
7 changed files with 29 additions and 12 deletions

View file

@ -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(

View file

@ -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(

View file

@ -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);

View file

@ -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,

View file

@ -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));

View file

@ -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));

View file

@ -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 */