Commit 67e9b61e authored by Alan Cox's avatar Alan Cox Committed by Linus Torvalds

[PATCH] update nbd driver to large sizes etc

parent 059fd0e0
...@@ -26,6 +26,8 @@ ...@@ -26,6 +26,8 @@
* reduce number of partial TCP segments sent. <steve@chygwyn.com> * reduce number of partial TCP segments sent. <steve@chygwyn.com>
* 01-12-6 Fix deadlock condition by making queue locks independant of * 01-12-6 Fix deadlock condition by making queue locks independant of
* the transmit lock. <steve@chygwyn.com> * the transmit lock. <steve@chygwyn.com>
* 02-10-11 Allow hung xmit to be aborted via SIGKILL & various fixes.
* <Paul.Clements@SteelEye.com> <James.Bottomley@SteelEye.com>
* *
* possible FIXME: make set_sock / set_blksize / set_size / do_it one syscall * possible FIXME: make set_sock / set_blksize / set_size / do_it one syscall
* why not: would need verify_area and friends, would share yet another * why not: would need verify_area and friends, would share yet another
...@@ -89,10 +91,12 @@ static int nbd_xmit(int send, struct socket *sock, char *buf, int size, int msg_ ...@@ -89,10 +91,12 @@ static int nbd_xmit(int send, struct socket *sock, char *buf, int size, int msg_
oldfs = get_fs(); oldfs = get_fs();
set_fs(get_ds()); set_fs(get_ds());
/* Allow interception of SIGKILL only
* Don't allow other signals to interrupt the transmission */
spin_lock_irqsave(&current->sig->siglock, flags); spin_lock_irqsave(&current->sig->siglock, flags);
oldset = current->blocked; oldset = current->blocked;
sigfillset(&current->blocked); sigfillset(&current->blocked);
sigdelsetmask(&current->blocked, sigmask(SIGKILL));
recalc_sigpending(); recalc_sigpending();
spin_unlock_irqrestore(&current->sig->siglock, flags); spin_unlock_irqrestore(&current->sig->siglock, flags);
...@@ -115,6 +119,17 @@ static int nbd_xmit(int send, struct socket *sock, char *buf, int size, int msg_ ...@@ -115,6 +119,17 @@ static int nbd_xmit(int send, struct socket *sock, char *buf, int size, int msg_
else else
result = sock_recvmsg(sock, &msg, size, 0); result = sock_recvmsg(sock, &msg, size, 0);
if (signal_pending(current)) {
siginfo_t info;
spin_lock_irqsave(&current->sig->siglock, flags);
printk(KERN_WARNING "NBD (pid %d: %s) got signal %d\n",
current->pid, current->comm,
dequeue_signal(&current->blocked, &info));
spin_unlock_irqrestore(&current->sig->siglock, flags);
result = -EINTR;
break;
}
if (result <= 0) { if (result <= 0) {
#ifdef PARANOIA #ifdef PARANOIA
printk(KERN_ERR "NBD: %s - sock=%ld at buf=%ld, size=%d returned %d.\n", printk(KERN_ERR "NBD: %s - sock=%ld at buf=%ld, size=%d returned %d.\n",
...@@ -154,6 +169,10 @@ void nbd_send_req(struct nbd_device *lo, struct request *req) ...@@ -154,6 +169,10 @@ void nbd_send_req(struct nbd_device *lo, struct request *req)
down(&lo->tx_lock); down(&lo->tx_lock);
if (!sock || !lo->sock) {
FAIL("Attempted sendmsg to closed socket\n");
}
result = nbd_xmit(1, sock, (char *) &request, sizeof(request), nbd_cmd(req) == NBD_CMD_WRITE ? MSG_MORE : 0); result = nbd_xmit(1, sock, (char *) &request, sizeof(request), nbd_cmd(req) == NBD_CMD_WRITE ? MSG_MORE : 0);
if (result <= 0) if (result <= 0)
FAIL("Sendmsg failed for control."); FAIL("Sendmsg failed for control.");
...@@ -324,11 +343,31 @@ static void do_nbd_request(request_queue_t * q) ...@@ -324,11 +343,31 @@ static void do_nbd_request(request_queue_t * q)
spin_unlock_irq(q->queue_lock); spin_unlock_irq(q->queue_lock);
spin_lock(&lo->queue_lock); spin_lock(&lo->queue_lock);
if (!lo->file) {
spin_unlock(&lo->queue_lock);
printk(KERN_ERR "nbd: failed between accept and semaphore, file lost\n");
req->errors++;
nbd_end_request(req);
spin_lock_irq(q->queue_lock);
continue;
}
list_add(&req->queuelist, &lo->queue_head); list_add(&req->queuelist, &lo->queue_head);
spin_unlock(&lo->queue_lock); spin_unlock(&lo->queue_lock);
nbd_send_req(lo, req); nbd_send_req(lo, req);
if (req->errors) {
printk(KERN_ERR "nbd: nbd_send_req failed\n");
spin_lock(&lo->queue_lock);
list_del(&req->queuelist);
spin_unlock(&lo->queue_lock);
nbd_end_request(req);
spin_lock_irq(q->queue_lock);
continue;
}
spin_lock_irq(q->queue_lock); spin_lock_irq(q->queue_lock);
continue; continue;
...@@ -371,12 +410,14 @@ static int nbd_ioctl(struct inode *inode, struct file *file, ...@@ -371,12 +410,14 @@ static int nbd_ioctl(struct inode *inode, struct file *file,
printk(KERN_ERR "nbd: Some requests are in progress -> can not turn off.\n"); printk(KERN_ERR "nbd: Some requests are in progress -> can not turn off.\n");
return -EBUSY; return -EBUSY;
} }
spin_unlock(&lo->queue_lock);
file = lo->file; file = lo->file;
if (!file) if (!file) {
spin_unlock(&lo->queue_lock);
return -EINVAL; return -EINVAL;
}
lo->file = NULL; lo->file = NULL;
lo->sock = NULL; lo->sock = NULL;
spin_unlock(&lo->queue_lock);
fput(file); fput(file);
return 0; return 0;
case NBD_SET_SOCK: case NBD_SET_SOCK:
...@@ -420,6 +461,26 @@ static int nbd_ioctl(struct inode *inode, struct file *file, ...@@ -420,6 +461,26 @@ static int nbd_ioctl(struct inode *inode, struct file *file,
if (!lo->file) if (!lo->file)
return -EINVAL; return -EINVAL;
nbd_do_it(lo); nbd_do_it(lo);
/* on return tidy up in case we have a signal */
/* Forcibly shutdown the socket causing all listeners
* to error
*
* FIXME: This code is duplicated from sys_shutdown, but
* there should be a more generic interface rather than
* calling socket ops directly here */
down(&lo->tx_lock);
printk(KERN_WARNING "nbd: shutting down socket\n");
lo->sock->ops->shutdown(lo->sock, SEND_SHUTDOWN|RCV_SHUTDOWN);
lo->sock = NULL;
up(&lo->tx_lock);
spin_lock(&lo->queue_lock);
file = lo->file;
lo->file = NULL;
spin_unlock(&lo->queue_lock);
nbd_clear_que(lo);
printk(KERN_WARNING "nbd: queue cleared\n");
if (file)
fput(file);
return lo->harderror; return lo->harderror;
case NBD_CLEAR_QUE: case NBD_CLEAR_QUE:
nbd_clear_que(lo); nbd_clear_que(lo);
...@@ -498,7 +559,7 @@ static int __init nbd_init(void) ...@@ -498,7 +559,7 @@ static int __init nbd_init(void)
init_MUTEX(&nbd_dev[i].tx_lock); init_MUTEX(&nbd_dev[i].tx_lock);
nbd_dev[i].blksize = 1024; nbd_dev[i].blksize = 1024;
nbd_dev[i].blksize_bits = 10; nbd_dev[i].blksize_bits = 10;
nbd_dev[i].bytesize = 0x7ffffc00; /* 2GB */ nbd_dev[i].bytesize = ((u64)0x7ffffc00) << 10; /* 2TB */
disk->major = MAJOR_NR; disk->major = MAJOR_NR;
disk->first_minor = i; disk->first_minor = i;
disk->fops = &nbd_fops; disk->fops = &nbd_fops;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment