aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/block/nbd.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/block/nbd.c')
-rw-r--r--drivers/block/nbd.c171
1 files changed, 117 insertions, 54 deletions
diff --git a/drivers/block/nbd.c b/drivers/block/nbd.c
index f75bda16a1fc..ad98dda6037d 100644
--- a/drivers/block/nbd.c
+++ b/drivers/block/nbd.c
@@ -29,6 +29,7 @@
29#include <linux/kernel.h> 29#include <linux/kernel.h>
30#include <net/sock.h> 30#include <net/sock.h>
31#include <linux/net.h> 31#include <linux/net.h>
32#include <linux/kthread.h>
32 33
33#include <asm/uaccess.h> 34#include <asm/uaccess.h>
34#include <asm/system.h> 35#include <asm/system.h>
@@ -55,6 +56,7 @@ static unsigned int debugflags;
55 56
56static unsigned int nbds_max = 16; 57static unsigned int nbds_max = 16;
57static struct nbd_device *nbd_dev; 58static struct nbd_device *nbd_dev;
59static int max_part;
58 60
59/* 61/*
60 * Use just one lock (or at most 1 per NIC). Two arguments for this: 62 * Use just one lock (or at most 1 per NIC). Two arguments for this:
@@ -337,7 +339,7 @@ static struct request *nbd_read_stat(struct nbd_device *lo)
337 } 339 }
338 340
339 req = nbd_find_request(lo, *(struct request **)reply.handle); 341 req = nbd_find_request(lo, *(struct request **)reply.handle);
340 if (unlikely(IS_ERR(req))) { 342 if (IS_ERR(req)) {
341 result = PTR_ERR(req); 343 result = PTR_ERR(req);
342 if (result != -ENOENT) 344 if (result != -ENOENT)
343 goto harderror; 345 goto harderror;
@@ -441,6 +443,85 @@ static void nbd_clear_que(struct nbd_device *lo)
441} 443}
442 444
443 445
446static void nbd_handle_req(struct nbd_device *lo, struct request *req)
447{
448 if (!blk_fs_request(req))
449 goto error_out;
450
451 nbd_cmd(req) = NBD_CMD_READ;
452 if (rq_data_dir(req) == WRITE) {
453 nbd_cmd(req) = NBD_CMD_WRITE;
454 if (lo->flags & NBD_READ_ONLY) {
455 printk(KERN_ERR "%s: Write on read-only\n",
456 lo->disk->disk_name);
457 goto error_out;
458 }
459 }
460
461 req->errors = 0;
462
463 mutex_lock(&lo->tx_lock);
464 if (unlikely(!lo->sock)) {
465 mutex_unlock(&lo->tx_lock);
466 printk(KERN_ERR "%s: Attempted send on closed socket\n",
467 lo->disk->disk_name);
468 req->errors++;
469 nbd_end_request(req);
470 return;
471 }
472
473 lo->active_req = req;
474
475 if (nbd_send_req(lo, req) != 0) {
476 printk(KERN_ERR "%s: Request send failed\n",
477 lo->disk->disk_name);
478 req->errors++;
479 nbd_end_request(req);
480 } else {
481 spin_lock(&lo->queue_lock);
482 list_add(&req->queuelist, &lo->queue_head);
483 spin_unlock(&lo->queue_lock);
484 }
485
486 lo->active_req = NULL;
487 mutex_unlock(&lo->tx_lock);
488 wake_up_all(&lo->active_wq);
489
490 return;
491
492error_out:
493 req->errors++;
494 nbd_end_request(req);
495}
496
497static int nbd_thread(void *data)
498{
499 struct nbd_device *lo = data;
500 struct request *req;
501
502 set_user_nice(current, -20);
503 while (!kthread_should_stop() || !list_empty(&lo->waiting_queue)) {
504 /* wait for something to do */
505 wait_event_interruptible(lo->waiting_wq,
506 kthread_should_stop() ||
507 !list_empty(&lo->waiting_queue));
508
509 /* extract request */
510 if (list_empty(&lo->waiting_queue))
511 continue;
512
513 spin_lock_irq(&lo->queue_lock);
514 req = list_entry(lo->waiting_queue.next, struct request,
515 queuelist);
516 list_del_init(&req->queuelist);
517 spin_unlock_irq(&lo->queue_lock);
518
519 /* handle request */
520 nbd_handle_req(lo, req);
521 }
522 return 0;
523}
524
444/* 525/*
445 * We always wait for result of write, for now. It would be nice to make it optional 526 * We always wait for result of write, for now. It would be nice to make it optional
446 * in future 527 * in future
@@ -456,65 +537,23 @@ static void do_nbd_request(struct request_queue * q)
456 struct nbd_device *lo; 537 struct nbd_device *lo;
457 538
458 blkdev_dequeue_request(req); 539 blkdev_dequeue_request(req);
540
541 spin_unlock_irq(q->queue_lock);
542
459 dprintk(DBG_BLKDEV, "%s: request %p: dequeued (flags=%x)\n", 543 dprintk(DBG_BLKDEV, "%s: request %p: dequeued (flags=%x)\n",
460 req->rq_disk->disk_name, req, req->cmd_type); 544 req->rq_disk->disk_name, req, req->cmd_type);
461 545
462 if (!blk_fs_request(req))
463 goto error_out;
464
465 lo = req->rq_disk->private_data; 546 lo = req->rq_disk->private_data;
466 547
467 BUG_ON(lo->magic != LO_MAGIC); 548 BUG_ON(lo->magic != LO_MAGIC);
468 549
469 nbd_cmd(req) = NBD_CMD_READ; 550 spin_lock_irq(&lo->queue_lock);
470 if (rq_data_dir(req) == WRITE) { 551 list_add_tail(&req->queuelist, &lo->waiting_queue);
471 nbd_cmd(req) = NBD_CMD_WRITE; 552 spin_unlock_irq(&lo->queue_lock);
472 if (lo->flags & NBD_READ_ONLY) {
473 printk(KERN_ERR "%s: Write on read-only\n",
474 lo->disk->disk_name);
475 goto error_out;
476 }
477 }
478
479 req->errors = 0;
480 spin_unlock_irq(q->queue_lock);
481
482 mutex_lock(&lo->tx_lock);
483 if (unlikely(!lo->sock)) {
484 mutex_unlock(&lo->tx_lock);
485 printk(KERN_ERR "%s: Attempted send on closed socket\n",
486 lo->disk->disk_name);
487 req->errors++;
488 nbd_end_request(req);
489 spin_lock_irq(q->queue_lock);
490 continue;
491 }
492
493 lo->active_req = req;
494 553
495 if (nbd_send_req(lo, req) != 0) { 554 wake_up(&lo->waiting_wq);
496 printk(KERN_ERR "%s: Request send failed\n",
497 lo->disk->disk_name);
498 req->errors++;
499 nbd_end_request(req);
500 } else {
501 spin_lock(&lo->queue_lock);
502 list_add(&req->queuelist, &lo->queue_head);
503 spin_unlock(&lo->queue_lock);
504 }
505
506 lo->active_req = NULL;
507 mutex_unlock(&lo->tx_lock);
508 wake_up_all(&lo->active_wq);
509 555
510 spin_lock_irq(q->queue_lock); 556 spin_lock_irq(q->queue_lock);
511 continue;
512
513error_out:
514 req->errors++;
515 spin_unlock(q->queue_lock);
516 nbd_end_request(req);
517 spin_lock(q->queue_lock);
518 } 557 }
519} 558}
520 559
@@ -524,6 +563,7 @@ static int nbd_ioctl(struct inode *inode, struct file *file,
524 struct nbd_device *lo = inode->i_bdev->bd_disk->private_data; 563 struct nbd_device *lo = inode->i_bdev->bd_disk->private_data;
525 int error; 564 int error;
526 struct request sreq ; 565 struct request sreq ;
566 struct task_struct *thread;
527 567
528 if (!capable(CAP_SYS_ADMIN)) 568 if (!capable(CAP_SYS_ADMIN))
529 return -EPERM; 569 return -EPERM;
@@ -572,10 +612,13 @@ static int nbd_ioctl(struct inode *inode, struct file *file,
572 error = -EINVAL; 612 error = -EINVAL;
573 file = fget(arg); 613 file = fget(arg);
574 if (file) { 614 if (file) {
615 struct block_device *bdev = inode->i_bdev;
575 inode = file->f_path.dentry->d_inode; 616 inode = file->f_path.dentry->d_inode;
576 if (S_ISSOCK(inode->i_mode)) { 617 if (S_ISSOCK(inode->i_mode)) {
577 lo->file = file; 618 lo->file = file;
578 lo->sock = SOCKET_I(inode); 619 lo->sock = SOCKET_I(inode);
620 if (max_part > 0)
621 bdev->bd_invalidated = 1;
579 error = 0; 622 error = 0;
580 } else { 623 } else {
581 fput(file); 624 fput(file);
@@ -607,7 +650,12 @@ static int nbd_ioctl(struct inode *inode, struct file *file,
607 case NBD_DO_IT: 650 case NBD_DO_IT:
608 if (!lo->file) 651 if (!lo->file)
609 return -EINVAL; 652 return -EINVAL;
653 thread = kthread_create(nbd_thread, lo, lo->disk->disk_name);
654 if (IS_ERR(thread))
655 return PTR_ERR(thread);
656 wake_up_process(thread);
610 error = nbd_do_it(lo); 657 error = nbd_do_it(lo);
658 kthread_stop(thread);
611 if (error) 659 if (error)
612 return error; 660 return error;
613 sock_shutdown(lo, 1); 661 sock_shutdown(lo, 1);
@@ -620,6 +668,8 @@ static int nbd_ioctl(struct inode *inode, struct file *file,
620 lo->bytesize = 0; 668 lo->bytesize = 0;
621 inode->i_bdev->bd_inode->i_size = 0; 669 inode->i_bdev->bd_inode->i_size = 0;
622 set_capacity(lo->disk, 0); 670 set_capacity(lo->disk, 0);
671 if (max_part > 0)
672 ioctl_by_bdev(inode->i_bdev, BLKRRPART, 0);
623 return lo->harderror; 673 return lo->harderror;
624 case NBD_CLEAR_QUE: 674 case NBD_CLEAR_QUE:
625 /* 675 /*
@@ -653,6 +703,7 @@ static int __init nbd_init(void)
653{ 703{
654 int err = -ENOMEM; 704 int err = -ENOMEM;
655 int i; 705 int i;
706 int part_shift;
656 707
657 BUILD_BUG_ON(sizeof(struct nbd_request) != 28); 708 BUILD_BUG_ON(sizeof(struct nbd_request) != 28);
658 709
@@ -660,8 +711,17 @@ static int __init nbd_init(void)
660 if (!nbd_dev) 711 if (!nbd_dev)
661 return -ENOMEM; 712 return -ENOMEM;
662 713
714 if (max_part < 0) {
715 printk(KERN_CRIT "nbd: max_part must be >= 0\n");
716 return -EINVAL;
717 }
718
719 part_shift = 0;
720 if (max_part > 0)
721 part_shift = fls(max_part);
722
663 for (i = 0; i < nbds_max; i++) { 723 for (i = 0; i < nbds_max; i++) {
664 struct gendisk *disk = alloc_disk(1); 724 struct gendisk *disk = alloc_disk(1 << part_shift);
665 elevator_t *old_e; 725 elevator_t *old_e;
666 if (!disk) 726 if (!disk)
667 goto out; 727 goto out;
@@ -696,17 +756,18 @@ static int __init nbd_init(void)
696 nbd_dev[i].file = NULL; 756 nbd_dev[i].file = NULL;
697 nbd_dev[i].magic = LO_MAGIC; 757 nbd_dev[i].magic = LO_MAGIC;
698 nbd_dev[i].flags = 0; 758 nbd_dev[i].flags = 0;
759 INIT_LIST_HEAD(&nbd_dev[i].waiting_queue);
699 spin_lock_init(&nbd_dev[i].queue_lock); 760 spin_lock_init(&nbd_dev[i].queue_lock);
700 INIT_LIST_HEAD(&nbd_dev[i].queue_head); 761 INIT_LIST_HEAD(&nbd_dev[i].queue_head);
701 mutex_init(&nbd_dev[i].tx_lock); 762 mutex_init(&nbd_dev[i].tx_lock);
702 init_waitqueue_head(&nbd_dev[i].active_wq); 763 init_waitqueue_head(&nbd_dev[i].active_wq);
764 init_waitqueue_head(&nbd_dev[i].waiting_wq);
703 nbd_dev[i].blksize = 1024; 765 nbd_dev[i].blksize = 1024;
704 nbd_dev[i].bytesize = 0; 766 nbd_dev[i].bytesize = 0;
705 disk->major = NBD_MAJOR; 767 disk->major = NBD_MAJOR;
706 disk->first_minor = i; 768 disk->first_minor = i << part_shift;
707 disk->fops = &nbd_fops; 769 disk->fops = &nbd_fops;
708 disk->private_data = &nbd_dev[i]; 770 disk->private_data = &nbd_dev[i];
709 disk->flags |= GENHD_FL_SUPPRESS_PARTITION_INFO;
710 sprintf(disk->disk_name, "nbd%d", i); 771 sprintf(disk->disk_name, "nbd%d", i);
711 set_capacity(disk, 0); 772 set_capacity(disk, 0);
712 add_disk(disk); 773 add_disk(disk);
@@ -744,7 +805,9 @@ MODULE_DESCRIPTION("Network Block Device");
744MODULE_LICENSE("GPL"); 805MODULE_LICENSE("GPL");
745 806
746module_param(nbds_max, int, 0444); 807module_param(nbds_max, int, 0444);
747MODULE_PARM_DESC(nbds_max, "How many network block devices to initialize."); 808MODULE_PARM_DESC(nbds_max, "number of network block devices to initialize (default: 16)");
809module_param(max_part, int, 0444);
810MODULE_PARM_DESC(max_part, "number of partitions per device (default: 0)");
748#ifndef NDEBUG 811#ifndef NDEBUG
749module_param(debugflags, int, 0644); 812module_param(debugflags, int, 0644);
750MODULE_PARM_DESC(debugflags, "flags for controlling debug output"); 813MODULE_PARM_DESC(debugflags, "flags for controlling debug output");