Received: by 2002:a05:6a10:8c0a:0:0:0:0 with SMTP id go10csp4047460pxb; Tue, 26 Jan 2021 10:58:54 -0800 (PST) X-Google-Smtp-Source: ABdhPJxrxhtGIPbFQ6IRkjEk4j9TXO895+SErCZOchL1UQJXdgd3FEaLeZDnmU62gVLNNhTBpw3Q X-Received: by 2002:a17:907:f81:: with SMTP id kb1mr4457130ejc.412.1611687533876; Tue, 26 Jan 2021 10:58:53 -0800 (PST) ARC-Seal: i=1; a=rsa-sha256; t=1611687533; cv=none; d=google.com; s=arc-20160816; b=CMSrQ3VKSn+A+oGN3cSGRHUGKNRVEZz482k2qhmkhbYbyL+zVBhYBx5eoExjjF2iFQ ewc3J3QkZ6WQZMwmSRJkoPOGqTLGraGEfnIfYyRWyQ0zF29E/omqa3gvpGMrH9MtDasH V3E9M4ybPcaEZjT1Nw7UGP2wo2zBdY1QKwmIlVIELhTD25j9ZdSqf1MvPUXWMSZyvY9U GlJAg4HbTsFuCLWztduJPR6Pmr0Xbgyiz3GLF+jsrQsQJ0gWqOjTR50ddJZvw77dufwX qwrm5uxK2NGl/nxwGh8+c6XzM1Y0MqM7oVZ+jRNSe3f0osJtpmRbw+gaiVW9CvPzAK59 d61A== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:content-transfer-encoding:mime-version :references:in-reply-to:message-id:date:subject:cc:to:from :dkim-signature; bh=BTLox4UUa3g8nvZKsniUAQdAXAqZ4BS/Jd39rSjhx4w=; b=zzvXh9u+TEo5foY0cvWi7wf34IdkcPnbcnfxaA9uzmih2eWV50nl3It+LifaWmj2S2 5oYgDgySf9f4FxmU4NN/3oTGarcnC4EbLfIlGYDSjPinkUhVL2Kujl7Y6Qe9LFjqWJyn NTT03wZbo45bPh36OUPp81Psjt9kUPcM5dMmAYnTgz+MN4FTrVpyT/2TB1jG4vJ42y6n D5HlK5jiY3TaaIqu7JSre23QoQdgnxfyUozSux4Pzncan/nys8944o90VT/wzhH4oHy+ kMjtaooIDLJ399qPuVd9PHhTiCEOiUK/gVdP3t+EiQ29PoZaNs8rkVQCisBTeEdbBRy8 Ceog== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@kernel.org header.s=k20201202 header.b=EKOfGw4Z; spf=pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 23.128.96.18 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=kernel.org Return-Path: Received: from vger.kernel.org (vger.kernel.org. [23.128.96.18]) by mx.google.com with ESMTP id cb22si8889584edb.112.2021.01.26.10.58.28; Tue, 26 Jan 2021 10:58:53 -0800 (PST) Received-SPF: pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 23.128.96.18 as permitted sender) client-ip=23.128.96.18; Authentication-Results: mx.google.com; dkim=pass header.i=@kernel.org header.s=k20201202 header.b=EKOfGw4Z; spf=pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 23.128.96.18 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=kernel.org Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S2404832AbhAZNmj (ORCPT + 99 others); Tue, 26 Jan 2021 08:42:39 -0500 Received: from mail.kernel.org ([198.145.29.99]:45870 "EHLO mail.kernel.org" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S2392686AbhAZNm3 (ORCPT ); Tue, 26 Jan 2021 08:42:29 -0500 Received: by mail.kernel.org (Postfix) with ESMTPSA id 3986322D04; Tue, 26 Jan 2021 13:41:10 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1611668470; bh=2ZxNXeRc9CNTm7NvuUA/v27FySFCbp/G99XhUzscrbs=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=EKOfGw4Zg7gjnWR8ysgoP+kq7grKvSLYg16fXbyZRVNHB0WM9IZTOKA18KuTnlmVX HkpmC8JD/FeW6DldnzS1w27hxiq5rhzgnicd1F7ZmwG8Aie4lPdAuplMIw0tRTXJKR ta0zYFFGH8kS8c/CZ+7a0y6EBs5D4R/wuYaQd2qbBfMncooUruq8aWdUocdcCGUgfm 114U3/j9bQpEsnfENUfNRHFBHVmRD2/fw/t2hKktxJ2/bvTb/Q6z253H5cUJDInAMf 41KjwhfJhW+XA1x2utJDu5rQlnNtP2XXDBbje/u4telVtbdxVmRWyjSIogbno/es1S KX5TkMfFDWkMQ== From: Jeff Layton To: ceph-devel@vger.kernel.org, idryomov@gmail.com, dhowells@redhat.com Cc: willy@infradead.org, linux-fsdevel@vger.kernel.org, linux-kernel@vger.kernel.org, linux-cachefs@redhat.com Subject: [PATCH 6/6] ceph: convert ceph_readpages to ceph_readahead Date: Tue, 26 Jan 2021 08:41:03 -0500 Message-Id: <20210126134103.240031-7-jlayton@kernel.org> X-Mailer: git-send-email 2.29.2 In-Reply-To: <20210126134103.240031-1-jlayton@kernel.org> References: <20210126134103.240031-1-jlayton@kernel.org> MIME-Version: 1.0 Content-Transfer-Encoding: 8bit Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org Convert ceph_readpages to ceph_readahead and make it use netfs_readahead. With this we can rip out a lot of the old readpage/readpages infrastructure. Signed-off-by: Jeff Layton --- fs/ceph/addr.c | 229 ++++++++----------------------------------------- 1 file changed, 34 insertions(+), 195 deletions(-) diff --git a/fs/ceph/addr.c b/fs/ceph/addr.c index 7f33418c5c6b..5eec6f66fe52 100644 --- a/fs/ceph/addr.c +++ b/fs/ceph/addr.c @@ -322,214 +322,53 @@ static int ceph_readpage(struct file *file, struct page *page) return netfs_readpage(file, page, &ceph_readpage_netfs_ops, NULL); } -/* - * Finish an async read(ahead) op. - */ -static void finish_read(struct ceph_osd_request *req) +static void ceph_readahead_cleanup(struct address_space *mapping, void *priv) { - struct inode *inode = req->r_inode; - struct ceph_fs_client *fsc = ceph_inode_to_client(inode); - struct ceph_osd_data *osd_data; - int rc = req->r_result <= 0 ? req->r_result : 0; - int bytes = req->r_result >= 0 ? req->r_result : 0; - int num_pages; - int i; - - dout("finish_read %p req %p rc %d bytes %d\n", inode, req, rc, bytes); - if (rc == -EBLOCKLISTED) - ceph_inode_to_client(inode)->blocklisted = true; - - /* unlock all pages, zeroing any data we didn't read */ - osd_data = osd_req_op_extent_osd_data(req, 0); - BUG_ON(osd_data->type != CEPH_OSD_DATA_TYPE_PAGES); - num_pages = calc_pages_for((u64)osd_data->alignment, - (u64)osd_data->length); - for (i = 0; i < num_pages; i++) { - struct page *page = osd_data->pages[i]; - - if (rc < 0 && rc != -ENOENT) - goto unlock; - if (bytes < (int)PAGE_SIZE) { - /* zero (remainder of) page */ - int s = bytes < 0 ? 0 : bytes; - zero_user_segment(page, s, PAGE_SIZE); - } - dout("finish_read %p uptodate %p idx %lu\n", inode, page, - page->index); - flush_dcache_page(page); - SetPageUptodate(page); -unlock: - unlock_page(page); - put_page(page); - bytes -= PAGE_SIZE; - } - - ceph_update_read_latency(&fsc->mdsc->metric, req->r_start_latency, - req->r_end_latency, rc); - - kfree(osd_data->pages); -} - -/* - * start an async read(ahead) operation. return nr_pages we submitted - * a read for on success, or negative error code. - */ -static int start_read(struct inode *inode, struct ceph_rw_context *rw_ctx, - struct list_head *page_list, int max) -{ - struct ceph_osd_client *osdc = - &ceph_inode_to_client(inode)->client->osdc; + struct inode *inode = mapping->host; struct ceph_inode_info *ci = ceph_inode(inode); - struct page *page = lru_to_page(page_list); - struct ceph_vino vino; - struct ceph_osd_request *req; - u64 off; - u64 len; - int i; - struct page **pages; - pgoff_t next_index; - int nr_pages = 0; - int got = 0; - int ret = 0; - - if (!rw_ctx) { - /* caller of readpages does not hold buffer and read caps - * (fadvise, madvise and readahead cases) */ - int want = CEPH_CAP_FILE_CACHE; - ret = ceph_try_get_caps(inode, CEPH_CAP_FILE_RD, want, - true, &got); - if (ret < 0) { - dout("start_read %p, error getting cap\n", inode); - } else if (!(got & want)) { - dout("start_read %p, no cache cap\n", inode); - ret = 0; - } - if (ret <= 0) { - if (got) - ceph_put_cap_refs(ci, got); - while (!list_empty(page_list)) { - page = lru_to_page(page_list); - list_del(&page->lru); - put_page(page); - } - return ret; - } - } - - off = (u64) page_offset(page); - - /* count pages */ - next_index = page->index; - list_for_each_entry_reverse(page, page_list, lru) { - if (page->index != next_index) - break; - nr_pages++; - next_index++; - if (max && nr_pages == max) - break; - } - len = nr_pages << PAGE_SHIFT; - dout("start_read %p nr_pages %d is %lld~%lld\n", inode, nr_pages, - off, len); - vino = ceph_vino(inode); - req = ceph_osdc_new_request(osdc, &ci->i_layout, vino, off, &len, - 0, 1, CEPH_OSD_OP_READ, - CEPH_OSD_FLAG_READ, NULL, - ci->i_truncate_seq, ci->i_truncate_size, - false); - if (IS_ERR(req)) { - ret = PTR_ERR(req); - goto out; - } - - /* build page vector */ - nr_pages = calc_pages_for(0, len); - pages = kmalloc_array(nr_pages, sizeof(*pages), GFP_KERNEL); - if (!pages) { - ret = -ENOMEM; - goto out_put; - } - for (i = 0; i < nr_pages; ++i) { - page = list_entry(page_list->prev, struct page, lru); - BUG_ON(PageLocked(page)); - list_del(&page->lru); - - dout("start_read %p adding %p idx %lu\n", inode, page, - page->index); - if (add_to_page_cache_lru(page, &inode->i_data, page->index, - GFP_KERNEL)) { - put_page(page); - dout("start_read %p add_to_page_cache failed %p\n", - inode, page); - nr_pages = i; - if (nr_pages > 0) { - len = nr_pages << PAGE_SHIFT; - osd_req_op_extent_update(req, 0, len); - break; - } - goto out_pages; - } - pages[i] = page; - } - osd_req_op_extent_osd_data_pages(req, 0, pages, len, 0, false, false); - req->r_callback = finish_read; - req->r_inode = inode; - - dout("start_read %p starting %p %lld~%lld\n", inode, req, off, len); - ret = ceph_osdc_start_request(osdc, req, false); - if (ret < 0) - goto out_pages; - ceph_osdc_put_request(req); + int got = (int)(uintptr_t)priv; - /* After adding locked pages to page cache, the inode holds cache cap. - * So we can drop our cap refs. */ if (got) ceph_put_cap_refs(ci, got); - - return nr_pages; - -out_pages: - for (i = 0; i < nr_pages; ++i) - unlock_page(pages[i]); - ceph_put_page_vector(pages, nr_pages, false); -out_put: - ceph_osdc_put_request(req); -out: - if (got) - ceph_put_cap_refs(ci, got); - return ret; } +const struct netfs_read_request_ops ceph_readahead_netfs_ops = { + .init_rreq = ceph_init_rreq, + .is_cache_enabled = ceph_is_cache_enabled, + .begin_cache_operation = ceph_begin_cache_operation, + .issue_op = ceph_netfs_issue_op, + .clamp_length = ceph_netfs_clamp_length, + .cleanup = ceph_readahead_cleanup, +}; - -/* - * Read multiple pages. Leave pages we don't read + unlock in page_list; - * the caller (VM) cleans them up. - */ -static int ceph_readpages(struct file *file, struct address_space *mapping, - struct list_head *page_list, unsigned nr_pages) +static void ceph_readahead(struct readahead_control *ractl) { - struct inode *inode = file_inode(file); - struct ceph_fs_client *fsc = ceph_inode_to_client(inode); - struct ceph_file_info *fi = file->private_data; + struct inode *inode = file_inode(ractl->file); + struct ceph_file_info *fi = ractl->file->private_data; struct ceph_rw_context *rw_ctx; - int rc = 0; - int max = 0; + int got = 0; + int ret = 0; if (ceph_inode(inode)->i_inline_version != CEPH_INLINE_NONE) - return -EINVAL; + return; rw_ctx = ceph_find_rw_context(fi); - max = fsc->mount_options->rsize >> PAGE_SHIFT; - dout("readpages %p file %p ctx %p nr_pages %d max %d\n", - inode, file, rw_ctx, nr_pages, max); - while (!list_empty(page_list)) { - rc = start_read(inode, rw_ctx, page_list, max); - if (rc < 0) - goto out; + if (!rw_ctx) { + /* + * readahead callers do not necessarily hold Fcb caps + * (e.g. fadvise, madvise). + */ + int want = CEPH_CAP_FILE_CACHE; + + ret = ceph_try_get_caps(inode, CEPH_CAP_FILE_RD, want, true, &got); + if (ret < 0) + dout("start_read %p, error getting cap\n", inode); + else if (!(got & want)) + dout("start_read %p, no cache cap\n", inode); + + if (ret <= 0) + return; } -out: - dout("readpages %p file %p ret %d\n", inode, file, rc); - return rc; + netfs_readahead(ractl, &ceph_readahead_netfs_ops, (void *)(uintptr_t)got); } struct ceph_writeback_ctl @@ -1482,7 +1321,7 @@ static ssize_t ceph_direct_io(struct kiocb *iocb, struct iov_iter *iter) const struct address_space_operations ceph_aops = { .readpage = ceph_readpage, - .readpages = ceph_readpages, + .readahead = ceph_readahead, .writepage = ceph_writepage, .writepages = ceph_writepages_start, .write_begin = ceph_write_begin, -- 2.29.2