summaryrefslogtreecommitdiffstats
path: root/sys
diff options
context:
space:
mode:
authorkib <kib@FreeBSD.org>2010-06-12 13:22:39 +0000
committerkib <kib@FreeBSD.org>2010-06-12 13:22:39 +0000
commitbbe91d0e0f42157f62abeae4e5e6ce4c66e1dace (patch)
tree076f63805dee8c2bf01d8b80db648b54edb8cc0e /sys
parent9e98593ebc5fa55b58e828b7f0b743e801532ca6 (diff)
downloadFreeBSD-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.c77
-rw-r--r--sys/sys/conf.h6
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);
OpenPOWER on IntegriCloud