From owner-svn-src-all@freebsd.org Tue Sep 3 20:31:50 2019 Return-Path: Delivered-To: svn-src-all@mailman.nyi.freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2610:1c1:1:606c::19:1]) by mailman.nyi.freebsd.org (Postfix) with ESMTP id 85D00D70C0; Tue, 3 Sep 2019 20:31:50 +0000 (UTC) (envelope-from kevans@FreeBSD.org) Received: from mxrelay.nyi.freebsd.org (mxrelay.nyi.freebsd.org [IPv6:2610:1c1:1:606c::19:3]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) server-signature RSA-PSS (4096 bits) client-signature RSA-PSS (4096 bits) client-digest SHA256) (Client CN "mxrelay.nyi.freebsd.org", Issuer "Let's Encrypt Authority X3" (verified OK)) by mx1.freebsd.org (Postfix) with ESMTPS id 46NJX62wMlz4L4k; Tue, 3 Sep 2019 20:31:50 +0000 (UTC) (envelope-from kevans@FreeBSD.org) Received: from repo.freebsd.org (repo.freebsd.org [IPv6:2610:1c1:1:6068::e6a:0]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (Client did not present a certificate) by mxrelay.nyi.freebsd.org (Postfix) with ESMTPS id 3024D894F; Tue, 3 Sep 2019 20:31:50 +0000 (UTC) (envelope-from kevans@FreeBSD.org) Received: from repo.freebsd.org ([127.0.1.37]) by repo.freebsd.org (8.15.2/8.15.2) with ESMTP id x83KVoaS000119; Tue, 3 Sep 2019 20:31:50 GMT (envelope-from kevans@FreeBSD.org) Received: (from kevans@localhost) by repo.freebsd.org (8.15.2/8.15.2/Submit) id x83KVmGk000110; Tue, 3 Sep 2019 20:31:48 GMT (envelope-from kevans@FreeBSD.org) Message-Id: <201909032031.x83KVmGk000110@repo.freebsd.org> X-Authentication-Warning: repo.freebsd.org: kevans set sender to kevans@FreeBSD.org using -f From: Kyle Evans Date: Tue, 3 Sep 2019 20:31:48 +0000 (UTC) To: src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org Subject: svn commit: r351795 - in head/sys: kern vm X-SVN-Group: head X-SVN-Commit-Author: kevans X-SVN-Commit-Paths: in head/sys: kern vm X-SVN-Commit-Revision: 351795 X-SVN-Commit-Repository: base MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit X-BeenThere: svn-src-all@freebsd.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: "SVN commit messages for the entire src tree \(except for " user" and " projects" \)" List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Tue, 03 Sep 2019 20:31:50 -0000 Author: kevans Date: Tue Sep 3 20:31:48 2019 New Revision: 351795 URL: https://svnweb.freebsd.org/changeset/base/351795 Log: vm pager: writemapping accounting for OBJT_SWAP Currently writemapping accounting is only done for vnode_pager which does some accounting on the underlying vnode. Extend this to allow accounting to be possible for any of the pager types. New pageops are added to update/release writecount that need to be implemented for any pager wishing to do said accounting, and we implement these methods now for both vnode_pager (unchanged) and swap_pager. The primary motivation for this is to allow other systems with OBJT_SWAP objects to check if their objects have any write mappings and reject operations with EBUSY if so. posixshm will be the first to do so in order to reject adding write seals to the shmfd if any writable mappings exist. Reviewed by: kib, markj Differential Revision: https://reviews.freebsd.org/D21456 Modified: head/sys/kern/vfs_vnops.c head/sys/vm/swap_pager.c head/sys/vm/vm_map.c head/sys/vm/vm_map.h head/sys/vm/vm_mmap.c head/sys/vm/vm_object.h head/sys/vm/vm_pager.h head/sys/vm/vnode_pager.c head/sys/vm/vnode_pager.h Modified: head/sys/kern/vfs_vnops.c ============================================================================== --- head/sys/kern/vfs_vnops.c Tue Sep 3 20:26:08 2019 (r351794) +++ head/sys/kern/vfs_vnops.c Tue Sep 3 20:31:48 2019 (r351795) @@ -87,7 +87,7 @@ __FBSDID("$FreeBSD$"); #include #include #include -#include +#include #ifdef HWPMC_HOOKS #include @@ -2502,7 +2502,7 @@ vn_mmap(struct file *fp, vm_map_t map, vm_offset_t *ad * writecount, then undo that now. */ if (writecounted) - vnode_pager_release_writecount(object, 0, size); + vm_pager_release_writecount(object, 0, size); vm_object_deallocate(object); } #ifdef HWPMC_HOOKS Modified: head/sys/vm/swap_pager.c ============================================================================== --- head/sys/vm/swap_pager.c Tue Sep 3 20:26:08 2019 (r351794) +++ head/sys/vm/swap_pager.c Tue Sep 3 20:31:48 2019 (r351795) @@ -376,6 +376,10 @@ static boolean_t static void swap_pager_init(void); static void swap_pager_unswapped(vm_page_t); static void swap_pager_swapoff(struct swdevt *sp); +static void swap_pager_update_writecount(vm_object_t object, + vm_offset_t start, vm_offset_t end); +static void swap_pager_release_writecount(vm_object_t object, + vm_offset_t start, vm_offset_t end); struct pagerops swappagerops = { .pgo_init = swap_pager_init, /* early system initialization of pager */ @@ -386,6 +390,8 @@ struct pagerops swappagerops = { .pgo_putpages = swap_pager_putpages, /* pageout */ .pgo_haspage = swap_pager_haspage, /* get backing store status for page */ .pgo_pageunswapped = swap_pager_unswapped, /* remove swap related to page */ + .pgo_update_writecount = swap_pager_update_writecount, + .pgo_release_writecount = swap_pager_release_writecount, }; /* @@ -611,6 +617,7 @@ swap_pager_alloc_init(void *handle, struct ucred *cred object = vm_object_allocate(OBJT_SWAP, OFF_TO_IDX(offset + PAGE_MASK + size)); + object->un_pager.swp.writemappings = 0; object->handle = handle; if (cred != NULL) { object->cred = cred; @@ -1903,6 +1910,7 @@ swp_pager_meta_build(vm_object_t object, vm_pindex_t p atomic_thread_fence_rel(); object->type = OBJT_SWAP; + object->un_pager.swp.writemappings = 0; KASSERT(object->handle == NULL, ("default pager with handle")); } @@ -2990,4 +2998,28 @@ sysctl_swap_async_max(SYSCTL_HANDLER_ARGS) mtx_unlock(&swbuf_mtx); return (0); +} + +static void +swap_pager_update_writecount(vm_object_t object, vm_offset_t start, + vm_offset_t end) +{ + + VM_OBJECT_WLOCK(object); + KASSERT((object->flags & OBJ_NOSPLIT) != 0, + ("Splittable object with writecount")); + object->un_pager.swp.writemappings += (vm_ooffset_t)end - start; + VM_OBJECT_WUNLOCK(object); +} + +static void +swap_pager_release_writecount(vm_object_t object, vm_offset_t start, + vm_offset_t end) +{ + + VM_OBJECT_WLOCK(object); + KASSERT((object->flags & OBJ_NOSPLIT) != 0, + ("Splittable object with writecount")); + object->un_pager.swp.writemappings -= (vm_ooffset_t)end - start; + VM_OBJECT_WUNLOCK(object); } Modified: head/sys/vm/vm_map.c ============================================================================== --- head/sys/vm/vm_map.c Tue Sep 3 20:26:08 2019 (r351794) +++ head/sys/vm/vm_map.c Tue Sep 3 20:31:48 2019 (r351795) @@ -575,10 +575,10 @@ vm_map_process_deferred(void) td->td_map_def_user = NULL; while (entry != NULL) { next = entry->next; - MPASS((entry->eflags & (MAP_ENTRY_VN_WRITECNT | - MAP_ENTRY_VN_EXEC)) != (MAP_ENTRY_VN_WRITECNT | + MPASS((entry->eflags & (MAP_ENTRY_WRITECNT | + MAP_ENTRY_VN_EXEC)) != (MAP_ENTRY_WRITECNT | MAP_ENTRY_VN_EXEC)); - if ((entry->eflags & MAP_ENTRY_VN_WRITECNT) != 0) { + if ((entry->eflags & MAP_ENTRY_WRITECNT) != 0) { /* * Decrement the object's writemappings and * possibly the vnode's v_writecount. @@ -587,7 +587,7 @@ vm_map_process_deferred(void) ("Submap with writecount")); object = entry->object.vm_object; KASSERT(object != NULL, ("No object for writecount")); - vnode_pager_release_writecount(object, entry->start, + vm_pager_release_writecount(object, entry->start, entry->end); } vm_map_entry_set_vnode_text(entry, false); @@ -1481,8 +1481,8 @@ vm_map_insert(vm_map_t map, vm_object_t object, vm_oof protoeflags |= MAP_ENTRY_GROWS_DOWN; if (cow & MAP_STACK_GROWS_UP) protoeflags |= MAP_ENTRY_GROWS_UP; - if (cow & MAP_VN_WRITECOUNT) - protoeflags |= MAP_ENTRY_VN_WRITECNT; + if (cow & MAP_WRITECOUNT) + protoeflags |= MAP_ENTRY_WRITECNT; if (cow & MAP_VN_EXEC) protoeflags |= MAP_ENTRY_VN_EXEC; if ((cow & MAP_CREATE_GUARD) != 0) @@ -2211,7 +2211,7 @@ _vm_map_clip_start(vm_map_t map, vm_map_entry_t entry, vm_map_entry_set_vnode_text(new_entry, true); /* * The object->un_pager.vnp.writemappings for the - * object of MAP_ENTRY_VN_WRITECNT type entry shall be + * object of MAP_ENTRY_WRITECNT type entry shall be * kept as is here. The virtual pages are * re-distributed among the clipped entries, so the sum is * left the same. @@ -3783,20 +3783,20 @@ vm_map_copy_entry( dst_entry->eflags |= MAP_ENTRY_COW | MAP_ENTRY_NEEDS_COPY; dst_entry->offset = src_entry->offset; - if (src_entry->eflags & MAP_ENTRY_VN_WRITECNT) { + if (src_entry->eflags & MAP_ENTRY_WRITECNT) { /* - * MAP_ENTRY_VN_WRITECNT cannot + * MAP_ENTRY_WRITECNT cannot * indicate write reference from * src_entry, since the entry is * marked as needs copy. Allocate a * fake entry that is used to - * decrement object->un_pager.vnp.writecount + * decrement object->un_pager writecount * at the appropriate time. Attach * fake_entry to the deferred list. */ fake_entry = vm_map_entry_create(dst_map); - fake_entry->eflags = MAP_ENTRY_VN_WRITECNT; - src_entry->eflags &= ~MAP_ENTRY_VN_WRITECNT; + fake_entry->eflags = MAP_ENTRY_WRITECNT; + src_entry->eflags &= ~MAP_ENTRY_WRITECNT; vm_object_reference(src_object); fake_entry->object.vm_object = src_object; fake_entry->start = src_entry->start; @@ -3971,7 +3971,7 @@ vmspace_fork(struct vmspace *vm1, vm_ooffset_t *fork_c * not relock it later for the assertion * correctness. */ - if (old_entry->eflags & MAP_ENTRY_VN_WRITECNT && + if (old_entry->eflags & MAP_ENTRY_WRITECNT && object->type == OBJT_VNODE) { KASSERT(((struct vnode *)object->handle)-> v_writecount > 0, @@ -3991,8 +3991,8 @@ vmspace_fork(struct vmspace *vm1, vm_ooffset_t *fork_c MAP_ENTRY_IN_TRANSITION); new_entry->wiring_thread = NULL; new_entry->wired_count = 0; - if (new_entry->eflags & MAP_ENTRY_VN_WRITECNT) { - vnode_pager_update_writecount(object, + if (new_entry->eflags & MAP_ENTRY_WRITECNT) { + vm_pager_update_writecount(object, new_entry->start, new_entry->end); } vm_map_entry_set_vnode_text(new_entry, true); @@ -4023,7 +4023,7 @@ vmspace_fork(struct vmspace *vm1, vm_ooffset_t *fork_c * Copied entry is COW over the old object. */ new_entry->eflags &= ~(MAP_ENTRY_USER_WIRED | - MAP_ENTRY_IN_TRANSITION | MAP_ENTRY_VN_WRITECNT); + MAP_ENTRY_IN_TRANSITION | MAP_ENTRY_WRITECNT); new_entry->wiring_thread = NULL; new_entry->wired_count = 0; new_entry->object.vm_object = NULL; @@ -4047,7 +4047,7 @@ vmspace_fork(struct vmspace *vm1, vm_ooffset_t *fork_c new_entry->end = old_entry->end; new_entry->eflags = old_entry->eflags & ~(MAP_ENTRY_USER_WIRED | MAP_ENTRY_IN_TRANSITION | - MAP_ENTRY_VN_WRITECNT | MAP_ENTRY_VN_EXEC); + MAP_ENTRY_WRITECNT | MAP_ENTRY_VN_EXEC); new_entry->protection = old_entry->protection; new_entry->max_protection = old_entry->max_protection; new_entry->inheritance = VM_INHERIT_ZERO; Modified: head/sys/vm/vm_map.h ============================================================================== --- head/sys/vm/vm_map.h Tue Sep 3 20:26:08 2019 (r351794) +++ head/sys/vm/vm_map.h Tue Sep 3 20:31:48 2019 (r351795) @@ -144,7 +144,7 @@ struct vm_map_entry { #define MAP_ENTRY_GROWS_UP 0x00002000 /* bottom-up stacks */ #define MAP_ENTRY_WIRE_SKIPPED 0x00004000 -#define MAP_ENTRY_VN_WRITECNT 0x00008000 /* writeable vnode +#define MAP_ENTRY_WRITECNT 0x00008000 /* tracked writeable mapping */ #define MAP_ENTRY_GUARD 0x00010000 #define MAP_ENTRY_STACK_GAP_DN 0x00020000 @@ -348,7 +348,7 @@ long vmspace_resident_count(struct vmspace *vmspace); #define MAP_CREATE_GUARD 0x00000080 #define MAP_DISABLE_COREDUMP 0x00000100 #define MAP_PREFAULT_MADVISE 0x00000200 /* from (user) madvise request */ -#define MAP_VN_WRITECOUNT 0x00000400 +#define MAP_WRITECOUNT 0x00000400 #define MAP_REMAP 0x00000800 #define MAP_STACK_GROWS_DOWN 0x00001000 #define MAP_STACK_GROWS_UP 0x00002000 Modified: head/sys/vm/vm_mmap.c ============================================================================== --- head/sys/vm/vm_mmap.c Tue Sep 3 20:26:08 2019 (r351794) +++ head/sys/vm/vm_mmap.c Tue Sep 3 20:31:48 2019 (r351795) @@ -1289,7 +1289,7 @@ vm_mmap_vnode(struct thread *td, vm_size_t objsize, } if (writex) { *writecounted = TRUE; - vnode_pager_update_writecount(obj, 0, objsize); + vm_pager_update_writecount(obj, 0, objsize); } } else { error = EINVAL; @@ -1345,7 +1345,7 @@ vm_mmap_vnode(struct thread *td, vm_size_t objsize, done: if (error != 0 && *writecounted) { *writecounted = FALSE; - vnode_pager_update_writecount(obj, objsize, 0); + vm_pager_update_writecount(obj, objsize, 0); } vput(vp); return (error); @@ -1480,7 +1480,7 @@ vm_mmap(vm_map_t map, vm_offset_t *addr, vm_size_t siz * writecount, then undo that now. */ if (writecounted) - vnode_pager_release_writecount(object, 0, size); + vm_pager_release_writecount(object, 0, size); vm_object_deallocate(object); } return (error); @@ -1569,7 +1569,7 @@ vm_mmap_object(vm_map_t map, vm_offset_t *addr, vm_siz if (flags & MAP_SHARED) docow |= MAP_INHERIT_SHARE; if (writecounted) - docow |= MAP_VN_WRITECOUNT; + docow |= MAP_WRITECOUNT; if (flags & MAP_STACK) { if (object != NULL) return (EINVAL); Modified: head/sys/vm/vm_object.h ============================================================================== --- head/sys/vm/vm_object.h Tue Sep 3 20:26:08 2019 (r351794) +++ head/sys/vm/vm_object.h Tue Sep 3 20:31:48 2019 (r351795) @@ -167,6 +167,7 @@ struct vm_object { struct { void *swp_tmpfs; struct pctrie swp_blks; + vm_ooffset_t writemappings; } swp; } un_pager; struct ucred *cred; Modified: head/sys/vm/vm_pager.h ============================================================================== --- head/sys/vm/vm_pager.h Tue Sep 3 20:26:08 2019 (r351794) +++ head/sys/vm/vm_pager.h Tue Sep 3 20:31:48 2019 (r351795) @@ -61,6 +61,7 @@ typedef boolean_t pgo_haspage_t(vm_object_t, vm_pindex typedef int pgo_populate_t(vm_object_t, vm_pindex_t, int, vm_prot_t, vm_pindex_t *, vm_pindex_t *); typedef void pgo_pageunswapped_t(vm_page_t); +typedef void pgo_writecount_t(vm_object_t, vm_offset_t, vm_offset_t); struct pagerops { pgo_init_t *pgo_init; /* Initialize pager. */ @@ -72,6 +73,9 @@ struct pagerops { pgo_haspage_t *pgo_haspage; /* Query page. */ pgo_populate_t *pgo_populate; /* Bulk spec pagein. */ pgo_pageunswapped_t *pgo_pageunswapped; + /* Operations for specialized writecount handling */ + pgo_writecount_t *pgo_update_writecount; + pgo_writecount_t *pgo_release_writecount; }; extern struct pagerops defaultpagerops; @@ -190,6 +194,26 @@ vm_pager_page_unswapped(vm_page_t m) VM_OBJECT_ASSERT_LOCKED(m->object); if (pagertab[m->object->type]->pgo_pageunswapped) (*pagertab[m->object->type]->pgo_pageunswapped)(m); +} + +static __inline void +vm_pager_update_writecount(vm_object_t object, vm_offset_t start, + vm_offset_t end) +{ + + if (pagertab[object->type]->pgo_update_writecount) + pagertab[object->type]->pgo_update_writecount(object, start, + end); +} + +static __inline void +vm_pager_release_writecount(vm_object_t object, vm_offset_t start, + vm_offset_t end) +{ + + if (pagertab[object->type]->pgo_release_writecount) + pagertab[object->type]->pgo_release_writecount(object, start, + end); } struct cdev_pager_ops { Modified: head/sys/vm/vnode_pager.c ============================================================================== --- head/sys/vm/vnode_pager.c Tue Sep 3 20:26:08 2019 (r351794) +++ head/sys/vm/vnode_pager.c Tue Sep 3 20:31:48 2019 (r351795) @@ -100,6 +100,10 @@ static vm_object_t vnode_pager_alloc(void *, vm_ooffse vm_ooffset_t, struct ucred *cred); static int vnode_pager_generic_getpages_done(struct buf *); static void vnode_pager_generic_getpages_done_async(struct buf *); +static void vnode_pager_update_writecount(vm_object_t, vm_offset_t, + vm_offset_t); +static void vnode_pager_release_writecount(vm_object_t, vm_offset_t, + vm_offset_t); struct pagerops vnodepagerops = { .pgo_alloc = vnode_pager_alloc, @@ -108,6 +112,8 @@ struct pagerops vnodepagerops = { .pgo_getpages_async = vnode_pager_getpages_async, .pgo_putpages = vnode_pager_putpages, .pgo_haspage = vnode_pager_haspage, + .pgo_update_writecount = vnode_pager_update_writecount, + .pgo_release_writecount = vnode_pager_release_writecount, }; static struct domainset *vnode_domainset = NULL; @@ -1500,7 +1506,7 @@ done: VM_OBJECT_WUNLOCK(obj); } -void +static void vnode_pager_update_writecount(vm_object_t object, vm_offset_t start, vm_offset_t end) { @@ -1529,7 +1535,7 @@ vnode_pager_update_writecount(vm_object_t object, vm_o VM_OBJECT_WUNLOCK(object); } -void +static void vnode_pager_release_writecount(vm_object_t object, vm_offset_t start, vm_offset_t end) { Modified: head/sys/vm/vnode_pager.h ============================================================================== --- head/sys/vm/vnode_pager.h Tue Sep 3 20:26:08 2019 (r351794) +++ head/sys/vm/vnode_pager.h Tue Sep 3 20:31:48 2019 (r351795) @@ -50,12 +50,8 @@ int vnode_pager_generic_putpages(struct vnode *vp, vm_ int vnode_pager_local_getpages(struct vop_getpages_args *ap); int vnode_pager_local_getpages_async(struct vop_getpages_async_args *ap); int vnode_pager_putpages_ioflags(int pager_flags); -void vnode_pager_release_writecount(vm_object_t object, vm_offset_t start, - vm_offset_t end); void vnode_pager_undirty_pages(vm_page_t *ma, int *rtvals, int written, off_t eof, int lpos); -void vnode_pager_update_writecount(vm_object_t object, vm_offset_t start, - vm_offset_t end); #endif /* _KERNEL */ #endif /* _VNODE_PAGER_ */