diff options
Diffstat (limited to 'block/genhd.c')
| -rw-r--r-- | block/genhd.c | 103 |
1 files changed, 11 insertions, 92 deletions
diff --git a/block/genhd.c b/block/genhd.c index db4c60c802d6..5a8d3bf02f17 100644 --- a/block/genhd.c +++ b/block/genhd.c | |||
| @@ -17,8 +17,6 @@ | |||
| 17 | #include <linux/buffer_head.h> | 17 | #include <linux/buffer_head.h> |
| 18 | #include <linux/mutex.h> | 18 | #include <linux/mutex.h> |
| 19 | 19 | ||
| 20 | #define MAX_PROBE_HASH 255 /* random */ | ||
| 21 | |||
| 22 | static struct subsystem block_subsys; | 20 | static struct subsystem block_subsys; |
| 23 | 21 | ||
| 24 | static DEFINE_MUTEX(block_subsys_lock); | 22 | static DEFINE_MUTEX(block_subsys_lock); |
| @@ -31,108 +29,29 @@ static struct blk_major_name { | |||
| 31 | struct blk_major_name *next; | 29 | struct blk_major_name *next; |
| 32 | int major; | 30 | int major; |
| 33 | char name[16]; | 31 | char name[16]; |
| 34 | } *major_names[MAX_PROBE_HASH]; | 32 | } *major_names[BLKDEV_MAJOR_HASH_SIZE]; |
| 35 | 33 | ||
| 36 | /* index in the above - for now: assume no multimajor ranges */ | 34 | /* index in the above - for now: assume no multimajor ranges */ |
| 37 | static inline int major_to_index(int major) | 35 | static inline int major_to_index(int major) |
| 38 | { | 36 | { |
| 39 | return major % MAX_PROBE_HASH; | 37 | return major % BLKDEV_MAJOR_HASH_SIZE; |
| 40 | } | ||
| 41 | |||
| 42 | struct blkdev_info { | ||
| 43 | int index; | ||
| 44 | struct blk_major_name *bd; | ||
| 45 | }; | ||
| 46 | |||
| 47 | /* | ||
| 48 | * iterate over a list of blkdev_info structures. allows | ||
| 49 | * the major_names array to be iterated over from outside this file | ||
| 50 | * must be called with the block_subsys_lock held | ||
| 51 | */ | ||
| 52 | void *get_next_blkdev(void *dev) | ||
| 53 | { | ||
| 54 | struct blkdev_info *info; | ||
| 55 | |||
| 56 | if (dev == NULL) { | ||
| 57 | info = kmalloc(sizeof(*info), GFP_KERNEL); | ||
| 58 | if (!info) | ||
| 59 | goto out; | ||
| 60 | info->index=0; | ||
| 61 | info->bd = major_names[info->index]; | ||
| 62 | if (info->bd) | ||
| 63 | goto out; | ||
| 64 | } else { | ||
| 65 | info = dev; | ||
| 66 | } | ||
| 67 | |||
| 68 | while (info->index < ARRAY_SIZE(major_names)) { | ||
| 69 | if (info->bd) | ||
| 70 | info->bd = info->bd->next; | ||
| 71 | if (info->bd) | ||
| 72 | goto out; | ||
| 73 | /* | ||
| 74 | * No devices on this chain, move to the next | ||
| 75 | */ | ||
| 76 | info->index++; | ||
| 77 | info->bd = (info->index < ARRAY_SIZE(major_names)) ? | ||
| 78 | major_names[info->index] : NULL; | ||
| 79 | if (info->bd) | ||
| 80 | goto out; | ||
| 81 | } | ||
| 82 | |||
| 83 | out: | ||
| 84 | return info; | ||
| 85 | } | ||
| 86 | |||
| 87 | void *acquire_blkdev_list(void) | ||
| 88 | { | ||
| 89 | mutex_lock(&block_subsys_lock); | ||
| 90 | return get_next_blkdev(NULL); | ||
| 91 | } | ||
| 92 | |||
| 93 | void release_blkdev_list(void *dev) | ||
| 94 | { | ||
| 95 | mutex_unlock(&block_subsys_lock); | ||
| 96 | kfree(dev); | ||
| 97 | } | 38 | } |
| 98 | 39 | ||
| 40 | #ifdef CONFIG_PROC_FS | ||
| 99 | 41 | ||
| 100 | /* | 42 | void blkdev_show(struct seq_file *f, off_t offset) |
| 101 | * Count the number of records in the blkdev_list. | ||
| 102 | * must be called with the block_subsys_lock held | ||
| 103 | */ | ||
| 104 | int count_blkdev_list(void) | ||
| 105 | { | 43 | { |
| 106 | struct blk_major_name *n; | 44 | struct blk_major_name *dp; |
| 107 | int i, count; | ||
| 108 | 45 | ||
| 109 | count = 0; | 46 | if (offset < BLKDEV_MAJOR_HASH_SIZE) { |
| 110 | 47 | mutex_lock(&block_subsys_lock); | |
| 111 | for (i = 0; i < ARRAY_SIZE(major_names); i++) { | 48 | for (dp = major_names[offset]; dp; dp = dp->next) |
| 112 | for (n = major_names[i]; n; n = n->next) | 49 | seq_printf(f, "%3d %s\n", dp->major, dp->name); |
| 113 | count++; | 50 | mutex_unlock(&block_subsys_lock); |
| 114 | } | 51 | } |
| 115 | |||
| 116 | return count; | ||
| 117 | } | ||
| 118 | |||
| 119 | /* | ||
| 120 | * extract the major and name values from a blkdev_info struct | ||
| 121 | * passed in as a void to *dev. Must be called with | ||
| 122 | * block_subsys_lock held | ||
| 123 | */ | ||
| 124 | int get_blkdev_info(void *dev, int *major, char **name) | ||
| 125 | { | ||
| 126 | struct blkdev_info *info = dev; | ||
| 127 | |||
| 128 | if (info->bd == NULL) | ||
| 129 | return 1; | ||
| 130 | |||
| 131 | *major = info->bd->major; | ||
| 132 | *name = info->bd->name; | ||
| 133 | return 0; | ||
| 134 | } | 52 | } |
| 135 | 53 | ||
| 54 | #endif /* CONFIG_PROC_FS */ | ||
| 136 | 55 | ||
| 137 | int register_blkdev(unsigned int major, const char *name) | 56 | int register_blkdev(unsigned int major, const char *name) |
| 138 | { | 57 | { |
