summaryrefslogtreecommitdiff
path: root/usr/src
diff options
context:
space:
mode:
authorKeith M Wesolowski <wesolows@foobazco.org>2013-02-21 23:12:27 +0000
committerKeith M Wesolowski <wesolows@foobazco.org>2013-02-21 23:12:27 +0000
commitd82d55f6f99743c699053ffba0552318154516c5 (patch)
tree65e3489b9c1685ce85df438ef7023634977e0b22 /usr/src
parentc6920fb1d0f6cd852da06e049631f1ee274b5b9d (diff)
parentc61ea5668634a215fd1c9000beb7f6d2853b3468 (diff)
downloadillumos-joyent-d82d55f6f99743c699053ffba0552318154516c5.tar.gz
Merge github.com:illumos/illumos-gate
* github.com:illumos/illumos-gate: (49 commits) commit c61ea5668634a215fd1c9000beb7f6d2853b3468 3557 dumpvp_size is not updated correctly when a dump zvol's size is changed 3558 setting the volsize on a dump device does not return back ENOSPC 3559 setting a volsize larger than the space available sometimes succeeds 3560 dumpadm should be able to remove a dump device commit 9eb57f7f3fbb970d4b9b89dcd5ecf543fe2414d5 3578 transferring the freed map to the defer map should be constant time 3579 ztest trips assertion in metaslab_weight() commit 9583f7179cb3bb19c38f4a8567cb8d51786036f1 3501 mdb: ::thread -d needs the SWITCH column commit 870e339d55f32bf17ce54ee9557ef0ac88ab4d5f 3496 sysevent runtime files are under /var/run commit 03205638622365000528794a52a1c0a8e846554e 3431 sharectl prints garbage when it failed commit cfe63ebf3593a7e45618955bfd1a754f30fc5fcf 3412 The ascii art in nfs4.h needs update commit 11bb729e438c0522ef1254effe8c8a39e441d7d5 1927 nfs4 stale clientid loop (OI server, Linux client) commit 28f2c52052034474a5881e13013564f72ffa345f 3515 sd gives RMW warnings for reads commit 16a4a8074274d2d7cc408589cf6359f4a378c861 3552 condensing one space map burns 3 seconds of CPU in spa_sync() thread 3564 spa_sync() spends 5-10% of its time in metaslab_sync() (when not condensing) 3566 recursive mutex panic in specfs commit 20128a0826f9c53167caa9215c12f08beee48e30 3561 arc_meta_limit should be exposed via kstats 3116 zpool reguid may log negative guids to internal SPA history commit c3a66015199e1814c2af8f7e6929af2004302e7e 3537 want pool io kstats commit ccc71be50bb49efb4e31004c77fb3e065e9c0596 3523 SMB NT Notify returning too soon commit bfbce3c1273efa22c185ea2995c57c37163fd7c3 3223 SMB FindFirst/FindNext don't fill in Last Name Offset commit 42c141d3747f50c9bfb13e3cf5f32828312a7b79 374 cron should send more useful mail commit 1f9f06cf154565efc5425d8e2c4d511ea99b0a58 3529 iostat should display time used by dtrace commit d5285cae913f4e01ffa0e6693a6d8ef1fbea30ba 3522 zfs module should not allow uninitialized variables commit 7535ae1914017b0e648abd7a139aca709fa82be3 3503 usba doesn't initialize cc_no_resources, causes gibberish output in kstat: commit e5dc7eac9e55f81548c4f12c8a2879d42a35ad84 3531 Race between log_sysevent_filename() and log_event_upcall() can cause panic commit 644b952899ad74c91b80401bc5cec525cdd9d87f 3512 rounding discrepancy in sa_find_sizes() 3513 mismatch between SA header size and layout commit 43ae55058ad99c869a9ae39d039490e8a3680520 3534 Disable EEE support in igb for I350 commit 838d71726afbdb6e9ea1358597d7a2da477d6831 3535 mdb ::print should pretty-print ipaddr_t and friends commit 15c4b7fc60958757a4ae2244a3910f06c3308202 3305 smbfs mount shows password commit 9dc3941c735ef88de46e850f745aa556d3a071a5 3507 Tunable to allow block allocation even on degraded vdevs commit e98f46cc16b6ba1555409cb3c7e384bdb0792875 3519 DTrace fails to resolve const types from fbt 3520 dtrace internal error -- token type 316 is not a valid D compilation token 3521 clean up dtrace unit tests commit db8a3845f437a4151d759cc8d253e54e2911d7e6 3516 Leftover multidata transmit kernel statistics in ipv6 commit fabf08ae7a95a47c3e249ee651d83d26f798bcfa 3514 Spurious errors setting up new SMB client sessions commit 1b912ec7100c10e7243bf0879af0fe580e08c73d 3498 panic in arc_read(): !refcount_is_zero(&pbuf->b_hdr->b_refcnt) commit aea676fd5203d93bed37515d4f405d6a31c21509 3508 NFS4 data corruption (client side) commit c93cc65a53e442bf8f9292f82e8c0797e0ed3f3d 3511 dtrace.c erroneously checks for memory alignment on amd64 commit 39f633a09e54fab2b9cf8d9d3ddc2a043b3e7465 3325 nsmb_close locking and teardown deadlock commit 28e4da25922bdfc5cba7ab29f47de911bbd78009 3465 ::walk ... | ::<dcmd> misinterprets input as symbol names 3466 ::tsd should handle missing/NULL values better 3467 mdb_ctf_vread() could be more useful 3468 mdb enhancements for zfs development 3470 ::whatis does not print callers from KMF_LITE 3473 mdb_get_module() returns wrong module commit 52fd7480cd8cd8da8ccac00d6af67471a23f06d2 3371 dumpadm -z is not documented in manpage 3380 zfs man page: documentation for zfs allow is confusing commit a0900badd8eb6bcca99411c8906b483e84f2da91 3196 ao_gendisp use by make is racey commit ff512403afa294019aee0a9c4e4f778f1d7ed207 3237 r10 is added 2 times to panic info commit 4846df9b53c813b173160a71c267f6678e9bf59b 3502 panic in smb_server_shutdown (sl_count assertion) commit 5f1ef25c7a11451cbd3080dc3ce8e8db4ca996c4 604 CIFS server should traverse child mount points commit e633f2d79475b51f0a4d46972282225abf851733 749 "/usr/bin/kstat" should be rewritten in C (fix SPARC build) commit 66448911ac89c254e89afc52e114402115a497e3 749 "/usr/bin/kstat" should be rewritten in C commit b17f03d7d89b75b69b9b7db22f2316b700e3a5a8 3485 statd is not handling incoming SM_NOTIFY properly when the hostname is not resolvable commit b7c47e8c412d4654019e45625cf2be8f7fd6ee66 3492 some e1000g devices don't support 15 unicast addresses commit 452fab4bfe0f4a0322a258885624366426683ae8 3419 usbftdi needs to support the BeagleBone commit 33c41f2b7f5e60517664bd7f392221865f833526 3477 SunSSH config should accept TCPKeepAlive as synonym for KeepAlive commit 3c1e517454d5ef05eda14277b3af58472e9b26a9 452 getconf should support NPROCESSORS_* commit c92bf99ee60c0b1fe1289fef2b4034126c7867a5 3474 tar should support -C on extract commit a6f561b4aee75d0d028e7b36b151c8ed8a86bc76 3035 LZ4 compression support in ZFS and GRUB commit 7b1753e64ab6c8c68e7cd79acbedfdfba12bd7f8 3444 README for usr/src/test 3445 ZFS tests for restricted aclmode Conflicts: usr/src/cmd/cron/cron.c usr/src/cmd/mdb/common/mdb/mdb_ctf.c usr/src/cmd/mdb/common/mdb/mdb_ctf.h usr/src/cmd/ssh/libssh/common/readconf.c usr/src/cmd/ssh/sshd/servconf.c usr/src/cmd/stat/Makefile usr/src/common/zfs/zfeature_common.c usr/src/common/zfs/zfeature_common.h usr/src/common/zfs/zfs_prop.c usr/src/man/man1m/zfs.1m usr/src/man/man4/ssh_config.4 usr/src/man/man4/sshd_config.4 usr/src/man/man5/zpool-features.5 usr/src/uts/common/fs/zfs/zfs_ioctl.c usr/src/uts/common/io/scsi/targets/sd.c
Diffstat (limited to 'usr/src')
-rw-r--r--usr/src/cmd/Makefile3
-rw-r--r--usr/src/cmd/cron/cron.c51
-rw-r--r--usr/src/cmd/dtrace/test/tst/common/funcs/tst.copyin.d9
-rw-r--r--usr/src/cmd/dtrace/test/tst/common/funcs/tst.strjoin.d9
-rw-r--r--usr/src/cmd/dtrace/test/tst/common/misc/tst.dynopt.d23
-rw-r--r--usr/src/cmd/dtrace/test/tst/common/pointers/err.BadAlign.d7
-rw-r--r--usr/src/cmd/dtrace/test/tst/common/pointers/err.InvalidAddress2.d5
-rw-r--r--usr/src/cmd/dtrace/test/tst/common/pointers/err.InvalidAddress3.d7
-rw-r--r--usr/src/cmd/dtrace/test/tst/common/pointers/err.InvalidAddress4.d11
-rw-r--r--usr/src/cmd/dtrace/test/tst/common/pointers/err.InvalidAddress5.d49
-rw-r--r--usr/src/cmd/dtrace/test/tst/common/print/err.D_PRINT_AGG.bad.d29
-rw-r--r--usr/src/cmd/dtrace/test/tst/common/print/err.D_PRINT_VOID.bad.d7
-rw-r--r--usr/src/cmd/dtrace/test/tst/common/print/err.D_PROTO_LEN.bad.d7
-rw-r--r--usr/src/cmd/dtrace/test/tst/common/safety/tst.copyin.d6
-rw-r--r--usr/src/cmd/dtrace/test/tst/common/scripting/tst.egid.ksh6
-rw-r--r--usr/src/cmd/dtrace/test/tst/common/speculation/err.BufSizeVariations2.d4
-rw-r--r--usr/src/cmd/dtrace/test/tst/common/trace/err.D_PROTO_LEN.bad.d10
-rw-r--r--usr/src/cmd/dtrace/test/tst/common/trace/err.D_TRACE_AGG.bad.d29
-rw-r--r--usr/src/cmd/dtrace/test/tst/common/trace/err.D_TRACE_VOID.bad.d9
-rw-r--r--usr/src/cmd/dtrace/test/tst/common/types/tst.const.d29
-rw-r--r--usr/src/cmd/dumpadm/dconf.c13
-rw-r--r--usr/src/cmd/fs.d/nfs/statd/sm_proc.c85
-rw-r--r--usr/src/cmd/fs.d/smbclnt/mount/mount.c8
-rw-r--r--usr/src/cmd/fs.d/smbclnt/smbiod/smbiod.c33
-rw-r--r--usr/src/cmd/getconf/getconf.c6
-rw-r--r--usr/src/cmd/kstat/kstat.pl245
-rw-r--r--usr/src/cmd/mdb/common/mdb/mdb.c3
-rw-r--r--usr/src/cmd/mdb/common/mdb/mdb_cmds.c2
-rw-r--r--usr/src/cmd/mdb/common/mdb/mdb_ctf.c394
-rw-r--r--usr/src/cmd/mdb/common/mdb/mdb_ctf.h11
-rw-r--r--usr/src/cmd/mdb/common/mdb/mdb_frame.h3
-rw-r--r--usr/src/cmd/mdb/common/mdb/mdb_modapi.c34
-rw-r--r--usr/src/cmd/mdb/common/mdb/mdb_print.c100
-rw-r--r--usr/src/cmd/mdb/common/modules/conf/mapfile-extern4
-rw-r--r--usr/src/cmd/mdb/common/modules/genunix/findstack_subr.c20
-rw-r--r--usr/src/cmd/mdb/common/modules/genunix/kmem.c7
-rw-r--r--usr/src/cmd/mdb/common/modules/genunix/thread.c15
-rw-r--r--usr/src/cmd/mdb/common/modules/genunix/tsd.c25
-rw-r--r--usr/src/cmd/mdb/common/modules/libc/libc.c82
-rw-r--r--usr/src/cmd/mdb/common/modules/zfs/zfs.c402
-rw-r--r--usr/src/cmd/mdb/i86xpv/modules/xpv/xpv.c46
-rw-r--r--usr/src/cmd/mdb/i86xpv/modules/xpv_psm/xpv_psm.c26
-rw-r--r--usr/src/cmd/mdb/i86xpv/modules/xpv_uppc/xpv_uppc.c18
-rw-r--r--usr/src/cmd/smbsrv/smbd/server.xml4
-rw-r--r--usr/src/cmd/ssh/libssh/common/readconf.c2
-rw-r--r--usr/src/cmd/ssh/sshd/servconf.c2
-rw-r--r--usr/src/cmd/stat/Makefile1
-rw-r--r--usr/src/cmd/stat/common/acquire.c2
-rw-r--r--usr/src/cmd/stat/common/statcommon.h6
-rw-r--r--usr/src/cmd/stat/iostat/iostat.c24
-rw-r--r--usr/src/cmd/stat/kstat/Makefile66
-rw-r--r--usr/src/cmd/stat/kstat/kstat.c1469
-rw-r--r--usr/src/cmd/stat/kstat/kstat.h269
-rw-r--r--usr/src/cmd/tar/tar.c1
-rw-r--r--usr/src/cmd/zdb/zdb.c19
-rw-r--r--usr/src/cmd/zfs/zfs_main.c12
-rw-r--r--usr/src/common/zfs/zfeature_common.c2
-rw-r--r--usr/src/common/zfs/zfeature_common.h2
-rw-r--r--usr/src/common/zfs/zfs_prop.c2
-rw-r--r--usr/src/lib/libdtrace/common/dt_cc.c6
-rw-r--r--usr/src/lib/libdtrace/common/dt_decl.c6
-rw-r--r--usr/src/lib/libdtrace/common/dt_errtags.h2
-rw-r--r--usr/src/lib/libshare/nfs/libshare_nfs.c4
-rw-r--r--usr/src/lib/libshare/smb/libshare_smb.c2
-rw-r--r--usr/src/lib/libzfs/common/libzfs_dataset.c22
-rw-r--r--usr/src/lib/libzfs/common/mapfile-vers1
-rw-r--r--usr/src/lib/libzpool/common/kernel.c34
-rw-r--r--usr/src/lib/libzpool/common/sys/zfs_context.h10
-rw-r--r--usr/src/lib/smbsrv/libsmb/common/libsmb.h1
-rw-r--r--usr/src/lib/smbsrv/libsmb/common/smb_cfg.c6
-rw-r--r--usr/src/lib/smbsrv/libsmb/common/smb_info.c2
-rw-r--r--usr/src/lib/smbsrv/libsmb/common/smb_kmod.c1
-rw-r--r--usr/src/man/man1/getconf.1137
-rw-r--r--usr/src/man/man1/tar.13
-rw-r--r--usr/src/man/man1m/dumpadm.1m50
-rw-r--r--usr/src/man/man1m/iostat.1m51
-rw-r--r--usr/src/man/man1m/kstat.1m36
-rw-r--r--usr/src/man/man1m/savecore.1m25
-rw-r--r--usr/src/man/man1m/syseventconfd.1m5
-rw-r--r--usr/src/man/man1m/syseventd.1m7
-rw-r--r--usr/src/man/man1m/zfs.1m147
-rw-r--r--usr/src/man/man4/smb.415
-rw-r--r--usr/src/man/man4/ssh_config.44
-rw-r--r--usr/src/man/man4/sshd_config.44
-rw-r--r--usr/src/man/man5/zpool-features.56
-rw-r--r--usr/src/pkg/manifests/driver-serial-usbftdi.mf1
-rw-r--r--usr/src/pkg/manifests/system-dtrace-tests.mf3
-rw-r--r--usr/src/pkg/manifests/system-test-zfstest.mf8
-rw-r--r--usr/src/test/README86
-rw-r--r--usr/src/test/zfs-tests/doc/README4
-rw-r--r--usr/src/test/zfs-tests/runfiles/delphix.run8
-rw-r--r--usr/src/test/zfs-tests/runfiles/openindiana.run8
-rw-r--r--usr/src/test/zfs-tests/tests/functional/acl/nontrivial/Makefile3
-rw-r--r--usr/src/test/zfs-tests/tests/functional/acl/nontrivial/zfs_acl_aclmode_restricted_001_neg.ksh82
-rw-r--r--usr/src/test/zfs-tests/tests/functional/acl/trivial/Makefile3
-rw-r--r--usr/src/test/zfs-tests/tests/functional/acl/trivial/zfs_acl_aclmode_restricted_001_pos.ksh130
-rw-r--r--usr/src/uts/common/dtrace/dtrace.c11
-rw-r--r--usr/src/uts/common/fs/nfs/nfs4_client.c29
-rw-r--r--usr/src/uts/common/fs/nfs/nfs4_srv.c4
-rw-r--r--usr/src/uts/common/fs/smbclnt/netsmb/smb_dev.c4
-rw-r--r--usr/src/uts/common/fs/smbclnt/netsmb/smb_smb.c10
-rw-r--r--usr/src/uts/common/fs/smbsrv/smb_common_transact.c7
-rw-r--r--usr/src/uts/common/fs/smbsrv/smb_fem.c27
-rw-r--r--usr/src/uts/common/fs/smbsrv/smb_find.c13
-rw-r--r--usr/src/uts/common/fs/smbsrv/smb_fsops.c17
-rw-r--r--usr/src/uts/common/fs/smbsrv/smb_kshare.c32
-rw-r--r--usr/src/uts/common/fs/smbsrv/smb_node.c75
-rw-r--r--usr/src/uts/common/fs/smbsrv/smb_nt_cancel.c5
-rw-r--r--usr/src/uts/common/fs/smbsrv/smb_nt_transact_notify_change.c674
-rw-r--r--usr/src/uts/common/fs/smbsrv/smb_odir.c84
-rw-r--r--usr/src/uts/common/fs/smbsrv/smb_ofile.c9
-rw-r--r--usr/src/uts/common/fs/smbsrv/smb_pathname.c24
-rw-r--r--usr/src/uts/common/fs/smbsrv/smb_rename.c29
-rw-r--r--usr/src/uts/common/fs/smbsrv/smb_server.c21
-rw-r--r--usr/src/uts/common/fs/smbsrv/smb_session.c14
-rw-r--r--usr/src/uts/common/fs/smbsrv/smb_trans2_find.c254
-rw-r--r--usr/src/uts/common/fs/smbsrv/smb_tree.c10
-rw-r--r--usr/src/uts/common/fs/specfs/specsubr.c5
-rw-r--r--usr/src/uts/common/fs/zfs/arc.c82
-rw-r--r--usr/src/uts/common/fs/zfs/bptree.c2
-rw-r--r--usr/src/uts/common/fs/zfs/dbuf.c28
-rw-r--r--usr/src/uts/common/fs/zfs/dmu.c3
-rw-r--r--usr/src/uts/common/fs/zfs/dmu_diff.c8
-rw-r--r--usr/src/uts/common/fs/zfs/dmu_objset.c15
-rw-r--r--usr/src/uts/common/fs/zfs/dmu_send.c20
-rw-r--r--usr/src/uts/common/fs/zfs/dmu_traverse.c79
-rw-r--r--usr/src/uts/common/fs/zfs/dsl_dataset.c11
-rw-r--r--usr/src/uts/common/fs/zfs/dsl_scan.c39
-rw-r--r--usr/src/uts/common/fs/zfs/lzjb.c7
-rw-r--r--usr/src/uts/common/fs/zfs/metaslab.c385
-rw-r--r--usr/src/uts/common/fs/zfs/refcount.c2
-rw-r--r--usr/src/uts/common/fs/zfs/sa.c29
-rw-r--r--usr/src/uts/common/fs/zfs/spa.c9
-rw-r--r--usr/src/uts/common/fs/zfs/spa_misc.c12
-rw-r--r--usr/src/uts/common/fs/zfs/space_map.c33
-rw-r--r--usr/src/uts/common/fs/zfs/sys/arc.h8
-rw-r--r--usr/src/uts/common/fs/zfs/sys/dmu_traverse.h3
-rw-r--r--usr/src/uts/common/fs/zfs/sys/dsl_pool.h6
-rw-r--r--usr/src/uts/common/fs/zfs/sys/metaslab_impl.h32
-rw-r--r--usr/src/uts/common/fs/zfs/sys/refcount.h5
-rw-r--r--usr/src/uts/common/fs/zfs/sys/spa_impl.h2
-rw-r--r--usr/src/uts/common/fs/zfs/sys/space_map.h7
-rw-r--r--usr/src/uts/common/fs/zfs/sys/zvol.h2
-rw-r--r--usr/src/uts/common/fs/zfs/vdev.c1
-rw-r--r--usr/src/uts/common/fs/zfs/vdev_queue.c54
-rw-r--r--usr/src/uts/common/fs/zfs/vdev_raidz.c3
-rw-r--r--usr/src/uts/common/fs/zfs/zap_leaf.c2
-rw-r--r--usr/src/uts/common/fs/zfs/zfs_byteswap.c2
-rw-r--r--usr/src/uts/common/fs/zfs/zfs_fuid.c9
-rw-r--r--usr/src/uts/common/fs/zfs/zfs_ioctl.c7
-rw-r--r--usr/src/uts/common/fs/zfs/zfs_log.c3
-rw-r--r--usr/src/uts/common/fs/zfs/zfs_rlock.c2
-rw-r--r--usr/src/uts/common/fs/zfs/zfs_vfsops.c18
-rw-r--r--usr/src/uts/common/fs/zfs/zfs_vnops.c9
-rw-r--r--usr/src/uts/common/fs/zfs/zil.c4
-rw-r--r--usr/src/uts/common/fs/zfs/zio.c2
-rw-r--r--usr/src/uts/common/fs/zfs/zvol.c99
-rw-r--r--usr/src/uts/common/inet/ip_stack.h5
-rw-r--r--usr/src/uts/common/io/dump.c8
-rw-r--r--usr/src/uts/common/io/e1000g/e1000g_main.c5
-rw-r--r--usr/src/uts/common/io/igb/igb_82575.c5
-rw-r--r--usr/src/uts/common/io/igb/igb_gld.c34
-rw-r--r--usr/src/uts/common/io/igb/igb_main.c2
-rw-r--r--usr/src/uts/common/io/scsi/targets/sd.c28
-rw-r--r--usr/src/uts/common/io/usb/clients/usbser/usbftdi/uftdi_dsd.c49
-rw-r--r--usr/src/uts/common/io/usb/usba/hcdi.c30
-rw-r--r--usr/src/uts/common/nfs/nfs4.h8
-rw-r--r--usr/src/uts/common/os/cpu.c105
-rw-r--r--usr/src/uts/common/os/log_sysevent.c138
-rw-r--r--usr/src/uts/common/smbsrv/smb_ioctl.h2
-rw-r--r--usr/src/uts/common/smbsrv/smb_kproto.h20
-rw-r--r--usr/src/uts/common/smbsrv/smb_ktypes.h38
-rw-r--r--usr/src/uts/common/smbsrv/smbinfo.h2
-rw-r--r--usr/src/uts/common/sys/cpuvar.h4
-rw-r--r--usr/src/uts/common/sys/dumpadm.h2
-rw-r--r--usr/src/uts/common/sys/usb/clients/usbser/usbftdi/uftdi_var.h9
-rw-r--r--usr/src/uts/common/sys/usb/usba/hcdi.h12
-rw-r--r--usr/src/uts/i86xpv/Makefile6
-rw-r--r--usr/src/uts/i86xpv/amd_opteron/Makefile4
-rw-r--r--usr/src/uts/i86xpv/cpu/scripts/Makefile (renamed from usr/src/cmd/kstat/Makefile)27
-rw-r--r--usr/src/uts/intel/ia32/os/archdep.c2
-rw-r--r--usr/src/uts/intel/zfs/Makefile1
-rw-r--r--usr/src/uts/sparc/zfs/Makefile1
183 files changed, 5408 insertions, 2239 deletions
diff --git a/usr/src/cmd/Makefile b/usr/src/cmd/Makefile
index 2df1f63a3a..3b38625c93 100644
--- a/usr/src/cmd/Makefile
+++ b/usr/src/cmd/Makefile
@@ -23,6 +23,7 @@
# Copyright 2010 Nexenta Systems, Inc. All rights reserved.
# Copyright (c) 2013 Joyent, Inc. All rights reserved.
# Copyright (c) 2012 by Delphix. All rights reserved.
+# Copyright (c) 2013 DEY Storage Systems, Inc. All rights reserved.
include ../Makefile.master
@@ -221,7 +222,6 @@ COMMON_SUBDIRS= \
killall \
krb5 \
ksh \
- kstat \
kvmstat \
last \
lastcomm \
@@ -612,7 +612,6 @@ MSGSUBDIRS= \
kbd \
krb5 \
ksh \
- kstat \
last \
ldap \
ldapcachemgr \
diff --git a/usr/src/cmd/cron/cron.c b/usr/src/cmd/cron/cron.c
index 347b03287a..8c5c54fb64 100644
--- a/usr/src/cmd/cron/cron.c
+++ b/usr/src/cmd/cron/cron.c
@@ -21,6 +21,8 @@
/*
* Copyright 2009 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
+ *
+ * Copyright 2013 Joshua M. Clulow <josh@sysmgr.org>
* Copyright 2012 Joyent, Inc. All rights reserved.
*/
@@ -146,7 +148,6 @@ error for each of your commands."
#define CLOCK_DRIFT "clock time drifted backwards after event!\n"
#define PIDERR "unexpected pid returned %d (ignored)"
#define CRONTABERR "Subject: Your crontab file has an error in it\n\n"
-#define CRONOUT "Subject: Output from \"cron\" command\n\n"
#define MALLOCERR "out of space, cannot create new string\n"
#define DIDFORK didfork
@@ -2797,6 +2798,7 @@ mail_result(struct usr *p, struct runinfo *pr, size_t filesize)
int nbytes;
char iobuf[BUFSIZ];
char *cmd;
+ char *lowname = (pr->jobtype == CRONEVENT ? "cron" : "at");
(void) uname(&name);
if ((ruser_ids = getpwnam(p->name)) == NULL)
@@ -2810,31 +2812,40 @@ mail_result(struct usr *p, struct runinfo *pr, size_t filesize)
if (mailpipe == NULL)
exit(127);
(void) fprintf(mailpipe, "To: %s\n", p->name);
- if (pr->jobtype == CRONEVENT) {
- (void) fprintf(mailpipe, CRONOUT);
- (void) fprintf(mailpipe, "Your \"cron\" job on %s\n",
- name.nodename);
- if (pr->jobname != NULL) {
- (void) fprintf(mailpipe, "%s\n\n", pr->jobname);
- }
- } else {
- (void) fprintf(mailpipe, "Subject: Output from \"at\" job\n\n");
- (void) fprintf(mailpipe, "Your \"at\" job on %s\n",
- name.nodename);
- if (pr->jobname != NULL) {
- (void) fprintf(mailpipe, "\"%s\"\n\n", pr->jobname);
- }
- }
- /* Tmp. file is fopen'ed w/ "r", secure open */
+ (void) fprintf(mailpipe, "Subject: %s <%s@%s> %s\n",
+ (pr->jobtype == CRONEVENT ? "Cron" : "At"),
+ p->name, name.nodename, pr->jobname);
+
+ /*
+ * RFC3834 (Section 5) defines the Auto-Submitted header to prevent
+ * vacation replies, et al, from being sent in response to
+ * machine-generated mail.
+ */
+ (void) fprintf(mailpipe, "Auto-Submitted: auto-generated\n");
+
+ /*
+ * Additional headers for mail filtering and diagnostics:
+ */
+ (void) fprintf(mailpipe, "X-Mailer: cron (%s %s)\n", name.sysname,
+ name.release);
+ (void) fprintf(mailpipe, "X-Cron-User: %s\n", p->name);
+ (void) fprintf(mailpipe, "X-Cron-Host: %s\n", name.nodename);
+ (void) fprintf(mailpipe, "X-Cron-Job-Name: %s\n", pr->jobname);
+ (void) fprintf(mailpipe, "X-Cron-Job-Type: %s\n", lowname);
+
+ /*
+ * Message Body:
+ *
+ * (Temporary file is fopen'ed with "r", secure open.)
+ */
+ (void) fprintf(mailpipe, "\n");
if (filesize > 0 &&
(st = fopen(pr->outfile, "r")) != NULL) {
- (void) fprintf(mailpipe,
- "produced the following output:\n\n");
while ((nbytes = fread(iobuf, sizeof (char), BUFSIZ, st)) != 0)
(void) fwrite(iobuf, sizeof (char), nbytes, mailpipe);
(void) fclose(st);
} else {
- (void) fprintf(mailpipe, "completed.\n");
+ (void) fprintf(mailpipe, "Job completed with no output.\n");
}
(void) pclose(mailpipe);
exit(0);
diff --git a/usr/src/cmd/dtrace/test/tst/common/funcs/tst.copyin.d b/usr/src/cmd/dtrace/test/tst/common/funcs/tst.copyin.d
index 186b97419e..4ecc23e676 100644
--- a/usr/src/cmd/dtrace/test/tst/common/funcs/tst.copyin.d
+++ b/usr/src/cmd/dtrace/test/tst/common/funcs/tst.copyin.d
@@ -24,7 +24,9 @@
* Use is subject to license terms.
*/
-#pragma ident "%Z%%M% %I% %E% SMI"
+/*
+ * Copyright (c) 2012 by Delphix. All rights reserved.
+ */
/*
* ASSERTION:
@@ -52,3 +54,8 @@ BEGIN
printf("envp[0] = \"%s\"", copyinstr(envp));
exit(0);
}
+
+BEGIN
+{
+ exit(1)
+}
diff --git a/usr/src/cmd/dtrace/test/tst/common/funcs/tst.strjoin.d b/usr/src/cmd/dtrace/test/tst/common/funcs/tst.strjoin.d
index 392c18a6df..0f23737d38 100644
--- a/usr/src/cmd/dtrace/test/tst/common/funcs/tst.strjoin.d
+++ b/usr/src/cmd/dtrace/test/tst/common/funcs/tst.strjoin.d
@@ -24,7 +24,9 @@
* Use is subject to license terms.
*/
-#pragma ident "%Z%%M% %I% %E% SMI"
+/*
+ * Copyright (c) 2012 by Delphix. All rights reserved.
+ */
#pragma D option quiet
@@ -36,3 +38,8 @@ BEGIN
printf("%s\n", strjoin("", ""));
exit(0);
}
+
+BEGIN
+{
+ exit(1);
+}
diff --git a/usr/src/cmd/dtrace/test/tst/common/misc/tst.dynopt.d b/usr/src/cmd/dtrace/test/tst/common/misc/tst.dynopt.d
index cb98d73375..78d96f00a6 100644
--- a/usr/src/cmd/dtrace/test/tst/common/misc/tst.dynopt.d
+++ b/usr/src/cmd/dtrace/test/tst/common/misc/tst.dynopt.d
@@ -24,38 +24,45 @@
* Use is subject to license terms.
*/
-#pragma ident "%Z%%M% %I% %E% SMI"
+/*
+ * Copyright (c) 2012 by Delphix. All rights reserved.
+ */
#pragma D option quiet
#pragma D option switchrate=1ms
#pragma D option aggrate=1ms
-tick-100ms
+tick-50ms
{
i++;
}
-tick-100ms
-/i > 1/
+tick-50ms
+/!(i & 1) && i > 1/
{
setopt("quiet", "no");
setopt("quiet");
setopt("quiet");
setopt("quiet", "yes");
@["abc"] = count();
+}
+
+tick-50ms
+/(i & 1) && i > 1/
+{
printa("%@d\n", @);
}
-tick-100ms
-/i == 5/
+tick-50ms
+/i == 10/
{
setopt("switchrate", "5sec");
setopt("aggrate", "5sec");
}
-tick-100ms
-/i == 31/
+tick-50ms
+/i == 61/
{
exit(0);
}
diff --git a/usr/src/cmd/dtrace/test/tst/common/pointers/err.BadAlign.d b/usr/src/cmd/dtrace/test/tst/common/pointers/err.BadAlign.d
index ab4106dbee..3923cd910a 100644
--- a/usr/src/cmd/dtrace/test/tst/common/pointers/err.BadAlign.d
+++ b/usr/src/cmd/dtrace/test/tst/common/pointers/err.BadAlign.d
@@ -24,7 +24,9 @@
* Use is subject to license terms.
*/
-#pragma ident "%Z%%M% %I% %E% SMI"
+/*
+ * Copyright (c) 2012 by Delphix. All rights reserved.
+ */
/*
* ASSERTION: This test reproduces the alignment error.
@@ -39,9 +41,10 @@
BEGIN
{
- x = (int *) 64;
+ x = (int *)64;
y = *x;
trace(y);
+ exit(0);
}
ERROR
diff --git a/usr/src/cmd/dtrace/test/tst/common/pointers/err.InvalidAddress2.d b/usr/src/cmd/dtrace/test/tst/common/pointers/err.InvalidAddress2.d
index 324f40113a..6c79bfa420 100644
--- a/usr/src/cmd/dtrace/test/tst/common/pointers/err.InvalidAddress2.d
+++ b/usr/src/cmd/dtrace/test/tst/common/pointers/err.InvalidAddress2.d
@@ -24,7 +24,9 @@
* Use is subject to license terms.
*/
-#pragma ident "%Z%%M% %I% %E% SMI"
+/*
+ * Copyright (c) 2012 by Delphix. All rights reserved.
+ */
/*
* ASSERTION: D pointers do not allow invalid pointer accesses.
@@ -44,6 +46,7 @@ BEGIN
y = (int *) (x - 3300778156056);
*y = 3;
trace(*y);
+ exit(0);
}
ERROR
diff --git a/usr/src/cmd/dtrace/test/tst/common/pointers/err.InvalidAddress3.d b/usr/src/cmd/dtrace/test/tst/common/pointers/err.InvalidAddress3.d
index 39bd1140bd..66c203061d 100644
--- a/usr/src/cmd/dtrace/test/tst/common/pointers/err.InvalidAddress3.d
+++ b/usr/src/cmd/dtrace/test/tst/common/pointers/err.InvalidAddress3.d
@@ -24,7 +24,9 @@
* Use is subject to license terms.
*/
-#pragma ident "%Z%%M% %I% %E% SMI"
+/*
+ * Copyright (c) 2012 by Delphix. All rights reserved.
+ */
/*
* ASSERTION: D pointers do not allow invalid pointer accesses.
@@ -39,9 +41,10 @@
BEGIN
{
- y = (int *) (-33007);
+ y = (int *)-33007;
*y = 3;
trace(*y);
+ exit(0);
}
ERROR
diff --git a/usr/src/cmd/dtrace/test/tst/common/pointers/err.InvalidAddress4.d b/usr/src/cmd/dtrace/test/tst/common/pointers/err.InvalidAddress4.d
index 9d6b144086..f5f49e966f 100644
--- a/usr/src/cmd/dtrace/test/tst/common/pointers/err.InvalidAddress4.d
+++ b/usr/src/cmd/dtrace/test/tst/common/pointers/err.InvalidAddress4.d
@@ -24,7 +24,9 @@
* Use is subject to license terms.
*/
-#pragma ident "%Z%%M% %I% %E% SMI"
+/*
+ * Copyright (c) 2012 by Delphix. All rights reserved.
+ */
/*
* ASSERTION: Demonstrating valid memory access.
@@ -40,10 +42,11 @@
BEGIN
{
x = (int *)alloca(sizeof (int));
- printf("Address x: %x\n", (int) x);
- y = (int *) (x - 2);
+ printf("Address x: %x\n", (int)x);
+ y = (int *)(x - 2);
*y = 3;
- printf("Address y: %x\tValue: %d\n", (int) y, *y);
+ printf("Address y: %x\tValue: %d\n", (int)y, *y);
+ exit(0);
}
ERROR
diff --git a/usr/src/cmd/dtrace/test/tst/common/pointers/err.InvalidAddress5.d b/usr/src/cmd/dtrace/test/tst/common/pointers/err.InvalidAddress5.d
index 64b7728948..c4d35e9e3f 100644
--- a/usr/src/cmd/dtrace/test/tst/common/pointers/err.InvalidAddress5.d
+++ b/usr/src/cmd/dtrace/test/tst/common/pointers/err.InvalidAddress5.d
@@ -24,7 +24,9 @@
* Use is subject to license terms.
*/
-#pragma ident "%Z%%M% %I% %E% SMI"
+/*
+ * Copyright (c) 2012 by Delphix. All rights reserved.
+ */
/*
* ASSERTION:
@@ -32,44 +34,51 @@
* a runtime error.
*
* SECTION: Pointers and Arrays/Generic Pointers
- *
- * NOTES:
- * This test doesn't apply to x86; for the time being, we're working
- * around this with the preprocessor.
*/
#pragma D option quiet
-int array[3];
-uintptr_t uptr;
+#if defined(__i386) || defined(__amd64)
+#define __x86 1
+#endif
+
+int array[2];
+char *ptr;
int *p;
int *q;
int *r;
BEGIN
{
-#ifdef __i386
- exit(1);
-#else
- array[0] = 20;
- array[1] = 40;
- array[2] = 80;
+ array[0] = 0x12345678;
+ array[1] = 0xabcdefff;
- uptr = (uintptr_t) &array[0];
+ ptr = (char *) &array[0];
- p = (int *) (uptr);
- q = (int *) (uptr + 2);
- r = (int *) (uptr + 3);
+ p = (int *) (ptr);
+ q = (int *) (ptr + 2);
+ r = (int *) (ptr + 3);
- printf("array[0]: %d\t*p: %d\n", array[0], *p);
- printf("array[1]: %d\t*q: %d\n", array[1], *q);
- printf("array[2]: %d\t*r: %d\n", array[2], *r);
+ printf("*p: 0x%x\n", *p);
+ printf("*q: 0x%x\n", *q);
+ printf("*r: 0x%x\n", *r);
+ /*
+ * On x86, the above unaligned memory accesses are allowed and should
+ * not result in the ERROR probe firing.
+ */
+#ifdef __x86
+ exit(1);
+#else
exit(0);
#endif
}
ERROR
{
+#ifdef __x86
+ exit(0);
+#else
exit(1);
+#endif
}
diff --git a/usr/src/cmd/dtrace/test/tst/common/print/err.D_PRINT_AGG.bad.d b/usr/src/cmd/dtrace/test/tst/common/print/err.D_PRINT_AGG.bad.d
new file mode 100644
index 0000000000..5479d00126
--- /dev/null
+++ b/usr/src/cmd/dtrace/test/tst/common/print/err.D_PRINT_AGG.bad.d
@@ -0,0 +1,29 @@
+/*
+ * 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) 2012 by Delphix. All rights reserved.
+ */
+
+BEGIN
+{
+ @ = count();
+ print(@);
+}
+
+BEGIN
+{
+ exit(0);
+}
diff --git a/usr/src/cmd/dtrace/test/tst/common/print/err.D_PRINT_VOID.bad.d b/usr/src/cmd/dtrace/test/tst/common/print/err.D_PRINT_VOID.bad.d
index 902f07272d..4f45885d42 100644
--- a/usr/src/cmd/dtrace/test/tst/common/print/err.D_PRINT_VOID.bad.d
+++ b/usr/src/cmd/dtrace/test/tst/common/print/err.D_PRINT_VOID.bad.d
@@ -20,10 +20,15 @@
*/
/*
- * Copyright (c) 2011 by Delphix. All rights reserved.
+ * Copyright (c) 2012 by Delphix. All rights reserved.
*/
BEGIN
{
print((void)`p0);
}
+
+BEGIN
+{
+ exit(0);
+}
diff --git a/usr/src/cmd/dtrace/test/tst/common/print/err.D_PROTO_LEN.bad.d b/usr/src/cmd/dtrace/test/tst/common/print/err.D_PROTO_LEN.bad.d
index a1d3be1f62..368caebacb 100644
--- a/usr/src/cmd/dtrace/test/tst/common/print/err.D_PROTO_LEN.bad.d
+++ b/usr/src/cmd/dtrace/test/tst/common/print/err.D_PROTO_LEN.bad.d
@@ -20,10 +20,15 @@
*/
/*
- * Copyright (c) 2011 by Delphix. All rights reserved.
+ * Copyright (c) 2012 by Delphix. All rights reserved.
*/
BEGIN
{
print();
}
+
+BEGIN
+{
+ exit(0);
+}
diff --git a/usr/src/cmd/dtrace/test/tst/common/safety/tst.copyin.d b/usr/src/cmd/dtrace/test/tst/common/safety/tst.copyin.d
index 7426d19e1b..beb1c50bba 100644
--- a/usr/src/cmd/dtrace/test/tst/common/safety/tst.copyin.d
+++ b/usr/src/cmd/dtrace/test/tst/common/safety/tst.copyin.d
@@ -24,7 +24,9 @@
* Use is subject to license terms.
*/
-#pragma ident "%Z%%M% %I% %E% SMI"
+/*
+ * Copyright (c) 2012 by Delphix. All rights reserved.
+ */
/*
* ASSERTION:
@@ -39,7 +41,7 @@
*/
-#pragma D option bufsize=16
+#pragma D option bufsize=32
#pragma D option bufpolicy=ring
#pragma D option statusrate=1nsec
diff --git a/usr/src/cmd/dtrace/test/tst/common/scripting/tst.egid.ksh b/usr/src/cmd/dtrace/test/tst/common/scripting/tst.egid.ksh
index 9e1955f298..b0d985401c 100644
--- a/usr/src/cmd/dtrace/test/tst/common/scripting/tst.egid.ksh
+++ b/usr/src/cmd/dtrace/test/tst/common/scripting/tst.egid.ksh
@@ -25,7 +25,9 @@
# Use is subject to license terms.
#
-#ident "%Z%%M% %I% %E% SMI"
+#
+# Copyright (c) 2012 by Delphix. All rights reserved.
+#
############################################################################
# ASSERTION:
@@ -70,7 +72,7 @@ EOF
#chmod 555 the .d file
chmod 555 $dfilename >/dev/null 2>&1
-if [ &? -ne 0 ]; then
+if [ $? -ne 0 ]; then
print -u2 "chmod $dfilename failed"
exit 1
fi
diff --git a/usr/src/cmd/dtrace/test/tst/common/speculation/err.BufSizeVariations2.d b/usr/src/cmd/dtrace/test/tst/common/speculation/err.BufSizeVariations2.d
index f660e9a8f3..5ac7957ced 100644
--- a/usr/src/cmd/dtrace/test/tst/common/speculation/err.BufSizeVariations2.d
+++ b/usr/src/cmd/dtrace/test/tst/common/speculation/err.BufSizeVariations2.d
@@ -24,7 +24,9 @@
* Use is subject to license terms.
*/
-#pragma ident "%Z%%M% %I% %E% SMI"
+/*
+ * Copyright (c) 2012 by Delphix. All rights reserved.
+ */
/*
* ASSERTION:
diff --git a/usr/src/cmd/dtrace/test/tst/common/trace/err.D_PROTO_LEN.bad.d b/usr/src/cmd/dtrace/test/tst/common/trace/err.D_PROTO_LEN.bad.d
index a1ec95ccb4..68c11950b5 100644
--- a/usr/src/cmd/dtrace/test/tst/common/trace/err.D_PROTO_LEN.bad.d
+++ b/usr/src/cmd/dtrace/test/tst/common/trace/err.D_PROTO_LEN.bad.d
@@ -24,8 +24,9 @@
* Use is subject to license terms.
*/
-#pragma ident "%Z%%M% %I% %E% SMI"
-
+/*
+ * Copyright (c) 2012 by Delphix. All rights reserved.
+ */
/*
* ASSERTION:
@@ -39,3 +40,8 @@ BEGIN
trace();
}
+
+BEGIN
+{
+ exit(0);
+}
diff --git a/usr/src/cmd/dtrace/test/tst/common/trace/err.D_TRACE_AGG.bad.d b/usr/src/cmd/dtrace/test/tst/common/trace/err.D_TRACE_AGG.bad.d
new file mode 100644
index 0000000000..b29b9f1799
--- /dev/null
+++ b/usr/src/cmd/dtrace/test/tst/common/trace/err.D_TRACE_AGG.bad.d
@@ -0,0 +1,29 @@
+/*
+ * 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) 2012 by Delphix. All rights reserved.
+ */
+
+BEGIN
+{
+ @ = count();
+ trace(@);
+}
+
+BEGIN
+{
+ exit(0);
+}
diff --git a/usr/src/cmd/dtrace/test/tst/common/trace/err.D_TRACE_VOID.bad.d b/usr/src/cmd/dtrace/test/tst/common/trace/err.D_TRACE_VOID.bad.d
index eb9f194a73..ed044b2236 100644
--- a/usr/src/cmd/dtrace/test/tst/common/trace/err.D_TRACE_VOID.bad.d
+++ b/usr/src/cmd/dtrace/test/tst/common/trace/err.D_TRACE_VOID.bad.d
@@ -24,7 +24,9 @@
* Use is subject to license terms.
*/
-#pragma ident "%Z%%M% %I% %E% SMI"
+/*
+ * Copyright (c) 2012 by Delphix. All rights reserved.
+ */
/*
* ASSERTION:
@@ -37,3 +39,8 @@ BEGIN
{
trace((void)`kmem_flags);
}
+
+BEGIN
+{
+ exit(0);
+}
diff --git a/usr/src/cmd/dtrace/test/tst/common/types/tst.const.d b/usr/src/cmd/dtrace/test/tst/common/types/tst.const.d
new file mode 100644
index 0000000000..dae3d9041e
--- /dev/null
+++ b/usr/src/cmd/dtrace/test/tst/common/types/tst.const.d
@@ -0,0 +1,29 @@
+/*
+ * 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) 2012 by Delphix. All rights reserved.
+ */
+
+/*
+ * Make sure we can scope types with modifiers.
+ */
+
+BEGIN
+{
+ trace((D`int *)0);
+ trace((const D`int *)0);
+ exit(0);
+}
diff --git a/usr/src/cmd/dumpadm/dconf.c b/usr/src/cmd/dumpadm/dconf.c
index 488b802462..81b0db25c1 100644
--- a/usr/src/cmd/dumpadm/dconf.c
+++ b/usr/src/cmd/dumpadm/dconf.c
@@ -70,6 +70,7 @@ static const char DC_STR_OFF[] = "off"; /* Off string */
static const char DC_STR_YES[] = "yes"; /* Enable on string */
static const char DC_STR_NO[] = "no"; /* Enable off string */
static const char DC_STR_SWAP[] = "swap"; /* Default dump device */
+static const char DC_STR_NONE[] = "none";
/* The pages included in the dump */
static const char DC_STR_KERNEL[] = "kernel"; /* Kernel only */
@@ -367,7 +368,7 @@ dconf_dev_ioctl(dumpconf_t *dcp, int cmd)
int
dconf_update(dumpconf_t *dcp, int checkinuse)
{
- int oconf;
+ int oconf;
int error;
char *msg;
@@ -438,6 +439,11 @@ dconf_update(dumpconf_t *dcp, int checkinuse)
}
free(swt);
+ } else if (strcmp(dcp->dc_device, DC_STR_NONE) == 0) {
+ if (ioctl(dcp->dc_dump_fd, DIOCRMDEV, NULL) == -1) {
+ warn(gettext("failed to remove dump device"));
+ return (-1);
+ }
} else if (dcp->dc_device[0] != '\0') {
/*
* If we're not in forcible update mode, then fail the change
@@ -564,6 +570,11 @@ dconf_str2device(dumpconf_t *dcp, char *buf)
return (0);
}
+ if (strcasecmp(buf, DC_STR_NONE) == 0) {
+ (void) strcpy(dcp->dc_device, DC_STR_NONE);
+ return (0);
+ }
+
if (valid_abspath(buf)) {
(void) strcpy(dcp->dc_device, buf);
return (0);
diff --git a/usr/src/cmd/fs.d/nfs/statd/sm_proc.c b/usr/src/cmd/fs.d/nfs/statd/sm_proc.c
index f9c8d7a66d..492cb9c639 100644
--- a/usr/src/cmd/fs.d/nfs/statd/sm_proc.c
+++ b/usr/src/cmd/fs.d/nfs/statd/sm_proc.c
@@ -23,6 +23,9 @@
* Copyright 2005 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
+/*
+ * Copyright 2013 Nexenta Systems, Inc. All rights reserved.
+ */
/* Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T */
/* All Rights Reserved */
@@ -37,8 +40,6 @@
* contributors.
*/
-#pragma ident "%Z%%M% %I% %E% SMI"
-
#include <stdio.h>
#include <sys/types.h>
#include <stdlib.h>
@@ -729,14 +730,12 @@ thr_send_notice(void *arg)
if (statd_call_lockd(&minfop->id, minfop->state) == -1) {
if (debug && minfop->id.mon_id.mon_name)
- (void) printf(
- "problem with notifying %s failure, give up\n",
- minfop->id.mon_id.mon_name);
+ (void) printf("problem with notifying %s failure, "
+ "give up\n", minfop->id.mon_id.mon_name);
} else {
if (debug)
- (void) printf(
- "send_notice: %s, %d notified.\n",
- minfop->id.mon_id.mon_name, minfop->state);
+ (void) printf("send_notice: %s, %d notified.\n",
+ minfop->id.mon_id.mon_name, minfop->state);
}
free(minfop->id.mon_id.mon_name);
@@ -914,24 +913,22 @@ pr_name_addr(name_addr_entry_t *name_addr)
(void) printf("name-to-address translation table:\n");
for (entry = name_addr; entry != NULL; entry = entry->next) {
(void) printf("\t%s: ",
- (entry->name ? entry->name : "(null)"));
+ (entry->name ? entry->name : "(null)"));
for (addr = entry->addresses; addr; addr = addr->next) {
switch (addr->family) {
- case AF_INET:
- ipv4_addr = *(struct in_addr *)addr->ah.
-n_bytes;
- (void) printf(" %s (fam %d)",
- inet_ntoa(ipv4_addr),
- addr->family);
- break;
- case AF_INET6:
- ipv6_addr = (char *)addr->ah.n_bytes;
- (void) printf(" %s (fam %d)",
- inet_ntop(addr->family,
-ipv6_addr, abuf, sizeof (abuf)), addr->family);
- break;
- default:
- return;
+ case AF_INET:
+ ipv4_addr = *(struct in_addr *)addr->ah.n_bytes;
+ (void) printf(" %s (fam %d)",
+ inet_ntoa(ipv4_addr), addr->family);
+ break;
+ case AF_INET6:
+ ipv6_addr = (char *)addr->ah.n_bytes;
+ (void) printf(" %s (fam %d)",
+ inet_ntop(addr->family, ipv6_addr, abuf,
+ sizeof (abuf)), addr->family);
+ break;
+ default:
+ return;
}
}
printf("\n");
@@ -939,14 +936,13 @@ ipv6_addr, abuf, sizeof (abuf)), addr->family);
}
/*
- * Statd has trouble dealing with hostname aliases because two
- * different aliases for the same machine don't match each other
- * when using strcmp. To deal with this, the hostnames must be
- * translated into some sort of universal identifier. These
- * identifiers can be compared. Universal network addresses are
- * currently used for this identifier because it is general and
- * easy to do. Other schemes are possible and this routine
- * could be converted if required.
+ * First, try to compare the hostnames as strings. If the hostnames does not
+ * match we might deal with the hostname aliases. In this case two different
+ * aliases for the same machine don't match each other when using strcmp. To
+ * deal with this, the hostnames must be translated into some sort of universal
+ * identifier. These identifiers can be compared. Universal network addresses
+ * are currently used for this identifier because it is general and easy to do.
+ * Other schemes are possible and this routine could be converted if required.
*
* If it can't find an address for some reason, 0 is returned.
*/
@@ -957,6 +953,11 @@ hostname_eq(char *host1, char *host2)
char *sysid2;
int rv;
+ /* Compare hostnames as strings */
+ if (host1 != NULL && host2 != NULL && strcmp(host1, host2) == 0)
+ return (1);
+
+ /* Try harder if hostnames do not match */
sysid1 = get_system_id(host1);
sysid2 = get_system_id(host2);
if ((sysid1 == NULL) || (sysid2 == NULL))
@@ -1003,7 +1004,7 @@ get_system_id(char *hostname)
}
while ((ncp = getnetconfig(hp)) != (struct netconfig *)NULL) {
if ((strcmp(ncp->nc_protofmly, NC_INET) == 0) ||
- (strcmp(ncp->nc_protofmly, NC_INET6) == 0)) {
+ (strcmp(ncp->nc_protofmly, NC_INET6) == 0)) {
addrs = NULL;
rv = netdir_getbyname(ncp, &service, &addrs);
if (rv != 0) {
@@ -1065,7 +1066,7 @@ merge_hosts(void)
for (n = lifc->lifc_len / sizeof (struct lifreq); n > 0; n--, lifrp++) {
(void) strncpy(lifr.lifr_name, lifrp->lifr_name,
- sizeof (lifr.lifr_name));
+ sizeof (lifr.lifr_name));
af = lifrp->lifr_addr.ss_family;
sock = socket(af, SOCK_DGRAM, 0);
@@ -1077,7 +1078,7 @@ merge_hosts(void)
/* If it's the loopback interface, ignore */
if (ioctl(sock, SIOCGLIFFLAGS, (caddr_t)&lifr) < 0) {
syslog(LOG_ERR,
- "statd: SIOCGLIFFLAGS failed, error: %m\n");
+ "statd: SIOCGLIFFLAGS failed, error: %m\n");
goto finish;
}
if (lifr.lifr_flags & IFF_LOOPBACK)
@@ -1085,7 +1086,7 @@ merge_hosts(void)
if (ioctl(sock, SIOCGLIFADDR, (caddr_t)&lifr) < 0) {
syslog(LOG_ERR,
- "statd: SIOCGLIFADDR failed, error: %m\n");
+ "statd: SIOCGLIFADDR failed, error: %m\n");
goto finish;
}
sa = (struct sockaddr_storage *)&(lifr.lifr_addr);
@@ -1216,7 +1217,7 @@ str_cmp_unqual_hostname(char *rawname1, char *rawname2)
if (debug) {
(void) printf("str_cmp_unqual: rawname1= %s, rawname2= %s\n",
- rawname1, rawname2);
+ rawname1, rawname2);
}
unq_len1 = strcspn(rawname1, ".");
@@ -1224,12 +1225,12 @@ str_cmp_unqual_hostname(char *rawname1, char *rawname2)
domain = strchr(rawname1, '.');
if (domain != NULL) {
if ((strncmp(rawname1, SM_ADDR_IPV4, unq_len1) == 0) ||
- (strncmp(rawname1, SM_ADDR_IPV6, unq_len1) == 0))
+ (strncmp(rawname1, SM_ADDR_IPV6, unq_len1) == 0))
return (1);
}
if ((unq_len1 == unq_len2) &&
- (strncmp(rawname1, rawname2, unq_len1) == 0)) {
+ (strncmp(rawname1, rawname2, unq_len1) == 0)) {
return (0);
}
@@ -1252,7 +1253,7 @@ str_cmp_address_specifier(char *specifier1, char *specifier2)
if (debug) {
(void) printf("str_cmp_addr: specifier1= %s, specifier2= %s\n",
- specifier1, specifier2);
+ specifier1, specifier2);
}
/*
@@ -1293,8 +1294,8 @@ str_cmp_address_specifier(char *specifier1, char *specifier2)
++rawaddr2;
if (inet_pton(af1, rawaddr1, dst1) == 1 &&
- inet_pton(af2, rawaddr1, dst2) == 1 &&
- memcmp(dst1, dst2, len) == 0) {
+ inet_pton(af2, rawaddr1, dst2) == 1 &&
+ memcmp(dst1, dst2, len) == 0) {
return (0);
}
}
diff --git a/usr/src/cmd/fs.d/smbclnt/mount/mount.c b/usr/src/cmd/fs.d/smbclnt/mount/mount.c
index afc4b3c4b0..d8a5a9853e 100644
--- a/usr/src/cmd/fs.d/smbclnt/mount/mount.c
+++ b/usr/src/cmd/fs.d/smbclnt/mount/mount.c
@@ -36,7 +36,7 @@
* Copyright 2010 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*
- * Copyright 2011 Nexenta Systems, Inc. All rights reserved.
+ * Copyright 2012 Nexenta Systems, Inc. All rights reserved.
*/
#include <stdio.h>
@@ -162,6 +162,7 @@ struct mnttab mnt;
* to an "ro" by option processing.
*/
char optbuf[MAX_MNTOPT_STR] = "rw";
+char special[MAXPATHLEN];
int
main(int argc, char *argv[])
@@ -298,7 +299,10 @@ main(int argc, char *argv[])
if (optind + 2 != argc)
usage();
- mnt.mnt_special = argv[optind];
+ (void) snprintf(special, sizeof (special), "//%s/%s",
+ ctx->ct_fullserver, ctx->ct_origshare);
+
+ mnt.mnt_special = special;
mnt.mnt_mountp = argv[optind+1];
if ((realpath(argv[optind+1], mount_point) == NULL) ||
diff --git a/usr/src/cmd/fs.d/smbclnt/smbiod/smbiod.c b/usr/src/cmd/fs.d/smbclnt/smbiod/smbiod.c
index 5296cb2be9..32fda8d5fb 100644
--- a/usr/src/cmd/fs.d/smbclnt/smbiod/smbiod.c
+++ b/usr/src/cmd/fs.d/smbclnt/smbiod/smbiod.c
@@ -21,6 +21,7 @@
/*
* Copyright (c) 2009, 2010, Oracle and/or its affiliates. All rights reserved.
+ * Copyright 2012 Nexenta Systems, Inc. All rights reserved.
*/
/*
@@ -281,24 +282,36 @@ iod_newvc(smb_iod_ssn_t *clnt_ssn)
bcopy(clnt_ssn, &ctx->ct_iod_ssn, sizeof (ctx->ct_iod_ssn));
/*
- * Do the initial connection setup here, so we can
- * report the outcome to the door client.
- */
- err = smb_iod_connect(ctx);
- if (err != 0)
- goto out;
-
- /*
- * Create the driver session now, so we don't
- * race with the door client findvc call.
+ * Create the driver session first, so that any subsequent
+ * requests for the same session will find this one and
+ * wait, the same as when a reconnect is triggered.
+ *
+ * There is still an inherent race here, where two callers
+ * both find no VC in the driver, and both come here trying
+ * to create the VC. In this case, we want the first one
+ * to actually do the VC setup, and the second to proceed
+ * as if the VC had been found in the driver. The second
+ * caller gets an EEXIST error from the ioctl in this case,
+ * which we therefore ignore here so that the caller will
+ * go ahead and look again in the driver for the new VC.
*/
if ((err = smb_ctx_gethandle(ctx)) != 0)
goto out;
if (ioctl(ctx->ct_dev_fd, SMBIOC_SSN_CREATE, &ctx->ct_ssn) < 0) {
err = errno;
+ if (err == EEXIST)
+ err = 0; /* see above */
goto out;
}
+ /*
+ * Do the initial connection setup here, so we can
+ * report the outcome to the door client.
+ */
+ err = smb_iod_connect(ctx);
+ if (err != 0)
+ goto out;
+
/* The rest happens in the iod_work thread. */
err = thr_create(NULL, 0, iod_work, ctx, THR_DETACHED, &tid);
if (err == 0) {
diff --git a/usr/src/cmd/getconf/getconf.c b/usr/src/cmd/getconf/getconf.c
index a7a8709d87..bf5ac5437c 100644
--- a/usr/src/cmd/getconf/getconf.c
+++ b/usr/src/cmd/getconf/getconf.c
@@ -747,6 +747,12 @@ static struct sctab {
_SC_V6_LPBIG_OFFBIG, "_V6_LPBIG_OFFBIG", SYSCONF, NOFLAGS,
_SC_V6_LPBIG_OFFBIG, "_POSIX_V6_LPBIG_OFFBIG", SYSCONF, NOFLAGS,
_SC_V6_LPBIG_OFFBIG, "POSIX_V6_LPBIG_OFFBIG", SYSCONF, NOFLAGS,
+/*
+ * System V Interface Definition
+ */
+ _SC_NPROCESSORS_CONF, "NPROCESSORS_CONF", SYSCONF, NOFLAGS,
+ _SC_NPROCESSORS_MAX, "NPROCESSORS_MAX", SYSCONF, NOFLAGS,
+ _SC_NPROCESSORS_ONLN, "NPROCESSORS_ONLN", SYSCONF, NOFLAGS,
0, NULL, 0, 0 /* end of table */
};
diff --git a/usr/src/cmd/kstat/kstat.pl b/usr/src/cmd/kstat/kstat.pl
deleted file mode 100644
index 44eaf85e1d..0000000000
--- a/usr/src/cmd/kstat/kstat.pl
+++ /dev/null
@@ -1,245 +0,0 @@
-#!/usr/perl5/bin/perl
-#
-# CDDL HEADER START
-#
-# The contents of this file are subject to the terms of the
-# Common Development and Distribution License (the "License").
-# You may not use this file except in compliance with the License.
-#
-# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
-# See the License for the specific language governing permissions
-# and limitations under the License.
-#
-# When distributing Covered Code, include this CDDL HEADER in each
-# file and include the License file at usr/src/OPENSOLARIS.LICENSE.
-# If applicable, add the following below this CDDL HEADER, with the
-# fields enclosed by brackets "[]" replaced with your own identifying
-# information: Portions Copyright [yyyy] [name of copyright owner]
-#
-# CDDL HEADER END
-#
-#
-#
-# Copyright 2009 Sun Microsystems, Inc. All rights reserved.
-# Use is subject to license terms.
-#
-
-require 5.8.4;
-use strict;
-use warnings;
-use locale;
-use Getopt::Std;
-use POSIX qw(locale_h strftime);
-use I18N::Langinfo qw(langinfo D_T_FMT);
-use File::Basename;
-use Sun::Solaris::Utils qw(textdomain gettext gmatch);
-use Sun::Solaris::Kstat;
-
-#
-# Print an usage message and exit
-#
-
-sub usage(@)
-{
- my (@msg) = @_;
- print STDERR basename($0), ": @msg\n" if (@msg);
- print STDERR gettext(
- "Usage:\n" .
- "kstat [ -qlp ] [ -T d|u ] [ -c class ]\n" .
- " [ -m module ] [ -i instance ] [ -n name ] [ -s statistic ]\n" .
- " [ interval [ count ] ]\n" .
- "kstat [ -qlp ] [ -T d|u ] [ -c class ]\n" .
- " [ module:instance:name:statistic ... ]\n" .
- " [ interval [ count ] ]\n"
- );
- exit(2);
-}
-
-#
-# Print a fatal error message and exit
-#
-
-sub error(@)
-{
- my (@msg) = @_;
- print STDERR basename($0), ": @msg\n" if (@msg);
- exit(1);
-}
-
-#
-# Generate an anonymous sub that can be used to filter the kstats we will
-# display. The generated sub will take one parameter, the string to match
-# against. There are three types of input catered for:
-# 1) Empty string. The returned sub will match anything
-# 2) String surrounded by '/' characters. This will be interpreted as a
-# perl RE. If the RE is syntactically incorrect, an error will be
-# reported.
-# 3) Any other string. The returned sub will use gmatch(3GEN) to match
-# against the passed string
-#
-
-sub gen_sub($)
-{
- my ($pat) = @_;
-
- # Anything undefined or empty will always match
- if (! defined($pat) || $pat eq '') {
- return (sub { 1; });
-
- # Anything surrounded by '/' is a perl RE
- } elsif ($pat =~ m!^/[^/]*/$!) {
- my $sub;
- if (! ($sub = eval "sub { return(\$_[0] =~ $pat); }" )) {
- $@ =~ s/\s+at\s+.*\n$//;
- usage($@);
- }
- return ($sub);
-
- # Otherwise default to gmatch
- } else {
- return (sub { return(gmatch($_[0], $pat)); });
- }
-}
-
-#
-# Main routine of the script
-#
-
-# Set message locale
-setlocale(LC_ALL, "");
-textdomain(TEXT_DOMAIN);
-
-# Process command options
-my (%opt, @matcher);
-getopts('?qlpT:m:i:n:s:c:', \%opt) || usage();
-usage() if exists($opt{'?'});
-
-# Validate -q and -l flags
-my $quiet = exists($opt{q}) ? 1 : 0;
-my $list = exists($opt{l}) ? 1 : 0;
-my $parseable = exists($opt{'p'}) || $list ? 1 : 0;
-usage(gettext("-q and -l are mutually exclusive")) if ($quiet && $list);
-
-# Get interval & count if specified
-my ($interval, $count) = (0, 1);
-if (@ARGV >= 2 && $ARGV[-2] =~ /^\d+$/ && $ARGV[-1] =~ /^\d+$/) {
- $count = pop(@ARGV);
- $interval = pop(@ARGV);
- usage(gettext("Interval must be an integer >= 1")) if ($interval < 1);
- usage(gettext("Count must be an integer >= 1")) if ($count < 1);
-} elsif (@ARGV >= 1 && $ARGV[-1] =~ /^\d+$/) {
- $interval = pop(@ARGV);
- $count = -1;
- usage(gettext("Interval must be an integer >= 1")) if ($interval < 1);
-}
-
-# Get timestamp flag
-my $timestamp;
-my $timefmt;
-if ($timestamp = $opt{T}) {
- if ($timestamp eq "d") {
- $timefmt = langinfo(D_T_FMT) . "\n";
- $timestamp = sub { print(strftime($timefmt, localtime())); };
- } elsif ($timestamp eq "u") {
- $timestamp = sub { print(time(), "\n"); };
- } else {
- usage(gettext("Invalid timestamp specifier"), $timestamp);
- }
-}
-
-# Deal with -[mins] flags
-if (grep(/[mins]/, keys(%opt))) {
- usage(gettext("module:instance:name:statistic and " .
- "-m -i -n -s are mutually exclusive")) if (@ARGV);
- push(@ARGV, join(":", map(exists($opt{$_}) ? $opt{$_} : "",
- qw(m i n s))));
-}
-
-# Deal with class, if specified
-my $class = gen_sub(exists($opt{c}) ? $opt{c} : '');
-
-# If no selectors have been defined, add a dummy one to match everything
-push(@ARGV, ":::") if (! @ARGV);
-
-# Convert each remaining option into four anonymous subs
-foreach my $p (@ARGV) {
- push(@matcher, [ map(gen_sub($_), (split(/:/, $p, 4))[0..3]) ]);
-}
-
-# Loop, printing the selected kstats as many times and as often as required
-my $ks = Sun::Solaris::Kstat->new(strip_strings => 1);
-my $matched = 0;
-
-# Format strings for displaying data
-my $fmt1 = "module: %-30.30s instance: %-6d\n";
-my $fmt2 = "name: %-30.30s class: %-.30s\n";
-my $fmt3 = "\t%-30s %s\n";
-
-while ($count == -1 || $count-- > 0) {
- &$timestamp() if ($timestamp);
-
- foreach my $m (@matcher) {
- my ($module, $instance, $name, $statistic) = @$m;
-
- foreach my $m (sort(grep(&$module($_), keys(%$ks)))) {
- my $mh = $ks->{$m};
-
- foreach my $i (sort({ $a <=> $b }
- grep(&$instance($_), keys(%$mh)))) {
- my $ih = $mh->{$i};
-
- foreach my $n (sort(grep(&$name($_),
- keys(%$ih)))) {
- my $nh = $ih->{$n};
-
- # Prune any not in the required class
- next if (! &$class($nh->{class}));
-
- if ($quiet) {
- $matched = grep(&$statistic($_),
- keys(%$nh)) ? 1 : 0;
-
- } elsif ($parseable) {
- foreach my $s
- (sort(grep(&$statistic($_),
- keys(%$nh)))) {
- print("$m:$i:$n:$s");
- print("\t$nh->{$s}")
- if (! $list);
- print("\n");
- $matched = 1;
- }
-
- # human-readable
- } else {
- if (my @stats =
- sort(grep(&$statistic($_),
- keys(%$nh)))) {
- printf($fmt1, $m, $i);
- printf($fmt2, $n,
- $nh->{class});
- foreach my $s
- (grep($_ ne "class",
- @stats)) {
- printf($fmt3,
- $s, $nh->{$s});
- }
- print("\n");
- $matched = 1;
- }
- }
- }
- }
- }
- }
- # Toggle line buffering off/on to flush output
- $| = 1; $| = 0;
-
- if ($interval && $count) {
- sleep($interval);
- $ks->update();
- print("\n");
- }
-}
-exit($matched ? 0 : 1);
diff --git a/usr/src/cmd/mdb/common/mdb/mdb.c b/usr/src/cmd/mdb/common/mdb/mdb.c
index 3ab14e08f0..6f2df6f533 100644
--- a/usr/src/cmd/mdb/common/mdb/mdb.c
+++ b/usr/src/cmd/mdb/common/mdb/mdb.c
@@ -1401,7 +1401,8 @@ mdb_get_module(void)
return (NULL);
if (mdb.m_frame->f_wcbs && mdb.m_frame->f_wcbs->w_walker &&
- mdb.m_frame->f_wcbs->w_walker->iwlk_modp)
+ mdb.m_frame->f_wcbs->w_walker->iwlk_modp &&
+ !mdb.m_frame->f_cbactive)
return (mdb.m_frame->f_wcbs->w_walker->iwlk_modp);
if (mdb.m_frame->f_cp && mdb.m_frame->f_cp->c_dcmd)
diff --git a/usr/src/cmd/mdb/common/mdb/mdb_cmds.c b/usr/src/cmd/mdb/common/mdb/mdb_cmds.c
index 585097dbc4..2818a35a70 100644
--- a/usr/src/cmd/mdb/common/mdb/mdb_cmds.c
+++ b/usr/src/cmd/mdb/common/mdb/mdb_cmds.c
@@ -2078,7 +2078,7 @@ cmd_dis(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv)
static int
walk_step(uintptr_t addr, const void *data, void *private)
{
- mdb_printf("%lr\n", addr);
+ mdb_printf("%#lr\n", addr);
return (WALK_NEXT);
}
diff --git a/usr/src/cmd/mdb/common/mdb/mdb_ctf.c b/usr/src/cmd/mdb/common/mdb/mdb_ctf.c
index b319ed31ec..b490ca9e2f 100644
--- a/usr/src/cmd/mdb/common/mdb/mdb_ctf.c
+++ b/usr/src/cmd/mdb/common/mdb/mdb_ctf.c
@@ -23,6 +23,7 @@
* Use is subject to license terms.
*/
/*
+ * Copyright (c) 2013 by Delphix. All rights reserved.
* Copyright (c) 2013, Joyent, Inc. All rights reserved.
*/
@@ -872,12 +873,44 @@ mdb_ctf_member_info(mdb_ctf_id_t id, const char *member, ulong_t *offp,
return (0);
}
+/*
+ * Returns offset in _bits_ in *retp.
+ */
int
mdb_ctf_offsetof(mdb_ctf_id_t id, const char *member, ulong_t *retp)
{
return (mdb_ctf_member_info(id, member, retp, NULL));
}
+/*
+ * Returns offset in _bytes_, or -1 on failure.
+ */
+int
+mdb_ctf_offsetof_by_name(const char *type, const char *member)
+{
+ mdb_ctf_id_t id;
+ ulong_t off;
+
+ if (mdb_ctf_lookup_by_name(type, &id) == -1) {
+ mdb_warn("couldn't find type %s", type);
+ return (-1);
+ }
+
+ if (mdb_ctf_offsetof(id, member, &off) == -1) {
+ mdb_warn("couldn't find member %s of type %s", member, type);
+ return (-1);
+ }
+ if (off % 8 != 0) {
+ mdb_warn("member %s of type %s is an unsupported bitfield\n",
+ member, type);
+ return (-1);
+ }
+ off /= 8;
+
+ return (off);
+}
+
+
/*ARGSUSED*/
static int
num_members_cb(const char *name, mdb_ctf_id_t id, ulong_t off, void *data)
@@ -1059,6 +1092,19 @@ done:
return (mbc.mbc_total);
}
+static void
+mdb_ctf_warn(uint_t flags, const char *format, ...)
+{
+ va_list alist;
+
+ if (flags & MDB_CTF_VREAD_QUIET)
+ return;
+
+ va_start(alist, format);
+ vwarn(format, alist);
+ va_end(alist);
+}
+
/*
* Check if two types are structurally the same rather than logically
* the same. That is to say that two types are equal if they have the
@@ -1148,11 +1194,13 @@ type_equals(mdb_ctf_id_t a, mdb_ctf_id_t b)
typedef struct member {
char *m_modbuf;
char *m_tgtbuf;
+ const char *m_tgtname;
mdb_ctf_id_t m_tgtid;
uint_t m_flags;
} member_t;
-static int vread_helper(mdb_ctf_id_t, char *, mdb_ctf_id_t, char *, uint_t);
+static int vread_helper(mdb_ctf_id_t, char *, mdb_ctf_id_t, char *,
+ const char *, uint_t);
static int
member_cb(const char *name, mdb_ctf_id_t modmid, ulong_t modoff, void *data)
@@ -1162,29 +1210,66 @@ member_cb(const char *name, mdb_ctf_id_t modmid, ulong_t modoff, void *data)
mdb_ctf_id_t tgtmid;
char *tgtbuf = mp->m_tgtbuf;
ulong_t tgtoff;
+ char tgtname[128];
+
+ (void) mdb_snprintf(tgtname, sizeof (tgtname),
+ "member %s of type %s", name, mp->m_tgtname);
if (mdb_ctf_member_info(mp->m_tgtid, name, &tgtoff, &tgtmid) != 0) {
- if (mp->m_flags & MDB_CTF_VREAD_IGNORE_ABSENT)
- return (0);
- else
- return (set_errno(EMDB_CTFNOMEMB));
+ mdb_ctf_warn(mp->m_flags,
+ "could not find %s\n", tgtname);
+ return (set_errno(EMDB_CTFNOMEMB));
}
return (vread_helper(modmid, modbuf + modoff / NBBY,
- tgtmid, tgtbuf + tgtoff / NBBY, mp->m_flags));
+ tgtmid, tgtbuf + tgtoff / NBBY, tgtname, mp->m_flags));
}
+typedef struct enum_value {
+ int *ev_modbuf;
+ const char *ev_name;
+} enum_value_t;
+
+static int
+enum_cb(const char *name, int value, void *data)
+{
+ enum_value_t *ev = data;
+
+ if (strcmp(name, ev->ev_name) == 0) {
+ *ev->ev_modbuf = value;
+ return (1);
+ }
+ return (0);
+}
static int
vread_helper(mdb_ctf_id_t modid, char *modbuf,
- mdb_ctf_id_t tgtid, char *tgtbuf, uint_t flags)
+ mdb_ctf_id_t tgtid, char *tgtbuf, const char *tgtname, uint_t flags)
{
size_t modsz, tgtsz;
int modkind, tgtkind;
member_t mbr;
+ enum_value_t ev;
int ret;
mdb_ctf_arinfo_t tar, mar;
int i;
+ char typename[128];
+ char mdbtypename[128];
+ ctf_encoding_t tgt_encoding, mod_encoding;
+ boolean_t signed_int = B_FALSE;
+
+ if (mdb_ctf_type_name(tgtid, typename, sizeof (typename)) == NULL) {
+ (void) mdb_snprintf(typename, sizeof (typename),
+ "#%ul", mdb_ctf_type_id(tgtid));
+ }
+ if (mdb_ctf_type_name(modid,
+ mdbtypename, sizeof (mdbtypename)) == NULL) {
+ (void) mdb_snprintf(mdbtypename, sizeof (mdbtypename),
+ "#%ul", mdb_ctf_type_id(modid));
+ }
+
+ if (tgtname == NULL)
+ tgtname = "";
/*
* Resolve the types to their canonical form.
@@ -1192,38 +1277,113 @@ vread_helper(mdb_ctf_id_t modid, char *modbuf,
(void) mdb_ctf_type_resolve(modid, &modid);
(void) mdb_ctf_type_resolve(tgtid, &tgtid);
- if ((modkind = mdb_ctf_type_kind(modid)) == -1)
+ if ((modkind = mdb_ctf_type_kind(modid)) == -1) {
+ mdb_ctf_warn(flags,
+ "couldn't determine type kind of mdb module type %s\n",
+ mdbtypename);
return (-1); /* errno is set for us */
- if ((tgtkind = mdb_ctf_type_kind(tgtid)) == -1)
+ }
+ if ((tgtkind = mdb_ctf_type_kind(tgtid)) == -1) {
+ mdb_ctf_warn(flags,
+ "couldn't determine type kind of %s\n", typename);
return (-1); /* errno is set for us */
+ }
- if (tgtkind != modkind)
+ if (tgtkind != modkind) {
+ mdb_ctf_warn(flags, "unexpected kind for type %s (%s)\n",
+ typename, tgtname);
return (set_errno(EMDB_INCOMPAT));
+ }
+
+ if ((modsz = mdb_ctf_type_size(modid)) == -1UL) {
+ mdb_ctf_warn(flags, "couldn't determine type size of "
+ "mdb module type %s\n", mdbtypename);
+ return (-1); /* errno is set for us */
+ }
+ if ((tgtsz = mdb_ctf_type_size(tgtid)) == -1UL) {
+ mdb_ctf_warn(flags, "couldn't determine size of %s (%s)\n",
+ typename, tgtname);
+ return (-1); /* errno is set for us */
+ }
switch (modkind) {
case CTF_K_INTEGER:
case CTF_K_FLOAT:
- case CTF_K_POINTER:
- if ((modsz = mdb_ctf_type_size(modid)) == -1UL)
+ /*
+ * Must determine if the target and module types have the same
+ * encoding before we can copy them.
+ */
+ if (mdb_ctf_type_encoding(tgtid, &tgt_encoding) != 0) {
+ mdb_ctf_warn(flags,
+ "couldn't determine encoding of type %s (%s)\n",
+ typename, tgtname);
return (-1); /* errno is set for us */
-
- if ((tgtsz = mdb_ctf_type_size(tgtid)) == -1UL)
+ }
+ if (mdb_ctf_type_encoding(modid, &mod_encoding) != 0) {
+ mdb_ctf_warn(flags, "couldn't determine encoding of "
+ "mdb module type %s\n", mdbtypename);
return (-1); /* errno is set for us */
+ }
+ if (modkind == CTF_K_INTEGER) {
+ if ((tgt_encoding.cte_format & CTF_INT_SIGNED) !=
+ (mod_encoding.cte_format & CTF_INT_SIGNED)) {
+ mdb_ctf_warn(flags,
+ "signedness mismatch between type "
+ "%s (%s) and mdb module type %s\n",
+ typename, tgtname, mdbtypename);
+ return (set_errno(EMDB_INCOMPAT));
+ }
+ signed_int =
+ ((tgt_encoding.cte_format & CTF_INT_SIGNED) != 0);
+ } else if (tgt_encoding.cte_format != mod_encoding.cte_format) {
+ mdb_ctf_warn(flags,
+ "encoding mismatch (%#x != %#x) between type "
+ "%s (%s) and mdb module type %s\n",
+ tgt_encoding.cte_format, mod_encoding.cte_format,
+ typename, tgtname, mdbtypename);
+ return (set_errno(EMDB_INCOMPAT));
+ }
+ /* FALLTHROUGH */
+ case CTF_K_POINTER:
/*
* If the sizes don't match we need to be tricky to make
* sure that the caller gets the correct data.
*/
if (modsz < tgtsz) {
- if (!(flags & MDB_CTF_VREAD_IGNORE_GROW))
- return (set_errno(EMDB_INCOMPAT));
+ mdb_ctf_warn(flags, "size of type %s (%s) is too "
+ "large for mdb module type %s\n",
+ typename, tgtname, mdbtypename);
+ return (set_errno(EMDB_INCOMPAT));
+ } else if (modsz > tgtsz) {
+ /* BEGIN CSTYLED */
+ /*
+ * Fill modbuf with 1's for sign extension if target
+ * buf is a signed integer and its value is negative.
+ *
+ * S = sign bit (in most-significant byte)
+ *
+ * BIG ENDIAN DATA
+ * +--------+--------+--------+--------+
+ * |S | | | |
+ * +--------+--------+--------+--------+
+ * 0 1 ... sz-1 sz
+ *
+ * LITTLE ENDIAN DATA
+ * +--------+--------+--------+--------+
+ * | | | |S |
+ * +--------+--------+--------+--------+
+ * 0 1 ... sz-1 sz
+ */
+ /* END CSTYLED */
#ifdef _BIG_ENDIAN
- bcopy(tgtbuf + tgtsz - modsz, modbuf, modsz);
+ if (signed_int && (tgtbuf[0] & 0x80) != 0)
#else
- bcopy(tgtbuf, modbuf, modsz);
+ if (signed_int && (tgtbuf[tgtsz - 1] & 0x80) != 0)
#endif
- } else if (modsz > tgtsz) {
- bzero(modbuf, modsz);
+ (void) memset(modbuf, 0xFF, modsz);
+ else
+ bzero(modbuf, modsz);
#ifdef _BIG_ENDIAN
bcopy(tgtbuf, modbuf + modsz - tgtsz, tgtsz);
#else
@@ -1235,11 +1395,53 @@ vread_helper(mdb_ctf_id_t modid, char *modbuf,
return (0);
+ case CTF_K_ENUM:
+ if (modsz != tgtsz || modsz != sizeof (int)) {
+ mdb_ctf_warn(flags, "unexpected size of type %s (%s)\n",
+ typename, tgtname);
+ return (set_errno(EMDB_INCOMPAT));
+ }
+
+ /*
+ * Default to the same value as in the target.
+ */
+ bcopy(tgtbuf, modbuf, sizeof (int));
+
+ /* LINTED */
+ i = *(int *)tgtbuf;
+
+ /* LINTED */
+ ev.ev_modbuf = (int *)modbuf;
+ ev.ev_name = mdb_ctf_enum_name(tgtid, i);
+ if (ev.ev_name == NULL) {
+ mdb_ctf_warn(flags,
+ "unexpected value %u of enum type %s (%s)\n",
+ i, typename, tgtname);
+ return (set_errno(EMDB_INCOMPAT));
+ }
+
+ ret = mdb_ctf_enum_iter(modid, enum_cb, &ev);
+ if (ret == 0) {
+ /* value not found */
+ mdb_ctf_warn(flags,
+ "unexpected value %s (%u) of enum type %s (%s)\n",
+ ev.ev_name, i, typename, tgtname);
+ return (set_errno(EMDB_INCOMPAT));
+ } else if (ret == 1) {
+ /* value found */
+ return (0);
+ } else if (ret == -1) {
+ mdb_ctf_warn(flags, "could not iterate enum %s (%s)\n",
+ typename, tgtname);
+ }
+ return (ret);
+
case CTF_K_STRUCT:
mbr.m_modbuf = modbuf;
mbr.m_tgtbuf = tgtbuf;
mbr.m_tgtid = tgtid;
mbr.m_flags = flags;
+ mbr.m_tgtname = typename;
return (mdb_ctf_member_iter(modid, member_cb, &mbr));
@@ -1248,21 +1450,18 @@ vread_helper(mdb_ctf_id_t modid, char *modbuf,
/*
* Unions are a little tricky. The only time it's truly
* safe to read in a union is if no part of the union or
- * any of its component types have changed. We allow the
- * consumer to ignore unions. The correct use of this
- * feature is to read the containing structure, figure
- * out which component of the union is valid, compute
+ * any of its component types have changed. The correct
+ * use of this feature is to read the containing structure,
+ * figure out which component of the union is valid, compute
* the location of that in the target and then read in
* that part of the structure.
*/
- if (flags & MDB_CTF_VREAD_IGNORE_UNIONS)
- return (0);
- if (!type_equals(modid, tgtid))
+ if (!type_equals(modid, tgtid)) {
+ mdb_ctf_warn(flags, "inexact match for union %s (%s)\n",
+ typename, tgtname);
return (set_errno(EMDB_INCOMPAT));
-
- modsz = mdb_ctf_type_size(modid);
- tgtsz = mdb_ctf_type_size(tgtid);
+ }
ASSERT(modsz == tgtsz);
@@ -1271,23 +1470,42 @@ vread_helper(mdb_ctf_id_t modid, char *modbuf,
return (0);
case CTF_K_ARRAY:
- if (mdb_ctf_array_info(tgtid, &tar) != 0)
+ if (mdb_ctf_array_info(tgtid, &tar) != 0) {
+ mdb_ctf_warn(flags,
+ "couldn't get array info for %s (%s)\n",
+ typename, tgtname);
return (-1); /* errno is set for us */
- if (mdb_ctf_array_info(modid, &mar) != 0)
+ }
+ if (mdb_ctf_array_info(modid, &mar) != 0) {
+ mdb_ctf_warn(flags,
+ "couldn't get array info for mdb module type %s\n",
+ mdbtypename);
return (-1); /* errno is set for us */
+ }
- if (tar.mta_nelems != mar.mta_nelems)
+ if (tar.mta_nelems != mar.mta_nelems) {
+ mdb_ctf_warn(flags,
+ "unexpected array size (%u) for type %s (%s)\n",
+ tar.mta_nelems, typename, tgtname);
return (set_errno(EMDB_INCOMPAT));
+ }
- if ((modsz = mdb_ctf_type_size(mar.mta_contents)) == -1UL)
+ if ((modsz = mdb_ctf_type_size(mar.mta_contents)) == -1UL) {
+ mdb_ctf_warn(flags, "couldn't determine type size of "
+ "mdb module type %s\n", mdbtypename);
return (-1); /* errno is set for us */
-
- if ((tgtsz = mdb_ctf_type_size(tar.mta_contents)) == -1UL)
+ }
+ if ((tgtsz = mdb_ctf_type_size(tar.mta_contents)) == -1UL) {
+ mdb_ctf_warn(flags,
+ "couldn't determine size of %s (%s)\n",
+ typename, tgtname);
return (-1); /* errno is set for us */
+ }
for (i = 0; i < tar.mta_nelems; i++) {
ret = vread_helper(mar.mta_contents, modbuf + i * modsz,
- tar.mta_contents, tgtbuf + i * tgtsz, flags);
+ tar.mta_contents, tgtbuf + i * tgtsz,
+ tgtname, flags);
if (ret != 0)
return (ret);
@@ -1296,12 +1514,67 @@ vread_helper(mdb_ctf_id_t modid, char *modbuf,
return (0);
}
+ mdb_ctf_warn(flags, "unsupported kind %d for type %s (%s)\n",
+ modkind, typename, tgtname);
return (set_errno(EMDB_INCOMPAT));
}
-
+/*
+ * Like mdb_vread(), mdb_ctf_vread() is used to read from the target's
+ * virtual address space. However, mdb_ctf_vread() can be used to safely
+ * read a complex type (e.g. a struct) from the target, even if MDB was compiled
+ * against a different definition of that type (e.g. when debugging a crash
+ * dump from an older release).
+ *
+ * Callers can achieve this by defining their own type which corresponds to the
+ * type in the target, but contains only the members that the caller requires.
+ * Using the CTF type information embedded in the target, mdb_ctf_vread will
+ * find the required members in the target and fill in the caller's structure.
+ * The members are located by name, and their types are verified to be
+ * compatible.
+ *
+ * By convention, the caller will declare a type with the name "mdb_<type>",
+ * where <type> is the name of the type in the target (e.g. mdb_zio_t). This
+ * type will contain the members that the caller is interested in. For example:
+ *
+ * typedef struct mdb_zio {
+ * enum zio_type io_type;
+ * void *io_waiter;
+ * struct {
+ * struct {
+ * void *list_next;
+ * } list_head;
+ * } io_parent_list;
+ * int io_error;
+ * } mdb_zio_t;
+ *
+ * mdb_zio_t zio;
+ * error = mdb_ctf_vread(&zio, "zio_t", "mdb_zio_t", zio_target_addr, 0);
+ *
+ * If a given MDB module has different dcmds or walkers that need to read
+ * different members from the same struct, then different "mdb_" types
+ * should be declared for each caller. By convention, these types should
+ * be named "mdb_<dcmd or walker>_<type>", e.g. mdb_findstack_kthread_t
+ * for ::findstack. If the MDB module is compiled from several source files,
+ * one must be especially careful to not define different types with the
+ * same name in different source files, because the compiler can not detect
+ * this error.
+ *
+ * Enums will also be translated by name, so the mdb module will receive
+ * the enum value it expects even if the target has renumbered the enum.
+ * Warning: it will therefore only work with enums are only used to store
+ * legitimate enum values (not several values or-ed together).
+ *
+ * By default, if mdb_ctf_vread() can not find any members or enum values,
+ * it will print a descriptive message (with mdb_warn()) and fail.
+ * Passing MDB_CTF_VREAD_QUIET in 'flags' will suppress the warning message.
+ * Additional flags can be used to ignore specific types of translation
+ * failure, but should be used with caution, because they will silently leave
+ * the caller's buffer uninitialized.
+ */
int
-mdb_ctf_vread(void *modbuf, const char *typename, uintptr_t addr, uint_t flags)
+mdb_ctf_vread(void *modbuf, const char *target_typename,
+ const char *mdb_typename, uintptr_t addr, uint_t flags)
{
ctf_file_t *mfp;
ctf_id_t mid;
@@ -1311,44 +1584,67 @@ mdb_ctf_vread(void *modbuf, const char *typename, uintptr_t addr, uint_t flags)
mdb_ctf_id_t modid;
mdb_module_t *mod;
- if ((mod = mdb_get_module()) == NULL || (mfp = mod->mod_ctfp) == NULL)
+ if ((mod = mdb_get_module()) == NULL || (mfp = mod->mod_ctfp) == NULL) {
+ mdb_ctf_warn(flags, "no ctf data found for mdb module %s\n",
+ mod->mod_name);
return (set_errno(EMDB_NOCTF));
+ }
- if ((mid = ctf_lookup_by_name(mfp, typename)) == CTF_ERR) {
- mdb_dprintf(MDB_DBG_CTF, "couldn't find module's ctf data\n");
+ if ((mid = ctf_lookup_by_name(mfp, mdb_typename)) == CTF_ERR) {
+ mdb_ctf_warn(flags, "couldn't find ctf data for "
+ "type %s in mdb module %s\n",
+ mdb_typename, mod->mod_name);
return (set_errno(ctf_to_errno(ctf_errno(mfp))));
}
set_ctf_id(&modid, mfp, mid);
- if (mdb_ctf_lookup_by_name(typename, &tgtid) != 0) {
- mdb_dprintf(MDB_DBG_CTF, "couldn't find target's ctf data\n");
+ if (mdb_ctf_lookup_by_name(target_typename, &tgtid) != 0) {
+ mdb_ctf_warn(flags,
+ "couldn't find type %s in target's ctf data\n",
+ target_typename);
return (set_errno(EMDB_NOCTF));
}
/*
* Read the data out of the target's address space.
*/
- if ((size = mdb_ctf_type_size(tgtid)) == -1UL)
+ if ((size = mdb_ctf_type_size(tgtid)) == -1UL) {
+ mdb_ctf_warn(flags, "couldn't determine size of type %s\n",
+ target_typename);
return (-1); /* errno is set for us */
+ }
tgtbuf = mdb_alloc(size, UM_SLEEP | UM_GC);
- if (mdb_vread(tgtbuf, size, addr) < 0)
+ if (mdb_vread(tgtbuf, size, addr) < 0) {
+ mdb_ctf_warn(flags, "couldn't read %s from %p\n",
+ target_typename, addr);
return (-1); /* errno is set for us */
+ }
- return (vread_helper(modid, modbuf, tgtid, tgtbuf, flags));
+ return (vread_helper(modid, modbuf, tgtid, tgtbuf, NULL, flags));
}
+/*
+ * Note: mdb_ctf_readsym() doesn't take separate parameters for the name
+ * of the target's type vs the mdb module's type. Use with complicated
+ * types (e.g. structs) may result in unnecessary failure if a member of
+ * the struct has been changed in the target, but is not actually needed
+ * by the mdb module. Use mdb_lookup_by_name() + mdb_ctf_vread() to
+ * avoid this problem.
+ */
int
mdb_ctf_readsym(void *buf, const char *typename, const char *name, uint_t flags)
{
GElf_Sym sym;
- if (mdb_lookup_by_name(name, &sym) != 0)
+ if (mdb_lookup_by_name(name, &sym) != 0) {
+ mdb_ctf_warn(flags, "couldn't find symbol %s\n", name);
return (-1); /* errno is set for us */
+ }
- return (mdb_ctf_vread(buf, typename, sym.st_value, flags));
+ return (mdb_ctf_vread(buf, typename, typename, sym.st_value, flags));
}
ctf_file_t *
diff --git a/usr/src/cmd/mdb/common/mdb/mdb_ctf.h b/usr/src/cmd/mdb/common/mdb/mdb_ctf.h
index 0e6d227f6e..2396145299 100644
--- a/usr/src/cmd/mdb/common/mdb/mdb_ctf.h
+++ b/usr/src/cmd/mdb/common/mdb/mdb_ctf.h
@@ -23,6 +23,7 @@
* Use is subject to license terms.
*/
/*
+ * Copyright (c) 2013 by Delphix. All rights reserved.
* Copyright (c) 2013, Joyent, Inc. All rights reserved.
*/
@@ -134,17 +135,15 @@ extern int mdb_ctf_member_info(mdb_ctf_id_t, const char *,
ulong_t *, mdb_ctf_id_t *);
extern int mdb_ctf_offsetof(mdb_ctf_id_t, const char *, ulong_t *);
extern int mdb_ctf_num_members(mdb_ctf_id_t);
+extern int mdb_ctf_offsetof_by_name(const char *, const char *);
extern ssize_t mdb_ctf_offset_to_name(mdb_ctf_id_t, ulong_t, char *, size_t,
int, mdb_ctf_id_t *, ulong_t *);
-#define MDB_CTF_VREAD_IGNORE_GROW 0x01
-#define MDB_CTF_VREAD_IGNORE_ABSENT 0x02
-#define MDB_CTF_VREAD_IGNORE_UNIONS 0x04
+#define MDB_CTF_VREAD_QUIET 0x100
-#define MDB_CTF_VREAD_IGNORE_ALL 0x07
-
-extern int mdb_ctf_vread(void *, const char *, uintptr_t, uint_t);
+extern int mdb_ctf_vread(void *, const char *, const char *,
+ uintptr_t, uint_t);
extern int mdb_ctf_readsym(void *, const char *, const char *, uint_t);
#ifdef _MDB
diff --git a/usr/src/cmd/mdb/common/mdb/mdb_frame.h b/usr/src/cmd/mdb/common/mdb/mdb_frame.h
index 32ce67ddb9..1a40680f5b 100644
--- a/usr/src/cmd/mdb/common/mdb/mdb_frame.h
+++ b/usr/src/cmd/mdb/common/mdb/mdb_frame.h
@@ -26,8 +26,6 @@
#ifndef _MDB_FRAME_H
#define _MDB_FRAME_H
-#pragma ident "%Z%%M% %I% %E% SMI"
-
#include <mdb/mdb_module.h>
#include <mdb/mdb_addrvec.h>
#include <mdb/mdb_list.h>
@@ -67,6 +65,7 @@ typedef struct mdb_frame {
struct mdb_lex_state *f_lstate; /* Current lex state */
uintmax_t f_dot; /* Value of '.' */
mdb_bool_t pipe; /* frame has pipe context */
+ uint_t f_cbactive; /* true iff a callback is active */
} mdb_frame_t;
#ifdef _MDB
diff --git a/usr/src/cmd/mdb/common/mdb/mdb_modapi.c b/usr/src/cmd/mdb/common/mdb/mdb_modapi.c
index 59c34022c7..a79894e80e 100644
--- a/usr/src/cmd/mdb/common/mdb/mdb_modapi.c
+++ b/usr/src/cmd/mdb/common/mdb/mdb_modapi.c
@@ -510,16 +510,44 @@ done:
return (rval);
}
+typedef struct pwalk_step {
+ mdb_walk_cb_t ps_cb;
+ void *ps_private;
+} pwalk_step_t;
+
+static int
+pwalk_step(uintptr_t addr, const void *data, void *private)
+{
+ pwalk_step_t *psp = private;
+ int ret;
+
+ mdb.m_frame->f_cbactive = B_TRUE;
+ ret = psp->ps_cb(addr, data, psp->ps_private);
+ mdb.m_frame->f_cbactive = B_FALSE;
+
+ return (ret);
+}
+
int
-mdb_pwalk(const char *name, mdb_walk_cb_t func, void *data, uintptr_t addr)
+mdb_pwalk(const char *name, mdb_walk_cb_t func, void *private, uintptr_t addr)
{
mdb_iwalker_t *iwp = mdb_walker_lookup(name);
+ pwalk_step_t p;
if (func == NULL)
return (set_errno(EINVAL));
- if (iwp != NULL)
- return (walk_common(mdb_wcb_create(iwp, func, data, addr)));
+ p.ps_cb = func;
+ p.ps_private = private;
+
+ if (iwp != NULL) {
+ int ret;
+ int cbactive = mdb.m_frame->f_cbactive;
+ mdb.m_frame->f_cbactive = B_FALSE;
+ ret = walk_common(mdb_wcb_create(iwp, pwalk_step, &p, addr));
+ mdb.m_frame->f_cbactive = cbactive;
+ return (ret);
+ }
return (-1); /* errno is set for us */
}
diff --git a/usr/src/cmd/mdb/common/mdb/mdb_print.c b/usr/src/cmd/mdb/common/mdb/mdb_print.c
index 64e35e8a3d..ee996be8cf 100644
--- a/usr/src/cmd/mdb/common/mdb/mdb_print.c
+++ b/usr/src/cmd/mdb/common/mdb/mdb_print.c
@@ -74,6 +74,7 @@ typedef struct printarg {
int pa_nest; /* array nesting depth */
int pa_tab; /* tabstop width */
uint_t pa_maxdepth; /* Limit max depth */
+ uint_t pa_nooutdepth; /* don't print output past this depth */
} printarg_t;
#define PA_SHOWTYPE 0x001 /* print type name */
@@ -698,8 +699,7 @@ setup_vcb(const char *name, uintptr_t addr)
int
cmd_list(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv)
{
- mdb_ctf_id_t id;
- ulong_t offset;
+ int offset;
uintptr_t a, tmp;
int ret;
@@ -732,34 +732,21 @@ cmd_list(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv)
if (ret != 0)
return (ret);
- if (mdb_ctf_lookup_by_name(buf, &id) != 0) {
- mdb_warn("failed to look up type %s", buf);
- return (DCMD_ABORT);
- }
-
argv++;
argc--;
- if (argc < 1 || argv->a_type != MDB_TYPE_STRING)
- return (DCMD_USAGE);
-
member = argv->a_un.a_str;
+ offset = mdb_ctf_offsetof_by_name(buf, member);
+ if (offset == -1)
+ return (DCMD_ABORT);
argv++;
argc--;
- if (mdb_ctf_offsetof(id, member, &offset) != 0) {
- mdb_warn("failed to find member %s of type %s",
- member, buf);
- return (DCMD_ABORT);
- }
-
- if (offset % (sizeof (uintptr_t) * NBBY) != 0) {
+ if (offset % (sizeof (uintptr_t)) != 0) {
mdb_warn("%s is not a word-aligned member\n", member);
return (DCMD_ABORT);
}
-
- offset /= NBBY;
}
/*
@@ -957,6 +944,7 @@ print_int_val(const char *type, ctf_encoding_t *ep, ulong_t off,
uint16_t i2;
uint8_t i1;
time_t t;
+ ipaddr_t I;
} u;
if (!(pap->pa_flags & PA_SHOWVAL))
@@ -991,12 +979,20 @@ print_int_val(const char *type, ctf_encoding_t *ep, ulong_t off,
}
/*
- * We pretty-print time_t values as a calendar date and time.
+ * We pretty-print some integer based types. time_t values are
+ * printed as a calendar date and time, and IPv4 addresses as human
+ * readable dotted quads.
*/
- if (!(pap->pa_flags & (PA_INTHEX | PA_INTDEC)) &&
- strcmp(type, "time_t") == 0 && u.t != 0) {
- mdb_printf("%Y", u.t);
- return (0);
+ if (!(pap->pa_flags & (PA_INTHEX | PA_INTDEC))) {
+ if (strcmp(type, "time_t") == 0 && u.t != 0) {
+ mdb_printf("%Y", u.t);
+ return (0);
+ }
+ if (strcmp(type, "ipaddr_t") == 0 ||
+ strcmp(type, "in_addr_t") == 0) {
+ mdb_printf("%I", u.I);
+ return (0);
+ }
}
/*
@@ -1296,6 +1292,46 @@ static int
print_sou(const char *type, const char *name, mdb_ctf_id_t id,
mdb_ctf_id_t base, ulong_t off, printarg_t *pap)
{
+ mdb_tgt_addr_t addr = pap->pa_addr + off / NBBY;
+
+ /*
+ * We have pretty-printing for some structures where displaying
+ * structure contents has no value.
+ */
+ if (pap->pa_flags & PA_SHOWVAL) {
+ if (strcmp(type, "in6_addr_t") == 0 ||
+ strcmp(type, "struct in6_addr") == 0) {
+ in6_addr_t in6addr;
+
+ if (mdb_tgt_aread(pap->pa_tgt, pap->pa_as, &in6addr,
+ sizeof (in6addr), addr) != sizeof (in6addr)) {
+ mdb_warn("failed to read %s pointer at %llx",
+ name, addr);
+ return (1);
+ }
+ mdb_printf("%N", &in6addr);
+ /*
+ * Don't print anything further down in the
+ * structure.
+ */
+ pap->pa_nooutdepth = pap->pa_depth;
+ return (0);
+ }
+ if (strcmp(type, "struct in_addr") == 0) {
+ in_addr_t inaddr;
+
+ if (mdb_tgt_aread(pap->pa_tgt, pap->pa_as, &inaddr,
+ sizeof (inaddr), addr) != sizeof (inaddr)) {
+ mdb_warn("failed to read %s pointer at %llx",
+ name, addr);
+ return (1);
+ }
+ mdb_printf("%I", inaddr);
+ pap->pa_nooutdepth = pap->pa_depth;
+ return (0);
+ }
+ }
+
if (pap->pa_depth == pap->pa_maxdepth)
mdb_printf("{ ... }");
else
@@ -1500,10 +1536,19 @@ elt_print(const char *name, mdb_ctf_id_t id, mdb_ctf_id_t base,
int kind, rc, d;
printarg_t *pap = data;
- for (d = pap->pa_depth - 1; d >= depth; d--)
- print_close_sou(pap, d);
+ for (d = pap->pa_depth - 1; d >= depth; d--) {
+ if (d < pap->pa_nooutdepth)
+ print_close_sou(pap, d);
+ }
+
+ /*
+ * Reset pa_nooutdepth if we've come back out of the structure we
+ * didn't want to print.
+ */
+ if (depth <= pap->pa_nooutdepth)
+ pap->pa_nooutdepth = (uint_t)-1;
- if (depth > pap->pa_maxdepth)
+ if (depth > pap->pa_maxdepth || depth > pap->pa_nooutdepth)
return (0);
if (!mdb_ctf_type_valid(base) ||
@@ -2299,6 +2344,7 @@ cmd_print(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv)
pa.pa_nholes = 0;
pa.pa_depth = 0;
pa.pa_maxdepth = opt_s;
+ pa.pa_nooutdepth = (uint_t)-1;
if ((flags & DCMD_ADDRSPEC) && !opt_i)
pa.pa_addr = opt_p ? mdb_get_dot() : addr;
diff --git a/usr/src/cmd/mdb/common/modules/conf/mapfile-extern b/usr/src/cmd/mdb/common/modules/conf/mapfile-extern
index c035d3fe55..5b4b8f2be1 100644
--- a/usr/src/cmd/mdb/common/modules/conf/mapfile-extern
+++ b/usr/src/cmd/mdb/common/modules/conf/mapfile-extern
@@ -1,5 +1,6 @@
#
# Copyright (c) 2008, 2010, Oracle and/or its affiliates. All rights reserved.
+# Copyright (c) 2012 by Delphix. All rights reserved.
#
# CDDL HEADER START
#
@@ -60,7 +61,10 @@ SYMBOL_SCOPE {
mdb_ctf_lookup_by_addr { FLAGS = EXTERN };
mdb_ctf_lookup_by_name { FLAGS = EXTERN };
mdb_ctf_member_iter { FLAGS = EXTERN };
+ mdb_ctf_module_lookup { FLAGS = EXTERN };
mdb_ctf_offsetof { FLAGS = EXTERN };
+ mdb_ctf_offsetof_by_name { FLAGS = EXTERN };
+ mdb_ctf_readsym { FLAGS = EXTERN };
mdb_ctf_type_cmp { FLAGS = EXTERN };
mdb_ctf_type_invalidate { FLAGS = EXTERN };
mdb_ctf_type_kind { FLAGS = EXTERN };
diff --git a/usr/src/cmd/mdb/common/modules/genunix/findstack_subr.c b/usr/src/cmd/mdb/common/modules/genunix/findstack_subr.c
index aa68d0236a..6fec78c5c5 100644
--- a/usr/src/cmd/mdb/common/modules/genunix/findstack_subr.c
+++ b/usr/src/cmd/mdb/common/modules/genunix/findstack_subr.c
@@ -21,6 +21,7 @@
/*
* Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2012 by Delphix. All rights reserved.
*/
#include <mdb/mdb_modapi.h>
@@ -126,11 +127,21 @@ crawl(uintptr_t frame, uintptr_t kbase, uintptr_t ktop, uintptr_t ubase,
return (levels);
}
+typedef struct mdb_findstack_kthread {
+ struct _sobj_ops *t_sobj_ops;
+ uint_t t_state;
+ ushort_t t_flag;
+ ushort_t t_schedflag;
+ caddr_t t_stk;
+ caddr_t t_stkbase;
+ label_t t_pcb;
+} mdb_findstack_kthread_t;
+
/*ARGSUSED*/
int
stacks_findstack(uintptr_t addr, findstack_info_t *fsip, uint_t print_warnings)
{
- kthread_t thr;
+ mdb_findstack_kthread_t thr;
size_t stksz;
uintptr_t ubase, utop;
uintptr_t kbase, ktop;
@@ -142,11 +153,8 @@ stacks_findstack(uintptr_t addr, findstack_info_t *fsip, uint_t print_warnings)
fsip->fsi_depth = 0;
fsip->fsi_overflow = 0;
- bzero(&thr, sizeof (thr));
- if (mdb_ctf_vread(&thr, "kthread_t", addr,
- MDB_CTF_VREAD_IGNORE_ALL) == -1) {
- if (print_warnings)
- mdb_warn("couldn't read thread at %p\n", addr);
+ if (mdb_ctf_vread(&thr, "kthread_t", "mdb_findstack_kthread_t",
+ addr, print_warnings ? 0 : MDB_CTF_VREAD_QUIET) == -1) {
fsip->fsi_failed = FSI_FAIL_BADTHREAD;
return (DCMD_ERR);
}
diff --git a/usr/src/cmd/mdb/common/modules/genunix/kmem.c b/usr/src/cmd/mdb/common/modules/genunix/kmem.c
index 909b7ecc7b..f1693d7bf6 100644
--- a/usr/src/cmd/mdb/common/modules/genunix/kmem.c
+++ b/usr/src/cmd/mdb/common/modules/genunix/kmem.c
@@ -25,6 +25,7 @@
/*
* Copyright 2011 Joyent, Inc. All rights reserved.
+ * Copyright (c) 2012 by Delphix. All rights reserved.
*/
#include <mdb/mdb_param.h>
@@ -2161,8 +2162,10 @@ whatis_print_kmf_lite(uintptr_t btaddr, size_t count)
/* validate the buffer state and read in the callers */
stat = (intptr_t)bt.bt_bufctl ^ bt.bt_bxstat;
- if (stat != KMEM_BUFTAG_ALLOC || stat != KMEM_BUFTAG_FREE ||
- mdb_vread(callers, count * sizeof (pc_t),
+ if (stat != KMEM_BUFTAG_ALLOC && stat != KMEM_BUFTAG_FREE)
+ return;
+
+ if (mdb_vread(callers, count * sizeof (pc_t),
btaddr + offsetof(kmem_buftag_lite_t, bt_history)) == -1)
return;
diff --git a/usr/src/cmd/mdb/common/modules/genunix/thread.c b/usr/src/cmd/mdb/common/modules/genunix/thread.c
index cf0e5b1623..652e5af2d6 100644
--- a/usr/src/cmd/mdb/common/modules/genunix/thread.c
+++ b/usr/src/cmd/mdb/common/modules/genunix/thread.c
@@ -22,9 +22,13 @@
* Copyright 2009 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
+/*
+ * Copyright 2013 Nexenta Systems, Inc. All rights reserved.
+ */
#include <mdb/mdb_modapi.h>
+#include <mdb/mdb_ks.h>
#include <sys/types.h>
#include <sys/thread.h>
#include <sys/lwp.h>
@@ -466,8 +470,8 @@ thread(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv)
if (oflags & TF_DISP) {
SPACER();
- mdb_printf("%<u> %?s %5s %2s%</u>",
- "DISPTIME", "BOUND", "PR");
+ mdb_printf("%<u> %?s %5s %2s %-6s%</u>",
+ "DISPTIME", "BOUND", "PR", "SWITCH");
}
mdb_printf("\n");
}
@@ -523,8 +527,13 @@ thread(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv)
/* dispatcher stuff */
if (oflags & TF_DISP) {
SPACER();
- mdb_printf(" %?lx %5d %2d",
+ mdb_printf(" %?lx %5d %2d ",
t.t_disp_time, t.t_bind_cpu, t.t_preempt);
+ if (t.t_disp_time != 0)
+ mdb_printf("t-%-4d",
+ (clock_t)mdb_get_lbolt() - t.t_disp_time);
+ else
+ mdb_printf("%-6s", "-");
}
mdb_printf("\n");
diff --git a/usr/src/cmd/mdb/common/modules/genunix/tsd.c b/usr/src/cmd/mdb/common/modules/genunix/tsd.c
index 975ee77637..d220ab633c 100644
--- a/usr/src/cmd/mdb/common/modules/genunix/tsd.c
+++ b/usr/src/cmd/mdb/common/modules/genunix/tsd.c
@@ -23,8 +23,9 @@
* Copyright (c) 2000-2001 by Sun Microsystems, Inc.
* All rights reserved.
*/
-
-#pragma ident "%Z%%M% %I% %E% SMI"
+/*
+ * Copyright (c) 2012 by Delphix. All rights reserved.
+ */
#include <sys/thread.h>
#include "tsd.h"
@@ -84,7 +85,7 @@ ttotsd(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv)
struct tsd_thread tsdata, *ts = &tsdata;
uintptr_t key = NULL;
uintptr_t eladdr;
- void *element;
+ void *element = NULL;
if (mdb_getopts(argc, argv, 'k', MDB_OPT_UINTPTR, &key, NULL) != argc)
return (DCMD_USAGE);
@@ -97,22 +98,16 @@ ttotsd(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv)
return (DCMD_ERR);
}
- if (t->t_tsd == NULL) {
- if (flags & DCMD_PIPE)
- return (DCMD_OK);
- mdb_warn("no tsd on thread\n");
- return (DCMD_ERR);
- }
+ if (t->t_tsd == NULL)
+ goto out;
if (mdb_vread(ts, sizeof (*ts), (uintptr_t)t->t_tsd) == -1) {
mdb_warn("failed to read tsd at %p", t->t_tsd);
return (DCMD_ERR);
}
- if (key > ts->ts_nkeys) {
- mdb_warn("key out of range\n");
- return (DCMD_ERR);
- }
+ if (key > ts->ts_nkeys)
+ goto out;
eladdr = (uintptr_t)(ts->ts_value + key - 1);
if (mdb_vread(&element, sizeof (element), eladdr) == -1) {
@@ -120,6 +115,10 @@ ttotsd(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv)
return (DCMD_ERR);
}
+out:
+ if (element == NULL && (flags & DCMD_PIPE))
+ return (DCMD_OK);
+
mdb_printf("%p\n", element);
return (DCMD_OK);
}
diff --git a/usr/src/cmd/mdb/common/modules/libc/libc.c b/usr/src/cmd/mdb/common/modules/libc/libc.c
index e3c9b9198f..44e4f49b87 100644
--- a/usr/src/cmd/mdb/common/modules/libc/libc.c
+++ b/usr/src/cmd/mdb/common/modules/libc/libc.c
@@ -21,6 +21,7 @@
/*
* Copyright (c) 2001, 2010, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2012 by Delphix. All rights reserved.
*/
/*
* Copyright (c) 2012, Joyent, Inc. All rights reserved.
@@ -28,6 +29,7 @@
#include <sys/mdb_modapi.h>
#include <mdb/mdb_whatis.h>
+#include <mdb/mdb_ctf.h>
#include <procfs.h>
#include <ucontext.h>
#include <siginfo.h>
@@ -1028,17 +1030,13 @@ tid2ulwp_walk(uintptr_t addr, ulwp_t *ulwp, tid2ulwp_walk_t *t2u)
return (WALK_NEXT);
}
-/*ARGSUSED*/
static int
-tid2ulwp(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv)
+tid2ulwp_impl(uintptr_t tid_addr, uintptr_t *ulwp_addrp)
{
tid2ulwp_walk_t t2u;
- if (argc != 0)
- return (DCMD_USAGE);
-
bzero(&t2u, sizeof (t2u));
- t2u.t2u_tid = (lwpid_t)addr;
+ t2u.t2u_tid = (lwpid_t)tid_addr;
if (mdb_walk("ulwp", (mdb_walk_cb_t)tid2ulwp_walk, &t2u) != 0) {
mdb_warn("can't walk 'ulwp'");
@@ -1049,9 +1047,78 @@ tid2ulwp(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv)
mdb_warn("thread ID %d not found", t2u.t2u_tid);
return (DCMD_ERR);
}
+ *ulwp_addrp = t2u.t2u_lwp;
+ return (DCMD_OK);
+}
- mdb_printf("%p\n", t2u.t2u_lwp);
+/*ARGSUSED*/
+static int
+tid2ulwp(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv)
+{
+ uintptr_t ulwp_addr;
+ int error;
+
+ if (argc != 0)
+ return (DCMD_USAGE);
+
+ error = tid2ulwp_impl(addr, &ulwp_addr);
+ if (error == DCMD_OK)
+ mdb_printf("%p\n", ulwp_addr);
+ return (error);
+}
+
+typedef struct mdb_libc_ulwp {
+ void *ul_ftsd[TSD_NFAST];
+ tsd_t *ul_stsd;
+} mdb_libc_ulwp_t;
+
+/*
+ * Map from thread pointer to tsd for given key
+ */
+static int
+d_tsd(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv)
+{
+ mdb_libc_ulwp_t u;
+ uintptr_t ulwp_addr;
+ uintptr_t key = NULL;
+ void *element = NULL;
+
+ if (mdb_getopts(argc, argv, 'k', MDB_OPT_UINTPTR, &key, NULL) != argc)
+ return (DCMD_USAGE);
+
+ if (!(flags & DCMD_ADDRSPEC) || key == NULL)
+ return (DCMD_USAGE);
+
+ if (tid2ulwp_impl(addr, &ulwp_addr) != DCMD_OK)
+ return (DCMD_ERR);
+
+ if (mdb_ctf_vread(&u, "ulwp_t", "mdb_libc_ulwp_t", ulwp_addr, 0) == -1)
+ return (DCMD_ERR);
+
+ if (key < TSD_NFAST) {
+ element = u.ul_ftsd[key];
+ } else if (u.ul_stsd != NULL) {
+ uint_t nalloc;
+ /* tsd_t is a union, so we can't use ctf_vread() on it. */
+ if (mdb_vread(&nalloc, sizeof (nalloc),
+ (uintptr_t)&u.ul_stsd->tsd_nalloc) == -1) {
+ mdb_warn("failed to read tsd_t at %p", u.ul_stsd);
+ return (DCMD_ERR);
+ }
+ if (key < nalloc) {
+ if (mdb_vread(&element, sizeof (element),
+ (uintptr_t)&u.ul_stsd->tsd_data[key]) == -1) {
+ mdb_warn("failed to read tsd_t at %p",
+ u.ul_stsd);
+ return (DCMD_ERR);
+ }
+ }
+ }
+
+ if (element == NULL && (flags & DCMD_PIPE))
+ return (DCMD_OK);
+ mdb_printf("%p\n", element);
return (DCMD_OK);
}
@@ -1065,6 +1132,7 @@ static const mdb_dcmd_t dcmds[] = {
{ "ucontext", ":", "print ucontext_t structure", d_ucontext, NULL },
{ "ulwp", ":", "print ulwp_t structure", d_ulwp, NULL },
{ "uberdata", ":", "print uberdata_t structure", d_uberdata, NULL },
+ { "tsd", ":-k key", "print tsd for this thread", d_tsd, NULL },
{ NULL }
};
diff --git a/usr/src/cmd/mdb/common/modules/zfs/zfs.c b/usr/src/cmd/mdb/common/modules/zfs/zfs.c
index 022f1b9b95..83cfa66dcb 100644
--- a/usr/src/cmd/mdb/common/modules/zfs/zfs.c
+++ b/usr/src/cmd/mdb/common/modules/zfs/zfs.c
@@ -21,7 +21,7 @@
/*
* Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved.
* Copyright 2011 Nexenta Systems, Inc. All rights reserved.
- * Copyright (c) 2012 by Delphix. All rights reserved.
+ * Copyright (c) 2013 by Delphix. All rights reserved.
*/
/* Portions Copyright 2010 Robert Milkowski */
@@ -50,6 +50,8 @@
#define ZFS_OBJ_NAME "libzpool.so.1"
#endif
+#define ZFS_STRUCT "struct " ZFS_OBJ_NAME "`"
+
#ifndef _KERNEL
int aok;
#endif
@@ -94,39 +96,13 @@ getmember(uintptr_t addr, const char *type, mdb_ctf_id_t *idp,
return (0);
}
-#define GETMEMB(addr, type, member, dest) \
- getmember(addr, #type, NULL, #member, sizeof (dest), &(dest))
+#define GETMEMB(addr, structname, member, dest) \
+ getmember(addr, ZFS_STRUCT structname, NULL, #member, \
+ sizeof (dest), &(dest))
#define GETMEMBID(addr, ctfid, member, dest) \
getmember(addr, NULL, ctfid, #member, sizeof (dest), &(dest))
-static int
-getrefcount(uintptr_t addr, mdb_ctf_id_t *id,
- const char *member, uint64_t *rc)
-{
- static int gotid;
- static mdb_ctf_id_t rc_id;
- ulong_t off;
-
- if (!gotid) {
- if (mdb_ctf_lookup_by_name("struct refcount", &rc_id) == -1) {
- mdb_warn("couldn't find struct refcount");
- return (DCMD_ERR);
- }
- gotid = TRUE;
- }
-
- if (mdb_ctf_offsetof(*id, member, &off) == -1) {
- char name[64];
- mdb_ctf_type_name(*id, name, sizeof (name));
- mdb_warn("couldn't find member %s of type %s\n", member, name);
- return (DCMD_ERR);
- }
- off /= 8;
-
- return (GETMEMBID(addr + off, &rc_id, rc_count, *rc));
-}
-
static boolean_t
strisprint(const char *cp)
{
@@ -188,9 +164,8 @@ freelist_walk_step(mdb_walk_state_t *wsp)
return (WALK_NEXT);
}
-
static int
-dataset_name(uintptr_t addr, char *buf)
+mdb_dsl_dir_name(uintptr_t addr, char *buf)
{
static int gotid;
static mdb_ctf_id_t dd_id;
@@ -198,7 +173,7 @@ dataset_name(uintptr_t addr, char *buf)
char dd_myname[MAXNAMELEN];
if (!gotid) {
- if (mdb_ctf_lookup_by_name("struct dsl_dir",
+ if (mdb_ctf_lookup_by_name(ZFS_STRUCT "dsl_dir",
&dd_id) == -1) {
mdb_warn("couldn't find struct dsl_dir");
return (DCMD_ERR);
@@ -211,7 +186,7 @@ dataset_name(uintptr_t addr, char *buf)
}
if (dd_parent) {
- if (dataset_name(dd_parent, buf))
+ if (mdb_dsl_dir_name(dd_parent, buf))
return (DCMD_ERR);
strcat(buf, "/");
}
@@ -236,12 +211,12 @@ objset_name(uintptr_t addr, char *buf)
buf[0] = '\0';
if (!gotid) {
- if (mdb_ctf_lookup_by_name("struct objset",
+ if (mdb_ctf_lookup_by_name(ZFS_STRUCT "objset",
&os_id) == -1) {
mdb_warn("couldn't find struct objset");
return (DCMD_ERR);
}
- if (mdb_ctf_lookup_by_name("struct dsl_dataset",
+ if (mdb_ctf_lookup_by_name(ZFS_STRUCT "dsl_dataset",
&ds_id) == -1) {
mdb_warn("couldn't find struct dsl_dataset");
return (DCMD_ERR);
@@ -263,7 +238,7 @@ objset_name(uintptr_t addr, char *buf)
return (DCMD_ERR);
}
- if (ds_dir && dataset_name(ds_dir, buf))
+ if (ds_dir && mdb_dsl_dir_name(ds_dir, buf))
return (DCMD_ERR);
if (ds_snapname[0]) {
@@ -400,58 +375,53 @@ blkptr(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv)
return (DCMD_OK);
}
+typedef struct mdb_dmu_buf_impl {
+ struct {
+ uint64_t db_object;
+ } db;
+ void *db_objset;
+ uint64_t db_level;
+ uint64_t db_blkid;
+ struct {
+ uint64_t rc_count;
+ } db_holds;
+} mdb_dmu_buf_impl_t;
+
/* ARGSUSED */
static int
dbuf(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv)
{
- mdb_ctf_id_t id;
- dmu_buf_t db;
- uintptr_t objset;
- uint8_t level;
- uint64_t blkid;
- uint64_t holds;
+ mdb_dmu_buf_impl_t db;
char objectname[32];
char blkidname[32];
char path[MAXNAMELEN];
- if (DCMD_HDRSPEC(flags)) {
+ if (DCMD_HDRSPEC(flags))
mdb_printf(" addr object lvl blkid holds os\n");
- }
- if (mdb_ctf_lookup_by_name("struct dmu_buf_impl", &id) == -1) {
- mdb_warn("couldn't find struct dmu_buf_impl_t");
+ if (mdb_ctf_vread(&db, ZFS_STRUCT "dmu_buf_impl", "mdb_dmu_buf_impl_t",
+ addr, 0) == -1)
return (DCMD_ERR);
- }
-
- if (GETMEMBID(addr, &id, db_objset, objset) ||
- GETMEMBID(addr, &id, db, db) ||
- GETMEMBID(addr, &id, db_level, level) ||
- GETMEMBID(addr, &id, db_blkid, blkid)) {
- return (WALK_ERR);
- }
- if (getrefcount(addr, &id, "db_holds", &holds)) {
- return (WALK_ERR);
- }
-
- if (db.db_object == DMU_META_DNODE_OBJECT)
+ if (db.db.db_object == DMU_META_DNODE_OBJECT)
(void) strcpy(objectname, "mdn");
else
(void) mdb_snprintf(objectname, sizeof (objectname), "%llx",
- (u_longlong_t)db.db_object);
+ (u_longlong_t)db.db.db_object);
- if (blkid == DMU_BONUS_BLKID)
+ if (db.db_blkid == DMU_BONUS_BLKID)
(void) strcpy(blkidname, "bonus");
else
(void) mdb_snprintf(blkidname, sizeof (blkidname), "%llx",
- (u_longlong_t)blkid);
+ (u_longlong_t)db.db_blkid);
- if (objset_name(objset, path)) {
- return (WALK_ERR);
+ if (objset_name((uintptr_t)db.db_objset, path)) {
+ return (DCMD_ERR);
}
- mdb_printf("%p %8s %1u %9s %2llu %s\n",
- addr, objectname, level, blkidname, holds, path);
+ mdb_printf("%p %8s %1u %9s %2llu %s\n", addr,
+ objectname, (int)db.db_level, blkidname,
+ db.db_holds.rc_count, path);
return (DCMD_OK);
}
@@ -735,7 +705,7 @@ dbufs(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv)
}
}
- if (mdb_ctf_lookup_by_name("struct dmu_buf_impl", &data.id) == -1) {
+ if (mdb_ctf_lookup_by_name(ZFS_STRUCT "dmu_buf_impl", &data.id) == -1) {
mdb_warn("couldn't find struct dmu_buf_impl_t");
return (DCMD_ERR);
}
@@ -801,7 +771,7 @@ abuf_find(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv)
}
}
- if (mdb_ctf_lookup_by_name("struct arc_buf_hdr", &data.id) == -1) {
+ if (mdb_ctf_lookup_by_name(ZFS_STRUCT "arc_buf_hdr", &data.id) == -1) {
mdb_warn("couldn't find struct arc_buf_hdr");
return (DCMD_ERR);
}
@@ -821,6 +791,12 @@ abuf_find(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv)
return (DCMD_OK);
}
+
+typedef struct dbgmsg_arg {
+ boolean_t da_verbose;
+ boolean_t da_address;
+} dbgmsg_arg_t;
+
/* ARGSUSED */
static int
dbgmsg_cb(uintptr_t addr, const void *unknown, void *arg)
@@ -829,12 +805,13 @@ dbgmsg_cb(uintptr_t addr, const void *unknown, void *arg)
static boolean_t gotid;
static ulong_t off;
- int *verbosep = arg;
+ dbgmsg_arg_t *da = arg;
time_t timestamp;
char buf[1024];
if (!gotid) {
- if (mdb_ctf_lookup_by_name("struct zfs_dbgmsg", &id) == -1) {
+ if (mdb_ctf_lookup_by_name(ZFS_STRUCT "zfs_dbgmsg", &id) ==
+ -1) {
mdb_warn("couldn't find struct zfs_dbgmsg");
return (WALK_ERR);
}
@@ -856,12 +833,14 @@ dbgmsg_cb(uintptr_t addr, const void *unknown, void *arg)
return (DCMD_ERR);
}
- if (*verbosep)
+ if (da->da_address)
+ mdb_printf("%p ", addr);
+ if (da->da_verbose)
mdb_printf("%Y ", timestamp);
mdb_printf("%s\n", buf);
- if (*verbosep)
+ if (da->da_verbose)
(void) mdb_call_dcmd("whatis", addr, DCMD_ADDRSPEC, 0, NULL);
return (WALK_NEXT);
@@ -872,10 +851,11 @@ static int
dbgmsg(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv)
{
GElf_Sym sym;
- int verbose = FALSE;
+ dbgmsg_arg_t da = { 0 };
if (mdb_getopts(argc, argv,
- 'v', MDB_OPT_SETBITS, TRUE, &verbose,
+ 'v', MDB_OPT_SETBITS, B_TRUE, &da.da_verbose,
+ 'a', MDB_OPT_SETBITS, B_TRUE, &da.da_address,
NULL) != argc)
return (DCMD_USAGE);
@@ -884,7 +864,7 @@ dbgmsg(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv)
return (DCMD_ERR);
}
- if (mdb_pwalk("list", dbgmsg_cb, &verbose, sym.st_value) != 0) {
+ if (mdb_pwalk("list", dbgmsg_cb, &da, sym.st_value) != 0) {
mdb_warn("can't walk zfs_dbgmsgs");
return (DCMD_ERR);
}
@@ -906,12 +886,12 @@ arc_print(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv)
static const char *bytestats[] = {
"p", "c", "c_min", "c_max", "size", "duplicate_buffers_size",
+ "arc_meta_used", "arc_meta_limit", "arc_meta_max",
NULL
};
static const char *extras[] = {
"arc_no_grow", "arc_tempreserve",
- "arc_meta_used", "arc_meta_limit", "arc_meta_max",
NULL
};
@@ -1096,6 +1076,10 @@ spa_print(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv)
return (DCMD_OK);
}
+typedef struct mdb_spa_config_spa {
+ nvlist_t *spa_config;
+} mdb_spa_config_spa_t;
+
/*
* ::spa_config
*
@@ -1107,15 +1091,14 @@ spa_print(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv)
static int
spa_print_config(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv)
{
- spa_t spa;
+ mdb_spa_config_spa_t spa;
if (argc != 0 || !(flags & DCMD_ADDRSPEC))
return (DCMD_USAGE);
- if (mdb_vread(&spa, sizeof (spa), addr) == -1) {
- mdb_warn("failed to read spa_t at %p", addr);
+ if (mdb_ctf_vread(&spa, ZFS_STRUCT "spa", "mdb_spa_config_spa_t",
+ addr, 0) == -1)
return (DCMD_ERR);
- }
if (spa.spa_config == NULL) {
mdb_printf("(none)\n");
@@ -1369,8 +1352,8 @@ metaslab_walk_step(mdb_walk_state_t *wsp)
ASSERT(mw->mw_nummss == 0);
vdevp = mw->mw_vdevs[mw->mw_curvdev];
- if (GETMEMB(vdevp, struct vdev, vdev_ms, mssp) ||
- GETMEMB(vdevp, struct vdev, vdev_ms_count, mw->mw_nummss)) {
+ if (GETMEMB(vdevp, "vdev", vdev_ms, mssp) ||
+ GETMEMB(vdevp, "vdev", vdev_ms_count, mw->mw_nummss)) {
return (WALK_ERR);
}
@@ -1417,9 +1400,9 @@ metaslab_walk_init(mdb_walk_state_t *wsp)
mw = mdb_zalloc(sizeof (metaslab_walk_data_t), UM_SLEEP | UM_GC);
- if (GETMEMB(wsp->walk_addr, struct spa, spa_root_vdev, root_vdevp) ||
- GETMEMB(root_vdevp, struct vdev, vdev_children, mw->mw_numvdevs) ||
- GETMEMB(root_vdevp, struct vdev, vdev_child, childp)) {
+ if (GETMEMB(wsp->walk_addr, "spa", spa_root_vdev, root_vdevp) ||
+ GETMEMB(root_vdevp, "vdev", vdev_children, mw->mw_numvdevs) ||
+ GETMEMB(root_vdevp, "vdev", vdev_child, childp)) {
return (DCMD_ERR);
}
@@ -1482,11 +1465,11 @@ space_cb(uintptr_t addr, const void *unknown, void *arg)
space_data_t *sd = arg;
mdb_metaslab_t ms;
- if (GETMEMB(addr, struct metaslab, ms_allocmap, ms.ms_allocmap) ||
- GETMEMB(addr, struct metaslab, ms_freemap, ms.ms_freemap) ||
- GETMEMB(addr, struct metaslab, ms_map, ms.ms_map) ||
- GETMEMB(addr, struct metaslab, ms_smo, ms.ms_smo) ||
- GETMEMB(addr, struct metaslab, ms_smo_syncing, ms.ms_smo_syncing)) {
+ if (GETMEMB(addr, "metaslab", ms_allocmap, ms.ms_allocmap) ||
+ GETMEMB(addr, "metaslab", ms_freemap, ms.ms_freemap) ||
+ GETMEMB(addr, "metaslab", ms_map, ms.ms_map) ||
+ GETMEMB(addr, "metaslab", ms_smo, ms.ms_smo) ||
+ GETMEMB(addr, "metaslab", ms_smo_syncing, ms.ms_smo_syncing)) {
return (WALK_ERR);
}
@@ -1525,33 +1508,33 @@ spa_space(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv)
space_data_t sd;
int shift = 20;
char *suffix = "M";
- int bits = FALSE;
+ int bytes = B_FALSE;
- if (mdb_getopts(argc, argv, 'b', MDB_OPT_SETBITS, TRUE, &bits, NULL) !=
+ if (mdb_getopts(argc, argv, 'b', MDB_OPT_SETBITS, TRUE, &bytes, NULL) !=
argc)
return (DCMD_USAGE);
if (!(flags & DCMD_ADDRSPEC))
return (DCMD_USAGE);
- if (bits) {
+ if (bytes) {
shift = 0;
suffix = "";
}
- if (GETMEMB(addr, struct spa, spa_dsl_pool, spa.spa_dsl_pool) ||
- GETMEMB(addr, struct spa, spa_root_vdev, spa.spa_root_vdev) ||
- GETMEMB(spa.spa_root_vdev, struct vdev, vdev_children, children) ||
- GETMEMB(spa.spa_root_vdev, struct vdev, vdev_child, childaddr) ||
- GETMEMB(spa.spa_dsl_pool, struct dsl_pool,
+ if (GETMEMB(addr, "spa", spa_dsl_pool, spa.spa_dsl_pool) ||
+ GETMEMB(addr, "spa", spa_root_vdev, spa.spa_root_vdev) ||
+ GETMEMB(spa.spa_root_vdev, "vdev", vdev_children, children) ||
+ GETMEMB(spa.spa_root_vdev, "vdev", vdev_child, childaddr) ||
+ GETMEMB(spa.spa_dsl_pool, "dsl_pool",
dp_root_dir, dp_root_dir) ||
- GETMEMB(dp_root_dir, struct dsl_dir, dd_phys, dd.dd_phys) ||
- GETMEMB(dp_root_dir, struct dsl_dir,
+ GETMEMB(dp_root_dir, "dsl_dir", dd_phys, dd.dd_phys) ||
+ GETMEMB(dp_root_dir, "dsl_dir",
dd_space_towrite, dd.dd_space_towrite) ||
- GETMEMB(dd.dd_phys, struct dsl_dir_phys,
+ GETMEMB(dd.dd_phys, "dsl_dir_phys",
dd_used_bytes, dsp.dd_used_bytes) ||
- GETMEMB(dd.dd_phys, struct dsl_dir_phys,
+ GETMEMB(dd.dd_phys, "dsl_dir_phys",
dd_compressed_bytes, dsp.dd_compressed_bytes) ||
- GETMEMB(dd.dd_phys, struct dsl_dir_phys,
+ GETMEMB(dd.dd_phys, "dsl_dir_phys",
dd_uncompressed_bytes, dsp.dd_uncompressed_bytes)) {
return (DCMD_ERR);
}
@@ -1749,13 +1732,25 @@ typedef struct zio_print_args {
uint_t zpa_flags;
} zio_print_args_t;
+typedef struct mdb_zio {
+ enum zio_type io_type;
+ enum zio_stage io_stage;
+ void *io_waiter;
+ uint64_t io_timestamp;
+ void *io_spa;
+ struct {
+ struct {
+ void *list_next;
+ } list_head;
+ } io_parent_list;
+ int io_error;
+} mdb_zio_t;
+
static int zio_child_cb(uintptr_t addr, const void *unknown, void *arg);
static int
-zio_print_cb(uintptr_t addr, const void *data, void *priv)
+zio_print_cb(uintptr_t addr, const mdb_zio_t *zio, zio_print_args_t *zpa)
{
- const zio_t *zio = data;
- zio_print_args_t *zpa = priv;
mdb_ctf_id_t type_enum, stage_enum;
int indent = zpa->zpa_current_depth;
const char *type, *stage;
@@ -1775,10 +1770,15 @@ zio_print_cb(uintptr_t addr, const void *data, void *priv)
else
type = "?";
- if ((stage = mdb_ctf_enum_name(stage_enum, zio->io_stage)) != NULL)
- stage += sizeof ("ZIO_STAGE_") - 1;
- else
- stage = "?";
+ if (zio->io_error == 0) {
+ stage = mdb_ctf_enum_name(stage_enum, zio->io_stage);
+ if (stage != NULL)
+ stage += sizeof ("ZIO_STAGE_") - 1;
+ else
+ stage = "?";
+ } else {
+ stage = "FAILED";
+ }
if (zpa->zpa_current_depth >= zpa->zpa_min_depth) {
if (zpa->zpa_flags & DCMD_PIPE_OUT) {
@@ -1797,9 +1797,11 @@ zio_print_cb(uintptr_t addr, const void *data, void *priv)
return (WALK_NEXT);
if (zpa->zpa_type == ZIO_WALK_PARENT)
- laddr = addr + OFFSETOF(zio_t, io_parent_list);
+ laddr = addr + mdb_ctf_offsetof_by_name(ZFS_STRUCT "zio",
+ "io_parent_list");
else
- laddr = addr + OFFSETOF(zio_t, io_child_list);
+ laddr = addr + mdb_ctf_offsetof_by_name(ZFS_STRUCT "zio",
+ "io_child_list");
zpa->zpa_current_depth++;
if (mdb_pwalk("list", zio_child_cb, zpa, laddr) != 0) {
@@ -1816,7 +1818,7 @@ static int
zio_child_cb(uintptr_t addr, const void *unknown, void *arg)
{
zio_link_t zl;
- zio_t zio;
+ mdb_zio_t zio;
uintptr_t ziop;
zio_print_args_t *zpa = arg;
@@ -1830,10 +1832,8 @@ zio_child_cb(uintptr_t addr, const void *unknown, void *arg)
else
ziop = (uintptr_t)zl.zl_child;
- if (mdb_vread(&zio, sizeof (zio_t), ziop) == -1) {
- mdb_warn("failed to read zio_t at %p", ziop);
+ if (mdb_ctf_vread(&zio, ZFS_STRUCT "zio", "mdb_zio_t", ziop, 0) == -1)
return (WALK_ERR);
- }
return (zio_print_cb(ziop, &zio, arg));
}
@@ -1842,7 +1842,7 @@ zio_child_cb(uintptr_t addr, const void *unknown, void *arg)
static int
zio_print(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv)
{
- zio_t zio;
+ mdb_zio_t zio;
zio_print_args_t zpa = { 0 };
if (!(flags & DCMD_ADDRSPEC))
@@ -1864,10 +1864,8 @@ zio_print(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv)
zpa.zpa_max_depth = 1;
}
- if (mdb_vread(&zio, sizeof (zio_t), addr) == -1) {
- mdb_warn("failed to read zio_t at %p", addr);
+ if (mdb_ctf_vread(&zio, ZFS_STRUCT "zio", "mdb_zio_t", addr, 0) == -1)
return (DCMD_ERR);
- }
if (!(flags & DCMD_PIPE_OUT) && DCMD_HDRSPEC(flags))
mdb_printf("%<u>%-*s %-5s %-16s %-?s%</u>\n", ZIO_MAXWIDTH,
@@ -2063,12 +2061,11 @@ zio_walk_init(mdb_walk_state_t *wsp)
static int
zio_walk_step(mdb_walk_state_t *wsp)
{
- zio_t zio;
+ mdb_zio_t zio;
- if (mdb_vread(&zio, sizeof (zio), wsp->walk_addr) == -1) {
- mdb_warn("failed to read zio_t at %p", wsp->walk_addr);
+ if (mdb_ctf_vread(&zio, ZFS_STRUCT "zio", "mdb_zio_t",
+ wsp->walk_addr, 0) == -1)
return (WALK_ERR);
- }
if (wsp->walk_data != NULL && wsp->walk_data != zio.io_spa)
return (WALK_NEXT);
@@ -2084,19 +2081,20 @@ zio_walk_step(mdb_walk_state_t *wsp)
static int
zio_walk_root_step(mdb_walk_state_t *wsp)
{
- zio_t zio;
+ mdb_zio_t zio;
- if (mdb_vread(&zio, sizeof (zio), wsp->walk_addr) == -1) {
- mdb_warn("failed to read zio_t at %p", wsp->walk_addr);
+ if (mdb_ctf_vread(&zio, ZFS_STRUCT "zio", "mdb_zio_t",
+ wsp->walk_addr, 0) == -1)
return (WALK_ERR);
- }
if (wsp->walk_data != NULL && wsp->walk_data != zio.io_spa)
return (WALK_NEXT);
/* If the parent list is not empty, ignore */
- if (zio.io_parent_list.list_head.list_next !=
- &((zio_t *)wsp->walk_addr)->io_parent_list.list_head)
+ if ((uintptr_t)zio.io_parent_list.list_head.list_next !=
+ wsp->walk_addr +
+ mdb_ctf_offsetof_by_name(ZFS_STRUCT "zio", "io_parent_list") +
+ mdb_ctf_offsetof_by_name("struct list", "list_head"))
return (WALK_NEXT);
return (wsp->walk_callback(wsp->walk_addr, &zio, wsp->walk_cbdata));
@@ -2179,8 +2177,8 @@ zfs_blkstats(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv)
if (!(flags & DCMD_ADDRSPEC))
return (DCMD_USAGE);
- if (GETMEMB(addr, struct spa, spa_dsl_pool, addr) ||
- GETMEMB(addr, struct dsl_pool, dp_blkstats, addr) ||
+ if (GETMEMB(addr, "spa", spa_dsl_pool, addr) ||
+ GETMEMB(addr, "dsl_pool", dp_blkstats, addr) ||
mdb_vread(&stats, sizeof (zfs_all_blkstats_t), addr) == -1) {
mdb_warn("failed to read data at %p;", addr);
mdb_printf("maybe no stats? run \"zpool scrub\" first.");
@@ -2334,10 +2332,16 @@ refcount(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv)
static int gotid;
static mdb_ctf_id_t rc_id;
ulong_t off;
+ boolean_t released = B_FALSE;
if (!(flags & DCMD_ADDRSPEC))
return (DCMD_USAGE);
+ if (mdb_getopts(argc, argv,
+ 'r', MDB_OPT_SETBITS, B_TRUE, &released,
+ NULL) != argc)
+ return (DCMD_USAGE);
+
if (!gotid) {
/*
* The refcount structure is different when compiled debug
@@ -2345,7 +2349,7 @@ refcount(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv)
* refcount definition from the ZFS module, in case it has
* been compiled debug but genunix is nondebug.
*/
- if (mdb_ctf_lookup_by_name("struct " ZFS_OBJ_NAME "`refcount",
+ if (mdb_ctf_lookup_by_name(ZFS_STRUCT "refcount",
&rc_id) == -1) {
mdb_warn("couldn't find struct refcount");
return (DCMD_ERR);
@@ -2353,10 +2357,15 @@ refcount(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv)
gotid = TRUE;
}
- if (GETMEMBID(addr, &rc_id, rc_count, rc_count) ||
- GETMEMBID(addr, &rc_id, rc_removed_count, rc_removed_count))
+ if (GETMEMBID(addr, &rc_id, rc_count, rc_count))
return (DCMD_ERR);
+ if (GETMEMBID(addr, &rc_id, rc_removed_count, rc_removed_count)) {
+ mdb_printf("refcount_t at %p has %llu current holds\n",
+ addr, (longlong_t)rc_count);
+ return (DCMD_OK);
+ }
+
mdb_printf("refcount_t at %p has %llu current holds, "
"%llu recently released holds\n",
addr, (longlong_t)rc_count, (longlong_t)rc_removed_count);
@@ -2368,12 +2377,14 @@ refcount(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv)
rc_list = addr + off/NBBY;
mdb_pwalk("list", reference_cb, (void*)B_FALSE, rc_list);
- if (rc_removed_count > 0)
- mdb_printf("released holds:\n");
- if (mdb_ctf_offsetof(rc_id, "rc_removed", &off) == -1)
- return (DCMD_ERR);
- rc_removed = addr + off/NBBY;
- mdb_pwalk("list", reference_cb, (void*)B_TRUE, rc_removed);
+ if (released) {
+ if (rc_removed_count > 0)
+ mdb_printf("released holds:\n");
+ if (mdb_ctf_offsetof(rc_id, "rc_removed", &off) == -1)
+ return (DCMD_ERR);
+ rc_removed = addr + off/NBBY;
+ mdb_pwalk("list", reference_cb, (void*)B_TRUE, rc_removed);
+ }
return (DCMD_OK);
}
@@ -2419,7 +2430,7 @@ sa_get_off_table(uintptr_t addr, uint32_t **off_tab, int attr_count)
{
uintptr_t idx_table;
- if (GETMEMB(addr, struct sa_idx_tab, sa_idx_tab, idx_table)) {
+ if (GETMEMB(addr, "sa_idx_tab", sa_idx_tab, idx_table)) {
mdb_printf("can't find offset table in sa_idx_tab\n");
return (-1);
}
@@ -2457,22 +2468,22 @@ sa_attr_print(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv)
else
return (DCMD_USAGE);
- if (GETMEMB(addr, struct sa_handle, sa_bonus_tab, bonus_tab) ||
- GETMEMB(addr, struct sa_handle, sa_spill_tab, spill_tab) ||
- GETMEMB(addr, struct sa_handle, sa_os, os) ||
- GETMEMB(addr, struct sa_handle, sa_bonus, db_bonus) ||
- GETMEMB(addr, struct sa_handle, sa_spill, db_spill)) {
+ if (GETMEMB(addr, "sa_handle", sa_bonus_tab, bonus_tab) ||
+ GETMEMB(addr, "sa_handle", sa_spill_tab, spill_tab) ||
+ GETMEMB(addr, "sa_handle", sa_os, os) ||
+ GETMEMB(addr, "sa_handle", sa_bonus, db_bonus) ||
+ GETMEMB(addr, "sa_handle", sa_spill, db_spill)) {
mdb_printf("Can't find necessary information in sa_handle "
"in sa_handle\n");
return (DCMD_ERR);
}
- if (GETMEMB(os, struct objset, os_sa, os_sa)) {
+ if (GETMEMB(os, "objset", os_sa, os_sa)) {
mdb_printf("Can't find os_sa in objset\n");
return (DCMD_ERR);
}
- if (GETMEMB(os_sa, struct sa_os, sa_num_attrs, attr_count)) {
+ if (GETMEMB(os_sa, "sa_os", sa_num_attrs, attr_count)) {
mdb_printf("Can't find sa_num_attrs\n");
return (DCMD_ERR);
}
@@ -2488,7 +2499,7 @@ sa_attr_print(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv)
return (DCMD_ERR);
}
- if (GETMEMB(db_bonus, struct dmu_buf, db_data, db_data)) {
+ if (GETMEMB(db_bonus, "dmu_buf", db_data, db_data)) {
mdb_printf("can't find db_data in bonus dbuf\n");
return (DCMD_ERR);
}
@@ -2503,7 +2514,7 @@ sa_attr_print(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv)
attr_count) == -1) {
return (DCMD_ERR);
}
- if (GETMEMB(db_spill, struct dmu_buf, db_data, db_data)) {
+ if (GETMEMB(db_spill, "dmu_buf", db_data, db_data)) {
mdb_printf("can't find db_data in spill dbuf\n");
return (DCMD_ERR);
}
@@ -2814,7 +2825,8 @@ zfs_acl_node_walk_init(mdb_walk_state_t *wsp)
return (WALK_ERR);
}
- wsp->walk_addr += OFFSETOF(zfs_acl_t, z_acl);
+ wsp->walk_addr +=
+ mdb_ctf_offsetof_by_name(ZFS_STRUCT "zfs_acl", "z_acl");
if (mdb_layered_walk("list", wsp) == -1) {
mdb_warn("failed to walk 'list'\n");
@@ -2974,6 +2986,58 @@ zfs_aces_walk_step(mdb_walk_state_t *wsp)
return (status);
}
+typedef struct mdb_zfs_rrwlock {
+ kthread_t *rr_writer;
+ boolean_t rr_writer_wanted;
+} mdb_zfs_rrwlock_t;
+
+static uint_t rrw_key;
+
+/* ARGSUSED */
+static int
+rrwlock(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv)
+{
+ mdb_zfs_rrwlock_t rrw;
+
+ if (rrw_key == 0) {
+ if (mdb_ctf_readsym(&rrw_key, "uint_t", "rrw_tsd_key", 0) == -1)
+ return (DCMD_ERR);
+ }
+
+ if (mdb_ctf_vread(&rrw, "rrwlock_t", "mdb_zfs_rrwlock_t", addr,
+ 0) == -1)
+ return (DCMD_ERR);
+
+ if (rrw.rr_writer != NULL) {
+ mdb_printf("write lock held by thread %p\n", rrw.rr_writer);
+ return (DCMD_OK);
+ }
+
+ if (rrw.rr_writer_wanted) {
+ mdb_printf("writer wanted\n");
+ }
+
+ mdb_printf("anonymous references:\n");
+ (void) mdb_call_dcmd("refcount", addr +
+ mdb_ctf_offsetof_by_name(ZFS_STRUCT "rrwlock", "rr_anon_rcount"),
+ DCMD_ADDRSPEC, 0, NULL);
+
+ mdb_printf("linked references:\n");
+ (void) mdb_call_dcmd("refcount", addr +
+ mdb_ctf_offsetof_by_name(ZFS_STRUCT "rrwlock", "rr_linked_rcount"),
+ DCMD_ADDRSPEC, 0, NULL);
+
+ /*
+ * XXX This should find references from
+ * "::walk thread | ::tsd -v <rrw_key>", but there is no support
+ * for programmatic consumption of dcmds, so this would be
+ * difficult, potentially requiring reimplementing ::tsd (both
+ * user and kernel versions) in this MDB module.
+ */
+
+ return (DCMD_OK);
+}
+
/*
* MDB module linkage information:
*
@@ -3014,7 +3078,9 @@ static const mdb_dcmd_t dcmds[] = {
"given a spa_t, print block type stats from last scrub",
zfs_blkstats },
{ "zfs_params", "", "print zfs tunable parameters", zfs_params },
- { "refcount", "", "print refcount_t holders", refcount },
+ { "refcount", ":[-r]\n"
+ "\t-r display recently removed references",
+ "print refcount_t holders", refcount },
{ "zap_leaf", "", "print zap_leaf_phys_t", zap_leaf },
{ "zfs_aces", ":[-v]", "print all ACEs from a zfs_acl_t",
zfs_acl_dump },
@@ -3024,33 +3090,35 @@ static const mdb_dcmd_t dcmds[] = {
sa_attr_table},
{ "sa_attr", ": attr_id",
"print SA attribute address when given sa_handle_t", sa_attr_print},
- { "zfs_dbgmsg", ":[-v]",
+ { "zfs_dbgmsg", ":[-va]",
"print zfs debug log", dbgmsg},
+ { "rrwlock", ":",
+ "print rrwlock_t, including readers", rrwlock},
{ NULL }
};
static const mdb_walker_t walkers[] = {
{ "zms_freelist", "walk ZFS metaslab freelist",
- freelist_walk_init, freelist_walk_step, NULL },
+ freelist_walk_init, freelist_walk_step, NULL },
{ "txg_list", "given any txg_list_t *, walk all entries in all txgs",
- txg_list_walk_init, txg_list_walk_step, NULL },
+ txg_list_walk_init, txg_list_walk_step, NULL },
{ "txg_list0", "given any txg_list_t *, walk all entries in txg 0",
- txg_list0_walk_init, txg_list_walk_step, NULL },
+ txg_list0_walk_init, txg_list_walk_step, NULL },
{ "txg_list1", "given any txg_list_t *, walk all entries in txg 1",
- txg_list1_walk_init, txg_list_walk_step, NULL },
+ txg_list1_walk_init, txg_list_walk_step, NULL },
{ "txg_list2", "given any txg_list_t *, walk all entries in txg 2",
- txg_list2_walk_init, txg_list_walk_step, NULL },
+ txg_list2_walk_init, txg_list_walk_step, NULL },
{ "txg_list3", "given any txg_list_t *, walk all entries in txg 3",
- txg_list3_walk_init, txg_list_walk_step, NULL },
+ txg_list3_walk_init, txg_list_walk_step, NULL },
{ "zio", "walk all zio structures, optionally for a particular spa_t",
- zio_walk_init, zio_walk_step, NULL },
- { "zio_root", "walk all root zio_t structures, optionally for a "
- "particular spa_t",
- zio_walk_init, zio_walk_root_step, NULL },
+ zio_walk_init, zio_walk_step, NULL },
+ { "zio_root",
+ "walk all root zio_t structures, optionally for a particular spa_t",
+ zio_walk_init, zio_walk_root_step, NULL },
{ "spa", "walk all spa_t entries in the namespace",
- spa_walk_init, spa_walk_step, NULL },
+ spa_walk_init, spa_walk_step, NULL },
{ "metaslab", "given a spa_t *, walk all metaslab_t structures",
- metaslab_walk_init, metaslab_walk_step, NULL },
+ metaslab_walk_init, metaslab_walk_step, NULL },
{ "zfs_acl_node", "given a zfs_acl_t, walk all zfs_acl_nodes",
zfs_acl_node_walk_init, zfs_acl_node_walk_step, NULL },
{ "zfs_acl_node_aces", "given a zfs_acl_node_t, walk all ACEs",
diff --git a/usr/src/cmd/mdb/i86xpv/modules/xpv/xpv.c b/usr/src/cmd/mdb/i86xpv/modules/xpv/xpv.c
index 8912e80b89..eb294d45d7 100644
--- a/usr/src/cmd/mdb/i86xpv/modules/xpv/xpv.c
+++ b/usr/src/cmd/mdb/i86xpv/modules/xpv/xpv.c
@@ -22,8 +22,9 @@
* Copyright 2007 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
-
-#pragma ident "%Z%%M% %I% %E% SMI"
+/*
+ * Copyright (c) 2012 by Delphix. All rights reserved.
+ */
#include <mdb/mdb_modapi.h>
#include <mdb/mdb_ks.h>
@@ -51,7 +52,7 @@ static mdb_ctf_id_t domain_type;
* interesting bits from the binary, and stash them in the structure
* defined below.
*/
-typedef struct domain {
+typedef struct mdb_xpv_domain {
short domain_id;
int tot_pages;
int max_pages;
@@ -59,9 +60,9 @@ typedef struct domain {
ulong_t domain_flags;
char is_hvm;
struct vcpu *vcpu[MAX_VIRT_CPUS];
- struct evtchn *evtchn[NR_EVTCHN_BUCKETS];
- struct domain *next_in_list;
-} domain_t;
+ struct evtchn *evtchn[NR_EVTCHN_BUCKETS];
+ struct domain *next_in_list;
+} mdb_xpv_domain_t;
static uintptr_t
get_dom0_addr()
@@ -110,7 +111,7 @@ int
domain_walk_step(mdb_walk_state_t *wsp)
{
domain_walk_t *dwp = (domain_walk_t *)wsp->walk_data;
- struct domain dom;
+ mdb_xpv_domain_t dom;
int status;
if (wsp->walk_addr == NULL)
@@ -119,11 +120,9 @@ domain_walk_step(mdb_walk_state_t *wsp)
status = wsp->walk_callback(wsp->walk_addr, (void *)wsp->walk_addr,
wsp->walk_cbdata);
- if (mdb_ctf_vread(&dom, "struct domain", wsp->walk_addr,
- MDB_CTF_VREAD_IGNORE_ABSENT) != 0) {
- mdb_warn("can't find next domain");
+ if (mdb_ctf_vread(&dom, "struct domain", "mdb_xpv_domain_t",
+ wsp->walk_addr, 0) != 0)
return (WALK_ERR);
- }
wsp->walk_addr = (uintptr_t)dom.next_in_list;
dwp->dw_step = TRUE;
@@ -199,7 +198,7 @@ vcpu_walk_fini(mdb_walk_state_t *wsp)
int
domain(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv)
{
- domain_t dom;
+ mdb_xpv_domain_t dom;
uintptr_t off, vcpu_addr, evtchn_addr;
if (!mdb_ctf_type_valid(domain_type)) {
@@ -220,11 +219,9 @@ domain(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv)
"ADDR", "ID", "TPAGES", "MPAGES", "FLAGS", "HVM",
"VCPU", "EVTCHN");
- if (mdb_ctf_vread(&dom, "struct domain", addr,
- MDB_CTF_VREAD_IGNORE_ABSENT) != 0) {
- mdb_warn("can't read domain information");
+ if (mdb_ctf_vread(&dom, "struct domain", "mdb_xpv_domain_t", addr,
+ 0) != 0)
return (DCMD_ERR);
- }
if (mdb_ctf_offsetof(domain_type, "vcpu", &off)) {
mdb_warn("can't find per-domain vcpu information");
@@ -258,24 +255,23 @@ static const mdb_walker_t walkers[] = {
static const mdb_modinfo_t modinfo = { MDB_API_VERSION, dcmds, walkers };
+typedef struct mdb_xpv_panic_info {
+ int pi_version;
+} mdb_xpv_panic_info_t;
+
const mdb_modinfo_t *
_mdb_init(void)
{
- GElf_Sym sym;
uintptr_t pip;
- struct panic_info pi;
+ mdb_xpv_panic_info_t pi;
- if (mdb_lookup_by_name("xpv_panic_info", &sym) < 0)
- return (NULL);
-
- if (mdb_ctf_vread(&pip, "uintptr_t", sym.st_value, 0) == -1) {
+ if (mdb_readsym(&pip, sizeof (pip), "xpv_panic_info") == -1) {
mdb_warn("failed to read xpv panic_info pointer");
return (NULL);
}
- if (mdb_ctf_vread(&pi, "struct panic_info", pip, 0) == -1) {
- mdb_warn("failed to read xpv panic_info");
+ if (mdb_ctf_vread(&pi, "struct panic_info", "mdb_xpv_panic_info_t",
+ pip, 0) == -1)
return (NULL);
- }
if (pi.pi_version != PANIC_INFO_VERSION) {
mdb_warn("unrecognized hypervisor panic format");
diff --git a/usr/src/cmd/mdb/i86xpv/modules/xpv_psm/xpv_psm.c b/usr/src/cmd/mdb/i86xpv/modules/xpv_psm/xpv_psm.c
index e802882ee3..3717a17d66 100644
--- a/usr/src/cmd/mdb/i86xpv/modules/xpv_psm/xpv_psm.c
+++ b/usr/src/cmd/mdb/i86xpv/modules/xpv_psm/xpv_psm.c
@@ -22,6 +22,9 @@
* Copyright 2009 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
+/*
+ * Copyright (c) 2013 by Delphix. All rights reserved.
+ */
#include <mdb/mdb_modapi.h>
#include <mdb/mdb_ks.h>
@@ -32,7 +35,12 @@
#include "intr_common.h"
-static shared_info_t shared_info;
+typedef struct mdb_shared_info {
+ unsigned long evtchn_pending[sizeof (unsigned long) * NBBY];
+ unsigned long evtchn_mask[sizeof (unsigned long) * NBBY];
+} mdb_shared_info_t;
+
+static mdb_shared_info_t shared_info;
static int have_shared_info;
static uintptr_t evtchn_cpus_addr;
static struct av_head avec_tbl[NR_IRQS];
@@ -109,8 +117,8 @@ update_tables(void)
/*
* It's normal for this to fail with a domain dump.
*/
- if (mdb_ctf_vread(&shared_info, "shared_info_t",
- shared_info_addr, 0) != -1)
+ if (mdb_ctf_vread(&shared_info, "shared_info_t", "mdb_shared_info_t",
+ shared_info_addr, MDB_CTF_VREAD_QUIET) != -1)
have_shared_info = 1;
return (1);
@@ -255,18 +263,20 @@ evtchn_pending(int i)
return (!!TEST_EVTCHN_BIT(i, &shared_info.evtchn_pending[0]));
}
+typedef struct mdb_xpv_psm_autovec {
+ dev_info_t *av_dip;
+} mdb_xpv_psm_autovec_t;
+
static void
print_bus(int irq)
{
char parent[7];
uintptr_t dip_addr;
struct dev_info dev_info;
- struct autovec avhp;
-
- bzero(&avhp, sizeof (avhp));
+ mdb_xpv_psm_autovec_t avhp;
- if (mdb_ctf_vread(&avhp, "struct autovec",
- (uintptr_t)avec_tbl[irq].avh_link, 0) == -1)
+ if (mdb_ctf_vread(&avhp, "struct autovec", "mdb_xpv_psm_autovec_t",
+ (uintptr_t)avec_tbl[irq].avh_link, MDB_CTF_VREAD_QUIET) == -1)
goto fail;
dip_addr = (uintptr_t)avhp.av_dip;
diff --git a/usr/src/cmd/mdb/i86xpv/modules/xpv_uppc/xpv_uppc.c b/usr/src/cmd/mdb/i86xpv/modules/xpv_uppc/xpv_uppc.c
index 32410bcebb..f5b4144285 100644
--- a/usr/src/cmd/mdb/i86xpv/modules/xpv_uppc/xpv_uppc.c
+++ b/usr/src/cmd/mdb/i86xpv/modules/xpv_uppc/xpv_uppc.c
@@ -22,8 +22,9 @@
* Copyright 2008 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
-
-#pragma ident "%Z%%M% %I% %E% SMI"
+/*
+ * Copyright (c) 2013 by Delphix. All rights reserved.
+ */
#include <mdb/mdb_modapi.h>
#include <mdb/mdb_ks.h>
@@ -32,7 +33,12 @@
#include "intr_common.h"
-static shared_info_t shared_info;
+typedef struct mdb_shared_info {
+ unsigned long evtchn_pending[sizeof (unsigned long) * NBBY];
+ unsigned long evtchn_mask[sizeof (unsigned long) * NBBY];
+} mdb_shared_info_t;
+
+static mdb_shared_info_t shared_info;
static struct av_head avec_tbl[NR_IRQS];
static uint16_t shared_tbl[MAX_ISA_IRQ + 1];
static irq_info_t irq_tbl[NR_IRQS];
@@ -74,11 +80,9 @@ update_tables(void)
return (0);
}
- if (mdb_ctf_vread(&shared_info, "shared_info_t",
- shared_info_addr, 0) == -1) {
- mdb_warn("failed to read shared_info");
+ if (mdb_ctf_vread(&shared_info, "shared_info_t", "mdb_shared_info_t",
+ shared_info_addr, 0) == -1)
return (0);
- }
return (1);
}
diff --git a/usr/src/cmd/smbsrv/smbd/server.xml b/usr/src/cmd/smbsrv/smbd/server.xml
index eea68bb135..cf5e69986e 100644
--- a/usr/src/cmd/smbsrv/smbd/server.xml
+++ b/usr/src/cmd/smbsrv/smbd/server.xml
@@ -21,8 +21,8 @@ information: Portions Copyright [yyyy] [name of copyright owner]
CDDL HEADER END
-Copyright 2011 Nexenta Systems, Inc. All rights reserved.
Copyright (c) 2007, 2010, Oracle and/or its affiliates. All rights reserved.
+Copyright 2011 Nexenta Systems, Inc. All rights reserved.
NOTE: This service manifest is not editable; its contents will
be overwritten by package or patch operations, including
@@ -217,6 +217,8 @@ file.
value='5.0' override='true'/>
<propval name='dfs_stdroot_num' type='integer'
value='0' override='true'/>
+ <propval name='traverse_mounts' type='boolean'
+ value='true' override='true'/>
</property_group>
<!-- SMB service-specific shares exec configuration defaults -->
diff --git a/usr/src/cmd/ssh/libssh/common/readconf.c b/usr/src/cmd/ssh/libssh/common/readconf.c
index 6254faa1d7..b1e7f89c7a 100644
--- a/usr/src/cmd/ssh/libssh/common/readconf.c
+++ b/usr/src/cmd/ssh/libssh/common/readconf.c
@@ -13,7 +13,7 @@
/*
* Copyright 2009 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
- * Copyright 2012 Joyent, Inc. All rights reserved.
+ * Copyright 2013 Joyent, Inc. All rights reserved.
*/
#include "includes.h"
diff --git a/usr/src/cmd/ssh/sshd/servconf.c b/usr/src/cmd/ssh/sshd/servconf.c
index 5d81ed30c4..16f1dcecf7 100644
--- a/usr/src/cmd/ssh/sshd/servconf.c
+++ b/usr/src/cmd/ssh/sshd/servconf.c
@@ -10,7 +10,7 @@
*/
/*
* Copyright (c) 2001, 2010, Oracle and/or its affiliates. All rights reserved.
- * Copyright 2012 Joyent, Inc. All rights reserved.
+ * Copyright 2013 Joyent, Inc. All rights reserved.
*/
#include "includes.h"
diff --git a/usr/src/cmd/stat/Makefile b/usr/src/cmd/stat/Makefile
index 762daf4c28..faffc6a437 100644
--- a/usr/src/cmd/stat/Makefile
+++ b/usr/src/cmd/stat/Makefile
@@ -30,6 +30,7 @@ include ../Makefile.cmd
SUBDIRS= arcstat \
fsstat \
iostat \
+ kstat \
mpstat \
vfsstat \
vmstat \
diff --git a/usr/src/cmd/stat/common/acquire.c b/usr/src/cmd/stat/common/acquire.c
index b952b8d5e4..99e9ac4f17 100644
--- a/usr/src/cmd/stat/common/acquire.c
+++ b/usr/src/cmd/stat/common/acquire.c
@@ -20,6 +20,7 @@
*/
/*
* Copyright (c) 2004, 2010, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2012 by Delphix. All rights reserved.
*/
#include "statcommon.h"
@@ -289,6 +290,7 @@ acquire_sys(struct snapshot *ss, kstat_ctl_t *kc)
return (errno);
if (kstat_add(&ss->s_cpus[i].cs_vm, &ss->s_sys.ss_agg_vm))
return (errno);
+ ss->s_nr_active_cpus++;
}
return (0);
diff --git a/usr/src/cmd/stat/common/statcommon.h b/usr/src/cmd/stat/common/statcommon.h
index 9ee077431d..fd3e9d2d9b 100644
--- a/usr/src/cmd/stat/common/statcommon.h
+++ b/usr/src/cmd/stat/common/statcommon.h
@@ -20,7 +20,10 @@
*/
/*
* Copyright (c) 2004, 2010, Oracle and/or its affiliates. All rights reserved.
- *
+ * Copyright (c) 2012 by Delphix. All rights reserved.
+ */
+
+/*
* Common routines for acquiring snapshots of kstats for
* iostat, mpstat, and vmstat.
*/
@@ -221,6 +224,7 @@ struct snapshot {
size_t s_iodevs_is_name_maxlen;
struct sys_snapshot s_sys;
struct biostats s_biostats;
+ size_t s_nr_active_cpus;
};
/* print a message and exit with failure */
diff --git a/usr/src/cmd/stat/iostat/iostat.c b/usr/src/cmd/stat/iostat/iostat.c
index 608f73f876..628dab1518 100644
--- a/usr/src/cmd/stat/iostat/iostat.c
+++ b/usr/src/cmd/stat/iostat/iostat.c
@@ -26,6 +26,9 @@
* rewritten from UCB 4.13 83/09/25
* rewritten from SunOS 4.1 SID 1.18 89/10/06
*/
+/*
+ * Copyright (c) 2012 by Delphix. All rights reserved.
+ */
#include <stdio.h>
#include <stdlib.h>
@@ -422,14 +425,14 @@ show_disk_header(void *v1, void *v2, void *data)
*
* 0---------1--------2---------3---------4---------5---------6---------7-------
* tty sd0 sd1 sd2 sd3 cpu
- * tin tout kps tps serv kps tps serv kps tps serv kps tps serv us sy wt id
+ * tin tout kps tps serv kps tps serv kps tps serv kps tps serv us sy dt id
* NNN NNNN NNN NNN NNNN NNN NNN NNNN NNN NNN NNNN NNN NNN NNNN NN NN NN NN
*
* When -D is specified, the disk header looks as follows (worst case):
*
* 0---------1--------2---------3---------4---------5---------6---------7-------
* tty sd0 sd1 sd2 sd3 cpu
- * tin tout rps wps util rps wps util rps wps util rps wps util us sy wt id
+ * tin tout rps wps util rps wps util rps wps util rps wps util us sy dt id
* NNN NNNN NNN NNN NNNN NNN NNN NNNN NNN NNN NNNN NNN NNN NNNN NN NN NN NN
*/
static void
@@ -940,7 +943,7 @@ usage(void)
"Usage: iostat [-cCdDeEiImMnpPrstxXYz] "
" [-l n] [-T d|u] [disk ...] [interval [count]]\n"
"\t\t-c: report percentage of time system has spent\n"
- "\t\t\tin user/system/wait/idle mode\n"
+ "\t\t\tin user/system/dtrace/idle mode\n"
"\t\t-C: report disk statistics by controller\n"
"\t\t-d: display disk Kb/sec, transfers/sec, avg. \n"
"\t\t\tservice time in milliseconds \n"
@@ -1489,9 +1492,9 @@ print_cpu_hdr2(void)
char *dstr;
if (do_raw == 0)
- dstr = " us sy wt id";
+ dstr = " us sy dt id";
else
- dstr = "us,sy,wt,id";
+ dstr = "us,sy,dt,id";
push_out(dstr);
}
@@ -1534,7 +1537,8 @@ print_cpu_data(void)
uint64_t idle;
uint64_t user;
uint64_t kern;
- uint64_t wait;
+ uint64_t dtrace;
+ uint64_t nsec_elapsed;
kstat_t *oldks = NULL;
if (oldss)
@@ -1548,9 +1552,13 @@ print_cpu_data(void)
idle = kstat_delta(oldks, &newss->s_sys.ss_agg_sys, "cpu_ticks_idle");
user = kstat_delta(oldks, &newss->s_sys.ss_agg_sys, "cpu_ticks_user");
kern = kstat_delta(oldks, &newss->s_sys.ss_agg_sys, "cpu_ticks_kernel");
- wait = kstat_delta(oldks, &newss->s_sys.ss_agg_sys, "cpu_ticks_wait");
+ dtrace = kstat_delta(oldks, &newss->s_sys.ss_agg_sys,
+ "cpu_nsec_dtrace");
+ nsec_elapsed = newss->s_sys.ss_agg_sys.ks_snaptime -
+ (oldks == NULL ? 0 : oldks->ks_snaptime);
push_out(fstr, user * percent, kern * percent,
- wait * percent, idle * percent);
+ dtrace * 100.0 / nsec_elapsed / newss->s_nr_active_cpus,
+ idle * percent);
}
/*
diff --git a/usr/src/cmd/stat/kstat/Makefile b/usr/src/cmd/stat/kstat/Makefile
new file mode 100644
index 0000000000..4c072ccd61
--- /dev/null
+++ b/usr/src/cmd/stat/kstat/Makefile
@@ -0,0 +1,66 @@
+#
+# CDDL HEADER START
+#
+# The contents of this file are subject to the terms of the
+# Common Development and Distribution License (the "License").
+# You may not use this file except in compliance with the License.
+#
+# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+# or http://www.opensolaris.org/os/licensing.
+# See the License for the specific language governing permissions
+# and limitations under the License.
+#
+# When distributing Covered Code, include this CDDL HEADER in each
+# file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+# If applicable, add the following below this CDDL HEADER, with the
+# fields enclosed by brackets "[]" replaced with your own identifying
+# information: Portions Copyright [yyyy] [name of copyright owner]
+#
+# CDDL HEADER END
+#
+#
+# Copyright 2009 Sun Microsystems, Inc. All rights reserved.
+# Use is subject to license terms.
+#
+
+PROG = kstat
+OBJS = kstat.o
+SRCS =$(OBJS:%.o=%.c) $(COMMON_SRCS)
+
+include $(SRC)/cmd/Makefile.cmd
+include $(SRC)/cmd/stat/Makefile.stat
+
+LDLIBS += -lavl -lcmdutils -ldevinfo -lgen -lkstat
+CFLAGS += $(CCVERBOSE) -I${STATCOMMONDIR}
+CERRWARN += -_gcc=-Wno-uninitialized
+CERRWARN += -_gcc=-Wno-switch
+CERRWARN += -_gcc=-Wno-parentheses
+
+CPPFLAGS_sparc += -I$(SRC)/uts/sfmmu
+CPPFLAGS_sparc += -I$(SRC)/uts/sun4u/sunfire
+CPPFLAGS += $(CPPFLAGS_$(MACH))
+
+FILEMODE= 0555
+
+lint := LINTFLAGS = -muxs -I$(STATCOMMONDIR)
+
+.KEEP_STATE:
+
+all: $(PROG)
+
+install: all $(ROOTPROG)
+
+$(PROG): $(OBJS) $(COMMON_OBJS)
+ $(LINK.c) -o $(PROG) $(OBJS) $(COMMON_OBJS) $(LDLIBS)
+ $(POST_PROCESS)
+
+%.o : $(STATCOMMONDIR)/%.c
+ $(COMPILE.c) -o $@ $<
+ $(POST_PROCESS_O)
+
+clean:
+ -$(RM) $(OBJS) $(COMMON_OBJS)
+
+lint: lint_SRCS
+
+include $(SRC)/cmd/Makefile.targ
diff --git a/usr/src/cmd/stat/kstat/kstat.c b/usr/src/cmd/stat/kstat/kstat.c
new file mode 100644
index 0000000000..2165101ac9
--- /dev/null
+++ b/usr/src/cmd/stat/kstat/kstat.c
@@ -0,0 +1,1469 @@
+/*
+ * CDDL HEADER START
+ *
+ * The contents of this file are subject to the terms of the
+ * Common Development and Distribution License (the "License").
+ * You may not use this file except in compliance with the License.
+ *
+ * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+ * or http://www.opensolaris.org/os/licensing.
+ * See the License for the specific language governing permissions
+ * and limitations under the License.
+ *
+ * When distributing Covered Code, include this CDDL HEADER in each
+ * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+ * If applicable, add the following below this CDDL HEADER, with the
+ * fields enclosed by brackets "[]" replaced with your own identifying
+ * information: Portions Copyright [yyyy] [name of copyright owner]
+ *
+ * CDDL HEADER END
+ */
+
+/*
+ * Copyright (c) 1999, 2010, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2013 David Hoeppner. All rights reserved.
+ * Copyright 2013 Nexenta Systems, Inc. All rights reserved.
+ */
+
+/*
+ * Display kernel statistics
+ *
+ * This is a reimplementation of the perl kstat command originally found
+ * under usr/src/cmd/kstat/kstat.pl
+ *
+ * Incompatibilities:
+ * - perl regular expressions replaced with extended REs bracketed by '/'
+ * - options checking is stricter
+ *
+ * Flags added:
+ * -C similar to the -p option but value is separated by a colon
+ * -h display help
+ * -j json format
+ */
+
+#include <assert.h>
+#include <ctype.h>
+#include <errno.h>
+#include <kstat.h>
+#include <langinfo.h>
+#include <libgen.h>
+#include <limits.h>
+#include <locale.h>
+#include <signal.h>
+#include <stddef.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <strings.h>
+#include <time.h>
+#include <unistd.h>
+#include <sys/list.h>
+#include <sys/time.h>
+#include <sys/types.h>
+
+#include "kstat.h"
+#include "statcommon.h"
+
+char *cmdname = "kstat"; /* Name of this command */
+int caught_cont = 0; /* Have caught a SIGCONT */
+
+static uint_t g_timestamp_fmt = NODATE;
+
+/* Helper flag - header was printed already? */
+static boolean_t g_headerflg;
+
+/* Saved command line options */
+static boolean_t g_cflg = B_FALSE;
+static boolean_t g_jflg = B_FALSE;
+static boolean_t g_lflg = B_FALSE;
+static boolean_t g_pflg = B_FALSE;
+static boolean_t g_qflg = B_FALSE;
+static ks_pattern_t g_ks_class = {"*", 0};
+
+/* Return zero if a selector did match */
+static int g_matched = 1;
+
+/* Sorted list of kstat instances */
+static list_t instances_list;
+static list_t selector_list;
+
+int
+main(int argc, char **argv)
+{
+ ks_selector_t *nselector;
+ ks_selector_t *uselector;
+ kstat_ctl_t *kc;
+ hrtime_t start_n;
+ hrtime_t period_n;
+ boolean_t errflg = B_FALSE;
+ boolean_t nselflg = B_FALSE;
+ boolean_t uselflg = B_FALSE;
+ char *q;
+ int count = 1;
+ int infinite_cycles = 0;
+ int interval = 0;
+ int n = 0;
+ int c, m, tmp;
+
+ (void) setlocale(LC_ALL, "");
+#if !defined(TEXT_DOMAIN) /* Should be defined by cc -D */
+#define TEXT_DOMAIN "SYS_TEST" /* Use this only if it wasn't */
+#endif
+ (void) textdomain(TEXT_DOMAIN);
+
+ /*
+ * Create the selector list and a dummy default selector to match
+ * everything. While we process the cmdline options we will add
+ * selectors to this list.
+ */
+ list_create(&selector_list, sizeof (ks_selector_t),
+ offsetof(ks_selector_t, ks_next));
+
+ nselector = new_selector();
+
+ /*
+ * Parse named command line arguments.
+ */
+ while ((c = getopt(argc, argv, "h?CqjlpT:m:i:n:s:c:")) != EOF)
+ switch (c) {
+ case 'h':
+ case '?':
+ usage();
+ exit(0);
+ break;
+ case 'C':
+ g_pflg = g_cflg = B_TRUE;
+ break;
+ case 'q':
+ g_qflg = B_TRUE;
+ break;
+ case 'j':
+ g_jflg = B_TRUE;
+ break;
+ case 'l':
+ g_pflg = g_lflg = B_TRUE;
+ break;
+ case 'p':
+ g_pflg = B_TRUE;
+ break;
+ case 'T':
+ switch (*optarg) {
+ case 'd':
+ g_timestamp_fmt = DDATE;
+ break;
+ case 'u':
+ g_timestamp_fmt = UDATE;
+ break;
+ default:
+ errflg = B_TRUE;
+ }
+ break;
+ case 'm':
+ nselflg = B_TRUE;
+ nselector->ks_module.pstr =
+ (char *)ks_safe_strdup(optarg);
+ break;
+ case 'i':
+ nselflg = B_TRUE;
+ nselector->ks_instance.pstr =
+ (char *)ks_safe_strdup(optarg);
+ break;
+ case 'n':
+ nselflg = B_TRUE;
+ nselector->ks_name.pstr =
+ (char *)ks_safe_strdup(optarg);
+ break;
+ case 's':
+ nselflg = B_TRUE;
+ nselector->ks_statistic.pstr =
+ (char *)ks_safe_strdup(optarg);
+ break;
+ case 'c':
+ g_ks_class.pstr =
+ (char *)ks_safe_strdup(optarg);
+ break;
+ default:
+ errflg = B_TRUE;
+ break;
+ }
+
+ if (g_qflg && (g_jflg || g_pflg)) {
+ (void) fprintf(stderr, gettext(
+ "-q and -lpj are mutually exclusive\n"));
+ errflg = B_TRUE;
+ }
+
+ if (errflg) {
+ usage();
+ exit(2);
+ }
+
+ argc -= optind;
+ argv += optind;
+
+ /*
+ * Consume the rest of the command line. Parsing the
+ * unnamed command line arguments.
+ */
+ while (argc--) {
+ errno = 0;
+ tmp = strtoul(*argv, &q, 10);
+ if (tmp == ULONG_MAX && errno == ERANGE) {
+ if (n == 0) {
+ (void) fprintf(stderr, gettext(
+ "Interval is too large\n"));
+ } else if (n == 1) {
+ (void) fprintf(stderr, gettext(
+ "Count is too large\n"));
+ }
+ usage();
+ exit(2);
+ }
+
+ if (errno != 0 || *q != '\0') {
+ m = 0;
+ uselector = new_selector();
+ while ((q = (char *)strsep(argv, ":")) != NULL) {
+ m++;
+ if (m > 4) {
+ free(uselector);
+ usage();
+ exit(2);
+ }
+
+ if (*q != '\0') {
+ switch (m) {
+ case 1:
+ uselector->ks_module.pstr =
+ (char *)ks_safe_strdup(q);
+ break;
+ case 2:
+ uselector->ks_instance.pstr =
+ (char *)ks_safe_strdup(q);
+ break;
+ case 3:
+ uselector->ks_name.pstr =
+ (char *)ks_safe_strdup(q);
+ break;
+ case 4:
+ uselector->ks_statistic.pstr =
+ (char *)ks_safe_strdup(q);
+ break;
+ default:
+ assert(B_FALSE);
+ }
+ }
+ }
+
+ if (m < 4) {
+ free(uselector);
+ usage();
+ exit(2);
+ }
+
+ uselflg = B_TRUE;
+ list_insert_tail(&selector_list, uselector);
+ } else {
+ if (tmp < 1) {
+ if (n == 0) {
+ (void) fprintf(stderr, gettext(
+ "Interval must be an "
+ "integer >= 1"));
+ } else if (n == 1) {
+ (void) fprintf(stderr, gettext(
+ "Count must be an integer >= 1"));
+ }
+ usage();
+ exit(2);
+ } else {
+ if (n == 0) {
+ interval = tmp;
+ count = -1;
+ } else if (n == 1) {
+ count = tmp;
+ } else {
+ usage();
+ exit(2);
+ }
+ }
+ n++;
+ }
+ argv++;
+ }
+
+ /*
+ * Check if we founded a named selector on the cmdline.
+ */
+ if (uselflg) {
+ if (nselflg) {
+ (void) fprintf(stderr, gettext(
+ "module:instance:name:statistic and "
+ "-m -i -n -s are mutually exclusive"));
+ usage();
+ exit(2);
+ } else {
+ free(nselector);
+ }
+ } else {
+ list_insert_tail(&selector_list, nselector);
+ }
+
+ assert(!list_is_empty(&selector_list));
+
+ list_create(&instances_list, sizeof (ks_instance_t),
+ offsetof(ks_instance_t, ks_next));
+
+ while ((kc = kstat_open()) == NULL) {
+ if (errno == EAGAIN) {
+ (void) poll(NULL, 0, 200);
+ } else {
+ perror("kstat_open");
+ exit(3);
+ }
+ }
+
+ if (count > 1) {
+ if (signal(SIGCONT, cont_handler) == SIG_ERR) {
+ (void) fprintf(stderr, gettext(
+ "signal failed"));
+ exit(3);
+ }
+ }
+
+ period_n = (hrtime_t)interval * NANOSEC;
+ start_n = gethrtime();
+
+ while (count == -1 || count-- > 0) {
+ ks_instances_read(kc);
+ ks_instances_print();
+
+ if (interval && count) {
+ ks_sleep_until(&start_n, period_n, infinite_cycles,
+ &caught_cont);
+ (void) kstat_chain_update(kc);
+ (void) putchar('\n');
+ }
+ }
+
+ (void) kstat_close(kc);
+
+ return (g_matched);
+}
+
+/*
+ * Print usage.
+ */
+static void
+usage(void)
+{
+ (void) fprintf(stderr, gettext(
+ "Usage:\n"
+ "kstat [ -Cjlpq ] [ -T d|u ] [ -c class ]\n"
+ " [ -m module ] [ -i instance ] [ -n name ] [ -s statistic ]\n"
+ " [ interval [ count ] ]\n"
+ "kstat [ -Cjlpq ] [ -T d|u ] [ -c class ]\n"
+ " [ module:instance:name:statistic ... ]\n"
+ " [ interval [ count ] ]\n"));
+}
+
+/*
+ * Sort compare function.
+ */
+static int
+compare_instances(ks_instance_t *l_arg, ks_instance_t *r_arg)
+{
+ int rval;
+
+ rval = strcasecmp(l_arg->ks_module, r_arg->ks_module);
+ if (rval == 0) {
+ if (l_arg->ks_instance == r_arg->ks_instance) {
+ return (strcasecmp(l_arg->ks_name, r_arg->ks_name));
+ } else if (l_arg->ks_instance < r_arg->ks_instance) {
+ return (-1);
+ } else {
+ return (1);
+ }
+ } else {
+ return (rval);
+ }
+}
+
+static char *
+ks_safe_strdup(char *str)
+{
+ char *ret;
+
+ if (str == NULL) {
+ return (NULL);
+ }
+
+ while ((ret = strdup(str)) == NULL) {
+ if (errno == EAGAIN) {
+ (void) poll(NULL, 0, 200);
+ } else {
+ perror("strdup");
+ exit(3);
+ }
+ }
+
+ return (ret);
+}
+
+static void
+ks_sleep_until(hrtime_t *wakeup, hrtime_t interval, int forever,
+ int *caught_cont)
+{
+ hrtime_t now, pause, pause_left;
+ struct timespec pause_tv;
+ int status;
+
+ now = gethrtime();
+ pause = *wakeup + interval - now;
+
+ if (pause <= 0 || pause < (interval / 4)) {
+ if (forever || *caught_cont) {
+ *wakeup = now + interval;
+ pause = interval;
+ } else {
+ pause = interval / 2;
+ *wakeup += interval;
+ }
+ } else {
+ *wakeup += interval;
+ }
+
+ if (pause < 1000) {
+ return;
+ }
+
+ pause_left = pause;
+ do {
+ pause_tv.tv_sec = pause_left / NANOSEC;
+ pause_tv.tv_nsec = pause_left % NANOSEC;
+ status = nanosleep(&pause_tv, (struct timespec *)NULL);
+ if (status < 0) {
+ if (errno == EINTR) {
+ now = gethrtime();
+ pause_left = *wakeup - now;
+ if (pause_left < 1000) {
+ return;
+ }
+ } else {
+ perror("nanosleep");
+ exit(3);
+ }
+ }
+ } while (status != 0);
+}
+
+/*
+ * Inserts an instance in the per selector list.
+ */
+static void
+nvpair_insert(ks_instance_t *ksi, char *name, ks_value_t *value,
+ uchar_t data_type)
+{
+ ks_nvpair_t *instance;
+ ks_nvpair_t *tmp;
+
+ instance = (ks_nvpair_t *)malloc(sizeof (ks_nvpair_t));
+ if (instance == NULL) {
+ perror("malloc");
+ exit(3);
+ }
+
+ (void) strlcpy(instance->name, name, KSTAT_STRLEN);
+ (void) memcpy(&instance->value, value, sizeof (ks_value_t));
+ instance->data_type = data_type;
+
+ tmp = list_head(&ksi->ks_nvlist);
+ while (tmp != NULL && strcasecmp(instance->name, tmp->name) > 0)
+ tmp = list_next(&ksi->ks_nvlist, tmp);
+
+ list_insert_before(&ksi->ks_nvlist, tmp, instance);
+}
+
+/*
+ * Allocates a new all-matching selector.
+ */
+static ks_selector_t *
+new_selector(void)
+{
+ ks_selector_t *selector;
+
+ selector = (ks_selector_t *)malloc(sizeof (ks_selector_t));
+ if (selector == NULL) {
+ perror("malloc");
+ exit(3);
+ }
+
+ list_link_init(&selector->ks_next);
+
+ selector->ks_module.pstr = "*";
+ selector->ks_instance.pstr = "*";
+ selector->ks_name.pstr = "*";
+ selector->ks_statistic.pstr = "*";
+
+ return (selector);
+}
+
+/*
+ * This function was taken from the perl kstat module code - please
+ * see for further comments there.
+ */
+static kstat_raw_reader_t
+lookup_raw_kstat_fn(char *module, char *name)
+{
+ char key[KSTAT_STRLEN * 2];
+ register char *f, *t;
+ int n = 0;
+
+ for (f = module, t = key; *f != '\0'; f++, t++) {
+ while (*f != '\0' && isdigit(*f))
+ f++;
+ *t = *f;
+ }
+ *t++ = ':';
+
+ for (f = name; *f != '\0'; f++, t++) {
+ while (*f != '\0' && isdigit(*f))
+ f++;
+ *t = *f;
+ }
+ *t = '\0';
+
+ while (ks_raw_lookup[n].fn != NULL) {
+ if (strncmp(ks_raw_lookup[n].name, key, strlen(key)) == 0)
+ return (ks_raw_lookup[n].fn);
+ n++;
+ }
+
+ return (0);
+}
+
+/*
+ * Match a string against a shell glob or extended regular expression.
+ */
+static boolean_t
+ks_match(const char *str, ks_pattern_t *pattern)
+{
+ int regcode;
+ char *regstr;
+ char *errbuf;
+ size_t bufsz;
+
+ if (pattern->pstr != NULL && gmatch(pattern->pstr, "/*/") != 0) {
+ /* All regex patterns are strdup'd copies */
+ regstr = pattern->pstr + 1;
+ *(strrchr(regstr, '/')) = '\0';
+
+ regcode = regcomp(&pattern->preg, regstr,
+ REG_EXTENDED | REG_NOSUB);
+ if (regcode != 0) {
+ bufsz = regerror(regcode, NULL, NULL, 0);
+ if (bufsz != 0) {
+ errbuf = malloc(bufsz);
+ if (errbuf == NULL) {
+ perror("malloc");
+ exit(3);
+ }
+ (void) regerror(regcode, NULL, errbuf, bufsz);
+ (void) fprintf(stderr, "kstat: %s\n", errbuf);
+ }
+ usage();
+ exit(2);
+ }
+
+ pattern->pstr = NULL;
+ }
+
+ if (pattern->pstr == NULL) {
+ return (regexec(&pattern->preg, str, 0, NULL, 0) == 0);
+ }
+
+ return ((gmatch(str, pattern->pstr) != 0));
+}
+
+/*
+ * Iterate over all kernel statistics and save matches.
+ */
+static void
+ks_instances_read(kstat_ctl_t *kc)
+{
+ kstat_raw_reader_t save_raw = NULL;
+ kid_t id;
+ ks_selector_t *selector;
+ ks_instance_t *ksi;
+ ks_instance_t *tmp;
+ kstat_t *kp;
+ boolean_t skip;
+
+ for (kp = kc->kc_chain; kp != NULL; kp = kp->ks_next) {
+ /* Don't bother storing the kstat headers */
+ if (strncmp(kp->ks_name, "kstat_", 6) == 0) {
+ continue;
+ }
+
+ /* Don't bother storing raw stats we don't understand */
+ if (kp->ks_type == KSTAT_TYPE_RAW) {
+ save_raw = lookup_raw_kstat_fn(kp->ks_module,
+ kp->ks_name);
+ if (save_raw == NULL) {
+#ifdef REPORT_UNKNOWN
+ (void) fprintf(stderr,
+ "Unknown kstat type %s:%d:%s - "
+ "%d of size %d\n", kp->ks_module,
+ kp->ks_instance, kp->ks_name,
+ kp->ks_ndata, kp->ks_data_size);
+#endif
+ continue;
+ }
+ }
+
+ /*
+ * Iterate over the list of selectors and skip
+ * instances we dont want. We filter for statistics
+ * later, as we dont know them yet.
+ */
+ skip = B_TRUE;
+ selector = list_head(&selector_list);
+ while (selector != NULL) {
+ if (ks_match(kp->ks_module, &selector->ks_module) ||
+ ks_match(kp->ks_name, &selector->ks_name)) {
+ skip = B_FALSE;
+ break;
+ }
+ selector = list_next(&selector_list, selector);
+ }
+
+ if (skip) {
+ continue;
+ }
+
+ /*
+ * Allocate a new instance and fill in the values
+ * we know so far.
+ */
+ ksi = (ks_instance_t *)malloc(sizeof (ks_instance_t));
+ if (ksi == NULL) {
+ perror("malloc");
+ exit(3);
+ }
+
+ list_link_init(&ksi->ks_next);
+
+ (void) strlcpy(ksi->ks_module, kp->ks_module, KSTAT_STRLEN);
+ (void) strlcpy(ksi->ks_name, kp->ks_name, KSTAT_STRLEN);
+ (void) strlcpy(ksi->ks_class, kp->ks_class, KSTAT_STRLEN);
+
+ ksi->ks_instance = kp->ks_instance;
+ ksi->ks_snaptime = kp->ks_snaptime;
+ ksi->ks_type = kp->ks_type;
+
+ list_create(&ksi->ks_nvlist, sizeof (ks_nvpair_t),
+ offsetof(ks_nvpair_t, nv_next));
+
+ SAVE_HRTIME_X(ksi, "crtime", kp->ks_crtime);
+ SAVE_HRTIME_X(ksi, "snaptime", kp->ks_snaptime);
+ if (g_pflg) {
+ SAVE_STRING_X(ksi, "class", kp->ks_class);
+ }
+
+ /* Insert this instance into a sorted list */
+ tmp = list_head(&instances_list);
+ while (tmp != NULL && compare_instances(ksi, tmp) > 0)
+ tmp = list_next(&instances_list, tmp);
+
+ list_insert_before(&instances_list, tmp, ksi);
+
+ /* Read the actual statistics */
+ id = kstat_read(kc, kp, NULL);
+ if (id == -1) {
+#ifdef REPORT_UNKNOWN
+ perror("kstat_read");
+#endif
+ continue;
+ }
+
+ switch (kp->ks_type) {
+ case KSTAT_TYPE_RAW:
+ save_raw(kp, ksi);
+ break;
+ case KSTAT_TYPE_NAMED:
+ save_named(kp, ksi);
+ break;
+ case KSTAT_TYPE_INTR:
+ save_intr(kp, ksi);
+ break;
+ case KSTAT_TYPE_IO:
+ save_io(kp, ksi);
+ break;
+ case KSTAT_TYPE_TIMER:
+ save_timer(kp, ksi);
+ break;
+ default:
+ assert(B_FALSE); /* Invalid type */
+ break;
+ }
+ }
+}
+
+/*
+ * Print the value of a name-value pair.
+ */
+static void
+ks_value_print(ks_nvpair_t *nvpair)
+{
+ switch (nvpair->data_type) {
+ case KSTAT_DATA_CHAR:
+ (void) fprintf(stdout, "%s", nvpair->value.c);
+ break;
+ case KSTAT_DATA_INT32:
+ (void) fprintf(stdout, "%d", nvpair->value.i32);
+ break;
+ case KSTAT_DATA_UINT32:
+ (void) fprintf(stdout, "%u", nvpair->value.ui32);
+ break;
+ case KSTAT_DATA_INT64:
+ (void) fprintf(stdout, "%lld", nvpair->value.i64);
+ break;
+ case KSTAT_DATA_UINT64:
+ (void) fprintf(stdout, "%llu", nvpair->value.ui64);
+ break;
+ case KSTAT_DATA_STRING:
+ (void) fprintf(stdout, "%s", KSTAT_NAMED_STR_PTR(nvpair));
+ break;
+ case KSTAT_DATA_HRTIME:
+ if (nvpair->value.ui64 == 0)
+ (void) fprintf(stdout, "0");
+ else
+ (void) fprintf(stdout, "%.9f",
+ nvpair->value.ui64 / 1000000000.0);
+ break;
+ default:
+ assert(B_FALSE);
+ }
+}
+
+/*
+ * Print a single instance.
+ */
+static void
+ks_instance_print(ks_instance_t *ksi, ks_nvpair_t *nvpair)
+{
+ if (g_headerflg) {
+ if (!g_pflg) {
+ (void) fprintf(stdout, DFLT_FMT,
+ ksi->ks_module, ksi->ks_instance,
+ ksi->ks_name, ksi->ks_class);
+ }
+ g_headerflg = B_FALSE;
+ }
+
+ if (g_pflg) {
+ (void) fprintf(stdout, KS_PFMT,
+ ksi->ks_module, ksi->ks_instance,
+ ksi->ks_name, nvpair->name);
+ if (!g_lflg) {
+ (void) putchar(g_cflg ? ':': '\t');
+ ks_value_print(nvpair);
+ }
+ } else {
+ (void) fprintf(stdout, KS_DFMT, nvpair->name);
+ ks_value_print(nvpair);
+ }
+
+ (void) putchar('\n');
+}
+
+/*
+ * Print a single instance in JSON format.
+ */
+static void
+ks_instance_print_json(ks_instance_t *ksi, ks_nvpair_t *nvpair)
+{
+ if (g_headerflg) {
+ (void) fprintf(stdout, JSON_FMT,
+ ksi->ks_module, ksi->ks_instance,
+ ksi->ks_name, ksi->ks_class,
+ ksi->ks_type);
+
+ if (ksi->ks_snaptime == 0)
+ (void) fprintf(stdout, "\t\"snaptime\": 0,\n");
+ else
+ (void) fprintf(stdout, "\t\"snaptime\": %.9f,\n",
+ ksi->ks_snaptime / 1000000000.0);
+
+ (void) fprintf(stdout, "\t\"data\": {\n");
+
+ g_headerflg = B_FALSE;
+ }
+
+ (void) fprintf(stdout, KS_JFMT, nvpair->name);
+ if (nvpair->data_type == KSTAT_DATA_STRING) {
+ (void) putchar('\"');
+ ks_value_print(nvpair);
+ (void) putchar('\"');
+ } else {
+ ks_value_print(nvpair);
+ }
+ if (nvpair != list_tail(&ksi->ks_nvlist))
+ (void) putchar(',');
+
+ (void) putchar('\n');
+}
+
+/*
+ * Print all instances.
+ */
+static void
+ks_instances_print(void)
+{
+ ks_selector_t *selector;
+ ks_instance_t *ksi, *ktmp;
+ ks_nvpair_t *nvpair, *ntmp;
+ void (*ks_print_fn)(ks_instance_t *, ks_nvpair_t *);
+ char *ks_number;
+
+ if (g_timestamp_fmt != NODATE)
+ print_timestamp(g_timestamp_fmt);
+
+ if (g_jflg) {
+ ks_print_fn = &ks_instance_print_json;
+ (void) putchar('[');
+ } else {
+ ks_print_fn = &ks_instance_print;
+ }
+
+ /* Iterate over each selector */
+ selector = list_head(&selector_list);
+ while (selector != NULL) {
+
+ /* Iterate over each instance */
+ for (ksi = list_head(&instances_list); ksi != NULL;
+ ksi = list_next(&instances_list, ksi)) {
+
+ (void) asprintf(&ks_number, "%d", ksi->ks_instance);
+ if (!(ks_match(ksi->ks_module, &selector->ks_module) &&
+ ks_match(ksi->ks_name, &selector->ks_name) &&
+ ks_match(ks_number, &selector->ks_instance) &&
+ ks_match(ksi->ks_class, &g_ks_class))) {
+ free(ks_number);
+ continue;
+ }
+
+ free(ks_number);
+
+ /* Finally iterate over each statistic */
+ g_headerflg = B_TRUE;
+ for (nvpair = list_head(&ksi->ks_nvlist);
+ nvpair != NULL;
+ nvpair = list_next(&ksi->ks_nvlist, nvpair)) {
+ if (!ks_match(nvpair->name,
+ &selector->ks_statistic))
+ continue;
+
+ g_matched = 0;
+ if (!g_qflg)
+ (*ks_print_fn)(ksi, nvpair);
+ }
+
+ if (!g_headerflg) {
+ if (g_jflg) {
+ (void) fprintf(stdout, "\t}\n}");
+ if (ksi != list_tail(&instances_list))
+ (void) putchar(',');
+ } else if (!g_pflg) {
+ (void) putchar('\n');
+ }
+ }
+ }
+
+ selector = list_next(&selector_list, selector);
+ }
+
+ if (g_jflg)
+ (void) fprintf(stdout, "]\n");
+
+ (void) fflush(stdout);
+
+ /* Free the instances list */
+ ksi = list_head(&instances_list);
+ while (ksi != NULL) {
+ nvpair = list_head(&ksi->ks_nvlist);
+ while (nvpair != NULL) {
+ ntmp = nvpair;
+ nvpair = list_next(&ksi->ks_nvlist, nvpair);
+ list_remove(&ksi->ks_nvlist, ntmp);
+ if (ntmp->data_type == KSTAT_DATA_STRING)
+ free(ntmp->value.str.addr.ptr);
+ free(ntmp);
+ }
+
+ ktmp = ksi;
+ ksi = list_next(&instances_list, ksi);
+ list_remove(&instances_list, ktmp);
+ list_destroy(&ktmp->ks_nvlist);
+ free(ktmp);
+ }
+}
+
+static void
+save_cpu_stat(kstat_t *kp, ks_instance_t *ksi)
+{
+ cpu_stat_t *stat;
+ cpu_sysinfo_t *sysinfo;
+ cpu_syswait_t *syswait;
+ cpu_vminfo_t *vminfo;
+
+ stat = (cpu_stat_t *)(kp->ks_data);
+ sysinfo = &stat->cpu_sysinfo;
+ syswait = &stat->cpu_syswait;
+ vminfo = &stat->cpu_vminfo;
+
+ SAVE_UINT32_X(ksi, "idle", sysinfo->cpu[CPU_IDLE]);
+ SAVE_UINT32_X(ksi, "user", sysinfo->cpu[CPU_USER]);
+ SAVE_UINT32_X(ksi, "kernel", sysinfo->cpu[CPU_KERNEL]);
+ SAVE_UINT32_X(ksi, "wait", sysinfo->cpu[CPU_WAIT]);
+ SAVE_UINT32_X(ksi, "wait_io", sysinfo->cpu[W_IO]);
+ SAVE_UINT32_X(ksi, "wait_swap", sysinfo->cpu[W_SWAP]);
+ SAVE_UINT32_X(ksi, "wait_pio", sysinfo->cpu[W_PIO]);
+ SAVE_UINT32(ksi, sysinfo, bread);
+ SAVE_UINT32(ksi, sysinfo, bwrite);
+ SAVE_UINT32(ksi, sysinfo, lread);
+ SAVE_UINT32(ksi, sysinfo, lwrite);
+ SAVE_UINT32(ksi, sysinfo, phread);
+ SAVE_UINT32(ksi, sysinfo, phwrite);
+ SAVE_UINT32(ksi, sysinfo, pswitch);
+ SAVE_UINT32(ksi, sysinfo, trap);
+ SAVE_UINT32(ksi, sysinfo, intr);
+ SAVE_UINT32(ksi, sysinfo, syscall);
+ SAVE_UINT32(ksi, sysinfo, sysread);
+ SAVE_UINT32(ksi, sysinfo, syswrite);
+ SAVE_UINT32(ksi, sysinfo, sysfork);
+ SAVE_UINT32(ksi, sysinfo, sysvfork);
+ SAVE_UINT32(ksi, sysinfo, sysexec);
+ SAVE_UINT32(ksi, sysinfo, readch);
+ SAVE_UINT32(ksi, sysinfo, writech);
+ SAVE_UINT32(ksi, sysinfo, rcvint);
+ SAVE_UINT32(ksi, sysinfo, xmtint);
+ SAVE_UINT32(ksi, sysinfo, mdmint);
+ SAVE_UINT32(ksi, sysinfo, rawch);
+ SAVE_UINT32(ksi, sysinfo, canch);
+ SAVE_UINT32(ksi, sysinfo, outch);
+ SAVE_UINT32(ksi, sysinfo, msg);
+ SAVE_UINT32(ksi, sysinfo, sema);
+ SAVE_UINT32(ksi, sysinfo, namei);
+ SAVE_UINT32(ksi, sysinfo, ufsiget);
+ SAVE_UINT32(ksi, sysinfo, ufsdirblk);
+ SAVE_UINT32(ksi, sysinfo, ufsipage);
+ SAVE_UINT32(ksi, sysinfo, ufsinopage);
+ SAVE_UINT32(ksi, sysinfo, inodeovf);
+ SAVE_UINT32(ksi, sysinfo, fileovf);
+ SAVE_UINT32(ksi, sysinfo, procovf);
+ SAVE_UINT32(ksi, sysinfo, intrthread);
+ SAVE_UINT32(ksi, sysinfo, intrblk);
+ SAVE_UINT32(ksi, sysinfo, idlethread);
+ SAVE_UINT32(ksi, sysinfo, inv_swtch);
+ SAVE_UINT32(ksi, sysinfo, nthreads);
+ SAVE_UINT32(ksi, sysinfo, cpumigrate);
+ SAVE_UINT32(ksi, sysinfo, xcalls);
+ SAVE_UINT32(ksi, sysinfo, mutex_adenters);
+ SAVE_UINT32(ksi, sysinfo, rw_rdfails);
+ SAVE_UINT32(ksi, sysinfo, rw_wrfails);
+ SAVE_UINT32(ksi, sysinfo, modload);
+ SAVE_UINT32(ksi, sysinfo, modunload);
+ SAVE_UINT32(ksi, sysinfo, bawrite);
+#ifdef STATISTICS /* see header file */
+ SAVE_UINT32(ksi, sysinfo, rw_enters);
+ SAVE_UINT32(ksi, sysinfo, win_uo_cnt);
+ SAVE_UINT32(ksi, sysinfo, win_uu_cnt);
+ SAVE_UINT32(ksi, sysinfo, win_so_cnt);
+ SAVE_UINT32(ksi, sysinfo, win_su_cnt);
+ SAVE_UINT32(ksi, sysinfo, win_suo_cnt);
+#endif
+
+ SAVE_INT32(ksi, syswait, iowait);
+ SAVE_INT32(ksi, syswait, swap);
+ SAVE_INT32(ksi, syswait, physio);
+
+ SAVE_UINT32(ksi, vminfo, pgrec);
+ SAVE_UINT32(ksi, vminfo, pgfrec);
+ SAVE_UINT32(ksi, vminfo, pgin);
+ SAVE_UINT32(ksi, vminfo, pgpgin);
+ SAVE_UINT32(ksi, vminfo, pgout);
+ SAVE_UINT32(ksi, vminfo, pgpgout);
+ SAVE_UINT32(ksi, vminfo, swapin);
+ SAVE_UINT32(ksi, vminfo, pgswapin);
+ SAVE_UINT32(ksi, vminfo, swapout);
+ SAVE_UINT32(ksi, vminfo, pgswapout);
+ SAVE_UINT32(ksi, vminfo, zfod);
+ SAVE_UINT32(ksi, vminfo, dfree);
+ SAVE_UINT32(ksi, vminfo, scan);
+ SAVE_UINT32(ksi, vminfo, rev);
+ SAVE_UINT32(ksi, vminfo, hat_fault);
+ SAVE_UINT32(ksi, vminfo, as_fault);
+ SAVE_UINT32(ksi, vminfo, maj_fault);
+ SAVE_UINT32(ksi, vminfo, cow_fault);
+ SAVE_UINT32(ksi, vminfo, prot_fault);
+ SAVE_UINT32(ksi, vminfo, softlock);
+ SAVE_UINT32(ksi, vminfo, kernel_asflt);
+ SAVE_UINT32(ksi, vminfo, pgrrun);
+ SAVE_UINT32(ksi, vminfo, execpgin);
+ SAVE_UINT32(ksi, vminfo, execpgout);
+ SAVE_UINT32(ksi, vminfo, execfree);
+ SAVE_UINT32(ksi, vminfo, anonpgin);
+ SAVE_UINT32(ksi, vminfo, anonpgout);
+ SAVE_UINT32(ksi, vminfo, anonfree);
+ SAVE_UINT32(ksi, vminfo, fspgin);
+ SAVE_UINT32(ksi, vminfo, fspgout);
+ SAVE_UINT32(ksi, vminfo, fsfree);
+}
+
+static void
+save_var(kstat_t *kp, ks_instance_t *ksi)
+{
+ struct var *var = (struct var *)(kp->ks_data);
+
+ assert(kp->ks_data_size == sizeof (struct var));
+
+ SAVE_INT32(ksi, var, v_buf);
+ SAVE_INT32(ksi, var, v_call);
+ SAVE_INT32(ksi, var, v_proc);
+ SAVE_INT32(ksi, var, v_maxupttl);
+ SAVE_INT32(ksi, var, v_nglobpris);
+ SAVE_INT32(ksi, var, v_maxsyspri);
+ SAVE_INT32(ksi, var, v_clist);
+ SAVE_INT32(ksi, var, v_maxup);
+ SAVE_INT32(ksi, var, v_hbuf);
+ SAVE_INT32(ksi, var, v_hmask);
+ SAVE_INT32(ksi, var, v_pbuf);
+ SAVE_INT32(ksi, var, v_sptmap);
+ SAVE_INT32(ksi, var, v_maxpmem);
+ SAVE_INT32(ksi, var, v_autoup);
+ SAVE_INT32(ksi, var, v_bufhwm);
+}
+
+static void
+save_ncstats(kstat_t *kp, ks_instance_t *ksi)
+{
+ struct ncstats *ncstats = (struct ncstats *)(kp->ks_data);
+
+ assert(kp->ks_data_size == sizeof (struct ncstats));
+
+ SAVE_INT32(ksi, ncstats, hits);
+ SAVE_INT32(ksi, ncstats, misses);
+ SAVE_INT32(ksi, ncstats, enters);
+ SAVE_INT32(ksi, ncstats, dbl_enters);
+ SAVE_INT32(ksi, ncstats, long_enter);
+ SAVE_INT32(ksi, ncstats, long_look);
+ SAVE_INT32(ksi, ncstats, move_to_front);
+ SAVE_INT32(ksi, ncstats, purges);
+}
+
+static void
+save_sysinfo(kstat_t *kp, ks_instance_t *ksi)
+{
+ sysinfo_t *sysinfo = (sysinfo_t *)(kp->ks_data);
+
+ assert(kp->ks_data_size == sizeof (sysinfo_t));
+
+ SAVE_UINT32(ksi, sysinfo, updates);
+ SAVE_UINT32(ksi, sysinfo, runque);
+ SAVE_UINT32(ksi, sysinfo, runocc);
+ SAVE_UINT32(ksi, sysinfo, swpque);
+ SAVE_UINT32(ksi, sysinfo, swpocc);
+ SAVE_UINT32(ksi, sysinfo, waiting);
+}
+
+static void
+save_vminfo(kstat_t *kp, ks_instance_t *ksi)
+{
+ vminfo_t *vminfo = (vminfo_t *)(kp->ks_data);
+
+ assert(kp->ks_data_size == sizeof (vminfo_t));
+
+ SAVE_UINT64(ksi, vminfo, freemem);
+ SAVE_UINT64(ksi, vminfo, swap_resv);
+ SAVE_UINT64(ksi, vminfo, swap_alloc);
+ SAVE_UINT64(ksi, vminfo, swap_avail);
+ SAVE_UINT64(ksi, vminfo, swap_free);
+ SAVE_UINT64(ksi, vminfo, updates);
+}
+
+static void
+save_nfs(kstat_t *kp, ks_instance_t *ksi)
+{
+ struct mntinfo_kstat *mntinfo = (struct mntinfo_kstat *)(kp->ks_data);
+
+ assert(kp->ks_data_size == sizeof (struct mntinfo_kstat));
+
+ SAVE_STRING(ksi, mntinfo, mik_proto);
+ SAVE_UINT32(ksi, mntinfo, mik_vers);
+ SAVE_UINT32(ksi, mntinfo, mik_flags);
+ SAVE_UINT32(ksi, mntinfo, mik_secmod);
+ SAVE_UINT32(ksi, mntinfo, mik_curread);
+ SAVE_UINT32(ksi, mntinfo, mik_curwrite);
+ SAVE_INT32(ksi, mntinfo, mik_timeo);
+ SAVE_INT32(ksi, mntinfo, mik_retrans);
+ SAVE_UINT32(ksi, mntinfo, mik_acregmin);
+ SAVE_UINT32(ksi, mntinfo, mik_acregmax);
+ SAVE_UINT32(ksi, mntinfo, mik_acdirmin);
+ SAVE_UINT32(ksi, mntinfo, mik_acdirmax);
+ SAVE_UINT32_X(ksi, "lookup_srtt", mntinfo->mik_timers[0].srtt);
+ SAVE_UINT32_X(ksi, "lookup_deviate", mntinfo->mik_timers[0].deviate);
+ SAVE_UINT32_X(ksi, "lookup_rtxcur", mntinfo->mik_timers[0].rtxcur);
+ SAVE_UINT32_X(ksi, "read_srtt", mntinfo->mik_timers[1].srtt);
+ SAVE_UINT32_X(ksi, "read_deviate", mntinfo->mik_timers[1].deviate);
+ SAVE_UINT32_X(ksi, "read_rtxcur", mntinfo->mik_timers[1].rtxcur);
+ SAVE_UINT32_X(ksi, "write_srtt", mntinfo->mik_timers[2].srtt);
+ SAVE_UINT32_X(ksi, "write_deviate", mntinfo->mik_timers[2].deviate);
+ SAVE_UINT32_X(ksi, "write_rtxcur", mntinfo->mik_timers[2].rtxcur);
+ SAVE_UINT32(ksi, mntinfo, mik_noresponse);
+ SAVE_UINT32(ksi, mntinfo, mik_failover);
+ SAVE_UINT32(ksi, mntinfo, mik_remap);
+ SAVE_STRING(ksi, mntinfo, mik_curserver);
+}
+
+#ifdef __sparc
+static void
+save_sfmmu_global_stat(kstat_t *kp, ks_instance_t *ksi)
+{
+ struct sfmmu_global_stat *sfmmug =
+ (struct sfmmu_global_stat *)(kp->ks_data);
+
+ assert(kp->ks_data_size == sizeof (struct sfmmu_global_stat));
+
+ SAVE_INT32(ksi, sfmmug, sf_tsb_exceptions);
+ SAVE_INT32(ksi, sfmmug, sf_tsb_raise_exception);
+ SAVE_INT32(ksi, sfmmug, sf_pagefaults);
+ SAVE_INT32(ksi, sfmmug, sf_uhash_searches);
+ SAVE_INT32(ksi, sfmmug, sf_uhash_links);
+ SAVE_INT32(ksi, sfmmug, sf_khash_searches);
+ SAVE_INT32(ksi, sfmmug, sf_khash_links);
+ SAVE_INT32(ksi, sfmmug, sf_swapout);
+ SAVE_INT32(ksi, sfmmug, sf_tsb_alloc);
+ SAVE_INT32(ksi, sfmmug, sf_tsb_allocfail);
+ SAVE_INT32(ksi, sfmmug, sf_tsb_sectsb_create);
+ SAVE_INT32(ksi, sfmmug, sf_scd_1sttsb_alloc);
+ SAVE_INT32(ksi, sfmmug, sf_scd_2ndtsb_alloc);
+ SAVE_INT32(ksi, sfmmug, sf_scd_1sttsb_allocfail);
+ SAVE_INT32(ksi, sfmmug, sf_scd_2ndtsb_allocfail);
+ SAVE_INT32(ksi, sfmmug, sf_tteload8k);
+ SAVE_INT32(ksi, sfmmug, sf_tteload64k);
+ SAVE_INT32(ksi, sfmmug, sf_tteload512k);
+ SAVE_INT32(ksi, sfmmug, sf_tteload4m);
+ SAVE_INT32(ksi, sfmmug, sf_tteload32m);
+ SAVE_INT32(ksi, sfmmug, sf_tteload256m);
+ SAVE_INT32(ksi, sfmmug, sf_tsb_load8k);
+ SAVE_INT32(ksi, sfmmug, sf_tsb_load4m);
+ SAVE_INT32(ksi, sfmmug, sf_hblk_hit);
+ SAVE_INT32(ksi, sfmmug, sf_hblk8_ncreate);
+ SAVE_INT32(ksi, sfmmug, sf_hblk8_nalloc);
+ SAVE_INT32(ksi, sfmmug, sf_hblk1_ncreate);
+ SAVE_INT32(ksi, sfmmug, sf_hblk1_nalloc);
+ SAVE_INT32(ksi, sfmmug, sf_hblk_slab_cnt);
+ SAVE_INT32(ksi, sfmmug, sf_hblk_reserve_cnt);
+ SAVE_INT32(ksi, sfmmug, sf_hblk_recurse_cnt);
+ SAVE_INT32(ksi, sfmmug, sf_hblk_reserve_hit);
+ SAVE_INT32(ksi, sfmmug, sf_get_free_success);
+ SAVE_INT32(ksi, sfmmug, sf_get_free_throttle);
+ SAVE_INT32(ksi, sfmmug, sf_get_free_fail);
+ SAVE_INT32(ksi, sfmmug, sf_put_free_success);
+ SAVE_INT32(ksi, sfmmug, sf_put_free_fail);
+ SAVE_INT32(ksi, sfmmug, sf_pgcolor_conflict);
+ SAVE_INT32(ksi, sfmmug, sf_uncache_conflict);
+ SAVE_INT32(ksi, sfmmug, sf_unload_conflict);
+ SAVE_INT32(ksi, sfmmug, sf_ism_uncache);
+ SAVE_INT32(ksi, sfmmug, sf_ism_recache);
+ SAVE_INT32(ksi, sfmmug, sf_recache);
+ SAVE_INT32(ksi, sfmmug, sf_steal_count);
+ SAVE_INT32(ksi, sfmmug, sf_pagesync);
+ SAVE_INT32(ksi, sfmmug, sf_clrwrt);
+ SAVE_INT32(ksi, sfmmug, sf_pagesync_invalid);
+ SAVE_INT32(ksi, sfmmug, sf_kernel_xcalls);
+ SAVE_INT32(ksi, sfmmug, sf_user_xcalls);
+ SAVE_INT32(ksi, sfmmug, sf_tsb_grow);
+ SAVE_INT32(ksi, sfmmug, sf_tsb_shrink);
+ SAVE_INT32(ksi, sfmmug, sf_tsb_resize_failures);
+ SAVE_INT32(ksi, sfmmug, sf_tsb_reloc);
+ SAVE_INT32(ksi, sfmmug, sf_user_vtop);
+ SAVE_INT32(ksi, sfmmug, sf_ctx_inv);
+ SAVE_INT32(ksi, sfmmug, sf_tlb_reprog_pgsz);
+ SAVE_INT32(ksi, sfmmug, sf_region_remap_demap);
+ SAVE_INT32(ksi, sfmmug, sf_create_scd);
+ SAVE_INT32(ksi, sfmmug, sf_join_scd);
+ SAVE_INT32(ksi, sfmmug, sf_leave_scd);
+ SAVE_INT32(ksi, sfmmug, sf_destroy_scd);
+}
+#endif
+
+#ifdef __sparc
+static void
+save_sfmmu_tsbsize_stat(kstat_t *kp, ks_instance_t *ksi)
+{
+ struct sfmmu_tsbsize_stat *sfmmut;
+
+ assert(kp->ks_data_size == sizeof (struct sfmmu_tsbsize_stat));
+ sfmmut = (struct sfmmu_tsbsize_stat *)(kp->ks_data);
+
+ SAVE_INT32(ksi, sfmmut, sf_tsbsz_8k);
+ SAVE_INT32(ksi, sfmmut, sf_tsbsz_16k);
+ SAVE_INT32(ksi, sfmmut, sf_tsbsz_32k);
+ SAVE_INT32(ksi, sfmmut, sf_tsbsz_64k);
+ SAVE_INT32(ksi, sfmmut, sf_tsbsz_128k);
+ SAVE_INT32(ksi, sfmmut, sf_tsbsz_256k);
+ SAVE_INT32(ksi, sfmmut, sf_tsbsz_512k);
+ SAVE_INT32(ksi, sfmmut, sf_tsbsz_1m);
+ SAVE_INT32(ksi, sfmmut, sf_tsbsz_2m);
+ SAVE_INT32(ksi, sfmmut, sf_tsbsz_4m);
+}
+#endif
+
+#ifdef __sparc
+static void
+save_simmstat(kstat_t *kp, ks_instance_t *ksi)
+{
+ uchar_t *simmstat;
+ char *simm_buf;
+ char *list = NULL;
+ int i;
+
+ assert(kp->ks_data_size == sizeof (uchar_t) * SIMM_COUNT);
+
+ for (i = 0, simmstat = (uchar_t *)(kp->ks_data); i < SIMM_COUNT - 1;
+ i++, simmstat++) {
+ if (list == NULL) {
+ (void) asprintf(&simm_buf, "%d,", *simmstat);
+ } else {
+ (void) asprintf(&simm_buf, "%s%d,", list, *simmstat);
+ free(list);
+ }
+ list = simm_buf;
+ }
+
+ (void) asprintf(&simm_buf, "%s%d", list, *simmstat);
+ SAVE_STRING_X(ksi, "status", simm_buf);
+ free(list);
+ free(simm_buf);
+}
+#endif
+
+#ifdef __sparc
+/*
+ * Helper function for save_temperature().
+ */
+static char *
+short_array_to_string(short *shortp, int len)
+{
+ char *list = NULL;
+ char *list_buf;
+
+ for (; len > 1; len--, shortp++) {
+ if (list == NULL) {
+ (void) asprintf(&list_buf, "%hd,", *shortp);
+ } else {
+ (void) asprintf(&list_buf, "%s%hd,", list, *shortp);
+ free(list);
+ }
+ list = list_buf;
+ }
+
+ (void) asprintf(&list_buf, "%s%hd", list, *shortp);
+ free(list);
+ return (list_buf);
+}
+
+static void
+save_temperature(kstat_t *kp, ks_instance_t *ksi)
+{
+ struct temp_stats *temps = (struct temp_stats *)(kp->ks_data);
+ char *buf;
+
+ assert(kp->ks_data_size == sizeof (struct temp_stats));
+
+ SAVE_UINT32(ksi, temps, index);
+
+ buf = short_array_to_string(temps->l1, L1_SZ);
+ SAVE_STRING_X(ksi, "l1", buf);
+ free(buf);
+
+ buf = short_array_to_string(temps->l2, L2_SZ);
+ SAVE_STRING_X(ksi, "l2", buf);
+ free(buf);
+
+ buf = short_array_to_string(temps->l3, L3_SZ);
+ SAVE_STRING_X(ksi, "l3", buf);
+ free(buf);
+
+ buf = short_array_to_string(temps->l4, L4_SZ);
+ SAVE_STRING_X(ksi, "l4", buf);
+ free(buf);
+
+ buf = short_array_to_string(temps->l5, L5_SZ);
+ SAVE_STRING_X(ksi, "l5", buf);
+ free(buf);
+
+ SAVE_INT32(ksi, temps, max);
+ SAVE_INT32(ksi, temps, min);
+ SAVE_INT32(ksi, temps, state);
+ SAVE_INT32(ksi, temps, temp_cnt);
+ SAVE_INT32(ksi, temps, shutdown_cnt);
+ SAVE_INT32(ksi, temps, version);
+ SAVE_INT32(ksi, temps, trend);
+ SAVE_INT32(ksi, temps, override);
+}
+#endif
+
+#ifdef __sparc
+static void
+save_temp_over(kstat_t *kp, ks_instance_t *ksi)
+{
+ short *sh = (short *)(kp->ks_data);
+ char *value;
+
+ assert(kp->ks_data_size == sizeof (short));
+
+ (void) asprintf(&value, "%hu", *sh);
+ SAVE_STRING_X(ksi, "override", value);
+ free(value);
+}
+#endif
+
+#ifdef __sparc
+static void
+save_ps_shadow(kstat_t *kp, ks_instance_t *ksi)
+{
+ uchar_t *uchar = (uchar_t *)(kp->ks_data);
+
+ assert(kp->ks_data_size == SYS_PS_COUNT);
+
+ SAVE_CHAR_X(ksi, "core_0", *uchar++);
+ SAVE_CHAR_X(ksi, "core_1", *uchar++);
+ SAVE_CHAR_X(ksi, "core_2", *uchar++);
+ SAVE_CHAR_X(ksi, "core_3", *uchar++);
+ SAVE_CHAR_X(ksi, "core_4", *uchar++);
+ SAVE_CHAR_X(ksi, "core_5", *uchar++);
+ SAVE_CHAR_X(ksi, "core_6", *uchar++);
+ SAVE_CHAR_X(ksi, "core_7", *uchar++);
+ SAVE_CHAR_X(ksi, "pps_0", *uchar++);
+ SAVE_CHAR_X(ksi, "clk_33", *uchar++);
+ SAVE_CHAR_X(ksi, "clk_50", *uchar++);
+ SAVE_CHAR_X(ksi, "v5_p", *uchar++);
+ SAVE_CHAR_X(ksi, "v12_p", *uchar++);
+ SAVE_CHAR_X(ksi, "v5_aux", *uchar++);
+ SAVE_CHAR_X(ksi, "v5_p_pch", *uchar++);
+ SAVE_CHAR_X(ksi, "v12_p_pch", *uchar++);
+ SAVE_CHAR_X(ksi, "v3_pch", *uchar++);
+ SAVE_CHAR_X(ksi, "v5_pch", *uchar++);
+ SAVE_CHAR_X(ksi, "p_fan", *uchar++);
+}
+#endif
+
+#ifdef __sparc
+static void
+save_fault_list(kstat_t *kp, ks_instance_t *ksi)
+{
+ struct ft_list *fault;
+ char name[KSTAT_STRLEN + 7];
+ int i;
+
+ for (i = 1, fault = (struct ft_list *)(kp->ks_data);
+ i <= 999999 && i <= kp->ks_data_size / sizeof (struct ft_list);
+ i++, fault++) {
+ (void) snprintf(name, sizeof (name), "unit_%d", i);
+ SAVE_INT32_X(ksi, name, fault->unit);
+ (void) snprintf(name, sizeof (name), "type_%d", i);
+ SAVE_INT32_X(ksi, name, fault->type);
+ (void) snprintf(name, sizeof (name), "fclass_%d", i);
+ SAVE_INT32_X(ksi, name, fault->fclass);
+ (void) snprintf(name, sizeof (name), "create_time_%d", i);
+ SAVE_HRTIME_X(ksi, name, fault->create_time);
+ (void) snprintf(name, sizeof (name), "msg_%d", i);
+ SAVE_STRING_X(ksi, name, fault->msg);
+ }
+}
+#endif
+
+static void
+save_named(kstat_t *kp, ks_instance_t *ksi)
+{
+ kstat_named_t *knp;
+ int n;
+
+ for (n = kp->ks_ndata, knp = KSTAT_NAMED_PTR(kp); n > 0; n--, knp++) {
+ switch (knp->data_type) {
+ case KSTAT_DATA_CHAR:
+ nvpair_insert(ksi, knp->name,
+ (ks_value_t *)&knp->value, KSTAT_DATA_CHAR);
+ break;
+ case KSTAT_DATA_INT32:
+ nvpair_insert(ksi, knp->name,
+ (ks_value_t *)&knp->value, KSTAT_DATA_INT32);
+ break;
+ case KSTAT_DATA_UINT32:
+ nvpair_insert(ksi, knp->name,
+ (ks_value_t *)&knp->value, KSTAT_DATA_UINT32);
+ break;
+ case KSTAT_DATA_INT64:
+ nvpair_insert(ksi, knp->name,
+ (ks_value_t *)&knp->value, KSTAT_DATA_INT64);
+ break;
+ case KSTAT_DATA_UINT64:
+ nvpair_insert(ksi, knp->name,
+ (ks_value_t *)&knp->value, KSTAT_DATA_UINT64);
+ break;
+ case KSTAT_DATA_STRING:
+ SAVE_STRING_X(ksi, knp->name, KSTAT_NAMED_STR_PTR(knp));
+ break;
+ default:
+ assert(B_FALSE); /* Invalid data type */
+ break;
+ }
+ }
+}
+
+static void
+save_intr(kstat_t *kp, ks_instance_t *ksi)
+{
+ kstat_intr_t *intr = KSTAT_INTR_PTR(kp);
+ char *intr_names[] = {"hard", "soft", "watchdog", "spurious",
+ "multiple_service"};
+ int n;
+
+ for (n = 0; n < KSTAT_NUM_INTRS; n++)
+ SAVE_UINT32_X(ksi, intr_names[n], intr->intrs[n]);
+}
+
+static void
+save_io(kstat_t *kp, ks_instance_t *ksi)
+{
+ kstat_io_t *ksio = KSTAT_IO_PTR(kp);
+
+ SAVE_UINT64(ksi, ksio, nread);
+ SAVE_UINT64(ksi, ksio, nwritten);
+ SAVE_UINT32(ksi, ksio, reads);
+ SAVE_UINT32(ksi, ksio, writes);
+ SAVE_HRTIME(ksi, ksio, wtime);
+ SAVE_HRTIME(ksi, ksio, wlentime);
+ SAVE_HRTIME(ksi, ksio, wlastupdate);
+ SAVE_HRTIME(ksi, ksio, rtime);
+ SAVE_HRTIME(ksi, ksio, rlentime);
+ SAVE_HRTIME(ksi, ksio, rlastupdate);
+ SAVE_UINT32(ksi, ksio, wcnt);
+ SAVE_UINT32(ksi, ksio, rcnt);
+}
+
+static void
+save_timer(kstat_t *kp, ks_instance_t *ksi)
+{
+ kstat_timer_t *ktimer = KSTAT_TIMER_PTR(kp);
+
+ SAVE_STRING(ksi, ktimer, name);
+ SAVE_UINT64(ksi, ktimer, num_events);
+ SAVE_HRTIME(ksi, ktimer, elapsed_time);
+ SAVE_HRTIME(ksi, ktimer, min_time);
+ SAVE_HRTIME(ksi, ktimer, max_time);
+ SAVE_HRTIME(ksi, ktimer, start_time);
+ SAVE_HRTIME(ksi, ktimer, stop_time);
+}
diff --git a/usr/src/cmd/stat/kstat/kstat.h b/usr/src/cmd/stat/kstat/kstat.h
new file mode 100644
index 0000000000..dcad921737
--- /dev/null
+++ b/usr/src/cmd/stat/kstat/kstat.h
@@ -0,0 +1,269 @@
+/*
+ * CDDL HEADER START
+ *
+ * The contents of this file are subject to the terms of the
+ * Common Development and Distribution License (the "License").
+ * You may not use this file except in compliance with the License.
+ *
+ * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+ * or http://www.opensolaris.org/os/licensing.
+ * See the License for the specific language governing permissions
+ * and limitations under the License.
+ *
+ * When distributing Covered Code, include this CDDL HEADER in each
+ * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+ * If applicable, add the following below this CDDL HEADER, with the
+ * fields enclosed by brackets "[]" replaced with your own identifying
+ * information: Portions Copyright [yyyy] [name of copyright owner]
+ *
+ * CDDL HEADER END
+ */
+/*
+ * Copyright 2006 Sun Microsystems, Inc. All rights reserved.
+ * Copyright 2013 David Hoeppner. All rights reserved.
+ * Copyright 2013 Nexenta Systems, Inc. All rights reserved.
+ */
+
+#ifndef _STAT_KSTAT_H
+#define _STAT_KSTAT_H
+
+/*
+ * Structures needed by the kstat reader functions.
+ */
+#include <sys/var.h>
+#include <sys/utsname.h>
+#include <sys/sysinfo.h>
+#include <sys/flock.h>
+#include <sys/dnlc.h>
+#include <regex.h>
+#include <nfs/nfs.h>
+#include <nfs/nfs_clnt.h>
+
+#ifdef __sparc
+#include <vm/hat_sfmmu.h>
+#include <sys/simmstat.h>
+#include <sys/sysctrl.h>
+#include <sys/fhc.h>
+#endif
+
+#define KSTAT_DATA_HRTIME (KSTAT_DATA_STRING + 1)
+
+typedef union ks_value {
+ char c[16];
+ int32_t i32;
+ uint32_t ui32;
+ struct {
+ union {
+ char *ptr;
+ char __pad[8];
+ } addr;
+ uint32_t len;
+ } str;
+
+ int64_t i64;
+ uint64_t ui64;
+} ks_value_t;
+
+#define SAVE_HRTIME(I, S, N) \
+{ \
+ ks_value_t v; \
+ v.ui64 = S->N; \
+ nvpair_insert(I, #N, &v, KSTAT_DATA_UINT64); \
+}
+
+#define SAVE_INT32(I, S, N) \
+{ \
+ ks_value_t v; \
+ v.i32 = S->N; \
+ nvpair_insert(I, #N, &v, KSTAT_DATA_INT32); \
+}
+
+#define SAVE_UINT32(I, S, N) \
+{ \
+ ks_value_t v; \
+ v.ui32 = S->N; \
+ nvpair_insert(I, #N, &v, KSTAT_DATA_UINT32); \
+}
+
+#define SAVE_INT64(I, S, N) \
+{ \
+ ks_value_t v; \
+ v.i64 = S->N; \
+ nvpair_insert(I, #N, &v, KSTAT_DATA_INT64); \
+}
+
+#define SAVE_UINT64(I, S, N) \
+{ \
+ ks_value_t v; \
+ v.ui64 = S->N; \
+ nvpair_insert(I, #N, &v, KSTAT_DATA_UINT64); \
+}
+
+/*
+ * We dont want const "strings" because we free
+ * the instances later.
+ */
+#define SAVE_STRING(I, S, N) \
+{ \
+ ks_value_t v; \
+ v.str.addr.ptr = safe_strdup(S->N); \
+ v.str.len = strlen(S->N); \
+ nvpair_insert(I, #N, &v, KSTAT_DATA_STRING); \
+}
+
+#define SAVE_HRTIME_X(I, N, V) \
+{ \
+ ks_value_t v; \
+ v.ui64 = V; \
+ nvpair_insert(I, N, &v, KSTAT_DATA_HRTIME); \
+}
+
+#define SAVE_INT32_X(I, N, V) \
+{ \
+ ks_value_t v; \
+ v.i32 = V; \
+ nvpair_insert(I, N, &v, KSTAT_DATA_INT32); \
+}
+
+#define SAVE_UINT32_X(I, N, V) \
+{ \
+ ks_value_t v; \
+ v.ui32 = V; \
+ nvpair_insert(I, N, &v, KSTAT_DATA_UINT32); \
+}
+
+#define SAVE_UINT64_X(I, N, V) \
+{ \
+ ks_value_t v; \
+ v.ui64 = V; \
+ nvpair_insert(I, N, &v, KSTAT_DATA_UINT64); \
+}
+
+#define SAVE_STRING_X(I, N, V) \
+{ \
+ ks_value_t v; \
+ v.str.addr.ptr = safe_strdup(V); \
+ v.str.len = strlen(V); \
+ nvpair_insert(I, N, &v, KSTAT_DATA_STRING); \
+}
+
+#define SAVE_CHAR_X(I, N, V) \
+{ \
+ ks_value_t v; \
+ (void) asprintf(&v.str.addr.ptr, "%c", V); \
+ v.str.len = 1; \
+ nvpair_insert(I, N, &v, KSTAT_DATA_STRING); \
+}
+
+#define DFLT_FMT \
+ "module: %-30.30s instance: %-6d\n" \
+ "name: %-30.30s class: %-.30s\n"
+
+#define JSON_FMT \
+ "{\n\t\"module\": \"%s\",\n" \
+ "\t\"instance\": %d,\n" \
+ "\t\"name\": \"%s\",\n" \
+ "\t\"class\": \"%s\",\n" \
+ "\t\"type\": %d,\n"
+
+#define KS_DFMT "\t%-30s "
+#define KS_JFMT "\t\t\"%s\": "
+#define KS_PFMT "%s:%d:%s:%s"
+
+typedef struct ks_instance {
+ list_node_t ks_next;
+ char ks_name[KSTAT_STRLEN];
+ char ks_module[KSTAT_STRLEN];
+ char ks_class[KSTAT_STRLEN];
+ int ks_instance;
+ uchar_t ks_type;
+ hrtime_t ks_snaptime;
+ list_t ks_nvlist;
+} ks_instance_t;
+
+typedef struct ks_nvpair {
+ list_node_t nv_next;
+ char name[KSTAT_STRLEN];
+ uchar_t data_type;
+ ks_value_t value;
+} ks_nvpair_t;
+
+typedef struct ks_pattern {
+ char *pstr;
+ regex_t preg;
+} ks_pattern_t;
+
+typedef struct ks_selector {
+ list_node_t ks_next;
+ ks_pattern_t ks_module;
+ ks_pattern_t ks_instance;
+ ks_pattern_t ks_name;
+ ks_pattern_t ks_statistic;
+} ks_selector_t;
+
+static void usage(void);
+static int compare_instances(ks_instance_t *, ks_instance_t *);
+static void nvpair_insert(ks_instance_t *, char *, ks_value_t *, uchar_t);
+static boolean_t ks_match(const char *, ks_pattern_t *);
+static ks_selector_t *new_selector(void);
+static void ks_instances_read(kstat_ctl_t *);
+static void ks_value_print(ks_nvpair_t *);
+static void ks_instance_print(ks_instance_t *, ks_nvpair_t *);
+static void ks_instances_print(void);
+static char *ks_safe_strdup(char *);
+static void ks_sleep_until(hrtime_t *, hrtime_t, int, int *);
+
+/* Raw kstat readers */
+static void save_cpu_stat(kstat_t *, ks_instance_t *);
+static void save_var(kstat_t *, ks_instance_t *);
+static void save_ncstats(kstat_t *, ks_instance_t *);
+static void save_sysinfo(kstat_t *, ks_instance_t *);
+static void save_vminfo(kstat_t *, ks_instance_t *);
+static void save_nfs(kstat_t *, ks_instance_t *);
+#ifdef __sparc
+static void save_sfmmu_global_stat(kstat_t *, ks_instance_t *);
+static void save_sfmmu_tsbsize_stat(kstat_t *, ks_instance_t *);
+static void save_simmstat(kstat_t *, ks_instance_t *);
+/* Helper function for save_temperature() */
+static char *short_array_to_string(short *, int);
+static void save_temperature(kstat_t *, ks_instance_t *);
+static void save_temp_over(kstat_t *, ks_instance_t *);
+static void save_ps_shadow(kstat_t *, ks_instance_t *);
+static void save_fault_list(kstat_t *, ks_instance_t *);
+#endif
+
+/* Named kstat readers */
+static void save_named(kstat_t *, ks_instance_t *);
+static void save_intr(kstat_t *, ks_instance_t *);
+static void save_io(kstat_t *, ks_instance_t *);
+static void save_timer(kstat_t *, ks_instance_t *);
+
+/* Typedef for raw kstat reader functions */
+typedef void (*kstat_raw_reader_t)(kstat_t *, ks_instance_t *);
+
+static struct {
+ kstat_raw_reader_t fn;
+ char *name;
+} ks_raw_lookup[] = {
+ /* Function name kstat name */
+ {save_cpu_stat, "cpu_stat:cpu_stat"},
+ {save_var, "unix:var"},
+ {save_ncstats, "unix:ncstats"},
+ {save_sysinfo, "unix:sysinfo"},
+ {save_vminfo, "unix:vminfo"},
+ {save_nfs, "nfs:mntinfo"},
+#ifdef __sparc
+ {save_sfmmu_global_stat, "unix:sfmmu_global_stat"},
+ {save_sfmmu_tsbsize_stat, "unix:sfmmu_tsbsize_stat"},
+ {save_simmstat, "unix:simm-status"},
+ {save_temperature, "unix:temperature"},
+ {save_temp_over, "unix:temperature override"},
+ {save_ps_shadow, "unix:ps_shadow"},
+ {save_fault_list, "unix:fault_list"},
+#endif
+ {NULL, NULL},
+};
+
+static kstat_raw_reader_t lookup_raw_kstat_fn(char *, char *);
+
+#endif /* _STAT_KSTAT_H */
diff --git a/usr/src/cmd/tar/tar.c b/usr/src/cmd/tar/tar.c
index dfcd3fb593..9e2aef3bee 100644
--- a/usr/src/cmd/tar/tar.c
+++ b/usr/src/cmd/tar/tar.c
@@ -21,6 +21,7 @@
/*
* Copyright (c) 1988, 2010, Oracle and/or its affiliates. All rights reserved.
* Copyright 2012 Milan Jurik. All rights reserved.
+ * Copyright (c) 2013, Joyent, Inc. All rights reserved.
*/
/* Copyright (c) 1983, 1984, 1985, 1986, 1987, 1988, 1989 AT&T */
diff --git a/usr/src/cmd/zdb/zdb.c b/usr/src/cmd/zdb/zdb.c
index e636a31a3e..2234a71528 100644
--- a/usr/src/cmd/zdb/zdb.c
+++ b/usr/src/cmd/zdb/zdb.c
@@ -571,7 +571,7 @@ static void
dump_metaslab_stats(metaslab_t *msp)
{
char maxbuf[32];
- space_map_t *sm = &msp->ms_map;
+ space_map_t *sm = msp->ms_map;
avl_tree_t *t = sm->sm_pp_root;
int free_pct = sm->sm_space * 100 / sm->sm_size;
@@ -587,7 +587,7 @@ dump_metaslab(metaslab_t *msp)
{
vdev_t *vd = msp->ms_group->mg_vd;
spa_t *spa = vd->vdev_spa;
- space_map_t *sm = &msp->ms_map;
+ space_map_t *sm = msp->ms_map;
space_map_obj_t *smo = &msp->ms_smo;
char freebuf[32];
@@ -1016,7 +1016,7 @@ visit_indirect(spa_t *spa, const dnode_phys_t *dnp,
arc_buf_t *buf;
uint64_t fill = 0;
- err = arc_read_nolock(NULL, spa, bp, arc_getbuf_func, &buf,
+ err = arc_read(NULL, spa, bp, arc_getbuf_func, &buf,
ZIO_PRIORITY_ASYNC_READ, ZIO_FLAG_CANFAIL, &flags, zb);
if (err)
return (err);
@@ -2073,9 +2073,8 @@ zdb_blkptr_done(zio_t *zio)
mutex_exit(&spa->spa_scrub_lock);
}
-/* ARGSUSED */
static int
-zdb_blkptr_cb(spa_t *spa, zilog_t *zilog, const blkptr_t *bp, arc_buf_t *pbuf,
+zdb_blkptr_cb(spa_t *spa, zilog_t *zilog, const blkptr_t *bp,
const zbookmark_t *zb, const dnode_phys_t *dnp, void *arg)
{
zdb_cb_t *zcb = arg;
@@ -2217,11 +2216,11 @@ zdb_leak_init(spa_t *spa, zdb_cb_t *zcb)
for (int m = 0; m < vd->vdev_ms_count; m++) {
metaslab_t *msp = vd->vdev_ms[m];
mutex_enter(&msp->ms_lock);
- space_map_unload(&msp->ms_map);
- VERIFY(space_map_load(&msp->ms_map,
+ space_map_unload(msp->ms_map);
+ VERIFY(space_map_load(msp->ms_map,
&zdb_space_map_ops, SM_ALLOC, &msp->ms_smo,
spa->spa_meta_objset) == 0);
- msp->ms_map.sm_ppd = vd;
+ msp->ms_map->sm_ppd = vd;
mutex_exit(&msp->ms_lock);
}
}
@@ -2244,7 +2243,7 @@ zdb_leak_fini(spa_t *spa)
for (int m = 0; m < vd->vdev_ms_count; m++) {
metaslab_t *msp = vd->vdev_ms[m];
mutex_enter(&msp->ms_lock);
- space_map_unload(&msp->ms_map);
+ space_map_unload(msp->ms_map);
mutex_exit(&msp->ms_lock);
}
}
@@ -2476,7 +2475,7 @@ typedef struct zdb_ddt_entry {
/* ARGSUSED */
static int
zdb_ddt_add_cb(spa_t *spa, zilog_t *zilog, const blkptr_t *bp,
- arc_buf_t *pbuf, const zbookmark_t *zb, const dnode_phys_t *dnp, void *arg)
+ const zbookmark_t *zb, const dnode_phys_t *dnp, void *arg)
{
avl_tree_t *t = arg;
avl_index_t where;
diff --git a/usr/src/cmd/zfs/zfs_main.c b/usr/src/cmd/zfs/zfs_main.c
index b32b5ab865..f41f427b59 100644
--- a/usr/src/cmd/zfs/zfs_main.c
+++ b/usr/src/cmd/zfs/zfs_main.c
@@ -791,10 +791,12 @@ zfs_do_create(int argc, char **argv)
if (type == ZFS_TYPE_VOLUME && !noreserve) {
zpool_handle_t *zpool_handle;
+ nvlist_t *real_props;
uint64_t spa_version;
char *p;
zfs_prop_t resv_prop;
char *strval;
+ char msg[1024];
if (p = strchr(argv[0], '/'))
*p = '\0';
@@ -810,7 +812,15 @@ zfs_do_create(int argc, char **argv)
resv_prop = ZFS_PROP_REFRESERVATION;
else
resv_prop = ZFS_PROP_RESERVATION;
- volsize = zvol_volsize_to_reservation(volsize, props);
+
+ (void) snprintf(msg, sizeof (msg),
+ gettext("cannot create '%s'"), argv[0]);
+ if (props && (real_props = zfs_valid_proplist(g_zfs, type,
+ props, 0, NULL, msg)) == NULL)
+ goto error;
+
+ volsize = zvol_volsize_to_reservation(volsize, real_props);
+ nvlist_free(real_props);
if (nvlist_lookup_string(props, zfs_prop_to_name(resv_prop),
&strval) != 0) {
diff --git a/usr/src/common/zfs/zfeature_common.c b/usr/src/common/zfs/zfeature_common.c
index 8dd88b5e02..5d97bb7d86 100644
--- a/usr/src/common/zfs/zfeature_common.c
+++ b/usr/src/common/zfs/zfeature_common.c
@@ -21,8 +21,8 @@
/*
* Copyright (c) 2012 by Delphix. All rights reserved.
- * Copyright (c) 2012 Joyent, Inc. All rights reserved.
* Copyright (c) 2013 by Saso Kiselkov. All rights reserved.
+ * Copyright (c) 2012 Joyent, Inc. All rights reserved.
*/
#ifdef _KERNEL
diff --git a/usr/src/common/zfs/zfeature_common.h b/usr/src/common/zfs/zfeature_common.h
index de51aec368..2265b28ac5 100644
--- a/usr/src/common/zfs/zfeature_common.h
+++ b/usr/src/common/zfs/zfeature_common.h
@@ -21,8 +21,8 @@
/*
* Copyright (c) 2012 by Delphix. All rights reserved.
- * Copyright (c) 2012 Joyent, Inc. All rights reserved.
* Copyright (c) 2013 by Saso Kiselkov. All rights reserved.
+ * Copyright (c) 2012 Joyent, Inc. All rights reserved.
*/
#ifndef _ZFEATURE_COMMON_H
diff --git a/usr/src/common/zfs/zfs_prop.c b/usr/src/common/zfs/zfs_prop.c
index 0a1f733357..8bdd1307d6 100644
--- a/usr/src/common/zfs/zfs_prop.c
+++ b/usr/src/common/zfs/zfs_prop.c
@@ -21,8 +21,8 @@
/*
* Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2011 by Delphix. All rights reserved.
- * Copyright (c) 2012, Joyent, Inc. All rights reserved.
* Copyright (c) 2013 by Saso Kiselkov. All rights reserved.
+ * Copyright (c) 2012, Joyent, Inc. All rights reserved.
*/
/* Portions Copyright 2010 Robert Milkowski */
diff --git a/usr/src/lib/libdtrace/common/dt_cc.c b/usr/src/lib/libdtrace/common/dt_cc.c
index 88e22274e3..f4b0509b4a 100644
--- a/usr/src/lib/libdtrace/common/dt_cc.c
+++ b/usr/src/lib/libdtrace/common/dt_cc.c
@@ -676,6 +676,12 @@ dt_action_trace(dtrace_hdl_t *dtp, dt_node_t *dnp, dtrace_stmtdesc_t *sdp)
"%s( ) may not be applied to a translated pointer\n", act);
}
+ if (dnp->dn_args->dn_kind == DT_NODE_AGG) {
+ dnerror(dnp->dn_args, istrace ? D_TRACE_AGG : D_PRINT_AGG,
+ "%s( ) may not be applied to an aggregation%s\n", act,
+ istrace ? "" : " -- did you mean printa()?");
+ }
+
dt_cg(yypcb, dnp->dn_args);
/*
diff --git a/usr/src/lib/libdtrace/common/dt_decl.c b/usr/src/lib/libdtrace/common/dt_decl.c
index d2a0b29ca8..563c0057da 100644
--- a/usr/src/lib/libdtrace/common/dt_decl.c
+++ b/usr/src/lib/libdtrace/common/dt_decl.c
@@ -21,6 +21,7 @@
/*
* Copyright (c) 2003, 2010, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2012 by Delphix. All rights reserved.
*/
#include <strings.h>
@@ -251,11 +252,6 @@ dt_decl_spec(ushort_t kind, char *name)
ddp->dd_kind = kind;
ddp->dd_name = name;
- if (name != NULL && strchr(name, '`') != NULL) {
- xyerror(D_DECL_SCOPE, "D scoping operator may not be used "
- "in a type name\n");
- }
-
return (dt_decl_check(ddp));
}
diff --git a/usr/src/lib/libdtrace/common/dt_errtags.h b/usr/src/lib/libdtrace/common/dt_errtags.h
index 0a9e7c029b..0dd34e4525 100644
--- a/usr/src/lib/libdtrace/common/dt_errtags.h
+++ b/usr/src/lib/libdtrace/common/dt_errtags.h
@@ -190,8 +190,10 @@ typedef enum {
D_PRINTA_AGGPROTO, /* printa() aggregation mismatch */
D_TRACE_VOID, /* trace() argument has void type */
D_TRACE_DYN, /* trace() argument has dynamic type */
+ D_TRACE_AGG, /* trace() argument is an aggregation */
D_PRINT_VOID, /* print() argument has void type */
D_PRINT_DYN, /* print() argument has dynamic type */
+ D_PRINT_AGG, /* print() argument is an aggregation */
D_TRACEMEM_ADDR, /* tracemem() address bad type */
D_TRACEMEM_SIZE, /* tracemem() size bad type */
D_TRACEMEM_ARGS, /* tracemem() illegal number of args */
diff --git a/usr/src/lib/libshare/nfs/libshare_nfs.c b/usr/src/lib/libshare/nfs/libshare_nfs.c
index ef3f9cab0b..0cf69a241a 100644
--- a/usr/src/lib/libshare/nfs/libshare_nfs.c
+++ b/usr/src/lib/libshare/nfs/libshare_nfs.c
@@ -24,7 +24,7 @@
* Copyright (c) 2012, Joyent, Inc. All rights reserved.
*/
/*
- * Copyright 2012 Nexenta Systems, Inc. All rights reserved.
+ * Copyright 2013 Nexenta Systems, Inc. All rights reserved.
*/
/*
@@ -2798,7 +2798,7 @@ restart_service(uint32_t svcs)
(void) fprintf(stderr,
dgettext(TEXT_DOMAIN,
"%s failed to restart: %s\n"),
- scf_strerror(scf_error()));
+ service, scf_strerror(scf_error()));
} else {
/*
* Check whether it has gone to "maintenance"
diff --git a/usr/src/lib/libshare/smb/libshare_smb.c b/usr/src/lib/libshare/smb/libshare_smb.c
index f1ed417898..76c9eb0909 100644
--- a/usr/src/lib/libshare/smb/libshare_smb.c
+++ b/usr/src/lib/libshare/smb/libshare_smb.c
@@ -916,6 +916,8 @@ struct smb_proto_option_defs {
SMB_REFRESH_REFRESH },
{ SMB_CI_PRINT_ENABLE, 0, 0, print_enable_validator,
SMB_REFRESH_REFRESH },
+ { SMB_CI_TRAVERSE_MOUNTS, 0, 0, true_false_validator,
+ SMB_REFRESH_REFRESH },
{ SMB_CI_MAP, 0, MAX_VALUE_BUFLEN, cmd_validator, SMB_REFRESH_REFRESH },
{ SMB_CI_UNMAP, 0, MAX_VALUE_BUFLEN, cmd_validator,
SMB_REFRESH_REFRESH },
diff --git a/usr/src/lib/libzfs/common/libzfs_dataset.c b/usr/src/lib/libzfs/common/libzfs_dataset.c
index 00ca716028..c827f55ad1 100644
--- a/usr/src/lib/libzfs/common/libzfs_dataset.c
+++ b/usr/src/lib/libzfs/common/libzfs_dataset.c
@@ -1288,6 +1288,7 @@ zfs_add_synthetic_resv(zfs_handle_t *zhp, nvlist_t *nvl)
uint64_t old_reservation;
uint64_t new_reservation;
zfs_prop_t resv_prop;
+ nvlist_t *props;
/*
* If this is an existing volume, and someone is setting the volsize,
@@ -1297,16 +1298,25 @@ zfs_add_synthetic_resv(zfs_handle_t *zhp, nvlist_t *nvl)
if (zfs_which_resv_prop(zhp, &resv_prop) < 0)
return (-1);
old_reservation = zfs_prop_get_int(zhp, resv_prop);
- if ((zvol_volsize_to_reservation(old_volsize, zhp->zfs_props) !=
- old_reservation) || nvlist_lookup_uint64(nvl,
- zfs_prop_to_name(resv_prop), &new_reservation) != ENOENT) {
+
+ props = fnvlist_alloc();
+ fnvlist_add_uint64(props, zfs_prop_to_name(ZFS_PROP_VOLBLOCKSIZE),
+ zfs_prop_get_int(zhp, ZFS_PROP_VOLBLOCKSIZE));
+
+ if ((zvol_volsize_to_reservation(old_volsize, props) !=
+ old_reservation) || nvlist_exists(nvl,
+ zfs_prop_to_name(resv_prop))) {
+ fnvlist_free(props);
return (0);
}
if (nvlist_lookup_uint64(nvl, zfs_prop_to_name(ZFS_PROP_VOLSIZE),
- &new_volsize) != 0)
+ &new_volsize) != 0) {
+ fnvlist_free(props);
return (-1);
- new_reservation = zvol_volsize_to_reservation(new_volsize,
- zhp->zfs_props);
+ }
+ new_reservation = zvol_volsize_to_reservation(new_volsize, props);
+ fnvlist_free(props);
+
if (nvlist_add_uint64(nvl, zfs_prop_to_name(resv_prop),
new_reservation) != 0) {
(void) no_memory(zhp->zfs_hdl);
diff --git a/usr/src/lib/libzfs/common/mapfile-vers b/usr/src/lib/libzfs/common/mapfile-vers
index cff2c0dc9a..d2ce523cf8 100644
--- a/usr/src/lib/libzfs/common/mapfile-vers
+++ b/usr/src/lib/libzfs/common/mapfile-vers
@@ -161,6 +161,7 @@ SYMBOL_VERSION SUNWprivate_1.1 {
zfs_unshareall_nfs;
zfs_unshareall_smb;
zfs_userspace;
+ zfs_valid_proplist;
zfs_get_fsacl;
zfs_set_fsacl;
zfs_userquota_prop_prefixes;
diff --git a/usr/src/lib/libzpool/common/kernel.c b/usr/src/lib/libzpool/common/kernel.c
index c698c23ef6..cc0d5428be 100644
--- a/usr/src/lib/libzpool/common/kernel.c
+++ b/usr/src/lib/libzpool/common/kernel.c
@@ -80,8 +80,8 @@ zk_thread_create(void (*func)(), void *arg)
*/
/*ARGSUSED*/
kstat_t *
-kstat_create(char *module, int instance, char *name, char *class,
- uchar_t type, ulong_t ndata, uchar_t ks_flag)
+kstat_create(const char *module, int instance, const char *name,
+ const char *class, uchar_t type, ulong_t ndata, uchar_t ks_flag)
{
return (NULL);
}
@@ -96,6 +96,36 @@ void
kstat_delete(kstat_t *ksp)
{}
+/*ARGSUSED*/
+void
+kstat_waitq_enter(kstat_io_t *kiop)
+{}
+
+/*ARGSUSED*/
+void
+kstat_waitq_exit(kstat_io_t *kiop)
+{}
+
+/*ARGSUSED*/
+void
+kstat_runq_enter(kstat_io_t *kiop)
+{}
+
+/*ARGSUSED*/
+void
+kstat_runq_exit(kstat_io_t *kiop)
+{}
+
+/*ARGSUSED*/
+void
+kstat_waitq_to_runq(kstat_io_t *kiop)
+{}
+
+/*ARGSUSED*/
+void
+kstat_runq_back_to_waitq(kstat_io_t *kiop)
+{}
+
/*
* =========================================================================
* mutexes
diff --git a/usr/src/lib/libzpool/common/sys/zfs_context.h b/usr/src/lib/libzpool/common/sys/zfs_context.h
index c638482d2e..bcb27cf1a5 100644
--- a/usr/src/lib/libzpool/common/sys/zfs_context.h
+++ b/usr/src/lib/libzpool/common/sys/zfs_context.h
@@ -255,10 +255,16 @@ extern void cv_broadcast(kcondvar_t *cv);
/*
* kstat creation, installation and deletion
*/
-extern kstat_t *kstat_create(char *, int,
- char *, char *, uchar_t, ulong_t, uchar_t);
+extern kstat_t *kstat_create(const char *, int,
+ const char *, const char *, uchar_t, ulong_t, uchar_t);
extern void kstat_install(kstat_t *);
extern void kstat_delete(kstat_t *);
+extern void kstat_waitq_enter(kstat_io_t *);
+extern void kstat_waitq_exit(kstat_io_t *);
+extern void kstat_runq_enter(kstat_io_t *);
+extern void kstat_runq_exit(kstat_io_t *);
+extern void kstat_waitq_to_runq(kstat_io_t *);
+extern void kstat_runq_back_to_waitq(kstat_io_t *);
/*
* Kernel memory
diff --git a/usr/src/lib/smbsrv/libsmb/common/libsmb.h b/usr/src/lib/smbsrv/libsmb/common/libsmb.h
index 255f3d545c..8a11384b61 100644
--- a/usr/src/lib/smbsrv/libsmb/common/libsmb.h
+++ b/usr/src/lib/smbsrv/libsmb/common/libsmb.h
@@ -150,6 +150,7 @@ typedef enum {
SMB_CI_UNMAP,
SMB_CI_DISPOSITION,
SMB_CI_DFS_STDROOT_NUM,
+ SMB_CI_TRAVERSE_MOUNTS,
SMB_CI_MAX
} smb_cfg_id_t;
diff --git a/usr/src/lib/smbsrv/libsmb/common/smb_cfg.c b/usr/src/lib/smbsrv/libsmb/common/smb_cfg.c
index e3b851695a..6270ca1af2 100644
--- a/usr/src/lib/smbsrv/libsmb/common/smb_cfg.c
+++ b/usr/src/lib/smbsrv/libsmb/common/smb_cfg.c
@@ -20,6 +20,7 @@
*/
/*
* Copyright (c) 2007, 2010, Oracle and/or its affiliates. All rights reserved.
+ * Copyright 2011 Nexenta Systems, Inc. All rights reserved.
*/
/*
@@ -132,9 +133,8 @@ static smb_cfg_param_t smb_cfg_table[] =
{SMB_CI_MAP, "map", SCF_TYPE_ASTRING, SMB_CF_EXEC},
{SMB_CI_UNMAP, "unmap", SCF_TYPE_ASTRING, SMB_CF_EXEC},
{SMB_CI_DISPOSITION, "disposition", SCF_TYPE_ASTRING, SMB_CF_EXEC},
-
- {SMB_CI_DFS_STDROOT_NUM, "dfs_stdroot_num", SCF_TYPE_INTEGER, 0}
-
+ {SMB_CI_DFS_STDROOT_NUM, "dfs_stdroot_num", SCF_TYPE_INTEGER, 0},
+ {SMB_CI_TRAVERSE_MOUNTS, "traverse_mounts", SCF_TYPE_BOOLEAN, 0}
/* SMB_CI_MAX */
};
diff --git a/usr/src/lib/smbsrv/libsmb/common/smb_info.c b/usr/src/lib/smbsrv/libsmb/common/smb_info.c
index fe1632a2c6..2b029fea6f 100644
--- a/usr/src/lib/smbsrv/libsmb/common/smb_info.c
+++ b/usr/src/lib/smbsrv/libsmb/common/smb_info.c
@@ -20,6 +20,7 @@
*/
/*
* Copyright (c) 2007, 2010, Oracle and/or its affiliates. All rights reserved.
+ * Copyright 2011 Nexenta Systems, Inc. All rights reserved.
*/
#include <assert.h>
@@ -92,6 +93,7 @@ smb_load_kconfig(smb_kmod_cfg_t *kcfg)
kcfg->skc_print_enable = smb_config_getbool(SMB_CI_PRINT_ENABLE);
kcfg->skc_oplock_enable = smb_config_getbool(SMB_CI_OPLOCK_ENABLE);
kcfg->skc_sync_enable = smb_config_getbool(SMB_CI_SYNC_ENABLE);
+ kcfg->skc_traverse_mounts = smb_config_getbool(SMB_CI_TRAVERSE_MOUNTS);
kcfg->skc_secmode = smb_config_get_secmode();
(void) smb_getdomainname(kcfg->skc_nbdomain,
sizeof (kcfg->skc_nbdomain));
diff --git a/usr/src/lib/smbsrv/libsmb/common/smb_kmod.c b/usr/src/lib/smbsrv/libsmb/common/smb_kmod.c
index 91bb16bc6e..7c2060f9dc 100644
--- a/usr/src/lib/smbsrv/libsmb/common/smb_kmod.c
+++ b/usr/src/lib/smbsrv/libsmb/common/smb_kmod.c
@@ -86,6 +86,7 @@ smb_kmod_setcfg(smb_kmod_cfg_t *cfg)
ioc.secmode = cfg->skc_secmode;
ioc.ipv6_enable = cfg->skc_ipv6_enable;
ioc.print_enable = cfg->skc_print_enable;
+ ioc.traverse_mounts = cfg->skc_traverse_mounts;
ioc.exec_flags = cfg->skc_execflags;
ioc.version = cfg->skc_version;
diff --git a/usr/src/man/man1/getconf.1 b/usr/src/man/man1/getconf.1
index fd23451e3c..ea38de392d 100644
--- a/usr/src/man/man1/getconf.1
+++ b/usr/src/man/man1/getconf.1
@@ -10,7 +10,7 @@
.\" The contents of this file are subject to the terms of the Common Development and Distribution License (the "License"). You may not use this file except in compliance with the License. You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE or http://www.opensolaris.org/os/licensing.
.\" See the License for the specific language governing permissions and limitations under the License. When distributing Covered Code, include this CDDL HEADER in each file and include the License file at usr/src/OPENSOLARIS.LICENSE. If applicable, add the following below this CDDL HEADER, with
.\" the fields enclosed by brackets "[]" replaced with your own identifying information: Portions Copyright [yyyy] [name of copyright owner]
-.TH GETCONF 1 "Sep 1, 2009"
+.TH GETCONF 1 "Jan 16, 2013"
.SH NAME
getconf \- get configuration values
.SH SYNOPSIS
@@ -458,73 +458,74 @@ LONG_MIN MB_LEN_MAX
NGROUPS_MAX NL_ARGMAX
NL_LANGMAX NL_MSGMAX
NL_NMAX NL_SETMAX
-NL_TEXTMAX NZERO
-OPEN_MAX POSIX2_BC_BASE_MAX
-POSIX2_BC_DIM_MAX POSIX2_BC_SCALE_MAX
-POSIX2_BC_STRING_MAX POSIX2_C_BIND
-POSIX2_C_DEV POSIX2_CHAR_TERM
-POSIX2_COLL_WEIGHTS_MAX POSIX2_C_VERSION
-POSIX2_EXPR_NEST_MAX POSIX2_FORT_DEV
-POSIX2_FORT_RUN POSIX2_LINE_MAX
-POSIX2_LOCALEDEF POSIX2_RE_DUP_MAX
-POSIX2_SW_DEV POSIX2_SYMLINKS
-POSIX2_UPE POSIX2_VERSION
-POSIX_ALLOC_SIZE_MIN POSIX_REC_INCR_XFER_SIZE
-POSIX_REC_MAX_XFER_SIZE POSIX_REC_MIN_XFER_SIZE
-POSIX_REC_XFER_ALIGN POSIX_V6_ILP32_OFF32
-POSIX_V6_ILP32_OFF32_CFLAGS POSIX_V6_ILP32_OFF32_LDFLAGS
-POSIX_V6_ILP32_OFF32_LIBS POSIX_V6_ILP32_OFFBIG
-POSIX_V6_ILP32_OFFBIG_CFLAGS POSIX_V6_ILP32_OFFBIG_LDFLAGS
-POSIX_V6_ILP32_OFFBIG_LIBS POSIX_V6_LP64_OFF64
-POSIX_V6_LP64_OFF64_CFLAGS POSIX_V6_LP64_OFF64_LDFLAGS
-POSIX_V6_LP64_OFF64_LIBS POSIX_V6_LPBIG_OFFBIG
-POSIX_V6_LPBIG_OFFBIG_CFLAGS POSIX_V6_LPBIG_OFFBIG_LDFLAGS
-POSIX_V6_LPBIG_OFFBIG_LIBS POSIX_V6_WIDTH_RESTRICTED_ENVS
-SYMLINK_MAX SYMLOOP_MAX
-_POSIX2_BC_BASE_MAX _POSIX2_BC_DIM_MAX
-_POSIX2_BC_SCALE_MAX _POSIX2_BC_STRING_MAX
-_POSIX2_CHARCLASS_NAME_MAX _POSIX2_CHAR_TERM
-_POSIX2_COLL_WEIGHTS_MAX _POSIX2_C_BIND
-_POSIX2_C_DEV _POSIX2_C_VERSION
-_POSIX2_EXPR_NEST_MAX _POSIX2_FORT_DEV
-_POSIX2_FORT_RUN _POSIX2_LINE_MAX
-_POSIX2_LOCALEDEF _POSIX2_PBS
-_POSIX2_PBS_ACCOUNTING _POSIX2_PBS_CHECKPOINT
-_POSIX2_PBS_LOCATE _POSIX2_PBS_MESSAGE
-_POSIX2_PBS_TRACK _POSIX2_RE_DUP_MAX
-_POSIX2_SW_DEV _POSIX2_UPE
-_POSIX2_VERSION _POSIX_ADVISORY_INFO
-_POSIX_AIO_LISTIO_MAX _POSIX_AIO_MAX
-_POSIX_ARG_MAX _POSIX_ASYNC_IO
-_POSIX_BARRIERS _POSIX_CHILD_MAX
-_POSIX_CLOCKRES_MIN _POSIX_CLOCK_SELECTION
-_POSIX_CPUTIME _POSIX_DELAYTIMER_MAX
-_POSIX_HOST_NAME_MAX _POSIX_IPV6
-_POSIX_JOB_CONTROL _POSIX_LINK_MAX
-_POSIX_LOGIN_NAME_MAX _POSIX_MAX_CANON
-_POSIX_MAX_INPUT _POSIX_MONOTONIC_CLOCK
-_POSIX_MQ_OPEN_MAX _POSIX_MQ_PRIO_MAX
-_POSIX_NAME_MAX _POSIX_NGROUPS_MAX
-_POSIX_OPEN_MAX _POSIX_PATH_MAX
-_POSIX_PIPE_BUF _POSIX_PRIO_IO
-_POSIX_RAW_SOCKETS _POSIX_READER_WRITER_LOCKS
-_POSIX_REGEXP _POSIX_RE_DUP_MAX
-_POSIX_RTSIG_MAX _POSIX_SAVED_IDS
-_POSIX_SEM_NSEMS_MAX _POSIX_SEM_VALUE_MAX
-_POSIX_SHELL _POSIX_SIGQUEUE_MAX
-_POSIX_SPAWN _POSIX_SPIN_LOCKS
-_POSIX_SPORADIC_SERVER _POSIX_SSIZE_MAX
-_POSIX_SS_REPL_MAX _POSIX_STREAM_MAX
-_POSIX_SYMLINK_MAX _POSIX_SYMLOOP_MAX
-_POSIX_SYNC_IO _POSIX_THREAD_ATTR_STACKADDR
-_POSIX_THREAD_ATTR_STACKSIZE _POSIX_THREAD_CPUTIME
-_POSIX_THREAD_DESTRUCTOR_ITERATIONS _POSIX_THREAD_KEYS_MAX
-_POSIX_THREAD_PRIORITY_SCHEDULING _POSIX_THREAD_PRIO_INHERIT
-_POSIX_THREAD_PRIO_PROTECT _POSIX_THREAD_PROCESS_SHARED
-_POSIX_THREAD_SAFE_FUNCTIONS _POSIX_THREAD_SPORADIC_SERVER
-_POSIX_THREAD_THREADS_MAX _POSIX_TIMEOUTS
-_POSIX_TIMER_MAX _POSIX_TRA_POSIX_TIMER_MAXCE
-_POSIX_TIMESTAMP_RESOLUTION
+NL_TEXTMAX NPROCESSORS_CONF
+NPROCESSORS_MAX NPROCESSORS_ONLN
+NZERO OPEN_MAX
+POSIX2_BC_BASE_MAX POSIX2_BC_DIM_MAX
+POSIX2_BC_SCALE_MAX POSIX2_BC_STRING_MAX
+POSIX2_C_BIND POSIX2_C_DEV
+POSIX2_CHAR_TERM POSIX2_COLL_WEIGHTS_MAX
+POSIX2_C_VERSION POSIX2_EXPR_NEST_MAX
+POSIX2_FORT_DEV POSIX2_FORT_RUN
+POSIX2_LINE_MAX POSIX2_LOCALEDEF
+POSIX2_RE_DUP_MAX POSIX2_SW_DEV
+POSIX2_SYMLINKS POSIX2_UPE
+POSIX2_VERSION POSIX_ALLOC_SIZE_MIN
+POSIX_REC_INCR_XFER_SIZE POSIX_REC_MAX_XFER_SIZE
+POSIX_REC_MIN_XFER_SIZE POSIX_REC_XFER_ALIGN
+POSIX_V6_ILP32_OFF32 POSIX_V6_ILP32_OFF32_CFLAGS
+POSIX_V6_ILP32_OFF32_LDFLAGS POSIX_V6_ILP32_OFF32_LIBS
+POSIX_V6_ILP32_OFFBIG POSIX_V6_ILP32_OFFBIG_CFLAGS
+POSIX_V6_ILP32_OFFBIG_LDFLAGS POSIX_V6_ILP32_OFFBIG_LIBS
+POSIX_V6_LP64_OFF64 POSIX_V6_LP64_OFF64_CFLAGS
+POSIX_V6_LP64_OFF64_LDFLAGS POSIX_V6_LP64_OFF64_LIBS
+POSIX_V6_LPBIG_OFFBIG POSIX_V6_LPBIG_OFFBIG_CFLAGS
+POSIX_V6_LPBIG_OFFBIG_LDFLAGS POSIX_V6_LPBIG_OFFBIG_LIBS
+POSIX_V6_WIDTH_RESTRICTED_ENVS SYMLINK_MAX
+SYMLOOP_MAX _POSIX2_BC_BASE_MAX
+_POSIX2_BC_DIM_MAX _POSIX2_BC_SCALE_MAX
+_POSIX2_BC_STRING_MAX _POSIX2_CHARCLASS_NAME_MAX
+_POSIX2_CHAR_TERM _POSIX2_COLL_WEIGHTS_MAX
+_POSIX2_C_BIND _POSIX2_C_DEV
+_POSIX2_C_VERSION _POSIX2_EXPR_NEST_MAX
+_POSIX2_FORT_DEV _POSIX2_FORT_RUN
+_POSIX2_LINE_MAX _POSIX2_LOCALEDEF
+_POSIX2_PBS _POSIX2_PBS_ACCOUNTING
+_POSIX2_PBS_CHECKPOINT _POSIX2_PBS_LOCATE
+_POSIX2_PBS_MESSAGE _POSIX2_PBS_TRACK
+_POSIX2_RE_DUP_MAX _POSIX2_SW_DEV
+_POSIX2_UPE _POSIX2_VERSION
+_POSIX_ADVISORY_INFO _POSIX_AIO_LISTIO_MAX
+_POSIX_AIO_MAX _POSIX_ARG_MAX
+_POSIX_ASYNC_IO _POSIX_BARRIERS
+_POSIX_CHILD_MAX _POSIX_CLOCKRES_MIN
+_POSIX_CLOCK_SELECTION _POSIX_CPUTIME
+_POSIX_DELAYTIMER_MAX _POSIX_HOST_NAME_MAX
+_POSIX_IPV6 _POSIX_JOB_CONTROL
+_POSIX_LINK_MAX _POSIX_LOGIN_NAME_MAX
+_POSIX_MAX_CANON _POSIX_MAX_INPUT
+_POSIX_MONOTONIC_CLOCK _POSIX_MQ_OPEN_MAX
+_POSIX_MQ_PRIO_MAX _POSIX_NAME_MAX
+_POSIX_NGROUPS_MAX _POSIX_OPEN_MAX
+_POSIX_PATH_MAX _POSIX_PIPE_BUF
+_POSIX_PRIO_IO _POSIX_RAW_SOCKETS
+_POSIX_READER_WRITER_LOCKS _POSIX_REGEXP
+_POSIX_RE_DUP_MAX _POSIX_RTSIG_MAX
+_POSIX_SAVED_IDS _POSIX_SEM_NSEMS_MAX
+_POSIX_SEM_VALUE_MAX _POSIX_SHELL
+_POSIX_SIGQUEUE_MAX _POSIX_SPAWN
+_POSIX_SPIN_LOCKS _POSIX_SPORADIC_SERVER
+_POSIX_SSIZE_MAX _POSIX_SS_REPL_MAX
+_POSIX_STREAM_MAX _POSIX_SYMLINK_MAX
+_POSIX_SYMLOOP_MAX _POSIX_SYNC_IO
+_POSIX_THREAD_ATTR_STACKADDR _POSIX_THREAD_ATTR_STACKSIZE
+_POSIX_THREAD_CPUTIME _POSIX_THREAD_DESTRUCTOR_ITERATIONS
+_POSIX_THREAD_KEYS_MAX _POSIX_THREAD_PRIORITY_SCHEDULING
+_POSIX_THREAD_PRIO_INHERIT _POSIX_THREAD_PRIO_PROTECT
+_POSIX_THREAD_PROCESS_SHARED _POSIX_THREAD_SAFE_FUNCTIONS
+_POSIX_THREAD_SPORADIC_SERVER _POSIX_THREAD_THREADS_MAX
+_POSIX_TIMEOUTS _POSIX_TIMER_MAX
+_POSIX_TRA_POSIX_TIMER_MAXCE _POSIX_TIMESTAMP_RESOLUTION
_POSIX_TRACE_EVENT_FILTER _POSIX_TRACE_EVENT_NAME_MAX
_POSIX_TRACE_INHERIT _POSIX_TRACE_LOG
_POSIX_TRACE_NAME_MAX _POSIX_TRACE_SYS_MAX
diff --git a/usr/src/man/man1/tar.1 b/usr/src/man/man1/tar.1
index 0641851b2f..0829a9c1c3 100644
--- a/usr/src/man/man1/tar.1
+++ b/usr/src/man/man1/tar.1
@@ -2,6 +2,7 @@
.\" Copyright 1989 AT&T
.\" Copyright (c) 2006, Sun Microsystems, Inc. All Rights Reserved
.\" Copyright 2012 Milan Jurik. All rights reserved.
+.\" Copyright (c) 2013, Joyent, Inc. All rights reserved.
.\" Portions Copyright (c) 1992, X/Open Company Limited All Rights Reserved
.\" Sun Microsystems, Inc. gratefully acknowledges The Open Group for permission to reproduce portions of its copyrighted documentation. Original documentation from The Open Group can be obtained online at
.\" http://www.opengroup.org/bookstore/.
@@ -10,7 +11,7 @@
.\" The contents of this file are subject to the terms of the Common Development and Distribution License (the "License"). You may not use this file except in compliance with the License.
.\" You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE or http://www.opensolaris.org/os/licensing. See the License for the specific language governing permissions and limitations under the License.
.\" When distributing Covered Code, include this CDDL HEADER in each file and include the License file at usr/src/OPENSOLARIS.LICENSE. If applicable, add the following below this CDDL HEADER, with the fields enclosed by brackets "[]" replaced with your own identifying information: Portions Copyright [yyyy] [name of copyright owner]
-.TH TAR 1 "May 9, 2012"
+.TH TAR 1 "Jan 16, 2013"
.SH NAME
tar \- create tape archives and add or extract files
.SH SYNOPSIS
diff --git a/usr/src/man/man1m/dumpadm.1m b/usr/src/man/man1m/dumpadm.1m
index cea8d120c3..d46160d7c3 100644
--- a/usr/src/man/man1m/dumpadm.1m
+++ b/usr/src/man/man1m/dumpadm.1m
@@ -1,9 +1,11 @@
'\" te
-.\" Copyright (c) 2008, Sun Microsystems, Inc. All Rights Reserved
+.\" Copyright (c) 2008, Sun Microsystems, Inc. All Rights Reserved
+.\" Copyright 2013 Nexenta Systems, Inc. All Rights Reserved.
+.\" Copyright (c) 2013 by Delphix. All rights reserved.
.\" The contents of this file are subject to the terms of the Common Development and Distribution License (the "License"). You may not use this file except in compliance with the License.
.\" You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE or http://www.opensolaris.org/os/licensing. See the License for the specific language governing permissions and limitations under the License.
.\" When distributing Covered Code, include this CDDL HEADER in each file and include the License file at usr/src/OPENSOLARIS.LICENSE. If applicable, add the following below this CDDL HEADER, with the fields enclosed by brackets "[]" replaced with your own identifying information: Portions Copyright [yyyy] [name of copyright owner]
-.TH DUMPADM 1M "Apr 10, 2008"
+.TH DUMPADM 1M "Feb 15, 2013"
.SH NAME
dumpadm \- configure operating system crash dump
.SH SYNOPSIS
@@ -11,7 +13,7 @@ dumpadm \- configure operating system crash dump
.nf
\fB/usr/sbin/dumpadm\fR [\fB-nuy\fR] [\fB-c\fR \fIcontent-type\fR] [\fB-d\fR \fIdump-device\fR]
[\fB-m\fR \fImin\fRk | \fImin\fRm | \fImin\fR%] [\fB-s\fR \fIsavecore-dir\fR]
- [\fB-r\fR \fIroot-dir\fR]
+ [\fB-r\fR \fIroot-dir\fR] [\fB-z\fR on | off]
.fi
.SH DESCRIPTION
@@ -35,12 +37,19 @@ your support engineer to aid in diagnosing the problem. As such, it is vital
that the crash dump be retrieved and given to your support provider. Following
an operating system crash, the \fBsavecore\fR(1M) utility is executed
automatically during boot to retrieve the crash dump from the dump device, and
-write it to a pair of files in your file system named \fIunix.X\fR and
-\fIvmcore.X\fR, where X is an integer identifying the dump. Together, these
-data files form the \fIsaved crash dump\fR. The directory in which the crash
+write it to the file system. The directory in which the crash
dump is saved on reboot can also be configured using \fBdumpadm\fR.
.sp
.LP
+When the operating system takes a crash dump the default behavior is to
+compress the crash dump. This behavior is controlled by the \fB-z\fR option.
+When compression is turned on, the \fBsavecore\fR(1M) utility writes one file
+to the file system named \fIvmdump.X\fR. If compression is disabled, it instead
+writes two files named \fIunix.X\fR and \fIvmcore.X\fR. In the uncompressed
+case, both data files form the \fIsaved crash dump\fR. In both cases X is an
+integer identifying the dump.
+.sp
+.LP
For systems with a UFS root file system, the default dump device is configured
to be an appropriate swap partition. Swap partitions are disk partitions
reserved as virtual memory backing store for the operating system. Thus, no
@@ -58,6 +67,7 @@ example# \fBdumpadm\fR
Dump device: /dev/dsk/c0t0d0s1 (swap)
Savecore directory: /var/crash/saturn
Savecore enabled: yes
+ Save compressed: on
.fi
.in -2
.sp
@@ -68,8 +78,8 @@ When no options are specified, \fBdumpadm\fR prints the current crash dump
configuration. The example shows the set of default values: the dump content is
set to kernel memory pages only, the dump device is a swap disk partition, the
directory for \fBsavecore\fR files is set to
-\fB/var/crash/\fR\fBhostname\fR\fB,\fR and \fBsavecore\fR is set to run
-automatically on reboot.
+\fB/var/crash/\fR\fIhostname\fR\fB,\fR \fBsavecore\fR is set to run
+automatically on reboot, and compression is turned on.
.sp
.LP
When one or more options are specified, \fBdumpadm\fR verifies that your
@@ -132,7 +142,7 @@ process, only kernel pages will be dumped.
.sp .6
.RS 4n
Modify the dump configuration to use the specified dump device. The dump device
-may one of the following:
+may be one of the following:
.sp
.ne 2
.na
@@ -163,6 +173,17 @@ given ZFS volume cannot be configured for both the swap area and the dump
device.
.RE
+.sp
+.ne 2
+.na
+\fB\fBnone\fR\fR
+.ad
+.sp .6
+.RS 4n
+If the special token \fBnone\fR is specified, the active dump device is removed
+and crash dumps are disabled.
+.RE
+
.RE
.sp
@@ -288,6 +309,16 @@ Modify the dump configuration to automatically run \fBsavecore\fR on reboot.
This is the default for this dump setting.
.RE
+.sp
+.ne 2
+.na
+\fB\fB-z on | off\fR\fR
+.ad
+.sp .6
+.RS 4n
+Turns crash dump compression \fBon\fR or \fBoff\fR.
+.RE
+
.SH EXAMPLES
.LP
\fBExample 1 \fRReconfiguring The Dump Device To A Dedicated Dump Device:
@@ -304,6 +335,7 @@ example# dumpadm -d /dev/dsk/c0t2d0s2
Dump device: /dev/dsk/c0t2d0s2 (dedicated)
Savecore directory: /var/crash/saturn
Savecore enabled: yes
+ Save compressed: on
.fi
.in -2
.sp
diff --git a/usr/src/man/man1m/iostat.1m b/usr/src/man/man1m/iostat.1m
index e45ceff5e3..9c54d91142 100644
--- a/usr/src/man/man1m/iostat.1m
+++ b/usr/src/man/man1m/iostat.1m
@@ -1,8 +1,27 @@
'\" te
+.\"
+.\" CDDL HEADER START
+.\"
+.\" The contents of this file are subject to the terms of the
+.\" Common Development and Distribution License (the "License").
+.\" You may not use this file except in compliance with the License.
+.\"
+.\" You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+.\" or http://www.opensolaris.org/os/licensing.
+.\" See the License for the specific language governing permissions
+.\" and limitations under the License.
+.\"
+.\" When distributing Covered Code, include this CDDL HEADER in each
+.\" file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+.\" If applicable, add the following below this CDDL HEADER, with the
+.\" fields enclosed by brackets "[]" replaced with your own identifying
+.\" information: Portions Copyright [yyyy] [name of copyright owner]
+.\"
+.\" CDDL HEADER END
+.\"
.\" Copyright (c) 2003, Sun Microsystems, Inc. All Rights reserved
-.\" The contents of this file are subject to the terms of the Common Development and Distribution License (the "License"). You may not use this file except in compliance with the License. You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE or http://www.opensolaris.org/os/licensing.
-.\" See the License for the specific language governing permissions and limitations under the License. When distributing Covered Code, include this CDDL HEADER in each file and include the License file at usr/src/OPENSOLARIS.LICENSE. If applicable, add the following below this CDDL HEADER, with
-.\" the fields enclosed by brackets "[]" replaced with your own identifying information: Portions Copyright [yyyy] [name of copyright owner]
+.\" Copyright (c) 2012 by Delphix. All rights reserved.
+.\"
.TH IOSTAT 1M "Mar 23, 2009"
.SH NAME
iostat \- report I/O statistics
@@ -194,16 +213,6 @@ average service time in wait queue, in milliseconds
average service time of active transactions, in milliseconds
.RE
-.sp
-.ne 2
-.na
-\fB\fBwt\fR\fR
-.ad
-.RS 10n
-the I/O wait time is no longer calculated as a percentage of \fBCPU\fR time,
-and this statistic will always return zero.
-.RE
-
.SH OPTIONS
.sp
.LP
@@ -215,8 +224,8 @@ The following options are supported:
.ad
.RS 12n
Report the percentage of time the system has spent in user mode, in system
-mode, waiting for \fBI/O,\fR and idling. See the NOTES section for more
-information.
+mode, in dtrace probes, and idling. See the NOTES section and
+\fBmpstat\fR(1m) for more information.
.RE
.sp
@@ -510,7 +519,7 @@ example% \fBiostat\fR \fB-xcnCXTdz\fR \fB5\fR
Mon Nov 24 14:58:36 2003
cpu
- us sy wt id
+ us sy dt id
14 31 0 20
extended device statistics
r/s w/s kr/s kw wait actv wsvc_t asvc_t %w %b device
@@ -520,8 +529,8 @@ Mon Nov 24 14:58:36 2003
Mon Nov 24 14:58:41 2003
cpu
- us sy wt id
- 11 31 0 22
+ us sy dt id
+ 11 31 1 22
extended device statistics
r/s w/s kr/s kw wait actv wsvc_t asvc_t %w %b device
0.8 41.0 5.2 20.5 0.0 0.2 0.2 4.4 0 6 c0
@@ -546,14 +555,14 @@ example% \fBiostat\fR \fB-x\fR \fBtc 5 2\fR
extended device statistics tty cpu
-device r/s w/s kr/s kw/s wait actv svc_t %w %b tin tout us sy wt id
+device r/s w/s kr/s kw/s wait actv svc_t %w %b tin tout us sy dt id
sd0 0.4 0.3 10.4 8.0 0.0 0.0 36.9 0 1 0 10 0 0 0 99
sd1 0.0 0.0 0.3 0.4 0.0 0.0 35.0 0 0
sd6 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0 0
nfs1 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0 0
nfs2 0.0 0.0 0.0 0.1 0.0 0.0 35.6 0 0
extended device statistics tty cpu
-device r/s w/s kr/s kw/s wait actv svc_t %w %b tin tout us sy wt id
+device r/s w/s kr/s kw/s wait actv svc_t %w %b tin tout us sy dt id
sd0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0 0 0 155 0 0 0 100
sd1 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0 0
sd6 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0 0
@@ -664,7 +673,7 @@ The \fBsvc_t\fR response time is not particularly significant when the
are fairly normal in such cases.
.sp
.LP
-The \fBmpstat\fR utility reports the same \fBwt\fR, \fBusr\fR, and \fBsys\fR
+The \fBmpstat\fR utility reports the same \fBdt\fR, \fBusr\fR, and \fBsys\fR
statistics. See \fBmpstat\fR(1M) for more information.
.sp
.LP
diff --git a/usr/src/man/man1m/kstat.1m b/usr/src/man/man1m/kstat.1m
index 02decab8e0..c7ce68f4ea 100644
--- a/usr/src/man/man1m/kstat.1m
+++ b/usr/src/man/man1m/kstat.1m
@@ -3,20 +3,20 @@
.\" The contents of this file are subject to the terms of the Common Development and Distribution License (the "License"). You may not use this file except in compliance with the License. You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE or http://www.opensolaris.org/os/licensing.
.\" See the License for the specific language governing permissions and limitations under the License. When distributing Covered Code, include this CDDL HEADER in each file and include the License file at usr/src/OPENSOLARIS.LICENSE. If applicable, add the following below this CDDL HEADER, with
.\" the fields enclosed by brackets "[]" replaced with your own identifying information: Portions Copyright [yyyy] [name of copyright owner]
-.TH KSTAT 1M "Mar 23, 2009"
+.TH KSTAT 1M "Jan 9, 2013"
.SH NAME
kstat \- display kernel statistics
.SH SYNOPSIS
.LP
.nf
-\fBkstat\fR [\fB-lpq\fR] [\fB-T\fR u | d ] [\fB-c\fR \fIclass\fR] [\fB-m\fR \fImodule\fR]
+\fBkstat\fR [\fB-Cjlpq\fR] [\fB-T\fR u | d ] [\fB-c\fR \fIclass\fR] [\fB-m\fR \fImodule\fR]
[\fB-i\fR \fIinstance\fR] [\fB-n\fR \fIname\fR] [\fB-s\fR \fIstatistic\fR]
[interval [count]]
.fi
.LP
.nf
-\fBkstat\fR [\fB-lpq\fR] [\fB-T\fR u | d ] [\fB-c\fR \fIclass\fR]
+\fBkstat\fR [\fB-Cjlpq\fR] [\fB-T\fR u | d ] [\fB-c\fR \fIclass\fR]
[\fImodule\fR:\fIinstance\fR:\fIname\fR:\fIstatistic\fR]...
[interval [count]]
.fi
@@ -59,11 +59,20 @@ appropriate quotes.
.sp
.LP
The argument for the \fB-c\fR, \fB-i\fR, \fB-m\fR, \fB-n\fR, and \fB-s\fR
-options may be specified as a shell glob pattern, or a Perl regular expression
+options may be specified as a shell glob pattern, or a regular expression
enclosed in '/' characters.
.sp
.ne 2
.na
+\fB\fB-C\fR\fR
+.ad
+.RS 16n
+Displays output in parseable format with a colon as separator.
+.RE
+
+.sp
+.ne 2
+.na
\fB\fB-c\fR \fIclass\fR\fR
.ad
.RS 16n
@@ -83,6 +92,15 @@ Displays only kstats that match the specified instance.
.sp
.ne 2
.na
+\fB\fB-j\fR\fR
+.ad
+.RS 16n
+Displays output in JSON format.
+.RE
+
+.sp
+.ne 2
+.na
\fB\fB-l\fR\fR
.ad
.RS 16n
@@ -161,7 +179,7 @@ The following operands are supported:
.RS 4n
Alternate method of specifying module, instance, name, and statistic as
described above. Each of the module, instance, name, or statistic specifiers
-may be a shell glob pattern or a Perl regular expression enclosed by '/'
+may be a shell glob pattern or a regular expression enclosed by '/'
characters. It is possible to use both specifier types within a single operand.
Leaving a specifier empty is equivalent to using the '*' glob pattern for that
specifier.
@@ -202,7 +220,7 @@ example$ \fBkstat -p -m unix -i 0 -n system_misc -s 'avenrun*'\fR
example$ \fBkstat -p -s 'avenrun*'\fR
example$ \fBkstat -p 'unix:0:system_misc:avenrun*'\fR
example$ \fBkstat -p ':::avenrun*'\fR
-example$ \fBkstat -p ':::/^avenrun_\ed+min$/'\fR
+example$ \fBkstat -p ':::/^avenrun_[0-9]+min$/'\fR
unix:0:system_misc:avenrun_15min 3
unix:0:system_misc:avenrun_1min 4
@@ -362,11 +380,11 @@ kernel statistics driver
.sp
.LP
\fBdate\fR(1), \fBsh\fR(1), \fBtime\fR(2), \fBgmatch\fR(3GEN),
-\fBkstat\fR(3KSTAT), \fBattributes\fR(5), \fBkstat\fR(7D), \fBsd\fR(7D),
-\fBkstat\fR(9S)
+\fBkstat\fR(3KSTAT), \fBattributes\fR(5), \fBregex\fR(5), \fBkstat\fR(7D),
+\fBsd\fR(7D), \fBkstat\fR(9S)
.SH NOTES
.sp
.LP
-If the pattern argument contains glob or Perl RE metacharacters which are also
+If the pattern argument contains glob or RE metacharacters which are also
shell metacharacters, it will be necessary to enclose the pattern with
appropriate shell quotes.
diff --git a/usr/src/man/man1m/savecore.1m b/usr/src/man/man1m/savecore.1m
index a7e22c6e41..e88ffbf8bc 100644
--- a/usr/src/man/man1m/savecore.1m
+++ b/usr/src/man/man1m/savecore.1m
@@ -1,7 +1,8 @@
'\" te
.\" Copyright (c) 2004, Sun Microsystems, Inc. All Rights Reserved.
.\" Copyright (c) 1983 Regents of the University of California. All rights reserved. The Berkeley software License Agreement specifies the terms and conditions for redistribution.
-.TH SAVECORE 1M "Sep 25, 2004"
+.\" Copyright 2013 Nexenta Systems, Inc. All Rights Reserved.
+.TH SAVECORE 1M "Jan 30, 2013"
.SH NAME
savecore \- save a crash dump of the operating system
.SH SYNOPSIS
@@ -14,13 +15,16 @@ savecore \- save a crash dump of the operating system
.sp
.LP
The \fBsavecore\fR utility saves a crash dump of the kernel (assuming that one
-was made) and writes a reboot message in the shutdown log. It is invoked by the
-\fBdumpadm\fR service each time the system boots.
+was made) and writes a reboot message in the shutdown log. By default, it is
+invoked by the \fBdumpadm\fR service each time the system boots.
.sp
.LP
-\fBsavecore\fR saves the crash dump data in the file
+Depending on the \fBdumpadm\fR(1M) configuration \fBsavecore\fR saves either
+the compressed or uncompressed crash dump. The compressed crash dump is saved in
+the file \fIdirectory\fR\fB/vmdump.\fR\fIn\fR.
+\fBsavecore\fR saves the uncompressed crash dump data in the file
\fIdirectory\fR\fB/vmcore.\fR\fIn\fR and the kernel's namelist in
-\fIdirectory\fR\fB/unix.\fR\fIn.\fR The trailing \fB\&.\fR\fIn\fR in the
+\fIdirectory\fR\fB/unix.\fR\fIn.\fR The trailing \fIn\fR in the
pathnames is replaced by a number which grows every time \fBsavecore\fR is run
in that directory.
.sp
@@ -111,6 +115,15 @@ specified, \fBsavecore\fR saves the crash dump files to the default
.sp
.ne 2
.na
+\fB\fIdirectory\fR\fB/vmdump.\fR\fIn\fR\fR
+.ad
+.RS 29n
+
+.RE
+
+.sp
+.ne 2
+.na
\fB\fIdirectory\fR\fB/vmcore.\fR\fIn\fR\fR
.ad
.RS 29n
@@ -147,7 +160,7 @@ specified, \fBsavecore\fR saves the crash dump files to the default
.sp
.ne 2
.na
-\fB\fB/var/crash/\&'uname \fR\fB-n\fR\fB\&'\fR\fR
+\fB\fB/var/crash/\&`uname \fR\fB-n\fR\fB\&`\fR\fR
.ad
.RS 29n
default crash dump directory
diff --git a/usr/src/man/man1m/syseventconfd.1m b/usr/src/man/man1m/syseventconfd.1m
index ac559248fe..49041a48a7 100644
--- a/usr/src/man/man1m/syseventconfd.1m
+++ b/usr/src/man/man1m/syseventconfd.1m
@@ -1,9 +1,10 @@
'\" te
.\" Copyright (c) 2004, Sun Microsystems, Inc. All Rights Reserved.
+.\" Copyright 2013 Nexenta Systems, Inc. All rights reserved.
.\" The contents of this file are subject to the terms of the Common Development and Distribution License (the "License"). You may not use this file except in compliance with the License.
.\" You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE or http://www.opensolaris.org/os/licensing. See the License for the specific language governing permissions and limitations under the License.
.\" When distributing Covered Code, include this CDDL HEADER in each file and include the License file at usr/src/OPENSOLARIS.LICENSE. If applicable, add the following below this CDDL HEADER, with the fields enclosed by brackets "[]" replaced with your own identifying information: Portions Copyright [yyyy] [name of copyright owner]
-.TH SYSEVENTCONFD 1M "Aug 6, 2004"
+.TH SYSEVENTCONFD 1M "Jan 31, 2013"
.SH NAME
syseventconfd \- kernel system event command invocation daemon
.SH SYNOPSIS
@@ -35,7 +36,7 @@ The root path must match the root path used to invoke \fBsyseventd\fR.
.sp
.ne 2
.na
-\fB\fB/etc/sysevent/syseventconfd_event_service\fR\fR
+\fB\fB/var/run/syseventconfd_door/reg_door\fR\fR
.ad
.sp .6
.RS 4n
diff --git a/usr/src/man/man1m/syseventd.1m b/usr/src/man/man1m/syseventd.1m
index c202b9cbec..b3f163e893 100644
--- a/usr/src/man/man1m/syseventd.1m
+++ b/usr/src/man/man1m/syseventd.1m
@@ -1,9 +1,10 @@
'\" te
.\" Copyright (c) 2004, Sun Microsystems, Inc. All Rights Reserved.
+.\" Copyright 2013 Nexenta Systems, Inc. All rights reserved.
.\" The contents of this file are subject to the terms of the Common Development and Distribution License (the "License"). You may not use this file except in compliance with the License.
.\" You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE or http://www.opensolaris.org/os/licensing. See the License for the specific language governing permissions and limitations under the License.
.\" When distributing Covered Code, include this CDDL HEADER in each file and include the License file at usr/src/OPENSOLARIS.LICENSE. If applicable, add the following below this CDDL HEADER, with the fields enclosed by brackets "[]" replaced with your own identifying information: Portions Copyright [yyyy] [name of copyright owner]
-.TH SYSEVENTD 1M "Aug 6, 2004"
+.TH SYSEVENTD 1M "Jan 31, 2013"
.SH NAME
syseventd \- kernel system event notification daemon
.SH SYNOPSIS
@@ -79,7 +80,7 @@ An error occurred.
.sp
.ne 2
.na
-\fB\fB/etc/sysevent/syseventd_daemon.lock\fR\fR
+\fB\fB/var/run/syseventd.lock\fR\fR
.ad
.sp .6
.RS 4n
@@ -89,7 +90,7 @@ daemon lock file
.sp
.ne 2
.na
-\fB\fB/etc/sysevent/sysevent_door\fR \fR
+\fB\fB/var/run/sysevent_door\fR \fR
.ad
.sp .6
.RS 4n
diff --git a/usr/src/man/man1m/zfs.1m b/usr/src/man/man1m/zfs.1m
index d09ed8f949..4f17e6a3cb 100644
--- a/usr/src/man/man1m/zfs.1m
+++ b/usr/src/man/man1m/zfs.1m
@@ -24,10 +24,10 @@
.\" Copyright 2011 Joshua M. Clulow <josh@sysmgr.org>
.\" Copyright (c) 2012 by Delphix. All rights reserved.
.\" Copyright (c) 2012, Joyent, Inc. All rights reserved.
-.\" Copyright 2012 Nexenta Systems, Inc. All Rights Reserved.
.\" Copyright (c) 2013 by Saso Kiselkov. All rights reserved.
+.\" Copyright 2013 Nexenta Systems, Inc. All Rights Reserved.
.\"
-.TH ZFS 1M "Aug 16, 2012"
+.TH ZFS 1M "Jan 26, 2013"
.SH NAME
zfs \- configures ZFS file systems
.SH SYNOPSIS
@@ -38,12 +38,12 @@ zfs \- configures ZFS file systems
.LP
.nf
-\fBzfs\fR \fBcreate\fR [\fB-p\fR] [\fB-o\fR \fIproperty\fR=\fIvalue\fR] ... \fIfilesystem\fR
+\fBzfs\fR \fBcreate\fR [\fB-p\fR] [\fB-o\fR \fIproperty\fR=\fIvalue\fR]... \fIfilesystem\fR
.fi
.LP
.nf
-\fBzfs\fR \fBcreate\fR [\fB-ps\fR] [\fB-b\fR \fIblocksize\fR] [\fB-o\fR \fIproperty\fR=\fIvalue\fR] ... \fB-V\fR \fIsize\fR \fIvolume\fR
+\fBzfs\fR \fBcreate\fR [\fB-ps\fR] [\fB-b\fR \fIblocksize\fR] [\fB-o\fR \fIproperty\fR=\fIvalue\fR]... \fB-V\fR \fIsize\fR \fIvolume\fR
.fi
.LP
@@ -53,7 +53,7 @@ zfs \- configures ZFS file systems
.LP
.nf
-\fBzfs\fR \fBdestroy\fR [\fB-dnpRrv\fR] \fIfilesystem\fR|\fIvolume\fR@\fIsnap\fR[%\fIsnap\fR][,...]
+\fBzfs\fR \fBdestroy\fR [\fB-dnpRrv\fR] \fIfilesystem\fR|\fIvolume\fR@\fIsnap\fR[%\fIsnap\fR][,\fIsnap\fR[%\fIsnap\fR]]...
.fi
.LP
@@ -69,7 +69,7 @@ zfs \- configures ZFS file systems
.LP
.nf
-\fBzfs\fR \fBclone\fR [\fB-p\fR] [\fB-o\fR \fIproperty\fR=\fIvalue\fR] ... \fIsnapshot\fR \fIfilesystem\fR|\fIvolume\fR
+\fBzfs\fR \fBclone\fR [\fB-p\fR] [\fB-o\fR \fIproperty\fR=\fIvalue\fR]... \fIsnapshot\fR \fIfilesystem\fR|\fIvolume\fR
.fi
.LP
@@ -95,24 +95,25 @@ zfs \- configures ZFS file systems
.LP
.nf
-\fBzfs\fR \fBlist\fR [\fB-r\fR|\fB-d\fR \fIdepth\fR][\fB-Hp\fR][\fB-o\fR \fIproperty\fR[,...]] [\fB-t\fR \fItype\fR[,...]]
- [\fB-s\fR \fIproperty\fR] ... [\fB-S\fR \fIproperty\fR] ... [\fIfilesystem\fR|\fIvolume\fR|\fIsnapshot\fR] ...
+\fBzfs\fR \fBlist\fR [\fB-r\fR|\fB-d\fR \fIdepth\fR][\fB-Hp\fR][\fB-o\fR \fIproperty\fR[,\fIproperty\fR]...] [\fB-t\fR \fItype\fR[,\fItype\fR]...]
+ [\fB-s\fR \fIproperty\fR]... [\fB-S\fR \fIproperty\fR]... [\fIfilesystem\fR|\fIvolume\fR|\fIsnapshot\fR]...
.fi
.LP
.nf
-\fBzfs\fR \fBset\fR \fIproperty\fR=\fIvalue\fR \fIfilesystem\fR|\fIvolume\fR|\fIsnapshot\fR ...
+\fBzfs\fR \fBset\fR \fIproperty\fR=\fIvalue\fR \fIfilesystem\fR|\fIvolume\fR|\fIsnapshot\fR...
.fi
.LP
.nf
-\fBzfs\fR \fBget\fR [\fB-r\fR|\fB-d\fR \fIdepth\fR][\fB-Hpc\fR][\fB-o\fR \fIfield\fR[,...]] [\fB-t\fR \fItype\fR[,...]]
- [\fB-s\fR \fIsource\fR[,...]] "\fIall\fR" | \fIproperty\fR[,...] \fIfilesystem\fR|\fIvolume\fR|\fIsnapshot\fR ...
+\fBzfs\fR \fBget\fR [\fB-r\fR|\fB-d\fR \fIdepth\fR][\fB-Hpc\fR][\fB-o\fR \fIfield\fR[,\fIfield\fR]...] [\fB-t\fR \fItype\fR[,\fItype\fR]...]
+ [\fB-s\fR \fIsource\fR[,\fIsource\fR]...] \fBall\fR | \fIproperty\fR[,\fIproperty\fR]...
+ \fIfilesystem\fR|\fIvolume\fR|\fIsnapshot\fR...
.fi
.LP
.nf
-\fBzfs\fR \fBinherit\fR [\fB-r\fR] \fIproperty\fR \fIfilesystem\fR|\fIvolume|snapshot\fR ...
+\fBzfs\fR \fBinherit\fR [\fB-r\fR] \fIproperty\fR \fIfilesystem\fR|\fIvolume|snapshot\fR...
.fi
.LP
@@ -127,14 +128,14 @@ zfs \- configures ZFS file systems
.LP
.nf
-\fBzfs\fR \fBuserspace\fR [\fB-Hinp\fR] [\fB-o\fR \fIfield\fR[,...]] [\fB-s\fR \fIfield\fR] ...
- [\fB-S\fR \fIfield\fR] ... [\fB-t\fR \fItype\fR[,...]] \fIfilesystem\fR|\fIsnapshot\fR
+\fBzfs\fR \fBuserspace\fR [\fB-Hinp\fR] [\fB-o\fR \fIfield\fR[,\fIfield\fR]...] [\fB-s\fR \fIfield\fR]...
+ [\fB-S\fR \fIfield\fR]... [\fB-t\fR \fItype\fR[,\fItype\fR]...] \fIfilesystem\fR|\fIsnapshot\fR
.fi
.LP
.nf
-\fBzfs\fR \fBgroupspace\fR [\fB-Hinp\fR] [\fB-o\fR \fIfield\fR[,...]] [\fB-s\fR \fIfield\fR] ...
- [\fB-S\fR \fIfield\fR] ... [\fB-t\fR \fItype\fR[,...]] \fIfilesystem\fR|\fIsnapshot\fR
+\fBzfs\fR \fBgroupspace\fR [\fB-Hinp\fR] [\fB-o\fR \fIfield\fR[,\fIfield\fR]...] [\fB-s\fR \fIfield\fR]...
+ [\fB-S\fR \fIfield\fR]... [\fB-t\fR \fItype\fR[,\fItype\fR]...] \fIfilesystem\fR|\fIsnapshot\fR
.fi
.LP
@@ -184,44 +185,47 @@ zfs \- configures ZFS file systems
.LP
.nf
-\fBzfs\fR \fBallow\fR [\fB-ldug\fR] "\fIeveryone\fR"|\fIuser\fR|\fIgroup\fR[,...] \fIperm\fR|\fI@setname\fR[,...]
- \fIfilesystem\fR|\fIvolume\fR
+\fBzfs\fR \fBallow\fR [\fB-ldug\fR] \fIuser\fR|\fIgroup\fR[,\fIuser\fR|\fIgroup\fR]...
+ \fIperm\fR|\fI@setname\fR[,\fIperm\fR|\fI@setname\fR]... \fIfilesystem\fR|\fIvolume\fR
.fi
.LP
.nf
-\fBzfs\fR \fBallow\fR [\fB-ld\fR] \fB-e\fR \fIperm\fR|@\fIsetname\fR[,...] \fIfilesystem\fR|\fIvolume\fR
+\fBzfs\fR \fBallow\fR [\fB-ld\fR] \fB-e\fR|\fBeveryone\fR \fIperm\fR|@\fIsetname\fR[,\fIperm\fR|\fI@setname\fR]...
+ \fIfilesystem\fR|\fIvolume\fR
.fi
.LP
.nf
-\fBzfs\fR \fBallow\fR \fB-c\fR \fIperm\fR|@\fIsetname\fR[,...] \fIfilesystem\fR|\fIvolume\fR
+\fBzfs\fR \fBallow\fR \fB-c\fR \fIperm\fR|@\fIsetname\fR[,\fIperm\fR|\fI@setname\fR]... \fIfilesystem\fR|\fIvolume\fR
.fi
.LP
.nf
-\fBzfs\fR \fBallow\fR \fB-s\fR @\fIsetname\fR \fIperm\fR|@\fIsetname\fR[,...] \fIfilesystem\fR|\fIvolume\fR
+\fBzfs\fR \fBallow\fR \fB-s\fR @\fIsetname\fR \fIperm\fR|@\fIsetname\fR[,\fIperm\fR|\fI@setname\fR]... \fIfilesystem\fR|\fIvolume\fR
.fi
.LP
.nf
-\fBzfs\fR \fBunallow\fR [\fB-rldug\fR] "\fIeveryone\fR"|\fIuser\fR|\fIgroup\fR[,...] [\fIperm\fR|@\fIsetname\fR[,... ]]
- \fIfilesystem\fR|\fIvolume\fR
+\fBzfs\fR \fBunallow\fR [\fB-rldug\fR] \fIuser\fR|\fIgroup\fR[,\fIuser\fR|\fIgroup\fR]...
+ [\fIperm\fR|@\fIsetname\fR[,\fIperm\fR|\fI@setname\fR]...] \fIfilesystem\fR|\fIvolume\fR
.fi
.LP
.nf
-\fBzfs\fR \fBunallow\fR [\fB-rld\fR] \fB-e\fR [\fIperm\fR|@\fIsetname\fR[,... ]] \fIfilesystem\fR|\fIvolume\fR
+\fBzfs\fR \fBunallow\fR [\fB-rld\fR] \fB-e\fR|\fBeveryone\fR [\fIperm\fR|@\fIsetname\fR[,\fIperm\fR|\fI@setname\fR]...]
+ \fIfilesystem\fR|\fIvolume\fR
.fi
.LP
.nf
-\fBzfs\fR \fBunallow\fR [\fB-r\fR] \fB-c\fR [\fIperm\fR|@\fIsetname\fR[ ... ]] \fIfilesystem\fR|\fIvolume\fR
+\fBzfs\fR \fBunallow\fR [\fB-r\fR] \fB-c\fR [\fIperm\fR|@\fIsetname\fR[,\fIperm\fR|\fI@setname\fR]...] \fIfilesystem\fR|\fIvolume\fR
.fi
.LP
.nf
-\fBzfs\fR \fBunallow\fR [\fB-r\fR] \fB-s\fR @\fIsetname\fR [\fIperm\fR|@\fIsetname\fR[,... ]] \fIfilesystem\fR|\fIvolume\fR
+\fBzfs\fR \fBunallow\fR [\fB-r\fR] \fB-s\fR @\fIsetname\fR [\fIperm\fR|@\fIsetname\fR[,\fIperm\fR|\fI@setname\fR]...]
+ \fIfilesystem\fR|\fIvolume\fR
.fi
.LP
@@ -1626,7 +1630,7 @@ Displays a help message.
.sp
.ne 2
.na
-\fB\fBzfs create\fR [\fB-p\fR] [\fB-o\fR \fIproperty\fR=\fIvalue\fR] ...
+\fB\fBzfs create\fR [\fB-p\fR] [\fB-o\fR \fIproperty\fR=\fIvalue\fR]...
\fIfilesystem\fR\fR
.ad
.sp .6
@@ -1667,7 +1671,7 @@ property is specified in multiple \fB-o\fR options.
.ne 2
.na
\fB\fBzfs create\fR [\fB-ps\fR] [\fB-b\fR \fIblocksize\fR] [\fB-o\fR
-\fIproperty\fR=\fIvalue\fR] ... \fB-V\fR \fIsize\fR \fIvolume\fR\fR
+\fIproperty\fR=\fIvalue\fR]... \fB-V\fR \fIsize\fR \fIvolume\fR\fR
.ad
.sp .6
.RS 4n
@@ -1814,7 +1818,7 @@ behavior for mounted file systems in use.
.sp
.ne 2
.na
-\fBzfs destroy\fR [\fB-dnpRrv\fR] \fIfilesystem\fR|\fIvolume\fR@\fIsnap\fR[%\fIsnap\fR][,...]
+\fBzfs destroy\fR [\fB-dnpRrv\fR] \fIfilesystem\fR|\fIvolume\fR@\fIsnap\fR[%\fIsnap\fR][,\fIsnap\fR[%\fIsnap\fR]]...
.ad
.sp .6
.RS 4n
@@ -1910,7 +1914,7 @@ behavior for mounted file systems in use.
.sp
.ne 2
.na
-\fB\fBzfs snapshot\fR [\fB-r\fR] [\fB-o\fR \fIproperty\fR=\fIvalue\fR] ...
+\fB\fBzfs snapshot\fR [\fB-r\fR] [\fB-o\fR \fIproperty\fR=\fIvalue\fR]...
\fIfilesystem@snapname\fR|\fIvolume@snapname\fR\fR...
.ad
.sp .6
@@ -1996,7 +2000,7 @@ that are to be destroyed.
.sp
.ne 2
.na
-\fB\fBzfs clone\fR [\fB-p\fR] [\fB-o\fR \fIproperty\fR=\fIvalue\fR] ...
+\fB\fBzfs clone\fR [\fB-p\fR] [\fB-o\fR \fIproperty\fR=\fIvalue\fR]...
\fIsnapshot\fR \fIfilesystem\fR|\fIvolume\fR\fR
.ad
.sp .6
@@ -2111,9 +2115,9 @@ only dataset that can be renamed recursively.
.ne 2
.na
\fB\fBzfs\fR \fBlist\fR [\fB-r\fR|\fB-d\fR \fIdepth\fR] [\fB-Hp\fR] [\fB-o\fR
-\fIproperty\fR[,\fI\&...\fR]] [ \fB-t\fR \fItype\fR[,\fI\&...\fR]] [ \fB-s\fR
-\fIproperty\fR ] ... [ \fB-S\fR \fIproperty\fR ] ...
-[\fIfilesystem\fR|\fIvolume\fR|\fIsnapshot\fR] ...\fR
+\fIproperty\fR[,\fIproperty\fR]...] [ \fB-t\fR \fItype\fR[,\fItype\fR]...] [ \fB-s\fR
+\fIproperty\fR ]... [ \fB-S\fR \fIproperty\fR ]...
+[\fIfilesystem\fR|\fIvolume\fR|\fIsnapshot\fR]...\fR
.ad
.sp .6
.RS 4n
@@ -2275,7 +2279,7 @@ Display numbers in parseable (exact) values.
.ne 2
.na
\fB\fBzfs set\fR \fIproperty\fR=\fIvalue\fR
-\fIfilesystem\fR|\fIvolume\fR|\fIsnapshot\fR ...\fR
+\fIfilesystem\fR|\fIvolume\fR|\fIsnapshot\fR...\fR
.ad
.sp .6
.RS 4n
@@ -2293,8 +2297,8 @@ Properties" section.
.ne 2
.na
\fB\fBzfs get\fR [\fB-r\fR|\fB-d\fR \fIdepth\fR] [\fB-Hpc\fR] [\fB-o\fR
-\fIfield\fR[,...] [\fB-t\fR \fItype\fR[,...]] [\fB-s\fR \fIsource\fR[,...] "\fIall\fR" |
-\fIproperty\fR[,...] \fIfilesystem\fR|\fIvolume\fR|\fIsnapshot\fR ...\fR
+\fIfield\fR[,\fIfield\fR]... [\fB-t\fR \fItype\fR[,\fItype\fR]...] [\fB-s\fR \fIsource\fR[,\fIsource\fR]... \fBall\fR |
+\fIproperty\fR[,\fIproperty\fR]... \fIfilesystem\fR|\fIvolume\fR|\fIsnapshot\fR...\fR
.ad
.sp .6
.RS 4n
@@ -2406,7 +2410,7 @@ volume's size and block size.
.ne 2
.na
\fB\fBzfs inherit\fR [\fB-r\fR] \fIproperty\fR
-\fIfilesystem\fR|\fIvolume\fR|\fIsnapshot\fR ...\fR
+\fIfilesystem\fR|\fIvolume\fR|\fIsnapshot\fR...\fR
.ad
.sp .6
.RS 4n
@@ -2503,10 +2507,10 @@ supported by this software.
.sp
.ne 2
.na
-\fBzfs\fR \fBuserspace\fR [\fB-Hinp\fR] [\fB-o\fR \fIfield\fR[,...]]
-[\fB-s\fR \fIfield\fR] ...
-[\fB-S\fR \fIfield\fR] ...
-[\fB-t\fR \fItype\fR[,...]] \fIfilesystem\fR|\fIsnapshot\fR
+\fBzfs\fR \fBuserspace\fR [\fB-Hinp\fR] [\fB-o\fR \fIfield\fR[,\fIfield\fR]...]
+[\fB-s\fR \fIfield\fR]...
+[\fB-S\fR \fIfield\fR]...
+[\fB-t\fR \fItype\fR[,\fItype\fR]...] \fIfilesystem\fR|\fIsnapshot\fR
.ad
.sp .6
.RS 4n
@@ -2546,7 +2550,7 @@ Use exact (parsable) numeric output.
.sp
.ne 2
.na
-\fB\fB-o\fR \fIfield\fR[,...]\fR
+\fB\fB-o\fR \fIfield\fR[,\fIfield\fR]...\fR
.ad
.sp .6
.RS 4n
@@ -2579,7 +2583,7 @@ Sort by this field in reverse order. See \fB-s\fR.
.sp
.ne 2
.na
-\fB\fB-t\fR \fItype\fR[,...]\fR
+\fB\fB-t\fR \fItype\fR[,\fItype\fR]...\fR
.ad
.sp .6
.RS 4n
@@ -2611,10 +2615,10 @@ will report that the POSIX entity has the total usage and quota for both.
.sp
.ne 2
.na
-\fBzfs\fR \fBgroupspace\fR [\fB-Hinp\fR] [\fB-o\fR \fIfield\fR[,...]]
-[\fB-s\fR \fIfield\fR] ...
-[\fB-S\fR \fIfield\fR] ...
-[\fB-t\fR \fItype\fR[,...]] \fIfilesystem\fR|\fIsnapshot\fR
+\fBzfs\fR \fBgroupspace\fR [\fB-Hinp\fR] [\fB-o\fR \fIfield\fR[,\fIfield\fR]...]
+[\fB-s\fR \fIfield\fR]...
+[\fB-S\fR \fIfield\fR]...
+[\fB-t\fR \fItype\fR[,\fItype\fR]...] \fIfilesystem\fR|\fIsnapshot\fR
.ad
.sp .6
.RS 4n
@@ -3075,13 +3079,13 @@ volume. See the other forms of \fBzfs allow\fR for more information.
.sp
.ne 2
.na
-\fB\fBzfs allow\fR [\fB-ldug\fR] "\fIeveryone\fR"|\fIuser\fR|\fIgroup\fR[,...]
-\fIperm\fR|@\fIsetname\fR[,...] \fIfilesystem\fR| \fIvolume\fR\fR
+\fB\fBzfs allow\fR [\fB-ldug\fR] \fIuser\fR|\fIgroup\fR[,\fIuser\fR|\fIgroup\fR]...
+\fIperm\fR|@\fIsetname\fR[,\fIperm\fR|@\fIsetname\fR]... \fIfilesystem\fR|\fIvolume\fR\fR
.ad
.br
.na
-\fB\fBzfs allow\fR [\fB-ld\fR] \fB-e\fR \fIperm\fR|@\fIsetname\fR[,...]
-\fIfilesystem\fR | \fIvolume\fR\fR
+\fB\fBzfs allow\fR [\fB-ld\fR] \fB-e\fR|\fBeveryone\fR \fIperm\fR|@\fIsetname\fR[,\fIperm\fR|@\fIsetname\fR]...
+\fIfilesystem\fR|\fIvolume\fR\fR
.ad
.sp .6
.RS 4n
@@ -3090,14 +3094,14 @@ non-privileged users.
.sp
.ne 2
.na
-\fB[\fB-ug\fR] "\fIeveryone\fR"|\fIuser\fR|\fIgroup\fR[,...]\fR
+[\fB-ug\fR] \fIuser\fR|\fIgroup\fR[,\fIuser\fR|\fIgroup\fR]...
.ad
.sp .6
.RS 4n
Specifies to whom the permissions are delegated. Multiple entities can be
specified as a comma-separated list. If neither of the \fB-ug\fR options are
specified, then the argument is interpreted preferentially as the keyword
-"everyone", then as a user name, and lastly as a group name. To specify a user
+\fBeveryone,\fR then as a user name, and lastly as a group name. To specify a user
or group named "everyone", use the \fB-u\fR or \fB-g\fR options. To specify a
group with the same name as a user, use the \fB-g\fR options.
.RE
@@ -3105,11 +3109,21 @@ group with the same name as a user, use the \fB-g\fR options.
.sp
.ne 2
.na
-\fB[\fB-e\fR] \fIperm\fR|@\fIsetname\fR[,...]\fR
+\fB-e\fR|\fBeveryone\fR
+.ad
+.sp .6
+.RS 4n
+Specifies that the permissions be delegated to everyone.
+.RE
+
+.sp
+.ne 2
+.na
+\fIperm\fR|@\fIsetname\fR[,\fIperm\fR|@\fIsetname\fR]...
.ad
.sp .6
.RS 4n
-Specifies that the permissions be delegated to "everyone." Multiple permissions
+The permissions to delegate. Multiple permissions
may be specified as a comma-separated list. Permission names are the same as
\fBZFS\fR subcommand and property names. See the property list below. Property
set names, which begin with an at sign (\fB@\fR) , may be specified. See the
@@ -3119,7 +3133,7 @@ set names, which begin with an at sign (\fB@\fR) , may be specified. See the
.sp
.ne 2
.na
-\fB[\fB-ld\fR] \fIfilesystem\fR|\fIvolume\fR\fR
+[\fB-ld\fR] \fIfilesystem\fR|\fIvolume\fR
.ad
.sp .6
.RS 4n
@@ -3209,7 +3223,7 @@ zoned property
.sp
.ne 2
.na
-\fB\fBzfs allow\fR \fB-c\fR \fIperm\fR|@\fIsetname\fR[,...]
+\fB\fBzfs allow\fR \fB-c\fR \fIperm\fR|@\fIsetname\fR[,\fIperm\fR|@\fIsetname\fR]...
\fIfilesystem\fR|\fIvolume\fR\fR
.ad
.sp .6
@@ -3221,7 +3235,7 @@ creator of any newly-created descendent file system.
.sp
.ne 2
.na
-\fB\fBzfs allow\fR \fB-s\fR @\fIsetname\fR \fIperm\fR|@\fIsetname\fR[,...]
+\fB\fBzfs allow\fR \fB-s\fR @\fIsetname\fR \fIperm\fR|@\fIsetname\fR[,\fIperm\fR|@\fIsetname\fR]...
\fIfilesystem\fR|\fIvolume\fR\fR
.ad
.sp .6
@@ -3237,18 +3251,17 @@ characters long.
.sp
.ne 2
.na
-\fB\fBzfs unallow\fR [\fB-rldug\fR]
-"\fIeveryone\fR"|\fIuser\fR|\fIgroup\fR[,...]
-[\fIperm\fR|@\fIsetname\fR[, ...]] \fIfilesystem\fR|\fIvolume\fR\fR
+\fB\fBzfs unallow\fR [\fB-rldug\fR] \fIuser\fR|\fIgroup\fR[,\fIuser\fR|\fIgroup\fR]...
+[\fIperm\fR|@\fIsetname\fR[,\fIperm\fR|@\fIsetname\fR]...] \fIfilesystem\fR|\fIvolume\fR\fR
.ad
.br
.na
-\fB\fBzfs unallow\fR [\fB-rld\fR] \fB-e\fR [\fIperm\fR|@\fIsetname\fR [,...]]
+\fB\fBzfs unallow\fR [\fB-rld\fR] \fB-e\fR|\fBeveryone\fR [\fIperm\fR|@\fIsetname\fR[,\fIperm\fR|@\fIsetname\fR]...]
\fIfilesystem\fR|\fIvolume\fR\fR
.ad
.br
.na
-\fB\fBzfs unallow\fR [\fB-r\fR] \fB-c\fR [\fIperm\fR|@\fIsetname\fR[,...]]\fR
+\fB\fBzfs unallow\fR [\fB-r\fR] \fB-c\fR [\fIperm\fR|@\fIsetname\fR[,\fIperm\fR|@\fIsetname\fR]...]\fR
.ad
.br
.na
@@ -3260,8 +3273,8 @@ Removes permissions that were granted with the \fBzfs allow\fR command. No
permissions are explicitly denied, so other permissions granted are still in
effect. For example, if the permission is granted by an ancestor. If no
permissions are specified, then all permissions for the specified \fIuser\fR,
-\fIgroup\fR, or \fIeveryone\fR are removed. Specifying "everyone" (or using the
-\fB-e\fR option) only removes the permissions that were granted to "everyone",
+\fIgroup\fR, or everyone are removed. Specifying \fBeveryone\fR (or using the
+\fB-e\fR option) only removes the permissions that were granted to everyone,
not all permissions for every user and group. See the \fBzfs allow\fR command
for a description of the \fB-ldugec\fR options.
.sp
@@ -3280,7 +3293,7 @@ Recursively remove the permissions from this file system and all descendents.
.ne 2
.na
\fB\fBzfs unallow\fR [\fB-r\fR] \fB-s\fR @\fIsetname\fR
-[\fIperm\fR|@\fIsetname\fR[,...]]\fR
+[\fIperm\fR|@\fIsetname\fR[,\fIperm\fR|@\fIsetname\fR]...]\fR
.ad
.br
.na
diff --git a/usr/src/man/man4/smb.4 b/usr/src/man/man4/smb.4
index b9744d405c..1bce91817e 100644
--- a/usr/src/man/man4/smb.4
+++ b/usr/src/man/man4/smb.4
@@ -1,5 +1,6 @@
'\" te
.\" Copyright (c) 2009, Sun Microsystems, Inc. All Rights Reserved.
+.\" Copyright 2011, Nexenta Systems, Inc. All Rights Reserved.
.\" The contents of this file are subject to the terms of the Common Development and Distribution License (the "License"). You may not use this file except in compliance with the License. You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE or http://www.opensolaris.org/os/licensing.
.\" See the License for the specific language governing permissions and limitations under the License. When distributing Covered Code, include this CDDL HEADER in each file and include the License file at usr/src/OPENSOLARIS.LICENSE. If applicable, add the following below this CDDL HEADER, with the
.\" fields enclosed by brackets "[]" replaced with your own identifying information: Portions Copyright [yyyy] [name of copyright owner]
@@ -401,6 +402,20 @@ Network Places on Windows clients. By default, no value is set.
.sp
.ne 2
.na
+\fB\fBtraverse_mounts\fR\fR
+.ad
+.sp .6
+.RS 4n
+The \fBtraverse_mounts\fR setting determines how the SMB server
+presents sub-mounts underneath an SMB share. When \fBtraverse_mounts\fR
+is \fBtrue\fR (the default), sub-mounts are presented to SMB clients
+like any other subdirectory. When \fBtraverse_mounts\fR is \fBfalse\fR,
+sub-mounts are not shown to SMB clients.
+.RE
+
+.sp
+.ne 2
+.na
\fB\fBunmap\fR\fR
.ad
.sp .6
diff --git a/usr/src/man/man4/ssh_config.4 b/usr/src/man/man4/ssh_config.4
index 7f2a9bb64e..31bc180f87 100644
--- a/usr/src/man/man4/ssh_config.4
+++ b/usr/src/man/man4/ssh_config.4
@@ -1,11 +1,11 @@
'\" te
.\" Copyright (c) 2009, Sun Microsystems, Inc. All Rights Reserved.
-.\" Copyright (c) 2012, Joyent, Inc. All Rights Reserved.
+.\" Copyright (c) 2013, Joyent, Inc. All Rights Reserved.
.\" To view Portions Copyright for OpenSSH, the default path is /var/sadm/pkg/SUNWsshdr/install/copyright. If the Solaris operating environment has been installed anywhere other than the default, modify the specified path to access the file at the installed location.
.\" The contents of this file are subject to the terms of the Common Development and Distribution License (the "License"). You may not use this file except in compliance with the License. You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE or http://www.opensolaris.org/os/licensing.
.\" See the License for the specific language governing permissions and limitations under the License. When distributing Covered Code, include this CDDL HEADER in each file and include the License file at usr/src/OPENSOLARIS.LICENSE. If applicable, add the following below this CDDL HEADER, with
.\" the fields enclosed by brackets "[]" replaced with your own identifying information: Portions Copyright [yyyy] [name of copyright owner]
-.TH SSH_CONFIG 4 "Apr 20, 2009"
+.TH SSH_CONFIG 4 "Jan 17, 2013"
.SH NAME
ssh_config \- ssh configuration file
.SH SYNOPSIS
diff --git a/usr/src/man/man4/sshd_config.4 b/usr/src/man/man4/sshd_config.4
index d87b71d491..bdc044886d 100644
--- a/usr/src/man/man4/sshd_config.4
+++ b/usr/src/man/man4/sshd_config.4
@@ -1,10 +1,10 @@
'\" te
.\" Copyright (c) 2009, Sun Microsystems, Inc. All Rights Reserved.
-.\" Copyright (c) 2012, Joyent, Inc. All Rights Reserved.
+.\" Copyright (c) 2013, Joyent, Inc. All Rights Reserved.
.\" The contents of this file are subject to the terms of the Common Development and Distribution License (the "License"). You may not use this file except in compliance with the License. You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE or http://www.opensolaris.org/os/licensing.
.\" See the License for the specific language governing permissions and limitations under the License. When distributing Covered Code, include this CDDL HEADER in each file and include the License file at usr/src/OPENSOLARIS.LICENSE. If applicable, add the following below this CDDL HEADER, with the
.\" fields enclosed by brackets "[]" replaced with your own identifying information: Portions Copyright [yyyy] [name of copyright owner]
-.TH SSHD_CONFIG 4 "Mar 26, 2009"
+.TH SSHD_CONFIG 4 "Jan 17, 2013"
.SH NAME
sshd_config \- sshd configuration file
.SH SYNOPSIS
diff --git a/usr/src/man/man5/zpool-features.5 b/usr/src/man/man5/zpool-features.5
index 63523f7cb9..94aac84f47 100644
--- a/usr/src/man/man5/zpool-features.5
+++ b/usr/src/man/man5/zpool-features.5
@@ -1,7 +1,7 @@
'\" te
.\" Copyright (c) 2012 by Delphix. All rights reserved.
-.\" Copyright (c) 2012 Joyent, Inc. All rights reserved.
.\" Copyright (c) 2013 by Saso Kiselkov. All rights reserved.
+.\" Copyright (c) 2012 Joyent, Inc. All rights reserved.
.\" The contents of this file are subject to the terms of the Common Development
.\" and Distribution License (the "License"). You may not use this file except
.\" in compliance with the License. You can obtain a copy of the license at
@@ -229,7 +229,11 @@ read-only compatible, this operation will render the pool unimportable
on systems without support for the \fBlz4_compress\fR feature. At the
moment, this operation cannot be reversed. Booting off of
\fBlz4\fR-compressed root pools is supported.
+.RE
+.sp
+.ne 2
+.na
\fB\fBfilesystem_limits\fR\fR
.ad
.RS 4n
diff --git a/usr/src/pkg/manifests/driver-serial-usbftdi.mf b/usr/src/pkg/manifests/driver-serial-usbftdi.mf
index 2a248dc611..b502a96c42 100644
--- a/usr/src/pkg/manifests/driver-serial-usbftdi.mf
+++ b/usr/src/pkg/manifests/driver-serial-usbftdi.mf
@@ -64,6 +64,7 @@ driver name=usbftdi perms="* 0666 root sys" \
alias=usb856,ac01 \
alias=usb93c,0601 \
alias=usb93c,0701 \
+ alias=usbif403,6010.config1.1 \
alias=usbif9e88,9e8f.config1.1
file path=kernel/drv/$(ARCH64)/usbftdi group=sys
$(i386_ONLY)file path=kernel/drv/usbftdi group=sys
diff --git a/usr/src/pkg/manifests/system-dtrace-tests.mf b/usr/src/pkg/manifests/system-dtrace-tests.mf
index b740da5a4f..709b1f6a92 100644
--- a/usr/src/pkg/manifests/system-dtrace-tests.mf
+++ b/usr/src/pkg/manifests/system-dtrace-tests.mf
@@ -1253,6 +1253,7 @@ file path=opt/SUNWdtrt/tst/common/preprocessor/tst.preexpifelse.d mode=0444
file path=opt/SUNWdtrt/tst/common/preprocessor/tst.preexpifelse.d.out \
mode=0444
file path=opt/SUNWdtrt/tst/common/preprocessor/tst.withinprobe.d mode=0444
+file path=opt/SUNWdtrt/tst/common/print/err.D_PRINT_AGG.bad.d mode=0444
file path=opt/SUNWdtrt/tst/common/print/err.D_PRINT_VOID.bad.d mode=0444
file path=opt/SUNWdtrt/tst/common/print/err.D_PROTO_LEN.bad.d mode=0444
file path=opt/SUNWdtrt/tst/common/print/tst.array.d mode=0444
@@ -1801,6 +1802,7 @@ file path=opt/SUNWdtrt/tst/common/tick-n/tst.tickus.d.out mode=0444
file path=opt/SUNWdtrt/tst/common/tick-n/tst.tickusec.d mode=0444
file path=opt/SUNWdtrt/tst/common/tick-n/tst.tickusec.d.out mode=0444
file path=opt/SUNWdtrt/tst/common/trace/err.D_PROTO_LEN.bad.d mode=0444
+file path=opt/SUNWdtrt/tst/common/trace/err.D_TRACE_AGG.bad.d mode=0444
file path=opt/SUNWdtrt/tst/common/trace/err.D_TRACE_VOID.bad.d mode=0444
file path=opt/SUNWdtrt/tst/common/trace/tst.dyn.d mode=0444
file path=opt/SUNWdtrt/tst/common/trace/tst.misc.d mode=0444
@@ -1936,6 +1938,7 @@ file path=opt/SUNWdtrt/tst/common/types/tst.bitops.d mode=0444
file path=opt/SUNWdtrt/tst/common/types/tst.charconstants.d mode=0444
file path=opt/SUNWdtrt/tst/common/types/tst.complex.d mode=0444
file path=opt/SUNWdtrt/tst/common/types/tst.condexpr.d mode=0444
+file path=opt/SUNWdtrt/tst/common/types/tst.const.d mode=0444
file path=opt/SUNWdtrt/tst/common/types/tst.constants.d mode=0444
file path=opt/SUNWdtrt/tst/common/types/tst.conv.d mode=0444
file path=opt/SUNWdtrt/tst/common/types/tst.enum.d mode=0444
diff --git a/usr/src/pkg/manifests/system-test-zfstest.mf b/usr/src/pkg/manifests/system-test-zfstest.mf
index 7c5beaec2b..4b137334cc 100644
--- a/usr/src/pkg/manifests/system-test-zfstest.mf
+++ b/usr/src/pkg/manifests/system-test-zfstest.mf
@@ -10,7 +10,7 @@
#
#
-# Copyright (c) 2012 by Delphix. All rights reserved.
+# Copyright (c) 2013 by Delphix. All rights reserved.
#
set name=pkg.fmri value=pkg:/system/test/zfstest@$(PKGVERS)
@@ -111,6 +111,9 @@ file path=opt/zfs-tests/tests/functional/acl/cifs/cleanup mode=0555
file path=opt/zfs-tests/tests/functional/acl/cifs/setup mode=0555
file path=opt/zfs-tests/tests/functional/acl/nontrivial/cleanup mode=0555
file path=opt/zfs-tests/tests/functional/acl/nontrivial/setup mode=0555
+file \
+ path=opt/zfs-tests/tests/functional/acl/nontrivial/zfs_acl_aclmode_restricted_001_neg \
+ mode=0555
file path=opt/zfs-tests/tests/functional/acl/nontrivial/zfs_acl_chmod_001_neg \
mode=0555
file path=opt/zfs-tests/tests/functional/acl/nontrivial/zfs_acl_chmod_002_pos \
@@ -183,6 +186,9 @@ file path=opt/zfs-tests/tests/functional/acl/nontrivial/zfs_acl_tar_002_pos \
mode=0555
file path=opt/zfs-tests/tests/functional/acl/trivial/cleanup mode=0555
file path=opt/zfs-tests/tests/functional/acl/trivial/setup mode=0555
+file \
+ path=opt/zfs-tests/tests/functional/acl/trivial/zfs_acl_aclmode_restricted_001_pos \
+ mode=0555
file path=opt/zfs-tests/tests/functional/acl/trivial/zfs_acl_chmod_001_pos \
mode=0555
file path=opt/zfs-tests/tests/functional/acl/trivial/zfs_acl_compress_001_pos \
diff --git a/usr/src/test/README b/usr/src/test/README
new file mode 100644
index 0000000000..f3fe2b8253
--- /dev/null
+++ b/usr/src/test/README
@@ -0,0 +1,86 @@
+#
+# 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) 2013 by Delphix. All rights reserved.
+#
+
+illumos Testing README
+
+1. A Brief History of usr/src/test
+2. How to Run These Tests
+3. How to Develop New Tests
+4. Porting Tests from Other Frameworks
+
+--------------------------------------------------------------------------------
+
+1. A Brief History of usr/src/test
+
+The tests here come in two varieties - tests written from scratch, and tests
+that have been ported from the Solaris Test Collection. Not all of the STC
+tests have been ported, and a forked repository of those that have been made
+publicly available may currently be found here:
+
+ https://bitbucket.org/illumos/illumos-stc/
+
+Regardless of origin, all of these tests are executed using the run(1) script
+described in the next section.
+
+2. How to Run These Tests
+
+Currently, all the test suites under usr/src/test provide a wrapper script
+around run(1). These wrappers allow environment variables to be set up which
+may (for example) allow the script to specify which disks may be used by a test
+suite, and which must be preserved. Additionally, the wrappers allow options to
+run(1) to be passed through so that a user may specify a custom configuration
+file for a test suite. For specifics on the options available in the framework
+itself, please see the run(1) manpage.
+
+3. How to Develop New Tests
+
+New tests should mimic the directory layout of existing tests to the degree
+possible. This includes the following directories:
+
+cmd - Any support binaries or scripts used by the tests in this package.
+doc - READMEs or other support documentation to be delivered with the package.
+runfiles - Configuration files that dictate how the tests are run.
+tests - The tests themselves (see below).
+
+The tests you create will be run, and given a PASS or FAIL status in accordance
+with the exit value returned by the test. A test may also be marked SKIPPED in
+the event that a prerequisite test is marked FAIL, or marked KILLED in the
+event the test times out. Note that there is no way to force a test to be
+marked SKIPPED; this is intentional. If a test must be skipped due to
+insufficient resources for example, then a wrapper script should be provided
+that chooses or creates an appropriate configuration file. The goal of every
+run is that every test is marked PASS.
+
+4. Porting Tests from Other Frameworks
+
+STF (Solaris Test Framework)
+
+Porting tests from this framework is relatively straightforward. For the most
+part the tests can be arranged in the new directory structure and added to the
+configuration file. The template for a configuration file can easily be created
+using the -w option to run(1). There are a few other changes that may be
+required:
+
+Some STF tests consume the values of variables from the user's environment.
+These variables must be set before beginning the test run either manually, or
+via a wrapper script.
+
+Groups of tests in STF can automatically source .cfg files specified in the
+'stf_description' file that exists in an STF directory. Ported tests that
+require any of these variables must manually source the .cfg file instead.
+
+The configuration file of a newly ported test must specify the user the test
+should run as, along with the timeout value. In STF, these are also specified
+in the 'stf_description' file.
diff --git a/usr/src/test/zfs-tests/doc/README b/usr/src/test/zfs-tests/doc/README
index 45b3fc52bf..7fe70f4526 100644
--- a/usr/src/test/zfs-tests/doc/README
+++ b/usr/src/test/zfs-tests/doc/README
@@ -10,7 +10,7 @@
#
#
-# Copyright (c) 2012 by Delphix. All rights reserved.
+# Copyright (c) 2013 by Delphix. All rights reserved.
#
ZFS Test Suite README
@@ -60,7 +60,7 @@ Once the pre-requisites are satisfied, simply run the zfstest script:
When the '-q' option is specified, it is passed to run(1) which causes output
to be written to the console only for tests that do not pass and the results
-summary.
+summary.
The ZFS Test Suite allows the user to specify a subset of the tests via a
runfile. The format of the runfile is explained in run(1), and the files that
diff --git a/usr/src/test/zfs-tests/runfiles/delphix.run b/usr/src/test/zfs-tests/runfiles/delphix.run
index 90de7d28ed..abab40b68c 100644
--- a/usr/src/test/zfs-tests/runfiles/delphix.run
+++ b/usr/src/test/zfs-tests/runfiles/delphix.run
@@ -10,7 +10,7 @@
#
#
-# Copyright (c) 2012 by Delphix. All rights reserved.
+# Copyright (c) 2013 by Delphix. All rights reserved.
#
[DEFAULT]
@@ -38,7 +38,8 @@ tests = ['zfs_acl_chmod_001_neg', 'zfs_acl_chmod_002_pos',
'zfs_acl_chmod_xattr_001_pos', 'zfs_acl_chmod_xattr_002_pos',
'zfs_acl_cp_001_pos', 'zfs_acl_cp_002_pos', 'zfs_acl_cpio_001_pos',
'zfs_acl_cpio_002_pos', 'zfs_acl_find_001_pos', 'zfs_acl_ls_001_pos',
- 'zfs_acl_mv_001_pos', 'zfs_acl_tar_001_pos', 'zfs_acl_tar_002_pos']
+ 'zfs_acl_mv_001_pos', 'zfs_acl_tar_001_pos', 'zfs_acl_tar_002_pos',
+ 'zfs_acl_aclmode_restricted_001_neg']
[/opt/zfs-tests/tests/functional/acl/trivial]
tests = ['zfs_acl_chmod_001_pos', 'zfs_acl_compress_001_pos',
@@ -47,7 +48,8 @@ tests = ['zfs_acl_chmod_001_pos', 'zfs_acl_compress_001_pos',
'zfs_acl_ls_002_neg', 'zfs_acl_mv_001_pos', 'zfs_acl_pack_001_pos',
'zfs_acl_pax_001_pos', 'zfs_acl_pax_002_pos', 'zfs_acl_pax_003_pos',
'zfs_acl_pax_004_pos', 'zfs_acl_pax_005_pos', 'zfs_acl_pax_006_pos',
- 'zfs_acl_tar_001_pos', 'zfs_acl_tar_002_neg']
+ 'zfs_acl_tar_001_pos', 'zfs_acl_tar_002_neg',
+ 'zfs_acl_aclmode_restricted_001_pos']
[/opt/zfs-tests/tests/functional/atime]
tests = ['atime_001_pos', 'atime_002_neg']
diff --git a/usr/src/test/zfs-tests/runfiles/openindiana.run b/usr/src/test/zfs-tests/runfiles/openindiana.run
index 90de7d28ed..abab40b68c 100644
--- a/usr/src/test/zfs-tests/runfiles/openindiana.run
+++ b/usr/src/test/zfs-tests/runfiles/openindiana.run
@@ -10,7 +10,7 @@
#
#
-# Copyright (c) 2012 by Delphix. All rights reserved.
+# Copyright (c) 2013 by Delphix. All rights reserved.
#
[DEFAULT]
@@ -38,7 +38,8 @@ tests = ['zfs_acl_chmod_001_neg', 'zfs_acl_chmod_002_pos',
'zfs_acl_chmod_xattr_001_pos', 'zfs_acl_chmod_xattr_002_pos',
'zfs_acl_cp_001_pos', 'zfs_acl_cp_002_pos', 'zfs_acl_cpio_001_pos',
'zfs_acl_cpio_002_pos', 'zfs_acl_find_001_pos', 'zfs_acl_ls_001_pos',
- 'zfs_acl_mv_001_pos', 'zfs_acl_tar_001_pos', 'zfs_acl_tar_002_pos']
+ 'zfs_acl_mv_001_pos', 'zfs_acl_tar_001_pos', 'zfs_acl_tar_002_pos',
+ 'zfs_acl_aclmode_restricted_001_neg']
[/opt/zfs-tests/tests/functional/acl/trivial]
tests = ['zfs_acl_chmod_001_pos', 'zfs_acl_compress_001_pos',
@@ -47,7 +48,8 @@ tests = ['zfs_acl_chmod_001_pos', 'zfs_acl_compress_001_pos',
'zfs_acl_ls_002_neg', 'zfs_acl_mv_001_pos', 'zfs_acl_pack_001_pos',
'zfs_acl_pax_001_pos', 'zfs_acl_pax_002_pos', 'zfs_acl_pax_003_pos',
'zfs_acl_pax_004_pos', 'zfs_acl_pax_005_pos', 'zfs_acl_pax_006_pos',
- 'zfs_acl_tar_001_pos', 'zfs_acl_tar_002_neg']
+ 'zfs_acl_tar_001_pos', 'zfs_acl_tar_002_neg',
+ 'zfs_acl_aclmode_restricted_001_pos']
[/opt/zfs-tests/tests/functional/atime]
tests = ['atime_001_pos', 'atime_002_neg']
diff --git a/usr/src/test/zfs-tests/tests/functional/acl/nontrivial/Makefile b/usr/src/test/zfs-tests/tests/functional/acl/nontrivial/Makefile
index c1e14d5c83..047170a3c3 100644
--- a/usr/src/test/zfs-tests/tests/functional/acl/nontrivial/Makefile
+++ b/usr/src/test/zfs-tests/tests/functional/acl/nontrivial/Makefile
@@ -10,7 +10,7 @@
#
#
-# Copyright (c) 2012 by Delphix. All rights reserved.
+# Copyright (c) 2013 by Delphix. All rights reserved.
#
include $(SRC)/Makefile.master
@@ -20,6 +20,7 @@ TESTDIR = $(ROOTOPTPKG)/tests/functional/acl/nontrivial
PROGS = cleanup \
setup \
+ zfs_acl_aclmode_restricted_001_neg \
zfs_acl_chmod_001_neg \
zfs_acl_chmod_002_pos \
zfs_acl_chmod_aclmode_001_pos \
diff --git a/usr/src/test/zfs-tests/tests/functional/acl/nontrivial/zfs_acl_aclmode_restricted_001_neg.ksh b/usr/src/test/zfs-tests/tests/functional/acl/nontrivial/zfs_acl_aclmode_restricted_001_neg.ksh
new file mode 100644
index 0000000000..9080bec691
--- /dev/null
+++ b/usr/src/test/zfs-tests/tests/functional/acl/nontrivial/zfs_acl_aclmode_restricted_001_neg.ksh
@@ -0,0 +1,82 @@
+#!/usr/bin/ksh -p
+#
+# CDDL HEADER START
+#
+# The contents of this file are subject to the terms of the
+# Common Development and Distribution License (the "License").
+# You may not use this file except in compliance with the License.
+#
+# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+# or http://www.opensolaris.org/os/licensing.
+# See the License for the specific language governing permissions
+# and limitations under the License.
+#
+# When distributing Covered Code, include this CDDL HEADER in each
+# file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+# If applicable, add the following below this CDDL HEADER, with the
+# fields enclosed by brackets "[]" replaced with your own identifying
+# information: Portions Copyright [yyyy] [name of copyright owner]
+#
+# CDDL HEADER END
+#
+
+#
+# Copyright 2008 Sun Microsystems, Inc. All rights reserved.
+# Use is subject to license terms.
+#
+
+#
+# Copyright (c) 2013 by Delphix. All rights reserved.
+# Copyright (c) 2013 by Paul B. Henson <henson@acm.org>.
+# All rights reserved.
+#
+
+
+. $STF_SUITE/tests/functional/acl/acl.cfg
+. $STF_SUITE/tests/functional/acl/acl_common.kshlib
+
+#
+# DESCRIPTION:
+# Verify mode bits based chmod fails on files/directories with
+# non-trivial ACLs when aclmode=restricted
+#
+# STRATEGY:
+# 1. Loop super user and non-super user to run the test case
+# 2. Create test file and directory
+# 3. Set non-trivial ACL on test file and directory
+# 4. Verify mode bits based chmod fails
+#
+
+verify_runnable "both"
+
+function cleanup
+{
+ # reset aclmode=discard
+ log_must $ZFS set aclmode=discard $TESTPOOL/$TESTFS
+}
+
+log_assert "Verify mode bits based chmod fails on files/directories "\
+ "with non-trivial ACLs when aclmode=restricted"
+log_onexit cleanup
+
+log_must $ZFS set aclmode=restricted $TESTPOOL/$TESTFS
+
+for user in root $ZFS_ACL_STAFF1; do
+ log_must set_cur_usr $user
+
+ log_must usr_exec $MKDIR $TESTDIR/testdir
+ log_must usr_exec $TOUCH $TESTDIR/testfile
+
+ # Make sure ACL is non-trival
+ log_must usr_exec $CHMOD A+user:${ZFS_ACL_STAFF1}:r::allow \
+ $TESTDIR/testdir $TESTDIR/testfile
+
+ log_mustnot usr_exec $CHMOD u-w $TESTDIR/testdir
+ log_mustnot usr_exec $CHMOD u-w $TESTDIR/testfile
+
+ log_must usr_exec $RMDIR $TESTDIR/testdir
+ log_must usr_exec $RM $TESTDIR/testfile
+done
+
+log_pass "Verify mode bits based chmod fails on files/directories "\
+ "with non-trivial ACLs when aclmode=restricted passed."
diff --git a/usr/src/test/zfs-tests/tests/functional/acl/trivial/Makefile b/usr/src/test/zfs-tests/tests/functional/acl/trivial/Makefile
index 3555c31da3..07ee251710 100644
--- a/usr/src/test/zfs-tests/tests/functional/acl/trivial/Makefile
+++ b/usr/src/test/zfs-tests/tests/functional/acl/trivial/Makefile
@@ -10,7 +10,7 @@
#
#
-# Copyright (c) 2012 by Delphix. All rights reserved.
+# Copyright (c) 2013 by Delphix. All rights reserved.
#
include $(SRC)/Makefile.master
@@ -20,6 +20,7 @@ TESTDIR = $(ROOTOPTPKG)/tests/functional/acl/trivial
PROGS = cleanup \
setup \
+ zfs_acl_aclmode_restricted_001_pos \
zfs_acl_chmod_001_pos \
zfs_acl_compress_001_pos \
zfs_acl_cp_001_pos \
diff --git a/usr/src/test/zfs-tests/tests/functional/acl/trivial/zfs_acl_aclmode_restricted_001_pos.ksh b/usr/src/test/zfs-tests/tests/functional/acl/trivial/zfs_acl_aclmode_restricted_001_pos.ksh
new file mode 100644
index 0000000000..86b23980c9
--- /dev/null
+++ b/usr/src/test/zfs-tests/tests/functional/acl/trivial/zfs_acl_aclmode_restricted_001_pos.ksh
@@ -0,0 +1,130 @@
+#!/bin/ksh -p
+#
+# CDDL HEADER START
+#
+# The contents of this file are subject to the terms of the
+# Common Development and Distribution License (the "License").
+# You may not use this file except in compliance with the License.
+#
+# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+# or http://www.opensolaris.org/os/licensing.
+# See the License for the specific language governing permissions
+# and limitations under the License.
+#
+# When distributing Covered Code, include this CDDL HEADER in each
+# file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+# If applicable, add the following below this CDDL HEADER, with the
+# fields enclosed by brackets "[]" replaced with your own identifying
+# information: Portions Copyright [yyyy] [name of copyright owner]
+#
+# CDDL HEADER END
+#
+
+#
+# Copyright 2009 Sun Microsystems, Inc. All rights reserved.
+# Use is subject to license terms.
+#
+
+#
+# Copyright (c) 2013 by Delphix. All rights reserved.
+# Copyright (c) 2013 by Paul B. Henson <henson@acm.org>. All rights reserved.
+#
+
+. $STF_SUITE/tests/functional/acl/acl.cfg
+. $STF_SUITE/tests/functional/acl/acl_common.kshlib
+
+#
+# DESCRIPTION:
+# Verify chmod permission settings on files and directories, as both root
+# and non-root users, with aclmode set to restricted.
+#
+# STRATEGY:
+# 1. Loop root and $ZFS_ACL_STAFF1 as root and non-root users.
+# 2. Create test file and directory in zfs filesystem.
+# 3. Execute 'chmod' with specified options.
+# 4. Check 'ls -l' output and compare with expect results.
+
+verify_runnable "both"
+
+function cleanup
+{
+ # reset aclmode=discard
+ log_must $ZFS set aclmode=discard $TESTPOOL/$TESTFS
+}
+
+# "init_map" "options" "expect_map"
+set -A argv \
+ "000" "a+rw" "rw-rw-rw-" "000" "a+rwx" "rwxrwxrwx" \
+ "000" "u+xr" "r-x------" "000" "gu-xw" "---------" \
+ "644" "a-r" "-w-------" "644" "augo-x" "rw-r--r--" \
+ "644" "=x" "--x--x--x" "644" "u-rw" "---r--r--" \
+ "644" "uo+x" "rwxr--r-x" "644" "ga-wr" "---------" \
+ "777" "augo+x" "rwxrwxrwx" "777" "go-xr" "rwx-w--w-" \
+ "777" "o-wx" "rwxrwxr--" "777" "ou-rx" "-w-rwx-w-" \
+ "777" "a+rwx" "rwxrwxrwx" "777" "u=rw" "rw-rwxrwx" \
+ "000" "123" "--x-w--wx" "000" "412" "r----x-w-" \
+ "231" "562" "r-xrw--w-" "712" "000" "---------" \
+ "777" "121" "--x-w---x" "123" "775" "rwxrwxr-x"
+
+log_assert " Verify chmod permission settings on files and directories for " \
+ "aclmode=restricted"
+log_onexit cleanup
+
+#
+# Verify file or directory have correct map after chmod
+#
+# $1 file or directory
+#
+function test_chmod_mapping #<file-dir>
+{
+ typeset node=$1
+ typeset -i i=0
+
+ while ((i < ${#argv[@]})); do
+ usr_exec $CHMOD ${argv[i]} $node
+ if (($? != 0)); then
+ log_note "usr_exec $CHMOD ${argv[i]} $node"
+ return 1
+ fi
+ usr_exec $CHMOD ${argv[((i + 1))]} $node
+ if (($? != 0)); then
+ log_note "usr_exec $CHMOD ${argv[((i + 1))]} $node"
+ return 1
+ fi
+
+ typeset mode
+ mode=$(get_mode ${node})
+
+ if [[ $mode != "-${argv[((i + 2))]}"* && \
+ $mode != "d${argv[((i + 2))]}"* ]]
+ then
+ log_fail "FAIL: '${argv[i]}' '${argv[((i + 1))]}' \
+ '${argv[((i + 2))]}'"
+ fi
+
+ ((i += 3))
+ done
+
+ return 0
+}
+
+# set aclmode=restricted
+log_must $ZFS set aclmode=restricted $TESTPOOL/$TESTFS
+
+for user in root $ZFS_ACL_STAFF1; do
+ log_must set_cur_usr $user
+
+ # Test file
+ log_must usr_exec $TOUCH $testfile
+ log_must test_chmod_mapping $testfile
+
+ # Test directory
+ log_must usr_exec $MKDIR $testdir
+ log_must test_chmod_mapping $testdir
+
+ log_must usr_exec $RM $testfile
+ log_must usr_exec $RM -rf $testdir
+done
+
+log_pass "Setting permissions using 'chmod' for aclmode=restricted completed " \
+ "successfully."
diff --git a/usr/src/uts/common/dtrace/dtrace.c b/usr/src/uts/common/dtrace/dtrace.c
index 5909a860f7..6f6c64e86b 100644
--- a/usr/src/uts/common/dtrace/dtrace.c
+++ b/usr/src/uts/common/dtrace/dtrace.c
@@ -362,7 +362,7 @@ static kmutex_t dtrace_errlock;
#define DTRACE_STORE(type, tomax, offset, what) \
*((type *)((uintptr_t)(tomax) + (uintptr_t)offset)) = (type)(what);
-#ifndef __i386
+#ifndef __x86
#define DTRACE_ALIGNCHECK(addr, size, flags) \
if (addr & (size - 1)) { \
*flags |= CPU_DTRACE_BADALIGN; \
@@ -6589,7 +6589,7 @@ dtrace_probe(dtrace_id_t id, uintptr_t arg0, uintptr_t arg1,
size_t size;
int vtime, onintr;
volatile uint16_t *flags;
- hrtime_t now;
+ hrtime_t now, end;
/*
* Kick out immediately if this CPU is still being born (in which case
@@ -6604,6 +6604,8 @@ dtrace_probe(dtrace_id_t id, uintptr_t arg0, uintptr_t arg1,
cpuid = CPU->cpu_id;
onintr = CPU_ON_INTR(CPU);
+ CPU->cpu_dtrace_probes++;
+
if (!onintr && probe->dtpr_predcache != DTRACE_CACHEIDNONE &&
probe->dtpr_predcache == curthread->t_predcache) {
/*
@@ -7185,8 +7187,11 @@ dtrace_probe(dtrace_id_t id, uintptr_t arg0, uintptr_t arg1,
buf->dtb_offset = offs + ecb->dte_size;
}
+ end = dtrace_gethrtime();
if (vtime)
- curthread->t_dtrace_start = dtrace_gethrtime();
+ curthread->t_dtrace_start = end;
+
+ CPU->cpu_dtrace_nsec += end - now;
dtrace_interrupt_enable(cookie);
}
diff --git a/usr/src/uts/common/fs/nfs/nfs4_client.c b/usr/src/uts/common/fs/nfs/nfs4_client.c
index d85c9d7e31..6c1006fbdc 100644
--- a/usr/src/uts/common/fs/nfs/nfs4_client.c
+++ b/usr/src/uts/common/fs/nfs/nfs4_client.c
@@ -1783,8 +1783,7 @@ nfs4_async_putapage(vnode_t *vp, page_t *pp, u_offset_t off, size_t len,
noasync:
- if (curproc == proc_pageout || curproc == proc_fsflush ||
- nfs_zone() == mi->mi_zone) {
+ if (curproc == proc_pageout || curproc == proc_fsflush) {
/*
* If we get here in the context of the pageout/fsflush,
* or we have run out of memory or we're attempting to
@@ -1804,18 +1803,20 @@ noasync:
return (0);
}
- /*
- * We'll get here only if (nfs_zone() != mi->mi_zone)
- * which means that this was a cross-zone sync putpage.
- *
- * We pass in B_ERROR to pvn_write_done() to re-mark the pages
- * as dirty and unlock them.
- *
- * We don't want to clear B_FORCE here as the caller presumably
- * knows what they're doing if they set it.
- */
- pvn_write_done(pp, flags | B_ERROR);
- return (EPERM);
+ if (nfs_zone() != mi->mi_zone) {
+ /*
+ * So this was a cross-zone sync putpage.
+ *
+ * We pass in B_ERROR to pvn_write_done() to re-mark the pages
+ * as dirty and unlock them.
+ *
+ * We don't want to clear B_FORCE here as the caller presumably
+ * knows what they're doing if they set it.
+ */
+ pvn_write_done(pp, flags | B_ERROR);
+ return (EPERM);
+ }
+ return ((*putapage)(vp, pp, off, len, flags, cr));
}
int
diff --git a/usr/src/uts/common/fs/nfs/nfs4_srv.c b/usr/src/uts/common/fs/nfs/nfs4_srv.c
index f2a9734541..079b84bcef 100644
--- a/usr/src/uts/common/fs/nfs/nfs4_srv.c
+++ b/usr/src/uts/common/fs/nfs/nfs4_srv.c
@@ -22,7 +22,7 @@
* Copyright (c) 2003, 2010, Oracle and/or its affiliates. All rights reserved.
*/
/*
- * Copyright 2012 Nexenta Systems, Inc. All rights reserved.
+ * Copyright 2013 Nexenta Systems, Inc. All rights reserved.
*/
/*
@@ -7341,7 +7341,7 @@ retry:
create = TRUE;
oo = rfs4_findopenowner(owner, &create, args->seqid);
if (oo == NULL) {
- *cs->statusp = resp->status = NFS4ERR_STALE_CLIENTID;
+ *cs->statusp = resp->status = NFS4ERR_RESOURCE;
rfs4_client_rele(cp);
goto end;
}
diff --git a/usr/src/uts/common/fs/smbclnt/netsmb/smb_dev.c b/usr/src/uts/common/fs/smbclnt/netsmb/smb_dev.c
index c553359ed6..02c6c9a946 100644
--- a/usr/src/uts/common/fs/smbclnt/netsmb/smb_dev.c
+++ b/usr/src/uts/common/fs/smbclnt/netsmb/smb_dev.c
@@ -31,7 +31,7 @@
*/
/*
- * Copyright 2011 Nexenta Systems, Inc. All rights reserved.
+ * Copyright 2012 Nexenta Systems, Inc. All rights reserved.
* Copyright 2009 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
@@ -491,7 +491,6 @@ nsmb_close(dev_t dev, int flags, int otyp, cred_t *cr)
smb_dev_t *sdp;
int err;
- mutex_enter(&dev_lck);
/*
* 1. Check the validity of the minor number.
* 2. Release any shares/vc associated with the connection.
@@ -508,6 +507,7 @@ nsmb_close(dev_t dev, int flags, int otyp, cred_t *cr)
/*
* Free the instance
*/
+ mutex_enter(&dev_lck);
ddi_soft_state_free(statep, inst);
mutex_exit(&dev_lck);
return (err);
diff --git a/usr/src/uts/common/fs/smbclnt/netsmb/smb_smb.c b/usr/src/uts/common/fs/smbclnt/netsmb/smb_smb.c
index f27bea0e87..6016f5061a 100644
--- a/usr/src/uts/common/fs/smbclnt/netsmb/smb_smb.c
+++ b/usr/src/uts/common/fs/smbclnt/netsmb/smb_smb.c
@@ -33,7 +33,7 @@
*/
/*
- * Copyright 2011 Nexenta Systems, Inc. All rights reserved.
+ * Copyright 2012 Nexenta Systems, Inc. All rights reserved.
* Copyright (c) 2008, 2010, Oracle and/or its affiliates. All rights reserved.
*/
@@ -500,8 +500,8 @@ smb_smb_close(struct smb_share *ssp, uint16_t fid, struct timespec *mtime,
smb_rq_bstart(rqp);
smb_rq_bend(rqp);
- /* Make sure we send it... */
- rqp->sr_flags |= SMBR_NOINTR_SEND;
+ /* Make sure we send, but only if already connected */
+ rqp->sr_flags |= (SMBR_NOINTR_SEND | SMBR_NORECONNECT);
error = smb_rq_simple(rqp);
smb_rq_done(rqp);
return (error);
@@ -593,8 +593,8 @@ smb_smb_close_prjob(struct smb_share *ssp, uint16_t fid,
smb_rq_bstart(rqp);
smb_rq_bend(rqp);
- /* Make sure we send it... */
- rqp->sr_flags |= SMBR_NOINTR_SEND;
+ /* Make sure we send but only if already connected */
+ rqp->sr_flags |= (SMBR_NOINTR_SEND | SMBR_NORECONNECT);
error = smb_rq_simple(rqp);
smb_rq_done(rqp);
return (error);
diff --git a/usr/src/uts/common/fs/smbsrv/smb_common_transact.c b/usr/src/uts/common/fs/smbsrv/smb_common_transact.c
index 21dff73b3c..7d534665fd 100644
--- a/usr/src/uts/common/fs/smbsrv/smb_common_transact.c
+++ b/usr/src/uts/common/fs/smbsrv/smb_common_transact.c
@@ -21,6 +21,7 @@
/*
* Copyright (c) 2007, 2010, Oracle and/or its affiliates. All rights reserved.
+ * Copyright 2012 Nexenta Systems, Inc. All rights reserved.
*/
#include <smbsrv/smb_kproto.h>
@@ -127,7 +128,7 @@ smb_com_transaction(smb_request_t *sr)
if (smb_xa_open(xa)) {
smb_xa_rele(sr->session, xa);
- smbsr_error(sr, 0, ERRDOS, ERRsrverror);
+ smbsr_error(sr, 0, ERRSRV, ERRsrverror);
return (SDRC_ERROR);
}
sr->r_xa = xa;
@@ -314,7 +315,7 @@ smb_com_transaction2(struct smb_request *sr)
if (smb_xa_open(xa)) {
smb_xa_rele(sr->session, xa);
- smbsr_error(sr, 0, ERRDOS, ERRsrverror);
+ smbsr_error(sr, 0, ERRSRV, ERRsrverror);
return (SDRC_ERROR);
}
sr->r_xa = xa;
@@ -586,7 +587,7 @@ smb_com_nt_transact(struct smb_request *sr)
if (smb_xa_open(xa)) {
smb_xa_rele(sr->session, xa);
- smbsr_error(sr, 0, ERRDOS, ERRsrverror);
+ smbsr_error(sr, 0, ERRSRV, ERRsrverror);
return (SDRC_ERROR);
}
sr->r_xa = xa;
diff --git a/usr/src/uts/common/fs/smbsrv/smb_fem.c b/usr/src/uts/common/fs/smbsrv/smb_fem.c
index e32b5fc925..38cfab1f5c 100644
--- a/usr/src/uts/common/fs/smbsrv/smb_fem.c
+++ b/usr/src/uts/common/fs/smbsrv/smb_fem.c
@@ -20,6 +20,7 @@
*/
/*
* Copyright (c) 2007, 2010, Oracle and/or its affiliates. All rights reserved.
+ * Copyright 2012 Nexenta Systems, Inc. All rights reserved.
*/
#include <smbsrv/smb_kproto.h>
@@ -223,7 +224,7 @@ smb_fem_fcn_create(
ct, vsecp);
if (error == 0)
- smb_node_notify_change(dnode);
+ smb_node_notify_change(dnode, FILE_ACTION_ADDED, name);
return (error);
}
@@ -257,7 +258,7 @@ smb_fem_fcn_remove(
error = vnext_remove(arg, name, cr, ct, flags);
if (error == 0)
- smb_node_notify_change(dnode);
+ smb_node_notify_change(dnode, FILE_ACTION_REMOVED, name);
return (error);
}
@@ -281,10 +282,18 @@ smb_fem_fcn_rename(
error = vnext_rename(arg, snm, tdvp, tnm, cr, ct, flags);
- if (error == 0)
- smb_node_notify_change(dnode);
+ if (error != 0)
+ return (error);
- return (error);
+ /*
+ * Note that renames in the same directory are normally
+ * delivered in {old,new} pairs, and clients expect them
+ * in that order, if both events are delivered.
+ */
+ smb_node_notify_change(dnode, FILE_ACTION_RENAMED_OLD_NAME, snm);
+ smb_node_notify_change(dnode, FILE_ACTION_RENAMED_NEW_NAME, tnm);
+
+ return (0);
}
static int
@@ -308,7 +317,7 @@ smb_fem_fcn_mkdir(
error = vnext_mkdir(arg, name, vap, vpp, cr, ct, flags, vsecp);
if (error == 0)
- smb_node_notify_change(dnode);
+ smb_node_notify_change(dnode, FILE_ACTION_ADDED, name);
return (error);
}
@@ -332,7 +341,7 @@ smb_fem_fcn_rmdir(
error = vnext_rmdir(arg, name, cdir, cr, ct, flags);
if (error == 0)
- smb_node_notify_change(dnode);
+ smb_node_notify_change(dnode, FILE_ACTION_REMOVED, name);
return (error);
}
@@ -356,7 +365,7 @@ smb_fem_fcn_link(
error = vnext_link(arg, svp, tnm, cr, ct, flags);
if (error == 0)
- smb_node_notify_change(dnode);
+ smb_node_notify_change(dnode, FILE_ACTION_ADDED, tnm);
return (error);
}
@@ -381,7 +390,7 @@ smb_fem_fcn_symlink(
error = vnext_symlink(arg, linkname, vap, target, cr, ct, flags);
if (error == 0)
- smb_node_notify_change(dnode);
+ smb_node_notify_change(dnode, FILE_ACTION_ADDED, linkname);
return (error);
}
diff --git a/usr/src/uts/common/fs/smbsrv/smb_find.c b/usr/src/uts/common/fs/smbsrv/smb_find.c
index 52250f68db..1dae4e8cb5 100644
--- a/usr/src/uts/common/fs/smbsrv/smb_find.c
+++ b/usr/src/uts/common/fs/smbsrv/smb_find.c
@@ -20,6 +20,7 @@
*/
/*
* Copyright (c) 2007, 2010, Oracle and/or its affiliates. All rights reserved.
+ * Copyright 2012 Nexenta Systems, Inc. All rights reserved.
*/
#include <smbsrv/smb_kproto.h>
@@ -230,7 +231,7 @@ smb_com_search(smb_request_t *sr)
smb_odir_t *od;
smb_fileinfo_t fileinfo;
smb_odir_resume_t odir_resume;
- boolean_t eos;
+ uint16_t eos;
to_upper = B_FALSE;
if ((sr->session->dialect <= LANMAN1_0) ||
@@ -328,7 +329,7 @@ smb_com_search(smb_request_t *sr)
while (count < maxcount) {
rc = smb_odir_read_fileinfo(sr, od, &fileinfo, &eos);
- if ((rc != 0 || (eos == B_TRUE)))
+ if (rc != 0 || eos != 0)
break;
if (*fileinfo.fi_shortname == '\0') {
@@ -407,7 +408,7 @@ smb_com_find(smb_request_t *sr)
char name83[SMB_SHORTNAMELEN];
smb_odir_t *od;
smb_fileinfo_t fileinfo;
- boolean_t eos;
+ uint16_t eos;
smb_pathname_t *pn;
unsigned char resume_char;
@@ -474,7 +475,7 @@ smb_com_find(smb_request_t *sr)
while (count < maxcount) {
rc = smb_odir_read_fileinfo(sr, od, &fileinfo, &eos);
- if ((rc != 0 || (eos == B_TRUE)))
+ if (rc != 0 || eos != 0)
break;
if (*fileinfo.fi_shortname == '\0') {
@@ -618,7 +619,7 @@ smb_com_find_unique(struct smb_request *sr)
char name83[SMB_SHORTNAMELEN];
smb_odir_t *od;
smb_fileinfo_t fileinfo;
- boolean_t eos;
+ uint16_t eos;
smb_vdb_t *vdb;
if (smbsr_decode_vwv(sr, "ww", &maxcount, &sattr) != 0)
@@ -660,7 +661,7 @@ smb_com_find_unique(struct smb_request *sr)
while (count < maxcount) {
rc = smb_odir_read_fileinfo(sr, od, &fileinfo, &eos);
- if ((rc != 0 || (eos == B_TRUE)))
+ if (rc != 0 || eos != 0)
break;
if (*fileinfo.fi_shortname == '\0') {
diff --git a/usr/src/uts/common/fs/smbsrv/smb_fsops.c b/usr/src/uts/common/fs/smbsrv/smb_fsops.c
index 68e32246cd..f9ec3fa674 100644
--- a/usr/src/uts/common/fs/smbsrv/smb_fsops.c
+++ b/usr/src/uts/common/fs/smbsrv/smb_fsops.c
@@ -20,6 +20,7 @@
*/
/*
* Copyright (c) 2007, 2010, Oracle and/or its affiliates. All rights reserved.
+ * Copyright 2012 Nexenta Systems, Inc. All rights reserved.
*/
#include <sys/sid.h>
@@ -423,7 +424,8 @@ smb_fsop_create_stream(smb_request_t *sr, cred_t *cr,
/* notify change to the unnamed stream */
if (rc == 0)
- smb_node_notify_change(dnode);
+ smb_node_notify_change(dnode,
+ FILE_ACTION_ADDED_STREAM, fname);
return (rc);
}
@@ -679,9 +681,10 @@ smb_fsop_remove(
rc = smb_vop_stream_remove(fnode->vp, name, flags, cr);
/* notify change to the unnamed stream */
- if ((rc == 0) && fnode->n_dnode)
- smb_node_notify_change(fnode->n_dnode);
-
+ if ((rc == 0) && fnode->n_dnode) {
+ smb_node_notify_change(fnode->n_dnode,
+ FILE_ACTION_REMOVED_STREAM, fnode->od_name);
+ }
} else if (smb_is_stream_name(name)) {
smb_stream_parse_name(name, fname, sname);
@@ -710,8 +713,10 @@ smb_fsop_remove(
smb_node_release(fnode);
/* notify change to the unnamed stream */
- if (rc == 0)
- smb_node_notify_change(dnode);
+ if (rc == 0) {
+ smb_node_notify_change(dnode,
+ FILE_ACTION_REMOVED_STREAM, fname);
+ }
} else {
rc = smb_vop_remove(dnode->vp, name, flags, cr);
diff --git a/usr/src/uts/common/fs/smbsrv/smb_kshare.c b/usr/src/uts/common/fs/smbsrv/smb_kshare.c
index 94a4dae9fe..9cf83a0297 100644
--- a/usr/src/uts/common/fs/smbsrv/smb_kshare.c
+++ b/usr/src/uts/common/fs/smbsrv/smb_kshare.c
@@ -21,6 +21,7 @@
/*
* Copyright (c) 2007, 2010, Oracle and/or its affiliates. All rights reserved.
+ * Copyright 2012 Nexenta Systems, Inc. All rights reserved.
*/
#include <smbsrv/smb_door.h>
@@ -60,6 +61,9 @@ static smb_avl_nops_t smb_kshare_avlops = {
smb_kshare_destroy
};
+extern int smb_server_lookup(smb_server_t **);
+extern void smb_server_release(smb_server_t *);
+
/*
* This function is not MultiThread safe. The caller has to make sure only one
* thread calls this function.
@@ -347,22 +351,35 @@ smb_kshare_fini(void)
int
smb_kshare_export_list(smb_ioc_share_t *ioc)
{
- nvlist_t *shrlist;
+ nvlist_t *shrlist = NULL;
nvlist_t *share;
nvpair_t *nvp;
smb_kshare_t *shr;
char *shrname;
- int rc;
+ int rc = 0;
+ smb_server_t *sv = NULL;
if (!smb_export_isready())
return (ENOTACTIVE);
+ if ((rc = smb_server_lookup(&sv)) != 0)
+ return (rc);
+
if ((rc = nvlist_unpack(ioc->shr, ioc->shrlen, &shrlist, KM_SLEEP))
!= 0)
- return (rc);
+ goto out;
for (nvp = nvlist_next_nvpair(shrlist, NULL); nvp != NULL;
nvp = nvlist_next_nvpair(shrlist, nvp)) {
+
+ /*
+ * Since this loop can run for a while we want to exit
+ * as soon as the server state is anything but RUNNING
+ * to allow shutdown to proceed.
+ */
+ if (sv->sv_state != SMB_SERVER_STATE_RUNNING)
+ goto out;
+
if (nvpair_type(nvp) != DATA_TYPE_NVLIST)
continue;
@@ -381,14 +398,19 @@ smb_kshare_export_list(smb_ioc_share_t *ioc)
continue;
}
+ /* smb_kshare_export consumes shr so it's not leaked */
if ((rc = smb_kshare_export(shr)) != 0) {
smb_kshare_destroy(shr);
continue;
}
}
+ rc = 0;
- nvlist_free(shrlist);
- return (0);
+out:
+ if (shrlist != NULL)
+ nvlist_free(shrlist);
+ smb_server_release(sv);
+ return (rc);
}
/*
diff --git a/usr/src/uts/common/fs/smbsrv/smb_node.c b/usr/src/uts/common/fs/smbsrv/smb_node.c
index bd69147095..bfb08c2d15 100644
--- a/usr/src/uts/common/fs/smbsrv/smb_node.c
+++ b/usr/src/uts/common/fs/smbsrv/smb_node.c
@@ -20,6 +20,7 @@
*/
/*
* Copyright (c) 2007, 2010, Oracle and/or its affiliates. All rights reserved.
+ * Copyright 2012 Nexenta Systems, Inc. All rights reserved.
*/
/*
* SMB Node State Machine
@@ -784,15 +785,51 @@ smb_node_share_check(smb_node_t *node)
return (status);
}
+/*
+ * SMB Change Notification
+ */
+
+void
+smb_node_fcn_subscribe(smb_node_t *node, smb_request_t *sr)
+{
+ smb_node_fcn_t *fcn = &node->n_fcn;
+
+ mutex_enter(&fcn->fcn_mutex);
+ if (fcn->fcn_count == 0)
+ smb_fem_fcn_install(node);
+ fcn->fcn_count++;
+ list_insert_tail(&fcn->fcn_watchers, sr);
+ mutex_exit(&fcn->fcn_mutex);
+}
+
+void
+smb_node_fcn_unsubscribe(smb_node_t *node, smb_request_t *sr)
+{
+ smb_node_fcn_t *fcn = &node->n_fcn;
+
+ mutex_enter(&fcn->fcn_mutex);
+ list_remove(&fcn->fcn_watchers, sr);
+ fcn->fcn_count--;
+ if (fcn->fcn_count == 0)
+ smb_fem_fcn_uninstall(node);
+ mutex_exit(&fcn->fcn_mutex);
+}
+
void
-smb_node_notify_change(smb_node_t *node)
+smb_node_notify_change(smb_node_t *node, uint_t action, const char *name)
{
SMB_NODE_VALID(node);
- if (node->flags & NODE_FLAGS_NOTIFY_CHANGE) {
- node->flags |= NODE_FLAGS_CHANGED;
- smb_process_node_notify_change_queue(node);
- }
+ smb_notify_event(node, action, name);
+
+ /*
+ * These two events come as a pair:
+ * FILE_ACTION_RENAMED_OLD_NAME
+ * FILE_ACTION_RENAMED_NEW_NAME
+ * Only do the parent notify for "new".
+ */
+ if (action == FILE_ACTION_RENAMED_OLD_NAME)
+ return;
smb_node_notify_parents(node);
}
@@ -808,17 +845,17 @@ smb_node_notify_change(smb_node_t *node)
void
smb_node_notify_parents(smb_node_t *dnode)
{
- smb_node_t *pnode = dnode;
+ smb_node_t *pnode; /* parent */
SMB_NODE_VALID(dnode);
+ pnode = dnode->n_dnode;
- while ((pnode = pnode->n_dnode) != NULL) {
+ while (pnode != NULL) {
SMB_NODE_VALID(pnode);
- if ((pnode->flags & NODE_FLAGS_NOTIFY_CHANGE) &&
- (pnode->flags & NODE_FLAGS_WATCH_TREE)) {
- pnode->flags |= NODE_FLAGS_CHANGED;
- smb_process_node_notify_change_queue(pnode);
- }
+ smb_notify_event(pnode, 0, dnode->od_name);
+ /* cd .. */
+ dnode = pnode;
+ pnode = dnode->n_dnode;
}
}
@@ -1140,6 +1177,9 @@ smb_node_constructor(void *buf, void *un, int kmflags)
offsetof(smb_ofile_t, f_nnd));
smb_llist_constructor(&node->n_lock_list, sizeof (smb_lock_t),
offsetof(smb_lock_t, l_lnd));
+ mutex_init(&node->n_fcn.fcn_mutex, NULL, MUTEX_DEFAULT, NULL);
+ list_create(&node->n_fcn.fcn_watchers, sizeof (smb_request_t),
+ offsetof(smb_request_t, sr_ncr.nc_lnd));
cv_init(&node->n_oplock.ol_cv, NULL, CV_DEFAULT, NULL);
mutex_init(&node->n_oplock.ol_mutex, NULL, MUTEX_DEFAULT, NULL);
list_create(&node->n_oplock.ol_grants, sizeof (smb_oplock_grant_t),
@@ -1165,6 +1205,8 @@ smb_node_destructor(void *buf, void *un)
rw_destroy(&node->n_lock);
cv_destroy(&node->n_oplock.ol_cv);
mutex_destroy(&node->n_oplock.ol_mutex);
+ list_destroy(&node->n_fcn.fcn_watchers);
+ mutex_destroy(&node->n_fcn.fcn_mutex);
smb_llist_destructor(&node->n_lock_list);
smb_llist_destructor(&node->n_ofile_list);
list_destroy(&node->n_oplock.ol_grants);
@@ -1416,9 +1458,12 @@ smb_node_setattr(smb_request_t *sr, smb_node_t *node,
if (tmp_attr.sa_mask)
smb_node_set_cached_timestamps(node, &tmp_attr);
- if (tmp_attr.sa_mask & SMB_AT_MTIME || explicit_times & SMB_AT_MTIME) {
- if (node->n_dnode != NULL)
- smb_node_notify_change(node->n_dnode);
+ if ((tmp_attr.sa_mask & SMB_AT_MTIME) ||
+ (explicit_times & SMB_AT_MTIME)) {
+ if (node->n_dnode != NULL) {
+ smb_node_notify_change(node->n_dnode,
+ FILE_ACTION_MODIFIED, node->od_name);
+ }
}
return (0);
diff --git a/usr/src/uts/common/fs/smbsrv/smb_nt_cancel.c b/usr/src/uts/common/fs/smbsrv/smb_nt_cancel.c
index 1e4d9df892..35bdf74b0d 100644
--- a/usr/src/uts/common/fs/smbsrv/smb_nt_cancel.c
+++ b/usr/src/uts/common/fs/smbsrv/smb_nt_cancel.c
@@ -21,6 +21,7 @@
/*
* Copyright 2009 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
+ * Copyright 2012 Nexenta Systems, Inc. All rights reserved.
*/
/*
@@ -79,9 +80,5 @@ smb_com_nt_cancel(smb_request_t *sr)
}
smb_slist_exit(&session->s_req_list);
- /* Now, search the notify change queue to find the request */
-
- smb_reply_specific_cancel_request(sr);
-
return (SDRC_NO_REPLY);
}
diff --git a/usr/src/uts/common/fs/smbsrv/smb_nt_transact_notify_change.c b/usr/src/uts/common/fs/smbsrv/smb_nt_transact_notify_change.c
index 2efd4cba5a..4b6befa344 100644
--- a/usr/src/uts/common/fs/smbsrv/smb_nt_transact_notify_change.c
+++ b/usr/src/uts/common/fs/smbsrv/smb_nt_transact_notify_change.c
@@ -20,8 +20,8 @@
*/
/*
- * Copyright 2011 Nexenta Systems, Inc. All rights reserved.
* Copyright (c) 2007, 2010, Oracle and/or its affiliates. All rights reserved.
+ * Copyright 2012 Nexenta Systems, Inc. All rights reserved.
*/
/*
@@ -113,86 +113,50 @@
#include <smbsrv/smb_kproto.h>
#include <sys/sdt.h>
-static void smb_notify_change_daemon(smb_thread_t *, void *);
-
-static boolean_t smb_notify_initialized = B_FALSE;
-static smb_slist_t smb_ncr_list;
-static smb_slist_t smb_nce_list;
-static smb_thread_t smb_thread_notify_daemon;
-
/*
- * smb_notify_init
- *
- * This function is not multi-thread safe. The caller must make sure only one
- * thread makes the call.
+ * We add this flag to the CompletionFilter (see above) when the
+ * client sets WatchTree. Must not overlap FILE_NOTIFY_VALID_MASK.
*/
-int
-smb_notify_init(void)
-{
- int rc;
-
- if (smb_notify_initialized)
- return (0);
-
- smb_slist_constructor(&smb_ncr_list, sizeof (smb_request_t),
- offsetof(smb_request_t, sr_ncr.nc_lnd));
-
- smb_slist_constructor(&smb_nce_list, sizeof (smb_request_t),
- offsetof(smb_request_t, sr_ncr.nc_lnd));
+#define NODE_FLAGS_WATCH_TREE 0x10000000
+#if (NODE_FLAGS_WATCH_TREE & FILE_NOTIFY_VALID_MASK)
+#error "NODE_FLAGS_WATCH_TREE"
+#endif
- smb_thread_init(&smb_thread_notify_daemon,
- "smb_notify_change_daemon", smb_notify_change_daemon, NULL);
-
- rc = smb_thread_start(&smb_thread_notify_daemon);
- if (rc) {
- smb_thread_destroy(&smb_thread_notify_daemon);
- smb_slist_destructor(&smb_ncr_list);
- smb_slist_destructor(&smb_nce_list);
- return (rc);
- }
-
- smb_notify_initialized = B_TRUE;
-
- return (0);
-}
-
-/*
- * smb_notify_fini
- *
- * This function is not multi-thread safe. The caller must make sure only one
- * thread makes the call.
- */
-void
-smb_notify_fini(void)
-{
- if (!smb_notify_initialized)
- return;
+static void smb_notify_sr(smb_request_t *, uint_t, const char *);
- smb_thread_stop(&smb_thread_notify_daemon);
- smb_thread_destroy(&smb_thread_notify_daemon);
- smb_slist_destructor(&smb_ncr_list);
- smb_slist_destructor(&smb_nce_list);
- smb_notify_initialized = B_FALSE;
-}
+static int smb_notify_encode_action(struct smb_request *, struct smb_xa *,
+ uint32_t, char *);
/*
* smb_nt_transact_notify_change
*
- * This function is responsible for processing NOTIFY CHANGE requests.
- * Requests are stored in a global queue. This queue is processed when
- * a monitored directory is changed or client cancels one of its already
- * sent requests.
+ * Handle and SMB NT transact NOTIFY CHANGE request.
+ * Basically, wait until "something has changed", and either
+ * return information about what changed, or return a special
+ * error telling the client "many things changed".
+ *
+ * The implementation uses a per-node list of waiting notify
+ * requests like this one, each with a blocked worker thead.
+ * Later, FEM and/or smbsrv events wake these threads, which
+ * then send the reply to the client.
*/
smb_sdrc_t
-smb_nt_transact_notify_change(struct smb_request *sr, struct smb_xa *xa)
+smb_nt_transact_notify_change(smb_request_t *sr, struct smb_xa *xa)
{
uint32_t CompletionFilter;
unsigned char WatchTree;
+ smb_error_t err;
+ int rc;
smb_node_t *node;
if (smb_mbc_decodef(&xa->req_setup_mb, "lwb",
- &CompletionFilter, &sr->smb_fid, &WatchTree) != 0)
- return (SDRC_NOT_IMPLEMENTED);
+ &CompletionFilter, &sr->smb_fid, &WatchTree) != 0) {
+ smbsr_error(sr, NT_STATUS_INVALID_PARAMETER, 0, 0);
+ return (SDRC_ERROR);
+ }
+ CompletionFilter &= FILE_NOTIFY_VALID_MASK;
+ if (WatchTree)
+ CompletionFilter |= NODE_FLAGS_WATCH_TREE;
smbsr_lookup_file(sr);
if (sr->fid_ofile == NULL) {
@@ -201,7 +165,6 @@ smb_nt_transact_notify_change(struct smb_request *sr, struct smb_xa *xa)
}
node = sr->fid_ofile->f_node;
-
if (node == NULL || !smb_node_is_dir(node)) {
/*
* Notify change requests are only valid on directories.
@@ -210,133 +173,70 @@ smb_nt_transact_notify_change(struct smb_request *sr, struct smb_xa *xa)
return (SDRC_ERROR);
}
+ /*
+ * Prepare to receive event data.
+ */
+ sr->sr_ncr.nc_flags = CompletionFilter;
+ ASSERT(sr->sr_ncr.nc_action == 0);
+ ASSERT(sr->sr_ncr.nc_fname == NULL);
+ sr->sr_ncr.nc_fname = kmem_zalloc(MAXNAMELEN, KM_SLEEP);
+
+ /*
+ * Subscribe to events on this node.
+ */
+ smb_node_fcn_subscribe(node, sr);
+
+ /*
+ * Wait for subscribed events to arrive.
+ * Expect SMB_REQ_STATE_EVENT_OCCURRED
+ * or SMB_REQ_STATE_CANCELED when signaled.
+ * Note it's possible (though rare) to already
+ * have SMB_REQ_STATE_CANCELED here.
+ */
mutex_enter(&sr->sr_mutex);
- switch (sr->sr_state) {
- case SMB_REQ_STATE_ACTIVE:
- node->waiting_event++;
- node->flags |= NODE_FLAGS_NOTIFY_CHANGE;
- if ((node->flags & NODE_FLAGS_CHANGED) == 0) {
- sr->sr_ncr.nc_node = node;
- sr->sr_ncr.nc_flags = CompletionFilter;
- if (WatchTree)
- sr->sr_ncr.nc_flags |= NODE_FLAGS_WATCH_TREE;
-
- sr->sr_keep = B_TRUE;
- sr->sr_state = SMB_REQ_STATE_WAITING_EVENT;
-
- smb_slist_insert_tail(&smb_ncr_list, sr);
-
- /*
- * Monitor events system-wide.
- *
- * XXX: smb_node_ref() and smb_node_release()
- * take &node->n_lock. May need alternate forms
- * of these routines if node->n_lock is taken
- * around calls to smb_fem_fcn_install() and
- * smb_fem_fcn_uninstall().
- */
-
- smb_fem_fcn_install(node);
-
- mutex_exit(&sr->sr_mutex);
- return (SDRC_SR_KEPT);
- } else {
- /* node already changed, reply immediately */
- if (--node->waiting_event == 0)
- node->flags &=
- ~(NODE_FLAGS_NOTIFY_CHANGE |
- NODE_FLAGS_CHANGED);
- mutex_exit(&sr->sr_mutex);
- return (SDRC_SUCCESS);
- }
-
- case SMB_REQ_STATE_CANCELED:
- mutex_exit(&sr->sr_mutex);
- smbsr_error(sr, NT_STATUS_CANCELLED, 0, 0);
- return (SDRC_ERROR);
-
- default:
- ASSERT(0);
- mutex_exit(&sr->sr_mutex);
- return (SDRC_SUCCESS);
+ if (sr->sr_state == SMB_REQ_STATE_ACTIVE)
+ sr->sr_state = SMB_REQ_STATE_WAITING_EVENT;
+ while (sr->sr_state == SMB_REQ_STATE_WAITING_EVENT) {
+ cv_wait(&sr->sr_ncr.nc_cv, &sr->sr_mutex);
}
-}
-
-/*
- * smb_reply_notify_change_request
- *
- * This function sends appropriate response to an already queued NOTIFY CHANGE
- * request. If node is changed (reply == NODE_FLAGS_CHANGED), a normal reply is
- * sent.
- * If client cancels the request or session dropped, an NT_STATUS_CANCELED
- * is sent in reply.
- */
-
-void
-smb_reply_notify_change_request(smb_request_t *sr)
-{
- smb_node_t *node;
- smb_srqueue_t *srq;
- int total_bytes, n_setup, n_param, n_data;
- int param_off, param_pad, data_off, data_pad;
- struct smb_xa *xa;
- smb_error_t err;
-
- SMB_REQ_VALID(sr);
- srq = sr->session->s_srqueue;
- smb_srqueue_waitq_to_runq(srq);
+ if (sr->sr_state == SMB_REQ_STATE_EVENT_OCCURRED)
+ sr->sr_state = SMB_REQ_STATE_ACTIVE;
+ mutex_exit(&sr->sr_mutex);
- xa = sr->r_xa;
- node = sr->sr_ncr.nc_node;
+ /*
+ * Unsubscribe from events on this node.
+ */
+ smb_node_fcn_unsubscribe(node, sr);
- if (--node->waiting_event == 0) {
- node->flags &= ~(NODE_FLAGS_NOTIFY_CHANGE | NODE_FLAGS_CHANGED);
- smb_fem_fcn_uninstall(node);
- }
+ /*
+ * Build the reply
+ */
- mutex_enter(&sr->sr_mutex);
switch (sr->sr_state) {
- case SMB_REQ_STATE_EVENT_OCCURRED:
- sr->sr_state = SMB_REQ_STATE_ACTIVE;
-
- /* many things changed */
-
- (void) smb_mbc_encodef(&xa->rep_data_mb, "l", 0L);
-
- /* setup the NT transact reply */
-
- n_setup = MBC_LENGTH(&xa->rep_setup_mb);
- n_param = MBC_LENGTH(&xa->rep_param_mb);
- n_data = MBC_LENGTH(&xa->rep_data_mb);
-
- n_setup = (n_setup + 1) / 2; /* Convert to setup words */
- param_pad = 1; /* must be one */
- param_off = param_pad + 32 + 37 + (n_setup << 1) + 2;
- /* Pad to 4 bytes */
- data_pad = (4 - ((param_off + n_param) & 3)) % 4;
- /* Param off from hdr */
- data_off = param_off + n_param + data_pad;
- total_bytes = param_pad + n_param + data_pad + n_data;
-
- (void) smbsr_encode_result(sr, 18+n_setup, total_bytes,
- "b3.llllllllbCw#.C#.C",
- 18 + n_setup, /* wct */
- n_param, /* Total Parameter Bytes */
- n_data, /* Total Data Bytes */
- n_param, /* Total Parameter Bytes this buffer */
- param_off, /* Param offset from header start */
- 0, /* Param displacement */
- n_data, /* Total Data Bytes this buffer */
- data_off, /* Data offset from header start */
- 0, /* Data displacement */
- n_setup, /* suwcnt */
- &xa->rep_setup_mb, /* setup[] */
- total_bytes, /* Total data bytes */
- param_pad,
- &xa->rep_param_mb,
- data_pad,
- &xa->rep_data_mb);
+ case SMB_REQ_STATE_ACTIVE:
+ /*
+ * If we have event data, marshall it now, else just
+ * say "many things changed". Note that when we are
+ * woken by a WatchTree event (action == 0) then we
+ * don't have true event details, and only know the
+ * directory under which something changed. In that
+ * case we just say "many things changed".
+ */
+ if (sr->sr_ncr.nc_action != 0 && 0 ==
+ smb_notify_encode_action(sr, xa,
+ sr->sr_ncr.nc_action, sr->sr_ncr.nc_fname)) {
+ rc = SDRC_SUCCESS;
+ break;
+ }
+ /*
+ * This error says "many things changed".
+ */
+ err.status = NT_STATUS_NOTIFY_ENUM_DIR;
+ err.errcls = ERRDOS;
+ err.errcode = ERROR_NOTIFY_ENUM_DIR;
+ smbsr_set_error(sr, &err);
+ rc = SDRC_ERROR;
break;
case SMB_REQ_STATE_CANCELED:
@@ -344,284 +244,226 @@ smb_reply_notify_change_request(smb_request_t *sr)
err.errcls = ERRDOS;
err.errcode = ERROR_OPERATION_ABORTED;
smbsr_set_error(sr, &err);
-
- (void) smb_mbc_encodef(&sr->reply, "bwbw",
- (short)0, 0L, (short)0, 0L);
- sr->smb_wct = 0;
- sr->smb_bcc = 0;
+ rc = SDRC_ERROR;
break;
+
default:
ASSERT(0);
+ err.status = NT_STATUS_INTERNAL_ERROR;
+ err.errcls = ERRDOS;
+ err.errcode = ERROR_INTERNAL_ERROR;
+ smbsr_set_error(sr, &err);
+ rc = SDRC_ERROR;
+ break;
}
- mutex_exit(&sr->sr_mutex);
- /* Setup the header */
- (void) smb_mbc_poke(&sr->reply, 0, SMB_HEADER_ED_FMT,
- sr->first_smb_com,
- sr->smb_rcls,
- sr->smb_reh,
- sr->smb_err,
- sr->smb_flg | SMB_FLAGS_REPLY,
- sr->smb_flg2,
- sr->smb_pid_high,
- sr->smb_sig,
- sr->smb_tid,
- sr->smb_pid,
- sr->smb_uid,
- sr->smb_mid);
-
- if (sr->session->signing.flags & SMB_SIGNING_ENABLED)
- smb_sign_reply(sr, NULL);
-
- /* send the reply */
- DTRACE_PROBE1(ncr__reply, struct smb_request *, sr)
- (void) smb_session_send(sr->session, 0, &sr->reply);
- smbsr_cleanup(sr);
+ if (sr->sr_ncr.nc_fname != NULL) {
+ kmem_free(sr->sr_ncr.nc_fname, MAXNAMELEN);
+ sr->sr_ncr.nc_fname = NULL;
+ }
- mutex_enter(&sr->sr_mutex);
- sr->sr_state = SMB_REQ_STATE_COMPLETED;
- mutex_exit(&sr->sr_mutex);
- smb_srqueue_runq_exit(srq);
- smb_request_free(sr);
+ return (rc);
}
/*
- * smb_process_session_notify_change_queue
+ * Encode a FILE_NOTIFY_INFORMATION struct.
*
- * This function traverses notify change request queue and sends
- * cancel replies to all of requests that are related to a specific
- * session.
+ * We only ever put one of these in a response, so this
+ * does not bother handling appending additional ones.
*/
-void
-smb_process_session_notify_change_queue(
- smb_session_t *session,
- smb_tree_t *tree)
+static int
+smb_notify_encode_action(struct smb_request *sr, struct smb_xa *xa,
+ uint32_t action, char *fname)
{
- smb_request_t *sr;
- smb_request_t *tmp;
- boolean_t sig = B_FALSE;
+ uint32_t namelen;
+ int rc;
- smb_slist_enter(&smb_ncr_list);
- smb_slist_enter(&smb_nce_list);
- sr = smb_slist_head(&smb_ncr_list);
- while (sr) {
- ASSERT(sr->sr_magic == SMB_REQ_MAGIC);
- tmp = smb_slist_next(&smb_ncr_list, sr);
- if ((sr->session == session) &&
- (tree == NULL || sr->tid_tree == tree)) {
- mutex_enter(&sr->sr_mutex);
- switch (sr->sr_state) {
- case SMB_REQ_STATE_WAITING_EVENT:
- smb_slist_obj_move(
- &smb_nce_list,
- &smb_ncr_list,
- sr);
- smb_srqueue_waitq_enter(
- sr->session->s_srqueue);
- sr->sr_state = SMB_REQ_STATE_CANCELED;
- sig = B_TRUE;
- break;
- default:
- ASSERT(0);
- break;
- }
- mutex_exit(&sr->sr_mutex);
- }
- sr = tmp;
- }
- smb_slist_exit(&smb_nce_list);
- smb_slist_exit(&smb_ncr_list);
- if (sig)
- smb_thread_signal(&smb_thread_notify_daemon);
-}
+ if (action < FILE_ACTION_ADDED ||
+ action > FILE_ACTION_MODIFIED_STREAM)
+ return (-1);
-/*
- * smb_process_file_notify_change_queue
- *
- * This function traverses notify change request queue and sends
- * cancel replies to all of requests that are related to the
- * specified file.
- */
-void
-smb_process_file_notify_change_queue(struct smb_ofile *of)
-{
- smb_request_t *sr;
- smb_request_t *tmp;
- boolean_t sig = B_FALSE;
+ namelen = smb_ascii_or_unicode_strlen(sr, fname);
+ if (namelen == 0)
+ return (-1);
- smb_slist_enter(&smb_ncr_list);
- smb_slist_enter(&smb_nce_list);
- sr = smb_slist_head(&smb_ncr_list);
- while (sr) {
- ASSERT(sr->sr_magic == SMB_REQ_MAGIC);
- tmp = smb_slist_next(&smb_ncr_list, sr);
- if (sr->fid_ofile == of) {
- mutex_enter(&sr->sr_mutex);
- switch (sr->sr_state) {
- case SMB_REQ_STATE_WAITING_EVENT:
- smb_slist_obj_move(&smb_nce_list,
- &smb_ncr_list, sr);
- smb_srqueue_waitq_enter(
- sr->session->s_srqueue);
- sr->sr_state = SMB_REQ_STATE_CANCELED;
- sig = B_TRUE;
- break;
- default:
- ASSERT(0);
- break;
- }
- mutex_exit(&sr->sr_mutex);
- }
- sr = tmp;
- }
- smb_slist_exit(&smb_nce_list);
- smb_slist_exit(&smb_ncr_list);
- if (sig)
- smb_thread_signal(&smb_thread_notify_daemon);
+ rc = smb_mbc_encodef(&xa->rep_data_mb, "%lllu", sr,
+ 0, /* NextEntryOffset */
+ action, namelen, fname);
+ return (rc);
}
/*
- * smb_reply_specific_cancel_request
+ * smb_notify_file_closed
*
- * This function searches global request list for a specific request. If found,
- * moves the request to event queue and kicks the notify change daemon.
+ * Cancel any change-notify calls on this open file.
*/
-
void
-smb_reply_specific_cancel_request(struct smb_request *zsr)
+smb_notify_file_closed(struct smb_ofile *of)
{
+ smb_session_t *ses;
smb_request_t *sr;
- smb_request_t *tmp;
- boolean_t sig = B_FALSE;
+ smb_slist_t *list;
- smb_slist_enter(&smb_ncr_list);
- smb_slist_enter(&smb_nce_list);
- sr = smb_slist_head(&smb_ncr_list);
+ SMB_OFILE_VALID(of);
+ ses = of->f_session;
+ SMB_SESSION_VALID(ses);
+ list = &ses->s_req_list;
+
+ smb_slist_enter(list);
+
+ sr = smb_slist_head(list);
while (sr) {
- ASSERT(sr->sr_magic == SMB_REQ_MAGIC);
- tmp = smb_slist_next(&smb_ncr_list, sr);
- if ((sr->session == zsr->session) &&
- (sr->smb_uid == zsr->smb_uid) &&
- (sr->smb_pid == zsr->smb_pid) &&
- (sr->smb_tid == zsr->smb_tid) &&
- (sr->smb_mid == zsr->smb_mid)) {
- mutex_enter(&sr->sr_mutex);
- switch (sr->sr_state) {
- case SMB_REQ_STATE_WAITING_EVENT:
- smb_slist_obj_move(&smb_nce_list,
- &smb_ncr_list, sr);
- smb_srqueue_waitq_enter(
- sr->session->s_srqueue);
- sr->sr_state = SMB_REQ_STATE_CANCELED;
- sig = B_TRUE;
- break;
- default:
- ASSERT(0);
- break;
- }
- mutex_exit(&sr->sr_mutex);
+ SMB_REQ_VALID(sr);
+ if (sr->sr_state == SMB_REQ_STATE_WAITING_EVENT &&
+ sr->fid_ofile == of) {
+ smb_request_cancel(sr);
}
- sr = tmp;
+ sr = smb_slist_next(list, sr);
}
- smb_slist_exit(&smb_nce_list);
- smb_slist_exit(&smb_ncr_list);
- if (sig)
- smb_thread_signal(&smb_thread_notify_daemon);
+
+ smb_slist_exit(list);
}
+
/*
- * smb_process_node_notify_change_queue
+ * smb_notify_event
+ *
+ * Post an event to the watchers on a given node.
+ *
+ * This makes one exception for RENAME, where we expect a
+ * pair of events for the {old,new} directory element names.
+ * This only delivers an event for the "new" name.
+ *
+ * The event delivery mechanism does not implement delivery of
+ * multiple events for one "NT Notify" call. One could do that,
+ * but modern clients don't actually use the event data. They
+ * set a max. received data size of zero, which means we discard
+ * the data and send the special "lots changed" error instead.
+ * Given that, there's not really any point in implementing the
+ * delivery of multiple events. In fact, we don't even need to
+ * implement single event delivery, but do so for completeness,
+ * for debug convenience, and to be nice to older clients that
+ * may actually want some event data instead of the error.
*
- * This function searches notify change request queue and sends
- * 'NODE MODIFIED' reply to all requests which are related to a
- * specific node.
- * WatchTree flag: We handle this flag in a special manner just
- * for DAVE clients. When something is changed, we notify all
- * requests which came from DAVE clients on the same volume which
- * has been modified. We don't care about the tree that they wanted
- * us to monitor. any change in any part of the volume will lead
- * to notifying all notify change requests from DAVE clients on the
- * different parts of the volume hierarchy.
+ * Given that we only deliver a single event for an "NT Notify"
+ * caller, we want to deliver the "new" name event. (The "old"
+ * name event is less important, even ignored by some clients.)
+ * Since we know these are delivered in pairs, we can simply
+ * discard the "old" name event, knowing that the "new" name
+ * event will be delivered immediately afterwards.
+ *
+ * So, why do event sources post the "old name" event at all?
+ * (1) For debugging, so we see both {old,new} names here.
+ * (2) If in the future someone decides to implement the
+ * delivery of both {old,new} events, the changes can be
+ * mostly isolated to this file.
*/
void
-smb_process_node_notify_change_queue(smb_node_t *node)
+smb_notify_event(smb_node_t *node, uint_t action, const char *name)
{
smb_request_t *sr;
- smb_request_t *tmp;
- smb_node_t *nc_node;
- boolean_t sig = B_FALSE;
+ smb_node_fcn_t *fcn;
- ASSERT(node->n_magic == SMB_NODE_MAGIC);
+ SMB_NODE_VALID(node);
+ fcn = &node->n_fcn;
- if (!(node->flags & NODE_FLAGS_NOTIFY_CHANGE))
- return;
+ if (action == FILE_ACTION_RENAMED_OLD_NAME)
+ return; /* see above */
- node->flags |= NODE_FLAGS_CHANGED;
+ mutex_enter(&fcn->fcn_mutex);
- smb_slist_enter(&smb_ncr_list);
- smb_slist_enter(&smb_nce_list);
- sr = smb_slist_head(&smb_ncr_list);
+ sr = list_head(&fcn->fcn_watchers);
while (sr) {
- ASSERT(sr->sr_magic == SMB_REQ_MAGIC);
- tmp = smb_slist_next(&smb_ncr_list, sr);
-
- nc_node = sr->sr_ncr.nc_node;
- if (nc_node == node) {
- mutex_enter(&sr->sr_mutex);
- switch (sr->sr_state) {
- case SMB_REQ_STATE_WAITING_EVENT:
- smb_slist_obj_move(&smb_nce_list,
- &smb_ncr_list, sr);
- smb_srqueue_waitq_enter(
- sr->session->s_srqueue);
- sr->sr_state = SMB_REQ_STATE_EVENT_OCCURRED;
- sig = B_TRUE;
- break;
- default:
- ASSERT(0);
- break;
- }
- mutex_exit(&sr->sr_mutex);
- }
- sr = tmp;
+ smb_notify_sr(sr, action, name);
+ sr = list_next(&fcn->fcn_watchers, sr);
}
- smb_slist_exit(&smb_nce_list);
- smb_slist_exit(&smb_ncr_list);
- if (sig)
- smb_thread_signal(&smb_thread_notify_daemon);
+
+ mutex_exit(&fcn->fcn_mutex);
}
/*
- * smb_notify_change_daemon
+ * What completion filter (masks) apply to each of the
+ * FILE_ACTION_... events.
+ */
+static const uint32_t
+smb_notify_action_mask[] = {
+ /* 0: Special, used by smb_node_notify_parents() */
+ NODE_FLAGS_WATCH_TREE,
+
+ /* FILE_ACTION_ADDED */
+ FILE_NOTIFY_CHANGE_NAME,
+
+ /* FILE_ACTION_REMOVED */
+ FILE_NOTIFY_CHANGE_NAME,
+
+ /* FILE_ACTION_MODIFIED */
+ FILE_NOTIFY_CHANGE_ATTRIBUTES |
+ FILE_NOTIFY_CHANGE_SIZE |
+ FILE_NOTIFY_CHANGE_LAST_WRITE |
+ FILE_NOTIFY_CHANGE_LAST_ACCESS |
+ FILE_NOTIFY_CHANGE_CREATION |
+ FILE_NOTIFY_CHANGE_EA |
+ FILE_NOTIFY_CHANGE_SECURITY,
+
+ /* FILE_ACTION_RENAMED_OLD_NAME */
+ FILE_NOTIFY_CHANGE_NAME,
+
+ /* FILE_ACTION_RENAMED_NEW_NAME */
+ FILE_NOTIFY_CHANGE_NAME,
+
+ /* FILE_ACTION_ADDED_STREAM */
+ FILE_NOTIFY_CHANGE_STREAM_NAME,
+
+ /* FILE_ACTION_REMOVED_STREAM */
+ FILE_NOTIFY_CHANGE_STREAM_NAME,
+
+ /* FILE_ACTION_MODIFIED_STREAM */
+ FILE_NOTIFY_CHANGE_STREAM_SIZE |
+ FILE_NOTIFY_CHANGE_STREAM_WRITE,
+};
+static const int smb_notify_action_nelm =
+ sizeof (smb_notify_action_mask) /
+ sizeof (smb_notify_action_mask[0]);
+
+/*
+ * smb_notify_sr
*
- * This function processes notify change event list and send appropriate
- * responses to the requests. This function executes in the system as an
- * indivdual thread.
+ * Post an event to an smb request waiting on some node.
+ *
+ * Note that node->fcn.mutex is held. This implies a
+ * lock order: node->fcn.mutex, then sr_mutex
*/
static void
-smb_notify_change_daemon(smb_thread_t *thread, void *arg)
+smb_notify_sr(smb_request_t *sr, uint_t action, const char *name)
{
- _NOTE(ARGUNUSED(arg))
+ smb_notify_change_req_t *ncr;
+ uint32_t mask;
- smb_request_t *sr;
- smb_request_t *tmp;
- list_t sr_list;
-
- list_create(&sr_list, sizeof (smb_request_t),
- offsetof(smb_request_t, sr_ncr.nc_lnd));
-
- while (smb_thread_continue(thread)) {
-
- while (smb_slist_move_tail(&sr_list, &smb_nce_list)) {
- sr = list_head(&sr_list);
- while (sr) {
- ASSERT(sr->sr_magic == SMB_REQ_MAGIC);
- tmp = list_next(&sr_list, sr);
- list_remove(&sr_list, sr);
- smb_reply_notify_change_request(sr);
- sr = tmp;
- }
- }
+ SMB_REQ_VALID(sr);
+ ncr = &sr->sr_ncr;
+
+ /*
+ * Compute the completion filter mask bits for which
+ * we will signal waiting notify requests.
+ */
+ if (action >= smb_notify_action_nelm) {
+ ASSERT(0);
+ return;
}
- list_destroy(&sr_list);
+ mask = smb_notify_action_mask[action];
+
+ mutex_enter(&sr->sr_mutex);
+ if (sr->sr_state == SMB_REQ_STATE_WAITING_EVENT &&
+ (ncr->nc_flags & mask) != 0) {
+ sr->sr_state = SMB_REQ_STATE_EVENT_OCCURRED;
+ /*
+ * Save event data in the sr_ncr field so the
+ * reply handler can return it.
+ */
+ ncr->nc_action = action;
+ if (name != NULL)
+ (void) strlcpy(ncr->nc_fname, name, MAXNAMELEN);
+ cv_signal(&ncr->nc_cv);
+ }
+ mutex_exit(&sr->sr_mutex);
}
diff --git a/usr/src/uts/common/fs/smbsrv/smb_odir.c b/usr/src/uts/common/fs/smbsrv/smb_odir.c
index 610126753b..aff6183f97 100644
--- a/usr/src/uts/common/fs/smbsrv/smb_odir.c
+++ b/usr/src/uts/common/fs/smbsrv/smb_odir.c
@@ -559,7 +559,7 @@ smb_odir_read(smb_request_t *sr, smb_odir_t *od,
*/
int
smb_odir_read_fileinfo(smb_request_t *sr, smb_odir_t *od,
- smb_fileinfo_t *fileinfo, boolean_t *eof)
+ smb_fileinfo_t *fileinfo, uint16_t *eof)
{
int rc, errnum;
smb_odirent_t *odirent;
@@ -584,7 +584,7 @@ smb_odir_read_fileinfo(smb_request_t *sr, smb_odir_t *od,
return (-1);
}
- if (!(od->d_flags & SMB_ODIR_FLAG_WILDCARDS)) {
+ if ((od->d_flags & SMB_ODIR_FLAG_WILDCARDS) == 0) {
if (od->d_eof)
rc = ENOENT;
else
@@ -617,10 +617,10 @@ smb_odir_read_fileinfo(smb_request_t *sr, smb_odir_t *od,
switch (rc) {
case 0:
- *eof = B_FALSE;
+ *eof = 0;
return (0);
case ENOENT:
- *eof = B_TRUE;
+ *eof = 1; /* per. FindFirst, FindNext spec. */
return (0);
default:
smbsr_errno(sr, rc);
@@ -743,6 +743,28 @@ smb_odir_save_cookie(smb_odir_t *od, int idx, uint32_t cookie)
}
/*
+ * smb_odir_save_fname
+ *
+ * Save a filename / offset pair, which are basically a
+ * one entry cache. See smb_com_trans2_find_next2.
+ */
+void
+smb_odir_save_fname(smb_odir_t *od, uint32_t cookie, const char *fname)
+{
+ ASSERT(od);
+ ASSERT(od->d_magic == SMB_ODIR_MAGIC);
+
+ mutex_enter(&od->d_mutex);
+
+ od->d_last_cookie = cookie;
+ bzero(od->d_last_name, MAXNAMELEN);
+ if (fname != NULL)
+ (void) strlcpy(od->d_last_name, fname, MAXNAMELEN);
+
+ mutex_exit(&od->d_mutex);
+}
+
+/*
* smb_odir_resume_at
*
* If SMB_ODIR_FLAG_WILDCARDS is not set the search is for a single
@@ -775,23 +797,45 @@ smb_odir_resume_at(smb_odir_t *od, smb_odir_resume_t *resume)
}
switch (resume->or_type) {
- case SMB_ODIR_RESUME_IDX:
- ASSERT(resume->or_idx >= 0);
- ASSERT(resume->or_idx < SMB_MAX_SEARCH);
-
- if ((resume->or_idx < 0) ||
- (resume->or_idx >= SMB_MAX_SEARCH)) {
- resume->or_idx = 0;
- }
- od->d_offset = od->d_cookies[resume->or_idx];
- break;
- case SMB_ODIR_RESUME_COOKIE:
+
+ default:
+ case SMB_ODIR_RESUME_CONT:
+ /* Continue where we left off. */
+ break;
+
+ case SMB_ODIR_RESUME_IDX:
+ /*
+ * This is used only by the (ancient) SMB_SEARCH.
+ * Modern clients use trans2 FindFirst, FindNext.
+ */
+ ASSERT(resume->or_idx >= 0);
+ ASSERT(resume->or_idx < SMB_MAX_SEARCH);
+
+ if ((resume->or_idx < 0) ||
+ (resume->or_idx >= SMB_MAX_SEARCH)) {
+ resume->or_idx = 0;
+ }
+ od->d_offset = od->d_cookies[resume->or_idx];
+ break;
+
+ case SMB_ODIR_RESUME_COOKIE:
+ od->d_offset = resume->or_cookie;
+ break;
+
+ case SMB_ODIR_RESUME_FNAME:
+ /*
+ * If the name matches the last one saved,
+ * use the offset that was saved with it in
+ * the odir. Otherwise use the cookie value
+ * in the resume data from the client.
+ */
+ if (strcmp(resume->or_fname, od->d_last_name) &&
+ od->d_last_cookie != 0) {
+ od->d_offset = od->d_last_cookie;
+ } else if (resume->or_cookie != 0) {
od->d_offset = resume->or_cookie;
- break;
- case SMB_ODIR_RESUME_FNAME:
- default:
- od->d_offset = od->d_cookies[0];
- break;
+ } /* else continue where we left off */
+ break;
}
/* Force a vop_readdir to refresh d_buf */
diff --git a/usr/src/uts/common/fs/smbsrv/smb_ofile.c b/usr/src/uts/common/fs/smbsrv/smb_ofile.c
index 6855a795bd..39635170e9 100644
--- a/usr/src/uts/common/fs/smbsrv/smb_ofile.c
+++ b/usr/src/uts/common/fs/smbsrv/smb_ofile.c
@@ -20,6 +20,7 @@
*/
/*
* Copyright (c) 2007, 2010, Oracle and/or its affiliates. All rights reserved.
+ * Copyright 2012 Nexenta Systems, Inc. All rights reserved.
*/
/*
@@ -324,11 +325,11 @@ smb_ofile_close(smb_ofile_t *of, uint32_t last_wtime)
of->f_cr);
/*
- * Cancel any notify change requests related
- * to this open instance.
+ * Cancel any notify change requests that
+ * may be using this open instance.
*/
- if (of->f_node->flags & NODE_FLAGS_NOTIFY_CHANGE)
- smb_process_file_notify_change_queue(of);
+ if (of->f_node->n_fcn.fcn_count)
+ smb_notify_file_closed(of);
smb_server_dec_files(of->f_server);
}
atomic_dec_32(&of->f_tree->t_open_files);
diff --git a/usr/src/uts/common/fs/smbsrv/smb_pathname.c b/usr/src/uts/common/fs/smbsrv/smb_pathname.c
index db9883667e..7b703f3027 100644
--- a/usr/src/uts/common/fs/smbsrv/smb_pathname.c
+++ b/usr/src/uts/common/fs/smbsrv/smb_pathname.c
@@ -129,9 +129,9 @@ smb_is_executable(char *path)
* smb_fsop_lookup(), smb_vop_lookup() and other smb_vop_*() routines in the
* following areas:
*
- * - non-traversal of child mounts (handled by smb_pathname_reduce)
- * - unmangling (handled in smb_pathname)
- * - "chroot" behavior of share root (handled by lookuppnvp)
+ * - traversal of child mounts (handled by smb_pathname_reduce)
+ * - unmangling (handled in smb_pathname)
+ * - "chroot" behavior of share root (handled by lookuppnvp)
*
* In addition, it needs to replace backslashes with forward slashes. It also
* ensures that link processing is done correctly, and that directory
@@ -271,18 +271,26 @@ smb_pathname_reduce(
kmem_free(usepath, MAXPATHLEN);
/*
- * Prevent access to anything outside of the share root, except
- * when mapping a share because that may require traversal from
- * / to a mounted file system. share_root_node is NULL when
- * mapping a share.
+ * Prevent traversal to another file system if mount point
+ * traversal is disabled.
*
* Note that we disregard whether the traversal of the path went
* outside of the file system and then came back (say via a link).
+ * This means that only symlinks that are expressed relatively to
+ * the share root work.
+ *
+ * share_root_node is NULL when mapping a share, so we disregard
+ * that case.
*/
if ((err == 0) && share_root_node) {
- if (share_root_node->vp->v_vfsp != (*dir_node)->vp->v_vfsp)
+ if (share_root_node->vp->v_vfsp != (*dir_node)->vp->v_vfsp) {
err = EACCES;
+ if ((sr) && (sr)->tid_tree &&
+ smb_tree_has_feature((sr)->tid_tree,
+ SMB_TREE_TRAVERSE_MOUNTS))
+ err = 0;
+ }
}
if (err) {
diff --git a/usr/src/uts/common/fs/smbsrv/smb_rename.c b/usr/src/uts/common/fs/smbsrv/smb_rename.c
index ca09cf4935..8541fdc847 100644
--- a/usr/src/uts/common/fs/smbsrv/smb_rename.c
+++ b/usr/src/uts/common/fs/smbsrv/smb_rename.c
@@ -20,6 +20,7 @@
*/
/*
* Copyright (c) 2007, 2010, Oracle and/or its affiliates. All rights reserved.
+ * Copyright 2012 Nexenta Systems, Inc. All rights reserved.
*/
#include <sys/synch.h>
@@ -480,10 +481,25 @@ smb_common_rename(smb_request_t *sr, smb_fqi_t *src_fqi, smb_fqi_t *dst_fqi)
src_dnode, src_fnode->od_name,
dst_dnode, new_name);
- smb_rename_release_src(sr);
+ if (rc == 0) {
+ /*
+ * Note that renames in the same directory are normally
+ * delivered in {old,new} pairs, and clients expect them
+ * in that order, if both events are delivered.
+ */
+ int a_src, a_dst; /* action codes */
+ if (src_dnode == dst_dnode) {
+ a_src = FILE_ACTION_RENAMED_OLD_NAME;
+ a_dst = FILE_ACTION_RENAMED_NEW_NAME;
+ } else {
+ a_src = FILE_ACTION_REMOVED;
+ a_dst = FILE_ACTION_ADDED;
+ }
+ smb_node_notify_change(src_dnode, a_src, src_fnode->od_name);
+ smb_node_notify_change(dst_dnode, a_dst, new_name);
+ }
- if (rc == 0)
- smb_node_notify_change(dst_dnode);
+ smb_rename_release_src(sr);
if (dst_fqi->fq_fnode) {
smb_node_end_crit(dst_fnode);
@@ -617,9 +633,12 @@ smb_make_link(smb_request_t *sr, smb_fqi_t *src_fqi, smb_fqi_t *dst_fqi)
rc = smb_fsop_link(sr, sr->user_cr, src_fqi->fq_fnode,
dst_fqi->fq_dnode, dst_fqi->fq_last_comp);
+ if (rc == 0) {
+ smb_node_notify_change(dst_fqi->fq_dnode,
+ FILE_ACTION_ADDED, dst_fqi->fq_last_comp);
+ }
+
smb_rename_release_src(sr);
- if (rc == 0)
- smb_node_notify_change(dst_fqi->fq_dnode);
smb_node_release(dst_fqi->fq_dnode);
return (rc);
}
diff --git a/usr/src/uts/common/fs/smbsrv/smb_server.c b/usr/src/uts/common/fs/smbsrv/smb_server.c
index e3bcec5ba6..3654744569 100644
--- a/usr/src/uts/common/fs/smbsrv/smb_server.c
+++ b/usr/src/uts/common/fs/smbsrv/smb_server.c
@@ -230,8 +230,8 @@ typedef struct {
static void smb_server_kstat_init(smb_server_t *);
static void smb_server_kstat_fini(smb_server_t *);
static void smb_server_timers(smb_thread_t *, void *);
-static int smb_server_lookup(smb_server_t **);
-static void smb_server_release(smb_server_t *);
+int smb_server_lookup(smb_server_t **);
+void smb_server_release(smb_server_t *);
static void smb_server_store_cfg(smb_server_t *, smb_ioc_cfg_t *);
static void smb_server_shutdown(smb_server_t *);
static int smb_server_fsop_start(smb_server_t *);
@@ -294,8 +294,6 @@ smb_server_svc_init(void)
continue;
if (rc = smb_fem_init())
continue;
- if (rc = smb_notify_init())
- continue;
if (rc = smb_net_init())
continue;
smb_llist_init();
@@ -306,7 +304,6 @@ smb_server_svc_init(void)
smb_llist_fini();
smb_net_fini();
- smb_notify_fini();
smb_fem_fini();
smb_node_fini();
smb_vop_fini();
@@ -328,7 +325,6 @@ smb_server_svc_fini(void)
if (smb_llist_get_count(&smb_servers) == 0) {
smb_llist_fini();
smb_net_fini();
- smb_notify_fini();
smb_fem_fini();
smb_node_fini();
smb_oplock_fini();
@@ -1408,6 +1404,14 @@ smb_server_shutdown(smb_server_t *sv)
smb_server_listener_stop(&sv->sv_tcp_daemon);
if (sv->sv_session != NULL) {
+ /*
+ * smb_kshare_export may have a request on here.
+ * Normal sessions do this in smb_session_cancel()
+ * but this is a "fake" session used only for the
+ * requests used by the kshare thread(s).
+ */
+ smb_slist_wait_for_empty(&sv->sv_session->s_req_list);
+
smb_session_delete(sv->sv_session);
sv->sv_session = NULL;
}
@@ -1637,7 +1641,7 @@ smb_server_receiver(void *arg)
* This function tries to find the server associated with the zone of the
* caller.
*/
-static int
+int
smb_server_lookup(smb_server_t **psv)
{
zoneid_t zid;
@@ -1673,7 +1677,7 @@ smb_server_lookup(smb_server_t **psv)
* This function decrements the reference count of the server and signals its
* condition variable if the state of the server is SMB_SERVER_STATE_DELETING.
*/
-static void
+void
smb_server_release(smb_server_t *sv)
{
SMB_SERVER_VALID(sv);
@@ -1844,6 +1848,7 @@ smb_server_store_cfg(smb_server_t *sv, smb_ioc_cfg_t *ioc)
sv->sv_cfg.skc_secmode = ioc->secmode;
sv->sv_cfg.skc_ipv6_enable = ioc->ipv6_enable;
sv->sv_cfg.skc_print_enable = ioc->print_enable;
+ sv->sv_cfg.skc_traverse_mounts = ioc->traverse_mounts;
sv->sv_cfg.skc_execflags = ioc->exec_flags;
sv->sv_cfg.skc_version = ioc->version;
(void) strlcpy(sv->sv_cfg.skc_nbdomain, ioc->nbdomain,
diff --git a/usr/src/uts/common/fs/smbsrv/smb_session.c b/usr/src/uts/common/fs/smbsrv/smb_session.c
index 6e1bd6d69a..f2a337158f 100644
--- a/usr/src/uts/common/fs/smbsrv/smb_session.c
+++ b/usr/src/uts/common/fs/smbsrv/smb_session.c
@@ -19,8 +19,8 @@
* CDDL HEADER END
*/
/*
- * Copyright 2011 Nexenta Systems, Inc. All rights reserved.
* Copyright (c) 2007, 2010, Oracle and/or its affiliates. All rights reserved.
+ * Copyright 2012 Nexenta Systems, Inc. All rights reserved.
*/
#include <sys/atomic.h>
#include <sys/strsubr.h>
@@ -392,13 +392,14 @@ smb_request_cancel(smb_request_t *sr)
break;
case SMB_REQ_STATE_WAITING_EVENT:
- case SMB_REQ_STATE_EVENT_OCCURRED:
/*
- * Cancellations for these states are handled by the
- * notify-change code
+ * This request is waiting in change notify.
*/
+ sr->sr_state = SMB_REQ_STATE_CANCELED;
+ cv_signal(&sr->sr_ncr.nc_cv);
break;
+ case SMB_REQ_STATE_EVENT_OCCURRED:
case SMB_REQ_STATE_COMPLETED:
case SMB_REQ_STATE_CANCELED:
/*
@@ -785,8 +786,6 @@ smb_session_cancel_requests(
{
smb_request_t *sr;
- smb_process_session_notify_change_queue(session, tree);
-
smb_slist_enter(&session->s_req_list);
sr = smb_slist_head(&session->s_req_list);
@@ -1076,6 +1075,7 @@ smb_request_alloc(smb_session_t *session, int req_length)
bzero(sr, sizeof (smb_request_t));
mutex_init(&sr->sr_mutex, NULL, MUTEX_DEFAULT, NULL);
+ cv_init(&sr->sr_ncr.nc_cv, NULL, CV_DEFAULT, NULL);
smb_srm_init(sr);
sr->session = session;
sr->sr_server = session->s_server;
@@ -1104,6 +1104,7 @@ smb_request_free(smb_request_t *sr)
ASSERT(sr->sr_magic == SMB_REQ_MAGIC);
ASSERT(sr->session);
ASSERT(sr->r_xa == NULL);
+ ASSERT(sr->sr_ncr.nc_fname == NULL);
if (sr->fid_ofile != NULL) {
smb_ofile_request_complete(sr->fid_ofile);
@@ -1132,6 +1133,7 @@ smb_request_free(smb_request_t *sr)
m_freem(sr->raw_data.chain);
sr->sr_magic = 0;
+ cv_destroy(&sr->sr_ncr.nc_cv);
mutex_destroy(&sr->sr_mutex);
kmem_cache_free(sr->sr_cache, sr);
}
diff --git a/usr/src/uts/common/fs/smbsrv/smb_trans2_find.c b/usr/src/uts/common/fs/smbsrv/smb_trans2_find.c
index 4eb2ca3740..037b2a3b36 100644
--- a/usr/src/uts/common/fs/smbsrv/smb_trans2_find.c
+++ b/usr/src/uts/common/fs/smbsrv/smb_trans2_find.c
@@ -19,6 +19,7 @@
* CDDL HEADER END
*/
/*
+ * Copyright 2012 Nexenta Systems, Inc. All rights reserved.
* Copyright 2010 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
@@ -206,15 +207,23 @@
#include <smbsrv/msgbuf.h>
#include <smbsrv/smb_fsops.h>
+/*
+ * Args (and other state) that we carry around among the
+ * various functions involved in FindFirst, FindNext.
+ */
typedef struct smb_find_args {
+ uint32_t fa_maxdata;
uint16_t fa_infolev;
uint16_t fa_maxcount;
uint16_t fa_fflag;
- uint32_t fa_maxdata;
+ uint16_t fa_eos; /* End Of Search */
+ uint16_t fa_lno; /* Last Name Offset */
+ uint32_t fa_lastkey; /* Last resume key */
+ char fa_lastname[MAXNAMELEN]; /* and name */
} smb_find_args_t;
static int smb_trans2_find_entries(smb_request_t *, smb_xa_t *,
- smb_odir_t *, smb_find_args_t *, boolean_t *);
+ smb_odir_t *, smb_find_args_t *);
static int smb_trans2_find_get_maxdata(smb_request_t *, uint16_t, uint16_t);
static int smb_trans2_find_mbc_encode(smb_request_t *, smb_xa_t *,
smb_fileinfo_t *, smb_find_args_t *);
@@ -276,7 +285,6 @@ smb_com_trans2_find_first2(smb_request_t *sr, smb_xa_t *xa)
smb_pathname_t *pn;
smb_odir_t *od;
smb_find_args_t args;
- boolean_t eos;
uint32_t odir_flags = 0;
bzero(&args, sizeof (smb_find_args_t));
@@ -327,7 +335,8 @@ smb_com_trans2_find_first2(smb_request_t *sr, smb_xa_t *xa)
od = smb_tree_lookup_odir(sr->tid_tree, odid);
if (od == NULL)
return (SDRC_ERROR);
- count = smb_trans2_find_entries(sr, xa, od, &args, &eos);
+
+ count = smb_trans2_find_entries(sr, xa, od, &args);
if (count == -1) {
smb_odir_close(od);
@@ -343,14 +352,18 @@ smb_com_trans2_find_first2(smb_request_t *sr, smb_xa_t *xa)
}
if ((args.fa_fflag & SMB_FIND_CLOSE_AFTER_REQUEST) ||
- (eos && (args.fa_fflag & SMB_FIND_CLOSE_AT_EOS))) {
+ (args.fa_eos && (args.fa_fflag & SMB_FIND_CLOSE_AT_EOS))) {
smb_odir_close(od);
} /* else leave odir open for trans2_find_next2 */
smb_odir_release(od);
(void) smb_mbc_encodef(&xa->rep_param_mb, "wwwww",
- odid, count, (eos) ? 1 : 0, 0, 0);
+ odid, /* Search ID */
+ count, /* Search Count */
+ args.fa_eos, /* End Of Search */
+ 0, /* EA Error Offset */
+ args.fa_lno); /* Last Name Offset */
return (SDRC_SUCCESS);
}
@@ -422,27 +435,24 @@ smb_com_trans2_find_next2(smb_request_t *sr, smb_xa_t *xa)
{
int count;
uint16_t odid;
- uint32_t cookie;
smb_odir_t *od;
smb_find_args_t args;
- boolean_t eos;
smb_odir_resume_t odir_resume;
- bzero(&args, sizeof (smb_find_args_t));
+ bzero(&args, sizeof (args));
+ bzero(&odir_resume, sizeof (odir_resume));
- if (smb_mbc_decodef(&xa->req_param_mb, "%wwwlw", sr, &odid,
- &args.fa_maxcount, &args.fa_infolev, &cookie, &args.fa_fflag)
- != 0) {
+ if (!STYPE_ISDSK(sr->tid_tree->t_res_type)) {
+ smbsr_error(sr, NT_STATUS_ACCESS_DENIED,
+ ERRDOS, ERROR_ACCESS_DENIED);
return (SDRC_ERROR);
}
- /* continuation by filename not supported */
- if ((args.fa_fflag & SMB_FIND_CONTINUE_FROM_LAST) || (cookie == 0)) {
- odir_resume.or_type = SMB_ODIR_RESUME_IDX;
- odir_resume.or_idx = 0;
- } else {
- odir_resume.or_type = SMB_ODIR_RESUME_COOKIE;
- odir_resume.or_cookie = cookie;
+ if (smb_mbc_decodef(&xa->req_param_mb, "%wwwlwu", sr,
+ &odid, &args.fa_maxcount, &args.fa_infolev,
+ &odir_resume.or_cookie, &args.fa_fflag,
+ &odir_resume.or_fname) != 0) {
+ return (SDRC_ERROR);
}
if (args.fa_fflag & SMB_FIND_WITH_BACKUP_INTENT)
@@ -459,9 +469,34 @@ smb_com_trans2_find_next2(smb_request_t *sr, smb_xa_t *xa)
ERRDOS, ERROR_INVALID_HANDLE);
return (SDRC_ERROR);
}
+
+ /*
+ * Set the correct position in the directory.
+ *
+ * "Continue from last" is easy, but due to a history of
+ * buggy server implementations, most clients don't use
+ * that method. The most widely used (and reliable) is
+ * resume by file name. Unfortunately, that can't really
+ * be fully supported unless your file system stores all
+ * directory entries in some sorted order (like NTFS).
+ * We can partially support resume by name, where the only
+ * name we're ever asked to resume on is the same as the
+ * most recent we returned. That's always what the client
+ * gives us as the resume name, so we can simply remember
+ * the last name/offset pair and use that to position on
+ * the following FindNext call. In the unlikely event
+ * that the client asks to resume somewhere else, we'll
+ * use the numeric resume key, and hope the client gives
+ * correctly uses one of the resume keys we provided.
+ */
+ if (args.fa_fflag & SMB_FIND_CONTINUE_FROM_LAST) {
+ odir_resume.or_type = SMB_ODIR_RESUME_CONT;
+ } else {
+ odir_resume.or_type = SMB_ODIR_RESUME_FNAME;
+ }
smb_odir_resume_at(od, &odir_resume);
- count = smb_trans2_find_entries(sr, xa, od, &args, &eos);
+ count = smb_trans2_find_entries(sr, xa, od, &args);
if (count == -1) {
smb_odir_close(od);
smb_odir_release(od);
@@ -469,13 +504,17 @@ smb_com_trans2_find_next2(smb_request_t *sr, smb_xa_t *xa)
}
if ((args.fa_fflag & SMB_FIND_CLOSE_AFTER_REQUEST) ||
- (eos && (args.fa_fflag & SMB_FIND_CLOSE_AT_EOS))) {
+ (args.fa_eos && (args.fa_fflag & SMB_FIND_CLOSE_AT_EOS))) {
smb_odir_close(od);
} /* else leave odir open for trans2_find_next2 */
smb_odir_release(od);
+
(void) smb_mbc_encodef(&xa->rep_param_mb, "wwww",
- count, (eos) ? 1 : 0, 0, 0);
+ count, /* Search Count */
+ args.fa_eos, /* End Of Search */
+ 0, /* EA Error Offset */
+ args.fa_lno); /* Last Name Offset */
return (SDRC_SUCCESS);
}
@@ -494,12 +533,12 @@ smb_com_trans2_find_next2(smb_request_t *sr, smb_xa_t *xa)
*/
static int
smb_trans2_find_entries(smb_request_t *sr, smb_xa_t *xa, smb_odir_t *od,
- smb_find_args_t *args, boolean_t *eos)
+ smb_find_args_t *args)
{
int rc;
uint16_t count, maxcount;
- uint32_t cookie;
smb_fileinfo_t fileinfo;
+ smb_odir_resume_t odir_resume;
if ((maxcount = args->fa_maxcount) == 0)
maxcount = 1;
@@ -509,9 +548,10 @@ smb_trans2_find_entries(smb_request_t *sr, smb_xa_t *xa, smb_odir_t *od,
count = 0;
while (count < maxcount) {
- if (smb_odir_read_fileinfo(sr, od, &fileinfo, eos) != 0)
+ if (smb_odir_read_fileinfo(sr, od, &fileinfo, &args->fa_eos)
+ != 0)
return (-1);
- if (*eos == B_TRUE)
+ if (args->fa_eos != 0)
break;
rc = smb_trans2_find_mbc_encode(sr, xa, &fileinfo, args);
@@ -520,21 +560,38 @@ smb_trans2_find_entries(smb_request_t *sr, smb_xa_t *xa, smb_odir_t *od,
if (rc == 1)
break;
- cookie = fileinfo.fi_cookie;
+ /*
+ * Save the info about the last file returned.
+ */
+ args->fa_lastkey = fileinfo.fi_cookie;
+ bcopy(fileinfo.fi_name, args->fa_lastname, MAXNAMELEN);
+
++count;
}
/* save the last cookie returned to client */
if (count != 0)
- smb_odir_save_cookie(od, 0, cookie);
+ smb_odir_save_fname(od, args->fa_lastkey, args->fa_lastname);
/*
* If all retrieved entries have been successfully encoded
* and eos has not already been detected, check if there are
* any more entries. eos will be set if there are no more.
*/
- if ((rc == 0) && (!*eos))
- (void) smb_odir_read_fileinfo(sr, od, &fileinfo, eos);
+ if ((rc == 0) && (args->fa_eos == 0))
+ (void) smb_odir_read_fileinfo(sr, od, &fileinfo, &args->fa_eos);
+
+ /*
+ * When the last entry we read from the directory did not
+ * fit in the return buffer, we will have read one entry
+ * that will not be returned in this call. That, and the
+ * check for EOS just above both can leave the directory
+ * position incorrect for the next call. Fix that now.
+ */
+ bzero(&odir_resume, sizeof (odir_resume));
+ odir_resume.or_type = SMB_ODIR_RESUME_COOKIE;
+ odir_resume.or_cookie = args->fa_lastkey;
+ smb_odir_resume_at(od, &odir_resume);
return (count);
}
@@ -608,6 +665,21 @@ smb_trans2_find_get_maxdata(smb_request_t *sr, uint16_t infolev, uint16_t fflag)
}
/*
+ * This is an experimental feature that allows us to return zero
+ * for all numeric resume keys, to match Windows behavior with an
+ * NTFS share. Setting this variable to zero does that.
+ *
+ * It's possible we could remove this variable and always set
+ * numeric resume keys to zero, but that would leave us unable
+ * to handle a FindNext call with an arbitrary start position.
+ * In practice we never see these, but in theory we could.
+ *
+ * See the long comment above smb_com_trans2_find_next2() for
+ * more details about resume key / resume name handling.
+ */
+int smbd_use_resume_keys = 1;
+
+/*
* smb_trans2_mbc_encode
*
* This function encodes the mbc for one directory entry.
@@ -632,23 +704,18 @@ static int
smb_trans2_find_mbc_encode(smb_request_t *sr, smb_xa_t *xa,
smb_fileinfo_t *fileinfo, smb_find_args_t *args)
{
- int namelen, shortlen, buflen;
+ int namelen, shortlen;
uint32_t next_entry_offset;
uint32_t dsize32, asize32;
uint32_t mb_flags = 0;
+ uint32_t resume_key;
char buf83[26];
- char *tmpbuf;
smb_msgbuf_t mb;
namelen = smb_ascii_or_unicode_strlen(sr, fileinfo->fi_name);
if (namelen == -1)
return (-1);
- next_entry_offset = args->fa_maxdata + namelen;
-
- if (MBC_ROOM_FOR(&xa->rep_data_mb, (args->fa_maxdata + namelen)) == 0)
- return (1);
-
/*
* If ascii the filename length returned to the client should
* include the null terminator for levels except STANDARD and
@@ -660,52 +727,49 @@ smb_trans2_find_mbc_encode(smb_request_t *sr, smb_xa_t *xa,
namelen += 1;
}
+ next_entry_offset = args->fa_maxdata + namelen;
+
+ if (MBC_ROOM_FOR(&xa->rep_data_mb, (args->fa_maxdata + namelen)) == 0)
+ return (1);
+
mb_flags = (sr->smb_flg2 & SMB_FLAGS2_UNICODE) ? SMB_MSGBUF_UNICODE : 0;
dsize32 = (fileinfo->fi_size > UINT_MAX) ?
UINT_MAX : (uint32_t)fileinfo->fi_size;
asize32 = (fileinfo->fi_alloc_size > UINT_MAX) ?
UINT_MAX : (uint32_t)fileinfo->fi_alloc_size;
+ resume_key = fileinfo->fi_cookie;
+ if (smbd_use_resume_keys == 0)
+ resume_key = 0;
+
+ /*
+ * This switch handles all the "information levels" (formats)
+ * that we support. Note that all formats have the file name
+ * placed after some fixed-size data, and the code to write
+ * the file name is factored out at the end of this switch.
+ */
switch (args->fa_infolev) {
case SMB_INFO_STANDARD:
if (args->fa_fflag & SMB_FIND_RETURN_RESUME_KEYS)
(void) smb_mbc_encodef(&xa->rep_data_mb, "l",
- fileinfo->fi_cookie);
+ resume_key);
- (void) smb_mbc_encodef(&xa->rep_data_mb, "%yyyllwbu", sr,
+ (void) smb_mbc_encodef(&xa->rep_data_mb, "%yyyllwb", sr,
smb_time_gmt_to_local(sr, fileinfo->fi_crtime.tv_sec),
smb_time_gmt_to_local(sr, fileinfo->fi_atime.tv_sec),
smb_time_gmt_to_local(sr, fileinfo->fi_mtime.tv_sec),
dsize32,
asize32,
fileinfo->fi_dosattr,
- namelen,
- fileinfo->fi_name);
+ namelen);
break;
case SMB_INFO_QUERY_EA_SIZE:
if (args->fa_fflag & SMB_FIND_RETURN_RESUME_KEYS)
(void) smb_mbc_encodef(&xa->rep_data_mb, "l",
- fileinfo->fi_cookie);
+ resume_key);
- /*
- * Unicode filename should NOT be aligned. Encode ('u')
- * into a temporary buffer, then encode buffer as a
- * byte stream ('#c').
- * Regardless of whether unicode or ascii, a single
- * termination byte is used.
- */
- buflen = namelen + sizeof (smb_wchar_t);
- tmpbuf = kmem_zalloc(buflen, KM_SLEEP);
- smb_msgbuf_init(&mb, (uint8_t *)tmpbuf, buflen, mb_flags);
- if (smb_msgbuf_encode(&mb, "u", fileinfo->fi_name) < 0) {
- smb_msgbuf_term(&mb);
- kmem_free(tmpbuf, buflen);
- return (-1);
- }
- tmpbuf[namelen] = '\0';
-
- (void) smb_mbc_encodef(&xa->rep_data_mb, "%yyyllwlb#c", sr,
+ (void) smb_mbc_encodef(&xa->rep_data_mb, "%yyyllwlb", sr,
smb_time_gmt_to_local(sr, fileinfo->fi_crtime.tv_sec),
smb_time_gmt_to_local(sr, fileinfo->fi_atime.tv_sec),
smb_time_gmt_to_local(sr, fileinfo->fi_mtime.tv_sec),
@@ -713,18 +777,13 @@ smb_trans2_find_mbc_encode(smb_request_t *sr, smb_xa_t *xa,
asize32,
fileinfo->fi_dosattr,
0L, /* EA Size */
- namelen,
- namelen + 1,
- tmpbuf);
-
- smb_msgbuf_term(&mb);
- kmem_free(tmpbuf, buflen);
+ namelen);
break;
case SMB_FIND_FILE_DIRECTORY_INFO:
- (void) smb_mbc_encodef(&xa->rep_data_mb, "%llTTTTqqllu", sr,
+ (void) smb_mbc_encodef(&xa->rep_data_mb, "%llTTTTqqll", sr,
next_entry_offset,
- fileinfo->fi_cookie,
+ resume_key,
&fileinfo->fi_crtime,
&fileinfo->fi_atime,
&fileinfo->fi_mtime,
@@ -732,14 +791,13 @@ smb_trans2_find_mbc_encode(smb_request_t *sr, smb_xa_t *xa,
fileinfo->fi_size,
fileinfo->fi_alloc_size,
fileinfo->fi_dosattr,
- namelen,
- fileinfo->fi_name);
+ namelen);
break;
case SMB_FIND_FILE_FULL_DIRECTORY_INFO:
- (void) smb_mbc_encodef(&xa->rep_data_mb, "%llTTTTqqlllu", sr,
+ (void) smb_mbc_encodef(&xa->rep_data_mb, "%llTTTTqqlll", sr,
next_entry_offset,
- fileinfo->fi_cookie,
+ resume_key,
&fileinfo->fi_crtime,
&fileinfo->fi_atime,
&fileinfo->fi_mtime,
@@ -748,14 +806,13 @@ smb_trans2_find_mbc_encode(smb_request_t *sr, smb_xa_t *xa,
fileinfo->fi_alloc_size,
fileinfo->fi_dosattr,
namelen,
- 0L,
- fileinfo->fi_name);
+ 0L);
break;
case SMB_FIND_FILE_ID_FULL_DIRECTORY_INFO:
- (void) smb_mbc_encodef(&xa->rep_data_mb, "%llTTTTqqlll4.qu", sr,
+ (void) smb_mbc_encodef(&xa->rep_data_mb, "%llTTTTqqlll4.q", sr,
next_entry_offset,
- fileinfo->fi_cookie,
+ resume_key,
&fileinfo->fi_crtime,
&fileinfo->fi_atime,
&fileinfo->fi_mtime,
@@ -765,8 +822,7 @@ smb_trans2_find_mbc_encode(smb_request_t *sr, smb_xa_t *xa,
fileinfo->fi_dosattr,
namelen,
0L,
- fileinfo->fi_nodeid,
- fileinfo->fi_name);
+ fileinfo->fi_nodeid);
break;
case SMB_FIND_FILE_BOTH_DIRECTORY_INFO:
@@ -779,10 +835,10 @@ smb_trans2_find_mbc_encode(smb_request_t *sr, smb_xa_t *xa,
}
shortlen = smb_wcequiv_strlen(fileinfo->fi_shortname);
- (void) smb_mbc_encodef(&xa->rep_data_mb, "%llTTTTqqlllb.24cu",
+ (void) smb_mbc_encodef(&xa->rep_data_mb, "%llTTTTqqlllb.24c",
sr,
next_entry_offset,
- fileinfo->fi_cookie,
+ resume_key,
&fileinfo->fi_crtime,
&fileinfo->fi_atime,
&fileinfo->fi_mtime,
@@ -793,8 +849,7 @@ smb_trans2_find_mbc_encode(smb_request_t *sr, smb_xa_t *xa,
namelen,
0L,
shortlen,
- buf83,
- fileinfo->fi_name);
+ buf83);
smb_msgbuf_term(&mb);
break;
@@ -811,10 +866,10 @@ smb_trans2_find_mbc_encode(smb_request_t *sr, smb_xa_t *xa,
fileinfo->fi_shortname);
(void) smb_mbc_encodef(&xa->rep_data_mb,
- "%llTTTTqqlllb.24c2.qu",
+ "%llTTTTqqlllb.24c2.q",
sr,
next_entry_offset,
- fileinfo->fi_cookie,
+ resume_key,
&fileinfo->fi_crtime,
&fileinfo->fi_atime,
&fileinfo->fi_mtime,
@@ -826,21 +881,40 @@ smb_trans2_find_mbc_encode(smb_request_t *sr, smb_xa_t *xa,
0L,
shortlen,
buf83,
- fileinfo->fi_nodeid,
- fileinfo->fi_name);
+ fileinfo->fi_nodeid);
smb_msgbuf_term(&mb);
break;
case SMB_FIND_FILE_NAMES_INFO:
- (void) smb_mbc_encodef(&xa->rep_data_mb, "%lllu", sr,
+ (void) smb_mbc_encodef(&xa->rep_data_mb, "%lll", sr,
next_entry_offset,
- fileinfo->fi_cookie,
- namelen,
- fileinfo->fi_name);
+ resume_key,
+ namelen);
break;
+
+ default:
+ /* invalid info. level */
+ return (-1);
}
+ /*
+ * At this point we have written all the fixed-size data
+ * for the specified info. level, and we're about to put
+ * the file name string in the message. We may later
+ * need the offset in the trans2 data where this string
+ * is placed, so save the message position now. Note:
+ * We also need to account for the alignment padding
+ * that may precede the unicode string.
+ */
+ args->fa_lno = xa->rep_data_mb.chain_offset;
+ if ((sr->smb_flg2 & SMB_FLAGS2_UNICODE) != 0 &&
+ (args->fa_lno & 1) != 0)
+ args->fa_lno++;
+
+ (void) smb_mbc_encodef(&xa->rep_data_mb, "%u", sr,
+ fileinfo->fi_name);
+
return (0);
}
diff --git a/usr/src/uts/common/fs/smbsrv/smb_tree.c b/usr/src/uts/common/fs/smbsrv/smb_tree.c
index a31b536236..13adc2d803 100644
--- a/usr/src/uts/common/fs/smbsrv/smb_tree.c
+++ b/usr/src/uts/common/fs/smbsrv/smb_tree.c
@@ -20,8 +20,8 @@
*/
/*
- * Copyright 2011 Nexenta Systems, Inc. All rights reserved.
* Copyright (c) 2007, 2010, Oracle and/or its affiliates. All rights reserved.
+ * Copyright 2011 Nexenta Systems, Inc. All rights reserved.
*/
/*
@@ -1107,6 +1107,8 @@ smb_tree_get_volname(vfs_t *vfsp, smb_tree_t *tree)
static void
smb_tree_get_flags(const smb_kshare_t *si, vfs_t *vfsp, smb_tree_t *tree)
{
+ smb_session_t *ssn = tree->t_session;
+
typedef struct smb_mtype {
char *mt_name;
size_t mt_namelen;
@@ -1134,11 +1136,15 @@ smb_tree_get_flags(const smb_kshare_t *si, vfs_t *vfsp, smb_tree_t *tree)
if (si->shr_flags & SMB_SHRF_ABE)
flags |= SMB_TREE_ABE;
- if (smb_session_oplocks_enable(tree->t_session)) {
+ if (ssn->s_cfg.skc_oplock_enable) {
/* if 'smb' zfs property: oplocks=enabled */
flags |= SMB_TREE_OPLOCKS;
}
+ /* Global config option for now. Later make per-share. */
+ if (ssn->s_cfg.skc_traverse_mounts)
+ flags |= SMB_TREE_TRAVERSE_MOUNTS;
+
/* if 'smb' zfs property: shortnames=enabled */
if (smb_shortnames)
flags |= SMB_TREE_SHORTNAMES;
diff --git a/usr/src/uts/common/fs/specfs/specsubr.c b/usr/src/uts/common/fs/specfs/specsubr.c
index c43b4bd921..a5937dec2b 100644
--- a/usr/src/uts/common/fs/specfs/specsubr.c
+++ b/usr/src/uts/common/fs/specfs/specsubr.c
@@ -22,6 +22,9 @@
* Copyright 2009 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
+/*
+ * Copyright (c) 2012 by Delphix. All rights reserved.
+ */
/* Copyright (c) 1983, 1984, 1985, 1986, 1987, 1988, 1989 AT&T */
/* All Rights Reserved */
@@ -1059,7 +1062,7 @@ spec_size_invalidate(dev_t dev, vtype_t type)
if ((csp = sfind(dev, type, NULL)) != NULL) {
mutex_enter(&csp->s_lock);
csp->s_flag &= ~SSIZEVALID;
- VN_RELE(STOV(csp));
+ VN_RELE_ASYNC(STOV(csp), system_taskq);
mutex_exit(&csp->s_lock);
}
mutex_exit(&stable_lock);
diff --git a/usr/src/uts/common/fs/zfs/arc.c b/usr/src/uts/common/fs/zfs/arc.c
index 83e442afce..a970fe9a3e 100644
--- a/usr/src/uts/common/fs/zfs/arc.c
+++ b/usr/src/uts/common/fs/zfs/arc.c
@@ -296,6 +296,9 @@ typedef struct arc_stats {
kstat_named_t arcstat_duplicate_buffers;
kstat_named_t arcstat_duplicate_buffers_size;
kstat_named_t arcstat_duplicate_reads;
+ kstat_named_t arcstat_meta_used;
+ kstat_named_t arcstat_meta_limit;
+ kstat_named_t arcstat_meta_max;
} arc_stats_t;
static arc_stats_t arc_stats = {
@@ -354,7 +357,10 @@ static arc_stats_t arc_stats = {
{ "memory_throttle_count", KSTAT_DATA_UINT64 },
{ "duplicate_buffers", KSTAT_DATA_UINT64 },
{ "duplicate_buffers_size", KSTAT_DATA_UINT64 },
- { "duplicate_reads", KSTAT_DATA_UINT64 }
+ { "duplicate_reads", KSTAT_DATA_UINT64 },
+ { "arc_meta_used", KSTAT_DATA_UINT64 },
+ { "arc_meta_limit", KSTAT_DATA_UINT64 },
+ { "arc_meta_max", KSTAT_DATA_UINT64 }
};
#define ARCSTAT(stat) (arc_stats.stat.value.ui64)
@@ -416,13 +422,13 @@ static arc_state_t *arc_l2c_only;
#define arc_c ARCSTAT(arcstat_c) /* target size of cache */
#define arc_c_min ARCSTAT(arcstat_c_min) /* min target cache size */
#define arc_c_max ARCSTAT(arcstat_c_max) /* max target cache size */
+#define arc_meta_limit ARCSTAT(arcstat_meta_limit) /* max size for metadata */
+#define arc_meta_used ARCSTAT(arcstat_meta_used) /* size of metadata */
+#define arc_meta_max ARCSTAT(arcstat_meta_max) /* max size of metadata */
static int arc_no_grow; /* Don't try to grow cache size */
static uint64_t arc_tempreserve;
static uint64_t arc_loaned_bytes;
-static uint64_t arc_meta_used;
-static uint64_t arc_meta_limit;
-static uint64_t arc_meta_max = 0;
typedef struct l2arc_buf_hdr l2arc_buf_hdr_t;
@@ -825,7 +831,6 @@ buf_cons(void *vbuf, void *unused, int kmflag)
bzero(buf, sizeof (arc_buf_t));
mutex_init(&buf->b_evict_lock, NULL, MUTEX_DEFAULT, NULL);
- rw_init(&buf->b_data_lock, NULL, RW_DEFAULT, NULL);
arc_space_consume(sizeof (arc_buf_t), ARC_SPACE_HDRS);
return (0);
@@ -855,7 +860,6 @@ buf_dest(void *vbuf, void *unused)
arc_buf_t *buf = vbuf;
mutex_destroy(&buf->b_evict_lock);
- rw_destroy(&buf->b_data_lock);
arc_space_return(sizeof (arc_buf_t), ARC_SPACE_HDRS);
}
@@ -1222,7 +1226,7 @@ arc_space_consume(uint64_t space, arc_space_type_t type)
break;
}
- atomic_add_64(&arc_meta_used, space);
+ ARCSTAT_INCR(arcstat_meta_used, space);
atomic_add_64(&arc_size, space);
}
@@ -1249,7 +1253,7 @@ arc_space_return(uint64_t space, arc_space_type_t type)
ASSERT(arc_meta_used >= space);
if (arc_meta_max < arc_meta_used)
arc_meta_max = arc_meta_used;
- atomic_add_64(&arc_meta_used, -space);
+ ARCSTAT_INCR(arcstat_meta_used, -space);
ASSERT(arc_size >= space);
atomic_add_64(&arc_size, -space);
}
@@ -2791,45 +2795,14 @@ arc_read_done(zio_t *zio)
*
* arc_read_done() will invoke all the requested "done" functions
* for readers of this block.
- *
- * Normal callers should use arc_read and pass the arc buffer and offset
- * for the bp. But if you know you don't need locking, you can use
- * arc_read_bp.
*/
int
-arc_read(zio_t *pio, spa_t *spa, const blkptr_t *bp, arc_buf_t *pbuf,
- arc_done_func_t *done, void *private, int priority, int zio_flags,
- uint32_t *arc_flags, const zbookmark_t *zb)
-{
- int err;
-
- if (pbuf == NULL) {
- /*
- * XXX This happens from traverse callback funcs, for
- * the objset_phys_t block.
- */
- return (arc_read_nolock(pio, spa, bp, done, private, priority,
- zio_flags, arc_flags, zb));
- }
-
- ASSERT(!refcount_is_zero(&pbuf->b_hdr->b_refcnt));
- ASSERT3U((char *)bp - (char *)pbuf->b_data, <, pbuf->b_hdr->b_size);
- rw_enter(&pbuf->b_data_lock, RW_READER);
-
- err = arc_read_nolock(pio, spa, bp, done, private, priority,
- zio_flags, arc_flags, zb);
- rw_exit(&pbuf->b_data_lock);
-
- return (err);
-}
-
-int
-arc_read_nolock(zio_t *pio, spa_t *spa, const blkptr_t *bp,
- arc_done_func_t *done, void *private, int priority, int zio_flags,
- uint32_t *arc_flags, const zbookmark_t *zb)
+arc_read(zio_t *pio, spa_t *spa, const blkptr_t *bp, arc_done_func_t *done,
+ void *private, int priority, int zio_flags, uint32_t *arc_flags,
+ const zbookmark_t *zb)
{
arc_buf_hdr_t *hdr;
- arc_buf_t *buf;
+ arc_buf_t *buf = NULL;
kmutex_t *hash_lock;
zio_t *rzio;
uint64_t guid = spa_load_guid(spa);
@@ -2911,7 +2884,7 @@ top:
uint64_t size = BP_GET_LSIZE(bp);
arc_callback_t *acb;
vdev_t *vd = NULL;
- uint64_t addr;
+ uint64_t addr = 0;
boolean_t devw = B_FALSE;
if (hdr == NULL) {
@@ -3026,6 +2999,10 @@ top:
cb->l2rcb_zb = *zb;
cb->l2rcb_flags = zio_flags;
+ ASSERT(addr >= VDEV_LABEL_START_SIZE &&
+ addr + size < vd->vdev_psize -
+ VDEV_LABEL_END_SIZE);
+
/*
* l2arc read. The SCL_L2ARC lock will be
* released by l2arc_read_done().
@@ -3225,8 +3202,8 @@ arc_release(arc_buf_t *buf, void *tag)
if (l2hdr) {
mutex_enter(&l2arc_buflist_mtx);
hdr->b_l2hdr = NULL;
- buf_size = hdr->b_size;
}
+ buf_size = hdr->b_size;
/*
* Do we have more than one buf?
@@ -3314,19 +3291,6 @@ arc_release(arc_buf_t *buf, void *tag)
}
}
-/*
- * Release this buffer. If it does not match the provided BP, fill it
- * with that block's contents.
- */
-/* ARGSUSED */
-int
-arc_release_bp(arc_buf_t *buf, void *tag, blkptr_t *bp, spa_t *spa,
- zbookmark_t *zb)
-{
- arc_release(buf, tag);
- return (0);
-}
-
int
arc_released(arc_buf_t *buf)
{
@@ -4235,7 +4199,7 @@ l2arc_read_done(zio_t *zio)
static list_t *
l2arc_list_locked(int list_num, kmutex_t **lock)
{
- list_t *list;
+ list_t *list = NULL;
ASSERT(list_num >= 0 && list_num <= 3);
diff --git a/usr/src/uts/common/fs/zfs/bptree.c b/usr/src/uts/common/fs/zfs/bptree.c
index 1a009cfe57..73922db88b 100644
--- a/usr/src/uts/common/fs/zfs/bptree.c
+++ b/usr/src/uts/common/fs/zfs/bptree.c
@@ -135,7 +135,7 @@ bptree_add(objset_t *os, uint64_t obj, blkptr_t *bp, uint64_t birth_txg,
/* ARGSUSED */
static int
-bptree_visit_cb(spa_t *spa, zilog_t *zilog, const blkptr_t *bp, arc_buf_t *pbuf,
+bptree_visit_cb(spa_t *spa, zilog_t *zilog, const blkptr_t *bp,
const zbookmark_t *zb, const dnode_phys_t *dnp, void *arg)
{
int err;
diff --git a/usr/src/uts/common/fs/zfs/dbuf.c b/usr/src/uts/common/fs/zfs/dbuf.c
index 63be8bc21e..b225a8c6d0 100644
--- a/usr/src/uts/common/fs/zfs/dbuf.c
+++ b/usr/src/uts/common/fs/zfs/dbuf.c
@@ -514,7 +514,6 @@ dbuf_read_impl(dmu_buf_impl_t *db, zio_t *zio, uint32_t *flags)
spa_t *spa;
zbookmark_t zb;
uint32_t aflags = ARC_NOWAIT;
- arc_buf_t *pbuf;
DB_DNODE_ENTER(db);
dn = DB_DNODE(db);
@@ -587,14 +586,8 @@ dbuf_read_impl(dmu_buf_impl_t *db, zio_t *zio, uint32_t *flags)
db->db.db_object, db->db_level, db->db_blkid);
dbuf_add_ref(db, NULL);
- /* ZIO_FLAG_CANFAIL callers have to check the parent zio's error */
- if (db->db_parent)
- pbuf = db->db_parent->db_buf;
- else
- pbuf = db->db_objset->os_phys_buf;
-
- (void) dsl_read(zio, spa, db->db_blkptr, pbuf,
+ (void) arc_read(zio, spa, db->db_blkptr,
dbuf_read_done, db, ZIO_PRIORITY_SYNC_READ,
(*flags & DB_RF_CANFAIL) ? ZIO_FLAG_CANFAIL : ZIO_FLAG_MUSTSUCCEED,
&aflags, &zb);
@@ -994,7 +987,6 @@ void
dbuf_release_bp(dmu_buf_impl_t *db)
{
objset_t *os;
- zbookmark_t zb;
DB_GET_OBJSET(&os, db);
ASSERT(dsl_pool_sync_context(dmu_objset_pool(os)));
@@ -1002,13 +994,7 @@ dbuf_release_bp(dmu_buf_impl_t *db)
list_link_active(&os->os_dsl_dataset->ds_synced_link));
ASSERT(db->db_parent == NULL || arc_released(db->db_parent->db_buf));
- zb.zb_objset = os->os_dsl_dataset ?
- os->os_dsl_dataset->ds_object : 0;
- zb.zb_object = db->db.db_object;
- zb.zb_level = db->db_level;
- zb.zb_blkid = db->db_blkid;
- (void) arc_release_bp(db->db_buf, db,
- db->db_blkptr, os->os_spa, &zb);
+ (void) arc_release(db->db_buf, db);
}
dbuf_dirty_record_t *
@@ -1843,7 +1829,6 @@ dbuf_prefetch(dnode_t *dn, uint64_t blkid)
if (bp && !BP_IS_HOLE(bp)) {
int priority = dn->dn_type == DMU_OT_DDT_ZAP ?
ZIO_PRIORITY_DDT_PREFETCH : ZIO_PRIORITY_ASYNC_READ;
- arc_buf_t *pbuf;
dsl_dataset_t *ds = dn->dn_objset->os_dsl_dataset;
uint32_t aflags = ARC_NOWAIT | ARC_PREFETCH;
zbookmark_t zb;
@@ -1851,13 +1836,8 @@ dbuf_prefetch(dnode_t *dn, uint64_t blkid)
SET_BOOKMARK(&zb, ds ? ds->ds_object : DMU_META_OBJSET,
dn->dn_object, 0, blkid);
- if (db)
- pbuf = db->db_buf;
- else
- pbuf = dn->dn_objset->os_phys_buf;
-
- (void) dsl_read(NULL, dn->dn_objset->os_spa,
- bp, pbuf, NULL, NULL, priority,
+ (void) arc_read(NULL, dn->dn_objset->os_spa,
+ bp, NULL, NULL, priority,
ZIO_FLAG_CANFAIL | ZIO_FLAG_SPECULATIVE,
&aflags, &zb);
}
diff --git a/usr/src/uts/common/fs/zfs/dmu.c b/usr/src/uts/common/fs/zfs/dmu.c
index 48620378a8..40d72f7042 100644
--- a/usr/src/uts/common/fs/zfs/dmu.c
+++ b/usr/src/uts/common/fs/zfs/dmu.c
@@ -406,8 +406,7 @@ dmu_buf_hold_array_by_dnode(dnode_t *dn, uint64_t offset, uint64_t length,
if (dn->dn_objset->os_dsl_dataset)
dp = dn->dn_objset->os_dsl_dataset->ds_dir->dd_pool;
- if (dp && dsl_pool_sync_context(dp))
- start = gethrtime();
+ start = gethrtime();
zio = zio_root(dn->dn_objset->os_spa, NULL, NULL, ZIO_FLAG_CANFAIL);
blkid = dbuf_whichblock(dn, offset);
for (i = 0; i < nblks; i++) {
diff --git a/usr/src/uts/common/fs/zfs/dmu_diff.c b/usr/src/uts/common/fs/zfs/dmu_diff.c
index 22340ebc53..dc237780c0 100644
--- a/usr/src/uts/common/fs/zfs/dmu_diff.c
+++ b/usr/src/uts/common/fs/zfs/dmu_diff.c
@@ -105,7 +105,7 @@ report_dnode(struct diffarg *da, uint64_t object, dnode_phys_t *dnp)
/* ARGSUSED */
static int
-diff_cb(spa_t *spa, zilog_t *zilog, const blkptr_t *bp, arc_buf_t *pbuf,
+diff_cb(spa_t *spa, zilog_t *zilog, const blkptr_t *bp,
const zbookmark_t *zb, const dnode_phys_t *dnp, void *arg)
{
struct diffarg *da = arg;
@@ -132,9 +132,9 @@ diff_cb(spa_t *spa, zilog_t *zilog, const blkptr_t *bp, arc_buf_t *pbuf,
int blksz = BP_GET_LSIZE(bp);
int i;
- if (dsl_read(NULL, spa, bp, pbuf,
- arc_getbuf_func, &abuf, ZIO_PRIORITY_ASYNC_READ,
- ZIO_FLAG_CANFAIL, &aflags, zb) != 0)
+ if (arc_read(NULL, spa, bp, arc_getbuf_func, &abuf,
+ ZIO_PRIORITY_ASYNC_READ, ZIO_FLAG_CANFAIL,
+ &aflags, zb) != 0)
return (EIO);
blk = abuf->b_data;
diff --git a/usr/src/uts/common/fs/zfs/dmu_objset.c b/usr/src/uts/common/fs/zfs/dmu_objset.c
index 4345b26757..1857d87311 100644
--- a/usr/src/uts/common/fs/zfs/dmu_objset.c
+++ b/usr/src/uts/common/fs/zfs/dmu_objset.c
@@ -278,12 +278,7 @@ dmu_objset_open_impl(spa_t *spa, dsl_dataset_t *ds, blkptr_t *bp,
aflags |= ARC_L2CACHE;
dprintf_bp(os->os_rootbp, "reading %s", "");
- /*
- * XXX when bprewrite scrub can change the bp,
- * and this is called from dmu_objset_open_ds_os, the bp
- * could change, and we'll need a lock.
- */
- err = dsl_read_nolock(NULL, spa, os->os_rootbp,
+ err = arc_read(NULL, spa, os->os_rootbp,
arc_getbuf_func, &os->os_phys_buf,
ZIO_PRIORITY_SYNC_READ, ZIO_FLAG_CANFAIL, &aflags, &zb);
if (err) {
@@ -1235,8 +1230,7 @@ dmu_objset_sync(objset_t *os, zio_t *pio, dmu_tx_t *tx)
SET_BOOKMARK(&zb, os->os_dsl_dataset ?
os->os_dsl_dataset->ds_object : DMU_META_OBJSET,
ZB_ROOT_OBJECT, ZB_ROOT_LEVEL, ZB_ROOT_BLKID);
- VERIFY3U(0, ==, arc_release_bp(os->os_phys_buf, &os->os_phys_buf,
- os->os_rootbp, os->os_spa, &zb));
+ arc_release(os->os_phys_buf, &os->os_phys_buf);
dmu_write_policy(os, NULL, 0, 0, &zp);
@@ -1440,7 +1434,8 @@ dmu_objset_userquota_get_ids(dnode_t *dn, boolean_t before, dmu_tx_t *tx)
objset_t *os = dn->dn_objset;
void *data = NULL;
dmu_buf_impl_t *db = NULL;
- uint64_t *user, *group;
+ uint64_t *user = NULL;
+ uint64_t *group = NULL;
int flags = dn->dn_id_flags;
int error;
boolean_t have_spill = B_FALSE;
@@ -1875,7 +1870,7 @@ dmu_objset_prefetch(const char *name, void *arg)
SET_BOOKMARK(&zb, ds->ds_object, ZB_ROOT_OBJECT,
ZB_ROOT_LEVEL, ZB_ROOT_BLKID);
- (void) dsl_read_nolock(NULL, dsl_dataset_get_spa(ds),
+ (void) arc_read(NULL, dsl_dataset_get_spa(ds),
&ds->ds_phys->ds_bp, NULL, NULL,
ZIO_PRIORITY_ASYNC_READ,
ZIO_FLAG_CANFAIL | ZIO_FLAG_SPECULATIVE,
diff --git a/usr/src/uts/common/fs/zfs/dmu_send.c b/usr/src/uts/common/fs/zfs/dmu_send.c
index b994357827..4a183ff66d 100644
--- a/usr/src/uts/common/fs/zfs/dmu_send.c
+++ b/usr/src/uts/common/fs/zfs/dmu_send.c
@@ -301,7 +301,7 @@ dump_dnode(dmu_sendarg_t *dsp, uint64_t object, dnode_phys_t *dnp)
/* ARGSUSED */
static int
-backup_cb(spa_t *spa, zilog_t *zilog, const blkptr_t *bp, arc_buf_t *pbuf,
+backup_cb(spa_t *spa, zilog_t *zilog, const blkptr_t *bp,
const zbookmark_t *zb, const dnode_phys_t *dnp, void *arg)
{
dmu_sendarg_t *dsp = arg;
@@ -330,9 +330,9 @@ backup_cb(spa_t *spa, zilog_t *zilog, const blkptr_t *bp, arc_buf_t *pbuf,
uint32_t aflags = ARC_WAIT;
arc_buf_t *abuf;
- if (dsl_read(NULL, spa, bp, pbuf,
- arc_getbuf_func, &abuf, ZIO_PRIORITY_ASYNC_READ,
- ZIO_FLAG_CANFAIL, &aflags, zb) != 0)
+ if (arc_read(NULL, spa, bp, arc_getbuf_func, &abuf,
+ ZIO_PRIORITY_ASYNC_READ, ZIO_FLAG_CANFAIL,
+ &aflags, zb) != 0)
return (EIO);
blk = abuf->b_data;
@@ -349,9 +349,9 @@ backup_cb(spa_t *spa, zilog_t *zilog, const blkptr_t *bp, arc_buf_t *pbuf,
arc_buf_t *abuf;
int blksz = BP_GET_LSIZE(bp);
- if (arc_read_nolock(NULL, spa, bp,
- arc_getbuf_func, &abuf, ZIO_PRIORITY_ASYNC_READ,
- ZIO_FLAG_CANFAIL, &aflags, zb) != 0)
+ if (arc_read(NULL, spa, bp, arc_getbuf_func, &abuf,
+ ZIO_PRIORITY_ASYNC_READ, ZIO_FLAG_CANFAIL,
+ &aflags, zb) != 0)
return (EIO);
err = dump_spill(dsp, zb->zb_object, blksz, abuf->b_data);
@@ -361,9 +361,9 @@ backup_cb(spa_t *spa, zilog_t *zilog, const blkptr_t *bp, arc_buf_t *pbuf,
arc_buf_t *abuf;
int blksz = BP_GET_LSIZE(bp);
- if (dsl_read(NULL, spa, bp, pbuf,
- arc_getbuf_func, &abuf, ZIO_PRIORITY_ASYNC_READ,
- ZIO_FLAG_CANFAIL, &aflags, zb) != 0) {
+ if (arc_read(NULL, spa, bp, arc_getbuf_func, &abuf,
+ ZIO_PRIORITY_ASYNC_READ, ZIO_FLAG_CANFAIL,
+ &aflags, zb) != 0) {
if (zfs_send_corrupt_data) {
/* Send a block filled with 0x"zfs badd bloc" */
abuf = arc_buf_alloc(spa, blksz, &abuf,
diff --git a/usr/src/uts/common/fs/zfs/dmu_traverse.c b/usr/src/uts/common/fs/zfs/dmu_traverse.c
index 34f19cdcbb..f3d5069d47 100644
--- a/usr/src/uts/common/fs/zfs/dmu_traverse.c
+++ b/usr/src/uts/common/fs/zfs/dmu_traverse.c
@@ -62,9 +62,9 @@ typedef struct traverse_data {
} traverse_data_t;
static int traverse_dnode(traverse_data_t *td, const dnode_phys_t *dnp,
- arc_buf_t *buf, uint64_t objset, uint64_t object);
+ uint64_t objset, uint64_t object);
static void prefetch_dnode_metadata(traverse_data_t *td, const dnode_phys_t *,
- arc_buf_t *buf, uint64_t objset, uint64_t object);
+ uint64_t objset, uint64_t object);
static int
traverse_zil_block(zilog_t *zilog, blkptr_t *bp, void *arg, uint64_t claim_txg)
@@ -81,7 +81,7 @@ traverse_zil_block(zilog_t *zilog, blkptr_t *bp, void *arg, uint64_t claim_txg)
SET_BOOKMARK(&zb, td->td_objset, ZB_ZIL_OBJECT, ZB_ZIL_LEVEL,
bp->blk_cksum.zc_word[ZIL_ZC_SEQ]);
- (void) td->td_func(td->td_spa, zilog, bp, NULL, &zb, NULL, td->td_arg);
+ (void) td->td_func(td->td_spa, zilog, bp, &zb, NULL, td->td_arg);
return (0);
}
@@ -105,7 +105,7 @@ traverse_zil_record(zilog_t *zilog, lr_t *lrc, void *arg, uint64_t claim_txg)
SET_BOOKMARK(&zb, td->td_objset, lr->lr_foid,
ZB_ZIL_LEVEL, lr->lr_offset / BP_GET_LSIZE(bp));
- (void) td->td_func(td->td_spa, zilog, bp, NULL, &zb, NULL,
+ (void) td->td_func(td->td_spa, zilog, bp, &zb, NULL,
td->td_arg);
}
return (0);
@@ -182,7 +182,7 @@ traverse_pause(traverse_data_t *td, const zbookmark_t *zb)
static void
traverse_prefetch_metadata(traverse_data_t *td,
- arc_buf_t *pbuf, const blkptr_t *bp, const zbookmark_t *zb)
+ const blkptr_t *bp, const zbookmark_t *zb)
{
uint32_t flags = ARC_NOWAIT | ARC_PREFETCH;
@@ -200,14 +200,13 @@ traverse_prefetch_metadata(traverse_data_t *td,
if (BP_GET_LEVEL(bp) == 0 && BP_GET_TYPE(bp) != DMU_OT_DNODE)
return;
- (void) arc_read(NULL, td->td_spa, bp,
- pbuf, NULL, NULL, ZIO_PRIORITY_ASYNC_READ,
- ZIO_FLAG_CANFAIL, &flags, zb);
+ (void) arc_read(NULL, td->td_spa, bp, NULL, NULL,
+ ZIO_PRIORITY_ASYNC_READ, ZIO_FLAG_CANFAIL, &flags, zb);
}
static int
traverse_visitbp(traverse_data_t *td, const dnode_phys_t *dnp,
- arc_buf_t *pbuf, const blkptr_t *bp, const zbookmark_t *zb)
+ const blkptr_t *bp, const zbookmark_t *zb)
{
zbookmark_t czb;
int err = 0, lasterr = 0;
@@ -228,8 +227,7 @@ traverse_visitbp(traverse_data_t *td, const dnode_phys_t *dnp,
}
if (BP_IS_HOLE(bp)) {
- err = td->td_func(td->td_spa, NULL, NULL, pbuf, zb, dnp,
- td->td_arg);
+ err = td->td_func(td->td_spa, NULL, NULL, zb, dnp, td->td_arg);
return (err);
}
@@ -249,7 +247,7 @@ traverse_visitbp(traverse_data_t *td, const dnode_phys_t *dnp,
}
if (td->td_flags & TRAVERSE_PRE) {
- err = td->td_func(td->td_spa, NULL, bp, pbuf, zb, dnp,
+ err = td->td_func(td->td_spa, NULL, bp, zb, dnp,
td->td_arg);
if (err == TRAVERSE_VISIT_NO_CHILDREN)
return (0);
@@ -265,8 +263,7 @@ traverse_visitbp(traverse_data_t *td, const dnode_phys_t *dnp,
blkptr_t *cbp;
int epb = BP_GET_LSIZE(bp) >> SPA_BLKPTRSHIFT;
- err = dsl_read(NULL, td->td_spa, bp, pbuf,
- arc_getbuf_func, &buf,
+ err = arc_read(NULL, td->td_spa, bp, arc_getbuf_func, &buf,
ZIO_PRIORITY_ASYNC_READ, ZIO_FLAG_CANFAIL, &flags, zb);
if (err)
return (err);
@@ -276,7 +273,7 @@ traverse_visitbp(traverse_data_t *td, const dnode_phys_t *dnp,
SET_BOOKMARK(&czb, zb->zb_objset, zb->zb_object,
zb->zb_level - 1,
zb->zb_blkid * epb + i);
- traverse_prefetch_metadata(td, buf, &cbp[i], &czb);
+ traverse_prefetch_metadata(td, &cbp[i], &czb);
}
/* recursively visitbp() blocks below this */
@@ -284,7 +281,7 @@ traverse_visitbp(traverse_data_t *td, const dnode_phys_t *dnp,
SET_BOOKMARK(&czb, zb->zb_objset, zb->zb_object,
zb->zb_level - 1,
zb->zb_blkid * epb + i);
- err = traverse_visitbp(td, dnp, buf, &cbp[i], &czb);
+ err = traverse_visitbp(td, dnp, &cbp[i], &czb);
if (err) {
if (!hard)
break;
@@ -296,21 +293,20 @@ traverse_visitbp(traverse_data_t *td, const dnode_phys_t *dnp,
int i;
int epb = BP_GET_LSIZE(bp) >> DNODE_SHIFT;
- err = dsl_read(NULL, td->td_spa, bp, pbuf,
- arc_getbuf_func, &buf,
+ err = arc_read(NULL, td->td_spa, bp, arc_getbuf_func, &buf,
ZIO_PRIORITY_ASYNC_READ, ZIO_FLAG_CANFAIL, &flags, zb);
if (err)
return (err);
dnp = buf->b_data;
for (i = 0; i < epb; i++) {
- prefetch_dnode_metadata(td, &dnp[i], buf, zb->zb_objset,
+ prefetch_dnode_metadata(td, &dnp[i], zb->zb_objset,
zb->zb_blkid * epb + i);
}
/* recursively visitbp() blocks below this */
for (i = 0; i < epb; i++) {
- err = traverse_dnode(td, &dnp[i], buf, zb->zb_objset,
+ err = traverse_dnode(td, &dnp[i], zb->zb_objset,
zb->zb_blkid * epb + i);
if (err) {
if (!hard)
@@ -323,24 +319,23 @@ traverse_visitbp(traverse_data_t *td, const dnode_phys_t *dnp,
objset_phys_t *osp;
dnode_phys_t *dnp;
- err = dsl_read_nolock(NULL, td->td_spa, bp,
- arc_getbuf_func, &buf,
+ err = arc_read(NULL, td->td_spa, bp, arc_getbuf_func, &buf,
ZIO_PRIORITY_ASYNC_READ, ZIO_FLAG_CANFAIL, &flags, zb);
if (err)
return (err);
osp = buf->b_data;
dnp = &osp->os_meta_dnode;
- prefetch_dnode_metadata(td, dnp, buf, zb->zb_objset,
+ prefetch_dnode_metadata(td, dnp, zb->zb_objset,
DMU_META_DNODE_OBJECT);
if (arc_buf_size(buf) >= sizeof (objset_phys_t)) {
prefetch_dnode_metadata(td, &osp->os_userused_dnode,
- buf, zb->zb_objset, DMU_USERUSED_OBJECT);
+ zb->zb_objset, DMU_USERUSED_OBJECT);
prefetch_dnode_metadata(td, &osp->os_groupused_dnode,
- buf, zb->zb_objset, DMU_USERUSED_OBJECT);
+ zb->zb_objset, DMU_USERUSED_OBJECT);
}
- err = traverse_dnode(td, dnp, buf, zb->zb_objset,
+ err = traverse_dnode(td, dnp, zb->zb_objset,
DMU_META_DNODE_OBJECT);
if (err && hard) {
lasterr = err;
@@ -348,7 +343,7 @@ traverse_visitbp(traverse_data_t *td, const dnode_phys_t *dnp,
}
if (err == 0 && arc_buf_size(buf) >= sizeof (objset_phys_t)) {
dnp = &osp->os_userused_dnode;
- err = traverse_dnode(td, dnp, buf, zb->zb_objset,
+ err = traverse_dnode(td, dnp, zb->zb_objset,
DMU_USERUSED_OBJECT);
}
if (err && hard) {
@@ -357,7 +352,7 @@ traverse_visitbp(traverse_data_t *td, const dnode_phys_t *dnp,
}
if (err == 0 && arc_buf_size(buf) >= sizeof (objset_phys_t)) {
dnp = &osp->os_groupused_dnode;
- err = traverse_dnode(td, dnp, buf, zb->zb_objset,
+ err = traverse_dnode(td, dnp, zb->zb_objset,
DMU_GROUPUSED_OBJECT);
}
}
@@ -367,8 +362,7 @@ traverse_visitbp(traverse_data_t *td, const dnode_phys_t *dnp,
post:
if (err == 0 && lasterr == 0 && (td->td_flags & TRAVERSE_POST)) {
- err = td->td_func(td->td_spa, NULL, bp, pbuf, zb, dnp,
- td->td_arg);
+ err = td->td_func(td->td_spa, NULL, bp, zb, dnp, td->td_arg);
if (err == ERESTART)
pause = B_TRUE;
}
@@ -384,25 +378,25 @@ post:
static void
prefetch_dnode_metadata(traverse_data_t *td, const dnode_phys_t *dnp,
- arc_buf_t *buf, uint64_t objset, uint64_t object)
+ uint64_t objset, uint64_t object)
{
int j;
zbookmark_t czb;
for (j = 0; j < dnp->dn_nblkptr; j++) {
SET_BOOKMARK(&czb, objset, object, dnp->dn_nlevels - 1, j);
- traverse_prefetch_metadata(td, buf, &dnp->dn_blkptr[j], &czb);
+ traverse_prefetch_metadata(td, &dnp->dn_blkptr[j], &czb);
}
if (dnp->dn_flags & DNODE_FLAG_SPILL_BLKPTR) {
SET_BOOKMARK(&czb, objset, object, 0, DMU_SPILL_BLKID);
- traverse_prefetch_metadata(td, buf, &dnp->dn_spill, &czb);
+ traverse_prefetch_metadata(td, &dnp->dn_spill, &czb);
}
}
static int
traverse_dnode(traverse_data_t *td, const dnode_phys_t *dnp,
- arc_buf_t *buf, uint64_t objset, uint64_t object)
+ uint64_t objset, uint64_t object)
{
int j, err = 0, lasterr = 0;
zbookmark_t czb;
@@ -410,7 +404,7 @@ traverse_dnode(traverse_data_t *td, const dnode_phys_t *dnp,
for (j = 0; j < dnp->dn_nblkptr; j++) {
SET_BOOKMARK(&czb, objset, object, dnp->dn_nlevels - 1, j);
- err = traverse_visitbp(td, dnp, buf, &dnp->dn_blkptr[j], &czb);
+ err = traverse_visitbp(td, dnp, &dnp->dn_blkptr[j], &czb);
if (err) {
if (!hard)
break;
@@ -420,7 +414,7 @@ traverse_dnode(traverse_data_t *td, const dnode_phys_t *dnp,
if (dnp->dn_flags & DNODE_FLAG_SPILL_BLKPTR) {
SET_BOOKMARK(&czb, objset, object, 0, DMU_SPILL_BLKID);
- err = traverse_visitbp(td, dnp, buf, &dnp->dn_spill, &czb);
+ err = traverse_visitbp(td, dnp, &dnp->dn_spill, &czb);
if (err) {
if (!hard)
return (err);
@@ -433,8 +427,7 @@ traverse_dnode(traverse_data_t *td, const dnode_phys_t *dnp,
/* ARGSUSED */
static int
traverse_prefetcher(spa_t *spa, zilog_t *zilog, const blkptr_t *bp,
- arc_buf_t *pbuf, const zbookmark_t *zb, const dnode_phys_t *dnp,
- void *arg)
+ const zbookmark_t *zb, const dnode_phys_t *dnp, void *arg)
{
prefetch_data_t *pfd = arg;
uint32_t aflags = ARC_NOWAIT | ARC_PREFETCH;
@@ -455,10 +448,8 @@ traverse_prefetcher(spa_t *spa, zilog_t *zilog, const blkptr_t *bp,
cv_broadcast(&pfd->pd_cv);
mutex_exit(&pfd->pd_mtx);
- (void) dsl_read(NULL, spa, bp, pbuf, NULL, NULL,
- ZIO_PRIORITY_ASYNC_READ,
- ZIO_FLAG_CANFAIL | ZIO_FLAG_SPECULATIVE,
- &aflags, zb);
+ (void) arc_read(NULL, spa, bp, NULL, NULL, ZIO_PRIORITY_ASYNC_READ,
+ ZIO_FLAG_CANFAIL | ZIO_FLAG_SPECULATIVE, &aflags, zb);
return (0);
}
@@ -476,7 +467,7 @@ traverse_prefetch_thread(void *arg)
SET_BOOKMARK(&czb, td.td_objset,
ZB_ROOT_OBJECT, ZB_ROOT_LEVEL, ZB_ROOT_BLKID);
- (void) traverse_visitbp(&td, NULL, NULL, td.td_rootbp, &czb);
+ (void) traverse_visitbp(&td, NULL, td.td_rootbp, &czb);
mutex_enter(&td_main->td_pfd->pd_mtx);
td_main->td_pfd->pd_exited = B_TRUE;
@@ -540,7 +531,7 @@ traverse_impl(spa_t *spa, dsl_dataset_t *ds, uint64_t objset, blkptr_t *rootbp,
SET_BOOKMARK(&czb, td.td_objset,
ZB_ROOT_OBJECT, ZB_ROOT_LEVEL, ZB_ROOT_BLKID);
- err = traverse_visitbp(&td, NULL, NULL, rootbp, &czb);
+ err = traverse_visitbp(&td, NULL, rootbp, &czb);
mutex_enter(&pd.pd_mtx);
pd.pd_cancel = B_TRUE;
diff --git a/usr/src/uts/common/fs/zfs/dsl_dataset.c b/usr/src/uts/common/fs/zfs/dsl_dataset.c
index 4de580b784..96ed1f3fb4 100644
--- a/usr/src/uts/common/fs/zfs/dsl_dataset.c
+++ b/usr/src/uts/common/fs/zfs/dsl_dataset.c
@@ -381,7 +381,7 @@ dsl_dataset_get_ref(dsl_pool_t *dp, uint64_t dsobj, void *tag,
ds = dmu_buf_get_user(dbuf);
if (ds == NULL) {
- dsl_dataset_t *winner;
+ dsl_dataset_t *winner = NULL;
ds = kmem_zalloc(sizeof (dsl_dataset_t), KM_SLEEP);
ds->ds_dbuf = dbuf;
@@ -466,11 +466,8 @@ dsl_dataset_get_ref(dsl_pool_t *dp, uint64_t dsobj, void *tag,
ds->ds_reserved = ds->ds_quota = 0;
}
- if (err == 0) {
- winner = dmu_buf_set_user_ie(dbuf, ds, &ds->ds_phys,
- dsl_dataset_evict);
- }
- if (err || winner) {
+ if (err != 0 || (winner = dmu_buf_set_user_ie(dbuf, ds,
+ &ds->ds_phys, dsl_dataset_evict)) != NULL) {
bplist_destroy(&ds->ds_pending_deadlist);
dsl_deadlist_close(&ds->ds_deadlist);
if (ds->ds_prev)
@@ -1266,7 +1263,7 @@ struct killarg {
/* ARGSUSED */
static int
-kill_blkptr(spa_t *spa, zilog_t *zilog, const blkptr_t *bp, arc_buf_t *pbuf,
+kill_blkptr(spa_t *spa, zilog_t *zilog, const blkptr_t *bp,
const zbookmark_t *zb, const dnode_phys_t *dnp, void *arg)
{
struct killarg *ka = arg;
diff --git a/usr/src/uts/common/fs/zfs/dsl_scan.c b/usr/src/uts/common/fs/zfs/dsl_scan.c
index 8f08f04a06..e171725799 100644
--- a/usr/src/uts/common/fs/zfs/dsl_scan.c
+++ b/usr/src/uts/common/fs/zfs/dsl_scan.c
@@ -366,24 +366,6 @@ dsl_free_sync(zio_t *pio, dsl_pool_t *dp, uint64_t txg, const blkptr_t *bpp)
zio_nowait(zio_free_sync(pio, dp->dp_spa, txg, bpp, pio->io_flags));
}
-int
-dsl_read(zio_t *pio, spa_t *spa, const blkptr_t *bpp, arc_buf_t *pbuf,
- arc_done_func_t *done, void *private, int priority, int zio_flags,
- uint32_t *arc_flags, const zbookmark_t *zb)
-{
- return (arc_read(pio, spa, bpp, pbuf, done, private,
- priority, zio_flags, arc_flags, zb));
-}
-
-int
-dsl_read_nolock(zio_t *pio, spa_t *spa, const blkptr_t *bpp,
- arc_done_func_t *done, void *private, int priority, int zio_flags,
- uint32_t *arc_flags, const zbookmark_t *zb)
-{
- return (arc_read_nolock(pio, spa, bpp, done, private,
- priority, zio_flags, arc_flags, zb));
-}
-
static uint64_t
dsl_scan_ds_maxtxg(dsl_dataset_t *ds)
{
@@ -554,12 +536,8 @@ dsl_scan_prefetch(dsl_scan_t *scn, arc_buf_t *buf, blkptr_t *bp,
SET_BOOKMARK(&czb, objset, object, BP_GET_LEVEL(bp), blkid);
- /*
- * XXX need to make sure all of these arc_read() prefetches are
- * done before setting xlateall (similar to dsl_read())
- */
(void) arc_read(scn->scn_zio_root, scn->scn_dp->dp_spa, bp,
- buf, NULL, NULL, ZIO_PRIORITY_ASYNC_READ,
+ NULL, NULL, ZIO_PRIORITY_ASYNC_READ,
ZIO_FLAG_CANFAIL | ZIO_FLAG_SCAN_THREAD, &flags, &czb);
}
@@ -617,8 +595,7 @@ dsl_scan_recurse(dsl_scan_t *scn, dsl_dataset_t *ds, dmu_objset_type_t ostype,
blkptr_t *cbp;
int epb = BP_GET_LSIZE(bp) >> SPA_BLKPTRSHIFT;
- err = arc_read_nolock(NULL, dp->dp_spa, bp,
- arc_getbuf_func, bufp,
+ err = arc_read(NULL, dp->dp_spa, bp, arc_getbuf_func, bufp,
ZIO_PRIORITY_ASYNC_READ, zio_flags, &flags, zb);
if (err) {
scn->scn_phys.scn_errors++;
@@ -640,8 +617,7 @@ dsl_scan_recurse(dsl_scan_t *scn, dsl_dataset_t *ds, dmu_objset_type_t ostype,
} else if (BP_GET_TYPE(bp) == DMU_OT_USERGROUP_USED) {
uint32_t flags = ARC_WAIT;
- err = arc_read_nolock(NULL, dp->dp_spa, bp,
- arc_getbuf_func, bufp,
+ err = arc_read(NULL, dp->dp_spa, bp, arc_getbuf_func, bufp,
ZIO_PRIORITY_ASYNC_READ, zio_flags, &flags, zb);
if (err) {
scn->scn_phys.scn_errors++;
@@ -653,8 +629,7 @@ dsl_scan_recurse(dsl_scan_t *scn, dsl_dataset_t *ds, dmu_objset_type_t ostype,
int i, j;
int epb = BP_GET_LSIZE(bp) >> DNODE_SHIFT;
- err = arc_read_nolock(NULL, dp->dp_spa, bp,
- arc_getbuf_func, bufp,
+ err = arc_read(NULL, dp->dp_spa, bp, arc_getbuf_func, bufp,
ZIO_PRIORITY_ASYNC_READ, zio_flags, &flags, zb);
if (err) {
scn->scn_phys.scn_errors++;
@@ -676,8 +651,7 @@ dsl_scan_recurse(dsl_scan_t *scn, dsl_dataset_t *ds, dmu_objset_type_t ostype,
uint32_t flags = ARC_WAIT;
objset_phys_t *osp;
- err = arc_read_nolock(NULL, dp->dp_spa, bp,
- arc_getbuf_func, bufp,
+ err = arc_read(NULL, dp->dp_spa, bp, arc_getbuf_func, bufp,
ZIO_PRIORITY_ASYNC_READ, zio_flags, &flags, zb);
if (err) {
scn->scn_phys.scn_errors++;
@@ -1653,7 +1627,8 @@ dsl_scan_scrub_cb(dsl_pool_t *dp,
zio_priority = ZIO_PRIORITY_SCRUB;
needs_io = B_TRUE;
scan_delay = zfs_scrub_delay;
- } else if (scn->scn_phys.scn_func == POOL_SCAN_RESILVER) {
+ } else {
+ ASSERT3U(scn->scn_phys.scn_func, ==, POOL_SCAN_RESILVER);
zio_flags |= ZIO_FLAG_RESILVER;
zio_priority = ZIO_PRIORITY_RESILVER;
needs_io = B_FALSE;
diff --git a/usr/src/uts/common/fs/zfs/lzjb.c b/usr/src/uts/common/fs/zfs/lzjb.c
index ab3de51b72..a938fee7a3 100644
--- a/usr/src/uts/common/fs/zfs/lzjb.c
+++ b/usr/src/uts/common/fs/zfs/lzjb.c
@@ -37,6 +37,7 @@
*/
#include <sys/types.h>
+#include <sys/param.h>
#define MATCH_BITS 6
#define MATCH_MIN 3
@@ -50,7 +51,8 @@ lzjb_compress(void *s_start, void *d_start, size_t s_len, size_t d_len, int n)
{
uchar_t *src = s_start;
uchar_t *dst = d_start;
- uchar_t *cpy, *copymap;
+ uchar_t *cpy;
+ uchar_t *copymap = NULL;
int copymask = 1 << (NBBY - 1);
int mlen, offset, hash;
uint16_t *hp;
@@ -99,7 +101,8 @@ lzjb_decompress(void *s_start, void *d_start, size_t s_len, size_t d_len, int n)
uchar_t *src = s_start;
uchar_t *dst = d_start;
uchar_t *d_end = (uchar_t *)d_start + d_len;
- uchar_t *cpy, copymap;
+ uchar_t *cpy;
+ uchar_t copymap = 0;
int copymask = 1 << (NBBY - 1);
while (dst < d_end) {
diff --git a/usr/src/uts/common/fs/zfs/metaslab.c b/usr/src/uts/common/fs/zfs/metaslab.c
index 6449788c1c..76c66a00a3 100644
--- a/usr/src/uts/common/fs/zfs/metaslab.c
+++ b/usr/src/uts/common/fs/zfs/metaslab.c
@@ -21,6 +21,7 @@
/*
* Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2012 by Delphix. All rights reserved.
+ * Copyright (c) 2013 by Saso Kiselkov. All rights reserved.
*/
#include <sys/zfs_context.h>
@@ -47,6 +48,14 @@ uint64_t metaslab_aliquot = 512ULL << 10;
uint64_t metaslab_gang_bang = SPA_MAXBLOCKSIZE + 1; /* force gang blocks */
/*
+ * The in-core space map representation is more compact than its on-disk form.
+ * The zfs_condense_pct determines how much more compact the in-core
+ * space_map representation must be before we compact it on-disk.
+ * Values should be greater than or equal to 100.
+ */
+int zfs_condense_pct = 200;
+
+/*
* This value defines the number of allowed allocation failures per vdev.
* If a device reaches this threshold in a given txg then we consider skipping
* allocations on that device.
@@ -91,6 +100,11 @@ int metaslab_prefetch_limit = SPA_DVAS_PER_BP;
int metaslab_smo_bonus_pct = 150;
/*
+ * Should we be willing to write data to degraded vdevs?
+ */
+boolean_t zfs_write_to_degraded = B_FALSE;
+
+/*
* ==========================================================================
* Metaslab classes
* ==========================================================================
@@ -200,9 +214,9 @@ metaslab_compare(const void *x1, const void *x2)
/*
* If the weights are identical, use the offset to force uniqueness.
*/
- if (m1->ms_map.sm_start < m2->ms_map.sm_start)
+ if (m1->ms_map->sm_start < m2->ms_map->sm_start)
return (-1);
- if (m1->ms_map.sm_start > m2->ms_map.sm_start)
+ if (m1->ms_map->sm_start > m2->ms_map->sm_start)
return (1);
ASSERT3P(m1, ==, m2);
@@ -717,14 +731,15 @@ metaslab_init(metaslab_group_t *mg, space_map_obj_t *smo,
* addition of new space; and for debugging, it ensures that we'd
* data fault on any attempt to use this metaslab before it's ready.
*/
- space_map_create(&msp->ms_map, start, size,
+ msp->ms_map = kmem_zalloc(sizeof (space_map_t), KM_SLEEP);
+ space_map_create(msp->ms_map, start, size,
vd->vdev_ashift, &msp->ms_lock);
metaslab_group_add(mg, msp);
if (metaslab_debug && smo->smo_object != 0) {
mutex_enter(&msp->ms_lock);
- VERIFY(space_map_load(&msp->ms_map, mg->mg_class->mc_ops,
+ VERIFY(space_map_load(msp->ms_map, mg->mg_class->mc_ops,
SM_FREE, smo, spa_meta_objset(vd->vdev_spa)) == 0);
mutex_exit(&msp->ms_lock);
}
@@ -752,22 +767,27 @@ metaslab_fini(metaslab_t *msp)
metaslab_group_t *mg = msp->ms_group;
vdev_space_update(mg->mg_vd,
- -msp->ms_smo.smo_alloc, 0, -msp->ms_map.sm_size);
+ -msp->ms_smo.smo_alloc, 0, -msp->ms_map->sm_size);
metaslab_group_remove(mg, msp);
mutex_enter(&msp->ms_lock);
- space_map_unload(&msp->ms_map);
- space_map_destroy(&msp->ms_map);
+ space_map_unload(msp->ms_map);
+ space_map_destroy(msp->ms_map);
+ kmem_free(msp->ms_map, sizeof (*msp->ms_map));
for (int t = 0; t < TXG_SIZE; t++) {
- space_map_destroy(&msp->ms_allocmap[t]);
- space_map_destroy(&msp->ms_freemap[t]);
+ space_map_destroy(msp->ms_allocmap[t]);
+ space_map_destroy(msp->ms_freemap[t]);
+ kmem_free(msp->ms_allocmap[t], sizeof (*msp->ms_allocmap[t]));
+ kmem_free(msp->ms_freemap[t], sizeof (*msp->ms_freemap[t]));
}
- for (int t = 0; t < TXG_DEFER_SIZE; t++)
- space_map_destroy(&msp->ms_defermap[t]);
+ for (int t = 0; t < TXG_DEFER_SIZE; t++) {
+ space_map_destroy(msp->ms_defermap[t]);
+ kmem_free(msp->ms_defermap[t], sizeof (*msp->ms_defermap[t]));
+ }
ASSERT0(msp->ms_deferspace);
@@ -786,7 +806,7 @@ static uint64_t
metaslab_weight(metaslab_t *msp)
{
metaslab_group_t *mg = msp->ms_group;
- space_map_t *sm = &msp->ms_map;
+ space_map_t *sm = msp->ms_map;
space_map_obj_t *smo = &msp->ms_smo;
vdev_t *vd = mg->mg_vd;
uint64_t weight, space;
@@ -794,6 +814,16 @@ metaslab_weight(metaslab_t *msp)
ASSERT(MUTEX_HELD(&msp->ms_lock));
/*
+ * This vdev is in the process of being removed so there is nothing
+ * for us to do here.
+ */
+ if (vd->vdev_removing) {
+ ASSERT0(smo->smo_alloc);
+ ASSERT0(vd->vdev_ms_shift);
+ return (0);
+ }
+
+ /*
* The baseline weight is the metaslab's free space.
*/
space = sm->sm_size - smo->smo_alloc;
@@ -846,7 +876,7 @@ metaslab_prefetch(metaslab_group_t *mg)
* Prefetch the next potential metaslabs
*/
for (msp = avl_first(t), m = 0; msp; msp = AVL_NEXT(t, msp), m++) {
- space_map_t *sm = &msp->ms_map;
+ space_map_t *sm = msp->ms_map;
space_map_obj_t *smo = &msp->ms_smo;
/* If we have reached our prefetch limit then we're done */
@@ -867,7 +897,7 @@ static int
metaslab_activate(metaslab_t *msp, uint64_t activation_weight)
{
metaslab_group_t *mg = msp->ms_group;
- space_map_t *sm = &msp->ms_map;
+ space_map_t *sm = msp->ms_map;
space_map_ops_t *sm_ops = msp->ms_group->mg_class->mc_ops;
ASSERT(MUTEX_HELD(&msp->ms_lock));
@@ -884,7 +914,7 @@ metaslab_activate(metaslab_t *msp, uint64_t activation_weight)
return (error);
}
for (int t = 0; t < TXG_DEFER_SIZE; t++)
- space_map_walk(&msp->ms_defermap[t],
+ space_map_walk(msp->ms_defermap[t],
space_map_claim, sm);
}
@@ -915,12 +945,158 @@ metaslab_passivate(metaslab_t *msp, uint64_t size)
* this metaslab again. In that case, it had better be empty,
* or we would be leaving space on the table.
*/
- ASSERT(size >= SPA_MINBLOCKSIZE || msp->ms_map.sm_space == 0);
+ ASSERT(size >= SPA_MINBLOCKSIZE || msp->ms_map->sm_space == 0);
metaslab_group_sort(msp->ms_group, msp, MIN(msp->ms_weight, size));
ASSERT((msp->ms_weight & METASLAB_ACTIVE_MASK) == 0);
}
/*
+ * Determine if the in-core space map representation can be condensed on-disk.
+ * We would like to use the following criteria to make our decision:
+ *
+ * 1. The size of the space map object should not dramatically increase as a
+ * result of writing out our in-core free map.
+ *
+ * 2. The minimal on-disk space map representation is zfs_condense_pct/100
+ * times the size than the in-core representation (i.e. zfs_condense_pct = 110
+ * and in-core = 1MB, minimal = 1.1.MB).
+ *
+ * Checking the first condition is tricky since we don't want to walk
+ * the entire AVL tree calculating the estimated on-disk size. Instead we
+ * use the size-ordered AVL tree in the space map and calculate the
+ * size required for the largest segment in our in-core free map. If the
+ * size required to represent that segment on disk is larger than the space
+ * map object then we avoid condensing this map.
+ *
+ * To determine the second criterion we use a best-case estimate and assume
+ * each segment can be represented on-disk as a single 64-bit entry. We refer
+ * to this best-case estimate as the space map's minimal form.
+ */
+static boolean_t
+metaslab_should_condense(metaslab_t *msp)
+{
+ space_map_t *sm = msp->ms_map;
+ space_map_obj_t *smo = &msp->ms_smo_syncing;
+ space_seg_t *ss;
+ uint64_t size, entries, segsz;
+
+ ASSERT(MUTEX_HELD(&msp->ms_lock));
+ ASSERT(sm->sm_loaded);
+
+ /*
+ * Use the sm_pp_root AVL tree, which is ordered by size, to obtain
+ * the largest segment in the in-core free map. If the tree is
+ * empty then we should condense the map.
+ */
+ ss = avl_last(sm->sm_pp_root);
+ if (ss == NULL)
+ return (B_TRUE);
+
+ /*
+ * Calculate the number of 64-bit entries this segment would
+ * require when written to disk. If this single segment would be
+ * larger on-disk than the entire current on-disk structure, then
+ * clearly condensing will increase the on-disk structure size.
+ */
+ size = (ss->ss_end - ss->ss_start) >> sm->sm_shift;
+ entries = size / (MIN(size, SM_RUN_MAX));
+ segsz = entries * sizeof (uint64_t);
+
+ return (segsz <= smo->smo_objsize &&
+ smo->smo_objsize >= (zfs_condense_pct *
+ sizeof (uint64_t) * avl_numnodes(&sm->sm_root)) / 100);
+}
+
+/*
+ * Condense the on-disk space map representation to its minimized form.
+ * The minimized form consists of a small number of allocations followed by
+ * the in-core free map.
+ */
+static void
+metaslab_condense(metaslab_t *msp, uint64_t txg, dmu_tx_t *tx)
+{
+ spa_t *spa = msp->ms_group->mg_vd->vdev_spa;
+ space_map_t *freemap = msp->ms_freemap[txg & TXG_MASK];
+ space_map_t condense_map;
+ space_map_t *sm = msp->ms_map;
+ objset_t *mos = spa_meta_objset(spa);
+ space_map_obj_t *smo = &msp->ms_smo_syncing;
+
+ ASSERT(MUTEX_HELD(&msp->ms_lock));
+ ASSERT3U(spa_sync_pass(spa), ==, 1);
+ ASSERT(sm->sm_loaded);
+
+ spa_dbgmsg(spa, "condensing: txg %llu, msp[%llu] %p, "
+ "smo size %llu, segments %lu", txg,
+ (msp->ms_map->sm_start / msp->ms_map->sm_size), msp,
+ smo->smo_objsize, avl_numnodes(&sm->sm_root));
+
+ /*
+ * Create an map that is a 100% allocated map. We remove segments
+ * that have been freed in this txg, any deferred frees that exist,
+ * and any allocation in the future. Removing segments should be
+ * a relatively inexpensive operation since we expect these maps to
+ * a small number of nodes.
+ */
+ space_map_create(&condense_map, sm->sm_start, sm->sm_size,
+ sm->sm_shift, sm->sm_lock);
+ space_map_add(&condense_map, condense_map.sm_start,
+ condense_map.sm_size);
+
+ /*
+ * Remove what's been freed in this txg from the condense_map.
+ * Since we're in sync_pass 1, we know that all the frees from
+ * this txg are in the freemap.
+ */
+ space_map_walk(freemap, space_map_remove, &condense_map);
+
+ for (int t = 0; t < TXG_DEFER_SIZE; t++)
+ space_map_walk(msp->ms_defermap[t],
+ space_map_remove, &condense_map);
+
+ for (int t = 1; t < TXG_CONCURRENT_STATES; t++)
+ space_map_walk(msp->ms_allocmap[(txg + t) & TXG_MASK],
+ space_map_remove, &condense_map);
+
+ /*
+ * We're about to drop the metaslab's lock thus allowing
+ * other consumers to change it's content. Set the
+ * space_map's sm_condensing flag to ensure that
+ * allocations on this metaslab do not occur while we're
+ * in the middle of committing it to disk. This is only critical
+ * for the ms_map as all other space_maps use per txg
+ * views of their content.
+ */
+ sm->sm_condensing = B_TRUE;
+
+ mutex_exit(&msp->ms_lock);
+ space_map_truncate(smo, mos, tx);
+ mutex_enter(&msp->ms_lock);
+
+ /*
+ * While we would ideally like to create a space_map representation
+ * that consists only of allocation records, doing so can be
+ * prohibitively expensive because the in-core free map can be
+ * large, and therefore computationally expensive to subtract
+ * from the condense_map. Instead we sync out two maps, a cheap
+ * allocation only map followed by the in-core free map. While not
+ * optimal, this is typically close to optimal, and much cheaper to
+ * compute.
+ */
+ space_map_sync(&condense_map, SM_ALLOC, smo, mos, tx);
+ space_map_vacate(&condense_map, NULL, NULL);
+ space_map_destroy(&condense_map);
+
+ space_map_sync(sm, SM_FREE, smo, mos, tx);
+ sm->sm_condensing = B_FALSE;
+
+ spa_dbgmsg(spa, "condensed: txg %llu, msp[%llu] %p, "
+ "smo size %llu", txg,
+ (msp->ms_map->sm_start / msp->ms_map->sm_size), msp,
+ smo->smo_objsize);
+}
+
+/*
* Write a metaslab to disk in the context of the specified transaction group.
*/
void
@@ -929,17 +1105,29 @@ metaslab_sync(metaslab_t *msp, uint64_t txg)
vdev_t *vd = msp->ms_group->mg_vd;
spa_t *spa = vd->vdev_spa;
objset_t *mos = spa_meta_objset(spa);
- space_map_t *allocmap = &msp->ms_allocmap[txg & TXG_MASK];
- space_map_t *freemap = &msp->ms_freemap[txg & TXG_MASK];
- space_map_t *freed_map = &msp->ms_freemap[TXG_CLEAN(txg) & TXG_MASK];
- space_map_t *sm = &msp->ms_map;
+ space_map_t *allocmap = msp->ms_allocmap[txg & TXG_MASK];
+ space_map_t **freemap = &msp->ms_freemap[txg & TXG_MASK];
+ space_map_t **freed_map = &msp->ms_freemap[TXG_CLEAN(txg) & TXG_MASK];
+ space_map_t *sm = msp->ms_map;
space_map_obj_t *smo = &msp->ms_smo_syncing;
dmu_buf_t *db;
dmu_tx_t *tx;
ASSERT(!vd->vdev_ishole);
- if (allocmap->sm_space == 0 && freemap->sm_space == 0)
+ /*
+ * This metaslab has just been added so there's no work to do now.
+ */
+ if (*freemap == NULL) {
+ ASSERT3P(allocmap, ==, NULL);
+ return;
+ }
+
+ ASSERT3P(allocmap, !=, NULL);
+ ASSERT3P(*freemap, !=, NULL);
+ ASSERT3P(*freed_map, !=, NULL);
+
+ if (allocmap->sm_space == 0 && (*freemap)->sm_space == 0)
return;
/*
@@ -967,49 +1155,36 @@ metaslab_sync(metaslab_t *msp, uint64_t txg)
mutex_enter(&msp->ms_lock);
- space_map_walk(freemap, space_map_add, freed_map);
-
- if (sm->sm_loaded && spa_sync_pass(spa) == 1 && smo->smo_objsize >=
- 2 * sizeof (uint64_t) * avl_numnodes(&sm->sm_root)) {
- /*
- * The in-core space map representation is twice as compact
- * as the on-disk one, so it's time to condense the latter
- * by generating a pure allocmap from first principles.
- *
- * This metaslab is 100% allocated,
- * minus the content of the in-core map (sm),
- * minus what's been freed this txg (freed_map),
- * minus deferred frees (ms_defermap[]),
- * minus allocations from txgs in the future
- * (because they haven't been committed yet).
- */
- space_map_vacate(allocmap, NULL, NULL);
- space_map_vacate(freemap, NULL, NULL);
-
- space_map_add(allocmap, allocmap->sm_start, allocmap->sm_size);
-
- space_map_walk(sm, space_map_remove, allocmap);
- space_map_walk(freed_map, space_map_remove, allocmap);
-
- for (int t = 0; t < TXG_DEFER_SIZE; t++)
- space_map_walk(&msp->ms_defermap[t],
- space_map_remove, allocmap);
+ if (sm->sm_loaded && spa_sync_pass(spa) == 1 &&
+ metaslab_should_condense(msp)) {
+ metaslab_condense(msp, txg, tx);
+ } else {
+ space_map_sync(allocmap, SM_ALLOC, smo, mos, tx);
+ space_map_sync(*freemap, SM_FREE, smo, mos, tx);
+ }
- for (int t = 1; t < TXG_CONCURRENT_STATES; t++)
- space_map_walk(&msp->ms_allocmap[(txg + t) & TXG_MASK],
- space_map_remove, allocmap);
+ space_map_vacate(allocmap, NULL, NULL);
- mutex_exit(&msp->ms_lock);
- space_map_truncate(smo, mos, tx);
- mutex_enter(&msp->ms_lock);
+ /*
+ * For sync pass 1, we avoid walking the entire space map and
+ * instead will just swap the pointers for freemap and
+ * freed_map. We can safely do this since the freed_map is
+ * guaranteed to be empty on the initial pass.
+ */
+ if (spa_sync_pass(spa) == 1) {
+ ASSERT0((*freed_map)->sm_space);
+ ASSERT0(avl_numnodes(&(*freed_map)->sm_root));
+ space_map_swap(freemap, freed_map);
+ } else {
+ space_map_vacate(*freemap, space_map_add, *freed_map);
}
- space_map_sync(allocmap, SM_ALLOC, smo, mos, tx);
- space_map_sync(freemap, SM_FREE, smo, mos, tx);
+ ASSERT0(msp->ms_allocmap[txg & TXG_MASK]->sm_space);
+ ASSERT0(msp->ms_freemap[txg & TXG_MASK]->sm_space);
mutex_exit(&msp->ms_lock);
- VERIFY(0 == dmu_bonus_hold(mos, smo->smo_object, FTAG, &db));
+ VERIFY0(dmu_bonus_hold(mos, smo->smo_object, FTAG, &db));
dmu_buf_will_dirty(db, tx);
ASSERT3U(db->db_size, >=, sizeof (*smo));
bcopy(smo, db->db_data, sizeof (*smo));
@@ -1027,9 +1202,9 @@ metaslab_sync_done(metaslab_t *msp, uint64_t txg)
{
space_map_obj_t *smo = &msp->ms_smo;
space_map_obj_t *smosync = &msp->ms_smo_syncing;
- space_map_t *sm = &msp->ms_map;
- space_map_t *freed_map = &msp->ms_freemap[TXG_CLEAN(txg) & TXG_MASK];
- space_map_t *defer_map = &msp->ms_defermap[txg % TXG_DEFER_SIZE];
+ space_map_t *sm = msp->ms_map;
+ space_map_t **freed_map = &msp->ms_freemap[TXG_CLEAN(txg) & TXG_MASK];
+ space_map_t **defer_map = &msp->ms_defermap[txg % TXG_DEFER_SIZE];
metaslab_group_t *mg = msp->ms_group;
vdev_t *vd = mg->mg_vd;
int64_t alloc_delta, defer_delta;
@@ -1040,40 +1215,57 @@ metaslab_sync_done(metaslab_t *msp, uint64_t txg)
/*
* If this metaslab is just becoming available, initialize its
- * allocmaps and freemaps and add its capacity to the vdev.
+ * allocmaps, freemaps, and defermap and add its capacity to the vdev.
*/
- if (freed_map->sm_size == 0) {
+ if (*freed_map == NULL) {
+ ASSERT(*defer_map == NULL);
for (int t = 0; t < TXG_SIZE; t++) {
- space_map_create(&msp->ms_allocmap[t], sm->sm_start,
+ msp->ms_allocmap[t] = kmem_zalloc(sizeof (space_map_t),
+ KM_SLEEP);
+ space_map_create(msp->ms_allocmap[t], sm->sm_start,
sm->sm_size, sm->sm_shift, sm->sm_lock);
- space_map_create(&msp->ms_freemap[t], sm->sm_start,
+ msp->ms_freemap[t] = kmem_zalloc(sizeof (space_map_t),
+ KM_SLEEP);
+ space_map_create(msp->ms_freemap[t], sm->sm_start,
sm->sm_size, sm->sm_shift, sm->sm_lock);
}
- for (int t = 0; t < TXG_DEFER_SIZE; t++)
- space_map_create(&msp->ms_defermap[t], sm->sm_start,
+ for (int t = 0; t < TXG_DEFER_SIZE; t++) {
+ msp->ms_defermap[t] = kmem_zalloc(sizeof (space_map_t),
+ KM_SLEEP);
+ space_map_create(msp->ms_defermap[t], sm->sm_start,
sm->sm_size, sm->sm_shift, sm->sm_lock);
+ }
+
+ freed_map = &msp->ms_freemap[TXG_CLEAN(txg) & TXG_MASK];
+ defer_map = &msp->ms_defermap[txg % TXG_DEFER_SIZE];
vdev_space_update(vd, 0, 0, sm->sm_size);
}
alloc_delta = smosync->smo_alloc - smo->smo_alloc;
- defer_delta = freed_map->sm_space - defer_map->sm_space;
+ defer_delta = (*freed_map)->sm_space - (*defer_map)->sm_space;
vdev_space_update(vd, alloc_delta + defer_delta, defer_delta, 0);
- ASSERT(msp->ms_allocmap[txg & TXG_MASK].sm_space == 0);
- ASSERT(msp->ms_freemap[txg & TXG_MASK].sm_space == 0);
+ ASSERT(msp->ms_allocmap[txg & TXG_MASK]->sm_space == 0);
+ ASSERT(msp->ms_freemap[txg & TXG_MASK]->sm_space == 0);
/*
* If there's a space_map_load() in progress, wait for it to complete
* so that we have a consistent view of the in-core space map.
- * Then, add defer_map (oldest deferred frees) to this map and
- * transfer freed_map (this txg's frees) to defer_map.
*/
space_map_load_wait(sm);
- space_map_vacate(defer_map, sm->sm_loaded ? space_map_free : NULL, sm);
- space_map_vacate(freed_map, space_map_add, defer_map);
+
+ /*
+ * Move the frees from the defer_map to this map (if it's loaded).
+ * Swap the freed_map and the defer_map -- this is safe to do
+ * because we've just emptied out the defer_map.
+ */
+ space_map_vacate(*defer_map, sm->sm_loaded ? space_map_free : NULL, sm);
+ ASSERT0((*defer_map)->sm_space);
+ ASSERT0(avl_numnodes(&(*defer_map)->sm_root));
+ space_map_swap(freed_map, defer_map);
*smo = *smosync;
@@ -1097,7 +1289,7 @@ metaslab_sync_done(metaslab_t *msp, uint64_t txg)
int evictable = 1;
for (int t = 1; t < TXG_CONCURRENT_STATES; t++)
- if (msp->ms_allocmap[(txg + t) & TXG_MASK].sm_space)
+ if (msp->ms_allocmap[(txg + t) & TXG_MASK]->sm_space)
evictable = 0;
if (evictable && !metaslab_debug)
@@ -1122,7 +1314,7 @@ metaslab_sync_reassess(metaslab_group_t *mg)
for (int m = 0; m < vd->vdev_ms_count; m++) {
metaslab_t *msp = vd->vdev_ms[m];
- if (msp->ms_map.sm_start > mg->mg_bonus_area)
+ if (msp->ms_map->sm_start > mg->mg_bonus_area)
break;
mutex_enter(&msp->ms_lock);
@@ -1143,7 +1335,7 @@ metaslab_distance(metaslab_t *msp, dva_t *dva)
{
uint64_t ms_shift = msp->ms_group->mg_vd->vdev_ms_shift;
uint64_t offset = DVA_GET_OFFSET(dva) >> ms_shift;
- uint64_t start = msp->ms_map.sm_start >> ms_shift;
+ uint64_t start = msp->ms_map->sm_start >> ms_shift;
if (msp->ms_group->mg_vd->vdev_id != DVA_GET_VDEV(dva))
return (1ULL << 63);
@@ -1231,6 +1423,16 @@ metaslab_group_alloc(metaslab_group_t *mg, uint64_t psize, uint64_t asize,
mutex_enter(&msp->ms_lock);
/*
+ * If this metaslab is currently condensing then pick again as
+ * we can't manipulate this metaslab until it's committed
+ * to disk.
+ */
+ if (msp->ms_map->sm_condensing) {
+ mutex_exit(&msp->ms_lock);
+ continue;
+ }
+
+ /*
* Ensure that the metaslab we have selected is still
* capable of handling our request. It's possible that
* another thread may have changed the weight while we
@@ -1256,20 +1458,20 @@ metaslab_group_alloc(metaslab_group_t *mg, uint64_t psize, uint64_t asize,
continue;
}
- if ((offset = space_map_alloc(&msp->ms_map, asize)) != -1ULL)
+ if ((offset = space_map_alloc(msp->ms_map, asize)) != -1ULL)
break;
atomic_inc_64(&mg->mg_alloc_failures);
- metaslab_passivate(msp, space_map_maxsize(&msp->ms_map));
+ metaslab_passivate(msp, space_map_maxsize(msp->ms_map));
mutex_exit(&msp->ms_lock);
}
- if (msp->ms_allocmap[txg & TXG_MASK].sm_space == 0)
+ if (msp->ms_allocmap[txg & TXG_MASK]->sm_space == 0)
vdev_dirty(mg->mg_vd, VDD_METASLAB, msp, txg);
- space_map_add(&msp->ms_allocmap[txg & TXG_MASK], offset, asize);
+ space_map_add(msp->ms_allocmap[txg & TXG_MASK], offset, asize);
mutex_exit(&msp->ms_lock);
@@ -1377,10 +1579,13 @@ top:
/*
* Avoid writing single-copy data to a failing vdev
+ * unless the user instructs us that it is okay.
*/
if ((vd->vdev_stat.vs_write_errors > 0 ||
vd->vdev_state < VDEV_STATE_HEALTHY) &&
- d == 0 && dshift == 3) {
+ d == 0 && dshift == 3 &&
+ !(zfs_write_to_degraded && vd->vdev_state ==
+ VDEV_STATE_DEGRADED)) {
all_zero = B_FALSE;
goto next;
}
@@ -1498,13 +1703,13 @@ metaslab_free_dva(spa_t *spa, const dva_t *dva, uint64_t txg, boolean_t now)
mutex_enter(&msp->ms_lock);
if (now) {
- space_map_remove(&msp->ms_allocmap[txg & TXG_MASK],
+ space_map_remove(msp->ms_allocmap[txg & TXG_MASK],
offset, size);
- space_map_free(&msp->ms_map, offset, size);
+ space_map_free(msp->ms_map, offset, size);
} else {
- if (msp->ms_freemap[txg & TXG_MASK].sm_space == 0)
+ if (msp->ms_freemap[txg & TXG_MASK]->sm_space == 0)
vdev_dirty(vd, VDD_METASLAB, msp, txg);
- space_map_add(&msp->ms_freemap[txg & TXG_MASK], offset, size);
+ space_map_add(msp->ms_freemap[txg & TXG_MASK], offset, size);
}
mutex_exit(&msp->ms_lock);
@@ -1539,10 +1744,10 @@ metaslab_claim_dva(spa_t *spa, const dva_t *dva, uint64_t txg)
mutex_enter(&msp->ms_lock);
- if ((txg != 0 && spa_writeable(spa)) || !msp->ms_map.sm_loaded)
+ if ((txg != 0 && spa_writeable(spa)) || !msp->ms_map->sm_loaded)
error = metaslab_activate(msp, METASLAB_WEIGHT_SECONDARY);
- if (error == 0 && !space_map_contains(&msp->ms_map, offset, size))
+ if (error == 0 && !space_map_contains(msp->ms_map, offset, size))
error = ENOENT;
if (error || txg == 0) { /* txg == 0 indicates dry run */
@@ -1550,12 +1755,12 @@ metaslab_claim_dva(spa_t *spa, const dva_t *dva, uint64_t txg)
return (error);
}
- space_map_claim(&msp->ms_map, offset, size);
+ space_map_claim(msp->ms_map, offset, size);
if (spa_writeable(spa)) { /* don't dirty if we're zdb(1M) */
- if (msp->ms_allocmap[txg & TXG_MASK].sm_space == 0)
+ if (msp->ms_allocmap[txg & TXG_MASK]->sm_space == 0)
vdev_dirty(vd, VDD_METASLAB, msp, txg);
- space_map_add(&msp->ms_allocmap[txg & TXG_MASK], offset, size);
+ space_map_add(msp->ms_allocmap[txg & TXG_MASK], offset, size);
}
mutex_exit(&msp->ms_lock);
diff --git a/usr/src/uts/common/fs/zfs/refcount.c b/usr/src/uts/common/fs/zfs/refcount.c
index 600132f080..3a8e144e90 100644
--- a/usr/src/uts/common/fs/zfs/refcount.c
+++ b/usr/src/uts/common/fs/zfs/refcount.c
@@ -110,7 +110,7 @@ refcount_count(refcount_t *rc)
int64_t
refcount_add_many(refcount_t *rc, uint64_t number, void *holder)
{
- reference_t *ref;
+ reference_t *ref = NULL;
int64_t count;
if (reference_tracking_enable) {
diff --git a/usr/src/uts/common/fs/zfs/sa.c b/usr/src/uts/common/fs/zfs/sa.c
index 06607d784e..cd3a58b5fa 100644
--- a/usr/src/uts/common/fs/zfs/sa.c
+++ b/usr/src/uts/common/fs/zfs/sa.c
@@ -553,6 +553,7 @@ sa_find_sizes(sa_os_t *sa, sa_bulk_attr_t *attr_desc, int attr_count,
{
int var_size = 0;
int i;
+ int j = -1;
int full_space;
int hdrsize;
boolean_t done = B_FALSE;
@@ -574,10 +575,12 @@ sa_find_sizes(sa_os_t *sa, sa_bulk_attr_t *attr_desc, int attr_count,
sizeof (sa_hdr_phys_t);
full_space = (buftype == SA_BONUS) ? DN_MAX_BONUSLEN : db->db_size;
+ ASSERT(IS_P2ALIGNED(full_space, 8));
for (i = 0; i != attr_count; i++) {
boolean_t is_var_sz;
+ *total = P2ROUNDUP(*total, 8);
*total += attr_desc[i].sa_length;
if (done)
goto next;
@@ -590,7 +593,14 @@ sa_find_sizes(sa_os_t *sa, sa_bulk_attr_t *attr_desc, int attr_count,
if (is_var_sz && var_size > 1) {
if (P2ROUNDUP(hdrsize + sizeof (uint16_t), 8) +
*total < full_space) {
+ /*
+ * Account for header space used by array of
+ * optional sizes of variable-length attributes.
+ * Record the index in case this increase needs
+ * to be reversed due to spill-over.
+ */
hdrsize += sizeof (uint16_t);
+ j = i;
} else {
done = B_TRUE;
*index = i;
@@ -619,6 +629,14 @@ next:
*will_spill = B_TRUE;
}
+ /*
+ * j holds the index of the last variable-sized attribute for
+ * which hdrsize was increased. Reverse the increase if that
+ * attribute will be relocated to the spill block.
+ */
+ if (*will_spill && j == *index)
+ hdrsize -= sizeof (uint16_t);
+
hdrsize = P2ROUNDUP(hdrsize, 8);
return (hdrsize);
}
@@ -642,7 +660,8 @@ sa_build_layouts(sa_handle_t *hdl, sa_bulk_attr_t *attr_desc, int attr_count,
int buf_space;
sa_attr_type_t *attrs, *attrs_start;
int i, lot_count;
- int hdrsize, spillhdrsize;
+ int hdrsize;
+ int spillhdrsize = 0;
int used;
dmu_object_type_t bonustype;
sa_lot_t *lot;
@@ -709,12 +728,15 @@ sa_build_layouts(sa_handle_t *hdl, sa_bulk_attr_t *attr_desc, int attr_count,
for (i = 0, len_idx = 0, hash = -1ULL; i != attr_count; i++) {
uint16_t length;
+ ASSERT(IS_P2ALIGNED(data_start, 8));
+ ASSERT(IS_P2ALIGNED(buf_space, 8));
attrs[i] = attr_desc[i].sa_attr;
length = SA_REGISTERED_LEN(sa, attrs[i]);
if (length == 0)
length = attr_desc[i].sa_length;
if (buf_space < length) { /* switch to spill buffer */
+ VERIFY(spilling);
VERIFY(bonustype == DMU_OT_SA);
if (buftype == SA_BONUS && !sa->sa_force_spill) {
sa_find_layout(hdl->sa_os, hash, attrs_start,
@@ -813,7 +835,7 @@ sa_attr_table_setup(objset_t *os, sa_attr_reg_t *reg_attrs, int count)
{
sa_os_t *sa = os->os_sa;
uint64_t sa_attr_count = 0;
- uint64_t sa_reg_count;
+ uint64_t sa_reg_count = 0;
int error = 0;
uint64_t attr_value;
sa_attr_table_t *tb;
@@ -1618,7 +1640,8 @@ sa_modify_attrs(sa_handle_t *hdl, sa_attr_type_t newattr,
sa_bulk_attr_t *attr_desc;
void *old_data[2];
int bonus_attr_count = 0;
- int bonus_data_size, spill_data_size;
+ int bonus_data_size = 0;
+ int spill_data_size = 0;
int spill_attr_count = 0;
int error;
uint16_t length;
diff --git a/usr/src/uts/common/fs/zfs/spa.c b/usr/src/uts/common/fs/zfs/spa.c
index 4988b500b1..fb68e91eed 100644
--- a/usr/src/uts/common/fs/zfs/spa.c
+++ b/usr/src/uts/common/fs/zfs/spa.c
@@ -374,7 +374,7 @@ spa_prop_validate(spa_t *spa, nvlist_t *props)
{
nvpair_t *elem;
int error = 0, reset_bootfs = 0;
- uint64_t objnum;
+ uint64_t objnum = 0;
boolean_t has_feature = B_FALSE;
elem = NULL;
@@ -715,7 +715,7 @@ spa_change_guid_sync(void *arg1, void *arg2, dmu_tx_t *tx)
vdev_config_dirty(rvd);
spa_config_exit(spa, SCL_STATE, FTAG);
- spa_history_log_internal(spa, "guid change", tx, "old=%lld new=%lld",
+ spa_history_log_internal(spa, "guid change", tx, "old=%llu new=%llu",
oldguid, *newguid);
}
@@ -1342,6 +1342,7 @@ spa_load_l2cache(spa_t *spa)
newvdevs = kmem_alloc(nl2cache * sizeof (void *), KM_SLEEP);
} else {
nl2cache = 0;
+ newvdevs = NULL;
}
oldvdevs = sav->sav_vdevs;
@@ -1732,7 +1733,7 @@ spa_load_verify_done(zio_t *zio)
/*ARGSUSED*/
static int
spa_load_verify_cb(spa_t *spa, zilog_t *zilog, const blkptr_t *bp,
- arc_buf_t *pbuf, const zbookmark_t *zb, const dnode_phys_t *dnp, void *arg)
+ const zbookmark_t *zb, const dnode_phys_t *dnp, void *arg)
{
if (bp != NULL) {
zio_t *rio = arg;
@@ -4446,7 +4447,7 @@ spa_vdev_detach(spa_t *spa, uint64_t guid, uint64_t pguid, int replace_done)
vdev_t *rvd = spa->spa_root_vdev;
vdev_t *vd, *pvd, *cvd, *tvd;
boolean_t unspare = B_FALSE;
- uint64_t unspare_guid;
+ uint64_t unspare_guid = 0;
char *vdpath;
ASSERT(spa_writeable(spa));
diff --git a/usr/src/uts/common/fs/zfs/spa_misc.c b/usr/src/uts/common/fs/zfs/spa_misc.c
index 0e2d0efda3..405d93c6ce 100644
--- a/usr/src/uts/common/fs/zfs/spa_misc.c
+++ b/usr/src/uts/common/fs/zfs/spa_misc.c
@@ -480,6 +480,7 @@ spa_add(const char *name, nvlist_t *config, const char *altroot)
mutex_init(&spa->spa_scrub_lock, NULL, MUTEX_DEFAULT, NULL);
mutex_init(&spa->spa_suspend_lock, NULL, MUTEX_DEFAULT, NULL);
mutex_init(&spa->spa_vdev_top_lock, NULL, MUTEX_DEFAULT, NULL);
+ mutex_init(&spa->spa_iokstat_lock, NULL, MUTEX_DEFAULT, NULL);
cv_init(&spa->spa_async_cv, NULL, CV_DEFAULT, NULL);
cv_init(&spa->spa_proc_cv, NULL, CV_DEFAULT, NULL);
@@ -559,6 +560,13 @@ spa_add(const char *name, nvlist_t *config, const char *altroot)
KM_SLEEP) == 0);
}
+ spa->spa_iokstat = kstat_create("zfs", 0, name,
+ "disk", KSTAT_TYPE_IO, 1, 0);
+ if (spa->spa_iokstat) {
+ spa->spa_iokstat->ks_lock = &spa->spa_iokstat_lock;
+ kstat_install(spa->spa_iokstat);
+ }
+
return (spa);
}
@@ -608,6 +616,9 @@ spa_remove(spa_t *spa)
spa_config_lock_destroy(spa);
+ kstat_delete(spa->spa_iokstat);
+ spa->spa_iokstat = NULL;
+
for (int t = 0; t < TXG_SIZE; t++)
bplist_destroy(&spa->spa_free_bplist[t]);
@@ -625,6 +636,7 @@ spa_remove(spa_t *spa)
mutex_destroy(&spa->spa_scrub_lock);
mutex_destroy(&spa->spa_suspend_lock);
mutex_destroy(&spa->spa_vdev_top_lock);
+ mutex_destroy(&spa->spa_iokstat_lock);
kmem_free(spa, sizeof (spa_t));
}
diff --git a/usr/src/uts/common/fs/zfs/space_map.c b/usr/src/uts/common/fs/zfs/space_map.c
index 17dd860eac..30a35c85da 100644
--- a/usr/src/uts/common/fs/zfs/space_map.c
+++ b/usr/src/uts/common/fs/zfs/space_map.c
@@ -107,6 +107,7 @@ space_map_add(space_map_t *sm, uint64_t start, uint64_t size)
int merge_before, merge_after;
ASSERT(MUTEX_HELD(sm->sm_lock));
+ VERIFY(!sm->sm_condensing);
VERIFY(size != 0);
VERIFY3U(start, >=, sm->sm_start);
VERIFY3U(end, <=, sm->sm_start + sm->sm_size);
@@ -175,6 +176,7 @@ space_map_remove(space_map_t *sm, uint64_t start, uint64_t size)
int left_over, right_over;
ASSERT(MUTEX_HELD(sm->sm_lock));
+ VERIFY(!sm->sm_condensing);
VERIFY(size != 0);
VERIFY(P2PHASE(start, 1ULL << sm->sm_shift) == 0);
VERIFY(P2PHASE(size, 1ULL << sm->sm_shift) == 0);
@@ -244,6 +246,20 @@ space_map_contains(space_map_t *sm, uint64_t start, uint64_t size)
}
void
+space_map_swap(space_map_t **msrc, space_map_t **mdst)
+{
+ space_map_t *sm;
+
+ ASSERT(MUTEX_HELD((*msrc)->sm_lock));
+ ASSERT0((*mdst)->sm_space);
+ ASSERT0(avl_numnodes(&(*mdst)->sm_root));
+
+ sm = *msrc;
+ *msrc = *mdst;
+ *mdst = sm;
+}
+
+void
space_map_vacate(space_map_t *sm, space_map_func_t *func, space_map_t *mdest)
{
space_seg_t *ss;
@@ -424,9 +440,9 @@ space_map_sync(space_map_t *sm, uint8_t maptype,
space_map_obj_t *smo, objset_t *os, dmu_tx_t *tx)
{
spa_t *spa = dmu_objset_spa(os);
- void *cookie = NULL;
+ avl_tree_t *t = &sm->sm_root;
space_seg_t *ss;
- uint64_t bufsize, start, size, run_len, delta, sm_space;
+ uint64_t bufsize, start, size, run_len, total, sm_space, nodes;
uint64_t *entry, *entry_map, *entry_map_end;
ASSERT(MUTEX_HELD(sm->sm_lock));
@@ -455,13 +471,14 @@ space_map_sync(space_map_t *sm, uint8_t maptype,
SM_DEBUG_SYNCPASS_ENCODE(spa_sync_pass(spa)) |
SM_DEBUG_TXG_ENCODE(dmu_tx_get_txg(tx));
- delta = 0;
+ total = 0;
+ nodes = avl_numnodes(&sm->sm_root);
sm_space = sm->sm_space;
- while ((ss = avl_destroy_nodes(&sm->sm_root, &cookie)) != NULL) {
+ for (ss = avl_first(t); ss != NULL; ss = AVL_NEXT(t, ss)) {
size = ss->ss_end - ss->ss_start;
start = (ss->ss_start - sm->sm_start) >> sm->sm_shift;
- delta += size;
+ total += size;
size >>= sm->sm_shift;
while (size) {
@@ -483,7 +500,6 @@ space_map_sync(space_map_t *sm, uint8_t maptype,
start += run_len;
size -= run_len;
}
- kmem_cache_free(space_seg_cache, ss);
}
if (entry != entry_map) {
@@ -499,12 +515,11 @@ space_map_sync(space_map_t *sm, uint8_t maptype,
* Ensure that the space_map's accounting wasn't changed
* while we were in the middle of writing it out.
*/
+ VERIFY3U(nodes, ==, avl_numnodes(&sm->sm_root));
VERIFY3U(sm->sm_space, ==, sm_space);
+ VERIFY3U(sm->sm_space, ==, total);
zio_buf_free(entry_map, bufsize);
-
- sm->sm_space -= delta;
- VERIFY0(sm->sm_space);
}
void
diff --git a/usr/src/uts/common/fs/zfs/sys/arc.h b/usr/src/uts/common/fs/zfs/sys/arc.h
index b109dcafbc..916d2abf14 100644
--- a/usr/src/uts/common/fs/zfs/sys/arc.h
+++ b/usr/src/uts/common/fs/zfs/sys/arc.h
@@ -49,7 +49,6 @@ struct arc_buf {
arc_buf_hdr_t *b_hdr;
arc_buf_t *b_next;
kmutex_t b_evict_lock;
- krwlock_t b_data_lock;
void *b_data;
arc_evict_func_t *b_efunc;
void *b_private;
@@ -93,8 +92,6 @@ void arc_buf_add_ref(arc_buf_t *buf, void *tag);
int arc_buf_remove_ref(arc_buf_t *buf, void *tag);
int arc_buf_size(arc_buf_t *buf);
void arc_release(arc_buf_t *buf, void *tag);
-int arc_release_bp(arc_buf_t *buf, void *tag, blkptr_t *bp, spa_t *spa,
- zbookmark_t *zb);
int arc_released(arc_buf_t *buf);
int arc_has_callback(arc_buf_t *buf);
void arc_buf_freeze(arc_buf_t *buf);
@@ -104,10 +101,7 @@ boolean_t arc_buf_eviction_needed(arc_buf_t *buf);
int arc_referenced(arc_buf_t *buf);
#endif
-int arc_read(zio_t *pio, spa_t *spa, const blkptr_t *bp, arc_buf_t *pbuf,
- arc_done_func_t *done, void *private, int priority, int zio_flags,
- uint32_t *arc_flags, const zbookmark_t *zb);
-int arc_read_nolock(zio_t *pio, spa_t *spa, const blkptr_t *bp,
+int arc_read(zio_t *pio, spa_t *spa, const blkptr_t *bp,
arc_done_func_t *done, void *private, int priority, int flags,
uint32_t *arc_flags, const zbookmark_t *zb);
zio_t *arc_write(zio_t *pio, spa_t *spa, uint64_t txg,
diff --git a/usr/src/uts/common/fs/zfs/sys/dmu_traverse.h b/usr/src/uts/common/fs/zfs/sys/dmu_traverse.h
index 3cbf42f56a..bc1590bc3a 100644
--- a/usr/src/uts/common/fs/zfs/sys/dmu_traverse.h
+++ b/usr/src/uts/common/fs/zfs/sys/dmu_traverse.h
@@ -40,8 +40,7 @@ struct zilog;
struct arc_buf;
typedef int (blkptr_cb_t)(spa_t *spa, zilog_t *zilog, const blkptr_t *bp,
- struct arc_buf *pbuf, const zbookmark_t *zb, const struct dnode_phys *dnp,
- void *arg);
+ const zbookmark_t *zb, const struct dnode_phys *dnp, void *arg);
#define TRAVERSE_PRE (1<<0)
#define TRAVERSE_POST (1<<1)
diff --git a/usr/src/uts/common/fs/zfs/sys/dsl_pool.h b/usr/src/uts/common/fs/zfs/sys/dsl_pool.h
index f8c98edc20..ab1229a2e6 100644
--- a/usr/src/uts/common/fs/zfs/sys/dsl_pool.h
+++ b/usr/src/uts/common/fs/zfs/sys/dsl_pool.h
@@ -134,12 +134,6 @@ void dsl_pool_willuse_space(dsl_pool_t *dp, int64_t space, dmu_tx_t *tx);
void dsl_free(dsl_pool_t *dp, uint64_t txg, const blkptr_t *bpp);
void dsl_free_sync(zio_t *pio, dsl_pool_t *dp, uint64_t txg,
const blkptr_t *bpp);
-int dsl_read(zio_t *pio, spa_t *spa, const blkptr_t *bpp, arc_buf_t *pbuf,
- arc_done_func_t *done, void *private, int priority, int zio_flags,
- uint32_t *arc_flags, const zbookmark_t *zb);
-int dsl_read_nolock(zio_t *pio, spa_t *spa, const blkptr_t *bpp,
- arc_done_func_t *done, void *private, int priority, int zio_flags,
- uint32_t *arc_flags, const zbookmark_t *zb);
void dsl_pool_create_origin(dsl_pool_t *dp, dmu_tx_t *tx);
void dsl_pool_upgrade_clones(dsl_pool_t *dp, dmu_tx_t *tx);
void dsl_pool_upgrade_dir_clones(dsl_pool_t *dp, dmu_tx_t *tx);
diff --git a/usr/src/uts/common/fs/zfs/sys/metaslab_impl.h b/usr/src/uts/common/fs/zfs/sys/metaslab_impl.h
index f1f1b38eee..138e14ef59 100644
--- a/usr/src/uts/common/fs/zfs/sys/metaslab_impl.h
+++ b/usr/src/uts/common/fs/zfs/sys/metaslab_impl.h
@@ -66,20 +66,38 @@ struct metaslab_group {
};
/*
- * Each metaslab's free space is tracked in space map object in the MOS,
- * which is only updated in syncing context. Each time we sync a txg,
+ * Each metaslab maintains an in-core free map (ms_map) that contains the
+ * current list of free segments. As blocks are allocated, the allocated
+ * segment is removed from the ms_map and added to a per txg allocation map.
+ * As blocks are freed, they are added to the per txg free map. These per
+ * txg maps allow us to process all allocations and frees in syncing context
+ * where it is safe to update the on-disk space maps.
+ *
+ * Each metaslab's free space is tracked in a space map object in the MOS,
+ * which is only updated in syncing context. Each time we sync a txg,
* we append the allocs and frees from that txg to the space map object.
* When the txg is done syncing, metaslab_sync_done() updates ms_smo
- * to ms_smo_syncing. Everything in ms_smo is always safe to allocate.
+ * to ms_smo_syncing. Everything in ms_smo is always safe to allocate.
+ *
+ * To load the in-core free map we read the space map object from disk.
+ * This object contains a series of alloc and free records that are
+ * combined to make up the list of all free segments in this metaslab. These
+ * segments are represented in-core by the ms_map and are stored in an
+ * AVL tree.
+ *
+ * As the space map objects grows (as a result of the appends) it will
+ * eventually become space-inefficient. When the space map object is
+ * zfs_condense_pct/100 times the size of the minimal on-disk representation,
+ * we rewrite it in its minimized form.
*/
struct metaslab {
kmutex_t ms_lock; /* metaslab lock */
space_map_obj_t ms_smo; /* synced space map object */
space_map_obj_t ms_smo_syncing; /* syncing space map object */
- space_map_t ms_allocmap[TXG_SIZE]; /* allocated this txg */
- space_map_t ms_freemap[TXG_SIZE]; /* freed this txg */
- space_map_t ms_defermap[TXG_DEFER_SIZE]; /* deferred frees */
- space_map_t ms_map; /* in-core free space map */
+ space_map_t *ms_allocmap[TXG_SIZE]; /* allocated this txg */
+ space_map_t *ms_freemap[TXG_SIZE]; /* freed this txg */
+ space_map_t *ms_defermap[TXG_DEFER_SIZE]; /* deferred frees */
+ space_map_t *ms_map; /* in-core free space map */
int64_t ms_deferspace; /* sum of ms_defermap[] space */
uint64_t ms_weight; /* weight vs. others in group */
metaslab_group_t *ms_group; /* metaslab group */
diff --git a/usr/src/uts/common/fs/zfs/sys/refcount.h b/usr/src/uts/common/fs/zfs/sys/refcount.h
index 1752c64e3e..1dcd467f91 100644
--- a/usr/src/uts/common/fs/zfs/sys/refcount.h
+++ b/usr/src/uts/common/fs/zfs/sys/refcount.h
@@ -20,6 +20,7 @@
*/
/*
* Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2012 by Delphix. All rights reserved.
*/
#ifndef _SYS_REFCOUNT_H
@@ -52,8 +53,8 @@ typedef struct refcount {
kmutex_t rc_mtx;
list_t rc_list;
list_t rc_removed;
- int64_t rc_count;
- int64_t rc_removed_count;
+ uint64_t rc_count;
+ uint64_t rc_removed_count;
} refcount_t;
/* Note: refcount_t must be initialized with refcount_create() */
diff --git a/usr/src/uts/common/fs/zfs/sys/spa_impl.h b/usr/src/uts/common/fs/zfs/sys/spa_impl.h
index 42ce5556d3..ffd676e2ed 100644
--- a/usr/src/uts/common/fs/zfs/sys/spa_impl.h
+++ b/usr/src/uts/common/fs/zfs/sys/spa_impl.h
@@ -231,6 +231,8 @@ struct spa {
uint64_t spa_deadman_calls; /* number of deadman calls */
uint64_t spa_sync_starttime; /* starting time fo spa_sync */
uint64_t spa_deadman_synctime; /* deadman expiration timer */
+ kmutex_t spa_iokstat_lock; /* protects spa_iokstat_* */
+ struct kstat *spa_iokstat; /* kstat of io to this pool */
/*
* spa_refcnt & spa_config_lock must be the last elements
* because refcount_t changes size based on compilation options.
diff --git a/usr/src/uts/common/fs/zfs/sys/space_map.h b/usr/src/uts/common/fs/zfs/sys/space_map.h
index 463b6bb4f2..2da50fb7b3 100644
--- a/usr/src/uts/common/fs/zfs/sys/space_map.h
+++ b/usr/src/uts/common/fs/zfs/sys/space_map.h
@@ -40,17 +40,17 @@ extern "C" {
typedef struct space_map_ops space_map_ops_t;
typedef struct space_map {
- avl_tree_t sm_root; /* AVL tree of map segments */
+ avl_tree_t sm_root; /* offset-ordered segment AVL tree */
uint64_t sm_space; /* sum of all segments in the map */
uint64_t sm_start; /* start of map */
uint64_t sm_size; /* size of map */
uint8_t sm_shift; /* unit shift */
- uint8_t sm_pad[3]; /* unused */
uint8_t sm_loaded; /* map loaded? */
uint8_t sm_loading; /* map loading? */
+ uint8_t sm_condensing; /* map condensing? */
kcondvar_t sm_load_cv; /* map load completion */
space_map_ops_t *sm_ops; /* space map block picker ops vector */
- avl_tree_t *sm_pp_root; /* picker-private AVL tree */
+ avl_tree_t *sm_pp_root; /* size-ordered, picker-private tree */
void *sm_ppd; /* picker-private data */
kmutex_t *sm_lock; /* pointer to lock that protects map */
} space_map_t;
@@ -149,6 +149,7 @@ extern void space_map_add(space_map_t *sm, uint64_t start, uint64_t size);
extern void space_map_remove(space_map_t *sm, uint64_t start, uint64_t size);
extern boolean_t space_map_contains(space_map_t *sm,
uint64_t start, uint64_t size);
+extern void space_map_swap(space_map_t **msrc, space_map_t **mdest);
extern void space_map_vacate(space_map_t *sm,
space_map_func_t *func, space_map_t *mdest);
extern void space_map_walk(space_map_t *sm,
diff --git a/usr/src/uts/common/fs/zfs/sys/zvol.h b/usr/src/uts/common/fs/zfs/sys/zvol.h
index 0059bf5102..db1f05ae9c 100644
--- a/usr/src/uts/common/fs/zfs/sys/zvol.h
+++ b/usr/src/uts/common/fs/zfs/sys/zvol.h
@@ -43,7 +43,7 @@ extern void zvol_create_cb(objset_t *os, void *arg, cred_t *cr, dmu_tx_t *tx);
extern int zvol_create_minor(const char *);
extern int zvol_remove_minor(const char *);
extern void zvol_remove_minors(const char *);
-extern int zvol_set_volsize(const char *, major_t, uint64_t);
+extern int zvol_set_volsize(const char *, uint64_t);
extern int zvol_open(dev_t *devp, int flag, int otyp, cred_t *cr);
extern int zvol_dump(dev_t dev, caddr_t addr, daddr_t offset, int nblocks);
diff --git a/usr/src/uts/common/fs/zfs/vdev.c b/usr/src/uts/common/fs/zfs/vdev.c
index 4f5c4e9c4d..41f9a07524 100644
--- a/usr/src/uts/common/fs/zfs/vdev.c
+++ b/usr/src/uts/common/fs/zfs/vdev.c
@@ -1836,6 +1836,7 @@ vdev_dtl_sync(vdev_t *vd, uint64_t txg)
space_map_truncate(smo, mos, tx);
space_map_sync(&smsync, SM_ALLOC, smo, mos, tx);
+ space_map_vacate(&smsync, NULL, NULL);
space_map_destroy(&smsync);
diff --git a/usr/src/uts/common/fs/zfs/vdev_queue.c b/usr/src/uts/common/fs/zfs/vdev_queue.c
index 8dec283fee..7101cf3fd4 100644
--- a/usr/src/uts/common/fs/zfs/vdev_queue.c
+++ b/usr/src/uts/common/fs/zfs/vdev_queue.c
@@ -30,6 +30,7 @@
#include <sys/zfs_context.h>
#include <sys/vdev_impl.h>
+#include <sys/spa_impl.h>
#include <sys/zio.h>
#include <sys/avl.h>
#include <sys/zfs_zone.h>
@@ -146,17 +147,64 @@ vdev_queue_fini(vdev_t *vd)
static void
vdev_queue_io_add(vdev_queue_t *vq, zio_t *zio)
{
+ spa_t *spa = zio->io_spa;
avl_add(&vq->vq_deadline_tree, zio);
zfs_zone_zio_enqueue(zio);
avl_add(zio->io_vdev_tree, zio);
+
+ if (spa->spa_iokstat != NULL) {
+ mutex_enter(&spa->spa_iokstat_lock);
+ kstat_waitq_enter(spa->spa_iokstat->ks_data);
+ mutex_exit(&spa->spa_iokstat_lock);
+ }
}
static void
vdev_queue_io_remove(vdev_queue_t *vq, zio_t *zio)
{
+ spa_t *spa = zio->io_spa;
avl_remove(&vq->vq_deadline_tree, zio);
zfs_zone_zio_dequeue(zio);
avl_remove(zio->io_vdev_tree, zio);
+
+ if (spa->spa_iokstat != NULL) {
+ mutex_enter(&spa->spa_iokstat_lock);
+ kstat_waitq_exit(spa->spa_iokstat->ks_data);
+ mutex_exit(&spa->spa_iokstat_lock);
+ }
+}
+
+static void
+vdev_queue_pending_add(vdev_queue_t *vq, zio_t *zio)
+{
+ spa_t *spa = zio->io_spa;
+ avl_add(&vq->vq_pending_tree, zio);
+ if (spa->spa_iokstat != NULL) {
+ mutex_enter(&spa->spa_iokstat_lock);
+ kstat_runq_enter(spa->spa_iokstat->ks_data);
+ mutex_exit(&spa->spa_iokstat_lock);
+ }
+}
+
+static void
+vdev_queue_pending_remove(vdev_queue_t *vq, zio_t *zio)
+{
+ spa_t *spa = zio->io_spa;
+ avl_remove(&vq->vq_pending_tree, zio);
+ if (spa->spa_iokstat != NULL) {
+ kstat_io_t *ksio = spa->spa_iokstat->ks_data;
+
+ mutex_enter(&spa->spa_iokstat_lock);
+ kstat_runq_exit(spa->spa_iokstat->ks_data);
+ if (zio->io_type == ZIO_TYPE_READ) {
+ ksio->reads++;
+ ksio->nread += zio->io_size;
+ } else if (zio->io_type == ZIO_TYPE_WRITE) {
+ ksio->writes++;
+ ksio->nwritten += zio->io_size;
+ }
+ mutex_exit(&spa->spa_iokstat_lock);
+ }
}
static void
@@ -327,7 +375,7 @@ again:
zio_execute(dio);
} while (dio != lio);
- avl_add(&vq->vq_pending_tree, aio);
+ vdev_queue_pending_add(vq, aio);
return (aio);
}
@@ -349,7 +397,7 @@ again:
goto again;
}
- avl_add(&vq->vq_pending_tree, fio);
+ vdev_queue_pending_add(vq, fio);
return (fio);
}
@@ -405,7 +453,7 @@ vdev_queue_io_done(zio_t *zio)
mutex_enter(&vq->vq_lock);
- avl_remove(&vq->vq_pending_tree, zio);
+ vdev_queue_pending_remove(vq, zio);
vq->vq_io_complete_ts = ddi_get_lbolt64();
vq->vq_io_delta_ts = vq->vq_io_complete_ts - zio->io_timestamp;
diff --git a/usr/src/uts/common/fs/zfs/vdev_raidz.c b/usr/src/uts/common/fs/zfs/vdev_raidz.c
index 49e8610542..e6e8b15f62 100644
--- a/usr/src/uts/common/fs/zfs/vdev_raidz.c
+++ b/usr/src/uts/common/fs/zfs/vdev_raidz.c
@@ -1191,7 +1191,8 @@ vdev_raidz_matrix_reconstruct(raidz_map_t *rm, int n, int nmissing,
uint64_t ccount;
uint8_t *dst[VDEV_RAIDZ_MAXPARITY];
uint64_t dcount[VDEV_RAIDZ_MAXPARITY];
- uint8_t log, val;
+ uint8_t log = 0;
+ uint8_t val;
int ll;
uint8_t *invlog[VDEV_RAIDZ_MAXPARITY];
uint8_t *p, *pp;
diff --git a/usr/src/uts/common/fs/zfs/zap_leaf.c b/usr/src/uts/common/fs/zfs/zap_leaf.c
index 19a795db82..b867ac4074 100644
--- a/usr/src/uts/common/fs/zfs/zap_leaf.c
+++ b/usr/src/uts/common/fs/zfs/zap_leaf.c
@@ -220,7 +220,7 @@ zap_leaf_array_create(zap_leaf_t *l, const char *buf,
uint16_t chunk_head;
uint16_t *chunkp = &chunk_head;
int byten = 0;
- uint64_t value;
+ uint64_t value = 0;
int shift = (integer_size-1)*8;
int len = num_integers;
diff --git a/usr/src/uts/common/fs/zfs/zfs_byteswap.c b/usr/src/uts/common/fs/zfs/zfs_byteswap.c
index acf632bdbe..6048eb1245 100644
--- a/usr/src/uts/common/fs/zfs/zfs_byteswap.c
+++ b/usr/src/uts/common/fs/zfs/zfs_byteswap.c
@@ -51,7 +51,7 @@ zfs_ace_byteswap(void *buf, size_t size, boolean_t zfs_layout)
{
caddr_t end;
caddr_t ptr;
- zfs_ace_t *zacep;
+ zfs_ace_t *zacep = NULL;
ace_t *acep;
uint16_t entry_type;
size_t entry_size;
diff --git a/usr/src/uts/common/fs/zfs/zfs_fuid.c b/usr/src/uts/common/fs/zfs/zfs_fuid.c
index a853f4d735..6eb03c2c18 100644
--- a/usr/src/uts/common/fs/zfs/zfs_fuid.c
+++ b/usr/src/uts/common/fs/zfs/zfs_fuid.c
@@ -556,9 +556,9 @@ zfs_fuid_create(zfsvfs_t *zfsvfs, uint64_t id, cred_t *cr,
uint32_t fuid_idx = FUID_INDEX(id);
uint32_t rid;
idmap_stat status;
- uint64_t idx;
+ uint64_t idx = 0;
zfs_fuid_t *zfuid = NULL;
- zfs_fuid_info_t *fuidp;
+ zfs_fuid_info_t *fuidp = NULL;
/*
* If POSIX ID, or entry is already a FUID then
@@ -583,6 +583,9 @@ zfs_fuid_create(zfsvfs_t *zfsvfs, uint64_t id, cred_t *cr,
if (fuidp == NULL)
return (UID_NOBODY);
+ VERIFY3U(type, >=, ZFS_OWNER);
+ VERIFY3U(type, <=, ZFS_ACE_GROUP);
+
switch (type) {
case ZFS_ACE_USER:
case ZFS_ACE_GROUP:
@@ -599,7 +602,7 @@ zfs_fuid_create(zfsvfs_t *zfsvfs, uint64_t id, cred_t *cr,
idx = FUID_INDEX(fuidp->z_fuid_group);
break;
};
- domain = fuidp->z_domain_table[idx -1];
+ domain = fuidp->z_domain_table[idx - 1];
} else {
if (type == ZFS_OWNER || type == ZFS_ACE_USER)
status = kidmap_getsidbyuid(crgetzone(cr), id,
diff --git a/usr/src/uts/common/fs/zfs/zfs_ioctl.c b/usr/src/uts/common/fs/zfs/zfs_ioctl.c
index b8b5ae57a8..6172a82e99 100644
--- a/usr/src/uts/common/fs/zfs/zfs_ioctl.c
+++ b/usr/src/uts/common/fs/zfs/zfs_ioctl.c
@@ -24,8 +24,8 @@
* Portions Copyright 2011 Martin Matuska
* Copyright 2011 Nexenta Systems, Inc. All rights reserved.
* Copyright (c) 2012 by Delphix. All rights reserved.
- * Copyright (c) 2012, Joyent, Inc. All rights reserved.
* Copyright (c) 2013 by Saso Kiselkov. All rights reserved.
+ * Copyright (c) 2012, Joyent, Inc. All rights reserved.
*/
/*
@@ -978,7 +978,7 @@ static int
zfs_secpolicy_snapshot(zfs_cmd_t *zc, nvlist_t *innvl, cred_t *cr)
{
nvlist_t *snaps;
- int error;
+ int error = 0;
nvpair_t *pair;
if (nvlist_lookup_nvlist(innvl, "snaps", &snaps) != 0)
@@ -2408,8 +2408,7 @@ zfs_prop_set_special(const char *dsname, zprop_source_t source,
err = dsl_dataset_set_reservation(dsname, source, intval);
break;
case ZFS_PROP_VOLSIZE:
- err = zvol_set_volsize(dsname, ddi_driver_major(zfs_dip),
- intval);
+ err = zvol_set_volsize(dsname, intval);
break;
case ZFS_PROP_VERSION:
{
diff --git a/usr/src/uts/common/fs/zfs/zfs_log.c b/usr/src/uts/common/fs/zfs/zfs_log.c
index 26ab78279b..de786bf7f4 100644
--- a/usr/src/uts/common/fs/zfs/zfs_log.c
+++ b/usr/src/uts/common/fs/zfs/zfs_log.c
@@ -238,7 +238,7 @@ zfs_log_create(zilog_t *zilog, dmu_tx_t *tx, uint64_t txtype,
itx_t *itx;
lr_create_t *lr;
lr_acl_create_t *lracl;
- size_t aclsize;
+ size_t aclsize = (vsecp != NULL) ? vsecp->vsa_aclentsz : 0;
size_t xvatsize = 0;
size_t txsize;
xvattr_t *xvap = (xvattr_t *)vap;
@@ -268,7 +268,6 @@ zfs_log_create(zilog_t *zilog, dmu_tx_t *tx, uint64_t txtype,
txsize = sizeof (*lr) + namesize + fuidsz + xvatsize;
lrsize = sizeof (*lr);
} else {
- aclsize = (vsecp) ? vsecp->vsa_aclentsz : 0;
txsize =
sizeof (lr_acl_create_t) + namesize + fuidsz +
ZIL_ACE_LENGTH(aclsize) + xvatsize;
diff --git a/usr/src/uts/common/fs/zfs/zfs_rlock.c b/usr/src/uts/common/fs/zfs/zfs_rlock.c
index 08f88b80de..be562496b0 100644
--- a/usr/src/uts/common/fs/zfs/zfs_rlock.c
+++ b/usr/src/uts/common/fs/zfs/zfs_rlock.c
@@ -463,7 +463,7 @@ static void
zfs_range_unlock_reader(znode_t *zp, rl_t *remove)
{
avl_tree_t *tree = &zp->z_range_avl;
- rl_t *rl, *next;
+ rl_t *rl, *next = NULL;
uint64_t len;
/*
diff --git a/usr/src/uts/common/fs/zfs/zfs_vfsops.c b/usr/src/uts/common/fs/zfs/zfs_vfsops.c
index c7bfbbaec4..5e63072b32 100644
--- a/usr/src/uts/common/fs/zfs/zfs_vfsops.c
+++ b/usr/src/uts/common/fs/zfs/zfs_vfsops.c
@@ -408,12 +408,18 @@ zfs_register_callbacks(vfs_t *vfsp)
objset_t *os = NULL;
zfsvfs_t *zfsvfs = NULL;
uint64_t nbmand;
- int readonly, do_readonly = B_FALSE;
- int setuid, do_setuid = B_FALSE;
- int exec, do_exec = B_FALSE;
- int devices, do_devices = B_FALSE;
- int xattr, do_xattr = B_FALSE;
- int atime, do_atime = B_FALSE;
+ boolean_t readonly = B_FALSE;
+ boolean_t do_readonly = B_FALSE;
+ boolean_t setuid = B_FALSE;
+ boolean_t do_setuid = B_FALSE;
+ boolean_t exec = B_FALSE;
+ boolean_t do_exec = B_FALSE;
+ boolean_t devices = B_FALSE;
+ boolean_t do_devices = B_FALSE;
+ boolean_t xattr = B_FALSE;
+ boolean_t do_xattr = B_FALSE;
+ boolean_t atime = B_FALSE;
+ boolean_t do_atime = B_FALSE;
int error = 0;
ASSERT(vfsp);
diff --git a/usr/src/uts/common/fs/zfs/zfs_vnops.c b/usr/src/uts/common/fs/zfs/zfs_vnops.c
index d297dd9cca..9910800290 100644
--- a/usr/src/uts/common/fs/zfs/zfs_vnops.c
+++ b/usr/src/uts/common/fs/zfs/zfs_vnops.c
@@ -451,7 +451,7 @@ zfs_read(vnode_t *vp, uio_t *uio, int ioflag, cred_t *cr, caller_context_t *ct)
zfsvfs_t *zfsvfs = zp->z_zfsvfs;
objset_t *os;
ssize_t n, nbytes;
- int error;
+ int error = 0;
rl_t *rl;
xuio_t *xuio = NULL;
@@ -603,9 +603,9 @@ zfs_write(vnode_t *vp, uio_t *uio, int ioflag, cred_t *cr, caller_context_t *ct)
ssize_t n, nbytes;
rl_t *rl;
int max_blksz = zfsvfs->z_max_blksz;
- int error;
+ int error = 0;
arc_buf_t *abuf;
- iovec_t *aiov;
+ iovec_t *aiov = NULL;
xuio_t *xuio = NULL;
int i_iov = 0;
int iovcnt = uio->uio_iovcnt;
@@ -2187,6 +2187,7 @@ zfs_readdir(vnode_t *vp, uio_t *uio, cred_t *cr, int *eofp,
odp = (struct dirent64 *)outbuf;
} else {
bufsize = bytes_wanted;
+ outbuf = NULL;
odp = (struct dirent64 *)iovp->iov_base;
}
eodp = (struct edirent *)odp;
@@ -2628,7 +2629,7 @@ zfs_setattr(vnode_t *vp, vattr_t *vap, int flags, cred_t *cr,
vattr_t oldva;
xvattr_t tmpxvattr;
uint_t mask = vap->va_mask;
- uint_t saved_mask;
+ uint_t saved_mask = 0;
int trim_mask = 0;
uint64_t new_mode;
uint64_t new_uid, new_gid;
diff --git a/usr/src/uts/common/fs/zfs/zil.c b/usr/src/uts/common/fs/zfs/zil.c
index 969723471e..81d2bb5a97 100644
--- a/usr/src/uts/common/fs/zfs/zil.c
+++ b/usr/src/uts/common/fs/zfs/zil.c
@@ -190,7 +190,7 @@ zil_read_log_block(zilog_t *zilog, const blkptr_t *bp, blkptr_t *nbp, void *dst,
SET_BOOKMARK(&zb, bp->blk_cksum.zc_word[ZIL_ZC_OBJSET],
ZB_ZIL_OBJECT, ZB_ZIL_LEVEL, bp->blk_cksum.zc_word[ZIL_ZC_SEQ]);
- error = dsl_read_nolock(NULL, zilog->zl_spa, bp, arc_getbuf_func, &abuf,
+ error = arc_read(NULL, zilog->zl_spa, bp, arc_getbuf_func, &abuf,
ZIO_PRIORITY_SYNC_READ, zio_flags, &aflags, &zb);
if (error == 0) {
@@ -266,7 +266,7 @@ zil_read_log_data(zilog_t *zilog, const lr_write_t *lr, void *wbuf)
SET_BOOKMARK(&zb, dmu_objset_id(zilog->zl_os), lr->lr_foid,
ZB_ZIL_LEVEL, lr->lr_offset / BP_GET_LSIZE(bp));
- error = arc_read_nolock(NULL, zilog->zl_spa, bp, arc_getbuf_func, &abuf,
+ error = arc_read(NULL, zilog->zl_spa, bp, arc_getbuf_func, &abuf,
ZIO_PRIORITY_SYNC_READ, zio_flags, &aflags, &zb);
if (error == 0) {
diff --git a/usr/src/uts/common/fs/zfs/zio.c b/usr/src/uts/common/fs/zfs/zio.c
index 40fce8670d..75a1860845 100644
--- a/usr/src/uts/common/fs/zfs/zio.c
+++ b/usr/src/uts/common/fs/zfs/zio.c
@@ -2002,7 +2002,7 @@ zio_ddt_collision(zio_t *zio, ddt_t *ddt, ddt_entry_t *dde)
ddt_exit(ddt);
- error = arc_read_nolock(NULL, spa, &blk,
+ error = arc_read(NULL, spa, &blk,
arc_getbuf_func, &abuf, ZIO_PRIORITY_SYNC_READ,
ZIO_FLAG_CANFAIL | ZIO_FLAG_SPECULATIVE,
&aflags, &zio->io_bookmark);
diff --git a/usr/src/uts/common/fs/zfs/zvol.c b/usr/src/uts/common/fs/zfs/zvol.c
index ea7f0417b8..ca700c272e 100644
--- a/usr/src/uts/common/fs/zfs/zvol.c
+++ b/usr/src/uts/common/fs/zfs/zvol.c
@@ -147,10 +147,11 @@ static int zvol_dump_fini(zvol_state_t *zv);
static int zvol_dump_init(zvol_state_t *zv, boolean_t resize);
static void
-zvol_size_changed(uint64_t volsize, major_t maj, minor_t min)
+zvol_size_changed(zvol_state_t *zv, uint64_t volsize)
{
- dev_t dev = makedevice(maj, min);
+ dev_t dev = makedevice(ddi_driver_major(zfs_dip), zv->zv_minor);
+ zv->zv_volsize = volsize;
VERIFY(ddi_prop_update_int64(dev, zfs_dip,
"Size", volsize) == DDI_SUCCESS);
VERIFY(ddi_prop_update_int64(dev, zfs_dip,
@@ -238,7 +239,7 @@ struct maparg {
/*ARGSUSED*/
static int
-zvol_map_block(spa_t *spa, zilog_t *zilog, const blkptr_t *bp, arc_buf_t *pbuf,
+zvol_map_block(spa_t *spa, zilog_t *zilog, const blkptr_t *bp,
const zbookmark_t *zb, const dnode_phys_t *dnp, void *arg)
{
struct maparg *ma = arg;
@@ -612,22 +613,22 @@ zvol_first_open(zvol_state_t *zv)
if (error)
return (error);
+ zv->zv_objset = os;
error = zap_lookup(os, ZVOL_ZAP_OBJ, "size", 8, 1, &volsize);
if (error) {
ASSERT(error == 0);
dmu_objset_disown(os, zvol_tag);
return (error);
}
- zv->zv_objset = os;
+
error = dmu_bonus_hold(os, ZVOL_OBJ, zvol_tag, &zv->zv_dbuf);
if (error) {
dmu_objset_disown(os, zvol_tag);
return (error);
}
- zv->zv_volsize = volsize;
+
+ zvol_size_changed(zv, volsize);
zv->zv_zilog = zil_open(os, zvol_get_data);
- zvol_size_changed(zv->zv_volsize, ddi_driver_major(zfs_dip),
- zv->zv_minor);
VERIFY(dsl_prop_get_integer(zv->zv_name, "readonly", &readonly,
NULL) == 0);
@@ -749,56 +750,37 @@ zvol_remove_minors(const char *name)
mutex_exit(&zfsdev_state_lock);
}
-int
-zvol_set_volsize(const char *name, major_t maj, uint64_t volsize)
+static int
+zvol_set_volsize_impl(objset_t *os, zvol_state_t *zv, uint64_t volsize)
{
- zvol_state_t *zv = NULL;
- objset_t *os;
- int error;
- dmu_object_info_t doi;
uint64_t old_volsize = 0ULL;
- uint64_t readonly;
-
- mutex_enter(&zfsdev_state_lock);
- zv = zvol_minor_lookup(name);
- if ((error = dmu_objset_hold(name, FTAG, &os)) != 0) {
- mutex_exit(&zfsdev_state_lock);
- return (error);
- }
-
- if ((error = dmu_object_info(os, ZVOL_OBJ, &doi)) != 0 ||
- (error = zvol_check_volsize(volsize,
- doi.doi_data_block_size)) != 0)
- goto out;
-
- VERIFY(dsl_prop_get_integer(name, "readonly", &readonly,
- NULL) == 0);
- if (readonly) {
- error = EROFS;
- goto out;
- }
+ int error;
+ ASSERT(MUTEX_HELD(&zfsdev_state_lock));
error = zvol_update_volsize(os, volsize);
+
/*
* Reinitialize the dump area to the new size. If we
* failed to resize the dump area then restore it back to
- * its original size.
+ * its original size. We must set the new volsize prior
+ * to calling dumpvp_resize() to ensure that the devices'
+ * size(9P) is not visible by the dump subsystem.
*/
if (zv && error == 0) {
+ old_volsize = zv->zv_volsize;
+ zvol_size_changed(zv, volsize);
+
if (zv->zv_flags & ZVOL_DUMPIFIED) {
- old_volsize = zv->zv_volsize;
- zv->zv_volsize = volsize;
if ((error = zvol_dumpify(zv)) != 0 ||
(error = dumpvp_resize()) != 0) {
+ int dumpify_error;
+
(void) zvol_update_volsize(os, old_volsize);
- zv->zv_volsize = old_volsize;
- error = zvol_dumpify(zv);
+ zvol_size_changed(zv, old_volsize);
+ dumpify_error = zvol_dumpify(zv);
+ error = dumpify_error ? dumpify_error : error;
}
}
- if (error == 0) {
- zv->zv_volsize = volsize;
- zvol_size_changed(volsize, maj, zv->zv_minor);
- }
}
/*
@@ -821,12 +803,41 @@ zvol_set_volsize(const char *name, major_t maj, uint64_t volsize)
nvlist_free(attr);
kmem_free(physpath, MAXPATHLEN);
}
+ return (error);
+}
+int
+zvol_set_volsize(const char *name, uint64_t volsize)
+{
+ zvol_state_t *zv = NULL;
+ objset_t *os;
+ int error;
+ dmu_object_info_t doi;
+ uint64_t readonly;
+
+ mutex_enter(&zfsdev_state_lock);
+ zv = zvol_minor_lookup(name);
+ if ((error = dmu_objset_hold(name, FTAG, &os)) != 0) {
+ mutex_exit(&zfsdev_state_lock);
+ return (error);
+ }
+
+ if ((error = dmu_object_info(os, ZVOL_OBJ, &doi)) != 0 ||
+ (error = zvol_check_volsize(volsize,
+ doi.doi_data_block_size)) != 0)
+ goto out;
+
+ VERIFY3U(dsl_prop_get_integer(name,
+ zfs_prop_to_name(ZFS_PROP_READONLY), &readonly, NULL), ==, 0);
+ if (readonly) {
+ error = EROFS;
+ goto out;
+ }
+
+ error = zvol_set_volsize_impl(os, zv, volsize);
out:
dmu_objset_rele(os, FTAG);
-
mutex_exit(&zfsdev_state_lock);
-
return (error);
}
diff --git a/usr/src/uts/common/inet/ip_stack.h b/usr/src/uts/common/inet/ip_stack.h
index 706752b236..e46a3b6a3c 100644
--- a/usr/src/uts/common/inet/ip_stack.h
+++ b/usr/src/uts/common/inet/ip_stack.h
@@ -113,11 +113,6 @@ typedef struct ip6_stat {
kstat_named_t ip6_udp_in_full_hw_cksum_err;
kstat_named_t ip6_udp_in_part_hw_cksum_err;
kstat_named_t ip6_udp_in_sw_cksum_err;
- kstat_named_t ip6_frag_mdt_pkt_out;
- kstat_named_t ip6_frag_mdt_discarded;
- kstat_named_t ip6_frag_mdt_allocfail;
- kstat_named_t ip6_frag_mdt_addpdescfail;
- kstat_named_t ip6_frag_mdt_allocd;
} ip6_stat_t;
typedef struct ire_stats {
diff --git a/usr/src/uts/common/io/dump.c b/usr/src/uts/common/io/dump.c
index 70a61bf9b8..ab5a9d0240 100644
--- a/usr/src/uts/common/io/dump.c
+++ b/usr/src/uts/common/io/dump.c
@@ -20,6 +20,7 @@
*/
/*
* Copyright (c) 1998, 2010, Oracle and/or its affiliates. All rights reserved.
+ * Delphix (c) 2012 by Delphix. All rights reserved.
*/
@@ -208,6 +209,13 @@ dump_ioctl(dev_t dev, int cmd, intptr_t arg, int mode, cred_t *cred, int *rvalp)
error = copyoutstr(dump_get_uuid(), (void *)arg, 37, NULL);
break;
+ case DIOCRMDEV:
+ mutex_enter(&dump_lock);
+ if (dumpvp != NULL)
+ dumpfini();
+ mutex_exit(&dump_lock);
+ break;
+
default:
error = ENXIO;
}
diff --git a/usr/src/uts/common/io/e1000g/e1000g_main.c b/usr/src/uts/common/io/e1000g/e1000g_main.c
index e4c0a817b5..dcc7d87190 100644
--- a/usr/src/uts/common/io/e1000g/e1000g_main.c
+++ b/usr/src/uts/common/io/e1000g/e1000g_main.c
@@ -23,8 +23,8 @@
*/
/*
- * Copyright 2011 Nexenta Systems, Inc. All rights reserved.
* Copyright 2012 DEY Storage Systems, Inc. All rights reserved.
+ * Copyright 2013 Nexenta Systems, Inc. All rights reserved.
*/
/*
@@ -2438,7 +2438,8 @@ e1000g_init_unicst(struct e1000g *Adapter)
if (Adapter->init_count == 0) {
/* Initialize the multiple unicast addresses */
- Adapter->unicst_total = MAX_NUM_UNICAST_ADDRESSES;
+ Adapter->unicst_total = min(hw->mac.rar_entry_count,
+ MAX_NUM_UNICAST_ADDRESSES);
/* Workaround for an erratum of 82571 chipst */
if ((hw->mac.type == e1000_82571) &&
diff --git a/usr/src/uts/common/io/igb/igb_82575.c b/usr/src/uts/common/io/igb/igb_82575.c
index 15241e7664..f3f69474ec 100644
--- a/usr/src/uts/common/io/igb/igb_82575.c
+++ b/usr/src/uts/common/io/igb/igb_82575.c
@@ -25,6 +25,7 @@
/*
* Copyright (c) 2008, 2010, Oracle and/or its affiliates. All rights reserved.
+ * Copyright 2013, Nexenta Systems, Inc. All rights reserved.
*/
/* IntelVersion: 1.146.2.2 v3_3_14_3_BHSW1 */
@@ -307,8 +308,8 @@ e1000_init_mac_params_82575(struct e1000_hw *hw)
mac->rar_entry_count = E1000_RAR_ENTRIES_82580;
if (mac->type == e1000_i350) {
mac->rar_entry_count = E1000_RAR_ENTRIES_I350;
- /* Enable EEE default settings for i350 */
- dev_spec->eee_disable = B_FALSE;
+ /* Disable EEE default settings for i350 */
+ dev_spec->eee_disable = B_TRUE;
}
/* Set if part includes ASF firmware */
mac->asf_firmware_present = true;
diff --git a/usr/src/uts/common/io/igb/igb_gld.c b/usr/src/uts/common/io/igb/igb_gld.c
index 56c5f3deb5..ed247bebe4 100644
--- a/usr/src/uts/common/io/igb/igb_gld.c
+++ b/usr/src/uts/common/io/igb/igb_gld.c
@@ -25,6 +25,7 @@
/*
* Copyright (c) 2008, 2010, Oracle and/or its affiliates. All rights reserved.
+ * Copyright 2013, Nexenta Systems, Inc. All rights reserved.
*/
#include "igb_sw.h"
@@ -1385,6 +1386,32 @@ igb_set_priv_prop(igb_t *igb, const char *pr_name,
struct e1000_hw *hw = &igb->hw;
int i;
+ if (strcmp(pr_name, "_eee_support") == 0) {
+ if (pr_val == NULL)
+ return (EINVAL);
+ (void) ddi_strtol(pr_val, (char **)NULL, 0, &result);
+ switch (result) {
+ case 0:
+ case 1:
+ if (hw->mac.type != e1000_i350) {
+ /*
+ * For now, only supported on I350.
+ * Add new mac.type values (or use < instead)
+ * as new cards offer up EEE.
+ */
+ return (ENXIO);
+ }
+ /* Must set this prior to the set call. */
+ hw->dev_spec._82575.eee_disable = !result;
+ if (e1000_set_eee_i350(hw) != E1000_SUCCESS)
+ err = EIO;
+ break;
+ default:
+ err = EINVAL;
+ /* FALLTHRU */
+ }
+ return (err);
+ }
if (strcmp(pr_name, "_tx_copy_thresh") == 0) {
if (pr_val == NULL) {
err = EINVAL;
@@ -1507,6 +1534,13 @@ igb_get_priv_prop(igb_t *igb, const char *pr_name, uint_t pr_valsize,
value = igb->param_adv_pause_cap;
} else if (strcmp(pr_name, "_adv_asym_pause_cap") == 0) {
value = igb->param_adv_asym_pause_cap;
+ } else if (strcmp(pr_name, "_eee_support") == 0) {
+ /*
+ * For now, only supported on I350. Add new mac.type values
+ * (or use < instead) as new cards offer up EEE.
+ */
+ value = (igb->hw.mac.type != e1000_i350) ? 0 :
+ !(igb->hw.dev_spec._82575.eee_disable);
} else if (strcmp(pr_name, "_tx_copy_thresh") == 0) {
value = igb->tx_copy_thresh;
} else if (strcmp(pr_name, "_tx_recycle_thresh") == 0) {
diff --git a/usr/src/uts/common/io/igb/igb_main.c b/usr/src/uts/common/io/igb/igb_main.c
index c4e4e33ae9..7864a3193f 100644
--- a/usr/src/uts/common/io/igb/igb_main.c
+++ b/usr/src/uts/common/io/igb/igb_main.c
@@ -25,6 +25,7 @@
/*
* Copyright (c) 2008, 2010, Oracle and/or its affiliates. All rights reserved.
+ * Copyright 2013, Nexenta Systems, Inc. All rights reserved.
*/
#include "igb_sw.h"
@@ -123,6 +124,7 @@ static void igb_fm_fini(igb_t *);
static void igb_release_multicast(igb_t *);
char *igb_priv_props[] = {
+ "_eee_support",
"_tx_copy_thresh",
"_tx_recycle_thresh",
"_tx_overload_thresh",
diff --git a/usr/src/uts/common/io/scsi/targets/sd.c b/usr/src/uts/common/io/scsi/targets/sd.c
index a1edcc664c..7e9940e33b 100644
--- a/usr/src/uts/common/io/scsi/targets/sd.c
+++ b/usr/src/uts/common/io/scsi/targets/sd.c
@@ -23,9 +23,9 @@
* Copyright (c) 1990, 2010, Oracle and/or its affiliates. All rights reserved.
*/
/*
- * Copyright 2011 Nexenta Systems, Inc. All rights reserved.
* Copyright (c) 2011 Bayard G. Bell. All rights reserved.
* Copyright (c) 2012 by Delphix. All rights reserved.
+ * Copyright 2013 Nexenta Systems, Inc. All rights reserved.
* Copyright 2012 DEY Storage Systems, Inc. All rights reserved.
*/
/*
@@ -12711,16 +12711,17 @@ sd_mapblockaddr_iostart(int index, struct sd_lun *un, struct buf *bp)
if (is_aligned) {
xp->xb_blkno = SD_SYS2TGTBLOCK(un, xp->xb_blkno);
} else {
- switch (un->un_f_rmw_type) {
- case SD_RMW_TYPE_RETURN_ERROR:
- if (un->un_f_enable_rmw)
- break;
- else {
- bp->b_flags |= B_ERROR;
- goto error_exit;
- }
-
- case SD_RMW_TYPE_DEFAULT:
+ /*
+ * There is no RMW if we're just reading, so don't
+ * warn or error out because of it.
+ */
+ if (bp->b_flags & B_READ) {
+ /*EMPTY*/
+ } else if (!un->un_f_enable_rmw &&
+ un->un_f_rmw_type == SD_RMW_TYPE_RETURN_ERROR) {
+ bp->b_flags |= B_ERROR;
+ goto error_exit;
+ } else if (un->un_f_rmw_type == SD_RMW_TYPE_DEFAULT) {
mutex_enter(SD_MUTEX(un));
if (!un->un_f_enable_rmw &&
un->un_rmw_msg_timeid == NULL) {
@@ -12738,11 +12739,6 @@ sd_mapblockaddr_iostart(int index, struct sd_lun *un, struct buf *bp)
un->un_rmw_incre_count ++;
}
mutex_exit(SD_MUTEX(un));
- break;
-
- case SD_RMW_TYPE_NO_WARNING:
- default:
- break;
}
nblocks = SD_TGT2SYSBLOCK(un, nblocks);
diff --git a/usr/src/uts/common/io/usb/clients/usbser/usbftdi/uftdi_dsd.c b/usr/src/uts/common/io/usb/clients/usbser/usbftdi/uftdi_dsd.c
index 97e73e907e..670926b6a2 100644
--- a/usr/src/uts/common/io/usb/clients/usbser/usbftdi/uftdi_dsd.c
+++ b/usr/src/uts/common/io/usb/clients/usbser/usbftdi/uftdi_dsd.c
@@ -25,6 +25,10 @@
*/
/*
+ * Copyright 2013 Hans Rosenfeld <rosenfeld@grumpf.hope-2000.org>
+ */
+
+/*
* FTDI FT232R USB UART device-specific driver
*
* May work on the (many) devices based on earlier versions of the chip.
@@ -220,6 +224,7 @@ uftdi_attach(ds_attach_info_t *aip)
switch (dd->idVendor) {
case USB_VENDOR_FTDI:
switch (dd->idProduct) {
+ case USB_PRODUCT_FTDI_SERIAL_2232C:
case USB_PRODUCT_FTDI_SERIAL_8U232AM:
case USB_PRODUCT_FTDI_SEMC_DSS20:
case USB_PRODUCT_FTDI_CFA_631:
@@ -328,23 +333,6 @@ uftdi_attach(ds_attach_info_t *aip)
return (USB_FAILURE);
}
- if (usb_pipe_get_max_bulk_transfer_size(uf->uf_dip,
- &uf->uf_xfer_sz) != USB_SUCCESS) {
- uftdi_cleanup(uf, 5);
- return (USB_FAILURE);
- }
-
- /*
- * TODO: modern ftdi devices have deeper (and asymmetric)
- * fifos than this minimal 64 bytes .. but how to tell
- * -safely- ?
- */
-
-#define FTDI_MAX_XFERSIZE 64
-
- if (uf->uf_xfer_sz > FTDI_MAX_XFERSIZE)
- uf->uf_xfer_sz = FTDI_MAX_XFERSIZE;
-
if (uftdi_dev_attach(uf) != USB_SUCCESS) {
uftdi_cleanup(uf, 5);
return (USB_FAILURE);
@@ -1501,6 +1489,12 @@ uftdi_open_pipes(uftdi_state_t *uf)
int ifc, alt;
usb_pipe_policy_t policy;
usb_ep_data_t *in_data, *out_data;
+ size_t max_xfer_sz;
+
+ /* get max transfer size */
+ if (usb_pipe_get_max_bulk_transfer_size(uf->uf_dip, &max_xfer_sz)
+ != USB_SUCCESS)
+ return (USB_FAILURE);
/* get ep data */
ifc = uf->uf_dev_data->dev_curr_if;
@@ -1518,6 +1512,21 @@ uftdi_open_pipes(uftdi_state_t *uf)
return (USB_FAILURE);
}
+ /*
+ * Set buffer sizes. Default to UFTDI_XFER_SZ_MAX.
+ * Use wMaxPacketSize from endpoint descriptor if it is nonzero.
+ * Cap at a max transfer size of host controller.
+ */
+ uf->uf_ibuf_sz = uf->uf_obuf_sz = UFTDI_XFER_SZ_MAX;
+
+ if (in_data->ep_descr.wMaxPacketSize)
+ uf->uf_ibuf_sz = in_data->ep_descr.wMaxPacketSize;
+ uf->uf_ibuf_sz = min(uf->uf_ibuf_sz, max_xfer_sz);
+
+ if (out_data->ep_descr.wMaxPacketSize)
+ uf->uf_obuf_sz = out_data->ep_descr.wMaxPacketSize;
+ uf->uf_obuf_sz = min(uf->uf_obuf_sz, max_xfer_sz);
+
/* open pipes */
policy.pp_max_async_reqs = 2;
@@ -1806,8 +1815,8 @@ uftdi_rx_start(uftdi_state_t *uf)
uf->uf_bulkin_state = UFTDI_PIPE_BUSY;
mutex_exit(&uf->uf_lock);
- br = usb_alloc_bulk_req(uf->uf_dip, uf->uf_xfer_sz, USB_FLAGS_SLEEP);
- br->bulk_len = uf->uf_xfer_sz;
+ br = usb_alloc_bulk_req(uf->uf_dip, uf->uf_ibuf_sz, USB_FLAGS_SLEEP);
+ br->bulk_len = uf->uf_ibuf_sz;
br->bulk_timeout = UFTDI_BULKIN_TIMEOUT;
br->bulk_cb = uftdi_bulkin_cb;
br->bulk_exc_cb = uftdi_bulkin_cb;
@@ -1861,7 +1870,7 @@ uftdi_tx_start(uftdi_state_t *uf, int *xferd)
ASSERT(MBLKL(uf->uf_tx_mp) > 0);
/* send as much data as port can receive */
- len = min(msgdsize(uf->uf_tx_mp), uf->uf_xfer_sz);
+ len = min(msgdsize(uf->uf_tx_mp), uf->uf_obuf_sz);
if (len <= 0)
return;
diff --git a/usr/src/uts/common/io/usb/usba/hcdi.c b/usr/src/uts/common/io/usb/usba/hcdi.c
index 073d367f51..42af937dfb 100644
--- a/usr/src/uts/common/io/usb/usba/hcdi.c
+++ b/usr/src/uts/common/io/usb/usba/hcdi.c
@@ -343,26 +343,20 @@ usba_hcdi_create_stats(usba_hcdi_t *hcdi, int instance)
"Command Timed Out", KSTAT_DATA_UINT64);
kstat_named_init(&esp->cc_not_accessed,
"Not Accessed By Hardware", KSTAT_DATA_UINT64);
+ kstat_named_init(&esp->cc_no_resources,
+ "No Resources", KSTAT_DATA_UINT64);
kstat_named_init(&esp->cc_unspecified_err,
"Unspecified Error", KSTAT_DATA_UINT64);
-#ifdef NOTYETNEEDED
- kstat_named_init(&esp->hcdi_usb_failure,
- "USB Failure", KSTAT_DATA_UINT64);
- kstat_named_init(&esp->hcdi_usb_no_resources,
- "No Resources", KSTAT_DATA_UINT64);
- kstat_named_init(&esp->hcdi_usb_no_bandwidth,
- "No Bandwidth", KSTAT_DATA_UINT64);
- kstat_named_init(&esp->hcdi_usb_pipe_reserved,
- "Pipe Reserved", KSTAT_DATA_UINT64);
- kstat_named_init(&esp->hcdi_usb_pipe_unshareable,
- "Pipe Unshareable", KSTAT_DATA_UINT64);
- kstat_named_init(&esp->hcdi_usb_not_supported,
- "Function Not Supported", KSTAT_DATA_UINT64);
- kstat_named_init(&esp->hcdi_usb_pipe_error,
- "Pipe Error", KSTAT_DATA_UINT64);
- kstat_named_init(&esp->hcdi_usb_pipe_busy,
- "Pipe Busy", KSTAT_DATA_UINT64);
-#endif
+ kstat_named_init(&esp->cc_stopped_polling,
+ "Stopped Polling", KSTAT_DATA_UINT64);
+ kstat_named_init(&esp->cc_pipe_closing,
+ "Pipe Closing", KSTAT_DATA_UINT64);
+ kstat_named_init(&esp->cc_pipe_reset,
+ "Pipe Reset", KSTAT_DATA_UINT64);
+ kstat_named_init(&esp->cc_not_supported,
+ "Command Not Supported", KSTAT_DATA_UINT64);
+ kstat_named_init(&esp->cc_flushed,
+ "Request Flushed", KSTAT_DATA_UINT64);
HCDI_ERROR_STATS(hcdi)->ks_private = hcdi;
HCDI_ERROR_STATS(hcdi)->ks_update = nulldev;
diff --git a/usr/src/uts/common/nfs/nfs4.h b/usr/src/uts/common/nfs/nfs4.h
index cf36c03d0a..c0d20ad5e7 100644
--- a/usr/src/uts/common/nfs/nfs4.h
+++ b/usr/src/uts/common/nfs/nfs4.h
@@ -23,7 +23,7 @@
* Use is subject to license terms.
*/
/*
- * Copyright 2012 Nexenta Systems, Inc. All rights reserved.
+ * Copyright 2013 Nexenta Systems, Inc. All rights reserved.
*/
#ifndef _NFS4_H
@@ -390,12 +390,12 @@ nvlist_t *rfs4_dss_paths, *rfs4_dss_oldpaths;
/*
* The following ascii art represents each of these data structs and
* their references to each other. Note: "<-(x)->" represents the
- * doubly link lists defined above.
+ * doubly link lists (list_t).
*
* ____________________
* | |
* | rfs4_client_t |
- * ->| (1),(2) |<-
+ * ->| (1) |<-
* / |____________________| \
* / ^ \
* / | \
@@ -409,7 +409,7 @@ nvlist_t *rfs4_dss_paths, *rfs4_dss_oldpaths;
* ____________________ ____________________ ____________________
* | | | | | |
* | rfs4_lo_state_t |->| rfs4_state_t |->| rfs4_file_t |
- * | <-(4)-> | | (4) <-(3)-> | | |
+ * | <-(4)-> | | (4) <-(3)-> | | (2) |
* |____________________| |____________________| |____________________|
*/
/*
diff --git a/usr/src/uts/common/os/cpu.c b/usr/src/uts/common/os/cpu.c
index b6c9d2ede3..a2047160d5 100644
--- a/usr/src/uts/common/os/cpu.c
+++ b/usr/src/uts/common/os/cpu.c
@@ -20,6 +20,7 @@
*/
/*
* Copyright (c) 1991, 2010, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2012 by Delphix. All rights reserved.
*/
/*
@@ -182,9 +183,11 @@ static struct cpu_sys_stats_ks_data {
kstat_named_t cpu_nsec_idle;
kstat_named_t cpu_nsec_user;
kstat_named_t cpu_nsec_kernel;
+ kstat_named_t cpu_nsec_dtrace;
kstat_named_t cpu_nsec_intr;
kstat_named_t cpu_load_intr;
kstat_named_t wait_ticks_io;
+ kstat_named_t dtrace_probes;
kstat_named_t bread;
kstat_named_t bwrite;
kstat_named_t lread;
@@ -232,61 +235,63 @@ static struct cpu_sys_stats_ks_data {
kstat_named_t bawrite;
kstat_named_t iowait;
} cpu_sys_stats_ks_data_template = {
- { "cpu_ticks_idle", KSTAT_DATA_UINT64 },
- { "cpu_ticks_user", KSTAT_DATA_UINT64 },
- { "cpu_ticks_kernel", KSTAT_DATA_UINT64 },
- { "cpu_ticks_wait", KSTAT_DATA_UINT64 },
+ { "cpu_ticks_idle", KSTAT_DATA_UINT64 },
+ { "cpu_ticks_user", KSTAT_DATA_UINT64 },
+ { "cpu_ticks_kernel", KSTAT_DATA_UINT64 },
+ { "cpu_ticks_wait", KSTAT_DATA_UINT64 },
{ "cpu_nsec_idle", KSTAT_DATA_UINT64 },
{ "cpu_nsec_user", KSTAT_DATA_UINT64 },
{ "cpu_nsec_kernel", KSTAT_DATA_UINT64 },
+ { "cpu_nsec_dtrace", KSTAT_DATA_UINT64 },
{ "cpu_nsec_intr", KSTAT_DATA_UINT64 },
{ "cpu_load_intr", KSTAT_DATA_UINT64 },
- { "wait_ticks_io", KSTAT_DATA_UINT64 },
- { "bread", KSTAT_DATA_UINT64 },
- { "bwrite", KSTAT_DATA_UINT64 },
- { "lread", KSTAT_DATA_UINT64 },
- { "lwrite", KSTAT_DATA_UINT64 },
- { "phread", KSTAT_DATA_UINT64 },
- { "phwrite", KSTAT_DATA_UINT64 },
- { "pswitch", KSTAT_DATA_UINT64 },
- { "trap", KSTAT_DATA_UINT64 },
- { "intr", KSTAT_DATA_UINT64 },
- { "syscall", KSTAT_DATA_UINT64 },
- { "sysread", KSTAT_DATA_UINT64 },
- { "syswrite", KSTAT_DATA_UINT64 },
- { "sysfork", KSTAT_DATA_UINT64 },
- { "sysvfork", KSTAT_DATA_UINT64 },
- { "sysexec", KSTAT_DATA_UINT64 },
- { "readch", KSTAT_DATA_UINT64 },
- { "writech", KSTAT_DATA_UINT64 },
- { "rcvint", KSTAT_DATA_UINT64 },
- { "xmtint", KSTAT_DATA_UINT64 },
- { "mdmint", KSTAT_DATA_UINT64 },
- { "rawch", KSTAT_DATA_UINT64 },
- { "canch", KSTAT_DATA_UINT64 },
- { "outch", KSTAT_DATA_UINT64 },
- { "msg", KSTAT_DATA_UINT64 },
- { "sema", KSTAT_DATA_UINT64 },
- { "namei", KSTAT_DATA_UINT64 },
- { "ufsiget", KSTAT_DATA_UINT64 },
- { "ufsdirblk", KSTAT_DATA_UINT64 },
- { "ufsipage", KSTAT_DATA_UINT64 },
- { "ufsinopage", KSTAT_DATA_UINT64 },
- { "procovf", KSTAT_DATA_UINT64 },
- { "intrthread", KSTAT_DATA_UINT64 },
- { "intrblk", KSTAT_DATA_UINT64 },
+ { "wait_ticks_io", KSTAT_DATA_UINT64 },
+ { "dtrace_probes", KSTAT_DATA_UINT64 },
+ { "bread", KSTAT_DATA_UINT64 },
+ { "bwrite", KSTAT_DATA_UINT64 },
+ { "lread", KSTAT_DATA_UINT64 },
+ { "lwrite", KSTAT_DATA_UINT64 },
+ { "phread", KSTAT_DATA_UINT64 },
+ { "phwrite", KSTAT_DATA_UINT64 },
+ { "pswitch", KSTAT_DATA_UINT64 },
+ { "trap", KSTAT_DATA_UINT64 },
+ { "intr", KSTAT_DATA_UINT64 },
+ { "syscall", KSTAT_DATA_UINT64 },
+ { "sysread", KSTAT_DATA_UINT64 },
+ { "syswrite", KSTAT_DATA_UINT64 },
+ { "sysfork", KSTAT_DATA_UINT64 },
+ { "sysvfork", KSTAT_DATA_UINT64 },
+ { "sysexec", KSTAT_DATA_UINT64 },
+ { "readch", KSTAT_DATA_UINT64 },
+ { "writech", KSTAT_DATA_UINT64 },
+ { "rcvint", KSTAT_DATA_UINT64 },
+ { "xmtint", KSTAT_DATA_UINT64 },
+ { "mdmint", KSTAT_DATA_UINT64 },
+ { "rawch", KSTAT_DATA_UINT64 },
+ { "canch", KSTAT_DATA_UINT64 },
+ { "outch", KSTAT_DATA_UINT64 },
+ { "msg", KSTAT_DATA_UINT64 },
+ { "sema", KSTAT_DATA_UINT64 },
+ { "namei", KSTAT_DATA_UINT64 },
+ { "ufsiget", KSTAT_DATA_UINT64 },
+ { "ufsdirblk", KSTAT_DATA_UINT64 },
+ { "ufsipage", KSTAT_DATA_UINT64 },
+ { "ufsinopage", KSTAT_DATA_UINT64 },
+ { "procovf", KSTAT_DATA_UINT64 },
+ { "intrthread", KSTAT_DATA_UINT64 },
+ { "intrblk", KSTAT_DATA_UINT64 },
{ "intrunpin", KSTAT_DATA_UINT64 },
- { "idlethread", KSTAT_DATA_UINT64 },
- { "inv_swtch", KSTAT_DATA_UINT64 },
- { "nthreads", KSTAT_DATA_UINT64 },
- { "cpumigrate", KSTAT_DATA_UINT64 },
- { "xcalls", KSTAT_DATA_UINT64 },
- { "mutex_adenters", KSTAT_DATA_UINT64 },
- { "rw_rdfails", KSTAT_DATA_UINT64 },
- { "rw_wrfails", KSTAT_DATA_UINT64 },
- { "modload", KSTAT_DATA_UINT64 },
- { "modunload", KSTAT_DATA_UINT64 },
- { "bawrite", KSTAT_DATA_UINT64 },
+ { "idlethread", KSTAT_DATA_UINT64 },
+ { "inv_swtch", KSTAT_DATA_UINT64 },
+ { "nthreads", KSTAT_DATA_UINT64 },
+ { "cpumigrate", KSTAT_DATA_UINT64 },
+ { "xcalls", KSTAT_DATA_UINT64 },
+ { "mutex_adenters", KSTAT_DATA_UINT64 },
+ { "rw_rdfails", KSTAT_DATA_UINT64 },
+ { "rw_wrfails", KSTAT_DATA_UINT64 },
+ { "modload", KSTAT_DATA_UINT64 },
+ { "modunload", KSTAT_DATA_UINT64 },
+ { "bawrite", KSTAT_DATA_UINT64 },
{ "iowait", KSTAT_DATA_UINT64 },
};
@@ -3206,6 +3211,8 @@ cpu_sys_stats_ks_update(kstat_t *ksp, int rw)
NSEC_TO_TICK(csskd->cpu_nsec_user.value.ui64);
csskd->cpu_ticks_kernel.value.ui64 =
NSEC_TO_TICK(csskd->cpu_nsec_kernel.value.ui64);
+ csskd->cpu_nsec_dtrace.value.ui64 = cp->cpu_dtrace_nsec;
+ csskd->dtrace_probes.value.ui64 = cp->cpu_dtrace_probes;
csskd->cpu_nsec_intr.value.ui64 = cp->cpu_intrlast;
csskd->cpu_load_intr.value.ui64 = cp->cpu_intrload;
csskd->bread.value.ui64 = css->bread;
diff --git a/usr/src/uts/common/os/log_sysevent.c b/usr/src/uts/common/os/log_sysevent.c
index 8923136f98..51cfa7f817 100644
--- a/usr/src/uts/common/os/log_sysevent.c
+++ b/usr/src/uts/common/os/log_sysevent.c
@@ -20,6 +20,7 @@
*/
/*
* Copyright (c) 2000, 2010, Oracle and/or its affiliates. All rights reserved.
+ * Copyright 2013 Nexenta Systems, Inc. All rights reserved.
*/
#include <sys/types.h>
@@ -95,10 +96,10 @@ int logevent_max_q_sz = 5000;
static int log_event_delivery = LOGEVENT_DELIVERY_HOLD;
-static char *logevent_door_upcall_filename = NULL;
-static int logevent_door_upcall_filename_size;
+static char logevent_door_upcall_filename[MAXPATHLEN];
static door_handle_t event_door = NULL; /* Door for upcalls */
+static kmutex_t event_door_mutex; /* To protect event_door */
/*
* async thread-related variables
@@ -146,33 +147,6 @@ static kmutex_t event_pause_mutex;
static kcondvar_t event_pause_cv;
static int event_pause_state = 0;
-/*
- * log_event_upcall_lookup - Establish door connection with user event
- * daemon (syseventd)
- */
-static int
-log_event_upcall_lookup()
-{
- int error;
-
- if (event_door) { /* Release our previous hold (if any) */
- door_ki_rele(event_door);
- }
-
- event_door = NULL;
-
- /*
- * Locate the door used for upcalls
- */
- if ((error =
- door_ki_open(logevent_door_upcall_filename, &event_door)) != 0) {
- return (error);
- }
-
- return (0);
-}
-
-
/*ARGSUSED*/
static void
log_event_busy_timeout(void *arg)
@@ -234,23 +208,44 @@ log_event_upcall(log_event_upcall_arg_t *arg)
darg.desc_ptr = NULL;
darg.desc_num = 0;
- if ((event_door == NULL) &&
- ((error = log_event_upcall_lookup()) != 0)) {
- LOG_DEBUG((CE_CONT,
- "log_event_upcall: event_door error (%d)\n", error));
-
- return (error);
- }
-
LOG_DEBUG1((CE_CONT, "log_event_upcall: 0x%llx\n",
(longlong_t)SE_SEQ((sysevent_t *)&arg->buf)));
save_arg = darg;
for (retry = 0; ; retry++) {
+
+ mutex_enter(&event_door_mutex);
+ if (event_door == NULL) {
+ mutex_exit(&event_door_mutex);
+
+ return (EBADF);
+ }
+
if ((error = door_ki_upcall_limited(event_door, &darg, NULL,
SIZE_MAX, 0)) == 0) {
+ mutex_exit(&event_door_mutex);
break;
}
+
+ /*
+ * EBADF is handled outside the switch below because we need to
+ * hold event_door_mutex a bit longer
+ */
+ if (error == EBADF) {
+ /* Server died */
+ door_ki_rele(event_door);
+ event_door = NULL;
+
+ mutex_exit(&event_door_mutex);
+ return (error);
+ }
+
+ mutex_exit(&event_door_mutex);
+
+ /*
+ * The EBADF case is already handled above with event_door_mutex
+ * held
+ */
switch (error) {
case EINTR:
neintr++;
@@ -266,24 +261,6 @@ log_event_upcall(log_event_upcall_arg_t *arg)
nticks = LOG_EVENT_MAX_PAUSE;
darg = save_arg;
break;
- case EBADF:
- LOG_DEBUG((CE_CONT, "log_event_upcall: rebinding\n"));
- /* Server may have died. Try rebinding */
- if ((error = log_event_upcall_lookup()) != 0) {
- LOG_DEBUG((CE_CONT,
- "log_event_upcall: lookup error %d\n",
- error));
- return (EBADF);
- }
- if (retry > 4) {
- LOG_DEBUG((CE_CONT,
- "log_event_upcall: ebadf\n"));
- return (EBADF);
- }
- LOG_DEBUG((CE_CONT, "log_event_upcall: "
- "retrying upcall after lookup\n"));
- darg = save_arg;
- break;
default:
cmn_err(CE_CONT,
"log_event_upcall: door_ki_upcall error %d\n",
@@ -347,17 +324,17 @@ log_event_deliver()
q = log_eventq_head;
while (q) {
- log_eventq_t *next;
-
- /*
- * Release event queue lock during upcall to
- * syseventd
- */
if (log_event_delivery == LOGEVENT_DELIVERY_HOLD) {
upcall_err = EAGAIN;
break;
}
+ log_event_delivery = LOGEVENT_DELIVERY_OK;
+
+ /*
+ * Release event queue lock during upcall to
+ * syseventd
+ */
mutex_exit(&eventq_head_mutex);
if ((upcall_err = log_event_upcall(&q->arg)) != 0) {
mutex_enter(&eventq_head_mutex);
@@ -390,6 +367,8 @@ log_event_deliver()
LOG_DEBUG((CE_CONT, "log_event_deliver: "
"door upcall/daemon restart race\n"));
} else {
+ log_eventq_t *next;
+
/*
* Move the event to the sent queue when a
* successful delivery has been made.
@@ -426,12 +405,9 @@ log_event_deliver()
* resumption, continue. Otherwise, we wait until
* we are signaled to continue.
*/
- if (log_event_delivery == LOGEVENT_DELIVERY_CONT) {
- log_event_delivery = LOGEVENT_DELIVERY_OK;
+ if (log_event_delivery == LOGEVENT_DELIVERY_CONT)
continue;
- } else {
- log_event_delivery = LOGEVENT_DELIVERY_HOLD;
- }
+ log_event_delivery = LOGEVENT_DELIVERY_HOLD;
LOG_DEBUG1((CE_CONT, "log_event_deliver: EAGAIN\n"));
break;
@@ -465,6 +441,8 @@ log_event_deliver()
void
log_event_init()
{
+ mutex_init(&event_door_mutex, NULL, MUTEX_DEFAULT, NULL);
+
mutex_init(&eventq_head_mutex, NULL, MUTEX_DEFAULT, NULL);
mutex_init(&eventq_sent_mutex, NULL, MUTEX_DEFAULT, NULL);
cv_init(&log_event_cv, NULL, CV_DEFAULT, NULL);
@@ -1601,23 +1579,19 @@ log_sysevent_flushq(int cmd, uint_t flag)
int
log_sysevent_filename(char *file)
{
- /*
- * Called serially by syseventd init code, no need to protect door
- * data.
- */
+ mutex_enter(&event_door_mutex);
+
+ (void) strlcpy(logevent_door_upcall_filename, file,
+ sizeof (logevent_door_upcall_filename));
+
/* Unbind old event door */
- if (logevent_door_upcall_filename) {
- kmem_free(logevent_door_upcall_filename,
- logevent_door_upcall_filename_size);
- if (event_door) {
- door_ki_rele(event_door);
- event_door = NULL;
- }
- }
- logevent_door_upcall_filename_size = strlen(file) + 1;
- logevent_door_upcall_filename = kmem_alloc(
- logevent_door_upcall_filename_size, KM_SLEEP);
- (void) strcpy(logevent_door_upcall_filename, file);
+ if (event_door != NULL)
+ door_ki_rele(event_door);
+ /* Establish door connection with user event daemon (syseventd) */
+ if (door_ki_open(logevent_door_upcall_filename, &event_door) != 0)
+ event_door = NULL;
+
+ mutex_exit(&event_door_mutex);
/*
* We are called when syseventd restarts. Move all sent, but
diff --git a/usr/src/uts/common/smbsrv/smb_ioctl.h b/usr/src/uts/common/smbsrv/smb_ioctl.h
index 3a94802b56..84d1081c43 100644
--- a/usr/src/uts/common/smbsrv/smb_ioctl.h
+++ b/usr/src/uts/common/smbsrv/smb_ioctl.h
@@ -20,6 +20,7 @@
*/
/*
* Copyright (c) 2007, 2010, Oracle and/or its affiliates. All rights reserved.
+ * Copyright 2011 Nexenta Systems, Inc. All rights reserved.
*/
#ifndef _SMB_IOCTL_H_
@@ -158,6 +159,7 @@ typedef struct smb_ioc_cfg {
int32_t secmode;
int32_t ipv6_enable;
int32_t print_enable;
+ int32_t traverse_mounts;
uint32_t exec_flags;
smb_version_t version;
char nbdomain[NETBIOS_NAME_SZ];
diff --git a/usr/src/uts/common/smbsrv/smb_kproto.h b/usr/src/uts/common/smbsrv/smb_kproto.h
index a0c6766406..3006153d08 100644
--- a/usr/src/uts/common/smbsrv/smb_kproto.h
+++ b/usr/src/uts/common/smbsrv/smb_kproto.h
@@ -173,9 +173,6 @@ SMB_COM_DECL(write_raw);
SMB_NT_TRANSACT_DECL(nt_transact_create);
-int smb_notify_init(void);
-void smb_notify_fini(void);
-
smb_sdrc_t smb_nt_transact_notify_change(smb_request_t *, smb_xa_t *);
smb_sdrc_t smb_nt_transact_query_security_info(smb_request_t *, smb_xa_t *);
smb_sdrc_t smb_nt_transact_set_security_info(smb_request_t *, smb_xa_t *);
@@ -208,8 +205,6 @@ void smb_close_all_connections(void);
int smb_net_id(uint32_t);
-void smb_process_file_notify_change_queue(smb_ofile_t *of);
-
/*
* oplock functions - node operations
*/
@@ -446,7 +441,10 @@ uint32_t smb_node_open_check(smb_node_t *, uint32_t, uint32_t);
DWORD smb_node_rename_check(smb_node_t *);
DWORD smb_node_delete_check(smb_node_t *);
boolean_t smb_node_share_check(smb_node_t *);
-void smb_node_notify_change(smb_node_t *);
+
+void smb_node_fcn_subscribe(smb_node_t *, smb_request_t *);
+void smb_node_fcn_unsubscribe(smb_node_t *, smb_request_t *);
+void smb_node_notify_change(smb_node_t *, uint_t, const char *);
void smb_node_notify_parents(smb_node_t *);
int smb_node_getattr(smb_request_t *, smb_node_t *, smb_attr_t *);
int smb_node_setattr(smb_request_t *, smb_node_t *, cred_t *,
@@ -477,9 +475,9 @@ void smb_vfs_rele(smb_export_t *, vfs_t *);
void smb_vfs_rele_all(smb_export_t *);
/* NOTIFY CHANGE */
-void smb_process_session_notify_change_queue(smb_session_t *, smb_tree_t *);
-void smb_process_node_notify_change_queue(smb_node_t *);
-void smb_reply_specific_cancel_request(smb_request_t *);
+
+void smb_notify_event(smb_node_t *, uint_t, const char *);
+void smb_notify_file_closed(smb_ofile_t *of);
void smb_fem_fcn_install(smb_node_t *);
void smb_fem_fcn_uninstall(smb_node_t *);
@@ -588,11 +586,13 @@ void smb_odir_delete(void *);
int smb_odir_read(smb_request_t *, smb_odir_t *,
smb_odirent_t *, boolean_t *);
int smb_odir_read_fileinfo(smb_request_t *, smb_odir_t *,
- smb_fileinfo_t *, boolean_t *);
+ smb_fileinfo_t *, uint16_t *);
int smb_odir_read_streaminfo(smb_request_t *, smb_odir_t *,
smb_streaminfo_t *, boolean_t *);
void smb_odir_save_cookie(smb_odir_t *, int, uint32_t cookie);
+void smb_odir_save_fname(smb_odir_t *, uint32_t, const char *);
+
void smb_odir_resume_at(smb_odir_t *, smb_odir_resume_t *);
/*
diff --git a/usr/src/uts/common/smbsrv/smb_ktypes.h b/usr/src/uts/common/smbsrv/smb_ktypes.h
index 8a7b6773e2..53bceab332 100644
--- a/usr/src/uts/common/smbsrv/smb_ktypes.h
+++ b/usr/src/uts/common/smbsrv/smb_ktypes.h
@@ -20,7 +20,7 @@
*/
/*
* Copyright (c) 2008, 2010, Oracle and/or its affiliates. All rights reserved.
- * Copyright 2011 Nexenta Systems, Inc. All rights reserved.
+ * Copyright 2012 Nexenta Systems, Inc. All rights reserved.
*/
/*
@@ -452,12 +452,18 @@ typedef struct {
} smb_rwx_t;
/* NOTIFY CHANGE */
+typedef struct smb_node_fcn {
+ kmutex_t fcn_mutex;
+ uint32_t fcn_count;
+ list_t fcn_watchers; /* smb_request_t, sr_ncr.nc_lnd */
+} smb_node_fcn_t;
typedef struct smb_notify_change_req {
- list_node_t nc_lnd;
- struct smb_node *nc_node;
- uint32_t nc_reply_type;
+ list_node_t nc_lnd; /* n_fcn.fcn_watchers */
+ kcondvar_t nc_cv; /* prot: sr_mutex */
uint32_t nc_flags;
+ uint32_t nc_action;
+ char *nc_fname;
} smb_notify_change_req_t;
/*
@@ -638,6 +644,7 @@ typedef struct smb_node {
volatile int waiting_event;
smb_times_t n_timestamps;
u_offset_t n_allocsz;
+ smb_node_fcn_t n_fcn;
smb_oplock_t n_oplock;
struct smb_node *n_dnode;
struct smb_node *n_unode;
@@ -652,10 +659,6 @@ typedef struct smb_node {
#define NODE_FLAGS_DFSLINK 0x00002000
#define NODE_FLAGS_VFSROOT 0x00004000
#define NODE_FLAGS_SYSTEM 0x00008000
-#define NODE_FLAGS_WATCH_TREE 0x10000000
-#define NODE_FLAGS_NOTIFY_CHANGE \
- (NODE_FLAGS_WATCH_TREE | FILE_NOTIFY_VALID_MASK)
-#define NODE_FLAGS_CHANGED 0x08000000
#define NODE_FLAGS_WRITE_THROUGH 0x00100000
#define NODE_XATTR_DIR 0x01000000
#define NODE_FLAGS_DELETE_ON_CLOSE 0x40000000
@@ -1029,6 +1032,7 @@ typedef struct smb_user {
#define SMB_TREE_QUOTA 0x00010000
#define SMB_TREE_DFSROOT 0x00020000
#define SMB_TREE_SPARSE 0x00040000
+#define SMB_TREE_TRAVERSE_MOUNTS 0x00080000
typedef enum {
SMB_TREE_STATE_CONNECTED = 0,
@@ -1103,12 +1107,16 @@ typedef struct smb_tree {
smb_tree_has_feature((sr)->tid_tree, SMB_TREE_SHORTNAMES) : 0)
/*
- * SMB_TREE_CONTAINS_NODE is used to check that a node is in the same
- * file system as the tree.
+ * SMB_TREE_CONTAINS_NODE is used to check if a node is on the same
+ * file system as the tree's root filesystem, or if mount point traversal
+ * should be allowed. Note that this is also called in some cases with
+ * sr=NULL, where it is expected to evaluate to TRUE.
*/
+
#define SMB_TREE_CONTAINS_NODE(sr, node) \
- (((sr) && (sr)->tid_tree) ? \
- (SMB_TREE_VFS((sr)->tid_tree) == SMB_NODE_VFS(node)) : 1)
+ ((sr) == NULL || (sr)->tid_tree == NULL || \
+ SMB_TREE_VFS((sr)->tid_tree) == SMB_NODE_VFS(node) || \
+ smb_tree_has_feature((sr)->tid_tree, SMB_TREE_TRAVERSE_MOUNTS))
/*
* SMB_OFILE_IS_READONLY reflects whether an ofile is readonly or not.
@@ -1262,6 +1270,7 @@ typedef enum {
} smb_odir_state_t;
typedef enum {
+ SMB_ODIR_RESUME_CONT,
SMB_ODIR_RESUME_IDX,
SMB_ODIR_RESUME_COOKIE,
SMB_ODIR_RESUME_FNAME
@@ -1301,9 +1310,11 @@ typedef struct smb_odir {
edirent_t *u_edp;
dirent64_t *u_dp;
} d_u;
+ uint32_t d_last_cookie;
uint32_t d_cookies[SMB_MAX_SEARCH];
char d_pattern[MAXNAMELEN];
char d_buf[SMB_ODIR_BUFSIZE];
+ char d_last_name[MAXNAMELEN];
} smb_odir_t;
#define d_bufptr d_u.u_bufptr
#define d_edp d_u.u_edp
@@ -1318,7 +1329,7 @@ typedef struct smb_odirent {
typedef struct smb_fileinfo {
char fi_name[MAXNAMELEN];
char fi_shortname[SMB_SHORTNAMELEN];
- uint32_t fi_cookie;
+ uint32_t fi_cookie; /* Dir offset (of next entry) */
uint32_t fi_dosattr; /* DOS attributes */
uint64_t fi_nodeid; /* file system node id */
uint64_t fi_size; /* file size in bytes */
@@ -1594,7 +1605,6 @@ typedef struct smb_request {
kmutex_t sr_mutex;
list_node_t sr_session_lnd;
smb_req_state_t sr_state;
- boolean_t sr_keep;
kmem_cache_t *sr_cache;
struct smb_server *sr_server;
pid_t *sr_pid;
diff --git a/usr/src/uts/common/smbsrv/smbinfo.h b/usr/src/uts/common/smbsrv/smbinfo.h
index 18e259c980..0d7f551699 100644
--- a/usr/src/uts/common/smbsrv/smbinfo.h
+++ b/usr/src/uts/common/smbsrv/smbinfo.h
@@ -20,6 +20,7 @@
*/
/*
* Copyright (c) 2007, 2010, Oracle and/or its affiliates. All rights reserved.
+ * Copyright 2011 Nexenta Systems, Inc. All rights reserved.
*/
#ifndef _SMBSRV_SMBINFO_H
@@ -126,6 +127,7 @@ typedef struct smb_kmod_cfg {
int32_t skc_secmode;
int32_t skc_ipv6_enable;
int32_t skc_print_enable;
+ int32_t skc_traverse_mounts;
uint32_t skc_execflags;
smb_version_t skc_version;
char skc_nbdomain[NETBIOS_NAME_SZ];
diff --git a/usr/src/uts/common/sys/cpuvar.h b/usr/src/uts/common/sys/cpuvar.h
index d4075d580b..6c07bcbc8a 100644
--- a/usr/src/uts/common/sys/cpuvar.h
+++ b/usr/src/uts/common/sys/cpuvar.h
@@ -21,6 +21,7 @@
/*
* Copyright (c) 1989, 2010, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2012 by Delphix. All rights reserved.
*/
#ifndef _SYS_CPUVAR_H
@@ -187,6 +188,9 @@ typedef struct cpu {
uintptr_t cpu_dtrace_caller; /* DTrace: caller, if any */
hrtime_t cpu_dtrace_chillmark; /* DTrace: chill mark time */
hrtime_t cpu_dtrace_chilled; /* DTrace: total chill time */
+ uint64_t cpu_dtrace_probes; /* DTrace: total probes fired */
+ hrtime_t cpu_dtrace_nsec; /* DTrace: ns in dtrace_probe */
+
volatile uint16_t cpu_mstate; /* cpu microstate */
volatile uint16_t cpu_mstate_gen; /* generation counter */
volatile hrtime_t cpu_mstate_start; /* cpu microstate start time */
diff --git a/usr/src/uts/common/sys/dumpadm.h b/usr/src/uts/common/sys/dumpadm.h
index 4e3704985d..616828bb2b 100644
--- a/usr/src/uts/common/sys/dumpadm.h
+++ b/usr/src/uts/common/sys/dumpadm.h
@@ -20,6 +20,7 @@
*/
/*
* Copyright (c) 1998, 2010, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2012 by Delphix. All rights reserved.
*/
#ifndef _SYS_DUMPADM_H
@@ -42,6 +43,7 @@ extern "C" {
#define DIOCDUMP (DDIOC | 0x16)
#define DIOCSETUUID (DDIOC | 0x17)
#define DIOCGETUUID (DDIOC | 0x18)
+#define DIOCRMDEV (DDIOC | 0x19)
/*
* Kernel-controlled dump state flags for dump_conflags
diff --git a/usr/src/uts/common/sys/usb/clients/usbser/usbftdi/uftdi_var.h b/usr/src/uts/common/sys/usb/clients/usbser/usbftdi/uftdi_var.h
index 09e3c03d97..61d802d129 100644
--- a/usr/src/uts/common/sys/usb/clients/usbser/usbftdi/uftdi_var.h
+++ b/usr/src/uts/common/sys/usb/clients/usbser/usbftdi/uftdi_var.h
@@ -22,6 +22,9 @@
* Copyright 2009 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
+/*
+ * Copyright 2013 Hans Rosenfeld <rosenfeld@grumpf.hope-2000.org>
+ */
#ifndef _USBSER_USBFTDI_UFTDI_VAR_H
#define _USBSER_USBFTDI_UFTDI_VAR_H
@@ -84,7 +87,8 @@ typedef struct uftdi_state {
int uf_bulkout_state; /* out pipe state */
usb_log_handle_t uf_lh; /* USBA log handle */
int uf_dev_state; /* USB device state */
- size_t uf_xfer_sz; /* HCI bulk xfer size */
+ size_t uf_ibuf_sz; /* input buffer size */
+ size_t uf_obuf_sz; /* output buffer size */
uftdi_pm_t *uf_pm; /* PM support */
@@ -112,7 +116,8 @@ _NOTE(DATA_READABLE_WITHOUT_LOCK(uftdi_state::{
uf_usb_events
uf_def_ph
uf_lh
- uf_xfer_sz
+ uf_ibuf_sz
+ uf_obuf_sz
uf_pm
uf_port_state
uf_cb
diff --git a/usr/src/uts/common/sys/usb/usba/hcdi.h b/usr/src/uts/common/sys/usb/usba/hcdi.h
index f9c645e6fb..5936f8b027 100644
--- a/usr/src/uts/common/sys/usb/usba/hcdi.h
+++ b/usr/src/uts/common/sys/usb/usba/hcdi.h
@@ -325,18 +325,6 @@ typedef struct hcdi_error_stats {
struct kstat_named cc_pipe_reset;
struct kstat_named cc_not_supported;
struct kstat_named cc_flushed;
-
-#ifdef NOTYETNEEDED
- /* USBA function return values */
- struct kstat_named hcdi_usb_failure;
- struct kstat_named hcdi_usb_no_resources;
- struct kstat_named hcdi_usb_no_bandwidth;
- struct kstat_named hcdi_usb_pipe_reserved;
- struct kstat_named hcdi_usb_pipe_unshareable;
- struct kstat_named hcdi_usb_not_supported;
- struct kstat_named hcdi_usb_pipe_error;
- struct kstat_named hcdi_usb_pipe_busy;
-#endif
} hcdi_error_stats_t;
/*
diff --git a/usr/src/uts/i86xpv/Makefile b/usr/src/uts/i86xpv/Makefile
index bc83eacb9a..cb0cd9611a 100644
--- a/usr/src/uts/i86xpv/Makefile
+++ b/usr/src/uts/i86xpv/Makefile
@@ -22,7 +22,7 @@
# Copyright 2007 Sun Microsystems, Inc. All rights reserved.
# Use is subject to license terms.
#
-# ident "%Z%%M% %I% %E% SMI"
+# Copyright 2013 Nexenta Systems, Inc. All rights reserved.
#
# This makefile drives the production of all implementation architecture
# dependent modules for the i86xpv architecture.
@@ -71,7 +71,8 @@ check := TARGET= check
INITIAL_TARGETS = \
genassym \
- unix
+ unix \
+ cpu/scripts
def all clean clobber clean.lint: setup genassym unix .WAIT \
$(KMODS) $(CLOSED_KMODS) $(XMODS) $(CLOSED_XMODS)
@@ -96,6 +97,7 @@ genassym unix $(KMODS): FRC
@cd $@; pwd; $(MAKE) $(NO_STATE) $(TARGET)
setup: FRC
+ @cd cpu/scripts; pwd; $(MAKE) $(TARGET)
$(XMODS): FRC
@if [ -f $@/Makefile ]; then \
diff --git a/usr/src/uts/i86xpv/amd_opteron/Makefile b/usr/src/uts/i86xpv/amd_opteron/Makefile
index bf89423451..23e03c33e3 100644
--- a/usr/src/uts/i86xpv/amd_opteron/Makefile
+++ b/usr/src/uts/i86xpv/amd_opteron/Makefile
@@ -20,6 +20,8 @@
# Copyright 2008 Sun Microsystems, Inc. All rights reserved.
# Use is subject to license terms.
#
+# Copyright 2013 Nexenta Systems, Inc. All rights reserved.
+#
#
# Path to the base of the uts directory tree (usually /usr/src/uts).
@@ -39,7 +41,7 @@ SRCDIR = ../../i86pc/cpu/amd_opteron
AO_MCA_DISP_C = $(OBJS_DIR)/ao_mca_disp.c
AO_MCA_DISP_SRC = $(SRCDIR)/ao_mca_disp.in
-AO_GENDISP = ../../i86pc/cpu/scripts/ao_gendisp
+AO_GENDISP = ../cpu/scripts/ao_gendisp
#
# Include common rules.
diff --git a/usr/src/cmd/kstat/Makefile b/usr/src/uts/i86xpv/cpu/scripts/Makefile
index 2265eb67d7..e5c08d85f6 100644
--- a/usr/src/cmd/kstat/Makefile
+++ b/usr/src/uts/i86xpv/cpu/scripts/Makefile
@@ -18,30 +18,29 @@
#
# CDDL HEADER END
#
+
#
# Copyright 2008 Sun Microsystems, Inc. All rights reserved.
# Use is subject to license terms.
#
-# ident "%Z%%M% %I% %E% SMI"
+# Copyright 2013 Nexenta Systems, Inc. All rights reserved.
#
-include ../Makefile.cmd
+PERLFILES= \
+ ao_gendisp
-PROG= kstat
+include ../../../Makefile.uts
.KEEP_STATE:
-all: $(PROG)
-
-install: all .WAIT $(ROOTPROG)
-
-_msg: $(PROG).po
-
-clean:
+def all install setup: ao_gendisp.pl $(PERLFILES)
-$(ROOTBINPROG): $(PROG)
- $(INS.file)
+# We are sharing the ao_gendisp source with the i86pc
+AO_GENDISP_PL=../../../i86pc/cpu/scripts/ao_gendisp.pl
+ao_gendisp.pl: $(AO_GENDISP_PL)
+ $(SYMLINK) $(AO_GENDISP_PL) $@
-lint:
+clean clobber:
+ $(RM) ao_gendisp.pl $(PERLFILES)
-include ../Makefile.targ
+include ../../../Makefile.targ
diff --git a/usr/src/uts/intel/ia32/os/archdep.c b/usr/src/uts/intel/ia32/os/archdep.c
index f5663b92d0..d83b16d673 100644
--- a/usr/src/uts/intel/ia32/os/archdep.c
+++ b/usr/src/uts/intel/ia32/os/archdep.c
@@ -26,6 +26,7 @@
/* All Rights Reserved */
/*
* Copyright (c) 2012, Joyent, Inc. All rights reserved.
+ * Copyright 2012 Nexenta Systems, Inc. All rights reserved.
*/
#include <sys/param.h>
@@ -1078,7 +1079,6 @@ panic_saveregs(panic_data_t *pdp, struct regs *rp)
PANICNVADD(pnv, "rbx", rp->r_rbx);
PANICNVADD(pnv, "rbp", rp->r_rbp);
PANICNVADD(pnv, "r10", rp->r_r10);
- PANICNVADD(pnv, "r10", rp->r_r10);
PANICNVADD(pnv, "r11", rp->r_r11);
PANICNVADD(pnv, "r12", rp->r_r12);
PANICNVADD(pnv, "r13", rp->r_r13);
diff --git a/usr/src/uts/intel/zfs/Makefile b/usr/src/uts/intel/zfs/Makefile
index f106577baa..be0f82115c 100644
--- a/usr/src/uts/intel/zfs/Makefile
+++ b/usr/src/uts/intel/zfs/Makefile
@@ -85,7 +85,6 @@ CERRWARN += -_gcc=-Wno-parentheses
CERRWARN += -_gcc=-Wno-unused-variable
CERRWARN += -_gcc=-Wno-unused-function
CERRWARN += -_gcc=-Wno-unused-label
-CERRWARN += -_gcc=-Wno-uninitialized
#
# Default build targets.
diff --git a/usr/src/uts/sparc/zfs/Makefile b/usr/src/uts/sparc/zfs/Makefile
index 018a9aaac2..b891e4fae1 100644
--- a/usr/src/uts/sparc/zfs/Makefile
+++ b/usr/src/uts/sparc/zfs/Makefile
@@ -89,7 +89,6 @@ CERRWARN += -_gcc=-Wno-parentheses
CERRWARN += -_gcc=-Wno-unused-variable
CERRWARN += -_gcc=-Wno-unused-function
CERRWARN += -_gcc=-Wno-unused-label
-CERRWARN += -_gcc=-Wno-uninitialized
#
# Default build targets.