summaryrefslogtreecommitdiffstats
path: root/sys/kern/kern_conf.c
diff options
context:
space:
mode:
authorkib <kib@FreeBSD.org>2010-05-06 19:22:50 +0000
committerkib <kib@FreeBSD.org>2010-05-06 19:22:50 +0000
commit77dcee692636f8f049511471d8c21c5821ade009 (patch)
tree07045cda76ff8aacd7c407e9e4115ed99973521d /sys/kern/kern_conf.c
parentfecc56fac19c93c470f79d1f557c149bd3c1e9b0 (diff)
downloadFreeBSD-src-77dcee692636f8f049511471d8c21c5821ade009.zip
FreeBSD-src-77dcee692636f8f049511471d8c21c5821ade009.tar.gz
Add MAKEDEV_NOWAIT flag to make_dev_credf(9), to create a device node
in a no-sleep context. If resource allocation cannot be done without sleep, make_dev_credf() fails and returns NULL. Reviewed by: jh MFC after: 2 weeks
Diffstat (limited to 'sys/kern/kern_conf.c')
-rw-r--r--sys/kern/kern_conf.c47
1 files changed, 28 insertions, 19 deletions
diff --git a/sys/kern/kern_conf.c b/sys/kern/kern_conf.c
index a2e292e..17a6827 100644
--- a/sys/kern/kern_conf.c
+++ b/sys/kern/kern_conf.c
@@ -505,7 +505,7 @@ giant_mmap_single(struct cdev *dev, vm_ooffset_t *offset, vm_size_t size,
}
static void
-notify(struct cdev *dev, const char *ev)
+notify(struct cdev *dev, const char *ev, int flags)
{
static const char prefix[] = "cdev=";
char *data;
@@ -514,7 +514,8 @@ notify(struct cdev *dev, const char *ev)
if (cold)
return;
namelen = strlen(dev->si_name);
- data = malloc(namelen + sizeof(prefix), M_TEMP, M_NOWAIT);
+ data = malloc(namelen + sizeof(prefix), M_TEMP,
+ (flags & MAKEDEV_NOWAIT) ? M_NOWAIT : M_WAITOK);
if (data == NULL)
return;
memcpy(data, prefix, sizeof(prefix) - 1);
@@ -524,17 +525,17 @@ notify(struct cdev *dev, const char *ev)
}
static void
-notify_create(struct cdev *dev)
+notify_create(struct cdev *dev, int flags)
{
- notify(dev, "CREATE");
+ notify(dev, "CREATE", flags);
}
static void
notify_destroy(struct cdev *dev)
{
- notify(dev, "DESTROY");
+ notify(dev, "DESTROY", MAKEDEV_WAITOK);
}
static struct cdev *
@@ -572,24 +573,27 @@ fini_cdevsw(struct cdevsw *devsw)
devsw->d_flags &= ~D_INIT;
}
-static void
-prep_cdevsw(struct cdevsw *devsw)
+static int
+prep_cdevsw(struct cdevsw *devsw, int flags)
{
struct cdevsw *dsw2;
mtx_assert(&devmtx, MA_OWNED);
if (devsw->d_flags & D_INIT)
- return;
+ return (1);
if (devsw->d_flags & D_NEEDGIANT) {
dev_unlock();
- dsw2 = malloc(sizeof *dsw2, M_DEVT, M_WAITOK);
+ dsw2 = malloc(sizeof *dsw2, M_DEVT,
+ (flags & MAKEDEV_NOWAIT) ? M_NOWAIT : M_WAITOK);
dev_lock();
+ if (dsw2 == NULL && !(devsw->d_flags & D_INIT))
+ return (0);
} else
dsw2 = NULL;
if (devsw->d_flags & D_INIT) {
if (dsw2 != NULL)
cdevsw_free_devlocked(dsw2);
- return;
+ return (1);
}
if (devsw->d_version != D_VERSION_03) {
@@ -647,6 +651,7 @@ prep_cdevsw(struct cdevsw *devsw)
if (dsw2 != NULL)
cdevsw_free_devlocked(dsw2);
+ return (1);
}
static struct cdev *
@@ -657,9 +662,15 @@ make_dev_credv(int flags, struct cdevsw *devsw, int unit,
struct cdev *dev;
int i;
- dev = devfs_alloc();
+ dev = devfs_alloc(flags);
+ if (dev == NULL)
+ return (NULL);
dev_lock();
- prep_cdevsw(devsw);
+ if (!prep_cdevsw(devsw, flags)) {
+ dev_unlock();
+ devfs_free(dev);
+ return (NULL);
+ }
dev = newdev(devsw, unit, dev);
if (flags & MAKEDEV_REF)
dev_refl(dev);
@@ -686,8 +697,6 @@ make_dev_credv(int flags, struct cdevsw *devsw, int unit,
dev->si_flags |= SI_NAMED;
if (cr != NULL)
dev->si_cred = crhold(cr);
- else
- dev->si_cred = NULL;
dev->si_uid = uid;
dev->si_gid = gid;
dev->si_mode = mode;
@@ -696,7 +705,7 @@ make_dev_credv(int flags, struct cdevsw *devsw, int unit,
clean_unrhdrl(devfs_inos);
dev_unlock_and_free();
- notify_create(dev);
+ notify_create(dev, flags);
return (dev);
}
@@ -771,7 +780,7 @@ make_dev_alias(struct cdev *pdev, const char *fmt, ...)
int i;
KASSERT(pdev != NULL, ("NULL pdev"));
- dev = devfs_alloc();
+ dev = devfs_alloc(MAKEDEV_WAITOK);
dev_lock();
dev->si_flags |= SI_ALIAS;
dev->si_flags |= SI_NAMED;
@@ -788,7 +797,7 @@ make_dev_alias(struct cdev *pdev, const char *fmt, ...)
clean_unrhdrl(devfs_inos);
dev_unlock();
- notify_create(dev);
+ notify_create(dev, MAKEDEV_WAITOK);
return (dev);
}
@@ -973,9 +982,9 @@ clone_create(struct clonedevs **cdp, struct cdevsw *csw, int *up,
* the end of the list.
*/
unit = *up;
- ndev = devfs_alloc();
+ ndev = devfs_alloc(MAKEDEV_WAITOK);
dev_lock();
- prep_cdevsw(csw);
+ prep_cdevsw(csw, MAKEDEV_WAITOK);
low = extra;
de = dl = NULL;
cd = *cdp;
OpenPOWER on IntegriCloud