diff options
author | Tejun Heo <tj@kernel.org> | 2010-11-13 05:55:17 -0500 |
---|---|---|
committer | Tejun Heo <tj@kernel.org> | 2010-11-13 05:55:17 -0500 |
commit | 6a027eff62f6ae32d49f2ae5dadd6f4eee1ddae2 (patch) | |
tree | 3ab86a6fb37d1e4a7d21708feafbb58d1be72e5c | |
parent | e525fd89d380c4a94c0d63913a1dd1a593ed25e7 (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>
-rw-r--r-- | fs/block_dev.c | 127 |
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 */ | ||
776 | static 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 | */ | ||
798 | static 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 */ | ||
805 | static 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 | */ | ||
829 | static 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 | |||
838 | static 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 |
849 | static int add_symlink(struct kobject *from, struct kobject *to) | 776 | static 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) | |||
1303 | int blkdev_put(struct block_device *bdev, fmode_t mode) | 1251 | int 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); |