diff --git a/sys/arch/xen/xenbus/xenbus_dev.c b/sys/arch/xen/xenbus/xenbus_dev.c index 9b0789a8fd1b..83eebfd14484 100644 --- a/sys/arch/xen/xenbus/xenbus_dev.c +++ b/sys/arch/xen/xenbus/xenbus_dev.c @@ -1,4 +1,4 @@ -/* $NetBSD: xenbus_dev.c,v 1.15 2020/04/07 08:14:43 jdolecek Exp $ */ +/* $NetBSD: xenbus_dev.c,v 1.16 2020/04/07 15:43:42 jdolecek Exp $ */ /* * xenbus_dev.c * @@ -31,16 +31,16 @@ */ #include -__KERNEL_RCSID(0, "$NetBSD: xenbus_dev.c,v 1.15 2020/04/07 08:14:43 jdolecek Exp $"); +__KERNEL_RCSID(0, "$NetBSD: xenbus_dev.c,v 1.16 2020/04/07 15:43:42 jdolecek Exp $"); #include "opt_xen.h" #include #include #include -#include #include #include +#include #include #include #include @@ -289,8 +289,7 @@ xenbus_dev_write(void *v) err = xenbus_dev_request_and_reply(&xlwp->u.msg, &reply); if (err == 0) { if (xlwp->u.msg.type == XS_TRANSACTION_START) { - trans = malloc(sizeof(*trans), M_DEVBUF, - M_WAITOK); + trans = kmem_alloc(sizeof(*trans), KM_SLEEP); trans->handle = (struct xenbus_transaction *) strtoul(reply, NULL, 0); SLIST_INSERT_HEAD(&xlwp->transactions, @@ -308,7 +307,7 @@ xenbus_dev_write(void *v) } SLIST_REMOVE(&xlwp->transactions, trans, xenbus_dev_transaction, trans_next); - free(trans, M_DEVBUF); + kmem_free(trans, sizeof(*trans)); } queue_reply(xlwp, (char *)&xlwp->u.msg, sizeof(xlwp->u.msg)); @@ -348,37 +347,50 @@ xenbus_dev_open(void *v) mutex_enter(&xenbus_dev_open_mtx); u = kfs->kfs_v; if (u == NULL) { - u = malloc(sizeof(*u), M_DEVBUF, M_WAITOK); - if (u == NULL) { - mutex_exit(&xenbus_dev_open_mtx); - return ENOMEM; - } - memset(u, 0, sizeof(*u)); + mutex_exit(&xenbus_dev_open_mtx); + + u = kmem_zalloc(sizeof(*u), KM_SLEEP); SLIST_INIT(&u->lwps); mutex_init(&u->mtx, MUTEX_DEFAULT, IPL_NONE); - kfs->kfs_v = u; + + mutex_enter(&xenbus_dev_open_mtx); + /* + * Must re-check if filled while waiting in alloc + * by some other lwp. + */ + if (kfs->kfs_v) { + kmem_free(u, sizeof(*u)); + u = kfs->kfs_v; + } else { + kfs->kfs_v = u; + } }; - mutex_enter(&u->mtx); mutex_exit(&xenbus_dev_open_mtx); + + mutex_enter(&u->mtx); SLIST_FOREACH(xlwp, &u->lwps, lwp_next) { if (xlwp->lwp == curlwp) { break; } } if (xlwp == NULL) { - xlwp = malloc(sizeof(*xlwp ), M_DEVBUF, M_WAITOK); - if (xlwp == NULL) { - mutex_exit(&u->mtx); - return ENOMEM; - } - memset(xlwp, 0, sizeof(*xlwp)); + mutex_exit(&u->mtx); + + xlwp = kmem_zalloc(sizeof(*xlwp), KM_SLEEP); xlwp->lwp = curlwp; SLIST_INIT(&xlwp->transactions); mutex_init(&xlwp->mtx, MUTEX_DEFAULT, IPL_NONE); - SLIST_INSERT_HEAD(&u->lwps, - xlwp, lwp_next); + + mutex_enter(&u->mtx); + /* + * While alloc can block, this can't be re-entered with + * curlwp, so no need to re-check. Also the node can't + * be closed while we are blocked here. + */ + SLIST_INSERT_HEAD(&u->lwps, xlwp, lwp_next); } mutex_exit(&u->mtx); + return 0; } @@ -415,7 +427,7 @@ xenbus_dev_close(void *v) trans = SLIST_FIRST(&xlwp->transactions); xenbus_transaction_end(trans->handle, 1); SLIST_REMOVE_HEAD(&xlwp->transactions, trans_next); - free(trans, M_DEVBUF); + kmem_free(trans, sizeof(*trans)); } mutex_exit(&xlwp->mtx); SLIST_REMOVE(&u->lwps, xlwp, xenbus_dev_lwp, lwp_next); @@ -430,8 +442,8 @@ xenbus_dev_close(void *v) mutex_destroy(&u->mtx); kfs->kfs_v = NULL; mutex_exit(&xenbus_dev_open_mtx); - free(xlwp, M_DEVBUF); - free(u, M_DEVBUF); + kmem_free(xlwp, sizeof(*xlwp)); + kmem_free(u, sizeof(*u)); return 0; }