# HG changeset patch
# User cl349@xxxxxxxxxxxxxxxxxxxx
# Node ID 80afc502461b56539092dec5c1fa6df05df8baf2
# Parent 282d5698ea40f40dc09871f0c92dc691b10b7269
Change xenbus_dev interface from ioctl to read/write.
Check boundaries so we can recover if userspace dies.
Also simplifies libxenstore.
Signed-off-by: Rusty Russell <rusty@xxxxxxxxxxxxxxx>
Signed-off-by: Christian Limpach <Christian.Limpach@xxxxxxxxxxxx>
diff -r 282d5698ea40 -r 80afc502461b .hgignore
--- a/.hgignore Mon Sep 12 20:46:37 2005
+++ b/.hgignore Mon Sep 12 21:12:16 2005
@@ -152,7 +152,6 @@
^tools/xenstat/xentop/xentop$
^tools/xenstore/testsuite/tmp/.*$
^tools/xenstore/xen$
-^tools/xenstore/xenbus_dev.h$
^tools/xenstore/xenstored$
^tools/xenstore/xenstored_test$
^tools/xenstore/xenstore-read$
diff -r 282d5698ea40 -r 80afc502461b
linux-2.6-xen-sparse/drivers/xen/xenbus/xenbus_dev.c
--- a/linux-2.6-xen-sparse/drivers/xen/xenbus/xenbus_dev.c Mon Sep 12
20:46:37 2005
+++ b/linux-2.6-xen-sparse/drivers/xen/xenbus/xenbus_dev.c Mon Sep 12
21:12:16 2005
@@ -5,6 +5,7 @@
* to xenstore.
*
* Copyright (c) 2005, Christian Limpach
+ * Copyright (c) 2005, Rusty Russell, IBM Corporation
*
* This file may be distributed separately from the Linux kernel, or
* incorporated into other software packages, subject to the following license:
@@ -41,104 +42,96 @@
#include <asm/uaccess.h>
#include <asm-xen/xenbus.h>
-#include <asm-xen/linux-public/xenbus_dev.h>
#include <asm-xen/xen_proc.h>
struct xenbus_dev_data {
- int in_transaction;
+ /* Are there bytes left to be read in this message? */
+ int bytes_left;
+ /* Are we still waiting for the reply to a message we wrote? */
+ int awaiting_reply;
+ /* Buffer for outgoing messages. */
+ unsigned int len;
+ union {
+ struct xsd_sockmsg msg;
+ char buffer[PAGE_SIZE];
+ } u;
};
static struct proc_dir_entry *xenbus_dev_intf;
-void *xs_talkv(enum xsd_sockmsg_type type, const struct kvec *iovec,
- unsigned int num_vecs, unsigned int *len);
+/* Reply can be long (dir, getperm): don't buffer, just examine
+ * headers so we can discard rest if they die. */
+static ssize_t xenbus_dev_read(struct file *filp,
+ char __user *ubuf,
+ size_t len, loff_t *ppos)
+{
+ struct xenbus_dev_data *data = filp->private_data;
+ struct xsd_sockmsg msg;
+ int err;
-static int xenbus_dev_talkv(struct xenbus_dev_data *u, unsigned long data)
-{
- struct xenbus_dev_talkv xt;
- unsigned int len;
- void *resp, *base;
- struct kvec *iovec;
- int ret = -EFAULT, v = 0;
+ /* Refill empty buffer? */
+ if (data->bytes_left == 0) {
+ if (len < sizeof(msg))
+ return -EINVAL;
- if (copy_from_user(&xt, (void *)data, sizeof(xt)))
- return -EFAULT;
-
- iovec = kmalloc(xt.num_vecs * sizeof(struct kvec), GFP_KERNEL);
- if (iovec == NULL)
- return -ENOMEM;
-
- if (copy_from_user(iovec, xt.iovec,
- xt.num_vecs * sizeof(struct kvec)))
- goto out;
-
- for (v = 0; v < xt.num_vecs; v++) {
- base = iovec[v].iov_base;
- iovec[v].iov_base = kmalloc(iovec[v].iov_len, GFP_KERNEL);
- if (iovec[v].iov_base == NULL ||
- copy_from_user(iovec[v].iov_base, base, iovec[v].iov_len))
- {
- if (iovec[v].iov_base)
- kfree(iovec[v].iov_base);
- else
- ret = -ENOMEM;
- v--;
- goto out;
- }
+ err = xb_read(&msg, sizeof(msg));
+ if (err)
+ return err;
+ data->bytes_left = msg.len;
+ if (ubuf && copy_to_user(ubuf, &msg, sizeof(msg)) != 0)
+ return -EFAULT;
+ /* We can receive spurious XS_WATCH_EVENT messages. */
+ if (msg.type != XS_WATCH_EVENT)
+ data->awaiting_reply = 0;
+ return sizeof(msg);
}
- resp = xs_talkv(xt.type, iovec, xt.num_vecs, &len);
- if (IS_ERR(resp)) {
- ret = PTR_ERR(resp);
- goto out;
- }
+ /* Don't read over next header, or over temporary buffer. */
+ if (len > sizeof(data->u.buffer))
+ len = sizeof(data->u.buffer);
+ if (len > data->bytes_left)
+ len = data->bytes_left;
- switch (xt.type) {
- case XS_TRANSACTION_START:
- u->in_transaction = 1;
- break;
- case XS_TRANSACTION_END:
- u->in_transaction = 0;
- break;
- default:
- break;
- }
+ err = xb_read(data->u.buffer, len);
+ if (err)
+ return err;
- ret = len;
- if (len > xt.len)
- len = xt.len;
-
- if (copy_to_user(xt.buf, resp, len))
- ret = -EFAULT;
-
- kfree(resp);
- out:
- while (v-- > 0)
- kfree(iovec[v].iov_base);
- kfree(iovec);
- return ret;
+ data->bytes_left -= len;
+ if (ubuf && copy_to_user(ubuf, data->u.buffer, len) != 0)
+ return -EFAULT;
+ return len;
}
-static int xenbus_dev_ioctl(struct inode *inode, struct file *filp,
- unsigned int cmd, unsigned long data)
+/* We do v. basic sanity checking so they don't screw up kernel later. */
+static ssize_t xenbus_dev_write(struct file *filp,
+ const char __user *ubuf,
+ size_t len, loff_t *ppos)
{
- struct xenbus_dev_data *u = filp->private_data;
- int ret = -ENOSYS;
+ struct xenbus_dev_data *data = filp->private_data;
+ int err;
- switch (cmd) {
- case IOCTL_XENBUS_DEV_TALKV:
- ret = xenbus_dev_talkv(u, data);
- break;
- default:
- ret = -EINVAL;
- break;
+ /* We gather data in buffer until we're ready to send it. */
+ if (len > data->len + sizeof(data->u))
+ return -EINVAL;
+ if (copy_from_user(data->u.buffer + data->len, ubuf, len) != 0)
+ return -EFAULT;
+ data->len += len;
+ if (data->len >= sizeof(data->u.msg) + data->u.msg.len) {
+ err = xb_write(data->u.buffer, data->len);
+ if (err)
+ return err;
+ data->len = 0;
+ data->awaiting_reply = 1;
}
- return ret;
+ return len;
}
static int xenbus_dev_open(struct inode *inode, struct file *filp)
{
struct xenbus_dev_data *u;
+
+ /* Don't try seeking. */
+ nonseekable_open(inode, filp);
u = kmalloc(sizeof(*u), GFP_KERNEL);
if (u == NULL)
@@ -155,20 +148,25 @@
static int xenbus_dev_release(struct inode *inode, struct file *filp)
{
- struct xenbus_dev_data *u = filp->private_data;
+ struct xenbus_dev_data *data = filp->private_data;
- if (u->in_transaction)
- xenbus_transaction_end(1);
+ /* Discard any unread replies. */
+ while (data->bytes_left || data->awaiting_reply)
+ xenbus_dev_read(filp, NULL, sizeof(data->u.buffer), NULL);
+
+ /* Harmless if no transaction in progress. */
+ xenbus_transaction_end(1);
up(&xenbus_lock);
- kfree(u);
+ kfree(data);
return 0;
}
static struct file_operations xenbus_dev_file_ops = {
- .ioctl = xenbus_dev_ioctl,
+ .read = xenbus_dev_read,
+ .write = xenbus_dev_write,
.open = xenbus_dev_open,
.release = xenbus_dev_release,
};
diff -r 282d5698ea40 -r 80afc502461b
linux-2.6-xen-sparse/drivers/xen/xenbus/xenbus_xs.c
--- a/linux-2.6-xen-sparse/drivers/xen/xenbus/xenbus_xs.c Mon Sep 12
20:46:37 2005
+++ b/linux-2.6-xen-sparse/drivers/xen/xenbus/xenbus_xs.c Mon Sep 12
21:12:16 2005
@@ -106,10 +106,10 @@
}
/* Send message to xs, get kmalloc'ed reply. ERR_PTR() on error. */
-void *xs_talkv(enum xsd_sockmsg_type type,
- const struct kvec *iovec,
- unsigned int num_vecs,
- unsigned int *len)
+static void *xs_talkv(enum xsd_sockmsg_type type,
+ const struct kvec *iovec,
+ unsigned int num_vecs,
+ unsigned int *len)
{
struct xsd_sockmsg msg;
void *ret = NULL;
diff -r 282d5698ea40 -r 80afc502461b tools/xenstore/Makefile
--- a/tools/xenstore/Makefile Mon Sep 12 20:46:37 2005
+++ b/tools/xenstore/Makefile Mon Sep 12 21:12:16 2005
@@ -17,7 +17,6 @@
BASECFLAGS+= -I$(XEN_ROOT)/tools/libxc
BASECFLAGS+= -I$(XEN_ROOT)/xen/include/public
BASECFLAGS+= -I.
-BASECFLAGS+= -I$(XEN_ROOT)/linux-2.6-xen-sparse/include/asm-xen/linux-public
CFLAGS += $(BASECFLAGS)
LDFLAGS += $(PROFILE) -L$(XEN_LIBXC)
diff -r 282d5698ea40 -r 80afc502461b tools/xenstore/xs.c
--- a/tools/xenstore/xs.c Mon Sep 12 20:46:37 2005
+++ b/tools/xenstore/xs.c Mon Sep 12 21:12:16 2005
@@ -36,12 +36,10 @@
#include "xenstored.h"
#include "xs_lib.h"
#include "utils.h"
-#include "xenbus_dev.h"
struct xs_handle
{
int fd;
- enum { SOCK, DEV } type;
};
/* Get the socket from the store daemon handle.
@@ -68,7 +66,6 @@
h = malloc(sizeof(*h));
if (h) {
h->fd = sock;
- h->type = SOCK;
return h;
}
}
@@ -82,16 +79,15 @@
static struct xs_handle *get_dev(const char *connect_to)
{
int fd, saved_errno;
- struct xs_handle *h = NULL;
-
- fd = open(connect_to, O_RDONLY);
+ struct xs_handle *h;
+
+ fd = open(connect_to, O_RDWR);
if (fd < 0)
return NULL;
h = malloc(sizeof(*h));
if (h) {
h->fd = fd;
- h->type = DEV;
return h;
}
@@ -190,9 +186,9 @@
}
/* Send message to xs, get malloc'ed reply. NULL and set errno on error. */
-static void *xs_talkv_sock(struct xs_handle *h, enum xsd_sockmsg_type type,
- const struct iovec *iovec, unsigned int num_vecs,
- unsigned int *len)
+static void *xs_talkv(struct xs_handle *h, enum xsd_sockmsg_type type,
+ const struct iovec *iovec, unsigned int num_vecs,
+ unsigned int *len)
{
struct xsd_sockmsg msg;
void *ret = NULL;
@@ -250,54 +246,6 @@
close(h->fd);
h->fd = -1;
errno = saved_errno;
- return NULL;
-}
-
-/* Send message to xs, get malloc'ed reply. NULL and set errno on error. */
-static void *xs_talkv_dev(struct xs_handle *h, enum xsd_sockmsg_type type,
- const struct iovec *iovec, unsigned int num_vecs,
- unsigned int *len)
-{
- struct xenbus_dev_talkv dt;
- char *buf;
- int err, buflen = 1024;
-
- again:
- buf = malloc(buflen);
- if (buf == NULL) {
- errno = ENOMEM;
- return NULL;
- }
- dt.type = type;
- dt.iovec = (struct kvec *)iovec;
- dt.num_vecs = num_vecs;
- dt.buf = buf;
- dt.len = buflen;
- err = ioctl(h->fd, IOCTL_XENBUS_DEV_TALKV, &dt);
- if (err < 0) {
- free(buf);
- errno = err;
- return NULL;
- }
- if (err > buflen) {
- free(buf);
- buflen = err;
- goto again;
- }
- if (len)
- *len = err;
- return buf;
-}
-
-/* Send message to xs, get malloc'ed reply. NULL and set errno on error. */
-static void *xs_talkv(struct xs_handle *h, enum xsd_sockmsg_type type,
- const struct iovec *iovec, unsigned int num_vecs,
- unsigned int *len)
-{
- if (h->type == SOCK)
- return xs_talkv_sock(h, type, iovec, num_vecs, len);
- if (h->type == DEV)
- return xs_talkv_dev(h, type, iovec, num_vecs, len);
return NULL;
}
diff -r 282d5698ea40 -r 80afc502461b
linux-2.6-xen-sparse/include/asm-xen/linux-public/xenbus_dev.h
--- a/linux-2.6-xen-sparse/include/asm-xen/linux-public/xenbus_dev.h Mon Sep
12 20:46:37 2005
+++ /dev/null Mon Sep 12 21:12:16 2005
@@ -1,47 +0,0 @@
-/*
- * xenbus_dev.h
- *
- * Copyright (c) 2005, Christian Limpach
- *
- * This file may be distributed separately from the Linux kernel, or
- * incorporated into other software packages, subject to the following license:
- *
- * Permission is hereby granted, free of charge, to any person obtaining a copy
- * of this source file (the "Software"), to deal in the Software without
- * restriction, including without limitation the rights to use, copy, modify,
- * merge, publish, distribute, sublicense, and/or sell copies of the Software,
- * and to permit persons to whom the Software is furnished to do so, subject to
- * the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in
- * all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
- * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
- * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
- * IN THE SOFTWARE.
- */
-
-#ifndef _XENBUS_DEV_H_
-#define _XENBUS_DEV_H_
-
-struct xenbus_dev_talkv {
- enum xsd_sockmsg_type type;
- const struct kvec *iovec;
- unsigned int num_vecs;
- char *buf;
- unsigned int len;
-};
-
-/*
- * @cmd: IOCTL_XENBUS_DEV_TALKV
- * @arg: struct xenbus_dev_talkv
- * Return: 0 on success, error code on failure.
- */
-#define IOCTL_XENBUS_DEV_TALKV \
- _IOC(_IOC_NONE, 'X', 0, sizeof(struct xenbus_dev_talkv))
-
-#endif /* _XENBUS_DEV_H_ */
_______________________________________________
Xen-changelog mailing list
Xen-changelog@xxxxxxxxxxxxxxxxxxx
http://lists.xensource.com/xen-changelog
|