]> git.saurik.com Git - apple/xnu.git/blobdiff - bsd/kern/ubc_subr.c
xnu-792.22.5.tar.gz
[apple/xnu.git] / bsd / kern / ubc_subr.c
index c56fe8b2b3f0f7956257124fd51661b5bc94c750..deaaa090a5e3dc053e5d92609bc318d36dfd2e55 100644 (file)
@@ -1,23 +1,29 @@
 /*
- * Copyright (c) 1999 Apple Computer, Inc. All rights reserved.
+ * Copyright (c) 1999-2004 Apple Computer, Inc. All rights reserved.
  *
- * @APPLE_LICENSE_HEADER_START@
+ * @APPLE_OSREFERENCE_LICENSE_HEADER_START@
  * 
- * The contents of this file constitute Original Code as defined in and
- * are subject to the Apple Public Source License Version 1.1 (the
- * "License").  You may not use this file except in compliance with the
- * License.  Please obtain a copy of the License at
- * http://www.apple.com/publicsource and read it before using this file.
+ * This file contains Original Code and/or Modifications of Original Code
+ * as defined in and that are subject to the Apple Public Source License
+ * Version 2.0 (the 'License'). You may not use this file except in
+ * compliance with the License. The rights granted to you under the License
+ * may not be used to create, or enable the creation or redistribution of,
+ * unlawful or unlicensed copies of an Apple operating system, or to
+ * circumvent, violate, or enable the circumvention or violation of, any
+ * terms of an Apple operating system software license agreement.
  * 
- * This Original Code and all software distributed under the License are
- * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER
+ * Please obtain a copy of the License at
+ * http://www.opensource.apple.com/apsl/ and read it before using this file.
+ * 
+ * The Original Code and all software distributed under the License are
+ * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
  * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
  * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT.  Please see the
- * License for the specific language governing rights and limitations
- * under the License.
+ * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
+ * Please see the License for the specific language governing rights and
+ * limitations under the License.
  * 
- * @APPLE_LICENSE_HEADER_END@
+ * @APPLE_OSREFERENCE_LICENSE_HEADER_END@
  */
 /* 
  *     File:   ubc_subr.c
  *
  *     Functions related to Unified Buffer cache.
  *
+ * Caller of UBC functions MUST have a valid reference on the vnode.
+ *
  */ 
 
+#undef DIAGNOSTIC
 #define DIAGNOSTIC 1
 
 #include <sys/types.h>
 #include <sys/param.h>
 #include <sys/systm.h>
 #include <sys/lock.h>
-#include <sys/ubc.h>
-#include <sys/mount.h>
-#include <sys/vnode.h>
-#include <sys/ubc.h>
+#include <sys/mman.h>
+#include <sys/mount_internal.h>
+#include <sys/vnode_internal.h>
+#include <sys/ubc_internal.h>
 #include <sys/ucred.h>
-#include <sys/proc.h>
+#include <sys/proc_internal.h>
+#include <sys/kauth.h>
 #include <sys/buf.h>
+#include <sys/user.h>
 
 #include <mach/mach_types.h>
 #include <mach/memory_object_types.h>
+#include <mach/memory_object_control.h>
+#include <mach/vm_map.h>
+#include <mach/upl.h>
 
+#include <kern/kern_types.h>
 #include <kern/zalloc.h>
+#include <kern/thread.h>
+#include <vm/vm_kern.h>
+#include <vm/vm_protos.h> /* last */
 
 #if DIAGNOSTIC
 #if defined(assert)
 #undef assert()
 #endif
 #define assert(cond)    \
