/* * This routine checks whether a floppy has been changed, and * invalidates all buffer-cache-entries in that case. This * is a relatively slow routine, so we have to try to minimize using * it. Thus it is called only upon a 'mount' or 'open'. This * is the best way of combining speed and utility, I think. * People changing diskettes in the middle of an operation deserve * to loose :-) * * NOTE! Although currently this is only for floppies, the idea is * that any additional removable block-device will use this routine, * and that mount/open needn't know that floppies/whatever are * special. */ void check_disk_change(dev_t dev) { int i; struct buffer_head * bh; switch(MAJOR(dev)){ case FLOPPY_MAJOR: if (!(bh = getblk(dev,0,1024))) return; i = floppy_change(bh); brelse(bh); break; #if defined(CONFIG_BLK_DEV_SD) && defined(CONFIG_SCSI) case SCSI_DISK_MAJOR: i = check_scsidisk_media_change(dev, 0); break; #endif #if defined(CONFIG_BLK_DEV_SR) && defined(CONFIG_SCSI) case SCSI_CDROM_MAJOR: i = check_cdrom_media_change(dev, 0); break; #endif #if defined(CONFIG_CDU31A) case CDU31A_CDROM_MAJOR: i = check_cdu31a_media_change(dev, 0); break; #endif #if defined(CONFIG_MCD) case MITSUMI_CDROM_MAJOR: i = check_mcd_media_change(dev, 0); break; #endif default: return; }; if (!i) return; printk("VFS: Disk change detected on device %d/%d\n", MAJOR(dev), MINOR(dev)); for (i=0 ; i<NR_SUPER ; i++) if (super_blocks[i].s_dev == dev) put_super(super_blocks[i].s_dev); invalidate_inodes(dev); invalidate_buffers(dev); #if defined(CONFIG_BLK_DEV_SD) && defined(CONFIG_SCSI) /* This is trickier for a removable hardisk, because we have to invalidate all of the partitions that lie on the disk. */ if (MAJOR(dev) == SCSI_DISK_MAJOR) revalidate_scsidisk(dev, 0); #endif }
static int sd_ioctl(struct inode * inode, struct file * file, unsigned int cmd, unsigned long arg) { kdev_t dev = inode->i_rdev; struct Scsi_Host * host; Scsi_Device * SDev; int diskinfo[4]; SDev = rscsi_disks[DEVICE_NR(dev)].device; if (!SDev) return -ENODEV; /* * If we are in the middle of error recovery, don't let anyone * else try and use this device. Also, if error recovery fails, it * may try and take the device offline, in which case all further * access to the device is prohibited. */ if( !scsi_block_when_processing_errors(SDev) ) { return -ENODEV; } switch (cmd) { case HDIO_GETGEO: /* Return BIOS disk parameters */ { struct hd_geometry *loc = (struct hd_geometry *) arg; if(!loc) return -EINVAL; host = rscsi_disks[DEVICE_NR(dev)].device->host; /* default to most commonly used values */ diskinfo[0] = 0x40; diskinfo[1] = 0x20; diskinfo[2] = rscsi_disks[DEVICE_NR(dev)].capacity >> 11; /* override with calculated, extended default, or driver values */ if(host->hostt->bios_param != NULL) host->hostt->bios_param(&rscsi_disks[DEVICE_NR(dev)], dev, &diskinfo[0]); else scsicam_bios_param(&rscsi_disks[DEVICE_NR(dev)], dev, &diskinfo[0]); if (put_user(diskinfo[0], &loc->heads) || put_user(diskinfo[1], &loc->sectors) || put_user(diskinfo[2], &loc->cylinders) || put_user(sd_gendisks[SD_MAJOR_IDX( inode->i_rdev)].part[MINOR( inode->i_rdev)].start_sect, &loc->start)) return -EFAULT; return 0; } case HDIO_GETGEO_BIG: { struct hd_big_geometry *loc = (struct hd_big_geometry *) arg; if(!loc) return -EINVAL; host = rscsi_disks[DEVICE_NR(dev)].device->host; /* default to most commonly used values */ diskinfo[0] = 0x40; diskinfo[1] = 0x20; diskinfo[2] = rscsi_disks[DEVICE_NR(dev)].capacity >> 11; /* override with calculated, extended default, or driver values */ if(host->hostt->bios_param != NULL) host->hostt->bios_param(&rscsi_disks[DEVICE_NR(dev)], dev, &diskinfo[0]); else scsicam_bios_param(&rscsi_disks[DEVICE_NR(dev)], dev, &diskinfo[0]); if (put_user(diskinfo[0], &loc->heads) || put_user(diskinfo[1], &loc->sectors) || put_user(diskinfo[2], (unsigned int *) &loc->cylinders) || put_user(sd_gendisks[SD_MAJOR_IDX( inode->i_rdev)].part[MINOR( inode->i_rdev)].start_sect, &loc->start)) return -EFAULT; return 0; } case BLKGETSIZE: case BLKGETSIZE64: case BLKROSET: case BLKROGET: case BLKRASET: case BLKRAGET: case BLKFLSBUF: case BLKSSZGET: case BLKPG: case BLKELVGET: case BLKELVSET: case BLKBSZGET: case BLKBSZSET: return blk_ioctl(inode->i_rdev, cmd, arg); case BLKRRPART: /* Re-read partition tables */ if (!capable(CAP_SYS_ADMIN)) return -EACCES; return revalidate_scsidisk(dev, 1); default: return scsi_ioctl(rscsi_disks[DEVICE_NR(dev)].device , cmd, (void *) arg); } }