Re: more gendisk stuff

From: Alexander Viro (viro@math.psu.edu)
Date: Thu Jun 21 2001 - 12:56:34 EST


On Thu, 21 Jun 2001 Andries.Brouwer@cwi.nl wrote:

> Al, I don't know whether you are interested in this stuff, but comments
> (other than: "the stuff is full of races") are welcome.

No comments on races, but there's obvious one on API: doing that on
per-major basis is _wrong_. That's why register_disk() takes device
number + range instead of major. Here's an old patch that should
demonstrate what register_disk() is supposed to do:

diff -urN linux-2.3.41/arch/m68k/atari/stram.c linux-bird.bdev/arch/m68k/atari/stram.c
--- linux-2.3.41/arch/m68k/atari/stram.c Fri Jan 28 21:45:36 2000
+++ linux-bird.bdev/arch/m68k/atari/stram.c Tue Feb 1 04:07:32 2000
@@ -1255,9 +1255,9 @@
     blksize_size[STRAM_MAJOR] = stram_blocksizes;
         stram_sizes[STRAM_MINOR] = (swap_end - swap_start)/1024;
     blk_size[STRAM_MAJOR] = stram_sizes;
- register_disk(NULL, MKDEV(STRAM_MAJOR, STRAM_MINOR), 1, &stram_fops,
- (swap_end-swap_start)>>9);
         do_z2_request(); /* to avoid warning */
+ register_disk(NULL, BDEV(STRAM_MAJOR, STRAM_MINOR), 1, &stram_fops,
+ (swap_end-swap_start)>>9);
         return( 0 );
 }
 
diff -urN linux-2.3.41/drivers/acorn/block/fd1772.c linux-bird.bdev/drivers/acorn/block/fd1772.c
--- linux-2.3.41/drivers/acorn/block/fd1772.c Tue Jan 11 00:21:04 2000
+++ linux-bird.bdev/drivers/acorn/block/fd1772.c Tue Feb 1 04:07:32 2000
@@ -1636,6 +1636,13 @@
 
         config_types();
 
+ for (i=0; i< FD_MAX_UNITS; i++) {
+ int type;
+ for (type = 0; type <= NUM_DISK_TYPES; type++)
+ register_disk(NULL, BDEV(MAJOR_NR, type*4+i), 1,
+ &floppy_fops, 0);
+ }
+
         return 0;
 }
 
