kernels/linux-2.4.0/fs/partitions/msdos.c
/*
 * Create devices for each logical partition in an extended partition.
 * The logical partitions form a linked list, with each entry being
 * a partition table with two entries.  The first entry
 * is the real data partition (with a start relative to the partition
 * table start).  The second is a pointer to the next logical partition
 * (with a start relative to the entire extended partition).
 * We do not create a Linux partition for the partition tables, but
 * only for the actual data partitions.
 */
Create devices for each logical partition in an extended partition.
The logical partitions form a linked list, with each entry being
a partition table with two entries.  The first entry
is the real data partition (with a start relative to the partition
table start).  The second is a pointer to the next logical partition
(with a start relative to the entire extended partition).
We do not create a Linux partition for the partition tables, but
only for the actual data partitions.
Create devices for each logical partition in an extended partition . The logical partitions form a linked list with each entry being a partition table with two entries . The first entry is the real data partition ( with a start relative to the partition table start ) . The second is a pointer to the next logical partition ( with a start relative to the entire extended partition ) . We do not create a Linux partition for the partition tables but only for the actual data partitions .
static void extended_partition(struct gendisk *hd, kdev_t dev)
{
	struct buffer_head *bh;
	struct partition *p;
	unsigned long first_sector, first_size, this_sector, this_size;
	int mask = (1 << hd->minor_shift) - 1;
	int sector_size = get_hardsect_size(dev) / 512;
	int loopct = 0;		
	int i;
	first_sector = hd->part[MINOR(dev)].start_sect;
	first_size = hd->part[MINOR(dev)].nr_sects;
	this_sector = first_sector;
	while (1) {
		if (++loopct > 100)
			return;
		if ((current_minor & mask) == 0)
			return;
		if (!(bh = bread(dev,0,get_ptable_blocksize(dev))))
			return;
		if ((*(__u16 *) (bh->b_data+510)) != cpu_to_le16(MSDOS_LABEL_MAGIC))
			goto done;
		p = (struct partition *) (0x1BE + bh->b_data);
		this_size = hd->part[MINOR(dev)].nr_sects;
		for (i=0; i<4; i++, p++) {
			if (!NR_SECTS(p) || is_extended_partition(p))
				continue;
			if (i >= 2
				&& START_SECT(p) + NR_SECTS(p) > this_size
				&& (this_sector + START_SECT(p) < first_sector ||
				    this_sector + START_SECT(p) + NR_SECTS(p) >
				     first_sector + first_size))
				continue;
			add_gd_partition(hd, current_minor,
					 this_sector+START_SECT(p)*sector_size,
					 NR_SECTS(p)*sector_size);
#if CONFIG_BLK_DEV_MD && CONFIG_AUTODETECT_RAID
			if (SYS_IND(p) == LINUX_RAID_PARTITION) {
			    md_autodetect_dev(MKDEV(hd->major,current_minor));
			}
#endif
			current_minor++;
			loopct = 0;
			if ((current_minor & mask) == 0)
				goto done;
		}
		p -= 4;
		for (i=0; i<4; i++, p++)
			if(NR_SECTS(p) && is_extended_partition(p))
				break;
		if (i == 4)
			goto done;	 
		hd->part[current_minor].nr_sects = NR_SECTS(p) * sector_size; 
		hd->part[current_minor].start_sect = first_sector + START_SECT(p) * sector_size;
		this_sector = first_sector + START_SECT(p) * sector_size;
		dev = MKDEV(hd->major, current_minor);
		bforget(bh);
	}
done:
	bforget(bh);
}
static void extended_partition ( struct gendisk * hd , kdev_t dev ) { struct buffer_head * bh ; struct partition * p ; unsigned long first_sector , first_size , this_sector , this_size ; int mask = ( 1 << hd -> minor_shift ) - 1 ; int sector_size = get_hardsect_size ( dev ) / 512 ; int loopct = 0 ; int i ; first_sector = hd -> part [ MINOR ( dev ) ] . start_sect ; first_size = hd -> part [ MINOR ( dev ) ] . nr_sects ; this_sector = first_sector ; while ( 1 ) { if ( ++ loopct > 100 ) return ; if ( ( current_minor & mask ) == 0 ) return ; if ( ! ( bh = bread ( dev , 0 , get_ptable_blocksize ( dev ) ) ) ) return ; if ( ( * ( __u16 * ) ( bh -> b_data + 510 ) ) != cpu_to_le16 ( MSDOS_LABEL_MAGIC ) ) goto done ; p = ( struct partition * ) ( 0x1BE + bh -> b_data ) ; this_size = hd -> part [ MINOR ( dev ) ] . nr_sects ; for ( i = 0 ; i < 4 ; i ++ , p ++ ) { if ( ! NR_SECTS ( p ) || is_extended_partition ( p ) ) continue ; if ( i >= 2 && START_SECT ( p ) + NR_SECTS ( p ) > this_size && ( this_sector + START_SECT ( p ) < first_sector || this_sector + START_SECT ( p ) + NR_SECTS ( p ) > first_sector + first_size ) ) continue ; add_gd_partition ( hd , current_minor , this_sector + START_SECT ( p ) * sector_size , NR_SECTS ( p ) * sector_size ) ; #if CONFIG_BLK_DEV_MD && CONFIG_AUTODETECT_RAID if ( SYS_IND ( p ) == LINUX_RAID_PARTITION ) { md_autodetect_dev ( MKDEV ( hd -> major , current_minor ) ) ; } #endif current_minor ++ ; loopct = 0 ; if ( ( current_minor & mask ) == 0 ) goto done ; } p -= 4 ; for ( i = 0 ; i < 4 ; i ++ , p ++ ) if ( NR_SECTS ( p ) && is_extended_partition ( p ) ) break ; if ( i == 4 ) goto done ; hd -> part [ current_minor ] . nr_sects = NR_SECTS ( p ) * sector_size ; hd -> part [ current_minor ] . start_sect = first_sector + START_SECT ( p ) * sector_size ; this_sector = first_sector + START_SECT ( p ) * sector_size ; dev = MKDEV ( hd -> major , current_minor ) ; bforget ( bh ) ; } done : bforget ( bh ) ; }
Create devices for each logical partition in an extended partition.
Create devices for each logical partition in an extended partition .
/* number of links followed
				   without finding a data partition */ /*
		 * Usually, the first entry is the real data partition,
		 * the 2nd entry is the next extended partition, or empty,
		 * and the 3rd and 4th entries are unused.
		 * However, DRDOS sometimes has the extended partition as
		 * the first entry (when the data partition is empty),
		 * and OS/2 seems to use all four entries.
		 */ /* 
		 * First process the data partition(s)
		 */ /* Check the 3rd and 4th entries -
			   these sometimes contain random garbage */ /*
		 * Next, process the (first) extended partition, if present.
		 * (So far, there seems to be no reason to make
		 *  extended_partition()  recursive and allow a tree
		 *  of extended partitions.)
		 * It should be a link to the next logical partition.
		 * Create a minor for this just long enough to get the next
		 * partition table.  The minor will be reused for the next
		 * data partition.
		 */ /* nothing left to do */ /* JSt */ /* Use bforget(), as we have changed the disk geometry */