* Calculate the desired readahead. Handle drop-behind. * * Returns the number of readahead blocks to pass to the pager. */
| 743 | * Returns the number of readahead blocks to pass to the pager. |
| 744 | */ |
| 745 | static int |
| 746 | vm_fault_readahead(struct faultstate *fs) |
| 747 | { |
| 748 | int era, nera; |
| 749 | u_char behavior; |
| 750 | |
| 751 | KASSERT(fs->lookup_still_valid, ("map unlocked")); |
| 752 | era = fs->entry->read_ahead; |
| 753 | behavior = vm_map_entry_behavior(fs->entry); |
| 754 | if (behavior == MAP_ENTRY_BEHAV_RANDOM) { |
| 755 | nera = 0; |
| 756 | } else if (behavior == MAP_ENTRY_BEHAV_SEQUENTIAL) { |
| 757 | nera = VM_FAULT_READ_AHEAD_MAX; |
| 758 | if (fs->vaddr == fs->entry->next_read) |
| 759 | vm_fault_dontneed(fs, fs->vaddr, nera); |
| 760 | } else if (fs->vaddr == fs->entry->next_read) { |
| 761 | /* |
| 762 | * This is a sequential fault. Arithmetically |
| 763 | * increase the requested number of pages in |
| 764 | * the read-ahead window. The requested |
| 765 | * number of pages is "# of sequential faults |
| 766 | * x (read ahead min + 1) + read ahead min" |
| 767 | */ |
| 768 | nera = VM_FAULT_READ_AHEAD_MIN; |
| 769 | if (era > 0) { |
| 770 | nera += era + 1; |
| 771 | if (nera > VM_FAULT_READ_AHEAD_MAX) |
| 772 | nera = VM_FAULT_READ_AHEAD_MAX; |
| 773 | } |
| 774 | if (era == VM_FAULT_READ_AHEAD_MAX) |
| 775 | vm_fault_dontneed(fs, fs->vaddr, nera); |
| 776 | } else { |
| 777 | /* |
| 778 | * This is a non-sequential fault. |
| 779 | */ |
| 780 | nera = 0; |
| 781 | } |
| 782 | if (era != nera) { |
| 783 | /* |
| 784 | * A read lock on the map suffices to update |
| 785 | * the read ahead count safely. |
| 786 | */ |
| 787 | fs->entry->read_ahead = nera; |
| 788 | } |
| 789 | |
| 790 | return (nera); |
| 791 | } |
| 792 | |
| 793 | static int |
| 794 | vm_fault_lookup(struct faultstate *fs) |
no test coverage detected