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