aboutsummaryrefslogtreecommitdiffstats
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
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>
-rw-r--r--Documentation/filesystems/caching/netfs-api.txt106
-rw-r--r--fs/9p/cache.c73
-rw-r--r--fs/afs/cache.c120
-rw-r--r--fs/afs/cell.c4
-rw-r--r--fs/afs/inode.c46
-rw-r--r--fs/afs/internal.h7
-rw-r--r--fs/afs/volume.c4
-rw-r--r--fs/cachefiles/interface.c38
-rw-r--r--fs/cachefiles/namei.c33
-rw-r--r--fs/cachefiles/xattr.c2
-rw-r--r--fs/ceph/cache.c93
-rw-r--r--fs/cifs/cache.c153
-rw-r--r--fs/cifs/fscache.c122
-rw-r--r--fs/cifs/fscache.h13
-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
-rw-r--r--fs/nfs/fscache-index.c140
-rw-r--r--fs/nfs/fscache.c83
-rw-r--r--fs/nfs/fscache.h16
-rw-r--r--include/linux/fscache.h110
26 files changed, 606 insertions, 786 deletions
diff --git a/Documentation/filesystems/caching/netfs-api.txt b/Documentation/filesystems/caching/netfs-api.txt
index 0eb31de3a2c1..332840ad4151 100644
--- a/Documentation/filesystems/caching/netfs-api.txt
+++ b/Documentation/filesystems/caching/netfs-api.txt
@@ -129,17 +129,9 @@ To define an object, a structure of the following type should be filled out:
129 const void *parent_netfs_data, 129 const void *parent_netfs_data,
130 const void *cookie_netfs_data); 130 const void *cookie_netfs_data);
131 131
132 uint16_t (*get_key)(const void *cookie_netfs_data,
133 void *buffer,
134 uint16_t bufmax);
135
136 void (*get_attr)(const void *cookie_netfs_data, 132 void (*get_attr)(const void *cookie_netfs_data,
137 uint64_t *size); 133 uint64_t *size);
138 134
139 uint16_t (*get_aux)(const void *cookie_netfs_data,
140 void *buffer,
141 uint16_t bufmax);
142
143 enum fscache_checkaux (*check_aux)(void *cookie_netfs_data, 135 enum fscache_checkaux (*check_aux)(void *cookie_netfs_data,
144 const void *data, 136 const void *data,
145 uint16_t datalen); 137 uint16_t datalen);
@@ -187,14 +179,7 @@ This has the following fields:
187 cache in the parent's list will be chosen, or failing that, the first 179 cache in the parent's list will be chosen, or failing that, the first
188 cache in the master list. 180 cache in the master list.
189 181
190 (4) A function to retrieve an object's key from the netfs [mandatory]. 182 (4) A function to retrieve attribute data from the netfs [optional].
191
192 This function will be called with the netfs data that was passed to the
193 cookie acquisition function and the maximum length of key data that it may
194 provide. It should write the required key data into the given buffer and
195 return the quantity it wrote.
196
197 (5) A function to retrieve attribute data from the netfs [optional].
198 183
199 This function will be called with the netfs data that was passed to the 184 This function will be called with the netfs data that was passed to the
200 cookie acquisition function. It should return the size of the file if 185 cookie acquisition function. It should return the size of the file if
@@ -203,20 +188,7 @@ This has the following fields:
203 188
204 If the function is absent, a file size of 0 is assumed. 189 If the function is absent, a file size of 0 is assumed.
205 190
206 (6) A function to retrieve auxiliary data from the netfs [optional]. 191 (5) A function to check the auxiliary data [optional].
207
208 This function will be called with the netfs data that was passed to the
209 cookie acquisition function and the maximum length of auxiliary data that
210 it may provide. It should write the auxiliary data into the given buffer
211 and return the quantity it wrote.
212
213 If this function is absent, the auxiliary data length will be set to 0.
214
215 The length of the auxiliary data buffer may be dependent on the key
216 length. A netfs mustn't rely on being able to provide more than 400 bytes
217 for both.
218
219 (7) A function to check the auxiliary data [optional].
220 192
221 This function will be called to check that a match found in the cache for 193 This function will be called to check that a match found in the cache for
222 this object is valid. For instance with AFS it could check the auxiliary 194 this object is valid. For instance with AFS it could check the auxiliary
@@ -235,7 +207,7 @@ This has the following fields:
235 This function can also be used to extract data from the auxiliary data in 207 This function can also be used to extract data from the auxiliary data in
236 the cache and copy it into the netfs's structures. 208 the cache and copy it into the netfs's structures.
237 209
238 (8) A pair of functions to manage contexts for the completion callback 210 (6) A pair of functions to manage contexts for the completion callback
239 [optional]. 211 [optional].
240 212
241 The cache read/write functions are passed a context which is then passed 213 The cache read/write functions are passed a context which is then passed
@@ -249,7 +221,7 @@ This has the following fields:
249 required for indices as indices may not contain data. These functions may 221 required for indices as indices may not contain data. These functions may
250 be called in interrupt context and so may not sleep. 222 be called in interrupt context and so may not sleep.
251 223
252 (9) A function to mark a page as retaining cache metadata [optional]. 224 (7) A function to mark a page as retaining cache metadata [optional].
253 225
254 This is called by the cache to indicate that it is retaining in-memory 226 This is called by the cache to indicate that it is retaining in-memory
255 information for this page and that the netfs should uncache the page when 227 information for this page and that the netfs should uncache the page when
@@ -261,7 +233,7 @@ This has the following fields:
261 233
262 This function is not required for indices as they're not permitted data. 234 This function is not required for indices as they're not permitted data.
263 235
264(10) A function to unmark all the pages retaining cache metadata [mandatory]. 236 (8) A function to unmark all the pages retaining cache metadata [mandatory].
265 237
266 This is called by FS-Cache to indicate that a backing store is being 238 This is called by FS-Cache to indicate that a backing store is being
267 unbound from a cookie and that all the marks on the pages should be 239 unbound from a cookie and that all the marks on the pages should be
@@ -333,12 +305,27 @@ the path to the file:
333 struct fscache_cookie * 305 struct fscache_cookie *
334 fscache_acquire_cookie(struct fscache_cookie *parent, 306 fscache_acquire_cookie(struct fscache_cookie *parent,
335 const struct fscache_object_def *def, 307 const struct fscache_object_def *def,
308 const void *index_key,
309 size_t index_key_len,
310 const void *aux_data,
311 size_t aux_data_len,
336 void *netfs_data, 312 void *netfs_data,
337 bool enable); 313 bool enable);
338 314
339This function creates an index entry in the index represented by parent, 315This function creates an index entry in the index represented by parent,
340filling in the index entry by calling the operations pointed to by def. 316filling in the index entry by calling the operations pointed to by def.
341 317
318A unique key that represents the object within the parent must be pointed to by
319index_key and is of length index_key_len.
320
321An optional blob of auxiliary data that is to be stored within the cache can be
322pointed to with aux_data and should be of length aux_data_len. This would
323typically be used for storing coherency data.
324
325The netfs may pass an arbitrary value in netfs_data and this will be presented
326to it in the event of any calling back. This may also be used in tracing or
327logging of messages.
328
342Note that this function never returns an error - all errors are handled 329Note that this function never returns an error - all errors are handled
343internally. It may, however, return NULL to indicate no cookie. It is quite 330internally. It may, however, return NULL to indicate no cookie. It is quite
344acceptable to pass this token back to this function as the parent to another 331acceptable to pass this token back to this function as the parent to another
@@ -355,29 +342,23 @@ must be enabled to do anything with it. A disabled cookie can be enabled by
355calling fscache_enable_cookie() (see below). 342calling fscache_enable_cookie() (see below).
356 343
357For example, with AFS, a cell would be added to the primary index. This index 344For example, with AFS, a cell would be added to the primary index. This index
358entry would have a dependent inode containing a volume location index for the 345entry would have a dependent inode containing volume mappings within this cell:
359volume mappings within this cell:
360 346
361 cell->cache = 347 cell->cache =
362 fscache_acquire_cookie(afs_cache_netfs.primary_index, 348 fscache_acquire_cookie(afs_cache_netfs.primary_index,
363 &afs_cell_cache_index_def, 349 &afs_cell_cache_index_def,
350 cell->name, strlen(cell->name),
351 NULL, 0,
364 cell, true); 352 cell, true);
365 353
366Then when a volume location was accessed, it would be entered into the cell's 354And then a particular volume could be added to that index by ID, creating
367index and an inode would be allocated that acts as a volume type and hash chain 355another index for vnodes (AFS inode equivalents):
368combination:
369
370 vlocation->cache =
371 fscache_acquire_cookie(cell->cache,
372 &afs_vlocation_cache_index_def,
373 vlocation, true);
374
375And then a particular flavour of volume (R/O for example) could be added to
376that index, creating another index for vnodes (AFS inode equivalents):
377 356
378 volume->cache = 357 volume->cache =
379 fscache_acquire_cookie(vlocation->cache, 358 fscache_acquire_cookie(volume->cell->cache,
380 &afs_volume_cache_index_def, 359 &afs_volume_cache_index_def,
360 &volume->vid, sizeof(volume->vid),
361 NULL, 0,
381 volume, true); 362 volume, true);
382 363
383 364
@@ -392,6 +373,8 @@ the object definition should be something other than index type.
392 vnode->cache = 373 vnode->cache =
393 fscache_acquire_cookie(volume->cache, 374 fscache_acquire_cookie(volume->cache,
394 &afs_vnode_cache_object_def, 375 &afs_vnode_cache_object_def,
376 &key, sizeof(key),
377 &aux, sizeof(aux),
395 vnode, true); 378 vnode, true);
396 379
397 380
@@ -408,6 +391,8 @@ it would be some other type of object such as a data file.
408 xattr->cache = 391 xattr->cache =
409 fscache_acquire_cookie(vnode->cache, 392 fscache_acquire_cookie(vnode->cache,
410 &afs_xattr_cache_object_def, 393 &afs_xattr_cache_object_def,
394 &xattr->name, strlen(xattr->name),
395 NULL, 0,
411 xattr, true); 396 xattr, true);
412 397
413Miscellaneous objects might be used to store extended attributes or directory 398Miscellaneous objects might be used to store extended attributes or directory
@@ -717,21 +702,23 @@ INDEX AND DATA FILE CONSISTENCY
717To find out whether auxiliary data for an object is up to data within the 702To find out whether auxiliary data for an object is up to data within the
718cache, the following function can be called: 703cache, the following function can be called:
719 704
720 int fscache_check_consistency(struct fscache_cookie *cookie) 705 int fscache_check_consistency(struct fscache_cookie *cookie,
706 const void *aux_data);
721 707
722This will call back to the netfs to check whether the auxiliary data associated 708This will call back to the netfs to check whether the auxiliary data associated
723with a cookie is correct. It returns 0 if it is and -ESTALE if it isn't; it 709with a cookie is correct; if aux_data is non-NULL, it will update the auxiliary
724may also return -ENOMEM and -ERESTARTSYS. 710data buffer first. It returns 0 if it is and -ESTALE if it isn't; it may also
711return -ENOMEM and -ERESTARTSYS.
725 712
726To request an update of the index data for an index or other object, the 713To request an update of the index data for an index or other object, the
727following function should be called: 714following function should be called:
728 715
729 void fscache_update_cookie(struct fscache_cookie *cookie); 716 void fscache_update_cookie(struct fscache_cookie *cookie,
717 const void *aux_data);
730 718
731This function will refer back to the netfs_data pointer stored in the cookie by 719This function will update the cookie's auxiliary data buffer from aux_data if
732the acquisition function to obtain the data to write into each revised index 720that is non-NULL and then schedule this to be stored on disk. The update
733entry. The update method in the parent index definition will be called to 721method in the parent index definition will be called to transfer the data.
734transfer the data.
735 722
736Note that partial updates may happen automatically at other times, such as when 723Note that partial updates may happen automatically at other times, such as when
737data blocks are added to a data file object. 724data blocks are added to a data file object.
@@ -750,6 +737,7 @@ The initial enablement state is set by fscache_acquire_cookie(), but the cookie
750can be enabled or disabled later. To disable a cookie, call: 737can be enabled or disabled later. To disable a cookie, call:
751 738
752 void fscache_disable_cookie(struct fscache_cookie *cookie, 739 void fscache_disable_cookie(struct fscache_cookie *cookie,
740 const void *aux_data,
753 bool invalidate); 741 bool invalidate);
754 742
755If the cookie is not already disabled, this locks the cookie against other 743If the cookie is not already disabled, this locks the cookie against other
@@ -764,6 +752,7 @@ markings are cleared up.
764Cookies can be enabled or reenabled with: 752Cookies can be enabled or reenabled with:
765 753
766 void fscache_enable_cookie(struct fscache_cookie *cookie, 754 void fscache_enable_cookie(struct fscache_cookie *cookie,
755 const void *aux_data,
767 bool (*can_enable)(void *data), 756 bool (*can_enable)(void *data),
768 void *data) 757 void *data)
769 758
@@ -777,6 +766,9 @@ ruling as to whether or not enablement should actually be permitted to begin.
777All possible failures are handled internally. The cookie will only be marked 766All possible failures are handled internally. The cookie will only be marked
778as enabled if provisional backing objects are allocated. 767as enabled if provisional backing objects are allocated.
779 768
769In both cases, the cookie's auxiliary data buffer is updated from aux_data if
770that is non-NULL inside the enablement lock before proceeding.
771
780 772
781=============================== 773===============================
782MISCELLANEOUS COOKIE OPERATIONS 774MISCELLANEOUS COOKIE OPERATIONS
@@ -823,6 +815,7 @@ COOKIE UNREGISTRATION
823To get rid of a cookie, this function should be called. 815To get rid of a cookie, this function should be called.
824 816
825 void fscache_relinquish_cookie(struct fscache_cookie *cookie, 817 void fscache_relinquish_cookie(struct fscache_cookie *cookie,
818 const void *aux_data,
826 bool retire); 819 bool retire);
827 820
828If retire is non-zero, then the object will be marked for recycling, and all 821If retire is non-zero, then the object will be marked for recycling, and all
@@ -833,6 +826,9 @@ If retire is zero, then the object may be available again when next the
833acquisition function is called. Retirement here will overrule the pinning on a 826acquisition function is called. Retirement here will overrule the pinning on a
834cookie. 827cookie.
835 828
829The cookie's auxiliary data will be updated from aux_data if that is non-NULL
830so that the cache can lazily update it on disk.
831
836One very important note - relinquish must NOT be called for a cookie unless all 832One very important note - relinquish must NOT be called for a cookie unless all
837the cookies for "child" indices, objects and pages have been relinquished 833the cookies for "child" indices, objects and pages have been relinquished
838first. 834first.
diff --git a/fs/9p/cache.c b/fs/9p/cache.c
index 64c58eb26159..9d0030af5672 100644
--- a/fs/9p/cache.c
+++ b/fs/9p/cache.c
@@ -55,41 +55,26 @@ int v9fs_random_cachetag(struct v9fs_session_info *v9ses)
55 return scnprintf(v9ses->cachetag, CACHETAG_LEN, "%lu", jiffies); 55 return scnprintf(v9ses->cachetag, CACHETAG_LEN, "%lu", jiffies);
56} 56}
57 57
58static uint16_t v9fs_cache_session_get_key(const void *cookie_netfs_data,
59 void *buffer, uint16_t bufmax)
60{
61 struct v9fs_session_info *v9ses;
62 uint16_t klen = 0;
63
64 v9ses = (struct v9fs_session_info *)cookie_netfs_data;
65 p9_debug(P9_DEBUG_FSC, "session %p buf %p size %u\n",
66 v9ses, buffer, bufmax);
67
68 if (v9ses->cachetag)
69 klen = strlen(v9ses->cachetag);
70
71 if (klen > bufmax)
72 return 0;
73
74 memcpy(buffer, v9ses->cachetag, klen);
75 p9_debug(P9_DEBUG_FSC, "cache session tag %s\n", v9ses->cachetag);
76 return klen;
77}
78
79const struct fscache_cookie_def v9fs_cache_session_index_def = { 58const struct fscache_cookie_def v9fs_cache_session_index_def = {
80 .name = "9P.session", 59 .name = "9P.session",
81 .type = FSCACHE_COOKIE_TYPE_INDEX, 60 .type = FSCACHE_COOKIE_TYPE_INDEX,
82 .get_key = v9fs_cache_session_get_key,
83}; 61};
84 62
85void v9fs_cache_session_get_cookie(struct v9fs_session_info *v9ses) 63void v9fs_cache_session_get_cookie(struct v9fs_session_info *v9ses)
86{ 64{
87 /* If no cache session tag was specified, we generate a random one. */ 65 /* If no cache session tag was specified, we generate a random one. */
88 if (!v9ses->cachetag) 66 if (!v9ses->cachetag) {
89 v9fs_random_cachetag(v9ses); 67 if (v9fs_random_cachetag(v9ses) < 0) {
68 v9ses->fscache = NULL;
69 return;
70 }
71 }
90 72
91 v9ses->fscache = fscache_acquire_cookie(v9fs_cache_netfs.primary_index, 73 v9ses->fscache = fscache_acquire_cookie(v9fs_cache_netfs.primary_index,
92 &v9fs_cache_session_index_def, 74 &v9fs_cache_session_index_def,
75 v9ses->cachetag,
76 strlen(v9ses->cachetag),
77 NULL, 0,
93 v9ses, true); 78 v9ses, true);
94 p9_debug(P9_DEBUG_FSC, "session %p get cookie %p\n", 79 p9_debug(P9_DEBUG_FSC, "session %p get cookie %p\n",
95 v9ses, v9ses->fscache); 80 v9ses, v9ses->fscache);
@@ -99,21 +84,10 @@ void v9fs_cache_session_put_cookie(struct v9fs_session_info *v9ses)
99{ 84{
100 p9_debug(P9_DEBUG_FSC, "session %p put cookie %p\n", 85 p9_debug(P9_DEBUG_FSC, "session %p put cookie %p\n",
101 v9ses, v9ses->fscache); 86 v9ses, v9ses->fscache);
102 fscache_relinquish_cookie(v9ses->fscache, 0); 87 fscache_relinquish_cookie(v9ses->fscache, NULL, false);
103 v9ses->fscache = NULL; 88 v9ses->fscache = NULL;
104} 89}
105 90
106
107static uint16_t v9fs_cache_inode_get_key(const void *cookie_netfs_data,
108 void *buffer, uint16_t bufmax)
109{
110 const struct v9fs_inode *v9inode = cookie_netfs_data;
111 memcpy(buffer, &v9inode->qid.path, sizeof(v9inode->qid.path));
112 p9_debug(P9_DEBUG_FSC, "inode %p get key %llu\n",
113 &v9inode->vfs_inode, v9inode->qid.path);
114 return sizeof(v9inode->qid.path);
115}
116
117static void v9fs_cache_inode_get_attr(const void *cookie_netfs_data, 91static void v9fs_cache_inode_get_attr(const void *cookie_netfs_data,
118 uint64_t *size) 92 uint64_t *size)
119{ 93{
@@ -124,16 +98,6 @@ static void v9fs_cache_inode_get_attr(const void *cookie_netfs_data,
124 &v9inode->vfs_inode, *size); 98 &v9inode->vfs_inode, *size);
125} 99}
126 100
127static uint16_t v9fs_cache_inode_get_aux(const void *cookie_netfs_data,
128 void *buffer, uint16_t buflen)
129{
130 const struct v9fs_inode *v9inode = cookie_netfs_data;
131 memcpy(buffer, &v9inode->qid.version, sizeof(v9inode->qid.version));
132 p9_debug(P9_DEBUG_FSC, "inode %p get aux %u\n",
133 &v9inode->vfs_inode, v9inode->qid.version);
134 return sizeof(v9inode->qid.version);
135}
136
137static enum 101static enum
138fscache_checkaux v9fs_cache_inode_check_aux(void *cookie_netfs_data, 102fscache_checkaux v9fs_cache_inode_check_aux(void *cookie_netfs_data,
139 const void *buffer, 103 const void *buffer,
@@ -154,9 +118,7 @@ fscache_checkaux v9fs_cache_inode_check_aux(void *cookie_netfs_data,
154const struct fscache_cookie_def v9fs_cache_inode_index_def = { 118const struct fscache_cookie_def v9fs_cache_inode_index_def = {
155 .name = "9p.inode", 119 .name = "9p.inode",
156 .type = FSCACHE_COOKIE_TYPE_DATAFILE, 120 .type = FSCACHE_COOKIE_TYPE_DATAFILE,
157 .get_key = v9fs_cache_inode_get_key,
158 .get_attr = v9fs_cache_inode_get_attr, 121 .get_attr = v9fs_cache_inode_get_attr,
159 .get_aux = v9fs_cache_inode_get_aux,
160 .check_aux = v9fs_cache_inode_check_aux, 122 .check_aux = v9fs_cache_inode_check_aux,
161}; 123};
162 124
@@ -175,6 +137,10 @@ void v9fs_cache_inode_get_cookie(struct inode *inode)
175 v9ses = v9fs_inode2v9ses(inode); 137 v9ses = v9fs_inode2v9ses(inode);
176 v9inode->fscache = fscache_acquire_cookie(v9ses->fscache, 138 v9inode->fscache = fscache_acquire_cookie(v9ses->fscache,
177 &v9fs_cache_inode_index_def, 139 &v9fs_cache_inode_index_def,
140 &v9inode->qid.path,
141 sizeof(v9inode->qid.path),
142 &v9inode->qid.version,
143 sizeof(v9inode->qid.version),
178 v9inode, true); 144 v9inode, true);
179 145
180 p9_debug(P9_DEBUG_FSC, "inode %p get cookie %p\n", 146 p9_debug(P9_DEBUG_FSC, "inode %p get cookie %p\n",
@@ -190,7 +156,8 @@ void v9fs_cache_inode_put_cookie(struct inode *inode)
190 p9_debug(P9_DEBUG_FSC, "inode %p put cookie %p\n", 156 p9_debug(P9_DEBUG_FSC, "inode %p put cookie %p\n",
191 inode, v9inode->fscache); 157 inode, v9inode->fscache);
192 158
193 fscache_relinquish_cookie(v9inode->fscache, 0); 159 fscache_relinquish_cookie(v9inode->fscache, &v9inode->qid.version,
160 false);
194 v9inode->fscache = NULL; 161 v9inode->fscache = NULL;
195} 162}
196 163
@@ -203,7 +170,7 @@ void v9fs_cache_inode_flush_cookie(struct inode *inode)
203 p9_debug(P9_DEBUG_FSC, "inode %p flush cookie %p\n", 170 p9_debug(P9_DEBUG_FSC, "inode %p flush cookie %p\n",
204 inode, v9inode->fscache); 171 inode, v9inode->fscache);
205 172
206 fscache_relinquish_cookie(v9inode->fscache, 1); 173 fscache_relinquish_cookie(v9inode->fscache, NULL, true);
207 v9inode->fscache = NULL; 174 v9inode->fscache = NULL;
208} 175}
209 176
@@ -236,11 +203,15 @@ void v9fs_cache_inode_reset_cookie(struct inode *inode)
236 old = v9inode->fscache; 203 old = v9inode->fscache;
237 204
238 mutex_lock(&v9inode->fscache_lock); 205 mutex_lock(&v9inode->fscache_lock);
239 fscache_relinquish_cookie(v9inode->fscache, 1); 206 fscache_relinquish_cookie(v9inode->fscache, NULL, true);
240 207
241 v9ses = v9fs_inode2v9ses(inode); 208 v9ses = v9fs_inode2v9ses(inode);
242 v9inode->fscache = fscache_acquire_cookie(v9ses->fscache, 209 v9inode->fscache = fscache_acquire_cookie(v9ses->fscache,
243 &v9fs_cache_inode_index_def, 210 &v9fs_cache_inode_index_def,
211 &v9inode->qid.path,
212 sizeof(v9inode->qid.path),
213 &v9inode->qid.version,
214 sizeof(v9inode->qid.version),
244 v9inode, true); 215 v9inode, true);
245 p9_debug(P9_DEBUG_FSC, "inode %p revalidating cookie old %p new %p\n", 216 p9_debug(P9_DEBUG_FSC, "inode %p revalidating cookie old %p new %p\n",
246 inode, old, v9inode->fscache); 217 inode, old, v9inode->fscache);
diff --git a/fs/afs/cache.c b/fs/afs/cache.c
index cd857db9b112..a16f1e024cf3 100644
--- a/fs/afs/cache.c
+++ b/fs/afs/cache.c
@@ -12,17 +12,8 @@
12#include <linux/sched.h> 12#include <linux/sched.h>
13#include "internal.h" 13#include "internal.h"
14 14
15static uint16_t afs_cell_cache_get_key(const void *cookie_netfs_data,
16 void *buffer, uint16_t buflen);
17static uint16_t afs_volume_cache_get_key(const void *cookie_netfs_data,
18 void *buffer, uint16_t buflen);
19
20static uint16_t afs_vnode_cache_get_key(const void *cookie_netfs_data,
21 void *buffer, uint16_t buflen);
22static void afs_vnode_cache_get_attr(const void *cookie_netfs_data, 15static void afs_vnode_cache_get_attr(const void *cookie_netfs_data,
23 uint64_t *size); 16 uint64_t *size);
24static uint16_t afs_vnode_cache_get_aux(const void *cookie_netfs_data,
25 void *buffer, uint16_t buflen);
26static enum fscache_checkaux afs_vnode_cache_check_aux(void *cookie_netfs_data, 17static enum fscache_checkaux afs_vnode_cache_check_aux(void *cookie_netfs_data,
27 const void *buffer, 18 const void *buffer,
28 uint16_t buflen); 19 uint16_t buflen);
@@ -35,98 +26,21 @@ struct fscache_netfs afs_cache_netfs = {
35struct fscache_cookie_def afs_cell_cache_index_def = { 26struct fscache_cookie_def afs_cell_cache_index_def = {
36 .name = "AFS.cell", 27 .name = "AFS.cell",
37 .type = FSCACHE_COOKIE_TYPE_INDEX, 28 .type = FSCACHE_COOKIE_TYPE_INDEX,
38 .get_key = afs_cell_cache_get_key,
39}; 29};
40 30
41struct fscache_cookie_def afs_volume_cache_index_def = { 31struct fscache_cookie_def afs_volume_cache_index_def = {
42 .name = "AFS.volume", 32 .name = "AFS.volume",
43 .type = FSCACHE_COOKIE_TYPE_INDEX, 33 .type = FSCACHE_COOKIE_TYPE_INDEX,
44 .get_key = afs_volume_cache_get_key,
45}; 34};
46 35
47struct fscache_cookie_def afs_vnode_cache_index_def = { 36struct fscache_cookie_def afs_vnode_cache_index_def = {
48 .name = "AFS.vnode", 37 .name = "AFS.vnode",
49 .type = FSCACHE_COOKIE_TYPE_DATAFILE, 38 .type = FSCACHE_COOKIE_TYPE_DATAFILE,
50 .get_key = afs_vnode_cache_get_key, 39 .get_attr = afs_vnode_cache_get_attr,
51 .get_attr = afs_vnode_cache_get_attr, 40 .check_aux = afs_vnode_cache_check_aux,
52 .get_aux = afs_vnode_cache_get_aux,
53 .check_aux = afs_vnode_cache_check_aux,
54}; 41};
55 42
56/* 43/*
57 * set the key for the index entry
58 */
59static uint16_t afs_cell_cache_get_key(const void *cookie_netfs_data,
60 void *buffer, uint16_t bufmax)
61{
62 const struct afs_cell *cell = cookie_netfs_data;
63 uint16_t klen;
64
65 _enter("%p,%p,%u", cell, buffer, bufmax);
66
67 klen = strlen(cell->name);
68 if (klen > bufmax)
69 return 0;
70
71 memcpy(buffer, cell->name, klen);
72 return klen;
73}
74
75/*****************************************************************************/
76/*
77 * set the key for the volume index entry
78 */
79static uint16_t afs_volume_cache_get_key(const void *cookie_netfs_data,
80 void *buffer, uint16_t bufmax)
81{
82 const struct afs_volume *volume = cookie_netfs_data;
83 struct {
84 u64 volid;
85 } __packed key;
86
87 _enter("{%u},%p,%u", volume->type, buffer, bufmax);
88
89 if (bufmax < sizeof(key))
90 return 0;
91
92 key.volid = volume->vid;
93 memcpy(buffer, &key, sizeof(key));
94 return sizeof(key);
95}
96
97/*****************************************************************************/
98/*
99 * set the key for the index entry
100 */
101static uint16_t afs_vnode_cache_get_key(const void *cookie_netfs_data,
102 void *buffer, uint16_t bufmax)
103{
104 const struct afs_vnode *vnode = cookie_netfs_data;
105 struct {
106 u32 vnode_id;
107 u32 unique;
108 u32 vnode_id_ext[2]; /* Allow for a 96-bit key */
109 } __packed key;
110
111 _enter("{%x,%x,%llx},%p,%u",
112 vnode->fid.vnode, vnode->fid.unique, vnode->status.data_version,
113 buffer, bufmax);
114
115 /* Allow for a 96-bit key */
116 memset(&key, 0, sizeof(key));
117 key.vnode_id = vnode->fid.vnode;
118 key.unique = vnode->fid.unique;
119 key.vnode_id_ext[0] = 0;
120 key.vnode_id_ext[1] = 0;
121
122 if (sizeof(key) > bufmax)
123 return 0;
124
125 memcpy(buffer, &key, sizeof(key));
126 return sizeof(key);
127}
128
129/*
130 * provide updated file attributes 44 * provide updated file attributes
131 */ 45 */
132static void afs_vnode_cache_get_attr(const void *cookie_netfs_data, 46static void afs_vnode_cache_get_attr(const void *cookie_netfs_data,
@@ -141,32 +55,6 @@ static void afs_vnode_cache_get_attr(const void *cookie_netfs_data,
141 *size = vnode->status.size; 55 *size = vnode->status.size;
142} 56}
143 57
144struct afs_vnode_cache_aux {
145 u64 data_version;
146} __packed;
147
148/*
149 * provide new auxiliary cache data
150 */
151static uint16_t afs_vnode_cache_get_aux(const void *cookie_netfs_data,
152 void *buffer, uint16_t bufmax)
153{
154 const struct afs_vnode *vnode = cookie_netfs_data;
155 struct afs_vnode_cache_aux aux;
156
157 _enter("{%x,%x,%Lx},%p,%u",
158 vnode->fid.vnode, vnode->fid.unique, vnode->status.data_version,
159 buffer, bufmax);
160
161 aux.data_version = vnode->status.data_version;
162
163 if (bufmax < sizeof(aux))
164 return 0;
165
166 memcpy(buffer, &aux, sizeof(aux));
167 return sizeof(aux);
168}
169
170/* 58/*
171 * check that the auxiliary data indicates that the entry is still valid 59 * check that the auxiliary data indicates that the entry is still valid
172 */ 60 */
diff --git a/fs/afs/cell.c b/fs/afs/cell.c
index 3d2c5e0e854e..0747460221cb 100644
--- a/fs/afs/cell.c
+++ b/fs/afs/cell.c
@@ -522,6 +522,8 @@ static int afs_activate_cell(struct afs_net *net, struct afs_cell *cell)
522#ifdef CONFIG_AFS_FSCACHE 522#ifdef CONFIG_AFS_FSCACHE
523 cell->cache = fscache_acquire_cookie(afs_cache_netfs.primary_index, 523 cell->cache = fscache_acquire_cookie(afs_cache_netfs.primary_index,
524 &afs_cell_cache_index_def, 524 &afs_cell_cache_index_def,
525 cell->name, strlen(cell->name),
526 NULL, 0,
525 cell, true); 527 cell, true);
526#endif 528#endif
527 ret = afs_proc_cell_setup(net, cell); 529 ret = afs_proc_cell_setup(net, cell);
@@ -547,7 +549,7 @@ static void afs_deactivate_cell(struct afs_net *net, struct afs_cell *cell)
547 spin_unlock(&net->proc_cells_lock); 549 spin_unlock(&net->proc_cells_lock);
548 550
549#ifdef CONFIG_AFS_FSCACHE 551#ifdef CONFIG_AFS_FSCACHE
550 fscache_relinquish_cookie(cell->cache, 0); 552 fscache_relinquish_cookie(cell->cache, NULL, false);
551 cell->cache = NULL; 553 cell->cache = NULL;
552#endif 554#endif
553 555
diff --git a/fs/afs/inode.c b/fs/afs/inode.c
index c942c79fc5f0..e499713efd2e 100644
--- a/fs/afs/inode.c
+++ b/fs/afs/inode.c
@@ -243,6 +243,33 @@ struct inode *afs_iget_pseudo_dir(struct super_block *sb, bool root)
243} 243}
244 244
245/* 245/*
246 * Get a cache cookie for an inode.
247 */
248static void afs_get_inode_cache(struct afs_vnode *vnode)
249{
250#ifdef CONFIG_AFS_FSCACHE
251 struct {
252 u32 vnode_id;
253 u32 unique;
254 u32 vnode_id_ext[2]; /* Allow for a 96-bit key */
255 } __packed key;
256 struct afs_vnode_cache_aux aux;
257
258 key.vnode_id = vnode->fid.vnode;
259 key.unique = vnode->fid.unique;
260 key.vnode_id_ext[0] = 0;
261 key.vnode_id_ext[1] = 0;
262 aux.data_version = vnode->status.data_version;
263
264 vnode->cache = fscache_acquire_cookie(vnode->volume->cache,
265 &afs_vnode_cache_index_def,
266 &key, sizeof(key),
267 &aux, sizeof(aux),
268 vnode, true);
269#endif
270}
271
272/*
246 * inode retrieval 273 * inode retrieval
247 */ 274 */
248struct inode *afs_iget(struct super_block *sb, struct key *key, 275struct inode *afs_iget(struct super_block *sb, struct key *key,
@@ -307,11 +334,7 @@ struct inode *afs_iget(struct super_block *sb, struct key *key,
307 /* set up caching before mapping the status, as map-status reads the 334 /* set up caching before mapping the status, as map-status reads the
308 * first page of symlinks to see if they're really mountpoints */ 335 * first page of symlinks to see if they're really mountpoints */
309 inode->i_size = vnode->status.size; 336 inode->i_size = vnode->status.size;
310#ifdef CONFIG_AFS_FSCACHE 337 afs_get_inode_cache(vnode);
311 vnode->cache = fscache_acquire_cookie(vnode->volume->cache,
312 &afs_vnode_cache_index_def,
313 vnode, true);
314#endif
315 338
316 ret = afs_inode_map_status(vnode, key); 339 ret = afs_inode_map_status(vnode, key);
317 if (ret < 0) 340 if (ret < 0)
@@ -327,7 +350,7 @@ struct inode *afs_iget(struct super_block *sb, struct key *key,
327 /* failure */ 350 /* failure */
328bad_inode: 351bad_inode:
329#ifdef CONFIG_AFS_FSCACHE 352#ifdef CONFIG_AFS_FSCACHE
330 fscache_relinquish_cookie(vnode->cache, ret == -ENOENT); 353 fscache_relinquish_cookie(vnode->cache, NULL, ret == -ENOENT);
331 vnode->cache = NULL; 354 vnode->cache = NULL;
332#endif 355#endif
333 iget_failed(inode); 356 iget_failed(inode);
@@ -511,9 +534,14 @@ void afs_evict_inode(struct inode *inode)
511 } 534 }
512 535
513#ifdef CONFIG_AFS_FSCACHE 536#ifdef CONFIG_AFS_FSCACHE
514 fscache_relinquish_cookie(vnode->cache, 537 {
515 test_bit(AFS_VNODE_DELETED, &vnode->flags)); 538 struct afs_vnode_cache_aux aux;
516 vnode->cache = NULL; 539
540 aux.data_version = vnode->status.data_version;
541 fscache_relinquish_cookie(vnode->cache, &aux,
542 test_bit(AFS_VNODE_DELETED, &vnode->flags));
543 vnode->cache = NULL;
544 }
517#endif 545#endif
518 546
519 afs_put_permits(vnode->permit_cache); 547 afs_put_permits(vnode->permit_cache);
diff --git a/fs/afs/internal.h b/fs/afs/internal.h
index 72217170b155..a6a1d75eee41 100644
--- a/fs/afs/internal.h
+++ b/fs/afs/internal.h
@@ -559,6 +559,13 @@ struct afs_fs_cursor {
559#define AFS_FS_CURSOR_NO_VSLEEP 0x0020 /* Set to prevent sleep on VBUSY, VOFFLINE, ... */ 559#define AFS_FS_CURSOR_NO_VSLEEP 0x0020 /* Set to prevent sleep on VBUSY, VOFFLINE, ... */
560}; 560};
561 561
562/*
563 * Cache auxiliary data.
564 */
565struct afs_vnode_cache_aux {
566 u64 data_version;
567} __packed;
568
562#include <trace/events/afs.h> 569#include <trace/events/afs.h>
563 570
564/*****************************************************************************/ 571/*****************************************************************************/
diff --git a/fs/afs/volume.c b/fs/afs/volume.c
index b517a588781f..345cb2d675d2 100644
--- a/fs/afs/volume.c
+++ b/fs/afs/volume.c
@@ -225,6 +225,8 @@ void afs_activate_volume(struct afs_volume *volume)
225#ifdef CONFIG_AFS_FSCACHE 225#ifdef CONFIG_AFS_FSCACHE
226 volume->cache = fscache_acquire_cookie(volume->cell->cache, 226 volume->cache = fscache_acquire_cookie(volume->cell->cache,
227 &afs_volume_cache_index_def, 227 &afs_volume_cache_index_def,
228 &volume->vid, sizeof(volume->vid),
229 NULL, 0,
228 volume, true); 230 volume, true);
229#endif 231#endif
230 232
@@ -245,7 +247,7 @@ void afs_deactivate_volume(struct afs_volume *volume)
245 write_unlock(&volume->cell->proc_lock); 247 write_unlock(&volume->cell->proc_lock);
246 248
247#ifdef CONFIG_AFS_FSCACHE 249#ifdef CONFIG_AFS_FSCACHE
248 fscache_relinquish_cookie(volume->cache, 250 fscache_relinquish_cookie(volume->cache, NULL,
249 test_bit(AFS_VOLUME_DELETED, &volume->flags)); 251 test_bit(AFS_VOLUME_DELETED, &volume->flags));
250 volume->cache = NULL; 252 volume->cache = NULL;
251#endif 253#endif
diff --git a/fs/cachefiles/interface.c b/fs/cachefiles/interface.c
index 405ebc3932c2..3264dcfdc92a 100644
--- a/fs/cachefiles/interface.c
+++ b/fs/cachefiles/interface.c
@@ -32,7 +32,7 @@ static struct fscache_object *cachefiles_alloc_object(
32 struct cachefiles_cache *cache; 32 struct cachefiles_cache *cache;
33 struct cachefiles_xattr *auxdata; 33 struct cachefiles_xattr *auxdata;
34 unsigned keylen, auxlen; 34 unsigned keylen, auxlen;
35 void *buffer; 35 void *buffer, *p;
36 char *key; 36 char *key;
37 37
38 cache = container_of(_cache, struct cachefiles_cache, cache); 38 cache = container_of(_cache, struct cachefiles_cache, cache);
@@ -65,8 +65,12 @@ static struct fscache_object *cachefiles_alloc_object(
65 if (!buffer) 65 if (!buffer)
66 goto nomem_buffer; 66 goto nomem_buffer;
67 67
68 keylen = cookie->def->get_key(cookie->netfs_data, buffer + 2, 512); 68 keylen = cookie->key_len;
69 ASSERTCMP(keylen, <, 512); 69 if (keylen <= sizeof(cookie->inline_key))
70 p = cookie->inline_key;
71 else
72 p = cookie->key;
73 memcpy(buffer + 2, p, keylen);
70 74
71 *(uint16_t *)buffer = keylen; 75 *(uint16_t *)buffer = keylen;
72 ((char *)buffer)[keylen + 2] = 0; 76 ((char *)buffer)[keylen + 2] = 0;
@@ -80,15 +84,17 @@ static struct fscache_object *cachefiles_alloc_object(
80 84
81 /* get hold of the auxiliary data and prepend the object type */ 85 /* get hold of the auxiliary data and prepend the object type */
82 auxdata = buffer; 86 auxdata = buffer;
83 auxlen = 0; 87 auxlen = cookie->aux_len;
84 if (cookie->def->get_aux) { 88 if (auxlen) {
85 auxlen = cookie->def->get_aux(cookie->netfs_data, 89 if (auxlen <= sizeof(cookie->inline_aux))
86 auxdata->data, 511); 90 p = cookie->inline_aux;
87 ASSERTCMP(auxlen, <, 511); 91 else
92 p = cookie->aux;
93 memcpy(auxdata->data, p, auxlen);
88 } 94 }
89 95
90 auxdata->len = auxlen + 1; 96 auxdata->len = auxlen + 1;
91 auxdata->type = cookie->def->type; 97 auxdata->type = cookie->type;
92 98
93 lookup_data->auxdata = auxdata; 99 lookup_data->auxdata = auxdata;
94 lookup_data->key = key; 100 lookup_data->key = key;
@@ -206,6 +212,7 @@ static void cachefiles_update_object(struct fscache_object *_object)
206 struct cachefiles_cache *cache; 212 struct cachefiles_cache *cache;
207 struct fscache_cookie *cookie; 213 struct fscache_cookie *cookie;
208 const struct cred *saved_cred; 214 const struct cred *saved_cred;
215 const void *aux;
209 unsigned auxlen; 216 unsigned auxlen;
210 217
211 _enter("{OBJ%x}", _object->debug_id); 218 _enter("{OBJ%x}", _object->debug_id);
@@ -220,26 +227,29 @@ static void cachefiles_update_object(struct fscache_object *_object)
220 } 227 }
221 228
222 cookie = object->fscache.cookie; 229 cookie = object->fscache.cookie;
230 auxlen = cookie->aux_len;
223 231
224 if (!cookie->def->get_aux) { 232 if (!auxlen) {
225 fscache_unuse_cookie(_object); 233 fscache_unuse_cookie(_object);
226 _leave(" [no aux]"); 234 _leave(" [no aux]");
227 return; 235 return;
228 } 236 }
229 237
230 auxdata = kmalloc(2 + 512 + 3, cachefiles_gfp); 238 auxdata = kmalloc(2 + auxlen + 3, cachefiles_gfp);
231 if (!auxdata) { 239 if (!auxdata) {
232 fscache_unuse_cookie(_object); 240 fscache_unuse_cookie(_object);
233 _leave(" [nomem]"); 241 _leave(" [nomem]");
234 return; 242 return;
235 } 243 }
236 244
237 auxlen = cookie->def->get_aux(cookie->netfs_data, auxdata->data, 511); 245 aux = (auxlen <= sizeof(cookie->inline_aux)) ?
246 cookie->inline_aux : cookie->aux;
247
248 memcpy(auxdata->data, aux, auxlen);
238 fscache_unuse_cookie(_object); 249 fscache_unuse_cookie(_object);
239 ASSERTCMP(auxlen, <, 511);
240 250
241 auxdata->len = auxlen + 1; 251 auxdata->len = auxlen + 1;
242 auxdata->type = cookie->def->type; 252 auxdata->type = cookie->type;
243 253
244 cachefiles_begin_secure(cache, &saved_cred); 254 cachefiles_begin_secure(cache, &saved_cred);
245 cachefiles_update_object_xattr(object, auxdata); 255 cachefiles_update_object_xattr(object, auxdata);
diff --git a/fs/cachefiles/namei.c b/fs/cachefiles/namei.c
index 5fc214256316..0daa1e3fe0df 100644
--- a/fs/cachefiles/namei.c
+++ b/fs/cachefiles/namei.c
@@ -30,11 +30,11 @@
30 */ 30 */
31static noinline 31static noinline
32void __cachefiles_printk_object(struct cachefiles_object *object, 32void __cachefiles_printk_object(struct cachefiles_object *object,
33 const char *prefix, 33 const char *prefix)
34 u8 *keybuf)
35{ 34{
36 struct fscache_cookie *cookie; 35 struct fscache_cookie *cookie;
37 unsigned keylen, loop; 36 const u8 *k;
37 unsigned loop;
38 38
39 pr_err("%sobject: OBJ%x\n", prefix, object->fscache.debug_id); 39 pr_err("%sobject: OBJ%x\n", prefix, object->fscache.debug_id);
40 pr_err("%sobjstate=%s fl=%lx wbusy=%x ev=%lx[%lx]\n", 40 pr_err("%sobjstate=%s fl=%lx wbusy=%x ev=%lx[%lx]\n",
@@ -56,23 +56,16 @@ void __cachefiles_printk_object(struct cachefiles_object *object,
56 object->fscache.cookie->parent, 56 object->fscache.cookie->parent,
57 object->fscache.cookie->netfs_data, 57 object->fscache.cookie->netfs_data,
58 object->fscache.cookie->flags); 58 object->fscache.cookie->flags);
59 if (keybuf && cookie->def) 59 pr_err("%skey=[%u] '", prefix, cookie->key_len);
60 keylen = cookie->def->get_key(cookie->netfs_data, keybuf, 60 k = (cookie->key_len <= sizeof(cookie->inline_key)) ?
61 CACHEFILES_KEYBUF_SIZE); 61 cookie->inline_key : cookie->key;
62 else 62 for (loop = 0; loop < cookie->key_len; loop++)
63 keylen = 0; 63 pr_cont("%02x", k[loop]);
64 pr_cont("'\n");
64 } else { 65 } else {
65 pr_err("%scookie=NULL\n", prefix); 66 pr_err("%scookie=NULL\n", prefix);
66 keylen = 0;
67 } 67 }
68 spin_unlock(&object->fscache.lock); 68 spin_unlock(&object->fscache.lock);
69
70 if (keylen) {
71 pr_err("%skey=[%u] '", prefix, keylen);
72 for (loop = 0; loop < keylen; loop++)
73 pr_cont("%02x", keybuf[loop]);
74 pr_cont("'\n");
75 }
76} 69}
77 70
78/* 71/*
@@ -81,14 +74,10 @@ void __cachefiles_printk_object(struct cachefiles_object *object,
81static noinline void cachefiles_printk_object(struct cachefiles_object *object, 74static noinline void cachefiles_printk_object(struct cachefiles_object *object,
82 struct cachefiles_object *xobject) 75 struct cachefiles_object *xobject)
83{ 76{
84 u8 *keybuf;
85
86 keybuf = kmalloc(CACHEFILES_KEYBUF_SIZE, GFP_NOIO);
87 if (object) 77 if (object)
88 __cachefiles_printk_object(object, "", keybuf); 78 __cachefiles_printk_object(object, "");
89 if (xobject) 79 if (xobject)
90 __cachefiles_printk_object(xobject, "x", keybuf); 80 __cachefiles_printk_object(xobject, "x");
91 kfree(keybuf);
92} 81}
93 82
94/* 83/*
diff --git a/fs/cachefiles/xattr.c b/fs/cachefiles/xattr.c
index d31c1a72d8a5..d84423c264af 100644
--- a/fs/cachefiles/xattr.c
+++ b/fs/cachefiles/xattr.c
@@ -113,6 +113,7 @@ int cachefiles_set_object_xattr(struct cachefiles_object *object,
113 /* attempt to install the cache metadata directly */ 113 /* attempt to install the cache metadata directly */
114 _debug("SET #%u", auxdata->len); 114 _debug("SET #%u", auxdata->len);
115 115
116 clear_bit(FSCACHE_COOKIE_AUX_UPDATED, &object->fscache.cookie->flags);
116 ret = vfs_setxattr(dentry, cachefiles_xattr_cache, 117 ret = vfs_setxattr(dentry, cachefiles_xattr_cache,
117 &auxdata->type, auxdata->len, 118 &auxdata->type, auxdata->len,
118 XATTR_CREATE); 119 XATTR_CREATE);
@@ -141,6 +142,7 @@ int cachefiles_update_object_xattr(struct cachefiles_object *object,
141 /* attempt to install the cache metadata directly */ 142 /* attempt to install the cache metadata directly */
142 _debug("SET #%u", auxdata->len); 143 _debug("SET #%u", auxdata->len);
143 144
145 clear_bit(FSCACHE_COOKIE_AUX_UPDATED, &object->fscache.cookie->flags);
144 ret = vfs_setxattr(dentry, cachefiles_xattr_cache, 146 ret = vfs_setxattr(dentry, cachefiles_xattr_cache,
145 &auxdata->type, auxdata->len, 147 &auxdata->type, auxdata->len,
146 XATTR_REPLACE); 148 XATTR_REPLACE);
diff --git a/fs/ceph/cache.c b/fs/ceph/cache.c
index a3ab265d3215..fee869061f05 100644
--- a/fs/ceph/cache.c
+++ b/fs/ceph/cache.c
@@ -41,34 +41,15 @@ static LIST_HEAD(ceph_fscache_list);
41struct ceph_fscache_entry { 41struct ceph_fscache_entry {
42 struct list_head list; 42 struct list_head list;
43 struct fscache_cookie *fscache; 43 struct fscache_cookie *fscache;
44 struct ceph_fsid fsid;
45 size_t uniq_len; 44 size_t uniq_len;
45 /* The following members must be last */
46 struct ceph_fsid fsid;
46 char uniquifier[0]; 47 char uniquifier[0];
47}; 48};
48 49
49static uint16_t ceph_fscache_session_get_key(const void *cookie_netfs_data,
50 void *buffer, uint16_t maxbuf)
51{
52 const struct ceph_fs_client* fsc = cookie_netfs_data;
53 const char *fscache_uniq = fsc->mount_options->fscache_uniq;
54 uint16_t fsid_len, uniq_len;
55
56 fsid_len = sizeof(fsc->client->fsid);
57 uniq_len = fscache_uniq ? strlen(fscache_uniq) : 0;
58 if (fsid_len + uniq_len > maxbuf)
59 return 0;
60
61 memcpy(buffer, &fsc->client->fsid, fsid_len);
62 if (uniq_len)
63 memcpy(buffer + fsid_len, fscache_uniq, uniq_len);
64
65 return fsid_len + uniq_len;
66}
67
68static const struct fscache_cookie_def ceph_fscache_fsid_object_def = { 50static const struct fscache_cookie_def ceph_fscache_fsid_object_def = {
69 .name = "CEPH.fsid", 51 .name = "CEPH.fsid",
70 .type = FSCACHE_COOKIE_TYPE_INDEX, 52 .type = FSCACHE_COOKIE_TYPE_INDEX,
71 .get_key = ceph_fscache_session_get_key,
72}; 53};
73 54
74int ceph_fscache_register(void) 55int ceph_fscache_register(void)
@@ -110,16 +91,19 @@ int ceph_fscache_register_fs(struct ceph_fs_client* fsc)
110 goto out_unlock; 91 goto out_unlock;
111 } 92 }
112 93
94 memcpy(&ent->fsid, fsid, sizeof(*fsid));
95 if (uniq_len > 0) {
96 memcpy(&ent->uniquifier, fscache_uniq, uniq_len);
97 ent->uniq_len = uniq_len;
98 }
99
113 fsc->fscache = fscache_acquire_cookie(ceph_cache_netfs.primary_index, 100 fsc->fscache = fscache_acquire_cookie(ceph_cache_netfs.primary_index,
114 &ceph_fscache_fsid_object_def, 101 &ceph_fscache_fsid_object_def,
102 &ent->fsid, sizeof(ent->fsid) + uniq_len,
103 NULL, 0,
115 fsc, true); 104 fsc, true);
116 105
117 if (fsc->fscache) { 106 if (fsc->fscache) {
118 memcpy(&ent->fsid, fsid, sizeof(*fsid));
119 if (uniq_len > 0) {
120 memcpy(&ent->uniquifier, fscache_uniq, uniq_len);
121 ent->uniq_len = uniq_len;
122 }
123 ent->fscache = fsc->fscache; 107 ent->fscache = fsc->fscache;
124 list_add_tail(&ent->list, &ceph_fscache_list); 108 list_add_tail(&ent->list, &ceph_fscache_list);
125 } else { 109 } else {
@@ -133,38 +117,6 @@ out_unlock:
133 return err; 117 return err;
134} 118}
135 119
136static uint16_t ceph_fscache_inode_get_key(const void *cookie_netfs_data,
137 void *buffer, uint16_t maxbuf)
138{
139 const struct ceph_inode_info* ci = cookie_netfs_data;
140 uint16_t klen;
141
142 /* use ceph virtual inode (id + snapshot) */
143 klen = sizeof(ci->i_vino);
144 if (klen > maxbuf)
145 return 0;
146
147 memcpy(buffer, &ci->i_vino, klen);
148 return klen;
149}
150
151static uint16_t ceph_fscache_inode_get_aux(const void *cookie_netfs_data,
152 void *buffer, uint16_t bufmax)
153{
154 struct ceph_aux_inode aux;
155 const struct ceph_inode_info* ci = cookie_netfs_data;
156 const struct inode* inode = &ci->vfs_inode;
157
158 memset(&aux, 0, sizeof(aux));
159 aux.version = ci->i_version;
160 aux.mtime = inode->i_mtime;
161 aux.size = i_size_read(inode);
162
163 memcpy(buffer, &aux, sizeof(aux));
164
165 return sizeof(aux);
166}
167
168static void ceph_fscache_inode_get_attr(const void *cookie_netfs_data, 120static void ceph_fscache_inode_get_attr(const void *cookie_netfs_data,
169 uint64_t *size) 121 uint64_t *size)
170{ 122{
@@ -197,9 +149,7 @@ static enum fscache_checkaux ceph_fscache_inode_check_aux(
197static const struct fscache_cookie_def ceph_fscache_inode_object_def = { 149static const struct fscache_cookie_def ceph_fscache_inode_object_def = {
198 .name = "CEPH.inode", 150 .name = "CEPH.inode",
199 .type = FSCACHE_COOKIE_TYPE_DATAFILE, 151 .type = FSCACHE_COOKIE_TYPE_DATAFILE,
200 .get_key = ceph_fscache_inode_get_key,
201 .get_attr = ceph_fscache_inode_get_attr, 152 .get_attr = ceph_fscache_inode_get_attr,
202 .get_aux = ceph_fscache_inode_get_aux,
203 .check_aux = ceph_fscache_inode_check_aux, 153 .check_aux = ceph_fscache_inode_check_aux,
204}; 154};
205 155
@@ -207,6 +157,7 @@ void ceph_fscache_register_inode_cookie(struct inode *inode)
207{ 157{
208 struct ceph_inode_info *ci = ceph_inode(inode); 158 struct ceph_inode_info *ci = ceph_inode(inode);
209 struct ceph_fs_client *fsc = ceph_inode_to_client(inode); 159 struct ceph_fs_client *fsc = ceph_inode_to_client(inode);
160 struct ceph_aux_inode aux;
210 161
211 /* No caching for filesystem */ 162 /* No caching for filesystem */
212 if (!fsc->fscache) 163 if (!fsc->fscache)
@@ -218,9 +169,15 @@ void ceph_fscache_register_inode_cookie(struct inode *inode)
218 169
219 inode_lock_nested(inode, I_MUTEX_CHILD); 170 inode_lock_nested(inode, I_MUTEX_CHILD);
220 if (!ci->fscache) { 171 if (!ci->fscache) {
172 memset(&aux, 0, sizeof(aux));
173 aux.version = ci->i_version;
174 aux.mtime = inode->i_mtime;
175 aux.size = i_size_read(inode);
221 ci->fscache = fscache_acquire_cookie(fsc->fscache, 176 ci->fscache = fscache_acquire_cookie(fsc->fscache,
222 &ceph_fscache_inode_object_def, 177 &ceph_fscache_inode_object_def,
223 ci, false); 178 &ci->i_vino, sizeof(ci->i_vino),
179 &aux, sizeof(aux),
180 ci, false);
224 } 181 }
225 inode_unlock(inode); 182 inode_unlock(inode);
226} 183}
@@ -235,7 +192,7 @@ void ceph_fscache_unregister_inode_cookie(struct ceph_inode_info* ci)
235 ci->fscache = NULL; 192 ci->fscache = NULL;
236 193
237 fscache_uncache_all_inode_pages(cookie, &ci->vfs_inode); 194 fscache_uncache_all_inode_pages(cookie, &ci->vfs_inode);
238 fscache_relinquish_cookie(cookie, 0); 195 fscache_relinquish_cookie(cookie, &ci->i_vino, false);
239} 196}
240 197
241static bool ceph_fscache_can_enable(void *data) 198static bool ceph_fscache_can_enable(void *data)
@@ -254,11 +211,11 @@ void ceph_fscache_file_set_cookie(struct inode *inode, struct file *filp)
254 if (inode_is_open_for_write(inode)) { 211 if (inode_is_open_for_write(inode)) {
255 dout("fscache_file_set_cookie %p %p disabling cache\n", 212 dout("fscache_file_set_cookie %p %p disabling cache\n",
256 inode, filp); 213 inode, filp);
257 fscache_disable_cookie(ci->fscache, false); 214 fscache_disable_cookie(ci->fscache, &ci->i_vino, false);
258 fscache_uncache_all_inode_pages(ci->fscache, inode); 215 fscache_uncache_all_inode_pages(ci->fscache, inode);
259 } else { 216 } else {
260 fscache_enable_cookie(ci->fscache, ceph_fscache_can_enable, 217 fscache_enable_cookie(ci->fscache, &ci->i_vino,
261 inode); 218 ceph_fscache_can_enable, inode);
262 if (fscache_cookie_enabled(ci->fscache)) { 219 if (fscache_cookie_enabled(ci->fscache)) {
263 dout("fscache_file_set_cookie %p %p enabling cache\n", 220 dout("fscache_file_set_cookie %p %p enabling cache\n",
264 inode, filp); 221 inode, filp);
@@ -385,7 +342,7 @@ void ceph_fscache_unregister_fs(struct ceph_fs_client* fsc)
385 WARN_ON_ONCE(!found); 342 WARN_ON_ONCE(!found);
386 mutex_unlock(&ceph_fscache_lock); 343 mutex_unlock(&ceph_fscache_lock);
387 344
388 __fscache_relinquish_cookie(fsc->fscache, 0); 345 __fscache_relinquish_cookie(fsc->fscache, NULL, false);
389 } 346 }
390 fsc->fscache = NULL; 347 fsc->fscache = NULL;
391} 348}
@@ -402,7 +359,7 @@ void ceph_fscache_revalidate_cookie(struct ceph_inode_info *ci)
402 * truncate while the caller holds CEPH_CAP_FILE_RD */ 359 * truncate while the caller holds CEPH_CAP_FILE_RD */
403 mutex_lock(&ci->i_truncate_mutex); 360 mutex_lock(&ci->i_truncate_mutex);
404 if (!cache_valid(ci)) { 361 if (!cache_valid(ci)) {
405 if (fscache_check_consistency(ci->fscache)) 362 if (fscache_check_consistency(ci->fscache, &ci->i_vino))
406 fscache_invalidate(ci->fscache); 363 fscache_invalidate(ci->fscache);
407 spin_lock(&ci->i_ceph_lock); 364 spin_lock(&ci->i_ceph_lock);
408 ci->i_fscache_gen = ci->i_rdcache_gen; 365 ci->i_fscache_gen = ci->i_rdcache_gen;
diff --git a/fs/cifs/cache.c b/fs/cifs/cache.c
index 2c14020e5e1d..b4fa270ef532 100644
--- a/fs/cifs/cache.c
+++ b/fs/cifs/cache.c
@@ -46,67 +46,11 @@ void cifs_fscache_unregister(void)
46} 46}
47 47
48/* 48/*
49 * Key layout of CIFS server cache index object
50 */
51struct cifs_server_key {
52 uint16_t family; /* address family */
53 __be16 port; /* IP port */
54 union {
55 struct in_addr ipv4_addr;
56 struct in6_addr ipv6_addr;
57 } addr[0];
58};
59
60/*
61 * Server object keyed by {IPaddress,port,family} tuple
62 */
63static uint16_t cifs_server_get_key(const void *cookie_netfs_data,
64 void *buffer, uint16_t maxbuf)
65{
66 const struct TCP_Server_Info *server = cookie_netfs_data;
67 const struct sockaddr *sa = (struct sockaddr *) &server->dstaddr;
68 const struct sockaddr_in *addr = (struct sockaddr_in *) sa;
69 const struct sockaddr_in6 *addr6 = (struct sockaddr_in6 *) sa;
70 struct cifs_server_key *key = buffer;
71 uint16_t key_len = sizeof(struct cifs_server_key);
72
73 memset(key, 0, key_len);
74
75 /*
76 * Should not be a problem as sin_family/sin6_family overlays
77 * sa_family field
78 */
79 switch (sa->sa_family) {
80 case AF_INET:
81 key->family = sa->sa_family;
82 key->port = addr->sin_port;
83 key->addr[0].ipv4_addr = addr->sin_addr;
84 key_len += sizeof(key->addr[0].ipv4_addr);
85 break;
86
87 case AF_INET6:
88 key->family = sa->sa_family;
89 key->port = addr6->sin6_port;
90 key->addr[0].ipv6_addr = addr6->sin6_addr;
91 key_len += sizeof(key->addr[0].ipv6_addr);
92 break;
93
94 default:
95 cifs_dbg(VFS, "Unknown network family '%d'\n", sa->sa_family);
96 key_len = 0;
97 break;
98 }
99
100 return key_len;
101}
102
103/*
104 * Server object for FS-Cache 49 * Server object for FS-Cache
105 */ 50 */
106const struct fscache_cookie_def cifs_fscache_server_index_def = { 51const struct fscache_cookie_def cifs_fscache_server_index_def = {
107 .name = "CIFS.server", 52 .name = "CIFS.server",
108 .type = FSCACHE_COOKIE_TYPE_INDEX, 53 .type = FSCACHE_COOKIE_TYPE_INDEX,
109 .get_key = cifs_server_get_key,
110}; 54};
111 55
112/* 56/*
@@ -116,7 +60,7 @@ struct cifs_fscache_super_auxdata {
116 u64 resource_id; /* unique server resource id */ 60 u64 resource_id; /* unique server resource id */
117}; 61};
118 62
119static char *extract_sharename(const char *treename) 63char *extract_sharename(const char *treename)
120{ 64{
121 const char *src; 65 const char *src;
122 char *delim, *dst; 66 char *delim, *dst;
@@ -140,52 +84,6 @@ static char *extract_sharename(const char *treename)
140 return dst; 84 return dst;
141} 85}
142 86
143/*
144 * Superblock object currently keyed by share name
145 */
146static uint16_t cifs_super_get_key(const void *cookie_netfs_data, void *buffer,
147 uint16_t maxbuf)
148{
149 const struct cifs_tcon *tcon = cookie_netfs_data;
150 char *sharename;
151 uint16_t len;
152
153 sharename = extract_sharename(tcon->treeName);
154 if (IS_ERR(sharename)) {
155 cifs_dbg(FYI, "%s: couldn't extract sharename\n", __func__);
156 sharename = NULL;
157 return 0;
158 }
159
160 len = strlen(sharename);
161 if (len > maxbuf)
162 return 0;
163
164 memcpy(buffer, sharename, len);
165
166 kfree(sharename);
167
168 return len;
169}
170
171static uint16_t
172cifs_fscache_super_get_aux(const void *cookie_netfs_data, void *buffer,
173 uint16_t maxbuf)
174{
175 struct cifs_fscache_super_auxdata auxdata;
176 const struct cifs_tcon *tcon = cookie_netfs_data;
177
178 memset(&auxdata, 0, sizeof(auxdata));
179 auxdata.resource_id = tcon->resource_id;
180
181 if (maxbuf > sizeof(auxdata))
182 maxbuf = sizeof(auxdata);
183
184 memcpy(buffer, &auxdata, maxbuf);
185
186 return maxbuf;
187}
188
189static enum 87static enum
190fscache_checkaux cifs_fscache_super_check_aux(void *cookie_netfs_data, 88fscache_checkaux cifs_fscache_super_check_aux(void *cookie_netfs_data,
191 const void *data, 89 const void *data,
@@ -212,36 +110,9 @@ fscache_checkaux cifs_fscache_super_check_aux(void *cookie_netfs_data,
212const struct fscache_cookie_def cifs_fscache_super_index_def = { 110const struct fscache_cookie_def cifs_fscache_super_index_def = {
213 .name = "CIFS.super", 111 .name = "CIFS.super",
214 .type = FSCACHE_COOKIE_TYPE_INDEX, 112 .type = FSCACHE_COOKIE_TYPE_INDEX,
215 .get_key = cifs_super_get_key,
216 .get_aux = cifs_fscache_super_get_aux,
217 .check_aux = cifs_fscache_super_check_aux, 113 .check_aux = cifs_fscache_super_check_aux,
218}; 114};
219 115
220/*
221 * Auxiliary data attached to CIFS inode within the cache
222 */
223struct cifs_fscache_inode_auxdata {
224 struct timespec last_write_time;
225 struct timespec last_change_time;
226 u64 eof;
227};
228
229static uint16_t cifs_fscache_inode_get_key(const void *cookie_netfs_data,
230 void *buffer, uint16_t maxbuf)
231{
232 const struct cifsInodeInfo *cifsi = cookie_netfs_data;
233 uint16_t keylen;
234
235 /* use the UniqueId as the key */
236 keylen = sizeof(cifsi->uniqueid);
237 if (keylen > maxbuf)
238 keylen = 0;
239 else
240 memcpy(buffer, &cifsi->uniqueid, keylen);
241
242 return keylen;
243}
244
245static void 116static void
246cifs_fscache_inode_get_attr(const void *cookie_netfs_data, uint64_t *size) 117cifs_fscache_inode_get_attr(const void *cookie_netfs_data, uint64_t *size)
247{ 118{
@@ -250,26 +121,6 @@ cifs_fscache_inode_get_attr(const void *cookie_netfs_data, uint64_t *size)
250 *size = cifsi->vfs_inode.i_size; 121 *size = cifsi->vfs_inode.i_size;
251} 122}
252 123
253static uint16_t
254cifs_fscache_inode_get_aux(const void *cookie_netfs_data, void *buffer,
255 uint16_t maxbuf)
256{
257 struct cifs_fscache_inode_auxdata auxdata;
258 const struct cifsInodeInfo *cifsi = cookie_netfs_data;
259
260 memset(&auxdata, 0, sizeof(auxdata));
261 auxdata.eof = cifsi->server_eof;
262 auxdata.last_write_time = cifsi->vfs_inode.i_mtime;
263 auxdata.last_change_time = cifsi->vfs_inode.i_ctime;
264
265 if (maxbuf > sizeof(auxdata))
266 maxbuf = sizeof(auxdata);
267
268 memcpy(buffer, &auxdata, maxbuf);
269
270 return maxbuf;
271}
272
273static enum 124static enum
274fscache_checkaux cifs_fscache_inode_check_aux(void *cookie_netfs_data, 125fscache_checkaux cifs_fscache_inode_check_aux(void *cookie_netfs_data,
275 const void *data, 126 const void *data,
@@ -295,8 +146,6 @@ fscache_checkaux cifs_fscache_inode_check_aux(void *cookie_netfs_data,
295const struct fscache_cookie_def cifs_fscache_inode_object_def = { 146const struct fscache_cookie_def cifs_fscache_inode_object_def = {
296 .name = "CIFS.uniqueid", 147 .name = "CIFS.uniqueid",
297 .type = FSCACHE_COOKIE_TYPE_DATAFILE, 148 .type = FSCACHE_COOKIE_TYPE_DATAFILE,
298 .get_key = cifs_fscache_inode_get_key,
299 .get_attr = cifs_fscache_inode_get_attr, 149 .get_attr = cifs_fscache_inode_get_attr,
300 .get_aux = cifs_fscache_inode_get_aux,
301 .check_aux = cifs_fscache_inode_check_aux, 150 .check_aux = cifs_fscache_inode_check_aux,
302}; 151};
diff --git a/fs/cifs/fscache.c b/fs/cifs/fscache.c
index 8d4b7bc8ae91..b89b59b01759 100644
--- a/fs/cifs/fscache.c
+++ b/fs/cifs/fscache.c
@@ -23,11 +23,63 @@
23#include "cifs_debug.h" 23#include "cifs_debug.h"
24#include "cifs_fs_sb.h" 24#include "cifs_fs_sb.h"
25 25
26/*
27 * Key layout of CIFS server cache index object
28 */
29struct cifs_server_key {
30 struct {
31 uint16_t family; /* address family */
32 __be16 port; /* IP port */
33 } hdr;
34 union {
35 struct in_addr ipv4_addr;
36 struct in6_addr ipv6_addr;
37 };
38} __packed;
39
40/*
41 * Get a cookie for a server object keyed by {IPaddress,port,family} tuple
42 */
26void cifs_fscache_get_client_cookie(struct TCP_Server_Info *server) 43void cifs_fscache_get_client_cookie(struct TCP_Server_Info *server)
27{ 44{
45 const struct sockaddr *sa = (struct sockaddr *) &server->dstaddr;
46 const struct sockaddr_in *addr = (struct sockaddr_in *) sa;
47 const struct sockaddr_in6 *addr6 = (struct sockaddr_in6 *) sa;
48 struct cifs_server_key key;
49 uint16_t key_len = sizeof(key.hdr);
50
51 memset(&key, 0, sizeof(key));
52
53 /*
54 * Should not be a problem as sin_family/sin6_family overlays
55 * sa_family field
56 */
57 key.hdr.family = sa->sa_family;
58 switch (sa->sa_family) {
59 case AF_INET:
60 key.hdr.port = addr->sin_port;
61 key.ipv4_addr = addr->sin_addr;
62 key_len += sizeof(key.ipv4_addr);
63 break;
64
65 case AF_INET6:
66 key.hdr.port = addr6->sin6_port;
67 key.ipv6_addr = addr6->sin6_addr;
68 key_len += sizeof(key.ipv6_addr);
69 break;
70
71 default:
72 cifs_dbg(VFS, "Unknown network family '%d'\n", sa->sa_family);
73 server->fscache = NULL;
74 return;
75 }
76
28 server->fscache = 77 server->fscache =
29 fscache_acquire_cookie(cifs_fscache_netfs.primary_index, 78 fscache_acquire_cookie(cifs_fscache_netfs.primary_index,
30 &cifs_fscache_server_index_def, server, true); 79 &cifs_fscache_server_index_def,
80 &key, key_len,
81 NULL, 0,
82 server, true);
31 cifs_dbg(FYI, "%s: (0x%p/0x%p)\n", 83 cifs_dbg(FYI, "%s: (0x%p/0x%p)\n",
32 __func__, server, server->fscache); 84 __func__, server, server->fscache);
33} 85}
@@ -36,17 +88,29 @@ void cifs_fscache_release_client_cookie(struct TCP_Server_Info *server)
36{ 88{
37 cifs_dbg(FYI, "%s: (0x%p/0x%p)\n", 89 cifs_dbg(FYI, "%s: (0x%p/0x%p)\n",
38 __func__, server, server->fscache); 90 __func__, server, server->fscache);
39 fscache_relinquish_cookie(server->fscache, 0); 91 fscache_relinquish_cookie(server->fscache, NULL, false);
40 server->fscache = NULL; 92 server->fscache = NULL;
41} 93}
42 94
43void cifs_fscache_get_super_cookie(struct cifs_tcon *tcon) 95void cifs_fscache_get_super_cookie(struct cifs_tcon *tcon)
44{ 96{
45 struct TCP_Server_Info *server = tcon->ses->server; 97 struct TCP_Server_Info *server = tcon->ses->server;
98 char *sharename;
99
100 sharename = extract_sharename(tcon->treeName);
101 if (IS_ERR(sharename)) {
102 cifs_dbg(FYI, "%s: couldn't extract sharename\n", __func__);
103 tcon->fscache = NULL;
104 return;
105 }
46 106
47 tcon->fscache = 107 tcon->fscache =
48 fscache_acquire_cookie(server->fscache, 108 fscache_acquire_cookie(server->fscache,
49 &cifs_fscache_super_index_def, tcon, true); 109 &cifs_fscache_super_index_def,
110 sharename, strlen(sharename),
111 &tcon->resource_id, sizeof(tcon->resource_id),
112 tcon, true);
113 kfree(sharename);
50 cifs_dbg(FYI, "%s: (0x%p/0x%p)\n", 114 cifs_dbg(FYI, "%s: (0x%p/0x%p)\n",
51 __func__, server->fscache, tcon->fscache); 115 __func__, server->fscache, tcon->fscache);
52} 116}
@@ -54,10 +118,28 @@ void cifs_fscache_get_super_cookie(struct cifs_tcon *tcon)
54void cifs_fscache_release_super_cookie(struct cifs_tcon *tcon) 118void cifs_fscache_release_super_cookie(struct cifs_tcon *tcon)
55{ 119{
56 cifs_dbg(FYI, "%s: (0x%p)\n", __func__, tcon->fscache); 120 cifs_dbg(FYI, "%s: (0x%p)\n", __func__, tcon->fscache);
57 fscache_relinquish_cookie(tcon->fscache, 0); 121 fscache_relinquish_cookie(tcon->fscache, &tcon->resource_id, false);
58 tcon->fscache = NULL; 122 tcon->fscache = NULL;
59} 123}
60 124
125static void cifs_fscache_acquire_inode_cookie(struct cifsInodeInfo *cifsi,
126 struct cifs_tcon *tcon)
127{
128 struct cifs_fscache_inode_auxdata auxdata;
129
130 memset(&auxdata, 0, sizeof(auxdata));
131 auxdata.eof = cifsi->server_eof;
132 auxdata.last_write_time = cifsi->vfs_inode.i_mtime;
133 auxdata.last_change_time = cifsi->vfs_inode.i_ctime;
134
135 cifsi->fscache =
136 fscache_acquire_cookie(tcon->fscache,
137 &cifs_fscache_inode_object_def,
138 &cifsi->uniqueid, sizeof(cifsi->uniqueid),
139 &auxdata, sizeof(auxdata),
140 cifsi, true);
141}
142
61static void cifs_fscache_enable_inode_cookie(struct inode *inode) 143static void cifs_fscache_enable_inode_cookie(struct inode *inode)
62{ 144{
63 struct cifsInodeInfo *cifsi = CIFS_I(inode); 145 struct cifsInodeInfo *cifsi = CIFS_I(inode);
@@ -67,21 +149,28 @@ static void cifs_fscache_enable_inode_cookie(struct inode *inode)
67 if (cifsi->fscache) 149 if (cifsi->fscache)
68 return; 150 return;
69 151
70 if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_FSCACHE) { 152 if (!(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_FSCACHE))
71 cifsi->fscache = fscache_acquire_cookie(tcon->fscache, 153 return;
72 &cifs_fscache_inode_object_def, cifsi, true); 154
73 cifs_dbg(FYI, "%s: got FH cookie (0x%p/0x%p)\n", 155 cifs_fscache_acquire_inode_cookie(cifsi, tcon);
74 __func__, tcon->fscache, cifsi->fscache); 156
75 } 157 cifs_dbg(FYI, "%s: got FH cookie (0x%p/0x%p)\n",
158 __func__, tcon->fscache, cifsi->fscache);
76} 159}
77 160
78void cifs_fscache_release_inode_cookie(struct inode *inode) 161void cifs_fscache_release_inode_cookie(struct inode *inode)
79{ 162{
163 struct cifs_fscache_inode_auxdata auxdata;
80 struct cifsInodeInfo *cifsi = CIFS_I(inode); 164 struct cifsInodeInfo *cifsi = CIFS_I(inode);
81 165
82 if (cifsi->fscache) { 166 if (cifsi->fscache) {
167 memset(&auxdata, 0, sizeof(auxdata));
168 auxdata.eof = cifsi->server_eof;
169 auxdata.last_write_time = cifsi->vfs_inode.i_mtime;
170 auxdata.last_change_time = cifsi->vfs_inode.i_ctime;
171
83 cifs_dbg(FYI, "%s: (0x%p)\n", __func__, cifsi->fscache); 172 cifs_dbg(FYI, "%s: (0x%p)\n", __func__, cifsi->fscache);
84 fscache_relinquish_cookie(cifsi->fscache, 0); 173 fscache_relinquish_cookie(cifsi->fscache, &auxdata, false);
85 cifsi->fscache = NULL; 174 cifsi->fscache = NULL;
86 } 175 }
87} 176}
@@ -93,7 +182,7 @@ static void cifs_fscache_disable_inode_cookie(struct inode *inode)
93 if (cifsi->fscache) { 182 if (cifsi->fscache) {
94 cifs_dbg(FYI, "%s: (0x%p)\n", __func__, cifsi->fscache); 183 cifs_dbg(FYI, "%s: (0x%p)\n", __func__, cifsi->fscache);
95 fscache_uncache_all_inode_pages(cifsi->fscache, inode); 184 fscache_uncache_all_inode_pages(cifsi->fscache, inode);
96 fscache_relinquish_cookie(cifsi->fscache, 1); 185 fscache_relinquish_cookie(cifsi->fscache, NULL, true);
97 cifsi->fscache = NULL; 186 cifsi->fscache = NULL;
98 } 187 }
99} 188}
@@ -110,16 +199,14 @@ void cifs_fscache_reset_inode_cookie(struct inode *inode)
110{ 199{
111 struct cifsInodeInfo *cifsi = CIFS_I(inode); 200 struct cifsInodeInfo *cifsi = CIFS_I(inode);
112 struct cifs_sb_info *cifs_sb = CIFS_SB(inode->i_sb); 201 struct cifs_sb_info *cifs_sb = CIFS_SB(inode->i_sb);
202 struct cifs_tcon *tcon = cifs_sb_master_tcon(cifs_sb);
113 struct fscache_cookie *old = cifsi->fscache; 203 struct fscache_cookie *old = cifsi->fscache;
114 204
115 if (cifsi->fscache) { 205 if (cifsi->fscache) {
116 /* retire the current fscache cache and get a new one */ 206 /* retire the current fscache cache and get a new one */
117 fscache_relinquish_cookie(cifsi->fscache, 1); 207 fscache_relinquish_cookie(cifsi->fscache, NULL, true);
118 208
119 cifsi->fscache = fscache_acquire_cookie( 209 cifs_fscache_acquire_inode_cookie(cifsi, tcon);
120 cifs_sb_master_tcon(cifs_sb)->fscache,
121 &cifs_fscache_inode_object_def,
122 cifsi, true);
123 cifs_dbg(FYI, "%s: new cookie 0x%p oldcookie 0x%p\n", 210 cifs_dbg(FYI, "%s: new cookie 0x%p oldcookie 0x%p\n",
124 __func__, cifsi->fscache, old); 211 __func__, cifsi->fscache, old);
125 } 212 }
@@ -239,4 +326,3 @@ void __cifs_fscache_invalidate_page(struct page *page, struct inode *inode)
239 fscache_wait_on_page_write(cookie, page); 326 fscache_wait_on_page_write(cookie, page);
240 fscache_uncache_page(cookie, page); 327 fscache_uncache_page(cookie, page);
241} 328}
242
diff --git a/fs/cifs/fscache.h b/fs/cifs/fscache.h
index 24794b6cd8ec..c7e3ac251e16 100644
--- a/fs/cifs/fscache.h
+++ b/fs/cifs/fscache.h
@@ -27,6 +27,18 @@
27 27
28#ifdef CONFIG_CIFS_FSCACHE 28#ifdef CONFIG_CIFS_FSCACHE
29 29
30/*
31 * Auxiliary data attached to CIFS inode within the cache
32 */
33struct cifs_fscache_inode_auxdata {
34 struct timespec last_write_time;
35 struct timespec last_change_time;
36 u64 eof;
37};
38
39/*
40 * cache.c
41 */
30extern struct fscache_netfs cifs_fscache_netfs; 42extern struct fscache_netfs cifs_fscache_netfs;
31extern const struct fscache_cookie_def cifs_fscache_server_index_def; 43extern const struct fscache_cookie_def cifs_fscache_server_index_def;
32extern const struct fscache_cookie_def cifs_fscache_super_index_def; 44extern const struct fscache_cookie_def cifs_fscache_super_index_def;
@@ -34,6 +46,7 @@ extern const struct fscache_cookie_def cifs_fscache_inode_object_def;
34 46
35extern int cifs_fscache_register(void); 47extern int cifs_fscache_register(void);
36extern void cifs_fscache_unregister(void); 48extern void cifs_fscache_unregister(void);
49extern char *extract_sharename(const char *);
37 50
38/* 51/*
39 * fscache.c 52 * fscache.c
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 &&
diff --git a/fs/nfs/fscache-index.c b/fs/nfs/fscache-index.c
index 0ee4b93d36ea..6fd3679b7137 100644
--- a/fs/nfs/fscache-index.c
+++ b/fs/nfs/fscache-index.c
@@ -50,59 +50,6 @@ void nfs_fscache_unregister(void)
50} 50}
51 51
52/* 52/*
53 * Layout of the key for an NFS server cache object.
54 */
55struct nfs_server_key {
56 uint16_t nfsversion; /* NFS protocol version */
57 uint16_t family; /* address family */
58 uint16_t port; /* IP port */
59 union {
60 struct in_addr ipv4_addr; /* IPv4 address */
61 struct in6_addr ipv6_addr; /* IPv6 address */
62 } addr[0];
63};
64
65/*
66 * Generate a key to describe a server in the main NFS index
67 * - We return the length of the key, or 0 if we can't generate one
68 */
69static uint16_t nfs_server_get_key(const void *cookie_netfs_data,
70 void *buffer, uint16_t bufmax)
71{
72 const struct nfs_client *clp = cookie_netfs_data;
73 const struct sockaddr_in6 *sin6 = (struct sockaddr_in6 *) &clp->cl_addr;
74 const struct sockaddr_in *sin = (struct sockaddr_in *) &clp->cl_addr;
75 struct nfs_server_key *key = buffer;
76 uint16_t len = sizeof(struct nfs_server_key);
77
78 memset(key, 0, len);
79 key->nfsversion = clp->rpc_ops->version;
80 key->family = clp->cl_addr.ss_family;
81
82 switch (clp->cl_addr.ss_family) {
83 case AF_INET:
84 key->port = sin->sin_port;
85 key->addr[0].ipv4_addr = sin->sin_addr;
86 len += sizeof(key->addr[0].ipv4_addr);
87 break;
88
89 case AF_INET6:
90 key->port = sin6->sin6_port;
91 key->addr[0].ipv6_addr = sin6->sin6_addr;
92 len += sizeof(key->addr[0].ipv6_addr);
93 break;
94
95 default:
96 printk(KERN_WARNING "NFS: Unknown network family '%d'\n",
97 clp->cl_addr.ss_family);
98 len = 0;
99 break;
100 }
101
102 return len;
103}
104
105/*
106 * Define the server object for FS-Cache. This is used to describe a server 53 * Define the server object for FS-Cache. This is used to describe a server
107 * object to fscache_acquire_cookie(). It is keyed by the NFS protocol and 54 * object to fscache_acquire_cookie(). It is keyed by the NFS protocol and
108 * server address parameters. 55 * server address parameters.
@@ -110,33 +57,9 @@ static uint16_t nfs_server_get_key(const void *cookie_netfs_data,
110const struct fscache_cookie_def nfs_fscache_server_index_def = { 57const struct fscache_cookie_def nfs_fscache_server_index_def = {
111 .name = "NFS.server", 58 .name = "NFS.server",
112 .type = FSCACHE_COOKIE_TYPE_INDEX, 59 .type = FSCACHE_COOKIE_TYPE_INDEX,
113 .get_key = nfs_server_get_key,
114}; 60};
115 61
116/* 62/*
117 * Generate a key to describe a superblock key in the main NFS index
118 */
119static uint16_t nfs_super_get_key(const void *cookie_netfs_data,
120 void *buffer, uint16_t bufmax)
121{
122 const struct nfs_fscache_key *key;
123 const struct nfs_server *nfss = cookie_netfs_data;
124 uint16_t len;
125
126 key = nfss->fscache_key;
127 len = sizeof(key->key) + key->key.uniq_len;
128 if (len > bufmax) {
129 len = 0;
130 } else {
131 memcpy(buffer, &key->key, sizeof(key->key));
132 memcpy(buffer + sizeof(key->key),
133 key->key.uniquifier, key->key.uniq_len);
134 }
135
136 return len;
137}
138
139/*
140 * Define the superblock object for FS-Cache. This is used to describe a 63 * Define the superblock object for FS-Cache. This is used to describe a
141 * superblock object to fscache_acquire_cookie(). It is keyed by all the NFS 64 * superblock object to fscache_acquire_cookie(). It is keyed by all the NFS
142 * parameters that might cause a separate superblock. 65 * parameters that might cause a separate superblock.
@@ -144,41 +67,9 @@ static uint16_t nfs_super_get_key(const void *cookie_netfs_data,
144const struct fscache_cookie_def nfs_fscache_super_index_def = { 67const struct fscache_cookie_def nfs_fscache_super_index_def = {
145 .name = "NFS.super", 68 .name = "NFS.super",
146 .type = FSCACHE_COOKIE_TYPE_INDEX, 69 .type = FSCACHE_COOKIE_TYPE_INDEX,
147 .get_key = nfs_super_get_key,
148}; 70};
149 71
150/* 72/*
151 * Definition of the auxiliary data attached to NFS inode storage objects
152 * within the cache.
153 *
154 * The contents of this struct are recorded in the on-disk local cache in the
155 * auxiliary data attached to the data storage object backing an inode. This
156 * permits coherency to be managed when a new inode binds to an already extant
157 * cache object.
158 */
159struct nfs_fscache_inode_auxdata {
160 struct timespec mtime;
161 struct timespec ctime;
162 loff_t size;
163 u64 change_attr;
164};
165
166/*
167 * Generate a key to describe an NFS inode in an NFS server's index
168 */
169static uint16_t nfs_fscache_inode_get_key(const void *cookie_netfs_data,
170 void *buffer, uint16_t bufmax)
171{
172 const struct nfs_inode *nfsi = cookie_netfs_data;
173 uint16_t nsize;
174
175 /* use the inode's NFS filehandle as the key */
176 nsize = nfsi->fh.size;
177 memcpy(buffer, nfsi->fh.data, nsize);
178 return nsize;
179}
180
181/*
182 * Get certain file attributes from the netfs data 73 * Get certain file attributes from the netfs data
183 * - This function can be absent for an index 74 * - This function can be absent for an index
184 * - Not permitted to return an error 75 * - Not permitted to return an error
@@ -193,35 +84,6 @@ static void nfs_fscache_inode_get_attr(const void *cookie_netfs_data,
193} 84}
194 85
195/* 86/*
196 * Get the auxiliary data from netfs data
197 * - This function can be absent if the index carries no state data
198 * - Should store the auxiliary data in the buffer
199 * - Should return the amount of amount stored
200 * - Not permitted to return an error
201 * - The netfs data from the cookie being used as the source is presented
202 */
203static uint16_t nfs_fscache_inode_get_aux(const void *cookie_netfs_data,
204 void *buffer, uint16_t bufmax)
205{
206 struct nfs_fscache_inode_auxdata auxdata;
207 const struct nfs_inode *nfsi = cookie_netfs_data;
208
209 memset(&auxdata, 0, sizeof(auxdata));
210 auxdata.size = nfsi->vfs_inode.i_size;
211 auxdata.mtime = nfsi->vfs_inode.i_mtime;
212 auxdata.ctime = nfsi->vfs_inode.i_ctime;
213
214 if (NFS_SERVER(&nfsi->vfs_inode)->nfs_client->rpc_ops->version == 4)
215 auxdata.change_attr = inode_peek_iversion_raw(&nfsi->vfs_inode);
216
217 if (bufmax > sizeof(auxdata))
218 bufmax = sizeof(auxdata);
219
220 memcpy(buffer, &auxdata, bufmax);
221 return bufmax;
222}
223
224/*
225 * Consult the netfs about the state of an object 87 * Consult the netfs about the state of an object
226 * - This function can be absent if the index carries no state data 88 * - This function can be absent if the index carries no state data
227 * - The netfs data from the cookie being used as the target is 89 * - The netfs data from the cookie being used as the target is
@@ -288,9 +150,7 @@ static void nfs_fh_put_context(void *cookie_netfs_data, void *context)
288const struct fscache_cookie_def nfs_fscache_inode_object_def = { 150const struct fscache_cookie_def nfs_fscache_inode_object_def = {
289 .name = "NFS.fh", 151 .name = "NFS.fh",
290 .type = FSCACHE_COOKIE_TYPE_DATAFILE, 152 .type = FSCACHE_COOKIE_TYPE_DATAFILE,
291 .get_key = nfs_fscache_inode_get_key,
292 .get_attr = nfs_fscache_inode_get_attr, 153 .get_attr = nfs_fscache_inode_get_attr,
293 .get_aux = nfs_fscache_inode_get_aux,
294 .check_aux = nfs_fscache_inode_check_aux, 154 .check_aux = nfs_fscache_inode_check_aux,
295 .get_context = nfs_fh_get_context, 155 .get_context = nfs_fh_get_context,
296 .put_context = nfs_fh_put_context, 156 .put_context = nfs_fh_put_context,
diff --git a/fs/nfs/fscache.c b/fs/nfs/fscache.c
index d63bea8bbfbb..c45ba2691cee 100644
--- a/fs/nfs/fscache.c
+++ b/fs/nfs/fscache.c
@@ -18,6 +18,7 @@
18#include <linux/in6.h> 18#include <linux/in6.h>
19#include <linux/seq_file.h> 19#include <linux/seq_file.h>
20#include <linux/slab.h> 20#include <linux/slab.h>
21#include <linux/iversion.h>
21 22
22#include "internal.h" 23#include "internal.h"
23#include "iostat.h" 24#include "iostat.h"
@@ -29,6 +30,21 @@ static struct rb_root nfs_fscache_keys = RB_ROOT;
29static DEFINE_SPINLOCK(nfs_fscache_keys_lock); 30static DEFINE_SPINLOCK(nfs_fscache_keys_lock);
30 31
31/* 32/*
33 * Layout of the key for an NFS server cache object.
34 */
35struct nfs_server_key {
36 struct {
37 uint16_t nfsversion; /* NFS protocol version */
38 uint16_t family; /* address family */
39 __be16 port; /* IP port */
40 } hdr;
41 union {
42 struct in_addr ipv4_addr; /* IPv4 address */
43 struct in6_addr ipv6_addr; /* IPv6 address */
44 };
45} __packed;
46
47/*
32 * Get the per-client index cookie for an NFS client if the appropriate mount 48 * Get the per-client index cookie for an NFS client if the appropriate mount
33 * flag was set 49 * flag was set
34 * - We always try and get an index cookie for the client, but get filehandle 50 * - We always try and get an index cookie for the client, but get filehandle
@@ -36,9 +52,40 @@ static DEFINE_SPINLOCK(nfs_fscache_keys_lock);
36 */ 52 */
37void nfs_fscache_get_client_cookie(struct nfs_client *clp) 53void nfs_fscache_get_client_cookie(struct nfs_client *clp)
38{ 54{
55 const struct sockaddr_in6 *sin6 = (struct sockaddr_in6 *) &clp->cl_addr;
56 const struct sockaddr_in *sin = (struct sockaddr_in *) &clp->cl_addr;
57 struct nfs_server_key key;
58 uint16_t len = sizeof(key.hdr);
59
60 memset(&key, 0, sizeof(key));
61 key.hdr.nfsversion = clp->rpc_ops->version;
62 key.hdr.family = clp->cl_addr.ss_family;
63
64 switch (clp->cl_addr.ss_family) {
65 case AF_INET:
66 key.hdr.port = sin->sin_port;
67 key.ipv4_addr = sin->sin_addr;
68 len += sizeof(key.ipv4_addr);
69 break;
70
71 case AF_INET6:
72 key.hdr.port = sin6->sin6_port;
73 key.ipv6_addr = sin6->sin6_addr;
74 len += sizeof(key.ipv6_addr);
75 break;
76
77 default:
78 printk(KERN_WARNING "NFS: Unknown network family '%d'\n",
79 clp->cl_addr.ss_family);
80 clp->fscache = NULL;
81 return;
82 }
83
39 /* create a cache index for looking up filehandles */ 84 /* create a cache index for looking up filehandles */
40 clp->fscache = fscache_acquire_cookie(nfs_fscache_netfs.primary_index, 85 clp->fscache = fscache_acquire_cookie(nfs_fscache_netfs.primary_index,
41 &nfs_fscache_server_index_def, 86 &nfs_fscache_server_index_def,
87 &key, len,
88 NULL, 0,
42 clp, true); 89 clp, true);
43 dfprintk(FSCACHE, "NFS: get client cookie (0x%p/0x%p)\n", 90 dfprintk(FSCACHE, "NFS: get client cookie (0x%p/0x%p)\n",
44 clp, clp->fscache); 91 clp, clp->fscache);
@@ -52,7 +99,7 @@ void nfs_fscache_release_client_cookie(struct nfs_client *clp)
52 dfprintk(FSCACHE, "NFS: releasing client cookie (0x%p/0x%p)\n", 99 dfprintk(FSCACHE, "NFS: releasing client cookie (0x%p/0x%p)\n",
53 clp, clp->fscache); 100 clp, clp->fscache);
54 101
55 fscache_relinquish_cookie(clp->fscache, 0); 102 fscache_relinquish_cookie(clp->fscache, NULL, false);
56 clp->fscache = NULL; 103 clp->fscache = NULL;
57} 104}
58 105
@@ -139,6 +186,8 @@ void nfs_fscache_get_super_cookie(struct super_block *sb, const char *uniq, int
139 /* create a cache index for looking up filehandles */ 186 /* create a cache index for looking up filehandles */
140 nfss->fscache = fscache_acquire_cookie(nfss->nfs_client->fscache, 187 nfss->fscache = fscache_acquire_cookie(nfss->nfs_client->fscache,
141 &nfs_fscache_super_index_def, 188 &nfs_fscache_super_index_def,
189 key, sizeof(*key) + ulen,
190 NULL, 0,
142 nfss, true); 191 nfss, true);
143 dfprintk(FSCACHE, "NFS: get superblock cookie (0x%p/0x%p)\n", 192 dfprintk(FSCACHE, "NFS: get superblock cookie (0x%p/0x%p)\n",
144 nfss, nfss->fscache); 193 nfss, nfss->fscache);
@@ -163,7 +212,7 @@ void nfs_fscache_release_super_cookie(struct super_block *sb)
163 dfprintk(FSCACHE, "NFS: releasing superblock cookie (0x%p/0x%p)\n", 212 dfprintk(FSCACHE, "NFS: releasing superblock cookie (0x%p/0x%p)\n",
164 nfss, nfss->fscache); 213 nfss, nfss->fscache);
165 214
166 fscache_relinquish_cookie(nfss->fscache, 0); 215 fscache_relinquish_cookie(nfss->fscache, NULL, false);
167 nfss->fscache = NULL; 216 nfss->fscache = NULL;
168 217
169 if (nfss->fscache_key) { 218 if (nfss->fscache_key) {
@@ -180,13 +229,25 @@ void nfs_fscache_release_super_cookie(struct super_block *sb)
180 */ 229 */
181void nfs_fscache_init_inode(struct inode *inode) 230void nfs_fscache_init_inode(struct inode *inode)
182{ 231{
232 struct nfs_fscache_inode_auxdata auxdata;
183 struct nfs_inode *nfsi = NFS_I(inode); 233 struct nfs_inode *nfsi = NFS_I(inode);
184 234
185 nfsi->fscache = NULL; 235 nfsi->fscache = NULL;
186 if (!S_ISREG(inode->i_mode)) 236 if (!S_ISREG(inode->i_mode))
187 return; 237 return;
238
239 memset(&auxdata, 0, sizeof(auxdata));
240 auxdata.size = nfsi->vfs_inode.i_size;
241 auxdata.mtime = nfsi->vfs_inode.i_mtime;
242 auxdata.ctime = nfsi->vfs_inode.i_ctime;
243
244 if (NFS_SERVER(&nfsi->vfs_inode)->nfs_client->rpc_ops->version == 4)
245 auxdata.change_attr = inode_peek_iversion_raw(&nfsi->vfs_inode);
246
188 nfsi->fscache = fscache_acquire_cookie(NFS_SB(inode->i_sb)->fscache, 247 nfsi->fscache = fscache_acquire_cookie(NFS_SB(inode->i_sb)->fscache,
189 &nfs_fscache_inode_object_def, 248 &nfs_fscache_inode_object_def,
249 nfsi->fh.data, nfsi->fh.size,
250 &auxdata, sizeof(auxdata),
190 nfsi, false); 251 nfsi, false);
191} 252}
192 253
@@ -195,12 +256,17 @@ void nfs_fscache_init_inode(struct inode *inode)
195 */ 256 */
196void nfs_fscache_clear_inode(struct inode *inode) 257void nfs_fscache_clear_inode(struct inode *inode)
197{ 258{
259 struct nfs_fscache_inode_auxdata auxdata;
198 struct nfs_inode *nfsi = NFS_I(inode); 260 struct nfs_inode *nfsi = NFS_I(inode);
199 struct fscache_cookie *cookie = nfs_i_fscache(inode); 261 struct fscache_cookie *cookie = nfs_i_fscache(inode);
200 262
201 dfprintk(FSCACHE, "NFS: clear cookie (0x%p/0x%p)\n", nfsi, cookie); 263 dfprintk(FSCACHE, "NFS: clear cookie (0x%p/0x%p)\n", nfsi, cookie);
202 264
203 fscache_relinquish_cookie(cookie, false); 265 memset(&auxdata, 0, sizeof(auxdata));
266 auxdata.size = nfsi->vfs_inode.i_size;
267 auxdata.mtime = nfsi->vfs_inode.i_mtime;
268 auxdata.ctime = nfsi->vfs_inode.i_ctime;
269 fscache_relinquish_cookie(cookie, &auxdata, false);
204 nfsi->fscache = NULL; 270 nfsi->fscache = NULL;
205} 271}
206 272
@@ -232,20 +298,27 @@ static bool nfs_fscache_can_enable(void *data)
232 */ 298 */
233void nfs_fscache_open_file(struct inode *inode, struct file *filp) 299void nfs_fscache_open_file(struct inode *inode, struct file *filp)
234{ 300{
301 struct nfs_fscache_inode_auxdata auxdata;
235 struct nfs_inode *nfsi = NFS_I(inode); 302 struct nfs_inode *nfsi = NFS_I(inode);
236 struct fscache_cookie *cookie = nfs_i_fscache(inode); 303 struct fscache_cookie *cookie = nfs_i_fscache(inode);
237 304
238 if (!fscache_cookie_valid(cookie)) 305 if (!fscache_cookie_valid(cookie))
239 return; 306 return;
240 307
308 memset(&auxdata, 0, sizeof(auxdata));
309 auxdata.size = nfsi->vfs_inode.i_size;
310 auxdata.mtime = nfsi->vfs_inode.i_mtime;
311 auxdata.ctime = nfsi->vfs_inode.i_ctime;
312
241 if (inode_is_open_for_write(inode)) { 313 if (inode_is_open_for_write(inode)) {
242 dfprintk(FSCACHE, "NFS: nfsi 0x%p disabling cache\n", nfsi); 314 dfprintk(FSCACHE, "NFS: nfsi 0x%p disabling cache\n", nfsi);
243 clear_bit(NFS_INO_FSCACHE, &nfsi->flags); 315 clear_bit(NFS_INO_FSCACHE, &nfsi->flags);
244 fscache_disable_cookie(cookie, true); 316 fscache_disable_cookie(cookie, &auxdata, true);
245 fscache_uncache_all_inode_pages(cookie, inode); 317 fscache_uncache_all_inode_pages(cookie, inode);
246 } else { 318 } else {
247 dfprintk(FSCACHE, "NFS: nfsi 0x%p enabling cache\n", nfsi); 319 dfprintk(FSCACHE, "NFS: nfsi 0x%p enabling cache\n", nfsi);
248 fscache_enable_cookie(cookie, nfs_fscache_can_enable, inode); 320 fscache_enable_cookie(cookie, &auxdata,
321 nfs_fscache_can_enable, inode);
249 if (fscache_cookie_enabled(cookie)) 322 if (fscache_cookie_enabled(cookie))
250 set_bit(NFS_INO_FSCACHE, &NFS_I(inode)->flags); 323 set_bit(NFS_INO_FSCACHE, &NFS_I(inode)->flags);
251 } 324 }
diff --git a/fs/nfs/fscache.h b/fs/nfs/fscache.h
index d7fe3e799f2f..96e989f579d1 100644
--- a/fs/nfs/fscache.h
+++ b/fs/nfs/fscache.h
@@ -57,6 +57,22 @@ struct nfs_fscache_key {
57}; 57};
58 58
59/* 59/*
60 * Definition of the auxiliary data attached to NFS inode storage objects
61 * within the cache.
62 *
63 * The contents of this struct are recorded in the on-disk local cache in the
64 * auxiliary data attached to the data storage object backing an inode. This
65 * permits coherency to be managed when a new inode binds to an already extant
66 * cache object.
67 */
68struct nfs_fscache_inode_auxdata {
69 struct timespec mtime;
70 struct timespec ctime;
71 loff_t size;
72 u64 change_attr;
73};
74
75/*
60 * fscache-index.c 76 * fscache-index.c
61 */ 77 */
62extern struct fscache_netfs nfs_fscache_netfs; 78extern struct fscache_netfs nfs_fscache_netfs;
diff --git a/include/linux/fscache.h b/include/linux/fscache.h
index fe0c349684fa..a2d3a2116248 100644
--- a/include/linux/fscache.h
+++ b/include/linux/fscache.h
@@ -83,17 +83,6 @@ struct fscache_cookie_def {
83 const void *parent_netfs_data, 83 const void *parent_netfs_data,
84 const void *cookie_netfs_data); 84 const void *cookie_netfs_data);
85 85
86 /* get an index key
87 * - should store the key data in the buffer
88 * - should return the amount of data stored
89 * - not permitted to return an error
90 * - the netfs data from the cookie being used as the source is
91 * presented
92 */
93 uint16_t (*get_key)(const void *cookie_netfs_data,
94 void *buffer,
95 uint16_t bufmax);
96
97 /* get certain file attributes from the netfs data 86 /* get certain file attributes from the netfs data
98 * - this function can be absent for an index 87 * - this function can be absent for an index
99 * - not permitted to return an error 88 * - not permitted to return an error
@@ -102,18 +91,6 @@ struct fscache_cookie_def {
102 */ 91 */
103 void (*get_attr)(const void *cookie_netfs_data, uint64_t *size); 92 void (*get_attr)(const void *cookie_netfs_data, uint64_t *size);
104 93
105 /* get the auxiliary data from netfs data
106 * - this function can be absent if the index carries no state data
107 * - should store the auxiliary data in the buffer
108 * - should return the amount of amount stored
109 * - not permitted to return an error
110 * - the netfs data from the cookie being used as the source is
111 * presented
112 */
113 uint16_t (*get_aux)(const void *cookie_netfs_data,
114 void *buffer,
115 uint16_t bufmax);
116
117 /* consult the netfs about the state of an object 94 /* consult the netfs about the state of an object
118 * - this function can be absent if the index carries no state data 95 * - this function can be absent if the index carries no state data
119 * - the netfs data from the cookie being used as the target is 96 * - the netfs data from the cookie being used as the target is
@@ -186,6 +163,19 @@ struct fscache_cookie {
186#define FSCACHE_COOKIE_RELINQUISHED 4 /* T if cookie has been relinquished */ 163#define FSCACHE_COOKIE_RELINQUISHED 4 /* T if cookie has been relinquished */
187#define FSCACHE_COOKIE_ENABLED 5 /* T if cookie is enabled */ 164#define FSCACHE_COOKIE_ENABLED 5 /* T if cookie is enabled */
188#define FSCACHE_COOKIE_ENABLEMENT_LOCK 6 /* T if cookie is being en/disabled */ 165#define FSCACHE_COOKIE_ENABLEMENT_LOCK 6 /* T if cookie is being en/disabled */
166#define FSCACHE_COOKIE_AUX_UPDATED 7 /* T if the auxiliary data was updated */
167
168 u8 type; /* Type of object */
169 u8 key_len; /* Length of index key */
170 u8 aux_len; /* Length of auxiliary data */
171 union {
172 void *key; /* Index key */
173 u8 inline_key[16]; /* - If the key is short enough */
174 };
175 union {
176 void *aux; /* Auxiliary data */
177 u8 inline_aux[8]; /* - If the aux data is short enough */
178 };
189}; 179};
190 180
191static inline bool fscache_cookie_enabled(struct fscache_cookie *cookie) 181static inline bool fscache_cookie_enabled(struct fscache_cookie *cookie)
@@ -208,10 +198,12 @@ extern void __fscache_release_cache_tag(struct fscache_cache_tag *);
208extern struct fscache_cookie *__fscache_acquire_cookie( 198extern struct fscache_cookie *__fscache_acquire_cookie(
209 struct fscache_cookie *, 199 struct fscache_cookie *,
210 const struct fscache_cookie_def *, 200 const struct fscache_cookie_def *,
201 const void *, size_t,
202 const void *, size_t,
211 void *, bool); 203 void *, bool);
212extern void __fscache_relinquish_cookie(struct fscache_cookie *, bool); 204extern void __fscache_relinquish_cookie(struct fscache_cookie *, const void *, bool);
213extern int __fscache_check_consistency(struct fscache_cookie *); 205extern int __fscache_check_consistency(struct fscache_cookie *, const void *);
214extern void __fscache_update_cookie(struct fscache_cookie *); 206extern void __fscache_update_cookie(struct fscache_cookie *, const void *);
215extern int __fscache_attr_changed(struct fscache_cookie *); 207extern int __fscache_attr_changed(struct fscache_cookie *);
216extern void __fscache_invalidate(struct fscache_cookie *); 208extern void __fscache_invalidate(struct fscache_cookie *);
217extern void __fscache_wait_on_invalidate(struct fscache_cookie *); 209extern void __fscache_wait_on_invalidate(struct fscache_cookie *);
@@ -238,8 +230,8 @@ extern void __fscache_uncache_all_inode_pages(struct fscache_cookie *,
238 struct inode *); 230 struct inode *);
239extern void __fscache_readpages_cancel(struct fscache_cookie *cookie, 231extern void __fscache_readpages_cancel(struct fscache_cookie *cookie,
240 struct list_head *pages); 232 struct list_head *pages);
241extern void __fscache_disable_cookie(struct fscache_cookie *, bool); 233extern void __fscache_disable_cookie(struct fscache_cookie *, const void *, bool);
242extern void __fscache_enable_cookie(struct fscache_cookie *, 234extern void __fscache_enable_cookie(struct fscache_cookie *, const void *,
243 bool (*)(void *), void *); 235 bool (*)(void *), void *);
244 236
245/** 237/**
@@ -317,6 +309,10 @@ void fscache_release_cache_tag(struct fscache_cache_tag *tag)
317 * fscache_acquire_cookie - Acquire a cookie to represent a cache object 309 * fscache_acquire_cookie - Acquire a cookie to represent a cache object
318 * @parent: The cookie that's to be the parent of this one 310 * @parent: The cookie that's to be the parent of this one
319 * @def: A description of the cache object, including callback operations 311 * @def: A description of the cache object, including callback operations
312 * @index_key: The index key for this cookie
313 * @index_key_len: Size of the index key
314 * @aux_data: The auxiliary data for the cookie (may be NULL)
315 * @aux_data_len: Size of the auxiliary data buffer
320 * @netfs_data: An arbitrary piece of data to be kept in the cookie to 316 * @netfs_data: An arbitrary piece of data to be kept in the cookie to
321 * represent the cache object to the netfs 317 * represent the cache object to the netfs
322 * @enable: Whether or not to enable a data cookie immediately 318 * @enable: Whether or not to enable a data cookie immediately
@@ -332,12 +328,18 @@ static inline
332struct fscache_cookie *fscache_acquire_cookie( 328struct fscache_cookie *fscache_acquire_cookie(
333 struct fscache_cookie *parent, 329 struct fscache_cookie *parent,
334 const struct fscache_cookie_def *def, 330 const struct fscache_cookie_def *def,
331 const void *index_key,
332 size_t index_key_len,
333 const void *aux_data,
334 size_t aux_data_len,
335 void *netfs_data, 335 void *netfs_data,
336 bool enable) 336 bool enable)
337{ 337{
338 if (fscache_cookie_valid(parent) && fscache_cookie_enabled(parent)) 338 if (fscache_cookie_valid(parent) && fscache_cookie_enabled(parent))
339 return __fscache_acquire_cookie(parent, def, netfs_data, 339 return __fscache_acquire_cookie(parent, def,
340 enable); 340 index_key, index_key_len,
341 aux_data, aux_data_len,
342 netfs_data, enable);
341 else 343 else
342 return NULL; 344 return NULL;
343} 345}
@@ -346,36 +348,44 @@ struct fscache_cookie *fscache_acquire_cookie(
346 * fscache_relinquish_cookie - Return the cookie to the cache, maybe discarding 348 * fscache_relinquish_cookie - Return the cookie to the cache, maybe discarding
347 * it 349 * it
348 * @cookie: The cookie being returned 350 * @cookie: The cookie being returned
351 * @aux_data: The updated auxiliary data for the cookie (may be NULL)
349 * @retire: True if the cache object the cookie represents is to be discarded 352 * @retire: True if the cache object the cookie represents is to be discarded
350 * 353 *
351 * This function returns a cookie to the cache, forcibly discarding the 354 * This function returns a cookie to the cache, forcibly discarding the
352 * associated cache object if retire is set to true. 355 * associated cache object if retire is set to true. The opportunity is
356 * provided to update the auxiliary data in the cache before the object is
357 * disconnected.
353 * 358 *
354 * See Documentation/filesystems/caching/netfs-api.txt for a complete 359 * See Documentation/filesystems/caching/netfs-api.txt for a complete
355 * description. 360 * description.
356 */ 361 */
357static inline 362static inline
358void fscache_relinquish_cookie(struct fscache_cookie *cookie, bool retire) 363void fscache_relinquish_cookie(struct fscache_cookie *cookie,
364 const void *aux_data,
365 bool retire)
359{ 366{
360 if (fscache_cookie_valid(cookie)) 367 if (fscache_cookie_valid(cookie))
361 __fscache_relinquish_cookie(cookie, retire); 368 __fscache_relinquish_cookie(cookie, aux_data, retire);
362} 369}
363 370
364/** 371/**
365 * fscache_check_consistency - Request that if the cache is updated 372 * fscache_check_consistency - Request validation of a cache's auxiliary data
366 * @cookie: The cookie representing the cache object 373 * @cookie: The cookie representing the cache object
374 * @aux_data: The updated auxiliary data for the cookie (may be NULL)
367 * 375 *
368 * Request an consistency check from fscache, which passes the request 376 * Request an consistency check from fscache, which passes the request to the
369 * to the backing cache. 377 * backing cache. The auxiliary data on the cookie will be updated first if
378 * @aux_data is set.
370 * 379 *
371 * Returns 0 if consistent and -ESTALE if inconsistent. May also 380 * Returns 0 if consistent and -ESTALE if inconsistent. May also
372 * return -ENOMEM and -ERESTARTSYS. 381 * return -ENOMEM and -ERESTARTSYS.
373 */ 382 */
374static inline 383static inline
375int fscache_check_consistency(struct fscache_cookie *cookie) 384int fscache_check_consistency(struct fscache_cookie *cookie,
385 const void *aux_data)
376{ 386{
377 if (fscache_cookie_valid(cookie) && fscache_cookie_enabled(cookie)) 387 if (fscache_cookie_valid(cookie) && fscache_cookie_enabled(cookie))
378 return __fscache_check_consistency(cookie); 388 return __fscache_check_consistency(cookie, aux_data);
379 else 389 else
380 return 0; 390 return 0;
381} 391}
@@ -383,18 +393,20 @@ int fscache_check_consistency(struct fscache_cookie *cookie)
383/** 393/**
384 * fscache_update_cookie - Request that a cache object be updated 394 * fscache_update_cookie - Request that a cache object be updated
385 * @cookie: The cookie representing the cache object 395 * @cookie: The cookie representing the cache object
396 * @aux_data: The updated auxiliary data for the cookie (may be NULL)
386 * 397 *
387 * Request an update of the index data for the cache object associated with the 398 * Request an update of the index data for the cache object associated with the
388 * cookie. 399 * cookie. The auxiliary data on the cookie will be updated first if @aux_data
400 * is set.
389 * 401 *
390 * See Documentation/filesystems/caching/netfs-api.txt for a complete 402 * See Documentation/filesystems/caching/netfs-api.txt for a complete
391 * description. 403 * description.
392 */ 404 */
393static inline 405static inline
394void fscache_update_cookie(struct fscache_cookie *cookie) 406void fscache_update_cookie(struct fscache_cookie *cookie, const void *aux_data)
395{ 407{
396 if (fscache_cookie_valid(cookie) && fscache_cookie_enabled(cookie)) 408 if (fscache_cookie_valid(cookie) && fscache_cookie_enabled(cookie))
397 __fscache_update_cookie(cookie); 409 __fscache_update_cookie(cookie, aux_data);
398} 410}
399 411
400/** 412/**
@@ -780,6 +792,7 @@ void fscache_uncache_all_inode_pages(struct fscache_cookie *cookie,
780/** 792/**
781 * fscache_disable_cookie - Disable a cookie 793 * fscache_disable_cookie - Disable a cookie
782 * @cookie: The cookie representing the cache object 794 * @cookie: The cookie representing the cache object
795 * @aux_data: The updated auxiliary data for the cookie (may be NULL)
783 * @invalidate: Invalidate the backing object 796 * @invalidate: Invalidate the backing object
784 * 797 *
785 * Disable a cookie from accepting further alloc, read, write, invalidate, 798 * Disable a cookie from accepting further alloc, read, write, invalidate,
@@ -790,34 +803,41 @@ void fscache_uncache_all_inode_pages(struct fscache_cookie *cookie,
790 * 803 *
791 * If @invalidate is set, then the backing object will be invalidated and 804 * If @invalidate is set, then the backing object will be invalidated and
792 * detached, otherwise it will just be detached. 805 * detached, otherwise it will just be detached.
806 *
807 * If @aux_data is set, then auxiliary data will be updated from that.
793 */ 808 */
794static inline 809static inline
795void fscache_disable_cookie(struct fscache_cookie *cookie, bool invalidate) 810void fscache_disable_cookie(struct fscache_cookie *cookie,
811 const void *aux_data,
812 bool invalidate)
796{ 813{
797 if (fscache_cookie_valid(cookie) && fscache_cookie_enabled(cookie)) 814 if (fscache_cookie_valid(cookie) && fscache_cookie_enabled(cookie))
798 __fscache_disable_cookie(cookie, invalidate); 815 __fscache_disable_cookie(cookie, aux_data, invalidate);
799} 816}
800 817
801/** 818/**
802 * fscache_enable_cookie - Reenable a cookie 819 * fscache_enable_cookie - Reenable a cookie
803 * @cookie: The cookie representing the cache object 820 * @cookie: The cookie representing the cache object
821 * @aux_data: The updated auxiliary data for the cookie (may be NULL)
804 * @can_enable: A function to permit enablement once lock is held 822 * @can_enable: A function to permit enablement once lock is held
805 * @data: Data for can_enable() 823 * @data: Data for can_enable()
806 * 824 *
807 * Reenable a previously disabled cookie, allowing it to accept further alloc, 825 * Reenable a previously disabled cookie, allowing it to accept further alloc,
808 * read, write, invalidate, update or acquire operations. An attempt will be 826 * read, write, invalidate, update or acquire operations. An attempt will be
809 * made to immediately reattach the cookie to a backing object. 827 * made to immediately reattach the cookie to a backing object. If @aux_data
828 * is set, the auxiliary data attached to the cookie will be updated.
810 * 829 *
811 * The can_enable() function is called (if not NULL) once the enablement lock 830 * The can_enable() function is called (if not NULL) once the enablement lock
812 * is held to rule on whether enablement is still permitted to go ahead. 831 * is held to rule on whether enablement is still permitted to go ahead.
813 */ 832 */
814static inline 833static inline
815void fscache_enable_cookie(struct fscache_cookie *cookie, 834void fscache_enable_cookie(struct fscache_cookie *cookie,
835 const void *aux_data,
816 bool (*can_enable)(void *data), 836 bool (*can_enable)(void *data),
817 void *data) 837 void *data)
818{ 838{
819 if (fscache_cookie_valid(cookie) && !fscache_cookie_enabled(cookie)) 839 if (fscache_cookie_valid(cookie) && !fscache_cookie_enabled(cookie))
820 __fscache_enable_cookie(cookie, can_enable, data); 840 __fscache_enable_cookie(cookie, aux_data, can_enable, data);
821} 841}
822 842
823#endif /* _LINUX_FSCACHE_H */ 843#endif /* _LINUX_FSCACHE_H */