VFS: Cachefiles should perform fs modifications on the top layer only
Cachefiles should perform fs modifications (eg. vfs_unlink()) on the top layer only and should not attempt to alter the lower layer. Signed-off-by: David Howells <dhowells@redhat.com> Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
This commit is contained in:
parent
ee8ac4d61c
commit
5153bc817c
|
@ -446,7 +446,7 @@ static int cachefiles_attr_changed(struct fscache_object *_object)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
cachefiles_begin_secure(cache, &saved_cred);
|
cachefiles_begin_secure(cache, &saved_cred);
|
||||||
mutex_lock(&object->backer->d_inode->i_mutex);
|
mutex_lock(&d_inode(object->backer)->i_mutex);
|
||||||
|
|
||||||
/* if there's an extension to a partial page at the end of the backing
|
/* if there's an extension to a partial page at the end of the backing
|
||||||
* file, we need to discard the partial page so that we pick up new
|
* file, we need to discard the partial page so that we pick up new
|
||||||
|
@ -465,7 +465,7 @@ static int cachefiles_attr_changed(struct fscache_object *_object)
|
||||||
ret = notify_change(object->backer, &newattrs, NULL);
|
ret = notify_change(object->backer, &newattrs, NULL);
|
||||||
|
|
||||||
truncate_failed:
|
truncate_failed:
|
||||||
mutex_unlock(&object->backer->d_inode->i_mutex);
|
mutex_unlock(&d_inode(object->backer)->i_mutex);
|
||||||
cachefiles_end_secure(cache, saved_cred);
|
cachefiles_end_secure(cache, saved_cred);
|
||||||
|
|
||||||
if (ret == -EIO) {
|
if (ret == -EIO) {
|
||||||
|
|
|
@ -286,13 +286,13 @@ static int cachefiles_bury_object(struct cachefiles_cache *cache,
|
||||||
if (ret < 0) {
|
if (ret < 0) {
|
||||||
cachefiles_io_error(cache, "Unlink security error");
|
cachefiles_io_error(cache, "Unlink security error");
|
||||||
} else {
|
} else {
|
||||||
ret = vfs_unlink(dir->d_inode, rep, NULL);
|
ret = vfs_unlink(d_inode(dir), rep, NULL);
|
||||||
|
|
||||||
if (preemptive)
|
if (preemptive)
|
||||||
cachefiles_mark_object_buried(cache, rep);
|
cachefiles_mark_object_buried(cache, rep);
|
||||||
}
|
}
|
||||||
|
|
||||||
mutex_unlock(&dir->d_inode->i_mutex);
|
mutex_unlock(&d_inode(dir)->i_mutex);
|
||||||
|
|
||||||
if (ret == -EIO)
|
if (ret == -EIO)
|
||||||
cachefiles_io_error(cache, "Unlink failed");
|
cachefiles_io_error(cache, "Unlink failed");
|
||||||
|
@ -303,7 +303,7 @@ static int cachefiles_bury_object(struct cachefiles_cache *cache,
|
||||||
|
|
||||||
/* directories have to be moved to the graveyard */
|
/* directories have to be moved to the graveyard */
|
||||||
_debug("move stale object to graveyard");
|
_debug("move stale object to graveyard");
|
||||||
mutex_unlock(&dir->d_inode->i_mutex);
|
mutex_unlock(&d_inode(dir)->i_mutex);
|
||||||
|
|
||||||
try_again:
|
try_again:
|
||||||
/* first step is to make up a grave dentry in the graveyard */
|
/* first step is to make up a grave dentry in the graveyard */
|
||||||
|
@ -387,8 +387,8 @@ try_again:
|
||||||
if (ret < 0) {
|
if (ret < 0) {
|
||||||
cachefiles_io_error(cache, "Rename security error %d", ret);
|
cachefiles_io_error(cache, "Rename security error %d", ret);
|
||||||
} else {
|
} else {
|
||||||
ret = vfs_rename(dir->d_inode, rep,
|
ret = vfs_rename(d_inode(dir), rep,
|
||||||
cache->graveyard->d_inode, grave, NULL, 0);
|
d_inode(cache->graveyard), grave, NULL, 0);
|
||||||
if (ret != 0 && ret != -ENOMEM)
|
if (ret != 0 && ret != -ENOMEM)
|
||||||
cachefiles_io_error(cache,
|
cachefiles_io_error(cache,
|
||||||
"Rename failed with error %d", ret);
|
"Rename failed with error %d", ret);
|
||||||
|
@ -420,13 +420,13 @@ int cachefiles_delete_object(struct cachefiles_cache *cache,
|
||||||
|
|
||||||
dir = dget_parent(object->dentry);
|
dir = dget_parent(object->dentry);
|
||||||
|
|
||||||
mutex_lock_nested(&dir->d_inode->i_mutex, I_MUTEX_PARENT);
|
mutex_lock_nested(&d_inode(dir)->i_mutex, I_MUTEX_PARENT);
|
||||||
|
|
||||||
if (test_bit(CACHEFILES_OBJECT_BURIED, &object->flags)) {
|
if (test_bit(CACHEFILES_OBJECT_BURIED, &object->flags)) {
|
||||||
/* object allocation for the same key preemptively deleted this
|
/* object allocation for the same key preemptively deleted this
|
||||||
* object's file so that it could create its own file */
|
* object's file so that it could create its own file */
|
||||||
_debug("object preemptively buried");
|
_debug("object preemptively buried");
|
||||||
mutex_unlock(&dir->d_inode->i_mutex);
|
mutex_unlock(&d_inode(dir)->i_mutex);
|
||||||
ret = 0;
|
ret = 0;
|
||||||
} else {
|
} else {
|
||||||
/* we need to check that our parent is _still_ our parent - it
|
/* we need to check that our parent is _still_ our parent - it
|
||||||
|
@ -438,7 +438,7 @@ int cachefiles_delete_object(struct cachefiles_cache *cache,
|
||||||
/* it got moved, presumably by cachefilesd culling it,
|
/* it got moved, presumably by cachefilesd culling it,
|
||||||
* so it's no longer in the key path and we can ignore
|
* so it's no longer in the key path and we can ignore
|
||||||
* it */
|
* it */
|
||||||
mutex_unlock(&dir->d_inode->i_mutex);
|
mutex_unlock(&d_inode(dir)->i_mutex);
|
||||||
ret = 0;
|
ret = 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -497,7 +497,7 @@ lookup_again:
|
||||||
/* search the current directory for the element name */
|
/* search the current directory for the element name */
|
||||||
_debug("lookup '%s'", name);
|
_debug("lookup '%s'", name);
|
||||||
|
|
||||||
mutex_lock_nested(&dir->d_inode->i_mutex, I_MUTEX_PARENT);
|
mutex_lock_nested(&d_inode(dir)->i_mutex, I_MUTEX_PARENT);
|
||||||
|
|
||||||
start = jiffies;
|
start = jiffies;
|
||||||
next = lookup_one_len(name, dir, nlen);
|
next = lookup_one_len(name, dir, nlen);
|
||||||
|
@ -529,7 +529,7 @@ lookup_again:
|
||||||
if (ret < 0)
|
if (ret < 0)
|
||||||
goto create_error;
|
goto create_error;
|
||||||
start = jiffies;
|
start = jiffies;
|
||||||
ret = vfs_mkdir(dir->d_inode, next, 0);
|
ret = vfs_mkdir(d_inode(dir), next, 0);
|
||||||
cachefiles_hist(cachefiles_mkdir_histogram, start);
|
cachefiles_hist(cachefiles_mkdir_histogram, start);
|
||||||
if (ret < 0)
|
if (ret < 0)
|
||||||
goto create_error;
|
goto create_error;
|
||||||
|
@ -558,7 +558,7 @@ lookup_again:
|
||||||
if (ret < 0)
|
if (ret < 0)
|
||||||
goto create_error;
|
goto create_error;
|
||||||
start = jiffies;
|
start = jiffies;
|
||||||
ret = vfs_create(dir->d_inode, next, S_IFREG, true);
|
ret = vfs_create(d_inode(dir), next, S_IFREG, true);
|
||||||
cachefiles_hist(cachefiles_create_histogram, start);
|
cachefiles_hist(cachefiles_create_histogram, start);
|
||||||
if (ret < 0)
|
if (ret < 0)
|
||||||
goto create_error;
|
goto create_error;
|
||||||
|
@ -581,7 +581,7 @@ lookup_again:
|
||||||
/* process the next component */
|
/* process the next component */
|
||||||
if (key) {
|
if (key) {
|
||||||
_debug("advance");
|
_debug("advance");
|
||||||
mutex_unlock(&dir->d_inode->i_mutex);
|
mutex_unlock(&d_inode(dir)->i_mutex);
|
||||||
dput(dir);
|
dput(dir);
|
||||||
dir = next;
|
dir = next;
|
||||||
next = NULL;
|
next = NULL;
|
||||||
|
@ -617,7 +617,7 @@ lookup_again:
|
||||||
/* note that we're now using this object */
|
/* note that we're now using this object */
|
||||||
ret = cachefiles_mark_object_active(cache, object);
|
ret = cachefiles_mark_object_active(cache, object);
|
||||||
|
|
||||||
mutex_unlock(&dir->d_inode->i_mutex);
|
mutex_unlock(&d_inode(dir)->i_mutex);
|
||||||
dput(dir);
|
dput(dir);
|
||||||
dir = NULL;
|
dir = NULL;
|
||||||
|
|
||||||
|
@ -695,7 +695,7 @@ lookup_error:
|
||||||
cachefiles_io_error(cache, "Lookup failed");
|
cachefiles_io_error(cache, "Lookup failed");
|
||||||
next = NULL;
|
next = NULL;
|
||||||
error:
|
error:
|
||||||
mutex_unlock(&dir->d_inode->i_mutex);
|
mutex_unlock(&d_inode(dir)->i_mutex);
|
||||||
dput(next);
|
dput(next);
|
||||||
error_out2:
|
error_out2:
|
||||||
dput(dir);
|
dput(dir);
|
||||||
|
@ -719,7 +719,7 @@ struct dentry *cachefiles_get_directory(struct cachefiles_cache *cache,
|
||||||
_enter(",,%s", dirname);
|
_enter(",,%s", dirname);
|
||||||
|
|
||||||
/* search the current directory for the element name */
|
/* search the current directory for the element name */
|
||||||
mutex_lock(&dir->d_inode->i_mutex);
|
mutex_lock(&d_inode(dir)->i_mutex);
|
||||||
|
|
||||||
start = jiffies;
|
start = jiffies;
|
||||||
subdir = lookup_one_len(dirname, dir, strlen(dirname));
|
subdir = lookup_one_len(dirname, dir, strlen(dirname));
|
||||||
|
@ -746,7 +746,7 @@ struct dentry *cachefiles_get_directory(struct cachefiles_cache *cache,
|
||||||
ret = security_path_mkdir(&path, subdir, 0700);
|
ret = security_path_mkdir(&path, subdir, 0700);
|
||||||
if (ret < 0)
|
if (ret < 0)
|
||||||
goto mkdir_error;
|
goto mkdir_error;
|
||||||
ret = vfs_mkdir(dir->d_inode, subdir, 0700);
|
ret = vfs_mkdir(d_inode(dir), subdir, 0700);
|
||||||
if (ret < 0)
|
if (ret < 0)
|
||||||
goto mkdir_error;
|
goto mkdir_error;
|
||||||
|
|
||||||
|
@ -758,7 +758,7 @@ struct dentry *cachefiles_get_directory(struct cachefiles_cache *cache,
|
||||||
subdir->d_inode->i_ino);
|
subdir->d_inode->i_ino);
|
||||||
}
|
}
|
||||||
|
|
||||||
mutex_unlock(&dir->d_inode->i_mutex);
|
mutex_unlock(&d_inode(dir)->i_mutex);
|
||||||
|
|
||||||
/* we need to make sure the subdir is a directory */
|
/* we need to make sure the subdir is a directory */
|
||||||
ASSERT(subdir->d_inode);
|
ASSERT(subdir->d_inode);
|
||||||
|
@ -790,19 +790,19 @@ check_error:
|
||||||
return ERR_PTR(ret);
|
return ERR_PTR(ret);
|
||||||
|
|
||||||
mkdir_error:
|
mkdir_error:
|
||||||
mutex_unlock(&dir->d_inode->i_mutex);
|
mutex_unlock(&d_inode(dir)->i_mutex);
|
||||||
dput(subdir);
|
dput(subdir);
|
||||||
pr_err("mkdir %s failed with error %d\n", dirname, ret);
|
pr_err("mkdir %s failed with error %d\n", dirname, ret);
|
||||||
return ERR_PTR(ret);
|
return ERR_PTR(ret);
|
||||||
|
|
||||||
lookup_error:
|
lookup_error:
|
||||||
mutex_unlock(&dir->d_inode->i_mutex);
|
mutex_unlock(&d_inode(dir)->i_mutex);
|
||||||
ret = PTR_ERR(subdir);
|
ret = PTR_ERR(subdir);
|
||||||
pr_err("Lookup %s failed with error %d\n", dirname, ret);
|
pr_err("Lookup %s failed with error %d\n", dirname, ret);
|
||||||
return ERR_PTR(ret);
|
return ERR_PTR(ret);
|
||||||
|
|
||||||
nomem_d_alloc:
|
nomem_d_alloc:
|
||||||
mutex_unlock(&dir->d_inode->i_mutex);
|
mutex_unlock(&d_inode(dir)->i_mutex);
|
||||||
_leave(" = -ENOMEM");
|
_leave(" = -ENOMEM");
|
||||||
return ERR_PTR(-ENOMEM);
|
return ERR_PTR(-ENOMEM);
|
||||||
}
|
}
|
||||||
|
@ -827,7 +827,7 @@ static struct dentry *cachefiles_check_active(struct cachefiles_cache *cache,
|
||||||
// dir, filename);
|
// dir, filename);
|
||||||
|
|
||||||
/* look up the victim */
|
/* look up the victim */
|
||||||
mutex_lock_nested(&dir->d_inode->i_mutex, I_MUTEX_PARENT);
|
mutex_lock_nested(&d_inode(dir)->i_mutex, I_MUTEX_PARENT);
|
||||||
|
|
||||||
start = jiffies;
|
start = jiffies;
|
||||||
victim = lookup_one_len(filename, dir, strlen(filename));
|
victim = lookup_one_len(filename, dir, strlen(filename));
|
||||||
|
@ -842,7 +842,7 @@ static struct dentry *cachefiles_check_active(struct cachefiles_cache *cache,
|
||||||
* at the netfs's request whilst the cull was in progress
|
* at the netfs's request whilst the cull was in progress
|
||||||
*/
|
*/
|
||||||
if (!victim->d_inode) {
|
if (!victim->d_inode) {
|
||||||
mutex_unlock(&dir->d_inode->i_mutex);
|
mutex_unlock(&d_inode(dir)->i_mutex);
|
||||||
dput(victim);
|
dput(victim);
|
||||||
_leave(" = -ENOENT [absent]");
|
_leave(" = -ENOENT [absent]");
|
||||||
return ERR_PTR(-ENOENT);
|
return ERR_PTR(-ENOENT);
|
||||||
|
@ -871,13 +871,13 @@ static struct dentry *cachefiles_check_active(struct cachefiles_cache *cache,
|
||||||
|
|
||||||
object_in_use:
|
object_in_use:
|
||||||
read_unlock(&cache->active_lock);
|
read_unlock(&cache->active_lock);
|
||||||
mutex_unlock(&dir->d_inode->i_mutex);
|
mutex_unlock(&d_inode(dir)->i_mutex);
|
||||||
dput(victim);
|
dput(victim);
|
||||||
//_leave(" = -EBUSY [in use]");
|
//_leave(" = -EBUSY [in use]");
|
||||||
return ERR_PTR(-EBUSY);
|
return ERR_PTR(-EBUSY);
|
||||||
|
|
||||||
lookup_error:
|
lookup_error:
|
||||||
mutex_unlock(&dir->d_inode->i_mutex);
|
mutex_unlock(&d_inode(dir)->i_mutex);
|
||||||
ret = PTR_ERR(victim);
|
ret = PTR_ERR(victim);
|
||||||
if (ret == -ENOENT) {
|
if (ret == -ENOENT) {
|
||||||
/* file or dir now absent - probably retired by netfs */
|
/* file or dir now absent - probably retired by netfs */
|
||||||
|
@ -936,7 +936,7 @@ int cachefiles_cull(struct cachefiles_cache *cache, struct dentry *dir,
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
error_unlock:
|
error_unlock:
|
||||||
mutex_unlock(&dir->d_inode->i_mutex);
|
mutex_unlock(&d_inode(dir)->i_mutex);
|
||||||
error:
|
error:
|
||||||
dput(victim);
|
dput(victim);
|
||||||
if (ret == -ENOENT) {
|
if (ret == -ENOENT) {
|
||||||
|
@ -971,7 +971,7 @@ int cachefiles_check_in_use(struct cachefiles_cache *cache, struct dentry *dir,
|
||||||
if (IS_ERR(victim))
|
if (IS_ERR(victim))
|
||||||
return PTR_ERR(victim);
|
return PTR_ERR(victim);
|
||||||
|
|
||||||
mutex_unlock(&dir->d_inode->i_mutex);
|
mutex_unlock(&d_inode(dir)->i_mutex);
|
||||||
dput(victim);
|
dput(victim);
|
||||||
//_leave(" = 0");
|
//_leave(" = 0");
|
||||||
return 0;
|
return 0;
|
||||||
|
|
Loading…
Reference in New Issue