From: Eric Biggers <ebiggers@kernel.org>
To: Chao Yu <yuchao0@huawei.com>
Cc: linux-f2fs-devel@lists.sourceforge.net, linux-fscrypt@vger.kernel.org
Subject: Re: [f2fs-dev] [PATCH v2] f2fs: clean up post-read processing
Date: Mon, 4 Jan 2021 10:33:22 -0800 [thread overview]
Message-ID: <X/NfcslNOlB2mNHO@sol.localdomain> (raw)
In-Reply-To: <0f488de1-ec9d-b1f1-641c-d624fecbb12d@huawei.com>
On Mon, Jan 04, 2021 at 04:43:56PM +0800, Chao Yu wrote:
> Hi Eric,
>
> On 2021/1/4 11:45, Eric Biggers wrote:
> > That's already handled; I made it so that STEP_DECOMPRESS is only enabled when
> > it's actually needed.
>
> Yup, now I see.
>
> Some comments as below.
>
> On 2020/12/29 7:26, Eric Biggers wrote:
> > From: Eric Biggers <ebiggers@google.com>
> >
> > Rework the post-read processing logic to be much easier to understand.
> >
> > At least one bug is fixed by this: if an I/O error occurred when reading
> > from disk, decryption and verity would be performed on the uninitialized
> > data, causing misleading messages in the kernel log.
> >
> > Signed-off-by: Eric Biggers <ebiggers@google.com>
> > ---
Please only quote the parts you're actually replying to.
> > +static void f2fs_post_read_work(struct work_struct *work)
> > {
> > - queue_work(sbi->post_read_wq, work);
> > -}
> > + struct bio_post_read_ctx *ctx =
> > + container_of(work, struct bio_post_read_ctx, work);
> > + struct bio *bio = ctx->bio;
> > -static void bio_post_read_processing(struct bio_post_read_ctx *ctx)
> > -{
> > - /*
> > - * We use different work queues for decryption and for verity because
> > - * verity may require reading metadata pages that need decryption, and
> > - * we shouldn't recurse to the same workqueue.
> > - */
> > + if (ctx->enabled_steps & STEP_DECRYPT)
> > + fscrypt_decrypt_bio(bio);
> > - if (ctx->enabled_steps & (1 << STEP_DECRYPT) ||
> > - ctx->enabled_steps & (1 << STEP_DECOMPRESS)) {
> > - INIT_WORK(&ctx->work, f2fs_post_read_work);
> > - f2fs_enqueue_post_read_work(ctx->sbi, &ctx->work);
> > - return;
> > - }
> > + if (ctx->enabled_steps & STEP_DECOMPRESS) {
> > + struct bio_vec *bv;
> > + struct bvec_iter_all iter_all;
> > + bool all_compressed = true;
> > - if (ctx->enabled_steps & (1 << STEP_VERITY)) {
> > - INIT_WORK(&ctx->work, f2fs_verity_work);
> > - fsverity_enqueue_verify_work(&ctx->work);
> > - return;
> > - }
> > + bio_for_each_segment_all(bv, bio, iter_all) {
> > + struct page *page = bv->bv_page;
> > + /* PG_error will be set if decryption failed. */
> > + bool failed = PageError(page);
> > - __f2fs_read_end_io(ctx->bio, false, false);
> > -}
> > + if (f2fs_is_compressed_page(page))
> > + f2fs_end_read_compressed_page(page, failed);
> > + else
> > + all_compressed = false;
> > + }
> > + /*
> > + * Optimization: if all the bio's pages are compressed, then
> > + * scheduling the per-bio verity work is unnecessary, as verity
> > + * will be fully handled at the compression cluster level.
> > + */
> > + if (all_compressed)
> > + ctx->enabled_steps &= ~STEP_VERITY;
> > + }
>
> Can we wrap above logic into a function for cleanup?
Are you saying you want the STEP_DECOMPRESS handling in a new function, e.g.
f2fs_handle_step_decompress()? I could do that, though this new function would
only be called from f2fs_post_read_work(), which isn't too long. So I'm not
sure it would be better.
> > +/* Context for decompressing one cluster on the read IO path */
> > struct decompress_io_ctx {
> > u32 magic; /* magic number to indicate page is compressed */
> > struct inode *inode; /* inode the context belong to */
> > @@ -1353,11 +1353,13 @@ struct decompress_io_ctx {
> > struct compress_data *cbuf; /* virtual mapped address on cpages */
> > size_t rlen; /* valid data length in rbuf */
> > size_t clen; /* valid data length in cbuf */
> > - atomic_t pending_pages; /* in-flight compressed page count */
> > - atomic_t verity_pages; /* in-flight page count for verity */
> > - bool failed; /* indicate IO error during decompression */
> > + atomic_t remaining_pages; /* number of compressed pages remaining to be read */
> > + refcount_t refcnt; /* 1 for decompression and 1 for each page still in a bio */
>
> Now, we use .remaining_pages to control to trigger cluster decompression;
> and .refcnt to control to release dic structure.
>
> How about adding a bit more description about above info for better
> readability?
Would you like longer comments even though every other field in this struct has
a 1-line comment?
> > -void f2fs_free_dic(struct decompress_io_ctx *dic);
> > -void f2fs_decompress_end_io(struct page **rpages,
> > - unsigned int cluster_size, bool err, bool verity);
> > +void f2fs_decompress_end_io(struct decompress_io_ctx *dic, bool failed);
> > +void f2fs_put_page_decompress_io_ctx(struct page *page);
> > int f2fs_init_compress_ctx(struct compress_ctx *cc);
> > void f2fs_destroy_compress_ctx(struct compress_ctx *cc);
> > void f2fs_init_compress_info(struct f2fs_sb_info *sbi);
> > @@ -3915,6 +3916,14 @@ static inline struct page *f2fs_compress_control_page(struct page *page)
> > }
> > static inline int f2fs_init_compress_mempool(void) { return 0; }
> > static inline void f2fs_destroy_compress_mempool(void) { }
> > +static inline void f2fs_end_read_compressed_page(struct page *page, bool failed)
> > +{
> > + WARN_ON_ONCE(1);
> > +}
> > +static inline void f2fs_put_page_decompress_io_ctx(struct page *page)
>
> f2fs_put_page_in_dic() or f2fs_put_dic_page()?
It's putting the decompression context of the page, not the page itself. So I
feel the name I've proposed makes more sense.
> > diff --git a/include/trace/events/f2fs.h b/include/trace/events/f2fs.h
> > index 56b113e3cd6aa..9e2981733ea4a 100644
> > --- a/include/trace/events/f2fs.h
> > +++ b/include/trace/events/f2fs.h
> > @@ -1794,7 +1794,7 @@ DEFINE_EVENT(f2fs_zip_start, f2fs_compress_pages_start,
> > TP_ARGS(inode, cluster_idx, cluster_size, algtype)
> > );
> > -DEFINE_EVENT(f2fs_zip_start, f2fs_decompress_pages_start,
> > +DEFINE_EVENT(f2fs_zip_start, f2fs_decompress_cluster_start,
>
> I suggest keeping original tracepoint name, it can avoid breaking userspace
> binary or script.
>
Tracepoints aren't a stable UAPI, and the new name is more logical because it
describes what is being decompressed rather than an implementation detail of
where the data is located (in pages).
- Eric
next prev parent reply other threads:[~2021-01-04 18:34 UTC|newest]
Thread overview: 6+ messages / expand[flat|nested] mbox.gz Atom feed top
2020-12-28 23:26 [PATCH v2] f2fs: clean up post-read processing Eric Biggers
2021-01-04 3:35 ` [f2fs-dev] " Chao Yu
2021-01-04 3:45 ` Eric Biggers
2021-01-04 8:43 ` Chao Yu
2021-01-04 18:33 ` Eric Biggers [this message]
2021-01-05 1:26 ` Chao Yu
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=X/NfcslNOlB2mNHO@sol.localdomain \
--to=ebiggers@kernel.org \
--cc=linux-f2fs-devel@lists.sourceforge.net \
--cc=linux-fscrypt@vger.kernel.org \
--cc=yuchao0@huawei.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox