summaryrefslogtreecommitdiffstats
path: root/sys/fs/devfs/devfs_vnops.c
diff options
context:
space:
mode:
Diffstat (limited to 'sys/fs/devfs/devfs_vnops.c')
-rw-r--r--sys/fs/devfs/devfs_vnops.c60
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);
}
OpenPOWER on IntegriCloud