block: use the holder as indication for exclusive opens
authorChristoph Hellwig <hch@lst.de>
Thu, 8 Jun 2023 11:02:43 +0000 (13:02 +0200)
committerJens Axboe <axboe@kernel.dk>
Mon, 12 Jun 2023 14:04:04 +0000 (08:04 -0600)
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 <hch@lst.de>
Reviewed-by: Hannes Reinecke <hare@suse.de>
Acked-by: Christian Brauner <brauner@kernel.org>
Acked-by: David Sterba <dsterba@suse.com> [btrfs]
Acked-by: Jack Wang <jinpu.wang@ionos.com> [rnbd]
Link: https://lore.kernel.org/r/20230608110258.189493-16-hch@lst.de
Signed-off-by: Jens Axboe <axboe@kernel.dk>
37 files changed:
block/bdev.c
block/fops.c
block/genhd.c
block/ioctl.c
drivers/block/drbd/drbd_nl.c
drivers/block/pktcdvd.c
drivers/block/rnbd/rnbd-srv.c
drivers/block/xen-blkback/xenbus.c
drivers/block/zram/zram_drv.c
drivers/md/bcache/super.c
drivers/md/dm.c
drivers/md/md.c
drivers/mtd/devices/block2mtd.c
drivers/nvme/target/io-cmd-bdev.c
drivers/s390/block/dasd_genhd.c
drivers/target/target_core_iblock.c
drivers/target/target_core_pscsi.c
fs/btrfs/dev-replace.c
fs/btrfs/ioctl.c
fs/btrfs/volumes.c
fs/btrfs/volumes.h
fs/erofs/super.c
fs/ext4/super.c
fs/f2fs/super.c
fs/jfs/jfs_logmgr.c
fs/nfs/blocklayout/dev.c
fs/nilfs2/super.c
fs/ocfs2/cluster/heartbeat.c
fs/reiserfs/journal.c
fs/reiserfs/reiserfs.h
fs/super.c
fs/xfs/xfs_super.c
include/linux/blkdev.h
kernel/power/hibernate.c
kernel/power/power.h
kernel/power/swap.c
mm/swapfile.c

index 2c6888ceb3784a9b6e7826f1b68927ecebfddbf0..db63e5bcc46ffabf699cf5d1aa945c2c60367edc 100644 (file)
@@ -604,7 +604,7 @@ void bd_abort_claiming(struct block_device *bdev, void *holder)
 }
 EXPORT_SYMBOL(bd_abort_claiming);
 
