From nobody Sat Apr 11 12:08:49 2026 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id 26A15C4332F for ; Tue, 8 Nov 2022 02:57:20 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S233216AbiKHC5R (ORCPT ); Mon, 7 Nov 2022 21:57:17 -0500 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:36352 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S233140AbiKHC5L (ORCPT ); Mon, 7 Nov 2022 21:57:11 -0500 Received: from out30-43.freemail.mail.aliyun.com (out30-43.freemail.mail.aliyun.com [115.124.30.43]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 2FFB72EF79; Mon, 7 Nov 2022 18:57:10 -0800 (PST) X-Alimail-AntiSpam: AC=PASS;BC=-1|-1;BR=01201311R191e4;CH=green;DM=||false|;DS=||;FP=0|-1|-1|-1|0|-1|-1|-1;HT=ay29a033018046056;MF=jefflexu@linux.alibaba.com;NM=1;PH=DS;RN=8;SR=0;TI=SMTPD_---0VUHLUPE_1667876226; Received: from localhost(mailfrom:jefflexu@linux.alibaba.com fp:SMTPD_---0VUHLUPE_1667876226) by smtp.aliyun-inc.com; Tue, 08 Nov 2022 10:57:08 +0800 From: Jingbo Xu To: dhowells@redhat.com, jlayton@kernel.org, xiang@kernel.org, chao@kernel.org, linux-cachefs@redhat.com, linux-erofs@lists.ozlabs.org Cc: linux-kernel@vger.kernel.org, linux-fsdevel@vger.kernel.org Subject: [PATCH v2 1/2] fscache,cachefiles: add prepare_ondemand_read() callback Date: Tue, 8 Nov 2022 10:57:04 +0800 Message-Id: <20221108025705.14816-2-jefflexu@linux.alibaba.com> X-Mailer: git-send-email 2.19.1.6.gb485710b In-Reply-To: <20221108025705.14816-1-jefflexu@linux.alibaba.com> References: <20221108025705.14816-1-jefflexu@linux.alibaba.com> MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org Content-Type: text/plain; charset="utf-8" Add prepare_ondemand_read() callback dedicated for the on-demand read scenario, so that callers from this scenario can be decoupled from netfs_io_subrequest. The original cachefiles_prepare_read() is now refactored to a generic routine accepting a parameter list instead of netfs_io_subrequest. There's no logic change, except that some debug info retrieved from netfs_io_subrequest is removed from trace_cachefiles_prep_read(). Signed-off-by: Jingbo Xu --- fs/cachefiles/io.c | 75 ++++++++++++++++++++----------- include/linux/netfs.h | 7 +++ include/trace/events/cachefiles.h | 27 ++++++----- 3 files changed, 68 insertions(+), 41 deletions(-) diff --git a/fs/cachefiles/io.c b/fs/cachefiles/io.c index 000a28f46e59..3eeafef21c4e 100644 --- a/fs/cachefiles/io.c +++ b/fs/cachefiles/io.c @@ -385,38 +385,35 @@ static int cachefiles_write(struct netfs_cache_resour= ces *cres, term_func, term_func_priv); } =20 -/* - * Prepare a read operation, shortening it to a cached/uncached - * boundary as appropriate. - */ -static enum netfs_io_source cachefiles_prepare_read(struct netfs_io_subreq= uest *subreq, - loff_t i_size) +static enum netfs_io_source cachefiles_do_prepare_read(struct netfs_cache_= resources *cres, + loff_t *_start, size_t *_len, + unsigned long *_flags, loff_t i_size) { enum cachefiles_prepare_read_trace why; - struct netfs_io_request *rreq =3D subreq->rreq; - struct netfs_cache_resources *cres =3D &rreq->cache_resources; - struct cachefiles_object *object; + struct cachefiles_object *object =3D NULL; struct cachefiles_cache *cache; struct fscache_cookie *cookie =3D fscache_cres_cookie(cres); const struct cred *saved_cred; struct file *file =3D cachefiles_cres_file(cres); enum netfs_io_source ret =3D NETFS_DOWNLOAD_FROM_SERVER; + loff_t start =3D *_start; + size_t len =3D *_len; loff_t off, to; ino_t ino =3D file ? file_inode(file)->i_ino : 0; int rc; =20 - _enter("%zx @%llx/%llx", subreq->len, subreq->start, i_size); + _enter("%zx @%llx/%llx", len, start, i_size); =20 - if (subreq->start >=3D i_size) { + if (start >=3D i_size) { ret =3D NETFS_FILL_WITH_ZEROES; why =3D cachefiles_trace_read_after_eof; goto out_no_object; } =20 if (test_bit(FSCACHE_COOKIE_NO_DATA_TO_READ, &cookie->flags)) { - __set_bit(NETFS_SREQ_COPY_TO_CACHE, &subreq->flags); + __set_bit(NETFS_SREQ_COPY_TO_CACHE, _flags); why =3D cachefiles_trace_read_no_data; - if (!test_bit(NETFS_SREQ_ONDEMAND, &subreq->flags)) + if (!test_bit(NETFS_SREQ_ONDEMAND, _flags)) goto out_no_object; } =20 @@ -437,7 +434,7 @@ static enum netfs_io_source cachefiles_prepare_read(str= uct netfs_io_subrequest * retry: off =3D cachefiles_inject_read_error(); if (off =3D=3D 0) - off =3D vfs_llseek(file, subreq->start, SEEK_DATA); + off =3D vfs_llseek(file, start, SEEK_DATA); if (off < 0 && off >=3D (loff_t)-MAX_ERRNO) { if (off =3D=3D (loff_t)-ENXIO) { why =3D cachefiles_trace_read_seek_nxio; @@ -449,21 +446,22 @@ static enum netfs_io_source cachefiles_prepare_read(s= truct netfs_io_subrequest * goto out; } =20 - if (off >=3D subreq->start + subreq->len) { + if (off >=3D start + len) { why =3D cachefiles_trace_read_found_hole; goto download_and_store; } =20 - if (off > subreq->start) { + if (off > start) { off =3D round_up(off, cache->bsize); - subreq->len =3D off - subreq->start; + len =3D off - start; + *_len =3D len; why =3D cachefiles_trace_read_found_part; goto download_and_store; } =20 to =3D cachefiles_inject_read_error(); if (to =3D=3D 0) - to =3D vfs_llseek(file, subreq->start, SEEK_HOLE); + to =3D vfs_llseek(file, start, SEEK_HOLE); if (to < 0 && to >=3D (loff_t)-MAX_ERRNO) { trace_cachefiles_io_error(object, file_inode(file), to, cachefiles_trace_seek_error); @@ -471,12 +469,13 @@ static enum netfs_io_source cachefiles_prepare_read(s= truct netfs_io_subrequest * goto out; } =20 - if (to < subreq->start + subreq->len) { - if (subreq->start + subreq->len >=3D i_size) + if (to < start + len) { + if (start + len >=3D i_size) to =3D round_up(to, cache->bsize); else to =3D round_down(to, cache->bsize); - subreq->len =3D to - subreq->start; + len =3D to - start; + *_len =3D len; } =20 why =3D cachefiles_trace_read_have_data; @@ -484,12 +483,11 @@ static enum netfs_io_source cachefiles_prepare_read(s= truct netfs_io_subrequest * goto out; =20 download_and_store: - __set_bit(NETFS_SREQ_COPY_TO_CACHE, &subreq->flags); - if (test_bit(NETFS_SREQ_ONDEMAND, &subreq->flags)) { - rc =3D cachefiles_ondemand_read(object, subreq->start, - subreq->len); + __set_bit(NETFS_SREQ_COPY_TO_CACHE, _flags); + if (test_bit(NETFS_SREQ_ONDEMAND, _flags)) { + rc =3D cachefiles_ondemand_read(object, start, len); if (!rc) { - __clear_bit(NETFS_SREQ_ONDEMAND, &subreq->flags); + __clear_bit(NETFS_SREQ_ONDEMAND, _flags); goto retry; } ret =3D NETFS_INVALID_READ; @@ -497,10 +495,32 @@ static enum netfs_io_source cachefiles_prepare_read(s= truct netfs_io_subrequest * out: cachefiles_end_secure(cache, saved_cred); out_no_object: - trace_cachefiles_prep_read(subreq, ret, why, ino); + trace_cachefiles_prep_read(object, start, len, *_flags, ret, why, ino); return ret; } =20 +/* + * Prepare a read operation, shortening it to a cached/uncached + * boundary as appropriate. + */ +static enum netfs_io_source cachefiles_prepare_read(struct netfs_io_subreq= uest *subreq, + loff_t i_size) +{ + return cachefiles_do_prepare_read(&subreq->rreq->cache_resources, + &subreq->start, &subreq->len, &subreq->flags, i_size); +} + +/* + * Prepare an on-demand read operation, shortening it to a cached/uncached + * boundary as appropriate. + */ +static enum netfs_io_source cachefiles_prepare_ondemand_read(struct netfs_= cache_resources *cres, + loff_t start, size_t *_len, loff_t i_size) +{ + unsigned long flags =3D 1 << NETFS_SREQ_ONDEMAND; + return cachefiles_do_prepare_read(cres, &start, _len, &flags, i_size); +} + /* * Prepare for a write to occur. */ @@ -621,6 +641,7 @@ static const struct netfs_cache_ops cachefiles_netfs_ca= che_ops =3D { .write =3D cachefiles_write, .prepare_read =3D cachefiles_prepare_read, .prepare_write =3D cachefiles_prepare_write, + .prepare_ondemand_read =3D cachefiles_prepare_ondemand_read, .query_occupancy =3D cachefiles_query_occupancy, }; =20 diff --git a/include/linux/netfs.h b/include/linux/netfs.h index f2402ddeafbf..d82071c37133 100644 --- a/include/linux/netfs.h +++ b/include/linux/netfs.h @@ -267,6 +267,13 @@ struct netfs_cache_ops { loff_t *_start, size_t *_len, loff_t i_size, bool no_space_allocated_yet); =20 + /* Prepare an on-demand read operation, shortening it to a cached/uncached + * boundary as appropriate. + */ + enum netfs_io_source (*prepare_ondemand_read)(struct netfs_cache_resource= s *cres, + loff_t start, size_t *_len, + loff_t i_size); + /* Query the occupancy of the cache in a region, returning where the * next chunk of data starts and how long it is. */ diff --git a/include/trace/events/cachefiles.h b/include/trace/events/cache= files.h index d8d4d73fe7b6..171c0d7f0bb7 100644 --- a/include/trace/events/cachefiles.h +++ b/include/trace/events/cachefiles.h @@ -428,44 +428,43 @@ TRACE_EVENT(cachefiles_vol_coherency, ); =20 TRACE_EVENT(cachefiles_prep_read, - TP_PROTO(struct netfs_io_subrequest *sreq, + TP_PROTO(struct cachefiles_object *obj, + loff_t start, + size_t len, + unsigned short flags, enum netfs_io_source source, enum cachefiles_prepare_read_trace why, ino_t cache_inode), =20 - TP_ARGS(sreq, source, why, cache_inode), + TP_ARGS(obj, start, len, flags, source, why, cache_inode), =20 TP_STRUCT__entry( - __field(unsigned int, rreq ) - __field(unsigned short, index ) + __field(unsigned int, obj ) __field(unsigned short, flags ) __field(enum netfs_io_source, source ) __field(enum cachefiles_prepare_read_trace, why ) __field(size_t, len ) __field(loff_t, start ) - __field(unsigned int, netfs_inode ) __field(unsigned int, cache_inode ) ), =20 TP_fast_assign( - __entry->rreq =3D sreq->rreq->debug_id; - __entry->index =3D sreq->debug_index; - __entry->flags =3D sreq->flags; + __entry->obj =3D obj ? obj->debug_id : 0; + __entry->flags =3D flags; __entry->source =3D source; __entry->why =3D why; - __entry->len =3D sreq->len; - __entry->start =3D sreq->start; - __entry->netfs_inode =3D sreq->rreq->inode->i_ino; + __entry->len =3D len; + __entry->start =3D start; __entry->cache_inode =3D cache_inode; ), =20 - TP_printk("R=3D%08x[%u] %s %s f=3D%02x s=3D%llx %zx ni=3D%x B=3D%x", - __entry->rreq, __entry->index, + TP_printk("o=3D%08x %s %s f=3D%02x s=3D%llx %zx B=3D%x", + __entry->obj, __print_symbolic(__entry->source, netfs_sreq_sources), __print_symbolic(__entry->why, cachefiles_prepare_read_traces), __entry->flags, __entry->start, __entry->len, - __entry->netfs_inode, __entry->cache_inode) + __entry->cache_inode) ); =20 TRACE_EVENT(cachefiles_read, --=20 2.19.1.6.gb485710b From nobody Sat Apr 11 12:08:49 2026 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id AB11FC433FE for ; Tue, 8 Nov 2022 02:57:29 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S232075AbiKHC52 (ORCPT ); Mon, 7 Nov 2022 21:57:28 -0500 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:36394 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S233202AbiKHC5N (ORCPT ); Mon, 7 Nov 2022 21:57:13 -0500 Received: from out30-45.freemail.mail.aliyun.com (out30-45.freemail.mail.aliyun.com [115.124.30.45]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id AD7E82E6AC; Mon, 7 Nov 2022 18:57:11 -0800 (PST) X-Alimail-AntiSpam: AC=PASS;BC=-1|-1;BR=01201311R551e4;CH=green;DM=||false|;DS=||;FP=0|-1|-1|-1|0|-1|-1|-1;HT=ay29a033018046050;MF=jefflexu@linux.alibaba.com;NM=1;PH=DS;RN=8;SR=0;TI=SMTPD_---0VUHOUMA_1667876228; Received: from localhost(mailfrom:jefflexu@linux.alibaba.com fp:SMTPD_---0VUHOUMA_1667876228) by smtp.aliyun-inc.com; Tue, 08 Nov 2022 10:57:09 +0800 From: Jingbo Xu To: dhowells@redhat.com, jlayton@kernel.org, xiang@kernel.org, chao@kernel.org, linux-cachefs@redhat.com, linux-erofs@lists.ozlabs.org Cc: linux-kernel@vger.kernel.org, linux-fsdevel@vger.kernel.org Subject: [PATCH v2 2/2] erofs: switch to prepare_ondemand_read() in fscache mode Date: Tue, 8 Nov 2022 10:57:05 +0800 Message-Id: <20221108025705.14816-3-jefflexu@linux.alibaba.com> X-Mailer: git-send-email 2.19.1.6.gb485710b In-Reply-To: <20221108025705.14816-1-jefflexu@linux.alibaba.com> References: <20221108025705.14816-1-jefflexu@linux.alibaba.com> MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org Content-Type: text/plain; charset="utf-8" Switch to prepare_ondemand_read() interface and a self-contained request completion to get rid of netfs_io_[request|subrequest]. The whole request will still be split into slices (subrequest) according to the cache state of the backing file. As long as one of the subrequests fails, the whole request will be marked as failed. Besides, add the missing xas_retry() checking when iterating xarray under RCU lock. Signed-off-by: Jingbo Xu --- fs/erofs/fscache.c | 259 ++++++++++++++++----------------------------- 1 file changed, 94 insertions(+), 165 deletions(-) diff --git a/fs/erofs/fscache.c b/fs/erofs/fscache.c index 260fa4737fc0..2d31894c3249 100644 --- a/fs/erofs/fscache.c +++ b/fs/erofs/fscache.c @@ -11,253 +11,178 @@ static DEFINE_MUTEX(erofs_domain_cookies_lock); static LIST_HEAD(erofs_domain_list); static struct vfsmount *erofs_pseudo_mnt; =20 -static struct netfs_io_request *erofs_fscache_alloc_request(struct address= _space *mapping, +struct erofs_fscache_request { + struct netfs_cache_resources cache_resources; + struct address_space *mapping; /* The mapping being accessed */ + loff_t start; /* Start position */ + size_t len; /* Length of the request */ + size_t submitted; /* Length of submitted */ + short error; /* 0 or error that occurred */ + refcount_t ref; +}; + +static struct erofs_fscache_request *erofs_fscache_req_alloc(struct addres= s_space *mapping, loff_t start, size_t len) { - struct netfs_io_request *rreq; + struct erofs_fscache_request *req; =20 - rreq =3D kzalloc(sizeof(struct netfs_io_request), GFP_KERNEL); - if (!rreq) + req =3D kzalloc(sizeof(struct erofs_fscache_request), GFP_KERNEL); + if (!req) return ERR_PTR(-ENOMEM); =20 - rreq->start =3D start; - rreq->len =3D len; - rreq->mapping =3D mapping; - rreq->inode =3D mapping->host; - INIT_LIST_HEAD(&rreq->subrequests); - refcount_set(&rreq->ref, 1); - return rreq; -} - -static void erofs_fscache_put_request(struct netfs_io_request *rreq) -{ - if (!refcount_dec_and_test(&rreq->ref)) - return; - if (rreq->cache_resources.ops) - rreq->cache_resources.ops->end_operation(&rreq->cache_resources); - kfree(rreq); -} - -static void erofs_fscache_put_subrequest(struct netfs_io_subrequest *subre= q) -{ - if (!refcount_dec_and_test(&subreq->ref)) - return; - erofs_fscache_put_request(subreq->rreq); - kfree(subreq); -} - -static void erofs_fscache_clear_subrequests(struct netfs_io_request *rreq) -{ - struct netfs_io_subrequest *subreq; + req->mapping =3D mapping; + req->start =3D start; + req->len =3D len; + refcount_set(&req->ref, 1); =20 - while (!list_empty(&rreq->subrequests)) { - subreq =3D list_first_entry(&rreq->subrequests, - struct netfs_io_subrequest, rreq_link); - list_del(&subreq->rreq_link); - erofs_fscache_put_subrequest(subreq); - } + return req; } =20 -static void erofs_fscache_rreq_unlock_folios(struct netfs_io_request *rreq) +static void erofs_fscache_req_complete(struct erofs_fscache_request *req) { - struct netfs_io_subrequest *subreq; struct folio *folio; - unsigned int iopos =3D 0; - pgoff_t start_page =3D rreq->start / PAGE_SIZE; - pgoff_t last_page =3D ((rreq->start + rreq->len) / PAGE_SIZE) - 1; - bool subreq_failed =3D false; - - XA_STATE(xas, &rreq->mapping->i_pages, start_page); + bool failed =3D req->error; + pgoff_t start_page =3D req->start / PAGE_SIZE; + pgoff_t last_page =3D ((req->start + req->len) / PAGE_SIZE) - 1; =20 - subreq =3D list_first_entry(&rreq->subrequests, - struct netfs_io_subrequest, rreq_link); - subreq_failed =3D (subreq->error < 0); + XA_STATE(xas, &req->mapping->i_pages, start_page); =20 rcu_read_lock(); xas_for_each(&xas, folio, last_page) { - unsigned int pgpos =3D - (folio_index(folio) - start_page) * PAGE_SIZE; - unsigned int pgend =3D pgpos + folio_size(folio); - bool pg_failed =3D false; - - for (;;) { - if (!subreq) { - pg_failed =3D true; - break; - } - - pg_failed |=3D subreq_failed; - if (pgend < iopos + subreq->len) - break; - - iopos +=3D subreq->len; - if (!list_is_last(&subreq->rreq_link, - &rreq->subrequests)) { - subreq =3D list_next_entry(subreq, rreq_link); - subreq_failed =3D (subreq->error < 0); - } else { - subreq =3D NULL; - subreq_failed =3D false; - } - if (pgend =3D=3D iopos) - break; - } - - if (!pg_failed) + if (xas_retry(&xas, folio)) + continue; + if (!failed) folio_mark_uptodate(folio); - folio_unlock(folio); } rcu_read_unlock(); + + if (req->cache_resources.ops) + req->cache_resources.ops->end_operation(&req->cache_resources); + + kfree(req); } =20 -static void erofs_fscache_rreq_complete(struct netfs_io_request *rreq) +static void erofs_fscache_req_put(struct erofs_fscache_request *req) { - erofs_fscache_rreq_unlock_folios(rreq); - erofs_fscache_clear_subrequests(rreq); - erofs_fscache_put_request(rreq); + if (refcount_dec_and_test(&req->ref)) + erofs_fscache_req_complete(req); } =20 -static void erofc_fscache_subreq_complete(void *priv, +static void erofs_fscache_subreq_complete(void *priv, ssize_t transferred_or_error, bool was_async) { - struct netfs_io_subrequest *subreq =3D priv; - struct netfs_io_request *rreq =3D subreq->rreq; + struct erofs_fscache_request *req =3D priv; =20 if (IS_ERR_VALUE(transferred_or_error)) - subreq->error =3D transferred_or_error; - - if (atomic_dec_and_test(&rreq->nr_outstanding)) - erofs_fscache_rreq_complete(rreq); - - erofs_fscache_put_subrequest(subreq); + req->error =3D transferred_or_error; + erofs_fscache_req_put(req); } =20 /* - * Read data from fscache and fill the read data into page cache described= by - * @rreq, which shall be both aligned with PAGE_SIZE. @pstart describes - * the start physical address in the cache file. + * Read data from fscache (cookie, pstart, len), and fill the read data in= to + * page cache described by (req->mapping, lstart, len). @pstart describeis= the + * start physical address in the cache file. */ static int erofs_fscache_read_folios_async(struct fscache_cookie *cookie, - struct netfs_io_request *rreq, loff_t pstart) + struct erofs_fscache_request *req, loff_t pstart, size_t len) { enum netfs_io_source source; - struct super_block *sb =3D rreq->mapping->host->i_sb; - struct netfs_io_subrequest *subreq; - struct netfs_cache_resources *cres =3D &rreq->cache_resources; + struct super_block *sb =3D req->mapping->host->i_sb; + struct netfs_cache_resources *cres =3D &req->cache_resources; struct iov_iter iter; - loff_t start =3D rreq->start; - size_t len =3D rreq->len; + loff_t lstart =3D req->start + req->submitted; size_t done =3D 0; int ret; =20 - atomic_set(&rreq->nr_outstanding, 1); + DBG_BUGON(len > req->len - req->submitted); =20 ret =3D fscache_begin_read_operation(cres, cookie); if (ret) - goto out; + return ret; =20 while (done < len) { - subreq =3D kzalloc(sizeof(struct netfs_io_subrequest), - GFP_KERNEL); - if (subreq) { - INIT_LIST_HEAD(&subreq->rreq_link); - refcount_set(&subreq->ref, 2); - subreq->rreq =3D rreq; - refcount_inc(&rreq->ref); - } else { - ret =3D -ENOMEM; - goto out; - } - - subreq->start =3D pstart + done; - subreq->len =3D len - done; - subreq->flags =3D 1 << NETFS_SREQ_ONDEMAND; - - list_add_tail(&subreq->rreq_link, &rreq->subrequests); + loff_t sstart =3D pstart + done; + size_t slen =3D len - done; =20 - source =3D cres->ops->prepare_read(subreq, LLONG_MAX); - if (WARN_ON(subreq->len =3D=3D 0)) + source =3D cres->ops->prepare_ondemand_read(cres, sstart, &slen, LLONG_M= AX); + if (WARN_ON(slen =3D=3D 0)) source =3D NETFS_INVALID_READ; if (source !=3D NETFS_READ_FROM_CACHE) { - erofs_err(sb, "failed to fscache prepare_read (source %d)", - source); - ret =3D -EIO; - subreq->error =3D ret; - erofs_fscache_put_subrequest(subreq); - goto out; + erofs_err(sb, "failed to fscache prepare_read (source %d)", source); + return -EIO; } =20 - atomic_inc(&rreq->nr_outstanding); - - iov_iter_xarray(&iter, READ, &rreq->mapping->i_pages, - start + done, subreq->len); + refcount_inc(&req->ref); + iov_iter_xarray(&iter, READ, &req->mapping->i_pages, + lstart + done, slen); =20 - ret =3D fscache_read(cres, subreq->start, &iter, - NETFS_READ_HOLE_FAIL, - erofc_fscache_subreq_complete, subreq); + ret =3D fscache_read(cres, sstart, &iter, NETFS_READ_HOLE_FAIL, + erofs_fscache_subreq_complete, req); if (ret =3D=3D -EIOCBQUEUED) ret =3D 0; if (ret) { erofs_err(sb, "failed to fscache_read (ret %d)", ret); - goto out; + return ret; } =20 - done +=3D subreq->len; + done +=3D slen; } -out: - if (atomic_dec_and_test(&rreq->nr_outstanding)) - erofs_fscache_rreq_complete(rreq); - - return ret; + DBG_BUGON(done !=3D len); + req->submitted +=3D len; + return 0; } =20 static int erofs_fscache_meta_read_folio(struct file *data, struct folio *= folio) { int ret; struct super_block *sb =3D folio_mapping(folio)->host->i_sb; - struct netfs_io_request *rreq; + struct erofs_fscache_request *req; struct erofs_map_dev mdev =3D { .m_deviceid =3D 0, .m_pa =3D folio_pos(folio), }; =20 ret =3D erofs_map_dev(sb, &mdev); - if (ret) - goto out; + if (ret) { + folio_unlock(folio); + return ret; + } =20 - rreq =3D erofs_fscache_alloc_request(folio_mapping(folio), + req =3D erofs_fscache_req_alloc(folio_mapping(folio), folio_pos(folio), folio_size(folio)); - if (IS_ERR(rreq)) { - ret =3D PTR_ERR(rreq); - goto out; + if (IS_ERR(req)) { + folio_unlock(folio); + return PTR_ERR(req); } =20 - return erofs_fscache_read_folios_async(mdev.m_fscache->cookie, - rreq, mdev.m_pa); -out: - folio_unlock(folio); + ret =3D erofs_fscache_read_folios_async(mdev.m_fscache->cookie, + req, mdev.m_pa, folio_size(folio)); + if (ret) + req->error =3D ret; + + erofs_fscache_req_put(req); return ret; } =20 /* * Read into page cache in the range described by (@pos, @len). * - * On return, the caller is responsible for page unlocking if the output @= unlock - * is true, or the callee will take this responsibility through netfs_io_r= equest - * interface. + * On return, if the output @unlock is true, the caller is responsible for= page + * unlocking; otherwise the callee will take this responsibility through r= equest + * completion. * * The return value is the number of bytes successfully handled, or negati= ve * error code on failure. The only exception is that, the length of the ra= nge - * instead of the error code is returned on failure after netfs_io_request= is - * allocated, so that .readahead() could advance rac accordingly. + * instead of the error code is returned on failure after request is alloc= ated, + * so that .readahead() could advance rac accordingly. */ static int erofs_fscache_data_read(struct address_space *mapping, loff_t pos, size_t len, bool *unlock) { struct inode *inode =3D mapping->host; struct super_block *sb =3D inode->i_sb; - struct netfs_io_request *rreq; + struct erofs_fscache_request *req; struct erofs_map_blocks map; struct erofs_map_dev mdev; struct iov_iter iter; @@ -314,13 +239,17 @@ static int erofs_fscache_data_read(struct address_spa= ce *mapping, if (ret) return ret; =20 - rreq =3D erofs_fscache_alloc_request(mapping, pos, count); - if (IS_ERR(rreq)) - return PTR_ERR(rreq); + req =3D erofs_fscache_req_alloc(mapping, pos, count); + if (IS_ERR(req)) + return PTR_ERR(req); =20 *unlock =3D false; - erofs_fscache_read_folios_async(mdev.m_fscache->cookie, - rreq, mdev.m_pa + (pos - map.m_la)); + ret =3D erofs_fscache_read_folios_async(mdev.m_fscache->cookie, + req, mdev.m_pa + (pos - map.m_la), count); + if (ret) + req->error =3D ret; + + erofs_fscache_req_put(req); return count; } =20 --=20 2.19.1.6.gb485710b