1 // SPDX-License-Identifier: GPL-2.0-or-later 2 /* Manage high-level VFS aspects of a cache. 3 * 4 * Copyright (C) 2007, 2021 Red Hat, Inc. All Rights Reserved. 5 * Written by David Howells (dhowells@redhat.com) 6 */ 7 8 #include <linux/slab.h> 9 #include <linux/statfs.h> 10 #include <linux/namei.h> 11 #include <trace/events/fscache.h> 12 #include "internal.h" 13 14 /* 15 * Bring a cache online. 16 */ 17 int cachefiles_add_cache(struct cachefiles_cache *cache) 18 { 19 struct fscache_cache *cache_cookie; 20 struct path path; 21 struct kstatfs stats; 22 struct dentry *graveyard, *cachedir, *root; 23 const struct cred *saved_cred; 24 int ret; 25 26 _enter(""); 27 28 cache_cookie = fscache_acquire_cache(cache->tag); 29 if (IS_ERR(cache_cookie)) 30 return PTR_ERR(cache_cookie); 31 32 /* we want to work under the module's security ID */ 33 ret = cachefiles_get_security_ID(cache); 34 if (ret < 0) 35 goto error_getsec; 36 37 cachefiles_begin_secure(cache, &saved_cred); 38 39 /* look up the directory at the root of the cache */ 40 ret = kern_path(cache->rootdirname, LOOKUP_DIRECTORY, &path); 41 if (ret < 0) 42 goto error_open_root; 43 44 cache->mnt = path.mnt; 45 root = path.dentry; 46 47 ret = -EINVAL; 48 if (is_idmapped_mnt(path.mnt)) { 49 pr_warn("File cache on idmapped mounts not supported"); 50 goto error_unsupported; 51 } 52 53 /* Check features of the backing filesystem: 54 * - Directories must support looking up and directory creation 55 * - We create tmpfiles to handle invalidation 56 * - We use xattrs to store metadata 57 * - We need to be able to query the amount of space available 58 * - We want to be able to sync the filesystem when stopping the cache 59 * - We use DIO to/from pages, so the blocksize mustn't be too big. 60 */ 61 ret = -EOPNOTSUPP; 62 if (d_is_negative(root) || 63 !d_backing_inode(root)->i_op->lookup || 64 !d_backing_inode(root)->i_op->mkdir || 65 !d_backing_inode(root)->i_op->tmpfile || 66 !(d_backing_inode(root)->i_opflags & IOP_XATTR) || 67 !root->d_sb->s_op->statfs || 68 !root->d_sb->s_op->sync_fs || 69 root->d_sb->s_blocksize > PAGE_SIZE) 70 goto error_unsupported; 71 72 ret = -EROFS; 73 if (sb_rdonly(root->d_sb)) 74 goto error_unsupported; 75 76 /* determine the security of the on-disk cache as this governs 77 * security ID of files we create */ 78 ret = cachefiles_determine_cache_security(cache, root, &saved_cred); 79 if (ret < 0) 80 goto error_unsupported; 81 82 /* get the cache size and blocksize */ 83 ret = vfs_statfs(&path, &stats); 84 if (ret < 0) 85 goto error_unsupported; 86 87 ret = -ERANGE; 88 if (stats.f_bsize <= 0) 89 goto error_unsupported; 90 91 ret = -EOPNOTSUPP; 92 if (stats.f_bsize > PAGE_SIZE) 93 goto error_unsupported; 94 95 cache->bsize = stats.f_bsize; 96 cache->bshift = ilog2(stats.f_bsize); 97 98 _debug("blksize %u (shift %u)", 99 cache->bsize, cache->bshift); 100 101 _debug("size %llu, avail %llu", 102 (unsigned long long) stats.f_blocks, 103 (unsigned long long) stats.f_bavail); 104 105 /* set up caching limits */ 106 do_div(stats.f_files, 100); 107 cache->fstop = stats.f_files * cache->fstop_percent; 108 cache->fcull = stats.f_files * cache->fcull_percent; 109 cache->frun = stats.f_files * cache->frun_percent; 110 111 _debug("limits {%llu,%llu,%llu} files", 112 (unsigned long long) cache->frun, 113 (unsigned long long) cache->fcull, 114 (unsigned long long) cache->fstop); 115 116 do_div(stats.f_blocks, 100); 117 cache->bstop = stats.f_blocks * cache->bstop_percent; 118 cache->bcull = stats.f_blocks * cache->bcull_percent; 119 cache->brun = stats.f_blocks * cache->brun_percent; 120 121 _debug("limits {%llu,%llu,%llu} blocks", 122 (unsigned long long) cache->brun, 123 (unsigned long long) cache->bcull, 124 (unsigned long long) cache->bstop); 125 126 /* get the cache directory and check its type */ 127 cachedir = cachefiles_get_directory(cache, root, "cache", NULL); 128 if (IS_ERR(cachedir)) { 129 ret = PTR_ERR(cachedir); 130 goto error_unsupported; 131 } 132 133 cache->store = cachedir; 134 135 /* get the graveyard directory */ 136 graveyard = cachefiles_get_directory(cache, root, "graveyard", NULL); 137 if (IS_ERR(graveyard)) { 138 ret = PTR_ERR(graveyard); 139 goto error_unsupported; 140 } 141 142 cache->graveyard = graveyard; 143 cache->cache = cache_cookie; 144 145 ret = fscache_add_cache(cache_cookie, &cachefiles_cache_ops, cache); 146 if (ret < 0) 147 goto error_add_cache; 148 149 /* done */ 150 set_bit(CACHEFILES_READY, &cache->flags); 151 dput(root); 152 153 pr_info("File cache on %s registered\n", cache_cookie->name); 154 155 /* check how much space the cache has */ 156 cachefiles_has_space(cache, 0, 0, cachefiles_has_space_check); 157 cachefiles_end_secure(cache, saved_cred); 158 _leave(" = 0 [%px]", cache->cache); 159 return 0; 160 161 error_add_cache: 162 cachefiles_put_directory(cache->graveyard); 163 cache->graveyard = NULL; 164 error_unsupported: 165 cachefiles_put_directory(cache->store); 166 cache->store = NULL; 167 mntput(cache->mnt); 168 cache->mnt = NULL; 169 dput(root); 170 error_open_root: 171 cachefiles_end_secure(cache, saved_cred); 172 put_cred(cache->cache_cred); 173 cache->cache_cred = NULL; 174 error_getsec: 175 fscache_relinquish_cache(cache_cookie); 176 cache->cache = NULL; 177 pr_err("Failed to register: %d\n", ret); 178 return ret; 179 } 180 181 /* 182 * See if we have space for a number of pages and/or a number of files in the 183 * cache 184 */ 185 int cachefiles_has_space(struct cachefiles_cache *cache, 186 unsigned fnr, unsigned bnr, 187 enum cachefiles_has_space_for reason) 188 { 189 struct kstatfs stats; 190 u64 b_avail, b_writing; 191 int ret; 192 193 struct path path = { 194 .mnt = cache->mnt, 195 .dentry = cache->mnt->mnt_root, 196 }; 197 198 //_enter("{%llu,%llu,%llu,%llu,%llu,%llu},%u,%u", 199 // (unsigned long long) cache->frun, 200 // (unsigned long long) cache->fcull, 201 // (unsigned long long) cache->fstop, 202 // (unsigned long long) cache->brun, 203 // (unsigned long long) cache->bcull, 204 // (unsigned long long) cache->bstop, 205 // fnr, bnr); 206 207 /* find out how many pages of blockdev are available */ 208 memset(&stats, 0, sizeof(stats)); 209 210 ret = vfs_statfs(&path, &stats); 211 if (ret < 0) { 212 trace_cachefiles_vfs_error(NULL, d_inode(path.dentry), ret, 213 cachefiles_trace_statfs_error); 214 if (ret == -EIO) 215 cachefiles_io_error(cache, "statfs failed"); 216 _leave(" = %d", ret); 217 return ret; 218 } 219 220 b_avail = stats.f_bavail; 221 b_writing = atomic_long_read(&cache->b_writing); 222 if (b_avail > b_writing) 223 b_avail -= b_writing; 224 else 225 b_avail = 0; 226 227 //_debug("avail %llu,%llu", 228 // (unsigned long long)stats.f_ffree, 229 // (unsigned long long)b_avail); 230 231 /* see if there is sufficient space */ 232 if (stats.f_ffree > fnr) 233 stats.f_ffree -= fnr; 234 else 235 stats.f_ffree = 0; 236 237 if (b_avail > bnr) 238 b_avail -= bnr; 239 else 240 b_avail = 0; 241 242 ret = -ENOBUFS; 243 if (stats.f_ffree < cache->fstop || 244 b_avail < cache->bstop) 245 goto stop_and_begin_cull; 246 247 ret = 0; 248 if (stats.f_ffree < cache->fcull || 249 b_avail < cache->bcull) 250 goto begin_cull; 251 252 if (test_bit(CACHEFILES_CULLING, &cache->flags) && 253 stats.f_ffree >= cache->frun && 254 b_avail >= cache->brun && 255 test_and_clear_bit(CACHEFILES_CULLING, &cache->flags) 256 ) { 257 _debug("cease culling"); 258 cachefiles_state_changed(cache); 259 } 260 261 //_leave(" = 0"); 262 return 0; 263 264 stop_and_begin_cull: 265 switch (reason) { 266 case cachefiles_has_space_for_write: 267 fscache_count_no_write_space(); 268 break; 269 case cachefiles_has_space_for_create: 270 fscache_count_no_create_space(); 271 break; 272 default: 273 break; 274 } 275 begin_cull: 276 if (!test_and_set_bit(CACHEFILES_CULLING, &cache->flags)) { 277 _debug("### CULL CACHE ###"); 278 cachefiles_state_changed(cache); 279 } 280 281 _leave(" = %d", ret); 282 return ret; 283 } 284 285 /* 286 * Mark all the objects as being out of service and queue them all for cleanup. 287 */ 288 static void cachefiles_withdraw_objects(struct cachefiles_cache *cache) 289 { 290 struct cachefiles_object *object; 291 unsigned int count = 0; 292 293 _enter(""); 294 295 spin_lock(&cache->object_list_lock); 296 297 while (!list_empty(&cache->object_list)) { 298 object = list_first_entry(&cache->object_list, 299 struct cachefiles_object, cache_link); 300 cachefiles_see_object(object, cachefiles_obj_see_withdrawal); 301 list_del_init(&object->cache_link); 302 fscache_withdraw_cookie(object->cookie); 303 count++; 304 if ((count & 63) == 0) { 305 spin_unlock(&cache->object_list_lock); 306 cond_resched(); 307 spin_lock(&cache->object_list_lock); 308 } 309 } 310 311 spin_unlock(&cache->object_list_lock); 312 _leave(" [%u objs]", count); 313 } 314 315 /* 316 * Withdraw fscache volumes. 317 */ 318 static void cachefiles_withdraw_fscache_volumes(struct cachefiles_cache *cache) 319 { 320 struct list_head *cur; 321 struct cachefiles_volume *volume; 322 struct fscache_volume *vcookie; 323 324 _enter(""); 325 retry: 326 spin_lock(&cache->object_list_lock); 327 list_for_each(cur, &cache->volumes) { 328 volume = list_entry(cur, struct cachefiles_volume, cache_link); 329 330 if (atomic_read(&volume->vcookie->n_accesses) == 0) 331 continue; 332 333 vcookie = fscache_try_get_volume(volume->vcookie, 334 fscache_volume_get_withdraw); 335 if (vcookie) { 336 spin_unlock(&cache->object_list_lock); 337 fscache_withdraw_volume(vcookie); 338 fscache_put_volume(vcookie, fscache_volume_put_withdraw); 339 goto retry; 340 } 341 } 342 spin_unlock(&cache->object_list_lock); 343 344 _leave(""); 345 } 346 347 /* 348 * Withdraw cachefiles volumes. 349 */ 350 static void cachefiles_withdraw_volumes(struct cachefiles_cache *cache) 351 { 352 _enter(""); 353 354 for (;;) { 355 struct fscache_volume *vcookie = NULL; 356 struct cachefiles_volume *volume = NULL; 357 358 spin_lock(&cache->object_list_lock); 359 if (!list_empty(&cache->volumes)) { 360 volume = list_first_entry(&cache->volumes, 361 struct cachefiles_volume, cache_link); 362 vcookie = fscache_try_get_volume(volume->vcookie, 363 fscache_volume_get_withdraw); 364 if (!vcookie) { 365 spin_unlock(&cache->object_list_lock); 366 cpu_relax(); 367 continue; 368 } 369 list_del_init(&volume->cache_link); 370 } 371 spin_unlock(&cache->object_list_lock); 372 if (!volume) 373 break; 374 375 cachefiles_withdraw_volume(volume); 376 fscache_put_volume(vcookie, fscache_volume_put_withdraw); 377 } 378 379 _leave(""); 380 } 381 382 /* 383 * Sync a cache to backing disk. 384 */ 385 static void cachefiles_sync_cache(struct cachefiles_cache *cache) 386 { 387 const struct cred *saved_cred; 388 int ret; 389 390 _enter("%s", cache->cache->name); 391 392 /* make sure all pages pinned by operations on behalf of the netfs are 393 * written to disc */ 394 cachefiles_begin_secure(cache, &saved_cred); 395 down_read(&cache->mnt->mnt_sb->s_umount); 396 ret = sync_filesystem(cache->mnt->mnt_sb); 397 up_read(&cache->mnt->mnt_sb->s_umount); 398 cachefiles_end_secure(cache, saved_cred); 399 400 if (ret == -EIO) 401 cachefiles_io_error(cache, 402 "Attempt to sync backing fs superblock returned error %d", 403 ret); 404 } 405 406 /* 407 * Withdraw cache objects. 408 */ 409 void cachefiles_withdraw_cache(struct cachefiles_cache *cache) 410 { 411 struct fscache_cache *fscache = cache->cache; 412 413 pr_info("File cache on %s unregistering\n", fscache->name); 414 415 fscache_withdraw_cache(fscache); 416 cachefiles_withdraw_fscache_volumes(cache); 417 418 /* we now have to destroy all the active objects pertaining to this 419 * cache - which we do by passing them off to thread pool to be 420 * disposed of */ 421 cachefiles_withdraw_objects(cache); 422 fscache_wait_for_objects(fscache); 423 424 cachefiles_withdraw_volumes(cache); 425 cachefiles_sync_cache(cache); 426 cache->cache = NULL; 427 fscache_relinquish_cache(fscache); 428 } 429
Linux® is a registered trademark of Linus Torvalds in the United States and other countries.
TOMOYO® is a registered trademark of NTT DATA CORPORATION.