Print this page
12701 segspt_minfree needs right-sizing
Reviewed by: Jerry Jelinek <jerry.jelinek@joyent.com>
Reviewed by: Patrick Mooney <pmooney@pfmooney.com>


   3  *
   4  * The contents of this file are subject to the terms of the
   5  * Common Development and Distribution License (the "License").
   6  * You may not use this file except in compliance with the License.
   7  *
   8  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
   9  * or http://www.opensolaris.org/os/licensing.
  10  * See the License for the specific language governing permissions
  11  * and limitations under the License.
  12  *
  13  * When distributing Covered Code, include this CDDL HEADER in each
  14  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
  15  * If applicable, add the following below this CDDL HEADER, with the
  16  * fields enclosed by brackets "[]" replaced with your own identifying
  17  * information: Portions Copyright [yyyy] [name of copyright owner]
  18  *
  19  * CDDL HEADER END
  20  */
  21 /*
  22  * Copyright (c) 1993, 2010, Oracle and/or its affiliates. All rights reserved.
  23  * Copyright 2018 Joyent, Inc.
  24  * Copyright (c) 2016 by Delphix. All rights reserved.
  25  */
  26 
  27 #include <sys/param.h>
  28 #include <sys/user.h>
  29 #include <sys/mman.h>
  30 #include <sys/kmem.h>
  31 #include <sys/sysmacros.h>
  32 #include <sys/cmn_err.h>
  33 #include <sys/systm.h>
  34 #include <sys/tuneable.h>
  35 #include <vm/hat.h>
  36 #include <vm/seg.h>
  37 #include <vm/as.h>
  38 #include <vm/anon.h>
  39 #include <vm/page.h>
  40 #include <sys/buf.h>
  41 #include <sys/swap.h>
  42 #include <sys/atomic.h>
  43 #include <vm/seg_spt.h>
  44 #include <sys/debug.h>
  45 #include <sys/vtrace.h>
  46 #include <sys/shm.h>
  47 #include <sys/shm_impl.h>
  48 #include <sys/lgrp.h>
  49 #include <sys/vmsystm.h>
  50 #include <sys/policy.h>
  51 #include <sys/project.h>
  52 #include <sys/tnf_probe.h>
  53 #include <sys/zone.h>
  54 
  55 #define SEGSPTADDR      (caddr_t)0x0
  56 
  57 /*
  58  * # pages used for spt
  59  */
  60 size_t  spt_used;
  61 
  62 /*
  63  * segspt_minfree is the memory left for system after ISM
  64  * locked its pages; it is set up to 5% of availrmem in
  65  * sptcreate when ISM is created.  ISM should not use more
  66  * than ~90% of availrmem; if it does, then the performance
  67  * of the system may decrease. Machines with large memories may
  68  * be able to use up more memory for ISM so we set the default
  69  * segspt_minfree to 5% (which gives ISM max 95% of availrmem.
  70  * If somebody wants even more memory for ISM (risking hanging
  71  * the system) they can patch the segspt_minfree to smaller number.
  72  */
  73 pgcnt_t segspt_minfree = 0;

  74 
  75 static int segspt_create(struct seg **segpp, void *argsp);
  76 static int segspt_unmap(struct seg *seg, caddr_t raddr, size_t ssize);
  77 static void segspt_free(struct seg *seg);
  78 static void segspt_free_pages(struct seg *seg, caddr_t addr, size_t len);
  79 static lgrp_mem_policy_info_t *segspt_getpolicy(struct seg *seg, caddr_t addr);
  80 
  81 /* ARGSUSED */
  82 __NORETURN static int
  83 segspt_badop_dup(struct seg *seg __unused, struct seg *newseg __unused)
  84 {
  85         panic("%s called", __func__);
  86 }
  87 
  88 /* ARGSUSED */
  89 __NORETURN static faultcode_t
  90 segspt_badop_fault(struct hat *hat, struct seg *seg, caddr_t addr,
  91     size_t len, enum fault_type type, enum seg_rw rw)
  92 {
  93         panic("%s called", __func__);


 299         segspt_shmgetprot,
 300         segspt_shmgetoffset,
 301         segspt_shmgettype,
 302         segspt_shmgetvp,
 303         segspt_shmadvise,       /* advise */
 304         segspt_shmdump,
 305         segspt_shmpagelock,
 306         segspt_shmsetpgsz,
 307         segspt_shmgetmemid,
 308         segspt_shmgetpolicy,
 309         segspt_shmcapable,
 310         seg_inherit_notsup
 311 };
 312 
 313 static void segspt_purge(struct seg *seg);
 314 static int segspt_reclaim(void *, caddr_t, size_t, struct page **,
 315                 enum seg_rw, int);
 316 static int spt_anon_getpages(struct seg *seg, caddr_t addr, size_t len,
 317                 page_t **ppa);
 318 





















 319 




 320 
 321 /*ARGSUSED*/
 322 int
 323 sptcreate(size_t size, struct seg **sptseg, struct anon_map *amp,
 324     uint_t prot, uint_t flags, uint_t share_szc)
 325 {
 326         int     err;
 327         struct  as      *newas;
 328         struct  segspt_crargs sptcargs;
 329 
 330 #ifdef DEBUG
 331         TNF_PROBE_1(sptcreate, "spt", /* CSTYLED */,
 332                         tnf_ulong, size, size );
 333 #endif
 334         if (segspt_minfree == 0)        /* leave min 5% of availrmem for */
 335                 segspt_minfree = availrmem/20;  /* for the system */
 336 
 337         if (!hat_supported(HAT_SHARED_PT, (void *)0))
 338                 return (EINVAL);
 339 
 340         /*
 341          * get a new as for this shared memory segment
 342          */
 343         newas = as_alloc();
 344         newas->a_proc = NULL;
 345         sptcargs.amp = amp;
 346         sptcargs.prot = prot;
 347         sptcargs.flags = flags;
 348         sptcargs.szc = share_szc;
 349         /*
 350          * create a shared page table (spt) segment
 351          */
 352 
 353         if (err = as_map(newas, SEGSPTADDR, size, segspt_create, &sptcargs)) {
 354                 as_free(newas);
 355                 return (err);




   3  *
   4  * The contents of this file are subject to the terms of the
   5  * Common Development and Distribution License (the "License").
   6  * You may not use this file except in compliance with the License.
   7  *
   8  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
   9  * or http://www.opensolaris.org/os/licensing.
  10  * See the License for the specific language governing permissions
  11  * and limitations under the License.
  12  *
  13  * When distributing Covered Code, include this CDDL HEADER in each
  14  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
  15  * If applicable, add the following below this CDDL HEADER, with the
  16  * fields enclosed by brackets "[]" replaced with your own identifying
  17  * information: Portions Copyright [yyyy] [name of copyright owner]
  18  *
  19  * CDDL HEADER END
  20  */
  21 /*
  22  * Copyright (c) 1993, 2010, Oracle and/or its affiliates. All rights reserved.
  23  * Copyright 2019 Joyent, Inc.
  24  * Copyright (c) 2016 by Delphix. All rights reserved.
  25  */
  26 
  27 #include <sys/param.h>
  28 #include <sys/user.h>
  29 #include <sys/mman.h>
  30 #include <sys/kmem.h>
  31 #include <sys/sysmacros.h>
  32 #include <sys/cmn_err.h>
  33 #include <sys/systm.h>
  34 #include <sys/tuneable.h>
  35 #include <vm/hat.h>
  36 #include <vm/seg.h>
  37 #include <vm/as.h>
  38 #include <vm/anon.h>
  39 #include <vm/page.h>
  40 #include <sys/buf.h>
  41 #include <sys/swap.h>
  42 #include <sys/atomic.h>
  43 #include <vm/seg_spt.h>
  44 #include <sys/debug.h>
  45 #include <sys/vtrace.h>
  46 #include <sys/shm.h>
  47 #include <sys/shm_impl.h>
  48 #include <sys/lgrp.h>
  49 #include <sys/vmsystm.h>
  50 #include <sys/policy.h>
  51 #include <sys/project.h>
  52 #include <sys/tnf_probe.h>
  53 #include <sys/zone.h>
  54 
  55 #define SEGSPTADDR      (caddr_t)0x0
  56 
  57 /*
  58  * # pages used for spt
  59  */
  60 size_t  spt_used;
  61 
  62 /*
  63  * See spt_setminfree().








  64  */
  65 pgcnt_t segspt_minfree = 0;
  66 size_t segspt_minfree_clamp = (1UL << 30); /* 1GB in bytes */
  67 
  68 static int segspt_create(struct seg **segpp, void *argsp);
  69 static int segspt_unmap(struct seg *seg, caddr_t raddr, size_t ssize);
  70 static void segspt_free(struct seg *seg);
  71 static void segspt_free_pages(struct seg *seg, caddr_t addr, size_t len);
  72 static lgrp_mem_policy_info_t *segspt_getpolicy(struct seg *seg, caddr_t addr);
  73 
  74 /* ARGSUSED */
  75 __NORETURN static int
  76 segspt_badop_dup(struct seg *seg __unused, struct seg *newseg __unused)
  77 {
  78         panic("%s called", __func__);
  79 }
  80 
  81 /* ARGSUSED */
  82 __NORETURN static faultcode_t
  83 segspt_badop_fault(struct hat *hat, struct seg *seg, caddr_t addr,
  84     size_t len, enum fault_type type, enum seg_rw rw)
  85 {
  86         panic("%s called", __func__);


 292         segspt_shmgetprot,
 293         segspt_shmgetoffset,
 294         segspt_shmgettype,
 295         segspt_shmgetvp,
 296         segspt_shmadvise,       /* advise */
 297         segspt_shmdump,
 298         segspt_shmpagelock,
 299         segspt_shmsetpgsz,
 300         segspt_shmgetmemid,
 301         segspt_shmgetpolicy,
 302         segspt_shmcapable,
 303         seg_inherit_notsup
 304 };
 305 
 306 static void segspt_purge(struct seg *seg);
 307 static int segspt_reclaim(void *, caddr_t, size_t, struct page **,
 308                 enum seg_rw, int);
 309 static int spt_anon_getpages(struct seg *seg, caddr_t addr, size_t len,
 310                 page_t **ppa);
 311 
 312 /*
 313  * This value corresponds to headroom in availrmem that ISM can never allocate
 314  * (but others can).  The original intent here was to prevent ISM from locking
 315  * all of the remaining availrmem into memory, making forward progress
 316  * difficult. It's not clear how much this matters on modern systems.
 317  *
 318  * The traditional default value of 5% of total memory is used, except on
 319  * systems where that quickly gets ridiculous: in that case we clamp at a rather
 320  * arbitrary value of 1GB.
 321  *
 322  * Note that since this is called lazily on the first sptcreate(), in theory,
 323  * this could represent a very small value if the system is heavily loaded
 324  * already. In practice, the first ISM user is pretty likely to come along
 325  * earlier during the system's operation.
 326  *
 327  * This never gets re-figured.
 328  */
 329 static void
 330 spt_setminfree(void)
 331 {
 332         segspt_minfree = availrmem / 20;
 333 
 334         if (segspt_minfree_clamp != 0 &&
 335             segspt_minfree > (segspt_minfree_clamp / PAGESIZE))
 336                 segspt_minfree = segspt_minfree_clamp / PAGESIZE;
 337 }
 338 

 339 int
 340 sptcreate(size_t size, struct seg **sptseg, struct anon_map *amp,
 341     uint_t prot, uint_t flags, uint_t share_szc)
 342 {
 343         int     err;
 344         struct  as      *newas;
 345         struct  segspt_crargs sptcargs;
 346 
 347 #ifdef DEBUG
 348         TNF_PROBE_1(sptcreate, "spt", /* CSTYLED */,
 349                         tnf_ulong, size, size );
 350 #endif
 351         if (segspt_minfree == 0)
 352                 spt_setminfree();
 353 
 354         if (!hat_supported(HAT_SHARED_PT, (void *)0))
 355                 return (EINVAL);
 356 
 357         /*
 358          * get a new as for this shared memory segment
 359          */
 360         newas = as_alloc();
 361         newas->a_proc = NULL;
 362         sptcargs.amp = amp;
 363         sptcargs.prot = prot;
 364         sptcargs.flags = flags;
 365         sptcargs.szc = share_szc;
 366         /*
 367          * create a shared page table (spt) segment
 368          */
 369 
 370         if (err = as_map(newas, SEGSPTADDR, size, segspt_create, &sptcargs)) {
 371                 as_free(newas);
 372                 return (err);