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 <eric@badgerio.us> (initial revision)
Obtained from:  Dell Inc.
PR:             198431
MFC after:      2 weeks
Reviewed by:    jhb
Approved by:    kib (mentor)
This commit is contained in:
Eric van Gyzen 2015-06-02 18:37:04 +00:00
parent b7a728aaba
commit 63e4c6cdf9
7 changed files with 49 additions and 18 deletions

View File

@ -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);

View File

@ -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);

View File

@ -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)

View File

@ -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;

View File

@ -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)

View File

@ -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)
{

View File

@ -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_ */