fedora core 6 1.2949 + vserver 2.2.0
[linux-2.6.git] / drivers / ide / ide-tape.c
index 0101d0d..b3bcd1d 100644 (file)
 
 #define IDETAPE_VERSION "1.19"
 
-#include <linux/config.h>
 #include <linux/module.h>
 #include <linux/types.h>
 #include <linux/string.h>
 #include <linux/timer.h>
 #include <linux/mm.h>
 #include <linux/interrupt.h>
+#include <linux/jiffies.h>
 #include <linux/major.h>
-#include <linux/devfs_fs_kernel.h>
 #include <linux/errno.h>
 #include <linux/genhd.h>
 #include <linux/slab.h>
 #include <linux/smp_lock.h>
 #include <linux/completion.h>
 #include <linux/bitops.h>
+#include <linux/mutex.h>
 
 #include <asm/byteorder.h>
 #include <asm/irq.h>
@@ -1011,7 +1011,7 @@ typedef struct ide_tape_obj {
          int debug_level; 
 } idetape_tape_t;
 
-static DECLARE_MUTEX(idetape_ref_sem);
+static DEFINE_MUTEX(idetape_ref_mutex);
 
 static struct class *idetape_sysfs_class;
 
@@ -1024,11 +1024,11 @@ static struct ide_tape_obj *ide_tape_get(struct gendisk *disk)
 {
        struct ide_tape_obj *tape = NULL;
 
-       down(&idetape_ref_sem);
+       mutex_lock(&idetape_ref_mutex);
        tape = ide_tape_g(disk);
        if (tape)
                kref_get(&tape->kref);
-       up(&idetape_ref_sem);
+       mutex_unlock(&idetape_ref_mutex);
        return tape;
 }
 
@@ -1036,9 +1036,9 @@ static void ide_tape_release(struct kref *);
 
 static void ide_tape_put(struct ide_tape_obj *tape)
 {
-       down(&idetape_ref_sem);
+       mutex_lock(&idetape_ref_mutex);
        kref_put(&tape->kref, ide_tape_release);
-       up(&idetape_ref_sem);
+       mutex_unlock(&idetape_ref_mutex);
 }
 
 /*
@@ -1290,11 +1290,11 @@ static struct ide_tape_obj *ide_tape_chrdev_get(unsigned int i)
 {
        struct ide_tape_obj *tape = NULL;
 
-       down(&idetape_ref_sem);
+       mutex_lock(&idetape_ref_mutex);
        tape = idetape_devs[i];
        if (tape)
                kref_get(&tape->kref);
-       up(&idetape_ref_sem);
+       mutex_unlock(&idetape_ref_mutex);
        return tape;
 }
 
@@ -1776,7 +1776,7 @@ static void idetape_create_request_sense_cmd (idetape_pc_t *pc)
 static void idetape_init_rq(struct request *rq, u8 cmd)
 {
        memset(rq, 0, sizeof(*rq));
-       rq->flags = REQ_SPECIAL;
+       rq->cmd_type = REQ_TYPE_SPECIAL;
        rq->cmd[0] = cmd;
 }
 
@@ -2335,7 +2335,7 @@ static ide_startstop_t idetape_rw_callback (ide_drive_t *drive)
        }
        if (time_after(jiffies, tape->insert_time))
                tape->insert_speed = tape->insert_size / 1024 * HZ / (jiffies - tape->insert_time);
-       if (jiffies - tape->avg_time >= HZ) {
+       if (time_after_eq(jiffies, tape->avg_time + HZ)) {
                tape->avg_speed = tape->avg_size * HZ / (jiffies - tape->avg_time) / 1024;
                tape->avg_size = 0;
                tape->avg_time = jiffies;
@@ -2423,8 +2423,8 @@ static ide_startstop_t idetape_do_request(ide_drive_t *drive,
 #if IDETAPE_DEBUG_LOG
 #if 0
        if (tape->debug_level >= 5)
-               printk(KERN_INFO "ide-tape: rq_status: %d, "
-                       "dev: %s, cmd: %ld, errors: %d\n", rq->rq_status,
+               printk(KERN_INFO "ide-tape:  %d, "
+                       "dev: %s, cmd: %ld, errors: %d\n",
                         rq->rq_disk->disk_name, rq->cmd[0], rq->errors);
 #endif
        if (tape->debug_level >= 2)
@@ -2433,12 +2433,12 @@ static ide_startstop_t idetape_do_request(ide_drive_t *drive,
                        rq->sector, rq->nr_sectors, rq->current_nr_sectors);
 #endif /* IDETAPE_DEBUG_LOG */
 
