diff options
author | phk <phk@FreeBSD.org> | 2000-09-06 11:26:43 +0000 |
---|---|---|
committer | phk <phk@FreeBSD.org> | 2000-09-06 11:26:43 +0000 |
commit | c9cb5c289d5aaaea9a1cb017bd8b2f24c3483f8e (patch) | |
tree | f3e131458b74087067e30359371eb0ee0414890b /sys/fs/devfs/devfs_vnops.c | |
parent | 6c07bccbf798848cb394146e35ef94c64121accd (diff) | |
download | FreeBSD-src-c9cb5c289d5aaaea9a1cb017bd8b2f24c3483f8e.zip FreeBSD-src-c9cb5c289d5aaaea9a1cb017bd8b2f24c3483f8e.tar.gz |
Add refcounts to the "global" DEVFS inode slots, this allows us
to recycle inodes after a destroy_dev() but not until all mounts
have picked up the change.
Add support for an overflow table for DEVFS inodes. The static
table defaults to 1024 inodes, if that fills, an overflow table
of 32k inodes is allocated. Both numbers can be changed at
compile time, the size of the overflow table also with the
sysctl vfs.devfs.noverflow.
Use atomic instructions to barrier between make_dev()/destroy_dev()
and the mounts.
Add lockmgr() locking of directories for operations accessing or
modifying the directory TAILQs.
Various nitpicking here and there.
Diffstat (limited to 'sys/fs/devfs/devfs_vnops.c')
-rw-r--r-- | sys/fs/devfs/devfs_vnops.c | 60 |
1 files changed, 38 insertions, 22 deletions
diff --git a/sys/fs/devfs/devfs_vnops.c b/sys/fs/devfs/devfs_vnops.c index e96dafb..db95406 100644 --- a/sys/fs/devfs/devfs_vnops.c +++ b/sys/fs/devfs/devfs_vnops.c @@ -43,19 +43,16 @@ #include <sys/vnode.h> #include <sys/malloc.h> #include <sys/proc.h> -#include <sys/stat.h> #include <sys/mount.h> #include <sys/namei.h> #include <sys/dirent.h> -#include <sys/eventhandler.h> -#define DEVFS_INTERN #include <fs/devfs/devfs.h> static int devfs_access __P((struct vop_access_args *ap)); static int devfs_badop __P((void)); static int devfs_getattr __P((struct vop_getattr_args *ap)); -static int devfs_lookup __P((struct vop_lookup_args *ap)); +static int devfs_lookupx __P((struct vop_lookup_args *ap)); static int devfs_print __P((struct vop_print_args *ap)); static int devfs_read __P((struct vop_read_args *ap)); static int devfs_readdir __P((struct vop_readdir_args *ap)); @@ -66,12 +63,12 @@ static int devfs_revoke __P((struct vop_revoke_args *ap)); static int devfs_setattr __P((struct vop_setattr_args *ap)); static int devfs_symlink __P((struct vop_symlink_args *ap)); - int devfs_allocv(struct devfs_dirent *de, struct mount *mp, struct vnode **vpp, struct proc *p) { int error; struct vnode *vp; + dev_t dev; if (p == NULL) p = curproc; /* XXX */ @@ -83,6 +80,13 @@ loop: *vpp = vp; return (0); } + if (de->de_dirent->d_type == DT_CHR) { + dev = *devfs_itod(de->de_inode); + if (dev == NULL) + return (ENOENT); + } else { + dev = NODEV; + } error = getnewvnode(VT_DEVFS, mp, devfs_vnodeop_p, &vp); if (error != 0) { printf("devfs_allocv: failed to allocate new vnode\n"); @@ -91,7 +95,7 @@ loop: if (de->de_dirent->d_type == DT_CHR) { vp->v_type = VCHR; - vp = addaliasu(vp, devfs_inot[de->de_inode]->si_udev); + vp = addaliasu(vp, dev->si_udev); vp->v_op = devfs_specop_p; } else if (de->de_dirent->d_type == DT_DIR) { vp->v_type = VDIR; @@ -153,6 +157,7 @@ devfs_getattr(ap) vap->va_mode = de->de_mode; vap->va_size = 0; vap->va_blocksize = DEV_BSIZE; + vap->va_type = vp->v_type; if (vp->v_type != VCHR) { vap->va_atime = de->de_atime; vap->va_mtime = de->de_mtime; @@ -162,23 +167,14 @@ devfs_getattr(ap) vap->va_atime = dev->si_atime; vap->va_mtime = dev->si_mtime; vap->va_ctime = dev->si_ctime; + vap->va_rdev = dev->si_udev; } vap->va_gen = 0; vap->va_flags = 0; - vap->va_rdev = 0; vap->va_bytes = 0; vap->va_nlink = de->de_links; vap->va_fileid = de->de_inode; - if (de->de_dirent->d_type == DT_DIR) { - vap->va_type = VDIR; - } else if (de->de_dirent->d_type == DT_LNK) { - vap->va_type = VLNK; - } else if (de->de_dirent->d_type == DT_CHR) { - vap->va_type = VCHR; - vap->va_rdev = devfs_inot[de->de_inode]->si_udev; - } - #ifdef DEBUG if (error) printf("devfs_getattr: return error %d\n", error); @@ -187,7 +183,7 @@ devfs_getattr(ap) } static int -devfs_lookup(ap) +devfs_lookupx(ap) struct vop_lookup_args /* { struct vnode * a_dvp; struct vnode ** a_vpp; @@ -358,6 +354,19 @@ found: return (0); } +static int +devfs_lookup(struct vop_lookup_args *ap) +{ + int j; + struct devfs_mount *dmp; + + dmp = VFSTODEVFS(ap->a_dvp->v_mount); + lockmgr(&dmp->dm_lock, LK_SHARED, 0, curproc); + j = devfs_lookupx(ap); + lockmgr(&dmp->dm_lock, LK_RELEASE, 0, curproc); + return (j); +} + /* ARGSUSED */ static int devfs_print(ap) @@ -415,6 +424,7 @@ devfs_readdir(ap) return (EINVAL); dmp = VFSTODEVFS(ap->a_vp->v_mount); + lockmgr(&dmp->dm_lock, LK_SHARED, 0, curproc); devfs_populate(dmp); error = 0; de = ap->a_vp->v_data; @@ -437,6 +447,7 @@ devfs_readdir(ap) off += dp->d_reclen; dd = TAILQ_NEXT(dd, de_list); } + lockmgr(&dmp->dm_lock, LK_RELEASE, 0, curproc); uio->uio_offset = off; return (error); } @@ -486,16 +497,19 @@ devfs_remove(ap) { struct vnode *vp = ap->a_vp; struct devfs_dirent *dd; - struct devfs_dirent *de; - struct devfs_mount *dm = VFSTODEVFS(vp->v_mount); + struct devfs_dirent *de, **dep; + struct devfs_mount *dmp = VFSTODEVFS(vp->v_mount); + lockmgr(&dmp->dm_lock, LK_EXCLUSIVE, 0, curproc); dd = ap->a_dvp->v_data; de = vp->v_data; - 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; + dep = devfs_itode(dmp, de->de_inode); + if (dep != NULL) + *dep = DE_DELETED; + de->de_flags |= DE_ORPHAN; vdrop(de->de_vnode); + lockmgr(&dmp->dm_lock, LK_RELEASE, 0, curproc); return (0); } @@ -589,8 +603,10 @@ devfs_symlink(ap) i = strlen(ap->a_target) + 1; MALLOC(de->de_symlink, char *, i, M_DEVFS, M_WAITOK); bcopy(ap->a_target, de->de_symlink, i); + lockmgr(&dmp->dm_lock, LK_EXCLUSIVE, 0, curproc); TAILQ_INSERT_TAIL(&dd->de_dlist, de, de_list); devfs_allocv(de, ap->a_dvp->v_mount, ap->a_vpp, 0); + lockmgr(&dmp->dm_lock, LK_RELEASE, 0, curproc); return (0); } |