summaryrefslogtreecommitdiffstats
path: root/sys/vm
diff options
context:
space:
mode:
authorkib <kib@FreeBSD.org>2013-04-28 19:38:59 +0000
committerkib <kib@FreeBSD.org>2013-04-28 19:38:59 +0000
commit2f2c1edec8b49b001f43df2df01de504dfd6ed3a (patch)
tree1a58748990918f89c2609e952ac76f14624b7411 /sys/vm
parentd4d37d6d8889403ad1350f932cbb9421b9b6023d (diff)
downloadFreeBSD-src-2f2c1edec8b49b001f43df2df01de504dfd6ed3a.zip
FreeBSD-src-2f2c1edec8b49b001f43df2df01de504dfd6ed3a.tar.gz
Rework the handling of the tmpfs node backing swap object and tmpfs
vnode v_object to avoid double-buffering. Use the same object both as the backing store for tmpfs node and as the v_object. Besides reducing memory use up to 2x times for situation of mapping files from tmpfs, it also makes tmpfs read and write operations copy twice bytes less. VM subsystem was already slightly adapted to tolerate OBJT_SWAP object as v_object. Now the vm_object_deallocate() is modified to not reinstantiate OBJ_ONEMAPPING flag and help the VFS to correctly handle VV_TEXT flag on the last dereference of the tmpfs backing object. Reviewed by: alc Tested by: pho, bf MFC after: 1 month
Diffstat (limited to 'sys/vm')
-rw-r--r--sys/vm/vm_object.c24
-rw-r--r--sys/vm/vm_object.h11
2 files changed, 34 insertions, 1 deletions
diff --git a/sys/vm/vm_object.c b/sys/vm/vm_object.c
index 1f7cb78..ce81ad5 100644
--- a/sys/vm/vm_object.c
+++ b/sys/vm/vm_object.c
@@ -505,6 +505,7 @@ void
vm_object_deallocate(vm_object_t object)
{
vm_object_t temp;
+ struct vnode *vp;
while (object != NULL) {
VM_OBJECT_WLOCK(object);
@@ -527,15 +528,36 @@ vm_object_deallocate(vm_object_t object)
VM_OBJECT_WUNLOCK(object);
return;
} else if (object->ref_count == 1) {
+ if (object->type == OBJT_SWAP &&
+ (object->flags & OBJ_TMPFS) != 0) {
+ vp = object->un_pager.swp.swp_tmpfs;
+ vhold(vp);
+ VM_OBJECT_WUNLOCK(object);
+ vn_lock(vp, LK_EXCLUSIVE | LK_RETRY);
+ vdrop(vp);
+ VM_OBJECT_WLOCK(object);
+ if (object->type == OBJT_DEAD) {
+ VM_OBJECT_WUNLOCK(object);
+ VOP_UNLOCK(vp, 0);
+ return;
+ } else if ((object->flags & OBJ_TMPFS) != 0) {
+ if (object->ref_count == 1)
+ VOP_UNSET_TEXT(vp);
+ VOP_UNLOCK(vp, 0);
+ }
+ }
if (object->shadow_count == 0 &&
object->handle == NULL &&
(object->type == OBJT_DEFAULT ||
- object->type == OBJT_SWAP)) {
+ (object->type == OBJT_SWAP &&
+ (object->flags & OBJ_TMPFS) == 0))) {
vm_object_set_flag(object, OBJ_ONEMAPPING);
} else if ((object->shadow_count == 1) &&
(object->handle == NULL) &&
(object->type == OBJT_DEFAULT ||
object->type == OBJT_SWAP)) {
+ KASSERT((object->flags & OBJ_TMPFS) == 0,
+ ("Shadowed tmpfs v_object"));
vm_object_t robject;
robject = LIST_FIRST(&object->shadow_head);
diff --git a/sys/vm/vm_object.h b/sys/vm/vm_object.h
index 2f2c961..cf54663 100644
--- a/sys/vm/vm_object.h
+++ b/sys/vm/vm_object.h
@@ -154,11 +154,21 @@ struct vm_object {
/*
* Swap pager
*
+ * swp_tmpfs - back-pointer to the tmpfs vnode,
+ * if any, which uses the vm object
+ * as backing store. The handle
+ * cannot be reused for linking,
+ * because the vnode can be
+ * reclaimed and recreated, making
+ * the handle changed and hash-chain
+ * invalid.
+ *
* swp_bcount - number of swap 'swblock' metablocks, each
* contains up to 16 swapblk assignments.
* see vm/swap_pager.h
*/
struct {
+ void *swp_tmpfs;
int swp_bcount;
} swp;
} un_pager;
@@ -179,6 +189,7 @@ struct vm_object {
#define OBJ_COLORED 0x1000 /* pg_color is defined */
#define OBJ_ONEMAPPING 0x2000 /* One USE (a single, non-forked) mapping flag */
#define OBJ_DISCONNECTWNT 0x4000 /* disconnect from vnode wanted */
+#define OBJ_TMPFS 0x8000
#define IDX_TO_OFF(idx) (((vm_ooffset_t)(idx)) << PAGE_SHIFT)
#define OFF_TO_IDX(off) ((vm_pindex_t)(((vm_ooffset_t)(off)) >> PAGE_SHIFT))
OpenPOWER on IntegriCloud