Changeset View
Changeset View
Standalone View
Standalone View
sys/fs/fdescfs/fdesc_vnops.c
Show First 20 Lines • Show All 426 Lines • ▼ Show 20 Lines | |||||
} | } | ||||
static int | static int | ||||
fdesc_getattr(struct vop_getattr_args *ap) | fdesc_getattr(struct vop_getattr_args *ap) | ||||
{ | { | ||||
struct vnode *vp = ap->a_vp; | struct vnode *vp = ap->a_vp; | ||||
struct vattr *vap = ap->a_vap; | struct vattr *vap = ap->a_vap; | ||||
struct timeval boottime; | struct timeval boottime; | ||||
struct file *fp; | |||||
int fd; | |||||
getboottime(&boottime); | getboottime(&boottime); | ||||
vap->va_mode = S_IRUSR|S_IXUSR|S_IRGRP|S_IXGRP|S_IROTH|S_IXOTH; | vap->va_mode = S_IRUSR|S_IXUSR|S_IRGRP|S_IXGRP|S_IROTH|S_IXOTH; | ||||
vap->va_fileid = VTOFDESC(vp)->fd_ix; | vap->va_fileid = VTOFDESC(vp)->fd_ix; | ||||
vap->va_uid = 0; | vap->va_uid = 0; | ||||
vap->va_gid = 0; | vap->va_gid = 0; | ||||
vap->va_blocksize = DEV_BSIZE; | vap->va_blocksize = DEV_BSIZE; | ||||
vap->va_atime.tv_sec = boottime.tv_sec; | vap->va_atime.tv_sec = boottime.tv_sec; | ||||
Show All 9 Lines | fdesc_getattr(struct vop_getattr_args *ap) | ||||
case Froot: | case Froot: | ||||
vap->va_type = VDIR; | vap->va_type = VDIR; | ||||
vap->va_nlink = 2; | vap->va_nlink = 2; | ||||
vap->va_size = DEV_BSIZE; | vap->va_size = DEV_BSIZE; | ||||
vap->va_rdev = NODEV; | vap->va_rdev = NODEV; | ||||
break; | break; | ||||
case Fdesc: | case Fdesc: | ||||
vap->va_type = (vp->v_vflag & VV_READLINK) == 0 ? VCHR : VLNK; | if ((vp->v_vflag & VV_READLINK) != 0) { | ||||
vap->va_type = VLNK; | |||||
fd = VTOFDESC(vp)->fd_fd; | |||||
if (fget(curthread, fd, &cap_no_rights, &fp) == 0) { | |||||
kib: This is severe layering violation, fget() is before vnode lock in the global order. I think… | |||||
vap->va_mode = 0; | |||||
if (fp->f_flag & FREAD) | |||||
vap->va_mode |= (S_IRUSR | S_IXUSR); | |||||
if (fp->f_flag & FWRITE) | |||||
vap->va_mode |= (S_IWUSR | S_IXUSR); | |||||
fdrop(fp, curthread); | |||||
} | |||||
} else { | |||||
vap->va_type = VCHR; | |||||
} | |||||
vap->va_nlink = 1; | vap->va_nlink = 1; | ||||
vap->va_size = 0; | vap->va_size = 0; | ||||
vap->va_rdev = makedev(0, vap->va_fileid); | vap->va_rdev = makedev(0, vap->va_fileid); | ||||
break; | break; | ||||
default: | default: | ||||
panic("fdesc_getattr"); | panic("fdesc_getattr"); | ||||
break; | break; | ||||
▲ Show 20 Lines • Show All 192 Lines • Show Last 20 Lines |
This is severe layering violation, fget() is before vnode lock in the global order. I think you do not get a warning from any debugging facility in kernel because fget() is mostly avoids locks ATM. Sill, this must not be done.
I do not have only two possible suggestions: either do not do anything, or possibly cache file flags in fdescfs vnode v_data at the time of fdesc_allocvp(). There is fget-ed file around that time.