Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0-or-later
0002 /* Volume handling.
0003  *
0004  * Copyright (C) 2021 Red Hat, Inc. All Rights Reserved.
0005  * Written by David Howells (dhowells@redhat.com)
0006  */
0007 
0008 #include <linux/fs.h>
0009 #include <linux/slab.h>
0010 #include "internal.h"
0011 #include <trace/events/fscache.h>
0012 
0013 /*
0014  * Allocate and set up a volume representation.  We make sure all the fanout
0015  * directories are created and pinned.
0016  */
0017 void cachefiles_acquire_volume(struct fscache_volume *vcookie)
0018 {
0019     struct cachefiles_volume *volume;
0020     struct cachefiles_cache *cache = vcookie->cache->cache_priv;
0021     const struct cred *saved_cred;
0022     struct dentry *vdentry, *fan;
0023     size_t len;
0024     char *name;
0025     bool is_new = false;
0026     int ret, n_accesses, i;
0027 
0028     _enter("");
0029 
0030     volume = kzalloc(sizeof(struct cachefiles_volume), GFP_KERNEL);
0031     if (!volume)
0032         return;
0033     volume->vcookie = vcookie;
0034     volume->cache = cache;
0035     INIT_LIST_HEAD(&volume->cache_link);
0036 
0037     cachefiles_begin_secure(cache, &saved_cred);
0038 
0039     len = vcookie->key[0];
0040     name = kmalloc(len + 3, GFP_NOFS);
0041     if (!name)
0042         goto error_vol;
0043     name[0] = 'I';
0044     memcpy(name + 1, vcookie->key + 1, len);
0045     name[len + 1] = 0;
0046 
0047 retry:
0048     vdentry = cachefiles_get_directory(cache, cache->store, name, &is_new);
0049     if (IS_ERR(vdentry))
0050         goto error_name;
0051     volume->dentry = vdentry;
0052 
0053     if (is_new) {
0054         if (!cachefiles_set_volume_xattr(volume))
0055             goto error_dir;
0056     } else {
0057         ret = cachefiles_check_volume_xattr(volume);
0058         if (ret < 0) {
0059             if (ret != -ESTALE)
0060                 goto error_dir;
0061             inode_lock_nested(d_inode(cache->store), I_MUTEX_PARENT);
0062             cachefiles_bury_object(cache, NULL, cache->store, vdentry,
0063                            FSCACHE_VOLUME_IS_WEIRD);
0064             cachefiles_put_directory(volume->dentry);
0065             cond_resched();
0066             goto retry;
0067         }
0068     }
0069     
0070     for (i = 0; i < 256; i++) {
0071         sprintf(name, "@%02x", i);
0072         fan = cachefiles_get_directory(cache, vdentry, name, NULL);
0073         if (IS_ERR(fan))
0074             goto error_fan;
0075         volume->fanout[i] = fan;
0076     }
0077 
0078     cachefiles_end_secure(cache, saved_cred);
0079 
0080     vcookie->cache_priv = volume;
0081     n_accesses = atomic_inc_return(&vcookie->n_accesses); /* Stop wakeups on dec-to-0 */
0082     trace_fscache_access_volume(vcookie->debug_id, 0,
0083                     refcount_read(&vcookie->ref),
0084                     n_accesses, fscache_access_cache_pin);
0085 
0086     spin_lock(&cache->object_list_lock);
0087     list_add(&volume->cache_link, &volume->cache->volumes);
0088     spin_unlock(&cache->object_list_lock);
0089 
0090     kfree(name);
0091     return;
0092 
0093 error_fan:
0094     for (i = 0; i < 256; i++)
0095         cachefiles_put_directory(volume->fanout[i]);
0096 error_dir:
0097     cachefiles_put_directory(volume->dentry);
0098 error_name:
0099     kfree(name);
0100 error_vol:
0101     kfree(volume);
0102     cachefiles_end_secure(cache, saved_cred);
0103 }
0104 
0105 /*
0106  * Release a volume representation.
0107  */
0108 static void __cachefiles_free_volume(struct cachefiles_volume *volume)
0109 {
0110     int i;
0111 
0112     _enter("");
0113 
0114     volume->vcookie->cache_priv = NULL;
0115 
0116     for (i = 0; i < 256; i++)
0117         cachefiles_put_directory(volume->fanout[i]);
0118     cachefiles_put_directory(volume->dentry);
0119     kfree(volume);
0120 }
0121 
0122 void cachefiles_free_volume(struct fscache_volume *vcookie)
0123 {
0124     struct cachefiles_volume *volume = vcookie->cache_priv;
0125 
0126     if (volume) {
0127         spin_lock(&volume->cache->object_list_lock);
0128         list_del_init(&volume->cache_link);
0129         spin_unlock(&volume->cache->object_list_lock);
0130         __cachefiles_free_volume(volume);
0131     }
0132 }
0133 
0134 void cachefiles_withdraw_volume(struct cachefiles_volume *volume)
0135 {
0136     fscache_withdraw_volume(volume->vcookie);
0137     cachefiles_set_volume_xattr(volume);
0138     __cachefiles_free_volume(volume);
0139 }