projects/linux·blob assoc-array-fixes · refs

408 lines · 12.3 KiB

1/* SPDX-License-Identifier: GPL-2.0-or-later */
2/* General netfs cache on cache files internal defs
3 *
4 * Copyright (C) 2021 Red Hat, Inc. All Rights Reserved.
5 * Written by David Howells ([email protected])
6 */
7
8#ifdef pr_fmt
9#undef pr_fmt
10#endif
11
12#define pr_fmt(fmt) "CacheFiles: " fmt
13
14
15#include <linux/fscache-cache.h>
16#include <linux/cred.h>
17#include <linux/security.h>
18
19#define CACHEFILES_DIO_BLOCK_SIZE 4096
20
21struct cachefiles_cache;
22struct cachefiles_object;
23
24enum cachefiles_content {
25 /* These values are saved on disk */
26 CACHEFILES_CONTENT_NO_DATA = 0, /* No content stored */
27 CACHEFILES_CONTENT_SINGLE = 1, /* Content is monolithic, all is present */
28 CACHEFILES_CONTENT_ALL = 2, /* Content is all present, no map */
29 CACHEFILES_CONTENT_BACKFS_MAP = 3, /* Content is piecemeal, mapped through backing fs */
30 CACHEFILES_CONTENT_DIRTY = 4, /* Content is dirty (only seen on disk) */
31 nr__cachefiles_content
32};
33
34/*
35 * Cached volume representation.
36 */
37struct cachefiles_volume {
38 struct cachefiles_cache *cache;
39 struct list_head cache_link; /* Link in cache->volumes */
40 struct fscache_volume *vcookie; /* The netfs's representation */
41 struct dentry *dentry; /* The volume dentry */
42 struct dentry *fanout[256]; /* Fanout subdirs */
43};
44
45/*
46 * Backing file state.
47 */
48struct cachefiles_object {
49 struct fscache_cookie *cookie; /* Netfs data storage object cookie */
50 struct cachefiles_volume *volume; /* Cache volume that holds this object */
51 struct list_head cache_link; /* Link in cache->*_list */
52 struct file *file; /* The file representing this object */
53 char *d_name; /* Backing file name */
54 int debug_id;
55 spinlock_t lock;
56 refcount_t ref;
57 enum cachefiles_content content_info:8; /* Info about content presence */
58 unsigned long flags;
59#define CACHEFILES_OBJECT_USING_TMPFILE 0 /* Have an unlinked tmpfile */
60};
61
62/*
63 * Cache files cache definition
64 */
65struct cachefiles_cache {
66 struct fscache_cache *cache; /* Cache cookie */
67 struct vfsmount *mnt; /* mountpoint holding the cache */
68 struct dentry *store; /* Directory into which live objects go */
69 struct dentry *graveyard; /* directory into which dead objects go */
70 struct file *cachefilesd; /* manager daemon handle */
71 struct list_head volumes; /* List of volume objects */
72 struct list_head object_list; /* List of active objects */
73 spinlock_t object_list_lock; /* Lock for volumes and object_list */
74 const struct cred *cache_cred; /* security override for accessing cache */
75 struct mutex daemon_mutex; /* command serialisation mutex */
76 wait_queue_head_t daemon_pollwq; /* poll waitqueue for daemon */
77 atomic_t gravecounter; /* graveyard uniquifier */
78 atomic_t f_released; /* number of objects released lately */
79 atomic_long_t b_released; /* number of blocks released lately */
80 atomic_long_t b_writing; /* Number of blocks being written */
81 unsigned frun_percent; /* when to stop culling (% files) */
82 unsigned fcull_percent; /* when to start culling (% files) */
83 unsigned fstop_percent; /* when to stop allocating (% files) */
84 unsigned brun_percent; /* when to stop culling (% blocks) */
85 unsigned bcull_percent; /* when to start culling (% blocks) */
86 unsigned bstop_percent; /* when to stop allocating (% blocks) */
87 unsigned bsize; /* cache's block size */
88 unsigned bshift; /* ilog2(bsize) */
89 uint64_t frun; /* when to stop culling */
90 uint64_t fcull; /* when to start culling */
91 uint64_t fstop; /* when to stop allocating */
92 sector_t brun; /* when to stop culling */
93 sector_t bcull; /* when to start culling */
94 sector_t bstop; /* when to stop allocating */
95 unsigned long flags;
96#define CACHEFILES_READY 0 /* T if cache prepared */
97#define CACHEFILES_DEAD 1 /* T if cache dead */
98#define CACHEFILES_CULLING 2 /* T if cull engaged */
99#define CACHEFILES_STATE_CHANGED 3 /* T if state changed (poll trigger) */
100 char *rootdirname; /* name of cache root directory */
101 char *tag; /* cache binding tag */
102 u32 secid; /* LSM security id */
103 bool have_secid; /* whether "secid" was set */
104};
105
106#include <trace/events/cachefiles.h>
107
108static inline
109struct file *cachefiles_cres_file(struct netfs_cache_resources *cres)
110{
111 return cres->cache_priv2;
112}
113
114static inline
115struct cachefiles_object *cachefiles_cres_object(struct netfs_cache_resources *cres)
116{
117 return fscache_cres_cookie(cres)->cache_priv;
118}
119
120/*
121 * note change of state for daemon
122 */
123static inline void cachefiles_state_changed(struct cachefiles_cache *cache)
124{
125 set_bit(CACHEFILES_STATE_CHANGED, &cache->flags);
126 wake_up_all(&cache->daemon_pollwq);
127}
128
129/*
130 * cache.c
131 */
132extern int cachefiles_add_cache(struct cachefiles_cache *cache);
133extern void cachefiles_withdraw_cache(struct cachefiles_cache *cache);
134
135enum cachefiles_has_space_for {
136 cachefiles_has_space_check,
137 cachefiles_has_space_for_write,
138 cachefiles_has_space_for_create,
139};
140extern int cachefiles_has_space(struct cachefiles_cache *cache,
141 unsigned fnr, unsigned bnr,
142 enum cachefiles_has_space_for reason);
143
144/*
145 * daemon.c
146 */
147extern const struct file_operations cachefiles_daemon_fops;
148
149/*
150 * error_inject.c
151 */
152#ifdef CONFIG_CACHEFILES_ERROR_INJECTION
153extern unsigned int cachefiles_error_injection_state;
154extern int cachefiles_register_error_injection(void);
155extern void cachefiles_unregister_error_injection(void);
156
157#else
158#define cachefiles_error_injection_state 0
159
160static inline int cachefiles_register_error_injection(void)
161{
162 return 0;
163}
164
165static inline void cachefiles_unregister_error_injection(void)
166{
167}
168#endif
169
170
171static inline int cachefiles_inject_read_error(void)
172{
173 return cachefiles_error_injection_state & 2 ? -EIO : 0;
174}
175
176static inline int cachefiles_inject_write_error(void)
177{
178 return cachefiles_error_injection_state & 2 ? -EIO :
179 cachefiles_error_injection_state & 1 ? -ENOSPC :
180 0;
181}
182
183static inline int cachefiles_inject_remove_error(void)
184{
185 return cachefiles_error_injection_state & 2 ? -EIO : 0;
186}
187
188/*
189 * interface.c
190 */
191extern const struct fscache_cache_ops cachefiles_cache_ops;
192extern void cachefiles_see_object(struct cachefiles_object *object,
193 enum cachefiles_obj_ref_trace why);
194extern struct cachefiles_object *cachefiles_grab_object(struct cachefiles_object *object,
195 enum cachefiles_obj_ref_trace why);
196extern void cachefiles_put_object(struct cachefiles_object *object,
197 enum cachefiles_obj_ref_trace why);
198
199/*
200 * io.c
201 */
202extern bool cachefiles_begin_operation(struct netfs_cache_resources *cres,
203 enum fscache_want_state want_state);
204extern int __cachefiles_prepare_write(struct cachefiles_object *object,
205 struct file *file,
206 loff_t *_start, size_t *_len, size_t upper_len,
207 bool no_space_allocated_yet);
208extern int __cachefiles_write(struct cachefiles_object *object,
209 struct file *file,
210 loff_t start_pos,
211 struct iov_iter *iter,
212 netfs_io_terminated_t term_func,
213 void *term_func_priv);
214
215/*
216 * key.c
217 */
218extern bool cachefiles_cook_key(struct cachefiles_object *object);
219
220/*
221 * main.c
222 */
223extern struct kmem_cache *cachefiles_object_jar;
224
225/*
226 * namei.c
227 */
228extern void cachefiles_unmark_inode_in_use(struct cachefiles_object *object,
229 struct file *file);
230extern int cachefiles_bury_object(struct cachefiles_cache *cache,
231 struct cachefiles_object *object,
232 struct dentry *dir,
233 struct dentry *rep,
234 enum fscache_why_object_killed why);
235extern int cachefiles_delete_object(struct cachefiles_object *object,
236 enum fscache_why_object_killed why);
237extern bool cachefiles_look_up_object(struct cachefiles_object *object);
238extern struct dentry *cachefiles_get_directory(struct cachefiles_cache *cache,
239 struct dentry *dir,
240 const char *name,
241 bool *_is_new);
242extern void cachefiles_put_directory(struct dentry *dir);
243
244extern int cachefiles_cull(struct cachefiles_cache *cache, struct dentry *dir,
245 char *filename);
246
247extern int cachefiles_check_in_use(struct cachefiles_cache *cache,
248 struct dentry *dir, char *filename);
249extern struct file *cachefiles_create_tmpfile(struct cachefiles_object *object);
250extern bool cachefiles_commit_tmpfile(struct cachefiles_cache *cache,
251 struct cachefiles_object *object);
252
253/*
254 * security.c
255 */
256extern int cachefiles_get_security_ID(struct cachefiles_cache *cache);
257extern int cachefiles_determine_cache_security(struct cachefiles_cache *cache,
258 struct dentry *root,
259 const struct cred **_saved_cred);
260
261static inline void cachefiles_begin_secure(struct cachefiles_cache *cache,
262 const struct cred **_saved_cred)
263{
264 *_saved_cred = override_creds(cache->cache_cred);
265}
266
267static inline void cachefiles_end_secure(struct cachefiles_cache *cache,
268 const struct cred *saved_cred)
269{
270 revert_creds(saved_cred);
271}
272
273/*
274 * volume.c
275 */
276void cachefiles_acquire_volume(struct fscache_volume *volume);
277void cachefiles_free_volume(struct fscache_volume *volume);
278void cachefiles_withdraw_volume(struct cachefiles_volume *volume);
279
280/*
281 * xattr.c
282 */
283extern int cachefiles_set_object_xattr(struct cachefiles_object *object);
284extern int cachefiles_check_auxdata(struct cachefiles_object *object,
285 struct file *file);
286extern int cachefiles_remove_object_xattr(struct cachefiles_cache *cache,
287 struct cachefiles_object *object,
288 struct dentry *dentry);
289extern void cachefiles_prepare_to_write(struct fscache_cookie *cookie);
290extern bool cachefiles_set_volume_xattr(struct cachefiles_volume *volume);
291extern int cachefiles_check_volume_xattr(struct cachefiles_volume *volume);
292
293/*
294 * Error handling
295 */
296#define cachefiles_io_error(___cache, FMT, ...) \
297do { \
298 pr_err("I/O Error: " FMT"\n", ##__VA_ARGS__); \
299 fscache_io_error((___cache)->cache); \
300 set_bit(CACHEFILES_DEAD, &(___cache)->flags); \
301} while (0)
302
303#define cachefiles_io_error_obj(object, FMT, ...) \
304do { \
305 struct cachefiles_cache *___cache; \
306 \
307 ___cache = (object)->volume->cache; \
308 cachefiles_io_error(___cache, FMT " [o=%08x]", ##__VA_ARGS__, \
309 (object)->debug_id); \
310} while (0)
311
312
313/*
314 * Debug tracing
315 */
316extern unsigned cachefiles_debug;
317#define CACHEFILES_DEBUG_KENTER 1
318#define CACHEFILES_DEBUG_KLEAVE 2
319#define CACHEFILES_DEBUG_KDEBUG 4
320
321#define dbgprintk(FMT, ...) \
322 printk(KERN_DEBUG "[%-6.6s] "FMT"\n", current->comm, ##__VA_ARGS__)
323
324#define kenter(FMT, ...) dbgprintk("==> %s("FMT")", __func__, ##__VA_ARGS__)
325#define kleave(FMT, ...) dbgprintk("<== %s()"FMT"", __func__, ##__VA_ARGS__)
326#define kdebug(FMT, ...) dbgprintk(FMT, ##__VA_ARGS__)
327
328
329#if defined(__KDEBUG)
330#define _enter(FMT, ...) kenter(FMT, ##__VA_ARGS__)
331#define _leave(FMT, ...) kleave(FMT, ##__VA_ARGS__)
332#define _debug(FMT, ...) kdebug(FMT, ##__VA_ARGS__)
333
334#elif defined(CONFIG_CACHEFILES_DEBUG)
335#define _enter(FMT, ...) \
336do { \
337 if (cachefiles_debug & CACHEFILES_DEBUG_KENTER) \
338 kenter(FMT, ##__VA_ARGS__); \
339} while (0)
340
341#define _leave(FMT, ...) \
342do { \
343 if (cachefiles_debug & CACHEFILES_DEBUG_KLEAVE) \
344 kleave(FMT, ##__VA_ARGS__); \
345} while (0)
346
347#define _debug(FMT, ...) \
348do { \
349 if (cachefiles_debug & CACHEFILES_DEBUG_KDEBUG) \
350 kdebug(FMT, ##__VA_ARGS__); \
351} while (0)
352
353#else
354#define _enter(FMT, ...) no_printk("==> %s("FMT")", __func__, ##__VA_ARGS__)
355#define _leave(FMT, ...) no_printk("<== %s()"FMT"", __func__, ##__VA_ARGS__)
356#define _debug(FMT, ...) no_printk(FMT, ##__VA_ARGS__)
357#endif
358
359#if 1 /* defined(__KDEBUGALL) */
360
361#define ASSERT(X) \
362do { \
363 if (unlikely(!(X))) { \
364 pr_err("\n"); \
365 pr_err("Assertion failed\n"); \
366 BUG(); \
367 } \
368} while (0)
369
370#define ASSERTCMP(X, OP, Y) \
371do { \
372 if (unlikely(!((X) OP (Y)))) { \
373 pr_err("\n"); \
374 pr_err("Assertion failed\n"); \
375 pr_err("%lx " #OP " %lx is false\n", \
376 (unsigned long)(X), (unsigned long)(Y)); \
377 BUG(); \
378 } \
379} while (0)
380
381#define ASSERTIF(C, X) \
382do { \
383 if (unlikely((C) && !(X))) { \
384 pr_err("\n"); \
385 pr_err("Assertion failed\n"); \
386 BUG(); \
387 } \
388} while (0)
389
390#define ASSERTIFCMP(C, X, OP, Y) \
391do { \
392 if (unlikely((C) && !((X) OP (Y)))) { \
393 pr_err("\n"); \
394 pr_err("Assertion failed\n"); \
395 pr_err("%lx " #OP " %lx is false\n", \
396 (unsigned long)(X), (unsigned long)(Y)); \
397 BUG(); \
398 } \
399} while (0)
400
401#else
402
403#define ASSERT(X) do {} while (0)
404#define ASSERTCMP(X, OP, Y) do {} while (0)
405#define ASSERTIF(C, X) do {} while (0)
406#define ASSERTIFCMP(C, X, OP, Y) do {} while (0)
407
408#endif