Similar to the same race but for the block device. * store pointer to struct ide_tape_obj in idetape_chrdevs[] * rename idetape_chrdevs[] to idetape_devs[] and kill idetape_chrdev_t * add ide_tape_chrdev_get() for getting reference to the tape * store tape pointer in file->private_data and fix all users of it * fix idetape_chrdev_{open,release}() to get/put reference to the tape
diff -Nru a/drivers/ide/ide-tape.c b/drivers/ide/ide-tape.c --- a/drivers/ide/ide-tape.c 2005-02-04 03:30:44 +01:00 +++ b/drivers/ide/ide-tape.c 2005-02-04 03:30:44 +01:00 @@ -1122,15 +1122,6 @@ #define IDETAPE_ERROR_EOD 103 /* - * idetape_chrdev_t provides the link between out character device - * interface and our block device interface and the corresponding - * ide_drive_t structure. - */ -typedef struct { - ide_drive_t *drive; -} idetape_chrdev_t; - -/* * The following is used to format the general configuration word of * the ATAPI IDENTIFY DEVICE command. */ @@ -1286,7 +1277,21 @@ * The variables below are used for the character device interface. * Additional state variables are defined in our ide_drive_t structure. */ -static idetape_chrdev_t idetape_chrdevs[MAX_HWIFS * MAX_DRIVES]; +static struct ide_tape_obj * idetape_devs[MAX_HWIFS * MAX_DRIVES]; + +#define ide_tape_f(file) ((file)->private_data) + +static struct ide_tape_obj *ide_tape_chrdev_get(unsigned int i) +{ + struct ide_tape_obj *tape = NULL; + + down(&idetape_ref_sem); + tape = idetape_devs[i]; + if (tape) + kref_get(&tape->kref); + up(&idetape_ref_sem); + return tape; +} /* * Function declarations @@ -3697,8 +3702,8 @@ static ssize_t idetape_chrdev_read (struct file *file, char __user *buf, size_t count, loff_t *ppos) { - ide_drive_t *drive = file->private_data; - idetape_tape_t *tape = drive->driver_data; + struct ide_tape_obj *tape = ide_tape_f(file); + ide_drive_t *drive = tape->drive; ssize_t bytes_read,temp, actually_read = 0, rc; #if IDETAPE_DEBUG_LOG @@ -3756,8 +3761,8 @@ static ssize_t idetape_chrdev_write (struct file *file, const char __user *buf, size_t count, loff_t *ppos) { - ide_drive_t *drive = file->private_data; - idetape_tape_t *tape = drive->driver_data; + struct ide_tape_obj *tape = ide_tape_f(file); + ide_drive_t *drive = tape->drive; ssize_t retval, actually_written = 0; /* The drive is write protected. */ @@ -4059,8 +4064,8 @@ */ static int idetape_chrdev_ioctl (struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg) { - ide_drive_t *drive = file->private_data; - idetape_tape_t *tape = drive->driver_data; + struct ide_tape_obj *tape = ide_tape_f(file); + ide_drive_t *drive = tape->drive; struct mtop mtop; struct mtget mtget; struct mtpos mtpos; @@ -4131,17 +4136,24 @@ if (i >= MAX_HWIFS * MAX_DRIVES) return -ENXIO; - drive = idetape_chrdevs[i].drive; - tape = drive->driver_data; - filp->private_data = drive; - if (test_and_set_bit(IDETAPE_BUSY, &tape->flags)) - return -EBUSY; + if (!(tape = ide_tape_chrdev_get(i))) + return -ENXIO; + + drive = tape->drive; + + filp->private_data = tape; + + if (test_and_set_bit(IDETAPE_BUSY, &tape->flags)) { + retval = -EBUSY; + goto out_put_tape; + } + retval = idetape_wait_ready(drive, 60 * HZ); if (retval) { clear_bit(IDETAPE_BUSY, &tape->flags); printk(KERN_ERR "ide-tape: %s: drive not ready\n", tape->name); - return retval; + goto out_put_tape; } idetape_read_position(drive); @@ -4165,7 +4177,8 @@ if ((filp->f_flags & O_ACCMODE) == O_WRONLY || (filp->f_flags & O_ACCMODE) == O_RDWR) { clear_bit(IDETAPE_BUSY, &tape->flags); - return -EROFS; + retval = -EROFS; + goto out_put_tape; } } @@ -4183,6 +4196,10 @@ idetape_restart_speed_control(drive); tape->restart_speed_control_req = 0; return 0; + +out_put_tape: + ide_tape_put(tape); + return retval; } static void idetape_write_release (ide_drive_t *drive, unsigned int minor) @@ -4206,8 +4223,8 @@ */ static int idetape_chrdev_release (struct inode *inode, struct file *filp) { - ide_drive_t *drive = filp->private_data; - idetape_tape_t *tape; + struct ide_tape_obj *tape = ide_tape_f(filp); + ide_drive_t *drive = tape->drive; idetape_pc_t pc; unsigned int minor = iminor(inode); @@ -4241,6 +4258,7 @@ } } clear_bit(IDETAPE_BUSY, &tape->flags); + ide_tape_put(tape); unlock_kernel(); return 0; } @@ -4649,7 +4667,6 @@ static int idetape_cleanup (ide_drive_t *drive) { idetape_tape_t *tape = drive->driver_data; - int minor = tape->minor; unsigned long flags; spin_lock_irqsave(&ide_lock, flags); @@ -4658,7 +4675,7 @@ spin_unlock_irqrestore(&ide_lock, flags); return 1; } - idetape_chrdevs[minor].drive = NULL; + spin_unlock_irqrestore(&ide_lock, flags); DRIVER(drive)->busy = 0; (void) ide_unregister_subdriver(drive); @@ -4678,6 +4695,7 @@ devfs_remove("%s/mt", drive->devfs_name); devfs_remove("%s/mtn", drive->devfs_name); devfs_unregister_tape(g->number); + idetape_devs[tape->minor] = NULL; g->private_data = NULL; g->fops = ide_fops; kfree(tape); @@ -4825,8 +4843,6 @@ kfree(tape); goto failed; } - for (minor = 0; idetape_chrdevs[minor].drive != NULL; minor++) - ; memset(tape, 0, sizeof(*tape)); @@ -4836,8 +4852,13 @@ drive->driver_data = tape; + down(&idetape_ref_sem); + for (minor = 0; idetape_devs[minor]; minor++) + ; + idetape_devs[minor] = tape; + up(&idetape_ref_sem); + idetape_setup(drive, tape, minor); - idetape_chrdevs[minor].drive = drive; devfs_mk_cdev(MKDEV(HWIF(drive)->major, minor), S_IFCHR | S_IRUGO | S_IWUGO, - To unsubscribe from this list: send the line "unsubscribe linux-kernel" in the body of a message to [EMAIL PROTECTED] More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/