| 890 | } |
| 891 | |
| 892 | static void |
| 893 | vm_fault_cow(struct faultstate *fs) |
| 894 | { |
| 895 | bool is_first_object_locked; |
| 896 | |
| 897 | KASSERT(fs->object != fs->first_object, |
| 898 | ("source and target COW objects are identical")); |
| 899 | |
| 900 | /* |
| 901 | * This allows pages to be virtually copied from a backing_object |
| 902 | * into the first_object, where the backing object has no other |
| 903 | * refs to it, and cannot gain any more refs. Instead of a bcopy, |
| 904 | * we just move the page from the backing object to the first |
| 905 | * object. Note that we must mark the page dirty in the first |
| 906 | * object so that it will go out to swap when needed. |
| 907 | */ |
| 908 | is_first_object_locked = false; |
| 909 | if ( |
| 910 | /* |
| 911 | * Only one shadow object and no other refs. |
| 912 | */ |
| 913 | fs->object->shadow_count == 1 && fs->object->ref_count == 1 && |
| 914 | /* |
| 915 | * No other ways to look the object up |
| 916 | */ |
| 917 | fs->object->handle == NULL && (fs->object->flags & OBJ_ANON) != 0 && |
| 918 | /* |
| 919 | * We don't chase down the shadow chain and we can acquire locks. |
| 920 | */ |
| 921 | (is_first_object_locked = VM_OBJECT_TRYWLOCK(fs->first_object)) && |
| 922 | fs->object == fs->first_object->backing_object && |
| 923 | VM_OBJECT_TRYWLOCK(fs->object)) { |
| 924 | /* |
| 925 | * Remove but keep xbusy for replace. fs->m is moved into |
| 926 | * fs->first_object and left busy while fs->first_m is |
| 927 | * conditionally freed. |
| 928 | */ |
| 929 | vm_page_remove_xbusy(fs->m); |
| 930 | vm_page_replace(fs->m, fs->first_object, fs->first_pindex, |
| 931 | fs->first_m); |
| 932 | vm_page_dirty(fs->m); |
| 933 | #if VM_NRESERVLEVEL > 0 |
| 934 | /* |
| 935 | * Rename the reservation. |
| 936 | */ |
| 937 | vm_reserv_rename(fs->m, fs->first_object, fs->object, |
| 938 | OFF_TO_IDX(fs->first_object->backing_object_offset)); |
| 939 | #endif |
| 940 | VM_OBJECT_WUNLOCK(fs->object); |
| 941 | VM_OBJECT_WUNLOCK(fs->first_object); |
| 942 | fs->first_m = fs->m; |
| 943 | fs->m = NULL; |
| 944 | VM_CNT_INC(v_cow_optim); |
| 945 | } else { |
| 946 | if (is_first_object_locked) |
| 947 | VM_OBJECT_WUNLOCK(fs->first_object); |
| 948 | /* |
| 949 | * Oh, well, lets copy it. |
no test coverage detected