Annotation of XNU/osfmk/vm/bsd_vm.c, revision 1.1.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.