summaryrefslogtreecommitdiff
path: root/fs/ceph/addr.c
diff options
context:
space:
mode:
authorJeff Layton <jlayton@kernel.org>2022-02-26 14:33:03 +0300
committerIlya Dryomov <idryomov@gmail.com>2023-08-22 10:01:47 +0300
commit03bc06c7b0bd8d86b9f17f459acaeb1283ba2700 (patch)
tree4fac68b0dbfa895f1851e00653a8e1a2ca7f217f /fs/ceph/addr.c
parentf628d799972799023d32c2542bb2639eb8c4f84e (diff)
downloadlinux-03bc06c7b0bd8d86b9f17f459acaeb1283ba2700.tar.xz
ceph: add new mount option to enable sparse reads
Add a new mount option that has the client issue sparse reads instead of normal ones. The callers now preallocate an sparse extent buffer that the libceph receive code can populate and hand back after the operation completes. After a successful sparse read, we can't use the req->r_result value to determine the amount of data "read", so instead we set the received length to be from the end of the last extent in the buffer. Any interstitial holes will have been filled by the receive code. [ xiubli: fix a double free on req reported by Ilya ] Signed-off-by: Jeff Layton <jlayton@kernel.org> Reviewed-by: Xiubo Li <xiubli@redhat.com> Reviewed-and-tested-by: Luís Henriques <lhenriques@suse.de> Reviewed-by: Milind Changire <mchangir@redhat.com> Signed-off-by: Ilya Dryomov <idryomov@gmail.com>
Diffstat (limited to 'fs/ceph/addr.c')
-rw-r--r--fs/ceph/addr.c15
1 files changed, 13 insertions, 2 deletions
diff --git a/fs/ceph/addr.c b/fs/ceph/addr.c
index 59cbfb80edbd..f45ebe957bbe 100644
--- a/fs/ceph/addr.c
+++ b/fs/ceph/addr.c
@@ -245,8 +245,10 @@ static void finish_netfs_read(struct ceph_osd_request *req)
struct ceph_fs_client *fsc = ceph_inode_to_client(req->r_inode);
struct ceph_osd_data *osd_data = osd_req_op_extent_osd_data(req, 0);
struct netfs_io_subrequest *subreq = req->r_priv;
+ struct ceph_osd_req_op *op = &req->r_ops[0];
int num_pages;
int err = req->r_result;
+ bool sparse = (op->op == CEPH_OSD_OP_SPARSE_READ);
ceph_update_read_metrics(&fsc->mdsc->metric, req->r_start_latency,
req->r_end_latency, osd_data->length, err);
@@ -255,7 +257,9 @@ static void finish_netfs_read(struct ceph_osd_request *req)
subreq->len, i_size_read(req->r_inode));
/* no object means success but no data */
- if (err == -ENOENT)
+ if (sparse && err >= 0)
+ err = ceph_sparse_ext_map_end(op);
+ else if (err == -ENOENT)
err = 0;
else if (err == -EBLOCKLISTED)
fsc->blocklisted = true;
@@ -338,6 +342,7 @@ static void ceph_netfs_issue_read(struct netfs_io_subrequest *subreq)
size_t page_off;
int err = 0;
u64 len = subreq->len;
+ bool sparse = ceph_test_mount_opt(fsc, SPARSEREAD);
if (ceph_inode_is_shutdown(inode)) {
err = -EIO;
@@ -348,7 +353,7 @@ static void ceph_netfs_issue_read(struct netfs_io_subrequest *subreq)
return;
req = ceph_osdc_new_request(&fsc->client->osdc, &ci->i_layout, vino, subreq->start, &len,
- 0, 1, CEPH_OSD_OP_READ,
+ 0, 1, sparse ? CEPH_OSD_OP_SPARSE_READ : CEPH_OSD_OP_READ,
CEPH_OSD_FLAG_READ | fsc->client->osdc.client->options->read_from_replica,
NULL, ci->i_truncate_seq, ci->i_truncate_size, false);
if (IS_ERR(req)) {
@@ -357,6 +362,12 @@ static void ceph_netfs_issue_read(struct netfs_io_subrequest *subreq)
goto out;
}
+ if (sparse) {
+ err = ceph_alloc_sparse_ext_map(&req->r_ops[0]);
+ if (err)
+ goto out;
+ }
+
dout("%s: pos=%llu orig_len=%zu len=%llu\n", __func__, subreq->start, subreq->len, len);
iov_iter_xarray(&iter, ITER_DEST, &rreq->mapping->i_pages, subreq->start, len);
err = iov_iter_get_pages_alloc2(&iter, &pages, len, &page_off);