diff options
Diffstat (limited to 'block/bsg.c')
| -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 | } |
