Index: head/sys/vm/vm_fault.c =================================================================== --- head/sys/vm/vm_fault.c +++ head/sys/vm/vm_fault.c @@ -108,6 +108,7 @@ static int vm_fault_additional_pages(vm_page_t, int, int, vm_page_t *, int *); #define VM_FAULT_READ_BEHIND 8 +#define VM_FAULT_READ_DEFAULT (1 + VM_FAULT_READ_AHEAD_INIT) #define VM_FAULT_READ_MAX (1 + VM_FAULT_READ_AHEAD_MAX) #define VM_FAULT_NINCR (VM_FAULT_READ_MAX / VM_FAULT_READ_BEHIND) #define VM_FAULT_SUM (VM_FAULT_NINCR * (VM_FAULT_NINCR + 1) / 2) @@ -292,7 +293,6 @@ int fault_flags, vm_page_t *m_hold) { vm_prot_t prot; - long ahead, behind; int alloc_req, era, faultcount, nera, reqpage, result; boolean_t growstack, is_first_object_locked, wired; int map_generation; @@ -302,7 +302,7 @@ struct faultstate fs; struct vnode *vp; vm_page_t m; - int locked, error; + int ahead, behind, cluster_offset, error, locked; hardfault = 0; growstack = TRUE; @@ -555,45 +555,59 @@ int rv; u_char behavior = vm_map_entry_behavior(fs.entry); + era = fs.entry->read_ahead; if (behavior == MAP_ENTRY_BEHAV_RANDOM || P_KILLED(curproc)) { behind = 0; + nera = 0; ahead = 0; } else if (behavior == MAP_ENTRY_BEHAV_SEQUENTIAL) { behind = 0; - ahead = atop(fs.entry->end - vaddr) - 1; - if (ahead > VM_FAULT_READ_AHEAD_MAX) - ahead = VM_FAULT_READ_AHEAD_MAX; + nera = VM_FAULT_READ_AHEAD_MAX; + ahead = nera; if (fs.pindex == fs.entry->next_read) vm_fault_cache_behind(&fs, VM_FAULT_READ_MAX); - } else { + } else if (fs.pindex == fs.entry->next_read) { /* - * If this is a sequential page fault, then - * arithmetically increase the number of pages - * in the read-ahead window. Otherwise, reset - * the read-ahead window to its smallest size. + * This is a sequential fault. Arithmetically + * increase the requested number of pages in + * the read-ahead window. The requested + * number of pages is "# of sequential faults + * x (read ahead min + 1) + read ahead min" */ - behind = atop(vaddr - fs.entry->start); - if (behind > VM_FAULT_READ_BEHIND) - behind = VM_FAULT_READ_BEHIND; - ahead = atop(fs.entry->end - vaddr) - 1; - era = fs.entry->read_ahead; - if (fs.pindex == fs.entry->next_read) { - nera = era + behind; + behind = 0; + nera = VM_FAULT_READ_AHEAD_MIN; + if (era > 0) { + nera += era + 1; if (nera > VM_FAULT_READ_AHEAD_MAX) nera = VM_FAULT_READ_AHEAD_MAX; - behind = 0; - if (ahead > nera) - ahead = nera; - if (era == VM_FAULT_READ_AHEAD_MAX) - vm_fault_cache_behind(&fs, - VM_FAULT_CACHE_BEHIND); - } else if (ahead > VM_FAULT_READ_AHEAD_MIN) - ahead = VM_FAULT_READ_AHEAD_MIN; - if (era != ahead) - fs.entry->read_ahead = ahead; + } + ahead = nera; + if (era == VM_FAULT_READ_AHEAD_MAX) + vm_fault_cache_behind(&fs, + VM_FAULT_CACHE_BEHIND); + } else { + /* + * This is a non-sequential fault. Request a + * cluster of pages that is aligned to a + * VM_FAULT_READ_DEFAULT page offset boundary + * within the object. Alignment to a page + * offset boundary is more likely to coincide + * with the underlying file system block than + * alignment to a virtual address boundary. + */ + cluster_offset = fs.pindex % + VM_FAULT_READ_DEFAULT; + behind = ulmin(cluster_offset, + atop(vaddr - fs.entry->start)); + nera = 0; + ahead = VM_FAULT_READ_DEFAULT - 1 - + cluster_offset; } + ahead = ulmin(ahead, atop(fs.entry->end - vaddr) - 1); + if (era != nera) + fs.entry->read_ahead = nera; /* * Call the pager to retrieve the data, if any, after