summaryrefslogtreecommitdiffstats
path: root/fs/cachefiles/volume.c
diff options
context:
space:
mode:
Diffstat (limited to 'fs/cachefiles/volume.c')
-rw-r--r--fs/cachefiles/volume.c25
1 files changed, 23 insertions, 2 deletions
diff --git a/fs/cachefiles/volume.c b/fs/cachefiles/volume.c
index 4a14f5e72764..89df0ba8ba5e 100644
--- a/fs/cachefiles/volume.c
+++ b/fs/cachefiles/volume.c
@@ -22,7 +22,8 @@ void cachefiles_acquire_volume(struct fscache_volume *vcookie)
struct dentry *vdentry, *fan;
size_t len;
char *name;
- int n_accesses, i;
+ bool is_new = false;
+ int ret, n_accesses, i;
_enter("");
@@ -43,11 +44,29 @@ void cachefiles_acquire_volume(struct fscache_volume *vcookie)
memcpy(name + 1, vcookie->key + 1, len);
name[len + 1] = 0;
- vdentry = cachefiles_get_directory(cache, cache->store, name, NULL);
+retry:
+ vdentry = cachefiles_get_directory(cache, cache->store, name, &is_new);
if (IS_ERR(vdentry))
goto error_name;
volume->dentry = vdentry;
+ if (is_new) {
+ if (!cachefiles_set_volume_xattr(volume))
+ goto error_dir;
+ } else {
+ ret = cachefiles_check_volume_xattr(volume);
+ if (ret < 0) {
+ if (ret != -ESTALE)
+ goto error_dir;
+ inode_lock_nested(d_inode(cache->store), I_MUTEX_PARENT);
+ cachefiles_bury_object(cache, NULL, cache->store, vdentry,
+ FSCACHE_VOLUME_IS_WEIRD);
+ cachefiles_put_directory(volume->dentry);
+ cond_resched();
+ goto retry;
+ }
+ }
+
for (i = 0; i < 256; i++) {
sprintf(name, "@%02x", i);
fan = cachefiles_get_directory(cache, vdentry, name, NULL);
@@ -74,6 +93,7 @@ void cachefiles_acquire_volume(struct fscache_volume *vcookie)
error_fan:
for (i = 0; i < 256; i++)
cachefiles_put_directory(volume->fanout[i]);
+error_dir:
cachefiles_put_directory(volume->dentry);
error_name:
kfree(name);
@@ -114,5 +134,6 @@ void cachefiles_free_volume(struct fscache_volume *vcookie)
void cachefiles_withdraw_volume(struct cachefiles_volume *volume)
{
fscache_withdraw_volume(volume->vcookie);
+ cachefiles_set_volume_xattr(volume);
__cachefiles_free_volume(volume);
}