diff options
Diffstat (limited to 'block/genhd.c')
-rw-r--r-- | block/genhd.c | 106 |
1 files changed, 86 insertions, 20 deletions
diff --git a/block/genhd.c b/block/genhd.c index f1ed83f3f083..db57546a709d 100644 --- a/block/genhd.c +++ b/block/genhd.c | |||
@@ -38,34 +38,100 @@ static inline int major_to_index(int major) | |||
38 | return major % MAX_PROBE_HASH; | 38 | return major % MAX_PROBE_HASH; |
39 | } | 39 | } |
40 | 40 | ||
41 | #ifdef CONFIG_PROC_FS | 41 | struct blkdev_info { |
42 | /* get block device names in somewhat random order */ | 42 | int index; |
43 | int get_blkdev_list(char *p, int used) | 43 | struct blk_major_name *bd; |
44 | }; | ||
45 | |||
46 | /* | ||
47 | * iterate over a list of blkdev_info structures. allows | ||
48 | * the major_names array to be iterated over from outside this file | ||
49 | * must be called with the block_subsys_sem held | ||
50 | */ | ||
51 | void *get_next_blkdev(void *dev) | ||
52 | { | ||
53 | struct blkdev_info *info; | ||
54 | |||
55 | if (dev == NULL) { | ||
56 | info = kmalloc(sizeof(*info), GFP_KERNEL); | ||
57 | if (!info) | ||
58 | goto out; | ||
59 | info->index=0; | ||
60 | info->bd = major_names[info->index]; | ||
61 | if (info->bd) | ||
62 | goto out; | ||
63 | } else { | ||
64 | info = dev; | ||
65 | } | ||
66 | |||
67 | while (info->index < ARRAY_SIZE(major_names)) { | ||
68 | if (info->bd) | ||
69 | info->bd = info->bd->next; | ||
70 | if (info->bd) | ||
71 | goto out; | ||
72 | /* | ||
73 | * No devices on this chain, move to the next | ||
74 | */ | ||
75 | info->index++; | ||
76 | info->bd = (info->index < ARRAY_SIZE(major_names)) ? | ||
77 | major_names[info->index] : NULL; | ||
78 | if (info->bd) | ||
79 | goto out; | ||
80 | } | ||
81 | |||
82 | out: | ||
83 | return info; | ||
84 | } | ||
85 | |||
86 | void *acquire_blkdev_list(void) | ||
87 | { | ||
88 | down(&block_subsys_sem); | ||
89 | return get_next_blkdev(NULL); | ||
90 | } | ||
91 | |||
92 | void release_blkdev_list(void *dev) | ||
93 | { | ||
94 | up(&block_subsys_sem); | ||
95 | kfree(dev); | ||
96 | } | ||
97 | |||
98 | |||
99 | /* | ||
100 | * Count the number of records in the blkdev_list. | ||
101 | * must be called with the block_subsys_sem held | ||
102 | */ | ||
103 | int count_blkdev_list(void) | ||
44 | { | 104 | { |
45 | struct blk_major_name *n; | 105 | struct blk_major_name *n; |
46 | int i, len; | 106 | int i, count; |
47 | 107 | ||
48 | len = snprintf(p, (PAGE_SIZE-used), "\nBlock devices:\n"); | 108 | count = 0; |
49 | 109 | ||
50 | down(&block_subsys_sem); | ||
51 | for (i = 0; i < ARRAY_SIZE(major_names); i++) { | 110 | for (i = 0; i < ARRAY_SIZE(major_names); i++) { |
52 | for (n = major_names[i]; n; n = n->next) { | 111 | for (n = major_names[i]; n; n = n->next) |
53 | /* | 112 | count++; |
54 | * If the curent string plus the 5 extra characters | ||
55 | * in the line would run us off the page, then we're done | ||
56 | */ | ||
57 | if ((len + used + strlen(n->name) + 5) >= PAGE_SIZE) | ||
58 | goto page_full; | ||
59 | len += sprintf(p+len, "%3d %s\n", | ||
60 | n->major, n->name); | ||
61 | } | ||
62 | } | 113 | } |
63 | page_full: | ||
64 | up(&block_subsys_sem); | ||
65 | 114 | ||
66 | return len; | 115 | return count; |
67 | } | 116 | } |
68 | #endif | 117 | |
118 | /* | ||
119 | * extract the major and name values from a blkdev_info struct | ||
120 | * passed in as a void to *dev. Must be called with | ||
121 | * block_subsys_sem held | ||
122 | */ | ||
123 | int get_blkdev_info(void *dev, int *major, char **name) | ||
124 | { | ||
125 | struct blkdev_info *info = dev; | ||
126 | |||
127 | if (info->bd == NULL) | ||
128 | return 1; | ||
129 | |||
130 | *major = info->bd->major; | ||
131 | *name = info->bd->name; | ||
132 | return 0; | ||
133 | } | ||
134 | |||
69 | 135 | ||
70 | int register_blkdev(unsigned int major, const char *name) | 136 | int register_blkdev(unsigned int major, const char *name) |
71 | { | 137 | { |