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
This commit is contained in:
parent
eb00b276ab
commit
d2ba618a63
Notes:
svn2git
2020-12-20 02:59:44 +00:00
svn path=/head/; revision=207729
@ -115,17 +115,21 @@ SYSCTL_INT(_debug_sizeof, OID_AUTO, cdev_priv, CTLFLAG_RD,
|
||||
0, sizeof(struct cdev_priv), "sizeof(struct cdev_priv)");
|
||||
|
||||
struct cdev *
|
||||
devfs_alloc(void)
|
||||
devfs_alloc(int flags)
|
||||
{
|
||||
struct cdev_priv *cdp;
|
||||
struct cdev *cdev;
|
||||
struct timespec ts;
|
||||
|
||||
cdp = malloc(sizeof *cdp, M_CDEVP, M_USE_RESERVE | M_ZERO | M_WAITOK);
|
||||
cdp = malloc(sizeof *cdp, M_CDEVP, M_USE_RESERVE | M_ZERO |
|
||||
((flags & MAKEDEV_NOWAIT) ? M_NOWAIT : M_WAITOK));
|
||||
if (cdp == NULL)
|
||||
return (NULL);
|
||||
|
||||
cdp->cdp_dirents = &cdp->cdp_dirent0;
|
||||
cdp->cdp_dirent0 = NULL;
|
||||
cdp->cdp_maxdirent = 0;
|
||||
cdp->cdp_inode = 0;
|
||||
|
||||
cdev = &cdp->cdp_c;
|
||||
|
||||
@ -133,6 +137,7 @@ devfs_alloc(void)
|
||||
LIST_INIT(&cdev->si_children);
|
||||
vfs_timestamp(&ts);
|
||||
cdev->si_atime = cdev->si_mtime = cdev->si_ctime = ts;
|
||||
cdev->si_cred = NULL;
|
||||
|
||||
return (cdev);
|
||||
}
|
||||
|
@ -70,7 +70,7 @@ struct cdev_priv {
|
||||
|
||||
#define cdev2priv(c) member2struct(cdev_priv, cdp_c, c)
|
||||
|
||||
struct cdev *devfs_alloc(void);
|
||||
struct cdev *devfs_alloc(int);
|
||||
void devfs_free(struct cdev *);
|
||||
void devfs_create(struct cdev *dev);
|
||||
void devfs_destroy(struct cdev *dev);
|
||||
|
@ -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;
|
||||
|
@ -262,8 +262,10 @@ struct cdev *make_dev(struct cdevsw *_devsw, int _unit, uid_t _uid, gid_t _gid,
|
||||
struct cdev *make_dev_cred(struct cdevsw *_devsw, int _unit,
|
||||
struct ucred *_cr, uid_t _uid, gid_t _gid, int _perms,
|
||||
const char *_fmt, ...) __printflike(7, 8);
|
||||
#define MAKEDEV_REF 0x1
|
||||
#define MAKEDEV_WHTOUT 0x2
|
||||
#define MAKEDEV_REF 0x1
|
||||
#define MAKEDEV_WHTOUT 0x2
|
||||
#define MAKEDEV_NOWAIT 0x4
|
||||
#define MAKEDEV_WAITOK 0x8
|
||||
struct cdev *make_dev_credf(int _flags,
|
||||
struct cdevsw *_devsw, int _unit,
|
||||
struct ucred *_cr, uid_t _uid, gid_t _gid, int _mode,
|
||||
|
Loading…
Reference in New Issue
Block a user