/*
* 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;
struct filefork *forkp;
struct cat_desc cndesc;
struct hfs_reload_cargs args;
- int lockflags;
hfsmp = VFSTOHFS(mountp);
vcb = HFSTOVCB(hfsmp);
* 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);
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. */
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;
+ }
}
}
/* 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);
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;
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;
}