ceph: try to allocate a smaller extent map for sparse read
authorXiubo Li <xiubli@redhat.com>
Tue, 7 Nov 2023 02:44:41 +0000 (10:44 +0800)
committerIlya Dryomov <idryomov@gmail.com>
Mon, 15 Jan 2024 14:40:50 +0000 (15:40 +0100)
In fscrypt case and for a smaller read length we can predict the
max count of the extent map. And for small read length use cases
this could save some memories.

[ idryomov: squash into a single patch to avoid build break, drop
  redundant variable in ceph_alloc_sparse_ext_map() ]

Signed-off-by: Xiubo Li <xiubli@redhat.com>
Reviewed-by: Ilya Dryomov <idryomov@gmail.com>
Signed-off-by: Ilya Dryomov <idryomov@gmail.com>
fs/ceph/addr.c
fs/ceph/file.c
fs/ceph/super.h
include/linux/ceph/osd_client.h

index 85be3bf18cdf38834de3141dfe0d6d75393c6d94..a5caafc1859ec7f864801a3554c9da33cea80ac7 100644 (file)
@@ -357,6 +357,7 @@ static void ceph_netfs_issue_read(struct netfs_io_subrequest *subreq)
        u64 len = subreq->len;
        bool sparse = IS_ENCRYPTED(inode) || ceph_test_mount_opt(fsc, SPARSEREAD);
        u64 off = subreq->start;
+       int extent_cnt;
 
        if (ceph_inode_is_shutdown(inode)) {
                err = -EIO;
@@ -379,7 +380,8 @@ static void ceph_netfs_issue_read(struct netfs_io_subrequest *subreq)
        }
 
        if (sparse) {
-               err = ceph_alloc_sparse_ext_map(&req->r_ops[0]);
+               extent_cnt = __ceph_sparse_read_ext_count(inode, len);
+               err = ceph_alloc_sparse_ext_map(&req->r_ops[0], extent_cnt);
                if (err)
                        goto out;
        }
index 3b5aae29e94478ced4e2a962bad1fa26f63b50cd..4dde0da10079b5e28334e4d91f11a15924871431 100644 (file)
@@ -1028,6 +1028,7 @@ ssize_t __ceph_sync_read(struct inode *inode, loff_t *ki_pos,
                struct ceph_osd_req_op *op;
                u64 read_off = off;
                u64 read_len = len;
+               int extent_cnt;
 
                /* determine new offset/length if encrypted */
                ceph_fscrypt_adjust_off_and_len(inode, &read_off, &read_len);
@@ -1067,7 +1068,8 @@ ssize_t __ceph_sync_read(struct inode *inode, loff_t *ki_pos,
 
                op = &req->r_ops[0];
                if (sparse) {
-                       ret = ceph_alloc_sparse_ext_map(op);
+                       extent_cnt = __ceph_sparse_read_ext_count(inode, read_len);
+                       ret = ceph_alloc_sparse_ext_map(op, extent_cnt);
                        if (ret) {
                                ceph_osdc_put_request(req);
                                break;
@@ -1464,6 +1466,7 @@ ceph_direct_read_write(struct kiocb *iocb, struct iov_iter *iter,
                ssize_t len;
                struct ceph_osd_req_op *op;
                int readop = sparse ? CEPH_OSD_OP_SPARSE_READ : CEPH_OSD_OP_READ;
+               int extent_cnt;
 
                if (write)
                        size = min_t(u64, size, fsc->mount_options->wsize);
@@ -1527,7 +1530,8 @@ ceph_direct_read_write(struct kiocb *iocb, struct iov_iter *iter,
                osd_req_op_extent_osd_data_bvecs(req, 0, bvecs, num_pages, len);
                op = &req->r_ops[0];
                if (sparse) {
-                       ret = ceph_alloc_sparse_ext_map(op);
+                       extent_cnt = __ceph_sparse_read_ext_count(inode, size);
+                       ret = ceph_alloc_sparse_ext_map(op, extent_cnt);
                        if (ret) {
                                ceph_osdc_put_request(req);
                                break;
index fe0f64a0acb27058014b188bec906e07310fad1f..b06e2bc86221bf02fe54b2aa3304be80bedc5214 100644 (file)
@@ -3,6 +3,7 @@
 #define _FS_CEPH_SUPER_H
 
 #include <linux/ceph/ceph_debug.h>
+#include <linux/ceph/osd_client.h>
 
 #include <asm/unaligned.h>
 #include <linux/backing-dev.h>
@@ -1407,6 +1408,19 @@ static inline void __ceph_update_quota(struct ceph_inode_info *ci,
                ceph_adjust_quota_realms_count(&ci->netfs.inode, has_quota);
 }
 
+static inline int __ceph_sparse_read_ext_count(struct inode *inode, u64 len)
+{
+       int cnt = 0;
+
+       if (IS_ENCRYPTED(inode)) {
+               cnt = len >> CEPH_FSCRYPT_BLOCK_SHIFT;
+               if (cnt > CEPH_SPARSE_EXT_ARRAY_INITIAL)
+                       cnt = 0;
+       }
+
+       return cnt;
+}
+
 extern void ceph_handle_quota(struct ceph_mds_client *mdsc,
                              struct ceph_mds_session *session,
                              struct ceph_msg *msg);
index b8610e9d2471f5a7928e8d1b62a418e491ea575d..fa018d5864e7422c522194c16ff45a8dd0db1376 100644 (file)
@@ -572,9 +572,12 @@ int __ceph_alloc_sparse_ext_map(struct ceph_osd_req_op *op, int cnt);
  */
 #define CEPH_SPARSE_EXT_ARRAY_INITIAL  16
 
-static inline int ceph_alloc_sparse_ext_map(struct ceph_osd_req_op *op)
+static inline int ceph_alloc_sparse_ext_map(struct ceph_osd_req_op *op, int cnt)
 {
-       return __ceph_alloc_sparse_ext_map(op, CEPH_SPARSE_EXT_ARRAY_INITIAL);
+       if (!cnt)
+               cnt = CEPH_SPARSE_EXT_ARRAY_INITIAL;
+
+       return __ceph_alloc_sparse_ext_map(op, cnt);
 }
 
 extern void ceph_osdc_get_request(struct ceph_osd_request *req);