Commit 768ddb1e authored by David Howells's avatar David Howells

netfs: Limit subrequest by size or number of segments

Limit a subrequest to a maximum size and/or a maximum number of contiguous
physical regions.  This permits, for instance, an subreq's iterator to be
limited to the number of DMA'able segments that a large RDMA request can
handle.
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 cae932d3
...@@ -525,6 +525,7 @@ netfs_rreq_prepare_read(struct netfs_io_request *rreq, ...@@ -525,6 +525,7 @@ netfs_rreq_prepare_read(struct netfs_io_request *rreq,
struct iov_iter *io_iter) struct iov_iter *io_iter)
{ {
enum netfs_io_source source; enum netfs_io_source source;
size_t lsize;
_enter("%llx-%llx,%llx", subreq->start, subreq->start + subreq->len, rreq->i_size); _enter("%llx-%llx,%llx", subreq->start, subreq->start + subreq->len, rreq->i_size);
...@@ -547,13 +548,30 @@ netfs_rreq_prepare_read(struct netfs_io_request *rreq, ...@@ -547,13 +548,30 @@ netfs_rreq_prepare_read(struct netfs_io_request *rreq,
source = NETFS_INVALID_READ; source = NETFS_INVALID_READ;
goto out; goto out;
} }
if (subreq->max_nr_segs) {
lsize = netfs_limit_iter(io_iter, 0, subreq->len,
subreq->max_nr_segs);
if (subreq->len > lsize) {
subreq->len = lsize;
trace_netfs_sreq(subreq, netfs_sreq_trace_limited);
}
} }
}
if (subreq->len > rreq->len)
pr_warn("R=%08x[%u] SREQ>RREQ %zx > %zx\n",
rreq->debug_id, subreq->debug_index,
subreq->len, rreq->len);
if (WARN_ON(subreq->len == 0)) { if (WARN_ON(subreq->len == 0)) {
source = NETFS_INVALID_READ; source = NETFS_INVALID_READ;
goto out; goto out;
} }
subreq->source = source;
trace_netfs_sreq(subreq, netfs_sreq_trace_prepare);
subreq->io_iter = *io_iter; subreq->io_iter = *io_iter;
iov_iter_truncate(&subreq->io_iter, subreq->len); iov_iter_truncate(&subreq->io_iter, subreq->len);
iov_iter_advance(io_iter, subreq->len); iov_iter_advance(io_iter, subreq->len);
......
...@@ -161,6 +161,7 @@ struct netfs_io_subrequest { ...@@ -161,6 +161,7 @@ struct netfs_io_subrequest {
refcount_t ref; refcount_t ref;
short error; /* 0 or error that occurred */ short error; /* 0 or error that occurred */
unsigned short debug_index; /* Index in list (for debugging output) */ unsigned short debug_index; /* Index in list (for debugging output) */
unsigned int max_nr_segs; /* 0 or max number of segments in an iterator */
enum netfs_io_source source; /* Where to read from/write to */ enum netfs_io_source source; /* Where to read from/write to */
unsigned long flags; unsigned long flags;
#define NETFS_SREQ_COPY_TO_CACHE 0 /* Set if should copy the data to the cache */ #define NETFS_SREQ_COPY_TO_CACHE 0 /* Set if should copy the data to the cache */
......
...@@ -44,6 +44,7 @@ ...@@ -44,6 +44,7 @@
#define netfs_sreq_traces \ #define netfs_sreq_traces \
EM(netfs_sreq_trace_download_instead, "RDOWN") \ EM(netfs_sreq_trace_download_instead, "RDOWN") \
EM(netfs_sreq_trace_free, "FREE ") \ EM(netfs_sreq_trace_free, "FREE ") \
EM(netfs_sreq_trace_limited, "LIMIT") \
EM(netfs_sreq_trace_prepare, "PREP ") \ EM(netfs_sreq_trace_prepare, "PREP ") \
EM(netfs_sreq_trace_resubmit_short, "SHORT") \ EM(netfs_sreq_trace_resubmit_short, "SHORT") \
EM(netfs_sreq_trace_submit, "SUBMT") \ EM(netfs_sreq_trace_submit, "SUBMT") \
......
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