File: genhd.c

package info (click to toggle)
kernel-image-2.4.17-hppa 32.4
  • links: PTS
  • area: main
  • in suites: woody
  • size: 156,356 kB
  • ctags: 442,585
  • sloc: ansic: 2,542,442; asm: 144,771; makefile: 8,468; sh: 3,097; perl: 2,578; yacc: 1,177; tcl: 577; lex: 352; awk: 251; lisp: 218; sed: 72
file content (204 lines) | stat: -rw-r--r-- 3,994 bytes parent folder | download | duplicates (4)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
/*
 *  Code extracted from
 *  linux/kernel/hd.c
 *
 *  Copyright (C) 1991-1998  Linus Torvalds
 *
 *  devfs support - jj, rgooch, 980122
 *
 *  Moved partition checking code to fs/partitions* - Russell King
 *  (linux@arm.uk.linux.org)
 */

/*
 * TODO:  rip out the remaining init crap from this file  --hch
 */

#include <linux/config.h>
#include <linux/module.h>
#include <linux/fs.h>
#include <linux/genhd.h>
#include <linux/kernel.h>
#include <linux/blk.h>
#include <linux/init.h>
#include <linux/spinlock.h>


static rwlock_t gendisk_lock;

/*
 * Global kernel list of partitioning information.
 *
 * XXX: you should _never_ access this directly.
 *	the only reason this is exported is source compatiblity.
 */
/*static*/ struct gendisk *gendisk_head;

EXPORT_SYMBOL(gendisk_head);


/**
 * add_gendisk - add partitioning information to kernel list
 * @gp: per-device partitioning information
 *
 * This function registers the partitioning information in @gp
 * with the kernel.
 */
void
add_gendisk(struct gendisk *gp)
{
	struct gendisk *sgp;

	write_lock(&gendisk_lock);

	/*
 	 *	In 2.5 this will go away. Fix the drivers who rely on
 	 *	old behaviour.
 	 */

	for (sgp = gendisk_head; sgp; sgp = sgp->next)
	{
		if (sgp == gp)
		{
//			printk(KERN_ERR "add_gendisk: device major %d is buggy and added a live gendisk!\n",
//				sgp->major)
			goto out;
		}
	}
	gp->next = gendisk_head;
	gendisk_head = gp;
out:
	write_unlock(&gendisk_lock);
}

EXPORT_SYMBOL(add_gendisk);


/**
 * del_gendisk - remove partitioning information from kernel list
 * @gp: per-device partitioning information
 *
 * This function unregisters the partitioning information in @gp
 * with the kernel.
 */
void
del_gendisk(struct gendisk *gp)
{
	struct gendisk **gpp;

	write_lock(&gendisk_lock);
	for (gpp = &gendisk_head; *gpp; gpp = &((*gpp)->next))
		if (*gpp == gp)
			break;
	if (*gpp)
		*gpp = (*gpp)->next;
	write_unlock(&gendisk_lock);
}

EXPORT_SYMBOL(del_gendisk);


/**
 * get_gendisk - get partitioning information for a given device
 * @dev: device to get partitioning information for
 *
 * This function gets the structure containing partitioning
 * information for the given device @dev.
 */
struct gendisk *
get_gendisk(kdev_t dev)
{
	struct gendisk *gp = NULL;
	int maj = MAJOR(dev);

	read_lock(&gendisk_lock);
	for (gp = gendisk_head; gp; gp = gp->next)
		if (gp->major == maj)
			break;
	read_unlock(&gendisk_lock);

	return gp;
}

EXPORT_SYMBOL(get_gendisk);


#ifdef CONFIG_PROC_FS
int
get_partition_list(char *page, char **start, off_t offset, int count)
{
	struct gendisk *gp;
	char buf[64];
	int len, n;

	len = sprintf(page, "major minor  #blocks  name\n\n");
	read_lock(&gendisk_lock);
	for (gp = gendisk_head; gp; gp = gp->next) {
		for (n = 0; n < (gp->nr_real << gp->minor_shift); n++) {
			if (gp->part[n].nr_sects == 0)
				continue;

			len += snprintf(page + len, 63,
					"%4d  %4d %10d %s\n",
					gp->major, n, gp->sizes[n],
					disk_name(gp, n, buf));
			if (len < offset)
				offset -= len, len = 0;
			else if (len >= offset + count)
				goto out;
		}
	}

out:
	read_unlock(&gendisk_lock);
	*start = page + offset;
	len -= offset;
	if (len < 0)
		len = 0;
	return len > count ? count : len;
}
#endif


extern int blk_dev_init(void);
#ifdef CONFIG_FUSION_BOOT
extern int fusion_init(void);
#endif
extern int net_dev_init(void);
extern void console_map_init(void);
extern int soc_probe(void);
extern int atmdev_init(void);
extern int i2o_init(void);
extern int cpqarray_init(void);

int __init device_init(void)
{
	rwlock_init(&gendisk_lock);
	blk_dev_init();
	sti();
#ifdef CONFIG_I2O
	i2o_init();
#endif
#ifdef CONFIG_FUSION_BOOT
	fusion_init();
#endif
#ifdef CONFIG_FC4_SOC
	/* This has to be done before scsi_dev_init */
	soc_probe();
#endif
#ifdef CONFIG_BLK_CPQ_DA
	cpqarray_init();
#endif
#ifdef CONFIG_NET
	net_dev_init();
#endif
#ifdef CONFIG_ATM
	(void) atmdev_init();
#endif
#ifdef CONFIG_VT
	console_map_init();
#endif
	return 0;
}

__initcall(device_init);