Commit 598443a2124618fc8fe5a8bae32c129666ac3eab

Authored by FUJITA Tomonori
Committed by James Bottomley
1 parent 4b39c1d983

[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

... ... @@ -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 }
... ... @@ -53,7 +53,6 @@
53 53 struct class_device *class_dev;
54 54 struct device *dev;
55 55 int minor;
56   - struct list_head list;
57 56 struct request_queue *queue;
58 57 };
59 58