Print this page

        

*** 18,28 **** * * CDDL HEADER END */ /* * Copyright (c) 1990, 2010, Oracle and/or its affiliates. All rights reserved. ! * Copyright 2016 Joyent, Inc. */ #include <sys/types.h> #include <sys/errno.h> #include <sys/param.h> --- 18,28 ---- * * CDDL HEADER END */ /* * Copyright (c) 1990, 2010, Oracle and/or its affiliates. All rights reserved. ! * Copyright 2015 Joyent, Inc. */ #include <sys/types.h> #include <sys/errno.h> #include <sys/param.h>
*** 41,51 **** #include <sys/policy.h> #include <sys/fs/tmp.h> #include <sys/fs/tmpnode.h> #include <sys/ddi.h> #include <sys/sunddi.h> - #include <vm/anon.h> #define KILOBYTE 1024 #define MEGABYTE (1024 * KILOBYTE) #define GIGABYTE (1024 * MEGABYTE) --- 41,50 ----
*** 53,136 **** #define VALIDMODEBITS 07777 extern pgcnt_t swapfs_minfree; - void * - tmp_kmem_zalloc(struct tmount *tm, size_t size, int flag) - { - void *buf; - zone_t *zone; - size_t pages; - - mutex_enter(&tm->tm_contents); - zone = tm->tm_vfsp->vfs_zone; - if (tm->tm_anonmem + size > tm->tm_anonmax || - tm->tm_anonmem + size < tm->tm_anonmem || - size + ptob(tmpfs_minfree) <= size || - !anon_checkspace(size + ptob(tmpfs_minfree), zone)) { - mutex_exit(&tm->tm_contents); - return (NULL); - } - - /* - * Only make anonymous memory reservations when a page boundary is - * crossed. This is necessary since the anon_resv functions rounds up - * to PAGESIZE internally. - */ - pages = btopr(tm->tm_allocmem + size); - pages -= btopr(tm->tm_allocmem); - if (pages > 0 && anon_try_resv_zone(ptob(pages), zone) == 0) { - mutex_exit(&tm->tm_contents); - return (NULL); - } - - tm->tm_allocmem += size; - tm->tm_anonmem += size; - mutex_exit(&tm->tm_contents); - - buf = kmem_zalloc(size, flag); - if (buf == NULL) { - mutex_enter(&tm->tm_contents); - ASSERT(tm->tm_anonmem > tm->tm_anonmem - size); - tm->tm_anonmem -= size; - if (pages > 0) { - /* - * Re-chasing the zone pointer is necessary since a - * forced umount could have been performed while the - * tm_contents lock was dropped during allocation. - */ - anon_unresv_zone(ptob(pages), tm->tm_vfsp->vfs_zone); - } - mutex_exit(&tm->tm_contents); - } - - return (buf); - } - - void - tmp_kmem_free(struct tmount *tm, void *buf, size_t size) - { - size_t pages; - - kmem_free(buf, size); - mutex_enter(&tm->tm_contents); - ASSERT(tm->tm_anonmem > tm->tm_anonmem - size); - tm->tm_anonmem -= size; - pages = btopr(tm->tm_allocmem); - tm->tm_allocmem -= size; - pages -= btopr(tm->tm_allocmem); - /* - * Like the tmp_kmem_zalloc case, only unreserve anonymous memory when - * a page boundary has been crossed. - */ - if (pages > 0) { - anon_unresv_zone(size, tm->tm_vfsp->vfs_zone); - } - mutex_exit(&tm->tm_contents); - } - int tmp_taccess(void *vtp, int mode, struct cred *cred) { struct tmpnode *tp = vtp; int shift = 0; --- 52,61 ----
*** 172,183 **** return (0); } /* ! * Convert a string containing a number (number of bytes) to a size_t, ! * containing the corresponding number of bytes. On 32-bit kernels, the * maximum value encoded in 'str' is PAGESIZE * ULONG_MAX, while the value * returned in 'maxpg' is at most ULONG_MAX. * * The number may be followed by a magnitude suffix: "k" or "K" for kilobytes; * "m" or "M" for megabytes; "g" or "G" for gigabytes. This interface allows --- 97,142 ---- return (0); } /* ! * Allocate zeroed memory if tmpfs_maxkmem has not been exceeded ! * or the 'musthave' flag is set. 'musthave' allocations should ! * always be subordinate to normal allocations so that tmpfs_maxkmem ! * can't be exceeded by more than a few KB. Example: when creating ! * a new directory, the tmpnode is a normal allocation; if that ! * succeeds, the dirents for "." and ".." are 'musthave' allocations. ! */ ! void * ! tmp_memalloc(size_t size, int musthave) ! { ! static time_t last_warning; ! time_t now; ! ! if (atomic_add_long_nv(&tmp_kmemspace, size) < tmpfs_maxkmem || ! musthave) ! return (kmem_zalloc(size, KM_SLEEP)); ! ! atomic_add_long(&tmp_kmemspace, -size); ! now = gethrestime_sec(); ! if (last_warning != now) { ! last_warning = now; ! cmn_err(CE_WARN, "tmp_memalloc: tmpfs over memory limit"); ! } ! return (NULL); ! } ! ! void ! tmp_memfree(void *cp, size_t size) ! { ! kmem_free(cp, size); ! atomic_add_long(&tmp_kmemspace, -size); ! } ! ! /* ! * Convert a string containing a number (number of bytes) to a pgcnt_t, ! * containing the corresponding number of pages. On 32-bit kernels, the * maximum value encoded in 'str' is PAGESIZE * ULONG_MAX, while the value * returned in 'maxpg' is at most ULONG_MAX. * * The number may be followed by a magnitude suffix: "k" or "K" for kilobytes; * "m" or "M" for megabytes; "g" or "G" for gigabytes. This interface allows
*** 191,206 **** * * Parse and overflow errors are detected and a non-zero number returned on * error. */ int ! tmp_convnum(char *str, size_t *maxbytes) { u_longlong_t num = 0; ! u_longlong_t max_bytes = (uint64_t)SIZE_MAX; ! size_t pages; ! char *c; const struct convchar { char *cc_char; uint64_t cc_factor; } convchars[] = { --- 150,167 ---- * * Parse and overflow errors are detected and a non-zero number returned on * error. */ int ! tmp_convnum(char *str, pgcnt_t *maxpg) { u_longlong_t num = 0; ! #ifdef _LP64 ! u_longlong_t max_bytes = ULONG_MAX; ! #else ! u_longlong_t max_bytes = PAGESIZE * (uint64_t)ULONG_MAX; ! #endif char *c; const struct convchar { char *cc_char; uint64_t cc_factor; } convchars[] = {
*** 286,312 **** valid_char: continue; } done: - /* ! * We've been given a size in bytes; however, we want to make sure that ! * we have at least one page worth no matter what. Therefore we use ! * btopr to round up. However, this may cause an overflow only if 'num' ! * is between (max_bytes - PAGESIZE) and (max_bytes). In this case the ! * resulting number is zero, which is what we check for below. Note, we ! * require at least one page, so if pages is zero, well, it wasn't going ! * to work anyways. */ ! pages = btopr(num); ! if (pages == 0) { return (EINVAL); - } - - *maxbytes = ptob(pages); - return (0); } /* * Parse an octal mode string for use as the permissions set for the root --- 247,264 ---- valid_char: continue; } done: /* ! * Since btopr() rounds up to page granularity, this round-up can ! * cause an overflow only if 'num' is between (max_bytes - PAGESIZE) ! * and (max_bytes). In this case the resulting number is zero, which ! * is what we check for below. */ ! if ((*maxpg = (pgcnt_t)btopr(num)) == 0 && num != 0) return (EINVAL); return (0); } /* * Parse an octal mode string for use as the permissions set for the root