@@ -564,9 +564,7 @@ static void afs_zap_data(struct afs_vnode *vnode)
{
_enter("{%llx:%llu}", vnode->fid.vid, vnode->fid.vnode);
-#ifdef CONFIG_AFS_FSCACHE
- fscache_invalidate(vnode->cache, i_size_read(&vnode->vfs_inode));
-#endif
+ afs_invalidate_cache(vnode, 0);
/* nuke all the non-dirty pages that aren't locked, mapped or being
* written back in a regular file and completely discard the pages in a
@@ -878,6 +878,15 @@ static inline void afs_set_cache_aux(struct afs_vnode *vnode,
aux->data_version = cpu_to_be64(vnode->status.data_version);
}
+static inline void afs_invalidate_cache(struct afs_vnode *vnode, unsigned int flags)
+{
+ struct afs_vnode_cache_aux aux;
+
+ afs_set_cache_aux(vnode, &aux);
+ fscache_invalidate(afs_vnode_cache(vnode), &aux,
+ i_size_read(&vnode->vfs_inode), flags);
+}
+
/*
* We use page->private to hold the amount of the page that we've written to,
* splitting the field into two parts. However, we need to represent a range
@@ -376,8 +376,7 @@ static int cachefiles_attr_changed(struct cachefiles_object *object)
/*
* Invalidate the storage associated with a cookie.
*/
-static bool cachefiles_invalidate_cookie(struct fscache_cookie *cookie,
- unsigned int flags)
+static bool cachefiles_invalidate_cookie(struct fscache_cookie *cookie)
{
struct cachefiles_object *object = cookie->cache_priv;
struct file *new_file, *old_file;
@@ -134,7 +134,7 @@ static int cachefiles_read(struct netfs_cache_resources *cres,
ki->iocb.ki_ioprio = get_current_ioprio();
ki->skipped = skipped;
ki->object = object;
- ki->inval_counter = object->cookie->inval_counter;
+ ki->inval_counter = cres->inval_counter;
ki->term_func = term_func;
ki->term_func_priv = term_func_priv;
ki->was_async = true;
@@ -239,7 +239,7 @@ static int cachefiles_write(struct netfs_cache_resources *cres,
ki->iocb.ki_hint = ki_hint_validate(file_write_hint(file));
ki->iocb.ki_ioprio = get_current_ioprio();
ki->object = object;
- ki->inval_counter = object->cookie->inval_counter;
+ ki->inval_counter = cres->inval_counter;
ki->start = start_pos;
ki->len = len;
ki->term_func = term_func;
@@ -694,17 +694,16 @@ static void fscache_cookie_drop_from_lru(struct fscache_cookie *cookie)
*/
static void fscache_invalidate_cookie(struct fscache_cookie *cookie)
{
- if (cookie->volume->cache->ops->invalidate_cookie(cookie, 0))
- fscache_set_cookie_stage(cookie, FSCACHE_COOKIE_STAGE_ACTIVE);
- else
- fscache_set_cookie_stage(cookie, FSCACHE_COOKIE_STAGE_FAILED);
+ cookie->volume->cache->ops->invalidate_cookie(cookie);
fscache_end_cookie_access(cookie, fscache_access_invalidate_cookie_end);
}
/*
- * Invalidate an object. Callable with spinlocks held.
+ * Invalidate an object.
*/
-void __fscache_invalidate(struct fscache_cookie *cookie, loff_t new_size)
+void __fscache_invalidate(struct fscache_cookie *cookie,
+ const void *aux_data, loff_t new_size,
+ unsigned int flags)
{
bool is_caching;
@@ -718,8 +717,9 @@ void __fscache_invalidate(struct fscache_cookie *cookie, loff_t new_size)
spin_lock(&cookie->lock);
set_bit(FSCACHE_COOKIE_NO_DATA_TO_READ, &cookie->flags);
- cookie->object_size = new_size;
+ fscache_update_aux(cookie, aux_data, &new_size);
cookie->inval_counter++;
+ trace_fscache_invalidate(cookie, new_size);
switch (cookie->stage) {
case FSCACHE_COOKIE_STAGE_INVALIDATING: /* is_still_valid will catch it */
@@ -81,6 +81,7 @@ static int fscache_begin_operation(struct netfs_cache_resources *cres,
cres->cache_priv = cookie;
cres->cache_priv2 = NULL;
cres->debug_id = cookie->debug_id;
+ cres->inval_counter = cookie->inval_counter;
if (!fscache_begin_cookie_access(cookie, why))
return -ENOBUFS;
@@ -67,8 +67,7 @@ struct fscache_cache_ops {
void (*withdraw_cookie)(struct fscache_cookie *cookie);
/* Invalidate an object */
- bool (*invalidate_cookie)(struct fscache_cookie *cookie,
- unsigned int flags);
+ bool (*invalidate_cookie)(struct fscache_cookie *cookie);
/* Begin an operation for the netfs lib */
bool (*begin_operation)(struct netfs_cache_resources *cres,
@@ -159,7 +159,7 @@ extern struct fscache_cookie *__fscache_acquire_cookie(
extern void __fscache_use_cookie(struct fscache_cookie *, bool);
extern void __fscache_unuse_cookie(struct fscache_cookie *, const void *, const loff_t *);
extern void __fscache_relinquish_cookie(struct fscache_cookie *, bool);
-extern void __fscache_invalidate(struct fscache_cookie *, loff_t);
+extern void __fscache_invalidate(struct fscache_cookie *, const void *, loff_t, unsigned int);
#ifdef FSCACHE_USE_NEW_IO_API
extern int __fscache_begin_read_operation(struct netfs_cache_resources *, struct fscache_cookie *);
#endif
@@ -388,22 +388,30 @@ void fscache_unpin_cookie(struct fscache_cookie *cookie)
/**
* fscache_invalidate - Notify cache that an object needs invalidation
* @cookie: The cookie representing the cache object
+ * @aux_data: The updated auxiliary data for the cookie (may be NULL)
* @size: The revised size of the object.
+ * @flags: Invalidation flags (FSCACHE_INVAL_*)
*
* Notify the cache that an object is needs to be invalidated and that it
* should abort any retrievals or stores it is doing on the cache. The object
* is then marked non-caching until such time as the invalidation is complete.
*
- * This can be called with spinlocks held.
+ * FSCACHE_INVAL_LIGHT indicates that if the object has been invalidated and
+ * replaced by a temporary object, the temporary object need not be replaced
+ * again. This is primarily intended for use with FSCACHE_ADV_SINGLE_CHUNK.
+ *
+ * FSCACHE_INVAL_DIO_WRITE indicates that this is due to a direct I/O write and
+ * may cause caching to be suspended on this cookie.
*
* See Documentation/filesystems/caching/netfs-api.rst for a complete
* description.
*/
static inline
-void fscache_invalidate(struct fscache_cookie *cookie, loff_t size)
+void fscache_invalidate(struct fscache_cookie *cookie,
+ const void *aux_data, loff_t size, unsigned int flags)
{
if (fscache_cookie_valid(cookie))
- __fscache_invalidate(cookie, size);
+ __fscache_invalidate(cookie, aux_data, size, flags);
}
/**
@@ -103,6 +103,7 @@ struct netfs_cache_resources {
void *cache_priv;
void *cache_priv2;
unsigned int debug_id; /* Cookie debug ID */
+ unsigned int inval_counter; /* object->inval_counter at begin_op */
};
/*
@@ -410,6 +410,25 @@ TRACE_EVENT(fscache_relinquish,
__entry->n_active, __entry->flags, __entry->retire)
);
+TRACE_EVENT(fscache_invalidate,
+ TP_PROTO(struct fscache_cookie *cookie, loff_t new_size),
+
+ TP_ARGS(cookie, new_size),
+
+ TP_STRUCT__entry(
+ __field(unsigned int, cookie )
+ __field(loff_t, new_size )
+ ),
+
+ TP_fast_assign(
+ __entry->cookie = cookie->debug_id;
+ __entry->new_size = new_size;
+ ),
+
+ TP_printk("c=%08x sz=%llx",
+ __entry->cookie, __entry->new_size)
+ );
+
#endif /* _TRACE_FSCACHE_H */
/* This part must be outside protection */
Rewrite the fscache_invalidate() function. The following changes are made to fscache: (1) Invalidation is now ignored or allowed to proceed depending on the 'stage' a non-index cookie is in with respect to the backing object. (2) If invalidation is proceeds, it pins the object and holds a cookie access count for the duration to prevent the cache from going away. (3) The fscache_object struct is given an invalidation counter that is incremented every time fscache_invalidate() is called, even if the cookie is at a stage in which it cannot be applied. The counter, however, can be noted and applied retroactively later. (4) The invalidation counter is noted in the operation struct when a cache operation is begun and can be checked on operation completion to find out if any consequent metadata changes should be dropped. (5) New operations aren't allowed to proceed if the object is being invalidated. Signed-off-by: David Howells <dhowells@redhat.com> --- fs/afs/inode.c | 4 +--- fs/afs/internal.h | 9 +++++++++ fs/cachefiles/interface.c | 3 +-- fs/cachefiles/io.c | 4 ++-- fs/fscache/cookie.c | 14 +++++++------- fs/fscache/io.c | 1 + include/linux/fscache-cache.h | 3 +-- include/linux/fscache.h | 16 ++++++++++++---- include/linux/netfs.h | 1 + include/trace/events/fscache.h | 19 +++++++++++++++++++ 10 files changed, 54 insertions(+), 20 deletions(-)