diff -urN linux-2.3.41/drivers/acorn/block/mfmhd.c linux-bird.bdev/drivers/acorn/block/mfmhd.c
--- linux-2.3.41/drivers/acorn/block/mfmhd.c Thu Jan 20 22:47:22 2000
+++ linux-bird.bdev/drivers/acorn/block/mfmhd.c Tue Feb 1 04:07:32 2000
@@ -1356,7 +1356,7 @@
 
         for (i = 0; i < mfm_drives; i++) {
                 mfm_geometry (i);
- register_disk(&mfm_gendisk, MKDEV(MAJOR_NR,i<<6), 1<<6,
+ register_disk(&mfm_gendisk, BDEV(MAJOR_NR,i<<6), 1<<6,
                                 &mfm_fops,
                                 mfm_info[i].cylinders * mfm_info[i].heads *
                                 mfm_info[i].sectors / 2);
diff -urN linux-2.3.41/drivers/ap1000/ap.c linux-bird.bdev/drivers/ap1000/ap.c
--- linux-2.3.41/drivers/ap1000/ap.c Thu Jan 20 22:47:22 2000
+++ linux-bird.bdev/drivers/ap1000/ap.c Tue Feb 1 04:07:32 2000
@@ -275,7 +275,7 @@
 
   read_ahead[MAJOR_NR] = 32; /* 16k read ahead */
   for (i=0;i<NUM_APDEVS;i++)
- register_disk(NILL, MKDEV(MAJOR_NR,i), 1, &ap_fops, 0);
+ register_disk(NILL, BDEV(MAJOR_NR,i), 1, &ap_fops, 0);
 
   return(0);
 }
diff -urN linux-2.3.41/drivers/ap1000/ddv.c linux-bird.bdev/drivers/ap1000/ddv.c
--- linux-2.3.41/drivers/ap1000/ddv.c Thu Jan 20 22:47:22 2000
+++ linux-bird.bdev/drivers/ap1000/ddv.c Tue Feb 1 04:07:32 2000
@@ -732,7 +732,7 @@
         ddv_geometry.cylinders = ddv_sect_length[0] /
                 (ddv_geometry.heads*ddv_geometry.sectors);
 
- register_disk(&ddv_gendisk, MKDEV(MAJOR_NR,0), 1<<PARTN_BITS,
+ register_disk(&ddv_gendisk, BDEV(MAJOR_NR,0), 1<<PARTN_BITS,
                         &ddv_fops, ddv_sect_length[0]);
         
         /* FIXME. The crap below is, well, crap. Pseudo-RAID and unsafe one */
diff -urN linux-2.3.41/drivers/block/DAC960.c linux-bird.bdev/drivers/block/DAC960.c
--- linux-2.3.41/drivers/block/DAC960.c Fri Jan 28 21:45:37 2000
+++ linux-bird.bdev/drivers/block/DAC960.c Tue Feb 1 04:07:32 2000
@@ -2944,7 +2944,7 @@
   for (LogicalDriveNumber = 0;
        LogicalDriveNumber < Controller->LogicalDriveCount;
        LogicalDriveNumber++)
- register_disk(GenericDiskInfo, MKDEV(GenericDiskInfo->major,
+ register_disk(GenericDiskInfo, BDEV(GenericDiskInfo->major,
                                        LogicalDriveNumber*DAC960_MaxPartitions),
                 DAC960_MaxPartitions, &DAC960_FileOperations,
                 LogicalDriveInformation[LogicalDriveNumber].LogicalDriveSize);
diff -urN linux-2.3.41/drivers/block/acsi.c linux-bird.bdev/drivers/block/acsi.c
--- linux-2.3.41/drivers/block/acsi.c Thu Jan 20 22:47:23 2000
+++ linux-bird.bdev/drivers/block/acsi.c Tue Feb 1 05:44:44 2000
@@ -106,6 +106,8 @@
         NONE, HARDDISK, CDROM
 } ACSI_TYPE;
 
+static struct block_driver *acsi_driver;
+
 struct acsi_info_struct {
         ACSI_TYPE type; /* type of device */
         unsigned target; /* target number */
@@ -1746,11 +1748,15 @@
         for( i = 0; i < (MAX_DEV << 4); i++ )
                 acsi_blocksizes[i] = 1024;
         blksize_size[MAJOR_NR] = acsi_blocksizes;
- for( i = 0; i < NDevices; ++i )
- register_disk(&acsi_gendisk, MKDEV(MAJOR_NR,i<<4),
- (acsi_info[i].type==HARDDISK)?1<<4:1,
- &acsi_fops,
- acsi_info[i].size);
+ for( i = 0; i < NDevices; ++i ) {
+ struct disk_struct *disk;
+ disk = register_disk(acsi_driver, &acsi_gendisk,
+ BDEV(MAJOR_NR,i<<4),
+ (acsi_info[i].type==HARDDISK)?1<<4:1,
+ &acsi_fops);
+ disk->sectors = acsi_info[i].size;
+ parse_partitions(disk);
+ }
         acsi_gendisk.nr_real = NDevices;
 }
 
@@ -1777,7 +1783,8 @@
         if (!MACH_IS_ATARI || !ATARIHW_PRESENT(ACSI))
                 return 0;
 
- if (register_blkdev( MAJOR_NR, "ad", &acsi_fops )) {
+ acsi_driver = register_block_driver("ad", MAJOR_NR);
+ if (IS_ERR(acsi_driver)) {
                 printk( KERN_ERR "Unable to get major %d for ACSI\n", MAJOR_NR );
                 return -EBUSY;
         }
@@ -1785,7 +1792,7 @@
         if (!(acsi_buffer =
                   (char *)atari_stram_alloc( ACSI_BUFFER_SIZE, NULL, "acsi" ))) {
                 printk( KERN_ERR "Unable to get ACSI ST-Ram buffer.\n" );
- unregister_blkdev( MAJOR_NR, "ad" );
+ unregister_block_driver(acsi_driver);
                 return -ENOMEM;
         }
         phys_acsi_buffer = virt_to_phys( acsi_buffer );
@@ -1801,6 +1808,7 @@
 #endif
         if (!err)
                 acsi_geninit();
+ range_unlock(acsi_driver->range);
         return err;
 }
 
@@ -1824,7 +1832,7 @@
         blk_cleanup_queue(BLK_DEFAULT_QUEUE(MAJOR_NR));
         atari_stram_free( acsi_buffer );
 
- if (unregister_blkdev( MAJOR_NR, "ad" ) != 0)
+ if (unregister_block_driver(acsi_driver) != 0)
                 printk( KERN_ERR "acsi: cleanup_module failed\n");
 
         for (gdp = &gendisk_head; *gdp; gdp = &((*gdp)->next))
diff -urN linux-2.3.41/drivers/block/amiflop.c linux-bird.bdev/drivers/block/amiflop.c
--- linux-2.3.41/drivers/block/amiflop.c Fri Jan 28 21:45:37 2000
+++ linux-bird.bdev/drivers/block/amiflop.c Tue Feb 1 05:03:20 2000
@@ -114,6 +114,7 @@
 #define FD_HD_3 0x55555555 /* high-density 3.5" (1760K) drive */
 #define FD_DD_5 0xaaaaaaaa /* double-density 5.25" (440K) drive */
 
+static struct block_driver *fd_driver;
 static long int fd_def_df0 = FD_DD_3; /* default for df0 if it doesn't identify */
 
 MODULE_PARM(fd_def_df0,"l");
@@ -1790,7 +1791,8 @@
         if (!AMIGAHW_PRESENT(AMI_FLOPPY))
                 return -ENXIO;
 
- if (register_blkdev(MAJOR_NR,"fd",&floppy_fops)) {
+ fd_driver = register_block_driver("fd", MAJOR_NR);
+ if (IS_ERR(fd_driver)) {
                 printk("fd: Unable to get major %d for floppy\n",MAJOR_NR);
                 return -EBUSY;
         }
@@ -1798,28 +1800,28 @@
         if ((raw_buf = (char *)amiga_chip_alloc (RAW_BUF_SIZE, "Floppy")) ==
             NULL) {
                 printk("fd: cannot get chip mem buffer\n");
- unregister_blkdev(MAJOR_NR,"fd");
+ unregister_block_driver(fd_driver);
                 return -ENOMEM;
         }
 
         if (request_irq(IRQ_AMIGA_DSKBLK, fd_block_done, 0, "floppy_dma", NULL)) {
                 printk("fd: cannot get irq for dma\n");
                 amiga_chip_free(raw_buf);
- unregister_blkdev(MAJOR_NR,"fd");
+ unregister_block_driver(fd_driver);
                 return -EBUSY;
         }
         if (request_irq(IRQ_AMIGA_CIAA_TB, ms_isr, 0, "floppy_timer", NULL)) {
                 printk("fd: cannot get irq for timer\n");
                 free_irq(IRQ_AMIGA_DSKBLK, NULL);
                 amiga_chip_free(raw_buf);
- unregister_blkdev(MAJOR_NR,"fd");
+ unregister_block_driver(fd_driver);
                 return -EBUSY;
         }
         if (fd_probe_drives() < 1) { /* No usable drives */
                 free_irq(IRQ_AMIGA_CIAA_TB, NULL);
                 free_irq(IRQ_AMIGA_DSKBLK, NULL);
                 amiga_chip_free(raw_buf);
- unregister_blkdev(MAJOR_NR,"fd");
+ unregister_block_driver(fd_driver);
                 return -ENXIO;
         }
 
@@ -1865,7 +1867,11 @@
         /* init ms timer */
         ciaa.crb = 8; /* one-shot, stop */
 
+ for (i=0; i<8; i++)
+ register_disk(fd_driver,NULL,BDEV(MAJOR_NR,i),1,&floppy_fops);
+
         (void)do_floppy; /* avoid warning about unused variable */
+ range_unlock(fd_driver->range);
         return 0;
 }
 
@@ -1893,6 +1899,6 @@
         blk_size[MAJOR_NR] = NULL;
         blksize_size[MAJOR_NR] = NULL;
         blk_cleanup_queue(BLK_DEFAULT_QUEUE(MAJOR_NR));
- unregister_blkdev(MAJOR_NR, "fd");
+ unregister_block_driver(fd_driver);
 }
 #endif
diff -urN linux-2.3.41/drivers/block/ataflop.c linux-bird.bdev/drivers/block/ataflop.c
--- linux-2.3.41/drivers/block/ataflop.c Tue Jan 11 00:21:05 2000
+++ linux-bird.bdev/drivers/block/ataflop.c Tue Feb 1 05:11:40 2000
@@ -99,6 +99,8 @@
 
 #undef DEBUG
 
+static struct block_driver *fd_driver;
+
 /* Disk types: DD, HD, ED */
 static struct atari_disk_type {
         const char *name;
@@ -1974,7 +1976,8 @@
                 /* Hades doesn't have Atari-compatible floppy */
                 return -ENXIO;
 
- if (register_blkdev(MAJOR_NR,"fd",&floppy_fops)) {
+ fd_driver = register_block_driver("fd", MAJOR_NR);
+ if (IS_ERR(fd_driver)) {
                 printk(KERN_ERR "Unable to get major %d for floppy\n",MAJOR_NR);
                 return -EBUSY;
         }
@@ -1997,7 +2000,7 @@
         DMABuffer = atari_stram_alloc( BUFFER_SIZE+512, NULL, "ataflop" );
         if (!DMABuffer) {
                 printk(KERN_ERR "atari_floppy_init: cannot get dma buffer\n");
- unregister_blkdev(MAJOR_NR, "fd");
+ unregister_block_driver(fd_driver);
                 return -ENOMEM;
         }
         TrackBuffer = DMABuffer + 512;
@@ -2026,6 +2029,14 @@
                UseTrackbuffer ? "" : "no ");
         config_types();
 
+ for (i=0; i< FD_MAX_UNITS; i++) {
+ int type;
+ for (type = 0; type <= NUM_DISK_MINORS; type++)
+ register_disk(fd_driver, NULL,
+ BDEV(MAJOR_NR,type*4+i), 1, &floppy_fops);
+ }
+
+ range_unlock(fd_driver->range);
         (void)do_floppy; /* avoid warning about unused variable */
         return 0;
 }
@@ -2069,7 +2080,7 @@
 
 void cleanup_module (void)
 {
- unregister_blkdev(MAJOR_NR, "fd");
+ unregister_block_driver(fd_driver);
 
         blk_cleanup_queue(BLK_DEFAULT_QUEUE(MAJOR_NR));
         timer_active &= ~(1 << FLOPPY_TIMER);
diff -urN linux-2.3.41/drivers/block/cpqarray.c linux-bird.bdev/drivers/block/cpqarray.c
--- linux-2.3.41/drivers/block/cpqarray.c Thu Jan 20 22:47:23 2000
+++ linux-bird.bdev/drivers/block/cpqarray.c Tue Feb 1 04:07:33 2000
@@ -480,7 +480,7 @@
 
                 ida_geninit(i);
                 for(j=0; j<NWD; j++)
- register_disk(&ida_gendisk[i], MKDEV(MAJOR_NR+i,j<<4),
+ register_disk(&ida_gendisk[i], BDEV(MAJOR_NR+i,j<<4),
                                         16, &ida_fops, hba[i]->drv[j].nr_blks);
         }
         /* done ! */
diff -urN linux-2.3.41/drivers/block/floppy.c linux-bird.bdev/drivers/block/floppy.c
--- linux-2.3.41/drivers/block/floppy.c Thu Jan 20 22:47:23 2000
+++ linux-bird.bdev/drivers/block/floppy.c Tue Feb 1 04:36:15 2000
@@ -135,6 +135,7 @@
 static int allowed_drive_mask = 0x33;
 static int irqdma_allocated = 0;
  
+static struct block_driver *floppy_driver;
 
 #include <linux/sched.h>
 #include <linux/fs.h>
@@ -4053,7 +4054,9 @@
 
         raw_cmd = 0;
 
- if (register_blkdev(MAJOR_NR,"fd",&floppy_fops)) {
+ floppy_driver = register_block_driver("fd", MAJOR_NR);
+
+ if (IS_ERR(floppy_driver)) {
                 printk("Unable to get major %d for floppy\n",MAJOR_NR);
                 return -EBUSY;
         }
@@ -4084,7 +4087,7 @@
         use_virtual_dma = can_use_virtual_dma & 1;
         fdc_state[0].address = FDC1;
         if (fdc_state[0].address == -1) {
- unregister_blkdev(MAJOR_NR,"fd");
+ unregister_block_driver(floppy_driver);
                 del_timer(&fd_timeout);
                 return -ENODEV;
         }
@@ -4096,7 +4099,7 @@
         if (floppy_grab_irq_and_dma()){
                 del_timer(&fd_timeout);
                 blk_cleanup_queue(BLK_DEFAULT_QUEUE(MAJOR_NR));
- unregister_blkdev(MAJOR_NR,"fd");
+ unregister_block_driver(floppy_driver);
                 del_timer(&fd_timeout);
                 return -EBUSY;
         }
@@ -4162,7 +4165,7 @@
                  if (usage_count)
                          floppy_release_irq_and_dma();
                 blk_cleanup_queue(BLK_DEFAULT_QUEUE(MAJOR_NR));
- unregister_blkdev(MAJOR_NR,"fd");
+ unregister_block_driver(floppy_driver);
         }
         
         for (drive = 0; drive < N_DRIVE; drive++) {
@@ -4171,9 +4174,11 @@
                 if (fdc_state[FDC(drive)].version == FDC_NONE)
                         continue;
                 for (i = 0; i<NUMBER(floppy_type); i++)
- register_disk(NULL, MKDEV(MAJOR_NR,TOMINOR(drive)+i*4),
- 1, &floppy_fops, 0);
+ register_disk(floppy_driver, NULL,
+ BDEV(MAJOR_NR,TOMINOR(drive)+i*4), 1,
+ &floppy_fops);
         }
+ range_unlock(floppy_driver->range);
         return have_no_fdc;
 }
 
@@ -4391,7 +4396,7 @@
 {
         int dummy;
                 
- unregister_blkdev(MAJOR_NR, "fd");
+ unregister_block_driver(floppy_driver);
 
         blk_cleanup_queue(BLK_DEFAULT_QUEUE(MAJOR_NR));
         /* eject disk, if any */
diff -urN linux-2.3.41/drivers/block/hd.c linux-bird.bdev/drivers/block/hd.c
--- linux-2.3.41/drivers/block/hd.c Thu Jan 20 22:47:23 2000
+++ linux-bird.bdev/drivers/block/hd.c Tue Feb 1 04:35:49 2000
@@ -73,6 +73,8 @@
 static void recal_intr(void);
 static void bad_rw_intr(void);
 
+static struct block_driver *hd_driver;
+
 static char recalibrate[MAX_HD];
 static char special_op[MAX_HD];
 static int access_count[MAX_HD];
@@ -792,15 +794,21 @@
 
         hd_gendisk.nr_real = NR_HD;
 
- for(drive=0; drive < NR_HD; drive++)
- register_disk(&hd_gendisk, MKDEV(MAJOR_NR,drive<<6), 1<<6,
- &hd_fops, hd_info[drive].head * hd_info[drive].sect *
- hd_info[drive].cyl);
+ for(drive=0; drive < NR_HD; drive++) {
+ struct disk_struct *disk
+ disk = register_disk(hd_driver, &hd_gendisk,
+ BDEV(MAJOR_NR,drive<<6), 1<<6,
+ &hd_fops);
+ disk->sectors = hd_info[drive].head * hd_info[drive].sect *
+ hd_info[drive].cyl;
+ parse_partitions(disk);
+ }
 }
 
 int __init hd_init(void)
 {
- if (register_blkdev(MAJOR_NR,"hd",&hd_fops)) {
+ hd_driver = register_block_driver("hd", MAJOR_NR);
+ if (IS_ERR(hd_driver) {
                 printk("hd: unable to get major %d for hard disk\n",MAJOR_NR);
                 return -1;
         }
@@ -810,6 +818,7 @@
         gendisk_head = &hd_gendisk;
         timer_table[HD_TIMER].fn = hd_times_out;
         hd_geninit();
+ range_unlock(hd_driver->range);
         return 0;
 }
 
diff -urN linux-2.3.41/drivers/block/ide-probe.c linux-bird.bdev/drivers/block/ide-probe.c
--- linux-2.3.41/drivers/block/ide-probe.c Fri Jan 28 21:45:38 2000
+++ linux-bird.bdev/drivers/block/ide-probe.c Tue Feb 1 04:07:33 2000
@@ -756,11 +756,14 @@
                 printk("%s: request_fn NOT DEFINED\n", hwif->name);
                 return (hwif->present = 0);
         }
+
+/*
         if (register_blkdev (hwif->major, hwif->name, ide_fops)) {
                 printk("%s: UNABLE TO GET MAJOR NUMBER %d\n", hwif->name, hwif->major);
                 return (hwif->present = 0);
         }
-
+*/
+
         if (init_irq (hwif)) {
                 int i = hwif->irq;
                 /*
diff -urN linux-2.3.41/drivers/block/ide.c linux-bird.bdev/drivers/block/ide.c
--- linux-2.3.41/drivers/block/ide.c Fri Jan 28 21:45:38 2000
+++ linux-bird.bdev/drivers/block/ide.c Tue Feb 1 04:07:33 2000
@@ -156,6 +156,8 @@
 #include <linux/kmod.h>
 #endif /* CONFIG_KMOD */
 
+struct block_driver *ide_driver = NULL;
+
 #ifdef CONFIG_BLK_DEV_VIA82CXXX
 extern byte fifoconfig; /* defined in via82cxxx.c used by ide_setup() */
 #endif /* CONFIG_BLK_DEV_VIA82CXXX */
@@ -554,22 +556,28 @@
 void ide_geninit (ide_hwif_t *hwif)
 {
         unsigned int unit;
- struct gendisk *gd = hwif->gd;
+ struct range_node * range;
+ range = block_area_add(ide_driver, BDEV(hwif->major, 0), 128);
 
         for (unit = 0; unit < MAX_DRIVES; ++unit) {
                 ide_drive_t *drive = &hwif->drives[unit];
 
                 if (!drive->present)
                         continue;
- if (drive->media!=ide_disk && drive->media!=ide_floppy)
+ if (drive->media!=ide_disk && drive->media!=ide_floppy &&
+ drive->media!=ide_cdrom)
                         continue;
- register_disk(gd,MKDEV(hwif->major,unit<<PARTN_BITS),
+ drive->disk = register_disk(
+ ide_driver,
+ hwif->gd,
+ BDEV(hwif->major,unit<<PARTN_BITS),
 #ifdef CONFIG_BLK_DEV_ISAPNP
                         (drive->forced_geom && drive->noprobe) ? 1 :
 #endif /* CONFIG_BLK_DEV_ISAPNP */
                         1<<PARTN_BITS, ide_fops,
                         current_capacity(drive));
         }
+ range_unlock(range);
 }
 
 static ide_startstop_t do_reset1 (ide_drive_t *, int); /* needed below */
@@ -1916,7 +1924,6 @@
         ide_hwgroup_t *hwgroup;
         int irq_count = 0, unit, i;
         unsigned long flags;
- unsigned int p, minor;
         ide_hwif_t old_hwif;
 
         if (index >= MAX_HWIFS)
@@ -1945,15 +1952,9 @@
                 drive = &hwif->drives[unit];
                 if (!drive->present)
                         continue;
- minor = drive->select.b.unit << PARTN_BITS;
- for (p = 0; p < (1<<PARTN_BITS); ++p) {
- if (drive->part[p].nr_sects > 0) {
- kdev_t devp = MKDEV(hwif->major, minor+p);
- struct super_block * sb = get_super(devp);
- if (sb) invalidate_inodes(sb);
- invalidate_buffers (devp);
- }
- }
+ if (drive->disk)
+ unregister_disk(drive->disk);
+ drive->disk = NULL;
 #ifdef CONFIG_PROC_FS
                 destroy_proc_ide_drives(hwif);
 #endif
@@ -2020,7 +2021,7 @@
         /*
          * Remove us from the kernel's knowledge
          */
- unregister_blkdev(hwif->major, hwif->name);
+ block_area_remove(ide_driver, BDEV(hwif->major, 0));
         kfree(blksize_size[hwif->major]);
         kfree(max_sectors[hwif->major]);
         kfree(max_readahead[hwif->major]);
@@ -3496,6 +3497,8 @@
 
         init_ide_data ();
 
+ ide_driver = register_block_driver("ide", 0);
+
         initializing = 1;
         ide_init_builtin_drivers();
         initializing = 0;
@@ -3552,6 +3555,7 @@
 #ifdef CONFIG_PROC_FS
         proc_ide_destroy();
 #endif
+ unregister_block_driver(ide_driver);
 }
 
 #else /* !MODULE */
diff -urN linux-2.3.41/drivers/block/loop.c linux-bird.bdev/drivers/block/loop.c
--- linux-2.3.41/drivers/block/loop.c Thu Jan 20 22:47:24 2000
+++ linux-bird.bdev/drivers/block/loop.c Tue Feb 1 05:16:40 2000
@@ -69,6 +69,7 @@
 #include <linux/blk.h>
 
 #include <linux/malloc.h>
+static struct block_driver *loop_driver;
 static int max_loop = 8;
 static struct loop_device *loop_dev;
 static int *loop_sizes;
@@ -715,7 +716,8 @@
 {
         int i;
 
- if (register_blkdev(MAJOR_NR, "loop", &lo_fops)) {
+ loop_driver = register_block_driver("loop", MAJOR_NR);
+ if (IS_ERR(loop_driver)) {
                 printk(KERN_WARNING "Unable to get major number %d for loop device\n",
                        MAJOR_NR);
                 return -EIO;
@@ -760,15 +762,16 @@
         blk_size[MAJOR_NR] = loop_sizes;
         blksize_size[MAJOR_NR] = loop_blksizes;
         for (i=0; i < max_loop; i++)
- register_disk(NULL, MKDEV(MAJOR_NR,i), 1, &lo_fops, 0);
+ register_disk(loop_driver, NULL, BDEV(MAJOR_NR,i), 1, &lo_fops);
 
+ range_unlock(loop_driver->range);
         return 0;
 }
 
 #ifdef MODULE
 void cleanup_module(void)
 {
- if (unregister_blkdev(MAJOR_NR, "loop") != 0)
+ if (unregister_block_driver(loop_driver) != 0)
                 printk(KERN_WARNING "loop: cannot unregister blkdev\n");
 
         kfree (loop_dev);
diff -urN linux-2.3.41/drivers/block/md.c linux-bird.bdev/drivers/block/md.c
--- linux-2.3.41/drivers/block/md.c Thu Jan 20 22:47:24 2000
+++ linux-bird.bdev/drivers/block/md.c Tue Feb 1 05:13:43 2000
@@ -68,6 +68,7 @@
 extern kdev_t name_to_kdev_t(char *line) __init;
 #endif
 
+static struct block_driver *md_driver;
 static struct hd_struct md_hd_struct[MAX_MD_DEV];
 static int md_blocksizes[MAX_MD_DEV];
 int md_maxreadahead[MAX_MD_DEV];
@@ -916,7 +917,7 @@
     md_blocksizes[i] = 1024;
     md_maxreadahead[i] = MD_DEFAULT_DISK_READAHEAD;
     md_dev[i].pers=NULL;
- register_disk(&md_gendisk, MKDEV(MAJOR_NR,i), 1, &md_fops, 0);
+ register_disk(md_driver, &md_gendisk, BDEV(MAJOR_NR,i), 1, &md_fops);
   }
 
 #ifdef CONFIG_PROC_FS
@@ -1229,7 +1230,8 @@
     MD_MAJOR_VERSION, MD_MINOR_VERSION, MD_PATCHLEVEL_VERSION,
     MAX_MD_DEV, MAX_REAL);
 
- if (register_blkdev (MD_MAJOR, "md", &md_fops))
+ md_driver = register_block_driver("md", MD_MAJOR);
+ if (IS_ERR(md_driver))
   {
     printk ("Unable to get major %d for md\n", MD_MAJOR);
     return (-1);
diff -urN linux-2.3.41/drivers/block/nbd.c linux-bird.bdev/drivers/block/nbd.c
--- linux-2.3.41/drivers/block/nbd.c Thu Jan 20 22:47:24 2000
+++ linux-bird.bdev/drivers/block/nbd.c Tue Feb 1 05:38:25 2000
@@ -46,6 +46,7 @@
 
 #define LO_MAGIC 0x68797548
 
+static struct block_driver *nbd_driver;
 static int nbd_blksizes[MAX_NBD];
 static int nbd_blksize_bits[MAX_NBD];
 static int nbd_sizes[MAX_NBD];
@@ -469,7 +470,8 @@
                 return -EIO;
         }
 
- if (register_blkdev(MAJOR_NR, "nbd", &nbd_fops)) {
+ nbd_driver = register_block_device("nbd", MAJOR_NR);
+ if (IS_ERR(nbd_driver)) {
                 printk("Unable to get major number %d for NBD\n",
                        MAJOR_NR);
                 return -EIO;
@@ -481,6 +483,7 @@
         blk_size[MAJOR_NR] = nbd_sizes;
         blk_init_queue(BLK_DEFAULT_QUEUE(MAJOR_NR), do_nbd_request);
         for (i = 0; i < MAX_NBD; i++) {
+ struct disk_struct *disk;
                 nbd_dev[i].refcnt = 0;
                 nbd_dev[i].file = NULL;
                 nbd_dev[i].magic = LO_MAGIC;
@@ -489,16 +492,18 @@
                 nbd_blksize_bits[i] = 10;
                 nbd_bytesizes[i] = 0x7ffffc00; /* 2GB */
                 nbd_sizes[i] = nbd_bytesizes[i] >> nbd_blksize_bits[i];
- register_disk(NULL, MKDEV(MAJOR_NR,i), 1, &nbd_fops,
- nbd_bytesizes[i]>>9);
+ disk = register_disk(nbd_driver, NULL, BDEV(MAJOR_NR,i), 1,
+ &nbd_fops);
+ disk->sectors = nbd_bytesizes[i]>>9;
         }
+ range_unlock(nbd_driver->range);
         return 0;
 }
 
 #ifdef MODULE
 void cleanup_module(void)
 {
- if (unregister_blkdev(MAJOR_NR, "nbd") != 0)
+ if (unregister_block_driver(nbd_driver) != 0)
                 printk("nbd: cleanup_module failed\n");
         else
                 printk("nbd: module cleaned up.\n");
diff -urN linux-2.3.41/drivers/block/paride/pcd.c linux-bird.bdev/drivers/block/paride/pcd.c
--- linux-2.3.41/drivers/block/paride/pcd.c Mon Dec 13 02:00:35 1999
+++ linux-bird.bdev/drivers/block/paride/pcd.c Tue Feb 1 04:07:33 2000
@@ -340,14 +340,17 @@
                 return -1;
         }
 
- for (unit=0;unit<PCD_UNITS;unit++)
- if (PCD.present) register_cdrom(&PCD.info);
-
         blk_init_queue(BLK_DEFAULT_QUEUE(MAJOR_NR), DEVICE_REQUEST);
         read_ahead[MAJOR_NR] = 8; /* 8 sector (4kB) read ahead */
 
         for (i=0;i<PCD_UNITS;i++) pcd_blocksizes[i] = 1024;
         blksize_size[MAJOR_NR] = pcd_blocksizes;
+
+ for (unit=0;unit<PCD_UNITS;unit++)
+ if (PCD.present) {
+ register_cdrom(&PCD.info);
+ register_disk(NULL,BDEV(major,unit),1,&cdrom_fops,0);
+ }
 
         return 0;
 }
diff -urN linux-2.3.41/drivers/block/paride/pd.c linux-bird.bdev/drivers/block/paride/pd.c
--- linux-2.3.41/drivers/block/paride/pd.c Thu Jan 20 22:47:24 2000
+++ linux-bird.bdev/drivers/block/paride/pd.c Tue Feb 1 04:07:33 2000
@@ -836,7 +836,7 @@
                 } else pi_release(PI);
             }
         for (unit=0;unit<PD_UNITS;unit++)
- register_disk(&pd_gendisk,MKDEV(MAJOR_NR,unit<<PD_BITS),
+ register_disk(&pd_gendisk,BDEV(MAJOR_NR,unit<<PD_BITS),
                                 PD_PARTNS,&pd_fops,
                                 PD.present?PD.capacity:0);
 
diff -urN linux-2.3.41/drivers/block/paride/pf.c linux-bird.bdev/drivers/block/paride/pf.c
--- linux-2.3.41/drivers/block/paride/pf.c Thu Jan 20 22:47:24 2000
+++ linux-bird.bdev/drivers/block/paride/pf.c Tue Feb 1 04:07:33 2000
@@ -361,7 +361,7 @@
         for (i=0;i<PF_UNITS;i++) pf_blocksizes[i] = 1024;
         blksize_size[MAJOR_NR] = pf_blocksizes;
         for (i=0;i<PF_UNITS;i++)
- register_disk(NULL, MKDEV(MAJOR_NR, i), 1, &pf_fops, 0);
+ register_disk(NULL, BDEV(MAJOR_NR, i), 1, &pf_fops, 0);
 
         return 0;
 }
diff -urN linux-2.3.41/drivers/block/ps2esdi.c linux-bird.bdev/drivers/block/ps2esdi.c
--- linux-2.3.41/drivers/block/ps2esdi.c Thu Jan 20 22:47:24 2000
+++ linux-bird.bdev/drivers/block/ps2esdi.c Tue Feb 1 05:48:58 2000
@@ -113,6 +113,7 @@
 static DECLARE_WAIT_QUEUE_HEAD(ps2esdi_wait_open);
 
 int no_int_yet;
+static struct block_driver *ps2esdi_driver;
 static int access_count[MAX_HD] = {0,};
 static char ps2esdi_valid[MAX_HD] = {0,};
 static int ps2esdi_sizes[MAX_HD << 6] = {0,};
@@ -170,10 +171,8 @@
 /* initialization routine called by ll_rw_blk.c */
 int __init ps2esdi_init(void)
 {
-
- /* register the device - pass the name, major number and operations
- vector . */
- if (register_blkdev(MAJOR_NR, "ed", &ps2esdi_fops)) {
+ ps2esdi_driver = register_block_driver("ed", MAJOR_NR);
+ if (IS_ERR(ps2esdi_driver)) {
                 printk("%s: Unable to get major number %d\n", DEVICE_NAME, MAJOR_NR);
                 return -1;
         }
@@ -185,6 +184,7 @@
         ps2esdi_gendisk.next = gendisk_head;
         gendisk_head = &ps2esdi_gendisk;
         ps2esdi_geninit();
+ range_unlock(ps2esdi_driver->range);
         return 0;
 } /* ps2esdi_init */
 
@@ -229,7 +229,7 @@
         release_region(io_base, 4);
         free_dma(dma_arb_level);
           free_irq(PS2ESDI_IRQ, NULL)
- unregister_blkdev(MAJOR_NR, "ed");
+ unregister_block_driver(ps2esdi_driver);
 }
 #endif /* MODULE */
 
@@ -420,10 +420,12 @@
         blksize_size[MAJOR_NR] = ps2esdi_blocksizes;
 
         for (i = 0; i < ps2esdi_drives; i++) {
- register_disk(&ps2esdi_gendisk,MKDEV(MAJOR_NR,i<<6),1<<6,
- &ps2esdi_fops,
- ps2esdi_info[i].head * ps2esdi_info[i].sect *
- ps2esdi_info[i].cyl);
+ struct disk_struct *disk;
+ disk = register_disk(ps2esdi_driver, &ps2esdi_gendisk,
+ BDEV(MAJOR_NR,i<<6), 1<<6, &ps2esdi_fops);
+ disk->sectors = ps2esdi_info[i].head * ps2esdi_info[i].sect *
+ ps2esdi_info[i].cyl;
+ parse_partitions(disk);
                 ps2esdi_valid[i] = 1;
         }
 }
diff -urN linux-2.3.41/drivers/block/rd.c linux-bird.bdev/drivers/block/rd.c
--- linux-2.3.41/drivers/block/rd.c Thu Jan 20 22:47:24 2000
+++ linux-bird.bdev/drivers/block/rd.c Tue Feb 1 04:59:22 2000
@@ -93,6 +93,7 @@
 /* Various static variables go here. Most are used only in the RAM disk code.
  */
 
+static struct block_driver *rd_driver;
 static unsigned long rd_length[NUM_RAMDISKS]; /* Size of RAM disks in bytes */
 static int rd_hardsec[NUM_RAMDISKS]; /* Size of real blocks in bytes */
 static int rd_blocksizes[NUM_RAMDISKS]; /* Size of 1024 byte blocks :) */
@@ -389,11 +390,7 @@
 static void __exit rd_cleanup (void)
 {
         int i;
-
- for (i = 0 ; i < NUM_RAMDISKS; i++)
- invalidate_buffers(MKDEV(MAJOR_NR, i));
-
- unregister_blkdev( MAJOR_NR, "ramdisk" );
+ unregister_block_driver(rd_driver);
         blk_cleanup_queue(BLK_DEFAULT_QUEUE(MAJOR_NR));
 }
 
@@ -401,6 +398,7 @@
 int __init rd_init (void)
 {
         int i;
+ struct disk_struct *disk;
 
         if (rd_blocksize > PAGE_SIZE || rd_blocksize < 512 ||
             (rd_blocksize & (rd_blocksize-1)))
@@ -410,7 +408,8 @@
                 rd_blocksize = BLOCK_SIZE;
         }
 
- if (register_blkdev(MAJOR_NR, "ramdisk", &fd_fops)) {
+ rd_driver = register_block_driver("ramdisk", MAJOR_NR);
+ if (IS_ERR(rd_driver)) {
                 printk("RAMDISK: Could not get major %d", MAJOR_NR);
                 return -EIO;
         }
@@ -429,12 +428,16 @@
         blksize_size[MAJOR_NR] = rd_blocksizes; /* Avoid set_blocksize() check */
         blk_size[MAJOR_NR] = rd_kbsize; /* Size of the RAM disk in kB */
 
- for (i = 0; i < NUM_RAMDISKS; i++)
- register_disk(NULL, MKDEV(MAJOR_NR,i), 1, &fd_fops, rd_size<<1);
+ for (i = 0; i < NUM_RAMDISKS; i++) {
+ disk=register_disk(rd_driver,NULL,BDEV(MAJOR_NR,i),1,&fd_fops);
+ disk->sectors=rd_size<<1;
+ }
 
 #ifdef CONFIG_BLK_DEV_INITRD
         /* We ought to separate initrd operations here */
- register_disk(NULL, MKDEV(MAJOR_NR,INITRD_MINOR), 1, &fd_fops, rd_size<<1);
+ disk = register_disk(rd_driver,NULL,
+ BDEV(MAJOR_NR,INITRD_MINOR),1,&fd_fops);
+ disk->sectors = rd_size<<1;
 #endif
 
                 /* rd_size is given in kB */
@@ -442,6 +445,7 @@
                "%d RAM disks of %dK size %d blocksize\n",
                NUM_RAMDISKS, rd_size, rd_blocksize);
 
+ range_unlock(rd_driver->range);
         return 0;
 }
 
diff -urN linux-2.3.41/drivers/block/swim3.c linux-bird.bdev/drivers/block/swim3.c
--- linux-2.3.41/drivers/block/swim3.c Tue Jan 11 00:21:05 2000
+++ linux-bird.bdev/drivers/block/swim3.c Tue Feb 1 04:07:33 2000
@@ -1039,6 +1039,7 @@
 int swim3_init(void)
 {
         struct device_node *swim;
+ int i;
 
         swim = find_devices("floppy");
         while (swim && (floppy_count < MAX_FLOPPIES))
@@ -1056,6 +1057,7 @@
 
         if (floppy_count > 0)
         {
+ int i;
                 if (register_blkdev(MAJOR_NR, "fd", &floppy_fops)) {
                         printk(KERN_ERR "Unable to get major %d for floppy\n",
                                MAJOR_NR);
@@ -1064,6 +1066,9 @@
                 blk_init_queue(BLK_DEFAULT_QUEUE(MAJOR_NR), DEVICE_REQUEST);
                 blksize_size[MAJOR_NR] = floppy_blocksizes;
                 blk_size[MAJOR_NR] = floppy_sizes;
+ for (i = 0; i<floppy_count; i++)
+ register_disk(NULL, BDEV(MAJOR_NR, i), 1,
+ &floppy_fops, 0);
         }
 
         return 0;
diff -urN linux-2.3.41/drivers/block/swim_iop.c linux-bird.bdev/drivers/block/swim_iop.c
--- linux-2.3.41/drivers/block/swim_iop.c Tue Jan 11 00:21:05 2000
+++ linux-bird.bdev/drivers/block/swim_iop.c Tue Feb 1 04:07:33 2000
@@ -190,6 +190,7 @@
 
                 init_timer(&fs->timeout);
                 floppy_count++;
+ register_disk(NULL, BDEV(MAJOR_NR,i), 1, &floppy_fops, 0);
         }
         printk("SWIM-IOP: detected %d installed drives.\n", floppy_count);
 
diff -urN linux-2.3.41/drivers/block/xd.c linux-bird.bdev/drivers/block/xd.c
--- linux-2.3.41/drivers/block/xd.c Thu Jan 20 22:47:24 2000
+++ linux-bird.bdev/drivers/block/xd.c Tue Feb 1 04:39:37 2000
@@ -127,6 +127,7 @@
         0xE0000
 };
 
+static struct block_driver *xd_driver;
 static struct hd_struct xd_struct[XD_MAXDRIVES << 6];
 static int xd_sizes[XD_MAXDRIVES << 6], xd_access[XD_MAXDRIVES] = { 0, 0 };
 static int xd_blocksizes[XD_MAXDRIVES << 6];
@@ -167,7 +168,8 @@
 /* xd_init: register the block device number and set up pointer tables */
 int __init xd_init (void)
 {
- if (register_blkdev(MAJOR_NR,"xd",&xd_fops)) {
+ xd_driver = register_block_driver("xd", MAJOR_NR);
+ if (IS_ERR(xd_driver)) {
                 printk("xd: Unable to get major number %d\n",MAJOR_NR);
                 return -1;
         }
@@ -176,6 +178,7 @@
         xd_gendisk.next = gendisk_head;
         gendisk_head = &xd_gendisk;
         xd_geninit();
+ range_unlock(xd_driver->range);
 
         return 0;
 }
@@ -247,10 +250,14 @@
         }
 
         for (i = 0; i < xd_drives; i++) {
+ struct disk_struct *disk;
                 xd_valid[i] = 1;
- register_disk(&xd_gendisk, MKDEV(MAJOR_NR,i<<6), 1<<6, &xd_fops,
- xd_info[i].heads * xd_info[i].cylinders *
- xd_info[i].sectors);
+ disk = register_disk(xd_driver, &xd_gendisk,
+ BDEV(MAJOR_NR,i<<6), 1<<6,
+ &xd_fops);
+ disk->sectors = xd_info[i].heads * xd_info[i].cylinders *
+ xd_info[i].sectors;
+ parse_partitions(disk);
         }
 
         xd_gendisk.nr_real = xd_drives;
@@ -1162,7 +1169,7 @@
         printk(KERN_INFO "XD: Loaded as a module.\n");
         if (!xd_drives) {
                 /* no drives detected - unload module */
- unregister_blkdev(MAJOR_NR, "xd");
+ unregister_block_driver(xd_driver);
                 xd_done();
                 return (-1);
         }
@@ -1174,17 +1181,7 @@
 {
         int partition,dev,start;
 
- unregister_blkdev(MAJOR_NR, "xd");
- for (dev = 0; dev < xd_drives; dev++) {
- start = dev << xd_gendisk.minor_shift;
- for (partition = xd_gendisk.max_p - 1; partition >= 0; partition--) {
- int minor = (start | partition);
- kdev_t devp = MKDEV(MAJOR_NR, minor);
- start = dev << xd_gendisk.minor_shift;
- sync_dev(devp);
- invalidate_buffers(devp);
- }
- }
+ unregister_block_driver(xd_driver);
         xd_done();
         if (xd_drives) {
                 free_irq(xd_irq, NULL);
diff -urN linux-2.3.41/drivers/block/z2ram.c linux-bird.bdev/drivers/block/z2ram.c
--- linux-2.3.41/drivers/block/z2ram.c Fri Jan 28 21:45:38 2000
+++ linux-bird.bdev/drivers/block/z2ram.c Tue Feb 1 04:07:33 2000
@@ -348,6 +348,10 @@
             MAJOR_NR );
         return -EBUSY;
     }
+
+ blk_init_queue(BLK_DEFAULT_QUEUE(MAJOR_NR), DEVICE_REQUEST);
+ blksize_size[ MAJOR_NR ] = z2_blocksizes;
+ blk_size[ MAJOR_NR ] = z2_sizes;
 
     {
             /* Initialize size arrays. */
@@ -356,12 +360,9 @@
             for (i = 0; i < Z2MINOR_COUNT; i++) {
                     z2_blocksizes[ i ] = 1024;
                     z2_sizes[ i ] = 0;
+ register_disk(NULL,BDEV(MAJOR_NR,i),1,&z2_fops,0);
             }
     }
-
- blk_init_queue(BLK_DEFAULT_QUEUE(MAJOR_NR), DEVICE_REQUEST);
- blksize_size[ MAJOR_NR ] = z2_blocksizes;
- blk_size[ MAJOR_NR ] = z2_sizes;
 
     return 0;
 }
