177443f61SDavid Howells /* SPDX-License-Identifier: GPL-2.0-or-later */ 277443f61SDavid Howells /* General netfs cache on cache files internal defs 377443f61SDavid Howells * 477443f61SDavid Howells * Copyright (C) 2021 Red Hat, Inc. All Rights Reserved. 577443f61SDavid Howells * Written by David Howells (dhowells@redhat.com) 677443f61SDavid Howells */ 777443f61SDavid Howells 877443f61SDavid Howells #ifdef pr_fmt 977443f61SDavid Howells #undef pr_fmt 1077443f61SDavid Howells #endif 1177443f61SDavid Howells 1277443f61SDavid Howells #define pr_fmt(fmt) "CacheFiles: " fmt 1377443f61SDavid Howells 1477443f61SDavid Howells 1577443f61SDavid Howells #include <linux/fscache-cache.h> 1677443f61SDavid Howells #include <linux/cred.h> 1777443f61SDavid Howells #include <linux/security.h> 1877443f61SDavid Howells 198390fbc4SDavid Howells struct cachefiles_cache; 208390fbc4SDavid Howells struct cachefiles_object; 218390fbc4SDavid Howells 228390fbc4SDavid Howells /* 238390fbc4SDavid Howells * Data file records. 248390fbc4SDavid Howells */ 258390fbc4SDavid Howells struct cachefiles_object { 268390fbc4SDavid Howells int debug_id; /* debugging ID */ 278390fbc4SDavid Howells }; 288390fbc4SDavid Howells 298390fbc4SDavid Howells /* 308390fbc4SDavid Howells * Cache files cache definition 318390fbc4SDavid Howells */ 328390fbc4SDavid Howells struct cachefiles_cache { 331493bf74SDavid Howells struct fscache_cache *cache; /* Cache cookie */ 348390fbc4SDavid Howells struct vfsmount *mnt; /* mountpoint holding the cache */ 35*d1065b0aSDavid Howells struct dentry *store; /* Directory into which live objects go */ 36*d1065b0aSDavid Howells struct dentry *graveyard; /* directory into which dead objects go */ 378390fbc4SDavid Howells struct file *cachefilesd; /* manager daemon handle */ 388390fbc4SDavid Howells const struct cred *cache_cred; /* security override for accessing cache */ 398390fbc4SDavid Howells struct mutex daemon_mutex; /* command serialisation mutex */ 408390fbc4SDavid Howells wait_queue_head_t daemon_pollwq; /* poll waitqueue for daemon */ 418390fbc4SDavid Howells atomic_t gravecounter; /* graveyard uniquifier */ 428390fbc4SDavid Howells atomic_t f_released; /* number of objects released lately */ 438390fbc4SDavid Howells atomic_long_t b_released; /* number of blocks released lately */ 4480f94f29SDavid Howells atomic_long_t b_writing; /* Number of blocks being written */ 458390fbc4SDavid Howells unsigned frun_percent; /* when to stop culling (% files) */ 468390fbc4SDavid Howells unsigned fcull_percent; /* when to start culling (% files) */ 478390fbc4SDavid Howells unsigned fstop_percent; /* when to stop allocating (% files) */ 488390fbc4SDavid Howells unsigned brun_percent; /* when to stop culling (% blocks) */ 498390fbc4SDavid Howells unsigned bcull_percent; /* when to start culling (% blocks) */ 508390fbc4SDavid Howells unsigned bstop_percent; /* when to stop allocating (% blocks) */ 518390fbc4SDavid Howells unsigned bsize; /* cache's block size */ 528390fbc4SDavid Howells unsigned bshift; /* min(ilog2(PAGE_SIZE / bsize), 0) */ 538390fbc4SDavid Howells uint64_t frun; /* when to stop culling */ 548390fbc4SDavid Howells uint64_t fcull; /* when to start culling */ 558390fbc4SDavid Howells uint64_t fstop; /* when to stop allocating */ 568390fbc4SDavid Howells sector_t brun; /* when to stop culling */ 578390fbc4SDavid Howells sector_t bcull; /* when to start culling */ 588390fbc4SDavid Howells sector_t bstop; /* when to stop allocating */ 598390fbc4SDavid Howells unsigned long flags; 608390fbc4SDavid Howells #define CACHEFILES_READY 0 /* T if cache prepared */ 618390fbc4SDavid Howells #define CACHEFILES_DEAD 1 /* T if cache dead */ 628390fbc4SDavid Howells #define CACHEFILES_CULLING 2 /* T if cull engaged */ 638390fbc4SDavid Howells #define CACHEFILES_STATE_CHANGED 3 /* T if state changed (poll trigger) */ 648390fbc4SDavid Howells char *rootdirname; /* name of cache root directory */ 658390fbc4SDavid Howells char *secctx; /* LSM security context */ 668390fbc4SDavid Howells char *tag; /* cache binding tag */ 678390fbc4SDavid Howells }; 688390fbc4SDavid Howells 69ecf5a6ceSDavid Howells #include <trace/events/cachefiles.h> 7077443f61SDavid Howells 7177443f61SDavid Howells /* 728667d434SDavid Howells * note change of state for daemon 738667d434SDavid Howells */ 748667d434SDavid Howells static inline void cachefiles_state_changed(struct cachefiles_cache *cache) 758667d434SDavid Howells { 768667d434SDavid Howells set_bit(CACHEFILES_STATE_CHANGED, &cache->flags); 778667d434SDavid Howells wake_up_all(&cache->daemon_pollwq); 788667d434SDavid Howells } 798667d434SDavid Howells 808667d434SDavid Howells /* 8180f94f29SDavid Howells * cache.c 8280f94f29SDavid Howells */ 83*d1065b0aSDavid Howells extern int cachefiles_add_cache(struct cachefiles_cache *cache); 8480f94f29SDavid Howells extern int cachefiles_has_space(struct cachefiles_cache *cache, 8580f94f29SDavid Howells unsigned fnr, unsigned bnr); 86*d1065b0aSDavid Howells extern void cachefiles_withdraw_cache(struct cachefiles_cache *cache); 8780f94f29SDavid Howells 8880f94f29SDavid Howells /* 898667d434SDavid Howells * daemon.c 908667d434SDavid Howells */ 918667d434SDavid Howells extern const struct file_operations cachefiles_daemon_fops; 928667d434SDavid Howells 938667d434SDavid Howells /* 94a70f6526SDavid Howells * error_inject.c 95a70f6526SDavid Howells */ 96a70f6526SDavid Howells #ifdef CONFIG_CACHEFILES_ERROR_INJECTION 97a70f6526SDavid Howells extern unsigned int cachefiles_error_injection_state; 98a70f6526SDavid Howells extern int cachefiles_register_error_injection(void); 99a70f6526SDavid Howells extern void cachefiles_unregister_error_injection(void); 100a70f6526SDavid Howells 101a70f6526SDavid Howells #else 102a70f6526SDavid Howells #define cachefiles_error_injection_state 0 103a70f6526SDavid Howells 104a70f6526SDavid Howells static inline int cachefiles_register_error_injection(void) 105a70f6526SDavid Howells { 106a70f6526SDavid Howells return 0; 107a70f6526SDavid Howells } 108a70f6526SDavid Howells 109a70f6526SDavid Howells static inline void cachefiles_unregister_error_injection(void) 110a70f6526SDavid Howells { 111a70f6526SDavid Howells } 112a70f6526SDavid Howells #endif 113a70f6526SDavid Howells 114a70f6526SDavid Howells 115a70f6526SDavid Howells static inline int cachefiles_inject_read_error(void) 116a70f6526SDavid Howells { 117a70f6526SDavid Howells return cachefiles_error_injection_state & 2 ? -EIO : 0; 118a70f6526SDavid Howells } 119a70f6526SDavid Howells 120a70f6526SDavid Howells static inline int cachefiles_inject_write_error(void) 121a70f6526SDavid Howells { 122a70f6526SDavid Howells return cachefiles_error_injection_state & 2 ? -EIO : 123a70f6526SDavid Howells cachefiles_error_injection_state & 1 ? -ENOSPC : 124a70f6526SDavid Howells 0; 125a70f6526SDavid Howells } 126a70f6526SDavid Howells 127a70f6526SDavid Howells static inline int cachefiles_inject_remove_error(void) 128a70f6526SDavid Howells { 129a70f6526SDavid Howells return cachefiles_error_injection_state & 2 ? -EIO : 0; 130a70f6526SDavid Howells } 131a70f6526SDavid Howells 1321493bf74SDavid Howells /* 133*d1065b0aSDavid Howells * interface.c 134*d1065b0aSDavid Howells */ 135*d1065b0aSDavid Howells extern const struct fscache_cache_ops cachefiles_cache_ops; 136*d1065b0aSDavid Howells 137*d1065b0aSDavid Howells /* 13832759f7dSDavid Howells * namei.c 13932759f7dSDavid Howells */ 14032759f7dSDavid Howells extern struct dentry *cachefiles_get_directory(struct cachefiles_cache *cache, 14132759f7dSDavid Howells struct dentry *dir, 14232759f7dSDavid Howells const char *name, 14332759f7dSDavid Howells bool *_is_new); 14432759f7dSDavid Howells extern void cachefiles_put_directory(struct dentry *dir); 14532759f7dSDavid Howells 14632759f7dSDavid Howells /* 147254947d4SDavid Howells * security.c 148254947d4SDavid Howells */ 149254947d4SDavid Howells extern int cachefiles_get_security_ID(struct cachefiles_cache *cache); 150254947d4SDavid Howells extern int cachefiles_determine_cache_security(struct cachefiles_cache *cache, 151254947d4SDavid Howells struct dentry *root, 152254947d4SDavid Howells const struct cred **_saved_cred); 153254947d4SDavid Howells 154254947d4SDavid Howells static inline void cachefiles_begin_secure(struct cachefiles_cache *cache, 155254947d4SDavid Howells const struct cred **_saved_cred) 156254947d4SDavid Howells { 157254947d4SDavid Howells *_saved_cred = override_creds(cache->cache_cred); 158254947d4SDavid Howells } 159254947d4SDavid Howells 160254947d4SDavid Howells static inline void cachefiles_end_secure(struct cachefiles_cache *cache, 161254947d4SDavid Howells const struct cred *saved_cred) 162254947d4SDavid Howells { 163254947d4SDavid Howells revert_creds(saved_cred); 164254947d4SDavid Howells } 165254947d4SDavid Howells 166254947d4SDavid Howells /* 1671493bf74SDavid Howells * Error handling 1681493bf74SDavid Howells */ 1691493bf74SDavid Howells #define cachefiles_io_error(___cache, FMT, ...) \ 1701493bf74SDavid Howells do { \ 1711493bf74SDavid Howells pr_err("I/O Error: " FMT"\n", ##__VA_ARGS__); \ 1721493bf74SDavid Howells fscache_io_error((___cache)->cache); \ 1731493bf74SDavid Howells set_bit(CACHEFILES_DEAD, &(___cache)->flags); \ 1741493bf74SDavid Howells } while (0) 1751493bf74SDavid Howells 176a70f6526SDavid Howells 177a70f6526SDavid Howells /* 178a70f6526SDavid Howells * Debug tracing 17977443f61SDavid Howells */ 18077443f61SDavid Howells extern unsigned cachefiles_debug; 18177443f61SDavid Howells #define CACHEFILES_DEBUG_KENTER 1 18277443f61SDavid Howells #define CACHEFILES_DEBUG_KLEAVE 2 18377443f61SDavid Howells #define CACHEFILES_DEBUG_KDEBUG 4 18477443f61SDavid Howells 18577443f61SDavid Howells #define dbgprintk(FMT, ...) \ 18677443f61SDavid Howells printk(KERN_DEBUG "[%-6.6s] "FMT"\n", current->comm, ##__VA_ARGS__) 18777443f61SDavid Howells 18877443f61SDavid Howells #define kenter(FMT, ...) dbgprintk("==> %s("FMT")", __func__, ##__VA_ARGS__) 18977443f61SDavid Howells #define kleave(FMT, ...) dbgprintk("<== %s()"FMT"", __func__, ##__VA_ARGS__) 19077443f61SDavid Howells #define kdebug(FMT, ...) dbgprintk(FMT, ##__VA_ARGS__) 19177443f61SDavid Howells 19277443f61SDavid Howells 19377443f61SDavid Howells #if defined(__KDEBUG) 19477443f61SDavid Howells #define _enter(FMT, ...) kenter(FMT, ##__VA_ARGS__) 19577443f61SDavid Howells #define _leave(FMT, ...) kleave(FMT, ##__VA_ARGS__) 19677443f61SDavid Howells #define _debug(FMT, ...) kdebug(FMT, ##__VA_ARGS__) 19777443f61SDavid Howells 19877443f61SDavid Howells #elif defined(CONFIG_CACHEFILES_DEBUG) 19977443f61SDavid Howells #define _enter(FMT, ...) \ 20077443f61SDavid Howells do { \ 20177443f61SDavid Howells if (cachefiles_debug & CACHEFILES_DEBUG_KENTER) \ 20277443f61SDavid Howells kenter(FMT, ##__VA_ARGS__); \ 20377443f61SDavid Howells } while (0) 20477443f61SDavid Howells 20577443f61SDavid Howells #define _leave(FMT, ...) \ 20677443f61SDavid Howells do { \ 20777443f61SDavid Howells if (cachefiles_debug & CACHEFILES_DEBUG_KLEAVE) \ 20877443f61SDavid Howells kleave(FMT, ##__VA_ARGS__); \ 20977443f61SDavid Howells } while (0) 21077443f61SDavid Howells 21177443f61SDavid Howells #define _debug(FMT, ...) \ 21277443f61SDavid Howells do { \ 21377443f61SDavid Howells if (cachefiles_debug & CACHEFILES_DEBUG_KDEBUG) \ 21477443f61SDavid Howells kdebug(FMT, ##__VA_ARGS__); \ 21577443f61SDavid Howells } while (0) 21677443f61SDavid Howells 21777443f61SDavid Howells #else 21877443f61SDavid Howells #define _enter(FMT, ...) no_printk("==> %s("FMT")", __func__, ##__VA_ARGS__) 21977443f61SDavid Howells #define _leave(FMT, ...) no_printk("<== %s()"FMT"", __func__, ##__VA_ARGS__) 22077443f61SDavid Howells #define _debug(FMT, ...) no_printk(FMT, ##__VA_ARGS__) 22177443f61SDavid Howells #endif 22277443f61SDavid Howells 22377443f61SDavid Howells #if 1 /* defined(__KDEBUGALL) */ 22477443f61SDavid Howells 22577443f61SDavid Howells #define ASSERT(X) \ 22677443f61SDavid Howells do { \ 22777443f61SDavid Howells if (unlikely(!(X))) { \ 22877443f61SDavid Howells pr_err("\n"); \ 22977443f61SDavid Howells pr_err("Assertion failed\n"); \ 23077443f61SDavid Howells BUG(); \ 23177443f61SDavid Howells } \ 23277443f61SDavid Howells } while (0) 23377443f61SDavid Howells 23477443f61SDavid Howells #define ASSERTCMP(X, OP, Y) \ 23577443f61SDavid Howells do { \ 23677443f61SDavid Howells if (unlikely(!((X) OP (Y)))) { \ 23777443f61SDavid Howells pr_err("\n"); \ 23877443f61SDavid Howells pr_err("Assertion failed\n"); \ 23977443f61SDavid Howells pr_err("%lx " #OP " %lx is false\n", \ 24077443f61SDavid Howells (unsigned long)(X), (unsigned long)(Y)); \ 24177443f61SDavid Howells BUG(); \ 24277443f61SDavid Howells } \ 24377443f61SDavid Howells } while (0) 24477443f61SDavid Howells 24577443f61SDavid Howells #define ASSERTIF(C, X) \ 24677443f61SDavid Howells do { \ 24777443f61SDavid Howells if (unlikely((C) && !(X))) { \ 24877443f61SDavid Howells pr_err("\n"); \ 24977443f61SDavid Howells pr_err("Assertion failed\n"); \ 25077443f61SDavid Howells BUG(); \ 25177443f61SDavid Howells } \ 25277443f61SDavid Howells } while (0) 25377443f61SDavid Howells 25477443f61SDavid Howells #define ASSERTIFCMP(C, X, OP, Y) \ 25577443f61SDavid Howells do { \ 25677443f61SDavid Howells if (unlikely((C) && !((X) OP (Y)))) { \ 25777443f61SDavid Howells pr_err("\n"); \ 25877443f61SDavid Howells pr_err("Assertion failed\n"); \ 25977443f61SDavid Howells pr_err("%lx " #OP " %lx is false\n", \ 26077443f61SDavid Howells (unsigned long)(X), (unsigned long)(Y)); \ 26177443f61SDavid Howells BUG(); \ 26277443f61SDavid Howells } \ 26377443f61SDavid Howells } while (0) 26477443f61SDavid Howells 26577443f61SDavid Howells #else 26677443f61SDavid Howells 26777443f61SDavid Howells #define ASSERT(X) do {} while (0) 26877443f61SDavid Howells #define ASSERTCMP(X, OP, Y) do {} while (0) 26977443f61SDavid Howells #define ASSERTIF(C, X) do {} while (0) 27077443f61SDavid Howells #define ASSERTIFCMP(C, X, OP, Y) do {} while (0) 27177443f61SDavid Howells 27277443f61SDavid Howells #endif 273