Index: src/sys/compat/linprocfs/linprocfs.c =================================================================== RCS file: /home/scvs/src/sys/compat/linprocfs/linprocfs.c,v retrieving revision 1.89.2.8.2.1 diff -u -p -r1.89.2.8.2.1 linprocfs.c --- src/sys/compat/linprocfs/linprocfs.c 2 Oct 2008 02:57:24 -0000 1.89.2.8.2.1 +++ src/sys/compat/linprocfs/linprocfs.c 15 Oct 2008 20:30:10 -0000 @@ -945,48 +945,47 @@ linprocfs_doprocenviron(PFS_FILL_ARGS) static int linprocfs_doprocmaps(PFS_FILL_ARGS) { - char mebuffer[512]; vm_map_t map = &p->p_vmspace->vm_map; - vm_map_entry_t entry; + vm_map_entry_t entry, tmp_entry; vm_object_t obj, tobj, lobj; + vm_offset_t saved_end; vm_ooffset_t off = 0; char *name = "", *freename = NULL; - size_t len; ino_t ino; + unsigned int last_timestamp; int ref_count, shadow_count, flags; int error; struct vnode *vp; struct vattr vat; int locked; - + PROC_LOCK(p); error = p_candebug(td, p); PROC_UNLOCK(p); if (error) return (error); - + if (uio->uio_rw != UIO_READ) return (EOPNOTSUPP); - - if (uio->uio_offset != 0) - return (0); - + error = 0; - if (map != &curthread->td_proc->p_vmspace->vm_map) - vm_map_lock_read(map); - for (entry = map->header.next; - ((uio->uio_resid > 0) && (entry != &map->header)); + vm_map_lock_read(map); + for (entry = map->header.next; entry != &map->header; entry = entry->next) { name = ""; freename = NULL; if (entry->eflags & MAP_ENTRY_IS_SUB_MAP) continue; + saved_end = entry->end; obj = entry->object.vm_object; - for (lobj = tobj = obj; tobj; tobj = tobj->backing_object) + for (lobj = tobj = obj; tobj; tobj = tobj->backing_object) { + VM_OBJECT_LOCK(tobj); + if (lobj != obj) + VM_OBJECT_UNLOCK(lobj); lobj = tobj; + } ino = 0; if (lobj) { - VM_OBJECT_LOCK(lobj); off = IDX_TO_OFF(lobj->size); if (lobj->type == OBJT_VNODE) { vp = lobj->handle; @@ -995,10 +994,12 @@ linprocfs_doprocmaps(PFS_FILL_ARGS) } else vp = NULL; + if (lobj != obj) + VM_OBJECT_UNLOCK(lobj); flags = obj->flags; ref_count = obj->ref_count; shadow_count = obj->shadow_count; - VM_OBJECT_UNLOCK(lobj); + VM_OBJECT_UNLOCK(obj); if (vp) { vn_fullpath(td, vp, &name, &freename); locked = VFS_LOCK_GIANT(vp->v_mount); @@ -1018,7 +1019,7 @@ linprocfs_doprocmaps(PFS_FILL_ARGS) * format: * start, end, access, offset, major, minor, inode, name. */ - snprintf(mebuffer, sizeof mebuffer, + error = sbuf_printf(sb, "%08lx-%08lx %s%s%s%s %08lx %02x:%02x %lu%s%s\n", (u_long)entry->start, (u_long)entry->end, (entry->protection & VM_PROT_READ)?"r":"-", @@ -1034,19 +1035,23 @@ linprocfs_doprocmaps(PFS_FILL_ARGS) ); if (freename) free(freename, M_TEMP); - len = strlen(mebuffer); - if (len > uio->uio_resid) - len = uio->uio_resid; /* - * XXX We should probably return - * EFBIG here, as in procfs. - */ - error = uiomove(mebuffer, len, uio); - if (error) - break; - } - if (map != &curthread->td_proc->p_vmspace->vm_map) + last_timestamp = map->timestamp; vm_map_unlock_read(map); - + if (error == -1) + return (0); + vm_map_lock_read(map); + if (last_timestamp + 1 != map->timestamp) { + /* + * Look again for the entry because the map was + * modified while it was unlocked. Specifically, + * the entry may have been clipped, merged, or deleted. + */ + vm_map_lookup_entry(map, saved_end - 1, &tmp_entry); + entry = tmp_entry; + } + } + vm_map_unlock_read(map); + return (error); }