summaryrefslogtreecommitdiffstats
path: root/fs/fscache
diff options
context:
space:
mode:
authorDavid Howells <dhowells@redhat.com>2018-04-04 08:41:28 -0400
committerDavid Howells <dhowells@redhat.com>2018-04-04 08:41:28 -0400
commit402cb8dda949d9b8c0df20ad2527d139faad7ca1 (patch)
tree83cdb77f5490a0990eade886aa7f8dd087864996 /fs/fscache
parent08c2e3d087840cd1e7141b62d92f3dc897147984 (diff)
fscache: Attach the index key and aux data to the cookie
Attach copies of the index key and auxiliary data to the fscache cookie so that: (1) The callbacks to the netfs for this stuff can be eliminated. This can simplify things in the cache as the information is still available, even after the cache has relinquished the cookie. (2) Simplifies the locking requirements of accessing the information as we don't have to worry about the netfs object going away on us. (3) The cache can do lazy updating of the coherency information on disk. As long as the cache is flushed before reboot/poweroff, there's no need to update the coherency info on disk every time it changes. (4) Cookies can be hashed or put in a tree as the index key is easily available. This allows: (a) Checks for duplicate cookies can be made at the top fscache layer rather than down in the bowels of the cache backend. (b) Caching can be added to a netfs object that has a cookie if the cache is brought online after the netfs object is allocated. A certain amount of space is made in the cookie for inline copies of the data, but if it won't fit there, extra memory will be allocated for it. The downside of this is that live cache operation requires more memory. Signed-off-by: David Howells <dhowells@redhat.com> Acked-by: Anna Schumaker <anna.schumaker@netapp.com> Tested-by: Steve Dickson <steved@redhat.com>
Diffstat (limited to 'fs/fscache')
-rw-r--r--fs/fscache/cache.c2
-rw-r--r--fs/fscache/cookie.c88
-rw-r--r--fs/fscache/fsdef.c49
-rw-r--r--fs/fscache/internal.h21
-rw-r--r--fs/fscache/netfs.c17
-rw-r--r--fs/fscache/object-list.c28
-rw-r--r--fs/fscache/object.c22
-rw-r--r--fs/fscache/operation.c2
8 files changed, 140 insertions, 89 deletions
diff --git a/fs/fscache/cache.c b/fs/fscache/cache.c
index 56cce7fdd39e..c184c5a356ff 100644
--- a/fs/fscache/cache.c
+++ b/fs/fscache/cache.c
@@ -125,7 +125,7 @@ struct fscache_cache *fscache_select_cache_for_object(
125 } 125 }
126 126
127 /* the parent is unbacked */ 127 /* the parent is unbacked */
128 if (cookie->def->type != FSCACHE_COOKIE_TYPE_INDEX) { 128 if (cookie->type != FSCACHE_COOKIE_TYPE_INDEX) {
129 /* cookie not an index and is unbacked */ 129 /* cookie not an index and is unbacked */
130 spin_unlock(&cookie->lock); 130 spin_unlock(&cookie->lock);
131 _leave(" = NULL [cookie ub,ni]"); 131 _leave(" = NULL [cookie ub,ni]");
diff --git a/fs/fscache/cookie.c b/fs/fscache/cookie.c
index ea1f80daaff4..4d6210082a60 100644
--- a/fs/fscache/cookie.c
+++ b/fs/fscache/cookie.c
@@ -58,6 +58,8 @@ void fscache_cookie_init_once(void *_cookie)
58struct fscache_cookie *__fscache_acquire_cookie( 58struct fscache_cookie *__fscache_acquire_cookie(
59 struct fscache_cookie *parent, 59 struct fscache_cookie *parent,
60 const struct fscache_cookie_def *def, 60 const struct fscache_cookie_def *def,
61 const void *index_key, size_t index_key_len,
62 const void *aux_data, size_t aux_data_len,
61 void *netfs_data, 63 void *netfs_data,
62 bool enable) 64 bool enable)
63{ 65{
@@ -69,6 +71,13 @@ struct fscache_cookie *__fscache_acquire_cookie(
69 parent ? (char *) parent->def->name : "<no-parent>", 71 parent ? (char *) parent->def->name : "<no-parent>",
70 def->name, netfs_data, enable); 72 def->name, netfs_data, enable);
71 73
74 if (!index_key || !index_key_len || index_key_len > 255 || aux_data_len > 255)
75 return NULL;
76 if (!aux_data || !aux_data_len) {
77 aux_data = NULL;
78 aux_data_len = 0;
79 }
80
72 fscache_stat(&fscache_n_acquires); 81 fscache_stat(&fscache_n_acquires);
73 82
74 /* if there's no parent cookie, then we don't create one here either */ 83 /* if there's no parent cookie, then we don't create one here either */
@@ -79,11 +88,10 @@ struct fscache_cookie *__fscache_acquire_cookie(
79 } 88 }
80 89
81 /* validate the definition */ 90 /* validate the definition */
82 BUG_ON(!def->get_key);
83 BUG_ON(!def->name[0]); 91 BUG_ON(!def->name[0]);
84 92
85 BUG_ON(def->type == FSCACHE_COOKIE_TYPE_INDEX && 93 BUG_ON(def->type == FSCACHE_COOKIE_TYPE_INDEX &&
86 parent->def->type != FSCACHE_COOKIE_TYPE_INDEX); 94 parent->type != FSCACHE_COOKIE_TYPE_INDEX);
87 95
88 /* allocate and initialise a cookie */ 96 /* allocate and initialise a cookie */
89 cookie = kmem_cache_alloc(fscache_cookie_jar, GFP_KERNEL); 97 cookie = kmem_cache_alloc(fscache_cookie_jar, GFP_KERNEL);
@@ -93,6 +101,25 @@ struct fscache_cookie *__fscache_acquire_cookie(
93 return NULL; 101 return NULL;
94 } 102 }
95 103
104 cookie->key_len = index_key_len;
105 cookie->aux_len = aux_data_len;
106
107 if (cookie->key_len <= sizeof(cookie->inline_key)) {
108 memcpy(cookie->inline_key, index_key, cookie->key_len);
109 } else {
110 cookie->key = kmemdup(index_key, cookie->key_len, GFP_KERNEL);
111 if (!cookie->key)
112 goto nomem;
113 }
114
115 if (cookie->aux_len <= sizeof(cookie->inline_aux)) {
116 memcpy(cookie->inline_aux, aux_data, cookie->aux_len);
117 } else {
118 cookie->aux = kmemdup(aux_data, cookie->aux_len, GFP_KERNEL);
119 if (!cookie->aux)
120 goto nomem;
121 }
122
96 atomic_set(&cookie->usage, 1); 123 atomic_set(&cookie->usage, 1);
97 atomic_set(&cookie->n_children, 0); 124 atomic_set(&cookie->n_children, 0);
98 125
@@ -108,12 +135,13 @@ struct fscache_cookie *__fscache_acquire_cookie(
108 cookie->parent = parent; 135 cookie->parent = parent;
109 cookie->netfs_data = netfs_data; 136 cookie->netfs_data = netfs_data;
110 cookie->flags = (1 << FSCACHE_COOKIE_NO_DATA_YET); 137 cookie->flags = (1 << FSCACHE_COOKIE_NO_DATA_YET);
111 138 cookie->type = def->type;
139
112 /* radix tree insertion won't use the preallocation pool unless it's 140 /* radix tree insertion won't use the preallocation pool unless it's
113 * told it may not wait */ 141 * told it may not wait */
114 INIT_RADIX_TREE(&cookie->stores, GFP_NOFS & ~__GFP_DIRECT_RECLAIM); 142 INIT_RADIX_TREE(&cookie->stores, GFP_NOFS & ~__GFP_DIRECT_RECLAIM);
115 143
116 switch (cookie->def->type) { 144 switch (cookie->type) {
117 case FSCACHE_COOKIE_TYPE_INDEX: 145 case FSCACHE_COOKIE_TYPE_INDEX:
118 fscache_stat(&fscache_n_cookie_index); 146 fscache_stat(&fscache_n_cookie_index);
119 break; 147 break;
@@ -131,7 +159,7 @@ struct fscache_cookie *__fscache_acquire_cookie(
131 /* if the object is an index then we need do nothing more here 159 /* if the object is an index then we need do nothing more here
132 * - we create indices on disk when we need them as an index 160 * - we create indices on disk when we need them as an index
133 * may exist in multiple caches */ 161 * may exist in multiple caches */
134 if (cookie->def->type != FSCACHE_COOKIE_TYPE_INDEX) { 162 if (cookie->type != FSCACHE_COOKIE_TYPE_INDEX) {
135 if (fscache_acquire_non_index_cookie(cookie) == 0) { 163 if (fscache_acquire_non_index_cookie(cookie) == 0) {
136 set_bit(FSCACHE_COOKIE_ENABLED, &cookie->flags); 164 set_bit(FSCACHE_COOKIE_ENABLED, &cookie->flags);
137 } else { 165 } else {
@@ -150,6 +178,14 @@ struct fscache_cookie *__fscache_acquire_cookie(
150 fscache_stat(&fscache_n_acquires_ok); 178 fscache_stat(&fscache_n_acquires_ok);
151 _leave(" = %p", cookie); 179 _leave(" = %p", cookie);
152 return cookie; 180 return cookie;
181
182nomem:
183 if (cookie->aux_len > sizeof(cookie->inline_aux))
184 kfree(cookie->aux);
185 if (cookie->key_len > sizeof(cookie->inline_key))
186 kfree(cookie->key);
187 kmem_cache_free(fscache_cookie_jar, cookie);
188 return NULL;
153} 189}
154EXPORT_SYMBOL(__fscache_acquire_cookie); 190EXPORT_SYMBOL(__fscache_acquire_cookie);
155 191
@@ -157,6 +193,7 @@ EXPORT_SYMBOL(__fscache_acquire_cookie);
157 * Enable a cookie to permit it to accept new operations. 193 * Enable a cookie to permit it to accept new operations.
158 */ 194 */
159void __fscache_enable_cookie(struct fscache_cookie *cookie, 195void __fscache_enable_cookie(struct fscache_cookie *cookie,
196 const void *aux_data,
160 bool (*can_enable)(void *data), 197 bool (*can_enable)(void *data),
161 void *data) 198 void *data)
162{ 199{
@@ -167,12 +204,14 @@ void __fscache_enable_cookie(struct fscache_cookie *cookie,
167 wait_on_bit_lock(&cookie->flags, FSCACHE_COOKIE_ENABLEMENT_LOCK, 204 wait_on_bit_lock(&cookie->flags, FSCACHE_COOKIE_ENABLEMENT_LOCK,
168 TASK_UNINTERRUPTIBLE); 205 TASK_UNINTERRUPTIBLE);
169 206
207 fscache_update_aux(cookie, aux_data);
208
170 if (test_bit(FSCACHE_COOKIE_ENABLED, &cookie->flags)) 209 if (test_bit(FSCACHE_COOKIE_ENABLED, &cookie->flags))
171 goto out_unlock; 210 goto out_unlock;
172 211
173 if (can_enable && !can_enable(data)) { 212 if (can_enable && !can_enable(data)) {
174 /* The netfs decided it didn't want to enable after all */ 213 /* The netfs decided it didn't want to enable after all */
175 } else if (cookie->def->type != FSCACHE_COOKIE_TYPE_INDEX) { 214 } else if (cookie->type != FSCACHE_COOKIE_TYPE_INDEX) {
176 /* Wait for outstanding disablement to complete */ 215 /* Wait for outstanding disablement to complete */
177 __fscache_wait_on_invalidate(cookie); 216 __fscache_wait_on_invalidate(cookie);
178 217
@@ -431,10 +470,7 @@ void __fscache_invalidate(struct fscache_cookie *cookie)
431 * there, and if it's doing that, it may as well just retire the 470 * there, and if it's doing that, it may as well just retire the
432 * cookie. 471 * cookie.
433 */ 472 */
434 ASSERTCMP(cookie->def->type, ==, FSCACHE_COOKIE_TYPE_DATAFILE); 473 ASSERTCMP(cookie->type, ==, FSCACHE_COOKIE_TYPE_DATAFILE);
435
436 /* We will be updating the cookie too. */
437 BUG_ON(!cookie->def->get_aux);
438 474
439 /* If there's an object, we tell the object state machine to handle the 475 /* If there's an object, we tell the object state machine to handle the
440 * invalidation on our behalf, otherwise there's nothing to do. 476 * invalidation on our behalf, otherwise there's nothing to do.
@@ -478,7 +514,7 @@ EXPORT_SYMBOL(__fscache_wait_on_invalidate);
478/* 514/*
479 * update the index entries backing a cookie 515 * update the index entries backing a cookie
480 */ 516 */
481void __fscache_update_cookie(struct fscache_cookie *cookie) 517void __fscache_update_cookie(struct fscache_cookie *cookie, const void *aux_data)
482{ 518{
483 struct fscache_object *object; 519 struct fscache_object *object;
484 520
@@ -492,10 +528,10 @@ void __fscache_update_cookie(struct fscache_cookie *cookie)
492 528
493 _enter("{%s}", cookie->def->name); 529 _enter("{%s}", cookie->def->name);
494 530
495 BUG_ON(!cookie->def->get_aux);
496
497 spin_lock(&cookie->lock); 531 spin_lock(&cookie->lock);
498 532
533 fscache_update_aux(cookie, aux_data);
534
499 if (fscache_cookie_enabled(cookie)) { 535 if (fscache_cookie_enabled(cookie)) {
500 /* update the index entry on disk in each cache backing this 536 /* update the index entry on disk in each cache backing this
501 * cookie. 537 * cookie.
@@ -514,7 +550,9 @@ EXPORT_SYMBOL(__fscache_update_cookie);
514/* 550/*
515 * Disable a cookie to stop it from accepting new requests from the netfs. 551 * Disable a cookie to stop it from accepting new requests from the netfs.
516 */ 552 */
517void __fscache_disable_cookie(struct fscache_cookie *cookie, bool invalidate) 553void __fscache_disable_cookie(struct fscache_cookie *cookie,
554 const void *aux_data,
555 bool invalidate)
518{ 556{
519 struct fscache_object *object; 557 struct fscache_object *object;
520 bool awaken = false; 558 bool awaken = false;
@@ -533,6 +571,9 @@ void __fscache_disable_cookie(struct fscache_cookie *cookie, bool invalidate)
533 571
534 wait_on_bit_lock(&cookie->flags, FSCACHE_COOKIE_ENABLEMENT_LOCK, 572 wait_on_bit_lock(&cookie->flags, FSCACHE_COOKIE_ENABLEMENT_LOCK,
535 TASK_UNINTERRUPTIBLE); 573 TASK_UNINTERRUPTIBLE);
574
575 fscache_update_aux(cookie, aux_data);
576
536 if (!test_and_clear_bit(FSCACHE_COOKIE_ENABLED, &cookie->flags)) 577 if (!test_and_clear_bit(FSCACHE_COOKIE_ENABLED, &cookie->flags))
537 goto out_unlock_enable; 578 goto out_unlock_enable;
538 579
@@ -570,7 +611,7 @@ void __fscache_disable_cookie(struct fscache_cookie *cookie, bool invalidate)
570 } 611 }
571 612
572 /* Make sure any pending writes are cancelled. */ 613 /* Make sure any pending writes are cancelled. */
573 if (cookie->def->type != FSCACHE_COOKIE_TYPE_INDEX) 614 if (cookie->type != FSCACHE_COOKIE_TYPE_INDEX)
574 fscache_invalidate_writes(cookie); 615 fscache_invalidate_writes(cookie);
575 616
576 /* Reset the cookie state if it wasn't relinquished */ 617 /* Reset the cookie state if it wasn't relinquished */
@@ -592,7 +633,9 @@ EXPORT_SYMBOL(__fscache_disable_cookie);
592 * - all dependents of this cookie must have already been unregistered 633 * - all dependents of this cookie must have already been unregistered
593 * (indices/files/pages) 634 * (indices/files/pages)
594 */ 635 */
595void __fscache_relinquish_cookie(struct fscache_cookie *cookie, bool retire) 636void __fscache_relinquish_cookie(struct fscache_cookie *cookie,
637 const void *aux_data,
638 bool retire)
596{ 639{
597 fscache_stat(&fscache_n_relinquishes); 640 fscache_stat(&fscache_n_relinquishes);
598 if (retire) 641 if (retire)
@@ -614,7 +657,7 @@ void __fscache_relinquish_cookie(struct fscache_cookie *cookie, bool retire)
614 if (test_and_set_bit(FSCACHE_COOKIE_RELINQUISHED, &cookie->flags)) 657 if (test_and_set_bit(FSCACHE_COOKIE_RELINQUISHED, &cookie->flags))
615 BUG(); 658 BUG();
616 659
617 __fscache_disable_cookie(cookie, retire); 660 __fscache_disable_cookie(cookie, aux_data, retire);
618 661
619 /* Clear pointers back to the netfs */ 662 /* Clear pointers back to the netfs */
620 cookie->netfs_data = NULL; 663 cookie->netfs_data = NULL;
@@ -656,6 +699,10 @@ void fscache_cookie_put(struct fscache_cookie *cookie,
656 699
657 parent = cookie->parent; 700 parent = cookie->parent;
658 BUG_ON(!hlist_empty(&cookie->backing_objects)); 701 BUG_ON(!hlist_empty(&cookie->backing_objects));
702 if (cookie->aux_len > sizeof(cookie->inline_aux))
703 kfree(cookie->aux);
704 if (cookie->key_len > sizeof(cookie->inline_key))
705 kfree(cookie->key);
659 kmem_cache_free(fscache_cookie_jar, cookie); 706 kmem_cache_free(fscache_cookie_jar, cookie);
660 707
661 cookie = parent; 708 cookie = parent;
@@ -670,7 +717,8 @@ void fscache_cookie_put(struct fscache_cookie *cookie,
670 * 717 *
671 * NOTE: it only serves no-index type 718 * NOTE: it only serves no-index type
672 */ 719 */
673int __fscache_check_consistency(struct fscache_cookie *cookie) 720int __fscache_check_consistency(struct fscache_cookie *cookie,
721 const void *aux_data)
674{ 722{
675 struct fscache_operation *op; 723 struct fscache_operation *op;
676 struct fscache_object *object; 724 struct fscache_object *object;
@@ -679,7 +727,7 @@ int __fscache_check_consistency(struct fscache_cookie *cookie)
679 727
680 _enter("%p,", cookie); 728 _enter("%p,", cookie);
681 729
682 ASSERTCMP(cookie->def->type, ==, FSCACHE_COOKIE_TYPE_DATAFILE); 730 ASSERTCMP(cookie->type, ==, FSCACHE_COOKIE_TYPE_DATAFILE);
683 731
684 if (fscache_wait_for_deferred_lookup(cookie) < 0) 732 if (fscache_wait_for_deferred_lookup(cookie) < 0)
685 return -ERESTARTSYS; 733 return -ERESTARTSYS;
@@ -699,6 +747,8 @@ int __fscache_check_consistency(struct fscache_cookie *cookie)
699 747
700 spin_lock(&cookie->lock); 748 spin_lock(&cookie->lock);
701 749
750 fscache_update_aux(cookie, aux_data);
751
702 if (!fscache_cookie_enabled(cookie) || 752 if (!fscache_cookie_enabled(cookie) ||
703 hlist_empty(&cookie->backing_objects)) 753 hlist_empty(&cookie->backing_objects))
704 goto inconsistent; 754 goto inconsistent;
diff --git a/fs/fscache/fsdef.c b/fs/fscache/fsdef.c
index 5a117df2a9ef..1122e97d56e8 100644
--- a/fs/fscache/fsdef.c
+++ b/fs/fscache/fsdef.c
@@ -13,12 +13,6 @@
13#include <linux/module.h> 13#include <linux/module.h>
14#include "internal.h" 14#include "internal.h"
15 15
16static uint16_t fscache_fsdef_netfs_get_key(const void *cookie_netfs_data,
17 void *buffer, uint16_t bufmax);
18
19static uint16_t fscache_fsdef_netfs_get_aux(const void *cookie_netfs_data,
20 void *buffer, uint16_t bufmax);
21
22static 16static
23enum fscache_checkaux fscache_fsdef_netfs_check_aux(void *cookie_netfs_data, 17enum fscache_checkaux fscache_fsdef_netfs_check_aux(void *cookie_netfs_data,
24 const void *data, 18 const void *data,
@@ -60,6 +54,7 @@ struct fscache_cookie fscache_fsdef_index = {
60 .backing_objects = HLIST_HEAD_INIT, 54 .backing_objects = HLIST_HEAD_INIT,
61 .def = &fscache_fsdef_index_def, 55 .def = &fscache_fsdef_index_def,
62 .flags = 1 << FSCACHE_COOKIE_ENABLED, 56 .flags = 1 << FSCACHE_COOKIE_ENABLED,
57 .type = FSCACHE_COOKIE_TYPE_INDEX,
63}; 58};
64EXPORT_SYMBOL(fscache_fsdef_index); 59EXPORT_SYMBOL(fscache_fsdef_index);
65 60
@@ -71,52 +66,10 @@ EXPORT_SYMBOL(fscache_fsdef_index);
71struct fscache_cookie_def fscache_fsdef_netfs_def = { 66struct fscache_cookie_def fscache_fsdef_netfs_def = {
72 .name = "FSDEF.netfs", 67 .name = "FSDEF.netfs",
73 .type = FSCACHE_COOKIE_TYPE_INDEX, 68 .type = FSCACHE_COOKIE_TYPE_INDEX,
74 .get_key = fscache_fsdef_netfs_get_key,
75 .get_aux = fscache_fsdef_netfs_get_aux,
76 .check_aux = fscache_fsdef_netfs_check_aux, 69 .check_aux = fscache_fsdef_netfs_check_aux,
77}; 70};
78 71
79/* 72/*
80 * get the key data for an FSDEF index record - this is the name of the netfs
81 * for which this entry is created
82 */
83static uint16_t fscache_fsdef_netfs_get_key(const void *cookie_netfs_data,
84 void *buffer, uint16_t bufmax)
85{
86 const struct fscache_netfs *netfs = cookie_netfs_data;
87 unsigned klen;
88
89 _enter("{%s.%u},", netfs->name, netfs->version);
90
91 klen = strlen(netfs->name);
92 if (klen > bufmax)
93 return 0;
94
95 memcpy(buffer, netfs->name, klen);
96 return klen;
97}
98
99/*
100 * get the auxiliary data for an FSDEF index record - this is the index
101 * structure version number of the netfs for which this version is created
102 */
103static uint16_t fscache_fsdef_netfs_get_aux(const void *cookie_netfs_data,
104 void *buffer, uint16_t bufmax)
105{
106 const struct fscache_netfs *netfs = cookie_netfs_data;
107 unsigned dlen;
108
109 _enter("{%s.%u},", netfs->name, netfs->version);
110
111 dlen = sizeof(uint32_t);
112 if (dlen > bufmax)
113 return 0;
114
115 memcpy(buffer, &netfs->version, dlen);
116 return dlen;
117}
118
119/*
120 * check that the index structure version number stored in the auxiliary data 73 * check that the index structure version number stored in the auxiliary data
121 * matches the one the netfs gave us 74 * matches the one the netfs gave us
122 */ 75 */
diff --git a/fs/fscache/internal.h b/fs/fscache/internal.h
index c27e2db3004e..5f905a499306 100644
--- a/fs/fscache/internal.h
+++ b/fs/fscache/internal.h
@@ -342,6 +342,27 @@ void fscache_put_context(struct fscache_cookie *cookie, void *context)
342 cookie->def->put_context(cookie->netfs_data, context); 342 cookie->def->put_context(cookie->netfs_data, context);
343} 343}
344 344
345/*
346 * Update the auxiliary data on a cookie.
347 */
348static inline
349void fscache_update_aux(struct fscache_cookie *cookie, const void *aux_data)
350{
351 void *p;
352
353 if (!aux_data)
354 return;
355 if (cookie->aux_len <= sizeof(cookie->inline_aux))
356 p = cookie->inline_aux;
357 else
358 p = cookie->aux;
359
360 if (memcmp(p, aux_data, cookie->aux_len) != 0) {
361 memcpy(p, aux_data, cookie->aux_len);
362 set_bit(FSCACHE_COOKIE_AUX_UPDATED, &cookie->flags);
363 }
364}
365
345/*****************************************************************************/ 366/*****************************************************************************/
346/* 367/*
347 * debug tracing 368 * debug tracing
diff --git a/fs/fscache/netfs.c b/fs/fscache/netfs.c
index c816600d1dde..a5998dfab7e7 100644
--- a/fs/fscache/netfs.c
+++ b/fs/fscache/netfs.c
@@ -37,6 +37,19 @@ int __fscache_register_netfs(struct fscache_netfs *netfs)
37 return -ENOMEM; 37 return -ENOMEM;
38 } 38 }
39 39
40 cookie->key_len = strlen(netfs->name);
41 if (cookie->key_len <= sizeof(cookie->inline_key)) {
42 memcpy(cookie->inline_key, netfs->name, strlen(netfs->name));
43 } else {
44 ret = -ENOMEM;
45 cookie->key = kmemdup(netfs->name, cookie->key_len, GFP_KERNEL);
46 if (!cookie->key)
47 goto nomem;
48 }
49
50 cookie->aux_len = sizeof(netfs->version);
51 memcpy(cookie->inline_aux, &netfs->version, cookie->aux_len);
52
40 /* initialise the primary index cookie */ 53 /* initialise the primary index cookie */
41 atomic_set(&cookie->usage, 1); 54 atomic_set(&cookie->usage, 1);
42 atomic_set(&cookie->n_children, 0); 55 atomic_set(&cookie->n_children, 0);
@@ -46,6 +59,7 @@ int __fscache_register_netfs(struct fscache_netfs *netfs)
46 cookie->parent = &fscache_fsdef_index; 59 cookie->parent = &fscache_fsdef_index;
47 cookie->netfs_data = netfs; 60 cookie->netfs_data = netfs;
48 cookie->flags = 1 << FSCACHE_COOKIE_ENABLED; 61 cookie->flags = 1 << FSCACHE_COOKIE_ENABLED;
62 cookie->type = FSCACHE_COOKIE_TYPE_INDEX;
49 63
50 spin_lock_init(&cookie->lock); 64 spin_lock_init(&cookie->lock);
51 spin_lock_init(&cookie->stores_lock); 65 spin_lock_init(&cookie->stores_lock);
@@ -73,6 +87,7 @@ int __fscache_register_netfs(struct fscache_netfs *netfs)
73already_registered: 87already_registered:
74 up_write(&fscache_addremove_sem); 88 up_write(&fscache_addremove_sem);
75 89
90nomem:
76 if (ret < 0) 91 if (ret < 0)
77 kmem_cache_free(fscache_cookie_jar, cookie); 92 kmem_cache_free(fscache_cookie_jar, cookie);
78 93
@@ -92,7 +107,7 @@ void __fscache_unregister_netfs(struct fscache_netfs *netfs)
92 down_write(&fscache_addremove_sem); 107 down_write(&fscache_addremove_sem);
93 108
94 list_del(&netfs->link); 109 list_del(&netfs->link);
95 fscache_relinquish_cookie(netfs->primary_index, 0); 110 fscache_relinquish_cookie(netfs->primary_index, NULL, false);
96 111
97 up_write(&fscache_addremove_sem); 112 up_write(&fscache_addremove_sem);
98 113
diff --git a/fs/fscache/object-list.c b/fs/fscache/object-list.c
index 0438d4cd91ef..43e6e28c164f 100644
--- a/fs/fscache/object-list.c
+++ b/fs/fscache/object-list.c
@@ -36,8 +36,6 @@ struct fscache_objlist_data {
36#define FSCACHE_OBJLIST_CONFIG_NOEVENTS 0x00000800 /* show objects without no events */ 36#define FSCACHE_OBJLIST_CONFIG_NOEVENTS 0x00000800 /* show objects without no events */
37#define FSCACHE_OBJLIST_CONFIG_WORK 0x00001000 /* show objects with work */ 37#define FSCACHE_OBJLIST_CONFIG_WORK 0x00001000 /* show objects with work */
38#define FSCACHE_OBJLIST_CONFIG_NOWORK 0x00002000 /* show objects without work */ 38#define FSCACHE_OBJLIST_CONFIG_NOWORK 0x00002000 /* show objects without work */
39
40 u8 buf[512]; /* key and aux data buffer */
41}; 39};
42 40
43/* 41/*
@@ -170,7 +168,7 @@ static int fscache_objlist_show(struct seq_file *m, void *v)
170 struct fscache_cookie *cookie; 168 struct fscache_cookie *cookie;
171 unsigned long config = data->config; 169 unsigned long config = data->config;
172 char _type[3], *type; 170 char _type[3], *type;
173 u8 *buf = data->buf, *p; 171 u8 *p;
174 172
175 if ((unsigned long) v == 1) { 173 if ((unsigned long) v == 1) {
176 seq_puts(m, "OBJECT PARENT STAT CHLDN OPS OOP IPR EX READS" 174 seq_puts(m, "OBJECT PARENT STAT CHLDN OPS OOP IPR EX READS"
@@ -254,7 +252,7 @@ static int fscache_objlist_show(struct seq_file *m, void *v)
254 if (fscache_use_cookie(obj)) { 252 if (fscache_use_cookie(obj)) {
255 uint16_t keylen = 0, auxlen = 0; 253 uint16_t keylen = 0, auxlen = 0;
256 254
257 switch (cookie->def->type) { 255 switch (cookie->type) {
258 case 0: 256 case 0:
259 type = "IX"; 257 type = "IX";
260 break; 258 break;
@@ -263,7 +261,7 @@ static int fscache_objlist_show(struct seq_file *m, void *v)
263 break; 261 break;
264 default: 262 default:
265 snprintf(_type, sizeof(_type), "%02u", 263 snprintf(_type, sizeof(_type), "%02u",
266 cookie->def->type); 264 cookie->type);
267 type = _type; 265 type = _type;
268 break; 266 break;
269 } 267 }
@@ -274,30 +272,30 @@ static int fscache_objlist_show(struct seq_file *m, void *v)
274 cookie->flags, 272 cookie->flags,
275 cookie->netfs_data); 273 cookie->netfs_data);
276 274
277 if (cookie->def->get_key && 275 if (config & FSCACHE_OBJLIST_CONFIG_KEY)
278 config & FSCACHE_OBJLIST_CONFIG_KEY) 276 keylen = cookie->key_len;
279 keylen = cookie->def->get_key(cookie->netfs_data,
280 buf, 400);
281 277
282 if (cookie->def->get_aux && 278 if (config & FSCACHE_OBJLIST_CONFIG_AUX)
283 config & FSCACHE_OBJLIST_CONFIG_AUX) 279 auxlen = cookie->aux_len;
284 auxlen = cookie->def->get_aux(cookie->netfs_data,
285 buf + keylen, 512 - keylen);
286 fscache_unuse_cookie(obj);
287 280
288 if (keylen > 0 || auxlen > 0) { 281 if (keylen > 0 || auxlen > 0) {
289 seq_puts(m, " "); 282 seq_puts(m, " ");
290 for (p = buf; keylen > 0; keylen--) 283 p = keylen <= sizeof(cookie->inline_key) ?
284 cookie->inline_key : cookie->key;
285 for (; keylen > 0; keylen--)
291 seq_printf(m, "%02x", *p++); 286 seq_printf(m, "%02x", *p++);
292 if (auxlen > 0) { 287 if (auxlen > 0) {
293 if (config & FSCACHE_OBJLIST_CONFIG_KEY) 288 if (config & FSCACHE_OBJLIST_CONFIG_KEY)
294 seq_puts(m, ", "); 289 seq_puts(m, ", ");
290 p = auxlen <= sizeof(cookie->inline_aux) ?
291 cookie->inline_aux : cookie->aux;
295 for (; auxlen > 0; auxlen--) 292 for (; auxlen > 0; auxlen--)
296 seq_printf(m, "%02x", *p++); 293 seq_printf(m, "%02x", *p++);
297 } 294 }
298 } 295 }
299 296
300 seq_puts(m, "\n"); 297 seq_puts(m, "\n");
298 fscache_unuse_cookie(obj);
301 } else { 299 } else {
302 seq_puts(m, "<no_netfs>\n"); 300 seq_puts(m, "<no_netfs>\n");
303 } 301 }
diff --git a/fs/fscache/object.c b/fs/fscache/object.c
index 7c0ddb7ae29a..a7b28f876fde 100644
--- a/fs/fscache/object.c
+++ b/fs/fscache/object.c
@@ -144,6 +144,7 @@ static void fscache_put_object(struct fscache_object *,
144 enum fscache_obj_ref_trace); 144 enum fscache_obj_ref_trace);
145static bool fscache_enqueue_dependents(struct fscache_object *, int); 145static bool fscache_enqueue_dependents(struct fscache_object *, int);
146static void fscache_dequeue_object(struct fscache_object *); 146static void fscache_dequeue_object(struct fscache_object *);
147static void fscache_update_aux_data(struct fscache_object *);
147 148
148/* 149/*
149 * we need to notify the parent when an op completes that we had outstanding 150 * we need to notify the parent when an op completes that we had outstanding
@@ -711,6 +712,11 @@ static const struct fscache_state *fscache_drop_object(struct fscache_object *ob
711 ASSERT(cookie != NULL); 712 ASSERT(cookie != NULL);
712 ASSERT(!hlist_unhashed(&object->cookie_link)); 713 ASSERT(!hlist_unhashed(&object->cookie_link));
713 714
715 if (test_bit(FSCACHE_COOKIE_AUX_UPDATED, &cookie->flags)) {
716 _debug("final update");
717 fscache_update_aux_data(object);
718 }
719
714 /* Make sure the cookie no longer points here and that the netfs isn't 720 /* Make sure the cookie no longer points here and that the netfs isn't
715 * waiting for us. 721 * waiting for us.
716 */ 722 */
@@ -1037,6 +1043,17 @@ static const struct fscache_state *fscache_invalidate_object(struct fscache_obje
1037} 1043}
1038 1044
1039/* 1045/*
1046 * Update auxiliary data.
1047 */
1048static void fscache_update_aux_data(struct fscache_object *object)
1049{
1050 fscache_stat(&fscache_n_updates_run);
1051 fscache_stat(&fscache_n_cop_update_object);
1052 object->cache->ops->update_object(object);
1053 fscache_stat_d(&fscache_n_cop_update_object);
1054}
1055
1056/*
1040 * Asynchronously update an object. 1057 * Asynchronously update an object.
1041 */ 1058 */
1042static const struct fscache_state *fscache_update_object(struct fscache_object *object, 1059static const struct fscache_state *fscache_update_object(struct fscache_object *object,
@@ -1044,10 +1061,7 @@ static const struct fscache_state *fscache_update_object(struct fscache_object *
1044{ 1061{
1045 _enter("{OBJ%x},%d", object->debug_id, event); 1062 _enter("{OBJ%x},%d", object->debug_id, event);
1046 1063
1047 fscache_stat(&fscache_n_updates_run); 1064 fscache_update_aux_data(object);
1048 fscache_stat(&fscache_n_cop_update_object);
1049 object->cache->ops->update_object(object);
1050 fscache_stat_d(&fscache_n_cop_update_object);
1051 1065
1052 _leave(""); 1066 _leave("");
1053 return transit_to(WAIT_FOR_CMD); 1067 return transit_to(WAIT_FOR_CMD);
diff --git a/fs/fscache/operation.c b/fs/fscache/operation.c
index 7a071e1e952d..e30c5975ea58 100644
--- a/fs/fscache/operation.c
+++ b/fs/fscache/operation.c
@@ -506,7 +506,7 @@ void fscache_put_operation(struct fscache_operation *op)
506 if (!atomic_dec_and_test(&op->usage)) 506 if (!atomic_dec_and_test(&op->usage))
507 return; 507 return;
508 508
509 trace_fscache_op(op->object->cookie, op, fscache_op_put); 509 trace_fscache_op(op->object ? op->object->cookie : NULL, op, fscache_op_put);
510 510
511 _debug("PUT OP"); 511 _debug("PUT OP");
512 ASSERTIFCMP(op->state != FSCACHE_OP_ST_INITIALISED && 512 ASSERTIFCMP(op->state != FSCACHE_OP_ST_INITIALISED &&