Index: sys/kern/kern_conf.c =================================================================== --- sys/kern/kern_conf.c +++ sys/kern/kern_conf.c @@ -56,9 +56,6 @@ static int destroy_dev_sched_cbl(struct cdev *dev, void (*cb)(void *), void *arg); static void destroy_dev_tq(void *ctx, int pending); -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 = TAILQ_HEAD_INITIALIZER(cdevp_free_list); @@ -566,7 +563,8 @@ } static struct cdev * -newdev(struct cdevsw *csw, int unit, struct cdev *si) +newdev(struct cdevsw *csw, int unit, struct cdev *si, + void *drv1, void *drv2) { struct cdev *si2; @@ -581,6 +579,8 @@ } } si->si_drv0 = unit; + si->si_drv1 = drv1; + si->si_drv2 = drv2; si->si_devsw = csw; LIST_INSERT_HEAD(&csw->d_devs, si, si_list); return (si); @@ -738,32 +738,41 @@ } 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) +make_dev_argv(struct cdev **ppdev, const struct make_dev_args *pargs, + const char *fmt, va_list ap) { - struct cdev *dev, *dev_new; + struct cdev *dev_new; + struct cdev *dev; int res; - KASSERT((flags & MAKEDEV_WAITOK) == 0 || (flags & MAKEDEV_NOWAIT) == 0, - ("make_dev_credv: both WAITOK and NOWAIT specified")); - dev_new = devfs_alloc(flags); + KASSERT(pargs != NULL, ("make_dev_argv: pargs is NULL")); + KASSERT((pargs->flags & MAKEDEV_WAITOK) == 0 || + (pargs->flags & MAKEDEV_NOWAIT) == 0, + ("make_dev_argv: both WAITOK and NOWAIT specified")); + KASSERT(pargs->si_devsw != NULL, + ("make_dev_argv: pargs->si_devsw is NULL")); + KASSERT(pargs->version == MAKE_DEV_ARGS_VERSION, + ("make_dev_argv: Invalid version %d != %d", + pargs->version, MAKE_DEV_ARGS_VERSION)); + + dev_new = devfs_alloc(pargs->flags); if (dev_new == NULL) return (ENOMEM); dev_lock(); - res = prep_cdevsw(devsw, flags); + res = prep_cdevsw(pargs->si_devsw, pargs->flags); if (res != 0) { dev_unlock(); devfs_free(dev_new); return (res); } - dev = newdev(devsw, unit, dev_new); + dev = newdev(pargs->si_devsw, pargs->si_drv0, dev_new, + pargs->si_drv1, pargs->si_drv2); if ((dev->si_flags & SI_NAMED) == 0) { res = prep_devname(dev, fmt, ap); if (res != 0) { - if ((flags & MAKEDEV_CHECKNAME) == 0) { + if ((pargs->flags & MAKEDEV_CHECKNAME) == 0) { panic( - "make_dev_credv: bad si_name (error=%d, si_name=%s)", + "make_dev_argv: bad si_name (error=%d, si_name=%s)", res, dev->si_name); } if (dev == dev_new) { @@ -775,9 +784,9 @@ return (res); } } - if (flags & MAKEDEV_REF) + if (pargs->flags & MAKEDEV_REF) dev_refl(dev); - if (flags & MAKEDEV_ETERNAL) + if (pargs->flags & MAKEDEV_ETERNAL) dev->si_flags |= SI_ETERNAL; if (dev->si_flags & SI_CHEAPCLONE && dev->si_flags & SI_NAMED) { @@ -787,26 +796,26 @@ * XXX: still ?? */ dev_unlock_and_free(); - *dres = dev; + *ppdev = dev; return (0); } KASSERT(!(dev->si_flags & SI_NAMED), ("make_dev() by driver %s on pre-existing device (min=%x, name=%s)", - devsw->d_name, dev2unit(dev), devtoname(dev))); + pargs->si_devsw->d_name, dev2unit(dev), devtoname(dev))); dev->si_flags |= SI_NAMED; - if (cr != NULL) - dev->si_cred = crhold(cr); - dev->si_uid = uid; - dev->si_gid = gid; - dev->si_mode = mode; + if (pargs->si_cred != NULL) + dev->si_cred = crhold(pargs->si_cred); + dev->si_uid = pargs->si_uid; + dev->si_gid = pargs->si_gid; + dev->si_mode = pargs->si_mode; devfs_create(dev); clean_unrhdrl(devfs_inos); dev_unlock_and_free(); - notify_create(dev, flags); + notify_create(dev, pargs->flags); - *dres = dev; + *ppdev = dev; return (0); } @@ -814,33 +823,66 @@ make_dev(struct cdevsw *devsw, int unit, uid_t uid, gid_t gid, int mode, const char *fmt, ...) { + struct make_dev_args args = { + .version = MAKE_DEV_ARGS_VERSION, + .si_drv0 = unit, + .si_uid = uid, + .si_gid = gid, + .si_mode = mode, + .si_devsw = devsw, + }; struct cdev *dev; va_list ap; int res; va_start(ap, fmt); - res = make_dev_credv(0, &dev, devsw, unit, NULL, uid, gid, mode, fmt, - ap); + res = make_dev_argv(&dev, &args, fmt, ap); va_end(ap); KASSERT(res == 0 && dev != NULL, - ("make_dev: failed make_dev_credv (error=%d)", res)); + ("make_dev: failed make_dev_argv (error=%d)", res)); return (dev); } +int +make_dev_args(struct cdev **ppdev, const struct make_dev_args *pargs, + const char *fmt, ...) +{ + va_list ap; + int res; + + va_start(ap, fmt); + res = make_dev_argv(ppdev, pargs, fmt, ap); + va_end(ap); + + KASSERT(((pargs->flags & MAKEDEV_NOWAIT) != 0 && res == ENOMEM) || + ((pargs->flags & MAKEDEV_CHECKNAME) != 0 && res != ENOMEM) || res == 0, + ("make_dev_args: failed make_dev_argv (error=%d)", res)); + return (res); +} + struct cdev * make_dev_cred(struct cdevsw *devsw, int unit, struct ucred *cr, uid_t uid, gid_t gid, int mode, const char *fmt, ...) { + struct make_dev_args args = { + .version = MAKE_DEV_ARGS_VERSION, + .si_cred = cr, + .si_drv0 = unit, + .si_uid = uid, + .si_gid = gid, + .si_mode = mode, + .si_devsw = devsw, + }; struct cdev *dev; va_list ap; int res; va_start(ap, fmt); - res = make_dev_credv(0, &dev, devsw, unit, cr, uid, gid, mode, fmt, ap); + res = make_dev_argv(&dev, &args, fmt, ap); va_end(ap); KASSERT(res == 0 && dev != NULL, - ("make_dev_cred: failed make_dev_credv (error=%d)", res)); + ("make_dev_cred: failed make_dev_argv (error=%d)", res)); return (dev); } @@ -848,18 +890,27 @@ 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 make_dev_args args = { + .version = MAKE_DEV_ARGS_VERSION, + .flags = flags, + .si_cred = cr, + .si_drv0 = unit, + .si_uid = uid, + .si_gid = gid, + .si_mode = mode, + .si_devsw = devsw, + }; struct cdev *dev; va_list ap; int res; va_start(ap, fmt); - res = make_dev_credv(flags, &dev, devsw, unit, cr, uid, gid, mode, - fmt, ap); + res = make_dev_argv(&dev, &args, fmt, ap); va_end(ap); KASSERT(((flags & MAKEDEV_NOWAIT) != 0 && res == ENOMEM) || ((flags & MAKEDEV_CHECKNAME) != 0 && res != ENOMEM) || res == 0, - ("make_dev_credf: failed make_dev_credv (error=%d)", res)); + ("make_dev_credf: failed make_dev_argv (error=%d)", res)); return (res == 0 ? dev : NULL); } @@ -867,17 +918,25 @@ make_dev_p(int flags, struct cdev **cdev, struct cdevsw *devsw, struct ucred *cr, uid_t uid, gid_t gid, int mode, const char *fmt, ...) { + struct make_dev_args args = { + .version = MAKE_DEV_ARGS_VERSION, + .flags = flags, + .si_cred = cr, + .si_uid = uid, + .si_gid = gid, + .si_mode = mode, + .si_devsw = devsw, + }; va_list ap; int res; va_start(ap, fmt); - res = make_dev_credv(flags, cdev, devsw, 0, cr, uid, gid, mode, - fmt, ap); + res = make_dev_argv(cdev, &args, fmt, ap); va_end(ap); KASSERT(((flags & MAKEDEV_NOWAIT) != 0 && res == ENOMEM) || ((flags & MAKEDEV_CHECKNAME) != 0 && res != ENOMEM) || res == 0, - ("make_dev_p: failed make_dev_credv (error=%d)", res)); + ("make_dev_p: failed make_dev_argv (error=%d)", res)); return (res); } @@ -1298,7 +1357,7 @@ } if (unit == -1) unit = low & CLONE_UNITMASK; - dev = newdev(csw, unit | extra, ndev); + dev = newdev(csw, unit | extra, ndev, NULL, NULL); if (dev->si_flags & SI_CLONELIST) { printf("dev %p (%s) is on clonelist\n", dev, dev->si_name); printf("unit=%d, low=%d, extra=0x%x\n", unit, low, extra); Index: sys/sys/conf.h =================================================================== --- sys/sys/conf.h +++ sys/sys/conf.h @@ -51,6 +51,21 @@ struct cdevsw; struct file; +#define MAKE_DEV_ARGS_VERSION 20151002 + +struct make_dev_args { + int version; + int flags; + int si_drv0; + uid_t si_uid; + gid_t si_gid; + mode_t si_mode; + struct cdevsw *si_devsw; + struct ucred *si_cred; + void *si_drv1; + void *si_drv2; +}; + struct cdev { void *si_spare0; u_int si_flags; @@ -240,6 +255,14 @@ void dev_ref(struct cdev *dev); void dev_refl(struct cdev *dev); void dev_rel(struct cdev *dev); +/* convenience wrappers for make_dev_args() */ +#define MAKE_DEV_ARGS_SUB(...) \ + .version = MAKE_DEV_ARGS_VERSION, __VA_ARGS__ +#define MAKE_DEV_ARGS(ppdev,args,...) \ + make_dev_args(ppdev, &(struct make_dev_args){ \ + MAKE_DEV_ARGS_SUB args}, __VA_ARGS__) +int make_dev_args(struct cdev **_ppdev, const struct make_dev_args *_pargs, + const char *_fmt, ...) __printflike(3, 4); struct cdev *make_dev(struct cdevsw *_devsw, int _unit, uid_t _uid, gid_t _gid, int _perms, const char *_fmt, ...) __printflike(6, 7); struct cdev *make_dev_cred(struct cdevsw *_devsw, int _unit,