From: Paul Clements <Paul.Clements@SteelEye.com>
To: Andrew Morton <akpm@osdl.org>
Cc: Lou Langholtz <ldl@aros.net>,
linux-kernel <linux-kernel@vger.kernel.org>
Subject: [PATCH 2.6.0-test2-mm] nbd: fix send/receive/shutdown/disconnect races
Date: Fri, 08 Aug 2003 16:07:19 -0400 [thread overview]
Message-ID: <3F3402F7.A8986417@SteelEye.com> (raw)
In-Reply-To: 3F33D41E.89CFA182@SteelEye.com
[-- Attachment #1: Type: text/plain, Size: 898 bytes --]
Here's the updated patch to fix several race conditions in nbd. It
requires reverting the already included (but incomplete)
nbd-race-fix.patch that's in -mm5.
This patch fixes the following race conditions:
1) adds an increment of req->ref_count to eliminate races between
do_nbd_request and nbd_end_request, which resulted in the freeing of
in-use requests -- there were races between send/receive, send/shutdown
(killall -9 nbd-client), and send/disconnect (nbd-client -d), which are
now all fixed
2) adds locking and properly orders the code in NBD_CLEAR_SOCK to
eliminate races with other code
3) adds an lo->sock check to nbd_clear_que to eliminate races between
do_nbd_request and nbd_clear_que, which resulted in the dequeuing of
active requests
4) adds an lo->sock check to NBD_DO_IT to eliminate races with
NBD_CLEAR_SOCK, which caused an Oops when "nbd-client -d" was called
--
Paul
[-- Attachment #2: nbd-race_fixes.diff --]
[-- Type: text/x-diff, Size: 3651 bytes --]
--- linux-2.6.0-test2-mm4-PRISTINE/drivers/block/nbd.c Sun Jul 27 12:58:51 2003
+++ linux-2.6.0-test2-mm4/drivers/block/nbd.c Fri Aug 8 15:23:33 2003
@@ -136,10 +136,23 @@ static void nbd_end_request(struct reque
{
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_INTERRUPTIBLE);
+ schedule_timeout(HZ); /* wait a second */
+ spin_lock(&lo->queue_lock);
+ }
+ spin_unlock(&lo->queue_lock);
+
#ifdef PARANOIA
requests_out++;
#endif
@@ -490,6 +503,7 @@ static void do_nbd_request(request_queue
}
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);
@@ -499,12 +513,16 @@ static void do_nbd_request(request_queue
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;
}
+ spin_lock(&lo->queue_lock);
+ req->ref_count--;
+ spin_unlock(&lo->queue_lock);
spin_lock_irq(q->queue_lock);
continue;
@@ -548,27 +566,27 @@ static int nbd_ioctl(struct inode *inode
if (!lo->sock)
return -EINVAL;
nbd_send_req(lo, &sreq);
- return 0 ;
+ return 0;
case NBD_CLEAR_SOCK:
+ error = 0;
+ down(&lo->tx_lock);
+ 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);
spin_lock(&lo->queue_lock);
if (!list_empty(&lo->queue_head)) {
- spin_unlock(&lo->queue_lock);
- printk(KERN_ERR "%s: Some requests are in progress -> can not turn off.\n",
- lo->disk->disk_name);
- return -EBUSY;
+ printk(KERN_ERR "nbd: disconnect: some requests are in progress -> please try again.\n");
+ error = -EBUSY;
}
- file = lo->file;
- if (!file) {
- spin_unlock(&lo->queue_lock);
- return -EINVAL;
- }
- lo->file = NULL;
- lo->sock = NULL;
spin_unlock(&lo->queue_lock);
- fput(file);
- return 0;
+ if (file)
+ fput(file);
+ return error;
case NBD_SET_SOCK:
if (lo->file)
return -EBUSY;
@@ -616,10 +634,13 @@ static int nbd_ioctl(struct inode *inode
* there should be a more generic interface rather than
* calling socket ops directly here */
down(&lo->tx_lock);
- printk(KERN_WARNING "%s: shutting down socket\n",
+ if (lo->sock) {
+ printk(KERN_WARNING "%s: shutting down socket\n",
lo->disk->disk_name);
- lo->sock->ops->shutdown(lo->sock, SEND_SHUTDOWN|RCV_SHUTDOWN);
- lo->sock = NULL;
+ 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;
@@ -631,6 +652,13 @@ static int nbd_ioctl(struct inode *inode
fput(file);
return lo->harderror;
case NBD_CLEAR_QUE:
+ down(&lo->tx_lock);
+ if (lo->sock) {
+ up(&lo->tx_lock);
+ return 0; /* probably should be error, but that would
+ * break "nbd-client -d", so just return 0 */
+ }
+ up(&lo->tx_lock);
nbd_clear_que(lo);
return 0;
case NBD_PRINT_DEBUG:
next prev parent reply other threads:[~2003-08-08 20:09 UTC|newest]
Thread overview: 16+ messages / expand[flat|nested] mbox.gz Atom feed top
2003-08-05 16:51 [PATCH] 2.6.0 NBD driver: remove send/recieve race for request Lou Langholtz
2003-08-05 19:37 ` Paul Clements
2003-08-05 22:48 ` Lou Langholtz
2003-08-06 0:51 ` Paul Clements
2003-08-06 7:34 ` Lou Langholtz
2003-08-08 5:02 ` Paul Clements
2003-08-08 5:27 ` Andrew Morton
2003-08-08 17:05 ` Paul Clements
2003-08-08 6:30 ` Lou Langholtz
2003-08-08 6:43 ` Andrew Morton
2003-08-08 6:59 ` Jens Axboe
2003-08-08 15:00 ` Paul Clements
2003-08-25 9:58 ` Jens Axboe
2003-08-08 16:47 ` Paul Clements
2003-08-08 20:07 ` Paul Clements [this message]
2003-08-09 22:10 ` [PATCH 2.4.22-pre] nbd: fix race conditions Paul Clements
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=3F3402F7.A8986417@SteelEye.com \
--to=paul.clements@steeleye.com \
--cc=akpm@osdl.org \
--cc=ldl@aros.net \
--cc=linux-kernel@vger.kernel.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.