]> git.saurik.com Git - apple/xnu.git/blobdiff - bsd/hfs/hfs_hotfiles.c
xnu-2782.40.9.tar.gz
[apple/xnu.git] / bsd / hfs / hfs_hotfiles.c
index ce0fe4dcf8c1f9789219733a33bafaa4cbe0ddbd..7ba80c737bc31470fd4394d89797d58be24a9c07 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2003-2008 Apple Inc. All rights reserved.
+ * Copyright (c) 2003-2013 Apple Inc. All rights reserved.
  *
  * @APPLE_OSREFERENCE_LICENSE_HEADER_START@
  * 
@@ -207,8 +207,8 @@ hfs_recording_start(struct hfsmount *hfsmp)
                    (SWAP_BE32 (hotfileinfo.timeleft) > 0) &&
                    (SWAP_BE32 (hotfileinfo.timebase) > 0)) {
                        hfsmp->hfc_maxfiles = SWAP_BE32 (hotfileinfo.maxfilecnt);
-                       hfsmp->hfc_timeout = SWAP_BE32 (hotfileinfo.timeleft) + tv.tv_sec ;
                        hfsmp->hfc_timebase = SWAP_BE32 (hotfileinfo.timebase);
+                       hfsmp->hfc_timeout = SWAP_BE32 (hotfileinfo.timeleft) + tv.tv_sec ;
                        /* Fix up any bogus timebase values. */
                        if (hfsmp->hfc_timebase < HFC_MIN_BASE_TIME) {
                                hfsmp->hfc_timebase = hfsmp->hfc_timeout - HFC_DEFAULT_DURATION;
@@ -428,7 +428,6 @@ out:
 /*
  * Suspend recording the hotest files on a file system.
  */
-__private_extern__
 int
 hfs_recording_suspend(struct hfsmount *hfsmp)
 {
@@ -469,7 +468,7 @@ hfs_recording_suspend(struct hfsmount *hfsmp)
            error = EINVAL;
            goto out;
        }
-       if (hfs_lock(VTOC(hfsmp->hfc_filevp), HFS_EXCLUSIVE_LOCK) != 0) {
+       if (hfs_lock(VTOC(hfsmp->hfc_filevp), HFS_EXCLUSIVE_LOCK, HFS_LOCK_DEFAULT) != 0) {
                error = EPERM;
                goto end_transaction;
        }
@@ -511,7 +510,6 @@ out:
 /*
  *
  */
-__private_extern__
 int
 hfs_recording_init(struct hfsmount *hfsmp)
 {
@@ -559,12 +557,17 @@ hfs_recording_init(struct hfsmount *hfsmp)
                        hfsmp->hfc_stage = HFC_IDLE;
                return (0);
        }
+
+       if (hfs_start_transaction(hfsmp) != 0) {
+               return EINVAL;
+       }
+
        error = hfc_btree_create(hfsmp, HFSTOVCB(hfsmp)->blockSize, HFC_DEFAULT_FILE_COUNT);
        if (error) {
 #if HFC_VERBOSE
                printf("hfs: Error %d creating hot file b-tree on %s \n", error, hfsmp->vcbVN);
 #endif
-               return (error);
+               goto out2;
        }
        /*
         * Open the Hot File B-tree file for writing.
@@ -576,7 +579,7 @@ hfs_recording_init(struct hfsmount *hfsmp)
 #if HFC_VERBOSE
                printf("hfs: Error %d opening hot file b-tree on %s \n", error, hfsmp->vcbVN);
 #endif
-               return (error);
+               goto out2;
        }
        MALLOC(iterator, BTreeIterator *, sizeof(*iterator), M_TEMP, M_WAITOK);
        if (iterator == NULL) {
@@ -612,7 +615,7 @@ hfs_recording_init(struct hfsmount *hfsmp)
            error = EINVAL;
            goto out1;
        } 
-       if (hfs_lock(VTOC(hfsmp->hfc_filevp), HFS_EXCLUSIVE_LOCK) != 0) {
+       if (hfs_lock(VTOC(hfsmp->hfc_filevp), HFS_EXCLUSIVE_LOCK, HFS_LOCK_DEFAULT) != 0) {
                error = EPERM;
                goto out0;
        }
@@ -697,6 +700,7 @@ out0:
 out1:
        (void) BTScanTerminate(&scanstate, &data, &data, &data);
 out2:  
+       hfs_end_transaction(hfsmp);
        if (iterator)
                FREE(iterator, M_TEMP);
        if (hfsmp->hfc_filevp) {
@@ -712,7 +716,6 @@ out2:
 /*
  * Use sync to perform ocassional background work.
  */
-__private_extern__
 int
 hfs_hotfilesync(struct hfsmount *hfsmp, vfs_context_t ctx)
 {
@@ -759,7 +762,6 @@ hfs_hotfilesync(struct hfsmount *hfsmp, vfs_context_t ctx)
  *
  * Note: the cnode is locked on entry.
  */
-__private_extern__
 int
 hfs_addhotfile(struct vnode *vp)
 {
@@ -790,9 +792,17 @@ hfs_addhotfile_internal(struct vnode *vp)
        if (hfsmp->hfc_stage != HFC_RECORDING)
                return (0);
 
-       if ((!vnode_isreg(vp) && !vnode_islnk(vp)) || vnode_issystem(vp)) {
+       /* 
+        * Only regular files are eligible for hotfiles addition. 
+        * 
+        * Symlinks were previously added to the list and may exist in 
+        * extant hotfiles regions, but no new ones will be added, and no
+        * symlinks will now be relocated/evicted from the hotfiles region.
+        */
+       if (!vnode_isreg(vp) || vnode_issystem(vp)) {
                return (0);
        }
+
        /* Skip resource forks for now. */
        if (VNODE_IS_RSRC(vp)) {
                return (0);
@@ -808,7 +818,7 @@ hfs_addhotfile_internal(struct vnode *vp)
            (ffp->ff_size == 0) ||
            (ffp->ff_blocks > hotdata->maxblocks) ||
            (cp->c_flag & (C_DELETED | C_NOEXISTS)) ||
-           (cp->c_flags & UF_NODUMP) ||
+           (cp->c_bsdflags & UF_NODUMP) ||
            (cp->c_atime < hfsmp->hfc_timebase)) {
                return (0);
        }
@@ -847,7 +857,6 @@ hfs_addhotfile_internal(struct vnode *vp)
  *
  * Note: the cnode is locked on entry.
  */
-__private_extern__
 int
 hfs_removehotfile(struct vnode *vp)
 {
@@ -861,7 +870,7 @@ hfs_removehotfile(struct vnode *vp)
        if (hfsmp->hfc_stage != HFC_RECORDING)
                return (0);
 
-       if ((!vnode_isreg(vp) && !vnode_islnk(vp)) || vnode_issystem(vp)) {
+       if ((!vnode_isreg(vp)) || vnode_issystem(vp)) {
                return (0);
        }
 
@@ -903,7 +912,7 @@ out:
 static int
 hotfiles_collect_callback(struct vnode *vp, __unused void *cargs)
 {
-        if ((vnode_isreg(vp) || vnode_islnk(vp)) && !vnode_issystem(vp))
+        if ((vnode_isreg(vp)) && !vnode_issystem(vp))
                (void) hfs_addhotfile_internal(vp);
 
        return (VNODE_RETURNED);
@@ -984,7 +993,7 @@ hotfiles_refine(struct hfsmount *hfsmp)
            error = EINVAL;
            goto out;
        } 
-       if (hfs_lock(VTOC(hfsmp->hfc_filevp), HFS_EXCLUSIVE_LOCK) != 0) {
+       if (hfs_lock(VTOC(hfsmp->hfc_filevp), HFS_EXCLUSIVE_LOCK, HFS_LOCK_DEFAULT) != 0) {
                error = EPERM;
                goto out1;
        }
@@ -1089,7 +1098,7 @@ hotfiles_adopt(struct hfsmount *hfsmp)
        if (hfsmp->hfc_stage != HFC_ADOPTION) {
                return (EBUSY);
        }
-       if (hfs_lock(VTOC(hfsmp->hfc_filevp), HFS_EXCLUSIVE_LOCK) != 0) {
+       if (hfs_lock(VTOC(hfsmp->hfc_filevp), HFS_EXCLUSIVE_LOCK, HFS_LOCK_DEFAULT) != 0) {
                return (EPERM);
        }
 
@@ -1128,7 +1137,7 @@ hotfiles_adopt(struct hfsmount *hfsmp)
                /*
                 * Acquire a vnode for this file.
                 */
-               error = hfs_vget(hfsmp, listp->hfl_hotfile[i].hf_fileid, &vp, 0);
+               error = hfs_vget(hfsmp, listp->hfl_hotfile[i].hf_fileid, &vp, 0, 0);
                if (error) {
                        if (error == ENOENT) {
                                error = 0;
@@ -1137,7 +1146,8 @@ hotfiles_adopt(struct hfsmount *hfsmp)
                        }
                        break;
                }
-               if (!vnode_isreg(vp) && !vnode_islnk(vp)) {
+               if (!vnode_isreg(vp)) {
+                       /* Symlinks are ineligible for adoption into the hotfile zone.  */
                        printf("hfs: hotfiles_adopt: huh, not a file %d (%d)\n", listp->hfl_hotfile[i].hf_fileid, VTOC(vp)->c_cnid);
                        hfs_unlock(VTOC(vp));
                        vnode_put(vp);
@@ -1298,7 +1308,7 @@ hotfiles_evict(struct hfsmount *hfsmp, vfs_context_t ctx)
        if ((listp = (hotfilelist_t  *)hfsmp->hfc_recdata) == NULL)
                return (0);     
 
-       if (hfs_lock(VTOC(hfsmp->hfc_filevp), HFS_EXCLUSIVE_LOCK) != 0) {
+       if (hfs_lock(VTOC(hfsmp->hfc_filevp), HFS_EXCLUSIVE_LOCK, HFS_LOCK_DEFAULT) != 0) {
                return (EPERM);
        }
 
@@ -1350,7 +1360,7 @@ hotfiles_evict(struct hfsmount *hfsmp, vfs_context_t ctx)
                /*
                 * Aquire the vnode for this file.
                 */
-               error = hfs_vget(hfsmp, key->fileID, &vp, 0);
+               error = hfs_vget(hfsmp, key->fileID, &vp, 0, 0);
                if (error) {
                        if (error == ENOENT) {
                                goto delete;  /* stale entry, go to next */
@@ -1360,12 +1370,18 @@ hotfiles_evict(struct hfsmount *hfsmp, vfs_context_t ctx)
                        }
                        break;
                }
-               if (!vnode_isreg(vp) && !vnode_islnk(vp)) {
+
+               /* 
+                * Symlinks that may have been inserted into the hotfile zone during a previous OS are now stuck 
+                * here.  We do not want to move them. 
+                */
+               if (!vnode_isreg(vp)) {
                        printf("hfs: hotfiles_evict: huh, not a file %d\n", key->fileID);
                        hfs_unlock(VTOC(vp));
                        vnode_put(vp);
                        goto delete;  /* invalid entry, go to next */
                }
+
                fileblocks = VTOF(vp)->ff_blocks;
                if ((blksmoved > 0) &&
                    (blksmoved + fileblocks) > HFC_BLKSPERSYNC) {
@@ -1520,7 +1536,7 @@ hotfiles_age(struct hfsmount *hfsmp)
            error = EINVAL;
            goto out2;
        } 
-       if (hfs_lock(VTOC(hfsmp->hfc_filevp), HFS_EXCLUSIVE_LOCK) != 0) {
+       if (hfs_lock(VTOC(hfsmp->hfc_filevp), HFS_EXCLUSIVE_LOCK, HFS_LOCK_DEFAULT) != 0) {
                error = EPERM;
                goto out1;
        }
@@ -1684,6 +1700,7 @@ hfc_btree_open(struct hfsmount *hfsmp, struct vnode **vpp)
        int  error;
        int  retry = 0;
        int lockflags;
+       int newvnode_flags = 0;
 
        *vpp = NULL;
        p = current_proc();
@@ -1695,7 +1712,7 @@ hfc_btree_open(struct hfsmount *hfsmp, struct vnode **vpp)
 
        lockflags = hfs_systemfile_lock(hfsmp, SFL_CATALOG, HFS_SHARED_LOCK);
 
-       error = cat_lookup(hfsmp, &cdesc, 0, &cdesc, &cattr, &cfork, NULL);
+       error = cat_lookup(hfsmp, &cdesc, 0, 0, &cdesc, &cattr, &cfork, NULL);
 
        hfs_systemfile_unlock(hfsmp, lockflags);
 
@@ -1705,7 +1722,8 @@ hfc_btree_open(struct hfsmount *hfsmp, struct vnode **vpp)
        }
 again:
        cdesc.cd_flags |= CD_ISMETA;
-       error = hfs_getnewvnode(hfsmp, NULL, NULL, &cdesc, 0, &cattr, &cfork, &vp);
+       error = hfs_getnewvnode(hfsmp, NULL, NULL, &cdesc, 0, &cattr, 
+                                                       &cfork, &vp, &newvnode_flags);
        if (error) {
                printf("hfs: hfc_btree_open: hfs_getnewvnode error %d\n", error);
                cat_releasedesc(&cdesc);
@@ -1757,11 +1775,11 @@ hfc_btree_close(struct hfsmount *hfsmp, struct vnode *vp)
 
 
        if (hfsmp->jnl) {
-           hfs_journal_flush(hfsmp);
+           hfs_journal_flush(hfsmp, FALSE);
        }
 
        if (vnode_get(vp) == 0) {
-               error = hfs_lock(VTOC(vp), HFS_EXCLUSIVE_LOCK);
+               error = hfs_lock(VTOC(vp), HFS_EXCLUSIVE_LOCK, HFS_LOCK_DEFAULT);
                if (error == 0) {
                        (void) hfs_fsync(vp, MNT_WAIT, 0, p);
                        error = BTClosePath(VTOF(vp));
@@ -1814,6 +1832,11 @@ hfc_btree_create(struct hfsmount *hfsmp, unsigned int nodesize, unsigned int ent
        VATTR_SET(&va, va_uid, 0);
        VATTR_SET(&va, va_gid, 0);
 
+       if (hfs_start_transaction(hfsmp) != 0) {
+           error = EINVAL;
+           goto out;
+       } 
+
        /* call ourselves directly, ignore the higher-level VFS file creation code */
        error = VNOP_CREATE(dvp, &vp, &cname, &va, ctx);
        if (error) {
@@ -1824,7 +1847,7 @@ hfc_btree_create(struct hfsmount *hfsmp, unsigned int nodesize, unsigned int ent
                vnode_put(dvp);
                dvp = NULL;
        }
-       if ((error = hfs_lock(VTOC(vp), HFS_EXCLUSIVE_LOCK))) {
+       if ((error = hfs_lock(VTOC(vp), HFS_EXCLUSIVE_LOCK, HFS_LOCK_DEFAULT))) {
                goto out;
        }
        cp = VTOC(vp);
@@ -1908,7 +1931,7 @@ hfc_btree_create(struct hfsmount *hfsmp, unsigned int nodesize, unsigned int ent
                index[(nodesize / 2) - 4] = SWAP_BE16 (offset);
 
                vnode_setnoflush(vp);
-               error = hfs_truncate(vp, (off_t)filesize, IO_NDELAY, 0, 0, ctx);
+               error = hfs_truncate(vp, (off_t)filesize, IO_NDELAY, 0, ctx);
                if (error) {
                        printf("hfs: error %d growing HFBT on %s\n", error, HFSTOVCB(hfsmp)->vcbVN);
                        goto out;
@@ -1941,6 +1964,7 @@ hfc_btree_create(struct hfsmount *hfsmp, unsigned int nodesize, unsigned int ent
                kmem_free(kernel_map, (vm_offset_t)buffer, nodesize);
        }
 out:
+       hfs_end_transaction(hfsmp);
        if (dvp) {
                vnode_put(dvp);
        }