int ntfs_vgetex(struct mount *mp, ino_t ino, u_int32_t attrtype, char *attrname, u_long lkflags, u_long flags, struct thread *td, struct vnode **vpp) { int error; struct ntfsmount *ntmp; struct ntnode *ip; struct fnode *fp; struct vnode *vp; enum vtype f_type; dprintf(("ntfs_vgetex: ino: %ju, attr: 0x%x:%s, lkf: 0x%lx, f: 0x%lx\n", (uintmax_t) ino, attrtype, attrname?attrname:"", lkflags, flags)); ntmp = VFSTONTFS(mp); *vpp = NULL; /* Get ntnode */ error = ntfs_ntlookup(ntmp, ino, &ip); if (error) { kprintf("ntfs_vget: ntfs_ntget failed\n"); return (error); } /* It may be not initialized fully, so force load it */ if (!(flags & VG_DONTLOADIN) && !(ip->i_flag & IN_LOADED)) { error = ntfs_loadntnode(ntmp, ip); if(error) { kprintf("ntfs_vget: CAN'T LOAD ATTRIBUTES FOR INO: %"PRId64"\n", ip->i_number); ntfs_ntput(ip); return (error); } } error = ntfs_fget(ntmp, ip, attrtype, attrname, &fp); if (error) { kprintf("ntfs_vget: ntfs_fget failed\n"); ntfs_ntput(ip); return (error); } f_type = VINT; if (!(flags & VG_DONTVALIDFN) && !(fp->f_flag & FN_VALID)) { if ((ip->i_frflag & NTFS_FRFLAG_DIR) && (fp->f_attrtype == NTFS_A_DATA && fp->f_attrname == NULL)) { f_type = VDIR; } else if (flags & VG_EXT) { f_type = VINT; fp->f_size = fp->f_allocated = 0; } else { f_type = VREG; error = ntfs_filesize(ntmp, fp, &fp->f_size, &fp->f_allocated); if (error) { ntfs_ntput(ip); return (error); } } fp->f_flag |= FN_VALID; } if (FTOV(fp)) { VGET(FTOV(fp), lkflags); *vpp = FTOV(fp); ntfs_ntput(ip); return (0); } error = getnewvnode(VT_NTFS, ntmp->ntm_mountp, &vp, VLKTIMEOUT, 0); if(error) { ntfs_frele(fp); ntfs_ntput(ip); return (error); } dprintf(("ntfs_vget: vnode: %p for ntnode: %ju\n", vp, (uintmax_t)ino)); fp->f_vp = vp; vp->v_data = fp; vp->v_type = f_type; if (ino == NTFS_ROOTINO) vsetflags(vp, VROOT); /* * Normal files use the buffer cache */ if (f_type == VREG) vinitvmio(vp, fp->f_size, PAGE_SIZE, -1); ntfs_ntput(ip); KKASSERT(lkflags & LK_TYPE_MASK); /* XXX leave vnode locked exclusively from getnewvnode */ *vpp = vp; return (0); }
int ntfs_vgetex( struct mount *mp, ino_t ino, u_int32_t attrtype, char *attrname, u_long lkflags, u_long flags, struct vnode **vpp) { int error; struct ntfsmount *ntmp; struct ntnode *ip; struct fnode *fp; struct vnode *vp; enum vtype f_type = VBAD; dprintf(("ntfs_vgetex: ino: %llu, attr: 0x%x:%s, lkf: 0x%lx, f:" " 0x%lx\n", (unsigned long long)ino, attrtype, attrname ? attrname : "", (u_long)lkflags, (u_long)flags)); ntmp = VFSTONTFS(mp); *vpp = NULL; loop: /* Get ntnode */ error = ntfs_ntlookup(ntmp, ino, &ip); if (error) { printf("ntfs_vget: ntfs_ntget failed\n"); return (error); } /* It may be not initialized fully, so force load it */ if (!(flags & VG_DONTLOADIN) && !(ip->i_flag & IN_LOADED)) { error = ntfs_loadntnode(ntmp, ip); if(error) { printf("ntfs_vget: CAN'T LOAD ATTRIBUTES FOR INO:" " %llu\n", (unsigned long long)ip->i_number); ntfs_ntput(ip); return (error); } } error = ntfs_fget(ntmp, ip, attrtype, attrname, &fp); if (error) { printf("ntfs_vget: ntfs_fget failed\n"); ntfs_ntput(ip); return (error); } if (!(flags & VG_DONTVALIDFN) && !(fp->f_flag & FN_VALID)) { if ((ip->i_frflag & NTFS_FRFLAG_DIR) && (fp->f_attrtype == NTFS_A_DATA && fp->f_attrname == NULL)) { f_type = VDIR; } else if (flags & VG_EXT) { f_type = VNON; fp->f_size = fp->f_allocated = 0; } else { f_type = VREG; error = ntfs_filesize(ntmp, fp, &fp->f_size, &fp->f_allocated); if (error) { ntfs_ntput(ip); return (error); } } fp->f_flag |= FN_VALID; } /* * We may be calling vget() now. To avoid potential deadlock, we need * to release ntnode lock, since due to locking order vnode * lock has to be acquired first. * ntfs_fget() bumped ntnode usecount, so ntnode won't be recycled * prematurely. * Take v_interlock before releasing ntnode lock to avoid races. */ vp = FTOV(fp); if (vp) { mutex_enter(vp->v_interlock); ntfs_ntput(ip); if (vget(vp, lkflags) != 0) goto loop; *vpp = vp; return 0; } ntfs_ntput(ip); error = getnewvnode(VT_NTFS, ntmp->ntm_mountp, ntfs_vnodeop_p, NULL, &vp); if(error) { ntfs_frele(fp); return (error); } ntfs_ntget(ip); error = ntfs_fget(ntmp, ip, attrtype, attrname, &fp); if (error) { printf("ntfs_vget: ntfs_fget failed\n"); ntfs_ntput(ip); return (error); } if (FTOV(fp)) { /* * Another thread beat us, put back freshly allocated * vnode and retry. */ ntfs_ntput(ip); ungetnewvnode(vp); goto loop; } dprintf(("ntfs_vget: vnode: %p for ntnode: %llu\n", vp, (unsigned long long)ino)); fp->f_vp = vp; vp->v_data = fp; if (f_type != VBAD) vp->v_type = f_type; genfs_node_init(vp, &ntfs_genfsops); if (ino == NTFS_ROOTINO) vp->v_vflag |= VV_ROOT; ntfs_ntput(ip); if (lkflags & (LK_EXCLUSIVE | LK_SHARED)) { error = vn_lock(vp, lkflags); if (error) { vput(vp); return (error); } } uvm_vnp_setsize(vp, fp->f_size); /* XXX: mess, cf. ntfs_lookupfile() */ vref(ip->i_devvp); *vpp = vp; return (0); }