Skip to content

Commit 402cb8d

Browse files
committed
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>
1 parent 08c2e3d commit 402cb8d

File tree

26 files changed

+606
-786
lines changed

26 files changed

+606
-786
lines changed

Documentation/filesystems/caching/netfs-api.txt

Lines changed: 51 additions & 55 deletions
Original file line numberDiff line numberDiff line change
@@ -129,17 +129,9 @@ To define an object, a structure of the following type should be filled out:
129129
const void *parent_netfs_data,
130130
const void *cookie_netfs_data);
131131

132-
uint16_t (*get_key)(const void *cookie_netfs_data,
133-
void *buffer,
134-
uint16_t bufmax);
135-
136132
void (*get_attr)(const void *cookie_netfs_data,
137133
uint64_t *size);
138134

139-
uint16_t (*get_aux)(const void *cookie_netfs_data,
140-
void *buffer,
141-
uint16_t bufmax);
142-
143135
enum fscache_checkaux (*check_aux)(void *cookie_netfs_data,
144136
const void *data,
145137
uint16_t datalen);
@@ -187,14 +179,7 @@ This has the following fields:
187179
cache in the parent's list will be chosen, or failing that, the first
188180
cache in the master list.
189181

190-
(4) A function to retrieve an object's key from the netfs [mandatory].
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].
182+
(4) A function to retrieve attribute data from the netfs [optional].
198183

199184
This function will be called with the netfs data that was passed to the
200185
cookie acquisition function. It should return the size of the file if
@@ -203,20 +188,7 @@ This has the following fields:
203188

204189
If the function is absent, a file size of 0 is assumed.
205190

206-
(6) A function to retrieve auxiliary data from the netfs [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].
191+
(5) A function to check the auxiliary data [optional].
220192

221193
This function will be called to check that a match found in the cache for
222194
this object is valid. For instance with AFS it could check the auxiliary
@@ -235,7 +207,7 @@ This has the following fields:
235207
This function can also be used to extract data from the auxiliary data in
236208
the cache and copy it into the netfs's structures.
237209

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
239211
[optional].
240212

241213
The cache read/write functions are passed a context which is then passed
@@ -249,7 +221,7 @@ This has the following fields:
249221
required for indices as indices may not contain data. These functions may
250222
be called in interrupt context and so may not sleep.
251223

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].
253225

254226
This is called by the cache to indicate that it is retaining in-memory
255227
information for this page and that the netfs should uncache the page when
@@ -261,7 +233,7 @@ This has the following fields:
261233

262234
This function is not required for indices as they're not permitted data.
263235

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].
265237

266238
This is called by FS-Cache to indicate that a backing store is being
267239
unbound from a cookie and that all the marks on the pages should be
@@ -333,12 +305,27 @@ the path to the file:
333305
struct fscache_cookie *
334306
fscache_acquire_cookie(struct fscache_cookie *parent,
335307
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,
336312
void *netfs_data,
337313
bool enable);
338314

339315
This function creates an index entry in the index represented by parent,
340316
filling in the index entry by calling the operations pointed to by def.
341317

318+
A unique key that represents the object within the parent must be pointed to by
319+
index_key and is of length index_key_len.
320+
321+
An optional blob of auxiliary data that is to be stored within the cache can be
322+
pointed to with aux_data and should be of length aux_data_len. This would
323+
typically be used for storing coherency data.
324+
325+
The netfs may pass an arbitrary value in netfs_data and this will be presented
326+
to it in the event of any calling back. This may also be used in tracing or
327+
logging of messages.
328+
342329
Note that this function never returns an error - all errors are handled
343330
internally. It may, however, return NULL to indicate no cookie. It is quite
344331
acceptable 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
355342
calling fscache_enable_cookie() (see below).
356343

357344
For example, with AFS, a cell would be added to the primary index. This index
358-
entry would have a dependent inode containing a volume location index for the
359-
volume mappings within this cell:
345+
entry would have a dependent inode containing volume mappings within this cell:
360346

361347
cell->cache =
362348
fscache_acquire_cookie(afs_cache_netfs.primary_index,
363349
&afs_cell_cache_index_def,
350+
cell->name, strlen(cell->name),
351+
NULL, 0,
364352
cell, true);
365353

366-
Then when a volume location was accessed, it would be entered into the cell's
367-
index and an inode would be allocated that acts as a volume type and hash chain
368-
combination:
369-
370-
vlocation->cache =
371-
fscache_acquire_cookie(cell->cache,
372-
&afs_vlocation_cache_index_def,
373-
vlocation, true);
374-
375-
And then a particular flavour of volume (R/O for example) could be added to
376-
that index, creating another index for vnodes (AFS inode equivalents):
354+
And then a particular volume could be added to that index by ID, creating
355+
another index for vnodes (AFS inode equivalents):
377356

378357
volume->cache =
379-
fscache_acquire_cookie(vlocation->cache,
358+
fscache_acquire_cookie(volume->cell->cache,
380359
&afs_volume_cache_index_def,
360+
&volume->vid, sizeof(volume->vid),
361+
NULL, 0,
381362
volume, true);
382363

383364

@@ -392,6 +373,8 @@ the object definition should be something other than index type.
392373
vnode->cache =
393374
fscache_acquire_cookie(volume->cache,
394375
&afs_vnode_cache_object_def,
376+
&key, sizeof(key),
377+
&aux, sizeof(aux),
395378
vnode, true);
396379

397380

@@ -408,6 +391,8 @@ it would be some other type of object such as a data file.
408391
xattr->cache =
409392
fscache_acquire_cookie(vnode->cache,
410393
&afs_xattr_cache_object_def,
394+
&xattr->name, strlen(xattr->name),
395+
NULL, 0,
411396
xattr, true);
412397

413398
Miscellaneous objects might be used to store extended attributes or directory
@@ -717,21 +702,23 @@ INDEX AND DATA FILE CONSISTENCY
717702
To find out whether auxiliary data for an object is up to data within the
718703
cache, the following function can be called:
719704

720-
int fscache_check_consistency(struct fscache_cookie *cookie)
705+
int fscache_check_consistency(struct fscache_cookie *cookie,
706+
const void *aux_data);
721707

722708
This will call back to the netfs to check whether the auxiliary data associated
723-
with a cookie is correct. It returns 0 if it is and -ESTALE if it isn't; it
724-
may also return -ENOMEM and -ERESTARTSYS.
709+
with a cookie is correct; if aux_data is non-NULL, it will update the auxiliary
710+
data buffer first. It returns 0 if it is and -ESTALE if it isn't; it may also
711+
return -ENOMEM and -ERESTARTSYS.
725712

726713
To request an update of the index data for an index or other object, the
727714
following function should be called:
728715

729-
void fscache_update_cookie(struct fscache_cookie *cookie);
716+
void fscache_update_cookie(struct fscache_cookie *cookie,
717+
const void *aux_data);
730718

731-
This function will refer back to the netfs_data pointer stored in the cookie by
732-
the acquisition function to obtain the data to write into each revised index
733-
entry. The update method in the parent index definition will be called to
734-
transfer the data.
719+
This function will update the cookie's auxiliary data buffer from aux_data if
720+
that is non-NULL and then schedule this to be stored on disk. The update
721+
method in the parent index definition will be called to transfer the data.
735722

736723
Note that partial updates may happen automatically at other times, such as when
737724
data 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
750737
can be enabled or disabled later. To disable a cookie, call:
751738

752739
void fscache_disable_cookie(struct fscache_cookie *cookie,
740+
const void *aux_data,
753741
bool invalidate);
754742

755743
If the cookie is not already disabled, this locks the cookie against other
@@ -764,6 +752,7 @@ markings are cleared up.
764752
Cookies can be enabled or reenabled with:
765753

766754
void fscache_enable_cookie(struct fscache_cookie *cookie,
755+
const void *aux_data,
767756
bool (*can_enable)(void *data),
768757
void *data)
769758

@@ -777,6 +766,9 @@ ruling as to whether or not enablement should actually be permitted to begin.
777766
All possible failures are handled internally. The cookie will only be marked
778767
as enabled if provisional backing objects are allocated.
779768

769+
In both cases, the cookie's auxiliary data buffer is updated from aux_data if
770+
that is non-NULL inside the enablement lock before proceeding.
771+
780772

781773
===============================
782774
MISCELLANEOUS COOKIE OPERATIONS
@@ -823,6 +815,7 @@ COOKIE UNREGISTRATION
823815
To get rid of a cookie, this function should be called.
824816

825817
void fscache_relinquish_cookie(struct fscache_cookie *cookie,
818+
const void *aux_data,
826819
bool retire);
827820

828821
If 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
833826
acquisition function is called. Retirement here will overrule the pinning on a
834827
cookie.
835828

829+
The cookie's auxiliary data will be updated from aux_data if that is non-NULL
830+
so that the cache can lazily update it on disk.
831+
836832
One very important note - relinquish must NOT be called for a cookie unless all
837833
the cookies for "child" indices, objects and pages have been relinquished
838834
first.

fs/9p/cache.c

Lines changed: 22 additions & 51 deletions
Original file line numberDiff line numberDiff line change
@@ -55,41 +55,26 @@ int v9fs_random_cachetag(struct v9fs_session_info *v9ses)
5555
return scnprintf(v9ses->cachetag, CACHETAG_LEN, "%lu", jiffies);
5656
}
5757

58-
static 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-
7958
const struct fscache_cookie_def v9fs_cache_session_index_def = {
8059
.name = "9P.session",
8160
.type = FSCACHE_COOKIE_TYPE_INDEX,
82-
.get_key = v9fs_cache_session_get_key,
8361
};
8462

