Wednesday, April 10, 2013

Service Management Facility

The Service Management Facility was introduced in Solaris 9 as an alternative way to manage services. In Solaris 10, SMF has been made the default way to manage most services. The SMF framework has significant advantages over the legacy SVR4 mechanisms, primarily in terms of service monitoring and integration with the Fault Management Facility.

Basic Commands

The basic commands for managing services under SMF (Service Management Facility) control are svcs, svccfg and svcadm. The man pages for these commands are a good source of detailed information.

inetadm can be used to monitor services under inetd control.

Many commands require referencing the service identifier, also known as an FMRI.

svcs

  • svcs -a: Lists all services currently installed, including their state.
  • svcs -d FMRI: Lists dependencies for FMRI.
  • svcs -D FMRI: Lists dependents for FMRI.
  • svcs -l FMRI: Provides a long listing of information about FMRI; includes dependency information
  • svcs -p FMRI: Shows relationships between services and processes.
  • svcs -t: This change is temporary (does not persist past a boot).
  • svcs -x: Explains why a service is not available.
  • svcs -xv: Verbose debugging information.

svcadm

  • svcadm clear FMRI: Clear faults for FMRI.
  • svcadm disable FMRI: Disable FMRI.
  • svcadm enable FMRI: Enable FMRI.
  • svcadm refresh FMRI: Force FMRI to read config file.
  • svcadm restart FMRI: Restart FMRI.

To make configuration changes to a non-inetd service, edit the configuration file, then enter the svcadm restart command.

svccfg

  • svccfg: Enter interactive mode.
  • svccfg -s FMRI setenv ENV_VARIABLE value: Set an environment variable for FMRI. Follow by svcadm refresh and restart commands.

inetadm

  • inetadm -l FMRI: Displays properties for FMRI.
  • inetadm -m FMRI property_name=value: Set a property for FMRI.

In particular, the "exec" value for an inetd-controlled service is the command line executed for that service by SMF. It may be desirable, for example, to change this value to add logging or other command-line flags.

To convert an inetd.conf file to SMF format, run the command:
inetconv -i /etc/inet/inetd.conf

Service Identifiers

Services are identified by their FMRI. (This stands for Fault Managed Resource Identifier.) An example is:
svc:/system/system-log:default
Some commands do not require the full FMRI if there is no ambiguity.

Legacy init scripts have FMRIs starting with lrc. For example:
lrc:/etc/rcS_d/S35cacheos_sh

Converted inetd services have a syntax like one of the following, depending on whether or not they are rpc services:
svc:network/service-name/protocol svc:network/rpc-service-name/rpc_protocol

SMF Service Starts

The svc.startd daemon is the master process starter and restarter for SMF. It tracks service state and manages dependencies.

Services that are managed through init scripts can be added to SMF via the inetconv command. Such additions are only monitored for status, but other SMF facilities may not work.

Maintenance

If a service is in the maintenance state, first make sure that all associated processes have died:
svcs -p FMRI
Next, (for all processes displayed by the above):
pkill -9 PID
Consult the appropriate logs in /var/svc/log to check any errors; perform any needed maintenance.
Restore the service:
svcadm clear FMRI

Scripts

The scripts that implement the startups and shutdowns are located in their usual place in /etc/init.d for the lrc services, or in /lib/svc/method for most of the other services.

Other locations may be specified for a particular service. To track down the script locations for a particular service, do something like the following:

# svccfg -s smtp
svc:/network/smtp> list
:properties
sendmail
svc:/network/smtp> select sendmail
svc:/network/smtp:sendmail> list
:properties
svc:/network/smtp:sendmail> listprop *exec
start/exec astring "/lib/svc/method/smtp-sendmail start"
stop/exec astring "/lib/svc/method/smtp-sendmail stop %{restarter/contract}" refresh/exec astring "/lib/svc/method/smtp-sendmail refresh"

Boot Messages

Boot messages are much less verbose than previously. To get verbose output, boot with the
boot -v
or
boot -m verbose
commands.

svcadm can be used to change the run levels. The FMRIs associated with the different run levels are:

  • S: milestone/single-user:default
  • 2: milestone/multi-user:default
  • 3: milestone/multi-user-server:default
Run levels can be displayed with
who -r

SMF Profiles

SMF profiles are XML files in /var/svc/profile which list sets of service instances which are enabled and disabled.

Different SMF profiles can be used. They are stored in /var/svc/profile. To use a different one, perform the following procedure:
svccfg apply /var/svc/profile/desired_profile.xml

The local profile /var/svc/profile/site.xml allows local customizations. This profile is applied after the standard profiles.

To make a copy of the current profile for editing, run:
svccfg extract> profile-file.xml

Service Configuration Repository

Stores persistent configuration information and SMF runtime data for services.

Each service's manifest is in an XML-formatted text file located in /var/svc/manifest. The information from the manifests is imported into the repository through svccfg import or during a reboot.

This is covered in the svccfg, svcprodp, service_bundle and svc.configd man pages.

If the repository is corrupted, it can be restored from an automatic backup using the /lib/svc/bin/restore_repository command. The svcadm refresh; svc adm restart command will make a snapshot active. Automatic snapshots are taken for initial (import of the manifest), running (when service methods are executed) and start (last successful start).

Revert to a Snapshot

The procedure to revert to a snapshot is the following:
Run svccfg in interactive mode:
svccfg
In the svc:> prompt, select the desired service with a full FMRI:
select FMRI
List the available snapshots:
listsnap
Revert to the desired snapshot:
revert desired_snapshot_label
Quit out of the svccfg interactive mode:
quit
Update the service configuration repository information:
svcadm refresh FMRI
svcadm restart FMRI

Boot Troubleshooting

To step through the SMF portion of the boot process, start with:
boot -m milestone=none
Then step through the milestones for the different boot levels:
svcadm milestone svc:/milestone/single-user:default
svcadm milestone svc:/milestone/multi-user:default
svcadm milestone svc:/milestone/multi-user-server:default

Several things should be examined if a service fails to start:

  • Is the service in maintenance mode? (svcs -l FMRI)
  • If so, why? Check the log file specified in the svcs -l FMRI | grep logfile output, and run svcs -xv FMRI
  • If the problem has been resolved, clear the fault with svcadm clear FMRI
  • Check for service dependencies with svcs -d FMRI The output from svcs -l distinguishes between optional and mandatory dependencies.
  • Check the startup properties with svcprop -p start FMRI The startup for the process can be trussed to get some visibility into where it is failing by inserting a truss into the start or exec statement for the service. To do this, just add truss -f -a -o /path/service-truss.out to the beginning of the start or exec statement with an svccfg -s statement.

Solaris Fault Management

The Solaris Fault Management Facility is designed to be integrated into the Service Management Facility to provide a self-healing capability to Solaris 10 systems.

The fmd daemon is responsible for monitoring several aspects of system health.

The fmadm config command shows the current configuration for fmd.

The Fault Manager logs can be viewed with fmdump -v and fmdump -e -v.

fmadm faulty will list any devices flagged as faulty.

fmstat shows statistics gathered by fmd.

Fault Management

With Solaris 10, Sun has implemented a daemon, fmd, to track and react to fault management. In addition to sending traditional syslog messages, the system sends binary telemetry events to fmd for correlation and analysis. Solaris 10 implements default fault management operations for several pieces of hardware in Sparc systems, including CPU, memory, and I/O bus events. Similar capabilities are being implemented for x64 systems.

Once the problem is defined, failing components may be offlined automatically without a system crash, or other corrective action may be taken by fmd. If a service dies as a result of the fault, the Service Management Facility (SMF) will attempt to restart it and any dependent processes.

The Fault Management Facility reports error messages in a well-defined and explicit format. Each error code is uniquely specified by a Universal Unique Identifier (UUID) related to a document on the Sun web site.

