]> git.saurik.com Git - apple/xnu.git/blobdiff - bsd/kern/kern_symfile.c
xnu-2422.90.20.tar.gz
[apple/xnu.git] / bsd / kern / kern_symfile.c
index 1636b4ab58b9414986fc19e36a933318c9df5a3b..062ffa524d36fcfa79daa1525af9ad0711b03462 100644 (file)
@@ -203,7 +203,7 @@ kern_open_file_for_direct_io(const char * name,
     int                                isssd = 0;
     uint32_t                    flags = 0;
     uint32_t                   blksize;
-    off_t                      maxiocount, count;
+    off_t                      maxiocount, count, segcount;
     boolean_t                   locked = FALSE;
 
     int (*do_ioctl)(void * p1, void * p2, u_long theIoctl, caddr_t result);
@@ -226,6 +226,13 @@ kern_open_file_for_direct_io(const char * name,
     if ((error = vnode_open(name, (O_CREAT | FWRITE), (0), 0, &ref->vp, ref->ctx)))
         goto out;
 
+    if (ref->vp->v_type == VREG)
+    {
+        vnode_lock_spin(ref->vp);
+        SET(ref->vp->v_flag, VSWAP);
+        vnode_unlock(ref->vp);
+    }
+
     if (write_file_addr && write_file_len)
     {
        if ((error = kern_write_file(ref, write_file_offset, write_file_addr, write_file_len)))
@@ -236,6 +243,7 @@ kern_open_file_for_direct_io(const char * name,
     VATTR_WANTED(&va, va_rdev);
     VATTR_WANTED(&va, va_fsid);
     VATTR_WANTED(&va, va_data_size);
+    VATTR_WANTED(&va, va_data_alloc);
     VATTR_WANTED(&va, va_nlink);
     error = EFAULT;
     if (vnode_getattr(ref->vp, &va, ref->ctx))
@@ -243,7 +251,7 @@ kern_open_file_for_direct_io(const char * name,
 
     kprintf("vp va_rdev major %d minor %d\n", major(va.va_rdev), minor(va.va_rdev));
     kprintf("vp va_fsid major %d minor %d\n", major(va.va_fsid), minor(va.va_fsid));
-    kprintf("vp size %qd\n", va.va_data_size);
+    kprintf("vp size %qd alloc %qd\n", va.va_data_size, va.va_data_alloc);
 
     if (ref->vp->v_type == VREG)
     {
@@ -258,17 +266,36 @@ kern_open_file_for_direct_io(const char * name,
         p2 = p;
         do_ioctl = &file_ioctl;
 
-       if (set_file_size)
+       if (set_file_size && (set_file_size != (off_t) va.va_data_alloc))
        {
-           off_t     bytesallocated = 0;
            u_int32_t alloc_flags = PREALLOCATE | ALLOCATEFROMPEOF | ALLOCATEALL;
-           error = VNOP_ALLOCATE(ref->vp, set_file_size, alloc_flags,
-                                 &bytesallocated, 0 /*fst_offset*/,
-                                 ref->ctx);
+
+           vnode_lock_spin(ref->vp);
+           CLR(ref->vp->v_flag, VSWAP);
+           vnode_unlock(ref->vp);
+
+            if (set_file_size < (off_t) va.va_data_alloc)
+            {
+                struct vnode_attr setva;
+                VATTR_INIT(&setva);
+                VATTR_SET(&setva, va_data_size, set_file_size);
+                error = vnode_setattr(ref->vp, &setva, ref->ctx);
+            }
+            else
+            {
+                off_t bytesallocated = set_file_size - va.va_data_alloc;
+                error = VNOP_ALLOCATE(ref->vp, bytesallocated, alloc_flags,
+                                      &bytesallocated, 0 /*fst_offset*/,
+                                      ref->ctx);
+                HIBLOG("VNOP_ALLOCATE(%d) %qd\n", error, bytesallocated);
+            }
            // F_SETSIZE:
-           if (!error) error = vnode_setsize(ref->vp, set_file_size, IO_NOZEROFILL, ref->ctx);
-           kprintf("vnode_setsize(%d) %qd\n", error, set_file_size);
-           ref->filelength = bytesallocated;
+           (void) vnode_setsize(ref->vp, set_file_size, IO_NOZEROFILL, ref->ctx);
+           ref->filelength = set_file_size;
+
+           vnode_lock_spin(ref->vp);
+           SET(ref->vp->v_flag, VSWAP);
+           vnode_unlock(ref->vp);
        }
     }
     else if ((ref->vp->v_type == VBLK) || (ref->vp->v_type == VCHR))
@@ -355,7 +382,15 @@ kern_open_file_for_direct_io(const char * name,
                 error = ENOTSUP;
                 goto out;
             }
+#if HIBFRAGMENT
+           uint64_t rev;
+           for (rev = 4096; rev <= getphysreq.length; rev += 4096)
+           {
+               callback(callback_ref, getphysreq.offset + getphysreq.length - rev, 4096);
+           }
+#else
             callback(callback_ref, getphysreq.offset, getphysreq.length);
+#endif
             physoffset += getphysreq.length;
         }
         f_offset += filechunk;
@@ -406,14 +441,20 @@ kern_open_file_for_direct_io(const char * name,
         maxiocount = count;
 
     error = do_ioctl(p1, p2, DKIOCGETMAXSEGMENTBYTECOUNTREAD, (caddr_t) &count);
+    if (!error)
+       error = do_ioctl(p1, p2, DKIOCGETMAXSEGMENTCOUNTREAD, (caddr_t) &segcount);
     if (error)
-        count = 0;
+        count = segcount = 0;
+    count *= segcount;
     if (count && (count < maxiocount))
         maxiocount = count;
 
     error = do_ioctl(p1, p2, DKIOCGETMAXSEGMENTBYTECOUNTWRITE, (caddr_t) &count);
+    if (!error)
+       error = do_ioctl(p1, p2, DKIOCGETMAXSEGMENTCOUNTWRITE, (caddr_t) &segcount);
     if (error)
-        count = 0;
+        count = segcount = 0;
+    count *= segcount;
     if (count && (count < maxiocount))
         maxiocount = count;
 
@@ -498,14 +539,14 @@ kern_close_file_for_direct_io(struct kern_direct_file_io_ref_t * ref,
         }
         (void) do_ioctl(p1, p2, DKIOCUNLOCKPHYSICALEXTENTS, NULL);
         
-        if (addr && write_length)
-        {
-            (void) kern_write_file(ref, write_offset, addr, write_length);
-        }
         if (discard_offset && discard_end && !ref->pinned)
         {
             (void) kern_ioctl_file_extents(ref, DKIOCUNMAP, discard_offset, discard_end);
         }
+        if (addr && write_length)
+        {
+            (void) kern_write_file(ref, write_offset, addr, write_length);
+        }
 
         error = vnode_close(ref->vp, FWRITE, ref->ctx);