Branch data Line data Source code
1 : : /* SPDX-License-Identifier: GPL-2.0-or-later */ 2 : : /* Internal definitions for FS-Cache 3 : : * 4 : : * Copyright (C) 2004-2007 Red Hat, Inc. All Rights Reserved. 5 : : * Written by David Howells (dhowells@redhat.com) 6 : : */ 7 : : 8 : : /* 9 : : * Lock order, in the order in which multiple locks should be obtained: 10 : : * - fscache_addremove_sem 11 : : * - cookie->lock 12 : : * - cookie->parent->lock 13 : : * - cache->object_list_lock 14 : : * - object->lock 15 : : * - object->parent->lock 16 : : * - cookie->stores_lock 17 : : * - fscache_thread_lock 18 : : * 19 : : */ 20 : : 21 : : #ifdef pr_fmt 22 : : #undef pr_fmt 23 : : #endif 24 : : 25 : : #define pr_fmt(fmt) "FS-Cache: " fmt 26 : : 27 : : #include <linux/fscache-cache.h> 28 : : #include <trace/events/fscache.h> 29 : : #include <linux/sched.h> 30 : : #include <linux/seq_file.h> 31 : : 32 : : #define FSCACHE_MIN_THREADS 4 33 : : #define FSCACHE_MAX_THREADS 32 34 : : 35 : : /* 36 : : * cache.c 37 : : */ 38 : : extern struct list_head fscache_cache_list; 39 : : extern struct rw_semaphore fscache_addremove_sem; 40 : : 41 : : extern struct fscache_cache *fscache_select_cache_for_object( 42 : : struct fscache_cookie *); 43 : : 44 : : /* 45 : : * cookie.c 46 : : */ 47 : : extern struct kmem_cache *fscache_cookie_jar; 48 : : 49 : : extern void fscache_free_cookie(struct fscache_cookie *); 50 : : extern struct fscache_cookie *fscache_alloc_cookie(struct fscache_cookie *, 51 : : const struct fscache_cookie_def *, 52 : : const void *, size_t, 53 : : const void *, size_t, 54 : : void *, loff_t); 55 : : extern struct fscache_cookie *fscache_hash_cookie(struct fscache_cookie *); 56 : : extern void fscache_cookie_put(struct fscache_cookie *, 57 : : enum fscache_cookie_trace); 58 : : 59 : : /* 60 : : * fsdef.c 61 : : */ 62 : : extern struct fscache_cookie fscache_fsdef_index; 63 : : extern struct fscache_cookie_def fscache_fsdef_netfs_def; 64 : : 65 : : /* 66 : : * histogram.c 67 : : */ 68 : : #ifdef CONFIG_FSCACHE_HISTOGRAM 69 : : extern atomic_t fscache_obj_instantiate_histogram[HZ]; 70 : : extern atomic_t fscache_objs_histogram[HZ]; 71 : : extern atomic_t fscache_ops_histogram[HZ]; 72 : : extern atomic_t fscache_retrieval_delay_histogram[HZ]; 73 : : extern atomic_t fscache_retrieval_histogram[HZ]; 74 : : 75 : 0 : static inline void fscache_hist(atomic_t histogram[], unsigned long start_jif) 76 : : { 77 : 0 : unsigned long jif = jiffies - start_jif; 78 : 0 : if (jif >= HZ) 79 : : jif = HZ - 1; 80 : 0 : atomic_inc(&histogram[jif]); 81 : 0 : } 82 : : 83 : : extern const struct seq_operations fscache_histogram_ops; 84 : : 85 : : #else 86 : : #define fscache_hist(hist, start_jif) do {} while (0) 87 : : #endif 88 : : 89 : : /* 90 : : * main.c 91 : : */ 92 : : extern unsigned fscache_defer_lookup; 93 : : extern unsigned fscache_defer_create; 94 : : extern unsigned fscache_debug; 95 : : extern struct kobject *fscache_root; 96 : : extern struct workqueue_struct *fscache_object_wq; 97 : : extern struct workqueue_struct *fscache_op_wq; 98 : : DECLARE_PER_CPU(wait_queue_head_t, fscache_object_cong_wait); 99 : : 100 : : static inline bool fscache_object_congested(void) 101 : : { 102 : 0 : return workqueue_congested(WORK_CPU_UNBOUND, fscache_object_wq); 103 : : } 104 : : 105 : : /* 106 : : * object.c 107 : : */ 108 : : extern void fscache_enqueue_object(struct fscache_object *); 109 : : 110 : : /* 111 : : * object-list.c 112 : : */ 113 : : #ifdef CONFIG_FSCACHE_OBJECT_LIST 114 : : extern const struct file_operations fscache_objlist_fops; 115 : : 116 : : extern void fscache_objlist_add(struct fscache_object *); 117 : : extern void fscache_objlist_remove(struct fscache_object *); 118 : : #else 119 : : #define fscache_objlist_add(object) do {} while(0) 120 : : #define fscache_objlist_remove(object) do {} while(0) 121 : : #endif 122 : : 123 : : /* 124 : : * operation.c 125 : : */ 126 : : extern int fscache_submit_exclusive_op(struct fscache_object *, 127 : : struct fscache_operation *); 128 : : extern int fscache_submit_op(struct fscache_object *, 129 : : struct fscache_operation *); 130 : : extern int fscache_cancel_op(struct fscache_operation *, bool); 131 : : extern void fscache_cancel_all_ops(struct fscache_object *); 132 : : extern void fscache_abort_object(struct fscache_object *); 133 : : extern void fscache_start_operations(struct fscache_object *); 134 : : extern void fscache_operation_gc(struct work_struct *); 135 : : 136 : : /* 137 : : * page.c 138 : : */ 139 : : extern int fscache_wait_for_deferred_lookup(struct fscache_cookie *); 140 : : extern int fscache_wait_for_operation_activation(struct fscache_object *, 141 : : struct fscache_operation *, 142 : : atomic_t *, 143 : : atomic_t *); 144 : : extern void fscache_invalidate_writes(struct fscache_cookie *); 145 : : 146 : : /* 147 : : * proc.c 148 : : */ 149 : : #ifdef CONFIG_PROC_FS 150 : : extern int __init fscache_proc_init(void); 151 : : extern void fscache_proc_cleanup(void); 152 : : #else 153 : : #define fscache_proc_init() (0) 154 : : #define fscache_proc_cleanup() do {} while (0) 155 : : #endif 156 : : 157 : : /* 158 : : * stats.c 159 : : */ 160 : : #ifdef CONFIG_FSCACHE_STATS 161 : : extern atomic_t fscache_n_ops_processed[FSCACHE_MAX_THREADS]; 162 : : extern atomic_t fscache_n_objs_processed[FSCACHE_MAX_THREADS]; 163 : : 164 : : extern atomic_t fscache_n_op_pend; 165 : : extern atomic_t fscache_n_op_run; 166 : : extern atomic_t fscache_n_op_enqueue; 167 : : extern atomic_t fscache_n_op_deferred_release; 168 : : extern atomic_t fscache_n_op_initialised; 169 : : extern atomic_t fscache_n_op_release; 170 : : extern atomic_t fscache_n_op_gc; 171 : : extern atomic_t fscache_n_op_cancelled; 172 : : extern atomic_t fscache_n_op_rejected; 173 : : 174 : : extern atomic_t fscache_n_attr_changed; 175 : : extern atomic_t fscache_n_attr_changed_ok; 176 : : extern atomic_t fscache_n_attr_changed_nobufs; 177 : : extern atomic_t fscache_n_attr_changed_nomem; 178 : : extern atomic_t fscache_n_attr_changed_calls; 179 : : 180 : : extern atomic_t fscache_n_allocs; 181 : : extern atomic_t fscache_n_allocs_ok; 182 : : extern atomic_t fscache_n_allocs_wait; 183 : : extern atomic_t fscache_n_allocs_nobufs; 184 : : extern atomic_t fscache_n_allocs_intr; 185 : : extern atomic_t fscache_n_allocs_object_dead; 186 : : extern atomic_t fscache_n_alloc_ops; 187 : : extern atomic_t fscache_n_alloc_op_waits; 188 : : 189 : : extern atomic_t fscache_n_retrievals; 190 : : extern atomic_t fscache_n_retrievals_ok; 191 : : extern atomic_t fscache_n_retrievals_wait; 192 : : extern atomic_t fscache_n_retrievals_nodata; 193 : : extern atomic_t fscache_n_retrievals_nobufs; 194 : : extern atomic_t fscache_n_retrievals_intr; 195 : : extern atomic_t fscache_n_retrievals_nomem; 196 : : extern atomic_t fscache_n_retrievals_object_dead; 197 : : extern atomic_t fscache_n_retrieval_ops; 198 : : extern atomic_t fscache_n_retrieval_op_waits; 199 : : 200 : : extern atomic_t fscache_n_stores; 201 : : extern atomic_t fscache_n_stores_ok; 202 : : extern atomic_t fscache_n_stores_again; 203 : : extern atomic_t fscache_n_stores_nobufs; 204 : : extern atomic_t fscache_n_stores_oom; 205 : : extern atomic_t fscache_n_store_ops; 206 : : extern atomic_t fscache_n_store_calls; 207 : : extern atomic_t fscache_n_store_pages; 208 : : extern atomic_t fscache_n_store_radix_deletes; 209 : : extern atomic_t fscache_n_store_pages_over_limit; 210 : : 211 : : extern atomic_t fscache_n_store_vmscan_not_storing; 212 : : extern atomic_t fscache_n_store_vmscan_gone; 213 : : extern atomic_t fscache_n_store_vmscan_busy; 214 : : extern atomic_t fscache_n_store_vmscan_cancelled; 215 : : extern atomic_t fscache_n_store_vmscan_wait; 216 : : 217 : : extern atomic_t fscache_n_marks; 218 : : extern atomic_t fscache_n_uncaches; 219 : : 220 : : extern atomic_t fscache_n_acquires; 221 : : extern atomic_t fscache_n_acquires_null; 222 : : extern atomic_t fscache_n_acquires_no_cache; 223 : : extern atomic_t fscache_n_acquires_ok; 224 : : extern atomic_t fscache_n_acquires_nobufs; 225 : : extern atomic_t fscache_n_acquires_oom; 226 : : 227 : : extern atomic_t fscache_n_invalidates; 228 : : extern atomic_t fscache_n_invalidates_run; 229 : : 230 : : extern atomic_t fscache_n_updates; 231 : : extern atomic_t fscache_n_updates_null; 232 : : extern atomic_t fscache_n_updates_run; 233 : : 234 : : extern atomic_t fscache_n_relinquishes; 235 : : extern atomic_t fscache_n_relinquishes_null; 236 : : extern atomic_t fscache_n_relinquishes_waitcrt; 237 : : extern atomic_t fscache_n_relinquishes_retire; 238 : : 239 : : extern atomic_t fscache_n_cookie_index; 240 : : extern atomic_t fscache_n_cookie_data; 241 : : extern atomic_t fscache_n_cookie_special; 242 : : 243 : : extern atomic_t fscache_n_object_alloc; 244 : : extern atomic_t fscache_n_object_no_alloc; 245 : : extern atomic_t fscache_n_object_lookups; 246 : : extern atomic_t fscache_n_object_lookups_negative; 247 : : extern atomic_t fscache_n_object_lookups_positive; 248 : : extern atomic_t fscache_n_object_lookups_timed_out; 249 : : extern atomic_t fscache_n_object_created; 250 : : extern atomic_t fscache_n_object_avail; 251 : : extern atomic_t fscache_n_object_dead; 252 : : 253 : : extern atomic_t fscache_n_checkaux_none; 254 : : extern atomic_t fscache_n_checkaux_okay; 255 : : extern atomic_t fscache_n_checkaux_update; 256 : : extern atomic_t fscache_n_checkaux_obsolete; 257 : : 258 : : extern atomic_t fscache_n_cop_alloc_object; 259 : : extern atomic_t fscache_n_cop_lookup_object; 260 : : extern atomic_t fscache_n_cop_lookup_complete; 261 : : extern atomic_t fscache_n_cop_grab_object; 262 : : extern atomic_t fscache_n_cop_invalidate_object; 263 : : extern atomic_t fscache_n_cop_update_object; 264 : : extern atomic_t fscache_n_cop_drop_object; 265 : : extern atomic_t fscache_n_cop_put_object; 266 : : extern atomic_t fscache_n_cop_sync_cache; 267 : : extern atomic_t fscache_n_cop_attr_changed; 268 : : extern atomic_t fscache_n_cop_read_or_alloc_page; 269 : : extern atomic_t fscache_n_cop_read_or_alloc_pages; 270 : : extern atomic_t fscache_n_cop_allocate_page; 271 : : extern atomic_t fscache_n_cop_allocate_pages; 272 : : extern atomic_t fscache_n_cop_write_page; 273 : : extern atomic_t fscache_n_cop_uncache_page; 274 : : extern atomic_t fscache_n_cop_dissociate_pages; 275 : : 276 : : extern atomic_t fscache_n_cache_no_space_reject; 277 : : extern atomic_t fscache_n_cache_stale_objects; 278 : : extern atomic_t fscache_n_cache_retired_objects; 279 : : extern atomic_t fscache_n_cache_culled_objects; 280 : : 281 : : static inline void fscache_stat(atomic_t *stat) 282 : : { 283 : : atomic_inc(stat); 284 : : } 285 : : 286 : : static inline void fscache_stat_d(atomic_t *stat) 287 : : { 288 : : atomic_dec(stat); 289 : : } 290 : : 291 : : #define __fscache_stat(stat) (stat) 292 : : 293 : : int fscache_stats_show(struct seq_file *m, void *v); 294 : : #else 295 : : 296 : : #define __fscache_stat(stat) (NULL) 297 : : #define fscache_stat(stat) do {} while (0) 298 : : #define fscache_stat_d(stat) do {} while (0) 299 : : #endif 300 : : 301 : : /* 302 : : * raise an event on an object 303 : : * - if the event is not masked for that object, then the object is 304 : : * queued for attention by the thread pool. 305 : : */ 306 : 0 : static inline void fscache_raise_event(struct fscache_object *object, 307 : : unsigned event) 308 : : { 309 : 0 : BUG_ON(event >= NR_FSCACHE_OBJECT_EVENTS); 310 : : #if 0 311 : : printk("*** fscache_raise_event(OBJ%d{%lx},%x)\n", 312 : : object->debug_id, object->event_mask, (1 << event)); 313 : : #endif 314 : 0 : if (!test_and_set_bit(event, &object->events) && 315 : 0 : test_bit(event, &object->event_mask)) 316 : 0 : fscache_enqueue_object(object); 317 : 0 : } 318 : : 319 : 3 : static inline void fscache_cookie_get(struct fscache_cookie *cookie, 320 : : enum fscache_cookie_trace where) 321 : : { 322 : 3 : int usage = atomic_inc_return(&cookie->usage); 323 : : 324 : 3 : trace_fscache_cookie(cookie, where, usage); 325 : 3 : } 326 : : 327 : : /* 328 : : * get an extra reference to a netfs retrieval context 329 : : */ 330 : : static inline 331 : : void *fscache_get_context(struct fscache_cookie *cookie, void *context) 332 : : { 333 : 0 : if (cookie->def->get_context) 334 : 0 : cookie->def->get_context(cookie->netfs_data, context); 335 : : return context; 336 : : } 337 : : 338 : : /* 339 : : * release a reference to a netfs retrieval context 340 : : */ 341 : : static inline 342 : : void fscache_put_context(struct fscache_cookie *cookie, void *context) 343 : : { 344 : 0 : if (cookie->def->put_context) 345 : 0 : cookie->def->put_context(cookie->netfs_data, context); 346 : : } 347 : : 348 : : /* 349 : : * Update the auxiliary data on a cookie. 350 : : */ 351 : : static inline 352 : 0 : void fscache_update_aux(struct fscache_cookie *cookie, const void *aux_data) 353 : : { 354 : : void *p; 355 : : 356 : 0 : if (!aux_data) 357 : 0 : return; 358 : 0 : if (cookie->aux_len <= sizeof(cookie->inline_aux)) 359 : 0 : p = cookie->inline_aux; 360 : : else 361 : 0 : p = cookie->aux; 362 : : 363 : 0 : if (memcmp(p, aux_data, cookie->aux_len) != 0) { 364 : 0 : memcpy(p, aux_data, cookie->aux_len); 365 : 0 : set_bit(FSCACHE_COOKIE_AUX_UPDATED, &cookie->flags); 366 : : } 367 : : } 368 : : 369 : : /*****************************************************************************/ 370 : : /* 371 : : * debug tracing 372 : : */ 373 : : #define dbgprintk(FMT, ...) \ 374 : : printk(KERN_DEBUG "[%-6.6s] "FMT"\n", current->comm, ##__VA_ARGS__) 375 : : 376 : : #define kenter(FMT, ...) dbgprintk("==> %s("FMT")", __func__, ##__VA_ARGS__) 377 : : #define kleave(FMT, ...) dbgprintk("<== %s()"FMT"", __func__, ##__VA_ARGS__) 378 : : #define kdebug(FMT, ...) dbgprintk(FMT, ##__VA_ARGS__) 379 : : 380 : : #define kjournal(FMT, ...) no_printk(FMT, ##__VA_ARGS__) 381 : : 382 : : #ifdef __KDEBUG 383 : : #define _enter(FMT, ...) kenter(FMT, ##__VA_ARGS__) 384 : : #define _leave(FMT, ...) kleave(FMT, ##__VA_ARGS__) 385 : : #define _debug(FMT, ...) kdebug(FMT, ##__VA_ARGS__) 386 : : 387 : : #elif defined(CONFIG_FSCACHE_DEBUG) 388 : : #define _enter(FMT, ...) \ 389 : : do { \ 390 : : if (__do_kdebug(ENTER)) \ 391 : : kenter(FMT, ##__VA_ARGS__); \ 392 : : } while (0) 393 : : 394 : : #define _leave(FMT, ...) \ 395 : : do { \ 396 : : if (__do_kdebug(LEAVE)) \ 397 : : kleave(FMT, ##__VA_ARGS__); \ 398 : : } while (0) 399 : : 400 : : #define _debug(FMT, ...) \ 401 : : do { \ 402 : : if (__do_kdebug(DEBUG)) \ 403 : : kdebug(FMT, ##__VA_ARGS__); \ 404 : : } while (0) 405 : : 406 : : #else 407 : : #define _enter(FMT, ...) no_printk("==> %s("FMT")", __func__, ##__VA_ARGS__) 408 : : #define _leave(FMT, ...) no_printk("<== %s()"FMT"", __func__, ##__VA_ARGS__) 409 : : #define _debug(FMT, ...) no_printk(FMT, ##__VA_ARGS__) 410 : : #endif 411 : : 412 : : /* 413 : : * determine whether a particular optional debugging point should be logged 414 : : * - we need to go through three steps to persuade cpp to correctly join the 415 : : * shorthand in FSCACHE_DEBUG_LEVEL with its prefix 416 : : */ 417 : : #define ____do_kdebug(LEVEL, POINT) \ 418 : : unlikely((fscache_debug & \ 419 : : (FSCACHE_POINT_##POINT << (FSCACHE_DEBUG_ ## LEVEL * 3)))) 420 : : #define ___do_kdebug(LEVEL, POINT) \ 421 : : ____do_kdebug(LEVEL, POINT) 422 : : #define __do_kdebug(POINT) \ 423 : : ___do_kdebug(FSCACHE_DEBUG_LEVEL, POINT) 424 : : 425 : : #define FSCACHE_DEBUG_CACHE 0 426 : : #define FSCACHE_DEBUG_COOKIE 1 427 : : #define FSCACHE_DEBUG_PAGE 2 428 : : #define FSCACHE_DEBUG_OPERATION 3 429 : : 430 : : #define FSCACHE_POINT_ENTER 1 431 : : #define FSCACHE_POINT_LEAVE 2 432 : : #define FSCACHE_POINT_DEBUG 4 433 : : 434 : : #ifndef FSCACHE_DEBUG_LEVEL 435 : : #define FSCACHE_DEBUG_LEVEL CACHE 436 : : #endif 437 : : 438 : : /* 439 : : * assertions 440 : : */ 441 : : #if 1 /* defined(__KDEBUGALL) */ 442 : : 443 : : #define ASSERT(X) \ 444 : : do { \ 445 : : if (unlikely(!(X))) { \ 446 : : pr_err("\n"); \ 447 : : pr_err("Assertion failed\n"); \ 448 : : BUG(); \ 449 : : } \ 450 : : } while (0) 451 : : 452 : : #define ASSERTCMP(X, OP, Y) \ 453 : : do { \ 454 : : if (unlikely(!((X) OP (Y)))) { \ 455 : : pr_err("\n"); \ 456 : : pr_err("Assertion failed\n"); \ 457 : : pr_err("%lx " #OP " %lx is false\n", \ 458 : : (unsigned long)(X), (unsigned long)(Y)); \ 459 : : BUG(); \ 460 : : } \ 461 : : } while (0) 462 : : 463 : : #define ASSERTIF(C, X) \ 464 : : do { \ 465 : : if (unlikely((C) && !(X))) { \ 466 : : pr_err("\n"); \ 467 : : pr_err("Assertion failed\n"); \ 468 : : BUG(); \ 469 : : } \ 470 : : } while (0) 471 : : 472 : : #define ASSERTIFCMP(C, X, OP, Y) \ 473 : : do { \ 474 : : if (unlikely((C) && !((X) OP (Y)))) { \ 475 : : pr_err("\n"); \ 476 : : pr_err("Assertion failed\n"); \ 477 : : pr_err("%lx " #OP " %lx is false\n", \ 478 : : (unsigned long)(X), (unsigned long)(Y)); \ 479 : : BUG(); \ 480 : : } \ 481 : : } while (0) 482 : : 483 : : #else 484 : : 485 : : #define ASSERT(X) do {} while (0) 486 : : #define ASSERTCMP(X, OP, Y) do {} while (0) 487 : : #define ASSERTIF(C, X) do {} while (0) 488 : : #define ASSERTIFCMP(C, X, OP, Y) do {} while (0) 489 : : 490 : : #endif /* assert or not */