summaryrefslogtreecommitdiffstats
path: root/sys/kern/kern_malloc.c
diff options
context:
space:
mode:
authormdf <mdf@FreeBSD.org>2010-09-13 18:48:23 +0000
committermdf <mdf@FreeBSD.org>2010-09-13 18:48:23 +0000
commit3ed6eac561ccce2958e668867ea38fd005bc635b (patch)
treeb0bd953f5f99c28abddea5f8c7bb39d837607940 /sys/kern/kern_malloc.c
parent9a10f7c4328c6763a33844ed9635ef3c2a7f1e84 (diff)
downloadFreeBSD-src-3ed6eac561ccce2958e668867ea38fd005bc635b.zip
FreeBSD-src-3ed6eac561ccce2958e668867ea38fd005bc635b.tar.gz
Revert r212370, as it causes a LOR on powerpc. powerpc does a few
unexpected things in copyout(9) and so wiring the user buffer is not sufficient to perform a copyout(9) while holding a random mutex. Requested by: nwhitehorn
Diffstat (limited to 'sys/kern/kern_malloc.c')
-rw-r--r--sys/kern/kern_malloc.c58
1 files changed, 49 insertions, 9 deletions
diff --git a/sys/kern/kern_malloc.c b/sys/kern/kern_malloc.c
index 6d9b775..1e97b55 100644
--- a/sys/kern/kern_malloc.c
+++ b/sys/kern/kern_malloc.c
@@ -828,11 +828,25 @@ sysctl_kern_malloc_stats(SYSCTL_HANDLER_ARGS)
struct malloc_type_internal *mtip;
struct malloc_type_header mth;
struct malloc_type *mtp;
- int error, i;
+ int buflen, count, error, i;
struct sbuf sbuf;
+ char *buffer;
- sbuf_new_for_sysctl(&sbuf, NULL, 128, req);
mtx_lock(&malloc_mtx);
+restart:
+ mtx_assert(&malloc_mtx, MA_OWNED);
+ count = kmemcount;
+ mtx_unlock(&malloc_mtx);
+ buflen = sizeof(mtsh) + count * (sizeof(mth) +
+ sizeof(struct malloc_type_stats) * MAXCPU) + 1;
+ buffer = malloc(buflen, M_TEMP, M_WAITOK | M_ZERO);
+ mtx_lock(&malloc_mtx);
+ if (count < kmemcount) {
+ free(buffer, M_TEMP);
+ goto restart;
+ }
+
+ sbuf_new(&sbuf, buffer, buflen, SBUF_FIXEDLEN);
/*
* Insert stream header.
@@ -841,7 +855,11 @@ sysctl_kern_malloc_stats(SYSCTL_HANDLER_ARGS)
mtsh.mtsh_version = MALLOC_TYPE_STREAM_VERSION;
mtsh.mtsh_maxcpus = MAXCPU;
mtsh.mtsh_count = kmemcount;
- (void)sbuf_bcat(&sbuf, &mtsh, sizeof(mtsh));
+ if (sbuf_bcat(&sbuf, &mtsh, sizeof(mtsh)) < 0) {
+ mtx_unlock(&malloc_mtx);
+ error = ENOMEM;
+ goto out;
+ }
/*
* Insert alternating sequence of type headers and type statistics.
@@ -854,19 +872,30 @@ sysctl_kern_malloc_stats(SYSCTL_HANDLER_ARGS)
*/
bzero(&mth, sizeof(mth));
strlcpy(mth.mth_name, mtp->ks_shortdesc, MALLOC_MAX_NAME);
- (void)sbuf_bcat(&sbuf, &mth, sizeof(mth));
+ if (sbuf_bcat(&sbuf, &mth, sizeof(mth)) < 0) {
+ mtx_unlock(&malloc_mtx);
+ error = ENOMEM;
+ goto out;
+ }
/*
* Insert type statistics for each CPU.
*/
for (i = 0; i < MAXCPU; i++) {
- (void)sbuf_bcat(&sbuf, &mtip->mti_stats[i],
- sizeof(mtip->mti_stats[i]));
+ if (sbuf_bcat(&sbuf, &mtip->mti_stats[i],
+ sizeof(mtip->mti_stats[i])) < 0) {
+ mtx_unlock(&malloc_mtx);
+ error = ENOMEM;
+ goto out;
+ }
}
}
mtx_unlock(&malloc_mtx);
- error = sbuf_finish(&sbuf);
+ sbuf_finish(&sbuf);
+ error = SYSCTL_OUT(req, sbuf_data(&sbuf), sbuf_len(&sbuf));
+out:
sbuf_delete(&sbuf);
+ free(buffer, M_TEMP);
return (error);
}
@@ -976,19 +1005,26 @@ DB_SHOW_COMMAND(multizone_matches, db_show_multizone_matches)
static int
sysctl_kern_mprof(SYSCTL_HANDLER_ARGS)
{
+ int linesize = 64;
struct sbuf sbuf;
uint64_t count;
uint64_t waste;
uint64_t mem;
+ int bufsize;
int error;
+ char *buf;
int rsize;
int size;
int i;
+ bufsize = linesize * (KMEM_ZSIZE + 1);
+ bufsize += 128; /* For the stats line */
+ bufsize += 128; /* For the banner line */
waste = 0;
mem = 0;
- sbuf_new_for_sysctl(&sbuf, NULL, 128, req);
+ buf = malloc(bufsize, M_TEMP, M_WAITOK|M_ZERO);
+ sbuf_new(&sbuf, buf, bufsize, SBUF_FIXEDLEN);
sbuf_printf(&sbuf,
"\n Size Requests Real Size\n");
for (i = 0; i < KMEM_ZSIZE; i++) {
@@ -1006,8 +1042,12 @@ sysctl_kern_mprof(SYSCTL_HANDLER_ARGS)
sbuf_printf(&sbuf,
"\nTotal memory used:\t%30llu\nTotal Memory wasted:\t%30llu\n",
(unsigned long long)mem, (unsigned long long)waste);
- error = sbuf_finish(&sbuf);
+ sbuf_finish(&sbuf);
+
+ error = SYSCTL_OUT(req, sbuf_data(&sbuf), sbuf_len(&sbuf));
+
sbuf_delete(&sbuf);
+ free(buf, M_TEMP);
return (error);
}
OpenPOWER on IntegriCloud