-       if ((rq->flags & REQ_SPECIAL) == 0) {
+       if (!blk_special_request(rq)) {
                /*
                 * We do not support buffer cache originated requests.
                 */
                printk(KERN_NOTICE "ide-tape: %s: Unsupported request in "
-                       "request queue (%ld)\n", drive->name, rq->flags);
+                       "request queue (%d)\n", drive->name, rq->cmd_type);
                ide_end_request(drive, 0, 0);
                return ide_stopped;
        }
@@ -2496,7 +2496,7 @@ static ide_startstop_t idetape_do_request(ide_drive_t *drive,
                        } else {
                                return ide_do_reset(drive);
                        }
-               } else if (jiffies - tape->dsc_polling_start > IDETAPE_DSC_MA_THRESHOLD)
+               } else if (time_after(jiffies, tape->dsc_polling_start + IDETAPE_DSC_MA_THRESHOLD))
                        tape->dsc_polling_frequency = IDETAPE_DSC_MA_SLOW;
                idetape_postpone_request(drive);
                return ide_stopped;
@@ -2573,11 +2573,11 @@ static idetape_stage_t *__idetape_kmalloc_stage (idetape_tape_t *tape, int full,
        int pages = tape->pages_per_stage;
        char *b_data = NULL;
 
-       if ((stage = (idetape_stage_t *) kmalloc (sizeof (idetape_stage_t),GFP_KERNEL)) == NULL)
+       if ((stage = kmalloc(sizeof (idetape_stage_t),GFP_KERNEL)) == NULL)
                return NULL;
        stage->next = NULL;
 
-       bh = stage->bh = (struct idetape_bh *)kmalloc(sizeof(struct idetape_bh), GFP_KERNEL);
+       bh = stage->bh = kmalloc(sizeof(struct idetape_bh), GFP_KERNEL);
        if (bh == NULL)
                goto abort;
        bh->b_reqnext = NULL;
@@ -2607,7 +2607,7 @@ static idetape_stage_t *__idetape_kmalloc_stage (idetape_tape_t *tape, int full,
                        continue;
                }
                prev_bh = bh;
-               if ((bh = (struct idetape_bh *)kmalloc(sizeof(struct idetape_bh), GFP_KERNEL)) == NULL) {
+               if ((bh = kmalloc(sizeof(struct idetape_bh), GFP_KERNEL)) == NULL) {
                        free_page((unsigned long) b_data);
                        goto abort;
                }
@@ -2644,21 +2644,23 @@ static idetape_stage_t *idetape_kmalloc_stage (idetape_tape_t *tape)
        return __idetape_kmalloc_stage(tape, 0, 0);
 }
 
-static void idetape_copy_stage_from_user (idetape_tape_t *tape, idetape_stage_t *stage, const char __user *buf, int n)
+static int idetape_copy_stage_from_user (idetape_tape_t *tape, idetape_stage_t *stage, const char __user *buf, int n)
 {
        struct idetape_bh *bh = tape->bh;
        int count;
+       int ret = 0;
 
        while (n) {
 #if IDETAPE_DEBUG_BUGS
                if (bh == NULL) {
                        printk(KERN_ERR "ide-tape: bh == NULL in "
                                "idetape_copy_stage_from_user\n");
-                       return;
+                       return 1;
                }
 #endif /* IDETAPE_DEBUG_BUGS */
                count = min((unsigned int)(bh->b_size - atomic_read(&bh->b_count)), (unsigned int)n);
-               copy_from_user(bh->b_data + atomic_read(&bh->b_count), buf, count);
+               if (copy_from_user(bh->b_data + atomic_read(&bh->b_count), buf, count))
+                       ret = 1;
                n -= count;
                atomic_add(count, &bh->b_count);
                buf += count;
@@ -2669,23 +2671,26 @@ static void idetape_copy_stage_from_user (idetape_tape_t *tape, idetape_stage_t
                }
        }
        tape->bh = bh;
+       return ret;
 }
 
-static void idetape_copy_stage_to_user (idetape_tape_t *tape, char __user *buf, idetape_stage_t *stage, int n)
+static int idetape_copy_stage_to_user (idetape_tape_t *tape, char __user *buf, idetape_stage_t *stage, int n)
 {
        struct idetape_bh *bh = tape->bh;
        int count;
+       int ret = 0;
 
        while (n) {
 #if IDETAPE_DEBUG_BUGS
                if (bh == NULL) {
                        printk(KERN_ERR "ide-tape: bh == NULL in "
                                "idetape_copy_stage_to_user\n");
-                       return;
+                       return 1;
                }
 #endif /* IDETAPE_DEBUG_BUGS */
                count = min(tape->b_count, n);
-               copy_to_user(buf, tape->b_data, count);
+               if  (copy_to_user(buf, tape->b_data, count))
+                       ret = 1;
                n -= count;
                tape->b_data += count;
                tape->b_count -= count;
@@ -2698,6 +2703,7 @@ static void idetape_copy_stage_to_user (idetape_tape_t *tape, char __user *buf,
                        }
                }
        }
+       return ret;
 }
 
 static void idetape_init_merge_stage (idetape_tape_t *tape)