Resources are uniquely identified by a Fault Managed Resource Identifier (FMRI). Each Field Replaceable Unit (FRU) has its own FMRI. FMRIs are associated with one of the following conditions:

  • ok: Present and available for use.
  • unknown: Not present or not usable, perhaps because it has been offlined or unconfigured.
  • degraded: Present and usable, but one or more problems have been identified.
  • faulted: Present but not usable; unrecoverable problems have been diagnosed and the resource has been disabled to prevent damage to the system.

The fmdump -V -u eventid command can be used to pull information on the type and location of the event. (The eventid is included in the text of the error message provided to syslog.) The -e option can be used to pull error log information rather than fault log information.

Statistical information on the performance of fmd can be viewed via the fmstat command. In particular, fmstat -m modulename provides information for a given module.

The fmadm command provides administrative support for the Fault Management Facility. It allows us to load and upload modules and view and update the resource cache. The most useful capabilities of fmadm are provided through the following subcommands:

  • config: Display the configuration of component modules.
  • faulty: Display faulted resources. With the -a option, list cached resource information. With the -i option, list persistent cache identifier information, instead of most recent state and UUID.
  • load /path/module: Load the module.
  • unload module: Unload module; the module name is the same as reported by fmadm config.
  • rotate logfile: Schedule rotation for the specified log file. Used with the logadm configuration file.

Tuesday, April 09, 2013

Solaris Important Header Files

Some of these header files contain important information that can be used when analyzing a core dump or setting parameter values.

Location
Description
/usr/include/sys Most system header files.
/usr/include/vm Header files describing virtual memory structures.
/usr/include/sys/fs Header files describing file system structures and types.
/usr/platform/`arch -k`/include/sys Architecture dependent structures.
/usr/platform/`arch -k`/include/vm Architecture-dependent virtual memory structures.
/usr/include/[net, nfs, rpc, protocols, inet, netinet] Define networking data structures.

Monday, April 08, 2013

Solaris System Configuration Files

For details about the files and commands summarized here, consult the appropriate man pages or Solaris Documentation
File
Description
/etc/bootparams Contains information regarding network boot clients.
/etc/cron.d/cron.allow
/etc/cron.d/cron.deny
Allow access to crontab for users listed in this file. If the file does not exist, access is permitted for users not in the /etc/cron.d/cron.deny file.
/etc/defaultdomain NIS domain set by /etc/init.d/inetinit
/etc/default/cron Sets cron logging with the CRONLOG variable.
/etc/default/login Controls root logins via specification of the CONSOLE variable, as well as variables for login logging thresholds and password requirements.
/etc/default/su Determines logging activity for su attempts via the SULOG and SYSLOG variables, sets some initial environment variables for su sessions.
/etc/dfs/dfstab Determines which directories will be NFS-shared at boot time. Each line is a share command.
/etc/dfs/sharetab Contains a table of resources that have been shared via share.
/etc/group Provides groupname translation information.
/etc/hostname.interface Assigns a hostname to interface; assigns an IP address by cross- referencing /etc/inet/hosts.
/etc/hosts.allow
/etc/hosts.deny
Determine which hosts will be allowed access to TCP wrapper mediated services.
/etc/hosts.equiv Determines which set of hosts will not need to provide passwords when using the "r" remote access commands (eg rlogin, rsh, rexec)
/etc/inet/hosts
/etc/hosts
Associates hostnames and IP addresses.
/etc/inet/inetd.conf
/etc/inetd.conf
Identifies the services that are started by inetd as well as the manner in which they are started. inetd.conf may even specify that TCP wrappers be used to protect a service.
/etc/inittab inittab is used by init to determine scripts to for different run levels as well as a default run level.
/etc/logindevperm Contains information to change permissions for devices upon console logins.
/etc/magic Database of magic numbers that identify file types for file.
/etc/mail/aliases
/etc/aliases
Contains mail aliases recognized by sendmail.
/etc/mail/sendmail.cf
/etc/sendmail.cf
Mail configuration file for sendmail.
/etc/minor_perm Specifies permissions for device files; used by drvconfig
/etc/mnttab Contains information about currently mounted resources.
/etc/name_to_major List of currently configured major device numbers; used by drvconfig.
/etc/netconfig Network configuration database read during network initialization.
/etc/netgroup Defines groups of hosts and/or users.
/etc/netmasks Determines default netmask settings.
/etc/nsswitch.conf Determines order in which different information sources are accessed when performing lookups.
/etc/path_to_inst Contents of physical device tree using physical device names and instance numbers.
/etc/protocols Known protocols.
/etc/remote Attributes for tip sessions.
/etc/rmtab Currently mounted filesystems.
/etc/rpc Available RPC programs.
/etc/services Well-known networking services and associated port numbers.
/etc/syslog.conf Configures syslogd logging.
/etc/system Can be used to force kernel module loading or set kernel tuneable parameters.
/etc/vfstab Information for mounting local and remote filesystems.
/var/adm/messages Main log file used by syslogd.
/var/adm/sulog Default log for recording use of su command.
/var/adm/utmpx User and accounting information.
/var/adm/wtmpx User login and accounting information.
/var/local/etc/ftpaccess
/var/local/etc/ftpconversions
/var/local/etc/ftpusers
wu-ftpd configuration files to set ftp access rights, conversion/compression types, and a list of userids to exclude from ftp operations.
/var/lp/log Print services activity log.
/var/sadm/install/contents Database of installed software packages.
/var/saf/_log Logs activity of SAF (Service Access Facility).

Book Review: Solaris Internals

This book should be in the library of any serious Solaris administrator. It is not a book for beginners, but it is well-organized and well-explained. The authors went to a great deal of trouble to clean up the parts of the original edition that were not as easily understood, and their effort shows.

The examples are clear and well-explained, and the information is indexed and cross-referenced in a way that makes it easy to follow threads across chapters.

The authors of this book have been extraordinarily generous with their time and energy. Jim Mauro was very encouraging and helpful in explaining topics which found their way onto my web site and into my book. The entire community owes these gentlemen a debt of gratitude for their professionalism and their generosity.

Sunday, April 07, 2013

Sun System Bus Sizing

This is an older posting I made to the original Solaris Troubleshooting site. The information is a little dated in terms of available hardware options, but the concepts and philosophy are the same.

The system bus has a fixed bandwidth. Too many devices on the bus can create more traffic than the bus can handle, which results in contention and packet loss.

prtdiag -v reports on many system bus configuration issues. It is possible to see if the bus is overloaded by adding up the reported capacities of the devices on a bus and seeing if they exceed the capacity of the bus.

Where possible, similar cards can be placed on the same board so that the interrupts are directed to the same CPU (and associated caches).

This is a table of typical system bus capacities:

Bus Speed Width Burst
Bandwidth
Sustained
Bandwidth
MBus 33MHz 64 bit 264 MB/s 86 MB/s
MBus 36MHz 64 bit 288 MB/s 94 MB/s
MBus 40MHz 64 bit 320 MB/s 105 MB/s
MBus 50MHz 64 bit 400 MB/s 130 MB/s
XDBus 40MHz 64 bit 320 MB/s 250 MB/s
XDBus 50MHz 64 bit 400 MB/s 312 MB/s
UPA 72MHz 128 bit 1.15 GB/s 1 GB/s
UPA 83.5MHz 128 bit 1.3 GB/s 1.2 GB/s
UPA 100MHz 128 bit 1.5 GB/s 1.44 GB/s
Gigaplane 83.5MHz 256 bit 2.6 GB/s 2.5 GB/s
GigaplaneXB 100MHz 1024 bit 12.8 GB/s 12.8 GB/s

Peripheral Buses

The two peripheral buses on Sun systems are Sbus and PCI bus. Sbus runs at 20-25MHz and comes in 32 or 64 bit sizes. Peak Sbus bandwidth is 200 MB/s. The venerable Sbus has been retired in favor of the newer PCI bus as PCI bus performance has improved.

