From: David Howells Date: Fri, 19 Feb 2010 18:14:21 +0000 (+0000) Subject: CacheFiles: Fix a race in cachefiles_delete_object() vs rename X-Git-Tag: v2.6.33~22^2 X-Git-Url: http://ftp.safe.ca/?a=commitdiff_plain;h=8f9941aeccc318f243ab3fa55aaa17f4c1cb33f9;p=safe%2Fjmp%2Flinux-2.6 CacheFiles: Fix a race in cachefiles_delete_object() vs rename 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 Signed-off-by: Al Viro --- diff --git a/fs/cachefiles/namei.c b/fs/cachefiles/namei.c index 14ac480..eeb4986 100644 --- a/fs/cachefiles/namei.c +++ b/fs/cachefiles/namei.c @@ -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);