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

*** 18,28 **** * * CDDL HEADER END */ /* * Copyright (c) 1993, 2010, Oracle and/or its affiliates. All rights reserved. ! * Copyright 2018 Joyent, Inc. * Copyright (c) 2016 by Delphix. All rights reserved. */ #include <sys/param.h> #include <sys/user.h> --- 18,28 ---- * * CDDL HEADER END */ /* * Copyright (c) 1993, 2010, Oracle and/or its affiliates. All rights reserved. ! * Copyright 2019 Joyent, Inc. * Copyright (c) 2016 by Delphix. All rights reserved. */ #include <sys/param.h> #include <sys/user.h>
*** 58,78 **** * # pages used for spt */ size_t spt_used; /* ! * segspt_minfree is the memory left for system after ISM ! * locked its pages; it is set up to 5% of availrmem in ! * sptcreate when ISM is created. ISM should not use more ! * than ~90% of availrmem; if it does, then the performance ! * of the system may decrease. Machines with large memories may ! * be able to use up more memory for ISM so we set the default ! * segspt_minfree to 5% (which gives ISM max 95% of availrmem. ! * If somebody wants even more memory for ISM (risking hanging ! * the system) they can patch the segspt_minfree to smaller number. */ pgcnt_t segspt_minfree = 0; static int segspt_create(struct seg **segpp, void *argsp); static int segspt_unmap(struct seg *seg, caddr_t raddr, size_t ssize); static void segspt_free(struct seg *seg); static void segspt_free_pages(struct seg *seg, caddr_t addr, size_t len); --- 58,71 ---- * # pages used for spt */ size_t spt_used; /* ! * See spt_setminfree(). */ pgcnt_t segspt_minfree = 0; + size_t segspt_minfree_clamp = (1UL << 30); /* 1GB in bytes */ static int segspt_create(struct seg **segpp, void *argsp); static int segspt_unmap(struct seg *seg, caddr_t raddr, size_t ssize); static void segspt_free(struct seg *seg); static void segspt_free_pages(struct seg *seg, caddr_t addr, size_t len);
*** 314,326 **** static int segspt_reclaim(void *, caddr_t, size_t, struct page **, enum seg_rw, int); static int spt_anon_getpages(struct seg *seg, caddr_t addr, size_t len, page_t **ppa); - /*ARGSUSED*/ int sptcreate(size_t size, struct seg **sptseg, struct anon_map *amp, uint_t prot, uint_t flags, uint_t share_szc) { int err; --- 307,343 ---- static int segspt_reclaim(void *, caddr_t, size_t, struct page **, enum seg_rw, int); static int spt_anon_getpages(struct seg *seg, caddr_t addr, size_t len, page_t **ppa); + /* + * This value corresponds to headroom in availrmem that ISM can never allocate + * (but others can). The original intent here was to prevent ISM from locking + * all of the remaining availrmem into memory, making forward progress + * difficult. It's not clear how much this matters on modern systems. + * + * The traditional default value of 5% of total memory is used, except on + * systems where that quickly gets ridiculous: in that case we clamp at a rather + * arbitrary value of 1GB. + * + * Note that since this is called lazily on the first sptcreate(), in theory, + * this could represent a very small value if the system is heavily loaded + * already. In practice, the first ISM user is pretty likely to come along + * earlier during the system's operation. + * + * This never gets re-figured. + */ + static void + spt_setminfree(void) + { + segspt_minfree = availrmem / 20; + if (segspt_minfree_clamp != 0 && + segspt_minfree > (segspt_minfree_clamp / PAGESIZE)) + segspt_minfree = segspt_minfree_clamp / PAGESIZE; + } int sptcreate(size_t size, struct seg **sptseg, struct anon_map *amp, uint_t prot, uint_t flags, uint_t share_szc) { int err;
*** 329,340 **** #ifdef DEBUG TNF_PROBE_1(sptcreate, "spt", /* CSTYLED */, tnf_ulong, size, size ); #endif ! if (segspt_minfree == 0) /* leave min 5% of availrmem for */ ! segspt_minfree = availrmem/20; /* for the system */ if (!hat_supported(HAT_SHARED_PT, (void *)0)) return (EINVAL); /* --- 346,357 ---- #ifdef DEBUG TNF_PROBE_1(sptcreate, "spt", /* CSTYLED */, tnf_ulong, size, size ); #endif ! if (segspt_minfree == 0) ! spt_setminfree(); if (!hat_supported(HAT_SHARED_PT, (void *)0)) return (EINVAL); /*