PCI buses runs at 33 or 66MHz and may be 32 or 64 bit. The peak PCI bus bandwidth is 528 MB/s for 64-bit buses at 66MHz.

(For desktop PC hardware, 33MHz PCI buses are still common. 33 MHz buses have peak bandwidths of 264 MB/s for 64-bit and 132 MB/s for 32-bit.)

Newer PCI-x buses run at 133MHz and allow up to 1066 MB/s. PCI-x 2.0 defines clock rates of 266MHz and 533MHz, with peak bandwidths of 2.1 GB/s and 4.2 GB/s, respectively.

Low profile PCI buses are becoming more common, since their smaller form factor fits well with the increasing miniaturization of the system. Low profile PCI comes in MD1 and MD2 flavors, with the primary difference being the shorter length of the MD1 cards. Currently, they do not support 64-bit PCI extensions.

Mini PCI cards are also produced for use in portable and sealed case computers. They are small in size, do not support 64-bit extensions and have a different connector layout, but still otherwise follow the PCI standard.

SCSI Bus

SCSI buses can operate at one of these speeds:
  • 4 MB/s (asynchronous)
  • 5 MB/s (synchronous)
  • 10 MB/s (fast)
  • 20 MB/s (ultra, fast/wide or fast-20)
  • 40 MB/s (ultra/wide or narrow ultra-2)
  • 80MB/s (wide ultra-2)
  • 160 MB/s (ultra-3 or ultra-160)
  • 320 MB/s (ultra-320)
SCSI buses and devices negotiate speed between the controller and the devices on the chain. prtconf can report information that can be used to determine the speed of a particular device.

The scsi_options parameter can be set in the /etc/system file to limit bus speed or set other characteristics. Check device documentation to determine if these settings need to be specified.

SCSI chains may be made of single-ended (SE) or differential connections. Differential connections come in low voltage (LVD) and high voltage (HVD) variants. SE, LVD, and HVD should not be mixed, as this may damage the equipment.

Differential connections permit longer chains, but the hardware is usually more expensive. Single-ended chains must be less than 6m in length; LVD chains must be less than 12m in length; HVD chains must be less than 20m for synchronous connections or 25m for asynchronous connections. (Remember that chain length includes the length of the connectors and cabling in the devices, not just the external cable.)

Starting with Ultra 2, only differential connections are available. Only LVD is available for Ultra160 or Ultra320.

The SCSI target numbers represent attachment points on the SCSI chain. Each target number may include as many as 8 devices (luns or logical unit numbers). Embedded SCSI devices only include one lun.

Higher target numbers receive better service. On a narrow bus, the target priorities run 7 -> 0. On a wide bus, they run 7 -> 0, then 15 -> 8. The host adapter is usually 7. This can cause problems where busy disks and tape devices share a SCSI bus, since tape devices are usually assigned target 6.

Saturday, April 06, 2013

Book Review: The Practice of System and Network Administration

System Administration as a Profession

"The Practice of System and Network Administration" is different from most of the other technical books on a professional SA's bookshelf. This book is about how to become a professional system administrator.

The profession is about more than knowning obscure options to different commands. To become a professional, a system administrator needs to change mindset from a straight-ahead techie to a member of the team who has specialized expertise.

System administration has not always been recognized as a profession. System administrators themselves are partly to blame for that. We have tended to focus strictly on technology and not on how to structure our work to benefit both ourselves and the organizations we work for. Limoncelli, Hogan and Chalup have put togeter a great standard reference for people who are ready to transition to being professional system administrators.

Solaris Kernel Tuning

sysdef -i reports on several system resource limits. Other parameters can be checked on a running system using adb -k :

adb -k /dev/ksyms /dev/mem
parameter-name/D
^D
(to exit)

More information on kernel tuning is available in Sun's online documentation.

maxusers

maxusers is the most frequently tuned kernel parameter. Its original use (as an overall limit to the number of concurrent users on a system) is much less important than its role as a basis for calculating other kernel parameters.

The default value is set to either the number of MB of physical memory or MAX_DEFAULT_MAXUSERS, whichever is lower.

For Solaris 2.5.1-7, MAX_DEFAULT_MAXUSERS is 1024. For Solaris 8-10, MAX_DEFAULT_MAXUSERS is 2048.

maxusers can be set explicitly in the /etc/system file, but is limited to 2x MAX_DEFAULT_MAXUSERS.

Several key kernel parameters are set when maxusers is set unless explicitly overridden in the /etc/system file. Some of these formulas differ between different versions of Solaris:

  • max_nprocs: Number of processes = 10 + (16 x maxusers)
  • ufs_ninode: Inode cache size = (17xmaxusers)+90 (Solaris 2.5.1) or 4x(maxusers + max_nprocs)+320 (Solaris 2.6-8). See the Disk I/O page for more information.
  • ncsize: Name lookup cache size = (17xmaxusers)+90 (Solaris 2.5.1) or 4x(maxusers + max_nprocs)+320 (Solaris 2.6-8). See the Disk I/O page for more information.
  • ndquot: Quota table size = (maxusers x 10) + max_nprocs
  • maxuprc: User process limit = max_nprocs - 5

ptys

Solaris 8+ dynamically sizes the number of ptys available to a system, so you are less likely to run into pty starvation than was the case under Solaris 2.5.1-7. There are still hard system limits that are set based upon hardware configuration, and it may be necessary to increase the number of ptys manually as in Solaris 2.5.1-7.

If the system is suffering from pty starvation, the number of ptys available can be increased by increasing pt_cnt above the default of 48. Solaris 2.5.1 and 2.6 systems should not have pt_cnt set higher than 3844 due to limitations with the telnet and rlogin daemons. Solaris 7 does not have this restriction, but there may be other system issues that prevent setting pt_cnt arbitrarily high. Once pt_cnt is increased, a reconfiguration boot (boot -r) is required to build the ptys.

If pt_cnt is increased, some sources recommend that other variables be set at the same time. Other sources (such as the Solaris2 FAQ) suggest that this advice is spurious and results in a needless consumption of resources. See the notes below before making any of these changes; setting the values too high may result in wasted memory. In any case, one form of these recommendations is:

  • npty: Set to pt_cnt (see the note below)
  • nautopush: Set to twice the value of pt_cnt
  • sadcnt: Set to same value as pt_cnt

npty limits the number of BSD ptys. These are not usually used by applications, but may need to be increased on a system running a special service. In addition to setting npty in the /etc/system file, the /etc/iu.ap file will need to be edited to substitute the value npty-1 in the third field of the ptsl line. After both changes are made, a boot -r is required for the changes to take effect. Note that Solaris does not support any more than 176 BSD ptys in any case.

sadcnt sets the number of STREAMS addressable devices and nautopush sets the number of STREAMS autopush entries. nautopush should be set to twice sadcnt. Whether or not these values need to be increased as above depends on the types of activity on the system.

RAM Tuneables

See the Memory/Swapping page for a discussion of parameters related to RAM and paging.

Disk I/O Tuneables

See the Disk I/O page for a full discussion of disk I/O-related tuneables.

IPC Tuneables

Check the IPC Tuning page for InterProcess Communication-related resource parameters.

File Descriptors

See the File Descriptors page for more discussion regarding tuning issues.

File descriptors are retired when the file is closed or the process terminates. Opens always choose the lowest-numbered file descriptor available. Available file descriptors are allocated as follows:

  • rlim_fd_cur: If you are running old code, it is dangerous to set this value higher than 256 due to limitations with the stdio library. If programs require more file descriptors, they should use setrlimit directly.
  • rlim_fd_max: If you are running old code, it is dangerous to set this value higher than 1024 due to limitations with select(). If programs require more file descriptors, they should use setrlimit directly.

(The cautionary notes on both of these items become less important as applications are re-written to use poll() rather than select(), or are developed as native 64-bit applications. Any changes should be tested in a non-production environment before deployment. The Solaris2 FAQ includes a discussion of this issue.)

