1 /*
2  *  Code extracted from drivers/block/genhd.c
3  *  Copyright (C) 1991-1998  Linus Torvalds
4  *  Re-organised Feb 1998 Russell King
5  *
6  *  We now have independent partition support from the
7  *  block drivers, which allows all the partition code to
8  *  be grouped in one location, and it to be mostly self
9  *  contained.
10  *
11  *  Added needed MAJORS for new pairs, {hdi,hdj}, {hdk,hdl}
12  */
13 
14 #include <linux/config.h>
15 #include <linux/fs.h>
16 #include <linux/genhd.h>
17 #include <linux/kernel.h>
18 #include <linux/major.h>
19 #include <linux/blk.h>
20 #include <linux/init.h>
21 #include <linux/raid/md.h>
22 
23 #include "check.h"
24 
25 #include "acorn.h"
26 #include "amiga.h"
27 #include "atari.h"
28 #include "ldm.h"
29 #include "mac.h"
30 #include "msdos.h"
31 #include "osf.h"
32 #include "sgi.h"
33 #include "sun.h"
34 #include "ibm.h"
35 #include "ultrix.h"
36 #include "efi.h"
37 
38 extern int *blk_size[];
39 
40 int warn_no_part = 1; /*This is ugly: should make genhd removable media aware*/
41 
42 static int (*check_part[])(struct gendisk *hd, struct block_device *bdev, unsigned long first_sect, int first_minor) = {
43 #ifdef CONFIG_ACORN_PARTITION
44 	acorn_partition,
45 #endif
46 #ifdef CONFIG_SGI_PARTITION
47 	sgi_partition,
48 #endif
49 #ifdef CONFIG_EFI_PARTITION
50 	efi_partition,		/* this must come before msdos */
51 #endif
52 #ifdef CONFIG_LDM_PARTITION
53 	ldm_partition,		/* this must come before msdos */
54 #endif
55 #ifdef CONFIG_MSDOS_PARTITION
56 	msdos_partition,
57 #endif
58 #ifdef CONFIG_OSF_PARTITION
59 	osf_partition,
60 #endif
61 #ifdef CONFIG_SUN_PARTITION
62 	sun_partition,
63 #endif
64 #ifdef CONFIG_AMIGA_PARTITION
65 	amiga_partition,
66 #endif
67 #ifdef CONFIG_ATARI_PARTITION
68 	atari_partition,
69 #endif
70 #ifdef CONFIG_MAC_PARTITION
71 	mac_partition,
72 #endif
73 #ifdef CONFIG_ULTRIX_PARTITION
74 	ultrix_partition,
75 #endif
76 #ifdef CONFIG_IBM_PARTITION
77 	ibm_partition,
78 #endif
79 	NULL
80 };
81 
82 /*
83  *	This is ucking fugly but its probably the best thing for 2.4.x
84  *	Take it as a clear reminder that: 1) we should put the device name
85  *	generation in the object kdev_t points to in 2.5.
86  *	and 2) ioctls better work on half-opened devices.
87  */
88 
89 #ifdef CONFIG_ARCH_S390
90 int (*genhd_dasd_name)(char*,int,int,struct gendisk*) = NULL;
91 int (*genhd_dasd_ioctl)(struct inode *inp, struct file *filp,
92 			    unsigned int no, unsigned long data);
93 EXPORT_SYMBOL(genhd_dasd_name);
94 EXPORT_SYMBOL(genhd_dasd_ioctl);
95 #endif
96 
97 /*
98  * disk_name() is used by partition check code and the md driver.
99  * It formats the devicename of the indicated disk into
100  * the supplied buffer (of size at least 32), and returns
101  * a pointer to that same buffer (for convenience).
102  */
103 
disk_name(struct gendisk * hd,int minor,char * buf)104 char *disk_name (struct gendisk *hd, int minor, char *buf)
105 {
106 	const char *maj = hd->major_name;
107 	unsigned int unit = (minor >> hd->minor_shift);
108 	unsigned int part = (minor & ((1 << hd->minor_shift) -1 ));
109 
110 	if ((unit < hd->nr_real) && hd->part[minor].de) {
111 		int pos;
112 
113 		pos = devfs_generate_path (hd->part[minor].de, buf, 64);
114 		if (pos >= 0)
115 			return buf + pos;
116 	}
117 
118 #ifdef CONFIG_ARCH_S390
119 	if (genhd_dasd_name
120 	    && genhd_dasd_name (buf, unit, part, hd) == 0)
121 		return buf;
122 #endif
123 	/*
124 	 * IDE devices use multiple major numbers, but the drives
125 	 * are named as:  {hda,hdb}, {hdc,hdd}, {hde,hdf}, {hdg,hdh}..
126 	 * This requires special handling here.
127 	 */
128 	switch (hd->major) {
129 		case IDE9_MAJOR:
130 			unit += 2;
131 		case IDE8_MAJOR:
132 			unit += 2;
133 		case IDE7_MAJOR:
134 			unit += 2;
135 		case IDE6_MAJOR:
136 			unit += 2;
137 		case IDE5_MAJOR:
138 			unit += 2;
139 		case IDE4_MAJOR:
140 			unit += 2;
141 		case IDE3_MAJOR:
142 			unit += 2;
143 		case IDE2_MAJOR:
144 			unit += 2;
145 		case IDE1_MAJOR:
146 			unit += 2;
147 		case IDE0_MAJOR:
148 			maj = "hd";
149 			break;
150 		case MD_MAJOR:
151 			sprintf(buf, "%s%d", maj, unit);
152 			return buf;
153 	}
154 	if (hd->major >= SCSI_DISK1_MAJOR && hd->major <= SCSI_DISK7_MAJOR) {
155 		unit = unit + (hd->major - SCSI_DISK1_MAJOR + 1) * 16;
156 		if (unit+'a' > 'z') {
157 			unit -= 26;
158 			sprintf(buf, "sd%c%c", 'a' + unit / 26, 'a' + unit % 26);
159 			if (part)
160 				sprintf(buf + 4, "%d", part);
161 			return buf;
162 		}
163 	}
164 	if (hd->major >= COMPAQ_SMART2_MAJOR && hd->major <= COMPAQ_SMART2_MAJOR+7) {
165 		int ctlr = hd->major - COMPAQ_SMART2_MAJOR;
166  		if (part == 0)
167  			sprintf(buf, "%s/c%dd%d", maj, ctlr, unit);
168  		else
169  			sprintf(buf, "%s/c%dd%dp%d", maj, ctlr, unit, part);
170  		return buf;
171  	}
172 	if (hd->major >= COMPAQ_CISS_MAJOR && hd->major <= COMPAQ_CISS_MAJOR+7) {
173                 int ctlr = hd->major - COMPAQ_CISS_MAJOR;
174                 if (part == 0)
175                         sprintf(buf, "%s/c%dd%d", maj, ctlr, unit);
176                 else
177                         sprintf(buf, "%s/c%dd%dp%d", maj, ctlr, unit, part);
178                 return buf;
179 	}
180 	if (hd->major >= DAC960_MAJOR && hd->major <= DAC960_MAJOR+7) {
181 		int ctlr = hd->major - DAC960_MAJOR;
182  		if (part == 0)
183  			sprintf(buf, "%s/c%dd%d", maj, ctlr, unit);
184  		else
185  			sprintf(buf, "%s/c%dd%dp%d", maj, ctlr, unit, part);
186  		return buf;
187  	}
188 	if (hd->major == ATARAID_MAJOR) {
189 		int disk = minor >> hd->minor_shift;
190 		int part = minor & (( 1 << hd->minor_shift) - 1);
191 		if (part == 0)
192 			sprintf(buf, "%s/d%d", maj, disk);
193 		else
194 			sprintf(buf, "%s/d%dp%d", maj, disk, part);
195 		return buf;
196 	}
197 	if (part)
198 		sprintf(buf, "%s%c%d", maj, unit+'a', part);
199 	else
200 		sprintf(buf, "%s%c", maj, unit+'a');
201 	return buf;
202 }
203 
204 /*
205  * Add a partitions details to the devices partition description.
206  */
add_gd_partition(struct gendisk * hd,int minor,unsigned int start,unsigned int size)207 void add_gd_partition(struct gendisk *hd, int minor, unsigned int start,
208                       unsigned int size)
209 {
210 #ifndef CONFIG_DEVFS_FS
211 	char buf[40];
212 #endif
213 
214 	hd->part[minor].start_sect = start;
215 	hd->part[minor].nr_sects   = size;
216 #ifdef CONFIG_DEVFS_FS
217 	printk(" p%d", (minor & ((1 << hd->minor_shift) - 1)));
218 #else
219 	if ((hd->major >= COMPAQ_SMART2_MAJOR+0 && hd->major <= COMPAQ_SMART2_MAJOR+7) ||
220 	    (hd->major >= COMPAQ_CISS_MAJOR+0 && hd->major <= COMPAQ_CISS_MAJOR+7))
221 		printk(" p%d", (minor & ((1 << hd->minor_shift) - 1)));
222 	else
223 		printk(" %s", disk_name(hd, minor, buf));
224 #endif
225 }
226 
check_partition(struct gendisk * hd,kdev_t dev,int first_part_minor)227 static void check_partition(struct gendisk *hd, kdev_t dev, int first_part_minor)
228 {
229 	devfs_handle_t de = NULL;
230 	static int first_time = 1;
231 	unsigned long first_sector;
232 	struct block_device *bdev;
233 	char buf[64];
234 	int i;
235 
236 	if (first_time)
237 		printk(KERN_INFO "Partition check:\n");
238 	first_time = 0;
239 	first_sector = hd->part[MINOR(dev)].start_sect;
240 
241 	/*
242 	 * This is a kludge to allow the partition check to be
243 	 * skipped for specific drives (e.g. IDE CD-ROM drives)
244 	 */
245 	if ((int)first_sector == -1) {
246 		hd->part[MINOR(dev)].start_sect = 0;
247 		return;
248 	}
249 
250 	if (hd->de_arr)
251 		de = hd->de_arr[MINOR(dev) >> hd->minor_shift];
252 	i = devfs_generate_path (de, buf, sizeof buf);
253 	if (i >= 0)
254 		printk(KERN_INFO " /dev/%s:", buf + i);
255 	else
256 		printk(KERN_INFO " %s:", disk_name(hd, MINOR(dev), buf));
257 	bdev = bdget(kdev_t_to_nr(dev));
258 	bdev->bd_inode->i_size = (loff_t)hd->part[MINOR(dev)].nr_sects << 9;
259 	bdev->bd_inode->i_blkbits = blksize_bits(block_size(dev));
260 	for (i = 0; check_part[i]; i++) {
261 		int res;
262 		res = check_part[i](hd, bdev, first_sector, first_part_minor);
263 		if (res) {
264 			if (res < 0 &&  warn_no_part)
265 				printk(" unable to read partition table\n");
266 			goto setup_devfs;
267 		}
268 	}
269 
270 	printk(" unknown partition table\n");
271 setup_devfs:
272 	invalidate_bdev(bdev, 1);
273 	truncate_inode_pages(bdev->bd_inode->i_mapping, 0);
274 	bdput(bdev);
275 	i = first_part_minor - 1;
276 	devfs_register_partitions (hd, i, hd->sizes ? 0 : 1);
277 }
278 
279 #ifdef CONFIG_DEVFS_FS
devfs_register_partition(struct gendisk * dev,int minor,int part)280 static void devfs_register_partition (struct gendisk *dev, int minor, int part)
281 {
282 	int devnum = minor >> dev->minor_shift;
283 	devfs_handle_t dir;
284 	unsigned int devfs_flags = DEVFS_FL_DEFAULT;
285 	char devname[16];
286 
287 	if (dev->part[minor + part].de) return;
288 	dir = devfs_get_parent (dev->part[minor].de);
289 	if (!dir) return;
290 	if ( dev->flags && (dev->flags[devnum] & GENHD_FL_REMOVABLE) )
291 		devfs_flags |= DEVFS_FL_REMOVABLE;
292 	sprintf (devname, "part%d", part);
293 	dev->part[minor + part].de =
294 	    devfs_register (dir, devname, devfs_flags,
295 			    dev->major, minor + part,
296 			    S_IFBLK | S_IRUSR | S_IWUSR,
297 			    dev->fops, NULL);
298 }
299 
300 static struct unique_numspace disc_numspace = UNIQUE_NUMBERSPACE_INITIALISER;
301 
devfs_register_disc(struct gendisk * dev,int minor)302 static void devfs_register_disc (struct gendisk *dev, int minor)
303 {
304 	int pos = 0;
305 	int devnum = minor >> dev->minor_shift;
306 	devfs_handle_t dir, slave;
307 	unsigned int devfs_flags = DEVFS_FL_DEFAULT;
308 	char dirname[64], symlink[16];
309 	static devfs_handle_t devfs_handle;
310 
311 	if (dev->part[minor].de) return;
312 	if ( dev->flags && (dev->flags[devnum] & GENHD_FL_REMOVABLE) )
313 		devfs_flags |= DEVFS_FL_REMOVABLE;
314 	if (dev->de_arr) {
315 		dir = dev->de_arr[devnum];
316 		if (!dir)  /*  Aware driver wants to block disc management  */
317 			return;
318 		pos = devfs_generate_path (dir, dirname + 3, sizeof dirname-3);
319 		if (pos < 0) return;
320 		strncpy (dirname + pos, "../", 3);
321 	}
322 	else {
323 		/*  Unaware driver: construct "real" directory  */
324 		sprintf (dirname, "../%s/disc%d", dev->major_name, devnum);
325 		dir = devfs_mk_dir (NULL, dirname + 3, NULL);
326 	}
327 	if (!devfs_handle)
328 		devfs_handle = devfs_mk_dir (NULL, "discs", NULL);
329 	dev->part[minor].number = devfs_alloc_unique_number (&disc_numspace);
330 	sprintf (symlink, "disc%d", dev->part[minor].number);
331 	devfs_mk_symlink (devfs_handle, symlink, DEVFS_FL_DEFAULT,
332 			  dirname + pos, &slave, NULL);
333 	dev->part[minor].de =
334 	    devfs_register (dir, "disc", devfs_flags, dev->major, minor,
335 			    S_IFBLK | S_IRUSR | S_IWUSR, dev->fops, NULL);
336 	devfs_auto_unregister (dev->part[minor].de, slave);
337 	if (!dev->de_arr)
338 		devfs_auto_unregister (slave, dir);
339 }
340 #endif  /*  CONFIG_DEVFS_FS  */
341 
devfs_register_partitions(struct gendisk * dev,int minor,int unregister)342 void devfs_register_partitions (struct gendisk *dev, int minor, int unregister)
343 {
344 #ifdef CONFIG_DEVFS_FS
345 	int part;
346 
347 	if (!unregister)
348 		devfs_register_disc (dev, minor);
349 	for (part = 1; part < dev->max_p; part++) {
350 		if ( unregister || (dev->part[minor].nr_sects < 1) ||
351 		     (dev->part[part + minor].nr_sects < 1) ) {
352 			devfs_unregister (dev->part[part + minor].de);
353 			dev->part[part + minor].de = NULL;
354 			continue;
355 		}
356 		devfs_register_partition (dev, minor, part);
357 	}
358 	if (unregister) {
359 		devfs_unregister (dev->part[minor].de);
360 		dev->part[minor].de = NULL;
361 		devfs_dealloc_unique_number (&disc_numspace,
362 					     dev->part[minor].number);
363 	}
364 #endif  /*  CONFIG_DEVFS_FS  */
365 }
366 
367 /*
368  * This function will re-read the partition tables for a given device,
369  * and set things back up again.  There are some important caveats,
370  * however.  You must ensure that no one is using the device, and no one
371  * can start using the device while this function is being executed.
372  *
373  * Much of the cleanup from the old partition tables should have already been
374  * done
375  */
376 
register_disk(struct gendisk * gdev,kdev_t dev,unsigned minors,struct block_device_operations * ops,long size)377 void register_disk(struct gendisk *gdev, kdev_t dev, unsigned minors,
378 	struct block_device_operations *ops, long size)
379 {
380 	if (!gdev)
381 		return;
382 	grok_partitions(gdev, MINOR(dev)>>gdev->minor_shift, minors, size);
383 }
384 
grok_partitions(struct gendisk * dev,int drive,unsigned minors,long size)385 void grok_partitions(struct gendisk *dev, int drive, unsigned minors, long size)
386 {
387 	int i;
388 	int first_minor	= drive << dev->minor_shift;
389 	int end_minor	= first_minor + dev->max_p;
390 
391 	if(!dev->sizes)
392 		blk_size[dev->major] = NULL;
393 
394 	dev->part[first_minor].nr_sects = size;
395 	/* No such device or no minors to use for partitions */
396 	if ( !size && dev->flags && (dev->flags[drive] & GENHD_FL_REMOVABLE) )
397 		devfs_register_partitions (dev, first_minor, 0);
398 	if (!size || minors == 1)
399 		return;
400 
401 	if (dev->sizes) {
402 		dev->sizes[first_minor] = size >> (BLOCK_SIZE_BITS - 9);
403 		for (i = first_minor + 1; i < end_minor; i++)
404 			dev->sizes[i] = 0;
405 	}
406 	blk_size[dev->major] = dev->sizes;
407 	check_partition(dev, MKDEV(dev->major, first_minor), 1 + first_minor);
408 
409  	/*
410  	 * We need to set the sizes array before we will be able to access
411  	 * any of the partitions on this device.
412  	 */
413 	if (dev->sizes != NULL) {	/* optional safeguard in ll_rw_blk.c */
414 		for (i = first_minor; i < end_minor; i++)
415 			dev->sizes[i] = dev->part[i].nr_sects >> (BLOCK_SIZE_BITS - 9);
416 	}
417 }
418 
read_dev_sector(struct block_device * bdev,unsigned long n,Sector * p)419 unsigned char *read_dev_sector(struct block_device *bdev, unsigned long n, Sector *p)
420 {
421 	struct address_space *mapping = bdev->bd_inode->i_mapping;
422 	int sect = PAGE_CACHE_SIZE / 512;
423 	struct page *page;
424 
425 	page = read_cache_page(mapping, n/sect,
426 			(filler_t *)mapping->a_ops->readpage, NULL);
427 	if (!IS_ERR(page)) {
428 		wait_on_page(page);
429 		if (!Page_Uptodate(page))
430 			goto fail;
431 		if (PageError(page))
432 			goto fail;
433 		p->v = page;
434 		return (unsigned char *)page_address(page) + 512 * (n % sect);
435 fail:
436 		page_cache_release(page);
437 	}
438 	p->v = NULL;
439 	return NULL;
440 }
441