diff options
| author | David Woodhouse <David.Woodhouse@intel.com> | 2008-10-13 12:13:56 -0400 |
|---|---|---|
| committer | David Woodhouse <David.Woodhouse@intel.com> | 2008-10-13 12:13:56 -0400 |
| commit | e758936e02700ff88a0b08b722a3847b95283ef2 (patch) | |
| tree | 50c919bef1b459a778b85159d5929de95b6c4a01 /fs/block_dev.c | |
| parent | 239cfbde1f5843c4a24199f117d5f67f637d72d5 (diff) | |
| parent | 4480f15b3306f43bbb0310d461142b4e897ca45b (diff) | |
Merge branch 'master' of git://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux-2.6
Conflicts:
include/asm-x86/statfs.h
Diffstat (limited to 'fs/block_dev.c')
| -rw-r--r-- | fs/block_dev.c | 182 |
1 files changed, 123 insertions, 59 deletions
diff --git a/fs/block_dev.c b/fs/block_dev.c index aff54219e049..d84f0469a016 100644 --- a/fs/block_dev.c +++ b/fs/block_dev.c | |||
| @@ -540,22 +540,6 @@ EXPORT_SYMBOL(bd_release); | |||
| 540 | * /sys/block/sda/holders/dm-0 --> /sys/block/dm-0 | 540 | * /sys/block/sda/holders/dm-0 --> /sys/block/dm-0 |
| 541 | */ | 541 | */ |
| 542 | 542 | ||
| 543 | static struct kobject *bdev_get_kobj(struct block_device *bdev) | ||
| 544 | { | ||
| 545 | if (bdev->bd_contains != bdev) | ||
| 546 | return kobject_get(&bdev->bd_part->dev.kobj); | ||
| 547 | else | ||
| 548 | return kobject_get(&bdev->bd_disk->dev.kobj); | ||
| 549 | } | ||
| 550 | |||
| 551 | static struct kobject *bdev_get_holder(struct block_device *bdev) | ||
| 552 | { | ||
| 553 | if (bdev->bd_contains != bdev) | ||
| 554 | return kobject_get(bdev->bd_part->holder_dir); | ||
| 555 | else | ||
| 556 | return kobject_get(bdev->bd_disk->holder_dir); | ||
| 557 | } | ||
| 558 | |||
| 559 | static int add_symlink(struct kobject *from, struct kobject *to) | 543 | static int add_symlink(struct kobject *from, struct kobject *to) |
| 560 | { | 544 | { |
| 561 | if (!from || !to) | 545 | if (!from || !to) |
| @@ -604,11 +588,11 @@ static int bd_holder_grab_dirs(struct block_device *bdev, | |||
| 604 | if (!bo->hdev) | 588 | if (!bo->hdev) |
| 605 | goto fail_put_sdir; | 589 | goto fail_put_sdir; |
| 606 | 590 | ||
| 607 | bo->sdev = bdev_get_kobj(bdev); | 591 | bo->sdev = kobject_get(&part_to_dev(bdev->bd_part)->kobj); |
| 608 | if (!bo->sdev) | 592 | if (!bo->sdev) |
| 609 | goto fail_put_hdev; | 593 | goto fail_put_hdev; |
| 610 | 594 | ||
| 611 | bo->hdir = bdev_get_holder(bdev); | 595 | bo->hdir = kobject_get(bdev->bd_part->holder_dir); |
| 612 | if (!bo->hdir) | 596 | if (!bo->hdir) |
| 613 | goto fail_put_sdev; | 597 | goto fail_put_sdev; |
| 614 | 598 | ||
| @@ -868,6 +852,87 @@ struct block_device *open_by_devnum(dev_t dev, unsigned mode) | |||
| 868 | 852 | ||
| 869 | EXPORT_SYMBOL(open_by_devnum); | 853 | EXPORT_SYMBOL(open_by_devnum); |
| 870 | 854 | ||
| 855 | /** | ||
| 856 | * flush_disk - invalidates all buffer-cache entries on a disk | ||
| 857 | * | ||
| 858 | * @bdev: struct block device to be flushed | ||
| 859 | * | ||
| 860 | * Invalidates all buffer-cache entries on a disk. It should be called | ||
| 861 | * when a disk has been changed -- either by a media change or online | ||
| 862 | * resize. | ||
| 863 | */ | ||
| 864 | static void flush_disk(struct block_device *bdev) | ||
| 865 | { | ||
| 866 | if (__invalidate_device(bdev)) { | ||
| 867 | char name[BDEVNAME_SIZE] = ""; | ||
| 868 | |||
| 869 | if (bdev->bd_disk) | ||
| 870 | disk_name(bdev->bd_disk, 0, name); | ||
| 871 | printk(KERN_WARNING "VFS: busy inodes on changed media or " | ||
| 872 | "resized disk %s\n", name); | ||
| 873 | } | ||
| 874 | |||
| 875 | if (!bdev->bd_disk) | ||
| 876 | return; | ||
| 877 | if (disk_partitionable(bdev->bd_disk)) | ||
| 878 | bdev->bd_invalidated = 1; | ||
| 879 | } | ||
| 880 | |||
| 881 | /** | ||
| 882 | * check_disk_size_change - checks for disk size change and adjusts bdev size. | ||
| 883 | * @disk: struct gendisk to check | ||
| 884 | * @bdev: struct bdev to adjust. | ||
| 885 | * | ||
| 886 | * This routine checks to see if the bdev size does not match the disk size | ||
| 887 | * and adjusts it if it differs. | ||
| 888 | */ | ||
| 889 | void check_disk_size_change(struct gendisk *disk, struct block_device *bdev) | ||
| 890 | { | ||
| 891 | loff_t disk_size, bdev_size; | ||
| 892 | |||
| 893 | disk_size = (loff_t)get_capacity(disk) << 9; | ||
| 894 | bdev_size = i_size_read(bdev->bd_inode); | ||
| 895 | if (disk_size != bdev_size) { | ||
| 896 | char name[BDEVNAME_SIZE]; | ||
| 897 | |||
| 898 | disk_name(disk, 0, name); | ||
| 899 | printk(KERN_INFO | ||
| 900 | "%s: detected capacity change from %lld to %lld\n", | ||
| 901 | name, bdev_size, disk_size); | ||
| 902 | i_size_write(bdev->bd_inode, disk_size); | ||
| 903 | flush_disk(bdev); | ||
| 904 | } | ||
| 905 | } | ||
| 906 | EXPORT_SYMBOL(check_disk_size_change); | ||
| 907 | |||
| 908 | /** | ||
| 909 | * revalidate_disk - wrapper for lower-level driver's revalidate_disk call-back | ||
| 910 | * @disk: struct gendisk to be revalidated | ||
| 911 | * | ||
| 912 | * This routine is a wrapper for lower-level driver's revalidate_disk | ||
| 913 | * call-backs. It is used to do common pre and post operations needed | ||
| 914 | * for all revalidate_disk operations. | ||
| 915 | */ | ||
| 916 | int revalidate_disk(struct gendisk *disk) | ||
| 917 | { | ||
| 918 | struct block_device *bdev; | ||
| 919 | int ret = 0; | ||
| 920 | |||
| 921 | if (disk->fops->revalidate_disk) | ||
| 922 | ret = disk->fops->revalidate_disk(disk); | ||
| 923 | |||
| 924 | bdev = bdget_disk(disk, 0); | ||
| 925 | if (!bdev) | ||
| 926 | return ret; | ||
| 927 | |||
| 928 | mutex_lock(&bdev->bd_mutex); | ||
| 929 | check_disk_size_change(disk, bdev); | ||
| 930 | mutex_unlock(&bdev->bd_mutex); | ||
| 931 | bdput(bdev); | ||
| 932 | return ret; | ||
| 933 | } | ||
| 934 | EXPORT_SYMBOL(revalidate_disk); | ||
| 935 | |||
| 871 | /* | 936 | /* |
| 872 | * This routine checks whether a removable media has been changed, | 937 | * This routine checks whether a removable media has been changed, |
| 873 | * and invalidates all buffer-cache-entries in that case. This | 938 | * and invalidates all buffer-cache-entries in that case. This |
| @@ -887,13 +952,9 @@ int check_disk_change(struct block_device *bdev) | |||
| 887 | if (!bdops->media_changed(bdev->bd_disk)) | 952 | if (!bdops->media_changed(bdev->bd_disk)) |
| 888 | return 0; | 953 | return 0; |
| 889 | 954 | ||
| 890 | if (__invalidate_device(bdev)) | 955 | flush_disk(bdev); |
| 891 | printk("VFS: busy inodes on changed media.\n"); | ||
| 892 | |||
| 893 | if (bdops->revalidate_disk) | 956 | if (bdops->revalidate_disk) |
| 894 | bdops->revalidate_disk(bdev->bd_disk); | 957 | bdops->revalidate_disk(bdev->bd_disk); |
| 895 | if (bdev->bd_disk->minors > 1) | ||
| 896 | bdev->bd_invalidated = 1; | ||
| 897 | return 1; | 958 | return 1; |
| 898 | } | 959 | } |
| 899 | 960 | ||
| @@ -927,10 +988,10 @@ static int __blkdev_put(struct block_device *bdev, int for_part); | |||
| 927 | 988 | ||
| 928 | static int do_open(struct block_device *bdev, struct file *file, int for_part) | 989 | static int do_open(struct block_device *bdev, struct file *file, int for_part) |
| 929 | { | 990 | { |
| 930 | struct module *owner = NULL; | ||
| 931 | struct gendisk *disk; | 991 | struct gendisk *disk; |
| 992 | struct hd_struct *part = NULL; | ||
| 932 | int ret; | 993 | int ret; |
| 933 | int part; | 994 | int partno; |
| 934 | int perm = 0; | 995 | int perm = 0; |
| 935 | 996 | ||
| 936 | if (file->f_mode & FMODE_READ) | 997 | if (file->f_mode & FMODE_READ) |
| @@ -948,25 +1009,27 @@ static int do_open(struct block_device *bdev, struct file *file, int for_part) | |||
| 948 | 1009 | ||
| 949 | ret = -ENXIO; | 1010 | ret = -ENXIO; |
| 950 | file->f_mapping = bdev->bd_inode->i_mapping; | 1011 | file->f_mapping = bdev->bd_inode->i_mapping; |
| 1012 | |||
| 951 | lock_kernel(); | 1013 | lock_kernel(); |
| 952 | disk = get_gendisk(bdev->bd_dev, &part); | 1014 | |
| 953 | if (!disk) { | 1015 | disk = get_gendisk(bdev->bd_dev, &partno); |
| 954 | unlock_kernel(); | 1016 | if (!disk) |
| 955 | bdput(bdev); | 1017 | goto out_unlock_kernel; |
| 956 | return ret; | 1018 | part = disk_get_part(disk, partno); |
| 957 | } | 1019 | if (!part) |
| 958 | owner = disk->fops->owner; | 1020 | goto out_unlock_kernel; |
| 959 | 1021 | ||
| 960 | mutex_lock_nested(&bdev->bd_mutex, for_part); | 1022 | mutex_lock_nested(&bdev->bd_mutex, for_part); |
| 961 | if (!bdev->bd_openers) { | 1023 | if (!bdev->bd_openers) { |
| 962 | bdev->bd_disk = disk; | 1024 | bdev->bd_disk = disk; |
| 1025 | bdev->bd_part = part; | ||
| 963 | bdev->bd_contains = bdev; | 1026 | bdev->bd_contains = bdev; |
| 964 | if (!part) { | 1027 | if (!partno) { |
| 965 | struct backing_dev_info *bdi; | 1028 | struct backing_dev_info *bdi; |
| 966 | if (disk->fops->open) { | 1029 | if (disk->fops->open) { |
| 967 | ret = disk->fops->open(bdev->bd_inode, file); | 1030 | ret = disk->fops->open(bdev->bd_inode, file); |
| 968 | if (ret) | 1031 | if (ret) |
| 969 | goto out_first; | 1032 | goto out_clear; |
| 970 | } | 1033 | } |
| 971 | if (!bdev->bd_openers) { | 1034 | if (!bdev->bd_openers) { |
| 972 | bd_set_size(bdev,(loff_t)get_capacity(disk)<<9); | 1035 | bd_set_size(bdev,(loff_t)get_capacity(disk)<<9); |
| @@ -978,36 +1041,36 @@ static int do_open(struct block_device *bdev, struct file *file, int for_part) | |||
| 978 | if (bdev->bd_invalidated) | 1041 | if (bdev->bd_invalidated) |
| 979 | rescan_partitions(disk, bdev); | 1042 | rescan_partitions(disk, bdev); |
| 980 | } else { | 1043 | } else { |
| 981 | struct hd_struct *p; | ||
| 982 | struct block_device *whole; | 1044 | struct block_device *whole; |
| 983 | whole = bdget_disk(disk, 0); | 1045 | whole = bdget_disk(disk, 0); |
| 984 | ret = -ENOMEM; | 1046 | ret = -ENOMEM; |
| 985 | if (!whole) | 1047 | if (!whole) |
| 986 | goto out_first; | 1048 | goto out_clear; |
| 987 | BUG_ON(for_part); | 1049 | BUG_ON(for_part); |
| 988 | ret = __blkdev_get(whole, file->f_mode, file->f_flags, 1); | 1050 | ret = __blkdev_get(whole, file->f_mode, file->f_flags, 1); |
| 989 | if (ret) | 1051 | if (ret) |
| 990 | goto out_first; | 1052 | goto out_clear; |
| 991 | bdev->bd_contains = whole; | 1053 | bdev->bd_contains = whole; |
| 992 | p = disk->part[part - 1]; | ||
| 993 | bdev->bd_inode->i_data.backing_dev_info = | 1054 | bdev->bd_inode->i_data.backing_dev_info = |
| 994 | whole->bd_inode->i_data.backing_dev_info; | 1055 | whole->bd_inode->i_data.backing_dev_info; |
| 995 | if (!(disk->flags & GENHD_FL_UP) || !p || !p->nr_sects) { | 1056 | if (!(disk->flags & GENHD_FL_UP) || |
| 1057 | !part || !part->nr_sects) { | ||
| 996 | ret = -ENXIO; | 1058 | ret = -ENXIO; |
| 997 | goto out_first; | 1059 | goto out_clear; |
| 998 | } | 1060 | } |
| 999 | kobject_get(&p->dev.kobj); | 1061 | bd_set_size(bdev, (loff_t)part->nr_sects << 9); |
| 1000 | bdev->bd_part = p; | ||
| 1001 | bd_set_size(bdev, (loff_t) p->nr_sects << 9); | ||
| 1002 | } | 1062 | } |
| 1003 | } else { | 1063 | } else { |
| 1064 | disk_put_part(part); | ||
| 1004 | put_disk(disk); | 1065 | put_disk(disk); |
| 1005 | module_put(owner); | 1066 | module_put(disk->fops->owner); |
| 1067 | part = NULL; | ||
| 1068 | disk = NULL; | ||
| 1006 | if (bdev->bd_contains == bdev) { | 1069 | if (bdev->bd_contains == bdev) { |
| 1007 | if (bdev->bd_disk->fops->open) { | 1070 | if (bdev->bd_disk->fops->open) { |
| 1008 | ret = bdev->bd_disk->fops->open(bdev->bd_inode, file); | 1071 | ret = bdev->bd_disk->fops->open(bdev->bd_inode, file); |
| 1009 | if (ret) | 1072 | if (ret) |
| 1010 | goto out; | 1073 | goto out_unlock_bdev; |
| 1011 | } | 1074 | } |
| 1012 | if (bdev->bd_invalidated) | 1075 | if (bdev->bd_invalidated) |
| 1013 | rescan_partitions(bdev->bd_disk, bdev); | 1076 | rescan_partitions(bdev->bd_disk, bdev); |
| @@ -1020,19 +1083,24 @@ static int do_open(struct block_device *bdev, struct file *file, int for_part) | |||
| 1020 | unlock_kernel(); | 1083 | unlock_kernel(); |
| 1021 | return 0; | 1084 | return 0; |
| 1022 | 1085 | ||
| 1023 | out_first: | 1086 | out_clear: |
| 1024 | bdev->bd_disk = NULL; | 1087 | bdev->bd_disk = NULL; |
| 1088 | bdev->bd_part = NULL; | ||
| 1025 | bdev->bd_inode->i_data.backing_dev_info = &default_backing_dev_info; | 1089 | bdev->bd_inode->i_data.backing_dev_info = &default_backing_dev_info; |
| 1026 | if (bdev != bdev->bd_contains) | 1090 | if (bdev != bdev->bd_contains) |
| 1027 | __blkdev_put(bdev->bd_contains, 1); | 1091 | __blkdev_put(bdev->bd_contains, 1); |
| 1028 | bdev->bd_contains = NULL; | 1092 | bdev->bd_contains = NULL; |
| 1029 | put_disk(disk); | 1093 | out_unlock_bdev: |
| 1030 | module_put(owner); | ||
| 1031 | out: | ||
| 1032 | mutex_unlock(&bdev->bd_mutex); | 1094 | mutex_unlock(&bdev->bd_mutex); |
| 1095 | out_unlock_kernel: | ||
| 1033 | unlock_kernel(); | 1096 | unlock_kernel(); |
| 1034 | if (ret) | 1097 | |
| 1035 | bdput(bdev); | 1098 | disk_put_part(part); |
| 1099 | if (disk) | ||
| 1100 | module_put(disk->fops->owner); | ||
| 1101 | put_disk(disk); | ||
| 1102 | bdput(bdev); | ||
| 1103 | |||
| 1036 | return ret; | 1104 | return ret; |
| 1037 | } | 1105 | } |
| 1038 | 1106 | ||
| @@ -1117,11 +1185,8 @@ static int __blkdev_put(struct block_device *bdev, int for_part) | |||
| 1117 | 1185 | ||
| 1118 | put_disk(disk); | 1186 | put_disk(disk); |
| 1119 | module_put(owner); | 1187 | module_put(owner); |
| 1120 | 1188 | disk_put_part(bdev->bd_part); | |
| 1121 | if (bdev->bd_contains != bdev) { | 1189 | bdev->bd_part = NULL; |
| 1122 | kobject_put(&bdev->bd_part->dev.kobj); | ||
| 1123 | bdev->bd_part = NULL; | ||
| 1124 | } | ||
| 1125 | bdev->bd_disk = NULL; | 1190 | bdev->bd_disk = NULL; |
| 1126 | bdev->bd_inode->i_data.backing_dev_info = &default_backing_dev_info; | 1191 | bdev->bd_inode->i_data.backing_dev_info = &default_backing_dev_info; |
| 1127 | if (bdev != bdev->bd_contains) | 1192 | if (bdev != bdev->bd_contains) |
| @@ -1197,10 +1262,9 @@ EXPORT_SYMBOL(ioctl_by_bdev); | |||
| 1197 | 1262 | ||
| 1198 | /** | 1263 | /** |
| 1199 | * lookup_bdev - lookup a struct block_device by name | 1264 | * lookup_bdev - lookup a struct block_device by name |
| 1265 | * @pathname: special file representing the block device | ||
| 1200 | * | 1266 | * |
| 1201 | * @path: special file representing the block device | 1267 | * Get a reference to the blockdevice at @pathname in the current |
| 1202 | * | ||
| 1203 | * Get a reference to the blockdevice at @path in the current | ||
| 1204 | * namespace if possible and return it. Return ERR_PTR(error) | 1268 | * namespace if possible and return it. Return ERR_PTR(error) |
| 1205 | * otherwise. | 1269 | * otherwise. |
| 1206 | */ | 1270 | */ |
