- /*
- * Skip clustered pagein if it is globally disabled
- * or random page reference behavior is expected
- * for the address range containing the faulting
- * address or the object paging block size is
- * equal to the page size.
- */
- if (!vm_allow_clustered_pagein ||
- behavior == VM_BEHAVIOR_RANDOM ||
- cluster_size == PAGE_SIZE) {
- cluster_start = trunc_page_64(cluster_start);
- goto no_clustering;
- }
-
- assert(offset >= lo_offset);
- assert(offset < hi_offset);
- assert(ALIGNED(object->paging_offset));
- assert(cluster_size >= PAGE_SIZE);
-
-#if TRACEFAULTPAGE
- dbgTrace(0xBEEF0011, (unsigned int) m, (unsigned int) 0); /* (TEST/DEBUG) */
-#endif
- /*
- * Decide whether to scan ahead or behind for
- * additional pages contiguous to the faulted
- * page in the same paging block. The decision
- * is based on system wide globals and the
- * expected page reference behavior of the
- * address range contained the faulting address.
- * First calculate some constants.
- */
- paging_offset = offset + object->paging_offset;
- cluster_offset = paging_offset & (cluster_size - 1);
- align_offset = paging_offset&(PAGE_SIZE_64-1);
- if (align_offset != 0) {
- cluster_offset = trunc_page_64(cluster_offset);
- }
-
-#define SPANS_CLUSTER(x) ((((x) - align_offset) & (vm_object_offset_t)(cluster_size - 1)) == 0)
-
- /*
- * Backward scan only if reverse sequential
- * behavior has been specified
- */
- CLUSTER_STAT(pages_at_lower_offsets = 0;)
- if (((vm_default_behind != 0 &&
- behavior == VM_BEHAVIOR_DEFAULT) ||
- behavior == VM_BEHAVIOR_RSEQNTL) && offset) {
- vm_object_offset_t cluster_bot;
-
- /*
- * Calculate lower search boundary.
- * Exclude pages that span a cluster boundary.
- * Clip to start of map entry.
- * For default page reference behavior, scan
- * default pages behind.
- */
- cluster_bot = (offset > cluster_offset) ?
- offset - cluster_offset : offset;
- if (align_offset != 0) {
- if ((cluster_bot < offset) &&
- SPANS_CLUSTER(cluster_bot)) {
- cluster_bot += PAGE_SIZE_64;
- }
- }
- if (behavior == VM_BEHAVIOR_DEFAULT) {
- vm_object_offset_t
- bot = (vm_object_offset_t)
- (vm_default_behind * PAGE_SIZE);
-
- if (cluster_bot < (offset - bot))
- cluster_bot = offset - bot;
- }
- if (lo_offset > cluster_bot)
- cluster_bot = lo_offset;
-
- for ( cluster_start = offset - PAGE_SIZE_64;
- (cluster_start >= cluster_bot) &&
- (cluster_start !=
- (align_offset - PAGE_SIZE_64));
- cluster_start -= PAGE_SIZE_64) {
- assert(cluster_size > PAGE_SIZE_64);
-retry_cluster_backw:
- if (!LOOK_FOR(object, cluster_start) ||
- vm_page_lookup(object, cluster_start)
- != VM_PAGE_NULL) {
- break;
- }
- if (object->internal) {
- /*
- * need to acquire a real page in
- * advance because this acts as
- * a throttling mechanism for
- * data_requests to the default
- * pager. If this fails, give up
- * trying to find any more pages
- * in the cluster and send off the
- * request for what we already have.
- */
- if ((m = vm_page_grab())
- == VM_PAGE_NULL) {
- cluster_start += PAGE_SIZE_64;
- cluster_end = offset + PAGE_SIZE_64;
- goto give_up;
- }
- } else if ((m = vm_page_grab_fictitious())
- == VM_PAGE_NULL) {
- vm_object_unlock(object);
- vm_page_more_fictitious();
- vm_object_lock(object);
- goto retry_cluster_backw;
- }