aboutsummaryrefslogtreecommitdiff
path: root/drivers/s390/char/tape_char.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/s390/char/tape_char.c')
-rw-r--r--drivers/s390/char/tape_char.c110
1 files changed, 56 insertions, 54 deletions
diff --git a/drivers/s390/char/tape_char.c b/drivers/s390/char/tape_char.c
index b830a8cbef7..6dc60725de9 100644
--- a/drivers/s390/char/tape_char.c
+++ b/drivers/s390/char/tape_char.c
@@ -1,19 +1,22 @@
/*
- * drivers/s390/char/tape_char.c
* character device frontend for tape device driver
*
* S390 and zSeries version
- * Copyright IBM Corp. 2001,2006
+ * Copyright IBM Corp. 2001, 2006
* Author(s): Carsten Otte <cotte@de.ibm.com>
* Michael Holzheu <holzheu@de.ibm.com>
* Tuan Ngo-Anh <ngoanh@de.ibm.com>
* Martin Schwidefsky <schwidefsky@de.ibm.com>
*/
+#define KMSG_COMPONENT "tape"
+#define pr_fmt(fmt) KMSG_COMPONENT ": " fmt
+
#include <linux/module.h>
#include <linux/types.h>
#include <linux/proc_fs.h>
#include <linux/mtio.h>
+#include <linux/compat.h>
#include <asm/uaccess.h>
@@ -23,8 +26,6 @@
#include "tape_std.h"
#include "tape_class.h"
-#define PRINTK_HEADER "TAPE_CHAR: "
-
#define TAPECHAR_MAJOR 0 /* get dynamic major */
/*
@@ -34,20 +35,23 @@ static ssize_t tapechar_read(struct file *, char __user *, size_t, loff_t *);
static ssize_t tapechar_write(struct file *, const char __user *, size_t, loff_t *);
static int tapechar_open(struct inode *,struct file *);
static int tapechar_release(struct inode *,struct file *);
-static int tapechar_ioctl(struct inode *, struct file *, unsigned int,
- unsigned long);
-static long tapechar_compat_ioctl(struct file *, unsigned int,
- unsigned long);
+static long tapechar_ioctl(struct file *, unsigned int, unsigned long);
+#ifdef CONFIG_COMPAT
+static long tapechar_compat_ioctl(struct file *, unsigned int, unsigned long);
+#endif
static const struct file_operations tape_fops =
{
.owner = THIS_MODULE,
.read = tapechar_read,
.write = tapechar_write,
- .ioctl = tapechar_ioctl,
+ .unlocked_ioctl = tapechar_ioctl,
+#ifdef CONFIG_COMPAT
.compat_ioctl = tapechar_compat_ioctl,
+#endif
.open = tapechar_open,
.release = tapechar_release,
+ .llseek = no_llseek,
};
static int tapechar_major = TAPECHAR_MAJOR;
@@ -83,9 +87,9 @@ tapechar_setup_device(struct tape_device * device)
void
tapechar_cleanup_device(struct tape_device *device)
{
- unregister_tape_dev(device->rt);
+ unregister_tape_dev(&device->cdev->dev, device->rt);
device->rt = NULL;
- unregister_tape_dev(device->nt);
+ unregister_tape_dev(&device->cdev->dev, device->nt);
device->nt = NULL;
}
@@ -101,14 +105,12 @@ tapechar_check_idalbuffer(struct tape_device *device, size_t block_size)
if (block_size > MAX_BLOCKSIZE) {
DBF_EVENT(3, "Invalid blocksize (%zd > %d)\n",
block_size, MAX_BLOCKSIZE);
- PRINT_ERR("Invalid blocksize (%zd> %d)\n",
- block_size, MAX_BLOCKSIZE);
return -EINVAL;
}
/* The current idal buffer is not correct. Allocate a new one. */
new = idal_buffer_alloc(block_size, 0);
- if (new == NULL)
+ if (IS_ERR(new))
return -ENOMEM;
if (device->char_data.idal_buf != NULL)
@@ -136,7 +138,7 @@ tapechar_read(struct file *filp, char __user *data, size_t count, loff_t *ppos)
/*
* If the tape isn't terminated yet, do it now. And since we then
* are at the end of the tape there wouldn't be anything to read
- * anyways. So we return immediatly.
+ * anyways. So we return immediately.
*/
if(device->required_tapemarks) {
return tape_std_terminate_write(device);
@@ -158,11 +160,6 @@ tapechar_read(struct file *filp, char __user *data, size_t count, loff_t *ppos)
if (rc)
return rc;
-#ifdef CONFIG_S390_TAPE_BLOCK
- /* Changes position. */
- device->blk_data.medium_changed = 1;
-#endif
-
DBF_EVENT(6, "TCHAR:nbytes: %lx\n", block_size);
/* Let the discipline build the ccw chain. */
request = device->discipline->read_block(device, block_size);
@@ -173,7 +170,6 @@ tapechar_read(struct file *filp, char __user *data, size_t count, loff_t *ppos)
if (rc == 0) {
rc = block_size - request->rescnt;
DBF_EVENT(6, "TCHAR:rbytes: %x\n", rc);
- filp->f_pos += rc;
/* Copy data from idal buffer to user space. */
if (idal_buffer_to_user(device->char_data.idal_buf,
data, rc) != 0)
@@ -216,11 +212,6 @@ tapechar_write(struct file *filp, const char __user *data, size_t count, loff_t
if (rc)
return rc;
-#ifdef CONFIG_S390_TAPE_BLOCK
- /* Changes position. */
- device->blk_data.medium_changed = 1;
-#endif
-
DBF_EVENT(6,"TCHAR:nbytes: %lx\n", block_size);
DBF_EVENT(6, "TCHAR:nblocks: %x\n", nblocks);
/* Let the discipline build the ccw chain. */
@@ -241,7 +232,6 @@ tapechar_write(struct file *filp, const char __user *data, size_t count, loff_t
break;
DBF_EVENT(6, "TCHAR:wbytes: %lx\n",
block_size - request->rescnt);
- filp->f_pos += block_size - request->rescnt;
written += block_size - request->rescnt;
if (request->rescnt != 0)
break;
@@ -283,26 +273,25 @@ tapechar_open (struct inode *inode, struct file *filp)
int minor, rc;
DBF_EVENT(6, "TCHAR:open: %i:%i\n",
- imajor(filp->f_path.dentry->d_inode),
- iminor(filp->f_path.dentry->d_inode));
+ imajor(file_inode(filp)),
+ iminor(file_inode(filp)));
- if (imajor(filp->f_path.dentry->d_inode) != tapechar_major)
+ if (imajor(file_inode(filp)) != tapechar_major)
return -ENODEV;
- minor = iminor(filp->f_path.dentry->d_inode);
- device = tape_get_device(minor / TAPE_MINORS_PER_DEV);
+ minor = iminor(file_inode(filp));
+ device = tape_find_device(minor / TAPE_MINORS_PER_DEV);
if (IS_ERR(device)) {
- DBF_EVENT(3, "TCHAR:open: tape_get_device() failed\n");
+ DBF_EVENT(3, "TCHAR:open: tape_find_device() failed\n");
return PTR_ERR(device);
}
-
rc = tape_open(device);
if (rc == 0) {
filp->private_data = device;
- return nonseekable_open(inode, filp);
- }
- tape_put_device(device);
+ nonseekable_open(inode, filp);
+ } else
+ tape_put_device(device);
return rc;
}
@@ -340,7 +329,8 @@ tapechar_release(struct inode *inode, struct file *filp)
device->char_data.idal_buf = NULL;
}
tape_release(device);
- filp->private_data = tape_put_device(device);
+ filp->private_data = NULL;
+ tape_put_device(device);
return 0;
}
@@ -349,16 +339,11 @@ tapechar_release(struct inode *inode, struct file *filp)
* Tape device io controls.
*/
static int
-tapechar_ioctl(struct inode *inp, struct file *filp,
- unsigned int no, unsigned long data)
+__tapechar_ioctl(struct tape_device *device,
+ unsigned int no, unsigned long data)
{
- struct tape_device *device;
int rc;
- DBF_EVENT(6, "TCHAR:ioct\n");
-
- device = (struct tape_device *) filp->private_data;
-
if (no == MTIOCTOP) {
struct mtop op;
@@ -383,9 +368,6 @@ tapechar_ioctl(struct inode *inp, struct file *filp,
case MTBSFM:
case MTFSFM:
case MTSEEK:
-#ifdef CONFIG_S390_TAPE_BLOCK
- device->blk_data.medium_changed = 1;
-#endif
if (device->required_tapemarks)
tape_std_terminate_write(device);
default:
@@ -451,21 +433,44 @@ tapechar_ioctl(struct inode *inp, struct file *filp,
}
static long
+tapechar_ioctl(struct file *filp, unsigned int no, unsigned long data)
+{
+ struct tape_device *device;
+ long rc;
+
+ DBF_EVENT(6, "TCHAR:ioct\n");
+
+ device = (struct tape_device *) filp->private_data;
+ mutex_lock(&device->mutex);
+ rc = __tapechar_ioctl(device, no, data);
+ mutex_unlock(&device->mutex);
+ return rc;
+}
+
+#ifdef CONFIG_COMPAT
+static long
tapechar_compat_ioctl(struct file *filp, unsigned int no, unsigned long data)
{
struct tape_device *device = filp->private_data;
int rval = -ENOIOCTLCMD;
+ unsigned long argp;
+ /* The 'arg' argument of any ioctl function may only be used for
+ * pointers because of the compat pointer conversion.
+ * Consider this when adding new ioctls.
+ */
+ argp = (unsigned long) compat_ptr(data);
if (device->discipline->ioctl_fn) {
- lock_kernel();
- rval = device->discipline->ioctl_fn(device, no, data);
- unlock_kernel();
+ mutex_lock(&device->mutex);
+ rval = device->discipline->ioctl_fn(device, no, argp);
+ mutex_unlock(&device->mutex);
if (rval == -EINVAL)
rval = -ENOIOCTLCMD;
}
return rval;
}
+#endif /* CONFIG_COMPAT */
/*
* Initialize character device frontend.
@@ -479,7 +484,6 @@ tapechar_init (void)
return -1;
tapechar_major = MAJOR(dev);
- PRINT_INFO("tape gets major %d for character devices\n", MAJOR(dev));
return 0;
}
@@ -490,7 +494,5 @@ tapechar_init (void)
void
tapechar_exit(void)
{
- PRINT_INFO("tape releases major %d for character devices\n",
- tapechar_major);
unregister_chrdev_region(MKDEV(tapechar_major, 0), 256);
}