Misc Tuneables

  • dump_cnt: Size of dumps.
  • rstchown: Posix/restricted chown enabled (default=1)
  • ngroups_max: Maximum number of supplementary groups per user (default=32).

Friday, April 05, 2013

IPC Issues

Most of the InterProcess Communication parameters are reported by sysdef -i . Other parameters can be checked on a running system using adb -k :
adb -k /dev/ksyms /dev/mem
parameter-name/D
^D
(to exit)

In Solaris 10, control of the shared memory, semaphore and message queue parameters have been shifted to project-based resource controls. (See the project, prctl and getrctl man pages for detailed information.)

Many of the maximum parameter values discussed below represent 32-bit limits on integer size for Solaris 2.6 and 2.5.1. In Solaris 7+, these limits have been lifted somewhat. In theory, the maximums for Solaris 7+ would be in the 16 EB (exabytes) range rather than 2 GB (for Solaris 2.6 and 2.5.1). In practice, implementation details limit the range to something like 16 TB (terabytes). Due to the memory used by the kernel to set up space for the structures governed by these parameters, it is important to think about the useage of the resource before tuning it. In most cases, the 32-bit limits provide more than adequate head room for growth.

Shared memory, semaphores and message queues are only enabled if the appropriate kernel modules are loaded. These are automatically loaded if certain IPC functions are called, but they can also be forced to load via /etc/system forceload commands or root modload commands.

Each of these three facilities runs on top of the /kernel/misc/ipc module. Shared memory connects to the ipc module via /kernel/sys/shmsys, semaphores connect via /kernel/sys/semsys and message queues connect via /kernel/sys/msgsys.

For Solaris 2.5.1-9, the module names will need to be included when setting these parameters in the /etc/system file. For example:
set shmsys:parameter=value

Solaris 10 sets the parameters for these facilities via the project interface.

Other IPC mechanisms exist (such as named pipes), but they are not tuneable in the sense of this discussion.

Each IPC resource has at least these attributes: key (identifies this instance of the resource), creator (UID/GID of the creating process), owner (UID/GID of the resource owner), and permissions (similar to filesystem read/write/execute owner/group/other permissions).

Each object is created by calling the appropriate *get function ( shmget / semget / msgget ) with the desired key. If no objects of that type with that key exist, it is created and a resource ID is passed back to the caller.

Once created, the IPC objects can be controlled with the appropriate *ctl function ( shmctl / semctl / msgctl ).

The ipcs command presents information on IPC services that are currently loaded. It presents a "facility not in system" message if a given module has not been loaded yet.

Shared Memory

Shared memory provides the fastest way for processes to pass large amounts of data to one another. As the name implies, shared memory refers to physical pages of memory that are shared by more than one process.

Of particular interest is the "Intimate Shared Memory" facility, where the translation tables are shared as well as the memory. This enhances the effectiveness of the TLB (Translation Lookaside Buffer), which is a CPU-based cache of translation table information. Since the same information is used for several processes, available buffer space can be used much more efficiently. In addition, ISM-designated memory cannot be paged out, which can be used to keep frequently-used data and binaries in memory.

Database applications are the heaviest users of shared memory. Vendor recommendations should be consulted when tuning the shared memory parameters.

Solaris 10 only uses the shmmax and shmmni parameters. (Other parameters are set dynamically within the Solaris 10 IPC model.)

  • shmmax (max-shm-memory in Solaris 10+): This is the maximum size of a shared memory segment (ie the largest value that can be used by shmget). Its theoretical maximum value is 4294967295 (4GB), but practical considerations usually limit it to less than this. There is no reason not to tune this value as high as possible, since no kernel resources are allocated based on this parameter. Solaris 10 sets shmmax to 1/4 physical memory by default, vs 512k for previous versions.
  • shmmin: This is the smallest possible shared memory segment size. The default is 1 byte; this parameter should probably not be tuned.
  • shmmni (max-shm-ids in Solaris 10+): Maximum number of shared memory identifiers at any given time. This parameter is used by kernel memory allocation to determine how much size to put aside for shmid_ds structures. Each of these is 112 bytes and requires an additional 8 bytes for a mutex lock; if it is set too high, memory useage can be a problem. The maximum setting for this variable in Solaris 2.5.1 and 2.6 is 2147483648 (2GB), and the default is 100. For Solaris 10, the default is 128 and the maximum is MAXINT.
  • shmseg: Maximum number of segments per process. It is usually set to shmmni, but it should always be less than 65535. Sun documentations suggests a maximum for this parameter of 32767 and a default of 8 for Solaris 2.5.1 and 2.6.

Semaphores

Semaphores are a shareable resource that take on a non-negative integer value. They are manipulted by the P (wait) and V (signal) functions, which decrement and increment the semaphore, respectively. When a process needs a resource, a "wait" is issued and the semaphore is decremented. When the semaphore contains a value of zero, the resources are not available and the calling process spins or blocks (as appropriate) until resources are available. When a process releases a resource controlled by a semaphore, it increments the semaphore and the waiting processes are notified.

Solaris 10 only uses the semmni, semmsl and semopm parameters. (Other parameters are dynamic within the Solaris 10 IPC model.)

  • semmap: This sets the number of entries in the semaphore map. This should never be greater than semmni. If the number of semaphores per semaphore set used by the application is "n" then set
    semmap = ((semmni + n - 1)/n)+1
    or more. Alternatively, we can set semmap to semmni x semmsl. An undersized semmap leads to "WARNING: rmfree map overflow" errors. The default setting is 10; the maximum for Solaris 2.6 is 2GB. The default for Solaris 9 was 25; Solaris 10 increased the default to 512. The limit is SHRT_MAX.
  • semmni (max-sem-ids in Solaris 10+): Maximum number of systemwide semaphore sets. Each control structure consumes 84 bytes. For Solaris 2.5.1-9, the default setting is 10; for Solaris 10, the default setting is 128. The maximum is 65535
  • semmns: Maximum number of semaphores in the system. Each structure uses 16 bytes. This parameter should be set to semmni x semmsl. The default is 60; the maximum is 2GB.
  • semmnu: Maximum number of undo structures in the system. This should be set to semmni so that each control structure has an undo structure. The default is 30, the maximum is 2 GB.
  • semmsl (max-sem-nsems in Solaris 10+): Maximum number of semaphores per semaphore set. The default is 25, the maximum is 65535.
  • semopm (max-sem-ops in Solaris 10+): Maximum number of semaphore operations that can be performed in each semop call. The default in Solaris 2.5.1-9 is 10, the maximum is 2 GB. Solaris 10 increased the default to 512.
  • semume: Maximum number of undo structures per process. This should be set to semopm times the number of processes that will be using semaphores at any one time. The default is 10; the maximum is 2 GB.
  • semusz: Number of bytes required for semume undo structures. This should not be tuned; it is set to semume x (1 + sizeof(undo)). The default is 96; the maximum is 2 GB.
  • semvmx: Maximum value of a semaphore. This should never exceed 32767 (default value) unless SEM_UNDO is never used. The default is 32767; the maximum is 65535.
  • semaem: Maximum adjust-on-exit value. This should almost always be left alone. The default is 16384; the maximum is 32767.

Message Queues

Unix uses message queues for asynchronous message passing between processes. Each message has a type field, which can be used for priority messaging or directing a message to a chosen recipient.

Message queues are implemented as FIFO (first-in first-out) mechanisms. They consist of a header pointing to a linked list.

Solaris 2.5.1 and before used very coarse-grained mutex locking for message queues, which resulted in uneccessary contention as compared to 2.6 and later versions.

