From 00c885e181e7e46ef8915b6b99fcf0988409403a Mon Sep 17 00:00:00 2001 From: Jung-uk Kim Date: Tue, 10 May 2011 16:44:16 +0000 Subject: [PATCH 01/30] Add SC_PIXEL_MODE to GENERIC for amd64 and i386. Requested by: many --- sys/amd64/conf/GENERIC | 1 + sys/i386/conf/GENERIC | 1 + 2 files changed, 2 insertions(+) diff --git a/sys/amd64/conf/GENERIC b/sys/amd64/conf/GENERIC index 33c142c1ea9..c43cd3365ff 100644 --- a/sys/amd64/conf/GENERIC +++ b/sys/amd64/conf/GENERIC @@ -165,6 +165,7 @@ device splash # Splash screen and screen saver support # syscons is the default console driver, resembling an SCO console device sc +options SC_PIXEL_MODE # add support for the raster text mode device agp # support several AGP chipsets diff --git a/sys/i386/conf/GENERIC b/sys/i386/conf/GENERIC index c8f8363bf96..ec5b113fb18 100644 --- a/sys/i386/conf/GENERIC +++ b/sys/i386/conf/GENERIC @@ -170,6 +170,7 @@ device splash # Splash screen and screen saver support # syscons is the default console driver, resembling an SCO console device sc +options SC_PIXEL_MODE # add support for the raster text mode device agp # support several AGP chipsets From 693ad91c2b7bfd08f04e5adc40cc5acf7c7fc08e Mon Sep 17 00:00:00 2001 From: Marius Strobl Date: Tue, 10 May 2011 18:38:01 +0000 Subject: [PATCH 02/30] Fix a bug in r221407; this driver doesn't add the media itself. PR: 156893 --- sys/dev/mii/ip1000phy.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sys/dev/mii/ip1000phy.c b/sys/dev/mii/ip1000phy.c index 3d90e7e3478..be82d4d71a2 100644 --- a/sys/dev/mii/ip1000phy.c +++ b/sys/dev/mii/ip1000phy.c @@ -111,7 +111,7 @@ ip1000phy_attach(device_t dev) strcmp(ma->mii_data->mii_ifp->if_dname, "stge") == 0 && (miibus_get_flags(dev) & MIIF_MACPRIV0) != 0) flags |= MIIF_PHYPRIV0; - mii_phy_dev_attach(dev, flags, &ip1000phy_funcs, 0); + mii_phy_dev_attach(dev, flags, &ip1000phy_funcs, 1); return (0); } From d648297f32757dc3348386b5b16c6b804f224e8e Mon Sep 17 00:00:00 2001 From: Marius Strobl Date: Tue, 10 May 2011 18:41:46 +0000 Subject: [PATCH 03/30] Fix whitespace. --- sys/dev/mii/ip1000phy.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sys/dev/mii/ip1000phy.c b/sys/dev/mii/ip1000phy.c index be82d4d71a2..566b5b0501e 100644 --- a/sys/dev/mii/ip1000phy.c +++ b/sys/dev/mii/ip1000phy.c @@ -70,7 +70,7 @@ static devclass_t ip1000phy_devclass; static driver_t ip1000phy_driver = { "ip1000phy", ip1000phy_methods, - sizeof (struct mii_softc) + sizeof(struct mii_softc) }; DRIVER_MODULE(ip1000phy, miibus, ip1000phy_driver, ip1000phy_devclass, 0, 0); From 707b4f44791738600fa8de6b5c2df061a23dd78d Mon Sep 17 00:00:00 2001 From: Marius Strobl Date: Tue, 10 May 2011 21:18:45 +0000 Subject: [PATCH 04/30] Add an ATOMIC_CLEAR_LONG. --- sys/sparc64/include/asmacros.h | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/sys/sparc64/include/asmacros.h b/sys/sparc64/include/asmacros.h index 840959fa803..777b35a4d18 100644 --- a/sys/sparc64/include/asmacros.h +++ b/sys/sparc64/include/asmacros.h @@ -90,6 +90,17 @@ bne,pn %icc, 9b ; \ mov r3, r2 +/* + * Atomically clear a number of bits of an u_long in memory. + */ +#define ATOMIC_CLEAR_LONG(r1, r2, r3, bits) \ + ldx [r1], r2 ; \ +9: andn r2, bits, r3 ; \ + casxa [r1] ASI_N, r2, r3 ; \ + cmp r2, r3 ; \ + bne,pn %icc, 9b ; \ + mov r3, r2 + #define PCPU(member) PCPU_REG + PC_ ## member #define PCPU_ADDR(member, reg) \ add PCPU_REG, PC_ ## member, reg From ac35ff65d307b9603f635e4ec340bde799b8a5af Mon Sep 17 00:00:00 2001 From: Oleksandr Tymoshenko Date: Wed, 11 May 2011 00:52:41 +0000 Subject: [PATCH 05/30] Use new option names for NFS client and NFS server See UPDATING entry for 20110427 --- sys/mips/conf/ADM5120 | 4 ++-- sys/mips/conf/ALCHEMY | 4 ++-- sys/mips/conf/AR71XX | 4 ++-- sys/mips/conf/AR91XX_BASE | 2 +- sys/mips/conf/IDT | 4 ++-- sys/mips/conf/MALTA | 4 ++-- sys/mips/conf/MALTA64 | 4 ++-- sys/mips/conf/OCTEON1 | 6 +++--- sys/mips/conf/PB92 | 2 +- sys/mips/conf/QEMU | 4 ++-- sys/mips/conf/RT305X | 4 ++-- sys/mips/conf/SENTRY5 | 4 ++-- sys/mips/conf/XLR | 2 +- sys/mips/conf/XLR64 | 2 +- sys/mips/conf/XLRN32 | 2 +- sys/mips/conf/std.SWARM | 4 ++-- 16 files changed, 28 insertions(+), 28 deletions(-) diff --git a/sys/mips/conf/ADM5120 b/sys/mips/conf/ADM5120 index 23ff643779d..a131eceee6e 100644 --- a/sys/mips/conf/ADM5120 +++ b/sys/mips/conf/ADM5120 @@ -33,8 +33,8 @@ options KDB options SCHED_4BSD #4BSD scheduler options INET #InterNETworking -options NFSCLIENT #Network Filesystem Client -options NFS_ROOT #NFS usable as /, requires NFSCLIENT +options NFSCL #Network Filesystem Client +options NFS_ROOT #NFS usable as /, requires NFSCL options PSEUDOFS #Pseudo-filesystem framework #options _KPOSIX_PRIORITY_SCHEDULING #Posix P1003_1B real-time extensions diff --git a/sys/mips/conf/ALCHEMY b/sys/mips/conf/ALCHEMY index db343186cc7..9b078f98e3e 100644 --- a/sys/mips/conf/ALCHEMY +++ b/sys/mips/conf/ALCHEMY @@ -33,8 +33,8 @@ options KDB options SCHED_4BSD #4BSD scheduler options INET #InterNETworking -options NFSCLIENT #Network Filesystem Client -options NFS_ROOT #NFS usable as /, requires NFSCLIENT +options NFSCL #Network Filesystem Client +options NFS_ROOT #NFS usable as /, requires NFSCL options PSEUDOFS #Pseudo-filesystem framework # options _KPOSIX_PRIORITY_SCHEDULING #Posix P1003_1B real-time extensions diff --git a/sys/mips/conf/AR71XX b/sys/mips/conf/AR71XX index 71f6b1d1c4b..c340f78fb64 100644 --- a/sys/mips/conf/AR71XX +++ b/sys/mips/conf/AR71XX @@ -19,8 +19,8 @@ options KDB options SCHED_4BSD #4BSD scheduler options INET #InterNETworking -options NFSCLIENT #Network Filesystem Client -options NFS_ROOT #NFS usable as /, requires NFSCLIENT +options NFSCL #Network Filesystem Client +options NFS_ROOT #NFS usable as /, requires NFSCL options PSEUDOFS #Pseudo-filesystem framework options _KPOSIX_PRIORITY_SCHEDULING #Posix P1003_1B real-time extensions diff --git a/sys/mips/conf/AR91XX_BASE b/sys/mips/conf/AR91XX_BASE index 252b6f9f134..6f6f6cd591e 100644 --- a/sys/mips/conf/AR91XX_BASE +++ b/sys/mips/conf/AR91XX_BASE @@ -29,7 +29,7 @@ options KDB options SCHED_4BSD #4BSD scheduler options INET #InterNETworking options INET6 #InterNETworking -options NFSCLIENT #Network Filesystem Client +options NFSCL #Network Filesystem Client options PSEUDOFS #Pseudo-filesystem framework options _KPOSIX_PRIORITY_SCHEDULING #Posix P1003_1B real-time extensions diff --git a/sys/mips/conf/IDT b/sys/mips/conf/IDT index 69d821f9de5..a6c14bbba13 100644 --- a/sys/mips/conf/IDT +++ b/sys/mips/conf/IDT @@ -16,8 +16,8 @@ options KDB options SCHED_4BSD #4BSD scheduler options INET #InterNETworking -options NFSCLIENT #Network Filesystem Client -options NFS_ROOT #NFS usable as /, requires NFSCLIENT +options NFSCL #Network Filesystem Client +options NFS_ROOT #NFS usable as /, requires NFSCL options PSEUDOFS #Pseudo-filesystem framework options BOOTP diff --git a/sys/mips/conf/MALTA b/sys/mips/conf/MALTA index 3a827a2b3ad..27598fb75c4 100644 --- a/sys/mips/conf/MALTA +++ b/sys/mips/conf/MALTA @@ -44,8 +44,8 @@ options KDB options SCHED_4BSD #4BSD scheduler options INET #InterNETworking -options NFSCLIENT #Network Filesystem Client -options NFS_ROOT #NFS usable as /, requires NFSCLIENT +options NFSCL #Network Filesystem Client +options NFS_ROOT #NFS usable as /, requires NFSCL options PSEUDOFS #Pseudo-filesystem framework options _KPOSIX_PRIORITY_SCHEDULING #Posix P1003_1B real-time extensions diff --git a/sys/mips/conf/MALTA64 b/sys/mips/conf/MALTA64 index 82114e123ac..45b686255d9 100644 --- a/sys/mips/conf/MALTA64 +++ b/sys/mips/conf/MALTA64 @@ -44,8 +44,8 @@ options KDB options SCHED_4BSD #4BSD scheduler options INET #InterNETworking -options NFSCLIENT #Network Filesystem Client -options NFS_ROOT #NFS usable as /, requires NFSCLIENT +options NFSCL #Network Filesystem Client +options NFS_ROOT #NFS usable as /, requires NFSCL options PSEUDOFS #Pseudo-filesystem framework options _KPOSIX_PRIORITY_SCHEDULING #Posix P1003_1B real-time extensions diff --git a/sys/mips/conf/OCTEON1 b/sys/mips/conf/OCTEON1 index 003b1717102..2a0abcf4224 100644 --- a/sys/mips/conf/OCTEON1 +++ b/sys/mips/conf/OCTEON1 @@ -51,10 +51,10 @@ options UFS_ACL # Support for access control lists options UFS_DIRHASH # Improve performance on big directories options UFS_GJOURNAL # Enable gjournal-based UFS journaling options MD_ROOT # MD is a potential root device -options NFSCLIENT # Network Filesystem Client -options NFSSERVER # Network Filesystem Server +options NFSCL # Network Filesystem Client +options NFSD # Network Filesystem Server options NFSLOCKD # Network Lock Manager -options NFS_ROOT # NFS usable as /, requires NFSCLIENT +options NFS_ROOT # NFS usable as /, requires NFSCL options MSDOSFS # MSDOS Filesystem options CD9660 # ISO 9660 Filesystem options PROCFS # Process filesystem (requires PSEUDOFS) diff --git a/sys/mips/conf/PB92 b/sys/mips/conf/PB92 index dba70d8ea3b..230736fa3c2 100644 --- a/sys/mips/conf/PB92 +++ b/sys/mips/conf/PB92 @@ -25,7 +25,7 @@ options KDB options SCHED_4BSD #4BSD scheduler options INET #InterNETworking options INET6 -# options NFSCLIENT #Network Filesystem Client +# options NFSCL #Network Filesystem Client options PSEUDOFS #Pseudo-filesystem framework options _KPOSIX_PRIORITY_SCHEDULING #Posix P1003_1B real-time extensions options ALQ diff --git a/sys/mips/conf/QEMU b/sys/mips/conf/QEMU index fde90851fca..68fe12c21b3 100644 --- a/sys/mips/conf/QEMU +++ b/sys/mips/conf/QEMU @@ -32,8 +32,8 @@ options KDB options SCHED_4BSD #4BSD scheduler options INET #InterNETworking -options NFSCLIENT #Network Filesystem Client -options NFS_ROOT #NFS usable as /, requires NFSCLIENT +options NFSCL #Network Filesystem Client +options NFS_ROOT #NFS usable as /, requires NFSCL options PSEUDOFS #Pseudo-filesystem framework options _KPOSIX_PRIORITY_SCHEDULING #Posix P1003_1B real-time extensions diff --git a/sys/mips/conf/RT305X b/sys/mips/conf/RT305X index 50ed9c480bf..00506e3098f 100644 --- a/sys/mips/conf/RT305X +++ b/sys/mips/conf/RT305X @@ -50,8 +50,8 @@ options SCHED_ULE #options SCHED_4BSD #4BSD scheduler #options COMPAT_43 options INET #InterNETworking -options NFSCLIENT #Network Filesystem Client -options NFS_ROOT #NFS usable as /, requires NFSCLIENT +options NFSCL #Network Filesystem Client +options NFS_ROOT #NFS usable as /, requires NFSCL options PSEUDOFS #Pseudo-filesystem framework #options _KPOSIX_PRIORITY_SCHEDULING #Posix P1003_1B real-time extensions diff --git a/sys/mips/conf/SENTRY5 b/sys/mips/conf/SENTRY5 index 79ed8ca5176..94364413892 100644 --- a/sys/mips/conf/SENTRY5 +++ b/sys/mips/conf/SENTRY5 @@ -44,8 +44,8 @@ options KDB options SCHED_4BSD #4BSD scheduler options INET #InterNETworking -options NFSCLIENT #Network Filesystem Client -options NFS_ROOT #NFS usable as /, requires NFSCLIENT +options NFSCL #Network Filesystem Client +options NFS_ROOT #NFS usable as /, requires NFSCL options PSEUDOFS #Pseudo-filesystem framework options _KPOSIX_PRIORITY_SCHEDULING #Posix P1003_1B real-time extensions diff --git a/sys/mips/conf/XLR b/sys/mips/conf/XLR index 3eea1c5559a..16845f46220 100644 --- a/sys/mips/conf/XLR +++ b/sys/mips/conf/XLR @@ -67,7 +67,7 @@ options FFS # Berkeley Fast Filesystem #options SOFTUPDATES # Enable FFS soft updates support options UFS_ACL # Support for access control lists options UFS_DIRHASH # Improve performance on big directories -options NFSCLIENT +options NFSCL options NFS_ROOT # options BOOTP diff --git a/sys/mips/conf/XLR64 b/sys/mips/conf/XLR64 index b4a84dca6b6..aa3c1b39207 100644 --- a/sys/mips/conf/XLR64 +++ b/sys/mips/conf/XLR64 @@ -42,7 +42,7 @@ options FFS # Berkeley Fast Filesystem #options SOFTUPDATES # Enable FFS soft updates support options UFS_ACL # Support for access control lists options UFS_DIRHASH # Improve performance on big directories -options NFSCLIENT +options NFSCL options NFS_ROOT # options BOOTP diff --git a/sys/mips/conf/XLRN32 b/sys/mips/conf/XLRN32 index 21d3069006d..eecab94e781 100644 --- a/sys/mips/conf/XLRN32 +++ b/sys/mips/conf/XLRN32 @@ -41,7 +41,7 @@ options FFS # Berkeley Fast Filesystem #options SOFTUPDATES # Enable FFS soft updates support options UFS_ACL # Support for access control lists options UFS_DIRHASH # Improve performance on big directories -options NFSCLIENT +options NFSCL options NFS_ROOT # options BOOTP diff --git a/sys/mips/conf/std.SWARM b/sys/mips/conf/std.SWARM index 37223b713e3..1d4d76b60c9 100644 --- a/sys/mips/conf/std.SWARM +++ b/sys/mips/conf/std.SWARM @@ -20,8 +20,8 @@ options KDB options SCHED_4BSD #4BSD scheduler options INET #InterNETworking -options NFSCLIENT #Network Filesystem Client -options NFS_ROOT #NFS usable as /, requires NFSCLIENT +options NFSCL #Network Filesystem Client +options NFS_ROOT #NFS usable as /, requires NFSCL options PSEUDOFS #Pseudo-filesystem framework options _KPOSIX_PRIORITY_SCHEDULING #Posix P1003_1B real-time extensions From c454afe290c410bc09dc83ad3b9789b3c35e3b60 Mon Sep 17 00:00:00 2001 From: Adrian Chadd Date: Wed, 11 May 2011 09:47:48 +0000 Subject: [PATCH 06/30] Restore the RSSI threshold after writing the board values. This would be overwritten by the board initvals written in ah->writeIni(). --- sys/dev/ath/ath_hal/ar5416/ar5416_reset.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/sys/dev/ath/ath_hal/ar5416/ar5416_reset.c b/sys/dev/ath/ath_hal/ar5416/ar5416_reset.c index d1ccfc4f9f0..55629243be2 100644 --- a/sys/dev/ath/ath_hal/ar5416/ar5416_reset.c +++ b/sys/dev/ath/ath_hal/ar5416/ar5416_reset.c @@ -157,9 +157,6 @@ ar5416Reset(struct ath_hal *ah, HAL_OPMODE opmode, FAIL(HAL_EIO); } - /* Restore bmiss rssi & count thresholds */ - OS_REG_WRITE(ah, AR_RSSI_THR, rssiThrReg); - /* Restore TSF */ if (tsf) ar5212SetTsf64(ah, tsf); @@ -270,6 +267,9 @@ ar5416Reset(struct ath_hal *ah, HAL_OPMODE opmode, OS_REG_WRITE(ah, AR_ISR, ~0); /* cleared on write */ + /* Restore bmiss rssi & count thresholds */ + OS_REG_WRITE(ah, AR_RSSI_THR, rssiThrReg); + if (!ar5212SetChannel(ah, chan)) FAIL(HAL_EIO); From 37fb34b48b8e62c2e42bb1f00daf4bbda3b6a90d Mon Sep 17 00:00:00 2001 From: Adrian Chadd Date: Wed, 11 May 2011 10:30:31 +0000 Subject: [PATCH 07/30] Remove a now unneeded comment.. --- sys/dev/ath/ath_hal/ar5416/ar5416_cal.c | 1 - 1 file changed, 1 deletion(-) diff --git a/sys/dev/ath/ath_hal/ar5416/ar5416_cal.c b/sys/dev/ath/ath_hal/ar5416/ar5416_cal.c index 03a4ee65d35..e546daf1b97 100644 --- a/sys/dev/ath/ath_hal/ar5416/ar5416_cal.c +++ b/sys/dev/ath/ath_hal/ar5416/ar5416_cal.c @@ -263,7 +263,6 @@ ar5416InitCal(struct ath_hal *ah, const struct ieee80211_channel *chan) * higher than normal value if DC offset and noise floor cal are * triggered at the same time. */ - /* XXX this actually kicks off a NF calibration -adrian */ OS_REG_SET_BIT(ah, AR_PHY_AGC_CONTROL, AR_PHY_AGC_CONTROL_NF); /* * This sometimes takes a -lot- longer than it should. From 85191ae6e8420cbd810b7b55461456fcc750da19 Mon Sep 17 00:00:00 2001 From: Adrian Chadd Date: Wed, 11 May 2011 11:02:20 +0000 Subject: [PATCH 08/30] Remove the initial NF completion check. This is taking quite a while for some people in some situations (eg AR5418 in phk's Abusive Radio Environment). Instead, the rest of the calibration related code should ensure that a NF calibration has occured before reading NF values and kicking off another NF calibration. The channel should also likely be marked as "noisy" (CWINT) if the NF calibration takes too long. --- sys/dev/ath/ath_hal/ar5416/ar5416_cal.c | 26 ++++--------------------- 1 file changed, 4 insertions(+), 22 deletions(-) diff --git a/sys/dev/ath/ath_hal/ar5416/ar5416_cal.c b/sys/dev/ath/ath_hal/ar5416/ar5416_cal.c index e546daf1b97..d9f42da65a3 100644 --- a/sys/dev/ath/ath_hal/ar5416/ar5416_cal.c +++ b/sys/dev/ath/ath_hal/ar5416/ar5416_cal.c @@ -264,31 +264,13 @@ ar5416InitCal(struct ath_hal *ah, const struct ieee80211_channel *chan) * triggered at the same time. */ OS_REG_SET_BIT(ah, AR_PHY_AGC_CONTROL, AR_PHY_AGC_CONTROL_NF); - /* - * This sometimes takes a -lot- longer than it should. - * Just give it a bit more time. - */ - for (i = 0; i < MAX_CAL_CHECK; i++) { - if (ar5212WaitNFCalComplete(ah, 10000)) - break; - HALDEBUG(ah, HAL_DEBUG_ANY, "%s: initial NF calibration did " - "not complete in time; noisy environment (pass %d)?\n", __func__, i); - } - /* - * Although periodic and NF calibrations shouldn't run concurrently, - * this was causing the radio to not be usable on the active - * channel if the channel was busy. - * - * Instead, now simply print a warning and continue. That way if users - * report "weird crap", they should get this warning. + * This may take a while to run; make sure subsequent + * calibration routines check that this has completed + * before reading the value and triggering a subsequent + * calibration. */ - if (i >= MAX_CAL_CHECK) { - ath_hal_printf(ah, "[ath] Warning - initial NF calibration did " - "not complete in time, noisy environment?\n"); - /* return AH_FALSE; */ - } /* Initialize list pointers */ cal->cal_list = cal->cal_last = cal->cal_curr = AH_NULL; From 5645b9a093405339de940f8ee1c504f9c2373c1d Mon Sep 17 00:00:00 2001 From: Adrian Chadd Date: Wed, 11 May 2011 13:20:25 +0000 Subject: [PATCH 09/30] Remove unused variable --- sys/dev/ath/ath_hal/ar5416/ar5416_cal.c | 1 - 1 file changed, 1 deletion(-) diff --git a/sys/dev/ath/ath_hal/ar5416/ar5416_cal.c b/sys/dev/ath/ath_hal/ar5416/ar5416_cal.c index d9f42da65a3..78fcd0f048b 100644 --- a/sys/dev/ath/ath_hal/ar5416/ar5416_cal.c +++ b/sys/dev/ath/ath_hal/ar5416/ar5416_cal.c @@ -241,7 +241,6 @@ ar5416InitCal(struct ath_hal *ah, const struct ieee80211_channel *chan) { struct ar5416PerCal *cal = &AH5416(ah)->ah_cal; HAL_CHANNEL_INTERNAL *ichan; - int i; ichan = ath_hal_checkchannel(ah, chan); HALASSERT(ichan != AH_NULL); From 46dde1e6faa08d0cc781b9066a9ad9c4bdfc0e26 Mon Sep 17 00:00:00 2001 From: Adrian Chadd Date: Wed, 11 May 2011 13:22:41 +0000 Subject: [PATCH 10/30] Add a new flag - HAL_DEBUG_UNMASKABLE - which always logs a debug message (when debug is enabled) no matter what. --- sys/dev/ath/ath_hal/ah_debug.h | 1 + sys/dev/ath/ath_hal/ah_internal.h | 3 ++- 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/sys/dev/ath/ath_hal/ah_debug.h b/sys/dev/ath/ath_hal/ah_debug.h index 14dfe38aa3c..f1678eb48e2 100644 --- a/sys/dev/ath/ath_hal/ah_debug.h +++ b/sys/dev/ath/ath_hal/ah_debug.h @@ -48,6 +48,7 @@ enum { HAL_DEBUG_DFS = 0x00200000, /* DFS debugging */ HAL_DEBUG_HANG = 0x00400000, /* BB/MAC hang debugging */ + HAL_DEBUG_UNMASKABLE = 0xf0000000, /* always printed */ HAL_DEBUG_ANY = 0xffffffff }; #endif /* _ATH_AH_DEBUG_H_ */ diff --git a/sys/dev/ath/ath_hal/ah_internal.h b/sys/dev/ath/ath_hal/ah_internal.h index 1dd8dcdce52..3cfc7e625d6 100644 --- a/sys/dev/ath/ath_hal/ah_internal.h +++ b/sys/dev/ath/ath_hal/ah_internal.h @@ -517,7 +517,8 @@ extern void ath_hal_free(void *); extern int ath_hal_debug; #define HALDEBUG(_ah, __m, ...) \ do { \ - if (ath_hal_debug & (__m)) { \ + if ((__m) == HAL_DEBUG_UNMASKABLE || \ + (ath_hal_debug & (__m))) { \ DO_HALDEBUG((_ah), (__m), __VA_ARGS__); \ } \ } while(0); From 7a8796d17ddc51ee8d476acb921d8da131c54f00 Mon Sep 17 00:00:00 2001 From: Adrian Chadd Date: Wed, 11 May 2011 13:24:17 +0000 Subject: [PATCH 11/30] Make sure the chip is awake before writing to it to finally detach it. Obtained from: Atheros --- sys/dev/ath/ath_hal/ar5416/ar5416_attach.c | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/sys/dev/ath/ath_hal/ar5416/ar5416_attach.c b/sys/dev/ath/ath_hal/ar5416/ar5416_attach.c index 9ef09844bf1..d54573352c9 100644 --- a/sys/dev/ath/ath_hal/ar5416/ar5416_attach.c +++ b/sys/dev/ath/ath_hal/ar5416/ar5416_attach.c @@ -420,6 +420,12 @@ ar5416Detach(struct ath_hal *ah) HALASSERT(ah != AH_NULL); HALASSERT(ah->ah_magic == AR5416_MAGIC); + /* Make sure that chip is awake before writing to it */ + if (! ar5416SetPowerMode(ah, HAL_PM_AWAKE, AH_TRUE)) + HALDEBUG(ah, HAL_DEBUG_UNMASKABLE, + "%s: failed to wake up chip\n", + __func__); + ar5416AniDetach(ah); ar5212RfDetach(ah); ah->ah_disable(ah); From fd331bf9bbd641c444c632b9904d73cdb1bdf0b5 Mon Sep 17 00:00:00 2001 From: Adrian Chadd Date: Wed, 11 May 2011 13:25:43 +0000 Subject: [PATCH 12/30] Always log if the NF CCA load fails; so users with debugging enabled can see they're likely in a very noisy environment. --- sys/dev/ath/ath_hal/ar5416/ar5416_cal.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/sys/dev/ath/ath_hal/ar5416/ar5416_cal.c b/sys/dev/ath/ath_hal/ar5416/ar5416_cal.c index 78fcd0f048b..e39de1d76c9 100644 --- a/sys/dev/ath/ath_hal/ar5416/ar5416_cal.c +++ b/sys/dev/ath/ath_hal/ar5416/ar5416_cal.c @@ -638,8 +638,8 @@ ar5416LoadNF(struct ath_hal *ah, const struct ieee80211_channel *chan) * here, the baseband nf cal will just be capped by our present * noisefloor until the next calibration timer. */ - HALDEBUG(ah, HAL_DEBUG_ANY, "Timeout while waiting for nf " - "to load: AR_PHY_AGC_CONTROL=0x%x\n", + HALDEBUG(ah, HAL_DEBUG_UNMASKABLE, "Timeout while waiting for " + "nf to load: AR_PHY_AGC_CONTROL=0x%x\n", OS_REG_READ(ah, AR_PHY_AGC_CONTROL)); return; } From 6b00c928cb91f49898f063c251bc1794c99a3b08 Mon Sep 17 00:00:00 2001 From: Adrian Chadd Date: Wed, 11 May 2011 13:40:13 +0000 Subject: [PATCH 13/30] Make the NF calibration logic (hopefully!) more resistive to noisy environments. In setups where NF calibration can take a while, don't load the CCA and kick off a new NF calibration if the previous one hasn't yet completed. This shouldn't happen unless the environment is noisy but those exist (hi phk!). Here, if the previous NF hasn't completed when ar5416LoadNf() is run (which reads the NF), it skips updating the history buffer, loading the NF CCA array and kicking off the next NF cal. It's hoped it'll occur in the next long calibration interval. Obtained from: Atheros, ath9k, my local HAL --- sys/dev/ath/ath_hal/ar5416/ar5416_cal.c | 40 +++++++++++++++++-------- 1 file changed, 28 insertions(+), 12 deletions(-) diff --git a/sys/dev/ath/ath_hal/ar5416/ar5416_cal.c b/sys/dev/ath/ath_hal/ar5416/ar5416_cal.c index e39de1d76c9..33366609ada 100644 --- a/sys/dev/ath/ath_hal/ar5416/ar5416_cal.c +++ b/sys/dev/ath/ath_hal/ar5416/ar5416_cal.c @@ -442,6 +442,7 @@ ar5416PerCalibrationN(struct ath_hal *ah, struct ieee80211_channel *chan, struct ar5416PerCal *cal = &AH5416(ah)->ah_cal; HAL_CAL_LIST *currCal = cal->cal_curr; HAL_CHANNEL_INTERNAL *ichan; + int r; OS_MARK(ah, AH_MARK_PERCAL, chan->ic_freq); @@ -498,17 +499,24 @@ ar5416PerCalibrationN(struct ath_hal *ah, struct ieee80211_channel *chan, * Get the value from the previous NF cal * and update the history buffer. */ - ar5416GetNf(ah, chan); + r = ar5416GetNf(ah, chan); + if (r <= 0) { + /* NF calibration result isn't valid */ + HALDEBUG(ah, HAL_DEBUG_UNMASKABLE, "%s: NF calibration" + " didn't finish; delaying CCA\n", __func__); + } else { + /* + * NF calibration result is valid. + * + * Load the NF from history buffer of the current channel. + * NF is slow time-variant, so it is OK to use a + * historical value. + */ + ar5416LoadNF(ah, AH_PRIVATE(ah)->ah_curchan); - /* - * Load the NF from history buffer of the current channel. - * NF is slow time-variant, so it is OK to use a - * historical value. - */ - ar5416LoadNF(ah, AH_PRIVATE(ah)->ah_curchan); - - /* start NF calibration, without updating BB NF register*/ - ar5416StartNFCal(ah); + /* start NF calibration, without updating BB NF register*/ + ar5416StartNFCal(ah); + } } return AH_TRUE; } @@ -758,17 +766,22 @@ ar5416SanitizeNF(struct ath_hal *ah, int16_t *nf) /* * Read the NF and check it against the noise floor threshhold + * + * Return 0 if the NF calibration hadn't finished, 0 if it was + * invalid, or > 0 for a valid NF reading. */ static int16_t ar5416GetNf(struct ath_hal *ah, struct ieee80211_channel *chan) { int16_t nf, nfThresh; int i; + int retval = 0; if (ar5212IsNFCalInProgress(ah)) { HALDEBUG(ah, HAL_DEBUG_ANY, "%s: NF didn't complete in calibration window\n", __func__); nf = 0; + retval = -1; /* NF didn't finish */ } else { /* Finished NF cal, check against threshold */ int16_t nfarray[NUM_NOISEFLOOR_READINGS] = { 0 }; @@ -780,7 +793,7 @@ ar5416GetNf(struct ath_hal *ah, struct ieee80211_channel *chan) ar5416SanitizeNF(ah, nfarray); if (ar5416GetEepromNoiseFloorThresh(ah, chan, &nfThresh)) { if (nf > nfThresh) { - HALDEBUG(ah, HAL_DEBUG_ANY, + HALDEBUG(ah, HAL_DEBUG_UNMASKABLE, "%s: noise floor failed detected; " "detected %d, threshold %d\n", __func__, nf, nfThresh); @@ -791,9 +804,11 @@ ar5416GetNf(struct ath_hal *ah, struct ieee80211_channel *chan) */ chan->ic_state |= IEEE80211_CHANSTATE_CWINT; nf = 0; + retval = 0; } } else { nf = 0; + retval = 0; } /* Update MIMO channel statistics, regardless of validity or not (for now) */ for (i = 0; i < 3; i++) { @@ -804,6 +819,7 @@ ar5416GetNf(struct ath_hal *ah, struct ieee80211_channel *chan) ar5416UpdateNFHistBuff(ah, AH5416(ah)->ah_cal.nfCalHist, nfarray); ichan->rawNoiseFloor = nf; + retval = nf; } - return nf; + return retval; } From 7449d2f5cbcad3dac76b3e3f06d0e2811fd96ae3 Mon Sep 17 00:00:00 2001 From: Colin Percival Date: Wed, 11 May 2011 15:23:27 +0000 Subject: [PATCH 14/30] Make freebsd-update(8) smarter in how it handles $FreeBSD$ tags in configuration files. If the current file differs from the canonical version from the old release only due to differences in the $FreeBSD$ tag (which can happen if the system was installed from source code, depending on how the src tree was checked out) then freebsd-update will treat the file as "unmodified" and silently update it to the "clean" version in the new release. If the only change being made to a configuration file is in the $FreeBSD$ tag (e.g., for any configuration files which have been modified locally, now that we're using SVN and the $FreeBSD$ tag changes when a branch is created), freebsd-update will no longer print the diff and prompt "Does this look reasonable (y/n)?". Nagged by: pgollucci MFC after: 1 month --- usr.sbin/freebsd-update/freebsd-update.sh | 36 +++++++++++++++++++++-- 1 file changed, 33 insertions(+), 3 deletions(-) diff --git a/usr.sbin/freebsd-update/freebsd-update.sh b/usr.sbin/freebsd-update/freebsd-update.sh index 0247e3830d1..8dca87d51a8 100644 --- a/usr.sbin/freebsd-update/freebsd-update.sh +++ b/usr.sbin/freebsd-update/freebsd-update.sh @@ -2254,6 +2254,19 @@ upgrade_oldall_to_oldnew () { mv $2 $3 } +# Helper for upgrade_merge: Return zero true iff the two files differ only +# in the contents of their $FreeBSD$ tags. +samef () { + X=`sed -E 's/\\$FreeBSD.*\\$/\$FreeBSD\$/' < $1 | ${SHA256}` + Y=`sed -E 's/\\$FreeBSD.*\\$/\$FreeBSD\$/' < $2 | ${SHA256}` + + if [ $X = $Y ]; then + return 0; + else + return 1; + fi +} + # From the list of "old" files in $1, merge changes in $2 with those in $3, # and update $3 to reflect the hashes of merged files. upgrade_merge () { @@ -2337,6 +2350,14 @@ upgrade_merge () { # Ask the user to handle any files which didn't merge. while read F; do + # If the installed file differs from the version in + # the old release only due to $FreeBSD$ tag expansion + # then just use the version in the new release. + if samef merge/old/${F} merge/${OLDRELNUM}/${F}; then + cp merge/${RELNUM}/${F} merge/new/${F} + continue + fi + cat <<-EOF The following file could not be merged automatically: ${F} @@ -2351,9 +2372,18 @@ manually... # Ask the user to confirm that he likes how the result # of merging files. while read F; do - # Skip files which haven't changed. - if [ -f merge/new/${F} ] && - cmp -s merge/old/${F} merge/new/${F}; then + # Skip files which haven't changed except possibly + # in their $FreeBSD$ tags. + if [ -f merge/old/${F} ] && [ -f merge/new/${F} ] && + samef merge/old/${F} merge/new/${F}; then + continue + fi + + # Skip files where the installed file differs from + # the old file only due to $FreeBSD$ tags. + if [ -f merge/old/${F} ] && + [ -f merge/${OLDRELNUM}/${F} ] && + samef merge/old/${F} merge/${OLDRELNUM}/${F}; then continue fi From ed1d540e70e3656d6095b51f539ee835c50f7890 Mon Sep 17 00:00:00 2001 From: Adrian Chadd Date: Wed, 11 May 2011 16:44:19 +0000 Subject: [PATCH 15/30] net80211 alq bugfixes: * Track number of logged operations * call alq_post() so things are logged * network order things --- sys/net80211/ieee80211_alq.c | 15 ++++++++++++--- 1 file changed, 12 insertions(+), 3 deletions(-) diff --git a/sys/net80211/ieee80211_alq.c b/sys/net80211/ieee80211_alq.c index 1ba996ca06b..a01fb0f88cb 100644 --- a/sys/net80211/ieee80211_alq.c +++ b/sys/net80211/ieee80211_alq.c @@ -64,7 +64,8 @@ __FBSDID("$FreeBSD$"); static struct alq *ieee80211_alq; static int ieee80211_alq_lost; -static char ieee80211_alq_logfile[MAXPATHLEN] = "/tmp/net80211.log"; +static int ieee80211_alq_logged; +static char ieee80211_alq_logfile[MAXPATHLEN] = "/mnt/tmp/net80211.log"; static unsigned int ieee80211_alq_qsize = 64*1024; static int @@ -113,6 +114,8 @@ SYSCTL_INT(_net_wlan, OID_AUTO, alq_size, CTLFLAG_RW, &ieee80211_alq_qsize, 0, "In-memory log size (#records)"); SYSCTL_INT(_net_wlan, OID_AUTO, alq_lost, CTLFLAG_RW, &ieee80211_alq_lost, 0, "Debugging operations not logged"); +SYSCTL_INT(_net_wlan, OID_AUTO, alq_logged, CTLFLAG_RW, + &ieee80211_alq_logged, 0, "Debugging operations logged"); static struct ale * ieee80211_alq_get(void) @@ -122,6 +125,8 @@ ieee80211_alq_get(void) ale = alq_get(ieee80211_alq, ALQ_NOWAIT); if (!ale) ieee80211_alq_lost++; + else + ieee80211_alq_logged++; return ale; } @@ -131,14 +136,18 @@ ieee80211_alq_log(struct ieee80211vap *vap, uint8_t op, u_char *p, int l) struct ale *ale; struct ieee80211_alq_rec *r; + if (ieee80211_alq == NULL) + return; + ale = ieee80211_alq_get(); if (! ale) return; r = (struct ieee80211_alq_rec *) ale; - r->r_timestamp = ticks; + r->r_timestamp = htonl(ticks); r->r_version = 1; - r->r_wlan = vap->iv_ifp->if_dunit; + r->r_wlan = htons(vap->iv_ifp->if_dunit); r->r_op = op; memcpy(&r->r_payload, p, MIN(l, sizeof(r->r_payload))); + alq_post(ieee80211_alq, ale); } From 22a6f5e8d5564b3fade4e836ad77813309eb3131 Mon Sep 17 00:00:00 2001 From: Adrian Chadd Date: Wed, 11 May 2011 17:20:35 +0000 Subject: [PATCH 16/30] Fix up the net80211 alq logging - this commit makes it usable. * revert a local path change that shouldn't have made it to the commit * fix some indenting/wrapping * Fix the ale data copy - i should be copying into the ale data pointer, not over the ale entry itself. --- sys/net80211/ieee80211_alq.c | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/sys/net80211/ieee80211_alq.c b/sys/net80211/ieee80211_alq.c index a01fb0f88cb..0d06d4b9ef9 100644 --- a/sys/net80211/ieee80211_alq.c +++ b/sys/net80211/ieee80211_alq.c @@ -65,7 +65,7 @@ __FBSDID("$FreeBSD$"); static struct alq *ieee80211_alq; static int ieee80211_alq_lost; static int ieee80211_alq_logged; -static char ieee80211_alq_logfile[MAXPATHLEN] = "/mnt/tmp/net80211.log"; +static char ieee80211_alq_logfile[MAXPATHLEN] = "/tmp/net80211.log"; static unsigned int ieee80211_alq_qsize = 64*1024; static int @@ -84,7 +84,9 @@ ieee80211_alq_setlogging(int enable) sizeof (struct ieee80211_alq_rec), ieee80211_alq_qsize); ieee80211_alq_lost = 0; - printf("net80211: logging to %s enabled\n", ieee80211_alq_logfile); + ieee80211_alq_logged = 0; + printf("net80211: logging to %s enabled; struct size %d bytes\n", + ieee80211_alq_logfile, sizeof(struct ieee80211_alq_rec)); } else { if (ieee80211_alq) alq_close(ieee80211_alq); @@ -143,7 +145,7 @@ ieee80211_alq_log(struct ieee80211vap *vap, uint8_t op, u_char *p, int l) if (! ale) return; - r = (struct ieee80211_alq_rec *) ale; + r = (struct ieee80211_alq_rec *) ale->ae_data; r->r_timestamp = htonl(ticks); r->r_version = 1; r->r_wlan = htons(vap->iv_ifp->if_dunit); From c79f2d97bed0ffc82f6a32affe51df7b6070b66a Mon Sep 17 00:00:00 2001 From: "David E. O'Brien" Date: Wed, 11 May 2011 17:50:19 +0000 Subject: [PATCH 17/30] + DTrace as a bootstrap tool is only needed on certain older systems. + Be more consistent between BMAKE and TMAKE. + Add NO_CTF to crosstools as is done for bootstrap and build tools. Reviewed by: marcel --- Makefile.inc1 | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) diff --git a/Makefile.inc1 b/Makefile.inc1 index 8d4bec7550f..fc774f2adfd 100644 --- a/Makefile.inc1 +++ b/Makefile.inc1 @@ -246,9 +246,10 @@ TMAKE= MAKEOBJDIRPREFIX=${OBJTREE} \ ${BMAKEENV} ${MAKE} -f Makefile.inc1 \ TARGET=${TARGET} TARGET_ARCH=${TARGET_ARCH} \ DESTDIR= \ + BOOTSTRAPPING=${OSRELDATE} \ SSP_CFLAGS= \ - BOOTSTRAPPING=${OSRELDATE} -DNO_LINT -DNO_CPU_CFLAGS \ - -DNO_WARNS -DNO_CTF + -DNO_LINT \ + -DNO_CPU_CFLAGS -DNO_WARNS -DNO_CTF # cross-tools stage XMAKE= TOOLS_PREFIX=${WORLDTMP} ${BMAKE} \ @@ -829,7 +830,7 @@ buildkernel: @echo "--------------------------------------------------------------" cd ${KRNLOBJDIR}/${_kernel}; \ MAKESRCPATH=${KERNSRCDIR}/dev/aic7xxx/aicasm \ - ${MAKE} SSP_CFLAGS= -DNO_CPU_CFLAGS \ + ${MAKE} SSP_CFLAGS= -DNO_CPU_CFLAGS -DNO_CTF \ -f ${KERNSRCDIR}/dev/aic7xxx/aicasm/Makefile # XXX - Gratuitously builds aicasm in the ``makeoptions NO_MODULES'' case. .if !defined(MODULES_WITH_WORLD) && !defined(NO_MODULES) && exists(${KERNSRCDIR}/modules) @@ -1024,7 +1025,9 @@ _clang_tblgen= \ usr.bin/clang/tblgen .endif -.if ${MK_CDDL} != "no" +.if ${MK_CDDL} != "no" && \ + ${BOOTSTRAPPING} < 800038 && \ + !(${BOOTSTRAPPING} >= 700112 && ${BOOTSTRAPPING} < 799999) _dtrace_tools= cddl/usr.bin/sgsmsg cddl/lib/libctf lib/libelf \ lib/libdwarf cddl/usr.bin/ctfconvert cddl/usr.bin/ctfmerge .endif @@ -1033,6 +1036,9 @@ _dtrace_tools= cddl/usr.bin/sgsmsg cddl/lib/libctf lib/libelf \ _dtc= gnu/usr.bin/dtc .endif +# Please document (add comment) why something is in 'bootstrap-tools'. +# Try to bound the building of the bootstrap-tool to just the +# FreeBSD versions that need the tool built at this stage of the build. bootstrap-tools: .for _tool in \ ${_clang_tblgen} \ From 98cde5eede4cd3a5011330d63ab913d7e21800a6 Mon Sep 17 00:00:00 2001 From: Dmitry Chagin Date: Wed, 11 May 2011 17:57:15 +0000 Subject: [PATCH 18/30] Remove wrong comment. MFC after: 1 week. --- sys/amd64/amd64/machdep.c | 3 --- 1 file changed, 3 deletions(-) diff --git a/sys/amd64/amd64/machdep.c b/sys/amd64/amd64/machdep.c index 127b2cf9a82..94b4037c8e2 100644 --- a/sys/amd64/amd64/machdep.c +++ b/sys/amd64/amd64/machdep.c @@ -1298,9 +1298,6 @@ add_smap_entry(struct bios_smap *smap, vm_paddr_t *physmap, int *physmap_idxp) * available physical memory in the system, then test this memory and * build the phys_avail array describing the actually-available memory. * - * If we cannot accurately determine the physical memory map, then use - * value from the 0xE801 call, and failing that, the RTC. - * * Total memory size may be set by the kernel environment variable * hw.physmem or the compile-time define MAXMEM. * From c98f06c929bb8c8a81b4254bebab2fb08a98b6ce Mon Sep 17 00:00:00 2001 From: Xin LI Date: Wed, 11 May 2011 18:57:17 +0000 Subject: [PATCH 19/30] Import nc from OpenBSD 4.9. --- atomicio.c | 4 +- nc.1 | 47 +++++++++++++++++------- netcat.c | 106 +++++++++++++++++++++++++++++++++++++---------------- socks.c | 22 +++++++++-- 4 files changed, 129 insertions(+), 50 deletions(-) diff --git a/atomicio.c b/atomicio.c index e9d98b3561e..feb6f194409 100644 --- a/atomicio.c +++ b/atomicio.c @@ -1,4 +1,4 @@ -/* $OpenBSD: atomicio.c,v 1.9 2007/09/07 14:50:44 tobias Exp $ */ +/* $OpenBSD: atomicio.c,v 1.10 2011/01/08 00:47:19 jeremy Exp $ */ /* * Copyright (c) 2006 Damien Miller. All rights reserved. * Copyright (c) 2005 Anil Madhavapeddy. All rights reserved. @@ -53,7 +53,7 @@ atomicio(ssize_t (*f) (int, void *, size_t), int fd, void *_s, size_t n) case -1: if (errno == EINTR) continue; - if (errno == EAGAIN) { + if ((errno == EAGAIN) || (errno == ENOBUFS)) { (void)poll(&pfd, 1, -1); continue; } diff --git a/nc.1 b/nc.1 index 05b46f8f74d..27040065dc2 100644 --- a/nc.1 +++ b/nc.1 @@ -1,4 +1,4 @@ -.\" $OpenBSD: nc.1,v 1.55 2010/07/25 07:51:39 guenther Exp $ +.\" $OpenBSD: nc.1,v 1.57 2011/01/09 22:16:46 jeremy Exp $ .\" .\" Copyright (c) 1996 David Sacerdote .\" All rights reserved. @@ -25,7 +25,7 @@ .\" (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF .\" THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. .\" -.Dd $Mdocdate: July 3 2010 $ +.Dd $Mdocdate: January 8 2011 $ .Dt NC 1 .Os .Sh NAME @@ -40,7 +40,7 @@ .Op Fl O Ar length .Op Fl P Ar proxy_username .Op Fl p Ar source_port -.Op Fl s Ar source_ip_address +.Op Fl s Ar source .Op Fl T Ar ToS .Op Fl V Ar rtable .Op Fl w Ar timeout @@ -49,7 +49,7 @@ .Fl x Ar proxy_address Ns Oo : Ns .Ar port Oc .Xc Oc -.Op Ar hostname +.Op Ar destination .Op Ar port .Ek .Sh DESCRIPTION @@ -57,8 +57,10 @@ The .Nm (or .Nm netcat ) -utility is used for just about anything under the sun involving TCP -or UDP. +utility is used for just about anything under the sun involving TCP, +UDP, or +.Ux Ns -domain +sockets. It can open TCP connections, send UDP packets, listen on arbitrary TCP and UDP ports, do port scanning, and deal with both IPv4 and IPv6. @@ -153,8 +155,12 @@ instead of sequentially within a range or in the order that the system assigns them. .It Fl S Enables the RFC 2385 TCP MD5 signature option. -.It Fl s Ar source_ip_address +.It Fl s Ar source Specifies the IP of the interface which is used to send the packets. +For +.Ux Ns -domain +datagram sockets, specifies the local temporary socket file +to create and use so that datagrams can be received. It is an error to use this option in conjunction with the .Fl l option. @@ -179,6 +185,16 @@ Specifies to use sockets. .It Fl u Use UDP instead of the default option of TCP. +For +.Ux Ns -domain +sockets, use a datagram socket instead of a stream socket. +If a +.Ux Ns -domain +socket is used, a temporary receiving socket is created in +.Pa /tmp +unless the +.Fl s +flag is given. .It Fl V Ar rtable Set the routing table to be used. The default is 0. @@ -220,7 +236,7 @@ If the protocol is not specified, SOCKS version 5 is used. Requests that .Nm should connect to -.Ar hostname +.Ar destination using a proxy at .Ar proxy_address and @@ -238,16 +254,22 @@ It is an error to use this option in conjunction with the option. .El .Pp -.Ar hostname +.Ar destination can be a numerical IP address or a symbolic hostname (unless the .Fl n option is given). -In general, a hostname must be specified, +In general, a destination must be specified, unless the .Fl l option is given (in which case the local host is used). +For +.Ux Ns -domain +sockets, a destination is required and is the socket path to connect to +(or listen on if the +.Fl l +option is given). .Pp .Ar port can be a single integer or a range of ports. @@ -256,8 +278,7 @@ In general, a destination port must be specified, unless the .Fl U -option is given -(in which case a socket must be specified). +option is given. .Sh CLIENT/SERVER MODEL It is quite simple to build a very basic client/server model using .Nm . @@ -390,7 +411,7 @@ IP for the local end of the connection: .Pp Create and listen on a .Ux Ns -domain -socket: +stream socket: .Pp .Dl $ nc -lU /var/tmp/dsocket .Pp diff --git a/netcat.c b/netcat.c index e471182b2ad..5c81e43e859 100644 --- a/netcat.c +++ b/netcat.c @@ -1,4 +1,4 @@ -/* $OpenBSD: netcat.c,v 1.98 2010/07/03 04:44:51 guenther Exp $ */ +/* $OpenBSD: netcat.c,v 1.100 2011/01/09 22:16:46 jeremy Exp $ */ /* * Copyright (c) 2001 Eric Jackson * @@ -62,6 +62,7 @@ #define PORT_MAX 65535 #define PORT_MAX_LEN 6 +#define UNIX_DG_TMP_SOCKET_SIZE 19 /* Command Line Options */ int dflag; /* detached, no stdin */ @@ -89,6 +90,7 @@ u_int rtableid; int timeout = -1; int family = AF_UNSPEC; char *portlist[PORT_MAX+1]; +char *unix_dg_tmp_socket; void atelnet(int, unsigned char *, unsigned int); void build_ports(char *); @@ -99,6 +101,7 @@ int remote_connect(const char *, const char *, struct addrinfo); int socks_connect(const char *, const char *, struct addrinfo, const char *, const char *, struct addrinfo, int, const char *); int udptest(int); +int unix_bind(char *); int unix_connect(char *); int unix_listen(char *); void set_common_sockopts(int); @@ -117,6 +120,7 @@ main(int argc, char *argv[]) char *proxy; const char *errstr, *proxyhost = "", *proxyport = NULL; struct addrinfo proxyhints; + char unix_dg_tmp_socket_buf[UNIX_DG_TMP_SOCKET_SIZE]; ret = 1; s = 0; @@ -241,8 +245,6 @@ main(int argc, char *argv[]) /* Cruft to make sure options are clean, and used properly. */ if (argv[0] && !argv[1] && family == AF_UNIX) { - if (uflag) - errx(1, "cannot use -u and -U"); host = argv[0]; uport = NULL; } else if (argv[0] && !argv[1]) { @@ -265,6 +267,19 @@ main(int argc, char *argv[]) if (!lflag && kflag) errx(1, "must use -l with -k"); + /* Get name of temporary socket for unix datagram client */ + if ((family == AF_UNIX) && uflag && !lflag) { + if (sflag) { + unix_dg_tmp_socket = sflag; + } else { + strlcpy(unix_dg_tmp_socket_buf, "/tmp/nc.XXXXXXXXXX", + UNIX_DG_TMP_SOCKET_SIZE); + if (mktemp(unix_dg_tmp_socket_buf) == NULL) + err(1, "mktemp"); + unix_dg_tmp_socket = unix_dg_tmp_socket_buf; + } + } + /* Initialize addrinfo structure. */ if (family != AF_UNIX) { memset(&hints, 0, sizeof(struct addrinfo)); @@ -307,8 +322,12 @@ main(int argc, char *argv[]) int connfd; ret = 0; - if (family == AF_UNIX) - s = unix_listen(host); + if (family == AF_UNIX) { + if (uflag) + s = unix_bind(host); + else + s = unix_listen(host); + } /* Allow only one connection at a time, but stay alive. */ for (;;) { @@ -337,17 +356,21 @@ main(int argc, char *argv[]) if (rv < 0) err(1, "connect"); - connfd = s; + readwrite(s); } else { len = sizeof(cliaddr); connfd = accept(s, (struct sockaddr *)&cliaddr, &len); + readwrite(connfd); + close(connfd); } - readwrite(connfd); - close(connfd); if (family != AF_UNIX) close(s); + else if (uflag) { + if (connect(s, NULL, 0) < 0) + err(1, "connect"); + } if (!kflag) break; @@ -361,6 +384,8 @@ main(int argc, char *argv[]) } else ret = 1; + if (uflag) + unlink(unix_dg_tmp_socket); exit(ret); } else { @@ -420,6 +445,38 @@ main(int argc, char *argv[]) exit(ret); } +/* + * unix_bind() + * Returns a unix socket bound to the given path + */ +int +unix_bind(char *path) +{ + struct sockaddr_un sun; + int s; + + /* Create unix domain socket. */ + if ((s = socket(AF_UNIX, uflag ? SOCK_DGRAM : SOCK_STREAM, + 0)) < 0) + return (-1); + + memset(&sun, 0, sizeof(struct sockaddr_un)); + sun.sun_family = AF_UNIX; + + if (strlcpy(sun.sun_path, path, sizeof(sun.sun_path)) >= + sizeof(sun.sun_path)) { + close(s); + errno = ENAMETOOLONG; + return (-1); + } + + if (bind(s, (struct sockaddr *)&sun, SUN_LEN(&sun)) < 0) { + close(s); + return (-1); + } + return (s); +} + /* * unix_connect() * Returns a socket connected to a local unix socket. Returns -1 on failure. @@ -430,8 +487,13 @@ unix_connect(char *path) struct sockaddr_un sun; int s; - if ((s = socket(AF_UNIX, SOCK_STREAM, 0)) < 0) - return (-1); + if (uflag) { + if ((s = unix_bind(unix_dg_tmp_socket)) < 0) + return (-1); + } else { + if ((s = socket(AF_UNIX, SOCK_STREAM, 0)) < 0) + return (-1); + } (void)fcntl(s, F_SETFD, 1); memset(&sun, 0, sizeof(struct sockaddr_un)); @@ -458,28 +520,10 @@ unix_connect(char *path) int unix_listen(char *path) { - struct sockaddr_un sun; int s; - - /* Create unix domain socket. */ - if ((s = socket(AF_UNIX, SOCK_STREAM, 0)) < 0) + if ((s = unix_bind(path)) < 0) return (-1); - memset(&sun, 0, sizeof(struct sockaddr_un)); - sun.sun_family = AF_UNIX; - - if (strlcpy(sun.sun_path, path, sizeof(sun.sun_path)) >= - sizeof(sun.sun_path)) { - close(s); - errno = ENAMETOOLONG; - return (-1); - } - - if (bind(s, (struct sockaddr *)&sun, SUN_LEN(&sun)) < 0) { - close(s); - return (-1); - } - if (listen(s, 5) < 0) { close(s); return (-1); @@ -886,9 +930,9 @@ usage(int ret) { fprintf(stderr, "usage: nc [-46DdhklnrStUuvz] [-I length] [-i interval] [-O length]\n" - "\t [-P proxy_username] [-p source_port] [-s source_ip_address] [-T ToS]\n" + "\t [-P proxy_username] [-p source_port] [-s source] [-T ToS]\n" "\t [-V rtable] [-w timeout] [-X proxy_protocol]\n" - "\t [-x proxy_address[:port]] [hostname] [port]\n"); + "\t [-x proxy_address[:port]] [destination] [port]\n"); if (ret) exit(1); } diff --git a/socks.c b/socks.c index b38dff741e1..71108d543b3 100644 --- a/socks.c +++ b/socks.c @@ -1,4 +1,4 @@ -/* $OpenBSD: socks.c,v 1.18 2010/04/20 07:26:35 nicm Exp $ */ +/* $OpenBSD: socks.c,v 1.19 2011/02/12 15:54:18 okan Exp $ */ /* * Copyright (c) 1999 Niklas Hallqvist. All rights reserved. @@ -222,11 +222,25 @@ socks_connect(const char *host, const char *port, if (cnt != wlen) err(1, "write failed (%zu/%zu)", cnt, wlen); - cnt = atomicio(read, proxyfd, buf, 10); - if (cnt != 10) - err(1, "read failed (%zu/10)", cnt); + cnt = atomicio(read, proxyfd, buf, 4); + if (cnt != 4) + err(1, "read failed (%zu/4)", cnt); if (buf[1] != 0) errx(1, "connection failed, SOCKS error %d", buf[1]); + switch (buf[3]) { + case SOCKS_IPV4: + cnt = atomicio(read, proxyfd, buf + 4, 6); + if (cnt != 6) + err(1, "read failed (%d/6)", cnt); + break; + case SOCKS_IPV6: + cnt = atomicio(read, proxyfd, buf + 4, 18); + if (cnt != 18) + err(1, "read failed (%d/18)", cnt); + break; + default: + errx(1, "connection failed, unsupported address type"); + } } else if (socksv == 4) { /* This will exit on lookup failure */ decode_addrport(host, port, (struct sockaddr *)&addr, From c63e8fe201075982fbdf523eeee179cabb0cf376 Mon Sep 17 00:00:00 2001 From: "Andrey V. Elsukov" Date: Wed, 11 May 2011 19:59:43 +0000 Subject: [PATCH 20/30] Add basic metadata integrity check. In case when partition table was probed and read successfull, but it contains invalid values (e.g. overlapped partitions, offset or size is out of bounds), then table will be rejected. MFC after: 1 month --- sys/geom/part/g_part.c | 49 +++++++++++++++++++++++++++++++++++++++++- 1 file changed, 48 insertions(+), 1 deletion(-) diff --git a/sys/geom/part/g_part.c b/sys/geom/part/g_part.c index 437914a15f4..aa5444e3c8f 100644 --- a/sys/geom/part/g_part.c +++ b/sys/geom/part/g_part.c @@ -231,6 +231,48 @@ g_part_geometry(struct g_part_table *table, struct g_consumer *cp, } } +static int +g_part_check_integrity(struct g_part_table *table, struct g_consumer *cp) +{ + struct g_part_entry *e1, *e2; + struct g_provider *pp; + + pp = cp->provider; + if (table->gpt_first > table->gpt_last || + table->gpt_last > pp->mediasize / pp->sectorsize - 1) + goto fail; + + LIST_FOREACH(e1, &table->gpt_entry, gpe_entry) { + if (e1->gpe_deleted || e1->gpe_internal) + continue; + if (e1->gpe_start < table->gpt_first || + e1->gpe_start > table->gpt_last || + e1->gpe_end < e1->gpe_start || + e1->gpe_end > table->gpt_last) + goto fail; + e2 = e1; + while ((e2 = LIST_NEXT(e2, gpe_entry)) != NULL) { + if (e2->gpe_deleted || e2->gpe_internal) + continue; + if (e1->gpe_start >= e2->gpe_start && + e1->gpe_start <= e2->gpe_end) + goto fail; + if (e1->gpe_end >= e2->gpe_start && + e1->gpe_end <= e2->gpe_end) + goto fail; + if (e1->gpe_start < e2->gpe_start && + e1->gpe_end > e2->gpe_end) + goto fail; + } + } + return (0); +fail: + if (bootverbose) + printf("GEOM_PART: integrity check failed (%s, %s)\n", + pp->name, table->gpt_scheme->name); + return (EINVAL); +} + struct g_part_entry * g_part_new_entry(struct g_part_table *table, int index, quad_t start, quad_t end) @@ -1308,11 +1350,13 @@ g_part_ctl_undo(struct gctl_req *req, struct g_part_parms *gpp) } error = G_PART_READ(table, cp); + if (error) + goto fail; + error = g_part_check_integrity(table, cp); if (error) goto fail; g_topology_lock(); - LIST_FOREACH(entry, &table->gpt_entry, gpe_entry) { if (!entry->gpe_internal) g_part_new_provider(gp, table, entry); @@ -1771,6 +1815,9 @@ g_part_taste(struct g_class *mp, struct g_provider *pp, int flags __unused) g_part_geometry(table, cp, pp->mediasize / pp->sectorsize); error = G_PART_READ(table, cp); + if (error) + goto fail; + error = g_part_check_integrity(table, cp); if (error) goto fail; From 73e3bb6563a71037ba6430402fd74f64fb470f72 Mon Sep 17 00:00:00 2001 From: Jack F Vogel Date: Wed, 11 May 2011 20:31:27 +0000 Subject: [PATCH 21/30] Chipset support for the new Intel Panther Point PCH, thanks to Seth Heasley for preparing the changes. --- sys/dev/ahci/ahci.c | 10 +++++++++- sys/dev/ata/ata-pci.h | 13 ++++++++++++ sys/dev/ata/chipsets/ata-intel.c | 12 +++++++++++ sys/dev/ichsmb/ichsmb_pci.c | 4 ++++ sys/dev/ichwd/ichwd.c | 34 +++++++++++++++++++++++++++++++- sys/dev/ichwd/ichwd.h | 32 ++++++++++++++++++++++++++++++ sys/dev/sound/pci/hda/hdac.c | 2 ++ 7 files changed, 105 insertions(+), 2 deletions(-) diff --git a/sys/dev/ahci/ahci.c b/sys/dev/ahci/ahci.c index f26bf3b497a..6ff8f9d72ef 100644 --- a/sys/dev/ahci/ahci.c +++ b/sys/dev/ahci/ahci.c @@ -164,10 +164,18 @@ static struct { {0x1c038086, 0x00, "Intel Cougar Point", 0}, {0x1c048086, 0x00, "Intel Cougar Point", 0}, {0x1c058086, 0x00, "Intel Cougar Point", 0}, - {0x23238086, 0x00, "Intel DH89xxCC", 0}, {0x1d028086, 0x00, "Intel Patsburg", 0}, {0x1d048086, 0x00, "Intel Patsburg", 0}, {0x1d068086, 0x00, "Intel Patsburg", 0}, + {0x1e028086, 0x00, "Intel Panther Point", 0}, + {0x1e038086, 0x00, "Intel Panther Point", 0}, + {0x1e048086, 0x00, "Intel Panther Point", 0}, + {0x1e058086, 0x00, "Intel Panther Point", 0}, + {0x1e068086, 0x00, "Intel Panther Point", 0}, + {0x1e078086, 0x00, "Intel Panther Point", 0}, + {0x1e0e8086, 0x00, "Intel Panther Point", 0}, + {0x1e0f8086, 0x00, "Intel Panther Point", 0}, + {0x23238086, 0x00, "Intel DH89xxCC", 0}, {0x2361197b, 0x00, "JMicron JMB361", AHCI_Q_NOFORCE}, {0x2363197b, 0x00, "JMicron JMB363", AHCI_Q_NOFORCE}, {0x2365197b, 0x00, "JMicron JMB365", AHCI_Q_NOFORCE}, diff --git a/sys/dev/ata/ata-pci.h b/sys/dev/ata/ata-pci.h index d4395d6606c..51064f6d7d5 100644 --- a/sys/dev/ata/ata-pci.h +++ b/sys/dev/ata/ata-pci.h @@ -233,6 +233,19 @@ struct ata_pci_controller { #define ATA_PBG_R2 0x1d068086 #define ATA_PBG_S2 0x1d088086 +#define ATA_PPT_S1 0x1e008086 +#define ATA_PPT_S2 0x1e018086 +#define ATA_PPT_AH1 0x1e028086 +#define ATA_PPT_AH2 0x1e038086 +#define ATA_PPT_R1 0x1e048086 +#define ATA_PPT_R2 0x1e058086 +#define ATA_PPT_R3 0x1e068086 +#define ATA_PPT_R4 0x1e078086 +#define ATA_PPT_S3 0x1e088086 +#define ATA_PPT_S4 0x1e098086 +#define ATA_PPT_R5 0x1e0e8086 +#define ATA_PPT_R6 0x1e0f8086 + #define ATA_I31244 0x32008086 #define ATA_ISCH 0x811a8086 #define ATA_DH89XXCC 0x23238086 diff --git a/sys/dev/ata/chipsets/ata-intel.c b/sys/dev/ata/chipsets/ata-intel.c index 7cf3d0d7a2e..3b514db9ad2 100644 --- a/sys/dev/ata/chipsets/ata-intel.c +++ b/sys/dev/ata/chipsets/ata-intel.c @@ -181,6 +181,18 @@ ata_intel_probe(device_t dev) { ATA_PBG_R1, 0, INTEL_AHCI, 0, ATA_SA300, "Patsburg" }, { ATA_PBG_R2, 0, INTEL_AHCI, 0, ATA_SA300, "Patsburg" }, { ATA_PBG_S2, 0, INTEL_6CH2, 0, ATA_SA300, "Patsburg" }, + { ATA_PPT_S1, 0, INTEL_6CH, 0, ATA_SA300, "Panther Point" }, + { ATA_PPT_S2, 0, INTEL_6CH, 0, ATA_SA300, "Panther Point" }, + { ATA_PPT_AH1, 0, INTEL_AHCI, 0, ATA_SA300, "Panther Point" }, + { ATA_PPT_AH2, 0, INTEL_AHCI, 0, ATA_SA300, "Panther Point" }, + { ATA_PPT_R1, 0, INTEL_AHCI, 0, ATA_SA300, "Panther Point" }, + { ATA_PPT_R2, 0, INTEL_AHCI, 0, ATA_SA300, "Panther Point" }, + { ATA_PPT_R3, 0, INTEL_AHCI, 0, ATA_SA300, "Panther Point" }, + { ATA_PPT_R4, 0, INTEL_AHCI, 0, ATA_SA300, "Panther Point" }, + { ATA_PPT_S3, 0, INTEL_6CH2, 0, ATA_SA300, "Panther Point" }, + { ATA_PPT_S4, 0, INTEL_6CH2, 0, ATA_SA300, "Panther Point" }, + { ATA_PPT_R5, 0, INTEL_AHCI, 0, ATA_SA300, "Panther Point" }, + { ATA_PPT_R6, 0, INTEL_AHCI, 0, ATA_SA300, "Panther Point" }, { ATA_I31244, 0, 0, 2, ATA_SA150, "31244" }, { ATA_ISCH, 0, 0, 1, ATA_UDMA5, "SCH" }, { ATA_DH89XXCC, 0, INTEL_AHCI, 0, ATA_SA300, "DH89xxCC" }, diff --git a/sys/dev/ichsmb/ichsmb_pci.c b/sys/dev/ichsmb/ichsmb_pci.c index aa1d0cd6559..48d6eb6e177 100644 --- a/sys/dev/ichsmb/ichsmb_pci.c +++ b/sys/dev/ichsmb/ichsmb_pci.c @@ -84,6 +84,7 @@ __FBSDID("$FreeBSD$"); #define ID_DH89XXCC 0x23308086 #define ID_PATSBURG 0x1d228086 #define ID_CPT 0x1c228086 +#define ID_PPT 0x1e228086 #define PCIS_SERIALBUS_SMBUS_PROGIF 0x00 @@ -186,6 +187,9 @@ ichsmb_pci_probe(device_t dev) case ID_CPT: device_set_desc(dev, "Intel Cougar Point SMBus controller"); break; + case ID_PPT: + device_set_desc(dev, "Intel Panther Point SMBus controller"); + break; default: return (ENXIO); } diff --git a/sys/dev/ichwd/ichwd.c b/sys/dev/ichwd/ichwd.c index b39747a2718..a66826e4c6e 100644 --- a/sys/dev/ichwd/ichwd.c +++ b/sys/dev/ichwd/ichwd.c @@ -157,9 +157,41 @@ static struct ichwd_device ichwd_devices[] = { { DEVICEID_CPT29, "Intel Cougar Point watchdog timer", 10 }, { DEVICEID_CPT30, "Intel Cougar Point watchdog timer", 10 }, { DEVICEID_CPT31, "Intel Cougar Point watchdog timer", 10 }, - { DEVICEID_DH89XXCC_LPC, "Intel DH89xxCC watchdog timer", 10 }, { DEVICEID_PATSBURG_LPC1, "Intel Patsburg watchdog timer", 10 }, { DEVICEID_PATSBURG_LPC2, "Intel Patsburg watchdog timer", 10 }, + { DEVICEID_PPT0, "Intel Panther Point watchdog timer", 10 }, + { DEVICEID_PPT1, "Intel Panther Point watchdog timer", 10 }, + { DEVICEID_PPT2, "Intel Panther Point watchdog timer", 10 }, + { DEVICEID_PPT3, "Intel Panther Point watchdog timer", 10 }, + { DEVICEID_PPT4, "Intel Panther Point watchdog timer", 10 }, + { DEVICEID_PPT5, "Intel Panther Point watchdog timer", 10 }, + { DEVICEID_PPT6, "Intel Panther Point watchdog timer", 10 }, + { DEVICEID_PPT7, "Intel Panther Point watchdog timer", 10 }, + { DEVICEID_PPT8, "Intel Panther Point watchdog timer", 10 }, + { DEVICEID_PPT9, "Intel Panther Point watchdog timer", 10 }, + { DEVICEID_PPT10, "Intel Panther Point watchdog timer", 10 }, + { DEVICEID_PPT11, "Intel Panther Point watchdog timer", 10 }, + { DEVICEID_PPT12, "Intel Panther Point watchdog timer", 10 }, + { DEVICEID_PPT13, "Intel Panther Point watchdog timer", 10 }, + { DEVICEID_PPT14, "Intel Panther Point watchdog timer", 10 }, + { DEVICEID_PPT15, "Intel Panther Point watchdog timer", 10 }, + { DEVICEID_PPT16, "Intel Panther Point watchdog timer", 10 }, + { DEVICEID_PPT17, "Intel Panther Point watchdog timer", 10 }, + { DEVICEID_PPT18, "Intel Panther Point watchdog timer", 10 }, + { DEVICEID_PPT19, "Intel Panther Point watchdog timer", 10 }, + { DEVICEID_PPT20, "Intel Panther Point watchdog timer", 10 }, + { DEVICEID_PPT21, "Intel Panther Point watchdog timer", 10 }, + { DEVICEID_PPT22, "Intel Panther Point watchdog timer", 10 }, + { DEVICEID_PPT23, "Intel Panther Point watchdog timer", 10 }, + { DEVICEID_PPT24, "Intel Panther Point watchdog timer", 10 }, + { DEVICEID_PPT25, "Intel Panther Point watchdog timer", 10 }, + { DEVICEID_PPT26, "Intel Panther Point watchdog timer", 10 }, + { DEVICEID_PPT27, "Intel Panther Point watchdog timer", 10 }, + { DEVICEID_PPT28, "Intel Panther Point watchdog timer", 10 }, + { DEVICEID_PPT29, "Intel Panther Point watchdog timer", 10 }, + { DEVICEID_PPT30, "Intel Panther Point watchdog timer", 10 }, + { DEVICEID_PPT31, "Intel Panther Point watchdog timer", 10 }, + { DEVICEID_DH89XXCC_LPC, "Intel DH89xxCC watchdog timer", 10 }, { 0, NULL, 0 }, }; diff --git a/sys/dev/ichwd/ichwd.h b/sys/dev/ichwd/ichwd.h index 0d93ef2ae9c..bb809d83941 100644 --- a/sys/dev/ichwd/ichwd.h +++ b/sys/dev/ichwd/ichwd.h @@ -99,6 +99,38 @@ struct ichwd_softc { #define DEVICEID_CPT31 0x1c5f #define DEVICEID_PATSBURG_LPC1 0x1d40 #define DEVICEID_PATSBURG_LPC2 0x1d41 +#define DEVICEID_PPT0 0x1e40 +#define DEVICEID_PPT1 0x1e41 +#define DEVICEID_PPT2 0x1e42 +#define DEVICEID_PPT3 0x1e43 +#define DEVICEID_PPT4 0x1e44 +#define DEVICEID_PPT5 0x1e45 +#define DEVICEID_PPT6 0x1e46 +#define DEVICEID_PPT7 0x1e47 +#define DEVICEID_PPT8 0x1e48 +#define DEVICEID_PPT9 0x1e49 +#define DEVICEID_PPT10 0x1e4a +#define DEVICEID_PPT11 0x1e4b +#define DEVICEID_PPT12 0x1e4c +#define DEVICEID_PPT13 0x1e4d +#define DEVICEID_PPT14 0x1e4e +#define DEVICEID_PPT15 0x1e4f +#define DEVICEID_PPT16 0x1e50 +#define DEVICEID_PPT17 0x1e51 +#define DEVICEID_PPT18 0x1e52 +#define DEVICEID_PPT19 0x1e53 +#define DEVICEID_PPT20 0x1e54 +#define DEVICEID_PPT21 0x1e55 +#define DEVICEID_PPT22 0x1e56 +#define DEVICEID_PPT23 0x1e57 +#define DEVICEID_PPT24 0x1e58 +#define DEVICEID_PPT25 0x1e59 +#define DEVICEID_PPT26 0x1e5a +#define DEVICEID_PPT27 0x1e5b +#define DEVICEID_PPT28 0x1e5c +#define DEVICEID_PPT29 0x1e5d +#define DEVICEID_PPT30 0x1e5e +#define DEVICEID_PPT31 0x1e5f #define DEVICEID_DH89XXCC_LPC 0x2310 #define DEVICEID_82801AA 0x2410 #define DEVICEID_82801AB 0x2420 diff --git a/sys/dev/sound/pci/hda/hdac.c b/sys/dev/sound/pci/hda/hdac.c index 0110035ef79..e13e35d338e 100644 --- a/sys/dev/sound/pci/hda/hdac.c +++ b/sys/dev/sound/pci/hda/hdac.c @@ -142,6 +142,7 @@ SND_DECLARE_FILE("$FreeBSD$"); #define INTEL_VENDORID 0x8086 #define HDA_INTEL_CPT HDA_MODEL_CONSTRUCT(INTEL, 0x1c20) #define HDA_INTEL_PATSBURG HDA_MODEL_CONSTRUCT(INTEL, 0x1d20) +#define HDA_INTEL_PPT1 HDA_MODEL_CONSTRUCT(INTEL, 0x1e20) #define HDA_INTEL_82801F HDA_MODEL_CONSTRUCT(INTEL, 0x2668) #define HDA_INTEL_63XXESB HDA_MODEL_CONSTRUCT(INTEL, 0x269a) #define HDA_INTEL_82801G HDA_MODEL_CONSTRUCT(INTEL, 0x27d8) @@ -495,6 +496,7 @@ static const struct { } hdac_devices[] = { { HDA_INTEL_CPT, "Intel Cougar Point", 0 }, { HDA_INTEL_PATSBURG,"Intel Patsburg", 0 }, + { HDA_INTEL_PPT, "Intel Panther Point", 0 }, { HDA_INTEL_82801F, "Intel 82801F", 0 }, { HDA_INTEL_63XXESB, "Intel 631x/632xESB", 0 }, { HDA_INTEL_82801G, "Intel 82801G", 0 }, From b2901e999b720aa72b85f9e30763007c76bebecd Mon Sep 17 00:00:00 2001 From: Andrew Thompson Date: Wed, 11 May 2011 21:47:30 +0000 Subject: [PATCH 22/30] Move the three geom kprocs as threads under a single pid. Reviewed by: julian --- sys/geom/geom_kern.c | 71 ++++++++++++++++---------------------------- 1 file changed, 25 insertions(+), 46 deletions(-) diff --git a/sys/geom/geom_kern.c b/sys/geom/geom_kern.c index 5e7e27461c8..1744d170160 100644 --- a/sys/geom/geom_kern.c +++ b/sys/geom/geom_kern.c @@ -44,6 +44,7 @@ __FBSDID("$FreeBSD$"); #include #include #include +#include #include #include #include @@ -57,7 +58,10 @@ MALLOC_DEFINE(M_GEOM, "GEOM", "Geom data structures"); struct sx topology_lock; -static struct proc *g_up_proc; +static struct proc *g_proc; +static struct thread *g_up_td; +static struct thread *g_down_td; +static struct thread *g_event_td; int g_debugflags; int g_collectstats = 1; @@ -82,71 +86,43 @@ int g_shutdown; */ static void -g_up_procbody(void) +g_up_procbody(void *arg) { - struct proc *p = g_up_proc; - struct thread *tp = FIRST_THREAD_IN_PROC(p); mtx_assert(&Giant, MA_NOTOWNED); - thread_lock(tp); - sched_prio(tp, PRIBIO); - thread_unlock(tp); + thread_lock(g_up_td); + sched_prio(g_up_td, PRIBIO); + thread_unlock(g_up_td); for(;;) { - g_io_schedule_up(tp); + g_io_schedule_up(g_up_td); } } -static struct kproc_desc g_up_kp = { - "g_up", - g_up_procbody, - &g_up_proc, -}; - -static struct proc *g_down_proc; - static void -g_down_procbody(void) +g_down_procbody(void *arg) { - struct proc *p = g_down_proc; - struct thread *tp = FIRST_THREAD_IN_PROC(p); mtx_assert(&Giant, MA_NOTOWNED); - thread_lock(tp); - sched_prio(tp, PRIBIO); - thread_unlock(tp); + thread_lock(g_down_td); + sched_prio(g_down_td, PRIBIO); + thread_unlock(g_down_td); for(;;) { - g_io_schedule_down(tp); + g_io_schedule_down(g_down_td); } } -static struct kproc_desc g_down_kp = { - "g_down", - g_down_procbody, - &g_down_proc, -}; - -static struct proc *g_event_proc; - static void -g_event_procbody(void) +g_event_procbody(void *arg) { - struct proc *p = g_event_proc; - struct thread *tp = FIRST_THREAD_IN_PROC(p); mtx_assert(&Giant, MA_NOTOWNED); - thread_lock(tp); - sched_prio(tp, PRIBIO); - thread_unlock(tp); + thread_lock(g_event_td); + sched_prio(g_event_td, PRIBIO); + thread_unlock(g_event_td); g_run_events(); /* NOTREACHED */ } -static struct kproc_desc g_event_kp = { - "g_event", - g_event_procbody, - &g_event_proc, -}; - static void geom_shutdown(void *foo __unused) { @@ -164,9 +140,12 @@ g_init(void) g_event_init(); g_ctl_init(); mtx_lock(&Giant); - kproc_start(&g_event_kp); - kproc_start(&g_up_kp); - kproc_start(&g_down_kp); + kproc_kthread_add(g_event_procbody, NULL, &g_proc, &g_event_td, + RFHIGHPID, 0, "geom", "g_event"); + kproc_kthread_add(g_up_procbody, NULL, &g_proc, &g_up_td, + RFHIGHPID, 0, "geom", "g_up"); + kproc_kthread_add(g_down_procbody, NULL, &g_proc, &g_down_td, + RFHIGHPID, 0, "geom", "g_down"); mtx_unlock(&Giant); EVENTHANDLER_REGISTER(shutdown_pre_sync, geom_shutdown, NULL, SHUTDOWN_PRI_FIRST); From 4cc96c3e8f3eda5ab4997d57519ce9560e5aafa9 Mon Sep 17 00:00:00 2001 From: Jack F Vogel Date: Thu, 12 May 2011 00:10:29 +0000 Subject: [PATCH 23/30] Correct a typo --- sys/dev/sound/pci/hda/hdac.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sys/dev/sound/pci/hda/hdac.c b/sys/dev/sound/pci/hda/hdac.c index e13e35d338e..7af53034a0c 100644 --- a/sys/dev/sound/pci/hda/hdac.c +++ b/sys/dev/sound/pci/hda/hdac.c @@ -496,7 +496,7 @@ static const struct { } hdac_devices[] = { { HDA_INTEL_CPT, "Intel Cougar Point", 0 }, { HDA_INTEL_PATSBURG,"Intel Patsburg", 0 }, - { HDA_INTEL_PPT, "Intel Panther Point", 0 }, + { HDA_INTEL_PPT1, "Intel Panther Point", 0 }, { HDA_INTEL_82801F, "Intel 82801F", 0 }, { HDA_INTEL_63XXESB, "Intel 631x/632xESB", 0 }, { HDA_INTEL_82801G, "Intel 82801G", 0 }, From 8a90965b834a047baf764d59c082d130a1e2d8ce Mon Sep 17 00:00:00 2001 From: Adrian Chadd Date: Thu, 12 May 2011 03:15:21 +0000 Subject: [PATCH 24/30] Fixes from Atheros: * If AR9130, give the chip extra time to reset * If AR5416, don't shutdown the chip during reset --- sys/dev/ath/ath_hal/ar5416/ar5416_power.c | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/sys/dev/ath/ath_hal/ar5416/ar5416_power.c b/sys/dev/ath/ath_hal/ar5416/ar5416_power.c index 9ffae9d5816..2d8c7f97277 100644 --- a/sys/dev/ath/ath_hal/ar5416/ar5416_power.c +++ b/sys/dev/ath/ath_hal/ar5416/ar5416_power.c @@ -56,7 +56,10 @@ ar5416SetPowerModeAwake(struct ath_hal *ah, int setChip) OS_REG_SET_BIT(ah, AR_RTC_RESET, AR_RTC_RESET_EN); OS_REG_SET_BIT(ah, AR_RTC_FORCE_WAKE, AR_RTC_FORCE_WAKE_EN); - OS_DELAY(50); /* Give chip the chance to awake */ + if (AR_SREV_HOWL(ah)) + OS_DELAY(10000); + else + OS_DELAY(50); /* Give chip the chance to awake */ for (i = POWER_UP_TIME / 50; i != 0; i--) { val = OS_REG_READ(ah, AR_RTC_STATUS) & AR_RTC_STATUS_M; @@ -94,7 +97,8 @@ ar5416SetPowerModeSleep(struct ath_hal *ah, int setChip) if (! AR_SREV_HOWL(ah)) OS_REG_WRITE(ah, AR_RC, AR_RC_AHB|AR_RC_HOSTIF); /* Shutdown chip. Active low */ - OS_REG_CLR_BIT(ah, AR_RTC_RESET, AR_RTC_RESET_EN); + if (! AR_SREV_OWL(ah)) + OS_REG_CLR_BIT(ah, AR_RTC_RESET, AR_RTC_RESET_EN); } } From 003df2a90f89d71a96e506635e86f27b0075c5e0 Mon Sep 17 00:00:00 2001 From: Adrian Chadd Date: Thu, 12 May 2011 03:25:24 +0000 Subject: [PATCH 25/30] Fix the half/quater rate PLL setup for AR5416, AR9160 and (beta?) AR9280 chips. Note: This doesn't "fix" half/quarter rate support for these chips; it merely fixes an oversight. Obtained from: Atheros --- sys/dev/ath/ath_hal/ar5416/ar5416_reset.c | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/sys/dev/ath/ath_hal/ar5416/ar5416_reset.c b/sys/dev/ath/ath_hal/ar5416/ar5416_reset.c index 55629243be2..c57e6b985ca 100644 --- a/sys/dev/ath/ath_hal/ar5416/ar5416_reset.c +++ b/sys/dev/ath/ath_hal/ar5416/ar5416_reset.c @@ -1389,10 +1389,12 @@ ar5416InitPLL(struct ath_hal *ah, const struct ieee80211_channel *chan) pll |= SM(0x1, AR_RTC_SOWL_PLL_CLKSEL); else if (IEEE80211_IS_CHAN_QUARTER(chan)) pll |= SM(0x2, AR_RTC_SOWL_PLL_CLKSEL); - else if (IEEE80211_IS_CHAN_5GHZ(chan)) + + if (IEEE80211_IS_CHAN_5GHZ(chan)) pll |= SM(0x28, AR_RTC_SOWL_PLL_DIV); else pll |= SM(0x2c, AR_RTC_SOWL_PLL_DIV); + } else pll |= SM(0x2c, AR_RTC_SOWL_PLL_DIV); } else if (AR_SREV_SOWL_10_OR_LATER(ah)) { @@ -1402,7 +1404,8 @@ ar5416InitPLL(struct ath_hal *ah, const struct ieee80211_channel *chan) pll |= SM(0x1, AR_RTC_SOWL_PLL_CLKSEL); else if (IEEE80211_IS_CHAN_QUARTER(chan)) pll |= SM(0x2, AR_RTC_SOWL_PLL_CLKSEL); - else if (IEEE80211_IS_CHAN_5GHZ(chan)) + + if (IEEE80211_IS_CHAN_5GHZ(chan)) pll |= SM(0x50, AR_RTC_SOWL_PLL_DIV); else pll |= SM(0x58, AR_RTC_SOWL_PLL_DIV); @@ -1415,7 +1418,8 @@ ar5416InitPLL(struct ath_hal *ah, const struct ieee80211_channel *chan) pll |= SM(0x1, AR_RTC_PLL_CLKSEL); else if (IEEE80211_IS_CHAN_QUARTER(chan)) pll |= SM(0x2, AR_RTC_PLL_CLKSEL); - else if (IEEE80211_IS_CHAN_5GHZ(chan)) + + if (IEEE80211_IS_CHAN_5GHZ(chan)) pll |= SM(0xa, AR_RTC_PLL_DIV); else pll |= SM(0xb, AR_RTC_PLL_DIV); From a5669965bda671897e4721b201207b6fbad916f1 Mon Sep 17 00:00:00 2001 From: Andriy Gapon Date: Thu, 12 May 2011 07:44:41 +0000 Subject: [PATCH 26/30] dsp/pcm: allow to mmap both read and write buffers using the same fd This brings our implementation in line with OSS specification for systems that support mmap. The change should also improve compatibility with OSS software not specifically written for FreeBSD, e.g. PulseAudio OSS plugin. Reviewed by: kib, jhb MFC after: 1 week --- sys/dev/sound/pcm/dsp.c | 56 +++++++++++++++++++++++++---------------- 1 file changed, 35 insertions(+), 21 deletions(-) diff --git a/sys/dev/sound/pcm/dsp.c b/sys/dev/sound/pcm/dsp.c index 66d0c8c13ef..8e9393109e1 100644 --- a/sys/dev/sound/pcm/dsp.c +++ b/sys/dev/sound/pcm/dsp.c @@ -34,6 +34,11 @@ #include #include +#include +#include +#include +#include + SND_DECLARE_FILE("$FreeBSD$"); static int dsp_mmap_allow_prot_exec = 0; @@ -67,6 +72,7 @@ static d_write_t dsp_write; static d_ioctl_t dsp_ioctl; static d_poll_t dsp_poll; static d_mmap_t dsp_mmap; +static d_mmap_single_t dsp_mmap_single; struct cdevsw dsp_cdevsw = { .d_version = D_VERSION, @@ -77,6 +83,7 @@ struct cdevsw dsp_cdevsw = { .d_ioctl = dsp_ioctl, .d_poll = dsp_poll, .d_mmap = dsp_mmap, + .d_mmap_single = dsp_mmap_single, .d_name = "dsp", }; @@ -2187,6 +2194,16 @@ static int dsp_mmap(struct cdev *i_dev, vm_ooffset_t offset, vm_paddr_t *paddr, int nprot, vm_memattr_t *memattr) { + + /* XXX memattr is not honored */ + *paddr = vtophys(offset); + return (0); +} + +static int +dsp_mmap_single(struct cdev *i_dev, vm_ooffset_t *offset, + vm_size_t size, struct vm_object **object, int nprot) +{ struct snddev_info *d; struct pcm_channel *wrch, *rdch, *c; @@ -2205,51 +2222,48 @@ dsp_mmap(struct cdev *i_dev, vm_ooffset_t offset, vm_paddr_t *paddr, #else if ((nprot & PROT_EXEC) && dsp_mmap_allow_prot_exec < 1) #endif - return (-1); + return (EINVAL); + + /* + * PROT_READ (alone) selects the input buffer. + * PROT_WRITE (alone) selects the output buffer. + * PROT_WRITE|PROT_READ together select the output buffer. + */ + if ((nprot & (PROT_READ | PROT_WRITE)) == 0) + return (EINVAL); d = dsp_get_info(i_dev); if (!DSP_REGISTERED(d, i_dev)) - return (-1); + return (EINVAL); PCM_GIANT_ENTER(d); getchns(i_dev, &rdch, &wrch, SD_F_PRIO_RD | SD_F_PRIO_WR); - /* - * XXX The linux api uses the nprot to select read/write buffer - * our vm system doesn't allow this, so force write buffer. - * - * This is just a quack to fool full-duplex mmap, so that at - * least playback _or_ recording works. If you really got the - * urge to make _both_ work at the same time, avoid O_RDWR. - * Just open each direction separately and mmap() it. - * - * Failure is not an option due to INVARIANTS check within - * device_pager.c, which means, we have to give up one over - * another. - */ - c = (wrch != NULL) ? wrch : rdch; - + c = ((nprot & PROT_WRITE) != 0) ? wrch : rdch; if (c == NULL || (c->flags & CHN_F_MMAP_INVALID) || - offset >= sndbuf_getsize(c->bufsoft) || + (*offset + size) > sndbuf_getsize(c->bufsoft) || (wrch != NULL && (wrch->flags & CHN_F_MMAP_INVALID)) || (rdch != NULL && (rdch->flags & CHN_F_MMAP_INVALID))) { relchns(i_dev, rdch, wrch, SD_F_PRIO_RD | SD_F_PRIO_WR); PCM_GIANT_EXIT(d); - return (-1); + return (EINVAL); } - /* XXX full-duplex quack. */ if (wrch != NULL) wrch->flags |= CHN_F_MMAP; if (rdch != NULL) rdch->flags |= CHN_F_MMAP; - *paddr = vtophys(sndbuf_getbufofs(c->bufsoft, offset)); + *offset = (vm_ooffset_t)sndbuf_getbufofs(c->bufsoft, *offset); relchns(i_dev, rdch, wrch, SD_F_PRIO_RD | SD_F_PRIO_WR); + *object = vm_pager_allocate(OBJT_DEVICE, i_dev, + size, nprot, *offset, curthread->td_ucred); PCM_GIANT_LEAVE(d); + if (*object == NULL) + return (EINVAL); return (0); } From 4b5404a9dec82a247f7298f40f2df475833f8e50 Mon Sep 17 00:00:00 2001 From: Adrian Chadd Date: Thu, 12 May 2011 10:11:24 +0000 Subject: [PATCH 27/30] Break out the AR9285 analog registers from ar5416/ar5416phy.h and put them in a new header file, ar9002/ar9285_an.h. Shuffle the AR9280 analog registers in ar5416/ar541phy.h into a contiguous spot. --- sys/dev/ath/ath_hal/ar5416/ar5416reg.h | 104 ++---------------- sys/dev/ath/ath_hal/ar9002/ar9285_cal.c | 1 + sys/dev/ath/ath_hal/ar9002/ar9285_reset.c | 1 + sys/dev/ath/ath_hal/ar9002/ar9285an.h | 124 ++++++++++++++++++++++ 4 files changed, 133 insertions(+), 97 deletions(-) create mode 100644 sys/dev/ath/ath_hal/ar9002/ar9285an.h diff --git a/sys/dev/ath/ath_hal/ar5416/ar5416reg.h b/sys/dev/ath/ath_hal/ar5416/ar5416reg.h index 88d7e02a22b..99213669c40 100644 --- a/sys/dev/ath/ath_hal/ar5416/ar5416reg.h +++ b/sys/dev/ath/ath_hal/ar5416/ar5416reg.h @@ -78,27 +78,6 @@ #define AR_RTC_DERIVED_CLK_PERIOD_S 1 #endif /* AH_SUPPORT_AR9130 */ -/* AR9280: rf long shift registers */ -#define AR_AN_RF2G1_CH0 0x7810 -#define AR_AN_RF5G1_CH0 0x7818 -#define AR_AN_RF2G1_CH1 0x7834 -#define AR_AN_RF5G1_CH1 0x783C -#define AR_AN_TOP2 0x7894 -#define AR_AN_SYNTH9 0x7868 -#define AR9285_AN_RF2G1 0x7820 -#define AR9285_AN_RF2G2 0x7824 -#define AR9285_AN_RF2G3 0x7828 -#define AR9285_AN_RF2G4 0x782C -#define AR9285_AN_RF2G6 0x7834 -#define AR9285_AN_RF2G7 0x7838 -#define AR9285_AN_RF2G8 0x783C -#define AR9285_AN_RF2G9 0x7840 -#define AR9285_AN_RXTXBB1 0x7854 -#define AR9285_AN_TOP2 0x7868 -#define AR9285_AN_TOP3 0x786c -#define AR9285_AN_TOP4 0x7870 -#define AR9285_AN_TOP4_DEFAULT 0x10142c00 - #define AR_RESET_TSF 0x8020 #define AR_RXFIFO_CFG 0x8114 #define AR_PHY_ERR_1 0x812c @@ -374,6 +353,13 @@ #define AR_RTC_PLL_CLKSEL_S 8 /* AR9280: rf long shift registers */ +#define AR_AN_RF2G1_CH0 0x7810 +#define AR_AN_RF5G1_CH0 0x7818 +#define AR_AN_RF2G1_CH1 0x7834 +#define AR_AN_RF5G1_CH1 0x783C +#define AR_AN_TOP2 0x7894 +#define AR_AN_SYNTH9 0x7868 + #define AR_AN_RF2G1_CH0_OB 0x03800000 #define AR_AN_RF2G1_CH0_OB_S 23 #define AR_AN_RF2G1_CH0_DB 0x1C000000 @@ -408,85 +394,9 @@ #define AR_AN_SYNTH9_REFDIVA 0xf8000000 #define AR_AN_SYNTH9_REFDIVA_S 27 -/* AR9285 Analog registers */ -#define AR9285_AN_RF2G1_ENPACAL 0x00000800 -#define AR9285_AN_RF2G1_ENPACAL_S 11 -#define AR9285_AN_RF2G1_PDPADRV1 0x02000000 -#define AR9285_AN_RF2G1_PDPADRV1_S 25 -#define AR9285_AN_RF2G1_PDPADRV2 0x01000000 -#define AR9285_AN_RF2G1_PDPADRV2_S 24 -#define AR9285_AN_RF2G1_PDPAOUT 0x00800000 -#define AR9285_AN_RF2G1_PDPAOUT_S 23 - -#define AR9285_AN_RF2G2_OFFCAL 0x00001000 -#define AR9285_AN_RF2G2_OFFCAL_S 12 - -#define AR9285_AN_RF2G3_PDVCCOMP 0x02000000 -#define AR9285_AN_RF2G3_PDVCCOMP_S 25 -#define AR9285_AN_RF2G3_OB_0 0x00E00000 -#define AR9285_AN_RF2G3_OB_0_S 21 -#define AR9285_AN_RF2G3_OB_1 0x001C0000 -#define AR9285_AN_RF2G3_OB_1_S 18 -#define AR9285_AN_RF2G3_OB_2 0x00038000 -#define AR9285_AN_RF2G3_OB_2_S 15 -#define AR9285_AN_RF2G3_OB_3 0x00007000 -#define AR9285_AN_RF2G3_OB_3_S 12 -#define AR9285_AN_RF2G3_OB_4 0x00000E00 -#define AR9285_AN_RF2G3_OB_4_S 9 - -#define AR9285_AN_RF2G3_DB1_0 0x000001C0 -#define AR9285_AN_RF2G3_DB1_0_S 6 -#define AR9285_AN_RF2G3_DB1_1 0x00000038 -#define AR9285_AN_RF2G3_DB1_1_S 3 -#define AR9285_AN_RF2G3_DB1_2 0x00000007 -#define AR9285_AN_RF2G3_DB1_2_S 0 - -#define AR9285_AN_RF2G4_DB1_3 0xE0000000 -#define AR9285_AN_RF2G4_DB1_3_S 29 -#define AR9285_AN_RF2G4_DB1_4 0x1C000000 -#define AR9285_AN_RF2G4_DB1_4_S 26 - -#define AR9285_AN_RF2G4_DB2_0 0x03800000 -#define AR9285_AN_RF2G4_DB2_0_S 23 -#define AR9285_AN_RF2G4_DB2_1 0x00700000 -#define AR9285_AN_RF2G4_DB2_1_S 20 -#define AR9285_AN_RF2G4_DB2_2 0x000E0000 -#define AR9285_AN_RF2G4_DB2_2_S 17 -#define AR9285_AN_RF2G4_DB2_3 0x0001C000 -#define AR9285_AN_RF2G4_DB2_3_S 14 -#define AR9285_AN_RF2G4_DB2_4 0x00003800 -#define AR9285_AN_RF2G4_DB2_4_S 11 - -#define AR9285_AN_RF2G6_CCOMP 0x00007800 -#define AR9285_AN_RF2G6_CCOMP_S 11 -#define AR9285_AN_RF2G6_OFFS 0x03f00000 -#define AR9285_AN_RF2G6_OFFS_S 20 - #define AR9271_AN_RF2G6_OFFS 0x07f00000 #define AR9271_AN_RF2G6_OFFS_S 20 -#define AR9285_AN_RF2G7_PWDDB 0x00000002 -#define AR9285_AN_RF2G7_PWDDB_S 1 -#define AR9285_AN_RF2G7_PADRVGN2TAB0 0xE0000000 -#define AR9285_AN_RF2G7_PADRVGN2TAB0_S 29 - -#define AR9285_AN_RF2G8_PADRVGN2TAB0 0x0001C000 -#define AR9285_AN_RF2G8_PADRVGN2TAB0_S 14 - -#define AR9285_AN_RXTXBB1_PDRXTXBB1 0x00000020 -#define AR9285_AN_RXTXBB1_PDRXTXBB1_S 5 -#define AR9285_AN_RXTXBB1_PDV2I 0x00000080 -#define AR9285_AN_RXTXBB1_PDV2I_S 7 -#define AR9285_AN_RXTXBB1_PDDACIF 0x00000100 -#define AR9285_AN_RXTXBB1_PDDACIF_S 8 -#define AR9285_AN_RXTXBB1_SPARE9 0x00000001 -#define AR9285_AN_RXTXBB1_SPARE9_S 0 - -#define AR9285_AN_TOP3_XPABIAS_LVL 0x0000000C -#define AR9285_AN_TOP3_XPABIAS_LVL_S 2 -#define AR9285_AN_TOP3_PWDDAC 0x00800000 -#define AR9285_AN_TOP3_PWDDAC_S 23 - /* Sleep control */ #define AR5416_SLEEP1_CAB_TIMEOUT 0xFFE00000 /* Cab timeout (TU) */ #define AR5416_SLEEP1_CAB_TIMEOUT_S 22 diff --git a/sys/dev/ath/ath_hal/ar9002/ar9285_cal.c b/sys/dev/ath/ath_hal/ar9002/ar9285_cal.c index f972ecb47f9..a743e21ef19 100644 --- a/sys/dev/ath/ath_hal/ar9002/ar9285_cal.c +++ b/sys/dev/ath/ath_hal/ar9002/ar9285_cal.c @@ -36,6 +36,7 @@ #include "ar5416/ar5416phy.h" #include "ar9002/ar9002phy.h" #include "ar9002/ar9285phy.h" +#include "ar9002/ar9285an.h" #include "ar9002/ar9285_cal.h" diff --git a/sys/dev/ath/ath_hal/ar9002/ar9285_reset.c b/sys/dev/ath/ath_hal/ar9002/ar9285_reset.c index bf0347bd157..d8087033e46 100644 --- a/sys/dev/ath/ath_hal/ar9002/ar9285_reset.c +++ b/sys/dev/ath/ath_hal/ar9002/ar9285_reset.c @@ -37,6 +37,7 @@ #include "ar5416/ar5416phy.h" #include "ar9002/ar9002phy.h" #include "ar9002/ar9285phy.h" +#include "ar9002/ar9285an.h" /* Eeprom versioning macros. Returns true if the version is equal or newer than the ver specified */ #define EEP_MINOR(_ah) \ diff --git a/sys/dev/ath/ath_hal/ar9002/ar9285an.h b/sys/dev/ath/ath_hal/ar9002/ar9285an.h new file mode 100644 index 00000000000..3b80938e3ab --- /dev/null +++ b/sys/dev/ath/ath_hal/ar9002/ar9285an.h @@ -0,0 +1,124 @@ +/* + * Copyright (c) 2008-2009 Sam Leffler, Errno Consulting + * Copyright (c) 2008 Atheros Communications, Inc. + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + * + * $FreeBSD$ + */ + +#ifndef __AR9285_AN_H__ +#define __AR9285_AN_H__ + +/* AR9285 Analog register definitions */ + +#define AR9285_AN_RF2G1 0x7820 + +#define AR9285_AN_RF2G1_ENPACAL 0x00000800 +#define AR9285_AN_RF2G1_ENPACAL_S 11 +#define AR9285_AN_RF2G1_PDPADRV1 0x02000000 +#define AR9285_AN_RF2G1_PDPADRV1_S 25 +#define AR9285_AN_RF2G1_PDPADRV2 0x01000000 +#define AR9285_AN_RF2G1_PDPADRV2_S 24 +#define AR9285_AN_RF2G1_PDPAOUT 0x00800000 +#define AR9285_AN_RF2G1_PDPAOUT_S 23 + +#define AR9285_AN_RF2G2 0x7824 + +#define AR9285_AN_RF2G2_OFFCAL 0x00001000 +#define AR9285_AN_RF2G2_OFFCAL_S 12 + +#define AR9285_AN_RF2G3 0x7828 + +#define AR9285_AN_RF2G3_PDVCCOMP 0x02000000 +#define AR9285_AN_RF2G3_PDVCCOMP_S 25 +#define AR9285_AN_RF2G3_OB_0 0x00E00000 +#define AR9285_AN_RF2G3_OB_0_S 21 +#define AR9285_AN_RF2G3_OB_1 0x001C0000 +#define AR9285_AN_RF2G3_OB_1_S 18 +#define AR9285_AN_RF2G3_OB_2 0x00038000 +#define AR9285_AN_RF2G3_OB_2_S 15 +#define AR9285_AN_RF2G3_OB_3 0x00007000 +#define AR9285_AN_RF2G3_OB_3_S 12 +#define AR9285_AN_RF2G3_OB_4 0x00000E00 +#define AR9285_AN_RF2G3_OB_4_S 9 +#define AR9285_AN_RF2G3_DB1_0 0x000001C0 +#define AR9285_AN_RF2G3_DB1_0_S 6 +#define AR9285_AN_RF2G3_DB1_1 0x00000038 +#define AR9285_AN_RF2G3_DB1_1_S 3 +#define AR9285_AN_RF2G3_DB1_2 0x00000007 +#define AR9285_AN_RF2G3_DB1_2_S 0 + +#define AR9285_AN_RF2G4 0x782C + +#define AR9285_AN_RF2G4_DB1_3 0xE0000000 +#define AR9285_AN_RF2G4_DB1_3_S 29 +#define AR9285_AN_RF2G4_DB1_4 0x1C000000 +#define AR9285_AN_RF2G4_DB1_4_S 26 + +#define AR9285_AN_RF2G4_DB2_0 0x03800000 +#define AR9285_AN_RF2G4_DB2_0_S 23 +#define AR9285_AN_RF2G4_DB2_1 0x00700000 +#define AR9285_AN_RF2G4_DB2_1_S 20 +#define AR9285_AN_RF2G4_DB2_2 0x000E0000 +#define AR9285_AN_RF2G4_DB2_2_S 17 +#define AR9285_AN_RF2G4_DB2_3 0x0001C000 +#define AR9285_AN_RF2G4_DB2_3_S 14 +#define AR9285_AN_RF2G4_DB2_4 0x00003800 +#define AR9285_AN_RF2G4_DB2_4_S 11 + +#define AR9285_AN_RF2G6 0x7834 + +#define AR9285_AN_RF2G6_CCOMP 0x00007800 +#define AR9285_AN_RF2G6_CCOMP_S 11 +#define AR9285_AN_RF2G6_OFFS 0x03f00000 +#define AR9285_AN_RF2G6_OFFS_S 20 + +#define AR9285_AN_RF2G7 0x7838 + +#define AR9285_AN_RF2G7_PWDDB 0x00000002 +#define AR9285_AN_RF2G7_PWDDB_S 1 +#define AR9285_AN_RF2G7_PADRVGN2TAB0 0xE0000000 +#define AR9285_AN_RF2G7_PADRVGN2TAB0_S 29 + +#define AR9285_AN_RF2G8 0x783C + +#define AR9285_AN_RF2G8_PADRVGN2TAB0 0x0001C000 +#define AR9285_AN_RF2G8_PADRVGN2TAB0_S 14 + +#define AR9285_AN_RF2G9 0x7840 + +#define AR9285_AN_RXTXBB1 0x7854 + +#define AR9285_AN_RXTXBB1_PDRXTXBB1 0x00000020 +#define AR9285_AN_RXTXBB1_PDRXTXBB1_S 5 +#define AR9285_AN_RXTXBB1_PDV2I 0x00000080 +#define AR9285_AN_RXTXBB1_PDV2I_S 7 +#define AR9285_AN_RXTXBB1_PDDACIF 0x00000100 +#define AR9285_AN_RXTXBB1_PDDACIF_S 8 +#define AR9285_AN_RXTXBB1_SPARE9 0x00000001 +#define AR9285_AN_RXTXBB1_SPARE9_S 0 + +#define AR9285_AN_TOP2 0x7868 + +#define AR9285_AN_TOP3 0x786c + +#define AR9285_AN_TOP3_XPABIAS_LVL 0x0000000C +#define AR9285_AN_TOP3_XPABIAS_LVL_S 2 +#define AR9285_AN_TOP3_PWDDAC 0x00800000 +#define AR9285_AN_TOP3_PWDDAC_S 23 + +#define AR9285_AN_TOP4 0x7870 +#define AR9285_AN_TOP4_DEFAULT 0x10142c00 + +#endif /* __AR9285_AN_H__ */ From 0daf62d9f5f7d2c15d00d71eb519b90516df016f Mon Sep 17 00:00:00 2001 From: Stanislav Sedov Date: Thu, 12 May 2011 10:11:39 +0000 Subject: [PATCH 28/30] - Commit work from libprocstat project. These patches add support for runtime file and processes information retrieval from the running kernel via sysctl in the form of new library, libprocstat. The library also supports KVM backend for analyzing memory crash dumps. Both procstat(1) and fstat(1) utilities have been modified to take advantage of the library (as the bonus point the fstat(1) utility no longer need superuser privileges to operate), and the procstat(1) utility is now able to display information from memory dumps as well. The newly introduced fuser(1) utility also uses this library and able to operate via sysctl and kvm backends. The library is by no means complete (e.g. KVM backend is missing vnode name resolution routines, and there're no manpages for the library itself) so I plan to improve it further. I'm commiting it so it will get wider exposure and review. We won't be able to MFC this work as it relies on changes in HEAD, which was introduced some time ago, that break kernel ABI. OTOH we may be able to merge the library with KVM backend if we really need it there. Discussed with: rwatson --- lib/Makefile | 1 + lib/libprocstat/Makefile | 36 + {usr.bin/fstat => lib/libprocstat}/cd9660.c | 43 +- lib/libprocstat/common_kvm.c | 207 +++ .../fstat.h => lib/libprocstat/common_kvm.h | 69 +- lib/libprocstat/libprocstat.c | 1306 +++++++++++++++++ lib/libprocstat/libprocstat.h | 160 ++ lib/libprocstat/libprocstat_internal.h | 39 + {usr.bin/fstat => lib/libprocstat}/msdosfs.c | 51 +- lib/libprocstat/ntfs.c | 71 + lib/libprocstat/nwfs.c | 76 + lib/libprocstat/smbfs.c | 77 + lib/libprocstat/udf.c | 102 ++ {usr.bin/fstat => lib/libprocstat}/zfs.c | 50 +- .../fstat => lib/libprocstat}/zfs/Makefile | 0 lib/libutil/Makefile | 6 +- lib/libutil/kinfo_getallproc.3 | 74 + lib/libutil/kinfo_getallproc.c | 98 ++ lib/libutil/kinfo_getproc.3 | 73 + lib/libutil/kinfo_getproc.c | 71 + lib/libutil/libutil.h | 5 + sys/kern/kern_descrip.c | 478 +++--- sys/kern/kern_proc.c | 12 +- sys/sys/user.h | 99 +- usr.bin/fstat/Makefile | 20 +- usr.bin/fstat/fstat.c | 1018 ++++--------- usr.bin/fstat/functions.h | 34 + usr.bin/fstat/fuser.1 | 148 ++ usr.bin/fstat/fuser.c | 369 +++++ usr.bin/fstat/main.c | 49 + usr.bin/procstat/Makefile | 2 +- usr.bin/procstat/procstat.c | 117 +- usr.bin/procstat/procstat.h | 20 +- usr.bin/procstat/procstat_args.c | 9 +- usr.bin/procstat/procstat_basic.c | 3 +- usr.bin/procstat/procstat_bin.c | 9 +- usr.bin/procstat/procstat_cred.c | 9 +- usr.bin/procstat/procstat_files.c | 156 +- usr.bin/procstat/procstat_kstack.c | 17 +- usr.bin/procstat/procstat_sigs.c | 9 +- usr.bin/procstat/procstat_threads.c | 11 +- usr.bin/procstat/procstat_vm.c | 7 +- 42 files changed, 3946 insertions(+), 1265 deletions(-) create mode 100644 lib/libprocstat/Makefile rename {usr.bin/fstat => lib/libprocstat}/cd9660.c (76%) create mode 100644 lib/libprocstat/common_kvm.c rename usr.bin/fstat/fstat.h => lib/libprocstat/common_kvm.h (52%) create mode 100644 lib/libprocstat/libprocstat.c create mode 100644 lib/libprocstat/libprocstat.h create mode 100644 lib/libprocstat/libprocstat_internal.h rename {usr.bin/fstat => lib/libprocstat}/msdosfs.c (81%) create mode 100644 lib/libprocstat/ntfs.c create mode 100644 lib/libprocstat/nwfs.c create mode 100644 lib/libprocstat/smbfs.c create mode 100644 lib/libprocstat/udf.c rename {usr.bin/fstat => lib/libprocstat}/zfs.c (79%) rename {usr.bin/fstat => lib/libprocstat}/zfs/Makefile (100%) create mode 100644 lib/libutil/kinfo_getallproc.3 create mode 100644 lib/libutil/kinfo_getallproc.c create mode 100644 lib/libutil/kinfo_getproc.3 create mode 100644 lib/libutil/kinfo_getproc.c create mode 100644 usr.bin/fstat/functions.h create mode 100644 usr.bin/fstat/fuser.1 create mode 100644 usr.bin/fstat/fuser.c create mode 100644 usr.bin/fstat/main.c diff --git a/lib/Makefile b/lib/Makefile index 4fef1bbccef..7be186fca21 100644 --- a/lib/Makefile +++ b/lib/Makefile @@ -92,6 +92,7 @@ SUBDIR= ${SUBDIR_ORDERED} \ ${_libpkg} \ ${_libpmc} \ ${_libproc} \ + libprocstat \ librt \ ${_librtld_db} \ ${_libsdp} \ diff --git a/lib/libprocstat/Makefile b/lib/libprocstat/Makefile new file mode 100644 index 00000000000..dc3dd581b78 --- /dev/null +++ b/lib/libprocstat/Makefile @@ -0,0 +1,36 @@ +# $FreeBSD$ + +.include + +LIB= procstat + +SRCS= cd9660.c \ + common_kvm.c \ + libprocstat.c \ + msdosfs.c \ + ntfs.c \ + nwfs.c \ + smbfs.c \ + udf.c + +INCS= libprocstat.h +CFLAGS+= -I. -I${.CURDIR} -D_KVM_VNODE +SHLIB_MAJOR= 1 +WITHOUT_MAN= yes + +# XXX This is a hack. +.if ${MK_CDDL} != "no" +CFLAGS+= -DZFS +OBJS+= zfs/zfs.o +SOBJS+= zfs/zfs.So +POBJS+= zfs/zfs.po +SUBDIR= zfs +zfs/zfs.o: .PHONY + @cd ${.CURDIR}/zfs && ${MAKE} zfs.o +zfs/zfs.So: .PHONY + @cd ${.CURDIR}/zfs && ${MAKE} zfs.So +zfs/zfs.po: .PHONY + @cd ${.CURDIR}/zfs && ${MAKE} zfs.po +.endif + +.include diff --git a/usr.bin/fstat/cd9660.c b/lib/libprocstat/cd9660.c similarity index 76% rename from usr.bin/fstat/cd9660.c rename to lib/libprocstat/cd9660.c index 1c26e8d854a..95882be5d9e 100644 --- a/usr.bin/fstat/cd9660.c +++ b/lib/libprocstat/cd9660.c @@ -49,31 +49,42 @@ __FBSDID("$FreeBSD$"); #include #include +#include + +#include + #include +#define _KERNEL +#include +#undef _KERNEL #include #include -#include "fstat.h" +#include "libprocstat.h" +#include "common_kvm.h" int -isofs_filestat(struct vnode *vp, struct filestat *fsp) +isofs_filestat(kvm_t *kd, struct vnode *vp, struct vnstat *vn) { struct iso_node isonode; + struct iso_mnt mnt; - if (!KVM_READ(VTOI(vp), &isonode, sizeof (isonode))) { - dprintf(stderr, "can't read iso_node at %p for pid %d\n", - (void *)VTOI(vp), Pid); - return 0; + if (!kvm_read_all(kd, (unsigned long)VTOI(vp), &isonode, + sizeof(isonode))) { + warnx("can't read iso_node at %p", + (void *)VTOI(vp)); + return (1); } -#if 0 - fsp->fsid = dev2udev(isonode.i_dev); -#endif - fsp->mode = (mode_t)isonode.inode.iso_mode; - fsp->rdev = isonode.inode.iso_rdev; - - fsp->fileid = (long)isonode.i_number; - fsp->size = (u_long)isonode.i_size; - return 1; + if (!kvm_read_all(kd, (unsigned long)isonode.i_mnt, &mnt, + sizeof(mnt))) { + warnx("can't read iso_mnt at %p", + (void *)VTOI(vp)); + return (1); + } + vn->vn_fsid = dev2udev(kd, mnt.im_dev); + vn->vn_mode = (mode_t)isonode.inode.iso_mode; + vn->vn_fileid = (long)isonode.i_number; + vn->vn_size = (u_long)isonode.i_size; + return (0); } - diff --git a/lib/libprocstat/common_kvm.c b/lib/libprocstat/common_kvm.c new file mode 100644 index 00000000000..1ff181c8077 --- /dev/null +++ b/lib/libprocstat/common_kvm.c @@ -0,0 +1,207 @@ +/*- + * Copyright (c) 2009 Stanislav Sedov + * Copyright (c) 1988, 1993 + * The Regents of the University of California. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include +__FBSDID("$FreeBSD$"); + +#include +#include +#include +#include +#include +#define _KERNEL +#include +#include +#include +#include +#include +#include +#undef _KERNEL +#include +#include +#include + +#include +#include +#include +#include +#include + +#include +#include "common_kvm.h" + +int +kvm_read_all(kvm_t *kd, unsigned long addr, void *buf, size_t nbytes) +{ + ssize_t error; + + if (nbytes >= SSIZE_MAX) + return (0); + error = kvm_read(kd, addr, buf, nbytes); + return (error == (ssize_t)(nbytes)); +} + +int +kdevtoname(kvm_t *kd, struct cdev *dev, char *buf) +{ + struct cdev si; + + assert(buf); + if (!kvm_read_all(kd, (unsigned long)dev, &si, sizeof(si))) + return (1); + strlcpy(buf, si.__si_namebuf, SPECNAMELEN + 1); + return (0); +} + +int +ufs_filestat(kvm_t *kd, struct vnode *vp, struct vnstat *vn) +{ + struct inode inode; + + if (!kvm_read_all(kd, (unsigned long)VTOI(vp), &inode, sizeof(inode))) { + warnx("can't read inode at %p", (void *)VTOI(vp)); + return (1); + } + /* + * The st_dev from stat(2) is a dev_t. These kernel structures + * contain cdev pointers. We need to convert to dev_t to make + * comparisons + */ + vn->vn_fsid = dev2udev(kd, inode.i_dev); + vn->vn_fileid = (long)inode.i_number; + vn->vn_mode = (mode_t)inode.i_mode; + vn->vn_size = (u_long)inode.i_size; + return (0); +} + +int +devfs_filestat(kvm_t *kd, struct vnode *vp, struct vnstat *vn) +{ + struct devfs_dirent devfs_dirent; + struct mount mount; + + if (!kvm_read_all(kd, (unsigned long)getvnodedata(vp), &devfs_dirent, + sizeof(devfs_dirent))) { + warnx("can't read devfs_dirent at %p", + (void *)vp->v_data); + return (1); + } + if (!kvm_read_all(kd, (unsigned long)getvnodemount(vp), &mount, + sizeof(mount))) { + warnx("can't read mount at %p", + (void *)getvnodemount(vp)); + return (1); + } + vn->vn_fsid = mount.mnt_stat.f_fsid.val[0]; + vn->vn_fileid = devfs_dirent.de_inode; + vn->vn_mode = (devfs_dirent.de_mode & ~S_IFMT) | S_IFCHR; + vn->vn_size = 0; + return (0); +} + +int +nfs_filestat(kvm_t *kd, struct vnode *vp, struct vnstat *vn) +{ + struct nfsnode nfsnode; + mode_t mode; + + if (!kvm_read_all(kd, (unsigned long)VTONFS(vp), &nfsnode, + sizeof(nfsnode))) { + warnx("can't read nfsnode at %p", + (void *)VTONFS(vp)); + return (1); + } + vn->vn_fsid = nfsnode.n_vattr.va_fsid; + vn->vn_fileid = nfsnode.n_vattr.va_fileid; + vn->vn_size = nfsnode.n_size; + mode = (mode_t)nfsnode.n_vattr.va_mode; + switch (vp->v_type) { + case VREG: + mode |= S_IFREG; + break; + case VDIR: + mode |= S_IFDIR; + break; + case VBLK: + mode |= S_IFBLK; + break; + case VCHR: + mode |= S_IFCHR; + break; + case VLNK: + mode |= S_IFLNK; + break; + case VSOCK: + mode |= S_IFSOCK; + break; + case VFIFO: + mode |= S_IFIFO; + break; + default: + break; + }; + vn->vn_mode = mode; + return (0); +} + +/* + * Read the cdev structure in the kernel in order to work out the + * associated dev_t + */ +dev_t +dev2udev(kvm_t *kd, struct cdev *dev) +{ + struct cdev_priv priv; + + assert(kd); + if (kvm_read_all(kd, (unsigned long)cdev2priv(dev), &priv, + sizeof(priv))) { + return ((dev_t)priv.cdp_inode); + } else { + warnx("can't convert cdev *%p to a dev_t\n", dev); + return (-1); + } +} + +void * +getvnodedata(struct vnode *vp) +{ + return (vp->v_data); +} + +struct mount * +getvnodemount(struct vnode *vp) +{ + return (vp->v_mount); +} diff --git a/usr.bin/fstat/fstat.h b/lib/libprocstat/common_kvm.h similarity index 52% rename from usr.bin/fstat/fstat.h rename to lib/libprocstat/common_kvm.h index 3533a60259f..d0b5307a007 100644 --- a/usr.bin/fstat/fstat.h +++ b/lib/libprocstat/common_kvm.h @@ -1,6 +1,6 @@ /*- - * Copyright (c) 1988, 1993 - * The Regents of the University of California. All rights reserved. + * Copyright (c) 2009 Stanislav Sedov + * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -10,9 +10,6 @@ * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. - * 4. Neither the name of the University nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE @@ -29,48 +26,28 @@ * $FreeBSD$ */ -#ifndef __FSTAT_H__ -#define __FSTAT_H__ +#ifndef _COMMON_KVM_H_ +#define _COMMON_KVM_H_ + +dev_t dev2udev(kvm_t *kd, struct cdev *dev); +int kdevtoname(kvm_t *kd, struct cdev *dev, char *); +int kvm_read_all(kvm_t *kd, unsigned long addr, void *buf, + size_t nbytes); /* - * a kvm_read that returns true if everything is read + * Filesystems specific access routines. */ -#define KVM_READ(kaddr, paddr, len) \ - ((len) < SSIZE_MAX && \ - kvm_read(kd, (u_long)(kaddr), (char *)(paddr), (len)) == (ssize_t)(len)) +int devfs_filestat(kvm_t *kd, struct vnode *vp, struct vnstat *vn); +int isofs_filestat(kvm_t *kd, struct vnode *vp, struct vnstat *vn); +int msdosfs_filestat(kvm_t *kd, struct vnode *vp, struct vnstat *vn); +int nfs_filestat(kvm_t *kd, struct vnode *vp, struct vnstat *vn); +int ntfs_filestat(kvm_t *kd, struct vnode *vp, struct vnstat *vn); +int nwfs_filestat(kvm_t *kd, struct vnode *vp, struct vnstat *vn); +int smbfs_filestat(kvm_t *kd, struct vnode *vp, struct vnstat *vn); +int udf_filestat(kvm_t *kd, struct vnode *vp, struct vnstat *vn); +int ufs_filestat(kvm_t *kd, struct vnode *vp, struct vnstat *vn); +int zfs_filestat(kvm_t *kd, struct vnode *vp, struct vnstat *vn); +void *getvnodedata(struct vnode *vp); +struct mount *getvnodemount(struct vnode *vp); -#define dprintf if (vflg) fprintf - -typedef struct devs { - struct devs *next; - long fsid; - long ino; - const char *name; -} DEVS; - -struct filestat { - long fsid; - long fileid; - mode_t mode; - u_long size; - dev_t rdev; -}; - -/* Ugh */ -extern kvm_t *kd; -extern int vflg; -extern int Pid; - -dev_t dev2udev(struct cdev *dev); - -/* Additional filesystem types */ -int isofs_filestat(struct vnode *vp, struct filestat *fsp); -int msdosfs_filestat(struct vnode *vp, struct filestat *fsp); - -#ifdef ZFS -int zfs_filestat(struct vnode *vp, struct filestat *fsp); -void *getvnodedata(struct vnode *vp); -struct mount *getvnodemount(struct vnode *vp); -#endif - -#endif /* __FSTAT_H__ */ +#endif /* _COMMON_KVM_H_ */ diff --git a/lib/libprocstat/libprocstat.c b/lib/libprocstat/libprocstat.c new file mode 100644 index 00000000000..cfe81a2438a --- /dev/null +++ b/lib/libprocstat/libprocstat.c @@ -0,0 +1,1306 @@ +/*- + * Copyright (c) 2009 Stanislav Sedov + * Copyright (c) 1988, 1993 + * The Regents of the University of California. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include +__FBSDID("$FreeBSD$"); + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#define _WANT_FILE +#include +#include +#define _KERNEL +#include +#include +#include +#include +#include +#include +#undef _KERNEL +#include +#include +#include + +#include +#include +#include + +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include "libprocstat_internal.h" +#include "common_kvm.h" + +int statfs(const char *, struct statfs *); /* XXX */ + +#define PROCSTAT_KVM 1 +#define PROCSTAT_SYSCTL 2 + +static char *getmnton(kvm_t *kd, struct mount *m); +static struct filestat_list *procstat_getfiles_kvm( + struct procstat *procstat, struct kinfo_proc *kp, int mmapped); +static struct filestat_list *procstat_getfiles_sysctl( + struct procstat *procstat, struct kinfo_proc *kp, int mmapped); +static int procstat_get_pipe_info_sysctl(struct filestat *fst, + struct pipestat *pipe, char *errbuf); +static int procstat_get_pipe_info_kvm(kvm_t *kd, struct filestat *fst, + struct pipestat *pipe, char *errbuf); +static int procstat_get_pts_info_sysctl(struct filestat *fst, + struct ptsstat *pts, char *errbuf); +static int procstat_get_pts_info_kvm(kvm_t *kd, struct filestat *fst, + struct ptsstat *pts, char *errbuf); +static int procstat_get_socket_info_sysctl(struct filestat *fst, + struct sockstat *sock, char *errbuf); +static int procstat_get_socket_info_kvm(kvm_t *kd, struct filestat *fst, + struct sockstat *sock, char *errbuf); +static int to_filestat_flags(int flags); +static int procstat_get_vnode_info_kvm(kvm_t *kd, struct filestat *fst, + struct vnstat *vn, char *errbuf); +static int procstat_get_vnode_info_sysctl(struct filestat *fst, + struct vnstat *vn, char *errbuf); +static int vntype2psfsttype(int type); + +void +procstat_close(struct procstat *procstat) +{ + + assert(procstat); + if (procstat->type == PROCSTAT_KVM) + kvm_close(procstat->kd); +} + +struct procstat * +procstat_open_sysctl(void) +{ + struct procstat *procstat; + + procstat = calloc(1, sizeof(*procstat)); + if (procstat == NULL) { + warn("malloc()"); + return (NULL); + } + procstat->type = PROCSTAT_SYSCTL; + return (procstat); +} + +struct procstat * +procstat_open_kvm(const char *nlistf, const char *memf) +{ + struct procstat *procstat; + kvm_t *kd; + char buf[_POSIX2_LINE_MAX]; + + procstat = calloc(1, sizeof(*procstat)); + if (procstat == NULL) { + warn("malloc()"); + return (NULL); + } + kd = kvm_openfiles(nlistf, memf, NULL, O_RDONLY, buf); + if (kd == NULL) { + warnx("kvm_openfiles(): %s", buf); + free(procstat); + return (NULL); + } + procstat->type = PROCSTAT_KVM; + procstat->kd = kd; + return (procstat); +} + +struct kinfo_proc * +procstat_getprocs(struct procstat *procstat, int what, int arg, + unsigned int *count) +{ + struct kinfo_proc *p0, *p; + size_t len; + int name[4]; + int error; + + assert(procstat); + assert(count); + p = NULL; + if (procstat->type == PROCSTAT_KVM) { + p0 = kvm_getprocs(procstat->kd, what, arg, count); + if (p0 == NULL || count == 0) + return (NULL); + len = *count * sizeof(*p); + p = malloc(len); + if (p == NULL) { + warnx("malloc(%zd)", len); + goto fail; + } + bcopy(p0, p, len); + return (p); + } else if (procstat->type == PROCSTAT_SYSCTL) { + len = 0; + name[0] = CTL_KERN; + name[1] = KERN_PROC; + name[2] = what; + name[3] = arg; + error = sysctl(name, 4, NULL, &len, NULL, 0); + if (error < 0 && errno != EPERM) { + warn("sysctl(kern.proc)"); + goto fail; + } + if (len == 0) { + warnx("no processes?"); + goto fail; + } + p = malloc(len); + if (p == NULL) { + warnx("malloc(%zd)", len); + goto fail; + } + error = sysctl(name, 4, p, &len, NULL, 0); + if (error < 0 && errno != EPERM) { + warn("sysctl(kern.proc)"); + goto fail; + } + /* Perform simple consistency checks. */ + if ((len % sizeof(*p)) != 0 || p->ki_structsize != sizeof(*p)) { + warnx("kinfo_proc structure size mismatch"); + goto fail; + } + *count = len / sizeof(*p); + return (p); + } else { + warnx("unknown access method"); + return (NULL); + } +fail: + if (p) + free(p); + return (NULL); +} + +void +procstat_freeprocs(struct procstat *procstat __unused, struct kinfo_proc *p) +{ + + if (p != NULL) + free(p); + p = NULL; +} + +struct filestat_list * +procstat_getfiles(struct procstat *procstat, struct kinfo_proc *kp, int mmapped) +{ + + if (procstat->type == PROCSTAT_SYSCTL) + return (procstat_getfiles_sysctl(procstat, kp, mmapped)); + else if (procstat->type == PROCSTAT_KVM) + return (procstat_getfiles_kvm(procstat, kp, mmapped)); + else + return (NULL); +} + +void +procstat_freefiles(struct procstat *procstat, struct filestat_list *head) +{ + struct filestat *fst, *tmp; + + STAILQ_FOREACH_SAFE(fst, head, next, tmp) { + if (fst->fs_path != NULL) + free(fst->fs_path); + free(fst); + } + free(head); + if (procstat->vmentries != NULL) { + free (procstat->vmentries); + procstat->vmentries = NULL; + } + if (procstat->files != NULL) { + free (procstat->files); + procstat->files = NULL; + } +} + +static struct filestat * +filestat_new_entry(void *typedep, int type, int fd, int fflags, int uflags, + int refcount, off_t offset, char *path) +{ + struct filestat *entry; + + entry = calloc(1, sizeof(*entry)); + if (entry == NULL) { + warn("malloc()"); + return (NULL); + } + entry->fs_typedep = typedep; + entry->fs_fflags = fflags; + entry->fs_uflags = uflags; + entry->fs_fd = fd; + entry->fs_type = type; + entry->fs_ref_count = refcount; + entry->fs_offset = offset; + entry->fs_path = path; + return (entry); +} + +static struct vnode * +getctty(kvm_t *kd, struct kinfo_proc *kp) +{ + struct pgrp pgrp; + struct proc proc; + struct session sess; + int error; + + assert(kp); + error = kvm_read_all(kd, (unsigned long)kp->ki_paddr, &proc, + sizeof(proc)); + if (error == 0) { + warnx("can't read proc struct at %p for pid %d", + kp->ki_paddr, kp->ki_pid); + return (NULL); + } + if (proc.p_pgrp == NULL) + return (NULL); + error = kvm_read_all(kd, (unsigned long)proc.p_pgrp, &pgrp, + sizeof(pgrp)); + if (error == 0) { + warnx("can't read pgrp struct at %p for pid %d", + proc.p_pgrp, kp->ki_pid); + return (NULL); + } + error = kvm_read_all(kd, (unsigned long)pgrp.pg_session, &sess, + sizeof(sess)); + if (error == 0) { + warnx("can't read session struct at %p for pid %d", + pgrp.pg_session, kp->ki_pid); + return (NULL); + } + return (sess.s_ttyvp); +} + +static struct filestat_list * +procstat_getfiles_kvm(struct procstat *procstat, struct kinfo_proc *kp, int mmapped) +{ + struct file file; + struct filedesc filed; + struct vm_map_entry vmentry; + struct vm_object object; + struct vmspace vmspace; + vm_map_entry_t entryp; + vm_map_t map; + vm_object_t objp; + struct vnode *vp; + struct file **ofiles; + struct filestat *entry; + struct filestat_list *head; + kvm_t *kd; + void *data; + int i, fflags; + int prot, type; + unsigned int nfiles; + + assert(procstat); + kd = procstat->kd; + if (kd == NULL) + return (NULL); + if (kp->ki_fd == NULL) + return (NULL); + if (!kvm_read_all(kd, (unsigned long)kp->ki_fd, &filed, + sizeof(filed))) { + warnx("can't read filedesc at %p", (void *)kp->ki_fd); + return (NULL); + } + + /* + * Allocate list head. + */ + head = malloc(sizeof(*head)); + if (head == NULL) + return (NULL); + STAILQ_INIT(head); + + /* root directory vnode, if one. */ + if (filed.fd_rdir) { + entry = filestat_new_entry(filed.fd_rdir, PS_FST_TYPE_VNODE, -1, + PS_FST_FFLAG_READ, PS_FST_UFLAG_RDIR, 0, 0, NULL); + if (entry != NULL) + STAILQ_INSERT_TAIL(head, entry, next); + } + /* current working directory vnode. */ + if (filed.fd_cdir) { + entry = filestat_new_entry(filed.fd_cdir, PS_FST_TYPE_VNODE, -1, + PS_FST_FFLAG_READ, PS_FST_UFLAG_CDIR, 0, 0, NULL); + if (entry != NULL) + STAILQ_INSERT_TAIL(head, entry, next); + } + /* jail root, if any. */ + if (filed.fd_jdir) { + entry = filestat_new_entry(filed.fd_jdir, PS_FST_TYPE_VNODE, -1, + PS_FST_FFLAG_READ, PS_FST_UFLAG_JAIL, 0, 0, NULL); + if (entry != NULL) + STAILQ_INSERT_TAIL(head, entry, next); + } + /* ktrace vnode, if one */ + if (kp->ki_tracep) { + entry = filestat_new_entry(kp->ki_tracep, PS_FST_TYPE_VNODE, -1, + PS_FST_FFLAG_READ | PS_FST_FFLAG_WRITE, + PS_FST_UFLAG_TRACE, 0, 0, NULL); + if (entry != NULL) + STAILQ_INSERT_TAIL(head, entry, next); + } + /* text vnode, if one */ + if (kp->ki_textvp) { + entry = filestat_new_entry(kp->ki_textvp, PS_FST_TYPE_VNODE, -1, + PS_FST_FFLAG_READ, PS_FST_UFLAG_TEXT, 0, 0, NULL); + if (entry != NULL) + STAILQ_INSERT_TAIL(head, entry, next); + } + /* Controlling terminal. */ + if ((vp = getctty(kd, kp)) != NULL) { + entry = filestat_new_entry(vp, PS_FST_TYPE_VNODE, -1, + PS_FST_FFLAG_READ | PS_FST_FFLAG_WRITE, + PS_FST_UFLAG_CTTY, 0, 0, NULL); + if (entry != NULL) + STAILQ_INSERT_TAIL(head, entry, next); + } + + nfiles = filed.fd_lastfile + 1; + ofiles = malloc(nfiles * sizeof(struct file *)); + if (ofiles == NULL) { + warn("malloc(%zd)", nfiles * sizeof(struct file *)); + goto do_mmapped; + } + if (!kvm_read_all(kd, (unsigned long)filed.fd_ofiles, ofiles, + nfiles * sizeof(struct file *))) { + warnx("cannot read file structures at %p", + (void *)filed.fd_ofiles); + free(ofiles); + goto do_mmapped; + } + for (i = 0; i <= filed.fd_lastfile; i++) { + if (ofiles[i] == NULL) + continue; + if (!kvm_read_all(kd, (unsigned long)ofiles[i], &file, + sizeof(struct file))) { + warnx("can't read file %d at %p", i, + (void *)ofiles[i]); + continue; + } + switch (file.f_type) { + case DTYPE_VNODE: + type = PS_FST_TYPE_VNODE; + data = file.f_vnode; + break; + case DTYPE_SOCKET: + type = PS_FST_TYPE_SOCKET; + data = file.f_data; + break; + case DTYPE_PIPE: + type = PS_FST_TYPE_PIPE; + data = file.f_data; + break; + case DTYPE_FIFO: + type = PS_FST_TYPE_FIFO; + data = file.f_vnode; + break; +#ifdef DTYPE_PTS + case DTYPE_PTS: + type = PS_FST_TYPE_PTS; + data = file.f_data; + break; +#endif + default: + continue; + } + entry = filestat_new_entry(data, type, i, + to_filestat_flags(file.f_flag), 0, 0, 0, NULL); + if (entry != NULL) + STAILQ_INSERT_TAIL(head, entry, next); + } + free(ofiles); + +do_mmapped: + + /* + * Process mmapped files if requested. + */ + if (mmapped) { + if (!kvm_read_all(kd, (unsigned long)kp->ki_vmspace, &vmspace, + sizeof(vmspace))) { + warnx("can't read vmspace at %p", + (void *)kp->ki_vmspace); + goto exit; + } + map = &vmspace.vm_map; + + for (entryp = map->header.next; + entryp != &kp->ki_vmspace->vm_map.header; + entryp = vmentry.next) { + if (!kvm_read_all(kd, (unsigned long)entryp, &vmentry, + sizeof(vmentry))) { + warnx("can't read vm_map_entry at %p", + (void *)entryp); + continue; + } + if (vmentry.eflags & MAP_ENTRY_IS_SUB_MAP) + continue; + if ((objp = vmentry.object.vm_object) == NULL) + continue; + for (; objp; objp = object.backing_object) { + if (!kvm_read_all(kd, (unsigned long)objp, + &object, sizeof(object))) { + warnx("can't read vm_object at %p", + (void *)objp); + break; + } + } + + /* We want only vnode objects. */ + if (object.type != OBJT_VNODE) + continue; + + prot = vmentry.protection; + fflags = 0; + if (prot & VM_PROT_READ) + fflags = PS_FST_FFLAG_READ; + if (prot & VM_PROT_WRITE) + fflags |= PS_FST_FFLAG_WRITE; + + /* + * Create filestat entry. + */ + entry = filestat_new_entry(object.handle, + PS_FST_TYPE_VNODE, -1, fflags, + PS_FST_UFLAG_MMAP, 0, 0, NULL); + if (entry != NULL) + STAILQ_INSERT_TAIL(head, entry, next); + } + } +exit: + return (head); +} + +/* + * kinfo types to filestat translation. + */ +static int +kinfo_type2fst(int kftype) +{ + static struct { + int kf_type; + int fst_type; + } kftypes2fst[] = { + { KF_TYPE_CRYPTO, PS_FST_TYPE_CRYPTO }, + { KF_TYPE_FIFO, PS_FST_TYPE_FIFO }, + { KF_TYPE_KQUEUE, PS_FST_TYPE_KQUEUE }, + { KF_TYPE_MQUEUE, PS_FST_TYPE_MQUEUE }, + { KF_TYPE_NONE, PS_FST_TYPE_NONE }, + { KF_TYPE_PIPE, PS_FST_TYPE_PIPE }, + { KF_TYPE_PTS, PS_FST_TYPE_PTS }, + { KF_TYPE_SEM, PS_FST_TYPE_SEM }, + { KF_TYPE_SHM, PS_FST_TYPE_SHM }, + { KF_TYPE_SOCKET, PS_FST_TYPE_SOCKET }, + { KF_TYPE_VNODE, PS_FST_TYPE_VNODE }, + { KF_TYPE_UNKNOWN, PS_FST_TYPE_UNKNOWN } + }; +#define NKFTYPES (sizeof(kftypes2fst) / sizeof(*kftypes2fst)) + unsigned int i; + + for (i = 0; i < NKFTYPES; i++) + if (kftypes2fst[i].kf_type == kftype) + break; + if (i == NKFTYPES) + return (PS_FST_TYPE_UNKNOWN); + return (kftypes2fst[i].fst_type); +} + +/* + * kinfo flags to filestat translation. + */ +static int +kinfo_fflags2fst(int kfflags) +{ + static struct { + int kf_flag; + int fst_flag; + } kfflags2fst[] = { + { KF_FLAG_APPEND, PS_FST_FFLAG_APPEND }, + { KF_FLAG_ASYNC, PS_FST_FFLAG_ASYNC }, + { KF_FLAG_CREAT, PS_FST_FFLAG_CREAT }, + { KF_FLAG_DIRECT, PS_FST_FFLAG_DIRECT }, + { KF_FLAG_EXCL, PS_FST_FFLAG_EXCL }, + { KF_FLAG_EXEC, PS_FST_FFLAG_EXEC }, + { KF_FLAG_EXLOCK, PS_FST_FFLAG_EXLOCK }, + { KF_FLAG_FSYNC, PS_FST_FFLAG_SYNC }, + { KF_FLAG_HASLOCK, PS_FST_FFLAG_HASLOCK }, + { KF_FLAG_NOFOLLOW, PS_FST_FFLAG_NOFOLLOW }, + { KF_FLAG_NONBLOCK, PS_FST_FFLAG_NONBLOCK }, + { KF_FLAG_READ, PS_FST_FFLAG_READ }, + { KF_FLAG_SHLOCK, PS_FST_FFLAG_SHLOCK }, + { KF_FLAG_TRUNC, PS_FST_FFLAG_TRUNC }, + { KF_FLAG_WRITE, PS_FST_FFLAG_WRITE } + }; +#define NKFFLAGS (sizeof(kfflags2fst) / sizeof(*kfflags2fst)) + unsigned int i; + int flags; + + flags = 0; + for (i = 0; i < NKFFLAGS; i++) + if ((kfflags & kfflags2fst[i].kf_flag) != 0) + flags |= kfflags2fst[i].fst_flag; + return (flags); +} + +static int +kinfo_uflags2fst(int fd) +{ + + switch (fd) { + case KF_FD_TYPE_CTTY: + return (PS_FST_UFLAG_CTTY); + case KF_FD_TYPE_CWD: + return (PS_FST_UFLAG_CDIR); + case KF_FD_TYPE_JAIL: + return (PS_FST_UFLAG_JAIL); + case KF_FD_TYPE_TEXT: + return (PS_FST_UFLAG_TEXT); + case KF_FD_TYPE_TRACE: + return (PS_FST_UFLAG_TRACE); + case KF_FD_TYPE_ROOT: + return (PS_FST_UFLAG_RDIR); + } + return (0); +} + +static struct filestat_list * +procstat_getfiles_sysctl(struct procstat *procstat, struct kinfo_proc *kp, int mmapped) +{ + struct kinfo_file *kif, *files; + struct kinfo_vmentry *kve, *vmentries; + struct filestat_list *head; + struct filestat *entry; + char *path; + off_t offset; + int cnt, fd, fflags; + int i, type, uflags; + int refcount; + + assert(kp); + if (kp->ki_fd == NULL) + return (NULL); + + files = kinfo_getfile(kp->ki_pid, &cnt); + if (files == NULL && errno != EPERM) { + warn("kinfo_getfile()"); + return (NULL); + } + procstat->files = files; + + /* + * Allocate list head. + */ + head = malloc(sizeof(*head)); + if (head == NULL) + return (NULL); + STAILQ_INIT(head); + for (i = 0; i < cnt; i++) { + kif = &files[i]; + + type = kinfo_type2fst(kif->kf_type); + fd = kif->kf_fd >= 0 ? kif->kf_fd : -1; + fflags = kinfo_fflags2fst(kif->kf_flags); + uflags = kinfo_uflags2fst(kif->kf_fd); + refcount = kif->kf_ref_count; + offset = kif->kf_offset; + if (*kif->kf_path != '\0') + path = strdup(kif->kf_path); + else + path = NULL; + + /* + * Create filestat entry. + */ + entry = filestat_new_entry(kif, type, fd, fflags, uflags, + refcount, offset, path); + if (entry != NULL) + STAILQ_INSERT_TAIL(head, entry, next); + } + if (mmapped != 0) { + vmentries = kinfo_getvmmap(kp->ki_pid, &cnt); + procstat->vmentries = vmentries; + if (vmentries == NULL || cnt == 0) + goto fail; + for (i = 0; i < cnt; i++) { + kve = &vmentries[i]; + if (kve->kve_type != KVME_TYPE_VNODE) + continue; + fflags = 0; + if (kve->kve_protection & KVME_PROT_READ) + fflags = PS_FST_FFLAG_READ; + if (kve->kve_protection & KVME_PROT_WRITE) + fflags |= PS_FST_FFLAG_WRITE; + offset = kve->kve_offset; + refcount = kve->kve_ref_count; + if (*kve->kve_path != '\0') + path = strdup(kve->kve_path); + else + path = NULL; + entry = filestat_new_entry(kve, PS_FST_TYPE_VNODE, -1, + fflags, PS_FST_UFLAG_MMAP, refcount, offset, path); + if (entry != NULL) + STAILQ_INSERT_TAIL(head, entry, next); + } + } +fail: + return (head); +} + +int +procstat_get_pipe_info(struct procstat *procstat, struct filestat *fst, + struct pipestat *ps, char *errbuf) +{ + + assert(ps); + if (procstat->type == PROCSTAT_KVM) { + return (procstat_get_pipe_info_kvm(procstat->kd, fst, ps, + errbuf)); + } else if (procstat->type == PROCSTAT_SYSCTL) { + return (procstat_get_pipe_info_sysctl(fst, ps, errbuf)); + } else { + warnx("unknow access method: %d", procstat->type); + snprintf(errbuf, _POSIX2_LINE_MAX, "error"); + return (1); + } +} + +static int +procstat_get_pipe_info_kvm(kvm_t *kd, struct filestat *fst, + struct pipestat *ps, char *errbuf) +{ + struct pipe pi; + void *pipep; + + assert(kd); + assert(ps); + assert(fst); + bzero(ps, sizeof(*ps)); + pipep = fst->fs_typedep; + if (pipep == NULL) + goto fail; + if (!kvm_read_all(kd, (unsigned long)pipep, &pi, sizeof(struct pipe))) { + warnx("can't read pipe at %p", (void *)pipep); + goto fail; + } + ps->addr = (uintptr_t)pipep; + ps->peer = (uintptr_t)pi.pipe_peer; + ps->buffer_cnt = pi.pipe_buffer.cnt; + return (0); + +fail: + snprintf(errbuf, _POSIX2_LINE_MAX, "error"); + return (1); +} + +static int +procstat_get_pipe_info_sysctl(struct filestat *fst, struct pipestat *ps, + char *errbuf __unused) +{ + struct kinfo_file *kif; + + assert(ps); + assert(fst); + bzero(ps, sizeof(*ps)); + kif = fst->fs_typedep; + if (kif == NULL) + return (1); + ps->addr = kif->kf_un.kf_pipe.kf_pipe_addr; + ps->peer = kif->kf_un.kf_pipe.kf_pipe_peer; + ps->buffer_cnt = kif->kf_un.kf_pipe.kf_pipe_buffer_cnt; + return (0); +} + +int +procstat_get_pts_info(struct procstat *procstat, struct filestat *fst, + struct ptsstat *pts, char *errbuf) +{ + + assert(pts); + if (procstat->type == PROCSTAT_KVM) { + return (procstat_get_pts_info_kvm(procstat->kd, fst, pts, + errbuf)); + } else if (procstat->type == PROCSTAT_SYSCTL) { + return (procstat_get_pts_info_sysctl(fst, pts, errbuf)); + } else { + warnx("unknow access method: %d", procstat->type); + snprintf(errbuf, _POSIX2_LINE_MAX, "error"); + return (1); + } +} + +static int +procstat_get_pts_info_kvm(kvm_t *kd, struct filestat *fst, + struct ptsstat *pts, char *errbuf) +{ + struct tty tty; + void *ttyp; + + assert(kd); + assert(pts); + assert(fst); + bzero(pts, sizeof(*pts)); + ttyp = fst->fs_typedep; + if (ttyp == NULL) + goto fail; + if (!kvm_read_all(kd, (unsigned long)ttyp, &tty, sizeof(struct tty))) { + warnx("can't read tty at %p", (void *)ttyp); + goto fail; + } + pts->dev = dev2udev(kd, tty.t_dev); + (void)kdevtoname(kd, tty.t_dev, pts->devname); + return (0); + +fail: + snprintf(errbuf, _POSIX2_LINE_MAX, "error"); + return (1); +} + +static int +procstat_get_pts_info_sysctl(struct filestat *fst, struct ptsstat *pts, + char *errbuf __unused) +{ + struct kinfo_file *kif; + + assert(pts); + assert(fst); + bzero(pts, sizeof(*pts)); + kif = fst->fs_typedep; + if (kif == NULL) + return (0); + pts->dev = kif->kf_un.kf_pts.kf_pts_dev; + strlcpy(pts->devname, kif->kf_path, sizeof(pts->devname)); + return (0); +} + +int +procstat_get_vnode_info(struct procstat *procstat, struct filestat *fst, + struct vnstat *vn, char *errbuf) +{ + + assert(vn); + if (procstat->type == PROCSTAT_KVM) { + return (procstat_get_vnode_info_kvm(procstat->kd, fst, vn, + errbuf)); + } else if (procstat->type == PROCSTAT_SYSCTL) { + return (procstat_get_vnode_info_sysctl(fst, vn, errbuf)); + } else { + warnx("unknow access method: %d", procstat->type); + snprintf(errbuf, _POSIX2_LINE_MAX, "error"); + return (1); + } +} + +static int +procstat_get_vnode_info_kvm(kvm_t *kd, struct filestat *fst, + struct vnstat *vn, char *errbuf) +{ + /* Filesystem specific handlers. */ + #define FSTYPE(fst) {#fst, fst##_filestat} + struct { + const char *tag; + int (*handler)(kvm_t *kd, struct vnode *vp, + struct vnstat *vn); + } fstypes[] = { + FSTYPE(devfs), + FSTYPE(isofs), + FSTYPE(msdosfs), + FSTYPE(nfs), + FSTYPE(ntfs), + FSTYPE(nwfs), + FSTYPE(smbfs), + FSTYPE(udf), + FSTYPE(ufs), +#ifdef ZFS + FSTYPE(zfs), +#endif + }; +#define NTYPES (sizeof(fstypes) / sizeof(*fstypes)) + struct vnode vnode; + char tagstr[12]; + void *vp; + int error, found; + unsigned int i; + + assert(kd); + assert(vn); + assert(fst); + vp = fst->fs_typedep; + if (vp == NULL) + goto fail; + error = kvm_read_all(kd, (unsigned long)vp, &vnode, sizeof(vnode)); + if (error == 0) { + warnx("can't read vnode at %p", (void *)vp); + goto fail; + } + bzero(vn, sizeof(*vn)); + vn->vn_type = vntype2psfsttype(vnode.v_type); + if (vnode.v_type == VNON || vnode.v_type == VBAD) + return (0); + error = kvm_read_all(kd, (unsigned long)vnode.v_tag, tagstr, + sizeof(tagstr)); + if (error == 0) { + warnx("can't read v_tag at %p", (void *)vp); + goto fail; + } + tagstr[sizeof(tagstr) - 1] = '\0'; + + /* + * Find appropriate handler. + */ + for (i = 0, found = 0; i < NTYPES; i++) + if (!strcmp(fstypes[i].tag, tagstr)) { + if (fstypes[i].handler(kd, &vnode, vn) != 0) { + goto fail; + } + break; + } + if (i == NTYPES) { + snprintf(errbuf, _POSIX2_LINE_MAX, "?(%s)", tagstr); + return (1); + } + vn->vn_mntdir = getmnton(kd, vnode.v_mount); + if ((vnode.v_type == VBLK || vnode.v_type == VCHR) && + vnode.v_rdev != NULL){ + vn->vn_dev = dev2udev(kd, vnode.v_rdev); + (void)kdevtoname(kd, vnode.v_rdev, vn->vn_devname); + } else { + vn->vn_dev = -1; + } + return (0); + +fail: + snprintf(errbuf, _POSIX2_LINE_MAX, "error"); + return (1); +} + +/* + * kinfo vnode type to filestat translation. + */ +static int +kinfo_vtype2fst(int kfvtype) +{ + static struct { + int kf_vtype; + int fst_vtype; + } kfvtypes2fst[] = { + { KF_VTYPE_VBAD, PS_FST_VTYPE_VBAD }, + { KF_VTYPE_VBLK, PS_FST_VTYPE_VBLK }, + { KF_VTYPE_VCHR, PS_FST_VTYPE_VCHR }, + { KF_VTYPE_VDIR, PS_FST_VTYPE_VDIR }, + { KF_VTYPE_VFIFO, PS_FST_VTYPE_VFIFO }, + { KF_VTYPE_VLNK, PS_FST_VTYPE_VLNK }, + { KF_VTYPE_VNON, PS_FST_VTYPE_VNON }, + { KF_VTYPE_VREG, PS_FST_VTYPE_VREG }, + { KF_VTYPE_VSOCK, PS_FST_VTYPE_VSOCK } + }; +#define NKFVTYPES (sizeof(kfvtypes2fst) / sizeof(*kfvtypes2fst)) + unsigned int i; + + for (i = 0; i < NKFVTYPES; i++) + if (kfvtypes2fst[i].kf_vtype == kfvtype) + break; + if (i == NKFVTYPES) + return (PS_FST_VTYPE_UNKNOWN); + return (kfvtypes2fst[i].fst_vtype); +} + +static int +procstat_get_vnode_info_sysctl(struct filestat *fst, struct vnstat *vn, + char *errbuf) +{ + struct statfs stbuf; + struct kinfo_file *kif; + struct kinfo_vmentry *kve; + uint64_t fileid; + uint64_t size; + char *name, *path; + uint32_t fsid; + uint16_t mode; + uint32_t rdev; + int vntype; + int status; + + assert(fst); + assert(vn); + bzero(vn, sizeof(*vn)); + if (fst->fs_typedep == NULL) + return (1); + if (fst->fs_uflags & PS_FST_UFLAG_MMAP) { + kve = fst->fs_typedep; + fileid = kve->kve_vn_fileid; + fsid = kve->kve_vn_fsid; + mode = kve->kve_vn_mode; + path = kve->kve_path; + rdev = kve->kve_vn_rdev; + size = kve->kve_vn_size; + vntype = kinfo_vtype2fst(kve->kve_vn_type); + status = kve->kve_status; + } else { + kif = fst->fs_typedep; + fileid = kif->kf_un.kf_file.kf_file_fileid; + fsid = kif->kf_un.kf_file.kf_file_fsid; + mode = kif->kf_un.kf_file.kf_file_mode; + path = kif->kf_path; + rdev = kif->kf_un.kf_file.kf_file_rdev; + size = kif->kf_un.kf_file.kf_file_size; + vntype = kinfo_vtype2fst(kif->kf_vnode_type); + status = kif->kf_status; + } + vn->vn_type = vntype; + if (vntype == PS_FST_VTYPE_VNON || vntype == PS_FST_VTYPE_VBAD) + return (0); + if ((status & KF_ATTR_VALID) == 0) { + snprintf(errbuf, _POSIX2_LINE_MAX, "? (no info available)"); + return (1); + } + if (path && *path) { + statfs(path, &stbuf); + vn->vn_mntdir = strdup(stbuf.f_mntonname); + } else + vn->vn_mntdir = strdup("-"); + vn->vn_dev = rdev; + if (vntype == PS_FST_VTYPE_VBLK) { + name = devname(rdev, S_IFBLK); + if (name != NULL) + strlcpy(vn->vn_devname, name, + sizeof(vn->vn_devname)); + } else if (vntype == PS_FST_VTYPE_VCHR) { + name = devname(vn->vn_dev, S_IFCHR); + if (name != NULL) + strlcpy(vn->vn_devname, name, + sizeof(vn->vn_devname)); + } + vn->vn_fsid = fsid; + vn->vn_fileid = fileid; + vn->vn_size = size; + vn->vn_mode = mode; + return (0); +} + +int +procstat_get_socket_info(struct procstat *procstat, struct filestat *fst, + struct sockstat *sock, char *errbuf) +{ + + assert(sock); + if (procstat->type == PROCSTAT_KVM) { + return (procstat_get_socket_info_kvm(procstat->kd, fst, sock, + errbuf)); + } else if (procstat->type == PROCSTAT_SYSCTL) { + return (procstat_get_socket_info_sysctl(fst, sock, errbuf)); + } else { + warnx("unknow access method: %d", procstat->type); + snprintf(errbuf, _POSIX2_LINE_MAX, "error"); + return (1); + } +} + +static int +procstat_get_socket_info_kvm(kvm_t *kd, struct filestat *fst, + struct sockstat *sock, char *errbuf) +{ + struct domain dom; + struct inpcb inpcb; + struct protosw proto; + struct socket s; + struct unpcb unpcb; + ssize_t len; + void *so; + + assert(kd); + assert(sock); + assert(fst); + bzero(sock, sizeof(*sock)); + so = fst->fs_typedep; + if (so == NULL) + goto fail; + sock->so_addr = (uintptr_t)so; + /* fill in socket */ + if (!kvm_read_all(kd, (unsigned long)so, &s, + sizeof(struct socket))) { + warnx("can't read sock at %p", (void *)so); + goto fail; + } + /* fill in protosw entry */ + if (!kvm_read_all(kd, (unsigned long)s.so_proto, &proto, + sizeof(struct protosw))) { + warnx("can't read protosw at %p", (void *)s.so_proto); + goto fail; + } + /* fill in domain */ + if (!kvm_read_all(kd, (unsigned long)proto.pr_domain, &dom, + sizeof(struct domain))) { + warnx("can't read domain at %p", + (void *)proto.pr_domain); + goto fail; + } + if ((len = kvm_read(kd, (unsigned long)dom.dom_name, sock->dname, + sizeof(sock->dname) - 1)) < 0) { + warnx("can't read domain name at %p", (void *)dom.dom_name); + sock->dname[0] = '\0'; + } + else + sock->dname[len] = '\0'; + + /* + * Fill in known data. + */ + sock->type = s.so_type; + sock->proto = proto.pr_protocol; + sock->dom_family = dom.dom_family; + sock->so_pcb = (uintptr_t)s.so_pcb; + + /* + * Protocol specific data. + */ + switch(dom.dom_family) { + case AF_INET: + case AF_INET6: + if (proto.pr_protocol == IPPROTO_TCP) { + if (s.so_pcb) { + if (kvm_read(kd, (u_long)s.so_pcb, + (char *)&inpcb, sizeof(struct inpcb)) + != sizeof(struct inpcb)) { + warnx("can't read inpcb at %p", + (void *)s.so_pcb); + } else + sock->inp_ppcb = + (uintptr_t)inpcb.inp_ppcb; + } + } + break; + case AF_UNIX: + if (s.so_pcb) { + if (kvm_read(kd, (u_long)s.so_pcb, (char *)&unpcb, + sizeof(struct unpcb)) != sizeof(struct unpcb)){ + warnx("can't read unpcb at %p", + (void *)s.so_pcb); + } else if (unpcb.unp_conn) { + sock->so_rcv_sb_state = s.so_rcv.sb_state; + sock->so_snd_sb_state = s.so_snd.sb_state; + sock->unp_conn = (uintptr_t)unpcb.unp_conn; + } + } + break; + default: + break; + } + return (0); + +fail: + snprintf(errbuf, _POSIX2_LINE_MAX, "error"); + return (1); +} + +static int +procstat_get_socket_info_sysctl(struct filestat *fst, struct sockstat *sock, + char *errbuf __unused) +{ + struct kinfo_file *kif; + + assert(sock); + assert(fst); + bzero(sock, sizeof(*sock)); + kif = fst->fs_typedep; + if (kif == NULL) + return (0); + + /* + * Fill in known data. + */ + sock->type = kif->kf_sock_type; + sock->proto = kif->kf_sock_protocol; + sock->dom_family = kif->kf_sock_domain; + sock->so_pcb = kif->kf_un.kf_sock.kf_sock_pcb; + strlcpy(sock->dname, kif->kf_path, sizeof(sock->dname)); + bcopy(&kif->kf_sa_local, &sock->sa_local, kif->kf_sa_local.ss_len); + bcopy(&kif->kf_sa_peer, &sock->sa_peer, kif->kf_sa_peer.ss_len); + + /* + * Protocol specific data. + */ + switch(sock->dom_family) { + case AF_INET: + case AF_INET6: + if (sock->proto == IPPROTO_TCP) + sock->inp_ppcb = kif->kf_un.kf_sock.kf_sock_inpcb; + break; + case AF_UNIX: + if (kif->kf_un.kf_sock.kf_sock_unpconn != 0) { + sock->so_rcv_sb_state = + kif->kf_un.kf_sock.kf_sock_rcv_sb_state; + sock->so_snd_sb_state = + kif->kf_un.kf_sock.kf_sock_snd_sb_state; + sock->unp_conn = + kif->kf_un.kf_sock.kf_sock_unpconn; + } + break; + default: + break; + } + return (0); +} + +/* + * Descriptor flags to filestat translation. + */ +static int +to_filestat_flags(int flags) +{ + static struct { + int flag; + int fst_flag; + } fstflags[] = { + { FREAD, PS_FST_FFLAG_READ }, + { FWRITE, PS_FST_FFLAG_WRITE }, + { O_APPEND, PS_FST_FFLAG_APPEND }, + { O_ASYNC, PS_FST_FFLAG_ASYNC }, + { O_CREAT, PS_FST_FFLAG_CREAT }, + { O_DIRECT, PS_FST_FFLAG_DIRECT }, + { O_EXCL, PS_FST_FFLAG_EXCL }, + { O_EXEC, PS_FST_FFLAG_EXEC }, + { O_EXLOCK, PS_FST_FFLAG_EXLOCK }, + { O_NOFOLLOW, PS_FST_FFLAG_NOFOLLOW }, + { O_NONBLOCK, PS_FST_FFLAG_NONBLOCK }, + { O_SHLOCK, PS_FST_FFLAG_SHLOCK }, + { O_SYNC, PS_FST_FFLAG_SYNC }, + { O_TRUNC, PS_FST_FFLAG_TRUNC } + }; +#define NFSTFLAGS (sizeof(fstflags) / sizeof(*fstflags)) + int fst_flags; + unsigned int i; + + fst_flags = 0; + for (i = 0; i < NFSTFLAGS; i++) + if (flags & fstflags[i].flag) + fst_flags |= fstflags[i].fst_flag; + return (fst_flags); +} + +/* + * Vnode type to filestate translation. + */ +static int +vntype2psfsttype(int type) +{ + static struct { + int vtype; + int fst_vtype; + } vt2fst[] = { + { VBAD, PS_FST_VTYPE_VBAD }, + { VBLK, PS_FST_VTYPE_VBLK }, + { VCHR, PS_FST_VTYPE_VCHR }, + { VDIR, PS_FST_VTYPE_VDIR }, + { VFIFO, PS_FST_VTYPE_VFIFO }, + { VLNK, PS_FST_VTYPE_VLNK }, + { VNON, PS_FST_VTYPE_VNON }, + { VREG, PS_FST_VTYPE_VREG }, + { VSOCK, PS_FST_VTYPE_VSOCK } + }; +#define NVFTYPES (sizeof(vt2fst) / sizeof(*vt2fst)) + unsigned int i, fst_type; + + fst_type = PS_FST_VTYPE_UNKNOWN; + for (i = 0; i < NVFTYPES; i++) { + if (type == vt2fst[i].vtype) { + fst_type = vt2fst[i].fst_vtype; + break; + } + } + return (fst_type); +} + +static char * +getmnton(kvm_t *kd, struct mount *m) +{ + static struct mount mnt; + static struct mtab { + struct mtab *next; + struct mount *m; + char mntonname[MNAMELEN + 1]; + } *mhead = NULL; + struct mtab *mt; + + for (mt = mhead; mt != NULL; mt = mt->next) + if (m == mt->m) + return (mt->mntonname); + if (!kvm_read_all(kd, (unsigned long)m, &mnt, sizeof(struct mount))) { + warnx("can't read mount table at %p", (void *)m); + return (NULL); + } + if ((mt = malloc(sizeof (struct mtab))) == NULL) + err(1, NULL); + mt->m = m; + bcopy(&mnt.mnt_stat.f_mntonname[0], &mt->mntonname[0], MNAMELEN); + mnt.mnt_stat.f_mntonname[MNAMELEN] = '\0'; + mt->next = mhead; + mhead = mt; + return (mt->mntonname); +} diff --git a/lib/libprocstat/libprocstat.h b/lib/libprocstat/libprocstat.h new file mode 100644 index 00000000000..62b1bd53bae --- /dev/null +++ b/lib/libprocstat/libprocstat.h @@ -0,0 +1,160 @@ +/*- + * Copyright (c) 2009 Stanislav Sedov + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * $FreeBSD$ + */ + +#ifndef _LIBPROCSTAT_H_ +#define _LIBPROCSTAT_H_ + +/* + * Vnode types. + */ +#define PS_FST_VTYPE_VNON 1 +#define PS_FST_VTYPE_VREG 2 +#define PS_FST_VTYPE_VDIR 3 +#define PS_FST_VTYPE_VBLK 4 +#define PS_FST_VTYPE_VCHR 5 +#define PS_FST_VTYPE_VLNK 6 +#define PS_FST_VTYPE_VSOCK 7 +#define PS_FST_VTYPE_VFIFO 8 +#define PS_FST_VTYPE_VBAD 9 +#define PS_FST_VTYPE_UNKNOWN 255 + +/* + * Descriptor types. + */ +#define PS_FST_TYPE_VNODE 1 +#define PS_FST_TYPE_FIFO 2 +#define PS_FST_TYPE_SOCKET 3 +#define PS_FST_TYPE_PIPE 4 +#define PS_FST_TYPE_PTS 5 +#define PS_FST_TYPE_KQUEUE 6 +#define PS_FST_TYPE_CRYPTO 7 +#define PS_FST_TYPE_MQUEUE 8 +#define PS_FST_TYPE_SHM 9 +#define PS_FST_TYPE_SEM 10 +#define PS_FST_TYPE_UNKNOWN 11 +#define PS_FST_TYPE_NONE 12 + +/* + * Special descriptor numbers. + */ +#define PS_FST_UFLAG_RDIR 0x0001 +#define PS_FST_UFLAG_CDIR 0x0002 +#define PS_FST_UFLAG_JAIL 0x0004 +#define PS_FST_UFLAG_TRACE 0x0008 +#define PS_FST_UFLAG_TEXT 0x0010 +#define PS_FST_UFLAG_MMAP 0x0020 +#define PS_FST_UFLAG_CTTY 0x0040 + +/* + * Descriptor flags. + */ +#define PS_FST_FFLAG_READ 0x0001 +#define PS_FST_FFLAG_WRITE 0x0002 +#define PS_FST_FFLAG_NONBLOCK 0x0004 +#define PS_FST_FFLAG_APPEND 0x0008 +#define PS_FST_FFLAG_SHLOCK 0x0010 +#define PS_FST_FFLAG_EXLOCK 0x0020 +#define PS_FST_FFLAG_ASYNC 0x0040 +#define PS_FST_FFLAG_SYNC 0x0080 +#define PS_FST_FFLAG_NOFOLLOW 0x0100 +#define PS_FST_FFLAG_CREAT 0x0200 +#define PS_FST_FFLAG_TRUNC 0x0400 +#define PS_FST_FFLAG_EXCL 0x0800 +#define PS_FST_FFLAG_DIRECT 0x1000 +#define PS_FST_FFLAG_EXEC 0x2000 +#define PS_FST_FFLAG_HASLOCK 0x4000 + +struct procstat; +struct filestat { + int fs_type; /* Descriptor type. */ + int fs_flags; /* filestat specific flags. */ + int fs_fflags; /* Descriptor access flags. */ + int fs_uflags; /* How this file is used. */ + int fs_fd; /* File descriptor number. */ + int fs_ref_count; /* Reference count. */ + off_t fs_offset; /* Seek location. */ + void *fs_typedep; /* Type dependent data. */ + char *fs_path; + STAILQ_ENTRY(filestat) next; +}; +struct vnstat { + uint64_t vn_fileid; + uint64_t vn_size; + char *vn_mntdir; + uint32_t vn_dev; + uint32_t vn_fsid; + int vn_type; + uint16_t vn_mode; + char vn_devname[SPECNAMELEN + 1]; +}; +struct ptsstat { + uint32_t dev; + char devname[SPECNAMELEN + 1]; +}; +struct pipestat { + size_t buffer_cnt; + uint64_t addr; + uint64_t peer; +}; +struct sockstat { + uint64_t inp_ppcb; + uint64_t so_addr; + uint64_t so_pcb; + uint64_t unp_conn; + int dom_family; + int proto; + int so_rcv_sb_state; + int so_snd_sb_state; + struct sockaddr_storage sa_local; /* Socket address. */ + struct sockaddr_storage sa_peer; /* Peer address. */ + int type; + char dname[32]; +}; + +STAILQ_HEAD(filestat_list, filestat); + +void procstat_close(struct procstat *procstat); +void procstat_freeprocs(struct procstat *procstat, struct kinfo_proc *p); +void procstat_freefiles(struct procstat *procstat, + struct filestat_list *head); +struct filestat_list *procstat_getfiles(struct procstat *procstat, + struct kinfo_proc *kp, int mmapped); +struct kinfo_proc *procstat_getprocs(struct procstat *procstat, + int what, int arg, unsigned int *count); +int procstat_get_pipe_info(struct procstat *procstat, struct filestat *fst, + struct pipestat *pipe, char *errbuf); +int procstat_get_pts_info(struct procstat *procstat, struct filestat *fst, + struct ptsstat *pts, char *errbuf); +int procstat_get_socket_info(struct procstat *procstat, struct filestat *fst, + struct sockstat *sock, char *errbuf); +int procstat_get_vnode_info(struct procstat *procstat, struct filestat *fst, + struct vnstat *vn, char *errbuf); +struct procstat *procstat_open_sysctl(void); +struct procstat *procstat_open_kvm(const char *nlistf, const char *memf); + +#endif /* !_LIBPROCSTAT_H_ */ diff --git a/lib/libprocstat/libprocstat_internal.h b/lib/libprocstat/libprocstat_internal.h new file mode 100644 index 00000000000..1c1d8428470 --- /dev/null +++ b/lib/libprocstat/libprocstat_internal.h @@ -0,0 +1,39 @@ +/*- + * Copyright (c) 2009 Stanislav Sedov + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * $FreeBSD$ + */ + +#ifndef _LIBPROCSTAT_INTERNAL_H_ +#define _LIBPROCSTAT_INTERNAL_H_ + +struct procstat { + int type; + kvm_t *kd; + void *vmentries; + void *files; +}; + +#endif /* !_LIBPROCSTAT_INTERNAL_H_ */ diff --git a/usr.bin/fstat/msdosfs.c b/lib/libprocstat/msdosfs.c similarity index 81% rename from usr.bin/fstat/msdosfs.c rename to lib/libprocstat/msdosfs.c index 7f80499310e..84b437e6c95 100644 --- a/usr.bin/fstat/msdosfs.c +++ b/lib/libprocstat/msdosfs.c @@ -42,6 +42,8 @@ __FBSDID("$FreeBSD$"); #include #include +#include + #define _KERNEL #include #include @@ -62,9 +64,10 @@ __FBSDID("$FreeBSD$"); * VTODE is defined in denode.h only if _KERNEL is defined, but that leads to * header explosion */ -#define VTODE(vp) ((struct denode *)(vp)->v_data) +#define VTODE(vp) ((struct denode *)getvnodedata(vp)) -#include "fstat.h" +#include "libprocstat.h" +#include "common_kvm.h" struct dosmount { struct dosmount *next; @@ -73,7 +76,7 @@ struct dosmount { }; int -msdosfs_filestat(struct vnode *vp, struct filestat *fsp) +msdosfs_filestat(kvm_t *kd, struct vnode *vp, struct vnstat *vn) { struct denode denode; static struct dosmount *mounts; @@ -81,10 +84,10 @@ msdosfs_filestat(struct vnode *vp, struct filestat *fsp) u_long dirsperblk; int fileid; - if (!KVM_READ(VTODE(vp), &denode, sizeof (denode))) { - dprintf(stderr, "can't read denode at %p for pid %d\n", - (void *)VTODE(vp), Pid); - return 0; + if (!kvm_read_all(kd, (unsigned long)VTODE(vp), &denode, + sizeof(denode))) { + warnx("can't read denode at %p", (void *)VTODE(vp)); + return (1); } /* @@ -96,30 +99,30 @@ msdosfs_filestat(struct vnode *vp, struct filestat *fsp) break; if (!mnt) { - if ((mnt = malloc(sizeof(struct dosmount))) == NULL) - err(1, NULL); - if (!KVM_READ(denode.de_pmp, &mnt->data, sizeof mnt->data)) { + if ((mnt = malloc(sizeof(struct dosmount))) == NULL) { + warn("malloc()"); + return (1); + } + if (!kvm_read_all(kd, (unsigned long)denode.de_pmp, + &mnt->data, sizeof(mnt->data))) { free(mnt); - dprintf(stderr, - "can't read mount info at %p for pid %d\n", - (void *)denode.de_pmp, Pid); - return 0; + warnx("can't read mount info at %p", + (void *)denode.de_pmp); + return (1); } mnt->next = mounts; mounts = mnt; mnt->kptr = denode.de_pmp; } - fsp->fsid = dev2udev(mnt->data.pm_dev); - fsp->mode = 0555; - fsp->mode |= denode.de_Attributes & ATTR_READONLY ? 0 : 0222; - fsp->mode &= mnt->data.pm_mask; + vn->vn_fsid = dev2udev(kd, mnt->data.pm_dev); + vn->vn_mode = 0555; + vn->vn_mode |= denode.de_Attributes & ATTR_READONLY ? 0 : 0222; + vn->vn_mode &= mnt->data.pm_mask; /* Distinguish directories and files. No "special" files in FAT. */ - fsp->mode |= denode.de_Attributes & ATTR_DIRECTORY ? S_IFDIR : S_IFREG; - - fsp->size = denode.de_FileSize; - fsp->rdev = 0; + vn->vn_mode |= denode.de_Attributes & ATTR_DIRECTORY ? S_IFDIR : S_IFREG; + vn->vn_size = denode.de_FileSize; /* * XXX - @@ -145,6 +148,6 @@ msdosfs_filestat(struct vnode *vp, struct filestat *fsp) fileid += denode.de_diroffset / sizeof(struct direntry); } - fsp->fileid = fileid; - return 1; + vn->vn_fileid = fileid; + return (0); } diff --git a/lib/libprocstat/ntfs.c b/lib/libprocstat/ntfs.c new file mode 100644 index 00000000000..888e6cd845e --- /dev/null +++ b/lib/libprocstat/ntfs.c @@ -0,0 +1,71 @@ +/*- + * Copyright (c) 2005-2009 Stanislav Sedov + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ +#include +__FBSDID("$FreeBSD$"); + +#include +#include +#include +#include +#include + +#include + +#include +#include +#include +#include + +#include +#include + +#include "libprocstat.h" +#include "common_kvm.h" + +int +ntfs_filestat(kvm_t *kd, struct vnode *vp, struct vnstat *vn) +{ + struct fnode fnod; + struct ntnode node; + int error; + + assert(kd); + assert(vn); + error = kvm_read_all(kd, (unsigned long)VTOF(vp), &fnod, sizeof(fnod)); + if (error != 0) { + warnx("can't read ntfs fnode at %p", (void *)VTOF(vp)); + return (1); + } + error = kvm_read_all(kd, (unsigned long)FTONT(&fnod), &node, + sizeof(node)); + if (error != 0) { + warnx("can't read ntfs node at %p", (void *)FTONT(&fnod)); + return (1); + } + vn->vn_fileid = node.i_number; + vn->vn_fsid = dev2udev(kd, node.i_dev); + return (0); +} diff --git a/lib/libprocstat/nwfs.c b/lib/libprocstat/nwfs.c new file mode 100644 index 00000000000..006f9aa0e8b --- /dev/null +++ b/lib/libprocstat/nwfs.c @@ -0,0 +1,76 @@ +/*- + * Copyright (c) 2005-2009 Stanislav Sedov + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ +#include +__FBSDID("$FreeBSD$"); + +#include +#include +#include +#include +#define _KERNEL +#include +#undef _KERNEL + +#include + +#include +#include +#include +#include + +#include +#include + +#include "libprocstat.h" +#include "common_kvm.h" + +int +nwfs_filestat(kvm_t *kd, struct vnode *vp, struct vnstat *vn) +{ + struct mount mnt; + struct nwnode node; + int error; + + assert(kd); + assert(vn); + error = kvm_read_all(kd, (unsigned long)VTONW(vp), &node, sizeof(node)); + if (error != 0) { + warnx("can't read nwfs fnode at %p", (void *)VTONW(vp)); + return (1); + } + error = kvm_read_all(kd, (unsigned long)getvnodemount(vp), &mnt, + sizeof(mnt)); + if (error != 0) { + warnx("can't read mount at %p for vnode %p", + (void *)getvnodemount(vp), vp); + return (1); + } + vn->vn_fileid = node.n_fid.f_id; + if (vn->vn_fileid == 0) + vn->vn_fileid = NWFS_ROOT_INO; + vn->vn_fsid = mnt.mnt_stat.f_fsid.val[0]; + return (0); +} diff --git a/lib/libprocstat/smbfs.c b/lib/libprocstat/smbfs.c new file mode 100644 index 00000000000..24d8acdd91b --- /dev/null +++ b/lib/libprocstat/smbfs.c @@ -0,0 +1,77 @@ +/*- + * Copyright (c) 2005-2009 Stanislav Sedov + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ +#include +__FBSDID("$FreeBSD$"); + +#include +#include +#include +#include +#define _KERNEL +#include +#undef _KERNEL + +#include + +#include +#include +#include +#include + +#include +#include + +#include "libprocstat.h" +#include "common_kvm.h" + +int +smbfs_filestat(kvm_t *kd, struct vnode *vp, struct vnstat *vn) +{ + struct smbnode node; + struct mount mnt; + int error; + + assert(kd); + assert(vn); + error = kvm_read_all(kd, (unsigned long)VTOSMB(vp), &node, + sizeof(node)); + if (error != 0) { + warnx("can't read smbfs fnode at %p", (void *)VTOSMB(vp)); + return (1); + } + error = kvm_read_all(kd, (unsigned long)getvnodemount(vp), &mnt, + sizeof(mnt)); + if (error != 0) { + warnx("can't read mount at %p for vnode %p", + (void *)getvnodemount(vp), vp); + return (1); + } + vn->vn_fileid = node.n_ino; + if (vn->vn_fileid == 0) + vn->vn_fileid = 2; + vn->vn_fsid = mnt.mnt_stat.f_fsid.val[0]; + return (0); +} diff --git a/lib/libprocstat/udf.c b/lib/libprocstat/udf.c new file mode 100644 index 00000000000..5d9310e9dcd --- /dev/null +++ b/lib/libprocstat/udf.c @@ -0,0 +1,102 @@ +/*- + * Copyright (c) 2005-2009 Stanislav Sedov + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ +#include +__FBSDID("$FreeBSD$"); + +#include +#include +#include +#include +#include +#define _KERNEL +#include +#undef _KERNEL + +#include + +#include +#include +#include +#include + +#include + +#include "libprocstat.h" +#include "common_kvm.h" + +/* XXX */ +struct udf_mnt { + int im_flags; + struct mount *im_mountp; + struct g_consumer *im_cp; + struct bufobj *im_bo; + struct cdev *im_dev; + struct vnode *im_devvp; + int bsize; + int bshift; + int bmask; + uint32_t part_start; + uint32_t part_len; + uint64_t root_id; + struct long_ad root_icb; + int p_sectors; + int s_table_entries; + void *s_table; + void *im_d2l; +}; +struct udf_node { + struct vnode *i_vnode; + struct udf_mnt *udfmp; + ino_t hash_id; + long diroff; + struct file_entry *fentry; +}; +#define VTON(vp) ((struct udf_node *)((vp)->v_data)) + +int +udf_filestat(kvm_t *kd, struct vnode *vp, struct vnstat *vn) +{ + struct udf_node node; + struct udf_mnt mnt; + int error; + + assert(kd); + assert(vn); + error = kvm_read_all(kd, (unsigned long)VTON(vp), &node, sizeof(node)); + if (error != 0) { + warnx("can't read udf fnode at %p", (void *)VTON(vp)); + return (1); + } + error = kvm_read_all(kd, (unsigned long)node.udfmp, &mnt, sizeof(mnt)); + if (error != 0) { + warnx("can't read udf_mnt at %p for vnode %p", + (void *)node.udfmp, vp); + return (1); + } + vn->vn_fileid = node.hash_id; + vn->vn_fsid = dev2udev(kd, mnt.im_dev); + return (0); +} diff --git a/usr.bin/fstat/zfs.c b/lib/libprocstat/zfs.c similarity index 79% rename from usr.bin/fstat/zfs.c rename to lib/libprocstat/zfs.c index cdca41ff1a7..aa6d78e3f40 100644 --- a/usr.bin/fstat/zfs.c +++ b/lib/libprocstat/zfs.c @@ -45,14 +45,16 @@ #include #include +#include + #include #include #include #include #define ZFS -#undef dprintf -#include +#include "libprocstat.h" +#include "common_kvm.h" /* * Offset calculations that are used to get data from znode without having the @@ -62,7 +64,7 @@ #define LOCATION_ZPHYS(zsize) ((zsize) - (2 * sizeof(void *) + sizeof(struct task))) int -zfs_filestat(struct vnode *vp, struct filestat *fsp) +zfs_filestat(kvm_t *kd, struct vnode *vp, struct vnstat *vn) { znode_phys_t zphys; @@ -76,20 +78,19 @@ zfs_filestat(struct vnode *vp, struct filestat *fsp) len = sizeof(size); if (sysctlbyname("debug.sizeof.znode", &size, &len, NULL, 0) == -1) { - dprintf(stderr, "error getting sysctl\n"); - return (0); + warnx("error getting sysctl"); + return (1); } znodeptr = malloc(size); if (znodeptr == NULL) { - dprintf(stderr, "error allocating memory for znode storage\n"); - return (0); + warnx("error allocating memory for znode storage"); + return (1); } - /* Since we have problems including vnode.h, we'll use the wrappers. */ vnodeptr = getvnodedata(vp); - if (!KVM_READ(vnodeptr, znodeptr, (size_t)size)) { - dprintf(stderr, "can't read znode at %p for pid %d\n", - (void *)vnodeptr, Pid); + if (!kvm_read_all(kd, (unsigned long)vnodeptr, znodeptr, + (size_t)size)) { + warnx("can't read znode at %p", (void *)vnodeptr); goto bad; } @@ -104,33 +105,30 @@ zfs_filestat(struct vnode *vp, struct filestat *fsp) zid = (uint64_t *)(dataptr + LOCATION_ZID); zphys_addr = *(void **)(dataptr + LOCATION_ZPHYS(size)); - if (!KVM_READ(zphys_addr, &zphys, sizeof(zphys))) { - dprintf(stderr, "can't read znode_phys at %p for pid %d\n", - zphys_addr, Pid); + if (!kvm_read_all(kd, (unsigned long)zphys_addr, &zphys, + sizeof(zphys))) { + warnx("can't read znode_phys at %p", zphys_addr); goto bad; } /* Get the mount pointer, and read from the address. */ mountptr = getvnodemount(vp); - if (!KVM_READ(mountptr, &mount, sizeof(mount))) { - dprintf(stderr, "can't read mount at %p for pid %d\n", - (void *)mountptr, Pid); + if (!kvm_read_all(kd, (unsigned long)mountptr, &mount, sizeof(mount))) { + warnx("can't read mount at %p", (void *)mountptr); goto bad; } - - fsp->fsid = (long)(uint32_t)mount.mnt_stat.f_fsid.val[0]; - fsp->fileid = *zid; + vn->vn_fsid = mount.mnt_stat.f_fsid.val[0]; + vn->vn_fileid = *zid; /* * XXX: Shows up wrong in output, but UFS has this error too. Could * be that we're casting mode-variables from 64-bit to 8-bit or simply * error in the mode-to-string function. */ - fsp->mode = (mode_t)zphys.zp_mode; - fsp->size = (u_long)zphys.zp_size; - fsp->rdev = (dev_t)zphys.zp_rdev; - free(znodeptr); - return (1); -bad: + vn->vn_mode = (mode_t)zphys.zp_mode; + vn->vn_size = (u_long)zphys.zp_size; free(znodeptr); return (0); +bad: + free(znodeptr); + return (1); } diff --git a/usr.bin/fstat/zfs/Makefile b/lib/libprocstat/zfs/Makefile similarity index 100% rename from usr.bin/fstat/zfs/Makefile rename to lib/libprocstat/zfs/Makefile diff --git a/lib/libutil/Makefile b/lib/libutil/Makefile index 9dc35c0f9ef..b2378adf768 100644 --- a/lib/libutil/Makefile +++ b/lib/libutil/Makefile @@ -9,7 +9,8 @@ LIB= util SHLIB_MAJOR= 9 SRCS= _secure_path.c auth.c expand_number.c flopen.c fparseln.c gr_util.c \ - hexdump.c humanize_number.c kinfo_getfile.c kinfo_getvmmap.c kld.c \ + hexdump.c humanize_number.c kinfo_getfile.c kinfo_getfile.c \ + kinfo_getallproc.c kinfo_getproc.c kinfo_getvmmap.c kld.c \ login_auth.c login_cap.c \ login_class.c login_crypt.c login_ok.c login_times.c login_tty.c \ pidfile.c property.c pty.c pw_util.c quotafile.c realhostname.c \ @@ -29,7 +30,8 @@ MAN+= kld.3 login_auth.3 login_tty.3 pty.3 \ _secure_path.3 uucplock.3 property.3 auth.3 realhostname.3 \ realhostname_sa.3 trimdomain.3 fparseln.3 humanize_number.3 \ pidfile.3 flopen.3 expand_number.3 hexdump.3 \ - kinfo_getfile.3 kinfo_getvmmap.3 quotafile.3 + kinfo_getfile.3 kinfo_getallproc.3 kinfo_getproc.3 \ + kinfo_getvmmap.3 quotafile.3 MAN+= login.conf.5 auth.conf.5 MLINKS+= kld.3 kld_isloaded.3 kld.3 kld_load.3 MLINKS+= property.3 properties_read.3 property.3 properties_free.3 diff --git a/lib/libutil/kinfo_getallproc.3 b/lib/libutil/kinfo_getallproc.3 new file mode 100644 index 00000000000..73981ae36be --- /dev/null +++ b/lib/libutil/kinfo_getallproc.3 @@ -0,0 +1,74 @@ +.\" +.\" Copyright (c) 2009 Ulf Lilleengen +.\" All rights reserved. +.\" +.\" Redistribution and use in source and binary forms, with or without +.\" modification, are permitted provided that the following conditions +.\" are met: +.\" 1. Redistributions of source code must retain the above copyright +.\" notice, this list of conditions and the following disclaimer. +.\" 2. Redistributions in binary form must reproduce the above copyright +.\" notice, this list of conditions and the following disclaimer in the +.\" documentation and/or other materials provided with the distribution. +.\" +.\" THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND +.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +.\" ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE +.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS +.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) +.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY +.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF +.\" SUCH DAMAGE. +.\" +.\" $FreeBSD$ +.\" +.Dd July 9, 2009 +.Os +.Dt KINFO_GETALLPROC 3 +.Sh NAME +.Nm kinfo_getallproc +.Nd function for getting process information of all processes from kernel +.Sh LIBRARY +.Lb libutil +.Sh SYNOPSIS +.In sys/types.h +.In libutil.h +.Ft struct kinfo_proc * +.Fn kinfo_getallproc "int *cntp" +.Sh DESCRIPTION +This function is used for obtaining process information of all processes from +the kernel. +.Pp +The +.Ar cntp +field is a pointer containing the number of process structures returned. +This function is a wrapper around +.Xr sysctl 3 +with the +.Dv KERN_PROC_PROC +mib. +While the kernel returns a packed structure, this function expands the +data into a fixed record format. +.Sh RETURN VALUES +On success the +.Fn kinfo_getallproc +function returns a pointer to +.Ar cntp +.Vt struct kinfo_proc +structures as defined by +.In sys/user.h . +The pointer was obtained by an internal call to +.Xr malloc 3 +and must be freed by the caller with a call to +.Xr free 3 . +On failure the +.Fn kinfo_getallproc +function returns +.Dv NULL . +.Sh SEE ALSO +.Xr free 3 , +.Xr malloc 3 , +.Xr sysctl 3 diff --git a/lib/libutil/kinfo_getallproc.c b/lib/libutil/kinfo_getallproc.c new file mode 100644 index 00000000000..0f43ce2e1ad --- /dev/null +++ b/lib/libutil/kinfo_getallproc.c @@ -0,0 +1,98 @@ +/*- + * Copyright (c) 2007 Robert N. M. Watson + * Copyright (c) 2009 Ulf Lilleengen + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * $FreeBSD$ + */ + +#include +__FBSDID("$FreeBSD$"); + +#include +#include +#include +#include +#include + +#include "libutil.h" + + +/* + * Sort processes first by pid and then tid. + */ +static int +kinfo_proc_compare(const void *a, const void *b) +{ + int i; + + i = ((const struct kinfo_proc *)a)->ki_pid - + ((const struct kinfo_proc *)b)->ki_pid; + if (i != 0) + return (i); + i = ((const struct kinfo_proc *)a)->ki_tid - + ((const struct kinfo_proc *)b)->ki_tid; + return (i); +} + +static void +kinfo_proc_sort(struct kinfo_proc *kipp, int count) +{ + + qsort(kipp, count, sizeof(*kipp), kinfo_proc_compare); +} + +struct kinfo_proc * +kinfo_getallproc(int *cntp) +{ + struct kinfo_proc *kipp; + size_t len; + int mib[3]; + + mib[0] = CTL_KERN; + mib[1] = KERN_PROC; + mib[2] = KERN_PROC_PROC; + + len = 0; + if (sysctl(mib, 3, NULL, &len, NULL, 0) < 0) + return (NULL); + + kipp = malloc(len); + if (kipp == NULL) + return (NULL); + + if (sysctl(mib, 3, kipp, &len, NULL, 0) < 0) + goto bad; + if (len % sizeof(*kipp) != 0) + goto bad; + if (kipp->ki_structsize != sizeof(*kipp)) + goto bad; + *cntp = len / sizeof(*kipp); + kinfo_proc_sort(kipp, len / sizeof(*kipp)); + return (kipp); +bad: + *cntp = 0; + free(kipp); + return (NULL); +} diff --git a/lib/libutil/kinfo_getproc.3 b/lib/libutil/kinfo_getproc.3 new file mode 100644 index 00000000000..2778ad1fc56 --- /dev/null +++ b/lib/libutil/kinfo_getproc.3 @@ -0,0 +1,73 @@ +.\" +.\" Copyright (c) 2009 Ulf Lilleengen +.\" All rights reserved. +.\" +.\" Redistribution and use in source and binary forms, with or without +.\" modification, are permitted provided that the following conditions +.\" are met: +.\" 1. Redistributions of source code must retain the above copyright +.\" notice, this list of conditions and the following disclaimer. +.\" 2. Redistributions in binary form must reproduce the above copyright +.\" notice, this list of conditions and the following disclaimer in the +.\" documentation and/or other materials provided with the distribution. +.\" +.\" THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND +.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +.\" ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE +.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS +.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) +.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY +.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF +.\" SUCH DAMAGE. +.\" +.\" $FreeBSD$ +.\" +.Dd July 9, 2009 +.Os +.Dt KINFO_GETPROC 3 +.Sh NAME +.Nm kinfo_getproc +.Nd function for getting process information from kernel +.Sh LIBRARY +.Lb libutil +.Sh SYNOPSIS +.In sys/types.h +.In libutil.h +.Ft struct kinfo_proc * +.Fn kinfo_getproc "pid_t pid" "int *cntp" +.Sh DESCRIPTION +This function is used for obtaining process information from the kernel. +.Pp +The +.Ar pid +field contains the process identifier. +This should be the a process that you have privilige to access. +This function is a wrapper around +.Xr sysctl 3 +with the +.Dv KERN_PROC_PID +mib. +While the kernel returns a packed structure, this function expands the +data into a fixed record format. +.Sh RETURN VALUES +On success the +.Fn kinfo_getproc +function returns a pointer to a +.Vt struct kinfo_proc +structure as defined by +.In sys/user.h . +The pointer was obtained by an internal call to +.Xr malloc 3 +and must be freed by the caller with a call to +.Xr free 3 . +On failure the +.Fn kinfo_getproc +function returns +.Dv NULL . +.Sh SEE ALSO +.Xr free 3 , +.Xr malloc 3 , +.Xr sysctl 3 diff --git a/lib/libutil/kinfo_getproc.c b/lib/libutil/kinfo_getproc.c new file mode 100644 index 00000000000..2ae6b57ee71 --- /dev/null +++ b/lib/libutil/kinfo_getproc.c @@ -0,0 +1,71 @@ +/*- + * Copyright (c) 2009 Ulf Lilleengen + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * $FreeBSD$ + */ + +#include +__FBSDID("$FreeBSD$"); + +#include +#include +#include +#include +#include + +#include "libutil.h" + +struct kinfo_proc * +kinfo_getproc(pid_t pid) +{ + struct kinfo_proc *kipp; + int mib[4]; + size_t len; + + len = 0; + mib[0] = CTL_KERN; + mib[1] = KERN_PROC; + mib[2] = KERN_PROC_PID; + mib[3] = pid; + if (sysctl(mib, 4, NULL, &len, NULL, 0) < 0) + return (NULL); + + kipp = malloc(len); + if (kipp == NULL) + return (NULL); + + if (sysctl(mib, 4, kipp, &len, NULL, 0) < 0) + goto bad; + if (len != sizeof(*kipp)) + goto bad; + if (kipp->ki_structsize != sizeof(*kipp)) + goto bad; + if (kipp->ki_pid != pid) + goto bad; + return (kipp); +bad: + free(kipp); + return (NULL); +} diff --git a/lib/libutil/libutil.h b/lib/libutil/libutil.h index f39e4f591df..fc6d3bb184f 100644 --- a/lib/libutil/libutil.h +++ b/lib/libutil/libutil.h @@ -88,6 +88,7 @@ struct termios; struct winsize; struct in_addr; struct kinfo_file; +struct kinfo_proc; struct kinfo_vmentry; __BEGIN_DECLS @@ -126,6 +127,10 @@ struct kinfo_file * kinfo_getfile(pid_t _pid, int *_cntp); struct kinfo_vmentry * kinfo_getvmmap(pid_t _pid, int *_cntp); +struct kinfo_proc * + kinfo_getallproc(int *_cntp); +struct kinfo_proc * + kinfo_getproc(pid_t _pid); #ifdef _STDIO_H_ /* avoid adding new includes */ char *fparseln(FILE *, size_t *, size_t *, const char[3], int); diff --git a/sys/kern/kern_descrip.c b/sys/kern/kern_descrip.c index 3f40f2b5cea..bf75db0deb9 100644 --- a/sys/kern/kern_descrip.c +++ b/sys/kern/kern_descrip.c @@ -59,6 +59,8 @@ __FBSDID("$FreeBSD$"); #include #include #include +#include +#include #include #include #include @@ -73,6 +75,8 @@ __FBSDID("$FreeBSD$"); #include #include #include +#include +#include #include #include #ifdef KTRACE @@ -81,6 +85,9 @@ __FBSDID("$FreeBSD$"); #include +#include +#include + #include #include @@ -106,6 +113,10 @@ static int fd_last_used(struct filedesc *, int, int); static void fdgrowtable(struct filedesc *, int); static void fdunused(struct filedesc *fdp, int fd); static void fdused(struct filedesc *fdp, int fd); +static int fill_vnode_info(struct vnode *vp, struct kinfo_file *kif); +static int fill_socket_info(struct socket *so, struct kinfo_file *kif); +static int fill_pts_info(struct tty *tp, struct kinfo_file *kif); +static int fill_pipe_info(struct pipe *pi, struct kinfo_file *kif); /* * A process is initially started out with NDFILE descriptors stored within @@ -2972,48 +2983,74 @@ CTASSERT(sizeof(struct kinfo_file) == KINFO_FILE_SIZE); #endif static int -export_vnode_for_sysctl(struct vnode *vp, int type, - struct kinfo_file *kif, struct filedesc *fdp, struct sysctl_req *req) +export_fd_for_sysctl(void *data, int type, int fd, int fflags, int refcnt, + int64_t offset, struct kinfo_file *kif, struct sysctl_req *req) { - int error; - char *fullpath, *freepath; - int vfslocked; + struct { + int fflag; + int kf_fflag; + } fflags_table[] = { + { FAPPEND, KF_FLAG_APPEND }, + { FASYNC, KF_FLAG_ASYNC }, + { FFSYNC, KF_FLAG_FSYNC }, + { FHASLOCK, KF_FLAG_HASLOCK }, + { FNONBLOCK, KF_FLAG_NONBLOCK }, + { FREAD, KF_FLAG_READ }, + { FWRITE, KF_FLAG_WRITE }, + { O_CREAT, KF_FLAG_CREAT }, + { O_DIRECT, KF_FLAG_DIRECT }, + { O_EXCL, KF_FLAG_EXCL }, + { O_EXEC, KF_FLAG_EXEC }, + { O_EXLOCK, KF_FLAG_EXLOCK }, + { O_NOFOLLOW, KF_FLAG_NOFOLLOW }, + { O_SHLOCK, KF_FLAG_SHLOCK }, + { O_TRUNC, KF_FLAG_TRUNC } + }; +#define NFFLAGS (sizeof(fflags_table) / sizeof(*fflags_table)) + struct vnode *vp; + int error, vfslocked; + unsigned int i; bzero(kif, sizeof(*kif)); - - vref(vp); - kif->kf_fd = type; - kif->kf_type = KF_TYPE_VNODE; - /* This function only handles directories. */ - if (vp->v_type != VDIR) { + switch (type) { + case KF_TYPE_FIFO: + case KF_TYPE_VNODE: + vp = (struct vnode *)data; + error = fill_vnode_info(vp, kif); + vfslocked = VFS_LOCK_GIANT(vp->v_mount); vrele(vp); - return (ENOTDIR); + VFS_UNLOCK_GIANT(vfslocked); + break; + case KF_TYPE_SOCKET: + error = fill_socket_info((struct socket *)data, kif); + break; + case KF_TYPE_PIPE: + error = fill_pipe_info((struct pipe *)data, kif); + break; + case KF_TYPE_PTS: + error = fill_pts_info((struct tty *)data, kif); + break; + default: + error = 0; } - kif->kf_vnode_type = KF_VTYPE_VDIR; + if (error == 0) + kif->kf_status |= KF_ATTR_VALID; /* - * This is not a true file descriptor, so we set a bogus refcount - * and offset to indicate these fields should be ignored. + * Translate file access flags. */ - kif->kf_ref_count = -1; - kif->kf_offset = -1; - - freepath = NULL; - fullpath = "-"; - FILEDESC_SUNLOCK(fdp); - vn_fullpath(curthread, vp, &fullpath, &freepath); - vfslocked = VFS_LOCK_GIANT(vp->v_mount); - vrele(vp); - VFS_UNLOCK_GIANT(vfslocked); - strlcpy(kif->kf_path, fullpath, sizeof(kif->kf_path)); - if (freepath != NULL) - free(freepath, M_TEMP); + for (i = 0; i < NFFLAGS; i++) + if (fflags & fflags_table[i].fflag) + kif->kf_flags |= fflags_table[i].kf_fflag; + kif->kf_fd = fd; + kif->kf_type = type; + kif->kf_ref_count = refcnt; + kif->kf_offset = offset; /* Pack record size down */ kif->kf_structsize = offsetof(struct kinfo_file, kf_path) + strlen(kif->kf_path) + 1; kif->kf_structsize = roundup(kif->kf_structsize, sizeof(uint64_t)); error = SYSCTL_OUT(req, kif, kif->kf_structsize); - FILEDESC_SLOCK(fdp); return (error); } @@ -3023,17 +3060,16 @@ export_vnode_for_sysctl(struct vnode *vp, int type, static int sysctl_kern_proc_filedesc(SYSCTL_HANDLER_ARGS) { - char *fullpath, *freepath; - struct kinfo_file *kif; - struct filedesc *fdp; - int error, i, *name; - struct socket *so; - struct vnode *vp; struct file *fp; + struct filedesc *fdp; + struct kinfo_file *kif; struct proc *p; - struct tty *tp; - int vfslocked; + struct vnode *cttyvp, *textvp, *tracevp; size_t oldidx; + int64_t offset; + void *data; + int error, i, *name; + int type, refcnt, fflags; name = (int *)arg1; if ((p = pfind((pid_t)name[0])) == NULL) @@ -3042,177 +3078,136 @@ sysctl_kern_proc_filedesc(SYSCTL_HANDLER_ARGS) PROC_UNLOCK(p); return (error); } + /* ktrace vnode */ + tracevp = p->p_tracevp; + if (tracevp != NULL) + vref(tracevp); + /* text vnode */ + textvp = p->p_textvp; + if (textvp != NULL) + vref(textvp); + /* Controlling tty. */ + cttyvp = NULL; + if (p->p_pgrp != NULL && p->p_pgrp->pg_session != NULL) { + cttyvp = p->p_pgrp->pg_session->s_ttyvp; + if (cttyvp != NULL) + vref(cttyvp); + } fdp = fdhold(p); PROC_UNLOCK(p); - if (fdp == NULL) - return (ENOENT); kif = malloc(sizeof(*kif), M_TEMP, M_WAITOK); + if (tracevp != NULL) + export_fd_for_sysctl(tracevp, KF_TYPE_VNODE, KF_FD_TYPE_TRACE, + FREAD | FWRITE, -1, -1, kif, req); + if (textvp != NULL) + export_fd_for_sysctl(textvp, KF_TYPE_VNODE, KF_FD_TYPE_TEXT, + FREAD, -1, -1, kif, req); + if (cttyvp != NULL) + export_fd_for_sysctl(cttyvp, KF_TYPE_VNODE, KF_FD_TYPE_CTTY, + FREAD | FWRITE, -1, -1, kif, req); + if (fdp == NULL) + goto fail; FILEDESC_SLOCK(fdp); - if (fdp->fd_cdir != NULL) - export_vnode_for_sysctl(fdp->fd_cdir, KF_FD_TYPE_CWD, kif, - fdp, req); - if (fdp->fd_rdir != NULL) - export_vnode_for_sysctl(fdp->fd_rdir, KF_FD_TYPE_ROOT, kif, - fdp, req); - if (fdp->fd_jdir != NULL) - export_vnode_for_sysctl(fdp->fd_jdir, KF_FD_TYPE_JAIL, kif, - fdp, req); + /* working directory */ + if (fdp->fd_cdir != NULL) { + vref(fdp->fd_cdir); + data = fdp->fd_cdir; + FILEDESC_SUNLOCK(fdp); + export_fd_for_sysctl(data, KF_TYPE_VNODE, KF_FD_TYPE_CWD, + FREAD, -1, -1, kif, req); + FILEDESC_SLOCK(fdp); + } + /* root directory */ + if (fdp->fd_rdir != NULL) { + vref(fdp->fd_rdir); + data = fdp->fd_rdir; + FILEDESC_SUNLOCK(fdp); + export_fd_for_sysctl(data, KF_TYPE_VNODE, KF_FD_TYPE_ROOT, + FREAD, -1, -1, kif, req); + FILEDESC_SLOCK(fdp); + } + /* jail directory */ + if (fdp->fd_jdir != NULL) { + vref(fdp->fd_jdir); + data = fdp->fd_jdir; + FILEDESC_SUNLOCK(fdp); + export_fd_for_sysctl(data, KF_TYPE_VNODE, KF_FD_TYPE_JAIL, + FREAD, -1, -1, kif, req); + FILEDESC_SLOCK(fdp); + } for (i = 0; i < fdp->fd_nfiles; i++) { if ((fp = fdp->fd_ofiles[i]) == NULL) continue; - bzero(kif, sizeof(*kif)); - vp = NULL; - so = NULL; - tp = NULL; - kif->kf_fd = i; + data = NULL; switch (fp->f_type) { case DTYPE_VNODE: - kif->kf_type = KF_TYPE_VNODE; - vp = fp->f_vnode; + type = KF_TYPE_VNODE; + vref(fp->f_vnode); + data = fp->f_vnode; break; case DTYPE_SOCKET: - kif->kf_type = KF_TYPE_SOCKET; - so = fp->f_data; + type = KF_TYPE_SOCKET; + data = fp->f_data; break; case DTYPE_PIPE: - kif->kf_type = KF_TYPE_PIPE; + type = KF_TYPE_PIPE; + data = fp->f_data; break; case DTYPE_FIFO: - kif->kf_type = KF_TYPE_FIFO; - vp = fp->f_vnode; + type = KF_TYPE_FIFO; + vref(fp->f_vnode); + data = fp->f_vnode; break; case DTYPE_KQUEUE: - kif->kf_type = KF_TYPE_KQUEUE; + type = KF_TYPE_KQUEUE; break; case DTYPE_CRYPTO: - kif->kf_type = KF_TYPE_CRYPTO; + type = KF_TYPE_CRYPTO; break; case DTYPE_MQUEUE: - kif->kf_type = KF_TYPE_MQUEUE; + type = KF_TYPE_MQUEUE; break; case DTYPE_SHM: - kif->kf_type = KF_TYPE_SHM; + type = KF_TYPE_SHM; break; case DTYPE_SEM: - kif->kf_type = KF_TYPE_SEM; + type = KF_TYPE_SEM; break; case DTYPE_PTS: - kif->kf_type = KF_TYPE_PTS; - tp = fp->f_data; + type = KF_TYPE_PTS; + data = fp->f_data; break; default: - kif->kf_type = KF_TYPE_UNKNOWN; + type = KF_TYPE_UNKNOWN; break; } - kif->kf_ref_count = fp->f_count; - if (fp->f_flag & FREAD) - kif->kf_flags |= KF_FLAG_READ; - if (fp->f_flag & FWRITE) - kif->kf_flags |= KF_FLAG_WRITE; - if (fp->f_flag & FAPPEND) - kif->kf_flags |= KF_FLAG_APPEND; - if (fp->f_flag & FASYNC) - kif->kf_flags |= KF_FLAG_ASYNC; - if (fp->f_flag & FFSYNC) - kif->kf_flags |= KF_FLAG_FSYNC; - if (fp->f_flag & FNONBLOCK) - kif->kf_flags |= KF_FLAG_NONBLOCK; - if (fp->f_flag & O_DIRECT) - kif->kf_flags |= KF_FLAG_DIRECT; - if (fp->f_flag & FHASLOCK) - kif->kf_flags |= KF_FLAG_HASLOCK; - kif->kf_offset = fp->f_offset; - if (vp != NULL) { - vref(vp); - switch (vp->v_type) { - case VNON: - kif->kf_vnode_type = KF_VTYPE_VNON; - break; - case VREG: - kif->kf_vnode_type = KF_VTYPE_VREG; - break; - case VDIR: - kif->kf_vnode_type = KF_VTYPE_VDIR; - break; - case VBLK: - kif->kf_vnode_type = KF_VTYPE_VBLK; - break; - case VCHR: - kif->kf_vnode_type = KF_VTYPE_VCHR; - break; - case VLNK: - kif->kf_vnode_type = KF_VTYPE_VLNK; - break; - case VSOCK: - kif->kf_vnode_type = KF_VTYPE_VSOCK; - break; - case VFIFO: - kif->kf_vnode_type = KF_VTYPE_VFIFO; - break; - case VBAD: - kif->kf_vnode_type = KF_VTYPE_VBAD; - break; - default: - kif->kf_vnode_type = KF_VTYPE_UNKNOWN; - break; - } - /* - * It is OK to drop the filedesc lock here as we will - * re-validate and re-evaluate its properties when - * the loop continues. - */ - freepath = NULL; - fullpath = "-"; - FILEDESC_SUNLOCK(fdp); - vn_fullpath(curthread, vp, &fullpath, &freepath); - vfslocked = VFS_LOCK_GIANT(vp->v_mount); - vrele(vp); - VFS_UNLOCK_GIANT(vfslocked); - strlcpy(kif->kf_path, fullpath, - sizeof(kif->kf_path)); - if (freepath != NULL) - free(freepath, M_TEMP); - FILEDESC_SLOCK(fdp); - } - if (so != NULL) { - struct sockaddr *sa; + refcnt = fp->f_count; + fflags = fp->f_flag; + offset = fp->f_offset; - if (so->so_proto->pr_usrreqs->pru_sockaddr(so, &sa) - == 0 && sa->sa_len <= sizeof(kif->kf_sa_local)) { - bcopy(sa, &kif->kf_sa_local, sa->sa_len); - free(sa, M_SONAME); - } - if (so->so_proto->pr_usrreqs->pru_peeraddr(so, &sa) - == 0 && sa->sa_len <= sizeof(kif->kf_sa_peer)) { - bcopy(sa, &kif->kf_sa_peer, sa->sa_len); - free(sa, M_SONAME); - } - kif->kf_sock_domain = - so->so_proto->pr_domain->dom_family; - kif->kf_sock_type = so->so_type; - kif->kf_sock_protocol = so->so_proto->pr_protocol; - } - if (tp != NULL) { - strlcpy(kif->kf_path, tty_devname(tp), - sizeof(kif->kf_path)); - } - /* Pack record size down */ - kif->kf_structsize = offsetof(struct kinfo_file, kf_path) + - strlen(kif->kf_path) + 1; - kif->kf_structsize = roundup(kif->kf_structsize, - sizeof(uint64_t)); + /* + * Create sysctl entry. + * It is OK to drop the filedesc lock here as we will + * re-validate and re-evaluate its properties when + * the loop continues. + */ oldidx = req->oldidx; - error = SYSCTL_OUT(req, kif, kif->kf_structsize); + if (type == KF_TYPE_VNODE || type == KF_TYPE_FIFO) + FILEDESC_SUNLOCK(fdp); + error = export_fd_for_sysctl(data, type, i, + fflags, refcnt, offset, kif, req); + if (type == KF_TYPE_VNODE || type == KF_TYPE_FIFO) + FILEDESC_SLOCK(fdp); if (error) { if (error == ENOMEM) { /* @@ -3228,11 +3223,164 @@ sysctl_kern_proc_filedesc(SYSCTL_HANDLER_ARGS) } } FILEDESC_SUNLOCK(fdp); +fail: fddrop(fdp); free(kif, M_TEMP); return (error); } +int +vntype_to_kinfo(int vtype) +{ + struct { + int vtype; + int kf_vtype; + } vtypes_table[] = { + { VBAD, KF_VTYPE_VBAD }, + { VBLK, KF_VTYPE_VBLK }, + { VCHR, KF_VTYPE_VCHR }, + { VDIR, KF_VTYPE_VDIR }, + { VFIFO, KF_VTYPE_VFIFO }, + { VLNK, KF_VTYPE_VLNK }, + { VNON, KF_VTYPE_VNON }, + { VREG, KF_VTYPE_VREG }, + { VSOCK, KF_VTYPE_VSOCK } + }; +#define NVTYPES (sizeof(vtypes_table) / sizeof(*vtypes_table)) + unsigned int i; + + /* + * Perform vtype translation. + */ + for (i = 0; i < NVTYPES; i++) + if (vtypes_table[i].vtype == vtype) + break; + if (i < NVTYPES) + return (vtypes_table[i].kf_vtype); + + return (KF_VTYPE_UNKNOWN); +} + +static int +fill_vnode_info(struct vnode *vp, struct kinfo_file *kif) +{ + struct vattr va; + char *fullpath, *freepath; + int error, vfslocked; + + if (vp == NULL) + return (1); + kif->kf_vnode_type = vntype_to_kinfo(vp->v_type); + freepath = NULL; + fullpath = "-"; + error = vn_fullpath(curthread, vp, &fullpath, &freepath); + if (error == 0) { + strlcpy(kif->kf_path, fullpath, sizeof(kif->kf_path)); + } + if (freepath != NULL) + free(freepath, M_TEMP); + + /* + * Retrieve vnode attributes. + */ + va.va_fsid = VNOVAL; + va.va_rdev = NODEV; + vfslocked = VFS_LOCK_GIANT(vp->v_mount); + vn_lock(vp, LK_SHARED | LK_RETRY); + error = VOP_GETATTR(vp, &va, curthread->td_ucred); + VOP_UNLOCK(vp, 0); + VFS_UNLOCK_GIANT(vfslocked); + if (error != 0) + return (error); + if (va.va_fsid != VNOVAL) + kif->kf_un.kf_file.kf_file_fsid = va.va_fsid; + else + kif->kf_un.kf_file.kf_file_fsid = + vp->v_mount->mnt_stat.f_fsid.val[0]; + kif->kf_un.kf_file.kf_file_fileid = va.va_fileid; + kif->kf_un.kf_file.kf_file_mode = MAKEIMODE(va.va_type, va.va_mode); + kif->kf_un.kf_file.kf_file_size = va.va_size; + kif->kf_un.kf_file.kf_file_rdev = va.va_rdev; + return (0); +} + +static int +fill_socket_info(struct socket *so, struct kinfo_file *kif) +{ + struct sockaddr *sa; + struct inpcb *inpcb; + struct unpcb *unpcb; + int error; + + if (so == NULL) + return (1); + kif->kf_sock_domain = so->so_proto->pr_domain->dom_family; + kif->kf_sock_type = so->so_type; + kif->kf_sock_protocol = so->so_proto->pr_protocol; + kif->kf_un.kf_sock.kf_sock_pcb = (uintptr_t)so->so_pcb; + switch(kif->kf_sock_domain) { + case AF_INET: + case AF_INET6: + if (kif->kf_sock_protocol == IPPROTO_TCP) { + if (so->so_pcb != NULL) { + inpcb = (struct inpcb *)(so->so_pcb); + kif->kf_un.kf_sock.kf_sock_inpcb = + (uintptr_t)inpcb->inp_ppcb; + } + } + break; + case AF_UNIX: + if (so->so_pcb != NULL) { + unpcb = (struct unpcb *)(so->so_pcb); + if (unpcb->unp_conn) { + kif->kf_un.kf_sock.kf_sock_unpconn = + (uintptr_t)unpcb->unp_conn; + kif->kf_un.kf_sock.kf_sock_rcv_sb_state = + so->so_rcv.sb_state; + kif->kf_un.kf_sock.kf_sock_snd_sb_state = + so->so_snd.sb_state; + } + } + break; + } + error = so->so_proto->pr_usrreqs->pru_sockaddr(so, &sa); + if (error == 0 && sa->sa_len <= sizeof(kif->kf_sa_local)) { + bcopy(sa, &kif->kf_sa_local, sa->sa_len); + free(sa, M_SONAME); + } + error = so->so_proto->pr_usrreqs->pru_peeraddr(so, &sa); + if (error == 0 && sa->sa_len <= sizeof(kif->kf_sa_peer)) { + bcopy(sa, &kif->kf_sa_peer, sa->sa_len); + free(sa, M_SONAME); + } + strncpy(kif->kf_path, so->so_proto->pr_domain->dom_name, + sizeof(kif->kf_path)); + return (0); +} + +static int +fill_pts_info(struct tty *tp, struct kinfo_file *kif) +{ + + if (tp == NULL) + return (1); + kif->kf_un.kf_pts.kf_pts_dev = tty_udev(tp); + strlcpy(kif->kf_path, tty_devname(tp), sizeof(kif->kf_path)); + return (0); +} + +static int +fill_pipe_info(struct pipe *pi, struct kinfo_file *kif) +{ + + if (pi == NULL) + return (1); + kif->kf_un.kf_pipe.kf_pipe_addr = (uintptr_t)pi; + kif->kf_un.kf_pipe.kf_pipe_peer = (uintptr_t)pi->pipe_peer; + kif->kf_un.kf_pipe.kf_pipe_buffer_cnt = pi->pipe_buffer.cnt; + return (0); +} + static SYSCTL_NODE(_kern_proc, KERN_PROC_FILEDESC, filedesc, CTLFLAG_RD, sysctl_kern_proc_filedesc, "Process filedesc entries"); diff --git a/sys/kern/kern_proc.c b/sys/kern/kern_proc.c index 34cc57071d4..4f1dc4567f1 100644 --- a/sys/kern/kern_proc.c +++ b/sys/kern/kern_proc.c @@ -1757,8 +1757,6 @@ sysctl_kern_proc_vmmap(SYSCTL_HANDLER_ARGS) last_timestamp = map->timestamp; vm_map_unlock_read(map); - kve->kve_fileid = 0; - kve->kve_fsid = 0; freepath = NULL; fullpath = ""; if (lobj) { @@ -1800,12 +1798,18 @@ sysctl_kern_proc_vmmap(SYSCTL_HANDLER_ARGS) if (vp != NULL) { vn_fullpath(curthread, vp, &fullpath, &freepath); + kve->kve_vn_type = vntype_to_kinfo(vp->v_type); cred = curthread->td_ucred; vfslocked = VFS_LOCK_GIANT(vp->v_mount); vn_lock(vp, LK_SHARED | LK_RETRY); if (VOP_GETATTR(vp, &va, cred) == 0) { - kve->kve_fileid = va.va_fileid; - kve->kve_fsid = va.va_fsid; + kve->kve_vn_fileid = va.va_fileid; + kve->kve_vn_fsid = va.va_fsid; + kve->kve_vn_mode = + MAKEIMODE(va.va_type, va.va_mode); + kve->kve_vn_size = va.va_size; + kve->kve_vn_rdev = va.va_rdev; + kve->kve_status = KF_ATTR_VALID; } vput(vp); VFS_UNLOCK_GIANT(vfslocked); diff --git a/sys/sys/user.h b/sys/sys/user.h index 5c5cbd4ec51..644f9113edd 100644 --- a/sys/sys/user.h +++ b/sys/sys/user.h @@ -233,6 +233,8 @@ struct user { * The KERN_PROC_FILE sysctl allows a process to dump the file descriptor * array of another process. */ +#define KF_ATTR_VALID 0x0001 + #define KF_TYPE_NONE 0 #define KF_TYPE_VNODE 1 #define KF_TYPE_SOCKET 2 @@ -260,6 +262,9 @@ struct user { #define KF_FD_TYPE_CWD -1 /* Current working directory */ #define KF_FD_TYPE_ROOT -2 /* Root directory */ #define KF_FD_TYPE_JAIL -3 /* Jail directory */ +#define KF_FD_TYPE_TRACE -4 /* ptrace vnode */ +#define KF_FD_TYPE_TEXT -5 /* Text vnode */ +#define KF_FD_TYPE_CTTY -6 /* Controlling terminal */ #define KF_FLAG_READ 0x00000001 #define KF_FLAG_WRITE 0x00000002 @@ -269,6 +274,13 @@ struct user { #define KF_FLAG_NONBLOCK 0x00000020 #define KF_FLAG_DIRECT 0x00000040 #define KF_FLAG_HASLOCK 0x00000080 +#define KF_FLAG_SHLOCK 0x00000100 +#define KF_FLAG_EXLOCK 0x00000200 +#define KF_FLAG_NOFOLLOW 0x00000400 +#define KF_FLAG_CREAT 0x00000800 +#define KF_FLAG_TRUNC 0x00001000 +#define KF_FLAG_EXCL 0x00002000 +#define KF_FLAG_EXEC 0x00004000 /* * Old format. Has variable hidden padding due to alignment. @@ -303,22 +315,67 @@ struct kinfo_ofile { #endif struct kinfo_file { - int kf_structsize; /* Variable size of record. */ - int kf_type; /* Descriptor type. */ - int kf_fd; /* Array index. */ - int kf_ref_count; /* Reference count. */ - int kf_flags; /* Flags. */ - int _kf_pad0; /* Round to 64 bit alignment */ - int64_t kf_offset; /* Seek location. */ - int kf_vnode_type; /* Vnode type. */ - int kf_sock_domain; /* Socket domain. */ - int kf_sock_type; /* Socket type. */ - int kf_sock_protocol; /* Socket protocol. */ + int kf_structsize; /* Variable size of record. */ + int kf_type; /* Descriptor type. */ + int kf_fd; /* Array index. */ + int kf_ref_count; /* Reference count. */ + int kf_flags; /* Flags. */ + int kf_pad0; /* Round to 64 bit alignment. */ + int64_t kf_offset; /* Seek location. */ + int kf_vnode_type; /* Vnode type. */ + int kf_sock_domain; /* Socket domain. */ + int kf_sock_type; /* Socket type. */ + int kf_sock_protocol; /* Socket protocol. */ struct sockaddr_storage kf_sa_local; /* Socket address. */ struct sockaddr_storage kf_sa_peer; /* Peer address. */ - int _kf_ispare[16]; /* Space for more stuff. */ + union { + struct { + /* Address of so_pcb. */ + uint64_t kf_sock_pcb; + /* Address of inp_ppcb. */ + uint64_t kf_sock_inpcb; + /* Address of unp_conn. */ + uint64_t kf_sock_unpconn; + /* Send buffer state. */ + uint16_t kf_sock_snd_sb_state; + /* Receive buffer state. */ + uint16_t kf_sock_rcv_sb_state; + /* Round to 64 bit alignment. */ + uint32_t kf_sock_pad0; + } kf_sock; + struct { + /* Global file id. */ + uint64_t kf_file_fileid; + /* File size. */ + uint64_t kf_file_size; + /* Vnode filesystem id. */ + uint32_t kf_file_fsid; + /* File device. */ + uint32_t kf_file_rdev; + /* File mode. */ + uint16_t kf_file_mode; + /* Round to 64 bit alignment. */ + uint16_t kf_file_pad0; + uint32_t kf_file_pad1; + } kf_file; + struct { + uint64_t kf_pipe_addr; + uint64_t kf_pipe_peer; + uint32_t kf_pipe_buffer_cnt; + /* Round to 64 bit alignment. */ + uint32_t kf_pipe_pad0[3]; + } kf_pipe; + struct { + uint32_t kf_pts_dev; + /* Round to 64 bit alignment. */ + uint32_t kf_pts_pad0[7]; + } kf_pts; + } kf_un; + uint16_t kf_status; /* Status flags. */ + uint16_t kf_pad1; /* Round to 32 bit alignment. */ + int _kf_ispare[7]; /* Space for more stuff. */ /* Truncated before copyout in sysctl */ - char kf_path[PATH_MAX]; /* Path to file, if any. */ + char kf_path[PATH_MAX]; /* Path to file, if any. */ }; /* @@ -379,16 +436,20 @@ struct kinfo_vmentry { uint64_t kve_start; /* Starting address. */ uint64_t kve_end; /* Finishing address. */ uint64_t kve_offset; /* Mapping offset in object */ - uint64_t kve_fileid; /* inode number if vnode */ - uint32_t kve_fsid; /* dev_t of vnode location */ + uint64_t kve_vn_fileid; /* inode number if vnode */ + uint32_t kve_vn_fsid; /* dev_t of vnode location */ int kve_flags; /* Flags on map entry. */ int kve_resident; /* Number of resident pages. */ int kve_private_resident; /* Number of private pages. */ int kve_protection; /* Protection bitmask. */ int kve_ref_count; /* VM obj ref count. */ int kve_shadow_count; /* VM obj shadow count. */ - int _kve_pad0; /* 64bit align next field */ - int _kve_ispare[16]; /* Space for more stuff. */ + int kve_vn_type; /* Vnode type. */ + uint64_t kve_vn_size; /* File size. */ + uint32_t kve_vn_rdev; /* Device id if device. */ + uint16_t kve_vn_mode; /* File mode. */ + uint16_t kve_status; /* Status flags. */ + int _kve_ispare[12]; /* Space for more stuff. */ /* Truncated before copyout in sysctl */ char kve_path[PATH_MAX]; /* Path to VM obj, if any. */ }; @@ -415,4 +476,8 @@ struct kinfo_kstack { int _kkst_ispare[16]; /* Space for more stuff. */ }; +#ifdef _KERNEL +int vntype_to_kinfo(int vtype); +#endif /* !_KERNEL */ + #endif diff --git a/usr.bin/fstat/Makefile b/usr.bin/fstat/Makefile index 23e907b9b5c..c59e123e62c 100644 --- a/usr.bin/fstat/Makefile +++ b/usr.bin/fstat/Makefile @@ -1,24 +1,12 @@ # @(#)Makefile 8.1 (Berkeley) 6/6/93 # $FreeBSD$ -.include - PROG= fstat -SRCS= cd9660.c fstat.c msdosfs.c +SRCS= fstat.c fuser.c main.c +LINKS= ${BINDIR}/fstat ${BINDIR}/fuser DPADD= ${LIBKVM} -LDADD= -lkvm -BINGRP= kmem -BINMODE=2555 +LDADD= -lkvm -lutil -lprocstat -CFLAGS+=-D_KVM_VNODE - -# XXX This is a hack. -.if ${MK_CDDL} != "no" -CFLAGS+= -DZFS -OBJS+= zfs/zfs.o -SUBDIR= zfs -zfs/zfs.o: .PHONY - @cd ${.CURDIR}/zfs && ${MAKE} zfs.o -.endif +MAN1= fuser.1 fstat.1 .include diff --git a/usr.bin/fstat/fstat.c b/usr.bin/fstat/fstat.c index 7725c88df25..9d057e51676 100644 --- a/usr.bin/fstat/fstat.c +++ b/usr.bin/fstat/fstat.c @@ -1,4 +1,5 @@ /*- + * Copyright (c) 2009 Stanislav Sedov * Copyright (c) 1988, 1993 * The Regents of the University of California. All rights reserved. * @@ -27,69 +28,24 @@ * SUCH DAMAGE. */ -#ifndef lint -static const char copyright[] = -"@(#) Copyright (c) 1988, 1993\n\ - The Regents of the University of California. All rights reserved.\n"; -#endif /* not lint */ - -#ifndef lint -#if 0 -static char sccsid[] = "@(#)fstat.c 8.3 (Berkeley) 5/2/95"; -#endif -#endif /* not lint */ #include __FBSDID("$FreeBSD$"); #include -#include -#include #include #include -#include #include #include -#include -#include -#include -#include #include -#include -#include #include -#define _WANT_FILE -#include -#include -#define _KERNEL -#include -#include -#include -#include -#include -#include -#undef _KERNEL -#include -#include -#include - -#include -#include -#include - -#include #include -#include -#include -#include +#include #include #include -#include -#include +#include #include -#include -#include #include #include #include @@ -98,69 +54,49 @@ __FBSDID("$FreeBSD$"); #include #include -#include "fstat.h" - -#define TEXT -1 -#define CDIR -2 -#define RDIR -3 -#define TRACE -4 -#define MMAP -5 -#define JDIR -6 - -DEVS *devs; - -#ifdef notdef -struct nlist nl[] = { - { "" }, -}; -#endif +#include "functions.h" int fsflg, /* show files on same filesystem as file(s) argument */ pflg, /* show files open by a particular pid */ uflg; /* show files open by a particular (effective) user */ int checkfile; /* true if restricting to particular files or filesystems */ int nflg; /* (numerical) display f.s. and rdev as dev_t */ -int vflg; /* display errors in locating kernel data objects etc... */ int mflg; /* include memory-mapped files */ +int vflg; /* be verbose */ +typedef struct devs { + struct devs *next; + uint32_t fsid; + uint64_t ino; + const char *name; +} DEVS; -struct file **ofiles; /* buffer of pointers to file structures */ -int maxfiles; -#define ALLOC_OFILES(d) \ - if ((d) > maxfiles) { \ - free(ofiles); \ - ofiles = malloc((d) * sizeof(struct file *)); \ - if (ofiles == NULL) { \ - err(1, NULL); \ - } \ - maxfiles = (d); \ - } - +DEVS *devs; char *memf, *nlistf; -kvm_t *kd; -static void fstat_kvm(int, int); -static void fstat_sysctl(int, int); -void dofiles(struct kinfo_proc *kp); -void dommap(struct kinfo_proc *kp); -void vtrans(struct vnode *vp, int i, int flag); -int ufs_filestat(struct vnode *vp, struct filestat *fsp); -int nfs_filestat(struct vnode *vp, struct filestat *fsp); -int devfs_filestat(struct vnode *vp, struct filestat *fsp); -char *getmnton(struct mount *m); -void pipetrans(struct pipe *pi, int i, int flag); -void socktrans(struct socket *sock, int i); -void ptstrans(struct tty *tp, int i, int flag); -void getinetproto(int number); -int getfname(const char *filename); -void usage(void); -char *kdevtoname(struct cdev *dev); +static int getfname(const char *filename); +static void dofiles(struct procstat *procstat, struct kinfo_proc *p); +static void print_access_flags(int flags); +static void print_file_info(struct procstat *procstat, + struct filestat *fst, const char *uname, const char *cmd, int pid); +static void print_pipe_info(struct procstat *procstat, + struct filestat *fst); +static void print_pts_info(struct procstat *procstat, + struct filestat *fst); +static void print_socket_info(struct procstat *procstat, + struct filestat *fst); +static void print_vnode_info(struct procstat *procstat, + struct filestat *fst); +static void usage(void) __dead2; int -main(int argc, char **argv) +do_fstat(int argc, char **argv) { + struct kinfo_proc *p; struct passwd *passwd; + struct procstat *procstat; int arg, ch, what; + int cnt, i; arg = 0; what = KERN_PROC_PROC; @@ -225,16 +161,18 @@ main(int argc, char **argv) } if (memf != NULL) - fstat_kvm(what, arg); + procstat = procstat_open_kvm(nlistf, memf); else - fstat_sysctl(what, arg); - exit(0); -} - -static void -print_header(void) -{ + procstat = procstat_open_sysctl(); + if (procstat == NULL) + errx(1, "procstat_open()"); + p = procstat_getprocs(procstat, what, arg, &cnt); + if (p == NULL) + errx(1, "procstat_getprocs()"); + /* + * Print header. + */ if (nflg) printf("%s", "USER CMD PID FD DEV INUM MODE SZ|DV R/W"); @@ -245,312 +183,65 @@ print_header(void) printf(" NAME\n"); else putchar('\n'); + + /* + * Go through the process list. + */ + for (i = 0; i < cnt; i++) { + if (p[i].ki_stat == SZOMB) + continue; + dofiles(procstat, &p[i]); + } + procstat_freeprocs(procstat, p); + procstat_close(procstat); + return (0); } static void -fstat_kvm(int what, int arg) +dofiles(struct procstat *procstat, struct kinfo_proc *kp) { - struct kinfo_proc *p, *plast; - char buf[_POSIX2_LINE_MAX]; - int cnt; + const char *cmd; + const char *uname; + struct filestat *fst; + struct filestat_list *head; + int pid; - ALLOC_OFILES(256); /* reserve space for file pointers */ + uname = user_from_uid(kp->ki_uid, 0); + pid = kp->ki_pid; + cmd = kp->ki_comm; - /* - * Discard setgid privileges if not the running kernel so that bad - * guys can't print interesting stuff from kernel memory. - */ - if (nlistf != NULL || memf != NULL) - setgid(getgid()); - - if ((kd = kvm_openfiles(nlistf, memf, NULL, O_RDONLY, buf)) == NULL) - errx(1, "%s", buf); - setgid(getgid()); -#ifdef notdef - if (kvm_nlist(kd, nl) != 0) - errx(1, "no namelist: %s", kvm_geterr(kd)); -#endif - if ((p = kvm_getprocs(kd, what, arg, &cnt)) == NULL) - errx(1, "%s", kvm_geterr(kd)); - print_header(); - for (plast = &p[cnt]; p < plast; ++p) { - if (p->ki_stat == SZOMB) - continue; - dofiles(p); - if (mflg) - dommap(p); - } + head = procstat_getfiles(procstat, kp, mflg); + if (head == NULL) + return; + STAILQ_FOREACH(fst, head, next) + print_file_info(procstat, fst, uname, cmd, pid); + procstat_freefiles(procstat, head); } + static void -fstat_sysctl(int what, int arg) +print_file_info(struct procstat *procstat, struct filestat *fst, + const char *uname, const char *cmd, int pid) { + struct vnstat vn; + DEVS *d; + const char *filename; + int error, fsmatch = 0; + char errbuf[_POSIX2_LINE_MAX]; - /* not yet implemented */ - fstat_kvm(what, arg); -} - -const char *Uname, *Comm; -int Pid; - -#define PREFIX(i) printf("%-8.8s %-10s %5d", Uname, Comm, Pid); \ - switch(i) { \ - case TEXT: \ - printf(" text"); \ - break; \ - case CDIR: \ - printf(" wd"); \ - break; \ - case RDIR: \ - printf(" root"); \ - break; \ - case TRACE: \ - printf(" tr"); \ - break; \ - case MMAP: \ - printf(" mmap"); \ - break; \ - case JDIR: \ - printf(" jail"); \ - break; \ - default: \ - printf(" %4d", i); \ - break; \ - } - -/* - * print open files attributed to this process - */ -void -dofiles(struct kinfo_proc *kp) -{ - int i; - struct file file; - struct filedesc filed; - - Uname = user_from_uid(kp->ki_uid, 0); - Pid = kp->ki_pid; - Comm = kp->ki_comm; - - if (kp->ki_fd == NULL) - return; - if (!KVM_READ(kp->ki_fd, &filed, sizeof (filed))) { - dprintf(stderr, "can't read filedesc at %p for pid %d\n", - (void *)kp->ki_fd, Pid); - return; - } - /* - * root directory vnode, if one - */ - if (filed.fd_rdir) - vtrans(filed.fd_rdir, RDIR, FREAD); - /* - * current working directory vnode - */ - if (filed.fd_cdir) - vtrans(filed.fd_cdir, CDIR, FREAD); - /* - * jail root, if any. - */ - if (filed.fd_jdir) - vtrans(filed.fd_jdir, JDIR, FREAD); - /* - * ktrace vnode, if one - */ - if (kp->ki_tracep) - vtrans(kp->ki_tracep, TRACE, FREAD|FWRITE); - /* - * text vnode, if one - */ - if (kp->ki_textvp) - vtrans(kp->ki_textvp, TEXT, FREAD); - /* - * open files - */ -#define FPSIZE (sizeof (struct file *)) -#define MAX_LASTFILE (0x1000000) - - /* Sanity check on filed.fd_lastfile */ - if (filed.fd_lastfile <= -1 || filed.fd_lastfile > MAX_LASTFILE) - return; - - ALLOC_OFILES(filed.fd_lastfile+1); - if (!KVM_READ(filed.fd_ofiles, ofiles, - (filed.fd_lastfile+1) * FPSIZE)) { - dprintf(stderr, - "can't read file structures at %p for pid %d\n", - (void *)filed.fd_ofiles, Pid); - return; - } - for (i = 0; i <= filed.fd_lastfile; i++) { - if (ofiles[i] == NULL) - continue; - if (!KVM_READ(ofiles[i], &file, sizeof (struct file))) { - dprintf(stderr, "can't read file %d at %p for pid %d\n", - i, (void *)ofiles[i], Pid); - continue; - } - if (file.f_type == DTYPE_VNODE) - vtrans(file.f_vnode, i, file.f_flag); - else if (file.f_type == DTYPE_SOCKET) { - if (checkfile == 0) - socktrans(file.f_data, i); - } -#ifdef DTYPE_PIPE - else if (file.f_type == DTYPE_PIPE) { - if (checkfile == 0) - pipetrans(file.f_data, i, file.f_flag); - } -#endif -#ifdef DTYPE_FIFO - else if (file.f_type == DTYPE_FIFO) { - if (checkfile == 0) - vtrans(file.f_vnode, i, file.f_flag); - } -#endif -#ifdef DTYPE_PTS - else if (file.f_type == DTYPE_PTS) { - if (checkfile == 0) - ptstrans(file.f_data, i, file.f_flag); - } -#endif - else { - dprintf(stderr, - "unknown file type %d for file %d of pid %d\n", - file.f_type, i, Pid); - } - } -} - -void -dommap(struct kinfo_proc *kp) -{ - vm_map_t map; - struct vmspace vmspace; - struct vm_map_entry entry; - vm_map_entry_t entryp; - struct vm_object object; - vm_object_t objp; - int prot, fflags; - - if (!KVM_READ(kp->ki_vmspace, &vmspace, sizeof(vmspace))) { - dprintf(stderr, - "can't read vmspace at %p for pid %d\n", - (void *)kp->ki_vmspace, Pid); - return; - } - map = &vmspace.vm_map; - - for (entryp = map->header.next; - entryp != &kp->ki_vmspace->vm_map.header; entryp = entry.next) { - if (!KVM_READ(entryp, &entry, sizeof(entry))) { - dprintf(stderr, - "can't read vm_map_entry at %p for pid %d\n", - (void *)entryp, Pid); + filename = NULL; + if (checkfile != 0) { + if (fst->fs_type != PS_FST_TYPE_VNODE && + fst->fs_type != PS_FST_TYPE_FIFO) return; - } - - if (entry.eflags & MAP_ENTRY_IS_SUB_MAP) - continue; - - if ((objp = entry.object.vm_object) == NULL) - continue; - - for (; objp; objp = object.backing_object) { - if (!KVM_READ(objp, &object, sizeof(object))) { - dprintf(stderr, - "can't read vm_object at %p for pid %d\n", - (void *)objp, Pid); - return; - } - } - - prot = entry.protection; - fflags = (prot & VM_PROT_READ ? FREAD : 0) | - (prot & VM_PROT_WRITE ? FWRITE : 0); - - switch (object.type) { - case OBJT_VNODE: - vtrans((struct vnode *)object.handle, MMAP, fflags); - break; - default: - break; - } - } -} - -char * -kdevtoname(struct cdev *dev) -{ - struct cdev si; - - if (!KVM_READ(dev, &si, sizeof si)) - return (NULL); - return (strdup(si.__si_namebuf)); -} - -void -vtrans(struct vnode *vp, int i, int flag) -{ - struct vnode vn; - struct filestat fst; - char rw[3], mode[15], tagstr[12], *tagptr; - const char *badtype, *filename; - - filename = badtype = NULL; - if (!KVM_READ(vp, &vn, sizeof (struct vnode))) { - dprintf(stderr, "can't read vnode at %p for pid %d\n", - (void *)vp, Pid); - return; - } - if (!KVM_READ(&vp->v_tag, &tagptr, sizeof tagptr) || - !KVM_READ(tagptr, tagstr, sizeof tagstr)) { - dprintf(stderr, "can't read v_tag at %p for pid %d\n", - (void *)vp, Pid); - return; - } - tagstr[sizeof(tagstr) - 1] = '\0'; - if (vn.v_type == VNON) - badtype = "none"; - else if (vn.v_type == VBAD) - badtype = "bad"; - else { - if (!strcmp("ufs", tagstr)) { - if (!ufs_filestat(&vn, &fst)) - badtype = "error"; - } else if (!strcmp("devfs", tagstr)) { - if (!devfs_filestat(&vn, &fst)) - badtype = "error"; - } else if (!strcmp("nfs", tagstr)) { - if (!nfs_filestat(&vn, &fst)) - badtype = "error"; - } else if (!strcmp("msdosfs", tagstr)) { - if (!msdosfs_filestat(&vn, &fst)) - badtype = "error"; - } else if (!strcmp("isofs", tagstr)) { - if (!isofs_filestat(&vn, &fst)) - badtype = "error"; -#ifdef ZFS - } else if (!strcmp("zfs", tagstr)) { - if (!zfs_filestat(&vn, &fst)) - badtype = "error"; -#endif - } else { - static char unknown[32]; - snprintf(unknown, sizeof unknown, "?(%s)", tagstr); - badtype = unknown; - } - } - if (checkfile) { - int fsmatch = 0; - DEVS *d; - - if (badtype) + error = procstat_get_vnode_info(procstat, fst, &vn, errbuf); + if (error != 0) return; + for (d = devs; d != NULL; d = d->next) - if (d->fsid == fst.fsid) { + if (d->fsid == vn.vn_fsid) { fsmatch = 1; - if (d->ino == fst.fileid) { + if ((unsigned)d->ino == vn.vn_fileid) { filename = d->name; break; } @@ -558,271 +249,83 @@ vtrans(struct vnode *vp, int i, int flag) if (fsmatch == 0 || (filename == NULL && fsflg == 0)) return; } - PREFIX(i); - if (badtype) { - (void)printf(" - - %10s -\n", badtype); - return; - } - if (nflg) - (void)printf(" %2d,%-2d", major(fst.fsid), minor(fst.fsid)); - else - (void)printf(" %-8s", getmnton(vn.v_mount)); - if (nflg) - (void)sprintf(mode, "%o", fst.mode); - else - strmode(fst.mode, mode); - (void)printf(" %6ld %10s", fst.fileid, mode); - switch (vn.v_type) { - case VBLK: - case VCHR: { - char *name; - name = kdevtoname(vn.v_rdev); - if (nflg || !name) - printf(" %2d,%-2d", major(fst.rdev), minor(fst.rdev)); - else { - printf(" %6s", name); - free(name); - } + /* + * Print entry prefix. + */ + printf("%-8.8s %-10s %5d", uname, cmd, pid); + if (fst->fs_uflags & PS_FST_UFLAG_TEXT) + printf(" text"); + else if (fst->fs_uflags & PS_FST_UFLAG_CDIR) + printf(" wd"); + else if (fst->fs_uflags & PS_FST_UFLAG_RDIR) + printf(" root"); + else if (fst->fs_uflags & PS_FST_UFLAG_TRACE) + printf(" tr"); + else if (fst->fs_uflags & PS_FST_UFLAG_MMAP) + printf(" mmap"); + else if (fst->fs_uflags & PS_FST_UFLAG_JAIL) + printf(" jail"); + else if (fst->fs_uflags & PS_FST_UFLAG_CTTY) + printf(" ctty"); + else + printf(" %4d", fst->fs_fd); + + /* + * Print type-specific data. + */ + switch (fst->fs_type) { + case PS_FST_TYPE_FIFO: + case PS_FST_TYPE_VNODE: + print_vnode_info(procstat, fst); break; + case PS_FST_TYPE_SOCKET: + print_socket_info(procstat, fst); + break; + case PS_FST_TYPE_PIPE: + print_pipe_info(procstat, fst); + break; + case PS_FST_TYPE_PTS: + print_pts_info(procstat, fst); + break; + default: + if (vflg) + fprintf(stderr, + "unknown file type %d for file %d of pid %d\n", + fst->fs_type, fst->fs_fd, pid); } - default: - printf(" %6lu", fst.size); - } - rw[0] = '\0'; - if (flag & FREAD) - strcat(rw, "r"); - if (flag & FWRITE) - strcat(rw, "w"); - printf(" %2s", rw); if (filename && !fsflg) printf(" %s", filename); putchar('\n'); } -int -ufs_filestat(struct vnode *vp, struct filestat *fsp) -{ - struct inode inode; - - if (!KVM_READ(VTOI(vp), &inode, sizeof (inode))) { - dprintf(stderr, "can't read inode at %p for pid %d\n", - (void *)VTOI(vp), Pid); - return 0; - } - /* - * The st_dev from stat(2) is a dev_t. These kernel structures - * contain cdev pointers. We need to convert to dev_t to make - * comparisons - */ - fsp->fsid = dev2udev(inode.i_dev); - fsp->fileid = (long)inode.i_number; - fsp->mode = (mode_t)inode.i_mode; - fsp->size = (u_long)inode.i_size; -#if should_be_but_is_hard - /* XXX - need to load i_ump and i_din[12] from kernel memory */ - if (inode.i_ump->um_fstype == UFS1) - fsp->rdev = inode.i_din1->di_rdev; - else - fsp->rdev = inode.i_din2->di_rdev; -#else - fsp->rdev = 0; -#endif - - return 1; -} - -int -devfs_filestat(struct vnode *vp, struct filestat *fsp) -{ - struct devfs_dirent devfs_dirent; - struct mount mount; - struct vnode vnode; - - if (!KVM_READ(vp->v_data, &devfs_dirent, sizeof (devfs_dirent))) { - dprintf(stderr, "can't read devfs_dirent at %p for pid %d\n", - (void *)vp->v_data, Pid); - return 0; - } - if (!KVM_READ(vp->v_mount, &mount, sizeof (mount))) { - dprintf(stderr, "can't read mount at %p for pid %d\n", - (void *)vp->v_mount, Pid); - return 0; - } - if (!KVM_READ(devfs_dirent.de_vnode, &vnode, sizeof (vnode))) { - dprintf(stderr, "can't read vnode at %p for pid %d\n", - (void *)devfs_dirent.de_vnode, Pid); - return 0; - } - fsp->fsid = (long)(uint32_t)mount.mnt_stat.f_fsid.val[0]; - fsp->fileid = devfs_dirent.de_inode; - fsp->mode = (devfs_dirent.de_mode & ~S_IFMT) | S_IFCHR; - fsp->size = 0; - fsp->rdev = dev2udev(vnode.v_rdev); - - return 1; -} - -int -nfs_filestat(struct vnode *vp, struct filestat *fsp) -{ - struct nfsnode nfsnode; - mode_t mode; - - if (!KVM_READ(VTONFS(vp), &nfsnode, sizeof (nfsnode))) { - dprintf(stderr, "can't read nfsnode at %p for pid %d\n", - (void *)VTONFS(vp), Pid); - return 0; - } - fsp->fsid = nfsnode.n_vattr.va_fsid; - fsp->fileid = nfsnode.n_vattr.va_fileid; - fsp->size = nfsnode.n_size; - fsp->rdev = nfsnode.n_vattr.va_rdev; - mode = (mode_t)nfsnode.n_vattr.va_mode; - switch (vp->v_type) { - case VREG: - mode |= S_IFREG; - break; - case VDIR: - mode |= S_IFDIR; - break; - case VBLK: - mode |= S_IFBLK; - break; - case VCHR: - mode |= S_IFCHR; - break; - case VLNK: - mode |= S_IFLNK; - break; - case VSOCK: - mode |= S_IFSOCK; - break; - case VFIFO: - mode |= S_IFIFO; - break; - case VNON: - case VBAD: - case VMARKER: - return 0; - }; - fsp->mode = mode; - - return 1; -} - - -char * -getmnton(struct mount *m) -{ - static struct mount mount; - static struct mtab { - struct mtab *next; - struct mount *m; - char mntonname[MNAMELEN]; - } *mhead = NULL; - struct mtab *mt; - - for (mt = mhead; mt != NULL; mt = mt->next) - if (m == mt->m) - return (mt->mntonname); - if (!KVM_READ(m, &mount, sizeof(struct mount))) { - warnx("can't read mount table at %p", (void *)m); - return (NULL); - } - if ((mt = malloc(sizeof (struct mtab))) == NULL) - err(1, NULL); - mt->m = m; - bcopy(&mount.mnt_stat.f_mntonname[0], &mt->mntonname[0], MNAMELEN); - mt->next = mhead; - mhead = mt; - return (mt->mntonname); -} - -void -pipetrans(struct pipe *pi, int i, int flag) -{ - struct pipe pip; - char rw[3]; - - PREFIX(i); - - /* fill in socket */ - if (!KVM_READ(pi, &pip, sizeof(struct pipe))) { - dprintf(stderr, "can't read pipe at %p\n", (void *)pi); - goto bad; - } - - printf("* pipe %8lx <-> %8lx", (u_long)pi, (u_long)pip.pipe_peer); - printf(" %6d", (int)pip.pipe_buffer.cnt); - rw[0] = '\0'; - if (flag & FREAD) - strcat(rw, "r"); - if (flag & FWRITE) - strcat(rw, "w"); - printf(" %2s", rw); - putchar('\n'); - return; - -bad: - printf("* error\n"); -} - -void -socktrans(struct socket *sock, int i) +static void +print_socket_info(struct procstat *procstat, struct filestat *fst) { static const char *stypename[] = { "unused", /* 0 */ - "stream", /* 1 */ + "stream", /* 1 */ "dgram", /* 2 */ "raw", /* 3 */ "rdm", /* 4 */ "seqpak" /* 5 */ }; -#define STYPEMAX 5 - struct socket so; - struct protosw proto; - struct domain dom; - struct inpcb inpcb; - struct unpcb unpcb; - int len; - char dname[32]; +#define STYPEMAX 5 + struct sockstat sock; + struct protoent *pe; + char errbuf[_POSIX2_LINE_MAX]; + int error; + static int isopen; - PREFIX(i); - - /* fill in socket */ - if (!KVM_READ(sock, &so, sizeof(struct socket))) { - dprintf(stderr, "can't read sock at %p\n", (void *)sock); - goto bad; - } - - /* fill in protosw entry */ - if (!KVM_READ(so.so_proto, &proto, sizeof(struct protosw))) { - dprintf(stderr, "can't read protosw at %p", - (void *)so.so_proto); - goto bad; - } - - /* fill in domain */ - if (!KVM_READ(proto.pr_domain, &dom, sizeof(struct domain))) { - dprintf(stderr, "can't read domain at %p\n", - (void *)proto.pr_domain); - goto bad; - } - - if ((len = kvm_read(kd, (u_long)dom.dom_name, dname, - sizeof(dname) - 1)) < 0) { - dprintf(stderr, "can't read domain name at %p\n", - (void *)dom.dom_name); - dname[0] = '\0'; + error = procstat_get_socket_info(procstat, fst, &sock, errbuf); + if (error != 0) { + printf("* error"); + return; } + if (sock.type > STYPEMAX) + printf("* %s ?%d", sock.dname, sock.type); else - dname[len] = '\0'; - - if ((u_short)so.so_type > STYPEMAX) - printf("* %s ?%d", dname, so.so_type); - else - printf("* %s %s", dname, stypename[so.so_type]); + printf("* %s %s", sock.dname, stypename[sock.type]); /* * protocol specific formatting @@ -835,139 +338,144 @@ socktrans(struct socket *sock, int i) * The idea is not to duplicate netstat, but to make available enough * information for further analysis. */ - switch(dom.dom_family) { + switch (sock.dom_family) { case AF_INET: case AF_INET6: - getinetproto(proto.pr_protocol); - if (proto.pr_protocol == IPPROTO_TCP ) { - if (so.so_pcb) { - if (kvm_read(kd, (u_long)so.so_pcb, - (char *)&inpcb, sizeof(struct inpcb)) - != sizeof(struct inpcb)) { - dprintf(stderr, - "can't read inpcb at %p\n", - (void *)so.so_pcb); - goto bad; - } - printf(" %lx", (u_long)inpcb.inp_ppcb); - } + if (!isopen) + setprotoent(++isopen); + if ((pe = getprotobynumber(sock.proto)) != NULL) + printf(" %s", pe->p_name); + else + printf(" %d", sock.proto); + if (sock.proto == IPPROTO_TCP ) { + if (sock.inp_ppcb != 0) + printf(" %lx", (u_long)sock.inp_ppcb); } - else if (so.so_pcb) - printf(" %lx", (u_long)so.so_pcb); + else if (sock.so_pcb != 0) + printf(" %lx", (u_long)sock.so_pcb); break; case AF_UNIX: /* print address of pcb and connected pcb */ - if (so.so_pcb) { - printf(" %lx", (u_long)so.so_pcb); - if (kvm_read(kd, (u_long)so.so_pcb, (char *)&unpcb, - sizeof(struct unpcb)) != sizeof(struct unpcb)){ - dprintf(stderr, "can't read unpcb at %p\n", - (void *)so.so_pcb); - goto bad; - } - if (unpcb.unp_conn) { + if (sock.so_pcb != 0) { + printf(" %lx", (u_long)sock.so_pcb); + if (sock.unp_conn) { char shoconn[4], *cp; cp = shoconn; - if (!(so.so_rcv.sb_state & SBS_CANTRCVMORE)) + if (!(sock.so_rcv_sb_state & SBS_CANTRCVMORE)) *cp++ = '<'; *cp++ = '-'; - if (!(so.so_snd.sb_state & SBS_CANTSENDMORE)) + if (!(sock.so_snd_sb_state & SBS_CANTSENDMORE)) *cp++ = '>'; *cp = '\0'; printf(" %s %lx", shoconn, - (u_long)unpcb.unp_conn); - } + (u_long)sock.unp_conn); + } } break; default: /* print protocol number and socket address */ - printf(" %d %lx", proto.pr_protocol, (u_long)sock); + printf(" %d %lx", sock.proto, (u_long)sock.so_addr); } - printf("\n"); - return; -bad: - printf("* error\n"); } -void -ptstrans(struct tty *tp, int i, int flag) +static void +print_pipe_info(struct procstat *procstat, struct filestat *fst) +{ + struct pipestat ps; + char errbuf[_POSIX2_LINE_MAX]; + int error; + + error = procstat_get_pipe_info(procstat, fst, &ps, errbuf); + if (error != 0) { + printf("* error"); + return; + } + printf("* pipe %8lx <-> %8lx", (u_long)ps.addr, (u_long)ps.peer); + printf(" %6zd", ps.buffer_cnt); + print_access_flags(fst->fs_fflags); +} + +static void +print_pts_info(struct procstat *procstat, struct filestat *fst) +{ + struct ptsstat pts; + char errbuf[_POSIX2_LINE_MAX]; + int error; + + error = procstat_get_pts_info(procstat, fst, &pts, errbuf); + if (error != 0) { + printf("* error"); + return; + } + printf("* pseudo-terminal master "); + if (nflg || !*pts.devname) { + printf("%10d,%-2d", major(pts.dev), minor(pts.dev)); + } else { + printf("%10s", pts.devname); + } + print_access_flags(fst->fs_fflags); +} + +static void +print_vnode_info(struct procstat *procstat, struct filestat *fst) +{ + struct vnstat vn; + char errbuf[_POSIX2_LINE_MAX]; + char mode[15]; + const char *badtype; + int error; + + badtype = NULL; + error = procstat_get_vnode_info(procstat, fst, &vn, errbuf); + if (error != 0) + badtype = errbuf; + else if (vn.vn_type == PS_FST_VTYPE_VBAD) + badtype = "bad"; + else if (vn.vn_type == PS_FST_VTYPE_VNON) + badtype = "none"; + if (badtype != NULL) { + printf(" - - %10s -", badtype); + return; + } + + if (nflg) + printf(" %2d,%-2d", major(vn.vn_fsid), minor(vn.vn_fsid)); + else if (vn.vn_mntdir != NULL) + (void)printf(" %-8s", vn.vn_mntdir); + + /* + * Print access mode. + */ + if (nflg) + (void)snprintf(mode, sizeof(mode), "%o", vn.vn_mode); + else { + strmode(vn.vn_mode, mode); + } + (void)printf(" %6ld %10s", vn.vn_fileid, mode); + + if (vn.vn_type == PS_FST_VTYPE_VBLK || vn.vn_type == PS_FST_VTYPE_VCHR) { + if (nflg || !*vn.vn_devname) + printf(" %2d,%-2d", major(vn.vn_dev), minor(vn.vn_dev)); + else { + printf(" %6s", vn.vn_devname); + } + } else + printf(" %6lu", vn.vn_size); + print_access_flags(fst->fs_fflags); +} + +static void +print_access_flags(int flags) { - struct tty tty; - char *name; char rw[3]; - dev_t rdev; - - PREFIX(i); - - /* Obtain struct tty. */ - if (!KVM_READ(tp, &tty, sizeof(struct tty))) { - dprintf(stderr, "can't read tty at %p\n", (void *)tp); - goto bad; - } - - /* Figure out the device name. */ - name = kdevtoname(tty.t_dev); - if (name == NULL) { - dprintf(stderr, "can't determine tty name at %p\n", (void *)tp); - goto bad; - } rw[0] = '\0'; - if (flag & FREAD) + if (flags & PS_FST_FFLAG_READ) strcat(rw, "r"); - if (flag & FWRITE) + if (flags & PS_FST_FFLAG_WRITE) strcat(rw, "w"); - - printf("* pseudo-terminal master "); - if (nflg || !name) { - rdev = dev2udev(tty.t_dev); - printf("%10d,%-2d", major(rdev), minor(rdev)); - } else { - printf("%10s", name); - } - printf(" %2s\n", rw); - - free(name); - - return; -bad: - printf("* error\n"); -} - -/* - * Read the cdev structure in the kernel in order to work out the - * associated dev_t - */ -dev_t -dev2udev(struct cdev *dev) -{ - struct cdev_priv priv; - - if (KVM_READ(cdev2priv(dev), &priv, sizeof priv)) { - return ((dev_t)priv.cdp_inode); - } else { - dprintf(stderr, "can't convert cdev *%p to a dev_t\n", dev); - return -1; - } -} - -/* - * getinetproto -- - * print name of protocol number - */ -void -getinetproto(int number) -{ - static int isopen; - struct protoent *pe; - - if (!isopen) - setprotoent(++isopen); - if ((pe = getprotobynumber(number)) != NULL) - printf(" %s", pe->p_name); - else - printf(" %d", number); + printf(" %2s", rw); } int @@ -978,7 +486,7 @@ getfname(const char *filename) if (stat(filename, &statbuf)) { warn("%s", filename); - return(0); + return (0); } if ((cur = malloc(sizeof(DEVS))) == NULL) err(1, NULL); @@ -988,24 +496,10 @@ getfname(const char *filename) cur->ino = statbuf.st_ino; cur->fsid = statbuf.st_dev; cur->name = filename; - return(1); + return (1); } -#ifdef ZFS -void * -getvnodedata(struct vnode *vp) -{ - return (vp->v_data); -} - -struct mount * -getvnodemount(struct vnode *vp) -{ - return (vp->v_mount); -} -#endif - -void +static void usage(void) { (void)fprintf(stderr, diff --git a/usr.bin/fstat/functions.h b/usr.bin/fstat/functions.h new file mode 100644 index 00000000000..a23d27ef734 --- /dev/null +++ b/usr.bin/fstat/functions.h @@ -0,0 +1,34 @@ +/*- + * Copyright (c) 2009 Stanislav Sedov + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * $FreeBSD$ + */ +#ifndef __FUNCTIONS_H__ +#define __FUNCTIONS_H__ + +int do_fstat(int argc, char *argv[]); +int do_fuser(int argc, char *argv[]); + +#endif /* !__FUNCTIONS_H__ */ diff --git a/usr.bin/fstat/fuser.1 b/usr.bin/fstat/fuser.1 new file mode 100644 index 00000000000..999a72d8f41 --- /dev/null +++ b/usr.bin/fstat/fuser.1 @@ -0,0 +1,148 @@ +.\" Copyright (c) 2005-2009 Stanislav Sedov +.\" All rights reserved. +.\" +.\" Redistribution and use in source and binary forms, with or without +.\" modification, are permitted provided that the following conditions +.\" are met: +.\" 1. Redistributions of source code must retain the above copyright +.\" notice, this list of conditions and the following disclaimer. +.\" 2. Redistributions in binary form must reproduce the above copyright +.\" notice, this list of conditions and the following disclaimer in the +.\" documentation and/or other materials provided with the distribution. +.\" +.\" THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND +.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +.\" ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE +.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS +.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) +.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY +.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF +.\" SUCH DAMAGE. +.\" +.\" $FreeBSD$ +.\" +.Dd July 31, 2009 +.Dt FUSER 1 +.Os +.Sh NAME +.Nm fuser +.Nd list IDs of all processes that have one or more files open +.Sh SYNOPSIS +.Nm +.Op Fl cfkmu +.Op Fl M Ar core +.Op Fl N Ar system +.Op Fl s Ar signal +.Op Ar +.Sh DESCRIPTION +The +.Nm +utility writes to stdout the PIDs of processes that have one or +more named files open. +For block and character special devices, all processes using files +on that device are listed. +A file is considered open by a process if it was explicitly opened, +is the working directory, root directory, jail root directory, +active executable text, kernel trace file or the controlling terminal +of the process. +If +.Fl m +option is specified, the +.Nm +utility will also look through mmapped files. +.Pp +The following options are available: +.Bl -tag -width indent +.It Fl c +Treat files as mount point and report on any files open in the file system. +.It Fl f +The report must be only for named files. +.It Fl k +Send signal to reported processes +.Pq SIGKILL by default . +.It Fl m +Search through mmapped files too. +.It Fl u +Write the user name associated with each process to stdout. +.It Fl M +Extract values associated with the name list from the specified core +instead of the default +.Pa /dev/kmem . +.It Fl N +Extract the name list from the specified system instead of the default, +which is the kernel image the system has booted from. +.It Fl s +Use given signal name instead of default SIGKILL. +.El +.Pp +The following symbols, written to stderr will indicate how files is used: +.Bl -tag -width MOUNT +.It Cm r +The file is the root directory of the process. +.It Cm c +The file is the current workdir directory of the process. +.It Cm j +The file is the jail-root of the process. +.It Cm t +The file is the kernel tracing file for the process. +.It Cm x +The file is executable text of the process. +.It Cm y +The process use this file as its controlling tty. +.It Cm m +The file is mmapped. +.It Cm w +The file is open for writing. +.It Cm a +The file is open as append only +.Pq O_APPEND was specified . +.It Cm d +The process bypasses fs cache while writing to this file +.Pq O_DIRECT was specified . +.It Cm s +Shared lock is hold. +.It Cm e +Exclusive lock is hold. +.El +.Sh EXIT STATUS +The +.Nm +utility returns 0 on successful completion and >0 otherwise. +.Sh EXAMPLES +The command: +.Dq Li "fuser -fu ." +writes to standart output the process IDs of processes that are using the +current directory and writes to stderr an indication of how those processes are +using the direcory and user names associated with the processes that are using +this directory. +.Sh SEE ALSO +.Xr fstat 1 , +.Xr ps 1 , +.Xr systat 1 , +.Xr iostat 8 , +.Xr pstat 8 , +.Xr vmstat 8 +.Sh STANDARTS +The +.Nm +utility is expected to conform to +.St -p1003.1-2004 . +.Sh BUGS +Since +.Nm +takes a snapshot of the system, it is only correct for a very short period +of time. +When working via +.Xr kvm 3 +interface the report will be limited to filesystems the +.Nm +utility knows about (currently only cd9660, devfs, nfs, ntfs, nwfs, udf, +ufs and zfs). +.Sh AUTHORS +The +.Nm +utility and this manual page was written by +.An Stanislav Sedov Aq stas@FreeBSD.org . diff --git a/usr.bin/fstat/fuser.c b/usr.bin/fstat/fuser.c new file mode 100644 index 00000000000..02975b38c3d --- /dev/null +++ b/usr.bin/fstat/fuser.c @@ -0,0 +1,369 @@ +/*- + * Copyright (c) 2005-2009 Stanislav Sedov + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + */ +#include +__FBSDID("$FreeBSD$"); + +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "functions.h" + +/* + * File access mode flags table. + */ +struct { + int flag; + char ch; +} fflags[] = { + {PS_FST_FFLAG_WRITE, 'w'}, + {PS_FST_FFLAG_APPEND, 'a'}, + {PS_FST_FFLAG_DIRECT, 'd'}, + {PS_FST_FFLAG_SHLOCK, 's'}, + {PS_FST_FFLAG_EXLOCK, 'e'} +}; +#define NFFLAGS (sizeof(fflags) / sizeof(*fflags)) + +/* + * Usage flags translation table. + */ +struct { + int flag; + char ch; +} uflags[] = { + {PS_FST_UFLAG_RDIR, 'r'}, + {PS_FST_UFLAG_CDIR, 'c'}, + {PS_FST_UFLAG_JAIL, 'j'}, + {PS_FST_UFLAG_TRACE, 't'}, + {PS_FST_UFLAG_TEXT, 'x'}, + {PS_FST_UFLAG_MMAP, 'm'}, + {PS_FST_UFLAG_CTTY, 'y'} +}; +#define NUFLAGS (sizeof(uflags) / sizeof(*uflags)) + +struct consumer { + pid_t pid; + uid_t uid; + int fd; + int flags; + int uflags; + STAILQ_ENTRY(consumer) next; +}; +struct reqfile { + uint32_t fsid; + uint64_t fileid; + const char *name; + STAILQ_HEAD(, consumer) consumers; +}; + +/* + * Option flags. + */ +#define UFLAG 0x01 /* -u flag: show users */ +#define FFLAG 0x02 /* -f flag: specified files only */ +#define CFLAG 0x04 /* -c flag: treat as mpoints */ +#define MFLAG 0x10 /* -m flag: mmapped files too */ +#define KFLAG 0x20 /* -k flag: send signal (SIGKILL by default) */ + +static int flags = 0; /* Option flags. */ + +static void printflags(struct consumer *consumer); +static int str2sig(const char *str); +static void usage(void) __dead2; +static int addfile(const char *path, struct reqfile *reqfile); +static void dofiles(struct procstat *procstat, struct kinfo_proc *kp, + struct reqfile *reqfiles, size_t nfiles); + +static void +usage(void) +{ + + fprintf(stderr, +"usage: fuser [-cfhkmu] [-M core] [-N system] [-s signal] file ...\n"); + exit(EX_USAGE); +} + +static void +printflags(struct consumer *cons) +{ + unsigned int i; + + assert(cons); + for (i = 0; i < NUFLAGS; i++) + if ((cons->uflags & uflags[i].flag) != 0) + fputc(uflags[i].ch, stderr); + for (i = 0; i < NFFLAGS; i++) + if ((cons->flags & fflags[i].flag) != 0) + fputc(fflags[i].ch, stderr); +} + +/* + * Add file to the list. + */ +static int +addfile(const char *path, struct reqfile *reqfile) +{ + struct stat sb; + + assert(path); + if (stat(path, &sb) != 0) { + warn("%s", path); + return (1); + } + reqfile->fileid = sb.st_ino; + reqfile->fsid = sb.st_dev; + reqfile->name = path; + STAILQ_INIT(&reqfile->consumers); + return (0); +} + +int +do_fuser(int argc, char *argv[]) +{ + struct consumer *consumer; + struct kinfo_proc *p, *procs; + struct procstat *procstat; + struct reqfile *reqfiles; + char *ep, *nlistf, *memf; + int ch, cnt, sig; + unsigned int i, nfiles; + + sig = SIGKILL; /* Default to kill. */ + nlistf = NULL; + memf = NULL; + while ((ch = getopt(argc, argv, "M:N:cfhkms:u")) != -1) + switch(ch) { + case 'f': + if ((flags & CFLAG) != 0) + usage(); + flags |= FFLAG; + break; + case 'c': + if ((flags & FFLAG) != 0) + usage(); + flags |= CFLAG; + break; + case 'N': + nlistf = optarg; + break; + case 'M': + memf = optarg; + break; + case 'u': + flags |= UFLAG; + break; + case 'm': + flags |= MFLAG; + break; + case 'k': + flags |= KFLAG; + break; + case 's': + if (isdigit(*optarg)) { + sig = strtol(optarg, &ep, 10); + if (*ep != '\0' || sig < 0 || sig >= sys_nsig) + errx(EX_USAGE, "illegal signal number" ": %s", + optarg); + } else { + sig = str2sig(optarg); + if (sig < 0) + errx(EX_USAGE, "illegal signal name: " + "%s", optarg); + } + break; + case 'h': + /* PASSTHROUGH */ + default: + usage(); + /* NORETURN */ + } + argv += optind; + argc -= optind; + + assert(argc >= 0); + if (argc == 0) + usage(); + /* NORETURN */ + + /* + * Process named files. + */ + reqfiles = malloc(argc * sizeof(struct reqfile)); + if (reqfiles == NULL) + err(EX_OSERR, "malloc()"); + nfiles = 0; + while (argc--) + if (!addfile(*(argv++), &reqfiles[nfiles])) + nfiles++; + if (nfiles == 0) + errx(EX_IOERR, "files not accessible"); + + if (memf != NULL) + procstat = procstat_open_kvm(nlistf, memf); + else + procstat = procstat_open_sysctl(); + if (procstat == NULL) + errx(1, "procstat_open()"); + procs = procstat_getprocs(procstat, KERN_PROC_PROC, 0, &cnt); + if (procs == NULL) + errx(1, "procstat_getprocs()"); + + /* + * Walk through process table and look for matching files. + */ + p = procs; + while(cnt--) + if (p->ki_stat != SZOMB) + dofiles(procstat, p++, reqfiles, nfiles); + + for (i = 0; i < nfiles; i++) { + fprintf(stderr, "%s:", reqfiles[i].name); + fflush(stderr); + STAILQ_FOREACH(consumer, &reqfiles[i].consumers, next) { + if (consumer->flags != 0) { + fprintf(stdout, "%6d", consumer->pid); + fflush(stdout); + printflags(consumer); + if ((flags & UFLAG) != 0) + fprintf(stderr, "(%s)", + user_from_uid(consumer->uid, 0)); + if ((flags & KFLAG) != 0) + kill(consumer->pid, sig); + fflush(stderr); + } + } + (void)fprintf(stderr, "\n"); + } + procstat_freeprocs(procstat, procs); + procstat_close(procstat); + free(reqfiles); + return (0); +} + +static void +dofiles(struct procstat *procstat, struct kinfo_proc *kp, + struct reqfile *reqfiles, size_t nfiles) +{ + struct vnstat vn; + struct consumer *cons; + struct filestat *fst; + struct filestat_list *head; + int error, match; + unsigned int i; + char errbuf[_POSIX2_LINE_MAX]; + + head = procstat_getfiles(procstat, kp, flags & MFLAG); + if (head == NULL) + return; + STAILQ_FOREACH(fst, head, next) { + if (fst->fs_type != PS_FST_TYPE_VNODE) + continue; + error = procstat_get_vnode_info(procstat, fst, &vn, errbuf); + if (error != 0) + continue; + for (i = 0; i < nfiles; i++) { + if (flags & CFLAG && reqfiles[i].fsid == vn.vn_fsid) { + break; + } + else if (reqfiles[i].fsid == vn.vn_fsid && + reqfiles[i].fileid == vn.vn_fileid) { + break; + } + else if (!(flags & FFLAG) && + (vn.vn_type == PS_FST_VTYPE_VCHR || + vn.vn_type == PS_FST_VTYPE_VBLK) && + vn.vn_fsid == reqfiles[i].fileid) { + break; + } + } + if (i == nfiles) + continue; /* No match. */ + + /* + * Look for existing entries. + */ + match = 0; + STAILQ_FOREACH(cons, &reqfiles[i].consumers, next) + if (cons->pid == kp->ki_pid) { + match = 1; + break; + } + if (match == 1) { /* Use old entry. */ + cons->flags |= fst->fs_fflags; + cons->uflags |= fst->fs_uflags; + } else { + /* + * Create new entry in the consumer chain. + */ + cons = calloc(1, sizeof(struct consumer)); + if (cons == NULL) { + warn("malloc()"); + continue; + } + cons->uid = kp->ki_uid; + cons->pid = kp->ki_pid; + cons->uflags = fst->fs_uflags; + cons->flags = fst->fs_fflags; + STAILQ_INSERT_TAIL(&reqfiles[i].consumers, cons, next); + } + } + procstat_freefiles(procstat, head); +} + +/* + * Returns signal number for it's string representation. + */ +static int +str2sig(const char *str) +{ + int i; + +#define SIGPREFIX "sig" + if (!strncasecmp(str, SIGPREFIX, sizeof(SIGPREFIX))) + str += sizeof(SIGPREFIX); + for (i = 1; i < sys_nsig; i++) { + if (!strcasecmp(sys_signame[i], str)) + return (i); + } + return (-1); +} diff --git a/usr.bin/fstat/main.c b/usr.bin/fstat/main.c new file mode 100644 index 00000000000..4123e64424e --- /dev/null +++ b/usr.bin/fstat/main.c @@ -0,0 +1,49 @@ +/*- + * Copyright (c) 2009 Stanislav Sedov . + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ + +#include +__FBSDID("$FreeBSD$"); + +#include +#include +#include +#include + +#include "functions.h" + +int +main(int argc, char *argv[]) +{ + char *p; + + p = basename(argv[0]); + if (p == NULL) + err(1, "basename(%s)", argv[0]); + if (!strcmp(p, "fuser")) + return (do_fuser(argc, argv)); + else + return (do_fstat(argc, argv)); +} diff --git a/usr.bin/procstat/Makefile b/usr.bin/procstat/Makefile index fa1c3b405a9..e8e35ed019f 100644 --- a/usr.bin/procstat/Makefile +++ b/usr.bin/procstat/Makefile @@ -13,7 +13,7 @@ SRCS= procstat.c \ procstat_threads.c \ procstat_vm.c -LDADD+= -lutil +LDADD+= -lutil -lprocstat -lkvm DPADD+= ${LIBUTIL} .include diff --git a/usr.bin/procstat/procstat.c b/usr.bin/procstat/procstat.c index ee95ae29005..69648fdedac 100644 --- a/usr.bin/procstat/procstat.c +++ b/usr.bin/procstat/procstat.c @@ -31,6 +31,7 @@ #include #include +#include #include #include #include @@ -45,36 +46,36 @@ static void usage(void) { - fprintf(stderr, "usage: procstat [-h] [-n] [-w interval] [-b | -c | -f | " - "-i | -j | -k | -s | -t | -v]\n"); + fprintf(stderr, "usage: procstat [-h] [-M core] [-N system] " + "[-w interval] [-b | -c | -f | -i | -j | -k | -s | -t | -v]\n"); fprintf(stderr, " [-a | pid ...]\n"); exit(EX_USAGE); } static void -procstat(pid_t pid, struct kinfo_proc *kipp) +procstat(struct procstat *prstat, struct kinfo_proc *kipp) { if (bflag) - procstat_bin(pid, kipp); + procstat_bin(kipp); else if (cflag) - procstat_args(pid, kipp); + procstat_args(kipp); else if (fflag) - procstat_files(pid, kipp); + procstat_files(prstat, kipp); else if (iflag) - procstat_sigs(pid, kipp); + procstat_sigs(prstat, kipp); else if (jflag) - procstat_threads_sigs(pid, kipp); + procstat_threads_sigs(prstat, kipp); else if (kflag) - procstat_kstack(pid, kipp, kflag); + procstat_kstack(kipp, kflag); else if (sflag) - procstat_cred(pid, kipp); + procstat_cred(kipp); else if (tflag) - procstat_threads(pid, kipp); + procstat_threads(kipp); else if (vflag) - procstat_vm(pid, kipp); + procstat_vm(kipp); else - procstat_basic(pid, kipp); + procstat_basic(kipp); } /* @@ -104,17 +105,26 @@ kinfo_proc_sort(struct kinfo_proc *kipp, int count) int main(int argc, char *argv[]) { - int ch, interval, name[4], tmp; - unsigned int i; - struct kinfo_proc *kipp; - size_t len; + int ch, interval, tmp; + int i; + struct kinfo_proc *p; + struct procstat *prstat; long l; pid_t pid; char *dummy; + char *nlistf, *memf; + int cnt; interval = 0; - while ((ch = getopt(argc, argv, "abcfijknhstvw:")) != -1) { + memf = nlistf = NULL; + while ((ch = getopt(argc, argv, "N:M:abcfijkhstvw:")) != -1) { switch (ch) { + case 'M': + memf = optarg; + break; + case 'N': + nlistf = optarg; + break; case 'a': aflag++; break; @@ -194,38 +204,27 @@ main(int argc, char *argv[]) if (!(aflag == 1 && argc == 0) && !(aflag == 0 && argc > 0)) usage(); + if (memf != NULL) + prstat = procstat_open_kvm(nlistf, memf); + else + prstat = procstat_open_sysctl(); + if (prstat == NULL) + errx(1, "procstat_open()"); do { if (aflag) { - name[0] = CTL_KERN; - name[1] = KERN_PROC; - name[2] = KERN_PROC_PROC; - - len = 0; - if (sysctl(name, 3, NULL, &len, NULL, 0) < 0) - err(-1, "sysctl: kern.proc.all"); - - kipp = malloc(len); - if (kipp == NULL) - err(-1, "malloc"); - - if (sysctl(name, 3, kipp, &len, NULL, 0) < 0) { - free(kipp); - err(-1, "sysctl: kern.proc.all"); - } - if (len % sizeof(*kipp) != 0) - err(-1, "kinfo_proc mismatch"); - if (kipp->ki_structsize != sizeof(*kipp)) - err(-1, "kinfo_proc structure mismatch"); - kinfo_proc_sort(kipp, len / sizeof(*kipp)); - for (i = 0; i < len / sizeof(*kipp); i++) { - procstat(kipp[i].ki_pid, &kipp[i]); + p = procstat_getprocs(prstat, KERN_PROC_PROC, 0, &cnt); + if (p == NULL) + errx(1, "procstat_getprocs()"); + kinfo_proc_sort(p, cnt); + for (i = 0; i < cnt; i++) { + procstat(prstat, &p[i]); /* Suppress header after first process. */ hflag = 1; } - free(kipp); + procstat_freeprocs(prstat, p); } - for (i = 0; i < (unsigned int)argc; i++) { + for (i = 0; i < argc; i++) { l = strtol(argv[i], &dummy, 10); if (*dummy != '\0') usage(); @@ -233,31 +232,12 @@ main(int argc, char *argv[]) usage(); pid = l; - name[0] = CTL_KERN; - name[1] = KERN_PROC; - name[2] = KERN_PROC_PID; - name[3] = pid; - - len = 0; - if (sysctl(name, 4, NULL, &len, NULL, 0) < 0) - err(-1, "sysctl: kern.proc.pid: %d", pid); - - kipp = malloc(len); - if (kipp == NULL) - err(-1, "malloc"); - - if (sysctl(name, 4, kipp, &len, NULL, 0) < 0) { - free(kipp); - err(-1, "sysctl: kern.proc.pid: %d", pid); - } - if (len != sizeof(*kipp)) - err(-1, "kinfo_proc mismatch"); - if (kipp->ki_structsize != sizeof(*kipp)) - errx(-1, "kinfo_proc structure mismatch"); - if (kipp->ki_pid != pid) - errx(-1, "kinfo_proc pid mismatch"); - procstat(pid, kipp); - free(kipp); + p = procstat_getprocs(prstat, KERN_PROC_PID, pid, &cnt); + if (p == NULL) + errx(1, "procstat_getprocs()"); + if (cnt != 0) + procstat(prstat, p); + procstat_freeprocs(prstat, p); /* Suppress header after first process. */ hflag = 1; @@ -265,5 +245,6 @@ main(int argc, char *argv[]) if (interval) sleep(interval); } while (interval); + procstat_close(prstat); exit(0); } diff --git a/usr.bin/procstat/procstat.h b/usr.bin/procstat/procstat.h index d73a2030775..ad425f30cdf 100644 --- a/usr.bin/procstat/procstat.h +++ b/usr.bin/procstat/procstat.h @@ -34,15 +34,15 @@ extern int hflag, nflag; struct kinfo_proc; void kinfo_proc_sort(struct kinfo_proc *kipp, int count); -void procstat_args(pid_t pid, struct kinfo_proc *kipp); -void procstat_basic(pid_t pid, struct kinfo_proc *kipp); -void procstat_bin(pid_t pid, struct kinfo_proc *kipp); -void procstat_cred(pid_t pid, struct kinfo_proc *kipp); -void procstat_files(pid_t pid, struct kinfo_proc *kipp); -void procstat_kstack(pid_t pid, struct kinfo_proc *kipp, int kflag); -void procstat_sigs(pid_t pid, struct kinfo_proc *kipp); -void procstat_threads(pid_t pid, struct kinfo_proc *kipp); -void procstat_threads_sigs(pid_t pid, struct kinfo_proc *kipp); -void procstat_vm(pid_t pid, struct kinfo_proc *kipp); +void procstat_args(struct kinfo_proc *kipp); +void procstat_basic(struct kinfo_proc *kipp); +void procstat_bin(struct kinfo_proc *kipp); +void procstat_cred(struct kinfo_proc *kipp); +void procstat_files(struct procstat *prstat, struct kinfo_proc *kipp); +void procstat_kstack(struct kinfo_proc *kipp, int kflag); +void procstat_sigs(struct procstat *prstat, struct kinfo_proc *kipp); +void procstat_threads(struct kinfo_proc *kipp); +void procstat_threads_sigs(struct procstat *prstat, struct kinfo_proc *kipp); +void procstat_vm(struct kinfo_proc *kipp); #endif /* !PROCSTAT_H */ diff --git a/usr.bin/procstat/procstat_args.c b/usr.bin/procstat/procstat_args.c index e5a7acda921..e8e6b947342 100644 --- a/usr.bin/procstat/procstat_args.c +++ b/usr.bin/procstat/procstat_args.c @@ -32,6 +32,7 @@ #include #include +#include #include #include #include @@ -42,7 +43,7 @@ static char args[ARG_MAX]; void -procstat_args(pid_t pid, struct kinfo_proc *kipp) +procstat_args(struct kinfo_proc *kipp) { int error, name[4]; size_t len; @@ -54,11 +55,11 @@ procstat_args(pid_t pid, struct kinfo_proc *kipp) name[0] = CTL_KERN; name[1] = KERN_PROC; name[2] = KERN_PROC_ARGS; - name[3] = pid; + name[3] = kipp->ki_pid; len = sizeof(args); error = sysctl(name, 4, args, &len, NULL, 0); if (error < 0 && errno != ESRCH) { - warn("sysctl: kern.proc.args: %d", pid); + warn("sysctl: kern.proc.args: %d", kipp->ki_pid); return; } if (error < 0) @@ -68,7 +69,7 @@ procstat_args(pid_t pid, struct kinfo_proc *kipp) len = strlen(args) + 1; } - printf("%5d ", pid); + printf("%5d ", kipp->ki_pid); printf("%-16s ", kipp->ki_comm); for (cp = args; cp < args + len; cp += strlen(cp) + 1) printf("%s%s", cp != args ? " " : "", cp); diff --git a/usr.bin/procstat/procstat_basic.c b/usr.bin/procstat/procstat_basic.c index 277517242a4..af43fd1329e 100644 --- a/usr.bin/procstat/procstat_basic.c +++ b/usr.bin/procstat/procstat_basic.c @@ -31,13 +31,14 @@ #include #include +#include #include #include #include "procstat.h" void -procstat_basic(pid_t pid __unused, struct kinfo_proc *kipp) +procstat_basic(struct kinfo_proc *kipp) { if (!hflag) diff --git a/usr.bin/procstat/procstat_bin.c b/usr.bin/procstat/procstat_bin.c index 8ed5efed9a1..cf4ca5b4644 100644 --- a/usr.bin/procstat/procstat_bin.c +++ b/usr.bin/procstat/procstat_bin.c @@ -32,6 +32,7 @@ #include #include +#include #include #include #include @@ -39,7 +40,7 @@ #include "procstat.h" void -procstat_bin(pid_t pid, struct kinfo_proc *kipp) +procstat_bin(struct kinfo_proc *kipp) { char pathname[PATH_MAX]; int error, name[4]; @@ -51,12 +52,12 @@ procstat_bin(pid_t pid, struct kinfo_proc *kipp) name[0] = CTL_KERN; name[1] = KERN_PROC; name[2] = KERN_PROC_PATHNAME; - name[3] = pid; + name[3] = kipp->ki_pid; len = sizeof(pathname); error = sysctl(name, 4, pathname, &len, NULL, 0); if (error < 0 && errno != ESRCH) { - warn("sysctl: kern.proc.pathname: %d", pid); + warn("sysctl: kern.proc.pathname: %d", kipp->ki_pid); return; } if (error < 0) @@ -64,7 +65,7 @@ procstat_bin(pid_t pid, struct kinfo_proc *kipp) if (len == 0 || strlen(pathname) == 0) strcpy(pathname, "-"); - printf("%5d ", pid); + printf("%5d ", kipp->ki_pid); printf("%-16s ", kipp->ki_comm); printf("%s\n", pathname); } diff --git a/usr.bin/procstat/procstat_cred.c b/usr.bin/procstat/procstat_cred.c index 1e91a94e9ae..ea8fdfd5ef4 100644 --- a/usr.bin/procstat/procstat_cred.c +++ b/usr.bin/procstat/procstat_cred.c @@ -31,6 +31,7 @@ #include #include +#include #include #include #include @@ -38,7 +39,7 @@ #include "procstat.h" void -procstat_cred(pid_t pid, struct kinfo_proc *kipp) +procstat_cred(struct kinfo_proc *kipp) { int i; int mib[4]; @@ -51,7 +52,7 @@ procstat_cred(pid_t pid, struct kinfo_proc *kipp) "COMM", "EUID", "RUID", "SVUID", "EGID", "RGID", "SVGID", "GROUPS"); - printf("%5d ", pid); + printf("%5d ", kipp->ki_pid); printf("%-16s ", kipp->ki_comm); printf("%5d ", kipp->ki_uid); printf("%5d ", kipp->ki_ruid); @@ -69,7 +70,7 @@ procstat_cred(pid_t pid, struct kinfo_proc *kipp) mib[0] = CTL_KERN; mib[1] = KERN_PROC; mib[2] = KERN_PROC_GROUPS; - mib[3] = pid; + mib[3] = kipp->ki_pid; ngroups = sysconf(_SC_NGROUPS_MAX) + 1; len = ngroups * sizeof(gid_t); @@ -78,7 +79,7 @@ procstat_cred(pid_t pid, struct kinfo_proc *kipp) if (sysctl(mib, 4, groups, &len, NULL, 0) == -1) { warn("sysctl: kern.proc.groups: %d " - "group list truncated", pid); + "group list truncated", kipp->ki_pid); free(groups); groups = NULL; } diff --git a/usr.bin/procstat/procstat_files.c b/usr.bin/procstat/procstat_files.c index debb0e44a20..f7d91a4384b 100644 --- a/usr.bin/procstat/procstat_files.c +++ b/usr.bin/procstat/procstat_files.c @@ -37,11 +37,11 @@ #include #include +#include #include #include #include #include -#include #include "procstat.h" @@ -132,162 +132,165 @@ print_address(struct sockaddr_storage *ss) } void -procstat_files(pid_t pid, struct kinfo_proc *kipp) -{ - struct kinfo_file *freep, *kif; - int i, cnt; +procstat_files(struct procstat *procstat, struct kinfo_proc *kipp) +{ + struct sockstat sock; + struct filestat_list *head; + struct filestat *fst; const char *str; + struct vnstat vn; + int error; if (!hflag) printf("%5s %-16s %4s %1s %1s %-8s %3s %7s %-3s %-12s\n", "PID", "COMM", "FD", "T", "V", "FLAGS", "REF", "OFFSET", "PRO", "NAME"); - freep = kinfo_getfile(pid, &cnt); - if (freep == NULL) + head = procstat_getfiles(procstat, kipp, 0); + if (head == NULL) return; - for (i = 0; i < cnt; i++) { - kif = &freep[i]; - - printf("%5d ", pid); + STAILQ_FOREACH(fst, head, next) { + printf("%5d ", kipp->ki_pid); printf("%-16s ", kipp->ki_comm); - switch (kif->kf_fd) { - case KF_FD_TYPE_CWD: + if (fst->fs_uflags & PS_FST_UFLAG_CTTY) + printf("ctty "); + else if (fst->fs_uflags & PS_FST_UFLAG_CDIR) printf(" cwd "); - break; - - case KF_FD_TYPE_ROOT: - printf("root "); - break; - - case KF_FD_TYPE_JAIL: + else if (fst->fs_uflags & PS_FST_UFLAG_JAIL) printf("jail "); - break; + else if (fst->fs_uflags & PS_FST_UFLAG_RDIR) + printf("root "); + else if (fst->fs_uflags & PS_FST_UFLAG_TEXT) + printf("text "); + else if (fst->fs_uflags & PS_FST_UFLAG_TRACE) + printf("trace "); + else + printf("%4d ", fst->fs_fd); - default: - printf("%4d ", kif->kf_fd); - break; - } - switch (kif->kf_type) { - case KF_TYPE_VNODE: + switch (fst->fs_type) { + case PS_FST_TYPE_VNODE: str = "v"; break; - case KF_TYPE_SOCKET: + case PS_FST_TYPE_SOCKET: str = "s"; break; - case KF_TYPE_PIPE: + case PS_FST_TYPE_PIPE: str = "p"; break; - case KF_TYPE_FIFO: + case PS_FST_TYPE_FIFO: str = "f"; break; - case KF_TYPE_KQUEUE: + case PS_FST_TYPE_KQUEUE: str = "k"; break; - case KF_TYPE_CRYPTO: + case PS_FST_TYPE_CRYPTO: str = "c"; break; - case KF_TYPE_MQUEUE: + case PS_FST_TYPE_MQUEUE: str = "m"; break; - case KF_TYPE_SHM: + case PS_FST_TYPE_SHM: str = "h"; break; - case KF_TYPE_PTS: + case PS_FST_TYPE_PTS: str = "t"; break; - case KF_TYPE_SEM: + case PS_FST_TYPE_SEM: str = "e"; break; - case KF_TYPE_NONE: - case KF_TYPE_UNKNOWN: + case PS_FST_TYPE_NONE: + case PS_FST_TYPE_UNKNOWN: default: str = "?"; break; } printf("%1s ", str); str = "-"; - if (kif->kf_type == KF_TYPE_VNODE) { - switch (kif->kf_vnode_type) { - case KF_VTYPE_VREG: + if (fst->fs_type == PS_FST_TYPE_VNODE) { + error = procstat_get_vnode_info(procstat, fst, &vn, NULL); + switch (vn.vn_type) { + case PS_FST_VTYPE_VREG: str = "r"; break; - case KF_VTYPE_VDIR: + case PS_FST_VTYPE_VDIR: str = "d"; break; - case KF_VTYPE_VBLK: + case PS_FST_VTYPE_VBLK: str = "b"; break; - case KF_VTYPE_VCHR: + case PS_FST_VTYPE_VCHR: str = "c"; break; - case KF_VTYPE_VLNK: + case PS_FST_VTYPE_VLNK: str = "l"; break; - case KF_VTYPE_VSOCK: + case PS_FST_VTYPE_VSOCK: str = "s"; break; - case KF_VTYPE_VFIFO: + case PS_FST_VTYPE_VFIFO: str = "f"; break; - case KF_VTYPE_VBAD: + case PS_FST_VTYPE_VBAD: str = "x"; break; - case KF_VTYPE_VNON: - case KF_VTYPE_UNKNOWN: + case PS_FST_VTYPE_VNON: + case PS_FST_VTYPE_UNKNOWN: default: str = "?"; break; } } printf("%1s ", str); - printf("%s", kif->kf_flags & KF_FLAG_READ ? "r" : "-"); - printf("%s", kif->kf_flags & KF_FLAG_WRITE ? "w" : "-"); - printf("%s", kif->kf_flags & KF_FLAG_APPEND ? "a" : "-"); - printf("%s", kif->kf_flags & KF_FLAG_ASYNC ? "s" : "-"); - printf("%s", kif->kf_flags & KF_FLAG_FSYNC ? "f" : "-"); - printf("%s", kif->kf_flags & KF_FLAG_NONBLOCK ? "n" : "-"); - printf("%s", kif->kf_flags & KF_FLAG_DIRECT ? "d" : "-"); - printf("%s ", kif->kf_flags & KF_FLAG_HASLOCK ? "l" : "-"); - if (kif->kf_ref_count > -1) - printf("%3d ", kif->kf_ref_count); + printf("%s", fst->fs_fflags & PS_FST_FFLAG_READ ? "r" : "-"); + printf("%s", fst->fs_fflags & PS_FST_FFLAG_WRITE ? "w" : "-"); + printf("%s", fst->fs_fflags & PS_FST_FFLAG_APPEND ? "a" : "-"); + printf("%s", fst->fs_fflags & PS_FST_FFLAG_ASYNC ? "s" : "-"); + printf("%s", fst->fs_fflags & PS_FST_FFLAG_SYNC ? "f" : "-"); + printf("%s", fst->fs_fflags & PS_FST_FFLAG_NONBLOCK ? "n" : "-"); + printf("%s", fst->fs_fflags & PS_FST_FFLAG_DIRECT ? "d" : "-"); + printf("%s ", fst->fs_fflags & PS_FST_FFLAG_HASLOCK ? "l" : "-"); + if (fst->fs_ref_count > -1) + printf("%3d ", fst->fs_ref_count); else printf("%3c ", '-'); - if (kif->kf_offset > -1) - printf("%7jd ", (intmax_t)kif->kf_offset); + if (fst->fs_offset > -1) + printf("%7jd ", (intmax_t)fst->fs_offset); else printf("%7c ", '-'); - switch (kif->kf_type) { - case KF_TYPE_VNODE: - case KF_TYPE_FIFO: - case KF_TYPE_PTS: + switch (fst->fs_type) { + case PS_FST_TYPE_VNODE: + case PS_FST_TYPE_FIFO: + case PS_FST_TYPE_PTS: printf("%-3s ", "-"); - printf("%-18s", kif->kf_path); + printf("%-18s", fst->fs_path != NULL ? fst->fs_path : "-"); break; - case KF_TYPE_SOCKET: + case PS_FST_TYPE_SOCKET: + error = procstat_get_socket_info(procstat, fst, &sock, NULL); + if (error != 0) + break; printf("%-3s ", - protocol_to_string(kif->kf_sock_domain, - kif->kf_sock_type, kif->kf_sock_protocol)); + protocol_to_string(sock.dom_family, + sock.type, sock.proto)); /* * While generally we like to print two addresses, * local and peer, for sockets, it turns out to be @@ -295,18 +298,18 @@ procstat_files(pid_t pid, struct kinfo_proc *kipp) * local sockets, as typically they aren't bound and * connected, and the path strings can get long. */ - if (kif->kf_sock_domain == AF_LOCAL) { + if (sock.dom_family == AF_LOCAL) { struct sockaddr_un *sun = - (struct sockaddr_un *)&kif->kf_sa_local; + (struct sockaddr_un *)&sock.sa_local; if (sun->sun_path[0] != 0) - print_address(&kif->kf_sa_local); + print_address(&sock.sa_local); else - print_address(&kif->kf_sa_peer); + print_address(&sock.sa_peer); } else { - print_address(&kif->kf_sa_local); + print_address(&sock.sa_local); printf(" "); - print_address(&kif->kf_sa_peer); + print_address(&sock.sa_peer); } break; @@ -317,5 +320,4 @@ procstat_files(pid_t pid, struct kinfo_proc *kipp) printf("\n"); } - free(freep); } diff --git a/usr.bin/procstat/procstat_kstack.c b/usr.bin/procstat/procstat_kstack.c index 9d5f71e3757..fd2b9ab22c4 100644 --- a/usr.bin/procstat/procstat_kstack.c +++ b/usr.bin/procstat/procstat_kstack.c @@ -32,6 +32,7 @@ #include #include +#include #include #include #include @@ -124,7 +125,7 @@ kinfo_kstack_sort(struct kinfo_kstack *kkstp, int count) void -procstat_kstack(pid_t pid, struct kinfo_proc *kipp, int kflag) +procstat_kstack(struct kinfo_proc *kipp, int kflag) { struct kinfo_kstack *kkstp, *kkstp_free; struct kinfo_proc *kip, *kip_free; @@ -140,12 +141,12 @@ procstat_kstack(pid_t pid, struct kinfo_proc *kipp, int kflag) name[0] = CTL_KERN; name[1] = KERN_PROC; name[2] = KERN_PROC_KSTACK; - name[3] = pid; + name[3] = kipp->ki_pid; kstk_len = 0; error = sysctl(name, 4, NULL, &kstk_len, NULL, 0); if (error < 0 && errno != ESRCH && errno != EPERM && errno != ENOENT) { - warn("sysctl: kern.proc.kstack: %d", pid); + warn("sysctl: kern.proc.kstack: %d", kipp->ki_pid); return; } if (error < 0 && errno == ENOENT) { @@ -160,7 +161,7 @@ procstat_kstack(pid_t pid, struct kinfo_proc *kipp, int kflag) err(-1, "malloc"); if (sysctl(name, 4, kkstp, &kstk_len, NULL, 0) < 0) { - warn("sysctl: kern.proc.pid: %d", pid); + warn("sysctl: kern.proc.pid: %d", kipp->ki_pid); free(kkstp); return; } @@ -171,12 +172,12 @@ procstat_kstack(pid_t pid, struct kinfo_proc *kipp, int kflag) name[0] = CTL_KERN; name[1] = KERN_PROC; name[2] = KERN_PROC_PID | KERN_PROC_INC_THREAD; - name[3] = pid; + name[3] = kipp->ki_pid; kip_len = 0; error = sysctl(name, 4, NULL, &kip_len, NULL, 0); if (error < 0 && errno != ESRCH) { - warn("sysctl: kern.proc.pid: %d", pid); + warn("sysctl: kern.proc.pid: %d", kipp->ki_pid); return; } if (error < 0) @@ -187,7 +188,7 @@ procstat_kstack(pid_t pid, struct kinfo_proc *kipp, int kflag) err(-1, "malloc"); if (sysctl(name, 4, kip, &kip_len, NULL, 0) < 0) { - warn("sysctl: kern.proc.pid: %d", pid); + warn("sysctl: kern.proc.pid: %d", kipp->ki_pid); free(kip); return; } @@ -209,7 +210,7 @@ procstat_kstack(pid_t pid, struct kinfo_proc *kipp, int kflag) if (kipp == NULL) continue; - printf("%5d ", pid); + printf("%5d ", kipp->ki_pid); printf("%6d ", kkstp->kkst_tid); printf("%-16s ", kipp->ki_comm); printf("%-16s ", (strlen(kipp->ki_ocomm) && diff --git a/usr.bin/procstat/procstat_sigs.c b/usr.bin/procstat/procstat_sigs.c index b1f5e35fb46..70df25004fd 100644 --- a/usr.bin/procstat/procstat_sigs.c +++ b/usr.bin/procstat/procstat_sigs.c @@ -37,6 +37,7 @@ #include #include #include +#include #include "procstat.h" @@ -63,10 +64,12 @@ procstat_print_sig(const sigset_t *set, int sig, char flag) } void -procstat_sigs(pid_t pid, struct kinfo_proc *kipp) +procstat_sigs(struct procstat *prstat __unused, struct kinfo_proc *kipp) { int j; + pid_t pid; + pid = kipp->ki_pid; if (!hflag) printf("%5s %-16s %-7s %4s\n", "PID", "COMM", "SIG", "FLAGS"); @@ -83,13 +86,15 @@ procstat_sigs(pid_t pid, struct kinfo_proc *kipp) } void -procstat_threads_sigs(pid_t pid, struct kinfo_proc *kipp) +procstat_threads_sigs(struct procstat *prstat __unused, struct kinfo_proc *kipp) { struct kinfo_proc *kip; + pid_t pid; int error, name[4], j; unsigned int i; size_t len; + pid = kipp->ki_pid; if (!hflag) printf("%5s %6s %-16s %-7s %4s\n", "PID", "TID", "COMM", "SIG", "FLAGS"); diff --git a/usr.bin/procstat/procstat_threads.c b/usr.bin/procstat/procstat_threads.c index 64e0a369ccc..7633608feeb 100644 --- a/usr.bin/procstat/procstat_threads.c +++ b/usr.bin/procstat/procstat_threads.c @@ -32,6 +32,7 @@ #include #include +#include #include #include #include @@ -39,7 +40,7 @@ #include "procstat.h" void -procstat_threads(pid_t pid, struct kinfo_proc *kipp) +procstat_threads(struct kinfo_proc *kipp) { struct kinfo_proc *kip; int error, name[4]; @@ -57,12 +58,12 @@ procstat_threads(pid_t pid, struct kinfo_proc *kipp) name[0] = CTL_KERN; name[1] = KERN_PROC; name[2] = KERN_PROC_PID | KERN_PROC_INC_THREAD; - name[3] = pid; + name[3] = kipp->ki_pid; len = 0; error = sysctl(name, 4, NULL, &len, NULL, 0); if (error < 0 && errno != ESRCH) { - warn("sysctl: kern.proc.pid: %d", pid); + warn("sysctl: kern.proc.pid: %d", kipp->ki_pid); return; } if (error < 0) @@ -73,7 +74,7 @@ procstat_threads(pid_t pid, struct kinfo_proc *kipp) err(-1, "malloc"); if (sysctl(name, 4, kip, &len, NULL, 0) < 0) { - warn("sysctl: kern.proc.pid: %d", pid); + warn("sysctl: kern.proc.pid: %d", kipp->ki_pid); free(kip); return; } @@ -81,7 +82,7 @@ procstat_threads(pid_t pid, struct kinfo_proc *kipp) kinfo_proc_sort(kip, len / sizeof(*kipp)); for (i = 0; i < len / sizeof(*kipp); i++) { kipp = &kip[i]; - printf("%5d ", pid); + printf("%5d ", kipp->ki_pid); printf("%6d ", kipp->ki_tid); printf("%-16s ", strlen(kipp->ki_comm) ? kipp->ki_comm : "-"); diff --git a/usr.bin/procstat/procstat_vm.c b/usr.bin/procstat/procstat_vm.c index 5c965a99076..2eada92f766 100644 --- a/usr.bin/procstat/procstat_vm.c +++ b/usr.bin/procstat/procstat_vm.c @@ -32,6 +32,7 @@ #include #include +#include #include #include #include @@ -40,7 +41,7 @@ #include "procstat.h" void -procstat_vm(pid_t pid, struct kinfo_proc *kipp __unused) +procstat_vm(struct kinfo_proc *kipp) { struct kinfo_vmentry *freep, *kve; int ptrwidth; @@ -53,12 +54,12 @@ procstat_vm(pid_t pid, struct kinfo_proc *kipp __unused) "PID", ptrwidth, "START", ptrwidth, "END", "PRT", "RES", "PRES", "REF", "SHD", "FL", "TP", "PATH"); - freep = kinfo_getvmmap(pid, &cnt); + freep = kinfo_getvmmap(kipp->ki_pid, &cnt); if (freep == NULL) return; for (i = 0; i < cnt; i++) { kve = &freep[i]; - printf("%5d ", pid); + printf("%5d ", kipp->ki_pid); printf("%#*jx ", ptrwidth, (uintmax_t)kve->kve_start); printf("%#*jx ", ptrwidth, (uintmax_t)kve->kve_end); printf("%s", kve->kve_protection & KVME_PROT_READ ? "r" : "-"); From ff6f41a4722d005627a28483dcf406fe77dba3f9 Mon Sep 17 00:00:00 2001 From: Stanislav Sedov Date: Thu, 12 May 2011 10:56:33 +0000 Subject: [PATCH 29/30] - Do no try to drop a NULL filedesc pointer. --- sys/kern/kern_descrip.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/sys/kern/kern_descrip.c b/sys/kern/kern_descrip.c index bf75db0deb9..180d598991c 100644 --- a/sys/kern/kern_descrip.c +++ b/sys/kern/kern_descrip.c @@ -3224,7 +3224,8 @@ sysctl_kern_proc_filedesc(SYSCTL_HANDLER_ARGS) } FILEDESC_SUNLOCK(fdp); fail: - fddrop(fdp); + if (fdp != NULL) + fddrop(fdp); free(kif, M_TEMP); return (error); } From 76dc2afdc76c1a8dd7e62cd6d731018102ebd4a4 Mon Sep 17 00:00:00 2001 From: Andriy Gapon Date: Thu, 12 May 2011 12:18:01 +0000 Subject: [PATCH 30/30] fix build on 32-bit platforms for r221803 Casting a pointer to a wide integer is probably not that bad, but I am still guilty of not testing this. Pointyhat to: avg MFC after: 1 week X-MFC with: r221803 --- sys/dev/sound/pcm/dsp.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sys/dev/sound/pcm/dsp.c b/sys/dev/sound/pcm/dsp.c index 8e9393109e1..1d52cbe3c7d 100644 --- a/sys/dev/sound/pcm/dsp.c +++ b/sys/dev/sound/pcm/dsp.c @@ -2255,7 +2255,7 @@ dsp_mmap_single(struct cdev *i_dev, vm_ooffset_t *offset, if (rdch != NULL) rdch->flags |= CHN_F_MMAP; - *offset = (vm_ooffset_t)sndbuf_getbufofs(c->bufsoft, *offset); + *offset = (uintptr_t)sndbuf_getbufofs(c->bufsoft, *offset); relchns(i_dev, rdch, wrch, SD_F_PRIO_RD | SD_F_PRIO_WR); *object = vm_pager_allocate(OBJT_DEVICE, i_dev, size, nprot, *offset, curthread->td_ucred);