diff -urN linux-2.3.41/drivers/cdrom/aztcd.c linux-bird.bdev/drivers/cdrom/aztcd.c
--- linux-2.3.41/drivers/cdrom/aztcd.c Thu Jan 20 22:47:24 2000
+++ linux-bird.bdev/drivers/cdrom/aztcd.c Tue Feb 1 04:07:33 2000
@@ -1796,7 +1796,6 @@
         blksize_size[MAJOR_NR] = aztcd_blocksizes;
 #endif
         read_ahead[MAJOR_NR] = 4;
- register_disk(NULL, MKDEV(MAJOR_NR,0), 1, &azt_fops, 0);
 
         if ((azt_port==0x1f0)||(azt_port==0x170))
            request_region(azt_port, 8, "aztcd"); /*IDE-interface*/
@@ -1806,6 +1805,7 @@
         azt_invalidate_buffers();
         aztPresent = 1;
         aztCloseDoor();
+ register_disk(NULL, BDEV(MAJOR_NR,0), 1, &azt_fops, 0);
         return (0);
 }
 
diff -urN linux-2.3.41/drivers/cdrom/cdu31a.c linux-bird.bdev/drivers/cdrom/cdu31a.c
--- linux-2.3.41/drivers/cdrom/cdu31a.c Mon Dec 13 17:08:40 1999
+++ linux-bird.bdev/drivers/cdrom/cdu31a.c Tue Feb 1 04:07:44 2000
@@ -3524,17 +3524,12 @@
       scd_info.mask = deficiency;
       strncpy(scd_info.name, "cdu31a", sizeof(scd_info.name));
 
+ disk_changed = 1;
       if (register_cdrom(&scd_info))
       {
          goto errout0;
       }
- }
-
-
- disk_changed = 1;
-
- if (drive_found)
- {
+ register_disk(NULL, BDEV(MAJOR_NR,0), 1, &cdrom_fops, 0);
       return(0);
    }
    else
diff -urN linux-2.3.41/drivers/cdrom/cm206.c linux-bird.bdev/drivers/cdrom/cm206.c
--- linux-2.3.41/drivers/cdrom/cm206.c Mon Dec 13 17:08:40 1999
+++ linux-bird.bdev/drivers/cdrom/cm206.c Tue Feb 1 04:07:44 2000
@@ -1395,12 +1395,7 @@
     cleanup(3);
     return -EIO;
   }
- cm206_info.dev = MKDEV(MAJOR_NR,0);
- if (register_cdrom(&cm206_info) != 0) {
- printk(KERN_INFO "Cannot register for cdrom %d!\n", MAJOR_NR);
- cleanup(3);
- return -EIO;
- }
+
   blk_init_queue(BLK_DEFAULT_QUEUE(MAJOR_NR), DEVICE_REQUEST);
   blksize_size[MAJOR_NR] = cm206_blocksizes;
   read_ahead[MAJOR_NR] = 16; /* reads ahead what? */
@@ -1411,6 +1406,15 @@
   cd->adapter_last = -1;
   cd->timer.function = cm206_timeout;
   cd->max_sectors = (inw(r_data_status) & ds_ram_size) ? 24 : 97;
+
+ cm206_info.dev = MKDEV(MAJOR_NR,0);
+ if (register_cdrom(&cm206_info) != 0) {
+ printk(KERN_INFO "Cannot register for cdrom %d!\n", MAJOR_NR);
+ cleanup(3);
+ return -EIO;
+ }
+ register_disk(NULL, BDEV(MAJOR_NR,0), 1, &cdrom_fops, 0);
+
   printk(KERN_INFO "%d kB adapter memory available, "
          " %ld bytes kernel memory used.\n", cd->max_sectors*2, size);
   return 0;
diff -urN linux-2.3.41/drivers/cdrom/gscd.c linux-bird.bdev/drivers/cdrom/gscd.c
--- linux-2.3.41/drivers/cdrom/gscd.c Thu Jan 20 22:47:24 2000
+++ linux-bird.bdev/drivers/cdrom/gscd.c Tue Feb 1 04:07:44 2000
@@ -1082,7 +1082,7 @@
         gscdPresent = 1;
 
         request_region(gscd_port, 4, "gscd");
