aboutsummaryrefslogtreecommitdiffstats
path: root/drivers
diff options
context:
space:
mode:
authorTejun Heo <tj@kernel.org>2010-11-13 05:55:17 -0500
committerTejun Heo <tj@kernel.org>2010-11-13 05:55:17 -0500
commite525fd89d380c4a94c0d63913a1dd1a593ed25e7 (patch)
treed226ef40d3f99e42fcf272ad432585cbd641ebec /drivers
parente09b457bdb7e8d23fc54dcef0930ac697d8de895 (diff)
block: make blkdev_get/put() handle exclusive access
Over time, block layer has accumulated a set of APIs dealing with bdev open, close, claim and release. * blkdev_get/put() are the primary open and close functions. * bd_claim/release() deal with exclusive open. * open/close_bdev_exclusive() are combination of open and claim and the other way around, respectively. * bd_link/unlink_disk_holder() to create and remove holder/slave symlinks. * open_by_devnum() wraps bdget() + blkdev_get(). The interface is a bit confusing and the decoupling of open and claim makes it impossible to properly guarantee exclusive access as in-kernel open + claim sequence can disturb the existing exclusive open even before the block layer knows the current open if for another exclusive access. Reorganize the interface such that, * blkdev_get() is extended to include exclusive access management. @holder argument is added and, if is @FMODE_EXCL specified, it will gain exclusive access atomically w.r.t. other exclusive accesses. * blkdev_put() is similarly extended. It now takes @mode argument and if @FMODE_EXCL is set, it releases an exclusive access. Also, when the last exclusive claim is released, the holder/slave symlinks are removed automatically. * bd_claim/release() and close_bdev_exclusive() are no longer necessary and either made static or removed. * bd_link_disk_holder() remains the same but bd_unlink_disk_holder() is no longer necessary and removed. * open_bdev_exclusive() becomes a simple wrapper around lookup_bdev() and blkdev_get(). It also has an unexpected extra bdev_read_only() test which probably should be moved into blkdev_get(). * open_by_devnum() is modified to take @holder argument and pass it to blkdev_get(). Most of bdev open/close operations are unified into blkdev_get/put() and most exclusive accesses are tested atomically at the open time (as it should). This cleans up code and removes some, both valid and invalid, but unnecessary all the same, corner cases. open_bdev_exclusive() and open_by_devnum() can use further cleanup - rename to blkdev_get_by_path() and blkdev_get_by_devt() and drop special features. Well, let's leave them for another day. Most conversions are straight-forward. drbd conversion is a bit more involved as there was some reordering, but the logic should stay the same. Signed-off-by: Tejun Heo <tj@kernel.org> Acked-by: Neil Brown <neilb@suse.de> Acked-by: Ryusuke Konishi <konishi.ryusuke@lab.ntt.co.jp> Acked-by: Mike Snitzer <snitzer@redhat.com> Acked-by: Philipp Reisner <philipp.reisner@linbit.com> Cc: Peter Osterlund <petero2@telia.com> Cc: Martin Schwidefsky <schwidefsky@de.ibm.com> Cc: Heiko Carstens <heiko.carstens@de.ibm.com> Cc: Jan Kara <jack@suse.cz> Cc: Andrew Morton <akpm@linux-foundation.org> Cc: Andreas Dilger <adilger.kernel@dilger.ca> Cc: "Theodore Ts'o" <tytso@mit.edu> Cc: Mark Fasheh <mfasheh@suse.com> Cc: Joel Becker <joel.becker@oracle.com> Cc: Alex Elder <aelder@sgi.com> Cc: Christoph Hellwig <hch@infradead.org> Cc: dm-devel@redhat.com Cc: drbd-dev@lists.linbit.com Cc: Leo Chen <leochen@broadcom.com> Cc: Scott Branden <sbranden@broadcom.com> Cc: Chris Mason <chris.mason@oracle.com> Cc: Steven Whitehouse <swhiteho@redhat.com> Cc: Dave Kleikamp <shaggy@linux.vnet.ibm.com> Cc: Joern Engel <joern@logfs.org> Cc: reiserfs-devel@vger.kernel.org Cc: Alexander Viro <viro@zeniv.linux.org.uk>
Diffstat (limited to 'drivers')
-rw-r--r--drivers/block/drbd/drbd_int.h2
-rw-r--r--drivers/block/drbd/drbd_main.c7
-rw-r--r--drivers/block/drbd/drbd_nl.c103
-rw-r--r--drivers/block/pktcdvd.c22
-rw-r--r--drivers/char/raw.c14
-rw-r--r--drivers/md/dm-table.c15
-rw-r--r--drivers/md/md.c14
-rw-r--r--drivers/mtd/devices/block2mtd.c17
-rw-r--r--drivers/s390/block/dasd_genhd.c2
9 files changed, 61 insertions, 135 deletions
diff --git a/drivers/block/drbd/drbd_int.h b/drivers/block/drbd/drbd_int.h
index 9bdcf4393c0a..0590b9f67ec6 100644
--- a/drivers/block/drbd/drbd_int.h
+++ b/drivers/block/drbd/drbd_int.h
@@ -923,8 +923,6 @@ struct drbd_md {
923struct drbd_backing_dev { 923struct drbd_backing_dev {
924 struct block_device *backing_bdev; 924 struct block_device *backing_bdev;
925 struct block_device *md_bdev; 925 struct block_device *md_bdev;
926 struct file *lo_file;
927 struct file *md_file;
928 struct drbd_md md; 926 struct drbd_md md;
929 struct disk_conf dc; /* The user provided config... */ 927 struct disk_conf dc; /* The user provided config... */
930 sector_t known_size; /* last known size of that backing device */ 928 sector_t known_size; /* last known size of that backing device */
diff --git a/drivers/block/drbd/drbd_main.c b/drivers/block/drbd/drbd_main.c
index 25c7a73c5062..7ec1a82064a9 100644
--- a/drivers/block/drbd/drbd_main.c
+++ b/drivers/block/drbd/drbd_main.c
@@ -3361,11 +3361,8 @@ void drbd_free_bc(struct drbd_backing_dev *ldev)
3361 if (ldev == NULL) 3361 if (ldev == NULL)
3362 return; 3362 return;
3363 3363
3364 bd_release(ldev->backing_bdev); 3364 blkdev_put(ldev->backing_bdev, FMODE_READ | FMODE_WRITE | FMODE_EXCL);
3365 bd_release(ldev->md_bdev); 3365 blkdev_put(ldev->md_bdev, FMODE_READ | FMODE_WRITE | FMODE_EXCL);
3366
3367 fput(ldev->lo_file);
3368 fput(ldev->md_file);
3369 3366
3370 kfree(ldev); 3367 kfree(ldev);
3371} 3368}
diff --git a/drivers/block/drbd/drbd_nl.c b/drivers/block/drbd/drbd_nl.c
index 87925e97e613..fd0346090289 100644
--- a/drivers/block/drbd/drbd_nl.c
+++ b/drivers/block/drbd/drbd_nl.c
@@ -855,7 +855,7 @@ static int drbd_nl_disk_conf(struct drbd_conf *mdev, struct drbd_nl_cfg_req *nlp
855 sector_t max_possible_sectors; 855 sector_t max_possible_sectors;
856 sector_t min_md_device_sectors; 856 sector_t min_md_device_sectors;
857 struct drbd_backing_dev *nbc = NULL; /* new_backing_conf */ 857 struct drbd_backing_dev *nbc = NULL; /* new_backing_conf */
858 struct inode *inode, *inode2; 858 struct block_device *bdev;
859 struct lru_cache *resync_lru = NULL; 859 struct lru_cache *resync_lru = NULL;
860 union drbd_state ns, os; 860 union drbd_state ns, os;
861 unsigned int max_seg_s; 861 unsigned int max_seg_s;
@@ -902,46 +902,40 @@ static int drbd_nl_disk_conf(struct drbd_conf *mdev, struct drbd_nl_cfg_req *nlp
902 } 902 }
903 } 903 }
904 904
905 nbc->lo_file = filp_open(nbc->dc.backing_dev, O_RDWR, 0); 905 bdev = open_bdev_exclusive(nbc->dc.backing_dev,
906 if (IS_ERR(nbc->lo_file)) { 906 FMODE_READ | FMODE_WRITE, mdev);
907 if (IS_ERR(bdev)) {
907 dev_err(DEV, "open(\"%s\") failed with %ld\n", nbc->dc.backing_dev, 908 dev_err(DEV, "open(\"%s\") failed with %ld\n", nbc->dc.backing_dev,
908 PTR_ERR(nbc->lo_file)); 909 PTR_ERR(bdev));
909 nbc->lo_file = NULL;
910 retcode = ERR_OPEN_DISK; 910 retcode = ERR_OPEN_DISK;
911 goto fail; 911 goto fail;
912 } 912 }
913 nbc->backing_bdev = bdev;
913 914
914 inode = nbc->lo_file->f_dentry->d_inode; 915 /*
915 916 * meta_dev_idx >= 0: external fixed size, possibly multiple
916 if (!S_ISBLK(inode->i_mode)) { 917 * drbd sharing one meta device. TODO in that case, paranoia
917 retcode = ERR_DISK_NOT_BDEV; 918 * check that [md_bdev, meta_dev_idx] is not yet used by some
918 goto fail; 919 * other drbd minor! (if you use drbd.conf + drbdadm, that
919 } 920 * should check it for you already; but if you don't, or
920 921 * someone fooled it, we need to double check here)
921 nbc->md_file = filp_open(nbc->dc.meta_dev, O_RDWR, 0); 922 */
922 if (IS_ERR(nbc->md_file)) { 923 bdev = open_bdev_exclusive(nbc->dc.meta_dev,
924 FMODE_READ | FMODE_WRITE,
925 (nbc->dc.meta_dev_idx < 0) ?
926 (void *)mdev : (void *)drbd_m_holder);
927 if (IS_ERR(bdev)) {
923 dev_err(DEV, "open(\"%s\") failed with %ld\n", nbc->dc.meta_dev, 928 dev_err(DEV, "open(\"%s\") failed with %ld\n", nbc->dc.meta_dev,
924 PTR_ERR(nbc->md_file)); 929 PTR_ERR(bdev));
925 nbc->md_file = NULL;
926 retcode = ERR_OPEN_MD_DISK; 930 retcode = ERR_OPEN_MD_DISK;
927 goto fail; 931 goto fail;
928 } 932 }
933 nbc->md_bdev = bdev;
929 934
930 inode2 = nbc->md_file->f_dentry->d_inode; 935 if ((nbc->backing_bdev == nbc->md_bdev) !=
931 936 (nbc->dc.meta_dev_idx == DRBD_MD_INDEX_INTERNAL ||
932 if (!S_ISBLK(inode2->i_mode)) { 937 nbc->dc.meta_dev_idx == DRBD_MD_INDEX_FLEX_INT)) {
933 retcode = ERR_MD_NOT_BDEV; 938 retcode = ERR_MD_IDX_INVALID;
934 goto fail;
935 }
936
937 nbc->backing_bdev = inode->i_bdev;
938 if (bd_claim(nbc->backing_bdev, mdev)) {
939 printk(KERN_ERR "drbd: bd_claim(%p,%p); failed [%p;%p;%u]\n",
940 nbc->backing_bdev, mdev,
941 nbc->backing_bdev->bd_holder,
942 nbc->backing_bdev->bd_contains->bd_holder,
943 nbc->backing_bdev->bd_holders);
944 retcode = ERR_BDCLAIM_DISK;
945 goto fail; 939 goto fail;
946 } 940 }
947 941
@@ -950,28 +944,7 @@ static int drbd_nl_disk_conf(struct drbd_conf *mdev, struct drbd_nl_cfg_req *nlp
950 offsetof(struct bm_extent, lce)); 944 offsetof(struct bm_extent, lce));
951 if (!resync_lru) { 945 if (!resync_lru) {
952 retcode = ERR_NOMEM; 946 retcode = ERR_NOMEM;
953 goto release_bdev_fail; 947 goto fail;
954 }
955
956 /* meta_dev_idx >= 0: external fixed size,
957 * possibly multiple drbd sharing one meta device.
958 * TODO in that case, paranoia check that [md_bdev, meta_dev_idx] is
959 * not yet used by some other drbd minor!
960 * (if you use drbd.conf + drbdadm,
961 * that should check it for you already; but if you don't, or someone
962 * fooled it, we need to double check here) */
963 nbc->md_bdev = inode2->i_bdev;
964 if (bd_claim(nbc->md_bdev, (nbc->dc.meta_dev_idx < 0) ? (void *)mdev
965 : (void *) drbd_m_holder)) {
966 retcode = ERR_BDCLAIM_MD_DISK;
967 goto release_bdev_fail;
968 }
969
970 if ((nbc->backing_bdev == nbc->md_bdev) !=
971 (nbc->dc.meta_dev_idx == DRBD_MD_INDEX_INTERNAL ||
972 nbc->dc.meta_dev_idx == DRBD_MD_INDEX_FLEX_INT)) {
973 retcode = ERR_MD_IDX_INVALID;
974 goto release_bdev2_fail;
975 } 948 }
976 949
977 /* RT - for drbd_get_max_capacity() DRBD_MD_INDEX_FLEX_INT */ 950 /* RT - for drbd_get_max_capacity() DRBD_MD_INDEX_FLEX_INT */
@@ -982,7 +955,7 @@ static int drbd_nl_disk_conf(struct drbd_conf *mdev, struct drbd_nl_cfg_req *nlp
982 (unsigned long long) drbd_get_max_capacity(nbc), 955 (unsigned long long) drbd_get_max_capacity(nbc),
983 (unsigned long long) nbc->dc.disk_size); 956 (unsigned long long) nbc->dc.disk_size);
984 retcode = ERR_DISK_TO_SMALL; 957 retcode = ERR_DISK_TO_SMALL;
985 goto release_bdev2_fail; 958 goto fail;
986 } 959 }
987 960
988 if (nbc->dc.meta_dev_idx < 0) { 961 if (nbc->dc.meta_dev_idx < 0) {
@@ -999,7 +972,7 @@ static int drbd_nl_disk_conf(struct drbd_conf *mdev, struct drbd_nl_cfg_req *nlp
999 dev_warn(DEV, "refusing attach: md-device too small, " 972 dev_warn(DEV, "refusing attach: md-device too small, "
1000 "at least %llu sectors needed for this meta-disk type\n", 973 "at least %llu sectors needed for this meta-disk type\n",
1001 (unsigned long long) min_md_device_sectors); 974 (unsigned long long) min_md_device_sectors);
1002 goto release_bdev2_fail; 975 goto fail;
1003 } 976 }
1004 977
1005 /* Make sure the new disk is big enough 978 /* Make sure the new disk is big enough
@@ -1007,7 +980,7 @@ static int drbd_nl_disk_conf(struct drbd_conf *mdev, struct drbd_nl_cfg_req *nlp
1007 if (drbd_get_max_capacity(nbc) < 980 if (drbd_get_max_capacity(nbc) <
1008 drbd_get_capacity(mdev->this_bdev)) { 981 drbd_get_capacity(mdev->this_bdev)) {
1009 retcode = ERR_DISK_TO_SMALL; 982 retcode = ERR_DISK_TO_SMALL;
1010 goto release_bdev2_fail; 983 goto fail;
1011 } 984 }
1012 985
1013 nbc->known_size = drbd_get_capacity(nbc->backing_bdev); 986 nbc->known_size = drbd_get_capacity(nbc->backing_bdev);
@@ -1030,7 +1003,7 @@ static int drbd_nl_disk_conf(struct drbd_conf *mdev, struct drbd_nl_cfg_req *nlp
1030 retcode = _drbd_request_state(mdev, NS(disk, D_ATTACHING), CS_VERBOSE); 1003 retcode = _drbd_request_state(mdev, NS(disk, D_ATTACHING), CS_VERBOSE);
1031 drbd_resume_io(mdev); 1004 drbd_resume_io(mdev);
1032 if (retcode < SS_SUCCESS) 1005 if (retcode < SS_SUCCESS)
1033 goto release_bdev2_fail; 1006 goto fail;
1034 1007
1035 if (!get_ldev_if_state(mdev, D_ATTACHING)) 1008 if (!get_ldev_if_state(mdev, D_ATTACHING))
1036 goto force_diskless; 1009 goto force_diskless;
@@ -1264,18 +1237,14 @@ static int drbd_nl_disk_conf(struct drbd_conf *mdev, struct drbd_nl_cfg_req *nlp
1264 force_diskless: 1237 force_diskless:
1265 drbd_force_state(mdev, NS(disk, D_DISKLESS)); 1238 drbd_force_state(mdev, NS(disk, D_DISKLESS));
1266 drbd_md_sync(mdev); 1239 drbd_md_sync(mdev);
1267 release_bdev2_fail:
1268 if (nbc)
1269 bd_release(nbc->md_bdev);
1270 release_bdev_fail:
1271 if (nbc)
1272 bd_release(nbc->backing_bdev);
1273 fail: 1240 fail:
1274 if (nbc) { 1241 if (nbc) {
1275 if (nbc->lo_file) 1242 if (nbc->backing_bdev)
1276 fput(nbc->lo_file); 1243 blkdev_put(nbc->backing_bdev,
1277 if (nbc->md_file) 1244 FMODE_READ | FMODE_WRITE | FMODE_EXCL);
1278 fput(nbc->md_file); 1245 if (nbc->md_bdev)
1246 blkdev_put(nbc->md_bdev,
1247 FMODE_READ | FMODE_WRITE | FMODE_EXCL);
1279 kfree(nbc); 1248 kfree(nbc);
1280 } 1249 }
1281 lc_destroy(resync_lru); 1250 lc_destroy(resync_lru);
diff --git a/drivers/block/pktcdvd.c b/drivers/block/pktcdvd.c
index 19b3568e9326..77d70eebb6b2 100644
--- a/drivers/block/pktcdvd.c
+++ b/drivers/block/pktcdvd.c
@@ -2296,15 +2296,12 @@ static int pkt_open_dev(struct pktcdvd_device *pd, fmode_t write)
2296 * so bdget() can't fail. 2296 * so bdget() can't fail.
2297 */ 2297 */
2298 bdget(pd->bdev->bd_dev); 2298 bdget(pd->bdev->bd_dev);
2299 if ((ret = blkdev_get(pd->bdev, FMODE_READ))) 2299 if ((ret = blkdev_get(pd->bdev, FMODE_READ | FMODE_EXCL, pd)))
2300 goto out; 2300 goto out;
2301 2301
2302 if ((ret = bd_claim(pd->bdev, pd)))
2303 goto out_putdev;
2304
2305 if ((ret = pkt_get_last_written(pd, &lba))) { 2302 if ((ret = pkt_get_last_written(pd, &lba))) {
2306 printk(DRIVER_NAME": pkt_get_last_written failed\n"); 2303 printk(DRIVER_NAME": pkt_get_last_written failed\n");
2307 goto out_unclaim; 2304 goto out_putdev;
2308 } 2305 }
2309 2306
2310 set_capacity(pd->disk, lba << 2); 2307 set_capacity(pd->disk, lba << 2);
@@ -2314,7 +2311,7 @@ static int pkt_open_dev(struct pktcdvd_device *pd, fmode_t write)
2314 q = bdev_get_queue(pd->bdev); 2311 q = bdev_get_queue(pd->bdev);
2315 if (write) { 2312 if (write) {
2316 if ((ret = pkt_open_write(pd))) 2313 if ((ret = pkt_open_write(pd)))
2317 goto out_unclaim; 2314 goto out_putdev;
2318 /* 2315 /*
2319 * Some CDRW drives can not handle writes larger than one packet, 2316 * Some CDRW drives can not handle writes larger than one packet,
2320 * even if the size is a multiple of the packet size. 2317 * even if the size is a multiple of the packet size.
@@ -2329,23 +2326,21 @@ static int pkt_open_dev(struct pktcdvd_device *pd, fmode_t write)
2329 } 2326 }
2330 2327
2331 if ((ret = pkt_set_segment_merging(pd, q))) 2328 if ((ret = pkt_set_segment_merging(pd, q)))
2332 goto out_unclaim; 2329 goto out_putdev;
2333 2330
2334 if (write) { 2331 if (write) {
2335 if (!pkt_grow_pktlist(pd, CONFIG_CDROM_PKTCDVD_BUFFERS)) { 2332 if (!pkt_grow_pktlist(pd, CONFIG_CDROM_PKTCDVD_BUFFERS)) {
2336 printk(DRIVER_NAME": not enough memory for buffers\n"); 2333 printk(DRIVER_NAME": not enough memory for buffers\n");
2337 ret = -ENOMEM; 2334 ret = -ENOMEM;
2338 goto out_unclaim; 2335 goto out_putdev;
2339 } 2336 }
2340 printk(DRIVER_NAME": %lukB available on disc\n", lba << 1); 2337 printk(DRIVER_NAME": %lukB available on disc\n", lba << 1);
2341 } 2338 }
2342 2339
2343 return 0; 2340 return 0;
2344 2341
2345out_unclaim:
2346 bd_release(pd->bdev);
2347out_putdev: 2342out_putdev:
2348 blkdev_put(pd->bdev, FMODE_READ); 2343 blkdev_put(pd->bdev, FMODE_READ | FMODE_EXCL);
2349out: 2344out:
2350 return ret; 2345 return ret;
2351} 2346}
@@ -2362,8 +2357,7 @@ static void pkt_release_dev(struct pktcdvd_device *pd, int flush)
2362 pkt_lock_door(pd, 0); 2357 pkt_lock_door(pd, 0);
2363 2358
2364 pkt_set_speed(pd, MAX_SPEED, MAX_SPEED); 2359 pkt_set_speed(pd, MAX_SPEED, MAX_SPEED);
2365 bd_release(pd->bdev); 2360 blkdev_put(pd->bdev, FMODE_READ | FMODE_EXCL);
2366 blkdev_put(pd->bdev, FMODE_READ);
2367 2361
2368 pkt_shrink_pktlist(pd); 2362 pkt_shrink_pktlist(pd);
2369} 2363}
@@ -2733,7 +2727,7 @@ static int pkt_new_dev(struct pktcdvd_device *pd, dev_t dev)
2733 bdev = bdget(dev); 2727 bdev = bdget(dev);
2734 if (!bdev) 2728 if (!bdev)
2735 return -ENOMEM; 2729 return -ENOMEM;
2736 ret = blkdev_get(bdev, FMODE_READ | FMODE_NDELAY); 2730 ret = blkdev_get(bdev, FMODE_READ | FMODE_NDELAY, NULL);
2737 if (ret) 2731 if (ret)
2738 return ret; 2732 return ret;
2739 2733
diff --git a/drivers/char/raw.c b/drivers/char/raw.c
index bfe25ea9766b..b4b9d5a47885 100644
--- a/drivers/char/raw.c
+++ b/drivers/char/raw.c
@@ -65,15 +65,12 @@ static int raw_open(struct inode *inode, struct file *filp)
65 if (!bdev) 65 if (!bdev)
66 goto out; 66 goto out;
67 igrab(bdev->bd_inode); 67 igrab(bdev->bd_inode);
68 err = blkdev_get(bdev, filp->f_mode); 68 err = blkdev_get(bdev, filp->f_mode | FMODE_EXCL, raw_open);
69 if (err) 69 if (err)
70 goto out; 70 goto out;
71 err = bd_claim(bdev, raw_open);
72 if (err)
73 goto out1;
74 err = set_blocksize(bdev, bdev_logical_block_size(bdev)); 71 err = set_blocksize(bdev, bdev_logical_block_size(bdev));
75 if (err) 72 if (err)
76 goto out2; 73 goto out1;
77 filp->f_flags |= O_DIRECT; 74 filp->f_flags |= O_DIRECT;
78 filp->f_mapping = bdev->bd_inode->i_mapping; 75 filp->f_mapping = bdev->bd_inode->i_mapping;
79 if (++raw_devices[minor].inuse == 1) 76 if (++raw_devices[minor].inuse == 1)
@@ -83,10 +80,8 @@ static int raw_open(struct inode *inode, struct file *filp)
83 mutex_unlock(&raw_mutex); 80 mutex_unlock(&raw_mutex);
84 return 0; 81 return 0;
85 82
86out2:
87 bd_release(bdev);
88out1: 83out1:
89 blkdev_put(bdev, filp->f_mode); 84 blkdev_put(bdev, filp->f_mode | FMODE_EXCL);
90out: 85out:
91 mutex_unlock(&raw_mutex); 86 mutex_unlock(&raw_mutex);
92 return err; 87 return err;
@@ -110,8 +105,7 @@ static int raw_release(struct inode *inode, struct file *filp)
110 } 105 }
111 mutex_unlock(&raw_mutex); 106 mutex_unlock(&raw_mutex);
112 107
113 bd_release(bdev); 108 blkdev_put(bdev, filp->f_mode | FMODE_EXCL);
114 blkdev_put(bdev, filp->f_mode);
115 return 0; 109 return 0;
116} 110}
117 111
diff --git a/drivers/md/dm-table.c b/drivers/md/dm-table.c
index 2c876ffc63df..9e88ca0c55e9 100644
--- a/drivers/md/dm-table.c
+++ b/drivers/md/dm-table.c
@@ -325,20 +325,13 @@ static int open_dev(struct dm_dev_internal *d, dev_t dev,
325 325
326 BUG_ON(d->dm_dev.bdev); 326 BUG_ON(d->dm_dev.bdev);
327 327
328 bdev = open_by_devnum(dev, d->dm_dev.mode); 328 bdev = open_by_devnum(dev, d->dm_dev.mode | FMODE_EXCL, _claim_ptr);
329 if (IS_ERR(bdev)) 329 if (IS_ERR(bdev))
330 return PTR_ERR(bdev); 330 return PTR_ERR(bdev);
331 331
332 r = bd_claim(bdev, _claim_ptr);
333 if (r) {
334 blkdev_put(bdev, d->dm_dev.mode);
335 return r;
336 }
337
338 r = bd_link_disk_holder(bdev, dm_disk(md)); 332 r = bd_link_disk_holder(bdev, dm_disk(md));
339 if (r) { 333 if (r) {
340 bd_release(bdev); 334 blkdev_put(bdev, d->dm_dev.mode | FMODE_EXCL);
341 blkdev_put(bdev, d->dm_dev.mode);
342 return r; 335 return r;
343 } 336 }
344 337
@@ -354,9 +347,7 @@ static void close_dev(struct dm_dev_internal *d, struct mapped_device *md)
354 if (!d->dm_dev.bdev) 347 if (!d->dm_dev.bdev)
355 return; 348 return;
356 349
357 bd_unlink_disk_holder(d->dm_dev.bdev); 350 blkdev_put(d->dm_dev.bdev, d->dm_dev.mode | FMODE_EXCL);
358 bd_release(d->dm_dev.bdev);
359 blkdev_put(d->dm_dev.bdev, d->dm_dev.mode);
360 d->dm_dev.bdev = NULL; 351 d->dm_dev.bdev = NULL;
361} 352}
362 353
diff --git a/drivers/md/md.c b/drivers/md/md.c
index c47644fca1a1..6af951ffe0bb 100644
--- a/drivers/md/md.c
+++ b/drivers/md/md.c
@@ -1907,7 +1907,6 @@ static void unbind_rdev_from_array(mdk_rdev_t * rdev)
1907 MD_BUG(); 1907 MD_BUG();
1908 return; 1908 return;
1909 } 1909 }
1910 bd_unlink_disk_holder(rdev->bdev);
1911 list_del_rcu(&rdev->same_set); 1910 list_del_rcu(&rdev->same_set);
1912 printk(KERN_INFO "md: unbind<%s>\n", bdevname(rdev->bdev,b)); 1911 printk(KERN_INFO "md: unbind<%s>\n", bdevname(rdev->bdev,b));
1913 rdev->mddev = NULL; 1912 rdev->mddev = NULL;
@@ -1935,19 +1934,13 @@ static int lock_rdev(mdk_rdev_t *rdev, dev_t dev, int shared)
1935 struct block_device *bdev; 1934 struct block_device *bdev;
1936 char b[BDEVNAME_SIZE]; 1935 char b[BDEVNAME_SIZE];
1937 1936
1938 bdev = open_by_devnum(dev, FMODE_READ|FMODE_WRITE); 1937 bdev = open_by_devnum(dev, FMODE_READ|FMODE_WRITE|FMODE_EXCL,
1938 shared ? (mdk_rdev_t *)lock_rdev : rdev);
1939 if (IS_ERR(bdev)) { 1939 if (IS_ERR(bdev)) {
1940 printk(KERN_ERR "md: could not open %s.\n", 1940 printk(KERN_ERR "md: could not open %s.\n",
1941 __bdevname(dev, b)); 1941 __bdevname(dev, b));
1942 return PTR_ERR(bdev); 1942 return PTR_ERR(bdev);
1943 } 1943 }
1944 err = bd_claim(bdev, shared ? (mdk_rdev_t *)lock_rdev : rdev);
1945 if (err) {
1946 printk(KERN_ERR "md: could not bd_claim %s.\n",
1947 bdevname(bdev, b));
1948 blkdev_put(bdev, FMODE_READ|FMODE_WRITE);
1949 return err;
1950 }
1951 if (!shared) 1944 if (!shared)
1952 set_bit(AllReserved, &rdev->flags); 1945 set_bit(AllReserved, &rdev->flags);
1953 rdev->bdev = bdev; 1946 rdev->bdev = bdev;
@@ -1960,8 +1953,7 @@ static void unlock_rdev(mdk_rdev_t *rdev)
1960 rdev->bdev = NULL; 1953 rdev->bdev = NULL;
1961 if (!bdev) 1954 if (!bdev)
1962 MD_BUG(); 1955 MD_BUG();
1963 bd_release(bdev); 1956 blkdev_put(bdev, FMODE_READ|FMODE_WRITE|FMODE_EXCL);
1964 blkdev_put(bdev, FMODE_READ|FMODE_WRITE);
1965} 1957}
1966 1958
1967void md_autodetect_dev(dev_t dev); 1959void md_autodetect_dev(dev_t dev);
diff --git a/drivers/mtd/devices/block2mtd.c b/drivers/mtd/devices/block2mtd.c
index a9e2d3b38aeb..aa557beb8f51 100644
--- a/drivers/mtd/devices/block2mtd.c
+++ b/drivers/mtd/devices/block2mtd.c
@@ -224,7 +224,7 @@ static void block2mtd_free_device(struct block2mtd_dev *dev)
224 if (dev->blkdev) { 224 if (dev->blkdev) {
225 invalidate_mapping_pages(dev->blkdev->bd_inode->i_mapping, 225 invalidate_mapping_pages(dev->blkdev->bd_inode->i_mapping,
226 0, -1); 226 0, -1);
227 close_bdev_exclusive(dev->blkdev, FMODE_READ|FMODE_WRITE); 227 blkdev_put(dev->blkdev, FMODE_READ|FMODE_WRITE|FMODE_EXCL);
228 } 228 }
229 229
230 kfree(dev); 230 kfree(dev);
@@ -234,7 +234,7 @@ static void block2mtd_free_device(struct block2mtd_dev *dev)
234/* FIXME: ensure that mtd->size % erase_size == 0 */ 234/* FIXME: ensure that mtd->size % erase_size == 0 */
235static struct block2mtd_dev *add_device(char *devname, int erase_size) 235static struct block2mtd_dev *add_device(char *devname, int erase_size)
236{ 236{
237 const fmode_t mode = FMODE_READ | FMODE_WRITE; 237 const fmode_t mode = FMODE_READ | FMODE_WRITE | FMODE_EXCL;
238 struct block_device *bdev; 238 struct block_device *bdev;
239 struct block2mtd_dev *dev; 239 struct block2mtd_dev *dev;
240 char *name; 240 char *name;
@@ -255,17 +255,8 @@ static struct block2mtd_dev *add_device(char *devname, int erase_size)
255 to resolve the device name by other means. */ 255 to resolve the device name by other means. */
256 256
257 dev_t devt = name_to_dev_t(devname); 257 dev_t devt = name_to_dev_t(devname);
258 if (devt) { 258 if (devt)
259 bdev = open_by_devnum(devt, mode); 259 bdev = open_by_devnum(devt, mode, dev);
260 if (!IS_ERR(bdev)) {
261 int ret;
262 ret = bd_claim(bdev, dev);
263 if (ret) {
264 blkdev_put(bdev, mode);
265 bdev = ERR_PTR(ret);
266 }
267 }
268 }
269 } 260 }
270#endif 261#endif
271 262
diff --git a/drivers/s390/block/dasd_genhd.c b/drivers/s390/block/dasd_genhd.c
index 30a1ca3d08b7..5505bc07e1e7 100644
--- a/drivers/s390/block/dasd_genhd.c
+++ b/drivers/s390/block/dasd_genhd.c
@@ -103,7 +103,7 @@ int dasd_scan_partitions(struct dasd_block *block)
103 struct block_device *bdev; 103 struct block_device *bdev;
104 104
105 bdev = bdget_disk(block->gdp, 0); 105 bdev = bdget_disk(block->gdp, 0);
106 if (!bdev || blkdev_get(bdev, FMODE_READ) < 0) 106 if (!bdev || blkdev_get(bdev, FMODE_READ, NULL) < 0)
107 return -ENODEV; 107 return -ENODEV;
108 /* 108 /*
109 * See fs/partition/check.c:register_disk,rescan_partitions 109 * See fs/partition/check.c:register_disk,rescan_partitions