diff options
Diffstat (limited to 'fs/cachefiles/volume.c')
-rw-r--r-- | fs/cachefiles/volume.c | 25 |
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); } |