- register_disk(NULL, MKDEV(MAJOR_NR,0), 1, &gscd_fops, 0);
+ register_disk(NULL, BDEV(MAJOR_NR,0), 1, &gscd_fops, 0);
 
         printk (KERN_INFO "GSCD: GoldStar CD-ROM Drive found.\n" );
         return 0;
diff -urN linux-2.3.41/drivers/cdrom/mcd.c linux-bird.bdev/drivers/cdrom/mcd.c
--- linux-2.3.41/drivers/cdrom/mcd.c Mon Dec 13 17:08:40 1999
+++ linux-bird.bdev/drivers/cdrom/mcd.c Tue Feb 1 04:07:44 2000
@@ -1282,6 +1282,7 @@
               cleanup(3);
               return -EIO;
         }
+ register_disk(NULL, BDEV(MAJOR_NR,0), 1, &cdrom_fops, 0);
         printk(msg);
 
         return 0;
diff -urN linux-2.3.41/drivers/cdrom/mcdx.c linux-bird.bdev/drivers/cdrom/mcdx.c
--- linux-2.3.41/drivers/cdrom/mcdx.c Mon Dec 13 17:08:40 1999
+++ linux-bird.bdev/drivers/cdrom/mcdx.c Tue Feb 1 04:07:44 2000
@@ -1185,6 +1185,7 @@
                         xwarn("cleanup() unregister_blkdev() failed\n");
                 return 2;
         }
+ register_disk(NULL, BDEV(MAJOR_NR,0), 1, &cdrom_fops, 0);
         printk(msg);
         return 0;
 }
diff -urN linux-2.3.41/drivers/cdrom/optcd.c linux-bird.bdev/drivers/cdrom/optcd.c
--- linux-2.3.41/drivers/cdrom/optcd.c Thu Jan 20 22:47:24 2000
+++ linux-bird.bdev/drivers/cdrom/optcd.c Tue Feb 1 04:07:45 2000
@@ -2072,7 +2072,7 @@
         blk_init_queue(BLK_DEFAULT_QUEUE(MAJOR_NR), DEVICE_REQUEST);
         read_ahead[MAJOR_NR] = 4;
         request_region(optcd_port, 4, "optcd");
- register_disk(NULL, MKDEV(MAJOR_NR,0), 1, &opt_fops, 0);
+ register_disk(NULL, BDEV(MAJOR_NR,0), 1, &opt_fops, 0);
 
         printk(KERN_INFO "optcd: DOLPHIN 8000 AT CDROM at 0x%x\n", optcd_port);
         return 0;
diff -urN linux-2.3.41/drivers/cdrom/sbpcd.c linux-bird.bdev/drivers/cdrom/sbpcd.c
--- linux-2.3.41/drivers/cdrom/sbpcd.c Mon Dec 13 17:08:40 1999
+++ linux-bird.bdev/drivers/cdrom/sbpcd.c Tue Feb 1 04:07:45 2000
@@ -5744,6 +5744,8 @@
         read_ahead[MAJOR_NR] = buffers * (CD_FRAMESIZE / 512);
         
         request_region(CDo_command,4,major_name);
+
+ blksize_size[MAJOR_NR]=sbpcd_blocksizes;
         
         for (j=0;j<NR_SBPCD;j++)
         {
@@ -5793,17 +5795,16 @@
                 sbpcd_infop->dev = MKDEV(MAJOR_NR, j);
                 strncpy(sbpcd_infop->name,major_name, sizeof(sbpcd_infop->name));
 
- if (register_cdrom(sbpcd_infop))
- {
- printk(" sbpcd: Unable to register with Uniform CD-ROm driver\n");
- }
-
                 /*
                  * set the block size
                  */
                 sbpcd_blocksizes[j]=CD_FRAMESIZE;
+
+ if (register_cdrom(sbpcd_infop))
+ printk(" sbpcd: Unable to register with Uniform CD-ROm driver\n");
+ else
+ register_disk(NULL,BDEV(MAJOR_NR,j),1,&cdrom_fops,0);
         }
- blksize_size[MAJOR_NR]=sbpcd_blocksizes;
 
 #ifndef MODULE
  init_done:
@@ -5827,13 +5828,6 @@
 {
         int j;
         
- if ((unregister_blkdev(MAJOR_NR, major_name) == -EINVAL))
- {
- msg(DBG_INF, "What's that: can't unregister %s.\n", major_name);
- return;
- }
- release_region(CDo_command,4);
-
         for (j=0;j<NR_SBPCD;j++)
         {
                 if (D_S[j].drv_id==-1) continue;
@@ -5846,6 +5840,14 @@
                 }
                 vfree(D_S[j].sbpcd_infop);
         }
+
+ if ((unregister_blkdev(MAJOR_NR, major_name) == -EINVAL))
+ {
+ msg(DBG_INF, "What's that: can't unregister %s.\n", major_name);
+ return;
+ }
+ release_region(CDo_command,4);
+
         msg(DBG_INF, "%s module released.\n", major_name);
 }
 
diff -urN linux-2.3.41/drivers/cdrom/sjcd.c linux-bird.bdev/drivers/cdrom/sjcd.c
--- linux-2.3.41/drivers/cdrom/sjcd.c Thu Jan 20 22:47:24 2000
+++ linux-bird.bdev/drivers/cdrom/sjcd.c Tue Feb 1 04:07:45 2000
@@ -1478,7 +1478,6 @@
   
   blk_init_queue(BLK_DEFAULT_QUEUE(MAJOR_NR), DEVICE_REQUEST);
   read_ahead[ MAJOR_NR ] = 4;
- register_disk(NULL, MKDEV(MAJOR_NR,0), 1, &sjcd_fops, 0);
   
   if( check_region( sjcd_base, 4 ) ){
     printk( "SJCD: Init failed, I/O port (%X) is already in use\n",
@@ -1565,6 +1564,7 @@
   printk(KERN_INFO "SJCD: Status: port=0x%x.\n", sjcd_base);
 
   sjcd_present++;
+ register_disk(NULL, BDEV(MAJOR_NR,0), 1, &sjcd_fops, 0);
   return( 0 );
 }
 
diff -urN linux-2.3.41/drivers/cdrom/sonycd535.c linux-bird.bdev/drivers/cdrom/sonycd535.c
--- linux-2.3.41/drivers/cdrom/sonycd535.c Thu Jan 20 22:47:24 2000
+++ linux-bird.bdev/drivers/cdrom/sonycd535.c Tue Feb 1 04:07:45 2000
@@ -1634,7 +1634,7 @@
                 return -EIO;
         }
         request_region(sony535_cd_base_io, 4, CDU535_HANDLE);
- register_disk(NULL, MKDEV(MAJOR_NR,0), 1, &cdu_fops, 0);
+ register_disk(NULL, BDEV(MAJOR_NR,0), 1, &cdu_fops, 0);
         return 0;
 }
 
diff -urN linux-2.3.41/drivers/i2o/i2o_block.c linux-bird.bdev/drivers/i2o/i2o_block.c
--- linux-2.3.41/drivers/i2o/i2o_block.c Thu Jan 20 22:47:25 2000
+++ linux-bird.bdev/drivers/i2o/i2o_block.c Tue Feb 1 04:07:45 2000
@@ -1120,7 +1120,7 @@
          */
 
         for (i = 0; i < MAX_I2OB; i++)
- register_disk(&i2ob_gendisk, MKDEV(MAJOR_NR,i<<4), 1<<4,
+ register_disk(&i2ob_gendisk, BDEV(MAJOR_NR,i<<4), 1<<4,
                         &i2ob_fops, 0);
         i2ob_probe();
         
diff -urN linux-2.3.41/drivers/scsi/sd.c linux-bird.bdev/drivers/scsi/sd.c
--- linux-2.3.41/drivers/scsi/sd.c Fri Jan 28 21:45:42 2000
+++ linux-bird.bdev/drivers/scsi/sd.c Tue Feb 1 04:07:45 2000
@@ -1012,17 +1012,21 @@
                 LAST_SD_GENDISK.next = gendisk_head;
                 gendisk_head = sd_gendisks;
         }
- for (i = 0; i < sd_template.dev_max; ++i)
- if (!rscsi_disks[i].capacity && rscsi_disks[i].device) {
- sd_init_onedisk(i);
- if (!rscsi_disks[i].has_part_table) {
- sd_sizes[i << 4] = rscsi_disks[i].capacity;
- register_disk(&SD_GENDISK(i), MKDEV_SD(i),
+ for (i = 0; i < sd_template.dev_max; ++i) {
+ if (!rscsi_disks[i].device) /* nothing to talk about */
+ continue;
+ if (rscsi_disks[i].capacity)
+ continue;
+ sd_init_onedisk(i);
+ if (rscsi_disks[i].has_part_table) /* we are already done */
+ continue;
+ sd_sizes[i << 4] = rscsi_disks[i].capacity;
+ rscsi_disks[i].disk = register_disk(&SD_GENDISK(i),
+ (unsigned)MKDEV_SD(i),
                                                 1<<4, &sd_fops,
                                                 rscsi_disks[i].capacity);
- rscsi_disks[i].has_part_table = 1;
- }
- }
+ rscsi_disks[i].has_part_table = 1;
+ }
         /* If our host adapter is capable of scatter-gather, then we increase
          * the read-ahead to 60 blocks (120 sectors). If not, we use
          * a two block (4 sector) read ahead. We can only respect this with the
@@ -1174,7 +1178,8 @@
                                 sd_gendisks->part[index].nr_sects = 0;
                                 sd_sizes[index] = 0;
                         }
- /* unregister_disk() */
+ unregister_disk(dpnt->disk);
+ dpnt->disk = NULL;
                         dpnt->has_part_table = 0;
                         dpnt->device = NULL;
                         dpnt->capacity = 0;
diff -urN linux-2.3.41/drivers/scsi/sd.h linux-bird.bdev/drivers/scsi/sd.h
--- linux-2.3.41/drivers/scsi/sd.h Fri Jan 7 21:49:15 2000
+++ linux-bird.bdev/drivers/scsi/sd.h Tue Feb 1 04:07:45 2000
@@ -25,6 +25,7 @@
 
 extern struct hd_struct *sd;
 
+struct disk_struct;
 typedef struct scsi_disk {
         unsigned capacity; /* size in blocks */
         Scsi_Device *device;
@@ -33,6 +34,7 @@
         unsigned char sector_bit_size; /* sector_size = 2 to the bit size power */
         unsigned char sector_bit_shift; /* power of 2 sectors per FS block */
         unsigned has_part_table:1; /* has partition table */
+ struct disk_struct *disk;
 } Scsi_Disk;
 
 extern int revalidate_scsidisk(kdev_t dev, int maxusage);
diff -urN linux-2.3.41/drivers/scsi/sr.c linux-bird.bdev/drivers/scsi/sr.c
--- linux-2.3.41/drivers/scsi/sr.c Fri Jan 28 21:45:42 2000
+++ linux-bird.bdev/drivers/scsi/sr.c Tue Feb 1 04:07:45 2000
@@ -735,6 +735,14 @@
         blk_dev[MAJOR_NR].queue = sr_find_queue;
         blk_size[MAJOR_NR] = sr_sizes;
 
+ /* If our host adapter is capable of scatter-gather, then we increase
+ * the read-ahead to 16 blocks (32 sectors). If not, we use
+ * a two block (4 sector) read ahead. */
+ if (scsi_CDs[0].device && scsi_CDs[0].device->host->sg_tablesize)
+ read_ahead[MAJOR_NR] = 32; /* 32 sector read-ahead. Always removable. */
+ else
+ read_ahead[MAJOR_NR] = 4; /* 4 sector read-ahead */
+
         for (i = 0; i < sr_template.nr_dev; ++i) {
                 /* If we have already seen this, then skip it. Comes up
                  * with loadable modules. */
@@ -768,17 +776,10 @@
                 sprintf(name, "sr%d", i);
                 strcpy(scsi_CDs[i].cdi.name, name);
                 register_cdrom(&scsi_CDs[i].cdi);
+ scsi_CDs[i].disk = register_disk(NULL, BDEV(MAJOR_NR,i), 1,
+ &cdrom_fops, 0);
         }
 
-
- /* If our host adapter is capable of scatter-gather, then we increase
- * the read-ahead to 16 blocks (32 sectors). If not, we use
- * a two block (4 sector) read ahead. */
- if (scsi_CDs[0].device && scsi_CDs[0].device->host->sg_tablesize)
- read_ahead[MAJOR_NR] = 32; /* 32 sector read-ahead. Always removable. */
- else
- read_ahead[MAJOR_NR] = 4; /* 4 sector read-ahead */
-
         return;
 }
 
