Page Menu
Home
FreeBSD
Search
Configure Global Search
Log In
Files
F166749030
D58851.diff
No One
Temporary
Actions
View File
Edit File
Delete File
View Transforms
Subscribe
Mute Notifications
Flag For Later
Award Token
Size
4 KB
Referenced Files
None
Subscribers
None
D58851.diff
View Options
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
Details
Attached
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)
Attached To
Mode
D58851: vm_object_take_pages_for_io(9)
Attached
Detach File
Event Timeline
Log In to Comment