linux-kernel.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
From: Demi Marie Obenour <demi@invisiblethingslab.com>
To: Jens Axboe <axboe@kernel.dk>
Cc: "Demi Marie Obenour" <demi@invisiblethingslab.com>,
	"Marek Marczykowski-Górecki" <marmarek@invisiblethingslab.com>,
	linux-block@vger.kernel.org, linux-kernel@vger.kernel.org
Subject: [RFC PATCH 1/7] block: Support creating a struct file from a block device
Date: Wed, 25 Jan 2023 22:33:53 -0500	[thread overview]
Message-ID: <20230126033358.1880-2-demi@invisiblethingslab.com> (raw)
In-Reply-To: <20230126033358.1880-1-demi@invisiblethingslab.com>

The newly added blkdev_get_file() function allows kernel code to create
a struct file for any block device.  The main use-case is for the
struct file to be exposed to userspace as a file descriptor.  A future
patch will modify the DM_DEV_CREATE_CREATE ioctl to allow userspace to
get a file descriptor to the newly created block device, avoiding nasty
race conditions.

Signed-off-by: Demi Marie Obenour <demi@invisiblethingslab.com>
---
 block/bdev.c           | 77 +++++++++++++++++++++++++++++++++++-------
 include/linux/blkdev.h |  5 +++
 2 files changed, 70 insertions(+), 12 deletions(-)

diff --git a/block/bdev.c b/block/bdev.c
index edc110d90df4041e7d337976951bd0d17525f1f7..09cb5ef900ca9ad5b21250bb63e64cc2a79f9289 100644
--- a/block/bdev.c
+++ b/block/bdev.c
@@ -459,10 +459,33 @@ static struct file_system_type bd_type = {
 struct super_block *blockdev_superblock __read_mostly;
 EXPORT_SYMBOL_GPL(blockdev_superblock);
 
+static struct vfsmount *bd_mnt __read_mostly;
+
+struct file *
+blkdev_get_file(struct block_device *bdev, fmode_t flags, void *holder)
+{
+	struct inode *inode;
+	struct file *filp;
+	int ret;
+
+	ret = blkdev_do_open(bdev, flags, holder);
+	if (ret)
+		return ERR_PTR(ret);
+	inode = bdev->bd_inode;
+	filp = alloc_file_pseudo(inode, bd_mnt, "[block]", flags | O_CLOEXEC, &def_blk_fops);
+	if (IS_ERR(filp)) {
+		blkdev_put(bdev, flags);
+	} else {
+		filp->f_mapping = inode->i_mapping;
+		filp->f_wb_err = filemap_sample_wb_err(filp->f_mapping);
+	}
+	return filp;
+}
+EXPORT_SYMBOL(blkdev_get_file);
+
 void __init bdev_cache_init(void)
 {
 	int err;
-	static struct vfsmount *bd_mnt;
 
 	bdev_cachep = kmem_cache_create("bdev_cache", sizeof(struct bdev_inode),
 			0, (SLAB_HWCACHE_ALIGN|SLAB_RECLAIM_ACCOUNT|
@@ -775,7 +798,7 @@ void blkdev_put_no_open(struct block_device *bdev)
  *
  * Use this interface ONLY if you really do not have anything better - i.e. when
  * you are behind a truly sucky interface and all you are given is a device
- * number.  Everything else should use blkdev_get_by_path().
+ * number.  Everything else should use blkdev_get_by_path() or blkdev_do_open().
  *
  * CONTEXT:
  * Might sleep.
@@ -785,9 +808,7 @@ void blkdev_put_no_open(struct block_device *bdev)
  */
 struct block_device *blkdev_get_by_dev(dev_t dev, fmode_t mode, void *holder)
 {
-	bool unblock_events = true;
 	struct block_device *bdev;
-	struct gendisk *disk;
 	int ret;
 
 	ret = devcgroup_check_permission(DEVCG_DEV_BLOCK,
@@ -800,18 +821,52 @@ struct block_device *blkdev_get_by_dev(dev_t dev, fmode_t mode, void *holder)
 	bdev = blkdev_get_no_open(dev);
 	if (!bdev)
 		return ERR_PTR(-ENXIO);
-	disk = bdev->bd_disk;
+
+	ret = blkdev_do_open(bdev, mode, holder);
+	if (ret) {
+		blkdev_put_no_open(bdev);
+		return ERR_PTR(ret);
+	}
+
+	return bdev;
+}
+EXPORT_SYMBOL(blkdev_get_by_dev);
+
+/**
+ * blkdev_do_open - open a block device by device pointer
+ * @bdev: pointer to the device to open
+ * @mode: FMODE_* mask
+ * @holder: exclusive holder identifier
+ *
+ * Open the block device pointed to by @bdev. If @mode includes
+ * %FMODE_EXCL, the block device is opened with exclusive access.  Specifying
+ * %FMODE_EXCL with a %NULL @holder is invalid.  Exclusive opens may nest for
+ * the same @holder.
+ *
+ * Unlike blkdev_get_by_dev() and bldev_get_by_path(), this function does not
+ * do any permission checks.  The most common use-case is where the device
+ * was freshly created by userspace.
+ *
+ * CONTEXT:
+ * Might sleep.
+ *
+ * RETURNS:
+ * Reference 0 on success, -errno on failure.
+ */
+int blkdev_do_open(struct block_device *bdev, fmode_t mode, void *holder) {
+	struct gendisk *disk = bdev->bd_disk;
+	int ret = -ENXIO;
+	bool unblock_events = true;
 
 	if (mode & FMODE_EXCL) {
 		ret = bd_prepare_to_claim(bdev, holder);
 		if (ret)
-			goto put_blkdev;
+			return ret;
 	}
 
 	disk_block_events(disk);
 
 	mutex_lock(&disk->open_mutex);
-	ret = -ENXIO;
 	if (!disk_live(disk))
 		goto abort_claiming;
 	if (!try_module_get(disk->fops->owner))
@@ -842,7 +897,7 @@ struct block_device *blkdev_get_by_dev(dev_t dev, fmode_t mode, void *holder)
 
 	if (unblock_events)
 		disk_unblock_events(disk);
-	return bdev;
+	return 0;
 put_module:
 	module_put(disk->fops->owner);
 abort_claiming:
@@ -850,11 +905,9 @@ struct block_device *blkdev_get_by_dev(dev_t dev, fmode_t mode, void *holder)
 		bd_abort_claiming(bdev, holder);
 	mutex_unlock(&disk->open_mutex);
 	disk_unblock_events(disk);
-put_blkdev:
-	blkdev_put_no_open(bdev);
-	return ERR_PTR(ret);
+	return ret;
 }
-EXPORT_SYMBOL(blkdev_get_by_dev);
+EXPORT_SYMBOL(blkdev_do_open);
 
 /**
  * blkdev_get_by_path - open a block device by name
diff --git a/include/linux/blkdev.h b/include/linux/blkdev.h
index 43d4e073b1115e4628a001081fbf08b296d342df..04635cb5ee29d22394a34c65eb34bea4e7847d8d 100644
--- a/include/linux/blkdev.h
+++ b/include/linux/blkdev.h
@@ -325,6 +325,11 @@ typedef int (*report_zones_cb)(struct blk_zone *zone, unsigned int idx,
 
 void disk_set_zoned(struct gendisk *disk, enum blk_zoned_model model);
 
+struct file *
+blkdev_get_file(struct block_device *bdev, fmode_t flags, void *holder);
+
+int blkdev_do_open(struct block_device *bdev, fmode_t flags, void *holder);
+
 #ifdef CONFIG_BLK_DEV_ZONED
 
 #define BLK_ALL_ZONES  ((unsigned int)-1)
-- 
Sincerely,
Demi Marie Obenour (she/her/hers)
Invisible Things Lab

  reply	other threads:[~2023-01-26  3:34 UTC|newest]

Thread overview: 20+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2023-01-26  3:33 [RFC PATCH 0/7] Allow race-free block device handling Demi Marie Obenour
2023-01-26  3:33 ` Demi Marie Obenour [this message]
2023-01-30  8:08   ` [RFC PATCH 1/7] block: Support creating a struct file from a block device Christoph Hellwig
2023-01-30 19:22     ` Demi Marie Obenour
2023-01-31  8:53       ` Christoph Hellwig
2023-01-31 16:27         ` Demi Marie Obenour
2023-02-01  7:45           ` Christoph Hellwig
2023-02-01 16:18             ` Demi Marie Obenour
2023-02-02  8:49           ` Ming Lei
2023-02-02 17:24             ` Demi Marie Obenour
2023-01-26  3:33 ` [RFC PATCH 2/7] Allow userspace to get an FD to a newly-created DM device Demi Marie Obenour
2023-01-26  3:33 ` [RFC PATCH 3/7] Implement diskseq checks in blkback Demi Marie Obenour
2023-01-26  3:33 ` [RFC PATCH 4/7] Increment diskseq when releasing a loop device Demi Marie Obenour
2023-01-30  8:09   ` Christoph Hellwig
2023-01-26  3:33 ` [RFC PATCH 6/7] Minor blkback cleanups Demi Marie Obenour
2023-01-26  3:33 ` [RFC PATCH 7/7] xen/blkback: Inform userspace that device has been opened Demi Marie Obenour
2023-02-02 16:50 ` [RFC PATCH 0/7] Allow race-free block device handling Mike Snitzer
2023-02-02 18:41   ` Demi Marie Obenour
2023-02-02 19:56     ` Mike Snitzer
2023-02-02 20:57       ` Demi Marie Obenour

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=20230126033358.1880-2-demi@invisiblethingslab.com \
    --to=demi@invisiblethingslab.com \
    --cc=axboe@kernel.dk \
    --cc=linux-block@vger.kernel.org \
    --cc=linux-kernel@vger.kernel.org \
    --cc=marmarek@invisiblethingslab.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).