Re: [PATCH] brd: avoid extra xarray lookups on first write

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



On Tue, May 06, 2025 at 04:38:36PM +0200, Christoph Hellwig wrote:
> +	rcu_read_lock();
> +	page = brd_lookup_page(brd, sector);
> +	if (!page && op_is_write(opf)) {
>  		/*
>  		 * Must use NOIO because we don't want to recurse back into the
>  		 * block or filesystem layers from page reclaim.
>  		 */
> -		err = brd_insert_page(brd, sector,
> -				(opf & REQ_NOWAIT) ? GFP_NOWAIT : GFP_NOIO);
> -		if (err) {
> -			if (err == -ENOMEM && (opf & REQ_NOWAIT))
> -				bio_wouldblock_error(bio);
> -			else
> -				bio_io_error(bio);
> -			return false;
> +		gfp_t gfp = (opf & REQ_NOWAIT) ? GFP_NOWAIT : GFP_NOIO;
> +
> +		rcu_read_unlock();
> +		page = alloc_page(gfp | __GFP_ZERO | __GFP_HIGHMEM);
> +		if (!page) {
> +			err = -ENOMEM;
> +			goto out_error;
> +		}
> +		rcu_read_lock();
> +
> +		xa_lock(&brd->brd_pages);
> +		ret = __xa_store(&brd->brd_pages, sector >> PAGE_SECTORS_SHIFT,
> +				page, gfp);

On success, __xa_store() says it replaces the old entry ("ret"), with
your new entry ("page"). I think you want to store the new entry only if
there is no old entry, so shouldn't this instead be:

		ret = __xa_cmpxchg(&brd->brd_pages, sector >> PAGE_SECTORS_SHIFT,
				   NULL, page, gfp);

?

> +		if (!ret)
> +			brd->brd_nr_pages++;
> +		xa_unlock(&brd->brd_pages);
> +
> +		if (ret) {
> +			__free_page(page);
> +			err = xa_err(ret);
> +			if (err < 0)
> +				goto out_error;
> +			page = ret;
>  		}




[Index of Archives]     [Linux RAID]     [Linux SCSI]     [Linux ATA RAID]     [IDE]     [Linux Wireless]     [Linux Kernel]     [ATH6KL]     [Linux Bluetooth]     [Linux Netdev]     [Kernel Newbies]     [Security]     [Git]     [Netfilter]     [Bugtraq]     [Yosemite News]     [MIPS Linux]     [ARM Linux]     [Linux Security]     [Device Mapper]

  Powered by Linux