@@ -5,6 +5,60 @@
#include <linux/fscache.h>
#include "internal.h"
+/*
+ * Read data from fscache and fill the read data into page cache described by
+ * @start/len, which shall be both aligned with PAGE_SIZE. @pstart describes
+ * the start physical address in the cache file.
+ */
+static int erofs_fscache_read_folios(struct fscache_cookie *cookie,
+ struct address_space *mapping,
+ loff_t start, size_t len,
+ loff_t pstart)
+{
+ enum netfs_io_source source;
+ struct netfs_io_request rreq = {};
+ struct netfs_io_subrequest subreq = { .rreq = &rreq, };
+ struct netfs_cache_resources *cres = &rreq.cache_resources;
+ struct super_block *sb = mapping->host->i_sb;
+ struct iov_iter iter;
+ size_t done = 0;
+ int ret;
+
+ ret = fscache_begin_read_operation(cres, cookie);
+ if (ret)
+ return ret;
+
+ while (done < len) {
+ subreq.start = pstart + done;
+ subreq.len = len - done;
+ subreq.flags = 1 << NETFS_SREQ_ONDEMAND;
+
+ source = cres->ops->prepare_read(&subreq, LLONG_MAX);
+ if (WARN_ON(subreq.len == 0))
+ source = NETFS_INVALID_READ;
+ if (source != NETFS_READ_FROM_CACHE) {
+ erofs_err(sb, "failed to fscache prepare_read (source %d)",
+ source);
+ ret = -EIO;
+ goto out;
+ }
+
+ iov_iter_xarray(&iter, READ, &mapping->i_pages,
+ start + done, subreq.len);
+ ret = fscache_read(cres, subreq.start, &iter,
+ NETFS_READ_HOLE_FAIL, NULL, NULL);
+ if (ret) {
+ erofs_err(sb, "failed to fscache_read (ret %d)", ret);
+ goto out;
+ }
+
+ done += subreq.len;
+ }
+out:
+ fscache_end_operation(cres);
+ return ret;
+}
+
static const struct address_space_operations erofs_fscache_meta_aops = {
};