@@ -789,16 +790,8 @@
 
         for (cpnt = scsi_CDs, i = 0; i < sr_template.dev_max; i++, cpnt++)
                 if (cpnt->device == SDp) {
- kdev_t devi = MKDEV(MAJOR_NR, i);
- struct super_block *sb = get_super(devi);
-
- /*
- * Since the cdrom is read-only, no need to sync the device.
- * We should be kind to our buffer cache, however.
- */
- if (sb)
- invalidate_inodes(sb);
- invalidate_buffers(devi);
+ unregister_disk(scsi_CDs[i].disk);
+ scsi_CDs[i].disk = NULL;
 
                         /*
                          * Reset things back to a sane state so that one can re-load a new
diff -urN linux-2.3.41/drivers/scsi/sr.h linux-bird.bdev/drivers/scsi/sr.h
--- linux-2.3.41/drivers/scsi/sr.h Mon Dec 13 02:04:20 1999
+++ linux-bird.bdev/drivers/scsi/sr.h Tue Feb 1 04:07:45 2000
@@ -19,6 +19,8 @@
 
 #include "scsi.h"
 
+struct disk_struct;
+
 typedef struct {
         unsigned capacity; /* size in blocks */
         Scsi_Device *device;
@@ -32,6 +34,7 @@
         unsigned readcd_known:1; /* drive supports READ_CD (0xbe) */
         unsigned readcd_cdda:1; /* reading audio data using READ_CD */
         struct cdrom_device_info cdi;
+ struct disk_struct *disk;
 } Scsi_CD;
 
 extern Scsi_CD *scsi_CDs;
diff -urN linux-2.3.41/fs/block_dev.c linux-bird.bdev/fs/block_dev.c
--- linux-2.3.41/fs/block_dev.c Fri Jan 28 21:45:45 2000
+++ linux-bird.bdev/fs/block_dev.c Tue Feb 1 04:24:50 2000
@@ -10,6 +10,7 @@
 #include <linux/fcntl.h>
 #include <linux/malloc.h>
 #include <linux/kmod.h>
+#include <linux/blkdev.h>
 
 #include <asm/uaccess.h>
 
@@ -304,7 +305,7 @@
 }
 
 /*
- * bdev cache handling - shamelessly stolen from inode.c
+ * bdev and disk_struct caches handling - shamelessly stolen from inode.c
  * We use smaller hashtable, though.
  */
 
@@ -314,12 +315,31 @@
 static struct list_head bdev_hashtable[HASH_SIZE];
 static spinlock_t bdev_lock = SPIN_LOCK_UNLOCKED;
 static kmem_cache_t * bdev_cachep;
+static kmem_cache_t * disks_cachep;
+
+#define alloc_disk() \
+ ((struct disk_struct *) kmem_cache_alloc(disks_cachep, SLAB_KERNEL))
+#define destroy_disk(disk) kmem_cache_free(bdev_cachep, (disk))
 
 #define alloc_bdev() \
          ((struct block_device *) kmem_cache_alloc(bdev_cachep, SLAB_KERNEL))
 #define destroy_bdev(bdev) kmem_cache_free(bdev_cachep, (bdev))
 
-static void init_once(void * foo, kmem_cache_t * cachep, unsigned long flags)
+static void init_disk(void * foo, kmem_cache_t * cachep, unsigned long flags)
+{
+ struct disk_struct * disk = (struct disk_struct *) foo;
+
+ if ((flags & (SLAB_CTOR_VERIFY|SLAB_CTOR_CONSTRUCTOR)) ==
+ SLAB_CTOR_CONSTRUCTOR)
+ {
+ memset(disk, 0, sizeof(*disk));
+ init_waitqueue_head(&disk->wqueue);
+ INIT_LIST_HEAD(&disk->disks);
+ INIT_LIST_HEAD(&disk->bdevs);
+ }
+}
+
+static void init_bdev(void * foo, kmem_cache_t * cachep, unsigned long flags)
 {
         struct block_device * bdev = (struct block_device *) foo;
 
@@ -331,6 +351,15 @@
         }
 }
 
