Commit 598443a2124618fc8fe5a8bae32c129666ac3eab
Committed by
James Bottomley
1 parent
4b39c1d983
Exists in
master
and in
20 other branches
[SCSI] bsg: use lib/idr.c to find a unique minor number
This replaces the current linear search for a unique minor number with lib/idr.c. Signed-off-by: FUJITA Tomonori <fujita.tomonori@lab.ntt.co.jp> Acked-by: Jens Axboe <jens.axboe@oracle.com> Signed-off-by: James Bottomley <James.Bottomley@SteelEye.com>
Showing 2 changed files with 30 additions and 40 deletions Side-by-side Diff
block/bsg.c
... | ... | @@ -24,6 +24,7 @@ |
24 | 24 | #include <linux/cdev.h> |
25 | 25 | #include <linux/percpu.h> |
26 | 26 | #include <linux/uio.h> |
27 | +#include <linux/idr.h> | |
27 | 28 | #include <linux/bsg.h> |
28 | 29 | |
29 | 30 | #include <scsi/scsi.h> |
30 | 31 | |
... | ... | @@ -70,13 +71,12 @@ |
70 | 71 | #endif |
71 | 72 | |
72 | 73 | static DEFINE_MUTEX(bsg_mutex); |
73 | -static int bsg_device_nr, bsg_minor_idx; | |
74 | +static DEFINE_IDR(bsg_minor_idr); | |
74 | 75 | |
75 | 76 | #define BSG_LIST_ARRAY_SIZE 8 |
76 | 77 | static struct hlist_head bsg_device_list[BSG_LIST_ARRAY_SIZE]; |
77 | 78 | |
78 | 79 | static struct class *bsg_class; |
79 | -static LIST_HEAD(bsg_class_list); | |
80 | 80 | static int bsg_major; |
81 | 81 | |
82 | 82 | static struct kmem_cache *bsg_cmd_cachep; |
83 | 83 | |
84 | 84 | |
85 | 85 | |
... | ... | @@ -781,23 +781,18 @@ |
781 | 781 | |
782 | 782 | static struct bsg_device *bsg_get_device(struct inode *inode, struct file *file) |
783 | 783 | { |
784 | - struct bsg_device *bd = __bsg_get_device(iminor(inode)); | |
785 | - struct bsg_class_device *bcd, *__bcd; | |
784 | + struct bsg_device *bd; | |
785 | + struct bsg_class_device *bcd; | |
786 | 786 | |
787 | + bd = __bsg_get_device(iminor(inode)); | |
787 | 788 | if (bd) |
788 | 789 | return bd; |
789 | 790 | |
790 | 791 | /* |
791 | 792 | * find the class device |
792 | 793 | */ |
793 | - bcd = NULL; | |
794 | 794 | mutex_lock(&bsg_mutex); |
795 | - list_for_each_entry(__bcd, &bsg_class_list, list) { | |
796 | - if (__bcd->minor == iminor(inode)) { | |
797 | - bcd = __bcd; | |
798 | - break; | |
799 | - } | |
800 | - } | |
795 | + bcd = idr_find(&bsg_minor_idr, iminor(inode)); | |
801 | 796 | mutex_unlock(&bsg_mutex); |
802 | 797 | |
803 | 798 | if (!bcd) |
804 | 799 | |
... | ... | @@ -936,13 +931,12 @@ |
936 | 931 | return; |
937 | 932 | |
938 | 933 | mutex_lock(&bsg_mutex); |
934 | + idr_remove(&bsg_minor_idr, bcd->minor); | |
939 | 935 | sysfs_remove_link(&q->kobj, "bsg"); |
940 | 936 | class_device_unregister(bcd->class_dev); |
941 | 937 | put_device(bcd->dev); |
942 | 938 | bcd->class_dev = NULL; |
943 | 939 | bcd->dev = NULL; |
944 | - list_del_init(&bcd->list); | |
945 | - bsg_device_nr--; | |
946 | 940 | mutex_unlock(&bsg_mutex); |
947 | 941 | } |
948 | 942 | EXPORT_SYMBOL_GPL(bsg_unregister_queue); |
949 | 943 | |
... | ... | @@ -950,9 +944,9 @@ |
950 | 944 | int bsg_register_queue(struct request_queue *q, struct device *gdev, |
951 | 945 | const char *name) |
952 | 946 | { |
953 | - struct bsg_class_device *bcd, *__bcd; | |
947 | + struct bsg_class_device *bcd; | |
954 | 948 | dev_t dev; |
955 | - int ret = -EMFILE; | |
949 | + int ret, minor; | |
956 | 950 | struct class_device *class_dev = NULL; |
957 | 951 | const char *devname; |
958 | 952 | |
959 | 953 | |
960 | 954 | |
961 | 955 | |
962 | 956 | |
... | ... | @@ -969,28 +963,26 @@ |
969 | 963 | |
970 | 964 | bcd = &q->bsg_dev; |
971 | 965 | memset(bcd, 0, sizeof(*bcd)); |
972 | - INIT_LIST_HEAD(&bcd->list); | |
973 | 966 | |
974 | 967 | 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 | 968 | |
980 | -retry: | |
981 | - list_for_each_entry(__bcd, &bsg_class_list, list) { | |
982 | - if (__bcd->minor == bsg_minor_idx) { | |
983 | - bsg_minor_idx++; | |
984 | - if (bsg_minor_idx == BSG_MAX_DEVS) | |
985 | - bsg_minor_idx = 0; | |
986 | - goto retry; | |
987 | - } | |
969 | + ret = idr_pre_get(&bsg_minor_idr, GFP_KERNEL); | |
970 | + if (!ret) { | |
971 | + ret = -ENOMEM; | |
972 | + goto unlock; | |
988 | 973 | } |
989 | 974 | |
990 | - bcd->minor = bsg_minor_idx++; | |
991 | - if (bsg_minor_idx == BSG_MAX_DEVS) | |
992 | - bsg_minor_idx = 0; | |
975 | + ret = idr_get_new(&bsg_minor_idr, bcd, &minor); | |
976 | + if (ret < 0) | |
977 | + goto unlock; | |
993 | 978 | |
979 | + if (minor >= BSG_MAX_DEVS) { | |
980 | + printk(KERN_ERR "bsg: too many bsg devices\n"); | |
981 | + ret = -EINVAL; | |
982 | + goto remove_idr; | |
983 | + } | |
984 | + | |
985 | + bcd->minor = minor; | |
994 | 986 | bcd->queue = q; |
995 | 987 | bcd->dev = get_device(gdev); |
996 | 988 | dev = MKDEV(bsg_major, bcd->minor); |
997 | 989 | |
998 | 990 | |
999 | 991 | |
1000 | 992 | |
1001 | 993 | |
... | ... | @@ -998,27 +990,26 @@ |
998 | 990 | devname); |
999 | 991 | if (IS_ERR(class_dev)) { |
1000 | 992 | ret = PTR_ERR(class_dev); |
1001 | - goto err_put; | |
993 | + goto put_dev; | |
1002 | 994 | } |
1003 | 995 | bcd->class_dev = class_dev; |
1004 | 996 | |
1005 | 997 | if (q->kobj.sd) { |
1006 | 998 | ret = sysfs_create_link(&q->kobj, &bcd->class_dev->kobj, "bsg"); |
1007 | 999 | if (ret) |
1008 | - goto err_unregister; | |
1000 | + goto unregister_class_dev; | |
1009 | 1001 | } |
1010 | 1002 | |
1011 | - list_add_tail(&bcd->list, &bsg_class_list); | |
1012 | - bsg_device_nr++; | |
1013 | - | |
1014 | 1003 | mutex_unlock(&bsg_mutex); |
1015 | 1004 | return 0; |
1016 | 1005 | |
1017 | -err_unregister: | |
1006 | +unregister_class_dev: | |
1018 | 1007 | class_device_unregister(class_dev); |
1019 | -err_put: | |
1008 | +put_dev: | |
1020 | 1009 | put_device(gdev); |
1021 | -err: | |
1010 | +remove_idr: | |
1011 | + idr_remove(&bsg_minor_idr, minor); | |
1012 | +unlock: | |
1022 | 1013 | mutex_unlock(&bsg_mutex); |
1023 | 1014 | return ret; |
1024 | 1015 | } |