aboutsummaryrefslogtreecommitdiff
path: root/sys
diff options
context:
space:
mode:
authorPoul-Henning Kamp <phk@FreeBSD.org>2004-06-18 08:08:47 +0000
committerPoul-Henning Kamp <phk@FreeBSD.org>2004-06-18 08:08:47 +0000
commit9d960907254f91237895418b53498a64a0c73308 (patch)
tree2cfb21ec3892ee896b688c791e4a5cf769649d3d /sys
parente1ebf690986588860b1489d01acf07ec259d203b (diff)
downloadsrc-9d960907254f91237895418b53498a64a0c73308.tar.gz
src-9d960907254f91237895418b53498a64a0c73308.zip
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.
Notes
Notes: svn path=/head/; revision=130678
Diffstat (limited to 'sys')
-rw-r--r--sys/fs/devfs/devfs_devs.c128
1 files changed, 55 insertions, 73 deletions
diff --git a/sys/fs/devfs/devfs_devs.c b/sys/fs/devfs/devfs_devs.c
index 732a23d8d711..6edb02bdb865 100644
--- a/sys/fs/devfs/devfs_devs.c
+++ b/sys/fs/devfs/devfs_devs.c
@@ -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;
}