Skip to content

Commit bee9f65

Browse files
dhowellssmfrench
authored andcommitted
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 <[email protected]> cc: [email protected] Acked-by: Jeff Layton <[email protected]> Reviewed-by: Rohith Surabattula <[email protected]> Signed-off-by: Steve French <[email protected]>
1 parent 052e04a commit bee9f65

File tree

3 files changed

+82
-0
lines changed

3 files changed

+82
-0
lines changed

Documentation/filesystems/netfs_library.rst

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -462,6 +462,10 @@ operation table looks like the following::
462462
struct iov_iter *iter,
463463
netfs_io_terminated_t term_func,
464464
void *term_func_priv);
465+
466+
int (*query_occupancy)(struct netfs_cache_resources *cres,
467+
loff_t start, size_t len, size_t granularity,
468+
loff_t *_data_start, size_t *_data_len);
465469
};
466470

467471
With a termination handler function pointer::
@@ -536,6 +540,18 @@ The methods defined in the table are:
536540
indicating whether the termination is definitely happening in the caller's
537541
context.
538542

543+
* ``query_occupancy()``
544+
545+
[Required] Called to find out where the next piece of data is within a
546+
particular region of the cache. The start and length of the region to be
547+
queried are passed in, along with the granularity to which the answer needs
548+
to be aligned. The function passes back the start and length of the data,
549+
if any, available within that region. Note that there may be a hole at the
550+
front.
551+
552+
It returns 0 if some data was found, -ENODATA if there was no usable data
553+
within the region or -ENOBUFS if there is no caching on this file.
554+
539555
Note that these methods are passed a pointer to the cache resource structure,
540556
not the read request structure as they could be used in other situations where
541557
there isn't a read request structure as well, such as writing dirty data to the

fs/cachefiles/io.c

Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -191,6 +191,64 @@ static int cachefiles_read(struct netfs_cache_resources *cres,
191191
return ret;
192192
}
193193

194+
/*
195+
* Query the occupancy of the cache in a region, returning where the next chunk
196+
* of data starts and how long it is.
197+
*/
198+
static int cachefiles_query_occupancy(struct netfs_cache_resources *cres,
199+
loff_t start, size_t len, size_t granularity,
200+
loff_t *_data_start, size_t *_data_len)
201+
{
202+
struct cachefiles_object *object;
203+
struct file *file;
204+
loff_t off, off2;
205+
206+
*_data_start = -1;
207+
*_data_len = 0;
208+
209+
if (!fscache_wait_for_operation(cres, FSCACHE_WANT_READ))
210+
return -ENOBUFS;
211+
212+
object = cachefiles_cres_object(cres);
213+
file = cachefiles_cres_file(cres);
214+
granularity = max_t(size_t, object->volume->cache->bsize, granularity);
215+
216+
_enter("%pD,%li,%llx,%zx/%llx",
217+
file, file_inode(file)->i_ino, start, len,
218+
i_size_read(file_inode(file)));
219+
220+
off = cachefiles_inject_read_error();
221+
if (off == 0)
222+
off = vfs_llseek(file, start, SEEK_DATA);
223+
if (off == -ENXIO)
224+
return -ENODATA; /* Beyond EOF */
225+
if (off < 0 && off >= (loff_t)-MAX_ERRNO)
226+
return -ENOBUFS; /* Error. */
227+
if (round_up(off, granularity) >= start + len)
228+
return -ENODATA; /* No data in range */
229+
230+
off2 = cachefiles_inject_read_error();
231+
if (off2 == 0)
232+
off2 = vfs_llseek(file, off, SEEK_HOLE);
233+
if (off2 == -ENXIO)
234+
return -ENODATA; /* Beyond EOF */
235+
if (off2 < 0 && off2 >= (loff_t)-MAX_ERRNO)
236+
return -ENOBUFS; /* Error. */
237+
238+
/* Round away partial blocks */
239+
off = round_up(off, granularity);
240+
off2 = round_down(off2, granularity);
241+
if (off2 <= off)
242+
return -ENODATA;
243+
244+
*_data_start = off;
245+
if (off2 > start + len)
246+
*_data_len = len;
247+
else
248+
*_data_len = off2 - off;
249+
return 0;
250+
}
251+
194252
/*
195253
* Handle completion of a write to the cache.
196254
*/
@@ -545,6 +603,7 @@ static const struct netfs_cache_ops cachefiles_netfs_cache_ops = {
545603
.write = cachefiles_write,
546604
.prepare_read = cachefiles_prepare_read,
547605
.prepare_write = cachefiles_prepare_write,
606+
.query_occupancy = cachefiles_query_occupancy,
548607
};
549608

550609
/*

include/linux/netfs.h

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -244,6 +244,13 @@ struct netfs_cache_ops {
244244
int (*prepare_write)(struct netfs_cache_resources *cres,
245245
loff_t *_start, size_t *_len, loff_t i_size,
246246
bool no_space_allocated_yet);
247+
248+
/* Query the occupancy of the cache in a region, returning where the
249+
* next chunk of data starts and how long it is.
250+
*/
251+
int (*query_occupancy)(struct netfs_cache_resources *cres,
252+
loff_t start, size_t len, size_t granularity,
253+
loff_t *_data_start, size_t *_data_len);
247254
};
248255

249256
struct readahead_control;

0 commit comments

Comments
 (0)