linux-doc.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
From: Christoph Hellwig <hch@infradead.org>
To: Sergei Shtepa <sergei.shtepa@veeam.com>
Cc: axboe@kernel.dk, corbet@lwn.net, linux-block@vger.kernel.org,
	linux-doc@vger.kernel.org, linux-kernel@vger.kernel.org
Subject: Re: [PATCH v2 17/21] block, blksnap: snapshot image block device
Date: Thu, 15 Dec 2022 01:45:34 -0800	[thread overview]
Message-ID: <Y5rsvibCBNGMwnn+@infradead.org> (raw)
In-Reply-To: <20221209142331.26395-18-sergei.shtepa@veeam.com>

On Fri, Dec 09, 2022 at 03:23:27PM +0100, Sergei Shtepa wrote:
> +static int snapimage_kthread_worker_fn(void *param);

Any chance to order th code so that you can avoid forward declarations
wherever possible.

> +static inline int snapimage_start_worker(struct snapimage *snapimage)
> +{
> +	struct task_struct *task;
> +
> +	spin_lock_init(&snapimage->queue_lock);
> +	bio_list_init(&snapimage->queue);
> +
> +	task = kthread_create(snapimage_kthread_worker_fn,
> +			      snapimage,
> +			      BLK_SNAP_IMAGE_NAME "%d",
> +			      MINOR(snapimage->image_dev_id));
> +	if (IS_ERR(task))
> +		return -ENOMEM;
> +
> +	snapimage->worker = get_task_struct(task);

There's not need to grab and put an extra reference to the task_struct,
the kthread code already holds one.

> +	while (!kthread_should_stop()) {
> +		bio = get_bio_from_queue(snapimage);
> +		if (!bio) {
> +			schedule_timeout_interruptible(HZ / 100);

Do you need a timeout sleep here?  All new arrivals should properly
wake the thread.

> +			continue;
> +		}
> +
> +		snapimage_process_bio(snapimage, bio);
> +	}
> +
> +	while ((bio = get_bio_from_queue(snapimage)))
> +		snapimage_process_bio(snapimage, bio);

It seems like the loop could be simplified to:

	for (;; {
		while ((bio = get_bio_from_queue(snapimage)))
			snapimage_process_bio(snapimage, bio);
		if (kthread_should_stop())
			break;
		schedule();
	}

	return 0;


> +static void snapimage_submit_bio(struct bio *bio)
> +{
> +	struct snapimage *snapimage = bio->bi_bdev->bd_disk->private_data;
> +	gfp_t gfp = GFP_NOIO;
> +
> +	if (bio->bi_opf & REQ_NOWAIT)
> +		gfp |= GFP_NOWAIT;

gfp isn't actually used anywhere.

> +	if (snapimage->is_ready) {
> +		spin_lock(&snapimage->queue_lock);
> +		bio_list_add(&snapimage->queue, bio);
> +		spin_unlock(&snapimage->queue_lock);
> +
> +		wake_up_process(snapimage->worker);
> +	} else
> +		bio_io_error(bio);
> +}

I think you can do away with the is_ready flag entirely by just
calling del_gendisk early enough.  See below.

> +void snapimage_free(struct snapimage *snapimage)
> +{
> +	pr_info("Snapshot image disk [%u:%u] delete\n",
> +		MAJOR(snapimage->image_dev_id), MINOR(snapimage->image_dev_id));
> +
> +	blk_mq_freeze_queue(snapimage->disk->queue);
> +	snapimage->is_ready = false;
> +	blk_mq_unfreeze_queue(snapimage->disk->queue);
> +
> +	snapimage_stop_worker(snapimage);
> +
> +	del_gendisk(snapimage->disk);

Just move the snapimage_stop_worker after del_gendisk here, and
you should be fine.

> +	put_disk(snapimage->disk);
> +
> +	diff_area_put(snapimage->diff_area);
> +	cbt_map_put(snapimage->cbt_map);
> +
> +	ida_free(&snapimage_devt_ida, MINOR(snapimage->image_dev_id));
> +	kfree(snapimage);

.. and then implement the free_disk block_device operation, and
move all code after the put_disk into it, which means all your
data structures are alive until the very last gendisk reference goes
away.

> +#ifdef GENHD_FL_NO_PART_SCAN
> +	disk->flags |= GENHD_FL_NO_PART_SCAN;
> +#else
> +	disk->flags |= GENHD_FL_NO_PART;
> +#endif

GENHD_FL_NO_PART_SCAN is gone, so this ifdef goes away.

> +	disk->major = _major;
> +	disk->first_minor = minor;
> +	disk->minors = 1; /* One disk has only one partition */

No new driver should manage the major/minor numbers manually, as
the block layer just assigns a dev_t by default if you don't se these.

> +	wake_up_process(snapimage->worker);

I don't think this wake_up is needed - the first queue bio should
wake the helper thread up.

> +int snapimage_init(void)
> +{
> +	int ret = 0;
> +
> +	ret = register_blkdev(0, BLK_SNAP_IMAGE_NAME);
> +	if (ret < 0) {
> +		pr_err("Failed to register snapshot image block device\n");
> +		return ret;
> +	}
> +
> +	_major = ret;
> +	pr_info("Snapshot image block device major %d was registered\n",
> +		_major);
> +
> +	return 0;
> +}
> +
> +void snapimage_done(void)
> +{
> +	unregister_blkdev(_major, BLK_SNAP_IMAGE_NAME);
> +	pr_info("Snapshot image block device [%d] was unregistered\n", _major);
> +}

And with block layer managed dev_t all this boilerplate can go away
as well.

> +#include <linux/blk_types.h>
> +#include <linux/blkdev.h>
> +#include <linux/blk-mq.h>

If you already include blk-mq.h, there is no need for the other two
headers as they are already implictly included.

  reply	other threads:[~2022-12-15  9:45 UTC|newest]

Thread overview: 45+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2022-12-09 14:23 [PATCH v2 00/21] blksnap - block devices snapshots module Sergei Shtepa
2022-12-09 14:23 ` [PATCH v2 01/21] documentation, blkfilter: Block Device Filtering Mechanism Sergei Shtepa
2022-12-10  4:15   ` Bagas Sanjaya
2022-12-09 14:23 ` [PATCH v2 02/21] block, " Sergei Shtepa
2022-12-15  9:26   ` Christoph Hellwig
2022-12-15 10:46     ` Sergei Shtepa
2022-12-16  7:04       ` Christoph Hellwig
2023-01-31 23:58   ` Mike Snitzer
2023-02-01 11:09     ` Fabio Fantoni
2023-02-01 13:16     ` Sergei Shtepa
2022-12-09 14:23 ` [PATCH v2 03/21] documentation, capability: fix Generic Block Device Capability Sergei Shtepa
2022-12-13 12:13   ` Fabio Fantoni
2022-12-30 15:35     ` Fabio Fantoni
2022-12-09 14:23 ` [PATCH v2 04/21] documentation, blksnap: Block Devices Snapshots Module Sergei Shtepa
2022-12-10  3:50   ` Bagas Sanjaya
2022-12-09 14:23 ` [PATCH v2 05/21] block, blksnap: header file of the module interface Sergei Shtepa
2022-12-09 14:23 ` [PATCH v2 06/21] block, blksnap: module management interface functions Sergei Shtepa
2022-12-15  9:28   ` Christoph Hellwig
     [not found]   ` <CGME20230103153406eucas1p205c48bd767e6a86f6f1121db7eb5fc19@eucas1p2.samsung.com>
2023-01-03 15:26     ` Pankaj Raghav
2022-12-09 14:23 ` [PATCH v2 07/21] block, blksnap: init() and exit() functions Sergei Shtepa
2022-12-15  9:30   ` Christoph Hellwig
2022-12-09 14:23 ` [PATCH v2 08/21] block, blksnap: interaction with sysfs Sergei Shtepa
2022-12-09 14:23 ` [PATCH v2 09/21] block, blksnap: attaching and detaching the filter and handling I/O units Sergei Shtepa
2022-12-15 10:01   ` Christoph Hellwig
2022-12-09 14:23 ` [PATCH v2 10/21] block, blksnap: map of change block tracking Sergei Shtepa
2022-12-09 14:23 ` [PATCH v2 11/21] block, blksnap: minimum data storage unit of the original block device Sergei Shtepa
2022-12-09 14:23 ` [PATCH v2 12/21] block, blksnap: buffer in memory for the minimum data storage unit Sergei Shtepa
2022-12-09 14:23 ` [PATCH v2 13/21] block, blksnap: functions and structures for performing block I/O operations Sergei Shtepa
2022-12-15 10:06   ` Christoph Hellwig
2022-12-09 14:23 ` [PATCH v2 14/21] block, blksnap: storage for storing difference blocks Sergei Shtepa
2022-12-09 14:23 ` [PATCH v2 15/21] block, blksnap: event queue from the difference storage Sergei Shtepa
2022-12-09 14:23 ` [PATCH v2 16/21] block, blksnap: owner of information about overwritten blocks of the original block device Sergei Shtepa
2022-12-09 14:23 ` [PATCH v2 17/21] block, blksnap: snapshot image " Sergei Shtepa
2022-12-15  9:45   ` Christoph Hellwig [this message]
2022-12-09 14:23 ` [PATCH v2 18/21] block, blksnap: snapshot Sergei Shtepa
2022-12-09 14:23 ` [PATCH v2 19/21] block, blksnap: Kconfig and Makefile Sergei Shtepa
2022-12-09 14:23 ` [PATCH v2 20/21] block, blksnap: adds a blksnap to the kernel tree Sergei Shtepa
2022-12-09 14:23 ` [PATCH v2 21/21] block, blksnap: adds a maintainer for new files Sergei Shtepa
2022-12-10  3:23 ` [PATCH v2 00/21] blksnap - block devices snapshots module Bagas Sanjaya
2022-12-10 22:57   ` Sergei Shtepa
2023-01-17 21:04 ` Mike Snitzer
2023-01-18 10:51   ` Hannes Reinecke
2023-01-24 11:34   ` Sergei Shtepa
2023-01-31 20:47     ` Mike Snitzer
2023-02-01  2:32       ` Mason Giles

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=Y5rsvibCBNGMwnn+@infradead.org \
    --to=hch@infradead.org \
    --cc=axboe@kernel.dk \
    --cc=corbet@lwn.net \
    --cc=linux-block@vger.kernel.org \
    --cc=linux-doc@vger.kernel.org \
    --cc=linux-kernel@vger.kernel.org \
    --cc=sergei.shtepa@veeam.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;
as well as URLs for NNTP newsgroup(s).