[PATCH 57/67] cachefiles, afs: Drive FSCACHE_COOKIE_NO_DATA_TO_READ

David Howells
2021-10-18T15:06:37Z

Drive the FSCACHE_COOKIE_NO_DATA_TO_READ bit to skip reads on cache files
that can't have any data available to read. This needs clearing once we've
written some data and then released the netfs page that contained it.

Signed-off-by: David Howells <dhowells@redhat.com>
---

fs/afs/file.c | 1 +
fs/cachefiles/io.c | 1 +
fs/fscache/cookie.c | 2 ++
include/linux/fscache.h | 16 ++++++++++++++++
4 files changed, 20 insertions(+)

diff --git a/fs/afs/file.c b/fs/afs/file.c
index 5db1e7d29ad5..7fe57f210259 100644
--- a/fs/afs/file.c
+++ b/fs/afs/file.c
@@ -506,6 +506,7 @@ static int afs_releasepage(struct page *page, gfp_t gfp_flags)
return false;
wait_on_page_fscache(page);
}
+ fscache_note_page_release(afs_vnode_cache(vnode));
#endif

if (PagePrivate(page)) {
diff --git a/fs/cachefiles/io.c b/fs/cachefiles/io.c
index 9b3b55a94e66..5e3579800689 100644
--- a/fs/cachefiles/io.c
+++ b/fs/cachefiles/io.c
@@ -195,6 +195,7 @@ static void cachefiles_write_complete(struct kiocb *iocb, long ret, long ret2)
__sb_writers_acquired(inode->i_sb, SB_FREEZE_WRITE);
__sb_end_write(inode->i_sb, SB_FREEZE_WRITE);

+ set_bit(FSCACHE_COOKIE_HAVE_DATA, &ki->object->cookie->flags);
if (ki->term_func)
ki->term_func(ki->term_func_priv, ret, ki->was_async);
cachefiles_put_kiocb(ki);
diff --git a/fs/fscache/cookie.c b/fs/fscache/cookie.c
index 1420027cfe97..369f9258bb50 100644
--- a/fs/fscache/cookie.c
+++ b/fs/fscache/cookie.c
@@ -263,6 +263,8 @@ static struct fscache_cookie *fscache_alloc_cookie(
cookie->key_len = index_key_len;
cookie->aux_len = aux_data_len;
cookie->object_size = object_size;
+ if (object_size == 0)
+ __set_bit(FSCACHE_COOKIE_NO_DATA_TO_READ, &cookie->flags);

if (fscache_set_key(cookie, index_key, index_key_len) < 0)
goto nomem;
diff --git a/include/linux/fscache.h b/include/linux/fscache.h
index ba192567d099..d18b7d3564ab 100644
--- a/include/linux/fscache.h
+++ b/include/linux/fscache.h
@@ -131,6 +131,7 @@ struct fscache_cookie {
#define FSCACHE_COOKIE_DO_WITHDRAW 10 /* T if this cookie needs withdrawing */
#define FSCACHE_COOKIE_DO_COMMIT 11 /* T if this cookie needs committing */
#define FSCACHE_COOKIE_DO_PREP_TO_WRITE 12 /* T if cookie needs write preparation */
+#define FSCACHE_COOKIE_HAVE_DATA 13 /* T if this cookie has data stored */

enum fscache_cookie_stage stage;
u8 advice; /* FSCACHE_ADV_* */
@@ -643,7 +644,22 @@ static inline void fscache_clear_inode_writeback(struct fscache_cookie *cookie,
loff_t i_size = i_size_read(inode);
fscache_unuse_cookie(cookie, aux, &i_size);
}
+}

+/**
+ * fscache_note_page_release - Note that a netfs page got released
+ * @cookie: The cookie corresponding to the file
+ *
+ * Note that a page that has been copied to the cache has been released. This
+ * means that future reads will need to look in the cache to see if it's there.
+ */
+static inline
+void fscache_note_page_release(struct fscache_cookie *cookie)
+{
+ if (cookie &&
+ test_bit(FSCACHE_COOKIE_HAVE_DATA, &cookie->flags) &&
+ test_bit(FSCACHE_COOKIE_NO_DATA_TO_READ, &cookie->flags))
+ clear_bit(FSCACHE_COOKIE_NO_DATA_TO_READ, &cookie->flags);
}

#ifdef FSCACHE_USE_FALLBACK_IO_API