-static void bd_end_claim(struct block_device *bdev)
+static void bd_end_claim(struct block_device *bdev, void *holder)
 {
        struct block_device *whole = bdev_whole(bdev);
        bool unblock = false;
@@ -614,6 +614,7 @@ static void bd_end_claim(struct block_device *bdev)
         * bdev_lock.  open_mutex is used to synchronize disk_holder unlinking.
         */
        mutex_lock(&bdev_lock);
+       WARN_ON_ONCE(bdev->bd_holder != holder);
        WARN_ON_ONCE(--bdev->bd_holders < 0);
        WARN_ON_ONCE(--whole->bd_holders < 0);
        if (!bdev->bd_holders) {
@@ -750,10 +751,9 @@ void blkdev_put_no_open(struct block_device *bdev)
  * @holder: exclusive holder identifier
  * @hops: holder operations
  *
- * Open the block device described by device number @dev. 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.
+ * Open the block device described by device number @dev. If @holder is not
+ * %NULL, the block device is opened with exclusive access.  Exclusive opens may
+ * nest for the same @holder.
  *
  * 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
@@ -785,10 +785,16 @@ struct block_device *blkdev_get_by_dev(dev_t dev, fmode_t mode, void *holder,
                return ERR_PTR(-ENXIO);
        disk = bdev->bd_disk;
 
-       if (mode & FMODE_EXCL) {
+       if (holder) {
+               mode |= FMODE_EXCL;
                ret = bd_prepare_to_claim(bdev, holder, hops);
                if (ret)
                        goto put_blkdev;
+       } else {
+               if (WARN_ON_ONCE(mode & FMODE_EXCL)) {
+                       ret = -EIO;
+                       goto put_blkdev;
+               }
        }
 
        disk_block_events(disk);
@@ -805,7 +811,7 @@ struct block_device *blkdev_get_by_dev(dev_t dev, fmode_t mode, void *holder,
                ret = blkdev_get_whole(bdev, mode);
        if (ret)
                goto put_module;
-       if (mode & FMODE_EXCL) {
+       if (holder) {
                bd_finish_claiming(bdev, holder, hops);
 
                /*
@@ -829,7 +835,7 @@ struct block_device *blkdev_get_by_dev(dev_t dev, fmode_t mode, void *holder,
 put_module:
        module_put(disk->fops->owner);
 abort_claiming:
-       if (mode & FMODE_EXCL)
+       if (holder)
                bd_abort_claiming(bdev, holder);
        mutex_unlock(&disk->open_mutex);
        disk_unblock_events(disk);
@@ -845,10 +851,9 @@ EXPORT_SYMBOL(blkdev_get_by_dev);
  * @mode: FMODE_* mask
  * @holder: exclusive holder identifier
  *
- * Open the block device described by the device file at @path.  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.
+ * Open the block device described by the device file at @path.  If @holder is
+ * not %NULL, the block device is opened with exclusive access.  Exclusive opens
+ * may nest for the same @holder.
  *
  * CONTEXT:
  * Might sleep.
@@ -869,7 +874,7 @@ struct block_device *blkdev_get_by_path(const char *path, fmode_t mode,
 
        bdev = blkdev_get_by_dev(dev, mode, holder, hops);
        if (!IS_ERR(bdev) && (mode & FMODE_WRITE) && bdev_read_only(bdev)) {
-               blkdev_put(bdev, mode);
+               blkdev_put(bdev, holder);
                return ERR_PTR(-EACCES);
        }
 
@@ -877,7 +882,7 @@ struct block_device *blkdev_get_by_path(const char *path, fmode_t mode,
 }
 EXPORT_SYMBOL(blkdev_get_by_path);
 
-void blkdev_put(struct block_device *bdev, fmode_t mode)
+void blkdev_put(struct block_device *bdev, void *holder)
 {
        struct gendisk *disk = bdev->bd_disk;
 
@@ -892,8 +897,8 @@ void blkdev_put(struct block_device *bdev, fmode_t mode)
                sync_blockdev(bdev);
 
        mutex_lock(&disk->open_mutex);
-       if (mode & FMODE_EXCL)
-               bd_end_claim(bdev);
+       if (holder)
+               bd_end_claim(bdev, holder);
 
        /*
         * Trigger event checking and tell drivers to flush MEDIA_CHANGE
index 26af2b39c758e1da9eb944ce3a13f89afd9e6d06..9f26e25bafa172b602a5a45ddb18a7e48a0cab26 100644 (file)
@@ -490,7 +490,9 @@ static int blkdev_open(struct inode *inode, struct file *filp)
        if ((filp->f_flags & O_ACCMODE) == 3)
                filp->f_mode |= FMODE_WRITE_IOCTL;
 
-       bdev = blkdev_get_by_dev(inode->i_rdev, filp->f_mode, filp, NULL);
+       bdev = blkdev_get_by_dev(inode->i_rdev, filp->f_mode,
+                                (filp->f_mode & FMODE_EXCL) ? filp : NULL,
+                                NULL);
        if (IS_ERR(bdev))
                return PTR_ERR(bdev);
 
@@ -504,7 +506,7 @@ static int blkdev_release(struct inode *inode, struct file *filp)
 {
        struct block_device *bdev = filp->private_data;
 
-       blkdev_put(bdev, filp->f_mode);
+       blkdev_put(bdev, (filp->f_mode & FMODE_EXCL) ? filp : NULL);
        return 0;
 }
 
index 4e5fd6aaa883fdba483e2789829d54646bc0874f..b56f8b5c88b3e3691e57046dc532b946f33e1519 100644 (file)
@@ -365,12 +365,11 @@ int disk_scan_partitions(struct gendisk *disk, fmode_t mode)
        }
 
        set_bit(GD_NEED_PART_SCAN, &disk->state);
-       bdev = blkdev_get_by_dev(disk_devt(disk), mode & ~FMODE_EXCL, NULL,
-                                NULL);
+       bdev = blkdev_get_by_dev(disk_devt(disk), mode, NULL, NULL);
        if (IS_ERR(bdev))
                ret =  PTR_ERR(bdev);
        else
-               blkdev_put(bdev, mode & ~FMODE_EXCL);
+               blkdev_put(bdev, NULL);
 
        /*
         * If blkdev_get_by_dev() failed early, GD_NEED_PART_SCAN is still set,
index c7d7d4345edb4f5b7b72dea382459b4c9db680fb..b39bd5b41ee49264b1af0f13d6b6bb07f557962d 100644 (file)
@@ -454,11 +454,10 @@ static int blkdev_bszset(struct block_device *bdev, fmode_t mode,
        if (mode & FMODE_EXCL)
                return set_blocksize(bdev, n);
 
-       if (IS_ERR(blkdev_get_by_dev(bdev->bd_dev, mode | FMODE_EXCL, &bdev,
-                       NULL)))
+       if (IS_ERR(blkdev_get_by_dev(bdev->bd_dev, mode, &bdev, NULL)))
                return -EBUSY;
        ret = set_blocksize(bdev, n);
-       blkdev_put(bdev, mode | FMODE_EXCL);
+       blkdev_put(bdev, &bdev);
 
        return ret;
 }
index cab59dab3410aa96a61de1ca731844ea9d0f305f..10b1e5171332f761314807246d382a7388daba76 100644 (file)
@@ -1640,8 +1640,7 @@ static struct block_device *open_backing_dev(struct drbd_device *device,
        struct block_device *bdev;
        int err = 0;
 
-       bdev = blkdev_get_by_path(bdev_path,
-                                 FMODE_READ | FMODE_WRITE | FMODE_EXCL,
+       bdev = blkdev_get_by_path(bdev_path, FMODE_READ | FMODE_WRITE,
                                  claim_ptr, NULL);
        if (IS_ERR(bdev)) {
                drbd_err(device, "open(\"%s\") failed with %ld\n",
@@ -1654,7 +1653,7 @@ static struct block_device *open_backing_dev(struct drbd_device *device,
 
        err = bd_link_disk_holder(bdev, device->vdisk);
        if (err) {
-               blkdev_put(bdev, FMODE_READ | FMODE_WRITE | FMODE_EXCL);
+               blkdev_put(bdev, claim_ptr);
                drbd_err(device, "bd_link_disk_holder(\"%s\", ...) failed with %d\n",
                                bdev_path, err);
                bdev = ERR_PTR(err);
@@ -1696,13 +1695,13 @@ static int open_backing_devices(struct drbd_device *device,
 }
 
 static void close_backing_dev(struct drbd_device *device, struct block_device *bdev,
-       bool do_bd_unlink)
+               void *claim_ptr, bool do_bd_unlink)
 {
        if (!bdev)
                return;
        if (do_bd_unlink)
                bd_unlink_disk_holder(bdev, device->vdisk);
-       blkdev_put(bdev, FMODE_READ | FMODE_WRITE | FMODE_EXCL);
+       blkdev_put(bdev, claim_ptr);
 }
 
 void drbd_backing_dev_free(struct drbd_device *device, struct drbd_backing_dev *ldev)
@@ -1710,8 +1709,11 @@ void drbd_backing_dev_free(struct drbd_device *device, struct drbd_backing_dev *
        if (ldev == NULL)
                return;
 
-       close_backing_dev(device, ldev->md_bdev, ldev->md_bdev != ldev->backing_bdev);
-       close_backing_dev(device, ldev->backing_bdev, true);
+       close_backing_dev(device, ldev->md_bdev,
+                         ldev->md.meta_dev_idx < 0 ?
+                               (void *)device : (void *)drbd_m_holder,
+                         ldev->md_bdev != ldev->backing_bdev);
+       close_backing_dev(device, ldev->backing_bdev, device, true);
 
        kfree(ldev->disk_conf);
        kfree(ldev);
@@ -2127,8 +2129,11 @@ int drbd_adm_attach(struct sk_buff *skb, struct genl_info *info)
  fail:
        conn_reconfig_done(connection);
        if (nbc) {
-               close_backing_dev(device, nbc->md_bdev, nbc->md_bdev != nbc->backing_bdev);
-               close_backing_dev(device, nbc->backing_bdev, true);
+               close_backing_dev(device, nbc->md_bdev,
+                         nbc->disk_conf->meta_dev_idx < 0 ?
+                               (void *)device : (void *)drbd_m_holder,
+                         nbc->md_bdev != nbc->backing_bdev);
+               close_backing_dev(device, nbc->backing_bdev, device, true);
                kfree(nbc);
        }
        kfree(new_disk_conf);
index 7bfc058cb66504b1445e8e286a0db335a5e75ea7..c3299e49edd5ef1e1620471468d81045fe4d6b4d 100644 (file)
@@ -2167,8 +2167,7 @@ static int pkt_open_dev(struct pktcdvd_device *pd, fmode_t write)
         * to read/write from/to it. It is already opened in O_NONBLOCK mode
         * so open should not fail.
         */
-       bdev = blkdev_get_by_dev(pd->bdev->bd_dev, FMODE_READ | FMODE_EXCL, pd,
-                                NULL);
+       bdev = blkdev_get_by_dev(pd->bdev->bd_dev, FMODE_READ, pd, NULL);
        if (IS_ERR(bdev)) {
                ret = PTR_ERR(bdev);
                goto out;
@@ -2215,7 +2214,7 @@ static int pkt_open_dev(struct pktcdvd_device *pd, fmode_t write)
        return 0;
 
 out_putdev:
-       blkdev_put(bdev, FMODE_READ | FMODE_EXCL);
+       blkdev_put(bdev, pd);
 out:
        return ret;
 }
@@ -2234,7 +2233,7 @@ static void pkt_release_dev(struct pktcdvd_device *pd, int flush)
        pkt_lock_door(pd, 0);
 
        pkt_set_speed(pd, MAX_SPEED, MAX_SPEED);
-       blkdev_put(pd->bdev, FMODE_READ | FMODE_EXCL);
+       blkdev_put(pd->bdev, pd);
 
        pkt_shrink_pktlist(pd);
 }
@@ -2520,7 +2519,7 @@ static int pkt_new_dev(struct pktcdvd_device *pd, dev_t dev)
                return PTR_ERR(bdev);
        sdev = scsi_device_from_queue(bdev->bd_disk->queue);
        if (!sdev) {
-               blkdev_put(bdev, FMODE_READ | FMODE_NDELAY);
+               blkdev_put(bdev, NULL);
                return -EINVAL;
        }
        put_device(&sdev->sdev_gendev);
@@ -2545,7 +2544,7 @@ static int pkt_new_dev(struct pktcdvd_device *pd, dev_t dev)
        return 0;
 
 out_mem:
-       blkdev_put(bdev, FMODE_READ | FMODE_NDELAY);
+       blkdev_put(bdev, NULL);
        /* This is safe: open() is still holding a reference. */
        module_put(THIS_MODULE);
        return -ENOMEM;
@@ -2751,7 +2750,7 @@ static int pkt_remove_dev(dev_t pkt_dev)
        pkt_debugfs_dev_remove(pd);
        pkt_sysfs_dev_remove(pd);
 
-       blkdev_put(pd->bdev, FMODE_READ | FMODE_NDELAY);
+       blkdev_put(pd->bdev, NULL);
 
        remove_proc_entry(pd->disk->disk_name, pkt_proc);
        dev_notice(ddev, "writer unmapped\n");
index a92a4289d0eccb4c2dd52db71996e4c802b7b176..a909f8763ce7ed9bd87cf229c87ce58659680415 100644 (file)
@@ -219,7 +219,7 @@ void rnbd_destroy_sess_dev(struct rnbd_srv_sess_dev *sess_dev, bool keep_id)
        rnbd_put_sess_dev(sess_dev);
        wait_for_completion(&dc); /* wait for inflights to drop to zero */
 
-       blkdev_put(sess_dev->bdev, sess_dev->open_flags);
+       blkdev_put(sess_dev->bdev, NULL);
        mutex_lock(&sess_dev->dev->lock);
        list_del(&sess_dev->dev_list);
        if (sess_dev->open_flags & FMODE_WRITE)
@@ -791,7 +791,7 @@ srv_dev_put:
        }
        rnbd_put_srv_dev(srv_dev);
 blkdev_put:
-       blkdev_put(bdev, open_flags);
+       blkdev_put(bdev, NULL);
 free_path:
        kfree(full_path);
 reject:
index 43b36da9b3544d72a0cfe9191896581d2326d580..141b60aad57038262432c652223e232bb07a97df 100644 (file)
@@ -473,7 +473,7 @@ static void xenvbd_sysfs_delif(struct xenbus_device *dev)
 static void xen_vbd_free(struct xen_vbd *vbd)
 {
        if (vbd->bdev)
-               blkdev_put(vbd->bdev, vbd->readonly ? FMODE_READ : FMODE_WRITE);
+               blkdev_put(vbd->bdev, NULL);
        vbd->bdev = NULL;
 }
 
index f5644c6060407056594b3ed7e768d17093cac95f..21615d67a9bd6662f0c0ee2298b446c8365e5261 100644 (file)
@@ -420,7 +420,7 @@ static void reset_bdev(struct zram *zram)
                return;
 
        bdev = zram->bdev;
-       blkdev_put(bdev, FMODE_READ|FMODE_WRITE|FMODE_EXCL);
+       blkdev_put(bdev, zram);
        /* hope filp_close flush all of IO */
        filp_close(zram->backing_dev, NULL);
        zram->backing_dev = NULL;
@@ -507,8 +507,8 @@ static ssize_t backing_dev_store(struct device *dev,
                goto out;
        }
 
-       bdev = blkdev_get_by_dev(inode->i_rdev,
-                       FMODE_READ | FMODE_WRITE | FMODE_EXCL, zram, NULL);
+       bdev = blkdev_get_by_dev(inode->i_rdev, FMODE_READ | FMODE_WRITE, zram,
+                                NULL);
        if (IS_ERR(bdev)) {
                err = PTR_ERR(bdev);
                bdev = NULL;
@@ -539,7 +539,7 @@ out:
        kvfree(bitmap);
 
        if (bdev)
-               blkdev_put(bdev, FMODE_READ | FMODE_WRITE | FMODE_EXCL);
+               blkdev_put(bdev, zram);
 
        if (backing_dev)
                filp_close(backing_dev, NULL);
index 4a2aed047aec1216ae66ab0c016efb90a843143d..7022fea396f25eeb285c81761788f66f3194e5db 100644 (file)
@@ -1369,7 +1369,7 @@ static void cached_dev_free(struct closure *cl)
                put_page(virt_to_page(dc->sb_disk));
 
        if (!IS_ERR_OR_NULL(dc->bdev))
-               blkdev_put(dc->bdev, FMODE_READ|FMODE_WRITE|FMODE_EXCL);
+               blkdev_put(dc->bdev, bcache_kobj);
 
        wake_up(&unregister_wait);
 
@@ -2218,7 +2218,7 @@ void bch_cache_release(struct kobject *kobj)
                put_page(virt_to_page(ca->sb_disk));
 
        if (!IS_ERR_OR_NULL(ca->bdev))
-               blkdev_put(ca->bdev, FMODE_READ|FMODE_WRITE|FMODE_EXCL);
+               blkdev_put(ca->bdev, bcache_kobj);
 
        kfree(ca);
        module_put(THIS_MODULE);
@@ -2359,7 +2359,7 @@ static int register_cache(struct cache_sb *sb, struct cache_sb_disk *sb_disk,
                 * call blkdev_put() to bdev in bch_cache_release(). So we
                 * explicitly call blkdev_put() here.
                 */
-               blkdev_put(bdev, FMODE_READ|FMODE_WRITE|FMODE_EXCL);
+               blkdev_put(bdev, bcache_kobj);
                if (ret == -ENOMEM)
                        err = "cache_alloc(): -ENOMEM";
                else if (ret == -EPERM)
@@ -2461,7 +2461,7 @@ static void register_bdev_worker(struct work_struct *work)
        if (!dc) {
                fail = true;
                put_page(virt_to_page(args->sb_disk));
-               blkdev_put(args->bdev, FMODE_READ | FMODE_WRITE | FMODE_EXCL);
+               blkdev_put(args->bdev, bcache_kobj);
                goto out;
        }
 
@@ -2491,7 +2491,7 @@ static void register_cache_worker(struct work_struct *work)
        if (!ca) {
                fail = true;
                put_page(virt_to_page(args->sb_disk));
-               blkdev_put(args->bdev, FMODE_READ | FMODE_WRITE | FMODE_EXCL);
+               blkdev_put(args->bdev, bcache_kobj);
                goto out;
        }
 
@@ -2558,8 +2558,7 @@ static ssize_t register_bcache(struct kobject *k, struct kobj_attribute *attr,
 
        ret = -EINVAL;
        err = "failed to open device";
-       bdev = blkdev_get_by_path(strim(path),
-                                 FMODE_READ|FMODE_WRITE|FMODE_EXCL,
+       bdev = blkdev_get_by_path(strim(path), FMODE_READ | FMODE_WRITE,
                                  bcache_kobj, NULL);
        if (IS_ERR(bdev)) {
                if (bdev == ERR_PTR(-EBUSY)) {
@@ -2648,7 +2647,7 @@ async_done:
 out_put_sb_page:
        put_page(virt_to_page(sb_disk));
 out_blkdev_put:
-       blkdev_put(bdev, FMODE_READ | FMODE_WRITE | FMODE_EXCL);
+       blkdev_put(bdev, register_bcache);
 out_free_sb:
        kfree(sb);
 out_free_path:
index 246b8f028a98f4ebaf2c785275da54882a58a539..b16e37362c5a012dcad19cc6c4cd5f0ab02e7fa1 100644 (file)
@@ -746,7 +746,7 @@ static struct table_device *open_table_device(struct mapped_device *md,
                return ERR_PTR(-ENOMEM);
        refcount_set(&td->count, 1);
 
-       bdev = blkdev_get_by_dev(dev, mode | FMODE_EXCL, _dm_claim_ptr, NULL);
+       bdev = blkdev_get_by_dev(dev, mode, _dm_claim_ptr, NULL);
        if (IS_ERR(bdev)) {
                r = PTR_ERR(bdev);
                goto out_free_td;
@@ -771,7 +771,7 @@ static struct table_device *open_table_device(struct mapped_device *md,
        return td;
 
 out_blkdev_put:
-       blkdev_put(bdev, mode | FMODE_EXCL);
+       blkdev_put(bdev, _dm_claim_ptr);
 out_free_td:
        kfree(td);
        return ERR_PTR(r);
@@ -784,7 +784,7 @@ static void close_table_device(struct table_device *td, struct mapped_device *md
 {
        if (md->disk->slave_dir)
                bd_unlink_disk_holder(td->dm_dev.bdev, md->disk);
-       blkdev_put(td->dm_dev.bdev, td->dm_dev.mode | FMODE_EXCL);
+       blkdev_put(td->dm_dev.bdev, _dm_claim_ptr);
        put_dax(td->dm_dev.dax_dev);
        list_del(&td->list);
        kfree(td);
index 159197dd7b6de1847f60eef3dec72ec7b38e629f..dad4a5539f9f681ba9b56e4565ed3764c75ff16a 100644 (file)
@@ -2449,7 +2449,10 @@ static void rdev_delayed_delete(struct work_struct *ws)
 
 void md_autodetect_dev(dev_t dev);
 
-static void export_rdev(struct md_rdev *rdev)
+/* just for claiming the bdev */
+static struct md_rdev claim_rdev;
+
+static void export_rdev(struct md_rdev *rdev, struct mddev *mddev)
 {
        pr_debug("md: export_rdev(%pg)\n", rdev->bdev);
        md_rdev_clear(rdev);
@@ -2457,7 +2460,7 @@ static void export_rdev(struct md_rdev *rdev)
        if (test_bit(AutoDetected, &rdev->flags))
                md_autodetect_dev(rdev->bdev->bd_dev);
 #endif
-       blkdev_put(rdev->bdev, FMODE_READ | FMODE_WRITE | FMODE_EXCL);
+       blkdev_put(rdev->bdev, mddev->major_version == -2 ? &claim_rdev : rdev);
        rdev->bdev = NULL;
        kobject_put(&rdev->kobj);
 }
@@ -2485,7 +2488,7 @@ static void md_kick_rdev_from_array(struct md_rdev *rdev)
        INIT_WORK(&rdev->del_work, rdev_delayed_delete);
        kobject_get(&rdev->kobj);
        queue_work(md_rdev_misc_wq, &rdev->del_work);
-       export_rdev(rdev);
+       export_rdev(rdev, rdev->mddev);
 }
 
 static void export_array(struct mddev *mddev)
@@ -3612,6 +3615,7 @@ int md_rdev_init(struct md_rdev *rdev)
        return badblocks_init(&rdev->badblocks, 0);
 }
 EXPORT_SYMBOL_GPL(md_rdev_init);
+
 /*
  * Import a device. If 'super_format' >= 0, then sanity check the superblock
  *
@@ -3624,7 +3628,6 @@ EXPORT_SYMBOL_GPL(md_rdev_init);
  */
 static struct md_rdev *md_import_device(dev_t newdev, int super_format, int super_minor)
 {
-       static struct md_rdev claim_rdev; /* just for claiming the bdev */
        struct md_rdev *rdev;
        sector_t size;
        int err;
@@ -3640,8 +3643,7 @@ static struct md_rdev *md_import_device(dev_t newdev, int super_format, int supe
        if (err)
                goto out_clear_rdev;
 
-       rdev->bdev = blkdev_get_by_dev(newdev,
-                       FMODE_READ | FMODE_WRITE | FMODE_EXCL,
+       rdev->bdev = blkdev_get_by_dev(newdev, FMODE_READ | FMODE_WRITE,
                        super_format == -2 ? &claim_rdev : rdev, NULL);
        if (IS_ERR(rdev->bdev)) {
                pr_warn("md: could not open device unknown-block(%u,%u).\n",
@@ -3679,7 +3681,7 @@ static struct md_rdev *md_import_device(dev_t newdev, int super_format, int supe
        return rdev;
 
 out_blkdev_put:
-       blkdev_put(rdev->bdev, FMODE_READ | FMODE_WRITE | FMODE_EXCL);
+       blkdev_put(rdev->bdev, super_format == -2 ? &claim_rdev : rdev);
 out_clear_rdev:
        md_rdev_clear(rdev);
 out_free_rdev:
@@ -4560,7 +4562,7 @@ new_dev_store(struct mddev *mddev, const char *buf, size_t len)
        err = bind_rdev_to_array(rdev, mddev);
  out:
        if (err)
-               export_rdev(rdev);
+               export_rdev(rdev, mddev);
        mddev_unlock(mddev);
        if (!err)
                md_new_event();
@@ -6498,7 +6500,7 @@ static void autorun_devices(int part)
                        rdev_for_each_list(rdev, tmp, &candidates) {
                                list_del_init(&rdev->same_set);
                                if (bind_rdev_to_array(rdev, mddev))
-                                       export_rdev(rdev);
+                                       export_rdev(rdev, mddev);
                        }
                        autorun_array(mddev);
                        mddev_unlock(mddev);
@@ -6508,7 +6510,7 @@ static void autorun_devices(int part)
                 */
                rdev_for_each_list(rdev, tmp, &candidates) {
                        list_del_init(&rdev->same_set);
-                       export_rdev(rdev);
+                       export_rdev(rdev, mddev);
                }
                mddev_put(mddev);
        }
@@ -6696,13 +6698,13 @@ int md_add_new_disk(struct mddev *mddev, struct mdu_disk_info_s *info)
                                pr_warn("md: %pg has different UUID to %pg\n",
                                        rdev->bdev,
                                        rdev0->bdev);
-                               export_rdev(rdev);
+                               export_rdev(rdev, mddev);
                                return -EINVAL;
                        }
                }
                err = bind_rdev_to_array(rdev, mddev);
                if (err)
-                       export_rdev(rdev);
+                       export_rdev(rdev, mddev);
                return err;
        }
 
@@ -6746,7 +6748,7 @@ int md_add_new_disk(struct mddev *mddev, struct mdu_disk_info_s *info)
                        /* This was a hot-add request, but events doesn't
                         * match, so reject it.
                         */
-                       export_rdev(rdev);
+                       export_rdev(rdev, mddev);
                        return -EINVAL;
                }
 
@@ -6772,7 +6774,7 @@ int md_add_new_disk(struct mddev *mddev, struct mdu_disk_info_s *info)
                                }
                        }
                        if (has_journal || mddev->bitmap) {
-                               export_rdev(rdev);
+                               export_rdev(rdev, mddev);
                                return -EBUSY;
                        }
                        set_bit(Journal, &rdev->flags);
@@ -6787,7 +6789,7 @@ int md_add_new_disk(struct mddev *mddev, struct mdu_disk_info_s *info)
                                /* --add initiated by this node */
                                err = md_cluster_ops->add_new_disk(mddev, rdev);
                                if (err) {
-                                       export_rdev(rdev);
+                                       export_rdev(rdev, mddev);
                                        return err;
                                }
                        }
@@ -6797,7 +6799,7 @@ int md_add_new_disk(struct mddev *mddev, struct mdu_disk_info_s *info)
                err = bind_rdev_to_array(rdev, mddev);
 
                if (err)
-                       export_rdev(rdev);
+                       export_rdev(rdev, mddev);
 
                if (mddev_is_clustered(mddev)) {
                        if (info->state & (1 << MD_DISK_CANDIDATE)) {
@@ -6860,7 +6862,7 @@ int md_add_new_disk(struct mddev *mddev, struct mdu_disk_info_s *info)
 
                err = bind_rdev_to_array(rdev, mddev);
                if (err) {
-                       export_rdev(rdev);
+                       export_rdev(rdev, mddev);
                        return err;
                }
        }
@@ -6985,7 +6987,7 @@ static int hot_add_disk(struct mddev *mddev, dev_t dev)
        return 0;
 
 abort_export:
-       export_rdev(rdev);
+       export_rdev(rdev, mddev);
        return err;
 }
 
index 218eb2af564a8121d6ec73331efa50a4358ad95e..44fc23af4c3f842df715173f9e8e90f72da17183 100644 (file)
@@ -209,7 +209,7 @@ static void block2mtd_free_device(struct block2mtd_dev *dev)
        if (dev->blkdev) {
                invalidate_mapping_pages(dev->blkdev->bd_inode->i_mapping,
                                        0, -1);
-               blkdev_put(dev->blkdev, FMODE_READ|FMODE_WRITE|FMODE_EXCL);
+               blkdev_put(dev->blkdev, NULL);
        }
 
        kfree(dev);
@@ -261,7 +261,7 @@ static struct block_device __ref *mdtblock_early_get_bdev(const char *devname,
 static struct block2mtd_dev *add_device(char *devname, int erase_size,
                char *label, int timeout)
 {
-       const fmode_t mode = FMODE_READ | FMODE_WRITE | FMODE_EXCL;
+       const fmode_t mode = FMODE_READ | FMODE_WRITE;
        struct block_device *bdev;
        struct block2mtd_dev *dev;
        char *name;
index 9b6d6d85c7254448215ccc208fdb4f298a7de545..65ed2d478fac89a8d48cb905a4c929f2f9a6dda4 100644 (file)
@@ -51,7 +51,7 @@ void nvmet_bdev_set_limits(struct block_device *bdev, struct nvme_id_ns *id)
 void nvmet_bdev_ns_disable(struct nvmet_ns *ns)
 {
        if (ns->bdev) {
-               blkdev_put(ns->bdev, FMODE_WRITE | FMODE_READ);
+               blkdev_put(ns->bdev, NULL);
                ns->bdev = NULL;
        }
 }
index f21198bc483e1afa3d5eee8df23ad03498bb5c3e..d2b27b84f854cc9ebf336f5ae009e0c019b1acf8 100644 (file)
@@ -179,7 +179,7 @@ void dasd_destroy_partitions(struct dasd_block *block)
        mutex_unlock(&bdev->bd_disk->open_mutex);
 
        /* Matching blkdev_put to the blkdev_get in dasd_scan_partitions. */
-       blkdev_put(bdev, FMODE_READ);
+       blkdev_put(bdev, NULL);
 }
 
 int dasd_gendisk_init(void)
index a5cbbefa78ee4e3cf045e49bc057b230a5827c9c..c62f961f46e378f2841671f200dc7ca3134b70e2 100644 (file)
@@ -108,7 +108,7 @@ static int iblock_configure_device(struct se_device *dev)
        pr_debug( "IBLOCK: Claiming struct block_device: %s\n",
                        ib_dev->ibd_udev_path);
 
-       mode = FMODE_READ|FMODE_EXCL;
+       mode = FMODE_READ;
        if (!ib_dev->ibd_readonly)
                mode |= FMODE_WRITE;
        else
@@ -175,7 +175,7 @@ static int iblock_configure_device(struct se_device *dev)
        return 0;
 
 out_blkdev_put:
-       blkdev_put(ib_dev->ibd_bd, FMODE_WRITE|FMODE_READ|FMODE_EXCL);
+       blkdev_put(ib_dev->ibd_bd, ib_dev);
 out_free_bioset:
        bioset_exit(&ib_dev->ibd_bio_set);
 out:
@@ -201,7 +201,7 @@ static void iblock_destroy_device(struct se_device *dev)
        struct iblock_dev *ib_dev = IBLOCK_DEV(dev);
 
        if (ib_dev->ibd_bd != NULL)
-               blkdev_put(ib_dev->ibd_bd, FMODE_WRITE|FMODE_READ|FMODE_EXCL);
+               blkdev_put(ib_dev->ibd_bd, ib_dev);
        bioset_exit(&ib_dev->ibd_bio_set);
 }
 
index e3494e036c6c85f69c5ad8caecc6fb3eb56ad721..da3b5512d7ae32ecbc6beb794e81a904e143a5f6 100644 (file)
@@ -366,8 +366,7 @@ static int pscsi_create_type_disk(struct se_device *dev, struct scsi_device *sd)
         * Claim exclusive struct block_device access to struct scsi_device
         * for TYPE_DISK and TYPE_ZBC using supplied udev_path
         */
-       bd = blkdev_get_by_path(dev->udev_path,
-                               FMODE_WRITE|FMODE_READ|FMODE_EXCL, pdv,
+       bd = blkdev_get_by_path(dev->udev_path, FMODE_WRITE | FMODE_READ, pdv,
                                NULL);
        if (IS_ERR(bd)) {
                pr_err("pSCSI: blkdev_get_by_path() failed\n");
@@ -378,7 +377,7 @@ static int pscsi_create_type_disk(struct se_device *dev, struct scsi_device *sd)
 
        ret = pscsi_add_device_to_list(dev, sd);
        if (ret) {
-               blkdev_put(pdv->pdv_bd, FMODE_WRITE|FMODE_READ|FMODE_EXCL);
+               blkdev_put(pdv->pdv_bd, pdv);
                scsi_device_put(sd);
                return ret;
        }
@@ -566,8 +565,7 @@ static void pscsi_destroy_device(struct se_device *dev)
                 */
                if ((sd->type == TYPE_DISK || sd->type == TYPE_ZBC) &&
                    pdv->pdv_bd) {
-                       blkdev_put(pdv->pdv_bd,
-                                  FMODE_WRITE|FMODE_READ|FMODE_EXCL);
+                       blkdev_put(pdv->pdv_bd, pdv);
                        pdv->pdv_bd = NULL;
                }
                /*
index 4de4984fa99ba320da5e5ed83c374428ba8aa34a..677e9d9e1527aa0c42622d551f08817dda699e6a 100644 (file)
@@ -257,7 +257,7 @@ static int btrfs_init_dev_replace_tgtdev(struct btrfs_fs_info *fs_info,
                return -EINVAL;
        }
 
-       bdev = blkdev_get_by_path(device_path, FMODE_WRITE | FMODE_EXCL,
+       bdev = blkdev_get_by_path(device_path, FMODE_WRITE,
                                  fs_info->bdev_holder, NULL);
        if (IS_ERR(bdev)) {
                btrfs_err(fs_info, "target device %s is invalid!", device_path);
@@ -315,7 +315,7 @@ static int btrfs_init_dev_replace_tgtdev(struct btrfs_fs_info *fs_info,
        device->bdev = bdev;
        set_bit(BTRFS_DEV_STATE_IN_FS_METADATA, &device->dev_state);
        set_bit(BTRFS_DEV_STATE_REPLACE_TGT, &device->dev_state);
-       device->mode = FMODE_EXCL;
+       device->holder = fs_info->bdev_holder;
        device->dev_stats_valid = 1;
        set_blocksize(device->bdev, BTRFS_BDEV_BLOCKSIZE);
        device->fs_devices = fs_devices;
@@ -334,7 +334,7 @@ static int btrfs_init_dev_replace_tgtdev(struct btrfs_fs_info *fs_info,
        return 0;
 
 error:
-       blkdev_put(bdev, FMODE_EXCL);
+       blkdev_put(bdev, fs_info->bdev_holder);
        return ret;
 }
 
index 2fa36f694daa53acd3a33e12c09e8df8210e5624..d99376a79ef43a9cc086fb054d4b1bb3c97bfa03 100644 (file)
@@ -2672,7 +2672,7 @@ static long btrfs_ioctl_rm_dev_v2(struct file *file, void __user *arg)
        struct btrfs_fs_info *fs_info = btrfs_sb(inode->i_sb);
        struct btrfs_ioctl_vol_args_v2 *vol_args;
        struct block_device *bdev = NULL;
-       fmode_t mode;
+       void *holder;
        int ret;
        bool cancel = false;
 
@@ -2709,7 +2709,7 @@ static long btrfs_ioctl_rm_dev_v2(struct file *file, void __user *arg)
                goto err_drop;
 
        /* Exclusive operation is now claimed */
-       ret = btrfs_rm_device(fs_info, &args, &bdev, &mode);
+       ret = btrfs_rm_device(fs_info, &args, &bdev, &holder);
 
        btrfs_exclop_finish(fs_info);
 
@@ -2724,7 +2724,7 @@ static long btrfs_ioctl_rm_dev_v2(struct file *file, void __user *arg)
 err_drop:
        mnt_drop_write_file(file);
        if (bdev)
-               blkdev_put(bdev, mode);
+               blkdev_put(bdev, holder);
 out:
        btrfs_put_dev_args_from_path(&args);
        kfree(vol_args);
@@ -2738,7 +2738,7 @@ static long btrfs_ioctl_rm_dev(struct file *file, void __user *arg)
        struct btrfs_fs_info *fs_info = btrfs_sb(inode->i_sb);
        struct btrfs_ioctl_vol_args *vol_args;
        struct block_device *bdev = NULL;
-       fmode_t mode;
+       void *holder;
        int ret;
        bool cancel = false;
 
@@ -2765,7 +2765,7 @@ static long btrfs_ioctl_rm_dev(struct file *file, void __user *arg)
        ret = exclop_start_or_cancel_reloc(fs_info, BTRFS_EXCLOP_DEV_REMOVE,
                                           cancel);
        if (ret == 0) {
-               ret = btrfs_rm_device(fs_info, &args, &bdev, &mode);
+               ret = btrfs_rm_device(fs_info, &args, &bdev, &holder);
                if (!ret)
                        btrfs_info(fs_info, "disk deleted %s", vol_args->name);
                btrfs_exclop_finish(fs_info);
@@ -2773,7 +2773,7 @@ static long btrfs_ioctl_rm_dev(struct file *file, void __user *arg)
 
        mnt_drop_write_file(file);
        if (bdev)
-               blkdev_put(bdev, mode);
+               blkdev_put(bdev, holder);
 out:
        btrfs_put_dev_args_from_path(&args);
        kfree(vol_args);
index 035868cee3ddc39e5b9c658dd4dade920101649a..7b12e05cdbf00bf521da35fcf6d1b600dc55e0f6 100644 (file)
@@ -507,14 +507,14 @@ btrfs_get_bdev_and_sb(const char *device_path, fmode_t flags, void *holder,
                sync_blockdev(*bdev);
        ret = set_blocksize(*bdev, BTRFS_BDEV_BLOCKSIZE);
        if (ret) {
-               blkdev_put(*bdev, flags);
+               blkdev_put(*bdev, holder);
                goto error;
        }
        invalidate_bdev(*bdev);
        *disk_super = btrfs_read_dev_super(*bdev);
        if (IS_ERR(*disk_super)) {
                ret = PTR_ERR(*disk_super);
-               blkdev_put(*bdev, flags);
+               blkdev_put(*bdev, holder);
                goto error;
        }
 
@@ -642,7 +642,7 @@ static int btrfs_open_one_device(struct btrfs_fs_devices *fs_devices,
 
        device->bdev = bdev;
        clear_bit(BTRFS_DEV_STATE_IN_FS_METADATA, &device->dev_state);
-       device->mode = flags;
+       device->holder = holder;
 
        fs_devices->open_devices++;
        if (test_bit(BTRFS_DEV_STATE_WRITEABLE, &device->dev_state) &&
@@ -656,7 +656,7 @@ static int btrfs_open_one_device(struct btrfs_fs_devices *fs_devices,
 
 error_free_page:
        btrfs_release_disk_super(disk_super);
-       blkdev_put(bdev, flags);
+       blkdev_put(bdev, holder);
 
        return -EINVAL;
 }
@@ -1057,7 +1057,7 @@ static void __btrfs_free_extra_devids(struct btrfs_fs_devices *fs_devices,
                        continue;
 
                if (device->bdev) {
-                       blkdev_put(device->bdev, device->mode);
+                       blkdev_put(device->bdev, device->holder);
                        device->bdev = NULL;
                        fs_devices->open_devices--;
                }
@@ -1103,7 +1103,7 @@ static void btrfs_close_bdev(struct btrfs_device *device)
                invalidate_bdev(device->bdev);
        }
 
-       blkdev_put(device->bdev, device->mode);
+       blkdev_put(device->bdev, device->holder);
 }
 
 static void btrfs_close_one_device(struct btrfs_device *device)
@@ -1213,8 +1213,6 @@ static int open_fs_devices(struct btrfs_fs_devices *fs_devices,
        struct btrfs_device *latest_dev = NULL;
        struct btrfs_device *tmp_device;
 
-       flags |= FMODE_EXCL;
-
        list_for_each_entry_safe(device, tmp_device, &fs_devices->devices,
                                 dev_list) {
                int ret;
@@ -1400,7 +1398,7 @@ struct btrfs_device *btrfs_scan_one_device(const char *path, fmode_t flags)
        btrfs_release_disk_super(disk_super);
 
 error_bdev_put:
-       blkdev_put(bdev, flags);
+       blkdev_put(bdev, NULL);
 
        return device;
 }
@@ -2087,7 +2085,7 @@ void btrfs_scratch_superblocks(struct btrfs_fs_info *fs_info,
 
 int btrfs_rm_device(struct btrfs_fs_info *fs_info,
                    struct btrfs_dev_lookup_args *args,
-                   struct block_device **bdev, fmode_t *mode)
+                   struct block_device **bdev, void **holder)
 {
        struct btrfs_trans_handle *trans;
        struct btrfs_device *device;
@@ -2226,7 +2224,7 @@ int btrfs_rm_device(struct btrfs_fs_info *fs_info,
        }
 
        *bdev = device->bdev;
-       *mode = device->mode;
+       *holder = device->holder;
        synchronize_rcu();
        btrfs_free_device(device);
 
@@ -2394,7 +2392,7 @@ int btrfs_get_dev_args_from_path(struct btrfs_fs_info *fs_info,
        else
                memcpy(args->fsid, disk_super->fsid, BTRFS_FSID_SIZE);
        btrfs_release_disk_super(disk_super);
-       blkdev_put(bdev, FMODE_READ);
+       blkdev_put(bdev, NULL);
        return 0;
 }
 
@@ -2627,7 +2625,7 @@ int btrfs_init_new_device(struct btrfs_fs_info *fs_info, const char *device_path
        if (sb_rdonly(sb) && !fs_devices->seeding)
                return -EROFS;
 
-       bdev = blkdev_get_by_path(device_path, FMODE_WRITE | FMODE_EXCL,
+       bdev = blkdev_get_by_path(device_path, FMODE_WRITE,
                                  fs_info->bdev_holder, NULL);
        if (IS_ERR(bdev))
                return PTR_ERR(bdev);
@@ -2690,7 +2688,7 @@ int btrfs_init_new_device(struct btrfs_fs_info *fs_info, const char *device_path
        device->commit_total_bytes = device->total_bytes;
        set_bit(BTRFS_DEV_STATE_IN_FS_METADATA, &device->dev_state);
        clear_bit(BTRFS_DEV_STATE_REPLACE_TGT, &device->dev_state);
-       device->mode = FMODE_EXCL;
+       device->holder = fs_info->bdev_holder;
        device->dev_stats_valid = 1;
        set_blocksize(device->bdev, BTRFS_BDEV_BLOCKSIZE);
 
@@ -2848,7 +2846,7 @@ error_free_zone:
 error_free_device:
        btrfs_free_device(device);
 error:
-       blkdev_put(bdev, FMODE_EXCL);
+       blkdev_put(bdev, fs_info->bdev_holder);
        if (locked) {
                mutex_unlock(&uuid_mutex);
                up_write(&sb->s_umount);
index eb97a397b3c3fb771ef3e0459baa79e14b618bcb..840a8df399072cabfbf9eaedd8c5e40bad6bf519 100644 (file)
@@ -94,8 +94,8 @@ struct btrfs_device {
 
        struct btrfs_zoned_device_info *zone_info;
 
-       /* the mode sent to blkdev_get */
-       fmode_t mode;
+       /* block device holder for blkdev_get/put */
+       void *holder;
 
        /*
         * Device's major-minor number. Must be set even if the device is not
@@ -619,7 +619,7 @@ void btrfs_put_dev_args_from_path(struct btrfs_dev_lookup_args *args);
 void btrfs_free_device(struct btrfs_device *device);
 int btrfs_rm_device(struct btrfs_fs_info *fs_info,
                    struct btrfs_dev_lookup_args *args,
-                   struct block_device **bdev, fmode_t *mode);
+                   struct block_device **bdev, void **holder);
 void __exit btrfs_cleanup_fs_uuids(void);
 int btrfs_num_copies(struct btrfs_fs_info *fs_info, u64 logical, u64 len);
 int btrfs_grow_device(struct btrfs_trans_handle *trans,
index 6c263e9cd38b2a43f138eed0683640f62ba15cf5..54dba967a2d44571ff12ce15936b044c36cc3c08 100644 (file)
@@ -19,6 +19,7 @@
 #include <trace/events/erofs.h>
 
 static struct kmem_cache *erofs_inode_cachep __read_mostly;
+struct file_system_type erofs_fs_type;
 
 void _erofs_err(struct super_block *sb, const char *function,
                const char *fmt, ...)
@@ -253,8 +254,8 @@ static int erofs_init_device(struct erofs_buf *buf, struct super_block *sb,
                        return PTR_ERR(fscache);
                dif->fscache = fscache;
        } else if (!sbi->devs->flatdev) {
-               bdev = blkdev_get_by_path(dif->path, FMODE_READ | FMODE_EXCL,
-                                         sb->s_type, NULL);
+               bdev = blkdev_get_by_path(dif->path, FMODE_READ, sb->s_type,
+                                         NULL);
                if (IS_ERR(bdev))
                        return PTR_ERR(bdev);
                dif->bdev = bdev;
@@ -877,7 +878,7 @@ static int erofs_release_device_info(int id, void *ptr, void *data)
 
        fs_put_dax(dif->dax_dev, NULL);
        if (dif->bdev)
-               blkdev_put(dif->bdev, FMODE_READ | FMODE_EXCL);
+               blkdev_put(dif->bdev, &erofs_fs_type);
        erofs_fscache_unregister_cookie(dif->fscache);
        dif->fscache = NULL;
        kfree(dif->path);
index 9070ea9154d7276f58620eaeb0916e2afa5e23cb..92dd699139a3f76f2c3c396bef48cbc8c11d8a33 100644 (file)
@@ -1112,7 +1112,7 @@ static struct block_device *ext4_blkdev_get(dev_t dev, struct super_block *sb)
 {
        struct block_device *bdev;
 
-       bdev = blkdev_get_by_dev(dev, FMODE_READ|FMODE_WRITE|FMODE_EXCL, sb,
+       bdev = blkdev_get_by_dev(dev, FMODE_READ | FMODE_WRITE, sb,
                                 &ext4_holder_ops);
        if (IS_ERR(bdev))
                goto fail;
@@ -1128,17 +1128,12 @@ fail:
 /*
  * Release the journal device
  */
-static void ext4_blkdev_put(struct block_device *bdev)
-{
-       blkdev_put(bdev, FMODE_READ|FMODE_WRITE|FMODE_EXCL);
-}
-
 static void ext4_blkdev_remove(struct ext4_sb_info *sbi)
 {
        struct block_device *bdev;
        bdev = sbi->s_journal_bdev;
        if (bdev) {
-               ext4_blkdev_put(bdev);
+               blkdev_put(bdev, sbi->s_es);
                sbi->s_journal_bdev = NULL;
        }
 }
@@ -5915,7 +5910,7 @@ static journal_t *ext4_get_dev_journal(struct super_block *sb,
 out_journal:
        jbd2_journal_destroy(journal);
 out_bdev:
-       ext4_blkdev_put(bdev);
+       blkdev_put(bdev, sb);
        return NULL;
 }
 
index 7c34ab082f13822a2b0dbe7a99e9fa905bf2a781..a5adb1d316e33111f22b079208950fc5ccfa7dc0 100644 (file)
@@ -1538,7 +1538,7 @@ static void destroy_device_list(struct f2fs_sb_info *sbi)
        int i;
 
        for (i = 0; i < sbi->s_ndevs; i++) {
-               blkdev_put(FDEV(i).bdev, FMODE_EXCL);
+               blkdev_put(FDEV(i).bdev, sbi->sb->s_type);
 #ifdef CONFIG_BLK_DEV_ZONED
                kvfree(FDEV(i).blkz_seq);
 #endif
index 46d393c8088a7461c7eae7ff67b93fd581638f02..82f70d46f4e54499c06fb9f2ddcbf4a1a74d4b93 100644 (file)
@@ -1100,7 +1100,7 @@ int lmLogOpen(struct super_block *sb)
         * file systems to log may have n-to-1 relationship;
         */
 
-       bdev = blkdev_get_by_dev(sbi->logdev, FMODE_READ|FMODE_WRITE|FMODE_EXCL,
+       bdev = blkdev_get_by_dev(sbi->logdev, FMODE_READ | FMODE_WRITE,
                                 log, NULL);
        if (IS_ERR(bdev)) {
                rc = PTR_ERR(bdev);
@@ -1141,7 +1141,7 @@ journal_found:
        lbmLogShutdown(log);
 
       close:           /* close external log device */
-       blkdev_put(bdev, FMODE_READ|FMODE_WRITE|FMODE_EXCL);
+       blkdev_put(bdev, log);
 
       free:            /* free log descriptor */
        mutex_unlock(&jfs_log_mutex);
@@ -1485,7 +1485,7 @@ int lmLogClose(struct super_block *sb)
        bdev = log->bdev;
        rc = lmLogShutdown(log);
 
-       blkdev_put(bdev, FMODE_READ|FMODE_WRITE|FMODE_EXCL);
+       blkdev_put(bdev, log);
 
        kfree(log);
 
index 38b066ca699ed706897679a886dbb749bbcbfc41..9be7f958f60e4533846503710511237d7f442f40 100644 (file)
@@ -35,7 +35,7 @@ bl_free_device(struct pnfs_block_dev *dev)
                }
 
                if (dev->bdev)
-                       blkdev_put(dev->bdev, FMODE_READ | FMODE_WRITE);
+                       blkdev_put(dev->bdev, NULL);
        }
 }
 
@@ -374,7 +374,7 @@ bl_parse_scsi(struct nfs_server *server, struct pnfs_block_dev *d,
        return 0;
 
 out_blkdev_put:
-       blkdev_put(d->bdev, FMODE_READ | FMODE_WRITE);
+       blkdev_put(d->bdev, NULL);
        return error;
 }
 
index 91bfbd973d1d5301bd1b37b524b4d2ea06d739cd..61d5e79a5e81df3c254e436155a8018123de2f21 100644 (file)
@@ -1278,7 +1278,7 @@ nilfs_mount(struct file_system_type *fs_type, int flags,
 {
        struct nilfs_super_data sd;
        struct super_block *s;
-       fmode_t mode = FMODE_READ | FMODE_EXCL;
+       fmode_t mode = FMODE_READ;
        struct dentry *root_dentry;
        int err, s_new = false;
 
@@ -1357,7 +1357,7 @@ nilfs_mount(struct file_system_type *fs_type, int flags,
        }
 
        if (!s_new)
-               blkdev_put(sd.bdev, mode);
+               blkdev_put(sd.bdev, fs_type);
 
        return root_dentry;
 
@@ -1366,7 +1366,7 @@ nilfs_mount(struct file_system_type *fs_type, int flags,
 
  failed:
        if (!s_new)
-               blkdev_put(sd.bdev, mode);
+               blkdev_put(sd.bdev, fs_type);
        return ERR_PTR(err);
 }
 
index 6b13b8c3f2b8af08113c6885d9824d73d1f975bf..c6ae9aee01edb9c5819fc405c2291a885d5d8eef 100644 (file)
@@ -1503,7 +1503,7 @@ static void o2hb_region_release(struct config_item *item)
        }
 
        if (reg->hr_bdev)
-               blkdev_put(reg->hr_bdev, FMODE_READ|FMODE_WRITE);
+               blkdev_put(reg->hr_bdev, NULL);
 
        kfree(reg->hr_slots);
 
@@ -1893,7 +1893,7 @@ static ssize_t o2hb_region_dev_store(struct config_item *item,
 
 out3:
        if (ret < 0) {
-               blkdev_put(reg->hr_bdev, FMODE_READ | FMODE_WRITE);
+               blkdev_put(reg->hr_bdev, NULL);
                reg->hr_bdev = NULL;
        }
 out2:
index 5e4db9a0c8e5a31582ef1bd64a87f316350a1b03..905297ea55458d7f25da3dc41c8fadc1df3790c8 100644 (file)
@@ -2589,7 +2589,7 @@ static void release_journal_dev(struct super_block *super,
                               struct reiserfs_journal *journal)
 {
        if (journal->j_dev_bd != NULL) {
-               blkdev_put(journal->j_dev_bd, journal->j_dev_mode);
+               blkdev_put(journal->j_dev_bd, journal);
                journal->j_dev_bd = NULL;
        }
 }
@@ -2598,9 +2598,10 @@ static int journal_init_dev(struct super_block *super,
                            struct reiserfs_journal *journal,
                            const char *jdev_name)
 {
+       fmode_t blkdev_mode = FMODE_READ;
+       void *holder = journal;
        int result;
        dev_t jdev;
-       fmode_t blkdev_mode = FMODE_READ | FMODE_WRITE | FMODE_EXCL;
 
        result = 0;
 
@@ -2608,16 +2609,15 @@ static int journal_init_dev(struct super_block *super,
        jdev = SB_ONDISK_JOURNAL_DEVICE(super) ?
            new_decode_dev(SB_ONDISK_JOURNAL_DEVICE(super)) : super->s_dev;
 
-       if (bdev_read_only(super->s_bdev))
-               blkdev_mode = FMODE_READ;
+       if (!bdev_read_only(super->s_bdev))
+               blkdev_mode |= FMODE_WRITE;
 
        /* there is no "jdev" option and journal is on separate device */
        if ((!jdev_name || !jdev_name[0])) {
                if (jdev == super->s_dev)
-                       blkdev_mode &= ~FMODE_EXCL;
-               journal->j_dev_bd = blkdev_get_by_dev(jdev, blkdev_mode,
-                                                     journal, NULL);
-               journal->j_dev_mode = blkdev_mode;
+                       holder = NULL;
+               journal->j_dev_bd = blkdev_get_by_dev(jdev, blkdev_mode, holder,
+                                                     NULL);
                if (IS_ERR(journal->j_dev_bd)) {
                        result = PTR_ERR(journal->j_dev_bd);
                        journal->j_dev_bd = NULL;
@@ -2631,8 +2631,7 @@ static int journal_init_dev(struct super_block *super,
                return 0;
        }
 
-       journal->j_dev_mode = blkdev_mode;
-       journal->j_dev_bd = blkdev_get_by_path(jdev_name, blkdev_mode, journal,
+       journal->j_dev_bd = blkdev_get_by_path(jdev_name, blkdev_mode, holder,
                                               NULL);
        if (IS_ERR(journal->j_dev_bd)) {
                result = PTR_ERR(journal->j_dev_bd);
index 1bccf6a2e908fbb2771b7cdbdba7a147bb92e351..55e85256aae8346920eab917f6baf02258caa25d 100644 (file)
@@ -300,7 +300,6 @@ struct reiserfs_journal {
        struct reiserfs_journal_cnode *j_first;
 
        struct block_device *j_dev_bd;
-       fmode_t j_dev_mode;
 
        /* first block on s_dev of reserved area journal */
        int j_1st_reserved_block;
index f127589700ab25058ace28c3aba30d94aa2adf1f..8563794a8bc462cd485dd7a5f1c4ed242d6715e9 100644 (file)
@@ -1255,7 +1255,7 @@ int get_tree_bdev(struct fs_context *fc,
 {
        struct block_device *bdev;
        struct super_block *s;
-       fmode_t mode = FMODE_READ | FMODE_EXCL;
+       fmode_t mode = FMODE_READ;
        int error = 0;
 
        if (!(fc->sb_flags & SB_RDONLY))
@@ -1279,7 +1279,7 @@ int get_tree_bdev(struct fs_context *fc,
        if (bdev->bd_fsfreeze_count > 0) {
                mutex_unlock(&bdev->bd_fsfreeze_mutex);
                warnf(fc, "%pg: Can't mount, blockdev is frozen", bdev);
-               blkdev_put(bdev, mode);
+               blkdev_put(bdev, fc->fs_type);
                return -EBUSY;
        }
 
@@ -1288,7 +1288,7 @@ int get_tree_bdev(struct fs_context *fc,
        s = sget_fc(fc, test_bdev_super_fc, set_bdev_super_fc);
        mutex_unlock(&bdev->bd_fsfreeze_mutex);
        if (IS_ERR(s)) {
-               blkdev_put(bdev, mode);
+               blkdev_put(bdev, fc->fs_type);
                return PTR_ERR(s);
        }
 
@@ -1297,7 +1297,7 @@ int get_tree_bdev(struct fs_context *fc,
                if ((fc->sb_flags ^ s->s_flags) & SB_RDONLY) {
                        warnf(fc, "%pg: Can't mount, would change RO state", bdev);
                        deactivate_locked_super(s);
-                       blkdev_put(bdev, mode);
+                       blkdev_put(bdev, fc->fs_type);
                        return -EBUSY;
                }
 
@@ -1309,7 +1309,7 @@ int get_tree_bdev(struct fs_context *fc,
                 * holding an active reference.
                 */
                up_write(&s->s_umount);
-               blkdev_put(bdev, mode);
+               blkdev_put(bdev, fc->fs_type);
                down_write(&s->s_umount);
        } else {
                s->s_mode = mode;
@@ -1344,7 +1344,7 @@ struct dentry *mount_bdev(struct file_system_type *fs_type,
 {
        struct block_device *bdev;
        struct super_block *s;
-       fmode_t mode = FMODE_READ | FMODE_EXCL;
+       fmode_t mode = FMODE_READ;
        int error = 0;
 
        if (!(flags & SB_RDONLY))
@@ -1386,7 +1386,7 @@ struct dentry *mount_bdev(struct file_system_type *fs_type,
                 * holding an active reference.
                 */
                up_write(&s->s_umount);
-               blkdev_put(bdev, mode);
+               blkdev_put(bdev, fs_type);
                down_write(&s->s_umount);
        } else {
                s->s_mode = mode;
@@ -1409,7 +1409,7 @@ struct dentry *mount_bdev(struct file_system_type *fs_type,
 error_s:
        error = PTR_ERR(s);
 error_bdev:
-       blkdev_put(bdev, mode);
+       blkdev_put(bdev, fs_type);
 error:
        return ERR_PTR(error);
 }
@@ -1418,13 +1418,11 @@ EXPORT_SYMBOL(mount_bdev);
 void kill_block_super(struct super_block *sb)
 {
        struct block_device *bdev = sb->s_bdev;
-       fmode_t mode = sb->s_mode;
 
        bdev->bd_super = NULL;
        generic_shutdown_super(sb);
        sync_blockdev(bdev);
-       WARN_ON_ONCE(!(mode & FMODE_EXCL));
-       blkdev_put(bdev, mode | FMODE_EXCL);
+       blkdev_put(bdev, sb->s_type);
 }
 
 EXPORT_SYMBOL(kill_block_super);
index 1b4bd5c88f4a11aa42dd9a3f6a54ffbbcb0f662f..3b7cf8268057fe7a9dc89d78a45b02700ab88426 100644 (file)
@@ -396,8 +396,8 @@ xfs_blkdev_get(
 {
        int                     error = 0;
 
-       *bdevp = blkdev_get_by_path(name, FMODE_READ|FMODE_WRITE|FMODE_EXCL,
-                                   mp, &xfs_holder_ops);
+       *bdevp = blkdev_get_by_path(name, FMODE_READ | FMODE_WRITE, mp,
+                                   &xfs_holder_ops);
        if (IS_ERR(*bdevp)) {
                error = PTR_ERR(*bdevp);
                xfs_warn(mp, "Invalid device [%s], error=%d", name, error);
@@ -408,10 +408,11 @@ xfs_blkdev_get(
 
 STATIC void
 xfs_blkdev_put(
+       struct xfs_mount        *mp,
        struct block_device     *bdev)
 {
        if (bdev)
-               blkdev_put(bdev, FMODE_READ|FMODE_WRITE|FMODE_EXCL);
+               blkdev_put(bdev, mp);
 }
 
 STATIC void
@@ -422,13 +423,13 @@ xfs_close_devices(
                struct block_device *logdev = mp->m_logdev_targp->bt_bdev;
 
                xfs_free_buftarg(mp->m_logdev_targp);
-               xfs_blkdev_put(logdev);
+               xfs_blkdev_put(mp, logdev);
        }
        if (mp->m_rtdev_targp) {
                struct block_device *rtdev = mp->m_rtdev_targp->bt_bdev;
 
                xfs_free_buftarg(mp->m_rtdev_targp);
-               xfs_blkdev_put(rtdev);
+               xfs_blkdev_put(mp, rtdev);
        }
        xfs_free_buftarg(mp->m_ddev_targp);
 }
@@ -503,10 +504,10 @@ xfs_open_devices(
  out_free_ddev_targ:
        xfs_free_buftarg(mp->m_ddev_targp);
  out_close_rtdev:
-       xfs_blkdev_put(rtdev);
+       xfs_blkdev_put(mp, rtdev);
  out_close_logdev:
        if (logdev && logdev != ddev)
-               xfs_blkdev_put(logdev);
+               xfs_blkdev_put(mp, logdev);
        return error;
 }
 
index 25bdd0cc74dce4151dcc1025d53d05bdba4805c3..d5b99796f12c11a9e0f1b90dc73f6f35bc22488b 100644 (file)
@@ -1480,7 +1480,7 @@ struct block_device *blkdev_get_by_path(const char *path, fmode_t mode,
 int bd_prepare_to_claim(struct block_device *bdev, void *holder,
                const struct blk_holder_ops *hops);
 void bd_abort_claiming(struct block_device *bdev, void *holder);
-void blkdev_put(struct block_device *bdev, fmode_t mode);
+void blkdev_put(struct block_device *bdev, void *holder);
 
 /* just for blk-cgroup, don't use elsewhere */
 struct block_device *blkdev_get_no_open(dev_t dev);
index 7ae95ec72f990278d1c36da083864b79b45ca685..f62e89d0d9068ea8b154e946f6bd730888f197e7 100644 (file)
@@ -688,22 +688,18 @@ static int load_image_and_restore(bool snapshot_test)
 {
        int error;
        unsigned int flags;
-       fmode_t mode = FMODE_READ;
-
-       if (snapshot_test)
-               mode |= FMODE_EXCL;
 
        pm_pr_dbg("Loading hibernation image.\n");
 
        lock_device_hotplug();
        error = create_basic_memory_bitmaps();
        if (error) {
-               swsusp_close(mode);
+               swsusp_close(snapshot_test);
                goto Unlock;
        }
 
        error = swsusp_read(&flags);
-       swsusp_close(mode);
+       swsusp_close(snapshot_test);
        if (!error)
                error = hibernation_restore(flags & SF_PLATFORM_MODE);
 
@@ -956,7 +952,7 @@ static int software_resume(void)
        /* The snapshot device should not be opened while we're running */
        if (!hibernate_acquire()) {
                error = -EBUSY;
-               swsusp_close(FMODE_READ | FMODE_EXCL);
+               swsusp_close(false);
                goto Unlock;
        }
 
@@ -991,7 +987,7 @@ static int software_resume(void)
        pm_pr_dbg("Hibernation image not present or could not be loaded.\n");
        return error;
  Close_Finish:
-       swsusp_close(FMODE_READ | FMODE_EXCL);
+       swsusp_close(false);
        goto Finish;
 }
 
index 978189fcafd124d888f1ab025e5114f7cc3344b5..a8e0c44b804e6c45f84f7a802f7f572fc4211665 100644 (file)
@@ -177,7 +177,7 @@ int swsusp_check(bool snapshot_test);
 extern void swsusp_free(void);
 extern int swsusp_read(unsigned int *flags_p);
 extern int swsusp_write(unsigned int flags);
-extern void swsusp_close(fmode_t);
+void swsusp_close(bool snapshot_test);
 #ifdef CONFIG_SUSPEND
 extern int swsusp_unmark(void);
 #endif
index b03ff1a33c7f68d1a1107ff8bde61c3b8286e69d..cc9259307c942ac24d6013e2fafd7b8476936094 100644 (file)
@@ -363,7 +363,7 @@ static int swsusp_swap_check(void)
 
        res = set_blocksize(hib_resume_bdev, PAGE_SIZE);
        if (res < 0)
-               blkdev_put(hib_resume_bdev, FMODE_WRITE);
+               blkdev_put(hib_resume_bdev, NULL);
 
        return res;
 }
@@ -443,7 +443,7 @@ static int get_swap_writer(struct swap_map_handle *handle)
 err_rel:
        release_swap_writer(handle);
 err_close:
-       swsusp_close(FMODE_WRITE);
+       swsusp_close(false);
        return ret;
 }
 
@@ -508,7 +508,7 @@ static int swap_writer_finish(struct swap_map_handle *handle,
        if (error)
                free_all_swap_pages(root_swap);
        release_swap_writer(handle);
-       swsusp_close(FMODE_WRITE);
+       swsusp_close(false);
 
        return error;
 }
@@ -1518,14 +1518,11 @@ static void *swsusp_holder;
 
 int swsusp_check(bool snapshot_test)
 {
+       void *holder = snapshot_test ? &swsusp_holder : NULL;
        int error;
-       fmode_t mode = FMODE_READ;
 
-       if (snapshot_test)
-               mode |= FMODE_EXCL;
-
-       hib_resume_bdev = blkdev_get_by_dev(swsusp_resume_device,
-                                           mode, &swsusp_holder, NULL);
+       hib_resume_bdev = blkdev_get_by_dev(swsusp_resume_device, FMODE_READ,
+                                           holder, NULL);
        if (!IS_ERR(hib_resume_bdev)) {
                set_blocksize(hib_resume_bdev, PAGE_SIZE);
                clear_page(swsusp_header);
@@ -1552,7 +1549,7 @@ int swsusp_check(bool snapshot_test)
 
 put:
                if (error)
-                       blkdev_put(hib_resume_bdev, mode);
+                       blkdev_put(hib_resume_bdev, holder);
                else
                        pr_debug("Image signature found, resuming\n");
        } else {
@@ -1569,14 +1566,14 @@ put:
  *     swsusp_close - close swap device.
  */
 
-void swsusp_close(fmode_t mode)
+void swsusp_close(bool snapshot_test)
 {
        if (IS_ERR(hib_resume_bdev)) {
                pr_debug("Image device not initialised\n");
                return;
        }
 
-       blkdev_put(hib_resume_bdev, mode);
+       blkdev_put(hib_resume_bdev, snapshot_test ? &swsusp_holder : NULL);
 }
 
 /**
index cfbcf7d5705f5f26631c8b2fccd701f65ab3bf00..16554256be6554e0724d50fb9560cb9981555abd 100644 (file)
@@ -2539,7 +2539,7 @@ SYSCALL_DEFINE1(swapoff, const char __user *, specialfile)
                struct block_device *bdev = I_BDEV(inode);
 
                set_blocksize(bdev, old_block_size);
-               blkdev_put(bdev, FMODE_READ | FMODE_WRITE | FMODE_EXCL);
+               blkdev_put(bdev, p);
        }
 
        inode_lock(inode);
@@ -2770,8 +2770,7 @@ static int claim_swapfile(struct swap_info_struct *p, struct inode *inode)
 
        if (S_ISBLK(inode->i_mode)) {
                p->bdev = blkdev_get_by_dev(inode->i_rdev,
-                                  FMODE_READ | FMODE_WRITE | FMODE_EXCL, p,
-                                  NULL);
+                                  FMODE_READ | FMODE_WRITE, p, NULL);
                if (IS_ERR(p->bdev)) {
                        error = PTR_ERR(p->bdev);
                        p->bdev = NULL;
@@ -3222,7 +3221,7 @@ bad_swap:
        p->cluster_next_cpu = NULL;
        if (inode && S_ISBLK(inode->i_mode) && p->bdev) {
                set_blocksize(p->bdev, p->old_block_size);
-               blkdev_put(p->bdev, FMODE_READ | FMODE_WRITE | FMODE_EXCL);
+               blkdev_put(p->bdev, p);
        }
        inode = NULL;
        destroy_swap_extents(p);