Skip to content
This repository was archived by the owner on Nov 8, 2023. It is now read-only.

Commit 2736e8e

Browse files
Christoph Hellwigaxboe
authored andcommitted
block: use the holder as indication for exclusive opens
The current interface for exclusive opens is rather confusing as it requires both the FMODE_EXCL flag and a holder. Remove the need to pass FMODE_EXCL and just key off the exclusive open off a non-NULL holder. For blkdev_put this requires adding the holder argument, which provides better debug checking that only the holder actually releases the hold, but at the same time allows removing the now superfluous mode argument. Signed-off-by: Christoph Hellwig <[email protected]> Reviewed-by: Hannes Reinecke <[email protected]> Acked-by: Christian Brauner <[email protected]> Acked-by: David Sterba <[email protected]> [btrfs] Acked-by: Jack Wang <[email protected]> [rnbd] Link: https://lore.kernel.org/r/[email protected] Signed-off-by: Jens Axboe <[email protected]>
1 parent 2ef7892 commit 2736e8e

File tree

37 files changed

+183
-192
lines changed

37 files changed

+183
-192
lines changed

block/bdev.c

Lines changed: 21 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -604,7 +604,7 @@ void bd_abort_claiming(struct block_device *bdev, void *holder)
604604
}
605605
EXPORT_SYMBOL(bd_abort_claiming);
606606

607-
static void bd_end_claim(struct block_device *bdev)
607+
static void bd_end_claim(struct block_device *bdev, void *holder)
608608
{
609609
struct block_device *whole = bdev_whole(bdev);
610610
bool unblock = false;
@@ -614,6 +614,7 @@ static void bd_end_claim(struct block_device *bdev)
614614
* bdev_lock. open_mutex is used to synchronize disk_holder unlinking.
615615
*/
616616
mutex_lock(&bdev_lock);
617+
WARN_ON_ONCE(bdev->bd_holder != holder);
617618
WARN_ON_ONCE(--bdev->bd_holders < 0);
618619
WARN_ON_ONCE(--whole->bd_holders < 0);
619620
if (!bdev->bd_holders) {
@@ -750,10 +751,9 @@ void blkdev_put_no_open(struct block_device *bdev)
750751
* @holder: exclusive holder identifier
751752
* @hops: holder operations
752753
*
753-
* Open the block device described by device number @dev. If @mode includes
754-
* %FMODE_EXCL, the block device is opened with exclusive access. Specifying
755-
* %FMODE_EXCL with a %NULL @holder is invalid. Exclusive opens may nest for
756-
* the same @holder.
754+
* Open the block device described by device number @dev. If @holder is not
755+
* %NULL, the block device is opened with exclusive access. Exclusive opens may
756+
* nest for the same @holder.
757757
*
758758
* Use this interface ONLY if you really do not have anything better - i.e. when
759759
* you are behind a truly sucky interface and all you are given is a device
@@ -785,10 +785,16 @@ struct block_device *blkdev_get_by_dev(dev_t dev, fmode_t mode, void *holder,
785785
return ERR_PTR(-ENXIO);
786786
disk = bdev->bd_disk;
787787

788-
if (mode & FMODE_EXCL) {
788+
if (holder) {
789+
mode |= FMODE_EXCL;
789790
ret = bd_prepare_to_claim(bdev, holder, hops);
790791
if (ret)
791792
goto put_blkdev;
793+
} else {
794+
if (WARN_ON_ONCE(mode & FMODE_EXCL)) {
795+
ret = -EIO;
796+
goto put_blkdev;
797+
}
792798
}
793799

794800
disk_block_events(disk);
@@ -805,7 +811,7 @@ struct block_device *blkdev_get_by_dev(dev_t dev, fmode_t mode, void *holder,
805811
ret = blkdev_get_whole(bdev, mode);
806812
if (ret)
807813
goto put_module;
808-
if (mode & FMODE_EXCL) {
814+
if (holder) {
809815
bd_finish_claiming(bdev, holder, hops);
810816

811817
/*
@@ -829,7 +835,7 @@ struct block_device *blkdev_get_by_dev(dev_t dev, fmode_t mode, void *holder,
829835
put_module:
830836
module_put(disk->fops->owner);
831837
abort_claiming:
832-
if (mode & FMODE_EXCL)
838+
if (holder)
833839
bd_abort_claiming(bdev, holder);
834840
mutex_unlock(&disk->open_mutex);
835841
disk_unblock_events(disk);
@@ -845,10 +851,9 @@ EXPORT_SYMBOL(blkdev_get_by_dev);
845851
* @mode: FMODE_* mask
846852
* @holder: exclusive holder identifier
847853
*
848-
* Open the block device described by the device file at @path. If @mode
849-
* includes %FMODE_EXCL, the block device is opened with exclusive access.
850-
* Specifying %FMODE_EXCL with a %NULL @holder is invalid. Exclusive opens may
851-
* nest for the same @holder.
854+
* Open the block device described by the device file at @path. If @holder is
855+
* not %NULL, the block device is opened with exclusive access. Exclusive opens
856+
* may nest for the same @holder.
852857
*
853858
* CONTEXT:
854859
* Might sleep.
@@ -869,15 +874,15 @@ struct block_device *blkdev_get_by_path(const char *path, fmode_t mode,
869874

870875
bdev = blkdev_get_by_dev(dev, mode, holder, hops);
871876
if (!IS_ERR(bdev) && (mode & FMODE_WRITE) && bdev_read_only(bdev)) {
872-
blkdev_put(bdev, mode);
877+
blkdev_put(bdev, holder);
873878
return ERR_PTR(-EACCES);
874879
}
875880

876881
return bdev;
877882
}
878883
EXPORT_SYMBOL(blkdev_get_by_path);
879884

880-
void blkdev_put(struct block_device *bdev, fmode_t mode)
885+
void blkdev_put(struct block_device *bdev, void *holder)
881886
{
882887
struct gendisk *disk = bdev->bd_disk;
883888

@@ -892,8 +897,8 @@ void blkdev_put(struct block_device *bdev, fmode_t mode)
892897
sync_blockdev(bdev);
893898

894899
mutex_lock(&disk->open_mutex);
895-
if (mode & FMODE_EXCL)
896-
bd_end_claim(bdev);
900+
if (holder)
901+
bd_end_claim(bdev, holder);
897902

898903
/*
899904
* Trigger event checking and tell drivers to flush MEDIA_CHANGE

block/fops.c

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -490,7 +490,9 @@ static int blkdev_open(struct inode *inode, struct file *filp)
490490
if ((filp->f_flags & O_ACCMODE) == 3)
491491
filp->f_mode |= FMODE_WRITE_IOCTL;
492492

493-
bdev = blkdev_get_by_dev(inode->i_rdev, filp->f_mode, filp, NULL);
493+
bdev = blkdev_get_by_dev(inode->i_rdev, filp->f_mode,
494+
(filp->f_mode & FMODE_EXCL) ? filp : NULL,
495+
NULL);
494496
if (IS_ERR(bdev))
495497
return PTR_ERR(bdev);
496498

@@ -504,7 +506,7 @@ static int blkdev_release(struct inode *inode, struct file *filp)
504506
{
505507
struct block_device *bdev = filp->private_data;
506508

507-
blkdev_put(bdev, filp->f_mode);
509+
blkdev_put(bdev, (filp->f_mode & FMODE_EXCL) ? filp : NULL);
508510
return 0;
509511
}
510512

block/genhd.c

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -365,12 +365,11 @@ int disk_scan_partitions(struct gendisk *disk, fmode_t mode)
365365
}
366366

367367
set_bit(GD_NEED_PART_SCAN, &disk->state);
368-
bdev = blkdev_get_by_dev(disk_devt(disk), mode & ~FMODE_EXCL, NULL,
369-
NULL);
368+
bdev = blkdev_get_by_dev(disk_devt(disk), mode, NULL, NULL);
370369
if (IS_ERR(bdev))
371370
ret = PTR_ERR(bdev);
372371
else
373-
blkdev_put(bdev, mode & ~FMODE_EXCL);
372+
blkdev_put(bdev, NULL);
374373

375374
/*
376375
* If blkdev_get_by_dev() failed early, GD_NEED_PART_SCAN is still set,

block/ioctl.c

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -454,11 +454,10 @@ static int blkdev_bszset(struct block_device *bdev, fmode_t mode,
454454
if (mode & FMODE_EXCL)
455455
return set_blocksize(bdev, n);
456456

457-
if (IS_ERR(blkdev_get_by_dev(bdev->bd_dev, mode | FMODE_EXCL, &bdev,
458-
NULL)))
457+
if (IS_ERR(blkdev_get_by_dev(bdev->bd_dev, mode, &bdev, NULL)))
459458
return -EBUSY;
460459
ret = set_blocksize(bdev, n);
461-
blkdev_put(bdev, mode | FMODE_EXCL);
460+
blkdev_put(bdev, &bdev);
462461

463462
return ret;
464463
}

drivers/block/drbd/drbd_nl.c

Lines changed: 14 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1640,8 +1640,7 @@ static struct block_device *open_backing_dev(struct drbd_device *device,
16401640
struct block_device *bdev;
16411641
int err = 0;
16421642

1643-
bdev = blkdev_get_by_path(bdev_path,
1644-
FMODE_READ | FMODE_WRITE | FMODE_EXCL,
1643+
bdev = blkdev_get_by_path(bdev_path, FMODE_READ | FMODE_WRITE,
16451644
claim_ptr, NULL);
16461645
if (IS_ERR(bdev)) {
16471646
drbd_err(device, "open(\"%s\") failed with %ld\n",
@@ -1654,7 +1653,7 @@ static struct block_device *open_backing_dev(struct drbd_device *device,
16541653

16551654
err = bd_link_disk_holder(bdev, device->vdisk);
16561655
if (err) {
1657-
blkdev_put(bdev, FMODE_READ | FMODE_WRITE | FMODE_EXCL);
1656+
blkdev_put(bdev, claim_ptr);
16581657
drbd_err(device, "bd_link_disk_holder(\"%s\", ...) failed with %d\n",
16591658
bdev_path, err);
16601659
bdev = ERR_PTR(err);
@@ -1696,22 +1695,25 @@ static int open_backing_devices(struct drbd_device *device,
16961695
}
16971696

16981697
static void close_backing_dev(struct drbd_device *device, struct block_device *bdev,
1699-
bool do_bd_unlink)
1698+
void *claim_ptr, bool do_bd_unlink)
17001699
{
17011700
if (!bdev)
17021701
return;
17031702
if (do_bd_unlink)
17041703
bd_unlink_disk_holder(bdev, device->vdisk);
1705-
blkdev_put(bdev, FMODE_READ | FMODE_WRITE | FMODE_EXCL);
1704+
blkdev_put(bdev, claim_ptr);
17061705
}
17071706

17081707
void drbd_backing_dev_free(struct drbd_device *device, struct drbd_backing_dev *ldev)
17091708
{
17101709
if (ldev == NULL)
17111710
return;
17121711

1713-
close_backing_dev(device, ldev->md_bdev, ldev->md_bdev != ldev->backing_bdev);
1714-
close_backing_dev(device, ldev->backing_bdev, true);
1712+
close_backing_dev(device, ldev->md_bdev,
1713+
ldev->md.meta_dev_idx < 0 ?
1714+
(void *)device : (void *)drbd_m_holder,
1715+
ldev->md_bdev != ldev->backing_bdev);
1716+
close_backing_dev(device, ldev->backing_bdev, device, true);
17151717

17161718
kfree(ldev->disk_conf);
17171719
kfree(ldev);
@@ -2127,8 +2129,11 @@ int drbd_adm_attach(struct sk_buff *skb, struct genl_info *info)
21272129
fail:
21282130
conn_reconfig_done(connection);
21292131
if (nbc) {
2130-
close_backing_dev(device, nbc->md_bdev, nbc->md_bdev != nbc->backing_bdev);
2131-
close_backing_dev(device, nbc->backing_bdev, true);
2132+
close_backing_dev(device, nbc->md_bdev,
2133+
nbc->disk_conf->meta_dev_idx < 0 ?
2134+
(void *)device : (void *)drbd_m_holder,
2135+
nbc->md_bdev != nbc->backing_bdev);
2136+
close_backing_dev(device, nbc->backing_bdev, device, true);
21322137
kfree(nbc);
21332138
}
21342139
kfree(new_disk_conf);

drivers/block/pktcdvd.c

Lines changed: 6 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -2167,8 +2167,7 @@ static int pkt_open_dev(struct pktcdvd_device *pd, fmode_t write)
21672167
* to read/write from/to it. It is already opened in O_NONBLOCK mode
21682168
* so open should not fail.
21692169
*/
2170-
bdev = blkdev_get_by_dev(pd->bdev->bd_dev, FMODE_READ | FMODE_EXCL, pd,
2171-
NULL);
2170+
bdev = blkdev_get_by_dev(pd->bdev->bd_dev, FMODE_READ, pd, NULL);
21722171
if (IS_ERR(bdev)) {
21732172
ret = PTR_ERR(bdev);
21742173
goto out;
@@ -2215,7 +2214,7 @@ static int pkt_open_dev(struct pktcdvd_device *pd, fmode_t write)
22152214
return 0;
22162215

22172216
out_putdev:
2218-
blkdev_put(bdev, FMODE_READ | FMODE_EXCL);
2217+
blkdev_put(bdev, pd);
22192218
out:
22202219
return ret;
22212220
}
@@ -2234,7 +2233,7 @@ static void pkt_release_dev(struct pktcdvd_device *pd, int flush)
22342233
pkt_lock_door(pd, 0);
22352234

22362235
pkt_set_speed(pd, MAX_SPEED, MAX_SPEED);
2237-
blkdev_put(pd->bdev, FMODE_READ | FMODE_EXCL);
2236+
blkdev_put(pd->bdev, pd);
22382237

22392238
pkt_shrink_pktlist(pd);
22402239
}
@@ -2520,7 +2519,7 @@ static int pkt_new_dev(struct pktcdvd_device *pd, dev_t dev)
25202519
return PTR_ERR(bdev);
25212520
sdev = scsi_device_from_queue(bdev->bd_disk->queue);
25222521
if (!sdev) {
2523-
blkdev_put(bdev, FMODE_READ | FMODE_NDELAY);
2522+
blkdev_put(bdev, NULL);
25242523
return -EINVAL;
25252524
}
25262525
put_device(&sdev->sdev_gendev);
@@ -2545,7 +2544,7 @@ static int pkt_new_dev(struct pktcdvd_device *pd, dev_t dev)
25452544
return 0;
25462545

25472546
out_mem:
2548-
blkdev_put(bdev, FMODE_READ | FMODE_NDELAY);
2547+
blkdev_put(bdev, NULL);
25492548
/* This is safe: open() is still holding a reference. */
25502549
module_put(THIS_MODULE);
25512550
return -ENOMEM;
@@ -2751,7 +2750,7 @@ static int pkt_remove_dev(dev_t pkt_dev)
27512750
pkt_debugfs_dev_remove(pd);
27522751
pkt_sysfs_dev_remove(pd);
27532752

2754-
blkdev_put(pd->bdev, FMODE_READ | FMODE_NDELAY);
2753+
blkdev_put(pd->bdev, NULL);
27552754

27562755
remove_proc_entry(pd->disk->disk_name, pkt_proc);
27572756
dev_notice(ddev, "writer unmapped\n");

drivers/block/rnbd/rnbd-srv.c

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -219,7 +219,7 @@ void rnbd_destroy_sess_dev(struct rnbd_srv_sess_dev *sess_dev, bool keep_id)
219219
rnbd_put_sess_dev(sess_dev);
220220
wait_for_completion(&dc); /* wait for inflights to drop to zero */
221221

222-
blkdev_put(sess_dev->bdev, sess_dev->open_flags);
222+
blkdev_put(sess_dev->bdev, NULL);
223223
mutex_lock(&sess_dev->dev->lock);
224224
list_del(&sess_dev->dev_list);
225225
if (sess_dev->open_flags & FMODE_WRITE)
@@ -791,7 +791,7 @@ static int process_msg_open(struct rnbd_srv_session *srv_sess,
791791
}
792792
rnbd_put_srv_dev(srv_dev);
793793
blkdev_put:
794-
blkdev_put(bdev, open_flags);
794+
blkdev_put(bdev, NULL);
795795
free_path:
796796
kfree(full_path);
797797
reject:

drivers/block/xen-blkback/xenbus.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -473,7 +473,7 @@ static void xenvbd_sysfs_delif(struct xenbus_device *dev)
473473
static void xen_vbd_free(struct xen_vbd *vbd)
474474
{
475475
if (vbd->bdev)
476-
blkdev_put(vbd->bdev, vbd->readonly ? FMODE_READ : FMODE_WRITE);
476+
blkdev_put(vbd->bdev, NULL);
477477
vbd->bdev = NULL;
478478
}
479479

drivers/block/zram/zram_drv.c

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -420,7 +420,7 @@ static void reset_bdev(struct zram *zram)
420420
return;
421421

422422
bdev = zram->bdev;
423-
blkdev_put(bdev, FMODE_READ|FMODE_WRITE|FMODE_EXCL);
423+
blkdev_put(bdev, zram);
424424
/* hope filp_close flush all of IO */
425425
filp_close(zram->backing_dev, NULL);
426426
zram->backing_dev = NULL;
@@ -507,8 +507,8 @@ static ssize_t backing_dev_store(struct device *dev,
507507
goto out;
508508
}
509509

510-
bdev = blkdev_get_by_dev(inode->i_rdev,
511-
FMODE_READ | FMODE_WRITE | FMODE_EXCL, zram, NULL);
510+
bdev = blkdev_get_by_dev(inode->i_rdev, FMODE_READ | FMODE_WRITE, zram,
511+
NULL);
512512
if (IS_ERR(bdev)) {
513513
err = PTR_ERR(bdev);
514514
bdev = NULL;
@@ -539,7 +539,7 @@ static ssize_t backing_dev_store(struct device *dev,
539539
kvfree(bitmap);
540540

541541
if (bdev)
542-
blkdev_put(bdev, FMODE_READ | FMODE_WRITE | FMODE_EXCL);
542+
blkdev_put(bdev, zram);
543543

544544
if (backing_dev)
545545
filp_close(backing_dev, NULL);

drivers/md/bcache/super.c

Lines changed: 7 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1369,7 +1369,7 @@ static void cached_dev_free(struct closure *cl)
13691369
put_page(virt_to_page(dc->sb_disk));
13701370

13711371
if (!IS_ERR_OR_NULL(dc->bdev))
1372-
blkdev_put(dc->bdev, FMODE_READ|FMODE_WRITE|FMODE_EXCL);
1372+
blkdev_put(dc->bdev, bcache_kobj);
13731373

13741374
wake_up(&unregister_wait);
13751375

@@ -2218,7 +2218,7 @@ void bch_cache_release(struct kobject *kobj)
22182218
put_page(virt_to_page(ca->sb_disk));
22192219

22202220
if (!IS_ERR_OR_NULL(ca->bdev))
2221-
blkdev_put(ca->bdev, FMODE_READ|FMODE_WRITE|FMODE_EXCL);
2221+
blkdev_put(ca->bdev, bcache_kobj);
22222222

22232223
kfree(ca);
22242224
module_put(THIS_MODULE);
@@ -2359,7 +2359,7 @@ static int register_cache(struct cache_sb *sb, struct cache_sb_disk *sb_disk,
23592359
* call blkdev_put() to bdev in bch_cache_release(). So we
23602360
* explicitly call blkdev_put() here.
23612361
*/
2362-
blkdev_put(bdev, FMODE_READ|FMODE_WRITE|FMODE_EXCL);
2362+
blkdev_put(bdev, bcache_kobj);
23632363
if (ret == -ENOMEM)
23642364
err = "cache_alloc(): -ENOMEM";
23652365
else if (ret == -EPERM)
@@ -2461,7 +2461,7 @@ static void register_bdev_worker(struct work_struct *work)
24612461
if (!dc) {
24622462
fail = true;
24632463
put_page(virt_to_page(args->sb_disk));
2464-
blkdev_put(args->bdev, FMODE_READ | FMODE_WRITE | FMODE_EXCL);
2464+
blkdev_put(args->bdev, bcache_kobj);
24652465
goto out;
24662466
}
24672467

@@ -2491,7 +2491,7 @@ static void register_cache_worker(struct work_struct *work)
24912491
if (!ca) {
24922492
fail = true;
24932493
put_page(virt_to_page(args->sb_disk));
2494-
blkdev_put(args->bdev, FMODE_READ | FMODE_WRITE | FMODE_EXCL);
2494+
blkdev_put(args->bdev, bcache_kobj);
24952495
goto out;
24962496
}
24972497

@@ -2558,8 +2558,7 @@ static ssize_t register_bcache(struct kobject *k, struct kobj_attribute *attr,
25582558

25592559
ret = -EINVAL;
25602560
err = "failed to open device";
2561-
bdev = blkdev_get_by_path(strim(path),
2562-
FMODE_READ|FMODE_WRITE|FMODE_EXCL,
2561+
bdev = blkdev_get_by_path(strim(path), FMODE_READ | FMODE_WRITE,
25632562
bcache_kobj, NULL);
25642563
if (IS_ERR(bdev)) {
25652564
if (bdev == ERR_PTR(-EBUSY)) {
@@ -2648,7 +2647,7 @@ static ssize_t register_bcache(struct kobject *k, struct kobj_attribute *attr,
26482647
out_put_sb_page:
26492648
put_page(virt_to_page(sb_disk));
26502649
out_blkdev_put:
2651-
blkdev_put(bdev, FMODE_READ | FMODE_WRITE | FMODE_EXCL);
2650+
blkdev_put(bdev, register_bcache);
26522651
out_free_sb:
26532652
kfree(sb);
26542653
out_free_path:

0 commit comments

Comments
 (0)