Commit e0ace6ca authored by David Howells's avatar David Howells

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: default avatarDavid Howells <dhowells@redhat.com>
Reviewed-by: default avatarJeff Layton <jlayton@kernel.org>
cc: linux-cachefs@redhat.com
cc: linux-fsdevel@vger.kernel.org
cc: linux-mm@kvack.org
parent 80645bd4
...@@ -233,7 +233,7 @@ extern bool cachefiles_begin_operation(struct netfs_cache_resources *cres, ...@@ -233,7 +233,7 @@ extern bool cachefiles_begin_operation(struct netfs_cache_resources *cres,
enum fscache_want_state want_state); enum fscache_want_state want_state);
extern int __cachefiles_prepare_write(struct cachefiles_object *object, extern int __cachefiles_prepare_write(struct cachefiles_object *object,
struct file *file, struct file *file,
loff_t *_start, size_t *_len, loff_t *_start, size_t *_len, size_t upper_len,
bool no_space_allocated_yet); bool no_space_allocated_yet);
extern int __cachefiles_write(struct cachefiles_object *object, extern int __cachefiles_write(struct cachefiles_object *object,
struct file *file, struct file *file,
......
...@@ -518,7 +518,7 @@ cachefiles_prepare_ondemand_read(struct netfs_cache_resources *cres, ...@@ -518,7 +518,7 @@ cachefiles_prepare_ondemand_read(struct netfs_cache_resources *cres,
*/ */
int __cachefiles_prepare_write(struct cachefiles_object *object, int __cachefiles_prepare_write(struct cachefiles_object *object,
struct file *file, struct file *file,
loff_t *_start, size_t *_len, loff_t *_start, size_t *_len, size_t upper_len,
bool no_space_allocated_yet) bool no_space_allocated_yet)
{ {
struct cachefiles_cache *cache = object->volume->cache; struct cachefiles_cache *cache = object->volume->cache;
...@@ -530,6 +530,8 @@ int __cachefiles_prepare_write(struct cachefiles_object *object, ...@@ -530,6 +530,8 @@ int __cachefiles_prepare_write(struct cachefiles_object *object,
down = start - round_down(start, PAGE_SIZE); down = start - round_down(start, PAGE_SIZE);
*_start = start - down; *_start = start - down;
*_len = round_up(down + len, PAGE_SIZE); *_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 /* 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 * the write - but we can skip that check if we have space already
...@@ -592,8 +594,8 @@ int __cachefiles_prepare_write(struct cachefiles_object *object, ...@@ -592,8 +594,8 @@ int __cachefiles_prepare_write(struct cachefiles_object *object,
} }
static int cachefiles_prepare_write(struct netfs_cache_resources *cres, static int cachefiles_prepare_write(struct netfs_cache_resources *cres,
loff_t *_start, size_t *_len, loff_t i_size, loff_t *_start, size_t *_len, size_t upper_len,
bool no_space_allocated_yet) loff_t i_size, bool no_space_allocated_yet)
{ {
struct cachefiles_object *object = cachefiles_cres_object(cres); struct cachefiles_object *object = cachefiles_cres_object(cres);
struct cachefiles_cache *cache = object->volume->cache; struct cachefiles_cache *cache = object->volume->cache;
...@@ -609,7 +611,7 @@ static int cachefiles_prepare_write(struct netfs_cache_resources *cres, ...@@ -609,7 +611,7 @@ static int cachefiles_prepare_write(struct netfs_cache_resources *cres,
cachefiles_begin_secure(cache, &saved_cred); cachefiles_begin_secure(cache, &saved_cred);
ret = __cachefiles_prepare_write(object, cachefiles_cres_file(cres), ret = __cachefiles_prepare_write(object, cachefiles_cres_file(cres),
_start, _len, _start, _len, upper_len,
no_space_allocated_yet); no_space_allocated_yet);
cachefiles_end_secure(cache, saved_cred); cachefiles_end_secure(cache, saved_cred);
return ret; return ret;
......
...@@ -52,7 +52,7 @@ static ssize_t cachefiles_ondemand_fd_write_iter(struct kiocb *kiocb, ...@@ -52,7 +52,7 @@ static ssize_t cachefiles_ondemand_fd_write_iter(struct kiocb *kiocb,
return -ENOBUFS; return -ENOBUFS;
cachefiles_begin_secure(cache, &saved_cred); 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); cachefiles_end_secure(cache, saved_cred);
if (ret < 0) if (ret < 0)
return ret; return ret;
......
...@@ -237,7 +237,7 @@ void __fscache_write_to_cache(struct fscache_cookie *cookie, ...@@ -237,7 +237,7 @@ void __fscache_write_to_cache(struct fscache_cookie *cookie,
fscache_access_io_write) < 0) fscache_access_io_write) < 0)
goto abandon_free; 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) if (ret < 0)
goto abandon_end; goto abandon_end;
......
...@@ -199,7 +199,7 @@ static void netfs_rreq_do_write_to_cache(struct netfs_io_request *rreq) ...@@ -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, ret = cres->ops->prepare_write(cres, &subreq->start, &subreq->len,
rreq->i_size, true); subreq->len, rreq->i_size, true);
if (ret < 0) { if (ret < 0) {
trace_netfs_failure(rreq, subreq, ret, netfs_fail_prepare_write); trace_netfs_failure(rreq, subreq, ret, netfs_fail_prepare_write);
trace_netfs_sreq(subreq, netfs_sreq_trace_write_skip); trace_netfs_sreq(subreq, netfs_sreq_trace_write_skip);
......
...@@ -33,6 +33,7 @@ struct netfs_io_request *netfs_alloc_request(struct address_space *mapping, ...@@ -33,6 +33,7 @@ struct netfs_io_request *netfs_alloc_request(struct address_space *mapping,
rreq->start = start; rreq->start = start;
rreq->len = len; rreq->len = len;
rreq->upper_len = len;
rreq->origin = origin; rreq->origin = origin;
rreq->netfs_ops = ctx->ops; rreq->netfs_ops = ctx->ops;
rreq->mapping = mapping; rreq->mapping = mapping;
......
...@@ -280,7 +280,7 @@ EXPORT_SYMBOL(netfs_queue_write_request); ...@@ -280,7 +280,7 @@ EXPORT_SYMBOL(netfs_queue_write_request);
*/ */
static void netfs_set_up_write_to_cache(struct netfs_io_request *wreq) 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_io_subrequest *subreq;
struct netfs_inode *ctx = netfs_inode(wreq->inode); struct netfs_inode *ctx = netfs_inode(wreq->inode);
struct fscache_cookie *cookie = netfs_i_cookie(ctx); 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) ...@@ -294,26 +294,21 @@ static void netfs_set_up_write_to_cache(struct netfs_io_request *wreq)
} }
_debug("write to cache"); _debug("write to cache");
subreq = netfs_create_write_request(wreq, NETFS_WRITE_TO_CACHE, start, len, ret = fscache_begin_write_operation(cres, cookie);
netfs_write_to_cache_op_worker); if (ret < 0)
if (!subreq)
return; return;
cres = &wreq->cache_resources; ret = cres->ops->prepare_write(cres, &start, &len, wreq->upper_len,
ret = fscache_begin_read_operation(cres, cookie); i_size_read(wreq->inode), true);
if (ret < 0) { if (ret < 0)
netfs_write_subrequest_terminated(subreq, ret, false);
return; return;
}
ret = cres->ops->prepare_write(cres, &start, &len, i_size_read(wreq->inode), subreq = netfs_create_write_request(wreq, NETFS_WRITE_TO_CACHE, start, len,
true); netfs_write_to_cache_op_worker);
if (ret < 0) { if (!subreq)
netfs_write_subrequest_terminated(subreq, ret, false);
return; 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_ ...@@ -180,7 +180,7 @@ static int fscache_fallback_write_pages(struct inode *inode, loff_t start, size_
if (ret < 0) if (ret < 0)
return ret; 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); no_space_allocated_yet);
if (ret == 0) if (ret == 0)
ret = fscache_write(&cres, start, &iter, NULL, NULL); ret = fscache_write(&cres, start, &iter, NULL, NULL);
......
...@@ -261,6 +261,7 @@ struct netfs_io_request { ...@@ -261,6 +261,7 @@ struct netfs_io_request {
atomic_t nr_copy_ops; /* Number of copy-to-cache ops in progress */ 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 submitted; /* Amount submitted for I/O so far */
size_t len; /* Length of the request */ 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 */ size_t transferred; /* Amount to be indicated as transferred */
short error; /* 0 or error that occurred */ short error; /* 0 or error that occurred */
enum netfs_io_origin origin; /* Origin of the request */ enum netfs_io_origin origin; /* Origin of the request */
...@@ -357,8 +358,8 @@ struct netfs_cache_ops { ...@@ -357,8 +358,8 @@ struct netfs_cache_ops {
* actually do. * actually do.
*/ */
int (*prepare_write)(struct netfs_cache_resources *cres, int (*prepare_write)(struct netfs_cache_resources *cres,
loff_t *_start, size_t *_len, loff_t i_size, loff_t *_start, size_t *_len, size_t upper_len,
bool no_space_allocated_yet); loff_t i_size, bool no_space_allocated_yet);
/* Prepare an on-demand read operation, shortening it to a cached/uncached /* Prepare an on-demand read operation, shortening it to a cached/uncached
* boundary as appropriate. * boundary as appropriate.
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment