aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDavid Howells <dhowells@redhat.com>2015-02-19 18:47:31 -0500
committerDavid Howells <dhowells@redhat.com>2015-02-24 05:05:27 -0500
commit182d919b84902eece162c63ed3d476c8016b4197 (patch)
treec2f02f26cdcaa4718121c94e8b050a598fab5f8c
parentb2b89ebfc0f0287e20516a5443d93af309b800cf (diff)
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>
-rw-r--r--Documentation/filesystems/caching/backend-api.txt23
-rw-r--r--Documentation/filesystems/caching/fscache.txt4
-rw-r--r--fs/cachefiles/internal.h1
-rw-r--r--fs/cachefiles/namei.c33
-rw-r--r--fs/fscache/internal.h5
-rw-r--r--fs/fscache/object.c47
-rw-r--r--fs/fscache/stats.c10
-rw-r--r--include/linux/fscache-cache.h12
8 files changed, 122 insertions, 13 deletions
diff --git a/Documentation/filesystems/caching/backend-api.txt b/Documentation/filesystems/caching/backend-api.txt
index 277d1e810670..c0bd5677271b 100644
--- a/Documentation/filesystems/caching/backend-api.txt
+++ b/Documentation/filesystems/caching/backend-api.txt
@@ -676,6 +676,29 @@ FS-Cache provides some utilities that a cache backend may make use of:
676 as possible. 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 (*) Get and release references on a retrieval record: 702 (*) Get and release references on a retrieval record:
680 703
681 void fscache_get_retrieval(struct fscache_retrieval *op); 704 void fscache_get_retrieval(struct fscache_retrieval *op);
diff --git a/Documentation/filesystems/caching/fscache.txt b/Documentation/filesystems/caching/fscache.txt
index 770267af5b3e..66fa7fbccfa4 100644
--- a/Documentation/filesystems/caching/fscache.txt
+++ b/Documentation/filesystems/caching/fscache.txt
@@ -303,6 +303,10 @@ proc files.
303 wrp=N Number of in-progress write_page() cache ops 303 wrp=N Number of in-progress write_page() cache ops
304 ucp=N Number of in-progress uncache_page() cache ops 304 ucp=N Number of in-progress uncache_page() cache ops
305 dsp=N Number of in-progress dissociate_pages() cache ops 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 (*) /proc/fs/fscache/histogram 312 (*) /proc/fs/fscache/histogram
diff --git a/fs/cachefiles/internal.h b/fs/cachefiles/internal.h
index 8c52472d2efa..aecd0859eacb 100644
--- a/fs/cachefiles/internal.h
+++ b/fs/cachefiles/internal.h
@@ -43,7 +43,6 @@ struct cachefiles_object {
43 loff_t i_size; /* object size */ 43 loff_t i_size; /* object size */
44 unsigned long flags; 44 unsigned long flags;
45#define CACHEFILES_OBJECT_ACTIVE 0 /* T if marked active */ 45#define CACHEFILES_OBJECT_ACTIVE 0 /* T if marked active */
46#define CACHEFILES_OBJECT_BURIED 1 /* T if preemptively buried */
47 atomic_t usage; /* object usage count */ 46 atomic_t usage; /* object usage count */
48 uint8_t type; /* object type */ 47 uint8_t type; /* object type */
49 uint8_t new; /* T if object new */ 48 uint8_t new; /* T if object new */
diff --git a/fs/cachefiles/namei.c b/fs/cachefiles/namei.c
index 7f8e83f9d74e..1d60195fc518 100644
--- a/fs/cachefiles/namei.c
+++ b/fs/cachefiles/namei.c
@@ -97,7 +97,8 @@ static noinline void cachefiles_printk_object(struct cachefiles_object *object,
97 * call vfs_unlink(), vfs_rmdir() or vfs_rename() 97 * call vfs_unlink(), vfs_rmdir() or vfs_rename()
98 */ 98 */
99static void cachefiles_mark_object_buried(struct cachefiles_cache *cache, 99static 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 struct cachefiles_object *object; 103 struct cachefiles_object *object;
103 struct rb_node *p; 104 struct rb_node *p;
@@ -132,8 +133,9 @@ found_dentry:
132 pr_err("\n"); 133 pr_err("\n");
133 pr_err("Error: Can't preemptively bury live object\n"); 134 pr_err("Error: Can't preemptively bury live object\n");
134 cachefiles_printk_object(object, NULL); 135 cachefiles_printk_object(object, NULL);
135 } else if (test_and_set_bit(CACHEFILES_OBJECT_BURIED, &object->flags)) { 136 } else {
136 pr_err("Error: Object already preemptively buried\n"); 137 if (why != FSCACHE_OBJECT_IS_STALE)
138 fscache_object_mark_killed(&object->fscache, why);
137 } 139 }
138 140
139 write_unlock(&cache->active_lock); 141 write_unlock(&cache->active_lock);
@@ -265,7 +267,8 @@ requeue:
265static int cachefiles_bury_object(struct cachefiles_cache *cache, 267static int cachefiles_bury_object(struct cachefiles_cache *cache,
266 struct dentry *dir, 268 struct dentry *dir,
267 struct dentry *rep, 269 struct dentry *rep,
268 bool preemptive) 270 bool preemptive,
271 enum fscache_why_object_killed why)
269{ 272{
270 struct dentry *grave, *trap; 273 struct dentry *grave, *trap;
271 struct path path, path_to_graveyard; 274 struct path path, path_to_graveyard;
@@ -289,7 +292,7 @@ static int cachefiles_bury_object(struct cachefiles_cache *cache,
289 ret = vfs_unlink(dir->d_inode, rep, NULL); 292 ret = vfs_unlink(dir->d_inode, rep, NULL);
290 293
291 if (preemptive) 294 if (preemptive)
292 cachefiles_mark_object_buried(cache, rep); 295 cachefiles_mark_object_buried(cache, rep, why);
293 } 296 }
294 297
295 mutex_unlock(&dir->d_inode->i_mutex); 298 mutex_unlock(&dir->d_inode->i_mutex);
@@ -394,7 +397,7 @@ try_again:
394 "Rename failed with error %d", ret); 397 "Rename failed with error %d", ret);
395 398
396 if (preemptive) 399 if (preemptive)
397 cachefiles_mark_object_buried(cache, rep); 400 cachefiles_mark_object_buried(cache, rep, why);
398 } 401 }
399 402
400 unlock_rename(cache->graveyard, dir); 403 unlock_rename(cache->graveyard, dir);
@@ -422,7 +425,7 @@ int cachefiles_delete_object(struct cachefiles_cache *cache,
422 425
423 mutex_lock_nested(&dir->d_inode->i_mutex, I_MUTEX_PARENT); 426 mutex_lock_nested(&dir->d_inode->i_mutex, I_MUTEX_PARENT);
424 427
425 if (test_bit(CACHEFILES_OBJECT_BURIED, &object->flags)) { 428 if (test_bit(FSCACHE_OBJECT_KILLED_BY_CACHE, &object->fscache.flags)) {
426 /* object allocation for the same key preemptively deleted this 429 /* object allocation for the same key preemptively deleted this
427 * object's file so that it could create its own file */ 430 * object's file so that it could create its own file */
428 _debug("object preemptively buried"); 431 _debug("object preemptively buried");
@@ -433,7 +436,8 @@ int cachefiles_delete_object(struct cachefiles_cache *cache,
433 * may have been renamed */ 436 * may have been renamed */
434 if (dir == object->dentry->d_parent) { 437 if (dir == object->dentry->d_parent) {
435 ret = cachefiles_bury_object(cache, dir, 438 ret = cachefiles_bury_object(cache, dir,
436 object->dentry, false); 439 object->dentry, false,
440 FSCACHE_OBJECT_WAS_RETIRED);
437 } else { 441 } else {
438 /* it got moved, presumably by cachefilesd culling it, 442 /* it got moved, presumably by cachefilesd culling it,
439 * so it's no longer in the key path and we can ignore 443 * so it's no longer in the key path and we can ignore
@@ -522,7 +526,7 @@ lookup_again:
522 if (!next->d_inode) { 526 if (!next->d_inode) {
523 ret = cachefiles_has_space(cache, 1, 0); 527 ret = cachefiles_has_space(cache, 1, 0);
524 if (ret < 0) 528 if (ret < 0)
525 goto create_error; 529 goto no_space_error;
526 530
527 path.dentry = dir; 531 path.dentry = dir;
528 ret = security_path_mkdir(&path, next, 0); 532 ret = security_path_mkdir(&path, next, 0);
@@ -551,7 +555,7 @@ lookup_again:
551 if (!next->d_inode) { 555 if (!next->d_inode) {
552 ret = cachefiles_has_space(cache, 1, 0); 556 ret = cachefiles_has_space(cache, 1, 0);
553 if (ret < 0) 557 if (ret < 0)
554 goto create_error; 558 goto no_space_error;
555 559
556 path.dentry = dir; 560 path.dentry = dir;
557 ret = security_path_mknod(&path, next, S_IFREG, 0); 561 ret = security_path_mknod(&path, next, S_IFREG, 0);
@@ -602,7 +606,8 @@ lookup_again:
602 * mutex) */ 606 * mutex) */
603 object->dentry = NULL; 607 object->dentry = NULL;
604 608
605 ret = cachefiles_bury_object(cache, dir, next, true); 609 ret = cachefiles_bury_object(cache, dir, next, true,
610 FSCACHE_OBJECT_IS_STALE);
606 dput(next); 611 dput(next);
607 next = NULL; 612 next = NULL;
608 613
@@ -610,6 +615,7 @@ lookup_again:
610 goto delete_error; 615 goto delete_error;
611 616
612 _debug("redo lookup"); 617 _debug("redo lookup");
618 fscache_object_retrying_stale(&object->fscache);
613 goto lookup_again; 619 goto lookup_again;
614 } 620 }
615 } 621 }
@@ -662,6 +668,8 @@ lookup_again:
662 _leave(" = 0 [%lu]", object->dentry->d_inode->i_ino); 668 _leave(" = 0 [%lu]", object->dentry->d_inode->i_ino);
663 return 0; 669 return 0;
664 670
671no_space_error:
672 fscache_object_mark_killed(&object->fscache, FSCACHE_OBJECT_NO_SPACE);
665create_error: 673create_error:
666 _debug("create error %d", ret); 674 _debug("create error %d", ret);
667 if (ret == -EIO) 675 if (ret == -EIO)
@@ -927,7 +935,8 @@ int cachefiles_cull(struct cachefiles_cache *cache, struct dentry *dir,
927 /* actually remove the victim (drops the dir mutex) */ 935 /* actually remove the victim (drops the dir mutex) */
928 _debug("bury"); 936 _debug("bury");
929 937
930 ret = cachefiles_bury_object(cache, dir, victim, false); 938 ret = cachefiles_bury_object(cache, dir, victim, false,
939 FSCACHE_OBJECT_WAS_CULLED);
931 if (ret < 0) 940 if (ret < 0)
932 goto error; 941 goto error;
933 942
diff --git a/fs/fscache/internal.h b/fs/fscache/internal.h
index 7872a62ef30c..3063a58b7d3d 100644
--- a/fs/fscache/internal.h
+++ b/fs/fscache/internal.h
@@ -271,6 +271,11 @@ extern atomic_t fscache_n_cop_write_page;
271extern atomic_t fscache_n_cop_uncache_page; 271extern atomic_t fscache_n_cop_uncache_page;
272extern atomic_t fscache_n_cop_dissociate_pages; 272extern atomic_t fscache_n_cop_dissociate_pages;
273 273
274extern atomic_t fscache_n_cache_no_space_reject;
275extern atomic_t fscache_n_cache_stale_objects;
276extern atomic_t fscache_n_cache_retired_objects;
277extern atomic_t fscache_n_cache_culled_objects;
278
274static inline void fscache_stat(atomic_t *stat) 279static inline void fscache_stat(atomic_t *stat)
275{ 280{
276 atomic_inc(stat); 281 atomic_inc(stat);
diff --git a/fs/fscache/object.c b/fs/fscache/object.c
index da032daf0e0d..12bb468bf0ae 100644
--- a/fs/fscache/object.c
+++ b/fs/fscache/object.c
@@ -1016,3 +1016,50 @@ static const struct fscache_state *fscache_update_object(struct fscache_object *
1016 _leave(""); 1016 _leave("");
1017 return transit_to(WAIT_FOR_CMD); 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 */
1027void fscache_object_retrying_stale(struct fscache_object *object)
1028{
1029 fscache_stat(&fscache_n_cache_no_space_reject);
1030}
1031EXPORT_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 */
1041void 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}
1065EXPORT_SYMBOL(fscache_object_mark_killed);
diff --git a/fs/fscache/stats.c b/fs/fscache/stats.c
index 40d13c70ef51..3a722e8f2307 100644
--- a/fs/fscache/stats.c
+++ b/fs/fscache/stats.c
@@ -130,6 +130,11 @@ atomic_t fscache_n_cop_write_page;
130atomic_t fscache_n_cop_uncache_page; 130atomic_t fscache_n_cop_uncache_page;
131atomic_t fscache_n_cop_dissociate_pages; 131atomic_t fscache_n_cop_dissociate_pages;
132 132
133atomic_t fscache_n_cache_no_space_reject;
134atomic_t fscache_n_cache_stale_objects;
135atomic_t fscache_n_cache_retired_objects;
136atomic_t fscache_n_cache_culled_objects;
137
133/* 138/*
134 * display the general statistics 139 * display the general statistics
135 */ 140 */
@@ -271,6 +276,11 @@ static int fscache_stats_show(struct seq_file *m, void *v)
271 atomic_read(&fscache_n_cop_write_page), 276 atomic_read(&fscache_n_cop_write_page),
272 atomic_read(&fscache_n_cop_uncache_page), 277 atomic_read(&fscache_n_cop_uncache_page),
273 atomic_read(&fscache_n_cop_dissociate_pages)); 278 atomic_read(&fscache_n_cop_dissociate_pages));
279 seq_printf(m, "CacheEv: nsp=%d stl=%d rtr=%d cul=%d\n",
280 atomic_read(&fscache_n_cache_no_space_reject),
281 atomic_read(&fscache_n_cache_stale_objects),
282 atomic_read(&fscache_n_cache_retired_objects),
283 atomic_read(&fscache_n_cache_culled_objects));
274 return 0; 284 return 0;
275} 285}
276 286
diff --git a/include/linux/fscache-cache.h b/include/linux/fscache-cache.h
index 771484993ca7..c9dafdaf3347 100644
--- a/include/linux/fscache-cache.h
+++ b/include/linux/fscache-cache.h
@@ -371,6 +371,7 @@ struct fscache_object {
371#define FSCACHE_OBJECT_IS_LOOKED_UP 4 /* T if object has been looked up */ 371#define FSCACHE_OBJECT_IS_LOOKED_UP 4 /* T if object has been looked up */
372#define FSCACHE_OBJECT_IS_AVAILABLE 5 /* T if object has become active */ 372#define FSCACHE_OBJECT_IS_AVAILABLE 5 /* T if object has become active */
373#define FSCACHE_OBJECT_RETIRED 6 /* T if object was retired on relinquishment */ 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 struct list_head cache_link; /* link in cache->object_list */ 376 struct list_head cache_link; /* link in cache->object_list */
376 struct hlist_node cookie_link; /* link in cookie->backing_objects */ 377 struct hlist_node cookie_link; /* link in cookie->backing_objects */
@@ -551,4 +552,15 @@ extern enum fscache_checkaux fscache_check_aux(struct fscache_object *object,
551 const void *data, 552 const void *data,
552 uint16_t datalen); 553 uint16_t datalen);
553 554
555extern void fscache_object_retrying_stale(struct fscache_object *object);
556
557enum fscache_why_object_killed {
558 FSCACHE_OBJECT_IS_STALE,
559 FSCACHE_OBJECT_NO_SPACE,
560 FSCACHE_OBJECT_WAS_RETIRED,
561 FSCACHE_OBJECT_WAS_CULLED,
562};
563extern void fscache_object_mark_killed(struct fscache_object *object,
564 enum fscache_why_object_killed why);
565
554#endif /* _LINUX_FSCACHE_CACHE_H */ 566#endif /* _LINUX_FSCACHE_CACHE_H */