Solaris 10 only uses the msgmni, msgmnb and msgtql parameters. (Other parameters are dynamic within the Solaris 10 IPC model.)

  • msgmap: Number of entries in the msg map. The default is 100, the maximum is 2 GB.
  • msgmax: Maximum size of a message. The default is 2048; the maximum is 2 GB. Shared memory should be considered for moving large messages between processes; it is much more efficient for large data transfers.
  • msgmnb (max-msg-qbytes in Solaris 10+): Maximum number of bytes for the message queue. Te default is 4096; the maximum is 2 GB. The default in Solaris 10 was increased to 65536 and the maximum increased to ULONG_MAX.
  • msgmni (max-msg-ids in Solaris 10+): Number of unique message queue identifiers. The default is 50; the maximum is 2 GB. The default in Solaris 10 has been increased to 128. This should be set to 10% above the sum of the recommendations for applications on the system. Kernel resources are allocated based upon this parameter, so it should not be sized arbitrarily large.
  • msgssz: Message segment size. The default is 8; the maximum is 2 GB.
  • msgtql (max-msg-messages in Solaris 10+): Number of message headers. The default is 40; the maximum is 2 GB. Solaris 10 increased the default to 8192 and the maximum to UINT_MAX
  • msgseg: Number of message segments. The default is 1024; the maximum is 32 KB.

Solaris 10+ IPC Resource Management

The Solaris 10 IPC resource management framework was designed to overcome several shortcomings of the older SVR4-based system. Several parameters were converted to be dynamically resized, the defaults were increased, the names were changed to be more human-readable, the resource limits were system-wide (permitting potential conflicts) and reboots were required for even minor changes.

The Solaris 10 system allows changes to be associated with a project and monitored via prctl.

Additional information about Solaris 10+ resource management can be found on the Resource Management web page or in Sun's System Administration Guide: Solaris Containers-Resource Management and Solaris Zones on the Sun Documentation Web Site.

For the purposes of IPC resource management, the following are the important parameters:

  • project.max-shm-ids: Maximum shared memory IDs for a project. Replaces shmmni
  • project.max-sem-ids: Maximum semaphore IDs for a project. Replaces semmni
  • project.max-msg-ids: Maximum message queue IDs for a project. Replaces msgmni
  • project.max-shm-memory: Total amount of shared memory allowed for a project. Replaces shmmax
  • process.max-sem-nsems: Maximum number of semaphores allowed per semaphore set. Replaces semmsl
  • process.max-sem-ops: Maximum number of semaphore operations allowed per semop. Replaces semopm
  • process.max-msg-qbytes: Maximum number of bytes of messages on a message queue. Replaces msgmnb
  • process.max-msg-messages: Maximum number of messages on a message queue. Replaces msgtql

Thursday, April 04, 2013

Component Parts of Disk I/O

What we blithely call a "Disk I/O" is actually made up of several components, each of which may have an impact on overall performance. These layers may be broken down as follows for a typical I/O operation:

  • POSIX: Application calls a POSIX library interface. (These frequently map directly to system calls, except for the asynchronous interfaces. These latter work via pread and pwrite.)
  • System Call: The relevant node and vfs system calls are:
    vnode system calls:
    • close()
    • creat()
    • fsync()
    • ioctl()
    • link()
    • mkdir()
    • open()
    • read()
    • rename()
    • rmdir()
    • seek()
    • unlink()
    • write()
    vfs system calls:
    • mount()
    • statfs()
    • sync()
    • umount()
  • VOP: The vnode operations interface is the architectural layer between the system calls and the filesystems. DTrace provides the best way to examine this layer. Starting in version 0.96, the DTrace Toolkit's vopstat command allows direct monitoring at this level.
  • Filesystems: There is some discussion of filesystem tuning and filesystem caching at the bottom of this page. Further information on troubleshooting a particular filesystem is contained in each filesystem's web page. (This site contains pages for NFS, UFS and ZFS filesystems.)
  • Physical Disk I/O: This is the portion of the I/O that involves the transfer of data to or from the physical hardware. Traditionally, I/O troubleshooting focuses on this portion of the I/O process.

McDougall, Mauro and Gregg suggest that the best way to see if I/O is a problem at all is to look at the amount of time spent on library and system calls via DTrace.

For example, the DTrace Toolkit's procsystime utility tracks time spent on each system call. Similarly, the dtruss -t syscall -p PID command can examine the time spent on a particular system call for a process. The truss -D -p PID command also reveals the time spent by a process in I/O system calls, but it imposes a severe performance penalty.

If the system call statistics reveal a problem, we should look at the raw disk I/O performance.

Physical Disk I/O

The primary tool to use in troubleshooting disk I/O problems is iostat. sar -d provides useful historical context. vmstat can provide information about disk saturation. For Solaris 10 systems, dtrace can provide extremely fine-grained information about I/O performance and what is causing any utilization or saturation problems. The DTrace Toolkit provides a number of ready-to-use scripts to take advantage of DTrace's capabilities.

To start, use iostat -xn 30 during busy times to look at the I/O characteristics of your devices. Ignore the first bunch of output (the first group of output is summary statistics), and look at the output every 30 seconds. If you are seeing svc_t (service time) values of more than 20 ms on disks that are in use (more than, say, 10% busy), then the end user will see noticeably sluggish performance.

