* a single lock.
* Thanks go to Jens Axboe and Al Viro for their LKML emails explaining this!
*/
-static spinlock_t nbd_lock = SPIN_LOCK_UNLOCKED;
+static DEFINE_SPINLOCK(nbd_lock);
#ifndef NDEBUG
static const char *ioctl_cmd_to_ascii(int cmd)
{
int uptodate = (req->errors == 0) ? 1 : 0;
request_queue_t *q = req->q;
- struct nbd_device *lo = req->rq_disk->private_data;
unsigned long flags;
dprintk(DBG_BLKDEV, "%s: request %p: %s\n", req->rq_disk->disk_name,
req, uptodate? "done": "failed");
- spin_lock(&lo->queue_lock);
- while (req->ref_count > 1) { /* still in send */
- spin_unlock(&lo->queue_lock);
- printk(KERN_DEBUG "%s: request %p still in use (%d), waiting\n",
- lo->disk->disk_name, req, req->ref_count);
- set_current_state(TASK_UNINTERRUPTIBLE);
- schedule_timeout(HZ); /* wait a second */
- spin_lock(&lo->queue_lock);
- }
- spin_unlock(&lo->queue_lock);
-
spin_lock_irqsave(q->queue_lock, flags);
if (!end_that_request_first(req, uptodate, req->nr_sectors)) {
end_that_request_last(req);
static int sock_xmit(struct socket *sock, int send, void *buf, int size,
int msg_flags)
{
- mm_segment_t oldfs;
int result;
struct msghdr msg;
- struct iovec iov;
+ struct kvec iov;
unsigned long flags;
sigset_t oldset;
- oldfs = get_fs();
- set_fs(get_ds());
/* Allow interception of SIGKILL only
* Don't allow other signals to interrupt the transmission */
spin_lock_irqsave(¤t->sighand->siglock, flags);
iov.iov_len = size;
msg.msg_name = NULL;
msg.msg_namelen = 0;
- msg.msg_iov = &iov;
- msg.msg_iovlen = 1;
msg.msg_control = NULL;
msg.msg_controllen = 0;
msg.msg_namelen = 0;
msg.msg_flags = msg_flags | MSG_NOSIGNAL;
if (send)
- result = sock_sendmsg(sock, &msg, size);
+ result = kernel_sendmsg(sock, &msg, &iov, 1, size);
else
- result = sock_recvmsg(sock, &msg, size, 0);
+ result = kernel_recvmsg(sock, &msg, &iov, 1, size, 0);
if (signal_pending(current)) {
siginfo_t info;
recalc_sigpending();
spin_unlock_irqrestore(¤t->sighand->siglock, flags);
- set_fs(oldfs);
return result;
}
return result;
}
-void nbd_send_req(struct nbd_device *lo, struct request *req)
+static int nbd_send_req(struct nbd_device *lo, struct request *req)
{
int result, i, flags;
struct nbd_request request;
}
}
up(&lo->tx_lock);
- return;
+ return 0;
error_out:
up(&lo->tx_lock);
- req->errors++;
+ return 1;
}
static struct request *nbd_find_request(struct nbd_device *lo, char *handle)
}
list_add(&req->queuelist, &lo->queue_head);
- req->ref_count++; /* make sure req does not get freed */
spin_unlock(&lo->queue_lock);
- nbd_send_req(lo, req);
-
- if (req->errors) {
+ if (nbd_send_req(lo, req) != 0) {
printk(KERN_ERR "%s: Request send failed\n",
lo->disk->disk_name);
- spin_lock(&lo->queue_lock);
- list_del_init(&req->queuelist);
- req->ref_count--;
- spin_unlock(&lo->queue_lock);
- nbd_end_request(req);
- spin_lock_irq(q->queue_lock);
- continue;
+ if (nbd_find_request(lo, (char *)&req) != NULL) {
+ /* we still own req */
+ req->errors++;
+ nbd_end_request(req);
+ } else /* we're racing with nbd_clear_que */
+ printk(KERN_DEBUG "nbd: can't find req\n");
}
- spin_lock(&lo->queue_lock);
- req->ref_count--;
- spin_unlock(&lo->queue_lock);
spin_lock_irq(q->queue_lock);
continue;
MODULE_LICENSE("GPL");
#ifndef NDEBUG
-MODULE_PARM(debugflags, "i");
+module_param(debugflags, int, 0644);
MODULE_PARM_DESC(debugflags, "flags for controlling debug output");
#endif