diff options
author | kib <kib@FreeBSD.org> | 2010-05-06 19:22:50 +0000 |
---|---|---|
committer | kib <kib@FreeBSD.org> | 2010-05-06 19:22:50 +0000 |
commit | 77dcee692636f8f049511471d8c21c5821ade009 (patch) | |
tree | 07045cda76ff8aacd7c407e9e4115ed99973521d /sys/kern/kern_conf.c | |
parent | fecc56fac19c93c470f79d1f557c149bd3c1e9b0 (diff) | |
download | FreeBSD-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.c | 47 |
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; |