(With modern disk arrays that contain significant amounts of cache, it may be more useful to compare to service times during periods when no performance problems are experienced. If the reads and writes are largely hitting the cache on a fiber-attached disk array, average service times in the 3-5 ms range can be achieved. If you are seeing a large increase in service time during the problem periods, you may need to look at your disk array's monitoring features to identify whether or not more disk array cache would be useful. The most useful measurements to be used with modern disk arrays are the throughput measurements, since large up-front caches mask any other issues.)

Disk Utilization

If a disk is more than 60% busy over sustained periods of time, this can indicate overuse of that resource. The %b iostat statistic provides a reasonable measure for utilization of regular disk resources. (The same statistic can be viewed via iostat -D in Solaris 10.)

Utilization may not take into account the usage pattern, the fact that disk array utilization numbers are almost impossible to interpret correctly, or whether application effects are adequately handled by I/O caching. The service times are the key to seeing whether a high utilization is actually causing a problem.

The DTrace Toolkit provides a way to directly measure disk utilization via the iotop -CP command. This command shows UIDs, process IDs and device names, which can help identify a culprit. (The -C option provides a rolling output rather than having it clear at each time step. The -P option shows the %I/O utilization.)

Disk Saturation

A high disk saturation (as measured via iostat's %w) always causes some level of performance impact, since I/Os are forced to queue up. Even if the disk is not saturated now, it is useful to look at throughput numbers and compare them to the expected maximums to make sure that there is adequate head room for unusually high activity. (We can measure the maximum directly by doing something like a dd or mkfile and looking at the reported throughput.)

If iostat consistently reports %w > 5, the disk subsystem is too busy. In this case, one thing that can be done is to reduce the size of the wait queue by setting sd_max_throttle to 64. (The sd_max_throttle parameter determines how many jobs can be queued up on a single HBA, and is set to 256 by default. If the sd_max_throttle threshhold is exceeded, it will result in a transport failure error message.)

Reducing sd_max_throttle is a temporary quick fix. Its primary effect is to keep things from getting quite so backed up and spiraling out of control. One of the permanent remedies below needs to be implemented.

Another possible cause for a persistently high %w is SCSI starvation, where low SCSI ID devices receive a lower precedence than a higher-numbered device (such as a tape drive). (See the System Bus/SCSI page for more information.)

Another indication of a saturated disk I/O subsystem is when the procs/b section of vmstat persistently reports a number of blocked processes that is comparable to the run queue (procs|kthr/r). (The run queue is roughly comparable to the load average.)

The DTrace Toolkit's iotop -o 10 command shows disk I/O time summaries. Each process's UID, process ID and device names are shown, along with the number of nanoseconds of disk time spent. This can help us to identify the heavy hitters on a saturated disk.

Usage Pattern

It is useful to know whether our I/O is predominantly random or sequential. Sequential I/O is typical of large file reads and writes, and typically involves operating on one block immediately after its neighbor. With this type of I/O, there is little penalty associated with the disk drive head having to move to a new location. Random I/O, on the other hand, involves large numbers of seeks and rotations, and is usually much slower.

Disk I/O can be investigated to find out whether it is primarily random or sequential. If sar -d reports that (blks/s)/(r+w/s) < 16Kb (~32 blocks), the I/O is predominantly random. If the ratio is > 128Kb (~256 blocks), it is predominantly sequential. This analysis may be useful when examining alternative disk configurations.

The DTrace Toolkit provides us a way to directly measure seek times using the seeksize.d script. This script is a direct measurement of disk usage patterns. If there are large numbers of large seeks, it indicates that our physical drives are spending a lot of time moving heads around rather than reading or writing data.

To identify the culprit, the DTrace Toolkit contains a script called bitesize.d, which provides a graph of I/O sizes carried out by each process. If there are a large number of small I/Os, the pattern is predominantly random. If there are mostly large I/Os, the process is exhibiting sequential behavior.

DTrace also provides a way to track which files are accessed how often. The args2->fi_pathname value from the io provider gives us a handle into this. For example, we could use a one-liner like:

dtrace -n 'io:::start { printf("%6s %-12s %6s", pid, execname args[2]->fi_pathname); } '
to provide raw data for further processing, or we could use an aggregation to collect statistics. The DTrace Toolkit's iosnoop program provides a flexible way to collect this sort of information. (The -h option provides usage notes on how to use it.)

Disk Errors

iostat -eE reports on disk error counts since the last reboot. Keep in mind that several types of events (such as ejecting a CD or some volume manager operations) are counted in this output. Once these error messages rise above 10 in any category, further investigation is warranted.

Restructuring I/O

The usual solutions to a disk I/O problem are:

  • Check filesystem kernel tuning parameters to make sure that DNLC and inode caches are working appropriately. (See "Filesystem Caching" below.)
  • Spread out the I/O traffic across more disks. This can be done in hardware if the I/O subsystem includes a RAID controller, or in software by striping the filesystem (using Solaris Volume Management/DiskSuite, Veritas Volume Manager or ZFS), by splitting up the data across additional filesystems on other disks, or even splitting the data across other servers. (In extreme cases, you can even consider striping data over only the outermost cylinders of several otherwise empty disk drives in order to maximize throughput.) Cockroft recommends 128KB as a good stripe width for most applications. In an ideal world, the stripe width would be an integer divisor of the average I/O size to split the traffic over all disks in the stripe.
  • Redesign the problematic process to reduce the number of disk I/Os. (Caching is one frequently-used strategy, either via cachefs or application-specific caching.)
  • The write throttle can be adjusted to provide better performance if there are large amounts of sequential write activity. The parameters in question are ufs:ufs_HW and ufs:ufs_LW. These are very sensitive and should not be adjusted too far at one time. When ufs_WRITES is set to 1 (default), the write throttle is enabled. When the number of outstanding writes exceeds ufs_HW, writes are suspended until the number of outstanding writes drops below ufs_LW. Both can be increased where large amounts of sequential writes are occurring.
  • tune_t_fsflushr sets the number of seconds after which fsflush will run autoup dictates how frequently each bit of memory is checked. Setting fsflush to run less frequently can also reduce disk activity, but it does run the risk of losing data that has been written to memory. These parameters can be adjusted using adb while looking for an optimum value, then set the values in the /etc/system file.
  • Check for SCSI starvation, i.e., for busy high-numbered SCSI devices (such as tape drives) that have a higher priority than lower-numbered devices.
  • Database I/O should be done to raw disk partitions or direct unbuffered I/O.
  • In some cases, it may be worthwhile to move frequently-accessed data to the outer edge of a hard drive. In the outer cylinders, the read and write rates are higher.
  • It may be worthwhile to match observed and configured I/O sizes by tuning maxphys and maxcontig.

Filesystem Performance

Physical disk I/O is usually the focus of I/O troubleshooting sessions. McDougall, Mauro and Gregg suggest that it is more appropriate to focus on overall service times of I/O related system calls. (As noted above, the DTrace Toolkit's procsystime utility tracks time spent on each system call, and the dtruss -t syscall -p PID command can examine the time spent on a particular system call for a process. The pfilestat utility in the newer versions of the Toolkit also gives an indication of how much time a process spends on different I/O-related system calls.)

This approach allows end-to-end monitoring of the important portions of the I/O process. The traditional approach ignores performance problems introduced by the filesystem itself.

Filesystem latency may come from any of the following:

  • Disk I/O wait: This may be as short as zero, in the event of a read cache hit. For a synchronous I/O event, this can be reduced by restructuring disk storage or by altering caching parameters. Disk I/O wait can be monitored directly through dtrace, including through the iowait.d script.
  • Filesystem cache misses: These include block, buffer, metadata and name lookup caches. These may be adjustable by increasing the size of the relevant caches.
  • I/Os being broken into multiple pieces, incurring the penalty of addtional operations. This may be a result of the maximum cluster size for the filesystem or the OS.
  • Filesystem locking: Most filesystems have per-file reader/writer locks. This can be most significant when there is a large file (like a database file) where reads have to wait for writes to a different portion of the file. Direct I/O is a mechanism for bypassing this limitation.
  • Metadata updating: Creations, renames, deletions and some file extensions cause some extra latency to allow for updates to filesystem metadata.

The DTrace Toolkit's vopstat command allows monitoring of the number and duration of operations at the VOP level. (VOP is the architectural layer between the system calls and the filesystems, so it is at a high enough level to provide interesting information.)

Filesystem Caching

There are several types of cache used by the Solaris filesystems to cache name and attribute lookups. These are:

  • DNLC (Directory Name Lookup Cache): This cache stores vnode to path directory lookup information, preventing the need to perform directory lookups on the fly. (Solaris 7 and higher have removed a previous file path length restriction.)
  • inode cache: This cache stores logical metadata information about files (size, access time, etc). It is a linked list that stores the inodes and pointers to all pages that are part of that file and are currently in memory. The inode cache is dedicated for use by UFS.
  • rnode cache: This is maintained on NFS clients to store information about NFS-mounted nodes. In addition, an NFS attribute cache stores logical metadata information.
  • buffer cache: The buffer cache stores inode, indirect block and cylinder group-related disk I/O. This references the physical metadata (eg block placement in the filesystem), as opposed to the logical metadata that is stored in other caches.

(Note that cache statistics will be skewed by things that walk the directory tree like find.)

The block cache provides performance enhancement by using otherwise idle memory in the page cache to keep copies of recently requested information. Cache hits in the block cache obviously have a huge performance advantage.

ZFS uses an adaptive replacement cache (ARC) rather than using the page cache fo file data (like most other filesystems do).

Directory Name Lookup Cache

The DNLC stores directory vnode/path translation information. (Starting with Solaris 7, a previous path length restriction of 30 characters was lifted.)

sar -a reports on the activity of this cache. In this output, namei/s reports the name lookup rate and iget/s reports the number of directory lookups per second. Note that an iget is issued for each component of a file's path, so the hit rate cannot be calculated directly from the sar -a output. The sar -a output is useful, however, when looking at cache efficiency in a more holistic sense.

For our purposes, the most important number is the total name lookups line in the vmstat -s output, or the dir_hits and dir_misses statistics in kstat -n dnlcstats. If the cache hit percentage is not above 90%, the DNLC should be resized. (Unless the activity is such that we would not expect a good hit ratio, such as large numbers of file creations.)

DNLC size is determined by the ncsize kernel parameter. By default, this is set to (17xmaxusers)+90 (Solaris 2.5.1) or 4x(maxusers + max_nprocs)+320 (Solaris 2.6-10). It is not recommended that it be set any higher than a value which corresponds to a maxusers value of 2048 for Solaris 2.5.1-7 or 4096 for Solaris 8-10. This can be viewed via mdb -k by querying ncsize/D

To set ncsize, add a line to the /etc/system as follows:
set ncsize=10000

The DNLC can be disabled by setting ncsize to a negative number (Solaris 2.5.1-7) or a non-positive number (Solaris 8-10).

Inode Cache

The inode cache is a linked list that stores the inodes that have been accessed along with pointers to all pages that are part of that file and are currently in memory.

sar -g reports %ufs_ipg, which is the percentage of inodes that were overwritten while still having active pages in memory. If this number is consistently nonzero, the inode cache should be increased. By default, this number (ufs_ninode) is set to the same value as ncsize, unless otherwise specified in the /etc/system file. As with ncsize, it is not recommended that ufs_ninode be set any higher than a value which corresponds to a ncsize for a maxusers value of 2048 for Solaris 2.5.1-7 or 4096 for Solaris 8-10.

The vmstat -s command also contains summary information about the inode cache in the inode_cache section. Among other things, this section includes sizing and hit rate information.

(The inode cache can grow beyond the ufs_ninode limit. When this happens, unused inodes will be flushed from the linked list.)

netstat -k (up through Solaris9) or kstat -n ufs_inode_cache (after Solaris 8) also report on inode cache statistics.

While resizing the inode cache, it is important to remember that each inode will use about 300 bytes of kernel memory. Check your kernel memory size (perhaps with sar -k) when resizing the cache. Since ufs_ninode is just a limit, it can be resized on the fly with adb.

Rnode Cache

The information in the rnode cache is similar to that from the inode cache, except that it is maintained for NFS-mounted files. The default rnode cache size is 2xncsize, which is usually sufficient. Rnode cache statistics can be examined in the rnode_cache section of netstat -k or via the kstat command.

Buffer Cache

The buffer cache is used to store inode, indirect block and cylinder group-related disk I/O. The hit rate on this cache can be discovered by examining the biostat section of the output from netstat -k and comparing the buffer cache hits to the buffer cache lookups. This cache acts as a buffer between the inode cache and the physical disk devices.

Sun suggests tuning bufhwm in the /etc/system file if sar -b reports less than 90% hit rate on reads or 65% on writes.

Cockroft notes that performance problems can result from allowing the buffer cache to grow too large, resulting in kernel memory allocation starvation. The default setting for bufhwm allows the buffer to consume up to 2% of system memory, which may be excessive. The buffer cache can probably be limited to 8MB safely by setting bufhwm in the /etc/system file:
set bufhwm=8000

Obviously, the effects of such a change should be examined by checking the buffer cache hit rate sar -b.

Page Cache

The virtual memory on ultrasparc systems is carved into 8KB chunks known as "pages." When a file is read,it is first loaded into memory, a process known as "paging in." These are recorded in the virtual memory statistics, such as the pi column in vmstat.

Items that are paged into memory are cached there for a time. Since the same files are frequently accessed repeatedly, this caching can dramatically improve I/O performance. We would expect the size of the page cache from read and write operations to be limited by segmap_percent, which has a default of 12% of physical memory.

The page scanner's job is to free up memory caching items that have not been accessed recently. Pages are made available by placing them on the free list.

The size of the page cache and its components can be viewed by running mdb -k and using the ::memstat dcmd. The performance of the cache can be viewed with utilities available in the DTrace Toolkit; the rfileio and rfsio utilities provide cache hit rates.

The page cache is bypassed by using direct I/O.

Physical Disk Layout

The disk layout for a hard drive includes the following:

  • bootblock
  • superblock: Superblock contents can be reported via the fstyp -v /dev/dsk/* command.
  • inode list: The number of inodes for a filesystem is calculated based upon a presumption of an average file size of ~2 KB. If this is not a good assumption, the number of inodes can be set via the newfs -i or mkfs command.
  • data blocks

Inodes

Each inode contains the following information:
  • file type, permissions, etc
  • number of hard links to the file
  • UID
  • GID
  • byte size
  • array of block addresses:
    The first several block addresses are used for data storage. Other block addresses store indirect blocks, which point at arrays containing pointers to further data blocks. Each inode contains 12 direct block pointers and 3 indirect block pointers.
  • generation number (incremented each time the inode is re-used)
  • access time
  • modification time
  • change time
  • Number of sectors: This is kept to allow support for holey files, and can be reported via ls -s
  • Shadow inode location: This is used for ACLs (access control lists).

Using the indirection provided in the array of block addresses, files can be created that contain holes, or large sets of null-filled bytes.

Physical I/O

Disk I/Os include the following components:
  • I/O bus access: If the bus is busy, the request is queued by the driver. The information is reported by sar -d wait and %w and iostat -x avwait.
  • Bus transfer time: Arbitration time (which device gets to use the bus--see the System Bus/SCSI page), time to transfer the command (usually ~ 1.5 ms), data transfer time (in the case of a write).
  • Seek time: Time for the head to move to the proper cylinder. Average seek times are reported by hard drive manufacturers. Usage patterns and the layout of data on the disks will determine the number of seeks that are required.
  • Rotation time: Time for the correct sector to rotate under the head. This is usually calculated as 1/2 the time for a disk rotation. Rotation speeds (in RPM) are reported by hard drive manufacturers.
  • ITR time: Internal Throughput Rate. This is the amount of time required for a transfer between the hard drive's cache and the device media. The ITR time is the limiting factor for sequential I/O, and is reported by the hard drive manufacturer.
  • Reconnection time: After the data has been moved to/from the hard drive's internal cache, a connection with the host adapter must be completed. This is similar to the arbitration/ command transfer time discussed above.
  • Interrupt time: Time for the completion interrupt to be processed. This is very hard to measure, but high interrupt rates on the CPUs associated with this system board may be an indication of problems.

The disk's ITR rating and internal cache size can be critical when tuning maxcontig (maximum contiguous I/O size). Note: maxphys and maxcontig must be tuned at the same time. The unit of measurement for maxphys is bytes; maxcontig is in blocks.

maxcontig can be changed via the mkfs, newfs or tunefs commands.

By default, maxphys is set to 128KB for Sparc and 56KB for x86 systems. maxcontig should be set to the same size (but in blocks). We would tune these smaller for random I/O and larger for sequential I/O.

Direct I/O

Large sequential I/O can cause performance problems due to excessive use of the memory page cache. One way to avoid this problem is to use direct I/O on filesystems where large sequential I/Os are common.

Direct I/O is a mechanism for bypassing the memory page cache alltogether. It is enforced by the directio() function or by the forcedirectio option to mount.

VxFS enables direct I/O for large sequential operations. It determines which operations are "large" by comparing them to the vxtunefs parameter discovered_direct_iosz (default 256KB).

One problem that can emerge is that if large sequential I/Os are handed to VxFS as several smaller operations, caching will still occur. This problem can be alleviated by reducing discovered_direct_iosz to a level that prevents caching of the smaller operations. In particular, this can be a problem in OLTP environments.

Additional Resources

Wednesday, April 03, 2013

CPU Loading

Intuitively, the load average is an average over time of the number of processes in the run queue. uptime reports load averages over 1-, 5- and 15-minute intervals. Typically, load averages are divided by the number of CPU cores to find the load per CPU. Load averages above 1 per CPU indicate that the CPUs are fully utilized. Depending on the type of load and the I/O requirements, user-visible performance may not be affected until levels of 2 per CPU are reached. A general rule of thumb is that load averages that are persistently above 4 times the number of CPUs will result in sluggish performance.

Prior to Solaris 10, the calculation algorithm directly computed the load average by periodically sampling the length of the run queue. Since this measurement can be skewed by threads that enter and exit more quickly than the sampling interval, Solaris 10 altered the algorithm to use microstate accounting instead.

Solaris 10 applies an exponential decay algorithm to a combination of high-resolution usr, sys and thread wait times. The numbers are comparable to a traditional load average.

The load averages can be monitored intermittently via uptime or over extended time periods by looking at run queue lengths and the amount of time that the run queue is occupied via sar -q.

One issue to watch for is the number of processes that are blocked while waiting for I/O. Check the disk I/O page for information on monitoring this.

Solaris 10 allows us to directly monitor the amount of time threads wait for a processor via the prstat -mL command in the LAT category.

For non-NFS servers, another danger sign is when the system consistently spends more time in sys than usr mode. (nfsd operates in the kernel in sys mode.) MacDougall and Mauro comment that a typical usr/sys ratio is in the neighborhood of 70/30 on a reasonably loaded system.

Another issue to watch for is a high number of system calls per second per processor. With today's faster CPUs, 20,000 would represent a reasonable threshold. This can be monitored via sar -c. In particular, the large numbers of forks or execs may represent excessive context switching. (Slower processors will be able to handle fewer system calls per second.) Context switching is monitored by vmstat or mpstat.

Tuesday, April 02, 2013

Watchdog Reset Diagnostics

A watchdog reset occurs when a fault condition occurs that the system deems as potentially dangerous. When such a fault occurs, the system immediately drops to the PROM monitor without taking a core dump. If the watchdog-reboot? parameter is set to true, the system will reboot. No further diagnostics will be possible, unless an error message appears either in the system logs (from immediately before the watchdog reset was executed) or on the console (during hardware diagnostics during the reboot).

If the watchdog-reboot? parameter is set to false, some limited diagnostics are available that may point to a culprit in the reset.

Further complicating the issue, watchdog resets may be caused by hardware or software problems. A software-triggered watchdog reset occurs when two trap errors take place so close together that the first one does not have time to complete before the second one is received by the system. This type of watchdog reset is sometimes called a "CPU" watchdog reset, since it occurs when the CPU receives a trap while the register bit to receive traps is not set.

Since hardware faults may cause traps, a CPU watchdog reset may be caused by either hardware or software failures.

A second type of watchdog reset is a "system" watchdog reset. These are almost always caused by a hardware fault.

If the system is still at the PROM monitor prompt following the watchdog reset, it is possible to execute the following commands to attempt to gather some information about the system state prior to the reset. If at all possible, the system should be observed through some sort of console or tip session that can be used to preserve the output of the PROM monitor session.

Post-Reset Diagnostics

.registers: Displays kernel internal registers.
.locals: Displays the registers in the current register window.
.psr: Displays the Processor Status Register.
f8002010 wector p: (Note: That word is not vector.) This displays messages similar to those in dmesg . They represent any final messages that may have occurred before the reset. See the Sun web site for more information on Watchdog Reset . Note that we have not had much success with this command, but it is recommended by Sun, and hope does spring eternal...
ctrace: Displays the trace of the current thread.

Additional debugging information can be made available to the ctrace command via a module called obpsym. This can be loaded in one of two ways:

  1. modload /platform/sun4x/kernel/misc/obpsym (where x is m, u or d, depending on the system architecture) from the root command line. This method loads the module for this boot only.
  2. forceload: misc/obpsym in the /etc/system file. This method loads the module during future reboots.

Sun recommends using both methods so that the obpsym module is reloaded on each reboot until the problem is diagnosed and resolved.

Once the PROM monitor diagnostics have been run, use sync at the ok> prompt to generate a core dump. This can be analyzed using the suggestions from the Crash Dump Analysis page. If a core is not saved, check the Savecore Troubleshooting page.

Watchdog resets are often caused by a hardware failure, usually requiring a system board or CPU replacement. Less frequently, memory replacements have cleared up the problem. Shortening the SCSI bus sometimes will eliminate the watchdog resets. Any hardware that can send a trap is potentially responsible for a watchdog reset.

Hardware faults may leave traces in log or console error messages. In particular, check for the following:

  • Asynchronous memory error: Indicates a memory problem.
  • Asynchronous memory fault: May be a bus problem between memory and CPU. Try replacing the system board first, then the CPU, then the memory.
  • Ecache parity error: Indicates a problem with the CPU's onboard cache. Replace the CPU.

Monday, April 01, 2013

Root Cause Analysis

Sometimes we end up "fixing" the same problem over and over. Root Cause Analysis helps us make sure that we have actually resolved the root cause of the problem.

5 Whys

For most problems, we can get to the root cause by drilling into proposed explanations by repeatedly asking "Why?" The 5 Whys method was developed by the Toyota Motor Corporation. It is based on the observation that five iterations of asking "Why?" is usually enough to get to the root cause of most real world problems.

For example:
Problem Statement: The system crashed. (Why?)
A memory chip failed. (Why?)
The machine room temperature exceeds recommendations. (Why?)
The HVAC unit is undersized given our heat load. (Why?)
Our projections for heat load were lower than what has been observed. (Why?)
We did the heat load projections ourselves rather than bringing in a qualified expert.

Some disadvantages of the 5 Whys method are:

  • The results are not repeatable. We may well end up with different results depending on who runs the exercise. For example, what if we had answered the second "why" with some other plausible explanation?
  • We are limited to the participants' knowledge of the system. In particular, we aren't going to find any answers that the participants don't already suspect.
  • We may not ask "why?" about the right symptoms of the problem.
  • We may stop short and not proceed to the actual root cause of the problem. For example, people may stop at the point about the HVAC unit being undersized, run the estimates themselves, and promptly purchase a larger (but still undersized) unit.

Current Reality Tree

The CRT's primary components are boxes describing symptoms and arrows representing relationships between them. Symptoms are divided into Undesirable Effects (UDE) and Neutral Effects (NE). This allows us to recognize the effects of things in our environment that are not viewed as undesirable, but which may contribute to a UDE.

Arrows may flow in both directions if necessary. In particular, this allows us to identify a negative feedback loop.

Two or more symptoms may have their arrows combined with an ellipse. This means that the combination of those symptoms is sufficient to provoke the following UDE, but that all of them are required.

To build a CRT, we ask a Key Question with our Problem Statement. The question will usually be of the form "Why is this happening?" Next, we need to create a list of several Undesirable Effects which are related to the Key Question. Each symptom (UDE or NE) gets a box. Wherever we can say something like "If A, then B," we would draw an arrow from A to B. Where we can say something like "If A is combined with B, then we get C," we would draw arrows from A and B to C, then group the arrows with an ellipse.

At the lowest level of the CRT, we should ask "Why?" and continue to build the tree down until we are at the Root Causes, also known as "Problems." If the lowest level boxes are still just symptoms of an underlying problem, build down as far as possible by asking "Why?" at each stage.

Some cases, like the one diagrammed here, end up with the root cause ending in a conflict between two Neutral Effects.

Evaporating Cloud and Future Reality Diagrams

The Evaporating Cloud refers to Goldratt's method for dealing with conflicts. In particular, Goldratt discusses the Core Conflict Cloud representing the Core Conflict in our CRT.

In an Evaporating Cloud Diagram, the end goal (aka the Systemic Objective) is placed in a box on the left. The two conflicting Prerequisite Conditions are placed in boxes at the right hand side of the drawing, with a lightning bolt arrow between them. The Necessary Conditions for the Systemic Objective are placed in boxes next to their respective conflicting prerequisite conditions.

The Evaporating Cloud Diagram illustrates the age-old conflict between upgrades and system stability. On the one hand, upgrades will increase the system reliability and performance. Neglecting upgrades for too long will eventually result in system problems. On the other hand, changes always carry some risk, so there is a strong desire to avoid the pain of changes, including upgrades.

In this case, we need to recognize the end goal of providing a reliable service. Upgrades need to be performed, but should be performed in a way that allows for adequate planning and testing in order to avoid introducing problems to a working system. This sort of solution "evaporates" the cloud.

We can use this solution to build a Future Reality Tree, which is like a Current Reality Tree, but with our solution injected into the diagram: