/*
- * Copyright (c) 2002 Apple Computer, Inc. All rights reserved.
+ * Copyright (c) 2002-2003 Apple Computer, Inc. All rights reserved.
*
* @APPLE_LICENSE_HEADER_START@
*
int recycle = 0;
int forkcount = 0;
int truncated = 0;
+ int started_tr = 0, grabbed_lock = 0;
+ cat_cookie_t cookie;
+ int cat_reserve = 0;
if (prtactive && vp->v_usecount != 0)
vprint("hfs_inactive: pushing active", vp);
if (cp->c_mode == 0)
goto out;
- if (vp->v_mount->mnt_flag & MNT_RDONLY)
+ if (hfsmp->hfs_flags & HFS_READ_ONLY)
goto out;
if (cp->c_datafork)
++forkcount;
/* If needed, get rid of any fork's data for a deleted file */
- if ((cp->c_flag & C_DELETED) &&
- vp->v_type == VREG &&
- (VTOF(vp)->ff_blocks != 0)) {
- error = VOP_TRUNCATE(vp, (off_t)0, IO_NDELAY, NOCRED, p);
- if (error) goto out;
- truncated = 1;
+ if ((vp->v_type == VREG) && (cp->c_flag & C_DELETED)) {
+ if (VTOF(vp)->ff_blocks != 0) {
+ error = VOP_TRUNCATE(vp, (off_t)0, IO_NDELAY, NOCRED, p);
+ if (error)
+ goto out;
+ truncated = 1;
+ }
recycle = 1;
}
*/
if ((cp->c_flag & C_DELETED) && (forkcount <= 1)) {
/*
- * Mark cnode in transit so that one can get this
+ * Mark cnode in transit so that no one can get this
* cnode from cnode hash.
*/
SET(cp->c_flag, C_TRANSIT);
cp->c_flag &= ~C_DELETED;
cp->c_rdev = 0;
-
+
+ // XXXdbg
+ hfs_global_shared_lock_acquire(hfsmp);
+ grabbed_lock = 1;
+ if (hfsmp->jnl) {
+ if (journal_start_transaction(hfsmp->jnl) != 0) {
+ error = EINVAL;
+ goto out;
+ }
+ started_tr = 1;
+ }
+
+ /*
+ * Reserve some space in the Catalog file.
+ */
+ if ((error = cat_preflight(hfsmp, CAT_DELETE, &cookie, p))) {
+ goto out;
+ }
+ cat_reserve = 1;
+
+
/* Lock catalog b-tree */
error = hfs_metafilelocking(hfsmp, kHFSCatalogFileID, LK_EXCLUSIVE, p);
if (error) goto out;
if (error) goto out;
#if QUOTA
- if (!hfs_getinoquota(cp))
- (void)hfs_chkiq(cp, -1, NOCRED, 0);
+ (void)hfs_chkiq(cp, -1, NOCRED, 0);
#endif /* QUOTA */
cp->c_mode = 0;
hfs_volupdate(hfsmp, VOL_RMFILE, 0);
}
- /* Push any defered access times to disk */
- if (cp->c_flag & C_ATIMEMOD) {
- cp->c_flag &= ~C_ATIMEMOD;
- if (HFSTOVCB(hfsmp)->vcbSigWord == kHFSPlusSigWord)
- cp->c_flag |= C_MODIFIED;
+ if (cp->c_flag & (C_ACCESS | C_CHANGE | C_MODIFIED | C_UPDATE)) {
+ tv = time;
+ // if the only thing being updated is the access time
+ // then set the modified bit too so that update will
+ // flush it to disk. otherwise it'll get dropped.
+ if ((cp->c_flag & C_CHANGEMASK) == C_ACCESS) {
+ cp->c_flag |= C_MODIFIED;
+ }
+ VOP_UPDATE(vp, &tv, &tv, 0);
}
- if (cp->c_flag & (C_ACCESS | C_CHANGE | C_MODIFIED | C_UPDATE)) {
- tv = time;
- VOP_UPDATE(vp, &tv, &tv, 0);
- }
out:
+ if (cat_reserve)
+ cat_postflight(hfsmp, &cookie, p);
+
+ // XXXdbg - have to do this because a goto could have come here
+ if (started_tr) {
+ journal_end_transaction(hfsmp->jnl);
+ started_tr = 0;
+ }
+ if (grabbed_lock) {
+ hfs_global_shared_lock_release(hfsmp);
+ }
+
VOP_UNLOCK(vp, 0, p);
/*
* If we are done with the vnode, reclaim it
if (prtactive && vp->v_usecount != 0)
vprint("hfs_reclaim(): pushing active", vp);
- devvp = cp->c_devvp; /* For later releasing */
+ /*
+ * Keep track of an inactive hot file.
+ */
+ (void) hfs_addhotfile(vp);
+
+ devvp = cp->c_devvp; /* For later releasing */
/*
* Find file fork for this vnode (if any)
} else if ((fp = cp->c_rsrcfork) && (cp->c_rsrc_vp == vp)) {
cp->c_rsrcfork = NULL;
cp->c_rsrc_vp = NULL;
+ if (VPARENT(vp) == cp->c_vp) {
+ cp->c_flag &= ~C_VPREFHELD;
+ }
altfp = cp->c_datafork;
} else {
cp->c_vp = NULL;
#if QUOTA
for (i = 0; i < MAXQUOTAS; i++) {
if (cp->c_dquot[i] != NODQUOT) {
- dqrele(vp, cp->c_dquot[i]);
+ dqreclaim(vp, cp->c_dquot[i]);
cp->c_dquot[i] = NODQUOT;
}
}
cp->c_desc.cd_nameptr = 0;
cp->c_desc.cd_flags &= ~CD_HASBUF;
cp->c_desc.cd_namelen = 0;
- FREE(nameptr, M_TEMP);
+ remove_name(nameptr);
}
CLR(cp->c_flag, (C_ALLOC | C_TRANSIT));
if (ISSET(cp->c_flag, C_WALLOC) || ISSET(cp->c_flag, C_WTRANSIT))
cp = hfs_chashget(dev, cnid, wantrsrc, &vp, &rvp);
if (cp != NULL) {
/* hide open files that have been deleted */
- if ((hfsmp->hfs_private_metadata_dir != 0)
- && (cp->c_parentcnid == hfsmp->hfs_private_metadata_dir)
+ if ((hfsmp->hfs_privdir_desc.cd_cnid != 0)
+ && (cp->c_parentcnid == hfsmp->hfs_privdir_desc.cd_cnid)
&& (cp->c_nlink == 0)) {
retval = ENOENT;
goto exit;
}
+
+ /* Hide private journal files */
+ if (hfsmp->jnl &&
+ (cp->c_parentcnid == kRootDirID) &&
+ ((cp->c_cnid == hfsmp->hfs_jnlfileid) ||
+ (cp->c_cnid == hfsmp->hfs_jnlinfoblkid))) {
+ retval = ENOENT;
+ goto exit;
+ }
+
if (wantrsrc && rvp != NULL) {
vp = rvp;
rvp = NULL;
cnattr.ca_fileid = kRootParID;
cnattr.ca_nlink = 2;
+ cnattr.ca_entries = 1;
cnattr.ca_mode = (S_IFDIR | S_IRWXU | S_IRWXG | S_IRWXO);
} else {
/* Lock catalog b-tree */
goto exit;
/* Hide open files that have been deleted */
- if ((hfsmp->hfs_private_metadata_dir != 0) &&
- (cndesc.cd_parentcnid == hfsmp->hfs_private_metadata_dir)) {
+ if ((hfsmp->hfs_privdir_desc.cd_cnid != 0) &&
+ (cndesc.cd_parentcnid == hfsmp->hfs_privdir_desc.cd_cnid) &&
+ (cnattr.ca_nlink == 0)) {
cat_releasedesc(&cndesc);
retval = ENOENT;
goto exit;
&& cndesc.cd_namelen > 0) {
replace_desc(VTOC(new_vp), &cndesc);
}
+
cat_releasedesc(&cndesc);
}
+
exit:
/* Release reference taken on opposite vnode (if any). */
if (vp)
- vput(vp);
+ vrele(vp);
else if (rvp)
- vput(rvp);
+ vrele(rvp);
if (retval) {
*vpp = NULL;
if (vp == NULL)
panic("hfs_getcnode: missing vp!");
- UBCINFOCHECK("hfs_getcnode", vp);
+ if (UBCISVALID(vp))
+ UBCINFOCHECK("hfs_getcnode", vp);
*vpp = vp;
return (0);
}
int retval;
dev_t dev;
struct proc *p = current_proc();
-
+#if 0
/* Bail when unmount is in progress */
if (mp->mnt_kern_flag & MNTK_UNMOUNT) {
*vpp = NULL;
return (EPERM);
}
+#endif
#if !FIFO
if (IFTOVT(attrp->ca_mode) == VFIFO) {
SET(cp2->c_flag, C_ALLOC);
cp2->c_cnid = descp->cd_cnid;
cp2->c_fileid = attrp->ca_fileid;
+ if (cp2->c_fileid == 0) {
+ FREE_ZONE(cp2, sizeof(struct cnode), M_HFSNODE);
+ *vpp = NULL;
+ return (ENOENT);
+ }
cp2->c_dev = dev;
lockinit(&cp2->c_lock, PINOD, "cnode", 0, 0);
(void) lockmgr(&cp2->c_lock, LK_EXCLUSIVE, (struct slock *)0, p);
/* Release reference taken on opposite vnode (if any). */
if (rvp)
- vput(rvp);
+ vrele(rvp);
if (vp)
- vput(vp);
+ vrele(vp);
vp = new_vp;
vp->v_ubcinfo = UBC_NOINFO;
bzero(fp, sizeof(struct filefork));
fp->ff_cp = cp;
if (forkp)
- bcopy(forkp, &fp->ff_data, sizeof(HFSPlusForkData));
- if (fp->ff_clumpsize == 0)
- fp->ff_clumpsize = HFSTOVCB(hfsmp)->vcbClpSiz;
+ bcopy(forkp, &fp->ff_data, sizeof(struct cat_fork));
rl_init(&fp->ff_invalidranges);
if (wantrsrc) {
if (cp->c_rsrcfork != NULL)
vp->v_type = IFTOVT(cp->c_mode);
/* Tag system files */
- if ((descp->cd_cnid < kHFSFirstUserCatalogNodeID) && (vp->v_type == VREG))
+ if ((descp->cd_flags & CD_ISMETA) && (vp->v_type == VREG))
vp->v_flag |= VSYSTEM;
/* Tag root directory */
if (cp->c_cnid == kRootDirID)
#endif
}
+ /*
+ * Stop tracking an active hot file.
+ */
+ (void) hfs_removehotfile(vp);
+
/* Vnode is now initialized - see if anyone was waiting for it. */
CLR(cp->c_flag, C_ALLOC);
if (ISSET(cp->c_flag, C_WALLOC)) {