From 63e4c6cdf955492b1c70cdc37f69c1070edc004c Mon Sep 17 00:00:00 2001 From: Eric van Gyzen Date: Tue, 2 Jun 2015 18:37:04 +0000 Subject: [PATCH] Provide vnode in memory map info for files on tmpfs When providing memory map information to userland, populate the vnode pointer for tmpfs files. Set the memory mapping to appear as a vnode type, to match FreeBSD 9 behavior. This fixes the use of tmpfs files with the dtrace pid provider, procstat -v, procfs, linprocfs, pmc (pmcstat), and ptrace (PT_VM_ENTRY). Submitted by: Eric Badger (initial revision) Obtained from: Dell Inc. PR: 198431 MFC after: 2 weeks Reviewed by: jhb Approved by: kib (mentor) --- sys/compat/linprocfs/linprocfs.c | 12 ++++-------- sys/dev/hwpmc/hwpmc_mod.c | 6 +++--- sys/fs/procfs/procfs_map.c | 14 ++++++++++---- sys/kern/kern_proc.c | 20 ++++++++++++++++++-- sys/kern/sys_process.c | 2 +- sys/vm/vm_object.c | 12 ++++++++++++ sys/vm/vm_object.h | 1 + 7 files changed, 49 insertions(+), 18 deletions(-) diff --git a/sys/compat/linprocfs/linprocfs.c b/sys/compat/linprocfs/linprocfs.c index 00d02865e713..25a832586c01 100644 --- a/sys/compat/linprocfs/linprocfs.c +++ b/sys/compat/linprocfs/linprocfs.c @@ -1025,20 +1025,16 @@ linprocfs_doprocmaps(PFS_FILL_ARGS) ino = 0; if (lobj) { off = IDX_TO_OFF(lobj->size); - if (lobj->type == OBJT_VNODE) { - vp = lobj->handle; - if (vp) - vref(vp); - } - else - vp = NULL; + vp = vm_object_vnode(lobj); + if (vp != NULL) + vref(vp); if (lobj != obj) VM_OBJECT_RUNLOCK(lobj); flags = obj->flags; ref_count = obj->ref_count; shadow_count = obj->shadow_count; VM_OBJECT_RUNLOCK(obj); - if (vp) { + if (vp != NULL) { vn_fullpath(td, vp, &name, &freename); vn_lock(vp, LK_SHARED | LK_RETRY); VOP_GETATTR(vp, &vat, td->td_ucred); diff --git a/sys/dev/hwpmc/hwpmc_mod.c b/sys/dev/hwpmc/hwpmc_mod.c index d1b56f10835c..131eb3575e24 100644 --- a/sys/dev/hwpmc/hwpmc_mod.c +++ b/sys/dev/hwpmc/hwpmc_mod.c @@ -1655,7 +1655,8 @@ pmc_log_process_mappings(struct pmc_owner *po, struct proc *p) continue; } - if (lobj->type != OBJT_VNODE || lobj->handle == NULL) { + vp = vm_object_vnode(lobj); + if (vp == NULL) { if (lobj != obj) VM_OBJECT_RUNLOCK(lobj); VM_OBJECT_RUNLOCK(obj); @@ -1667,7 +1668,7 @@ pmc_log_process_mappings(struct pmc_owner *po, struct proc *p) * vnode, so we don't emit redundant MAP-IN * directives. */ - if (entry->start == last_end && lobj->handle == last_vp) { + if (entry->start == last_end && vp == last_vp) { last_end = entry->end; if (lobj != obj) VM_OBJECT_RUNLOCK(lobj); @@ -1690,7 +1691,6 @@ pmc_log_process_mappings(struct pmc_owner *po, struct proc *p) last_timestamp = map->timestamp; vm_map_unlock_read(map); - vp = lobj->handle; vref(vp); if (lobj != obj) VM_OBJECT_RUNLOCK(lobj); diff --git a/sys/fs/procfs/procfs_map.c b/sys/fs/procfs/procfs_map.c index eae70229e6bd..b00aac3ac891 100644 --- a/sys/fs/procfs/procfs_map.c +++ b/sys/fs/procfs/procfs_map.c @@ -159,11 +159,11 @@ procfs_doprocmap(PFS_FILL_ARGS) freepath = NULL; fullpath = "-"; if (lobj) { + vp = NULL; switch (lobj->type) { default: case OBJT_DEFAULT: type = "default"; - vp = NULL; break; case OBJT_VNODE: type = "vnode"; @@ -171,13 +171,19 @@ procfs_doprocmap(PFS_FILL_ARGS) vref(vp); break; case OBJT_SWAP: - type = "swap"; - vp = NULL; + if ((lobj->flags & OBJ_TMPFS_NODE) != 0) { + type = "vnode"; + if ((lobj->flags & OBJ_TMPFS) != 0) { + vp = lobj->un_pager.swp.swp_tmpfs; + vref(vp); + } + } else { + type = "swap"; + } break; case OBJT_SG: case OBJT_DEVICE: type = "device"; - vp = NULL; break; } if (lobj != obj) diff --git a/sys/kern/kern_proc.c b/sys/kern/kern_proc.c index 6618c0849373..fc33febee40e 100644 --- a/sys/kern/kern_proc.c +++ b/sys/kern/kern_proc.c @@ -2113,7 +2113,15 @@ sysctl_kern_proc_ovmmap(SYSCTL_HANDLER_ARGS) vref(vp); break; case OBJT_SWAP: - kve->kve_type = KVME_TYPE_SWAP; + if ((lobj->flags & OBJ_TMPFS_NODE) != 0) { + kve->kve_type = KVME_TYPE_VNODE; + if ((lobj->flags & OBJ_TMPFS) != 0) { + vp = lobj->un_pager.swp.swp_tmpfs; + vref(vp); + } + } else { + kve->kve_type = KVME_TYPE_SWAP; + } break; case OBJT_DEVICE: kve->kve_type = KVME_TYPE_DEVICE; @@ -2339,7 +2347,15 @@ kern_proc_vmmap_out(struct proc *p, struct sbuf *sb) vref(vp); break; case OBJT_SWAP: - kve->kve_type = KVME_TYPE_SWAP; + if ((lobj->flags & OBJ_TMPFS_NODE) != 0) { + kve->kve_type = KVME_TYPE_VNODE; + if ((lobj->flags & OBJ_TMPFS) != 0) { + vp = lobj->un_pager.swp.swp_tmpfs; + vref(vp); + } + } else { + kve->kve_type = KVME_TYPE_SWAP; + } break; case OBJT_DEVICE: kve->kve_type = KVME_TYPE_DEVICE; diff --git a/sys/kern/sys_process.c b/sys/kern/sys_process.c index 09a43f4bfc76..d82fda030cb8 100644 --- a/sys/kern/sys_process.c +++ b/sys/kern/sys_process.c @@ -402,7 +402,7 @@ ptrace_vm_entry(struct thread *td, struct proc *p, struct ptrace_vm_entry *pve) lobj = tobj; pve->pve_offset += tobj->backing_object_offset; } - vp = (lobj->type == OBJT_VNODE) ? lobj->handle : NULL; + vp = vm_object_vnode(lobj); if (vp != NULL) vref(vp); if (lobj != obj) diff --git a/sys/vm/vm_object.c b/sys/vm/vm_object.c index 30623b2e50cf..e240b67d2fa8 100644 --- a/sys/vm/vm_object.c +++ b/sys/vm/vm_object.c @@ -2287,6 +2287,18 @@ vm_object_unwire(vm_object_t object, vm_ooffset_t offset, vm_size_t length, } } +struct vnode * +vm_object_vnode(vm_object_t object) +{ + + VM_OBJECT_ASSERT_LOCKED(object); + if (object->type == OBJT_VNODE) + return (object->handle); + if (object->type == OBJT_SWAP && (object->flags & OBJ_TMPFS) != 0) + return (object->un_pager.swp.swp_tmpfs); + return (NULL); +} + static int sysctl_vm_object_list(SYSCTL_HANDLER_ARGS) { diff --git a/sys/vm/vm_object.h b/sys/vm/vm_object.h index 731c9e3e8d71..1f591568137c 100644 --- a/sys/vm/vm_object.h +++ b/sys/vm/vm_object.h @@ -322,6 +322,7 @@ boolean_t vm_object_sync(vm_object_t, vm_ooffset_t, vm_size_t, boolean_t, boolean_t); void vm_object_unwire(vm_object_t object, vm_ooffset_t offset, vm_size_t length, uint8_t queue); +struct vnode *vm_object_vnode(vm_object_t object); #endif /* _KERNEL */ #endif /* _VM_OBJECT_ */