1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17#include <linux/config.h>
18#include <linux/module.h>
19#include <linux/fs.h>
20#include <linux/genhd.h>
21#include <linux/kernel.h>
22#include <linux/blk.h>
23#include <linux/init.h>
24#include <linux/spinlock.h>
25#include <linux/seq_file.h>
26
27
28
29
30
31
32
33
34 struct gendisk *gendisk_head;
35static struct gendisk *gendisk_array[MAX_BLKDEV];
36static rwlock_t gendisk_lock = RW_LOCK_UNLOCKED;
37
38EXPORT_SYMBOL(gendisk_head);
39
40
41
42
43
44
45
46
47
48void
49add_gendisk(struct gendisk *gp)
50{
51 struct gendisk *sgp;
52
53 write_lock(&gendisk_lock);
54
55
56
57
58
59
60 for (sgp = gendisk_head; sgp; sgp = sgp->next)
61 {
62 if (sgp == gp)
63 {
64
65
66 goto out;
67 }
68 }
69 gendisk_array[gp->major] = gp;
70 gp->next = gendisk_head;
71 gendisk_head = gp;
72out:
73 write_unlock(&gendisk_lock);
74}
75
76EXPORT_SYMBOL(add_gendisk);
77
78
79
80
81
82
83
84
85
86void
87del_gendisk(struct gendisk *gp)
88{
89 struct gendisk **gpp;
90
91 write_lock(&gendisk_lock);
92 gendisk_array[gp->major] = NULL;
93 for (gpp = &gendisk_head; *gpp; gpp = &((*gpp)->next))
94 if (*gpp == gp)
95 break;
96 if (*gpp)
97 *gpp = (*gpp)->next;
98 write_unlock(&gendisk_lock);
99}
100
101EXPORT_SYMBOL(del_gendisk);
102
103
104
105
106
107
108
109
110
111struct gendisk *
112get_gendisk(kdev_t dev)
113{
114 struct gendisk *gp = NULL;
115 int maj = MAJOR(dev);
116
117 read_lock(&gendisk_lock);
118 if ((gp = gendisk_array[maj]))
119 goto out;
120
121
122 for (gp = gendisk_head; gp; gp = gp->next)
123 if (gp->major == maj)
124 break;
125out:
126 read_unlock(&gendisk_lock);
127 return gp;
128}
129
130EXPORT_SYMBOL(get_gendisk);
131
132
133
134
135
136
137
138
139
140
141int
142walk_gendisk(int (*walk)(struct gendisk *, void *), void *data)
143{
144 struct gendisk *gp;
145 int error = 0;
146
147 read_lock(&gendisk_lock);
148 for (gp = gendisk_head; gp; gp = gp->next)
149 if ((error = walk(gp, data)))
150 break;
151 read_unlock(&gendisk_lock);
152
153 return error;
154}
155
156#ifdef CONFIG_PROC_FS
157
158static void *part_start(struct seq_file *s, loff_t *ppos)
159{
160 struct gendisk *gp;
161 loff_t pos = *ppos;
162
163 read_lock(&gendisk_lock);
164 for (gp = gendisk_head; gp; gp = gp->next)
165 if (!pos--)
166 return gp;
167 return NULL;
168}
169
170static void *part_next(struct seq_file *s, void *v, loff_t *pos)
171{
172 ++*pos;
173 return ((struct gendisk *)v)->next;
174}
175
176static void part_stop(struct seq_file *s, void *v)
177{
178 read_unlock(&gendisk_lock);
179}
180
181static int part_show(struct seq_file *s, void *v)
182{
183 struct gendisk *gp = v;
184 char buf[64];
185 int n;
186
187 if (gp == gendisk_head) {
188 seq_puts(s, "major minor #blocks name"
189#ifdef CONFIG_BLK_STATS
190 " rio rmerge rsect ruse wio wmerge "
191 "wsect wuse running use aveq"
192#endif
193 "\n\n");
194 }
195
196
197 for (n = 0; n < (gp->nr_real << gp->minor_shift); n++) {
198 if (gp->part[n].nr_sects) {
199#ifdef CONFIG_BLK_STATS
200 struct hd_struct *hd = &gp->part[n];
201
202 disk_round_stats(hd);
203 seq_printf(s, "%4d %4d %10d %s "
204 "%d %d %d %d %d %d %d %d %d %d %d\n",
205 gp->major, n, gp->sizes[n],
206 disk_name(gp, n, buf),
207 hd->rd_ios, hd->rd_merges,
208#define MSEC(x) ((x) * 1000 / HZ)
209 hd->rd_sectors, MSEC(hd->rd_ticks),
210 hd->wr_ios, hd->wr_merges,
211 hd->wr_sectors, MSEC(hd->wr_ticks),
212 hd->ios_in_flight, MSEC(hd->io_ticks),
213 MSEC(hd->aveq));
214#else
215 seq_printf(s, "%4d %4d %10d %s\n",
216 gp->major, n, gp->sizes[n],
217 disk_name(gp, n, buf));
218#endif
219 }
220 }
221
222 return 0;
223}
224
225struct seq_operations partitions_op = {
226 .start = part_start,
227 .next = part_next,
228 .stop = part_stop,
229 .show = part_show,
230};
231#endif
232
233extern int blk_dev_init(void);
234extern int net_dev_init(void);
235extern void console_map_init(void);
236extern int atmdev_init(void);
237
238int __init device_init(void)
239{
240 blk_dev_init();
241 sti();
242#ifdef CONFIG_NET
243 net_dev_init();
244#endif
245#ifdef CONFIG_ATM
246 (void) atmdev_init();
247#endif
248#ifdef CONFIG_VT
249 console_map_init();
250#endif
251 return 0;
252}
253
254__initcall(device_init);
255