Skip to content

Commit

Permalink
---
Browse files Browse the repository at this point in the history
yaml
---
r: 139712
b: refs/heads/master
c: 1a2ad21
h: refs/heads/master
v: v3
  • Loading branch information
Pavel Machek authored and Linus Torvalds committed Apr 3, 2009
1 parent bfbdd06 commit af6f598
Show file tree
Hide file tree
Showing 2 changed files with 68 additions and 36 deletions.
2 changes: 1 addition & 1 deletion [refs]
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
---
refs/heads/master: 1b0f7ffd0ea27cd3a0b9ca04e3df9522048c32a3
refs/heads/master: 1a2ad21128bb4eb79f3c05e5801edcc5ed3ef1d3
102 changes: 67 additions & 35 deletions trunk/drivers/block/nbd.c
Original file line number Diff line number Diff line change
Expand Up @@ -568,27 +568,17 @@ static void do_nbd_request(struct request_queue * q)
}
}

static int nbd_ioctl(struct block_device *bdev, fmode_t mode,
unsigned int cmd, unsigned long arg)
{
struct nbd_device *lo = bdev->bd_disk->private_data;
struct file *file;
int error;
struct request sreq ;
struct task_struct *thread;

if (!capable(CAP_SYS_ADMIN))
return -EPERM;

BUG_ON(lo->magic != LO_MAGIC);

/* Anyone capable of this syscall can do *real bad* things */
dprintk(DBG_IOCTL, "%s: nbd_ioctl cmd=%s(0x%x) arg=%lu\n",
lo->disk->disk_name, ioctl_cmd_to_ascii(cmd), cmd, arg);
/* Must be called with tx_lock held */

static int __nbd_ioctl(struct block_device *bdev, struct nbd_device *lo,
unsigned int cmd, unsigned long arg)
{
switch (cmd) {
case NBD_DISCONNECT:
case NBD_DISCONNECT: {
struct request sreq;

printk(KERN_INFO "%s: NBD_DISCONNECT\n", lo->disk->disk_name);

blk_rq_init(NULL, &sreq);
sreq.cmd_type = REQ_TYPE_SPECIAL;
nbd_cmd(&sreq) = NBD_CMD_DISC;
Expand All @@ -599,29 +589,29 @@ static int nbd_ioctl(struct block_device *bdev, fmode_t mode,
*/
sreq.sector = 0;
sreq.nr_sectors = 0;
if (!lo->sock)
if (!lo->sock)
return -EINVAL;
mutex_lock(&lo->tx_lock);
nbd_send_req(lo, &sreq);
mutex_unlock(&lo->tx_lock);
nbd_send_req(lo, &sreq);
return 0;
}

case NBD_CLEAR_SOCK:
error = 0;
mutex_lock(&lo->tx_lock);
case NBD_CLEAR_SOCK: {
struct file *file;

lo->sock = NULL;
mutex_unlock(&lo->tx_lock);
file = lo->file;
lo->file = NULL;
nbd_clear_que(lo);
BUG_ON(!list_empty(&lo->queue_head));
if (file)
fput(file);
return error;
case NBD_SET_SOCK:
return 0;
}

case NBD_SET_SOCK: {
struct file *file;
if (lo->file)
return -EBUSY;
error = -EINVAL;
file = fget(arg);
if (file) {
struct inode *inode = file->f_path.dentry->d_inode;
Expand All @@ -630,48 +620,65 @@ static int nbd_ioctl(struct block_device *bdev, fmode_t mode,
lo->sock = SOCKET_I(inode);
if (max_part > 0)
bdev->bd_invalidated = 1;
error = 0;
return 0;
} else {
fput(file);
}
}
return error;
return -EINVAL;
}

case NBD_SET_BLKSIZE:
lo->blksize = arg;
lo->bytesize &= ~(lo->blksize-1);
bdev->bd_inode->i_size = lo->bytesize;
set_blocksize(bdev, lo->blksize);
set_capacity(lo->disk, lo->bytesize >> 9);
return 0;

case NBD_SET_SIZE:
lo->bytesize = arg & ~(lo->blksize-1);
bdev->bd_inode->i_size = lo->bytesize;
set_blocksize(bdev, lo->blksize);
set_capacity(lo->disk, lo->bytesize >> 9);
return 0;

case NBD_SET_TIMEOUT:
lo->xmit_timeout = arg * HZ;
return 0;

case NBD_SET_SIZE_BLOCKS:
lo->bytesize = ((u64) arg) * lo->blksize;
bdev->bd_inode->i_size = lo->bytesize;
set_blocksize(bdev, lo->blksize);
set_capacity(lo->disk, lo->bytesize >> 9);
return 0;
case NBD_DO_IT:

case NBD_DO_IT: {
struct task_struct *thread;
struct file *file;
int error;

if (lo->pid)
return -EBUSY;
if (!lo->file)
return -EINVAL;

mutex_unlock(&lo->tx_lock);

thread = kthread_create(nbd_thread, lo, lo->disk->disk_name);
if (IS_ERR(thread))
if (IS_ERR(thread)) {
mutex_lock(&lo->tx_lock);
return PTR_ERR(thread);
}
wake_up_process(thread);
error = nbd_do_it(lo);
kthread_stop(thread);

mutex_lock(&lo->tx_lock);
if (error)
return error;
sock_shutdown(lo, 1);
sock_shutdown(lo, 0);
file = lo->file;
lo->file = NULL;
nbd_clear_que(lo);
Expand All @@ -684,21 +691,46 @@ static int nbd_ioctl(struct block_device *bdev, fmode_t mode,
if (max_part > 0)
ioctl_by_bdev(bdev, BLKRRPART, 0);
return lo->harderror;
}

case NBD_CLEAR_QUE:
/*
* This is for compatibility only. The queue is always cleared
* by NBD_DO_IT or NBD_CLEAR_SOCK.
*/
BUG_ON(!lo->sock && !list_empty(&lo->queue_head));
return 0;

case NBD_PRINT_DEBUG:
printk(KERN_INFO "%s: next = %p, prev = %p, head = %p\n",
bdev->bd_disk->disk_name,
lo->queue_head.next, lo->queue_head.prev,
&lo->queue_head);
return 0;
}
return -EINVAL;
return -ENOTTY;
}

static int nbd_ioctl(struct block_device *bdev, fmode_t mode,
unsigned int cmd, unsigned long arg)
{
struct nbd_device *lo = bdev->bd_disk->private_data;
int error;

if (!capable(CAP_SYS_ADMIN))
return -EPERM;

BUG_ON(lo->magic != LO_MAGIC);

/* Anyone capable of this syscall can do *real bad* things */
dprintk(DBG_IOCTL, "%s: nbd_ioctl cmd=%s(0x%x) arg=%lu\n",
lo->disk->disk_name, ioctl_cmd_to_ascii(cmd), cmd, arg);

mutex_lock(&lo->tx_lock);
error = __nbd_ioctl(bdev, lo, cmd, arg);
mutex_unlock(&lo->tx_lock);

return error;
}

static struct block_device_operations nbd_fops =
Expand Down

0 comments on commit af6f598

Please sign in to comment.