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.c112
1 files changed, 71 insertions, 41 deletions
diff --git a/drivers/block/nbd.c b/drivers/block/nbd.c
index 8299e2d3b611..4d6de4f15ccb 100644
--- a/drivers/block/nbd.c
+++ b/drivers/block/nbd.c
@@ -4,7 +4,7 @@
4 * Note that you can not swap over this thing, yet. Seems to work but 4 * Note that you can not swap over this thing, yet. Seems to work but
5 * deadlocks sometimes - you can not swap over TCP in general. 5 * deadlocks sometimes - you can not swap over TCP in general.
6 * 6 *
7 * Copyright 1997-2000 Pavel Machek <pavel@ucw.cz> 7 * Copyright 1997-2000, 2008 Pavel Machek <pavel@suse.cz>
8 * Parts copyright 2001 Steven Whitehouse <steve@chygwyn.com> 8 * Parts copyright 2001 Steven Whitehouse <steve@chygwyn.com>
9 * 9 *
10 * This file is released under GPLv2 or later. 10 * This file is released under GPLv2 or later.
@@ -276,7 +276,7 @@ static int nbd_send_req(struct nbd_device *lo, struct request *req)
276 return 0; 276 return 0;
277 277
278error_out: 278error_out:
279 return 1; 279 return -EIO;
280} 280}
281 281
282static struct request *nbd_find_request(struct nbd_device *lo, 282static struct request *nbd_find_request(struct nbd_device *lo,
@@ -467,9 +467,7 @@ static void nbd_handle_req(struct nbd_device *lo, struct request *req)
467 mutex_unlock(&lo->tx_lock); 467 mutex_unlock(&lo->tx_lock);
468 printk(KERN_ERR "%s: Attempted send on closed socket\n", 468 printk(KERN_ERR "%s: Attempted send on closed socket\n",
469 lo->disk->disk_name); 469 lo->disk->disk_name);
470 req->errors++; 470 goto error_out;
471 nbd_end_request(req);
472 return;
473 } 471 }
474 472
475 lo->active_req = req; 473 lo->active_req = req;
@@ -531,7 +529,7 @@ static int nbd_thread(void *data)
531 * { printk( "Warning: Ignoring result!\n"); nbd_end_request( req ); } 529 * { printk( "Warning: Ignoring result!\n"); nbd_end_request( req ); }
532 */ 530 */
533 531
534static void do_nbd_request(struct request_queue * q) 532static void do_nbd_request(struct request_queue *q)
535{ 533{
536 struct request *req; 534 struct request *req;
537 535
@@ -568,27 +566,17 @@ static void do_nbd_request(struct request_queue * q)
568 } 566 }
569} 567}
570 568
571static int nbd_ioctl(struct block_device *bdev, fmode_t mode, 569/* Must be called with tx_lock held */
572 unsigned int cmd, unsigned long arg)
573{
574 struct nbd_device *lo = bdev->bd_disk->private_data;
575 struct file *file;
576 int error;
577 struct request sreq ;
578 struct task_struct *thread;
579
580 if (!capable(CAP_SYS_ADMIN))
581 return -EPERM;
582
583 BUG_ON(lo->magic != LO_MAGIC);
584
585 /* Anyone capable of this syscall can do *real bad* things */
586 dprintk(DBG_IOCTL, "%s: nbd_ioctl cmd=%s(0x%x) arg=%lu\n",
587 lo->disk->disk_name, ioctl_cmd_to_ascii(cmd), cmd, arg);
588 570
571static int __nbd_ioctl(struct block_device *bdev, struct nbd_device *lo,
572 unsigned int cmd, unsigned long arg)
573{
589 switch (cmd) { 574 switch (cmd) {
590 case NBD_DISCONNECT: 575 case NBD_DISCONNECT: {
576 struct request sreq;
577
591 printk(KERN_INFO "%s: NBD_DISCONNECT\n", lo->disk->disk_name); 578 printk(KERN_INFO "%s: NBD_DISCONNECT\n", lo->disk->disk_name);
579
592 blk_rq_init(NULL, &sreq); 580 blk_rq_init(NULL, &sreq);
593 sreq.cmd_type = REQ_TYPE_SPECIAL; 581 sreq.cmd_type = REQ_TYPE_SPECIAL;
594 nbd_cmd(&sreq) = NBD_CMD_DISC; 582 nbd_cmd(&sreq) = NBD_CMD_DISC;
@@ -599,29 +587,29 @@ static int nbd_ioctl(struct block_device *bdev, fmode_t mode,
599 */ 587 */
600 sreq.sector = 0; 588 sreq.sector = 0;
601 sreq.nr_sectors = 0; 589 sreq.nr_sectors = 0;
602 if (!lo->sock) 590 if (!lo->sock)
603 return -EINVAL; 591 return -EINVAL;
604 mutex_lock(&lo->tx_lock); 592 nbd_send_req(lo, &sreq);
605 nbd_send_req(lo, &sreq);
606 mutex_unlock(&lo->tx_lock);
607 return 0; 593 return 0;
594 }
608 595
609 case NBD_CLEAR_SOCK: 596 case NBD_CLEAR_SOCK: {
610 error = 0; 597 struct file *file;
611 mutex_lock(&lo->tx_lock); 598
612 lo->sock = NULL; 599 lo->sock = NULL;
613 mutex_unlock(&lo->tx_lock);
614 file = lo->file; 600 file = lo->file;
615 lo->file = NULL; 601 lo->file = NULL;
616 nbd_clear_que(lo); 602 nbd_clear_que(lo);
617 BUG_ON(!list_empty(&lo->queue_head)); 603 BUG_ON(!list_empty(&lo->queue_head));
618 if (file) 604 if (file)
619 fput(file); 605 fput(file);
620 return error; 606 return 0;
621 case NBD_SET_SOCK: 607 }
608
609 case NBD_SET_SOCK: {
610 struct file *file;
622 if (lo->file) 611 if (lo->file)
623 return -EBUSY; 612 return -EBUSY;
624 error = -EINVAL;
625 file = fget(arg); 613 file = fget(arg);
626 if (file) { 614 if (file) {
627 struct inode *inode = file->f_path.dentry->d_inode; 615 struct inode *inode = file->f_path.dentry->d_inode;
@@ -630,12 +618,14 @@ static int nbd_ioctl(struct block_device *bdev, fmode_t mode,
630 lo->sock = SOCKET_I(inode); 618 lo->sock = SOCKET_I(inode);
631 if (max_part > 0) 619 if (max_part > 0)
632 bdev->bd_invalidated = 1; 620 bdev->bd_invalidated = 1;
633 error = 0; 621 return 0;
634 } else { 622 } else {
635 fput(file); 623 fput(file);
636 } 624 }
637 } 625 }
638 return error; 626 return -EINVAL;
627 }
628
639 case NBD_SET_BLKSIZE: 629 case NBD_SET_BLKSIZE:
640 lo->blksize = arg; 630 lo->blksize = arg;
641 lo->bytesize &= ~(lo->blksize-1); 631 lo->bytesize &= ~(lo->blksize-1);
@@ -643,35 +633,50 @@ static int nbd_ioctl(struct block_device *bdev, fmode_t mode,
643 set_blocksize(bdev, lo->blksize); 633 set_blocksize(bdev, lo->blksize);
644 set_capacity(lo->disk, lo->bytesize >> 9); 634 set_capacity(lo->disk, lo->bytesize >> 9);
645 return 0; 635 return 0;
636
646 case NBD_SET_SIZE: 637 case NBD_SET_SIZE:
647 lo->bytesize = arg & ~(lo->blksize-1); 638 lo->bytesize = arg & ~(lo->blksize-1);
648 bdev->bd_inode->i_size = lo->bytesize; 639 bdev->bd_inode->i_size = lo->bytesize;
649 set_blocksize(bdev, lo->blksize); 640 set_blocksize(bdev, lo->blksize);
650 set_capacity(lo->disk, lo->bytesize >> 9); 641 set_capacity(lo->disk, lo->bytesize >> 9);
651 return 0; 642 return 0;
643
652 case NBD_SET_TIMEOUT: 644 case NBD_SET_TIMEOUT:
653 lo->xmit_timeout = arg * HZ; 645 lo->xmit_timeout = arg * HZ;
654 return 0; 646 return 0;
647
655 case NBD_SET_SIZE_BLOCKS: 648 case NBD_SET_SIZE_BLOCKS:
656 lo->bytesize = ((u64) arg) * lo->blksize; 649 lo->bytesize = ((u64) arg) * lo->blksize;
657 bdev->bd_inode->i_size = lo->bytesize; 650 bdev->bd_inode->i_size = lo->bytesize;
658 set_blocksize(bdev, lo->blksize); 651 set_blocksize(bdev, lo->blksize);
659 set_capacity(lo->disk, lo->bytesize >> 9); 652 set_capacity(lo->disk, lo->bytesize >> 9);
660 return 0; 653 return 0;
661 case NBD_DO_IT: 654
655 case NBD_DO_IT: {
656 struct task_struct *thread;
657 struct file *file;
658 int error;
659
662 if (lo->pid) 660 if (lo->pid)
663 return -EBUSY; 661 return -EBUSY;
664 if (!lo->file) 662 if (!lo->file)
665 return -EINVAL; 663 return -EINVAL;
664
665 mutex_unlock(&lo->tx_lock);
666
666 thread = kthread_create(nbd_thread, lo, lo->disk->disk_name); 667 thread = kthread_create(nbd_thread, lo, lo->disk->disk_name);
667 if (IS_ERR(thread)) 668 if (IS_ERR(thread)) {
669 mutex_lock(&lo->tx_lock);
668 return PTR_ERR(thread); 670 return PTR_ERR(thread);
671 }
669 wake_up_process(thread); 672 wake_up_process(thread);
670 error = nbd_do_it(lo); 673 error = nbd_do_it(lo);
671 kthread_stop(thread); 674 kthread_stop(thread);
675
676 mutex_lock(&lo->tx_lock);
672 if (error) 677 if (error)
673 return error; 678 return error;
674 sock_shutdown(lo, 1); 679 sock_shutdown(lo, 0);
675 file = lo->file; 680 file = lo->file;
676 lo->file = NULL; 681 lo->file = NULL;
677 nbd_clear_que(lo); 682 nbd_clear_que(lo);
@@ -684,6 +689,8 @@ static int nbd_ioctl(struct block_device *bdev, fmode_t mode,
684 if (max_part > 0) 689 if (max_part > 0)
685 ioctl_by_bdev(bdev, BLKRRPART, 0); 690 ioctl_by_bdev(bdev, BLKRRPART, 0);
686 return lo->harderror; 691 return lo->harderror;
692 }
693
687 case NBD_CLEAR_QUE: 694 case NBD_CLEAR_QUE:
688 /* 695 /*
689 * This is for compatibility only. The queue is always cleared 696 * This is for compatibility only. The queue is always cleared
@@ -691,6 +698,7 @@ static int nbd_ioctl(struct block_device *bdev, fmode_t mode,
691 */ 698 */
692 BUG_ON(!lo->sock && !list_empty(&lo->queue_head)); 699 BUG_ON(!lo->sock && !list_empty(&lo->queue_head));
693 return 0; 700 return 0;
701
694 case NBD_PRINT_DEBUG: 702 case NBD_PRINT_DEBUG:
695 printk(KERN_INFO "%s: next = %p, prev = %p, head = %p\n", 703 printk(KERN_INFO "%s: next = %p, prev = %p, head = %p\n",
696 bdev->bd_disk->disk_name, 704 bdev->bd_disk->disk_name,
@@ -698,7 +706,29 @@ static int nbd_ioctl(struct block_device *bdev, fmode_t mode,
698 &lo->queue_head); 706 &lo->queue_head);
699 return 0; 707 return 0;
700 } 708 }
701 return -EINVAL; 709 return -ENOTTY;
710}
711
712static int nbd_ioctl(struct block_device *bdev, fmode_t mode,
713 unsigned int cmd, unsigned long arg)
714{
715 struct nbd_device *lo = bdev->bd_disk->private_data;
716 int error;
717
718 if (!capable(CAP_SYS_ADMIN))
719 return -EPERM;
720
721 BUG_ON(lo->magic != LO_MAGIC);
722
723 /* Anyone capable of this syscall can do *real bad* things */
724 dprintk(DBG_IOCTL, "%s: nbd_ioctl cmd=%s(0x%x) arg=%lu\n",
725 lo->disk->disk_name, ioctl_cmd_to_ascii(cmd), cmd, arg);
726
727 mutex_lock(&lo->tx_lock);
728 error = __nbd_ioctl(bdev, lo, cmd, arg);
729 mutex_unlock(&lo->tx_lock);
730
731 return error;
702} 732}
703 733
704static struct block_device_operations nbd_fops = 734static struct block_device_operations nbd_fops =