Reduce a fair bit of the atomics because we are now called with a
lock from kern_conf.c and cdev's act a lot more like real objects these days.
This commit is contained in:
parent
e1ebf69098
commit
9d96090725
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2000
|
||||
* Copyright (c) 2000,2004
|
||||
* Poul-Henning Kamp. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
@ -58,7 +58,6 @@ static int devfs_noverflowwant = NDEVFSOVERFLOW;
|
||||
static int devfs_noverflow;
|
||||
static unsigned devfs_generation;
|
||||
|
||||
static void devfs_attemptoverflow(int insist);
|
||||
static struct devfs_dirent *devfs_find (struct devfs_dirent *dd, const char *name, int namelen);
|
||||
|
||||
SYSCTL_NODE(_vfs, OID_AUTO, devfs, CTLFLAG_RW, 0, "DEVFS filesystem");
|
||||
@ -137,43 +136,6 @@ devfs_itod (int inode)
|
||||
return (NULL);
|
||||
}
|
||||
|
||||
static void
|
||||
devfs_attemptoverflow(int insist)
|
||||
{
|
||||
struct cdev ***ot;
|
||||
int *or;
|
||||
int n, nb;
|
||||
|
||||
/* Check if somebody beat us to it */
|
||||
if (devfs_overflow != NULL)
|
||||
return;
|
||||
ot = NULL;
|
||||
or = NULL;
|
||||
n = devfs_noverflowwant;
|
||||
nb = sizeof (struct cdev **) * n;
|
||||
MALLOC(ot, struct cdev ***, nb, M_DEVFS, (insist ? M_WAITOK : M_NOWAIT) | M_ZERO);
|
||||
if (ot == NULL)
|
||||
goto bail;
|
||||
nb = sizeof (int) * n;
|
||||
MALLOC(or, int *, nb, M_DEVFS, (insist ? M_WAITOK : M_NOWAIT) | M_ZERO);
|
||||
if (or == NULL)
|
||||
goto bail;
|
||||
if (!atomic_cmpset_ptr(&devfs_overflow, NULL, ot))
|
||||
goto bail;
|
||||
devfs_refoverflow = or;
|
||||
devfs_noverflow = n;
|
||||
printf("DEVFS Overflow table with %d entries allocated when %d in use\n", n, devfs_numino);
|
||||
return;
|
||||
|
||||
bail:
|
||||
/* Somebody beat us to it, or something went wrong. */
|
||||
if (ot != NULL)
|
||||
FREE(ot, M_DEVFS);
|
||||
if (or != NULL)
|
||||
FREE(or, M_DEVFS);
|
||||
return;
|
||||
}
|
||||
|
||||
static struct devfs_dirent *
|
||||
devfs_find(struct devfs_dirent *dd, const char *name, int namelen)
|
||||
{
|
||||
@ -367,20 +329,26 @@ devfs_populate(struct devfs_mount *dm)
|
||||
de->de_dir = dd;
|
||||
devfs_rules_apply(dm, de);
|
||||
TAILQ_INSERT_TAIL(&dd->de_dlist, de, de_list);
|
||||
#if 0
|
||||
printf("Add ino%d %s\n", i, dev->si_name);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
lockmgr(&dm->dm_lock, LK_DOWNGRADE, 0, curthread);
|
||||
return (0);
|
||||
}
|
||||
|
||||
/*
|
||||
* devfs_create() and devfs_destroy() are called from kern_conf.c and
|
||||
* in both cases the devlock() mutex is held, so no further locking
|
||||
* is necesary and no sleeping allowed.
|
||||
*/
|
||||
|
||||
void
|
||||
devfs_create(struct cdev *dev)
|
||||
{
|
||||
int ino, i, *ip;
|
||||
struct cdev **dp;
|
||||
struct cdev **ot;
|
||||
int *or;
|
||||
int n;
|
||||
|
||||
for (;;) {
|
||||
/* Grab the next inode number */
|
||||
@ -389,56 +357,70 @@ devfs_create(struct cdev *dev)
|
||||
/* wrap around when we reach the end */
|
||||
if (i >= NDEVFSINO + devfs_noverflow)
|
||||
i = 3;
|
||||
if (!atomic_cmpset_int(&devfs_nextino, ino, i))
|
||||
continue;
|
||||
devfs_nextino = i;
|
||||
|
||||
/* see if it was occupied */
|
||||
dp = devfs_itod(ino);
|
||||
if (dp == NULL)
|
||||
Debugger("dp == NULL\n");
|
||||
KASSERT(dp != NULL, ("DEVFS: No devptr inode %d", ino));
|
||||
if (*dp != NULL)
|
||||
continue;
|
||||
ip = devfs_itor(ino);
|
||||
if (ip == NULL)
|
||||
Debugger("ip == NULL\n");
|
||||
KASSERT(ip != NULL, ("DEVFS: No iptr inode %d", ino));
|
||||
if (*ip != 0)
|
||||
continue;
|
||||
|
||||
if (!atomic_cmpset_ptr(dp, NULL, dev))
|
||||
continue;
|
||||
|
||||
dev->si_inode = ino;
|
||||
for (;;) {
|
||||
i = devfs_topino;
|
||||
if (i >= ino)
|
||||
break;
|
||||
if (atomic_cmpset_int(&devfs_topino, i, ino))
|
||||
break;
|
||||
printf("failed topino %d %d\n", i, ino);
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
atomic_add_int(&devfs_numino, 1);
|
||||
atomic_add_int(&devfs_generation, 1);
|
||||
if (devfs_overflow == NULL && devfs_numino + 100 > NDEVFSINO)
|
||||
devfs_attemptoverflow(0);
|
||||
*dp = dev;
|
||||
dev->si_inode = ino;
|
||||
if (i > devfs_topino)
|
||||
devfs_topino = i;
|
||||
|
||||
devfs_numino++;
|
||||
devfs_generation++;
|
||||
|
||||
if (devfs_overflow != NULL || devfs_numino + 100 < NDEVFSINO)
|
||||
return;
|
||||
|
||||
/*
|
||||
* Try to allocate overflow table
|
||||
* XXX: we can probably be less panicy these days and a linked
|
||||
* XXX: list of PAGESIZE/PTRSIZE entries might be a better idea.
|
||||
*
|
||||
* XXX: we may be into witness unlove here.
|
||||
*/
|
||||
n = devfs_noverflowwant;
|
||||
ot = malloc(sizeof(*ot) * n, M_DEVFS, M_NOWAIT | M_ZERO);
|
||||
if (ot == NULL)
|
||||
return;
|
||||
or = malloc(sizeof(*or) * n, M_DEVFS, M_NOWAIT | M_ZERO);
|
||||
if (or == NULL) {
|
||||
free(ot, M_DEVFS);
|
||||
return;
|
||||
}
|
||||
devfs_overflow = ot;
|
||||
devfs_refoverflow = or;
|
||||
devfs_noverflow = n;
|
||||
printf("DEVFS Overflow table with %d entries allocated\n", n);
|
||||
return;
|
||||
}
|
||||
|
||||
void
|
||||
devfs_destroy(struct cdev *dev)
|
||||
{
|
||||
int ino, i;
|
||||
int ino;
|
||||
struct cdev **dp;
|
||||
|
||||
ino = dev->si_inode;
|
||||
dev->si_inode = 0;
|
||||
if (ino == 0)
|
||||
return;
|
||||
if (atomic_cmpset_ptr(devfs_itod(ino), dev, NULL)) {
|
||||
atomic_add_int(&devfs_generation, 1);
|
||||
atomic_add_int(&devfs_numino, -1);
|
||||
i = devfs_nextino;
|
||||
if (ino < i)
|
||||
atomic_cmpset_int(&devfs_nextino, i, ino);
|
||||
}
|
||||
dp = devfs_itod(ino);
|
||||
KASSERT(*dp == dev,
|
||||
("DEVFS: destroying wrong cdev ino %d", ino));
|
||||
*dp = NULL;
|
||||
devfs_numino--;
|
||||
devfs_generation++;
|
||||
if (ino < devfs_nextino)
|
||||
devfs_nextino = ino;
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user