public inbox for cluster-cvs@sourceware.org help / color / mirror / Atom feed
From: fabbione@sourceware.org To: cluster-cvs@sources.redhat.com, cluster-devel@redhat.com Subject: Cluster Project branch, STABLE2, updated. cluster-2.03.04-19-g40bb88d Date: Fri, 20 Jun 2008 04:20:00 -0000 [thread overview] Message-ID: <20080620042033.16654.qmail@sourceware.org> (raw) This is an automated email from the git hooks/post-receive script. It was generated because a ref change was pushed to the repository containing the project "Cluster Project". http://sources.redhat.com/git/gitweb.cgi?p=cluster.git;a=commitdiff;h=40bb88dbe0b246107e7106a04bf2c8793d3c445d The branch, STABLE2 has been updated via 40bb88dbe0b246107e7106a04bf2c8793d3c445d (commit) via c645bda5140d88a490f9b62cd0ad65c832f152dc (commit) from ac95cea5aa26a149e2d34d156186aa29329e7952 (commit) Those revisions listed above that are new to this repository have not appeared on any other notification email; so we list those revisions in full, below. - Log ----------------------------------------------------------------- commit 40bb88dbe0b246107e7106a04bf2c8793d3c445d Author: Benjamin Marzinski <bmarzins@redhat.com> Date: Thu Jun 19 15:44:27 2008 -0500 [gnbd-kernel] bz 449812: disallow sending requests after a send has failed. This fix adds a "corrupt" flag to the gnbd device structure. This flag is cleared when a new socket connection is opened to the server. It is set whenever a send fails. After this all future sends will fail, and the receiver process will stop accepting replies as soon as it notices the flag. commit c645bda5140d88a490f9b62cd0ad65c832f152dc Author: Benjamin Marzinski <bmarzins@redhat.com> Date: Thu Jun 19 14:01:20 2008 -0500 gnbd-kernel: Fix receiver race It is possible to have the gnbd receiver process finish and end a request before the sending process has finished using the request structure. This can cause a kernel panic. This fix adds a waitqueue (tx_wait) and a pointer to the request currently being send (current_request) to the gnbd device structure. current_request is set before any request is sent to the server. When the send is complete, it is cleared and the wait_queue is woken. A new function, wait_for_send() is called whenever it is possible for a call to gnbd_end_request() to interleave with a send. It waits on the waitqueue if the request about to be ended is currently being sent. Conflicts: gnbd-kernel/src/gnbd.c ----------------------------------------------------------------------- Summary of changes: gnbd-kernel/src/gnbd.c | 60 ++++++++++++++++++++++++++++++++++++++++++++--- gnbd-kernel/src/gnbd.h | 3 ++ 2 files changed, 59 insertions(+), 4 deletions(-) diff --git a/gnbd-kernel/src/gnbd.c b/gnbd-kernel/src/gnbd.c index d6a8035..ade7347 100644 --- a/gnbd-kernel/src/gnbd.c +++ b/gnbd-kernel/src/gnbd.c @@ -254,6 +254,26 @@ static const char *gnbdcmd_to_ascii(int cmd) } #endif /* NDEBUG */ + +static int wait_for_send(struct request *req, struct gnbd_device *dev) +{ + DECLARE_WAITQUEUE(wait, current); + + add_wait_queue(&dev->tx_wait, &wait); + while(dev->current_request == req) { + set_current_state(TASK_INTERRUPTIBLE); + if (signal_pending(current)) { + printk(KERN_WARNING "gnbd (pid %d: %s) wait interrupted by signal\n", + current->pid, current->comm); + return -EINTR; + } + schedule(); + } + set_current_state(TASK_RUNNING); + remove_wait_queue(&dev->tx_wait, &wait); + return 0; +} + static void gnbd_end_request(struct request *req) { int error = req->errors ? -EIO : 0; @@ -369,6 +389,12 @@ int __gnbd_send_req(struct gnbd_device *dev, struct socket *sock, down(&dev->tx_lock); + if (dev->corrupt) { + printk(KERN_ERR "%s: Attempted to send on a faulty socket\n", + dev->disk->disk_name); + result = -EBADFD; + goto error_out; + } if (!sock) { printk(KERN_ERR "%s: Attempted send on closed socket\n", dev->disk->disk_name); @@ -381,13 +407,14 @@ int __gnbd_send_req(struct gnbd_device *dev, struct socket *sock, gnbdcmd_to_ascii(gnbd_cmd(req)), (unsigned long long)req->sector << 9, req->nr_sectors << 9); + dev->current_request = req; result = sock_xmit(sock, 1, &request, sizeof(request), (gnbd_cmd(req) == GNBD_CMD_WRITE)? MSG_MORE: 0, can_signal); if (result < 0) { printk(KERN_ERR "%s: Send control failed (result %d)\n", dev->disk->disk_name, result); - goto error_out; + goto send_error_out; } if (gnbd_cmd(req) == GNBD_CMD_WRITE) { @@ -410,13 +437,19 @@ int __gnbd_send_req(struct gnbd_device *dev, struct socket *sock, printk(KERN_ERR "%s: Send data failed (result %d)\n", dev->disk->disk_name, result); - goto error_out; + goto send_error_out; } } } + dev->current_request = NULL; + wake_up(&dev->tx_wait); up(&dev->tx_lock); return 0; +send_error_out: + dev->corrupt = 1; + dev->current_request = NULL; + wake_up(&dev->tx_wait); error_out: up(&dev->tx_lock); return result; @@ -477,6 +510,11 @@ int gnbd_do_it(struct gnbd_device *dev) BUG_ON(dev->magic != GNBD_MAGIC); while((result = sock_xmit(sock, 0, &reply,sizeof(reply), MSG_WAITALL, 1)) > 0){ + if (dev->corrupt) { + printk(KERN_ERR "%s: faulty socket\n",dev->disk->disk_name); + return -EBADFD; + } + if (ntohl(reply.magic) == GNBD_KEEP_ALIVE_MAGIC) /* FIXME -- I should reset the wait time here */ continue; @@ -511,6 +549,9 @@ int gnbd_do_it(struct gnbd_device *dev) return result; } remove_req: + result = wait_for_send(req, dev); + if (result != 0) + return result; spin_lock(&dev->queue_lock); list_del_init(&req->queuelist); dev->last_received = jiffies; @@ -523,8 +564,9 @@ remove_req: return result; } -void gnbd_clear_que(struct gnbd_device *dev) +int gnbd_clear_que(struct gnbd_device *dev) { + int err; struct request *req; BUG_ON(dev->magic != GNBD_MAGIC); @@ -533,6 +575,9 @@ void gnbd_clear_que(struct gnbd_device *dev) req = NULL; if (!list_empty(&dev->queue_head)) { req = list_entry(dev->queue_head.next, struct request, queuelist); + err = wait_for_send(req, dev); + if (err) + return err; list_del_init(&req->queuelist); } if (req && req != &ping_req) { @@ -540,6 +585,8 @@ void gnbd_clear_que(struct gnbd_device *dev) gnbd_end_request(req); } } while (req); + + return 0; } /* @@ -693,7 +740,9 @@ static int gnbd_ctl_ioctl(struct inode *inode, struct file *file, if (down_interruptible(&dev->do_it_lock)) return -EBUSY; dev->receiver_pid = -1; - gnbd_clear_que(dev); + error = gnbd_clear_que(dev); + if (error) + return error; bdev = dev->bdev; if (bdev) { blk_run_queue(dev->disk->queue); @@ -735,6 +784,7 @@ static int gnbd_ctl_ioctl(struct inode *inode, struct file *file, } dev->file = file; dev->sock = SOCKET_I(inode); + dev->corrupt = 0; dev->receiver_pid = current->pid; blk_run_queue(dev->disk->queue); error = gnbd_do_it(dev); @@ -961,6 +1011,8 @@ static int __init gnbd_init(void) INIT_LIST_HEAD(&gnbd_dev[i].queue_head); init_MUTEX(&gnbd_dev[i].tx_lock); init_MUTEX(&gnbd_dev[i].do_it_lock); + init_waitqueue_head(&gnbd_dev[i].tx_wait); + gnbd_dev[i].current_request = NULL; gnbd_dev[i].class_dev.class = &gnbd_class; sprintf(gnbd_dev[i].class_dev.class_id, "gnbd%d", i); err = class_device_register(&gnbd_dev[i].class_dev); diff --git a/gnbd-kernel/src/gnbd.h b/gnbd-kernel/src/gnbd.h index b868f86..8456d25 100644 --- a/gnbd-kernel/src/gnbd.h +++ b/gnbd-kernel/src/gnbd.h @@ -43,6 +43,9 @@ struct gnbd_device { char name[32]; unsigned long last_received; struct block_device *bdev; + struct request *current_request; + wait_queue_head_t tx_wait; + int corrupt; }; #endif /* __KERNEL__ */ hooks/post-receive -- Cluster Project
reply other threads:[~2008-06-20 4:20 UTC|newest] Thread overview: [no followups] expand[flat|nested] mbox.gz Atom feed
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=20080620042033.16654.qmail@sourceware.org \ --to=fabbione@sourceware.org \ --cc=cluster-cvs@sources.redhat.com \ --cc=cluster-devel@redhat.com \ /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: linkBe sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions for how to clone and mirror all data and code used for this inbox; as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).