char * findname(kvm_t *kd, struct kbit *vmspace, struct vm_map_entry *vme, struct kbit *vp, struct kbit *vfs, struct kbit *uvm_obj) { static char buf[1024], *name; size_t l; if (UVM_ET_ISOBJ(vme)) { if (A(vfs)) { l = strlen(D(vfs, mount)->mnt_stat.f_mntonname); switch (search_cache(kd, vp, &name, buf, sizeof(buf))) { case 0: /* found something */ if (name - (1 + 11 + l) < buf) break; name--; *name = '/'; /*FALLTHROUGH*/ case 2: /* found nothing */ name -= 11; memcpy(name, " -unknown- ", (size_t)11); name -= l; memcpy(name, D(vfs, mount)->mnt_stat.f_mntonname, l); break; case 1: /* all is well */ if (name - (1 + l) < buf) break; name--; *name = '/'; if (l != 1) { name -= l; memcpy(name, D(vfs, mount)->mnt_stat.f_mntonname, l); } break; } } else if (UVM_OBJ_IS_DEVICE(D(uvm_obj, uvm_object))) { struct kbit kdev; dev_t dev; P(&kdev) = P(uvm_obj); S(&kdev) = sizeof(struct uvm_device); KDEREF(kd, &kdev); dev = D(&kdev, uvm_device)->u_device; name = devname(dev, S_IFCHR); if (name != NULL) snprintf(buf, sizeof(buf), "/dev/%s", name); else snprintf(buf, sizeof(buf), " [ device %d,%d ]", major(dev), minor(dev)); name = buf; } else if (UVM_OBJ_IS_AOBJ(D(uvm_obj, uvm_object))) name = " [ uvm_aobj ]"; else if (UVM_OBJ_IS_VNODE(D(uvm_obj, uvm_object))) name = " [ ?VNODE? ]"; else { snprintf(buf, sizeof(buf), " [ unknown (%p) ]", D(uvm_obj, uvm_object)->pgops); name = buf; } } else if (D(vmspace, vmspace)->vm_maxsaddr <= (caddr_t)vme->start && (D(vmspace, vmspace)->vm_maxsaddr + (size_t)maxssiz) >= (caddr_t)vme->end) { name = " [ stack ]"; } else if (D(vmspace, vmspace)->vm_daddr <= (caddr_t)vme->start && D(vmspace, vmspace)->vm_daddr + BRKSIZ >= (caddr_t)vme->end) { name = " [ heap ]"; } else if (UVM_ET_ISHOLE(vme)) name = " [ hole ]"; else name = " [ anon ]"; return (name); }
/* ARGSUSED */ int sys_mincore(struct lwp *l, const struct sys_mincore_args *uap, register_t *retval) { /* { syscallarg(void *) addr; syscallarg(size_t) len; syscallarg(char *) vec; } */ struct proc *p = l->l_proc; struct vm_page *pg; char *vec, pgi; struct uvm_object *uobj; struct vm_amap *amap; struct vm_anon *anon; struct vm_map_entry *entry; vaddr_t start, end, lim; struct vm_map *map; vsize_t len; int error = 0, npgs; map = &p->p_vmspace->vm_map; start = (vaddr_t)SCARG(uap, addr); len = SCARG(uap, len); vec = SCARG(uap, vec); if (start & PAGE_MASK) return EINVAL; len = round_page(len); end = start + len; if (end <= start) return EINVAL; /* * Lock down vec, so our returned status isn't outdated by * storing the status byte for a page. */ npgs = len >> PAGE_SHIFT; error = uvm_vslock(p->p_vmspace, vec, npgs, VM_PROT_WRITE); if (error) { return error; } vm_map_lock_read(map); if (uvm_map_lookup_entry(map, start, &entry) == false) { error = ENOMEM; goto out; } for (/* nothing */; entry != &map->header && entry->start < end; entry = entry->next) { KASSERT(!UVM_ET_ISSUBMAP(entry)); KASSERT(start >= entry->start); /* Make sure there are no holes. */ if (entry->end < end && (entry->next == &map->header || entry->next->start > entry->end)) { error = ENOMEM; goto out; } lim = end < entry->end ? end : entry->end; /* * Special case for objects with no "real" pages. Those * are always considered resident (mapped devices). */ if (UVM_ET_ISOBJ(entry)) { KASSERT(!UVM_OBJ_IS_KERN_OBJECT(entry->object.uvm_obj)); if (UVM_OBJ_IS_DEVICE(entry->object.uvm_obj)) { for (/* nothing */; start < lim; start += PAGE_SIZE, vec++) subyte(vec, 1); continue; } } amap = entry->aref.ar_amap; /* upper layer */ uobj = entry->object.uvm_obj; /* lower layer */ if (amap != NULL) amap_lock(amap); if (uobj != NULL) mutex_enter(uobj->vmobjlock); for (/* nothing */; start < lim; start += PAGE_SIZE, vec++) { pgi = 0; if (amap != NULL) { /* Check the upper layer first. */ anon = amap_lookup(&entry->aref, start - entry->start); /* Don't need to lock anon here. */ if (anon != NULL && anon->an_page != NULL) { /* * Anon has the page for this entry * offset. */ pgi = 1; } } if (uobj != NULL && pgi == 0) { /* Check the lower layer. */ pg = uvm_pagelookup(uobj, entry->offset + (start - entry->start)); if (pg != NULL) { /* * Object has the page for this entry * offset. */ pgi = 1; } } (void) subyte(vec, pgi); } if (uobj != NULL) mutex_exit(uobj->vmobjlock); if (amap != NULL) amap_unlock(amap); } out: vm_map_unlock_read(map); uvm_vsunlock(p->p_vmspace, SCARG(uap, vec), npgs); return error; }