[PATCH] 2.6.0 NBD driver: remove send/recieve race for request

From: Lou Langholtz (ldl@aros.net)
Date: Tue Aug 05 2003 - 11:51:04 EST


The following patch removes a race condition in the network block device
driver in 2.6.0*. Without this patch, the reply receiving thread could
end (and free up the memory for) the request structure before the
request sending thread is completely done accessing it and would then
access invalid memory. This particular patch has only been compile
tested and visually inspected. The invalid memory access had originally
been found in a derivative nbd work that I've been developing and this
race was found to be the cause (and removing the race fixed this problem).

diff -urN linux-2.6.0-test2-mm4/drivers/block/nbd.c linux-2.6.0-test2-mm4-no_send_race/drivers/block/nbd.c
--- linux-2.6.0-test2-mm4/drivers/block/nbd.c 2003-08-04 22:01:24.000000000 -0600
+++ linux-2.6.0-test2-mm4-no_send_race/drivers/block/nbd.c 2003-08-04 22:01:45.000000000 -0600
@@ -234,15 +234,16 @@
         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;
+ int result, i, flags, rw;
         struct nbd_request request;
         unsigned long size = req->nr_sectors << 9;
         struct socket *sock = lo->sock;
 
+ rw = nbd_cmd(req);
         request.magic = htonl(NBD_REQUEST_MAGIC);
- request.type = htonl(nbd_cmd(req));
+ request.type = htonl(rw);
         request.from = cpu_to_be64((u64) req->sector << 9);
         request.len = htonl(size);
         memcpy(request.handle, &req, sizeof(req));
@@ -256,19 +257,18 @@
         }
 
         dprintk(DBG_TX, "%s: request %p: sending control (%s@%llu,%luB)\n",
- lo->disk->disk_name, req,
- nbdcmd_to_ascii(nbd_cmd(req)),
+ lo->disk->disk_name, req, nbdcmd_to_ascii(rw),
                         (unsigned long long)req->sector << 9,
                         req->nr_sectors << 9);
         result = sock_xmit(sock, 1, &request, sizeof(request),
- (nbd_cmd(req) == NBD_CMD_WRITE)? MSG_MORE: 0);
+ (rw == NBD_CMD_WRITE)? MSG_MORE: 0);
         if (result <= 0) {
                 printk(KERN_ERR "%s: Send control failed (result %d)\n",
                                 lo->disk->disk_name, result);
                 goto error_out;
         }
 
- if (nbd_cmd(req) == NBD_CMD_WRITE) {
+ if (rw == NBD_CMD_WRITE) {
                 struct bio *bio;
                 /*
                  * we are really probing at internals to determine
@@ -294,11 +294,12 @@
                 }
         }
         up(&lo->tx_lock);
- return;
+ return 0;
 
       error_out:
         up(&lo->tx_lock);
         req->errors++;
+ return req->errors;
 }
 
 static struct request *nbd_find_request(struct nbd_device *lo, char *handle)
@@ -492,9 +493,7 @@
                 list_add(&req->queuelist, &lo->queue_head);
                 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);

-
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
Please read the FAQ at http://www.tux.org/lkml/



This archive was generated by hypermail 2b29 : Thu Aug 07 2003 - 22:00:29 EST