xref: /openbmc/linux/fs/cachefiles/internal.h (revision d1065b0a6fd9397edd3094c56b777d0d8ec1290d)
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