Commit 91b58109 authored by Alexander Viro's avatar Alexander Viro Committed by Linus Torvalds

[PATCH] invalidate_device()/check_disk_change() fixes

	* bogus calls of invalidate_buffers() gone from floppy_open()
	* invalidate_buffers() killed.

	* new helper - __invalidate_device(bdev, do_sync).  invalidate_device()
is calling it.

	* fixed races between floppy_open()/floppy_open and
floppy_open()/set_geometry():
	a) floppy_open()/floppy_release() is done under a semaphore.  That
closes the races between simultaneous open() on /dev/fd0foo and /dev/fd0bar.
	b) pointer to struct block_device is kept as long as floppy is
opened (per-drive, non-NULL when number of openers is non-zero, does not
contribute to block_device refcount).
	c) set_geometry() grabs the same semaphore and invalidates the
devices directly instead of messing with setting fake "it had changed"
and calling __check_disk_change().

	* __check_disk_change() killed - no remaining callers
	* full_check_disk_change() killed - ditto.
parent 45065e10
...@@ -1474,9 +1474,6 @@ static int floppy_open(struct inode *inode, struct file *filp) ...@@ -1474,9 +1474,6 @@ static int floppy_open(struct inode *inode, struct file *filp)
fd_device[drive] = type; fd_device[drive] = type;
if (old_dev && old_dev != type)
invalidate_buffers(mk_kdev(MAJOR_NR, drive + (old_dev<<2)));
if (filp->f_flags & O_NDELAY) if (filp->f_flags & O_NDELAY)
return 0; return 0;
......
...@@ -1496,7 +1496,7 @@ static int fd_ioctl(struct inode *inode, struct file *filp, ...@@ -1496,7 +1496,7 @@ static int fd_ioctl(struct inode *inode, struct file *filp,
break; break;
case FDFMTEND: case FDFMTEND:
floppy_off(drive); floppy_off(drive);
invalidate_device(inode->i_rdev, 0); invalidate_bdev(inode->i_bdev, 0);
break; break;
case FDGETPRM: case FDGETPRM:
memset((void *)&getprm, 0, sizeof (getprm)); memset((void *)&getprm, 0, sizeof (getprm));
...@@ -1604,9 +1604,6 @@ static int floppy_open(struct inode *inode, struct file *filp) ...@@ -1604,9 +1604,6 @@ static int floppy_open(struct inode *inode, struct file *filp)
#endif #endif
local_irq_restore(flags); local_irq_restore(flags);
if (old_dev != system)
invalidate_buffers(mk_kdev(FLOPPY_MAJOR, drive + (system << 2)));
unit[drive].dtype=&data_types[system]; unit[drive].dtype=&data_types[system];
unit[drive].blocks=unit[drive].type->heads*unit[drive].type->tracks* unit[drive].blocks=unit[drive].type->heads*unit[drive].type->tracks*
data_types[system].sects*unit[drive].type->sect_mult; data_types[system].sects*unit[drive].type->sect_mult;
......
...@@ -364,7 +364,7 @@ static __inline__ void set_head_settle_flag( void ); ...@@ -364,7 +364,7 @@ static __inline__ void set_head_settle_flag( void );
static __inline__ int get_head_settle_flag( void ); static __inline__ int get_head_settle_flag( void );
static void floppy_irq (int irq, void *dummy, struct pt_regs *fp); static void floppy_irq (int irq, void *dummy, struct pt_regs *fp);
static void fd_error( void ); static void fd_error( void );
static int do_format(kdev_t drive, struct atari_format_descr *desc); static int do_format(int drive, int type, struct atari_format_descr *desc);
static void do_fd_action( int drive ); static void do_fd_action( int drive );
static void fd_calibrate( void ); static void fd_calibrate( void );
static void fd_calibrate_done( int status ); static void fd_calibrate_done( int status );
...@@ -656,12 +656,11 @@ static void fd_error( void ) ...@@ -656,12 +656,11 @@ static void fd_error( void )
p += n; \ p += n; \
} while(0) } while(0)
static int do_format(kdev_t device, struct atari_format_descr *desc) static int do_format(int drive, int type, struct atari_format_descr *desc)
{ {
unsigned char *p; unsigned char *p;
int sect, nsect; int sect, nsect;
unsigned long flags; unsigned long flags;
int type, drive = minor(device) & 3;
DPRINT(("do_format( dr=%d tr=%d he=%d offs=%d )\n", DPRINT(("do_format( dr=%d tr=%d he=%d offs=%d )\n",
drive, desc->track, desc->head, desc->sect_offset )); drive, desc->track, desc->head, desc->sect_offset ));
...@@ -673,7 +672,6 @@ static int do_format(kdev_t device, struct atari_format_descr *desc) ...@@ -673,7 +672,6 @@ static int do_format(kdev_t device, struct atari_format_descr *desc)
atari_turnon_irq( IRQ_MFP_FDC ); /* should be already, just to be sure */ atari_turnon_irq( IRQ_MFP_FDC ); /* should be already, just to be sure */
local_irq_restore(flags); local_irq_restore(flags);
type = minor(device) >> 2;
if (type) { if (type) {
if (--type >= NUM_DISK_MINORS || if (--type >= NUM_DISK_MINORS ||
minor2disktype[type].drive_types > DriveType) { minor2disktype[type].drive_types > DriveType) {
...@@ -1690,7 +1688,7 @@ static int fd_ioctl(struct inode *inode, struct file *filp, ...@@ -1690,7 +1688,7 @@ static int fd_ioctl(struct inode *inode, struct file *filp,
return -EBUSY; return -EBUSY;
if (copy_from_user(&fmt_desc, (void *) param, sizeof(fmt_desc))) if (copy_from_user(&fmt_desc, (void *) param, sizeof(fmt_desc)))
return -EFAULT; return -EFAULT;
return do_format(device, &fmt_desc); return do_format(drive, type, &fmt_desc);
case FDCLRPRM: case FDCLRPRM:
UDT = NULL; UDT = NULL;
/* MSch: invalidate default_params */ /* MSch: invalidate default_params */
...@@ -1864,9 +1862,6 @@ static int floppy_open( struct inode *inode, struct file *filp ) ...@@ -1864,9 +1862,6 @@ static int floppy_open( struct inode *inode, struct file *filp )
fd_device[drive] = type; fd_device[drive] = type;
if (old_dev && old_dev != type)
invalidate_buffers(mk_kdev(FLOPPY_MAJOR, drive + (type<<2)));
if (filp->f_flags & O_NDELAY) if (filp->f_flags & O_NDELAY)
return 0; return 0;
......
...@@ -283,12 +283,6 @@ static inline void fallback_on_nodma_alloc(char **addr, size_t l) ...@@ -283,12 +283,6 @@ static inline void fallback_on_nodma_alloc(char **addr, size_t l)
static unsigned long fake_change; static unsigned long fake_change;
static int initialising=1; static int initialising=1;
static inline int TYPE(kdev_t x) {
return (minor(x)>>2) & 0x1f;
}
static inline int DRIVE(kdev_t x) {
return (minor(x)&0x03) | ((minor(x)&0x80) >> 5);
}
#define ITYPE(x) (((x)>>2) & 0x1f) #define ITYPE(x) (((x)>>2) & 0x1f)
#define TOMINOR(x) ((x & 3) | ((x & 4) << 5)) #define TOMINOR(x) ((x & 3) | ((x & 4) << 5))
#define UNIT(x) ((x) & 0x03) /* drive on fdc */ #define UNIT(x) ((x) & 0x03) /* drive on fdc */
...@@ -415,6 +409,8 @@ static struct floppy_drive_struct drive_state[N_DRIVE]; ...@@ -415,6 +409,8 @@ static struct floppy_drive_struct drive_state[N_DRIVE];
static struct floppy_write_errors write_errors[N_DRIVE]; static struct floppy_write_errors write_errors[N_DRIVE];
static struct timer_list motor_off_timer[N_DRIVE]; static struct timer_list motor_off_timer[N_DRIVE];
static struct gendisk *disks[N_DRIVE]; static struct gendisk *disks[N_DRIVE];
static struct block_device *opened_bdev[N_DRIVE];
static DECLARE_MUTEX(open_lock);
static struct floppy_raw_cmd *raw_cmd, default_raw_cmd; static struct floppy_raw_cmd *raw_cmd, default_raw_cmd;
/* /*
...@@ -3332,25 +3328,21 @@ static inline int set_geometry(unsigned int cmd, struct floppy_struct *g, ...@@ -3332,25 +3328,21 @@ static inline int set_geometry(unsigned int cmd, struct floppy_struct *g,
if (type){ if (type){
if (!capable(CAP_SYS_ADMIN)) if (!capable(CAP_SYS_ADMIN))
return -EPERM; return -EPERM;
down(&open_lock);
LOCK_FDC(drive,1); LOCK_FDC(drive,1);
for (cnt = 0; cnt < N_DRIVE; cnt++){
if (ITYPE(drive_state[cnt].fd_device) == type &&
drive_state[cnt].fd_ref)
set_bit(drive, &fake_change);
}
floppy_type[type] = *g; floppy_type[type] = *g;
floppy_type[type].name="user format"; floppy_type[type].name="user format";
for (cnt = type << 2; cnt < (type << 2) + 4; cnt++) for (cnt = type << 2; cnt < (type << 2) + 4; cnt++)
floppy_sizes[cnt]= floppy_sizes[cnt+0x80]= floppy_sizes[cnt]= floppy_sizes[cnt+0x80]=
floppy_type[type].size+1; floppy_type[type].size+1;
process_fd_request(); process_fd_request();
for (cnt = 0; cnt < N_DRIVE; cnt++){ for (cnt = 0; cnt < N_DRIVE; cnt++) {
if (ITYPE(drive_state[cnt].fd_device) == type && struct block_device *bdev = opened_bdev[cnt];
drive_state[cnt].fd_ref) if (!bdev || ITYPE(drive_state[cnt].fd_device) != type)
__check_disk_change( continue;
MKDEV(FLOPPY_MAJOR, __invalidate_device(bdev, 0);
drive_state[cnt].fd_device));
} }
up(&open_lock);
} else { } else {
LOCK_FDC(drive,1); LOCK_FDC(drive,1);
if (cmd != FDDEFPRM) if (cmd != FDDEFPRM)
...@@ -3448,8 +3440,8 @@ static int fd_ioctl(struct inode *inode, struct file *filp, unsigned int cmd, ...@@ -3448,8 +3440,8 @@ static int fd_ioctl(struct inode *inode, struct file *filp, unsigned int cmd,
#define OUT(c,x) case c: outparam = (const char *) (x); break #define OUT(c,x) case c: outparam = (const char *) (x); break
#define IN(c,x,tag) case c: *(x) = inparam. tag ; return 0 #define IN(c,x,tag) case c: *(x) = inparam. tag ; return 0
int i,drive,type; int drive = (long)inode->i_bdev->bd_disk->private_data;
kdev_t device; int i, type = ITYPE(UDRS->fd_device);
int ret; int ret;
int size; int size;
union inparam { union inparam {
...@@ -3460,9 +3452,6 @@ static int fd_ioctl(struct inode *inode, struct file *filp, unsigned int cmd, ...@@ -3460,9 +3452,6 @@ static int fd_ioctl(struct inode *inode, struct file *filp, unsigned int cmd,
} inparam; /* parameters coming from user space */ } inparam; /* parameters coming from user space */
const char *outparam; /* parameters passed back to user space */ const char *outparam; /* parameters passed back to user space */
device = inode->i_rdev;
type = TYPE(device);
drive = DRIVE(device);
/* convert compatibility eject ioctls into floppy eject ioctl. /* convert compatibility eject ioctls into floppy eject ioctl.
* We do this in order to provide a means to eject floppy disks before * We do this in order to provide a means to eject floppy disks before
...@@ -3675,15 +3664,19 @@ static void __init config_types(void) ...@@ -3675,15 +3664,19 @@ static void __init config_types(void)
static int floppy_release(struct inode * inode, struct file * filp) static int floppy_release(struct inode * inode, struct file * filp)
{ {
int drive = DRIVE(inode->i_rdev); int drive = (long)inode->i_bdev->bd_disk->private_data;
down(&open_lock);
if (UDRS->fd_ref < 0) if (UDRS->fd_ref < 0)
UDRS->fd_ref=0; UDRS->fd_ref=0;
else if (!UDRS->fd_ref--) { else if (!UDRS->fd_ref--) {
DPRINT("floppy_release with fd_ref == 0"); DPRINT("floppy_release with fd_ref == 0");
UDRS->fd_ref = 0; UDRS->fd_ref = 0;
} }
if (!UDRS->fd_ref)
opened_bdev[drive] = NULL;
floppy_release_irq_and_dma(); floppy_release_irq_and_dma();
up(&open_lock);
return 0; return 0;
} }
...@@ -3692,28 +3685,19 @@ static int floppy_release(struct inode * inode, struct file * filp) ...@@ -3692,28 +3685,19 @@ static int floppy_release(struct inode * inode, struct file * filp)
* /dev/PS0 etc), and disallows simultaneous access to the same * /dev/PS0 etc), and disallows simultaneous access to the same
* drive with different device numbers. * drive with different device numbers.
*/ */
#define RETERR(x) do{floppy_release(inode,filp); return -(x);}while(0)
static int floppy_open(struct inode * inode, struct file * filp) static int floppy_open(struct inode * inode, struct file * filp)
{ {
int drive; int drive = (long)inode->i_bdev->bd_disk->private_data;
int old_dev; int old_dev;
int try; int try;
int res = -EBUSY;
char *tmp; char *tmp;
filp->private_data = (void*) 0; filp->private_data = (void*) 0;
down(&open_lock);
drive = DRIVE(inode->i_rdev);
if (drive >= N_DRIVE ||
!(allowed_drive_mask & (1 << drive)) ||
fdc_state[FDC(drive)].version == FDC_NONE)
return -ENXIO;
if (TYPE(inode->i_rdev) >= NUMBER(floppy_type))
return -ENXIO;
old_dev = UDRS->fd_device; old_dev = UDRS->fd_device;
if (UDRS->fd_ref && old_dev != minor(inode->i_rdev)) if (opened_bdev[drive] && opened_bdev[drive] != inode->i_bdev)
return -EBUSY; goto out2;
if (!UDRS->fd_ref && (UDP->flags & FD_BROKEN_DCL)){ if (!UDRS->fd_ref && (UDP->flags & FD_BROKEN_DCL)){
USETF(FD_DISK_CHANGED); USETF(FD_DISK_CHANGED);
...@@ -3722,16 +3706,20 @@ static int floppy_open(struct inode * inode, struct file * filp) ...@@ -3722,16 +3706,20 @@ static int floppy_open(struct inode * inode, struct file * filp)
if (UDRS->fd_ref == -1 || if (UDRS->fd_ref == -1 ||
(UDRS->fd_ref && (filp->f_flags & O_EXCL))) (UDRS->fd_ref && (filp->f_flags & O_EXCL)))
return -EBUSY; goto out2;
if (floppy_grab_irq_and_dma()) if (floppy_grab_irq_and_dma())
return -EBUSY; goto out2;
if (filp->f_flags & O_EXCL) if (filp->f_flags & O_EXCL)
UDRS->fd_ref = -1; UDRS->fd_ref = -1;
else else
UDRS->fd_ref++; UDRS->fd_ref++;
opened_bdev[drive] = inode->i_bdev;
res = -ENXIO;
if (!floppy_track_buffer){ if (!floppy_track_buffer){
/* if opening an ED drive, reserve a big buffer, /* if opening an ED drive, reserve a big buffer,
* else reserve a small one */ * else reserve a small one */
...@@ -3751,7 +3739,7 @@ static int floppy_open(struct inode * inode, struct file * filp) ...@@ -3751,7 +3739,7 @@ static int floppy_open(struct inode * inode, struct file * filp)
} }
if (!tmp && !floppy_track_buffer) { if (!tmp && !floppy_track_buffer) {
DPRINT("Unable to allocate DMA memory\n"); DPRINT("Unable to allocate DMA memory\n");
RETERR(ENXIO); goto out;
} }
if (floppy_track_buffer) { if (floppy_track_buffer) {
if (tmp) if (tmp)
...@@ -3768,8 +3756,6 @@ static int floppy_open(struct inode * inode, struct file * filp) ...@@ -3768,8 +3756,6 @@ static int floppy_open(struct inode * inode, struct file * filp)
if (old_dev != -1 && old_dev != minor(inode->i_rdev)) { if (old_dev != -1 && old_dev != minor(inode->i_rdev)) {
if (buffer_drive == drive) if (buffer_drive == drive)
buffer_track = -1; buffer_track = -1;
/* umm, invalidate_buffers() in ->open?? --hch */
invalidate_buffers(mk_kdev(FLOPPY_MAJOR,old_dev));
} }
/* Allow ioctls if we have write-permissions even if read-only open. /* Allow ioctls if we have write-permissions even if read-only open.
...@@ -3782,18 +3768,30 @@ static int floppy_open(struct inode * inode, struct file * filp) ...@@ -3782,18 +3768,30 @@ static int floppy_open(struct inode * inode, struct file * filp)
if (UFDCS->rawcmd == 1) if (UFDCS->rawcmd == 1)
UFDCS->rawcmd = 2; UFDCS->rawcmd = 2;
if (filp->f_flags & O_NDELAY) if (!filp->f_flags & O_NDELAY) {
return 0;
if (filp->f_mode & 3) { if (filp->f_mode & 3) {
UDRS->last_checked = 0; UDRS->last_checked = 0;
check_disk_change(inode->i_bdev); check_disk_change(inode->i_bdev);
if (UTESTF(FD_DISK_CHANGED)) if (UTESTF(FD_DISK_CHANGED))
RETERR(ENXIO); goto out;
} }
res = -EROFS;
if ((filp->f_mode & 2) && !(UTESTF(FD_DISK_WRITABLE))) if ((filp->f_mode & 2) && !(UTESTF(FD_DISK_WRITABLE)))
RETERR(EROFS); goto out;
}
up(&open_lock);
return 0; return 0;
#undef RETERR out:
if (UDRS->fd_ref < 0)
UDRS->fd_ref=0;
else
UDRS->fd_ref--;
if (!UDRS->fd_ref)
opened_bdev[drive] = NULL;
floppy_release_irq_and_dma();
out2:
up(&open_lock);
return res;
} }
/* /*
...@@ -4216,6 +4214,8 @@ static struct gendisk *floppy_find(dev_t dev, int *part, void *data) ...@@ -4216,6 +4214,8 @@ static struct gendisk *floppy_find(dev_t dev, int *part, void *data)
!(allowed_drive_mask & (1 << drive)) || !(allowed_drive_mask & (1 << drive)) ||
fdc_state[FDC(drive)].version == FDC_NONE) fdc_state[FDC(drive)].version == FDC_NONE)
return NULL; return NULL;
if (((*part >> 2) & 0x1f) >= NUMBER(floppy_type))
return NULL;
*part = 0; *part = 0;
return get_disk(disks[drive]); return get_disk(disks[drive]);
} }
......
...@@ -318,12 +318,6 @@ static inline void fallback_on_nodma_alloc(char **addr, size_t l) ...@@ -318,12 +318,6 @@ static inline void fallback_on_nodma_alloc(char **addr, size_t l)
static unsigned long fake_change; static unsigned long fake_change;
static int initialising=1; static int initialising=1;
static inline int TYPE(kdev_t x) {
return (minor(x)>>2) & 0x1f;
}
static inline int DRIVE(kdev_t x) {
return (minor(x)&0x03) | ((minor(x)&0x80) >> 5);
}
#define ITYPE(x) (((x)>>2) & 0x1f) #define ITYPE(x) (((x)>>2) & 0x1f)
#define TOMINOR(x) ((x & 3) | ((x & 4) << 5)) #define TOMINOR(x) ((x & 3) | ((x & 4) << 5))
#define UNIT(x) ((x) & 0x03) /* drive on fdc */ #define UNIT(x) ((x) & 0x03) /* drive on fdc */
...@@ -450,6 +444,8 @@ static struct floppy_drive_struct drive_state[N_DRIVE]; ...@@ -450,6 +444,8 @@ static struct floppy_drive_struct drive_state[N_DRIVE];
static struct floppy_write_errors write_errors[N_DRIVE]; static struct floppy_write_errors write_errors[N_DRIVE];
static struct timer_list motor_off_timer[N_DRIVE]; static struct timer_list motor_off_timer[N_DRIVE];
static struct gendisk *disks[N_DRIVE]; static struct gendisk *disks[N_DRIVE];
static struct block_device *opened_bdev[N_DRIVE];
static DECLARE_MUTEX(open_lock);
static struct floppy_raw_cmd *raw_cmd, default_raw_cmd; static struct floppy_raw_cmd *raw_cmd, default_raw_cmd;
/* /*
...@@ -3384,25 +3380,21 @@ static inline int set_geometry(unsigned int cmd, struct floppy_struct *g, ...@@ -3384,25 +3380,21 @@ static inline int set_geometry(unsigned int cmd, struct floppy_struct *g,
if (type){ if (type){
if (!capable(CAP_SYS_ADMIN)) if (!capable(CAP_SYS_ADMIN))
return -EPERM; return -EPERM;
down(&open_lock);
LOCK_FDC(drive,1); LOCK_FDC(drive,1);
for (cnt = 0; cnt < N_DRIVE; cnt++){
if (ITYPE(drive_state[cnt].fd_device) == type &&
drive_state[cnt].fd_ref)
set_bit(drive, &fake_change);
}
floppy_type[type] = *g; floppy_type[type] = *g;
floppy_type[type].name="user format"; floppy_type[type].name="user format";
for (cnt = type << 2; cnt < (type << 2) + 4; cnt++) for (cnt = type << 2; cnt < (type << 2) + 4; cnt++)
floppy_sizes[cnt]= floppy_sizes[cnt+0x80]= floppy_sizes[cnt]= floppy_sizes[cnt+0x80]=
floppy_type[type].size+1; floppy_type[type].size+1;
process_fd_request(); process_fd_request();
for (cnt = 0; cnt < N_DRIVE; cnt++){ for (cnt = 0; cnt < N_DRIVE; cnt++) {
if (ITYPE(drive_state[cnt].fd_device) == type && struct block_device *bdev = opened_bdev[cnt];
drive_state[cnt].fd_ref) if (!bdev || ITYPE(drive_state[cnt].fd_device) != type)
__check_disk_change( continue;
MKDEV(FLOPPY_MAJOR, __invalidate_device(bdev, 0);
drive_state[cnt].fd_device));
} }
up(&open_lock);
} else { } else {
LOCK_FDC(drive,1); LOCK_FDC(drive,1);
if (cmd != FDDEFPRM) if (cmd != FDDEFPRM)
...@@ -3500,8 +3492,8 @@ static int fd_ioctl(struct inode *inode, struct file *filp, unsigned int cmd, ...@@ -3500,8 +3492,8 @@ static int fd_ioctl(struct inode *inode, struct file *filp, unsigned int cmd,
#define OUT(c,x) case c: outparam = (const char *) (x); break #define OUT(c,x) case c: outparam = (const char *) (x); break
#define IN(c,x,tag) case c: *(x) = inparam. tag ; return 0 #define IN(c,x,tag) case c: *(x) = inparam. tag ; return 0
int i,drive,type; int drive = (long)inode->i_bdev->bd_disk->private_data;
kdev_t device; int i, type = ITYPE(UDRS->fd_device);
int ret; int ret;
int size; int size;
union inparam { union inparam {
...@@ -3512,10 +3504,6 @@ static int fd_ioctl(struct inode *inode, struct file *filp, unsigned int cmd, ...@@ -3512,10 +3504,6 @@ static int fd_ioctl(struct inode *inode, struct file *filp, unsigned int cmd,
} inparam; /* parameters coming from user space */ } inparam; /* parameters coming from user space */
const char *outparam; /* parameters passed back to user space */ const char *outparam; /* parameters passed back to user space */
device = inode->i_rdev;
type = TYPE(device);
drive = DRIVE(device);
/* convert compatibility eject ioctls into floppy eject ioctl. /* convert compatibility eject ioctls into floppy eject ioctl.
* We do this in order to provide a means to eject floppy disks before * We do this in order to provide a means to eject floppy disks before
* installing the new fdutils package */ * installing the new fdutils package */
...@@ -3750,15 +3738,19 @@ static void __init config_types(void) ...@@ -3750,15 +3738,19 @@ static void __init config_types(void)
static int floppy_release(struct inode * inode, struct file * filp) static int floppy_release(struct inode * inode, struct file * filp)
{ {
int drive = DRIVE(inode->i_rdev); int drive = (long)inode->i_bdev->bd_disk->private_data;
down(&open_lock);
if (UDRS->fd_ref < 0) if (UDRS->fd_ref < 0)
UDRS->fd_ref=0; UDRS->fd_ref=0;
else if (!UDRS->fd_ref--) { else if (!UDRS->fd_ref--) {
DPRINT("floppy_release with fd_ref == 0"); DPRINT("floppy_release with fd_ref == 0");
UDRS->fd_ref = 0; UDRS->fd_ref = 0;
} }
if (!UDRS->fd_ref)
opened_bdev[drive] = NULL;
floppy_release_irq_and_dma(); floppy_release_irq_and_dma();
up(&open_lock);
return 0; return 0;
} }
...@@ -3771,9 +3763,10 @@ static int floppy_release(struct inode * inode, struct file * filp) ...@@ -3771,9 +3763,10 @@ static int floppy_release(struct inode * inode, struct file * filp)
static int floppy_open(struct inode * inode, struct file * filp) static int floppy_open(struct inode * inode, struct file * filp)
{ {
int drive; int drive = (long)inode->i_bdev->bd_disk->private_data;
int old_dev; int old_dev;
int try; int try;
int res = -EBUSY;
char *tmp; char *tmp;
#ifdef PC9800_DEBUG_FLOPPY #ifdef PC9800_DEBUG_FLOPPY
...@@ -3781,7 +3774,6 @@ static int floppy_open(struct inode * inode, struct file * filp) ...@@ -3781,7 +3774,6 @@ static int floppy_open(struct inode * inode, struct file * filp)
#endif #endif
filp->private_data = (void*) 0; filp->private_data = (void*) 0;
drive = DRIVE(inode->i_rdev);
#ifdef PC9800_DEBUG_FLOPPY #ifdef PC9800_DEBUG_FLOPPY
printk("floppy open: drive=%d, current_drive=%d, UDP->cmos=%d\n" printk("floppy open: drive=%d, current_drive=%d, UDP->cmos=%d\n"
"floppy open: FDCS={spec1=%d, spec2=%d, dtr=%d, version=%d, dor=%d, address=%lu}\n", "floppy open: FDCS={spec1=%d, spec2=%d, dtr=%d, version=%d, dor=%d, address=%lu}\n",
...@@ -3796,16 +3788,10 @@ static int floppy_open(struct inode * inode, struct file * filp) ...@@ -3796,16 +3788,10 @@ static int floppy_open(struct inode * inode, struct file * filp)
} }
#endif /* PC9800_DEBUG_FLOPPY */ #endif /* PC9800_DEBUG_FLOPPY */
if (drive >= N_DRIVE || down(&open_lock);
!(allowed_drive_mask & (1 << drive)) ||
fdc_state[FDC(drive)].version == FDC_NONE)
return -ENXIO;
if (TYPE(inode->i_rdev) >= NUMBER(floppy_type))
return -ENXIO;
old_dev = UDRS->fd_device; old_dev = UDRS->fd_device;
if (UDRS->fd_ref && old_dev != minor(inode->i_rdev)) if (opened_bdev[drive] && opened_bdev[drive] != inode->i_bdev)
return -EBUSY; goto out2;
if (!UDRS->fd_ref && (UDP->flags & FD_BROKEN_DCL)){ if (!UDRS->fd_ref && (UDP->flags & FD_BROKEN_DCL)){
USETF(FD_DISK_CHANGED); USETF(FD_DISK_CHANGED);
...@@ -3814,16 +3800,20 @@ static int floppy_open(struct inode * inode, struct file * filp) ...@@ -3814,16 +3800,20 @@ static int floppy_open(struct inode * inode, struct file * filp)
if (UDRS->fd_ref == -1 || if (UDRS->fd_ref == -1 ||
(UDRS->fd_ref && (filp->f_flags & O_EXCL))) (UDRS->fd_ref && (filp->f_flags & O_EXCL)))
return -EBUSY; goto out2;
if (floppy_grab_irq_and_dma()) if (floppy_grab_irq_and_dma())
return -EBUSY; goto out2;
if (filp->f_flags & O_EXCL) if (filp->f_flags & O_EXCL)
UDRS->fd_ref = -1; UDRS->fd_ref = -1;
else else
UDRS->fd_ref++; UDRS->fd_ref++;
opened_bdev[drive] = inode->i_bdev;
res = -ENXIO;
if (!floppy_track_buffer){ if (!floppy_track_buffer){
/* if opening an ED drive, reserve a big buffer, /* if opening an ED drive, reserve a big buffer,
* else reserve a small one */ * else reserve a small one */
...@@ -3843,7 +3833,7 @@ static int floppy_open(struct inode * inode, struct file * filp) ...@@ -3843,7 +3833,7 @@ static int floppy_open(struct inode * inode, struct file * filp)
} }
if (!tmp && !floppy_track_buffer) { if (!tmp && !floppy_track_buffer) {
DPRINT("Unable to allocate DMA memory\n"); DPRINT("Unable to allocate DMA memory\n");
RETERR(ENXIO); goto out;
} }
if (floppy_track_buffer) { if (floppy_track_buffer) {
if (tmp) if (tmp)
...@@ -3860,8 +3850,6 @@ static int floppy_open(struct inode * inode, struct file * filp) ...@@ -3860,8 +3850,6 @@ static int floppy_open(struct inode * inode, struct file * filp)
if (old_dev != -1 && old_dev != minor(inode->i_rdev)) { if (old_dev != -1 && old_dev != minor(inode->i_rdev)) {
if (buffer_drive == drive) if (buffer_drive == drive)
buffer_track = -1; buffer_track = -1;
/* umm, invalidate_buffers() in ->open?? --hch */
invalidate_buffers(mk_kdev(FLOPPY_MAJOR,old_dev));
} }
#ifdef PC9800_DEBUG_FLOPPY #ifdef PC9800_DEBUG_FLOPPY
...@@ -3883,22 +3871,33 @@ static int floppy_open(struct inode * inode, struct file * filp) ...@@ -3883,22 +3871,33 @@ static int floppy_open(struct inode * inode, struct file * filp)
printk("floppy open: floppy.c:%d passed\n", __LINE__); printk("floppy open: floppy.c:%d passed\n", __LINE__);
#endif #endif
if (filp->f_flags & O_NDELAY) if (!(filp->f_flags & O_NDELAY)) {
return 0;
if (filp->f_mode & 3) { if (filp->f_mode & 3) {
UDRS->last_checked = 0; UDRS->last_checked = 0;
check_disk_change(inode->i_bdev); check_disk_change(inode->i_bdev);
if (UTESTF(FD_DISK_CHANGED)) if (UTESTF(FD_DISK_CHANGED))
RETERR(ENXIO); goto out;
} }
res = -EROFS;
if ((filp->f_mode & 2) && !(UTESTF(FD_DISK_WRITABLE))) if ((filp->f_mode & 2) && !(UTESTF(FD_DISK_WRITABLE)))
RETERR(EROFS); goto out;
#ifdef PC9800_DEBUG_FLOPPY #ifdef PC9800_DEBUG_FLOPPY
printk("floppy open: end normally\n"); printk("floppy open: end normally\n");
#endif #endif
}
up(&open_lock);
return 0; return 0;
#undef RETERR out:
if (UDRS->fd_ref < 0)
UDRS->fd_ref=0;
else
UDRS->fd_ref--;
if (!UDRS->fd_ref)
opened_bdev[drive] = NULL;
floppy_release_irq_and_dma();
out2:
up(&open_lock);
return res;
} }
/* /*
...@@ -4254,6 +4253,8 @@ static struct gendisk *floppy_find(dev_t dev, int *part, void *data) ...@@ -4254,6 +4253,8 @@ static struct gendisk *floppy_find(dev_t dev, int *part, void *data)
!(allowed_drive_mask & (1 << drive)) || !(allowed_drive_mask & (1 << drive)) ||
fdc_state[FDC(drive)].version == FDC_NONE) fdc_state[FDC(drive)].version == FDC_NONE)
return NULL; return NULL;
if (((*part>>2) & 0x1f) >= NUMBER(floppy_type))
return NULL;
return get_disk(disks[drive]); return get_disk(disks[drive]);
} }
......
...@@ -661,8 +661,6 @@ static int pt_ioctl(struct inode *inode,struct file *file, ...@@ -661,8 +661,6 @@ static int pt_ioctl(struct inode *inode,struct file *file,
int unit; int unit;
struct mtop mtop; struct mtop mtop;
if (!inode || kdev_none(inode->i_rdev))
return -EINVAL;
unit = DEVICE_NR(inode->i_rdev); unit = DEVICE_NR(inode->i_rdev);
if (unit >= PT_UNITS) if (unit >= PT_UNITS)
return -EINVAL; return -EINVAL;
......
...@@ -449,14 +449,13 @@ int check_disk_change(struct block_device *bdev) ...@@ -449,14 +449,13 @@ int check_disk_change(struct block_device *bdev)
{ {
struct gendisk *disk = bdev->bd_disk; struct gendisk *disk = bdev->bd_disk;
struct block_device_operations * bdops = disk->fops; struct block_device_operations * bdops = disk->fops;
kdev_t dev = to_kdev_t(bdev->bd_dev);
if (!bdops->media_changed) if (!bdops->media_changed)
return 0; return 0;
if (!bdops->media_changed(bdev->bd_disk)) if (!bdops->media_changed(bdev->bd_disk))
return 0; return 0;
if (invalidate_device(dev, 0)) if (__invalidate_device(bdev, 0))
printk("VFS: busy inodes on changed media.\n"); printk("VFS: busy inodes on changed media.\n");
if (bdops->revalidate_disk) if (bdops->revalidate_disk)
...@@ -466,36 +465,6 @@ int check_disk_change(struct block_device *bdev) ...@@ -466,36 +465,6 @@ int check_disk_change(struct block_device *bdev)
return 1; return 1;
} }
int full_check_disk_change(struct block_device *bdev)
{
int res = 0;
if (bdev->bd_contains != bdev)
BUG();
down(&bdev->bd_sem);
if (check_disk_change(bdev) && bdev->bd_invalidated) {
rescan_partitions(bdev->bd_disk, bdev);
res = 1;
}
up(&bdev->bd_sem);
return res;
}
/*
* Will die as soon as two remaining callers get converted.
*/
int __check_disk_change(dev_t dev)
{
struct block_device *bdev = bdget(dev);
int res;
if (!bdev)
return 0;
if (blkdev_get(bdev, FMODE_READ, 0, BDEV_RAW) < 0)
return 0;
res = full_check_disk_change(bdev);
blkdev_put(bdev, BDEV_RAW);
return res;
}
static void bd_set_size(struct block_device *bdev, loff_t size) static void bd_set_size(struct block_device *bdev, loff_t size)
{ {
unsigned bsize = bdev_hardsect_size(bdev); unsigned bsize = bdev_hardsect_size(bdev);
......
...@@ -447,15 +447,6 @@ void invalidate_bdev(struct block_device *bdev, int destroy_dirty_buffers) ...@@ -447,15 +447,6 @@ void invalidate_bdev(struct block_device *bdev, int destroy_dirty_buffers)
invalidate_inode_pages(bdev->bd_inode->i_mapping); invalidate_inode_pages(bdev->bd_inode->i_mapping);
} }
void __invalidate_buffers(kdev_t dev, int destroy_dirty_buffers)
{
struct block_device *bdev = bdget(kdev_t_to_nr(dev));
if (bdev) {
invalidate_bdev(bdev, destroy_dirty_buffers);
bdput(bdev);
}
}
/* /*
* Kick pdflush then try to free up some ZONE_NORMAL memory. * Kick pdflush then try to free up some ZONE_NORMAL memory.
*/ */
......
...@@ -340,15 +340,11 @@ int invalidate_inodes(struct super_block * sb) ...@@ -340,15 +340,11 @@ int invalidate_inodes(struct super_block * sb)
return busy; return busy;
} }
int invalidate_device(kdev_t dev, int do_sync) int __invalidate_device(struct block_device *bdev, int do_sync)
{ {
struct super_block *sb; struct super_block *sb;
struct block_device *bdev = bdget(kdev_t_to_nr(dev));
int res; int res;
if (!bdev)
return 0;
if (do_sync) if (do_sync)
fsync_bdev(bdev); fsync_bdev(bdev);
...@@ -366,6 +362,15 @@ int invalidate_device(kdev_t dev, int do_sync) ...@@ -366,6 +362,15 @@ int invalidate_device(kdev_t dev, int do_sync)
drop_super(sb); drop_super(sb);
} }
invalidate_bdev(bdev, 0); invalidate_bdev(bdev, 0);
return res;
}
int invalidate_device(kdev_t dev, int do_sync)
{
int res = 0;
struct block_device *bdev = bdget(kdev_t_to_nr(dev));
if (bdev)
res = __invalidate_device(bdev, do_sync);
bdput(bdev); bdput(bdev);
return res; return res;
} }
......
...@@ -128,9 +128,6 @@ BUFFER_FNS(Boundary, boundary) ...@@ -128,9 +128,6 @@ BUFFER_FNS(Boundary, boundary)
}) })
#define page_has_buffers(page) PagePrivate(page) #define page_has_buffers(page) PagePrivate(page)
#define invalidate_buffers(dev) __invalidate_buffers((dev), 0)
/* /*
* Declarations * Declarations
*/ */
...@@ -159,7 +156,6 @@ void unmap_underlying_metadata(struct block_device *bdev, sector_t block); ...@@ -159,7 +156,6 @@ void unmap_underlying_metadata(struct block_device *bdev, sector_t block);
void mark_buffer_async_read(struct buffer_head *bh); void mark_buffer_async_read(struct buffer_head *bh);
void mark_buffer_async_write(struct buffer_head *bh); void mark_buffer_async_write(struct buffer_head *bh);
void invalidate_bdev(struct block_device *, int); void invalidate_bdev(struct block_device *, int);
void __invalidate_buffers(kdev_t dev, int);
int sync_blockdev(struct block_device *bdev); int sync_blockdev(struct block_device *bdev);
void __wait_on_buffer(struct buffer_head *); void __wait_on_buffer(struct buffer_head *);
wait_queue_head_t *bh_waitq_head(struct buffer_head *bh); wait_queue_head_t *bh_waitq_head(struct buffer_head *bh);
......
...@@ -1102,9 +1102,8 @@ extern int fs_may_remount_ro(struct super_block *); ...@@ -1102,9 +1102,8 @@ extern int fs_may_remount_ro(struct super_block *);
#define bio_data_dir(bio) ((bio)->bi_rw & 1) #define bio_data_dir(bio) ((bio)->bi_rw & 1)
extern int check_disk_change(struct block_device *); extern int check_disk_change(struct block_device *);
extern int full_check_disk_change(struct block_device *);
extern int __check_disk_change(dev_t);
extern int invalidate_inodes(struct super_block *); extern int invalidate_inodes(struct super_block *);
extern int __invalidate_device(struct block_device *, int);
extern int invalidate_device(kdev_t, int); extern int invalidate_device(kdev_t, int);
unsigned long invalidate_mapping_pages(struct address_space *mapping, unsigned long invalidate_mapping_pages(struct address_space *mapping,
pgoff_t start, pgoff_t end); pgoff_t start, pgoff_t end);
......
...@@ -186,11 +186,10 @@ EXPORT_SYMBOL(filp_close); ...@@ -186,11 +186,10 @@ EXPORT_SYMBOL(filp_close);
EXPORT_SYMBOL(put_filp); EXPORT_SYMBOL(put_filp);
EXPORT_SYMBOL(files_lock); EXPORT_SYMBOL(files_lock);
EXPORT_SYMBOL(check_disk_change); EXPORT_SYMBOL(check_disk_change);
EXPORT_SYMBOL(__check_disk_change);
EXPORT_SYMBOL(__invalidate_buffers);
EXPORT_SYMBOL(invalidate_bdev); EXPORT_SYMBOL(invalidate_bdev);
EXPORT_SYMBOL(invalidate_inodes); EXPORT_SYMBOL(invalidate_inodes);
EXPORT_SYMBOL(invalidate_device); EXPORT_SYMBOL(invalidate_device);
EXPORT_SYMBOL(__invalidate_device);
EXPORT_SYMBOL(invalidate_inode_pages); EXPORT_SYMBOL(invalidate_inode_pages);
EXPORT_SYMBOL_GPL(invalidate_inode_pages2); EXPORT_SYMBOL_GPL(invalidate_inode_pages2);
EXPORT_SYMBOL(truncate_inode_pages); EXPORT_SYMBOL(truncate_inode_pages);
......
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