+struct range_node *root_bdev_range = NULL;
+
+static void bdev_loader(struct range_node *dummy, unsigned devnum)
+{
+ char name[20];
+ sprintf(name, "block-major-%d", MAJOR(devnum));
+ request_module(name);
+}
+
 void bdev_init(void)
 {
         int i;
@@ -345,10 +374,25 @@
 
         bdev_cachep = kmem_cache_create("bdev_cache",
                                          sizeof(struct block_device),
- 0, SLAB_HWCACHE_ALIGN, init_once,
+ 0, SLAB_HWCACHE_ALIGN, init_bdev,
                                          NULL);
         if (!bdev_cachep)
                 panic("cannot create bdev slab cache");
+
+ disks_cachep = kmem_cache_create("disks_cache",
+ sizeof(struct disk_struct),
+ 0, SLAB_HWCACHE_ALIGN, init_disk,
+ NULL);
+ if (!disks_cachep)
+ panic("cannot create disk_struct slab cache");
+
+ root_bdev_range = range_create();
+ if (!root_bdev_range)
+ panic("cannot allocate the root range for block devices");
+ root_bdev_range->from = BDEV(1,0);
+ root_bdev_range->to = BDEV(254,255);
+ root_bdev_range->loader = bdev_loader;
+ range_unlock(root_bdev_range);
 }
 
 /*
@@ -390,7 +434,7 @@
                 return NULL;
         atomic_set(&new_bdev->bd_count,1);
         new_bdev->bd_dev = dev;
- new_bdev->bd_op = NULL;
+ new_bdev->bd_disk = NULL;
         spin_lock(&bdev_lock);
         bdev = bdfind(dev, head);
         if (!bdev) {
@@ -422,56 +466,208 @@
         { NULL, NULL },
 };
 
-int get_blkdev_list(char * p)
+/* Handling of the block_driver. Too few of them to bother with slabs */
+
+static LIST_HEAD(block_drivers_list);
+static spinlock_t drivers_lock = SPIN_LOCK_UNLOCKED; /* insert/remove/look */
+
+struct block_driver *register_block_driver(char *name, int major)
 {
- int i;
- int len;
+ struct block_driver *res;
+ struct range_node *range;
+ int err = -ENOMEM;
+ res = (struct block_driver *)kmalloc(sizeof(*res), GFP_KERNEL);
+ if (!res)
+ goto fail;
+ memset(res, 0, sizeof(*res));
+ INIT_LIST_HEAD(&res->disks);
+ res->name = name;
+ if (major) {
+ range = range_create();
+ if (!range)
+ goto fail_range;
+ range->kind = BDEV_DRIVER_RANGE;
+ err = range_add(root_bdev_range, BDEV(major,0),
+ BDEV(major,255), range);
+ if (err)
+ goto fail_add;
+ res->range = range;
+ }
+ spin_lock(&drivers_lock);
+ list_add(&res->drivers,block_drivers_list.prev);
+ spin_unlock(&drivers_lock);
+ return res;
 
- len = sprintf(p, "\nBlock devices:\n");
- for (i = 0; i < MAX_BLKDEV ; i++) {
- if (blkdevs[i].bdops) {
- len += sprintf(p+len, "%3d %s\n", i, blkdevs[i].name);
+fail_add:
+ range_delete(range);
+fail_range:
+ kfree(res);
+fail:
+ return ERR_PTR(err);
+}
+
+struct disk_struct *__register_disk(struct block_driver *driver,
+ struct gendisk *gdev,
+ unsigned first, unsigned minors,
+ struct block_device_operations *ops,
+ struct module *owner)
+{
+ struct disk_struct *disk;
+ struct range_node *range, *area;
+ int err = -ENOMEM;
+
+ disk = alloc_disk();
+ if (!disk)
+ goto fail;
+
+ disk->name = NULL; /* FIXME */
+ disk->gendisk = gdev;
+ disk->bd_ops = ops;
+ disk->driver = driver;
+
+ range = range_create();
+ if (!range)
+ goto fail_range;
+
+ range->owner = owner;
+ range->data = (void*)disk;
+ disk->range = range;
+ range->kind = BDEV_DISK_RANGE;
+
+ /* Let's find where to put it */
+ err = -EINVAL;
+ for(area = driver->range; area; area = (struct range_node*)area->data)
+ if (area->from <= first && area->to >= first+minors-1)
+ break;
+ if (area)
+ err = range_add(area, first, first+minors-1, range);
+ if (err)
+ goto fail_add;
+ list_add(&disk->disks, &driver->disks);
+ range_unlock(range);
+ return disk;
+
+fail_add:
+ range_delete(range);
+fail_range:
+ destroy_disk(disk);
+fail:
+ return ERR_PTR(err);
+}
+
+void unregister_disk(struct disk_struct *disk)
+{
+ range_delete(disk->range);
+ disk->range = NULL;
+ /*
+ * If Stephen really wants to keep buffer_cache across the close,
+ * fine - we will just check that nobody is opened, invalidate
+ * the cache and detach block_devices from the disk_struct.
+ */
+ if (!list_empty(&disk->bdevs))
+ goto should_never_ever_happen;
+ list_del(&disk->disks);
+ INIT_LIST_HEAD(&disk->disks);
+ disk->driver = NULL;
+ destroy_disk(disk);
+ return;
+
+should_never_ever_happen:
+ /* We just do not do it. */
+ panic("unregister_disk with device(s) still opened. We are buggered\n");
+}
+
+int unregister_block_driver(struct block_driver *driver)
+{
+ int err;
+ struct range_node *area;
+ while (!list_empty(&driver->disks))
+ unregister_disk(list_entry(driver->disks.next,
+ struct disk_struct, disks));
+ spin_lock(&drivers_lock);
+ area = driver->range;
+ while(driver->range) {
+ area = driver->range;
+ driver->range = area->data;
+ err = range_delete(area);
+ if (err) {
+ driver->range = area;
+ spin_unlock(&drivers_lock);
+ return err;
                 }
         }
- return len;
+ list_del(&driver->drivers);
+ spin_unlock(&drivers_lock);
+ INIT_LIST_HEAD(&driver->drivers);
+ kfree(driver);
+ return 0;
 }
 
-/*
- Return the function table of a device.
- Load the driver if needed.
-*/
-static const struct block_device_operations * get_blkfops(unsigned int major)
-{
- const struct block_device_operations *ret = NULL;
-
- /* major 0 is used for non-device mounts */
- if (major && major < MAX_BLKDEV) {
-#ifdef CONFIG_KMOD
- if (!blkdevs[major].bdops) {
- char name[20];
- sprintf(name, "block-major-%d", major);
- request_module(name);
- }
-#endif
- ret = blkdevs[major].bdops;
+int block_area_remove(struct block_driver *driver, unsigned from)
+{
+ int err = -ENODEV;
+ struct range_node **p = &driver->range;
+ spin_lock(&drivers_lock);
+ while(*p && (*p)->from != from)
+ p = (struct range_node **)&(*p)->data;
+ if (*p) {
+ struct range_node *next = (*p)->data;
+ err = range_delete(*p);
+ if (!err)
+ *p = next;
+ }
+ spin_unlock(&drivers_lock);
+ return err;
+}
+
+struct range_node *block_area_add(struct block_driver *driver, unsigned from, unsigned size)
+{
+ struct range_node * range = range_create();
+ struct range_node **p;
+ int err = -ENOMEM;
+ if (!range)
+ goto fail;
+ range->kind = BDEV_DRIVER_RANGE;
+ err = range_add(root_bdev_range, from, from+size-1, range);
+ if (err)
+ goto fail_add;
+ spin_lock(&drivers_lock);
+ for (p = &driver->range; *p; p=(struct range_node **)&(*p)->data)
+ ;
+ *p = range;
+ spin_unlock(&drivers_lock);
+ return range;
+
+fail_add:
+ range_delete(range);
+fail:
+ return ERR_PTR(err);
+}
+
+int get_blkdev_list(char * p)
+{
+ int len;
+ struct list_head *tmp;
+ struct block_driver *driver;
+ struct range_node *area;
+ char *name;
+
+ len = sprintf(p, "\nBlock devices:\n");
+ spin_lock(&drivers_lock);
+ tmp = block_drivers_list.next;
+ while (tmp != &block_drivers_list) {
+ driver = list_entry(tmp,struct block_driver,drivers);
+ name = driver->name;
+ for (area = driver->range; area ; area = area->data)
+ len += sprintf(p+len,"%3d %s\n",MAJOR(area->from),name);
+ tmp = tmp->next;
         }
- return ret;
+ spin_unlock(&drivers_lock);
+ return len;
 }
 
 int register_blkdev(unsigned int major, const char * name, struct block_device_operations *bdops)
 {
- if (major == 0) {
- for (major = MAX_BLKDEV-1; major > 0; major--) {
- if (blkdevs[major].bdops == NULL) {
- blkdevs[major].name = name;
- blkdevs[major].bdops = bdops;
- return major;
- }
- }
- return -EBUSY;
- }
- if (major >= MAX_BLKDEV)
- return -EINVAL;
         if (blkdevs[major].bdops && blkdevs[major].bdops != bdops)
                 return -EBUSY;
         blkdevs[major].name = name;
@@ -536,46 +732,79 @@
         int res;
         mm_segment_t old_fs = get_fs();
 
- if (!bdev->bd_op->ioctl)
+ if (!bdev->bd_disk->bd_ops->ioctl)
                 return -EINVAL;
         inode_fake.i_rdev=rdev;
         init_waitqueue_head(&inode_fake.i_wait);
         set_fs(KERNEL_DS);
- res = bdev->bd_op->ioctl(&inode_fake, NULL, cmd, arg);
+ res = bdev->bd_disk->bd_ops->ioctl(&inode_fake, NULL, cmd, arg);
         set_fs(old_fs);
         return res;
 }
 
+static inline int blkdev_bind(struct block_device *bdev)
+{
+ struct range_node *range;
+ if (bdev->bd_disk)
+ return 0;
+ range = range_lookup(root_bdev_range, bdev->bd_dev);
+ if (range->kind != BDEV_DISK_RANGE)
+ goto fail;
+ bdev->bd_disk = range->data;
+ list_add(&bdev->bd_part, &bdev->bd_disk->bdevs);
+ return 0;
+fail:
+ range_put(range);
+ return -ENODEV;
+}
+
+static inline void blkdev_drop(struct block_device *bdev)
+{
+ if (!atomic_read(&bdev->bd_openers)) {
+ range_put(bdev->bd_disk->range);
+ bdev->bd_disk = NULL;
+ list_del(&bdev->bd_part);
+ INIT_LIST_HEAD(&bdev->bd_part);
+ }
+}
+
 int blkdev_get(struct block_device *bdev, mode_t mode, unsigned flags, int kind)
 {
         int ret = -ENODEV;
         kdev_t rdev = to_kdev_t(bdev->bd_dev); /* this should become bdev */
+ struct file fake_file = {};
+ struct dentry fake_dentry = {};
+ struct inode *fake_inode;
+
         down(&bdev->bd_sem);
- if (!bdev->bd_op)
- bdev->bd_op = get_blkfops(MAJOR(rdev));
- if (bdev->bd_op) {
- /*
- * This crockload is due to bad choice of ->open() type.
- * It will go away.
- */
- struct file fake_file = {};
- struct dentry fake_dentry = {};
- struct inode *fake_inode = get_empty_inode();
- ret = -ENOMEM;
- if (fake_inode) {
- fake_file.f_mode = mode;
- fake_file.f_flags = flags;
- fake_file.f_dentry = &fake_dentry;
- fake_dentry.d_inode = fake_inode;
- fake_inode->i_rdev = rdev;
- ret = 0;
- if (bdev->bd_op->open)
- ret = bdev->bd_op->open(fake_inode, &fake_file);
- if (!ret)
- atomic_inc(&bdev->bd_openers);
- iput(fake_inode);
- }
- }
+
+ ret = blkdev_bind(bdev);
+ if (ret)
+ goto out;
+
+ /*
+ * This crockload is due to bad choice of ->open() type.
+ * It will go away.
+ */
+ ret = -ENOMEM;
+ fake_inode = get_empty_inode();
+ if (!fake_inode)
+ goto out;
+ fake_file.f_mode = mode;
+ fake_file.f_flags = flags;
+ fake_file.f_dentry = &fake_dentry;
+ fake_dentry.d_inode = fake_inode;
+ fake_inode->i_rdev = rdev;
+ ret = 0;
+
+ if (bdev->bd_disk->bd_ops->open)
+ ret = bdev->bd_disk->bd_ops->open(fake_inode, &fake_file);
+ if (!ret)
+ atomic_inc(&bdev->bd_openers);
+ else
+ blkdev_drop(bdev);
+ iput(fake_inode);
+out:
         up(&bdev->bd_sem);
         return ret;
 }
@@ -585,15 +814,16 @@
         int ret = -ENODEV;
         struct block_device *bdev = inode->i_bdev;
         down(&bdev->bd_sem);
- if (!bdev->bd_op)
- bdev->bd_op = get_blkfops(MAJOR(inode->i_rdev));
- if (bdev->bd_op) {
- ret = 0;
- if (bdev->bd_op->open)
- ret = bdev->bd_op->open(inode,filp);
- if (!ret)
- atomic_inc(&bdev->bd_openers);
- }
+ ret = blkdev_bind(bdev);
+ if (ret)
+ goto out;
+ if (bdev->bd_disk->bd_ops->open)
+ ret = bdev->bd_disk->bd_ops->open(inode,filp);
+ if (!ret)
+ atomic_inc(&bdev->bd_openers);
+ else
+ blkdev_drop(bdev);
+out:
         up(&bdev->bd_sem);
         return ret;
 }
@@ -610,18 +840,16 @@
                 /* invalidating buffers will go here */
                 invalidate_buffers(rdev);
         }
- if (bdev->bd_op->release) {
+ if (bdev->bd_disk->bd_ops->release) {
                 struct inode * fake_inode = get_empty_inode();
                 ret = -ENOMEM;
                 if (fake_inode) {
                         fake_inode->i_rdev = rdev;
- ret = bdev->bd_op->release(fake_inode, NULL);
+ ret = bdev->bd_disk->bd_ops->release(fake_inode, NULL);
                         iput(fake_inode);
                 }
         }
- if (!atomic_read(&bdev->bd_openers))
- bdev->bd_op = NULL; /* we can't rely on driver being */
- /* kind to stay around. */
+ blkdev_drop(bdev);
         up(&bdev->bd_sem);
         return ret;
 }
@@ -634,8 +862,9 @@
 static int blkdev_ioctl(struct inode *inode, struct file *file, unsigned cmd,
                         unsigned long arg)
 {
- if (inode->i_bdev->bd_op->ioctl)
- return inode->i_bdev->bd_op->ioctl(inode, file, cmd, arg);
+ struct block_device_operations *bd_ops = inode->i_bdev->bd_disk->bd_ops;
+ if (bd_ops->ioctl)
+ return bd_ops->ioctl(inode, file, cmd, arg);
         return -EINVAL;
 }
 
diff -urN linux-2.3.41/fs/partitions/check.c linux-bird.bdev/fs/partitions/check.c
--- linux-2.3.41/fs/partitions/check.c Fri Jan 28 21:45:46 2000
+++ linux-bird.bdev/fs/partitions/check.c Tue Feb 1 04:08:49 2000
@@ -273,14 +273,6 @@
  * 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;
diff -urN linux-2.3.41/include/linux/blkdev.h linux-bird.bdev/include/linux/blkdev.h
--- linux-2.3.41/include/linux/blkdev.h Fri Jan 28 21:45:48 2000
+++ linux-bird.bdev/include/linux/blkdev.h Tue Feb 1 04:26:00 2000
@@ -5,6 +5,41 @@
 #include <linux/sched.h>
 #include <linux/genhd.h>
 #include <linux/tqueue.h>
+#include <linux/range_tree.h>
+
+enum { BDEV_DRIVER_RANGE=1, BDEV_DISK_RANGE=2 };
+struct block_driver {
+ /* list of our disks */
+ struct list_head disks;
+
+ /* list of all block drivers */
+ struct list_head drivers;
+
+ /* first range of device numbers; if we have more than one -
+ * ->range->data will point to the next. */
+ struct range_node * range;
+ char * name;
+};
+
+struct disk_struct {
+ /* list of all disks belonging to the same driver */
+ struct list_head disks;
+ /* our driver */
+ struct block_driver * driver;
+ /* device numbers range; ->range->data points back to us */
+ struct range_node * range;
+ /* list of all opened block devices that belong to us */
+ struct list_head bdevs;
+ /* disk size; unit is 512 byte, same as in struct request */
+ unsigned long sectors;
+ struct block_device_operations *bd_ops;
+ int users;
+ /* serialization between open and reading partition table */
+ wait_queue_head_t wqueue;
+ /* atavism */
+ struct gendisk * gendisk;
+ char * name;
+};
 
 /*
  * Ok, this is an expanded form so that we can use the same
@@ -102,13 +137,32 @@
  */
 #define BLK_DEFAULT_QUEUE(_MAJOR) &blk_dev[_MAJOR].request_queue
 
+extern struct range_node *root_bdev_range;
+
 extern struct sec_size * blk_sec[MAX_BLKDEV];
 extern struct blk_dev_struct blk_dev[MAX_BLKDEV];
 extern wait_queue_head_t wait_for_request;
-extern void grok_partitions(struct gendisk *dev, int drive, unsigned minors, long size);
-extern void register_disk(struct gendisk *dev, kdev_t first, unsigned minors, struct block_device_operations *ops, long size);
+extern struct block_driver *register_block_driver(char *name, int major);
+extern int unregister_block_driver(struct block_driver *driver);
+extern struct range_node *block_area_add(struct block_driver *driver, unsigned from, unsigned size);
+extern int block_area_remove(struct block_driver *driver, unsigned from);
+extern struct disk_struct *__register_disk(struct block_driver *driver,
+ struct gendisk *gdev,
+ unsigned first, unsigned minors,
+ struct block_device_operations *ops,
+ struct module *owner);
+
+static inline struct disk_struct *register_disk(struct block_driver *driver,
+ struct gendisk *gdev,
+ unsigned first, unsigned minors,
+ struct block_device_operations *ops) {
+ return __register_disk(driver, gdev, first, minors, ops, THIS_MODULE);
+}
+extern void unregister_disk(struct disk_struct *disk);
+extern void parse_partitions(struct disk_struct *disk);
 extern void unplug_device(void * data);
 extern void make_request(int major,int rw, struct buffer_head * bh);
+#define BDEV(major,minor) ((unsigned)MKDEV((major),(minor)))
 
 /*
  * Access functions for manipulating queue properties
diff -urN linux-2.3.41/include/linux/fs.h linux-bird.bdev/include/linux/fs.h
--- linux-2.3.41/include/linux/fs.h Fri Jan 28 21:45:48 2000
+++ linux-bird.bdev/include/linux/fs.h Tue Feb 1 04:07:53 2000
@@ -338,14 +338,17 @@
         unsigned long nrpages;
 };
 
+struct disk_struct;
+
 struct block_device {
         struct list_head bd_hash;
         atomic_t bd_count;
+ struct disk_struct * bd_disk;
 /* struct address_space bd_data; */
         dev_t bd_dev; /* not a kdev_t - it's a search key */
         atomic_t bd_openers;
- const struct block_device_operations *bd_op;
         struct semaphore bd_sem; /* open/close mutex */
+ struct list_head bd_part; /* other opened partitions */
 };
 
 struct inode {
diff -urN linux-2.3.41/include/linux/ide.h linux-bird.bdev/include/linux/ide.h
--- linux-2.3.41/include/linux/ide.h Fri Jan 28 21:45:48 2000
+++ linux-bird.bdev/include/linux/ide.h Tue Feb 1 04:07:53 2000
@@ -292,6 +292,7 @@
         void *driver_data; /* extra driver data */
         struct proc_dir_entry *proc; /* /proc/ide/ directory entry */
         void *settings; /* /proc/ide/ drive settings */
+ struct disk_struct *disk; /* disk_struct for disks/floppies/CDs */
         char driver_req[10]; /* requests specific driver */
 #if 1
         struct thresholds_s *smart_thresholds;
diff -urN linux-2.3.41/include/linux/range_tree.h linux-bird.bdev/include/linux/range_tree.h
--- linux-2.3.41/include/linux/range_tree.h Wed Dec 31 19:00:00 1969
+++ linux-bird.bdev/include/linux/range_tree.h Tue Feb 1 04:07:53 2000
@@ -0,0 +1,58 @@
+#ifndef _RANGE_TREE_H
+#define _RANGE_TREE_H
+#include <linux/list.h>
+#include <linux/module.h>
+
+struct range_node;
+/*
+ * Gets a reference to range and element of range; supposed to try to get
+ * smaller range containing the element.
+ */
+
+typedef void range_split_t(struct range_node *, unsigned);
+
+/*
+ * Subranges are kept in array. More accurately, references to them are.
+ * Array is sorted by the subrange (they can't intersect ;-). We keep pairs
+ * (reference to subrange's node , left boundary) there.
+ */
+struct range_ref {
+ unsigned from;
+ struct range_node *node;
+};
+
+/*
+ * Range. 'from' and 'to' are its boundaries, 'subnodes' is its array of
+ * references to subranges, 'subs' is the size of used part of array, 'real' -
+ * it's size. 'child' and 'sibs' host the lists of children - cyclic list starts
+ * at parent's 'child' and goes through 'sibs' of children. List is ordered by
+ * the range. 'parent' points to, erm, parent. For the root node - points to
+ * itself. 'loader' is the subrange-finding function of this range (typically
+ * it loads an appropriate module that registers subrange). 'data' is opaque -
+ * it is set upon range creation and ignored by us. Callers should know what
+ * they placed there and what to do with it. 'owner' refers to the module that
+ * registered the range.
+ */
+struct range_node {
+ unsigned from, to;
+ unsigned subs, real;
+ struct range_ref *subnodes;
+ struct range_node *parent;
+ struct list_head child;
+ struct list_head sibs;
+ range_split_t *loader;
+ struct module *owner;
+ void *data;
+ int locked;
+ int kind;
+};
+
+struct range_node *range_lookup(struct range_node *, unsigned);
+int range_add(struct range_node *, unsigned, unsigned, struct range_node*);
+int range_fit(struct range_node *, unsigned, struct range_node *);
+struct range_node *range_create(void);
+int range_delete(struct range_node *);
+void range_put(struct range_node *node);
+void range_unlock(struct range_node *node);
+void range_trees_init(void);
+#endif
diff -urN linux-2.3.41/init/main.c linux-bird.bdev/init/main.c
--- linux-2.3.41/init/main.c Thu Jan 20 22:47:32 2000
+++ linux-bird.bdev/init/main.c Tue Feb 1 04:07:53 2000
@@ -92,6 +92,7 @@
 extern void sysctl_init(void);
 extern void filescache_init(void);
 extern void signals_init(void);
+extern void range_trees_init(void);
 extern void bdev_init(void);
 extern int init_pcmcia_ds(void);
 
@@ -521,6 +522,7 @@
         page_cache_init(mempages);
         kiobuf_init();
         signals_init();
+ range_trees_init();
         bdev_init();
         inode_init();
         file_table_init();
diff -urN linux-2.3.41/kernel/ksyms.c linux-bird.bdev/kernel/ksyms.c
--- linux-2.3.41/kernel/ksyms.c Fri Jan 28 21:45:49 2000
+++ linux-bird.bdev/kernel/ksyms.c Tue Feb 1 04:07:53 2000
@@ -262,7 +262,11 @@
 EXPORT_SYMBOL(ioctl_by_bdev);
 EXPORT_SYMBOL(gendisk_head);
 EXPORT_SYMBOL(grok_partitions);
-EXPORT_SYMBOL(register_disk);
+EXPORT_SYMBOL(register_block_driver);
+EXPORT_SYMBOL(unregister_block_driver);
+EXPORT_SYMBOL(__register_disk);
+EXPORT_SYMBOL(unregister_disk);
+EXPORT_SYMBOL(range_unlock);
 EXPORT_SYMBOL(unplug_device);
 EXPORT_SYMBOL(make_request);
 EXPORT_SYMBOL(tq_disk);
diff -urN linux-2.3.41/lib/Makefile linux-bird.bdev/lib/Makefile
--- linux-2.3.41/lib/Makefile Mon Nov 27 08:54:00 1995
+++ linux-bird.bdev/lib/Makefile Tue Feb 1 04:07:53 2000
@@ -7,6 +7,6 @@
 #
 
 L_TARGET := lib.a
-L_OBJS := errno.o ctype.o string.o vsprintf.o
+L_OBJS := errno.o ctype.o string.o vsprintf.o range_tree.o
 
 include $(TOPDIR)/Rules.make
diff -urN linux-2.3.41/lib/range_tree.c linux-bird.bdev/lib/range_tree.c
--- linux-2.3.41/lib/range_tree.c Wed Dec 31 19:00:00 1969
+++ linux-bird.bdev/lib/range_tree.c Tue Feb 1 04:07:53 2000
@@ -0,0 +1,296 @@
+#include <linux/range_tree.h>
+#include <linux/malloc.h>
+
+#define DEBUG_RANGES
+
+static rwlock_t ranges_lock = RW_LOCK_UNLOCKED;
+static kmem_cache_t * range_cachep;
+static DECLARE_WAIT_QUEUE_HEAD(ranges_wait);
+
+#define alloc_range() \
+ ((struct range_node *) kmem_cache_alloc(range_cachep, SLAB_KERNEL))
+#define destroy_range(range) kmem_cache_free(range_cachep, (range))
+
+static inline struct range_ref *__range_find(struct range_ref *p, unsigned n,
+ unsigned key)
+{
+ unsigned m;
+ struct range_ref *q;
+ while (n > 1) {
+ m = n/2;
+ q = p + m;
+ if (q->from > key)
+ n = m;
+ else {
+ p = q;
+ n -= m;
+ }
+ }
+ return p;
+}
+
+static struct range_node *__range_lookup(struct range_node *node, unsigned key)
+{
+ struct range_node *next;
+ struct range_ref *p;
+ read_lock(&ranges_lock);
+ while (1) {
+ if (node->locked)
+ goto locked;
+ if (!node->subs)
+ break;
+ p = __range_find(node->subnodes, node->subs, key);
+ next = p->node;
+ if (key > next->to)
+ break;
+ /* Did we go before the first subrange? */
+ if (key <next->from)
+ break;
+ node = next;
+ }
+ if (node->owner)
+ __MOD_INC_USE_COUNT(node->owner);
+out:
+ read_unlock(&ranges_lock);
+ return node;
+locked:
+ node = NULL;
+ goto out;
+}
+
+struct range_node *range_create(void)
+{
+ struct range_node *p = alloc_range();
+ if (p)
+ p->locked = 1;
+ return p;
+}
+
+static inline int __range_add(struct range_node *node, unsigned index,
+ unsigned from, unsigned to, struct range_node *child)
+{
+ struct range_ref *p;
+ unsigned i;
+
+ /* need to expand? */
+ if (node->subs == node->real) {
+ /* Had anything? */
+ if (!node->real) {
+ node->subnodes = kmalloc(32*sizeof(struct range_ref),
+ GFP_KERNEL);
+ if (!node->subnodes)
+ return -ENOMEM;
+ node->real = 32;
+ } else {
+ void *p;
+ p = kmalloc(node->real*2*sizeof(struct range_ref),
+ GFP_KERNEL);
+ if (!p)
+ return -ENOMEM;
+ memcpy(p, node->subnodes,
+ node->real*sizeof(struct range_ref));
+ kfree(node->subnodes);
+ node->subnodes = p;
+ }
+ }
+ child->from = from;
+ child->to = to;
+ /* We need to shift everything starting from node->subnodes+index */
+ for (i=node->subs, p=node->subnodes+i; i>index; p[0]=p[-1], p--, i--)
+ ;
+ p->from = from;
+ p->node = child;
+ node->subs++;
+ child->parent = node;
+ if (index)
+ list_add(&child->sibs, &p[-1].node->sibs);
+ else
+ list_add(&child->sibs, &node->child);
+ return 0;
+}
+
+int range_add(struct range_node *node, unsigned from,
+ unsigned to, struct range_node *child)
+{
+ int err = -EBUSY;
+ unsigned i = 0;
+ struct range_ref *p;
+
+#ifdef DEBUG_RANGES
+ printk(KERN_INFO "range_add: %4x--%4x\n", from, to);
+#endif
+
+ write_lock(&ranges_lock);
+
+ if (!node->subs)
+ goto found;
+ p = __range_find(node->subnodes, node->subs, from);
+ /* Before the first subrange? */
+ if (from < p->from)
+ goto found;
+ if (from <= p->node->to)
+ goto fail;
+ i = (p - node->subnodes) + 1;
+found:
+ err = -EINVAL;
+ if (from < node->from || to > node->to || from > to)
+ goto fail;
+ err = __range_add(node,i,from,to,child);
+fail:
+ write_unlock(&ranges_lock);
+ return err;
+}
+
+int range_fit(struct range_node *node, unsigned size,
+ struct range_node *child)
+{
+ int i, err = -EBUSY;
+ unsigned long base;
+ struct range_ref *p;
+
+ write_lock(&ranges_lock);
+
+ for (i=0, base=node->from, p=node->subnodes; i<node->subs; i++, p++) {
+ if (p->from >= base+size)
+ goto found;
+ base = p->node->to;
+ base++;
+ }
+ if (base + size - 1 > node->to)
+ goto fail;
+found:
+ err = __range_add(node,i,(unsigned)base,(unsigned)(base+size-1),child);
+fail:
+ write_unlock(&ranges_lock);
+ return err;
+}
+
+int range_delete(struct range_node *node)
+{
+ int err = -EBUSY;
+
+#ifdef DEBUG_RANGES
+ printk(KERN_INFO "range_delete: %4x--%4x\n", node->from, node->to);
+#endif
+
+ write_lock(&ranges_lock);
+ if (node->subs)
+ goto fail;
+ if (node->real)
+ kfree(node->subnodes);
+ node->real = 0;
+ if (node->parent) {
+ struct range_ref *p;
+ int i;
+ err = -EINVAL;
+ if (!node->parent->subs)
+ goto fail;
+ p = __range_find(node->parent->subnodes,
+ node->parent->subs,
+ node->from);
+ if (p->node != node)
+ goto fail;
+ for(i = p-node->parent->subnodes;
+ i<node->parent->subs-1;
+ p[0]=p[1], p++, i++)
+ ;
+ node->parent->subs--;
+ list_del(&node->sibs);
+ node->parent = NULL;
+ node->kind = 0;
+ node->loader = NULL;
+ node->owner = NULL;
+ node->data = NULL;
+ if (node->locked) {
+ node->locked = 0;
+ wake_up(&ranges_wait);
+ }
+ }
+ INIT_LIST_HEAD(&node->sibs);
+ err = 0;
+ destroy_range(node);
+fail:
+ write_unlock(&ranges_lock);
+ return err;
+}
+
+void range_put(struct range_node *node)
+{
+ if (node->owner)
+ __MOD_DEC_USE_COUNT(node->owner);
+}
+
+void range_unlock(struct range_node *node)
+{
+#ifdef DEBUG_RANGES
+ printk(KERN_INFO "range_unlock: %4x--%4x\n", node->from, node->to);
+#endif
+ write_lock(&ranges_lock);
+ node->locked = 0;
+ write_unlock(&ranges_lock);
+ wake_up(&ranges_wait);
+}
+
+struct range_node *range_lookup(struct range_node *node, unsigned key)
+{
+ struct range_node *p, *q;
+retry:
+#ifdef DEBUG_RANGES
+ printk(KERN_INFO "range_lookup(%4x): %4x--%4x\n", key, node->from, node->to);
+#endif
+ q = __range_lookup(node, key);
+ if (!q)
+ goto locked;
+ while (q->loader) {
+ q->loader(q, key);
+#ifdef DEBUG_RANGES
+ printk(KERN_INFO "range_lookup(%4x): %4x--%4x\n", key, q->from, q->to);
+#endif
+ p = __range_lookup(q, key);
+ range_put(q);
+ if (!p)
+ goto locked;
+ if (p == q)
+ break;
+ q = p;
+ }
+ return q;
+locked:
+ /*
+ * We met a locked range. It means that somebody had allocated it
+ * and right now allocates subranges there. We just sleep and restart
+ * from square one once some range gets unlocked. Yes, it might be
+ * made less coarse. We don't need that - to start with, it's a slow
+ * path and it's taken only when we get a lookup into the range while
+ * the module is initializing (lookup that lead to module loading will
+ * not go here - usually it will sleep in request_module()). In theory
+ * we might want to sleep on class of range, but I doubt that it will
+ * actually buy us anything.
+ */
+
+ sleep_on(&ranges_wait);
+ goto retry;
+}
+
+static void init_once(void * p, kmem_cache_t * cachep, unsigned long flags)
+{
+ struct range_node * node = (struct range_node *) p;
+
+ if ((flags & (SLAB_CTOR_VERIFY|SLAB_CTOR_CONSTRUCTOR)) ==
+ SLAB_CTOR_CONSTRUCTOR)
+ {
+ memset(node, 0, sizeof(*node));
+ INIT_LIST_HEAD(&node->sibs);
+ INIT_LIST_HEAD(&node->child);
+ }
+}
+
+void range_trees_init(void)
+{
+ range_cachep = kmem_cache_create("range_cache",
+ sizeof(struct range_node),
+ 0, SLAB_HWCACHE_ALIGN, init_once,
+ NULL);
+ if (!range_cachep)
+ panic("cannot create range slab cache");
+}

-
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
Please read the FAQ at http://www.tux.org/lkml/



This archive was generated by hypermail 2b29 : Sat Jun 23 2001 - 21:00:33 EST