|
@@ -832,8 +832,27 @@ static bool vma_has_reserves(struct vm_area_struct *vma, long chg)
|
|
* Only the process that called mmap() has reserves for
|
|
* Only the process that called mmap() has reserves for
|
|
* private mappings.
|
|
* private mappings.
|
|
*/
|
|
*/
|
|
- if (is_vma_resv_set(vma, HPAGE_RESV_OWNER))
|
|
|
|
- return true;
|
|
|
|
|
|
+ if (is_vma_resv_set(vma, HPAGE_RESV_OWNER)) {
|
|
|
|
+ /*
|
|
|
|
+ * Like the shared case above, a hole punch or truncate
|
|
|
|
+ * could have been performed on the private mapping.
|
|
|
|
+ * Examine the value of chg to determine if reserves
|
|
|
|
+ * actually exist or were previously consumed.
|
|
|
|
+ * Very Subtle - The value of chg comes from a previous
|
|
|
|
+ * call to vma_needs_reserves(). The reserve map for
|
|
|
|
+ * private mappings has different (opposite) semantics
|
|
|
|
+ * than that of shared mappings. vma_needs_reserves()
|
|
|
|
+ * has already taken this difference in semantics into
|
|
|
|
+ * account. Therefore, the meaning of chg is the same
|
|
|
|
+ * as in the shared case above. Code could easily be
|
|
|
|
+ * combined, but keeping it separate draws attention to
|
|
|
|
+ * subtle differences.
|
|
|
|
+ */
|
|
|
|
+ if (chg)
|
|
|
|
+ return false;
|
|
|
|
+ else
|
|
|
|
+ return true;
|
|
|
|
+ }
|
|
|
|
|
|
return false;
|
|
return false;
|
|
}
|
|
}
|
|
@@ -1816,6 +1835,25 @@ static long __vma_reservation_common(struct hstate *h,
|
|
|
|
|
|
if (vma->vm_flags & VM_MAYSHARE)
|
|
if (vma->vm_flags & VM_MAYSHARE)
|
|
return ret;
|
|
return ret;
|
|
|
|
+ else if (is_vma_resv_set(vma, HPAGE_RESV_OWNER) && ret >= 0) {
|
|
|
|
+ /*
|
|
|
|
+ * In most cases, reserves always exist for private mappings.
|
|
|
|
+ * However, a file associated with mapping could have been
|
|
|
|
+ * hole punched or truncated after reserves were consumed.
|
|
|
|
+ * As subsequent fault on such a range will not use reserves.
|
|
|
|
+ * Subtle - The reserve map for private mappings has the
|
|
|
|
+ * opposite meaning than that of shared mappings. If NO
|
|
|
|
+ * entry is in the reserve map, it means a reservation exists.
|
|
|
|
+ * If an entry exists in the reserve map, it means the
|
|
|
|
+ * reservation has already been consumed. As a result, the
|
|
|
|
+ * return value of this routine is the opposite of the
|
|
|
|
+ * value returned from reserve map manipulation routines above.
|
|
|
|
+ */
|
|
|
|
+ if (ret)
|
|
|
|
+ return 0;
|
|
|
|
+ else
|
|
|
|
+ return 1;
|
|
|
|
+ }
|
|
else
|
|
else
|
|
return ret < 0 ? ret : 0;
|
|
return ret < 0 ? ret : 0;
|
|
}
|
|
}
|