mirror of
https://github.com/torvalds/linux.git
synced 2024-12-28 05:41:55 +00:00
netfs, cachefiles: Pass upper bound length to allow expansion
Make netfslib pass the maximum length to the ->prepare_write() op to tell the cache how much it can expand the length of a write to. This allows a write to the server at the end of a file to be limited to a few bytes whilst writing an entire block to the cache (something required by direct I/O). Signed-off-by: David Howells <dhowells@redhat.com> Reviewed-by: Jeff Layton <jlayton@kernel.org> cc: linux-cachefs@redhat.com cc: linux-fsdevel@vger.kernel.org cc: linux-mm@kvack.org
This commit is contained in:
parent
80645bd4aa
commit
e0ace6ca98
@ -233,7 +233,7 @@ extern bool cachefiles_begin_operation(struct netfs_cache_resources *cres,
|
||||
enum fscache_want_state want_state);
|
||||
extern int __cachefiles_prepare_write(struct cachefiles_object *object,
|
||||
struct file *file,
|
||||
loff_t *_start, size_t *_len,
|
||||
loff_t *_start, size_t *_len, size_t upper_len,
|
||||
bool no_space_allocated_yet);
|
||||
extern int __cachefiles_write(struct cachefiles_object *object,
|
||||
struct file *file,
|
||||
|
@ -518,7 +518,7 @@ cachefiles_prepare_ondemand_read(struct netfs_cache_resources *cres,
|
||||
*/
|
||||
int __cachefiles_prepare_write(struct cachefiles_object *object,
|
||||
struct file *file,
|
||||
loff_t *_start, size_t *_len,
|
||||
loff_t *_start, size_t *_len, size_t upper_len,
|
||||
bool no_space_allocated_yet)
|
||||
{
|
||||
struct cachefiles_cache *cache = object->volume->cache;
|
||||
@ -530,6 +530,8 @@ int __cachefiles_prepare_write(struct cachefiles_object *object,
|
||||
down = start - round_down(start, PAGE_SIZE);
|
||||
*_start = start - down;
|
||||
*_len = round_up(down + len, PAGE_SIZE);
|
||||
if (down < start || *_len > upper_len)
|
||||
return -ENOBUFS;
|
||||
|
||||
/* We need to work out whether there's sufficient disk space to perform
|
||||
* the write - but we can skip that check if we have space already
|
||||
@ -592,8 +594,8 @@ check_space:
|
||||
}
|
||||
|
||||
static int cachefiles_prepare_write(struct netfs_cache_resources *cres,
|
||||
loff_t *_start, size_t *_len, loff_t i_size,
|
||||
bool no_space_allocated_yet)
|
||||
loff_t *_start, size_t *_len, size_t upper_len,
|
||||
loff_t i_size, bool no_space_allocated_yet)
|
||||
{
|
||||
struct cachefiles_object *object = cachefiles_cres_object(cres);
|
||||
struct cachefiles_cache *cache = object->volume->cache;
|
||||
@ -609,7 +611,7 @@ static int cachefiles_prepare_write(struct netfs_cache_resources *cres,
|
||||
|
||||
cachefiles_begin_secure(cache, &saved_cred);
|
||||
ret = __cachefiles_prepare_write(object, cachefiles_cres_file(cres),
|
||||
_start, _len,
|
||||
_start, _len, upper_len,
|
||||
no_space_allocated_yet);
|
||||
cachefiles_end_secure(cache, saved_cred);
|
||||
return ret;
|
||||
|
@ -52,7 +52,7 @@ static ssize_t cachefiles_ondemand_fd_write_iter(struct kiocb *kiocb,
|
||||
return -ENOBUFS;
|
||||
|
||||
cachefiles_begin_secure(cache, &saved_cred);
|
||||
ret = __cachefiles_prepare_write(object, file, &pos, &len, true);
|
||||
ret = __cachefiles_prepare_write(object, file, &pos, &len, len, true);
|
||||
cachefiles_end_secure(cache, saved_cred);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
@ -237,7 +237,7 @@ void __fscache_write_to_cache(struct fscache_cookie *cookie,
|
||||
fscache_access_io_write) < 0)
|
||||
goto abandon_free;
|
||||
|
||||
ret = cres->ops->prepare_write(cres, &start, &len, i_size, false);
|
||||
ret = cres->ops->prepare_write(cres, &start, &len, len, i_size, false);
|
||||
if (ret < 0)
|
||||
goto abandon_end;
|
||||
|
||||
|
@ -199,7 +199,7 @@ static void netfs_rreq_do_write_to_cache(struct netfs_io_request *rreq)
|
||||
}
|
||||
|
||||
ret = cres->ops->prepare_write(cres, &subreq->start, &subreq->len,
|
||||
rreq->i_size, true);
|
||||
subreq->len, rreq->i_size, true);
|
||||
if (ret < 0) {
|
||||
trace_netfs_failure(rreq, subreq, ret, netfs_fail_prepare_write);
|
||||
trace_netfs_sreq(subreq, netfs_sreq_trace_write_skip);
|
||||
|
@ -33,6 +33,7 @@ struct netfs_io_request *netfs_alloc_request(struct address_space *mapping,
|
||||
|
||||
rreq->start = start;
|
||||
rreq->len = len;
|
||||
rreq->upper_len = len;
|
||||
rreq->origin = origin;
|
||||
rreq->netfs_ops = ctx->ops;
|
||||
rreq->mapping = mapping;
|
||||
|
@ -280,7 +280,7 @@ EXPORT_SYMBOL(netfs_queue_write_request);
|
||||
*/
|
||||
static void netfs_set_up_write_to_cache(struct netfs_io_request *wreq)
|
||||
{
|
||||
struct netfs_cache_resources *cres;
|
||||
struct netfs_cache_resources *cres = &wreq->cache_resources;
|
||||
struct netfs_io_subrequest *subreq;
|
||||
struct netfs_inode *ctx = netfs_inode(wreq->inode);
|
||||
struct fscache_cookie *cookie = netfs_i_cookie(ctx);
|
||||
@ -294,26 +294,21 @@ static void netfs_set_up_write_to_cache(struct netfs_io_request *wreq)
|
||||
}
|
||||
|
||||
_debug("write to cache");
|
||||
ret = fscache_begin_write_operation(cres, cookie);
|
||||
if (ret < 0)
|
||||
return;
|
||||
|
||||
ret = cres->ops->prepare_write(cres, &start, &len, wreq->upper_len,
|
||||
i_size_read(wreq->inode), true);
|
||||
if (ret < 0)
|
||||
return;
|
||||
|
||||
subreq = netfs_create_write_request(wreq, NETFS_WRITE_TO_CACHE, start, len,
|
||||
netfs_write_to_cache_op_worker);
|
||||
if (!subreq)
|
||||
return;
|
||||
|
||||
cres = &wreq->cache_resources;
|
||||
ret = fscache_begin_read_operation(cres, cookie);
|
||||
if (ret < 0) {
|
||||
netfs_write_subrequest_terminated(subreq, ret, false);
|
||||
return;
|
||||
}
|
||||
|
||||
ret = cres->ops->prepare_write(cres, &start, &len, i_size_read(wreq->inode),
|
||||
true);
|
||||
if (ret < 0) {
|
||||
netfs_write_subrequest_terminated(subreq, ret, false);
|
||||
return;
|
||||
}
|
||||
|
||||
netfs_queue_write_request(subreq);
|
||||
netfs_write_to_cache_op(subreq);
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -180,7 +180,7 @@ static int fscache_fallback_write_pages(struct inode *inode, loff_t start, size_
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
ret = cres.ops->prepare_write(&cres, &start, &len, i_size_read(inode),
|
||||
ret = cres.ops->prepare_write(&cres, &start, &len, len, i_size_read(inode),
|
||||
no_space_allocated_yet);
|
||||
if (ret == 0)
|
||||
ret = fscache_write(&cres, start, &iter, NULL, NULL);
|
||||
|
@ -261,6 +261,7 @@ struct netfs_io_request {
|
||||
atomic_t nr_copy_ops; /* Number of copy-to-cache ops in progress */
|
||||
size_t submitted; /* Amount submitted for I/O so far */
|
||||
size_t len; /* Length of the request */
|
||||
size_t upper_len; /* Length can be extended to here */
|
||||
size_t transferred; /* Amount to be indicated as transferred */
|
||||
short error; /* 0 or error that occurred */
|
||||
enum netfs_io_origin origin; /* Origin of the request */
|
||||
@ -357,8 +358,8 @@ struct netfs_cache_ops {
|
||||
* actually do.
|
||||
*/
|
||||
int (*prepare_write)(struct netfs_cache_resources *cres,
|
||||
loff_t *_start, size_t *_len, loff_t i_size,
|
||||
bool no_space_allocated_yet);
|
||||
loff_t *_start, size_t *_len, size_t upper_len,
|
||||
loff_t i_size, bool no_space_allocated_yet);
|
||||
|
||||
/* Prepare an on-demand read operation, shortening it to a cached/uncached
|
||||
* boundary as appropriate.
|
||||
|
Loading…
Reference in New Issue
Block a user