Commit 816ab591 authored by Alexander Viro's avatar Alexander Viro Committed by Linus Torvalds

[PATCH] partition table flush/read cleanup

Big One.  Flushing/rereading partition tables is taken from
->revalidate() for partitioned devices; now it's done in the
caller (check_disk_change()).  BLKRRPART handling also moved
out of drivers - they are still allowed to override it (DAC960
and i2o are the only remaining ones), but common case is handled
in fs/block_dev.c.

Note: we are still only shifting stuff - bd_sem deadlocks in
check_disk_change() are still there.  However, now we have all
relevant code outside of drivers and that will allow to fix the
thing (see next patches).
parent fc4dfb65
......@@ -226,7 +226,6 @@ static char *Copy_buffer;
static void mfm_seek(void);
static void mfm_rerequest(void);
static void mfm_request(void);
static int mfm_reread_partitions(kdev_t dev);
static void mfm_specify (void);
static void issue_request(int dev, unsigned int block, unsigned int nsect,
struct request *req);
......@@ -1165,20 +1164,19 @@ static int mfm_ioctl(struct inode *inode, struct file *file, u_int cmd, u_long a
{
struct hd_geometry *geo = (struct hd_geometry *) arg;
kdev_t dev;
int device, major, minor, err;
int device, minor, err;
if (!inode || !(dev = inode->i_rdev))
return -EINVAL;
major = major(dev);
minor = minor(dev);
device = DEVICE_NR(minor(inode->i_rdev)), err;
if (device >= mfm_drives)
return -EINVAL;
switch (cmd) {
case HDIO_GETGEO:
if (cmd != HDIO_GETGEO)
return -EINVAL;
if (!arg)
return -EINVAL;
if (put_user (mfm_info[device].heads, &geo->heads))
......@@ -1190,15 +1188,6 @@ static int mfm_ioctl(struct inode *inode, struct file *file, u_int cmd, u_long a
if (put_user (mfm[minor].start_sect, &geo->start))
return -EFAULT;
return 0;
case BLKRRPART:
if (!capable(CAP_SYS_ADMIN))
return -EACCES;
return mfm_reread_partitions(dev);
default:
return -EINVAL;
}
}
static int mfm_open(struct inode *inode, struct file *file)
......@@ -1396,25 +1385,6 @@ int mfm_init (void)
return 0;
}
/*
* This routine is called to flush all partitions and partition tables
* for a changed MFM disk, and then re-read the new partition table.
*/
static int mfm_reread_partitions(kdev_t dev)
{
unsigned int unit = DEVICE_NR(minor(dev));
kdev_t device = mk_kdev(MAJOR_NR, unit << mfm_gendisk.minor_shift);
int err = dev_lock_part(device);
if (err)
return err;
wipe_partitions(device);
/* Divide by 2, since sectors are 2 times smaller than usual ;-) */
grok_partitions(device, mfm_info[unit].heads *
mfm_info[unit].cylinders * mfm_info[unit].sectors / 2);
dev_unlock_part(device);
return 0;
}
#ifdef MODULE
MODULE_LICENSE("GPL");
......
......@@ -369,7 +369,6 @@ static void acsi_prevent_removal( int target, int flag );
static int acsi_change_blk_size( int target, int lun);
static int acsi_mode_sense( int target, int lun, SENSE_DATA *sd );
static void acsi_geninit(void);
static int revalidate_acsidisk( kdev_t dev, int maxusage );
static int acsi_revalidate (kdev_t);
/************************* End of Prototypes **************************/
......@@ -1108,19 +1107,12 @@ static int acsi_ioctl( struct inode *inode, struct file *file,
put_user(get_start_sect(inode->i_bdev), &geo->start);
return 0;
}
case SCSI_IOCTL_GET_IDLUN:
/* SCSI compatible GET_IDLUN call to get target's ID and LUN number */
put_user( acsi_info[dev].target | (acsi_info[dev].lun << 8),
&((Scsi_Idlun *) arg)->dev_id );
put_user( 0, &((Scsi_Idlun *) arg)->host_unique_id );
return 0;
case BLKRRPART: /* Re-read partition tables */
if (!capable(CAP_SYS_ADMIN))
return -EACCES;
return revalidate_acsidisk(inode->i_rdev, 1);
default:
return -EINVAL;
}
......@@ -1809,20 +1801,11 @@ void cleanup_module(void)
*
*/
static int revalidate_acsidisk(kdev_t dev, int maxusage )
static int acsi_revalidate(kdev_t dev)
{
int unit = DEVICE_NR(minor(dev));
struct acsi_info_struct *aip = &acsi_info[unit];
kdev_t device = mk_kdev(MAJOR_NR, unit<<4);
int res = dev_lock_part(device);
if (res < 0)
return res;
res = wipe_partitions(device);
stdma_lock( NULL, NULL );
if (acsi_devinit(aip) != DEV_SUPPORTED) {
printk( KERN_ERR "ACSI: revalidate failed for target %d lun %d\n",
aip->target, aip->lun);
......@@ -1834,16 +1817,6 @@ static int revalidate_acsidisk(kdev_t dev, int maxusage )
ENABLE_IRQ();
stdma_release();
if (!res)
grok_partitions(device, aip->size);
dev_unlock_part(device);
return res;
}
static int acsi_revalidate (kdev_t dev)
{
return revalidate_acsidisk (dev, 0);
acsi_part[minor(dev)].nr_sects = aip->size;
return 0;
}
......@@ -269,12 +269,6 @@ int blk_ioctl(struct block_device *bdev, unsigned int cmd, unsigned long arg)
/* size in bytes */
ullval = bdev->bd_inode->i_size;
return put_user(ullval, (u64 *) arg);
#if 0
case BLKRRPART: /* Re-read partition tables */
if (!capable(CAP_SYS_ADMIN))
return -EACCES;
return reread_partitions(dev, 1);
#endif
case BLKPG:
return blkpg_ioctl(bdev, (struct blkpg_ioctl_arg *) arg);
......
......@@ -106,7 +106,7 @@ static int cciss_ioctl(struct inode *inode, struct file *filep,
static int revalidate_allvol(kdev_t dev);
static int revalidate_logvol(kdev_t dev, int maxusage);
static int frevalidate_logvol(kdev_t dev);
static int cciss_revalidate(kdev_t dev);
static int deregister_disk(int ctlr, int logvol);
static int register_new_disk(kdev_t dev, int cltr);
......@@ -130,7 +130,7 @@ static struct block_device_operations cciss_fops = {
open: cciss_open,
release: cciss_release,
ioctl: cciss_ioctl,
revalidate: frevalidate_logvol,
revalidate: cciss_revalidate,
};
#include "cciss_scsi.c" /* For SCSI tape support */
......@@ -437,8 +437,6 @@ static int cciss_ioctl(struct inode *inode, struct file *filep,
return(0);
}
case BLKRRPART:
return revalidate_logvol(inode->i_rdev, 1);
case CCISS_GETPCIINFO:
{
cciss_pci_info_struct pciinfo;
......@@ -724,6 +722,15 @@ static int cciss_ioctl(struct inode *inode, struct file *filep,
}
static int cciss_revalidate(kdev_t dev)
{
int ctlr = major(dev) - MAJOR_NR;
int target = minor(dev) >> NWD_SHIFT;
struct gendisk *gdev = &(hba[ctlr]->gendisk);
gdev->part[minor(dev)].nr_sects = hba[ctlr]->drv[target].nr_blocks;
return 0;
}
/* Borrowed and adapted from sd.c */
/*
* FIXME: we are missing the exclusion with ->open() here - it can happen
......@@ -762,14 +769,6 @@ static int revalidate_logvol(kdev_t dev, int maxusage)
return res;
}
static int frevalidate_logvol(kdev_t dev)
{
#ifdef CCISS_DEBUG
printk(KERN_DEBUG "cciss: frevalidate has been called\n");
#endif /* CCISS_DEBUG */
return revalidate_logvol(dev, 0);
}
/*
* revalidate_allvol is for online array config utilities. After a
* utility reconfigures the drives in the array, it can use this function
......
......@@ -153,7 +153,7 @@ static inline void complete_command(cmdlist_t *cmd, int timeout);
static void do_ida_intr(int irq, void *dev_id, struct pt_regs * regs);
static void ida_timer(unsigned long tdata);
static int frevalidate_logvol(kdev_t dev);
static int ida_revalidate(kdev_t dev);
static int revalidate_logvol(kdev_t dev, int maxusage);
static int revalidate_allvol(kdev_t dev);
......@@ -188,7 +188,7 @@ static struct block_device_operations ida_fops = {
open: ida_open,
release: ida_release,
ioctl: ida_ioctl,
revalidate: frevalidate_logvol,
revalidate: ida_revalidate,
};
......@@ -1107,8 +1107,6 @@ static int ida_ioctl(struct inode *inode, struct file *filep, unsigned int cmd,
sizeof(drv_info_t)))
return -EFAULT;
return 0;
case BLKRRPART:
return revalidate_logvol(inode->i_rdev, 1);
case IDAPASSTHRU:
if (!capable(CAP_SYS_RAWIO)) return -EPERM;
if (copy_from_user(&my_io, io, sizeof(my_io)))
......@@ -1441,11 +1439,6 @@ DBG(
return (IO_OK);
}
static int frevalidate_logvol(kdev_t dev)
{
return revalidate_logvol(dev, 0);
}
/*
* revalidate_allvol is for online array config utilities. After a
* utility reconfigures the drives in the array, it can use this function
......@@ -1505,6 +1498,15 @@ static int revalidate_allvol(kdev_t dev)
return 0;
}
static int ida_revalidate(kdev_t dev)
{
int ctlr = major(dev) - MAJOR_NR;
int target = DEVICE_NR(dev);
struct gendisk *gdev = &ida_gendisk[ctlr];
gdev->part[minor(dev)].nr_sects = hba[ctlr]->drv[target].nr_blocks;
return 0;
}
/* Borrowed and adapted from sd.c */
/*
* FIXME: exclusion with ->open()
......
......@@ -404,10 +404,6 @@ static int pd_ioctl(struct inode *inode,struct file *file,
}
put_user(get_start_sect(inode->i_bdev), (long *)&geo->start);
return 0;
case BLKRRPART:
if (!capable(CAP_SYS_ADMIN))
return -EACCES;
return pd_revalidate(inode->i_rdev);
default:
return -EINVAL;
}
......@@ -439,23 +435,13 @@ static int pd_check_media( kdev_t dev)
static int pd_revalidate(kdev_t dev)
{
int unit = DEVICE_NR(dev);
kdev_t device = mk_kdev(MAJOR_NR, unit << PD_BITS);
int res;
if ((unit >= PD_UNITS) || !PD.present)
return -ENODEV;
res = dev_lock_part(device);
if (res < 0)
return res;
res = wipe_partitions(device);
if (res == 0 && pd_identify(unit))
grok_partitions(device, PD.capacity);
dev_unlock_part(device);
return res;
if (pd_identify(unit))
pd_hd[minor(dev)].nr_sects = PD.capacity;
else
pd_hd[minor(dev)].nr_sects = 0;
return 0;
}
#define WR(c,r,v) pi_write_regr(PI,c,r,v)
......
......@@ -95,8 +95,6 @@ static int ps2esdi_open(struct inode *inode, struct file *file);
static int ps2esdi_ioctl(struct inode *inode, struct file *file,
u_int cmd, u_long arg);
static int ps2esdi_reread_partitions(kdev_t dev);
static int ps2esdi_read_status_words(int num_words, int max_words, u_short * buffer);
static void dump_cmd_complete_status(u_int int_ret_code);
......@@ -1080,53 +1078,18 @@ static int ps2esdi_open(struct inode *inode, struct file *file)
static int ps2esdi_ioctl(struct inode *inode,
struct file *file, u_int cmd, u_long arg)
{
struct ps2esdi_geometry *geometry = (struct ps2esdi_geometry *) arg;
int dev = DEVICE_NR(inode->i_rdev), err;
if (inode && (dev < ps2esdi_drives))
switch (cmd) {
case HDIO_GETGEO:
if (arg) {
if (cmd != HDIO_GETGEO)
return -EINVAL;
if ((err = verify_area(VERIFY_WRITE, geometry, sizeof(*geometry))))
return (err);
put_user(ps2esdi_info[dev].head, (char *) &geometry->heads);
put_user(ps2esdi_info[dev].sect, (char *) &geometry->sectors);
put_user(ps2esdi_info[dev].cyl, (short *) &geometry->cylinders);
put_user(get_start_sect(inode->b_rdev),
(long *) &geometry->start);
put_user(get_start_sect(inode->b_rdev), (long *) &geometry->start);
return 0;
}
break;
case BLKRRPART:
if (!capable(CAP_SYS_ADMIN))
return -EACCES;
return (ps2esdi_reread_partitions(inode->i_rdev));
}
return (-EINVAL);
}
static int ps2esdi_reread_partitions(kdev_t dev)
{
int target = DEVICE_NR(dev);
kdev_t device = mk_kdev(MAJOR_NR, target << 6);
int res = dev_lock_part(device);
if (res < 0)
return res;
res = wipe_partitions(device);
if (res == 0)
grok_partitions(device, ps2esdi_info[target].head
* ps2esdi_info[target].cyl
* ps2esdi_info[target].sect);
dev_unlock_part(device);
return res;
}
static void ps2esdi_reset_timer(unsigned long unused)
......
......@@ -818,14 +818,7 @@ static void del_battery_timer(void)
static int mm_revalidate(kdev_t i_rdev)
{
int card_number = DEVICE_NR(i_rdev);
kdev_t device = mk_kdev(MAJOR_NR, card_number << MM_SHIFT);
int res = dev_lock_part(device);
if (res < 0)
return res;
wipe_partitions(device);
printk(KERN_INFO "mm partition check: (%d)\n", card_number);
grok_partitions(device, cards[card_number].mm_size << 1);
dev_unlock_part(device);
mm_partitions[minor(i_rdev)] = cards[card_number].mm_size << 1;
return 0;
}
/*
......@@ -835,22 +828,10 @@ static int mm_revalidate(kdev_t i_rdev)
*/
static int mm_ioctl(struct inode *i, struct file *f, unsigned int cmd, unsigned long arg)
{
int err, size, card_number;
if (cmd == case HDIO_GETGEO) {
unsigned int minor = minor(i->i_rdev);
int err, size, card_number = (minor >> MM_SHIFT);
struct hd_geometry geo;
unsigned int minor;
if (!i)
return -EINVAL;
minor = minor(i->i_rdev);
card_number = (minor >> MM_SHIFT);
switch(cmd) {
case BLKRRPART:
return (mm_revalidate(i->i_rdev));
case HDIO_GETGEO:
/*
* get geometry: we have to fake one... trim the size to a
* multiple of 2048 (1M): tell we have 32 sectors, 64 heads,
......@@ -867,12 +848,9 @@ static int mm_ioctl(struct inode *i, struct file *f, unsigned int cmd, unsigned
if (copy_to_user((void *) arg, &geo, sizeof(geo)))
return -EFAULT;
return 0;
default:
return -EINVAL;
}
return -ENOTTY; /* unknown command */
return -EINVAL;
}
/*
-----------------------------------------------------------------------------------
......
......@@ -330,37 +330,11 @@ static int xd_ioctl (struct inode *inode,struct file *file,u_int cmd,u_long arg)
return put_user(!nodma, (long *) arg);
case HDIO_GET_MULTCOUNT:
return put_user(xd_maxsectors, (long *) arg);
case BLKRRPART:
if (!capable(CAP_SYS_ADMIN))
return -EACCES;
return xd_reread_partitions(inode->i_rdev);
default:
return -EINVAL;
}
}
/* xd_reread_partitions: rereads the partition table from a drive */
static int xd_reread_partitions(kdev_t dev)
{
int target = DEVICE_NR(dev);
kdev_t device = mk_kdev(MAJOR_NR, target << 6);
int res = dev_lock_part(device);
if (res < 0)
return 0;
res = wipe_partitions(device);
if (!res)
grok_partitions(device, xd_info[target].heads
* xd_info[target].cylinders
* xd_info[target].sectors);
dev_unlock_part(device);
return res;
}
/* xd_readwrite: handle a read/write request */
static int xd_readwrite (u_char operation,u_char drive,char *buffer,u_int block,u_int count)
{
......
......@@ -113,7 +113,6 @@ static void xd_geninit (void);
static int xd_open (struct inode *inode,struct file *file);
static void do_xd_request (request_queue_t * q);
static int xd_ioctl (struct inode *inode,struct file *file,unsigned int cmd,unsigned long arg);
static int xd_reread_partitions (kdev_t dev);
static int xd_readwrite (u_char operation,u_char drive,char *buffer,u_int block,u_int count);
static void xd_recalibrate (u_char drive);
......
......@@ -108,8 +108,6 @@
static spinlock_t hd_lock = SPIN_LOCK_UNLOCKED;
static int revalidate_hddisk(kdev_t, int);
#define TIMEOUT_VALUE (6*HZ)
#define HD_DELAY 0
......@@ -683,11 +681,6 @@ static int hd_ioctl(struct inode * inode, struct file * file,
return copy_to_user(loc, &g, sizeof g) ? -EFAULT : 0;
}
case BLKRRPART: /* Re-read partition tables */
if (!capable(CAP_SYS_ADMIN))
return -EACCES;
return revalidate_hddisk(inode->i_rdev, 1);
default:
return -EINVAL;
}
......@@ -879,32 +872,6 @@ int __init hd_init(void)
return 0;
}
#define CAPACITY (hd_info[target].head*hd_info[target].sect*hd_info[target].cyl)
/* We assume that the BIOS parameters do not change, so the disk capacity
will not change */
/*
* This routine is called to flush all partitions and partition tables
* for a changed disk, and then re-read the new partition table.
* If we are revalidating a disk because of a media change, then we
* enter with usage == 0. If we are using an ioctl, we automatically have
* usage == 1 (we need an open channel to use an ioctl :-), so this
* is our limit.
*/
static int revalidate_hddisk(kdev_t dev, int maxusage)
{
int target = DEVICE_NR(dev);
kdev_t device = mk_kdev(MAJOR_NR, target << 6);
int res = dev_lock_part(device);
if (res < 0)
return res;
res = wipe_partitions(device);
if (!res)
grok_partitions(device, CAPACITY);
dev_unlock_part(device);
return res;
}
static int parse_hd_setup (char *line) {
int ints[6];
......
......@@ -2875,19 +2875,8 @@ int ide_cdrom_check_media_change(struct ata_device *drive)
static
void ide_cdrom_revalidate(struct ata_device *drive)
{
struct cdrom_info *info = drive->driver_data;
struct atapi_toc *toc;
struct request_sense sense;
cdrom_read_toc(drive, &sense);
if (!CDROM_STATE_FLAGS(drive)->toc_valid)
return;
toc = info->toc;
/* for general /dev/cdrom like mounting, one big disc */
drive->part[0].nr_sects = toc->capacity * SECTORS_PER_FRAME;
}
static sector_t ide_cdrom_capacity(struct ata_device *drive)
......
......@@ -5537,13 +5537,6 @@ static int idetape_cleanup(struct ata_device *drive)
return 0;
}
static void idetape_revalidate(struct ata_device *_dummy)
{
/* We don't have to handle any partition information here, which is the
* default behaviour of this method.
*/
}
static void idetape_attach(struct ata_device *);
static struct ata_operations idetape_driver = {
......@@ -5556,8 +5549,6 @@ static struct ata_operations idetape_driver = {
.ioctl = idetape_blkdev_ioctl,
.open = idetape_blkdev_open,
.release = idetape_blkdev_release,
.check_media_change = NULL,
.revalidate = idetape_revalidate,
};
......
......@@ -1106,7 +1106,7 @@ struct block_device_operations ide_fops[] = {{
.release = ide_release,
.ioctl = ata_ioctl,
.check_media_change = ide_check_media_change,
.revalidate = ata_revalidate
.revalidate = ide_revalidate
}};
EXPORT_SYMBOL(ide_fops);
......
......@@ -349,9 +349,6 @@ int ata_ioctl(struct inode *inode, struct file *file, unsigned int cmd, unsigned
case CDROMCLOSETRAY:
return block_ioctl(inode->i_bdev, cmd, arg);
case BLKRRPART: /* Re-read partition tables */
return ata_revalidate(inode->i_rdev);
/* Now check whatever this particular ioctl has a device type
* specific implementation.
*/
......
......@@ -260,40 +260,25 @@ struct ata_device *get_info_ptr(kdev_t i_rdev)
* usage == 1 (we need an open channel to use an ioctl :-), so this
* is our limit.
*/
int ata_revalidate(kdev_t i_rdev)
int ide_revalidate(kdev_t dev)
{
kdev_t device = mk_kdev(major(i_rdev), minor(i_rdev) & ~PARTN_MASK);
struct ata_device *drive;
int res;
struct ata_channel *channel;
struct gendisk *disk;
int unit;
if ((drive = get_info_ptr(device)) == NULL)
if ((drive = get_info_ptr(dev)) == NULL)
return -ENODEV;
MOD_INC_USE_COUNT;
res = dev_lock_part(device);
if (res < 0) {
MOD_DEC_USE_COUNT;
return res;
}
res = wipe_partitions(device);
if (!res) {
if (ata_ops(drive) && ata_ops(drive)->revalidate) {
ata_get(ata_ops(drive));
/* This is expected to be a no-op for tapes and SCSI
* based access.
*/
ata_ops(drive)->revalidate(drive);
ata_put(ata_ops(drive));
} else
grok_partitions(device, ata_capacity(drive));
}
dev_unlock_part(device);
MOD_DEC_USE_COUNT;
return res;
channel = drive->channel;
unit = drive - channel->drives;
disk = channel->gd[unit];
disk->part[0].nr_sects = ata_capacity(drive);
return 0;
}
void ide_driver_module(void)
......@@ -1139,8 +1124,6 @@ void unregister_ata_driver(struct ata_operations *driver)
}
}
EXPORT_SYMBOL(unregister_ata_driver);
EXPORT_SYMBOL(ide_hwifs);
EXPORT_SYMBOL(ide_lock);
......
......@@ -184,6 +184,7 @@ static int ftl_ioctl(struct inode *inode, struct file *file,
static int ftl_open(struct inode *inode, struct file *file);
static release_t ftl_close(struct inode *inode, struct file *file);
static int ftl_reread_partitions(kdev_t dev);
static int ftl_revalidate(kdev_t dev);
static void ftl_erase_callback(struct erase_info *done);
......@@ -192,6 +193,7 @@ static struct block_device_operations ftl_blk_fops = {
open: ftl_open,
release: ftl_close,
ioctl: ftl_ioctl,
revalidate: ftl_revalidate,
};
/*======================================================================
......@@ -1106,8 +1108,8 @@ static int ftl_ioctl(struct inode *inode, struct file *file,
if (!part)
return -ENODEV; /* How? */
switch (cmd) {
case HDIO_GETGEO:
if (cmd != HDIO_GETGEO)
return -EINVAL;
ret = verify_area(VERIFY_WRITE, (long *)arg, sizeof(*geo));
if (ret) return ret;
/* Sort of arbitrary: round size down to 4K boundary */
......@@ -1116,15 +1118,7 @@ static int ftl_ioctl(struct inode *inode, struct file *file,
put_user(8, (char *)&geo->sectors);
put_user((sect>>3), (short *)&geo->cylinders);
put_user(get_start_sect(inode->i_bdev), (u_long *)&geo->start);
break;
case BLKRRPART:
ret = ftl_reread_partitions(inode->i_rdev);
break;
default:
ret = -EINVAL;
}
return ret;
return 0;
} /* ftl_ioctl */
/*======================================================================
......@@ -1133,22 +1127,14 @@ static int ftl_ioctl(struct inode *inode, struct file *file,
======================================================================*/
static int ftl_reread_partitions(kdev_t dev)
static int ftl_revalidate(kdev_t dev)
{
int minor = minor(dev);
partition_t *part = myparts[minor >> 4];
kdev_t device = mk_kdev(MAJOR_NR, minor & ~15);
int res = dev_lock_part(device);
if (rec < 0)
return res;
res = wipe_partitions(device);
if (!res) {
int unit = minor(dev) >> 4;
partition_t *part = myparts[unit];
scan_header(part);
grok_partitions(device,
part->disk->part[0].nr_sects =
le32_to_cpu(part->header.FormattedSize)/SECTOR_SIZE);
}
dev_unlock_part(device);
return res;
return 0;
}
/*======================================================================
......
......@@ -799,21 +799,6 @@ static int nftl_ioctl(struct inode * inode, struct file * file, unsigned int cmd
if (nftl->mtd->sync)
nftl->mtd->sync(nftl->mtd);
return 0;
case BLKRRPART:
if (!capable(CAP_SYS_ADMIN)) return -EACCES;
{
kdev_t device = mk_kdev(MAJOR_NR,
minor(inode->i_rdev) & -(1<<NFTL_PARTN_BITS));
res = dev_lock_part(device);
if (res < 0)
return res;
res = wipe_partitions(device);
if (!res)
grok_partitions(device, nftl->nr_sects);
dev_unlock_part(device);
}
return res;
default:
return -EINVAL;
}
......
......@@ -447,31 +447,6 @@ static int dasd_ioctl_set_ro(void *inp, int no, long args)
return 0;
}
/*
* Reread partition table.
*/
static int dasd_ioctl_rr_partition(void *inp, int no, long args)
{
dasd_devmap_t *devmap;
dasd_device_t *device;
if (!capable(CAP_SYS_ADMIN))
return -EACCES;
devmap = dasd_devmap_from_kdev(((struct inode *) inp)->i_rdev);
device = (devmap != NULL) ?
dasd_get_device(devmap) : ERR_PTR(-ENODEV);
if (IS_ERR(device))
return PTR_ERR(device);
if (atomic_read(&device->open_count) != 1)
DEV_MESSAGE(KERN_WARNING, device, "%s",
"BLKRRPART: device is open! expect errors.");
dasd_destroy_partitions(device);
dasd_setup_partitions(device);
dasd_put_device(devmap);
return 0;
}
/*
* Return disk geometry.
*/
......@@ -516,7 +491,6 @@ static struct { int no; dasd_ioctl_fn_t fn; } dasd_ioctls[] =
{ BIODASDPRRD, dasd_ioctl_read_profile },
{ BIODASDPRRST, dasd_ioctl_reset_profile },
{ BLKROSET, dasd_ioctl_set_ro },
{ BLKRRPART, dasd_ioctl_rr_partition },
{ DASDAPIVER, dasd_ioctl_api_version },
{ HDIO_GETGEO, dasd_ioctl_getgeo },
{ -1, NULL }
......
......@@ -334,18 +334,11 @@ static int xpram_ioctl (struct inode *inode, struct file *filp,
{
struct hd_geometry *geo;
unsigned long size;
int idx;
if ((!inode) || kdev_none(inode->i_rdev))
return -EINVAL;
idx = minor(inode->i_rdev);
int idx = minor(inode->i_rdev);
if (idx >= xpram_devs)
return -ENODEV;
switch (cmd) {
case BLKRRPART:
/* re-read partition table: can't do it */
if (cmd != HDIO_GETGEO)
return -EINVAL;
case HDIO_GETGEO:
/*
* get geometry: we have to fake one... trim the size to a
* multiple of 64 (32k): tell we have 16 sectors, 4 heads,
......@@ -360,9 +353,7 @@ static int xpram_ioctl (struct inode *inode, struct file *filp,
put_user(16, &geo->sectors);
put_user(4, &geo->start);
return 0;
default:
return -EINVAL;
}
}
}
static struct block_device_operations xpram_devops =
......
......@@ -91,7 +91,7 @@ static Scsi_Disk ** sd_dsk_arr;
static rwlock_t sd_dsk_arr_lock = RW_LOCK_UNLOCKED;
static int check_scsidisk_media_change(kdev_t);
static int fop_revalidate_scsidisk(kdev_t);
static int sd_revalidate(kdev_t);
static void sd_init_onedisk(Scsi_Disk * sdkp, int dsk_nr);
......@@ -243,12 +243,6 @@ static int sd_ioctl(struct inode * inode, struct file * filp,
return -EFAULT;
return 0;
}
case BLKRRPART: /* Re-read partition tables */
if (!capable(CAP_SYS_ADMIN))
return -EACCES;
return revalidate_scsidisk(dev, 1);
default:
return scsi_ioctl(sdp, cmd, (void *) arg);
}
......@@ -600,7 +594,7 @@ static struct block_device_operations sd_fops =
release: sd_release,
ioctl: sd_ioctl,
check_media_change: check_scsidisk_media_change,
revalidate: fop_revalidate_scsidisk
revalidate: sd_revalidate
};
static struct gendisk **sd_disks;
......@@ -1387,50 +1381,17 @@ static int sd_attach(Scsi_Device * sdp)
return 0;
}
/**
* revalidate_scsidisk - called to flush all partitions and partition
* tables for a changed scsi disk. sd_init_onedisk() is then called
* followed by re-reading the new partition table.
* @dev: kernel device descriptor (kdev_t)
* @maxusage: 0 when called from block level, 1 when called from
* sd_ioctl().
*
* Returns 0 if successful; negated errno value otherwise.
*/
int revalidate_scsidisk(kdev_t dev, int maxusage)
static int sd_revalidate(kdev_t dev)
{
int dsk_nr = DEVICE_NR(dev);
Scsi_Disk * sdkp;
Scsi_Device * sdp;
kdev_t device = mk_kdev(major(dev), minor(dev) & ~15);
int res;
Scsi_Disk * sdkp = sd_get_sdisk(dsk_nr);
SCSI_LOG_HLQUEUE(3, printk("revalidate_scsidisk: dsk_nr=%d\n",
DEVICE_NR(dev)));
sdkp = sd_get_sdisk(dsk_nr);
if ((NULL == sdkp) || (NULL == (sdp = sdkp->device)))
if (!sdkp || !sdkp->device)
return -ENODEV;
res = dev_lock_part(device);
if (res < 0)
return res;
res = wipe_partitions(device);
if (res)
goto leave;
sd_init_onedisk(sdkp, dsk_nr);
grok_partitions(device, sdkp->capacity);
leave:
dev_unlock_part(device);
return res;
}
static int fop_revalidate_scsidisk(kdev_t dev)
{
return revalidate_scsidisk(dev, 0);
sd_disks[dsk_nr]->part[0].nr_sects = sdkp->capacity;
return 0;
}
/**
......
......@@ -502,6 +502,8 @@ int check_disk_change(struct block_device *bdev)
{
struct block_device_operations * bdops = bdev->bd_op;
kdev_t dev = to_kdev_t(bdev->bd_dev);
struct gendisk *disk;
struct hd_struct *part;
if (bdops->check_media_change == NULL)
return 0;
......@@ -514,8 +516,23 @@ int check_disk_change(struct block_device *bdev)
if (invalidate_device(dev, 0))
printk("VFS: busy inodes on changed media.\n");
disk = get_gendisk(dev);
part = disk->part + minor(dev) - disk->first_minor;
if (disk && disk->minor_shift) {
if (!down_trylock(&bdev->bd_part_sem)) {
if (!bdev->bd_part_count) {
if (wipe_partitions(dev) == 0) {
if (bdops->revalidate)
bdops->revalidate(dev);
grok_partitions(dev, part[0].nr_sects);
}
}
up(&bdev->bd_part_sem);
}
} else {
if (bdops->revalidate)
bdops->revalidate(dev);
}
return 1;
}
......@@ -734,9 +751,38 @@ int blkdev_close(struct inode * inode, struct file * filp)
return blkdev_put(inode->i_bdev, BDEV_FILE);
}
static int blkdev_reread_part(struct block_device *bdev)
{
kdev_t dev = to_kdev_t(bdev->bd_dev);
struct gendisk *disk = get_gendisk(dev);
struct hd_struct *part;
int res;
if (!disk)
return -EINVAL;
part = disk->part + minor(dev) - disk->first_minor;
if (!capable(CAP_SYS_ADMIN))
return -EACCES;
if (down_trylock(&bdev->bd_part_sem));
return -EBUSY;
if (bdev->bd_part_count) {
up(&bdev->bd_part_sem);
return -EBUSY;
}
res = wipe_partitions(dev);
if (!res) {
if (bdev->bd_op->revalidate)
bdev->bd_op->revalidate(dev);
grok_partitions(dev, part[0].nr_sects);
}
up(&bdev->bd_part_sem);
return res;
}
static int blkdev_ioctl(struct inode *inode, struct file *file, unsigned cmd,
unsigned long arg)
{
struct block_device *bdev = inode->i_bdev;
int ret = -EINVAL;
switch (cmd) {
/*
......@@ -756,21 +802,23 @@ static int blkdev_ioctl(struct inode *inode, struct file *file, unsigned cmd,
case BLKFRASET:
case BLKBSZSET:
case BLKPG:
ret = blk_ioctl(inode->i_bdev, cmd, arg);
ret = blk_ioctl(bdev, cmd, arg);
break;
default:
if (inode->i_bdev->bd_op->ioctl)
ret =inode->i_bdev->bd_op->ioctl(inode, file, cmd, arg);
if (bdev->bd_op->ioctl)
ret =bdev->bd_op->ioctl(inode, file, cmd, arg);
if (ret == -EINVAL) {
switch (cmd) {
case BLKGETSIZE:
case BLKGETSIZE64:
case BLKFLSBUF:
case BLKROSET:
ret = blk_ioctl(inode->i_bdev,cmd,arg);
ret = blk_ioctl(bdev,cmd,arg);
break;
case BLKRRPART:
ret = blkdev_reread_part(bdev);
}
}
break;
}
return ret;
}
......
......@@ -2377,23 +2377,20 @@ static int check_disc_changed (struct devfs_entry *de)
int tmp;
int retval = 0;
kdev_t dev = mk_kdev (de->u.fcb.u.device.major, de->u.fcb.u.device.minor);
struct block_device *bdev;
struct block_device_operations *bdops;
extern int warn_no_part;
if ( !S_ISBLK (de->mode) ) return 0;
bdev = bdget(kdev_t_to_nr(dev));
if (!bdev) return 0;
bdops = devfs_get_ops (de);
if (!bdops) return 0;
if (bdops->check_media_change == NULL) goto out;
if ( !bdops->check_media_change (dev) ) goto out;
retval = 1;
printk (KERN_DEBUG "VFS: Disk change detected on device %s\n",
kdevname (dev) );
if ( invalidate_device (dev, 0) )
printk (KERN_WARNING "VFS: busy inodes on changed media..\n");
bdev->bd_op = bdops;
/* Ugly hack to disable messages about unable to read partition table */
tmp = warn_no_part;
warn_no_part = 0;
if (bdops->revalidate) bdops->revalidate (dev);
retval = check_disk_change(bdev);
warn_no_part = tmp;
out:
devfs_put_ops (de);
......
......@@ -1307,31 +1307,5 @@ static inline ino_t parent_ino(struct dentry *dentry)
return res;
}
/* NOTE NOTE NOTE: this interface _will_ change in a couple of patches */
static inline int dev_lock_part(kdev_t dev)
{
struct block_device *bdev = bdget(kdev_t_to_nr(dev));
if (!bdev)
return -ENOMEM;
if (!down_trylock(&bdev->bd_part_sem)) {
if (!bdev->bd_part_count)
return 0;
up(&bdev->bd_part_sem);
}
bdput(bdev);
return -EBUSY;
}
static inline void dev_unlock_part(kdev_t dev)
{
struct block_device *bdev = bdget(kdev_t_to_nr(dev));
if (!bdev)
BUG();
up(&bdev->bd_part_sem);
bdput(bdev);
bdput(bdev);
}
#endif /* __KERNEL__ */
#endif /* _LINUX_FS_H */
......@@ -1161,7 +1161,7 @@ extern int idescsi_init(void);
extern int ata_register_device(struct ata_device *, struct ata_operations *);
extern int ata_unregister_device(struct ata_device *drive);
extern int ata_revalidate(kdev_t i_rdev);
extern int ide_revalidate(kdev_t i_rdev);
extern void ide_driver_module(void);
#ifdef CONFIG_PCI
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment