Linux RAID subsystem development
 help / color / mirror / Atom feed
From: Su Yue <l@damenly.org>
To: Yu Kuai <yukuai@kernel.org>
Cc: Song Liu <song@kernel.org>,  Yu Kuai <yukuai@fygo.io>,
	 Li Nan <magiclinan@didiglobal.com>,  Xiao Ni <xiao@kernel.org>,
	linux-raid@vger.kernel.org,  linux-kernel@vger.kernel.org
Subject: Re: [PATCH] md/md-llbitmap: allocate page controls independently
Date: Mon, 15 Jun 2026 19:06:23 +0800	[thread overview]
Message-ID: <h5n4awr4.fsf@damenly.org> (raw)
In-Reply-To: <20260605091527.2463539-6-yukuai@kernel.org> (Yu Kuai's message of "Fri, 5 Jun 2026 17:15:12 +0800")

On Fri 05 Jun 2026 at 17:15, Yu Kuai <yukuai@kernel.org> wrote:

> From: Yu Kuai <yukuai@fygo.io>
>
> Allocate one llbitmap page-control object at a time and free 
> each
> object through the same model.
>
> Let llbitmap_read_page() return a zeroed page without reading 
> disk when
> the page index is beyond the current bitmap size, so 
> page-control
> allocation no longer needs a separate read_existing flag.
>
> This keeps the llbitmap page-control lifetime self-consistent 
> and
> prepares the page-cache code for later in-place growth.
>
> Signed-off-by: Yu Kuai <yukuai@fygo.io>
>

Straight enough.

Reviewed-by: Su Yue <glass.su@suse.com>

> ---
>  drivers/md/md-llbitmap.c | 99 
>  +++++++++++++++++++++++++---------------
>  1 file changed, 62 insertions(+), 37 deletions(-)
>
> diff --git a/drivers/md/md-llbitmap.c b/drivers/md/md-llbitmap.c
> index ecf3ed712315..2f2896fe4d6f 100644
> --- a/drivers/md/md-llbitmap.c
> +++ b/drivers/md/md-llbitmap.c
> @@ -510,24 +510,32 @@ static void llbitmap_write(struct llbitmap 
> *llbitmap, enum llbitmap_state state,
>  		llbitmap_set_page_dirty(llbitmap, idx, bit, true);
>  	else if (state == BitNeedSyncUnwritten)
>  		llbitmap_set_page_dirty(llbitmap, idx, bit, false);
>  }
>
> +static unsigned int llbitmap_used_pages(struct llbitmap 
> *llbitmap,
> +					unsigned long chunks)
> +{
> +	return DIV_ROUND_UP(chunks + BITMAP_DATA_OFFSET, PAGE_SIZE);
> +}
> +
>  static struct page *llbitmap_read_page(struct llbitmap 
>  *llbitmap, int idx)
>  {
>  	struct mddev *mddev = llbitmap->mddev;
>  	struct page *page = NULL;
>  	struct md_rdev *rdev;
>
> -	if (llbitmap->pctl && llbitmap->pctl[idx])
> +	if (llbitmap->pctl && idx < llbitmap->nr_pages && 
> llbitmap->pctl[idx])
>  		page = llbitmap->pctl[idx]->page;
>  	if (page)
>  		return page;
>
>  	page = alloc_page(GFP_KERNEL | __GFP_ZERO);
>  	if (!page)
>  		return ERR_PTR(-ENOMEM);
> +	if (idx >= llbitmap_used_pages(llbitmap, llbitmap->chunks))
> +		return page;
>
>  	rdev_for_each(rdev, mddev) {
>  		sector_t sector;
>
>  		if (rdev->raid_disk < 0 || test_bit(Faulty, &rdev->flags) 
>  ||
> @@ -594,65 +602,82 @@ static void llbitmap_free_pages(struct 
> llbitmap *llbitmap)
>  		return;
>
>  	for (i = 0; i < llbitmap->nr_pages; i++) {
>  		struct llbitmap_page_ctl *pctl = llbitmap->pctl[i];
>
> -		if (!pctl || !pctl->page)
> -			break;
> -
> -		__free_page(pctl->page);
> +		if (!pctl)
> +			continue;
> +		if (pctl->page)
> +			__free_page(pctl->page);
>  		percpu_ref_exit(&pctl->active);
> +		kfree(pctl);
>  	}
>
> -	kfree(llbitmap->pctl[0]);
>  	kfree(llbitmap->pctl);
>  	llbitmap->pctl = NULL;
>  }
>
> -static int llbitmap_cache_pages(struct llbitmap *llbitmap)
> +static struct llbitmap_page_ctl *
> +llbitmap_alloc_page_ctl(struct llbitmap *llbitmap, int idx)
>  {
>  	struct llbitmap_page_ctl *pctl;
> -	unsigned int nr_pages = DIV_ROUND_UP(llbitmap->chunks +
> -					     BITMAP_DATA_OFFSET, PAGE_SIZE);
> +	struct page *page;
>  	unsigned int size = struct_size(pctl, dirty, BITS_TO_LONGS(
>  						llbitmap->blocks_per_page));
> -	int i;
> -
> -	llbitmap->pctl = kmalloc_array(nr_pages, sizeof(void *),
> -				       GFP_KERNEL | __GFP_ZERO);
> -	if (!llbitmap->pctl)
> -		return -ENOMEM;
>
>  	size = round_up(size, cache_line_size());
> -	pctl = kmalloc_array(nr_pages, size, GFP_KERNEL | __GFP_ZERO);
> -	if (!pctl) {
> -		kfree(llbitmap->pctl);
> -		return -ENOMEM;
> +	pctl = kzalloc(size, GFP_KERNEL);
> +	if (!pctl)
> +		return ERR_PTR(-ENOMEM);
> +
> +	page = llbitmap_read_page(llbitmap, idx);
> +
> +	if (IS_ERR(page)) {
> +		kfree(pctl);
> +		return ERR_CAST(page);
>  	}
>
> -	llbitmap->nr_pages = nr_pages;
> +	if (percpu_ref_init(&pctl->active, active_release,
> +			    PERCPU_REF_ALLOW_REINIT, GFP_KERNEL)) {
> +		__free_page(page);
> +		kfree(pctl);
> +		return ERR_PTR(-ENOMEM);
> +	}
>
> -	for (i = 0; i < nr_pages; i++, pctl = (void *)pctl + size) {
> -		struct page *page = llbitmap_read_page(llbitmap, i);
> +	pctl->page = page;
> +	pctl->state = page_address(page);
> +	init_waitqueue_head(&pctl->wait);
> +	return pctl;
> +}
>
> -		llbitmap->pctl[i] = pctl;
> +static unsigned int llbitmap_reserved_pages(struct llbitmap 
> *llbitmap)
> +{
> +	return DIV_ROUND_UP(llbitmap->mddev->bitmap_info.space << 
> SECTOR_SHIFT,
> +			    PAGE_SIZE);
> +}
>
> -		if (IS_ERR(page)) {
> -			llbitmap_free_pages(llbitmap);
> -			return PTR_ERR(page);
> -		}
> +static int llbitmap_alloc_pages(struct llbitmap *llbitmap)
> +{
> +	unsigned int used_pages = llbitmap_used_pages(llbitmap, 
> llbitmap->chunks);
> +	unsigned int nr_pages = max(used_pages, 
> llbitmap_reserved_pages(llbitmap));
> +	int i;
> +
> +	llbitmap->pctl = kcalloc(nr_pages, sizeof(*llbitmap->pctl), 
> GFP_KERNEL);
> +	if (!llbitmap->pctl)
> +		return -ENOMEM;
>
> -		if (percpu_ref_init(&pctl->active, active_release,
> -				    PERCPU_REF_ALLOW_REINIT, GFP_KERNEL)) {
> -			__free_page(page);
> +	llbitmap->nr_pages = nr_pages;
> +
> +	for (i = 0; i < nr_pages; i++) {
> +		llbitmap->pctl[i] = llbitmap_alloc_page_ctl(llbitmap, i);
> +		if (IS_ERR(llbitmap->pctl[i])) {
> +			int ret = PTR_ERR(llbitmap->pctl[i]);
> +
> +			llbitmap->pctl[i] = NULL;
>  			llbitmap_free_pages(llbitmap);
> -			return -ENOMEM;
> +			return ret;
>  		}
> -
> -		pctl->page = page;
> -		pctl->state = page_address(page);
> -		init_waitqueue_head(&pctl->wait);
>  	}
>
>  	return 0;
>  }
>
> @@ -921,11 +946,11 @@ static int llbitmap_init(struct llbitmap 
> *llbitmap)
>  	llbitmap->chunksize = chunksize;
>  	llbitmap->chunks = chunks;
>  	llbitmap->sync_size = blocks;
>  	mddev->bitmap_info.daemon_sleep = DEFAULT_DAEMON_SLEEP;
>
> -	ret = llbitmap_cache_pages(llbitmap);
> +	ret = llbitmap_alloc_pages(llbitmap);
>  	if (ret)
>  		return ret;
>
>  	llbitmap_state_machine(llbitmap, 0, llbitmap->chunks - 1,
>  			       BitmapActionInit);
> @@ -1030,11 +1055,11 @@ static int llbitmap_read_sb(struct 
> llbitmap *llbitmap)
>  	llbitmap->barrier_idle = DEFAULT_BARRIER_IDLE;
>  	llbitmap->chunksize = chunksize;
>  	llbitmap->chunks = DIV_ROUND_UP_SECTOR_T(sync_size, 
>  chunksize);
>  	llbitmap->chunkshift = ffz(~chunksize);
>  	llbitmap->sync_size = sync_size;
> -	ret = llbitmap_cache_pages(llbitmap);
> +	ret = llbitmap_alloc_pages(llbitmap);
>
>  out_put_page:
>  	__free_page(sb_page);
>  	kunmap_local(sb);
>  	return ret;

  reply	other threads:[~2026-06-15 11:11 UTC|newest]

Thread overview: 28+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2026-06-05  9:15 [PATCH 00/20] md/md-llbitmap: support reshape for RAID10 and RAID5 Yu Kuai
2026-06-05  9:15 ` [PATCH] md: add exact bitmap mapping and reshape hooks Yu Kuai
2026-06-05  9:15 ` [PATCH] md: skip bitmap accounting for empty write ranges Yu Kuai
2026-06-05  9:15 ` [PATCH] md: add helper to split bios at reshape offset Yu Kuai
2026-06-05  9:15 ` [PATCH] md/md-llbitmap: track bitmap sync_size explicitly Yu Kuai
2026-06-15 10:48   ` Su Yue
2026-06-05  9:15 ` [PATCH] md/md-llbitmap: allocate page controls independently Yu Kuai
2026-06-15 11:06   ` Su Yue [this message]
2026-06-05  9:15 ` [PATCH] md/md-llbitmap: grow the page cache in place for reshape Yu Kuai
2026-06-15 11:16   ` Su Yue
2026-06-15 16:19     ` yu kuai
2026-06-05  9:15 ` [PATCH] md/md-llbitmap: track target reshape geometry fields Yu Kuai
2026-06-05  9:15 ` [PATCH] md/md-llbitmap: finish reshape geometry Yu Kuai
2026-06-05  9:15 ` [PATCH] md/md-llbitmap: refuse reshape while llbitmap still needs sync Yu Kuai
2026-06-05  9:15 ` [PATCH] md/md-llbitmap: add reshape range mapping helpers Yu Kuai
2026-06-05  9:15 ` [PATCH] md/md-llbitmap: don't skip reshape ranges from bitmap state Yu Kuai
2026-06-05  9:15 ` [PATCH] md/md-llbitmap: remap checkpointed bits as reshape progresses Yu Kuai
2026-06-05  9:15 ` [PATCH] md/md-llbitmap: clamp state-machine walks to tracked bits Yu Kuai
2026-06-05  9:15 ` [PATCH] md/raid10: reject llbitmap reshape when md chunk shrinks Yu Kuai
2026-06-05  9:15 ` [PATCH] md/raid10: wire llbitmap reshape lifecycle Yu Kuai
2026-06-05  9:15 ` [PATCH] md/raid10: split reshape bios before bitmap accounting Yu Kuai
2026-06-05  9:15 ` [PATCH] md/raid5: add exact old and new llbitmap mapping helpers Yu Kuai
2026-06-05  9:15 ` [PATCH] md/raid5: reject llbitmap reshape when md chunk shrinks Yu Kuai
2026-06-05  9:15 ` [PATCH] md/raid5: wire llbitmap reshape lifecycle Yu Kuai
2026-06-05  9:15 ` [PATCH] md/raid5: split reshape bios before bitmap accounting Yu Kuai
2026-06-05 17:27   ` kernel test robot
2026-06-06  2:15   ` kernel test robot
  -- strict thread matches above, loose matches on Subject: below --
2026-04-19  3:09 [PATCH 00/19] md: support llbitmap reshape for raid10 and raid5 Yu Kuai
2026-04-19  3:09 ` [PATCH] md/md-llbitmap: allocate page controls independently Yu Kuai

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=h5n4awr4.fsf@damenly.org \
    --to=l@damenly.org \
    --cc=linux-kernel@vger.kernel.org \
    --cc=linux-raid@vger.kernel.org \
    --cc=magiclinan@didiglobal.com \
    --cc=song@kernel.org \
    --cc=xiao@kernel.org \
    --cc=yukuai@fygo.io \
    --cc=yukuai@kernel.org \
    /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