diff options
| author | Trond Myklebust <Trond.Myklebust@netapp.com> | 2006-07-05 13:13:03 -0400 |
|---|---|---|
| committer | Trond Myklebust <Trond.Myklebust@netapp.com> | 2006-07-05 13:13:03 -0400 |
| commit | 5e66dd6d66ffe758b39b6dcadf2330753ee1159b (patch) | |
| tree | a72cdcff4448e4af9425cc213ddf56ab23e697fe /fs/block_dev.c | |
| parent | 026477c1141b67e98e3bd8bdedb7d4b88a3ecd09 (diff) | |
| parent | ca78f6baca863afe2e6a244a0fe94b3a70211d46 (diff) | |
Merge branch 'master' of /home/trondmy/kernel/linux-2.6/
Diffstat (limited to 'fs/block_dev.c')
| -rw-r--r-- | fs/block_dev.c | 102 |
1 files changed, 87 insertions, 15 deletions
diff --git a/fs/block_dev.c b/fs/block_dev.c index 9633a490dab0..37534573960b 100644 --- a/fs/block_dev.c +++ b/fs/block_dev.c | |||
| @@ -739,7 +739,7 @@ static int bd_claim_by_kobject(struct block_device *bdev, void *holder, | |||
| 739 | if (!bo) | 739 | if (!bo) |
| 740 | return -ENOMEM; | 740 | return -ENOMEM; |
| 741 | 741 | ||
| 742 | mutex_lock(&bdev->bd_mutex); | 742 | mutex_lock_nested(&bdev->bd_mutex, BD_MUTEX_PARTITION); |
| 743 | res = bd_claim(bdev, holder); | 743 | res = bd_claim(bdev, holder); |
| 744 | if (res || !add_bd_holder(bdev, bo)) | 744 | if (res || !add_bd_holder(bdev, bo)) |
| 745 | free_bd_holder(bo); | 745 | free_bd_holder(bo); |
| @@ -764,7 +764,7 @@ static void bd_release_from_kobject(struct block_device *bdev, | |||
| 764 | if (!kobj) | 764 | if (!kobj) |
| 765 | return; | 765 | return; |
| 766 | 766 | ||
| 767 | mutex_lock(&bdev->bd_mutex); | 767 | mutex_lock_nested(&bdev->bd_mutex, BD_MUTEX_PARTITION); |
| 768 | bd_release(bdev); | 768 | bd_release(bdev); |
| 769 | if ((bo = del_bd_holder(bdev, kobj))) | 769 | if ((bo = del_bd_holder(bdev, kobj))) |
| 770 | free_bd_holder(bo); | 770 | free_bd_holder(bo); |
| @@ -822,6 +822,22 @@ struct block_device *open_by_devnum(dev_t dev, unsigned mode) | |||
| 822 | 822 | ||
| 823 | EXPORT_SYMBOL(open_by_devnum); | 823 | EXPORT_SYMBOL(open_by_devnum); |
| 824 | 824 | ||
| 825 | static int | ||
| 826 | blkdev_get_partition(struct block_device *bdev, mode_t mode, unsigned flags); | ||
| 827 | |||
| 828 | struct block_device *open_partition_by_devnum(dev_t dev, unsigned mode) | ||
| 829 | { | ||
| 830 | struct block_device *bdev = bdget(dev); | ||
| 831 | int err = -ENOMEM; | ||
| 832 | int flags = mode & FMODE_WRITE ? O_RDWR : O_RDONLY; | ||
| 833 | if (bdev) | ||
| 834 | err = blkdev_get_partition(bdev, mode, flags); | ||
| 835 | return err ? ERR_PTR(err) : bdev; | ||
| 836 | } | ||
| 837 | |||
| 838 | EXPORT_SYMBOL(open_partition_by_devnum); | ||
| 839 | |||
| 840 | |||
| 825 | /* | 841 | /* |
| 826 | * This routine checks whether a removable media has been changed, | 842 | * This routine checks whether a removable media has been changed, |
| 827 | * and invalidates all buffer-cache-entries in that case. This | 843 | * and invalidates all buffer-cache-entries in that case. This |
| @@ -868,7 +884,11 @@ void bd_set_size(struct block_device *bdev, loff_t size) | |||
| 868 | } | 884 | } |
| 869 | EXPORT_SYMBOL(bd_set_size); | 885 | EXPORT_SYMBOL(bd_set_size); |
| 870 | 886 | ||
| 871 | static int do_open(struct block_device *bdev, struct file *file) | 887 | static int |
| 888 | blkdev_get_whole(struct block_device *bdev, mode_t mode, unsigned flags); | ||
| 889 | |||
| 890 | static int | ||
| 891 | do_open(struct block_device *bdev, struct file *file, unsigned int subclass) | ||
| 872 | { | 892 | { |
| 873 | struct module *owner = NULL; | 893 | struct module *owner = NULL; |
| 874 | struct gendisk *disk; | 894 | struct gendisk *disk; |
| @@ -885,7 +905,8 @@ static int do_open(struct block_device *bdev, struct file *file) | |||
| 885 | } | 905 | } |
| 886 | owner = disk->fops->owner; | 906 | owner = disk->fops->owner; |
| 887 | 907 | ||
| 888 | mutex_lock(&bdev->bd_mutex); | 908 | mutex_lock_nested(&bdev->bd_mutex, subclass); |
| 909 | |||
| 889 | if (!bdev->bd_openers) { | 910 | if (!bdev->bd_openers) { |
| 890 | bdev->bd_disk = disk; | 911 | bdev->bd_disk = disk; |
| 891 | bdev->bd_contains = bdev; | 912 | bdev->bd_contains = bdev; |
| @@ -912,11 +933,11 @@ static int do_open(struct block_device *bdev, struct file *file) | |||
| 912 | ret = -ENOMEM; | 933 | ret = -ENOMEM; |
| 913 | if (!whole) | 934 | if (!whole) |
| 914 | goto out_first; | 935 | goto out_first; |
| 915 | ret = blkdev_get(whole, file->f_mode, file->f_flags); | 936 | ret = blkdev_get_whole(whole, file->f_mode, file->f_flags); |
| 916 | if (ret) | 937 | if (ret) |
| 917 | goto out_first; | 938 | goto out_first; |
| 918 | bdev->bd_contains = whole; | 939 | bdev->bd_contains = whole; |
| 919 | mutex_lock(&whole->bd_mutex); | 940 | mutex_lock_nested(&whole->bd_mutex, BD_MUTEX_WHOLE); |
| 920 | whole->bd_part_count++; | 941 | whole->bd_part_count++; |
| 921 | p = disk->part[part - 1]; | 942 | p = disk->part[part - 1]; |
| 922 | bdev->bd_inode->i_data.backing_dev_info = | 943 | bdev->bd_inode->i_data.backing_dev_info = |
| @@ -944,7 +965,8 @@ static int do_open(struct block_device *bdev, struct file *file) | |||
| 944 | if (bdev->bd_invalidated) | 965 | if (bdev->bd_invalidated) |
| 945 | rescan_partitions(bdev->bd_disk, bdev); | 966 | rescan_partitions(bdev->bd_disk, bdev); |
| 946 | } else { | 967 | } else { |
| 947 | mutex_lock(&bdev->bd_contains->bd_mutex); | 968 | mutex_lock_nested(&bdev->bd_contains->bd_mutex, |
| 969 | BD_MUTEX_PARTITION); | ||
| 948 | bdev->bd_contains->bd_part_count++; | 970 | bdev->bd_contains->bd_part_count++; |
| 949 | mutex_unlock(&bdev->bd_contains->bd_mutex); | 971 | mutex_unlock(&bdev->bd_contains->bd_mutex); |
| 950 | } | 972 | } |
| @@ -985,11 +1007,49 @@ int blkdev_get(struct block_device *bdev, mode_t mode, unsigned flags) | |||
| 985 | fake_file.f_dentry = &fake_dentry; | 1007 | fake_file.f_dentry = &fake_dentry; |
| 986 | fake_dentry.d_inode = bdev->bd_inode; | 1008 | fake_dentry.d_inode = bdev->bd_inode; |
| 987 | 1009 | ||
| 988 | return do_open(bdev, &fake_file); | 1010 | return do_open(bdev, &fake_file, BD_MUTEX_NORMAL); |
| 989 | } | 1011 | } |
| 990 | 1012 | ||
| 991 | EXPORT_SYMBOL(blkdev_get); | 1013 | EXPORT_SYMBOL(blkdev_get); |
| 992 | 1014 | ||
| 1015 | static int | ||
| 1016 | blkdev_get_whole(struct block_device *bdev, mode_t mode, unsigned flags) | ||
| 1017 | { | ||
| 1018 | /* | ||
| 1019 | * This crockload is due to bad choice of ->open() type. | ||
| 1020 | * It will go away. | ||
| 1021 | * For now, block device ->open() routine must _not_ | ||
| 1022 | * examine anything in 'inode' argument except ->i_rdev. | ||
| 1023 | */ | ||
| 1024 | struct file fake_file = {}; | ||
| 1025 | struct dentry fake_dentry = {}; | ||
| 1026 | fake_file.f_mode = mode; | ||
| 1027 | fake_file.f_flags = flags; | ||
| 1028 | fake_file.f_dentry = &fake_dentry; | ||
| 1029 | fake_dentry.d_inode = bdev->bd_inode; | ||
| 1030 | |||
| 1031 | return do_open(bdev, &fake_file, BD_MUTEX_WHOLE); | ||
| 1032 | } | ||
| 1033 | |||
| 1034 | static int | ||
| 1035 | blkdev_get_partition(struct block_device *bdev, mode_t mode, unsigned flags) | ||
| 1036 | { | ||
| 1037 | /* | ||
| 1038 | * This crockload is due to bad choice of ->open() type. | ||
| 1039 | * It will go away. | ||
| 1040 | * For now, block device ->open() routine must _not_ | ||
| 1041 | * examine anything in 'inode' argument except ->i_rdev. | ||
| 1042 | */ | ||
| 1043 | struct file fake_file = {}; | ||
| 1044 | struct dentry fake_dentry = {}; | ||
| 1045 | fake_file.f_mode = mode; | ||
| 1046 | fake_file.f_flags = flags; | ||
| 1047 | fake_file.f_dentry = &fake_dentry; | ||
| 1048 | fake_dentry.d_inode = bdev->bd_inode; | ||
| 1049 | |||
| 1050 | return do_open(bdev, &fake_file, BD_MUTEX_PARTITION); | ||
| 1051 | } | ||
| 1052 | |||
| 993 | static int blkdev_open(struct inode * inode, struct file * filp) | 1053 | static int blkdev_open(struct inode * inode, struct file * filp) |
| 994 | { | 1054 | { |
| 995 | struct block_device *bdev; | 1055 | struct block_device *bdev; |
| @@ -1005,7 +1065,7 @@ static int blkdev_open(struct inode * inode, struct file * filp) | |||
| 1005 | 1065 | ||
| 1006 | bdev = bd_acquire(inode); | 1066 | bdev = bd_acquire(inode); |
| 1007 | 1067 | ||
| 1008 | res = do_open(bdev, filp); | 1068 | res = do_open(bdev, filp, BD_MUTEX_NORMAL); |
| 1009 | if (res) | 1069 | if (res) |
| 1010 | return res; | 1070 | return res; |
| 1011 | 1071 | ||
| @@ -1019,13 +1079,13 @@ static int blkdev_open(struct inode * inode, struct file * filp) | |||
| 1019 | return res; | 1079 | return res; |
| 1020 | } | 1080 | } |
| 1021 | 1081 | ||
| 1022 | int blkdev_put(struct block_device *bdev) | 1082 | static int __blkdev_put(struct block_device *bdev, unsigned int subclass) |
| 1023 | { | 1083 | { |
| 1024 | int ret = 0; | 1084 | int ret = 0; |
| 1025 | struct inode *bd_inode = bdev->bd_inode; | 1085 | struct inode *bd_inode = bdev->bd_inode; |
| 1026 | struct gendisk *disk = bdev->bd_disk; | 1086 | struct gendisk *disk = bdev->bd_disk; |
| 1027 | 1087 | ||
| 1028 | mutex_lock(&bdev->bd_mutex); | 1088 | mutex_lock_nested(&bdev->bd_mutex, subclass); |
| 1029 | lock_kernel(); | 1089 | lock_kernel(); |
| 1030 | if (!--bdev->bd_openers) { | 1090 | if (!--bdev->bd_openers) { |
| 1031 | sync_blockdev(bdev); | 1091 | sync_blockdev(bdev); |
| @@ -1035,7 +1095,8 @@ int blkdev_put(struct block_device *bdev) | |||
| 1035 | if (disk->fops->release) | 1095 | if (disk->fops->release) |
| 1036 | ret = disk->fops->release(bd_inode, NULL); | 1096 | ret = disk->fops->release(bd_inode, NULL); |
| 1037 | } else { | 1097 | } else { |
| 1038 | mutex_lock(&bdev->bd_contains->bd_mutex); | 1098 | mutex_lock_nested(&bdev->bd_contains->bd_mutex, |
| 1099 | subclass + 1); | ||
| 1039 | bdev->bd_contains->bd_part_count--; | 1100 | bdev->bd_contains->bd_part_count--; |
| 1040 | mutex_unlock(&bdev->bd_contains->bd_mutex); | 1101 | mutex_unlock(&bdev->bd_contains->bd_mutex); |
| 1041 | } | 1102 | } |
| @@ -1051,9 +1112,8 @@ int blkdev_put(struct block_device *bdev) | |||
| 1051 | } | 1112 | } |
| 1052 | bdev->bd_disk = NULL; | 1113 | bdev->bd_disk = NULL; |
| 1053 | bdev->bd_inode->i_data.backing_dev_info = &default_backing_dev_info; | 1114 | bdev->bd_inode->i_data.backing_dev_info = &default_backing_dev_info; |
| 1054 | if (bdev != bdev->bd_contains) { | 1115 | if (bdev != bdev->bd_contains) |
| 1055 | blkdev_put(bdev->bd_contains); | 1116 | __blkdev_put(bdev->bd_contains, subclass + 1); |
| 1056 | } | ||
| 1057 | bdev->bd_contains = NULL; | 1117 | bdev->bd_contains = NULL; |
| 1058 | } | 1118 | } |
| 1059 | unlock_kernel(); | 1119 | unlock_kernel(); |
| @@ -1062,8 +1122,20 @@ int blkdev_put(struct block_device *bdev) | |||
| 1062 | return ret; | 1122 | return ret; |
| 1063 | } | 1123 | } |
| 1064 | 1124 | ||
| 1125 | int blkdev_put(struct block_device *bdev) | ||
| 1126 | { | ||
| 1127 | return __blkdev_put(bdev, BD_MUTEX_NORMAL); | ||
| 1128 | } | ||
| 1129 | |||
| 1065 | EXPORT_SYMBOL(blkdev_put); | 1130 | EXPORT_SYMBOL(blkdev_put); |
| 1066 | 1131 | ||
| 1132 | int blkdev_put_partition(struct block_device *bdev) | ||
| 1133 | { | ||
| 1134 | return __blkdev_put(bdev, BD_MUTEX_PARTITION); | ||
| 1135 | } | ||
| 1136 | |||
| 1137 | EXPORT_SYMBOL(blkdev_put_partition); | ||
| 1138 | |||
| 1067 | static int blkdev_close(struct inode * inode, struct file * filp) | 1139 | static int blkdev_close(struct inode * inode, struct file * filp) |
| 1068 | { | 1140 | { |
| 1069 | struct block_device *bdev = I_BDEV(filp->f_mapping->host); | 1141 | struct block_device *bdev = I_BDEV(filp->f_mapping->host); |
