⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 check.c

📁 Linux内核源代码 为压缩文件 是<<Linux内核>>一书中的源代码
💻 C
字号:
/* *  Code extracted from drivers/block/genhd.c *  Copyright (C) 1991-1998  Linus Torvalds *  Re-organised Feb 1998 Russell King * *  We now have independent partition support from the *  block drivers, which allows all the partition code to *  be grouped in one location, and it to be mostly self *  contained. * *  Added needed MAJORS for new pairs, {hdi,hdj}, {hdk,hdl} */#include <linux/config.h>#include <linux/fs.h>#include <linux/genhd.h>#include <linux/kernel.h>#include <linux/major.h>#include <linux/blk.h>#include <linux/init.h>#include <linux/raid/md.h>#include "check.h"#include "acorn.h"#include "amiga.h"#include "atari.h"#include "mac.h"#include "msdos.h"#include "osf.h"#include "sgi.h"#include "sun.h"#include "ibm.h"#include "ultrix.h"extern void device_init(void);extern int *blk_size[];extern void rd_load(void);extern void initrd_load(void);struct gendisk *gendisk_head;int warn_no_part = 1; /*This is ugly: should make genhd removable media aware*/static int (*check_part[])(struct gendisk *hd, kdev_t dev, unsigned long first_sect, int first_minor) = {#ifdef CONFIG_ACORN_PARTITION	acorn_partition,#endif#ifdef CONFIG_MSDOS_PARTITION	msdos_partition,#endif#ifdef CONFIG_OSF_PARTITION	osf_partition,#endif#ifdef CONFIG_SUN_PARTITION	sun_partition,#endif#ifdef CONFIG_AMIGA_PARTITION	amiga_partition,#endif#ifdef CONFIG_ATARI_PARTITION	atari_partition,#endif#ifdef CONFIG_MAC_PARTITION	mac_partition,#endif#ifdef CONFIG_SGI_PARTITION	sgi_partition,#endif#ifdef CONFIG_ULTRIX_PARTITION	ultrix_partition,#endif#ifdef CONFIG_IBM_PARTITION	ibm_partition,#endif	NULL};/* * disk_name() is used by genhd.c and blkpg.c. * It formats the devicename of the indicated disk into * the supplied buffer (of size at least 32), and returns * a pointer to that same buffer (for convenience). */char *disk_name (struct gendisk *hd, int minor, char *buf){	unsigned int part;	const char *maj = hd->major_name;	int unit = (minor >> hd->minor_shift) + 'a';	part = minor & ((1 << hd->minor_shift) - 1);	if (hd->part[minor].de) {		int pos;		pos = devfs_generate_path (hd->part[minor].de, buf, 64);		if (pos >= 0)			return buf + pos;	}	/*	 * IDE devices use multiple major numbers, but the drives	 * are named as:  {hda,hdb}, {hdc,hdd}, {hde,hdf}, {hdg,hdh}..	 * This requires special handling here.	 */	switch (hd->major) {		case IDE9_MAJOR:			unit += 2;		case IDE8_MAJOR:			unit += 2;		case IDE7_MAJOR:			unit += 2;		case IDE6_MAJOR:			unit += 2;		case IDE5_MAJOR:			unit += 2;		case IDE4_MAJOR:			unit += 2;		case IDE3_MAJOR:			unit += 2;		case IDE2_MAJOR:			unit += 2;		case IDE1_MAJOR:			unit += 2;		case IDE0_MAJOR:			maj = "hd";			break;		case MD_MAJOR:			sprintf(buf, "%s%d", maj, unit - 'a');			return buf;	}	if (hd->major >= SCSI_DISK1_MAJOR && hd->major <= SCSI_DISK7_MAJOR) {		unit = unit + (hd->major - SCSI_DISK1_MAJOR + 1) * 16;		if (unit > 'z') {			unit -= 'z' + 1;			sprintf(buf, "sd%c%c", 'a' + unit / 26, 'a' + unit % 26);			if (part)				sprintf(buf + 4, "%d", part);			return buf;		}	}	if (hd->major >= COMPAQ_SMART2_MAJOR && hd->major <= COMPAQ_SMART2_MAJOR+7) {		int ctlr = hd->major - COMPAQ_SMART2_MAJOR; 		int disk = minor >> hd->minor_shift; 		int part = minor & (( 1 << hd->minor_shift) - 1); 		if (part == 0) 			sprintf(buf, "%s/c%dd%d", maj, ctlr, disk); 		else 			sprintf(buf, "%s/c%dd%dp%d", maj, ctlr, disk, part); 		return buf; 	}	if (hd->major >= COMPAQ_CISS_MAJOR && hd->major <= COMPAQ_CISS_MAJOR+7) {                int ctlr = hd->major - COMPAQ_CISS_MAJOR;                int disk = minor >> hd->minor_shift;                int part = minor & (( 1 << hd->minor_shift) - 1);                if (part == 0)                        sprintf(buf, "%s/c%dd%d", maj, ctlr, disk);                else                        sprintf(buf, "%s/c%dd%dp%d", maj, ctlr, disk, part);                return buf;	}	if (hd->major >= DAC960_MAJOR && hd->major <= DAC960_MAJOR+7) {		int ctlr = hd->major - DAC960_MAJOR; 		int disk = minor >> hd->minor_shift; 		int part = minor & (( 1 << hd->minor_shift) - 1); 		if (part == 0) 			sprintf(buf, "%s/c%dd%d", maj, ctlr, disk); 		else 			sprintf(buf, "%s/c%dd%dp%d", maj, ctlr, disk, part); 		return buf; 	}	if (part)		sprintf(buf, "%s%c%d", maj, unit, part);	else		sprintf(buf, "%s%c", maj, unit);	return buf;}/* * Add a partitions details to the devices partition description. */void add_gd_partition(struct gendisk *hd, int minor, int start, int size){#ifndef CONFIG_DEVFS_FS	char buf[40];#endif	hd->part[minor].start_sect = start;	hd->part[minor].nr_sects   = size;#ifdef CONFIG_DEVFS_FS	printk(" p%d", (minor & ((1 << hd->minor_shift) - 1)));#else	if ((hd->major >= COMPAQ_SMART2_MAJOR+0 && hd->major <= COMPAQ_SMART2_MAJOR+7) ||	    (hd->major >= COMPAQ_CISS_MAJOR+0 && hd->major <= COMPAQ_CISS_MAJOR+7))		printk(" p%d", (minor & ((1 << hd->minor_shift) - 1)));	else		printk(" %s", disk_name(hd, minor, buf));#endif}unsigned int get_ptable_blocksize(kdev_t dev){	int ret = 1024;	/*	 * See whether the low-level driver has given us a minumum blocksize.	 * If so, check to see whether it is larger than the default of 1024.	 */	if (!blksize_size[MAJOR(dev)])		return ret;	/*	 * Check for certain special power of two sizes that we allow.	 * With anything larger than 1024, we must force the blocksize up to	 * the natural blocksize for the device so that we don't have to try	 * and read partial sectors.  Anything smaller should be just fine.	 */	switch (blksize_size[MAJOR(dev)][MINOR(dev)]) {		case 2048:			ret = 2048;			break;		case 4096:			ret = 4096;			break;		case 8192:			ret = 8192;			break;		case 1024:		case 512:		case 256:		case 0:			/*			 * These are all OK.			 */			break;		default:			panic("Strange blocksize for partition table\n");	}	return ret;}#ifdef CONFIG_PROC_FSint get_partition_list(char *page, char **start, off_t offset, int count){	struct gendisk *dsk;	int len;	len = sprintf(page, "major minor  #blocks  name\n\n");	for (dsk = gendisk_head; dsk; dsk = dsk->next) {		int n;		for (n = 0; n < (dsk->nr_real << dsk->minor_shift); n++)			if (dsk->part[n].nr_sects) {				char buf[64];				len += sprintf(page + len,					       "%4d  %4d %10d %s\n",					       dsk->major, n, dsk->sizes[n],					       disk_name(dsk, n, buf));				if (len < offset)					offset -= len, len = 0;				else if (len >= offset + count)					goto leave_loops;			}	}leave_loops:	*start = page + offset;	len -= offset;	if (len < 0)		len = 0;	return len > count ? count : len;}#endifstatic void check_partition(struct gendisk *hd, kdev_t dev, int first_part_minor){	devfs_handle_t de = NULL;	static int first_time = 1;	unsigned long first_sector;	char buf[64];	int i;	if (first_time)		printk(KERN_INFO "Partition check:\n");	first_time = 0;	first_sector = hd->part[MINOR(dev)].start_sect;	/*	 * This is a kludge to allow the partition check to be	 * skipped for specific drives (e.g. IDE CD-ROM drives)	 */	if ((int)first_sector == -1) {		hd->part[MINOR(dev)].start_sect = 0;		return;	}	if (hd->de_arr)		de = hd->de_arr[MINOR(dev) >> hd->minor_shift];	i = devfs_generate_path (de, buf, sizeof buf);	if (i >= 0)		printk(KERN_INFO " /dev/%s:", buf + i);	else		printk(KERN_INFO " %s:", disk_name(hd, MINOR(dev), buf));	for (i = 0; check_part[i]; i++)		if (check_part[i](hd, dev, first_sector, first_part_minor))			goto setup_devfs;	printk(" unknown partition table\n");setup_devfs:	i = first_part_minor - 1;	devfs_register_partitions (hd, i, hd->sizes ? 0 : 1);}#ifdef CONFIG_DEVFS_FSstatic void devfs_register_partition (struct gendisk *dev, int minor, int part){	int devnum = minor >> dev->minor_shift;	devfs_handle_t dir;	unsigned int devfs_flags = DEVFS_FL_DEFAULT;	char devname[16];	if (dev->part[minor + part].de) return;	dir = devfs_get_parent (dev->part[minor].de);	if (!dir) return;	if ( dev->flags && (dev->flags[devnum] & GENHD_FL_REMOVABLE) )		devfs_flags |= DEVFS_FL_REMOVABLE;	sprintf (devname, "part%d", part);	dev->part[minor + part].de =	    devfs_register (dir, devname, devfs_flags,			    dev->major, minor + part,			    S_IFBLK | S_IRUSR | S_IWUSR,			    dev->fops, NULL);}static void devfs_register_disc (struct gendisk *dev, int minor){	int pos = 0;	int devnum = minor >> dev->minor_shift;	devfs_handle_t dir, slave;	unsigned int devfs_flags = DEVFS_FL_DEFAULT;	char dirname[64], symlink[16];	static unsigned int disc_counter;	static devfs_handle_t devfs_handle;	if (dev->part[minor].de) return;	if ( dev->flags && (dev->flags[devnum] & GENHD_FL_REMOVABLE) )		devfs_flags |= DEVFS_FL_REMOVABLE;	if (dev->de_arr) {		dir = dev->de_arr[devnum];		if (!dir)  /*  Aware driver wants to block disc management  */			return;		pos = devfs_generate_path (dir, dirname + 3, sizeof dirname-3);		if (pos < 0) return;		strncpy (dirname + pos, "../", 3);	}	else {		/*  Unaware driver: construct "real" directory  */		sprintf (dirname, "../%s/disc%d", dev->major_name, devnum);		dir = devfs_mk_dir (NULL, dirname + 3, NULL);	}	if (!devfs_handle)		devfs_handle = devfs_mk_dir (NULL, "discs", NULL);	sprintf (symlink, "disc%u", disc_counter++);	devfs_mk_symlink (devfs_handle, symlink, DEVFS_FL_DEFAULT,			  dirname + pos, &slave, NULL);	dev->part[minor].de =	    devfs_register (dir, "disc", devfs_flags, dev->major, minor,			    S_IFBLK | S_IRUSR | S_IWUSR, dev->fops, NULL);	devfs_auto_unregister (dev->part[minor].de, slave);	if (!dev->de_arr)		devfs_auto_unregister (slave, dir);}#endif  /*  CONFIG_DEVFS_FS  */void devfs_register_partitions (struct gendisk *dev, int minor, int unregister){#ifdef CONFIG_DEVFS_FS	int part;	if (!unregister)		devfs_register_disc (dev, minor);	for (part = 1; part < dev->max_p; part++) {		if ( unregister || (dev->part[part + minor].nr_sects < 1) ) {			devfs_unregister (dev->part[part + minor].de);			dev->part[part + minor].de = NULL;			continue;		}		devfs_register_partition (dev, minor, part);	}	if (unregister) {		devfs_unregister (dev->part[minor].de);		dev->part[minor].de = NULL;	}#endif  /*  CONFIG_DEVFS_FS  */}/* * This function will re-read the partition tables for a given device, * and set things back up again.  There are some important caveats, * however.  You must ensure that no one is using the device, and no one * can start using the device while this function is being executed. * * Much of the cleanup from the old partition tables should have already been * done */void register_disk(struct gendisk *gdev, kdev_t dev, unsigned minors,	struct block_device_operations *ops, long size){	if (!gdev)		return;	grok_partitions(gdev, MINOR(dev)>>gdev->minor_shift, minors, size);}void grok_partitions(struct gendisk *dev, int drive, unsigned minors, long size){	int i;	int first_minor	= drive << dev->minor_shift;	int end_minor	= first_minor + dev->max_p;	if(!dev->sizes)		blk_size[dev->major] = NULL;	dev->part[first_minor].nr_sects = size;	/* No Such Agen^Wdevice or no minors to use for partitions */	if (!size || minors == 1)		return;	blk_size[dev->major] = NULL;	check_partition(dev, MKDEV(dev->major, first_minor), 1 + first_minor); 	/* 	 * We need to set the sizes array before we will be able to access 	 * any of the partitions on this device. 	 */	if (dev->sizes != NULL) {	/* optional safeguard in ll_rw_blk.c */		for (i = first_minor; i < end_minor; i++)			dev->sizes[i] = dev->part[i].nr_sects >> (BLOCK_SIZE_BITS - 9);		blk_size[dev->major] = dev->sizes;	}}int __init partition_setup(void){	device_init();#ifdef CONFIG_BLK_DEV_RAM#ifdef CONFIG_BLK_DEV_INITRD	if (initrd_start && mount_initrd) initrd_load();	else#endif	rd_load();#endif	return 0;}__initcall(partition_setup);

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -