Merge branch 'for-2.6.39/stack-plug' into for-2.6.39/core
[linux-3.10.git] / drivers / s390 / char / tape_block.c
index 1e79676..83cea9a 100644 (file)
  */
 
 #define KMSG_COMPONENT "tape"
+#define pr_fmt(fmt) KMSG_COMPONENT ": " fmt
 
 #include <linux/fs.h>
 #include <linux/module.h>
 #include <linux/blkdev.h>
+#include <linux/mutex.h>
 #include <linux/interrupt.h>
 #include <linux/buffer_head.h>
 #include <linux/kernel.h>
 /*
  * file operation structure for tape block frontend
  */
+static DEFINE_MUTEX(tape_block_mutex);
 static int tapeblock_open(struct block_device *, fmode_t);
 static int tapeblock_release(struct gendisk *, fmode_t);
-static int tapeblock_ioctl(struct block_device *, fmode_t, unsigned int,
-                               unsigned long);
-static int tapeblock_medium_changed(struct gendisk *);
+static unsigned int tapeblock_check_events(struct gendisk *, unsigned int);
 static int tapeblock_revalidate_disk(struct gendisk *);
 
-static struct block_device_operations tapeblock_fops = {
+static const struct block_device_operations tapeblock_fops = {
        .owner           = THIS_MODULE,
        .open            = tapeblock_open,
        .release         = tapeblock_release,
-       .locked_ioctl           = tapeblock_ioctl,
-       .media_changed   = tapeblock_medium_changed,
+       .check_events    = tapeblock_check_events,
        .revalidate_disk = tapeblock_revalidate_disk,
 };
 
@@ -161,10 +161,10 @@ tapeblock_requeue(struct work_struct *work) {
 
        spin_lock_irq(&device->blk_data.request_queue_lock);
        while (
-               !blk_queue_plugged(queue) &&
-               (req = blk_fetch_request(queue)) &&
+               blk_peek_request(queue) &&
                nr_queued < TAPEBLOCK_MIN_REQUEUE
        ) {
+               req = blk_fetch_request(queue);
                if (rq_data_dir(req) == WRITE) {
                        DBF_EVENT(1, "TBLOCK: Rejecting write request\n");
                        spin_unlock_irq(&device->blk_data.request_queue_lock);
@@ -217,15 +217,13 @@ tapeblock_setup_device(struct tape_device * device)
        if (!blkdat->request_queue)
                return -ENOMEM;
 
-       elevator_exit(blkdat->request_queue->elevator);
-       rc = elevator_init(blkdat->request_queue, "noop");
+       rc = elevator_change(blkdat->request_queue, "noop");
        if (rc)
                goto cleanup_queue;
 
-       blk_queue_hardsect_size(blkdat->request_queue, TAPEBLOCK_HSEC_SIZE);
-       blk_queue_max_sectors(blkdat->request_queue, TAPEBLOCK_MAX_SEC);
-       blk_queue_max_phys_segments(blkdat->request_queue, -1L);
-       blk_queue_max_hw_segments(blkdat->request_queue, -1L);
+       blk_queue_logical_block_size(blkdat->request_queue, TAPEBLOCK_HSEC_SIZE);
+       blk_queue_max_hw_sectors(blkdat->request_queue, TAPEBLOCK_MAX_SEC);
+       blk_queue_max_segments(blkdat->request_queue, -1L);
        blk_queue_max_segment_size(blkdat->request_queue, -1L);
        blk_queue_segment_boundary(blkdat->request_queue, -1L);
 
@@ -238,7 +236,8 @@ tapeblock_setup_device(struct tape_device * device)
        disk->major = tapeblock_major;
        disk->first_minor = device->first_minor;
        disk->fops = &tapeblock_fops;
-       disk->private_data = tape_get_device_reference(device);
+       disk->events = DISK_EVENT_MEDIA_CHANGE;
+       disk->private_data = tape_get_device(device);
        disk->queue = blkdat->request_queue;
        set_capacity(disk, 0);
        sprintf(disk->disk_name, "btibm%d",
@@ -246,11 +245,11 @@ tapeblock_setup_device(struct tape_device * device)
 
        blkdat->disk = disk;
        blkdat->medium_changed = 1;
-       blkdat->request_queue->queuedata = tape_get_device_reference(device);
+       blkdat->request_queue->queuedata = tape_get_device(device);
 
        add_disk(disk);
 
-       tape_get_device_reference(device);
+       tape_get_device(device);
        INIT_WORK(&blkdat->requeue_task, tapeblock_requeue);
 
        return 0;
@@ -265,7 +264,7 @@ cleanup_queue:
 void
 tapeblock_cleanup_device(struct tape_device *device)
 {
-       flush_scheduled_work();
+       flush_work_sync(&device->blk_data.requeue_task);
        tape_put_device(device);
 
        if (!device->blk_data.disk) {
@@ -273,13 +272,14 @@ tapeblock_cleanup_device(struct tape_device *device)
        }
 
        del_gendisk(device->blk_data.disk);
-       device->blk_data.disk->private_data =
-               tape_put_device(device->blk_data.disk->private_data);
+       device->blk_data.disk->private_data = NULL;
+       tape_put_device(device);
        put_disk(device->blk_data.disk);
 
        device->blk_data.disk = NULL;
 cleanup_queue:
-       device->blk_data.request_queue->queuedata = tape_put_device(device);
+       device->blk_data.request_queue->queuedata = NULL;
+       tape_put_device(device);
 
        blk_cleanup_queue(device->blk_data.request_queue);
        device->blk_data.request_queue = NULL;
@@ -302,8 +302,6 @@ tapeblock_revalidate_disk(struct gendisk *disk)
        if (!device->blk_data.medium_changed)
                return 0;
 
-       dev_info(&device->cdev->dev, "Determining the size of the recorded "
-               "area...\n");
        rc = tape_mtop(device, MTFSFM, 1);
        if (rc)
                return rc;
@@ -312,6 +310,8 @@ tapeblock_revalidate_disk(struct gendisk *disk)
        if (rc < 0)
                return rc;
 
+       pr_info("%s: Determining the size of the recorded area...\n",
+               dev_name(&device->cdev->dev));
        DBF_LH(3, "Image file ends at %d\n", rc);
        nr_of_blks = rc;
 
@@ -330,8 +330,8 @@ tapeblock_revalidate_disk(struct gendisk *disk)
        device->bof = rc;
        nr_of_blks -= rc;
 
-       dev_info(&device->cdev->dev, "The size of the recorded area is %i "
-               "blocks\n", nr_of_blks);
+       pr_info("%s: The size of the recorded area is %i blocks\n",
+               dev_name(&device->cdev->dev), nr_of_blks);
        set_capacity(device->blk_data.disk,
                nr_of_blks*(TAPEBLOCK_HSEC_SIZE/512));
 
@@ -340,8 +340,8 @@ tapeblock_revalidate_disk(struct gendisk *disk)
        return 0;
 }
 
-static int
-tapeblock_medium_changed(struct gendisk *disk)
+static unsigned int
+tapeblock_check_events(struct gendisk *disk, unsigned int clearing)
 {
        struct tape_device *device;
 
@@ -349,7 +349,7 @@ tapeblock_medium_changed(struct gendisk *disk)
        DBF_LH(6, "tapeblock_medium_changed(%p) = %d\n",
                device, device->blk_data.medium_changed);
 
-       return device->blk_data.medium_changed;
+       return device->blk_data.medium_changed ? DISK_EVENT_MEDIA_CHANGE : 0;
 }
 
 /*
@@ -362,12 +362,13 @@ tapeblock_open(struct block_device *bdev, fmode_t mode)
        struct tape_device *    device;
        int                     rc;
 
-       device = tape_get_device_reference(disk->private_data);
+       mutex_lock(&tape_block_mutex);
+       device = tape_get_device(disk->private_data);
 
        if (device->required_tapemarks) {
                DBF_EVENT(2, "TBLOCK: missing tapemarks\n");
-               dev_warn(&device->cdev->dev, "Opening the tape failed because"
-                       " of missing end-of-file marks\n");
+               pr_warning("%s: Opening the tape failed because of missing "
+                          "end-of-file marks\n", dev_name(&device->cdev->dev));
                rc = -EPERM;
                goto put_device;
        }
@@ -385,12 +386,14 @@ tapeblock_open(struct block_device *bdev, fmode_t mode)
         *       is called.
         */
        tape_state_set(device, TS_BLKUSE);
+       mutex_unlock(&tape_block_mutex);
        return 0;
 
 release:
        tape_release(device);
  put_device:
        tape_put_device(device);
+       mutex_unlock(&tape_block_mutex);
        return rc;
 }
 
@@ -404,51 +407,17 @@ static int
 tapeblock_release(struct gendisk *disk, fmode_t mode)
 {
        struct tape_device *device = disk->private_data;
-
+       mutex_lock(&tape_block_mutex);
        tape_state_set(device, TS_IN_USE);
        tape_release(device);
        tape_put_device(device);
+       mutex_unlock(&tape_block_mutex);
 
        return 0;
 }
 
 /*
- * Support of some generic block device IOCTLs.
- */
-static int
-tapeblock_ioctl(
-       struct block_device *   bdev,
-       fmode_t                 mode,
-       unsigned int            command,
-       unsigned long           arg
-) {
-       int rc;
-       int minor;
-       struct gendisk *disk = bdev->bd_disk;
-       struct tape_device *device;
-
-       rc     = 0;
-       BUG_ON(!disk);
-       device = disk->private_data;
-       BUG_ON(!device);
-       minor  = MINOR(bdev->bd_dev);
-
-       DBF_LH(6, "tapeblock_ioctl(0x%0x)\n", command);
-       DBF_LH(6, "device = %d:%d\n", tapeblock_major, minor);
-
-       switch (command) {
-               /* Refuse some IOCTL calls without complaining (mount). */
-               case 0x5310:            /* CDROMMULTISESSION */
-                       rc = -EINVAL;
-                       break;
-               default:
-                       rc = -EINVAL;
-       }
-
-       return rc;
-}
-
-/*
  * Initialize block device frontend.
  */
 int