]> git.saurik.com Git - apple/xnu.git/blobdiff - bsd/hfs/hfs_vnops.c
xnu-792.6.70.tar.gz
[apple/xnu.git] / bsd / hfs / hfs_vnops.c
index 5c0cc83ed9cb7c55c1cca837d64a9985d2487ee0..507bb153cb8b12485a6d3756b3816f86017fa636 100644 (file)
@@ -43,6 +43,7 @@
 #include <machine/spl.h>
 
 #include <sys/kdebug.h>
+#include <sys/sysctl.h>
 
 #include "hfs.h"
 #include "hfs_catalog.h"
@@ -65,6 +66,9 @@
 
 /* Global vfs data structures for hfs */
 
+/* Always F_FULLFSYNC? 1=yes,0=no (default due to "various" reasons is 'no') */
+int always_do_fullfsync = 0;
+SYSCTL_INT (_kern, OID_AUTO, always_do_fullfsync, CTLFLAG_RW, &always_do_fullfsync, 0, "always F_FULLFSYNC when fsync is called");
 
 extern unsigned long strtoul(const char *, char **, int);
 
@@ -236,6 +240,7 @@ hfs_vnop_close(ap)
        if (hfsmp->hfs_freezing_proc == p && proc_exiting(p)) {
            hfsmp->hfs_freezing_proc = NULL;
            hfs_global_exclusive_lock_release(hfsmp);
+           lck_rw_unlock_exclusive(&hfsmp->hfs_insync);
        }
 
        busy = vnode_isinuse(vp, 1);
@@ -284,7 +289,7 @@ hfs_vnop_getattr(struct vnop_getattr_args *ap)
                        if (vnode_isvroot(vp)) {
                                if (hfsmp->hfs_privdir_desc.cd_cnid != 0)
                                        --entries;     /* hide private dir */
-                               if (hfsmp->jnl)
+                               if (hfsmp->jnl || ((HFSTOVCB(hfsmp)->vcbAtrb & kHFSVolumeJournaledMask) && (hfsmp->hfs_flags & HFS_READ_ONLY)))
                                        entries -= 2;  /* hide the journal files */
                        }
                        VATTR_RETURN(vap, va_nlink, (uint64_t)entries);
@@ -962,6 +967,7 @@ hfs_vnop_exchange(ap)
        from_cp->c_uid = to_cp->c_uid;
        from_cp->c_flags = to_cp->c_flags;
        from_cp->c_mode = to_cp->c_mode;
+       from_cp->c_attr.ca_recflags = to_cp->c_attr.ca_recflags;
        bcopy(to_cp->c_finderinfo, from_cp->c_finderinfo, 32);
 
        bcopy(&tempdesc, &to_cp->c_desc, sizeof(struct cat_desc));
@@ -975,6 +981,7 @@ hfs_vnop_exchange(ap)
        to_cp->c_uid = tempattr.ca_uid;
        to_cp->c_flags = tempattr.ca_flags;
        to_cp->c_mode = tempattr.ca_mode;
+       to_cp->c_attr.ca_recflags = tempattr.ca_recflags;
        bcopy(tempattr.ca_finderinfo, to_cp->c_finderinfo, 32);
 
        /* Rehash the cnodes using their new file IDs */
@@ -1137,7 +1144,7 @@ metasync:
                cp->c_touch_acctime = FALSE;
                cp->c_touch_chgtime = FALSE;
                cp->c_touch_modtime = FALSE;
-       } else /* User file */ {
+       } else if ( !(vp->v_flag & VSWAP) ) /* User file */ {
                retval = hfs_update(vp, wait);
 
                /* When MNT_WAIT is requested push out any delayed meta data */
@@ -1150,7 +1157,7 @@ metasync:
                // fsync() and if so push out any pending transactions 
                // that this file might is a part of (and get them on
                // stable storage).
-               if (fullsync) {
+               if (fullsync || always_do_fullfsync) {
                    if (hfsmp->jnl) {
                        journal_flush(hfsmp->jnl);
                    } else {
@@ -1883,6 +1890,10 @@ out:
 __private_extern__ void
 replace_desc(struct cnode *cp, struct cat_desc *cdp)
 {
+    if (&cp->c_desc == cdp) {
+        return;
+    }
+         
        /* First release allocated name buffer */
        if (cp->c_desc.cd_flags & CD_HASBUF && cp->c_desc.cd_nameptr != 0) {
                char *name = cp->c_desc.cd_nameptr;
@@ -2441,6 +2452,10 @@ hfs_vnop_readdir(ap)
        if (nfs_cookies) {
                cnid_hint = (cnid_t)(uio_offset(uio) >> 32);
                uio_setoffset(uio, uio_offset(uio) & 0x00000000ffffffffLL);
+               if (cnid_hint == INT_MAX) { /* searching pass the last item */
+                       eofflag = 1;
+                       goto out;
+               }
        }
        /*
         * Synthesize entries for "." and ".."
@@ -2565,7 +2580,7 @@ hfs_vnop_readdir(ap)
        }
        
        /* Pack the buffer with dirent entries. */
-       error = cat_getdirentries(hfsmp, cp->c_entries, dirhint, uio, extended, &items);
+       error = cat_getdirentries(hfsmp, cp->c_entries, dirhint, uio, extended, &items, &eofflag);
 
        hfs_systemfile_unlock(hfsmp, lockflags);
 
@@ -3156,6 +3171,22 @@ hfs_vgetrsrc(struct hfsmount *hfsmp, struct vnode *vp, struct vnode **rvpp, __un
                struct componentname cn;
                int lockflags;
 
+               /*
+                * Make sure cnode lock is exclusive, if not upgrade it.
+                *
+                * We assume that we were called from a read-only VNOP (getattr)
+                * and that its safe to have the cnode lock dropped and reacquired.
+                */
+               if (cp->c_lockowner != current_thread()) {
+                       /*
+                        * If the upgrade fails we loose the lock and
+                        * have to take the exclusive lock on our own.
+                        */
+                       if (lck_rw_lock_shared_to_exclusive(&cp->c_rwlock) != 0)
+                               lck_rw_lock_exclusive(&cp->c_rwlock);
+                       cp->c_lockowner = current_thread();
+               }
+
                lockflags = hfs_systemfile_lock(hfsmp, SFL_CATALOG, HFS_SHARED_LOCK);
 
                /* Get resource fork data */