Annotation of XNU/osfmk/vm/bsd_vm.c, revision 1.1

1.1     ! root        1: /*
        !             2:  * Copyright (c) 2000 Apple Computer, Inc. All rights reserved.
        !             3:  *
        !             4:  * @APPLE_LICENSE_HEADER_START@
        !             5:  *
        !             6:  * The contents of this file constitute Original Code as defined in and
        !             7:  * are subject to the Apple Public Source License Version 1.1 (the
        !             8:  * "License").  You may not use this file except in compliance with the
        !             9:  * License.  Please obtain a copy of the License at
        !            10:  * http://www.apple.com/publicsource and read it before using this file.
        !            11:  *
        !            12:  * This Original Code and all software distributed under the License are
        !            13:  * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER
        !            14:  * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
        !            15:  * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
        !            16:  * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT.  Please see the
        !            17:  * License for the specific language governing rights and limitations
        !            18:  * under the License.
        !            19:  *
        !            20:  * @APPLE_LICENSE_HEADER_END@
        !            21:  */
        !            22: 
        !            23: #include <sys/errno.h>
        !            24: #include <kern/host.h>
        !            25: #include <mach/mach_types.h>
        !            26: #include <vm/vm_map.h>
        !            27: #include <vm/vm_kern.h>
        !            28: #include <vm/vm_pageout.h>
        !            29: #include <mach/kern_return.h>
        !            30: #include <mach/memory_object_types.h>
        !            31: #include <mach/port.h>
        !            32: #include <mach/policy.h>
        !            33: #include <ipc/ipc_port.h>
        !            34: #include <ipc/ipc_space.h>
        !            35: #include <kern/thread.h>
        !            36: #include <vm/vm_pageout.h>
        !            37: 
        !            38: 
        !            39: /* BSD VM COMPONENT INTERFACES */
        !            40: int
        !            41: get_map_nentries(
        !            42:        vm_map_t);
        !            43: 
        !            44: vm_offset_t
        !            45: get_map_start(
        !            46:        vm_map_t);
        !            47: 
        !            48: vm_offset_t
        !            49: get_map_end(
        !            50:        vm_map_t);
        !            51: 
        !            52: void
        !            53: map_ref_fixup(
        !            54:        vm_map_t,
        !            55:        vm_map_t);
        !            56: 
        !            57: /*
        !            58:  * 
        !            59:  */
        !            60: int
        !            61: get_map_nentries(
        !            62:        vm_map_t map)
        !            63: {
        !            64:        return(map->hdr.nentries);
        !            65: }
        !            66: 
        !            67: /*
        !            68:  * 
        !            69:  */
        !            70: vm_offset_t
        !            71: get_map_start(
        !            72:        vm_map_t map)
        !            73: {
        !            74:        return(vm_map_first_entry(map)->vme_start);
        !            75: }
        !            76: 
        !            77: /*
        !            78:  * 
        !            79:  */
        !            80: vm_offset_t
        !            81: get_map_end(
        !            82:        vm_map_t map)
        !            83: {
        !            84:        return(vm_map_last_entry(map)->vme_end);
        !            85: }
        !            86: 
        !            87: /*
        !            88:  * TODO: TO BE REMOVED 
        !            89:  */
        !            90: void
        !            91: map_ref_fixup(
        !            92:        vm_map_t old_map,
        !            93:        vm_map_t new_map)
        !            94: {
        !            95:        if (old_map->ref_count >1)
        !            96:                old_map->ref_count = 1;
        !            97:        new_map->ref_count =2;
        !            98: }
        !            99: 
        !           100: /* 
        !           101:  * BSD VNODE PAGER 
        !           102:  */
        !           103: 
        !           104: /* until component support available */
        !           105: int    vnode_pager_workaround;
        !           106: 
        !           107: typedef int vnode_port_t;
        !           108: 
        !           109: typedef struct vnode_pager {
        !           110:        ipc_port_t pager;                       /* pager */
        !           111:        ipc_port_t pager_handle;        /* pager handle */
        !           112:        ipc_port_t vm_obj_handle;       /* memory object's control handle */
        !           113:        vnode_port_t vnode_handle;      /* vnode handle */
        !           114: } *vnode_pager_t;
        !           115: 
        !           116: typedef struct vnode_port_entry {
        !           117:        queue_chain_t   links;          /* queue links */
        !           118:        ipc_port_t      name;                   /* port name */
        !           119:        vnode_pager_t   pager_rec;      /* pager record */
        !           120: } *vnode_port_entry_t;
        !           121: 
        !           122: 
        !           123: #define         VNODE_PORT_HASH_COUNT   127
        !           124: #define         vnode_port_hash(name_port) \
        !           125:                         (((int)(name_port) & 0xffffff) % VNODE_PORT_HASH_COUNT)
        !           126: 
        !           127: queue_head_t   vnode_port_hashtable[VNODE_PORT_HASH_COUNT];
        !           128: zone_t                 vnode_port_hash_zone;
        !           129: decl_simple_lock_data(,vnode_port_hash_lock)
        !           130: 
        !           131: 
        !           132: ipc_port_t
        !           133: trigger_name_to_port(
        !           134:        mach_port_t);
        !           135: 
        !           136: void 
        !           137: vnode_pager_bootstrap(
        !           138:        void);
        !           139: 
        !           140: void
        !           141: vnode_pager_alloc_map(
        !           142:        void);
        !           143: 
        !           144: ipc_port_t
        !           145: vnode_pager_setup(
        !           146:        vnode_port_t,
        !           147:        ipc_port_t);
        !           148: 
        !           149: ipc_port_t
        !           150: vnode_pager_lookup(
        !           151:        vnode_port_t,
        !           152:        ipc_port_t);
        !           153: 
        !           154: kern_return_t
        !           155: vnode_pager_init(
        !           156:        ipc_port_t, 
        !           157:        ipc_port_t, 
        !           158:        vm_size_t);
        !           159: 
        !           160: kern_return_t
        !           161: vnode_pager_data_request( 
        !           162:        ipc_port_t, 
        !           163:        ipc_port_t,
        !           164:        vm_offset_t, 
        !           165:        vm_size_t, 
        !           166:        vm_prot_t);
        !           167: 
        !           168: kern_return_t
        !           169: vnode_pager_data_return(
        !           170:        ipc_port_t,
        !           171:        ipc_port_t,
        !           172:        vm_offset_t,
        !           173:        pointer_t,
        !           174:        vm_size_t,
        !           175:        boolean_t,
        !           176:        boolean_t);
        !           177: 
        !           178: void
        !           179: vnode_pager_no_senders(
        !           180:        ipc_port_t,
        !           181:        mach_port_mscount_t);
        !           182: 
        !           183: kern_return_t
        !           184: vnode_pager_terminate(
        !           185:        ipc_port_t,
        !           186:        ipc_port_t);
        !           187: 
        !           188: kern_return_t
        !           189: vnode_pager_cluster_read(
        !           190:        vnode_pager_t, 
        !           191:        vm_offset_t, 
        !           192:        vm_size_t,
        !           193:        vm_object_t);
        !           194: 
        !           195: void
        !           196: vnode_pager_cluster_write(
        !           197:        vnode_pager_t,
        !           198:        vm_offset_t,
        !           199:        vm_size_t,
        !           200:        vm_object_t);
        !           201: 
        !           202: kern_return_t
        !           203: memory_object_change_attributes(
        !           204:        vm_object_t,
        !           205:        memory_object_flavor_t,
        !           206:        memory_object_info_t,
        !           207:        mach_msg_type_number_t,
        !           208:        ipc_port_t,
        !           209:        mach_msg_type_name_t);
        !           210: 
        !           211: vnode_pager_t
        !           212: vnode_object_create(
        !           213:        vnode_port_t    vp);
        !           214: 
        !           215: void
        !           216: vnode_port_hash_init(void);
        !           217: 
        !           218: void
        !           219: vnode_port_hash_insert(
        !           220:        ipc_port_t,   
        !           221:        vnode_pager_t);
        !           222: 
        !           223: vnode_pager_t
        !           224: vnode_port_hash_lookup(
        !           225:        ipc_port_t);
        !           226: 
        !           227: void
        !           228: vnode_port_hash_delete(
        !           229:        ipc_port_t);
        !           230: 
        !           231: void
        !           232: vnode_pager_release_from_cache(
        !           233:        int     *cnt);
        !           234: 
        !           235: void
        !           236: vnode_pager_create( 
        !           237:        vnode_port_t,
        !           238:        ipc_port_t);
        !           239: 
        !           240: int
        !           241: vnode_pageout(
        !           242:        vnode_port_t, 
        !           243:        vm_offset_t, 
        !           244:        vm_offset_t, 
        !           245:        int, 
        !           246:        int *);
        !           247: 
        !           248: int    
        !           249: vnode_pagein(
        !           250:        vnode_port_t, 
        !           251:        vm_offset_t, 
        !           252:        vm_offset_t, 
        !           253:        int, 
        !           254:        int *);
        !           255: 
        !           256: zone_t vnode_pager_zone;
        !           257: 
        !           258: 
        !           259: #define        VNODE_PAGER_NULL        ((vnode_pager_t) 0)
        !           260: 
        !           261: /* TODO: Should be set dynamically by vnode_pager_init() */
        !           262: #define CLUSTER_SHIFT  1
        !           263: 
        !           264: /* TODO: Should be set dynamically by vnode_pager_bootstrap() */
        !           265: #define        MAX_VNODE               10000
        !           266: 
        !           267: 
        !           268: #if DEBUG
        !           269: int pagerdebug=0;
        !           270: 
        !           271: #define PAGER_ALL              0xffffffff
        !           272: #define        PAGER_INIT              0x00000001
        !           273: #define        PAGER_PAGEIN    0x00000002
        !           274: 
        !           275: #define PAGER_DEBUG(LEVEL, A) {if ((pagerdebug & LEVEL)==LEVEL){printf A;}}
        !           276: #else
        !           277: #define PAGER_DEBUG(LEVEL, A)
        !           278: #endif
        !           279: 
        !           280: /*
        !           281:  *     Routine:        macx_triggers
        !           282:  *     Function:
        !           283:  *             Syscall interface to set the call backs for low and
        !           284:  *             high water marks.
        !           285:  */
        !           286: int
        !           287: macx_triggers(
        !           288:        int     hi_water,
        !           289:        int     low_water,
        !           290:        int     flags,
        !           291:        mach_port_t     trigger_name)
        !           292: {
        !           293:        kern_return_t kr;
        !           294:        ipc_port_t              default_pager_port = MACH_PORT_NULL;
        !           295:        ipc_port_t              trigger_port;
        !           296: 
        !           297:        kr = host_default_memory_manager(realhost.host_priv_self, 
        !           298:                                        &default_pager_port, 0);
        !           299:        if(kr != KERN_SUCCESS) {
        !           300:                return EINVAL;
        !           301:        }
        !           302:        trigger_port = trigger_name_to_port(trigger_name);
        !           303:        if(trigger_port == NULL) {
        !           304:                return EINVAL;
        !           305:        }
        !           306:         /* trigger_port is locked and active */
        !           307:         ip_unlock(trigger_port);
        !           308:        default_pager_triggers(default_pager_port, 
        !           309:                        hi_water, low_water, flags, trigger_port);
        !           310:        ipc_port_make_send(trigger_port); 
        !           311: 
        !           312:        /*
        !           313:         * Set thread scheduling priority and policy for the current thread
        !           314:         * it is assumed for the time being that the thread setting the alert
        !           315:         * is the same one which will be servicing it. 
        !           316:         */
        !           317:        {
        !           318:                struct policy_timeshare_base     fifo_base;
        !           319:                struct policy_timeshare_limit fifo_limit;
        !           320:                policy_base_t   base;
        !           321:                processor_set_t pset;
        !           322:                policy_limit_t  limit;
        !           323: 
        !           324:                pset = (current_thread())->processor_set;  
        !           325:                base = (policy_base_t) &fifo_base;
        !           326:                limit = (policy_limit_t) &fifo_limit;
        !           327:                fifo_base.base_priority = BASEPRI_KERNEL;
        !           328:                fifo_limit.max_priority = BASEPRI_KERNEL;
        !           329:                thread_set_policy((current_thread())->top_act, pset, POLICY_FIFO, base, POLICY_TIMESHARE_BASE_COUNT, limit, POLICY_TIMESHARE_LIMIT_COUNT);
        !           330:        }
        !           331:  
        !           332:        current_thread()->vm_privilege = TRUE;
        !           333: }
        !           334: 
        !           335: /*
        !           336:  *
        !           337:  */
        !           338: ipc_port_t
        !           339: trigger_name_to_port(
        !           340:        mach_port_t     trigger_name)
        !           341: {
        !           342:        ipc_port_t      trigger_port;
        !           343:        ipc_space_t     space;
        !           344: 
        !           345:        if (trigger_name == 0)
        !           346:                return (NULL);
        !           347: 
        !           348:        space  = current_space();
        !           349:        if(ipc_port_translate_receive(space, (mach_port_name_t)trigger_name, 
        !           350:                                                &trigger_port) != KERN_SUCCESS)
        !           351:                return (NULL);
        !           352:        return trigger_port;
        !           353: }
        !           354: 
        !           355: /*
        !           356:  *
        !           357:  */
        !           358: void
        !           359: vnode_pager_bootstrap(void)
        !           360: {
        !           361:        register vm_size_t      size;
        !           362: 
        !           363:        size = (vm_size_t) sizeof(struct vnode_pager);
        !           364:        vnode_pager_zone = zinit(size, (vm_size_t) MAX_VNODE*size,
        !           365:                                PAGE_SIZE, "vnode pager structures");
        !           366:        vnode_port_hash_init();
        !           367: 
        !           368:        return;
        !           369: }
        !           370: 
        !           371: /*
        !           372:  *
        !           373:  */
        !           374: ipc_port_t
        !           375: vnode_pager_setup(
        !           376:        vnode_port_t    vp,
        !           377:        ipc_port_t      pager)
        !           378: {
        !           379:        vnode_pager_t   vnode_object;
        !           380:        kern_return_t   kr;
        !           381:        ipc_port_t      previous;
        !           382: 
        !           383:        if (pager &&
        !           384:            (vnode_object = vnode_port_hash_lookup(pager))) {
        !           385:                if (vnode_object->vnode_handle == vp) 
        !           386:                        return(pager);
        !           387:        }
        !           388: 
        !           389:        vnode_object = vnode_object_create(vp);
        !           390:        if (vnode_object == VNODE_PAGER_NULL)
        !           391:                panic("vnode_pager_setup: vnode_object_create() failed");
        !           392: 
        !           393:        vnode_object->pager = ipc_port_alloc_kernel();
        !           394:        assert (vnode_object->pager != IP_NULL);
        !           395:        pager_mux_hash_insert(vnode_object->pager, 
        !           396:                        (rpc_subsystem_t)&vnode_pager_workaround);
        !           397: 
        !           398:        vnode_object->pager_handle = ipc_port_make_send(vnode_object->pager);
        !           399: 
        !           400:        vnode_port_hash_insert(vnode_object->pager_handle, vnode_object);
        !           401: 
        !           402:        ipc_port_make_sonce(vnode_object->pager);
        !           403:        ip_lock(vnode_object->pager);   /* unlocked in nsrequest below */
        !           404:        ipc_port_nsrequest(vnode_object->pager, 1, vnode_object->pager, &previous);
        !           405: 
        !           406:        PAGER_DEBUG(PAGER_INIT, ("vnode_pager_setup: vp %x pager %x vnode_pager %x\n", vp, vnode_object->pager_handle, vnode_object));
        !           407: 
        !           408:        vnode_pager_create( vp, vnode_object->pager_handle);
        !           409:        return(vnode_object->pager_handle);
        !           410: }
        !           411: 
        !           412: /*
        !           413:  *
        !           414:  */
        !           415: ipc_port_t
        !           416: vnode_pager_lookup(
        !           417:        vnode_port_t    vp,
        !           418:        ipc_port_t      pager)
        !           419: {
        !           420:        vnode_pager_t   vnode_object;
        !           421:        kern_return_t   kr;
        !           422: 
        !           423:        if (pager &&
        !           424:            (vnode_object = vnode_port_hash_lookup(pager))) {
        !           425:                if (vnode_object->vnode_handle == vp) 
        !           426:                        return(vnode_object->vm_obj_handle);
        !           427:                else 
        !           428:                        return NULL;
        !           429:        }
        !           430:        else 
        !           431:                return NULL;
        !           432: }
        !           433: 
        !           434: /*
        !           435:  *
        !           436:  */
        !           437: kern_return_t
        !           438: vnode_pager_init(ipc_port_t pager, 
        !           439:                ipc_port_t pager_request, 
        !           440:                vm_size_t pg_size)
        !           441: {
        !           442:        vnode_pager_t   vnode_object;
        !           443:        kern_return_t   kr;
        !           444:        memory_object_attr_info_data_t  attributes;
        !           445:        vm_object_t     vm_object;
        !           446: 
        !           447: 
        !           448:        PAGER_DEBUG(PAGER_ALL, ("vnode_pager_init: %x, %x, %x\n", pager, pager_request, pg_size));
        !           449: 
        !           450:        vnode_object = vnode_port_hash_lookup(pager);
        !           451:        if (vnode_object == VNODE_PAGER_NULL)
        !           452:                panic("vnode_pager_init: lookup failed");
        !           453: 
        !           454:        vnode_object->vm_obj_handle = pager_request;
        !           455: 
        !           456:        vm_object = vm_object_lookup(pager_request);
        !           457: 
        !           458:        if (vm_object == VM_OBJECT_NULL)
        !           459:                panic("vnode_pager_init: vm_object_lookup() failed");
        !           460: 
        !           461:        attributes.copy_strategy = MEMORY_OBJECT_COPY_DELAY;
        !           462:        attributes.cluster_size = (1 << (CLUSTER_SHIFT + PAGE_SHIFT));
        !           463:        attributes.may_cache_object = TRUE;
        !           464:        attributes.temporary = TRUE;
        !           465: 
        !           466:        kr = memory_object_change_attributes(
        !           467:                                        vm_object,
        !           468:                                        MEMORY_OBJECT_ATTRIBUTE_INFO,
        !           469:                                        (memory_object_info_t) &attributes,
        !           470:                                        MEMORY_OBJECT_ATTR_INFO_COUNT,
        !           471:                                        MACH_PORT_NULL, 0);
        !           472:        if (kr != KERN_SUCCESS)
        !           473:                panic("vnode_pager_init: memory_object_change_attributes() failed");
        !           474: 
        !           475:        return(KERN_SUCCESS);
        !           476: }
        !           477: 
        !           478: /*
        !           479:  *
        !           480:  */
        !           481: kern_return_t
        !           482: vnode_pager_data_return(
        !           483:         ipc_port_t     mem_obj,
        !           484:         ipc_port_t     control_port,
        !           485:         vm_offset_t    offset,
        !           486:         pointer_t      addr,
        !           487:         vm_size_t      data_cnt,
        !           488:         boolean_t      dirty,
        !           489:         boolean_t      kernel_copy)  
        !           490: {
        !           491:        register vnode_pager_t  vnode_object;
        !           492: 
        !           493:        vnode_object = vnode_port_hash_lookup(mem_obj);
        !           494:        if (vnode_object == VNODE_PAGER_NULL)
        !           495:                panic("vnode_pager_data_return: lookup failed");
        !           496: 
        !           497:        vnode_pager_cluster_write(vnode_object, offset, data_cnt, (vm_object_t)control_port->ip_kobject);
        !           498: 
        !           499:        return KERN_SUCCESS;
        !           500: }
        !           501: 
        !           502: /*
        !           503:  *
        !           504:  */
        !           505: kern_return_t  
        !           506: vnode_pager_data_request(
        !           507:        ipc_port_t      mem_obj,
        !           508:        ipc_port_t      mem_obj_control,
        !           509:        vm_offset_t     offset,
        !           510:        vm_size_t       length,
        !           511:        vm_prot_t       protection_required)
        !           512: {
        !           513:        register vnode_pager_t  vnode_object;
        !           514: 
        !           515:        PAGER_DEBUG(PAGER_ALL, ("vnode_pager_data_request: %x, %x, %x, %x, %x\n", mem_obj, mem_obj_control, offset, length, protection_required));
        !           516: 
        !           517:        vnode_object = vnode_port_hash_lookup(mem_obj);
        !           518: 
        !           519:        PAGER_DEBUG(PAGER_PAGEIN, ("vnode_pager_data_request: %x, %x, %x, %x, %x, vnode_object %x\n", mem_obj, mem_obj_control, offset, length, protection_required, vnode_object));
        !           520:                
        !           521:        if (vnode_object == VNODE_PAGER_NULL)
        !           522:                panic("vnode_pager_data_request: lookup failed");
        !           523: 
        !           524:        vnode_pager_cluster_read(vnode_object, offset, length, (vm_object_t)mem_obj_control->ip_kobject);
        !           525: 
        !           526:        return KERN_SUCCESS;
        !           527: }
        !           528: 
        !           529: /*
        !           530:  *
        !           531:  */
        !           532: void
        !           533: vnode_pager_no_senders(
        !           534:        ipc_port_t      mem_obj,
        !           535:        mach_port_mscount_t mscount)
        !           536: {
        !           537:        register vnode_pager_t  vnode_object;
        !           538:        boolean_t funnel_state;
        !           539: 
        !           540:        PAGER_DEBUG(PAGER_ALL, ("vnode_pager_nosenders: %x, %x\n", mem_obj, mscount));
        !           541: 
        !           542:        vnode_object = vnode_port_hash_lookup(mem_obj);
        !           543:        if (vnode_object == VNODE_PAGER_NULL)
        !           544:                panic("vnode_pager_no_senders: lookup failed");
        !           545: 
        !           546:        assert(vnode_object->pager_handle == mem_obj);
        !           547: 
        !           548:        pager_mux_hash_delete((ipc_port_t) vnode_object->pager_handle);
        !           549:        ipc_port_dealloc_kernel(vnode_object->pager);
        !           550:        vnode_port_hash_delete(vnode_object->pager_handle);
        !           551:        if (vnode_object->vnode_handle != (vnode_port_t) NULL) {
        !           552:                funnel_state = thread_set_funneled(TRUE); 
        !           553:                vrele(vnode_object->vnode_handle);
        !           554:                (void) thread_set_funneled(funnel_state);
        !           555:        }
        !           556:        zfree(vnode_pager_zone, (vm_offset_t) vnode_object);
        !           557: 
        !           558:        return;
        !           559: }
        !           560: 
        !           561: /*
        !           562:  *
        !           563:  */
        !           564: kern_return_t
        !           565: vnode_pager_terminate(
        !           566:        ipc_port_t      mem_obj,
        !           567:        ipc_port_t      mem_obj_control)
        !           568: {
        !           569:        register vnode_pager_t  vnode_object;
        !           570: 
        !           571:        PAGER_DEBUG(PAGER_ALL, ("vnode_pager_terminate: %x, %x\n", mem_obj, mem_obj_control));
        !           572: 
        !           573:        vnode_object = vnode_port_hash_lookup(mem_obj);
        !           574:        if (vnode_object == VNODE_PAGER_NULL)
        !           575:                panic("vnode_pager_terminate: lookup failed");
        !           576: 
        !           577:        assert(vnode_object->pager_handle == mem_obj);
        !           578: 
        !           579:        /* release extra send right created by the fact that the caller */
        !           580:        /* of vnode_pager_setup does not establish a mapping between a  */
        !           581:        /* cache object and the mem_obj (AMO).  When a subsequent vm_map */
        !           582:        /* is done, vm_map will bump the send right count */
        !           583:        ipc_port_release_send(mem_obj);
        !           584: 
        !           585:        /* release a send right because terminate is called directly and */
        !           586:        /* not through IPC, the right won't disappear quietly */
        !           587:        ipc_port_release_send(mem_obj);
        !           588: 
        !           589:        ipc_port_dealloc_kernel(mem_obj_control);
        !           590: 
        !           591:        return(KERN_SUCCESS);
        !           592: }
        !           593: 
        !           594: /*
        !           595:  *
        !           596:  */
        !           597: kern_return_t
        !           598: vnode_pager_synchronize(
        !           599:        ipc_port_t      pager,
        !           600:        ipc_port_t      pager_request,
        !           601:        vm_offset_t     offset,
        !           602:        vm_offset_t     length,
        !           603:        vm_sync_t       sync_flags)
        !           604: {
        !           605:        memory_object_synchronize_completed(vm_object_lookup(pager_request), offset, length);
        !           606: 
        !           607:        return (KERN_SUCCESS);
        !           608: }
        !           609: 
        !           610: /*
        !           611:  *
        !           612:  */
        !           613: void
        !           614: vnode_pager_cluster_write(
        !           615:        vnode_pager_t   vnode_object,
        !           616:        vm_offset_t     offset,
        !           617:        vm_size_t       cnt,
        !           618:        vm_object_t     object)
        !           619: {
        !           620:        vm_offset_t     data;
        !           621:        upl_t           page_list;
        !           622:        int             error = 0;
        !           623:        int             size;
        !           624: 
        !           625:        upl_system_list_request(object, offset, 
        !           626:                        cnt, cnt, &page_list, NULL, 0,
        !           627:                        (UPL_CLEAN_IN_PLACE | UPL_NO_SYNC | UPL_COPYOUT_FROM));
        !           628:        upl_map(kernel_map, page_list, &data);
        !           629:        
        !           630:        error = vnode_pageout(
        !           631:                        vnode_object->vnode_handle, data, offset, cnt, NULL);
        !           632: 
        !           633:        upl_un_map(kernel_map, page_list);
        !           634:        if (error == 0) {
        !           635:                upl_commit(page_list, NULL);    
        !           636:        } else {
        !           637:                upl_abort(page_list, 0);
        !           638:        } 
        !           639: 
        !           640:        return;
        !           641: }
        !           642: 
        !           643: 
        !           644: /*
        !           645:  *
        !           646:  */
        !           647: kern_return_t
        !           648: vnode_pager_cluster_read(
        !           649:        vnode_pager_t   vnode_object,
        !           650:        vm_offset_t     offset,
        !           651:        vm_size_t       cnt,
        !           652:        vm_object_t     object)
        !           653: {
        !           654:        vm_offset_t     buffer;
        !           655:        int             error = 0;
        !           656:        int             local_error = 0;
        !           657:        int             kret;
        !           658:        int             size;
        !           659:        upl_t           page_list;
        !           660:        vm_offset_t     base, orig_offset;
        !           661:        kern_return_t   kr;
        !           662: 
        !           663:        size = PAGE_SIZE;
        !           664:        orig_offset = offset;
        !           665:        base = offset;
        !           666: 
        !           667:        kr = upl_system_list_request(object, offset, 
        !           668:                                        cnt, cnt, &page_list, NULL, 0,
        !           669:                                        UPL_CLEAN_IN_PLACE |  UPL_NO_SYNC);
        !           670:        if(kr != KERN_SUCCESS) {
        !           671:                panic("VNODE_PAGER_CLUSTER_READ: upl_system_list_request failed");
        !           672:        }
        !           673:        kr = upl_map(kernel_map, page_list, &buffer);
        !           674:        if(kr != KERN_SUCCESS) {
        !           675:                upl_abort(page_list, UPL_ABORT_RESTART);
        !           676:                return KERN_SUCCESS;
        !           677:        }
        !           678: 
        !           679:        while (cnt) {
        !           680: 
        !           681:                kret = vnode_pagein(vnode_object->vnode_handle, buffer, offset, size, &local_error);
        !           682: 
        !           683:                PAGER_DEBUG(PAGER_PAGEIN, ("vnode_pagein ret: vp %x, buf %x buf[0] %x\n", vnode_object->vnode_handle, buffer, *((int *)buffer)));
        !           684: 
        !           685:                if (local_error != 0) {
        !           686:                        error = local_error;
        !           687:                        local_error = 0;
        !           688:                        if(offset > base) {
        !           689:                                upl_un_map(kernel_map, page_list);
        !           690:                                upl_commit_range(page_list, base - orig_offset, 
        !           691:                                                offset - base, FALSE, NULL);
        !           692:                                upl_map(kernel_map, page_list, &buffer);
        !           693:                        }
        !           694:                        base = offset+size;
        !           695:                }
        !           696: 
        !           697:                cnt -= size;
        !           698:                offset += size;
        !           699:        } 
        !           700: 
        !           701:        if(error != 0) {
        !           702:                upl_un_map(kernel_map, page_list);
        !           703:                if(offset > base) {
        !           704:                        upl_commit_range(page_list, base - orig_offset, 
        !           705:                                                offset - base, FALSE, NULL);
        !           706:                }
        !           707:                upl_abort(page_list, UPL_ABORT_ERROR);
        !           708:                return(KERN_FAILURE);
        !           709:        }
        !           710:        upl_un_map(kernel_map, page_list);
        !           711:        upl_commit(page_list, NULL);    
        !           712: 
        !           713:        return(KERN_SUCCESS);
        !           714: }
        !           715: 
        !           716: 
        !           717: /*
        !           718:  *
        !           719:  */
        !           720: void
        !           721: vnode_pager_release_from_cache(
        !           722:                int     *cnt)
        !           723: {
        !           724:        memory_object_free_from_cache(
        !           725:                        &realhost, (int)&vnode_pager_workaround, cnt);
        !           726: }
        !           727: 
        !           728: /*
        !           729:  *
        !           730:  */
        !           731: vnode_pager_t
        !           732: vnode_object_create(
        !           733:         vnode_port_t   vp)
        !           734: {
        !           735:        register vnode_pager_t  vnode_object;
        !           736: 
        !           737:        vnode_object = (struct vnode_pager *) zalloc(vnode_pager_zone);
        !           738:        if (vnode_object == VNODE_PAGER_NULL)
        !           739:                return(VNODE_PAGER_NULL);
        !           740:        vnode_object->pager_handle = IP_NULL;
        !           741:        vnode_object->vm_obj_handle = IP_NULL;
        !           742:        vnode_object->vnode_handle = vp;
        !           743: 
        !           744:        return(vnode_object);
        !           745: }
        !           746: 
        !           747: /*
        !           748:  *
        !           749:  */
        !           750: void
        !           751: vnode_port_hash_init(void)
        !           752: {
        !           753:        register vm_size_t      size;
        !           754:        register int            i;
        !           755: 
        !           756: 
        !           757:        size = (vm_size_t) sizeof(struct vnode_port_entry);
        !           758: 
        !           759:        vnode_port_hash_zone = zinit(size,
        !           760:                                     (vm_size_t) MAX_VNODE * size,
        !           761:                                     PAGE_SIZE, "vnode_pager port hash");
        !           762: 
        !           763:        for (i = 0; i < VNODE_PORT_HASH_COUNT; i++) 
        !           764:                queue_init(&vnode_port_hashtable[i]);
        !           765: 
        !           766:        simple_lock_init(&vnode_port_hash_lock,ETAP_NO_TRACE);
        !           767: }
        !           768: 
        !           769: /*
        !           770:  *
        !           771:  */
        !           772: void
        !           773: vnode_port_hash_insert(
        !           774:        ipc_port_t              name_port,
        !           775:        vnode_pager_t   rec)
        !           776: {
        !           777:        register vnode_port_entry_t     new_entry;
        !           778: 
        !           779:        new_entry = (vnode_port_entry_t) zalloc(vnode_port_hash_zone);
        !           780:        /*
        !           781:         * TODO: Delete the following check once MAX_VNODE is removed 
        !           782:         */
        !           783:        if (!new_entry)
        !           784:                panic("vnode_port_hash_insert: no space");
        !           785:        new_entry->name = name_port;
        !           786:        new_entry->pager_rec = rec;
        !           787: 
        !           788:        simple_lock(&vnode_port_hash_lock);
        !           789:        queue_enter(&vnode_port_hashtable[vnode_port_hash(name_port)],
        !           790:                        new_entry, vnode_port_entry_t, links);
        !           791:        simple_unlock(&vnode_port_hash_lock);
        !           792: }
        !           793: 
        !           794: /*
        !           795:  *
        !           796:  */
        !           797: vnode_pager_t
        !           798: vnode_port_hash_lookup(
        !           799:        ipc_port_t       name_port)
        !           800: {
        !           801:        register queue_t                bucket;
        !           802:        register vnode_port_entry_t     entry;
        !           803:        vnode_pager_t                   rec;
        !           804: 
        !           805:        bucket = (queue_t) &vnode_port_hashtable[vnode_port_hash(name_port)];
        !           806: 
        !           807:        simple_lock(&vnode_port_hash_lock);
        !           808:        entry = (vnode_port_entry_t) queue_first(bucket);
        !           809:        while (!queue_end(bucket,&entry->links)) {
        !           810:                if (entry->name == name_port) {
        !           811:                        rec = entry->pager_rec;
        !           812:                        simple_unlock(&vnode_port_hash_lock);
        !           813:                        return(rec);
        !           814:                }
        !           815:                entry = (vnode_port_entry_t)queue_next(&entry->links);
        !           816:        }
        !           817:        simple_unlock(&vnode_port_hash_lock);
        !           818:        return(VNODE_PAGER_NULL);
        !           819: }
        !           820: 
        !           821: /*
        !           822:  *
        !           823:  */
        !           824: void
        !           825: vnode_port_hash_delete(
        !           826:        ipc_port_t name_port)
        !           827: {
        !           828:        register queue_t bucket;
        !           829:        register vnode_port_entry_t entry;
        !           830: 
        !           831:        bucket = (queue_t) &vnode_port_hashtable[vnode_port_hash(name_port)];
        !           832: 
        !           833:        simple_lock(&vnode_port_hash_lock);
        !           834:        entry = (vnode_port_entry_t) queue_first(bucket);
        !           835:        while (!queue_end(bucket,&entry->links)) {
        !           836:                if (entry->name == name_port) {
        !           837:                        queue_remove(bucket, entry, vnode_port_entry_t,links);
        !           838:                        simple_unlock(&vnode_port_hash_lock);
        !           839:                        zfree(vnode_port_hash_zone, (vm_offset_t) entry);
        !           840:                        return;
        !           841:                }
        !           842:                entry = (vnode_port_entry_t)queue_next(&entry->links);
        !           843:        }
        !           844:        simple_unlock(&vnode_port_hash_lock);
        !           845: }

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.