8563
void v9fs_cache_session_get_cookie(struct v9fs_session_info *v9ses)
8664
{
8765
/* If no cache session tag was specified, we generate a random one. */
88-
if (!v9ses->cachetag)
89-
v9fs_random_cachetag(v9ses);
66+
if (!v9ses->cachetag) {
67+
if (v9fs_random_cachetag(v9ses) < 0) {
68+
v9ses->fscache = NULL;
69+
return;
70+
}
71+
}
9072

9173
v9ses->fscache = fscache_acquire_cookie(v9fs_cache_netfs.primary_index,
9274
&v9fs_cache_session_index_def,
75+
v9ses->cachetag,
76+
strlen(v9ses->cachetag),
77+
NULL, 0,
9378
v9ses, true);
9479
p9_debug(P9_DEBUG_FSC, "session %p get cookie %p\n",
9580
v9ses, v9ses->fscache);
@@ -99,21 +84,10 @@ void v9fs_cache_session_put_cookie(struct v9fs_session_info *v9ses)
9984
{
10085
p9_debug(P9_DEBUG_FSC, "session %p put cookie %p\n",
10186
v9ses, v9ses->fscache);
102-
fscache_relinquish_cookie(v9ses->fscache, 0);
87+
fscache_relinquish_cookie(v9ses->fscache, NULL, false);
10388
v9ses->fscache = NULL;
10489
}
10590

106-
107-
static 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-
11791
static void v9fs_cache_inode_get_attr(const void *cookie_netfs_data,
11892
uint64_t *size)
11993
{
@@ -124,16 +98,6 @@ static void v9fs_cache_inode_get_attr(const void *cookie_netfs_data,
12498
&v9inode->vfs_inode, *size);
12599
}
126100

127-
static 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-
137101
static enum
138102
fscache_checkaux v9fs_cache_inode_check_aux(void *cookie_netfs_data,
139103
const void *buffer,
@@ -154,9 +118,7 @@ fscache_checkaux v9fs_cache_inode_check_aux(void *cookie_netfs_data,
154118
const struct fscache_cookie_def v9fs_cache_inode_index_def = {
155119
.name = "9p.inode",
156120
.type = FSCACHE_COOKIE_TYPE_DATAFILE,
157-
.get_key = v9fs_cache_inode_get_key,
158121
.get_attr = v9fs_cache_inode_get_attr,
159-
.get_aux = v9fs_cache_inode_get_aux,
160122
.check_aux = v9fs_cache_inode_check_aux,
161123
};
162124

@@ -175,6 +137,10 @@ void v9fs_cache_inode_get_cookie(struct inode *inode)
175137
v9ses = v9fs_inode2v9ses(inode);
176138
v9inode->fscache = fscache_acquire_cookie(v9ses->fscache,
177139
&v9fs_cache_inode_index_def,
140+
&v9inode->qid.path,
141+
sizeof(v9inode->qid.path),
142+
&v9inode->qid.version,
143+
sizeof(v9inode->qid.version),
178144
v9inode, true);
179145

180146
p9_debug(P9_DEBUG_FSC, "inode %p get cookie %p\n",
@@ -190,7 +156,8 @@ void v9fs_cache_inode_put_cookie(struct inode *inode)
190156
p9_debug(P9_DEBUG_FSC, "inode %p put cookie %p\n",
191157
inode, v9inode->fscache);
192158

193-
fscache_relinquish_cookie(v9inode->fscache, 0);
159+
fscache_relinquish_cookie(v9inode->fscache, &v9inode->qid.version,
160+
false);
194161
v9inode->fscache = NULL;
195162
}
196163

@@ -203,7 +170,7 @@ void v9fs_cache_inode_flush_cookie(struct inode *inode)
203170
p9_debug(P9_DEBUG_FSC, "inode %p flush cookie %p\n",
204171
inode, v9inode->fscache);
205172

206-
fscache_relinquish_cookie(v9inode->fscache, 1);
173+
fscache_relinquish_cookie(v9inode->fscache, NULL, true);
207174
v9inode->fscache = NULL;
208175
}
209176

@@ -236,11 +203,15 @@ void v9fs_cache_inode_reset_cookie(struct inode *inode)
236203
old = v9inode->fscache;
237204

238205
mutex_lock(&v9inode->fscache_lock);
239-
fscache_relinquish_cookie(v9inode->fscache, 1);
206+
fscache_relinquish_cookie(v9inode->fscache, NULL, true);
240207

241208
v9ses = v9fs_inode2v9ses(inode);
242209
v9inode->fscache = fscache_acquire_cookie(v9ses->fscache,
243210
&v9fs_cache_inode_index_def,
211+
&v9inode->qid.path,
212+
sizeof(v9inode->qid.path),
213+
&v9inode->qid.version,
214+
sizeof(v9inode->qid.version),
244215
v9inode, true);
245216
p9_debug(P9_DEBUG_FSC, "inode %p revalidating cookie old %p new %p\n",
246217
inode, old, v9inode->fscache);

0 commit comments

Comments
 (0)