diff options
author | phk <phk@FreeBSD.org> | 2000-08-24 15:36:55 +0000 |
---|---|---|
committer | phk <phk@FreeBSD.org> | 2000-08-24 15:36:55 +0000 |
commit | ec761116e25ef0a9e43ec5670c7c6565a4848a0b (patch) | |
tree | 526f85e393c165d9f02f974b9d8214c9b1605bc4 /sys/fs/devfs/devfs_devs.c | |
parent | f234fce050713400cc0e6419a59b0f6df01a2501 (diff) | |
download | FreeBSD-src-ec761116e25ef0a9e43ec5670c7c6565a4848a0b.zip FreeBSD-src-ec761116e25ef0a9e43ec5670c7c6565a4848a0b.tar.gz |
Fix panic when removing open device (found by bp@)
Implement subdirs.
Build the full "devicename" for cloning functions.
Fix panic when deleted device goes away.
Collaps devfs_dir and devfs_dirent structures.
Add proper cloning to the /dev/fd* "device-"driver.
Fix a bug in make_dev_alias() handling which made aliases appear
multiple times.
Use devfs_clone to implement getdiskbyname()
Make specfs maintain the stat(2) timestamps per dev_t
Diffstat (limited to 'sys/fs/devfs/devfs_devs.c')
-rw-r--r-- | sys/fs/devfs/devfs_devs.c | 79 |
1 files changed, 56 insertions, 23 deletions
diff --git a/sys/fs/devfs/devfs_devs.c b/sys/fs/devfs/devfs_devs.c index 10be9da..8b301c9 100644 --- a/sys/fs/devfs/devfs_devs.c +++ b/sys/fs/devfs/devfs_devs.c @@ -57,29 +57,46 @@ devfs_newdirent(char *name, int namelen) de->de_dirent->d_reclen = GENERIC_DIRSIZ(&d); bcopy(name, de->de_dirent->d_name, namelen + 1); nanotime(&de->de_ctime); + de->de_mtime = de->de_atime = de->de_ctime; + de->de_links = 1; return (de); } -struct devfs_dir * -devfs_vmkdir(void) +struct devfs_dirent * +devfs_vmkdir(char *name, int namelen, struct devfs_dirent *dotdot) { - struct devfs_dir *dd; + struct devfs_dirent *dd; struct devfs_dirent *de; - MALLOC(dd, struct devfs_dir *, sizeof(*dd), M_DEVFS, M_WAITOK); - bzero(dd, sizeof(*dd)); - TAILQ_INIT(&dd->dd_list); + dd = devfs_newdirent(name, namelen); + + TAILQ_INIT(&dd->de_dlist); + + dd->de_dirent->d_type = DT_DIR; + dd->de_mode = 0755; + dd->de_links = 2; + dd->de_dir = dd; de = devfs_newdirent(".", 1); de->de_dirent->d_type = DT_DIR; - TAILQ_INSERT_TAIL(&dd->dd_list, de, de_list); - de = TAILQ_FIRST(&dd->dd_list); - de->de_mode = 0755; + de->de_dir = dd; + de->de_flags |= DE_DOT; + TAILQ_INSERT_TAIL(&dd->de_dlist, de, de_list); + + de = devfs_newdirent("..", 2); + de->de_dirent->d_type = DT_DIR; + if (dotdot == NULL) + de->de_dir = dd; + else + de->de_dir = dotdot; + de->de_flags |= DE_DOTDOT; + TAILQ_INSERT_TAIL(&dd->de_dlist, de, de_list); + return (dd); } -void -devfs_delete(struct devfs_dir *dd, struct devfs_dirent *de) +static void +devfs_delete(struct devfs_dirent *dd, struct devfs_dirent *de) { if (de->de_symlink) { @@ -90,17 +107,17 @@ devfs_delete(struct devfs_dir *dd, struct devfs_dirent *de) de->de_vnode->v_data = NULL; vdrop(de->de_vnode); } - TAILQ_REMOVE(&dd->dd_list, de, de_list); + TAILQ_REMOVE(&dd->de_dlist, de, de_list); FREE(de, M_DEVFS); } void -devfs_purge(struct devfs_dir *dd) +devfs_purge(struct devfs_dirent *dd) { struct devfs_dirent *de; for (;;) { - de = TAILQ_FIRST(&dd->dd_list); + de = TAILQ_FIRST(&dd->de_dlist); if (de == NULL) break; devfs_delete(dd, de); @@ -114,7 +131,7 @@ devfs_populate(struct devfs_mount *dm) { int i, j; dev_t dev, pdev; - struct devfs_dir *dd; + struct devfs_dirent *dd; struct devfs_dirent *de; char *q, *s; @@ -123,13 +140,14 @@ devfs_populate(struct devfs_mount *dm) for (i = 0; i < NDEVINO; i++) { dev = devfs_inot[i]; de = dm->dm_dirent[i]; + if (dev == NULL && de == DE_DELETED) { + dm->dm_dirent[i] = NULL; + continue; + } if (dev == NULL && de != NULL) { -#if 0 - printf("Del ino%d %s\n", i, de->de_dirent->d_name); -#endif dd = de->de_dir; dm->dm_dirent[i] = NULL; - TAILQ_REMOVE(&dd->dd_list, de, de_list); + TAILQ_REMOVE(&dd->de_dlist, de, de_list); if (de->de_vnode) { de->de_vnode->v_data = NULL; vdrop(de->de_vnode); @@ -143,17 +161,32 @@ devfs_populate(struct devfs_mount *dm) continue; dd = dm->dm_basedir; s = dev->si_name; + nextdir: for (q = s; *q != '/' && *q != '\0'; q++) continue; if (*q == '/') { - continue; + TAILQ_FOREACH(de, &dd->de_dlist, de_list) { + if (de->de_dirent->d_namlen != q - s) + continue; + if (bcmp(de->de_dirent->d_name, s, q - s)) + continue; + goto fdir; + } + de = devfs_vmkdir(s, q - s, dd); + de->de_inode = dm->dm_inode++; + TAILQ_INSERT_TAIL(&dd->de_dlist, de, de_list); + dd->de_links++; + fdir: + s = q + 1; + dd = de; + goto nextdir; } de = devfs_newdirent(s, q - s); if (dev->si_flags & SI_ALIAS) { de->de_inode = dm->dm_inode++; de->de_uid = 0; de->de_gid = 0; - de->de_mode = 0642; + de->de_mode = 0666; de->de_dirent->d_type = DT_LNK; pdev = dev->si_drv1; j = strlen(pdev->si_name) + 1; @@ -165,9 +198,9 @@ devfs_populate(struct devfs_mount *dm) de->de_gid = dev->si_gid; de->de_mode = dev->si_mode; de->de_dirent->d_type = DT_CHR; - dm->dm_dirent[i] = de; } - TAILQ_INSERT_TAIL(&dd->dd_list, de, de_list); + dm->dm_dirent[i] = de; + TAILQ_INSERT_TAIL(&dd->de_dlist, de, de_list); #if 0 printf("Add ino%d %s\n", i, dev->si_name); #endif |