aboutsummaryrefslogtreecommitdiffstats
path: root/fs
diff options
context:
space:
mode:
authorPeter Zijlstra <a.p.zijlstra@chello.nl>2006-08-27 04:23:31 -0400
committerLinus Torvalds <torvalds@g5.osdl.org>2006-08-27 14:01:29 -0400
commit6946bd636364effce06ea46fe8f8cd6e2edb004e (patch)
treef910a0c27dbb36ad94e228c9a7509051c2ce57ae /fs
parent7334bb4ae931159384acf168eacb0d5d6e0d083c (diff)
[PATCH] lockdep: fix blkdev_open() warning
On Wed, 2006-08-09 at 07:57 +0200, Rolf Eike Beer wrote: > ============================================= > [ INFO: possible recursive locking detected ] > --------------------------------------------- > parted/7929 is trying to acquire lock: > (&bdev->bd_mutex){--..}, at: [<c105eb8d>] __blkdev_put+0x1e/0x13c > > but task is already holding lock: > (&bdev->bd_mutex){--..}, at: [<c105eec6>] do_open+0x72/0x3a8 > > other info that might help us debug this: > 1 lock held by parted/7929: > #0: (&bdev->bd_mutex){--..}, at: [<c105eec6>] do_open+0x72/0x3a8 > stack backtrace: > [<c1003aad>] show_trace_log_lvl+0x58/0x15b > [<c100495f>] show_trace+0xd/0x10 > [<c1004979>] dump_stack+0x17/0x1a > [<c102dee5>] __lock_acquire+0x753/0x99c > [<c102e3b0>] lock_acquire+0x4a/0x6a > [<c1204501>] mutex_lock_nested+0xc8/0x20c > [<c105eb8d>] __blkdev_put+0x1e/0x13c > [<c105ecc4>] blkdev_put+0xa/0xc > [<c105f18a>] do_open+0x336/0x3a8 > [<c105f21b>] blkdev_open+0x1f/0x4c > [<c1057b40>] __dentry_open+0xc7/0x1aa > [<c1057c91>] nameidata_to_filp+0x1c/0x2e > [<c1057cd1>] do_filp_open+0x2e/0x35 > [<c1057dd7>] do_sys_open+0x38/0x68 > [<c1057e33>] sys_open+0x16/0x18 > [<c1002845>] sysenter_past_esp+0x56/0x8d OK, I'm having a look here; its all new to me so bear with me. blkdev_open() calls do_open(bdev, ...,BD_MUTEX_NORMAL) and takes mutex_lock_nested(&bdev->bd_mutex, BD_MUTEX_NORMAL) then something fails, and we're thrown to: out_first: where if (bdev != bdev->bd_contains) blkdev_put(bdev->bd_contains) which is __blkdev_put(bdev->bd_contains, BD_MUTEX_NORMAL) which does mutex_lock_nested(&bdev->bd_contains->bd_mutex, BD_MUTEX_NORMAL) <--- lockdep trigger When going to out_first, dbev->bd_contains is either bdev or whole, and since we take the branch it must be whole. So it seems to me the following patch would be the right one: [akpm@osdl.org: compile fix] Signed-off-by: Peter Zijlstra <a.p.zijlstra@chello.nl> Cc: Arjan van de Ven <arjan@linux.intel.com> Acked-by: NeilBrown <neilb@suse.de> Signed-off-by: Andrew Morton <akpm@osdl.org> Signed-off-by: Linus Torvalds <torvalds@osdl.org>
Diffstat (limited to 'fs')
-rw-r--r--fs/block_dev.c114
1 files changed, 56 insertions, 58 deletions
diff --git a/fs/block_dev.c b/fs/block_dev.c
index 37534573960b..045f98854f14 100644
--- a/fs/block_dev.c
+++ b/fs/block_dev.c
@@ -884,6 +884,61 @@ void bd_set_size(struct block_device *bdev, loff_t size)
884} 884}
885EXPORT_SYMBOL(bd_set_size); 885EXPORT_SYMBOL(bd_set_size);
886 886
887static int __blkdev_put(struct block_device *bdev, unsigned int subclass)
888{
889 int ret = 0;
890 struct inode *bd_inode = bdev->bd_inode;
891 struct gendisk *disk = bdev->bd_disk;
892
893 mutex_lock_nested(&bdev->bd_mutex, subclass);
894 lock_kernel();
895 if (!--bdev->bd_openers) {
896 sync_blockdev(bdev);
897 kill_bdev(bdev);
898 }
899 if (bdev->bd_contains == bdev) {
900 if (disk->fops->release)
901 ret = disk->fops->release(bd_inode, NULL);
902 } else {
903 mutex_lock_nested(&bdev->bd_contains->bd_mutex,
904 subclass + 1);
905 bdev->bd_contains->bd_part_count--;
906 mutex_unlock(&bdev->bd_contains->bd_mutex);
907 }
908 if (!bdev->bd_openers) {
909 struct module *owner = disk->fops->owner;
910
911 put_disk(disk);
912 module_put(owner);
913
914 if (bdev->bd_contains != bdev) {
915 kobject_put(&bdev->bd_part->kobj);
916 bdev->bd_part = NULL;
917 }
918 bdev->bd_disk = NULL;
919 bdev->bd_inode->i_data.backing_dev_info = &default_backing_dev_info;
920 if (bdev != bdev->bd_contains)
921 __blkdev_put(bdev->bd_contains, subclass + 1);
922 bdev->bd_contains = NULL;
923 }
924 unlock_kernel();
925 mutex_unlock(&bdev->bd_mutex);
926 bdput(bdev);
927 return ret;
928}
929
930int blkdev_put(struct block_device *bdev)
931{
932 return __blkdev_put(bdev, BD_MUTEX_NORMAL);
933}
934EXPORT_SYMBOL(blkdev_put);
935
936int blkdev_put_partition(struct block_device *bdev)
937{
938 return __blkdev_put(bdev, BD_MUTEX_PARTITION);
939}
940EXPORT_SYMBOL(blkdev_put_partition);
941
887static int 942static int
888blkdev_get_whole(struct block_device *bdev, mode_t mode, unsigned flags); 943blkdev_get_whole(struct block_device *bdev, mode_t mode, unsigned flags);
889 944
@@ -980,7 +1035,7 @@ out_first:
980 bdev->bd_disk = NULL; 1035 bdev->bd_disk = NULL;
981 bdev->bd_inode->i_data.backing_dev_info = &default_backing_dev_info; 1036 bdev->bd_inode->i_data.backing_dev_info = &default_backing_dev_info;
982 if (bdev != bdev->bd_contains) 1037 if (bdev != bdev->bd_contains)
983 blkdev_put(bdev->bd_contains); 1038 __blkdev_put(bdev->bd_contains, BD_MUTEX_WHOLE);
984 bdev->bd_contains = NULL; 1039 bdev->bd_contains = NULL;
985 put_disk(disk); 1040 put_disk(disk);
986 module_put(owner); 1041 module_put(owner);
@@ -1079,63 +1134,6 @@ static int blkdev_open(struct inode * inode, struct file * filp)
1079 return res; 1134 return res;
1080} 1135}
1081 1136
1082static int __blkdev_put(struct block_device *bdev, unsigned int subclass)
1083{
1084 int ret = 0;
1085 struct inode *bd_inode = bdev->bd_inode;
1086 struct gendisk *disk = bdev->bd_disk;
1087
1088 mutex_lock_nested(&bdev->bd_mutex, subclass);
1089 lock_kernel();
1090 if (!--bdev->bd_openers) {
1091 sync_blockdev(bdev);
1092 kill_bdev(bdev);
1093 }
1094 if (bdev->bd_contains == bdev) {
1095 if (disk->fops->release)
1096 ret = disk->fops->release(bd_inode, NULL);
1097 } else {
1098 mutex_lock_nested(&bdev->bd_contains->bd_mutex,
1099 subclass + 1);
1100 bdev->bd_contains->bd_part_count--;
1101 mutex_unlock(&bdev->bd_contains->bd_mutex);
1102 }
1103 if (!bdev->bd_openers) {
1104 struct module *owner = disk->fops->owner;
1105
1106 put_disk(disk);
1107 module_put(owner);
1108
1109 if (bdev->bd_contains != bdev) {
1110 kobject_put(&bdev->bd_part->kobj);
1111 bdev->bd_part = NULL;
1112 }
1113 bdev->bd_disk = NULL;
1114 bdev->bd_inode->i_data.backing_dev_info = &default_backing_dev_info;
1115 if (bdev != bdev->bd_contains)
1116 __blkdev_put(bdev->bd_contains, subclass + 1);
1117 bdev->bd_contains = NULL;
1118 }
1119 unlock_kernel();
1120 mutex_unlock(&bdev->bd_mutex);
1121 bdput(bdev);
1122 return ret;
1123}
1124
1125int blkdev_put(struct block_device *bdev)
1126{
1127 return __blkdev_put(bdev, BD_MUTEX_NORMAL);
1128}
1129
1130EXPORT_SYMBOL(blkdev_put);
1131
1132int blkdev_put_partition(struct block_device *bdev)
1133{
1134 return __blkdev_put(bdev, BD_MUTEX_PARTITION);
1135}
1136
1137EXPORT_SYMBOL(blkdev_put_partition);
1138
1139static int blkdev_close(struct inode * inode, struct file * filp) 1137static int blkdev_close(struct inode * inode, struct file * filp)
1140{ 1138{
1141 struct block_device *bdev = I_BDEV(filp->f_mapping->host); 1139 struct block_device *bdev = I_BDEV(filp->f_mapping->host);