Author: royger
Date: Mon Feb 16 09:53:43 2015
New Revision: 278844
URL: https://svnweb.freebsd.org/changeset/base/278844

Log:
  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

Modified:
  head/sys/dev/xen/xenstore/xenstore_dev.c

Modified: head/sys/dev/xen/xenstore/xenstore_dev.c
==============================================================================
--- head/sys/dev/xen/xenstore/xenstore_dev.c    Mon Feb 16 07:01:02 2015        
(r278843)
+++ head/sys/dev/xen/xenstore/xenstore_dev.c    Mon Feb 16 09:53:43 2015        
(r278844)
@@ -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 ui
        return (error);
 }
 
-static int
-xs_dev_open(struct cdev *dev, int oflags, int devtype, struct thread *td)
-{
-       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)
+static void
+xs_dev_dtor(void *arg)
 {
-       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
        }
 
        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);
 
_______________________________________________
svn-src-head@freebsd.org mailing list
http://lists.freebsd.org/mailman/listinfo/svn-src-head
To unsubscribe, send any mail to "svn-src-head-unsubscr...@freebsd.org"

Reply via email to