netfs, cachefiles: Add a method to query presence of data in the cache
Add a netfs_cache_ops method by which a network filesystem can ask the cache about what data it has available and where so that it can make a multipage read more efficient. Signed-off-by: David Howells <dhowells@redhat.com> cc: linux-cachefs@redhat.com Acked-by: Jeff Layton <jlayton@kernel.org> Reviewed-by: Rohith Surabattula <rohiths@microsoft.com> Signed-off-by: Steve French <stfrench@microsoft.com>
This commit is contained in:
parent
052e04a52d
commit
bee9f65523
@ -462,6 +462,10 @@ operation table looks like the following::
|
||||
struct iov_iter *iter,
|
||||
netfs_io_terminated_t term_func,
|
||||
void *term_func_priv);
|
||||
|
||||
int (*query_occupancy)(struct netfs_cache_resources *cres,
|
||||
loff_t start, size_t len, size_t granularity,
|
||||
loff_t *_data_start, size_t *_data_len);
|
||||
};
|
||||
|
||||
With a termination handler function pointer::
|
||||
@ -536,6 +540,18 @@ The methods defined in the table are:
|
||||
indicating whether the termination is definitely happening in the caller's
|
||||
context.
|
||||
|
||||
* ``query_occupancy()``
|
||||
|
||||
[Required] Called to find out where the next piece of data is within a
|
||||
particular region of the cache. The start and length of the region to be
|
||||
queried are passed in, along with the granularity to which the answer needs
|
||||
to be aligned. The function passes back the start and length of the data,
|
||||
if any, available within that region. Note that there may be a hole at the
|
||||
front.
|
||||
|
||||
It returns 0 if some data was found, -ENODATA if there was no usable data
|
||||
within the region or -ENOBUFS if there is no caching on this file.
|
||||
|
||||
Note that these methods are passed a pointer to the cache resource structure,
|
||||
not the read request structure as they could be used in other situations where
|
||||
there isn't a read request structure as well, such as writing dirty data to the
|
||||
|
@ -191,6 +191,64 @@ presubmission_error:
|
||||
return ret;
|
||||
}
|
||||
|
||||
/*
|
||||
* Query the occupancy of the cache in a region, returning where the next chunk
|
||||
* of data starts and how long it is.
|
||||
*/
|
||||
static int cachefiles_query_occupancy(struct netfs_cache_resources *cres,
|
||||
loff_t start, size_t len, size_t granularity,
|
||||
loff_t *_data_start, size_t *_data_len)
|
||||
{
|
||||
struct cachefiles_object *object;
|
||||
struct file *file;
|
||||
loff_t off, off2;
|
||||
|
||||
*_data_start = -1;
|
||||
*_data_len = 0;
|
||||
|
||||
if (!fscache_wait_for_operation(cres, FSCACHE_WANT_READ))
|
||||
return -ENOBUFS;
|
||||
|
||||
object = cachefiles_cres_object(cres);
|
||||
file = cachefiles_cres_file(cres);
|
||||
granularity = max_t(size_t, object->volume->cache->bsize, granularity);
|
||||
|
||||
_enter("%pD,%li,%llx,%zx/%llx",
|
||||
file, file_inode(file)->i_ino, start, len,
|
||||
i_size_read(file_inode(file)));
|
||||
|
||||
off = cachefiles_inject_read_error();
|
||||
if (off == 0)
|
||||
off = vfs_llseek(file, start, SEEK_DATA);
|
||||
if (off == -ENXIO)
|
||||
return -ENODATA; /* Beyond EOF */
|
||||
if (off < 0 && off >= (loff_t)-MAX_ERRNO)
|
||||
return -ENOBUFS; /* Error. */
|
||||
if (round_up(off, granularity) >= start + len)
|
||||
return -ENODATA; /* No data in range */
|
||||
|
||||
off2 = cachefiles_inject_read_error();
|
||||
if (off2 == 0)
|
||||
off2 = vfs_llseek(file, off, SEEK_HOLE);
|
||||
if (off2 == -ENXIO)
|
||||
return -ENODATA; /* Beyond EOF */
|
||||
if (off2 < 0 && off2 >= (loff_t)-MAX_ERRNO)
|
||||
return -ENOBUFS; /* Error. */
|
||||
|
||||
/* Round away partial blocks */
|
||||
off = round_up(off, granularity);
|
||||
off2 = round_down(off2, granularity);
|
||||
if (off2 <= off)
|
||||
return -ENODATA;
|
||||
|
||||
*_data_start = off;
|
||||
if (off2 > start + len)
|
||||
*_data_len = len;
|
||||
else
|
||||
*_data_len = off2 - off;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Handle completion of a write to the cache.
|
||||
*/
|
||||
@ -545,6 +603,7 @@ static const struct netfs_cache_ops cachefiles_netfs_cache_ops = {
|
||||
.write = cachefiles_write,
|
||||
.prepare_read = cachefiles_prepare_read,
|
||||
.prepare_write = cachefiles_prepare_write,
|
||||
.query_occupancy = cachefiles_query_occupancy,
|
||||
};
|
||||
|
||||
/*
|
||||
|
@ -244,6 +244,13 @@ struct netfs_cache_ops {
|
||||
int (*prepare_write)(struct netfs_cache_resources *cres,
|
||||
loff_t *_start, size_t *_len, loff_t i_size,
|
||||
bool no_space_allocated_yet);
|
||||
|
||||
/* Query the occupancy of the cache in a region, returning where the
|
||||
* next chunk of data starts and how long it is.
|
||||
*/
|
||||
int (*query_occupancy)(struct netfs_cache_resources *cres,
|
||||
loff_t start, size_t len, size_t granularity,
|
||||
loff_t *_data_start, size_t *_data_len);
|
||||
};
|
||||
|
||||
struct readahead_control;
|
||||
|
Loading…
Reference in New Issue
Block a user