-
Notifications
You must be signed in to change notification settings - Fork 55.2k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
block: make the block holder code optional
Move the block holder code into a separate file as it is not in any way related to the other block_dev.c code, and add a new selectable config option for it so that we don't have to build it without any remapped drivers selected. The Kconfig symbol contains a _DEPRECATED suffix to match the comments added in commit 49731ba ("block: restore multiple bd_link_disk_holder() support"). Signed-off-by: Christoph Hellwig <hch@lst.de> Reviewed-by: Mike Snitzer <snitzer@redhat.com> Link: https://lore.kernel.org/r/20210804094147.459763-2-hch@lst.de Signed-off-by: Jens Axboe <axboe@kernel.dk>
- Loading branch information
Showing
8 changed files
with
151 additions
and
146 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,139 @@ | ||
// SPDX-License-Identifier: GPL-2.0-only | ||
#include <linux/genhd.h> | ||
|
||
struct bd_holder_disk { | ||
struct list_head list; | ||
struct gendisk *disk; | ||
int refcnt; | ||
}; | ||
|
||
static struct bd_holder_disk *bd_find_holder_disk(struct block_device *bdev, | ||
struct gendisk *disk) | ||
{ | ||
struct bd_holder_disk *holder; | ||
|
||
list_for_each_entry(holder, &bdev->bd_holder_disks, list) | ||
if (holder->disk == disk) | ||
return holder; | ||
return NULL; | ||
} | ||
|
||
static int add_symlink(struct kobject *from, struct kobject *to) | ||
{ | ||
return sysfs_create_link(from, to, kobject_name(to)); | ||
} | ||
|
||
static void del_symlink(struct kobject *from, struct kobject *to) | ||
{ | ||
sysfs_remove_link(from, kobject_name(to)); | ||
} | ||
|
||
/** | ||
* bd_link_disk_holder - create symlinks between holding disk and slave bdev | ||
* @bdev: the claimed slave bdev | ||
* @disk: the holding disk | ||
* | ||
* DON'T USE THIS UNLESS YOU'RE ALREADY USING IT. | ||
* | ||
* This functions creates the following sysfs symlinks. | ||
* | ||
* - from "slaves" directory of the holder @disk to the claimed @bdev | ||
* - from "holders" directory of the @bdev to the holder @disk | ||
* | ||
* For example, if /dev/dm-0 maps to /dev/sda and disk for dm-0 is | ||
* passed to bd_link_disk_holder(), then: | ||
* | ||
* /sys/block/dm-0/slaves/sda --> /sys/block/sda | ||
* /sys/block/sda/holders/dm-0 --> /sys/block/dm-0 | ||
* | ||
* The caller must have claimed @bdev before calling this function and | ||
* ensure that both @bdev and @disk are valid during the creation and | ||
* lifetime of these symlinks. | ||
* | ||
* CONTEXT: | ||
* Might sleep. | ||
* | ||
* RETURNS: | ||
* 0 on success, -errno on failure. | ||
*/ | ||
int bd_link_disk_holder(struct block_device *bdev, struct gendisk *disk) | ||
{ | ||
struct bd_holder_disk *holder; | ||
int ret = 0; | ||
|
||
mutex_lock(&bdev->bd_disk->open_mutex); | ||
|
||
WARN_ON_ONCE(!bdev->bd_holder); | ||
|
||
/* FIXME: remove the following once add_disk() handles errors */ | ||
if (WARN_ON(!disk->slave_dir || !bdev->bd_holder_dir)) | ||
goto out_unlock; | ||
|
||
holder = bd_find_holder_disk(bdev, disk); | ||
if (holder) { | ||
holder->refcnt++; | ||
goto out_unlock; | ||
} | ||
|
||
holder = kzalloc(sizeof(*holder), GFP_KERNEL); | ||
if (!holder) { | ||
ret = -ENOMEM; | ||
goto out_unlock; | ||
} | ||
|
||
INIT_LIST_HEAD(&holder->list); | ||
holder->disk = disk; | ||
holder->refcnt = 1; | ||
|
||
ret = add_symlink(disk->slave_dir, bdev_kobj(bdev)); | ||
if (ret) | ||
goto out_free; | ||
|
||
ret = add_symlink(bdev->bd_holder_dir, &disk_to_dev(disk)->kobj); | ||
if (ret) | ||
goto out_del; | ||
/* | ||
* bdev could be deleted beneath us which would implicitly destroy | ||
* the holder directory. Hold on to it. | ||
*/ | ||
kobject_get(bdev->bd_holder_dir); | ||
|
||
list_add(&holder->list, &bdev->bd_holder_disks); | ||
goto out_unlock; | ||
|
||
out_del: | ||
del_symlink(disk->slave_dir, bdev_kobj(bdev)); | ||
out_free: | ||
kfree(holder); | ||
out_unlock: | ||
mutex_unlock(&bdev->bd_disk->open_mutex); | ||
return ret; | ||
} | ||
EXPORT_SYMBOL_GPL(bd_link_disk_holder); | ||
|
||
/** | ||
* bd_unlink_disk_holder - destroy symlinks created by bd_link_disk_holder() | ||
* @bdev: the calimed slave bdev | ||
* @disk: the holding disk | ||
* | ||
* DON'T USE THIS UNLESS YOU'RE ALREADY USING IT. | ||
* | ||
* CONTEXT: | ||
* Might sleep. | ||
*/ | ||
void bd_unlink_disk_holder(struct block_device *bdev, struct gendisk *disk) | ||
{ | ||
struct bd_holder_disk *holder; | ||
|
||
mutex_lock(&bdev->bd_disk->open_mutex); | ||
holder = bd_find_holder_disk(bdev, disk); | ||
if (!WARN_ON_ONCE(holder == NULL) && !--holder->refcnt) { | ||
del_symlink(disk->slave_dir, bdev_kobj(bdev)); | ||
del_symlink(bdev->bd_holder_dir, &disk_to_dev(disk)->kobj); | ||
kobject_put(bdev->bd_holder_dir); | ||
list_del_init(&holder->list); | ||
kfree(holder); | ||
} | ||
mutex_unlock(&bdev->bd_disk->open_mutex); | ||
} | ||
EXPORT_SYMBOL_GPL(bd_unlink_disk_holder); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters