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