mirror of
https://git.FreeBSD.org/src.git
synced 2025-01-26 16:18:31 +00:00
xen: fix xenstore dev
Xenstore user-space device has two problems currently: - It does not correctly handle concurrent clients, because it's storing each client data in dev->si_drv1. - It does not correctly free this data when the client closes the device. In order to solve both of this issues store the per-client data using cdevpriv, which also comes with a hook in order to perform the necessary cleanup on device close. While there also make the device eternal. Sponsored by: Citrix Systems R&D Reported and Tested by: thompsa MFC after: 2 weeks
This commit is contained in:
parent
39a58828ef
commit
f79cdf2998
Notes:
svn2git
2020-12-20 02:59:44 +00:00
svn path=/head/; revision=278844
@ -77,7 +77,11 @@ static int
|
||||
xs_dev_read(struct cdev *dev, struct uio *uio, int ioflag)
|
||||
{
|
||||
int error;
|
||||
struct xs_dev_data *u = dev->si_drv1;
|
||||
struct xs_dev_data *u;
|
||||
|
||||
error = devfs_get_cdevpriv((void **)&u);
|
||||
if (error != 0)
|
||||
return (error);
|
||||
|
||||
while (u->read_prod == u->read_cons) {
|
||||
error = tsleep(u, PCATCH, "xsdread", hz/10);
|
||||
@ -115,11 +119,15 @@ static int
|
||||
xs_dev_write(struct cdev *dev, struct uio *uio, int ioflag)
|
||||
{
|
||||
int error;
|
||||
struct xs_dev_data *u = dev->si_drv1;
|
||||
struct xs_dev_data *u;
|
||||
struct xs_dev_transaction *trans;
|
||||
void *reply;
|
||||
int len = uio->uio_resid;
|
||||
|
||||
error = devfs_get_cdevpriv((void **)&u);
|
||||
if (error != 0)
|
||||
return (error);
|
||||
|
||||
if ((len + u->len) > sizeof(u->u.buffer))
|
||||
return (EINVAL);
|
||||
|
||||
@ -177,25 +185,10 @@ xs_dev_write(struct cdev *dev, struct uio *uio, int ioflag)
|
||||
return (error);
|
||||
}
|
||||
|
||||
static int
|
||||
xs_dev_open(struct cdev *dev, int oflags, int devtype, struct thread *td)
|
||||
static void
|
||||
xs_dev_dtor(void *arg)
|
||||
{
|
||||
struct xs_dev_data *u;
|
||||
|
||||
#if 0 /* XXX figure out if equiv needed */
|
||||
nonseekable_open(inode, filp);
|
||||
#endif
|
||||
u = malloc(sizeof(*u), M_XENSTORE, M_WAITOK|M_ZERO);
|
||||
LIST_INIT(&u->transactions);
|
||||
dev->si_drv1 = u;
|
||||
|
||||
return (0);
|
||||
}
|
||||
|
||||
static int
|
||||
xs_dev_close(struct cdev *dev, int fflag, int devtype, struct thread *td)
|
||||
{
|
||||
struct xs_dev_data *u = dev->si_drv1;
|
||||
struct xs_dev_data *u = arg;
|
||||
struct xs_dev_transaction *trans, *tmp;
|
||||
|
||||
LIST_FOREACH_SAFE(trans, &u->transactions, list, tmp) {
|
||||
@ -205,7 +198,21 @@ xs_dev_close(struct cdev *dev, int fflag, int devtype, struct thread *td)
|
||||
}
|
||||
|
||||
free(u, M_XENSTORE);
|
||||
return (0);
|
||||
}
|
||||
|
||||
static int
|
||||
xs_dev_open(struct cdev *dev, int oflags, int devtype, struct thread *td)
|
||||
{
|
||||
struct xs_dev_data *u;
|
||||
int error;
|
||||
|
||||
u = malloc(sizeof(*u), M_XENSTORE, M_WAITOK|M_ZERO);
|
||||
LIST_INIT(&u->transactions);
|
||||
error = devfs_set_cdevpriv(u, xs_dev_dtor);
|
||||
if (error != 0)
|
||||
free(u, M_XENSTORE);
|
||||
|
||||
return (error);
|
||||
}
|
||||
|
||||
static struct cdevsw xs_dev_cdevsw = {
|
||||
@ -213,7 +220,6 @@ static struct cdevsw xs_dev_cdevsw = {
|
||||
.d_read = xs_dev_read,
|
||||
.d_write = xs_dev_write,
|
||||
.d_open = xs_dev_open,
|
||||
.d_close = xs_dev_close,
|
||||
.d_name = "xs_dev",
|
||||
};
|
||||
|
||||
@ -262,8 +268,8 @@ xs_dev_attach(device_t dev)
|
||||
{
|
||||
struct cdev *xs_cdev;
|
||||
|
||||
xs_cdev = make_dev(&xs_dev_cdevsw, 0, UID_ROOT, GID_WHEEL, 0400,
|
||||
"xen/xenstore");
|
||||
xs_cdev = make_dev_credf(MAKEDEV_ETERNAL, &xs_dev_cdevsw, 0, NULL,
|
||||
UID_ROOT, GID_WHEEL, 0400, "xen/xenstore");
|
||||
if (xs_cdev == NULL)
|
||||
return (EINVAL);
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user