diff options
author | kib <kib@FreeBSD.org> | 2010-06-12 13:22:39 +0000 |
---|---|---|
committer | kib <kib@FreeBSD.org> | 2010-06-12 13:22:39 +0000 |
commit | bbe91d0e0f42157f62abeae4e5e6ce4c66e1dace (patch) | |
tree | 076f63805dee8c2bf01d8b80db648b54edb8cc0e /sys | |
parent | 9e98593ebc5fa55b58e828b7f0b743e801532ca6 (diff) | |
download | FreeBSD-src-bbe91d0e0f42157f62abeae4e5e6ce4c66e1dace.zip FreeBSD-src-bbe91d0e0f42157f62abeae4e5e6ce4c66e1dace.tar.gz |
Add another variation of make_dev(9), make_dev_p(9), that is allowed
to fail and can return useful error code.
Requested by: jh
Reviewed by: imp, jh
MFC after: 3 weeks
Diffstat (limited to 'sys')
-rw-r--r-- | sys/kern/kern_conf.c | 77 | ||||
-rw-r--r-- | sys/sys/conf.h | 6 |
2 files changed, 58 insertions, 25 deletions
diff --git a/sys/kern/kern_conf.c b/sys/kern/kern_conf.c index e499407..f22b232 100644 --- a/sys/kern/kern_conf.c +++ b/sys/kern/kern_conf.c @@ -55,9 +55,8 @@ struct mtx devmtx; static void destroy_devl(struct cdev *dev); static int destroy_dev_sched_cbl(struct cdev *dev, void (*cb)(void *), void *arg); -static struct cdev *make_dev_credv(int flags, - struct cdevsw *devsw, int unit, - struct ucred *cr, uid_t uid, gid_t gid, int mode, const char *fmt, +static int make_dev_credv(int flags, struct cdev **dres, struct cdevsw *devsw, + int unit, struct ucred *cr, uid_t uid, gid_t gid, int mode, const char *fmt, va_list ap); static struct cdev_priv_list cdevp_free_list = @@ -580,20 +579,20 @@ prep_cdevsw(struct cdevsw *devsw, int flags) mtx_assert(&devmtx, MA_OWNED); if (devsw->d_flags & D_INIT) - return (1); + return (0); if (devsw->d_flags & D_NEEDGIANT) { dev_unlock(); 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); + return (ENOMEM); } else dsw2 = NULL; if (devsw->d_flags & D_INIT) { if (dsw2 != NULL) cdevsw_free_devlocked(dsw2); - return (1); + return (0); } if (devsw->d_version != D_VERSION_03) { @@ -651,25 +650,28 @@ prep_cdevsw(struct cdevsw *devsw, int flags) if (dsw2 != NULL) cdevsw_free_devlocked(dsw2); - return (1); + return (0); } -static struct cdev * -make_dev_credv(int flags, struct cdevsw *devsw, int unit, - struct ucred *cr, uid_t uid, - gid_t gid, int mode, const char *fmt, va_list ap) +static int +make_dev_credv(int flags, struct cdev **dres, struct cdevsw *devsw, int unit, + struct ucred *cr, uid_t uid, gid_t gid, int mode, const char *fmt, + va_list ap) { struct cdev *dev; - int i; + int i, res; + KASSERT((flags & MAKEDEV_WAITOK) == 0 || (flags & MAKEDEV_NOWAIT) == 0, + ("make_dev_credv: both WAITOK and NOWAIT specified")); dev = devfs_alloc(flags); if (dev == NULL) - return (NULL); + return (ENOMEM); dev_lock(); - if (!prep_cdevsw(devsw, flags)) { + res = prep_cdevsw(devsw, flags); + if (res != 0) { dev_unlock(); devfs_free(dev); - return (NULL); + return (res); } dev = newdev(devsw, unit, dev); if (flags & MAKEDEV_REF) @@ -682,7 +684,8 @@ make_dev_credv(int flags, struct cdevsw *devsw, int unit, * XXX: still ?? */ dev_unlock_and_free(); - return (dev); + *dres = dev; + return (0); } KASSERT(!(dev->si_flags & SI_NAMED), ("make_dev() by driver %s on pre-existing device (min=%x, name=%s)", @@ -707,7 +710,8 @@ make_dev_credv(int flags, struct cdevsw *devsw, int unit, notify_create(dev, flags); - return (dev); + *dres = dev; + return (0); } struct cdev * @@ -716,10 +720,13 @@ make_dev(struct cdevsw *devsw, int unit, uid_t uid, gid_t gid, int mode, { struct cdev *dev; va_list ap; + int res; va_start(ap, fmt); - dev = make_dev_credv(0, devsw, unit, NULL, uid, gid, mode, fmt, ap); + res = make_dev_credv(0, &dev, devsw, unit, NULL, uid, gid, mode, fmt, + ap); va_end(ap); + KASSERT(res == 0 && dev != NULL, ("make_dev: failed make_dev_credv")); return (dev); } @@ -729,28 +736,50 @@ make_dev_cred(struct cdevsw *devsw, int unit, struct ucred *cr, uid_t uid, { struct cdev *dev; va_list ap; + int res; va_start(ap, fmt); - dev = make_dev_credv(0, devsw, unit, cr, uid, gid, mode, fmt, ap); + res = make_dev_credv(0, &dev, devsw, unit, cr, uid, gid, mode, fmt, ap); va_end(ap); + KASSERT(res == 0 && dev != NULL, + ("make_dev_cred: failed make_dev_credv")); return (dev); } struct cdev * -make_dev_credf(int flags, struct cdevsw *devsw, int unit, - struct ucred *cr, uid_t uid, - gid_t gid, int mode, const char *fmt, ...) +make_dev_credf(int flags, struct cdevsw *devsw, int unit, struct ucred *cr, + uid_t uid, gid_t gid, int mode, const char *fmt, ...) { struct cdev *dev; va_list ap; + int res; va_start(ap, fmt); - dev = make_dev_credv(flags, devsw, unit, cr, uid, gid, mode, + res = make_dev_credv(flags, &dev, devsw, unit, cr, uid, gid, mode, fmt, ap); va_end(ap); - return (dev); + KASSERT((flags & MAKEDEV_NOWAIT) != 0 || res == 0, + ("make_dev_credf: failed make_dev_credv")); + return (res == 0 ? dev : NULL); +} + +int +make_dev_p(int flags, struct cdev **cdev, struct cdevsw *devsw, int unit, + struct ucred *cr, uid_t uid, gid_t gid, int mode, const char *fmt, ...) +{ + va_list ap; + int res; + + va_start(ap, fmt); + res = make_dev_credv(flags, cdev, devsw, unit, cr, uid, gid, mode, + fmt, ap); + va_end(ap); + + KASSERT((flags & MAKEDEV_NOWAIT) != 0 || res == 0, + ("make_dev_credf: failed make_dev_credv")); + return (res); } static void diff --git a/sys/sys/conf.h b/sys/sys/conf.h index 937414d..1039aea 100644 --- a/sys/sys/conf.h +++ b/sys/sys/conf.h @@ -270,7 +270,11 @@ struct cdev *make_dev_credf(int _flags, struct cdevsw *_devsw, int _unit, struct ucred *_cr, uid_t _uid, gid_t _gid, int _mode, const char *_fmt, ...) __printflike(8, 9); -struct cdev *make_dev_alias(struct cdev *_pdev, const char *_fmt, ...) __printflike(2, 3); +int make_dev_p(int _flags, struct cdev **_cdev, struct cdevsw *_devsw, + int _unit, struct ucred *_cr, uid_t _uid, gid_t _gid, int _mode, + const char *_fmt, ...) __printflike(9, 10); +struct cdev *make_dev_alias(struct cdev *_pdev, const char *_fmt, ...) + __printflike(2, 3); void dev_lock(void); void dev_unlock(void); void setconf(void); |