Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

FS-Cache: Count culled objects and objects rejected due to lack of space

Count the number of objects that get culled by the cache backend and the
number of objects that the cache backend declines to instantiate due to lack
of space in the cache.

These numbers are made available through /proc/fs/fscache/stats

Signed-off-by: David Howells <dhowells@redhat.com>
Reviewed-by: Steve Dickson <steved@redhat.com>
Acked-by: Jeff Layton <jeff.layton@primarydata.com>

+122 -13
+23
Documentation/filesystems/caching/backend-api.txt
··· 676 676 as possible. 677 677 678 678 679 + (*) Indicate that a stale object was found and discarded: 680 + 681 + void fscache_object_retrying_stale(struct fscache_object *object); 682 + 683 + This is called to indicate that the lookup procedure found an object in 684 + the cache that the netfs decided was stale. The object has been 685 + discarded from the cache and the lookup will be performed again. 686 + 687 + 688 + (*) Indicate that the caching backend killed an object: 689 + 690 + void fscache_object_mark_killed(struct fscache_object *object, 691 + enum fscache_why_object_killed why); 692 + 693 + This is called to indicate that the cache backend preemptively killed an 694 + object. The why parameter should be set to indicate the reason: 695 + 696 + FSCACHE_OBJECT_IS_STALE - the object was stale and needs discarding. 697 + FSCACHE_OBJECT_NO_SPACE - there was insufficient cache space 698 + FSCACHE_OBJECT_WAS_RETIRED - the object was retired when relinquished. 699 + FSCACHE_OBJECT_WAS_CULLED - the object was culled to make space. 700 + 701 + 679 702 (*) Get and release references on a retrieval record: 680 703 681 704 void fscache_get_retrieval(struct fscache_retrieval *op);
+4
Documentation/filesystems/caching/fscache.txt
··· 303 303 wrp=N Number of in-progress write_page() cache ops 304 304 ucp=N Number of in-progress uncache_page() cache ops 305 305 dsp=N Number of in-progress dissociate_pages() cache ops 306 + CacheEv nsp=N Number of object lookups/creations rejected due to lack of space 307 + stl=N Number of stale objects deleted 308 + rtr=N Number of objects retired when relinquished 309 + cul=N Number of objects culled 306 310 307 311 308 312 (*) /proc/fs/fscache/histogram
-1
fs/cachefiles/internal.h
··· 43 43 loff_t i_size; /* object size */ 44 44 unsigned long flags; 45 45 #define CACHEFILES_OBJECT_ACTIVE 0 /* T if marked active */ 46 - #define CACHEFILES_OBJECT_BURIED 1 /* T if preemptively buried */ 47 46 atomic_t usage; /* object usage count */ 48 47 uint8_t type; /* object type */ 49 48 uint8_t new; /* T if object new */
+21 -12
fs/cachefiles/namei.c
··· 97 97 * call vfs_unlink(), vfs_rmdir() or vfs_rename() 98 98 */ 99 99 static void cachefiles_mark_object_buried(struct cachefiles_cache *cache, 100 - struct dentry *dentry) 100 + struct dentry *dentry, 101 + enum fscache_why_object_killed why) 101 102 { 102 103 struct cachefiles_object *object; 103 104 struct rb_node *p; ··· 133 132 pr_err("\n"); 134 133 pr_err("Error: Can't preemptively bury live object\n"); 135 134 cachefiles_printk_object(object, NULL); 136 - } else if (test_and_set_bit(CACHEFILES_OBJECT_BURIED, &object->flags)) { 137 - pr_err("Error: Object already preemptively buried\n"); 135 + } else { 136 + if (why != FSCACHE_OBJECT_IS_STALE) 137 + fscache_object_mark_killed(&object->fscache, why); 138 138 } 139 139 140 140 write_unlock(&cache->active_lock); ··· 267 265 static int cachefiles_bury_object(struct cachefiles_cache *cache, 268 266 struct dentry *dir, 269 267 struct dentry *rep, 270 - bool preemptive) 268 + bool preemptive, 269 + enum fscache_why_object_killed why) 271 270 { 272 271 struct dentry *grave, *trap; 273 272 struct path path, path_to_graveyard; ··· 292 289 ret = vfs_unlink(dir->d_inode, rep, NULL); 293 290 294 291 if (preemptive) 295 - cachefiles_mark_object_buried(cache, rep); 292 + cachefiles_mark_object_buried(cache, rep, why); 296 293 } 297 294 298 295 mutex_unlock(&dir->d_inode->i_mutex); ··· 397 394 "Rename failed with error %d", ret); 398 395 399 396 if (preemptive) 400 - cachefiles_mark_object_buried(cache, rep); 397 + cachefiles_mark_object_buried(cache, rep, why); 401 398 } 402 399 403 400 unlock_rename(cache->graveyard, dir); ··· 425 422 426 423 mutex_lock_nested(&dir->d_inode->i_mutex, I_MUTEX_PARENT); 427 424 428 - if (test_bit(CACHEFILES_OBJECT_BURIED, &object->flags)) { 425 + if (test_bit(FSCACHE_OBJECT_KILLED_BY_CACHE, &object->fscache.flags)) { 429 426 /* object allocation for the same key preemptively deleted this 430 427 * object's file so that it could create its own file */ 431 428 _debug("object preemptively buried"); ··· 436 433 * may have been renamed */ 437 434 if (dir == object->dentry->d_parent) { 438 435 ret = cachefiles_bury_object(cache, dir, 439 - object->dentry, false); 436 + object->dentry, false, 437 + FSCACHE_OBJECT_WAS_RETIRED); 440 438 } else { 441 439 /* it got moved, presumably by cachefilesd culling it, 442 440 * so it's no longer in the key path and we can ignore ··· 526 522 if (!next->d_inode) { 527 523 ret = cachefiles_has_space(cache, 1, 0); 528 524 if (ret < 0) 529 - goto create_error; 525 + goto no_space_error; 530 526 531 527 path.dentry = dir; 532 528 ret = security_path_mkdir(&path, next, 0); ··· 555 551 if (!next->d_inode) { 556 552 ret = cachefiles_has_space(cache, 1, 0); 557 553 if (ret < 0) 558 - goto create_error; 554 + goto no_space_error; 559 555 560 556 path.dentry = dir; 561 557 ret = security_path_mknod(&path, next, S_IFREG, 0); ··· 606 602 * mutex) */ 607 603 object->dentry = NULL; 608 604 609 - ret = cachefiles_bury_object(cache, dir, next, true); 605 + ret = cachefiles_bury_object(cache, dir, next, true, 606 + FSCACHE_OBJECT_IS_STALE); 610 607 dput(next); 611 608 next = NULL; 612 609 ··· 615 610 goto delete_error; 616 611 617 612 _debug("redo lookup"); 613 + fscache_object_retrying_stale(&object->fscache); 618 614 goto lookup_again; 619 615 } 620 616 } ··· 668 662 _leave(" = 0 [%lu]", object->dentry->d_inode->i_ino); 669 663 return 0; 670 664 665 + no_space_error: 666 + fscache_object_mark_killed(&object->fscache, FSCACHE_OBJECT_NO_SPACE); 671 667 create_error: 672 668 _debug("create error %d", ret); 673 669 if (ret == -EIO) ··· 935 927 /* actually remove the victim (drops the dir mutex) */ 936 928 _debug("bury"); 937 929 938 - ret = cachefiles_bury_object(cache, dir, victim, false); 930 + ret = cachefiles_bury_object(cache, dir, victim, false, 931 + FSCACHE_OBJECT_WAS_CULLED); 939 932 if (ret < 0) 940 933 goto error; 941 934
+5
fs/fscache/internal.h
··· 271 271 extern atomic_t fscache_n_cop_uncache_page; 272 272 extern atomic_t fscache_n_cop_dissociate_pages; 273 273 274 + extern atomic_t fscache_n_cache_no_space_reject; 275 + extern atomic_t fscache_n_cache_stale_objects; 276 + extern atomic_t fscache_n_cache_retired_objects; 277 + extern atomic_t fscache_n_cache_culled_objects; 278 + 274 279 static inline void fscache_stat(atomic_t *stat) 275 280 { 276 281 atomic_inc(stat);
+47
fs/fscache/object.c
··· 1016 1016 _leave(""); 1017 1017 return transit_to(WAIT_FOR_CMD); 1018 1018 } 1019 + 1020 + /** 1021 + * fscache_object_retrying_stale - Note retrying stale object 1022 + * @object: The object that will be retried 1023 + * 1024 + * Note that an object lookup found an on-disk object that was adjudged to be 1025 + * stale and has been deleted. The lookup will be retried. 1026 + */ 1027 + void fscache_object_retrying_stale(struct fscache_object *object) 1028 + { 1029 + fscache_stat(&fscache_n_cache_no_space_reject); 1030 + } 1031 + EXPORT_SYMBOL(fscache_object_retrying_stale); 1032 + 1033 + /** 1034 + * fscache_object_mark_killed - Note that an object was killed 1035 + * @object: The object that was culled 1036 + * @why: The reason the object was killed. 1037 + * 1038 + * Note that an object was killed. Returns true if the object was 1039 + * already marked killed, false if it wasn't. 1040 + */ 1041 + void fscache_object_mark_killed(struct fscache_object *object, 1042 + enum fscache_why_object_killed why) 1043 + { 1044 + if (test_and_set_bit(FSCACHE_OBJECT_KILLED_BY_CACHE, &object->flags)) { 1045 + pr_err("Error: Object already killed by cache [%s]\n", 1046 + object->cache->identifier); 1047 + return; 1048 + } 1049 + 1050 + switch (why) { 1051 + case FSCACHE_OBJECT_NO_SPACE: 1052 + fscache_stat(&fscache_n_cache_no_space_reject); 1053 + break; 1054 + case FSCACHE_OBJECT_IS_STALE: 1055 + fscache_stat(&fscache_n_cache_stale_objects); 1056 + break; 1057 + case FSCACHE_OBJECT_WAS_RETIRED: 1058 + fscache_stat(&fscache_n_cache_retired_objects); 1059 + break; 1060 + case FSCACHE_OBJECT_WAS_CULLED: 1061 + fscache_stat(&fscache_n_cache_culled_objects); 1062 + break; 1063 + } 1064 + } 1065 + EXPORT_SYMBOL(fscache_object_mark_killed);
+10
fs/fscache/stats.c
··· 130 130 atomic_t fscache_n_cop_uncache_page; 131 131 atomic_t fscache_n_cop_dissociate_pages; 132 132 133 + atomic_t fscache_n_cache_no_space_reject; 134 + atomic_t fscache_n_cache_stale_objects; 135 + atomic_t fscache_n_cache_retired_objects; 136 + atomic_t fscache_n_cache_culled_objects; 137 + 133 138 /* 134 139 * display the general statistics 135 140 */ ··· 276 271 atomic_read(&fscache_n_cop_write_page), 277 272 atomic_read(&fscache_n_cop_uncache_page), 278 273 atomic_read(&fscache_n_cop_dissociate_pages)); 274 + seq_printf(m, "CacheEv: nsp=%d stl=%d rtr=%d cul=%d\n", 275 + atomic_read(&fscache_n_cache_no_space_reject), 276 + atomic_read(&fscache_n_cache_stale_objects), 277 + atomic_read(&fscache_n_cache_retired_objects), 278 + atomic_read(&fscache_n_cache_culled_objects)); 279 279 return 0; 280 280 } 281 281
+12
include/linux/fscache-cache.h
··· 371 371 #define FSCACHE_OBJECT_IS_LOOKED_UP 4 /* T if object has been looked up */ 372 372 #define FSCACHE_OBJECT_IS_AVAILABLE 5 /* T if object has become active */ 373 373 #define FSCACHE_OBJECT_RETIRED 6 /* T if object was retired on relinquishment */ 374 + #define FSCACHE_OBJECT_KILLED_BY_CACHE 7 /* T if object was killed by the cache */ 374 375 375 376 struct list_head cache_link; /* link in cache->object_list */ 376 377 struct hlist_node cookie_link; /* link in cookie->backing_objects */ ··· 551 550 extern enum fscache_checkaux fscache_check_aux(struct fscache_object *object, 552 551 const void *data, 553 552 uint16_t datalen); 553 + 554 + extern void fscache_object_retrying_stale(struct fscache_object *object); 555 + 556 + enum fscache_why_object_killed { 557 + FSCACHE_OBJECT_IS_STALE, 558 + FSCACHE_OBJECT_NO_SPACE, 559 + FSCACHE_OBJECT_WAS_RETIRED, 560 + FSCACHE_OBJECT_WAS_CULLED, 561 + }; 562 + extern void fscache_object_mark_killed(struct fscache_object *object, 563 + enum fscache_why_object_killed why); 554 564 555 565 #endif /* _LINUX_FSCACHE_CACHE_H */