summaryrefslogtreecommitdiffstats
path: root/sys
diff options
context:
space:
mode:
authorphk <phk@FreeBSD.org>2000-08-24 15:36:55 +0000
committerphk <phk@FreeBSD.org>2000-08-24 15:36:55 +0000
commitec761116e25ef0a9e43ec5670c7c6565a4848a0b (patch)
tree526f85e393c165d9f02f974b9d8214c9b1605bc4 /sys
parentf234fce050713400cc0e6419a59b0f6df01a2501 (diff)
downloadFreeBSD-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')
-rw-r--r--sys/fs/devfs/devfs.h25
-rw-r--r--sys/fs/devfs/devfs_devs.c79
-rw-r--r--sys/fs/devfs/devfs_vfsops.c25
-rw-r--r--sys/fs/devfs/devfs_vnops.c192
-rw-r--r--sys/fs/specfs/spec_vnops.c14
-rw-r--r--sys/kern/kern_descrip.c44
-rw-r--r--sys/kern/vfs_conf.c20
-rw-r--r--sys/kern/vfs_mount.c20
-rw-r--r--sys/miscfs/specfs/spec_vnops.c14
-rw-r--r--sys/sys/conf.h3
-rw-r--r--sys/sys/linedisc.h3
11 files changed, 299 insertions, 140 deletions
diff --git a/sys/fs/devfs/devfs.h b/sys/fs/devfs/devfs.h
index 00a34b1..e144a4b 100644
--- a/sys/fs/devfs/devfs.h
+++ b/sys/fs/devfs/devfs.h
@@ -42,15 +42,17 @@
MALLOC_DECLARE(M_DEVFS);
-struct devfs_dir {
- TAILQ_HEAD(, devfs_dirent) dd_list;
-};
-
struct devfs_dirent {
int de_inode;
+ int de_flags;
+#define DE_ORPHAN 0x1
+#define DE_DOT 0x2
+#define DE_DOTDOT 0x4
struct dirent *de_dirent;
TAILQ_ENTRY(devfs_dirent) de_list;
- struct devfs_dir *de_dir;
+ TAILQ_HEAD(, devfs_dirent) de_dlist;
+ struct devfs_dirent *de_dir;
+ int de_links;
mode_t de_mode;
uid_t de_uid;
gid_t de_gid;
@@ -67,10 +69,11 @@ struct devfs_node {
struct devfs_mount {
struct vnode *dm_root; /* Root node */
- struct devfs_dir *dm_rootdir;
- struct devfs_dir *dm_basedir;
+ struct devfs_dirent *dm_rootdir;
+ struct devfs_dirent *dm_basedir;
unsigned dm_generation;
struct devfs_dirent *dm_dirent[NDEVINO];
+#define DE_DELETED ((struct devfs_dirent *)&devfs_inot[0])
int dm_inode;
};
@@ -79,15 +82,17 @@ extern dev_t devfs_inot[NDEVINO];
extern int devfs_nino;
extern unsigned devfs_generation;
+
#define VFSTODEVFS(mp) ((struct devfs_mount *)((mp)->mnt_data))
extern vop_t **devfs_vnodeop_p;
extern vop_t **devfs_specop_p;
+
int devfs_populate __P((struct devfs_mount *dm));
-struct devfs_dir * devfs_vmkdir __P((void));
struct devfs_dirent * devfs_newdirent __P((char *name, int namelen));
-void devfs_purge __P((struct devfs_dir *dd));
-void devfs_delete __P((struct devfs_dir *dd, struct devfs_dirent *de));
+void devfs_purge __P((struct devfs_dirent *dd));
+struct devfs_dirent * devfs_vmkdir __P((char *name, int namelen,
+ struct devfs_dirent *dotdot));
#endif /* DEVFS_INTERN */
typedef void (*devfs_clone_fn) __P((void *arg, char *name, int namelen, dev_t *result));
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
diff --git a/sys/fs/devfs/devfs_vfsops.c b/sys/fs/devfs/devfs_vfsops.c
index 27b1fd7..b5ccac4 100644
--- a/sys/fs/devfs/devfs_vfsops.c
+++ b/sys/fs/devfs/devfs_vfsops.c
@@ -97,29 +97,12 @@ devfs_mount(mp, path, data, ndp, p)
fmp->dm_inode = NDEVINO;
fmp->dm_root = rvp;
- fmp->dm_rootdir = devfs_vmkdir();
+
+ fmp->dm_rootdir = devfs_vmkdir("(root)", 6, NULL);
+ fmp->dm_rootdir->de_inode = 2;
rvp->v_data = fmp->dm_rootdir;
- TAILQ_FIRST(&fmp->dm_rootdir->dd_list)->de_vnode = rvp;
- TAILQ_FIRST(&fmp->dm_rootdir->dd_list)->de_inode = 2;
-
-#ifdef DEVFS_DEVBASE
- {
- struct devfs_dirent *de;
-
- fmp->dm_basedir = devfs_vmkdir();
- de = devfs_newdirent("dev", 3);
- de->de_inode = fmp->dm_inode++;
- de->de_dir = fmp->dm_basedir;
- TAILQ_FIRST(&de->de_dir->dd_list)->de_inode = de->de_inode;
- de->de_uid = 0;
- de->de_gid = 0;
- de->de_mode = 0755;
- de->de_dirent->d_type = DT_DIR;
- TAILQ_INSERT_TAIL(&fmp->dm_rootdir->dd_list, de, de_list);
- }
-#else
+
fmp->dm_basedir = fmp->dm_rootdir;
-#endif
if (path != NULL) {
(void) copyinstr(path, mp->mnt_stat.f_mntonname, MNAMELEN - 1, &size);
diff --git a/sys/fs/devfs/devfs_vnops.c b/sys/fs/devfs/devfs_vnops.c
index 496eba5..432f83a 100644
--- a/sys/fs/devfs/devfs_vnops.c
+++ b/sys/fs/devfs/devfs_vnops.c
@@ -93,18 +93,14 @@ loop:
vp->v_type = VCHR;
vp = addaliasu(vp, devfs_inot[de->de_inode]->si_udev);
vp->v_op = devfs_specop_p;
- vp->v_data = de;
} else if (de->de_dirent->d_type == DT_DIR) {
vp->v_type = VDIR;
- vp->v_data = de->de_dir;
- TAILQ_FIRST(&de->de_dir->dd_list)->de_vnode = vp;
} else if (de->de_dirent->d_type == DT_LNK) {
vp->v_type = VLNK;
- vp->v_data = de;
} else {
vp->v_type = VBAD;
- vp->v_data = de;
}
+ vp->v_data = de;
de->de_vnode = vp;
vhold(vp);
*vpp = vp;
@@ -127,14 +123,21 @@ devfs_lookup(ap)
struct vnode *dvp = ap->a_dvp;
char *pname = cnp->cn_nameptr;
struct proc *p = cnp->cn_proc;
- struct devfs_dir *dd;
+ struct devfs_dirent *dd;
struct devfs_dirent *de;
- struct devfs_mount *fmp;
+ struct devfs_mount *dmp;
dev_t cdev;
- int error, cloned;
+ int error, cloned, i;
+ char specname[SPECNAMELEN + 1];
*vpp = NULLVP;
+#if 0
+ error = VOP_ACCESS(dvp, VEXEC, cred, cnp->cn_proc);
+ if (error)
+ return (error);
+#endif
+
VOP_UNLOCK(dvp, 0, p);
if (cnp->cn_namelen == 1 && *pname == '.') {
*vpp = dvp;
@@ -145,12 +148,12 @@ devfs_lookup(ap)
cloned = 0;
- fmp = (struct devfs_mount *)dvp->v_mount->mnt_data;
+ dmp = VFSTODEVFS(dvp->v_mount);
again:
- devfs_populate(fmp);
+ devfs_populate(dmp);
dd = dvp->v_data;
- TAILQ_FOREACH(de, &dd->dd_list, de_list) {
+ TAILQ_FOREACH(de, &dd->de_dlist, de_list) {
if (cnp->cn_namelen != de->de_dirent->d_namlen)
continue;
if (bcmp(cnp->cn_nameptr, de->de_dirent->d_name, de->de_dirent->d_namlen) != 0)
@@ -159,11 +162,43 @@ again:
}
if (!cloned) {
- /* OK, we didn't have that one, so lets try to create it on the fly... */
+ /*
+ * OK, we didn't have an entry for the name we were asked for
+ * so we try to see if anybody can create it on demand.
+ * We need to construct the full "devname" for this device
+ * relative to "basedir" or the clone functions would not
+ * be able to tell "/dev/foo" from "/dev/bar/foo"
+ */
+ i = SPECNAMELEN;
+ specname[i] = '\0';
+ i -= cnp->cn_namelen;
+ if (i < 0)
+ goto noclone;
+ bcopy(cnp->cn_nameptr, specname + i, cnp->cn_namelen);
+ de = dd;
+ while (de != dmp->dm_basedir) {
+ i--;
+ if (i < 0)
+ goto noclone;
+ specname[i] = '/';
+ i -= de->de_dirent->d_namlen;
+ if (i < 0)
+ goto noclone;
+ bcopy(de->de_dirent->d_name, specname + i,
+ de->de_dirent->d_namlen);
+ de = TAILQ_FIRST(&de->de_dlist); /* "." */
+ de = TAILQ_NEXT(de, de_list); /* ".." */
+ de = de->de_dir;
+ }
+
+#if 0
+ printf("Finished specname: %d \"%s\"\n", i, specname + i);
+#endif
cdev = NODEV;
- EVENTHANDLER_INVOKE(devfs_clone, cnp->cn_nameptr, cnp->cn_namelen, &cdev);
+ EVENTHANDLER_INVOKE(devfs_clone, specname + i,
+ strlen(specname + i), &cdev);
#if 0
- printf("cloned %s -> %p %s\n", cnp->cn_nameptr, cdev,
+ printf("cloned %s -> %p %s\n", specname + i, cdev,
cdev == NODEV ? "NODEV" : cdev->si_name);
#endif
if (cdev != NODEV) {
@@ -172,6 +207,7 @@ again:
}
}
+noclone:
/* No luck, too bad. */
if ((cnp->cn_nameiop == CREATE || cnp->cn_nameiop == RENAME) &&
@@ -221,14 +257,10 @@ devfs_access(ap)
{
struct vnode *vp = ap->a_vp;
struct devfs_dirent *de;
- struct devfs_dir *dd;
- if (vp->v_type == VDIR) {
- dd = vp->v_data;
- de = TAILQ_FIRST(&dd->dd_list);
- } else {
- de = vp->v_data;
- }
+ de = vp->v_data;
+ if (vp->v_type == VDIR)
+ de = de->de_dir;
return (vaccess(vp->v_type, de->de_mode, de->de_uid, de->de_gid,
ap->a_mode, ap->a_cred));
@@ -247,14 +279,11 @@ devfs_getattr(ap)
struct vattr *vap = ap->a_vap;
int error = 0;
struct devfs_dirent *de;
- struct devfs_dir *dd;
+ dev_t dev;
- if (vp->v_type == VDIR) {
- dd = vp->v_data;
- de = TAILQ_FIRST(&dd->dd_list);
- } else {
- de = vp->v_data;
- }
+ de = vp->v_data;
+ if (vp->v_type == VDIR)
+ de = de->de_dir;
bzero((caddr_t) vap, sizeof(*vap));
vattr_null(vap);
vap->va_uid = de->de_uid;
@@ -262,28 +291,23 @@ devfs_getattr(ap)
vap->va_mode = de->de_mode;
vap->va_size = 0;
vap->va_blocksize = DEV_BSIZE;
- vap->va_atime = de->de_atime;
- vap->va_mtime = de->de_mtime;
- vap->va_ctime = de->de_ctime;
+ if (vp->v_type != VCHR) {
+ vap->va_atime = de->de_atime;
+ vap->va_mtime = de->de_mtime;
+ vap->va_ctime = de->de_ctime;
+ } else {
+ dev = vp->v_rdev;
+ vap->va_atime = dev->si_atime;
+ vap->va_mtime = dev->si_mtime;
+ vap->va_ctime = dev->si_ctime;
+ }
vap->va_gen = 0;
vap->va_flags = 0;
vap->va_rdev = 0;
vap->va_bytes = 0;
- vap->va_nlink = 1;
+ vap->va_nlink = de->de_links;
vap->va_fileid = de->de_inode;
-#if 0
- if (vp->v_flag & VROOT) {
-#ifdef DEBUG
- printf("devfs_getattr: stat rootdir\n");
-#endif
- vap->va_type = VDIR;
- vap->va_nlink = 2;
- vap->va_fileid = 2;
- vap->va_size = DEV_BSIZE;
- } else
-#endif
-
if (de->de_dirent->d_type == DT_DIR) {
vap->va_type = VDIR;
} else if (de->de_dirent->d_type == DT_LNK) {
@@ -309,35 +333,35 @@ devfs_setattr(ap)
struct proc *a_p;
} */ *ap;
{
- struct devfs_dir *dd;
struct devfs_dirent *de;
+ int c;
- if (ap->a_vp->v_type == VDIR) {
- dd = ap->a_vp->v_data;
- de = TAILQ_FIRST(&dd->dd_list);
- } else {
- de = ap->a_vp->v_data;
- }
+ de = ap->a_vp->v_data;
+ if (ap->a_vp->v_type == VDIR)
+ de = de->de_dir;
+ c = 0;
if (ap->a_vap->va_flags != VNOVAL)
return (EOPNOTSUPP);
- if (ap->a_vap->va_uid != (uid_t)VNOVAL)
+ if (ap->a_vap->va_uid != (uid_t)VNOVAL) {
de->de_uid = ap->a_vap->va_uid;
- if (ap->a_vap->va_gid != (gid_t)VNOVAL)
+ c = 1;
+ }
+ if (ap->a_vap->va_gid != (gid_t)VNOVAL) {
de->de_gid = ap->a_vap->va_gid;
- if (ap->a_vap->va_mode != (mode_t)VNOVAL)
+ c = 1;
+ }
+ if (ap->a_vap->va_mode != (mode_t)VNOVAL) {
de->de_mode = ap->a_vap->va_mode;
+ c = 1;
+ }
if (ap->a_vap->va_atime.tv_sec != VNOVAL)
de->de_atime = ap->a_vap->va_atime;
if (ap->a_vap->va_mtime.tv_sec != VNOVAL)
de->de_mtime = ap->a_vap->va_mtime;
- /*
- * Silently ignore attribute changes.
- * This allows for open with truncate to have no
- * effect until some data is written. I want to
- * do it this way because all writes are atomic.
- */
+ if (c)
+ getnanotime(&de->de_ctime);
return (0);
}
@@ -355,26 +379,33 @@ devfs_readdir(ap)
int error, i;
struct uio *uio = ap->a_uio;
struct dirent *dp;
- struct devfs_dir *dd;
+ struct devfs_dirent *dd;
struct devfs_dirent *de;
+ struct devfs_mount *dmp;
off_t off;
if (ap->a_vp->v_type != VDIR)
return (ENOTDIR);
+ dmp = VFSTODEVFS(ap->a_vp->v_mount);
+ devfs_populate(dmp);
i = (u_int)off / UIO_MX;
error = 0;
- dd = ap->a_vp->v_data;
- de = TAILQ_FIRST(&dd->dd_list);
+ de = ap->a_vp->v_data;
+ dd = TAILQ_FIRST(&de->de_dlist);
off = 0;
- while (uio->uio_resid >= UIO_MX && de != NULL) {
- dp = de->de_dirent;
+ while (uio->uio_resid >= UIO_MX && dd != NULL) {
+ if (dd->de_dirent->d_type == DT_DIR)
+ de = dd->de_dir;
+ else
+ de = dd;
+ dp = dd->de_dirent;
dp->d_fileno = de->de_inode;
if (off >= uio->uio_offset)
if ((error = uiomove((caddr_t)dp, dp->d_reclen, uio)) != 0)
break;
off += dp->d_reclen;
- de = TAILQ_NEXT(de, de_list);
+ dd = TAILQ_NEXT(dd, de_list);
}
uio->uio_offset = off;
@@ -405,7 +436,14 @@ devfs_reclaim(ap)
} */ *ap;
{
struct vnode *vp = ap->a_vp;
+ struct devfs_dirent *de;
+ de = vp->v_data;
+ if (de != NULL && de->de_flags & DE_ORPHAN) {
+ if (de->de_symlink)
+ FREE(de->de_symlink, M_DEVFS);
+ FREE(de, M_DEVFS);
+ }
vp->v_data = NULL;
return (0);
}
@@ -419,12 +457,17 @@ devfs_remove(ap)
} */ *ap;
{
struct vnode *vp = ap->a_vp;
- struct devfs_dir *dd;
+ struct devfs_dirent *dd;
struct devfs_dirent *de;
+ struct devfs_mount *dm = VFSTODEVFS(vp->v_mount);
dd = ap->a_dvp->v_data;
de = vp->v_data;
- devfs_delete(dd, de);
+ de->de_flags |= DE_ORPHAN;
+ TAILQ_REMOVE(&dd->de_dlist, de, de_list);
+ if (de->de_inode < NDEVINO)
+ dm->dm_dirent[de->de_inode] = DE_DELETED;
+ vdrop(de->de_vnode);
return (0);
}
@@ -444,7 +487,8 @@ devfs_revoke(ap)
struct devfs_dirent *de;
de = vp->v_data;
- vdrop(de->de_vnode);
+ if (!(de->de_flags & DE_ORPHAN))
+ vdrop(de->de_vnode);
de->de_vnode = NULL;
vop_revoke(ap);
return (0);
@@ -461,22 +505,22 @@ devfs_symlink(ap)
} */ *ap;
{
int i;
- struct devfs_dir *dd;
+ struct devfs_dirent *dd;
struct devfs_dirent *de;
- struct devfs_mount *fmp;
+ struct devfs_mount *dmp;
- fmp = (struct devfs_mount *)ap->a_dvp->v_mount->mnt_data;
+ dmp = (struct devfs_mount *)ap->a_dvp->v_mount->mnt_data;
dd = ap->a_dvp->v_data;
de = devfs_newdirent(ap->a_cnp->cn_nameptr, ap->a_cnp->cn_namelen);
de->de_uid = 0;
de->de_gid = 0;
de->de_mode = 0642;
- de->de_inode = fmp->dm_inode++;
+ de->de_inode = dmp->dm_inode++;
de->de_dirent->d_type = DT_LNK;
i = strlen(ap->a_target) + 1;
MALLOC(de->de_symlink, char *, i, M_DEVFS, M_WAITOK);
bcopy(ap->a_target, de->de_symlink, i);
- TAILQ_INSERT_TAIL(&dd->dd_list, de, de_list);
+ TAILQ_INSERT_TAIL(&dd->de_dlist, de, de_list);
devfs_allocv(de, ap->a_dvp->v_mount, ap->a_vpp, 0);
VREF(*(ap->a_vpp));
return (0);
diff --git a/sys/fs/specfs/spec_vnops.c b/sys/fs/specfs/spec_vnops.c
index f6bd853..f681cc8 100644
--- a/sys/fs/specfs/spec_vnops.c
+++ b/sys/fs/specfs/spec_vnops.c
@@ -246,19 +246,22 @@ spec_read(ap)
struct proc *p;
struct uio *uio;
dev_t dev;
- int error;
+ int error, resid;
vp = ap->a_vp;
dev = vp->v_rdev;
uio = ap->a_uio;
p = uio->uio_procp;
+ resid = uio->uio_resid;
- if (uio->uio_resid == 0)
+ if (resid == 0)
return (0);
VOP_UNLOCK(vp, 0, p);
error = (*devsw(dev)->d_read) (dev, uio, ap->a_ioflag);
vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, p);
+ if (uio->uio_resid != resid || (error == 0 && resid != 0))
+ getnanotime(&dev->si_atime);
return (error);
}
@@ -279,16 +282,21 @@ spec_write(ap)
struct proc *p;
struct uio *uio;
dev_t dev;
- int error;
+ int error, resid;
vp = ap->a_vp;
dev = vp->v_rdev;
uio = ap->a_uio;
p = uio->uio_procp;
+ resid = uio->uio_resid;
VOP_UNLOCK(vp, 0, p);
error = (*devsw(dev)->d_write) (dev, uio, ap->a_ioflag);
vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, p);
+ if (uio->uio_resid != resid || (error == 0 && resid != 0)) {
+ getnanotime(&dev->si_ctime);
+ dev->si_mtime = dev->si_ctime;
+ }
return (error);
}
diff --git a/sys/kern/kern_descrip.c b/sys/kern/kern_descrip.c
index 3b67922..e497aee 100644
--- a/sys/kern/kern_descrip.c
+++ b/sys/kern/kern_descrip.c
@@ -40,6 +40,7 @@
*/
#include "opt_compat.h"
+#include "opt_devfs.h"
#include <sys/param.h>
#include <sys/systm.h>
#include <sys/sysproto.h>
@@ -61,6 +62,12 @@
#include <vm/vm.h>
#include <vm/vm_extern.h>
+#ifdef DEVFS
+#include <sys/ctype.h>
+#include <sys/eventhandler.h>
+#include <fs/devfs/devfs.h>
+#endif
+
static MALLOC_DEFINE(M_FILEDESC, "file desc", "Open file descriptor table");
MALLOC_DEFINE(M_FILE, "file", "Open file structure");
static MALLOC_DEFINE(M_SIGIO, "sigio", "sigio structures");
@@ -1313,16 +1320,41 @@ SYSCTL_INT(_kern, KERN_MAXFILES, maxfiles, CTLFLAG_RW,
&maxfiles, 0, "Maximum number of files");
static void
+fildesc_clone(void *arg, char *name, int namelen, dev_t *dev)
+{
+ int u;
+
+ if (*dev != NODEV)
+ return;
+ if (devfs_stdclone(name, NULL, "fd/", &u) != 1)
+ return;
+ if (u <= 2)
+ return;
+ *dev = make_dev(&fildesc_cdevsw, u, UID_BIN, GID_BIN, 0666, name);
+ return;
+}
+
+static void
fildesc_drvinit(void *unused)
{
+ dev_t dev;
+
+ dev = make_dev(&fildesc_cdevsw, 0, UID_BIN, GID_BIN, 0666, "fd/0");
+ make_dev_alias(dev, "stdin");
+ dev = make_dev(&fildesc_cdevsw, 1, UID_BIN, GID_BIN, 0666, "fd/1");
+ make_dev_alias(dev, "stdout");
+ dev = make_dev(&fildesc_cdevsw, 2, UID_BIN, GID_BIN, 0666, "fd/2");
+ make_dev_alias(dev, "stderr");
+#ifdef DEVFS
+ EVENTHANDLER_REGISTER(devfs_clone, fildesc_clone, 0, 1000);
+#else
+ {
int fd;
- for (fd = 0; fd < NUMFDESC; fd++)
- make_dev(&fildesc_cdevsw, fd,
- UID_BIN, GID_BIN, 0666, "fd/%d", fd);
- make_dev(&fildesc_cdevsw, 0, UID_ROOT, GID_WHEEL, 0666, "stdin");
- make_dev(&fildesc_cdevsw, 1, UID_ROOT, GID_WHEEL, 0666, "stdout");
- make_dev(&fildesc_cdevsw, 2, UID_ROOT, GID_WHEEL, 0666, "stderr");
+ for (fd = 3; fd < NUMFDESC; fd++)
+ make_dev(&fildesc_cdevsw, fd, UID_BIN, GID_BIN, 0666, "fd/%d", fd);
+ }
+#endif
}
struct fileops badfileops = {
diff --git a/sys/kern/vfs_conf.c b/sys/kern/vfs_conf.c
index 9a0ca2c..c75ba40 100644
--- a/sys/kern/vfs_conf.c
+++ b/sys/kern/vfs_conf.c
@@ -43,6 +43,7 @@
*/
#include "opt_rootdevname.h"
+#include "opt_devfs.h"
#include <sys/param.h>
#include <sys/kernel.h>
@@ -62,6 +63,11 @@
#include <ddb/ddb.h>
#endif
+#ifdef DEVFS
+#include <sys/eventhandler.h>
+#include <fs/devfs/devfs.h>
+#endif
+
MALLOC_DEFINE(M_MOUNT, "mount", "vfs mount structure");
#define ROOTNAME "root_device"
@@ -320,6 +326,19 @@ gets(char *cp)
*/
dev_t
getdiskbyname(char *name) {
+#ifdef DEVFS
+ char *cp;
+ dev_t dev;
+
+ cp = name;
+ if (!bcmp(cp, "/dev/", 5))
+ cp += 5;
+
+ dev = NODEV;
+ EVENTHANDLER_INVOKE(devfs_clone, cp, strlen(cp), &dev);
+ return (dev);
+
+#else
char *cp;
int cd, unit, slice, part;
dev_t dev;
@@ -367,6 +386,7 @@ gotit:
return (NODEV);
}
return (makedev(cd, dkmakeminor(unit, slice, part)));
+#endif
}
/*
diff --git a/sys/kern/vfs_mount.c b/sys/kern/vfs_mount.c
index 9a0ca2c..c75ba40 100644
--- a/sys/kern/vfs_mount.c
+++ b/sys/kern/vfs_mount.c
@@ -43,6 +43,7 @@
*/
#include "opt_rootdevname.h"
+#include "opt_devfs.h"
#include <sys/param.h>
#include <sys/kernel.h>
@@ -62,6 +63,11 @@
#include <ddb/ddb.h>
#endif
+#ifdef DEVFS
+#include <sys/eventhandler.h>
+#include <fs/devfs/devfs.h>
+#endif
+
MALLOC_DEFINE(M_MOUNT, "mount", "vfs mount structure");
#define ROOTNAME "root_device"
@@ -320,6 +326,19 @@ gets(char *cp)
*/
dev_t
getdiskbyname(char *name) {
+#ifdef DEVFS
+ char *cp;
+ dev_t dev;
+
+ cp = name;
+ if (!bcmp(cp, "/dev/", 5))
+ cp += 5;
+
+ dev = NODEV;
+ EVENTHANDLER_INVOKE(devfs_clone, cp, strlen(cp), &dev);
+ return (dev);
+
+#else
char *cp;
int cd, unit, slice, part;
dev_t dev;
@@ -367,6 +386,7 @@ gotit:
return (NODEV);
}
return (makedev(cd, dkmakeminor(unit, slice, part)));
+#endif
}
/*
diff --git a/sys/miscfs/specfs/spec_vnops.c b/sys/miscfs/specfs/spec_vnops.c
index f6bd853..f681cc8 100644
--- a/sys/miscfs/specfs/spec_vnops.c
+++ b/sys/miscfs/specfs/spec_vnops.c
@@ -246,19 +246,22 @@ spec_read(ap)
struct proc *p;
struct uio *uio;
dev_t dev;
- int error;
+ int error, resid;
vp = ap->a_vp;
dev = vp->v_rdev;
uio = ap->a_uio;
p = uio->uio_procp;
+ resid = uio->uio_resid;
- if (uio->uio_resid == 0)
+ if (resid == 0)
return (0);
VOP_UNLOCK(vp, 0, p);
error = (*devsw(dev)->d_read) (dev, uio, ap->a_ioflag);
vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, p);
+ if (uio->uio_resid != resid || (error == 0 && resid != 0))
+ getnanotime(&dev->si_atime);
return (error);
}
@@ -279,16 +282,21 @@ spec_write(ap)
struct proc *p;
struct uio *uio;
dev_t dev;
- int error;
+ int error, resid;
vp = ap->a_vp;
dev = vp->v_rdev;
uio = ap->a_uio;
p = uio->uio_procp;
+ resid = uio->uio_resid;
VOP_UNLOCK(vp, 0, p);
error = (*devsw(dev)->d_write) (dev, uio, ap->a_ioflag);
vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, p);
+ if (uio->uio_resid != resid || (error == 0 && resid != 0)) {
+ getnanotime(&dev->si_ctime);
+ dev->si_mtime = dev->si_ctime;
+ }
return (error);
}
diff --git a/sys/sys/conf.h b/sys/sys/conf.h
index b5d9c5a..e68c0ea 100644
--- a/sys/sys/conf.h
+++ b/sys/sys/conf.h
@@ -56,6 +56,9 @@ struct specinfo {
u_int si_flags;
#define SI_STASHED 0x0001 /* created in stashed storage */
#define SI_ALIAS 0x0002 /* carrier of alias name */
+ struct timespec si_atime;
+ struct timespec si_ctime;
+ struct timespec si_mtime;
udev_t si_udev;
LIST_ENTRY(specinfo) si_hash;
SLIST_HEAD(, vnode) si_hlist;
diff --git a/sys/sys/linedisc.h b/sys/sys/linedisc.h
index b5d9c5a..e68c0ea 100644
--- a/sys/sys/linedisc.h
+++ b/sys/sys/linedisc.h
@@ -56,6 +56,9 @@ struct specinfo {
u_int si_flags;
#define SI_STASHED 0x0001 /* created in stashed storage */
#define SI_ALIAS 0x0002 /* carrier of alias name */
+ struct timespec si_atime;
+ struct timespec si_ctime;
+ struct timespec si_mtime;
udev_t si_udev;
LIST_ENTRY(specinfo) si_hash;
SLIST_HEAD(, vnode) si_hlist;
OpenPOWER on IntegriCloud