Skip to content

Commit

Permalink
CacheFiles: Fix a race in cachefiles_delete_object() vs rename
Browse files Browse the repository at this point in the history
cachefiles_delete_object() can race with rename.  It gets the parent directory
of the object it's asked to delete, then locks it - but rename may have changed
the object's parent between the get and the completion of the lock.

However, if such a circumstance is detected, we abandon our attempt to delete
the object - since it's no longer in the index key path, it won't be seen
again by lookups of that key.  The assumption is that cachefilesd may have
culled it by renaming it to the graveyard for later destruction.

Signed-off-by: David Howells <dhowells@redhat.com>
Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
  • Loading branch information
David Howells authored and Al Viro committed Feb 20, 2010
1 parent aeaa5cc commit 8f9941a
Showing 1 changed file with 11 additions and 1 deletion.
12 changes: 11 additions & 1 deletion fs/cachefiles/namei.c
Original file line number Diff line number Diff line change
Expand Up @@ -348,7 +348,17 @@ int cachefiles_delete_object(struct cachefiles_cache *cache,
dir = dget_parent(object->dentry);

mutex_lock_nested(&dir->d_inode->i_mutex, I_MUTEX_PARENT);
ret = cachefiles_bury_object(cache, dir, object->dentry);

/* we need to check that our parent is _still_ our parent - it may have
* been renamed */
if (dir == object->dentry->d_parent) {
ret = cachefiles_bury_object(cache, dir, object->dentry);
} else {
/* it got moved, presumably by cachefilesd culling it, so it's
* no longer in the key path and we can ignore it */
mutex_unlock(&dir->d_inode->i_mutex);
ret = 0;
}

dput(dir);
_leave(" = %d", ret);
Expand Down

0 comments on commit 8f9941a

Please sign in to comment.