Reuse kern_proc_vmmap_resident() for procfs_map resident count.

The existing algorithm in procfs_map() to calculate count of resident
pages in an entry is too primitive, resulting in too long run time for
large sparse mapping entries.  Re-use the kern_proc_vmmap_resident()
from kern_proc.c which only looks at the existing pages in the
iterations.

Also, this makes procfs to honor kern.proc_vmmap_skip_resident_count,
if user does not need this information.

Reported by:	Glenn Weinberg <glenn.weinberg@intel.com>
PR:	224532
No objections from:	des (procfs maintainer)
Sponsored by:	The FreeBSD Foundation
MFC after:	1 week
Differential revision:	https://reviews.freebsd.org/D13595
This commit is contained in:
Konstantin Belousov 2017-12-28 13:23:13 +00:00
parent baaa79699a
commit cfb03f67d9
Notes: svn2git 2020-12-20 02:59:44 +00:00
svn path=/head/; revision=327286

View File

@ -84,12 +84,17 @@ procfs_doprocmap(PFS_FILL_ARGS)
vm_map_t map;
vm_map_entry_t entry, tmp_entry;
struct vnode *vp;
char *fullpath, *freepath;
char *fullpath, *freepath, *type;
struct ucred *cred;
int error;
vm_object_t obj, tobj, lobj;
int error, privateresident, ref_count, resident, shadow_count, flags;
vm_offset_t e_start, e_end;
vm_eflags_t e_eflags;
vm_prot_t e_prot;
unsigned int last_timestamp;
bool super;
#ifdef COMPAT_FREEBSD32
int wrap32 = 0;
bool wrap32;
#endif
PROC_LOCK(p);
@ -102,11 +107,12 @@ procfs_doprocmap(PFS_FILL_ARGS)
return (EOPNOTSUPP);
#ifdef COMPAT_FREEBSD32
if (SV_CURPROC_FLAG(SV_ILP32)) {
if (!(SV_PROC_FLAG(p, SV_ILP32)))
return (EOPNOTSUPP);
wrap32 = 1;
}
wrap32 = false;
if (SV_CURPROC_FLAG(SV_ILP32)) {
if (!(SV_PROC_FLAG(p, SV_ILP32)))
return (EOPNOTSUPP);
wrap32 = true;
}
#endif
vm = vmspace_acquire_ref(p);
@ -116,14 +122,6 @@ procfs_doprocmap(PFS_FILL_ARGS)
vm_map_lock_read(map);
for (entry = map->header.next; entry != &map->header;
entry = entry->next) {
vm_object_t obj, tobj, lobj;
int ref_count, shadow_count, flags;
vm_offset_t e_start, e_end, addr;
int resident, privateresident;
char *type;
vm_eflags_t e_eflags;
vm_prot_t e_prot;
if (entry->eflags & MAP_ENTRY_IS_SUB_MAP)
continue;
@ -132,6 +130,7 @@ procfs_doprocmap(PFS_FILL_ARGS)
e_start = entry->start;
e_end = entry->end;
privateresident = 0;
resident = 0;
obj = entry->object.vm_object;
if (obj != NULL) {
VM_OBJECT_RLOCK(obj);
@ -140,21 +139,18 @@ procfs_doprocmap(PFS_FILL_ARGS)
}
cred = (entry->cred) ? entry->cred : (obj ? obj->cred : NULL);
resident = 0;
addr = entry->start;
while (addr < entry->end) {
if (pmap_extract(map->pmap, addr))
resident++;
addr += PAGE_SIZE;
}
for (lobj = tobj = obj; tobj; tobj = tobj->backing_object) {
for (lobj = tobj = obj; tobj != NULL;
tobj = tobj->backing_object) {
if (tobj != obj)
VM_OBJECT_RLOCK(tobj);
if (lobj != obj)
VM_OBJECT_RUNLOCK(lobj);
lobj = tobj;
}
if (obj != NULL)
kern_proc_vmmap_resident(map, entry, &resident, &super);
for (tobj = obj; tobj != NULL; tobj = tobj->backing_object) {
if (tobj != obj && tobj != lobj)
VM_OBJECT_RUNLOCK(tobj);
}
last_timestamp = map->timestamp;
vm_map_unlock_read(map);