aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/s390/char/tape_char.c
diff options
context:
space:
mode:
authorAndrea Bastoni <bastoni@cs.unc.edu>2010-05-30 19:16:45 -0400
committerAndrea Bastoni <bastoni@cs.unc.edu>2010-05-30 19:16:45 -0400
commitada47b5fe13d89735805b566185f4885f5a3f750 (patch)
tree644b88f8a71896307d71438e9b3af49126ffb22b /drivers/s390/char/tape_char.c
parent43e98717ad40a4ae64545b5ba047c7b86aa44f4f (diff)
parent3280f21d43ee541f97f8cda5792150d2dbec20d5 (diff)
Merge branch 'wip-2.6.34' into old-private-masterarchived-private-master
Diffstat (limited to 'drivers/s390/char/tape_char.c')
-rw-r--r--drivers/s390/char/tape_char.c75
1 files changed, 46 insertions, 29 deletions
diff --git a/drivers/s390/char/tape_char.c b/drivers/s390/char/tape_char.c
index 31566c55adfe..539045acaad4 100644
--- a/drivers/s390/char/tape_char.c
+++ b/drivers/s390/char/tape_char.c
@@ -10,11 +10,15 @@
10 * Martin Schwidefsky <schwidefsky@de.ibm.com> 10 * Martin Schwidefsky <schwidefsky@de.ibm.com>
11 */ 11 */
12 12
13#define KMSG_COMPONENT "tape"
14#define pr_fmt(fmt) KMSG_COMPONENT ": " fmt
15
13#include <linux/module.h> 16#include <linux/module.h>
14#include <linux/types.h> 17#include <linux/types.h>
15#include <linux/proc_fs.h> 18#include <linux/proc_fs.h>
16#include <linux/mtio.h> 19#include <linux/mtio.h>
17#include <linux/smp_lock.h> 20#include <linux/smp_lock.h>
21#include <linux/compat.h>
18 22
19#include <asm/uaccess.h> 23#include <asm/uaccess.h>
20 24
@@ -33,18 +37,20 @@ static ssize_t tapechar_read(struct file *, char __user *, size_t, loff_t *);
33static ssize_t tapechar_write(struct file *, const char __user *, size_t, loff_t *); 37static ssize_t tapechar_write(struct file *, const char __user *, size_t, loff_t *);
34static int tapechar_open(struct inode *,struct file *); 38static int tapechar_open(struct inode *,struct file *);
35static int tapechar_release(struct inode *,struct file *); 39static int tapechar_release(struct inode *,struct file *);
36static int tapechar_ioctl(struct inode *, struct file *, unsigned int, 40static long tapechar_ioctl(struct file *, unsigned int, unsigned long);
37 unsigned long); 41#ifdef CONFIG_COMPAT
38static long tapechar_compat_ioctl(struct file *, unsigned int, 42static long tapechar_compat_ioctl(struct file *, unsigned int, unsigned long);
39 unsigned long); 43#endif
40 44
41static const struct file_operations tape_fops = 45static const struct file_operations tape_fops =
42{ 46{
43 .owner = THIS_MODULE, 47 .owner = THIS_MODULE,
44 .read = tapechar_read, 48 .read = tapechar_read,
45 .write = tapechar_write, 49 .write = tapechar_write,
46 .ioctl = tapechar_ioctl, 50 .unlocked_ioctl = tapechar_ioctl,
51#ifdef CONFIG_COMPAT
47 .compat_ioctl = tapechar_compat_ioctl, 52 .compat_ioctl = tapechar_compat_ioctl,
53#endif
48 .open = tapechar_open, 54 .open = tapechar_open,
49 .release = tapechar_release, 55 .release = tapechar_release,
50}; 56};
@@ -170,7 +176,6 @@ tapechar_read(struct file *filp, char __user *data, size_t count, loff_t *ppos)
170 if (rc == 0) { 176 if (rc == 0) {
171 rc = block_size - request->rescnt; 177 rc = block_size - request->rescnt;
172 DBF_EVENT(6, "TCHAR:rbytes: %x\n", rc); 178 DBF_EVENT(6, "TCHAR:rbytes: %x\n", rc);
173 filp->f_pos += rc;
174 /* Copy data from idal buffer to user space. */ 179 /* Copy data from idal buffer to user space. */
175 if (idal_buffer_to_user(device->char_data.idal_buf, 180 if (idal_buffer_to_user(device->char_data.idal_buf,
176 data, rc) != 0) 181 data, rc) != 0)
@@ -238,7 +243,6 @@ tapechar_write(struct file *filp, const char __user *data, size_t count, loff_t
238 break; 243 break;
239 DBF_EVENT(6, "TCHAR:wbytes: %lx\n", 244 DBF_EVENT(6, "TCHAR:wbytes: %lx\n",
240 block_size - request->rescnt); 245 block_size - request->rescnt);
241 filp->f_pos += block_size - request->rescnt;
242 written += block_size - request->rescnt; 246 written += block_size - request->rescnt;
243 if (request->rescnt != 0) 247 if (request->rescnt != 0)
244 break; 248 break;
@@ -286,26 +290,20 @@ tapechar_open (struct inode *inode, struct file *filp)
286 if (imajor(filp->f_path.dentry->d_inode) != tapechar_major) 290 if (imajor(filp->f_path.dentry->d_inode) != tapechar_major)
287 return -ENODEV; 291 return -ENODEV;
288 292
289 lock_kernel();
290 minor = iminor(filp->f_path.dentry->d_inode); 293 minor = iminor(filp->f_path.dentry->d_inode);
291 device = tape_get_device(minor / TAPE_MINORS_PER_DEV); 294 device = tape_find_device(minor / TAPE_MINORS_PER_DEV);
292 if (IS_ERR(device)) { 295 if (IS_ERR(device)) {
293 DBF_EVENT(3, "TCHAR:open: tape_get_device() failed\n"); 296 DBF_EVENT(3, "TCHAR:open: tape_find_device() failed\n");
294 rc = PTR_ERR(device); 297 return PTR_ERR(device);
295 goto out;
296 } 298 }
297 299
298
299 rc = tape_open(device); 300 rc = tape_open(device);
300 if (rc == 0) { 301 if (rc == 0) {
301 filp->private_data = device; 302 filp->private_data = device;
302 rc = nonseekable_open(inode, filp); 303 nonseekable_open(inode, filp);
303 } 304 } else
304 else
305 tape_put_device(device); 305 tape_put_device(device);
306 306
307out:
308 unlock_kernel();
309 return rc; 307 return rc;
310} 308}
311 309
@@ -342,7 +340,8 @@ tapechar_release(struct inode *inode, struct file *filp)
342 device->char_data.idal_buf = NULL; 340 device->char_data.idal_buf = NULL;
343 } 341 }
344 tape_release(device); 342 tape_release(device);
345 filp->private_data = tape_put_device(device); 343 filp->private_data = NULL;
344 tape_put_device(device);
346 345
347 return 0; 346 return 0;
348} 347}
@@ -351,16 +350,11 @@ tapechar_release(struct inode *inode, struct file *filp)
351 * Tape device io controls. 350 * Tape device io controls.
352 */ 351 */
353static int 352static int
354tapechar_ioctl(struct inode *inp, struct file *filp, 353__tapechar_ioctl(struct tape_device *device,
355 unsigned int no, unsigned long data) 354 unsigned int no, unsigned long data)
356{ 355{
357 struct tape_device *device;
358 int rc; 356 int rc;
359 357
360 DBF_EVENT(6, "TCHAR:ioct\n");
361
362 device = (struct tape_device *) filp->private_data;
363
364 if (no == MTIOCTOP) { 358 if (no == MTIOCTOP) {
365 struct mtop op; 359 struct mtop op;
366 360
@@ -453,21 +447,44 @@ tapechar_ioctl(struct inode *inp, struct file *filp,
453} 447}
454 448
455static long 449static long
450tapechar_ioctl(struct file *filp, unsigned int no, unsigned long data)
451{
452 struct tape_device *device;
453 long rc;
454
455 DBF_EVENT(6, "TCHAR:ioct\n");
456
457 device = (struct tape_device *) filp->private_data;
458 mutex_lock(&device->mutex);
459 rc = __tapechar_ioctl(device, no, data);
460 mutex_unlock(&device->mutex);
461 return rc;
462}
463
464#ifdef CONFIG_COMPAT
465static long
456tapechar_compat_ioctl(struct file *filp, unsigned int no, unsigned long data) 466tapechar_compat_ioctl(struct file *filp, unsigned int no, unsigned long data)
457{ 467{
458 struct tape_device *device = filp->private_data; 468 struct tape_device *device = filp->private_data;
459 int rval = -ENOIOCTLCMD; 469 int rval = -ENOIOCTLCMD;
470 unsigned long argp;
460 471
472 /* The 'arg' argument of any ioctl function may only be used for
473 * pointers because of the compat pointer conversion.
474 * Consider this when adding new ioctls.
475 */
476 argp = (unsigned long) compat_ptr(data);
461 if (device->discipline->ioctl_fn) { 477 if (device->discipline->ioctl_fn) {
462 lock_kernel(); 478 mutex_lock(&device->mutex);
463 rval = device->discipline->ioctl_fn(device, no, data); 479 rval = device->discipline->ioctl_fn(device, no, argp);
464 unlock_kernel(); 480 mutex_unlock(&device->mutex);
465 if (rval == -EINVAL) 481 if (rval == -EINVAL)
466 rval = -ENOIOCTLCMD; 482 rval = -ENOIOCTLCMD;
467 } 483 }
468 484
469 return rval; 485 return rval;
470} 486}
487#endif /* CONFIG_COMPAT */
471 488
472/* 489/*
473 * Initialize character device frontend. 490 * Initialize character device frontend.