X-Git-Url: https://git.saurik.com/apple/xnu.git/blobdiff_plain/378393581903b274cb7a4d18e0d978071a6b592d..13fec9890cf095cc781fdf7b8917cb03bf32dd4c:/bsd/hfs/hfs_vfsops.c diff --git a/bsd/hfs/hfs_vfsops.c b/bsd/hfs/hfs_vfsops.c index 7ebe8aff7..ba4a5983d 100644 --- a/bsd/hfs/hfs_vfsops.c +++ b/bsd/hfs/hfs_vfsops.c @@ -548,7 +548,7 @@ hfs_reload_callback(struct vnode *vp, void *cargs) /* * Re-read cnode data for all active vnodes (non-metadata files). */ - if (!VNODE_IS_RSRC(vp)) { + if (!vnode_issystem(vp) && !VNODE_IS_RSRC(vp)) { struct cat_fork *datafork; struct cat_desc desc; @@ -591,7 +591,6 @@ hfs_reload(struct mount *mountp, kauth_cred_t cred, struct proc *p) struct filefork *forkp; struct cat_desc cndesc; struct hfs_reload_cargs args; - int lockflags; hfsmp = VFSTOHFS(mountp); vcb = HFSTOVCB(hfsmp); @@ -617,9 +616,7 @@ hfs_reload(struct mount *mountp, kauth_cred_t cred, struct proc *p) * the vnode will be in an 'unbusy' state (VNODE_WAIT) and * properly referenced and unreferenced around the callback */ - lockflags = hfs_systemfile_lock(hfsmp, SFL_CATALOG, HFS_EXCLUSIVE_LOCK); vnode_iterate(mountp, VNODE_RELOAD | VNODE_WAIT, hfs_reload_callback, (void *)&args); - hfs_systemfile_unlock(hfsmp, lockflags); if (args.error) return (args.error); @@ -2163,6 +2160,7 @@ hfs_vget(struct hfsmount *hfsmp, cnid_t cnid, struct vnode **vpp, int skiplock) struct cat_attr cnattr; struct cat_fork cnfork; struct componentname cn; + u_int32_t linkref = 0; int error; /* Check for cnids that should't be exported. */ @@ -2215,18 +2213,19 @@ hfs_vget(struct hfsmount *hfsmp, cnid_t cnid, struct vnode **vpp, int skiplock) return (error); } - /* Hide open files that have been deleted */ - if ((hfsmp->hfs_privdir_desc.cd_cnid != 0) && - (cndesc.cd_parentcnid == hfsmp->hfs_privdir_desc.cd_cnid)) { - // XXXdbg - if this is a hardlink, we could call - // hfs_chash_snoop() to see if there is - // already a cnode and vnode present for - // this fileid. however I'd rather not - // risk it at this point in Tiger. - cat_releasedesc(&cndesc); - error = ENOENT; - *vpp = NULL; - return (error); + /* + * If we just looked up a raw hardlink inode, + * then finish initializing it. + */ + if ((cndesc.cd_parentcnid == hfsmp->hfs_privdir_desc.cd_cnid) && + (bcmp(cndesc.cd_nameptr, HFS_INODE_PREFIX, HFS_INODE_PREFIX_LEN) == 0)) { + linkref = strtoul((const char*)&cndesc.cd_nameptr[HFS_INODE_PREFIX_LEN], NULL, 10); + cnattr.ca_rdev = linkref; + + // patch up the parentcnid + if (cnattr.ca_attrblks != 0) { + cndesc.cd_parentcnid = cnattr.ca_attrblks; + } } } @@ -2246,6 +2245,10 @@ hfs_vget(struct hfsmount *hfsmp, cnid_t cnid, struct vnode **vpp, int skiplock) /* XXX should we supply the parent as well... ? */ error = hfs_getnewvnode(hfsmp, NULLVP, &cn, &cndesc, 0, &cnattr, &cnfork, &vp); + if (error == 0 && linkref != 0) { + VTOC(vp)->c_flag |= C_HARDLINK; + } + FREE_ZONE(cn.cn_pnbuf, cn.cn_pnlen, M_NAMEI); cat_releasedesc(&cndesc); @@ -3277,7 +3280,6 @@ hfs_reclaimspace(struct hfsmount *hfsmp, u_long startblk) if (VTOF(vp)->ff_blocks > 0) { error = hfs_relocate(vp, hfsmp->hfs_metazone_end + 1, kauth_cred_get(), current_proc()); } - hfs_unlock(VTOC(vp)); if (error) break; @@ -3286,17 +3288,17 @@ hfs_reclaimspace(struct hfsmount *hfsmp, u_long startblk) error = hfs_vgetrsrc(hfsmp, vp, &rvp, current_proc()); if (error) break; - hfs_lock(VTOC(rvp), HFS_EXCLUSIVE_LOCK); error = hfs_relocate(rvp, hfsmp->hfs_metazone_end + 1, kauth_cred_get(), current_proc()); - hfs_unlock(VTOC(rvp)); vnode_put(rvp); if (error) break; } + hfs_unlock(VTOC(vp)); vnode_put(vp); vp = NULL; } if (vp) { + hfs_unlock(VTOC(vp)); vnode_put(vp); vp = NULL; }