@@ -2758,16 +2764,16 @@ static void idetape_add_stage_tail (ide_drive_t *drive,idetape_stage_t *stage)
  */
 static void idetape_wait_for_request (ide_drive_t *drive, struct request *rq)
 {
-       DECLARE_COMPLETION(wait);
+       DECLARE_COMPLETION_ONSTACK(wait);
        idetape_tape_t *tape = drive->driver_data;
 
 #if IDETAPE_DEBUG_BUGS
-       if (rq == NULL || (rq->flags & REQ_SPECIAL) == 0) {
+       if (rq == NULL || !blk_special_request(rq)) {
                printk (KERN_ERR "ide-tape: bug: Trying to sleep on non-valid request\n");
                return;
        }
 #endif /* IDETAPE_DEBUG_BUGS */
-       rq->waiting = &wait;
+       rq->end_io_data = &wait;
        rq->end_io = blk_end_sync_rq;
        spin_unlock_irq(&tape->spinlock);
        wait_for_completion(&wait);
@@ -3717,6 +3723,7 @@ static ssize_t idetape_chrdev_read (struct file *file, char __user *buf,
        struct ide_tape_obj *tape = ide_tape_f(file);
        ide_drive_t *drive = tape->drive;
        ssize_t bytes_read,temp, actually_read = 0, rc;
+       ssize_t ret = 0;
 
 #if IDETAPE_DEBUG_LOG
        if (tape->debug_level >= 3)
@@ -3735,7 +3742,8 @@ static ssize_t idetape_chrdev_read (struct file *file, char __user *buf,
                return (0);
        if (tape->merge_stage_size) {
                actually_read = min((unsigned int)(tape->merge_stage_size), (unsigned int)count);
-               idetape_copy_stage_to_user(tape, buf, tape->merge_stage, actually_read);
+               if (idetape_copy_stage_to_user(tape, buf, tape->merge_stage, actually_read))
+                       ret = -EFAULT;
                buf += actually_read;
                tape->merge_stage_size -= actually_read;
                count -= actually_read;
@@ -3744,7 +3752,8 @@ static ssize_t idetape_chrdev_read (struct file *file, char __user *buf,
                bytes_read = idetape_add_chrdev_read_request(drive, tape->capabilities.ctl);
                if (bytes_read <= 0)
                        goto finish;
-               idetape_copy_stage_to_user(tape, buf, tape->merge_stage, bytes_read);
+               if (idetape_copy_stage_to_user(tape, buf, tape->merge_stage, bytes_read))
+                       ret = -EFAULT;
                buf += bytes_read;
                count -= bytes_read;
                actually_read += bytes_read;
@@ -3754,7 +3763,8 @@ static ssize_t idetape_chrdev_read (struct file *file, char __user *buf,
                if (bytes_read <= 0)
                        goto finish;
                temp = min((unsigned long)count, (unsigned long)bytes_read);
-               idetape_copy_stage_to_user(tape, buf, tape->merge_stage, temp);
+               if (idetape_copy_stage_to_user(tape, buf, tape->merge_stage, temp))
+                       ret = -EFAULT;
                actually_read += temp;
                tape->merge_stage_size = bytes_read-temp;
        }
@@ -3767,7 +3777,8 @@ finish:
                idetape_space_over_filemarks(drive, MTFSF, 1);
                return 0;
        }
-       return actually_read;
+
+       return (ret) ? ret : actually_read;
 }
 
 static ssize_t idetape_chrdev_write (struct file *file, const char __user *buf,
@@ -3775,7 +3786,8 @@ static ssize_t idetape_chrdev_write (struct file *file, const char __user *buf,
 {
        struct ide_tape_obj *tape = ide_tape_f(file);
        ide_drive_t *drive = tape->drive;
-       ssize_t retval, actually_written = 0;
+       ssize_t actually_written = 0;
+       ssize_t ret = 0;
 
        /* The drive is write protected. */
        if (tape->write_prot)
@@ -3811,7 +3823,7 @@ static ssize_t idetape_chrdev_write (struct file *file, const char __user *buf,
                 *      some drives (Seagate STT3401A) will return an error.
                 */
                if (drive->dsc_overlap) {
-                       retval = idetape_queue_rw_tail(drive, REQ_IDETAPE_WRITE, 0, tape->merge_stage->bh);
+                       ssize_t retval = idetape_queue_rw_tail(drive, REQ_IDETAPE_WRITE, 0, tape->merge_stage->bh);
                        if (retval < 0) {
                                __idetape_kfree_stage(tape->merge_stage);
                                tape->merge_stage = NULL;
@@ -3832,12 +3844,14 @@ static ssize_t idetape_chrdev_write (struct file *file, const char __user *buf,
                }
 #endif /* IDETAPE_DEBUG_BUGS */
                actually_written = min((unsigned int)(tape->stage_size - tape->merge_stage_size), (unsigned int)count);
-               idetape_copy_stage_from_user(tape, tape->merge_stage, buf, actually_written);
+               if (idetape_copy_stage_from_user(tape, tape->merge_stage, buf, actually_written))
+                               ret = -EFAULT;
                buf += actually_written;
                tape->merge_stage_size += actually_written;
                count -= actually_written;
 
                if (tape->merge_stage_size == tape->stage_size) {
+                       ssize_t retval;
                        tape->merge_stage_size = 0;
                        retval = idetape_add_chrdev_write_request(drive, tape->capabilities.ctl);
                        if (retval <= 0)
@@ -3845,7 +3859,9 @@ static ssize_t idetape_chrdev_write (struct file *file, const char __user *buf,
                }
        }
        while (count >= tape->stage_size) {
-               idetape_copy_stage_from_user(tape, tape->merge_stage, buf, tape->stage_size);
+               ssize_t retval;
+               if (idetape_copy_stage_from_user(tape, tape->merge_stage, buf, tape->stage_size))
+                       ret = -EFAULT;
                buf += tape->stage_size;
                count -= tape->stage_size;
                retval = idetape_add_chrdev_write_request(drive, tape->capabilities.ctl);
@@ -3855,10 +3871,11 @@ static ssize_t idetape_chrdev_write (struct file *file, const char __user *buf,
        }
        if (count) {
                actually_written += count;
-               idetape_copy_stage_from_user(tape, tape->merge_stage, buf, count);
+               if (idetape_copy_stage_from_user(tape, tape->merge_stage, buf, count))
+                       ret = -EFAULT;
                tape->merge_stage_size += count;
        }
-       return (actually_written);
+       return (ret) ? ret : actually_written;
 }
 
 static int idetape_write_filemark (ide_drive_t *drive)
@@ -4707,9 +4724,6 @@ static void ide_tape_release(struct kref *kref)
                        MKDEV(IDETAPE_MAJOR, tape->minor));
        class_device_destroy(idetape_sysfs_class,
                        MKDEV(IDETAPE_MAJOR, tape->minor + 128));
-       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;
        put_disk(g);
@@ -4846,7 +4860,7 @@ static int ide_tape_probe(ide_drive_t *drive)
                printk(KERN_WARNING "ide-tape: Use drive %s with ide-scsi emulation and osst.\n", drive->name);
                printk(KERN_WARNING "ide-tape: OnStream support will be removed soon from ide-tape!\n");
        }
-       tape = (idetape_tape_t *) kzalloc (sizeof (idetape_tape_t), GFP_KERNEL);
+       tape = kzalloc(sizeof (idetape_tape_t), GFP_KERNEL);
        if (tape == NULL) {
                printk(KERN_ERR "ide-tape: %s: Can't allocate a tape structure\n", drive->name);
                goto failed;
@@ -4870,11 +4884,11 @@ static int ide_tape_probe(ide_drive_t *drive)
 
        drive->driver_data = tape;
 
-       down(&idetape_ref_sem);
+       mutex_lock(&idetape_ref_mutex);
        for (minor = 0; idetape_devs[minor]; minor++)
                ;
        idetape_devs[minor] = tape;
-       up(&idetape_ref_sem);
+       mutex_unlock(&idetape_ref_mutex);
 
        idetape_setup(drive, tape, minor);
 
@@ -4883,14 +4897,6 @@ static int ide_tape_probe(ide_drive_t *drive)
        class_device_create(idetape_sysfs_class, NULL,
                        MKDEV(IDETAPE_MAJOR, minor + 128), &drive->gendev, "n%s", tape->name);
 
-       devfs_mk_cdev(MKDEV(HWIF(drive)->major, minor),
-                       S_IFCHR | S_IRUGO | S_IWUGO,
-                       "%s/mt", drive->devfs_name);
-       devfs_mk_cdev(MKDEV(HWIF(drive)->major, minor + 128),
-                       S_IFCHR | S_IRUGO | S_IWUGO,
-                       "%s/mtn", drive->devfs_name);
-
-       g->number = devfs_register_tape(drive->devfs_name);
        g->fops = &idetape_block_ops;
        ide_register_region(g);