From 9d0ac662182643f3b6579f48816de772cb77b47c Mon Sep 17 00:00:00 2001 From: John Levon Date: Thu, 19 Jul 2018 02:27:08 +0000 Subject: 9060 ::dtrace_options causes mdb to dump core Reviewed by: Jerry Jelinek Reviewed by: Yuri Pankov Approved by: Dan McDonald --- usr/src/cmd/mdb/common/modules/dtrace/dtrace.c | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/usr/src/cmd/mdb/common/modules/dtrace/dtrace.c b/usr/src/cmd/mdb/common/modules/dtrace/dtrace.c index c9ae9876b1..b2ff5d9671 100644 --- a/usr/src/cmd/mdb/common/modules/dtrace/dtrace.c +++ b/usr/src/cmd/mdb/common/modules/dtrace/dtrace.c @@ -22,7 +22,7 @@ /* * Copyright (c) 2003, 2010, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2013 by Delphix. All rights reserved. - * Copyright (c) 2017, Joyent, Inc. All rights reserved. + * Copyright (c) 2018, Joyent, Inc. All rights reserved. */ /* @@ -2517,9 +2517,16 @@ static struct dtrace_options { { "aggsortkey", dtrace_options_numtostr }, { "aggsortrev", dtrace_options_numtostr }, { "aggsortpos", dtrace_options_numtostr }, - { "aggsortkeypos", dtrace_options_numtostr } + { "aggsortkeypos", dtrace_options_numtostr }, + { "temporal", dtrace_options_numtostr }, + { "agghist", dtrace_options_numtostr }, + { "aggpack", dtrace_options_numtostr }, + { "aggzoom", dtrace_options_numtostr }, + { "zone", dtrace_options_numtostr } }; +CTASSERT(ARRAY_SIZE(_dtrace_options) == DTRACEOPT_MAX); + static void dtrace_options_help(void) { -- cgit v1.2.3 From 11f6a9680e013a7c9c57dc0b64d3e91e2eee1a6b Mon Sep 17 00:00:00 2001 From: Serapheim Dimitropoulos Date: Tue, 12 Jun 2018 15:34:20 -0700 Subject: 9591 ms_shift can be incorrectly changed in MOS config for indirect vdevs that have been historically expanded Reviewed by: Matthew Ahrens Reviewed by: George Wilson Reviewed by: John Kennedy Reviewed by: Prashanth Sreenivasa Reviewed by: Tim Chase Approved by: Richard Lowe --- usr/src/pkg/manifests/system-test-zfstest.mf | 3 +- .../zfs-tests/tests/functional/removal/Makefile | 51 +------------ .../tests/functional/removal/remove_expanded.ksh | 89 ++++++++++++++++++++++ usr/src/uts/common/fs/zfs/spa_config.c | 14 +++- usr/src/uts/common/fs/zfs/vdev.c | 4 +- 5 files changed, 109 insertions(+), 52 deletions(-) create mode 100644 usr/src/test/zfs-tests/tests/functional/removal/remove_expanded.ksh diff --git a/usr/src/pkg/manifests/system-test-zfstest.mf b/usr/src/pkg/manifests/system-test-zfstest.mf index 140fc1221e..681c719275 100644 --- a/usr/src/pkg/manifests/system-test-zfstest.mf +++ b/usr/src/pkg/manifests/system-test-zfstest.mf @@ -2365,7 +2365,7 @@ file path=opt/zfs-tests/tests/functional/refreserv/refreserv_004_pos mode=0555 file path=opt/zfs-tests/tests/functional/refreserv/refreserv_005_pos mode=0555 file path=opt/zfs-tests/tests/functional/refreserv/setup mode=0555 file path=opt/zfs-tests/tests/functional/removal/cleanup mode=0555 -file path=opt/zfs-tests/tests/functional/removal/removal.kshlib mode=0555 +file path=opt/zfs-tests/tests/functional/removal/removal.kshlib mode=0444 file path=opt/zfs-tests/tests/functional/removal/removal_all_vdev mode=0555 file path=opt/zfs-tests/tests/functional/removal/removal_check_space mode=0555 file path=opt/zfs-tests/tests/functional/removal/removal_condense_export \ @@ -2396,6 +2396,7 @@ file path=opt/zfs-tests/tests/functional/removal/removal_with_snapshot \ mode=0555 file path=opt/zfs-tests/tests/functional/removal/removal_with_write mode=0555 file path=opt/zfs-tests/tests/functional/removal/removal_with_zdb mode=0555 +file path=opt/zfs-tests/tests/functional/removal/remove_expanded mode=0555 file path=opt/zfs-tests/tests/functional/removal/remove_mirror mode=0555 file path=opt/zfs-tests/tests/functional/removal/remove_mirror_sanity \ mode=0555 diff --git a/usr/src/test/zfs-tests/tests/functional/removal/Makefile b/usr/src/test/zfs-tests/tests/functional/removal/Makefile index b4b9fa0031..f889ceb372 100644 --- a/usr/src/test/zfs-tests/tests/functional/removal/Makefile +++ b/usr/src/test/zfs-tests/tests/functional/removal/Makefile @@ -10,57 +10,12 @@ # # -# Copyright (c) 2014, 2017 by Delphix. All rights reserved. +# Copyright (c) 2014, 2018 by Delphix. All rights reserved. # include $(SRC)/Makefile.master ROOTOPTPKG = $(ROOT)/opt/zfs-tests -TESTDIR = $(ROOTOPTPKG)/tests/functional/removal +TARGETDIR = $(ROOTOPTPKG)/tests/functional/removal -PROGS = cleanup \ - removal_all_vdev \ - removal_check_space \ - removal_condense_export \ - removal_multiple_indirection \ - removal_remap \ - removal_reservation \ - removal_sanity \ - removal_remap_deadlists \ - removal_with_add \ - removal_with_create_fs \ - removal_with_dedup \ - removal_with_export \ - removal_with_ganging \ - removal_with_remap \ - removal_with_remove \ - removal_with_scrub \ - removal_with_send \ - removal_with_send_recv \ - removal_with_snapshot \ - removal_with_write \ - removal_with_zdb \ - removal_resume_export \ - remove_mirror \ - remove_mirror_sanity \ - remove_raidz - -FILES = removal.kshlib - -CMDS = $(PROGS:%=$(TESTDIR)/%) $(FILES:%=$(TESTDIR)/%) -$(CMDS) := FILEMODE = 0555 - -all lint clean clobber: - -install: $(CMDS) - -$(CMDS): $(TESTDIR) - -$(TESTDIR): - $(INS.dir) - -$(TESTDIR)/%: %.ksh - $(INS.rename) - -$(TESTDIR)/%: % - $(INS.file) +include $(SRC)/test/zfs-tests/Makefile.com diff --git a/usr/src/test/zfs-tests/tests/functional/removal/remove_expanded.ksh b/usr/src/test/zfs-tests/tests/functional/removal/remove_expanded.ksh new file mode 100644 index 0000000000..9beb84e591 --- /dev/null +++ b/usr/src/test/zfs-tests/tests/functional/removal/remove_expanded.ksh @@ -0,0 +1,89 @@ +#! /bin/ksh -p +# +# CDDL HEADER START +# +# This file and its contents are supplied under the terms of the +# Common Development and Distribution License ("CDDL"), version 1.0. +# You may only use this file in accordance with the terms of version +# 1.0 of the CDDL. +# +# A full copy of the text of the CDDL should have accompanied this +# source. A copy of the CDDL is also available via the Internet at +# http://www.illumos.org/license/CDDL. +# +# CDDL HEADER END +# + +# +# Copyright (c) 2018 by Delphix. All rights reserved. +# + +. $STF_SUITE/include/libtest.shlib +. $STF_SUITE/tests/functional/removal/removal.kshlib + +# +# BACKGROUND: +# +# ztest hit an issue where it ran zdb and zdb failed because +# it couldn't access some indirect mappings at the end of a +# vdev. The issue was that the vdev's ms_shift had changed after +# it was removed by the addition of another vdev. This test is +# a regression test for ensuring this case doesn't come up again. +# + + +TMPDIR=${TMPDIR:-/tmp} +DISK0=$TMPDIR/dsk0 +DISK1=$TMPDIR/dsk1 +DISK2=$TMPDIR/dsk2 + +log_must mkfile -n $MINVDEVSIZE $DISK0 +log_must mkfile -n $(($MINVDEVSIZE * 3)) $DISK1 +log_must mkfile -n $MINVDEVSIZE $DISK2 + +function cleanup +{ + default_cleanup_noexit + log_must rm -f $DISK0 $DISK1 $DISK2 +} + +# +# Setup the pool with one disk . +# +log_must default_setup_noexit "$DISK0" +log_onexit cleanup + +# +# Expand vdev. +# +log_must truncate -s $(($MINVDEVSIZE * 2)) $DISK0 +log_must zpool reopen $TESTPOOL +log_must zpool online -e $TESTPOOL $DISK0 + +# +# Fill up the whole vdev. +# +dd if=/dev/urandom of=$TESTDIR/$TESTFILE0 bs=8M + +# +# Add another vdev and remove the first vdev creating indirect +# mappings for nearly all the allocatable space from the first +# vdev. Wait for removal to finish. +# +log_must zpool add $TESTPOOL $DISK1 +log_must zpool remove $TESTPOOL $DISK0 +log_must wait_for_removal $TESTPOOL + +# +# Add a new vdev that will trigger a change in the config. +# Run sync once to ensure that the config actually changed. +# +log_must zpool add $TESTPOOL $DISK2 +log_must sync + +# +# Ensure that zdb does not find any problems with this. +# +log_must zdb $TESTPOOL + +log_pass "Removal of expanded vdev doesn't cause any problems." diff --git a/usr/src/uts/common/fs/zfs/spa_config.c b/usr/src/uts/common/fs/zfs/spa_config.c index 1fe675337f..7d568ffcf8 100644 --- a/usr/src/uts/common/fs/zfs/spa_config.c +++ b/usr/src/uts/common/fs/zfs/spa_config.c @@ -22,7 +22,7 @@ /* * Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved. * Copyright 2011 Nexenta Systems, Inc. All rights reserved. - * Copyright (c) 2011, 2015 by Delphix. All rights reserved. + * Copyright (c) 2011, 2018 by Delphix. All rights reserved. * Copyright 2017 Joyent, Inc. */ @@ -510,6 +510,18 @@ spa_config_update(spa_t *spa, int what) */ for (c = 0; c < rvd->vdev_children; c++) { vdev_t *tvd = rvd->vdev_child[c]; + + /* + * Explicitly skip vdevs that are indirect or + * log vdevs that are being removed. The reason + * is that both of those can have vdev_ms_array + * set to 0 and we wouldn't want to change their + * metaslab size nor call vdev_expand() on them. + */ + if (!vdev_is_concrete(tvd) || + (tvd->vdev_islog && tvd->vdev_removing)) + continue; + if (tvd->vdev_ms_array == 0) vdev_metaslab_set_size(tvd); vdev_expand(tvd, txg); diff --git a/usr/src/uts/common/fs/zfs/vdev.c b/usr/src/uts/common/fs/zfs/vdev.c index 43c6e4c9a1..f6845f3dcb 100644 --- a/usr/src/uts/common/fs/zfs/vdev.c +++ b/usr/src/uts/common/fs/zfs/vdev.c @@ -4086,11 +4086,11 @@ vdev_expand(vdev_t *vd, uint64_t txg) { ASSERT(vd->vdev_top == vd); ASSERT(spa_config_held(vd->vdev_spa, SCL_ALL, RW_WRITER) == SCL_ALL); + ASSERT(vdev_is_concrete(vd)); vdev_set_deflate_ratio(vd); - if ((vd->vdev_asize >> vd->vdev_ms_shift) > vd->vdev_ms_count && - vdev_is_concrete(vd)) { + if ((vd->vdev_asize >> vd->vdev_ms_shift) > vd->vdev_ms_count) { VERIFY(vdev_metaslab_init(vd, txg) == 0); vdev_config_dirty(vd); } -- cgit v1.2.3 From c2919acbea007fa95c709b60d073db9a24526e01 Mon Sep 17 00:00:00 2001 From: Matthew Ahrens Date: Thu, 31 May 2018 10:29:12 -0700 Subject: 9577 remove zfs_dbuf_evict_key tsd Reviewed by: George Wilson Reviewed by: Serapheim Dimitropoulos Reviewed by: Brian Behlendorf Reviewed by: Andy Stormont Approved by: Richard Lowe --- usr/src/uts/common/fs/zfs/dbuf.c | 69 ++++++++++++---------------------- usr/src/uts/common/fs/zfs/dnode.c | 7 ++-- usr/src/uts/common/fs/zfs/dnode_sync.c | 17 ++++++++- usr/src/uts/common/fs/zfs/sys/dbuf.h | 4 +- usr/src/uts/common/fs/zfs/sys/dnode.h | 4 +- 5 files changed, 46 insertions(+), 55 deletions(-) diff --git a/usr/src/uts/common/fs/zfs/dbuf.c b/usr/src/uts/common/fs/zfs/dbuf.c index bd430b381b..4fcf14fba5 100644 --- a/usr/src/uts/common/fs/zfs/dbuf.c +++ b/usr/src/uts/common/fs/zfs/dbuf.c @@ -51,8 +51,6 @@ #include #include -uint_t zfs_dbuf_evict_key; - static boolean_t dbuf_undirty(dmu_buf_impl_t *db, dmu_tx_t *tx); static void dbuf_write(dbuf_dirty_record_t *dr, arc_buf_t *data, dmu_tx_t *tx); @@ -524,14 +522,6 @@ dbuf_evict_one(void) ASSERT(!MUTEX_HELD(&dbuf_evict_lock)); - /* - * Set the thread's tsd to indicate that it's processing evictions. - * Once a thread stops evicting from the dbuf cache it will - * reset its tsd to NULL. - */ - ASSERT3P(tsd_get(zfs_dbuf_evict_key), ==, NULL); - (void) tsd_set(zfs_dbuf_evict_key, (void *)B_TRUE); - dmu_buf_impl_t *db = multilist_sublist_tail(mls); while (db != NULL && mutex_tryenter(&db->db_mtx) == 0) { db = multilist_sublist_prev(mls, db); @@ -551,7 +541,6 @@ dbuf_evict_one(void) } else { multilist_sublist_unlock(mls); } - (void) tsd_set(zfs_dbuf_evict_key, NULL); } /* @@ -605,29 +594,6 @@ dbuf_evict_thread(void *unused) static void dbuf_evict_notify(void) { - - /* - * We use thread specific data to track when a thread has - * started processing evictions. This allows us to avoid deeply - * nested stacks that would have a call flow similar to this: - * - * dbuf_rele()-->dbuf_rele_and_unlock()-->dbuf_evict_notify() - * ^ | - * | | - * +-----dbuf_destroy()<--dbuf_evict_one()<--------+ - * - * The dbuf_eviction_thread will always have its tsd set until - * that thread exits. All other threads will only set their tsd - * if they are participating in the eviction process. This only - * happens if the eviction thread is unable to process evictions - * fast enough. To keep the dbuf cache size in check, other threads - * can evict from the dbuf cache directly. Those threads will set - * their tsd values so that we ensure that they only evict one dbuf - * from the dbuf cache. - */ - if (tsd_get(zfs_dbuf_evict_key) != NULL) - return; - /* * We check if we should evict without holding the dbuf_evict_lock, * because it's OK to occasionally make the wrong decision here, @@ -704,7 +670,6 @@ retry: refcount_create(&dbuf_caches[dcs].size); } - tsd_create(&zfs_dbuf_evict_key, NULL); dbuf_evict_thread_exit = B_FALSE; mutex_init(&dbuf_evict_lock, NULL, MUTEX_DEFAULT, NULL); cv_init(&dbuf_evict_cv, NULL, CV_DEFAULT, NULL); @@ -731,7 +696,6 @@ dbuf_fini(void) cv_wait(&dbuf_evict_cv, &dbuf_evict_lock); } mutex_exit(&dbuf_evict_lock); - tsd_destroy(&zfs_dbuf_evict_key); mutex_destroy(&dbuf_evict_lock); cv_destroy(&dbuf_evict_cv); @@ -1011,7 +975,7 @@ dbuf_read_done(zio_t *zio, arc_buf_t *buf, void *vdb) db->db_state = DB_CACHED; } cv_broadcast(&db->db_changed); - dbuf_rele_and_unlock(db, NULL); + dbuf_rele_and_unlock(db, NULL, B_FALSE); } static void @@ -2171,7 +2135,8 @@ dbuf_destroy(dmu_buf_impl_t *db) * value in dnode_move(), since DB_DNODE_EXIT doesn't actually * release any lock. */ - dnode_rele(dn, db); + mutex_enter(&dn->dn_mtx); + dnode_rele_and_unlock(dn, db, B_TRUE); db->db_dnode_handle = NULL; dbuf_hash_remove(db); @@ -2198,8 +2163,10 @@ dbuf_destroy(dmu_buf_impl_t *db) * If this dbuf is referenced from an indirect dbuf, * decrement the ref count on the indirect dbuf. */ - if (parent && parent != dndb) - dbuf_rele(parent, db); + if (parent && parent != dndb) { + mutex_enter(&parent->db_mtx); + dbuf_rele_and_unlock(parent, db, B_TRUE); + } } /* @@ -2823,7 +2790,7 @@ void dbuf_rele(dmu_buf_impl_t *db, void *tag) { mutex_enter(&db->db_mtx); - dbuf_rele_and_unlock(db, tag); + dbuf_rele_and_unlock(db, tag, B_FALSE); } void @@ -2834,10 +2801,19 @@ dmu_buf_rele(dmu_buf_t *db, void *tag) /* * dbuf_rele() for an already-locked dbuf. This is necessary to allow - * db_dirtycnt and db_holds to be updated atomically. + * db_dirtycnt and db_holds to be updated atomically. The 'evicting' + * argument should be set if we are already in the dbuf-evicting code + * path, in which case we don't want to recursively evict. This allows us to + * avoid deeply nested stacks that would have a call flow similar to this: + * + * dbuf_rele()-->dbuf_rele_and_unlock()-->dbuf_evict_notify() + * ^ | + * | | + * +-----dbuf_destroy()<--dbuf_evict_one()<--------+ + * */ void -dbuf_rele_and_unlock(dmu_buf_impl_t *db, void *tag) +dbuf_rele_and_unlock(dmu_buf_impl_t *db, void *tag, boolean_t evicting) { int64_t holds; @@ -2940,7 +2916,8 @@ dbuf_rele_and_unlock(dmu_buf_impl_t *db, void *tag) db->db.db_size, db); mutex_exit(&db->db_mtx); - if (db->db_caching_status == DB_DBUF_CACHE) { + if (db->db_caching_status == DB_DBUF_CACHE && + !evicting) { dbuf_evict_notify(); } } @@ -3203,7 +3180,7 @@ dbuf_sync_leaf(dbuf_dirty_record_t *dr, dmu_tx_t *tx) kmem_free(dr, sizeof (dbuf_dirty_record_t)); ASSERT(db->db_dirtycnt > 0); db->db_dirtycnt -= 1; - dbuf_rele_and_unlock(db, (void *)(uintptr_t)txg); + dbuf_rele_and_unlock(db, (void *)(uintptr_t)txg, B_FALSE); return; } @@ -3553,7 +3530,7 @@ dbuf_write_done(zio_t *zio, arc_buf_t *buf, void *vdb) ASSERT(db->db_dirtycnt > 0); db->db_dirtycnt -= 1; db->db_data_pending = NULL; - dbuf_rele_and_unlock(db, (void *)(uintptr_t)tx->tx_txg); + dbuf_rele_and_unlock(db, (void *)(uintptr_t)tx->tx_txg, B_FALSE); } static void diff --git a/usr/src/uts/common/fs/zfs/dnode.c b/usr/src/uts/common/fs/zfs/dnode.c index 2d7d780192..2720cdbce4 100644 --- a/usr/src/uts/common/fs/zfs/dnode.c +++ b/usr/src/uts/common/fs/zfs/dnode.c @@ -1229,11 +1229,11 @@ void dnode_rele(dnode_t *dn, void *tag) { mutex_enter(&dn->dn_mtx); - dnode_rele_and_unlock(dn, tag); + dnode_rele_and_unlock(dn, tag, B_FALSE); } void -dnode_rele_and_unlock(dnode_t *dn, void *tag) +dnode_rele_and_unlock(dnode_t *dn, void *tag, boolean_t evicting) { uint64_t refs; /* Get while the hold prevents the dnode from moving. */ @@ -1264,7 +1264,8 @@ dnode_rele_and_unlock(dnode_t *dn, void *tag) * that the handle has zero references, but that will be * asserted anyway when the handle gets destroyed. */ - dbuf_rele(db, dnh); + mutex_enter(&db->db_mtx); + dbuf_rele_and_unlock(db, dnh, evicting); } } diff --git a/usr/src/uts/common/fs/zfs/dnode_sync.c b/usr/src/uts/common/fs/zfs/dnode_sync.c index 2ee75c90c2..02f263c82e 100644 --- a/usr/src/uts/common/fs/zfs/dnode_sync.c +++ b/usr/src/uts/common/fs/zfs/dnode_sync.c @@ -21,7 +21,7 @@ /* * Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved. - * Copyright (c) 2012, 2017 by Delphix. All rights reserved. + * Copyright (c) 2012, 2018 by Delphix. All rights reserved. * Copyright (c) 2014 Spectra Logic Corporation, All rights reserved. */ @@ -439,6 +439,19 @@ dnode_evict_dbufs(dnode_t *dn) avl_insert_here(&dn->dn_dbufs, &db_marker, db, AVL_BEFORE); + /* + * We need to use the "marker" dbuf rather than + * simply getting the next dbuf, because + * dbuf_destroy() may actually remove multiple dbufs. + * It can call itself recursively on the parent dbuf, + * which may also be removed from dn_dbufs. The code + * flow would look like: + * + * dbuf_destroy(): + * dnode_rele_and_unlock(parent_dbuf, evicting=TRUE): + * if (!cacheable || pending_evict) + * dbuf_destroy() + */ dbuf_destroy(db); db_next = AVL_NEXT(&dn->dn_dbufs, &db_marker); @@ -497,7 +510,7 @@ dnode_undirty_dbufs(list_t *list) list_destroy(&dr->dt.di.dr_children); } kmem_free(dr, sizeof (dbuf_dirty_record_t)); - dbuf_rele_and_unlock(db, (void *)(uintptr_t)txg); + dbuf_rele_and_unlock(db, (void *)(uintptr_t)txg, B_FALSE); } } diff --git a/usr/src/uts/common/fs/zfs/sys/dbuf.h b/usr/src/uts/common/fs/zfs/sys/dbuf.h index f467878b72..ec966432f2 100644 --- a/usr/src/uts/common/fs/zfs/sys/dbuf.h +++ b/usr/src/uts/common/fs/zfs/sys/dbuf.h @@ -20,7 +20,7 @@ */ /* * Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved. - * Copyright (c) 2012, 2015 by Delphix. All rights reserved. + * Copyright (c) 2012, 2018 by Delphix. All rights reserved. * Copyright (c) 2013 by Saso Kiselkov. All rights reserved. * Copyright (c) 2014 Spectra Logic Corporation, All rights reserved. */ @@ -303,7 +303,7 @@ boolean_t dbuf_try_add_ref(dmu_buf_t *db, objset_t *os, uint64_t obj, uint64_t dbuf_refcount(dmu_buf_impl_t *db); void dbuf_rele(dmu_buf_impl_t *db, void *tag); -void dbuf_rele_and_unlock(dmu_buf_impl_t *db, void *tag); +void dbuf_rele_and_unlock(dmu_buf_impl_t *db, void *tag, boolean_t evicting); dmu_buf_impl_t *dbuf_find(struct objset *os, uint64_t object, uint8_t level, uint64_t blkid); diff --git a/usr/src/uts/common/fs/zfs/sys/dnode.h b/usr/src/uts/common/fs/zfs/sys/dnode.h index 5566c70add..89a7b2ef60 100644 --- a/usr/src/uts/common/fs/zfs/sys/dnode.h +++ b/usr/src/uts/common/fs/zfs/sys/dnode.h @@ -20,7 +20,7 @@ */ /* * Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved. - * Copyright (c) 2012, 2017 by Delphix. All rights reserved. + * Copyright (c) 2012, 2018 by Delphix. All rights reserved. * Copyright (c) 2014 Spectra Logic Corporation, All rights reserved. */ @@ -291,7 +291,7 @@ int dnode_hold_impl(struct objset *dd, uint64_t object, int flag, void *ref, dnode_t **dnp); boolean_t dnode_add_ref(dnode_t *dn, void *ref); void dnode_rele(dnode_t *dn, void *ref); -void dnode_rele_and_unlock(dnode_t *dn, void *tag); +void dnode_rele_and_unlock(dnode_t *dn, void *tag, boolean_t evicting); void dnode_setdirty(dnode_t *dn, dmu_tx_t *tx); void dnode_sync(dnode_t *dn, dmu_tx_t *tx); void dnode_allocate(dnode_t *dn, dmu_object_type_t ot, int blocksize, int ibs, -- cgit v1.2.3 From 65d28c0b2556a9bb47ed2b033469a4182ff5b488 Mon Sep 17 00:00:00 2001 From: John Wren Kennedy Date: Tue, 26 Jun 2018 16:30:22 -0600 Subject: 9184 Add ZFS performance test for fixed blocksize random read/write IO Reviewed by: Dan Kimmel Reviewed by: John Kennedy Approved by: Robert Mustacchi --- usr/src/pkg/manifests/system-test-zfstest.mf | 2 + .../test/zfs-tests/runfiles/perf-regression.run | 3 +- .../tests/perf/fio/random_readwrite_fixed.fio | 35 +++++++++ .../tests/perf/regression/random_reads.ksh | 8 +-- .../perf/regression/random_readwrite_fixed.ksh | 82 ++++++++++++++++++++++ .../tests/perf/regression/random_writes.ksh | 8 +-- .../tests/perf/regression/sequential_reads.ksh | 8 +-- .../regression/sequential_reads_arc_cached.ksh | 10 +-- .../sequential_reads_arc_cached_clone.ksh | 10 +-- .../regression/sequential_reads_dbuf_cached.ksh | 4 +- .../tests/perf/regression/sequential_writes.ksh | 8 +-- 11 files changed, 149 insertions(+), 29 deletions(-) create mode 100644 usr/src/test/zfs-tests/tests/perf/fio/random_readwrite_fixed.fio create mode 100644 usr/src/test/zfs-tests/tests/perf/regression/random_readwrite_fixed.ksh diff --git a/usr/src/pkg/manifests/system-test-zfstest.mf b/usr/src/pkg/manifests/system-test-zfstest.mf index 681c719275..a009ec8392 100644 --- a/usr/src/pkg/manifests/system-test-zfstest.mf +++ b/usr/src/pkg/manifests/system-test-zfstest.mf @@ -2720,12 +2720,14 @@ file path=opt/zfs-tests/tests/longevity/slop_space_test mode=0555 file path=opt/zfs-tests/tests/perf/fio/mkfiles.fio mode=0444 file path=opt/zfs-tests/tests/perf/fio/random_reads.fio mode=0444 file path=opt/zfs-tests/tests/perf/fio/random_readwrite.fio mode=0444 +file path=opt/zfs-tests/tests/perf/fio/random_readwrite_fixed.fio mode=0444 file path=opt/zfs-tests/tests/perf/fio/random_writes.fio mode=0444 file path=opt/zfs-tests/tests/perf/fio/sequential_reads.fio mode=0444 file path=opt/zfs-tests/tests/perf/fio/sequential_writes.fio mode=0444 file path=opt/zfs-tests/tests/perf/perf.shlib mode=0444 file path=opt/zfs-tests/tests/perf/regression/random_reads mode=0555 file path=opt/zfs-tests/tests/perf/regression/random_readwrite mode=0555 +file path=opt/zfs-tests/tests/perf/regression/random_readwrite_fixed mode=0555 file path=opt/zfs-tests/tests/perf/regression/random_writes mode=0555 file path=opt/zfs-tests/tests/perf/regression/random_writes_zil mode=0555 file path=opt/zfs-tests/tests/perf/regression/sequential_reads mode=0555 diff --git a/usr/src/test/zfs-tests/runfiles/perf-regression.run b/usr/src/test/zfs-tests/runfiles/perf-regression.run index b28f0e7f78..7e72e5c984 100644 --- a/usr/src/test/zfs-tests/runfiles/perf-regression.run +++ b/usr/src/test/zfs-tests/runfiles/perf-regression.run @@ -26,5 +26,6 @@ outputdir = /var/tmp/test_results [/opt/zfs-tests/tests/perf/regression] tests = ['sequential_writes', 'sequential_reads', 'sequential_reads_arc_cached', 'sequential_reads_arc_cached_clone', 'sequential_reads_dbuf_cached', - 'random_reads', 'random_writes', 'random_readwrite', 'random_writes_zil'] + 'random_reads', 'random_writes', 'random_readwrite', 'random_writes_zil', + 'random_readwrite_fixed'] post = diff --git a/usr/src/test/zfs-tests/tests/perf/fio/random_readwrite_fixed.fio b/usr/src/test/zfs-tests/tests/perf/fio/random_readwrite_fixed.fio new file mode 100644 index 0000000000..ed44955532 --- /dev/null +++ b/usr/src/test/zfs-tests/tests/perf/fio/random_readwrite_fixed.fio @@ -0,0 +1,35 @@ +# +# This file and its contents are supplied under the terms of the +# Common Development and Distribution License ("CDDL"), version 1.0. +# You may only use this file in accordance with the terms of version +# 1.0 of the CDDL. +# +# A full copy of the text of the CDDL should have accompanied this +# source. A copy of the CDDL is also available via the Internet at +# http://www.illumos.org/license/CDDL. +# + +# +# Copyright (c) 2017 by Delphix. All rights reserved. +# + +[global] +filename_format=file$jobnum +nrfiles=16 +group_reporting=1 +fallocate=0 +overwrite=0 +thread=1 +rw=randrw +rwmixread=70 +time_based=1 +directory=${DIRECTORY} +runtime=${RUNTIME} +bs=${BLOCKSIZE} +ioengine=psync +sync=${SYNC_TYPE} +numjobs=${NUMJOBS} +buffer_compress_percentage=66 +buffer_compress_chunk=4096 + +[job] diff --git a/usr/src/test/zfs-tests/tests/perf/regression/random_reads.ksh b/usr/src/test/zfs-tests/tests/perf/regression/random_reads.ksh index 5679a8d7eb..99b961abca 100644 --- a/usr/src/test/zfs-tests/tests/perf/regression/random_reads.ksh +++ b/usr/src/test/zfs-tests/tests/perf/regression/random_reads.ksh @@ -58,7 +58,7 @@ if [[ -n $PERF_REGRESSION_WEEKLY ]]; then export PERF_NTHREADS=${PERF_NTHREADS:-'8 16 32 64'} export PERF_NTHREADS_PER_FS=${PERF_NTHREADS_PER_FS:-'0'} export PERF_SYNC_TYPES=${PERF_SYNC_TYPES:-'1'} - export PERF_IOSIZES=${PERF_IOSIZES:-'8k'} + export PERF_IOSIZES=${PERF_IOSIZES:-'8k 64k 128k'} elif [[ -n $PERF_REGRESSION_NIGHTLY ]]; then export PERF_RUNTIME=${PERF_RUNTIME:-$PERF_RUNTIME_NIGHTLY} export PERF_RUNTYPE=${PERF_RUNTYPE:-'nightly'} @@ -81,9 +81,9 @@ lun_list=$(pool_to_lun_list $PERFPOOL) log_note "Collecting backend IO stats with lun list $lun_list" export collect_scripts=( "kstat zfs:0 1" "kstat" - "vmstat 1" "vmstat" - "mpstat 1" "mpstat" - "iostat -xcnz 1" "iostat" + "vmstat -T d 1" "vmstat" + "mpstat -T d 1" "mpstat" + "iostat -T d -xcnz 1" "iostat" "dtrace -Cs $PERF_SCRIPTS/io.d $PERFPOOL $lun_list 1" "io" "dtrace -s $PERF_SCRIPTS/profile.d" "profile" ) diff --git a/usr/src/test/zfs-tests/tests/perf/regression/random_readwrite_fixed.ksh b/usr/src/test/zfs-tests/tests/perf/regression/random_readwrite_fixed.ksh new file mode 100644 index 0000000000..fb62731eda --- /dev/null +++ b/usr/src/test/zfs-tests/tests/perf/regression/random_readwrite_fixed.ksh @@ -0,0 +1,82 @@ +#!/usr/bin/ksh +# file and its contents are supplied under the terms of the +# Common Development and Distribution License ("CDDL"), version 1.0. +# You may only use this file in accordance with the terms of version +# 1.0 of the CDDL. +# +# A full copy of the text of the CDDL should have accompanied this +# source. A copy of the CDDL is also available via the Internet at +# http://www.illumos.org/license/CDDL. +# + +# +# Copyright (c) 2017 by Delphix. All rights reserved. +# + +# +# Description: +# Trigger fio runs using the random_readwrite_fixed job file. The number of runs and +# data collected is determined by the PERF_* variables. See do_fio_run for +# details about these variables. +# +# The files to read and write from are created prior to the first fio run, +# and used for all fio runs. The ARC is cleared with `zinject -a` prior to +# each run so reads will go to disk. +# + +. $STF_SUITE/include/libtest.shlib +. $STF_SUITE/tests/perf/perf.shlib + +function cleanup +{ + recreate_perf_pool +} + +log_onexit cleanup + +recreate_perf_pool +populate_perf_filesystems + +# Aim to fill the pool to 50% capacity while accounting for a 3x compressratio. +export TOTAL_SIZE=$(($(get_prop avail $PERFPOOL) * 3 / 2)) + +# Variables for use by fio. +if [[ -n $PERF_REGRESSION_WEEKLY ]]; then + export PERF_RUNTIME=${PERF_RUNTIME:-$PERF_RUNTIME_WEEKLY} + export PERF_RUNTYPE=${PERF_RUNTYPE:-'weekly'} + export PERF_NTHREADS=${PERF_NTHREADS:-'8 16 32 64'} + export PERF_NTHREADS_PER_FS=${PERF_NTHREADS_PER_FS:-'0'} + export PERF_SYNC_TYPES=${PERF_SYNC_TYPES:-'0 1'} + export PERF_IOSIZES='8k 64k' +elif [[ -n $PERF_REGRESSION_NIGHTLY ]]; then + export PERF_RUNTIME=${PERF_RUNTIME:-$PERF_RUNTIME_NIGHTLY} + export PERF_RUNTYPE=${PERF_RUNTYPE:-'nightly'} + export PERF_NTHREADS=${PERF_NTHREADS:-'64 128'} + export PERF_NTHREADS_PER_FS=${PERF_NTHREADS_PER_FS:-'0'} + export PERF_SYNC_TYPES=${PERF_SYNC_TYPES:-'1'} + export PERF_IOSIZES='8k' +fi + +# Layout the files to be used by the readwrite tests. Create as many files +# as the largest number of threads. An fio run with fewer threads will use +# a subset of the available files. +export NUMJOBS=$(get_max $PERF_NTHREADS) +export FILE_SIZE=$((TOTAL_SIZE / NUMJOBS)) +export DIRECTORY=$(get_directory) +log_must fio $FIO_SCRIPTS/mkfiles.fio + +# Set up the scripts and output files that will log performance data. +lun_list=$(pool_to_lun_list $PERFPOOL) +log_note "Collecting backend IO stats with lun list $lun_list" +export collect_scripts=( + "kstat zfs:0 1" "kstat" + "vmstat -T d 1" "vmstat" + "mpstat -T d 1" "mpstat" + "iostat -T d -xcnz 1" "iostat" + "dtrace -Cs $PERF_SCRIPTS/io.d $PERFPOOL $lun_list 1" "io" + "dtrace -s $PERF_SCRIPTS/profile.d" "profile" +) + +log_note "Random reads and writes with $PERF_RUNTYPE settings" +do_fio_run random_readwrite_fixed.fio false true +log_pass "Measure IO stats during random read and write load" diff --git a/usr/src/test/zfs-tests/tests/perf/regression/random_writes.ksh b/usr/src/test/zfs-tests/tests/perf/regression/random_writes.ksh index fdb6421887..223d9b384c 100644 --- a/usr/src/test/zfs-tests/tests/perf/regression/random_writes.ksh +++ b/usr/src/test/zfs-tests/tests/perf/regression/random_writes.ksh @@ -57,7 +57,7 @@ if [[ -n $PERF_REGRESSION_WEEKLY ]]; then export PERF_NTHREADS=${PERF_NTHREADS:-'1 4 8 16 32 64 128'} export PERF_NTHREADS_PER_FS=${PERF_NTHREADS_PER_FS:-'0'} export PERF_SYNC_TYPES=${PERF_SYNC_TYPES:-'0 1'} - export PERF_IOSIZES=${PERF_IOSIZES:-'8k'} + export PERF_IOSIZES=${PERF_IOSIZES:-'8k 64k 256k'} elif [[ -n $PERF_REGRESSION_NIGHTLY ]]; then export PERF_RUNTIME=${PERF_RUNTIME:-$PERF_RUNTIME_NIGHTLY} export PERF_RUNTYPE=${PERF_RUNTYPE:-'nightly'} @@ -72,9 +72,9 @@ lun_list=$(pool_to_lun_list $PERFPOOL) log_note "Collecting backend IO stats with lun list $lun_list" export collect_scripts=( "kstat zfs:0 1" "kstat" - "vmstat 1" "vmstat" - "mpstat 1" "mpstat" - "iostat -xcnz 1" "iostat" + "vmstat -T d 1" "vmstat" + "mpstat -T d 1" "mpstat" + "iostat -T d -xcnz 1" "iostat" "dtrace -Cs $PERF_SCRIPTS/io.d $PERFPOOL $lun_list 1" "io" "dtrace -s $PERF_SCRIPTS/profile.d" "profile" ) diff --git a/usr/src/test/zfs-tests/tests/perf/regression/sequential_reads.ksh b/usr/src/test/zfs-tests/tests/perf/regression/sequential_reads.ksh index 6034a03151..49295a1c40 100644 --- a/usr/src/test/zfs-tests/tests/perf/regression/sequential_reads.ksh +++ b/usr/src/test/zfs-tests/tests/perf/regression/sequential_reads.ksh @@ -58,7 +58,7 @@ if [[ -n $PERF_REGRESSION_WEEKLY ]]; then export PERF_NTHREADS=${PERF_NTHREADS:-'8 16 32 64'} export PERF_NTHREADS_PER_FS=${PERF_NTHREADS_PER_FS:-'0'} export PERF_SYNC_TYPES=${PERF_SYNC_TYPES:-'1'} - export PERF_IOSIZES=${PERF_IOSIZES:-'64k 128k 1m'} + export PERF_IOSIZES=${PERF_IOSIZES:-'8k 64k 128k'} elif [[ -n $PERF_REGRESSION_NIGHTLY ]]; then export PERF_RUNTIME=${PERF_RUNTIME:-$PERF_RUNTIME_NIGHTLY} export PERF_RUNTYPE=${PERF_RUNTYPE:-'nightly'} @@ -81,9 +81,9 @@ lun_list=$(pool_to_lun_list $PERFPOOL) log_note "Collecting backend IO stats with lun list $lun_list" export collect_scripts=( "kstat zfs:0 1" "kstat" - "vmstat 1" "vmstat" - "mpstat 1" "mpstat" - "iostat -xcnz 1" "iostat" + "vmstat -T d 1" "vmstat" + "mpstat -T d 1" "mpstat" + "iostat -T d -xcnz 1" "iostat" "dtrace -Cs $PERF_SCRIPTS/io.d $PERFPOOL $lun_list 1" "io" "dtrace -Cs $PERF_SCRIPTS/prefetch_io.d $PERFPOOL 1" "prefetch" "dtrace -s $PERF_SCRIPTS/profile.d" "profile" diff --git a/usr/src/test/zfs-tests/tests/perf/regression/sequential_reads_arc_cached.ksh b/usr/src/test/zfs-tests/tests/perf/regression/sequential_reads_arc_cached.ksh index 4a0cc7ace7..addbd75010 100644 --- a/usr/src/test/zfs-tests/tests/perf/regression/sequential_reads_arc_cached.ksh +++ b/usr/src/test/zfs-tests/tests/perf/regression/sequential_reads_arc_cached.ksh @@ -45,10 +45,10 @@ export TOTAL_SIZE=$(($(get_max_arc_size) / 2)) if [[ -n $PERF_REGRESSION_WEEKLY ]]; then export PERF_RUNTIME=${PERF_RUNTIME:-$PERF_RUNTIME_WEEKLY} export PERF_RUNTYPE=${PERF_RUNTYPE:-'weekly'} - export PERF_NTHREADS=${PERF_NTHREADS:-'16 64'} + export PERF_NTHREADS=${PERF_NTHREADS:-'8 16 32 64'} export PERF_NTHREADS_PER_FS=${PERF_NTHREADS_PER_FS:-'0'} export PERF_SYNC_TYPES=${PERF_SYNC_TYPES:-'1'} - export PERF_IOSIZES=${PERF_IOSIZES:-'64k 128k 1m'} + export PERF_IOSIZES=${PERF_IOSIZES:-'8k 64k 128k'} elif [[ -n $PERF_REGRESSION_NIGHTLY ]]; then export PERF_RUNTIME=${PERF_RUNTIME:-$PERF_RUNTIME_NIGHTLY} export PERF_RUNTYPE=${PERF_RUNTYPE:-'nightly'} @@ -71,9 +71,9 @@ lun_list=$(pool_to_lun_list $PERFPOOL) log_note "Collecting backend IO stats with lun list $lun_list" export collect_scripts=( "kstat zfs:0 1" "kstat" - "vmstat 1" "vmstat" - "mpstat 1" "mpstat" - "iostat -xcnz 1" "iostat" + "vmstat -T d 1" "vmstat" + "mpstat -T d 1" "mpstat" + "iostat -T d -xcnz 1" "iostat" "dtrace -Cs $PERF_SCRIPTS/io.d $PERFPOOL $lun_list 1" "io" "dtrace -Cs $PERF_SCRIPTS/prefetch_io.d $PERFPOOL 1" "prefetch" "dtrace -s $PERF_SCRIPTS/profile.d" "profile" diff --git a/usr/src/test/zfs-tests/tests/perf/regression/sequential_reads_arc_cached_clone.ksh b/usr/src/test/zfs-tests/tests/perf/regression/sequential_reads_arc_cached_clone.ksh index 6f71811012..4ffe1f21c0 100644 --- a/usr/src/test/zfs-tests/tests/perf/regression/sequential_reads_arc_cached_clone.ksh +++ b/usr/src/test/zfs-tests/tests/perf/regression/sequential_reads_arc_cached_clone.ksh @@ -51,10 +51,10 @@ export TOTAL_SIZE=$(($(get_max_arc_size) / 2)) if [[ -n $PERF_REGRESSION_WEEKLY ]]; then export PERF_RUNTIME=${PERF_RUNTIME:-$PERF_RUNTIME_WEEKLY} export PERF_RUNTYPE=${PERF_RUNTYPE:-'weekly'} - export PERF_NTHREADS=${PERF_NTHREADS:-'16 64'} + export PERF_NTHREADS=${PERF_NTHREADS:-'8 16 32 64'} export PERF_NTHREADS_PER_FS=${PERF_NTHREADS_PER_FS:-'0'} export PERF_SYNC_TYPES=${PERF_SYNC_TYPES:-'1'} - export PERF_IOSIZES=${PERF_IOSIZES:-'64k 128k 1m'} + export PERF_IOSIZES=${PERF_IOSIZES:-'8k 64k 128k'} elif [[ -n $PERF_REGRESSION_NIGHTLY ]]; then export PERF_RUNTIME=${PERF_RUNTIME:-$PERF_RUNTIME_NIGHTLY} export PERF_RUNTYPE=${PERF_RUNTYPE:-'nightly'} @@ -97,9 +97,9 @@ lun_list=$(pool_to_lun_list $PERFPOOL) log_note "Collecting backend IO stats with lun list $lun_list" export collect_scripts=( "kstat zfs:0 1" "kstat" - "vmstat 1" "vmstat" - "mpstat 1" "mpstat" - "iostat -xcnz 1" "iostat" + "vmstat -T d 1" "vmstat" + "mpstat -T d 1" "mpstat" + "iostat -T d -xcnz 1" "iostat" "dtrace -Cs $PERF_SCRIPTS/io.d $PERFPOOL $lun_list 1" "io" "dtrace -Cs $PERF_SCRIPTS/prefetch_io.d $PERFPOOL 1" "prefetch" "dtrace -s $PERF_SCRIPTS/profile.d" "profile" diff --git a/usr/src/test/zfs-tests/tests/perf/regression/sequential_reads_dbuf_cached.ksh b/usr/src/test/zfs-tests/tests/perf/regression/sequential_reads_dbuf_cached.ksh index ff17d93e67..140a05e4ac 100644 --- a/usr/src/test/zfs-tests/tests/perf/regression/sequential_reads_dbuf_cached.ksh +++ b/usr/src/test/zfs-tests/tests/perf/regression/sequential_reads_dbuf_cached.ksh @@ -49,10 +49,10 @@ export TOTAL_SIZE=$(($(get_max_dbuf_cache_size) * 3 / 4)) if [[ -n $PERF_REGRESSION_WEEKLY ]]; then export PERF_RUNTIME=${PERF_RUNTIME:-$PERF_RUNTIME_WEEKLY} export PERF_RUNTYPE=${PERF_RUNTYPE:-'weekly'} - export PERF_NTHREADS=${PERF_NTHREADS:-'16 64'} + export PERF_NTHREADS=${PERF_NTHREADS:-'8 16 32 64'} export PERF_NTHREADS_PER_FS=${PERF_NTHREADS_PER_FS:-'0'} export PERF_SYNC_TYPES=${PERF_SYNC_TYPES:-'1'} - export PERF_IOSIZES=${PERF_IOSIZES:-'64k'} + export PERF_IOSIZES=${PERF_IOSIZES:-'8k 64k 128k'} elif [[ -n $PERF_REGRESSION_NIGHTLY ]]; then export PERF_RUNTIME=${PERF_RUNTIME:-$PERF_RUNTIME_NIGHTLY} export PERF_RUNTYPE=${PERF_RUNTYPE:-'nightly'} diff --git a/usr/src/test/zfs-tests/tests/perf/regression/sequential_writes.ksh b/usr/src/test/zfs-tests/tests/perf/regression/sequential_writes.ksh index 1007ea1c9c..ec671a425f 100644 --- a/usr/src/test/zfs-tests/tests/perf/regression/sequential_writes.ksh +++ b/usr/src/test/zfs-tests/tests/perf/regression/sequential_writes.ksh @@ -57,7 +57,7 @@ if [[ -n $PERF_REGRESSION_WEEKLY ]]; then export PERF_NTHREADS=${PERF_NTHREADS:-'1 4 8 16 32 64 128'} export PERF_NTHREADS_PER_FS=${PERF_NTHREADS_PER_FS:-'0'} export PERF_SYNC_TYPES=${PERF_SYNC_TYPES:-'0 1'} - export PERF_IOSIZES=${PERF_IOSIZES:-'8k 128k 1m'} + export PERF_IOSIZES=${PERF_IOSIZES:-'8k 64k 256k'} elif [[ -n $PERF_REGRESSION_NIGHTLY ]]; then export PERF_RUNTIME=${PERF_RUNTIME:-$PERF_RUNTIME_NIGHTLY} export PERF_RUNTYPE=${PERF_RUNTYPE:-'nightly'} @@ -72,9 +72,9 @@ lun_list=$(pool_to_lun_list $PERFPOOL) log_note "Collecting backend IO stats with lun list $lun_list" export collect_scripts=( "kstat zfs:0 1" "kstat" - "vmstat 1" "vmstat" - "mpstat 1" "mpstat" - "iostat -xcnz 1" "iostat" + "vmstat -T d 1" "vmstat" + "mpstat -T d 1" "mpstat" + "iostat -T d -xcnz 1" "iostat" "dtrace -Cs $PERF_SCRIPTS/io.d $PERFPOOL $lun_list 1" "io" "dtrace -s $PERF_SCRIPTS/profile.d" "profile" ) -- cgit v1.2.3 From 566b4223c74de6cad48ddbedf35a12d6a511c8c5 Mon Sep 17 00:00:00 2001 From: Toomas Soome Date: Mon, 19 Feb 2018 20:32:44 +0200 Subject: 9133 ucbcmd: this statement may fall through Reviewed by: Andrew Stormont Reviewed by: C Fraire Reviewed by: Ken Mays Approved by: Dan McDonald --- usr/src/ucbcmd/sed/sed.h | 7 +++---- usr/src/ucbcmd/sed/sed0.c | 3 +-- usr/src/ucbcmd/sed/sed1.c | 7 ++----- usr/src/ucbcmd/stty/stty.c | 1 + usr/src/ucbcmd/tset/tset.c | 12 ++++-------- 5 files changed, 11 insertions(+), 19 deletions(-) diff --git a/usr/src/ucbcmd/sed/sed.h b/usr/src/ucbcmd/sed/sed.h index f814ce4ef6..465d38613d 100644 --- a/usr/src/ucbcmd/sed/sed.h +++ b/usr/src/ucbcmd/sed/sed.h @@ -30,8 +30,6 @@ #ifndef _SED_H #define _SED_H -#pragma ident "%Z%%M% %I% %E% SMI" - /* * sed -- stream editor */ @@ -49,7 +47,6 @@ #define PEEKC() (*sp) #define UNGETC(c) (--sp) #define RETURN(c) cp = sp; return(ep); -#define ERROR(c) regerr(c) #define CEND 16 #define CLNUM 14 @@ -153,7 +150,9 @@ char *compsub(); struct label *search(); char *gline(); char *place(); -void comperr(char *); +void comperr(char *) __NORETURN; +void regerr(int) __NORETURN; +#define ERROR(c) regerr(c) void execute(char *); #endif /* _SED_H */ diff --git a/usr/src/ucbcmd/sed/sed0.c b/usr/src/ucbcmd/sed/sed0.c index 5be6112e36..1b5e3881bf 100644 --- a/usr/src/ucbcmd/sed/sed0.c +++ b/usr/src/ucbcmd/sed/sed0.c @@ -27,6 +27,7 @@ /* All Rights Reserved */ #include +#include #include #include "sed.h" @@ -70,8 +71,6 @@ char TOOBIG[] = "Suffix too large - 512 max: %s"; extern int sed; /* IMPORTANT flag !!! */ extern char *comple(); -extern char *malloc(); - static void dechain(void); static void fcomp(void); diff --git a/usr/src/ucbcmd/sed/sed1.c b/usr/src/ucbcmd/sed/sed1.c index c5f5d89144..c4777340df 100644 --- a/usr/src/ucbcmd/sed/sed1.c +++ b/usr/src/ucbcmd/sed/sed1.c @@ -27,10 +27,8 @@ /* Copyright (c) 1984 AT&T */ /* All Rights Reserved */ - -#pragma ident "%Z%%M% %I% %E% SMI" - #include +#include #include #include #include @@ -667,7 +665,7 @@ char *ep; return(p); } -int +void regerr(int err) { switch(err) { @@ -726,7 +724,6 @@ regerr(int err) exit(2); break; } - return (0); } static void diff --git a/usr/src/ucbcmd/stty/stty.c b/usr/src/ucbcmd/stty/stty.c index 65e79501d8..127a118c78 100644 --- a/usr/src/ucbcmd/stty/stty.c +++ b/usr/src/ucbcmd/stty/stty.c @@ -28,6 +28,7 @@ /* All Rights Reserved */ #include +#include #include #include #include diff --git a/usr/src/ucbcmd/tset/tset.c b/usr/src/ucbcmd/tset/tset.c index dcdbcac983..9e520f6a23 100644 --- a/usr/src/ucbcmd/tset/tset.c +++ b/usr/src/ucbcmd/tset/tset.c @@ -268,6 +268,7 @@ #define oldintr oldmodes.c_cc[VINTR] #include +#include #include #include @@ -322,8 +323,6 @@ #define DEFTYPE "unknown" -#define NOTTY 'x' - /* * Baud Rate Conditionals */ @@ -390,7 +389,6 @@ char Kill_char; /* new kill character */ char Intr_char; /* new interrupt character */ char Specialerase; /* set => Erase_char only on terminals with backspace */ -char Ttyid = NOTTY; /* terminal identifier */ char *TtyType; /* type of terminal */ char *DefType; /* default type if none other computed */ char *NewType; /* mapping identifier based on old flags */ @@ -559,6 +557,7 @@ main(int argc, char *argv[]) /* special erase: operate on all but TTY33 */ Specialerase = YES; /* explicit fall-through to -e case */ + /* FALLTHROUGH */ case 'e': /* erase character */ if (*p == NULL) @@ -775,14 +774,11 @@ mapold: Map->Ident = NewType; if (bufp && *bufp != '/') (void) strcpy(bufp-8, "NOTHING"); /* overwrite only "TERMCAP" */ /* get current idea of terminal type from environment */ - if (!Dash_h && TtyType == 0) + if (!Dash_h && TtyType == NULL) TtyType = getenv("TERM"); - if (!RepOnly && Ttyid == NOTTY && (TtyType == 0 || !Dash_h)) - Ttyid = ttyname(FILEDES); - /* If still undefined, use DEFTYPE */ - if (TtyType == 0) { + if (TtyType == NULL) { TtyType = DEFTYPE; } -- cgit v1.2.3 From 49169a56b4da7a6f2d206ecc2166fbe2457343b9 Mon Sep 17 00:00:00 2001 From: Richard Lowe Date: Tue, 6 Feb 2018 20:32:44 +0200 Subject: 9417 check_rtime: except more C++ Reviewed by: Andrew Stormont Reviewed by: Ken Mays Approved by: Dan McDonald --- exception_lists/check_rtime | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/exception_lists/check_rtime b/exception_lists/check_rtime index b77527db34..093fe9ee0c 100644 --- a/exception_lists/check_rtime +++ b/exception_lists/check_rtime @@ -123,7 +123,7 @@ UNUSED_RPATH /usr/snadm/lib.*\ from\ .*/usr/snadm/lib/libspmicommon\.so\.1 UNUSED_RPATH /usr/gcc/.*/lib.*\ from\ .* # Unused runpaths for reasons not captured above -UNUSED_RPATH /usr/lib/smbsrv.*\ from\ .*libsmb\.so\.1 # future needs +UNUSED_RPATH /usr/lib/smbsrv.*\ from\ .*libsmb\.so\.1 # future needs # Unreferenced objects of non-OSnet objects we can't change UNREF_OBJ /lib.*\ of\ .*libcimapi\.so @@ -157,6 +157,7 @@ UNREF_OBJ /libgcc_s.*\ of\ .*libgmodule-2\.0\.so\.0 # Unreferenced object of objects we can't change for other reasons UNREF_OBJ /libmapmalloc\.so\.1;\ unused\ dependency\ of # interposer UNREF_OBJ /libstdc\+\+\.so\.6;\ unused\ dependency\ of # gcc build +UNREF_OBJ /libgcc_s\.so\.1;\ unused\ dependency\ of # gcc build UNREF_OBJ /libgcc_s\.so\.1.*\ of\ .*libstdc\+\+\.so\.6 # omnios gcc mix UNREF_OBJ /libm\.so\.2.*\ of\ .*libstdc\+\+\.so\.6 # gcc build UNREF_OBJ /lib.*\ of\ .*/lib/picl/plugins/ # picl @@ -193,8 +194,11 @@ OLDDEP libw\.so\.1 # on297 build 7 # NOSYMSORT opt/SUNWdtrt/tst/common/pid/tst.weak2.exe # DTrace test NOSYMSORT ld\.so\.1 # libc_pic.a user +NOSYMSORT usr/bin/audioconvert # C++ +NOSYMSORT usr/bin/make # C++ NOSYMSORT usr/MACH(lib)/libsun_fc\.so\.1 # C++ NOSYMSORT usr/MACH(lib)/libfru\.so\.1 # C++ +NOSYMSORT usr/lib/libnisdb\.so\.2 # C++ # The majority of illumos deliverables should not depend on the GCC runtime # (any necessary runtime symbol should be provided by libc.so, instead). -- cgit v1.2.3 From e4768a3447c8320148c66b297c2acb00217f575d Mon Sep 17 00:00:00 2001 From: Toomas Soome Date: Wed, 7 Feb 2018 20:32:44 +0200 Subject: 9477 loader: cstyle update of common/commands.c Reviewed by: Yuri Pankov Reviewed by: Andy Fiddaman Approved by: Dan McDonald --- usr/src/boot/sys/boot/common/commands.c | 694 ++++++++++++++++---------------- usr/src/common/ficl/emu/loader_emu.c | 20 +- 2 files changed, 363 insertions(+), 351 deletions(-) diff --git a/usr/src/boot/sys/boot/common/commands.c b/usr/src/boot/sys/boot/common/commands.c index 942e6d09fb..04a2bf591f 100644 --- a/usr/src/boot/sys/boot/common/commands.c +++ b/usr/src/boot/sys/boot/common/commands.c @@ -37,10 +37,11 @@ char command_errbuf[COMMAND_ERRBUFSZ]; static int page_file(char *filename); +/* BEGIN CSTYLED */ /* * Help is read from a formatted text file. * - * Entries in the file are formatted as + * Entries in the file are formatted as # Ttopic [Ssubtopic] Ddescription help @@ -57,158 +58,165 @@ here * * If no argument(s) are supplied by the user, the help for 'help' is displayed. */ +/* END CSTYLED */ COMMAND_SET(help, "help", "detailed help", command_help); static int -help_getnext(int fd, char **topic, char **subtopic, char **desc) +help_getnext(int fd, char **topic, char **subtopic, char **desc) { - char line[81], *cp, *ep; - - /* Make sure we provide sane values. */ - *topic = *subtopic = *desc = NULL; - for (;;) { - if (fgetstr(line, 80, fd) < 0) - return(0); - - if ((strlen(line) < 3) || (line[0] != '#') || (line[1] != ' ')) - continue; - - cp = line + 2; - while ((cp != NULL) && (*cp != 0)) { - ep = strchr(cp, ' '); - if ((*cp == 'T') && (*topic == NULL)) { - if (ep != NULL) - *ep++ = 0; - *topic = strdup(cp + 1); - } else if ((*cp == 'S') && (*subtopic == NULL)) { - if (ep != NULL) - *ep++ = 0; - *subtopic = strdup(cp + 1); - } else if (*cp == 'D') { - *desc = strdup(cp + 1); - ep = NULL; - } - cp = ep; - } - if (*topic == NULL) { - free(*subtopic); - free(*desc); - *subtopic = *desc = NULL; - continue; + char line[81], *cp, *ep; + + /* Make sure we provide sane values. */ + *topic = *subtopic = *desc = NULL; + for (;;) { + if (fgetstr(line, 80, fd) < 0) + return (0); + + if (strlen(line) < 3 || line[0] != '#' || line[1] != ' ') + continue; + + *topic = *subtopic = *desc = NULL; + cp = line + 2; + while (cp != NULL && *cp != 0) { + ep = strchr(cp, ' '); + if (*cp == 'T' && *topic == NULL) { + if (ep != NULL) + *ep++ = 0; + *topic = strdup(cp + 1); + } else if (*cp == 'S' && *subtopic == NULL) { + if (ep != NULL) + *ep++ = 0; + *subtopic = strdup(cp + 1); + } else if (*cp == 'D') { + *desc = strdup(cp + 1); + ep = NULL; + } + cp = ep; + } + if (*topic == NULL) { + free(*subtopic); + free(*desc); + *subtopic = *desc = NULL; + continue; + } + return (1); } - return(1); - } } static int help_emitsummary(char *topic, char *subtopic, char *desc) { - int i; - - pager_output(" "); - pager_output(topic); - i = strlen(topic); - if (subtopic != NULL) { - pager_output(" "); - pager_output(subtopic); - i += strlen(subtopic) + 1; - } - if (desc != NULL) { - do { - pager_output(" "); - } while (i++ < 30); - pager_output(desc); - } - return (pager_output("\n")); + int i; + + pager_output(" "); + pager_output(topic); + i = strlen(topic); + if (subtopic != NULL) { + pager_output(" "); + pager_output(subtopic); + i += strlen(subtopic) + 1; + } + if (desc != NULL) { + do { + pager_output(" "); + } while (i++ < 30); + pager_output(desc); + } + return (pager_output("\n")); } - + static int -command_help(int argc, char *argv[]) +command_help(int argc, char *argv[]) { - char buf[81]; /* XXX buffer size? */ - int hfd, matched, doindex; - char *topic, *subtopic, *t, *s, *d; - - /* page the help text from our load path */ - snprintf(buf, sizeof (buf), "%s/boot/loader.help", getenv("loaddev")); - if ((hfd = open(buf, O_RDONLY)) < 0) { - printf("Verbose help not available, use '?' to list commands\n"); - return(CMD_OK); - } - - /* pick up request from arguments */ - topic = subtopic = NULL; - switch(argc) { - case 3: - subtopic = strdup(argv[2]); - case 2: - topic = strdup(argv[1]); - break; - case 1: - topic = strdup("help"); - break; - default: - command_errmsg = "usage is 'help []"; - close(hfd); - return(CMD_ERROR); - } - - /* magic "index" keyword */ - doindex = !strcmp(topic, "index"); - matched = doindex; - - /* Scan the helpfile looking for help matching the request */ - pager_open(); - while (help_getnext(hfd, &t, &s, &d)) { - - if (doindex) { /* dink around formatting */ - if (help_emitsummary(t, s, d)) - break; + char buf[81]; /* XXX buffer size? */ + int hfd, matched, doindex; + char *topic, *subtopic, *t, *s, *d; + + /* page the help text from our load path */ + snprintf(buf, sizeof (buf), "%s/boot/loader.help", getenv("loaddev")); + if ((hfd = open(buf, O_RDONLY)) < 0) { + printf("Verbose help not available, " + "use '?' to list commands\n"); + return (CMD_OK); + } - } else if (strcmp(topic, t)) { - /* topic mismatch */ - if (matched) /* nothing more on this topic, stop scanning */ + /* pick up request from arguments */ + topic = subtopic = NULL; + switch (argc) { + case 3: + subtopic = strdup(argv[2]); + /* FALLTHROUGH */ + case 2: + topic = strdup(argv[1]); + break; + case 1: + topic = strdup("help"); break; + default: + command_errmsg = "usage is 'help []"; + close(hfd); + return (CMD_ERROR); + } - } else { - /* topic matched */ - matched = 1; - if (((subtopic == NULL) && (s == NULL)) || - ((subtopic != NULL) && (s != NULL) && !strcmp(subtopic, s))) { - /* exact match, print text */ - while ((fgetstr(buf, 80, hfd) >= 0) && (buf[0] != '#')) { - if (pager_output(buf)) - break; - if (pager_output("\n")) - break; + /* magic "index" keyword */ + doindex = strcmp(topic, "index") == 0? 1 : 0; + matched = doindex; + + /* Scan the helpfile looking for help matching the request */ + pager_open(); + while (help_getnext(hfd, &t, &s, &d)) { + + if (doindex) { /* dink around formatting */ + if (help_emitsummary(t, s, d)) + break; + + } else if (strcmp(topic, t)) { + /* topic mismatch */ + if (matched) { + /* nothing more on this topic, stop scanning */ + break; + } + } else { + /* topic matched */ + matched = 1; + if ((subtopic == NULL && s == NULL) || + (subtopic != NULL && s != NULL && + strcmp(subtopic, s) == 0)) { + /* exact match, print text */ + while (fgetstr(buf, 80, hfd) >= 0 && + buf[0] != '#') { + if (pager_output(buf)) + break; + if (pager_output("\n")) + break; + } + } else if (subtopic == NULL && s != NULL) { + /* topic match, list subtopics */ + if (help_emitsummary(t, s, d)) + break; + } } - } else if ((subtopic == NULL) && (s != NULL)) { - /* topic match, list subtopics */ - if (help_emitsummary(t, s, d)) - break; - } + free(t); + free(s); + free(d); + t = s = d = NULL; } free(t); free(s); free(d); - t = s = d = NULL; - } - free(t); - free(s); - free(d); - pager_close(); - close(hfd); - if (!matched) { - snprintf(command_errbuf, sizeof (command_errbuf), - "no help available for '%s'", topic); + pager_close(); + close(hfd); + if (!matched) { + snprintf(command_errbuf, sizeof (command_errbuf), + "no help available for '%s'", topic); + free(topic); + free(subtopic); + return (CMD_ERROR); + } free(topic); free(subtopic); - return(CMD_ERROR); - } - free(topic); - free(subtopic); - return(CMD_OK); + return (CMD_OK); } COMMAND_SET(commandlist, "?", "list commands", command_commandlist); @@ -216,25 +224,26 @@ COMMAND_SET(commandlist, "?", "list commands", command_commandlist); static int command_commandlist(int argc __unused, char *argv[] __unused) { - struct bootblk_command **cmdp; - int res; - char name[20]; - - res = 0; - pager_open(); - res = pager_output("Available commands:\n"); - SET_FOREACH(cmdp, Xcommand_set) { - if (res) - break; - if (((*cmdp)->c_name != NULL) && ((*cmdp)->c_desc != NULL)) { - snprintf(name, sizeof (name), " %-15s ", (*cmdp)->c_name); - pager_output(name); - pager_output((*cmdp)->c_desc); - res = pager_output("\n"); + struct bootblk_command **cmdp; + int res; + char name[20]; + + res = 0; + pager_open(); + res = pager_output("Available commands:\n"); + SET_FOREACH(cmdp, Xcommand_set) { + if (res) + break; + if ((*cmdp)->c_name != NULL && (*cmdp)->c_desc != NULL) { + snprintf(name, sizeof (name)," %-15s ", + (*cmdp)->c_name); + pager_output(name); + pager_output((*cmdp)->c_desc); + res = pager_output("\n"); + } } - } - pager_close(); - return(CMD_OK); + pager_close(); + return (CMD_OK); } /* @@ -247,35 +256,35 @@ COMMAND_SET(show, "show", "show variable(s)", command_show); static int command_show(int argc, char *argv[]) { - struct env_var *ev; - char *cp; - - if (argc < 2) { - /* - * With no arguments, print everything. - */ - pager_open(); - for (ev = environ; ev != NULL; ev = ev->ev_next) { - pager_output(ev->ev_name); - cp = getenv(ev->ev_name); - if (cp != NULL) { - pager_output("="); - pager_output(cp); - } - if (pager_output("\n")) - break; - } - pager_close(); - } else { - if ((cp = getenv(argv[1])) != NULL) { - printf("%s\n", cp); + struct env_var *ev; + char *cp; + + if (argc < 2) { + /* + * With no arguments, print everything. + */ + pager_open(); + for (ev = environ; ev != NULL; ev = ev->ev_next) { + pager_output(ev->ev_name); + cp = getenv(ev->ev_name); + if (cp != NULL) { + pager_output("="); + pager_output(cp); + } + if (pager_output("\n")) + break; + } + pager_close(); } else { - snprintf(command_errbuf, sizeof (command_errbuf), - "variable '%s' not found", argv[1]); - return(CMD_ERROR); + if ((cp = getenv(argv[1])) != NULL) { + printf("%s\n", cp); + } else { + snprintf(command_errbuf, sizeof (command_errbuf), + "variable '%s' not found", argv[1]); + return (CMD_ERROR); + } } - } - return(CMD_OK); + return (CMD_OK); } COMMAND_SET(set, "set", "set a variable", command_set); @@ -283,18 +292,18 @@ COMMAND_SET(set, "set", "set a variable", command_set); static int command_set(int argc, char *argv[]) { - int err; - - if (argc != 2) { - command_errmsg = "wrong number of arguments"; - return(CMD_ERROR); - } else { - if ((err = putenv(argv[1])) != 0) { - command_errmsg = strerror(err); - return(CMD_ERROR); + int err; + + if (argc != 2) { + command_errmsg = "wrong number of arguments"; + return (CMD_ERROR); + } else { + if ((err = putenv(argv[1])) != 0) { + command_errmsg = strerror(err); + return (CMD_ERROR); + } } - } - return(CMD_OK); + return (CMD_OK); } COMMAND_SET(setprop, "setprop", "set a variable", command_setprop); @@ -302,37 +311,37 @@ COMMAND_SET(setprop, "setprop", "set a variable", command_setprop); static int command_setprop(int argc, char *argv[]) { - int err; - - if (argc != 3) { - command_errmsg = "wrong number of arguments"; - return(CMD_ERROR); - } else { - if ((err = setenv(argv[1], argv[2], 1)) != 0) { - command_errmsg = strerror(err); - return(CMD_ERROR); + int err; + + if (argc != 3) { + command_errmsg = "wrong number of arguments"; + return (CMD_ERROR); + } else { + if ((err = setenv(argv[1], argv[2], 1)) != 0) { + command_errmsg = strerror(err); + return (CMD_ERROR); + } } - } - return(CMD_OK); + return (CMD_OK); } COMMAND_SET(unset, "unset", "unset a variable", command_unset); static int -command_unset(int argc, char *argv[]) +command_unset(int argc, char *argv[]) { - int err; - - if (argc != 2) { - command_errmsg = "wrong number of arguments"; - return(CMD_ERROR); - } else { - if ((err = unsetenv(argv[1])) != 0) { - command_errmsg = strerror(err); - return(CMD_ERROR); + int err; + + if (argc != 2) { + command_errmsg = "wrong number of arguments"; + return (CMD_ERROR); + } else { + if ((err = unsetenv(argv[1])) != 0) { + command_errmsg = strerror(err); + return (CMD_ERROR); + } } - } - return(CMD_OK); + return (CMD_OK); } COMMAND_SET(echo, "echo", "echo arguments", command_echo); @@ -340,34 +349,34 @@ COMMAND_SET(echo, "echo", "echo arguments", command_echo); static int command_echo(int argc, char *argv[]) { - char *s; - int nl, ch; - - nl = 0; - optind = 1; - optreset = 1; - while ((ch = getopt(argc, argv, "n")) != -1) { - switch(ch) { - case 'n': - nl = 1; - break; - case '?': - default: - /* getopt has already reported an error */ - return(CMD_OK); + char *s; + int nl, ch; + + nl = 0; + optind = 1; + optreset = 1; + while ((ch = getopt(argc, argv, "n")) != -1) { + switch (ch) { + case 'n': + nl = 1; + break; + case '?': + default: + /* getopt has already reported an error */ + return (CMD_OK); + } } - } - argv += (optind); - argc -= (optind); + argv += (optind); + argc -= (optind); - s = unargv(argc, argv); - if (s != NULL) { - printf("%s", s); - free(s); - } - if (!nl) - printf("\n"); - return(CMD_OK); + s = unargv(argc, argv); + if (s != NULL) { + printf("%s", s); + free(s); + } + if (!nl) + printf("\n"); + return (CMD_OK); } /* @@ -379,55 +388,55 @@ COMMAND_SET(read, "read", "read input from the terminal", command_read); static int command_read(int argc, char *argv[]) { - char *prompt; - int timeout; - time_t when; - char *cp; - char *name; - char buf[256]; /* XXX size? */ - int c; - - timeout = -1; - prompt = NULL; - optind = 1; - optreset = 1; - while ((c = getopt(argc, argv, "p:t:")) != -1) { - switch(c) { - - case 'p': - prompt = optarg; - break; - case 't': - timeout = strtol(optarg, &cp, 0); - if (cp == optarg) { - snprintf(command_errbuf, sizeof (command_errbuf), - "bad timeout '%s'", optarg); - return(CMD_ERROR); - } - break; - default: - return(CMD_OK); + char *prompt; + int timeout; + time_t when; + char *cp; + char *name; + char buf[256]; /* XXX size? */ + int c; + + timeout = -1; + prompt = NULL; + optind = 1; + optreset = 1; + while ((c = getopt(argc, argv, "p:t:")) != -1) { + switch (c) { + case 'p': + prompt = optarg; + break; + case 't': + timeout = strtol(optarg, &cp, 0); + if (cp == optarg) { + snprintf(command_errbuf, + sizeof (command_errbuf), + "bad timeout '%s'", optarg); + return (CMD_ERROR); + } + break; + default: + return (CMD_OK); + } } - } - - argv += (optind); - argc -= (optind); - name = (argc > 0) ? argv[0]: NULL; - - if (prompt != NULL) - printf("%s", prompt); - if (timeout >= 0) { - when = time(NULL) + timeout; - while (!ischar()) - if (time(NULL) >= when) - return(CMD_OK); /* is timeout an error? */ - } - - ngets(buf, sizeof(buf)); - - if (name != NULL) - setenv(name, buf, 1); - return(CMD_OK); + + argv += (optind); + argc -= (optind); + name = (argc > 0) ? argv[0]: NULL; + + if (prompt != NULL) + printf("%s", prompt); + if (timeout >= 0) { + when = time(NULL) + timeout; + while (!ischar()) + if (time(NULL) >= when) + return (CMD_OK); /* is timeout an error? */ + } + + ngets(buf, sizeof (buf)); + + if (name != NULL) + setenv(name, buf, 1); + return (CMD_OK); } /* @@ -438,44 +447,46 @@ COMMAND_SET(more, "more", "show contents of a file", command_more); static int command_more(int argc, char *argv[]) { - int i; - int res; - char line[80]; - - res=0; - pager_open(); - for (i = 1; (i < argc) && (res == 0); i++) { - snprintf(line, sizeof (line), "*** FILE %s BEGIN ***\n", argv[i]); - if (pager_output(line)) - break; - res = page_file(argv[i]); - if (!res) { - snprintf(line, sizeof (line), "*** FILE %s END ***\n", argv[i]); - res = pager_output(line); + int i; + int res; + char line[80]; + + res = 0; + pager_open(); + for (i = 1; (i < argc) && (res == 0); i++) { + snprintf(line, sizeof (line), "*** FILE %s BEGIN ***\n", + argv[i]); + if (pager_output(line)) + break; + res = page_file(argv[i]); + if (!res) { + snprintf(line, sizeof (line), "*** FILE %s END ***\n", + argv[i]); + res = pager_output(line); + } } - } - pager_close(); + pager_close(); - if (res == 0) - return CMD_OK; - else - return CMD_ERROR; + if (res == 0) + return (CMD_OK); + else + return (CMD_ERROR); } static int page_file(char *filename) { - int result; + int result; - result = pager_file(filename); + result = pager_file(filename); - if (result == -1) { - snprintf(command_errbuf, sizeof (command_errbuf), - "error showing %s", filename); - } + if (result == -1) { + snprintf(command_errbuf, sizeof (command_errbuf), + "error showing %s", filename); + } - return result; -} + return (result); +} /* * List all disk-like devices @@ -485,37 +496,38 @@ COMMAND_SET(lsdev, "lsdev", "list all devices", command_lsdev); static int command_lsdev(int argc, char *argv[]) { - int verbose, ch, i; - char line[80]; - - verbose = 0; - optind = 1; - optreset = 1; - while ((ch = getopt(argc, argv, "v")) != -1) { - switch(ch) { - case 'v': - verbose = 1; - break; - case '?': - default: - /* getopt has already reported an error */ - return(CMD_OK); + int verbose, ch, i; + char line[80]; + + verbose = 0; + optind = 1; + optreset = 1; + while ((ch = getopt(argc, argv, "v")) != -1) { + switch (ch) { + case 'v': + verbose = 1; + break; + case '?': + default: + /* getopt has already reported an error */ + return (CMD_OK); + } } - } - argv += (optind); - argc -= (optind); - - pager_open(); - for (i = 0; devsw[i] != NULL; i++) { - if (devsw[i]->dv_print != NULL){ - if (devsw[i]->dv_print(verbose)) - break; - } else { - snprintf(line, sizeof (line), "%s: (unknown)\n", devsw[i]->dv_name); - if (pager_output(line)) - break; + argv += (optind); + argc -= (optind); + + pager_open(); + for (i = 0; devsw[i] != NULL; i++) { + if (devsw[i]->dv_print != NULL) { + if (devsw[i]->dv_print(verbose)) + break; + } else { + snprintf(line, sizeof (line), "%s: (unknown)\n", + devsw[i]->dv_name); + if (pager_output(line)) + break; + } } - } - pager_close(); - return(CMD_OK); + pager_close(); + return (CMD_OK); } diff --git a/usr/src/common/ficl/emu/loader_emu.c b/usr/src/common/ficl/emu/loader_emu.c index ad5ce87cbc..51e368cc99 100644 --- a/usr/src/common/ficl/emu/loader_emu.c +++ b/usr/src/common/ficl/emu/loader_emu.c @@ -1074,18 +1074,18 @@ help_getnext(int fd, char **topic, char **subtopic, char **desc) if (fgetstr(line, 80, fd) < 0) return (0); - if ((strlen(line) < 3) || (line[0] != '#') || (line[1] != ' ')) + if (strlen(line) < 3 || line[0] != '#' || line[1] != ' ') continue; *topic = *subtopic = *desc = NULL; cp = line + 2; - while ((cp != NULL) && (*cp != 0)) { + while (cp != NULL && *cp != 0) { ep = strchr(cp, ' '); - if ((*cp == 'T') && (*topic == NULL)) { + if (*cp == 'T' && *topic == NULL) { if (ep != NULL) *ep++ = 0; *topic = strdup(cp + 1); - } else if ((*cp == 'S') && (*subtopic == NULL)) { + } else if (*cp == 'S' && *subtopic == NULL) { if (ep != NULL) *ep++ = 0; *subtopic = strdup(cp + 1); @@ -1178,18 +1178,18 @@ command_help(int argc, char *argv[]) } else { /* topic matched */ matched = 1; - if (((subtopic == NULL) && (s == NULL)) || - ((subtopic != NULL) && (s != NULL) && + if ((subtopic == NULL && s == NULL) || + (subtopic != NULL && s != NULL && strcmp(subtopic, s) == 0)) { /* exact match, print text */ - while ((fgetstr(buf, 80, hfd) >= 0) && - (buf[0] != '#')) { + while (fgetstr(buf, 80, hfd) >= 0 && + buf[0] != '#') { if (pager_output(buf)) break; if (pager_output("\n")) break; } - } else if ((subtopic == NULL) && (s != NULL)) { + } else if (subtopic == NULL && s != NULL) { /* topic match, list subtopics */ if (help_emitsummary(t, s, d)) break; @@ -1231,7 +1231,7 @@ command_commandlist(int argc __unused, char *argv[] __unused) STAILQ_FOREACH(cmdp, &commands, next) { if (res) break; - if ((cmdp->c_name != NULL) && (cmdp->c_desc != NULL)) { + if (cmdp->c_name != NULL && cmdp->c_desc != NULL) { snprintf(name, sizeof (name), " %-15s ", cmdp->c_name); pager_output(name); -- cgit v1.2.3 From 4b9a859a90a27a1aaf064cac9a4fa96bcca57337 Mon Sep 17 00:00:00 2001 From: Marcel Telka Date: Mon, 12 Feb 2018 20:32:44 +0200 Subject: 9651 README.pkg: Extra zero in PKGVERS Reviewed by: Toomas Soome Reviewed by: Vitaliy Gusev Approved by: Dan McDonald --- usr/src/pkg/README.pkg | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/usr/src/pkg/README.pkg b/usr/src/pkg/README.pkg index 823e3cf152..9c4d86ad3f 100644 --- a/usr/src/pkg/README.pkg +++ b/usr/src/pkg/README.pkg @@ -218,7 +218,7 @@ These are the PKGMOG_DEFINES in usr/src/pkg/Makefile. $(ARCH32) $(ARCH64) $(PKGVERS), which is set to - $(PKGVERS_COMPONENT),$(PKGVERS_BUILTON)-0.$(PKGVERS_BRANCH) + $(PKGVERS_COMPONENT),$(PKGVERS_BUILTON)-$(PKGVERS_BRANCH) pkgmogrify(1) also allows us to include a set of default transformations. The definitions for these transforms are in usr/src/pkg/transforms/. An -- cgit v1.2.3 From 284ce987a33170d916c005f044ef6ce9ce8e1517 Mon Sep 17 00:00:00 2001 From: Patrick Mooney Date: Thu, 3 Aug 2017 18:19:56 +0000 Subject: 9641 want stack-clash mitigation Reviewed by: Jerry Jelinek Reviewed by: Alex Wilson Reviewed by: Mike Gerdts Reviewed by: Toomas Soome Approved by: Robert Mustacchi --- usr/src/cmd/mdb/common/modules/genunix/memory.c | 43 +++- usr/src/uts/common/Makefile.files | 1 + usr/src/uts/common/exec/elf/elf.c | 4 + usr/src/uts/common/fs/proc/prioctl.c | 25 ++ usr/src/uts/common/fs/proc/prsubr.c | 35 +++ usr/src/uts/common/fs/ufs/ufs_vnops.c | 3 +- usr/src/uts/common/os/exec.c | 62 ++++- usr/src/uts/common/os/grow.c | 36 ++- usr/src/uts/common/sys/proc.h | 11 +- usr/src/uts/common/vm/as.h | 10 +- usr/src/uts/common/vm/seg.h | 3 +- usr/src/uts/common/vm/seg_dev.c | 4 +- usr/src/uts/common/vm/seg_dev.h | 3 +- usr/src/uts/common/vm/seg_hole.c | 304 ++++++++++++++++++++++++ usr/src/uts/common/vm/seg_hole.h | 40 ++++ usr/src/uts/common/vm/seg_spt.c | 10 +- usr/src/uts/common/vm/seg_spt.h | 5 +- usr/src/uts/common/vm/seg_umap.c | 5 +- usr/src/uts/common/vm/seg_umap.h | 4 +- usr/src/uts/common/vm/seg_vn.c | 43 ++-- usr/src/uts/common/vm/seg_vn.h | 8 +- usr/src/uts/common/vm/vm_as.c | 156 ++++++++---- usr/src/uts/i86pc/vm/vm_machdep.c | 21 +- usr/src/uts/i86xpv/vm/seg_mf.c | 4 +- usr/src/uts/i86xpv/vm/seg_mf.h | 3 +- 25 files changed, 721 insertions(+), 122 deletions(-) create mode 100644 usr/src/uts/common/vm/seg_hole.c create mode 100644 usr/src/uts/common/vm/seg_hole.h diff --git a/usr/src/cmd/mdb/common/modules/genunix/memory.c b/usr/src/cmd/mdb/common/modules/genunix/memory.c index 34e746f36c..fa4918b9b8 100644 --- a/usr/src/cmd/mdb/common/modules/genunix/memory.c +++ b/usr/src/cmd/mdb/common/modules/genunix/memory.c @@ -20,7 +20,7 @@ */ /* * Copyright (c) 2001, 2010, Oracle and/or its affiliates. All rights reserved. - * Copyright 2015 Joyent, Inc. + * Copyright 2017 Joyent, Inc. */ #include @@ -40,6 +40,7 @@ #include #include #include +#include #if defined(__i386) || defined(__amd64) #include #endif @@ -975,6 +976,11 @@ seg(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv) return (DCMD_OK); } +typedef struct pmap_walk_types { + uintptr_t pwt_segvn; + uintptr_t pwt_seghole; +} pmap_walk_types_t; + /*ARGSUSED*/ static int pmap_walk_count_pages(uintptr_t addr, const void *data, void *out) @@ -987,12 +993,14 @@ pmap_walk_count_pages(uintptr_t addr, const void *data, void *out) } static int -pmap_walk_seg(uintptr_t addr, const struct seg *seg, uintptr_t segvn) +pmap_walk_seg(uintptr_t addr, const struct seg *seg, + const pmap_walk_types_t *types) { + const uintptr_t ops = (uintptr_t)seg->s_ops; mdb_printf("%0?p %0?p %7dk", addr, seg->s_base, seg->s_size / 1024); - if (segvn == (uintptr_t)seg->s_ops && seg->s_data != NULL) { + if (ops == types->pwt_segvn && seg->s_data != NULL) { struct segvn_data svn; pgcnt_t nres = 0; @@ -1018,6 +1026,18 @@ pmap_walk_seg(uintptr_t addr, const struct seg *seg, uintptr_t segvn) } else { mdb_printf(" [ anon ]"); } + } else if (ops == types->pwt_seghole && seg->s_data != NULL) { + seghole_data_t shd; + char name[16]; + + (void) mdb_vread(&shd, sizeof (shd), (uintptr_t)seg->s_data); + if (shd.shd_name == NULL || mdb_readstr(name, sizeof (name), + (uintptr_t)shd.shd_name) == 0) { + name[0] = '\0'; + } + + mdb_printf(" %8s [ hole%s%s ]", "-", + name[0] == '0' ? "" : ":", name); } else { mdb_printf(" %8s [ &%a ]", "?", seg->s_ops); } @@ -1027,11 +1047,14 @@ pmap_walk_seg(uintptr_t addr, const struct seg *seg, uintptr_t segvn) } static int -pmap_walk_seg_quick(uintptr_t addr, const struct seg *seg, uintptr_t segvn) +pmap_walk_seg_quick(uintptr_t addr, const struct seg *seg, + const pmap_walk_types_t *types) { + const uintptr_t ops = (uintptr_t)seg->s_ops; + mdb_printf("%0?p %0?p %7dk", addr, seg->s_base, seg->s_size / 1024); - if (segvn == (uintptr_t)seg->s_ops && seg->s_data != NULL) { + if (ops == types->pwt_segvn && seg->s_data != NULL) { struct segvn_data svn; svn.vp = NULL; @@ -1054,10 +1077,10 @@ pmap_walk_seg_quick(uintptr_t addr, const struct seg *seg, uintptr_t segvn) int pmap(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv) { - uintptr_t segvn; proc_t proc; uint_t quick = FALSE; mdb_walk_cb_t cb = (mdb_walk_cb_t)pmap_walk_seg; + pmap_walk_types_t wtypes = { 0 }; GElf_Sym sym; @@ -1074,9 +1097,9 @@ pmap(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv) } if (mdb_lookup_by_name("segvn_ops", &sym) == 0) - segvn = (uintptr_t)sym.st_value; - else - segvn = NULL; + wtypes.pwt_segvn = (uintptr_t)sym.st_value; + if (mdb_lookup_by_name("seghole_ops", &sym) == 0) + wtypes.pwt_seghole = (uintptr_t)sym.st_value; mdb_printf("%?s %?s %8s ", "SEG", "BASE", "SIZE"); @@ -1087,7 +1110,7 @@ pmap(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv) mdb_printf("%8s %s\n", "RES", "PATH"); } - if (mdb_pwalk("seg", cb, (void *)segvn, (uintptr_t)proc.p_as) == -1) { + if (mdb_pwalk("seg", cb, (void *)&wtypes, (uintptr_t)proc.p_as) == -1) { mdb_warn("failed to walk segments of as %p", proc.p_as); return (DCMD_ERR); } diff --git a/usr/src/uts/common/Makefile.files b/usr/src/uts/common/Makefile.files index 0071fb9b35..f06d10c527 100644 --- a/usr/src/uts/common/Makefile.files +++ b/usr/src/uts/common/Makefile.files @@ -303,6 +303,7 @@ GENUNIX_OBJS += \ sctp_crc32.o \ secflags.o \ seg_dev.o \ + seg_hole.o \ seg_kp.o \ seg_kpm.o \ seg_map.o \ diff --git a/usr/src/uts/common/exec/elf/elf.c b/usr/src/uts/common/exec/elf/elf.c index 141baa4aeb..d3cc0b8f0d 100644 --- a/usr/src/uts/common/exec/elf/elf.c +++ b/usr/src/uts/common/exec/elf/elf.c @@ -2075,6 +2075,10 @@ top: void *tmp = NULL; extern struct seg_ops segspt_shmops; + if ((seg->s_flags & S_HOLE) != 0) { + continue; + } + for (saddr = seg->s_base; saddr < eaddr; saddr = naddr) { uint_t prot; size_t size; diff --git a/usr/src/uts/common/fs/proc/prioctl.c b/usr/src/uts/common/fs/proc/prioctl.c index f1f39ed3be..3ed40c5d96 100644 --- a/usr/src/uts/common/fs/proc/prioctl.c +++ b/usr/src/uts/common/fs/proc/prioctl.c @@ -22,6 +22,7 @@ /* * Copyright 2010 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. + * Copyright 2017 Joyent, Inc. */ /* Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T */ @@ -3542,6 +3543,10 @@ oprgetmap(proc_t *p, list_t *iolhead) caddr_t saddr, naddr; void *tmp = NULL; + if ((seg->s_flags & S_HOLE) != 0) { + continue; + } + for (saddr = seg->s_base; saddr < eaddr; saddr = naddr) { prot = pr_getprot(seg, 0, &tmp, &saddr, &naddr, eaddr); if (saddr == naddr) @@ -3602,6 +3607,10 @@ oprgetmap32(proc_t *p, list_t *iolhead) caddr_t saddr, naddr; void *tmp = NULL; + if ((seg->s_flags & S_HOLE) != 0) { + continue; + } + for (saddr = seg->s_base; saddr < eaddr; saddr = naddr) { prot = pr_getprot(seg, 0, &tmp, &saddr, &naddr, eaddr); if (saddr == naddr) @@ -3655,6 +3664,10 @@ oprpdsize(struct as *as) void *tmp = NULL; size_t npage; + if ((seg->s_flags & S_HOLE) != 0) { + continue; + } + for (saddr = seg->s_base; saddr < eaddr; saddr = naddr) { (void) pr_getprot(seg, 0, &tmp, &saddr, &naddr, eaddr); if ((npage = (naddr - saddr) / PAGESIZE) != 0) @@ -3685,6 +3698,10 @@ oprpdsize32(struct as *as) void *tmp = NULL; size_t npage; + if ((seg->s_flags & S_HOLE) != 0) { + continue; + } + for (saddr = seg->s_base; saddr < eaddr; saddr = naddr) { (void) pr_getprot(seg, 0, &tmp, &saddr, &naddr, eaddr); if ((npage = (naddr - saddr) / PAGESIZE) != 0) @@ -3735,6 +3752,10 @@ again: caddr_t saddr, naddr; void *tmp = NULL; + if ((seg->s_flags & S_HOLE) != 0) { + continue; + } + for (saddr = seg->s_base; saddr < eaddr; saddr = naddr) { size_t len; size_t npage; @@ -3842,6 +3863,10 @@ again: caddr_t saddr, naddr; void *tmp = NULL; + if ((seg->s_flags & S_HOLE) != 0) { + continue; + } + for (saddr = seg->s_base; saddr < eaddr; saddr = naddr) { size_t len; size_t npage; diff --git a/usr/src/uts/common/fs/proc/prsubr.c b/usr/src/uts/common/fs/proc/prsubr.c index 4781fbaa77..a2ab06d769 100644 --- a/usr/src/uts/common/fs/proc/prsubr.c +++ b/usr/src/uts/common/fs/proc/prsubr.c @@ -1383,6 +1383,10 @@ prnsegs(struct as *as, int reserved) caddr_t saddr, naddr; void *tmp = NULL; + if ((seg->s_flags & S_HOLE) != 0) { + continue; + } + for (saddr = seg->s_base; saddr < eaddr; saddr = naddr) { (void) pr_getprot(seg, reserved, &tmp, &saddr, &naddr, eaddr); @@ -1638,6 +1642,10 @@ prgetmap(proc_t *p, int reserved, list_t *iolhead) caddr_t saddr, naddr; void *tmp = NULL; + if ((seg->s_flags & S_HOLE) != 0) { + continue; + } + for (saddr = seg->s_base; saddr < eaddr; saddr = naddr) { prot = pr_getprot(seg, reserved, &tmp, &saddr, &naddr, eaddr); @@ -1749,6 +1757,10 @@ prgetmap32(proc_t *p, int reserved, list_t *iolhead) caddr_t saddr, naddr; void *tmp = NULL; + if ((seg->s_flags & S_HOLE) != 0) { + continue; + } + for (saddr = seg->s_base; saddr < eaddr; saddr = naddr) { prot = pr_getprot(seg, reserved, &tmp, &saddr, &naddr, eaddr); @@ -1852,6 +1864,10 @@ prpdsize(struct as *as) void *tmp = NULL; size_t npage; + if ((seg->s_flags & S_HOLE) != 0) { + continue; + } + for (saddr = seg->s_base; saddr < eaddr; saddr = naddr) { (void) pr_getprot(seg, 0, &tmp, &saddr, &naddr, eaddr); if ((npage = (naddr - saddr) / PAGESIZE) != 0) @@ -1882,6 +1898,10 @@ prpdsize32(struct as *as) void *tmp = NULL; size_t npage; + if ((seg->s_flags & S_HOLE) != 0) { + continue; + } + for (saddr = seg->s_base; saddr < eaddr; saddr = naddr) { (void) pr_getprot(seg, 0, &tmp, &saddr, &naddr, eaddr); if ((npage = (naddr - saddr) / PAGESIZE) != 0) @@ -1933,6 +1953,10 @@ again: caddr_t saddr, naddr; void *tmp = NULL; + if ((seg->s_flags & S_HOLE) != 0) { + continue; + } + for (saddr = seg->s_base; saddr < eaddr; saddr = naddr) { struct vnode *vp; struct vattr vattr; @@ -2080,6 +2104,10 @@ again: caddr_t saddr, naddr; void *tmp = NULL; + if ((seg->s_flags & S_HOLE) != 0) { + continue; + } + for (saddr = seg->s_base; saddr < eaddr; saddr = naddr) { struct vnode *vp; struct vattr vattr; @@ -4032,6 +4060,9 @@ prgetxmap(proc_t *p, list_t *iolhead) uint64_t npages; uint64_t pagenum; + if ((seg->s_flags & S_HOLE) != 0) { + continue; + } /* * Segment loop part one: iterate from the base of the segment * to its end, pausing at each address boundary (baddr) between @@ -4228,6 +4259,10 @@ prgetxmap32(proc_t *p, list_t *iolhead) uint64_t npages; uint64_t pagenum; + if ((seg->s_flags & S_HOLE) != 0) { + continue; + } + /* * Segment loop part one: iterate from the base of the segment * to its end, pausing at each address boundary (baddr) between diff --git a/usr/src/uts/common/fs/ufs/ufs_vnops.c b/usr/src/uts/common/fs/ufs/ufs_vnops.c index 801e6f26fc..91efa776cc 100644 --- a/usr/src/uts/common/fs/ufs/ufs_vnops.c +++ b/usr/src/uts/common/fs/ufs/ufs_vnops.c @@ -21,7 +21,7 @@ /* * Copyright (c) 1984, 2010, Oracle and/or its affiliates. All rights reserved. - * Copyright 2017 Joyent, Inc. + * Copyright 2018 Joyent, Inc. * Copyright (c) 2016 by Delphix. All rights reserved. */ @@ -183,7 +183,6 @@ static int ufs_setsecattr(struct vnode *, vsecattr_t *, int, struct cred *, static int ufs_priv_access(void *, int, struct cred *); static int ufs_eventlookup(struct vnode *, char *, struct cred *, struct vnode **); -extern int as_map_locked(struct as *, caddr_t, size_t, int ((*)()), void *); /* * For lockfs: ulockfs begin/end is now inlined in the ufs_xxx functions. diff --git a/usr/src/uts/common/os/exec.c b/usr/src/uts/common/os/exec.c index 0065b4945b..53c552f135 100644 --- a/usr/src/uts/common/os/exec.c +++ b/usr/src/uts/common/os/exec.c @@ -26,7 +26,7 @@ /* Copyright (c) 1988 AT&T */ /* All Rights Reserved */ /* - * Copyright 2016 Joyent, Inc. + * Copyright 2017 Joyent, Inc. */ #include @@ -78,6 +78,7 @@ #include #include #include +#include #define PRIV_RESET 0x01 /* needs to reset privs */ #define PRIV_SETID 0x02 /* needs to change uids */ @@ -114,6 +115,14 @@ size_t aslr_max_brk_skew = 16 * 1024 * 1024; /* 16MB */ #pragma weak exec_stackgap = aslr_max_stack_skew /* Old, compatible name */ size_t aslr_max_stack_skew = 64 * 1024; /* 64KB */ +/* + * Size of guard segment for 64-bit processes and minimum size it can be shrunk + * to in the case of grow() operations. These are kept as variables in case + * they need to be tuned in an emergency. + */ +size_t stack_guard_seg_sz = 256 * 1024 * 1024; +size_t stack_guard_min_sz = 64 * 1024 * 1024; + /* * exece() - system call wrapper around exec_common() */ @@ -1858,6 +1867,15 @@ exec_get_spslew(void) * The initial user stack layout is as follows: * * User Stack + * +---------------+ + * | | + * | stack guard | + * | (64-bit only) | + * | | + * +...............+ <--- stack limit (base - curproc->p_stk_ctl) + * . . + * . . + * . . * +---------------+ <--- curproc->p_usrstack * | | * | slew | @@ -1899,6 +1917,11 @@ exec_get_spslew(void) * +---------------+ <--- argv[] * | argc | * +---------------+ <--- stack base + * + * In 64-bit processes, a stack guard segment is allocated at the address + * immediately below where the stack limit ends. This protects new library + * mappings (such as the linker) from being placed in relatively dangerous + * proximity to the stack. */ int exec_args(execa_t *uap, uarg_t *args, intpdata_t *intp, void **auxvpp) @@ -1912,6 +1935,9 @@ exec_args(execa_t *uap, uarg_t *args, intpdata_t *intp, void **auxvpp) struct as *as; extern int use_stk_lpg; size_t sp_slew; +#if defined(_LP64) + const size_t sg_sz = (stack_guard_seg_sz & PAGEMASK); +#endif /* defined(_LP64) */ args->from_model = p->p_model; if (p->p_model == DATAMODEL_NATIVE) { @@ -2060,6 +2086,8 @@ exec_args(execa_t *uap, uarg_t *args, intpdata_t *intp, void **auxvpp) p->p_brkpageszc = 0; p->p_stksize = 0; p->p_stkpageszc = 0; + p->p_stkg_start = 0; + p->p_stkg_end = 0; p->p_model = args->to_model; p->p_usrstack = usrstack; p->p_stkprot = args->stk_prot; @@ -2097,10 +2125,36 @@ exec_args(execa_t *uap, uarg_t *args, intpdata_t *intp, void **auxvpp) (void) hat_setup(as->a_hat, HAT_ALLOC); hat_join_srd(as->a_hat, args->ex_vp); - /* - * Finally, write out the contents of the new stack. - */ + /* Write out the contents of the new stack. */ error = stk_copyout(args, usrstack - sp_slew, auxvpp, up); kmem_free(args->stk_base, args->stk_size); + +#if defined(_LP64) + /* Add stack guard segment (if needed) after successful copyout */ + if (error == 0 && p->p_model == DATAMODEL_LP64 && sg_sz != 0) { + seghole_crargs_t sca; + caddr_t addr_end = (caddr_t)(((uintptr_t)usrstack - + p->p_stk_ctl) & PAGEMASK); + caddr_t addr_start = addr_end - sg_sz; + + DTRACE_PROBE4(stack__guard__chk, proc_t *, p, + caddr_t, addr_start, caddr_t, addr_end, size_t, sg_sz); + + if (addr_end >= usrstack || addr_start >= addr_end || + valid_usr_range(addr_start, sg_sz, PROT_NONE, as, + as->a_userlimit) != RANGE_OKAY) { + return (E2BIG); + } + + /* Create un-mappable area in AS with seg_hole */ + sca.name = "stack_guard"; + error = as_map(as, addr_start, sg_sz, seghole_create, &sca); + if (error == 0) { + p->p_stkg_start = (uintptr_t)addr_start; + p->p_stkg_end = (uintptr_t)addr_start + sg_sz; + } + } +#endif /* defined(_LP64) */ + return (error); } diff --git a/usr/src/uts/common/os/grow.c b/usr/src/uts/common/os/grow.c index 647bca2542..de2a4f26c4 100644 --- a/usr/src/uts/common/os/grow.c +++ b/usr/src/uts/common/os/grow.c @@ -19,7 +19,10 @@ * CDDL HEADER END */ -/* Copyright 2013 OmniTI Computer Consulting, Inc. All rights reserved. */ +/* + * Copyright 2013 OmniTI Computer Consulting, Inc. All rights reserved. + * Copyright 2017 Joyent, Inc. + */ /* * Copyright 2009 Sun Microsystems, Inc. All rights reserved. @@ -329,9 +332,10 @@ grow(caddr_t sp) } else { err = grow_internal(sp, p->p_stkpageszc); } + newsize = p->p_stksize; as_rangeunlock(as); - if (err == 0 && (newsize = p->p_stksize) > oldsize) { + if (err == 0 && newsize > oldsize) { ASSERT(IS_P2ALIGNED(oldsize, PAGESIZE)); ASSERT(IS_P2ALIGNED(newsize, PAGESIZE)); /* @@ -424,6 +428,7 @@ grow_internal(caddr_t sp, uint_t growszc) struct proc *p = curproc; size_t newsize; size_t oldsize; + uintptr_t new_start; int error; size_t pgsz; uint_t szc; @@ -494,7 +499,32 @@ grow_internal(caddr_t sp, uint_t growszc) } crargs.lgrp_mem_policy_flags = LGRP_MP_FLAG_EXTEND_DOWN; - if ((error = as_map(p->p_as, p->p_usrstack - newsize, newsize - oldsize, + /* + * The stack is about to grow into its guard. This can be acceptable + * if the size restriction on the stack has been expanded since its + * initialization during exec(). In such cases, the guard segment will + * be shrunk, provided the new size is reasonable. + */ + new_start = (uintptr_t)p->p_usrstack - newsize; + if (p->p_stkg_start != 0 && new_start > p->p_stkg_start && + new_start < p->p_stkg_end) { + const size_t unmap_sz = p->p_stkg_end - new_start; + const size_t remain_sz = new_start - p->p_stkg_start; + extern size_t stack_guard_min_sz; + + /* Do not allow the guard to shrink below minimum size */ + if (remain_sz < stack_guard_min_sz) { + return (ENOMEM); + } + + error = as_unmap(p->p_as, (caddr_t)new_start, unmap_sz); + if (error != 0) { + return (error); + } + p->p_stkg_end -= unmap_sz; + } + + if ((error = as_map(p->p_as, (caddr_t)new_start, newsize - oldsize, segvn_create, &crargs)) != 0) { if (error == EAGAIN) { cmn_err(CE_WARN, "Sorry, no swap space to grow stack " diff --git a/usr/src/uts/common/sys/proc.h b/usr/src/uts/common/sys/proc.h index e1b1a2289f..712bd7cb24 100644 --- a/usr/src/uts/common/sys/proc.h +++ b/usr/src/uts/common/sys/proc.h @@ -251,8 +251,15 @@ typedef struct proc { kmutex_t p_maplock; /* lock for pr_mappage() */ struct proc *p_rlink; /* linked list for server */ kcondvar_t p_srwchan_cv; - size_t p_stksize; /* process stack size in bytes */ - uint_t p_stkpageszc; /* preferred stack max page size code */ + + /* + * Stack sizing and guard information. + * Generally protected by as_rangelock() + */ + size_t p_stksize; /* process stack size in bytes */ + uint_t p_stkpageszc; /* preferred stack max page size code */ + uintptr_t p_stkg_start; /* start of stack guard */ + uintptr_t p_stkg_end; /* end of stack guard */ /* * Microstate accounting, resource usage, and real-time profiling diff --git a/usr/src/uts/common/vm/as.h b/usr/src/uts/common/vm/as.h index e910db1ddc..83bd7b52ba 100644 --- a/usr/src/uts/common/vm/as.h +++ b/usr/src/uts/common/vm/as.h @@ -24,7 +24,7 @@ */ /* - * Copyright (c) 2013, Joyent, Inc. All rights reserved. + * Copyright 2018 Joyent, Inc. */ /* Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T */ @@ -256,6 +256,8 @@ extern struct as kas; /* kernel's address space */ #define AS_SEGNEXT(as, seg) AVL_NEXT(&(as)->a_segtree, (seg)) #define AS_SEGPREV(as, seg) AVL_PREV(&(as)->a_segtree, (seg)) +typedef int (*segcreate_func_t)(struct seg **, void *); + void as_init(void); void as_avlinit(struct as *); struct seg *as_segat(struct as *as, caddr_t addr); @@ -273,8 +275,10 @@ faultcode_t as_faulta(struct as *as, caddr_t addr, size_t size); int as_setprot(struct as *as, caddr_t addr, size_t size, uint_t prot); int as_checkprot(struct as *as, caddr_t addr, size_t size, uint_t prot); int as_unmap(struct as *as, caddr_t addr, size_t size); -int as_map(struct as *as, caddr_t addr, size_t size, int ((*crfp)()), - void *argsp); +int as_map(struct as *as, caddr_t addr, size_t size, segcreate_func_t crfp, + void *argsp); +int as_map_locked(struct as *as, caddr_t addr, size_t size, + segcreate_func_t crfp, void *argsp); void as_purge(struct as *as); int as_gap(struct as *as, size_t minlen, caddr_t *basep, size_t *lenp, uint_t flags, caddr_t addr); diff --git a/usr/src/uts/common/vm/seg.h b/usr/src/uts/common/vm/seg.h index be1c9514e9..9dde7028c4 100644 --- a/usr/src/uts/common/vm/seg.h +++ b/usr/src/uts/common/vm/seg.h @@ -21,7 +21,7 @@ /* * Copyright 2008 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. - * Copyright (c) 2015, Joyent, Inc. + * Copyright 2017 Joyent, Inc. */ /* Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T */ @@ -113,6 +113,7 @@ typedef struct seg { } seg_t; #define S_PURGE (0x01) /* seg should be purged in as_gap() */ +#define S_HOLE (0x02) /* seg represents hole in AS */ struct seg_ops { int (*dup)(struct seg *, struct seg *); diff --git a/usr/src/uts/common/vm/seg_dev.c b/usr/src/uts/common/vm/seg_dev.c index f43a288cec..89e6461bbf 100644 --- a/usr/src/uts/common/vm/seg_dev.c +++ b/usr/src/uts/common/vm/seg_dev.c @@ -22,6 +22,7 @@ /* * Copyright 2010 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. + * Copyright 2018 Joyent, Inc. */ /* Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T */ @@ -357,8 +358,9 @@ devmap_ctxto(void *data) * Create a device segment. */ int -segdev_create(struct seg *seg, void *argsp) +segdev_create(struct seg **segpp, void *argsp) { + struct seg *seg = *segpp; struct segdev_data *sdp; struct segdev_crargs *a = (struct segdev_crargs *)argsp; devmap_handle_t *dhp = (devmap_handle_t *)a->devmap_data; diff --git a/usr/src/uts/common/vm/seg_dev.h b/usr/src/uts/common/vm/seg_dev.h index 6240125489..07a15afc6b 100644 --- a/usr/src/uts/common/vm/seg_dev.h +++ b/usr/src/uts/common/vm/seg_dev.h @@ -21,6 +21,7 @@ /* * Copyright 2009 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. + * Copyright 2018 Joyent, Inc. */ /* Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T */ @@ -122,7 +123,7 @@ struct devmap_pmem_cookie { extern void segdev_init(void); -extern int segdev_create(struct seg *, void *); +extern int segdev_create(struct seg **, void *); extern int segdev_copyto(struct seg *, caddr_t, const void *, void *, size_t); extern int segdev_copyfrom(struct seg *, caddr_t, const void *, void *, size_t); diff --git a/usr/src/uts/common/vm/seg_hole.c b/usr/src/uts/common/vm/seg_hole.c new file mode 100644 index 0000000000..14b2153718 --- /dev/null +++ b/usr/src/uts/common/vm/seg_hole.c @@ -0,0 +1,304 @@ +/* + * This file and its contents are supplied under the terms of the + * Common Development and Distribution License ("CDDL"), version 1.0. + * You may only use this file in accordance with the terms of version + * 1.0 of the CDDL. + * + * A full copy of the text of the CDDL should have accompanied this + * source. A copy of the CDDL is also available via the Internet at + * http://www.illumos.org/license/CDDL. + */ + +/* + * Copyright 2018 Joyent, Inc. + */ + + +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include + + +static int seghole_dup(struct seg *, struct seg *); +static int seghole_unmap(struct seg *, caddr_t, size_t); +static void seghole_free(struct seg *); +static faultcode_t seghole_fault(struct hat *, struct seg *, caddr_t, size_t, + enum fault_type, enum seg_rw); +static faultcode_t seghole_faulta(struct seg *, caddr_t); +static int seghole_setprot(struct seg *, caddr_t, size_t, uint_t); +static int seghole_checkprot(struct seg *, caddr_t, size_t, uint_t); +static int seghole_sync(struct seg *, caddr_t, size_t, int, uint_t); +static size_t seghole_incore(struct seg *, caddr_t, size_t, char *); +static int seghole_lockop(struct seg *, caddr_t, size_t, int, int, ulong_t *, + size_t); +static int seghole_getprot(struct seg *, caddr_t, size_t, uint_t *); +static u_offset_t seghole_getoffset(struct seg *, caddr_t); +static int seghole_gettype(struct seg *, caddr_t); +static int seghole_getvp(struct seg *, caddr_t, struct vnode **); +static int seghole_advise(struct seg *, caddr_t, size_t, uint_t); +static void seghole_dump(struct seg *); +static int seghole_pagelock(struct seg *, caddr_t, size_t, struct page ***, + enum lock_type, enum seg_rw); +static int seghole_setpagesize(struct seg *, caddr_t, size_t, uint_t); +static int seghole_capable(struct seg *, segcapability_t); + +static struct seg_ops seghole_ops = { + seghole_dup, + seghole_unmap, + seghole_free, + seghole_fault, + seghole_faulta, + seghole_setprot, + seghole_checkprot, + NULL, /* kluster: disabled */ + NULL, /* swapout: disabled */ + seghole_sync, + seghole_incore, + seghole_lockop, + seghole_getprot, + seghole_getoffset, + seghole_gettype, + seghole_getvp, + seghole_advise, + seghole_dump, + seghole_pagelock, + seghole_setpagesize, + NULL, /* getmemid: disabled */ + NULL, /* getpolicy: disabled */ + seghole_capable, + seg_inherit_notsup +}; + +/* + * Create a hole in the AS. + */ +int +seghole_create(struct seg **segpp, void *argsp) +{ + struct seg *seg = *segpp; + seghole_crargs_t *crargs = argsp; + seghole_data_t *data; + + data = kmem_alloc(sizeof (seghole_data_t), KM_SLEEP); + data->shd_name = crargs->name; + + seg->s_ops = &seghole_ops; + seg->s_data = data; + seg->s_flags = S_HOLE; + + return (0); +} + +static int +seghole_dup(struct seg *seg, struct seg *newseg) +{ + seghole_data_t *shd = (seghole_data_t *)seg->s_data; + seghole_data_t *newshd; + + ASSERT(seg->s_as && AS_WRITE_HELD(seg->s_as)); + + newshd = kmem_zalloc(sizeof (seghole_data_t), KM_SLEEP); + newshd->shd_name = shd->shd_name; + + newseg->s_ops = seg->s_ops; + newseg->s_data = newshd; + newseg->s_flags = S_HOLE; + + return (0); +} + +static int +seghole_unmap(struct seg *seg, caddr_t addr, size_t len) +{ + ASSERT(seg->s_as && AS_WRITE_HELD(seg->s_as)); + + /* Entire segment is being unmapped */ + if (addr == seg->s_base && len == seg->s_size) { + seg_free(seg); + return (0); + } + + /* Shrinking from low address side */ + if (addr == seg->s_base) { + seg->s_base += len; + seg->s_size -= len; + return (0); + } + + /* Shrinking from high address side */ + if ((addr + len) == (seg->s_base + seg->s_size)) { + seg->s_size -= len; + return (0); + } + + /* Do not tolerate splitting the segment */ + return (EINVAL); +} + +static void +seghole_free(struct seg *seg) +{ + seghole_data_t *data = (seghole_data_t *)seg->s_data; + + ASSERT(data != NULL); + + kmem_free(data, sizeof (*data)); + seg->s_data = NULL; +} + +/* ARGSUSED */ +static faultcode_t +seghole_fault(struct hat *hat, struct seg *seg, caddr_t addr, size_t len, + enum fault_type type, enum seg_rw tw) +{ + ASSERT(seg->s_as && AS_LOCK_HELD(seg->s_as)); + + return (FC_NOMAP); +} + +/* ARGSUSED */ +static faultcode_t +seghole_faulta(struct seg *seg, caddr_t addr) +{ + return (FC_NOMAP); +} + +/* ARGSUSED */ +static int +seghole_setprot(struct seg *seg, caddr_t addr, size_t len, uint_t prot) +{ + ASSERT(seg->s_as && AS_LOCK_HELD(seg->s_as)); + + return (ENOMEM); +} + +/* ARGSUSED */ +static int +seghole_checkprot(struct seg *seg, caddr_t addr, size_t len, uint_t prot) +{ + ASSERT(seg->s_as && AS_LOCK_HELD(seg->s_as)); + + return (ENOMEM); +} + +/* ARGSUSED */ +static int +seghole_sync(struct seg *seg, caddr_t addr, size_t len, int attr, uint_t flags) +{ + /* Always succeed since there are no backing store to sync */ + return (0); +} + +/* ARGSUSED */ +static size_t +seghole_incore(struct seg *seg, caddr_t addr, size_t len, char *vec) +{ + ASSERT(seg->s_as && AS_LOCK_HELD(seg->s_as)); + + return (0); +} + +/* ARGSUSED */ +static int +seghole_lockop(struct seg *seg, caddr_t addr, size_t len, int attr, int op, + ulong_t *lockmap, size_t pos) +{ + /* + * Emit an error consistent with there being no segment in this hole in + * the AS. The MC_LOCKAS and MC_UNLOCKAS commands will explicitly skip + * hole segments, allowing such operations to proceed as expected. + */ + return (ENOMEM); +} + +static int +seghole_getprot(struct seg *seg, caddr_t addr, size_t len, uint_t *protv) +{ + size_t pgno; + + ASSERT(seg->s_as && AS_LOCK_HELD(seg->s_as)); + + /* + * Few SEGOP_GETPROT callers actually check for an error, so it's + * necessary to report zeroed protection for the length of the request. + */ + pgno = seg_page(seg, addr + len) - seg_page(seg, addr) + 1; + while (pgno > 0) { + protv[--pgno] = 0; + } + + return (ENOMEM); +} + +/* ARGSUSED */ +static u_offset_t +seghole_getoffset(struct seg *seg, caddr_t addr) +{ + /* + * To avoid leaking information about the layout of the kernel address + * space, always report '0' as the offset. + */ + return (0); +} + +/* ARGSUSED */ +static int +seghole_gettype(struct seg *seg, caddr_t addr) +{ + return (MAP_PRIVATE); +} + +/* ARGSUSED */ +static int +seghole_getvp(struct seg *seg, caddr_t addr, struct vnode **vpp) +{ + ASSERT(seg->s_as && AS_LOCK_HELD(seg->s_as)); + + return (ENOMEM); +} + +/* ARGSUSED */ +static int +seghole_advise(struct seg *seg, caddr_t addr, size_t len, uint_t behav) +{ + return (ENOMEM); +} + +/* ARGSUSED */ +static void +seghole_dump(struct seg *seg) +{ + /* There's nothing to dump from a hole in the AS */ +} + +/* ARGSUSED */ +static int +seghole_pagelock(struct seg *seg, caddr_t addr, size_t len, struct page ***ppp, + enum lock_type type, enum seg_rw rw) +{ + return (EFAULT); +} + +/* ARGSUSED */ +static int +seghole_setpagesize(struct seg *seg, caddr_t addr, size_t len, uint_t szc) +{ + return (ENOMEM); +} + +/* ARGSUSED */ +static int +seghole_capable(struct seg *seg, segcapability_t capability) +{ + /* no special capablities */ + return (0); +} diff --git a/usr/src/uts/common/vm/seg_hole.h b/usr/src/uts/common/vm/seg_hole.h new file mode 100644 index 0000000000..2bff880f4f --- /dev/null +++ b/usr/src/uts/common/vm/seg_hole.h @@ -0,0 +1,40 @@ +/* + * This file and its contents are supplied under the terms of the + * Common Development and Distribution License ("CDDL"), version 1.0. + * You may only use this file in accordance with the terms of version + * 1.0 of the CDDL. + * + * A full copy of the text of the CDDL should have accompanied this + * source. A copy of the CDDL is also available via the Internet at + * http://www.illumos.org/license/CDDL. + */ + +/* + * Copyright 2018 Joyent, Inc. + */ + +#ifndef _VM_SEG_HOLE_H +#define _VM_SEG_HOLE_H + +#ifdef __cplusplus +extern "C" { +#endif + +typedef struct seghole_crargs { + const char *name; +} seghole_crargs_t; + +typedef struct seghole_data { + const char *shd_name; +} seghole_data_t; + +extern int seghole_create(struct seg **, void *); + +#define AS_MAP_CHECK_SEGHOLE(crfp) \ + ((crfp) == (segcreate_func_t)seghole_create) + +#ifdef __cplusplus +} +#endif + +#endif /* _VM_SEG_HOLE_H */ diff --git a/usr/src/uts/common/vm/seg_spt.c b/usr/src/uts/common/vm/seg_spt.c index b0f992b7a6..cc00e16333 100644 --- a/usr/src/uts/common/vm/seg_spt.c +++ b/usr/src/uts/common/vm/seg_spt.c @@ -20,7 +20,7 @@ */ /* * Copyright (c) 1993, 2010, Oracle and/or its affiliates. All rights reserved. - * Copyright (c) 2015, Joyent, Inc. All rights reserved. + * Copyright 2018 Joyent, Inc. * Copyright (c) 2016 by Delphix. All rights reserved. */ @@ -72,7 +72,7 @@ size_t spt_used; */ pgcnt_t segspt_minfree = 0; -static int segspt_create(struct seg *seg, caddr_t argsp); +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); @@ -369,8 +369,9 @@ segspt_unmap(struct seg *seg, caddr_t raddr, size_t ssize) } int -segspt_create(struct seg *seg, caddr_t argsp) +segspt_create(struct seg **segpp, void *argsp) { + struct seg *seg = *segpp; int err; caddr_t addr = seg->s_base; struct spt_data *sptd; @@ -1671,8 +1672,9 @@ softlock_decrement: } int -segspt_shmattach(struct seg *seg, caddr_t *argsp) +segspt_shmattach(struct seg **segpp, void *argsp) { + struct seg *seg = *segpp; struct shm_data *shmd_arg = (struct shm_data *)argsp; struct shm_data *shmd; struct anon_map *shm_amp = shmd_arg->shm_amp; diff --git a/usr/src/uts/common/vm/seg_spt.h b/usr/src/uts/common/vm/seg_spt.h index ebc2ebf465..d8cea0a4d0 100644 --- a/usr/src/uts/common/vm/seg_spt.h +++ b/usr/src/uts/common/vm/seg_spt.h @@ -21,13 +21,12 @@ /* * Copyright 2008 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. + * Copyright 2018 Joyent, Inc. */ #ifndef _VM_SEG_SPT_H #define _VM_SEG_SPT_H -#pragma ident "%Z%%M% %I% %E% SMI" - #ifdef __cplusplus extern "C" { #endif @@ -101,7 +100,7 @@ typedef struct shm_data { int sptcreate(size_t size, struct seg **sptseg, struct anon_map *amp, uint_t prot, uint_t flags, uint_t szc); void sptdestroy(struct as *, struct anon_map *); -int segspt_shmattach(struct seg *, caddr_t *); +int segspt_shmattach(struct seg **, void *); #define isspt(sp) ((sp)->shm_sptinfo ? (sp)->shm_sptinfo->sptas : NULL) #define spt_locked(a) ((a) & SHM_SHARE_MMU) diff --git a/usr/src/uts/common/vm/seg_umap.c b/usr/src/uts/common/vm/seg_umap.c index 3b4bb04f69..985cb51759 100644 --- a/usr/src/uts/common/vm/seg_umap.c +++ b/usr/src/uts/common/vm/seg_umap.c @@ -10,7 +10,7 @@ */ /* - * Copyright 2016 Joyent, Inc. + * Copyright 2018 Joyent, Inc. */ /* @@ -99,8 +99,9 @@ static struct seg_ops segumap_ops = { * Create a kernel/user-mapped segment. */ int -segumap_create(struct seg *seg, void *argsp) +segumap_create(struct seg **segpp, void *argsp) { + struct seg *seg = *segpp; segumap_crargs_t *a = (struct segumap_crargs *)argsp; segumap_data_t *data; diff --git a/usr/src/uts/common/vm/seg_umap.h b/usr/src/uts/common/vm/seg_umap.h index 8db23723ed..c348bf471a 100644 --- a/usr/src/uts/common/vm/seg_umap.h +++ b/usr/src/uts/common/vm/seg_umap.h @@ -10,7 +10,7 @@ */ /* - * Copyright 2016 Joyent, Inc. + * Copyright 2018 Joyent, Inc. */ #ifndef _VM_SEG_UMAP_H @@ -33,7 +33,7 @@ typedef struct segumap_data { size_t sud_softlockcnt; } segumap_data_t; -extern int segumap_create(struct seg *, void *); +extern int segumap_create(struct seg **, void *); #ifdef __cplusplus } diff --git a/usr/src/uts/common/vm/seg_vn.c b/usr/src/uts/common/vm/seg_vn.c index 875dec7fe9..deb08c24e6 100644 --- a/usr/src/uts/common/vm/seg_vn.c +++ b/usr/src/uts/common/vm/seg_vn.c @@ -20,7 +20,7 @@ */ /* * Copyright (c) 1986, 2010, Oracle and/or its affiliates. All rights reserved. - * Copyright 2015, Joyent, Inc. All rights reserved. + * Copyright 2018 Joyent, Inc. * Copyright 2015 Nexenta Systems, Inc. All rights reserved. */ @@ -538,8 +538,9 @@ segvn_setvnode_mpss(vnode_t *vp) } int -segvn_create(struct seg *seg, void *argsp) +segvn_create(struct seg **segpp, void *argsp) { + struct seg *seg = *segpp; extern lgrp_mem_policy_t lgrp_mem_default_policy; struct segvn_crargs *a = (struct segvn_crargs *)argsp; struct segvn_data *svd; @@ -758,6 +759,11 @@ segvn_create(struct seg *seg, void *argsp) (a->szc == pseg->s_szc && IS_P2ALIGNED(pseg->s_base, pgsz) && IS_P2ALIGNED(pseg->s_size, pgsz))); + /* + * Communicate out the newly concatenated + * segment as part of the result. + */ + *segpp = pseg; return (0); } } @@ -797,6 +803,11 @@ segvn_create(struct seg *seg, void *argsp) (a->szc == nseg->s_szc && IS_P2ALIGNED(nseg->s_base, pgsz) && IS_P2ALIGNED(nseg->s_size, pgsz))); + /* + * Communicate out the newly concatenated + * segment as part of the result. + */ + *segpp = nseg; return (0); } } @@ -1253,10 +1264,8 @@ segvn_concat(struct seg *seg1, struct seg *seg2, int amp_cat) * Return 0 on success. */ static int -segvn_extend_prev(seg1, seg2, a, swresv) - struct seg *seg1, *seg2; - struct segvn_crargs *a; - size_t swresv; +segvn_extend_prev(struct seg *seg1, struct seg *seg2, struct segvn_crargs *a, + size_t swresv) { struct segvn_data *svd1 = (struct segvn_data *)seg1->s_data; size_t size; @@ -1333,7 +1342,7 @@ segvn_extend_prev(seg1, seg2, a, swresv) struct vpage *vp, *evp; new_vpage = kmem_zalloc(vpgtob(seg_pages(seg1) + seg_pages(seg2)), - KM_NOSLEEP); + KM_NOSLEEP); if (new_vpage == NULL) return (-1); bcopy(svd1->vpage, new_vpage, vpgtob(seg_pages(seg1))); @@ -1373,11 +1382,8 @@ segvn_extend_prev(seg1, seg2, a, swresv) * Return 0 on success. */ static int -segvn_extend_next( - struct seg *seg1, - struct seg *seg2, - struct segvn_crargs *a, - size_t swresv) +segvn_extend_next(struct seg *seg1, struct seg *seg2, struct segvn_crargs *a, + size_t swresv) { struct segvn_data *svd2 = (struct segvn_data *)seg2->s_data; size_t size; @@ -3357,7 +3363,6 @@ static int segvn_fill_vp_pages(struct segvn_data *svd, vnode_t *vp, u_offset_t off, uint_t szc, page_t **ppa, page_t **ppplist, uint_t *ret_pszc, int *downsize) - { page_t *pplist = *ppplist; size_t pgsz = page_get_pagesize(szc); @@ -3498,7 +3503,7 @@ segvn_fill_vp_pages(struct segvn_data *svd, vnode_t *vp, u_offset_t off, goto out; } io_err = VOP_PAGEIO(vp, io_pplist, io_off, io_len, - B_READ, svd->cred, NULL); + B_READ, svd->cred, NULL); if (io_err) { VM_STAT_ADD(segvnvmstats.fill_vp_pages[8]); page_unlock(targpp); @@ -9456,7 +9461,7 @@ segvn_purge(struct seg *seg) /*ARGSUSED*/ static int segvn_reclaim(void *ptag, caddr_t addr, size_t len, struct page **pplist, - enum seg_rw rw, int async) + enum seg_rw rw, int async) { struct seg *seg = (struct seg *)ptag; struct segvn_data *svd = (struct segvn_data *)seg->s_data; @@ -9533,7 +9538,7 @@ segvn_reclaim(void *ptag, caddr_t addr, size_t len, struct page **pplist, /*ARGSUSED*/ static int shamp_reclaim(void *ptag, caddr_t addr, size_t len, struct page **pplist, - enum seg_rw rw, int async) + enum seg_rw rw, int async) { amp_t *amp = (amp_t *)ptag; pgcnt_t np, npages; @@ -10206,10 +10211,8 @@ segvn_trupdate(void) } static void -segvn_trupdate_seg(struct seg *seg, - segvn_data_t *svd, - svntr_t *svntrp, - ulong_t hash) +segvn_trupdate_seg(struct seg *seg, segvn_data_t *svd, svntr_t *svntrp, + ulong_t hash) { proc_t *p; lgrp_id_t lgrp_id; diff --git a/usr/src/uts/common/vm/seg_vn.h b/usr/src/uts/common/vm/seg_vn.h index 6fef7d678d..97a0db012d 100644 --- a/usr/src/uts/common/vm/seg_vn.h +++ b/usr/src/uts/common/vm/seg_vn.h @@ -21,7 +21,7 @@ /* * Copyright 2009 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. - * Copyright (c) 2015, Joyent, Inc. All rights reserved. + * Copyright 2018 Joyent, Inc. */ /* Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T */ @@ -162,14 +162,14 @@ typedef struct segvn_data { { NULL, NULL, 0, MAP_PRIVATE, prot, max, 0, NULL, 0, 0 } #define AS_MAP_CHECK_VNODE_LPOOB(crfp, argsp) \ - ((crfp) == (int (*)())segvn_create && \ + ((crfp) == (segcreate_func_t)segvn_create && \ (((struct segvn_crargs *)(argsp))->flags & \ (MAP_TEXT | MAP_INITDATA)) && \ ((struct segvn_crargs *)(argsp))->szc == 0 && \ ((struct segvn_crargs *)(argsp))->vp != NULL) #define AS_MAP_CHECK_ANON_LPOOB(crfp, argsp) \ - ((crfp) == (int (*)())segvn_create && \ + ((crfp) == (segcreate_func_t)segvn_create && \ (((struct segvn_crargs *)(argsp))->szc == 0 || \ ((struct segvn_crargs *)(argsp))->szc == AS_MAP_HEAP || \ ((struct segvn_crargs *)(argsp))->szc == AS_MAP_STACK) && \ @@ -228,7 +228,7 @@ typedef struct svntr_stats { } svntr_stats_t; extern void segvn_init(void); -extern int segvn_create(struct seg *, void *); +extern int segvn_create(struct seg **, void *); extern struct seg_ops segvn_ops; diff --git a/usr/src/uts/common/vm/vm_as.c b/usr/src/uts/common/vm/vm_as.c index ea28b0814d..853b092e6d 100644 --- a/usr/src/uts/common/vm/vm_as.c +++ b/usr/src/uts/common/vm/vm_as.c @@ -21,7 +21,7 @@ /* * Copyright 2010 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. - * Copyright 2015, Joyent, Inc. All rights reserved. + * Copyright 2018 Joyent, Inc. * Copyright (c) 2016 by Delphix. All rights reserved. */ @@ -67,6 +67,7 @@ #include #include #include +#include #include clock_t deadlk_wait = 1; /* number of ticks to wait before retrying */ @@ -75,7 +76,6 @@ static struct kmem_cache *as_cache; static void as_setwatchprot(struct as *, caddr_t, size_t, uint_t); static void as_clearwatchprot(struct as *, caddr_t, size_t); -int as_map_locked(struct as *, caddr_t, size_t, int ((*)()), void *); /* @@ -816,7 +816,9 @@ as_dup(struct as *as, struct proc *forkedproc) as_free(newas); return (error); } - newas->a_size += seg->s_size; + if ((newseg->s_flags & S_HOLE) == 0) { + newas->a_size += seg->s_size; + } } newas->a_resvsize = as->a_resvsize - purgesize; @@ -1312,6 +1314,8 @@ top: as_clearwatchprot(as, raddr, eaddr - raddr); for (seg = as_findseg(as, raddr, 0); seg != NULL; seg = seg_next) { + const boolean_t is_hole = ((seg->s_flags & S_HOLE) != 0); + if (eaddr <= seg->s_base) break; /* eaddr was in a gap; all done */ @@ -1416,9 +1420,11 @@ retry: return (-1); } - as->a_size -= ssize; - if (rsize) - as->a_resvsize -= rsize; + if (!is_hole) { + as->a_size -= ssize; + if (rsize) + as->a_resvsize -= rsize; + } raddr += ssize; } AS_LOCK_EXIT(as); @@ -1427,35 +1433,34 @@ retry: static int as_map_segvn_segs(struct as *as, caddr_t addr, size_t size, uint_t szcvec, - int (*crfp)(), struct segvn_crargs *vn_a, int *segcreated) + segcreate_func_t crfp, struct segvn_crargs *vn_a, boolean_t *segcreated) { - uint_t szc; - uint_t nszc; + uint_t szc, nszc, save_szcvec; int error; - caddr_t a; - caddr_t eaddr; - size_t segsize; - struct seg *seg; + caddr_t a, eaddr; size_t pgsz; - int do_off = (vn_a->vp != NULL || vn_a->amp != NULL); - uint_t save_szcvec; + const boolean_t do_off = (vn_a->vp != NULL || vn_a->amp != NULL); ASSERT(AS_WRITE_HELD(as)); ASSERT(IS_P2ALIGNED(addr, PAGESIZE)); ASSERT(IS_P2ALIGNED(size, PAGESIZE)); ASSERT(vn_a->vp == NULL || vn_a->amp == NULL); + if (!do_off) { vn_a->offset = 0; } if (szcvec <= 1) { - seg = seg_alloc(as, addr, size); + struct seg *seg, *segref; + + seg = segref = seg_alloc(as, addr, size); if (seg == NULL) { return (ENOMEM); } vn_a->szc = 0; - error = (*crfp)(seg, vn_a); + error = (*crfp)(&seg, vn_a); if (error != 0) { + VERIFY3P(seg, ==, segref); seg_free(seg); } else { as->a_size += size; @@ -1479,21 +1484,26 @@ as_map_segvn_segs(struct as *as, caddr_t addr, size_t size, uint_t szcvec, pgsz = page_get_pagesize(nszc); a = (caddr_t)P2ROUNDUP((uintptr_t)addr, pgsz); if (a != addr) { + struct seg *seg, *segref; + size_t segsize; + ASSERT(a < eaddr); + segsize = a - addr; - seg = seg_alloc(as, addr, segsize); + seg = segref = seg_alloc(as, addr, segsize); if (seg == NULL) { return (ENOMEM); } vn_a->szc = szc; - error = (*crfp)(seg, vn_a); + error = (*crfp)(&seg, vn_a); if (error != 0) { + VERIFY3P(seg, ==, segref); seg_free(seg); return (error); } as->a_size += segsize; as->a_resvsize += segsize; - *segcreated = 1; + *segcreated = B_TRUE; if (do_off) { vn_a->offset += segsize; } @@ -1509,20 +1519,24 @@ as_map_segvn_segs(struct as *as, caddr_t addr, size_t size, uint_t szcvec, a = (caddr_t)P2ALIGN((uintptr_t)eaddr, pgsz); ASSERT(a >= addr); if (a != addr) { + struct seg *seg, *segref; + size_t segsize; + segsize = a - addr; - seg = seg_alloc(as, addr, segsize); + seg = segref = seg_alloc(as, addr, segsize); if (seg == NULL) { return (ENOMEM); } vn_a->szc = szc; - error = (*crfp)(seg, vn_a); + error = (*crfp)(&seg, vn_a); if (error != 0) { + VERIFY3P(seg, ==, segref); seg_free(seg); return (error); } as->a_size += segsize; as->a_resvsize += segsize; - *segcreated = 1; + *segcreated = B_TRUE; if (do_off) { vn_a->offset += segsize; } @@ -1541,14 +1555,13 @@ as_map_segvn_segs(struct as *as, caddr_t addr, size_t size, uint_t szcvec, static int as_map_vnsegs(struct as *as, caddr_t addr, size_t size, - int (*crfp)(), struct segvn_crargs *vn_a, int *segcreated) + segcreate_func_t crfp, struct segvn_crargs *vn_a, boolean_t *segcreated) { uint_t mapflags = vn_a->flags & (MAP_TEXT | MAP_INITDATA); int type = (vn_a->type == MAP_SHARED) ? MAPPGSZC_SHM : MAPPGSZC_PRIVM; uint_t szcvec = map_pgszcvec(addr, size, (uintptr_t)addr, mapflags, type, 0); int error; - struct seg *seg; struct vattr va; u_offset_t eoff; size_t save_size = 0; @@ -1562,13 +1575,16 @@ as_map_vnsegs(struct as *as, caddr_t addr, size_t size, again: if (szcvec <= 1) { - seg = seg_alloc(as, addr, size); + struct seg *seg, *segref; + + seg = segref = seg_alloc(as, addr, size); if (seg == NULL) { return (ENOMEM); } vn_a->szc = 0; - error = (*crfp)(seg, vn_a); + error = (*crfp)(&seg, vn_a); if (error != 0) { + VERIFY3P(seg, ==, segref); seg_free(seg); } else { as->a_size += size; @@ -1623,7 +1639,7 @@ again: */ static int as_map_ansegs(struct as *as, caddr_t addr, size_t size, - int (*crfp)(), struct segvn_crargs *vn_a, int *segcreated) + segcreate_func_t crfp, struct segvn_crargs *vn_a, boolean_t *segcreated) { uint_t szcvec; uchar_t type; @@ -1653,21 +1669,21 @@ as_map_ansegs(struct as *as, caddr_t addr, size_t size, } int -as_map(struct as *as, caddr_t addr, size_t size, int (*crfp)(), void *argsp) +as_map(struct as *as, caddr_t addr, size_t size, segcreate_func_t crfp, + void *argsp) { AS_LOCK_ENTER(as, RW_WRITER); return (as_map_locked(as, addr, size, crfp, argsp)); } int -as_map_locked(struct as *as, caddr_t addr, size_t size, int (*crfp)(), +as_map_locked(struct as *as, caddr_t addr, size_t size, segcreate_func_t crfp, void *argsp) { - struct seg *seg = NULL; caddr_t raddr; /* rounded down addr */ size_t rsize; /* rounded up size */ int error; - int unmap = 0; + boolean_t is_hole = B_FALSE; /* * The use of a_proc is preferred to handle the case where curproc is * a door_call server and is allocating memory in the client's (a_proc) @@ -1693,63 +1709,97 @@ as_map_locked(struct as *as, caddr_t addr, size_t size, int (*crfp)(), as->a_updatedir = 1; /* inform /proc */ gethrestime(&as->a_updatetime); - if (as != &kas && as->a_size + rsize > (size_t)p->p_vmem_ctl) { - AS_LOCK_EXIT(as); - - (void) rctl_action(rctlproc_legacy[RLIMIT_VMEM], p->p_rctls, p, - RCA_UNSAFE_ALL); + if (as != &kas) { + /* + * Ensure that the virtual size of the process will not exceed + * the configured limit. Since seg_hole segments will later + * set the S_HOLE flag indicating their status as a hole in the + * AS, they are excluded from this check. + */ + if (as->a_size + rsize > (size_t)p->p_vmem_ctl && + !AS_MAP_CHECK_SEGHOLE(crfp)) { + AS_LOCK_EXIT(as); - return (ENOMEM); + (void) rctl_action(rctlproc_legacy[RLIMIT_VMEM], + p->p_rctls, p, RCA_UNSAFE_ALL); + return (ENOMEM); + } } if (AS_MAP_CHECK_VNODE_LPOOB(crfp, argsp)) { + boolean_t do_unmap = B_FALSE; + crargs = *(struct segvn_crargs *)argsp; - error = as_map_vnsegs(as, raddr, rsize, crfp, &crargs, &unmap); + error = as_map_vnsegs(as, raddr, rsize, crfp, &crargs, + &do_unmap); if (error != 0) { AS_LOCK_EXIT(as); - if (unmap) { + if (do_unmap) { (void) as_unmap(as, addr, size); } return (error); } } else if (AS_MAP_CHECK_ANON_LPOOB(crfp, argsp)) { + boolean_t do_unmap = B_FALSE; + crargs = *(struct segvn_crargs *)argsp; - error = as_map_ansegs(as, raddr, rsize, crfp, &crargs, &unmap); + error = as_map_ansegs(as, raddr, rsize, crfp, &crargs, + &do_unmap); if (error != 0) { AS_LOCK_EXIT(as); - if (unmap) { + if (do_unmap) { (void) as_unmap(as, addr, size); } return (error); } } else { - seg = seg_alloc(as, addr, size); + struct seg *seg, *segref; + + seg = segref = seg_alloc(as, addr, size); if (seg == NULL) { AS_LOCK_EXIT(as); return (ENOMEM); } - error = (*crfp)(seg, argsp); + /* + * It is possible that the segment creation routine will free + * 'seg' as part of a more advanced operation, such as when + * segvn concatenates adjacent segments together. When this + * occurs, the seg*_create routine must communicate the + * resulting segment out via the 'struct seg **' parameter. + * + * If segment creation fails, it must not free the passed-in + * segment, nor alter the argument pointer. + */ + error = (*crfp)(&seg, argsp); if (error != 0) { + VERIFY3P(seg, ==, segref); seg_free(seg); AS_LOCK_EXIT(as); return (error); } + /* - * Add size now so as_unmap will work if as_ctl fails. + * Check if the resulting segment represents a hole in the + * address space, rather than contributing to the AS size. */ - as->a_size += rsize; - as->a_resvsize += rsize; + is_hole = ((seg->s_flags & S_HOLE) != 0); + + /* Add size now so as_unmap will work if as_ctl fails. */ + if (!is_hole) { + as->a_size += rsize; + as->a_resvsize += rsize; + } } as_setwatch(as); /* - * If the address space is locked, - * establish memory locks for the new segment. + * Establish memory locks for the segment if the address space is + * locked, provided it's not an explicit hole in the AS. */ mutex_enter(&as->a_contents); - if (AS_ISPGLCK(as)) { + if (AS_ISPGLCK(as) && !is_hole) { mutex_exit(&as->a_contents); AS_LOCK_EXIT(as); error = as_ctl(as, addr, size, MC_LOCK, 0, 0, NULL, 0); @@ -2277,6 +2327,9 @@ retry: } for (seg = AS_SEGFIRST(as); seg; seg = AS_SEGNEXT(as, seg)) { + if ((seg->s_flags & S_HOLE) != 0) { + continue; + } error = SEGOP_LOCKOP(seg, seg->s_base, seg->s_size, attr, MC_LOCK, mlock_map, pos); if (error != 0) @@ -2306,6 +2359,9 @@ retry: mutex_exit(&as->a_contents); for (seg = AS_SEGFIRST(as); seg; seg = AS_SEGNEXT(as, seg)) { + if ((seg->s_flags & S_HOLE) != 0) { + continue; + } error = SEGOP_LOCKOP(seg, seg->s_base, seg->s_size, attr, MC_UNLOCK, NULL, 0); if (error != 0) diff --git a/usr/src/uts/i86pc/vm/vm_machdep.c b/usr/src/uts/i86pc/vm/vm_machdep.c index 4fa587ce7a..cb46bba853 100644 --- a/usr/src/uts/i86pc/vm/vm_machdep.c +++ b/usr/src/uts/i86pc/vm/vm_machdep.c @@ -776,9 +776,6 @@ map_addr_proc( base = p->p_brkbase; #if defined(__amd64) - /* - * XX64 Yes, this needs more work. - */ if (p->p_model == DATAMODEL_NATIVE) { if (userlimit < as->a_userlimit) { /* @@ -798,16 +795,24 @@ map_addr_proc( } } else { /* - * XX64 This layout is probably wrong .. but in - * the event we make the amd64 address space look - * like sparcv9 i.e. with the stack -above- the - * heap, this bit of code might even be correct. + * With the stack positioned at a higher address than + * the heap for 64-bit processes, it is necessary to be + * mindful of its location and potential size. + * + * Unallocated space above the top of the stack (that + * is, at a lower address) but still within the bounds + * of the stack limit should be considered unavailable. + * + * As the 64-bit stack guard is mapped in immediately + * adjacent to the stack limit boundary, this prevents + * new mappings from having accidentally dangerous + * proximity to the stack. */ slen = p->p_usrstack - base - ((p->p_stk_ctl + PAGEOFFSET) & PAGEMASK); } } else -#endif +#endif /* defined(__amd64) */ slen = userlimit - base; /* Make len be a multiple of PAGESIZE */ diff --git a/usr/src/uts/i86xpv/vm/seg_mf.c b/usr/src/uts/i86xpv/vm/seg_mf.c index 081ee85b15..4ce5f3777a 100644 --- a/usr/src/uts/i86xpv/vm/seg_mf.c +++ b/usr/src/uts/i86xpv/vm/seg_mf.c @@ -22,6 +22,7 @@ /* * Copyright 2008 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. + * Copyright 2018 Joyent, Inc. */ /* @@ -115,8 +116,9 @@ segmf_data_zalloc(struct seg *seg) } int -segmf_create(struct seg *seg, void *args) +segmf_create(struct seg **segpp, void *args) { + struct seg *seg = *segpp; struct segmf_crargs *a = args; struct segmf_data *data; struct as *as = seg->s_as; diff --git a/usr/src/uts/i86xpv/vm/seg_mf.h b/usr/src/uts/i86xpv/vm/seg_mf.h index 316a1f51bd..bc6aaf425d 100644 --- a/usr/src/uts/i86xpv/vm/seg_mf.h +++ b/usr/src/uts/i86xpv/vm/seg_mf.h @@ -22,6 +22,7 @@ /* * Copyright 2008 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. + * Copyright 2018 Joyent, Inc. */ #ifndef _VM_SEG_MF_H @@ -42,7 +43,7 @@ struct segmf_crargs { uchar_t maxprot; }; -extern int segmf_create(struct seg *, void *); +extern int segmf_create(struct seg **, void *); extern int segmf_add_mfns(struct seg *, caddr_t, mfn_t, pgcnt_t, domid_t); -- cgit v1.2.3 From f44a1392c9d1c0ff0faf96d4eed0952a6b5cfbe0 Mon Sep 17 00:00:00 2001 From: Robert Mustacchi Date: Thu, 5 Oct 2017 03:38:49 +0000 Subject: 9569 smbios(1M) could decode voltage and curent probes 9570 smbios(1M) could decode cooling devices 9571 smbios(1M) could decode temperature probes 9572 smb_impl.h structs should comment corresponding type 9573 overshifted smbios major version leads to undershifted data 9574 smbios(1M) shouldn't print non-existant bios versions Reviewed by: Tim Kordas Reviewed by: Dan McDonald Reviewed by: Toomas Soome Reviewed by: Igor Kozhukhov Reviewed by: Yuri Pankov Approved by: Dan McDonald --- usr/src/cmd/smbios/smbios.c | 245 +++++++++++++++++++++++++++++- usr/src/common/smbios/mktables.sh | 8 + usr/src/common/smbios/smb_info.c | 152 ++++++++++++++++++ usr/src/lib/libsmbios/common/mapfile-vers | 12 ++ usr/src/uts/common/sys/smbios.h | 167 ++++++++++++++++++++ usr/src/uts/common/sys/smbios_impl.h | 170 ++++++++++++++++++++- 6 files changed, 752 insertions(+), 2 deletions(-) diff --git a/usr/src/cmd/smbios/smbios.c b/usr/src/cmd/smbios/smbios.c index c7bd5d75c6..a40e393a91 100644 --- a/usr/src/cmd/smbios/smbios.c +++ b/usr/src/cmd/smbios/smbios.c @@ -314,7 +314,13 @@ print_bios(smbios_hdl_t *shp, FILE *fp) b.smbb_biosv.smbv_major, b.smbb_biosv.smbv_minor); } - if (b.smbb_nxcflags > SMB_BIOSXB_ECFW_MIN) { + /* + * If the major and minor versions are 0xff then that indicates that the + * embedded controller does not exist. + */ + if (b.smbb_nxcflags > SMB_BIOSXB_ECFW_MIN && + b.smbb_ecfwv.smbv_major != 0xff && + b.smbb_ecfwv.smbv_minor != 0xff) { oprintf(fp, " Embedded Ctlr Firmware Version Number: %u.%u\n", b.smbb_ecfwv.smbv_major, b.smbb_ecfwv.smbv_minor); } @@ -976,6 +982,227 @@ print_hwsec(smbios_hdl_t *shp, FILE *fp) fp, " Front Panel Reset Status: %u", h.smbh_pan_ps); } +static void +print_vprobe(smbios_hdl_t *shp, id_t id, FILE *fp) +{ + smbios_vprobe_t vp; + + if (smbios_info_vprobe(shp, id, &vp) != 0) { + smbios_warn(shp, "failed to read voltage probe information"); + return; + } + + oprintf(fp, " Description: %s\n", vp.smbvp_description != NULL ? + vp.smbvp_description : "unknown"); + desc_printf(smbios_vprobe_loc_desc(vp.smbvp_location), + fp, " Location: %u", vp.smbvp_location); + desc_printf(smbios_vprobe_status_desc(vp.smbvp_status), + fp, " Status: %u", vp.smbvp_status); + + if (vp.smbvp_maxval != SMB_PROBE_UNKNOWN_VALUE) { + oprintf(fp, " Maximum Possible Voltage: %u mV\n", + vp.smbvp_maxval); + } else { + oprintf(fp, " Maximum Possible Voltage: unknown\n"); + } + + if (vp.smbvp_minval != SMB_PROBE_UNKNOWN_VALUE) { + oprintf(fp, " Minimum Possible Voltage: %u mV\n", + vp.smbvp_minval); + } else { + oprintf(fp, " Minimum Possible Voltage: unknown\n"); + } + + if (vp.smbvp_resolution != SMB_PROBE_UNKNOWN_VALUE) { + oprintf(fp, " Probe Resolution: %u.%u mV\n", + vp.smbvp_resolution / 10, + vp.smbvp_resolution % 10); + } else { + oprintf(fp, " Probe Resolution: unknown\n"); + } + + if (vp.smbvp_tolerance != SMB_PROBE_UNKNOWN_VALUE) { + oprintf(fp, " Probe Tolerance: +/-%u mV\n", + vp.smbvp_tolerance); + } else { + oprintf(fp, " Probe Tolerance: unknown\n"); + } + + if (vp.smbvp_accuracy != SMB_PROBE_UNKNOWN_VALUE) { + oprintf(fp, " Probe Accuracy: +/-%u.%02u%%\n", + vp.smbvp_accuracy / 100, + vp.smbvp_accuracy % 100); + } else { + oprintf(fp, " Probe Accuracy: unknown\n"); + } + + oprintf(fp, " OEM- or BIOS- defined value: 0x%x\n", vp.smbvp_oem); + + if (vp.smbvp_nominal != SMB_PROBE_UNKNOWN_VALUE) { + oprintf(fp, " Probe Nominal Value: %u mV\n", vp.smbvp_nominal); + } else { + oprintf(fp, " Probe Nominal Value: unknown\n"); + } +} + +static void +print_cooldev(smbios_hdl_t *shp, id_t id, FILE *fp) +{ + smbios_cooldev_t cd; + + if (smbios_info_cooldev(shp, id, &cd) != 0) { + smbios_warn(shp, "failed to read cooling device " + "information"); + return; + } + + id_printf(fp, " Temperature Probe Handle: ", cd.smbcd_tprobe); + desc_printf(smbios_cooldev_type_desc(cd.smbcd_type), + fp, " Device Type: %u", cd.smbcd_type); + desc_printf(smbios_cooldev_status_desc(cd.smbcd_status), + fp, " Status: %u", cd.smbcd_status); + oprintf(fp, " Cooling Unit Group: %u\n", cd.smbcd_group); + oprintf(fp, " OEM- or BIOS- defined data: 0x%x\n", cd.smbcd_oem); + if (cd.smbcd_nominal != SMB_PROBE_UNKNOWN_VALUE) { + oprintf(fp, " Nominal Speed: %u RPM\n", cd.smbcd_nominal); + } else { + oprintf(fp, " Nominal Speed: unknown\n"); + } + + if (cd.smbcd_descr != NULL && cd.smbcd_descr[0] != '\0') { + oprintf(fp, " Description: %s\n", cd.smbcd_descr); + } +} + +static void +print_tprobe(smbios_hdl_t *shp, id_t id, FILE *fp) +{ + smbios_tprobe_t tp; + + if (smbios_info_tprobe(shp, id, &tp) != 0) { + smbios_warn(shp, "failed to read temperature probe " + "information"); + return; + } + + oprintf(fp, " Description: %s\n", tp.smbtp_description != NULL ? + tp.smbtp_description : "unknown"); + desc_printf(smbios_tprobe_loc_desc(tp.smbtp_location), + fp, " Location: %u", tp.smbtp_location); + desc_printf(smbios_tprobe_status_desc(tp.smbtp_status), + fp, " Status: %u", tp.smbtp_status); + + if (tp.smbtp_maxval != SMB_PROBE_UNKNOWN_VALUE) { + oprintf(fp, " Maximum Possible Temperature: %u.%u C\n", + tp.smbtp_maxval / 10, tp.smbtp_maxval % 10); + } else { + oprintf(fp, " Maximum Possible Temperature: unknown\n"); + } + + if (tp.smbtp_minval != SMB_PROBE_UNKNOWN_VALUE) { + oprintf(fp, " Minimum Possible Temperature: %u.%u C\n", + tp.smbtp_minval / 10, tp.smbtp_minval % 10); + } else { + oprintf(fp, " Minimum Possible Temperature: unknown\n"); + } + + if (tp.smbtp_resolution != SMB_PROBE_UNKNOWN_VALUE) { + oprintf(fp, " Probe Resolution: %u.%03u C\n", + tp.smbtp_resolution / 1000, + tp.smbtp_resolution % 1000); + } else { + oprintf(fp, " Probe Resolution: unknown\n"); + } + + if (tp.smbtp_tolerance != SMB_PROBE_UNKNOWN_VALUE) { + oprintf(fp, " Probe Tolerance: +/-%u.%u C\n", + tp.smbtp_tolerance / 10, tp.smbtp_tolerance % 10); + } else { + oprintf(fp, " Probe Tolerance: unknown\n"); + } + + if (tp.smbtp_accuracy != SMB_PROBE_UNKNOWN_VALUE) { + oprintf(fp, " Probe Accuracy: +/-%u.%02u%%\n", + tp.smbtp_accuracy / 100, + tp.smbtp_accuracy % 100); + } else { + oprintf(fp, " Probe Accuracy: unknown\n"); + } + + oprintf(fp, " OEM- or BIOS- defined value: 0x%x\n", tp.smbtp_oem); + + if (tp.smbtp_nominal != SMB_PROBE_UNKNOWN_VALUE) { + oprintf(fp, " Probe Nominal Value: %u.%u C\n", + tp.smbtp_nominal / 10, tp.smbtp_nominal % 10); + } else { + oprintf(fp, " Probe Nominal Value: unknown\n"); + } +} + +static void +print_iprobe(smbios_hdl_t *shp, id_t id, FILE *fp) +{ + smbios_iprobe_t ip; + + if (smbios_info_iprobe(shp, id, &ip) != 0) { + smbios_warn(shp, "failed to read current probe information"); + return; + } + + oprintf(fp, " Description: %s\n", ip.smbip_description != NULL ? + ip.smbip_description : "unknown"); + desc_printf(smbios_iprobe_loc_desc(ip.smbip_location), + fp, " Location: %u", ip.smbip_location); + desc_printf(smbios_iprobe_status_desc(ip.smbip_status), + fp, " Status: %u", ip.smbip_status); + + if (ip.smbip_maxval != SMB_PROBE_UNKNOWN_VALUE) { + oprintf(fp, " Maximum Possible Current: %u mA\n", + ip.smbip_maxval); + } else { + oprintf(fp, " Maximum Possible Current: unknown\n"); + } + + if (ip.smbip_minval != SMB_PROBE_UNKNOWN_VALUE) { + oprintf(fp, " Minimum Possible Current: %u mA\n", + ip.smbip_minval); + } else { + oprintf(fp, " Minimum Possible Current: unknown\n"); + } + + if (ip.smbip_resolution != SMB_PROBE_UNKNOWN_VALUE) { + oprintf(fp, " Probe Resolution: %u.%u mA\n", + ip.smbip_resolution / 10, + ip.smbip_resolution % 10); + } else { + oprintf(fp, " Probe Resolution: unknown\n"); + } + + if (ip.smbip_tolerance != SMB_PROBE_UNKNOWN_VALUE) { + oprintf(fp, " Probe Tolerance: +/-%u mA\n", + ip.smbip_tolerance); + } else { + oprintf(fp, " Probe Tolerance: unknown\n"); + } + + if (ip.smbip_accuracy != SMB_PROBE_UNKNOWN_VALUE) { + oprintf(fp, " Probe Accuracy: +/-%u.%02u%%\n", + ip.smbip_accuracy / 100, + ip.smbip_accuracy % 100); + } else { + oprintf(fp, " Probe Accuracy: unknown\n"); + } + + oprintf(fp, " OEM- or BIOS- defined value: 0x%x\n", ip.smbip_oem); + + if (ip.smbip_nominal != SMB_PROBE_UNKNOWN_VALUE) { + oprintf(fp, " Probe Nominal Value: %u mA\n", ip.smbip_nominal); + } else { + oprintf(fp, " Probe Nominal Value: unknown\n"); + } +} + + static void print_boot(smbios_hdl_t *shp, FILE *fp) { @@ -1255,6 +1482,22 @@ print_struct(smbios_hdl_t *shp, const smbios_struct_t *sp, void *fp) oprintf(fp, "\n"); print_hwsec(shp, fp); break; + case SMB_TYPE_VPROBE: + oprintf(fp, "\n"); + print_vprobe(shp, sp->smbstr_id, fp); + break; + case SMB_TYPE_COOLDEV: + oprintf(fp, "\n"); + print_cooldev(shp, sp->smbstr_id, fp); + break; + case SMB_TYPE_TPROBE: + oprintf(fp, "\n"); + print_tprobe(shp, sp->smbstr_id, fp); + break; + case SMB_TYPE_IPROBE: + oprintf(fp, "\n"); + print_iprobe(shp, sp->smbstr_id, fp); + break; case SMB_TYPE_BOOT: oprintf(fp, "\n"); print_boot(shp, fp); diff --git a/usr/src/common/smbios/mktables.sh b/usr/src/common/smbios/mktables.sh index 7a001c0eb3..969c329b25 100644 --- a/usr/src/common/smbios/mktables.sh +++ b/usr/src/common/smbios/mktables.sh @@ -72,12 +72,16 @@ SMB_CAG_ smbios_cache_logical_desc uint_t SMB_CAM_ smbios_cache_mode_desc uint_t SMB_CHST_ smbios_chassis_state_desc uint_t SMB_CHT_ smbios_chassis_type_desc uint_t +SMB_COOLDEV_S_ smbios_cooldev_status_desc uint_t +SMB_COOLDEV_T_ smbios_cooldev_type_desc uint_t SMB_EVFL_ smbios_evlog_flag_desc uint_t SMB_EVHF_ smbios_evlog_format_desc uint_t SMB_EVM_ smbios_evlog_method_desc uint_t SMB_HWSEC_PS_ smbios_hwsec_desc uint_t SMB_IPMI_F_ smbios_ipmi_flag_desc uint_t SMB_IPMI_T_ smbios_ipmi_type_desc uint_t +SMB_IPROBE_L_ smbios_iprobe_loc_desc uint_t +SMB_IPROBE_S_ smbios_iprobe_status_desc uint_t SMB_POWERSUP_F_ smbios_powersup_flag_desc uint_t SMB_POWERSUP_I_ smbios_powersup_input_desc uint_t SMB_POWERSUP_S_ smbios_powersup_status_desc uint_t @@ -103,7 +107,11 @@ SMB_SLL_ smbios_slot_length_desc uint_t SMB_SLT_ smbios_slot_type_desc uint_t SMB_SLU_ smbios_slot_usage_desc uint_t SMB_SLW_ smbios_slot_width_desc uint_t +SMB_TPROBE_L_ smbios_tprobe_loc_desc uint_t +SMB_TPROBE_S_ smbios_tprobe_status_desc uint_t SMB_TYPE_ smbios_type_desc uint_t +SMB_VPROBE_L_ smbios_vprobe_loc_desc uint_t +SMB_VPROBE_S_ smbios_vprobe_status_desc uint_t SMB_WAKEUP_ smbios_system_wakeup_desc uint_t ' diff --git a/usr/src/common/smbios/smb_info.c b/usr/src/common/smbios/smb_info.c index 476ce0b059..b28413d6a5 100644 --- a/usr/src/common/smbios/smb_info.c +++ b/usr/src/common/smbios/smb_info.c @@ -1318,3 +1318,155 @@ smbios_info_powersup(smbios_hdl_t *shp, id_t id, smbios_powersup_t *psup) return (0); } + +int +smbios_info_vprobe(smbios_hdl_t *shp, id_t id, smbios_vprobe_t *vprobe) +{ + const smb_struct_t *stp = smb_lookup_id(shp, id); + smb_vprobe_t vp; + + if (stp == NULL) + return (-1); /* errno is set for us */ + + if (stp->smbst_hdr->smbh_type != SMB_TYPE_VPROBE) + return (smb_set_errno(shp, ESMB_TYPE)); + + if (stp->smbst_hdr->smbh_len < SMB_VPROBE_MINLEN) + return (smb_set_errno(shp, ESMB_SHORT)); + + bzero(vprobe, sizeof (*vprobe)); + smb_info_bcopy(stp->smbst_hdr, &vp, sizeof (vp)); + vprobe->smbvp_description = smb_strptr(stp, vp.smbvpr_descr); + vprobe->smbvp_location = SMB_VPROBE_LOCATION(vp.smbvpr_locstat); + vprobe->smbvp_status = SMB_VPROBE_STATUS(vp.smbvpr_locstat); + vprobe->smbvp_maxval = vp.smbvpr_maxval; + vprobe->smbvp_minval = vp.smbvpr_minval; + vprobe->smbvp_resolution = vp.smbvpr_resolution; + vprobe->smbvp_tolerance = vp.smbvpr_tolerance; + vprobe->smbvp_accuracy = vp.smbvpr_accuracy; + + if (stp->smbst_hdr->smbh_len >= SMB_VPROBE_NOMINAL_MINLEN) { + vprobe->smbvp_nominal = vp.smbvpr_nominal; + } else { + vprobe->smbvp_nominal = SMB_PROBE_UNKNOWN_VALUE; + } + + return (0); +} + +int +smbios_info_cooldev(smbios_hdl_t *shp, id_t id, smbios_cooldev_t *cooldev) +{ + const smb_struct_t *stp = smb_lookup_id(shp, id); + smb_cooldev_t cd; + + if (stp == NULL) + return (-1); /* errno is set for us */ + + if (stp->smbst_hdr->smbh_type != SMB_TYPE_COOLDEV) + return (smb_set_errno(shp, ESMB_TYPE)); + + if (stp->smbst_hdr->smbh_len < SMB_COOLDEV_MINLEN) + return (smb_set_errno(shp, ESMB_SHORT)); + + bzero(cooldev, sizeof (*cooldev)); + smb_info_bcopy(stp->smbst_hdr, &cd, sizeof (cd)); + cooldev->smbcd_tprobe = cd.smbcdev_tprobe; + cooldev->smbcd_type = SMB_COOLDEV_TYPE(cd.smbcdev_typstat); + cooldev->smbcd_status = SMB_COOLDEV_STATUS(cd.smbcdev_typstat); + cooldev->smbcd_group = cd.smbcdev_group; + cooldev->smbcd_oem = cd.smbcdev_oem; + + if (stp->smbst_hdr->smbh_len >= SMB_COOLDEV_NOMINAL_MINLEN) { + cooldev->smbcd_nominal = cd.smbcdev_nominal; + } else { + cooldev->smbcd_nominal = SMB_PROBE_UNKNOWN_VALUE; + } + + /* + * The description field was added in SMBIOS version 2.7. The + * SMB_TYPE_COOLDEV support was only added after all of the 2.7+ fields + * were added in the spec. So while a user may request an older version, + * we don't have to worry about old structures and just simply skip it + * if they're not asking for it. + */ + if (smb_libgteq(shp, SMB_VERSION_27) && + smb_gteq(shp, SMB_VERSION_27) && + stp->smbst_hdr->smbh_len >= SMB_COOLDEV_DESCR_MINLEN) { + cooldev->smbcd_descr = smb_strptr(stp, cd.smbcdev_descr); + } else { + cooldev->smbcd_descr = NULL; + } + + return (0); +} + +int +smbios_info_tprobe(smbios_hdl_t *shp, id_t id, smbios_tprobe_t *tprobe) +{ + const smb_struct_t *stp = smb_lookup_id(shp, id); + smb_tprobe_t tp; + + if (stp == NULL) + return (-1); /* errno is set for us */ + + if (stp->smbst_hdr->smbh_type != SMB_TYPE_TPROBE) + return (smb_set_errno(shp, ESMB_TYPE)); + + if (stp->smbst_hdr->smbh_len < SMB_TPROBE_MINLEN) + return (smb_set_errno(shp, ESMB_SHORT)); + + bzero(tprobe, sizeof (*tprobe)); + smb_info_bcopy(stp->smbst_hdr, &tp, sizeof (tp)); + tprobe->smbtp_description = smb_strptr(stp, tp.smbtpr_descr); + tprobe->smbtp_location = SMB_TPROBE_LOCATION(tp.smbtpr_locstat); + tprobe->smbtp_status = SMB_TPROBE_STATUS(tp.smbtpr_locstat); + tprobe->smbtp_maxval = tp.smbtpr_maxval; + tprobe->smbtp_minval = tp.smbtpr_minval; + tprobe->smbtp_resolution = tp.smbtpr_resolution; + tprobe->smbtp_tolerance = tp.smbtpr_tolerance; + tprobe->smbtp_accuracy = tp.smbtpr_accuracy; + + if (stp->smbst_hdr->smbh_len >= SMB_TPROBE_NOMINAL_MINLEN) { + tprobe->smbtp_nominal = tp.smbtpr_nominal; + } else { + tprobe->smbtp_nominal = SMB_PROBE_UNKNOWN_VALUE; + } + + return (0); +} + +int +smbios_info_iprobe(smbios_hdl_t *shp, id_t id, smbios_iprobe_t *iprobe) +{ + const smb_struct_t *sip = smb_lookup_id(shp, id); + smb_iprobe_t ip; + + if (sip == NULL) + return (-1); /* errno is set for us */ + + if (sip->smbst_hdr->smbh_type != SMB_TYPE_IPROBE) + return (smb_set_errno(shp, ESMB_TYPE)); + + if (sip->smbst_hdr->smbh_len < SMB_IPROBE_MINLEN) + return (smb_set_errno(shp, ESMB_SHORT)); + + bzero(iprobe, sizeof (*iprobe)); + smb_info_bcopy(sip->smbst_hdr, &ip, sizeof (ip)); + iprobe->smbip_description = smb_strptr(sip, ip.smbipr_descr); + iprobe->smbip_location = SMB_IPROBE_LOCATION(ip.smbipr_locstat); + iprobe->smbip_status = SMB_IPROBE_STATUS(ip.smbipr_locstat); + iprobe->smbip_maxval = ip.smbipr_maxval; + iprobe->smbip_minval = ip.smbipr_minval; + iprobe->smbip_resolution = ip.smbipr_resolution; + iprobe->smbip_tolerance = ip.smbipr_tolerance; + iprobe->smbip_accuracy = ip.smbipr_accuracy; + + if (sip->smbst_hdr->smbh_len >= SMB_IPROBE_NOMINAL_MINLEN) { + iprobe->smbip_nominal = ip.smbipr_nominal; + } else { + iprobe->smbip_nominal = SMB_PROBE_UNKNOWN_VALUE; + } + + return (0); +} diff --git a/usr/src/lib/libsmbios/common/mapfile-vers b/usr/src/lib/libsmbios/common/mapfile-vers index f2e6544050..6df8e6d4a6 100644 --- a/usr/src/lib/libsmbios/common/mapfile-vers +++ b/usr/src/lib/libsmbios/common/mapfile-vers @@ -68,6 +68,8 @@ SYMBOL_VERSION SUNWprivate_1.1 { smbios_chassis_state_desc; smbios_chassis_type_desc; smbios_checksum; + smbios_cooldev_status_desc; + smbios_cooldev_type_desc; smbios_close; smbios_csn; smbios_errmsg; @@ -83,11 +85,13 @@ SYMBOL_VERSION SUNWprivate_1.1 { smbios_info_boot; smbios_info_cache; smbios_info_chassis; + smbios_info_cooldev; smbios_info_common; smbios_info_contains; smbios_info_eventlog; smbios_info_hwsec; smbios_info_ipmi; + smbios_info_iprobe; smbios_info_lang; smbios_info_memarray; smbios_info_extmemarray; @@ -108,9 +112,13 @@ SYMBOL_VERSION SUNWprivate_1.1 { smbios_info_strtab; smbios_info_system; smbios_info_pciexrc; + smbios_info_tprobe; + smbios_info_vprobe; smbios_ipmi_flag_desc; smbios_ipmi_flag_name; smbios_ipmi_type_desc; + smbios_iprobe_loc_desc; + smbios_iprobe_status_desc; smbios_iter; smbios_lookup_id; smbios_lookup_type; @@ -147,9 +155,13 @@ SYMBOL_VERSION SUNWprivate_1.1 { smbios_slot_usage_desc; smbios_slot_width_desc; smbios_system_wakeup_desc; + smbios_tprobe_loc_desc; + smbios_tprobe_status_desc; smbios_truncated; smbios_type_desc; smbios_type_name; + smbios_vprobe_loc_desc; + smbios_vprobe_status_desc; smbios_write; local: *; diff --git a/usr/src/uts/common/sys/smbios.h b/usr/src/uts/common/sys/smbios.h index 094017f1da..17c8d199ec 100644 --- a/usr/src/uts/common/sys/smbios.h +++ b/usr/src/uts/common/sys/smbios.h @@ -1296,6 +1296,156 @@ typedef struct smbios_hwsec { #define SMB_HWSEC_PS_NOTIMPL 0x02 /* password not implemented */ #define SMB_HWSEC_PS_UNKNOWN 0x03 /* password status unknown */ +/* + * This value is used to represent a probe that has an unknown value. + */ +#define SMB_PROBE_UNKNOWN_VALUE 0x8000 + +/* + * SMBIOS Voltage Probe. See DSP0134 Section 7.27 for more information. + * Please see the specification for the units of each value. + */ +typedef struct smbios_vprobe { + const char *smbvp_description; /* description information */ + uint8_t smbvp_location; /* probe location */ + uint8_t smbvp_status; /* probe status */ + uint16_t smbvp_maxval; /* maximum voltage */ + uint16_t smbvp_minval; /* minimum voltage */ + uint16_t smbvp_resolution; /* probe resolution */ + uint16_t smbvp_tolerance; /* probe tolerance */ + uint16_t smbvp_accuracy; /* probe accuracy */ + uint32_t smbvp_oem; /* vendor-specific data */ + uint16_t smbvp_nominal; /* nominal value */ +} smbios_vprobe_t; + +#define SMB_VPROBE_S_OTHER 0x01 /* other */ +#define SMB_VPROBE_S_UNKNOWN 0x02 /* unknown */ +#define SMB_VPROBE_S_OK 0x03 /* OK */ +#define SMB_VPROBE_S_NONCRIT 0x04 /* non-critical */ +#define SMB_VPROBE_S_CRIT 0x05 /* critical */ +#define SMB_VPROBE_S_NONRECOV 0x06 /* non-recoverable */ + +#define SMB_VPROBE_L_OTHER 0x01 /* other */ +#define SMB_VPROBE_L_UNKNOWN 0x02 /* unknown */ +#define SMB_VPROBE_L_PROC 0x03 /* processor */ +#define SMB_VPROBE_L_DISK 0x04 /* disk */ +#define SMB_VPROBE_L_PBAY 0x05 /* peripheral bay */ +#define SMB_VPROBE_L_MGMT 0x06 /* system management module */ +#define SMB_VPROBE_L_MOBO 0x07 /* motherboard */ +#define SMB_VPROBE_L_MEMMOD 0x08 /* memory module */ +#define SMB_VPROBE_L_PROCMOD 0x09 /* processor module */ +#define SMB_VPROBE_L_POWER 0x0a /* power unit */ +#define SMB_VPROBE_L_AIC 0x0b /* add-in card */ + +/* + * SMBIOS Cooling Device. See DSP0134 Section 7.28 for more information. + * Please see the specification for the units of each value. + */ +typedef struct smbios_cooldev { + id_t smbcd_tprobe; /* temperature probe handle */ + uint8_t smbcd_type; /* cooling device type */ + uint8_t smbcd_status; /* status */ + uint8_t smbcd_group; /* group ID */ + uint32_t smbcd_oem; /* vendor-specific data */ + uint16_t smbcd_nominal; /* nominal speed */ + const char *smbcd_descr; /* device description */ +} smbios_cooldev_t; + +#define SMB_COOLDEV_S_OTHER 0x01 /* other */ +#define SMB_COOLDEV_S_UNKNOWN 0x02 /* unknown */ +#define SMB_COOLDEV_S_OK 0x03 /* OK */ +#define SMB_COOLDEV_S_NONCRIT 0x04 /* non-critical */ +#define SMB_COOLDEV_S_CRIT 0x05 /* critical */ +#define SMB_COOLDEV_S_NONRECOV 0x06 /* non-recoverable */ + +#define SMB_COOLDEV_T_OTHER 0x01 /* other */ +#define SMB_COOLDEV_T_UNKNOWN 0x02 /* unknown */ +#define SMB_COOLDEV_T_FAN 0x03 /* fan */ +#define SMB_COOLDEV_T_BLOWER 0x04 /* centrifugal blower */ +#define SMB_COOLDEV_T_CHIPFAN 0x05 /* chip fan */ +#define SMB_COOLDEV_T_CABFAN 0x06 /* cabinet fan */ +#define SMB_COOLDEV_T_PSFAN 0x07 /* power supply fan */ +#define SMB_COOLDEV_T_HEATPIPE 0x08 /* head pipe */ +#define SMB_COOLDEV_T_IREFRIG 0x09 /* integrated refrigeration */ +#define SMB_COOLDEV_T_ACTCOOL 0x10 /* active cooling */ +#define SMB_COOLDEV_T_PASSCOOL 0x11 /* passive cooling */ + +/* + * SMBIOS Temperature Probe. See DSP0134 Section 7.29 for more information. + * Please see the specification for the units of each value. + */ +typedef struct smbios_tprobe { + const char *smbtp_description; /* description information */ + uint8_t smbtp_location; /* probe location */ + uint8_t smbtp_status; /* probe status */ + uint16_t smbtp_maxval; /* maximum temperature */ + uint16_t smbtp_minval; /* minimum temperature */ + uint16_t smbtp_resolution; /* probe resolution */ + uint16_t smbtp_tolerance; /* probe tolerance */ + uint16_t smbtp_accuracy; /* probe accuracy */ + uint32_t smbtp_oem; /* vendor-specific data */ + uint16_t smbtp_nominal; /* nominal value */ +} smbios_tprobe_t; + +#define SMB_TPROBE_S_OTHER 0x01 /* other */ +#define SMB_TPROBE_S_UNKNOWN 0x02 /* unknown */ +#define SMB_TPROBE_S_OK 0x03 /* OK */ +#define SMB_TPROBE_S_NONCRIT 0x04 /* non-critical */ +#define SMB_TPROBE_S_CRIT 0x05 /* critical */ +#define SMB_TPROBE_S_NONRECOV 0x06 /* non-recoverable */ + +#define SMB_TPROBE_L_OTHER 0x01 /* other */ +#define SMB_TPROBE_L_UNKNOWN 0x02 /* unknown */ +#define SMB_TPROBE_L_PROC 0x03 /* processor */ +#define SMB_TPROBE_L_DISK 0x04 /* disk */ +#define SMB_TPROBE_L_PBAY 0x05 /* peripheral bay */ +#define SMB_TPROBE_L_MGMT 0x06 /* system management module */ +#define SMB_TPROBE_L_MOBO 0x07 /* motherboard */ +#define SMB_TPROBE_L_MEMMOD 0x08 /* memory module */ +#define SMB_TPROBE_L_PROCMOD 0x09 /* processor module */ +#define SMB_TPROBE_L_POWER 0x0a /* power unit */ +#define SMB_TPROBE_L_AIC 0x0b /* add-in card */ +#define SMB_TPROBE_L_FPBOARD 0x0c /* front panel board */ +#define SMB_TPROBE_L_BPBOARD 0x0d /* rear panel board */ +#define SMB_TPROBE_L_PSBOARD 0x0e /* power system board */ +#define SMB_TPROBE_L_DBPANE 0x0f /* drive back plane */ + +/* + * SMBIOS Current Probe. See DSP0134 Section 7.30 for more information. + * Please see the specification for the units of each value. + */ +typedef struct smbios_iprobe { + const char *smbip_description; /* description information */ + uint8_t smbip_location; /* probe location */ + uint8_t smbip_status; /* probe status */ + uint16_t smbip_maxval; /* maximum current */ + uint16_t smbip_minval; /* minimum current */ + uint16_t smbip_resolution; /* probe resolution */ + uint16_t smbip_tolerance; /* probe tolerance */ + uint16_t smbip_accuracy; /* probe accuracy */ + uint32_t smbip_oem; /* vendor-specific data */ + uint16_t smbip_nominal; /* nominal value */ +} smbios_iprobe_t; + +#define SMB_IPROBE_S_OTHER 0x01 /* other */ +#define SMB_IPROBE_S_UNKNOWN 0x02 /* unknown */ +#define SMB_IPROBE_S_OK 0x03 /* OK */ +#define SMB_IPROBE_S_NONCRIT 0x04 /* non-critical */ +#define SMB_IPROBE_S_CRIT 0x05 /* critical */ +#define SMB_IPROBE_S_NONRECOV 0x06 /* non-recoverable */ + +#define SMB_IPROBE_L_OTHER 0x01 /* other */ +#define SMB_IPROBE_L_UNKNOWN 0x02 /* unknown */ +#define SMB_IPROBE_L_PROC 0x03 /* processor */ +#define SMB_IPROBE_L_DISK 0x04 /* disk */ +#define SMB_IPROBE_L_PBAY 0x05 /* peripheral bay */ +#define SMB_IPROBE_L_MGMT 0x06 /* system management module */ +#define SMB_IPROBE_L_MOBO 0x07 /* motherboard */ +#define SMB_IPROBE_L_MEMMOD 0x08 /* memory module */ +#define SMB_IPROBE_L_PROCMOD 0x09 /* processor module */ +#define SMB_IPROBE_L_POWER 0x0a /* power unit */ +#define SMB_IPROBE_L_AIC 0x0b /* add-in card */ + /* * SMBIOS System Boot Information. See DSP0134 Section 7.33 for more * information. The contents of the data varies by type and is undocumented @@ -1549,11 +1699,16 @@ extern int smbios_info_extmemdevice(smbios_hdl_t *, id_t, smbios_memdevice_ext_t *); extern int smbios_info_memdevmap(smbios_hdl_t *, id_t, smbios_memdevmap_t *); extern id_t smbios_info_hwsec(smbios_hdl_t *, smbios_hwsec_t *); +extern int smbios_info_vprobe(smbios_hdl_t *, id_t, smbios_vprobe_t *); +extern int smbios_info_cooldev(smbios_hdl_t *, id_t, smbios_cooldev_t *); +extern int smbios_info_tprobe(smbios_hdl_t *, id_t, smbios_tprobe_t *); +extern int smbios_info_iprobe(smbios_hdl_t *, id_t, smbios_iprobe_t *); extern id_t smbios_info_boot(smbios_hdl_t *, smbios_boot_t *); extern id_t smbios_info_ipmi(smbios_hdl_t *, smbios_ipmi_t *); extern int smbios_info_powersup(smbios_hdl_t *, id_t, smbios_powersup_t *); extern int smbios_info_pciexrc(smbios_hdl_t *, id_t, smbios_pciexrc_t *); + extern const char *smbios_psn(smbios_hdl_t *); extern const char *smbios_csn(smbios_hdl_t *); @@ -1596,6 +1751,18 @@ extern const char *smbios_evlog_flag_name(uint_t); extern const char *smbios_evlog_format_desc(uint_t); extern const char *smbios_evlog_method_desc(uint_t); +extern const char *smbios_vprobe_loc_desc(uint_t); +extern const char *smbios_vprobe_status_desc(uint_t); + +extern const char *smbios_cooldev_status_desc(uint_t); +extern const char *smbios_cooldev_type_desc(uint_t); + +extern const char *smbios_tprobe_loc_desc(uint_t); +extern const char *smbios_tprobe_status_desc(uint_t); + +extern const char *smbios_iprobe_loc_desc(uint_t); +extern const char *smbios_iprobe_status_desc(uint_t); + extern const char *smbios_ipmi_flag_name(uint_t); extern const char *smbios_ipmi_flag_desc(uint_t); extern const char *smbios_ipmi_type_desc(uint_t); diff --git a/usr/src/uts/common/sys/smbios_impl.h b/usr/src/uts/common/sys/smbios_impl.h index ea11aea2c1..66edfb027a 100644 --- a/usr/src/uts/common/sys/smbios_impl.h +++ b/usr/src/uts/common/sys/smbios_impl.h @@ -67,6 +67,9 @@ typedef struct smb_header { uint16_t smbh_hdl; /* structure handle */ } smb_header_t; +/* + * SMBIOS implementation structure for SMB_TYPE_BIOS. + */ typedef struct smb_bios { smb_header_t smbbi_hdr; /* structure header */ uint8_t smbbi_vendor; /* bios vendor string */ @@ -78,6 +81,9 @@ typedef struct smb_bios { uint8_t smbbi_xcflags[1]; /* bios characteristics extensions */ } smb_bios_t; +/* + * SMBIOS implementation structure for SMB_TYPE_SYSTEM. + */ typedef struct smb_system { smb_header_t smbsi_hdr; /* structure header */ uint8_t smbsi_manufacturer; /* manufacturer */ @@ -90,6 +96,9 @@ typedef struct smb_system { uint8_t smbsi_family; /* family */ } smb_system_t; +/* + * SMBIOS implementation structure for SMB_TYPE_BASEBOARD. + */ typedef struct smb_bboard { smb_header_t smbbb_hdr; /* structure header */ uint8_t smbbb_manufacturer; /* manufacturer */ @@ -105,6 +114,9 @@ typedef struct smb_bboard { uint16_t smbbb_cv[1]; /* array of contained handles */ } smb_bboard_t; +/* + * SMBIOS implementation structure for SMB_TYPE_CHASSIS. + */ typedef struct smb_chassis { smb_header_t smbch_hdr; /* structure header */ uint8_t smbch_manufacturer; /* manufacturer */ @@ -129,6 +141,9 @@ typedef struct smb_chassis { (smbcp)->smbch_cv + ((smbcp)->smbch_cn * (smbcp)->smbch_cm)) #define SMB_CHT_LOCK 0x80 /* lock bit within smbch_type */ +/* + * SMBIOS implementation structure for SMB_TYPE_PROCESSOR. + */ typedef struct smb_processor { smb_header_t smbpr_hdr; /* structure header */ uint8_t smbpr_socket; /* socket designation */ @@ -159,6 +174,9 @@ typedef struct smb_processor { uint16_t smbpr_threadcount2; /* second number of enabled threads */ } smb_processor_t; +/* + * SMBIOS implementation structure for SMB_TYPE_CACHE. + */ typedef struct smb_cache { smb_header_t smbca_hdr; /* structure header */ uint8_t smbca_socket; /* socket designation */ @@ -193,6 +211,9 @@ typedef struct smb_cache { #define SMB_CACHE_CFG_SOCKETED(c) (((c) >> 3) & 1) #define SMB_CACHE_CFG_LEVEL(c) (((c) & 7) + 1) +/* + * SMBIOS implementation structure for SMB_TYPE_PORT. + */ typedef struct smb_port { smb_header_t smbpo_hdr; /* structure header */ uint8_t smbpo_iref; /* internal reference designator */ @@ -202,6 +223,9 @@ typedef struct smb_port { uint8_t smbpo_ptype; /* port type */ } smb_port_t; +/* + * SMBIOS implementation structure for SMB_TYPE_SLOT. + */ typedef struct smb_slot { smb_header_t smbsl_hdr; /* structure header */ uint8_t smbsl_name; /* reference designation */ @@ -217,6 +241,9 @@ typedef struct smb_slot { uint8_t smbsl_df; /* device/function number */ } smb_slot_t; +/* + * SMBIOS implementation structure for SMB_TYPE_OBDEVS. + */ typedef struct smb_obdev { uint8_t smbob_type; /* encoded type and enable bit */ uint8_t smbob_name; /* description string */ @@ -224,11 +251,18 @@ typedef struct smb_obdev { #define SMB_OBT_ENABLED 0x80 /* enable bit within smbob_type */ +/* + * SMBIOS implementation structure for SMB_TYPE_OEMSTR, SMB_TYPE_SYSCONFSTR, + * and SMB_TYPE_LANG. + */ typedef struct smb_strtab { smb_header_t smbtb_hdr; /* structure header */ uint8_t smbtb_count; /* number of strings */ } smb_strtab_t; +/* + * SMBIOS implementation structure for SMB_TYPE_LANG. + */ typedef struct smb_lang { smb_header_t smblang_hdr; /* structure header */ uint8_t smblang_num; /* number of installed languages */ @@ -237,6 +271,9 @@ typedef struct smb_lang { uint8_t smblang_cur; /* current language string */ } smb_lang_t; +/* + * SMBIOS implementation structure for SMB_TYPE_EVENTLOG. + */ typedef struct smb_sel { smb_header_t smbsel_hdr; /* structure header */ uint16_t smbsel_len; /* log area length */ @@ -252,6 +289,9 @@ typedef struct smb_sel { uint8_t smbsel_typev[1]; /* array of type descriptors */ } smb_sel_t; +/* + * SMBIOS implementation structure for SMB_TYPE_MEMARRAY. + */ typedef struct smb_memarray { smb_header_t smbmarr_hdr; /* structure header */ uint8_t smbmarr_loc; /* location */ @@ -263,6 +303,9 @@ typedef struct smb_memarray { uint64_t smbmarr_extcap; /* extended maximum capacity */ } smb_memarray_t; +/* + * SMBIOS implementation structure for SMB_TYPE_MEMARRAYMAP. + */ typedef struct smb_memarrmap { smb_header_t smbamap_hdr; /* structure header */ uint32_t smbamap_start; /* starting address in kilobytes */ @@ -273,6 +316,9 @@ typedef struct smb_memarrmap { uint64_t smbamap_extend; /* extended ending address in bytes */ } smb_memarrmap_t; +/* + * SMBIOS implementation structure for SMB_TYPE_MEMDEVICE. + */ typedef struct smb_memdevice { smb_header_t smbmdev_hdr; /* structure header */ uint16_t smbmdev_array; /* array handle */ @@ -301,6 +347,9 @@ typedef struct smb_memdevice { #define SMB_MDS_KBYTES 0x8000 /* size in specified in kilobytes */ +/* + * SMBIOS implementation structure for SMB_TYPE_MEMDEVICEMAP. + */ typedef struct smb_memdevmap { smb_header_t smbdmap_hdr; /* structure header */ uint32_t smbdmap_start; /* starting address in kilobytes */ @@ -314,6 +363,9 @@ typedef struct smb_memdevmap { uint64_t smbdmap_extend; /* extended ending address */ } smb_memdevmap_t; +/* + * SMBIOS implementation structure for SMB_TYPE_BATTERY. + */ typedef struct smb_battery { smb_header_t smbbat_hdr; /* structure header */ uint8_t smbbat_loc; /* location */ @@ -333,6 +385,9 @@ typedef struct smb_battery { uint32_t smbbat_oemdata; /* OEM-specific data */ } smb_battery_t; +/* + * SMBIOS implementation structure for SMB_TYPE_SECURITY. + */ typedef struct smb_hwsec { smb_header_t smbhs_hdr; /* structure header */ uint8_t smbhs_settings; /* settings byte */ @@ -343,12 +398,104 @@ typedef struct smb_hwsec { #define SMB_HWS_ADM_PS(x) (((x) & 0x0C) >> 2) #define SMB_HWS_PAN_PS(x) (((x) & 0x03) >> 0) +/* + * SMBIOS implementation structure for SMB_TYPE_VPROBE. + */ +typedef struct smb_vprobe { + smb_header_t smbvpr_hdr; /* structure header */ + uint8_t smbvpr_descr; /* description string */ + uint8_t smbvpr_locstat; /* location and status */ + uint16_t smbvpr_maxval; /* maximum voltage */ + uint16_t smbvpr_minval; /* minimum voltage */ + uint16_t smbvpr_resolution; /* probe resolution */ + uint16_t smbvpr_tolerance; /* probe tolerance */ + uint16_t smbvpr_accuracy; /* probe accuracy */ + uint32_t smbvpr_oem; /* vendor-specific data */ + uint16_t smbvpr_nominal; /* nominal value */ +} smb_vprobe_t; + +#define SMB_VPROBE_MINLEN 0x14 +#define SMB_VPROBE_NOMINAL_MINLEN 0x16 + +#define SMB_VPROBE_LOCATION(x) ((x) & 0x1f) +#define SMB_VPROBE_STATUS(x) (((x) >> 5) & 0x7) + +/* + * SMBIOS implementation structure for SMB_TYPE_COOLDEV. + */ +typedef struct smb_cooldev { + smb_header_t smbcdev_hdr; /* structure header */ + uint16_t smbcdev_tprobe; /* temperature probe */ + uint8_t smbcdev_typstat; /* type and status */ + uint8_t smbcdev_group; /* group identifier */ + uint32_t smbcdev_oem; /* vendor-specific data */ + uint16_t smbcdev_nominal; /* nominal value */ + uint8_t smbcdev_descr; /* description string */ +} smb_cooldev_t; + +#define SMB_COOLDEV_MINLEN 0x0c +#define SMB_COOLDEV_NOMINAL_MINLEN 0x0e +#define SMB_COOLDEV_DESCR_MINLEN 0x0f + +#define SMB_COOLDEV_TYPE(x) ((x) & 0x1f) +#define SMB_COOLDEV_STATUS(x) (((x) >> 5) & 0x7) + +/* + * SMBIOS implementation structure for SMB_TYPE_TPROBE. + */ +typedef struct smb_tprobe { + smb_header_t smbtpr_hdr; /* structure header */ + uint8_t smbtpr_descr; /* description string */ + uint8_t smbtpr_locstat; /* location and status */ + uint16_t smbtpr_maxval; /* maximum temperature */ + uint16_t smbtpr_minval; /* minimum temperature */ + uint16_t smbtpr_resolution; /* probe resolution */ + uint16_t smbtpr_tolerance; /* probe tolerance */ + uint16_t smbtpr_accuracy; /* probe accuracy */ + uint32_t smbtpr_oem; /* vendor-specific data */ + uint16_t smbtpr_nominal; /* nominal value */ +} smb_tprobe_t; + +#define SMB_TPROBE_MINLEN 0x14 +#define SMB_TPROBE_NOMINAL_MINLEN 0x16 + +#define SMB_TPROBE_LOCATION(x) ((x) & 0x1f) +#define SMB_TPROBE_STATUS(x) (((x) >> 5) & 0x7) + +/* + * SMBIOS implementation structure for SMB_TYPE_IPROBE. + */ +typedef struct smb_iprobe { + smb_header_t smbipr_hdr; /* structure header */ + uint8_t smbipr_descr; /* description string */ + uint8_t smbipr_locstat; /* location and status */ + uint16_t smbipr_maxval; /* maximum current */ + uint16_t smbipr_minval; /* minimum current */ + uint16_t smbipr_resolution; /* probe resolution */ + uint16_t smbipr_tolerance; /* probe tolerance */ + uint16_t smbipr_accuracy; /* probe accuracy */ + uint32_t smbipr_oem; /* vendor-specific data */ + uint16_t smbipr_nominal; /* nominal value */ +} smb_iprobe_t; + +#define SMB_IPROBE_MINLEN 0x14 +#define SMB_IPROBE_NOMINAL_MINLEN 0x16 + +#define SMB_IPROBE_LOCATION(x) ((x) & 0x1f) +#define SMB_IPROBE_STATUS(x) (((x) >> 5) & 0x7) + +/* + * SMBIOS implementation structure for SMB_TYPE_BOOT. + */ typedef struct smb_boot { smb_header_t smbbo_hdr; /* structure header */ uint8_t smbbo_pad[6]; /* reserved for future use */ uint8_t smbbo_status[1]; /* variable-length status buffer */ } smb_boot_t; +/* + * SMBIOS implementation structure for SMB_TYPE_IPMIDEV. + */ typedef struct smb_ipmi { smb_header_t smbipm_hdr; /* structure header */ uint8_t smbipm_type; /* interface type */ @@ -381,6 +528,9 @@ typedef struct smb_ipmi { #define SMB_IPM_IMODE_EDGE 0 #define SMB_IPM_IMODE_LEVEL 1 +/* + * SMBIOS implementation structure for SMB_TYPE_POWERSUP. + */ typedef struct smb_powersup { smb_header_t smbpsup_hdr; /* structure header */ uint8_t smbpsup_group; /* group id */ @@ -405,6 +555,9 @@ typedef struct smb_powersup { #define SMB_PSU_CHARS_STATUS(x) (((x) >> 7) & 0x7) #define SMB_PSU_CHARS_TYPE(x) (((x) >> 10) & 0xf) +/* + * SMBIOS implementation structure for SMB_TYPE_OBDEVEXT. + */ typedef struct smb_obdev_ext { smb_header_t smbobe_hdr; /* structure header */ uint8_t smbobe_name; /* reference designation */ @@ -415,6 +568,9 @@ typedef struct smb_obdev_ext { uint8_t smbobe_df; /* device/function number */ } smb_obdev_ext_t; +/* + * SMBIOS implementation structure for SUN_OEM_EXT_PROCESSOR. + */ typedef struct smb_processor_ext { smb_header_t smbpre_hdr; /* structure header */ uint16_t smbpre_processor; /* processor handle */ @@ -423,6 +579,9 @@ typedef struct smb_processor_ext { uint16_t smbpre_apicid[1]; /* strand initial apic id */ } smb_processor_ext_t; +/* + * SMBIOS implementation structure for SUN_OEM_EXT_PORT. + */ typedef struct smb_port_ext { smb_header_t smbpoe_hdr; /* structure header */ uint16_t smbpoe_chassis; /* chassis handle */ @@ -432,12 +591,18 @@ typedef struct smb_port_ext { uint8_t smbpoe_phy; /* PHY number */ } smb_port_ext_t; +/* + * SMBIOS implementation structure for SUN_OEM_PCIEXRC. + */ typedef struct smb_pciexrc { smb_header_t smbpciexrc_hdr; /* structure header */ uint16_t smbpciexrc_bboard; /* base board handle */ uint16_t smbpciexrc_bdf; /* PCI Bus/Dev/Func */ } smb_pciexrc_t; +/* + * SMBIOS implementation structure for SUN_OEM_EXT_MEMARRAY. + */ typedef struct smb_memarray_ext { smb_header_t smbmarre_hdr; /* structure header */ uint16_t smbmarre_ma; /* memory array handle */ @@ -445,6 +610,9 @@ typedef struct smb_memarray_ext { uint16_t smbmarre_bdf; /* PCI bus/dev/funct */ } smb_memarray_ext_t; +/* + * SMBIOS implementation structure for SUN_OEM_EXT_MEMDEVICE. + */ typedef struct smb_memdevice_ext { smb_header_t smbmdeve_hdr; /* structure header */ uint16_t smbmdeve_mdev; /* memory device handle */ @@ -491,7 +659,7 @@ struct smbios_hdl { #define SMB_RANGE_LIMIT 0xFFFFF /* limit of physical address range */ #define SMB_SCAN_STEP 16 /* stepping by paragraph */ -#define SMB_MAJMIN(M, m) ((((M) & 0xFF) << 16) | ((m) & 0xFF)) +#define SMB_MAJMIN(M, m) ((((M) & 0xFF) << 8) | ((m) & 0xFF)) #define SMB_MAJOR(v) (((v) & 0xFF00) >> 8) #define SMB_MINOR(v) (((v) & 0x00FF)) -- cgit v1.2.3 From 614f1d633e921143ad22010eeec64ed7c6aa627c Mon Sep 17 00:00:00 2001 From: Jerry Jelinek Date: Tue, 31 Oct 2017 18:39:20 +0000 Subject: 9055 panic in prgetattr Reviewed by: Jason King Reviewed by: Rich Lowe Approved by: Dan McDonald --- usr/src/uts/common/fs/proc/prvnops.c | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) diff --git a/usr/src/uts/common/fs/proc/prvnops.c b/usr/src/uts/common/fs/proc/prvnops.c index dedf1127cb..9a08f0c030 100644 --- a/usr/src/uts/common/fs/proc/prvnops.c +++ b/usr/src/uts/common/fs/proc/prvnops.c @@ -1592,6 +1592,11 @@ pr_read_spymaster(prnode_t *pnp, uio_t *uiop) if ((error = prlock(pnp, ZNO)) != 0) return (error); + if (pnp->pr_common->prc_thread == NULL) { + prunlock(pnp); + return (0); + } + lwp = pnp->pr_common->prc_thread->t_lwp; if (lwp->lwp_spymaster == NULL) { @@ -2621,6 +2626,11 @@ pr_read_spymaster_32(prnode_t *pnp, uio_t *uiop) if ((error = prlock(pnp, ZNO)) != 0) return (error); + if (pnp->pr_common->prc_thread == NULL) { + prunlock(pnp); + return (0); + } + lwp = pnp->pr_common->prc_thread->t_lwp; if (lwp->lwp_spymaster == NULL) { @@ -3147,7 +3157,8 @@ prgetattr(vnode_t *vp, vattr_t *vap, int flags, cred_t *cr, vap->va_size = 0; break; case PR_SPYMASTER: - if (pnp->pr_common->prc_thread->t_lwp->lwp_spymaster != NULL) { + if (pnp->pr_common->prc_thread != NULL && + pnp->pr_common->prc_thread->t_lwp->lwp_spymaster != NULL) { vap->va_size = PR_OBJSIZE(psinfo32_t, psinfo_t); } else { vap->va_size = 0; -- cgit v1.2.3