aboutsummaryrefslogtreecommitdiffstats
path: root/fs/block_dev.c
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
commit6a027eff62f6ae32d49f2ae5dadd6f4eee1ddae2 (patch)
tree3ab86a6fb37d1e4a7d21708feafbb58d1be72e5c /fs/block_dev.c
parente525fd89d380c4a94c0d63913a1dd1a593ed25e7 (diff)
block: reorganize claim/release implementation
With claim/release rolled into blkdev_get/put(), there's no reason to keep bd_abort/finish_claim(), __bd_claim() and bd_release() as separate functions. It only makes the code difficult to follow. Collapse them into blkdev_get/put(). This will ease future changes around claim/release. Signed-off-by: Tejun Heo <tj@kernel.org>
Diffstat (limited to 'fs/block_dev.c')
-rw-r--r--fs/block_dev.c127
1 files changed, 48 insertions, 79 deletions
diff --git a/fs/block_dev.c b/fs/block_dev.c
index fc48912354d1..269bfbbd10fc 100644
--- a/fs/block_dev.c
+++ b/fs/block_dev.c
@@ -772,79 +772,6 @@ static struct block_device *bd_start_claiming(struct block_device *bdev,
772 } 772 }
773} 773}
774 774
775/* releases bdev_lock */
776static void __bd_abort_claiming(struct block_device *whole, void *holder)
777{
778 BUG_ON(whole->bd_claiming != holder);
779 whole->bd_claiming = NULL;
780 wake_up_bit(&whole->bd_claiming, 0);
781
782 spin_unlock(&bdev_lock);
783 bdput(whole);
784}
785
786/**
787 * bd_abort_claiming - abort claiming a block device
788 * @whole: whole block device returned by bd_start_claiming()
789 * @holder: holder trying to claim @bdev
790 *
791 * Abort a claiming block started by bd_start_claiming(). Note that
792 * @whole is not the block device to be claimed but the whole device
793 * returned by bd_start_claiming().
794 *
795 * CONTEXT:
796 * Grabs and releases bdev_lock.
797 */
798static void bd_abort_claiming(struct block_device *whole, void *holder)
799{
800 spin_lock(&bdev_lock);
801 __bd_abort_claiming(whole, holder); /* releases bdev_lock */
802}
803
804/* increment holders when we have a legitimate claim. requires bdev_lock */
805static void __bd_claim(struct block_device *bdev, struct block_device *whole,
806 void *holder)
807{
808 /* note that for a whole device bd_holders
809 * will be incremented twice, and bd_holder will
810 * be set to bd_may_claim before being set to holder
811 */
812 whole->bd_holders++;
813 whole->bd_holder = bd_may_claim;
814 bdev->bd_holders++;
815 bdev->bd_holder = holder;
816}
817
818/**
819 * bd_finish_claiming - finish claiming a block device
820 * @bdev: block device of interest (passed to bd_start_claiming())
821 * @whole: whole block device returned by bd_start_claiming()
822 * @holder: holder trying to claim @bdev
823 *
824 * Finish a claiming block started by bd_start_claiming().
825 *
826 * CONTEXT:
827 * Grabs and releases bdev_lock.
828 */
829static void bd_finish_claiming(struct block_device *bdev,
830 struct block_device *whole, void *holder)
831{
832 spin_lock(&bdev_lock);
833 BUG_ON(!bd_may_claim(bdev, whole, holder));
834 __bd_claim(bdev, whole, holder);
835 __bd_abort_claiming(whole, holder); /* not actually an abort */
836}
837
838static void bd_release(struct block_device *bdev)
839{
840 spin_lock(&bdev_lock);
841 if (!--bdev->bd_contains->bd_holders)
842 bdev->bd_contains->bd_holder = NULL;
843 if (!--bdev->bd_holders)
844 bdev->bd_holder = NULL;
845 spin_unlock(&bdev_lock);
846}
847
848#ifdef CONFIG_SYSFS 775#ifdef CONFIG_SYSFS
849static int add_symlink(struct kobject *from, struct kobject *to) 776static int add_symlink(struct kobject *from, struct kobject *to)
850{ 777{
@@ -1223,10 +1150,30 @@ int blkdev_get(struct block_device *bdev, fmode_t mode, void *holder)
1223 res = __blkdev_get(bdev, mode, 0); 1150 res = __blkdev_get(bdev, mode, 0);
1224 1151
1225 if (whole) { 1152 if (whole) {
1226 if (res == 0) 1153 /* finish claiming */
1227 bd_finish_claiming(bdev, whole, holder); 1154 spin_lock(&bdev_lock);
1228 else 1155
1229 bd_abort_claiming(whole, holder); 1156 if (res == 0) {
1157 BUG_ON(!bd_may_claim(bdev, whole, holder));
1158 /*
1159 * Note that for a whole device bd_holders
1160 * will be incremented twice, and bd_holder
1161 * will be set to bd_may_claim before being
1162 * set to holder
1163 */
1164 whole->bd_holders++;
1165 whole->bd_holder = bd_may_claim;
1166 bdev->bd_holders++;
1167 bdev->bd_holder = holder;
1168 }
1169
1170 /* tell others that we're done */
1171 BUG_ON(whole->bd_claiming != holder);
1172 whole->bd_claiming = NULL;
1173 wake_up_bit(&whole->bd_claiming, 0);
1174
1175 spin_unlock(&bdev_lock);
1176 bdput(whole);
1230 } 1177 }
1231 1178
1232 return res; 1179 return res;
@@ -1272,6 +1219,7 @@ static int __blkdev_put(struct block_device *bdev, fmode_t mode, int for_part)
1272 bdev->bd_part_count--; 1219 bdev->bd_part_count--;
1273 1220
1274 if (!--bdev->bd_openers) { 1221 if (!--bdev->bd_openers) {
1222 WARN_ON_ONCE(bdev->bd_holders);
1275 sync_blockdev(bdev); 1223 sync_blockdev(bdev);
1276 kill_bdev(bdev); 1224 kill_bdev(bdev);
1277 } 1225 }
@@ -1303,10 +1251,31 @@ static int __blkdev_put(struct block_device *bdev, fmode_t mode, int for_part)
1303int blkdev_put(struct block_device *bdev, fmode_t mode) 1251int blkdev_put(struct block_device *bdev, fmode_t mode)
1304{ 1252{
1305 if (mode & FMODE_EXCL) { 1253 if (mode & FMODE_EXCL) {
1254 bool bdev_free;
1255
1256 /*
1257 * Release a claim on the device. The holder fields
1258 * are protected with bdev_lock. bd_mutex is to
1259 * synchronize disk_holder unlinking.
1260 */
1306 mutex_lock(&bdev->bd_mutex); 1261 mutex_lock(&bdev->bd_mutex);
1307 bd_release(bdev); 1262 spin_lock(&bdev_lock);
1308 if (!bdev->bd_holders) 1263
1264 WARN_ON_ONCE(--bdev->bd_holders < 0);
1265 WARN_ON_ONCE(--bdev->bd_contains->bd_holders < 0);
1266
1267 /* bd_contains might point to self, check in a separate step */
1268 if ((bdev_free = !bdev->bd_holders))
1269 bdev->bd_holder = NULL;
1270 if (!bdev->bd_contains->bd_holders)
1271 bdev->bd_contains->bd_holder = NULL;
1272
1273 spin_unlock(&bdev_lock);
1274
1275 /* if this was the last claim, holder link should go too */
1276 if (bdev_free)
1309 bd_unlink_disk_holder(bdev); 1277 bd_unlink_disk_holder(bdev);
1278
1310 mutex_unlock(&bdev->bd_mutex); 1279 mutex_unlock(&bdev->bd_mutex);
1311 } 1280 }
1312 return __blkdev_put(bdev, mode, 0); 1281 return __blkdev_put(bdev, mode, 0);