diff options
Diffstat (limited to 'drivers/block/pktcdvd.c')
-rw-r--r-- | drivers/block/pktcdvd.c | 72 |
1 files changed, 45 insertions, 27 deletions
diff --git a/drivers/block/pktcdvd.c b/drivers/block/pktcdvd.c index e45eaa264119..7e7b892f621a 100644 --- a/drivers/block/pktcdvd.c +++ b/drivers/block/pktcdvd.c | |||
@@ -1,6 +1,7 @@ | |||
1 | /* | 1 | /* |
2 | * Copyright (C) 2000 Jens Axboe <axboe@suse.de> | 2 | * Copyright (C) 2000 Jens Axboe <axboe@suse.de> |
3 | * Copyright (C) 2001-2004 Peter Osterlund <petero2@telia.com> | 3 | * Copyright (C) 2001-2004 Peter Osterlund <petero2@telia.com> |
4 | * Copyright (C) 2006 Thomas Maier <balagi@justmail.de> | ||
4 | * | 5 | * |
5 | * May be copied or modified under the terms of the GNU General Public | 6 | * May be copied or modified under the terms of the GNU General Public |
6 | * License. See linux/COPYING for more information. | 7 | * License. See linux/COPYING for more information. |
@@ -2436,36 +2437,33 @@ static struct block_device_operations pktcdvd_ops = { | |||
2436 | /* | 2437 | /* |
2437 | * Set up mapping from pktcdvd device to CD-ROM device. | 2438 | * Set up mapping from pktcdvd device to CD-ROM device. |
2438 | */ | 2439 | */ |
2439 | static int pkt_setup_dev(struct pkt_ctrl_command *ctrl_cmd) | 2440 | static int pkt_setup_dev(dev_t dev, dev_t* pkt_dev) |
2440 | { | 2441 | { |
2441 | int idx; | 2442 | int idx; |
2442 | int ret = -ENOMEM; | 2443 | int ret = -ENOMEM; |
2443 | struct pktcdvd_device *pd; | 2444 | struct pktcdvd_device *pd; |
2444 | struct gendisk *disk; | 2445 | struct gendisk *disk; |
2445 | dev_t dev = new_decode_dev(ctrl_cmd->dev); | 2446 | |
2447 | mutex_lock_nested(&ctl_mutex, SINGLE_DEPTH_NESTING); | ||
2446 | 2448 | ||
2447 | for (idx = 0; idx < MAX_WRITERS; idx++) | 2449 | for (idx = 0; idx < MAX_WRITERS; idx++) |
2448 | if (!pkt_devs[idx]) | 2450 | if (!pkt_devs[idx]) |
2449 | break; | 2451 | break; |
2450 | if (idx == MAX_WRITERS) { | 2452 | if (idx == MAX_WRITERS) { |
2451 | printk(DRIVER_NAME": max %d writers supported\n", MAX_WRITERS); | 2453 | printk(DRIVER_NAME": max %d writers supported\n", MAX_WRITERS); |
2452 | return -EBUSY; | 2454 | ret = -EBUSY; |
2455 | goto out_mutex; | ||
2453 | } | 2456 | } |
2454 | 2457 | ||
2455 | pd = kzalloc(sizeof(struct pktcdvd_device), GFP_KERNEL); | 2458 | pd = kzalloc(sizeof(struct pktcdvd_device), GFP_KERNEL); |
2456 | if (!pd) | 2459 | if (!pd) |
2457 | return ret; | 2460 | goto out_mutex; |
2458 | 2461 | ||
2459 | pd->rb_pool = mempool_create_kmalloc_pool(PKT_RB_POOL_SIZE, | 2462 | pd->rb_pool = mempool_create_kmalloc_pool(PKT_RB_POOL_SIZE, |
2460 | sizeof(struct pkt_rb_node)); | 2463 | sizeof(struct pkt_rb_node)); |
2461 | if (!pd->rb_pool) | 2464 | if (!pd->rb_pool) |
2462 | goto out_mem; | 2465 | goto out_mem; |
2463 | 2466 | ||
2464 | disk = alloc_disk(1); | ||
2465 | if (!disk) | ||
2466 | goto out_mem; | ||
2467 | pd->disk = disk; | ||
2468 | |||
2469 | INIT_LIST_HEAD(&pd->cdrw.pkt_free_list); | 2467 | INIT_LIST_HEAD(&pd->cdrw.pkt_free_list); |
2470 | INIT_LIST_HEAD(&pd->cdrw.pkt_active_list); | 2468 | INIT_LIST_HEAD(&pd->cdrw.pkt_active_list); |
2471 | spin_lock_init(&pd->cdrw.active_list_lock); | 2469 | spin_lock_init(&pd->cdrw.active_list_lock); |
@@ -2476,11 +2474,15 @@ static int pkt_setup_dev(struct pkt_ctrl_command *ctrl_cmd) | |||
2476 | init_waitqueue_head(&pd->wqueue); | 2474 | init_waitqueue_head(&pd->wqueue); |
2477 | pd->bio_queue = RB_ROOT; | 2475 | pd->bio_queue = RB_ROOT; |
2478 | 2476 | ||
2477 | disk = alloc_disk(1); | ||
2478 | if (!disk) | ||
2479 | goto out_mem; | ||
2480 | pd->disk = disk; | ||
2479 | disk->major = pktdev_major; | 2481 | disk->major = pktdev_major; |
2480 | disk->first_minor = idx; | 2482 | disk->first_minor = idx; |
2481 | disk->fops = &pktcdvd_ops; | 2483 | disk->fops = &pktcdvd_ops; |
2482 | disk->flags = GENHD_FL_REMOVABLE; | 2484 | disk->flags = GENHD_FL_REMOVABLE; |
2483 | sprintf(disk->disk_name, DRIVER_NAME"%d", idx); | 2485 | strcpy(disk->disk_name, pd->name); |
2484 | disk->private_data = pd; | 2486 | disk->private_data = pd; |
2485 | disk->queue = blk_alloc_queue(GFP_KERNEL); | 2487 | disk->queue = blk_alloc_queue(GFP_KERNEL); |
2486 | if (!disk->queue) | 2488 | if (!disk->queue) |
@@ -2492,8 +2494,12 @@ static int pkt_setup_dev(struct pkt_ctrl_command *ctrl_cmd) | |||
2492 | goto out_new_dev; | 2494 | goto out_new_dev; |
2493 | 2495 | ||
2494 | add_disk(disk); | 2496 | add_disk(disk); |
2497 | |||
2495 | pkt_devs[idx] = pd; | 2498 | pkt_devs[idx] = pd; |
2496 | ctrl_cmd->pkt_dev = new_encode_dev(pd->pkt_dev); | 2499 | if (pkt_dev) |
2500 | *pkt_dev = pd->pkt_dev; | ||
2501 | |||
2502 | mutex_unlock(&ctl_mutex); | ||
2497 | return 0; | 2503 | return 0; |
2498 | 2504 | ||
2499 | out_new_dev: | 2505 | out_new_dev: |
@@ -2504,17 +2510,22 @@ out_mem: | |||
2504 | if (pd->rb_pool) | 2510 | if (pd->rb_pool) |
2505 | mempool_destroy(pd->rb_pool); | 2511 | mempool_destroy(pd->rb_pool); |
2506 | kfree(pd); | 2512 | kfree(pd); |
2513 | out_mutex: | ||
2514 | mutex_unlock(&ctl_mutex); | ||
2515 | printk(DRIVER_NAME": setup of pktcdvd device failed\n"); | ||
2507 | return ret; | 2516 | return ret; |
2508 | } | 2517 | } |
2509 | 2518 | ||
2510 | /* | 2519 | /* |
2511 | * Tear down mapping from pktcdvd device to CD-ROM device. | 2520 | * Tear down mapping from pktcdvd device to CD-ROM device. |
2512 | */ | 2521 | */ |
2513 | static int pkt_remove_dev(struct pkt_ctrl_command *ctrl_cmd) | 2522 | static int pkt_remove_dev(dev_t pkt_dev) |
2514 | { | 2523 | { |
2515 | struct pktcdvd_device *pd; | 2524 | struct pktcdvd_device *pd; |
2516 | int idx; | 2525 | int idx; |
2517 | dev_t pkt_dev = new_decode_dev(ctrl_cmd->pkt_dev); | 2526 | int ret = 0; |
2527 | |||
2528 | mutex_lock_nested(&ctl_mutex, SINGLE_DEPTH_NESTING); | ||
2518 | 2529 | ||
2519 | for (idx = 0; idx < MAX_WRITERS; idx++) { | 2530 | for (idx = 0; idx < MAX_WRITERS; idx++) { |
2520 | pd = pkt_devs[idx]; | 2531 | pd = pkt_devs[idx]; |
@@ -2523,12 +2534,14 @@ static int pkt_remove_dev(struct pkt_ctrl_command *ctrl_cmd) | |||
2523 | } | 2534 | } |
2524 | if (idx == MAX_WRITERS) { | 2535 | if (idx == MAX_WRITERS) { |
2525 | DPRINTK(DRIVER_NAME": dev not setup\n"); | 2536 | DPRINTK(DRIVER_NAME": dev not setup\n"); |
2526 | return -ENXIO; | 2537 | ret = -ENXIO; |
2538 | goto out; | ||
2527 | } | 2539 | } |
2528 | 2540 | ||
2529 | if (pd->refcnt > 0) | 2541 | if (pd->refcnt > 0) { |
2530 | return -EBUSY; | 2542 | ret = -EBUSY; |
2531 | 2543 | goto out; | |
2544 | } | ||
2532 | if (!IS_ERR(pd->cdrw.thread)) | 2545 | if (!IS_ERR(pd->cdrw.thread)) |
2533 | kthread_stop(pd->cdrw.thread); | 2546 | kthread_stop(pd->cdrw.thread); |
2534 | 2547 | ||
@@ -2547,12 +2560,19 @@ static int pkt_remove_dev(struct pkt_ctrl_command *ctrl_cmd) | |||
2547 | 2560 | ||
2548 | /* This is safe: open() is still holding a reference. */ | 2561 | /* This is safe: open() is still holding a reference. */ |
2549 | module_put(THIS_MODULE); | 2562 | module_put(THIS_MODULE); |
2550 | return 0; | 2563 | |
2564 | out: | ||
2565 | mutex_unlock(&ctl_mutex); | ||
2566 | return ret; | ||
2551 | } | 2567 | } |
2552 | 2568 | ||
2553 | static void pkt_get_status(struct pkt_ctrl_command *ctrl_cmd) | 2569 | static void pkt_get_status(struct pkt_ctrl_command *ctrl_cmd) |
2554 | { | 2570 | { |
2555 | struct pktcdvd_device *pd = pkt_find_dev_from_minor(ctrl_cmd->dev_index); | 2571 | struct pktcdvd_device *pd; |
2572 | |||
2573 | mutex_lock_nested(&ctl_mutex, SINGLE_DEPTH_NESTING); | ||
2574 | |||
2575 | pd = pkt_find_dev_from_minor(ctrl_cmd->dev_index); | ||
2556 | if (pd) { | 2576 | if (pd) { |
2557 | ctrl_cmd->dev = new_encode_dev(pd->bdev->bd_dev); | 2577 | ctrl_cmd->dev = new_encode_dev(pd->bdev->bd_dev); |
2558 | ctrl_cmd->pkt_dev = new_encode_dev(pd->pkt_dev); | 2578 | ctrl_cmd->pkt_dev = new_encode_dev(pd->pkt_dev); |
@@ -2561,6 +2581,8 @@ static void pkt_get_status(struct pkt_ctrl_command *ctrl_cmd) | |||
2561 | ctrl_cmd->pkt_dev = 0; | 2581 | ctrl_cmd->pkt_dev = 0; |
2562 | } | 2582 | } |
2563 | ctrl_cmd->num_devices = MAX_WRITERS; | 2583 | ctrl_cmd->num_devices = MAX_WRITERS; |
2584 | |||
2585 | mutex_unlock(&ctl_mutex); | ||
2564 | } | 2586 | } |
2565 | 2587 | ||
2566 | static int pkt_ctl_ioctl(struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg) | 2588 | static int pkt_ctl_ioctl(struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg) |
@@ -2568,6 +2590,7 @@ static int pkt_ctl_ioctl(struct inode *inode, struct file *file, unsigned int cm | |||
2568 | void __user *argp = (void __user *)arg; | 2590 | void __user *argp = (void __user *)arg; |
2569 | struct pkt_ctrl_command ctrl_cmd; | 2591 | struct pkt_ctrl_command ctrl_cmd; |
2570 | int ret = 0; | 2592 | int ret = 0; |
2593 | dev_t pkt_dev = 0; | ||
2571 | 2594 | ||
2572 | if (cmd != PACKET_CTRL_CMD) | 2595 | if (cmd != PACKET_CTRL_CMD) |
2573 | return -ENOTTY; | 2596 | return -ENOTTY; |
@@ -2579,21 +2602,16 @@ static int pkt_ctl_ioctl(struct inode *inode, struct file *file, unsigned int cm | |||
2579 | case PKT_CTRL_CMD_SETUP: | 2602 | case PKT_CTRL_CMD_SETUP: |
2580 | if (!capable(CAP_SYS_ADMIN)) | 2603 | if (!capable(CAP_SYS_ADMIN)) |
2581 | return -EPERM; | 2604 | return -EPERM; |
2582 | mutex_lock_nested(&ctl_mutex, SINGLE_DEPTH_NESTING); | 2605 | ret = pkt_setup_dev(new_decode_dev(ctrl_cmd.dev), &pkt_dev); |
2583 | ret = pkt_setup_dev(&ctrl_cmd); | 2606 | ctrl_cmd.pkt_dev = new_encode_dev(pkt_dev); |
2584 | mutex_unlock(&ctl_mutex); | ||
2585 | break; | 2607 | break; |
2586 | case PKT_CTRL_CMD_TEARDOWN: | 2608 | case PKT_CTRL_CMD_TEARDOWN: |
2587 | if (!capable(CAP_SYS_ADMIN)) | 2609 | if (!capable(CAP_SYS_ADMIN)) |
2588 | return -EPERM; | 2610 | return -EPERM; |
2589 | mutex_lock_nested(&ctl_mutex, SINGLE_DEPTH_NESTING); | 2611 | ret = pkt_remove_dev(new_decode_dev(ctrl_cmd.pkt_dev)); |
2590 | ret = pkt_remove_dev(&ctrl_cmd); | ||
2591 | mutex_unlock(&ctl_mutex); | ||
2592 | break; | 2612 | break; |
2593 | case PKT_CTRL_CMD_STATUS: | 2613 | case PKT_CTRL_CMD_STATUS: |
2594 | mutex_lock_nested(&ctl_mutex, SINGLE_DEPTH_NESTING); | ||
2595 | pkt_get_status(&ctrl_cmd); | 2614 | pkt_get_status(&ctrl_cmd); |
2596 | mutex_unlock(&ctl_mutex); | ||
2597 | break; | 2615 | break; |
2598 | default: | 2616 | default: |
2599 | return -ENOTTY; | 2617 | return -ENOTTY; |