Branch data Line data Source code
1 : : // SPDX-License-Identifier: GPL-2.0-or-later 2 : : /* Bind and unbind a cache from the filesystem backing it 3 : : * 4 : : * Copyright (C) 2007 Red Hat, Inc. All Rights Reserved. 5 : : * Written by David Howells (dhowells@redhat.com) 6 : : */ 7 : : 8 : : #include <linux/module.h> 9 : : #include <linux/init.h> 10 : : #include <linux/sched.h> 11 : : #include <linux/completion.h> 12 : : #include <linux/slab.h> 13 : : #include <linux/fs.h> 14 : : #include <linux/file.h> 15 : : #include <linux/namei.h> 16 : : #include <linux/mount.h> 17 : : #include <linux/statfs.h> 18 : : #include <linux/ctype.h> 19 : : #include <linux/xattr.h> 20 : : #include "internal.h" 21 : : 22 : : static int cachefiles_daemon_add_cache(struct cachefiles_cache *caches); 23 : : 24 : : /* 25 : : * bind a directory as a cache 26 : : */ 27 : 0 : int cachefiles_daemon_bind(struct cachefiles_cache *cache, char *args) 28 : : { 29 : : _enter("{%u,%u,%u,%u,%u,%u},%s", 30 : : cache->frun_percent, 31 : : cache->fcull_percent, 32 : : cache->fstop_percent, 33 : : cache->brun_percent, 34 : : cache->bcull_percent, 35 : : cache->bstop_percent, 36 : : args); 37 : : 38 : : /* start by checking things over */ 39 : 0 : ASSERT(cache->fstop_percent >= 0 && 40 : : cache->fstop_percent < cache->fcull_percent && 41 : : cache->fcull_percent < cache->frun_percent && 42 : : cache->frun_percent < 100); 43 : : 44 : 0 : ASSERT(cache->bstop_percent >= 0 && 45 : : cache->bstop_percent < cache->bcull_percent && 46 : : cache->bcull_percent < cache->brun_percent && 47 : : cache->brun_percent < 100); 48 : : 49 : 0 : if (*args) { 50 : 0 : pr_err("'bind' command doesn't take an argument\n"); 51 : 0 : return -EINVAL; 52 : : } 53 : : 54 : 0 : if (!cache->rootdirname) { 55 : 0 : pr_err("No cache directory specified\n"); 56 : 0 : return -EINVAL; 57 : : } 58 : : 59 : : /* don't permit already bound caches to be re-bound */ 60 : 0 : if (test_bit(CACHEFILES_READY, &cache->flags)) { 61 : 0 : pr_err("Cache already bound\n"); 62 : 0 : return -EBUSY; 63 : : } 64 : : 65 : : /* make sure we have copies of the tag and dirname strings */ 66 : 0 : if (!cache->tag) { 67 : : /* the tag string is released by the fops->release() 68 : : * function, so we don't release it on error here */ 69 : 0 : cache->tag = kstrdup("CacheFiles", GFP_KERNEL); 70 : 0 : if (!cache->tag) 71 : : return -ENOMEM; 72 : : } 73 : : 74 : : /* add the cache */ 75 : 0 : return cachefiles_daemon_add_cache(cache); 76 : : } 77 : : 78 : : /* 79 : : * add a cache 80 : : */ 81 : 0 : static int cachefiles_daemon_add_cache(struct cachefiles_cache *cache) 82 : : { 83 : : struct cachefiles_object *fsdef; 84 : : struct path path; 85 : : struct kstatfs stats; 86 : : struct dentry *graveyard, *cachedir, *root; 87 : : const struct cred *saved_cred; 88 : : int ret; 89 : : 90 : : _enter(""); 91 : : 92 : : /* we want to work under the module's security ID */ 93 : 0 : ret = cachefiles_get_security_ID(cache); 94 : 0 : if (ret < 0) 95 : : return ret; 96 : : 97 : : cachefiles_begin_secure(cache, &saved_cred); 98 : : 99 : : /* allocate the root index object */ 100 : : ret = -ENOMEM; 101 : : 102 : 0 : fsdef = kmem_cache_alloc(cachefiles_object_jar, GFP_KERNEL); 103 : 0 : if (!fsdef) 104 : : goto error_root_object; 105 : : 106 : 0 : ASSERTCMP(fsdef->backer, ==, NULL); 107 : : 108 : : atomic_set(&fsdef->usage, 1); 109 : 0 : fsdef->type = FSCACHE_COOKIE_TYPE_INDEX; 110 : : 111 : : _debug("- fsdef %p", fsdef); 112 : : 113 : : /* look up the directory at the root of the cache */ 114 : 0 : ret = kern_path(cache->rootdirname, LOOKUP_DIRECTORY, &path); 115 : 0 : if (ret < 0) 116 : : goto error_open_root; 117 : : 118 : 0 : cache->mnt = path.mnt; 119 : 0 : root = path.dentry; 120 : : 121 : : /* check parameters */ 122 : : ret = -EOPNOTSUPP; 123 : 0 : if (d_is_negative(root) || 124 : 0 : !d_backing_inode(root)->i_op->lookup || 125 : 0 : !d_backing_inode(root)->i_op->mkdir || 126 : 0 : !(d_backing_inode(root)->i_opflags & IOP_XATTR) || 127 : 0 : !root->d_sb->s_op->statfs || 128 : 0 : !root->d_sb->s_op->sync_fs) 129 : : goto error_unsupported; 130 : : 131 : : ret = -EROFS; 132 : 0 : if (sb_rdonly(root->d_sb)) 133 : : goto error_unsupported; 134 : : 135 : : /* determine the security of the on-disk cache as this governs 136 : : * security ID of files we create */ 137 : 0 : ret = cachefiles_determine_cache_security(cache, root, &saved_cred); 138 : 0 : if (ret < 0) 139 : : goto error_unsupported; 140 : : 141 : : /* get the cache size and blocksize */ 142 : 0 : ret = vfs_statfs(&path, &stats); 143 : 0 : if (ret < 0) 144 : : goto error_unsupported; 145 : : 146 : : ret = -ERANGE; 147 : 0 : if (stats.f_bsize <= 0) 148 : : goto error_unsupported; 149 : : 150 : : ret = -EOPNOTSUPP; 151 : 0 : if (stats.f_bsize > PAGE_SIZE) 152 : : goto error_unsupported; 153 : : 154 : 0 : cache->bsize = stats.f_bsize; 155 : 0 : cache->bshift = 0; 156 : 0 : if (stats.f_bsize < PAGE_SIZE) 157 : 0 : cache->bshift = PAGE_SHIFT - ilog2(stats.f_bsize); 158 : : 159 : : _debug("blksize %u (shift %u)", 160 : : cache->bsize, cache->bshift); 161 : : 162 : : _debug("size %llu, avail %llu", 163 : : (unsigned long long) stats.f_blocks, 164 : : (unsigned long long) stats.f_bavail); 165 : : 166 : : /* set up caching limits */ 167 : 0 : do_div(stats.f_files, 100); 168 : 0 : cache->fstop = stats.f_files * cache->fstop_percent; 169 : 0 : cache->fcull = stats.f_files * cache->fcull_percent; 170 : 0 : cache->frun = stats.f_files * cache->frun_percent; 171 : : 172 : : _debug("limits {%llu,%llu,%llu} files", 173 : : (unsigned long long) cache->frun, 174 : : (unsigned long long) cache->fcull, 175 : : (unsigned long long) cache->fstop); 176 : : 177 : 0 : stats.f_blocks >>= cache->bshift; 178 : 0 : do_div(stats.f_blocks, 100); 179 : 0 : cache->bstop = stats.f_blocks * cache->bstop_percent; 180 : 0 : cache->bcull = stats.f_blocks * cache->bcull_percent; 181 : 0 : cache->brun = stats.f_blocks * cache->brun_percent; 182 : : 183 : : _debug("limits {%llu,%llu,%llu} blocks", 184 : : (unsigned long long) cache->brun, 185 : : (unsigned long long) cache->bcull, 186 : : (unsigned long long) cache->bstop); 187 : : 188 : : /* get the cache directory and check its type */ 189 : 0 : cachedir = cachefiles_get_directory(cache, root, "cache"); 190 : 0 : if (IS_ERR(cachedir)) { 191 : : ret = PTR_ERR(cachedir); 192 : 0 : goto error_unsupported; 193 : : } 194 : : 195 : 0 : fsdef->dentry = cachedir; 196 : 0 : fsdef->fscache.cookie = NULL; 197 : : 198 : 0 : ret = cachefiles_check_object_type(fsdef); 199 : 0 : if (ret < 0) 200 : : goto error_unsupported; 201 : : 202 : : /* get the graveyard directory */ 203 : 0 : graveyard = cachefiles_get_directory(cache, root, "graveyard"); 204 : 0 : if (IS_ERR(graveyard)) { 205 : : ret = PTR_ERR(graveyard); 206 : 0 : goto error_unsupported; 207 : : } 208 : : 209 : 0 : cache->graveyard = graveyard; 210 : : 211 : : /* publish the cache */ 212 : 0 : fscache_init_cache(&cache->cache, 213 : : &cachefiles_cache_ops, 214 : : "%s", 215 : 0 : fsdef->dentry->d_sb->s_id); 216 : : 217 : 0 : fscache_object_init(&fsdef->fscache, &fscache_fsdef_index, 218 : : &cache->cache); 219 : : 220 : 0 : ret = fscache_add_cache(&cache->cache, &fsdef->fscache, cache->tag); 221 : 0 : if (ret < 0) 222 : : goto error_add_cache; 223 : : 224 : : /* done */ 225 : 0 : set_bit(CACHEFILES_READY, &cache->flags); 226 : 0 : dput(root); 227 : : 228 : 0 : pr_info("File cache on %s registered\n", cache->cache.identifier); 229 : : 230 : : /* check how much space the cache has */ 231 : 0 : cachefiles_has_space(cache, 0, 0); 232 : 0 : cachefiles_end_secure(cache, saved_cred); 233 : 0 : return 0; 234 : : 235 : : error_add_cache: 236 : 0 : dput(cache->graveyard); 237 : 0 : cache->graveyard = NULL; 238 : : error_unsupported: 239 : 0 : mntput(cache->mnt); 240 : 0 : cache->mnt = NULL; 241 : 0 : dput(fsdef->dentry); 242 : 0 : fsdef->dentry = NULL; 243 : 0 : dput(root); 244 : : error_open_root: 245 : 0 : kmem_cache_free(cachefiles_object_jar, fsdef); 246 : : error_root_object: 247 : 0 : cachefiles_end_secure(cache, saved_cred); 248 : 0 : pr_err("Failed to register: %d\n", ret); 249 : 0 : return ret; 250 : : } 251 : : 252 : : /* 253 : : * unbind a cache on fd release 254 : : */ 255 : 0 : void cachefiles_daemon_unbind(struct cachefiles_cache *cache) 256 : : { 257 : : _enter(""); 258 : : 259 : 0 : if (test_bit(CACHEFILES_READY, &cache->flags)) { 260 : 0 : pr_info("File cache on %s unregistering\n", 261 : : cache->cache.identifier); 262 : : 263 : 0 : fscache_withdraw_cache(&cache->cache); 264 : : } 265 : : 266 : 0 : dput(cache->graveyard); 267 : 0 : mntput(cache->mnt); 268 : : 269 : 0 : kfree(cache->rootdirname); 270 : 0 : kfree(cache->secctx); 271 : 0 : kfree(cache->tag); 272 : : 273 : : _leave(""); 274 : 0 : }