diff options
Diffstat (limited to 'block')
-rw-r--r-- | block/bsg.c | 78 |
1 files changed, 30 insertions, 48 deletions
diff --git a/block/bsg.c b/block/bsg.c index 3b2f05258a92..d60eee549405 100644 --- a/block/bsg.c +++ b/block/bsg.c | |||
@@ -9,13 +9,6 @@ | |||
9 | * archive for more details. | 9 | * archive for more details. |
10 | * | 10 | * |
11 | */ | 11 | */ |
12 | /* | ||
13 | * TODO | ||
14 | * - Should this get merged, block/scsi_ioctl.c will be migrated into | ||
15 | * this file. To keep maintenance down, it's easier to have them | ||
16 | * seperated right now. | ||
17 | * | ||
18 | */ | ||
19 | #include <linux/module.h> | 12 | #include <linux/module.h> |
20 | #include <linux/init.h> | 13 | #include <linux/init.h> |
21 | #include <linux/file.h> | 14 | #include <linux/file.h> |
@@ -24,6 +17,7 @@ | |||
24 | #include <linux/cdev.h> | 17 | #include <linux/cdev.h> |
25 | #include <linux/percpu.h> | 18 | #include <linux/percpu.h> |
26 | #include <linux/uio.h> | 19 | #include <linux/uio.h> |
20 | #include <linux/idr.h> | ||
27 | #include <linux/bsg.h> | 21 | #include <linux/bsg.h> |
28 | 22 | ||
29 | #include <scsi/scsi.h> | 23 | #include <scsi/scsi.h> |
@@ -70,13 +64,12 @@ enum { | |||
70 | #endif | 64 | #endif |
71 | 65 | ||
72 | static DEFINE_MUTEX(bsg_mutex); | 66 | static DEFINE_MUTEX(bsg_mutex); |
73 | static int bsg_device_nr, bsg_minor_idx; | 67 | static DEFINE_IDR(bsg_minor_idr); |
74 | 68 | ||
75 | #define BSG_LIST_ARRAY_SIZE 8 | 69 | #define BSG_LIST_ARRAY_SIZE 8 |
76 | static struct hlist_head bsg_device_list[BSG_LIST_ARRAY_SIZE]; | 70 | static struct hlist_head bsg_device_list[BSG_LIST_ARRAY_SIZE]; |
77 | 71 | ||
78 | static struct class *bsg_class; | 72 | static struct class *bsg_class; |
79 | static LIST_HEAD(bsg_class_list); | ||
80 | static int bsg_major; | 73 | static int bsg_major; |
81 | 74 | ||
82 | static struct kmem_cache *bsg_cmd_cachep; | 75 | static struct kmem_cache *bsg_cmd_cachep; |
@@ -92,7 +85,6 @@ struct bsg_command { | |||
92 | struct bio *bidi_bio; | 85 | struct bio *bidi_bio; |
93 | int err; | 86 | int err; |
94 | struct sg_io_v4 hdr; | 87 | struct sg_io_v4 hdr; |
95 | struct sg_io_v4 __user *uhdr; | ||
96 | char sense[SCSI_SENSE_BUFFERSIZE]; | 88 | char sense[SCSI_SENSE_BUFFERSIZE]; |
97 | }; | 89 | }; |
98 | 90 | ||
@@ -620,7 +612,6 @@ static int __bsg_write(struct bsg_device *bd, const char __user *buf, | |||
620 | break; | 612 | break; |
621 | } | 613 | } |
622 | 614 | ||
623 | bc->uhdr = (struct sg_io_v4 __user *) buf; | ||
624 | if (copy_from_user(&bc->hdr, buf, sizeof(bc->hdr))) { | 615 | if (copy_from_user(&bc->hdr, buf, sizeof(bc->hdr))) { |
625 | ret = -EFAULT; | 616 | ret = -EFAULT; |
626 | break; | 617 | break; |
@@ -781,23 +772,18 @@ static struct bsg_device *__bsg_get_device(int minor) | |||
781 | 772 | ||
782 | static struct bsg_device *bsg_get_device(struct inode *inode, struct file *file) | 773 | static struct bsg_device *bsg_get_device(struct inode *inode, struct file *file) |
783 | { | 774 | { |
784 | struct bsg_device *bd = __bsg_get_device(iminor(inode)); | 775 | struct bsg_device *bd; |
785 | struct bsg_class_device *bcd, *__bcd; | 776 | struct bsg_class_device *bcd; |
786 | 777 | ||
778 | bd = __bsg_get_device(iminor(inode)); | ||
787 | if (bd) | 779 | if (bd) |
788 | return bd; | 780 | return bd; |
789 | 781 | ||
790 | /* | 782 | /* |
791 | * find the class device | 783 | * find the class device |
792 | */ | 784 | */ |
793 | bcd = NULL; | ||
794 | mutex_lock(&bsg_mutex); | 785 | mutex_lock(&bsg_mutex); |
795 | list_for_each_entry(__bcd, &bsg_class_list, list) { | 786 | bcd = idr_find(&bsg_minor_idr, iminor(inode)); |
796 | if (__bcd->minor == iminor(inode)) { | ||
797 | bcd = __bcd; | ||
798 | break; | ||
799 | } | ||
800 | } | ||
801 | mutex_unlock(&bsg_mutex); | 787 | mutex_unlock(&bsg_mutex); |
802 | 788 | ||
803 | if (!bcd) | 789 | if (!bcd) |
@@ -936,13 +922,12 @@ void bsg_unregister_queue(struct request_queue *q) | |||
936 | return; | 922 | return; |
937 | 923 | ||
938 | mutex_lock(&bsg_mutex); | 924 | mutex_lock(&bsg_mutex); |
925 | idr_remove(&bsg_minor_idr, bcd->minor); | ||
939 | sysfs_remove_link(&q->kobj, "bsg"); | 926 | sysfs_remove_link(&q->kobj, "bsg"); |
940 | class_device_unregister(bcd->class_dev); | 927 | class_device_unregister(bcd->class_dev); |
941 | put_device(bcd->dev); | 928 | put_device(bcd->dev); |
942 | bcd->class_dev = NULL; | 929 | bcd->class_dev = NULL; |
943 | bcd->dev = NULL; | 930 | bcd->dev = NULL; |
944 | list_del_init(&bcd->list); | ||
945 | bsg_device_nr--; | ||
946 | mutex_unlock(&bsg_mutex); | 931 | mutex_unlock(&bsg_mutex); |
947 | } | 932 | } |
948 | EXPORT_SYMBOL_GPL(bsg_unregister_queue); | 933 | EXPORT_SYMBOL_GPL(bsg_unregister_queue); |
@@ -950,9 +935,9 @@ EXPORT_SYMBOL_GPL(bsg_unregister_queue); | |||
950 | int bsg_register_queue(struct request_queue *q, struct device *gdev, | 935 | int bsg_register_queue(struct request_queue *q, struct device *gdev, |
951 | const char *name) | 936 | const char *name) |
952 | { | 937 | { |
953 | struct bsg_class_device *bcd, *__bcd; | 938 | struct bsg_class_device *bcd; |
954 | dev_t dev; | 939 | dev_t dev; |
955 | int ret = -EMFILE; | 940 | int ret, minor; |
956 | struct class_device *class_dev = NULL; | 941 | struct class_device *class_dev = NULL; |
957 | const char *devname; | 942 | const char *devname; |
958 | 943 | ||
@@ -969,28 +954,26 @@ int bsg_register_queue(struct request_queue *q, struct device *gdev, | |||
969 | 954 | ||
970 | bcd = &q->bsg_dev; | 955 | bcd = &q->bsg_dev; |
971 | memset(bcd, 0, sizeof(*bcd)); | 956 | memset(bcd, 0, sizeof(*bcd)); |
972 | INIT_LIST_HEAD(&bcd->list); | ||
973 | 957 | ||
974 | mutex_lock(&bsg_mutex); | 958 | mutex_lock(&bsg_mutex); |
975 | if (bsg_device_nr == BSG_MAX_DEVS) { | ||
976 | printk(KERN_ERR "bsg: too many bsg devices\n"); | ||
977 | goto err; | ||
978 | } | ||
979 | 959 | ||
980 | retry: | 960 | ret = idr_pre_get(&bsg_minor_idr, GFP_KERNEL); |
981 | list_for_each_entry(__bcd, &bsg_class_list, list) { | 961 | if (!ret) { |
982 | if (__bcd->minor == bsg_minor_idx) { | 962 | ret = -ENOMEM; |
983 | bsg_minor_idx++; | 963 | goto unlock; |
984 | if (bsg_minor_idx == BSG_MAX_DEVS) | ||
985 | bsg_minor_idx = 0; | ||
986 | goto retry; | ||
987 | } | ||
988 | } | 964 | } |
989 | 965 | ||
990 | bcd->minor = bsg_minor_idx++; | 966 | ret = idr_get_new(&bsg_minor_idr, bcd, &minor); |
991 | if (bsg_minor_idx == BSG_MAX_DEVS) | 967 | if (ret < 0) |
992 | bsg_minor_idx = 0; | 968 | goto unlock; |
993 | 969 | ||
970 | if (minor >= BSG_MAX_DEVS) { | ||
971 | printk(KERN_ERR "bsg: too many bsg devices\n"); | ||
972 | ret = -EINVAL; | ||
973 | goto remove_idr; | ||
974 | } | ||
975 | |||
976 | bcd->minor = minor; | ||
994 | bcd->queue = q; | 977 | bcd->queue = q; |
995 | bcd->dev = get_device(gdev); | 978 | bcd->dev = get_device(gdev); |
996 | dev = MKDEV(bsg_major, bcd->minor); | 979 | dev = MKDEV(bsg_major, bcd->minor); |
@@ -998,27 +981,26 @@ retry: | |||
998 | devname); | 981 | devname); |
999 | if (IS_ERR(class_dev)) { | 982 | if (IS_ERR(class_dev)) { |
1000 | ret = PTR_ERR(class_dev); | 983 | ret = PTR_ERR(class_dev); |
1001 | goto err_put; | 984 | goto put_dev; |
1002 | } | 985 | } |
1003 | bcd->class_dev = class_dev; | 986 | bcd->class_dev = class_dev; |
1004 | 987 | ||
1005 | if (q->kobj.sd) { | 988 | if (q->kobj.sd) { |
1006 | ret = sysfs_create_link(&q->kobj, &bcd->class_dev->kobj, "bsg"); | 989 | ret = sysfs_create_link(&q->kobj, &bcd->class_dev->kobj, "bsg"); |
1007 | if (ret) | 990 | if (ret) |
1008 | goto err_unregister; | 991 | goto unregister_class_dev; |
1009 | } | 992 | } |
1010 | 993 | ||
1011 | list_add_tail(&bcd->list, &bsg_class_list); | ||
1012 | bsg_device_nr++; | ||
1013 | |||
1014 | mutex_unlock(&bsg_mutex); | 994 | mutex_unlock(&bsg_mutex); |
1015 | return 0; | 995 | return 0; |
1016 | 996 | ||
1017 | err_unregister: | 997 | unregister_class_dev: |
1018 | class_device_unregister(class_dev); | 998 | class_device_unregister(class_dev); |
1019 | err_put: | 999 | put_dev: |
1020 | put_device(gdev); | 1000 | put_device(gdev); |
1021 | err: | 1001 | remove_idr: |
1002 | idr_remove(&bsg_minor_idr, minor); | ||
1003 | unlock: | ||
1022 | mutex_unlock(&bsg_mutex); | 1004 | mutex_unlock(&bsg_mutex); |
1023 | return ret; | 1005 | return ret; |
1024 | } | 1006 | } |