diff options
author | Andrea Bastoni <bastoni@cs.unc.edu> | 2010-05-30 19:16:45 -0400 |
---|---|---|
committer | Andrea Bastoni <bastoni@cs.unc.edu> | 2010-05-30 19:16:45 -0400 |
commit | ada47b5fe13d89735805b566185f4885f5a3f750 (patch) | |
tree | 644b88f8a71896307d71438e9b3af49126ffb22b /drivers/s390/char/tape_char.c | |
parent | 43e98717ad40a4ae64545b5ba047c7b86aa44f4f (diff) | |
parent | 3280f21d43ee541f97f8cda5792150d2dbec20d5 (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.c | 75 |
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 *); | |||
33 | static ssize_t tapechar_write(struct file *, const char __user *, size_t, loff_t *); | 37 | static ssize_t tapechar_write(struct file *, const char __user *, size_t, loff_t *); |
34 | static int tapechar_open(struct inode *,struct file *); | 38 | static int tapechar_open(struct inode *,struct file *); |
35 | static int tapechar_release(struct inode *,struct file *); | 39 | static int tapechar_release(struct inode *,struct file *); |
36 | static int tapechar_ioctl(struct inode *, struct file *, unsigned int, | 40 | static long tapechar_ioctl(struct file *, unsigned int, unsigned long); |
37 | unsigned long); | 41 | #ifdef CONFIG_COMPAT |
38 | static long tapechar_compat_ioctl(struct file *, unsigned int, | 42 | static long tapechar_compat_ioctl(struct file *, unsigned int, unsigned long); |
39 | unsigned long); | 43 | #endif |
40 | 44 | ||
41 | static const struct file_operations tape_fops = | 45 | static 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 | ||
307 | out: | ||
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 | */ |
353 | static int | 352 | static int |
354 | tapechar_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 | ||
455 | static long | 449 | static long |
450 | tapechar_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 | ||
465 | static long | ||
456 | tapechar_compat_ioctl(struct file *filp, unsigned int no, unsigned long data) | 466 | tapechar_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. |