vserver 1.9.5.x5
[linux-2.6.git] / drivers / block / nbd.c
index 3554188..2f5cc3e 100644 (file)
@@ -92,7 +92,7 @@ static struct nbd_device nbd_dev[MAX_NBD];
  *    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)
@@ -128,23 +128,11 @@ static void nbd_end_request(struct request *req)
 {
        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);
@@ -158,15 +146,12 @@ static void nbd_end_request(struct request *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(&current->sighand->siglock, flags);
@@ -182,17 +167,15 @@ static int sock_xmit(struct socket *sock, int send, void *buf, int size,
                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;
@@ -219,7 +202,6 @@ static int sock_xmit(struct socket *sock, int send, void *buf, int size,
        recalc_sigpending();
        spin_unlock_irqrestore(&current->sighand->siglock, flags);
 
-       set_fs(oldfs);
        return result;
 }
 
@@ -234,7 +216,7 @@ static inline int sock_send_bvec(struct socket *sock, struct bio_vec *bvec,
        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;
@@ -294,11 +276,11 @@ void nbd_send_req(struct nbd_device *lo, struct request *req)
                }
        }
        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)
@@ -483,26 +465,19 @@ static void do_nbd_request(request_queue_t * q)
                }
 
                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;
 
@@ -751,6 +726,6 @@ MODULE_DESCRIPTION("Network Block Device");
 MODULE_LICENSE("GPL");
 
 #ifndef NDEBUG
-MODULE_PARM(debugflags, "i");
+module_param(debugflags, int, 0644);
 MODULE_PARM_DESC(debugflags, "flags for controlling debug output");
 #endif