Page MenuHomeFreeBSD

D58851.diff
No OneTemporary

D58851.diff

diff --git a/sys/vm/vm_object.h b/sys/vm/vm_object.h
--- a/sys/vm/vm_object.h
+++ b/sys/vm/vm_object.h
@@ -391,6 +391,11 @@
vm_size_t length, uint8_t queue);
struct vnode *vm_object_vnode(vm_object_t object);
bool vm_object_is_active(vm_object_t obj);
+int vm_object_take_pages_for_io(vm_object_t obj, vm_prot_t prot,
+ vm_page_t ma[], int total_ma_len, vm_ooffset_t start, vm_ooffset_t end,
+ int *ma_len);
+void vm_object_put_pages_after_io(vm_object_t obj, vm_prot_t prot,
+ vm_page_t ma[], int ma_len, vm_ooffset_t start, vm_ooffset_t wend);
#endif /* _KERNEL */
#endif /* _VM_OBJECT_ */
diff --git a/sys/vm/vm_object.c b/sys/vm/vm_object.c
--- a/sys/vm/vm_object.c
+++ b/sys/vm/vm_object.c
@@ -2512,6 +2512,141 @@
return (obj->ref_count > atomic_load_int(&obj->shadow_count));
}
+static void
+vm_object_unbusy_pages_after_io(vm_object_t obj, vm_prot_t prot, vm_page_t ma[],
+ int ma_len)
+{
+ int j;
+
+ VM_OBJECT_ASSERT_WLOCKED(obj);
+ MPASS((obj->flags & OBJ_UNMANAGED) == 0);
+ MPASS(prot == VM_PROT_READ || prot == VM_PROT_WRITE);
+#ifdef INVARIANTS
+ for (j = 1; j < ma_len; j++) {
+ MPASS(ma[j]->object == obj);
+ MPASS(ma[j]->pindex == ma[0]->pindex + j);
+ }
+#endif
+
+ if (prot == VM_PROT_READ) {
+ for (j = 0; j < ma_len; j++)
+ vm_page_sunbusy(ma[j]);
+ } else {
+ for (j = 0; j < ma_len; j++)
+ vm_page_xunbusy(ma[j]);
+ }
+}
+
+static void
+vm_object_reference_pages(vm_page_t ma[], int ma_len)
+{
+ int j;
+
+ for (j = 0; j < ma_len; j++)
+ vm_page_reference(ma[j]);
+}
+
+void
+vm_object_put_pages_after_io(vm_object_t obj, vm_prot_t prot, vm_page_t ma[],
+ int ma_len, vm_ooffset_t start, vm_ooffset_t wend)
+{
+ int d_len, i;
+
+ VM_OBJECT_ASSERT_WLOCKED(obj);
+ MPASS(ma_len > 0);
+ MPASS(ma[0]->object == obj);
+ MPASS(ma[0]->pindex = IDX_TO_OFF(trunc_page(start)));
+ MPASS(ma[0]->pindex + ma_len >= IDX_TO_OFF(round_page(wend)));
+
+ if (prot == VM_PROT_WRITE) {
+ d_len = atop(MIN(round_page(wend), ptoa(obj->size)) -
+ trunc_page(start));
+ MPASS(d_len <= ma_len);
+ for (i = 0; i < d_len; i++)
+ vm_page_dirty(ma[i]);
+ }
+ vm_object_unbusy_pages_after_io(obj, prot, ma, ma_len);
+}
+
+/*
+ * vm_object_take_pages_for_io(): prepare the range of the object
+ * pages from start to end inclusive for io. Object must be
+ * write-locked. If the object is backed by a vnode, the vnode must
+ * be locked.
+ *
+ * The run of the prepared pages is pointed to by the ma[] array,
+ * which length is passed as total_ma_len. The length of the filled
+ * part of the array is returned in *ma_lenp.
+ *
+ * If prot == VM_PROT_READ, the pages are sbusy and write mappings of
+ * them are invalidated, which ensures that pages do not change
+ * identity and cannot be modified by a parallel write.
+ *
+ * If prot == VM_PROT_WRITE, the pages are xbusy and all mappings of
+ * them are invalidated, which allows to write to the pages as needed.
+ *
+ * After the io operation is done, call vm_object_put_pages() to
+ * unbusy the pages. If the prot == VM_PROT_WRITE, then pages from
+ * the beginning of the run to wend are dirtied. The wend offset
+ * might be less than the end offset passed to take_pages(), which is
+ * useful if the write was short.
+ */
+int
+vm_object_take_pages_for_io(vm_object_t obj, vm_prot_t prot, vm_page_t ma[],
+ int total_ma_len, vm_ooffset_t start, vm_ooffset_t end, int *ma_lenp)
+{
+ vm_page_t m;
+ vm_pindex_t pi, ma_len;
+ int error, i;
+
+ VM_OBJECT_ASSERT_WLOCKED(obj);
+ MPASS((obj->flags & OBJ_UNMANAGED) == 0);
+ MPASS(prot == VM_PROT_READ || prot == VM_PROT_WRITE);
+ if (obj->type == OBJT_VNODE)
+ ASSERT_VOP_LOCKED(obj->handle, "vm_object_busy_pages");
+
+ end = MIN(round_page(end), ptoa(obj->size));
+ start = trunc_page(start);
+ ma_len = atop(end - start);
+ MPASS(total_ma_len >= ma_len);
+
+ vm_object_pip_add(obj, 1);
+
+again:
+ for (i = 0, pi = atop(start); i < ma_len; i++, pi++) {
+ m = vm_page_lookup(obj, pi);
+ if (m == NULL || !vm_page_all_valid(m)) {
+ vm_object_reference_pages(ma, i);
+ vm_object_unbusy_pages_after_io(obj, prot, ma, i);
+ error = vm_page_grab_valid(&m, obj, pi, VM_ALLOC_ZERO |
+ VM_ALLOC_NOBUSY);
+ if (error != KERN_SUCCESS)
+ return (error);
+ vm_page_reference(m);
+ goto again;
+ }
+ if (vm_page_busy_acquire(m, VM_ALLOC_WAITFAIL |
+ (prot == VM_PROT_READ ? VM_ALLOC_SBUSY : 0))) {
+ ma[i] = m;
+ continue;
+ }
+ vm_object_reference_pages(ma, i);
+ vm_object_unbusy_pages_after_io(obj, prot, ma, i);
+ goto again;
+ }
+
+ vm_object_pip_wakeup(obj);
+
+ for (i = 0; i < ma_len; i++) {
+ if (prot == VM_PROT_READ)
+ pmap_remove_write(ma[i]);
+ else
+ pmap_remove_all(ma[i]);
+ }
+ *ma_lenp = ma_len;
+ return (KERN_SUCCESS);
+}
+
static int
vm_object_list_handler(struct sysctl_req *req, bool swap_only)
{

File Metadata

Mime Type
text/plain
Expires
Mon, Aug 17, 3:36 AM (3 h, 16 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
36808336
Default Alt Text
D58851.diff (4 KB)

Event Timeline