-    if (!(cond)) panic("%s:%d (%s)", __FILE__, __LINE__, # cond)
+    ((void) ((cond) ? 0 : panic("%s:%d (%s)", __FILE__, __LINE__, # cond)))
 #else
 #include <kern/assert.h>
 #endif /* DIAGNOSTIC */
 
-struct zone    *ubc_info_zone;
-
-#if DIAGNOSTIC
-#define USHOULDNOT(fun)        panic("%s: should not", (fun));
-#else
-#define USHOULDNOT(fun)
-#endif /* DIAGNOSTIC */
-
-
-static void *_ubc_getobject(struct vnode *, int);
-static void ubc_lock(struct vnode *);
-static void ubc_unlock(struct vnode *);
-
-static void
-ubc_getobjref(struct vnode *vp)
-{
-       register struct ubc_info        *uip;
-       void *pager_cport;
-       void *object;
-
-       uip = vp->v_ubcinfo;
+int ubc_info_init_internal(struct vnode *vp, int withfsize, off_t filesize);
+static int ubc_umcallback(vnode_t, void *);
+int ubc_isinuse_locked(vnode_t, int, int);
+static int ubc_msync_internal(vnode_t, off_t, off_t, off_t *, int, int *);
 
-       if (pager_cport = (void *)vnode_pager_lookup(vp, uip->ui_pager))
-               object = (void *)vm_object_lookup(pager_cport);
-
-       if (object != uip->ui_object) {
-#if 0
-               Debugger("ubc_getobjref: object changed");
-#endif /* 0 */
-               uip->ui_object = object;
-       }
-
-       if (uip->ui_object == NULL)
-               panic("ubc_getobjref: lost object");
-}
+struct zone    *ubc_info_zone;
 
 /*
  *     Initialization of the zone for Unified Buffer Cache.
  */
-void
+__private_extern__ void
 ubc_init()
 {
        int     i;
@@ -112,129 +101,123 @@ ubc_init()
  */
 int
 ubc_info_init(struct vnode *vp)
+{
+       return(ubc_info_init_internal(vp, 0, 0));
+}
+int
+ubc_info_init_withsize(struct vnode *vp, off_t filesize)
+{
+       return(ubc_info_init_internal(vp, 1, filesize));
+}
+
+int
+ubc_info_init_internal(struct vnode *vp, int withfsize, off_t filesize)
 {
        register struct ubc_info        *uip;
        void *  pager;
-       struct vattr    vattr;
        struct proc *p = current_proc();
        int error = 0;
        kern_return_t kret;
-       void *  pager_cport;
+       memory_object_control_t control;
 
-       assert(vp);
-       assert(UBCISVALID(vp));
+       uip = vp->v_ubcinfo;
 
-       ubc_lock(vp);
-       if (ISSET(vp->v_flag,  VUINIT)) {
-               /*
-                * other thread is already doing this
-                * wait till done
-                */
-               while (ISSET(vp->v_flag,  VUINIT)) {
-                       SET(vp->v_flag, VUWANT); /* XXX overloaded! */
-                       ubc_unlock(vp);
-                       (void) tsleep((caddr_t)vp, PINOD, "ubcinfo", 0);
-                       ubc_lock(vp);
-               }
-               ubc_unlock(vp);
-               return (0);
-       } else {
-               SET(vp->v_flag, VUINIT);
-       }
+       if (uip == UBC_INFO_NULL) {
 
-       uip = vp->v_ubcinfo;
-       if ((uip == UBC_INFO_NULL) || (uip == UBC_NOINFO)) {
-               ubc_unlock(vp);
                uip = (struct ubc_info *) zalloc(ubc_info_zone);
-               bzero(uip, sizeof(struct ubc_info));
-               ubc_lock(vp);
-               SET(uip->ui_flags, UI_INITED);
+               bzero((char *)uip, sizeof(struct ubc_info));
+
                uip->ui_vnode = vp;
+               uip->ui_flags = UI_INITED;
                uip->ui_ucred = NOCRED;
        }
+#if DIAGNOSTIC
+       else
+               Debugger("ubc_info_init: already");
+#endif /* DIAGNOSTIC */
        
        assert(uip->ui_flags != UI_NONE);
        assert(uip->ui_vnode == vp);
 
-#if 0
-       if(ISSET(uip->ui_flags, UI_HASPAGER))
-               goto done;
-#endif /* 0 */
-
        /* now set this ubc_info in the vnode */
        vp->v_ubcinfo = uip;
-       SET(uip->ui_flags, UI_HASPAGER);
-       ubc_unlock(vp);
+
        pager = (void *)vnode_pager_setup(vp, uip->ui_pager);
        assert(pager);
 
+       SET(uip->ui_flags, UI_HASPAGER);
+       uip->ui_pager = pager;
+
        /*
-        * Can not use VOP_GETATTR() to get accurate value
-        * of ui_size. Thanks to NFS.
+        * Note: We can not use VNOP_GETATTR() to get accurate
+        * value of ui_size. Thanks to NFS.
         * nfs_getattr() can call vinvalbuf() and in this case
         * ubc_info is not set up to deal with that.
         * So use bogus size.
         */
 
-       /* create a vm_object association */
-       kret = vm_object_create_nomap(pager, (vm_object_offset_t)uip->ui_size);
-       if (kret != KERN_SUCCESS)
-               panic("ubc_info_init: vm_object_create_nomap returned %d", kret);
-
-       /* _ubc_getobject() gets a reference on the memory object */
-       if (_ubc_getobject(vp, 0) == NULL)
-               panic("ubc_info_init: lost vmobject : uip = 0X%08x", uip);
-
        /*
-        * vm_object_allocate() called from vm_object_create_nomap()
-        * created the object with a refcount of 1
-        * need to drop the reference gained by vm_object_lookup()
+        * create a vnode - vm_object association
+        * memory_object_create_named() creates a "named" reference on the
+        * memory object we hold this reference as long as the vnode is
+        * "alive."  Since memory_object_create_named() took its own reference
+        * on the vnode pager we passed it, we can drop the reference
+        * vnode_pager_setup() returned here.
         */
-       vm_object_deallocate(uip->ui_object);
+       kret = memory_object_create_named(pager,
+               (memory_object_size_t)uip->ui_size, &control);
+       vnode_pager_deallocate(pager); 
+       if (kret != KERN_SUCCESS)
+               panic("ubc_info_init: memory_object_create_named returned %d", kret);
 
+       assert(control);
+       uip->ui_control = control;      /* cache the value of the mo control */
+       SET(uip->ui_flags, UI_HASOBJREF);       /* with a named reference */
+#if 0
        /* create a pager reference on the vnode */
-       error = vget(vp, LK_INTERLOCK, p);
+       error = vnode_pager_vget(vp);
        if (error)
-               panic("ubc_info_init: vget error = %d", error);
-
-       /* initialize the size */
-       error = VOP_GETATTR(vp, &vattr, p->p_ucred, p);
-
-       ubc_lock(vp);
-       uip->ui_size = (error ? 0: vattr.va_size);
-
-done:
-       CLR(vp->v_flag, VUINIT);
-       if (ISSET(vp->v_flag, VUWANT)) {
-               CLR(vp->v_flag, VUWANT);
-               ubc_unlock(vp);
-               wakeup((caddr_t)vp);
-       } else 
-               ubc_unlock(vp);
+               panic("ubc_info_init: vnode_pager_vget error = %d", error);
+#endif
+       if (withfsize == 0) {
+               struct vfs_context context;
+               /* initialize the size */
+               context.vc_proc = p;
+               context.vc_ucred = kauth_cred_get();
+               error = vnode_size(vp, &uip->ui_size, &context);
+               if (error)
+                       uip->ui_size = 0;
+       } else {
+               uip->ui_size = filesize;
+       }
+       vp->v_lflag |= VNAMED_UBC;
 
-       return(error);
+       return (error);
 }
 
 /* Free the ubc_info */
-void
-ubc_info_free(struct vnode *vp)
+static void
+ubc_info_free(struct ubc_info *uip)
 {
-       register struct ubc_info        *uip;
-       struct ucred *credp;
+       if (IS_VALID_CRED(uip->ui_ucred)) {
+               kauth_cred_unref(&uip->ui_ucred);
+       }
+
+       if (uip->ui_control != MEMORY_OBJECT_CONTROL_NULL)
+               memory_object_control_deallocate(uip->ui_control);
        
-       assert(vp);
+       cluster_release(uip);
 
-       uip = vp->v_ubcinfo;
-       vp->v_ubcinfo = UBC_INFO_NULL;
-       credp = uip->ui_ucred;
-       if (credp != NOCRED) {
-               uip->ui_ucred = NOCRED;
-               crfree(credp);
-       }
        zfree(ubc_info_zone, (vm_offset_t)uip);
        return;
 }
 
+void
+ubc_info_deallocate(struct ubc_info *uip)
+{
+        ubc_info_free(uip);
+}
+
 /*
  * Communicate with VM the size change of the file
  * returns 1 on success, 0 on failure
@@ -245,20 +228,14 @@ ubc_setsize(struct vnode *vp, off_t nsize)
        off_t osize;    /* ui_size before change */
        off_t lastpg, olastpgend, lastoff;
        struct ubc_info *uip;
-       void *object;
+       memory_object_control_t control;
        kern_return_t kret;
-       int didhold;
 
-#if DIAGNOSTIC
-       assert(vp);
-       assert(nsize >= (off_t)0);
-#endif
-
-       if (UBCINVALID(vp))
-               return(0);
+       if (nsize < (off_t)0)
+               return (0);
 
        if (!UBCINFOEXISTS(vp))
-               return(0);
+               return (0);
 
        uip = vp->v_ubcinfo;
        osize = uip->ui_size;   /* call ubc_getsize() ??? */
@@ -266,7 +243,7 @@ ubc_setsize(struct vnode *vp, off_t nsize)
        uip->ui_size = nsize;
 
        if (nsize >= osize)     /* Nothing more to do */
-               return(0);
+               return (1);             /* return success */
 
        /*
         * When the file shrinks, invalidate the pages beyond the
@@ -276,11 +253,10 @@ ubc_setsize(struct vnode *vp, off_t nsize)
         * end of the file.
         */
 
-       didhold = ubc_hold(vp);
        lastpg = trunc_page_64(nsize);
        olastpgend = round_page_64(osize);
-       object = _ubc_getobject(vp, UBC_NOREACTIVATE);
-       assert(object);
+       control = uip->ui_control;
+       assert(control);
        lastoff = (nsize & PAGE_MASK_64);
 
        /*
@@ -288,227 +264,119 @@ ubc_setsize(struct vnode *vp, off_t nsize)
         * invalidating is sufficient
         */
         if (!lastoff) {
-        /*
-         * memory_object_lock_request() drops an object
-         * reference. gain a reference before calling it
-         */
-        ubc_getobjref(vp);
-
         /* invalidate last page and old contents beyond nsize */
-        kret = memory_object_lock_request(object,
-                    (vm_object_offset_t)lastpg,
-                    (memory_object_size_t)(olastpgend - lastpg),
-                    MEMORY_OBJECT_RETURN_NONE,TRUE,
-                    VM_PROT_NO_CHANGE,MACH_PORT_NULL);
+        kret = memory_object_lock_request(control,
+                    (memory_object_offset_t)lastpg,
+                   (memory_object_size_t)(olastpgend - lastpg), NULL, NULL,
+                    MEMORY_OBJECT_RETURN_NONE, MEMORY_OBJECT_DATA_FLUSH,
+                    VM_PROT_NO_CHANGE);
         if (kret != KERN_SUCCESS)
             printf("ubc_setsize: invalidate failed (error = %d)\n", kret);
 
-               if (didhold)
-                       ubc_rele(vp);
                return ((kret == KERN_SUCCESS) ? 1 : 0);
         }
 
-       /* 
-        * memory_object_lock_request() drops an object
-        * reference. gain a reference before calling it
-        */
-       ubc_getobjref(vp);
-
        /* flush the last page */
-       kret = memory_object_lock_request(object,
-                               (vm_object_offset_t)lastpg,
-                               PAGE_SIZE_64,
-                               MEMORY_OBJECT_RETURN_DIRTY,FALSE,
-                               VM_PROT_NO_CHANGE,MACH_PORT_NULL);
+       kret = memory_object_lock_request(control,
+                               (memory_object_offset_t)lastpg,
+                               PAGE_SIZE_64, NULL, NULL,
+                               MEMORY_OBJECT_RETURN_DIRTY, FALSE,
+                               VM_PROT_NO_CHANGE);
 
        if (kret == KERN_SUCCESS) {
-               /* 
-                * memory_object_lock_request() drops an object
-                * reference. gain a reference before calling it
-                */
-               ubc_getobjref(vp);
-
                /* invalidate last page and old contents beyond nsize */
-               kret = memory_object_lock_request(object,
-                                       (vm_object_offset_t)lastpg,
-                                       (memory_object_size_t)(olastpgend - lastpg),
-                                       MEMORY_OBJECT_RETURN_NONE,TRUE,
-                                       VM_PROT_NO_CHANGE,MACH_PORT_NULL);
+               kret = memory_object_lock_request(control,
+                                       (memory_object_offset_t)lastpg,
+                                       (memory_object_size_t)(olastpgend - lastpg), NULL, NULL,
+                                       MEMORY_OBJECT_RETURN_NONE, MEMORY_OBJECT_DATA_FLUSH,
+                                       VM_PROT_NO_CHANGE);
                if (kret != KERN_SUCCESS)
                        printf("ubc_setsize: invalidate failed (error = %d)\n", kret);
        } else
                printf("ubc_setsize: flush failed (error = %d)\n", kret);
 
-       if (didhold)
-               ubc_rele(vp);
        return ((kret == KERN_SUCCESS) ? 1 : 0);
 }
 
 /*
  * Get the size of the file
- * For local file systems the size is locally cached. For NFS
- * there might be a network transaction for this.
  */
 off_t
 ubc_getsize(struct vnode *vp)
 {
-       /* XXX deal with NFS */
+       /* people depend on the side effect of this working this way
+        * as they call this for directory 
+        */
+       if (!UBCINFOEXISTS(vp))
+               return ((off_t)0);
        return (vp->v_ubcinfo->ui_size);
 }
 
-/* lock for changes to struct UBC */
-static void
-ubc_lock(struct vnode *vp)
-{
-       /* For now, just use the v_interlock */
-       simple_lock(&vp->v_interlock);
-}
-
-/* unlock */
-static void
-ubc_unlock(struct vnode *vp)
-{
-       /* For now, just use the v_interlock */
-       simple_unlock(&vp->v_interlock);
-}
-
 /*
- * Caller indicate that the object corresponding to the vnode 
- * can not be cached in object cache. Make it so.
+ * call ubc_sync_range(vp, 0, EOF, UBC_PUSHALL) on all the vnodes
+ * for this mount point.
  * returns 1 on success, 0 on failure
- *
- * Caller of ubc_uncache() MUST have a valid reference on the vnode.
  */
-int
-ubc_uncache(struct vnode *vp)
-{
-       void *object;
-       kern_return_t kret;
-       struct ubc_info *uip;
-       memory_object_perf_info_data_t   perf;
-       int didhold;
-
-       assert(vp);
-
-       if (!UBCINFOEXISTS(vp))
-               return (0);
-
-       uip = vp->v_ubcinfo;
 
-       assert(uip != UBC_INFO_NULL);
-
-       /*
-        * AGE it so that vfree() can make sure that it
-        * would get recycled soon after the last reference is gone
-        * This will insure that .nfs turds would not linger
-        */
-       vagevp(vp);
-
-       /* set the "do not cache" bit */
-       SET(uip->ui_flags, UI_DONTCACHE);
-
-       didhold = ubc_hold(vp);
-
-       object = _ubc_getobject(vp, UBC_NOREACTIVATE);
-       assert(object);
+__private_extern__ int
+ubc_umount(struct mount *mp)
+{
+       vnode_iterate(mp, 0, ubc_umcallback, 0);
+       return(0);
+}
 
-       /* 
-        * memory_object_change_attributes() drops an object
-        * reference. gain a reference before calling it
-        */
-       ubc_getobjref(vp);
+static int
+ubc_umcallback(vnode_t vp, __unused void * args)
+{
 
-       perf.cluster_size = PAGE_SIZE; /* XXX use real cluster_size. */
-       perf.may_cache = FALSE;
-       kret = memory_object_change_attributes(object,
-                               MEMORY_OBJECT_PERFORMANCE_INFO,
-                               (memory_object_info_t) &perf,
-                               MEMORY_OBJECT_PERF_INFO_COUNT,
-                               MACH_PORT_NULL, 0);
+       if (UBCINFOEXISTS(vp)) {
 
-       if (didhold)
-               ubc_rele(vp);
+               cluster_push(vp, 0);
 
-       if (kret != KERN_SUCCESS) {
-#if DIAGNOSTIC
-               panic("ubc_uncache: memory_object_change_attributes "
-                       "kret = %d", kret);
-#endif /* DIAGNOSTIC */
-               return (0);
+               (void) ubc_msync(vp, (off_t)0, ubc_getsize(vp), NULL, UBC_PUSHALL);
        }
-
-       return (1);
+       return (VNODE_RETURNED);
 }
 
 
-/*
- * call ubc_clean() and ubc_uncache() on all the vnodes
- * for this mount point.
- * returns 1 on success, 0 on failure
- */
-int
-ubc_umount(struct mount *mp)
-{
-       struct proc *p = current_proc();
-       struct vnode *vp, *nvp;
-       int ret = 1;
-
-loop:
-       simple_lock(&mntvnode_slock);
-       for (vp = mp->mnt_vnodelist.lh_first; vp; vp = nvp) {
-               if (vp->v_mount != mp) {
-                       simple_unlock(&mntvnode_slock);
-                       goto loop;
-               }
-               nvp = vp->v_mntvnodes.le_next;
-               simple_unlock(&mntvnode_slock);
-               if (UBCINFOEXISTS(vp)) {
-                       ret &= ubc_clean(vp, 0); /* do not invalidate */
-                       ret &= ubc_uncache(vp);
-                       ubc_release(vp);
-               }
-               simple_lock(&mntvnode_slock);
-       }
-       simple_unlock(&mntvnode_slock);
-       return (ret);
-}
 
-/*
- * Call ubc_unmount() for all filesystems.
- * The list is traversed in reverse order
- * of mounting to avoid dependencies.
- */
-void
-ubc_unmountall()
+/* Get the credentials */
+kauth_cred_t
+ubc_getcred(struct vnode *vp)
 {
-       struct mount *mp, *nmp;
+        if (UBCINFOEXISTS(vp))
+               return (vp->v_ubcinfo->ui_ucred);
 
-       /*
-        * Since this only runs when rebooting, it is not interlocked.
-        */
-       for (mp = mountlist.cqh_last; mp != (void *)&mountlist; mp = nmp) {
-               nmp = mp->mnt_list.cqe_prev;
-               (void) ubc_umount(mp);
-       }
+       return (NOCRED);
 }
 
-/* Get the credentials */
-struct ucred *
-ubc_getcred(struct vnode *vp)
+int
+ubc_setthreadcred(struct vnode *vp, struct proc *p, thread_t thread)
 {
        struct ubc_info *uip;
+       kauth_cred_t credp;
+       struct uthread *uthread = get_bsdthread_info(thread);
 
-       assert(vp);
+       if (!UBCINFOEXISTS(vp))
+               return (1);
 
-       uip = vp->v_ubcinfo;
+       vnode_lock(vp);
 
-       assert(uip);
+       uip = vp->v_ubcinfo;
+       credp = uip->ui_ucred;
 
-       if (UBCINVALID(vp)) {
-               return (NOCRED);
+       if (!IS_VALID_CRED(credp)) {
+               /* use per-thread cred, if assumed identity, else proc cred */
+               if (uthread == NULL || (uthread->uu_flag & UT_SETUID) == 0) {
+                       uip->ui_ucred = kauth_cred_proc_ref(p);
+               } else {
+                       uip->ui_ucred = uthread->uu_ucred;
+                       kauth_cred_ref(uip->ui_ucred);
+               }
        }
+       vnode_unlock(vp);
 
-       return (uip->ui_ucred);
+       return (0);
 }
 
 /*
@@ -516,640 +384,611 @@ ubc_getcred(struct vnode *vp)
  * existing credentials are not changed
  * returns 1 on success and 0 on failure
  */
-
 int
 ubc_setcred(struct vnode *vp, struct proc *p)
 {
        struct ubc_info *uip;
-       struct ucred *credp;
-
-       assert(vp);
-       assert(p);
-
-       uip = vp->v_ubcinfo;
-
-       assert(uip);
+       kauth_cred_t credp;
 
-       if (UBCINVALID(vp)) {
-               USHOULDNOT("ubc_setcred");
+        if ( !UBCINFOEXISTS(vp))
                return (0); 
-       }
 
+       vnode_lock(vp);
+
+       uip = vp->v_ubcinfo;
        credp = uip->ui_ucred;
-       if (credp == NOCRED) {
-               crhold(p->p_ucred);
-               uip->ui_ucred = p->p_ucred;
+
+       if (!IS_VALID_CRED(credp)) {
+               uip->ui_ucred = kauth_cred_proc_ref(p);
        } 
+       vnode_unlock(vp);
 
        return (1);
 }
 
 /* Get the pager */
-void *
+__private_extern__ memory_object_t
 ubc_getpager(struct vnode *vp)
 {
-       struct ubc_info *uip;
-
-       assert(vp);
-
-       uip = vp->v_ubcinfo;
-
-       assert(uip);
+        if (UBCINFOEXISTS(vp))
+               return (vp->v_ubcinfo->ui_pager);
 
-       if (UBCINVALID(vp)) {
-               USHOULDNOT("ubc_getpager");
-               return (0);
-       }
-
-       return (uip->ui_pager);
+       return (0);
 }
 
 /*
  * Get the memory object associated with this vnode
  * If the vnode was reactivated, memory object would not exist.
  * Unless "do not rectivate" was specified, look it up using the pager.
- * The vm_object_lookup() would create a reference on the memory object.
  * If hold was requested create an object reference of one does not
  * exist already.
  */
 
-static void *
-_ubc_getobject(struct vnode *vp, int flags)
+memory_object_control_t
+ubc_getobject(struct vnode *vp, __unused int flags)
 {
-       struct ubc_info *uip;
-       void *object;
-
-       uip = vp->v_ubcinfo;
-       object = uip->ui_object;
+        if (UBCINFOEXISTS(vp))
+               return((vp->v_ubcinfo->ui_control));
 
-       if ((object == NULL) && ISSET(uip->ui_flags, UI_HASPAGER)
-               && !(flags & UBC_NOREACTIVATE)) {
-               void *pager_cport; 
+       return (0);
+}
 
-               if (ISSET(uip->ui_flags, UI_HASOBJREF))
-                       panic("ubc_getobject: lost object");
 
-               if (pager_cport = (void *)vnode_pager_lookup(vp, uip->ui_pager)) {
-                       object = (void *)vm_object_lookup(pager_cport);
-#if 0
-                       if ((uip->ui_object) && (uip->ui_object != object))
-                               Debugger("_ubc_getobject: object changed");
-#endif /* 0 */
+off_t
+ubc_blktooff(vnode_t vp, daddr64_t blkno)
+{
+       off_t file_offset;
+       int error;
 
-                       uip->ui_object = object;
-               }
+       if (UBCINVALID(vp))
+               return ((off_t)-1);
 
-               if (object != NULL)
-                       SET(uip->ui_flags, UI_HASOBJREF);
-       }
+       error = VNOP_BLKTOOFF(vp, blkno, &file_offset);
+       if (error)
+               file_offset = -1;
 
-       if ((flags & UBC_HOLDOBJECT)
-               && (object != NULL)) {
-               if (!ISSET(uip->ui_flags, UI_HASOBJREF)) {
-                       ubc_getobjref(vp);
-                       SET(uip->ui_flags, UI_HASOBJREF);
-               }
-       }
-       return (uip->ui_object);
+       return (file_offset);
 }
 
-void *
-ubc_getobject(struct vnode *vp, int flags)
+daddr64_t
+ubc_offtoblk(vnode_t vp, off_t offset)
 {
-       struct ubc_info *uip;
-       void *object;
-
-       assert(vp);
-       uip = vp->v_ubcinfo;
-       assert(uip);
+       daddr64_t blkno;
+       int error = 0;
 
-       if (UBCINVALID(vp)) {
-               return (0);
-       }
+       if (UBCINVALID(vp))
+               return ((daddr64_t)-1);
 
-       object = _ubc_getobject(vp, flags);
-       assert(object);
+       error = VNOP_OFFTOBLK(vp, offset, &blkno);
+       if (error)
+               blkno = -1;
 
-       if (!ISSET(uip->ui_flags, (UI_HASOBJREF|UI_WASMAPPED)) 
-               && !(uip->ui_holdcnt)) {
-               if (!(flags & UBC_PAGINGOP))
-               panic("ubc_getobject: lost reference");
-       }
+       return (blkno);
 }
 
-/* Set the pager */
 int
-ubc_setpager(struct vnode *vp, void *pager)
+ubc_pages_resident(vnode_t vp)
 {
-       struct ubc_info *uip;
-
-       assert(vp);
-
-       uip = vp->v_ubcinfo;
+       kern_return_t           kret;
+       boolean_t                       has_pages_resident;
+       
+       if ( !UBCINFOEXISTS(vp))
+               return (0);
+                       
+       kret = memory_object_pages_resident(vp->v_ubcinfo->ui_control, &has_pages_resident);
+       
+       if (kret != KERN_SUCCESS)
+               return (0);
+               
+       if (has_pages_resident == TRUE)
+               return (1);
+               
+       return (0);
+}
 
-       assert(uip);
 
-       if (UBCINVALID(vp)) {
-               USHOULDNOT("ubc_setpager");
-               return (0);
-       }
 
-       uip->ui_pager = pager;
-       return (1);
+/*
+ * This interface will eventually be deprecated
+ *
+ * clean and/or invalidate  a range in the memory object that backs this
+ * vnode. The start offset is truncated to the page boundary and the
+ * size is adjusted to include the last page in the range.
+ *
+ * returns 1 for success,  0 for failure
+ */
+int
+ubc_sync_range(vnode_t vp, off_t beg_off, off_t end_off, int flags)
+{
+        return (ubc_msync_internal(vp, beg_off, end_off, NULL, flags, NULL));
 }
 
-int 
-ubc_setflags(struct vnode * vp, int  flags)
-{
-       struct ubc_info *uip;
 
-       if (UBCINVALID(vp)) {
-               USHOULDNOT("ubc_setflags");
-               return (EINVAL);
-       }
+/*
+ * clean and/or invalidate  a range in the memory object that backs this
+ * vnode. The start offset is truncated to the page boundary and the
+ * size is adjusted to include the last page in the range.
+ * if a
+ */
+errno_t
+ubc_msync(vnode_t vp, off_t beg_off, off_t end_off, off_t *resid_off, int flags)
+{
+        int retval;
+       int io_errno = 0;
+       
+       if (resid_off)
+               *resid_off = beg_off;
 
-       assert(vp);
+        retval = ubc_msync_internal(vp, beg_off, end_off, resid_off, flags, &io_errno);
 
-       uip = vp->v_ubcinfo;
-
-       assert(uip);
+       if (retval == 0 && io_errno == 0)
+               return (EINVAL);
+       return (io_errno);
+}
 
-       SET(uip->ui_flags, flags);
 
-       return(0);      
-} 
 
-int 
-ubc_clearflags(struct vnode * vp, int  flags)
+/*
+ * clean and/or invalidate  a range in the memory object that backs this
+ * vnode. The start offset is truncated to the page boundary and the
+ * size is adjusted to include the last page in the range.
+ */
+static int
+ubc_msync_internal(vnode_t vp, off_t beg_off, off_t end_off, off_t *resid_off, int flags, int *io_errno)
 {
-       struct ubc_info *uip;
-
-       if (UBCINVALID(vp)) {
-               USHOULDNOT("ubc_clearflags");
-               return (EINVAL);
-       }
+       memory_object_size_t    tsize;
+       kern_return_t           kret;
+       int request_flags = 0;
+       int flush_flags   = MEMORY_OBJECT_RETURN_NONE;
+       
+       if ( !UBCINFOEXISTS(vp))
+               return (0);
+       if (end_off <= beg_off)
+               return (0);
+       if ((flags & (UBC_INVALIDATE | UBC_PUSHDIRTY | UBC_PUSHALL)) == 0)
+               return (0);
+
+       if (flags & UBC_INVALIDATE)
+               /*
+                * discard the resident pages
+                */
+               request_flags = (MEMORY_OBJECT_DATA_FLUSH | MEMORY_OBJECT_DATA_NO_CHANGE);
 
-       assert(vp);
+       if (flags & UBC_SYNC)
+               /*
+                * wait for all the I/O to complete before returning
+                */
+               request_flags |= MEMORY_OBJECT_IO_SYNC;
 
-       uip = vp->v_ubcinfo;
+       if (flags & UBC_PUSHDIRTY)
+               /*
+                * we only return the dirty pages in the range
+                */
+               flush_flags = MEMORY_OBJECT_RETURN_DIRTY;
 
-       assert(uip);
+       if (flags & UBC_PUSHALL)
+               /*
+                * then return all the interesting pages in the range (both dirty and precious)
+                * to the pager
+                */
+               flush_flags = MEMORY_OBJECT_RETURN_ALL;
 
-       CLR(uip->ui_flags, flags);
+       beg_off = trunc_page_64(beg_off);
+       end_off = round_page_64(end_off);
+       tsize   = (memory_object_size_t)end_off - beg_off;
 
-       return(0);      
-} 
+       /* flush and/or invalidate pages in the range requested */
+       kret = memory_object_lock_request(vp->v_ubcinfo->ui_control,
+                                         beg_off, tsize, resid_off, io_errno,
+                                         flush_flags, request_flags, VM_PROT_NO_CHANGE);
+       
+       return ((kret == KERN_SUCCESS) ? 1 : 0);
+}
 
 
-int 
-ubc_issetflags(struct vnode * vp, int  flags)
+/*
+ * The vnode is mapped explicitly, mark it so.
+ */
+__private_extern__ int
+ubc_map(vnode_t vp, int flags)
 {
        struct ubc_info *uip;
+       int error = 0;
+       int need_ref = 0;
+       struct vfs_context context;
 
-       if (UBCINVALID(vp)) {
-               USHOULDNOT("ubc_issetflags");
-               return (EINVAL);
-       }
-
-       assert(vp);
-
-       uip = vp->v_ubcinfo;
-
-       assert(uip);
-
-       return(ISSET(uip->ui_flags, flags));
-} 
+       if (vnode_getwithref(vp))
+               return (0);
 
-off_t
-ubc_blktooff(struct vnode *vp, daddr_t blkno)
-{
-       off_t file_offset;
-       int error;
+       if (UBCINFOEXISTS(vp)) {
+               context.vc_proc = current_proc();
+               context.vc_ucred = kauth_cred_get();
 
-       assert(vp);
-    if (UBCINVALID(vp)) { 
-               USHOULDNOT("ubc_blktooff");
-        return ((off_t)-1);
-    }   
+               error = VNOP_MMAP(vp, flags, &context);
 
-       error = VOP_BLKTOOFF(vp, blkno, &file_offset);
-       if (error)
-               file_offset = -1;
+               if (error != EPERM)
+                       error = 0;
 
-       return (file_offset);
-}
-daddr_t
-ubc_offtoblk(struct vnode *vp, off_t offset)
-{
-       daddr_t blkno;
-       int error=0;
+               if (error == 0) {
+                       vnode_lock(vp);
+                       
+                       uip = vp->v_ubcinfo;
 
-       assert(vp);
-    if (UBCINVALID(vp)) { 
-        return ((daddr_t)-1);
-    }   
+                       if ( !ISSET(uip->ui_flags, UI_ISMAPPED))
+                               need_ref = 1;
+                       SET(uip->ui_flags, (UI_WASMAPPED | UI_ISMAPPED));
 
-       error = VOP_OFFTOBLK(vp, offset, &blkno);
-       if (error)
-               blkno = -1;
+                       vnode_unlock(vp);
+                       
+                       if (need_ref)
+                               vnode_ref(vp);
+               }
+       }
+       vnode_put(vp);
 
-       return (blkno);
+       return (error);
 }
 
 /*
- * Cause the file data in VM to be pushed out to the storage
- * it also causes all currently valid pages to be released
- * returns 1 on success, 0 on failure
+ * destroy the named reference for a given vnode
  */
-int
-ubc_clean(struct vnode *vp, int invalidate)
+__private_extern__ int
+ubc_destroy_named(struct vnode *vp)
 {
-       off_t size;
+       memory_object_control_t control;
        struct ubc_info *uip;
-       void *object;
        kern_return_t kret;
-       int flags = 0;
-       int didhold;
-
-#if DIAGNOSTIC
-       assert(vp);
-#endif
-
-       if (UBCINVALID(vp))
-               return(0);
-
-       if (!UBCINFOEXISTS(vp))
-               return(0);
 
        /*
-        * if invalidate was requested, write dirty data and then discard
-        * the resident pages
+        * We may already have had the object terminated
+        * and the ubcinfo released as a side effect of
+        * some earlier processing.  If so, pretend we did
+        * it, because it probably was a result of our
+        * efforts.
         */
-       if (invalidate)
-               flags = (MEMORY_OBJECT_DATA_FLUSH | MEMORY_OBJECT_DATA_NO_CHANGE);
+       if (!UBCINFOEXISTS(vp))
+               return (1);
 
-       didhold = ubc_hold(vp);
        uip = vp->v_ubcinfo;
-       size = uip->ui_size;    /* call ubc_getsize() ??? */
-
-       object = _ubc_getobject(vp, UBC_NOREACTIVATE);
-       assert(object);
 
        /* 
-        * memory_object_lock_request() drops an object
-        * reference. gain a reference before calling it
+        * Terminate the memory object.
+        * memory_object_destroy() will result in
+        * vnode_pager_no_senders(). 
+        * That will release the pager reference
+        * and the vnode will move to the free list.
         */
-       ubc_getobjref(vp);
+       control = ubc_getobject(vp, UBC_HOLDOBJECT);
+       if (control != MEMORY_OBJECT_CONTROL_NULL) {
 
-       vp->v_flag &= ~VHASDIRTY;
-       vp->v_clen = 0;
+         /*
+          * XXXXX - should we hold the vnode lock here?
+          */
+               if (ISSET(vp->v_flag, VTERMINATE))
+                       panic("ubc_destroy_named: already teminating");
+               SET(vp->v_flag, VTERMINATE);
 
-       /* Write the dirty data in the file and discard cached pages */
-       kret = memory_object_lock_request(object,
-                               (vm_object_offset_t)0,
-                               (memory_object_size_t)round_page_64(size),
-                               MEMORY_OBJECT_RETURN_ALL, flags,
-                               VM_PROT_NO_CHANGE,MACH_PORT_NULL);
+               kret = memory_object_destroy(control, 0);
+               if (kret != KERN_SUCCESS)
+                       return (0);
 
-       if (kret != KERN_SUCCESS) {
-               printf("ubc_clean: clean failed (error = %d)\n", kret);
+               /* 
+                * memory_object_destroy() is asynchronous
+                * with respect to vnode_pager_no_senders().
+                * wait for vnode_pager_no_senders() to clear
+                * VTERMINATE
+                */
+               vnode_lock(vp);
+               while (ISSET(vp->v_lflag, VNAMED_UBC)) {
+                       (void)msleep((caddr_t)&vp->v_lflag, &vp->v_lock,
+                                                PINOD, "ubc_destroy_named", 0);
+               }
+               vnode_unlock(vp);
        }
-
-       if (didhold)
-               ubc_rele(vp);
-
-       return ((kret == KERN_SUCCESS) ? 1 : 0);
+       return (1);
 }
 
+
 /*
- * Cause the file data in VM to be pushed out to the storage
- * currently valid pages are NOT invalidated
- * returns 1 on success, 0 on failure
+ * Find out whether a vnode is in use by UBC
+ * Returns 1 if file is in use by UBC, 0 if not
  */
 int
-ubc_pushdirty(struct vnode *vp)
+ubc_isinuse(struct vnode *vp, int busycount)
 {
-       off_t size;
-       struct ubc_info *uip;
-       void *object;
-       kern_return_t kret;
-       int didhold;
-
-#if DIAGNOSTIC
-       assert(vp);
-#endif
-
-       if (UBCINVALID(vp))
-               return(0);
-
-       if (!UBCINFOEXISTS(vp))
-               return(0);
-
-       didhold = ubc_hold(vp);
-       uip = vp->v_ubcinfo;
-       size = uip->ui_size;    /* call ubc_getsize() ??? */
-
-       object = _ubc_getobject(vp, UBC_NOREACTIVATE);
-       assert(object);
+       if ( !UBCINFOEXISTS(vp))
+               return (0);
+       return(ubc_isinuse_locked(vp, busycount, 0));
+}
 
-       /* 
-        * memory_object_lock_request() drops an object
-        * reference. gain a reference before calling it
-        */
-       ubc_getobjref(vp);
 
-       vp->v_flag &= ~VHASDIRTY;
-       vp->v_clen = 0;
+int
+ubc_isinuse_locked(struct vnode *vp, int busycount, int locked)
+{
+       int retval = 0;
 
-       /* Write the dirty data in the file and discard cached pages */
-       kret = memory_object_lock_request(object,
-                               (vm_object_offset_t)0,
-                               (memory_object_size_t)round_page_64(size),
-                               MEMORY_OBJECT_RETURN_DIRTY,FALSE,
-                               VM_PROT_NO_CHANGE,MACH_PORT_NULL);
 
-       if (kret != KERN_SUCCESS) {
-               printf("ubc_pushdirty: flush failed (error = %d)\n", kret);
-       }
+       if (!locked)
+               vnode_lock(vp);
 
-       if (didhold)
-               ubc_rele(vp);
+       if ((vp->v_usecount - vp->v_kusecount) > busycount)
+               retval = 1;
 
-       return ((kret == KERN_SUCCESS) ? 1 : 0);
+       if (!locked)
+               vnode_unlock(vp);
+       return (retval);
 }
 
+
 /*
- * Make sure the vm object does not vanish 
- * returns 1 if the hold count was incremented
- * returns 0 if the hold count was not incremented
- * This return value should be used to balance 
- * ubc_hold() and ubc_rele().
+ * MUST only be called by the VM
  */
-int
-ubc_hold(struct vnode *vp)
+__private_extern__ void
+ubc_unmap(struct vnode *vp)
 {
+       struct vfs_context context;
        struct ubc_info *uip;
-       void *object;
+       int     need_rele = 0;
 
-       if (UBCINVALID(vp))
-               return (0);
+       if (vnode_getwithref(vp))
+               return;
 
-       if (!UBCINFOEXISTS(vp)) {
-               /* nothing more to do for a dying vnode */
-               if  ((vp->v_flag & VXLOCK) || (vp->v_flag & VTERMINATE))
-                       return (0);
-               vp->v_ubcinfo = UBC_INFO_NULL;
-               ubc_info_init(vp);
-       }
-       uip = vp->v_ubcinfo;
-       object = _ubc_getobject(vp, UBC_NOREACTIVATE);
-       assert(object);
-
-       if (uip->ui_holdcnt++ == 0)
-                       ubc_getobjref(vp);
-       if (uip->ui_holdcnt < 0)
-               panic("ubc_hold: ui_holdcnt");
+       if (UBCINFOEXISTS(vp)) {
+               vnode_lock(vp);
 
-       return (1);
+               uip = vp->v_ubcinfo;
+               if (ISSET(uip->ui_flags, UI_ISMAPPED)) {
+                       CLR(uip->ui_flags, UI_ISMAPPED);
+                       need_rele = 1;
+               }
+               vnode_unlock(vp);
+               
+               if (need_rele) {
+                       context.vc_proc = current_proc();
+                       context.vc_ucred = kauth_cred_get();
+                       (void)VNOP_MNOMAP(vp, &context);
+
+                       vnode_rele(vp);
+               }
+       }
+       /*
+        * the drop of the vnode ref will cleanup
+        */
+       vnode_put(vp);
 }
 
-/* relese the reference on the vm object */
-void
-ubc_rele(struct vnode *vp)
+kern_return_t
+ubc_page_op(
+       struct vnode    *vp,
+       off_t           f_offset,
+       int             ops,
+       ppnum_t *phys_entryp,
+       int             *flagsp)
 {
-       struct ubc_info *uip;
-       void *object;
+       memory_object_control_t         control;
 
-       if (UBCINVALID(vp))
-               return;
+       control = ubc_getobject(vp, UBC_FLAGS_NONE);
+       if (control == MEMORY_OBJECT_CONTROL_NULL)
+               return KERN_INVALID_ARGUMENT;
 
-       if (!UBCINFOEXISTS(vp)) {
-               /* nothing more to do for a dying vnode */
-               if ((vp->v_flag & VXLOCK) || (vp->v_flag & VTERMINATE))
-                       return;
-               panic("ubc_rele: can not");
-       }
+       return (memory_object_page_op(control,
+                                     (memory_object_offset_t)f_offset,
+                                     ops,
+                                     phys_entryp,
+                                     flagsp));
+}
+                                     
+__private_extern__ kern_return_t
+ubc_page_op_with_control(
+       memory_object_control_t  control,
+       off_t                    f_offset,
+       int                      ops,
+       ppnum_t                  *phys_entryp,
+       int                      *flagsp)
+{
+       return (memory_object_page_op(control,
+                                     (memory_object_offset_t)f_offset,
+                                     ops,
+                                     phys_entryp,
+                                     flagsp));
+}
+                                     
+kern_return_t
+ubc_range_op(
+       struct vnode    *vp,
+       off_t           f_offset_beg,
+       off_t           f_offset_end,
+       int             ops,
+       int             *range)
+{
+       memory_object_control_t         control;
 
-       uip = vp->v_ubcinfo;
+       control = ubc_getobject(vp, UBC_FLAGS_NONE);
+       if (control == MEMORY_OBJECT_CONTROL_NULL)
+               return KERN_INVALID_ARGUMENT;
 
-       /* get the object before loosing to hold count */
-       object = _ubc_getobject(vp, UBC_NOREACTIVATE);
+       return (memory_object_range_op(control,
+                                     (memory_object_offset_t)f_offset_beg,
+                                     (memory_object_offset_t)f_offset_end,
+                                     ops,
+                                     range));
+}
+                                     
+kern_return_t
+ubc_create_upl(
+       struct vnode    *vp,
+       off_t                   f_offset,
+       long                    bufsize,
+       upl_t                   *uplp,
+       upl_page_info_t **plp,
+       int                             uplflags)
+{
+       memory_object_control_t         control;
+       int                             count;
+       int                             ubcflags;
+       kern_return_t                   kr;
+       
+       if (bufsize & 0xfff)
+               return KERN_INVALID_ARGUMENT;
 
-       if (uip->ui_holdcnt == 0)
-               panic("ubc_rele: ui_holdcnt");
+       if (uplflags & UPL_FOR_PAGEOUT) {
+               uplflags &= ~UPL_FOR_PAGEOUT;
+               ubcflags  =  UBC_FOR_PAGEOUT;
+       } else
+               ubcflags = UBC_FLAGS_NONE;
 
-       if (--uip->ui_holdcnt == 0) {
-               /* If the object is already dead do nothing */
-               if (object)
-               vm_object_deallocate(object);
-#if DIAGNOSTIC
-               else
-                       printf("ubc_rele: null object for %x", vp);
-#endif /* DIAGNOSTIC */
-       }
+       control = ubc_getobject(vp, ubcflags);
+       if (control == MEMORY_OBJECT_CONTROL_NULL)
+               return KERN_INVALID_ARGUMENT;
 
-       return;
+       if (uplflags & UPL_WILL_BE_DUMPED) {
+               uplflags &= ~UPL_WILL_BE_DUMPED;
+               uplflags |= (UPL_NO_SYNC|UPL_SET_INTERNAL);
+       } else
+               uplflags |= (UPL_NO_SYNC|UPL_CLEAN_IN_PLACE|UPL_SET_INTERNAL);
+       count = 0;
+       kr = memory_object_upl_request(control, f_offset, bufsize,
+                                                                  uplp, NULL, &count, uplflags);
+       if (plp != NULL)
+                       *plp = UPL_GET_INTERNAL_PAGE_LIST(*uplp);
+       return kr;
 }
+                                     
 
-/*
- * The vnode is mapped explicitly
- * Mark it so, and release the vm object reference gained in
- * ubc_info_init()
- */
-void
-ubc_map(struct vnode *vp)
+kern_return_t
+ubc_upl_map(
+       upl_t           upl,
+       vm_offset_t     *dst_addr)
 {
-       struct ubc_info *uip;
-       void *object;
-       ubc_lock(vp);
-#if DIAGNOSTIC
-       assert(vp);
-#endif
-
-       if (UBCINVALID(vp)) {
-               ubc_unlock(vp);
-               return;
-       }
-
-       if (!UBCINFOEXISTS(vp))
-               panic("ubc_map: can not");
-
-       uip = vp->v_ubcinfo;
+       return (vm_upl_map(kernel_map, upl, dst_addr));
+}
 
-       SET(uip->ui_flags, UI_WASMAPPED);
-       uip->ui_mapped = 1;
-       ubc_unlock(vp);
 
-#if 1
-       /*
-        * Do not release the ubc reference on the
-        * memory object right away. Let vnreclaim
-        * deal with that
-        */
-#else
-       /*
-        * Release the ubc reference. memory object cahe
-        * is responsible for caching this object now.
-        */
-       if (ISSET(uip->ui_flags, UI_HASOBJREF)) {
-               object = _ubc_getobject(vp, UBC_NOREACTIVATE);
-               assert(object);
-               CLR(uip->ui_flags, UI_HASOBJREF);
-               vm_object_deallocate(object);
-       }
-#endif
+kern_return_t
+ubc_upl_unmap(
+       upl_t   upl)
+{
+       return(vm_upl_unmap(kernel_map, upl));
+}
 
-       return;
+kern_return_t
+ubc_upl_commit(
+       upl_t                   upl)
+{
+       upl_page_info_t *pl;
+       kern_return_t   kr;
 
+       pl = UPL_GET_INTERNAL_PAGE_LIST(upl);
+       kr = upl_commit(upl, pl, MAX_UPL_TRANSFER);
+       upl_deallocate(upl);
+       return kr;
 }
 
-/*
- * Release the memory object reference on the vnode
- * only if it is not in use
- * Return 1 if the reference was released, 0 otherwise.
- */
-int
-ubc_release(struct vnode *vp)
+
+kern_return_t
+ubc_upl_commit_range(
+       upl_t                   upl,
+       vm_offset_t             offset,
+       vm_size_t               size,
+       int                             flags)
 {
-       struct ubc_info *uip;
-       void *object;
-#if DIAGNOSTIC
-       assert(vp);
-#endif
+       upl_page_info_t *pl;
+       boolean_t               empty;
+       kern_return_t   kr;
 
-       if (UBCINVALID(vp))
-               return (0);
+       if (flags & UPL_COMMIT_FREE_ON_EMPTY)
+               flags |= UPL_COMMIT_NOTIFY_EMPTY;
 
-       if (!UBCINFOEXISTS(vp))
-               panic("ubc_release: can not");
+       pl = UPL_GET_INTERNAL_PAGE_LIST(upl);
 
-       uip = vp->v_ubcinfo;
+       kr = upl_commit_range(upl, offset, size, flags,
+                                                 pl, MAX_UPL_TRANSFER, &empty);
 
-       /* can not release held vnodes */
-       if (uip->ui_holdcnt)
-               return (0);
+       if((flags & UPL_COMMIT_FREE_ON_EMPTY) && empty)
+               upl_deallocate(upl);
 
-       if (ISSET(uip->ui_flags, UI_HASOBJREF)) {
-               object = _ubc_getobject(vp, UBC_NOREACTIVATE);
-               assert(object);
-               CLR(uip->ui_flags, UI_HASOBJREF);
-               vm_object_deallocate(object);
-               return (1);
-       } else 
-               return (0);
+       return kr;
 }
-
-/*
- * Invalidate a range in the memory object that backs this
- * vnode. The offset is truncated to the page boundary and the
- * size is adjusted to include the last page in the range.
- */
-int
-ubc_invalidate(struct vnode *vp, off_t offset, size_t size)
+       
+kern_return_t
+ubc_upl_abort_range(
+       upl_t                   upl,
+       vm_offset_t             offset,
+       vm_size_t               size,
+       int                             abort_flags)
 {
-       struct ubc_info *uip;
-       void *object;
-       kern_return_t kret;
-       off_t toff;
-       size_t tsize;
-       int didhold;
+       kern_return_t   kr;
+       boolean_t               empty = FALSE;
 
-#if DIAGNOSTIC
-       assert(vp);
-#endif
+       if (abort_flags & UPL_ABORT_FREE_ON_EMPTY)
+               abort_flags |= UPL_ABORT_NOTIFY_EMPTY;
 
-       if (UBCINVALID(vp))
-               return;
+       kr = upl_abort_range(upl, offset, size, abort_flags, &empty);
 
-       if (!UBCINFOEXISTS(vp))
-               panic("ubc_invalidate: can not");
-
-       didhold = ubc_hold(vp);
-       toff = trunc_page_64(offset);
-       tsize = (size_t)(round_page_64(offset+size) - toff);
-       uip = vp->v_ubcinfo;
-       object = _ubc_getobject(vp, UBC_NOREACTIVATE);
-       assert(object);
-
-       /* 
-        * memory_object_lock_request() drops an object
-        * reference. gain a reference before calling it
-        */
-       ubc_getobjref(vp);
-
-       /* invalidate pages in the range requested */
-       kret = memory_object_lock_request(object,
-                               (vm_object_offset_t)toff,
-                               (memory_object_size_t)tsize,
-                               MEMORY_OBJECT_RETURN_NONE,
-                               (MEMORY_OBJECT_DATA_NO_CHANGE| MEMORY_OBJECT_DATA_FLUSH),
-                               VM_PROT_NO_CHANGE,MACH_PORT_NULL);
-       if (kret != KERN_SUCCESS)
-               printf("ubc_invalidate: invalidate failed (error = %d)\n", kret);
-
-       if (didhold)
-               ubc_rele(vp);
+       if((abort_flags & UPL_ABORT_FREE_ON_EMPTY) && empty)
+               upl_deallocate(upl);
 
-       return ((kret == KERN_SUCCESS) ? 1 : 0);
+       return kr;
 }
 
-/*
- * Find out whether a vnode is in use by UBC
- * Returns 1 if file is in use by UBC, 0 if not
- */
-int
-ubc_isinuse(struct vnode *vp, int tookref)
+kern_return_t
+ubc_upl_abort(
+       upl_t                   upl,
+       int                             abort_type)
 {
-       int busycount = tookref ? 2 : 1;
+       kern_return_t   kr;
 
-       if (!UBCINFOEXISTS(vp))
-               return(0);
-
-       if (vp->v_usecount > busycount)
-               return (1);
+       kr = upl_abort(upl, abort_type);
+       upl_deallocate(upl);
+       return kr;
+}
 
-       if ((vp->v_usecount == busycount)
-               && (vp->v_ubcinfo->ui_mapped == 1))
-               return(1);
-       else
-               return(0);
+upl_page_info_t *
+ubc_upl_pageinfo(
+       upl_t                   upl)
+{             
+       return (UPL_GET_INTERNAL_PAGE_LIST(upl));
 }
 
+/************* UBC APIS **************/
 
-/* -- UGLY HACK ALERT -- */
-/*
- * The backdoor routine to clear the UI_WASMAPPED bit.
- * MUST only be called by the VM
- *
- * Note that this routine is not under funnel. There are numerous
- * thing about the calling sequence that make this work on SMP.
- * Any code change in those paths can break this.
- *
- * This will be replaced soon.
- */
-void
-ubc_unmap(struct vnode *vp)
+int 
+UBCINFOMISSING(struct vnode * vp)
 {
-       struct ubc_info *uip;
-#if DIAGNOSTIC
-       assert(vp);
-#endif
-
-       if (UBCINVALID(vp)) {
-               return;
-       }
-
-       if (!UBCINFOEXISTS(vp))
-               panic("ubc_unmap: can not");
+       return((vp) && ((vp)->v_type == VREG) && ((vp)->v_ubcinfo == UBC_INFO_NULL));
+}
 
-       ubc_lock(vp);
-       uip = vp->v_ubcinfo;
+int 
+UBCINFORECLAIMED(struct vnode * vp)
+{
+       return((vp) && ((vp)->v_type == VREG) && ((vp)->v_ubcinfo == UBC_INFO_NULL));
+}
 
-       uip->ui_mapped = 0;
-       ubc_unlock(vp);
 
-       return;
+int 
+UBCINFOEXISTS(struct vnode * vp)
+{
+        return((vp) && ((vp)->v_type == VREG) && ((vp)->v_ubcinfo != UBC_INFO_NULL));
+}
+int 
+UBCISVALID(struct vnode * vp)
+{
+       return((vp) && ((vp)->v_type == VREG) && !((vp)->v_flag & VSYSTEM));
+}
+int 
+UBCINVALID(struct vnode * vp)
+{
+       return(((vp) == NULL) || ((vp) && ((vp)->v_type != VREG))
+               || ((vp) && ((vp)->v_flag & VSYSTEM)));
+}
+int 
+UBCINFOCHECK(const char * fun, struct vnode * vp)
+{
+       if ((vp) && ((vp)->v_type == VREG) &&
+               ((vp)->v_ubcinfo == UBC_INFO_NULL)) {
+               panic("%s: lost ubc_info", (fun));
+               return(1);
+       } else
+               return(0);
 }