<?xml version="1.0"?>
<feed xmlns="http://www.w3.org/2005/Atom" xml:lang="en">
	<id>https:/// /zeptoos/api.php?action=feedcontributions&amp;feedformat=atom&amp;user=Iskra</id>
	<title>ZeptoOS - User contributions [en]</title>
	<link rel="self" type="application/atom+xml" href="https:/// /zeptoos/api.php?action=feedcontributions&amp;feedformat=atom&amp;user=Iskra"/>
	<link rel="alternate" type="text/html" href=" /zeptoos/index.php/Special:Contributions/Iskra"/>
	<updated>2026-06-09T06:05:57Z</updated>
	<subtitle>User contributions</subtitle>
	<generator>MediaWiki 1.35.6</generator>
	<entry>
		<id> /zeptoos/index.php?title=Configuration&amp;diff=628</id>
		<title>Configuration</title>
		<link rel="alternate" type="text/html" href=" /zeptoos/index.php?title=Configuration&amp;diff=628"/>
		<updated>2022-02-25T19:38:47Z</updated>

		<summary type="html">&lt;p&gt;Iskra: /* Downloading */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;[[Introduction]] | [[ZeptoOS_Documentation|Top]] | [[Installation]]&lt;br /&gt;
----&lt;br /&gt;
&lt;br /&gt;
== Downloading ==&lt;br /&gt;
&lt;br /&gt;
* Log on one of the front end nodes of the Blue Gene (a login node or a service node).&lt;br /&gt;
&lt;br /&gt;
* Download the ZeptoOS tarball from the ZeptoOS [https://www.mcs.anl.gov/research/projects/zeptoos/downloads downloads page].&lt;br /&gt;
&lt;br /&gt;
* Extract the sources from the package:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
$ tar xjf ZeptoOS-&amp;lt;version&amp;gt;.tar.bz2&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Configuring ==&lt;br /&gt;
&lt;br /&gt;
Change to the top-level &amp;lt;tt&amp;gt;ZeptoOS-&amp;lt;version&amp;gt;&amp;lt;/tt&amp;gt; directory:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
$ cd ZeptoOS-&amp;lt;version&amp;gt;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
A &amp;lt;tt&amp;gt;configure&amp;lt;/tt&amp;gt; script is provided to set the pathnames to various system directories:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
$ ./configure&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
If invoked without any arguments, it will use the defaults, which should be appropriate if ZeptoOS is configured on a system with a supported BG/P driver version.  The pathnames can be changed with the help of a textual user interface by invoking the script as follows:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
$ ./configure --edit&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This will display the following menu:&lt;br /&gt;
&lt;br /&gt;
[[Image:Configure1.png|border|Main menu]]&lt;br /&gt;
&lt;br /&gt;
Please select the top item (&amp;lt;tt&amp;gt;BG/P DIST_DIR&amp;lt;/tt&amp;gt;).  The screen will change to:&lt;br /&gt;
&lt;br /&gt;
[[Image:Configure2.png|border|DIST_DIR menu]]&lt;br /&gt;
&lt;br /&gt;
The following options are available:&lt;br /&gt;
&lt;br /&gt;
; DRV_DIR&lt;br /&gt;
: The directory with the BG/P driver tree.  The default (&amp;lt;tt&amp;gt;/bgsys/drivers/ppcfloor/&amp;lt;/tt&amp;gt;) is a link pointing to the currently active driver.&lt;br /&gt;
; BGP_CROSS&lt;br /&gt;
: A prefix to the pathnames of the GNU cross-compilers used to build the compute node and I/O node software.&lt;br /&gt;
; BGCNS_H_PATH and BGCNS_H&lt;br /&gt;
: The location of a file needed to rebuild the kernel (these options are temporary and will be removed in the next version).&lt;br /&gt;
; OS_DIR&lt;br /&gt;
: The directory with the supplementary I/O node software used when booting the I/O nodes.  It needs to be set to match the BG/P driver version being used.&lt;br /&gt;
&lt;br /&gt;
The second top-level menu (&amp;lt;tt&amp;gt;Debugging&amp;lt;/tt&amp;gt;) has only one option:&lt;br /&gt;
&lt;br /&gt;
; ADD_DEBUG_TOOLS&lt;br /&gt;
: Check this option to include &amp;lt;tt&amp;gt;gdb&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;strace&amp;lt;/tt&amp;gt; in the compute node ramdisk.  They are not included by default because of their size.&lt;br /&gt;
&lt;br /&gt;
The third top-level menu (&amp;lt;tt&amp;gt;Kernel Profiling&amp;lt;/tt&amp;gt;) is discussed in the [[(K)TAU#Configure ZeptoOS to point to KTAU patch and path|(K)TAU section]]&lt;br /&gt;
&lt;br /&gt;
Select &amp;lt;tt&amp;gt;Exit&amp;lt;/tt&amp;gt; (multiple times if needed) and confirm if you want to save any changes made.&lt;br /&gt;
&lt;br /&gt;
== Building ==&lt;br /&gt;
&lt;br /&gt;
To start using the pre-built binaries simply type:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
$ make&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
On the first invocation, this will ask for a root password to use on I/O nodes:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
Create root password for I/O Node&lt;br /&gt;
   Leave the password field empty if you want to disable root login&lt;br /&gt;
   New password:&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
'''Security note: root-level access to I/O nodes should only be given to trusted individuals.  A root user can access and modify files of all users in the system.'''&lt;br /&gt;
&lt;br /&gt;
Once the password has been entered and confirmed, &amp;lt;tt&amp;gt;make&amp;lt;/tt&amp;gt; will use pre-built kernel images, and will build the ramdisks from pre-built tools and utilities.  The following generated files will be placed in the top-level directory:&lt;br /&gt;
&lt;br /&gt;
; BGP-CN-zImage-with-initrd.elf&lt;br /&gt;
: ZeptoOS compute node Linux with embedded compute node ramdisk.&lt;br /&gt;
; BGP-ION-zImage.elf&lt;br /&gt;
: ZeptoOS I/O node kernel.&lt;br /&gt;
; BGP-ION-ramdisk-for-CNL.elf&lt;br /&gt;
: ZeptoOS I/O node ramdisk for use with the ZeptoOS compute node Linux.&lt;br /&gt;
; BGP-ION-ramdisk-for-CNK.elf&lt;br /&gt;
: ZeptoOS I/O node ramdisk for use with the IBM CNK (optional).&lt;br /&gt;
&lt;br /&gt;
It is possible to rebuild individual ZeptoOS components using one of the following &amp;lt;tt&amp;gt;make&amp;lt;/tt&amp;gt; targets (the list is also available by typing &amp;lt;tt&amp;gt;make help&amp;lt;/tt&amp;gt; or &amp;lt;tt&amp;gt;make menu&amp;lt;/tt&amp;gt;):&lt;br /&gt;
&lt;br /&gt;
; bgp-cn-linux&lt;br /&gt;
: Rebuilds the compute node ramdisk and embeds it into a compute node kernel image.&lt;br /&gt;
; bgp-ion-ramdisk-cnl&lt;br /&gt;
: Rebuilds the I/O node ramdisk for the ZeptoOS compute node Linux.&lt;br /&gt;
; bgp-ion-ramdisk-cnk&lt;br /&gt;
: Rebuilds the I/O node ramdisk for the IBM CNK.&lt;br /&gt;
; bgp-ion-linux-build&lt;br /&gt;
: Rebuilds the I/O node kernel.&lt;br /&gt;
; bgp-cn-linux-build&lt;br /&gt;
: Rebuilds the compute node kernel and ramdisk and embeds the ramdisk into the kernel.&lt;br /&gt;
; bgp-all-pkg-rebuild&lt;br /&gt;
: Rebuilds all packages from sources.&lt;br /&gt;
; bgp-libs-build&lt;br /&gt;
: Rebuilds SPI, DCMF and MPICH from sources&lt;br /&gt;
(the following &amp;lt;tt&amp;gt;make&amp;lt;/tt&amp;gt; targets are mostly for internal use)&lt;br /&gt;
; bgp-ion-linux&lt;br /&gt;
: Copies a recently rebuilt I/O node kernel if one is available; otherwise, uses a prebuilt binary (will not rebuild the kernel).&lt;br /&gt;
; bgp-all-pkg-smart&lt;br /&gt;
: Copies recently rebuilt packages if available; otherwise, uses prebuilt binaries (used when preparing to rebuild ramdisks).&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
[[Introduction]] | [[ZeptoOS_Documentation|Top]] | [[Installation]]&lt;/div&gt;</summary>
		<author><name>Iskra</name></author>
	</entry>
	<entry>
		<id> /zeptoos/index.php?title=Configuration&amp;diff=626</id>
		<title>Configuration</title>
		<link rel="alternate" type="text/html" href=" /zeptoos/index.php?title=Configuration&amp;diff=626"/>
		<updated>2022-02-25T19:37:19Z</updated>

		<summary type="html">&lt;p&gt;Iskra: /* Downloading */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;[[Introduction]] | [[ZeptoOS_Documentation|Top]] | [[Installation]]&lt;br /&gt;
----&lt;br /&gt;
&lt;br /&gt;
== Downloading ==&lt;br /&gt;
&lt;br /&gt;
* Log on one of the front end nodes of the Blue Gene (a login node or a service node).&lt;br /&gt;
&lt;br /&gt;
* Download the ZeptoOS tarball from the ZeptoOS [https://www.mcs.anl.gov/research/projects/zeptoos/download download page].&lt;br /&gt;
&lt;br /&gt;
* Extract the sources from the package:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
$ tar xjf ZeptoOS-&amp;lt;version&amp;gt;.tar.bz2&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Configuring ==&lt;br /&gt;
&lt;br /&gt;
Change to the top-level &amp;lt;tt&amp;gt;ZeptoOS-&amp;lt;version&amp;gt;&amp;lt;/tt&amp;gt; directory:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
$ cd ZeptoOS-&amp;lt;version&amp;gt;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
A &amp;lt;tt&amp;gt;configure&amp;lt;/tt&amp;gt; script is provided to set the pathnames to various system directories:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
$ ./configure&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
If invoked without any arguments, it will use the defaults, which should be appropriate if ZeptoOS is configured on a system with a supported BG/P driver version.  The pathnames can be changed with the help of a textual user interface by invoking the script as follows:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
$ ./configure --edit&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This will display the following menu:&lt;br /&gt;
&lt;br /&gt;
[[Image:Configure1.png|border|Main menu]]&lt;br /&gt;
&lt;br /&gt;
Please select the top item (&amp;lt;tt&amp;gt;BG/P DIST_DIR&amp;lt;/tt&amp;gt;).  The screen will change to:&lt;br /&gt;
&lt;br /&gt;
[[Image:Configure2.png|border|DIST_DIR menu]]&lt;br /&gt;
&lt;br /&gt;
The following options are available:&lt;br /&gt;
&lt;br /&gt;
; DRV_DIR&lt;br /&gt;
: The directory with the BG/P driver tree.  The default (&amp;lt;tt&amp;gt;/bgsys/drivers/ppcfloor/&amp;lt;/tt&amp;gt;) is a link pointing to the currently active driver.&lt;br /&gt;
; BGP_CROSS&lt;br /&gt;
: A prefix to the pathnames of the GNU cross-compilers used to build the compute node and I/O node software.&lt;br /&gt;
; BGCNS_H_PATH and BGCNS_H&lt;br /&gt;
: The location of a file needed to rebuild the kernel (these options are temporary and will be removed in the next version).&lt;br /&gt;
; OS_DIR&lt;br /&gt;
: The directory with the supplementary I/O node software used when booting the I/O nodes.  It needs to be set to match the BG/P driver version being used.&lt;br /&gt;
&lt;br /&gt;
The second top-level menu (&amp;lt;tt&amp;gt;Debugging&amp;lt;/tt&amp;gt;) has only one option:&lt;br /&gt;
&lt;br /&gt;
; ADD_DEBUG_TOOLS&lt;br /&gt;
: Check this option to include &amp;lt;tt&amp;gt;gdb&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;strace&amp;lt;/tt&amp;gt; in the compute node ramdisk.  They are not included by default because of their size.&lt;br /&gt;
&lt;br /&gt;
The third top-level menu (&amp;lt;tt&amp;gt;Kernel Profiling&amp;lt;/tt&amp;gt;) is discussed in the [[(K)TAU#Configure ZeptoOS to point to KTAU patch and path|(K)TAU section]]&lt;br /&gt;
&lt;br /&gt;
Select &amp;lt;tt&amp;gt;Exit&amp;lt;/tt&amp;gt; (multiple times if needed) and confirm if you want to save any changes made.&lt;br /&gt;
&lt;br /&gt;
== Building ==&lt;br /&gt;
&lt;br /&gt;
To start using the pre-built binaries simply type:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
$ make&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
On the first invocation, this will ask for a root password to use on I/O nodes:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
Create root password for I/O Node&lt;br /&gt;
   Leave the password field empty if you want to disable root login&lt;br /&gt;
   New password:&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
'''Security note: root-level access to I/O nodes should only be given to trusted individuals.  A root user can access and modify files of all users in the system.'''&lt;br /&gt;
&lt;br /&gt;
Once the password has been entered and confirmed, &amp;lt;tt&amp;gt;make&amp;lt;/tt&amp;gt; will use pre-built kernel images, and will build the ramdisks from pre-built tools and utilities.  The following generated files will be placed in the top-level directory:&lt;br /&gt;
&lt;br /&gt;
; BGP-CN-zImage-with-initrd.elf&lt;br /&gt;
: ZeptoOS compute node Linux with embedded compute node ramdisk.&lt;br /&gt;
; BGP-ION-zImage.elf&lt;br /&gt;
: ZeptoOS I/O node kernel.&lt;br /&gt;
; BGP-ION-ramdisk-for-CNL.elf&lt;br /&gt;
: ZeptoOS I/O node ramdisk for use with the ZeptoOS compute node Linux.&lt;br /&gt;
; BGP-ION-ramdisk-for-CNK.elf&lt;br /&gt;
: ZeptoOS I/O node ramdisk for use with the IBM CNK (optional).&lt;br /&gt;
&lt;br /&gt;
It is possible to rebuild individual ZeptoOS components using one of the following &amp;lt;tt&amp;gt;make&amp;lt;/tt&amp;gt; targets (the list is also available by typing &amp;lt;tt&amp;gt;make help&amp;lt;/tt&amp;gt; or &amp;lt;tt&amp;gt;make menu&amp;lt;/tt&amp;gt;):&lt;br /&gt;
&lt;br /&gt;
; bgp-cn-linux&lt;br /&gt;
: Rebuilds the compute node ramdisk and embeds it into a compute node kernel image.&lt;br /&gt;
; bgp-ion-ramdisk-cnl&lt;br /&gt;
: Rebuilds the I/O node ramdisk for the ZeptoOS compute node Linux.&lt;br /&gt;
; bgp-ion-ramdisk-cnk&lt;br /&gt;
: Rebuilds the I/O node ramdisk for the IBM CNK.&lt;br /&gt;
; bgp-ion-linux-build&lt;br /&gt;
: Rebuilds the I/O node kernel.&lt;br /&gt;
; bgp-cn-linux-build&lt;br /&gt;
: Rebuilds the compute node kernel and ramdisk and embeds the ramdisk into the kernel.&lt;br /&gt;
; bgp-all-pkg-rebuild&lt;br /&gt;
: Rebuilds all packages from sources.&lt;br /&gt;
; bgp-libs-build&lt;br /&gt;
: Rebuilds SPI, DCMF and MPICH from sources&lt;br /&gt;
(the following &amp;lt;tt&amp;gt;make&amp;lt;/tt&amp;gt; targets are mostly for internal use)&lt;br /&gt;
; bgp-ion-linux&lt;br /&gt;
: Copies a recently rebuilt I/O node kernel if one is available; otherwise, uses a prebuilt binary (will not rebuild the kernel).&lt;br /&gt;
; bgp-all-pkg-smart&lt;br /&gt;
: Copies recently rebuilt packages if available; otherwise, uses prebuilt binaries (used when preparing to rebuild ramdisks).&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
[[Introduction]] | [[ZeptoOS_Documentation|Top]] | [[Installation]]&lt;/div&gt;</summary>
		<author><name>Iskra</name></author>
	</entry>
	<entry>
		<id> /zeptoos/index.php?title=MediaWiki:Sidebar&amp;diff=624</id>
		<title>MediaWiki:Sidebar</title>
		<link rel="alternate" type="text/html" href=" /zeptoos/index.php?title=MediaWiki:Sidebar&amp;diff=624"/>
		<updated>2018-02-21T19:19:32Z</updated>

		<summary type="html">&lt;p&gt;Iskra: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;* &lt;br /&gt;
** mainpage|Top&lt;br /&gt;
** http://www.mcs.anl.gov/research/projects/zeptoos/|ZeptoOS Home&lt;br /&gt;
* SEARCH&lt;br /&gt;
* TOOLBOX&lt;br /&gt;
* LANGUAGES&lt;/div&gt;</summary>
		<author><name>Iskra</name></author>
	</entry>
	<entry>
		<id> /zeptoos/index.php?title=ZeptoOS:About&amp;diff=622</id>
		<title>ZeptoOS:About</title>
		<link rel="alternate" type="text/html" href=" /zeptoos/index.php?title=ZeptoOS:About&amp;diff=622"/>
		<updated>2018-02-20T21:26:44Z</updated>

		<summary type="html">&lt;p&gt;Iskra: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;[http://www.mcs.anl.gov/research/projects/zeptoos/ ZeptoOS] is a research project studying operating systems for petascale architectures with 10,000 to 1 million CPUs. Operating system and run-time software is strained by ultra-scale machines, and a variety of fascinating research topics are revealed at such amazing scale. Archtectures such as IBM's BlueGene and Cray's XT3 are on the path toward petaflops and beyond, and make perfect testbeds for computer science explorations.&lt;br /&gt;
&lt;br /&gt;
The ZeptoOS project is a collaboration between Argonne National Laboratory and the University of Oregon.&lt;/div&gt;</summary>
		<author><name>Iskra</name></author>
	</entry>
	<entry>
		<id> /zeptoos/index.php?title=FAQ&amp;diff=621</id>
		<title>FAQ</title>
		<link rel="alternate" type="text/html" href=" /zeptoos/index.php?title=FAQ&amp;diff=621"/>
		<updated>2010-05-06T22:49:12Z</updated>

		<summary type="html">&lt;p&gt;Iskra: /* How to obtain a Cobalt job ID */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;[[ZeptoOS_Documentation|Top]]&lt;br /&gt;
----&lt;br /&gt;
&lt;br /&gt;
==How to obtain a CN node number==&lt;br /&gt;
&lt;br /&gt;
This depends on what number one is interested in.&lt;br /&gt;
&lt;br /&gt;
===Pset rank===&lt;br /&gt;
&lt;br /&gt;
A pset rank is a number identifying a compute node within each ''pset'' (an I/O node and the compute nodes that communicate with it).  Note that on partitions larger than one pset, the pset ranks will not be unique.  Also, pset ranks do ''not'' start from &amp;lt;tt&amp;gt;0&amp;lt;/tt&amp;gt;; they start from &amp;lt;tt&amp;gt;1&amp;lt;/tt&amp;gt; for some mysterious reason (do not blame us &amp;amp;#8211; blame IBM&amp;amp;nbsp;:-).&lt;br /&gt;
&lt;br /&gt;
Pset rank is used as the last octet in the IP address on the tree network connecting the compute nodes and the I/O nodes (''x'' in &amp;lt;tt&amp;gt;192.168.1.&amp;lt;/tt&amp;gt;''x'').&lt;br /&gt;
&lt;br /&gt;
The pset rank is available on the compute nodes from &amp;lt;tt&amp;gt;/proc/personality.sh&amp;lt;/tt&amp;gt;, in the &amp;lt;tt&amp;gt;BG_RANK_IN_PSET&amp;lt;/tt&amp;gt; variable:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
#!/bin/sh&lt;br /&gt;
&lt;br /&gt;
. /proc/personality.sh&lt;br /&gt;
&lt;br /&gt;
echo &amp;quot;My pset rank is $BG_RANK_IN_PSET&amp;quot;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
From a C program it will be easier to use the binary personality available from &amp;lt;tt&amp;gt;/proc/personality&amp;lt;/tt&amp;gt;.  The definition of the structure can be found in &amp;lt;tt&amp;gt;/bgsys/drivers/ppcfloor/arch/include/common/bgp_personality.h&amp;lt;/tt&amp;gt;.  The pset rank is in &amp;lt;tt&amp;gt;Network_Config.RankInPSet&amp;lt;/tt&amp;gt;:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
#include &amp;lt;stdio.h&amp;gt;&lt;br /&gt;
#include &amp;lt;fcntl.h&amp;gt;&lt;br /&gt;
#include &amp;lt;unistd.h&amp;gt;&lt;br /&gt;
#include &amp;lt;common/bgp_personality.h&amp;gt;&lt;br /&gt;
&lt;br /&gt;
int main(void)&lt;br /&gt;
{&lt;br /&gt;
    _BGP_Personality_t personality;&lt;br /&gt;
    int fd;&lt;br /&gt;
&lt;br /&gt;
    if ((fd = open(&amp;quot;/proc/personality&amp;quot;, O_RDONLY)) == -1)&lt;br /&gt;
    {&lt;br /&gt;
        perror(&amp;quot;open&amp;quot;);&lt;br /&gt;
        return 1;&lt;br /&gt;
    }&lt;br /&gt;
    if (read(fd, &amp;amp;personality, sizeof(personality)) != sizeof(personality))&lt;br /&gt;
    {&lt;br /&gt;
        perror(&amp;quot;read&amp;quot;);&lt;br /&gt;
        close(fd);&lt;br /&gt;
        return 1;&lt;br /&gt;
    }&lt;br /&gt;
    close(fd);&lt;br /&gt;
&lt;br /&gt;
    printf(&amp;quot;My pset rank is %d\n&amp;quot;, personality.Network_Config.RankInPSet);&lt;br /&gt;
&lt;br /&gt;
    return 0;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
(compile the above with &amp;lt;tt&amp;gt;-I/bgsys/drivers/ppcfloor/arch/include&amp;lt;/tt&amp;gt;)&lt;br /&gt;
&lt;br /&gt;
===Torus rank===&lt;br /&gt;
&lt;br /&gt;
A torus rank is a number identifying a compute node within a whole partition.  In a way, it is much &amp;quot;nicer&amp;quot; than a pset rank since it is unique within a job and it also starts from &amp;lt;tt&amp;gt;0&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
The torus rank is easy to obtain from a C program: it is the &amp;lt;tt&amp;gt;Network_Config.Rank&amp;lt;/tt&amp;gt; field of the personality structure.&lt;br /&gt;
&lt;br /&gt;
Unfortunately, the torus rank is not available in &amp;lt;tt&amp;gt;/proc/personality.sh&amp;lt;/tt&amp;gt;, but a shell script can easily calculate it from other fields:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
TORUS_RANK=`echo $BG_PSETORG | awk &amp;quot;{print \\$1 + \\$2 * $BG_XSIZE + \&lt;br /&gt;
            \\$3 * $BG_XSIZE * $BG_YSIZE}&amp;quot;`&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===MPI rank===&lt;br /&gt;
&lt;br /&gt;
An MPI rank should not be confused with the torus rank, even though by default the two are the same.  MPI rank is a property of a process, ''not'' node.  If one submits a job in the &amp;lt;tt&amp;gt;VN&amp;lt;/tt&amp;gt; or &amp;lt;tt&amp;gt;DUAL&amp;lt;/tt&amp;gt; mode, there will be multiple MPI tasks per node, obviously each with a different MPI rank.  Also, using the &amp;lt;tt&amp;gt;BG_MAPPING&amp;lt;/tt&amp;gt; environment variable changes the mapping between the torus coordinates and MPI ranks.&lt;br /&gt;
&lt;br /&gt;
While obtaining MPI rank from an MPI application is trivial, how to obtain it from a shell script?&lt;br /&gt;
&lt;br /&gt;
One way would be to invoke a simple C program:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
#include &amp;lt;stdio.h&amp;gt;&lt;br /&gt;
#include &amp;quot;zoid_api.h&amp;quot;&lt;br /&gt;
&lt;br /&gt;
int main(void)&lt;br /&gt;
{&lt;br /&gt;
    if (__zoid_init())&lt;br /&gt;
        return 1;&lt;br /&gt;
    printf(&amp;quot;%d\n&amp;quot;, __zoid_my_rank());&lt;br /&gt;
    return 0;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
(compile with &amp;lt;tt&amp;gt;-I&amp;lt;/tt&amp;gt;''path_to_ZeptoOS_source''&amp;lt;tt&amp;gt;/packages/zoid/prebuilt -L&amp;lt;/tt&amp;gt;''path_to_ZeptoOS_source''&amp;lt;tt&amp;gt;/packages/zoid/prebuilt -lzoid_cn&amp;lt;/tt&amp;gt;)&lt;br /&gt;
&lt;br /&gt;
A slight disadvantage of this approach is that &amp;lt;tt&amp;gt;__zoid_init&amp;lt;/tt&amp;gt; registers the process with the ZOID daemon on the I/O node, which is an overhead we do not need.  Another solution, without using any binaries, is as follows:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
MPI_RANK=`echo $CONTROL_INIT | awk -F, '{print $4}'`&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This has a disadvantage of using internal ZOID variables which are not guaranteed to be supported in future releases.&lt;br /&gt;
&lt;br /&gt;
==How to open a socket from a CN to the outside world==&lt;br /&gt;
&lt;br /&gt;
ZOID provides IP packet forwarding between the compute nodes and the I/O nodes.  However, because the compute nodes use non-routable IP addresses (&amp;lt;tt&amp;gt;192.168.1.&amp;lt;/tt&amp;gt;''x''), they cannot communicate directly with the outside world.&lt;br /&gt;
&lt;br /&gt;
The most transparent solution to this problem is to perform network address translation (NAT) on the I/O nodes using the Linux kernel netfilter infrastructure.  We used to enable this by default, but experiments have shown it to have a detrimental effect on the overall performance of the TCP/IP stack on the I/O nodes, slowing down access to the network filesystems.&lt;br /&gt;
&lt;br /&gt;
To enable the translation, pass &amp;lt;tt&amp;gt;ZOID_ENABLE_NAT&amp;lt;/tt&amp;gt; environment variable when submitting a job.  An administrator can also enable this option permanently in the [[ZOID#opt_enable_nat|config file]].&lt;br /&gt;
&lt;br /&gt;
==How to obtain a Cobalt job ID==&lt;br /&gt;
&lt;br /&gt;
Cobalt passes the job id to the application processes launched on the compute nodes using the &amp;lt;tt&amp;gt;COBALT_JOBID&amp;lt;/tt&amp;gt; environment variable.&lt;br /&gt;
&lt;br /&gt;
This variable is also accessible from the [[ZOID#User script|user script]] running on the I/O nodes, using the &amp;lt;tt&amp;gt;ZOID_JOB_ENV&amp;lt;/tt&amp;gt; variable:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
COBALT_JOBID=`echo $ZOID_JOB_ENV | sed 's/^.*COBALT_JOBID=\([^:]*\).*$/\1/'`&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Why large MPI processes do not work==&lt;br /&gt;
&lt;br /&gt;
A common reason might be that they do not have enough memory to run.  MPI processes run within the big memory region, which by default is limited to just 256&amp;amp;nbsp;MB so as not to deplete the ordinary Linux paged memory pool too much (main memory is allocated to the big memory region at boot time and it cannot be reclaimed by the kernel, even if it were unused).&lt;br /&gt;
&lt;br /&gt;
See the [[Kernel#Kernel (command line) parameters|Kernel]] section to learn how to increase the limit; the parameter to use is &amp;lt;tt&amp;gt;flatmemsizeMB&amp;lt;/tt&amp;gt;.  We suggest creating multiple profiles with different big memory sizes to accommodate different uses of ZeptoOS.&lt;br /&gt;
&lt;br /&gt;
==Why SSH keeps asking for a password==&lt;br /&gt;
&lt;br /&gt;
As we envisioned it, partition owners should be able to log on the I/O nodes belonging to their jobs without being asked for a password.  The following considerations apply:&lt;br /&gt;
# The account information on the partition owner must be added to the &amp;lt;tt&amp;gt;/etc/passwd&amp;lt;/tt&amp;gt; file on the I/O nodes when launching a job; this is discussed [[ZOID#The /bin.rd/update_passwd_file.sh file|here]].&lt;br /&gt;
# For password-less logins, &amp;lt;tt&amp;gt;shosts.equiv&amp;lt;/tt&amp;gt; must be configured before (re)building the I/O node ramdisk, as discussed [[Testing#Interactive login|here]].  Alternatively, users could set up SSH key pairs in their home directories (password-less, or using &amp;lt;tt&amp;gt;ssh-agent&amp;lt;/tt&amp;gt; to cache the password).&lt;br /&gt;
# SSH might temporarily prevent a partition owner from logging in if an attempt is made before the job starts running, as discussed [[Testing#Interactive login|here]].  Root can always log in, by providing the password set when building the I/O node ramdisk for the first time.&lt;br /&gt;
# Finally, keep in mind that a particular site might have disabled this feature on purpose.&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
[[ZeptoOS_Documentation|Top]]&lt;/div&gt;</summary>
		<author><name>Iskra</name></author>
	</entry>
	<entry>
		<id> /zeptoos/index.php?title=FAQ&amp;diff=620</id>
		<title>FAQ</title>
		<link rel="alternate" type="text/html" href=" /zeptoos/index.php?title=FAQ&amp;diff=620"/>
		<updated>2009-10-19T22:24:14Z</updated>

		<summary type="html">&lt;p&gt;Iskra: /* How to open a socket from a CN to the outside world */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;[[ZeptoOS_Documentation|Top]]&lt;br /&gt;
----&lt;br /&gt;
&lt;br /&gt;
==How to obtain a CN node number==&lt;br /&gt;
&lt;br /&gt;
This depends on what number one is interested in.&lt;br /&gt;
&lt;br /&gt;
===Pset rank===&lt;br /&gt;
&lt;br /&gt;
A pset rank is a number identifying a compute node within each ''pset'' (an I/O node and the compute nodes that communicate with it).  Note that on partitions larger than one pset, the pset ranks will not be unique.  Also, pset ranks do ''not'' start from &amp;lt;tt&amp;gt;0&amp;lt;/tt&amp;gt;; they start from &amp;lt;tt&amp;gt;1&amp;lt;/tt&amp;gt; for some mysterious reason (do not blame us &amp;amp;#8211; blame IBM&amp;amp;nbsp;:-).&lt;br /&gt;
&lt;br /&gt;
Pset rank is used as the last octet in the IP address on the tree network connecting the compute nodes and the I/O nodes (''x'' in &amp;lt;tt&amp;gt;192.168.1.&amp;lt;/tt&amp;gt;''x'').&lt;br /&gt;
&lt;br /&gt;
The pset rank is available on the compute nodes from &amp;lt;tt&amp;gt;/proc/personality.sh&amp;lt;/tt&amp;gt;, in the &amp;lt;tt&amp;gt;BG_RANK_IN_PSET&amp;lt;/tt&amp;gt; variable:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
#!/bin/sh&lt;br /&gt;
&lt;br /&gt;
. /proc/personality.sh&lt;br /&gt;
&lt;br /&gt;
echo &amp;quot;My pset rank is $BG_RANK_IN_PSET&amp;quot;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
From a C program it will be easier to use the binary personality available from &amp;lt;tt&amp;gt;/proc/personality&amp;lt;/tt&amp;gt;.  The definition of the structure can be found in &amp;lt;tt&amp;gt;/bgsys/drivers/ppcfloor/arch/include/common/bgp_personality.h&amp;lt;/tt&amp;gt;.  The pset rank is in &amp;lt;tt&amp;gt;Network_Config.RankInPSet&amp;lt;/tt&amp;gt;:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
#include &amp;lt;stdio.h&amp;gt;&lt;br /&gt;
#include &amp;lt;fcntl.h&amp;gt;&lt;br /&gt;
#include &amp;lt;unistd.h&amp;gt;&lt;br /&gt;
#include &amp;lt;common/bgp_personality.h&amp;gt;&lt;br /&gt;
&lt;br /&gt;
int main(void)&lt;br /&gt;
{&lt;br /&gt;
    _BGP_Personality_t personality;&lt;br /&gt;
    int fd;&lt;br /&gt;
&lt;br /&gt;
    if ((fd = open(&amp;quot;/proc/personality&amp;quot;, O_RDONLY)) == -1)&lt;br /&gt;
    {&lt;br /&gt;
        perror(&amp;quot;open&amp;quot;);&lt;br /&gt;
        return 1;&lt;br /&gt;
    }&lt;br /&gt;
    if (read(fd, &amp;amp;personality, sizeof(personality)) != sizeof(personality))&lt;br /&gt;
    {&lt;br /&gt;
        perror(&amp;quot;read&amp;quot;);&lt;br /&gt;
        close(fd);&lt;br /&gt;
        return 1;&lt;br /&gt;
    }&lt;br /&gt;
    close(fd);&lt;br /&gt;
&lt;br /&gt;
    printf(&amp;quot;My pset rank is %d\n&amp;quot;, personality.Network_Config.RankInPSet);&lt;br /&gt;
&lt;br /&gt;
    return 0;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
(compile the above with &amp;lt;tt&amp;gt;-I/bgsys/drivers/ppcfloor/arch/include&amp;lt;/tt&amp;gt;)&lt;br /&gt;
&lt;br /&gt;
===Torus rank===&lt;br /&gt;
&lt;br /&gt;
A torus rank is a number identifying a compute node within a whole partition.  In a way, it is much &amp;quot;nicer&amp;quot; than a pset rank since it is unique within a job and it also starts from &amp;lt;tt&amp;gt;0&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
The torus rank is easy to obtain from a C program: it is the &amp;lt;tt&amp;gt;Network_Config.Rank&amp;lt;/tt&amp;gt; field of the personality structure.&lt;br /&gt;
&lt;br /&gt;
Unfortunately, the torus rank is not available in &amp;lt;tt&amp;gt;/proc/personality.sh&amp;lt;/tt&amp;gt;, but a shell script can easily calculate it from other fields:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
TORUS_RANK=`echo $BG_PSETORG | awk &amp;quot;{print \\$1 + \\$2 * $BG_XSIZE + \&lt;br /&gt;
            \\$3 * $BG_XSIZE * $BG_YSIZE}&amp;quot;`&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===MPI rank===&lt;br /&gt;
&lt;br /&gt;
An MPI rank should not be confused with the torus rank, even though by default the two are the same.  MPI rank is a property of a process, ''not'' node.  If one submits a job in the &amp;lt;tt&amp;gt;VN&amp;lt;/tt&amp;gt; or &amp;lt;tt&amp;gt;DUAL&amp;lt;/tt&amp;gt; mode, there will be multiple MPI tasks per node, obviously each with a different MPI rank.  Also, using the &amp;lt;tt&amp;gt;BG_MAPPING&amp;lt;/tt&amp;gt; environment variable changes the mapping between the torus coordinates and MPI ranks.&lt;br /&gt;
&lt;br /&gt;
While obtaining MPI rank from an MPI application is trivial, how to obtain it from a shell script?&lt;br /&gt;
&lt;br /&gt;
One way would be to invoke a simple C program:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
#include &amp;lt;stdio.h&amp;gt;&lt;br /&gt;
#include &amp;quot;zoid_api.h&amp;quot;&lt;br /&gt;
&lt;br /&gt;
int main(void)&lt;br /&gt;
{&lt;br /&gt;
    if (__zoid_init())&lt;br /&gt;
        return 1;&lt;br /&gt;
    printf(&amp;quot;%d\n&amp;quot;, __zoid_my_rank());&lt;br /&gt;
    return 0;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
(compile with &amp;lt;tt&amp;gt;-I&amp;lt;/tt&amp;gt;''path_to_ZeptoOS_source''&amp;lt;tt&amp;gt;/packages/zoid/prebuilt -L&amp;lt;/tt&amp;gt;''path_to_ZeptoOS_source''&amp;lt;tt&amp;gt;/packages/zoid/prebuilt -lzoid_cn&amp;lt;/tt&amp;gt;)&lt;br /&gt;
&lt;br /&gt;
A slight disadvantage of this approach is that &amp;lt;tt&amp;gt;__zoid_init&amp;lt;/tt&amp;gt; registers the process with the ZOID daemon on the I/O node, which is an overhead we do not need.  Another solution, without using any binaries, is as follows:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
MPI_RANK=`echo $CONTROL_INIT | awk -F, '{print $4}'`&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This has a disadvantage of using internal ZOID variables which are not guaranteed to be supported in future releases.&lt;br /&gt;
&lt;br /&gt;
==How to open a socket from a CN to the outside world==&lt;br /&gt;
&lt;br /&gt;
ZOID provides IP packet forwarding between the compute nodes and the I/O nodes.  However, because the compute nodes use non-routable IP addresses (&amp;lt;tt&amp;gt;192.168.1.&amp;lt;/tt&amp;gt;''x''), they cannot communicate directly with the outside world.&lt;br /&gt;
&lt;br /&gt;
The most transparent solution to this problem is to perform network address translation (NAT) on the I/O nodes using the Linux kernel netfilter infrastructure.  We used to enable this by default, but experiments have shown it to have a detrimental effect on the overall performance of the TCP/IP stack on the I/O nodes, slowing down access to the network filesystems.&lt;br /&gt;
&lt;br /&gt;
To enable the translation, pass &amp;lt;tt&amp;gt;ZOID_ENABLE_NAT&amp;lt;/tt&amp;gt; environment variable when submitting a job.  An administrator can also enable this option permanently in the [[ZOID#opt_enable_nat|config file]].&lt;br /&gt;
&lt;br /&gt;
==How to obtain a Cobalt job ID==&lt;br /&gt;
&lt;br /&gt;
Cobalt passes the job id to the application processes launched on the compute nodes using the &amp;lt;tt&amp;gt;COBALT_JOBID&amp;lt;/tt&amp;gt; environment variable.&lt;br /&gt;
&lt;br /&gt;
This variable is also accessible from the [[ZOID#User script|user script]] running on the I/O nodes, using the &amp;lt;tt&amp;gt;ZOID_JOB_ENV&amp;lt;/tt&amp;gt; variable:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
COBALT_JOBID=`echo $ZOID_JOB_ENV | sed 's/^.*COBALT_JOBID=\([^:]*\)/\1/'`&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Why large MPI processes do not work==&lt;br /&gt;
&lt;br /&gt;
A common reason might be that they do not have enough memory to run.  MPI processes run within the big memory region, which by default is limited to just 256&amp;amp;nbsp;MB so as not to deplete the ordinary Linux paged memory pool too much (main memory is allocated to the big memory region at boot time and it cannot be reclaimed by the kernel, even if it were unused).&lt;br /&gt;
&lt;br /&gt;
See the [[Kernel#Kernel (command line) parameters|Kernel]] section to learn how to increase the limit; the parameter to use is &amp;lt;tt&amp;gt;flatmemsizeMB&amp;lt;/tt&amp;gt;.  We suggest creating multiple profiles with different big memory sizes to accommodate different uses of ZeptoOS.&lt;br /&gt;
&lt;br /&gt;
==Why SSH keeps asking for a password==&lt;br /&gt;
&lt;br /&gt;
As we envisioned it, partition owners should be able to log on the I/O nodes belonging to their jobs without being asked for a password.  The following considerations apply:&lt;br /&gt;
# The account information on the partition owner must be added to the &amp;lt;tt&amp;gt;/etc/passwd&amp;lt;/tt&amp;gt; file on the I/O nodes when launching a job; this is discussed [[ZOID#The /bin.rd/update_passwd_file.sh file|here]].&lt;br /&gt;
# For password-less logins, &amp;lt;tt&amp;gt;shosts.equiv&amp;lt;/tt&amp;gt; must be configured before (re)building the I/O node ramdisk, as discussed [[Testing#Interactive login|here]].  Alternatively, users could set up SSH key pairs in their home directories (password-less, or using &amp;lt;tt&amp;gt;ssh-agent&amp;lt;/tt&amp;gt; to cache the password).&lt;br /&gt;
# SSH might temporarily prevent a partition owner from logging in if an attempt is made before the job starts running, as discussed [[Testing#Interactive login|here]].  Root can always log in, by providing the password set when building the I/O node ramdisk for the first time.&lt;br /&gt;
# Finally, keep in mind that a particular site might have disabled this feature on purpose.&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
[[ZeptoOS_Documentation|Top]]&lt;/div&gt;</summary>
		<author><name>Iskra</name></author>
	</entry>
	<entry>
		<id> /zeptoos/index.php?title=Limitations&amp;diff=614</id>
		<title>Limitations</title>
		<link rel="alternate" type="text/html" href=" /zeptoos/index.php?title=Limitations&amp;diff=614"/>
		<updated>2009-05-11T22:37:07Z</updated>

		<summary type="html">&lt;p&gt;Iskra: /* Known Bugs / Current Limitations */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;[[ZeptoOS_Documentation|Top]]&lt;br /&gt;
----&lt;br /&gt;
&lt;br /&gt;
==Known Bugs / Current Limitations==&lt;br /&gt;
&lt;br /&gt;
===No VN/DUAL mode in MPI===&lt;br /&gt;
&lt;br /&gt;
Blue Gene/P supports three job modes:&lt;br /&gt;
&lt;br /&gt;
* SMP (one application process per node)&lt;br /&gt;
* DUAL (two application processes per node)&lt;br /&gt;
* VN (four application processes per node)&lt;br /&gt;
&lt;br /&gt;
In Cobalt, the job mode can be specified using &amp;lt;tt&amp;gt;cqsub -m&amp;lt;/tt&amp;gt; or &amp;lt;tt&amp;gt;qsub --mode&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
ZeptoOS will launch the appropriate number of application processes per node as determined by the mode; however, MPI jobs currently only work in the SMP mode.  We plan to fix this problem in the near future.&lt;br /&gt;
&lt;br /&gt;
===No Universal Performance Counter (UPC)===&lt;br /&gt;
&lt;br /&gt;
UPC is not available in this release. Thus, PAPI will not work since it depends on UPC.&lt;br /&gt;
We are currently trying to enable the UPC support in our Linux environment.&lt;br /&gt;
&lt;br /&gt;
===MPI-IO support===&lt;br /&gt;
&lt;br /&gt;
Due to the limitations of FUSE (the compute-node infrastructure we use for I/O forwarding of POSIX calls), if using the standard glibc, pathnames passed to MPI-IO routines need to be prefixed with &amp;lt;tt&amp;gt;bglockless:&amp;lt;/tt&amp;gt; or &amp;lt;tt&amp;gt;bgl:&amp;lt;/tt&amp;gt; (the latter will not work with PVFS; the former should work with all filesystems).&lt;br /&gt;
&lt;br /&gt;
This should not be necessary when using the version of glibc [[Other Packages#ZOID glibc|modified for ZOID]].  That version should also give a better performance, so please give it a try if the performance with the standard glibc is unsatisfactory.&lt;br /&gt;
&lt;br /&gt;
Also, within the DOE FastOS [http://www.iofsl.org/ I/O forwarding project] we are working on a new, high performance I/O forwarding infrastructure for parallel applications and as this work matures, we will integrate it into ZeptoOS.&lt;br /&gt;
&lt;br /&gt;
===Some MPI jobs hung when they are killed===&lt;br /&gt;
&lt;br /&gt;
We have been seeing this a lot with &amp;lt;tt&amp;gt;cn-ipfwd&amp;lt;/tt&amp;gt;, the [[Other Packages#IP over torus|IP-over-torus]] program.  This program runs &amp;quot;forever&amp;quot;, so it eventually needs to be killed.  When that happens, it will frequently hung one or more compute nodes, preventing the partition from shutting down cleanly.&lt;br /&gt;
&lt;br /&gt;
However, the service node will force a shutdown after a timeout of five minutes, so in practice this is not a significant problem.  Also, we have not seen this problem with ordinary MPI applications (unlike most MPI applications, &amp;lt;tt&amp;gt;cn-ipfwd&amp;lt;/tt&amp;gt; is multithreaded and communicates a lot with the kernel).&lt;br /&gt;
&lt;br /&gt;
===mpirun -nofree does not work===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;mpirun -nofree&amp;lt;/tt&amp;gt; (submitting multiple jobs without rebooting the nodes) does not work in the current release.  Currently, partitions must be rebooted.  We intend to fix it in the next version.&lt;br /&gt;
&lt;br /&gt;
==Features Coming Soon==&lt;br /&gt;
&lt;br /&gt;
===Multiple MPI jobs one after another===&lt;br /&gt;
&lt;br /&gt;
Since ZeptoOS supports submitting a shell script as a compute node &amp;quot;application&amp;quot;, it is possible to run multiple &amp;quot;real&amp;quot; applications from within one job:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
#!/bin/sh&lt;br /&gt;
&lt;br /&gt;
for i in 1 2 3 4 5 6 7 8 9 10; do&lt;br /&gt;
    /path/to/real/application&lt;br /&gt;
done&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This does work for sequential applications, but not for those that are linked with MPI; with MPI, an application can only be run once.  However, we have an experimental code that lifts this limitation and we plan to include it in the next release.&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
[[ZeptoOS_Documentation|Top]]&lt;/div&gt;</summary>
		<author><name>Iskra</name></author>
	</entry>
	<entry>
		<id> /zeptoos/index.php?title=Changes&amp;diff=612</id>
		<title>Changes</title>
		<link rel="alternate" type="text/html" href=" /zeptoos/index.php?title=Changes&amp;diff=612"/>
		<updated>2009-05-11T17:53:29Z</updated>

		<summary type="html">&lt;p&gt;Iskra: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;[[ZeptoOS_Documentation|Top]]&lt;br /&gt;
----&lt;br /&gt;
&lt;br /&gt;
'''ZeptoOS-BGP 2.0''' released May 11, 2009.&amp;lt;br/&amp;gt;&lt;br /&gt;
Most important changes:&lt;br /&gt;
&lt;br /&gt;
* first public release with support for Blue Gene/P&lt;br /&gt;
* ZeptoOS Compute Node Linux with:&lt;br /&gt;
** Big Memory&lt;br /&gt;
** Native communication support&lt;br /&gt;
** IP forwarding&lt;br /&gt;
* ZOID enabled by default&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
'''ZeptoOS-BG 1.5''' released June 28, 2007.&amp;lt;br/&amp;gt;&lt;br /&gt;
Most important changes:&lt;br /&gt;
&lt;br /&gt;
* tested on V1R3M2 driver, should work with V1R3M0 and V1R3M1 as well&lt;br /&gt;
* support for ZOID&lt;br /&gt;
* ION kernel with experimental support for compute class processes and static TLB&lt;br /&gt;
* PVFS2 updated to version 2.6.3 &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
'''ZeptoOS-BG 1.4''' released January 31, 2006.&amp;lt;br/&amp;gt;&lt;br /&gt;
Most important changes:&lt;br /&gt;
&lt;br /&gt;
* tested on V1R2M1 driver and may work with V1R2M0&lt;br /&gt;
* 2.6 ION kernel (based on 2.6.5)&lt;br /&gt;
* pvfs2 binary and rc script update&lt;br /&gt;
* boot msg clean up&lt;br /&gt;
* ZeptoInstall.sh fixes&lt;br /&gt;
* misc. such as fixing /tmp perms &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
'''ZeptoOS-BG 1.2''' released November 11, 2005.&amp;lt;br/&amp;gt;&lt;br /&gt;
Most important changes:&lt;br /&gt;
&lt;br /&gt;
* Integrated support for KTAU, a kernel profiling/tracing tool.&lt;br /&gt;
* Support for custom /bgl/dist-type directory trees. Eliminates a need to put ZeptoOS-specific stuff inside a directory shared with standard IBM profile.&lt;br /&gt;
* An installation script is now available, to ease the installation process.&lt;br /&gt;
* Added zswitcher, a command to switch kernel/ramdisk of a partition.&lt;br /&gt;
* Added zdiff-elfrd, a command to compare two ramdisks.&lt;br /&gt;
* Improved zinfo: more robust, more secure, easier to set up.&lt;br /&gt;
* CIOD read/write buffer size can now be calculated automatically, taking into account available memory, compute to I/O node ratio, etc.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
'''ZeptoOS-BG 1.1''' released September 6, 2005.&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
[[ZeptoOS_Documentation|Top]]&lt;/div&gt;</summary>
		<author><name>Iskra</name></author>
	</entry>
	<entry>
		<id> /zeptoos/index.php?title=ZOID&amp;diff=611</id>
		<title>ZOID</title>
		<link rel="alternate" type="text/html" href=" /zeptoos/index.php?title=ZOID&amp;diff=611"/>
		<updated>2009-05-11T02:04:07Z</updated>

		<summary type="html">&lt;p&gt;Iskra: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;[[Ramdisk]] | [[ZeptoOS_Documentation|Top]] | [[(K)TAU]]&lt;br /&gt;
----&lt;br /&gt;
&lt;br /&gt;
==Introduction==&lt;br /&gt;
&lt;br /&gt;
ZOID is an I/O forwarding component of the ZeptoOS project.  Any communication between the compute nodes and the I/O nodes (job management, file I/O, sockets) is handled by ZOID.&lt;br /&gt;
&lt;br /&gt;
ZOID infrastructure consists of:&lt;br /&gt;
* A multithreaded &amp;lt;tt&amp;gt;zoid&amp;lt;/tt&amp;gt; daemon on the I/O nodes which performs I/O forwarding for the compute nodes and which also communicates with the service node to perform job management,&lt;br /&gt;
* &amp;lt;tt&amp;gt;control&amp;lt;/tt&amp;gt; daemon on the compute nodes which is responsible for job management tasks such as the launching of application processes, for the forwarding of &amp;lt;tt&amp;gt;stdin&amp;lt;/tt&amp;gt;/&amp;lt;tt&amp;gt;out&amp;lt;/tt&amp;gt;/&amp;lt;tt&amp;gt;err&amp;lt;/tt&amp;gt; data, and for the forwarding of IP packets,&lt;br /&gt;
* &amp;lt;tt&amp;gt;zoid-fuse&amp;lt;/tt&amp;gt; daemon on the compute nodes which performs file I/O forwarding for POSIX-compliant applications.&lt;br /&gt;
&lt;br /&gt;
==User interface==&lt;br /&gt;
&lt;br /&gt;
ZOID is meant to be transparent to users, but there are a few optional mechanisms available to interact with it.&lt;br /&gt;
&lt;br /&gt;
===User script===&lt;br /&gt;
&lt;br /&gt;
Right before a job starts running, and right after the last process of a job has terminated, ZOID daemon attempts to invoke a ''user script'' on I/O nodes.  By default, the daemon invokes &amp;lt;tt&amp;gt;$HOME/zoid-user-script.sh&amp;lt;/tt&amp;gt; (this pathname can be [[#opt_user_script|changed]] by an administrator).  A single parameter is passed to the script: &amp;lt;tt&amp;gt;1&amp;lt;/tt&amp;gt; at the job startup, and &amp;lt;tt&amp;gt;0&amp;lt;/tt&amp;gt; at the termination.&lt;br /&gt;
&lt;br /&gt;
Information about the job will be passed to the script in the following environment variables:&lt;br /&gt;
; &amp;lt;tt&amp;gt;ZOID_JOB_EXEC&amp;lt;/tt&amp;gt;&lt;br /&gt;
: name of the job executable,&lt;br /&gt;
; &amp;lt;tt&amp;gt;ZOID_JOB_ARGS&amp;lt;/tt&amp;gt;&lt;br /&gt;
: job arguments, separated by colons (&amp;lt;tt&amp;gt;:&amp;lt;/tt&amp;gt;)&lt;br /&gt;
; &amp;lt;tt&amp;gt;ZOID_JOB_ENV&amp;lt;/tt&amp;gt;&lt;br /&gt;
: job environment variables, separated by colons (&amp;lt;tt&amp;gt;:&amp;lt;/tt&amp;gt;)&lt;br /&gt;
; &amp;lt;tt&amp;gt;ZOID_JOB_ID&amp;lt;/tt&amp;gt;&lt;br /&gt;
: BG/P control system job id ('''Note:''' this is generally different from the Cobalt job ID; see [[FAQ#How to obtain a Cobalt job ID|FAQ]] for the latter),&lt;br /&gt;
; &amp;lt;tt&amp;gt;ZOID_JOB_GLOBAL_SIZE&amp;lt;/tt&amp;gt;&lt;br /&gt;
: the number of processes in the job (the size of &amp;lt;tt&amp;gt;MPI_COMM_WORLD&amp;lt;/tt&amp;gt;),&lt;br /&gt;
; &amp;lt;tt&amp;gt;ZOID_JOB_LOCAL_SIZE&amp;lt;/tt&amp;gt;&lt;br /&gt;
: the number of job processes handled by this I/O node,&lt;br /&gt;
; &amp;lt;tt&amp;gt;ZOID_JOB_MODE&amp;lt;/tt&amp;gt;&lt;br /&gt;
: &amp;lt;tt&amp;gt;0&amp;lt;/tt&amp;gt; for SMP, &amp;lt;tt&amp;gt;1&amp;lt;/tt&amp;gt; for VN, and &amp;lt;tt&amp;gt;2&amp;lt;/tt&amp;gt; for DUAL,&lt;br /&gt;
; &amp;lt;tt&amp;gt;SHELL&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;PATH&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;USER&amp;lt;/tt&amp;gt;, and &amp;lt;tt&amp;gt;HOME&amp;lt;/tt&amp;gt;&lt;br /&gt;
: will also be set...&lt;br /&gt;
&lt;br /&gt;
'''Notes:'''&lt;br /&gt;
* The user script is invoked ''synchronously'' by the daemon, i.e., the job will not start running until the script terminates.  If one needs some processes to run on the I/O nodes while the job is running, they should be started in the background (&amp;amp;amp;).&lt;br /&gt;
* For this feature to work, [[#The /bin.rd/update_passwd_file.sh file|update_passwd_file.sh]] must be working correctly.&lt;br /&gt;
&lt;br /&gt;
===File broadcast===&lt;br /&gt;
A &amp;lt;tt&amp;gt;/bin.rd/f2cn&amp;lt;/tt&amp;gt; command is available on the I/O nodes for a very efficient (hardware-assisted) broadcasting of files to all the compute nodes handled by the given I/O node.&lt;br /&gt;
&lt;br /&gt;
The command takes two arguments:&lt;br /&gt;
* absolute pathname to the input file on the I/O node,&lt;br /&gt;
* absolute pathname to the output file on the compute nodes.&lt;br /&gt;
&lt;br /&gt;
The input file does not need to be physically on the I/O node; it can be on a network filesystem mounted on the node.  The file will be created in the ramdisk of each compute node.&lt;br /&gt;
&lt;br /&gt;
The throughput is in practice limited by how fast the input file can be read; we have seen results in excess of 300&amp;amp;nbsp;MB/s for files residing in the I/O node ramdisk.&lt;br /&gt;
&lt;br /&gt;
'''Note:''' all the compute nodes in the pset must be up and running.  Do not use this command on ''incomplete'' partitions (e.g., a one-process job on a 64-node partition); this will likely hang the ZOID daemon.&lt;br /&gt;
&lt;br /&gt;
'''Note2:''' this feature can safely be used from within a [[#User script|user script]], so one can, e.g., pre-stage large binaries, like this:&lt;br /&gt;
&lt;br /&gt;
User script (&amp;lt;tt&amp;gt;$HOME/zoid-user-script.sh&amp;lt;/tt&amp;gt;):&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
#!/bin/sh&lt;br /&gt;
&lt;br /&gt;
if [ &amp;quot;$1&amp;quot; -eq &amp;quot;1&amp;quot; ]; then&lt;br /&gt;
    /bin.rd/f2cn $HOME/large_binary /tmp/large_binary&lt;br /&gt;
fi&lt;br /&gt;
exit 0&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Job script (submitted using Cobalt or mpirun):&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
#!/bin/sh&lt;br /&gt;
&lt;br /&gt;
chmod 755 /tmp/large_binary&lt;br /&gt;
/tmp/large_binary&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Performance counters===&lt;br /&gt;
&lt;br /&gt;
A &amp;lt;tt&amp;gt;/bin.rd/statquery&amp;lt;/tt&amp;gt; command is available on the I/O nodes for obtaining the performance counters of the I/O daemon.&lt;br /&gt;
&lt;br /&gt;
The command takes a single optional argument:&lt;br /&gt;
* the interval between successive queries, in seconds.&lt;br /&gt;
&lt;br /&gt;
If the argument is not provided, the command will terminate after the first query.&lt;br /&gt;
&lt;br /&gt;
Here is a sample output generated:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
Timestamp:                      1240439085.688831&lt;br /&gt;
Total messages sent:            5767&lt;br /&gt;
Total bytes sent:               7619170&lt;br /&gt;
Total messages received:        5717&lt;br /&gt;
Total bytes received:           72575&lt;br /&gt;
IP fwd messages sent:           196&lt;br /&gt;
IP fwd bytes sent:              5889&lt;br /&gt;
IP fwd messages received:       84&lt;br /&gt;
IP fwd bytes received:          6453&lt;br /&gt;
Stream messages sent:           65&lt;br /&gt;
Stream bytes sent:              520&lt;br /&gt;
Stream messages received:       65&lt;br /&gt;
Stream bytes received:          1416&lt;br /&gt;
Broadcast messages sent:        1&lt;br /&gt;
Broadcast bytes sent:           2437906&lt;br /&gt;
Internal messages sent:         193&lt;br /&gt;
Internal bytes sent:            39524&lt;br /&gt;
Internal messages received:     256&lt;br /&gt;
Internal bytes received:        1792&lt;br /&gt;
Plugin 5 messages sent:         0&lt;br /&gt;
Plugin 5 bytes sent:            0&lt;br /&gt;
Plugin 5 messages received:     0&lt;br /&gt;
Plugin 5 bytes received:        0&lt;br /&gt;
Plugin 2 messages sent:         5312&lt;br /&gt;
Plugin 2 bytes sent:            5135331&lt;br /&gt;
Plugin 2 messages received:     5312&lt;br /&gt;
Plugin 2 bytes received:        62914&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The meaning of the fields is as follows:&lt;br /&gt;
; Timestamp&lt;br /&gt;
: number of seconds and microseconds from the epoch, as returned by &amp;lt;tt&amp;gt;gettimeofday(2)&amp;lt;/tt&amp;gt;,&lt;br /&gt;
; IP fwd&lt;br /&gt;
: IP packet forwarding between compute nodes and I/O nodes,&lt;br /&gt;
; Stream&lt;br /&gt;
: &amp;lt;tt&amp;gt;stdin&amp;lt;/tt&amp;gt;/&amp;lt;tt&amp;gt;out&amp;lt;/tt&amp;gt;/&amp;lt;tt&amp;gt;err&amp;lt;/tt&amp;gt; streams,&lt;br /&gt;
; Broadcast&lt;br /&gt;
: [[#File broadcast|file broadcasts]],&lt;br /&gt;
; Internal&lt;br /&gt;
: job control messages, etc.&lt;br /&gt;
; Plugin 5&lt;br /&gt;
: internal &amp;lt;tt&amp;gt;mapping&amp;lt;/tt&amp;gt; plug-in, used by MPI,&lt;br /&gt;
; Plugin 2&lt;br /&gt;
: &amp;lt;tt&amp;gt;unix&amp;lt;/tt&amp;gt; plugin (POSIX file I/O).&lt;br /&gt;
&lt;br /&gt;
The counters are 64-bit integers, so they will take a while to overflow :-).&lt;br /&gt;
&lt;br /&gt;
Example user script (&amp;lt;tt&amp;gt;$HOME/zoid-user-script.sh&amp;lt;/tt&amp;gt;) that samples the statistics every 60 seconds and writes them to a unique file:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
#!/bin/sh&lt;br /&gt;
&lt;br /&gt;
if [ &amp;quot;$1&amp;quot; -eq &amp;quot;1&amp;quot; ]; then&lt;br /&gt;
    /bin.rd/statquery 60 &amp;gt;$HOME/zoid_stats.$ZOID_JOB_ID.`hostname` &amp;amp;&lt;br /&gt;
fi&lt;br /&gt;
exit 0&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Administrator interface==&lt;br /&gt;
&lt;br /&gt;
===Configuration file===&lt;br /&gt;
&lt;br /&gt;
The &amp;lt;tt&amp;gt;zoid&amp;lt;/tt&amp;gt; I/O daemon accepts a number of command-line options that can be used to change its behavior.  They can be adjusted by editing the &amp;lt;tt&amp;gt;ramdisk/ION/ramdisk-add/etc/sysconfig/zoid&amp;lt;/tt&amp;gt; file and rebuilding the I/O node ramdisk:&lt;br /&gt;
&lt;br /&gt;
; &amp;lt;span id=&amp;quot;opt_buffer_size&amp;quot;&amp;gt;ZOID_BUFFER_SIZE (-b)&amp;lt;/span&amp;gt;&lt;br /&gt;
: Specifies the size of the buffers used for messages.  Because a separate buffer is needed for a request and a reply, and typically no more than one of these needs to be large, to save memory ZOID supports buffers of two sizes: a small one (4&amp;amp;nbsp;KB by default) and a large one (4&amp;amp;nbsp;MB+1&amp;amp;nbsp;KB by default &amp;amp;#8211; the 1&amp;amp;nbsp;KB is there to accommodate the headers).  Use a colon (&amp;lt;tt&amp;gt;:&amp;lt;/tt&amp;gt;) to separate the two sizes when customizing this value.  If desired, support for second buffer size can be disabled by providing only one value to this option.&lt;br /&gt;
; ZOID_ACK_THRESHOLD (-a)&lt;br /&gt;
: Specifies a size threshold for the rendezvous protocol for messages coming from the compute nodes, in the units of tree network packets (240 bytes of data each).  An eager protocol is used for messages below the threshold.  Messages above the threshold use flow control in the form of a rendezvous protocol with message acknowledgements; basically, the daemon will only receive one large message at a time, which improves the predictability and an overall throughput.  The daemon default for this option is to not use the acknowledgements, but the config file defaults to a value of &amp;lt;tt&amp;gt;8&amp;lt;/tt&amp;gt;, which is the size of the hardware FIFO buffer of the tree network device.  Set this option to 0 (or comment it out altogether) to disable message acknowledgements.&lt;br /&gt;
; &amp;lt;span id=&amp;quot;opt_modules&amp;quot;&amp;gt;ZOID_MODULES (-m)&amp;lt;/span&amp;gt;&lt;br /&gt;
: Specifies a &amp;lt;tt&amp;gt;:&amp;lt;/tt&amp;gt;-separated list of ZOID plug-ins to load.  This defaults to &amp;lt;tt&amp;gt;&amp;quot;unix_impl.so:unix_preload.so:mapping_impl.so:mapping_preload.so&amp;quot;&amp;lt;/tt&amp;gt; in the config file; do not remove any of these or basic system services will stop working.  The &amp;lt;tt&amp;gt;unix&amp;lt;/tt&amp;gt; plug-in provides POSIX file I/O support, while &amp;lt;tt&amp;gt;mapping&amp;lt;/tt&amp;gt; is used by our MPI implementation to map between MPI ranks and Blue Gene X/Y/Z/T coordinates.  Custom plug-ins can be created and added here; see [[#Programmer interface|Programmer interface]] for details.&lt;br /&gt;
; &amp;lt;span id=&amp;quot;opt_enable_nat&amp;quot;&amp;gt;ZOID_ENABLE_NAT (-n)&amp;lt;/span&amp;gt;&lt;br /&gt;
: Enables network address translatation (NAT) for IP packets coming from the compute nodes, allowing compute nodes to communicate with the outside world.  This support is disabled by default because it was found to have a detrimental effect on the overall performance of the TCP/IP stack on the I/O nodes, slowing down network filesystems.  This feature can also be enabled on a per-job basis by setting the &amp;lt;tt&amp;gt;ZOID_ENABLE_NAT&amp;lt;/tt&amp;gt; environment variable when submitting a job (see the [[FAQ#How to open a socket from a CN to the outside world|FAQ]]).&lt;br /&gt;
; &amp;lt;span id=&amp;quot;opt_user_script&amp;quot;&amp;gt;ZOID_USER_SCRIPT (-u)&amp;lt;/span&amp;gt;&lt;br /&gt;
: Specifies the pathname to the [[#User script|user script]]; it defaults to &amp;lt;tt&amp;gt;&amp;quot;/bin.rd/zoid-user-script.sh&amp;quot;&amp;lt;/tt&amp;gt;.  This script can be found in &amp;lt;tt&amp;gt;ramdisk/ION/ramdisk-add/bin/zoid-user-script.sh&amp;lt;/tt&amp;gt;; it sets a few environment variables and then invokes user's custom &amp;lt;tt&amp;gt;$HOME/zoid-user-script.sh&amp;lt;/tt&amp;gt;.  Hence, to adjust the behavior of this feature, either change this option or the script in the ramdisk.&amp;lt;br/&amp;gt;'''Note:''' to be able to invoke a script from user's home directory, [[#The /bin.rd/update_passwd_file.sh file|update_passwd_file.sh]] must be working correctly.&lt;br /&gt;
&lt;br /&gt;
===The /bin.rd/update_passwd_file.sh file===&lt;br /&gt;
&lt;br /&gt;
Allowing the partition owner to log into the I/O node using SSH is one of the features of the ZeptoOS software stack.  Only the administrator and the partition owner are given login access; this is controlled by the &amp;lt;tt&amp;gt;/bin.rd/update_passwd_file.sh&amp;lt;/tt&amp;gt; script, which is invoked by the daemon while the partition is being initialized.  The script can be found in &amp;lt;tt&amp;gt;ramdisk/ION/ramdisk-add/bin/update_passwd_file.sh&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
The script makes a number of assumptions that could be site-specific, so it might require an adjustment.  The daemon invokes the script passing a numerical UNIX user ID of the partition owner as the only argument.  The script then scans the &amp;lt;tt&amp;gt;/bgsys/iofs/etc/passwd&amp;lt;/tt&amp;gt; for an entry with the same user ID (on Argonne machines, this file contains all valid account names).  If a matching entry is found, it is appended to the &amp;lt;tt&amp;gt;/etc/passwd&amp;lt;/tt&amp;gt; file in the I/O node ramdisk, thus enabling login access to the node for that user.&lt;br /&gt;
&lt;br /&gt;
If allowing ordinary users access to the I/O nodes is undesirable, one can simply put &amp;lt;tt&amp;gt;exit 0&amp;lt;/tt&amp;gt; at the top of the script to disable it.&lt;br /&gt;
&lt;br /&gt;
===The /bin.rd/nat file===&lt;br /&gt;
&lt;br /&gt;
If NAT has been [[#opt_enable_nat|requested]], the daemon invokes the &amp;lt;tt&amp;gt;/bin.rd/nat&amp;lt;/tt&amp;gt; script to enabled it.  This script can be found in &amp;lt;tt&amp;gt;ramdisk/ION/ramdisk-add/bin/nat&amp;lt;/tt&amp;gt;.  Generally, it should not require any modifications.&lt;br /&gt;
&lt;br /&gt;
==Programmer interface==&lt;br /&gt;
&lt;br /&gt;
ZOID is a flexible, extensible, high-performance function call forwarding (RPC) infrastructure.  Built-in features and the standard plug-ins provide familiar POSIX file I/O and BSD socket interfaces, but, because of the number of software layers involved, they introduce a significant overhead.  For applications requiring maximum bandwidth between the compute and I/O nodes, ZOID provides an option of a customized function call forwarding with minimal overheads.  This section provides an overview of how to create such custom plug-ins.&lt;br /&gt;
&lt;br /&gt;
===Overview===&lt;br /&gt;
&lt;br /&gt;
All that ZOID provides is a function call forwarding support, and a limited one at that.  Any logic (caching, prefetching, etc.) needs to be custom-built on top of it.&lt;br /&gt;
&lt;br /&gt;
Follow existing plug-ins, found in &amp;lt;tt&amp;gt;packages/zoid/src/&amp;lt;/tt&amp;gt;, as examples.  The &amp;lt;tt&amp;gt;unix&amp;lt;/tt&amp;gt; plug-in is generally the most up to date, but other plug-ins such as &amp;lt;tt&amp;gt;mapping&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;zoidfs&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;barrier&amp;lt;/tt&amp;gt;, and &amp;lt;tt&amp;gt;test&amp;lt;/tt&amp;gt; should also be fine.&lt;br /&gt;
&lt;br /&gt;
A plug-in consists of automatically generated client-side and server-side stubs (which perform the marshalling and demarshalling of function call parameters and results, the forwarding of the function call, etc.), and of a hand-written server-side implementation which provides the implementation code for the forwarded function calls.  One might also decide to provide hand-written client-side wrappers to hide some details of the ZOID API (such as the error handling) or to adhere to a particular existing API, as is the case with the &amp;lt;tt&amp;gt;unix&amp;lt;/tt&amp;gt; plug-in (the wrappers used by the FUSE client are available in &amp;lt;tt&amp;gt;packages/zoid/src/unix/stubs/&amp;lt;/tt&amp;gt;; another version is in the GNU libc sources, in &amp;lt;tt&amp;gt;packages/glibc/src/zoid/sysdeps/unix/sysv/linux/powerpc/powerpc32/&amp;lt;/tt&amp;gt;).&lt;br /&gt;
&lt;br /&gt;
The &amp;lt;tt&amp;gt;scanner.pl&amp;lt;/tt&amp;gt; script, found in &amp;lt;tt&amp;gt;packages/zoid/src/&amp;lt;/tt&amp;gt;, creates the automatically-generated client and server stubs based on a hand-written input header file described below.  Again, please follow the examples from the existing plug-ins, such as &amp;lt;tt&amp;gt;unix&amp;lt;/tt&amp;gt; or &amp;lt;tt&amp;gt;mapping&amp;lt;/tt&amp;gt;.  The &amp;lt;tt&amp;gt;Makefile&amp;lt;/tt&amp;gt; in those plug-ins is written in a generic fashion and should only require a change to the &amp;lt;tt&amp;gt;PREFIX&amp;lt;/tt&amp;gt; line to be usable with another plug-in.  Use that &amp;lt;tt&amp;gt;Makefile&amp;lt;/tt&amp;gt; to invoke the &amp;lt;tt&amp;gt;scanner.pl&amp;lt;/tt&amp;gt; script and to compile the generated source files.&lt;br /&gt;
&lt;br /&gt;
===Input header file===&lt;br /&gt;
&lt;br /&gt;
The input header file must be a valid C header file with additional hints in the comments.  The file is read by the &amp;lt;tt&amp;gt;scanner.pl&amp;lt;/tt&amp;gt; script.&lt;br /&gt;
&lt;br /&gt;
The parser in the script is rather limited and does not handle many C constructs.  It is thus essential that the header file be as simple as possible.  In particular, function prototypes should be specified at the end of the file, not intermixed with any other specifications such as data type definitions.&lt;br /&gt;
&lt;br /&gt;
Ordinary comments are best placed on separate lines.&lt;br /&gt;
&lt;br /&gt;
'''Note:''' the parser is case ''sensitive''.&lt;br /&gt;
&lt;br /&gt;
====Start line====&lt;br /&gt;
&lt;br /&gt;
Any complex declarations that the scanner cannot parse should be placed at the top of the file, because the parser ignores everything until it encounters the following magic start line:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
/* START-ZOID-SCANNER ID=&amp;lt;n&amp;gt; INIT=&amp;lt;s1&amp;gt; FINI=&amp;lt;s2&amp;gt; PROC=&amp;lt;s3&amp;gt; */&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
; ID=&amp;lt;n&amp;gt;&lt;br /&gt;
: Each plug-in needs a unique, 16-bit identifier, passed in &amp;lt;tt&amp;gt;&amp;lt;n&amp;gt;&amp;lt;/tt&amp;gt;.  The following identifiers are already in use: &amp;lt;tt&amp;gt;0&amp;lt;/tt&amp;gt; (internal), &amp;lt;tt&amp;gt;1&amp;lt;/tt&amp;gt; (&amp;lt;tt&amp;gt;zoidfs&amp;lt;/tt&amp;gt; plug-in), &amp;lt;tt&amp;gt;2&amp;lt;/tt&amp;gt; (&amp;lt;tt&amp;gt;unix&amp;lt;/tt&amp;gt;), &amp;lt;tt&amp;gt;3&amp;lt;/tt&amp;gt; (&amp;lt;tt&amp;gt;lofar&amp;lt;/tt&amp;gt;), &amp;lt;tt&amp;gt;4&amp;lt;/tt&amp;gt; (&amp;lt;tt&amp;gt;test&amp;lt;/tt&amp;gt;), &amp;lt;tt&amp;gt;5&amp;lt;/tt&amp;gt; (&amp;lt;tt&amp;gt;mapping&amp;lt;/tt&amp;gt;), and &amp;lt;tt&amp;gt;10&amp;lt;/tt&amp;gt; (&amp;lt;tt&amp;gt;ftb&amp;lt;/tt&amp;gt;).&lt;br /&gt;
; INIT=&amp;lt;s1&amp;gt;&lt;br /&gt;
: &amp;lt;tt&amp;gt;&amp;lt;s1&amp;gt;&amp;lt;/tt&amp;gt; provides the name of an initialization function which will be invoked before a job starts running; see [[#Start-line functions|Start-line functions]] for more information.  If a plug-in does not need this feature, please specify &amp;lt;tt&amp;gt;INIT=NULL&amp;lt;/tt&amp;gt;.&lt;br /&gt;
; FINI=&amp;lt;s2&amp;gt;&lt;br /&gt;
: &amp;lt;tt&amp;gt;&amp;lt;s2&amp;gt;&amp;lt;/tt&amp;gt; provides the name of a termination function which will be invoked after all job processes have exited; see [[#Start-line functions|Start-line functions]] for more information.  If a plug-in does not need this feature, please specify &amp;lt;tt&amp;gt;FINI=NULL&amp;lt;/tt&amp;gt;.&lt;br /&gt;
; PROC=&amp;lt;s3&amp;gt;&lt;br /&gt;
: &amp;lt;tt&amp;gt;&amp;lt;s3&amp;gt;&amp;lt;/tt&amp;gt; provides the name of a callback function which will be invoked on a startup and termination of every application and ZOID-enabled process; see [[#Start-line functions|Start-line functions]] for more information.  If a plug-in does not need this feature, please specify &amp;lt;tt&amp;gt;PROC=NULL&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
====Argument hints====&lt;br /&gt;
&lt;br /&gt;
Hints are generally needed by the scanner to correctly encode and decode function arguments.  They need to be placed after each argument, before a separating comma (or a closing bracket), and should be embedded inside dedicated C comments.  Multiple hints per argument are usually provided; these are separated by a colon (&amp;lt;tt&amp;gt;:&amp;lt;/tt&amp;gt;). The following hints are currently defined:&lt;br /&gt;
&lt;br /&gt;
; in, out, inout&lt;br /&gt;
: Specifies whether the argument is an input argument, an output argument, or both.  &amp;lt;tt&amp;gt;in&amp;lt;/tt&amp;gt; is the default.&lt;br /&gt;
; obj, str, ptr, arr, arr2d&lt;br /&gt;
: Specifies the type of the argument, respectively a plain object (say, an &amp;lt;tt&amp;gt;int&amp;lt;/tt&amp;gt;, or a structure passed by value), a &amp;lt;tt&amp;gt;'\0'&amp;lt;/tt&amp;gt;-terminated character string, a pointer to a plain object, an array of objects, or a two-dimensional array (&amp;lt;tt&amp;gt;type**&amp;lt;/tt&amp;gt;, not &amp;lt;tt&amp;gt;type[][]&amp;lt;/tt&amp;gt;).  &amp;lt;tt&amp;gt;obj&amp;lt;/tt&amp;gt; is the default.&lt;br /&gt;
; size&lt;br /&gt;
: Required for array arguments (&amp;lt;tt&amp;gt;arr&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;arr2d&amp;lt;/tt&amp;gt;).  Indicates the index of another argument in the same function, which is used to pass the array size.  Absolute numbers are accepted (&amp;lt;tt&amp;gt;1&amp;lt;/tt&amp;gt; to ''number of arguments'') or relative ones (&amp;lt;tt&amp;gt;+1&amp;lt;/tt&amp;gt; for the next argument, &amp;lt;tt&amp;gt;-1&amp;lt;/tt&amp;gt; for the previous argument, etc).&amp;lt;br/&amp;gt;  For &amp;lt;tt&amp;gt;arr&amp;lt;/tt&amp;gt; arguments, the size argument must be of a numerical type, or a pointer to such a type.  For &amp;lt;tt&amp;gt;arr2d&amp;lt;/tt&amp;gt; arguments, the size argument must itself be an array (an &amp;lt;tt&amp;gt;arr&amp;lt;/tt&amp;gt; argument) of numerical elements, specifying the sizes along the less significant dimension of the array (the size of the more significant dimension is the size of the &amp;lt;tt&amp;gt;arr&amp;lt;/tt&amp;gt; array itself).&amp;lt;br/&amp;gt;  Please note that the unit of size for the numerical types is the size of the base array type (thus, &amp;lt;tt&amp;gt;sizeof(int)&amp;lt;/tt&amp;gt; for an array of &amp;lt;tt&amp;gt;int&amp;lt;/tt&amp;gt;s), not byte (if one would like it to be byte, just make the array argument have type &amp;lt;tt&amp;gt;char*&amp;lt;/tt&amp;gt; or &amp;lt;tt&amp;gt;void*&amp;lt;/tt&amp;gt; (a GCC extension)).&lt;br /&gt;
; nullok&lt;br /&gt;
: An option for arguments passed by pointer (basically, all but &amp;lt;tt&amp;gt;obj&amp;lt;/tt&amp;gt;).  If provided, it indicates that the argument is allowed to be &amp;lt;tt&amp;gt;NULL&amp;lt;/tt&amp;gt;.  This is not the default because supporting &amp;lt;tt&amp;gt;NULL&amp;lt;/tt&amp;gt; pointers results in an additional computational and protocol overhead.  '''Note:''' if a &amp;lt;tt&amp;gt;NULL&amp;lt;/tt&amp;gt; pointer is passed to an argument that lacks the &amp;lt;tt&amp;gt;nullok&amp;lt;/tt&amp;gt; flag, the client ''will'' crash.&lt;br /&gt;
; zerocopy&lt;br /&gt;
: An option for array arguments.  Enables a more efficient marshalling/demarshalling protocol for the array, which does not use extra memory copies.  Can be used for no more than one &amp;lt;tt&amp;gt;in&amp;lt;/tt&amp;gt; argument and no more than one &amp;lt;tt&amp;gt;out&amp;lt;/tt&amp;gt; argument.  [[#Zerocopy performance|Zerocopy performance]] discusses performance considerations when using this option.&lt;br /&gt;
; userbuf&lt;br /&gt;
: An option for &amp;lt;tt&amp;gt;zerocopy&amp;lt;/tt&amp;gt;; only supported for &amp;lt;tt&amp;gt;arr&amp;lt;/tt&amp;gt; arguments.  Enables a special form of zero-copy support, discussed in [[#Zerocopy with a custom output buffer|Zerocopy with a custom output buffer]] and [[#Zerocopy with a custom input buffer|Zerocopy with a custom input buffer]].&lt;br /&gt;
&lt;br /&gt;
Here is an example function prototype with the hints:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
int zoidfs_readlink(const zoidfs_handle_t * handle /* in:ptr */,&lt;br /&gt;
                    char * buffer /* out:arr:size=+1 */,&lt;br /&gt;
                    size_t buffer_length /* in:obj */);&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
====Limitations====&lt;br /&gt;
&lt;br /&gt;
As indicated earlier, the scanner is limited, so keep the prototypes simple.&lt;br /&gt;
&lt;br /&gt;
Return type of a forwarded function must be scalar or &amp;lt;tt&amp;gt;void&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Structures with pointer fields inside of them cannot be forwarded.&lt;br /&gt;
&lt;br /&gt;
====Generated files====&lt;br /&gt;
&lt;br /&gt;
For every function prototype found, the scanner generates two output files: one for a client calling the function and one for the server, where the function is in fact executed.  Code in the generated files performs marshalling and demarshalling of function arguments and results.&lt;br /&gt;
&lt;br /&gt;
Two more files per plug-in are generated: ''header''&amp;lt;tt&amp;gt;_defs.h&amp;lt;/tt&amp;gt; and ''header''&amp;lt;tt&amp;gt;_dispatch.c&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
None of the generated files should be modified.&lt;br /&gt;
&lt;br /&gt;
===Server-side API===&lt;br /&gt;
&lt;br /&gt;
Server-side stubs and the server-side implementation need to be passed as modules when invoking the ZOID I/O daemon, as described [[#opt_modules|earlier]].&lt;br /&gt;
&lt;br /&gt;
The hand-written server-side implementation code should include the &amp;lt;tt&amp;gt;zoid_api.h&amp;lt;/tt&amp;gt; header file (available from &amp;lt;tt&amp;gt;packages/zoid/prebuilt/&amp;lt;/tt&amp;gt;) and the plug-in input header file.&lt;br /&gt;
&lt;br /&gt;
All the functions listed in the header file need to be defined in the server-side implementation code.  The code needs to be compiled as a shared library; use the &amp;lt;tt&amp;gt;implementation/&amp;lt;/tt&amp;gt; subdirectory of the &amp;lt;tt&amp;gt;unix&amp;lt;/tt&amp;gt; plug-in as an example.  Please note that since ZOID is multi-threaded, multiple functions can be invoked at the same time, so one must ensure that the implementation is multi-thread-safe.&lt;br /&gt;
&lt;br /&gt;
====Start-line functions====&lt;br /&gt;
&lt;br /&gt;
The following [[#Start line|start-line]] functions can be defined:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
void INIT(int pset_mpi_proc_count, int argc, int envc, const char* argenv);&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The INIT function is invoked during initialization, right before a job starts running.  Arguments:&lt;br /&gt;
&lt;br /&gt;
; pset_mpi_proc_count&lt;br /&gt;
: The number of job processes that will be handled by this I/O node.  Note that I/O nodes also handle additional ZOID-enabled processes, such as the FUSE clients, which are not included in this number.&lt;br /&gt;
; argc&lt;br /&gt;
: The number of command-line arguments plus one.&lt;br /&gt;
; envc&lt;br /&gt;
: The number of environment variables.&lt;br /&gt;
; argenv&lt;br /&gt;
: An array of &amp;lt;tt&amp;gt;'\0'&amp;lt;/tt&amp;gt;-terminated strings, one after another.  The first string is the name of the job executable, followed by &amp;lt;tt&amp;gt;argc-1&amp;lt;/tt&amp;gt; command-line arguments, followed by &amp;lt;tt&amp;gt;envc&amp;lt;/tt&amp;gt; environment variables.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
void FINI(void);&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The FINI function is invoked after the last process of the job has terminated.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
void PROC(int added, int pset_pid);&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The PROC function is invoked on the startup and termination of every application and ZOID-enabled process on the compute node.  Arguments:&lt;br /&gt;
&lt;br /&gt;
; added&lt;br /&gt;
: &amp;lt;tt&amp;gt;1&amp;lt;/tt&amp;gt; if the process was started, &amp;lt;tt&amp;gt;0&amp;lt;/tt&amp;gt; if it was terminated.&lt;br /&gt;
; pset_pid&lt;br /&gt;
: A process identifier (as returned by [[#Implementation functions|&amp;lt;tt&amp;gt;__zoid_calling_process_id&amp;lt;/tt&amp;gt;]]).&lt;br /&gt;
&lt;br /&gt;
====Implementation functions====&lt;br /&gt;
&lt;br /&gt;
The hand-written server-side implementation functions can themselves call back a few ZOID functions, available by including the &amp;lt;tt&amp;gt;zoid_api.h&amp;lt;/tt&amp;gt; header file:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
int __zoid_calling_process_id(void);&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This function returns a unique identifier of the compute node process that invoked the function.  The identifier is ''not'' an MPI rank, because some processes, such as the FUSE clients, are not part of the application and hence do not have a rank.  The identifiers are only unique within one I/O node, and they can be reused if a process starts after another one has terminated.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
void __zoid_register_userbuf(void* userbuf,&lt;br /&gt;
                             void (*callback)(void* userbuf, void* priv),&lt;br /&gt;
                             void* priv);&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This function will be discussed in [[#Zerocopy with a custom output buffer|Zerocopy with a custom output buffer]].&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
int __zoid_send_output(int pid, int fd, const char* buffer, int len);&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This function writes an arbitrary string to the job's standard output or error.  Arguments:&lt;br /&gt;
&lt;br /&gt;
; pid&lt;br /&gt;
: Process identifier as returned by &amp;lt;tt&amp;gt;__zoid_calling_process_id&amp;lt;/tt&amp;gt;.  The process in question ''must'' have an MPI rank, meaning that it must be either an application process or a process launched from an application process.&lt;br /&gt;
; fd&lt;br /&gt;
: &amp;lt;tt&amp;gt;1&amp;lt;/tt&amp;gt; for standard output, &amp;lt;tt&amp;gt;2&amp;lt;/tt&amp;gt; for standard error.&lt;br /&gt;
; buffer, len&lt;br /&gt;
: The string and its length.  &amp;lt;tt&amp;gt;'\0'&amp;lt;/tt&amp;gt; should not be included in &amp;lt;tt&amp;gt;len&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;buffer&amp;lt;/tt&amp;gt; does not need to be &amp;lt;tt&amp;gt;'\0'&amp;lt;/tt&amp;gt;-terminated.&lt;br /&gt;
&lt;br /&gt;
The function returns 0 if successful, and -1 if not (such as when the process identified by &amp;lt;tt&amp;gt;pid&amp;lt;/tt&amp;gt; does not have an MPI rank).&lt;br /&gt;
&lt;br /&gt;
===Client-side API===&lt;br /&gt;
&lt;br /&gt;
A compute node application needs to be linked with the client-side stubs and with a common support library &amp;lt;tt&amp;gt;libzoid_cn.a&amp;lt;/tt&amp;gt; (a prebuilt version of the latter is in &amp;lt;tt&amp;gt;packages/zoid/prebuilt&amp;lt;/tt&amp;gt;; sources are in &amp;lt;tt&amp;gt;packages/zoid/src/cnl/client&amp;lt;/tt&amp;gt;).  Several functions are available to applications by including the &amp;lt;tt&amp;gt;zoid_api.h&amp;lt;/tt&amp;gt; header file:&lt;br /&gt;
&lt;br /&gt;
====Initialization====&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
int __zoid_init(void);&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This function ''must'' be invoked before any ZOID or ZOID-forwarded functions can be invoked.  It returns &amp;lt;tt&amp;gt;0&amp;lt;/tt&amp;gt; if successful, &amp;lt;tt&amp;gt;1&amp;lt;/tt&amp;gt; otherwise.  There is no corresponding termination function.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
int __zoid_job_size(void);&lt;br /&gt;
int __zoid_my_rank(void);&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
These functions return, respectively, the number of processes in the job (the size of &amp;lt;tt&amp;gt;MPI_COMM_WORLD&amp;lt;/tt&amp;gt;), and the MPI rank of the&lt;br /&gt;
current process.  Either will return &amp;lt;tt&amp;gt;-1&amp;lt;/tt&amp;gt; if the current process does not have an MPI rank, i.e., if it is not an application process and was not launched from an application process (say, if it was launched from an interactive shell).&lt;br /&gt;
&lt;br /&gt;
====Error conditions====&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
int __zoid_error(void);&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This function should be invoked on the client side after ''every'' forwarded function call returns, to determine if any errors occured within the forwarding layer.  A return value of &amp;lt;tt&amp;gt;0&amp;lt;/tt&amp;gt; indicates a success; otherwise, one of the following error values will be returned:&lt;br /&gt;
&lt;br /&gt;
; ENOSYS&lt;br /&gt;
: Invalid command sent from the client.  Typically indicates that the corresponding I/O-node-side [[#opt_modules|modules]] have not been loaded.&lt;br /&gt;
; ENOMEM&lt;br /&gt;
: Out of memory condition.&lt;br /&gt;
; E2BIG&lt;br /&gt;
: Message exceeded the internal size limit.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
int __zoid_excessive_size(void);&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
If &amp;lt;tt&amp;gt;__zoid_error&amp;lt;/tt&amp;gt; returned &amp;lt;tt&amp;gt;E2BIG&amp;lt;/tt&amp;gt;, calling this function will provide an indication of by how many bytes the input or output was too large.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;span id=&amp;quot;size_restrictions&amp;quot;&amp;gt;ZOID&amp;lt;/span&amp;gt; [[#opt_buffer_size|has a limit]] on the message size, around 4&amp;amp;nbsp;MB by default.  The limit is enforced on both input and output.  The limit only applies to buffers &amp;quot;owned&amp;quot; by ZOID on the daemon side; it does not apply to custom [[#Zerocopy with a custom input buffer|input]] or [[#Zerocopy with a custom output buffer|output]] buffers.&lt;br /&gt;
&lt;br /&gt;
If the limit is hit, the operation needs to be split into smaller ones.  Information returned by &amp;lt;tt&amp;gt;__zoid_excessive_size&amp;lt;/tt&amp;gt; makes it easy to adjust the buffer and resubmit.&lt;br /&gt;
&lt;br /&gt;
'''Note:''' While the input-side (argument) overflow is flagged immediately on the client side, and is thus fairly cheap to hit, the output-side (result) overflow is flagged on the I/O node, after the request has been sent there (but before the implementation function is invoked).  It is thus advised to cache at least the size limit for the output side for the next invocation, to avoid a future communication overhead.  The size limit is function-specific, since it depends on sizes of other arguments and results.&lt;br /&gt;
&lt;br /&gt;
Here is an example of how the client-side convenience wrapper for a call such as POSIX &amp;lt;tt&amp;gt;read&amp;lt;/tt&amp;gt; could be implemented:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
ssize_t read(int fd, void *buf, size_t nbytes)&lt;br /&gt;
{&lt;br /&gt;
    static ssize_t max_read_nbytes = -1;&lt;br /&gt;
    ssize_t bytes_read;&lt;br /&gt;
&lt;br /&gt;
    bytes_read = 0;&lt;br /&gt;
    do&lt;br /&gt;
    {&lt;br /&gt;
        ssize_t toread, justread;&lt;br /&gt;
        int error;&lt;br /&gt;
&lt;br /&gt;
        toread = nbytes - bytes_read;&lt;br /&gt;
&lt;br /&gt;
        if (max_read_nbytes != -1 &amp;amp;&amp;amp; toread &amp;gt; max_read_nbytes)&lt;br /&gt;
            toread = max_read_nbytes;&lt;br /&gt;
&lt;br /&gt;
        /* unix_read is the forwarded function call.  */&lt;br /&gt;
        justread = unix_read(fd, buf + bytes_read, toread);&lt;br /&gt;
&lt;br /&gt;
        if ((error = __zoid_error()))&lt;br /&gt;
        {&lt;br /&gt;
            if (error != E2BIG)&lt;br /&gt;
            {&lt;br /&gt;
                /* For a generic ZOID error, just bail out.  */&lt;br /&gt;
                errno = error;&lt;br /&gt;
                return -1;&lt;br /&gt;
            }&lt;br /&gt;
&lt;br /&gt;
            /* We tried to send a too large read request.  Adjust.  */&lt;br /&gt;
            max_read_nbytes = toread - __zoid_excessive_size();&lt;br /&gt;
        }&lt;br /&gt;
        else&lt;br /&gt;
        {&lt;br /&gt;
            if (justread &amp;lt; 0)&lt;br /&gt;
            {&lt;br /&gt;
                /* For a generic read() error, just bail out.&lt;br /&gt;
                   In case of an I/O error, unix_read returns -errno.  */&lt;br /&gt;
                errno = -justread;&lt;br /&gt;
                return -1;&lt;br /&gt;
            }&lt;br /&gt;
&lt;br /&gt;
            bytes_read += justread;&lt;br /&gt;
&lt;br /&gt;
            if (justread != toread)&lt;br /&gt;
                /* unix_read as such succeeded, but it read fewer bytes than&lt;br /&gt;
                   expected.  We terminate prematurely then.  */&lt;br /&gt;
                break;&lt;br /&gt;
        }&lt;br /&gt;
    } while (bytes_read &amp;lt; nbytes);&lt;br /&gt;
&lt;br /&gt;
    return bytes_read;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Additional considerations===&lt;br /&gt;
&lt;br /&gt;
====Forwarding &amp;lt;tt&amp;gt;errno&amp;lt;/tt&amp;gt;====&lt;br /&gt;
&lt;br /&gt;
If one needs to pass a variable such as &amp;lt;tt&amp;gt;errno&amp;lt;/tt&amp;gt; from the I/O node to the client, the most straightforward way is to add an extra integer &amp;lt;tt&amp;gt;out&amp;lt;/tt&amp;gt; pointer argument to all functions and pass it that way.  Another option is to do it the same way the UNIX kernel does: pass it as a negative return value from the functions.  The &amp;lt;tt&amp;gt;unix&amp;lt;/tt&amp;gt; plug-in does it that way, so, e.g., the implementation of &amp;lt;tt&amp;gt;close&amp;lt;/tt&amp;gt; on the I/O node looks something like this:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
if (close(server_fd) == -1)&lt;br /&gt;
    return -errno;&lt;br /&gt;
else&lt;br /&gt;
    return 0;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Then, on the client side, we have a convenience wrapper:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
int close(int fd)&lt;br /&gt;
{&lt;br /&gt;
    return unix_decode_result(unix_close(fd));&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;unix_decode_result&amp;lt;/tt&amp;gt; is a preprocessor macro that handles both ZOID errors and errors returned by the plug-in.  It uses a number of GCC extensions to make it as transparent as possible:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
#define unix_decode_result(result)      \&lt;br /&gt;
({                                      \&lt;br /&gt;
    typeof (result) _result = (result); \&lt;br /&gt;
    int _n;                             \&lt;br /&gt;
    if ((_n = __zoid_error()) != 0)     \&lt;br /&gt;
    {                                   \&lt;br /&gt;
        errno = _n;                     \&lt;br /&gt;
        _result = -1;                   \&lt;br /&gt;
    }                                   \&lt;br /&gt;
    else if (_result &amp;lt; 0)               \&lt;br /&gt;
    {                                   \&lt;br /&gt;
        errno = -_result;               \&lt;br /&gt;
        _result = -1;                   \&lt;br /&gt;
    }                                   \&lt;br /&gt;
    _result;                            \&lt;br /&gt;
})&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
====Returning variable amounts of data in arrays====&lt;br /&gt;
&lt;br /&gt;
Just like with UNIX system calls, ZOID does not allocate memory for the results.  Instead, callers must provide pre-allocated arrays, along with their sizes.  UNIX would then typically return the size of the used part as a return value from a system call.  Unfortunately, ZOID cannot make use of that &amp;amp;#8211; it will use the same array size argument to determine how much data to send back, so even if only a small part of the provided buffer is actually filled in, the whole buffer will be sent back, which is inefficient.  This can be prevented by passing the array size as an &amp;lt;tt&amp;gt;inout&amp;lt;/tt&amp;gt; pointer to a numerical type.  A server-side implementation of a function such as &amp;lt;tt&amp;gt;read&amp;lt;/tt&amp;gt; then looks like this:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
ssize_t unix_read(int fd /* in:obj */,&lt;br /&gt;
                  void *buf /* out:arr:size=+1 */,&lt;br /&gt;
                  size_t *count /* inout:ptr */)&lt;br /&gt;
{&lt;br /&gt;
    ssize_t ret;&lt;br /&gt;
&lt;br /&gt;
    ...&lt;br /&gt;
&lt;br /&gt;
    if ((ret = read(fd, buf, *count)) == -1)&lt;br /&gt;
    {&lt;br /&gt;
        *count = 0;&lt;br /&gt;
        return -errno;&lt;br /&gt;
    }&lt;br /&gt;
    else&lt;br /&gt;
    {&lt;br /&gt;
        *count = ret;&lt;br /&gt;
        return ret;&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Obviously, the client side needs to be modified as well, to pass the size argument by address.&lt;br /&gt;
&lt;br /&gt;
'''Note:''' this feature has certain implementation limitations.  It can misbehave in the presence of multiple output arrays (or a single output &amp;lt;tt&amp;gt;arr2d&amp;lt;/tt&amp;gt;, which internally behaves a lot like multiple separate &amp;lt;tt&amp;gt;arr&amp;lt;/tt&amp;gt;s).  Essentially, for efficiency reasons, the placement of arrays in the result buffer is determined before an implementation function is invoked.  If this feature is used to change the size of one array, and that array is followed in the output buffer by another array, a &amp;quot;hole&amp;quot; will be created in the buffer, causing problems.  However, in the most common case of a single output array the feature is completely reliable.&lt;br /&gt;
&lt;br /&gt;
====Zerocopy performance====&lt;br /&gt;
&lt;br /&gt;
Implementation-wise, ZOID is always zero-copy on the server side, meaning that data that implementation functions put in the &amp;lt;tt&amp;gt;out&amp;lt;/tt&amp;gt; arrays is sent to the compute nodes without any extra memory copies.&lt;br /&gt;
&lt;br /&gt;
Client side is only zero-copy for arrays that use the &amp;lt;tt&amp;gt;zerocopy&amp;lt;/tt&amp;gt; flag in the header file.  Because of the additial protocol overheads that &amp;lt;tt&amp;gt;zerocopy&amp;lt;/tt&amp;gt; introduces, it should be used only for potentially large memory buffers, such as the buffers of file I/O &amp;lt;tt&amp;gt;read&amp;lt;/tt&amp;gt; or &amp;lt;tt&amp;gt;write&amp;lt;/tt&amp;gt; calls.&lt;br /&gt;
&lt;br /&gt;
'''Note:''' for maximum performance, the arrays passed as &amp;lt;tt&amp;gt;zerocopy&amp;lt;/tt&amp;gt; arguments on the compute nodes must be aligned in memory to the 16-bytes boundary; otherwise, an interim buffer will be used.  The memory allocation routines such as &amp;lt;tt&amp;gt;malloc&amp;lt;/tt&amp;gt; have been modified to align memory to that boundary.  If there is a danger that the user code might pass a large unaligned buffer, and the semantics will not be affected, it makes sense to write code that detects insufficient alignment and splits the operation in two: a small unaligned one (say, up to 240 bytes &amp;amp;#8211; the data payload of a single packet on the tree network), followed by a larger, properly aligned one.&lt;br /&gt;
&lt;br /&gt;
====Zerocopy with a custom output buffer====&lt;br /&gt;
&lt;br /&gt;
Normally, memory for output arrays to be filled in by server-side implementation functions is allocated by the ZOID daemon.  This might be inconvenient when the data to be filled arrives asynchronously, possibly before the implementation function is even invoked; in such situations, an interim memory buffer must be used, forcing an extra memory copy.&lt;br /&gt;
&lt;br /&gt;
This extra copy can be avoided for &amp;lt;tt&amp;gt;zerocopy&amp;lt;/tt&amp;gt; output &amp;lt;tt&amp;gt;arr&amp;lt;/tt&amp;gt; types if the &amp;lt;tt&amp;gt;userbuf&amp;lt;/tt&amp;gt; flag has been used.  No space will then be preallocated by the daemon for the array (the server-side stub will pass a &amp;lt;tt&amp;gt;NULL&amp;lt;/tt&amp;gt; pointer); instead, the implementation function must provide the daemon with its own buffer.  It can do it by calling:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
void __zoid_register_userbuf(void* userbuf,&lt;br /&gt;
                             void (*callback)(void* userbuf, void* priv),&lt;br /&gt;
                             void* priv);&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Arguments:&lt;br /&gt;
&lt;br /&gt;
; userbuf&lt;br /&gt;
: The address of the buffer.&lt;br /&gt;
; callback&lt;br /&gt;
: A callback function that is invoked by the daemon when the buffer has been sent to the client and is thus no longer needed.  &amp;lt;tt&amp;gt;userbuf&amp;lt;/tt&amp;gt; is passed as the first argument to the callback.  It is safe for the callback to invoke &amp;lt;tt&amp;gt;__zoid_calling_process_id&amp;lt;/tt&amp;gt;, if desired.&lt;br /&gt;
; priv&lt;br /&gt;
: A private data passed as the second argument to the &amp;lt;tt&amp;gt;callback&amp;lt;/tt&amp;gt;.  It is not interpreted by ZOID in any way.&lt;br /&gt;
&lt;br /&gt;
The size of the provided buffer is determined like for any other array argument: the maximum value is provided by the client via the &amp;lt;tt&amp;gt;size&amp;lt;/tt&amp;gt; argument.  The server-side implementation part may choose to return less than the maximum amount, as explained [[#Returning variable amounts of data in arrays|earlier]].&lt;br /&gt;
&lt;br /&gt;
As in other zero-copy cases, for maximum performance, the buffer provided must be aligned in memory to the 16-bytes boundary; otherwise, an interim buffer will be used.  The memory allocation routines such as &amp;lt;tt&amp;gt;malloc&amp;lt;/tt&amp;gt; have been modified to align memory to that boundary, but we recommend explicitly calling &amp;lt;tt&amp;gt;posix_memalign&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
'''Note:''' because the buffer provided is ''not'' allocated by ZOID, message size restrictions discussed [[#size_restrictions|earlier]] do not apply to it.  Please do not abuse this capability.  There is a good reason for the message size limit: it is there so that the maximum amount of memory required by the ZOID daemon stays limited.  Too many too large user-allocated buffers might result in an out-of-memory condition on the I/O node.&lt;br /&gt;
&lt;br /&gt;
We provide a simple example below.  It is a little artificial in the sense that the buffer is allocated within the implementation function; as we indicated, this feature is most likely to be useful with buffers allocated outside of the implementation functions:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
static void buffer_cb(void* userbuf, void* priv)&lt;br /&gt;
{&lt;br /&gt;
    free(userbuf);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
ssize_t unix_read(int fd /* in:obj */,&lt;br /&gt;
                  void *buf /* out:arr:size=+1:zerocopy:userbuf */,&lt;br /&gt;
                  size_t *count /* inout:ptr */)&lt;br /&gt;
{&lt;br /&gt;
    ssize_t ret;&lt;br /&gt;
&lt;br /&gt;
    ...&lt;br /&gt;
&lt;br /&gt;
    if (posix_memalign(&amp;amp;buf, 16, *count))&lt;br /&gt;
    {&lt;br /&gt;
        *count = 0;&lt;br /&gt;
        return -ENOMEM;&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    __zoid_register_userbuf(buf, &amp;amp;buffer_cb, NULL);&lt;br /&gt;
&lt;br /&gt;
    if ((ret = read(fd, buf, *count)) == -1)&lt;br /&gt;
    {&lt;br /&gt;
        *count = 0;&lt;br /&gt;
        return -errno;&lt;br /&gt;
    }&lt;br /&gt;
    else&lt;br /&gt;
    {&lt;br /&gt;
        *count = ret;&lt;br /&gt;
        return ret;&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
====Zerocopy with a custom input buffer====&lt;br /&gt;
&lt;br /&gt;
The &amp;lt;tt&amp;gt;userbuf&amp;lt;/tt&amp;gt; flag discussed above can also be used for ''input'' &amp;lt;tt&amp;gt;zerocopy&amp;lt;/tt&amp;gt; &amp;lt;tt&amp;gt;arr&amp;lt;/tt&amp;gt; arguments.  This could be useful to avoid extra memory copies if the data in the array will be needed after the implementation function has returned.&lt;br /&gt;
&lt;br /&gt;
If the flag is used, the daemon will not allocate the memory for the array; instead, in the middle of receiving the request from the client, it will call an allocation routine from the server-side implementation code.  The name of the allocation routine is the name of the function that uses the input &amp;lt;tt&amp;gt;userbuf&amp;lt;/tt&amp;gt; argument, with &amp;lt;tt&amp;gt;_allocate_cb&amp;lt;/tt&amp;gt; suffix attached to it.  Its prototype needs to be as follows:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
void* &amp;lt;name&amp;gt;_allocate_cb(int len);&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The single argument passed by the daemon is the length of the array in bytes.  The routine must return a pointer to a buffer of that size or &amp;lt;tt&amp;gt;NULL&amp;lt;/tt&amp;gt; if that is not possible (in which case, the function will fail and &amp;lt;tt&amp;gt;__zoid_error&amp;lt;/tt&amp;gt; on the client side will return &amp;lt;tt&amp;gt;ENOMEM&amp;lt;/tt&amp;gt;).&lt;br /&gt;
&lt;br /&gt;
There is a restriction on the type of the array: its base type must have a size of one byte, so the array should be of type &amp;lt;tt&amp;gt;char*&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;unsigned char*&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;void*&amp;lt;/tt&amp;gt; (a GCC extension), etc.&lt;br /&gt;
&lt;br /&gt;
The allocation routine is invoked in the same context as ordinary implementation functions.  It may block if it so desires; this will block the compute node client that invoked the routine, but all other clients can keep communicating with the server, thanks to its multi-threaded architecture.&lt;br /&gt;
&lt;br /&gt;
Once the allocation routine has returned and a complete request has been received by the daemon, the implementation function is invoked as usual, with a correct address of the input &amp;lt;tt&amp;gt;userbuf&amp;lt;/tt&amp;gt; array.  It is the responsibility of the plug-in implementer to release the memory occupied by that array when it is no longer needed.&lt;br /&gt;
&lt;br /&gt;
As with other user-level callbacks, the allocation routine may call &amp;lt;tt&amp;gt;__zoid_calling_process_id&amp;lt;/tt&amp;gt; to learn which client process sent the request.  Also, as in other zero-copy cases, for maximum performance, the buffer provided must be aligned in memory to the 16-bytes boundary; otherwise, an interim buffer will be used.  The memory allocation routines such as &amp;lt;tt&amp;gt;malloc&amp;lt;/tt&amp;gt; have been modified to align memory to that boundary, but we recommend explicitly calling &amp;lt;tt&amp;gt;posix_memalign&amp;lt;/tt&amp;gt;.  Finally, as with output &amp;lt;tt&amp;gt;userbuf&amp;lt;/tt&amp;gt;, message size restrictions discussed [[#size_restrictions|earlier]] do not apply to the user-allocated buffers.  Please do not abuse this capability.  There is a good reason for the message size limit: it is there so that the maximum amount of memory required by the ZOID daemon stays limited.  Too many too large user-allocated buffers might result in an out-of-memory condition on the I/O node.&lt;br /&gt;
&lt;br /&gt;
Under rare circumstances, input &amp;lt;tt&amp;gt;userbuf&amp;lt;/tt&amp;gt; could result in memory leaks.  For this to take place, the job would have to be interrupted after the allocation routine has been run, but before the implementation function is called.  This could only cause problems if I/O nodes are not rebooted between jobs.  Those concerned about this scenario can eliminate the leak by adding necessary memory release code to the [[#Start-line functions|FINI]] function.&lt;br /&gt;
&lt;br /&gt;
A simple example:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
void* unix_write_allocate_cb(int len)&lt;br /&gt;
{&lt;br /&gt;
    void* ptr;&lt;br /&gt;
&lt;br /&gt;
    if (posix_memalign(&amp;amp;ptr, 16, len))&lt;br /&gt;
        return NULL;&lt;br /&gt;
&lt;br /&gt;
    return ptr;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
ssize_t unix_write(int fd /* in:obj */,&lt;br /&gt;
                   const void *buf /* in:arr:size=+1:zerocopy:userbuf */,&lt;br /&gt;
                   size_t count /* in:obj */)&lt;br /&gt;
{&lt;br /&gt;
    ssize_t ret;&lt;br /&gt;
&lt;br /&gt;
    ...&lt;br /&gt;
&lt;br /&gt;
    if ((ret = write(fd, buf, count)) == -1)&lt;br /&gt;
        ret = -errno;&lt;br /&gt;
&lt;br /&gt;
    free((void*)buf);&lt;br /&gt;
&lt;br /&gt;
    return ret;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
[[Ramdisk]] | [[ZeptoOS_Documentation|Top]] | [[(K)TAU]]&lt;/div&gt;</summary>
		<author><name>Iskra</name></author>
	</entry>
	<entry>
		<id> /zeptoos/index.php?title=ZOID&amp;diff=610</id>
		<title>ZOID</title>
		<link rel="alternate" type="text/html" href=" /zeptoos/index.php?title=ZOID&amp;diff=610"/>
		<updated>2009-05-08T23:04:29Z</updated>

		<summary type="html">&lt;p&gt;Iskra: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;[[Ramdisk]] | [[ZeptoOS_Documentation|Top]] | [[(K)TAU]]&lt;br /&gt;
----&lt;br /&gt;
&lt;br /&gt;
==Introduction==&lt;br /&gt;
&lt;br /&gt;
ZOID is an I/O forwarding component of the ZeptoOS project.  Any communication between the compute nodes and the I/O nodes (job management, file I/O, sockets) is handled by ZOID.&lt;br /&gt;
&lt;br /&gt;
ZOID infrastructure consists of:&lt;br /&gt;
* A multithreaded &amp;lt;tt&amp;gt;zoid&amp;lt;/tt&amp;gt; daemon on the I/O nodes which performs I/O forwarding for the compute nodes and which also communicates with the service node to perform job management,&lt;br /&gt;
* &amp;lt;tt&amp;gt;control&amp;lt;/tt&amp;gt; daemon on the compute nodes which is responsible for job management tasks such as the launching of application processes, for the forwarding of &amp;lt;tt&amp;gt;stdin&amp;lt;/tt&amp;gt;/&amp;lt;tt&amp;gt;out&amp;lt;/tt&amp;gt;/&amp;lt;tt&amp;gt;err&amp;lt;/tt&amp;gt; data, and for the forwarding of IP packets,&lt;br /&gt;
* &amp;lt;tt&amp;gt;zoid-fuse&amp;lt;/tt&amp;gt; daemon on the compute nodes which performs file I/O forwarding for POSIX-compliant applications.&lt;br /&gt;
&lt;br /&gt;
==User interface==&lt;br /&gt;
&lt;br /&gt;
ZOID is meant to be transparent to users, but there are a few optional mechanisms available to interact with it.&lt;br /&gt;
&lt;br /&gt;
===User script===&lt;br /&gt;
&lt;br /&gt;
Right before a job starts running, and right after the last process of a job has terminated, ZOID daemon attempts to invoke a ''user script'' on I/O nodes.  By default, the daemon invokes &amp;lt;tt&amp;gt;$HOME/zoid-user-script.sh&amp;lt;/tt&amp;gt; (this pathname can be [[#opt_user_script|changed]] by an administrator).  A single parameter is passed to the script: &amp;lt;tt&amp;gt;1&amp;lt;/tt&amp;gt; at the job startup, and &amp;lt;tt&amp;gt;0&amp;lt;/tt&amp;gt; at the termination.&lt;br /&gt;
&lt;br /&gt;
Information about the job will be passed to the script in the following environment variables:&lt;br /&gt;
; &amp;lt;tt&amp;gt;ZOID_JOB_EXEC&amp;lt;/tt&amp;gt;&lt;br /&gt;
: name of the job executable,&lt;br /&gt;
; &amp;lt;tt&amp;gt;ZOID_JOB_ARGS&amp;lt;/tt&amp;gt;&lt;br /&gt;
: job arguments, separated by colons (&amp;lt;tt&amp;gt;:&amp;lt;/tt&amp;gt;)&lt;br /&gt;
; &amp;lt;tt&amp;gt;ZOID_JOB_ENV&amp;lt;/tt&amp;gt;&lt;br /&gt;
: job environment variables, separated by colons (&amp;lt;tt&amp;gt;:&amp;lt;/tt&amp;gt;)&lt;br /&gt;
; &amp;lt;tt&amp;gt;ZOID_JOB_ID&amp;lt;/tt&amp;gt;&lt;br /&gt;
: BG/P control system job id ('''Note:''' this is generally different from the Cobalt job ID; see [[FAQ#How to obtain a Cobalt job ID|FAQ]] for the latter),&lt;br /&gt;
; &amp;lt;tt&amp;gt;ZOID_JOB_GLOBAL_SIZE&amp;lt;/tt&amp;gt;&lt;br /&gt;
: the number of processes in the job (the size of &amp;lt;tt&amp;gt;MPI_COMM_WORLD&amp;lt;/tt&amp;gt;),&lt;br /&gt;
; &amp;lt;tt&amp;gt;ZOID_JOB_LOCAL_SIZE&amp;lt;/tt&amp;gt;&lt;br /&gt;
: the number of job processes handled by this I/O node,&lt;br /&gt;
; &amp;lt;tt&amp;gt;ZOID_JOB_MODE&amp;lt;/tt&amp;gt;&lt;br /&gt;
: &amp;lt;tt&amp;gt;0&amp;lt;/tt&amp;gt; for SMP, &amp;lt;tt&amp;gt;1&amp;lt;/tt&amp;gt; for VN, and &amp;lt;tt&amp;gt;2&amp;lt;/tt&amp;gt; for DUAL,&lt;br /&gt;
; &amp;lt;tt&amp;gt;SHELL&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;PATH&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;USER&amp;lt;/tt&amp;gt;, and &amp;lt;tt&amp;gt;HOME&amp;lt;/tt&amp;gt;&lt;br /&gt;
: will also be set...&lt;br /&gt;
&lt;br /&gt;
'''Notes:'''&lt;br /&gt;
* The user script is invoked ''synchronously'' by the daemon, i.e., the job will not start running until the script terminates.  If one needs some processes to run on the I/O nodes while the job is running, they should be started in the background (&amp;amp;amp;).&lt;br /&gt;
* For this feature to work, [[#The /bin.rd/update_passwd_file.sh file|update_passwd_file.sh]] must be working correctly.&lt;br /&gt;
&lt;br /&gt;
===File broadcast===&lt;br /&gt;
A &amp;lt;tt&amp;gt;/bin.rd/f2cn&amp;lt;/tt&amp;gt; command is available on the I/O nodes for a very efficient (hardware-assisted) broadcasting of files to all the compute nodes handled by the given I/O node.&lt;br /&gt;
&lt;br /&gt;
The command takes two arguments:&lt;br /&gt;
* absolute pathname to the input file on the I/O node,&lt;br /&gt;
* absolute pathname to the output file on the compute nodes.&lt;br /&gt;
&lt;br /&gt;
The input file does not need to be physically on the I/O node; it can be on a network filesystem mounted on the node.  The file will be created in the ramdisk of each compute node.&lt;br /&gt;
&lt;br /&gt;
The throughput is in practice limited by how fast the input file can be read; we have seen results in excess of 300&amp;amp;nbsp;MB/s for files residing in the I/O node ramdisk.&lt;br /&gt;
&lt;br /&gt;
'''Note:''' all the compute nodes in the pset must be up and running.  Do not use this command on ''incomplete'' partitions (e.g., a one-process job on a 64-node partition); this will likely hang the ZOID daemon.&lt;br /&gt;
&lt;br /&gt;
'''Note2:''' this feature can safely be used from within a [[#User script|user script]], so one can, e.g., pre-stage large binaries, like this:&lt;br /&gt;
&lt;br /&gt;
User script (&amp;lt;tt&amp;gt;$HOME/zoid-user-script.sh&amp;lt;/tt&amp;gt;):&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
#!/bin/sh&lt;br /&gt;
&lt;br /&gt;
if [ &amp;quot;$1&amp;quot; -eq &amp;quot;1&amp;quot; ]; then&lt;br /&gt;
    /bin.rd/f2cn $HOME/large_binary /tmp/large_binary&lt;br /&gt;
fi&lt;br /&gt;
exit 0&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Job script (submitted using Cobalt or mpirun):&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
#!/bin/sh&lt;br /&gt;
&lt;br /&gt;
chmod 755 /tmp/large_binary&lt;br /&gt;
/tmp/large_binary&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Performance counters===&lt;br /&gt;
&lt;br /&gt;
A &amp;lt;tt&amp;gt;/bin.rd/statquery&amp;lt;/tt&amp;gt; command is available on the I/O nodes for obtaining the performance counters of the I/O daemon.&lt;br /&gt;
&lt;br /&gt;
The command takes a single optional argument:&lt;br /&gt;
* the interval between successive queries, in seconds.&lt;br /&gt;
&lt;br /&gt;
If the argument is not provided, the command will terminate after the first query.&lt;br /&gt;
&lt;br /&gt;
Here is a sample output generated:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
Timestamp:                      1240439085.688831&lt;br /&gt;
Total messages sent:            5767&lt;br /&gt;
Total bytes sent:               7619170&lt;br /&gt;
Total messages received:        5717&lt;br /&gt;
Total bytes received:           72575&lt;br /&gt;
IP fwd messages sent:           196&lt;br /&gt;
IP fwd bytes sent:              5889&lt;br /&gt;
IP fwd messages received:       84&lt;br /&gt;
IP fwd bytes received:          6453&lt;br /&gt;
Stream messages sent:           65&lt;br /&gt;
Stream bytes sent:              520&lt;br /&gt;
Stream messages received:       65&lt;br /&gt;
Stream bytes received:          1416&lt;br /&gt;
Broadcast messages sent:        1&lt;br /&gt;
Broadcast bytes sent:           2437906&lt;br /&gt;
Internal messages sent:         193&lt;br /&gt;
Internal bytes sent:            39524&lt;br /&gt;
Internal messages received:     256&lt;br /&gt;
Internal bytes received:        1792&lt;br /&gt;
Plugin 5 messages sent:         0&lt;br /&gt;
Plugin 5 bytes sent:            0&lt;br /&gt;
Plugin 5 messages received:     0&lt;br /&gt;
Plugin 5 bytes received:        0&lt;br /&gt;
Plugin 2 messages sent:         5312&lt;br /&gt;
Plugin 2 bytes sent:            5135331&lt;br /&gt;
Plugin 2 messages received:     5312&lt;br /&gt;
Plugin 2 bytes received:        62914&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The meaning of the fields is as follows:&lt;br /&gt;
; Timestamp&lt;br /&gt;
: number of seconds and microseconds from the epoch, as returned by &amp;lt;tt&amp;gt;gettimeofday(2)&amp;lt;/tt&amp;gt;,&lt;br /&gt;
; IP fwd&lt;br /&gt;
: IP packet forwarding between compute nodes and I/O nodes,&lt;br /&gt;
; Stream&lt;br /&gt;
: &amp;lt;tt&amp;gt;stdin&amp;lt;/tt&amp;gt;/&amp;lt;tt&amp;gt;out&amp;lt;/tt&amp;gt;/&amp;lt;tt&amp;gt;err&amp;lt;/tt&amp;gt; streams,&lt;br /&gt;
; Broadcast&lt;br /&gt;
: [[#File broadcast|file broadcasts]],&lt;br /&gt;
; Internal&lt;br /&gt;
: job control messages, etc.&lt;br /&gt;
; Plugin 5&lt;br /&gt;
: internal &amp;lt;tt&amp;gt;mapping&amp;lt;/tt&amp;gt; plug-in, used by MPI,&lt;br /&gt;
; Plugin 2&lt;br /&gt;
: &amp;lt;tt&amp;gt;unix&amp;lt;/tt&amp;gt; plugin (POSIX file I/O).&lt;br /&gt;
&lt;br /&gt;
The counters are 64-bit integers, so they will take a while to overflow :-).&lt;br /&gt;
&lt;br /&gt;
Example user script (&amp;lt;tt&amp;gt;$HOME/zoid-user-script.sh&amp;lt;/tt&amp;gt;) that samples the statistics every 60 seconds and writes them to a unique file:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
#!/bin/sh&lt;br /&gt;
&lt;br /&gt;
if [ &amp;quot;$1&amp;quot; -eq &amp;quot;1&amp;quot; ]; then&lt;br /&gt;
    /bin.rd/statquery 60 &amp;gt;$HOME/zoid_stats.$ZOID_JOB_ID.`hostname` &amp;amp;&lt;br /&gt;
fi&lt;br /&gt;
exit 0&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Administrator interface==&lt;br /&gt;
&lt;br /&gt;
===Configuration file===&lt;br /&gt;
&lt;br /&gt;
The &amp;lt;tt&amp;gt;zoid&amp;lt;/tt&amp;gt; I/O daemon accepts a number of command-line options that can be used to change its behavior.  They can be adjusted by editing the &amp;lt;tt&amp;gt;ramdisk/ION/ramdisk-add/etc/sysconfig/zoid&amp;lt;/tt&amp;gt; file and rebuilding the I/O node ramdisk:&lt;br /&gt;
&lt;br /&gt;
; &amp;lt;span id=&amp;quot;opt_buffer_size&amp;quot;&amp;gt;ZOID_BUFFER_SIZE (-b)&amp;lt;/span&amp;gt;&lt;br /&gt;
: Specifies the size of the buffers used for messages.  Because a separate buffer is needed for a request and a reply, and typically no more than one of these needs to be large, to save memory ZOID supports buffers of two sizes: a small one (4&amp;amp;nbsp;KB by default) and a large one (4&amp;amp;nbsp;MB+1&amp;amp;nbsp;KB by default &amp;amp;#8211; the 1&amp;amp;nbsp;KB is there to accommodate the headers).  Use a colon (&amp;lt;tt&amp;gt;:&amp;lt;/tt&amp;gt;) to separate the two sizes when customizing this value.  If desired, support for second buffer size can be disabled by providing only one value to this option.&lt;br /&gt;
; ZOID_ACK_THRESHOLD (-a)&lt;br /&gt;
: Specifies a size threshold for the rendezvous protocol for messages coming from the compute nodes, in the units of tree network packets (240 bytes of data each).  An eager protocol is used for messages below the threshold.  Messages above the threshold use flow control in the form of a rendezvous protocol with message acknowledgements; basically, the daemon will only receive one large message at a time, which improves the predictability and an overall throughput.  The daemon default for this option is to not use the acknowledgements, but the config file defaults to a value of &amp;lt;tt&amp;gt;8&amp;lt;/tt&amp;gt;, which is the size of the hardware FIFO buffer of the tree network device.  Set this option to 0 (or comment it out altogether) to disable message acknowledgements.&lt;br /&gt;
; &amp;lt;span id=&amp;quot;opt_modules&amp;quot;&amp;gt;ZOID_MODULES (-m)&amp;lt;/span&amp;gt;&lt;br /&gt;
: Specifies a &amp;lt;tt&amp;gt;:&amp;lt;/tt&amp;gt;-separated list of ZOID plug-ins to load.  This defaults to &amp;lt;tt&amp;gt;&amp;quot;unix_impl.so:unix_preload.so:mapping_impl.so:mapping_preload.so&amp;quot;&amp;lt;/tt&amp;gt; in the config file; do not remove any of these or basic system services will stop working.  The &amp;lt;tt&amp;gt;unix&amp;lt;/tt&amp;gt; plug-in provides POSIX file I/O support, while &amp;lt;tt&amp;gt;mapping&amp;lt;/tt&amp;gt; is used by our MPI implementation to map between MPI ranks and Blue Gene X/Y/Z/T coordinates.  Custom plug-ins can be created and added here; see [[#Programmer interface|Programmer interface]] for details.&lt;br /&gt;
; &amp;lt;span id=&amp;quot;opt_enable_nat&amp;quot;&amp;gt;ZOID_ENABLE_NAT (-n)&amp;lt;/span&amp;gt;&lt;br /&gt;
: Enables network address translatation (NAT) for IP packets coming from the compute nodes, allowing compute nodes to communicate with the outside world.  This support is disabled by default because it was found to have a detrimental effect on the overall performance of the TCP/IP stack on the I/O nodes, slowing down network filesystems.  This feature can also be enabled on a per-job basis by setting the &amp;lt;tt&amp;gt;ZOID_ENABLE_NAT&amp;lt;/tt&amp;gt; environment variable when submitting a job (see the [[FAQ#How to open a socket from a CN to the outside world|FAQ]]).&lt;br /&gt;
; &amp;lt;span id=&amp;quot;opt_user_script&amp;quot;&amp;gt;ZOID_USER_SCRIPT (-u)&amp;lt;/span&amp;gt;&lt;br /&gt;
: Specifies the pathname to the [[#User script|user script]]; it defaults to &amp;lt;tt&amp;gt;&amp;quot;/bin.rd/zoid-user-script.sh&amp;quot;&amp;lt;/tt&amp;gt;.  This script can be found in &amp;lt;tt&amp;gt;ramdisk/ION/ramdisk-add/bin/zoid-user-script.sh&amp;lt;/tt&amp;gt;; it sets a few environment variables and then invokes user's custom &amp;lt;tt&amp;gt;$HOME/zoid-user-script.sh&amp;lt;/tt&amp;gt;.  Hence, to adjust the behavior of this feature, either change this option or the script in the ramdisk.&amp;lt;br/&amp;gt;'''Note:''' to be able to invoke a script from user's home directory, [[#The /bin.rd/update_passwd_file.sh file|update_passwd_file.sh]] must be working correctly.&lt;br /&gt;
&lt;br /&gt;
===The /bin.rd/update_passwd_file.sh file===&lt;br /&gt;
&lt;br /&gt;
Allowing the partition owner to log into the I/O node using SSH is one of the features of the ZeptoOS software stack.  Only the administrator and the partition owner are given login access; this is controlled by the &amp;lt;tt&amp;gt;/bin.rd/update_passwd_file.sh&amp;lt;/tt&amp;gt; script, which is invoked by the daemon while the partition is being initialized.  The script can be found in &amp;lt;tt&amp;gt;ramdisk/ION/ramdisk-add/bin/update_passwd_file.sh&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
The script makes a number of assumptions that could be site-specific, so it might require an adjustment.  The daemon invokes the script passing a numerical UNIX user ID of the partition owner as the only argument.  The script then scans the &amp;lt;tt&amp;gt;/bgsys/iofs/etc/passwd&amp;lt;/tt&amp;gt; for an entry with the same user ID (on Argonne machines, this file contains all valid account names).  If a matching entry is found, it is appended to the &amp;lt;tt&amp;gt;/etc/passwd&amp;lt;/tt&amp;gt; file in the I/O node ramdisk, thus enabling login access to the node for that user.&lt;br /&gt;
&lt;br /&gt;
If allowing ordinary users access to the I/O nodes is undesirable, one can simply put &amp;lt;tt&amp;gt;exit 0&amp;lt;/tt&amp;gt; at the top of the script to disable it.&lt;br /&gt;
&lt;br /&gt;
===The /bin.rd/nat file===&lt;br /&gt;
&lt;br /&gt;
If NAT has been [[#opt_enable_nat|requested]], the daemon invokes the &amp;lt;tt&amp;gt;/bin.rd/nat&amp;lt;/tt&amp;gt; script to enabled it.  This script can be found in &amp;lt;tt&amp;gt;ramdisk/ION/ramdisk-add/bin/nat&amp;lt;/tt&amp;gt;.  Generally, it should not require any modifications.&lt;br /&gt;
&lt;br /&gt;
==Programmer interface==&lt;br /&gt;
&lt;br /&gt;
ZOID is a flexible, extensible, high-performance function call forwarding (RPC) infrastructure.  Built-in features and the standard plug-ins provide familiar POSIX file I/O and BSD socket interfaces, but, because of the number of software layers involved, they introduce a significant overhead.  For applications requiring maximum bandwidth between the compute and I/O nodes, ZOID provides an option of a customized function call forwarding with minimal overheads.  This section provides an overview of how to create such custom plug-ins.&lt;br /&gt;
&lt;br /&gt;
===Overview===&lt;br /&gt;
&lt;br /&gt;
All that ZOID provides is a function call forwarding support, and a limited one at that.  Any logic (caching, prefetching, etc.) needs to be custom-built on top of it.&lt;br /&gt;
&lt;br /&gt;
Follow existing plug-ins, found in &amp;lt;tt&amp;gt;packages/zoid/src/&amp;lt;/tt&amp;gt;, as examples.  The &amp;lt;tt&amp;gt;unix&amp;lt;/tt&amp;gt; plug-in is generally the most up to date, but other plug-ins such as &amp;lt;tt&amp;gt;mapping&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;zoidfs&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;barrier&amp;lt;/tt&amp;gt;, and &amp;lt;tt&amp;gt;test&amp;lt;/tt&amp;gt; should also be fine.&lt;br /&gt;
&lt;br /&gt;
A plug-in consists of automatically generated client-side and server-side stubs (which perform the marshalling and demarshalling of function call parameters and results, the forwarding of the function call, etc.), and of a hand-written server-side implementation which provides the implementation code for the forwarded function calls.  One might also decide to provide hand-written client-side wrappers to hide some details of the ZOID API (such as the error handling) or to adhere to a particular existing API, as is the case with the &amp;lt;tt&amp;gt;unix&amp;lt;/tt&amp;gt; plug-in (the wrappers used by the FUSE client are available in &amp;lt;tt&amp;gt;packages/zoid/src/unix/stubs/&amp;lt;/tt&amp;gt;; another version is in the GNU libc sources, in &amp;lt;tt&amp;gt;packages/glibc/src/zoid/sysdeps/unix/sysv/linux/powerpc/powerpc32/&amp;lt;/tt&amp;gt;).&lt;br /&gt;
&lt;br /&gt;
The &amp;lt;tt&amp;gt;scanner.pl&amp;lt;/tt&amp;gt; script, found in &amp;lt;tt&amp;gt;packages/zoid/src/&amp;lt;/tt&amp;gt;, creates the automatically-generated client and server stubs based on a hand-written input header file described below.  Again, please follow the examples from the existing plug-ins, such as &amp;lt;tt&amp;gt;unix&amp;lt;/tt&amp;gt; or &amp;lt;tt&amp;gt;mapping&amp;lt;/tt&amp;gt;.  The &amp;lt;tt&amp;gt;Makefile&amp;lt;/tt&amp;gt; in those plug-ins is written in a generic fashion and should only require a change to the &amp;lt;tt&amp;gt;PREFIX&amp;lt;/tt&amp;gt; line to be usable with another plug-in.  Use that &amp;lt;tt&amp;gt;Makefile&amp;lt;/tt&amp;gt; to invoke the &amp;lt;tt&amp;gt;scanner.pl&amp;lt;/tt&amp;gt; script and to compile the generated source files.&lt;br /&gt;
&lt;br /&gt;
===Input header file===&lt;br /&gt;
&lt;br /&gt;
The input header file must be a valid C header file with additional hints in the comments.  The file is read by the &amp;lt;tt&amp;gt;scanner.pl&amp;lt;/tt&amp;gt; script.&lt;br /&gt;
&lt;br /&gt;
The parser in the script is rather limited and does not handle many C constructs.  It is thus essential that the header file be as simple as possible.  In particular, function prototypes should be specified at the end of the file, not intermixed with any other specifications such as data type definitions.&lt;br /&gt;
&lt;br /&gt;
Ordinary comments are best placed on separate lines.&lt;br /&gt;
&lt;br /&gt;
'''Note:''' the parser is case ''sensitive''.&lt;br /&gt;
&lt;br /&gt;
====Start line====&lt;br /&gt;
&lt;br /&gt;
Any complex declarations that the scanner cannot parse should be placed at the top of the file, because the parser ignores everything until it encounters the following magic start line:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
/* START-ZOID-SCANNER ID=&amp;lt;n&amp;gt; INIT=&amp;lt;s1&amp;gt; FINI=&amp;lt;s2&amp;gt; PROC=&amp;lt;s3&amp;gt; */&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
; ID=&amp;lt;n&amp;gt;&lt;br /&gt;
: Each plug-in needs a unique, 16-bit identifier, passed in &amp;lt;tt&amp;gt;&amp;lt;n&amp;gt;&amp;lt;/tt&amp;gt;.  The following identifiers are already in use: &amp;lt;tt&amp;gt;0&amp;lt;/tt&amp;gt; (internal), &amp;lt;tt&amp;gt;1&amp;lt;/tt&amp;gt; (&amp;lt;tt&amp;gt;zoidfs&amp;lt;/tt&amp;gt; plug-in), &amp;lt;tt&amp;gt;2&amp;lt;/tt&amp;gt; (&amp;lt;tt&amp;gt;unix&amp;lt;/tt&amp;gt;), &amp;lt;tt&amp;gt;3&amp;lt;/tt&amp;gt; (&amp;lt;tt&amp;gt;lofar&amp;lt;/tt&amp;gt;), &amp;lt;tt&amp;gt;4&amp;lt;/tt&amp;gt; (&amp;lt;tt&amp;gt;test&amp;lt;/tt&amp;gt;), &amp;lt;tt&amp;gt;5&amp;lt;/tt&amp;gt; (&amp;lt;tt&amp;gt;mapping&amp;lt;/tt&amp;gt;), and &amp;lt;tt&amp;gt;10&amp;lt;/tt&amp;gt; (&amp;lt;tt&amp;gt;ftb&amp;lt;/tt&amp;gt;).&lt;br /&gt;
; INIT=&amp;lt;s1&amp;gt;&lt;br /&gt;
: &amp;lt;tt&amp;gt;&amp;lt;s1&amp;gt;&amp;lt;/tt&amp;gt; provides the name of an initialization function which will be invoked before a job starts running; see [[#Start-line functions|Start-line functions]] for more information.  If a plug-in does not need this feature, please specify &amp;lt;tt&amp;gt;INIT=NULL&amp;lt;/tt&amp;gt;.&lt;br /&gt;
; FINI=&amp;lt;s2&amp;gt;&lt;br /&gt;
: &amp;lt;tt&amp;gt;&amp;lt;s2&amp;gt;&amp;lt;/tt&amp;gt; provides the name of a termination function which will be invoked after all job processes have exited; see [[#Start-line functions|Start-line functions]] for more information.  If a plug-in does not need this feature, please specify &amp;lt;tt&amp;gt;FINI=NULL&amp;lt;/tt&amp;gt;.&lt;br /&gt;
; PROC=&amp;lt;s3&amp;gt;&lt;br /&gt;
: &amp;lt;tt&amp;gt;&amp;lt;s3&amp;gt;&amp;lt;/tt&amp;gt; provides the name of a callback function which will be invoked on a startup and termination of every application and ZOID-enabled process; see [[#Start-line functions|Start-line functions]] for more information.  If a plug-in does not need this feature, please specify &amp;lt;tt&amp;gt;PROC=NULL&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
====Argument hints====&lt;br /&gt;
&lt;br /&gt;
Hints are generally needed by the scanner to correctly encode and decode function arguments.  They need to be placed after each argument, before a separating comma (or a closing bracket), and should be embedded inside dedicated C comments.  Multiple hints per argument are usually provided; these are separated by a colon (&amp;lt;tt&amp;gt;:&amp;lt;/tt&amp;gt;). The following hints are currently defined:&lt;br /&gt;
&lt;br /&gt;
; in, out, inout&lt;br /&gt;
: Specifies whether the argument is an input argument, an output argument, or both.  &amp;lt;tt&amp;gt;in&amp;lt;/tt&amp;gt; is the default.&lt;br /&gt;
; obj, str, ptr, arr, arr2d&lt;br /&gt;
: Specifies the type of the argument, respectively a plain object (say, an &amp;lt;tt&amp;gt;int&amp;lt;/tt&amp;gt;, or a structure passed by value), a &amp;lt;tt&amp;gt;'\0'&amp;lt;/tt&amp;gt;-terminated character string, a pointer to a plain object, an array of objects, or a two-dimensional array (&amp;lt;tt&amp;gt;type**&amp;lt;/tt&amp;gt;, not &amp;lt;tt&amp;gt;type[][]&amp;lt;/tt&amp;gt;).  &amp;lt;tt&amp;gt;obj&amp;lt;/tt&amp;gt; is the default.&lt;br /&gt;
; size&lt;br /&gt;
: Required for array arguments (&amp;lt;tt&amp;gt;arr&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;arr2d&amp;lt;/tt&amp;gt;).  Indicates the index of another argument in the same function, which is used to pass the array size.  Absolute numbers are accepted (&amp;lt;tt&amp;gt;1&amp;lt;/tt&amp;gt; to ''number of arguments'') or relative ones (&amp;lt;tt&amp;gt;+1&amp;lt;/tt&amp;gt; for the next argument, &amp;lt;tt&amp;gt;-1&amp;lt;/tt&amp;gt; for the previous argument, etc).&amp;lt;br/&amp;gt;  For &amp;lt;tt&amp;gt;arr&amp;lt;/tt&amp;gt; arguments, the size argument must be of a numerical type, or a pointer to such a type.  For &amp;lt;tt&amp;gt;arr2d&amp;lt;/tt&amp;gt; arguments, the size argument must itself be an array (an &amp;lt;tt&amp;gt;arr&amp;lt;/tt&amp;gt; argument) of numerical elements, specifying the sizes along the less significant dimension of the array (the size of the more significant dimension is the size of the &amp;lt;tt&amp;gt;arr&amp;lt;/tt&amp;gt; array itself).&amp;lt;br/&amp;gt;  Please note that the unit of size for the numerical types is the size of the base array type (thus, &amp;lt;tt&amp;gt;sizeof(int)&amp;lt;/tt&amp;gt; for an array of &amp;lt;tt&amp;gt;int&amp;lt;/tt&amp;gt;s), not byte (if one would like it to be byte, just make the array argument have type &amp;lt;tt&amp;gt;char*&amp;lt;/tt&amp;gt; or &amp;lt;tt&amp;gt;void*&amp;lt;/tt&amp;gt; (a GCC extension)).&lt;br /&gt;
; nullok&lt;br /&gt;
: An option for arguments passed by pointer (basically, all but &amp;lt;tt&amp;gt;obj&amp;lt;/tt&amp;gt;).  If provided, it indicates that the argument is allowed to be &amp;lt;tt&amp;gt;NULL&amp;lt;/tt&amp;gt;.  This is not the default because supporting &amp;lt;tt&amp;gt;NULL&amp;lt;/tt&amp;gt; pointers results in an additional computational and protocol overhead.  '''Note:''' if a &amp;lt;tt&amp;gt;NULL&amp;lt;/tt&amp;gt; pointer is passed to an argument that lacks the &amp;lt;tt&amp;gt;nullok&amp;lt;/tt&amp;gt; flag, the client ''will'' crash.&lt;br /&gt;
; zerocopy&lt;br /&gt;
: An option for array arguments.  Enables a more efficient marshalling/demarshalling protocol for the array, which does not use extra memory copies.  Can be used for no more than one &amp;lt;tt&amp;gt;in&amp;lt;/tt&amp;gt; argument and no more than one &amp;lt;tt&amp;gt;out&amp;lt;/tt&amp;gt; argument.  [[#Zerocopy performance|Zerocopy performance]] discusses performance considerations when using this option.&lt;br /&gt;
; userbuf&lt;br /&gt;
: An option for &amp;lt;tt&amp;gt;zerocopy&amp;lt;/tt&amp;gt;; only supported for &amp;lt;tt&amp;gt;arr&amp;lt;/tt&amp;gt; arguments.  Enables a special form of zero-copy support, discussed in [[#Zerocopy with a custom output buffer|Zerocopy with a custom output buffer]] and [[#Zerocopy with a custom input buffer|Zerocopy with a custom input buffer]].&lt;br /&gt;
&lt;br /&gt;
Here is an example function prototype with the hints:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
int zoidfs_readlink(const zoidfs_handle_t * handle /* in:ptr */,&lt;br /&gt;
                    char * buffer /* out:arr:size=+1 */,&lt;br /&gt;
                    size_t buffer_length /* in:obj */);&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
====Limitations====&lt;br /&gt;
&lt;br /&gt;
As indicated earlier, the scanner is limited, so keep the prototypes simple.&lt;br /&gt;
&lt;br /&gt;
Return type of a forwarded function must be scalar or &amp;lt;tt&amp;gt;void&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Structures with pointer fields inside of them cannot be forwarded.&lt;br /&gt;
&lt;br /&gt;
====Generated files====&lt;br /&gt;
&lt;br /&gt;
For every function prototype found, the scanner generates two output files: one for a client calling the function and one for the server, where the function is in fact executed.  Code in the generated files performs marshalling and demarshalling of function arguments and results.&lt;br /&gt;
&lt;br /&gt;
Two more files per plug-in are generated: ''header''&amp;lt;tt&amp;gt;_defs.h&amp;lt;/tt&amp;gt; and ''header''&amp;lt;tt&amp;gt;_dispatch.c&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
None of the generated files should be modified.&lt;br /&gt;
&lt;br /&gt;
===Server-side API===&lt;br /&gt;
&lt;br /&gt;
Server-side stubs and the server-side implementation need to be passed as modules when invoking the ZOID I/O daemon, as described [[#opt_modules|earlier]].&lt;br /&gt;
&lt;br /&gt;
The hand-written server-side implementation code should include the &amp;lt;tt&amp;gt;zoid_api.h&amp;lt;/tt&amp;gt; header file (available from &amp;lt;tt&amp;gt;packages/zoid/prebuilt/&amp;lt;/tt&amp;gt;) and the plug-in input header file.&lt;br /&gt;
&lt;br /&gt;
All the functions listed in the header file need to be defined in the server-side implementation code.  The code needs to be compiled as a shared library; use the &amp;lt;tt&amp;gt;implementation/&amp;lt;/tt&amp;gt; subdirectory of the &amp;lt;tt&amp;gt;unix&amp;lt;/tt&amp;gt; plug-in as an example.  Please note that since ZOID is multi-threaded, multiple functions can be invoked at the same time, so one must ensure that the implementation is multi-thread-safe.&lt;br /&gt;
&lt;br /&gt;
====Start-line functions====&lt;br /&gt;
&lt;br /&gt;
The following [[#Start line|start-line]] functions can be defined:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
void INIT(int pset_mpi_proc_count, int argc, int envc, const char* argenv);&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The INIT function is invoked during initialization, right before a job starts running.  Arguments:&lt;br /&gt;
&lt;br /&gt;
; pset_mpi_proc_count&lt;br /&gt;
: The number of job processes that will be handled by this I/O node.  Note that I/O nodes also handle additional ZOID-enabled processes, such as the FUSE clients, which are not included in this number.&lt;br /&gt;
; argc&lt;br /&gt;
: The number of command-line arguments plus one.&lt;br /&gt;
; envc&lt;br /&gt;
: The number of environment variables.&lt;br /&gt;
; argenv&lt;br /&gt;
: An array of &amp;lt;tt&amp;gt;'\0'&amp;lt;/tt&amp;gt;-terminated strings, one after another.  The first string is the name of the job executable, followed by &amp;lt;tt&amp;gt;argc-1&amp;lt;/tt&amp;gt; command-line arguments, followed by &amp;lt;tt&amp;gt;envc&amp;lt;/tt&amp;gt; environment variables.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
void FINI(void);&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The FINI function is invoked after the last process of the job has terminated.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
void PROC(int added, int pset_pid);&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The PROC function is invoked on the startup and termination of every application and ZOID-enabled process on the compute node.  Arguments:&lt;br /&gt;
&lt;br /&gt;
; added&lt;br /&gt;
: &amp;lt;tt&amp;gt;1&amp;lt;/tt&amp;gt; if the process was started, &amp;lt;tt&amp;gt;0&amp;lt;/tt&amp;gt; if it was terminated.&lt;br /&gt;
; pset_pid&lt;br /&gt;
: A process identifier (as returned by [[#Implementation functions|&amp;lt;tt&amp;gt;__zoid_calling_process_id&amp;lt;/tt&amp;gt;]]).&lt;br /&gt;
&lt;br /&gt;
====Implementation functions====&lt;br /&gt;
&lt;br /&gt;
The hand-written server-side implementation functions can themselves call back a few ZOID functions, available by including the &amp;lt;tt&amp;gt;zoid_api.h&amp;lt;/tt&amp;gt; header file:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
int __zoid_calling_process_id(void);&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This function returns a unique identifier of the compute node process that invoked the function.  The identifier is ''not'' an MPI rank, because some processes, such as the FUSE clients, are not part of the application and hence do not have a rank.  The identifiers are only unique within one I/O node, and they can be reused if a process starts after another one has terminated.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
void __zoid_register_userbuf(void* userbuf,&lt;br /&gt;
                             void (*callback)(void* userbuf, void* priv),&lt;br /&gt;
                             void* priv);&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This function will be discussed in [[#Zerocopy with a custom output buffer|Zerocopy with a custom output buffer]].&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
int __zoid_send_output(int pid, int fd, const char* buffer, int len);&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This function writes an arbitrary string to the job's standard output or error.  Arguments:&lt;br /&gt;
&lt;br /&gt;
; pid&lt;br /&gt;
: Process identifier as returned by &amp;lt;tt&amp;gt;__zoid_calling_process_id&amp;lt;/tt&amp;gt;.  The process in question ''must'' have an MPI rank, meaning that it must be either an application process or a process launched from an application process.&lt;br /&gt;
; fd&lt;br /&gt;
: &amp;lt;tt&amp;gt;1&amp;lt;/tt&amp;gt; for standard output, &amp;lt;tt&amp;gt;2&amp;lt;/tt&amp;gt; for standard error.&lt;br /&gt;
; buffer, len&lt;br /&gt;
: The string and its length.  &amp;lt;tt&amp;gt;'\0'&amp;lt;/tt&amp;gt; should not be included in &amp;lt;tt&amp;gt;len&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;buffer&amp;lt;/tt&amp;gt; does not need to be &amp;lt;tt&amp;gt;'\0'&amp;lt;/tt&amp;gt;-terminated.&lt;br /&gt;
&lt;br /&gt;
The function returns 0 if successful, and -1 if not (such as when the process identified by &amp;lt;tt&amp;gt;pid&amp;lt;/tt&amp;gt; does not have an MPI rank).&lt;br /&gt;
&lt;br /&gt;
===Client-side API===&lt;br /&gt;
&lt;br /&gt;
A compute node application needs to be linked with the client-side stubs and with a common support library &amp;lt;tt&amp;gt;libzoid_cn.a&amp;lt;/tt&amp;gt; (a prebuilt version of the latter is in &amp;lt;tt&amp;gt;packages/zoid/prebuilt&amp;lt;/tt&amp;gt;; sources are in &amp;lt;tt&amp;gt;packages/zoid/src/cnl/client&amp;lt;/tt&amp;gt;).  Several functions are available to applications by including the &amp;lt;tt&amp;gt;zoid_api.h&amp;lt;/tt&amp;gt; header file:&lt;br /&gt;
&lt;br /&gt;
====Initialization====&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
int __zoid_init(void);&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This function ''must'' be invoked before any ZOID or ZOID-forwarded functions can be invoked.  It returns &amp;lt;tt&amp;gt;0&amp;lt;/tt&amp;gt; if successful, &amp;lt;tt&amp;gt;1&amp;lt;/tt&amp;gt; otherwise.  There is no corresponding termination function.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
int __zoid_job_size(void);&lt;br /&gt;
int __zoid_my_rank(void);&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
These functions return, respectively, the number of processes in the job (the size of &amp;lt;tt&amp;gt;MPI_COMM_WORLD&amp;lt;/tt&amp;gt;), and the MPI rank of the&lt;br /&gt;
current process.  Either will return &amp;lt;tt&amp;gt;-1&amp;lt;/tt&amp;gt; if the current process does not have an MPI rank, i.e., if it is not an application process and was not launched from an application process (say, if it was launched from an interactive shell).&lt;br /&gt;
&lt;br /&gt;
====Error conditions====&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
int __zoid_error(void);&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This function should be invoked on the client side after ''every'' forwarded function call returns, to determine if any errors occured within the forwarding layer.  A return value of &amp;lt;tt&amp;gt;0&amp;lt;/tt&amp;gt; indicates a success; otherwise, one of the following error values will be returned:&lt;br /&gt;
&lt;br /&gt;
; ENOSYS&lt;br /&gt;
: Invalid command sent from the client.  Typically indicates that the corresponding I/O-node-side [[#opt_modules|modules]] have not been loaded.&lt;br /&gt;
; ENOMEM&lt;br /&gt;
: Out of memory condition.&lt;br /&gt;
; E2BIG&lt;br /&gt;
: Message exceeded the internal size limit.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
int __zoid_excessive_size(void);&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
If &amp;lt;tt&amp;gt;__zoid_error&amp;lt;/tt&amp;gt; returned &amp;lt;tt&amp;gt;E2BIG&amp;lt;/tt&amp;gt;, calling this function will provide an indication of by how many bytes the input or output was too large.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;span id=&amp;quot;size_restrictions&amp;quot;&amp;gt;ZOID&amp;lt;/span&amp;gt; [[#opt_buffer_size|has a limit]] on the message size, around 4&amp;amp;nbsp;MB by default.  The limit is enforced on both input and output.  The limit only applies to buffers &amp;quot;owned&amp;quot; by ZOID on the daemon side; it does not apply to custom [[#Zerocopy with a custom input buffer|input]] or [[#Zerocopy with a custom output buffer|output]] buffers.&lt;br /&gt;
&lt;br /&gt;
If the limit is hit, the operation needs to be split into smaller ones.  Information returned by &amp;lt;tt&amp;gt;__zoid_excessive_size&amp;lt;/tt&amp;gt; makes it easy to adjust the buffer and resubmit.&lt;br /&gt;
&lt;br /&gt;
'''Note:''' While the input-side (argument) overflow is flagged immediately on the client side, and is thus fairly cheap to hit, the output-side (result) overflow is flagged on the I/O node, after the request has been sent there (but before the implementation function is invoked).  It is thus advised to cache at least the size limit for the output side for the next invocation, to avoid a future communication overhead.  The size limit is function-specific, since it depends on sizes of other arguments and results.&lt;br /&gt;
&lt;br /&gt;
Here is an example of how the client-side convenience wrapper for a call such as POSIX &amp;lt;tt&amp;gt;read&amp;lt;/tt&amp;gt; could be implemented:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
ssize_t read(int fd, void *buf, size_t nbytes)&lt;br /&gt;
{&lt;br /&gt;
    static ssize_t max_read_nbytes = -1;&lt;br /&gt;
    ssize_t bytes_read;&lt;br /&gt;
&lt;br /&gt;
    bytes_read = 0;&lt;br /&gt;
    do&lt;br /&gt;
    {&lt;br /&gt;
        ssize_t toread, justread;&lt;br /&gt;
        int error;&lt;br /&gt;
&lt;br /&gt;
        toread = nbytes - bytes_read;&lt;br /&gt;
&lt;br /&gt;
        if (max_read_nbytes != -1 &amp;amp;&amp;amp; toread &amp;gt; max_read_nbytes)&lt;br /&gt;
            toread = max_read_nbytes;&lt;br /&gt;
&lt;br /&gt;
        /* unix_read is the forwarded function call.  */&lt;br /&gt;
        justread = unix_read(fd, buf + bytes_read, toread);&lt;br /&gt;
&lt;br /&gt;
        if ((error = __zoid_error()))&lt;br /&gt;
        {&lt;br /&gt;
            if (error != E2BIG)&lt;br /&gt;
            {&lt;br /&gt;
                /* For a generic ZOID error, just bail out.  */&lt;br /&gt;
                errno = error;&lt;br /&gt;
                return -1;&lt;br /&gt;
            }&lt;br /&gt;
&lt;br /&gt;
            /* We tried to send a too large read request.  Adjust.  */&lt;br /&gt;
            max_read_nbytes = toread - __zoid_excessive_size();&lt;br /&gt;
        }&lt;br /&gt;
        else&lt;br /&gt;
        {&lt;br /&gt;
            if (justread &amp;lt; 0)&lt;br /&gt;
            {&lt;br /&gt;
                /* For a generic read() error, just bail out.&lt;br /&gt;
                   In case of an I/O error, unix_read returns -errno.  */&lt;br /&gt;
                errno = -justread;&lt;br /&gt;
                return -1;&lt;br /&gt;
            }&lt;br /&gt;
&lt;br /&gt;
            bytes_read += justread;&lt;br /&gt;
&lt;br /&gt;
            if (justread != toread)&lt;br /&gt;
                /* unix_read as such succeeded, but it read fewer bytes than&lt;br /&gt;
                   expected.  We terminate prematurely then.  */&lt;br /&gt;
                break;&lt;br /&gt;
        }&lt;br /&gt;
    } while (bytes_read &amp;lt; nbytes);&lt;br /&gt;
&lt;br /&gt;
    return bytes_read;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Additional considerations===&lt;br /&gt;
&lt;br /&gt;
====Forwarding &amp;lt;tt&amp;gt;errno&amp;lt;/tt&amp;gt;====&lt;br /&gt;
&lt;br /&gt;
If one needs to pass a variable such as &amp;lt;tt&amp;gt;errno&amp;lt;/tt&amp;gt; from the I/O node to the client, the most straightforward way is to add an extra integer &amp;lt;tt&amp;gt;out&amp;lt;/tt&amp;gt; pointer argument to all functions and pass it that way.  Another option is to do it the same way the UNIX kernel does: pass it as a negative return value from the functions.  The &amp;lt;tt&amp;gt;unix&amp;lt;/tt&amp;gt; plug-in does it that way, so, e.g., the implementation of &amp;lt;tt&amp;gt;close&amp;lt;/tt&amp;gt; on the I/O node looks something like this:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
if (close(server_fd) == -1)&lt;br /&gt;
    return -errno;&lt;br /&gt;
else&lt;br /&gt;
    return 0;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Then, on the client side, we have a convenience wrapper:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
int close(int fd)&lt;br /&gt;
{&lt;br /&gt;
    return unix_decode_result(unix_close(fd));&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;unix_decode_result&amp;lt;/tt&amp;gt; is a preprocessor macro that handles both ZOID errors and errors returned by the plug-in.  It uses a number of GCC extensions to make it as transparent as possible:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
#define unix_decode_result(result)      \&lt;br /&gt;
({                                      \&lt;br /&gt;
    typeof (result) _result = (result); \&lt;br /&gt;
    int _n;                             \&lt;br /&gt;
    if ((_n = __zoid_error()) != 0)     \&lt;br /&gt;
    {                                   \&lt;br /&gt;
        errno = _n;                     \&lt;br /&gt;
        _result = -1;                   \&lt;br /&gt;
    }                                   \&lt;br /&gt;
    else if (_result &amp;lt; 0)               \&lt;br /&gt;
    {                                   \&lt;br /&gt;
        errno = -_result;               \&lt;br /&gt;
        _result = -1;                   \&lt;br /&gt;
    }                                   \&lt;br /&gt;
    _result;                            \&lt;br /&gt;
})&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
====Returning variable amounts of data in arrays====&lt;br /&gt;
&lt;br /&gt;
Just like with UNIX system calls, ZOID does not allocate memory for the results.  Instead, callers must provide pre-allocated arrays, along with their sizes.  UNIX would then typically return the size of the used part as a return value from a system call.  Unfortunately, ZOID cannot make use of that &amp;amp;#8211; it will use the same array size argument to determine how much data to send back, so even if only a small part of the provided buffer is actually filled in, the whole buffer will be sent back, which is inefficient.  This can be prevented by passing the array size as an &amp;lt;tt&amp;gt;inout&amp;lt;/tt&amp;gt; pointer to a numerical type.  A server-side implementation of a function such as &amp;lt;tt&amp;gt;read&amp;lt;/tt&amp;gt; then looks like this:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
ssize_t unix_read(int fd /* in:obj */,&lt;br /&gt;
                  void *buf /* out:arr:size=+1 */,&lt;br /&gt;
                  size_t *count /* inout:ptr */)&lt;br /&gt;
{&lt;br /&gt;
    ssize_t ret;&lt;br /&gt;
&lt;br /&gt;
    ...&lt;br /&gt;
&lt;br /&gt;
    if ((ret = read(fd, buf, *count)) == -1)&lt;br /&gt;
    {&lt;br /&gt;
        *count = 0;&lt;br /&gt;
        return -errno;&lt;br /&gt;
    }&lt;br /&gt;
    else&lt;br /&gt;
    {&lt;br /&gt;
        *count = ret;&lt;br /&gt;
        return ret;&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Obviously, the client side needs to be modified as well, to pass the size argument by address.&lt;br /&gt;
&lt;br /&gt;
'''Note:''' this feature has certain implementation limitations.  It can misbehave in the presence of multiple output arrays (or a single output &amp;lt;tt&amp;gt;arr2d&amp;lt;/tt&amp;gt;, which internally behaves a lot like multiple separate &amp;lt;tt&amp;gt;arr&amp;lt;/tt&amp;gt;s).  Essentially, for efficiency reasons, the placement of arrays in the result buffer is determined before an implementation function is invoked.  If this feature is used to change the size of one array, and that array is followed in the output buffer by another array, a &amp;quot;hole&amp;quot; will be created in the buffer, causing problems.  However, in the most common case of a single output array the feature is completely reliable.&lt;br /&gt;
&lt;br /&gt;
====Zerocopy performance====&lt;br /&gt;
&lt;br /&gt;
Implementation-wise, ZOID is always zero-copy on the server side, meaning that data that implementation functions put in the &amp;lt;tt&amp;gt;out&amp;lt;/tt&amp;gt; arrays is sent to the compute nodes without any extra memory copies.&lt;br /&gt;
&lt;br /&gt;
Client side is only zero-copy for arrays that use the &amp;lt;tt&amp;gt;zerocopy&amp;lt;/tt&amp;gt; flag in the header file.  Because of the additial protocol overheads that &amp;lt;tt&amp;gt;zerocopy&amp;lt;/tt&amp;gt; introduces, it should be used only for potentially large memory buffers, such as the buffers of file I/O &amp;lt;tt&amp;gt;read&amp;lt;/tt&amp;gt; or &amp;lt;tt&amp;gt;write&amp;lt;/tt&amp;gt; calls.&lt;br /&gt;
&lt;br /&gt;
'''Note:''' for maximum performance, the arrays passed as &amp;lt;tt&amp;gt;zerocopy&amp;lt;/tt&amp;gt; arguments on the compute nodes must be aligned in memory to the 16-bytes boundary; otherwise, an interim buffer will be used.  The memory allocation routines such as &amp;lt;tt&amp;gt;malloc&amp;lt;/tt&amp;gt; have been modified to align memory to that boundary.  If there is a danger that the user code might pass a large unaligned buffer, and the semantics will not be affected, it makes sense to write code that detects insufficient alignment and splits the operation in two: a small unaligned one (say, up to 240 bytes &amp;amp;#8211; the data payload of a single packet on the tree network), followed by a larger, properly aligned one.&lt;br /&gt;
&lt;br /&gt;
====Zerocopy with a custom output buffer====&lt;br /&gt;
&lt;br /&gt;
Normally, memory for output arrays to be filled in by server-side implementation functions is allocated by the ZOID daemon.  This might be inconvenient when the data to be filled arrives asynchronously, possibly before the implementation function is even invoked; in such situations, an interim memory buffer must be used, forcing an extra memory copy.&lt;br /&gt;
&lt;br /&gt;
This can be avoided for zero-copy output &amp;lt;tt&amp;gt;arr&amp;lt;/tt&amp;gt; types if the &amp;lt;tt&amp;gt;userbuf&amp;lt;/tt&amp;gt; flag has been used.  No space will then be preallocated by the daemon for the array (the server-side stub will pass a &amp;lt;tt&amp;gt;NULL&amp;lt;/tt&amp;gt; pointer); instead, the implementation function must provide the daemon with its own buffer.  It can do it by calling:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
void __zoid_register_userbuf(void* userbuf,&lt;br /&gt;
                             void (*callback)(void* userbuf, void* priv),&lt;br /&gt;
                             void* priv);&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Arguments:&lt;br /&gt;
&lt;br /&gt;
; userbuf&lt;br /&gt;
: The address of the buffer.&lt;br /&gt;
; callback&lt;br /&gt;
: A callback function that is invoked by the daemon when the buffer has been sent to the client and is thus no longer needed.  &amp;lt;tt&amp;gt;userbuf&amp;lt;/tt&amp;gt; is passed as the first argument to the callback.  It is safe for the callback to invoke &amp;lt;tt&amp;gt;__zoid_calling_process_id&amp;lt;/tt&amp;gt;.&lt;br /&gt;
; priv&lt;br /&gt;
: A private data passed as the second argument to the &amp;lt;tt&amp;gt;callback&amp;lt;/tt&amp;gt;.  It is not interpreted by ZOID in any way.&lt;br /&gt;
&lt;br /&gt;
The size of the provided buffer is determined like for any other array argument: the maximum value is provided by the client via the &amp;lt;tt&amp;gt;size&amp;lt;/tt&amp;gt; argument.  The server-side implementation part may choose to return less than the maximum amount, as explained [[#Returning variable amounts of data in arrays|earlier]].&lt;br /&gt;
&lt;br /&gt;
As in other zero-copy cases, for maximum performance, the buffer provided must be aligned in memory to the 16-bytes boundary; otherwise, an interim buffer will be used.  The memory allocation routines such as &amp;lt;tt&amp;gt;malloc&amp;lt;/tt&amp;gt; have been modified to align memory to that boundary, but we recommend explicitly calling &amp;lt;tt&amp;gt;posix_memalign&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
'''Note:''' because the buffer provided is ''not'' allocated by ZOID, message size restrictions discussed [[#size_restrictions|earlier]] do not apply to it.  Please do not abuse this capability.  There is a good reason for the message size limit: it is there so that the maximum amount of memory required by the ZOID daemon stays limited.  Too many too large user-allocated buffers might result in an out-of-memory condition on the I/O node.&lt;br /&gt;
&lt;br /&gt;
We provide a simple example below.  It is a little artificial in the sense that the buffer is allocated within the implementation function; as we indicated, this feature is most useful with buffers allocated outside of the implementation functions:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
static void buffer_cb(void* userbuf, void* priv)&lt;br /&gt;
{&lt;br /&gt;
    free(userbuf);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
ssize_t unix_read(int fd /* in:obj */,&lt;br /&gt;
                  void *buf /* out:arr:size=+1:zerocopy:userbuf */,&lt;br /&gt;
                  size_t *count /* inout:ptr */)&lt;br /&gt;
{&lt;br /&gt;
    ssize_t ret;&lt;br /&gt;
&lt;br /&gt;
    ...&lt;br /&gt;
&lt;br /&gt;
    if (posix_memalign(&amp;amp;buf, 16, *count))&lt;br /&gt;
    {&lt;br /&gt;
        *count = 0;&lt;br /&gt;
        return -ENOMEM;&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    __zoid_register_userbuf(buf, &amp;amp;buffer_cb, NULL);&lt;br /&gt;
&lt;br /&gt;
    if ((ret = read(fd, buf, *count)) == -1)&lt;br /&gt;
    {&lt;br /&gt;
        *count = 0;&lt;br /&gt;
        return -errno;&lt;br /&gt;
    }&lt;br /&gt;
    else&lt;br /&gt;
    {&lt;br /&gt;
        *count = ret;&lt;br /&gt;
        return ret;&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
====Zerocopy with a custom input buffer====&lt;br /&gt;
&lt;br /&gt;
The &amp;lt;tt&amp;gt;userbuf&amp;lt;/tt&amp;gt; flag discussed above can also be used for ''input'' zero-copy &amp;lt;tt&amp;gt;arr&amp;lt;/tt&amp;gt; arguments.  This could be useful to avoid extra memory copies if the data in the array will be needed after the implementation function has returned.&lt;br /&gt;
&lt;br /&gt;
If the flag is used, the daemon will not allocate the memory for the array; instead, in the middle of receiving the request from the client, it will call an allocation routine from the server-side implementation code.  The name of the allocation routine is the name of the function that uses the input &amp;lt;tt&amp;gt;userbuf&amp;lt;/tt&amp;gt; argument, with &amp;lt;tt&amp;gt;_allocate_cb&amp;lt;/tt&amp;gt; suffix attached to it.  Its prototype needs to be as follows:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
void* &amp;lt;name&amp;gt;_allocate_cb(int len);&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The single argument passed by the daemon is the length of the array in bytes.  The routine must return a pointer to a buffer of that size or &amp;lt;tt&amp;gt;NULL&amp;lt;/tt&amp;gt; if that is not possible (in which case, the function will fail and &amp;lt;tt&amp;gt;__zoid_error&amp;lt;/tt&amp;gt; on the client side will return &amp;lt;tt&amp;gt;ENOMEM&amp;lt;/tt&amp;gt;).&lt;br /&gt;
&lt;br /&gt;
There is a restriction on the type of the array: its base type must have a size of one byte, so the array should be of type &amp;lt;tt&amp;gt;char*&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;unsigned char*&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;void*&amp;lt;/tt&amp;gt; (a GCC extension), etc.&lt;br /&gt;
&lt;br /&gt;
The allocation routine is invoked in the same context as ordinary implementation functions.  It may block if it so desires; this will block the compute node client that invoked the routine, but all other clients can keep communicating with the server, thanks to its multi-threaded architecture.&lt;br /&gt;
&lt;br /&gt;
Once the allocation routine has returned and a complete request has been received by the daemon, the implementation function is invoked as usual, with a correct address of the input &amp;lt;tt&amp;gt;userbuf&amp;lt;/tt&amp;gt; array.  It is the responsibility of the plug-in implementer to release the memory occupied by that array when it is no longer needed.&lt;br /&gt;
&lt;br /&gt;
As with other user-level callbacks, the allocation routine may call &amp;lt;tt&amp;gt;__zoid_calling_process_id&amp;lt;/tt&amp;gt; to learn which client process sent the request.  Also, as in other zero-copy cases, for maximum performance, the buffer provided must be aligned in memory to the 16-bytes boundary; otherwise, an interim buffer will be used.  The memory allocation routines such as &amp;lt;tt&amp;gt;malloc&amp;lt;/tt&amp;gt; have been modified to align memory to that boundary, but we recommend explicitly calling &amp;lt;tt&amp;gt;posix_memalign&amp;lt;/tt&amp;gt;.  Finally, as with output &amp;lt;tt&amp;gt;userbuf&amp;lt;/tt&amp;gt;, message size restrictions discussed [[#size_restrictions|earlier]] do not apply to the user-allocated buffers.  Please do not abuse this capability.  There is a good reason for the message size limit: it is there so that the maximum amount of memory required by the ZOID daemon stays limited.  Too many too large user-allocated buffers might result in an out-of-memory condition on the I/O node.&lt;br /&gt;
&lt;br /&gt;
Under rare circumstances, input &amp;lt;tt&amp;gt;userbuf&amp;lt;/tt&amp;gt; could result in memory leaks.  For this to take place, the job would have to be interrupted after the allocation routine has been run, but before the implementation function is called.  This could only cause problems if I/O nodes are not rebooted between jobs.  Those concerned about this scenario can eliminate the leak by adding necessary memory release code to the [[#Start-line functions|FINI]] function.&lt;br /&gt;
&lt;br /&gt;
A simple example:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
void* unix_write_allocate_cb(int len)&lt;br /&gt;
{&lt;br /&gt;
    void* ptr;&lt;br /&gt;
&lt;br /&gt;
    if (posix_memalign(&amp;amp;ptr, 16, len))&lt;br /&gt;
        return NULL;&lt;br /&gt;
&lt;br /&gt;
    return ptr;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
ssize_t unix_write(int fd /* in:obj */,&lt;br /&gt;
                   const void *buf /* in:arr:size=+1:zerocopy:userbuf */,&lt;br /&gt;
                   size_t count /* in:obj */)&lt;br /&gt;
{&lt;br /&gt;
    ssize_t ret;&lt;br /&gt;
&lt;br /&gt;
    ...&lt;br /&gt;
&lt;br /&gt;
    if ((ret = write(fd, buf, count)) == -1)&lt;br /&gt;
        ret = -errno;&lt;br /&gt;
&lt;br /&gt;
    free((void*)buf);&lt;br /&gt;
&lt;br /&gt;
    return ret;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
[[Ramdisk]] | [[ZeptoOS_Documentation|Top]] | [[(K)TAU]]&lt;/div&gt;</summary>
		<author><name>Iskra</name></author>
	</entry>
	<entry>
		<id> /zeptoos/index.php?title=Licensing&amp;diff=609</id>
		<title>Licensing</title>
		<link rel="alternate" type="text/html" href=" /zeptoos/index.php?title=Licensing&amp;diff=609"/>
		<updated>2009-05-08T22:33:20Z</updated>

		<summary type="html">&lt;p&gt;Iskra: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;[[ZeptoOS_Documentation|Top]]&lt;br /&gt;
----&lt;br /&gt;
&lt;br /&gt;
In general, new, original software developed under the ZeptoOS project is distributed under the GNU GPL / LGPL licenses, as appropriate.  Those licenses can be found in the top-level directory of the ZeptoOS tarball. If you are not familiar with the GPL or LGPL licensing, please see the files above and also visit http://www.gnu.org/.&lt;br /&gt;
&lt;br /&gt;
However, ZeptoOS is a collection of many existing software components, packaged and distributed under a number of licenses, such as:&lt;br /&gt;
&lt;br /&gt;
; GPL / LGPL&lt;br /&gt;
: Linux kernel, GNU libc, FUSE, PVFS, BusyBox, iptables, NBD, psmisc,&lt;br /&gt;
; CPL (Common Public License)&lt;br /&gt;
: DCMF, SPI,&lt;br /&gt;
; BSD&lt;br /&gt;
: MPICH, TAU (note that TAU is distributed separately from the ZeptoOS tarball), netkit-rsh&lt;br /&gt;
&lt;br /&gt;
The important thing is that all these licenses are free/open source, [http://www.opensource.org/licenses OSI-approved licenses].&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
[[ZeptoOS_Documentation|Top]]&lt;/div&gt;</summary>
		<author><name>Iskra</name></author>
	</entry>
	<entry>
		<id> /zeptoos/index.php?title=Limitations&amp;diff=608</id>
		<title>Limitations</title>
		<link rel="alternate" type="text/html" href=" /zeptoos/index.php?title=Limitations&amp;diff=608"/>
		<updated>2009-05-08T22:31:22Z</updated>

		<summary type="html">&lt;p&gt;Iskra: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;[[ZeptoOS_Documentation|Top]]&lt;br /&gt;
----&lt;br /&gt;
&lt;br /&gt;
==Known Bugs / Current Limitations==&lt;br /&gt;
&lt;br /&gt;
===No VN/DUAL mode in MPI===&lt;br /&gt;
&lt;br /&gt;
Blue Gene/P supports three job modes:&lt;br /&gt;
&lt;br /&gt;
* SMP (one application process per node)&lt;br /&gt;
* DUAL (two application processes per node)&lt;br /&gt;
* VN (four application processes per node)&lt;br /&gt;
&lt;br /&gt;
In Cobalt, the job mode can be specified using &amp;lt;tt&amp;gt;cqsub -m&amp;lt;/tt&amp;gt; or &amp;lt;tt&amp;gt;qsub --mode&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
ZeptoOS will launch the appropriate number of application processes per node as determined by the mode; however, MPI jobs currently only work in the SMP mode.  We plan to fix this problem in the near future.&lt;br /&gt;
&lt;br /&gt;
===No Universal Performance Counter (UPC)===&lt;br /&gt;
&lt;br /&gt;
UPC is not available in this release. Thus, PAPI will not work since it depends on UPC.&lt;br /&gt;
We are currently trying to enable the UPC support in our Linux environment.&lt;br /&gt;
&lt;br /&gt;
===MPI-IO support===&lt;br /&gt;
&lt;br /&gt;
Due to the limitations of FUSE (the compute-node infrastructure we use for I/O forwarding of POSIX calls), if using the standard glibc, pathnames passed to MPI-IO routines need to be prefixed with &amp;lt;tt&amp;gt;bglockless:&amp;lt;/tt&amp;gt; or &amp;lt;tt&amp;gt;bgl:&amp;lt;/tt&amp;gt; (the latter will not work with PVFS; the former should work with all filesystems).&lt;br /&gt;
&lt;br /&gt;
This should not be necessary when using the version of glibc [[Other Packages#ZOID glibc|modified for ZOID]].  That version should also give a better performance, so please give it a try if the performance with the standard glibc is unsatisfactory.&lt;br /&gt;
&lt;br /&gt;
Also, within the DOE FastOS [http://www.iofsl.org/ I/O forwarding project] we are working on a new, high performance I/O forwarding infrastructure for parallel applications and as this work matures, we will integrate it into ZeptoOS.&lt;br /&gt;
&lt;br /&gt;
===Some MPI jobs hung when they are killed===&lt;br /&gt;
&lt;br /&gt;
We have been seeing this a lot with &amp;lt;tt&amp;gt;cn-ipfwd&amp;lt;/tt&amp;gt;, the [[Other Packages#IP over torus|IP-over-torus]] program.  This program runs &amp;quot;forever&amp;quot;, so it eventually needs to be killed.  When that happens, it will frequently hung one or more compute nodes, preventing the partition from shutting down cleanly.&lt;br /&gt;
&lt;br /&gt;
However, the service node will force a shutdown after a timeout of five minutes, so in practice this is not a significant problem.  Also, we have not seen this problem with ordinary MPI applications (unlike most MPI applications, &amp;lt;tt&amp;gt;cn-ipfwd&amp;lt;/tt&amp;gt; is multithreaded and communicates a lot with the kernel).&lt;br /&gt;
&lt;br /&gt;
==Features Coming Soon==&lt;br /&gt;
&lt;br /&gt;
===Multiple MPI jobs one after another===&lt;br /&gt;
&lt;br /&gt;
Since ZeptoOS supports submitting a shell script as a compute node &amp;quot;application&amp;quot;, it is possible to run multiple &amp;quot;real&amp;quot; applications from within one job:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
#!/bin/sh&lt;br /&gt;
&lt;br /&gt;
for i in 1 2 3 4 5 6 7 8 9 10; do&lt;br /&gt;
    /path/to/real/application&lt;br /&gt;
done&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This does work for sequential applications, but not for those that are linked with MPI; with MPI, an application can only be run once.  However, we have an experimental code that lifts this limitation and we plan to include it in the next release.&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
[[ZeptoOS_Documentation|Top]]&lt;/div&gt;</summary>
		<author><name>Iskra</name></author>
	</entry>
	<entry>
		<id> /zeptoos/index.php?title=FAQ&amp;diff=607</id>
		<title>FAQ</title>
		<link rel="alternate" type="text/html" href=" /zeptoos/index.php?title=FAQ&amp;diff=607"/>
		<updated>2009-05-08T22:26:26Z</updated>

		<summary type="html">&lt;p&gt;Iskra: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;[[ZeptoOS_Documentation|Top]]&lt;br /&gt;
----&lt;br /&gt;
&lt;br /&gt;
==How to obtain a CN node number==&lt;br /&gt;
&lt;br /&gt;
This depends on what number one is interested in.&lt;br /&gt;
&lt;br /&gt;
===Pset rank===&lt;br /&gt;
&lt;br /&gt;
A pset rank is a number identifying a compute node within each ''pset'' (an I/O node and the compute nodes that communicate with it).  Note that on partitions larger than one pset, the pset ranks will not be unique.  Also, pset ranks do ''not'' start from &amp;lt;tt&amp;gt;0&amp;lt;/tt&amp;gt;; they start from &amp;lt;tt&amp;gt;1&amp;lt;/tt&amp;gt; for some mysterious reason (do not blame us &amp;amp;#8211; blame IBM&amp;amp;nbsp;:-).&lt;br /&gt;
&lt;br /&gt;
Pset rank is used as the last octet in the IP address on the tree network connecting the compute nodes and the I/O nodes (''x'' in &amp;lt;tt&amp;gt;192.168.1.&amp;lt;/tt&amp;gt;''x'').&lt;br /&gt;
&lt;br /&gt;
The pset rank is available on the compute nodes from &amp;lt;tt&amp;gt;/proc/personality.sh&amp;lt;/tt&amp;gt;, in the &amp;lt;tt&amp;gt;BG_RANK_IN_PSET&amp;lt;/tt&amp;gt; variable:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
#!/bin/sh&lt;br /&gt;
&lt;br /&gt;
. /proc/personality.sh&lt;br /&gt;
&lt;br /&gt;
echo &amp;quot;My pset rank is $BG_RANK_IN_PSET&amp;quot;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
From a C program it will be easier to use the binary personality available from &amp;lt;tt&amp;gt;/proc/personality&amp;lt;/tt&amp;gt;.  The definition of the structure can be found in &amp;lt;tt&amp;gt;/bgsys/drivers/ppcfloor/arch/include/common/bgp_personality.h&amp;lt;/tt&amp;gt;.  The pset rank is in &amp;lt;tt&amp;gt;Network_Config.RankInPSet&amp;lt;/tt&amp;gt;:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
#include &amp;lt;stdio.h&amp;gt;&lt;br /&gt;
#include &amp;lt;fcntl.h&amp;gt;&lt;br /&gt;
#include &amp;lt;unistd.h&amp;gt;&lt;br /&gt;
#include &amp;lt;common/bgp_personality.h&amp;gt;&lt;br /&gt;
&lt;br /&gt;
int main(void)&lt;br /&gt;
{&lt;br /&gt;
    _BGP_Personality_t personality;&lt;br /&gt;
    int fd;&lt;br /&gt;
&lt;br /&gt;
    if ((fd = open(&amp;quot;/proc/personality&amp;quot;, O_RDONLY)) == -1)&lt;br /&gt;
    {&lt;br /&gt;
        perror(&amp;quot;open&amp;quot;);&lt;br /&gt;
        return 1;&lt;br /&gt;
    }&lt;br /&gt;
    if (read(fd, &amp;amp;personality, sizeof(personality)) != sizeof(personality))&lt;br /&gt;
    {&lt;br /&gt;
        perror(&amp;quot;read&amp;quot;);&lt;br /&gt;
        close(fd);&lt;br /&gt;
        return 1;&lt;br /&gt;
    }&lt;br /&gt;
    close(fd);&lt;br /&gt;
&lt;br /&gt;
    printf(&amp;quot;My pset rank is %d\n&amp;quot;, personality.Network_Config.RankInPSet);&lt;br /&gt;
&lt;br /&gt;
    return 0;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
(compile the above with &amp;lt;tt&amp;gt;-I/bgsys/drivers/ppcfloor/arch/include&amp;lt;/tt&amp;gt;)&lt;br /&gt;
&lt;br /&gt;
===Torus rank===&lt;br /&gt;
&lt;br /&gt;
A torus rank is a number identifying a compute node within a whole partition.  In a way, it is much &amp;quot;nicer&amp;quot; than a pset rank since it is unique within a job and it also starts from &amp;lt;tt&amp;gt;0&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
The torus rank is easy to obtain from a C program: it is the &amp;lt;tt&amp;gt;Network_Config.Rank&amp;lt;/tt&amp;gt; field of the personality structure.&lt;br /&gt;
&lt;br /&gt;
Unfortunately, the torus rank is not available in &amp;lt;tt&amp;gt;/proc/personality.sh&amp;lt;/tt&amp;gt;, but a shell script can easily calculate it from other fields:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
TORUS_RANK=`echo $BG_PSETORG | awk &amp;quot;{print \\$1 + \\$2 * $BG_XSIZE + \&lt;br /&gt;
            \\$3 * $BG_XSIZE * $BG_YSIZE}&amp;quot;`&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===MPI rank===&lt;br /&gt;
&lt;br /&gt;
An MPI rank should not be confused with the torus rank, even though by default the two are the same.  MPI rank is a property of a process, ''not'' node.  If one submits a job in the &amp;lt;tt&amp;gt;VN&amp;lt;/tt&amp;gt; or &amp;lt;tt&amp;gt;DUAL&amp;lt;/tt&amp;gt; mode, there will be multiple MPI tasks per node, obviously each with a different MPI rank.  Also, using the &amp;lt;tt&amp;gt;BG_MAPPING&amp;lt;/tt&amp;gt; environment variable changes the mapping between the torus coordinates and MPI ranks.&lt;br /&gt;
&lt;br /&gt;
While obtaining MPI rank from an MPI application is trivial, how to obtain it from a shell script?&lt;br /&gt;
&lt;br /&gt;
One way would be to invoke a simple C program:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
#include &amp;lt;stdio.h&amp;gt;&lt;br /&gt;
#include &amp;quot;zoid_api.h&amp;quot;&lt;br /&gt;
&lt;br /&gt;
int main(void)&lt;br /&gt;
{&lt;br /&gt;
    if (__zoid_init())&lt;br /&gt;
        return 1;&lt;br /&gt;
    printf(&amp;quot;%d\n&amp;quot;, __zoid_my_rank());&lt;br /&gt;
    return 0;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
(compile with &amp;lt;tt&amp;gt;-I&amp;lt;/tt&amp;gt;''path_to_ZeptoOS_source''&amp;lt;tt&amp;gt;/packages/zoid/prebuilt -L&amp;lt;/tt&amp;gt;''path_to_ZeptoOS_source''&amp;lt;tt&amp;gt;/packages/zoid/prebuilt -lzoid_cn&amp;lt;/tt&amp;gt;)&lt;br /&gt;
&lt;br /&gt;
A slight disadvantage of this approach is that &amp;lt;tt&amp;gt;__zoid_init&amp;lt;/tt&amp;gt; registers the process with the ZOID daemon on the I/O node, which is an overhead we do not need.  Another solution, without using any binaries, is as follows:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
MPI_RANK=`echo $CONTROL_INIT | awk -F, '{print $4}'`&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This has a disadvantage of using internal ZOID variables which are not guaranteed to be supported in future releases.&lt;br /&gt;
&lt;br /&gt;
==How to open a socket from a CN to the outside world==&lt;br /&gt;
&lt;br /&gt;
ZOID provides IP packet forwarding between the compute nodes and the I/O nodes.  However, because the compute nodes use non-routable IP addresses (&amp;lt;tt&amp;gt;192.168.1.&amp;lt;/tt&amp;gt;''x''), they cannot communicate directly with the outside world.&lt;br /&gt;
&lt;br /&gt;
The most transparent solution to this problem is to perform network address translation (NAT) on the I/O nodes using the Linux kernel netfilter infrastructure.  We used to enable this by default, but experiments have shown it to have a detrimental effect on the overall performance of the TCP/IP stack on the I/O nodes, slowing down access to the network filesystems.&lt;br /&gt;
&lt;br /&gt;
To enable the translation, pass &amp;lt;tt&amp;gt;ZOID_NAT_ENABLE&amp;lt;/tt&amp;gt; environment variable when submitting a job.  An administrator can also enable this option permanently in the [[ZOID#opt_enable_nat|config file]].&lt;br /&gt;
&lt;br /&gt;
==How to obtain a Cobalt job ID==&lt;br /&gt;
&lt;br /&gt;
Cobalt passes the job id to the application processes launched on the compute nodes using the &amp;lt;tt&amp;gt;COBALT_JOBID&amp;lt;/tt&amp;gt; environment variable.&lt;br /&gt;
&lt;br /&gt;
This variable is also accessible from the [[ZOID#User script|user script]] running on the I/O nodes, using the &amp;lt;tt&amp;gt;ZOID_JOB_ENV&amp;lt;/tt&amp;gt; variable:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
COBALT_JOBID=`echo $ZOID_JOB_ENV | sed 's/^.*COBALT_JOBID=\([^:]*\)/\1/'`&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Why large MPI processes do not work==&lt;br /&gt;
&lt;br /&gt;
A common reason might be that they do not have enough memory to run.  MPI processes run within the big memory region, which by default is limited to just 256&amp;amp;nbsp;MB so as not to deplete the ordinary Linux paged memory pool too much (main memory is allocated to the big memory region at boot time and it cannot be reclaimed by the kernel, even if it were unused).&lt;br /&gt;
&lt;br /&gt;
See the [[Kernel#Kernel (command line) parameters|Kernel]] section to learn how to increase the limit; the parameter to use is &amp;lt;tt&amp;gt;flatmemsizeMB&amp;lt;/tt&amp;gt;.  We suggest creating multiple profiles with different big memory sizes to accommodate different uses of ZeptoOS.&lt;br /&gt;
&lt;br /&gt;
==Why SSH keeps asking for a password==&lt;br /&gt;
&lt;br /&gt;
As we envisioned it, partition owners should be able to log on the I/O nodes belonging to their jobs without being asked for a password.  The following considerations apply:&lt;br /&gt;
# The account information on the partition owner must be added to the &amp;lt;tt&amp;gt;/etc/passwd&amp;lt;/tt&amp;gt; file on the I/O nodes when launching a job; this is discussed [[ZOID#The /bin.rd/update_passwd_file.sh file|here]].&lt;br /&gt;
# For password-less logins, &amp;lt;tt&amp;gt;shosts.equiv&amp;lt;/tt&amp;gt; must be configured before (re)building the I/O node ramdisk, as discussed [[Testing#Interactive login|here]].  Alternatively, users could set up SSH key pairs in their home directories (password-less, or using &amp;lt;tt&amp;gt;ssh-agent&amp;lt;/tt&amp;gt; to cache the password).&lt;br /&gt;
# SSH might temporarily prevent a partition owner from logging in if an attempt is made before the job starts running, as discussed [[Testing#Interactive login|here]].  Root can always log in, by providing the password set when building the I/O node ramdisk for the first time.&lt;br /&gt;
# Finally, keep in mind that a particular site might have disabled this feature on purpose.&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
[[ZeptoOS_Documentation|Top]]&lt;/div&gt;</summary>
		<author><name>Iskra</name></author>
	</entry>
	<entry>
		<id> /zeptoos/index.php?title=Other_Packages&amp;diff=606</id>
		<title>Other Packages</title>
		<link rel="alternate" type="text/html" href=" /zeptoos/index.php?title=Other_Packages&amp;diff=606"/>
		<updated>2009-05-08T22:17:15Z</updated>

		<summary type="html">&lt;p&gt;Iskra: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;[[(K)TAU]] | [[ZeptoOS_Documentation|Top]]&lt;br /&gt;
----&lt;br /&gt;
&lt;br /&gt;
==PVFS==&lt;br /&gt;
&lt;br /&gt;
[http://www.pvfs.org/ PVFS] stands for Parallel Virtual File System, an open source parallel file system designed to scale to petabytes of storage and to provide access rates at 100s of GB/s.  At Argonne BGP systems, PVFS servers are running and PVFS start-up script is installed in the BGP site-specific directory (&amp;lt;tt&amp;gt;/bgp/iofs/&amp;lt;/tt&amp;gt;), so that a PVFS volume is mounted at ION boot time. &lt;br /&gt;
&lt;br /&gt;
We included PVFS version 2.8.1 source code and its prebuilt client binaries in the ZeptoOS release for the sites that are interested in PVFS. We also included a very simple example PVFS start-up script that can be added to the ION ramdisk. If you have PVFS servers running in your system, you can follow the steps below to add the necessary PVFS client components to the ramdisk:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
$ cd packages/pvfs2/prebuilt&lt;br /&gt;
$ sh add-pvfs2-client-ION-ramdisk.sh tcp://192.168.1.1:333/pvfs2-fs&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Please replace &amp;lt;tt&amp;gt;tcp://192.168.1.1:3334/pvfs2-fs&amp;lt;/tt&amp;gt; with the actual server info.&lt;br /&gt;
&lt;br /&gt;
Details on building and running PVFS servers are outside of the scope of this document, but the following example might give a basic idea of how to build and run PVFS:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
[Build]&lt;br /&gt;
$ cd pvfs-2.8.1&lt;br /&gt;
$ ./configure [options....]&lt;br /&gt;
$ make&lt;br /&gt;
&lt;br /&gt;
[Create a server config file]&lt;br /&gt;
$ ./src/apps/admin/pvfs2-genconfig fs.conf&lt;br /&gt;
&lt;br /&gt;
[Start the server]&lt;br /&gt;
$ ./src/server/pvfs2-server -f fs.conf -a ALIAS&lt;br /&gt;
$ ./src/server/pvfs2-server    fs.conf -a ALIAS&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
'''Note:'''&lt;br /&gt;
* replace &amp;lt;tt&amp;gt;ALIAS&amp;lt;/tt&amp;gt; with your real alias in &amp;lt;tt&amp;gt;fs.conf&amp;lt;/tt&amp;gt;&lt;br /&gt;
* the first &amp;lt;tt&amp;gt;pvfs2-server&amp;lt;/tt&amp;gt; invocation just initializes a PVFS volume&lt;br /&gt;
* the second invocation actually starts the server&lt;br /&gt;
&lt;br /&gt;
==IP over torus==&lt;br /&gt;
&lt;br /&gt;
This is currently a preview feature.  It implements IP packet forwarding on top of MPI, over the torus network.  Torus is a point-to-point network that interconnects all the compute nodes in a partition.  Every compute node gets a unique IP address, of the form:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
10.128.0.0 | &amp;lt;rank&amp;gt;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
where &amp;lt;tt&amp;gt;&amp;lt;rank&amp;gt;&amp;lt;/tt&amp;gt; is the [[FAQ#MPI rank|MPI rank]].  Thus, for a 64-node partition, the IP addresses will range between &amp;lt;tt&amp;gt;10.128.0.0&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;10.128.0.63&amp;lt;/tt&amp;gt;, and for a 1024-node partition, they will range between &amp;lt;tt&amp;gt;10.128.0.0&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;10.128.3.255&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
To try this feature out, submit as a compute job the &amp;lt;tt&amp;gt;cn-ipfwd.sh&amp;lt;/tt&amp;gt; script, which should have been installed in &amp;lt;tt&amp;gt;/path/to/install/cnbin/&amp;lt;/tt&amp;gt;.  The script can act as a standalone job or as a wrapper.  If invoked without any arguments, it initializes the IP forwarding and then goes to sleep; if any arguments have been passed, they are interpreted as the name of the binary (along with its command line arguments) to invoke once the IP forwarding is initialized, e.g. (an example with Cobalt):&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
$ cqsub -k &amp;lt;profile-name&amp;gt; -t &amp;lt;time&amp;gt; -n 64 /path/to/install/cnbin/ipfwd.sh \&lt;br /&gt;
&amp;lt;name of another binary&amp;gt; &amp;lt;arguments to that binary&amp;gt;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The script can be copied to another location and adjusted to one's needs.&lt;br /&gt;
&lt;br /&gt;
Once the job is running, log into a compute node, and run &amp;lt;tt&amp;gt;ifconfig&amp;lt;/tt&amp;gt;; there should be a new virtual network device &amp;lt;tt&amp;gt;tun1&amp;lt;/tt&amp;gt; (in addition to the usual &amp;lt;tt&amp;gt;tun0&amp;lt;/tt&amp;gt;, used for IP forwarding between compute nodes and I/O nodes):&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
~ # ifconfig tun1&lt;br /&gt;
tun1      Link encap:UNSPEC  HWaddr 00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00  &lt;br /&gt;
          inet addr:10.128.0.0  P-t-P:10.128.0.0  Mask:255.255.255.255&lt;br /&gt;
          UP POINTOPOINT RUNNING NOARP MULTICAST  MTU:65535  Metric:1&lt;br /&gt;
          RX packets:0 errors:0 dropped:0 overruns:0 frame:0&lt;br /&gt;
          TX packets:0 errors:0 dropped:0 overruns:0 carrier:0&lt;br /&gt;
          collisions:0 txqueuelen:500 &lt;br /&gt;
          RX bytes:0 (0.0 B)  TX bytes:0 (0.0 B)&lt;br /&gt;
~ # ping 10.128.0.1&lt;br /&gt;
PING 10.128.0.1 (10.128.0.1): 56 data bytes&lt;br /&gt;
64 bytes from 10.128.0.1: seq=0 ttl=64 time=0.321 ms&lt;br /&gt;
64 bytes from 10.128.0.1: seq=1 ttl=64 time=0.191 ms&lt;br /&gt;
64 bytes from 10.128.0.1: seq=2 ttl=64 time=0.203 ms&lt;br /&gt;
64 bytes from 10.128.0.1: seq=3 ttl=64 time=0.194 ms&lt;br /&gt;
64 bytes from 10.128.0.1: seq=4 ttl=64 time=0.207 ms&lt;br /&gt;
--- 10.128.0.1 ping statistics ---&lt;br /&gt;
5 packets transmitted, 5 packets received, 0% packet loss&lt;br /&gt;
round-trip min/avg/max = 0.191/0.223/0.321 ms&lt;br /&gt;
~ # rsh 10.128.0.1 'grep BG_RANK_IN_PSET /proc/personality.sh'&lt;br /&gt;
BG_RANK_IN_PSET=59&lt;br /&gt;
~ # &lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This feature can be used to implement an arbitrary IP-based network protocol between the compute nodes.  We have even experimented running a TCP/IP-based MPICH on top of it (which, while obviously not as fast as the native Blue Gene one, has the advantage of being able to, e.g., run multiple MPI jobs at a time on a single partition).&lt;br /&gt;
&lt;br /&gt;
One major disadvantage of this feature is that the current implementation is computationally intensive; it permanently occupies one core on each node.&lt;br /&gt;
&lt;br /&gt;
==ZOID glibc==&lt;br /&gt;
&lt;br /&gt;
This is another preview feature.  It provides a modified version of GNU libc for the compute nodes, which features much better file I/O throughput rates to the I/O nodes and remote file systems than the default one.  It does so by communicating with the ZOID daemon directly, instead of going through the compute node Linux kernel and the FUSE client (which, while convenient, is slow).&lt;br /&gt;
&lt;br /&gt;
The modified glibc is meant for compiled application processes, not for shell scripts and such.  It is currently only available in a static (&amp;lt;tt&amp;gt;.a&amp;lt;/tt&amp;gt;) version.  It is installed with the rest of the ZeptoOS, in &amp;lt;tt&amp;gt;/path/to/install/lib/zoid/&amp;lt;/tt&amp;gt;.  To link with it, simply add &amp;lt;tt&amp;gt;-L/path/to/install/lib/zoid&amp;lt;/tt&amp;gt; to the final linking stage.  Use the following command to verify that the modified version of glibc has been used for linking:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
$ nm &amp;lt;binary&amp;gt; | grep __zoid_init&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
(no output will be generated if the standard glibc was used)&lt;br /&gt;
&lt;br /&gt;
When submitting a job linked with this glibc, please set the environment variable &amp;lt;tt&amp;gt;ZOID_DIRS&amp;lt;/tt&amp;gt; to a list of &amp;lt;tt&amp;gt;:&amp;lt;/tt&amp;gt;-separated pathname prefixes.  Only files opened using pathnames beginning with those prefixes will be directly forwarded to the I/O node; other files will be handled via the compute node kernel and possibly FUSE, which is much slower.&lt;br /&gt;
&lt;br /&gt;
Here is a simple benchmark:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
#include &amp;lt;stdio.h&amp;gt;&lt;br /&gt;
#include &amp;lt;stdlib.h&amp;gt;&lt;br /&gt;
&lt;br /&gt;
#include &amp;lt;fcntl.h&amp;gt;&lt;br /&gt;
#include &amp;lt;unistd.h&amp;gt;&lt;br /&gt;
#include &amp;lt;sys/time.h&amp;gt;&lt;br /&gt;
&lt;br /&gt;
#define BUFSIZE (1024 * 1024 * 100)&lt;br /&gt;
&lt;br /&gt;
int main(int argc, char* argv[])&lt;br /&gt;
{&lt;br /&gt;
    char* buffer;&lt;br /&gt;
    int fd;&lt;br /&gt;
    struct timeval start, stop;&lt;br /&gt;
    double time;&lt;br /&gt;
&lt;br /&gt;
    if (argc != 2)&lt;br /&gt;
    {&lt;br /&gt;
	fprintf(stderr, &amp;quot;Usage: %s &amp;lt;pathname&amp;gt;\n&amp;quot;, argv[0]);&lt;br /&gt;
	return 1;&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    if (!(buffer = malloc(BUFSIZE)))&lt;br /&gt;
    {&lt;br /&gt;
	perror(&amp;quot;malloc&amp;quot;);&lt;br /&gt;
	return 1;&lt;br /&gt;
    }&lt;br /&gt;
    if ((fd = open(argv[1], O_CREAT | O_WRONLY, 0666)) == -1)&lt;br /&gt;
    {&lt;br /&gt;
	perror(&amp;quot;open&amp;quot;);&lt;br /&gt;
	return 1;&lt;br /&gt;
    }&lt;br /&gt;
    gettimeofday(&amp;amp;start, NULL);&lt;br /&gt;
    if (write(fd, buffer, BUFSIZE) != BUFSIZE)&lt;br /&gt;
    {&lt;br /&gt;
	perror(&amp;quot;write&amp;quot;);&lt;br /&gt;
	return 1;&lt;br /&gt;
    }&lt;br /&gt;
    gettimeofday(&amp;amp;stop, NULL);&lt;br /&gt;
    close(fd);&lt;br /&gt;
    free(buffer);&lt;br /&gt;
&lt;br /&gt;
    time = stop.tv_sec - start.tv_sec + (stop.tv_usec - start.tv_usec) * 1e-6;&lt;br /&gt;
    printf(&amp;quot;Writing %d B took %g s, %g B/s\n&amp;quot;, BUFSIZE, time, BUFSIZE / time);&lt;br /&gt;
&lt;br /&gt;
    return 0;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
It writes 1&amp;amp;nbsp;GB of data to a file passed on the command line.  With Cobalt, we submit it as follows:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
$ cqsub -k &amp;lt;profile-name&amp;gt; -t 10 -n 1 -e ZOID_DIRS=$HOME $PWD/speed_zoid $HOME/speed_zoid-out&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
With our home directories on a GPFS filesystem, we get the following performance:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
Writing 1073741824 B took 4.58026 s, 2.34428e+08 B/s&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
On the other hand, if we link it with the standard glibc, or if we forget to set &amp;lt;tt&amp;gt;ZOID_DIRS&amp;lt;/tt&amp;gt;, the performance we observe is as follows:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
Writing 1073741824 B took 10.4905 s, 1.02354e+08 B/s&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The modified glibc is not used by default because it is not yet complete.  However, if one does not try to outsmart it (in particular, we recommend always passing absolute pathnames), it should work reliably.&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
[[(K)TAU]] | [[ZeptoOS_Documentation|Top]]&lt;/div&gt;</summary>
		<author><name>Iskra</name></author>
	</entry>
	<entry>
		<id> /zeptoos/index.php?title=Other_Packages&amp;diff=605</id>
		<title>Other Packages</title>
		<link rel="alternate" type="text/html" href=" /zeptoos/index.php?title=Other_Packages&amp;diff=605"/>
		<updated>2009-05-08T22:10:26Z</updated>

		<summary type="html">&lt;p&gt;Iskra: /* PVFS */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;[[(K)TAU]] | [[ZeptoOS_Documentation|Top]]&lt;br /&gt;
----&lt;br /&gt;
&lt;br /&gt;
==PVFS==&lt;br /&gt;
&lt;br /&gt;
[http://www.pvfs.org/ PVFS] stands for Parallel Virtual File System, an open source parallel file system designed to scale to petabytes of storage and to provide access rates at 100s of GB/s.  At Argonne BGP systems, PVFS servers are running and PVFS start-up script is installed in the BGP site-specific directory (&amp;lt;tt&amp;gt;/bgp/iofs/&amp;lt;/tt&amp;gt;), so that a PVFS volume is mounted at ION boot time. &lt;br /&gt;
&lt;br /&gt;
We included PVFS version 2.8.1 source code and its prebuilt client binaries in the ZeptoOS release for the sites that are interested in PVFS. We also include a very simple example PVFS start-up script that can be added to the ION ramdisk. If you have PVFS servers running in your system, you can follow the steps below to add the necessary PVFS client components to the ramdisk.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
$ cd packages/pvfs2/prebuilt&lt;br /&gt;
$ sh add-pvfs2-client-ION-ramdisk.sh tcp://192.168.1.1:333/pvfs2-fs&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Please replace &amp;lt;tt&amp;gt;tcp://192.168.1.1:3334/pvfs2-fs&amp;lt;/tt&amp;gt; with the actual server info.&lt;br /&gt;
&lt;br /&gt;
Details on building and running the PVFS servers are outside of the scope of this document, but the following example might give a basic idea to build and run the pvfs2 server.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
[Build]&lt;br /&gt;
$ cd pvfs-2.8.1&lt;br /&gt;
$ ./configure [options....]&lt;br /&gt;
$ make&lt;br /&gt;
&lt;br /&gt;
[Create a server config file]&lt;br /&gt;
$ ./src/apps/admin/pvfs2-genconfig fs.conf&lt;br /&gt;
&lt;br /&gt;
[Start the server]&lt;br /&gt;
$ ./src/server/pvfs2-server -f fs.conf -a ALIAS&lt;br /&gt;
$ ./src/server/pvfs2-server    fs.conf -a ALIAS&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
'''Note:'''&lt;br /&gt;
* replace &amp;lt;tt&amp;gt;ALIAS&amp;lt;/tt&amp;gt; with your real alias in &amp;lt;tt&amp;gt;fs.conf&amp;lt;/tt&amp;gt;&lt;br /&gt;
* the first &amp;lt;tt&amp;gt;pvfs2-server&amp;lt;/tt&amp;gt; invocation just initializes a PVFS volume&lt;br /&gt;
* the second invocation actually starts the server&lt;br /&gt;
&lt;br /&gt;
==IP over torus==&lt;br /&gt;
&lt;br /&gt;
This is currently a preview feature.  It implements IP packet forwarding on top of MPI, over the torus network.  Torus is a point-to-point network that interconnects all the compute nodes in a partition.  Every compute node gets a unique IP address, of the form:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
10.128.0.0 | &amp;lt;rank&amp;gt;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
where &amp;lt;tt&amp;gt;&amp;lt;rank&amp;gt;&amp;lt;/tt&amp;gt; is the [[FAQ#MPI rank|MPI rank]].  Thus, for a 64-node partition, the IP addresses will range between &amp;lt;tt&amp;gt;10.128.0.0&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;10.128.0.63&amp;lt;/tt&amp;gt;, and for a 1024-node partition, they will range between &amp;lt;tt&amp;gt;10.128.0.0&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;10.128.3.255&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
To try this feature out, submit as a compute job the &amp;lt;tt&amp;gt;cn-ipfwd.sh&amp;lt;/tt&amp;gt; script, which should have been installed in &amp;lt;tt&amp;gt;/path/to/install/cnbin/&amp;lt;/tt&amp;gt;.  The script can act as a standalone job or as a wrapper.  If invoked without any arguments, it initializes the IP forwarding and then goes to sleep; if any arguments have been passed, they are interpreted as the name of the binary (along with its command line arguments) to invoke once the IP forwarding is initialized, e.g. (an example with Cobalt):&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
$ cqsub -k &amp;lt;profile-name&amp;gt; -t &amp;lt;time&amp;gt; -n 64 /path/to/install/cnbin/ipfwd.sh \&lt;br /&gt;
&amp;lt;name of another binary&amp;gt; &amp;lt;arguments to that binary&amp;gt;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The script can be copied to another location and adjusted to one's needs.&lt;br /&gt;
&lt;br /&gt;
Once the job is running, log into a compute node, and run &amp;lt;tt&amp;gt;ifconfig&amp;lt;/tt&amp;gt;; there should be a new virtual network device &amp;lt;tt&amp;gt;tun1&amp;lt;/tt&amp;gt; (in addition to the usual &amp;lt;tt&amp;gt;tun0&amp;lt;/tt&amp;gt;, used for IP forwarding between compute nodes and I/O nodes):&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
~ # ifconfig tun1&lt;br /&gt;
tun1      Link encap:UNSPEC  HWaddr 00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00  &lt;br /&gt;
          inet addr:10.128.0.0  P-t-P:10.128.0.0  Mask:255.255.255.255&lt;br /&gt;
          UP POINTOPOINT RUNNING NOARP MULTICAST  MTU:65535  Metric:1&lt;br /&gt;
          RX packets:0 errors:0 dropped:0 overruns:0 frame:0&lt;br /&gt;
          TX packets:0 errors:0 dropped:0 overruns:0 carrier:0&lt;br /&gt;
          collisions:0 txqueuelen:500 &lt;br /&gt;
          RX bytes:0 (0.0 B)  TX bytes:0 (0.0 B)&lt;br /&gt;
~ # ping 10.128.0.1&lt;br /&gt;
PING 10.128.0.1 (10.128.0.1): 56 data bytes&lt;br /&gt;
64 bytes from 10.128.0.1: seq=0 ttl=64 time=0.321 ms&lt;br /&gt;
64 bytes from 10.128.0.1: seq=1 ttl=64 time=0.191 ms&lt;br /&gt;
64 bytes from 10.128.0.1: seq=2 ttl=64 time=0.203 ms&lt;br /&gt;
64 bytes from 10.128.0.1: seq=3 ttl=64 time=0.194 ms&lt;br /&gt;
64 bytes from 10.128.0.1: seq=4 ttl=64 time=0.207 ms&lt;br /&gt;
--- 10.128.0.1 ping statistics ---&lt;br /&gt;
5 packets transmitted, 5 packets received, 0% packet loss&lt;br /&gt;
round-trip min/avg/max = 0.191/0.223/0.321 ms&lt;br /&gt;
~ # rsh 10.128.0.1 'grep BG_RANK_IN_PSET /proc/personality.sh'&lt;br /&gt;
BG_RANK_IN_PSET=59&lt;br /&gt;
~ # &lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This feature can be used to implement an arbitrary IP-based network protocol between the compute nodes.  We have even experimented running a TCP/IP-based MPICH on top of it (which, while obviously not as fast as the native Blue Gene one, has the advantage of being able to, e.g., run multiple MPI jobs at a time on a single partition).&lt;br /&gt;
&lt;br /&gt;
One major disadvantage of this feature is that the current implementation is computationally intensive; it permanently occupies one core on each node.&lt;br /&gt;
&lt;br /&gt;
==ZOID glibc==&lt;br /&gt;
&lt;br /&gt;
This is another preview feature.  It provides a modified version of GNU libc for the compute nodes, which features much better file I/O throughput rates to the I/O nodes and remote file systems than the default one.  It does so by communicating with the ZOID daemon directly, instead of going through the Linux kernel and the FUSE client (which, while convenient, is slow).&lt;br /&gt;
&lt;br /&gt;
The modified glibc is meant for compiled application processes, not for shell scripts and such.  It is currently only available in a static (&amp;lt;tt&amp;gt;.a&amp;lt;/tt&amp;gt;) version.  It is installed with the rest of the ZeptoOS, in &amp;lt;tt&amp;gt;/path/to/install/lib/zoid/&amp;lt;/tt&amp;gt;.  To link with it, simply add &amp;lt;tt&amp;gt;-L/path/to/install/lib/zoid&amp;lt;/tt&amp;gt; to the final linking stage.  Use the following command to verify that the modified version of glibc has been used for linking:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
$ nm &amp;lt;binary&amp;gt; | grep __zoid_init&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
(no output will be generated if the standard glibc was used)&lt;br /&gt;
&lt;br /&gt;
When submitting a job linked with this glibc, please set the environment variable &amp;lt;tt&amp;gt;ZOID_DIRS&amp;lt;/tt&amp;gt; to a list of &amp;lt;tt&amp;gt;:&amp;lt;/tt&amp;gt;-separated pathname prefixes.  Only files opened using pathnames beginning with those prefixes will be directly forwarded to the I/O node; other files will be handled via the compute node kernel and possibly FUSE, which is much slower.&lt;br /&gt;
&lt;br /&gt;
Here is a simple benchmark:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
#include &amp;lt;stdio.h&amp;gt;&lt;br /&gt;
#include &amp;lt;stdlib.h&amp;gt;&lt;br /&gt;
&lt;br /&gt;
#include &amp;lt;fcntl.h&amp;gt;&lt;br /&gt;
#include &amp;lt;unistd.h&amp;gt;&lt;br /&gt;
#include &amp;lt;sys/time.h&amp;gt;&lt;br /&gt;
&lt;br /&gt;
#define BUFSIZE (1024 * 1024 * 100)&lt;br /&gt;
&lt;br /&gt;
int main(int argc, char* argv[])&lt;br /&gt;
{&lt;br /&gt;
    char* buffer;&lt;br /&gt;
    int fd;&lt;br /&gt;
    struct timeval start, stop;&lt;br /&gt;
    double time;&lt;br /&gt;
&lt;br /&gt;
    if (argc != 2)&lt;br /&gt;
    {&lt;br /&gt;
	fprintf(stderr, &amp;quot;Usage: %s &amp;lt;pathname&amp;gt;\n&amp;quot;, argv[0]);&lt;br /&gt;
	return 1;&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    if (!(buffer = malloc(BUFSIZE)))&lt;br /&gt;
    {&lt;br /&gt;
	perror(&amp;quot;malloc&amp;quot;);&lt;br /&gt;
	return 1;&lt;br /&gt;
    }&lt;br /&gt;
    if ((fd = open(argv[1], O_CREAT | O_WRONLY, 0666)) == -1)&lt;br /&gt;
    {&lt;br /&gt;
	perror(&amp;quot;open&amp;quot;);&lt;br /&gt;
	return 1;&lt;br /&gt;
    }&lt;br /&gt;
    gettimeofday(&amp;amp;start, NULL);&lt;br /&gt;
    if (write(fd, buffer, BUFSIZE) != BUFSIZE)&lt;br /&gt;
    {&lt;br /&gt;
	perror(&amp;quot;write&amp;quot;);&lt;br /&gt;
	return 1;&lt;br /&gt;
    }&lt;br /&gt;
    gettimeofday(&amp;amp;stop, NULL);&lt;br /&gt;
    close(fd);&lt;br /&gt;
    free(buffer);&lt;br /&gt;
&lt;br /&gt;
    time = stop.tv_sec - start.tv_sec + (stop.tv_usec - start.tv_usec) * 1e-6;&lt;br /&gt;
    printf(&amp;quot;Writing %d B took %g s, %g B/s\n&amp;quot;, BUFSIZE, time, BUFSIZE / time);&lt;br /&gt;
&lt;br /&gt;
    return 0;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
It writes 1&amp;amp;nbsp;GB of data to a file passed on the command line.  With Cobalt, we submit it as follows:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
$ cqsub -k &amp;lt;profile-name&amp;gt; -t 10 -n 1 -e ZOID_DIRS=$HOME $PWD/speed_zoid $HOME/speed_zoid-out&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
With our home directories on a GPFS filesystem, we get the following performance:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
Writing 1073741824 B took 4.58026 s, 2.34428e+08 B/s&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
On the other hand, if we link it with the standard glibc, or if we forget to set &amp;lt;tt&amp;gt;ZOID_DIRS&amp;lt;/tt&amp;gt;, the performance we observe is as follows:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
Writing 1073741824 B took 10.4905 s, 1.02354e+08 B/s&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The modified glibc is not used by default, because it is not yet complete.  However, if one does not try to outsmart it (in particular, we recommend always passing absolute pathnames), it should work reliably.&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
[[(K)TAU]] | [[ZeptoOS_Documentation|Top]]&lt;/div&gt;</summary>
		<author><name>Iskra</name></author>
	</entry>
	<entry>
		<id> /zeptoos/index.php?title=Ramdisk&amp;diff=604</id>
		<title>Ramdisk</title>
		<link rel="alternate" type="text/html" href=" /zeptoos/index.php?title=Ramdisk&amp;diff=604"/>
		<updated>2009-05-08T21:50:14Z</updated>

		<summary type="html">&lt;p&gt;Iskra: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;[[Kernel]] | [[ZeptoOS_Documentation|Top]] | [[ZOID]]&lt;br /&gt;
----&lt;br /&gt;
&lt;br /&gt;
==Introduction==&lt;br /&gt;
&lt;br /&gt;
Both the CN and the ION Linux kernels require a ramdisk to boot.  Ramdisk images contain minimal Linux utilities, init scripts, configuration files, kernel modules, etc, which are required by the OS boot process.&lt;br /&gt;
&lt;br /&gt;
ION ramdisk is an ELF file that contains a cpio archive of system files. Two ION ramdisk images are currently generated:&lt;br /&gt;
&lt;br /&gt;
; BGP-ION-ramdisk-for-CNL.elf&lt;br /&gt;
: Default ION ramdisk for ZeptoOS compute node Linux.&lt;br /&gt;
; BGP-ION-ramdisk-for-CNK.elf &lt;br /&gt;
: Use this one if you need to run IBM CNK on the compute nodes (uses IBM CIOD instead of ZOID)&lt;br /&gt;
&lt;br /&gt;
Our ION ramdisks are similar to the default ION ramdisk from IBM, but we add some extra files to support ZeptoOS features. The extra files are located in &amp;lt;tt&amp;gt;ramdisk/ION/ramdisk-add/&amp;lt;/tt&amp;gt;. The &amp;lt;tt&amp;gt;build-ramdisk&amp;lt;/tt&amp;gt; script from IBM BGP driver is used to create the ION ramdisks.&lt;br /&gt;
&lt;br /&gt;
The CN ramdisk is also a gzip'ed cpio archive of system files, but CN ramdisk is embedded into the CN kernel image (&amp;lt;tt&amp;gt;BGP-CN-zImage-with-initrd.elf&amp;lt;/tt&amp;gt;).  The CN ramdisk is created by a custom ramdisk build script (&amp;lt;tt&amp;gt;ramdisk/CN/create-bgp-cn-linux-ramdisk.pl&amp;lt;/tt&amp;gt;). Both &amp;lt;tt&amp;gt;build-ramdisk&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;create-bgp-cn-linux-ramdisk.pl&amp;lt;/tt&amp;gt; are wrappers around the Linux kernel's &amp;lt;tt&amp;gt;gen_init_cpio&amp;lt;/tt&amp;gt; command.&lt;br /&gt;
&lt;br /&gt;
==Creating ramdisk images==&lt;br /&gt;
&lt;br /&gt;
The ramdisk images are always (re-)created from prebuilt objects if one types &amp;lt;tt&amp;gt;make&amp;lt;/tt&amp;gt; at the top level directory (without any make target).&lt;br /&gt;
&lt;br /&gt;
If one wants to create an ION ramdisk individually (without rebuilding other images), type:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
$ make bgp-ion-ramdisk-cnl&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
If one wants to create a CN ramdisk (technically, create a CN kernel image with new ramdisk contents), type:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
$ make bgp-cn-linux&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
'''Note:''' the newly built CN ramdisk can be found in &amp;lt;tt&amp;gt;ramdisk/CN/bgp-cn-ramdisk.cpio.gz&amp;lt;/tt&amp;gt;, but it is not usable until it is embedded into the kernel image.&lt;br /&gt;
&lt;br /&gt;
For other ramdisk-related make targets, please refer to [[Configuration#Building|Configuration]].&lt;br /&gt;
&lt;br /&gt;
==Modifying ramdisk contents==&lt;br /&gt;
&lt;br /&gt;
You can customize ramdisk contents for your purpose, i.e., debugging, running your custom system software on BGP, etc.&lt;br /&gt;
&lt;br /&gt;
===CN ramdisk===&lt;br /&gt;
&lt;br /&gt;
The CN ramdisk can be customized by editing the CN ramdisk build script, which is &amp;lt;tt&amp;gt;ramdisk/CN/create-bgp-cn-linux-ramdisk.pl&amp;lt;/tt&amp;gt;.  The build script allows to set the permission bits, create device files, etc.&lt;br /&gt;
&lt;br /&gt;
Most of the contents of the CN ramdisk is kept in &amp;lt;tt&amp;gt;ramdisk/CN/tree/&amp;lt;/tt&amp;gt;, but this is not a hard rule.  Source files can reside anywhere as long as they are accessible from the script. It may be possible to use binaries and libraries from the login nodes, as long as they are a 32-bit PPC files (use the &amp;lt;tt&amp;gt;file&amp;lt;/tt&amp;gt; command to verify) and all their dependencies are also copied.&lt;br /&gt;
&lt;br /&gt;
Here is a practical example. Suppose that you need the &amp;lt;tt&amp;gt;od&amp;lt;/tt&amp;gt; command in CN ramdisk.  You could build the command from source code, but if you want to do something quick, you can try using the login node's version:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
$ file /usr/bin/od&lt;br /&gt;
/usr/bin/od: ELF 32-bit MSB executable, PowerPC or cisco 4500, version 1 (SYSV),&lt;br /&gt;
for GNU/Linux 2.6.4, dynamically linked (uses shared libs), for GNU/Linux 2.6.4, stripped&lt;br /&gt;
$ ldd /usr/bin/od&lt;br /&gt;
linux-vdso32.so.1 =&amp;gt;  (0x00100000)&lt;br /&gt;
libc.so.6 =&amp;gt; /lib/ppc970/libc.so.6 (0x0fe8b000)&lt;br /&gt;
/lib/ld.so.1 (0xf7fe1000)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
It is a 32-bit PPC executable and the current CN ramdisk has all the necessary shared libraries, so it can be used.  Now add the command to a perl array named &amp;lt;tt&amp;gt;@cmdlists&amp;lt;/tt&amp;gt; in &amp;lt;tt&amp;gt;ramdisk/CN/create-bgp-cn-linux-ramdisk.pl&amp;lt;/tt&amp;gt; script and invoke &amp;lt;tt&amp;gt;make&amp;lt;/tt&amp;gt; to recreate the CN ramdisk:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
$ vi ramdisk/CN/create-bgp-cn-linux-ramdisk.pl&lt;br /&gt;
# add the following line to @cmdlists &lt;br /&gt;
     &amp;quot;file /bin/od   /usr/bin/od 0755  0  0&amp;quot;,&lt;br /&gt;
$ make bgp-cn-linux&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Now the CN ramdisk has &amp;lt;tt&amp;gt;/bin/od&amp;lt;/tt&amp;gt; with file permissions &amp;lt;tt&amp;gt;0755&amp;lt;/tt&amp;gt;, uid &amp;lt;tt&amp;gt;0&amp;lt;/tt&amp;gt;, and gid &amp;lt;tt&amp;gt;0&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
The added line is a command for the &amp;lt;tt&amp;gt;gen_init_cpio&amp;lt;/tt&amp;gt; tool. One can also create directories, device files, symbolic links, named pipes, socket files, etc:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
file &amp;lt;name&amp;gt; &amp;lt;location&amp;gt; &amp;lt;mode&amp;gt; &amp;lt;uid&amp;gt; &amp;lt;gid&amp;gt;&lt;br /&gt;
dir &amp;lt;name&amp;gt; &amp;lt;mode&amp;gt; &amp;lt;uid&amp;gt; &amp;lt;gid&amp;gt;&lt;br /&gt;
nod &amp;lt;name&amp;gt; &amp;lt;mode&amp;gt; &amp;lt;uid&amp;gt; &amp;lt;gid&amp;gt; &amp;lt;dev_type&amp;gt; &amp;lt;maj&amp;gt; &amp;lt;min&amp;gt;&lt;br /&gt;
slink &amp;lt;name&amp;gt; &amp;lt;target&amp;gt; &amp;lt;mode&amp;gt; &amp;lt;uid&amp;gt; &amp;lt;gid&amp;gt;&lt;br /&gt;
pipe &amp;lt;name&amp;gt; &amp;lt;mode&amp;gt; &amp;lt;uid&amp;gt; &amp;lt;gid&amp;gt;&lt;br /&gt;
sock &amp;lt;name&amp;gt; &amp;lt;mode&amp;gt; &amp;lt;uid&amp;gt; &amp;lt;gid&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;name&amp;gt;      name of the file/dir/nod/etc in the archive&lt;br /&gt;
&amp;lt;location&amp;gt;  location of the file in the current filesystem&lt;br /&gt;
&amp;lt;target&amp;gt;    link target&lt;br /&gt;
&amp;lt;mode&amp;gt;      mode/permissions of the file&lt;br /&gt;
&amp;lt;uid&amp;gt;       user id (0=root)&lt;br /&gt;
&amp;lt;gid&amp;gt;       group id (0=root)&lt;br /&gt;
&amp;lt;dev_type&amp;gt;  device type (b=block, c=character)&lt;br /&gt;
&amp;lt;maj&amp;gt;       major number of nod&lt;br /&gt;
&amp;lt;min&amp;gt;       minor number of nod&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The order of the commands in @cmdlists ''matters''.  They are executed from top to bottom, so one cannot add a file to a directory that has not yet been created.&lt;br /&gt;
&lt;br /&gt;
====CN Linux startup script====&lt;br /&gt;
&lt;br /&gt;
The first thing that the Linux kernel does after it boots is to execute the &amp;lt;tt&amp;gt;init&amp;lt;/tt&amp;gt; program.  The &amp;lt;tt&amp;gt;init&amp;lt;/tt&amp;gt; program is usually in &amp;lt;tt&amp;gt;/sbin/&amp;lt;/tt&amp;gt;, and in the CN ramdisk case it is part of the busybox. &amp;lt;tt&amp;gt;init&amp;lt;/tt&amp;gt; reads in a config file from &amp;lt;tt&amp;gt;/etc/inittab&amp;lt;/tt&amp;gt;, which in our case instructs it to execute the &amp;lt;tt&amp;gt;/etc/init.d/rc.sysinit&amp;lt;/tt&amp;gt; startup script.&lt;br /&gt;
&lt;br /&gt;
Our startup script is very minimalistic; its two most important actions are to start the telnet daemon to allow users to login from the I/O nodes and then to start the ZOID &amp;lt;tt&amp;gt;control&amp;lt;/tt&amp;gt; process which takes care of IP forwarding and job control.&lt;br /&gt;
&lt;br /&gt;
In case you need to start some processes at the CN boot time, you can add their invocations to &amp;lt;tt&amp;gt;ramdisk/CN/tree/etc/init.d/rc.sysinit&amp;lt;/tt&amp;gt;, ''before'' &amp;lt;tt&amp;gt;/sbin/control&amp;lt;/tt&amp;gt; is invoked.&lt;br /&gt;
&lt;br /&gt;
===ION ramdisk===&lt;br /&gt;
&lt;br /&gt;
Unlike the CN ramdisk, the range of customization is limited on the ION ramdisk. There is no control over file permission bits, one cannot create device nodes, etc. Currently we build the ION ramdisk using IBM's &amp;lt;tt&amp;gt;build-ramdisk&amp;lt;/tt&amp;gt; script by specifying an add-on tree which contains our extra files.&lt;br /&gt;
&lt;br /&gt;
Essentially, customization is limited to:&lt;br /&gt;
* adding new files,&lt;br /&gt;
* overwriting default ramdisk files by adding custom files with the same names.&lt;br /&gt;
&lt;br /&gt;
Once files have been added under &amp;lt;tt&amp;gt;ramdisk/ION/ramdisk-add/&amp;lt;/tt&amp;gt;, they will be automatically added to the ramdisk on the next rebuild.  Here is an example of how to add a file to the ION ramdisk:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
$ vi ramdisk/ION/ramdisk-add/etc/yourfile&lt;br /&gt;
$ make bgp-ion-ramdisk-cnl&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
If you need more than file adding, you might need to edit the &amp;lt;tt&amp;gt;build-ramdisk&amp;lt;/tt&amp;gt; script itself. The script is located in &amp;lt;tt&amp;gt;/bgsys/drivers/ppcfloor/&amp;lt;/tt&amp;gt;. Copy the script to a working directory, edit it and change the script path in &amp;lt;tt&amp;gt;ramdisk/ION/Makefile&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
====ION startup script====&lt;br /&gt;
&lt;br /&gt;
There is no &amp;lt;tt&amp;gt;rc.sysinit&amp;lt;/tt&amp;gt; in &amp;lt;tt&amp;gt;ramdisk/ION/ramdisk-add/&amp;lt;/tt&amp;gt;, because &amp;lt;tt&amp;gt;rc.sysinit&amp;lt;/tt&amp;gt; is provided in the IBM ramdisk tree (i.e., &amp;lt;tt&amp;gt;/bgsys/drivers/ppcfloor/ramdisk/etc/init.d/rc.sysinit&amp;lt;/tt&amp;gt; is the default one).  If needed, copy the default one to the ZeptoOS &amp;lt;tt&amp;gt;ramdisk/etc/init.d/rc.sysinit&amp;lt;/tt&amp;gt; and modify it to change the startup behaviour, but this is in general not recommended.&lt;br /&gt;
&lt;br /&gt;
In most cases, what one is looking for is to start a process at the ION boot time.  For such purpose, one can add a custom ION RC script to &amp;lt;tt&amp;gt;ramdisk-add/etc/init.d/rc3.d/&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
RC scripts have the following naming convention:&lt;br /&gt;
&lt;br /&gt;
* S##xxxx : boot-time scripts&lt;br /&gt;
* K##xxxx : shut-down scripts&lt;br /&gt;
&lt;br /&gt;
The script names start with &amp;lt;tt&amp;gt;S&amp;lt;/tt&amp;gt; or &amp;lt;tt&amp;gt;K&amp;lt;/tt&amp;gt;; those starting with &amp;lt;tt&amp;gt;S&amp;lt;/tt&amp;gt; are the boot-time scripts and those starting with &amp;lt;tt&amp;gt;K&amp;lt;/tt&amp;gt; are the shut-down scripts.  The two-digit number following the &amp;lt;tt&amp;gt;S&amp;lt;/tt&amp;gt; or &amp;lt;tt&amp;gt;K&amp;lt;/tt&amp;gt; is used to determine the execution order; scripts with lower numbers are executed earlier. The number is followed by the script name. On execution, &amp;quot;start&amp;quot; is passed as the first argument to boot-time scripts, and &amp;quot;stop&amp;quot; to shut-down scripts, so the same script can be used for both purposes.  Here is a template of an RC script:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
#!/bin/sh&lt;br /&gt;
. /etc/rc.status&lt;br /&gt;
&lt;br /&gt;
rc_reset&lt;br /&gt;
case &amp;quot;$1&amp;quot; in&lt;br /&gt;
    start)&lt;br /&gt;
        # fill here #&lt;br /&gt;
        ;;&lt;br /&gt;
    stop)&lt;br /&gt;
        # fill here #&lt;br /&gt;
        ;;&lt;br /&gt;
    restart)&lt;br /&gt;
        # fill here #&lt;br /&gt;
        ;;&lt;br /&gt;
    status)&lt;br /&gt;
        # fill here #&lt;br /&gt;
        ;;&lt;br /&gt;
    *)&lt;br /&gt;
	echo &amp;quot;Usage: $0 {start|stop|restart|status}&amp;quot;&lt;br /&gt;
	exit 1&lt;br /&gt;
	;;&lt;br /&gt;
esac&lt;br /&gt;
rc_exit&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The ZeptoOS ION ramdisk contains the following RC scripts by default (some of these are ZeptoOS-specific, others come from the IBM ramdisk tree):&lt;br /&gt;
&lt;br /&gt;
'''boot''' scripts:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
S00zepto&lt;br /&gt;
S01bootsysctl&lt;br /&gt;
S02syslog&lt;br /&gt;
S05ntp&lt;br /&gt;
S11sshd&lt;br /&gt;
S12zepto&lt;br /&gt;
S40gpfs&lt;br /&gt;
S43ibmcmp&lt;br /&gt;
S46essl&lt;br /&gt;
S50ciod&lt;br /&gt;
S51zoid&lt;br /&gt;
S99zepto&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
'''shutdown''' scripts:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
K05ntp&lt;br /&gt;
K10sshd&lt;br /&gt;
K15ciod&lt;br /&gt;
K20gpfs&lt;br /&gt;
K30syslog&lt;br /&gt;
K50bgsys.64&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Ramdisk size limitation===&lt;br /&gt;
&lt;br /&gt;
In regular Linux environments, ramdisk size is limited by free memory size at the time when ramdisk is loaded into memory. However, on BGP, closed-source partition booting software cannot handle images of arbitrary sizes. We do not have an exact number on the boot image size limitation, but we have seen with the current software stack that images of 100&amp;amp;nbsp;MB or larger might fail to boot. After adding large files to the ramdisk, please check the size of the generated image files, specifically &amp;lt;tt&amp;gt;BGP-ION-ramdisk-for-CNL.elf&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;BGP-CN-zImage-with-initrd.elf&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
==Extracting files from an existing ramdisk image==&lt;br /&gt;
&lt;br /&gt;
To extract files from an existing ramdisk image, do the following (ION ramdisk only):&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
$ ./packages/tools/z-extract-cpio-from-ramdisk.sh  &amp;lt;existing_ramdisk_image&amp;gt; ramdisk.cpio&lt;br /&gt;
$ mkdir treeroot &amp;amp;&amp;amp; cd treeroot&lt;br /&gt;
$ cpio -idv &amp;lt; ../ramdisk.cpio&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
[[Kernel]] | [[ZeptoOS_Documentation|Top]] | [[ZOID]]&lt;/div&gt;</summary>
		<author><name>Iskra</name></author>
	</entry>
	<entry>
		<id> /zeptoos/index.php?title=Ramdisk&amp;diff=603</id>
		<title>Ramdisk</title>
		<link rel="alternate" type="text/html" href=" /zeptoos/index.php?title=Ramdisk&amp;diff=603"/>
		<updated>2009-05-08T21:28:40Z</updated>

		<summary type="html">&lt;p&gt;Iskra: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;[[Kernel]] | [[ZeptoOS_Documentation|Top]] | [[ZOID]]&lt;br /&gt;
----&lt;br /&gt;
&lt;br /&gt;
==Introduction==&lt;br /&gt;
&lt;br /&gt;
Both the CN and the ION Linux kernels require a ramdisk to boot.  Ramdisk images contain minimal Linux utilities, init scripts, configuration files, kernel modules, etc, which are required by the OS boot process.&lt;br /&gt;
&lt;br /&gt;
ION ramdisk is an ELF file that contains a cpio archive of system files. Two ION ramdisk images are currently generated:&lt;br /&gt;
&lt;br /&gt;
; BGP-ION-ramdisk-for-CNL.elf&lt;br /&gt;
: Default ION ramdisk for ZeptoOS compute node Linux.&lt;br /&gt;
; BGP-ION-ramdisk-for-CNK.elf &lt;br /&gt;
: Use this one if you need to run IBM CNK on the compute nodes (uses IBM CIOD instead of ZOID)&lt;br /&gt;
&lt;br /&gt;
Our ION ramdisks are similar to the default ION ramdisk from IBM, but we add some extra files to support ZeptoOS features. The extra files are located in &amp;lt;tt&amp;gt;ramdisk/ION/ramdisk-add/&amp;lt;/tt&amp;gt;. The &amp;lt;tt&amp;gt;build-ramdisk&amp;lt;/tt&amp;gt; script from IBM BGP driver is used to create the ION ramdisks.&lt;br /&gt;
&lt;br /&gt;
The CN ramdisk is also a gzip'ed cpio archive of system files, but CN ramdisk is embedded into the CN kernel image (&amp;lt;tt&amp;gt;BGP-CN-zImage-with-initrd.elf&amp;lt;/tt&amp;gt;).  The CN ramdisk is created by a custom ramdisk build script (&amp;lt;tt&amp;gt;ramdisk/CN/create-bgp-cn-linux-ramdisk.pl&amp;lt;/tt&amp;gt;). Both &amp;lt;tt&amp;gt;build-ramdisk&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;create-bgp-cn-linux-ramdisk.pl&amp;lt;/tt&amp;gt; are wrappers around the Linux kernel's &amp;lt;tt&amp;gt;gen_init_cpio&amp;lt;/tt&amp;gt; command.&lt;br /&gt;
&lt;br /&gt;
==Creating ramdisk images==&lt;br /&gt;
&lt;br /&gt;
The ramdisk images are always (re-)created from prebuilt objects if one types &amp;lt;tt&amp;gt;make&amp;lt;/tt&amp;gt; at the top level directory (without any make target).&lt;br /&gt;
&lt;br /&gt;
If one wants to create an ION ramdisk individually (without rebuilding other images), type:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
$ make bgp-ion-ramdisk-cnl&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
If one wants to create a CN ramdisk (technically, create a CN kernel image with new ramdisk contents), type:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
$ make bgp-cn-linux&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
'''Note:''' the newly built CN ramdisk can be found in &amp;lt;tt&amp;gt;ramdisk/CN/bgp-cn-ramdisk.cpio.gz&amp;lt;/tt&amp;gt;, but it is not usable until it is embedded into the kernel image.&lt;br /&gt;
&lt;br /&gt;
For other ramdisk-related make targets, please refer to [[Configuration#Building|Configuration]].&lt;br /&gt;
&lt;br /&gt;
==Modifying ramdisk contents==&lt;br /&gt;
&lt;br /&gt;
You can customize ramdisk contents for your purpose, i.e., debugging, running your custom system software on BGP, etc.&lt;br /&gt;
&lt;br /&gt;
===CN ramdisk===&lt;br /&gt;
&lt;br /&gt;
The CN ramdisk can be customized by editing the CN ramdisk build script, which is &amp;lt;tt&amp;gt;ramdisk/CN/create-bgp-cn-linux-ramdisk.pl&amp;lt;/tt&amp;gt;.  The build script allows to set the permission bits, create device files, etc.&lt;br /&gt;
&lt;br /&gt;
Most of the contents of the CN ramdisk is kept in &amp;lt;tt&amp;gt;ramdisk/CN/tree/&amp;lt;/tt&amp;gt;, but this is not a hard rule.  Source files can reside anywhere as long as they are accessible from the script. It may be possible to use binaries and libraries from the login nodes, as long as they are a 32-bit PPC files (use the &amp;lt;tt&amp;gt;file&amp;lt;/tt&amp;gt; command to verify) and all their dependencies are also copied.&lt;br /&gt;
&lt;br /&gt;
Here is a practical example. Suppose that you need the &amp;lt;tt&amp;gt;od&amp;lt;/tt&amp;gt; command in CN ramdisk.  You could build the command from source code, but if you want to do something quick, you can try using the login node's version:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
$ file /usr/bin/od&lt;br /&gt;
/usr/bin/od: ELF 32-bit MSB executable, PowerPC or cisco 4500, version 1 (SYSV),&lt;br /&gt;
for GNU/Linux 2.6.4, dynamically linked (uses shared libs), for GNU/Linux 2.6.4, stripped&lt;br /&gt;
$ ldd /usr/bin/od&lt;br /&gt;
linux-vdso32.so.1 =&amp;gt;  (0x00100000)&lt;br /&gt;
libc.so.6 =&amp;gt; /lib/ppc970/libc.so.6 (0x0fe8b000)&lt;br /&gt;
/lib/ld.so.1 (0xf7fe1000)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
It is a 32-bit PPC executable and the current CN ramdisk has all the necessary shared libraries, so it can be used.  Now add the command to a perl array named &amp;lt;tt&amp;gt;@cmdlists&amp;lt;/tt&amp;gt; in &amp;lt;tt&amp;gt;ramdisk/CN/create-bgp-cn-linux-ramdisk.pl&amp;lt;/tt&amp;gt; script and type &amp;lt;tt&amp;gt;make&amp;lt;/tt&amp;gt; to recreate the CN ramdisk:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
$ vi ramdisk/CN/create-bgp-cn-linux-ramdisk.pl&lt;br /&gt;
# add the following line to @cmdlists &lt;br /&gt;
     &amp;quot;file /bin/od   /usr/bin/od 0755  0  0&amp;quot;,&lt;br /&gt;
$ make bgp-cn-linux&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Now the CN ramdisk has &amp;lt;tt&amp;gt;/bin/od&amp;lt;/tt&amp;gt; with file permissions &amp;lt;tt&amp;gt;0755&amp;lt;/tt&amp;gt;, uid=0, and gid=0.&lt;br /&gt;
&lt;br /&gt;
The added line is a command for the &amp;lt;tt&amp;gt;gen_init_cpio&amp;lt;/tt&amp;gt; tool. One can also create directories, device files, symbolick links, pipe files, socket files, etc:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
file &amp;lt;name&amp;gt; &amp;lt;location&amp;gt; &amp;lt;mode&amp;gt; &amp;lt;uid&amp;gt; &amp;lt;gid&amp;gt;&lt;br /&gt;
dir &amp;lt;name&amp;gt; &amp;lt;mode&amp;gt; &amp;lt;uid&amp;gt; &amp;lt;gid&amp;gt;&lt;br /&gt;
nod &amp;lt;name&amp;gt; &amp;lt;mode&amp;gt; &amp;lt;uid&amp;gt; &amp;lt;gid&amp;gt; &amp;lt;dev_type&amp;gt; &amp;lt;maj&amp;gt; &amp;lt;min&amp;gt;&lt;br /&gt;
slink &amp;lt;name&amp;gt; &amp;lt;target&amp;gt; &amp;lt;mode&amp;gt; &amp;lt;uid&amp;gt; &amp;lt;gid&amp;gt;&lt;br /&gt;
pipe &amp;lt;name&amp;gt; &amp;lt;mode&amp;gt; &amp;lt;uid&amp;gt; &amp;lt;gid&amp;gt;&lt;br /&gt;
sock &amp;lt;name&amp;gt; &amp;lt;mode&amp;gt; &amp;lt;uid&amp;gt; &amp;lt;gid&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;name&amp;gt;      name of the file/dir/nod/etc in the archive&lt;br /&gt;
&amp;lt;location&amp;gt;  location of the file in the current filesystem&lt;br /&gt;
&amp;lt;target&amp;gt;    link target&lt;br /&gt;
&amp;lt;mode&amp;gt;      mode/permissions of the file&lt;br /&gt;
&amp;lt;uid&amp;gt;       user id (0=root)&lt;br /&gt;
&amp;lt;gid&amp;gt;       group id (0=root)&lt;br /&gt;
&amp;lt;dev_type&amp;gt;  device type (b=block, c=character)&lt;br /&gt;
&amp;lt;maj&amp;gt;       major number of nod&lt;br /&gt;
&amp;lt;min&amp;gt;       minor number of nod&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The order of the commands in @cmdlists ''matters''.  They are executed from top to bottom, so one cannot add a file to a directory that has not yet been created.&lt;br /&gt;
&lt;br /&gt;
====CN Linux startup script====&lt;br /&gt;
&lt;br /&gt;
The first thing that the Linux kernel does after it boots is to execute the &amp;lt;tt&amp;gt;init&amp;lt;/tt&amp;gt; program.  The &amp;lt;tt&amp;gt;init&amp;lt;/tt&amp;gt; program is usually in &amp;lt;tt&amp;gt;/sbin/&amp;lt;/tt&amp;gt;, and in the CN ramdisk case it is part of the busybox. &amp;lt;tt&amp;gt;init&amp;lt;/tt&amp;gt; reads in a config file from &amp;lt;tt&amp;gt;/etc/inittab&amp;lt;/tt&amp;gt;, which in our case instructs it to execute the &amp;lt;tt&amp;gt;/etc/init.d/rc.sysinit&amp;lt;/tt&amp;gt; startup script.&lt;br /&gt;
&lt;br /&gt;
Our startup script is very minimalistic; its two most important actions are to start the telnet daemon to allow users to login from the I/O nodes and then to start the ZOID &amp;lt;tt&amp;gt;control&amp;lt;/tt&amp;gt; process which takes care of IP forwarding and job control.&lt;br /&gt;
&lt;br /&gt;
In case you need to start some processes at the CN boot time, you can add their invocations to &amp;lt;tt&amp;gt;ramdisk/CN/tree/etc/init.d/rc.sysinit&amp;lt;/tt&amp;gt;, ''before'' &amp;lt;tt&amp;gt;/sbin/control&amp;lt;/tt&amp;gt; is invoked.&lt;br /&gt;
&lt;br /&gt;
===ION ramdisk===&lt;br /&gt;
&lt;br /&gt;
Unlike the CN ramdisk, the range of customization is limited on the ION ramdisk. There is no control over file permission bits, one cannot create device nodes, etc. Currently we build the ION ramdisk using IBM's &amp;lt;tt&amp;gt;build-ramdisk&amp;lt;/tt&amp;gt; script by specifying an add-on tree which contains our extra files.&lt;br /&gt;
&lt;br /&gt;
Essentially, customization is limited to:&lt;br /&gt;
* adding new files,&lt;br /&gt;
* overwriting default ramdisk files by adding custom files with the same names.&lt;br /&gt;
&lt;br /&gt;
Once files have been added under &amp;lt;tt&amp;gt;ramdisk/ION/ramdisk-add/&amp;lt;/tt&amp;gt;, they will be automatically added to the ramdisk on the next rebuild.  Here is an example of how to add a file to the ION ramdisk:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
$ vi ramdisk/ION/ramdisk-add/etc/yourfile&lt;br /&gt;
$ make bgp-ion-ramdisk-cnl&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
If you need more than file adding, you might need to edit the &amp;lt;tt&amp;gt;build-ramdisk&amp;lt;/tt&amp;gt; script itself. The script is located in &amp;lt;tt&amp;gt;/bgsys/drivers/ppcfloor/&amp;lt;/tt&amp;gt;. Copy the script to a working directory, edit it and change the script path in &amp;lt;tt&amp;gt;ramdisk/ION/Makefile&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
====ION startup script====&lt;br /&gt;
&lt;br /&gt;
There is no &amp;lt;tt&amp;gt;rc.sysinit&amp;lt;/tt&amp;gt; in &amp;lt;tt&amp;gt;ramdisk/ION/ramdisk-add/&amp;lt;/tt&amp;gt;, because &amp;lt;tt&amp;gt;rc.sysinit&amp;lt;/tt&amp;gt; is provided in the IBM ramdisk tree (i.e., &amp;lt;tt&amp;gt;/bgsys/drivers/ppcfloor/ramdisk/etc/init.d/rc.sysinit&amp;lt;/tt&amp;gt; is default one).  If needed, one can copy the default one to the ZeptoOS &amp;lt;tt&amp;gt;ramdisk/etc/init.d/rc.sysinit&amp;lt;/tt&amp;gt; and modify it to change the startup behaviour, but this is in general not recommended.&lt;br /&gt;
&lt;br /&gt;
In most cases, what one is looking for is to start a process at the ION boot time.  For such purpose, one can add a custom ION RC script to &amp;lt;tt&amp;gt;ramdisk-add/etc/init.d/rc3.d/&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
RC scripts have the following naming convention:&lt;br /&gt;
&lt;br /&gt;
* S##xxxx : boot-time scripts&lt;br /&gt;
* K##xxxx : shut-down scripts&lt;br /&gt;
&lt;br /&gt;
They start with &amp;lt;tt&amp;gt;S&amp;lt;/tt&amp;gt; or &amp;lt;tt&amp;gt;K&amp;lt;/tt&amp;gt;; those starting with &amp;lt;tt&amp;gt;S&amp;lt;/tt&amp;gt; are the boot-time scripts and those starting with &amp;lt;tt&amp;gt;K&amp;lt;/tt&amp;gt; are the shut-down scripts.  The two-digit number following &amp;lt;tt&amp;gt;S&amp;lt;/tt&amp;gt; or &amp;lt;tt&amp;gt;K&amp;lt;/tt&amp;gt; is used to determine the execution order; scripts with lower numbers are executed earlier. The number is followed by the script name. On execution, &amp;quot;start&amp;quot; is passed as the first argument to boot-time scripts, and &amp;quot;stop&amp;quot; to shut-down scripts.  Here is a template of an RC script:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
#!/bin/sh&lt;br /&gt;
. /etc/rc.status&lt;br /&gt;
&lt;br /&gt;
rc_reset&lt;br /&gt;
case &amp;quot;$1&amp;quot; in&lt;br /&gt;
    start)&lt;br /&gt;
        # fill here #&lt;br /&gt;
        ;;&lt;br /&gt;
    stop)&lt;br /&gt;
        # fill here #&lt;br /&gt;
        ;;&lt;br /&gt;
    restart)&lt;br /&gt;
        # fill here #&lt;br /&gt;
        ;;&lt;br /&gt;
    status)&lt;br /&gt;
        # fill here #&lt;br /&gt;
        ;;&lt;br /&gt;
    *)&lt;br /&gt;
	echo &amp;quot;Usage: $0 {start|stop|restart|status}&amp;quot;&lt;br /&gt;
	exit 1&lt;br /&gt;
	;;&lt;br /&gt;
esac&lt;br /&gt;
rc_exit&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The ZeptoOS ION ramdisk contains the following RC scripts by default (some of these are ZeptoOS-specific, others come from the IBM ramdisk tree):&lt;br /&gt;
&lt;br /&gt;
'''boot''' scripts:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
S00zepto&lt;br /&gt;
S01bootsysctl&lt;br /&gt;
S02syslog&lt;br /&gt;
S05ntp&lt;br /&gt;
S11sshd&lt;br /&gt;
S12zepto&lt;br /&gt;
S40gpfs&lt;br /&gt;
S43ibmcmp&lt;br /&gt;
S46essl&lt;br /&gt;
S50ciod&lt;br /&gt;
S51zoid&lt;br /&gt;
S99zepto&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
'''shutdown''' scripts:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
K05ntp&lt;br /&gt;
K10sshd&lt;br /&gt;
K15ciod&lt;br /&gt;
K20gpfs&lt;br /&gt;
K30syslog&lt;br /&gt;
K50bgsys.64&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Ramdisk size limitation===&lt;br /&gt;
&lt;br /&gt;
In regular Linux environments, ramdisk size is limited by free memory size at the time when ramdisk is loaded into memory. However, on BGP, closed-source system software cannot handle images of arbitrary sizes. We do not have an exact number on the boot image size limitation, but we have seen with the current software stack that images of 100&amp;amp;nbsp;MB or larger might fail to boot. If one adds large files to the ramdisk, please check the size of the generated image files, specifically &amp;lt;tt&amp;gt;BGP-ION-ramdisk-for-CNL.elf&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;BGP-CN-zImage-with-initrd.elf&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
==Extracting files from an existing ramdisk image==&lt;br /&gt;
&lt;br /&gt;
To extract file from an existing ramdisk image, do the following (ION ramdisk only):&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
$ ./packages/tools/z-extract-cpio-from-ramdisk.sh  &amp;lt;existing_ramdisk_image&amp;gt; ramdisk.cpio&lt;br /&gt;
$ mkdir treeroot &amp;amp;&amp;amp; cd treeroot&lt;br /&gt;
$ cpio -idv &amp;lt; ../ramdisk.cpio&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
[[Kernel]] | [[ZeptoOS_Documentation|Top]] | [[ZOID]]&lt;/div&gt;</summary>
		<author><name>Iskra</name></author>
	</entry>
	<entry>
		<id> /zeptoos/index.php?title=MPICH,_DCMF,_and_SPI&amp;diff=602</id>
		<title>MPICH, DCMF, and SPI</title>
		<link rel="alternate" type="text/html" href=" /zeptoos/index.php?title=MPICH,_DCMF,_and_SPI&amp;diff=602"/>
		<updated>2009-05-08T20:44:14Z</updated>

		<summary type="html">&lt;p&gt;Iskra: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;[[Testing]] | [[ZeptoOS_Documentation|Top]] | [[Kernel]]&lt;br /&gt;
----&lt;br /&gt;
&lt;br /&gt;
==Introduction==&lt;br /&gt;
&lt;br /&gt;
To support high performance computing (HPC) applications, specifically MPI applications, we have ported IBM's CNK communication software stack to the ZeptoOS compute node Linux environment.  MPICH used in this ZeptoOS release is mpich2-1.0.7 with IBM patches. It is reasonably stable, and the performance of MPI applications on the ZeptoOS compute node Linux is comparable to that on CNK.  While there are some limitations at the moment, there are benefits as well.&lt;br /&gt;
&lt;br /&gt;
Benefits:&lt;br /&gt;
* No limitation on the number of threads&lt;br /&gt;
** 4 or more OpenMP threads per node&lt;br /&gt;
** Additional threads as I/O or backgroup tasks&lt;br /&gt;
* It is Linux!&lt;br /&gt;
** Debugging tools such as gdb, strace, etc&lt;br /&gt;
** Various file systems, such as ramfs&lt;br /&gt;
&lt;br /&gt;
Current limitations:&lt;br /&gt;
* Only the SMP mode is supported&lt;br /&gt;
* Shared libraries are not provided at the moment&lt;br /&gt;
* No binary compatibility between CNK and ZeptoOS CN Linux MPI binaries&lt;br /&gt;
&lt;br /&gt;
We will support a VN-equivalent mode (multiple MPI tasks per node) and provide shared libraries in a future release.&lt;br /&gt;
&lt;br /&gt;
As in IBM CNK environment, Deep Computing Messaging Framework (DCMF) and System Programming Interface (SPI) are available.  It is possible to write a DCMF code or an SPI code directly if necessary. DCMF is a communication library that provides non-blocking operations. Please refer to the [http://dcmf.anl-external.org/wiki/index.php/Main_Page DCMF wiki] for details.  We are using DCMF version 1.0.0 in the current ZeptoOS release, which is older than the DCMF in the current driver release (V1R3M0). SPI is the lowest-level user-space API for the torus DMA, collective network, BGP-specifc lock mechanisms, and other compute node specific features.  There is no public document on SPI available at the moment, but almost all header files and source code are available. Internally, MPICH depends on DMCF, which in turn depends on SPI.  We will say more about it [[#Software stack layout|later]].&lt;br /&gt;
&lt;br /&gt;
===ZCB and Big memory===&lt;br /&gt;
&lt;br /&gt;
MPI applications running under the ZeptoOS compute node Linux environment (technically, applications that require the DMA operation or a maximum memory bandwidth) need to be configured as Zepto Compute Binaries (ZCB).  This is done using the &amp;lt;tt&amp;gt;zelftool&amp;lt;/tt&amp;gt;, which is invoked behind the scenes when linking a binary using the ZeptoOS MPI compiler wrapper scripts (&amp;lt;tt&amp;gt;zmpicc&amp;lt;/tt&amp;gt;, etc).&lt;br /&gt;
&lt;br /&gt;
ZeptoOS compute node kernel treats ZCB executables differently from ordinary processes. It creates a special memory mapping region called big memory, which is covered by large pages with semi-static TLB entries, and it loads all application sections to the big memory region. Big memory region has virtually no TLB misses and it also enables DMA operations.&lt;br /&gt;
&lt;br /&gt;
Some system calls will not work correctly if used from a ZCB process, in particular &amp;lt;tt&amp;gt;fork&amp;lt;/tt&amp;gt; (but creating threads ''does'' work).  Also, being a separate memory region set up at kernel boot time, the size of big memory is fixed.  It is set to 256&amp;amp;nbsp;MB by default, which could be too small for larger MPI processes; it can be [[FAQ#Why large MPI processes do not work|increased]] before booting a partition, at the expense of the ordinary Linux paged memory.&lt;br /&gt;
&lt;br /&gt;
==Compiling HPC applications==&lt;br /&gt;
&lt;br /&gt;
While the same compiler can be used as for the applications running under the IBM CNK, ZeptoOS compute node environment requires linking with ZeptoOS-specific communication libraries (applications linked with the CNK MPI will not work on ZeptoOS).&lt;br /&gt;
&lt;br /&gt;
===Compiler wrapper scripts===&lt;br /&gt;
&lt;br /&gt;
We provide compiler wrapper scripts which automatically link with appropriate libraries from the ZeptoOS installation directory.  We provide the same set of wrapper scripts that IBM provides, with an extra &amp;lt;tt&amp;gt;z&amp;lt;/tt&amp;gt; prefix:&lt;br /&gt;
&lt;br /&gt;
; zmpicc, zmpicxx, zmpif77, zmpif90&lt;br /&gt;
: Wrapper scripts that invoke BGP-enhanced GNU compilers&lt;br /&gt;
&lt;br /&gt;
; zmpixlc, zmpixlcxx, zmpixlf2003, zmpixlf77, zmpixlf90, zmpixlf95&lt;br /&gt;
: Wrapper scripts that invoke IBM XL compilers&lt;br /&gt;
&lt;br /&gt;
; zmpixlc_r, zmpixlcxx_r, zmpixlf2003_r, zmpixlf77_r, zmpixlf90_r, zmpixlf95_r&lt;br /&gt;
: Wrapper scripts that invoke IBM XL compilers (thread safe compilation for OpenMP)&lt;br /&gt;
&lt;br /&gt;
To get insight into the internals of these scripts, invoke them with the &amp;lt;tt&amp;gt;-show&amp;lt;/tt&amp;gt; option.&lt;br /&gt;
&lt;br /&gt;
====A compilation example====&lt;br /&gt;
&lt;br /&gt;
There is nothing special about compiling a program for ZeptoOS.  Here is a real-world example of how to build a well-known [http://climate.lanl.gov/Models/POP/ Parallel Ocean Program (POP)].&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
$ wget http://climate.lanl.gov/Models/POP/POP_2.0.1.tar.Z&lt;br /&gt;
$ tar xvfz POP_2.0.1.tar.Z &amp;amp;&amp;amp; cd pop&lt;br /&gt;
$ ./setup_run_dir ztest &amp;amp;&amp;amp; cd ztest&lt;br /&gt;
$ edit ibm_mpi.gnu   # see the patch below&lt;br /&gt;
$ export ARCHDIR=ibm_mpi&lt;br /&gt;
$ make   # takes a while&lt;br /&gt;
$ edit pop_in   # test data set&lt;br /&gt;
-  nprocs_clinic = 4&lt;br /&gt;
-  nprocs_tropic = 4&lt;br /&gt;
+  nprocs_clinic = 64&lt;br /&gt;
+  nprocs_tropic = 64&lt;br /&gt;
$ cqsub -n 64 -t 10 -k &amp;lt;zepto_profile&amp;gt; ./pop&lt;br /&gt;
&lt;br /&gt;
--------------------&lt;br /&gt;
--- orig/ibm_mpi.gnu    2009-04-15 15:01:58.666457601 -0500&lt;br /&gt;
+++ ztest/ibm_mpi.gnu    2009-04-15 14:17:58.099132435 -0500&lt;br /&gt;
@@ -6,17 +6,18 @@&lt;br /&gt;
# will someday be a file which is a cookbook in Q&amp;amp;A style: &amp;quot;How do I do X?&amp;quot;&lt;br /&gt;
# is followed by something like &amp;quot;Go to file Y and add Z to line NNN.&amp;quot;&lt;br /&gt;
#&lt;br /&gt;
-FC = mpxlf90_r&lt;br /&gt;
-LD = mpxlf90_r&lt;br /&gt;
-CC = mpcc_r&lt;br /&gt;
-Cp = /usr/bin/cp&lt;br /&gt;
-Cpp = /usr/ccs/lib/cpp -P&lt;br /&gt;
+ZPATH=&amp;lt;zepto_dir&amp;gt;&lt;br /&gt;
+FC = $(ZPATH)/zmpixlf90&lt;br /&gt;
+LD = $(ZPATH)/zmpixlf90&lt;br /&gt;
+CC = $(ZPATH)/zmpixlc&lt;br /&gt;
+Cp = /bin/cp&lt;br /&gt;
+Cpp = /usr/bin/cpp -P&lt;br /&gt;
AWK = /usr/bin/awk&lt;br /&gt;
-ABI = -q64&lt;br /&gt;
+#ABI = -q64&lt;br /&gt;
COMMDIR = mpi&lt;br /&gt;
&lt;br /&gt;
-NETCDFINC = -I/usr/local/include&lt;br /&gt;
-NETCDFLIB = -L/usr/local/lib&lt;br /&gt;
+NETCDFINC = -I/soft/apps/netcdf-4.0/include/&lt;br /&gt;
+NETCDFLIB = -L/soft/apps/netcdf-4.0/lib&lt;br /&gt;
&lt;br /&gt;
#  Enable MPI library for parallel code, yes/no.&lt;br /&gt;
&lt;br /&gt;
@@ -58,7 +59,8 @@&lt;br /&gt;
#&lt;br /&gt;
#----------------------------------------------------------------------------&lt;br /&gt;
&lt;br /&gt;
-FBASE = $(ABI) -qarch=auto -qnosave -bmaxdata:0x80000000 $(NETCDFINC) -I$(ObjDepDir)&lt;br /&gt;
+#FBASE = $(ABI) -qarch=auto -qnosave -bmaxdata:0x80000000 $(NETCDFINC) -I$(ObjDepDir)&lt;br /&gt;
+FBASE = $(ABI) -qarch=auto -qnosave  $(NETCDFINC) -I$(ObjDepDir)&lt;br /&gt;
&lt;br /&gt;
ifeq ($(TRAP_FPE),yes)&lt;br /&gt;
  FBASE := $(FBASE) -qflttrap=overflow:zerodivide:enable -qspillsize=32704&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Compiling without the wrapper scripts===&lt;br /&gt;
&lt;br /&gt;
If one wishes to invoke the compiler directly, please make sure that the Makefile or build environment points to ZeptoOS header files and libraries correctly. An example would be:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
$ /bgsys/drivers/ppcfloor/gnu-linux/bin/powerpc-bgp-linux-gcc \&lt;br /&gt;
-o mpi-test-linux -Wall -O3 -I&amp;lt;zepto_dir&amp;gt;/include mpi-test.c \&lt;br /&gt;
-L&amp;lt;zepto_dir&amp;gt;/lib -lmpich.zcl -ldcmfcoll.zcl -ldcmf.zcl -lSPI.zcl -lzcl \&lt;br /&gt;
-lzoid_cn -lrt -lpthread -lm&lt;br /&gt;
$ &amp;lt;zepto_dir&amp;gt;/bin/zelftool -e mpi-test-linux&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
'''Notes:''' &lt;br /&gt;
* Replace &amp;lt;tt&amp;gt;&amp;lt;zepto_dir&amp;gt;&amp;lt;/tt&amp;gt; with the ZeptoOS install path.&lt;br /&gt;
* Do not forget to call the &amp;lt;tt&amp;gt;zelftool&amp;lt;/tt&amp;gt; utility, which makes the executable a Zepto Compute Binary.&lt;br /&gt;
&amp;lt;!--&lt;br /&gt;
The file layout in the zepto install path would be:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
|-- bin&lt;br /&gt;
|   |-- zelftool&lt;br /&gt;
|-- include&lt;br /&gt;
|   |-- dcmf.h&lt;br /&gt;
|   |-- dcmf_collectives.h&lt;br /&gt;
|   |-- dcmf_coremath.h&lt;br /&gt;
|   |-- dcmf_globalcollectives.h&lt;br /&gt;
|   |-- dcmf_multisend.h&lt;br /&gt;
|   |-- dcmf_optimath.h&lt;br /&gt;
|   |-- mpe_thread.h&lt;br /&gt;
|   |-- mpi.h&lt;br /&gt;
|   |-- mpi.mod&lt;br /&gt;
|   |-- mpi_base.mod&lt;br /&gt;
|   |-- mpi_constants.mod&lt;br /&gt;
|   |-- mpi_sizeofs.mod&lt;br /&gt;
|   |-- mpicxx.h&lt;br /&gt;
|   |-- mpif.h&lt;br /&gt;
|   |-- mpio.h&lt;br /&gt;
|   |-- mpiof.h&lt;br /&gt;
|   `-- mpix.h&lt;br /&gt;
`-- lib&lt;br /&gt;
    |-- libSPI.zcl.a&lt;br /&gt;
    |-- libcxxmpich.zcl.a&lt;br /&gt;
    |-- libdcmf.zcl.a&lt;br /&gt;
    |-- libdcmfcoll.zcl.a&lt;br /&gt;
    |-- libfmpich.zcl.a&lt;br /&gt;
    |-- libfmpich_.zcl.a&lt;br /&gt;
    |-- libmpich.zcl.a&lt;br /&gt;
    |-- libmpich.zclf90.a&lt;br /&gt;
    |-- libzcl.a&lt;br /&gt;
    `-- libzoid_cn.a&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
--&amp;gt;&lt;br /&gt;
==Building MPICH, DCMF, and SPI libraries==&lt;br /&gt;
&lt;br /&gt;
We provide all the necessary source code to build MPICH, DCMF, and SPI.  To build these libraries, just type:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
$ make -C comm rebuild-target&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
It may take half an hour to an hour to complete the build process, depending on what file system is being used (i.e., GPFS is a lot slower than a local file system).&lt;br /&gt;
&lt;br /&gt;
The &amp;lt;tt&amp;gt;rebuild-target&amp;lt;/tt&amp;gt; target does not know anything about the existing installation directory; it only copies the built libraries and header files to the &amp;lt;tt&amp;gt;comm/tmp&amp;lt;/tt&amp;gt; directory. To install the newly built libraries, do the following:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
$ make -C comm update-prebuilt&lt;br /&gt;
$ python install.py &amp;lt;zepto_dir&amp;gt;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The &amp;lt;tt&amp;gt;update-prebuilt&amp;lt;/tt&amp;gt; target basically copies the files from the &amp;lt;tt&amp;gt;comm/tmp&amp;lt;/tt&amp;gt; directory to the &amp;lt;tt&amp;gt;comm/prebuilt&amp;lt;/tt&amp;gt; directory, which is where the &amp;lt;tt&amp;gt;install.py&amp;lt;/tt&amp;gt; script looks for to copy the files to &amp;lt;tt&amp;gt;&amp;lt;zepto_dir&amp;gt;&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
==Software stack layout==&lt;br /&gt;
&lt;br /&gt;
[[Image:Zepto-Comm-Stack.png|right]]&lt;br /&gt;
&lt;br /&gt;
The figure on the right depicts the layout of the communication software stack in the ZeptoOS compute node environment.  This is very similar to the IBM's CNK stack, with the exception of an extra ZEPTO SPI layer, and the use of Linux instead of CNK.&lt;br /&gt;
&lt;br /&gt;
Since MPICH is a well-known software package we will not discuss it here, but we will briefly describe the DCMF and SPI components:&lt;br /&gt;
&lt;br /&gt;
* DCMF&lt;br /&gt;
** stands for Deep Computing Messaging Framework,&lt;br /&gt;
** developed by IBM originally for Blue Gene architecture,&lt;br /&gt;
** hardware initialization, query functions,&lt;br /&gt;
** supports BGP Torus DMA, collective network,&lt;br /&gt;
** provides a timer,&lt;br /&gt;
** supports non-blocking collective operations,&lt;br /&gt;
** BGP MPICH uses DCMF internally (IBM provides a glue layer).&lt;br /&gt;
* SPI&lt;br /&gt;
** stands for System Programming Interface,&lt;br /&gt;
** developed by IBM; BGP-specific code,&lt;br /&gt;
** kernel interfaces &amp;amp;#8211; DMA control, lockbox, etc,&lt;br /&gt;
** DMA-related definitions&lt;br /&gt;
*** can be used in both user space and kernel space,&lt;br /&gt;
** RAS, BGP personality, mapping-related functions.&lt;br /&gt;
&lt;br /&gt;
BGP SPI was designed specifically for IBM CNK, so it is not compatible with Linux.  ZEPTO SPI is a thin software layer that absorbs the differences between the CNK and Linux or drops the requests that Linux cannot handle.&lt;br /&gt;
&lt;br /&gt;
==Source code==&lt;br /&gt;
&lt;br /&gt;
The source code and header files of DCMF and SPI can be found in the &amp;lt;tt&amp;gt;comm&amp;lt;/tt&amp;gt; directory. The source code of MPICH is in &amp;lt;tt&amp;gt;DCMF/lib/mpich2/mpich2-1.0.7.tar.gz&amp;lt;/tt&amp;gt;, which is unpacked at build time.&lt;br /&gt;
&lt;br /&gt;
The DCMF source code is located in &amp;lt;tt&amp;gt;DCMF/sys/&amp;lt;/tt&amp;gt;, with the core code in &amp;lt;tt&amp;gt;DCMF/sys/messaging/&amp;lt;/tt&amp;gt;. Component Collective Messaging Interface (CCMI) is part of DCMF and its source code is in &amp;lt;tt&amp;gt;DCMF/sys/collectives/&amp;lt;/tt&amp;gt;. Test codes can be found in &amp;lt;tt&amp;gt;DCMF/sys/collectives/tests/&amp;lt;/tt&amp;gt; for CCMI and &amp;lt;tt&amp;gt;DCMF/sys/messaging/tests/&amp;lt;/tt&amp;gt; for the core. Those test codes can be a good example of DCMF/CCMI programming.&lt;br /&gt;
&lt;br /&gt;
SPI headers are in &amp;lt;tt&amp;gt;arch-runtime/arch/&amp;lt;/tt&amp;gt; and SPI source code is in &amp;lt;tt&amp;gt;comm/arch-runtime/runtime/&amp;lt;/tt&amp;gt;.  The source code of the ZEPTO SPI layer is in &amp;lt;tt&amp;gt;arch-runtime/zcl_spi/&amp;lt;/tt&amp;gt;, while the header files are in &amp;lt;tt&amp;gt;arch-runtime/arch/include/zepto/&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Here is an overview of the directory tree:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
comm&lt;br /&gt;
|-- DCMF&lt;br /&gt;
|   |-- lib&lt;br /&gt;
|   |   |-- dev&lt;br /&gt;
|   |   `-- mpich2&lt;br /&gt;
|   |       `-- make&lt;br /&gt;
|   |-- sys&lt;br /&gt;
|   |   |-- collectives&lt;br /&gt;
|   |   |   |-- adaptor&lt;br /&gt;
|   |   |   |-- kernel&lt;br /&gt;
|   |   |   |-- tests&lt;br /&gt;
|   |   |   `-- tools&lt;br /&gt;
|   |   |-- include&lt;br /&gt;
|   |   `-- messaging&lt;br /&gt;
|   |       |-- devices&lt;br /&gt;
|   |       |-- messager&lt;br /&gt;
|   |       |-- protocols&lt;br /&gt;
|   |       |-- queueing&lt;br /&gt;
|   |       |-- sysdep&lt;br /&gt;
|   |       `-- tests&lt;br /&gt;
|-- arch-runtime&lt;br /&gt;
|   |-- arch&lt;br /&gt;
|   |   `-- include&lt;br /&gt;
|   |       |-- bpcore&lt;br /&gt;
|   |       |-- cnk&lt;br /&gt;
|   |       |-- common&lt;br /&gt;
|   |       |-- spi&lt;br /&gt;
|   |       `-- zepto&lt;br /&gt;
|   |-- runtime&lt;br /&gt;
|   |-- testcodes&lt;br /&gt;
|   `-- zcl_spi&lt;br /&gt;
`-- testcodes&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Debug output===&lt;br /&gt;
&lt;br /&gt;
ZeptoOS versions of SPI and DCMF have a built-in debug output.  The output is disabled by default, and can be enabled by setting the environment variable &amp;lt;tt&amp;gt;ZEPTO_TRACE&amp;lt;/tt&amp;gt; when submitting a job.  The integer value of the variable indicates the debug level (a higher number results in more debug output).&lt;br /&gt;
&lt;br /&gt;
An example:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
$ cqsub -k &amp;lt;zepto_profile&amp;gt; -n 64 -t 10 ... -e ZEPTO_TRACE=2 ./a.out&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
[[Testing]] | [[ZeptoOS_Documentation|Top]] | [[Kernel]]&lt;/div&gt;</summary>
		<author><name>Iskra</name></author>
	</entry>
	<entry>
		<id> /zeptoos/index.php?title=Kernel&amp;diff=601</id>
		<title>Kernel</title>
		<link rel="alternate" type="text/html" href=" /zeptoos/index.php?title=Kernel&amp;diff=601"/>
		<updated>2009-05-08T19:58:07Z</updated>

		<summary type="html">&lt;p&gt;Iskra: /* Log files, etc */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;[[MPICH, DCMF, and SPI]] | [[ZeptoOS_Documentation|Top]] | [[Ramdisk]]&lt;br /&gt;
----&lt;br /&gt;
&lt;br /&gt;
==Introduction==&lt;br /&gt;
&lt;br /&gt;
We currently provide two Linux kernels:&lt;br /&gt;
&lt;br /&gt;
* 2.6.19-based kernel: ZeptoOS CN kernel&lt;br /&gt;
** IBM V1R3 patch and ZeptoOS patch applied&lt;br /&gt;
** 64&amp;amp;nbsp;KB page size and big memory region available&lt;br /&gt;
** Device drivers for compute node devices such as DMA, lockbox, etc&lt;br /&gt;
** Allows to run MPICH/DCMF code through Zepto Compute Binary (ZCB)&lt;br /&gt;
** Can be used as enhanced ION kernel&lt;br /&gt;
&lt;br /&gt;
* 2.6.16-based kernel: ZeptoOS ION kernel&lt;br /&gt;
** IBM V1R3 patch applied&lt;br /&gt;
** Only minor changes compared to the IBM ION kernel.&lt;br /&gt;
&lt;br /&gt;
We focus our development efforts on the 2.6.19-based kernel.  It is meant primarily for the compute nodes, but can also be used on the I/O nodes.  The problem is that GPFS does not work with this kernel, so we also provide the 2.6.16-based kernel which GPFS does work with.&lt;br /&gt;
&lt;br /&gt;
==Kernel directory structure==&lt;br /&gt;
&lt;br /&gt;
The &amp;lt;tt&amp;gt;kernel&amp;lt;/tt&amp;gt; directory consists of three main subdirectories: &amp;lt;tt&amp;gt;prebuilt&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;config&amp;lt;/tt&amp;gt;, and &amp;lt;tt&amp;gt;tarball&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
kernel&lt;br /&gt;
|-- prebuilt&lt;br /&gt;
|   |-- 2.6.16&lt;br /&gt;
|   |   `-- ION&lt;br /&gt;
|   `-- 2.6.19&lt;br /&gt;
|       |-- CN&lt;br /&gt;
|       `-- objs&lt;br /&gt;
|-- tarball&lt;br /&gt;
`-- config&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The &amp;lt;tt&amp;gt;prebuilt&amp;lt;/tt&amp;gt; directory contains prebuilt kernel images and modules. While a complete prebuilt ION kernel ELF file is provided, for the CN kernel we provide intermediate object files instead.  This is because we embed the CN ramdisk in the CN kernel image when building ZeptoOS, and this process requires the object files.&lt;br /&gt;
&lt;br /&gt;
The &amp;lt;tt&amp;gt;tarball&amp;lt;/tt&amp;gt; directory contains kernel tarballs separately for the ION and the CN Linux kernel. Technically, those tarballs are snapshots of the ZeptoOS kernel git repository. The directory might contain a &amp;lt;tt&amp;gt;.patch&amp;lt;/tt&amp;gt; file that contains the differences between the last snapshot and the current git HEAD since we wanted to avoid creating a snapshot from git for small modifications. Associated git log files can also be found in this directory. A &amp;lt;tt&amp;gt;.SNAPSHOT_HEAD&amp;lt;/tt&amp;gt; file indicates the git revision at the time when a snapshot was created, so this information is used to create a patch file.&lt;br /&gt;
&lt;br /&gt;
As an example, here is a list of files for the CN kernel:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
linux-2.6.19.2-BGP-V1R3.git.log&lt;br /&gt;
linux-2.6.19.2-BGP-V1R3.patch&lt;br /&gt;
linux-2.6.19.2-BGP-V1R3.SNAPSHOT_HEAD&lt;br /&gt;
linux-2.6.19.2-BGP-V1R3.tar.bz2&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The &amp;lt;tt&amp;gt;config&amp;lt;/tt&amp;gt; directory contains Linux kernel configs.  In case of the 2.6.19 kernel, we provide separate config files for the compute node and the I/O node.&lt;br /&gt;
&lt;br /&gt;
==Building a kernel==&lt;br /&gt;
&lt;br /&gt;
The &amp;lt;tt&amp;gt;Makefile&amp;lt;/tt&amp;gt; in the &amp;lt;tt&amp;gt;kernel&amp;lt;/tt&amp;gt; directory has many targets. Just type &amp;lt;tt&amp;gt;make&amp;lt;/tt&amp;gt; and it will print out a help message. &lt;br /&gt;
&lt;br /&gt;
If one needs to build (or rebuild) a kernel from a source tarball, use &amp;lt;tt&amp;gt;bgp-ion-linux-build&amp;lt;/tt&amp;gt; or &amp;lt;tt&amp;gt;bgp-cn-linux-build&amp;lt;/tt&amp;gt; targets. By default, it extracts ION or CN kernel tarball in a directory named &amp;lt;tt&amp;gt;work&amp;lt;/tt&amp;gt;, applies a patch if any and starts the kernel build. Once the kernel has successfully been built, kernel images (in both ZeptoOS top-level directory and the &amp;lt;tt&amp;gt;tmp&amp;lt;/tt&amp;gt; directory) will be replaced with newly built ones. The ION kernel source code is extracted into &amp;lt;tt&amp;gt;work/linux-2.6.16.46-297-BGP-V1R3&amp;lt;/tt&amp;gt; and the CN kernel source into &amp;lt;tt&amp;gt;work/linux-2.6.19.2-BGP-V1R3&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Here is an example of building and rebuilding the CN kernel:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
$ cd kernel&lt;br /&gt;
$ make bgp-cn-linux-build&lt;br /&gt;
....&lt;br /&gt;
$ ls -al ../BGP-CN-zImage-with-initrd.elf&lt;br /&gt;
$ vi work/linux-2.6.19.2-BGP-V1R3/kernel/sched.c&lt;br /&gt;
$ make bgp-cn-linux-build&lt;br /&gt;
....&lt;br /&gt;
$ ls -al ../BGP-CN-zImage-with-initrd.elf&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Building a kernel from the ZeptoOS kernel git repository===&lt;br /&gt;
&lt;br /&gt;
As mentioned earlier, kernel tarballs are used as the source by default.  If instead one passes &amp;lt;tt&amp;gt;GIT=1&amp;lt;/tt&amp;gt; to &amp;lt;tt&amp;gt;make&amp;lt;/tt&amp;gt;, one can build directly from the ZeptoOS kernel git tree. This is very useful for kernel development since it makes it easier to keep track of local modifications. &lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
$ cd kernel&lt;br /&gt;
$ make GIT=1 bgp-cn-linux-build&lt;br /&gt;
....&lt;br /&gt;
$ vi repo/linux-2.6.19.2-BGP-V1R3/kernel/sched.c&lt;br /&gt;
$ make GIT=1 bgp-cn-linux-build&lt;br /&gt;
....&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This will create &amp;lt;tt&amp;gt;repo/linux-2.6.19.2-BGP-V1R3&amp;lt;/tt&amp;gt;, which is a git repository that is cloned from http://git.anl-external.org/bg-linux.repos/linux-2.6.19-BGP-V1R3.git/. Our http repo is read-only, so you cannot push your modifications to it. Instead, please post any patches to the [mailto:zeptoos@lists.mcs.anl.gov ZeptoOS developers mailing list]. &lt;br /&gt;
&lt;br /&gt;
See also the [http://bg-linux.anl-external.org/wiki/index.php/Main_Page BG-Linux page] for the details on our kernel git repository.&lt;br /&gt;
&lt;br /&gt;
===Kernel config===&lt;br /&gt;
&lt;br /&gt;
When one invokes &amp;lt;tt&amp;gt;make&amp;lt;/tt&amp;gt; with a kernel build target for the first time, the associated kernel config file is copied to &amp;lt;tt&amp;gt;.config&amp;lt;/tt&amp;gt; in the kernel build directory.  &amp;lt;tt&amp;gt;config/bgp-cn-2.6.19.2-dot-config&amp;lt;/tt&amp;gt; is applied to the CN Linux kernel build tree, and &amp;lt;tt&amp;gt;config/bgp-ion-2.6.16.46-dot-config&amp;lt;/tt&amp;gt; is applied to the ION Linux kernel build tree.&lt;br /&gt;
&lt;br /&gt;
Here are the locations of the kernel config files:&lt;br /&gt;
* Regular build&lt;br /&gt;
** work/build-2.6.19.2-BGP-V1R3/.config&lt;br /&gt;
** work/build-2.6.16.46-297-BGP-V1R3/.config&lt;br /&gt;
* GIT build&lt;br /&gt;
** repo/build-2.6.19.2-BGP-V1R3/.config&lt;br /&gt;
** repo/build-2.6.16.46-297-BGP-V1R3/.config&lt;br /&gt;
&lt;br /&gt;
Please note that the kernel config file is copied only once, until one does a &amp;lt;tt&amp;gt;distclean&amp;lt;/tt&amp;gt; or removes the files manually.&lt;br /&gt;
&lt;br /&gt;
The &amp;lt;tt&amp;gt;bgp-cn-linux-menuconfig&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;bgp-ion-linux-menuconfig&amp;lt;/tt&amp;gt; &amp;lt;tt&amp;gt;make&amp;lt;/tt&amp;gt; targets invoke text-based Linux kernel configuration menus:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
$ make bgp-ion-linux-menuconfig&lt;br /&gt;
$ make bgp-cn-linux-menuconfig&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
For GIT build:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
$ make GIT=1 bgp-ion-linux-menuconfig&lt;br /&gt;
$ make GIT=1 bgp-cn-linux-menuconfig&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
These menu targets never update the default kernel config files from the &amp;lt;tt&amp;gt;config&amp;lt;/tt&amp;gt; directory.  If one wants to apply a new config permanently, please copy it to the &amp;lt;tt&amp;gt;config&amp;lt;/tt&amp;gt; directory by hand:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
$ cp work/build-2.6.19.2-BGP-V1R3/.config config/bgp-cn-2.6.19.2-dot-config&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Kernel (command line) parameters==&lt;br /&gt;
&lt;br /&gt;
In common server/desktop Linux environments, kernel parameters can be passed via a bootloader such as grub. However, Blue Gene/P boot mechanism does not provide such capability, so we have modified the CN Linux kernel (2.6.19) to use a kernel parameter string embedded in kernel ELF image file itself.&lt;br /&gt;
&lt;br /&gt;
One can (re)set the kernel parameters in a kernel ELF file using a command line tool &amp;lt;tt&amp;gt;zkparam.py&amp;lt;/tt&amp;gt;, located in the &amp;lt;tt&amp;gt;bin&amp;lt;/tt&amp;gt; subdirectory of the ZeptoOS installation directory.  Here is the synopsis of the tool:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
zkparam.py &amp;lt;kernel_image&amp;gt; [options]&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
If options are omitted, the tool shows the current kernel parameters:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
$ ./kernel/zkparam.py BGP-CN-zImage-with-initrd.elf zepto_console_output=2&lt;br /&gt;
$ ./kernel/zkparam.py BGP-CN-zImage-with-initrd.elf&lt;br /&gt;
Current Kernel Parameters:&lt;br /&gt;
 zepto_console_output=2&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===ZeptoOS-pecific kernel parameters===&lt;br /&gt;
&lt;br /&gt;
* '''zepto_debug'''=&amp;lt;integer&amp;gt;&lt;br /&gt;
** Specifies the ZeptoOS kernel debug level.&lt;br /&gt;
** The higher the number, the more messages are generated.&lt;br /&gt;
** &amp;lt;tt&amp;gt;0&amp;lt;/tt&amp;gt; turns off all debug messages.&lt;br /&gt;
** default=1&lt;br /&gt;
* '''flatmemsizeMB'''=&amp;lt;integer&amp;gt;&lt;br /&gt;
** Specifies the size of big memory in MB.&lt;br /&gt;
** Currently the granularity of memory size is 256&amp;amp;nbsp;MB.&lt;br /&gt;
** default=256  min=256  max=1792&lt;br /&gt;
* '''zepto_console_output'''=&amp;lt;integer&amp;gt;&lt;br /&gt;
** Specifies the console output behavior. &lt;br /&gt;
** 0 disables console output from all compute nodes.&lt;br /&gt;
** 1 enables console output from the first compute node ([[FAQ#Torus rank|torus rank]] 0).&lt;br /&gt;
** 2 enables console output from all compute nodes.&lt;br /&gt;
&lt;br /&gt;
==Log files, etc==&lt;br /&gt;
&amp;lt;!--&lt;br /&gt;
===Compute Node log===&lt;br /&gt;
&lt;br /&gt;
Debug messages from compute node (i.e, via printk) will appear in one of system log files.&lt;br /&gt;
The system log file is recreated every time at system reset. You can find the location of the system log file&lt;br /&gt;
by typing the following command. &lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
$ ls -1 /bgsys/logs/BGP/sn*-mmcs_db_server*.log|tail -1&lt;br /&gt;
/bgsys/logs/BGP/sn1-mmcs_db_server-2009-0209-11:58:20.log&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Please also take a look at a convenient script BGP/packages/tools/cn-log.sh&lt;br /&gt;
&lt;br /&gt;
===ION Node log===&lt;br /&gt;
&lt;br /&gt;
Debug message from ION node will appear in ION node log files in /bgsys/logs/BGP/,&lt;br /&gt;
/bgsys/logs/BGP/R00-M0-N00-J00.log for example.&lt;br /&gt;
Each ION has own log file. ION to CN ratio is 1:64 in ANL system. If your job is a 64 (physical) nodes job,&lt;br /&gt;
you have one ION log file. &lt;br /&gt;
&lt;br /&gt;
Please also take a look at a convenient script BGP/packages/tools/ion-log.sh&lt;br /&gt;
&lt;br /&gt;
===RAS events===&lt;br /&gt;
--&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The compute node and I/O node logfiles have been discussed extensively in [[Testing#Log files|Testing]].&lt;br /&gt;
&lt;br /&gt;
In addition to regular console logs, the kernels can also generate RAS messages, which will not appear in the log files; they are instead stored in a database on the service node. At Argonne we have a custom command line tool named &amp;lt;tt&amp;gt;bg-listevents&amp;lt;/tt&amp;gt; that shows a record of RAS events (type &amp;lt;tt&amp;gt;bg-listevents -h&amp;lt;/tt&amp;gt; for command line arguments).&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
[[MPICH, DCMF, and SPI]] | [[ZeptoOS_Documentation|Top]] | [[Ramdisk]]&lt;/div&gt;</summary>
		<author><name>Iskra</name></author>
	</entry>
	<entry>
		<id> /zeptoos/index.php?title=Kernel&amp;diff=600</id>
		<title>Kernel</title>
		<link rel="alternate" type="text/html" href=" /zeptoos/index.php?title=Kernel&amp;diff=600"/>
		<updated>2009-05-08T19:57:52Z</updated>

		<summary type="html">&lt;p&gt;Iskra: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;[[MPICH, DCMF, and SPI]] | [[ZeptoOS_Documentation|Top]] | [[Ramdisk]]&lt;br /&gt;
----&lt;br /&gt;
&lt;br /&gt;
==Introduction==&lt;br /&gt;
&lt;br /&gt;
We currently provide two Linux kernels:&lt;br /&gt;
&lt;br /&gt;
* 2.6.19-based kernel: ZeptoOS CN kernel&lt;br /&gt;
** IBM V1R3 patch and ZeptoOS patch applied&lt;br /&gt;
** 64&amp;amp;nbsp;KB page size and big memory region available&lt;br /&gt;
** Device drivers for compute node devices such as DMA, lockbox, etc&lt;br /&gt;
** Allows to run MPICH/DCMF code through Zepto Compute Binary (ZCB)&lt;br /&gt;
** Can be used as enhanced ION kernel&lt;br /&gt;
&lt;br /&gt;
* 2.6.16-based kernel: ZeptoOS ION kernel&lt;br /&gt;
** IBM V1R3 patch applied&lt;br /&gt;
** Only minor changes compared to the IBM ION kernel.&lt;br /&gt;
&lt;br /&gt;
We focus our development efforts on the 2.6.19-based kernel.  It is meant primarily for the compute nodes, but can also be used on the I/O nodes.  The problem is that GPFS does not work with this kernel, so we also provide the 2.6.16-based kernel which GPFS does work with.&lt;br /&gt;
&lt;br /&gt;
==Kernel directory structure==&lt;br /&gt;
&lt;br /&gt;
The &amp;lt;tt&amp;gt;kernel&amp;lt;/tt&amp;gt; directory consists of three main subdirectories: &amp;lt;tt&amp;gt;prebuilt&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;config&amp;lt;/tt&amp;gt;, and &amp;lt;tt&amp;gt;tarball&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
kernel&lt;br /&gt;
|-- prebuilt&lt;br /&gt;
|   |-- 2.6.16&lt;br /&gt;
|   |   `-- ION&lt;br /&gt;
|   `-- 2.6.19&lt;br /&gt;
|       |-- CN&lt;br /&gt;
|       `-- objs&lt;br /&gt;
|-- tarball&lt;br /&gt;
`-- config&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The &amp;lt;tt&amp;gt;prebuilt&amp;lt;/tt&amp;gt; directory contains prebuilt kernel images and modules. While a complete prebuilt ION kernel ELF file is provided, for the CN kernel we provide intermediate object files instead.  This is because we embed the CN ramdisk in the CN kernel image when building ZeptoOS, and this process requires the object files.&lt;br /&gt;
&lt;br /&gt;
The &amp;lt;tt&amp;gt;tarball&amp;lt;/tt&amp;gt; directory contains kernel tarballs separately for the ION and the CN Linux kernel. Technically, those tarballs are snapshots of the ZeptoOS kernel git repository. The directory might contain a &amp;lt;tt&amp;gt;.patch&amp;lt;/tt&amp;gt; file that contains the differences between the last snapshot and the current git HEAD since we wanted to avoid creating a snapshot from git for small modifications. Associated git log files can also be found in this directory. A &amp;lt;tt&amp;gt;.SNAPSHOT_HEAD&amp;lt;/tt&amp;gt; file indicates the git revision at the time when a snapshot was created, so this information is used to create a patch file.&lt;br /&gt;
&lt;br /&gt;
As an example, here is a list of files for the CN kernel:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
linux-2.6.19.2-BGP-V1R3.git.log&lt;br /&gt;
linux-2.6.19.2-BGP-V1R3.patch&lt;br /&gt;
linux-2.6.19.2-BGP-V1R3.SNAPSHOT_HEAD&lt;br /&gt;
linux-2.6.19.2-BGP-V1R3.tar.bz2&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The &amp;lt;tt&amp;gt;config&amp;lt;/tt&amp;gt; directory contains Linux kernel configs.  In case of the 2.6.19 kernel, we provide separate config files for the compute node and the I/O node.&lt;br /&gt;
&lt;br /&gt;
==Building a kernel==&lt;br /&gt;
&lt;br /&gt;
The &amp;lt;tt&amp;gt;Makefile&amp;lt;/tt&amp;gt; in the &amp;lt;tt&amp;gt;kernel&amp;lt;/tt&amp;gt; directory has many targets. Just type &amp;lt;tt&amp;gt;make&amp;lt;/tt&amp;gt; and it will print out a help message. &lt;br /&gt;
&lt;br /&gt;
If one needs to build (or rebuild) a kernel from a source tarball, use &amp;lt;tt&amp;gt;bgp-ion-linux-build&amp;lt;/tt&amp;gt; or &amp;lt;tt&amp;gt;bgp-cn-linux-build&amp;lt;/tt&amp;gt; targets. By default, it extracts ION or CN kernel tarball in a directory named &amp;lt;tt&amp;gt;work&amp;lt;/tt&amp;gt;, applies a patch if any and starts the kernel build. Once the kernel has successfully been built, kernel images (in both ZeptoOS top-level directory and the &amp;lt;tt&amp;gt;tmp&amp;lt;/tt&amp;gt; directory) will be replaced with newly built ones. The ION kernel source code is extracted into &amp;lt;tt&amp;gt;work/linux-2.6.16.46-297-BGP-V1R3&amp;lt;/tt&amp;gt; and the CN kernel source into &amp;lt;tt&amp;gt;work/linux-2.6.19.2-BGP-V1R3&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Here is an example of building and rebuilding the CN kernel:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
$ cd kernel&lt;br /&gt;
$ make bgp-cn-linux-build&lt;br /&gt;
....&lt;br /&gt;
$ ls -al ../BGP-CN-zImage-with-initrd.elf&lt;br /&gt;
$ vi work/linux-2.6.19.2-BGP-V1R3/kernel/sched.c&lt;br /&gt;
$ make bgp-cn-linux-build&lt;br /&gt;
....&lt;br /&gt;
$ ls -al ../BGP-CN-zImage-with-initrd.elf&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Building a kernel from the ZeptoOS kernel git repository===&lt;br /&gt;
&lt;br /&gt;
As mentioned earlier, kernel tarballs are used as the source by default.  If instead one passes &amp;lt;tt&amp;gt;GIT=1&amp;lt;/tt&amp;gt; to &amp;lt;tt&amp;gt;make&amp;lt;/tt&amp;gt;, one can build directly from the ZeptoOS kernel git tree. This is very useful for kernel development since it makes it easier to keep track of local modifications. &lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
$ cd kernel&lt;br /&gt;
$ make GIT=1 bgp-cn-linux-build&lt;br /&gt;
....&lt;br /&gt;
$ vi repo/linux-2.6.19.2-BGP-V1R3/kernel/sched.c&lt;br /&gt;
$ make GIT=1 bgp-cn-linux-build&lt;br /&gt;
....&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This will create &amp;lt;tt&amp;gt;repo/linux-2.6.19.2-BGP-V1R3&amp;lt;/tt&amp;gt;, which is a git repository that is cloned from http://git.anl-external.org/bg-linux.repos/linux-2.6.19-BGP-V1R3.git/. Our http repo is read-only, so you cannot push your modifications to it. Instead, please post any patches to the [mailto:zeptoos@lists.mcs.anl.gov ZeptoOS developers mailing list]. &lt;br /&gt;
&lt;br /&gt;
See also the [http://bg-linux.anl-external.org/wiki/index.php/Main_Page BG-Linux page] for the details on our kernel git repository.&lt;br /&gt;
&lt;br /&gt;
===Kernel config===&lt;br /&gt;
&lt;br /&gt;
When one invokes &amp;lt;tt&amp;gt;make&amp;lt;/tt&amp;gt; with a kernel build target for the first time, the associated kernel config file is copied to &amp;lt;tt&amp;gt;.config&amp;lt;/tt&amp;gt; in the kernel build directory.  &amp;lt;tt&amp;gt;config/bgp-cn-2.6.19.2-dot-config&amp;lt;/tt&amp;gt; is applied to the CN Linux kernel build tree, and &amp;lt;tt&amp;gt;config/bgp-ion-2.6.16.46-dot-config&amp;lt;/tt&amp;gt; is applied to the ION Linux kernel build tree.&lt;br /&gt;
&lt;br /&gt;
Here are the locations of the kernel config files:&lt;br /&gt;
* Regular build&lt;br /&gt;
** work/build-2.6.19.2-BGP-V1R3/.config&lt;br /&gt;
** work/build-2.6.16.46-297-BGP-V1R3/.config&lt;br /&gt;
* GIT build&lt;br /&gt;
** repo/build-2.6.19.2-BGP-V1R3/.config&lt;br /&gt;
** repo/build-2.6.16.46-297-BGP-V1R3/.config&lt;br /&gt;
&lt;br /&gt;
Please note that the kernel config file is copied only once, until one does a &amp;lt;tt&amp;gt;distclean&amp;lt;/tt&amp;gt; or removes the files manually.&lt;br /&gt;
&lt;br /&gt;
The &amp;lt;tt&amp;gt;bgp-cn-linux-menuconfig&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;bgp-ion-linux-menuconfig&amp;lt;/tt&amp;gt; &amp;lt;tt&amp;gt;make&amp;lt;/tt&amp;gt; targets invoke text-based Linux kernel configuration menus:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
$ make bgp-ion-linux-menuconfig&lt;br /&gt;
$ make bgp-cn-linux-menuconfig&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
For GIT build:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
$ make GIT=1 bgp-ion-linux-menuconfig&lt;br /&gt;
$ make GIT=1 bgp-cn-linux-menuconfig&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
These menu targets never update the default kernel config files from the &amp;lt;tt&amp;gt;config&amp;lt;/tt&amp;gt; directory.  If one wants to apply a new config permanently, please copy it to the &amp;lt;tt&amp;gt;config&amp;lt;/tt&amp;gt; directory by hand:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
$ cp work/build-2.6.19.2-BGP-V1R3/.config config/bgp-cn-2.6.19.2-dot-config&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Kernel (command line) parameters==&lt;br /&gt;
&lt;br /&gt;
In common server/desktop Linux environments, kernel parameters can be passed via a bootloader such as grub. However, Blue Gene/P boot mechanism does not provide such capability, so we have modified the CN Linux kernel (2.6.19) to use a kernel parameter string embedded in kernel ELF image file itself.&lt;br /&gt;
&lt;br /&gt;
One can (re)set the kernel parameters in a kernel ELF file using a command line tool &amp;lt;tt&amp;gt;zkparam.py&amp;lt;/tt&amp;gt;, located in the &amp;lt;tt&amp;gt;bin&amp;lt;/tt&amp;gt; subdirectory of the ZeptoOS installation directory.  Here is the synopsis of the tool:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
zkparam.py &amp;lt;kernel_image&amp;gt; [options]&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
If options are omitted, the tool shows the current kernel parameters:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
$ ./kernel/zkparam.py BGP-CN-zImage-with-initrd.elf zepto_console_output=2&lt;br /&gt;
$ ./kernel/zkparam.py BGP-CN-zImage-with-initrd.elf&lt;br /&gt;
Current Kernel Parameters:&lt;br /&gt;
 zepto_console_output=2&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===ZeptoOS-pecific kernel parameters===&lt;br /&gt;
&lt;br /&gt;
* '''zepto_debug'''=&amp;lt;integer&amp;gt;&lt;br /&gt;
** Specifies the ZeptoOS kernel debug level.&lt;br /&gt;
** The higher the number, the more messages are generated.&lt;br /&gt;
** &amp;lt;tt&amp;gt;0&amp;lt;/tt&amp;gt; turns off all debug messages.&lt;br /&gt;
** default=1&lt;br /&gt;
* '''flatmemsizeMB'''=&amp;lt;integer&amp;gt;&lt;br /&gt;
** Specifies the size of big memory in MB.&lt;br /&gt;
** Currently the granularity of memory size is 256&amp;amp;nbsp;MB.&lt;br /&gt;
** default=256  min=256  max=1792&lt;br /&gt;
* '''zepto_console_output'''=&amp;lt;integer&amp;gt;&lt;br /&gt;
** Specifies the console output behavior. &lt;br /&gt;
** 0 disables console output from all compute nodes.&lt;br /&gt;
** 1 enables console output from the first compute node ([[FAQ#Torus rank|torus rank]] 0).&lt;br /&gt;
** 2 enables console output from all compute nodes.&lt;br /&gt;
&lt;br /&gt;
==Log files, etc==&lt;br /&gt;
&amp;lt;!--&lt;br /&gt;
===Compute Node log===&lt;br /&gt;
&lt;br /&gt;
Debug messages from compute node (i.e, via printk) will appear in one of system log files.&lt;br /&gt;
The system log file is recreated every time at system reset. You can find the location of the system log file&lt;br /&gt;
by typing the following command. &lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
$ ls -1 /bgsys/logs/BGP/sn*-mmcs_db_server*.log|tail -1&lt;br /&gt;
/bgsys/logs/BGP/sn1-mmcs_db_server-2009-0209-11:58:20.log&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Please also take a look at a convenient script BGP/packages/tools/cn-log.sh&lt;br /&gt;
&lt;br /&gt;
===ION Node log===&lt;br /&gt;
&lt;br /&gt;
Debug message from ION node will appear in ION node log files in /bgsys/logs/BGP/,&lt;br /&gt;
/bgsys/logs/BGP/R00-M0-N00-J00.log for example.&lt;br /&gt;
Each ION has own log file. ION to CN ratio is 1:64 in ANL system. If your job is a 64 (physical) nodes job,&lt;br /&gt;
you have one ION log file. &lt;br /&gt;
&lt;br /&gt;
Please also take a look at a convenient script BGP/packages/tools/ion-log.sh&lt;br /&gt;
&lt;br /&gt;
===RAS events===&lt;br /&gt;
--&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The compute node and I/O node logfiles have been discussed extensively in [[Testing#Log files|Testing]].&lt;br /&gt;
&lt;br /&gt;
In addition to regular console logs, the kernels can also generate RAS messages, which will not appear in the log files; they are instead stored in a database on the service node. At Argonne we have a command line tool named &amp;lt;tt&amp;gt;bg-listevents&amp;lt;/tt&amp;gt; that shows a record of RAS events (type &amp;lt;tt&amp;gt;bg-listevents -h&amp;lt;/tt&amp;gt; for command line arguments).&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
[[MPICH, DCMF, and SPI]] | [[ZeptoOS_Documentation|Top]] | [[Ramdisk]]&lt;/div&gt;</summary>
		<author><name>Iskra</name></author>
	</entry>
	<entry>
		<id> /zeptoos/index.php?title=Kernel&amp;diff=599</id>
		<title>Kernel</title>
		<link rel="alternate" type="text/html" href=" /zeptoos/index.php?title=Kernel&amp;diff=599"/>
		<updated>2009-05-08T19:44:31Z</updated>

		<summary type="html">&lt;p&gt;Iskra: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;[[MPICH, DCMF, and SPI]] | [[ZeptoOS_Documentation|Top]] | [[Ramdisk]]&lt;br /&gt;
----&lt;br /&gt;
&lt;br /&gt;
==Introduction==&lt;br /&gt;
&lt;br /&gt;
We currently provide two Linux kernels:&lt;br /&gt;
&lt;br /&gt;
* 2.6.19-based kernel: ZeptoOS CN kernel&lt;br /&gt;
** IBM V1R3 patch and ZeptoOS patch applied&lt;br /&gt;
** 64&amp;amp;nbsp;KB page size and big memory region available&lt;br /&gt;
** Device drivers for compute node devices such as DMA, lockbox, etc&lt;br /&gt;
** Allows to run MPICH/DCMF code through Zepto Compute Binary (ZCB)&lt;br /&gt;
** Can be used as enhanced ION kernel&lt;br /&gt;
&lt;br /&gt;
* 2.6.16-based kernel: ZeptoOS ION kernel&lt;br /&gt;
** IBM V1R3 patch applied&lt;br /&gt;
** Only minor changes compared to the IBM ION kernel.&lt;br /&gt;
&lt;br /&gt;
We focus our development efforts on the 2.6.19-based kernel.  It is meant primarily for the compute nodes, but can also be used on the I/O nodes.  The problem is that GPFS does not work with this kernel, so we also provide the 2.6.16-based kernel which GPFS does work with.&lt;br /&gt;
&lt;br /&gt;
==Kernel directory structure==&lt;br /&gt;
&lt;br /&gt;
The &amp;lt;tt&amp;gt;kernel&amp;lt;/tt&amp;gt; directory consists of three main subdirectories: &amp;lt;tt&amp;gt;prebuilt&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;config&amp;lt;/tt&amp;gt;, and &amp;lt;tt&amp;gt;tarball&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
kernel&lt;br /&gt;
|-- prebuilt&lt;br /&gt;
|   |-- 2.6.16&lt;br /&gt;
|   |   `-- ION&lt;br /&gt;
|   `-- 2.6.19&lt;br /&gt;
|       |-- CN&lt;br /&gt;
|       `-- objs&lt;br /&gt;
|-- tarball&lt;br /&gt;
`-- config&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The &amp;lt;tt&amp;gt;prebuilt&amp;lt;/tt&amp;gt; directory contains prebuilt kernel images and modules. While a complete prebuilt ION kernel ELF file is provided, for the CN kernel we provide intermediate object files instead.  This is because we embed the CN ramdisk in the CN kernel image when building ZeptoOS, and this process requires the object files.&lt;br /&gt;
&lt;br /&gt;
The &amp;lt;tt&amp;gt;tarball&amp;lt;/tt&amp;gt; directory contains kernel tarballs separately for the ION and the CN Linux kernel. Technically, those tarballs are snapshots of the ZeptoOS kernel git repository. The directory might contain a &amp;lt;tt&amp;gt;.patch&amp;lt;/tt&amp;gt; file that contains the differences between the last snapshot and the current git HEAD since we wanted to avoid creating a snapshot from git for small modifications. Associated git log files can also be found in this directory. A &amp;lt;tt&amp;gt;.SNAPSHOT_HEAD&amp;lt;/tt&amp;gt; file indicates the git revision at the time when a snapshot was created, so this information is used to create a patch file.&lt;br /&gt;
&lt;br /&gt;
As an example, here is a list of files for the CN kernel:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
linux-2.6.19.2-BGP-V1R3.git.log&lt;br /&gt;
linux-2.6.19.2-BGP-V1R3.patch&lt;br /&gt;
linux-2.6.19.2-BGP-V1R3.SNAPSHOT_HEAD&lt;br /&gt;
linux-2.6.19.2-BGP-V1R3.tar.bz2&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The &amp;lt;tt&amp;gt;config&amp;lt;/tt&amp;gt; directory contains Linux kernel configs.  In case of the 2.6.19 kernel, we provide separate config files for the compute node and the I/O node.&lt;br /&gt;
&lt;br /&gt;
==Building a kernel==&lt;br /&gt;
&lt;br /&gt;
The &amp;lt;tt&amp;gt;Makefile&amp;lt;/tt&amp;gt; in the &amp;lt;tt&amp;gt;kernel&amp;lt;/tt&amp;gt; directory has many targets. Just type &amp;lt;tt&amp;gt;make&amp;lt;/tt&amp;gt; and it will print out a help message. &lt;br /&gt;
&lt;br /&gt;
If one needs to build (or rebuild) a kernel from a source tarball, use &amp;lt;tt&amp;gt;bgp-ion-linux-build&amp;lt;/tt&amp;gt; or &amp;lt;tt&amp;gt;bgp-cn-linux-build&amp;lt;/tt&amp;gt; targets. By default, it extracts ION or CN kernel tarball in a directory named &amp;lt;tt&amp;gt;work&amp;lt;/tt&amp;gt;, applies a patch if any and starts the kernel build. Once the kernel has successfully been built, kernel images (in both ZeptoOS top-level directory and the &amp;lt;tt&amp;gt;tmp&amp;lt;/tt&amp;gt; directory) will be replaced with newly built ones. The ION kernel source code is extracted into &amp;lt;tt&amp;gt;work/linux-2.6.16.46-297-BGP-V1R3&amp;lt;/tt&amp;gt; and the CN kernel source into &amp;lt;tt&amp;gt;work/linux-2.6.19.2-BGP-V1R3&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Here is an example of building and rebuilding the CN kernel:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
$ cd kernel&lt;br /&gt;
$ make bgp-cn-linux-build&lt;br /&gt;
....&lt;br /&gt;
$ ls -al ../BGP-CN-zImage-with-initrd.elf&lt;br /&gt;
$ vi work/linux-2.6.19.2-BGP-V1R3/kernel/sched.c&lt;br /&gt;
$ make bgp-cn-linux-build&lt;br /&gt;
....&lt;br /&gt;
$ ls -al ../BGP-CN-zImage-with-initrd.elf&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Building a kernel from the ZeptoOS kernel git repository===&lt;br /&gt;
&lt;br /&gt;
As mentioned earlier, kernel tarballs are used as the source by default.  If instead one passes &amp;lt;tt&amp;gt;GIT=1&amp;lt;/tt&amp;gt; to &amp;lt;tt&amp;gt;make&amp;lt;/tt&amp;gt;, one can build directly from the ZeptoOS kernel git tree. This is very useful for kernel development since it makes it easier to keep track of local modifications. &lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
$ cd kernel&lt;br /&gt;
$ make GIT=1 bgp-cn-linux-build&lt;br /&gt;
....&lt;br /&gt;
$ vi repo/linux-2.6.19.2-BGP-V1R3/kernel/sched.c&lt;br /&gt;
$ make GIT=1 bgp-cn-linux-build&lt;br /&gt;
....&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This will create &amp;lt;tt&amp;gt;repo/linux-2.6.19.2-BGP-V1R3&amp;lt;/tt&amp;gt;, which is a git repository that is cloned from http://git.anl-external.org/bg-linux.repos/linux-2.6.19-BGP-V1R3.git/. Our http repo is read-only, so you cannot push your modifications to it. Instead, please post any patches to the [mailto:zeptoos@lists.mcs.anl.gov ZeptoOS developers mailing list]. &lt;br /&gt;
&lt;br /&gt;
See also the [http://bg-linux.anl-external.org/wiki/index.php/Main_Page BG-Linux page] for the details on our kernel git repository.&lt;br /&gt;
&lt;br /&gt;
===Kernel config===&lt;br /&gt;
&lt;br /&gt;
When one invokes &amp;lt;tt&amp;gt;make&amp;lt;/tt&amp;gt; with a kernel build target for the first time, the associated kernel config file is copied to &amp;lt;tt&amp;gt;.config&amp;lt;/tt&amp;gt; in the kernel build directory.  &amp;lt;tt&amp;gt;config/bgp-cn-2.6.19.2-dot-config&amp;lt;/tt&amp;gt; is applied to the CN Linux kernel build tree, and &amp;lt;tt&amp;gt;config/bgp-ion-2.6.16.46-dot-config&amp;lt;/tt&amp;gt; is applied to the ION Linux kernel build tree.&lt;br /&gt;
&lt;br /&gt;
Here are the locations of the kernel config files:&lt;br /&gt;
* Regular build&lt;br /&gt;
** work/build-2.6.19.2-BGP-V1R3/.config&lt;br /&gt;
** work/build-2.6.16.46-297-BGP-V1R3/.config&lt;br /&gt;
* GIT build&lt;br /&gt;
** repo/build-2.6.19.2-BGP-V1R3/.config&lt;br /&gt;
** repo/build-2.6.16.46-297-BGP-V1R3/.config&lt;br /&gt;
&lt;br /&gt;
Please note that the kernel config file is copied only once, until one does a &amp;lt;tt&amp;gt;distclean&amp;lt;/tt&amp;gt; or removes the files manually.&lt;br /&gt;
&lt;br /&gt;
The &amp;lt;tt&amp;gt;bgp-cn-linux-menuconfig&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;bgp-ion-linux-menuconfig&amp;lt;/tt&amp;gt; &amp;lt;tt&amp;gt;make&amp;lt;/tt&amp;gt; targets invoke text-based Linux kernel configuration menus:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
$ make bgp-ion-linux-menuconfig&lt;br /&gt;
$ make bgp-cn-linux-menuconfig&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
For GIT build:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
$ make GIT=1 bgp-ion-linux-menuconfig&lt;br /&gt;
$ make GIT=1 bgp-cn-linux-menuconfig&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
These menu targets never update the default kernel config files from the &amp;lt;tt&amp;gt;config&amp;lt;/tt&amp;gt; directory.  If one wants to apply a new config permanently, please copy it to the &amp;lt;tt&amp;gt;config&amp;lt;/tt&amp;gt; directory by hand:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
$ cp work/build-2.6.19.2-BGP-V1R3/.config config/bgp-cn-2.6.19.2-dot-config&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Kernel (command line) parameters==&lt;br /&gt;
&lt;br /&gt;
In common server/desktop Linux environments, kernel parameters can be passed via a bootloader such as grub. However, Blue Gene/P boot mechanism does not provide such capability, so we have modified the CN Linux kernel (2.6.19) to use a kernel parameter string embedded in kernel ELF image file itself.&lt;br /&gt;
&lt;br /&gt;
One can (re)set the kernel parameters in a kernel ELF file using a command line tool &amp;lt;tt&amp;gt;zkparam.py&amp;lt;/tt&amp;gt;, located in the &amp;lt;tt&amp;gt;bin&amp;lt;/tt&amp;gt; subdirectory of the ZeptoOS installation directory.  Here is the synopsis of the tool:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
zkparam.py &amp;lt;kernel_image&amp;gt; [options]&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
If options are omitted, the tool shows the current kernel parameters.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
$ ./kernel/zkparam.py  BGP-CN-zImage-with-initrd.elf  zepto_console_output=2&lt;br /&gt;
$ ./kernel/zkparam.py  BGP-CN-zImage-with-initrd.elf &lt;br /&gt;
Current Kernel Parameters:&lt;br /&gt;
 zepto_console_output=2&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===ZeptoOS-pecific kernel parameters===&lt;br /&gt;
&lt;br /&gt;
* '''zepto_debug'''=&amp;lt;integer&amp;gt;&lt;br /&gt;
** Specifies the ZeptoOS kernel debug level.&lt;br /&gt;
** The higher the number, the more messages are generated.&lt;br /&gt;
** &amp;lt;tt&amp;gt;0&amp;lt;/tt&amp;gt; turns off all debug messages.&lt;br /&gt;
** default=1&lt;br /&gt;
* '''flatmemsizeMB'''=&amp;lt;integer&amp;gt;&lt;br /&gt;
** Specifies the size of big memory in MB.&lt;br /&gt;
** Currently the granularity of memory size is 256&amp;amp;nbsp;MB.&lt;br /&gt;
** default=256  min=256  max=1792&lt;br /&gt;
* '''zepto_console_output'''=&amp;lt;integer&amp;gt;&lt;br /&gt;
** Specifies the console output behavior. &lt;br /&gt;
** 0 disables console output from all compute nodes.&lt;br /&gt;
** 1 enables console output from the first compute node ([[FAQ#Torus rank|torus rank]] 0).&lt;br /&gt;
** 2 enables console output from all compute nodes.&lt;br /&gt;
&lt;br /&gt;
==Log files, etc==&lt;br /&gt;
&amp;lt;!--&lt;br /&gt;
===Compute Node log===&lt;br /&gt;
&lt;br /&gt;
Debug messages from compute node (i.e, via printk) will appear in one of system log files.&lt;br /&gt;
The system log file is recreated every time at system reset. You can find the location of the system log file&lt;br /&gt;
by typing the following command. &lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
$ ls -1 /bgsys/logs/BGP/sn*-mmcs_db_server*.log|tail -1&lt;br /&gt;
/bgsys/logs/BGP/sn1-mmcs_db_server-2009-0209-11:58:20.log&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Please also take a look at a convenient script BGP/packages/tools/cn-log.sh&lt;br /&gt;
&lt;br /&gt;
===ION Node log===&lt;br /&gt;
&lt;br /&gt;
Debug message from ION node will appear in ION node log files in /bgsys/logs/BGP/,&lt;br /&gt;
/bgsys/logs/BGP/R00-M0-N00-J00.log for example.&lt;br /&gt;
Each ION has own log file. ION to CN ratio is 1:64 in ANL system. If your job is a 64 (physical) nodes job,&lt;br /&gt;
you have one ION log file. &lt;br /&gt;
&lt;br /&gt;
Please also take a look at a convenient script BGP/packages/tools/ion-log.sh&lt;br /&gt;
&lt;br /&gt;
===RAS events===&lt;br /&gt;
--&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The compute node and I/O node logfile have been discussed extensively in [[Testing#Log files|Testing]].&lt;br /&gt;
&lt;br /&gt;
In addition to regular console logs, the kernels can also generate RAS message, which will not appear in the log files. A command line tool named &amp;lt;tt&amp;gt;bg-listevents&amp;lt;/tt&amp;gt; shows you a record of RAS events. Type &amp;lt;tt&amp;gt;bg-listevents -h&amp;lt;/tt&amp;gt; for command line arguments.&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
[[MPICH, DCMF, and SPI]] | [[ZeptoOS_Documentation|Top]] | [[Ramdisk]]&lt;/div&gt;</summary>
		<author><name>Iskra</name></author>
	</entry>
	<entry>
		<id> /zeptoos/index.php?title=Kernel&amp;diff=598</id>
		<title>Kernel</title>
		<link rel="alternate" type="text/html" href=" /zeptoos/index.php?title=Kernel&amp;diff=598"/>
		<updated>2009-05-08T17:58:37Z</updated>

		<summary type="html">&lt;p&gt;Iskra: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;[[MPICH, DCMF, and SPI]] | [[ZeptoOS_Documentation|Top]] | [[Ramdisk]]&lt;br /&gt;
----&lt;br /&gt;
&lt;br /&gt;
==Introduction==&lt;br /&gt;
&lt;br /&gt;
We currently provide two Linux kernels:&lt;br /&gt;
&lt;br /&gt;
* 2.6.19-based kernel: ZeptoOS CN kernel&lt;br /&gt;
** IBM V1R3 patch and ZeptoOS patch applied&lt;br /&gt;
** 64&amp;amp;nbsp;KB page size and big memory region available&lt;br /&gt;
** Device drivers for compute node devices such as DMA, lockbox, etc&lt;br /&gt;
** Allows to run MPICH/DCMF code through Zepto Compute Binary (ZCB)&lt;br /&gt;
** Can be used as enhanced ION kernel&lt;br /&gt;
&lt;br /&gt;
* 2.6.16-based kernel: ZeptoOS ION kernel&lt;br /&gt;
** IBM V1R3 patch applied&lt;br /&gt;
** Only minor changes compared to the IBM ION kernel.&lt;br /&gt;
&lt;br /&gt;
We focus our development efforts on the 2.6.19-based kernel.  It is meant primarily for the compute nodes, but can also be used on the I/O nodes.  The problem is that GPFS does not work with this kernel, so we also provide the 2.6.16-based kernel which GPFS does work with.&lt;br /&gt;
&lt;br /&gt;
==Kernel directory structure==&lt;br /&gt;
&lt;br /&gt;
The &amp;lt;tt&amp;gt;kernel&amp;lt;/tt&amp;gt; directory consists of three main subdirectories: &amp;lt;tt&amp;gt;prebuilt&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;config&amp;lt;/tt&amp;gt;, and &amp;lt;tt&amp;gt;tarball&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
kernel&lt;br /&gt;
|-- prebuilt&lt;br /&gt;
|   |-- 2.6.16&lt;br /&gt;
|   |   `-- ION&lt;br /&gt;
|   `-- 2.6.19&lt;br /&gt;
|       |-- CN&lt;br /&gt;
|       `-- objs&lt;br /&gt;
|-- tarball&lt;br /&gt;
`-- config&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The &amp;lt;tt&amp;gt;prebuilt&amp;lt;/tt&amp;gt; directory contains prebuilt kernel images and modules. While a complete prebuilt ION kernel ELF file is provided, for the CN kernel we provide intermediate object files instead.  This is because we embed the CN ramdisk in the CN kernel image when building ZeptoOS, and this process requires the object files.&lt;br /&gt;
&lt;br /&gt;
The &amp;lt;tt&amp;gt;tarball&amp;lt;/tt&amp;gt; directory contains kernel tarballs separately for the ION and the CN Linux kernel. Technically, those tarballs are snapshots of the ZeptoOS kernel git repository. The directory might contain a &amp;lt;tt&amp;gt;.patch&amp;lt;/tt&amp;gt; file that contains the differences between the last snapshot and the current git HEAD since we wanted to avoid creating a snapshot from git for small modifications. Associated git log files can also be found in this directory. A &amp;lt;tt&amp;gt;.SNAPSHOT_HEAD&amp;lt;/tt&amp;gt; file indicates the git revision at the time when a snapshot was created, so this information is used to create a patch file.&lt;br /&gt;
&lt;br /&gt;
As an example, here is a list of files for the CN kernel:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
linux-2.6.19.2-BGP-V1R3.git.log&lt;br /&gt;
linux-2.6.19.2-BGP-V1R3.patch&lt;br /&gt;
linux-2.6.19.2-BGP-V1R3.SNAPSHOT_HEAD&lt;br /&gt;
linux-2.6.19.2-BGP-V1R3.tar.bz2&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The &amp;lt;tt&amp;gt;config&amp;lt;/tt&amp;gt; directory contains Linux kernel configs.  In case of the 2.6.19 kernel, we provide separate config files for the compute node and the I/O node.&lt;br /&gt;
&lt;br /&gt;
==Building a kernel==&lt;br /&gt;
&lt;br /&gt;
The &amp;lt;tt&amp;gt;Makefile&amp;lt;/tt&amp;gt; in the &amp;lt;tt&amp;gt;kernel&amp;lt;/tt&amp;gt; directory has many targets. Just type &amp;lt;tt&amp;gt;make&amp;lt;/tt&amp;gt; and it will print out a help message. &lt;br /&gt;
&lt;br /&gt;
If one needs to build (or rebuild) a kernel from a source tarball, use &amp;lt;tt&amp;gt;bgp-ion-linux-build&amp;lt;/tt&amp;gt; or &amp;lt;tt&amp;gt;bgp-cn-linux-build&amp;lt;/tt&amp;gt; targets. By default, it extracts ION or CN kernel tarball in a directory named &amp;lt;tt&amp;gt;work&amp;lt;/tt&amp;gt;, applies a patch if any and starts the kernel build. Once the kernel has successfully been built, kernel images (in both ZeptoOS top-level directory and the &amp;lt;tt&amp;gt;tmp&amp;lt;/tt&amp;gt; directory) will be replaced with newly built ones. The ION kernel source code is extracted into &amp;lt;tt&amp;gt;work/linux-2.6.16.46-297-BGP-V1R3&amp;lt;/tt&amp;gt; and the CN kernel source into &amp;lt;tt&amp;gt;work/linux-2.6.19.2-BGP-V1R3&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Here is an example of building and rebuilding the CN kernel:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
$ cd kernel&lt;br /&gt;
$ make bgp-cn-linux-build&lt;br /&gt;
....&lt;br /&gt;
$ ls -al ../BGP-CN-zImage-with-initrd.elf&lt;br /&gt;
$ vi work/linux-2.6.19.2-BGP-V1R3/kernel/sched.c&lt;br /&gt;
$ make bgp-cn-linux-build&lt;br /&gt;
....&lt;br /&gt;
$ ls -al ../BGP-CN-zImage-with-initrd.elf&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Building a kernel from the ZeptoOS kernel git repository===&lt;br /&gt;
&lt;br /&gt;
As mentioned earlier, kernel tarballs are used as the source by default.  If instead one passes &amp;lt;tt&amp;gt;GIT=1&amp;lt;/tt&amp;gt; to &amp;lt;tt&amp;gt;make&amp;lt;/tt&amp;gt;, one can build directly from the ZeptoOS kernel git tree. This is very useful for kernel development since it makes it easier to keep track of local modifications. &lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
$ cd kernel&lt;br /&gt;
$ make GIT=1 bgp-cn-linux-build&lt;br /&gt;
....&lt;br /&gt;
$ vi repo/linux-2.6.19.2-BGP-V1R3/kernel/sched.c&lt;br /&gt;
$ make GIT=1 bgp-cn-linux-build&lt;br /&gt;
....&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This will create &amp;lt;tt&amp;gt;repo/linux-2.6.19.2-BGP-V1R3&amp;lt;/tt&amp;gt;, which is a git repository that is cloned from http://git.anl-external.org/bg-linux.repos/linux-2.6.19-BGP-V1R3.git/. Our http repo is read-only, so you cannot push your modifications to it. Instead, please post any patches to the [mailto:zeptoos@lists.mcs.anl.gov ZeptoOS developers mailing list]. &lt;br /&gt;
&lt;br /&gt;
See also the [http://bg-linux.anl-external.org/wiki/index.php/Main_Page BG-Linux page] for the details on our kernel git repository.&lt;br /&gt;
&lt;br /&gt;
===Kernel config===&lt;br /&gt;
&lt;br /&gt;
When one invokes &amp;lt;tt&amp;gt;make&amp;lt;/tt&amp;gt; with a kernel build target for the first time, the associated kernel config file is copied to &amp;lt;tt&amp;gt;.config&amp;lt;/tt&amp;gt; in the kernel build directory.  &amp;lt;tt&amp;gt;config/bgp-cn-2.6.19.2-dot-config&amp;lt;/tt&amp;gt; is applied to the CN Linux kernel build tree, and &amp;lt;tt&amp;gt;config/bgp-ion-2.6.16.46-dot-config&amp;lt;/tt&amp;gt; is applied to the ION Linux kernel build tree.&lt;br /&gt;
&lt;br /&gt;
Here is the location of the kernel config file:&lt;br /&gt;
* Regular build&lt;br /&gt;
** work/build-2.6.19.2-BGP-V1R3/.config&lt;br /&gt;
** work/build-2.6.16.46-297-BGP-V1R3/.config&lt;br /&gt;
* GIT build&lt;br /&gt;
** repo/build-2.6.19.2-BGP-V1R3/.config&lt;br /&gt;
** repo/build-2.6.16.46-297-BGP-V1R3/.config&lt;br /&gt;
&lt;br /&gt;
Please note that the kernel config file is copied only once, until you do a &amp;lt;tt&amp;gt;distclean&amp;lt;/tt&amp;gt; or remove the files manually.&lt;br /&gt;
&lt;br /&gt;
The &amp;lt;tt&amp;gt;bgp-cn-linux-menuconfig&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;bgp-ion-linux-menuconfig&amp;lt;/tt&amp;gt; &amp;lt;tt&amp;gt;make&amp;lt;/tt&amp;gt; targets invoke text-based Linux kernel configuration menus:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
$ make bgp-ion-linux-menuconfig&lt;br /&gt;
$ make bgp-cn-linux-menuconfig&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
For GIT build:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
$ make GIT=1 bgp-ion-linux-menuconfig&lt;br /&gt;
$ make GIT=1 bgp-cn-linux-menuconfig&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
These menu targets never update the default kernel config files from the &amp;lt;tt&amp;gt;config&amp;lt;/tt&amp;gt; directory.  If you want to apply a new config permanently, please copy it to the &amp;lt;tt&amp;gt;config&amp;lt;/tt&amp;gt; directory by hand:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
$ cp work/build-2.6.19.2-BGP-V1R3/.config  config/bgp-cn-2.6.19.2-dot-config&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Kernel (command line) parameters==&lt;br /&gt;
&lt;br /&gt;
In common server/desktop Linux environments, kernel parameters can be passed via bootloader such as grub. However, Blue Gene/P boot mechanism does not provide such capability, so we have modified the CN Linux kernel (2.6.19) to use a kernel parameter string embedded in kernel ELF image file itself.&lt;br /&gt;
&lt;br /&gt;
One can (re)set the kernel parameters in a kernel ELF file using a command line tool &amp;lt;tt&amp;gt;zkparam.py&amp;lt;/tt&amp;gt;, located in the &amp;lt;tt&amp;gt;bin&amp;lt;tt&amp;gt; subdirectory of the ZeptoOS installation directory.  Here is the synopsis of the tool:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
zkparam.py &amp;lt;kernel_image&amp;gt; [options]&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
If options are omitted, the tool shows the current kernel parameters.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
$ ./kernel/zkparam.py  BGP-CN-zImage-with-initrd.elf  zepto_console_output=2&lt;br /&gt;
$ ./kernel/zkparam.py  BGP-CN-zImage-with-initrd.elf &lt;br /&gt;
Current Kernel Parameters:&lt;br /&gt;
 zepto_console_output=2&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===ZeptoOS-pecific kernel parameters===&lt;br /&gt;
&lt;br /&gt;
* '''zepto_debug'''=&amp;lt;integer&amp;gt;&lt;br /&gt;
** Specifies the ZeptoOS kernel debug level.&lt;br /&gt;
** The higher the number, the more messages are generated.&lt;br /&gt;
** &amp;lt;tt&amp;gt;0&amp;lt;/tt&amp;gt; turns off all debug messages.&lt;br /&gt;
** default=1&lt;br /&gt;
* '''flatmemsizeMB'''=&amp;lt;integer&amp;gt;&lt;br /&gt;
** Specifies the size of big memory in MB.&lt;br /&gt;
** Currently the granularity of memory size is 256&amp;amp;nbsp;MB.&lt;br /&gt;
** default=256  min=256  max=1792&lt;br /&gt;
* '''zepto_console_output'''=&amp;lt;integer&amp;gt;&lt;br /&gt;
** Specifies the console output behavior. &lt;br /&gt;
** 0 disables console output from all compute nodes.&lt;br /&gt;
** 1 enables console output from the first compute node ([[FAQ#Torus rank|torus rank]] 0).&lt;br /&gt;
** 2 enables console output from all compute nodes.&lt;br /&gt;
&lt;br /&gt;
==Log files, etc==&lt;br /&gt;
&amp;lt;!--&lt;br /&gt;
===Compute Node log===&lt;br /&gt;
&lt;br /&gt;
Debug messages from compute node (i.e, via printk) will appear in one of system log files.&lt;br /&gt;
The system log file is recreated every time at system reset. You can find the location of the system log file&lt;br /&gt;
by typing the following command. &lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
$ ls -1 /bgsys/logs/BGP/sn*-mmcs_db_server*.log|tail -1&lt;br /&gt;
/bgsys/logs/BGP/sn1-mmcs_db_server-2009-0209-11:58:20.log&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Please also take a look at a convenient script BGP/packages/tools/cn-log.sh&lt;br /&gt;
&lt;br /&gt;
===ION Node log===&lt;br /&gt;
&lt;br /&gt;
Debug message from ION node will appear in ION node log files in /bgsys/logs/BGP/,&lt;br /&gt;
/bgsys/logs/BGP/R00-M0-N00-J00.log for example.&lt;br /&gt;
Each ION has own log file. ION to CN ratio is 1:64 in ANL system. If your job is a 64 (physical) nodes job,&lt;br /&gt;
you have one ION log file. &lt;br /&gt;
&lt;br /&gt;
Please also take a look at a convenient script BGP/packages/tools/ion-log.sh&lt;br /&gt;
&lt;br /&gt;
===RAS events===&lt;br /&gt;
--&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The compute node and I/O node logfile have been discussed extensively in [[Testing#Log files|Testing]].&lt;br /&gt;
&lt;br /&gt;
In addition to regular console logs, the kernels can also generate RAS message, which will not appear in the log files. A command line tool named &amp;lt;tt&amp;gt;bg-listevents&amp;lt;/tt&amp;gt; shows you a record of RAS events. Type &amp;lt;tt&amp;gt;bg-listevents -h&amp;lt;/tt&amp;gt; for command line arguments.&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
[[MPICH, DCMF, and SPI]] | [[ZeptoOS_Documentation|Top]] | [[Ramdisk]]&lt;/div&gt;</summary>
		<author><name>Iskra</name></author>
	</entry>
	<entry>
		<id> /zeptoos/index.php?title=Kernel&amp;diff=597</id>
		<title>Kernel</title>
		<link rel="alternate" type="text/html" href=" /zeptoos/index.php?title=Kernel&amp;diff=597"/>
		<updated>2009-05-08T17:00:50Z</updated>

		<summary type="html">&lt;p&gt;Iskra: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;[[MPICH, DCMF, and SPI]] | [[ZeptoOS_Documentation|Top]] | [[Ramdisk]]&lt;br /&gt;
----&lt;br /&gt;
&lt;br /&gt;
==Introduction==&lt;br /&gt;
&lt;br /&gt;
We currently provide two Linux kernels:&lt;br /&gt;
&lt;br /&gt;
* 2.6.19-based kernel: ZeptoOS CN kernel&lt;br /&gt;
** IBM V1R3 patch and ZeptoOS patch applied&lt;br /&gt;
** 64&amp;amp;nbsp;KB page size and big memory region available&lt;br /&gt;
** Device drivers for compute node devices such as DMA, lockbox, etc&lt;br /&gt;
** Allows to run MPICH/DCMF code through Zepto Compute Binary (ZCB)&lt;br /&gt;
** Can be used as enhanced ION kernel&lt;br /&gt;
&lt;br /&gt;
* 2.6.16-based kernel: ZeptoOS ION kernel&lt;br /&gt;
** IBM V1R3 patch applied&lt;br /&gt;
** Only minor changes compared to the IBM ION kernel.&lt;br /&gt;
&lt;br /&gt;
We focus our development efforts on the 2.6.19-based kernel.  It is meant primarily for the compute nodes, but can also be used on the I/O nodes.  The problem is that GPFS does not work with this kernel, so we also provide the 2.6.16-based kernel which GPFS does work with.&lt;br /&gt;
&lt;br /&gt;
==Kernel directory structure==&lt;br /&gt;
&lt;br /&gt;
The &amp;lt;tt&amp;gt;kernel&amp;lt;/tt&amp;gt; directory consists of three main subdirectories: &amp;lt;tt&amp;gt;prebuilt&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;config&amp;lt;/tt&amp;gt;, and &amp;lt;tt&amp;gt;tarball&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
kernel&lt;br /&gt;
|-- prebuilt&lt;br /&gt;
|   |-- 2.6.16&lt;br /&gt;
|   |   `-- ION&lt;br /&gt;
|   `-- 2.6.19&lt;br /&gt;
|       |-- CN&lt;br /&gt;
|       `-- objs&lt;br /&gt;
|-- tarball&lt;br /&gt;
`-- config&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The &amp;lt;tt&amp;gt;prebuilt&amp;lt;/tt&amp;gt; directory contains prebuilt kernel images and modules. While a complete prebuilt ION kernel ELF file is provided, for the CN kernel we provide intermediate object files instead.  This is because we embed the CN ramdisk in the CN kernel image when building ZeptoOS, and this process requires the object files.&lt;br /&gt;
&lt;br /&gt;
The &amp;lt;tt&amp;gt;tarball&amp;lt;/tt&amp;gt; directory contains kernel tarballs separately for the ION and the CN Linux kernel. Technically, those tarballs are a snapshot of the ZeptoOS kernel git repository. The directory might contain a &amp;lt;tt&amp;gt;.patch&amp;lt;/tt&amp;gt; file that contains the differences between the last snapshot and the current git HEAD since we wanted to avoid creating a snapshot from git for small modifications. Associated git log file can also be found in this directory. A &amp;lt;tt&amp;gt;.SNAPSHOT_HEAD&amp;lt;/tt&amp;gt; file indicates the git revision at the time when a snapshot was created, so this information is used to create a patch file.&lt;br /&gt;
&lt;br /&gt;
Here is a list of files for the CN kernel:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
linux-2.6.19.2-BGP-V1R3.git.log&lt;br /&gt;
linux-2.6.19.2-BGP-V1R3.patch&lt;br /&gt;
linux-2.6.19.2-BGP-V1R3.SNAPSHOT_HEAD&lt;br /&gt;
linux-2.6.19.2-BGP-V1R3.tar.bz2&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The &amp;lt;tt&amp;gt;config&amp;lt;/tt&amp;gt; directory contains Linux kernel configs.  In case of the 2.6.19 kernel, we provide separate config files for the compute node and the I/O node.&lt;br /&gt;
&lt;br /&gt;
==Building a kernel==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;Makefile&amp;lt;/tt&amp;gt; in the &amp;lt;tt&amp;gt;kernel&amp;lt;/tt&amp;gt; directory has many options. Just type &amp;lt;tt&amp;gt;make&amp;lt;/tt&amp;gt; and it will print out a help message. &lt;br /&gt;
&lt;br /&gt;
If one needs to build (or rebuild) a kernel from the source tarball, use &amp;lt;tt&amp;gt;bgp-ion-linux-build&amp;lt;/tt&amp;gt; or &amp;lt;tt&amp;gt;bgp-cn-linux-build&amp;lt;/tt&amp;gt; target. By default, it extracts ION or CN kernel tarball in a directory named &amp;lt;tt&amp;gt;work&amp;lt;/tt&amp;gt;, applies a patch if any and starts the kernel build. Once the kernel has successfully been built, kernel images (in both ZeptoOS top-level directory and the &amp;lt;tt&amp;gt;tmp&amp;lt;/tt&amp;gt; directory) will be replaced with newly built images. The ION kernel source code is extracted into &amp;lt;tt&amp;gt;work/linux-2.6.16.46-297-BGP-V1R3&amp;lt;/tt&amp;gt; and the CN kernel source into &amp;lt;tt&amp;gt;work/linux-2.6.19.2-BGP-V1R3&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Here is an example of building and rebuilding the CN kernel:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
$ cd kernel&lt;br /&gt;
$ make bgp-cn-linux-build&lt;br /&gt;
....&lt;br /&gt;
$ ls -al ../BGP-CN-zImage-with-initrd.elf&lt;br /&gt;
$ vi work/linux-2.6.19.2-BGP-V1R3/kernel/sched.c&lt;br /&gt;
$ make bgp-cn-linux-build&lt;br /&gt;
....&lt;br /&gt;
$ ls -al ../BGP-CN-zImage-with-initrd.elf&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Building a kernel from the ZeptoOS kernel git repository===&lt;br /&gt;
&lt;br /&gt;
As mentioned earlier, the kernel tarball is used as the source by default.  If instead one passes &amp;lt;tt&amp;gt;GIT=1&amp;lt;/tt&amp;gt; to &amp;lt;tt&amp;gt;make&amp;lt;/tt&amp;gt;, one can build directly from the ZeptoOS kernel git tree. This is very useful for kernel development since it makes it easier to keep track of local modifications. &lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
$ cd kernel&lt;br /&gt;
$ make GIT=1 bgp-cn-linux-build&lt;br /&gt;
....&lt;br /&gt;
$ vi repo/linux-2.6.19.2-BGP-V1R3/kernel/sched.c&lt;br /&gt;
$ make GIT=1 bgp-cn-linux-build&lt;br /&gt;
....&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This will create &amp;lt;tt&amp;gt;repo/linux-2.6.19.2-BGP-V1R3&amp;lt;/tt&amp;gt;, which is a git repository that is cloned from http://git.anl-external.org/bg-linux.repos/linux-2.6.19-BGP-V1R3.git/. Our http repo is read-only, so you cannot push your modifications to it. Instead, please post any patches to the [mailto:zeptoos@lists.mcs.anl.gov ZeptoOS mailing list] instead. &lt;br /&gt;
&lt;br /&gt;
See also the [http://bg-linux.anl-external.org/wiki/index.php/Main_Page BG-Linux page] for the details on our kernel git repository.&lt;br /&gt;
&lt;br /&gt;
===Kernel config===&lt;br /&gt;
&lt;br /&gt;
When one invokes &amp;lt;tt&amp;gt;make&amp;lt;/tt&amp;gt; with a kernel build target for the first time, the associated kernel config file is copied to &amp;lt;tt&amp;gt;.config&amp;lt;/tt&amp;gt; in the kernel build directory.  &amp;lt;tt&amp;gt;config/bgp-cn-2.6.19.2-dot-config&amp;lt;/tt&amp;gt; is applied to the CN Linux kernel build tree, and &amp;lt;tt&amp;gt;config/bgp-ion-2.6.16.46-dot-config&amp;lt;/tt&amp;gt; is applied to the ION Linux kernel build tree.&lt;br /&gt;
&lt;br /&gt;
Here is the location of the kernel config file:&lt;br /&gt;
* Regular build&lt;br /&gt;
** work/build-2.6.19.2-BGP-V1R3/.config&lt;br /&gt;
** work/build-2.6.16.46-297-BGP-V1R3/.config&lt;br /&gt;
* GIT build&lt;br /&gt;
** repo/build-2.6.19.2-BGP-V1R3/.config&lt;br /&gt;
** repo/build-2.6.16.46-297-BGP-V1R3/.config&lt;br /&gt;
&lt;br /&gt;
Please note that the kernel config file is copied only once, until you do a &amp;lt;tt&amp;gt;distclean&amp;lt;/tt&amp;gt; or remove the files manually.&lt;br /&gt;
&lt;br /&gt;
The &amp;lt;tt&amp;gt;bgp-cn-linux-menuconfig&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;bgp-ion-linux-menuconfig&amp;lt;/tt&amp;gt; &amp;lt;tt&amp;gt;make&amp;lt;/tt&amp;gt; targets invoke text-based Linux kernel configuration menus:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
$ make bgp-ion-linux-menuconfig&lt;br /&gt;
$ make bgp-cn-linux-menuconfig&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
For GIT build:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
$ make GIT=1 bgp-ion-linux-menuconfig&lt;br /&gt;
$ make GIT=1 bgp-cn-linux-menuconfig&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
These menu targets never update the default kernel config files from the &amp;lt;tt&amp;gt;config&amp;lt;/tt&amp;gt; directory.  If you want to apply a new config permanently, please copy it to the &amp;lt;tt&amp;gt;config&amp;lt;/tt&amp;gt; directory by hand:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
$ cp work/build-2.6.19.2-BGP-V1R3/.config  config/bgp-cn-2.6.19.2-dot-config&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Kernel (command line) parameters==&lt;br /&gt;
&lt;br /&gt;
In common server/desktop Linux environments, kernel parameters can be passed via bootloader such as grub. However, Blue Gene/P boot mechanism does not provide such capability, so we have modified the CN Linux kernel (2.6.19) to use a kernel parameter string embedded in kernel ELF image file itself.&lt;br /&gt;
&lt;br /&gt;
One can (re)set the kernel parameters in a kernel ELF file using a command line tool &amp;lt;tt&amp;gt;zkparam.py&amp;lt;/tt&amp;gt;, located in the &amp;lt;tt&amp;gt;bin&amp;lt;tt&amp;gt; subdirectory of the ZeptoOS installation directory.  Here is the synopsis of the tool:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
zkparam.py &amp;lt;kernel_image&amp;gt; [options]&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
If options are omitted, the tool shows the current kernel parameters.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
$ ./kernel/zkparam.py  BGP-CN-zImage-with-initrd.elf  zepto_console_output=2&lt;br /&gt;
$ ./kernel/zkparam.py  BGP-CN-zImage-with-initrd.elf &lt;br /&gt;
Current Kernel Parameters:&lt;br /&gt;
 zepto_console_output=2&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===ZeptoOS-pecific kernel parameters===&lt;br /&gt;
&lt;br /&gt;
* '''zepto_debug'''=&amp;lt;integer&amp;gt;&lt;br /&gt;
** Specifies the ZeptoOS kernel debug level.&lt;br /&gt;
** The higher the number, the more messages are generated.&lt;br /&gt;
** &amp;lt;tt&amp;gt;0&amp;lt;/tt&amp;gt; turns off all debug messages.&lt;br /&gt;
** default=1&lt;br /&gt;
* '''flatmemsizeMB'''=&amp;lt;integer&amp;gt;&lt;br /&gt;
** Specifies the size of big memory in MB.&lt;br /&gt;
** Currently the granularity of memory size is 256&amp;amp;nbsp;MB.&lt;br /&gt;
** default=256  min=256  max=1792&lt;br /&gt;
* '''zepto_console_output'''=&amp;lt;integer&amp;gt;&lt;br /&gt;
** Specifies the console output behavior. &lt;br /&gt;
** 0 disables console output from all compute nodes.&lt;br /&gt;
** 1 enables console output from the first compute node ([[FAQ#Torus rank|torus rank]] 0).&lt;br /&gt;
** 2 enables console output from all compute nodes.&lt;br /&gt;
&lt;br /&gt;
==Log files, etc==&lt;br /&gt;
&amp;lt;!--&lt;br /&gt;
===Compute Node log===&lt;br /&gt;
&lt;br /&gt;
Debug messages from compute node (i.e, via printk) will appear in one of system log files.&lt;br /&gt;
The system log file is recreated every time at system reset. You can find the location of the system log file&lt;br /&gt;
by typing the following command. &lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
$ ls -1 /bgsys/logs/BGP/sn*-mmcs_db_server*.log|tail -1&lt;br /&gt;
/bgsys/logs/BGP/sn1-mmcs_db_server-2009-0209-11:58:20.log&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Please also take a look at a convenient script BGP/packages/tools/cn-log.sh&lt;br /&gt;
&lt;br /&gt;
===ION Node log===&lt;br /&gt;
&lt;br /&gt;
Debug message from ION node will appear in ION node log files in /bgsys/logs/BGP/,&lt;br /&gt;
/bgsys/logs/BGP/R00-M0-N00-J00.log for example.&lt;br /&gt;
Each ION has own log file. ION to CN ratio is 1:64 in ANL system. If your job is a 64 (physical) nodes job,&lt;br /&gt;
you have one ION log file. &lt;br /&gt;
&lt;br /&gt;
Please also take a look at a convenient script BGP/packages/tools/ion-log.sh&lt;br /&gt;
&lt;br /&gt;
===RAS events===&lt;br /&gt;
--&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The compute node and I/O node logfile have been discussed extensively in [[Testing#Log files|Testing]].&lt;br /&gt;
&lt;br /&gt;
In addition to regular console logs, the kernels can also generate RAS message, which will not appear in the log files. A command line tool named &amp;lt;tt&amp;gt;bg-listevents&amp;lt;/tt&amp;gt; shows you a record of RAS events. Type &amp;lt;tt&amp;gt;bg-listevents -h&amp;lt;/tt&amp;gt; for command line arguments.&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
[[MPICH, DCMF, and SPI]] | [[ZeptoOS_Documentation|Top]] | [[Ramdisk]]&lt;/div&gt;</summary>
		<author><name>Iskra</name></author>
	</entry>
	<entry>
		<id> /zeptoos/index.php?title=Testing&amp;diff=595</id>
		<title>Testing</title>
		<link rel="alternate" type="text/html" href=" /zeptoos/index.php?title=Testing&amp;diff=595"/>
		<updated>2009-05-08T16:56:52Z</updated>

		<summary type="html">&lt;p&gt;Iskra: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;[[Installation]] | [[ZeptoOS_Documentation|Top]] | [[MPICH, DCMF, and SPI]]&lt;br /&gt;
----&lt;br /&gt;
&lt;br /&gt;
Once ZeptoOS is configured and installed, it is time to test it.  Here are a few trivial tests to verify that the environment is working:&lt;br /&gt;
&lt;br /&gt;
==The /bin/sleep job==&lt;br /&gt;
&lt;br /&gt;
If using Cobalt, submit using either of the commands below:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
$ cqsub -k &amp;lt;profile-name&amp;gt; -t &amp;lt;time&amp;gt; -n 1 /bin/sleep 3600&lt;br /&gt;
$ qsub --kernel &amp;lt;profile-name&amp;gt; -t &amp;lt;time&amp;gt; -n 1 /bin/sleep 3600&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
If using &amp;lt;tt&amp;gt;mpirun&amp;lt;/tt&amp;gt; directly, submit as follows:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
$ mpirun -verbose 1 -partition &amp;lt;partition-name&amp;gt; -np 1 -timeout &amp;lt;time&amp;gt; \&lt;br /&gt;
-cwd $PWD -exe /bin/sleep 3600&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This test, if successful, will verify that the ZeptoOS compute and I/O node environments are booting correctly.  We deliberately chose a system binary such as &amp;lt;tt&amp;gt;/bin/sleep&amp;lt;/tt&amp;gt; instead of something from a network file system to reduce the number of dependencies.&lt;br /&gt;
&lt;br /&gt;
If everything works out fine, messages such as the following will be found in the error stream (''jobid''.error file if using Cobalt):&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
FE_MPI (Info) : initialize() - using jobname '' provided by scheduler interface&lt;br /&gt;
FE_MPI (Info) : Invoking mpirun backend&lt;br /&gt;
FE_MPI (Info) : connectToServer() - Handshake successful&lt;br /&gt;
BRIDGE (Info) : rm_set_serial() - The machine serial number (alias) is BGP&lt;br /&gt;
FE_MPI (Info) : Preparing partition&lt;br /&gt;
BE_MPI (Info) : Examining specified partition&lt;br /&gt;
BE_MPI (Info) : Checking partition ANL-R00-M1-N12-64 initial state ...&lt;br /&gt;
BE_MPI (Info) : Partition ANL-R00-M1-N12-64 initial state = FREE ('F')&lt;br /&gt;
BE_MPI (Info) : Checking partition owner...&lt;br /&gt;
BE_MPI (Info) : Setting new owner&lt;br /&gt;
BE_MPI (Info) : Initiating boot of the partition&lt;br /&gt;
BE_MPI (Info) : Waiting for partition ANL-R00-M1-N12-64 to boot...&lt;br /&gt;
BE_MPI (Info) : Partition is ready&lt;br /&gt;
BE_MPI (Info) : Done preparing partition&lt;br /&gt;
FE_MPI (Info) : Adding job&lt;br /&gt;
BE_MPI (Info) : Adding job to database...&lt;br /&gt;
FE_MPI (Info) : Job added with the following id: 98461&lt;br /&gt;
FE_MPI (Info) : Starting job 98461&lt;br /&gt;
FE_MPI (Info) : Waiting for job to terminate&lt;br /&gt;
BE_MPI (Info) : IO - Threads initialized&lt;br /&gt;
BE_MPI (Info) : I/O input runner thread terminated&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
(we stripped the timestamp prefixes to make the lines shorter)&lt;br /&gt;
&lt;br /&gt;
If these messages are immediately followed by other, error messages, then there is a problem.  One common instance would be:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
BE_MPI (Info) : I/O output runner thread terminated&lt;br /&gt;
BE_MPI (Info) : Job 98463 switched to state ERROR ('E')&lt;br /&gt;
BE_MPI (ERROR): Job execution failed&lt;br /&gt;
[...]&lt;br /&gt;
BE_MPI (ERROR): The error message in the job record is as follows:&lt;br /&gt;
BE_MPI (ERROR):   &amp;quot;Load failed on 172.16.3.11: Program segment is not 1MB aligned&amp;quot;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This error indicates that the job was submitted to the default software environment with the light-weight kernel, not to ZeptoOS (at the very least, the default I/O node ramdisk was used).  Go back to the [[Installation#Setting up a kernel profile|Installation]] section to fix the problem.  Information from the system log files (see below) can be useful to diagnose the problem.&lt;br /&gt;
&lt;br /&gt;
==Log files==&lt;br /&gt;
&lt;br /&gt;
===I/O node===&lt;br /&gt;
&lt;br /&gt;
Every I/O node has its own log file located in &amp;lt;tt&amp;gt;/bgsys/logs/BGP/&amp;lt;/tt&amp;gt;, with a name such as &amp;lt;tt&amp;gt;R*-M*-N*-J*.log&amp;lt;/tt&amp;gt;.  This name will generally correspond to the name of the partition where the job was running.  Above, our job ran on &amp;lt;tt&amp;gt;ANL-R00-M1-N12-64&amp;lt;/tt&amp;gt; (we could see that in the error stream; Cobalt users can also use &amp;lt;tt&amp;gt;[c]qstat&amp;lt;/tt&amp;gt;); a corresponding I/O node log file on Argonne machines will be &amp;lt;tt&amp;gt;R00-M1-N12-J00.log&amp;lt;/tt&amp;gt;.  This is how a log file from a successful ZeptoOS boot looks like:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;Linux version 2.6.16.46-297 (geeko@buildhost) (gcc version 4.1.2 (BGP)) #1 SMP Wed Apr 22 15:04:42 CDT 2009&lt;br /&gt;
Kernel command line: console=bgcons root=/dev/ram0 lpj=8500000&lt;br /&gt;
init started:  BusyBox v1.4.2 (2008-04-10 05:20:01 UTC) multi-call binary&lt;br /&gt;
Starting RPC portmap daemon..done&lt;br /&gt;
eth0: Link status [RX+,TX+]&lt;br /&gt;
mount server reported tcp not available, falling back to udp&lt;br /&gt;
mount: RPC: Remote system error - No route to host&lt;br /&gt;
Zepto ION startup-00&lt;br /&gt;
eth0      Link encap:Ethernet  HWaddr 00:14:5E:7D:0C:57  &lt;br /&gt;
          inet addr:172.16.3.15  Bcast:172.31.255.255  Mask:255.240.0.0&lt;br /&gt;
          UP BROADCAST RUNNING MULTICAST  MTU:9000  Metric:1&lt;br /&gt;
          RX packets:880 errors:0 dropped:0 overruns:0 frame:0&lt;br /&gt;
          TX packets:1009 errors:0 dropped:0 overruns:0 carrier:0&lt;br /&gt;
          collisions:0 txqueuelen:1000 &lt;br /&gt;
          RX bytes:3878545 (3.6 Mb)  TX bytes:151458 (147.9 Kb)&lt;br /&gt;
          Interrupt:32 &lt;br /&gt;
Zepto ION startup-00 done&lt;br /&gt;
                                                                      done&lt;br /&gt;
Starting syslog servicesDec 31 18:00:36 ion-15 syslogd 1.4.1: restart.&lt;br /&gt;
                                                                      done&lt;br /&gt;
Starting network time protocol daemon (NTPD) using 172.17.3.1&lt;br /&gt;
May  1 12:57:11 ion-15 ntpdate[642]: step time server 172.17.3.1 offset 1241200617.470271 sec&lt;br /&gt;
May  1 12:57:11 ion-15 ntpd[653]: ntpd 4.2.0a@1.1196-r Sat Oct  4 00:01:53 UTC 2008 (1)&lt;br /&gt;
May  1 12:57:11 ion-15 ntpd[653]: precision = 1.000 usec&lt;br /&gt;
May  1 12:57:11 ion-15 ntpd[653]: Listening on interface wildcard, 0.0.0.0#123&lt;br /&gt;
May  1 12:57:11 ion-15 ntpd[653]: Listening on interface eth0, 172.16.3.15#123&lt;br /&gt;
May  1 12:57:11 ion-15 ntpd[653]: Listening on interface lo, 127.0.0.1#123&lt;br /&gt;
May  1 12:57:11 ion-15 ntpd[653]: kernel time sync status 0040&lt;br /&gt;
                                                                      done&lt;br /&gt;
Enabling ssh&lt;br /&gt;
Mounting site filesystems&lt;br /&gt;
                                                                      done&lt;br /&gt;
Loading PVFS2 kernel module                                           done&lt;br /&gt;
Sleeping 0 seconds before starting PVFS                               done&lt;br /&gt;
Starting PVFS2 client                                                 done&lt;br /&gt;
Sleeping 10 seconds before mounting PVFS&lt;br /&gt;
                                                                      done&lt;br /&gt;
Mounting PVFS2 filesystems                                            done&lt;br /&gt;
Starting SSH daemonMay  1 12:57:21 ion-15 sshd[833]: Server listening on 0.0.0.0 port 22.&lt;br /&gt;
                                                                      done&lt;br /&gt;
Zepto ION startup-12&lt;br /&gt;
Zepto ION startup-12 done&lt;br /&gt;
Starting GPFS&lt;br /&gt;
May  1 12:57:26 ion-15 syslogd 1.4.1: restart.&lt;br /&gt;
/etc/init.d/rc3.d/S40gpfs: GPFS is ready on I/O node ion-15 : 172.16.3.15 : R00-M1-N12-J00&lt;br /&gt;
ln: creating symbolic link `/home/acherryl/acherryl' to `/gpfs/home/acherryl': File exists&lt;br /&gt;
ln: creating symbolic link `/home/bgpadmin/bgpadmin' to `/gpfs/home/bgpadmin': File exists&lt;br /&gt;
ln: creating symbolic link `/home/davidr/davidr' to `/gpfs/home/davidr': File exists&lt;br /&gt;
ln: creating symbolic link `/home/scullinl/scullinl' to `/gpfs/home/scullinl': File exists&lt;br /&gt;
Starting ZOID...&lt;br /&gt;
                                                                      done&lt;br /&gt;
Zepto ION startup-99&lt;br /&gt;
Zepto ION startup-99 done&lt;br /&gt;
May  1 17:57:59 ion-15 init: Starting pid 2823, console /dev/console: '/bin/sh'&lt;br /&gt;
BusyBox v1.4.2 (2008-10-04 00:02:35 UTC) Built-in shell (ash)&lt;br /&gt;
Enter 'help' for a list of built-in commands.&lt;br /&gt;
/bin/sh: can't access tty; job control turned off&lt;br /&gt;
~ # &lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
(again, we stripped the prefixes to make the lines shorter)&lt;br /&gt;
&lt;br /&gt;
Messages such as &amp;lt;tt&amp;gt;Zepto ION startup&amp;lt;/tt&amp;gt; or &amp;lt;tt&amp;gt;Starting ZOID&amp;lt;/tt&amp;gt; clearly indicate that a ZeptoOS I/O node ramdisk is being used.  If instead one mistakenly boots with the default ramdisk, this could be recognized by messages such as:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
Starting CIO services&lt;br /&gt;
[ciod:initialized]                                                    done&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
(&amp;lt;tt&amp;gt;ciod&amp;lt;/tt&amp;gt; is ''never'' started when using the ZeptoOS compute node Linux)&lt;br /&gt;
&lt;br /&gt;
In addition to verifying the ramdisk, the correct I/O node kernel can also be verified using the I/O node logfile by checking the kernel build timestamp in the first line of the boot log.  As of this writing the default kernel on the Argonne machines has a timestamp of &amp;lt;tt&amp;gt;Wed Oct 29 18:51:19 UTC 2008&amp;lt;/tt&amp;gt;; as can be seen above, the ZeptoOS kernel was built more recently.&lt;br /&gt;
&lt;br /&gt;
===Compute node===&lt;br /&gt;
&lt;br /&gt;
All the compute nodes on the machine share the same MMCS log file, located in &amp;lt;tt&amp;gt;/bgsys/logs/BGP/&amp;lt;/tt&amp;gt;.  The name of the log file is not fixed (it contains a timestamp), but &amp;lt;tt&amp;gt;&amp;lt;service_node&amp;gt;-bgdb0-mmcs_db_server-current.log&amp;lt;/tt&amp;gt; always links to the current file.  Because the file is shared with other jobs, we recommed to grep it for user name, partition name, or both.&lt;br /&gt;
&lt;br /&gt;
A correct boot log when booting ZeptoOS will look something like this:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
iskra:ANL-R00-M1-N12-64 {20}.0: Common Node Services V1R3M0 (efix:0)&lt;br /&gt;
iskra:ANL-R00-M1-N12-64 {20}.0: Licensed Machine Code - Property of IBM.&lt;br /&gt;
iskra:ANL-R00-M1-N12-64 {20}.0: Blue Gene/P Licensed Machine Code.&lt;br /&gt;
iskra:ANL-R00-M1-N12-64 {20}.0: Copyright IBM Corp., 2006, 2007 All Rights Reserved.&lt;br /&gt;
iskra:ANL-R00-M1-N12-64 {20}.0: Z: Zepto Linux Kernel relocating CNS... dst=80280000 src=fff40000 size=262144&lt;br /&gt;
iskra:ANL-R00-M1-N12-64 {20}.0: Z: CNS is successfully relocated to 00280000 in physical memory&lt;br /&gt;
iskra:ANL-R00-M1-N12-64 {20}.0: Linux version 2.6.19.2-g66cbca2d (kazutomo@login1) (gcc version 4.1.2 (BGP)) #12 SMP Tue Apr 21 12:58:11 CDT 2009&lt;br /&gt;
iskra:ANL-R00-M1-N12-64 {20}.0: Zone PFN ranges:&lt;br /&gt;
iskra:ANL-R00-M1-N12-64 {20}.0:   DMA             0 -&amp;gt;    28672&lt;br /&gt;
iskra:ANL-R00-M1-N12-64 {20}.0:   Normal      28672 -&amp;gt;    28672&lt;br /&gt;
iskra:ANL-R00-M1-N12-64 {20}.0: early_node_map[1] active PFN ranges&lt;br /&gt;
iskra:ANL-R00-M1-N12-64 {20}.1:     0:        0 -&amp;gt;    28672&lt;br /&gt;
iskra:ANL-R00-M1-N12-64 {20}.1: Built 1 zonelists.  Total pages: 28658&lt;br /&gt;
iskra:ANL-R00-M1-N12-64 {20}.1: Kernel command line: console=bgcons root=/dev/ram0 lpj=8500000&lt;br /&gt;
iskra:ANL-R00-M1-N12-64 {20}.1: PID hash table entries: 4096 (order: 12, 16384 bytes)&lt;br /&gt;
iskra:ANL-R00-M1-N12-64 {20}.0: Dentry cache hash table entries: 262144 (order: 4, 1048576 bytes)&lt;br /&gt;
iskra:ANL-R00-M1-N12-64 {20}.0: Inode-cache hash table entries: 131072 (order: 3, 524288 bytes)&lt;br /&gt;
iskra:ANL-R00-M1-N12-64 {20}.0: Memory: 1826560k available (1408k kernel code, 832k data, 192k init, 0k highmem)&lt;br /&gt;
iskra:ANL-R00-M1-N12-64 {20}.0: Calibrating delay loop (skipped)... 1700.00 BogoMIPS preset&lt;br /&gt;
iskra:ANL-R00-M1-N12-64 {20}.0: Mount-cache hash table entries: 8192&lt;br /&gt;
iskra:ANL-R00-M1-N12-64 {20}.0: CPU 1 done callin...&lt;br /&gt;
iskra:ANL-R00-M1-N12-64 {20}.0: CPU 1 done setup...&lt;br /&gt;
iskra:ANL-R00-M1-N12-64 {20}.0: CPU 1 done timebase take...&lt;br /&gt;
iskra:ANL-R00-M1-N12-64 {20}.0: Processor 1 found.&lt;br /&gt;
iskra:ANL-R00-M1-N12-64 {20}.0: CPU 2 done callin...&lt;br /&gt;
iskra:ANL-R00-M1-N12-64 {20}.0: CPU 2 done setup...&lt;br /&gt;
iskra:ANL-R00-M1-N12-64 {20}.0: CPU 2 done timebase take...&lt;br /&gt;
iskra:ANL-R00-M1-N12-64 {20}.0: Processor 2 found.&lt;br /&gt;
iskra:ANL-R00-M1-N12-64 {20}.0: CPU 3 done callin...&lt;br /&gt;
iskra:ANL-R00-M1-N12-64 {20}.0: CPU 3 done setup...&lt;br /&gt;
iskra:ANL-R00-M1-N12-64 {20}.0: CPU 3 done timebase take...&lt;br /&gt;
iskra:ANL-R00-M1-N12-64 {20}.0: Processor 3 found.&lt;br /&gt;
iskra:ANL-R00-M1-N12-64 {20}.0: Brought up 4 CPUs&lt;br /&gt;
iskra:ANL-R00-M1-N12-64 {20}.0: migration_cost=0&lt;br /&gt;
iskra:ANL-R00-M1-N12-64 {20}.0: checking if image is initramfs... it is&lt;br /&gt;
iskra:ANL-R00-M1-N12-64 {20}.0: Freeing initrd memory: 2575k freed&lt;br /&gt;
iskra:ANL-R00-M1-N12-64 {20}.0: NET: Registered protocol family 16&lt;br /&gt;
iskra:ANL-R00-M1-N12-64 {20}.0: NET: Registered protocol family 2&lt;br /&gt;
iskra:ANL-R00-M1-N12-64 {20}.0: IP route cache hash table entries: 16384 (order: 0, 65536 bytes)&lt;br /&gt;
iskra:ANL-R00-M1-N12-64 {20}.0: TCP established hash table entries: 65536 (order: 3, 524288 bytes)&lt;br /&gt;
iskra:ANL-R00-M1-N12-64 {20}.0: TCP bind hash table entries: 32768 (order: 2, 262144 bytes)&lt;br /&gt;
iskra:ANL-R00-M1-N12-64 {20}.0: TCP: Hash tables configured (established 65536 bind 32768)&lt;br /&gt;
iskra:ANL-R00-M1-N12-64 {20}.0: TCP reno registered&lt;br /&gt;
iskra:ANL-R00-M1-N12-64 {20}.0: fuse init (API version 7.7)&lt;br /&gt;
iskra:ANL-R00-M1-N12-64 {20}.0: io scheduler noop registered (default)&lt;br /&gt;
iskra:ANL-R00-M1-N12-64 {20}.0: RAMDISK driver initialized: 16 RAM disks of 32768K size 1024 blocksize&lt;br /&gt;
iskra:ANL-R00-M1-N12-64 {20}.0: tun: Universal TUN/TAP device driver, 1.6&lt;br /&gt;
iskra:ANL-R00-M1-N12-64 {20}.0: tun: (C) 1999-2004 Max Krasnyansky &amp;lt;maxk@qualcomm.com&amp;gt;&lt;br /&gt;
iskra:ANL-R00-M1-N12-64 {20}.0: TCP cubic registered&lt;br /&gt;
iskra:ANL-R00-M1-N12-64 {20}.0: NET: Registered protocol family 1&lt;br /&gt;
iskra:ANL-R00-M1-N12-64 {20}.0: NET: Registered protocol family 17&lt;br /&gt;
iskra:ANL-R00-M1-N12-64 {20}.0: NET: Registered protocol family 15&lt;br /&gt;
iskra:ANL-R00-M1-N12-64 {20}.0: Freeing unused kernel memory: 192k init&lt;br /&gt;
iskra:ANL-R00-M1-N12-64 {20}.0: init started: BusyBox(for ZeptoOS Compute Node) v1.12.1 (2009-04-21 16:08:55 CDT)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This is very easy to tell from a boot log of the default light-weight kernel, which will consist of the first four lines ''only''.&lt;br /&gt;
&lt;br /&gt;
The MMCS log file contains other useful information besides the boot log of the compute nodes.  Before the kernel starts booting, the following messages related to the newly submitted job can be found there:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
DBBlockCmd  DatabaseBlockCommandThread started: block ANL-R00-M1-N12-64, user iskra, action 1&lt;br /&gt;
DBBlockCmd  setusername iskra &lt;br /&gt;
iskra       db_allocate ANL-R00-M1-N12-64 &lt;br /&gt;
iskra       DBConsoleController::setAllocating() ANL-R00-M1-N12-64&lt;br /&gt;
iskra       block state C&lt;br /&gt;
iskra       DBConsoleController::addBlock(ANL-R00-M1-N12-64)&lt;br /&gt;
iskra:ANL-R00-M1-N12-64     BlockController::connect()&lt;br /&gt;
iskra:ANL-R00-M1-N12-64     connecting to mcServer at 127.0.0.1:1206&lt;br /&gt;
    Connected to MCServer as iskra@sn1. Client version 3. Server version 3 on fd 101&lt;br /&gt;
iskra:ANL-R00-M1-N12-64     connected to mcServer&lt;br /&gt;
iskra:ANL-R00-M1-N12-64     mcServer target set ANL-R00-M1-N12-64 created&lt;br /&gt;
iskra:ANL-R00-M1-N12-64     mcServer target set ANL-R00-M1-N12-64 opened&lt;br /&gt;
iskra:ANL-R00-M1-N12-64     {0} I/O log file: /bgsys/logs/BGP/R00-M1-N12-J00.log&lt;br /&gt;
iskra:ANL-R00-M1-N12-64     MailboxListener starting&lt;br /&gt;
iskra:ANL-R00-M1-N12-64     DBConsoleController::doneAllocating() ANL-R00-M1-N12-64&lt;br /&gt;
iskra:ANL-R00-M1-N12-64     BlockController::boot_block \&lt;br /&gt;
uloader=/bgsys/argonne-utils/partitions/ANL-R00-M1-N12-64/uloader \&lt;br /&gt;
cnload=/bgsys/argonne-utils/partitions/ANL-R00-M1-N12-64/CNS,/bgsys/argonne-utils/partitions/ANL-R00-M1-N12-64/CNK \&lt;br /&gt;
ioload=/bgsys/argonne-utils/partitions/ANL-R00-M1-N12-64/CNS,/bgsys/argonne-utils/partitions/ANL-R00-M1-N12-64/INK,/bgsys/argonne-utils/partitions/ANL-R00-M1-N12-64/ramdisk &lt;br /&gt;
iskra:ANL-R00-M1-N12-64     boot_block cookie: 587867023 compute_nodes: 64 io_nodes: 1&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Of particular relevance is the pathname to the I/O node log file(s) (if it cannot be easily guessed from the partition name) and the pathnames to the kernels and ramdisks used to boot the partition.&lt;br /&gt;
&lt;br /&gt;
After the kernel boot log, the log file will also contain information about subsequent phases of starting a job:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
iskra:ANL-R00-M1-N12-64     I/O node initialized: R00-M1-N12-J00&lt;br /&gt;
iskra:ANL-R00-M1-N12-64     DBBlockController::waitBoot(ANL-R00-M1-N12-64) block initialization successful&lt;br /&gt;
iskra       DatabaseBlockCommandThread stopped&lt;br /&gt;
DBJobCmd    DatabaseJobCommandThread started: job 98461, user iskra, action 1&lt;br /&gt;
DBJobCmd    setusername iskra &lt;br /&gt;
iskra       Starting Job 98461&lt;br /&gt;
    New thread 4398305505840, for jobid 98461&lt;br /&gt;
    selectBlock(): ANL-R00-M1-N12-64        iskra(1)        connected state: I owner: iskra&lt;br /&gt;
ANL-R00-M1-N12-64   Jobid is 98461, homedir is /gpfs/home/iskra&lt;br /&gt;
ANL-R00-M1-N12-64   persist: 1&lt;br /&gt;
ANL-R00-M1-N12-64   connecting to mpirun...&lt;br /&gt;
ANL-R00-M1-N12-64   setting mpirun stream, fd=386&lt;br /&gt;
ANL-R00-M1-N12-64   contacting control node 0 at 172.16.3.15:7000&lt;br /&gt;
ANL-R00-M1-N12-64   connected to control node 0 at 172.16.3.15:7000&lt;br /&gt;
ANL-R00-M1-N12-64   Job::load() /bin/sleep &lt;br /&gt;
ANL-R00-M1-N12-64   Job loaded: 98461&lt;br /&gt;
ANL-R00-M1-N12-64   About to start /bin/sleep&lt;br /&gt;
ANL-R00-M1-N12-64   Job 98461 set to RUNNING&lt;br /&gt;
iskra:ANL-R00-M1-N12-64     {20}.0: floating point used in kernel (task=8080cfe0, pc=80017064)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Interactive login==&lt;br /&gt;
&lt;br /&gt;
We are assuming at this point that launching &amp;lt;tt&amp;gt;/bin/sleep&amp;lt;/tt&amp;gt; has been successful and that the &amp;quot;job&amp;quot; is running.  We can now start an interactive session on our BG/P resources.  Probably the most complicated part of this operation is finding the IP address of the I/O node(s).  The allocation of I/O nodes to partitions is fixed, so on a small machine one could simply make a list.  This information is also available in the log files discussed above.&lt;br /&gt;
&lt;br /&gt;
The IP address is printed near the top of the I/O node boot log, as part of the interface configuration of the Ethernet device:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
eth0      Link encap:Ethernet  HWaddr 00:14:5E:7D:0C:57  &lt;br /&gt;
          inet addr:172.16.3.15  Bcast:172.31.255.255  Mask:255.240.0.0&lt;br /&gt;
          UP BROADCAST RUNNING MULTICAST  MTU:9000  Metric:1&lt;br /&gt;
          RX packets:880 errors:0 dropped:0 overruns:0 frame:0&lt;br /&gt;
          TX packets:1009 errors:0 dropped:0 overruns:0 carrier:0&lt;br /&gt;
          collisions:0 txqueuelen:1000 &lt;br /&gt;
          RX bytes:3878545 (3.6 Mb)  TX bytes:151458 (147.9 Kb)&lt;br /&gt;
          Interrupt:32&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
In this case, the address is &amp;lt;tt&amp;gt;172.16.3.15&amp;lt;/tt&amp;gt; (the &amp;lt;tt&amp;gt;inet addr&amp;lt;/tt&amp;gt; value).&lt;br /&gt;
&lt;br /&gt;
The IP address is also available from the MMCS log file:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
ANL-R00-M1-N12-64   contacting control node 0 at 172.16.3.15:7000&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
With larger partitions that include multiple I/O nodes, querying the MMCS logfile is probably better, as it will list all the addresses.&lt;br /&gt;
&lt;br /&gt;
Once the IP address is known, one can simply use the SSH:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
iskra@login1.surveyor:~&amp;gt; ssh 172.16.3.15&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
BusyBox v1.4.2 (2008-10-04 00:02:35 UTC) Built-in shell (ash)&lt;br /&gt;
Enter 'help' for a list of built-in commands.&lt;br /&gt;
&lt;br /&gt;
/gpfs/home/iskra $ hostname&lt;br /&gt;
ion-15&lt;br /&gt;
/gpfs/home/iskra $ &lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
If everything is configured correctly, SSH will only let in root and the partition owner; no other unprivileged user will be allowed on the node.  However, this might require site-specific customizations to work properly.  To enable access for the partition owner, an administrator might need to make adjustments to [[ZOID#The /bin.rd/update_passwd_file.sh file|update_passwd_file.sh]].  To enable password-less login for the partition owners without requiring them to set up personal SSH key pairs, we recommend to add the names of the front end nodes to the &amp;lt;tt&amp;gt;shosts.equiv&amp;lt;/tt&amp;gt; file, found in &amp;lt;tt&amp;gt;ramdisk/ION/ramdisk-add/etc/ssh.zepto/&amp;lt;/tt&amp;gt; (it is empty by default; remember to use the names from the network that interconnects front end and I/O nodes, which might be different from hostnames, e.g., at Argonne we need to add the &amp;lt;tt&amp;gt;-data&amp;lt;/tt&amp;gt; suffix to the hostnames).  Until this has all been set up, one might prefer to log on as root (&amp;lt;tt&amp;gt;ssh -l root&amp;lt;/tt&amp;gt;), passing the password provided when [[Configuration#Building|building]] the ZeptoOS environment.&lt;br /&gt;
&lt;br /&gt;
Also, even when the partition owner is correctly set up, there will be a time window while booting the I/O node when the SSH daemon is already running, but a job has not yet been started; during that window, the partition owner cannot log on. If that happens, wait a few seconds and try again.&lt;br /&gt;
&lt;br /&gt;
Here is part of the &amp;lt;tt&amp;gt;ps&amp;lt;/tt&amp;gt; output from an I/O node:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
/gpfs/home/iskra $ ps -ef&lt;br /&gt;
UID        PID  PPID  C STIME TTY          TIME CMD&lt;br /&gt;
[...]&lt;br /&gt;
65534       98     1  0 16:09 ?        00:00:00 /sbin/portmap&lt;br /&gt;
root       108    19  0 16:09 ?        00:00:00 [rpciod/0]&lt;br /&gt;
root       109    19  0 16:09 ?        00:00:00 [rpciod/1]&lt;br /&gt;
root       110    19  0 16:09 ?        00:00:00 [rpciod/2]&lt;br /&gt;
root       111    19  0 16:09 ?        00:00:00 [rpciod/3]&lt;br /&gt;
root       570     1  0 16:09 ?        00:00:00 /sbin/syslogd&lt;br /&gt;
root       577     1  0 16:09 ?        00:00:00 /sbin/klogd -c 1 -x -x&lt;br /&gt;
ntp        653     1  0 16:09 ?        00:00:00 /usr/sbin/ntpd -p /var/run/ntpd.&lt;br /&gt;
root       688     1  0 16:09 ?        00:00:00 [lockd]&lt;br /&gt;
root       775     1  0 16:09 ?        00:00:00 /bgsys/iosoft/pvfs2/sbin/pvfs2-c&lt;br /&gt;
root       776   775  0 16:09 ?        00:00:00 pvfs2-client-core --child -a 5 -&lt;br /&gt;
root       833     1  0 16:10 ?        00:00:00 /usr/sbin/sshd -o PidFile=/var/r&lt;br /&gt;
root      1016     1  0 16:10 ?        00:00:00 /bin/ksh /usr/lpp/mmfs/bin/runmm&lt;br /&gt;
root      1079     1  0 16:10 ?        00:00:00 [nfsWatchKproc]&lt;br /&gt;
root      1080     1  0 16:10 ?        00:00:00 [gpfsSwapdKproc]&lt;br /&gt;
root      1146  1016  0 16:10 ?        00:00:01 /usr/lpp/mmfs/bin//mmfsd&lt;br /&gt;
root      1153     1  0 16:10 ?        00:00:00 [mmkproc]&lt;br /&gt;
root      1152     1  0 16:10 ?        00:00:00 [mmkproc]&lt;br /&gt;
root      1154     1  0 16:10 ?        00:00:00 [mmkproc]&lt;br /&gt;
iskra     2810     1 98 16:10 ?        00:04:09 /bin.rd/zoid -a 8 -m unix_impl.s&lt;br /&gt;
root      2823     1  0 16:10 ?        00:00:00 /bin/sh&lt;br /&gt;
root      3328   833  0 16:10 ?        00:00:00 sshd: iskra [priv]             &lt;br /&gt;
iskra     3332  3328  0 16:10 ?        00:00:00 sshd: iskra@ttyp0              &lt;br /&gt;
iskra     3333  3332  0 16:10 ttyp0    00:00:00 -sh&lt;br /&gt;
iskra     3346  3333  0 16:14 ttyp0    00:00:00 ps -ef&lt;br /&gt;
/gpfs/home/iskra $ &lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The I/O nodes run a small Linux setup with the root file system in the ramdisk.  Custom processes can be started, just like on any ordinary Linux node.  In the example above, it is mostly a few system daemons and the remote file system clients (GPFS, PVFS).  Please verify at this stage that the remote file systems have been mounted correctly.&lt;br /&gt;
&lt;br /&gt;
One custom process running on the node is [[ZOID]], the I/O forwarding and job control daemon, which enables the communication with the compute nodes.  One of the facilities offered by ZOID is IP forwarding between the I/O nodes and the compute nodes, implemented using the virtual network tunneling device available in Linux:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
/gpfs/home/iskra $ ifconfig tun0&lt;br /&gt;
tun0      Link encap:UNSPEC  HWaddr 00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00  &lt;br /&gt;
          inet addr:192.168.1.254  P-t-P:192.168.1.254  Mask:255.255.255.255&lt;br /&gt;
          UP POINTOPOINT RUNNING NOARP MULTICAST  MTU:65535  Metric:1&lt;br /&gt;
          RX packets:0 errors:0 dropped:0 overruns:0 frame:0&lt;br /&gt;
          TX packets:0 errors:0 dropped:0 overruns:0 carrier:0&lt;br /&gt;
          collisions:0 txqueuelen:500 &lt;br /&gt;
          RX bytes:0 (0.0 b)  TX bytes:0 (0.0 b)&lt;br /&gt;
/gpfs/home/iskra $ &lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
At least on Argonne machines, with a 64:1 ratio of compute nodes to I/O nodes, compute nodes have addresses &amp;lt;tt&amp;gt;192.168.1.1&amp;lt;/tt&amp;gt; to &amp;lt;tt&amp;gt;192.168.1.64&amp;lt;/tt&amp;gt; (the last octet of the address is the [[FAQ#Pset rank|pset rank]]).  Somewhat confusingly, the first compute node (compute node &amp;lt;tt&amp;gt;0&amp;lt;/tt&amp;gt;) has IP address &amp;lt;tt&amp;gt;192.168.1.64&amp;lt;/tt&amp;gt;, so if one submits a one-node job as we did, that is the IP address that needs to be used to log on that sole running compute node.  On a machine with a 16:1 ratio of compute nodes to I/O nodes, the first compute node has IP address &amp;lt;tt&amp;gt;192.168.1.16&amp;lt;/tt&amp;gt;.  If you are beginning to see a pattern here, then be advised that with a 64:1 ratio, the IP address of the second compute node is... &amp;lt;tt&amp;gt;192.168.1.59&amp;lt;/tt&amp;gt;.  Do not blame us for this chaos &amp;amp;#8211; blame IBM&amp;amp;nbsp;:-).&lt;br /&gt;
&lt;br /&gt;
The compute nodes are running a &amp;lt;tt&amp;gt;telnet&amp;lt;/tt&amp;gt; daemon, and no password is required to log on them:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
/gpfs/home/iskra $ telnet 192.168.1.64&lt;br /&gt;
&lt;br /&gt;
Entering character mode&lt;br /&gt;
Escape character is '^]'.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
BusyBox(for ZeptoOS Compute Node) v1.12.1 (2009-04-21 16:08:55 CDT) built-in shell (ash)&lt;br /&gt;
Enter 'help' for a list of built-in commands.&lt;br /&gt;
&lt;br /&gt;
~ # &lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The IP address of the I/O node on this virtual network is &amp;lt;tt&amp;gt;192.168.1.254&amp;lt;/tt&amp;gt;. The network is local to each I/O node, so for larger partitions with more than one I/O node, there will be multiple distinct virtual networks that cannot communicate with each other, and the IP addresses will duplicate.&lt;br /&gt;
&lt;br /&gt;
Here is part of the &amp;lt;tt&amp;gt;ps&amp;lt;/tt&amp;gt; output from a compute node:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
~ # ps -ef&lt;br /&gt;
  PID USER       VSZ STAT COMMAND&lt;br /&gt;
[...]&lt;br /&gt;
   34 root      5440 S    /bin/sh /etc/init.d/rc.sysinit &lt;br /&gt;
   44 root      5504 S    /sbin/telnetd -l /bin/sh &lt;br /&gt;
   47 root      6528 S    /sbin/inetd &lt;br /&gt;
   48 root     46400 R N  /sbin/control &lt;br /&gt;
   62 root      7872 S    /bin/zoid-fuse -o allow_other -s /fuse &lt;br /&gt;
  116 root      5248 S    /bin/sleep 3600 &lt;br /&gt;
  118 root      5504 S    /bin/sh &lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Compute nodes have an even more stripped-down environment than the I/O nodes.  There are no user accounts &amp;amp;#8211; everything runs as root, including the application processes.  This is not a security concern, because the only practical way for a compute node to communicate with the outside world is through the I/O node, and I/O nodes ''do'' enforce user-level access control.&lt;br /&gt;
&lt;br /&gt;
There are two custom processes running on each compute node:&lt;br /&gt;
&lt;br /&gt;
'''control''' is a job management daemon responsible for tasks such as the launching of application processes, for the forwarding of stdin/out/err data, and for the management of the virtual network tunneling device from the compute node side.  Do not interfere with this process in any way; this would likely make the node inaccessible.&lt;br /&gt;
&lt;br /&gt;
'''zoid-fuse''' is a FUSE ([http://fuse.sourceforge.net/ Filesystem in Userspace]) client responsible for making the filesystems from the I/O nodes available to ordinary POSIX-compliant processes running on the compute nodes.  The whole filesystem namespace from the I/O nodes is made available on the compute nodes under &amp;lt;tt&amp;gt;/fuse/&amp;lt;/tt&amp;gt;, and symbolic links such as &amp;lt;tt&amp;gt;/home -&amp;gt; /fuse/home&amp;lt;/tt&amp;gt; are set up to keep the front end and I/O node pathnames valid on the compute nodes.  Please verify that this is correctly set up.  We do not foresee a need to change this setup, but should that prove necessary, the responsbile &amp;lt;tt&amp;gt;fuse-start&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;fuse-stop&amp;lt;/tt&amp;gt; scripts can be found under &amp;lt;tt&amp;gt;ramdisk/CN/tree/bin/&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
==Shell script job==&lt;br /&gt;
&lt;br /&gt;
Assuming that the above steps have been successful, one can now test running a simple job from a network filesystem, such as one's home directory.&lt;br /&gt;
&lt;br /&gt;
Here is a sample shell script to try:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
#!/bin/sh&lt;br /&gt;
&lt;br /&gt;
. /proc/personality.sh&lt;br /&gt;
&lt;br /&gt;
while true; do&lt;br /&gt;
    echo &amp;quot;Node $BG_RANK_IN_PSET running (stdout)&amp;quot;&lt;br /&gt;
    echo &amp;quot;Node $BG_RANK_IN_PSET running (stderr)&amp;quot; 1&amp;gt;&amp;amp;2&lt;br /&gt;
    sleep 10&lt;br /&gt;
done&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
(please see the [[FAQ#Pset rank|FAQ]] for the explanation of &amp;lt;tt&amp;gt;/proc/personality.sh&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;BG_RANK_IN_PSET&amp;lt;/tt&amp;gt;)&lt;br /&gt;
&lt;br /&gt;
Create the script file on a network filesystem that is available on the I/O nodes, set the executable bit (&amp;lt;tt&amp;gt;chmod 755&amp;lt;/tt&amp;gt;) and submit it.  Verify that the script starts correctly and that at least the standard error output is visible immediately.  The script prints a line of output from each node every ten seconds.  It does so both to the standard output and to the standard error, because, depending on software configuration, the standard output stream could be buffered on the service node.  If that is the case, kill the job and verify that the standard output data did appear.&lt;br /&gt;
&lt;br /&gt;
==MPI and OpenMP jobs==&lt;br /&gt;
&lt;br /&gt;
The final tests involve parallel programming jobs, respectively MPI and OpenMP.  Use the test programs provided with the distribution. From the top level directory:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
$ cd comm/testcodes&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Compiling===&lt;br /&gt;
&lt;br /&gt;
The programs can be compiled on a login node using:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
$ /path/to/install/bin/zmpicc -o mpi-test-linux mpi-test.c&lt;br /&gt;
$ /path/to/install/bin/zmpixlc_r -qsmp=omp -o omp-test-linux omp-test.c&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Submitting===&lt;br /&gt;
&lt;br /&gt;
Submit the MPI test like any other job; use one of the below commands:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
$ cqsub -k &amp;lt;profile-name&amp;gt; -t &amp;lt;time&amp;gt; -n &amp;lt;number-of-processes&amp;gt; $PWD/mpi-test-linux&lt;br /&gt;
$ qsub --kernel &amp;lt;profile-name&amp;gt; -t &amp;lt;time&amp;gt; -n &amp;lt;number-of-processes&amp;gt;  $PWD/mpi-test-linux&lt;br /&gt;
$ mpirun -verbose 1 -partition &amp;lt;partition-name&amp;gt; -np &amp;lt;number-of-processes&amp;gt; -timeout &amp;lt;time&amp;gt; \&lt;br /&gt;
-cwd $PWD -exe $PWD/omp-test-linux&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
For the OpenMP test, we pass the number of OpenMP threads to use in the &amp;lt;tt&amp;gt;OMP_NUM_THREADS&amp;lt;/tt&amp;gt; environment variable:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
$ cqsub -k &amp;lt;profile-name&amp;gt; -t &amp;lt;time&amp;gt; -n 1 -e OMP_NUM_THREADS=&amp;lt;num&amp;gt; $PWD/omp-test-linux&lt;br /&gt;
$ qsub --kernel &amp;lt;profile-name&amp;gt; -t &amp;lt;time&amp;gt; -n 1 --env OMP_NUM_THREADS=&amp;lt;num&amp;gt; $PWD/mpi-test-linux&lt;br /&gt;
$ mpirun -verbose 1 -partition &amp;lt;partition-name&amp;gt; -np 1 -timeout &amp;lt;time&amp;gt; \&lt;br /&gt;
-cwd $PWD -env OMP_NUM_THREADS=&amp;lt;num&amp;gt; -exe $PWD/omp-test-linux&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The MPI test benchmarks the performance of various MPI operations.  The OpenMP test is just a parallel &amp;quot;Hello world&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
'''Note:''' see the [[FAQ#Why large MPI processes do not work|FAQ]] if submitting larger MPI processes does not work properly.&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
[[Installation]] | [[ZeptoOS_Documentation|Top]] | [[MPICH, DCMF, and SPI]]&lt;/div&gt;</summary>
		<author><name>Iskra</name></author>
	</entry>
	<entry>
		<id> /zeptoos/index.php?title=Testing&amp;diff=594</id>
		<title>Testing</title>
		<link rel="alternate" type="text/html" href=" /zeptoos/index.php?title=Testing&amp;diff=594"/>
		<updated>2009-05-08T15:33:59Z</updated>

		<summary type="html">&lt;p&gt;Iskra: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;[[Installation]] | [[ZeptoOS_Documentation|Top]] | [[MPICH, DCMF, and SPI]]&lt;br /&gt;
----&lt;br /&gt;
&lt;br /&gt;
Once ZeptoOS is configured and installed, it is time to test it.  Here are a few trivial tests to verify that the environment is working:&lt;br /&gt;
&lt;br /&gt;
==The /bin/sleep job==&lt;br /&gt;
&lt;br /&gt;
If using Cobalt, submit using either of the commands below:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
$ cqsub -k &amp;lt;profile-name&amp;gt; -t &amp;lt;time&amp;gt; -n 1 /bin/sleep 3600&lt;br /&gt;
$ qsub --kernel &amp;lt;profile-name&amp;gt; -t &amp;lt;time&amp;gt; -n 1 /bin/sleep 3600&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
If using &amp;lt;tt&amp;gt;mpirun&amp;lt;/tt&amp;gt; directly, submit as follows:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
$ mpirun -verbose 1 -partition &amp;lt;partition-name&amp;gt; -np 1 -timeout &amp;lt;time&amp;gt; \&lt;br /&gt;
-cwd $PWD -exe /bin/sleep 3600&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This test, if successful, will verify that the ZeptoOS compute and I/O node environments are booting correctly.  We deliberately chose a system binary such as &amp;lt;tt&amp;gt;/bin/sleep&amp;lt;/tt&amp;gt; instead of something from a network filesystem so that even if the network filesystem does not come up for some reason, the test can still succeed.&lt;br /&gt;
&lt;br /&gt;
If everything works out fine, messages such as the following will be found in the error stream (''jobid''.error file if using Cobalt):&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
FE_MPI (Info) : initialize() - using jobname '' provided by scheduler interface&lt;br /&gt;
FE_MPI (Info) : Invoking mpirun backend&lt;br /&gt;
FE_MPI (Info) : connectToServer() - Handshake successful&lt;br /&gt;
BRIDGE (Info) : rm_set_serial() - The machine serial number (alias) is BGP&lt;br /&gt;
FE_MPI (Info) : Preparing partition&lt;br /&gt;
BE_MPI (Info) : Examining specified partition&lt;br /&gt;
BE_MPI (Info) : Checking partition ANL-R00-M1-N12-64 initial state ...&lt;br /&gt;
BE_MPI (Info) : Partition ANL-R00-M1-N12-64 initial state = FREE ('F')&lt;br /&gt;
BE_MPI (Info) : Checking partition owner...&lt;br /&gt;
BE_MPI (Info) : Setting new owner&lt;br /&gt;
BE_MPI (Info) : Initiating boot of the partition&lt;br /&gt;
BE_MPI (Info) : Waiting for partition ANL-R00-M1-N12-64 to boot...&lt;br /&gt;
BE_MPI (Info) : Partition is ready&lt;br /&gt;
BE_MPI (Info) : Done preparing partition&lt;br /&gt;
FE_MPI (Info) : Adding job&lt;br /&gt;
BE_MPI (Info) : Adding job to database...&lt;br /&gt;
FE_MPI (Info) : Job added with the following id: 98461&lt;br /&gt;
FE_MPI (Info) : Starting job 98461&lt;br /&gt;
FE_MPI (Info) : Waiting for job to terminate&lt;br /&gt;
BE_MPI (Info) : IO - Threads initialized&lt;br /&gt;
BE_MPI (Info) : I/O input runner thread terminated&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
(we stripped the timestamp prefixes to make the lines shorter)&lt;br /&gt;
&lt;br /&gt;
If these messages are immediately followed by other, error messages, then there is a problem.  One common instance would be:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
BE_MPI (Info) : I/O output runner thread terminated&lt;br /&gt;
BE_MPI (Info) : Job 98463 switched to state ERROR ('E')&lt;br /&gt;
BE_MPI (ERROR): Job execution failed&lt;br /&gt;
[...]&lt;br /&gt;
BE_MPI (ERROR): The error message in the job record is as follows:&lt;br /&gt;
BE_MPI (ERROR):   &amp;quot;Load failed on 172.16.3.11: Program segment is not 1MB aligned&amp;quot;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This error indicates that the job was submitted to the default software environment, not to ZeptoOS (at the very least, the default I/O node ramdisk was used).  You need to go back to the [[Installation#Setting up a kernel profile|Installation]] section to fix the problem.  Information from the system log files can be useful to diagnose the problem.&lt;br /&gt;
&lt;br /&gt;
==Log files==&lt;br /&gt;
&lt;br /&gt;
===I/O node===&lt;br /&gt;
&lt;br /&gt;
Every I/O node has its own log file located in &amp;lt;tt&amp;gt;/bgsys/logs/BGP/&amp;lt;/tt&amp;gt;, with a name such as &amp;lt;tt&amp;gt;R*-M*-N*-J*.log&amp;lt;/tt&amp;gt;.  This name will generally correspond to the name of the partition where the job was running.  Above, our job ran on &amp;lt;tt&amp;gt;ANL-R00-M1-N12-64&amp;lt;/tt&amp;gt; (we could see that in the error stream; Cobalt users can also use &amp;lt;tt&amp;gt;[c]qstat&amp;lt;/tt&amp;gt;); a corresponding I/O node log file on Argonne machines will be &amp;lt;tt&amp;gt;R00-M1-N12-J00.log&amp;lt;/tt&amp;gt;.  This is how a log file from a successful ZeptoOS boot looks like:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;Linux version 2.6.16.46-297 (geeko@buildhost) (gcc version 4.1.2 (BGP)) #1 SMP Wed Apr 22 15:04:42 CDT 2009&lt;br /&gt;
Kernel command line: console=bgcons root=/dev/ram0 lpj=8500000&lt;br /&gt;
init started:  BusyBox v1.4.2 (2008-04-10 05:20:01 UTC) multi-call binary&lt;br /&gt;
Starting RPC portmap daemon..done&lt;br /&gt;
eth0: Link status [RX+,TX+]&lt;br /&gt;
mount server reported tcp not available, falling back to udp&lt;br /&gt;
mount: RPC: Remote system error - No route to host&lt;br /&gt;
Zepto ION startup-00&lt;br /&gt;
eth0      Link encap:Ethernet  HWaddr 00:14:5E:7D:0C:57  &lt;br /&gt;
          inet addr:172.16.3.15  Bcast:172.31.255.255  Mask:255.240.0.0&lt;br /&gt;
          UP BROADCAST RUNNING MULTICAST  MTU:9000  Metric:1&lt;br /&gt;
          RX packets:880 errors:0 dropped:0 overruns:0 frame:0&lt;br /&gt;
          TX packets:1009 errors:0 dropped:0 overruns:0 carrier:0&lt;br /&gt;
          collisions:0 txqueuelen:1000 &lt;br /&gt;
          RX bytes:3878545 (3.6 Mb)  TX bytes:151458 (147.9 Kb)&lt;br /&gt;
          Interrupt:32 &lt;br /&gt;
Zepto ION startup-00 done&lt;br /&gt;
                                                                      done&lt;br /&gt;
Starting syslog servicesDec 31 18:00:36 ion-15 syslogd 1.4.1: restart.&lt;br /&gt;
                                                                      done&lt;br /&gt;
Starting network time protocol daemon (NTPD) using 172.17.3.1&lt;br /&gt;
May  1 12:57:11 ion-15 ntpdate[642]: step time server 172.17.3.1 offset 1241200617.470271 sec&lt;br /&gt;
May  1 12:57:11 ion-15 ntpd[653]: ntpd 4.2.0a@1.1196-r Sat Oct  4 00:01:53 UTC 2008 (1)&lt;br /&gt;
May  1 12:57:11 ion-15 ntpd[653]: precision = 1.000 usec&lt;br /&gt;
May  1 12:57:11 ion-15 ntpd[653]: Listening on interface wildcard, 0.0.0.0#123&lt;br /&gt;
May  1 12:57:11 ion-15 ntpd[653]: Listening on interface eth0, 172.16.3.15#123&lt;br /&gt;
May  1 12:57:11 ion-15 ntpd[653]: Listening on interface lo, 127.0.0.1#123&lt;br /&gt;
May  1 12:57:11 ion-15 ntpd[653]: kernel time sync status 0040&lt;br /&gt;
                                                                      done&lt;br /&gt;
Enabling ssh&lt;br /&gt;
Mounting site filesystems&lt;br /&gt;
                                                                      done&lt;br /&gt;
Loading PVFS2 kernel module                                           done&lt;br /&gt;
Sleeping 0 seconds before starting PVFS                               done&lt;br /&gt;
Starting PVFS2 client                                                 done&lt;br /&gt;
Sleeping 10 seconds before mounting PVFS&lt;br /&gt;
                                                                      done&lt;br /&gt;
Mounting PVFS2 filesystems                                            done&lt;br /&gt;
Starting SSH daemonMay  1 12:57:21 ion-15 sshd[833]: Server listening on 0.0.0.0 port 22.&lt;br /&gt;
                                                                      done&lt;br /&gt;
Zepto ION startup-12&lt;br /&gt;
Zepto ION startup-12 done&lt;br /&gt;
Starting GPFS&lt;br /&gt;
May  1 12:57:26 ion-15 syslogd 1.4.1: restart.&lt;br /&gt;
/etc/init.d/rc3.d/S40gpfs: GPFS is ready on I/O node ion-15 : 172.16.3.15 : R00-M1-N12-J00&lt;br /&gt;
ln: creating symbolic link `/home/acherryl/acherryl' to `/gpfs/home/acherryl': File exists&lt;br /&gt;
ln: creating symbolic link `/home/bgpadmin/bgpadmin' to `/gpfs/home/bgpadmin': File exists&lt;br /&gt;
ln: creating symbolic link `/home/davidr/davidr' to `/gpfs/home/davidr': File exists&lt;br /&gt;
ln: creating symbolic link `/home/scullinl/scullinl' to `/gpfs/home/scullinl': File exists&lt;br /&gt;
Starting ZOID...&lt;br /&gt;
                                                                      done&lt;br /&gt;
Zepto ION startup-99&lt;br /&gt;
Zepto ION startup-99 done&lt;br /&gt;
May  1 17:57:59 ion-15 init: Starting pid 2823, console /dev/console: '/bin/sh'&lt;br /&gt;
BusyBox v1.4.2 (2008-10-04 00:02:35 UTC) Built-in shell (ash)&lt;br /&gt;
Enter 'help' for a list of built-in commands.&lt;br /&gt;
/bin/sh: can't access tty; job control turned off&lt;br /&gt;
~ # &lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
(again, we stripped the prefixes to make the lines shorter)&lt;br /&gt;
&lt;br /&gt;
Messages such as &amp;lt;tt&amp;gt;Zepto ION startup&amp;lt;/tt&amp;gt; or &amp;lt;tt&amp;gt;Starting ZOID&amp;lt;/tt&amp;gt; clearly indicate that a ZeptoOS I/O node ramdisk is being used.  If one instead mistakenly booted with the default ramdisk, this could be recognized by messages such as:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
Starting CIO services&lt;br /&gt;
[ciod:initialized]                                                    done&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
(&amp;lt;tt&amp;gt;ciod&amp;lt;/tt&amp;gt; is ''never'' started when using Zepto Compute Node Linux)&lt;br /&gt;
&lt;br /&gt;
In addition to verifying the ramdisk, the correct I/O node kernel can also be verified using the I/O node logfile by checking the kernel build timestamp in the first line of the boot log.  As of this writing the default kernel on the Argonne machines has a timestamp of &amp;lt;tt&amp;gt;Wed Oct 29 18:51:19 UTC 2008&amp;lt;/tt&amp;gt;; as can be seen above, the ZeptoOS kernel was built more recently.&lt;br /&gt;
&lt;br /&gt;
===Compute node===&lt;br /&gt;
&lt;br /&gt;
All the compute nodes on the machine share the same MMCS log file, located in &amp;lt;tt&amp;gt;/bgsys/logs/BGP/&amp;lt;/tt&amp;gt;.  The name of the log file is not fixed (it contains a timestamp), but &amp;lt;tt&amp;gt;sn1-bgdb0-mmcs_db_server-current.log&amp;lt;/tt&amp;gt; always links to the current file.  Because the file is shared with other jobs, we recommed to grep it for user name, partition name, or both.&lt;br /&gt;
&lt;br /&gt;
A correct boot log when when booting ZeptoOS will look something like this:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
iskra:ANL-R00-M1-N12-64 {20}.0: Common Node Services V1R3M0 (efix:0)&lt;br /&gt;
iskra:ANL-R00-M1-N12-64 {20}.0: Licensed Machine Code - Property of IBM.&lt;br /&gt;
iskra:ANL-R00-M1-N12-64 {20}.0: Blue Gene/P Licensed Machine Code.&lt;br /&gt;
iskra:ANL-R00-M1-N12-64 {20}.0: Copyright IBM Corp., 2006, 2007 All Rights Reserved.&lt;br /&gt;
iskra:ANL-R00-M1-N12-64 {20}.0: Z: Zepto Linux Kernel relocating CNS... dst=80280000 src=fff40000 size=262144&lt;br /&gt;
iskra:ANL-R00-M1-N12-64 {20}.0: Z: CNS is successfully relocated to 00280000 in physical memory&lt;br /&gt;
iskra:ANL-R00-M1-N12-64 {20}.0: Linux version 2.6.19.2-g66cbca2d (kazutomo@login1) (gcc version 4.1.2 (BGP)) #12 SMP Tue Apr 21 12:58:11 CDT 2009&lt;br /&gt;
iskra:ANL-R00-M1-N12-64 {20}.0: Zone PFN ranges:&lt;br /&gt;
iskra:ANL-R00-M1-N12-64 {20}.0:   DMA             0 -&amp;gt;    28672&lt;br /&gt;
iskra:ANL-R00-M1-N12-64 {20}.0:   Normal      28672 -&amp;gt;    28672&lt;br /&gt;
iskra:ANL-R00-M1-N12-64 {20}.0: early_node_map[1] active PFN ranges&lt;br /&gt;
iskra:ANL-R00-M1-N12-64 {20}.1:     0:        0 -&amp;gt;    28672&lt;br /&gt;
iskra:ANL-R00-M1-N12-64 {20}.1: Built 1 zonelists.  Total pages: 28658&lt;br /&gt;
iskra:ANL-R00-M1-N12-64 {20}.1: Kernel command line: console=bgcons root=/dev/ram0 lpj=8500000&lt;br /&gt;
iskra:ANL-R00-M1-N12-64 {20}.1: PID hash table entries: 4096 (order: 12, 16384 bytes)&lt;br /&gt;
iskra:ANL-R00-M1-N12-64 {20}.0: Dentry cache hash table entries: 262144 (order: 4, 1048576 bytes)&lt;br /&gt;
iskra:ANL-R00-M1-N12-64 {20}.0: Inode-cache hash table entries: 131072 (order: 3, 524288 bytes)&lt;br /&gt;
iskra:ANL-R00-M1-N12-64 {20}.0: Memory: 1826560k available (1408k kernel code, 832k data, 192k init, 0k highmem)&lt;br /&gt;
iskra:ANL-R00-M1-N12-64 {20}.0: Calibrating delay loop (skipped)... 1700.00 BogoMIPS preset&lt;br /&gt;
iskra:ANL-R00-M1-N12-64 {20}.0: Mount-cache hash table entries: 8192&lt;br /&gt;
iskra:ANL-R00-M1-N12-64 {20}.0: CPU 1 done callin...&lt;br /&gt;
iskra:ANL-R00-M1-N12-64 {20}.0: CPU 1 done setup...&lt;br /&gt;
iskra:ANL-R00-M1-N12-64 {20}.0: CPU 1 done timebase take...&lt;br /&gt;
iskra:ANL-R00-M1-N12-64 {20}.0: Processor 1 found.&lt;br /&gt;
iskra:ANL-R00-M1-N12-64 {20}.0: CPU 2 done callin...&lt;br /&gt;
iskra:ANL-R00-M1-N12-64 {20}.0: CPU 2 done setup...&lt;br /&gt;
iskra:ANL-R00-M1-N12-64 {20}.0: CPU 2 done timebase take...&lt;br /&gt;
iskra:ANL-R00-M1-N12-64 {20}.0: Processor 2 found.&lt;br /&gt;
iskra:ANL-R00-M1-N12-64 {20}.0: CPU 3 done callin...&lt;br /&gt;
iskra:ANL-R00-M1-N12-64 {20}.0: CPU 3 done setup...&lt;br /&gt;
iskra:ANL-R00-M1-N12-64 {20}.0: CPU 3 done timebase take...&lt;br /&gt;
iskra:ANL-R00-M1-N12-64 {20}.0: Processor 3 found.&lt;br /&gt;
iskra:ANL-R00-M1-N12-64 {20}.0: Brought up 4 CPUs&lt;br /&gt;
iskra:ANL-R00-M1-N12-64 {20}.0: migration_cost=0&lt;br /&gt;
iskra:ANL-R00-M1-N12-64 {20}.0: checking if image is initramfs... it is&lt;br /&gt;
iskra:ANL-R00-M1-N12-64 {20}.0: Freeing initrd memory: 2575k freed&lt;br /&gt;
iskra:ANL-R00-M1-N12-64 {20}.0: NET: Registered protocol family 16&lt;br /&gt;
iskra:ANL-R00-M1-N12-64 {20}.0: NET: Registered protocol family 2&lt;br /&gt;
iskra:ANL-R00-M1-N12-64 {20}.0: IP route cache hash table entries: 16384 (order: 0, 65536 bytes)&lt;br /&gt;
iskra:ANL-R00-M1-N12-64 {20}.0: TCP established hash table entries: 65536 (order: 3, 524288 bytes)&lt;br /&gt;
iskra:ANL-R00-M1-N12-64 {20}.0: TCP bind hash table entries: 32768 (order: 2, 262144 bytes)&lt;br /&gt;
iskra:ANL-R00-M1-N12-64 {20}.0: TCP: Hash tables configured (established 65536 bind 32768)&lt;br /&gt;
iskra:ANL-R00-M1-N12-64 {20}.0: TCP reno registered&lt;br /&gt;
iskra:ANL-R00-M1-N12-64 {20}.0: fuse init (API version 7.7)&lt;br /&gt;
iskra:ANL-R00-M1-N12-64 {20}.0: io scheduler noop registered (default)&lt;br /&gt;
iskra:ANL-R00-M1-N12-64 {20}.0: RAMDISK driver initialized: 16 RAM disks of 32768K size 1024 blocksize&lt;br /&gt;
iskra:ANL-R00-M1-N12-64 {20}.0: tun: Universal TUN/TAP device driver, 1.6&lt;br /&gt;
iskra:ANL-R00-M1-N12-64 {20}.0: tun: (C) 1999-2004 Max Krasnyansky &amp;lt;maxk@qualcomm.com&amp;gt;&lt;br /&gt;
iskra:ANL-R00-M1-N12-64 {20}.0: TCP cubic registered&lt;br /&gt;
iskra:ANL-R00-M1-N12-64 {20}.0: NET: Registered protocol family 1&lt;br /&gt;
iskra:ANL-R00-M1-N12-64 {20}.0: NET: Registered protocol family 17&lt;br /&gt;
iskra:ANL-R00-M1-N12-64 {20}.0: NET: Registered protocol family 15&lt;br /&gt;
iskra:ANL-R00-M1-N12-64 {20}.0: Freeing unused kernel memory: 192k init&lt;br /&gt;
iskra:ANL-R00-M1-N12-64 {20}.0: init started: BusyBox(for ZeptoOS Compute Node) v1.12.1 (2009-04-21 16:08:55 CDT)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This is very easy to tell from a boot log of the default light-weight kernel, which will consist of the first four lines ''only''.&lt;br /&gt;
&lt;br /&gt;
The MMCS log file contains other useful information besides the boot log of the compute nodes.  Before the kernel starts booting, the following messages related to the newly submitted job can be found there:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
DBBlockCmd  DatabaseBlockCommandThread started: block ANL-R00-M1-N12-64, user iskra, action 1&lt;br /&gt;
DBBlockCmd  setusername iskra &lt;br /&gt;
iskra       db_allocate ANL-R00-M1-N12-64 &lt;br /&gt;
iskra       DBConsoleController::setAllocating() ANL-R00-M1-N12-64&lt;br /&gt;
iskra       block state C&lt;br /&gt;
iskra       DBConsoleController::addBlock(ANL-R00-M1-N12-64)&lt;br /&gt;
iskra:ANL-R00-M1-N12-64     BlockController::connect()&lt;br /&gt;
iskra:ANL-R00-M1-N12-64     connecting to mcServer at 127.0.0.1:1206&lt;br /&gt;
    Connected to MCServer as iskra@sn1. Client version 3. Server version 3 on fd 101&lt;br /&gt;
iskra:ANL-R00-M1-N12-64     connected to mcServer&lt;br /&gt;
iskra:ANL-R00-M1-N12-64     mcServer target set ANL-R00-M1-N12-64 created&lt;br /&gt;
iskra:ANL-R00-M1-N12-64     mcServer target set ANL-R00-M1-N12-64 opened&lt;br /&gt;
iskra:ANL-R00-M1-N12-64     {0} I/O log file: /bgsys/logs/BGP/R00-M1-N12-J00.log&lt;br /&gt;
iskra:ANL-R00-M1-N12-64     MailboxListener starting&lt;br /&gt;
iskra:ANL-R00-M1-N12-64     DBConsoleController::doneAllocating() ANL-R00-M1-N12-64&lt;br /&gt;
iskra:ANL-R00-M1-N12-64     BlockController::boot_block \&lt;br /&gt;
uloader=/bgsys/argonne-utils/partitions/ANL-R00-M1-N12-64/uloader \&lt;br /&gt;
cnload=/bgsys/argonne-utils/partitions/ANL-R00-M1-N12-64/CNS,/bgsys/argonne-utils/partitions/ANL-R00-M1-N12-64/CNK \&lt;br /&gt;
ioload=/bgsys/argonne-utils/partitions/ANL-R00-M1-N12-64/CNS,/bgsys/argonne-utils/partitions/ANL-R00-M1-N12-64/INK,/bgsys/argonne-utils/partitions/ANL-R00-M1-N12-64/ramdisk &lt;br /&gt;
iskra:ANL-R00-M1-N12-64     boot_block cookie: 587867023 compute_nodes: 64 io_nodes: 1&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Of particular relevance is the pathname to the I/O node log file(s) (if it cannot be easily guessed from the partition name) and the pathnames to the kernels and ramdisks used to boot the partition.&lt;br /&gt;
&lt;br /&gt;
After the kernel boot log, the log file will also contain information about subsequent phases of starting a job:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
iskra:ANL-R00-M1-N12-64     I/O node initialized: R00-M1-N12-J00&lt;br /&gt;
iskra:ANL-R00-M1-N12-64     DBBlockController::waitBoot(ANL-R00-M1-N12-64) block initialization successful&lt;br /&gt;
iskra       DatabaseBlockCommandThread stopped&lt;br /&gt;
DBJobCmd    DatabaseJobCommandThread started: job 98461, user iskra, action 1&lt;br /&gt;
DBJobCmd    setusername iskra &lt;br /&gt;
iskra       Starting Job 98461&lt;br /&gt;
    New thread 4398305505840, for jobid 98461&lt;br /&gt;
    selectBlock(): ANL-R00-M1-N12-64        iskra(1)        connected state: I owner: iskra&lt;br /&gt;
ANL-R00-M1-N12-64   Jobid is 98461, homedir is /gpfs/home/iskra&lt;br /&gt;
ANL-R00-M1-N12-64   persist: 1&lt;br /&gt;
ANL-R00-M1-N12-64   connecting to mpirun...&lt;br /&gt;
ANL-R00-M1-N12-64   setting mpirun stream, fd=386&lt;br /&gt;
ANL-R00-M1-N12-64   contacting control node 0 at 172.16.3.15:7000&lt;br /&gt;
ANL-R00-M1-N12-64   connected to control node 0 at 172.16.3.15:7000&lt;br /&gt;
ANL-R00-M1-N12-64   Job::load() /bin/sleep &lt;br /&gt;
ANL-R00-M1-N12-64   Job loaded: 98461&lt;br /&gt;
ANL-R00-M1-N12-64   About to start /bin/sleep&lt;br /&gt;
ANL-R00-M1-N12-64   Job 98461 set to RUNNING&lt;br /&gt;
iskra:ANL-R00-M1-N12-64     {20}.0: floating point used in kernel (task=8080cfe0, pc=80017064)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Interactive login==&lt;br /&gt;
&lt;br /&gt;
We are assuming at this point that launching &amp;lt;tt&amp;gt;/bin/sleep&amp;lt;/tt&amp;gt; has been successful and that the &amp;quot;job&amp;quot; is running.  We can now start an interactive session on our BG/P resources.  Probably the most complicated part of this operation is finding the IP address of the I/O node(s).  The allocation of I/O nodes to partitions is fixed, so on a small machine one could simply make a list.  This information is also available in the log files discussed above.&lt;br /&gt;
&lt;br /&gt;
The IP address is printed near the top of the I/O node boot log, as part of the interface configuration of the Ethernet device:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
eth0      Link encap:Ethernet  HWaddr 00:14:5E:7D:0C:57  &lt;br /&gt;
          inet addr:172.16.3.15  Bcast:172.31.255.255  Mask:255.240.0.0&lt;br /&gt;
          UP BROADCAST RUNNING MULTICAST  MTU:9000  Metric:1&lt;br /&gt;
          RX packets:880 errors:0 dropped:0 overruns:0 frame:0&lt;br /&gt;
          TX packets:1009 errors:0 dropped:0 overruns:0 carrier:0&lt;br /&gt;
          collisions:0 txqueuelen:1000 &lt;br /&gt;
          RX bytes:3878545 (3.6 Mb)  TX bytes:151458 (147.9 Kb)&lt;br /&gt;
          Interrupt:32&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
In this case, the address is &amp;lt;tt&amp;gt;172.16.3.15&amp;lt;/tt&amp;gt; (the &amp;lt;tt&amp;gt;inet addr&amp;lt;/tt&amp;gt; value).&lt;br /&gt;
&lt;br /&gt;
The IP address is also available from the MMCS log file:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
ANL-R00-M1-N12-64   contacting control node 0 at 172.16.3.15:7000&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
With larger partitions that include multiple I/O nodes, querying the MMCS logfile is probably better, as it will list all the addresses.&lt;br /&gt;
&lt;br /&gt;
Once the IP address is known, one can simply use the SSH:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
iskra@login1.surveyor:~&amp;gt; ssh 172.16.3.15&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
BusyBox v1.4.2 (2008-10-04 00:02:35 UTC) Built-in shell (ash)&lt;br /&gt;
Enter 'help' for a list of built-in commands.&lt;br /&gt;
&lt;br /&gt;
/gpfs/home/iskra $ hostname&lt;br /&gt;
ion-15&lt;br /&gt;
/gpfs/home/iskra $ &lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
If everything is configured correctly, SSH will only let in root and the partition owner; no other unprivileged user will be allowed on the node.  However, this might require site-specific customization to work properly.  To enable access for the partition owner, one might need to make adjustments to [[ZOID#The /bin.rd/update_passwd_file.sh file|update_passwd_file.sh]].  To enable password-less login for the partition owners without requiring them to set up personal SSH keypairs, we recommend to add the names of the front end nodes to the &amp;lt;tt&amp;gt;shosts.equiv&amp;lt;/tt&amp;gt; file, found in &amp;lt;tt&amp;gt;ramdisk/ION/ramdisk-add/etc/ssh.zepto/&amp;lt;/tt&amp;gt; (it is empty by default; remember to use the names from the network that interconnects front end and I/O nodes, which might be different from hostnames, e.g., at Argonne we need to add the &amp;lt;tt&amp;gt;-data&amp;lt;/tt&amp;gt; suffix to the hostnames).  Until this has all been set up, one might prefer to log on as root (&amp;lt;tt&amp;gt;ssh -l root&amp;lt;/tt&amp;gt;), passing the password provided while [[Configuration#Building|building]] the ZeptoOS environment.&lt;br /&gt;
&lt;br /&gt;
Also, even when the partition owner is correctly set up, there will be a time window while booting the I/O node when the SSH daemon is already running, but a job has not yet been started; during that window, the partition owner cannot log on. If that happens, wait a few seconds and try again.&lt;br /&gt;
&lt;br /&gt;
Here's part of the &amp;lt;tt&amp;gt;ps&amp;lt;/tt&amp;gt; output from the I/O node:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
/gpfs/home/iskra $ ps -ef&lt;br /&gt;
UID        PID  PPID  C STIME TTY          TIME CMD&lt;br /&gt;
[...]&lt;br /&gt;
65534       98     1  0 16:09 ?        00:00:00 /sbin/portmap&lt;br /&gt;
root       108    19  0 16:09 ?        00:00:00 [rpciod/0]&lt;br /&gt;
root       109    19  0 16:09 ?        00:00:00 [rpciod/1]&lt;br /&gt;
root       110    19  0 16:09 ?        00:00:00 [rpciod/2]&lt;br /&gt;
root       111    19  0 16:09 ?        00:00:00 [rpciod/3]&lt;br /&gt;
root       570     1  0 16:09 ?        00:00:00 /sbin/syslogd&lt;br /&gt;
root       577     1  0 16:09 ?        00:00:00 /sbin/klogd -c 1 -x -x&lt;br /&gt;
ntp        653     1  0 16:09 ?        00:00:00 /usr/sbin/ntpd -p /var/run/ntpd.&lt;br /&gt;
root       688     1  0 16:09 ?        00:00:00 [lockd]&lt;br /&gt;
root       775     1  0 16:09 ?        00:00:00 /bgsys/iosoft/pvfs2/sbin/pvfs2-c&lt;br /&gt;
root       776   775  0 16:09 ?        00:00:00 pvfs2-client-core --child -a 5 -&lt;br /&gt;
root       833     1  0 16:10 ?        00:00:00 /usr/sbin/sshd -o PidFile=/var/r&lt;br /&gt;
root      1016     1  0 16:10 ?        00:00:00 /bin/ksh /usr/lpp/mmfs/bin/runmm&lt;br /&gt;
root      1079     1  0 16:10 ?        00:00:00 [nfsWatchKproc]&lt;br /&gt;
root      1080     1  0 16:10 ?        00:00:00 [gpfsSwapdKproc]&lt;br /&gt;
root      1146  1016  0 16:10 ?        00:00:01 /usr/lpp/mmfs/bin//mmfsd&lt;br /&gt;
root      1153     1  0 16:10 ?        00:00:00 [mmkproc]&lt;br /&gt;
root      1152     1  0 16:10 ?        00:00:00 [mmkproc]&lt;br /&gt;
root      1154     1  0 16:10 ?        00:00:00 [mmkproc]&lt;br /&gt;
iskra     2810     1 98 16:10 ?        00:04:09 /bin.rd/zoid -a 8 -m unix_impl.s&lt;br /&gt;
root      2823     1  0 16:10 ?        00:00:00 /bin/sh&lt;br /&gt;
root      3328   833  0 16:10 ?        00:00:00 sshd: iskra [priv]             &lt;br /&gt;
iskra     3332  3328  0 16:10 ?        00:00:00 sshd: iskra@ttyp0              &lt;br /&gt;
iskra     3333  3332  0 16:10 ttyp0    00:00:00 -sh&lt;br /&gt;
iskra     3346  3333  0 16:14 ttyp0    00:00:00 ps -ef&lt;br /&gt;
/gpfs/home/iskra $ &lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The I/O nodes run a small Linux setup with the root filesystem in the ramdisk.  Custom processes can be started, just like on any ordinary Linux node.  In the example above, it is mostly a few system daemons and the remote filesystem clients (GPFS, PVFS).  Please verify at this stage that the remote filesystem have been mounted correctly.&lt;br /&gt;
&lt;br /&gt;
One custom process running on the node is [[ZOID]], the I/O forwarding and job control daemon, which enables the communication with the compute nodes.  One of the facilities offered by ZOID is IP forwarding between the I/O node and the compute nodes, implemented using the virtual network tunneling device available in Linux:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
/gpfs/home/iskra $ ifconfig tun0&lt;br /&gt;
tun0      Link encap:UNSPEC  HWaddr 00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00  &lt;br /&gt;
          inet addr:192.168.1.254  P-t-P:192.168.1.254  Mask:255.255.255.255&lt;br /&gt;
          UP POINTOPOINT RUNNING NOARP MULTICAST  MTU:65535  Metric:1&lt;br /&gt;
          RX packets:0 errors:0 dropped:0 overruns:0 frame:0&lt;br /&gt;
          TX packets:0 errors:0 dropped:0 overruns:0 carrier:0&lt;br /&gt;
          collisions:0 txqueuelen:500 &lt;br /&gt;
          RX bytes:0 (0.0 b)  TX bytes:0 (0.0 b)&lt;br /&gt;
/gpfs/home/iskra $ &lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
At least on Argonne machines, with a 64:1 ratio of compute nodes to I/O nodes, compute nodes have addresses &amp;lt;tt&amp;gt;192.168.1.1&amp;lt;/tt&amp;gt; to &amp;lt;tt&amp;gt;192.168.1.64&amp;lt;/tt&amp;gt; (the last octet of the address is the [[FAQ#Pset rank|pset rank]]).  Somewhat confusingly, the first compute node (compute node &amp;lt;tt&amp;gt;0&amp;lt;/tt&amp;gt;) has IP address &amp;lt;tt&amp;gt;192.168.1.64&amp;lt;/tt&amp;gt;, so if one submits a one-node job as we did, that is the IP address that needs to be used to log on that sole running compute node.  The IP address of the second compute node is... &amp;lt;tt&amp;gt;192.168.1.59&amp;lt;/tt&amp;gt;.  On a machine with a 16:1 ratio of compute nodes to I/O nodes, the first compute node has IP address &amp;lt;tt&amp;gt;192.168.1.16&amp;lt;/tt&amp;gt;.  Do not blame us for this chaos &amp;amp;#8211; blame IBM&amp;amp;nbsp;:-).&lt;br /&gt;
&lt;br /&gt;
The compute nodes are running a &amp;lt;tt&amp;gt;telnet&amp;lt;/tt&amp;gt; daemon, and no password is required to log on them:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
/gpfs/home/iskra $ telnet 192.168.1.64&lt;br /&gt;
&lt;br /&gt;
Entering character mode&lt;br /&gt;
Escape character is '^]'.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
BusyBox(for ZeptoOS Compute Node) v1.12.1 (2009-04-21 16:08:55 CDT) built-in shell (ash)&lt;br /&gt;
Enter 'help' for a list of built-in commands.&lt;br /&gt;
&lt;br /&gt;
~ # &lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The IP address of the I/O node on this virtual network is &amp;lt;tt&amp;gt;192.168.1.254&amp;lt;/tt&amp;gt;. The network is local to each I/O node, so for larger jobs, there will be multiple distinct virtual networks that cannot communicate with each other, and the IP addresses will duplicate.&lt;br /&gt;
&lt;br /&gt;
Here's part of the &amp;lt;tt&amp;gt;ps&amp;lt;/tt&amp;gt; output from the compute node:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
~ # ps -ef&lt;br /&gt;
  PID USER       VSZ STAT COMMAND&lt;br /&gt;
[...]&lt;br /&gt;
   34 root      5440 S    /bin/sh /etc/init.d/rc.sysinit &lt;br /&gt;
   44 root      5504 S    /sbin/telnetd -l /bin/sh &lt;br /&gt;
   47 root      6528 S    /sbin/inetd &lt;br /&gt;
   48 root     46400 R N  /sbin/control &lt;br /&gt;
   62 root      7872 S    /bin/zoid-fuse -o allow_other -s /fuse &lt;br /&gt;
  116 root      5248 S    /bin/sleep 3600 &lt;br /&gt;
  118 root      5504 S    /bin/sh &lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Compute nodes have an even more stripped-down environment than the I/O nodes.  There are no user accounts &amp;amp;#8211; everything runs as root, including the application processes.  This is not a security concern, because the only practical way for a compute node to communicate with the outside world is through the I/O node, and I/O nodes ''do'' enforce user-level access control.&lt;br /&gt;
&lt;br /&gt;
There are two custom processes running on each compute node:&lt;br /&gt;
&lt;br /&gt;
'''control''' is a job management daemon responsible for tasks such as the launching of application processes, for the forwarding of stdin/out/err data, and for the management of the virtual network tunneling device from the compute node side.  Do not interfere with this process in any way; this would likely make the node inaccessible.&lt;br /&gt;
&lt;br /&gt;
'''zoid-fuse''' is a FUSE ([http://fuse.sourceforge.net/ Filesystem in Userspace]) client responsible for making the filesystems from the I/O nodes available to ordinary POSIX-compliant processes running on the compute nodes.  The whole filesystem namespace from the I/O nodes is made available on the compute nodes under &amp;lt;tt&amp;gt;/fuse/&amp;lt;/tt&amp;gt;, and symbolic links such as &amp;lt;tt&amp;gt;/home -&amp;gt; /fuse/home&amp;lt;/tt&amp;gt; are set up to keep the login and I/O node pathnames valid on the compute nodes.  Please verify that this is correctly set up.  We do not foresee a need to change this setup, but should that prove necessary, the responsbile &amp;lt;tt&amp;gt;fuse-start&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;fuse-stop&amp;lt;/tt&amp;gt; scripts can be found under &amp;lt;tt&amp;gt;ramdisk/CN/tree/bin&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
==Shell script job==&lt;br /&gt;
&lt;br /&gt;
Assuming that the above steps have been successful, one can now test running a simple job from a network filesystem, such as one's home directory.&lt;br /&gt;
&lt;br /&gt;
Here is a sample shell script to try:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
#!/bin/sh&lt;br /&gt;
&lt;br /&gt;
. /proc/personality.sh&lt;br /&gt;
&lt;br /&gt;
while true; do&lt;br /&gt;
    echo &amp;quot;Node $BG_RANK_IN_PSET running (stdout)&amp;quot;&lt;br /&gt;
    echo &amp;quot;Node $BG_RANK_IN_PSET running (stderr)&amp;quot; 1&amp;gt;&amp;amp;2&lt;br /&gt;
    sleep 10&lt;br /&gt;
done&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
(please see the [[FAQ#Pset rank|FAQ]] for the explanation of &amp;lt;tt&amp;gt;/proc/personality.sh&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;BG_RANK_IN_PSET&amp;lt;/tt&amp;gt;)&lt;br /&gt;
&lt;br /&gt;
Please create the script file on the network filesystem, set the executable bit (&amp;lt;tt&amp;gt;chmod 755&amp;lt;/tt&amp;gt;) and submit it.  Verify that the script starts correctly and that at least the standard error output is visible immediately.  The scripts print a line of output from each node every ten seconds.  It does so both to the standard output and to the standard error, because, depending on software configuration, the standard output stream could be buffered.  If that is the case, kill the job and verify that the standard output data did appear.&lt;br /&gt;
&lt;br /&gt;
==MPI and OpenMP jobs==&lt;br /&gt;
&lt;br /&gt;
The final tests involve parallel programming jobs, respectively MPI and OpenMP.  Use the test programs provided with the distribution. From the top level directory:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
$ cd comm/testcodes&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Compiling===&lt;br /&gt;
&lt;br /&gt;
The programs can be compiled on a login node using:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
$ /path/to/install/bin/zmpicc -o mpi-test-linux mpi-test.c&lt;br /&gt;
$ /path/to/install/bin/zmpixlc_r -qsmp=omp -o omp-test-linux omp-test.c&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Submitting===&lt;br /&gt;
&lt;br /&gt;
Submit the MPI test like any other job; use one of the below:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
$ cqsub -k &amp;lt;profile-name&amp;gt; -t &amp;lt;time&amp;gt; -n &amp;lt;number-of-processes&amp;gt; $PWD/mpi-test-linux&lt;br /&gt;
$ qsub --kernel &amp;lt;profile-name&amp;gt; -t &amp;lt;time&amp;gt; -n &amp;lt;number-of-processes&amp;gt;  $PWD/mpi-test-linux&lt;br /&gt;
$ mpirun -verbose 1 -partition &amp;lt;partition-name&amp;gt; -np &amp;lt;number-of-processes&amp;gt; -timeout &amp;lt;time&amp;gt; \&lt;br /&gt;
-cwd $PWD -exe $PWD/omp-test-linux&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
For the OpenMP test, we pass the number of OpenMP threads to use in the &amp;lt;tt&amp;gt;OMP_NUM_THREADS&amp;lt;/tt&amp;gt; variable:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
$ cqsub -k &amp;lt;profile-name&amp;gt; -t &amp;lt;time&amp;gt; -n 1 -e OMP_NUM_THREADS=&amp;lt;num&amp;gt; $PWD/omp-test-linux&lt;br /&gt;
$ qsub --kernel &amp;lt;profile-name&amp;gt; -t &amp;lt;time&amp;gt; -n 1 --env OMP_NUM_THREADS=&amp;lt;num&amp;gt; $PWD/mpi-test-linux&lt;br /&gt;
$ mpirun -verbose 1 -partition &amp;lt;partition-name&amp;gt; -np 1 -timeout &amp;lt;time&amp;gt; \&lt;br /&gt;
-cwd $PWD -env OMP_NUM_THREADS=&amp;lt;num&amp;gt; -exe $PWD/omp-test-linux&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The MPI test benchmarks the performance of various MPI operations.  The OpenMP test is just a parallel &amp;quot;Hello world&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
'''Note:''' see the [[FAQ#Why large MPI processes do not work|FAQ]] if submitting larger MPI processes does not work properly.&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
[[Installation]] | [[ZeptoOS_Documentation|Top]] | [[MPICH, DCMF, and SPI]]&lt;/div&gt;</summary>
		<author><name>Iskra</name></author>
	</entry>
	<entry>
		<id> /zeptoos/index.php?title=Installation&amp;diff=593</id>
		<title>Installation</title>
		<link rel="alternate" type="text/html" href=" /zeptoos/index.php?title=Installation&amp;diff=593"/>
		<updated>2009-05-08T15:32:53Z</updated>

		<summary type="html">&lt;p&gt;Iskra: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;[[Configuration]] | [[ZeptoOS_Documentation|Top]] | [[Testing]]&lt;br /&gt;
----&lt;br /&gt;
&lt;br /&gt;
==Installing the support files==&lt;br /&gt;
&lt;br /&gt;
Installing ZeptoOS consists of two parts.  In the first part we install support files (header files, libraries, scripts, etc) used primarily when building compute node binaries for ZeptoOS.  To perform this step, change to the top-level directory and type:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
$ python install.py /path/to/install&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This will install the following files:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
Install Home:  /path/to/install&lt;br /&gt;
Creating install directories ...&lt;br /&gt;
Making /path/to/install/bin&lt;br /&gt;
Making /path/to/install/cnbin&lt;br /&gt;
Making /path/to/install/include&lt;br /&gt;
Making /path/to/install/lib&lt;br /&gt;
Making /path/to/install/lib/zoid&lt;br /&gt;
&lt;br /&gt;
Installing MPICH2 scripts ...&lt;br /&gt;
/path/to/install/bin/zmpicc&lt;br /&gt;
/path/to/install/bin/zmpicxx&lt;br /&gt;
/path/to/install/bin/zmpif77&lt;br /&gt;
/path/to/install/bin/zmpif90&lt;br /&gt;
/path/to/install/bin/zmpixlc&lt;br /&gt;
/path/to/install/bin/zmpixlc_r&lt;br /&gt;
/path/to/install/bin/zmpixlcxx&lt;br /&gt;
/path/to/install/bin/zmpixlcxx_r&lt;br /&gt;
/path/to/install/bin/zmpixlf2003&lt;br /&gt;
/path/to/install/bin/zmpixlf2003_r&lt;br /&gt;
/path/to/install/bin/zmpixlf77&lt;br /&gt;
/path/to/install/bin/zmpixlf77_r&lt;br /&gt;
/path/to/install/bin/zmpixlf90&lt;br /&gt;
/path/to/install/bin/zmpixlf90_r&lt;br /&gt;
/path/to/install/bin/zmpixlf95&lt;br /&gt;
/path/to/install/bin/zmpixlf95_r&lt;br /&gt;
&lt;br /&gt;
Installing Compute Node binaries ...&lt;br /&gt;
/path/to/install/cnbin/cn-ipfwd.sh&lt;br /&gt;
/path/to/install/cnbin/cn-ipfwd&lt;br /&gt;
&lt;br /&gt;
Installing misc files ...&lt;br /&gt;
/path/to/install/bin/zelftool&lt;br /&gt;
/path/to/install/bin/zkparam.py&lt;br /&gt;
&lt;br /&gt;
Installing MPICH2 headers ...&lt;br /&gt;
/path/to/install/include/mpe_thread.h&lt;br /&gt;
/path/to/install/include/mpi.h&lt;br /&gt;
/path/to/install/include/mpi.mod&lt;br /&gt;
/path/to/install/include/mpi_base.mod&lt;br /&gt;
/path/to/install/include/mpi_constants.mod&lt;br /&gt;
/path/to/install/include/mpi_sizeofs.mod&lt;br /&gt;
/path/to/install/include/mpicxx.h&lt;br /&gt;
/path/to/install/include/mpif.h&lt;br /&gt;
/path/to/install/include/mpio.h&lt;br /&gt;
/path/to/install/include/mpiof.h&lt;br /&gt;
/path/to/install/include/mpix.h&lt;br /&gt;
&lt;br /&gt;
Installing MPICH2 libraries ...&lt;br /&gt;
/path/to/install/lib/libcxxmpich.zcl.a&lt;br /&gt;
/path/to/install/lib/libfmpich.zcl.a&lt;br /&gt;
/path/to/install/lib/libfmpich_.zcl.a&lt;br /&gt;
/path/to/install/lib/libmpich.zcl.a&lt;br /&gt;
/path/to/install/lib/libmpich.zclf90.a&lt;br /&gt;
&lt;br /&gt;
Installing SPI libraries ...&lt;br /&gt;
/path/to/install/lib/libSPI.zcl.a&lt;br /&gt;
/path/to/install/lib/libzcl.a&lt;br /&gt;
&lt;br /&gt;
Installing ZOID files ...&lt;br /&gt;
/path/to/install/lib/libzoid_cn.a&lt;br /&gt;
/path/to/install/lib/zoid/libc.a&lt;br /&gt;
/path/to/install/lib/zoid/libpthread.a&lt;br /&gt;
&lt;br /&gt;
Installing DCMF files ...&lt;br /&gt;
/path/to/install/include/dcmf.h&lt;br /&gt;
/path/to/install/include/dcmf_collectives.h&lt;br /&gt;
/path/to/install/include/dcmf_coremath.h&lt;br /&gt;
/path/to/install/include/dcmf_globalcollectives.h&lt;br /&gt;
/path/to/install/include/dcmf_multisend.h&lt;br /&gt;
/path/to/install/include/dcmf_optimath.h&lt;br /&gt;
/path/to/install/lib/libdcmf.zcl.a&lt;br /&gt;
/path/to/install/lib/libdcmfcoll.zcl.a&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Setting up a kernel profile==&lt;br /&gt;
&lt;br /&gt;
The second part of the ZeptoOS installation is the process of setting up a ZeptoOS kernel profile.&lt;br /&gt;
&lt;br /&gt;
Blue Gene systems are partitionable, meaning that the hardware can be split into multiple, largely independent, sub-units.  More importantly, the system supports using different software stacks (what we call ''kernel profiles'') on different partitions at the same time.  For our immediate purposes, this means that one can safely experiment with ZeptoOS on one partition while other users are running production jobs using the default light-weight kernel on the rest of the machine.&lt;br /&gt;
&lt;br /&gt;
A kernel profile consists of the following elements:&lt;br /&gt;
&lt;br /&gt;
; loader&lt;br /&gt;
: A proprietary low-level bootstrap code, loaded onto all compute and I/O nodes.&lt;br /&gt;
; CN image list&lt;br /&gt;
: A series of images loaded onto each compute node.&lt;br /&gt;
; ION image list&lt;br /&gt;
: A series of images loaded onto each I/O node.&lt;br /&gt;
&lt;br /&gt;
All the images are loaded onto the machine from the service node via the service (JTAG) network.  The loader is loaded first, followed by the CN- and ION-specific images loaded in order.&lt;br /&gt;
&lt;br /&gt;
The CN image list defaults to the CNS followed by the CNK.  The ION image list defaults to the CNS, followed by the Linux kernel, followed by the Linux ramdisk.  CNS stands for Common Node Services &amp;amp;#8211; it is a proprietary &amp;quot;firmware&amp;quot; which negotiates between the hardware and the kernel.&lt;br /&gt;
&lt;br /&gt;
To enable ZeptoOS, we need to boot the ZeptoOS CN kernel and ramdisk and the Zepto ION kernel and ramdisk in a partition that we want to use.  The loader and the CNS are closed-source components, so ZeptoOS uses the same images for them as the default kernel profile.&lt;br /&gt;
&lt;br /&gt;
In the remainder of this section we discuss how to assign and boot ZeptoOS-specific images.&lt;br /&gt;
&lt;br /&gt;
===System using Cobalt===&lt;br /&gt;
 &lt;br /&gt;
If the BGP system in question has the [http://trac.mcs.anl.gov/projects/cobalt/ Cobalt] scheduler installed and its kernel profile feature has been configured properly, then using ZeptoOS should be easy.  All that is necessary is to make a subdirectory in the kernel profile directory and to create a couple of symbolic links that point to ZeptoOS images.&lt;br /&gt;
&lt;br /&gt;
On Argonne BGP machines, &amp;lt;tt&amp;gt;/bgsys/argonne-utils/profiles/&amp;lt;/tt&amp;gt; is the top-level kernel profile directory; individual profiles are stored in its subdirectories.  Assuming that the ZeptoOS images have already been created (see [[Configuration]]), and that one has write permissions to the kernel profile directory, here are the steps to create a new kernel profile:&lt;br /&gt;
 &lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
$ cd &amp;lt;kernel_profile_dir&amp;gt;&lt;br /&gt;
$ mkdir &amp;lt;your_profile&amp;gt; &amp;amp;&amp;amp; cd &amp;lt;your_profile&amp;gt;&lt;br /&gt;
$ ln -s &amp;lt;zepto_dir&amp;gt;/BGP-CN-zImage-with-initrd.elf CNK&lt;br /&gt;
$ ln -s &amp;lt;zepto_dir&amp;gt;/BGP-ION-zImage.elf INK&lt;br /&gt;
$ ln -s &amp;lt;zepto_dir&amp;gt;/BGP-ION-ramdisk-for-CNL.elf ramdisk&lt;br /&gt;
$ ln -s ../default/CNS&lt;br /&gt;
$ ln -s ../default/uloader&lt;br /&gt;
&amp;lt;/pre&amp;gt; &lt;br /&gt;
&lt;br /&gt;
'''Note:''' ensure that the ZeptoOS images are world-readable from the service node, otherwise jobs will fail to start.  If needed, copy the images to the kernel profile rather than link to them.&lt;br /&gt;
&lt;br /&gt;
For Argonne users, we provide a convenience script &amp;lt;tt&amp;gt;mkprofile-ANL.sh&amp;lt;/tt&amp;gt; with some extra features. The following command line is equivalent to the above steps:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
$ cd &amp;lt;zepto_dir&amp;gt; &amp;amp;&amp;amp; ./mkprofile-ANL.sh --profile=&amp;lt;your_profile&amp;gt;&lt;br /&gt;
&amp;lt;/pre&amp;gt; &lt;br /&gt;
 &lt;br /&gt;
Invoking the script with the &amp;lt;tt&amp;gt;-h&amp;lt;/tt&amp;gt; option prints an overview of command line options. In particular, use &amp;lt;tt&amp;gt;-c&amp;lt;/tt&amp;gt; if you prefer to copy images instead of making the links.&lt;br /&gt;
 &lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
$ ./mkprofile-ANL.sh -h&lt;br /&gt;
Usage: ./mkprofile-ANL.sh [OPTIONS]&lt;br /&gt;
&lt;br /&gt;
Options:&lt;br /&gt;
-h             : Show this message&lt;br /&gt;
-c             : Copy images instead of making symbolic link&lt;br /&gt;
-f             : Overwrite existing profile&lt;br /&gt;
--profile=name : Specify profile name&lt;br /&gt;
--cn=fn        : Compute Node Kernel Image&lt;br /&gt;
--ion=fn       : Specify I/O Node Kernel Image&lt;br /&gt;
--rd=fn        : Specify I/O Node Ramdisk Image&lt;br /&gt;
--ls           : show files in profile&lt;br /&gt;
--dryrun&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Once the ZeptoOS kernel profile is set up, it can be booted &lt;br /&gt;
by specifying the profile name when submitting a job using either &amp;lt;tt&amp;gt;cqsub&amp;lt;/tt&amp;gt; or &amp;lt;tt&amp;gt;qsub&amp;lt;/tt&amp;gt;:&lt;br /&gt;
 &lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
$ cqsub -k &amp;lt;profile_name&amp;gt; ...&lt;br /&gt;
$ qsub --kernel &amp;lt;profile_name&amp;gt; ...&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Testing and troubleshooting ZeptoOS is discussed in detail in the [[Testing|next section]].&lt;br /&gt;
&lt;br /&gt;
===Manual installation using the MMCS console===&lt;br /&gt;
&lt;br /&gt;
If the system does not use Cobalt, we will need to resort to using Blue Gene Midplane Management Control System (MMCS).  MMCS is a low-level control mechanism; administrator-level access permissions are required to use it.&lt;br /&gt;
&lt;br /&gt;
Before we begin, please select a partition to experiment on.  The partition should be unused; if some reservation system is in place, please reserve that partition (but do not boot it yet).&lt;br /&gt;
&lt;br /&gt;
====Assigning ZeptoOS images to the partition====&lt;br /&gt;
&lt;br /&gt;
Log on the service node and start the MMCS console:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
$ ssh &amp;lt;service_node&amp;gt;&lt;br /&gt;
sn $ mmcs_db_console&lt;br /&gt;
connecting to mmcs_server&lt;br /&gt;
connected to mmcs_server&lt;br /&gt;
connected to DB2&lt;br /&gt;
mmcs$&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
We begin by obtaining the current boot configuration of the partition, so that at the end we can revert it to the initial condition:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
mmcs$ getblockinfo &amp;lt;partition_name&amp;gt;&lt;br /&gt;
OK&lt;br /&gt;
boot info for block &amp;lt;partition_name&amp;gt;:&lt;br /&gt;
mloader: /bgsys/drivers/ppcfloor/boot/uloader&lt;br /&gt;
cnloadImg: /bgsys/drivers/ppcfloor/boot/cns,/bgsys/drivers/ppcfloor/boot/cnk&lt;br /&gt;
ioloadImg: /bgsys/drivers/ppcfloor/boot/cns,/bgsys/drivers/ppcfloor/boot/linux,/bgsys/drivers/ppcfloor/boot/ramdisk&lt;br /&gt;
status: F&lt;br /&gt;
mmcs$ &lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Now assign ZeptoOS images to the partition:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
mmcs$ setblockinfo &amp;lt;partition_name&amp;gt; /bgsys/drivers/ppcfloor/boot/uloader \&lt;br /&gt;
/bgsys/drivers/ppcfloor/boot/cns,&amp;lt;zepto_dir&amp;gt;/BGP-CN-zImage-with-initrd.elf \&lt;br /&gt;
/bgsys/drivers/ppcfloor/boot/cns,&amp;lt;zepto_dir&amp;gt;/BGP-ION-zImage.elf,&amp;lt;zepto_dir&amp;gt;/BGP-ION-ramdisk-for-CNL.elf&lt;br /&gt;
mmcs$ quit&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
====Booting ZeptoOS====&lt;br /&gt;
 &lt;br /&gt;
Once the partition has been correctly configured, the ZeptoOS images will be loaded when you run a job on that partition (via &amp;lt;tt&amp;gt;mpirun&amp;lt;/tt&amp;gt;, for example):&lt;br /&gt;
 &lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
$ mpirun -verbose 1 -partition &amp;lt;partition_name&amp;gt; -np 64 -timeout 600 -cwd $PWD -exe ./a.out&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Testing and troubleshooting ZeptoOS is discussed in detail in the [[Testing|next section]].&lt;br /&gt;
&lt;br /&gt;
====Restore the original configuration====&lt;br /&gt;
&lt;br /&gt;
'''Do not forget this step!'''&lt;br /&gt;
&lt;br /&gt;
Once the experiments are over, restore the partition to its original configuration:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
$ ssh &amp;lt;service_node&amp;gt;&lt;br /&gt;
sn $ mmcs_db_console&lt;br /&gt;
connecting to mmcs_server&lt;br /&gt;
connected to mmcs_server&lt;br /&gt;
connected to DB2&lt;br /&gt;
mmcs$ setblockinfo &amp;lt;partition_name&amp;gt; /bgsys/drivers/ppcfloor/boot/uloader \&lt;br /&gt;
/bgsys/drivers/ppcfloor/boot/cns,/bgsys/drivers/ppcfloor/boot/cnk \&lt;br /&gt;
/bgsys/drivers/ppcfloor/boot/cns,/bgsys/drivers/ppcfloor/boot/linux,/bgsys/drivers/ppcfloor/boot/ramdisk&lt;br /&gt;
mmcs$ quit&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
[[Configuration]] | [[ZeptoOS_Documentation|Top]] | [[Testing]]&lt;/div&gt;</summary>
		<author><name>Iskra</name></author>
	</entry>
	<entry>
		<id> /zeptoos/index.php?title=Configuration&amp;diff=592</id>
		<title>Configuration</title>
		<link rel="alternate" type="text/html" href=" /zeptoos/index.php?title=Configuration&amp;diff=592"/>
		<updated>2009-05-08T15:21:21Z</updated>

		<summary type="html">&lt;p&gt;Iskra: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;[[Introduction]] | [[ZeptoOS_Documentation|Top]] | [[Installation]]&lt;br /&gt;
----&lt;br /&gt;
&lt;br /&gt;
== Downloading ==&lt;br /&gt;
&lt;br /&gt;
* Log on one of the front end nodes of the Blue Gene (a login node or a service node).&lt;br /&gt;
&lt;br /&gt;
* Download the ZeptoOS tarball from the ZeptoOS [http://press.mcs.anl.gov/zeptoos/download download page].&lt;br /&gt;
&lt;br /&gt;
* Extract the sources from the package:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
$ tar xjf ZeptoOS-&amp;lt;version&amp;gt;.tar.bz2&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Configuring ==&lt;br /&gt;
&lt;br /&gt;
Change to the top-level &amp;lt;tt&amp;gt;ZeptoOS-&amp;lt;version&amp;gt;&amp;lt;/tt&amp;gt; directory:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
$ cd ZeptoOS-&amp;lt;version&amp;gt;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
A &amp;lt;tt&amp;gt;configure&amp;lt;/tt&amp;gt; script is provided to set the pathnames to various system directories:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
$ ./configure&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
If invoked without any arguments, it will use the defaults, which should be appropriate if ZeptoOS is configured on a system with a supported BG/P driver version.  The pathnames can be changed with the help of a textual user interface by invoking the script as follows:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
$ ./configure --edit&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This will display the following menu:&lt;br /&gt;
&lt;br /&gt;
[[Image:Configure1.png|border|Main menu]]&lt;br /&gt;
&lt;br /&gt;
Please select the top item (&amp;lt;tt&amp;gt;BG/P DIST_DIR&amp;lt;/tt&amp;gt;).  The screen will change to:&lt;br /&gt;
&lt;br /&gt;
[[Image:Configure2.png|border|DIST_DIR menu]]&lt;br /&gt;
&lt;br /&gt;
The following options are available:&lt;br /&gt;
&lt;br /&gt;
; DRV_DIR&lt;br /&gt;
: The directory with the BG/P driver tree.  The default (&amp;lt;tt&amp;gt;/bgsys/drivers/ppcfloor/&amp;lt;/tt&amp;gt;) is a link pointing to the currently active driver.&lt;br /&gt;
; BGP_CROSS&lt;br /&gt;
: A prefix to the pathnames of the GNU cross-compilers used to build the compute node and I/O node software.&lt;br /&gt;
; BGCNS_H_PATH and BGCNS_H&lt;br /&gt;
: The location of a file needed to rebuild the kernel (these options are temporary and will be removed in the next version).&lt;br /&gt;
; OS_DIR&lt;br /&gt;
: The directory with the supplementary I/O node software used when booting the I/O nodes.  It needs to be set to match the BG/P driver version being used.&lt;br /&gt;
&lt;br /&gt;
The second top-level menu (&amp;lt;tt&amp;gt;Debugging&amp;lt;/tt&amp;gt;) has only one option:&lt;br /&gt;
&lt;br /&gt;
; ADD_DEBUG_TOOLS&lt;br /&gt;
: Check this option to include &amp;lt;tt&amp;gt;gdb&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;strace&amp;lt;/tt&amp;gt; in the compute node ramdisk.  They are not included by default because of their size.&lt;br /&gt;
&lt;br /&gt;
The third top-level menu (&amp;lt;tt&amp;gt;Kernel Profiling&amp;lt;/tt&amp;gt;) is discussed in the [[(K)TAU#Configure ZeptoOS to point to KTAU patch and path|(K)TAU section]]&lt;br /&gt;
&lt;br /&gt;
Select &amp;lt;tt&amp;gt;Exit&amp;lt;/tt&amp;gt; (multiple times if needed) and confirm if you want to save any changes made.&lt;br /&gt;
&lt;br /&gt;
== Building ==&lt;br /&gt;
&lt;br /&gt;
To start using the pre-built binaries simply type:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
$ make&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
On the first invocation, this will ask for a root password to use on I/O nodes:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
Create root password for I/O Node&lt;br /&gt;
   Leave the password field empty if you want to disable root login&lt;br /&gt;
   New password:&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
'''Security note: root-level access to I/O nodes should only be given to trusted individuals.  A root user can access and modify files of all users in the system.'''&lt;br /&gt;
&lt;br /&gt;
Once the password has been entered and confirmed, &amp;lt;tt&amp;gt;make&amp;lt;/tt&amp;gt; will use pre-built kernel images, and will build the ramdisks from pre-built tools and utilities.  The following generated files will be placed in the top-level directory:&lt;br /&gt;
&lt;br /&gt;
; BGP-CN-zImage-with-initrd.elf&lt;br /&gt;
: ZeptoOS compute node Linux with embedded compute node ramdisk.&lt;br /&gt;
; BGP-ION-zImage.elf&lt;br /&gt;
: ZeptoOS I/O node kernel.&lt;br /&gt;
; BGP-ION-ramdisk-for-CNL.elf&lt;br /&gt;
: ZeptoOS I/O node ramdisk for use with the ZeptoOS compute node Linux.&lt;br /&gt;
; BGP-ION-ramdisk-for-CNK.elf&lt;br /&gt;
: ZeptoOS I/O node ramdisk for use with the IBM CNK (optional).&lt;br /&gt;
&lt;br /&gt;
It is possible to rebuild individual ZeptoOS components using one of the following &amp;lt;tt&amp;gt;make&amp;lt;/tt&amp;gt; targets (the list is also available by typing &amp;lt;tt&amp;gt;make help&amp;lt;/tt&amp;gt; or &amp;lt;tt&amp;gt;make menu&amp;lt;/tt&amp;gt;):&lt;br /&gt;
&lt;br /&gt;
; bgp-cn-linux&lt;br /&gt;
: Rebuilds the compute node ramdisk and embeds it into a compute node kernel image.&lt;br /&gt;
; bgp-ion-ramdisk-cnl&lt;br /&gt;
: Rebuilds the I/O node ramdisk for the ZeptoOS compute node Linux.&lt;br /&gt;
; bgp-ion-ramdisk-cnk&lt;br /&gt;
: Rebuilds the I/O node ramdisk for the IBM CNK.&lt;br /&gt;
; bgp-ion-linux-build&lt;br /&gt;
: Rebuilds the I/O node kernel.&lt;br /&gt;
; bgp-cn-linux-build&lt;br /&gt;
: Rebuilds the compute node kernel and ramdisk and embeds the ramdisk into the kernel.&lt;br /&gt;
; bgp-all-pkg-rebuild&lt;br /&gt;
: Rebuilds all packages from sources.&lt;br /&gt;
(the following &amp;lt;tt&amp;gt;make&amp;lt;/tt&amp;gt; targets are mostly for internal use)&lt;br /&gt;
; bgp-ion-linux&lt;br /&gt;
: Copies a recently rebuilt I/O node kernel if one is available; otherwise, uses a prebuilt binary (will not rebuild the kernel).&lt;br /&gt;
; bgp-all-pkg-smart&lt;br /&gt;
: Copies recently rebuilt packages if available; otherwise, uses prebuilt binaries (used when preparing to rebuild ramdisks).&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
[[Introduction]] | [[ZeptoOS_Documentation|Top]] | [[Installation]]&lt;/div&gt;</summary>
		<author><name>Iskra</name></author>
	</entry>
	<entry>
		<id> /zeptoos/index.php?title=Changes&amp;diff=589</id>
		<title>Changes</title>
		<link rel="alternate" type="text/html" href=" /zeptoos/index.php?title=Changes&amp;diff=589"/>
		<updated>2009-05-08T15:03:29Z</updated>

		<summary type="html">&lt;p&gt;Iskra: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;[[ZeptoOS_Documentation|Top]]&lt;br /&gt;
----&lt;br /&gt;
&lt;br /&gt;
'''ZeptoOS-BGP 2.0''' released May XX, 2009.&amp;lt;br/&amp;gt;&lt;br /&gt;
Most important changes:&lt;br /&gt;
&lt;br /&gt;
* first public release with support for Blue Gene/P&lt;br /&gt;
* ZeptoOS Compute Node Kernel with:&lt;br /&gt;
** Big Memory&lt;br /&gt;
** Native communication support&lt;br /&gt;
** IP forwarding&lt;br /&gt;
* ZOID enabled by default&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
'''ZeptoOS-BG 1.5''' released June 28, 2007.&amp;lt;br/&amp;gt;&lt;br /&gt;
Most important changes:&lt;br /&gt;
&lt;br /&gt;
* tested on V1R3M2 driver, should work with V1R3M0 and V1R3M1 as well&lt;br /&gt;
* support for ZOID&lt;br /&gt;
* ION kernel with experimental support for compute class processes and static TLB&lt;br /&gt;
* PVFS2 updated to version 2.6.3 &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
'''ZeptoOS-BG 1.4''' released January 31, 2006.&amp;lt;br/&amp;gt;&lt;br /&gt;
Most important changes:&lt;br /&gt;
&lt;br /&gt;
* tested on V1R2M1 driver and may work with V1R2M0&lt;br /&gt;
* 2.6 ION kernel (based on 2.6.5)&lt;br /&gt;
* pvfs2 binary and rc script update&lt;br /&gt;
* boot msg clean up&lt;br /&gt;
* ZeptoInstall.sh fixes&lt;br /&gt;
* misc. such as fixing /tmp perms &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
'''ZeptoOS-BG 1.2''' released November 11, 2005.&amp;lt;br/&amp;gt;&lt;br /&gt;
Most important changes:&lt;br /&gt;
&lt;br /&gt;
* Integrated support for KTAU, a kernel profiling/tracing tool.&lt;br /&gt;
* Support for custom /bgl/dist-type directory trees. Eliminates a need to put ZeptoOS-specific stuff inside a directory shared with standard IBM profile.&lt;br /&gt;
* An installation script is now available, to ease the installation process.&lt;br /&gt;
* Added zswitcher, a command to switch kernel/ramdisk of a partition.&lt;br /&gt;
* Added zdiff-elfrd, a command to compare two ramdisks.&lt;br /&gt;
* Improved zinfo: more robust, more secure, easier to set up.&lt;br /&gt;
* CIOD read/write buffer size can now be calculated automatically, taking into account available memory, compute to I/O node ratio, etc.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
'''ZeptoOS-BG 1.1''' released September 6, 2005.&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
[[ZeptoOS_Documentation|Top]]&lt;/div&gt;</summary>
		<author><name>Iskra</name></author>
	</entry>
	<entry>
		<id> /zeptoos/index.php?title=Requirements&amp;diff=587</id>
		<title>Requirements</title>
		<link rel="alternate" type="text/html" href=" /zeptoos/index.php?title=Requirements&amp;diff=587"/>
		<updated>2009-05-08T14:58:29Z</updated>

		<summary type="html">&lt;p&gt;Iskra: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;[[ZeptoOS_Documentation|Top]]&lt;br /&gt;
----&lt;br /&gt;
&lt;br /&gt;
* Blue Gene/P system with the V1R3 driver installed &lt;br /&gt;
* Blue Gene/P PowerPC Front End Node &lt;br /&gt;
* The ability to create a kernel profile&lt;br /&gt;
** If the system has the Cobalt scheduler installed and its kernel profile feature is available, you need write permissions to the profile directory.&lt;br /&gt;
** If no Cobalt kernel profile feature is available, you need access permission to the service node and the MMCS console.&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
[[ZeptoOS_Documentation|Top]]&lt;/div&gt;</summary>
		<author><name>Iskra</name></author>
	</entry>
	<entry>
		<id> /zeptoos/index.php?title=Feature_List&amp;diff=586</id>
		<title>Feature List</title>
		<link rel="alternate" type="text/html" href=" /zeptoos/index.php?title=Feature_List&amp;diff=586"/>
		<updated>2009-05-08T14:57:27Z</updated>

		<summary type="html">&lt;p&gt;Iskra: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;[[ZeptoOS_Documentation|Top]]&lt;br /&gt;
----&lt;br /&gt;
&lt;br /&gt;
; ZeptoOS Compute Node Linux&lt;br /&gt;
: Optimized kernel based on Linux 2.6.19 runs on the compute nodes of Blue Gene/P, with a slim ramdisk less than 1/3 of the size of the default I/O-node one.&lt;br /&gt;
&lt;br /&gt;
; ZeptoOS-enhanced I/O node Linux&lt;br /&gt;
: Our I/O node kernel and ramdisk are based on the standard V1R3M0 release, but feature a number of ZeptoOS-specific improvements.&lt;br /&gt;
&lt;br /&gt;
; Run arbitrary processes on the compute nodes&lt;br /&gt;
: Shell scripts, Java VM, unrestricted pthreads, etc.&lt;br /&gt;
&lt;br /&gt;
; Big Memory support&lt;br /&gt;
: Zepto Compute Binaries run in Big Memory, a flat memory area covered by huge, semi-static TLB entries, resulting in a run-time performance comparable to that of a light-weight kernel.&lt;br /&gt;
&lt;br /&gt;
; Native communication support&lt;br /&gt;
: The DMA driver, as well as standard BG/P communication libraries such as MPICH2 and the lower-level DCMF and SPI have been ported to the ZeptoOS Compute Node Linux, providing the applications with communication performance matching that of the light-weight kernel.  Currently only the SMP mode is supported.&lt;br /&gt;
&lt;br /&gt;
; ZOID&lt;br /&gt;
: ZeptoOS I/O Daemon performs job control and enables communication (remote file I/O, etc) between the compute nodes and the I/O nodes.  ZOID can be easily extended through plug-ins to perform the forwarding of custom APIs.&lt;br /&gt;
&lt;br /&gt;
; Log into your I/O nodes&lt;br /&gt;
: SSH daemon is enabled by default and is configured to allow the partition owner to log on the I/O nodes while the job is running.&lt;br /&gt;
&lt;br /&gt;
; Log into your compute nodes&lt;br /&gt;
: Once logged on an I/O node, a user can open an interactive session to a compute node using &amp;lt;tt&amp;gt;telnet&amp;lt;/tt&amp;gt; in order to, e.g., attach &amp;lt;tt&amp;gt;gdb&amp;lt;/tt&amp;gt; to an application process running there.  This is made possible using IP packet forwarding over the tree network, performed by ZOID.&lt;br /&gt;
&lt;br /&gt;
; PVFS support&lt;br /&gt;
: Pre-built binaries of PVFS client code version 2.8.1, including the I/O node kernel module, are included in the ZeptoOS tarball for your convenience.&lt;br /&gt;
&lt;br /&gt;
; ALL source code&lt;br /&gt;
: The ZeptoOS tarball includes ''all'' the source code: kernels, ramdisks, communication libraries, I/O forwarding, support libraries, tools and utilities, etc, along with all the support scripts and Makefiles needed to build binaries out of them.  Pre-built binaries are also included for your convenience.&lt;br /&gt;
&lt;br /&gt;
; Safe to use alongside IBM CNK&lt;br /&gt;
: Thanks to the way that Blue Gene machines are designed, ZeptoOS can easily and safely be used alongside the IBM CNK.  Depending on the software configuration, the kernel to use can be specified on a per-partition, or even per-job, basis.&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
[[ZeptoOS_Documentation|Top]]&lt;/div&gt;</summary>
		<author><name>Iskra</name></author>
	</entry>
	<entry>
		<id> /zeptoos/index.php?title=Installation&amp;diff=585</id>
		<title>Installation</title>
		<link rel="alternate" type="text/html" href=" /zeptoos/index.php?title=Installation&amp;diff=585"/>
		<updated>2009-05-07T23:02:35Z</updated>

		<summary type="html">&lt;p&gt;Iskra: /* Installing the support files */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;[[Configuration]] | [[ZeptoOS_Documentation|Top]] | [[Testing]]&lt;br /&gt;
----&lt;br /&gt;
&lt;br /&gt;
==Installing the support files==&lt;br /&gt;
&lt;br /&gt;
Installing ZeptoOS consists of two parts.  In the first part we install support files (header files, libraries, scripts, etc) use primarily when building compute node binaries for ZeptoOS.  To perform this step, change to the top-level directory and type:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
$ python install.py /path/to/install&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This will install the following files:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
Install Home:  /path/to/install&lt;br /&gt;
Creating install directories ...&lt;br /&gt;
Making /path/to/install/bin&lt;br /&gt;
Making /path/to/install/cnbin&lt;br /&gt;
Making /path/to/install/include&lt;br /&gt;
Making /path/to/install/lib&lt;br /&gt;
Making /path/to/install/lib/zoid&lt;br /&gt;
&lt;br /&gt;
Installing MPICH2 scripts ...&lt;br /&gt;
/path/to/install/bin/zmpicc&lt;br /&gt;
/path/to/install/bin/zmpicxx&lt;br /&gt;
/path/to/install/bin/zmpif77&lt;br /&gt;
/path/to/install/bin/zmpif90&lt;br /&gt;
/path/to/install/bin/zmpixlc&lt;br /&gt;
/path/to/install/bin/zmpixlc_r&lt;br /&gt;
/path/to/install/bin/zmpixlcxx&lt;br /&gt;
/path/to/install/bin/zmpixlcxx_r&lt;br /&gt;
/path/to/install/bin/zmpixlf2003&lt;br /&gt;
/path/to/install/bin/zmpixlf2003_r&lt;br /&gt;
/path/to/install/bin/zmpixlf77&lt;br /&gt;
/path/to/install/bin/zmpixlf77_r&lt;br /&gt;
/path/to/install/bin/zmpixlf90&lt;br /&gt;
/path/to/install/bin/zmpixlf90_r&lt;br /&gt;
/path/to/install/bin/zmpixlf95&lt;br /&gt;
/path/to/install/bin/zmpixlf95_r&lt;br /&gt;
&lt;br /&gt;
Installing Compute Node binaries ...&lt;br /&gt;
/path/to/install/cnbin/cn-ipfwd.sh&lt;br /&gt;
/path/to/install/cnbin/cn-ipfwd&lt;br /&gt;
&lt;br /&gt;
Installing misc files ...&lt;br /&gt;
/path/to/install/bin/zelftool&lt;br /&gt;
/path/to/install/bin/zkparam.py&lt;br /&gt;
&lt;br /&gt;
Installing MPICH2 headers ...&lt;br /&gt;
/path/to/install/include/mpe_thread.h&lt;br /&gt;
/path/to/install/include/mpi.h&lt;br /&gt;
/path/to/install/include/mpi.mod&lt;br /&gt;
/path/to/install/include/mpi_base.mod&lt;br /&gt;
/path/to/install/include/mpi_constants.mod&lt;br /&gt;
/path/to/install/include/mpi_sizeofs.mod&lt;br /&gt;
/path/to/install/include/mpicxx.h&lt;br /&gt;
/path/to/install/include/mpif.h&lt;br /&gt;
/path/to/install/include/mpio.h&lt;br /&gt;
/path/to/install/include/mpiof.h&lt;br /&gt;
/path/to/install/include/mpix.h&lt;br /&gt;
&lt;br /&gt;
Installing MPICH2 libraries ...&lt;br /&gt;
/path/to/install/lib/libcxxmpich.zcl.a&lt;br /&gt;
/path/to/install/lib/libfmpich.zcl.a&lt;br /&gt;
/path/to/install/lib/libfmpich_.zcl.a&lt;br /&gt;
/path/to/install/lib/libmpich.zcl.a&lt;br /&gt;
/path/to/install/lib/libmpich.zclf90.a&lt;br /&gt;
&lt;br /&gt;
Installing SPI libraries ...&lt;br /&gt;
/path/to/install/lib/libSPI.zcl.a&lt;br /&gt;
/path/to/install/lib/libzcl.a&lt;br /&gt;
&lt;br /&gt;
Installing ZOID files ...&lt;br /&gt;
/path/to/install/lib/libzoid_cn.a&lt;br /&gt;
/path/to/install/lib/zoid/libc.a&lt;br /&gt;
/path/to/install/lib/zoid/libpthread.a&lt;br /&gt;
&lt;br /&gt;
Installing DCMF files ...&lt;br /&gt;
/path/to/install/include/dcmf.h&lt;br /&gt;
/path/to/install/include/dcmf_collectives.h&lt;br /&gt;
/path/to/install/include/dcmf_coremath.h&lt;br /&gt;
/path/to/install/include/dcmf_globalcollectives.h&lt;br /&gt;
/path/to/install/include/dcmf_multisend.h&lt;br /&gt;
/path/to/install/include/dcmf_optimath.h&lt;br /&gt;
/path/to/install/lib/libdcmf.zcl.a&lt;br /&gt;
/path/to/install/lib/libdcmfcoll.zcl.a&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Setting up a kernel profile==&lt;br /&gt;
&lt;br /&gt;
The second part of the ZeptoOS installation is the process of setting up a ZeptoOS kernel profile.&lt;br /&gt;
&lt;br /&gt;
Blue Gene systems are partitionable, meaning that the hardware can be split into multiple, largely independent, sub-units.  More importantly, the system supports using different software stacks (what we call ''kernel profiles'') on different partitions at the same time.  This means that one can safely experiment with ZeptoOS on one partition while other users are running production jobs using the default light-weight kernel on the rest of the machine.&lt;br /&gt;
&lt;br /&gt;
A kernel profile consists of the following elements:&lt;br /&gt;
&lt;br /&gt;
; loader&lt;br /&gt;
: A proprietary low-level bootstrap code, loaded onto all compute and I/O nodes.&lt;br /&gt;
; CN image list&lt;br /&gt;
: A series of images loaded onto each compute node.&lt;br /&gt;
; ION image list&lt;br /&gt;
: A series of images loaded onto each I/O node.&lt;br /&gt;
&lt;br /&gt;
All the images are loaded onto the machine from the service node via the service (JTAG) network.  The loader is loaded first, followed by the CN- and ION-specific images loaded in order.&lt;br /&gt;
&lt;br /&gt;
The CN image list defaults to CNS followed by the CNK.  The ION image list defaults to CNS, followed by the Linux kernel, followed by the Linux ramdisk.  CNS stands for Common Node Services &amp;amp;#8211; it is a proprietary &amp;quot;firmware&amp;quot; which negotiates between the hardware and the kernel.&lt;br /&gt;
&lt;br /&gt;
To enable ZeptoOS, we need to boot the Zepto CN kernel and ramdisk and the Zepto ION kernel and ramdisk in a partition that we want to use.  The loader and the CNS are closed-source components, so ZeptoOS uses the same images for them as the default kernel profile.&lt;br /&gt;
&lt;br /&gt;
In the remainder of this section we discuss how to assign and boot ZeptoOS-specific images.&lt;br /&gt;
&lt;br /&gt;
===System using Cobalt===&lt;br /&gt;
 &lt;br /&gt;
If the BGP system in question has the [http://trac.mcs.anl.gov/projects/cobalt/ Cobalt] scheduler installed and its kernel profile feature has been configured properly, then using ZeptoOS there should be easy.  All that is necessary is to make a subdirectory in the kernel profile directory and to create a couple of symbolic links that point to ZeptoOS images.&lt;br /&gt;
&lt;br /&gt;
On Argonne BGP machines, &amp;lt;tt&amp;gt;/bgsys/argonne-utils/profiles/&amp;lt;/tt&amp;gt; is the top-level kernel profile directory; individual profiles are stored in its subdirectories.  Assuming that the ZeptoOS images have already been created (see [[Configuration]]), and that one has write permissions to the kernel profile directory, here are the steps to create a new kernel profile:&lt;br /&gt;
 &lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
$ cd &amp;lt;kernel_profile_dir&amp;gt;&lt;br /&gt;
$ mkdir &amp;lt;your_profile&amp;gt; &amp;amp;&amp;amp; cd &amp;lt;your_profile&amp;gt;&lt;br /&gt;
$ ln -s &amp;lt;zepto_dir&amp;gt;/BGP-CN-zImage-with-initrd.elf CNK&lt;br /&gt;
$ ln -s &amp;lt;zepto_dir&amp;gt;/BGP-ION-zImage.elf INK&lt;br /&gt;
$ ln -s &amp;lt;zepto_dir&amp;gt;/BGP-ION-ramdisk-for-CNL.elf ramdisk&lt;br /&gt;
$ ln -s ../default/CNS&lt;br /&gt;
$ ln -s ../default/uloader&lt;br /&gt;
&amp;lt;/pre&amp;gt; &lt;br /&gt;
&lt;br /&gt;
'''Note:''' ensure that the ZeptoOS images are world-readable, otherwise jobs will fail to start.  If needed, copy the images to the kernel profile rather than link to them.&lt;br /&gt;
&lt;br /&gt;
For Argonne users, we provide a convenience script &amp;lt;tt&amp;gt;mkprofile-ANL.sh&amp;lt;/tt&amp;gt; with some extra features. The following command line is equivalent to the above steps:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
$ cd &amp;lt;zepto_dir&amp;gt; &amp;amp;&amp;amp; ./mkprofile-ANL.sh --profile=&amp;lt;your_profile&amp;gt;&lt;br /&gt;
&amp;lt;/pre&amp;gt; &lt;br /&gt;
 &lt;br /&gt;
Invoking it with the &amp;lt;tt&amp;gt;-h&amp;lt;/tt&amp;gt; option prints an overview of command line options. In particular, use &amp;lt;tt&amp;gt;-c&amp;lt;/tt&amp;gt; if you prefer to copy images instead of making the links.&lt;br /&gt;
 &lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
$ ./mkprofile-ANL.sh -h&lt;br /&gt;
Usage: ./mkprofile-ANL.sh [OPTIONS]&lt;br /&gt;
&lt;br /&gt;
Options:&lt;br /&gt;
-h             : Show this message&lt;br /&gt;
-c             : Copy images instead of making symbolic link&lt;br /&gt;
-f             : Overwrite existing profile&lt;br /&gt;
--profile=name : Specify profile name&lt;br /&gt;
--cn=fn        : Compute Node Kernel Image&lt;br /&gt;
--ion=fn       : Specify I/O Node Kernel Image&lt;br /&gt;
--rd=fn        : Specify I/O Node Ramdisk Image&lt;br /&gt;
--ls           : show files in profile&lt;br /&gt;
--dryrun&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Once the ZeptoOS kernel profile is set up, it can be booted &lt;br /&gt;
by specifying the profile name when submitting a job using either &amp;lt;tt&amp;gt;cqsub&amp;lt;/tt&amp;gt; or &amp;lt;tt&amp;gt;qsub&amp;lt;/tt&amp;gt;:&lt;br /&gt;
 &lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
$ cqsub -k &amp;lt;profile_name&amp;gt; ...&lt;br /&gt;
$ qsub --kernel &amp;lt;profile_name&amp;gt; ...&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Testing and troubleshooting ZeptoOS is discussed in detail in the [[Testing|next section]].&lt;br /&gt;
&lt;br /&gt;
===Manual installation using the MMCS console===&lt;br /&gt;
&lt;br /&gt;
If the system does not use Cobalt, we will need to resort to using Blue Gene Midplane Management Control System (MMCS).  MMCS is a low-level control mechanism; administrator-level access permissions are required to use it.&lt;br /&gt;
&lt;br /&gt;
Before we begin, please select a partition that we can experiment on.  The partition should be unused; if some reservation system is in place, please reserve that partition (but do not boot it yet).&lt;br /&gt;
&lt;br /&gt;
====Assigning ZeptoOS images to the partition====&lt;br /&gt;
&lt;br /&gt;
Log on the service node and start the MMCS console:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
$ ssh &amp;lt;service_node&amp;gt;&lt;br /&gt;
sn $ mmcs_db_console&lt;br /&gt;
connecting to mmcs_server&lt;br /&gt;
connected to mmcs_server&lt;br /&gt;
connected to DB2&lt;br /&gt;
mmcs$&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
We begin by obtaining the current configuration of a partition, so that at the end we can revert it to the initial condition:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
mmcs$ getblockinfo &amp;lt;partition_name&amp;gt;&lt;br /&gt;
OK&lt;br /&gt;
boot info for block &amp;lt;partition_name&amp;gt;:&lt;br /&gt;
mloader: /bgsys/drivers/ppcfloor/boot/uloader&lt;br /&gt;
cnloadImg: /bgsys/drivers/ppcfloor/boot/cns,/bgsys/drivers/ppcfloor/boot/cnk&lt;br /&gt;
ioloadImg: /bgsys/drivers/ppcfloor/boot/cns,/bgsys/drivers/ppcfloor/boot/linux,/bgsys/drivers/ppcfloor/boot/ramdisk&lt;br /&gt;
status: F&lt;br /&gt;
mmcs$ &lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Now assign ZeptoOS images to the partition:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
mmcs$ setblockinfo &amp;lt;partition_name&amp;gt; /bgsys/drivers/ppcfloor/boot/uloader \&lt;br /&gt;
/bgsys/drivers/ppcfloor/boot/cns,&amp;lt;zepto_dir&amp;gt;/BGP-CN-zImage-with-initrd.elf \&lt;br /&gt;
/bgsys/drivers/ppcfloor/boot/cns,&amp;lt;zepto_dir&amp;gt;/BGP-ION-zImage.elf,&amp;lt;zepto_dir&amp;gt;/BGP-ION-ramdisk-for-CNL.elf&lt;br /&gt;
mmcs$ quit&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
====Booting ZeptoOS====&lt;br /&gt;
 &lt;br /&gt;
Once you have correctly configured a partition, the ZeptoOS images will be loaded when you run a job on that partition (via &amp;lt;tt&amp;gt;mpirun&amp;lt;/tt&amp;gt;, for example):&lt;br /&gt;
 &lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
$ mpirun -verbose 1 -partition &amp;lt;partition_name&amp;gt; -np 64 -timeout 600 -cwd $PWD -exe ./a.out&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Testing and troubleshooting ZeptoOS is discussed in detail in the [[Testing|next section]].&lt;br /&gt;
&lt;br /&gt;
====Restore the original configuration====&lt;br /&gt;
&lt;br /&gt;
'''Do not forget this step!'''&lt;br /&gt;
&lt;br /&gt;
After you are finished using ZeptoOS, you need to restore the partition to its original configuration:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
$ ssh &amp;lt;service_node&amp;gt;&lt;br /&gt;
sn $ mmcs_db_console&lt;br /&gt;
connecting to mmcs_server&lt;br /&gt;
connected to mmcs_server&lt;br /&gt;
connected to DB2&lt;br /&gt;
mmcs$ setblockinfo &amp;lt;partition_name&amp;gt; /bgsys/drivers/ppcfloor/boot/uloader \&lt;br /&gt;
/bgsys/drivers/ppcfloor/boot/cns,/bgsys/drivers/ppcfloor/boot/cnk \&lt;br /&gt;
/bgsys/drivers/ppcfloor/boot/cns,/bgsys/drivers/ppcfloor/boot/linux,/bgsys/drivers/ppcfloor/boot/ramdisk&lt;br /&gt;
mmcs$ quit&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
[[Configuration]] | [[ZeptoOS_Documentation|Top]] | [[Testing]]&lt;/div&gt;</summary>
		<author><name>Iskra</name></author>
	</entry>
	<entry>
		<id> /zeptoos/index.php?title=FAQ&amp;diff=581</id>
		<title>FAQ</title>
		<link rel="alternate" type="text/html" href=" /zeptoos/index.php?title=FAQ&amp;diff=581"/>
		<updated>2009-05-07T21:21:52Z</updated>

		<summary type="html">&lt;p&gt;Iskra: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;[[ZeptoOS_Documentation|Top]]&lt;br /&gt;
----&lt;br /&gt;
&lt;br /&gt;
==How to obtain a CN node number==&lt;br /&gt;
&lt;br /&gt;
This depends on what number one is interested in.&lt;br /&gt;
&lt;br /&gt;
===Pset rank===&lt;br /&gt;
&lt;br /&gt;
A pset rank is a number identifying a compute node within each ''pset'' (an I/O node and the compute nodes that communicate with it).  Note that on partitions larger than one pset, the pset ranks will not be unique.  Also, pset ranks do ''not'' start from &amp;lt;tt&amp;gt;0&amp;lt;/tt&amp;gt;; they start from &amp;lt;tt&amp;gt;1&amp;lt;/tt&amp;gt; for some mysterious reason (do not blame us &amp;amp;#8211; blame IBM&amp;amp;nbsp;:-).&lt;br /&gt;
&lt;br /&gt;
Pset rank is used as the last octet in the IP address on the tree network connecting the compute nodes and the I/O nodes (''x'' in &amp;lt;tt&amp;gt;192.168.1.&amp;lt;/tt&amp;gt;''x'').&lt;br /&gt;
&lt;br /&gt;
The pset rank is available on the compute nodes from &amp;lt;tt&amp;gt;/proc/personality.sh&amp;lt;/tt&amp;gt;, in the &amp;lt;tt&amp;gt;BG_RANK_IN_PSET&amp;lt;/tt&amp;gt; variable:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
#!/bin/sh&lt;br /&gt;
&lt;br /&gt;
. /proc/personality.sh&lt;br /&gt;
&lt;br /&gt;
echo &amp;quot;My pset rank is $BG_RANK_IN_PSET&amp;quot;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
From a C program it will be easier to use the binary personality available from &amp;lt;tt&amp;gt;/proc/personality&amp;lt;/tt&amp;gt;.  The definition of the structure can be found in &amp;lt;tt&amp;gt;/bgsys/drivers/ppcfloor/arch/include/common/bgp_personality.h&amp;lt;/tt&amp;gt;.  The pset rank is in &amp;lt;tt&amp;gt;Network_Config.RankInPSet&amp;lt;/tt&amp;gt;:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
#include &amp;lt;stdio.h&amp;gt;&lt;br /&gt;
#include &amp;lt;fcntl.h&amp;gt;&lt;br /&gt;
#include &amp;lt;unistd.h&amp;gt;&lt;br /&gt;
#include &amp;lt;common/bgp_personality.h&amp;gt;&lt;br /&gt;
&lt;br /&gt;
int main(void)&lt;br /&gt;
{&lt;br /&gt;
    _BGP_Personality_t personality;&lt;br /&gt;
    int fd;&lt;br /&gt;
&lt;br /&gt;
    if ((fd = open(&amp;quot;/proc/personality&amp;quot;, O_RDONLY)) == -1)&lt;br /&gt;
    {&lt;br /&gt;
        perror(&amp;quot;open&amp;quot;);&lt;br /&gt;
        return 1;&lt;br /&gt;
    }&lt;br /&gt;
    if (read(fd, &amp;amp;personality, sizeof(personality)) != sizeof(personality))&lt;br /&gt;
    {&lt;br /&gt;
        perror(&amp;quot;read&amp;quot;);&lt;br /&gt;
        close(fd);&lt;br /&gt;
        return 1;&lt;br /&gt;
    }&lt;br /&gt;
    close(fd);&lt;br /&gt;
&lt;br /&gt;
    printf(&amp;quot;My pset rank is %d\n&amp;quot;, personality.Network_Config.RankInPSet);&lt;br /&gt;
&lt;br /&gt;
    return 0;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
(compile the above with &amp;lt;tt&amp;gt;-I/bgsys/drivers/ppcfloor/arch/include&amp;lt;/tt&amp;gt;)&lt;br /&gt;
&lt;br /&gt;
===Torus rank===&lt;br /&gt;
&lt;br /&gt;
A torus rank is a number identifying a compute node within a whole partition.  In a way, it is much &amp;quot;nicer&amp;quot; than a pset rank since it is unique within a job and it also starts from &amp;lt;tt&amp;gt;0&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
The torus rank is easy to obtain from a C program: it is the &amp;lt;tt&amp;gt;Network_Config.Rank&amp;lt;/tt&amp;gt; field of the personality structure.&lt;br /&gt;
&lt;br /&gt;
Unfortunately, the torus rank is not available in &amp;lt;tt&amp;gt;/proc/personality.sh&amp;lt;/tt&amp;gt;, but a shell script can easily calculate it from other fields:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
TORUS_RANK=`echo $BG_PSETORG | awk &amp;quot;{print \\$1 + \\$2 * $BG_XSIZE + \&lt;br /&gt;
            \\$3 * $BG_XSIZE * $BG_YSIZE}&amp;quot;`&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===MPI rank===&lt;br /&gt;
&lt;br /&gt;
MPI rank should not be confused with a torus rank, even though by default the two are the same.  MPI rank is a property of a process, ''not'' node.  If one submits a job in the &amp;lt;tt&amp;gt;VN&amp;lt;/tt&amp;gt; or &amp;lt;tt&amp;gt;DUAL&amp;lt;/tt&amp;gt; mode, there will be multiple MPI tasks per node, obviously each with a different MPI rank.  Also, using the &amp;lt;tt&amp;gt;BG_MAPPING&amp;lt;/tt&amp;gt; environment variable changes the mapping between the torus coordinates and MPI ranks.&lt;br /&gt;
&lt;br /&gt;
While obtaining MPI rank from an MPI application is trivial, how to obtain it from a shell script?&lt;br /&gt;
&lt;br /&gt;
One way would be to invoke a simple C program:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
#include &amp;lt;stdio.h&amp;gt;&lt;br /&gt;
#include &amp;quot;zoid_api.h&amp;quot;&lt;br /&gt;
&lt;br /&gt;
int main(void)&lt;br /&gt;
{&lt;br /&gt;
    if (__zoid_init())&lt;br /&gt;
        return 1;&lt;br /&gt;
    printf(&amp;quot;%d\n&amp;quot;, __zoid_my_rank());&lt;br /&gt;
    return 0;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
(compile with &amp;lt;tt&amp;gt;-I&amp;lt;/tt&amp;gt;''path_to_ZeptoOS''&amp;lt;tt&amp;gt;/packages/zoid/prebuilt -L&amp;lt;/tt&amp;gt;''path_to_ZeptoOS''&amp;lt;tt&amp;gt;/packages/zoid/prebuilt -lzoid_cn&amp;lt;/tt&amp;gt;)&lt;br /&gt;
&lt;br /&gt;
A slight disadvantage of this approach is that &amp;lt;tt&amp;gt;__zoid_init&amp;lt;/tt&amp;gt; registers the process with the ZOID daemon on the I/O node, which is an overhead we do not need.  Another solution, without using any binaries, is as follows:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
MPI_RANK=`echo $CONTROL_INIT | awk -F, '{print $4}'`&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This has a disadvantage of using internal ZOID variables which are not guaranteed to be supported in future releases.&lt;br /&gt;
&lt;br /&gt;
==How to open a socket from a CN to the outside world==&lt;br /&gt;
&lt;br /&gt;
ZOID provides IP packet forwarding between the compute nodes and the I/O nodes.  However, because the compute nodes use non-routable IP addresses (&amp;lt;tt&amp;gt;192.168.1.&amp;lt;/tt&amp;gt;''x''), they cannot communicate directly with the outside world.&lt;br /&gt;
&lt;br /&gt;
The most transparent solution to this problem is to perform network address translation (NAT) on the I/O nodes using the Linux kernel netfilter infrastructure.  We used to enable this by default, but experiments have shown it to have a detrimental effect on the overall performance of the TCP/IP stack on the I/O nodes, slowing down access to the network filesystems.&lt;br /&gt;
&lt;br /&gt;
To enable the translation, pass &amp;lt;tt&amp;gt;ZOID_NAT_ENABLE&amp;lt;/tt&amp;gt; environment variable when submitting a job.  An administrator can also enable this option permanently in the [[ZOID#opt_enable_nat|config file]].&lt;br /&gt;
&lt;br /&gt;
==How to obtain a Cobalt job ID==&lt;br /&gt;
&lt;br /&gt;
Cobalt passes the job id to the application processes launched on the compute nodes using the &amp;lt;tt&amp;gt;COBALT_JOBID&amp;lt;/tt&amp;gt; environment variable.&lt;br /&gt;
&lt;br /&gt;
This variable is also accessible from the [[ZOID#User script|user script]] running on the I/O nodes, using the &amp;lt;tt&amp;gt;ZOID_JOB_ENV&amp;lt;/tt&amp;gt; variable:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
COBALT_JOBID=`echo $ZOID_JOB_ENV | sed 's/^.*COBALT_JOBID=\([^:]*\)/\1/'`&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Why large MPI processes do not work==&lt;br /&gt;
&lt;br /&gt;
A common reason might be that they do not have enough memory to run.  MPI processes run within the big memory region, which by default is limited to just 256&amp;amp;nbsp;MB so as not to deplete the ordinary Linux paged memory pool too much (main memory is allocated to the big memory region at boot time and it cannot be reclaimed by the kernel, even if it were unused).&lt;br /&gt;
&lt;br /&gt;
See the [[Kernel#Kernel (command line) parameters|Kernel]] section to learn how to increase the limit; the parameter to use is &amp;lt;tt&amp;gt;flatmemsizeMB&amp;lt;/tt&amp;gt;.  We suggest creating multiple profiles with different big memory sizes to accommodate different uses of ZeptoOS.&lt;br /&gt;
&lt;br /&gt;
==Why SSH keeps asking for a password==&lt;br /&gt;
&lt;br /&gt;
As we envisioned it, partition owners should be able to log on the I/O nodes belonging to their jobs without being asked for a password.  The following considerations apply:&lt;br /&gt;
# The account information on the partition owner must be added to the &amp;lt;tt&amp;gt;/etc/passwd&amp;lt;/tt&amp;gt; file on the I/O nodes when launching a job; this is discussed [[ZOID#The /bin.rd/update_passwd_file.sh file|here]].&lt;br /&gt;
# For password-less logins, &amp;lt;tt&amp;gt;shosts.equiv&amp;lt;/tt&amp;gt; must be configured before (re)building the I/O node ramdisk, as discussed [[Testing#Interactive login|here]].  Alternatively, users could set up SSH key pairs in their home directories (password-less, or using &amp;lt;tt&amp;gt;ssh-agent&amp;lt;/tt&amp;gt; to cache the password).&lt;br /&gt;
# SSH might temporarily prevent a partition owner from logging in if an attempt is made before the job starts running, as discussed [[Testing#Interactive login|here]].  Root can always log in, by providing the password set when building the I/O node ramdisk for the first time.&lt;br /&gt;
# Finally, keep in mind that a particular site might have disabled this feature on purpose.&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
[[ZeptoOS_Documentation|Top]]&lt;/div&gt;</summary>
		<author><name>Iskra</name></author>
	</entry>
	<entry>
		<id> /zeptoos/index.php?title=FAQ&amp;diff=580</id>
		<title>FAQ</title>
		<link rel="alternate" type="text/html" href=" /zeptoos/index.php?title=FAQ&amp;diff=580"/>
		<updated>2009-05-07T20:51:30Z</updated>

		<summary type="html">&lt;p&gt;Iskra: /* Why large MPI processes do not work */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;[[ZeptoOS_Documentation|Top]]&lt;br /&gt;
----&lt;br /&gt;
&lt;br /&gt;
==How to obtain a CN node number==&lt;br /&gt;
&lt;br /&gt;
This depends on what number one is interested in.&lt;br /&gt;
&lt;br /&gt;
===Pset rank===&lt;br /&gt;
&lt;br /&gt;
A pset rank is a number identifying a compute node within each ''pset'' (an I/O node and the compute nodes that communicate with it).  Note that on partitions larger than one pset, the pset ranks will not be unique.  Also, pset ranks do ''not'' start from &amp;lt;tt&amp;gt;0&amp;lt;/tt&amp;gt;; they start from &amp;lt;tt&amp;gt;1&amp;lt;/tt&amp;gt; for some mysterious reason (do not blame us &amp;amp;#8211; blame IBM&amp;amp;nbsp;:-).&lt;br /&gt;
&lt;br /&gt;
Pset rank is used as the last octet in the IP address on the tree network connecting the compute nodes and the I/O nodes (''x'' in &amp;lt;tt&amp;gt;192.168.1.&amp;lt;/tt&amp;gt;''x'').&lt;br /&gt;
&lt;br /&gt;
The pset rank is available on the compute nodes from &amp;lt;tt&amp;gt;/proc/personality.sh&amp;lt;/tt&amp;gt;, in the &amp;lt;tt&amp;gt;BG_RANK_IN_PSET&amp;lt;/tt&amp;gt; variable:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
#!/bin/sh&lt;br /&gt;
&lt;br /&gt;
. /proc/personality.sh&lt;br /&gt;
&lt;br /&gt;
echo &amp;quot;My pset rank is $BG_RANK_IN_PSET&amp;quot;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
From a C program it will be easier to use the binary personality available from &amp;lt;tt&amp;gt;/proc/personality&amp;lt;/tt&amp;gt;.  The definition of the structure can be found in &amp;lt;tt&amp;gt;/bgsys/drivers/ppcfloor/arch/include/common/bgp_personality.h&amp;lt;/tt&amp;gt;.  The pset rank is in &amp;lt;tt&amp;gt;Network_Config.RankInPSet&amp;lt;/tt&amp;gt;:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
#include &amp;lt;stdio.h&amp;gt;&lt;br /&gt;
#include &amp;lt;fcntl.h&amp;gt;&lt;br /&gt;
#include &amp;lt;unistd.h&amp;gt;&lt;br /&gt;
#include &amp;lt;common/bgp_personality.h&amp;gt;&lt;br /&gt;
&lt;br /&gt;
int main(void)&lt;br /&gt;
{&lt;br /&gt;
    _BGP_Personality_t personality;&lt;br /&gt;
    int fd;&lt;br /&gt;
&lt;br /&gt;
    if ((fd = open(&amp;quot;/proc/personality&amp;quot;, O_RDONLY)) == -1)&lt;br /&gt;
    {&lt;br /&gt;
        perror(&amp;quot;open&amp;quot;);&lt;br /&gt;
        return 1;&lt;br /&gt;
    }&lt;br /&gt;
    if (read(fd, &amp;amp;personality, sizeof(personality)) != sizeof(personality))&lt;br /&gt;
    {&lt;br /&gt;
        perror(&amp;quot;read&amp;quot;);&lt;br /&gt;
        close(fd);&lt;br /&gt;
        return 1;&lt;br /&gt;
    }&lt;br /&gt;
    close(fd);&lt;br /&gt;
&lt;br /&gt;
    printf(&amp;quot;My pset rank is %d\n&amp;quot;, personality.Network_Config.RankInPSet);&lt;br /&gt;
&lt;br /&gt;
    return 0;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
(compile the above with &amp;lt;tt&amp;gt;-I/bgsys/drivers/ppcfloor/arch/include&amp;lt;/tt&amp;gt;)&lt;br /&gt;
&lt;br /&gt;
===Torus rank===&lt;br /&gt;
&lt;br /&gt;
A torus rank is a number identifying a compute node within a whole partition.  In a way, it is much &amp;quot;nicer&amp;quot; than a pset rank since it is unique within a job and it also starts from &amp;lt;tt&amp;gt;0&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
The torus rank is easy to obtain from a C program: it is the &amp;lt;tt&amp;gt;Network_Config.Rank&amp;lt;/tt&amp;gt; field of the personality structure.&lt;br /&gt;
&lt;br /&gt;
Unfortunately, the torus rank is not available in &amp;lt;tt&amp;gt;/proc/personality.sh&amp;lt;/tt&amp;gt;, but a shell script can easily calculate it from other fields:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
TORUS_RANK=`echo $BG_PSETORG | awk &amp;quot;{print \\$1 + \\$2 * $BG_XSIZE + \&lt;br /&gt;
            \\$3 * $BG_XSIZE * $BG_YSIZE}&amp;quot;`&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===MPI rank===&lt;br /&gt;
&lt;br /&gt;
MPI rank should not be confused with a torus rank, even though by default the two are the same.  MPI rank is a property of a process, ''not'' node.  If one submits a job in the &amp;lt;tt&amp;gt;VN&amp;lt;/tt&amp;gt; or &amp;lt;tt&amp;gt;DUAL&amp;lt;/tt&amp;gt; mode, there will be multiple MPI tasks per node, obviously each with a different MPI rank.  Also, using the &amp;lt;tt&amp;gt;BG_MAPPING&amp;lt;/tt&amp;gt; environment variable changes the mapping between the torus coordinates and MPI ranks.&lt;br /&gt;
&lt;br /&gt;
While obtaining MPI rank from an MPI application is trivial, how to obtain it from a shell script?&lt;br /&gt;
&lt;br /&gt;
One way would be to invoke a simple C program:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
#include &amp;lt;stdio.h&amp;gt;&lt;br /&gt;
#include &amp;quot;zoid_api.h&amp;quot;&lt;br /&gt;
&lt;br /&gt;
int main(void)&lt;br /&gt;
{&lt;br /&gt;
    if (__zoid_init())&lt;br /&gt;
        return 1;&lt;br /&gt;
    printf(&amp;quot;%d\n&amp;quot;, __zoid_my_rank());&lt;br /&gt;
    return 0;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
(compile with &amp;lt;tt&amp;gt;-I&amp;lt;/tt&amp;gt;''path_to_ZeptoOS''&amp;lt;tt&amp;gt;/packages/zoid/prebuilt -L&amp;lt;/tt&amp;gt;''path_to_ZeptoOS''&amp;lt;tt&amp;gt;/packages/zoid/prebuilt -lzoid_cn&amp;lt;/tt&amp;gt;)&lt;br /&gt;
&lt;br /&gt;
A slight disadvantage of this approach is that &amp;lt;tt&amp;gt;__zoid_init&amp;lt;/tt&amp;gt; registers the process with the ZOID daemon on the I/O node, which is an overhead we do not need.  Another solution, without using any binaries, is as follows:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
MPI_RANK=`echo $CONTROL_INIT | awk -F, '{print $4}'`&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This has a disadvantage of using internal ZOID variables which are not guaranteed to be supported in future releases.&lt;br /&gt;
&lt;br /&gt;
==How to open a socket from a CN to the outside world==&lt;br /&gt;
&lt;br /&gt;
ZOID provides IP packet forwarding between the compute nodes and the I/O nodes.  However, because the compute nodes use non-routable IP addresses (&amp;lt;tt&amp;gt;192.168.1.&amp;lt;/tt&amp;gt;''x''), they cannot communicate directly with the outside world.&lt;br /&gt;
&lt;br /&gt;
The most transparent solution to this problem is to perform network address translation (NAT) on the I/O nodes using the Linux kernel netfilter infrastructure.  We used to enable this by default, but experiments have shown it to have a detrimental effect on the overall performance of the TCP/IP stack on the I/O nodes, slowing down access to the network filesystems.&lt;br /&gt;
&lt;br /&gt;
To enable the translation, pass &amp;lt;tt&amp;gt;ZOID_NAT_ENABLE&amp;lt;/tt&amp;gt; environment variable when submitting a job.  An administrator can also enable this option permanently in the [[ZOID#opt_enable_nat|config file]].&lt;br /&gt;
&lt;br /&gt;
==How to obtain a Cobalt job ID==&lt;br /&gt;
&lt;br /&gt;
Cobalt passes the job id to the application processes launched on the compute nodes using the &amp;lt;tt&amp;gt;COBALT_JOBID&amp;lt;/tt&amp;gt; environment variable.&lt;br /&gt;
&lt;br /&gt;
This variable is also accessible from the [[ZOID#User script|user script]] running on the I/O nodes, using the &amp;lt;tt&amp;gt;ZOID_JOB_ENV&amp;lt;/tt&amp;gt; variable:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
COBALT_JOBID=`echo $ZOID_JOB_ENV | sed 's/^.*COBALT_JOBID=\([^:]*\)/\1/'`&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Why large MPI processes do not work==&lt;br /&gt;
&lt;br /&gt;
A common reason might be that they do not have enough memory to run.  MPI processes run within the big memory region, which by default is limited to just 256&amp;amp;nbsp;MB so as not to deplete the ordinary Linux paged memory pool too much (main memory is allocated to the big memory region at boot time and it cannot be reclaimed by the kernel, even if it were unused).&lt;br /&gt;
&lt;br /&gt;
See the [[Kernel#Kernel (command line) parameters|Kernel]] section to learn how to increase the limit; the parameter to use is &amp;lt;tt&amp;gt;flatmemsizeMB&amp;lt;/tt&amp;gt;.  We suggest creating multiple profiles with different big memory sizes to accommodate different uses of ZeptoOS.&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
[[ZeptoOS_Documentation|Top]]&lt;/div&gt;</summary>
		<author><name>Iskra</name></author>
	</entry>
	<entry>
		<id> /zeptoos/index.php?title=FAQ&amp;diff=579</id>
		<title>FAQ</title>
		<link rel="alternate" type="text/html" href=" /zeptoos/index.php?title=FAQ&amp;diff=579"/>
		<updated>2009-05-07T20:48:33Z</updated>

		<summary type="html">&lt;p&gt;Iskra: /* Why large MPI processes do not work */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;[[ZeptoOS_Documentation|Top]]&lt;br /&gt;
----&lt;br /&gt;
&lt;br /&gt;
==How to obtain a CN node number==&lt;br /&gt;
&lt;br /&gt;
This depends on what number one is interested in.&lt;br /&gt;
&lt;br /&gt;
===Pset rank===&lt;br /&gt;
&lt;br /&gt;
A pset rank is a number identifying a compute node within each ''pset'' (an I/O node and the compute nodes that communicate with it).  Note that on partitions larger than one pset, the pset ranks will not be unique.  Also, pset ranks do ''not'' start from &amp;lt;tt&amp;gt;0&amp;lt;/tt&amp;gt;; they start from &amp;lt;tt&amp;gt;1&amp;lt;/tt&amp;gt; for some mysterious reason (do not blame us &amp;amp;#8211; blame IBM&amp;amp;nbsp;:-).&lt;br /&gt;
&lt;br /&gt;
Pset rank is used as the last octet in the IP address on the tree network connecting the compute nodes and the I/O nodes (''x'' in &amp;lt;tt&amp;gt;192.168.1.&amp;lt;/tt&amp;gt;''x'').&lt;br /&gt;
&lt;br /&gt;
The pset rank is available on the compute nodes from &amp;lt;tt&amp;gt;/proc/personality.sh&amp;lt;/tt&amp;gt;, in the &amp;lt;tt&amp;gt;BG_RANK_IN_PSET&amp;lt;/tt&amp;gt; variable:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
#!/bin/sh&lt;br /&gt;
&lt;br /&gt;
. /proc/personality.sh&lt;br /&gt;
&lt;br /&gt;
echo &amp;quot;My pset rank is $BG_RANK_IN_PSET&amp;quot;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
From a C program it will be easier to use the binary personality available from &amp;lt;tt&amp;gt;/proc/personality&amp;lt;/tt&amp;gt;.  The definition of the structure can be found in &amp;lt;tt&amp;gt;/bgsys/drivers/ppcfloor/arch/include/common/bgp_personality.h&amp;lt;/tt&amp;gt;.  The pset rank is in &amp;lt;tt&amp;gt;Network_Config.RankInPSet&amp;lt;/tt&amp;gt;:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
#include &amp;lt;stdio.h&amp;gt;&lt;br /&gt;
#include &amp;lt;fcntl.h&amp;gt;&lt;br /&gt;
#include &amp;lt;unistd.h&amp;gt;&lt;br /&gt;
#include &amp;lt;common/bgp_personality.h&amp;gt;&lt;br /&gt;
&lt;br /&gt;
int main(void)&lt;br /&gt;
{&lt;br /&gt;
    _BGP_Personality_t personality;&lt;br /&gt;
    int fd;&lt;br /&gt;
&lt;br /&gt;
    if ((fd = open(&amp;quot;/proc/personality&amp;quot;, O_RDONLY)) == -1)&lt;br /&gt;
    {&lt;br /&gt;
        perror(&amp;quot;open&amp;quot;);&lt;br /&gt;
        return 1;&lt;br /&gt;
    }&lt;br /&gt;
    if (read(fd, &amp;amp;personality, sizeof(personality)) != sizeof(personality))&lt;br /&gt;
    {&lt;br /&gt;
        perror(&amp;quot;read&amp;quot;);&lt;br /&gt;
        close(fd);&lt;br /&gt;
        return 1;&lt;br /&gt;
    }&lt;br /&gt;
    close(fd);&lt;br /&gt;
&lt;br /&gt;
    printf(&amp;quot;My pset rank is %d\n&amp;quot;, personality.Network_Config.RankInPSet);&lt;br /&gt;
&lt;br /&gt;
    return 0;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
(compile the above with &amp;lt;tt&amp;gt;-I/bgsys/drivers/ppcfloor/arch/include&amp;lt;/tt&amp;gt;)&lt;br /&gt;
&lt;br /&gt;
===Torus rank===&lt;br /&gt;
&lt;br /&gt;
A torus rank is a number identifying a compute node within a whole partition.  In a way, it is much &amp;quot;nicer&amp;quot; than a pset rank since it is unique within a job and it also starts from &amp;lt;tt&amp;gt;0&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
The torus rank is easy to obtain from a C program: it is the &amp;lt;tt&amp;gt;Network_Config.Rank&amp;lt;/tt&amp;gt; field of the personality structure.&lt;br /&gt;
&lt;br /&gt;
Unfortunately, the torus rank is not available in &amp;lt;tt&amp;gt;/proc/personality.sh&amp;lt;/tt&amp;gt;, but a shell script can easily calculate it from other fields:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
TORUS_RANK=`echo $BG_PSETORG | awk &amp;quot;{print \\$1 + \\$2 * $BG_XSIZE + \&lt;br /&gt;
            \\$3 * $BG_XSIZE * $BG_YSIZE}&amp;quot;`&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===MPI rank===&lt;br /&gt;
&lt;br /&gt;
MPI rank should not be confused with a torus rank, even though by default the two are the same.  MPI rank is a property of a process, ''not'' node.  If one submits a job in the &amp;lt;tt&amp;gt;VN&amp;lt;/tt&amp;gt; or &amp;lt;tt&amp;gt;DUAL&amp;lt;/tt&amp;gt; mode, there will be multiple MPI tasks per node, obviously each with a different MPI rank.  Also, using the &amp;lt;tt&amp;gt;BG_MAPPING&amp;lt;/tt&amp;gt; environment variable changes the mapping between the torus coordinates and MPI ranks.&lt;br /&gt;
&lt;br /&gt;
While obtaining MPI rank from an MPI application is trivial, how to obtain it from a shell script?&lt;br /&gt;
&lt;br /&gt;
One way would be to invoke a simple C program:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
#include &amp;lt;stdio.h&amp;gt;&lt;br /&gt;
#include &amp;quot;zoid_api.h&amp;quot;&lt;br /&gt;
&lt;br /&gt;
int main(void)&lt;br /&gt;
{&lt;br /&gt;
    if (__zoid_init())&lt;br /&gt;
        return 1;&lt;br /&gt;
    printf(&amp;quot;%d\n&amp;quot;, __zoid_my_rank());&lt;br /&gt;
    return 0;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
(compile with &amp;lt;tt&amp;gt;-I&amp;lt;/tt&amp;gt;''path_to_ZeptoOS''&amp;lt;tt&amp;gt;/packages/zoid/prebuilt -L&amp;lt;/tt&amp;gt;''path_to_ZeptoOS''&amp;lt;tt&amp;gt;/packages/zoid/prebuilt -lzoid_cn&amp;lt;/tt&amp;gt;)&lt;br /&gt;
&lt;br /&gt;
A slight disadvantage of this approach is that &amp;lt;tt&amp;gt;__zoid_init&amp;lt;/tt&amp;gt; registers the process with the ZOID daemon on the I/O node, which is an overhead we do not need.  Another solution, without using any binaries, is as follows:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
MPI_RANK=`echo $CONTROL_INIT | awk -F, '{print $4}'`&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This has a disadvantage of using internal ZOID variables which are not guaranteed to be supported in future releases.&lt;br /&gt;
&lt;br /&gt;
==How to open a socket from a CN to the outside world==&lt;br /&gt;
&lt;br /&gt;
ZOID provides IP packet forwarding between the compute nodes and the I/O nodes.  However, because the compute nodes use non-routable IP addresses (&amp;lt;tt&amp;gt;192.168.1.&amp;lt;/tt&amp;gt;''x''), they cannot communicate directly with the outside world.&lt;br /&gt;
&lt;br /&gt;
The most transparent solution to this problem is to perform network address translation (NAT) on the I/O nodes using the Linux kernel netfilter infrastructure.  We used to enable this by default, but experiments have shown it to have a detrimental effect on the overall performance of the TCP/IP stack on the I/O nodes, slowing down access to the network filesystems.&lt;br /&gt;
&lt;br /&gt;
To enable the translation, pass &amp;lt;tt&amp;gt;ZOID_NAT_ENABLE&amp;lt;/tt&amp;gt; environment variable when submitting a job.  An administrator can also enable this option permanently in the [[ZOID#opt_enable_nat|config file]].&lt;br /&gt;
&lt;br /&gt;
==How to obtain a Cobalt job ID==&lt;br /&gt;
&lt;br /&gt;
Cobalt passes the job id to the application processes launched on the compute nodes using the &amp;lt;tt&amp;gt;COBALT_JOBID&amp;lt;/tt&amp;gt; environment variable.&lt;br /&gt;
&lt;br /&gt;
This variable is also accessible from the [[ZOID#User script|user script]] running on the I/O nodes, using the &amp;lt;tt&amp;gt;ZOID_JOB_ENV&amp;lt;/tt&amp;gt; variable:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
COBALT_JOBID=`echo $ZOID_JOB_ENV | sed 's/^.*COBALT_JOBID=\([^:]*\)/\1/'`&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Why large MPI processes do not work==&lt;br /&gt;
&lt;br /&gt;
A common reason might be that they do not have enough memory to run.  MPI processes run within the Big Memory region, which by default is limited to just 256&amp;amp;nbsp;MB so as not to deplete the ordinary Linux paged memory pool too much (main memory is allocated to the Big Memory region at boot time and it cannot be used for paged memory, even if it were unused).&lt;br /&gt;
&lt;br /&gt;
See the [[Kernel#Kernel (command line) parameters|Kernel]] section to learn how to increase the limit; the parameter to use is &amp;lt;tt&amp;gt;flatmemsizeMB&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
[[ZeptoOS_Documentation|Top]]&lt;/div&gt;</summary>
		<author><name>Iskra</name></author>
	</entry>
	<entry>
		<id> /zeptoos/index.php?title=MPICH,_DCMF,_and_SPI&amp;diff=578</id>
		<title>MPICH, DCMF, and SPI</title>
		<link rel="alternate" type="text/html" href=" /zeptoos/index.php?title=MPICH,_DCMF,_and_SPI&amp;diff=578"/>
		<updated>2009-05-07T20:45:09Z</updated>

		<summary type="html">&lt;p&gt;Iskra: /* ZCB and Big memory */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;[[Testing]] | [[ZeptoOS_Documentation|Top]] | [[Kernel]]&lt;br /&gt;
----&lt;br /&gt;
&lt;br /&gt;
==Introduction==&lt;br /&gt;
&lt;br /&gt;
To support high performance computing (HPC) applications, specifically MPI applications, we have ported IBM CNK's communication software stack to the ZeptoOS compute node Linux environment.  MPICH used in this ZeptoOS release is mpich2-1.0.7 with IBM patches. It is reasonably stable, and the performance of MPI applications on the ZeptoOS compute node Linux is comparable to that on CNK.  While there are some limitations at the moment, there are benefits as well.&lt;br /&gt;
&lt;br /&gt;
Benefits:&lt;br /&gt;
* No limitation on the number of threads&lt;br /&gt;
** 4 or more OpenMP threads per node&lt;br /&gt;
** Additional threads as I/O or backgroup tasks&lt;br /&gt;
* It is Linux!&lt;br /&gt;
** Debugging tools such as gdb, strace, etc&lt;br /&gt;
** Various file systems, such as ramfs&lt;br /&gt;
&lt;br /&gt;
Current limitations:&lt;br /&gt;
* Only the SMP mode is supported&lt;br /&gt;
* Shared libraries are not provided now&lt;br /&gt;
* No binary compatibility between CNK and ZeptoOS CN Linux&lt;br /&gt;
&lt;br /&gt;
We will support a VN-equivalent mode (multiple MPI tasks per node) and provide shared libraries in a future release.&lt;br /&gt;
&lt;br /&gt;
As in IBM CNK environment, Deep Computing Messaging Framework (DCMF) and System Programming Interface (SPI) are available.  It is possible to write a DCMF code or a SPI code directly if necessary. DCMF is a communication library that provides non-blocking operations. Please refer to the [http://dcmf.anl-external.org/wiki/index.php/Main_Page DCMF wiki] for details.  We are using DCMF version 1.0.0 in the current ZeptoOS release, which is older than the DCMF in the current driver release (V1R3M0). SPI is the lowest-level user space API for the torus DMA, collective network, BGP-specifc lock mechanisms, and other compute node specific features.  There is no public document on SPI available at the moment, but almost all header files and source code is available. Internally, MPICH depends on DMCF, which in turn depends on SPI.  We will say more about it [[#Software stack layout|later]].&lt;br /&gt;
&lt;br /&gt;
===ZCB and Big memory===&lt;br /&gt;
&lt;br /&gt;
MPI application running under the ZeptoOS compute node environment (technically, applications that require the DMA operation or a maximum memory bandwidth) need to be configured as Zepto Compute Binaries (ZCB).  This is done using the &amp;lt;tt&amp;gt;zelftool&amp;lt;/tt&amp;gt;, invoked behind the scenes when linking a binary using the ZeptoOS MPI compiler wrapper scripts (&amp;lt;tt&amp;gt;zmpicc&amp;lt;/tt&amp;gt;, etc).&lt;br /&gt;
&lt;br /&gt;
ZeptoOS compute node kernel treats ZCB executables differently from ordinary processes. It creates a special memory mapping region called big memory, which is covered by large pages with semi-static TLB entries, and it loads all applications sections to the big memory region. Big memory region has virtually no TLB misses and it also enables DMA operations.&lt;br /&gt;
&lt;br /&gt;
Some system calls will not work correctly if used from a ZCB process, in particular &amp;lt;tt&amp;gt;fork&amp;lt;/tt&amp;gt; (but creating threads does work).  Also, being a separate memory region set up at kernel boot time, the size of big memory is fixed.  It is set to 256&amp;amp;nbsp;MB by default, which could be too small for larger MPI processes; it can be [[FAQ#Why large MPI processes do not work|increased]] before booting a partition, at the expense of the ordinary Linux paged memory.&lt;br /&gt;
&lt;br /&gt;
==Compiling HPC applications==&lt;br /&gt;
&lt;br /&gt;
While the same compiler can be used as for the IBM CNK, ZeptoOS compute node environment requires linking with ZeptoOS-specific communication libraries (applications linked with the CNK MPI will not work on ZeptoOS).&lt;br /&gt;
&lt;br /&gt;
===Compiler wrapper scripts===&lt;br /&gt;
&lt;br /&gt;
We provide compiler wrapper scripts which automatically link with appropriate libraries from the ZeptoOS installation directory.  We provide the same set of wrapper scripts that IBM provides, with an extra &amp;lt;tt&amp;gt;z&amp;lt;/tt&amp;gt; prefix:&lt;br /&gt;
&lt;br /&gt;
; zmpicc, zmpicxx, zmpif77, zmpif90&lt;br /&gt;
: Wrapper scripts that invoke BGP-enhanced GNU compilers&lt;br /&gt;
&lt;br /&gt;
; zmpixlc, zmpixlcxx, zmpixlf2003, zmpixlf77, zmpixlf90, zmpixlf95&lt;br /&gt;
: Wrapper scripts that invoke IBM XL compilers&lt;br /&gt;
&lt;br /&gt;
; zmpixlc_r, zmpixlcxx_r, zmpixlf2003_r, zmpixlf77_r, zmpixlf90_r, zmpixlf95_r&lt;br /&gt;
: Wrapper scripts that invoke IBM XL compilers (thread safe compilation for OpenMP)&lt;br /&gt;
&lt;br /&gt;
To get insight into the internals of these scripts, invoke them with the &amp;lt;tt&amp;gt;-show&amp;lt;/tt&amp;gt; option.&lt;br /&gt;
&lt;br /&gt;
====A compilation example====&lt;br /&gt;
&lt;br /&gt;
Understanding build system on a program might take some time, but there is nothing special to compile a program for ZeptoOS.&lt;br /&gt;
&lt;br /&gt;
Here is a real-world example of how to build a well-known [http://climate.lanl.gov/Models/POP/ Parallel Ocean Program (POP)].&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
$ wget http://climate.lanl.gov/Models/POP/POP_2.0.1.tar.Z&lt;br /&gt;
$ tar xvfz POP_2.0.1.tar.Z &amp;amp;&amp;amp; cd pop&lt;br /&gt;
$ ./setup_run_dir ztest &amp;amp;&amp;amp; cd ztest&lt;br /&gt;
$ edit ibm_mpi.gnu   # see the patch below&lt;br /&gt;
$ export ARCHDIR=ibm_mpi&lt;br /&gt;
$ make   # takes a while&lt;br /&gt;
$ edit pop_in   # test data set&lt;br /&gt;
-  nprocs_clinic = 4&lt;br /&gt;
-  nprocs_tropic = 4&lt;br /&gt;
+  nprocs_clinic = 64&lt;br /&gt;
+  nprocs_tropic = 64&lt;br /&gt;
$ cqsub -n 64 -t 10 -k &amp;lt;zepto_profile&amp;gt; ./pop&lt;br /&gt;
&lt;br /&gt;
--------------------&lt;br /&gt;
--- orig/ibm_mpi.gnu    2009-04-15 15:01:58.666457601 -0500&lt;br /&gt;
+++ ztest/ibm_mpi.gnu    2009-04-15 14:17:58.099132435 -0500&lt;br /&gt;
@@ -6,17 +6,18 @@&lt;br /&gt;
# will someday be a file which is a cookbook in Q&amp;amp;A style: &amp;quot;How do I do X?&amp;quot;&lt;br /&gt;
# is followed by something like &amp;quot;Go to file Y and add Z to line NNN.&amp;quot;&lt;br /&gt;
#&lt;br /&gt;
-FC = mpxlf90_r&lt;br /&gt;
-LD = mpxlf90_r&lt;br /&gt;
-CC = mpcc_r&lt;br /&gt;
-Cp = /usr/bin/cp&lt;br /&gt;
-Cpp = /usr/ccs/lib/cpp -P&lt;br /&gt;
+ZPATH=&amp;lt;zepto_dir&amp;gt;&lt;br /&gt;
+FC = $(ZPATH)/zmpixlf90&lt;br /&gt;
+LD = $(ZPATH)/zmpixlf90&lt;br /&gt;
+CC = $(ZPATH)/zmpixlc&lt;br /&gt;
+Cp = /bin/cp&lt;br /&gt;
+Cpp = /usr/bin/cpp -P&lt;br /&gt;
AWK = /usr/bin/awk&lt;br /&gt;
-ABI = -q64&lt;br /&gt;
+#ABI = -q64&lt;br /&gt;
COMMDIR = mpi&lt;br /&gt;
&lt;br /&gt;
-NETCDFINC = -I/usr/local/include&lt;br /&gt;
-NETCDFLIB = -L/usr/local/lib&lt;br /&gt;
+NETCDFINC = -I/soft/apps/netcdf-4.0/include/&lt;br /&gt;
+NETCDFLIB = -L/soft/apps/netcdf-4.0/lib&lt;br /&gt;
&lt;br /&gt;
#  Enable MPI library for parallel code, yes/no.&lt;br /&gt;
&lt;br /&gt;
@@ -58,7 +59,8 @@&lt;br /&gt;
#&lt;br /&gt;
#----------------------------------------------------------------------------&lt;br /&gt;
&lt;br /&gt;
-FBASE = $(ABI) -qarch=auto -qnosave -bmaxdata:0x80000000 $(NETCDFINC) -I$(ObjDepDir)&lt;br /&gt;
+#FBASE = $(ABI) -qarch=auto -qnosave -bmaxdata:0x80000000 $(NETCDFINC) -I$(ObjDepDir)&lt;br /&gt;
+FBASE = $(ABI) -qarch=auto -qnosave  $(NETCDFINC) -I$(ObjDepDir)&lt;br /&gt;
&lt;br /&gt;
ifeq ($(TRAP_FPE),yes)&lt;br /&gt;
  FBASE := $(FBASE) -qflttrap=overflow:zerodivide:enable -qspillsize=32704&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Compiling without the wrapper scripts===&lt;br /&gt;
&lt;br /&gt;
If one wishes to invoke the compiler directly, please make sure that the Makefile or build environment points to ZeptoOS header files and libraries correctly. An example would be:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
$ /bgsys/drivers/ppcfloor/gnu-linux/bin/powerpc-bgp-linux-gcc \&lt;br /&gt;
-o mpi-test-linux -Wall -O3 -I&amp;lt;zepto_dir&amp;gt;/include mpi-test.c \&lt;br /&gt;
-L&amp;lt;zepto_dir&amp;gt;/lib -lmpich.zcl -ldcmfcoll.zcl -ldcmf.zcl -lSPI.zcl -lzcl \&lt;br /&gt;
-lzoid_cn -lrt -lpthread -lm&lt;br /&gt;
$ &amp;lt;zepto_dir&amp;gt;/bin/zelftool -e mpi-test-linux&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
'''Notes:''' &lt;br /&gt;
* Replace &amp;lt;tt&amp;gt;&amp;lt;zepto_dir&amp;gt;&amp;lt;/tt&amp;gt; with your actuall ZeptoOS install path.&lt;br /&gt;
* Do not forget to call the &amp;lt;tt&amp;gt;zelftool&amp;lt;/tt&amp;gt; utility, which makes the executable a Zepto Compute Binary.&lt;br /&gt;
&amp;lt;!--&lt;br /&gt;
The file layout in the zepto install path would be:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
|-- bin&lt;br /&gt;
|   |-- zelftool&lt;br /&gt;
|-- include&lt;br /&gt;
|   |-- dcmf.h&lt;br /&gt;
|   |-- dcmf_collectives.h&lt;br /&gt;
|   |-- dcmf_coremath.h&lt;br /&gt;
|   |-- dcmf_globalcollectives.h&lt;br /&gt;
|   |-- dcmf_multisend.h&lt;br /&gt;
|   |-- dcmf_optimath.h&lt;br /&gt;
|   |-- mpe_thread.h&lt;br /&gt;
|   |-- mpi.h&lt;br /&gt;
|   |-- mpi.mod&lt;br /&gt;
|   |-- mpi_base.mod&lt;br /&gt;
|   |-- mpi_constants.mod&lt;br /&gt;
|   |-- mpi_sizeofs.mod&lt;br /&gt;
|   |-- mpicxx.h&lt;br /&gt;
|   |-- mpif.h&lt;br /&gt;
|   |-- mpio.h&lt;br /&gt;
|   |-- mpiof.h&lt;br /&gt;
|   `-- mpix.h&lt;br /&gt;
`-- lib&lt;br /&gt;
    |-- libSPI.zcl.a&lt;br /&gt;
    |-- libcxxmpich.zcl.a&lt;br /&gt;
    |-- libdcmf.zcl.a&lt;br /&gt;
    |-- libdcmfcoll.zcl.a&lt;br /&gt;
    |-- libfmpich.zcl.a&lt;br /&gt;
    |-- libfmpich_.zcl.a&lt;br /&gt;
    |-- libmpich.zcl.a&lt;br /&gt;
    |-- libmpich.zclf90.a&lt;br /&gt;
    |-- libzcl.a&lt;br /&gt;
    `-- libzoid_cn.a&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
--&amp;gt;&lt;br /&gt;
==Building MPICH, DCMF, and SPI libraries==&lt;br /&gt;
&lt;br /&gt;
We provide all the necessary source code to build MPICH, DCMF, and SPI.  To build these libraries, just type:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
$ make -C comm rebuild-target&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
It may take half an hour to an hour to complete the build process, depending on what file system you are using (i.e., GPFS is a lot slower than a local file system).&lt;br /&gt;
&lt;br /&gt;
The &amp;lt;tt&amp;gt;rebuild-target&amp;lt;/tt&amp;gt; target does not know anything about the existing installation directory; it only copies the built libraries and header files to the &amp;lt;tt&amp;gt;comm/tmp&amp;lt;/tt&amp;gt; directory. To install the newly built libraries, do the following:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
$ make -C comm update-prebuilt&lt;br /&gt;
$ python install.py &amp;lt;zepto_dir&amp;gt;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The &amp;lt;tt&amp;gt;update-prebuilt&amp;lt;/tt&amp;gt; target basically copies the files from the &amp;lt;tt&amp;gt;comm/tmp&amp;lt;/tt&amp;gt; directory to the &amp;lt;tt&amp;gt;comm/prebuilt&amp;lt;/tt&amp;gt; directory, which is where the &amp;lt;tt&amp;gt;install.py&amp;lt;/tt&amp;gt; script looks for to copy the files to &amp;lt;tt&amp;gt;&amp;lt;zepto_dir&amp;gt;&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
==Software stack layout==&lt;br /&gt;
&lt;br /&gt;
[[Image:Zepto-Comm-Stack.png|right]]&lt;br /&gt;
&lt;br /&gt;
The figure on the right depicts the layout of the communication software stack in the ZeptoOS compute node environment.  This is very similar to the IBM CNK's stack, with the exception of an extra ZEPTO SPI layer, and the use of Linux instead of CNK.&lt;br /&gt;
&lt;br /&gt;
Since MPICH is a well-known software package we will not discuss it here, but we will briefly describe the DCMF and SPI components:&lt;br /&gt;
&lt;br /&gt;
* DCMF&lt;br /&gt;
** Stands for Deep Computing Messaging Framework&lt;br /&gt;
** Developed by IBM originally for Blue Gene architecture &lt;br /&gt;
** Hardware initialization, query functions&lt;br /&gt;
** Supports BGP Torus DMA, collective network&lt;br /&gt;
** Provides timer&lt;br /&gt;
** Supports non-blocking collective operations&lt;br /&gt;
** BGP MPICH uses DCMF internally (IBM provides a glue layer)&lt;br /&gt;
* SPI&lt;br /&gt;
** Stands for System Programming Interface&lt;br /&gt;
** Developed by IBM. BGP-specific code.&lt;br /&gt;
** Kernel interfaces &amp;amp;#8211; DMA control, lockbox, etc&lt;br /&gt;
** DMA related definitions &lt;br /&gt;
*** can be used in both user space and kernel space&lt;br /&gt;
** RAS, BGP personality, mapping related functions&lt;br /&gt;
&lt;br /&gt;
BGP SPI was designed specifically for IBM CNK, so it is not compatible with Linux.  ZEPTO SPI is a thin software layer that absorbs the differences between the CNK and Linux or drops the requests that Linux cannot handle.&lt;br /&gt;
&lt;br /&gt;
==Source code==&lt;br /&gt;
&lt;br /&gt;
The source code and header files of DCMF and SPI can be found in the &amp;lt;tt&amp;gt;comm&amp;lt;/tt&amp;gt; directory. The source code of MPICH is in &amp;lt;tt&amp;gt;DCMF/lib/mpich2/mpich2-1.0.7.tar.gz&amp;lt;/tt&amp;gt;, which will be extracted at build time.&lt;br /&gt;
&lt;br /&gt;
The DCMF source code is located in &amp;lt;tt&amp;gt;DCMF/sys/&amp;lt;/tt&amp;gt;. DCMF core source code is in &amp;lt;tt&amp;gt;DCMF/sys/messaging/&amp;lt;/tt&amp;gt;. Component Collective Messaging Interface (CCMI) is part of DCMF and its source code is in &amp;lt;tt&amp;gt;DCMF/sys/collectives/&amp;lt;/tt&amp;gt;. Test codes can be found in &amp;lt;tt&amp;gt;DCMF/sys/collectives/tests/&amp;lt;/tt&amp;gt; for CCMI and &amp;lt;tt&amp;gt;DCMF/sys/messaging/tests/&amp;lt;/tt&amp;gt;. Those test codes can be a good example for DCMF/CCMI programming.&lt;br /&gt;
&lt;br /&gt;
SPI headers are in &amp;lt;tt&amp;gt;arch-runtime/arch/&amp;lt;/tt&amp;gt; and SPI source code is in &amp;lt;tt&amp;gt;comm/arch-runtime/runtime/&amp;lt;/tt&amp;gt;.  The source code of the ZEPTO SPI layer is in &amp;lt;tt&amp;gt;arch-runtime/zcl_spi/&amp;lt;/tt&amp;gt;, while the header files are in &amp;lt;tt&amp;gt;arch-runtime/arch/include/zepto/&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Here is an overview of the directory tree:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
comm&lt;br /&gt;
|-- DCMF&lt;br /&gt;
|   |-- lib&lt;br /&gt;
|   |   |-- dev&lt;br /&gt;
|   |   `-- mpich2&lt;br /&gt;
|   |       `-- make&lt;br /&gt;
|   |-- sys&lt;br /&gt;
|   |   |-- collectives&lt;br /&gt;
|   |   |   |-- adaptor&lt;br /&gt;
|   |   |   |-- kernel&lt;br /&gt;
|   |   |   |-- tests&lt;br /&gt;
|   |   |   `-- tools&lt;br /&gt;
|   |   |-- include&lt;br /&gt;
|   |   `-- messaging&lt;br /&gt;
|   |       |-- devices&lt;br /&gt;
|   |       |-- messager&lt;br /&gt;
|   |       |-- protocols&lt;br /&gt;
|   |       |-- queueing&lt;br /&gt;
|   |       |-- sysdep&lt;br /&gt;
|   |       `-- tests&lt;br /&gt;
|-- arch-runtime&lt;br /&gt;
|   |-- arch&lt;br /&gt;
|   |   `-- include&lt;br /&gt;
|   |       |-- bpcore&lt;br /&gt;
|   |       |-- cnk&lt;br /&gt;
|   |       |-- common&lt;br /&gt;
|   |       |-- spi&lt;br /&gt;
|   |       `-- zepto&lt;br /&gt;
|   |-- runtime&lt;br /&gt;
|   |-- testcodes&lt;br /&gt;
|   `-- zcl_spi&lt;br /&gt;
`-- testcodes&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Debug output===&lt;br /&gt;
&lt;br /&gt;
ZeptoOS versions of SPI and DCMF have a built-in debug output.  The output is disabled by default, and can be enabled by setting the environment variable &amp;lt;tt&amp;gt;ZEPTO_TRACE&amp;lt;/tt&amp;gt; when submitting a job.  The integer value of the variable indicates the debug level (a higher number results in more debug output).&lt;br /&gt;
&lt;br /&gt;
An example:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
$ cqsub -k &amp;lt;zepto_profile&amp;gt; -n 64 -t 10 ... -e ZEPTO_TRACE=2 ./a.out&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
[[Testing]] | [[ZeptoOS_Documentation|Top]] | [[Kernel]]&lt;/div&gt;</summary>
		<author><name>Iskra</name></author>
	</entry>
	<entry>
		<id> /zeptoos/index.php?title=Testing&amp;diff=577</id>
		<title>Testing</title>
		<link rel="alternate" type="text/html" href=" /zeptoos/index.php?title=Testing&amp;diff=577"/>
		<updated>2009-05-07T20:43:51Z</updated>

		<summary type="html">&lt;p&gt;Iskra: /* Submitting */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;[[Installation]] | [[ZeptoOS_Documentation|Top]] | [[MPICH, DCMF, and SPI]]&lt;br /&gt;
----&lt;br /&gt;
&lt;br /&gt;
Once ZeptoOS is configured and installed, it is time to test it.  Here are a few trivial tests to verify that the environment is working:&lt;br /&gt;
&lt;br /&gt;
==The /bin/sleep job==&lt;br /&gt;
&lt;br /&gt;
If you are using Cobalt, submit using either of the commands below:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
$ cqsub -k &amp;lt;profile-name&amp;gt; -t &amp;lt;time&amp;gt; -n 1 /bin/sleep 3600&lt;br /&gt;
$ qsub --kernel &amp;lt;profile-name&amp;gt; -t &amp;lt;time&amp;gt; -n 1 /bin/sleep 3600&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
If you are using &amp;lt;tt&amp;gt;mpirun&amp;lt;/tt&amp;gt; directly, submit as follows:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
$ mpirun -verbose 1 -partition &amp;lt;partition-name&amp;gt; -np 1 -timeout &amp;lt;time&amp;gt; \&lt;br /&gt;
-cwd $PWD -exe /bin/sleep 3600&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This test, if successful, will verify that the ZeptoOS compute and I/O node environments are booting correctly.  We deliberately chose a system binary such as &amp;lt;tt&amp;gt;/bin/sleep&amp;lt;/tt&amp;gt; instead of something from a network filesystem so that even if the network filesystem does not come up for some reason, the test can still succeed.&lt;br /&gt;
&lt;br /&gt;
If everything works out fine, messages such as the following will be found in the error stream (''jobid''.error file if using Cobalt):&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
FE_MPI (Info) : initialize() - using jobname '' provided by scheduler interface&lt;br /&gt;
FE_MPI (Info) : Invoking mpirun backend&lt;br /&gt;
FE_MPI (Info) : connectToServer() - Handshake successful&lt;br /&gt;
BRIDGE (Info) : rm_set_serial() - The machine serial number (alias) is BGP&lt;br /&gt;
FE_MPI (Info) : Preparing partition&lt;br /&gt;
BE_MPI (Info) : Examining specified partition&lt;br /&gt;
BE_MPI (Info) : Checking partition ANL-R00-M1-N12-64 initial state ...&lt;br /&gt;
BE_MPI (Info) : Partition ANL-R00-M1-N12-64 initial state = FREE ('F')&lt;br /&gt;
BE_MPI (Info) : Checking partition owner...&lt;br /&gt;
BE_MPI (Info) : Setting new owner&lt;br /&gt;
BE_MPI (Info) : Initiating boot of the partition&lt;br /&gt;
BE_MPI (Info) : Waiting for partition ANL-R00-M1-N12-64 to boot...&lt;br /&gt;
BE_MPI (Info) : Partition is ready&lt;br /&gt;
BE_MPI (Info) : Done preparing partition&lt;br /&gt;
FE_MPI (Info) : Adding job&lt;br /&gt;
BE_MPI (Info) : Adding job to database...&lt;br /&gt;
FE_MPI (Info) : Job added with the following id: 98461&lt;br /&gt;
FE_MPI (Info) : Starting job 98461&lt;br /&gt;
FE_MPI (Info) : Waiting for job to terminate&lt;br /&gt;
BE_MPI (Info) : IO - Threads initialized&lt;br /&gt;
BE_MPI (Info) : I/O input runner thread terminated&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
(we stripped the timestamp prefixes to make the lines shorter)&lt;br /&gt;
&lt;br /&gt;
If these messages are immediately followed by other, error messages, then there is a problem.  One common instance would be:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
BE_MPI (Info) : I/O output runner thread terminated&lt;br /&gt;
BE_MPI (Info) : Job 98463 switched to state ERROR ('E')&lt;br /&gt;
BE_MPI (ERROR): Job execution failed&lt;br /&gt;
[...]&lt;br /&gt;
BE_MPI (ERROR): The error message in the job record is as follows:&lt;br /&gt;
BE_MPI (ERROR):   &amp;quot;Load failed on 172.16.3.11: Program segment is not 1MB aligned&amp;quot;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This error indicates that the job was submitted to the default software environment, not to ZeptoOS (at the very least, the default I/O node ramdisk was used).  You need to go back to the [[Installation#Setting up a kernel profile|Installation]] section to fix the problem.  Information from the system log files can be useful to diagnose the problem.&lt;br /&gt;
&lt;br /&gt;
==Log files==&lt;br /&gt;
&lt;br /&gt;
===I/O node===&lt;br /&gt;
&lt;br /&gt;
Every I/O node has its own log file located in &amp;lt;tt&amp;gt;/bgsys/logs/BGP/&amp;lt;/tt&amp;gt;, with a name such as &amp;lt;tt&amp;gt;R*-M*-N*-J*.log&amp;lt;/tt&amp;gt;.  This name will generally correspond to the name of the partition where the job was running.  Above, our job ran on &amp;lt;tt&amp;gt;ANL-R00-M1-N12-64&amp;lt;/tt&amp;gt; (we could see that in the error stream; Cobalt users can also use &amp;lt;tt&amp;gt;[c]qstat&amp;lt;/tt&amp;gt;); a corresponding I/O node log file on Argonne machines will be &amp;lt;tt&amp;gt;R00-M1-N12-J00.log&amp;lt;/tt&amp;gt;.  This is how a log file from a successful ZeptoOS boot looks like:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;Linux version 2.6.16.46-297 (geeko@buildhost) (gcc version 4.1.2 (BGP)) #1 SMP Wed Apr 22 15:04:42 CDT 2009&lt;br /&gt;
Kernel command line: console=bgcons root=/dev/ram0 lpj=8500000&lt;br /&gt;
init started:  BusyBox v1.4.2 (2008-04-10 05:20:01 UTC) multi-call binary&lt;br /&gt;
Starting RPC portmap daemon..done&lt;br /&gt;
eth0: Link status [RX+,TX+]&lt;br /&gt;
mount server reported tcp not available, falling back to udp&lt;br /&gt;
mount: RPC: Remote system error - No route to host&lt;br /&gt;
Zepto ION startup-00&lt;br /&gt;
eth0      Link encap:Ethernet  HWaddr 00:14:5E:7D:0C:57  &lt;br /&gt;
          inet addr:172.16.3.15  Bcast:172.31.255.255  Mask:255.240.0.0&lt;br /&gt;
          UP BROADCAST RUNNING MULTICAST  MTU:9000  Metric:1&lt;br /&gt;
          RX packets:880 errors:0 dropped:0 overruns:0 frame:0&lt;br /&gt;
          TX packets:1009 errors:0 dropped:0 overruns:0 carrier:0&lt;br /&gt;
          collisions:0 txqueuelen:1000 &lt;br /&gt;
          RX bytes:3878545 (3.6 Mb)  TX bytes:151458 (147.9 Kb)&lt;br /&gt;
          Interrupt:32 &lt;br /&gt;
Zepto ION startup-00 done&lt;br /&gt;
                                                                      done&lt;br /&gt;
Starting syslog servicesDec 31 18:00:36 ion-15 syslogd 1.4.1: restart.&lt;br /&gt;
                                                                      done&lt;br /&gt;
Starting network time protocol daemon (NTPD) using 172.17.3.1&lt;br /&gt;
May  1 12:57:11 ion-15 ntpdate[642]: step time server 172.17.3.1 offset 1241200617.470271 sec&lt;br /&gt;
May  1 12:57:11 ion-15 ntpd[653]: ntpd 4.2.0a@1.1196-r Sat Oct  4 00:01:53 UTC 2008 (1)&lt;br /&gt;
May  1 12:57:11 ion-15 ntpd[653]: precision = 1.000 usec&lt;br /&gt;
May  1 12:57:11 ion-15 ntpd[653]: Listening on interface wildcard, 0.0.0.0#123&lt;br /&gt;
May  1 12:57:11 ion-15 ntpd[653]: Listening on interface eth0, 172.16.3.15#123&lt;br /&gt;
May  1 12:57:11 ion-15 ntpd[653]: Listening on interface lo, 127.0.0.1#123&lt;br /&gt;
May  1 12:57:11 ion-15 ntpd[653]: kernel time sync status 0040&lt;br /&gt;
                                                                      done&lt;br /&gt;
Enabling ssh&lt;br /&gt;
Mounting site filesystems&lt;br /&gt;
                                                                      done&lt;br /&gt;
Loading PVFS2 kernel module                                           done&lt;br /&gt;
Sleeping 0 seconds before starting PVFS                               done&lt;br /&gt;
Starting PVFS2 client                                                 done&lt;br /&gt;
Sleeping 10 seconds before mounting PVFS&lt;br /&gt;
                                                                      done&lt;br /&gt;
Mounting PVFS2 filesystems                                            done&lt;br /&gt;
Starting SSH daemonMay  1 12:57:21 ion-15 sshd[833]: Server listening on 0.0.0.0 port 22.&lt;br /&gt;
                                                                      done&lt;br /&gt;
Zepto ION startup-12&lt;br /&gt;
Zepto ION startup-12 done&lt;br /&gt;
Starting GPFS&lt;br /&gt;
May  1 12:57:26 ion-15 syslogd 1.4.1: restart.&lt;br /&gt;
/etc/init.d/rc3.d/S40gpfs: GPFS is ready on I/O node ion-15 : 172.16.3.15 : R00-M1-N12-J00&lt;br /&gt;
ln: creating symbolic link `/home/acherryl/acherryl' to `/gpfs/home/acherryl': File exists&lt;br /&gt;
ln: creating symbolic link `/home/bgpadmin/bgpadmin' to `/gpfs/home/bgpadmin': File exists&lt;br /&gt;
ln: creating symbolic link `/home/davidr/davidr' to `/gpfs/home/davidr': File exists&lt;br /&gt;
ln: creating symbolic link `/home/scullinl/scullinl' to `/gpfs/home/scullinl': File exists&lt;br /&gt;
Starting ZOID...&lt;br /&gt;
                                                                      done&lt;br /&gt;
Zepto ION startup-99&lt;br /&gt;
Zepto ION startup-99 done&lt;br /&gt;
May  1 17:57:59 ion-15 init: Starting pid 2823, console /dev/console: '/bin/sh'&lt;br /&gt;
BusyBox v1.4.2 (2008-10-04 00:02:35 UTC) Built-in shell (ash)&lt;br /&gt;
Enter 'help' for a list of built-in commands.&lt;br /&gt;
/bin/sh: can't access tty; job control turned off&lt;br /&gt;
~ # &lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
(again, we stripped the prefixes to make the lines shorter)&lt;br /&gt;
&lt;br /&gt;
Messages such as &amp;lt;tt&amp;gt;Zepto ION startup&amp;lt;/tt&amp;gt; or &amp;lt;tt&amp;gt;Starting ZOID&amp;lt;/tt&amp;gt; clearly indicate that a ZeptoOS I/O node ramdisk is being used.  If one instead mistakenly booted with the default ramdisk, this could be recognized by messages such as:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
Starting CIO services&lt;br /&gt;
[ciod:initialized]                                                    done&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
(&amp;lt;tt&amp;gt;ciod&amp;lt;/tt&amp;gt; is ''never'' started when using Zepto Compute Node Linux)&lt;br /&gt;
&lt;br /&gt;
In addition to verifying the ramdisk, the correct I/O node kernel can also be verified using the I/O node logfile by checking the kernel build timestamp in the first line of the boot log.  As of this writing the default kernel on the Argonne machines has a timestamp of &amp;lt;tt&amp;gt;Wed Oct 29 18:51:19 UTC 2008&amp;lt;/tt&amp;gt;; as can be seen above, the ZeptoOS kernel was built more recently.&lt;br /&gt;
&lt;br /&gt;
===Compute node===&lt;br /&gt;
&lt;br /&gt;
All the compute nodes on the machine share the same MMCS log file, located in &amp;lt;tt&amp;gt;/bgsys/logs/BGP/&amp;lt;/tt&amp;gt;.  The name of the log file is not fixed (it contains a timestamp), but &amp;lt;tt&amp;gt;sn1-bgdb0-mmcs_db_server-current.log&amp;lt;/tt&amp;gt; always links to the current file.  Because the file is shared with other jobs, we recommed to grep it for user name, partition name, or both.&lt;br /&gt;
&lt;br /&gt;
A correct boot log when when booting ZeptoOS will look something like this:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
iskra:ANL-R00-M1-N12-64 {20}.0: Common Node Services V1R3M0 (efix:0)&lt;br /&gt;
iskra:ANL-R00-M1-N12-64 {20}.0: Licensed Machine Code - Property of IBM.&lt;br /&gt;
iskra:ANL-R00-M1-N12-64 {20}.0: Blue Gene/P Licensed Machine Code.&lt;br /&gt;
iskra:ANL-R00-M1-N12-64 {20}.0: Copyright IBM Corp., 2006, 2007 All Rights Reserved.&lt;br /&gt;
iskra:ANL-R00-M1-N12-64 {20}.0: Z: Zepto Linux Kernel relocating CNS... dst=80280000 src=fff40000 size=262144&lt;br /&gt;
iskra:ANL-R00-M1-N12-64 {20}.0: Z: CNS is successfully relocated to 00280000 in physical memory&lt;br /&gt;
iskra:ANL-R00-M1-N12-64 {20}.0: Linux version 2.6.19.2-g66cbca2d (kazutomo@login1) (gcc version 4.1.2 (BGP)) #12 SMP Tue Apr 21 12:58:11 CDT 2009&lt;br /&gt;
iskra:ANL-R00-M1-N12-64 {20}.0: Zone PFN ranges:&lt;br /&gt;
iskra:ANL-R00-M1-N12-64 {20}.0:   DMA             0 -&amp;gt;    28672&lt;br /&gt;
iskra:ANL-R00-M1-N12-64 {20}.0:   Normal      28672 -&amp;gt;    28672&lt;br /&gt;
iskra:ANL-R00-M1-N12-64 {20}.0: early_node_map[1] active PFN ranges&lt;br /&gt;
iskra:ANL-R00-M1-N12-64 {20}.1:     0:        0 -&amp;gt;    28672&lt;br /&gt;
iskra:ANL-R00-M1-N12-64 {20}.1: Built 1 zonelists.  Total pages: 28658&lt;br /&gt;
iskra:ANL-R00-M1-N12-64 {20}.1: Kernel command line: console=bgcons root=/dev/ram0 lpj=8500000&lt;br /&gt;
iskra:ANL-R00-M1-N12-64 {20}.1: PID hash table entries: 4096 (order: 12, 16384 bytes)&lt;br /&gt;
iskra:ANL-R00-M1-N12-64 {20}.0: Dentry cache hash table entries: 262144 (order: 4, 1048576 bytes)&lt;br /&gt;
iskra:ANL-R00-M1-N12-64 {20}.0: Inode-cache hash table entries: 131072 (order: 3, 524288 bytes)&lt;br /&gt;
iskra:ANL-R00-M1-N12-64 {20}.0: Memory: 1826560k available (1408k kernel code, 832k data, 192k init, 0k highmem)&lt;br /&gt;
iskra:ANL-R00-M1-N12-64 {20}.0: Calibrating delay loop (skipped)... 1700.00 BogoMIPS preset&lt;br /&gt;
iskra:ANL-R00-M1-N12-64 {20}.0: Mount-cache hash table entries: 8192&lt;br /&gt;
iskra:ANL-R00-M1-N12-64 {20}.0: CPU 1 done callin...&lt;br /&gt;
iskra:ANL-R00-M1-N12-64 {20}.0: CPU 1 done setup...&lt;br /&gt;
iskra:ANL-R00-M1-N12-64 {20}.0: CPU 1 done timebase take...&lt;br /&gt;
iskra:ANL-R00-M1-N12-64 {20}.0: Processor 1 found.&lt;br /&gt;
iskra:ANL-R00-M1-N12-64 {20}.0: CPU 2 done callin...&lt;br /&gt;
iskra:ANL-R00-M1-N12-64 {20}.0: CPU 2 done setup...&lt;br /&gt;
iskra:ANL-R00-M1-N12-64 {20}.0: CPU 2 done timebase take...&lt;br /&gt;
iskra:ANL-R00-M1-N12-64 {20}.0: Processor 2 found.&lt;br /&gt;
iskra:ANL-R00-M1-N12-64 {20}.0: CPU 3 done callin...&lt;br /&gt;
iskra:ANL-R00-M1-N12-64 {20}.0: CPU 3 done setup...&lt;br /&gt;
iskra:ANL-R00-M1-N12-64 {20}.0: CPU 3 done timebase take...&lt;br /&gt;
iskra:ANL-R00-M1-N12-64 {20}.0: Processor 3 found.&lt;br /&gt;
iskra:ANL-R00-M1-N12-64 {20}.0: Brought up 4 CPUs&lt;br /&gt;
iskra:ANL-R00-M1-N12-64 {20}.0: migration_cost=0&lt;br /&gt;
iskra:ANL-R00-M1-N12-64 {20}.0: checking if image is initramfs... it is&lt;br /&gt;
iskra:ANL-R00-M1-N12-64 {20}.0: Freeing initrd memory: 2575k freed&lt;br /&gt;
iskra:ANL-R00-M1-N12-64 {20}.0: NET: Registered protocol family 16&lt;br /&gt;
iskra:ANL-R00-M1-N12-64 {20}.0: NET: Registered protocol family 2&lt;br /&gt;
iskra:ANL-R00-M1-N12-64 {20}.0: IP route cache hash table entries: 16384 (order: 0, 65536 bytes)&lt;br /&gt;
iskra:ANL-R00-M1-N12-64 {20}.0: TCP established hash table entries: 65536 (order: 3, 524288 bytes)&lt;br /&gt;
iskra:ANL-R00-M1-N12-64 {20}.0: TCP bind hash table entries: 32768 (order: 2, 262144 bytes)&lt;br /&gt;
iskra:ANL-R00-M1-N12-64 {20}.0: TCP: Hash tables configured (established 65536 bind 32768)&lt;br /&gt;
iskra:ANL-R00-M1-N12-64 {20}.0: TCP reno registered&lt;br /&gt;
iskra:ANL-R00-M1-N12-64 {20}.0: fuse init (API version 7.7)&lt;br /&gt;
iskra:ANL-R00-M1-N12-64 {20}.0: io scheduler noop registered (default)&lt;br /&gt;
iskra:ANL-R00-M1-N12-64 {20}.0: RAMDISK driver initialized: 16 RAM disks of 32768K size 1024 blocksize&lt;br /&gt;
iskra:ANL-R00-M1-N12-64 {20}.0: tun: Universal TUN/TAP device driver, 1.6&lt;br /&gt;
iskra:ANL-R00-M1-N12-64 {20}.0: tun: (C) 1999-2004 Max Krasnyansky &amp;lt;maxk@qualcomm.com&amp;gt;&lt;br /&gt;
iskra:ANL-R00-M1-N12-64 {20}.0: TCP cubic registered&lt;br /&gt;
iskra:ANL-R00-M1-N12-64 {20}.0: NET: Registered protocol family 1&lt;br /&gt;
iskra:ANL-R00-M1-N12-64 {20}.0: NET: Registered protocol family 17&lt;br /&gt;
iskra:ANL-R00-M1-N12-64 {20}.0: NET: Registered protocol family 15&lt;br /&gt;
iskra:ANL-R00-M1-N12-64 {20}.0: Freeing unused kernel memory: 192k init&lt;br /&gt;
iskra:ANL-R00-M1-N12-64 {20}.0: init started: BusyBox(for ZeptoOS Compute Node) v1.12.1 (2009-04-21 16:08:55 CDT)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This is very easy to tell from a boot log of the default light-weight kernel, which will consist of the first four lines ''only''.&lt;br /&gt;
&lt;br /&gt;
The MMCS log file contains other useful information besides the boot log of the compute nodes.  Before the kernel starts booting, the following messages related to the newly submitted job can be found there:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
DBBlockCmd  DatabaseBlockCommandThread started: block ANL-R00-M1-N12-64, user iskra, action 1&lt;br /&gt;
DBBlockCmd  setusername iskra &lt;br /&gt;
iskra       db_allocate ANL-R00-M1-N12-64 &lt;br /&gt;
iskra       DBConsoleController::setAllocating() ANL-R00-M1-N12-64&lt;br /&gt;
iskra       block state C&lt;br /&gt;
iskra       DBConsoleController::addBlock(ANL-R00-M1-N12-64)&lt;br /&gt;
iskra:ANL-R00-M1-N12-64     BlockController::connect()&lt;br /&gt;
iskra:ANL-R00-M1-N12-64     connecting to mcServer at 127.0.0.1:1206&lt;br /&gt;
    Connected to MCServer as iskra@sn1. Client version 3. Server version 3 on fd 101&lt;br /&gt;
iskra:ANL-R00-M1-N12-64     connected to mcServer&lt;br /&gt;
iskra:ANL-R00-M1-N12-64     mcServer target set ANL-R00-M1-N12-64 created&lt;br /&gt;
iskra:ANL-R00-M1-N12-64     mcServer target set ANL-R00-M1-N12-64 opened&lt;br /&gt;
iskra:ANL-R00-M1-N12-64     {0} I/O log file: /bgsys/logs/BGP/R00-M1-N12-J00.log&lt;br /&gt;
iskra:ANL-R00-M1-N12-64     MailboxListener starting&lt;br /&gt;
iskra:ANL-R00-M1-N12-64     DBConsoleController::doneAllocating() ANL-R00-M1-N12-64&lt;br /&gt;
iskra:ANL-R00-M1-N12-64     BlockController::boot_block \&lt;br /&gt;
uloader=/bgsys/argonne-utils/partitions/ANL-R00-M1-N12-64/uloader \&lt;br /&gt;
cnload=/bgsys/argonne-utils/partitions/ANL-R00-M1-N12-64/CNS,/bgsys/argonne-utils/partitions/ANL-R00-M1-N12-64/CNK \&lt;br /&gt;
ioload=/bgsys/argonne-utils/partitions/ANL-R00-M1-N12-64/CNS,/bgsys/argonne-utils/partitions/ANL-R00-M1-N12-64/INK,/bgsys/argonne-utils/partitions/ANL-R00-M1-N12-64/ramdisk &lt;br /&gt;
iskra:ANL-R00-M1-N12-64     boot_block cookie: 587867023 compute_nodes: 64 io_nodes: 1&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Of particular relevance is the pathname to the I/O node log file(s) (if it cannot be easily guessed from the partition name) and the pathnames to the kernels and ramdisks used to boot the partition.&lt;br /&gt;
&lt;br /&gt;
After the kernel boot log, the log file will also contain information about subsequent phases of starting a job:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
iskra:ANL-R00-M1-N12-64     I/O node initialized: R00-M1-N12-J00&lt;br /&gt;
iskra:ANL-R00-M1-N12-64     DBBlockController::waitBoot(ANL-R00-M1-N12-64) block initialization successful&lt;br /&gt;
iskra       DatabaseBlockCommandThread stopped&lt;br /&gt;
DBJobCmd    DatabaseJobCommandThread started: job 98461, user iskra, action 1&lt;br /&gt;
DBJobCmd    setusername iskra &lt;br /&gt;
iskra       Starting Job 98461&lt;br /&gt;
    New thread 4398305505840, for jobid 98461&lt;br /&gt;
    selectBlock(): ANL-R00-M1-N12-64        iskra(1)        connected state: I owner: iskra&lt;br /&gt;
ANL-R00-M1-N12-64   Jobid is 98461, homedir is /gpfs/home/iskra&lt;br /&gt;
ANL-R00-M1-N12-64   persist: 1&lt;br /&gt;
ANL-R00-M1-N12-64   connecting to mpirun...&lt;br /&gt;
ANL-R00-M1-N12-64   setting mpirun stream, fd=386&lt;br /&gt;
ANL-R00-M1-N12-64   contacting control node 0 at 172.16.3.15:7000&lt;br /&gt;
ANL-R00-M1-N12-64   connected to control node 0 at 172.16.3.15:7000&lt;br /&gt;
ANL-R00-M1-N12-64   Job::load() /bin/sleep &lt;br /&gt;
ANL-R00-M1-N12-64   Job loaded: 98461&lt;br /&gt;
ANL-R00-M1-N12-64   About to start /bin/sleep&lt;br /&gt;
ANL-R00-M1-N12-64   Job 98461 set to RUNNING&lt;br /&gt;
iskra:ANL-R00-M1-N12-64     {20}.0: floating point used in kernel (task=8080cfe0, pc=80017064)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Interactive login==&lt;br /&gt;
&lt;br /&gt;
We are assuming at this point that launching &amp;lt;tt&amp;gt;/bin/sleep&amp;lt;/tt&amp;gt; has been successful and that the &amp;quot;job&amp;quot; is running.  We can now start an interactive session on our BG/P resources.  Probably the most complicated part of this operation is finding the IP address of the I/O node(s).  The allocation of I/O nodes to partitions is fixed, so on a small machine one could simply make a list.  This information is also available in the log files discussed above.&lt;br /&gt;
&lt;br /&gt;
The IP address is printed near the top of the I/O node boot log, as part of the interface configuration of the Ethernet device:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
eth0      Link encap:Ethernet  HWaddr 00:14:5E:7D:0C:57  &lt;br /&gt;
          inet addr:172.16.3.15  Bcast:172.31.255.255  Mask:255.240.0.0&lt;br /&gt;
          UP BROADCAST RUNNING MULTICAST  MTU:9000  Metric:1&lt;br /&gt;
          RX packets:880 errors:0 dropped:0 overruns:0 frame:0&lt;br /&gt;
          TX packets:1009 errors:0 dropped:0 overruns:0 carrier:0&lt;br /&gt;
          collisions:0 txqueuelen:1000 &lt;br /&gt;
          RX bytes:3878545 (3.6 Mb)  TX bytes:151458 (147.9 Kb)&lt;br /&gt;
          Interrupt:32&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
In this case, the address is &amp;lt;tt&amp;gt;172.16.3.15&amp;lt;/tt&amp;gt; (the &amp;lt;tt&amp;gt;inet addr&amp;lt;/tt&amp;gt; value).&lt;br /&gt;
&lt;br /&gt;
The IP address is also available from the MMCS log file:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
ANL-R00-M1-N12-64   contacting control node 0 at 172.16.3.15:7000&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
With larger partitions that include multiple I/O nodes, querying the MMCS logfile is probably better, as it will list all the addresses.&lt;br /&gt;
&lt;br /&gt;
Once the IP address is known, one can simply use the SSH:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
iskra@login1.surveyor:~&amp;gt; ssh 172.16.3.15&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
BusyBox v1.4.2 (2008-10-04 00:02:35 UTC) Built-in shell (ash)&lt;br /&gt;
Enter 'help' for a list of built-in commands.&lt;br /&gt;
&lt;br /&gt;
/gpfs/home/iskra $ hostname&lt;br /&gt;
ion-15&lt;br /&gt;
/gpfs/home/iskra $ &lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
If everything is configured correctly, SSH will only let in root and the partition owner; no other unprivileged user will be allowed on the node.  However, this might require site-specific customization to work properly.  To enable access for the partition owner, one might need to make adjustments to [[ZOID#The /bin.rd/update_passwd_file.sh file|update_passwd_file.sh]].  To enable password-less login for the partition owners without requiring them to set up personal SSH keypairs, we recommend to add the names of the front end nodes to the &amp;lt;tt&amp;gt;shosts.equiv&amp;lt;/tt&amp;gt; file, found in &amp;lt;tt&amp;gt;ramdisk/ION/ramdisk-add/etc/ssh.zepto/&amp;lt;/tt&amp;gt; (it is empty by default; remember to use the names from the network that interconnects front end and I/O nodes, which might be different from hostnames, e.g., at Argonne we need to add the &amp;lt;tt&amp;gt;-data&amp;lt;/tt&amp;gt; suffix to the hostnames).  Until this has all been set up, one might prefer to log on as root (&amp;lt;tt&amp;gt;ssh -l root&amp;lt;/tt&amp;gt;), passing the password provided while [[Configuration#Building|building]] the ZeptoOS environment.&lt;br /&gt;
&lt;br /&gt;
Also, even when the partition owner is correctly set up, there will be a time window while booting the I/O node when the SSH daemon is already running, but a job has not yet been started; during that window, the partition owner cannot log on. If that happens, wait a few seconds and try again.&lt;br /&gt;
&lt;br /&gt;
Here's part of the &amp;lt;tt&amp;gt;ps&amp;lt;/tt&amp;gt; output from the I/O node:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
/gpfs/home/iskra $ ps -ef&lt;br /&gt;
UID        PID  PPID  C STIME TTY          TIME CMD&lt;br /&gt;
[...]&lt;br /&gt;
65534       98     1  0 16:09 ?        00:00:00 /sbin/portmap&lt;br /&gt;
root       108    19  0 16:09 ?        00:00:00 [rpciod/0]&lt;br /&gt;
root       109    19  0 16:09 ?        00:00:00 [rpciod/1]&lt;br /&gt;
root       110    19  0 16:09 ?        00:00:00 [rpciod/2]&lt;br /&gt;
root       111    19  0 16:09 ?        00:00:00 [rpciod/3]&lt;br /&gt;
root       570     1  0 16:09 ?        00:00:00 /sbin/syslogd&lt;br /&gt;
root       577     1  0 16:09 ?        00:00:00 /sbin/klogd -c 1 -x -x&lt;br /&gt;
ntp        653     1  0 16:09 ?        00:00:00 /usr/sbin/ntpd -p /var/run/ntpd.&lt;br /&gt;
root       688     1  0 16:09 ?        00:00:00 [lockd]&lt;br /&gt;
root       775     1  0 16:09 ?        00:00:00 /bgsys/iosoft/pvfs2/sbin/pvfs2-c&lt;br /&gt;
root       776   775  0 16:09 ?        00:00:00 pvfs2-client-core --child -a 5 -&lt;br /&gt;
root       833     1  0 16:10 ?        00:00:00 /usr/sbin/sshd -o PidFile=/var/r&lt;br /&gt;
root      1016     1  0 16:10 ?        00:00:00 /bin/ksh /usr/lpp/mmfs/bin/runmm&lt;br /&gt;
root      1079     1  0 16:10 ?        00:00:00 [nfsWatchKproc]&lt;br /&gt;
root      1080     1  0 16:10 ?        00:00:00 [gpfsSwapdKproc]&lt;br /&gt;
root      1146  1016  0 16:10 ?        00:00:01 /usr/lpp/mmfs/bin//mmfsd&lt;br /&gt;
root      1153     1  0 16:10 ?        00:00:00 [mmkproc]&lt;br /&gt;
root      1152     1  0 16:10 ?        00:00:00 [mmkproc]&lt;br /&gt;
root      1154     1  0 16:10 ?        00:00:00 [mmkproc]&lt;br /&gt;
iskra     2810     1 98 16:10 ?        00:04:09 /bin.rd/zoid -a 8 -m unix_impl.s&lt;br /&gt;
root      2823     1  0 16:10 ?        00:00:00 /bin/sh&lt;br /&gt;
root      3328   833  0 16:10 ?        00:00:00 sshd: iskra [priv]             &lt;br /&gt;
iskra     3332  3328  0 16:10 ?        00:00:00 sshd: iskra@ttyp0              &lt;br /&gt;
iskra     3333  3332  0 16:10 ttyp0    00:00:00 -sh&lt;br /&gt;
iskra     3346  3333  0 16:14 ttyp0    00:00:00 ps -ef&lt;br /&gt;
/gpfs/home/iskra $ &lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The I/O nodes run a small Linux setup with the root filesystem in the ramdisk.  Custom processes can be started, just like on any ordinary Linux node.  In the example above, it is mostly a few system daemons and the remote filesystem clients (GPFS, PVFS).  Please verify at this stage that the remote filesystem have been mounted correctly.&lt;br /&gt;
&lt;br /&gt;
One custom process running on the node is [[ZOID]], the I/O forwarding and job control daemon, which enables the communication with the compute nodes.  One of the facilities offered by ZOID is IP forwarding between the I/O node and the compute nodes, implemented using the virtual network tunneling device available in Linux:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
/gpfs/home/iskra $ ifconfig tun0&lt;br /&gt;
tun0      Link encap:UNSPEC  HWaddr 00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00  &lt;br /&gt;
          inet addr:192.168.1.254  P-t-P:192.168.1.254  Mask:255.255.255.255&lt;br /&gt;
          UP POINTOPOINT RUNNING NOARP MULTICAST  MTU:65535  Metric:1&lt;br /&gt;
          RX packets:0 errors:0 dropped:0 overruns:0 frame:0&lt;br /&gt;
          TX packets:0 errors:0 dropped:0 overruns:0 carrier:0&lt;br /&gt;
          collisions:0 txqueuelen:500 &lt;br /&gt;
          RX bytes:0 (0.0 b)  TX bytes:0 (0.0 b)&lt;br /&gt;
/gpfs/home/iskra $ &lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
At least on Argonne machines, with a 64:1 ratio of compute nodes to I/O nodes, compute nodes have addresses &amp;lt;tt&amp;gt;192.168.1.1&amp;lt;/tt&amp;gt; to &amp;lt;tt&amp;gt;192.168.1.64&amp;lt;/tt&amp;gt; (the last octet of the address is the [[FAQ#Pset rank|pset rank]]).  Somewhat confusingly, the first compute node (compute node &amp;lt;tt&amp;gt;0&amp;lt;/tt&amp;gt;) has IP address &amp;lt;tt&amp;gt;192.168.1.64&amp;lt;/tt&amp;gt;, so if one submits a one-node job as we did, that is the IP address that needs to be used to log on that sole running compute node.  The IP address of the second compute node is... &amp;lt;tt&amp;gt;192.168.1.59&amp;lt;/tt&amp;gt;.  On a machine with a 16:1 ratio of compute nodes to I/O nodes, the first compute node has IP address &amp;lt;tt&amp;gt;192.168.1.16&amp;lt;/tt&amp;gt;.  Do not blame us for this chaos &amp;amp;#8211; blame IBM&amp;amp;nbsp;:-).&lt;br /&gt;
&lt;br /&gt;
The compute nodes are running a &amp;lt;tt&amp;gt;telnet&amp;lt;/tt&amp;gt; daemon, and no password is required to log on them:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
/gpfs/home/iskra $ telnet 192.168.1.64&lt;br /&gt;
&lt;br /&gt;
Entering character mode&lt;br /&gt;
Escape character is '^]'.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
BusyBox(for ZeptoOS Compute Node) v1.12.1 (2009-04-21 16:08:55 CDT) built-in shell (ash)&lt;br /&gt;
Enter 'help' for a list of built-in commands.&lt;br /&gt;
&lt;br /&gt;
~ # &lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The IP address of the I/O node on this virtual network is &amp;lt;tt&amp;gt;192.168.1.254&amp;lt;/tt&amp;gt;. The network is local to each I/O node, so for larger jobs, there will be multiple distinct virtual networks that cannot communicate with each other, and the IP addresses will duplicate.&lt;br /&gt;
&lt;br /&gt;
Here's part of the &amp;lt;tt&amp;gt;ps&amp;lt;/tt&amp;gt; output from the compute node:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
~ # ps -ef&lt;br /&gt;
  PID USER       VSZ STAT COMMAND&lt;br /&gt;
[...]&lt;br /&gt;
   34 root      5440 S    /bin/sh /etc/init.d/rc.sysinit &lt;br /&gt;
   44 root      5504 S    /sbin/telnetd -l /bin/sh &lt;br /&gt;
   47 root      6528 S    /sbin/inetd &lt;br /&gt;
   48 root     46400 R N  /sbin/control &lt;br /&gt;
   62 root      7872 S    /bin/zoid-fuse -o allow_other -s /fuse &lt;br /&gt;
  116 root      5248 S    /bin/sleep 3600 &lt;br /&gt;
  118 root      5504 S    /bin/sh &lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Compute nodes have an even more stripped-down environment than the I/O nodes.  There are no user accounts &amp;amp;#8211; everything runs as root, including the application processes.  This is not a security concern, because the only practical way for a compute node to communicate with the outside world is through the I/O node, and I/O nodes ''do'' enforce user-level access control.&lt;br /&gt;
&lt;br /&gt;
There are two custom processes running on each compute node:&lt;br /&gt;
&lt;br /&gt;
'''control''' is a job management daemon responsible for tasks such as the launching of application processes, for the forwarding of stdin/out/err data, and for the management of the virtual network tunneling device from the compute node side.  Do not interfere with this process in any way; this would likely make the node inaccessible.&lt;br /&gt;
&lt;br /&gt;
'''zoid-fuse''' is a FUSE ([http://fuse.sourceforge.net/ Filesystem in Userspace]) client responsible for making the filesystems from the I/O nodes available to ordinary POSIX-compliant processes running on the compute nodes.  The whole filesystem namespace from the I/O nodes is made available on the compute nodes under &amp;lt;tt&amp;gt;/fuse/&amp;lt;/tt&amp;gt;, and symbolic links such as &amp;lt;tt&amp;gt;/home -&amp;gt; /fuse/home&amp;lt;/tt&amp;gt; are set up to keep the login and I/O node pathnames valid on the compute nodes.  Please verify that this is correctly set up.  We do not foresee a need to change this setup, but should that prove necessary, the responsbile &amp;lt;tt&amp;gt;fuse-start&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;fuse-stop&amp;lt;/tt&amp;gt; scripts can be found under &amp;lt;tt&amp;gt;ramdisk/CN/tree/bin&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
==Shell script job==&lt;br /&gt;
&lt;br /&gt;
Assuming that the above steps have been successful, one can now test running a simple job from a network filesystem, such as one's home directory.&lt;br /&gt;
&lt;br /&gt;
Here is a sample shell script to try:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
#!/bin/sh&lt;br /&gt;
&lt;br /&gt;
. /proc/personality.sh&lt;br /&gt;
&lt;br /&gt;
while true; do&lt;br /&gt;
    echo &amp;quot;Node $BG_RANK_IN_PSET running (stdout)&amp;quot;&lt;br /&gt;
    echo &amp;quot;Node $BG_RANK_IN_PSET running (stderr)&amp;quot; 1&amp;gt;&amp;amp;2&lt;br /&gt;
    sleep 10&lt;br /&gt;
done&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
(please see the [[FAQ#Pset rank|FAQ]] for the explanation of &amp;lt;tt&amp;gt;/proc/personality.sh&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;BG_RANK_IN_PSET&amp;lt;/tt&amp;gt;)&lt;br /&gt;
&lt;br /&gt;
Please create the script file on the network filesystem, set the executable bit (&amp;lt;tt&amp;gt;chmod 755&amp;lt;/tt&amp;gt;) and submit it.  Verify that the script starts correctly and that at least the standard error output is visible immediately.  The scripts print a line of output from each node every ten seconds.  It does so both to the standard output and to the standard error, because, depending on software configuration, the standard output stream could be buffered.  If that is the case, kill the job and verify that the standard output data did appear.&lt;br /&gt;
&lt;br /&gt;
==MPI and OpenMP jobs==&lt;br /&gt;
&lt;br /&gt;
The final tests involve parallel programming jobs, respectively MPI and OpenMP.  Use the test programs provided with the distribution. From the top level directory:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
$ cd comm/testcodes&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Compiling===&lt;br /&gt;
&lt;br /&gt;
The programs can be compiled on a login node using:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
$ /path/to/install/bin/zmpicc -o mpi-test-linux mpi-test.c&lt;br /&gt;
$ /path/to/install/bin/zmpixlc_r -qsmp=omp -o omp-test-linux omp-test.c&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Submitting===&lt;br /&gt;
&lt;br /&gt;
Submit the MPI test like any other job; use one of the below:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
$ cqsub -k &amp;lt;profile-name&amp;gt; -t &amp;lt;time&amp;gt; -n &amp;lt;number-of-processes&amp;gt; $PWD/mpi-test-linux&lt;br /&gt;
$ qsub --kernel &amp;lt;profile-name&amp;gt; -t &amp;lt;time&amp;gt; -n &amp;lt;number-of-processes&amp;gt;  $PWD/mpi-test-linux&lt;br /&gt;
$ mpirun -verbose 1 -partition &amp;lt;partition-name&amp;gt; -np &amp;lt;number-of-processes&amp;gt; -timeout &amp;lt;time&amp;gt; \&lt;br /&gt;
-cwd $PWD -exe $PWD/omp-test-linux&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
For the OpenMP test, we pass the number of OpenMP threads to use in the &amp;lt;tt&amp;gt;OMP_NUM_THREADS&amp;lt;/tt&amp;gt; variable:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
$ cqsub -k &amp;lt;profile-name&amp;gt; -t &amp;lt;time&amp;gt; -n 1 -e OMP_NUM_THREADS=&amp;lt;num&amp;gt; $PWD/omp-test-linux&lt;br /&gt;
$ qsub --kernel &amp;lt;profile-name&amp;gt; -t &amp;lt;time&amp;gt; -n 1 --env OMP_NUM_THREADS=&amp;lt;num&amp;gt; $PWD/mpi-test-linux&lt;br /&gt;
$ mpirun -verbose 1 -partition &amp;lt;partition-name&amp;gt; -np 1 -timeout &amp;lt;time&amp;gt; \&lt;br /&gt;
-cwd $PWD -env OMP_NUM_THREADS=&amp;lt;num&amp;gt; -exe $PWD/omp-test-linux&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The MPI test benchmarks the performance of various MPI operations.  The OpenMP test is just a parallel &amp;quot;Hello world&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
'''Note:''' see the [[FAQ#Why large MPI processes do not work|FAQ]] if submitting larger MPI processes does not work properly.&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
[[Installation]] | [[ZeptoOS_Documentation|Top]] | [[MPICH, DCMF, and SPI]]&lt;/div&gt;</summary>
		<author><name>Iskra</name></author>
	</entry>
	<entry>
		<id> /zeptoos/index.php?title=FAQ&amp;diff=576</id>
		<title>FAQ</title>
		<link rel="alternate" type="text/html" href=" /zeptoos/index.php?title=FAQ&amp;diff=576"/>
		<updated>2009-05-07T20:43:36Z</updated>

		<summary type="html">&lt;p&gt;Iskra: /* Why large MPI programs do not work */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;[[ZeptoOS_Documentation|Top]]&lt;br /&gt;
----&lt;br /&gt;
&lt;br /&gt;
==How to obtain a CN node number==&lt;br /&gt;
&lt;br /&gt;
This depends on what number one is interested in.&lt;br /&gt;
&lt;br /&gt;
===Pset rank===&lt;br /&gt;
&lt;br /&gt;
A pset rank is a number identifying a compute node within each ''pset'' (an I/O node and the compute nodes that communicate with it).  Note that on partitions larger than one pset, the pset ranks will not be unique.  Also, pset ranks do ''not'' start from &amp;lt;tt&amp;gt;0&amp;lt;/tt&amp;gt;; they start from &amp;lt;tt&amp;gt;1&amp;lt;/tt&amp;gt; for some mysterious reason (do not blame us &amp;amp;#8211; blame IBM&amp;amp;nbsp;:-).&lt;br /&gt;
&lt;br /&gt;
Pset rank is used as the last octet in the IP address on the tree network connecting the compute nodes and the I/O nodes (''x'' in &amp;lt;tt&amp;gt;192.168.1.&amp;lt;/tt&amp;gt;''x'').&lt;br /&gt;
&lt;br /&gt;
The pset rank is available on the compute nodes from &amp;lt;tt&amp;gt;/proc/personality.sh&amp;lt;/tt&amp;gt;, in the &amp;lt;tt&amp;gt;BG_RANK_IN_PSET&amp;lt;/tt&amp;gt; variable:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
#!/bin/sh&lt;br /&gt;
&lt;br /&gt;
. /proc/personality.sh&lt;br /&gt;
&lt;br /&gt;
echo &amp;quot;My pset rank is $BG_RANK_IN_PSET&amp;quot;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
From a C program it will be easier to use the binary personality available from &amp;lt;tt&amp;gt;/proc/personality&amp;lt;/tt&amp;gt;.  The definition of the structure can be found in &amp;lt;tt&amp;gt;/bgsys/drivers/ppcfloor/arch/include/common/bgp_personality.h&amp;lt;/tt&amp;gt;.  The pset rank is in &amp;lt;tt&amp;gt;Network_Config.RankInPSet&amp;lt;/tt&amp;gt;:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
#include &amp;lt;stdio.h&amp;gt;&lt;br /&gt;
#include &amp;lt;fcntl.h&amp;gt;&lt;br /&gt;
#include &amp;lt;unistd.h&amp;gt;&lt;br /&gt;
#include &amp;lt;common/bgp_personality.h&amp;gt;&lt;br /&gt;
&lt;br /&gt;
int main(void)&lt;br /&gt;
{&lt;br /&gt;
    _BGP_Personality_t personality;&lt;br /&gt;
    int fd;&lt;br /&gt;
&lt;br /&gt;
    if ((fd = open(&amp;quot;/proc/personality&amp;quot;, O_RDONLY)) == -1)&lt;br /&gt;
    {&lt;br /&gt;
        perror(&amp;quot;open&amp;quot;);&lt;br /&gt;
        return 1;&lt;br /&gt;
    }&lt;br /&gt;
    if (read(fd, &amp;amp;personality, sizeof(personality)) != sizeof(personality))&lt;br /&gt;
    {&lt;br /&gt;
        perror(&amp;quot;read&amp;quot;);&lt;br /&gt;
        close(fd);&lt;br /&gt;
        return 1;&lt;br /&gt;
    }&lt;br /&gt;
    close(fd);&lt;br /&gt;
&lt;br /&gt;
    printf(&amp;quot;My pset rank is %d\n&amp;quot;, personality.Network_Config.RankInPSet);&lt;br /&gt;
&lt;br /&gt;
    return 0;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
(compile the above with &amp;lt;tt&amp;gt;-I/bgsys/drivers/ppcfloor/arch/include&amp;lt;/tt&amp;gt;)&lt;br /&gt;
&lt;br /&gt;
===Torus rank===&lt;br /&gt;
&lt;br /&gt;
A torus rank is a number identifying a compute node within a whole partition.  In a way, it is much &amp;quot;nicer&amp;quot; than a pset rank since it is unique within a job and it also starts from &amp;lt;tt&amp;gt;0&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
The torus rank is easy to obtain from a C program: it is the &amp;lt;tt&amp;gt;Network_Config.Rank&amp;lt;/tt&amp;gt; field of the personality structure.&lt;br /&gt;
&lt;br /&gt;
Unfortunately, the torus rank is not available in &amp;lt;tt&amp;gt;/proc/personality.sh&amp;lt;/tt&amp;gt;, but a shell script can easily calculate it from other fields:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
TORUS_RANK=`echo $BG_PSETORG | awk &amp;quot;{print \\$1 + \\$2 * $BG_XSIZE + \&lt;br /&gt;
            \\$3 * $BG_XSIZE * $BG_YSIZE}&amp;quot;`&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===MPI rank===&lt;br /&gt;
&lt;br /&gt;
MPI rank should not be confused with a torus rank, even though by default the two are the same.  MPI rank is a property of a process, ''not'' node.  If one submits a job in the &amp;lt;tt&amp;gt;VN&amp;lt;/tt&amp;gt; or &amp;lt;tt&amp;gt;DUAL&amp;lt;/tt&amp;gt; mode, there will be multiple MPI tasks per node, obviously each with a different MPI rank.  Also, using the &amp;lt;tt&amp;gt;BG_MAPPING&amp;lt;/tt&amp;gt; environment variable changes the mapping between the torus coordinates and MPI ranks.&lt;br /&gt;
&lt;br /&gt;
While obtaining MPI rank from an MPI application is trivial, how to obtain it from a shell script?&lt;br /&gt;
&lt;br /&gt;
One way would be to invoke a simple C program:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
#include &amp;lt;stdio.h&amp;gt;&lt;br /&gt;
#include &amp;quot;zoid_api.h&amp;quot;&lt;br /&gt;
&lt;br /&gt;
int main(void)&lt;br /&gt;
{&lt;br /&gt;
    if (__zoid_init())&lt;br /&gt;
        return 1;&lt;br /&gt;
    printf(&amp;quot;%d\n&amp;quot;, __zoid_my_rank());&lt;br /&gt;
    return 0;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
(compile with &amp;lt;tt&amp;gt;-I&amp;lt;/tt&amp;gt;''path_to_ZeptoOS''&amp;lt;tt&amp;gt;/packages/zoid/prebuilt -L&amp;lt;/tt&amp;gt;''path_to_ZeptoOS''&amp;lt;tt&amp;gt;/packages/zoid/prebuilt -lzoid_cn&amp;lt;/tt&amp;gt;)&lt;br /&gt;
&lt;br /&gt;
A slight disadvantage of this approach is that &amp;lt;tt&amp;gt;__zoid_init&amp;lt;/tt&amp;gt; registers the process with the ZOID daemon on the I/O node, which is an overhead we do not need.  Another solution, without using any binaries, is as follows:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
MPI_RANK=`echo $CONTROL_INIT | awk -F, '{print $4}'`&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This has a disadvantage of using internal ZOID variables which are not guaranteed to be supported in future releases.&lt;br /&gt;
&lt;br /&gt;
==How to open a socket from a CN to the outside world==&lt;br /&gt;
&lt;br /&gt;
ZOID provides IP packet forwarding between the compute nodes and the I/O nodes.  However, because the compute nodes use non-routable IP addresses (&amp;lt;tt&amp;gt;192.168.1.&amp;lt;/tt&amp;gt;''x''), they cannot communicate directly with the outside world.&lt;br /&gt;
&lt;br /&gt;
The most transparent solution to this problem is to perform network address translation (NAT) on the I/O nodes using the Linux kernel netfilter infrastructure.  We used to enable this by default, but experiments have shown it to have a detrimental effect on the overall performance of the TCP/IP stack on the I/O nodes, slowing down access to the network filesystems.&lt;br /&gt;
&lt;br /&gt;
To enable the translation, pass &amp;lt;tt&amp;gt;ZOID_NAT_ENABLE&amp;lt;/tt&amp;gt; environment variable when submitting a job.  An administrator can also enable this option permanently in the [[ZOID#opt_enable_nat|config file]].&lt;br /&gt;
&lt;br /&gt;
==How to obtain a Cobalt job ID==&lt;br /&gt;
&lt;br /&gt;
Cobalt passes the job id to the application processes launched on the compute nodes using the &amp;lt;tt&amp;gt;COBALT_JOBID&amp;lt;/tt&amp;gt; environment variable.&lt;br /&gt;
&lt;br /&gt;
This variable is also accessible from the [[ZOID#User script|user script]] running on the I/O nodes, using the &amp;lt;tt&amp;gt;ZOID_JOB_ENV&amp;lt;/tt&amp;gt; variable:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
COBALT_JOBID=`echo $ZOID_JOB_ENV | sed 's/^.*COBALT_JOBID=\([^:]*\)/\1/'`&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Why large MPI processes do not work==&lt;br /&gt;
&lt;br /&gt;
A common reason might be that they do not have enough memory to run.  MPI processes run within the Big Memory region, which is limited to 256&amp;amp;nbsp;MB by default.  See the [[Kernel#Kernel (command line) parameters|Kernel]] section to learn how to change that; the parameter to use is &amp;lt;tt&amp;gt;flatmemsizeMB&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
[[ZeptoOS_Documentation|Top]]&lt;/div&gt;</summary>
		<author><name>Iskra</name></author>
	</entry>
	<entry>
		<id> /zeptoos/index.php?title=MPICH,_DCMF,_and_SPI&amp;diff=575</id>
		<title>MPICH, DCMF, and SPI</title>
		<link rel="alternate" type="text/html" href=" /zeptoos/index.php?title=MPICH,_DCMF,_and_SPI&amp;diff=575"/>
		<updated>2009-05-07T20:40:52Z</updated>

		<summary type="html">&lt;p&gt;Iskra: /* ZCB and Big memory */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;[[Testing]] | [[ZeptoOS_Documentation|Top]] | [[Kernel]]&lt;br /&gt;
----&lt;br /&gt;
&lt;br /&gt;
==Introduction==&lt;br /&gt;
&lt;br /&gt;
To support high performance computing (HPC) applications, specifically MPI applications, we have ported IBM CNK's communication software stack to the ZeptoOS compute node Linux environment.  MPICH used in this ZeptoOS release is mpich2-1.0.7 with IBM patches. It is reasonably stable, and the performance of MPI applications on the ZeptoOS compute node Linux is comparable to that on CNK.  While there are some limitations at the moment, there are benefits as well.&lt;br /&gt;
&lt;br /&gt;
Benefits:&lt;br /&gt;
* No limitation on the number of threads&lt;br /&gt;
** 4 or more OpenMP threads per node&lt;br /&gt;
** Additional threads as I/O or backgroup tasks&lt;br /&gt;
* It is Linux!&lt;br /&gt;
** Debugging tools such as gdb, strace, etc&lt;br /&gt;
** Various file systems, such as ramfs&lt;br /&gt;
&lt;br /&gt;
Current limitations:&lt;br /&gt;
* Only the SMP mode is supported&lt;br /&gt;
* Shared libraries are not provided now&lt;br /&gt;
* No binary compatibility between CNK and ZeptoOS CN Linux&lt;br /&gt;
&lt;br /&gt;
We will support a VN-equivalent mode (multiple MPI tasks per node) and provide shared libraries in a future release.&lt;br /&gt;
&lt;br /&gt;
As in IBM CNK environment, Deep Computing Messaging Framework (DCMF) and System Programming Interface (SPI) are available.  It is possible to write a DCMF code or a SPI code directly if necessary. DCMF is a communication library that provides non-blocking operations. Please refer to the [http://dcmf.anl-external.org/wiki/index.php/Main_Page DCMF wiki] for details.  We are using DCMF version 1.0.0 in the current ZeptoOS release, which is older than the DCMF in the current driver release (V1R3M0). SPI is the lowest-level user space API for the torus DMA, collective network, BGP-specifc lock mechanisms, and other compute node specific features.  There is no public document on SPI available at the moment, but almost all header files and source code is available. Internally, MPICH depends on DMCF, which in turn depends on SPI.  We will say more about it [[#Software stack layout|later]].&lt;br /&gt;
&lt;br /&gt;
===ZCB and Big memory===&lt;br /&gt;
&lt;br /&gt;
MPI application running under the ZeptoOS compute node environment (technically, applications that require the DMA operation or a maximum memory bandwidth) need to be configured as Zepto Compute Binaries (ZCB).  This is done using the &amp;lt;tt&amp;gt;zelftool&amp;lt;/tt&amp;gt;, invoked behind the scenes when linking a binary using the ZeptoOS MPI compiler wrapper scripts (&amp;lt;tt&amp;gt;zmpicc&amp;lt;/tt&amp;gt;, etc).&lt;br /&gt;
&lt;br /&gt;
ZeptoOS compute node kernel treats ZCB executables differently from ordinary processes. It creates a special memory mapping region called big memory, which is covered by large pages with semi-static TLB entries, and it loads all applications sections to the big memory region. Big memory region has virtually no TLB misses and it also enables DMA operations.&lt;br /&gt;
&lt;br /&gt;
Some system calls will not work correctly if used from a ZCB process, in particular &amp;lt;tt&amp;gt;fork&amp;lt;/tt&amp;gt; (but creating threads does work).  Also, being a separate memory region set up at kernel boot time, the size of big memory is fixed.  It is set to 256&amp;amp;nbsp;MB by default, which could be too small for larger MPI tasks; it can be [[FAQ#Why large MPI programs do not work|increased]] before booting a partition, at the expense of the ordinary Linux paged memory.&lt;br /&gt;
&lt;br /&gt;
==Compiling HPC applications==&lt;br /&gt;
&lt;br /&gt;
While the same compiler can be used as for the IBM CNK, ZeptoOS compute node environment requires linking with ZeptoOS-specific communication libraries (applications linked with the CNK MPI will not work on ZeptoOS).&lt;br /&gt;
&lt;br /&gt;
===Compiler wrapper scripts===&lt;br /&gt;
&lt;br /&gt;
We provide compiler wrapper scripts which automatically link with appropriate libraries from the ZeptoOS installation directory.  We provide the same set of wrapper scripts that IBM provides, with an extra &amp;lt;tt&amp;gt;z&amp;lt;/tt&amp;gt; prefix:&lt;br /&gt;
&lt;br /&gt;
; zmpicc, zmpicxx, zmpif77, zmpif90&lt;br /&gt;
: Wrapper scripts that invoke BGP-enhanced GNU compilers&lt;br /&gt;
&lt;br /&gt;
; zmpixlc, zmpixlcxx, zmpixlf2003, zmpixlf77, zmpixlf90, zmpixlf95&lt;br /&gt;
: Wrapper scripts that invoke IBM XL compilers&lt;br /&gt;
&lt;br /&gt;
; zmpixlc_r, zmpixlcxx_r, zmpixlf2003_r, zmpixlf77_r, zmpixlf90_r, zmpixlf95_r&lt;br /&gt;
: Wrapper scripts that invoke IBM XL compilers (thread safe compilation for OpenMP)&lt;br /&gt;
&lt;br /&gt;
To get insight into the internals of these scripts, invoke them with the &amp;lt;tt&amp;gt;-show&amp;lt;/tt&amp;gt; option.&lt;br /&gt;
&lt;br /&gt;
====A compilation example====&lt;br /&gt;
&lt;br /&gt;
Understanding build system on a program might take some time, but there is nothing special to compile a program for ZeptoOS.&lt;br /&gt;
&lt;br /&gt;
Here is a real-world example of how to build a well-known [http://climate.lanl.gov/Models/POP/ Parallel Ocean Program (POP)].&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
$ wget http://climate.lanl.gov/Models/POP/POP_2.0.1.tar.Z&lt;br /&gt;
$ tar xvfz POP_2.0.1.tar.Z &amp;amp;&amp;amp; cd pop&lt;br /&gt;
$ ./setup_run_dir ztest &amp;amp;&amp;amp; cd ztest&lt;br /&gt;
$ edit ibm_mpi.gnu   # see the patch below&lt;br /&gt;
$ export ARCHDIR=ibm_mpi&lt;br /&gt;
$ make   # takes a while&lt;br /&gt;
$ edit pop_in   # test data set&lt;br /&gt;
-  nprocs_clinic = 4&lt;br /&gt;
-  nprocs_tropic = 4&lt;br /&gt;
+  nprocs_clinic = 64&lt;br /&gt;
+  nprocs_tropic = 64&lt;br /&gt;
$ cqsub -n 64 -t 10 -k &amp;lt;zepto_profile&amp;gt; ./pop&lt;br /&gt;
&lt;br /&gt;
--------------------&lt;br /&gt;
--- orig/ibm_mpi.gnu    2009-04-15 15:01:58.666457601 -0500&lt;br /&gt;
+++ ztest/ibm_mpi.gnu    2009-04-15 14:17:58.099132435 -0500&lt;br /&gt;
@@ -6,17 +6,18 @@&lt;br /&gt;
# will someday be a file which is a cookbook in Q&amp;amp;A style: &amp;quot;How do I do X?&amp;quot;&lt;br /&gt;
# is followed by something like &amp;quot;Go to file Y and add Z to line NNN.&amp;quot;&lt;br /&gt;
#&lt;br /&gt;
-FC = mpxlf90_r&lt;br /&gt;
-LD = mpxlf90_r&lt;br /&gt;
-CC = mpcc_r&lt;br /&gt;
-Cp = /usr/bin/cp&lt;br /&gt;
-Cpp = /usr/ccs/lib/cpp -P&lt;br /&gt;
+ZPATH=&amp;lt;zepto_dir&amp;gt;&lt;br /&gt;
+FC = $(ZPATH)/zmpixlf90&lt;br /&gt;
+LD = $(ZPATH)/zmpixlf90&lt;br /&gt;
+CC = $(ZPATH)/zmpixlc&lt;br /&gt;
+Cp = /bin/cp&lt;br /&gt;
+Cpp = /usr/bin/cpp -P&lt;br /&gt;
AWK = /usr/bin/awk&lt;br /&gt;
-ABI = -q64&lt;br /&gt;
+#ABI = -q64&lt;br /&gt;
COMMDIR = mpi&lt;br /&gt;
&lt;br /&gt;
-NETCDFINC = -I/usr/local/include&lt;br /&gt;
-NETCDFLIB = -L/usr/local/lib&lt;br /&gt;
+NETCDFINC = -I/soft/apps/netcdf-4.0/include/&lt;br /&gt;
+NETCDFLIB = -L/soft/apps/netcdf-4.0/lib&lt;br /&gt;
&lt;br /&gt;
#  Enable MPI library for parallel code, yes/no.&lt;br /&gt;
&lt;br /&gt;
@@ -58,7 +59,8 @@&lt;br /&gt;
#&lt;br /&gt;
#----------------------------------------------------------------------------&lt;br /&gt;
&lt;br /&gt;
-FBASE = $(ABI) -qarch=auto -qnosave -bmaxdata:0x80000000 $(NETCDFINC) -I$(ObjDepDir)&lt;br /&gt;
+#FBASE = $(ABI) -qarch=auto -qnosave -bmaxdata:0x80000000 $(NETCDFINC) -I$(ObjDepDir)&lt;br /&gt;
+FBASE = $(ABI) -qarch=auto -qnosave  $(NETCDFINC) -I$(ObjDepDir)&lt;br /&gt;
&lt;br /&gt;
ifeq ($(TRAP_FPE),yes)&lt;br /&gt;
  FBASE := $(FBASE) -qflttrap=overflow:zerodivide:enable -qspillsize=32704&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Compiling without the wrapper scripts===&lt;br /&gt;
&lt;br /&gt;
If one wishes to invoke the compiler directly, please make sure that the Makefile or build environment points to ZeptoOS header files and libraries correctly. An example would be:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
$ /bgsys/drivers/ppcfloor/gnu-linux/bin/powerpc-bgp-linux-gcc \&lt;br /&gt;
-o mpi-test-linux -Wall -O3 -I&amp;lt;zepto_dir&amp;gt;/include mpi-test.c \&lt;br /&gt;
-L&amp;lt;zepto_dir&amp;gt;/lib -lmpich.zcl -ldcmfcoll.zcl -ldcmf.zcl -lSPI.zcl -lzcl \&lt;br /&gt;
-lzoid_cn -lrt -lpthread -lm&lt;br /&gt;
$ &amp;lt;zepto_dir&amp;gt;/bin/zelftool -e mpi-test-linux&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
'''Notes:''' &lt;br /&gt;
* Replace &amp;lt;tt&amp;gt;&amp;lt;zepto_dir&amp;gt;&amp;lt;/tt&amp;gt; with your actuall ZeptoOS install path.&lt;br /&gt;
* Do not forget to call the &amp;lt;tt&amp;gt;zelftool&amp;lt;/tt&amp;gt; utility, which makes the executable a Zepto Compute Binary.&lt;br /&gt;
&amp;lt;!--&lt;br /&gt;
The file layout in the zepto install path would be:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
|-- bin&lt;br /&gt;
|   |-- zelftool&lt;br /&gt;
|-- include&lt;br /&gt;
|   |-- dcmf.h&lt;br /&gt;
|   |-- dcmf_collectives.h&lt;br /&gt;
|   |-- dcmf_coremath.h&lt;br /&gt;
|   |-- dcmf_globalcollectives.h&lt;br /&gt;
|   |-- dcmf_multisend.h&lt;br /&gt;
|   |-- dcmf_optimath.h&lt;br /&gt;
|   |-- mpe_thread.h&lt;br /&gt;
|   |-- mpi.h&lt;br /&gt;
|   |-- mpi.mod&lt;br /&gt;
|   |-- mpi_base.mod&lt;br /&gt;
|   |-- mpi_constants.mod&lt;br /&gt;
|   |-- mpi_sizeofs.mod&lt;br /&gt;
|   |-- mpicxx.h&lt;br /&gt;
|   |-- mpif.h&lt;br /&gt;
|   |-- mpio.h&lt;br /&gt;
|   |-- mpiof.h&lt;br /&gt;
|   `-- mpix.h&lt;br /&gt;
`-- lib&lt;br /&gt;
    |-- libSPI.zcl.a&lt;br /&gt;
    |-- libcxxmpich.zcl.a&lt;br /&gt;
    |-- libdcmf.zcl.a&lt;br /&gt;
    |-- libdcmfcoll.zcl.a&lt;br /&gt;
    |-- libfmpich.zcl.a&lt;br /&gt;
    |-- libfmpich_.zcl.a&lt;br /&gt;
    |-- libmpich.zcl.a&lt;br /&gt;
    |-- libmpich.zclf90.a&lt;br /&gt;
    |-- libzcl.a&lt;br /&gt;
    `-- libzoid_cn.a&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
--&amp;gt;&lt;br /&gt;
==Building MPICH, DCMF, and SPI libraries==&lt;br /&gt;
&lt;br /&gt;
We provide all the necessary source code to build MPICH, DCMF, and SPI.  To build these libraries, just type:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
$ make -C comm rebuild-target&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
It may take half an hour to an hour to complete the build process, depending on what file system you are using (i.e., GPFS is a lot slower than a local file system).&lt;br /&gt;
&lt;br /&gt;
The &amp;lt;tt&amp;gt;rebuild-target&amp;lt;/tt&amp;gt; target does not know anything about the existing installation directory; it only copies the built libraries and header files to the &amp;lt;tt&amp;gt;comm/tmp&amp;lt;/tt&amp;gt; directory. To install the newly built libraries, do the following:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
$ make -C comm update-prebuilt&lt;br /&gt;
$ python install.py &amp;lt;zepto_dir&amp;gt;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The &amp;lt;tt&amp;gt;update-prebuilt&amp;lt;/tt&amp;gt; target basically copies the files from the &amp;lt;tt&amp;gt;comm/tmp&amp;lt;/tt&amp;gt; directory to the &amp;lt;tt&amp;gt;comm/prebuilt&amp;lt;/tt&amp;gt; directory, which is where the &amp;lt;tt&amp;gt;install.py&amp;lt;/tt&amp;gt; script looks for to copy the files to &amp;lt;tt&amp;gt;&amp;lt;zepto_dir&amp;gt;&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
==Software stack layout==&lt;br /&gt;
&lt;br /&gt;
[[Image:Zepto-Comm-Stack.png|right]]&lt;br /&gt;
&lt;br /&gt;
The figure on the right depicts the layout of the communication software stack in the ZeptoOS compute node environment.  This is very similar to the IBM CNK's stack, with the exception of an extra ZEPTO SPI layer, and the use of Linux instead of CNK.&lt;br /&gt;
&lt;br /&gt;
Since MPICH is a well-known software package we will not discuss it here, but we will briefly describe the DCMF and SPI components:&lt;br /&gt;
&lt;br /&gt;
* DCMF&lt;br /&gt;
** Stands for Deep Computing Messaging Framework&lt;br /&gt;
** Developed by IBM originally for Blue Gene architecture &lt;br /&gt;
** Hardware initialization, query functions&lt;br /&gt;
** Supports BGP Torus DMA, collective network&lt;br /&gt;
** Provides timer&lt;br /&gt;
** Supports non-blocking collective operations&lt;br /&gt;
** BGP MPICH uses DCMF internally (IBM provides a glue layer)&lt;br /&gt;
* SPI&lt;br /&gt;
** Stands for System Programming Interface&lt;br /&gt;
** Developed by IBM. BGP-specific code.&lt;br /&gt;
** Kernel interfaces &amp;amp;#8211; DMA control, lockbox, etc&lt;br /&gt;
** DMA related definitions &lt;br /&gt;
*** can be used in both user space and kernel space&lt;br /&gt;
** RAS, BGP personality, mapping related functions&lt;br /&gt;
&lt;br /&gt;
BGP SPI was designed specifically for IBM CNK, so it is not compatible with Linux.  ZEPTO SPI is a thin software layer that absorbs the differences between the CNK and Linux or drops the requests that Linux cannot handle.&lt;br /&gt;
&lt;br /&gt;
==Source code==&lt;br /&gt;
&lt;br /&gt;
The source code and header files of DCMF and SPI can be found in the &amp;lt;tt&amp;gt;comm&amp;lt;/tt&amp;gt; directory. The source code of MPICH is in &amp;lt;tt&amp;gt;DCMF/lib/mpich2/mpich2-1.0.7.tar.gz&amp;lt;/tt&amp;gt;, which will be extracted at build time.&lt;br /&gt;
&lt;br /&gt;
The DCMF source code is located in &amp;lt;tt&amp;gt;DCMF/sys/&amp;lt;/tt&amp;gt;. DCMF core source code is in &amp;lt;tt&amp;gt;DCMF/sys/messaging/&amp;lt;/tt&amp;gt;. Component Collective Messaging Interface (CCMI) is part of DCMF and its source code is in &amp;lt;tt&amp;gt;DCMF/sys/collectives/&amp;lt;/tt&amp;gt;. Test codes can be found in &amp;lt;tt&amp;gt;DCMF/sys/collectives/tests/&amp;lt;/tt&amp;gt; for CCMI and &amp;lt;tt&amp;gt;DCMF/sys/messaging/tests/&amp;lt;/tt&amp;gt;. Those test codes can be a good example for DCMF/CCMI programming.&lt;br /&gt;
&lt;br /&gt;
SPI headers are in &amp;lt;tt&amp;gt;arch-runtime/arch/&amp;lt;/tt&amp;gt; and SPI source code is in &amp;lt;tt&amp;gt;comm/arch-runtime/runtime/&amp;lt;/tt&amp;gt;.  The source code of the ZEPTO SPI layer is in &amp;lt;tt&amp;gt;arch-runtime/zcl_spi/&amp;lt;/tt&amp;gt;, while the header files are in &amp;lt;tt&amp;gt;arch-runtime/arch/include/zepto/&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Here is an overview of the directory tree:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
comm&lt;br /&gt;
|-- DCMF&lt;br /&gt;
|   |-- lib&lt;br /&gt;
|   |   |-- dev&lt;br /&gt;
|   |   `-- mpich2&lt;br /&gt;
|   |       `-- make&lt;br /&gt;
|   |-- sys&lt;br /&gt;
|   |   |-- collectives&lt;br /&gt;
|   |   |   |-- adaptor&lt;br /&gt;
|   |   |   |-- kernel&lt;br /&gt;
|   |   |   |-- tests&lt;br /&gt;
|   |   |   `-- tools&lt;br /&gt;
|   |   |-- include&lt;br /&gt;
|   |   `-- messaging&lt;br /&gt;
|   |       |-- devices&lt;br /&gt;
|   |       |-- messager&lt;br /&gt;
|   |       |-- protocols&lt;br /&gt;
|   |       |-- queueing&lt;br /&gt;
|   |       |-- sysdep&lt;br /&gt;
|   |       `-- tests&lt;br /&gt;
|-- arch-runtime&lt;br /&gt;
|   |-- arch&lt;br /&gt;
|   |   `-- include&lt;br /&gt;
|   |       |-- bpcore&lt;br /&gt;
|   |       |-- cnk&lt;br /&gt;
|   |       |-- common&lt;br /&gt;
|   |       |-- spi&lt;br /&gt;
|   |       `-- zepto&lt;br /&gt;
|   |-- runtime&lt;br /&gt;
|   |-- testcodes&lt;br /&gt;
|   `-- zcl_spi&lt;br /&gt;
`-- testcodes&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Debug output===&lt;br /&gt;
&lt;br /&gt;
ZeptoOS versions of SPI and DCMF have a built-in debug output.  The output is disabled by default, and can be enabled by setting the environment variable &amp;lt;tt&amp;gt;ZEPTO_TRACE&amp;lt;/tt&amp;gt; when submitting a job.  The integer value of the variable indicates the debug level (a higher number results in more debug output).&lt;br /&gt;
&lt;br /&gt;
An example:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
$ cqsub -k &amp;lt;zepto_profile&amp;gt; -n 64 -t 10 ... -e ZEPTO_TRACE=2 ./a.out&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
[[Testing]] | [[ZeptoOS_Documentation|Top]] | [[Kernel]]&lt;/div&gt;</summary>
		<author><name>Iskra</name></author>
	</entry>
	<entry>
		<id> /zeptoos/index.php?title=FAQ&amp;diff=574</id>
		<title>FAQ</title>
		<link rel="alternate" type="text/html" href=" /zeptoos/index.php?title=FAQ&amp;diff=574"/>
		<updated>2009-05-07T20:32:15Z</updated>

		<summary type="html">&lt;p&gt;Iskra: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;[[ZeptoOS_Documentation|Top]]&lt;br /&gt;
----&lt;br /&gt;
&lt;br /&gt;
==How to obtain a CN node number==&lt;br /&gt;
&lt;br /&gt;
This depends on what number one is interested in.&lt;br /&gt;
&lt;br /&gt;
===Pset rank===&lt;br /&gt;
&lt;br /&gt;
A pset rank is a number identifying a compute node within each ''pset'' (an I/O node and the compute nodes that communicate with it).  Note that on partitions larger than one pset, the pset ranks will not be unique.  Also, pset ranks do ''not'' start from &amp;lt;tt&amp;gt;0&amp;lt;/tt&amp;gt;; they start from &amp;lt;tt&amp;gt;1&amp;lt;/tt&amp;gt; for some mysterious reason (do not blame us &amp;amp;#8211; blame IBM&amp;amp;nbsp;:-).&lt;br /&gt;
&lt;br /&gt;
Pset rank is used as the last octet in the IP address on the tree network connecting the compute nodes and the I/O nodes (''x'' in &amp;lt;tt&amp;gt;192.168.1.&amp;lt;/tt&amp;gt;''x'').&lt;br /&gt;
&lt;br /&gt;
The pset rank is available on the compute nodes from &amp;lt;tt&amp;gt;/proc/personality.sh&amp;lt;/tt&amp;gt;, in the &amp;lt;tt&amp;gt;BG_RANK_IN_PSET&amp;lt;/tt&amp;gt; variable:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
#!/bin/sh&lt;br /&gt;
&lt;br /&gt;
. /proc/personality.sh&lt;br /&gt;
&lt;br /&gt;
echo &amp;quot;My pset rank is $BG_RANK_IN_PSET&amp;quot;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
From a C program it will be easier to use the binary personality available from &amp;lt;tt&amp;gt;/proc/personality&amp;lt;/tt&amp;gt;.  The definition of the structure can be found in &amp;lt;tt&amp;gt;/bgsys/drivers/ppcfloor/arch/include/common/bgp_personality.h&amp;lt;/tt&amp;gt;.  The pset rank is in &amp;lt;tt&amp;gt;Network_Config.RankInPSet&amp;lt;/tt&amp;gt;:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
#include &amp;lt;stdio.h&amp;gt;&lt;br /&gt;
#include &amp;lt;fcntl.h&amp;gt;&lt;br /&gt;
#include &amp;lt;unistd.h&amp;gt;&lt;br /&gt;
#include &amp;lt;common/bgp_personality.h&amp;gt;&lt;br /&gt;
&lt;br /&gt;
int main(void)&lt;br /&gt;
{&lt;br /&gt;
    _BGP_Personality_t personality;&lt;br /&gt;
    int fd;&lt;br /&gt;
&lt;br /&gt;
    if ((fd = open(&amp;quot;/proc/personality&amp;quot;, O_RDONLY)) == -1)&lt;br /&gt;
    {&lt;br /&gt;
        perror(&amp;quot;open&amp;quot;);&lt;br /&gt;
        return 1;&lt;br /&gt;
    }&lt;br /&gt;
    if (read(fd, &amp;amp;personality, sizeof(personality)) != sizeof(personality))&lt;br /&gt;
    {&lt;br /&gt;
        perror(&amp;quot;read&amp;quot;);&lt;br /&gt;
        close(fd);&lt;br /&gt;
        return 1;&lt;br /&gt;
    }&lt;br /&gt;
    close(fd);&lt;br /&gt;
&lt;br /&gt;
    printf(&amp;quot;My pset rank is %d\n&amp;quot;, personality.Network_Config.RankInPSet);&lt;br /&gt;
&lt;br /&gt;
    return 0;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
(compile the above with &amp;lt;tt&amp;gt;-I/bgsys/drivers/ppcfloor/arch/include&amp;lt;/tt&amp;gt;)&lt;br /&gt;
&lt;br /&gt;
===Torus rank===&lt;br /&gt;
&lt;br /&gt;
A torus rank is a number identifying a compute node within a whole partition.  In a way, it is much &amp;quot;nicer&amp;quot; than a pset rank since it is unique within a job and it also starts from &amp;lt;tt&amp;gt;0&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
The torus rank is easy to obtain from a C program: it is the &amp;lt;tt&amp;gt;Network_Config.Rank&amp;lt;/tt&amp;gt; field of the personality structure.&lt;br /&gt;
&lt;br /&gt;
Unfortunately, the torus rank is not available in &amp;lt;tt&amp;gt;/proc/personality.sh&amp;lt;/tt&amp;gt;, but a shell script can easily calculate it from other fields:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
TORUS_RANK=`echo $BG_PSETORG | awk &amp;quot;{print \\$1 + \\$2 * $BG_XSIZE + \&lt;br /&gt;
            \\$3 * $BG_XSIZE * $BG_YSIZE}&amp;quot;`&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===MPI rank===&lt;br /&gt;
&lt;br /&gt;
MPI rank should not be confused with a torus rank, even though by default the two are the same.  MPI rank is a property of a process, ''not'' node.  If one submits a job in the &amp;lt;tt&amp;gt;VN&amp;lt;/tt&amp;gt; or &amp;lt;tt&amp;gt;DUAL&amp;lt;/tt&amp;gt; mode, there will be multiple MPI tasks per node, obviously each with a different MPI rank.  Also, using the &amp;lt;tt&amp;gt;BG_MAPPING&amp;lt;/tt&amp;gt; environment variable changes the mapping between the torus coordinates and MPI ranks.&lt;br /&gt;
&lt;br /&gt;
While obtaining MPI rank from an MPI application is trivial, how to obtain it from a shell script?&lt;br /&gt;
&lt;br /&gt;
One way would be to invoke a simple C program:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
#include &amp;lt;stdio.h&amp;gt;&lt;br /&gt;
#include &amp;quot;zoid_api.h&amp;quot;&lt;br /&gt;
&lt;br /&gt;
int main(void)&lt;br /&gt;
{&lt;br /&gt;
    if (__zoid_init())&lt;br /&gt;
        return 1;&lt;br /&gt;
    printf(&amp;quot;%d\n&amp;quot;, __zoid_my_rank());&lt;br /&gt;
    return 0;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
(compile with &amp;lt;tt&amp;gt;-I&amp;lt;/tt&amp;gt;''path_to_ZeptoOS''&amp;lt;tt&amp;gt;/packages/zoid/prebuilt -L&amp;lt;/tt&amp;gt;''path_to_ZeptoOS''&amp;lt;tt&amp;gt;/packages/zoid/prebuilt -lzoid_cn&amp;lt;/tt&amp;gt;)&lt;br /&gt;
&lt;br /&gt;
A slight disadvantage of this approach is that &amp;lt;tt&amp;gt;__zoid_init&amp;lt;/tt&amp;gt; registers the process with the ZOID daemon on the I/O node, which is an overhead we do not need.  Another solution, without using any binaries, is as follows:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
MPI_RANK=`echo $CONTROL_INIT | awk -F, '{print $4}'`&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This has a disadvantage of using internal ZOID variables which are not guaranteed to be supported in future releases.&lt;br /&gt;
&lt;br /&gt;
==How to open a socket from a CN to the outside world==&lt;br /&gt;
&lt;br /&gt;
ZOID provides IP packet forwarding between the compute nodes and the I/O nodes.  However, because the compute nodes use non-routable IP addresses (&amp;lt;tt&amp;gt;192.168.1.&amp;lt;/tt&amp;gt;''x''), they cannot communicate directly with the outside world.&lt;br /&gt;
&lt;br /&gt;
The most transparent solution to this problem is to perform network address translation (NAT) on the I/O nodes using the Linux kernel netfilter infrastructure.  We used to enable this by default, but experiments have shown it to have a detrimental effect on the overall performance of the TCP/IP stack on the I/O nodes, slowing down access to the network filesystems.&lt;br /&gt;
&lt;br /&gt;
To enable the translation, pass &amp;lt;tt&amp;gt;ZOID_NAT_ENABLE&amp;lt;/tt&amp;gt; environment variable when submitting a job.  An administrator can also enable this option permanently in the [[ZOID#opt_enable_nat|config file]].&lt;br /&gt;
&lt;br /&gt;
==How to obtain a Cobalt job ID==&lt;br /&gt;
&lt;br /&gt;
Cobalt passes the job id to the application processes launched on the compute nodes using the &amp;lt;tt&amp;gt;COBALT_JOBID&amp;lt;/tt&amp;gt; environment variable.&lt;br /&gt;
&lt;br /&gt;
This variable is also accessible from the [[ZOID#User script|user script]] running on the I/O nodes, using the &amp;lt;tt&amp;gt;ZOID_JOB_ENV&amp;lt;/tt&amp;gt; variable:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
COBALT_JOBID=`echo $ZOID_JOB_ENV | sed 's/^.*COBALT_JOBID=\([^:]*\)/\1/'`&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Why large MPI programs do not work==&lt;br /&gt;
&lt;br /&gt;
A common reason might be that they do not have enough memory to run.  MPI programs run within the Big Memory region, which is limited to 256&amp;amp;nbsp;MB by default.  See the [[Kernel#Kernel (command line) parameters|Kernel]] section to learn how to change that; the parameter to use is &amp;lt;tt&amp;gt;flatmemsizeMB&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
[[ZeptoOS_Documentation|Top]]&lt;/div&gt;</summary>
		<author><name>Iskra</name></author>
	</entry>
	<entry>
		<id> /zeptoos/index.php?title=ZOID&amp;diff=573</id>
		<title>ZOID</title>
		<link rel="alternate" type="text/html" href=" /zeptoos/index.php?title=ZOID&amp;diff=573"/>
		<updated>2009-05-07T20:25:33Z</updated>

		<summary type="html">&lt;p&gt;Iskra: /* Configuration file */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;[[Ramdisk]] | [[ZeptoOS_Documentation|Top]] | [[(K)TAU]]&lt;br /&gt;
----&lt;br /&gt;
&lt;br /&gt;
==Introduction==&lt;br /&gt;
&lt;br /&gt;
ZOID is an I/O forwarding component of the ZeptoOS project.  Any communication between the compute nodes and the I/O nodes (job management, file I/O, sockets) is handled by ZOID.&lt;br /&gt;
&lt;br /&gt;
ZOID infrastructure consists of:&lt;br /&gt;
* A multithreaded &amp;lt;tt&amp;gt;zoid&amp;lt;/tt&amp;gt; daemon on the I/O nodes which performs I/O forwarding for the compute nodes and which also communicates with the service node to perform job management,&lt;br /&gt;
* &amp;lt;tt&amp;gt;control&amp;lt;/tt&amp;gt; daemon on the compute nodes which is responsible for job management tasks such as the launching of application processes, for the forwarding of &amp;lt;tt&amp;gt;stdin&amp;lt;/tt&amp;gt;/&amp;lt;tt&amp;gt;out&amp;lt;/tt&amp;gt;/&amp;lt;tt&amp;gt;err&amp;lt;/tt&amp;gt; data, and for forwarding of IP packets,&lt;br /&gt;
* &amp;lt;tt&amp;gt;zoid-fuse&amp;lt;/tt&amp;gt; daemon on the compute nodes which performs file I/O forwarding for POSIX-compliant applications.&lt;br /&gt;
&lt;br /&gt;
==User interface==&lt;br /&gt;
&lt;br /&gt;
ZOID is meant to be transparent to users, but there are a few optional mechanisms available to interact with it.&lt;br /&gt;
&lt;br /&gt;
===User script===&lt;br /&gt;
&lt;br /&gt;
Right before a job starts running, and right after the last process of a job has terminated, ZOID daemon attempts to invoke a ''user script'' on I/O nodes.  By default, the daemon invokes &amp;lt;tt&amp;gt;$HOME/zoid-user-script.sh&amp;lt;/tt&amp;gt; (this pathname can be [[#opt_user_script|changed]] by an administrator).  A single parameter is passed to the script: &amp;lt;tt&amp;gt;1&amp;lt;/tt&amp;gt; at the job startup, and &amp;lt;tt&amp;gt;0&amp;lt;/tt&amp;gt; at the termination.&lt;br /&gt;
&lt;br /&gt;
Information about the job will be passed to the script in the following environment variables:&lt;br /&gt;
; &amp;lt;tt&amp;gt;ZOID_JOB_EXEC&amp;lt;/tt&amp;gt;&lt;br /&gt;
: name of the job executable,&lt;br /&gt;
; &amp;lt;tt&amp;gt;ZOID_JOB_ARGS&amp;lt;/tt&amp;gt;&lt;br /&gt;
: job arguments, separated by colons (&amp;lt;tt&amp;gt;:&amp;lt;/tt&amp;gt;)&lt;br /&gt;
; &amp;lt;tt&amp;gt;ZOID_JOB_ENV&amp;lt;/tt&amp;gt;&lt;br /&gt;
: job environment variables, separated by colons (&amp;lt;tt&amp;gt;:&amp;lt;/tt&amp;gt;)&lt;br /&gt;
; &amp;lt;tt&amp;gt;ZOID_JOB_ID&amp;lt;/tt&amp;gt;&lt;br /&gt;
: BG/P control system job id ('''Note:''' this is generally different from the Cobalt job ID; see [[FAQ#How to obtain a Cobalt job ID|FAQ]] for the latter),&lt;br /&gt;
; &amp;lt;tt&amp;gt;ZOID_JOB_GLOBAL_SIZE&amp;lt;/tt&amp;gt;&lt;br /&gt;
: the number of processes in the job (the size of &amp;lt;tt&amp;gt;MPI_COMM_WORLD&amp;lt;/tt&amp;gt;),&lt;br /&gt;
; &amp;lt;tt&amp;gt;ZOID_JOB_LOCAL_SIZE&amp;lt;/tt&amp;gt;&lt;br /&gt;
: the number of job processes handled by this I/O node,&lt;br /&gt;
; &amp;lt;tt&amp;gt;ZOID_JOB_MODE&amp;lt;/tt&amp;gt;&lt;br /&gt;
: &amp;lt;tt&amp;gt;0&amp;lt;/tt&amp;gt; for SMP, &amp;lt;tt&amp;gt;1&amp;lt;/tt&amp;gt; for VN, and &amp;lt;tt&amp;gt;2&amp;lt;/tt&amp;gt; for DUAL,&lt;br /&gt;
; &amp;lt;tt&amp;gt;SHELL&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;PATH&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;USER&amp;lt;/tt&amp;gt;, and &amp;lt;tt&amp;gt;HOME&amp;lt;/tt&amp;gt;&lt;br /&gt;
: will also be set...&lt;br /&gt;
&lt;br /&gt;
'''Note:''' the user script is invoked ''synchronously'' by the daemon, i.e., the job will not start running until the script terminates.  If one needs some processes to run on the I/O nodes while the job is running, they should be started in the background (&amp;amp;amp;).&lt;br /&gt;
&lt;br /&gt;
'''Note 2:''' for this feature to work, [[#The /bin.rd/update_passwd_file.sh file|update_passwd_file.sh]] must be working correctly.&lt;br /&gt;
&lt;br /&gt;
===File broadcast===&lt;br /&gt;
A &amp;lt;tt&amp;gt;/bin.rd/f2cn&amp;lt;/tt&amp;gt; command is available on the I/O nodes for a very efficient (hardware-assisted) broadcasting of files to all the compute nodes handled by the given I/O node.&lt;br /&gt;
&lt;br /&gt;
The command takes two arguments:&lt;br /&gt;
* absolute pathname to the input file on the I/O node,&lt;br /&gt;
* absolute pathname to the output file on the compute nodes.&lt;br /&gt;
&lt;br /&gt;
The input file does not need to be physically on the I/O node; it can be on a network filesystem mounted on the node.  The file will be created in the ramdisk of each compute node.&lt;br /&gt;
&lt;br /&gt;
The throughput is in practice limited by how fast the input file can be read; we have seen results in excess of 300&amp;amp;nbsp;MB/s for files residing in the I/O node ramdisk.&lt;br /&gt;
&lt;br /&gt;
'''Note:''' all the compute nodes in the pset must be up and running.  Do not use this command on ''incomplete'' partitions (e.g., a one-process job on a 64-node partition); this will likely hang the ZOID daemon.&lt;br /&gt;
&lt;br /&gt;
'''Note2:''' this feature can safely be used from within a [[#User script|user script]], so one can, e.g., pre-stage large binaries, like this:&lt;br /&gt;
&lt;br /&gt;
User script (&amp;lt;tt&amp;gt;$HOME/zoid-user-script.sh&amp;lt;/tt&amp;gt;):&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
#!/bin/sh&lt;br /&gt;
&lt;br /&gt;
if [ &amp;quot;$1&amp;quot; -eq &amp;quot;1&amp;quot; ]; then&lt;br /&gt;
    /bin.rd/f2cn $HOME/large_binary /tmp/large_binary&lt;br /&gt;
fi&lt;br /&gt;
exit 0&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Job script (submitted using Cobalt or mpirun):&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
#!/bin/sh&lt;br /&gt;
&lt;br /&gt;
chmod 755 /tmp/large_binary&lt;br /&gt;
/tmp/large_binary&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Performance counters===&lt;br /&gt;
&lt;br /&gt;
A &amp;lt;tt&amp;gt;/bin.rd/statquery&amp;lt;/tt&amp;gt; command is available on the I/O nodes for obtaining the performance counters of the I/O daemon.&lt;br /&gt;
&lt;br /&gt;
The command takes a single optional argument:&lt;br /&gt;
* the interval between successive queries, in seconds.&lt;br /&gt;
&lt;br /&gt;
If the argument is not provided, the command will terminate after the first query.&lt;br /&gt;
&lt;br /&gt;
Here is a sample output generated:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
Timestamp:                      1240439085.688831&lt;br /&gt;
Total messages sent:            5767&lt;br /&gt;
Total bytes sent:               7619170&lt;br /&gt;
Total messages received:        5717&lt;br /&gt;
Total bytes received:           72575&lt;br /&gt;
IP fwd messages sent:           196&lt;br /&gt;
IP fwd bytes sent:              5889&lt;br /&gt;
IP fwd messages received:       84&lt;br /&gt;
IP fwd bytes received:          6453&lt;br /&gt;
Stream messages sent:           65&lt;br /&gt;
Stream bytes sent:              520&lt;br /&gt;
Stream messages received:       65&lt;br /&gt;
Stream bytes received:          1416&lt;br /&gt;
Broadcast messages sent:        1&lt;br /&gt;
Broadcast bytes sent:           2437906&lt;br /&gt;
Internal messages sent:         193&lt;br /&gt;
Internal bytes sent:            39524&lt;br /&gt;
Internal messages received:     256&lt;br /&gt;
Internal bytes received:        1792&lt;br /&gt;
Plugin 5 messages sent:         0&lt;br /&gt;
Plugin 5 bytes sent:            0&lt;br /&gt;
Plugin 5 messages received:     0&lt;br /&gt;
Plugin 5 bytes received:        0&lt;br /&gt;
Plugin 2 messages sent:         5312&lt;br /&gt;
Plugin 2 bytes sent:            5135331&lt;br /&gt;
Plugin 2 messages received:     5312&lt;br /&gt;
Plugin 2 bytes received:        62914&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The meaning of the fields is as follows:&lt;br /&gt;
; Timestamp&lt;br /&gt;
: number of seconds and microseconds from the epoch, as returned by &amp;lt;tt&amp;gt;gettimeofday(2)&amp;lt;/tt&amp;gt;,&lt;br /&gt;
; IP fwd&lt;br /&gt;
: IP packet forwarding between compute nodes and I/O nodes,&lt;br /&gt;
; Stream&lt;br /&gt;
: &amp;lt;tt&amp;gt;stdin&amp;lt;/tt&amp;gt;/&amp;lt;tt&amp;gt;out&amp;lt;/tt&amp;gt;/&amp;lt;tt&amp;gt;err&amp;lt;/tt&amp;gt; streams,&lt;br /&gt;
; Broadcast&lt;br /&gt;
: [[#File broadcast|file broadcasts]],&lt;br /&gt;
; Internal&lt;br /&gt;
: job control messages, etc.&lt;br /&gt;
; Plugin 5&lt;br /&gt;
: internal &amp;lt;tt&amp;gt;mapping&amp;lt;/tt&amp;gt; plug-in, used by MPI,&lt;br /&gt;
; Plugin 2&lt;br /&gt;
: &amp;lt;tt&amp;gt;unix&amp;lt;/tt&amp;gt; plugin (POSIX file I/O).&lt;br /&gt;
&lt;br /&gt;
The counters are 64-bit integers, so they will take a while to overflow :-).&lt;br /&gt;
&lt;br /&gt;
Example user script (&amp;lt;tt&amp;gt;$HOME/zoid-user-script.sh&amp;lt;/tt&amp;gt;) that samples the statistics every 60 seconds and writes them to a unique file:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
#!/bin/sh&lt;br /&gt;
&lt;br /&gt;
if [ &amp;quot;$1&amp;quot; -eq &amp;quot;1&amp;quot; ]; then&lt;br /&gt;
    /bin.rd/statquery 60 &amp;gt;$HOME/zoid_stats.$ZOID_JOB_ID.`hostname` &amp;amp;&lt;br /&gt;
fi&lt;br /&gt;
exit 0&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Administrator interface==&lt;br /&gt;
&lt;br /&gt;
===Configuration file===&lt;br /&gt;
&lt;br /&gt;
The &amp;lt;tt&amp;gt;zoid&amp;lt;/tt&amp;gt; I/O daemon accepts a number of command-line options that can be used to change its behavior.  They can be adjusted by editing the &amp;lt;tt&amp;gt;ramdisk/ION/ramdisk-add/etc/sysconfig/zoid&amp;lt;/tt&amp;gt; file and rebuilding the I/O node ramdisk:&lt;br /&gt;
&lt;br /&gt;
; &amp;lt;span id=&amp;quot;opt_buffer_size&amp;quot;&amp;gt;ZOID_BUFFER_SIZE (-b)&amp;lt;/span&amp;gt;&lt;br /&gt;
: Specifies the size of the buffers used for messages.  Because a separate buffer is needed for a request and a reply, and typically no more than one of these needs to be large, to save memory ZOID supports buffers of two sizes: a small one (4&amp;amp;nbsp;KB by default) and a large one (4&amp;amp;nbsp;MB+1&amp;amp;nbsp;KB by default &amp;amp;#8211; the 1&amp;amp;nbsp;KB is there to accommodate the headers).  Use a colon (&amp;lt;tt&amp;gt;:&amp;lt;/tt&amp;gt;) to separate the two sizes when customizing this value.  If desired, support for second buffer size can be disabled by providing only one value to this option.&lt;br /&gt;
; ZOID_ACK_THRESHOLD (-a)&lt;br /&gt;
: Specifies a size threshold for the rendezvous protocol for messages coming from the compute nodes, in the units of tree network packets (240 bytes of data each).  An eager protocol is used for messages below the threshold.  Messages above the threshold use flow control in the form of a rendezvous protocol with message acknowledgements; basically, the daemon will only receive one large message at a time, which improves the predictability and an overall throughput.  The daemon default for this option is to not use the acknowledgements, but the config file defaults to a value of &amp;lt;tt&amp;gt;8&amp;lt;/tt&amp;gt;, which is the size of the hardware FIFO buffer of the tree network device.  Set this option to 0 (or comment it out altogether) to disable message acknowledgements.&lt;br /&gt;
; &amp;lt;span id=&amp;quot;opt_modules&amp;quot;&amp;gt;ZOID_MODULES (-m)&amp;lt;/span&amp;gt;&lt;br /&gt;
: Specifies a &amp;lt;tt&amp;gt;:&amp;lt;/tt&amp;gt;-separated list of ZOID plug-ins to load.  This defaults to &amp;lt;tt&amp;gt;&amp;quot;unix_impl.so:unix_preload.so:mapping_impl.so:mapping_preload.so&amp;quot;&amp;lt;/tt&amp;gt; in the config file; do not remove any of these or basic system services will stop working.  The &amp;lt;tt&amp;gt;unix&amp;lt;/tt&amp;gt; plug-in provide POSIX file I/O support, while &amp;lt;tt&amp;gt;mapping&amp;lt;/tt&amp;gt; is used by our MPI implementation to map between MPI ranks and Blue Gene X/Y/Z/T coordinates.  Custom plug-ins can be created and added here; see [[#Programmer interface|Programmer interface]] for details.&lt;br /&gt;
; &amp;lt;span id=&amp;quot;opt_enable_nat&amp;quot;&amp;gt;ZOID_ENABLE_NAT (-n)&amp;lt;/span&amp;gt;&lt;br /&gt;
: Enables network address translatation (NAT) for IP packets coming from the compute nodes, allowing compute nodes to communicate with the outside world.  This support is disabled by default because it was found to have a detrimental effect on the overall performance of the TCP/IP stack on the I/O nodes, slowing down network filesystems.  This feature can also be enabled on a per-job basis by setting the &amp;lt;tt&amp;gt;ZOID_ENABLE_NAT&amp;lt;/tt&amp;gt; environment variable when submitting a job (see the [[FAQ#How to open a socket from a CN to the outside world|FAQ]]).&lt;br /&gt;
; &amp;lt;span id=&amp;quot;opt_user_script&amp;quot;&amp;gt;ZOID_USER_SCRIPT (-u)&amp;lt;/span&amp;gt;&lt;br /&gt;
: Specifies the pathname to the [[#User script|user script]]; it defaults to &amp;lt;tt&amp;gt;&amp;quot;/bin.rd/zoid-user-script.sh&amp;quot;&amp;lt;/tt&amp;gt;.  This script can be found in &amp;lt;tt&amp;gt;ramdisk/ION/ramdisk-add/bin/zoid-user-script.sh&amp;lt;/tt&amp;gt;; it sets a few environment variables and then invokes user's custom &amp;lt;tt&amp;gt;$HOME/zoid-user-script.sh&amp;lt;/tt&amp;gt;.  Hence, to adjust the behavior of this feature, either change this option or the script in the ramdisk.&amp;lt;br/&amp;gt;'''Note:''' to be able to invoke a script from user's home directory, [[#The /bin.rd/update_passwd_file.sh file|update_passwd_file.sh]] must be working correctly.&lt;br /&gt;
&lt;br /&gt;
===The /bin.rd/update_passwd_file.sh file===&lt;br /&gt;
&lt;br /&gt;
Allowing the partition owner to log into the I/O node using SSH is one of the features of the ZeptoOS software stack.  Only the administrator and the partition owner are given login access; this is controlled by the &amp;lt;tt&amp;gt;/bin.rd/update_passwd_file.sh&amp;lt;/tt&amp;gt; script, which is invoked by the daemon while the partition is being initialized.  The script can be found in &amp;lt;tt&amp;gt;ramdisk/ION/ramdisk-add/bin/update_passwd_file.sh&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
The script makes a number of assumptions that could be site-specific, so it might require an adjustment.  The daemon invokes the script passing a numerical UNIX user ID of the partition owner as the only argument.  The script then scans the &amp;lt;tt&amp;gt;/bgsys/iofs/etc/passwd&amp;lt;/tt&amp;gt; for an entry with the same user ID (on Argonne machines, this files contains all valid account names).  If a matching entry is found, it is appended to the &amp;lt;tt&amp;gt;/etc/passwd&amp;lt;/tt&amp;gt; file in the I/O node ramdisk, thus enabling login access to the node for that user.&lt;br /&gt;
&lt;br /&gt;
If allowing ordinary users access to the I/O nodes is undesirable, one can simply put &amp;lt;tt&amp;gt;exit 0&amp;lt;/tt&amp;gt; at the top of the script to disable it.&lt;br /&gt;
&lt;br /&gt;
===The /bin.rd/nat file===&lt;br /&gt;
&lt;br /&gt;
If NAT has been [[#opt_enable_nat|requested]], the daemon invokes the &amp;lt;tt&amp;gt;/bin.rd/nat&amp;lt;/tt&amp;gt; script to enabled it.  This script can be found in &amp;lt;tt&amp;gt;ramdisk/ION/ramdisk-add/bin/nat&amp;lt;/tt&amp;gt;.  Generally, it should not require any modifications.&lt;br /&gt;
&lt;br /&gt;
==Programmer interface==&lt;br /&gt;
&lt;br /&gt;
ZOID is a flexible, extensible, high-performance function call forwarding (RPC) infrastructure.  Built-in features and the standard plug-ins provide familiar POSIX file I/O and BSD socket interfaces, but, because of the number of software layers involved, they introduce a significant overhead.  For applications requiring maximum bandwidth between the compute and I/O nodes, ZOID provides an option of a customized function call forwarding with minimal overheads.  This section provides an overview of how to create such custom plug-ins.&lt;br /&gt;
&lt;br /&gt;
===Overview===&lt;br /&gt;
&lt;br /&gt;
All that ZOID provides is a function call forwarding support, and a limited one at that.  Any logic (caching, prefetching, etc.) needs to be custom-built on top of it.&lt;br /&gt;
&lt;br /&gt;
Follow existing plug-ins, found in &amp;lt;tt&amp;gt;packages/zoid/src/&amp;lt;/tt&amp;gt;, as examples.  The &amp;lt;tt&amp;gt;unix&amp;lt;/tt&amp;gt; plug-in is generally the most up to date, but other plug-ins such as &amp;lt;tt&amp;gt;mapping&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;zoidfs&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;barrier&amp;lt;/tt&amp;gt;, and &amp;lt;tt&amp;gt;test&amp;lt;/tt&amp;gt; should also be fine.&lt;br /&gt;
&lt;br /&gt;
A plug-in consists of automatically generated client-side and server-side stubs (which perform the marshalling and demarshalling of function call parameters and results, the forwarding of the function call, etc.), and of a hand-written server-side implementation which provides the implementation code for the forwarded function calls.  One might also decide to provide hand-written client-side wrappers to hide some details of the ZOID API (such as the error handling) or to adhere to a particular existing API, as is the case with the &amp;lt;tt&amp;gt;unix&amp;lt;/tt&amp;gt; plug-in (the wrappers used by the FUSE client are available in &amp;lt;tt&amp;gt;packages/zoid/src/unix/stubs/&amp;lt;/tt&amp;gt;; another version is in the GNU libc sources, in &amp;lt;tt&amp;gt;packages/glibc/src/zoid/sysdeps/unix/sysv/linux/powerpc/powerpc32/&amp;lt;/tt&amp;gt;).&lt;br /&gt;
&lt;br /&gt;
The &amp;lt;tt&amp;gt;scanner.pl&amp;lt;/tt&amp;gt; script, found in &amp;lt;tt&amp;gt;packages/zoid/src/&amp;lt;/tt&amp;gt;, creates the automatically-generated client and server stubs based on a hand-written input header file described below.  Again, please follow the examples from the existing plug-ins, such as &amp;lt;tt&amp;gt;unix&amp;lt;/tt&amp;gt; or &amp;lt;tt&amp;gt;mapping&amp;lt;/tt&amp;gt;.  The &amp;lt;tt&amp;gt;Makefile&amp;lt;/tt&amp;gt; in those plug-ins is written in a generic fashion and should only require a change to the &amp;lt;tt&amp;gt;PREFIX&amp;lt;/tt&amp;gt; line to be usable with another plug-in.  Use that &amp;lt;tt&amp;gt;Makefile&amp;lt;/tt&amp;gt; to invoke the &amp;lt;tt&amp;gt;scanner.pl&amp;lt;/tt&amp;gt; script and to compile the generated source files.&lt;br /&gt;
&lt;br /&gt;
===Input header file===&lt;br /&gt;
&lt;br /&gt;
The input header file must be a valid C header file with additional hints in the comments.  The file is read by the &amp;lt;tt&amp;gt;scanner.pl&amp;lt;/tt&amp;gt; script.&lt;br /&gt;
&lt;br /&gt;
The parser in the script is rather limited and does not handle many C constructs.  It is thus essential that the header file be as simple as possible.  In particular, function prototypes should be specified at the end of the file, not intermixed with any other specifications such as data type definitions.&lt;br /&gt;
&lt;br /&gt;
Ordinary comments are best placed on separate lines.&lt;br /&gt;
&lt;br /&gt;
'''Note:''' the parser is case ''sensitive''.&lt;br /&gt;
&lt;br /&gt;
====Start line====&lt;br /&gt;
&lt;br /&gt;
Any complex declarations that the scanner cannot parse should be placed at the top of the file, because the parser ignores everything until it encounters the following magic start line:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
/* START-ZOID-SCANNER ID=&amp;lt;n&amp;gt; INIT=&amp;lt;s1&amp;gt; FINI=&amp;lt;s2&amp;gt; PROC=&amp;lt;s3&amp;gt; */&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
; ID=&amp;lt;n&amp;gt;&lt;br /&gt;
: Each plug-in needs a unique, 16-bit identifier, passed in &amp;lt;tt&amp;gt;&amp;lt;n&amp;gt;&amp;lt;/tt&amp;gt;.  The following identifiers are already in use: &amp;lt;tt&amp;gt;0&amp;lt;/tt&amp;gt; (internal), &amp;lt;tt&amp;gt;1&amp;lt;/tt&amp;gt; (&amp;lt;tt&amp;gt;zoidfs&amp;lt;/tt&amp;gt; plug-in), &amp;lt;tt&amp;gt;2&amp;lt;/tt&amp;gt; (&amp;lt;tt&amp;gt;unix&amp;lt;/tt&amp;gt;), &amp;lt;tt&amp;gt;3&amp;lt;/tt&amp;gt; (&amp;lt;tt&amp;gt;lofar&amp;lt;/tt&amp;gt;), &amp;lt;tt&amp;gt;4&amp;lt;/tt&amp;gt; (&amp;lt;tt&amp;gt;test&amp;lt;/tt&amp;gt;), &amp;lt;tt&amp;gt;5&amp;lt;/tt&amp;gt; (&amp;lt;tt&amp;gt;mapping&amp;lt;/tt&amp;gt;), and &amp;lt;tt&amp;gt;10&amp;lt;/tt&amp;gt; (&amp;lt;tt&amp;gt;ftb&amp;lt;/tt&amp;gt;).&lt;br /&gt;
; INIT=&amp;lt;s1&amp;gt;&lt;br /&gt;
: &amp;lt;tt&amp;gt;&amp;lt;s1&amp;gt;&amp;lt;/tt&amp;gt; provides the name of an initialization function which will be invoked before a job starts running; see [[#Start-line functions|Start-line functions]] for more information.  If a plug-in does not need this feature, please specify &amp;lt;tt&amp;gt;INIT=NULL&amp;lt;/tt&amp;gt;.&lt;br /&gt;
; FINI=&amp;lt;s2&amp;gt;&lt;br /&gt;
: &amp;lt;tt&amp;gt;&amp;lt;s2&amp;gt;&amp;lt;/tt&amp;gt; provides the name of a termination function which will be invoked after all job processes have exited; see [[#Start-line functions|Start-line functions]] for more information.  If a plug-in does not need this feature, please specify &amp;lt;tt&amp;gt;FINI=NULL&amp;lt;/tt&amp;gt;.&lt;br /&gt;
; PROC=&amp;lt;s3&amp;gt;&lt;br /&gt;
: &amp;lt;tt&amp;gt;&amp;lt;s3&amp;gt;&amp;lt;/tt&amp;gt; provides the name of a callback function which will be invoked on a startup and termination of every application and ZOID-enabled process; see [[#Start-line functions|Start-line functions]] for more information.  If a plug-in does not need this feature, please specify &amp;lt;tt&amp;gt;PROC=NULL&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
====Argument hints====&lt;br /&gt;
&lt;br /&gt;
Hints are generally needed by the scanner to correctly encode and decode function arguments.  They need to be placed after each argument, before a separating comma (or a closing bracket), and should be embedded inside dedicated C comments.  Multiple hints per argument are usually provided; these are separated by a colon (&amp;lt;tt&amp;gt;:&amp;lt;/tt&amp;gt;). The following hints are currently defined:&lt;br /&gt;
&lt;br /&gt;
; in, out, inout&lt;br /&gt;
: Specifies whether the argument is an input argument, an output argument, or both.  &amp;lt;tt&amp;gt;in&amp;lt;/tt&amp;gt; is the default.&lt;br /&gt;
; obj, str, ptr, arr, arr2d&lt;br /&gt;
: Specifies the type of the argument, respectively a plain object (say, an &amp;lt;tt&amp;gt;int&amp;lt;/tt&amp;gt;, or a structure passed by value), a &amp;lt;tt&amp;gt;'\0'&amp;lt;/tt&amp;gt;-terminated character string, a pointer to a plain object, an array of objects, or a two-dimensional array (&amp;lt;tt&amp;gt;type**&amp;lt;/tt&amp;gt;, not &amp;lt;tt&amp;gt;type[][]&amp;lt;/tt&amp;gt;).  &amp;lt;tt&amp;gt;obj&amp;lt;/tt&amp;gt; is the default.&lt;br /&gt;
; size&lt;br /&gt;
: Required for array arguments (&amp;lt;tt&amp;gt;arr&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;arr2d&amp;lt;/tt&amp;gt;).  Indicates the index of another argument in the same function, which is used to pass the array size.  Absolute numbers are accepted (&amp;lt;tt&amp;gt;1&amp;lt;/tt&amp;gt; to ''number of arguments'') or relative ones (&amp;lt;tt&amp;gt;+1&amp;lt;/tt&amp;gt; for the next argument, &amp;lt;tt&amp;gt;-1&amp;lt;/tt&amp;gt; for the previous argument, etc).&amp;lt;br/&amp;gt;  For &amp;lt;tt&amp;gt;arr&amp;lt;/tt&amp;gt; arguments, the size argument must be of a numerical type, or a pointer to such a type.  For &amp;lt;tt&amp;gt;arr2d&amp;lt;/tt&amp;gt; arguments, the size argument must itself be an array (an &amp;lt;tt&amp;gt;arr&amp;lt;/tt&amp;gt; argument) of numerical elements, specifying the sizes along the less significant dimension of the array (the size of the more significant dimension is the size of the &amp;lt;tt&amp;gt;arr&amp;lt;/tt&amp;gt; array itself).&amp;lt;br/&amp;gt;  Please note that the unit of size for the numerical types is the size of the base array type (thus, &amp;lt;tt&amp;gt;sizeof(int)&amp;lt;/tt&amp;gt; for an array of &amp;lt;tt&amp;gt;int&amp;lt;/tt&amp;gt;s), not byte (if one would like it to be byte, just make the array argument have type &amp;lt;tt&amp;gt;char*&amp;lt;/tt&amp;gt; or &amp;lt;tt&amp;gt;void*&amp;lt;/tt&amp;gt; (a GCC extension)).&lt;br /&gt;
; nullok&lt;br /&gt;
: An option for arguments passed by pointer (basically, all but &amp;lt;tt&amp;gt;obj&amp;lt;/tt&amp;gt;).  If provided, it indicates that the argument is allowed to be &amp;lt;tt&amp;gt;NULL&amp;lt;/tt&amp;gt;.  This is not the default because supporting &amp;lt;tt&amp;gt;NULL&amp;lt;/tt&amp;gt; pointers results in an additional computational and protocol overhead.  '''Note:''' if a &amp;lt;tt&amp;gt;NULL&amp;lt;/tt&amp;gt; pointer is passed to an argument that lacks the &amp;lt;tt&amp;gt;nullok&amp;lt;/tt&amp;gt; flag, the client ''will'' crash.&lt;br /&gt;
; zerocopy&lt;br /&gt;
: An option for array arguments.  Enables a more efficient marshalling/demarshalling protocol for the array, which does not use extra memory copies.  Can be used for no more than one &amp;lt;tt&amp;gt;in&amp;lt;/tt&amp;gt; argument and no more than one &amp;lt;tt&amp;gt;out&amp;lt;/tt&amp;gt; argument.  [[#Zerocopy performance|Zerocopy performance]] discusses performance considerations when using this option.&lt;br /&gt;
; userbuf&lt;br /&gt;
: An option for &amp;lt;tt&amp;gt;zerocopy&amp;lt;/tt&amp;gt;; only supported for &amp;lt;tt&amp;gt;arr&amp;lt;/tt&amp;gt; arguments.  Enables a special form of zero-copy support, discussed in [[#Zerocopy with a custom output buffer|Zerocopy with a custom output buffer]] and [[#Zerocopy with a custom input buffer|Zerocopy with a custom input buffer]].&lt;br /&gt;
&lt;br /&gt;
Here is an example function prototype with the hints:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
int zoidfs_readlink(const zoidfs_handle_t * handle /* in:ptr */,&lt;br /&gt;
                    char * buffer /* out:arr:size=+1 */,&lt;br /&gt;
                    size_t buffer_length /* in:obj */);&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
====Limitations====&lt;br /&gt;
&lt;br /&gt;
As indicated earlier, the scanner is limited, so keep the prototypes simple.&lt;br /&gt;
&lt;br /&gt;
Return type of a forwarded function must be scalar or &amp;lt;tt&amp;gt;void&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Structures with pointer fields inside of them cannot be forwarded.&lt;br /&gt;
&lt;br /&gt;
====Generated files====&lt;br /&gt;
&lt;br /&gt;
For every function prototype found, the scanner generates two output files: one for a client calling the function and one for the server, where the function is in fact executed.  Code in the generated files performs marshalling and demarshalling of function arguments and results.&lt;br /&gt;
&lt;br /&gt;
Two more files per plug-in are generated: ''header''&amp;lt;tt&amp;gt;_defs.h&amp;lt;/tt&amp;gt; and ''header''&amp;lt;tt&amp;gt;_dispatch.c&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
None of the generated files should be modified.&lt;br /&gt;
&lt;br /&gt;
===Server-side API===&lt;br /&gt;
&lt;br /&gt;
Server-side stubs and the server-side implementation need to be passed as modules when invoking the ZOID I/O daemon, as described [[#opt_modules|earlier]].&lt;br /&gt;
&lt;br /&gt;
The hand-written server-side implementation code should include the &amp;lt;tt&amp;gt;zoid_api.h&amp;lt;/tt&amp;gt; header file (available from &amp;lt;tt&amp;gt;packages/zoid/prebuilt/&amp;lt;/tt&amp;gt;) and the plug-in input header file.&lt;br /&gt;
&lt;br /&gt;
All the functions listed in the header file need to be defined in the server-side implementation code.  The code needs to be compiled as a shared library; use the &amp;lt;tt&amp;gt;implementation/&amp;lt;/tt&amp;gt; subdirectory of the &amp;lt;tt&amp;gt;unix&amp;lt;/tt&amp;gt; plug-in as an example.  Please note that since ZOID is multi-threaded, multiple functions can be invoked at the same time, so one must ensure that the implementation is multi-thread-safe.&lt;br /&gt;
&lt;br /&gt;
====Start-line functions====&lt;br /&gt;
&lt;br /&gt;
The following [[#Start line|start-line]] functions can be defined:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
void INIT(int pset_mpi_proc_count, int argc, int envc, const char* argenv);&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The INIT function is invoked during initialization, right before a job starts running.  Arguments:&lt;br /&gt;
&lt;br /&gt;
; pset_mpi_proc_count&lt;br /&gt;
: The number of job processes that will be handled by this I/O node.  Note that I/O nodes also handle additional ZOID-enabled processes, such as the FUSE clients, which are not included in this number.&lt;br /&gt;
; argc&lt;br /&gt;
: The number of command-line arguments plus one.&lt;br /&gt;
; envc&lt;br /&gt;
: The number of environment variables.&lt;br /&gt;
; argenv&lt;br /&gt;
: An array of &amp;lt;tt&amp;gt;'\0'&amp;lt;/tt&amp;gt;-terminated strings, one after another.  The first string is the name of the job executable, followed by &amp;lt;tt&amp;gt;argc-1&amp;lt;/tt&amp;gt; command-line arguments, followed by &amp;lt;tt&amp;gt;envc&amp;lt;/tt&amp;gt; environment variables.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
void FINI(void);&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The FINI function is invoked after the last process of the job has terminated.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
void PROC(int added, int pset_pid);&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The PROC function is invoked on the startup and termination of every application and ZOID-enabled process on the compute node.  Arguments:&lt;br /&gt;
&lt;br /&gt;
; added&lt;br /&gt;
: &amp;lt;tt&amp;gt;1&amp;lt;/tt&amp;gt; if the process was started, &amp;lt;tt&amp;gt;0&amp;lt;/tt&amp;gt; if it was terminated.&lt;br /&gt;
; pset_pid&lt;br /&gt;
: A process identifier (as returned by [[#Implementation functions|&amp;lt;tt&amp;gt;__zoid_calling_process_id&amp;lt;/tt&amp;gt;]]).&lt;br /&gt;
&lt;br /&gt;
====Implementation functions====&lt;br /&gt;
&lt;br /&gt;
The hand-written server-side implementation functions can themselves call back a few ZOID functions, available by including the &amp;lt;tt&amp;gt;zoid_api.h&amp;lt;/tt&amp;gt; header file:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
int __zoid_calling_process_id(void);&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This function returns a unique identifier of the compute node process that invoked the function.  The identifier is ''not'' an MPI rank, because some processes, such as the FUSE clients, are not part of the application and hence do not have a rank.  The identifiers are only unique within one I/O node, and they can be reused if a process starts after another one has terminated.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
void __zoid_register_userbuf(void* userbuf,&lt;br /&gt;
                             void (*callback)(void* userbuf, void* priv),&lt;br /&gt;
                             void* priv);&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This function will be discussed in [[#Zerocopy with a custom output buffer|Zerocopy with a custom output buffer]].&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
int __zoid_send_output(int pid, int fd, const char* buffer, int len);&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This function writes an arbitrary string to the job's standard output or error.  Arguments:&lt;br /&gt;
&lt;br /&gt;
; pid&lt;br /&gt;
: Process identifier as returned by &amp;lt;tt&amp;gt;__zoid_calling_process_id&amp;lt;/tt&amp;gt;.  The process in question ''must'' have an MPI rank, meaning that it must be either an application process or a process launched from an application process.&lt;br /&gt;
; fd&lt;br /&gt;
: &amp;lt;tt&amp;gt;1&amp;lt;/tt&amp;gt; for standard output, &amp;lt;tt&amp;gt;2&amp;lt;/tt&amp;gt; for standard error.&lt;br /&gt;
; buffer, len&lt;br /&gt;
: The string and its length.  &amp;lt;tt&amp;gt;'\0'&amp;lt;/tt&amp;gt; should not be included in &amp;lt;tt&amp;gt;len&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;buffer&amp;lt;/tt&amp;gt; does not need to be &amp;lt;tt&amp;gt;'\0'&amp;lt;/tt&amp;gt;-terminated.&lt;br /&gt;
&lt;br /&gt;
The function returns 0 if successful, and -1 if not (such as when the process identified by &amp;lt;tt&amp;gt;pid&amp;lt;/tt&amp;gt; does not have an MPI rank).&lt;br /&gt;
&lt;br /&gt;
===Client-side API===&lt;br /&gt;
&lt;br /&gt;
A compute node application needs to be linked with the client-side stubs and with a common support library &amp;lt;tt&amp;gt;libzoid_cn.a&amp;lt;/tt&amp;gt; (a prebuilt version of the latter is in &amp;lt;tt&amp;gt;packages/zoid/prebuilt&amp;lt;/tt&amp;gt;; sources are in &amp;lt;tt&amp;gt;packages/zoid/src/cnl/client&amp;lt;/tt&amp;gt;).  Several functions are available to applications by including the &amp;lt;tt&amp;gt;zoid_api.h&amp;lt;/tt&amp;gt; header file:&lt;br /&gt;
&lt;br /&gt;
====Initialization====&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
int __zoid_init(void);&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This function ''must'' be invoked before any ZOID or ZOID-forwarded functions can be invoked.  It returns &amp;lt;tt&amp;gt;0&amp;lt;/tt&amp;gt; if successful, &amp;lt;tt&amp;gt;1&amp;lt;/tt&amp;gt; otherwise.  There is no corresponding termination function.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
int __zoid_job_size(void);&lt;br /&gt;
int __zoid_my_rank(void);&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
These functions return, respectively, the number of processes in the job (the size of &amp;lt;tt&amp;gt;MPI_COMM_WORLD&amp;lt;/tt&amp;gt;), and the MPI rank of the&lt;br /&gt;
current process.  Either will return &amp;lt;tt&amp;gt;-1&amp;lt;/tt&amp;gt; if the current process does not have an MPI rank, i.e., if it is not an application process and was not launched from an application process (say, if it was launched from an interactive shell).&lt;br /&gt;
&lt;br /&gt;
====Error conditions====&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
int __zoid_error(void);&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This function should be invoked on the client side after ''every'' forwarded function call returns, to determine if any errors occured within the forwarding layer.  A return value of &amp;lt;tt&amp;gt;0&amp;lt;/tt&amp;gt; indicates a success; otherwise, one of the following error values will be returned:&lt;br /&gt;
&lt;br /&gt;
; ENOSYS&lt;br /&gt;
: Invalid command sent from the client.  Typically indicates that the corresponding I/O-node-side [[#opt_modules|modules]] have not been loaded.&lt;br /&gt;
; ENOMEM&lt;br /&gt;
: Out of memory condition.&lt;br /&gt;
; E2BIG&lt;br /&gt;
: Message exceeded the internal size limit.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
int __zoid_excessive_size(void);&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
If &amp;lt;tt&amp;gt;__zoid_error&amp;lt;/tt&amp;gt; returned &amp;lt;tt&amp;gt;E2BIG&amp;lt;/tt&amp;gt;, calling this function will provide an indication of by how many bytes the input or output was too large.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;span id=&amp;quot;size_restrictions&amp;quot;&amp;gt;ZOID&amp;lt;/span&amp;gt; [[#opt_buffer_size|has a limit]] on the message size, around 4&amp;amp;nbsp;MB by default.  The limit is enforced on both input and output.  The limit only applies to buffers &amp;quot;owned&amp;quot; by ZOID on the daemon side; it does not apply to custom [[#Zerocopy with a custom input buffer|input]] or [[#Zerocopy with a custom output buffer|output]] buffers.&lt;br /&gt;
&lt;br /&gt;
If the limit is hit, the operation needs to be split into smaller ones.  Information returned by &amp;lt;tt&amp;gt;__zoid_excessive_size&amp;lt;/tt&amp;gt; makes it easy to adjust the buffer and resubmit.&lt;br /&gt;
&lt;br /&gt;
'''Note:''' While the input-side (argument) overflow is flagged immediately on the client side, and is thus fairly cheap to hit, the output-side (result) overflow is flagged on the I/O node, after the request has been sent there (but before the implementation function is invoked).  It is thus advised to cache at least the size limit for the output side for the next invocation, to avoid a future communication overhead.  The size limit is function-specific, since it depends on sizes of other arguments and results.&lt;br /&gt;
&lt;br /&gt;
Here is an example of how the client-side convenience wrapper for a call such as POSIX &amp;lt;tt&amp;gt;read&amp;lt;/tt&amp;gt; could be implemented:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
ssize_t read(int fd, void *buf, size_t nbytes)&lt;br /&gt;
{&lt;br /&gt;
    static ssize_t max_read_nbytes = -1;&lt;br /&gt;
    ssize_t bytes_read;&lt;br /&gt;
&lt;br /&gt;
    bytes_read = 0;&lt;br /&gt;
    do&lt;br /&gt;
    {&lt;br /&gt;
        ssize_t toread, justread;&lt;br /&gt;
        int error;&lt;br /&gt;
&lt;br /&gt;
        toread = nbytes - bytes_read;&lt;br /&gt;
&lt;br /&gt;
        if (max_read_nbytes != -1 &amp;amp;&amp;amp; toread &amp;gt; max_read_nbytes)&lt;br /&gt;
            toread = max_read_nbytes;&lt;br /&gt;
&lt;br /&gt;
        /* unix_read is the forwarded function call.  */&lt;br /&gt;
        justread = unix_read(fd, buf + bytes_read, toread);&lt;br /&gt;
&lt;br /&gt;
        if ((error = __zoid_error()))&lt;br /&gt;
        {&lt;br /&gt;
            if (error != E2BIG)&lt;br /&gt;
            {&lt;br /&gt;
                /* For a generic ZOID error, just bail out.  */&lt;br /&gt;
                errno = error;&lt;br /&gt;
                return -1;&lt;br /&gt;
            }&lt;br /&gt;
&lt;br /&gt;
            /* We tried to send a too large read request.  Adjust.  */&lt;br /&gt;
            max_read_nbytes = toread - __zoid_excessive_size();&lt;br /&gt;
        }&lt;br /&gt;
        else&lt;br /&gt;
        {&lt;br /&gt;
            if (justread &amp;lt; 0)&lt;br /&gt;
            {&lt;br /&gt;
                /* For a generic read() error, just bail out.&lt;br /&gt;
                   In case of an I/O error, unix_read returns -errno.  */&lt;br /&gt;
                errno = -justread;&lt;br /&gt;
                return -1;&lt;br /&gt;
            }&lt;br /&gt;
&lt;br /&gt;
            bytes_read += justread;&lt;br /&gt;
&lt;br /&gt;
            if (justread != toread)&lt;br /&gt;
                /* unix_read as such succeeded, but it read fewer bytes than&lt;br /&gt;
                   expected.  We terminate prematurely then.  */&lt;br /&gt;
                break;&lt;br /&gt;
        }&lt;br /&gt;
    } while (bytes_read &amp;lt; nbytes);&lt;br /&gt;
&lt;br /&gt;
    return bytes_read;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Additional considerations===&lt;br /&gt;
&lt;br /&gt;
====Forwarding &amp;lt;tt&amp;gt;errno&amp;lt;/tt&amp;gt;====&lt;br /&gt;
&lt;br /&gt;
If one needs to pass a variable such as &amp;lt;tt&amp;gt;errno&amp;lt;/tt&amp;gt; from the I/O node to the client, the most straightforward way is to add an extra integer &amp;lt;tt&amp;gt;out&amp;lt;/tt&amp;gt; pointer argument to all functions and pass it that way.  Another option is to do it the same way the UNIX kernel does: pass it as a negative return value from the functions.  The &amp;lt;tt&amp;gt;unix&amp;lt;/tt&amp;gt; plug-in does it that way, so, e.g., the implementation of &amp;lt;tt&amp;gt;close&amp;lt;/tt&amp;gt; on the I/O node looks something like this:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
if (close(server_fd) == -1)&lt;br /&gt;
    return -errno;&lt;br /&gt;
else&lt;br /&gt;
    return 0;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Then, on the client side, we have a convenience wrapper:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
int close(int fd)&lt;br /&gt;
{&lt;br /&gt;
    return unix_decode_result(unix_close(fd));&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;unix_decode_result&amp;lt;/tt&amp;gt; is a preprocessor macro that handles both ZOID errors and errors returned by the plug-in.  It uses a number of GCC extensions to make it as transparent as possible:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
#define unix_decode_result(result)      \&lt;br /&gt;
({                                      \&lt;br /&gt;
    typeof (result) _result = (result); \&lt;br /&gt;
    int _n;                             \&lt;br /&gt;
    if ((_n = __zoid_error()) != 0)     \&lt;br /&gt;
    {                                   \&lt;br /&gt;
        errno = _n;                     \&lt;br /&gt;
        _result = -1;                   \&lt;br /&gt;
    }                                   \&lt;br /&gt;
    else if (_result &amp;lt; 0)               \&lt;br /&gt;
    {                                   \&lt;br /&gt;
        errno = -_result;               \&lt;br /&gt;
        _result = -1;                   \&lt;br /&gt;
    }                                   \&lt;br /&gt;
    _result;                            \&lt;br /&gt;
})&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
====Returning variable amounts of data in arrays====&lt;br /&gt;
&lt;br /&gt;
Just like with UNIX system calls, ZOID does not allocate memory for the results.  Instead, callers must provide pre-allocated arrays, along with their sizes.  UNIX would then typically return the size of the used part as a return value from a system call.  Unfortunately, ZOID cannot make use of that &amp;amp;#8211; it will use the same array size argument to determine how much data to send back, so even if only a small part of the provided buffer is actually filled in, the whole buffer will be sent back, which is inefficient.  This can be prevented by passing the array size as an &amp;lt;tt&amp;gt;inout&amp;lt;/tt&amp;gt; pointer to a numerical type.  A server-side implementation of a function such as &amp;lt;tt&amp;gt;read&amp;lt;/tt&amp;gt; then looks like this:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
ssize_t unix_read(int fd /* in:obj */,&lt;br /&gt;
                  void *buf /* out:arr:size=+1 */,&lt;br /&gt;
                  size_t *count /* inout:ptr */)&lt;br /&gt;
{&lt;br /&gt;
    ssize_t ret;&lt;br /&gt;
&lt;br /&gt;
    ...&lt;br /&gt;
&lt;br /&gt;
    if ((ret = read(fd, buf, *count)) == -1)&lt;br /&gt;
    {&lt;br /&gt;
        *count = 0;&lt;br /&gt;
        return -errno;&lt;br /&gt;
    }&lt;br /&gt;
    else&lt;br /&gt;
    {&lt;br /&gt;
        *count = ret;&lt;br /&gt;
        return ret;&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Obviously, the client side needs to be modified as well, to pass the size argument by address.&lt;br /&gt;
&lt;br /&gt;
'''Note:''' this feature has certain implementation limitations.  It can misbehave in the presence of multiple output arrays (or a single output &amp;lt;tt&amp;gt;arr2d&amp;lt;/tt&amp;gt;, which internally behaves a lot like multiple separate &amp;lt;tt&amp;gt;arr&amp;lt;/tt&amp;gt;s).  Essentially, for efficiency reasons, the placement of arrays in the result buffer is determined before an implementation function is invoked.  If this feature is used to change the size of one array, and that array is followed in the output buffer by another array, a &amp;quot;hole&amp;quot; will be created in the buffer, causing problems.  However, in the most common case of a single output array the feature is completely reliable.&lt;br /&gt;
&lt;br /&gt;
====Zerocopy performance====&lt;br /&gt;
&lt;br /&gt;
Implementation-wise, ZOID is always zero-copy on the server side, meaning that data that implementation functions put in the &amp;lt;tt&amp;gt;out&amp;lt;/tt&amp;gt; arrays is sent to the compute nodes without any extra memory copies.&lt;br /&gt;
&lt;br /&gt;
Client side is only zero-copy for arrays that use the &amp;lt;tt&amp;gt;zerocopy&amp;lt;/tt&amp;gt; flag in the header file.  Because of the additial protocol overheads that &amp;lt;tt&amp;gt;zerocopy&amp;lt;/tt&amp;gt; introduces, it should be used only for potentially large memory buffers, such as the buffers of file I/O &amp;lt;tt&amp;gt;read&amp;lt;/tt&amp;gt; or &amp;lt;tt&amp;gt;write&amp;lt;/tt&amp;gt; calls.&lt;br /&gt;
&lt;br /&gt;
'''Note:''' for maximum performance, the arrays passed as &amp;lt;tt&amp;gt;zerocopy&amp;lt;/tt&amp;gt; arguments on the compute nodes must be aligned in memory to the 16-bytes boundary; otherwise, an interim buffer will be used.  The memory allocation routines such as &amp;lt;tt&amp;gt;malloc&amp;lt;/tt&amp;gt; have been modified to align memory to that boundary.  If there is a danger that the user code might pass a large unaligned buffer, and the semantics will not be affected, it makes sense to write code that detects insufficient alignment and splits the operation in two: a small unaligned one (say, up to 240 bytes &amp;amp;#8211; the data payload of a single packet on the tree network), followed by a larger, properly aligned one.&lt;br /&gt;
&lt;br /&gt;
====Zerocopy with a custom output buffer====&lt;br /&gt;
&lt;br /&gt;
Normally, memory for output arrays to be filled in by server-side implementation functions is allocated by the ZOID daemon.  This might be inconvenient when the data to be filled arrives asynchronously, possibly before the implementation function is even invoked; in such situations, an interim memory buffer must be used, forcing an extra memory copy.&lt;br /&gt;
&lt;br /&gt;
This can be avoided for zero-copy output &amp;lt;tt&amp;gt;arr&amp;lt;/tt&amp;gt; types if the &amp;lt;tt&amp;gt;userbuf&amp;lt;/tt&amp;gt; flag has been used.  No space will then be preallocated by the daemon for the array (the server-side stub will pass a &amp;lt;tt&amp;gt;NULL&amp;lt;/tt&amp;gt; pointer); instead, the implementation function must provide the daemon with its own buffer.  It can do it by calling:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
void __zoid_register_userbuf(void* userbuf,&lt;br /&gt;
                             void (*callback)(void* userbuf, void* priv),&lt;br /&gt;
                             void* priv);&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Arguments:&lt;br /&gt;
&lt;br /&gt;
; userbuf&lt;br /&gt;
: The address of the buffer.&lt;br /&gt;
; callback&lt;br /&gt;
: A callback function that is invoked by the daemon when the buffer has been sent to the client and is thus no longer needed.  &amp;lt;tt&amp;gt;userbuf&amp;lt;/tt&amp;gt; is passed as the first argument to the callback.  It is safe for the callback to invoke &amp;lt;tt&amp;gt;__zoid_calling_process_id&amp;lt;/tt&amp;gt;.&lt;br /&gt;
; priv&lt;br /&gt;
: A private data passed as the second argument to the &amp;lt;tt&amp;gt;callback&amp;lt;/tt&amp;gt;.  It is not interpreted by ZOID in any way.&lt;br /&gt;
&lt;br /&gt;
The size of the provided buffer is determined like for any other array argument: the maximum value is provided by the client via the &amp;lt;tt&amp;gt;size&amp;lt;/tt&amp;gt; argument.  The server-side implementation part may choose to return less than the maximum amount, as explained [[#Returning variable amounts of data in arrays|earlier]].&lt;br /&gt;
&lt;br /&gt;
As in other zero-copy cases, for maximum performance, the buffer provided must be aligned in memory to the 16-bytes boundary; otherwise, an interim buffer will be used.  The memory allocation routines such as &amp;lt;tt&amp;gt;malloc&amp;lt;/tt&amp;gt; have been modified to align memory to that boundary, but we recommend explicitly calling &amp;lt;tt&amp;gt;posix_memalign&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
'''Note:''' because the buffer provided is ''not'' allocated by ZOID, message size restrictions discussed [[#size_restrictions|earlier]] do not apply to it.  Please do not abuse this capability.  There is a good reason for the message size limit: it is there so that the maximum amount of memory required by the ZOID daemon stays limited.  Too many too large user-allocated buffers might result in an out-of-memory condition on the I/O node.&lt;br /&gt;
&lt;br /&gt;
We provide a simple example below.  It is a little artificial in the sense that the buffer is allocated within the implementation function; as we indicated, this feature is most useful with buffers allocated outside of the implementation functions:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
static void buffer_cb(void* userbuf, void* priv)&lt;br /&gt;
{&lt;br /&gt;
    free(userbuf);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
ssize_t unix_read(int fd /* in:obj */,&lt;br /&gt;
                  void *buf /* out:arr:size=+1:zerocopy:userbuf */,&lt;br /&gt;
                  size_t *count /* inout:ptr */)&lt;br /&gt;
{&lt;br /&gt;
    ssize_t ret;&lt;br /&gt;
&lt;br /&gt;
    ...&lt;br /&gt;
&lt;br /&gt;
    if (posix_memalign(&amp;amp;buf, 16, *count))&lt;br /&gt;
    {&lt;br /&gt;
        *count = 0;&lt;br /&gt;
        return -ENOMEM;&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    __zoid_register_userbuf(buf, &amp;amp;buffer_cb, NULL);&lt;br /&gt;
&lt;br /&gt;
    if ((ret = read(fd, buf, *count)) == -1)&lt;br /&gt;
    {&lt;br /&gt;
        *count = 0;&lt;br /&gt;
        return -errno;&lt;br /&gt;
    }&lt;br /&gt;
    else&lt;br /&gt;
    {&lt;br /&gt;
        *count = ret;&lt;br /&gt;
        return ret;&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
====Zerocopy with a custom input buffer====&lt;br /&gt;
&lt;br /&gt;
The &amp;lt;tt&amp;gt;userbuf&amp;lt;/tt&amp;gt; flag discussed above can also be used for ''input'' zero-copy &amp;lt;tt&amp;gt;arr&amp;lt;/tt&amp;gt; arguments.  This could be useful to avoid extra memory copies if the data in the array will be needed after the implementation function has returned.&lt;br /&gt;
&lt;br /&gt;
If the flag is used, the daemon will not allocate the memory for the array; instead, in the middle of receiving the request from the client, it will call an allocation routine from the server-side implementation code.  The name of the allocation routine is the name of the function that uses the input &amp;lt;tt&amp;gt;userbuf&amp;lt;/tt&amp;gt; argument, with &amp;lt;tt&amp;gt;_allocate_cb&amp;lt;/tt&amp;gt; suffix attached to it.  Its prototype needs to be as follows:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
void* &amp;lt;name&amp;gt;_allocate_cb(int len);&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The single argument passed by the daemon is the length of the array in bytes.  The routine must return a pointer to a buffer of that size or &amp;lt;tt&amp;gt;NULL&amp;lt;/tt&amp;gt; if that is not possible (in which case, the function will fail and &amp;lt;tt&amp;gt;__zoid_error&amp;lt;/tt&amp;gt; on the client side will return &amp;lt;tt&amp;gt;ENOMEM&amp;lt;/tt&amp;gt;).&lt;br /&gt;
&lt;br /&gt;
There is a restriction on the type of the array: its base type must have a size of one byte, so the array should be of type &amp;lt;tt&amp;gt;char*&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;unsigned char*&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;void*&amp;lt;/tt&amp;gt; (a GCC extension), etc.&lt;br /&gt;
&lt;br /&gt;
The allocation routine is invoked in the same context as ordinary implementation functions.  It may block if it so desires; this will block the compute node client that invoked the routine, but all other clients can keep communicating with the server, thanks to its multi-threaded architecture.&lt;br /&gt;
&lt;br /&gt;
Once the allocation routine has returned and a complete request has been received by the daemon, the implementation function is invoked as usual, with a correct address of the input &amp;lt;tt&amp;gt;userbuf&amp;lt;/tt&amp;gt; array.  It is the responsibility of the plug-in implementer to release the memory occupied by that array when it is no longer needed.&lt;br /&gt;
&lt;br /&gt;
As with other user-level callbacks, the allocation routine may call &amp;lt;tt&amp;gt;__zoid_calling_process_id&amp;lt;/tt&amp;gt; to learn which client process sent the request.  Also, as in other zero-copy cases, for maximum performance, the buffer provided must be aligned in memory to the 16-bytes boundary; otherwise, an interim buffer will be used.  The memory allocation routines such as &amp;lt;tt&amp;gt;malloc&amp;lt;/tt&amp;gt; have been modified to align memory to that boundary, but we recommend explicitly calling &amp;lt;tt&amp;gt;posix_memalign&amp;lt;/tt&amp;gt;.  Finally, as with output &amp;lt;tt&amp;gt;userbuf&amp;lt;/tt&amp;gt;, message size restrictions discussed [[#size_restrictions|earlier]] do not apply to the user-allocated buffers.  Please do not abuse this capability.  There is a good reason for the message size limit: it is there so that the maximum amount of memory required by the ZOID daemon stays limited.  Too many too large user-allocated buffers might result in an out-of-memory condition on the I/O node.&lt;br /&gt;
&lt;br /&gt;
Under rare circumstances, input &amp;lt;tt&amp;gt;userbuf&amp;lt;/tt&amp;gt; could result in memory leaks.  For this to take place, the job would have to be interrupted after the allocation routine has been run, but before the implementation function is called.  This could only cause problems if I/O nodes are not rebooted between jobs.  Those concerned about this scenario can eliminate the leak by adding necessary memory release code to the [[#Start-line functions|FINI]] function.&lt;br /&gt;
&lt;br /&gt;
A simple example:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
void* unix_write_allocate_cb(int len)&lt;br /&gt;
{&lt;br /&gt;
    void* ptr;&lt;br /&gt;
&lt;br /&gt;
    if (posix_memalign(&amp;amp;ptr, 16, len))&lt;br /&gt;
        return NULL;&lt;br /&gt;
&lt;br /&gt;
    return ptr;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
ssize_t unix_write(int fd /* in:obj */,&lt;br /&gt;
                   const void *buf /* in:arr:size=+1:zerocopy:userbuf */,&lt;br /&gt;
                   size_t count /* in:obj */)&lt;br /&gt;
{&lt;br /&gt;
    ssize_t ret;&lt;br /&gt;
&lt;br /&gt;
    ...&lt;br /&gt;
&lt;br /&gt;
    if ((ret = write(fd, buf, count)) == -1)&lt;br /&gt;
        ret = -errno;&lt;br /&gt;
&lt;br /&gt;
    free((void*)buf);&lt;br /&gt;
&lt;br /&gt;
    return ret;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
[[Ramdisk]] | [[ZeptoOS_Documentation|Top]] | [[(K)TAU]]&lt;/div&gt;</summary>
		<author><name>Iskra</name></author>
	</entry>
	<entry>
		<id> /zeptoos/index.php?title=ZOID&amp;diff=572</id>
		<title>ZOID</title>
		<link rel="alternate" type="text/html" href=" /zeptoos/index.php?title=ZOID&amp;diff=572"/>
		<updated>2009-05-07T20:24:45Z</updated>

		<summary type="html">&lt;p&gt;Iskra: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;[[Ramdisk]] | [[ZeptoOS_Documentation|Top]] | [[(K)TAU]]&lt;br /&gt;
----&lt;br /&gt;
&lt;br /&gt;
==Introduction==&lt;br /&gt;
&lt;br /&gt;
ZOID is an I/O forwarding component of the ZeptoOS project.  Any communication between the compute nodes and the I/O nodes (job management, file I/O, sockets) is handled by ZOID.&lt;br /&gt;
&lt;br /&gt;
ZOID infrastructure consists of:&lt;br /&gt;
* A multithreaded &amp;lt;tt&amp;gt;zoid&amp;lt;/tt&amp;gt; daemon on the I/O nodes which performs I/O forwarding for the compute nodes and which also communicates with the service node to perform job management,&lt;br /&gt;
* &amp;lt;tt&amp;gt;control&amp;lt;/tt&amp;gt; daemon on the compute nodes which is responsible for job management tasks such as the launching of application processes, for the forwarding of &amp;lt;tt&amp;gt;stdin&amp;lt;/tt&amp;gt;/&amp;lt;tt&amp;gt;out&amp;lt;/tt&amp;gt;/&amp;lt;tt&amp;gt;err&amp;lt;/tt&amp;gt; data, and for forwarding of IP packets,&lt;br /&gt;
* &amp;lt;tt&amp;gt;zoid-fuse&amp;lt;/tt&amp;gt; daemon on the compute nodes which performs file I/O forwarding for POSIX-compliant applications.&lt;br /&gt;
&lt;br /&gt;
==User interface==&lt;br /&gt;
&lt;br /&gt;
ZOID is meant to be transparent to users, but there are a few optional mechanisms available to interact with it.&lt;br /&gt;
&lt;br /&gt;
===User script===&lt;br /&gt;
&lt;br /&gt;
Right before a job starts running, and right after the last process of a job has terminated, ZOID daemon attempts to invoke a ''user script'' on I/O nodes.  By default, the daemon invokes &amp;lt;tt&amp;gt;$HOME/zoid-user-script.sh&amp;lt;/tt&amp;gt; (this pathname can be [[#opt_user_script|changed]] by an administrator).  A single parameter is passed to the script: &amp;lt;tt&amp;gt;1&amp;lt;/tt&amp;gt; at the job startup, and &amp;lt;tt&amp;gt;0&amp;lt;/tt&amp;gt; at the termination.&lt;br /&gt;
&lt;br /&gt;
Information about the job will be passed to the script in the following environment variables:&lt;br /&gt;
; &amp;lt;tt&amp;gt;ZOID_JOB_EXEC&amp;lt;/tt&amp;gt;&lt;br /&gt;
: name of the job executable,&lt;br /&gt;
; &amp;lt;tt&amp;gt;ZOID_JOB_ARGS&amp;lt;/tt&amp;gt;&lt;br /&gt;
: job arguments, separated by colons (&amp;lt;tt&amp;gt;:&amp;lt;/tt&amp;gt;)&lt;br /&gt;
; &amp;lt;tt&amp;gt;ZOID_JOB_ENV&amp;lt;/tt&amp;gt;&lt;br /&gt;
: job environment variables, separated by colons (&amp;lt;tt&amp;gt;:&amp;lt;/tt&amp;gt;)&lt;br /&gt;
; &amp;lt;tt&amp;gt;ZOID_JOB_ID&amp;lt;/tt&amp;gt;&lt;br /&gt;
: BG/P control system job id ('''Note:''' this is generally different from the Cobalt job ID; see [[FAQ#How to obtain a Cobalt job ID|FAQ]] for the latter),&lt;br /&gt;
; &amp;lt;tt&amp;gt;ZOID_JOB_GLOBAL_SIZE&amp;lt;/tt&amp;gt;&lt;br /&gt;
: the number of processes in the job (the size of &amp;lt;tt&amp;gt;MPI_COMM_WORLD&amp;lt;/tt&amp;gt;),&lt;br /&gt;
; &amp;lt;tt&amp;gt;ZOID_JOB_LOCAL_SIZE&amp;lt;/tt&amp;gt;&lt;br /&gt;
: the number of job processes handled by this I/O node,&lt;br /&gt;
; &amp;lt;tt&amp;gt;ZOID_JOB_MODE&amp;lt;/tt&amp;gt;&lt;br /&gt;
: &amp;lt;tt&amp;gt;0&amp;lt;/tt&amp;gt; for SMP, &amp;lt;tt&amp;gt;1&amp;lt;/tt&amp;gt; for VN, and &amp;lt;tt&amp;gt;2&amp;lt;/tt&amp;gt; for DUAL,&lt;br /&gt;
; &amp;lt;tt&amp;gt;SHELL&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;PATH&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;USER&amp;lt;/tt&amp;gt;, and &amp;lt;tt&amp;gt;HOME&amp;lt;/tt&amp;gt;&lt;br /&gt;
: will also be set...&lt;br /&gt;
&lt;br /&gt;
'''Note:''' the user script is invoked ''synchronously'' by the daemon, i.e., the job will not start running until the script terminates.  If one needs some processes to run on the I/O nodes while the job is running, they should be started in the background (&amp;amp;amp;).&lt;br /&gt;
&lt;br /&gt;
'''Note 2:''' for this feature to work, [[#The /bin.rd/update_passwd_file.sh file|update_passwd_file.sh]] must be working correctly.&lt;br /&gt;
&lt;br /&gt;
===File broadcast===&lt;br /&gt;
A &amp;lt;tt&amp;gt;/bin.rd/f2cn&amp;lt;/tt&amp;gt; command is available on the I/O nodes for a very efficient (hardware-assisted) broadcasting of files to all the compute nodes handled by the given I/O node.&lt;br /&gt;
&lt;br /&gt;
The command takes two arguments:&lt;br /&gt;
* absolute pathname to the input file on the I/O node,&lt;br /&gt;
* absolute pathname to the output file on the compute nodes.&lt;br /&gt;
&lt;br /&gt;
The input file does not need to be physically on the I/O node; it can be on a network filesystem mounted on the node.  The file will be created in the ramdisk of each compute node.&lt;br /&gt;
&lt;br /&gt;
The throughput is in practice limited by how fast the input file can be read; we have seen results in excess of 300&amp;amp;nbsp;MB/s for files residing in the I/O node ramdisk.&lt;br /&gt;
&lt;br /&gt;
'''Note:''' all the compute nodes in the pset must be up and running.  Do not use this command on ''incomplete'' partitions (e.g., a one-process job on a 64-node partition); this will likely hang the ZOID daemon.&lt;br /&gt;
&lt;br /&gt;
'''Note2:''' this feature can safely be used from within a [[#User script|user script]], so one can, e.g., pre-stage large binaries, like this:&lt;br /&gt;
&lt;br /&gt;
User script (&amp;lt;tt&amp;gt;$HOME/zoid-user-script.sh&amp;lt;/tt&amp;gt;):&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
#!/bin/sh&lt;br /&gt;
&lt;br /&gt;
if [ &amp;quot;$1&amp;quot; -eq &amp;quot;1&amp;quot; ]; then&lt;br /&gt;
    /bin.rd/f2cn $HOME/large_binary /tmp/large_binary&lt;br /&gt;
fi&lt;br /&gt;
exit 0&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Job script (submitted using Cobalt or mpirun):&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
#!/bin/sh&lt;br /&gt;
&lt;br /&gt;
chmod 755 /tmp/large_binary&lt;br /&gt;
/tmp/large_binary&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Performance counters===&lt;br /&gt;
&lt;br /&gt;
A &amp;lt;tt&amp;gt;/bin.rd/statquery&amp;lt;/tt&amp;gt; command is available on the I/O nodes for obtaining the performance counters of the I/O daemon.&lt;br /&gt;
&lt;br /&gt;
The command takes a single optional argument:&lt;br /&gt;
* the interval between successive queries, in seconds.&lt;br /&gt;
&lt;br /&gt;
If the argument is not provided, the command will terminate after the first query.&lt;br /&gt;
&lt;br /&gt;
Here is a sample output generated:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
Timestamp:                      1240439085.688831&lt;br /&gt;
Total messages sent:            5767&lt;br /&gt;
Total bytes sent:               7619170&lt;br /&gt;
Total messages received:        5717&lt;br /&gt;
Total bytes received:           72575&lt;br /&gt;
IP fwd messages sent:           196&lt;br /&gt;
IP fwd bytes sent:              5889&lt;br /&gt;
IP fwd messages received:       84&lt;br /&gt;
IP fwd bytes received:          6453&lt;br /&gt;
Stream messages sent:           65&lt;br /&gt;
Stream bytes sent:              520&lt;br /&gt;
Stream messages received:       65&lt;br /&gt;
Stream bytes received:          1416&lt;br /&gt;
Broadcast messages sent:        1&lt;br /&gt;
Broadcast bytes sent:           2437906&lt;br /&gt;
Internal messages sent:         193&lt;br /&gt;
Internal bytes sent:            39524&lt;br /&gt;
Internal messages received:     256&lt;br /&gt;
Internal bytes received:        1792&lt;br /&gt;
Plugin 5 messages sent:         0&lt;br /&gt;
Plugin 5 bytes sent:            0&lt;br /&gt;
Plugin 5 messages received:     0&lt;br /&gt;
Plugin 5 bytes received:        0&lt;br /&gt;
Plugin 2 messages sent:         5312&lt;br /&gt;
Plugin 2 bytes sent:            5135331&lt;br /&gt;
Plugin 2 messages received:     5312&lt;br /&gt;
Plugin 2 bytes received:        62914&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The meaning of the fields is as follows:&lt;br /&gt;
; Timestamp&lt;br /&gt;
: number of seconds and microseconds from the epoch, as returned by &amp;lt;tt&amp;gt;gettimeofday(2)&amp;lt;/tt&amp;gt;,&lt;br /&gt;
; IP fwd&lt;br /&gt;
: IP packet forwarding between compute nodes and I/O nodes,&lt;br /&gt;
; Stream&lt;br /&gt;
: &amp;lt;tt&amp;gt;stdin&amp;lt;/tt&amp;gt;/&amp;lt;tt&amp;gt;out&amp;lt;/tt&amp;gt;/&amp;lt;tt&amp;gt;err&amp;lt;/tt&amp;gt; streams,&lt;br /&gt;
; Broadcast&lt;br /&gt;
: [[#File broadcast|file broadcasts]],&lt;br /&gt;
; Internal&lt;br /&gt;
: job control messages, etc.&lt;br /&gt;
; Plugin 5&lt;br /&gt;
: internal &amp;lt;tt&amp;gt;mapping&amp;lt;/tt&amp;gt; plug-in, used by MPI,&lt;br /&gt;
; Plugin 2&lt;br /&gt;
: &amp;lt;tt&amp;gt;unix&amp;lt;/tt&amp;gt; plugin (POSIX file I/O).&lt;br /&gt;
&lt;br /&gt;
The counters are 64-bit integers, so they will take a while to overflow :-).&lt;br /&gt;
&lt;br /&gt;
Example user script (&amp;lt;tt&amp;gt;$HOME/zoid-user-script.sh&amp;lt;/tt&amp;gt;) that samples the statistics every 60 seconds and writes them to a unique file:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
#!/bin/sh&lt;br /&gt;
&lt;br /&gt;
if [ &amp;quot;$1&amp;quot; -eq &amp;quot;1&amp;quot; ]; then&lt;br /&gt;
    /bin.rd/statquery 60 &amp;gt;$HOME/zoid_stats.$ZOID_JOB_ID.`hostname` &amp;amp;&lt;br /&gt;
fi&lt;br /&gt;
exit 0&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Administrator interface==&lt;br /&gt;
&lt;br /&gt;
===Configuration file===&lt;br /&gt;
&lt;br /&gt;
The &amp;lt;tt&amp;gt;zoid&amp;lt;/tt&amp;gt; I/O daemon accepts a number of command-line options that can be used to change its behavior.  They can be adjusted by editing the &amp;lt;tt&amp;gt;ramdisk/ION/ramdisk-add/etc/sysconfig/zoid&amp;lt;/tt&amp;gt; file and rebuilding the I/O node ramdisk:&lt;br /&gt;
&lt;br /&gt;
; &amp;lt;span id=&amp;quot;opt_buffer_size&amp;quot;&amp;gt;ZOID_BUFFER_SIZE (-b)&amp;lt;/span&amp;gt;&lt;br /&gt;
: Specifies the size of the buffers used for messages.  Because a separate buffer is needed for a request and a reply, and typically no more than one of these needs to be large, to save memory ZOID supports buffers of two sizes: a small one (4&amp;amp;nbsp;KB by default) and a large one (4&amp;amp;nbsp;MB+1&amp;amp;nbsp;KB by default &amp;amp;#8211; the 1&amp;amp;nbsp;KB is there to accommodate the headers).  Use a colon (&amp;lt;tt&amp;gt;:&amp;lt;/tt&amp;gt;) to separate the two sizes when customizing this value.  If desired, support for second buffer size can be disabled by providing only one value to this option.&lt;br /&gt;
; ZOID_ACK_THRESHOLD (-a)&lt;br /&gt;
: Specifies a size threshold for the rendezvous protocol for messages coming from the compute nodes, in the units of tree network packets (240 bytes of data each).  An eager protocol is used for messages below the threshold.  Messages above the threshold use flow control in the form of a rendezvous protocol with message acknowledgements; basically, the daemon will only receive one large message at a time, which improves the predictability and an overall throughput.  The daemon default for this option is to not use the acknowledgements, but the config file defaults to a value of &amp;lt;tt&amp;gt;8&amp;lt;/tt&amp;gt;, which is the size of the hardware FIFO buffer of the tree network device.  Set this option to 0 (or comment it out altogether) to disable message acknowledgements.&lt;br /&gt;
; &amp;lt;span id=&amp;quot;opt_modules&amp;quot;&amp;gt;ZOID_MODULES (-m)&amp;lt;/span&amp;gt;&lt;br /&gt;
: Specifies a &amp;lt;tt&amp;gt;:&amp;lt;/tt&amp;gt;-separated list of ZOID plug-ins to load.  This defaults to &amp;lt;tt&amp;gt;&amp;quot;unix_impl.so:unix_preload.so:mapping_impl.so:mapping_preload.so&amp;quot;&amp;lt;/tt&amp;gt; in the config file; do not remove any of these or basic system services will stop working.  The &amp;lt;tt&amp;gt;unix&amp;lt;/tt&amp;gt; plug-in provide POSIX file I/O support, while &amp;lt;tt&amp;gt;mapping&amp;lt;/tt&amp;gt; is used by our MPI implementation to map between MPI ranks and Blue Gene X/Y/Z/T coordinates.  Custom plug-ins can be created and added here; see [[#Programmer interface|Programmer interface]] for details.&lt;br /&gt;
; &amp;lt;span id=&amp;quot;opt_enable_nat&amp;quot;&amp;gt;ZOID_ENABLE_NAT (-n)&amp;lt;/span&amp;gt;&lt;br /&gt;
: Enables network address translatation (NAT) for IP packets coming from the compute nodes, allowing compute nodes to communicate with the outside world.  This support is disabled by default because it was found to have a detrimental effect on the overall performance of the TCP/IP stack on the I/O nodes, slowing down network filesystems.  This feature can also be enabled on a per-job basis by setting the &amp;lt;tt&amp;gt;ZOID_ENABLE_NAT&amp;lt;/tt&amp;gt; environment variable when submitting a job (see the [[FAQ#How to open a socket from a CN to the outside world|FAQ]]).&lt;br /&gt;
; &amp;lt;span id=&amp;quot;opt_user_script&amp;quot;&amp;gt;ZOID_USER_SCRIPT (-u)&amp;lt;/span&amp;gt;&lt;br /&gt;
: Specifies the pathname to the [[#User script|user script]]; it defaults to &amp;lt;tt&amp;gt;&amp;quot;/bin.rd/zoid-user-script.sh&amp;quot;&amp;lt;/tt&amp;gt;.  This script can be found in &amp;lt;tt&amp;gt;ramdisk/ION/ramdisk-add/bin/zoid-user-script.sh&amp;lt;/tt&amp;gt;; it sets a few environment variables and then invokes user's custom &amp;lt;tt&amp;gt;$HOME/zoid-user-script.sh&amp;lt;/tt&amp;gt;.  Hence, to adjust the behavior of this feature, either change this option or the script in the ramdisk.&amp;lt;br/&amp;gt;'''Note:''' for this feature to work, [[#The /bin.rd/update_passwd_file.sh file|update_passwd_file.sh]] must be working correctly.&lt;br /&gt;
&lt;br /&gt;
===The /bin.rd/update_passwd_file.sh file===&lt;br /&gt;
&lt;br /&gt;
Allowing the partition owner to log into the I/O node using SSH is one of the features of the ZeptoOS software stack.  Only the administrator and the partition owner are given login access; this is controlled by the &amp;lt;tt&amp;gt;/bin.rd/update_passwd_file.sh&amp;lt;/tt&amp;gt; script, which is invoked by the daemon while the partition is being initialized.  The script can be found in &amp;lt;tt&amp;gt;ramdisk/ION/ramdisk-add/bin/update_passwd_file.sh&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
The script makes a number of assumptions that could be site-specific, so it might require an adjustment.  The daemon invokes the script passing a numerical UNIX user ID of the partition owner as the only argument.  The script then scans the &amp;lt;tt&amp;gt;/bgsys/iofs/etc/passwd&amp;lt;/tt&amp;gt; for an entry with the same user ID (on Argonne machines, this files contains all valid account names).  If a matching entry is found, it is appended to the &amp;lt;tt&amp;gt;/etc/passwd&amp;lt;/tt&amp;gt; file in the I/O node ramdisk, thus enabling login access to the node for that user.&lt;br /&gt;
&lt;br /&gt;
If allowing ordinary users access to the I/O nodes is undesirable, one can simply put &amp;lt;tt&amp;gt;exit 0&amp;lt;/tt&amp;gt; at the top of the script to disable it.&lt;br /&gt;
&lt;br /&gt;
===The /bin.rd/nat file===&lt;br /&gt;
&lt;br /&gt;
If NAT has been [[#opt_enable_nat|requested]], the daemon invokes the &amp;lt;tt&amp;gt;/bin.rd/nat&amp;lt;/tt&amp;gt; script to enabled it.  This script can be found in &amp;lt;tt&amp;gt;ramdisk/ION/ramdisk-add/bin/nat&amp;lt;/tt&amp;gt;.  Generally, it should not require any modifications.&lt;br /&gt;
&lt;br /&gt;
==Programmer interface==&lt;br /&gt;
&lt;br /&gt;
ZOID is a flexible, extensible, high-performance function call forwarding (RPC) infrastructure.  Built-in features and the standard plug-ins provide familiar POSIX file I/O and BSD socket interfaces, but, because of the number of software layers involved, they introduce a significant overhead.  For applications requiring maximum bandwidth between the compute and I/O nodes, ZOID provides an option of a customized function call forwarding with minimal overheads.  This section provides an overview of how to create such custom plug-ins.&lt;br /&gt;
&lt;br /&gt;
===Overview===&lt;br /&gt;
&lt;br /&gt;
All that ZOID provides is a function call forwarding support, and a limited one at that.  Any logic (caching, prefetching, etc.) needs to be custom-built on top of it.&lt;br /&gt;
&lt;br /&gt;
Follow existing plug-ins, found in &amp;lt;tt&amp;gt;packages/zoid/src/&amp;lt;/tt&amp;gt;, as examples.  The &amp;lt;tt&amp;gt;unix&amp;lt;/tt&amp;gt; plug-in is generally the most up to date, but other plug-ins such as &amp;lt;tt&amp;gt;mapping&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;zoidfs&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;barrier&amp;lt;/tt&amp;gt;, and &amp;lt;tt&amp;gt;test&amp;lt;/tt&amp;gt; should also be fine.&lt;br /&gt;
&lt;br /&gt;
A plug-in consists of automatically generated client-side and server-side stubs (which perform the marshalling and demarshalling of function call parameters and results, the forwarding of the function call, etc.), and of a hand-written server-side implementation which provides the implementation code for the forwarded function calls.  One might also decide to provide hand-written client-side wrappers to hide some details of the ZOID API (such as the error handling) or to adhere to a particular existing API, as is the case with the &amp;lt;tt&amp;gt;unix&amp;lt;/tt&amp;gt; plug-in (the wrappers used by the FUSE client are available in &amp;lt;tt&amp;gt;packages/zoid/src/unix/stubs/&amp;lt;/tt&amp;gt;; another version is in the GNU libc sources, in &amp;lt;tt&amp;gt;packages/glibc/src/zoid/sysdeps/unix/sysv/linux/powerpc/powerpc32/&amp;lt;/tt&amp;gt;).&lt;br /&gt;
&lt;br /&gt;
The &amp;lt;tt&amp;gt;scanner.pl&amp;lt;/tt&amp;gt; script, found in &amp;lt;tt&amp;gt;packages/zoid/src/&amp;lt;/tt&amp;gt;, creates the automatically-generated client and server stubs based on a hand-written input header file described below.  Again, please follow the examples from the existing plug-ins, such as &amp;lt;tt&amp;gt;unix&amp;lt;/tt&amp;gt; or &amp;lt;tt&amp;gt;mapping&amp;lt;/tt&amp;gt;.  The &amp;lt;tt&amp;gt;Makefile&amp;lt;/tt&amp;gt; in those plug-ins is written in a generic fashion and should only require a change to the &amp;lt;tt&amp;gt;PREFIX&amp;lt;/tt&amp;gt; line to be usable with another plug-in.  Use that &amp;lt;tt&amp;gt;Makefile&amp;lt;/tt&amp;gt; to invoke the &amp;lt;tt&amp;gt;scanner.pl&amp;lt;/tt&amp;gt; script and to compile the generated source files.&lt;br /&gt;
&lt;br /&gt;
===Input header file===&lt;br /&gt;
&lt;br /&gt;
The input header file must be a valid C header file with additional hints in the comments.  The file is read by the &amp;lt;tt&amp;gt;scanner.pl&amp;lt;/tt&amp;gt; script.&lt;br /&gt;
&lt;br /&gt;
The parser in the script is rather limited and does not handle many C constructs.  It is thus essential that the header file be as simple as possible.  In particular, function prototypes should be specified at the end of the file, not intermixed with any other specifications such as data type definitions.&lt;br /&gt;
&lt;br /&gt;
Ordinary comments are best placed on separate lines.&lt;br /&gt;
&lt;br /&gt;
'''Note:''' the parser is case ''sensitive''.&lt;br /&gt;
&lt;br /&gt;
====Start line====&lt;br /&gt;
&lt;br /&gt;
Any complex declarations that the scanner cannot parse should be placed at the top of the file, because the parser ignores everything until it encounters the following magic start line:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
/* START-ZOID-SCANNER ID=&amp;lt;n&amp;gt; INIT=&amp;lt;s1&amp;gt; FINI=&amp;lt;s2&amp;gt; PROC=&amp;lt;s3&amp;gt; */&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
; ID=&amp;lt;n&amp;gt;&lt;br /&gt;
: Each plug-in needs a unique, 16-bit identifier, passed in &amp;lt;tt&amp;gt;&amp;lt;n&amp;gt;&amp;lt;/tt&amp;gt;.  The following identifiers are already in use: &amp;lt;tt&amp;gt;0&amp;lt;/tt&amp;gt; (internal), &amp;lt;tt&amp;gt;1&amp;lt;/tt&amp;gt; (&amp;lt;tt&amp;gt;zoidfs&amp;lt;/tt&amp;gt; plug-in), &amp;lt;tt&amp;gt;2&amp;lt;/tt&amp;gt; (&amp;lt;tt&amp;gt;unix&amp;lt;/tt&amp;gt;), &amp;lt;tt&amp;gt;3&amp;lt;/tt&amp;gt; (&amp;lt;tt&amp;gt;lofar&amp;lt;/tt&amp;gt;), &amp;lt;tt&amp;gt;4&amp;lt;/tt&amp;gt; (&amp;lt;tt&amp;gt;test&amp;lt;/tt&amp;gt;), &amp;lt;tt&amp;gt;5&amp;lt;/tt&amp;gt; (&amp;lt;tt&amp;gt;mapping&amp;lt;/tt&amp;gt;), and &amp;lt;tt&amp;gt;10&amp;lt;/tt&amp;gt; (&amp;lt;tt&amp;gt;ftb&amp;lt;/tt&amp;gt;).&lt;br /&gt;
; INIT=&amp;lt;s1&amp;gt;&lt;br /&gt;
: &amp;lt;tt&amp;gt;&amp;lt;s1&amp;gt;&amp;lt;/tt&amp;gt; provides the name of an initialization function which will be invoked before a job starts running; see [[#Start-line functions|Start-line functions]] for more information.  If a plug-in does not need this feature, please specify &amp;lt;tt&amp;gt;INIT=NULL&amp;lt;/tt&amp;gt;.&lt;br /&gt;
; FINI=&amp;lt;s2&amp;gt;&lt;br /&gt;
: &amp;lt;tt&amp;gt;&amp;lt;s2&amp;gt;&amp;lt;/tt&amp;gt; provides the name of a termination function which will be invoked after all job processes have exited; see [[#Start-line functions|Start-line functions]] for more information.  If a plug-in does not need this feature, please specify &amp;lt;tt&amp;gt;FINI=NULL&amp;lt;/tt&amp;gt;.&lt;br /&gt;
; PROC=&amp;lt;s3&amp;gt;&lt;br /&gt;
: &amp;lt;tt&amp;gt;&amp;lt;s3&amp;gt;&amp;lt;/tt&amp;gt; provides the name of a callback function which will be invoked on a startup and termination of every application and ZOID-enabled process; see [[#Start-line functions|Start-line functions]] for more information.  If a plug-in does not need this feature, please specify &amp;lt;tt&amp;gt;PROC=NULL&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
====Argument hints====&lt;br /&gt;
&lt;br /&gt;
Hints are generally needed by the scanner to correctly encode and decode function arguments.  They need to be placed after each argument, before a separating comma (or a closing bracket), and should be embedded inside dedicated C comments.  Multiple hints per argument are usually provided; these are separated by a colon (&amp;lt;tt&amp;gt;:&amp;lt;/tt&amp;gt;). The following hints are currently defined:&lt;br /&gt;
&lt;br /&gt;
; in, out, inout&lt;br /&gt;
: Specifies whether the argument is an input argument, an output argument, or both.  &amp;lt;tt&amp;gt;in&amp;lt;/tt&amp;gt; is the default.&lt;br /&gt;
; obj, str, ptr, arr, arr2d&lt;br /&gt;
: Specifies the type of the argument, respectively a plain object (say, an &amp;lt;tt&amp;gt;int&amp;lt;/tt&amp;gt;, or a structure passed by value), a &amp;lt;tt&amp;gt;'\0'&amp;lt;/tt&amp;gt;-terminated character string, a pointer to a plain object, an array of objects, or a two-dimensional array (&amp;lt;tt&amp;gt;type**&amp;lt;/tt&amp;gt;, not &amp;lt;tt&amp;gt;type[][]&amp;lt;/tt&amp;gt;).  &amp;lt;tt&amp;gt;obj&amp;lt;/tt&amp;gt; is the default.&lt;br /&gt;
; size&lt;br /&gt;
: Required for array arguments (&amp;lt;tt&amp;gt;arr&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;arr2d&amp;lt;/tt&amp;gt;).  Indicates the index of another argument in the same function, which is used to pass the array size.  Absolute numbers are accepted (&amp;lt;tt&amp;gt;1&amp;lt;/tt&amp;gt; to ''number of arguments'') or relative ones (&amp;lt;tt&amp;gt;+1&amp;lt;/tt&amp;gt; for the next argument, &amp;lt;tt&amp;gt;-1&amp;lt;/tt&amp;gt; for the previous argument, etc).&amp;lt;br/&amp;gt;  For &amp;lt;tt&amp;gt;arr&amp;lt;/tt&amp;gt; arguments, the size argument must be of a numerical type, or a pointer to such a type.  For &amp;lt;tt&amp;gt;arr2d&amp;lt;/tt&amp;gt; arguments, the size argument must itself be an array (an &amp;lt;tt&amp;gt;arr&amp;lt;/tt&amp;gt; argument) of numerical elements, specifying the sizes along the less significant dimension of the array (the size of the more significant dimension is the size of the &amp;lt;tt&amp;gt;arr&amp;lt;/tt&amp;gt; array itself).&amp;lt;br/&amp;gt;  Please note that the unit of size for the numerical types is the size of the base array type (thus, &amp;lt;tt&amp;gt;sizeof(int)&amp;lt;/tt&amp;gt; for an array of &amp;lt;tt&amp;gt;int&amp;lt;/tt&amp;gt;s), not byte (if one would like it to be byte, just make the array argument have type &amp;lt;tt&amp;gt;char*&amp;lt;/tt&amp;gt; or &amp;lt;tt&amp;gt;void*&amp;lt;/tt&amp;gt; (a GCC extension)).&lt;br /&gt;
; nullok&lt;br /&gt;
: An option for arguments passed by pointer (basically, all but &amp;lt;tt&amp;gt;obj&amp;lt;/tt&amp;gt;).  If provided, it indicates that the argument is allowed to be &amp;lt;tt&amp;gt;NULL&amp;lt;/tt&amp;gt;.  This is not the default because supporting &amp;lt;tt&amp;gt;NULL&amp;lt;/tt&amp;gt; pointers results in an additional computational and protocol overhead.  '''Note:''' if a &amp;lt;tt&amp;gt;NULL&amp;lt;/tt&amp;gt; pointer is passed to an argument that lacks the &amp;lt;tt&amp;gt;nullok&amp;lt;/tt&amp;gt; flag, the client ''will'' crash.&lt;br /&gt;
; zerocopy&lt;br /&gt;
: An option for array arguments.  Enables a more efficient marshalling/demarshalling protocol for the array, which does not use extra memory copies.  Can be used for no more than one &amp;lt;tt&amp;gt;in&amp;lt;/tt&amp;gt; argument and no more than one &amp;lt;tt&amp;gt;out&amp;lt;/tt&amp;gt; argument.  [[#Zerocopy performance|Zerocopy performance]] discusses performance considerations when using this option.&lt;br /&gt;
; userbuf&lt;br /&gt;
: An option for &amp;lt;tt&amp;gt;zerocopy&amp;lt;/tt&amp;gt;; only supported for &amp;lt;tt&amp;gt;arr&amp;lt;/tt&amp;gt; arguments.  Enables a special form of zero-copy support, discussed in [[#Zerocopy with a custom output buffer|Zerocopy with a custom output buffer]] and [[#Zerocopy with a custom input buffer|Zerocopy with a custom input buffer]].&lt;br /&gt;
&lt;br /&gt;
Here is an example function prototype with the hints:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
int zoidfs_readlink(const zoidfs_handle_t * handle /* in:ptr */,&lt;br /&gt;
                    char * buffer /* out:arr:size=+1 */,&lt;br /&gt;
                    size_t buffer_length /* in:obj */);&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
====Limitations====&lt;br /&gt;
&lt;br /&gt;
As indicated earlier, the scanner is limited, so keep the prototypes simple.&lt;br /&gt;
&lt;br /&gt;
Return type of a forwarded function must be scalar or &amp;lt;tt&amp;gt;void&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Structures with pointer fields inside of them cannot be forwarded.&lt;br /&gt;
&lt;br /&gt;
====Generated files====&lt;br /&gt;
&lt;br /&gt;
For every function prototype found, the scanner generates two output files: one for a client calling the function and one for the server, where the function is in fact executed.  Code in the generated files performs marshalling and demarshalling of function arguments and results.&lt;br /&gt;
&lt;br /&gt;
Two more files per plug-in are generated: ''header''&amp;lt;tt&amp;gt;_defs.h&amp;lt;/tt&amp;gt; and ''header''&amp;lt;tt&amp;gt;_dispatch.c&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
None of the generated files should be modified.&lt;br /&gt;
&lt;br /&gt;
===Server-side API===&lt;br /&gt;
&lt;br /&gt;
Server-side stubs and the server-side implementation need to be passed as modules when invoking the ZOID I/O daemon, as described [[#opt_modules|earlier]].&lt;br /&gt;
&lt;br /&gt;
The hand-written server-side implementation code should include the &amp;lt;tt&amp;gt;zoid_api.h&amp;lt;/tt&amp;gt; header file (available from &amp;lt;tt&amp;gt;packages/zoid/prebuilt/&amp;lt;/tt&amp;gt;) and the plug-in input header file.&lt;br /&gt;
&lt;br /&gt;
All the functions listed in the header file need to be defined in the server-side implementation code.  The code needs to be compiled as a shared library; use the &amp;lt;tt&amp;gt;implementation/&amp;lt;/tt&amp;gt; subdirectory of the &amp;lt;tt&amp;gt;unix&amp;lt;/tt&amp;gt; plug-in as an example.  Please note that since ZOID is multi-threaded, multiple functions can be invoked at the same time, so one must ensure that the implementation is multi-thread-safe.&lt;br /&gt;
&lt;br /&gt;
====Start-line functions====&lt;br /&gt;
&lt;br /&gt;
The following [[#Start line|start-line]] functions can be defined:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
void INIT(int pset_mpi_proc_count, int argc, int envc, const char* argenv);&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The INIT function is invoked during initialization, right before a job starts running.  Arguments:&lt;br /&gt;
&lt;br /&gt;
; pset_mpi_proc_count&lt;br /&gt;
: The number of job processes that will be handled by this I/O node.  Note that I/O nodes also handle additional ZOID-enabled processes, such as the FUSE clients, which are not included in this number.&lt;br /&gt;
; argc&lt;br /&gt;
: The number of command-line arguments plus one.&lt;br /&gt;
; envc&lt;br /&gt;
: The number of environment variables.&lt;br /&gt;
; argenv&lt;br /&gt;
: An array of &amp;lt;tt&amp;gt;'\0'&amp;lt;/tt&amp;gt;-terminated strings, one after another.  The first string is the name of the job executable, followed by &amp;lt;tt&amp;gt;argc-1&amp;lt;/tt&amp;gt; command-line arguments, followed by &amp;lt;tt&amp;gt;envc&amp;lt;/tt&amp;gt; environment variables.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
void FINI(void);&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The FINI function is invoked after the last process of the job has terminated.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
void PROC(int added, int pset_pid);&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The PROC function is invoked on the startup and termination of every application and ZOID-enabled process on the compute node.  Arguments:&lt;br /&gt;
&lt;br /&gt;
; added&lt;br /&gt;
: &amp;lt;tt&amp;gt;1&amp;lt;/tt&amp;gt; if the process was started, &amp;lt;tt&amp;gt;0&amp;lt;/tt&amp;gt; if it was terminated.&lt;br /&gt;
; pset_pid&lt;br /&gt;
: A process identifier (as returned by [[#Implementation functions|&amp;lt;tt&amp;gt;__zoid_calling_process_id&amp;lt;/tt&amp;gt;]]).&lt;br /&gt;
&lt;br /&gt;
====Implementation functions====&lt;br /&gt;
&lt;br /&gt;
The hand-written server-side implementation functions can themselves call back a few ZOID functions, available by including the &amp;lt;tt&amp;gt;zoid_api.h&amp;lt;/tt&amp;gt; header file:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
int __zoid_calling_process_id(void);&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This function returns a unique identifier of the compute node process that invoked the function.  The identifier is ''not'' an MPI rank, because some processes, such as the FUSE clients, are not part of the application and hence do not have a rank.  The identifiers are only unique within one I/O node, and they can be reused if a process starts after another one has terminated.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
void __zoid_register_userbuf(void* userbuf,&lt;br /&gt;
                             void (*callback)(void* userbuf, void* priv),&lt;br /&gt;
                             void* priv);&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This function will be discussed in [[#Zerocopy with a custom output buffer|Zerocopy with a custom output buffer]].&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
int __zoid_send_output(int pid, int fd, const char* buffer, int len);&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This function writes an arbitrary string to the job's standard output or error.  Arguments:&lt;br /&gt;
&lt;br /&gt;
; pid&lt;br /&gt;
: Process identifier as returned by &amp;lt;tt&amp;gt;__zoid_calling_process_id&amp;lt;/tt&amp;gt;.  The process in question ''must'' have an MPI rank, meaning that it must be either an application process or a process launched from an application process.&lt;br /&gt;
; fd&lt;br /&gt;
: &amp;lt;tt&amp;gt;1&amp;lt;/tt&amp;gt; for standard output, &amp;lt;tt&amp;gt;2&amp;lt;/tt&amp;gt; for standard error.&lt;br /&gt;
; buffer, len&lt;br /&gt;
: The string and its length.  &amp;lt;tt&amp;gt;'\0'&amp;lt;/tt&amp;gt; should not be included in &amp;lt;tt&amp;gt;len&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;buffer&amp;lt;/tt&amp;gt; does not need to be &amp;lt;tt&amp;gt;'\0'&amp;lt;/tt&amp;gt;-terminated.&lt;br /&gt;
&lt;br /&gt;
The function returns 0 if successful, and -1 if not (such as when the process identified by &amp;lt;tt&amp;gt;pid&amp;lt;/tt&amp;gt; does not have an MPI rank).&lt;br /&gt;
&lt;br /&gt;
===Client-side API===&lt;br /&gt;
&lt;br /&gt;
A compute node application needs to be linked with the client-side stubs and with a common support library &amp;lt;tt&amp;gt;libzoid_cn.a&amp;lt;/tt&amp;gt; (a prebuilt version of the latter is in &amp;lt;tt&amp;gt;packages/zoid/prebuilt&amp;lt;/tt&amp;gt;; sources are in &amp;lt;tt&amp;gt;packages/zoid/src/cnl/client&amp;lt;/tt&amp;gt;).  Several functions are available to applications by including the &amp;lt;tt&amp;gt;zoid_api.h&amp;lt;/tt&amp;gt; header file:&lt;br /&gt;
&lt;br /&gt;
====Initialization====&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
int __zoid_init(void);&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This function ''must'' be invoked before any ZOID or ZOID-forwarded functions can be invoked.  It returns &amp;lt;tt&amp;gt;0&amp;lt;/tt&amp;gt; if successful, &amp;lt;tt&amp;gt;1&amp;lt;/tt&amp;gt; otherwise.  There is no corresponding termination function.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
int __zoid_job_size(void);&lt;br /&gt;
int __zoid_my_rank(void);&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
These functions return, respectively, the number of processes in the job (the size of &amp;lt;tt&amp;gt;MPI_COMM_WORLD&amp;lt;/tt&amp;gt;), and the MPI rank of the&lt;br /&gt;
current process.  Either will return &amp;lt;tt&amp;gt;-1&amp;lt;/tt&amp;gt; if the current process does not have an MPI rank, i.e., if it is not an application process and was not launched from an application process (say, if it was launched from an interactive shell).&lt;br /&gt;
&lt;br /&gt;
====Error conditions====&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
int __zoid_error(void);&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This function should be invoked on the client side after ''every'' forwarded function call returns, to determine if any errors occured within the forwarding layer.  A return value of &amp;lt;tt&amp;gt;0&amp;lt;/tt&amp;gt; indicates a success; otherwise, one of the following error values will be returned:&lt;br /&gt;
&lt;br /&gt;
; ENOSYS&lt;br /&gt;
: Invalid command sent from the client.  Typically indicates that the corresponding I/O-node-side [[#opt_modules|modules]] have not been loaded.&lt;br /&gt;
; ENOMEM&lt;br /&gt;
: Out of memory condition.&lt;br /&gt;
; E2BIG&lt;br /&gt;
: Message exceeded the internal size limit.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
int __zoid_excessive_size(void);&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
If &amp;lt;tt&amp;gt;__zoid_error&amp;lt;/tt&amp;gt; returned &amp;lt;tt&amp;gt;E2BIG&amp;lt;/tt&amp;gt;, calling this function will provide an indication of by how many bytes the input or output was too large.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;span id=&amp;quot;size_restrictions&amp;quot;&amp;gt;ZOID&amp;lt;/span&amp;gt; [[#opt_buffer_size|has a limit]] on the message size, around 4&amp;amp;nbsp;MB by default.  The limit is enforced on both input and output.  The limit only applies to buffers &amp;quot;owned&amp;quot; by ZOID on the daemon side; it does not apply to custom [[#Zerocopy with a custom input buffer|input]] or [[#Zerocopy with a custom output buffer|output]] buffers.&lt;br /&gt;
&lt;br /&gt;
If the limit is hit, the operation needs to be split into smaller ones.  Information returned by &amp;lt;tt&amp;gt;__zoid_excessive_size&amp;lt;/tt&amp;gt; makes it easy to adjust the buffer and resubmit.&lt;br /&gt;
&lt;br /&gt;
'''Note:''' While the input-side (argument) overflow is flagged immediately on the client side, and is thus fairly cheap to hit, the output-side (result) overflow is flagged on the I/O node, after the request has been sent there (but before the implementation function is invoked).  It is thus advised to cache at least the size limit for the output side for the next invocation, to avoid a future communication overhead.  The size limit is function-specific, since it depends on sizes of other arguments and results.&lt;br /&gt;
&lt;br /&gt;
Here is an example of how the client-side convenience wrapper for a call such as POSIX &amp;lt;tt&amp;gt;read&amp;lt;/tt&amp;gt; could be implemented:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
ssize_t read(int fd, void *buf, size_t nbytes)&lt;br /&gt;
{&lt;br /&gt;
    static ssize_t max_read_nbytes = -1;&lt;br /&gt;
    ssize_t bytes_read;&lt;br /&gt;
&lt;br /&gt;
    bytes_read = 0;&lt;br /&gt;
    do&lt;br /&gt;
    {&lt;br /&gt;
        ssize_t toread, justread;&lt;br /&gt;
        int error;&lt;br /&gt;
&lt;br /&gt;
        toread = nbytes - bytes_read;&lt;br /&gt;
&lt;br /&gt;
        if (max_read_nbytes != -1 &amp;amp;&amp;amp; toread &amp;gt; max_read_nbytes)&lt;br /&gt;
            toread = max_read_nbytes;&lt;br /&gt;
&lt;br /&gt;
        /* unix_read is the forwarded function call.  */&lt;br /&gt;
        justread = unix_read(fd, buf + bytes_read, toread);&lt;br /&gt;
&lt;br /&gt;
        if ((error = __zoid_error()))&lt;br /&gt;
        {&lt;br /&gt;
            if (error != E2BIG)&lt;br /&gt;
            {&lt;br /&gt;
                /* For a generic ZOID error, just bail out.  */&lt;br /&gt;
                errno = error;&lt;br /&gt;
                return -1;&lt;br /&gt;
            }&lt;br /&gt;
&lt;br /&gt;
            /* We tried to send a too large read request.  Adjust.  */&lt;br /&gt;
            max_read_nbytes = toread - __zoid_excessive_size();&lt;br /&gt;
        }&lt;br /&gt;
        else&lt;br /&gt;
        {&lt;br /&gt;
            if (justread &amp;lt; 0)&lt;br /&gt;
            {&lt;br /&gt;
                /* For a generic read() error, just bail out.&lt;br /&gt;
                   In case of an I/O error, unix_read returns -errno.  */&lt;br /&gt;
                errno = -justread;&lt;br /&gt;
                return -1;&lt;br /&gt;
            }&lt;br /&gt;
&lt;br /&gt;
            bytes_read += justread;&lt;br /&gt;
&lt;br /&gt;
            if (justread != toread)&lt;br /&gt;
                /* unix_read as such succeeded, but it read fewer bytes than&lt;br /&gt;
                   expected.  We terminate prematurely then.  */&lt;br /&gt;
                break;&lt;br /&gt;
        }&lt;br /&gt;
    } while (bytes_read &amp;lt; nbytes);&lt;br /&gt;
&lt;br /&gt;
    return bytes_read;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Additional considerations===&lt;br /&gt;
&lt;br /&gt;
====Forwarding &amp;lt;tt&amp;gt;errno&amp;lt;/tt&amp;gt;====&lt;br /&gt;
&lt;br /&gt;
If one needs to pass a variable such as &amp;lt;tt&amp;gt;errno&amp;lt;/tt&amp;gt; from the I/O node to the client, the most straightforward way is to add an extra integer &amp;lt;tt&amp;gt;out&amp;lt;/tt&amp;gt; pointer argument to all functions and pass it that way.  Another option is to do it the same way the UNIX kernel does: pass it as a negative return value from the functions.  The &amp;lt;tt&amp;gt;unix&amp;lt;/tt&amp;gt; plug-in does it that way, so, e.g., the implementation of &amp;lt;tt&amp;gt;close&amp;lt;/tt&amp;gt; on the I/O node looks something like this:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
if (close(server_fd) == -1)&lt;br /&gt;
    return -errno;&lt;br /&gt;
else&lt;br /&gt;
    return 0;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Then, on the client side, we have a convenience wrapper:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
int close(int fd)&lt;br /&gt;
{&lt;br /&gt;
    return unix_decode_result(unix_close(fd));&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;unix_decode_result&amp;lt;/tt&amp;gt; is a preprocessor macro that handles both ZOID errors and errors returned by the plug-in.  It uses a number of GCC extensions to make it as transparent as possible:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
#define unix_decode_result(result)      \&lt;br /&gt;
({                                      \&lt;br /&gt;
    typeof (result) _result = (result); \&lt;br /&gt;
    int _n;                             \&lt;br /&gt;
    if ((_n = __zoid_error()) != 0)     \&lt;br /&gt;
    {                                   \&lt;br /&gt;
        errno = _n;                     \&lt;br /&gt;
        _result = -1;                   \&lt;br /&gt;
    }                                   \&lt;br /&gt;
    else if (_result &amp;lt; 0)               \&lt;br /&gt;
    {                                   \&lt;br /&gt;
        errno = -_result;               \&lt;br /&gt;
        _result = -1;                   \&lt;br /&gt;
    }                                   \&lt;br /&gt;
    _result;                            \&lt;br /&gt;
})&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
====Returning variable amounts of data in arrays====&lt;br /&gt;
&lt;br /&gt;
Just like with UNIX system calls, ZOID does not allocate memory for the results.  Instead, callers must provide pre-allocated arrays, along with their sizes.  UNIX would then typically return the size of the used part as a return value from a system call.  Unfortunately, ZOID cannot make use of that &amp;amp;#8211; it will use the same array size argument to determine how much data to send back, so even if only a small part of the provided buffer is actually filled in, the whole buffer will be sent back, which is inefficient.  This can be prevented by passing the array size as an &amp;lt;tt&amp;gt;inout&amp;lt;/tt&amp;gt; pointer to a numerical type.  A server-side implementation of a function such as &amp;lt;tt&amp;gt;read&amp;lt;/tt&amp;gt; then looks like this:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
ssize_t unix_read(int fd /* in:obj */,&lt;br /&gt;
                  void *buf /* out:arr:size=+1 */,&lt;br /&gt;
                  size_t *count /* inout:ptr */)&lt;br /&gt;
{&lt;br /&gt;
    ssize_t ret;&lt;br /&gt;
&lt;br /&gt;
    ...&lt;br /&gt;
&lt;br /&gt;
    if ((ret = read(fd, buf, *count)) == -1)&lt;br /&gt;
    {&lt;br /&gt;
        *count = 0;&lt;br /&gt;
        return -errno;&lt;br /&gt;
    }&lt;br /&gt;
    else&lt;br /&gt;
    {&lt;br /&gt;
        *count = ret;&lt;br /&gt;
        return ret;&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Obviously, the client side needs to be modified as well, to pass the size argument by address.&lt;br /&gt;
&lt;br /&gt;
'''Note:''' this feature has certain implementation limitations.  It can misbehave in the presence of multiple output arrays (or a single output &amp;lt;tt&amp;gt;arr2d&amp;lt;/tt&amp;gt;, which internally behaves a lot like multiple separate &amp;lt;tt&amp;gt;arr&amp;lt;/tt&amp;gt;s).  Essentially, for efficiency reasons, the placement of arrays in the result buffer is determined before an implementation function is invoked.  If this feature is used to change the size of one array, and that array is followed in the output buffer by another array, a &amp;quot;hole&amp;quot; will be created in the buffer, causing problems.  However, in the most common case of a single output array the feature is completely reliable.&lt;br /&gt;
&lt;br /&gt;
====Zerocopy performance====&lt;br /&gt;
&lt;br /&gt;
Implementation-wise, ZOID is always zero-copy on the server side, meaning that data that implementation functions put in the &amp;lt;tt&amp;gt;out&amp;lt;/tt&amp;gt; arrays is sent to the compute nodes without any extra memory copies.&lt;br /&gt;
&lt;br /&gt;
Client side is only zero-copy for arrays that use the &amp;lt;tt&amp;gt;zerocopy&amp;lt;/tt&amp;gt; flag in the header file.  Because of the additial protocol overheads that &amp;lt;tt&amp;gt;zerocopy&amp;lt;/tt&amp;gt; introduces, it should be used only for potentially large memory buffers, such as the buffers of file I/O &amp;lt;tt&amp;gt;read&amp;lt;/tt&amp;gt; or &amp;lt;tt&amp;gt;write&amp;lt;/tt&amp;gt; calls.&lt;br /&gt;
&lt;br /&gt;
'''Note:''' for maximum performance, the arrays passed as &amp;lt;tt&amp;gt;zerocopy&amp;lt;/tt&amp;gt; arguments on the compute nodes must be aligned in memory to the 16-bytes boundary; otherwise, an interim buffer will be used.  The memory allocation routines such as &amp;lt;tt&amp;gt;malloc&amp;lt;/tt&amp;gt; have been modified to align memory to that boundary.  If there is a danger that the user code might pass a large unaligned buffer, and the semantics will not be affected, it makes sense to write code that detects insufficient alignment and splits the operation in two: a small unaligned one (say, up to 240 bytes &amp;amp;#8211; the data payload of a single packet on the tree network), followed by a larger, properly aligned one.&lt;br /&gt;
&lt;br /&gt;
====Zerocopy with a custom output buffer====&lt;br /&gt;
&lt;br /&gt;
Normally, memory for output arrays to be filled in by server-side implementation functions is allocated by the ZOID daemon.  This might be inconvenient when the data to be filled arrives asynchronously, possibly before the implementation function is even invoked; in such situations, an interim memory buffer must be used, forcing an extra memory copy.&lt;br /&gt;
&lt;br /&gt;
This can be avoided for zero-copy output &amp;lt;tt&amp;gt;arr&amp;lt;/tt&amp;gt; types if the &amp;lt;tt&amp;gt;userbuf&amp;lt;/tt&amp;gt; flag has been used.  No space will then be preallocated by the daemon for the array (the server-side stub will pass a &amp;lt;tt&amp;gt;NULL&amp;lt;/tt&amp;gt; pointer); instead, the implementation function must provide the daemon with its own buffer.  It can do it by calling:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
void __zoid_register_userbuf(void* userbuf,&lt;br /&gt;
                             void (*callback)(void* userbuf, void* priv),&lt;br /&gt;
                             void* priv);&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Arguments:&lt;br /&gt;
&lt;br /&gt;
; userbuf&lt;br /&gt;
: The address of the buffer.&lt;br /&gt;
; callback&lt;br /&gt;
: A callback function that is invoked by the daemon when the buffer has been sent to the client and is thus no longer needed.  &amp;lt;tt&amp;gt;userbuf&amp;lt;/tt&amp;gt; is passed as the first argument to the callback.  It is safe for the callback to invoke &amp;lt;tt&amp;gt;__zoid_calling_process_id&amp;lt;/tt&amp;gt;.&lt;br /&gt;
; priv&lt;br /&gt;
: A private data passed as the second argument to the &amp;lt;tt&amp;gt;callback&amp;lt;/tt&amp;gt;.  It is not interpreted by ZOID in any way.&lt;br /&gt;
&lt;br /&gt;
The size of the provided buffer is determined like for any other array argument: the maximum value is provided by the client via the &amp;lt;tt&amp;gt;size&amp;lt;/tt&amp;gt; argument.  The server-side implementation part may choose to return less than the maximum amount, as explained [[#Returning variable amounts of data in arrays|earlier]].&lt;br /&gt;
&lt;br /&gt;
As in other zero-copy cases, for maximum performance, the buffer provided must be aligned in memory to the 16-bytes boundary; otherwise, an interim buffer will be used.  The memory allocation routines such as &amp;lt;tt&amp;gt;malloc&amp;lt;/tt&amp;gt; have been modified to align memory to that boundary, but we recommend explicitly calling &amp;lt;tt&amp;gt;posix_memalign&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
'''Note:''' because the buffer provided is ''not'' allocated by ZOID, message size restrictions discussed [[#size_restrictions|earlier]] do not apply to it.  Please do not abuse this capability.  There is a good reason for the message size limit: it is there so that the maximum amount of memory required by the ZOID daemon stays limited.  Too many too large user-allocated buffers might result in an out-of-memory condition on the I/O node.&lt;br /&gt;
&lt;br /&gt;
We provide a simple example below.  It is a little artificial in the sense that the buffer is allocated within the implementation function; as we indicated, this feature is most useful with buffers allocated outside of the implementation functions:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
static void buffer_cb(void* userbuf, void* priv)&lt;br /&gt;
{&lt;br /&gt;
    free(userbuf);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
ssize_t unix_read(int fd /* in:obj */,&lt;br /&gt;
                  void *buf /* out:arr:size=+1:zerocopy:userbuf */,&lt;br /&gt;
                  size_t *count /* inout:ptr */)&lt;br /&gt;
{&lt;br /&gt;
    ssize_t ret;&lt;br /&gt;
&lt;br /&gt;
    ...&lt;br /&gt;
&lt;br /&gt;
    if (posix_memalign(&amp;amp;buf, 16, *count))&lt;br /&gt;
    {&lt;br /&gt;
        *count = 0;&lt;br /&gt;
        return -ENOMEM;&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    __zoid_register_userbuf(buf, &amp;amp;buffer_cb, NULL);&lt;br /&gt;
&lt;br /&gt;
    if ((ret = read(fd, buf, *count)) == -1)&lt;br /&gt;
    {&lt;br /&gt;
        *count = 0;&lt;br /&gt;
        return -errno;&lt;br /&gt;
    }&lt;br /&gt;
    else&lt;br /&gt;
    {&lt;br /&gt;
        *count = ret;&lt;br /&gt;
        return ret;&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
====Zerocopy with a custom input buffer====&lt;br /&gt;
&lt;br /&gt;
The &amp;lt;tt&amp;gt;userbuf&amp;lt;/tt&amp;gt; flag discussed above can also be used for ''input'' zero-copy &amp;lt;tt&amp;gt;arr&amp;lt;/tt&amp;gt; arguments.  This could be useful to avoid extra memory copies if the data in the array will be needed after the implementation function has returned.&lt;br /&gt;
&lt;br /&gt;
If the flag is used, the daemon will not allocate the memory for the array; instead, in the middle of receiving the request from the client, it will call an allocation routine from the server-side implementation code.  The name of the allocation routine is the name of the function that uses the input &amp;lt;tt&amp;gt;userbuf&amp;lt;/tt&amp;gt; argument, with &amp;lt;tt&amp;gt;_allocate_cb&amp;lt;/tt&amp;gt; suffix attached to it.  Its prototype needs to be as follows:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
void* &amp;lt;name&amp;gt;_allocate_cb(int len);&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The single argument passed by the daemon is the length of the array in bytes.  The routine must return a pointer to a buffer of that size or &amp;lt;tt&amp;gt;NULL&amp;lt;/tt&amp;gt; if that is not possible (in which case, the function will fail and &amp;lt;tt&amp;gt;__zoid_error&amp;lt;/tt&amp;gt; on the client side will return &amp;lt;tt&amp;gt;ENOMEM&amp;lt;/tt&amp;gt;).&lt;br /&gt;
&lt;br /&gt;
There is a restriction on the type of the array: its base type must have a size of one byte, so the array should be of type &amp;lt;tt&amp;gt;char*&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;unsigned char*&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;void*&amp;lt;/tt&amp;gt; (a GCC extension), etc.&lt;br /&gt;
&lt;br /&gt;
The allocation routine is invoked in the same context as ordinary implementation functions.  It may block if it so desires; this will block the compute node client that invoked the routine, but all other clients can keep communicating with the server, thanks to its multi-threaded architecture.&lt;br /&gt;
&lt;br /&gt;
Once the allocation routine has returned and a complete request has been received by the daemon, the implementation function is invoked as usual, with a correct address of the input &amp;lt;tt&amp;gt;userbuf&amp;lt;/tt&amp;gt; array.  It is the responsibility of the plug-in implementer to release the memory occupied by that array when it is no longer needed.&lt;br /&gt;
&lt;br /&gt;
As with other user-level callbacks, the allocation routine may call &amp;lt;tt&amp;gt;__zoid_calling_process_id&amp;lt;/tt&amp;gt; to learn which client process sent the request.  Also, as in other zero-copy cases, for maximum performance, the buffer provided must be aligned in memory to the 16-bytes boundary; otherwise, an interim buffer will be used.  The memory allocation routines such as &amp;lt;tt&amp;gt;malloc&amp;lt;/tt&amp;gt; have been modified to align memory to that boundary, but we recommend explicitly calling &amp;lt;tt&amp;gt;posix_memalign&amp;lt;/tt&amp;gt;.  Finally, as with output &amp;lt;tt&amp;gt;userbuf&amp;lt;/tt&amp;gt;, message size restrictions discussed [[#size_restrictions|earlier]] do not apply to the user-allocated buffers.  Please do not abuse this capability.  There is a good reason for the message size limit: it is there so that the maximum amount of memory required by the ZOID daemon stays limited.  Too many too large user-allocated buffers might result in an out-of-memory condition on the I/O node.&lt;br /&gt;
&lt;br /&gt;
Under rare circumstances, input &amp;lt;tt&amp;gt;userbuf&amp;lt;/tt&amp;gt; could result in memory leaks.  For this to take place, the job would have to be interrupted after the allocation routine has been run, but before the implementation function is called.  This could only cause problems if I/O nodes are not rebooted between jobs.  Those concerned about this scenario can eliminate the leak by adding necessary memory release code to the [[#Start-line functions|FINI]] function.&lt;br /&gt;
&lt;br /&gt;
A simple example:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
void* unix_write_allocate_cb(int len)&lt;br /&gt;
{&lt;br /&gt;
    void* ptr;&lt;br /&gt;
&lt;br /&gt;
    if (posix_memalign(&amp;amp;ptr, 16, len))&lt;br /&gt;
        return NULL;&lt;br /&gt;
&lt;br /&gt;
    return ptr;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
ssize_t unix_write(int fd /* in:obj */,&lt;br /&gt;
                   const void *buf /* in:arr:size=+1:zerocopy:userbuf */,&lt;br /&gt;
                   size_t count /* in:obj */)&lt;br /&gt;
{&lt;br /&gt;
    ssize_t ret;&lt;br /&gt;
&lt;br /&gt;
    ...&lt;br /&gt;
&lt;br /&gt;
    if ((ret = write(fd, buf, count)) == -1)&lt;br /&gt;
        ret = -errno;&lt;br /&gt;
&lt;br /&gt;
    free((void*)buf);&lt;br /&gt;
&lt;br /&gt;
    return ret;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
[[Ramdisk]] | [[ZeptoOS_Documentation|Top]] | [[(K)TAU]]&lt;/div&gt;</summary>
		<author><name>Iskra</name></author>
	</entry>
	<entry>
		<id> /zeptoos/index.php?title=ZOID&amp;diff=571</id>
		<title>ZOID</title>
		<link rel="alternate" type="text/html" href=" /zeptoos/index.php?title=ZOID&amp;diff=571"/>
		<updated>2009-05-07T20:22:41Z</updated>

		<summary type="html">&lt;p&gt;Iskra: /* User script */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;[[Ramdisk]] | [[ZeptoOS_Documentation|Top]] | [[(K)TAU]]&lt;br /&gt;
----&lt;br /&gt;
&lt;br /&gt;
==Introduction==&lt;br /&gt;
&lt;br /&gt;
ZOID is an I/O forwarding component of the ZeptoOS project.  Any communication between the compute nodes and the I/O nodes (job management, file I/O, sockets) is handled by ZOID.&lt;br /&gt;
&lt;br /&gt;
ZOID infrastructure consists of:&lt;br /&gt;
* A multithreaded &amp;lt;tt&amp;gt;zoid&amp;lt;/tt&amp;gt; daemon on the I/O nodes which performs I/O forwarding for the compute nodes and which also communicates with the service node to perform job management,&lt;br /&gt;
* &amp;lt;tt&amp;gt;control&amp;lt;/tt&amp;gt; daemon on the compute nodes which is responsible for job management tasks such as the launching of application processes, for the forwarding of &amp;lt;tt&amp;gt;stdin&amp;lt;/tt&amp;gt;/&amp;lt;tt&amp;gt;out&amp;lt;/tt&amp;gt;/&amp;lt;tt&amp;gt;err&amp;lt;/tt&amp;gt; data, and for forwarding of IP packets,&lt;br /&gt;
* &amp;lt;tt&amp;gt;zoid-fuse&amp;lt;/tt&amp;gt; daemon on the compute nodes which performs file I/O forwarding for POSIX-compliant applications.&lt;br /&gt;
&lt;br /&gt;
==User interface==&lt;br /&gt;
&lt;br /&gt;
ZOID is meant to be transparent to users, but there are a few optional mechanisms available to interact with it.&lt;br /&gt;
&lt;br /&gt;
===User script===&lt;br /&gt;
&lt;br /&gt;
Right before a job starts running, and right after the last process of a job has terminated, ZOID daemon attempts to invoke a ''user script'' on I/O nodes.  By default, the daemon invokes &amp;lt;tt&amp;gt;$HOME/zoid-user-script.sh&amp;lt;/tt&amp;gt; (this pathname can be [[#opt_user_script|changed]] by an administrator).  A single parameter is passed to the script: &amp;lt;tt&amp;gt;1&amp;lt;/tt&amp;gt; at the job startup, and &amp;lt;tt&amp;gt;0&amp;lt;/tt&amp;gt; at the termination.&lt;br /&gt;
&lt;br /&gt;
Information about the job will be passed to the script in the following environment variables:&lt;br /&gt;
; &amp;lt;tt&amp;gt;ZOID_JOB_EXEC&amp;lt;/tt&amp;gt;&lt;br /&gt;
: name of the job executable,&lt;br /&gt;
; &amp;lt;tt&amp;gt;ZOID_JOB_ARGS&amp;lt;/tt&amp;gt;&lt;br /&gt;
: job arguments, separated by colons (&amp;lt;tt&amp;gt;:&amp;lt;/tt&amp;gt;)&lt;br /&gt;
; &amp;lt;tt&amp;gt;ZOID_JOB_ENV&amp;lt;/tt&amp;gt;&lt;br /&gt;
: job environment variables, separated by colons (&amp;lt;tt&amp;gt;:&amp;lt;/tt&amp;gt;)&lt;br /&gt;
; &amp;lt;tt&amp;gt;ZOID_JOB_ID&amp;lt;/tt&amp;gt;&lt;br /&gt;
: BG/P control system job id ('''Note:''' this is generally different from the Cobalt job ID; see [[FAQ#How to obtain a Cobalt job ID|FAQ]] for the latter),&lt;br /&gt;
; &amp;lt;tt&amp;gt;ZOID_JOB_GLOBAL_SIZE&amp;lt;/tt&amp;gt;&lt;br /&gt;
: the number of processes in the job (the size of &amp;lt;tt&amp;gt;MPI_COMM_WORLD&amp;lt;/tt&amp;gt;),&lt;br /&gt;
; &amp;lt;tt&amp;gt;ZOID_JOB_LOCAL_SIZE&amp;lt;/tt&amp;gt;&lt;br /&gt;
: the number of job processes handled by this I/O node,&lt;br /&gt;
; &amp;lt;tt&amp;gt;ZOID_JOB_MODE&amp;lt;/tt&amp;gt;&lt;br /&gt;
: &amp;lt;tt&amp;gt;0&amp;lt;/tt&amp;gt; for SMP, &amp;lt;tt&amp;gt;1&amp;lt;/tt&amp;gt; for VN, and &amp;lt;tt&amp;gt;2&amp;lt;/tt&amp;gt; for DUAL,&lt;br /&gt;
; &amp;lt;tt&amp;gt;SHELL&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;PATH&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;USER&amp;lt;/tt&amp;gt;, and &amp;lt;tt&amp;gt;HOME&amp;lt;/tt&amp;gt;&lt;br /&gt;
: will also be set...&lt;br /&gt;
&lt;br /&gt;
'''Note:''' the user script is invoked ''synchronously'' by the daemon, i.e., the job will not start running until the script terminates.  If one needs some processes to run on the I/O nodes while the job is running, they should be started in the background (&amp;amp;amp;).&lt;br /&gt;
&lt;br /&gt;
'''Note 2:''' for this feature to work, [[#The /bin.rd/update_passwd_file.sh file|update_passwd_file.sh]] must be working correctly.&lt;br /&gt;
&lt;br /&gt;
===File broadcast===&lt;br /&gt;
A &amp;lt;tt&amp;gt;/bin.rd/f2cn&amp;lt;/tt&amp;gt; command is available on the I/O nodes for a very efficient (hardware-assisted) broadcasting of files to all the compute nodes handled by the given I/O node.&lt;br /&gt;
&lt;br /&gt;
The command takes two arguments:&lt;br /&gt;
* absolute pathname to the input file on the I/O node,&lt;br /&gt;
* absolute pathname to the output file on the compute nodes.&lt;br /&gt;
&lt;br /&gt;
The input file does not need to be physically on the I/O node; it can be on a network filesystem mounted on the node.  The file will be created in the ramdisk of each compute node.&lt;br /&gt;
&lt;br /&gt;
The throughput is in practice limited by how fast the input file can be read; we have seen results in excess of 300&amp;amp;nbsp;MB/s for files residing in the I/O node ramdisk.&lt;br /&gt;
&lt;br /&gt;
'''Note:''' all the compute nodes in the pset must be up and running.  Do not use this command on ''incomplete'' partitions (e.g., a one-process job on a 64-node partition); this will likely hang the ZOID daemon.&lt;br /&gt;
&lt;br /&gt;
'''Note2:''' this feature can safely be used from within a [[#User script|user script]], so one can, e.g., pre-stage large binaries, like this:&lt;br /&gt;
&lt;br /&gt;
User script (&amp;lt;tt&amp;gt;$HOME/zoid-user-script.sh&amp;lt;/tt&amp;gt;):&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
#!/bin/sh&lt;br /&gt;
&lt;br /&gt;
if [ &amp;quot;$1&amp;quot; -eq &amp;quot;1&amp;quot; ]; then&lt;br /&gt;
    /bin.rd/f2cn $HOME/large_binary /tmp/large_binary&lt;br /&gt;
fi&lt;br /&gt;
exit 0&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Job script (submitted using Cobalt or mpirun):&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
#!/bin/sh&lt;br /&gt;
&lt;br /&gt;
chmod 755 /tmp/large_binary&lt;br /&gt;
/tmp/large_binary&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Performance counters===&lt;br /&gt;
&lt;br /&gt;
A &amp;lt;tt&amp;gt;/bin.rd/statquery&amp;lt;/tt&amp;gt; command is available on the I/O nodes for obtaining the performance counters of the I/O daemon.&lt;br /&gt;
&lt;br /&gt;
The command takes a single optional argument:&lt;br /&gt;
* the interval between successive queries, in seconds.&lt;br /&gt;
&lt;br /&gt;
If the argument is not provided, the command will terminate after the first query.&lt;br /&gt;
&lt;br /&gt;
Here is a sample output generated:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
Timestamp:                      1240439085.688831&lt;br /&gt;
Total messages sent:            5767&lt;br /&gt;
Total bytes sent:               7619170&lt;br /&gt;
Total messages received:        5717&lt;br /&gt;
Total bytes received:           72575&lt;br /&gt;
IP fwd messages sent:           196&lt;br /&gt;
IP fwd bytes sent:              5889&lt;br /&gt;
IP fwd messages received:       84&lt;br /&gt;
IP fwd bytes received:          6453&lt;br /&gt;
Stream messages sent:           65&lt;br /&gt;
Stream bytes sent:              520&lt;br /&gt;
Stream messages received:       65&lt;br /&gt;
Stream bytes received:          1416&lt;br /&gt;
Broadcast messages sent:        1&lt;br /&gt;
Broadcast bytes sent:           2437906&lt;br /&gt;
Internal messages sent:         193&lt;br /&gt;
Internal bytes sent:            39524&lt;br /&gt;
Internal messages received:     256&lt;br /&gt;
Internal bytes received:        1792&lt;br /&gt;
Plugin 5 messages sent:         0&lt;br /&gt;
Plugin 5 bytes sent:            0&lt;br /&gt;
Plugin 5 messages received:     0&lt;br /&gt;
Plugin 5 bytes received:        0&lt;br /&gt;
Plugin 2 messages sent:         5312&lt;br /&gt;
Plugin 2 bytes sent:            5135331&lt;br /&gt;
Plugin 2 messages received:     5312&lt;br /&gt;
Plugin 2 bytes received:        62914&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The meaning of the fields is as follows:&lt;br /&gt;
; Timestamp&lt;br /&gt;
: number of seconds and microseconds from the epoch, as returned by &amp;lt;tt&amp;gt;gettimeofday(2)&amp;lt;/tt&amp;gt;,&lt;br /&gt;
; IP fwd&lt;br /&gt;
: IP packet forwarding between compute nodes and I/O nodes,&lt;br /&gt;
; Stream&lt;br /&gt;
: &amp;lt;tt&amp;gt;stdin&amp;lt;/tt&amp;gt;/&amp;lt;tt&amp;gt;out&amp;lt;/tt&amp;gt;/&amp;lt;tt&amp;gt;err&amp;lt;/tt&amp;gt; streams,&lt;br /&gt;
; Broadcast&lt;br /&gt;
: [[#File broadcast|file broadcasts]],&lt;br /&gt;
; Internal&lt;br /&gt;
: job control messages, etc.&lt;br /&gt;
; Plugin 5&lt;br /&gt;
: internal &amp;lt;tt&amp;gt;mapping&amp;lt;/tt&amp;gt; plug-in, used by MPI,&lt;br /&gt;
; Plugin 2&lt;br /&gt;
: &amp;lt;tt&amp;gt;unix&amp;lt;/tt&amp;gt; plugin (POSIX file I/O).&lt;br /&gt;
&lt;br /&gt;
The counters are 64-bit integers, so they will take a while to overflow :-).&lt;br /&gt;
&lt;br /&gt;
Example user script (&amp;lt;tt&amp;gt;$HOME/zoid-user-script.sh&amp;lt;/tt&amp;gt;) that samples the statistics every 60 seconds and writes them to a unique file:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
#!/bin/sh&lt;br /&gt;
&lt;br /&gt;
if [ &amp;quot;$1&amp;quot; -eq &amp;quot;1&amp;quot; ]; then&lt;br /&gt;
    /bin.rd/statquery 60 &amp;gt;$HOME/zoid_stats.$ZOID_JOB_ID.`hostname` &amp;amp;&lt;br /&gt;
fi&lt;br /&gt;
exit 0&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Administrator interface==&lt;br /&gt;
&lt;br /&gt;
===Configuration file===&lt;br /&gt;
&lt;br /&gt;
The &amp;lt;tt&amp;gt;zoid&amp;lt;/tt&amp;gt; I/O daemon accepts a number of command-line options that can be used to change its behavior.  They can be adjusted by editing the &amp;lt;tt&amp;gt;ramdisk/ION/ramdisk-add/etc/sysconfig/zoid&amp;lt;/tt&amp;gt; file and rebuilding the I/O node ramdisk:&lt;br /&gt;
&lt;br /&gt;
; &amp;lt;span id=&amp;quot;opt_buffer_size&amp;quot;&amp;gt;ZOID_BUFFER_SIZE (-b)&amp;lt;/span&amp;gt;&lt;br /&gt;
: Specifies the size of the buffers used for messages.  Because a separate buffer is needed for a request and a reply, and typically no more than one of these needs to be large, to save memory ZOID supports buffers of two sizes: a small one (4&amp;amp;nbsp;KB by default) and a large one (4&amp;amp;nbsp;MB+1&amp;amp;nbsp;KB by default &amp;amp;#8211; the 1&amp;amp;nbsp;KB is there to accommodate the headers).  Use a colon (&amp;lt;tt&amp;gt;:&amp;lt;/tt&amp;gt;) to separate the two sizes when customizing this value.  If desired, support for second buffer size can be disabled by providing only one value to this option.&lt;br /&gt;
; ZOID_ACK_THRESHOLD (-a)&lt;br /&gt;
: Specifies a size threshold for the rendezvous protocol for messages coming from the compute nodes, in the units of tree network packets (240 bytes of data each).  An eager protocol is used for messages below the threshold.  Messages above the threshold use flow control in the form of a rendezvous protocol with message acknowledgements; basically, the daemon will only receive one large message at a time, which improves the predictability and an overall throughput.  The daemon default for this option is to not use the acknowledgements, but the config file defaults to a value of &amp;lt;tt&amp;gt;8&amp;lt;/tt&amp;gt;, which is the size of the hardware FIFO buffer of the tree network device.  Set this option to 0 (or comment it out altogether) to disable message acknowledgements.&lt;br /&gt;
; &amp;lt;span id=&amp;quot;opt_modules&amp;quot;&amp;gt;ZOID_MODULES (-m)&amp;lt;/span&amp;gt;&lt;br /&gt;
: Specifies a &amp;lt;tt&amp;gt;:&amp;lt;/tt&amp;gt;-separated list of ZOID plug-ins to load.  This defaults to &amp;lt;tt&amp;gt;&amp;quot;unix_impl.so:unix_preload.so:mapping_impl.so:mapping_preload.so&amp;quot;&amp;lt;/tt&amp;gt; in the config file; do not remove any of these or basic system services will stop working.  The &amp;lt;tt&amp;gt;unix&amp;lt;/tt&amp;gt; plug-in provide POSIX file I/O support, while &amp;lt;tt&amp;gt;mapping&amp;lt;/tt&amp;gt; is used by our MPI implementation to map between MPI ranks and Blue Gene X/Y/Z/T coordinates.  Custom plug-ins can be created and added here; see [[#Programmer interface|Programmer interface]] for details.&lt;br /&gt;
; &amp;lt;span id=&amp;quot;opt_enable_nat&amp;quot;&amp;gt;ZOID_ENABLE_NAT (-n)&amp;lt;/span&amp;gt;&lt;br /&gt;
: Enables network address translatation (NAT) for IP packets coming from the compute nodes, allowing compute nodes to communicate with the outside world.  This support is disabled by default because it was found to have a detrimental effect on the overall performance of the TCP/IP stack on the I/O nodes, slowing down network filesystems.  This feature can also be enabled on a per-job basis by setting the &amp;lt;tt&amp;gt;ZOID_ENABLE_NAT&amp;lt;/tt&amp;gt; environment variable when submitting a job (see the [[FAQ#How to open a socket from a CN to the outside world|FAQ]]).&lt;br /&gt;
; &amp;lt;span id=&amp;quot;opt_user_script&amp;quot;&amp;gt;ZOID_USER_SCRIPT (-u)&amp;lt;/span&amp;gt;&lt;br /&gt;
: Specifies the pathname to the [[#User script|user script]]; it defaults to &amp;lt;tt&amp;gt;&amp;quot;/bin.rd/zoid-user-script.sh&amp;quot;&amp;lt;/tt&amp;gt;.  This script can be found in &amp;lt;tt&amp;gt;ramdisk/ION/ramdisk-add/bin/zoid-user-script.sh&amp;lt;/tt&amp;gt;; it sets a few environment variables and then invokes user's custom &amp;lt;tt&amp;gt;$HOME/zoid-user-script.sh&amp;lt;/tt&amp;gt;.  Hence, to adjust the behavior of this feature, either change this option or the script in the ramdisk.&lt;br /&gt;
&lt;br /&gt;
===The /bin.rd/update_passwd_file.sh file===&lt;br /&gt;
&lt;br /&gt;
Allowing the partition owner to log into the I/O node using SSH is one of the features of the ZeptoOS software stack.  Only the administrator and the partition owner are given login access; this is controlled by the &amp;lt;tt&amp;gt;/bin.rd/update_passwd_file.sh&amp;lt;/tt&amp;gt; script, which is invoked by the daemon while the partition is being initialized.  The script can be found in &amp;lt;tt&amp;gt;ramdisk/ION/ramdisk-add/bin/update_passwd_file.sh&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
The script makes a number of assumptions that could be site-specific, so it might require an adjustment.  The daemon invokes the script passing a numerical UNIX user ID of the partition owner as the only argument.  The script then scans the &amp;lt;tt&amp;gt;/bgsys/iofs/etc/passwd&amp;lt;/tt&amp;gt; for an entry with the same user ID (on Argonne machines, this files contains all valid account names).  If a matching entry is found, it is appended to the &amp;lt;tt&amp;gt;/etc/passwd&amp;lt;/tt&amp;gt; file in the I/O node ramdisk, thus enabling login access to the node for that user.&lt;br /&gt;
&lt;br /&gt;
If allowing ordinary users access to the I/O nodes is undesirable, one can simply put &amp;lt;tt&amp;gt;exit 0&amp;lt;/tt&amp;gt; at the top of the script to disable it.&lt;br /&gt;
&lt;br /&gt;
===The /bin.rd/nat file===&lt;br /&gt;
&lt;br /&gt;
If NAT has been [[#opt_enable_nat|requested]], the daemon invokes the &amp;lt;tt&amp;gt;/bin.rd/nat&amp;lt;/tt&amp;gt; script to enabled it.  This script can be found in &amp;lt;tt&amp;gt;ramdisk/ION/ramdisk-add/bin/nat&amp;lt;/tt&amp;gt;.  Generally, it should not require any modifications.&lt;br /&gt;
&lt;br /&gt;
==Programmer interface==&lt;br /&gt;
&lt;br /&gt;
ZOID is a flexible, extensible, high-performance function call forwarding (RPC) infrastructure.  Built-in features and the standard plug-ins provide familiar POSIX file I/O and BSD socket interfaces, but, because of the number of software layers involved, they introduce a significant overhead.  For applications requiring maximum bandwidth between the compute and I/O nodes, ZOID provides an option of a customized function call forwarding with minimal overheads.  This section provides an overview of how to create such custom plug-ins.&lt;br /&gt;
&lt;br /&gt;
===Overview===&lt;br /&gt;
&lt;br /&gt;
All that ZOID provides is a function call forwarding support, and a limited one at that.  Any logic (caching, prefetching, etc.) needs to be custom-built on top of it.&lt;br /&gt;
&lt;br /&gt;
Follow existing plug-ins, found in &amp;lt;tt&amp;gt;packages/zoid/src/&amp;lt;/tt&amp;gt;, as examples.  The &amp;lt;tt&amp;gt;unix&amp;lt;/tt&amp;gt; plug-in is generally the most up to date, but other plug-ins such as &amp;lt;tt&amp;gt;mapping&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;zoidfs&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;barrier&amp;lt;/tt&amp;gt;, and &amp;lt;tt&amp;gt;test&amp;lt;/tt&amp;gt; should also be fine.&lt;br /&gt;
&lt;br /&gt;
A plug-in consists of automatically generated client-side and server-side stubs (which perform the marshalling and demarshalling of function call parameters and results, the forwarding of the function call, etc.), and of a hand-written server-side implementation which provides the implementation code for the forwarded function calls.  One might also decide to provide hand-written client-side wrappers to hide some details of the ZOID API (such as the error handling) or to adhere to a particular existing API, as is the case with the &amp;lt;tt&amp;gt;unix&amp;lt;/tt&amp;gt; plug-in (the wrappers used by the FUSE client are available in &amp;lt;tt&amp;gt;packages/zoid/src/unix/stubs/&amp;lt;/tt&amp;gt;; another version is in the GNU libc sources, in &amp;lt;tt&amp;gt;packages/glibc/src/zoid/sysdeps/unix/sysv/linux/powerpc/powerpc32/&amp;lt;/tt&amp;gt;).&lt;br /&gt;
&lt;br /&gt;
The &amp;lt;tt&amp;gt;scanner.pl&amp;lt;/tt&amp;gt; script, found in &amp;lt;tt&amp;gt;packages/zoid/src/&amp;lt;/tt&amp;gt;, creates the automatically-generated client and server stubs based on a hand-written input header file described below.  Again, please follow the examples from the existing plug-ins, such as &amp;lt;tt&amp;gt;unix&amp;lt;/tt&amp;gt; or &amp;lt;tt&amp;gt;mapping&amp;lt;/tt&amp;gt;.  The &amp;lt;tt&amp;gt;Makefile&amp;lt;/tt&amp;gt; in those plug-ins is written in a generic fashion and should only require a change to the &amp;lt;tt&amp;gt;PREFIX&amp;lt;/tt&amp;gt; line to be usable with another plug-in.  Use that &amp;lt;tt&amp;gt;Makefile&amp;lt;/tt&amp;gt; to invoke the &amp;lt;tt&amp;gt;scanner.pl&amp;lt;/tt&amp;gt; script and to compile the generated source files.&lt;br /&gt;
&lt;br /&gt;
===Input header file===&lt;br /&gt;
&lt;br /&gt;
The input header file must be a valid C header file with additional hints in the comments.  The file is read by the &amp;lt;tt&amp;gt;scanner.pl&amp;lt;/tt&amp;gt; script.&lt;br /&gt;
&lt;br /&gt;
The parser in the script is rather limited and does not handle many C constructs.  It is thus essential that the header file be as simple as possible.  In particular, function prototypes should be specified at the end of the file, not intermixed with any other specifications such as data type definitions.&lt;br /&gt;
&lt;br /&gt;
Ordinary comments are best placed on separate lines.&lt;br /&gt;
&lt;br /&gt;
'''Note:''' the parser is case ''sensitive''.&lt;br /&gt;
&lt;br /&gt;
====Start line====&lt;br /&gt;
&lt;br /&gt;
Any complex declarations that the scanner cannot parse should be placed at the top of the file, because the parser ignores everything until it encounters the following magic start line:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
/* START-ZOID-SCANNER ID=&amp;lt;n&amp;gt; INIT=&amp;lt;s1&amp;gt; FINI=&amp;lt;s2&amp;gt; PROC=&amp;lt;s3&amp;gt; */&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
; ID=&amp;lt;n&amp;gt;&lt;br /&gt;
: Each plug-in needs a unique, 16-bit identifier, passed in &amp;lt;tt&amp;gt;&amp;lt;n&amp;gt;&amp;lt;/tt&amp;gt;.  The following identifiers are already in use: &amp;lt;tt&amp;gt;0&amp;lt;/tt&amp;gt; (internal), &amp;lt;tt&amp;gt;1&amp;lt;/tt&amp;gt; (&amp;lt;tt&amp;gt;zoidfs&amp;lt;/tt&amp;gt; plug-in), &amp;lt;tt&amp;gt;2&amp;lt;/tt&amp;gt; (&amp;lt;tt&amp;gt;unix&amp;lt;/tt&amp;gt;), &amp;lt;tt&amp;gt;3&amp;lt;/tt&amp;gt; (&amp;lt;tt&amp;gt;lofar&amp;lt;/tt&amp;gt;), &amp;lt;tt&amp;gt;4&amp;lt;/tt&amp;gt; (&amp;lt;tt&amp;gt;test&amp;lt;/tt&amp;gt;), &amp;lt;tt&amp;gt;5&amp;lt;/tt&amp;gt; (&amp;lt;tt&amp;gt;mapping&amp;lt;/tt&amp;gt;), and &amp;lt;tt&amp;gt;10&amp;lt;/tt&amp;gt; (&amp;lt;tt&amp;gt;ftb&amp;lt;/tt&amp;gt;).&lt;br /&gt;
; INIT=&amp;lt;s1&amp;gt;&lt;br /&gt;
: &amp;lt;tt&amp;gt;&amp;lt;s1&amp;gt;&amp;lt;/tt&amp;gt; provides the name of an initialization function which will be invoked before a job starts running; see [[#Start-line functions|Start-line functions]] for more information.  If a plug-in does not need this feature, please specify &amp;lt;tt&amp;gt;INIT=NULL&amp;lt;/tt&amp;gt;.&lt;br /&gt;
; FINI=&amp;lt;s2&amp;gt;&lt;br /&gt;
: &amp;lt;tt&amp;gt;&amp;lt;s2&amp;gt;&amp;lt;/tt&amp;gt; provides the name of a termination function which will be invoked after all job processes have exited; see [[#Start-line functions|Start-line functions]] for more information.  If a plug-in does not need this feature, please specify &amp;lt;tt&amp;gt;FINI=NULL&amp;lt;/tt&amp;gt;.&lt;br /&gt;
; PROC=&amp;lt;s3&amp;gt;&lt;br /&gt;
: &amp;lt;tt&amp;gt;&amp;lt;s3&amp;gt;&amp;lt;/tt&amp;gt; provides the name of a callback function which will be invoked on a startup and termination of every application and ZOID-enabled process; see [[#Start-line functions|Start-line functions]] for more information.  If a plug-in does not need this feature, please specify &amp;lt;tt&amp;gt;PROC=NULL&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
====Argument hints====&lt;br /&gt;
&lt;br /&gt;
Hints are generally needed by the scanner to correctly encode and decode function arguments.  They need to be placed after each argument, before a separating comma (or a closing bracket), and should be embedded inside dedicated C comments.  Multiple hints per argument are usually provided; these are separated by a colon (&amp;lt;tt&amp;gt;:&amp;lt;/tt&amp;gt;). The following hints are currently defined:&lt;br /&gt;
&lt;br /&gt;
; in, out, inout&lt;br /&gt;
: Specifies whether the argument is an input argument, an output argument, or both.  &amp;lt;tt&amp;gt;in&amp;lt;/tt&amp;gt; is the default.&lt;br /&gt;
; obj, str, ptr, arr, arr2d&lt;br /&gt;
: Specifies the type of the argument, respectively a plain object (say, an &amp;lt;tt&amp;gt;int&amp;lt;/tt&amp;gt;, or a structure passed by value), a &amp;lt;tt&amp;gt;'\0'&amp;lt;/tt&amp;gt;-terminated character string, a pointer to a plain object, an array of objects, or a two-dimensional array (&amp;lt;tt&amp;gt;type**&amp;lt;/tt&amp;gt;, not &amp;lt;tt&amp;gt;type[][]&amp;lt;/tt&amp;gt;).  &amp;lt;tt&amp;gt;obj&amp;lt;/tt&amp;gt; is the default.&lt;br /&gt;
; size&lt;br /&gt;
: Required for array arguments (&amp;lt;tt&amp;gt;arr&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;arr2d&amp;lt;/tt&amp;gt;).  Indicates the index of another argument in the same function, which is used to pass the array size.  Absolute numbers are accepted (&amp;lt;tt&amp;gt;1&amp;lt;/tt&amp;gt; to ''number of arguments'') or relative ones (&amp;lt;tt&amp;gt;+1&amp;lt;/tt&amp;gt; for the next argument, &amp;lt;tt&amp;gt;-1&amp;lt;/tt&amp;gt; for the previous argument, etc).&amp;lt;br/&amp;gt;  For &amp;lt;tt&amp;gt;arr&amp;lt;/tt&amp;gt; arguments, the size argument must be of a numerical type, or a pointer to such a type.  For &amp;lt;tt&amp;gt;arr2d&amp;lt;/tt&amp;gt; arguments, the size argument must itself be an array (an &amp;lt;tt&amp;gt;arr&amp;lt;/tt&amp;gt; argument) of numerical elements, specifying the sizes along the less significant dimension of the array (the size of the more significant dimension is the size of the &amp;lt;tt&amp;gt;arr&amp;lt;/tt&amp;gt; array itself).&amp;lt;br/&amp;gt;  Please note that the unit of size for the numerical types is the size of the base array type (thus, &amp;lt;tt&amp;gt;sizeof(int)&amp;lt;/tt&amp;gt; for an array of &amp;lt;tt&amp;gt;int&amp;lt;/tt&amp;gt;s), not byte (if one would like it to be byte, just make the array argument have type &amp;lt;tt&amp;gt;char*&amp;lt;/tt&amp;gt; or &amp;lt;tt&amp;gt;void*&amp;lt;/tt&amp;gt; (a GCC extension)).&lt;br /&gt;
; nullok&lt;br /&gt;
: An option for arguments passed by pointer (basically, all but &amp;lt;tt&amp;gt;obj&amp;lt;/tt&amp;gt;).  If provided, it indicates that the argument is allowed to be &amp;lt;tt&amp;gt;NULL&amp;lt;/tt&amp;gt;.  This is not the default because supporting &amp;lt;tt&amp;gt;NULL&amp;lt;/tt&amp;gt; pointers results in an additional computational and protocol overhead.  '''Note:''' if a &amp;lt;tt&amp;gt;NULL&amp;lt;/tt&amp;gt; pointer is passed to an argument that lacks the &amp;lt;tt&amp;gt;nullok&amp;lt;/tt&amp;gt; flag, the client ''will'' crash.&lt;br /&gt;
; zerocopy&lt;br /&gt;
: An option for array arguments.  Enables a more efficient marshalling/demarshalling protocol for the array, which does not use extra memory copies.  Can be used for no more than one &amp;lt;tt&amp;gt;in&amp;lt;/tt&amp;gt; argument and no more than one &amp;lt;tt&amp;gt;out&amp;lt;/tt&amp;gt; argument.  [[#Zerocopy performance|Zerocopy performance]] discusses performance considerations when using this option.&lt;br /&gt;
; userbuf&lt;br /&gt;
: An option for &amp;lt;tt&amp;gt;zerocopy&amp;lt;/tt&amp;gt;; only supported for &amp;lt;tt&amp;gt;arr&amp;lt;/tt&amp;gt; arguments.  Enables a special form of zero-copy support, discussed in [[#Zerocopy with a custom output buffer|Zerocopy with a custom output buffer]] and [[#Zerocopy with a custom input buffer|Zerocopy with a custom input buffer]].&lt;br /&gt;
&lt;br /&gt;
Here is an example function prototype with the hints:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
int zoidfs_readlink(const zoidfs_handle_t * handle /* in:ptr */,&lt;br /&gt;
                    char * buffer /* out:arr:size=+1 */,&lt;br /&gt;
                    size_t buffer_length /* in:obj */);&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
====Limitations====&lt;br /&gt;
&lt;br /&gt;
As indicated earlier, the scanner is limited, so keep the prototypes simple.&lt;br /&gt;
&lt;br /&gt;
Return type of a forwarded function must be scalar or &amp;lt;tt&amp;gt;void&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Structures with pointer fields inside of them cannot be forwarded.&lt;br /&gt;
&lt;br /&gt;
====Generated files====&lt;br /&gt;
&lt;br /&gt;
For every function prototype found, the scanner generates two output files: one for a client calling the function and one for the server, where the function is in fact executed.  Code in the generated files performs marshalling and demarshalling of function arguments and results.&lt;br /&gt;
&lt;br /&gt;
Two more files per plug-in are generated: ''header''&amp;lt;tt&amp;gt;_defs.h&amp;lt;/tt&amp;gt; and ''header''&amp;lt;tt&amp;gt;_dispatch.c&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
None of the generated files should be modified.&lt;br /&gt;
&lt;br /&gt;
===Server-side API===&lt;br /&gt;
&lt;br /&gt;
Server-side stubs and the server-side implementation need to be passed as modules when invoking the ZOID I/O daemon, as described [[#opt_modules|earlier]].&lt;br /&gt;
&lt;br /&gt;
The hand-written server-side implementation code should include the &amp;lt;tt&amp;gt;zoid_api.h&amp;lt;/tt&amp;gt; header file (available from &amp;lt;tt&amp;gt;packages/zoid/prebuilt/&amp;lt;/tt&amp;gt;) and the plug-in input header file.&lt;br /&gt;
&lt;br /&gt;
All the functions listed in the header file need to be defined in the server-side implementation code.  The code needs to be compiled as a shared library; use the &amp;lt;tt&amp;gt;implementation/&amp;lt;/tt&amp;gt; subdirectory of the &amp;lt;tt&amp;gt;unix&amp;lt;/tt&amp;gt; plug-in as an example.  Please note that since ZOID is multi-threaded, multiple functions can be invoked at the same time, so one must ensure that the implementation is multi-thread-safe.&lt;br /&gt;
&lt;br /&gt;
====Start-line functions====&lt;br /&gt;
&lt;br /&gt;
The following [[#Start line|start-line]] functions can be defined:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
void INIT(int pset_mpi_proc_count, int argc, int envc, const char* argenv);&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The INIT function is invoked during initialization, right before a job starts running.  Arguments:&lt;br /&gt;
&lt;br /&gt;
; pset_mpi_proc_count&lt;br /&gt;
: The number of job processes that will be handled by this I/O node.  Note that I/O nodes also handle additional ZOID-enabled processes, such as the FUSE clients, which are not included in this number.&lt;br /&gt;
; argc&lt;br /&gt;
: The number of command-line arguments plus one.&lt;br /&gt;
; envc&lt;br /&gt;
: The number of environment variables.&lt;br /&gt;
; argenv&lt;br /&gt;
: An array of &amp;lt;tt&amp;gt;'\0'&amp;lt;/tt&amp;gt;-terminated strings, one after another.  The first string is the name of the job executable, followed by &amp;lt;tt&amp;gt;argc-1&amp;lt;/tt&amp;gt; command-line arguments, followed by &amp;lt;tt&amp;gt;envc&amp;lt;/tt&amp;gt; environment variables.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
void FINI(void);&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The FINI function is invoked after the last process of the job has terminated.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
void PROC(int added, int pset_pid);&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The PROC function is invoked on the startup and termination of every application and ZOID-enabled process on the compute node.  Arguments:&lt;br /&gt;
&lt;br /&gt;
; added&lt;br /&gt;
: &amp;lt;tt&amp;gt;1&amp;lt;/tt&amp;gt; if the process was started, &amp;lt;tt&amp;gt;0&amp;lt;/tt&amp;gt; if it was terminated.&lt;br /&gt;
; pset_pid&lt;br /&gt;
: A process identifier (as returned by [[#Implementation functions|&amp;lt;tt&amp;gt;__zoid_calling_process_id&amp;lt;/tt&amp;gt;]]).&lt;br /&gt;
&lt;br /&gt;
====Implementation functions====&lt;br /&gt;
&lt;br /&gt;
The hand-written server-side implementation functions can themselves call back a few ZOID functions, available by including the &amp;lt;tt&amp;gt;zoid_api.h&amp;lt;/tt&amp;gt; header file:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
int __zoid_calling_process_id(void);&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This function returns a unique identifier of the compute node process that invoked the function.  The identifier is ''not'' an MPI rank, because some processes, such as the FUSE clients, are not part of the application and hence do not have a rank.  The identifiers are only unique within one I/O node, and they can be reused if a process starts after another one has terminated.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
void __zoid_register_userbuf(void* userbuf,&lt;br /&gt;
                             void (*callback)(void* userbuf, void* priv),&lt;br /&gt;
                             void* priv);&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This function will be discussed in [[#Zerocopy with a custom output buffer|Zerocopy with a custom output buffer]].&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
int __zoid_send_output(int pid, int fd, const char* buffer, int len);&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This function writes an arbitrary string to the job's standard output or error.  Arguments:&lt;br /&gt;
&lt;br /&gt;
; pid&lt;br /&gt;
: Process identifier as returned by &amp;lt;tt&amp;gt;__zoid_calling_process_id&amp;lt;/tt&amp;gt;.  The process in question ''must'' have an MPI rank, meaning that it must be either an application process or a process launched from an application process.&lt;br /&gt;
; fd&lt;br /&gt;
: &amp;lt;tt&amp;gt;1&amp;lt;/tt&amp;gt; for standard output, &amp;lt;tt&amp;gt;2&amp;lt;/tt&amp;gt; for standard error.&lt;br /&gt;
; buffer, len&lt;br /&gt;
: The string and its length.  &amp;lt;tt&amp;gt;'\0'&amp;lt;/tt&amp;gt; should not be included in &amp;lt;tt&amp;gt;len&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;buffer&amp;lt;/tt&amp;gt; does not need to be &amp;lt;tt&amp;gt;'\0'&amp;lt;/tt&amp;gt;-terminated.&lt;br /&gt;
&lt;br /&gt;
The function returns 0 if successful, and -1 if not (such as when the process identified by &amp;lt;tt&amp;gt;pid&amp;lt;/tt&amp;gt; does not have an MPI rank).&lt;br /&gt;
&lt;br /&gt;
===Client-side API===&lt;br /&gt;
&lt;br /&gt;
A compute node application needs to be linked with the client-side stubs and with a common support library &amp;lt;tt&amp;gt;libzoid_cn.a&amp;lt;/tt&amp;gt; (a prebuilt version of the latter is in &amp;lt;tt&amp;gt;packages/zoid/prebuilt&amp;lt;/tt&amp;gt;; sources are in &amp;lt;tt&amp;gt;packages/zoid/src/cnl/client&amp;lt;/tt&amp;gt;).  Several functions are available to applications by including the &amp;lt;tt&amp;gt;zoid_api.h&amp;lt;/tt&amp;gt; header file:&lt;br /&gt;
&lt;br /&gt;
====Initialization====&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
int __zoid_init(void);&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This function ''must'' be invoked before any ZOID or ZOID-forwarded functions can be invoked.  It returns &amp;lt;tt&amp;gt;0&amp;lt;/tt&amp;gt; if successful, &amp;lt;tt&amp;gt;1&amp;lt;/tt&amp;gt; otherwise.  There is no corresponding termination function.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
int __zoid_job_size(void);&lt;br /&gt;
int __zoid_my_rank(void);&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
These functions return, respectively, the number of processes in the job (the size of &amp;lt;tt&amp;gt;MPI_COMM_WORLD&amp;lt;/tt&amp;gt;), and the MPI rank of the&lt;br /&gt;
current process.  Either will return &amp;lt;tt&amp;gt;-1&amp;lt;/tt&amp;gt; if the current process does not have an MPI rank, i.e., if it is not an application process and was not launched from an application process (say, if it was launched from an interactive shell).&lt;br /&gt;
&lt;br /&gt;
====Error conditions====&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
int __zoid_error(void);&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This function should be invoked on the client side after ''every'' forwarded function call returns, to determine if any errors occured within the forwarding layer.  A return value of &amp;lt;tt&amp;gt;0&amp;lt;/tt&amp;gt; indicates a success; otherwise, one of the following error values will be returned:&lt;br /&gt;
&lt;br /&gt;
; ENOSYS&lt;br /&gt;
: Invalid command sent from the client.  Typically indicates that the corresponding I/O-node-side [[#opt_modules|modules]] have not been loaded.&lt;br /&gt;
; ENOMEM&lt;br /&gt;
: Out of memory condition.&lt;br /&gt;
; E2BIG&lt;br /&gt;
: Message exceeded the internal size limit.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
int __zoid_excessive_size(void);&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
If &amp;lt;tt&amp;gt;__zoid_error&amp;lt;/tt&amp;gt; returned &amp;lt;tt&amp;gt;E2BIG&amp;lt;/tt&amp;gt;, calling this function will provide an indication of by how many bytes the input or output was too large.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;span id=&amp;quot;size_restrictions&amp;quot;&amp;gt;ZOID&amp;lt;/span&amp;gt; [[#opt_buffer_size|has a limit]] on the message size, around 4&amp;amp;nbsp;MB by default.  The limit is enforced on both input and output.  The limit only applies to buffers &amp;quot;owned&amp;quot; by ZOID on the daemon side; it does not apply to custom [[#Zerocopy with a custom input buffer|input]] or [[#Zerocopy with a custom output buffer|output]] buffers.&lt;br /&gt;
&lt;br /&gt;
If the limit is hit, the operation needs to be split into smaller ones.  Information returned by &amp;lt;tt&amp;gt;__zoid_excessive_size&amp;lt;/tt&amp;gt; makes it easy to adjust the buffer and resubmit.&lt;br /&gt;
&lt;br /&gt;
'''Note:''' While the input-side (argument) overflow is flagged immediately on the client side, and is thus fairly cheap to hit, the output-side (result) overflow is flagged on the I/O node, after the request has been sent there (but before the implementation function is invoked).  It is thus advised to cache at least the size limit for the output side for the next invocation, to avoid a future communication overhead.  The size limit is function-specific, since it depends on sizes of other arguments and results.&lt;br /&gt;
&lt;br /&gt;
Here is an example of how the client-side convenience wrapper for a call such as POSIX &amp;lt;tt&amp;gt;read&amp;lt;/tt&amp;gt; could be implemented:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
ssize_t read(int fd, void *buf, size_t nbytes)&lt;br /&gt;
{&lt;br /&gt;
    static ssize_t max_read_nbytes = -1;&lt;br /&gt;
    ssize_t bytes_read;&lt;br /&gt;
&lt;br /&gt;
    bytes_read = 0;&lt;br /&gt;
    do&lt;br /&gt;
    {&lt;br /&gt;
        ssize_t toread, justread;&lt;br /&gt;
        int error;&lt;br /&gt;
&lt;br /&gt;
        toread = nbytes - bytes_read;&lt;br /&gt;
&lt;br /&gt;
        if (max_read_nbytes != -1 &amp;amp;&amp;amp; toread &amp;gt; max_read_nbytes)&lt;br /&gt;
            toread = max_read_nbytes;&lt;br /&gt;
&lt;br /&gt;
        /* unix_read is the forwarded function call.  */&lt;br /&gt;
        justread = unix_read(fd, buf + bytes_read, toread);&lt;br /&gt;
&lt;br /&gt;
        if ((error = __zoid_error()))&lt;br /&gt;
        {&lt;br /&gt;
            if (error != E2BIG)&lt;br /&gt;
            {&lt;br /&gt;
                /* For a generic ZOID error, just bail out.  */&lt;br /&gt;
                errno = error;&lt;br /&gt;
                return -1;&lt;br /&gt;
            }&lt;br /&gt;
&lt;br /&gt;
            /* We tried to send a too large read request.  Adjust.  */&lt;br /&gt;
            max_read_nbytes = toread - __zoid_excessive_size();&lt;br /&gt;
        }&lt;br /&gt;
        else&lt;br /&gt;
        {&lt;br /&gt;
            if (justread &amp;lt; 0)&lt;br /&gt;
            {&lt;br /&gt;
                /* For a generic read() error, just bail out.&lt;br /&gt;
                   In case of an I/O error, unix_read returns -errno.  */&lt;br /&gt;
                errno = -justread;&lt;br /&gt;
                return -1;&lt;br /&gt;
            }&lt;br /&gt;
&lt;br /&gt;
            bytes_read += justread;&lt;br /&gt;
&lt;br /&gt;
            if (justread != toread)&lt;br /&gt;
                /* unix_read as such succeeded, but it read fewer bytes than&lt;br /&gt;
                   expected.  We terminate prematurely then.  */&lt;br /&gt;
                break;&lt;br /&gt;
        }&lt;br /&gt;
    } while (bytes_read &amp;lt; nbytes);&lt;br /&gt;
&lt;br /&gt;
    return bytes_read;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Additional considerations===&lt;br /&gt;
&lt;br /&gt;
====Forwarding &amp;lt;tt&amp;gt;errno&amp;lt;/tt&amp;gt;====&lt;br /&gt;
&lt;br /&gt;
If one needs to pass a variable such as &amp;lt;tt&amp;gt;errno&amp;lt;/tt&amp;gt; from the I/O node to the client, the most straightforward way is to add an extra integer &amp;lt;tt&amp;gt;out&amp;lt;/tt&amp;gt; pointer argument to all functions and pass it that way.  Another option is to do it the same way the UNIX kernel does: pass it as a negative return value from the functions.  The &amp;lt;tt&amp;gt;unix&amp;lt;/tt&amp;gt; plug-in does it that way, so, e.g., the implementation of &amp;lt;tt&amp;gt;close&amp;lt;/tt&amp;gt; on the I/O node looks something like this:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
if (close(server_fd) == -1)&lt;br /&gt;
    return -errno;&lt;br /&gt;
else&lt;br /&gt;
    return 0;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Then, on the client side, we have a convenience wrapper:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
int close(int fd)&lt;br /&gt;
{&lt;br /&gt;
    return unix_decode_result(unix_close(fd));&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;unix_decode_result&amp;lt;/tt&amp;gt; is a preprocessor macro that handles both ZOID errors and errors returned by the plug-in.  It uses a number of GCC extensions to make it as transparent as possible:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
#define unix_decode_result(result)      \&lt;br /&gt;
({                                      \&lt;br /&gt;
    typeof (result) _result = (result); \&lt;br /&gt;
    int _n;                             \&lt;br /&gt;
    if ((_n = __zoid_error()) != 0)     \&lt;br /&gt;
    {                                   \&lt;br /&gt;
        errno = _n;                     \&lt;br /&gt;
        _result = -1;                   \&lt;br /&gt;
    }                                   \&lt;br /&gt;
    else if (_result &amp;lt; 0)               \&lt;br /&gt;
    {                                   \&lt;br /&gt;
        errno = -_result;               \&lt;br /&gt;
        _result = -1;                   \&lt;br /&gt;
    }                                   \&lt;br /&gt;
    _result;                            \&lt;br /&gt;
})&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
====Returning variable amounts of data in arrays====&lt;br /&gt;
&lt;br /&gt;
Just like with UNIX system calls, ZOID does not allocate memory for the results.  Instead, callers must provide pre-allocated arrays, along with their sizes.  UNIX would then typically return the size of the used part as a return value from a system call.  Unfortunately, ZOID cannot make use of that &amp;amp;#8211; it will use the same array size argument to determine how much data to send back, so even if only a small part of the provided buffer is actually filled in, the whole buffer will be sent back, which is inefficient.  This can be prevented by passing the array size as an &amp;lt;tt&amp;gt;inout&amp;lt;/tt&amp;gt; pointer to a numerical type.  A server-side implementation of a function such as &amp;lt;tt&amp;gt;read&amp;lt;/tt&amp;gt; then looks like this:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
ssize_t unix_read(int fd /* in:obj */,&lt;br /&gt;
                  void *buf /* out:arr:size=+1 */,&lt;br /&gt;
                  size_t *count /* inout:ptr */)&lt;br /&gt;
{&lt;br /&gt;
    ssize_t ret;&lt;br /&gt;
&lt;br /&gt;
    ...&lt;br /&gt;
&lt;br /&gt;
    if ((ret = read(fd, buf, *count)) == -1)&lt;br /&gt;
    {&lt;br /&gt;
        *count = 0;&lt;br /&gt;
        return -errno;&lt;br /&gt;
    }&lt;br /&gt;
    else&lt;br /&gt;
    {&lt;br /&gt;
        *count = ret;&lt;br /&gt;
        return ret;&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Obviously, the client side needs to be modified as well, to pass the size argument by address.&lt;br /&gt;
&lt;br /&gt;
'''Note:''' this feature has certain implementation limitations.  It can misbehave in the presence of multiple output arrays (or a single output &amp;lt;tt&amp;gt;arr2d&amp;lt;/tt&amp;gt;, which internally behaves a lot like multiple separate &amp;lt;tt&amp;gt;arr&amp;lt;/tt&amp;gt;s).  Essentially, for efficiency reasons, the placement of arrays in the result buffer is determined before an implementation function is invoked.  If this feature is used to change the size of one array, and that array is followed in the output buffer by another array, a &amp;quot;hole&amp;quot; will be created in the buffer, causing problems.  However, in the most common case of a single output array the feature is completely reliable.&lt;br /&gt;
&lt;br /&gt;
====Zerocopy performance====&lt;br /&gt;
&lt;br /&gt;
Implementation-wise, ZOID is always zero-copy on the server side, meaning that data that implementation functions put in the &amp;lt;tt&amp;gt;out&amp;lt;/tt&amp;gt; arrays is sent to the compute nodes without any extra memory copies.&lt;br /&gt;
&lt;br /&gt;
Client side is only zero-copy for arrays that use the &amp;lt;tt&amp;gt;zerocopy&amp;lt;/tt&amp;gt; flag in the header file.  Because of the additial protocol overheads that &amp;lt;tt&amp;gt;zerocopy&amp;lt;/tt&amp;gt; introduces, it should be used only for potentially large memory buffers, such as the buffers of file I/O &amp;lt;tt&amp;gt;read&amp;lt;/tt&amp;gt; or &amp;lt;tt&amp;gt;write&amp;lt;/tt&amp;gt; calls.&lt;br /&gt;
&lt;br /&gt;
'''Note:''' for maximum performance, the arrays passed as &amp;lt;tt&amp;gt;zerocopy&amp;lt;/tt&amp;gt; arguments on the compute nodes must be aligned in memory to the 16-bytes boundary; otherwise, an interim buffer will be used.  The memory allocation routines such as &amp;lt;tt&amp;gt;malloc&amp;lt;/tt&amp;gt; have been modified to align memory to that boundary.  If there is a danger that the user code might pass a large unaligned buffer, and the semantics will not be affected, it makes sense to write code that detects insufficient alignment and splits the operation in two: a small unaligned one (say, up to 240 bytes &amp;amp;#8211; the data payload of a single packet on the tree network), followed by a larger, properly aligned one.&lt;br /&gt;
&lt;br /&gt;
====Zerocopy with a custom output buffer====&lt;br /&gt;
&lt;br /&gt;
Normally, memory for output arrays to be filled in by server-side implementation functions is allocated by the ZOID daemon.  This might be inconvenient when the data to be filled arrives asynchronously, possibly before the implementation function is even invoked; in such situations, an interim memory buffer must be used, forcing an extra memory copy.&lt;br /&gt;
&lt;br /&gt;
This can be avoided for zero-copy output &amp;lt;tt&amp;gt;arr&amp;lt;/tt&amp;gt; types if the &amp;lt;tt&amp;gt;userbuf&amp;lt;/tt&amp;gt; flag has been used.  No space will then be preallocated by the daemon for the array (the server-side stub will pass a &amp;lt;tt&amp;gt;NULL&amp;lt;/tt&amp;gt; pointer); instead, the implementation function must provide the daemon with its own buffer.  It can do it by calling:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
void __zoid_register_userbuf(void* userbuf,&lt;br /&gt;
                             void (*callback)(void* userbuf, void* priv),&lt;br /&gt;
                             void* priv);&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Arguments:&lt;br /&gt;
&lt;br /&gt;
; userbuf&lt;br /&gt;
: The address of the buffer.&lt;br /&gt;
; callback&lt;br /&gt;
: A callback function that is invoked by the daemon when the buffer has been sent to the client and is thus no longer needed.  &amp;lt;tt&amp;gt;userbuf&amp;lt;/tt&amp;gt; is passed as the first argument to the callback.  It is safe for the callback to invoke &amp;lt;tt&amp;gt;__zoid_calling_process_id&amp;lt;/tt&amp;gt;.&lt;br /&gt;
; priv&lt;br /&gt;
: A private data passed as the second argument to the &amp;lt;tt&amp;gt;callback&amp;lt;/tt&amp;gt;.  It is not interpreted by ZOID in any way.&lt;br /&gt;
&lt;br /&gt;
The size of the provided buffer is determined like for any other array argument: the maximum value is provided by the client via the &amp;lt;tt&amp;gt;size&amp;lt;/tt&amp;gt; argument.  The server-side implementation part may choose to return less than the maximum amount, as explained [[#Returning variable amounts of data in arrays|earlier]].&lt;br /&gt;
&lt;br /&gt;
As in other zero-copy cases, for maximum performance, the buffer provided must be aligned in memory to the 16-bytes boundary; otherwise, an interim buffer will be used.  The memory allocation routines such as &amp;lt;tt&amp;gt;malloc&amp;lt;/tt&amp;gt; have been modified to align memory to that boundary, but we recommend explicitly calling &amp;lt;tt&amp;gt;posix_memalign&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
'''Note:''' because the buffer provided is ''not'' allocated by ZOID, message size restrictions discussed [[#size_restrictions|earlier]] do not apply to it.  Please do not abuse this capability.  There is a good reason for the message size limit: it is there so that the maximum amount of memory required by the ZOID daemon stays limited.  Too many too large user-allocated buffers might result in an out-of-memory condition on the I/O node.&lt;br /&gt;
&lt;br /&gt;
We provide a simple example below.  It is a little artificial in the sense that the buffer is allocated within the implementation function; as we indicated, this feature is most useful with buffers allocated outside of the implementation functions:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
static void buffer_cb(void* userbuf, void* priv)&lt;br /&gt;
{&lt;br /&gt;
    free(userbuf);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
ssize_t unix_read(int fd /* in:obj */,&lt;br /&gt;
                  void *buf /* out:arr:size=+1:zerocopy:userbuf */,&lt;br /&gt;
                  size_t *count /* inout:ptr */)&lt;br /&gt;
{&lt;br /&gt;
    ssize_t ret;&lt;br /&gt;
&lt;br /&gt;
    ...&lt;br /&gt;
&lt;br /&gt;
    if (posix_memalign(&amp;amp;buf, 16, *count))&lt;br /&gt;
    {&lt;br /&gt;
        *count = 0;&lt;br /&gt;
        return -ENOMEM;&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    __zoid_register_userbuf(buf, &amp;amp;buffer_cb, NULL);&lt;br /&gt;
&lt;br /&gt;
    if ((ret = read(fd, buf, *count)) == -1)&lt;br /&gt;
    {&lt;br /&gt;
        *count = 0;&lt;br /&gt;
        return -errno;&lt;br /&gt;
    }&lt;br /&gt;
    else&lt;br /&gt;
    {&lt;br /&gt;
        *count = ret;&lt;br /&gt;
        return ret;&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
====Zerocopy with a custom input buffer====&lt;br /&gt;
&lt;br /&gt;
The &amp;lt;tt&amp;gt;userbuf&amp;lt;/tt&amp;gt; flag discussed above can also be used for ''input'' zero-copy &amp;lt;tt&amp;gt;arr&amp;lt;/tt&amp;gt; arguments.  This could be useful to avoid extra memory copies if the data in the array will be needed after the implementation function has returned.&lt;br /&gt;
&lt;br /&gt;
If the flag is used, the daemon will not allocate the memory for the array; instead, in the middle of receiving the request from the client, it will call an allocation routine from the server-side implementation code.  The name of the allocation routine is the name of the function that uses the input &amp;lt;tt&amp;gt;userbuf&amp;lt;/tt&amp;gt; argument, with &amp;lt;tt&amp;gt;_allocate_cb&amp;lt;/tt&amp;gt; suffix attached to it.  Its prototype needs to be as follows:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
void* &amp;lt;name&amp;gt;_allocate_cb(int len);&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The single argument passed by the daemon is the length of the array in bytes.  The routine must return a pointer to a buffer of that size or &amp;lt;tt&amp;gt;NULL&amp;lt;/tt&amp;gt; if that is not possible (in which case, the function will fail and &amp;lt;tt&amp;gt;__zoid_error&amp;lt;/tt&amp;gt; on the client side will return &amp;lt;tt&amp;gt;ENOMEM&amp;lt;/tt&amp;gt;).&lt;br /&gt;
&lt;br /&gt;
There is a restriction on the type of the array: its base type must have a size of one byte, so the array should be of type &amp;lt;tt&amp;gt;char*&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;unsigned char*&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;void*&amp;lt;/tt&amp;gt; (a GCC extension), etc.&lt;br /&gt;
&lt;br /&gt;
The allocation routine is invoked in the same context as ordinary implementation functions.  It may block if it so desires; this will block the compute node client that invoked the routine, but all other clients can keep communicating with the server, thanks to its multi-threaded architecture.&lt;br /&gt;
&lt;br /&gt;
Once the allocation routine has returned and a complete request has been received by the daemon, the implementation function is invoked as usual, with a correct address of the input &amp;lt;tt&amp;gt;userbuf&amp;lt;/tt&amp;gt; array.  It is the responsibility of the plug-in implementer to release the memory occupied by that array when it is no longer needed.&lt;br /&gt;
&lt;br /&gt;
As with other user-level callbacks, the allocation routine may call &amp;lt;tt&amp;gt;__zoid_calling_process_id&amp;lt;/tt&amp;gt; to learn which client process sent the request.  Also, as in other zero-copy cases, for maximum performance, the buffer provided must be aligned in memory to the 16-bytes boundary; otherwise, an interim buffer will be used.  The memory allocation routines such as &amp;lt;tt&amp;gt;malloc&amp;lt;/tt&amp;gt; have been modified to align memory to that boundary, but we recommend explicitly calling &amp;lt;tt&amp;gt;posix_memalign&amp;lt;/tt&amp;gt;.  Finally, as with output &amp;lt;tt&amp;gt;userbuf&amp;lt;/tt&amp;gt;, message size restrictions discussed [[#size_restrictions|earlier]] do not apply to the user-allocated buffers.  Please do not abuse this capability.  There is a good reason for the message size limit: it is there so that the maximum amount of memory required by the ZOID daemon stays limited.  Too many too large user-allocated buffers might result in an out-of-memory condition on the I/O node.&lt;br /&gt;
&lt;br /&gt;
Under rare circumstances, input &amp;lt;tt&amp;gt;userbuf&amp;lt;/tt&amp;gt; could result in memory leaks.  For this to take place, the job would have to be interrupted after the allocation routine has been run, but before the implementation function is called.  This could only cause problems if I/O nodes are not rebooted between jobs.  Those concerned about this scenario can eliminate the leak by adding necessary memory release code to the [[#Start-line functions|FINI]] function.&lt;br /&gt;
&lt;br /&gt;
A simple example:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
void* unix_write_allocate_cb(int len)&lt;br /&gt;
{&lt;br /&gt;
    void* ptr;&lt;br /&gt;
&lt;br /&gt;
    if (posix_memalign(&amp;amp;ptr, 16, len))&lt;br /&gt;
        return NULL;&lt;br /&gt;
&lt;br /&gt;
    return ptr;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
ssize_t unix_write(int fd /* in:obj */,&lt;br /&gt;
                   const void *buf /* in:arr:size=+1:zerocopy:userbuf */,&lt;br /&gt;
                   size_t count /* in:obj */)&lt;br /&gt;
{&lt;br /&gt;
    ssize_t ret;&lt;br /&gt;
&lt;br /&gt;
    ...&lt;br /&gt;
&lt;br /&gt;
    if ((ret = write(fd, buf, count)) == -1)&lt;br /&gt;
        ret = -errno;&lt;br /&gt;
&lt;br /&gt;
    free((void*)buf);&lt;br /&gt;
&lt;br /&gt;
    return ret;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
[[Ramdisk]] | [[ZeptoOS_Documentation|Top]] | [[(K)TAU]]&lt;/div&gt;</summary>
		<author><name>Iskra</name></author>
	</entry>
	<entry>
		<id> /zeptoos/index.php?title=Testing&amp;diff=570</id>
		<title>Testing</title>
		<link rel="alternate" type="text/html" href=" /zeptoos/index.php?title=Testing&amp;diff=570"/>
		<updated>2009-05-07T20:12:54Z</updated>

		<summary type="html">&lt;p&gt;Iskra: /* Interactive login */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;[[Installation]] | [[ZeptoOS_Documentation|Top]] | [[MPICH, DCMF, and SPI]]&lt;br /&gt;
----&lt;br /&gt;
&lt;br /&gt;
Once ZeptoOS is configured and installed, it is time to test it.  Here are a few trivial tests to verify that the environment is working:&lt;br /&gt;
&lt;br /&gt;
==The /bin/sleep job==&lt;br /&gt;
&lt;br /&gt;
If you are using Cobalt, submit using either of the commands below:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
$ cqsub -k &amp;lt;profile-name&amp;gt; -t &amp;lt;time&amp;gt; -n 1 /bin/sleep 3600&lt;br /&gt;
$ qsub --kernel &amp;lt;profile-name&amp;gt; -t &amp;lt;time&amp;gt; -n 1 /bin/sleep 3600&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
If you are using &amp;lt;tt&amp;gt;mpirun&amp;lt;/tt&amp;gt; directly, submit as follows:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
$ mpirun -verbose 1 -partition &amp;lt;partition-name&amp;gt; -np 1 -timeout &amp;lt;time&amp;gt; \&lt;br /&gt;
-cwd $PWD -exe /bin/sleep 3600&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This test, if successful, will verify that the ZeptoOS compute and I/O node environments are booting correctly.  We deliberately chose a system binary such as &amp;lt;tt&amp;gt;/bin/sleep&amp;lt;/tt&amp;gt; instead of something from a network filesystem so that even if the network filesystem does not come up for some reason, the test can still succeed.&lt;br /&gt;
&lt;br /&gt;
If everything works out fine, messages such as the following will be found in the error stream (''jobid''.error file if using Cobalt):&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
FE_MPI (Info) : initialize() - using jobname '' provided by scheduler interface&lt;br /&gt;
FE_MPI (Info) : Invoking mpirun backend&lt;br /&gt;
FE_MPI (Info) : connectToServer() - Handshake successful&lt;br /&gt;
BRIDGE (Info) : rm_set_serial() - The machine serial number (alias) is BGP&lt;br /&gt;
FE_MPI (Info) : Preparing partition&lt;br /&gt;
BE_MPI (Info) : Examining specified partition&lt;br /&gt;
BE_MPI (Info) : Checking partition ANL-R00-M1-N12-64 initial state ...&lt;br /&gt;
BE_MPI (Info) : Partition ANL-R00-M1-N12-64 initial state = FREE ('F')&lt;br /&gt;
BE_MPI (Info) : Checking partition owner...&lt;br /&gt;
BE_MPI (Info) : Setting new owner&lt;br /&gt;
BE_MPI (Info) : Initiating boot of the partition&lt;br /&gt;
BE_MPI (Info) : Waiting for partition ANL-R00-M1-N12-64 to boot...&lt;br /&gt;
BE_MPI (Info) : Partition is ready&lt;br /&gt;
BE_MPI (Info) : Done preparing partition&lt;br /&gt;
FE_MPI (Info) : Adding job&lt;br /&gt;
BE_MPI (Info) : Adding job to database...&lt;br /&gt;
FE_MPI (Info) : Job added with the following id: 98461&lt;br /&gt;
FE_MPI (Info) : Starting job 98461&lt;br /&gt;
FE_MPI (Info) : Waiting for job to terminate&lt;br /&gt;
BE_MPI (Info) : IO - Threads initialized&lt;br /&gt;
BE_MPI (Info) : I/O input runner thread terminated&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
(we stripped the timestamp prefixes to make the lines shorter)&lt;br /&gt;
&lt;br /&gt;
If these messages are immediately followed by other, error messages, then there is a problem.  One common instance would be:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
BE_MPI (Info) : I/O output runner thread terminated&lt;br /&gt;
BE_MPI (Info) : Job 98463 switched to state ERROR ('E')&lt;br /&gt;
BE_MPI (ERROR): Job execution failed&lt;br /&gt;
[...]&lt;br /&gt;
BE_MPI (ERROR): The error message in the job record is as follows:&lt;br /&gt;
BE_MPI (ERROR):   &amp;quot;Load failed on 172.16.3.11: Program segment is not 1MB aligned&amp;quot;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This error indicates that the job was submitted to the default software environment, not to ZeptoOS (at the very least, the default I/O node ramdisk was used).  You need to go back to the [[Installation#Setting up a kernel profile|Installation]] section to fix the problem.  Information from the system log files can be useful to diagnose the problem.&lt;br /&gt;
&lt;br /&gt;
==Log files==&lt;br /&gt;
&lt;br /&gt;
===I/O node===&lt;br /&gt;
&lt;br /&gt;
Every I/O node has its own log file located in &amp;lt;tt&amp;gt;/bgsys/logs/BGP/&amp;lt;/tt&amp;gt;, with a name such as &amp;lt;tt&amp;gt;R*-M*-N*-J*.log&amp;lt;/tt&amp;gt;.  This name will generally correspond to the name of the partition where the job was running.  Above, our job ran on &amp;lt;tt&amp;gt;ANL-R00-M1-N12-64&amp;lt;/tt&amp;gt; (we could see that in the error stream; Cobalt users can also use &amp;lt;tt&amp;gt;[c]qstat&amp;lt;/tt&amp;gt;); a corresponding I/O node log file on Argonne machines will be &amp;lt;tt&amp;gt;R00-M1-N12-J00.log&amp;lt;/tt&amp;gt;.  This is how a log file from a successful ZeptoOS boot looks like:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;Linux version 2.6.16.46-297 (geeko@buildhost) (gcc version 4.1.2 (BGP)) #1 SMP Wed Apr 22 15:04:42 CDT 2009&lt;br /&gt;
Kernel command line: console=bgcons root=/dev/ram0 lpj=8500000&lt;br /&gt;
init started:  BusyBox v1.4.2 (2008-04-10 05:20:01 UTC) multi-call binary&lt;br /&gt;
Starting RPC portmap daemon..done&lt;br /&gt;
eth0: Link status [RX+,TX+]&lt;br /&gt;
mount server reported tcp not available, falling back to udp&lt;br /&gt;
mount: RPC: Remote system error - No route to host&lt;br /&gt;
Zepto ION startup-00&lt;br /&gt;
eth0      Link encap:Ethernet  HWaddr 00:14:5E:7D:0C:57  &lt;br /&gt;
          inet addr:172.16.3.15  Bcast:172.31.255.255  Mask:255.240.0.0&lt;br /&gt;
          UP BROADCAST RUNNING MULTICAST  MTU:9000  Metric:1&lt;br /&gt;
          RX packets:880 errors:0 dropped:0 overruns:0 frame:0&lt;br /&gt;
          TX packets:1009 errors:0 dropped:0 overruns:0 carrier:0&lt;br /&gt;
          collisions:0 txqueuelen:1000 &lt;br /&gt;
          RX bytes:3878545 (3.6 Mb)  TX bytes:151458 (147.9 Kb)&lt;br /&gt;
          Interrupt:32 &lt;br /&gt;
Zepto ION startup-00 done&lt;br /&gt;
                                                                      done&lt;br /&gt;
Starting syslog servicesDec 31 18:00:36 ion-15 syslogd 1.4.1: restart.&lt;br /&gt;
                                                                      done&lt;br /&gt;
Starting network time protocol daemon (NTPD) using 172.17.3.1&lt;br /&gt;
May  1 12:57:11 ion-15 ntpdate[642]: step time server 172.17.3.1 offset 1241200617.470271 sec&lt;br /&gt;
May  1 12:57:11 ion-15 ntpd[653]: ntpd 4.2.0a@1.1196-r Sat Oct  4 00:01:53 UTC 2008 (1)&lt;br /&gt;
May  1 12:57:11 ion-15 ntpd[653]: precision = 1.000 usec&lt;br /&gt;
May  1 12:57:11 ion-15 ntpd[653]: Listening on interface wildcard, 0.0.0.0#123&lt;br /&gt;
May  1 12:57:11 ion-15 ntpd[653]: Listening on interface eth0, 172.16.3.15#123&lt;br /&gt;
May  1 12:57:11 ion-15 ntpd[653]: Listening on interface lo, 127.0.0.1#123&lt;br /&gt;
May  1 12:57:11 ion-15 ntpd[653]: kernel time sync status 0040&lt;br /&gt;
                                                                      done&lt;br /&gt;
Enabling ssh&lt;br /&gt;
Mounting site filesystems&lt;br /&gt;
                                                                      done&lt;br /&gt;
Loading PVFS2 kernel module                                           done&lt;br /&gt;
Sleeping 0 seconds before starting PVFS                               done&lt;br /&gt;
Starting PVFS2 client                                                 done&lt;br /&gt;
Sleeping 10 seconds before mounting PVFS&lt;br /&gt;
                                                                      done&lt;br /&gt;
Mounting PVFS2 filesystems                                            done&lt;br /&gt;
Starting SSH daemonMay  1 12:57:21 ion-15 sshd[833]: Server listening on 0.0.0.0 port 22.&lt;br /&gt;
                                                                      done&lt;br /&gt;
Zepto ION startup-12&lt;br /&gt;
Zepto ION startup-12 done&lt;br /&gt;
Starting GPFS&lt;br /&gt;
May  1 12:57:26 ion-15 syslogd 1.4.1: restart.&lt;br /&gt;
/etc/init.d/rc3.d/S40gpfs: GPFS is ready on I/O node ion-15 : 172.16.3.15 : R00-M1-N12-J00&lt;br /&gt;
ln: creating symbolic link `/home/acherryl/acherryl' to `/gpfs/home/acherryl': File exists&lt;br /&gt;
ln: creating symbolic link `/home/bgpadmin/bgpadmin' to `/gpfs/home/bgpadmin': File exists&lt;br /&gt;
ln: creating symbolic link `/home/davidr/davidr' to `/gpfs/home/davidr': File exists&lt;br /&gt;
ln: creating symbolic link `/home/scullinl/scullinl' to `/gpfs/home/scullinl': File exists&lt;br /&gt;
Starting ZOID...&lt;br /&gt;
                                                                      done&lt;br /&gt;
Zepto ION startup-99&lt;br /&gt;
Zepto ION startup-99 done&lt;br /&gt;
May  1 17:57:59 ion-15 init: Starting pid 2823, console /dev/console: '/bin/sh'&lt;br /&gt;
BusyBox v1.4.2 (2008-10-04 00:02:35 UTC) Built-in shell (ash)&lt;br /&gt;
Enter 'help' for a list of built-in commands.&lt;br /&gt;
/bin/sh: can't access tty; job control turned off&lt;br /&gt;
~ # &lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
(again, we stripped the prefixes to make the lines shorter)&lt;br /&gt;
&lt;br /&gt;
Messages such as &amp;lt;tt&amp;gt;Zepto ION startup&amp;lt;/tt&amp;gt; or &amp;lt;tt&amp;gt;Starting ZOID&amp;lt;/tt&amp;gt; clearly indicate that a ZeptoOS I/O node ramdisk is being used.  If one instead mistakenly booted with the default ramdisk, this could be recognized by messages such as:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
Starting CIO services&lt;br /&gt;
[ciod:initialized]                                                    done&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
(&amp;lt;tt&amp;gt;ciod&amp;lt;/tt&amp;gt; is ''never'' started when using Zepto Compute Node Linux)&lt;br /&gt;
&lt;br /&gt;
In addition to verifying the ramdisk, the correct I/O node kernel can also be verified using the I/O node logfile by checking the kernel build timestamp in the first line of the boot log.  As of this writing the default kernel on the Argonne machines has a timestamp of &amp;lt;tt&amp;gt;Wed Oct 29 18:51:19 UTC 2008&amp;lt;/tt&amp;gt;; as can be seen above, the ZeptoOS kernel was built more recently.&lt;br /&gt;
&lt;br /&gt;
===Compute node===&lt;br /&gt;
&lt;br /&gt;
All the compute nodes on the machine share the same MMCS log file, located in &amp;lt;tt&amp;gt;/bgsys/logs/BGP/&amp;lt;/tt&amp;gt;.  The name of the log file is not fixed (it contains a timestamp), but &amp;lt;tt&amp;gt;sn1-bgdb0-mmcs_db_server-current.log&amp;lt;/tt&amp;gt; always links to the current file.  Because the file is shared with other jobs, we recommed to grep it for user name, partition name, or both.&lt;br /&gt;
&lt;br /&gt;
A correct boot log when when booting ZeptoOS will look something like this:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
iskra:ANL-R00-M1-N12-64 {20}.0: Common Node Services V1R3M0 (efix:0)&lt;br /&gt;
iskra:ANL-R00-M1-N12-64 {20}.0: Licensed Machine Code - Property of IBM.&lt;br /&gt;
iskra:ANL-R00-M1-N12-64 {20}.0: Blue Gene/P Licensed Machine Code.&lt;br /&gt;
iskra:ANL-R00-M1-N12-64 {20}.0: Copyright IBM Corp., 2006, 2007 All Rights Reserved.&lt;br /&gt;
iskra:ANL-R00-M1-N12-64 {20}.0: Z: Zepto Linux Kernel relocating CNS... dst=80280000 src=fff40000 size=262144&lt;br /&gt;
iskra:ANL-R00-M1-N12-64 {20}.0: Z: CNS is successfully relocated to 00280000 in physical memory&lt;br /&gt;
iskra:ANL-R00-M1-N12-64 {20}.0: Linux version 2.6.19.2-g66cbca2d (kazutomo@login1) (gcc version 4.1.2 (BGP)) #12 SMP Tue Apr 21 12:58:11 CDT 2009&lt;br /&gt;
iskra:ANL-R00-M1-N12-64 {20}.0: Zone PFN ranges:&lt;br /&gt;
iskra:ANL-R00-M1-N12-64 {20}.0:   DMA             0 -&amp;gt;    28672&lt;br /&gt;
iskra:ANL-R00-M1-N12-64 {20}.0:   Normal      28672 -&amp;gt;    28672&lt;br /&gt;
iskra:ANL-R00-M1-N12-64 {20}.0: early_node_map[1] active PFN ranges&lt;br /&gt;
iskra:ANL-R00-M1-N12-64 {20}.1:     0:        0 -&amp;gt;    28672&lt;br /&gt;
iskra:ANL-R00-M1-N12-64 {20}.1: Built 1 zonelists.  Total pages: 28658&lt;br /&gt;
iskra:ANL-R00-M1-N12-64 {20}.1: Kernel command line: console=bgcons root=/dev/ram0 lpj=8500000&lt;br /&gt;
iskra:ANL-R00-M1-N12-64 {20}.1: PID hash table entries: 4096 (order: 12, 16384 bytes)&lt;br /&gt;
iskra:ANL-R00-M1-N12-64 {20}.0: Dentry cache hash table entries: 262144 (order: 4, 1048576 bytes)&lt;br /&gt;
iskra:ANL-R00-M1-N12-64 {20}.0: Inode-cache hash table entries: 131072 (order: 3, 524288 bytes)&lt;br /&gt;
iskra:ANL-R00-M1-N12-64 {20}.0: Memory: 1826560k available (1408k kernel code, 832k data, 192k init, 0k highmem)&lt;br /&gt;
iskra:ANL-R00-M1-N12-64 {20}.0: Calibrating delay loop (skipped)... 1700.00 BogoMIPS preset&lt;br /&gt;
iskra:ANL-R00-M1-N12-64 {20}.0: Mount-cache hash table entries: 8192&lt;br /&gt;
iskra:ANL-R00-M1-N12-64 {20}.0: CPU 1 done callin...&lt;br /&gt;
iskra:ANL-R00-M1-N12-64 {20}.0: CPU 1 done setup...&lt;br /&gt;
iskra:ANL-R00-M1-N12-64 {20}.0: CPU 1 done timebase take...&lt;br /&gt;
iskra:ANL-R00-M1-N12-64 {20}.0: Processor 1 found.&lt;br /&gt;
iskra:ANL-R00-M1-N12-64 {20}.0: CPU 2 done callin...&lt;br /&gt;
iskra:ANL-R00-M1-N12-64 {20}.0: CPU 2 done setup...&lt;br /&gt;
iskra:ANL-R00-M1-N12-64 {20}.0: CPU 2 done timebase take...&lt;br /&gt;
iskra:ANL-R00-M1-N12-64 {20}.0: Processor 2 found.&lt;br /&gt;
iskra:ANL-R00-M1-N12-64 {20}.0: CPU 3 done callin...&lt;br /&gt;
iskra:ANL-R00-M1-N12-64 {20}.0: CPU 3 done setup...&lt;br /&gt;
iskra:ANL-R00-M1-N12-64 {20}.0: CPU 3 done timebase take...&lt;br /&gt;
iskra:ANL-R00-M1-N12-64 {20}.0: Processor 3 found.&lt;br /&gt;
iskra:ANL-R00-M1-N12-64 {20}.0: Brought up 4 CPUs&lt;br /&gt;
iskra:ANL-R00-M1-N12-64 {20}.0: migration_cost=0&lt;br /&gt;
iskra:ANL-R00-M1-N12-64 {20}.0: checking if image is initramfs... it is&lt;br /&gt;
iskra:ANL-R00-M1-N12-64 {20}.0: Freeing initrd memory: 2575k freed&lt;br /&gt;
iskra:ANL-R00-M1-N12-64 {20}.0: NET: Registered protocol family 16&lt;br /&gt;
iskra:ANL-R00-M1-N12-64 {20}.0: NET: Registered protocol family 2&lt;br /&gt;
iskra:ANL-R00-M1-N12-64 {20}.0: IP route cache hash table entries: 16384 (order: 0, 65536 bytes)&lt;br /&gt;
iskra:ANL-R00-M1-N12-64 {20}.0: TCP established hash table entries: 65536 (order: 3, 524288 bytes)&lt;br /&gt;
iskra:ANL-R00-M1-N12-64 {20}.0: TCP bind hash table entries: 32768 (order: 2, 262144 bytes)&lt;br /&gt;
iskra:ANL-R00-M1-N12-64 {20}.0: TCP: Hash tables configured (established 65536 bind 32768)&lt;br /&gt;
iskra:ANL-R00-M1-N12-64 {20}.0: TCP reno registered&lt;br /&gt;
iskra:ANL-R00-M1-N12-64 {20}.0: fuse init (API version 7.7)&lt;br /&gt;
iskra:ANL-R00-M1-N12-64 {20}.0: io scheduler noop registered (default)&lt;br /&gt;
iskra:ANL-R00-M1-N12-64 {20}.0: RAMDISK driver initialized: 16 RAM disks of 32768K size 1024 blocksize&lt;br /&gt;
iskra:ANL-R00-M1-N12-64 {20}.0: tun: Universal TUN/TAP device driver, 1.6&lt;br /&gt;
iskra:ANL-R00-M1-N12-64 {20}.0: tun: (C) 1999-2004 Max Krasnyansky &amp;lt;maxk@qualcomm.com&amp;gt;&lt;br /&gt;
iskra:ANL-R00-M1-N12-64 {20}.0: TCP cubic registered&lt;br /&gt;
iskra:ANL-R00-M1-N12-64 {20}.0: NET: Registered protocol family 1&lt;br /&gt;
iskra:ANL-R00-M1-N12-64 {20}.0: NET: Registered protocol family 17&lt;br /&gt;
iskra:ANL-R00-M1-N12-64 {20}.0: NET: Registered protocol family 15&lt;br /&gt;
iskra:ANL-R00-M1-N12-64 {20}.0: Freeing unused kernel memory: 192k init&lt;br /&gt;
iskra:ANL-R00-M1-N12-64 {20}.0: init started: BusyBox(for ZeptoOS Compute Node) v1.12.1 (2009-04-21 16:08:55 CDT)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This is very easy to tell from a boot log of the default light-weight kernel, which will consist of the first four lines ''only''.&lt;br /&gt;
&lt;br /&gt;
The MMCS log file contains other useful information besides the boot log of the compute nodes.  Before the kernel starts booting, the following messages related to the newly submitted job can be found there:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
DBBlockCmd  DatabaseBlockCommandThread started: block ANL-R00-M1-N12-64, user iskra, action 1&lt;br /&gt;
DBBlockCmd  setusername iskra &lt;br /&gt;
iskra       db_allocate ANL-R00-M1-N12-64 &lt;br /&gt;
iskra       DBConsoleController::setAllocating() ANL-R00-M1-N12-64&lt;br /&gt;
iskra       block state C&lt;br /&gt;
iskra       DBConsoleController::addBlock(ANL-R00-M1-N12-64)&lt;br /&gt;
iskra:ANL-R00-M1-N12-64     BlockController::connect()&lt;br /&gt;
iskra:ANL-R00-M1-N12-64     connecting to mcServer at 127.0.0.1:1206&lt;br /&gt;
    Connected to MCServer as iskra@sn1. Client version 3. Server version 3 on fd 101&lt;br /&gt;
iskra:ANL-R00-M1-N12-64     connected to mcServer&lt;br /&gt;
iskra:ANL-R00-M1-N12-64     mcServer target set ANL-R00-M1-N12-64 created&lt;br /&gt;
iskra:ANL-R00-M1-N12-64     mcServer target set ANL-R00-M1-N12-64 opened&lt;br /&gt;
iskra:ANL-R00-M1-N12-64     {0} I/O log file: /bgsys/logs/BGP/R00-M1-N12-J00.log&lt;br /&gt;
iskra:ANL-R00-M1-N12-64     MailboxListener starting&lt;br /&gt;
iskra:ANL-R00-M1-N12-64     DBConsoleController::doneAllocating() ANL-R00-M1-N12-64&lt;br /&gt;
iskra:ANL-R00-M1-N12-64     BlockController::boot_block \&lt;br /&gt;
uloader=/bgsys/argonne-utils/partitions/ANL-R00-M1-N12-64/uloader \&lt;br /&gt;
cnload=/bgsys/argonne-utils/partitions/ANL-R00-M1-N12-64/CNS,/bgsys/argonne-utils/partitions/ANL-R00-M1-N12-64/CNK \&lt;br /&gt;
ioload=/bgsys/argonne-utils/partitions/ANL-R00-M1-N12-64/CNS,/bgsys/argonne-utils/partitions/ANL-R00-M1-N12-64/INK,/bgsys/argonne-utils/partitions/ANL-R00-M1-N12-64/ramdisk &lt;br /&gt;
iskra:ANL-R00-M1-N12-64     boot_block cookie: 587867023 compute_nodes: 64 io_nodes: 1&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Of particular relevance is the pathname to the I/O node log file(s) (if it cannot be easily guessed from the partition name) and the pathnames to the kernels and ramdisks used to boot the partition.&lt;br /&gt;
&lt;br /&gt;
After the kernel boot log, the log file will also contain information about subsequent phases of starting a job:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
iskra:ANL-R00-M1-N12-64     I/O node initialized: R00-M1-N12-J00&lt;br /&gt;
iskra:ANL-R00-M1-N12-64     DBBlockController::waitBoot(ANL-R00-M1-N12-64) block initialization successful&lt;br /&gt;
iskra       DatabaseBlockCommandThread stopped&lt;br /&gt;
DBJobCmd    DatabaseJobCommandThread started: job 98461, user iskra, action 1&lt;br /&gt;
DBJobCmd    setusername iskra &lt;br /&gt;
iskra       Starting Job 98461&lt;br /&gt;
    New thread 4398305505840, for jobid 98461&lt;br /&gt;
    selectBlock(): ANL-R00-M1-N12-64        iskra(1)        connected state: I owner: iskra&lt;br /&gt;
ANL-R00-M1-N12-64   Jobid is 98461, homedir is /gpfs/home/iskra&lt;br /&gt;
ANL-R00-M1-N12-64   persist: 1&lt;br /&gt;
ANL-R00-M1-N12-64   connecting to mpirun...&lt;br /&gt;
ANL-R00-M1-N12-64   setting mpirun stream, fd=386&lt;br /&gt;
ANL-R00-M1-N12-64   contacting control node 0 at 172.16.3.15:7000&lt;br /&gt;
ANL-R00-M1-N12-64   connected to control node 0 at 172.16.3.15:7000&lt;br /&gt;
ANL-R00-M1-N12-64   Job::load() /bin/sleep &lt;br /&gt;
ANL-R00-M1-N12-64   Job loaded: 98461&lt;br /&gt;
ANL-R00-M1-N12-64   About to start /bin/sleep&lt;br /&gt;
ANL-R00-M1-N12-64   Job 98461 set to RUNNING&lt;br /&gt;
iskra:ANL-R00-M1-N12-64     {20}.0: floating point used in kernel (task=8080cfe0, pc=80017064)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Interactive login==&lt;br /&gt;
&lt;br /&gt;
We are assuming at this point that launching &amp;lt;tt&amp;gt;/bin/sleep&amp;lt;/tt&amp;gt; has been successful and that the &amp;quot;job&amp;quot; is running.  We can now start an interactive session on our BG/P resources.  Probably the most complicated part of this operation is finding the IP address of the I/O node(s).  The allocation of I/O nodes to partitions is fixed, so on a small machine one could simply make a list.  This information is also available in the log files discussed above.&lt;br /&gt;
&lt;br /&gt;
The IP address is printed near the top of the I/O node boot log, as part of the interface configuration of the Ethernet device:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
eth0      Link encap:Ethernet  HWaddr 00:14:5E:7D:0C:57  &lt;br /&gt;
          inet addr:172.16.3.15  Bcast:172.31.255.255  Mask:255.240.0.0&lt;br /&gt;
          UP BROADCAST RUNNING MULTICAST  MTU:9000  Metric:1&lt;br /&gt;
          RX packets:880 errors:0 dropped:0 overruns:0 frame:0&lt;br /&gt;
          TX packets:1009 errors:0 dropped:0 overruns:0 carrier:0&lt;br /&gt;
          collisions:0 txqueuelen:1000 &lt;br /&gt;
          RX bytes:3878545 (3.6 Mb)  TX bytes:151458 (147.9 Kb)&lt;br /&gt;
          Interrupt:32&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
In this case, the address is &amp;lt;tt&amp;gt;172.16.3.15&amp;lt;/tt&amp;gt; (the &amp;lt;tt&amp;gt;inet addr&amp;lt;/tt&amp;gt; value).&lt;br /&gt;
&lt;br /&gt;
The IP address is also available from the MMCS log file:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
ANL-R00-M1-N12-64   contacting control node 0 at 172.16.3.15:7000&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
With larger partitions that include multiple I/O nodes, querying the MMCS logfile is probably better, as it will list all the addresses.&lt;br /&gt;
&lt;br /&gt;
Once the IP address is known, one can simply use the SSH:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
iskra@login1.surveyor:~&amp;gt; ssh 172.16.3.15&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
BusyBox v1.4.2 (2008-10-04 00:02:35 UTC) Built-in shell (ash)&lt;br /&gt;
Enter 'help' for a list of built-in commands.&lt;br /&gt;
&lt;br /&gt;
/gpfs/home/iskra $ hostname&lt;br /&gt;
ion-15&lt;br /&gt;
/gpfs/home/iskra $ &lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
If everything is configured correctly, SSH will only let in root and the partition owner; no other unprivileged user will be allowed on the node.  However, this might require site-specific customization to work properly.  To enable access for the partition owner, one might need to make adjustments to [[ZOID#The /bin.rd/update_passwd_file.sh file|update_passwd_file.sh]].  To enable password-less login for the partition owners without requiring them to set up personal SSH keypairs, we recommend to add the names of the front end nodes to the &amp;lt;tt&amp;gt;shosts.equiv&amp;lt;/tt&amp;gt; file, found in &amp;lt;tt&amp;gt;ramdisk/ION/ramdisk-add/etc/ssh.zepto/&amp;lt;/tt&amp;gt; (it is empty by default; remember to use the names from the network that interconnects front end and I/O nodes, which might be different from hostnames, e.g., at Argonne we need to add the &amp;lt;tt&amp;gt;-data&amp;lt;/tt&amp;gt; suffix to the hostnames).  Until this has all been set up, one might prefer to log on as root (&amp;lt;tt&amp;gt;ssh -l root&amp;lt;/tt&amp;gt;), passing the password provided while [[Configuration#Building|building]] the ZeptoOS environment.&lt;br /&gt;
&lt;br /&gt;
Also, even when the partition owner is correctly set up, there will be a time window while booting the I/O node when the SSH daemon is already running, but a job has not yet been started; during that window, the partition owner cannot log on. If that happens, wait a few seconds and try again.&lt;br /&gt;
&lt;br /&gt;
Here's part of the &amp;lt;tt&amp;gt;ps&amp;lt;/tt&amp;gt; output from the I/O node:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
/gpfs/home/iskra $ ps -ef&lt;br /&gt;
UID        PID  PPID  C STIME TTY          TIME CMD&lt;br /&gt;
[...]&lt;br /&gt;
65534       98     1  0 16:09 ?        00:00:00 /sbin/portmap&lt;br /&gt;
root       108    19  0 16:09 ?        00:00:00 [rpciod/0]&lt;br /&gt;
root       109    19  0 16:09 ?        00:00:00 [rpciod/1]&lt;br /&gt;
root       110    19  0 16:09 ?        00:00:00 [rpciod/2]&lt;br /&gt;
root       111    19  0 16:09 ?        00:00:00 [rpciod/3]&lt;br /&gt;
root       570     1  0 16:09 ?        00:00:00 /sbin/syslogd&lt;br /&gt;
root       577     1  0 16:09 ?        00:00:00 /sbin/klogd -c 1 -x -x&lt;br /&gt;
ntp        653     1  0 16:09 ?        00:00:00 /usr/sbin/ntpd -p /var/run/ntpd.&lt;br /&gt;
root       688     1  0 16:09 ?        00:00:00 [lockd]&lt;br /&gt;
root       775     1  0 16:09 ?        00:00:00 /bgsys/iosoft/pvfs2/sbin/pvfs2-c&lt;br /&gt;
root       776   775  0 16:09 ?        00:00:00 pvfs2-client-core --child -a 5 -&lt;br /&gt;
root       833     1  0 16:10 ?        00:00:00 /usr/sbin/sshd -o PidFile=/var/r&lt;br /&gt;
root      1016     1  0 16:10 ?        00:00:00 /bin/ksh /usr/lpp/mmfs/bin/runmm&lt;br /&gt;
root      1079     1  0 16:10 ?        00:00:00 [nfsWatchKproc]&lt;br /&gt;
root      1080     1  0 16:10 ?        00:00:00 [gpfsSwapdKproc]&lt;br /&gt;
root      1146  1016  0 16:10 ?        00:00:01 /usr/lpp/mmfs/bin//mmfsd&lt;br /&gt;
root      1153     1  0 16:10 ?        00:00:00 [mmkproc]&lt;br /&gt;
root      1152     1  0 16:10 ?        00:00:00 [mmkproc]&lt;br /&gt;
root      1154     1  0 16:10 ?        00:00:00 [mmkproc]&lt;br /&gt;
iskra     2810     1 98 16:10 ?        00:04:09 /bin.rd/zoid -a 8 -m unix_impl.s&lt;br /&gt;
root      2823     1  0 16:10 ?        00:00:00 /bin/sh&lt;br /&gt;
root      3328   833  0 16:10 ?        00:00:00 sshd: iskra [priv]             &lt;br /&gt;
iskra     3332  3328  0 16:10 ?        00:00:00 sshd: iskra@ttyp0              &lt;br /&gt;
iskra     3333  3332  0 16:10 ttyp0    00:00:00 -sh&lt;br /&gt;
iskra     3346  3333  0 16:14 ttyp0    00:00:00 ps -ef&lt;br /&gt;
/gpfs/home/iskra $ &lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The I/O nodes run a small Linux setup with the root filesystem in the ramdisk.  Custom processes can be started, just like on any ordinary Linux node.  In the example above, it is mostly a few system daemons and the remote filesystem clients (GPFS, PVFS).  Please verify at this stage that the remote filesystem have been mounted correctly.&lt;br /&gt;
&lt;br /&gt;
One custom process running on the node is [[ZOID]], the I/O forwarding and job control daemon, which enables the communication with the compute nodes.  One of the facilities offered by ZOID is IP forwarding between the I/O node and the compute nodes, implemented using the virtual network tunneling device available in Linux:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
/gpfs/home/iskra $ ifconfig tun0&lt;br /&gt;
tun0      Link encap:UNSPEC  HWaddr 00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00  &lt;br /&gt;
          inet addr:192.168.1.254  P-t-P:192.168.1.254  Mask:255.255.255.255&lt;br /&gt;
          UP POINTOPOINT RUNNING NOARP MULTICAST  MTU:65535  Metric:1&lt;br /&gt;
          RX packets:0 errors:0 dropped:0 overruns:0 frame:0&lt;br /&gt;
          TX packets:0 errors:0 dropped:0 overruns:0 carrier:0&lt;br /&gt;
          collisions:0 txqueuelen:500 &lt;br /&gt;
          RX bytes:0 (0.0 b)  TX bytes:0 (0.0 b)&lt;br /&gt;
/gpfs/home/iskra $ &lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
At least on Argonne machines, with a 64:1 ratio of compute nodes to I/O nodes, compute nodes have addresses &amp;lt;tt&amp;gt;192.168.1.1&amp;lt;/tt&amp;gt; to &amp;lt;tt&amp;gt;192.168.1.64&amp;lt;/tt&amp;gt; (the last octet of the address is the [[FAQ#Pset rank|pset rank]]).  Somewhat confusingly, the first compute node (compute node &amp;lt;tt&amp;gt;0&amp;lt;/tt&amp;gt;) has IP address &amp;lt;tt&amp;gt;192.168.1.64&amp;lt;/tt&amp;gt;, so if one submits a one-node job as we did, that is the IP address that needs to be used to log on that sole running compute node.  The IP address of the second compute node is... &amp;lt;tt&amp;gt;192.168.1.59&amp;lt;/tt&amp;gt;.  On a machine with a 16:1 ratio of compute nodes to I/O nodes, the first compute node has IP address &amp;lt;tt&amp;gt;192.168.1.16&amp;lt;/tt&amp;gt;.  Do not blame us for this chaos &amp;amp;#8211; blame IBM&amp;amp;nbsp;:-).&lt;br /&gt;
&lt;br /&gt;
The compute nodes are running a &amp;lt;tt&amp;gt;telnet&amp;lt;/tt&amp;gt; daemon, and no password is required to log on them:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
/gpfs/home/iskra $ telnet 192.168.1.64&lt;br /&gt;
&lt;br /&gt;
Entering character mode&lt;br /&gt;
Escape character is '^]'.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
BusyBox(for ZeptoOS Compute Node) v1.12.1 (2009-04-21 16:08:55 CDT) built-in shell (ash)&lt;br /&gt;
Enter 'help' for a list of built-in commands.&lt;br /&gt;
&lt;br /&gt;
~ # &lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The IP address of the I/O node on this virtual network is &amp;lt;tt&amp;gt;192.168.1.254&amp;lt;/tt&amp;gt;. The network is local to each I/O node, so for larger jobs, there will be multiple distinct virtual networks that cannot communicate with each other, and the IP addresses will duplicate.&lt;br /&gt;
&lt;br /&gt;
Here's part of the &amp;lt;tt&amp;gt;ps&amp;lt;/tt&amp;gt; output from the compute node:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
~ # ps -ef&lt;br /&gt;
  PID USER       VSZ STAT COMMAND&lt;br /&gt;
[...]&lt;br /&gt;
   34 root      5440 S    /bin/sh /etc/init.d/rc.sysinit &lt;br /&gt;
   44 root      5504 S    /sbin/telnetd -l /bin/sh &lt;br /&gt;
   47 root      6528 S    /sbin/inetd &lt;br /&gt;
   48 root     46400 R N  /sbin/control &lt;br /&gt;
   62 root      7872 S    /bin/zoid-fuse -o allow_other -s /fuse &lt;br /&gt;
  116 root      5248 S    /bin/sleep 3600 &lt;br /&gt;
  118 root      5504 S    /bin/sh &lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Compute nodes have an even more stripped-down environment than the I/O nodes.  There are no user accounts &amp;amp;#8211; everything runs as root, including the application processes.  This is not a security concern, because the only practical way for a compute node to communicate with the outside world is through the I/O node, and I/O nodes ''do'' enforce user-level access control.&lt;br /&gt;
&lt;br /&gt;
There are two custom processes running on each compute node:&lt;br /&gt;
&lt;br /&gt;
'''control''' is a job management daemon responsible for tasks such as the launching of application processes, for the forwarding of stdin/out/err data, and for the management of the virtual network tunneling device from the compute node side.  Do not interfere with this process in any way; this would likely make the node inaccessible.&lt;br /&gt;
&lt;br /&gt;
'''zoid-fuse''' is a FUSE ([http://fuse.sourceforge.net/ Filesystem in Userspace]) client responsible for making the filesystems from the I/O nodes available to ordinary POSIX-compliant processes running on the compute nodes.  The whole filesystem namespace from the I/O nodes is made available on the compute nodes under &amp;lt;tt&amp;gt;/fuse/&amp;lt;/tt&amp;gt;, and symbolic links such as &amp;lt;tt&amp;gt;/home -&amp;gt; /fuse/home&amp;lt;/tt&amp;gt; are set up to keep the login and I/O node pathnames valid on the compute nodes.  Please verify that this is correctly set up.  We do not foresee a need to change this setup, but should that prove necessary, the responsbile &amp;lt;tt&amp;gt;fuse-start&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;fuse-stop&amp;lt;/tt&amp;gt; scripts can be found under &amp;lt;tt&amp;gt;ramdisk/CN/tree/bin&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
==Shell script job==&lt;br /&gt;
&lt;br /&gt;
Assuming that the above steps have been successful, one can now test running a simple job from a network filesystem, such as one's home directory.&lt;br /&gt;
&lt;br /&gt;
Here is a sample shell script to try:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
#!/bin/sh&lt;br /&gt;
&lt;br /&gt;
. /proc/personality.sh&lt;br /&gt;
&lt;br /&gt;
while true; do&lt;br /&gt;
    echo &amp;quot;Node $BG_RANK_IN_PSET running (stdout)&amp;quot;&lt;br /&gt;
    echo &amp;quot;Node $BG_RANK_IN_PSET running (stderr)&amp;quot; 1&amp;gt;&amp;amp;2&lt;br /&gt;
    sleep 10&lt;br /&gt;
done&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
(please see the [[FAQ#Pset rank|FAQ]] for the explanation of &amp;lt;tt&amp;gt;/proc/personality.sh&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;BG_RANK_IN_PSET&amp;lt;/tt&amp;gt;)&lt;br /&gt;
&lt;br /&gt;
Please create the script file on the network filesystem, set the executable bit (&amp;lt;tt&amp;gt;chmod 755&amp;lt;/tt&amp;gt;) and submit it.  Verify that the script starts correctly and that at least the standard error output is visible immediately.  The scripts print a line of output from each node every ten seconds.  It does so both to the standard output and to the standard error, because, depending on software configuration, the standard output stream could be buffered.  If that is the case, kill the job and verify that the standard output data did appear.&lt;br /&gt;
&lt;br /&gt;
==MPI and OpenMP jobs==&lt;br /&gt;
&lt;br /&gt;
The final tests involve parallel programming jobs, respectively MPI and OpenMP.  Use the test programs provided with the distribution. From the top level directory:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
$ cd comm/testcodes&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Compiling===&lt;br /&gt;
&lt;br /&gt;
The programs can be compiled on a login node using:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
$ /path/to/install/bin/zmpicc -o mpi-test-linux mpi-test.c&lt;br /&gt;
$ /path/to/install/bin/zmpixlc_r -qsmp=omp -o omp-test-linux omp-test.c&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Submitting===&lt;br /&gt;
&lt;br /&gt;
Submit the MPI test like any other job; use one of the below:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
$ cqsub -k &amp;lt;profile-name&amp;gt; -t &amp;lt;time&amp;gt; -n &amp;lt;number-of-processes&amp;gt; $PWD/mpi-test-linux&lt;br /&gt;
$ qsub --kernel &amp;lt;profile-name&amp;gt; -t &amp;lt;time&amp;gt; -n &amp;lt;number-of-processes&amp;gt;  $PWD/mpi-test-linux&lt;br /&gt;
$ mpirun -verbose 1 -partition &amp;lt;partition-name&amp;gt; -np &amp;lt;number-of-processes&amp;gt; -timeout &amp;lt;time&amp;gt; \&lt;br /&gt;
-cwd $PWD -exe $PWD/omp-test-linux&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
For the OpenMP test, we pass the number of OpenMP threads to use in the &amp;lt;tt&amp;gt;OMP_NUM_THREADS&amp;lt;/tt&amp;gt; variable:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
$ cqsub -k &amp;lt;profile-name&amp;gt; -t &amp;lt;time&amp;gt; -n 1 -e OMP_NUM_THREADS=&amp;lt;num&amp;gt; $PWD/omp-test-linux&lt;br /&gt;
$ qsub --kernel &amp;lt;profile-name&amp;gt; -t &amp;lt;time&amp;gt; -n 1 --env OMP_NUM_THREADS=&amp;lt;num&amp;gt; $PWD/mpi-test-linux&lt;br /&gt;
$ mpirun -verbose 1 -partition &amp;lt;partition-name&amp;gt; -np 1 -timeout &amp;lt;time&amp;gt; \&lt;br /&gt;
-cwd $PWD -env OMP_NUM_THREADS=&amp;lt;num&amp;gt; -exe $PWD/omp-test-linux&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The MPI test benchmarks the performance of various MPI operations.  The OpenMP test is just a parallel &amp;quot;Hello world&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
[[Installation]] | [[ZeptoOS_Documentation|Top]] | [[MPICH, DCMF, and SPI]]&lt;/div&gt;</summary>
		<author><name>Iskra</name></author>
	</entry>
	<entry>
		<id> /zeptoos/index.php?title=Testing&amp;diff=569</id>
		<title>Testing</title>
		<link rel="alternate" type="text/html" href=" /zeptoos/index.php?title=Testing&amp;diff=569"/>
		<updated>2009-05-07T20:01:25Z</updated>

		<summary type="html">&lt;p&gt;Iskra: /* Interactive login */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;[[Installation]] | [[ZeptoOS_Documentation|Top]] | [[MPICH, DCMF, and SPI]]&lt;br /&gt;
----&lt;br /&gt;
&lt;br /&gt;
Once ZeptoOS is configured and installed, it is time to test it.  Here are a few trivial tests to verify that the environment is working:&lt;br /&gt;
&lt;br /&gt;
==The /bin/sleep job==&lt;br /&gt;
&lt;br /&gt;
If you are using Cobalt, submit using either of the commands below:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
$ cqsub -k &amp;lt;profile-name&amp;gt; -t &amp;lt;time&amp;gt; -n 1 /bin/sleep 3600&lt;br /&gt;
$ qsub --kernel &amp;lt;profile-name&amp;gt; -t &amp;lt;time&amp;gt; -n 1 /bin/sleep 3600&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
If you are using &amp;lt;tt&amp;gt;mpirun&amp;lt;/tt&amp;gt; directly, submit as follows:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
$ mpirun -verbose 1 -partition &amp;lt;partition-name&amp;gt; -np 1 -timeout &amp;lt;time&amp;gt; \&lt;br /&gt;
-cwd $PWD -exe /bin/sleep 3600&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This test, if successful, will verify that the ZeptoOS compute and I/O node environments are booting correctly.  We deliberately chose a system binary such as &amp;lt;tt&amp;gt;/bin/sleep&amp;lt;/tt&amp;gt; instead of something from a network filesystem so that even if the network filesystem does not come up for some reason, the test can still succeed.&lt;br /&gt;
&lt;br /&gt;
If everything works out fine, messages such as the following will be found in the error stream (''jobid''.error file if using Cobalt):&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
FE_MPI (Info) : initialize() - using jobname '' provided by scheduler interface&lt;br /&gt;
FE_MPI (Info) : Invoking mpirun backend&lt;br /&gt;
FE_MPI (Info) : connectToServer() - Handshake successful&lt;br /&gt;
BRIDGE (Info) : rm_set_serial() - The machine serial number (alias) is BGP&lt;br /&gt;
FE_MPI (Info) : Preparing partition&lt;br /&gt;
BE_MPI (Info) : Examining specified partition&lt;br /&gt;
BE_MPI (Info) : Checking partition ANL-R00-M1-N12-64 initial state ...&lt;br /&gt;
BE_MPI (Info) : Partition ANL-R00-M1-N12-64 initial state = FREE ('F')&lt;br /&gt;
BE_MPI (Info) : Checking partition owner...&lt;br /&gt;
BE_MPI (Info) : Setting new owner&lt;br /&gt;
BE_MPI (Info) : Initiating boot of the partition&lt;br /&gt;
BE_MPI (Info) : Waiting for partition ANL-R00-M1-N12-64 to boot...&lt;br /&gt;
BE_MPI (Info) : Partition is ready&lt;br /&gt;
BE_MPI (Info) : Done preparing partition&lt;br /&gt;
FE_MPI (Info) : Adding job&lt;br /&gt;
BE_MPI (Info) : Adding job to database...&lt;br /&gt;
FE_MPI (Info) : Job added with the following id: 98461&lt;br /&gt;
FE_MPI (Info) : Starting job 98461&lt;br /&gt;
FE_MPI (Info) : Waiting for job to terminate&lt;br /&gt;
BE_MPI (Info) : IO - Threads initialized&lt;br /&gt;
BE_MPI (Info) : I/O input runner thread terminated&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
(we stripped the timestamp prefixes to make the lines shorter)&lt;br /&gt;
&lt;br /&gt;
If these messages are immediately followed by other, error messages, then there is a problem.  One common instance would be:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
BE_MPI (Info) : I/O output runner thread terminated&lt;br /&gt;
BE_MPI (Info) : Job 98463 switched to state ERROR ('E')&lt;br /&gt;
BE_MPI (ERROR): Job execution failed&lt;br /&gt;
[...]&lt;br /&gt;
BE_MPI (ERROR): The error message in the job record is as follows:&lt;br /&gt;
BE_MPI (ERROR):   &amp;quot;Load failed on 172.16.3.11: Program segment is not 1MB aligned&amp;quot;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This error indicates that the job was submitted to the default software environment, not to ZeptoOS (at the very least, the default I/O node ramdisk was used).  You need to go back to the [[Installation#Setting up a kernel profile|Installation]] section to fix the problem.  Information from the system log files can be useful to diagnose the problem.&lt;br /&gt;
&lt;br /&gt;
==Log files==&lt;br /&gt;
&lt;br /&gt;
===I/O node===&lt;br /&gt;
&lt;br /&gt;
Every I/O node has its own log file located in &amp;lt;tt&amp;gt;/bgsys/logs/BGP/&amp;lt;/tt&amp;gt;, with a name such as &amp;lt;tt&amp;gt;R*-M*-N*-J*.log&amp;lt;/tt&amp;gt;.  This name will generally correspond to the name of the partition where the job was running.  Above, our job ran on &amp;lt;tt&amp;gt;ANL-R00-M1-N12-64&amp;lt;/tt&amp;gt; (we could see that in the error stream; Cobalt users can also use &amp;lt;tt&amp;gt;[c]qstat&amp;lt;/tt&amp;gt;); a corresponding I/O node log file on Argonne machines will be &amp;lt;tt&amp;gt;R00-M1-N12-J00.log&amp;lt;/tt&amp;gt;.  This is how a log file from a successful ZeptoOS boot looks like:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;Linux version 2.6.16.46-297 (geeko@buildhost) (gcc version 4.1.2 (BGP)) #1 SMP Wed Apr 22 15:04:42 CDT 2009&lt;br /&gt;
Kernel command line: console=bgcons root=/dev/ram0 lpj=8500000&lt;br /&gt;
init started:  BusyBox v1.4.2 (2008-04-10 05:20:01 UTC) multi-call binary&lt;br /&gt;
Starting RPC portmap daemon..done&lt;br /&gt;
eth0: Link status [RX+,TX+]&lt;br /&gt;
mount server reported tcp not available, falling back to udp&lt;br /&gt;
mount: RPC: Remote system error - No route to host&lt;br /&gt;
Zepto ION startup-00&lt;br /&gt;
eth0      Link encap:Ethernet  HWaddr 00:14:5E:7D:0C:57  &lt;br /&gt;
          inet addr:172.16.3.15  Bcast:172.31.255.255  Mask:255.240.0.0&lt;br /&gt;
          UP BROADCAST RUNNING MULTICAST  MTU:9000  Metric:1&lt;br /&gt;
          RX packets:880 errors:0 dropped:0 overruns:0 frame:0&lt;br /&gt;
          TX packets:1009 errors:0 dropped:0 overruns:0 carrier:0&lt;br /&gt;
          collisions:0 txqueuelen:1000 &lt;br /&gt;
          RX bytes:3878545 (3.6 Mb)  TX bytes:151458 (147.9 Kb)&lt;br /&gt;
          Interrupt:32 &lt;br /&gt;
Zepto ION startup-00 done&lt;br /&gt;
                                                                      done&lt;br /&gt;
Starting syslog servicesDec 31 18:00:36 ion-15 syslogd 1.4.1: restart.&lt;br /&gt;
                                                                      done&lt;br /&gt;
Starting network time protocol daemon (NTPD) using 172.17.3.1&lt;br /&gt;
May  1 12:57:11 ion-15 ntpdate[642]: step time server 172.17.3.1 offset 1241200617.470271 sec&lt;br /&gt;
May  1 12:57:11 ion-15 ntpd[653]: ntpd 4.2.0a@1.1196-r Sat Oct  4 00:01:53 UTC 2008 (1)&lt;br /&gt;
May  1 12:57:11 ion-15 ntpd[653]: precision = 1.000 usec&lt;br /&gt;
May  1 12:57:11 ion-15 ntpd[653]: Listening on interface wildcard, 0.0.0.0#123&lt;br /&gt;
May  1 12:57:11 ion-15 ntpd[653]: Listening on interface eth0, 172.16.3.15#123&lt;br /&gt;
May  1 12:57:11 ion-15 ntpd[653]: Listening on interface lo, 127.0.0.1#123&lt;br /&gt;
May  1 12:57:11 ion-15 ntpd[653]: kernel time sync status 0040&lt;br /&gt;
                                                                      done&lt;br /&gt;
Enabling ssh&lt;br /&gt;
Mounting site filesystems&lt;br /&gt;
                                                                      done&lt;br /&gt;
Loading PVFS2 kernel module                                           done&lt;br /&gt;
Sleeping 0 seconds before starting PVFS                               done&lt;br /&gt;
Starting PVFS2 client                                                 done&lt;br /&gt;
Sleeping 10 seconds before mounting PVFS&lt;br /&gt;
                                                                      done&lt;br /&gt;
Mounting PVFS2 filesystems                                            done&lt;br /&gt;
Starting SSH daemonMay  1 12:57:21 ion-15 sshd[833]: Server listening on 0.0.0.0 port 22.&lt;br /&gt;
                                                                      done&lt;br /&gt;
Zepto ION startup-12&lt;br /&gt;
Zepto ION startup-12 done&lt;br /&gt;
Starting GPFS&lt;br /&gt;
May  1 12:57:26 ion-15 syslogd 1.4.1: restart.&lt;br /&gt;
/etc/init.d/rc3.d/S40gpfs: GPFS is ready on I/O node ion-15 : 172.16.3.15 : R00-M1-N12-J00&lt;br /&gt;
ln: creating symbolic link `/home/acherryl/acherryl' to `/gpfs/home/acherryl': File exists&lt;br /&gt;
ln: creating symbolic link `/home/bgpadmin/bgpadmin' to `/gpfs/home/bgpadmin': File exists&lt;br /&gt;
ln: creating symbolic link `/home/davidr/davidr' to `/gpfs/home/davidr': File exists&lt;br /&gt;
ln: creating symbolic link `/home/scullinl/scullinl' to `/gpfs/home/scullinl': File exists&lt;br /&gt;
Starting ZOID...&lt;br /&gt;
                                                                      done&lt;br /&gt;
Zepto ION startup-99&lt;br /&gt;
Zepto ION startup-99 done&lt;br /&gt;
May  1 17:57:59 ion-15 init: Starting pid 2823, console /dev/console: '/bin/sh'&lt;br /&gt;
BusyBox v1.4.2 (2008-10-04 00:02:35 UTC) Built-in shell (ash)&lt;br /&gt;
Enter 'help' for a list of built-in commands.&lt;br /&gt;
/bin/sh: can't access tty; job control turned off&lt;br /&gt;
~ # &lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
(again, we stripped the prefixes to make the lines shorter)&lt;br /&gt;
&lt;br /&gt;
Messages such as &amp;lt;tt&amp;gt;Zepto ION startup&amp;lt;/tt&amp;gt; or &amp;lt;tt&amp;gt;Starting ZOID&amp;lt;/tt&amp;gt; clearly indicate that a ZeptoOS I/O node ramdisk is being used.  If one instead mistakenly booted with the default ramdisk, this could be recognized by messages such as:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
Starting CIO services&lt;br /&gt;
[ciod:initialized]                                                    done&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
(&amp;lt;tt&amp;gt;ciod&amp;lt;/tt&amp;gt; is ''never'' started when using Zepto Compute Node Linux)&lt;br /&gt;
&lt;br /&gt;
In addition to verifying the ramdisk, the correct I/O node kernel can also be verified using the I/O node logfile by checking the kernel build timestamp in the first line of the boot log.  As of this writing the default kernel on the Argonne machines has a timestamp of &amp;lt;tt&amp;gt;Wed Oct 29 18:51:19 UTC 2008&amp;lt;/tt&amp;gt;; as can be seen above, the ZeptoOS kernel was built more recently.&lt;br /&gt;
&lt;br /&gt;
===Compute node===&lt;br /&gt;
&lt;br /&gt;
All the compute nodes on the machine share the same MMCS log file, located in &amp;lt;tt&amp;gt;/bgsys/logs/BGP/&amp;lt;/tt&amp;gt;.  The name of the log file is not fixed (it contains a timestamp), but &amp;lt;tt&amp;gt;sn1-bgdb0-mmcs_db_server-current.log&amp;lt;/tt&amp;gt; always links to the current file.  Because the file is shared with other jobs, we recommed to grep it for user name, partition name, or both.&lt;br /&gt;
&lt;br /&gt;
A correct boot log when when booting ZeptoOS will look something like this:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
iskra:ANL-R00-M1-N12-64 {20}.0: Common Node Services V1R3M0 (efix:0)&lt;br /&gt;
iskra:ANL-R00-M1-N12-64 {20}.0: Licensed Machine Code - Property of IBM.&lt;br /&gt;
iskra:ANL-R00-M1-N12-64 {20}.0: Blue Gene/P Licensed Machine Code.&lt;br /&gt;
iskra:ANL-R00-M1-N12-64 {20}.0: Copyright IBM Corp., 2006, 2007 All Rights Reserved.&lt;br /&gt;
iskra:ANL-R00-M1-N12-64 {20}.0: Z: Zepto Linux Kernel relocating CNS... dst=80280000 src=fff40000 size=262144&lt;br /&gt;
iskra:ANL-R00-M1-N12-64 {20}.0: Z: CNS is successfully relocated to 00280000 in physical memory&lt;br /&gt;
iskra:ANL-R00-M1-N12-64 {20}.0: Linux version 2.6.19.2-g66cbca2d (kazutomo@login1) (gcc version 4.1.2 (BGP)) #12 SMP Tue Apr 21 12:58:11 CDT 2009&lt;br /&gt;
iskra:ANL-R00-M1-N12-64 {20}.0: Zone PFN ranges:&lt;br /&gt;
iskra:ANL-R00-M1-N12-64 {20}.0:   DMA             0 -&amp;gt;    28672&lt;br /&gt;
iskra:ANL-R00-M1-N12-64 {20}.0:   Normal      28672 -&amp;gt;    28672&lt;br /&gt;
iskra:ANL-R00-M1-N12-64 {20}.0: early_node_map[1] active PFN ranges&lt;br /&gt;
iskra:ANL-R00-M1-N12-64 {20}.1:     0:        0 -&amp;gt;    28672&lt;br /&gt;
iskra:ANL-R00-M1-N12-64 {20}.1: Built 1 zonelists.  Total pages: 28658&lt;br /&gt;
iskra:ANL-R00-M1-N12-64 {20}.1: Kernel command line: console=bgcons root=/dev/ram0 lpj=8500000&lt;br /&gt;
iskra:ANL-R00-M1-N12-64 {20}.1: PID hash table entries: 4096 (order: 12, 16384 bytes)&lt;br /&gt;
iskra:ANL-R00-M1-N12-64 {20}.0: Dentry cache hash table entries: 262144 (order: 4, 1048576 bytes)&lt;br /&gt;
iskra:ANL-R00-M1-N12-64 {20}.0: Inode-cache hash table entries: 131072 (order: 3, 524288 bytes)&lt;br /&gt;
iskra:ANL-R00-M1-N12-64 {20}.0: Memory: 1826560k available (1408k kernel code, 832k data, 192k init, 0k highmem)&lt;br /&gt;
iskra:ANL-R00-M1-N12-64 {20}.0: Calibrating delay loop (skipped)... 1700.00 BogoMIPS preset&lt;br /&gt;
iskra:ANL-R00-M1-N12-64 {20}.0: Mount-cache hash table entries: 8192&lt;br /&gt;
iskra:ANL-R00-M1-N12-64 {20}.0: CPU 1 done callin...&lt;br /&gt;
iskra:ANL-R00-M1-N12-64 {20}.0: CPU 1 done setup...&lt;br /&gt;
iskra:ANL-R00-M1-N12-64 {20}.0: CPU 1 done timebase take...&lt;br /&gt;
iskra:ANL-R00-M1-N12-64 {20}.0: Processor 1 found.&lt;br /&gt;
iskra:ANL-R00-M1-N12-64 {20}.0: CPU 2 done callin...&lt;br /&gt;
iskra:ANL-R00-M1-N12-64 {20}.0: CPU 2 done setup...&lt;br /&gt;
iskra:ANL-R00-M1-N12-64 {20}.0: CPU 2 done timebase take...&lt;br /&gt;
iskra:ANL-R00-M1-N12-64 {20}.0: Processor 2 found.&lt;br /&gt;
iskra:ANL-R00-M1-N12-64 {20}.0: CPU 3 done callin...&lt;br /&gt;
iskra:ANL-R00-M1-N12-64 {20}.0: CPU 3 done setup...&lt;br /&gt;
iskra:ANL-R00-M1-N12-64 {20}.0: CPU 3 done timebase take...&lt;br /&gt;
iskra:ANL-R00-M1-N12-64 {20}.0: Processor 3 found.&lt;br /&gt;
iskra:ANL-R00-M1-N12-64 {20}.0: Brought up 4 CPUs&lt;br /&gt;
iskra:ANL-R00-M1-N12-64 {20}.0: migration_cost=0&lt;br /&gt;
iskra:ANL-R00-M1-N12-64 {20}.0: checking if image is initramfs... it is&lt;br /&gt;
iskra:ANL-R00-M1-N12-64 {20}.0: Freeing initrd memory: 2575k freed&lt;br /&gt;
iskra:ANL-R00-M1-N12-64 {20}.0: NET: Registered protocol family 16&lt;br /&gt;
iskra:ANL-R00-M1-N12-64 {20}.0: NET: Registered protocol family 2&lt;br /&gt;
iskra:ANL-R00-M1-N12-64 {20}.0: IP route cache hash table entries: 16384 (order: 0, 65536 bytes)&lt;br /&gt;
iskra:ANL-R00-M1-N12-64 {20}.0: TCP established hash table entries: 65536 (order: 3, 524288 bytes)&lt;br /&gt;
iskra:ANL-R00-M1-N12-64 {20}.0: TCP bind hash table entries: 32768 (order: 2, 262144 bytes)&lt;br /&gt;
iskra:ANL-R00-M1-N12-64 {20}.0: TCP: Hash tables configured (established 65536 bind 32768)&lt;br /&gt;
iskra:ANL-R00-M1-N12-64 {20}.0: TCP reno registered&lt;br /&gt;
iskra:ANL-R00-M1-N12-64 {20}.0: fuse init (API version 7.7)&lt;br /&gt;
iskra:ANL-R00-M1-N12-64 {20}.0: io scheduler noop registered (default)&lt;br /&gt;
iskra:ANL-R00-M1-N12-64 {20}.0: RAMDISK driver initialized: 16 RAM disks of 32768K size 1024 blocksize&lt;br /&gt;
iskra:ANL-R00-M1-N12-64 {20}.0: tun: Universal TUN/TAP device driver, 1.6&lt;br /&gt;
iskra:ANL-R00-M1-N12-64 {20}.0: tun: (C) 1999-2004 Max Krasnyansky &amp;lt;maxk@qualcomm.com&amp;gt;&lt;br /&gt;
iskra:ANL-R00-M1-N12-64 {20}.0: TCP cubic registered&lt;br /&gt;
iskra:ANL-R00-M1-N12-64 {20}.0: NET: Registered protocol family 1&lt;br /&gt;
iskra:ANL-R00-M1-N12-64 {20}.0: NET: Registered protocol family 17&lt;br /&gt;
iskra:ANL-R00-M1-N12-64 {20}.0: NET: Registered protocol family 15&lt;br /&gt;
iskra:ANL-R00-M1-N12-64 {20}.0: Freeing unused kernel memory: 192k init&lt;br /&gt;
iskra:ANL-R00-M1-N12-64 {20}.0: init started: BusyBox(for ZeptoOS Compute Node) v1.12.1 (2009-04-21 16:08:55 CDT)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This is very easy to tell from a boot log of the default light-weight kernel, which will consist of the first four lines ''only''.&lt;br /&gt;
&lt;br /&gt;
The MMCS log file contains other useful information besides the boot log of the compute nodes.  Before the kernel starts booting, the following messages related to the newly submitted job can be found there:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
DBBlockCmd  DatabaseBlockCommandThread started: block ANL-R00-M1-N12-64, user iskra, action 1&lt;br /&gt;
DBBlockCmd  setusername iskra &lt;br /&gt;
iskra       db_allocate ANL-R00-M1-N12-64 &lt;br /&gt;
iskra       DBConsoleController::setAllocating() ANL-R00-M1-N12-64&lt;br /&gt;
iskra       block state C&lt;br /&gt;
iskra       DBConsoleController::addBlock(ANL-R00-M1-N12-64)&lt;br /&gt;
iskra:ANL-R00-M1-N12-64     BlockController::connect()&lt;br /&gt;
iskra:ANL-R00-M1-N12-64     connecting to mcServer at 127.0.0.1:1206&lt;br /&gt;
    Connected to MCServer as iskra@sn1. Client version 3. Server version 3 on fd 101&lt;br /&gt;
iskra:ANL-R00-M1-N12-64     connected to mcServer&lt;br /&gt;
iskra:ANL-R00-M1-N12-64     mcServer target set ANL-R00-M1-N12-64 created&lt;br /&gt;
iskra:ANL-R00-M1-N12-64     mcServer target set ANL-R00-M1-N12-64 opened&lt;br /&gt;
iskra:ANL-R00-M1-N12-64     {0} I/O log file: /bgsys/logs/BGP/R00-M1-N12-J00.log&lt;br /&gt;
iskra:ANL-R00-M1-N12-64     MailboxListener starting&lt;br /&gt;
iskra:ANL-R00-M1-N12-64     DBConsoleController::doneAllocating() ANL-R00-M1-N12-64&lt;br /&gt;
iskra:ANL-R00-M1-N12-64     BlockController::boot_block \&lt;br /&gt;
uloader=/bgsys/argonne-utils/partitions/ANL-R00-M1-N12-64/uloader \&lt;br /&gt;
cnload=/bgsys/argonne-utils/partitions/ANL-R00-M1-N12-64/CNS,/bgsys/argonne-utils/partitions/ANL-R00-M1-N12-64/CNK \&lt;br /&gt;
ioload=/bgsys/argonne-utils/partitions/ANL-R00-M1-N12-64/CNS,/bgsys/argonne-utils/partitions/ANL-R00-M1-N12-64/INK,/bgsys/argonne-utils/partitions/ANL-R00-M1-N12-64/ramdisk &lt;br /&gt;
iskra:ANL-R00-M1-N12-64     boot_block cookie: 587867023 compute_nodes: 64 io_nodes: 1&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Of particular relevance is the pathname to the I/O node log file(s) (if it cannot be easily guessed from the partition name) and the pathnames to the kernels and ramdisks used to boot the partition.&lt;br /&gt;
&lt;br /&gt;
After the kernel boot log, the log file will also contain information about subsequent phases of starting a job:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
iskra:ANL-R00-M1-N12-64     I/O node initialized: R00-M1-N12-J00&lt;br /&gt;
iskra:ANL-R00-M1-N12-64     DBBlockController::waitBoot(ANL-R00-M1-N12-64) block initialization successful&lt;br /&gt;
iskra       DatabaseBlockCommandThread stopped&lt;br /&gt;
DBJobCmd    DatabaseJobCommandThread started: job 98461, user iskra, action 1&lt;br /&gt;
DBJobCmd    setusername iskra &lt;br /&gt;
iskra       Starting Job 98461&lt;br /&gt;
    New thread 4398305505840, for jobid 98461&lt;br /&gt;
    selectBlock(): ANL-R00-M1-N12-64        iskra(1)        connected state: I owner: iskra&lt;br /&gt;
ANL-R00-M1-N12-64   Jobid is 98461, homedir is /gpfs/home/iskra&lt;br /&gt;
ANL-R00-M1-N12-64   persist: 1&lt;br /&gt;
ANL-R00-M1-N12-64   connecting to mpirun...&lt;br /&gt;
ANL-R00-M1-N12-64   setting mpirun stream, fd=386&lt;br /&gt;
ANL-R00-M1-N12-64   contacting control node 0 at 172.16.3.15:7000&lt;br /&gt;
ANL-R00-M1-N12-64   connected to control node 0 at 172.16.3.15:7000&lt;br /&gt;
ANL-R00-M1-N12-64   Job::load() /bin/sleep &lt;br /&gt;
ANL-R00-M1-N12-64   Job loaded: 98461&lt;br /&gt;
ANL-R00-M1-N12-64   About to start /bin/sleep&lt;br /&gt;
ANL-R00-M1-N12-64   Job 98461 set to RUNNING&lt;br /&gt;
iskra:ANL-R00-M1-N12-64     {20}.0: floating point used in kernel (task=8080cfe0, pc=80017064)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Interactive login==&lt;br /&gt;
&lt;br /&gt;
We are assuming at this point that launching &amp;lt;tt&amp;gt;/bin/sleep&amp;lt;/tt&amp;gt; has been successful and that the &amp;quot;job&amp;quot; is running.  We can now start an interactive session on our BG/P resources.  Probably the most complicated part of this operation is finding the IP address of the I/O node(s).  The allocation of I/O nodes to partitions is fixed, so on a small machine one could simply make a list.  This information is also available in the log files discussed above.&lt;br /&gt;
&lt;br /&gt;
The IP address is printed near the top of the I/O node boot log, as part of the interface configuration of the Ethernet device:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
eth0      Link encap:Ethernet  HWaddr 00:14:5E:7D:0C:57  &lt;br /&gt;
          inet addr:172.16.3.15  Bcast:172.31.255.255  Mask:255.240.0.0&lt;br /&gt;
          UP BROADCAST RUNNING MULTICAST  MTU:9000  Metric:1&lt;br /&gt;
          RX packets:880 errors:0 dropped:0 overruns:0 frame:0&lt;br /&gt;
          TX packets:1009 errors:0 dropped:0 overruns:0 carrier:0&lt;br /&gt;
          collisions:0 txqueuelen:1000 &lt;br /&gt;
          RX bytes:3878545 (3.6 Mb)  TX bytes:151458 (147.9 Kb)&lt;br /&gt;
          Interrupt:32&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
In this case, the address is &amp;lt;tt&amp;gt;172.16.3.15&amp;lt;/tt&amp;gt; (the &amp;lt;tt&amp;gt;inet addr&amp;lt;/tt&amp;gt; value).&lt;br /&gt;
&lt;br /&gt;
The IP address is also available from the MMCS log file:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
ANL-R00-M1-N12-64   contacting control node 0 at 172.16.3.15:7000&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
With larger partitions that include multiple I/O nodes, querying the MMCS logfile is probably better, as it will list all the addresses.&lt;br /&gt;
&lt;br /&gt;
Once the IP address is known, one can simply use the SSH:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
iskra@login1.surveyor:~&amp;gt; ssh 172.16.3.15&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
BusyBox v1.4.2 (2008-10-04 00:02:35 UTC) Built-in shell (ash)&lt;br /&gt;
Enter 'help' for a list of built-in commands.&lt;br /&gt;
&lt;br /&gt;
/gpfs/home/iskra $ hostname&lt;br /&gt;
ion-15&lt;br /&gt;
/gpfs/home/iskra $ &lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
If everything is configured correctly, SSH will only let in root and the partition owner; no other unprivileged user will be allowed on the node.  However, this might require site-specific customization to work properly.  To enable access for the partition owner, one might need to make adjustments to [[ZOID#The /bin.rd/update_passwd_file.sh file|update_passwd_file.sh]].  To enable password-less login for the partition owners without requiring them to set up personal SSH keypairs, we recommend to add the names of the front end nodes to the &amp;lt;tt&amp;gt;shosts.equiv&amp;lt;/tt&amp;gt; file, found in &amp;lt;tt&amp;gt;ramdisk/ION/ramdisk-add/etc/ssh.zepto/&amp;lt;/tt&amp;gt; (it is empty by default; remember to use the names from the network that interconnects front end and I/O nodes, which might be different from hostnames, e.g., at Argonne we need to add the &amp;lt;tt&amp;gt;-data&amp;lt;/tt&amp;gt; suffix to the hostnames).  Until this has all been set up, one might prefer to log on as root (&amp;lt;tt&amp;gt;ssh -l root&amp;lt;/tt&amp;gt;), passing the password provided while [[Configuration#Building|building]] the ZeptoOS environment.&lt;br /&gt;
&lt;br /&gt;
Also, even when the partition owner is correctly set up, there will be a time window while booting the I/O node when the SSH daemon is already running, but a job has not yet been started; during that window, the partition owner cannot log on. If that happens, wait a few seconds and try again.&lt;br /&gt;
&lt;br /&gt;
Here's part of the &amp;lt;tt&amp;gt;ps&amp;lt;/tt&amp;gt; output from the I/O node:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
/gpfs/home/iskra $ ps -ef&lt;br /&gt;
UID        PID  PPID  C STIME TTY          TIME CMD&lt;br /&gt;
[...]&lt;br /&gt;
65534       98     1  0 16:09 ?        00:00:00 /sbin/portmap&lt;br /&gt;
root       108    19  0 16:09 ?        00:00:00 [rpciod/0]&lt;br /&gt;
root       109    19  0 16:09 ?        00:00:00 [rpciod/1]&lt;br /&gt;
root       110    19  0 16:09 ?        00:00:00 [rpciod/2]&lt;br /&gt;
root       111    19  0 16:09 ?        00:00:00 [rpciod/3]&lt;br /&gt;
root       570     1  0 16:09 ?        00:00:00 /sbin/syslogd&lt;br /&gt;
root       577     1  0 16:09 ?        00:00:00 /sbin/klogd -c 1 -x -x&lt;br /&gt;
ntp        653     1  0 16:09 ?        00:00:00 /usr/sbin/ntpd -p /var/run/ntpd.&lt;br /&gt;
root       688     1  0 16:09 ?        00:00:00 [lockd]&lt;br /&gt;
root       775     1  0 16:09 ?        00:00:00 /bgsys/iosoft/pvfs2/sbin/pvfs2-c&lt;br /&gt;
root       776   775  0 16:09 ?        00:00:00 pvfs2-client-core --child -a 5 -&lt;br /&gt;
root       833     1  0 16:10 ?        00:00:00 /usr/sbin/sshd -o PidFile=/var/r&lt;br /&gt;
root      1016     1  0 16:10 ?        00:00:00 /bin/ksh /usr/lpp/mmfs/bin/runmm&lt;br /&gt;
root      1079     1  0 16:10 ?        00:00:00 [nfsWatchKproc]&lt;br /&gt;
root      1080     1  0 16:10 ?        00:00:00 [gpfsSwapdKproc]&lt;br /&gt;
root      1146  1016  0 16:10 ?        00:00:01 /usr/lpp/mmfs/bin//mmfsd&lt;br /&gt;
root      1153     1  0 16:10 ?        00:00:00 [mmkproc]&lt;br /&gt;
root      1152     1  0 16:10 ?        00:00:00 [mmkproc]&lt;br /&gt;
root      1154     1  0 16:10 ?        00:00:00 [mmkproc]&lt;br /&gt;
iskra     2810     1 98 16:10 ?        00:04:09 /bin.rd/zoid -a 8 -m unix_impl.s&lt;br /&gt;
root      2823     1  0 16:10 ?        00:00:00 /bin/sh&lt;br /&gt;
root      3328   833  0 16:10 ?        00:00:00 sshd: iskra [priv]             &lt;br /&gt;
iskra     3332  3328  0 16:10 ?        00:00:00 sshd: iskra@ttyp0              &lt;br /&gt;
iskra     3333  3332  0 16:10 ttyp0    00:00:00 -sh&lt;br /&gt;
iskra     3346  3333  0 16:14 ttyp0    00:00:00 ps -ef&lt;br /&gt;
/gpfs/home/iskra $ &lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The I/O nodes run a small Linux setup with the root filesystem in the ramdisk.  Custom processes can be started, just like on any ordinary Linux node.  In the example above, it is mostly a few system daemons and the remote filesystem clients (GPFS, PVFS).  Please verify at this stage that the remote filesystem have been mounted correctly.&lt;br /&gt;
&lt;br /&gt;
One custom process running on the node is [[ZOID]], the I/O forwarding and job control daemon, which enables the communication with the compute nodes.  One of the facilities offered by ZOID is IP forwarding between the I/O node and the compute nodes, implemented using the virtual network tunneling device available in Linux:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
/gpfs/home/iskra $ ifconfig tun0&lt;br /&gt;
tun0      Link encap:UNSPEC  HWaddr 00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00  &lt;br /&gt;
          inet addr:192.168.1.254  P-t-P:192.168.1.254  Mask:255.255.255.255&lt;br /&gt;
          UP POINTOPOINT RUNNING NOARP MULTICAST  MTU:65535  Metric:1&lt;br /&gt;
          RX packets:0 errors:0 dropped:0 overruns:0 frame:0&lt;br /&gt;
          TX packets:0 errors:0 dropped:0 overruns:0 carrier:0&lt;br /&gt;
          collisions:0 txqueuelen:500 &lt;br /&gt;
          RX bytes:0 (0.0 b)  TX bytes:0 (0.0 b)&lt;br /&gt;
/gpfs/home/iskra $ &lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
At least on Argonne machines, with a 64:1 ratio of compute nodes to I/O nodes, compute nodes have addresses &amp;lt;tt&amp;gt;192.168.1.1&amp;lt;/tt&amp;gt; to &amp;lt;tt&amp;gt;192.168.1.64&amp;lt;/tt&amp;gt; (the last octet of the address is the [[FAQ#Pset rank|pset rank]]).  Somewhat confusingly, the first compute node (compute node &amp;lt;tt&amp;gt;0&amp;lt;/tt&amp;gt;) has IP address &amp;lt;tt&amp;gt;192.168.1.64&amp;lt;/tt&amp;gt;, so if one submits a one-node job as we did, that is the IP address that needs to be used to log on that sole running compute node.  The IP address of the second compute node is... &amp;lt;tt&amp;gt;192.168.1.59&amp;lt;/tt&amp;gt; (do not blame us &amp;amp;#8211; blame IBM&amp;amp;nbsp;:-).&lt;br /&gt;
&lt;br /&gt;
The compute nodes are running a &amp;lt;tt&amp;gt;telnet&amp;lt;/tt&amp;gt; daemon, and no password is required to log on them:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
/gpfs/home/iskra $ telnet 192.168.1.64&lt;br /&gt;
&lt;br /&gt;
Entering character mode&lt;br /&gt;
Escape character is '^]'.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
BusyBox(for ZeptoOS Compute Node) v1.12.1 (2009-04-21 16:08:55 CDT) built-in shell (ash)&lt;br /&gt;
Enter 'help' for a list of built-in commands.&lt;br /&gt;
&lt;br /&gt;
~ # &lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The IP address of the I/O node on this virtual network is &amp;lt;tt&amp;gt;192.168.1.254&amp;lt;/tt&amp;gt;. The network is local to each I/O node, so for larger jobs, there will be multiple distinct virtual networks that cannot communicate with each other, and the IP addresses will duplicate.&lt;br /&gt;
&lt;br /&gt;
Here's part of the &amp;lt;tt&amp;gt;ps&amp;lt;/tt&amp;gt; output from the compute node:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
~ # ps -ef&lt;br /&gt;
  PID USER       VSZ STAT COMMAND&lt;br /&gt;
[...]&lt;br /&gt;
   34 root      5440 S    /bin/sh /etc/init.d/rc.sysinit &lt;br /&gt;
   44 root      5504 S    /sbin/telnetd -l /bin/sh &lt;br /&gt;
   47 root      6528 S    /sbin/inetd &lt;br /&gt;
   48 root     46400 R N  /sbin/control &lt;br /&gt;
   62 root      7872 S    /bin/zoid-fuse -o allow_other -s /fuse &lt;br /&gt;
  116 root      5248 S    /bin/sleep 3600 &lt;br /&gt;
  118 root      5504 S    /bin/sh &lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Compute nodes have an even more stripped-down environment than the I/O nodes.  There are no user accounts &amp;amp;#8211; everything runs as root, including the application processes.  This is not a security concern, because the only practical way for a compute node to communicate with the outside world is through the I/O node, and I/O nodes ''do'' enforce user-level access control.&lt;br /&gt;
&lt;br /&gt;
There are two custom processes running on each compute node:&lt;br /&gt;
&lt;br /&gt;
'''control''' is a job management daemon responsible for tasks such as the launching of application processes, for the forwarding of stdin/out/err data, and for the management of the virtual network tunneling device from the compute node side.  Do not interfere with this process in any way; this would likely make the node inaccessible.&lt;br /&gt;
&lt;br /&gt;
'''zoid-fuse''' is a FUSE ([http://fuse.sourceforge.net/ Filesystem in Userspace]) client responsible for making the filesystems from the I/O nodes available to ordinary POSIX-compliant processes running on the compute nodes.  The whole filesystem namespace from the I/O nodes is made available on the compute nodes under &amp;lt;tt&amp;gt;/fuse/&amp;lt;/tt&amp;gt;, and symbolic links such as &amp;lt;tt&amp;gt;/home -&amp;gt; /fuse/home&amp;lt;/tt&amp;gt; are set up to keep the login and I/O node pathnames valid on the compute nodes.  Please verify that this is correctly set up.  We do not foresee a need to change this setup, but should that prove necessary, the responsbile &amp;lt;tt&amp;gt;fuse-start&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;fuse-stop&amp;lt;/tt&amp;gt; scripts can be found under &amp;lt;tt&amp;gt;ramdisk/CN/tree/bin&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
==Shell script job==&lt;br /&gt;
&lt;br /&gt;
Assuming that the above steps have been successful, one can now test running a simple job from a network filesystem, such as one's home directory.&lt;br /&gt;
&lt;br /&gt;
Here is a sample shell script to try:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
#!/bin/sh&lt;br /&gt;
&lt;br /&gt;
. /proc/personality.sh&lt;br /&gt;
&lt;br /&gt;
while true; do&lt;br /&gt;
    echo &amp;quot;Node $BG_RANK_IN_PSET running (stdout)&amp;quot;&lt;br /&gt;
    echo &amp;quot;Node $BG_RANK_IN_PSET running (stderr)&amp;quot; 1&amp;gt;&amp;amp;2&lt;br /&gt;
    sleep 10&lt;br /&gt;
done&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
(please see the [[FAQ#Pset rank|FAQ]] for the explanation of &amp;lt;tt&amp;gt;/proc/personality.sh&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;BG_RANK_IN_PSET&amp;lt;/tt&amp;gt;)&lt;br /&gt;
&lt;br /&gt;
Please create the script file on the network filesystem, set the executable bit (&amp;lt;tt&amp;gt;chmod 755&amp;lt;/tt&amp;gt;) and submit it.  Verify that the script starts correctly and that at least the standard error output is visible immediately.  The scripts print a line of output from each node every ten seconds.  It does so both to the standard output and to the standard error, because, depending on software configuration, the standard output stream could be buffered.  If that is the case, kill the job and verify that the standard output data did appear.&lt;br /&gt;
&lt;br /&gt;
==MPI and OpenMP jobs==&lt;br /&gt;
&lt;br /&gt;
The final tests involve parallel programming jobs, respectively MPI and OpenMP.  Use the test programs provided with the distribution. From the top level directory:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
$ cd comm/testcodes&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Compiling===&lt;br /&gt;
&lt;br /&gt;
The programs can be compiled on a login node using:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
$ /path/to/install/bin/zmpicc -o mpi-test-linux mpi-test.c&lt;br /&gt;
$ /path/to/install/bin/zmpixlc_r -qsmp=omp -o omp-test-linux omp-test.c&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Submitting===&lt;br /&gt;
&lt;br /&gt;
Submit the MPI test like any other job; use one of the below:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
$ cqsub -k &amp;lt;profile-name&amp;gt; -t &amp;lt;time&amp;gt; -n &amp;lt;number-of-processes&amp;gt; $PWD/mpi-test-linux&lt;br /&gt;
$ qsub --kernel &amp;lt;profile-name&amp;gt; -t &amp;lt;time&amp;gt; -n &amp;lt;number-of-processes&amp;gt;  $PWD/mpi-test-linux&lt;br /&gt;
$ mpirun -verbose 1 -partition &amp;lt;partition-name&amp;gt; -np &amp;lt;number-of-processes&amp;gt; -timeout &amp;lt;time&amp;gt; \&lt;br /&gt;
-cwd $PWD -exe $PWD/omp-test-linux&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
For the OpenMP test, we pass the number of OpenMP threads to use in the &amp;lt;tt&amp;gt;OMP_NUM_THREADS&amp;lt;/tt&amp;gt; variable:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
$ cqsub -k &amp;lt;profile-name&amp;gt; -t &amp;lt;time&amp;gt; -n 1 -e OMP_NUM_THREADS=&amp;lt;num&amp;gt; $PWD/omp-test-linux&lt;br /&gt;
$ qsub --kernel &amp;lt;profile-name&amp;gt; -t &amp;lt;time&amp;gt; -n 1 --env OMP_NUM_THREADS=&amp;lt;num&amp;gt; $PWD/mpi-test-linux&lt;br /&gt;
$ mpirun -verbose 1 -partition &amp;lt;partition-name&amp;gt; -np 1 -timeout &amp;lt;time&amp;gt; \&lt;br /&gt;
-cwd $PWD -env OMP_NUM_THREADS=&amp;lt;num&amp;gt; -exe $PWD/omp-test-linux&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The MPI test benchmarks the performance of various MPI operations.  The OpenMP test is just a parallel &amp;quot;Hello world&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
[[Installation]] | [[ZeptoOS_Documentation|Top]] | [[MPICH, DCMF, and SPI]]&lt;/div&gt;</summary>
		<author><name>Iskra</name></author>
	</entry>
	<entry>
		<id> /zeptoos/index.php?title=Kernel&amp;diff=568</id>
		<title>Kernel</title>
		<link rel="alternate" type="text/html" href=" /zeptoos/index.php?title=Kernel&amp;diff=568"/>
		<updated>2009-05-07T18:24:57Z</updated>

		<summary type="html">&lt;p&gt;Iskra: /* Kernel (command line) parameters */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;[[MPICH, DCMF, and SPI]] | [[ZeptoOS_Documentation|Top]] | [[Ramdisk]]&lt;br /&gt;
----&lt;br /&gt;
&lt;br /&gt;
==Introduction==&lt;br /&gt;
&lt;br /&gt;
We currently provide two Linux kernels because of GPFS support on ION.&lt;br /&gt;
&lt;br /&gt;
* 2.6.19-based kernel: ZeptoOS CN kernel&lt;br /&gt;
** IBM V1R3 patch and ZeptoOS patch applied&lt;br /&gt;
** 64&amp;amp;nbsp;KB pagesize and big memory region available&lt;br /&gt;
** Device drivers for compute node devices such as DMA, lockbox, etc&lt;br /&gt;
** Allows to run MPICH/DCMF code through Zepto Compute Binary (ZCB)&lt;br /&gt;
** Can be used as enhanced ION kernel&lt;br /&gt;
&lt;br /&gt;
* 2.6.16-based kernel: ZeptoOS ION kernel&lt;br /&gt;
** IBM V1R3 patch applied&lt;br /&gt;
** Only minor changes compared to the IBM ION kernel.&lt;br /&gt;
&lt;br /&gt;
We focus our development efforts on the 2.6.19-based kernel.  It is meant primarily for the compute nodes, but can also be used on the I/O nodes.  The problem is that GPFS does not work with this kernel, so we also provide the 2.6.16-based kernel which works with GPFS.&lt;br /&gt;
&lt;br /&gt;
==Kernel directory structure==&lt;br /&gt;
&lt;br /&gt;
The &amp;lt;tt&amp;gt;kernel&amp;lt;/tt&amp;gt; directory basically consists of three main subdirectories: &amp;lt;tt&amp;gt;prebuilt&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;config&amp;lt;/tt&amp;gt;, and &amp;lt;tt&amp;gt;tarball&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
kernel&lt;br /&gt;
|-- prebuilt&lt;br /&gt;
|   |-- 2.6.16&lt;br /&gt;
|   |   `-- ION&lt;br /&gt;
|   `-- 2.6.19&lt;br /&gt;
|       |-- CN&lt;br /&gt;
|       `-- objs&lt;br /&gt;
|-- tarball&lt;br /&gt;
`-- config&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The &amp;lt;tt&amp;gt;prebuilt&amp;lt;/tt&amp;gt; directory contains prebuilt kernel images and modules. While a complete prebuilt ION kernel ELF file is provided, for the CN kernel we provide intermediate object files instead.  This is because we embed the CN ramdisk in the CN kernel image when building ZeptoOS, and this process requires the object files.&lt;br /&gt;
&lt;br /&gt;
The &amp;lt;tt&amp;gt;tarball&amp;lt;/tt&amp;gt; directory contains kernel tarballs separately for the ION and the CN Linux kernel. Technically, those tarballs are a snapshot of the ZeptoOS kernel git repository. The directory might contain a &amp;lt;tt&amp;gt;.patch&amp;lt;/tt&amp;gt; file that contains the differences between the last snapshot and the current git HEAD since we wanted to avoid creating a snapshot from git for small modifications. Associated git log file can also be found in this directory. A &amp;lt;tt&amp;gt;.SNAPSHOT_HEAD&amp;lt;/tt&amp;gt; file indicates the git revision at the time when a snapshot was created, so this information is used to create a patch file.&lt;br /&gt;
&lt;br /&gt;
Here is a list of files for the CN kernel:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
linux-2.6.19.2-BGP-V1R3.git.log&lt;br /&gt;
linux-2.6.19.2-BGP-V1R3.patch&lt;br /&gt;
linux-2.6.19.2-BGP-V1R3.SNAPSHOT_HEAD&lt;br /&gt;
linux-2.6.19.2-BGP-V1R3.tar.bz2&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The &amp;lt;tt&amp;gt;config&amp;lt;/tt&amp;gt; directory contains Linux kernel configs.  In case of the 2.6.19 kernel, we provide separate config files for the compute node and the I/O node.&lt;br /&gt;
&lt;br /&gt;
==Building a kernel==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;Makefile&amp;lt;/tt&amp;gt; in the &amp;lt;tt&amp;gt;kernel&amp;lt;/tt&amp;gt; directory has many options. Just type &amp;lt;tt&amp;gt;make&amp;lt;/tt&amp;gt; and it will print out a help message. &lt;br /&gt;
&lt;br /&gt;
If one needs to build (or rebuild) a kernel from the source tarball, use &amp;lt;tt&amp;gt;bgp-ion-linux-build&amp;lt;/tt&amp;gt; or &amp;lt;tt&amp;gt;bgp-cn-linux-build&amp;lt;/tt&amp;gt; target. By default, it extracts ION or CN kernel tarball in a directory named &amp;lt;tt&amp;gt;work&amp;lt;/tt&amp;gt;, applies a patch if any and starts the kernel build. Once the kernel has successfully been built, kernel images (in both ZeptoOS top-level directory and the &amp;lt;tt&amp;gt;tmp&amp;lt;/tt&amp;gt; directory) will be replaced with newly built images. The ION kernel source code is extracted into &amp;lt;tt&amp;gt;work/linux-2.6.16.46-297-BGP-V1R3&amp;lt;/tt&amp;gt; and the CN kernel source into &amp;lt;tt&amp;gt;work/linux-2.6.19.2-BGP-V1R3&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Here is an example of building and rebuilding the CN kernel:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
$ cd kernel&lt;br /&gt;
$ make bgp-cn-linux-build&lt;br /&gt;
....&lt;br /&gt;
$ ls -al ../BGP-CN-zImage-with-initrd.elf&lt;br /&gt;
$ vi work/linux-2.6.19.2-BGP-V1R3/kernel/sched.c&lt;br /&gt;
$ make bgp-cn-linux-build&lt;br /&gt;
....&lt;br /&gt;
$ ls -al ../BGP-CN-zImage-with-initrd.elf&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Building a kernel from the ZeptoOS kernel git repository===&lt;br /&gt;
&lt;br /&gt;
As mentioned earlier, the kernel tarball is used as the source by default.  If instead one passes &amp;lt;tt&amp;gt;GIT=1&amp;lt;/tt&amp;gt; to &amp;lt;tt&amp;gt;make&amp;lt;/tt&amp;gt;, one can build directly from the ZeptoOS kernel git tree. This is very useful for kernel development since it makes it easier to keep track of local modifications. &lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
$ cd kernel&lt;br /&gt;
$ make GIT=1 bgp-cn-linux-build&lt;br /&gt;
....&lt;br /&gt;
$ vi repo/linux-2.6.19.2-BGP-V1R3/kernel/sched.c&lt;br /&gt;
$ make GIT=1 bgp-cn-linux-build&lt;br /&gt;
....&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This will create &amp;lt;tt&amp;gt;repo/linux-2.6.19.2-BGP-V1R3&amp;lt;/tt&amp;gt;, which is a git repository that is cloned from http://git.anl-external.org/bg-linux.repos/linux-2.6.19-BGP-V1R3.git/. Our http repo is read-only, so you cannot push your modifications to it. Instead, please post any patches to the [mailto:zeptoos@lists.mcs.anl.gov ZeptoOS mailing list] instead. &lt;br /&gt;
&lt;br /&gt;
See also the [http://bg-linux.anl-external.org/wiki/index.php/Main_Page BG-Linux page] for the details on our kernel git repository.&lt;br /&gt;
&lt;br /&gt;
===Kernel config===&lt;br /&gt;
&lt;br /&gt;
When one invokes &amp;lt;tt&amp;gt;make&amp;lt;/tt&amp;gt; with a kernel build target for the first time, the associated kernel config file is copied to &amp;lt;tt&amp;gt;.config&amp;lt;/tt&amp;gt; in the kernel build directory.  &amp;lt;tt&amp;gt;config/bgp-cn-2.6.19.2-dot-config&amp;lt;/tt&amp;gt; is applied to the CN Linux kernel build tree, and &amp;lt;tt&amp;gt;config/bgp-ion-2.6.16.46-dot-config&amp;lt;/tt&amp;gt; is applied to the ION Linux kernel build tree.&lt;br /&gt;
&lt;br /&gt;
Here is the location of the kernel config file:&lt;br /&gt;
* Regular build&lt;br /&gt;
** work/build-2.6.19.2-BGP-V1R3/.config&lt;br /&gt;
** work/build-2.6.16.46-297-BGP-V1R3/.config&lt;br /&gt;
* GIT build&lt;br /&gt;
** repo/build-2.6.19.2-BGP-V1R3/.config&lt;br /&gt;
** repo/build-2.6.16.46-297-BGP-V1R3/.config&lt;br /&gt;
&lt;br /&gt;
Please note that the kernel config file is copied only once, until you do a &amp;lt;tt&amp;gt;distclean&amp;lt;/tt&amp;gt; or remove the files manually.&lt;br /&gt;
&lt;br /&gt;
The &amp;lt;tt&amp;gt;bgp-cn-linux-menuconfig&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;bgp-ion-linux-menuconfig&amp;lt;/tt&amp;gt; &amp;lt;tt&amp;gt;make&amp;lt;/tt&amp;gt; targets invoke text-based Linux kernel configuration menus:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
$ make bgp-ion-linux-menuconfig&lt;br /&gt;
$ make bgp-cn-linux-menuconfig&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
For GIT build:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
$ make GIT=1 bgp-ion-linux-menuconfig&lt;br /&gt;
$ make GIT=1 bgp-cn-linux-menuconfig&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
These menu targets never update the default kernel config files from the &amp;lt;tt&amp;gt;config&amp;lt;/tt&amp;gt; directory.  If you want to apply a new config permanently, please copy it to the &amp;lt;tt&amp;gt;config&amp;lt;/tt&amp;gt; directory by hand:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
$ cp work/build-2.6.19.2-BGP-V1R3/.config  config/bgp-cn-2.6.19.2-dot-config&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Kernel (command line) parameters==&lt;br /&gt;
&lt;br /&gt;
In common server/desktop Linux environments, kernel parameters can be passed via bootloader such as grub. However, Blue Gene/P boot mechanism does not provide such capability, so we have modified the CN Linux kernel (2.6.19) to use a kernel parameter string embedded in kernel ELF image file itself.&lt;br /&gt;
&lt;br /&gt;
One can (re)set the kernel parameters in a kernel ELF file using a command line tool &amp;lt;tt&amp;gt;zkparam.py&amp;lt;/tt&amp;gt;, located in the &amp;lt;tt&amp;gt;bin&amp;lt;tt&amp;gt; subdirectory of the ZeptoOS installation directory.  Here is the synopsis of the tool:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
zkparam.py &amp;lt;kernel_image&amp;gt; [options]&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
If options are omitted, the tool shows the current kernel parameters.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
$ ./kernel/zkparam.py  BGP-CN-zImage-with-initrd.elf  zepto_console_output=2&lt;br /&gt;
$ ./kernel/zkparam.py  BGP-CN-zImage-with-initrd.elf &lt;br /&gt;
Current Kernel Parameters:&lt;br /&gt;
 zepto_console_output=2&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===ZeptoOS-pecific kernel parameters===&lt;br /&gt;
&lt;br /&gt;
* '''zepto_debug'''=&amp;lt;integer&amp;gt;&lt;br /&gt;
** Specifies the ZeptoOS kernel debug level.&lt;br /&gt;
** The higher the number, the more messages are generated.&lt;br /&gt;
** &amp;lt;tt&amp;gt;0&amp;lt;/tt&amp;gt; turns off all debug messages.&lt;br /&gt;
** default=1&lt;br /&gt;
* '''flatmemsizeMB'''=&amp;lt;integer&amp;gt;&lt;br /&gt;
** Specifies the size of big memory in MB.&lt;br /&gt;
** Currently the granularity of memory size is 256&amp;amp;nbsp;MB.&lt;br /&gt;
** default=256  min=256  max=1792&lt;br /&gt;
* '''zepto_console_output'''=&amp;lt;integer&amp;gt;&lt;br /&gt;
** Specifies the console output behavior. &lt;br /&gt;
** 0 disables console output from all compute nodes.&lt;br /&gt;
** 1 enables console output from the first compute node ([[FAQ#Torus rank|torus rank]] 0).&lt;br /&gt;
** 2 enables console output from all compute nodes.&lt;br /&gt;
&lt;br /&gt;
==Log files, etc==&lt;br /&gt;
&amp;lt;!--&lt;br /&gt;
===Compute Node log===&lt;br /&gt;
&lt;br /&gt;
Debug messages from compute node (i.e, via printk) will appear in one of system log files.&lt;br /&gt;
The system log file is recreated every time at system reset. You can find the location of the system log file&lt;br /&gt;
by typing the following command. &lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
$ ls -1 /bgsys/logs/BGP/sn*-mmcs_db_server*.log|tail -1&lt;br /&gt;
/bgsys/logs/BGP/sn1-mmcs_db_server-2009-0209-11:58:20.log&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Please also take a look at a convenient script BGP/packages/tools/cn-log.sh&lt;br /&gt;
&lt;br /&gt;
===ION Node log===&lt;br /&gt;
&lt;br /&gt;
Debug message from ION node will appear in ION node log files in /bgsys/logs/BGP/,&lt;br /&gt;
/bgsys/logs/BGP/R00-M0-N00-J00.log for example.&lt;br /&gt;
Each ION has own log file. ION to CN ratio is 1:64 in ANL system. If your job is a 64 (physical) nodes job,&lt;br /&gt;
you have one ION log file. &lt;br /&gt;
&lt;br /&gt;
Please also take a look at a convenient script BGP/packages/tools/ion-log.sh&lt;br /&gt;
&lt;br /&gt;
===RAS events===&lt;br /&gt;
--&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The compute node and I/O node logfile have been discussed extensively in [[Testing#Log files|Testing]].&lt;br /&gt;
&lt;br /&gt;
In addition to regular console logs, the kernels can also generate RAS message, which will not appear in the log files. A command line tool named &amp;lt;tt&amp;gt;bg-listevents&amp;lt;/tt&amp;gt; shows you a record of RAS events. Type &amp;lt;tt&amp;gt;bg-listevents -h&amp;lt;/tt&amp;gt; for command line arguments.&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
[[MPICH, DCMF, and SPI]] | [[ZeptoOS_Documentation|Top]] | [[Ramdisk]]&lt;/div&gt;</summary>
		<author><name>Iskra</name></author>
	</entry>
	<entry>
		<id> /zeptoos/index.php?title=Configuration&amp;diff=567</id>
		<title>Configuration</title>
		<link rel="alternate" type="text/html" href=" /zeptoos/index.php?title=Configuration&amp;diff=567"/>
		<updated>2009-05-07T17:53:35Z</updated>

		<summary type="html">&lt;p&gt;Iskra: /* Configuring */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;[[Introduction]] | [[ZeptoOS_Documentation|Top]] | [[Installation]]&lt;br /&gt;
----&lt;br /&gt;
&lt;br /&gt;
== Downloading ==&lt;br /&gt;
&lt;br /&gt;
* Log on one of the frontend nodes of the Blue Gene (a login node or a service node).&lt;br /&gt;
&lt;br /&gt;
* Download the ZeptoOS tarball from the ZeptoOS [http://press.mcs.anl.gov/zeptoos/download download page].&lt;br /&gt;
&lt;br /&gt;
* Extract the sources from the package:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
$ tar xjf ZeptoOS-*.tar.bz2&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Configuring ==&lt;br /&gt;
&lt;br /&gt;
Change to the top-level &amp;lt;tt&amp;gt;ZeptoOS-&amp;lt;version&amp;gt;&amp;lt;/tt&amp;gt; directory:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
$ cd ZeptoOS-&amp;lt;version&amp;gt;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
A &amp;lt;tt&amp;gt;configure&amp;lt;/tt&amp;gt; script is provided to set the pathnames to various system directories.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
$ ./configure&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
If invoked without any arguments, it will use the defaults, which should be appropriate if ZeptoOS is configured on a system with a supported BG/P driver version.  The pathnames can be changed with the help of a user interface by invoking the script as follows:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
$ ./configure --edit&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This will display the following menu:&lt;br /&gt;
&lt;br /&gt;
[[Image:Configure1.png|border|Main menu]]&lt;br /&gt;
&lt;br /&gt;
Please select the top item (&amp;lt;tt&amp;gt;BG/P DIST_DIR&amp;lt;/tt&amp;gt;).  The screen will change to:&lt;br /&gt;
&lt;br /&gt;
[[Image:Configure2.png|border|DIST_DIR menu]]&lt;br /&gt;
&lt;br /&gt;
The following options are available:&lt;br /&gt;
&lt;br /&gt;
; DRV_DIR&lt;br /&gt;
: The directory with the BG/P driver tree.  The default (&amp;lt;tt&amp;gt;/bgsys/drivers/ppcfloor/&amp;lt;/tt&amp;gt;) is a link pointing to the currently active driver.&lt;br /&gt;
; BGP_CROSS&lt;br /&gt;
: A prefix to the pathnames of the GNU cross-compilers used to build the compute node and I/O node software.&lt;br /&gt;
; BGCNS_H_PATH and BGCNS_H&lt;br /&gt;
: The location of a file needed to rebuild the kernel (these options are temporary and will be removed in the next version).&lt;br /&gt;
; OS_DIR&lt;br /&gt;
: The directory with the supplementary I/O node software used when booting the I/O nodes.  It needs to be set to match the BG/P driver version being used.&lt;br /&gt;
&lt;br /&gt;
The second top-level menu (&amp;lt;tt&amp;gt;Debugging&amp;lt;/tt&amp;gt;) has only one option:&lt;br /&gt;
&lt;br /&gt;
; ADD_DEBUG_TOOLS&lt;br /&gt;
: Check this option to include &amp;lt;tt&amp;gt;gdb&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;strace&amp;lt;/tt&amp;gt; in the compute node ramdisk.  They are not included by default because of their size.&lt;br /&gt;
&lt;br /&gt;
The third top-level menu (&amp;lt;tt&amp;gt;Kernel Profiling&amp;lt;/tt&amp;gt;) is discussed in the [[(K)TAU#Configure ZeptoOS to point to KTAU patch and path|(K)TAU section]]&lt;br /&gt;
&lt;br /&gt;
Select &amp;lt;tt&amp;gt;Exit&amp;lt;/tt&amp;gt; (multiple times if needed) and confirm if you want to save any changes made.&lt;br /&gt;
&lt;br /&gt;
== Building ==&lt;br /&gt;
&lt;br /&gt;
To start using the pre-built binaries simply type:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
$ make&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
On the first invocation, this will ask for a root password to use on I/O nodes:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
Create root password for I/O Node&lt;br /&gt;
   Leave the password field empty if you want to disable root login&lt;br /&gt;
   New password:&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
'''Security note: root-level access to I/O nodes should only be given to trusted individuals.  A root user can access and modify files of all users in the system.'''&lt;br /&gt;
&lt;br /&gt;
Once a password has been entered and confirmed, &amp;lt;tt&amp;gt;make&amp;lt;/tt&amp;gt; will use pre-built kernel images, and will build the ramdisks from pre-built tools and utilities.  The following generated files will be placed in the top-level directory:&lt;br /&gt;
&lt;br /&gt;
; BGP-CN-zImage-with-initrd.elf&lt;br /&gt;
: A merged ZeptoOS compute node Linux and compute node ramdisk file.&lt;br /&gt;
; BGP-ION-ramdisk-for-CNL.elf&lt;br /&gt;
: ZeptoOS I/O node ramdisk for use with the ZeptoOS compute node Linux.&lt;br /&gt;
; BGP-ION-ramdisk-for-CNK.elf&lt;br /&gt;
: ZeptoOS I/O node ramdisk for use with the IBM CNK (optional).&lt;br /&gt;
; BGP-ION-zImage.elf&lt;br /&gt;
: ZeptoOS I/O node kernel.&lt;br /&gt;
&lt;br /&gt;
It is possible to rebuild individual ZeptoOS components using one of the following &amp;lt;tt&amp;gt;make&amp;lt;/tt&amp;gt; targets (the list is also available by typing &amp;lt;tt&amp;gt;make help&amp;lt;/tt&amp;gt; or &amp;lt;tt&amp;gt;make menu&amp;lt;/tt&amp;gt;):&lt;br /&gt;
&lt;br /&gt;
; bgp-ion-ramdisk-cnk&lt;br /&gt;
: Rebuilds the I/O node ramdisk for the IBM CNK.&lt;br /&gt;
; bgp-ion-ramdisk-cnl&lt;br /&gt;
: Rebuilds the I/O node ramdisk for the ZeptoOS compute node Linux.&lt;br /&gt;
; bgp-cn-linux&lt;br /&gt;
: Rebuilds the compute node ramdisk and embeds it into a compute node kernel image.&lt;br /&gt;
; bgp-ion-linux-build&lt;br /&gt;
: Rebuilds the I/O node kernel.&lt;br /&gt;
; bgp-cn-linux-build&lt;br /&gt;
: Rebuilds the compute node kernel and ramdisk and merges them.&lt;br /&gt;
; bgp-all-pkg-rebuild&lt;br /&gt;
: Rebuilds all packages from sources.&lt;br /&gt;
(the following &amp;lt;tt&amp;gt;make&amp;lt;/tt&amp;gt;targets are mostly for internal use)&lt;br /&gt;
; bgp-ion-linux&lt;br /&gt;
: Copies a recently rebuilt I/O node kernel if one is available; otherwise, uses a prebuilt binary (will not rebuild the kernel).&lt;br /&gt;
; bgp-all-pkg-smart&lt;br /&gt;
: Copies recently rebuilt packages if available; otherwise, uses prebuilt binaries (used when preparing to rebuild ramdisks).&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
[[Introduction]] | [[ZeptoOS_Documentation|Top]] | [[Installation]]&lt;/div&gt;</summary>
		<author><name>Iskra</name></author>
	</entry>
	<entry>
		<id> /zeptoos/index.php?title=Ramdisk&amp;diff=566</id>
		<title>Ramdisk</title>
		<link rel="alternate" type="text/html" href=" /zeptoos/index.php?title=Ramdisk&amp;diff=566"/>
		<updated>2009-05-07T17:50:33Z</updated>

		<summary type="html">&lt;p&gt;Iskra: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;[[Kernel]] | [[ZeptoOS_Documentation|Top]] | [[ZOID]]&lt;br /&gt;
----&lt;br /&gt;
&lt;br /&gt;
==Introduction==&lt;br /&gt;
&lt;br /&gt;
Both the CN and ION Linux kernels require a ramdisk to boot.  Ramdisk images contain minimal Linux utilities, init scripts, configuration files, kernel modules, etc, which are required by the OS boot process.&lt;br /&gt;
&lt;br /&gt;
ION ramdisk is an ELF file that contains a cpio archive of system files. Two ION ramdisk images are currently generated:&lt;br /&gt;
&lt;br /&gt;
; BGP-ION-ramdisk-for-CNL.elf&lt;br /&gt;
: Default ION ramdisk for ZeptoOS.&lt;br /&gt;
; BGP-ION-ramdisk-for-CNK.elf &lt;br /&gt;
: Use this one if you need to run IBM CNK on the compute nodes (uses IBM CIOD instead of ZOID)&lt;br /&gt;
&lt;br /&gt;
Our ION ramdisks are similar to the default ION ramdisk from IBM, but we add some extra files to support ZeptoOS features. The extra files are located in &amp;lt;tt&amp;gt;ramdisk/ION/ramdisk-add/&amp;lt;/tt&amp;gt;. The &amp;lt;tt&amp;gt;build-ramdisk&amp;lt;/tt&amp;gt; script from IBM BGP driver is used to create the ION ramdisks.&lt;br /&gt;
&lt;br /&gt;
The CN ramdisk is also a gzip'ed cpio archive of system files, but CN ramdisk is embedded into the CN kernel image (&amp;lt;tt&amp;gt;BGP-CN-zImage-with-initrd.elf&amp;lt;/tt&amp;gt;).  The CN ramdisk is created by a custom ramdisk build script (&amp;lt;tt&amp;gt;ramdisk/CN/create-bgp-cn-linux-ramdisk.pl&amp;lt;/tt&amp;gt;). Both &amp;lt;tt&amp;gt;build-ramdisk&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;create-bgp-cn-linux-ramdisk.pl&amp;lt;/tt&amp;gt; are wrappers of the Linux kernel's &amp;lt;tt&amp;gt;gen_init_cpio&amp;lt;/tt&amp;gt; command.&lt;br /&gt;
&lt;br /&gt;
==Creating ramdisk images==&lt;br /&gt;
&lt;br /&gt;
The ramdisk images are always (re-)created from prebuild objects if one types &amp;lt;tt&amp;gt;make&amp;lt;/tt&amp;gt; at the top level directory (without any make target).&lt;br /&gt;
&lt;br /&gt;
If one wants to create an ION ramdisk individually (without rebuilding other images), type:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
$ make bgp-ion-ramdisk-cnl&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
If one wants to create a CN ramdisk (technically, create a CN kernel image with new ramdisk contents), type:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
$ make bgp-cn-linux&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
'''Note:''' the newly built CN ramdisk can be found in &amp;lt;tt&amp;gt;ramdisk/CN/bgp-cn-ramdisk.cpio.gz&amp;lt;/tt&amp;gt;, but it is not useable until it is embedded into the kernel image.&lt;br /&gt;
&lt;br /&gt;
For other ramdisk-related make targets, please refer to [[Configuration#Building|Configuration]].&lt;br /&gt;
&lt;br /&gt;
==Modifying ramdisk contents==&lt;br /&gt;
&lt;br /&gt;
You can customize ramdisk contents for your purpose, i.e., debugging, running your custom system software on BGP, etc.&lt;br /&gt;
&lt;br /&gt;
===CN ramdisk===&lt;br /&gt;
&lt;br /&gt;
The CN ramdisk can be customized by editing the CN ramdisk build script, which is &amp;lt;tt&amp;gt;ramdisk/CN/create-bgp-cn-linux-ramdisk.pl&amp;lt;/tt&amp;gt;.  The build script allows to set the permission bits, create device files, etc.&lt;br /&gt;
&lt;br /&gt;
Most of the contents of the CN ramdisk is kept in &amp;lt;tt&amp;gt;ramdisk/CN/tree/&amp;lt;tt&amp;gt;, but this is not a hard rule.  Source files can reside anywhere as long as they are accessible from the script. It may be possible to use binaries and libraries from the login nodes, as long as they are a 32-bit PPC files (use the &amp;lt;tt&amp;gt;file&amp;lt;/tt&amp;gt; command to verify) and all their dependencies are also copied.&lt;br /&gt;
&lt;br /&gt;
Here is a practical example. Suppose that you need the &amp;lt;tt&amp;gt;od&amp;lt;/tt&amp;gt; command in CN ramdisk.  You could build the command from source code, but if you want to do something quick, you can try using the login node's version:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
$ file /usr/bin/od&lt;br /&gt;
/usr/bin/od: ELF 32-bit MSB executable, PowerPC or cisco 4500, version 1 (SYSV),&lt;br /&gt;
for GNU/Linux 2.6.4, dynamically linked (uses shared libs), for GNU/Linux 2.6.4, stripped&lt;br /&gt;
$ ldd /usr/bin/od&lt;br /&gt;
linux-vdso32.so.1 =&amp;gt;  (0x00100000)&lt;br /&gt;
libc.so.6 =&amp;gt; /lib/ppc970/libc.so.6 (0x0fe8b000)&lt;br /&gt;
/lib/ld.so.1 (0xf7fe1000)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
It is a 32-bit PPC executable and the current CN ramdisk has all the necessary shared libraries, so it can be used.  Now add the command to a perl array named &amp;lt;tt&amp;gt;@cmdlists&amp;lt;/tt&amp;gt; in &amp;lt;tt&amp;gt;ramdisk/CN/create-bgp-cn-linux-ramdisk.pl&amp;lt;/tt&amp;gt; script and type &amp;lt;tt&amp;gt;make&amp;lt;/tt&amp;gt; to recreate the CN ramdisk:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
$ vi ramdisk/CN/create-bgp-cn-linux-ramdisk.pl&lt;br /&gt;
# add the following line to @cmdlists &lt;br /&gt;
     &amp;quot;file /bin/od   /usr/bin/od 0755  0  0&amp;quot;,&lt;br /&gt;
$ make bgp-cn-linux&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Now the CN ramdisk has &amp;lt;tt&amp;gt;/bin/od&amp;lt;/tt&amp;gt; with file permissions &amp;lt;tt&amp;gt;0755&amp;lt;/tt&amp;gt;, uid=0, and gid=0.&lt;br /&gt;
&lt;br /&gt;
The added line is a command for the &amp;lt;tt&amp;gt;gen_init_cpio&amp;lt;/tt&amp;gt; tool. One can also create directories, device files, symbolick links, pipe files, socket files, etc:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
file &amp;lt;name&amp;gt; &amp;lt;location&amp;gt; &amp;lt;mode&amp;gt; &amp;lt;uid&amp;gt; &amp;lt;gid&amp;gt;&lt;br /&gt;
dir &amp;lt;name&amp;gt; &amp;lt;mode&amp;gt; &amp;lt;uid&amp;gt; &amp;lt;gid&amp;gt;&lt;br /&gt;
nod &amp;lt;name&amp;gt; &amp;lt;mode&amp;gt; &amp;lt;uid&amp;gt; &amp;lt;gid&amp;gt; &amp;lt;dev_type&amp;gt; &amp;lt;maj&amp;gt; &amp;lt;min&amp;gt;&lt;br /&gt;
slink &amp;lt;name&amp;gt; &amp;lt;target&amp;gt; &amp;lt;mode&amp;gt; &amp;lt;uid&amp;gt; &amp;lt;gid&amp;gt;&lt;br /&gt;
pipe &amp;lt;name&amp;gt; &amp;lt;mode&amp;gt; &amp;lt;uid&amp;gt; &amp;lt;gid&amp;gt;&lt;br /&gt;
sock &amp;lt;name&amp;gt; &amp;lt;mode&amp;gt; &amp;lt;uid&amp;gt; &amp;lt;gid&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;name&amp;gt;      name of the file/dir/nod/etc in the archive&lt;br /&gt;
&amp;lt;location&amp;gt;  location of the file in the current filesystem&lt;br /&gt;
&amp;lt;target&amp;gt;    link target&lt;br /&gt;
&amp;lt;mode&amp;gt;      mode/permissions of the file&lt;br /&gt;
&amp;lt;uid&amp;gt;       user id (0=root)&lt;br /&gt;
&amp;lt;gid&amp;gt;       group id (0=root)&lt;br /&gt;
&amp;lt;dev_type&amp;gt;  device type (b=block, c=character)&lt;br /&gt;
&amp;lt;maj&amp;gt;       major number of nod&lt;br /&gt;
&amp;lt;min&amp;gt;       minor number of nod&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The order of the commands in @cmdlists ''matters''.  They are executed from top to bottom, so one cannot add a file to a directory that has not yet been created.&lt;br /&gt;
&lt;br /&gt;
====CN Linux startup script====&lt;br /&gt;
&lt;br /&gt;
The first thing that the Linux kernel does after it boots is to execute the &amp;lt;tt&amp;gt;init&amp;lt;/tt&amp;gt; program.  The &amp;lt;tt&amp;gt;init&amp;lt;/tt&amp;gt; program is usually in &amp;lt;tt&amp;gt;/sbin/&amp;lt;/tt&amp;gt;, and in the CN ramdisk case it is part of the busybox. &amp;lt;tt&amp;gt;init&amp;lt;/tt&amp;gt; reads in a config file from &amp;lt;tt&amp;gt;/etc/inittab&amp;lt;/tt&amp;gt;, which in our case instructs it to execute the &amp;lt;tt&amp;gt;/etc/init.d/rc.sysinit&amp;lt;/tt&amp;gt; startup script.&lt;br /&gt;
&lt;br /&gt;
Our startup script is very minimalistic; its two most important actions are to start the telnet daemon to allow users to login from the I/O nodes and then to start the ZOID &amp;lt;tt&amp;gt;control&amp;lt;/tt&amp;gt; process which takes care of IP forwarding and job control.&lt;br /&gt;
&lt;br /&gt;
In case you need to start some processes at the CN boot time, you can add their invocations to &amp;lt;tt&amp;gt;ramdisk/CN/tree/etc/init.d/rc.sysinit&amp;lt;/tt&amp;gt;, ''before'' &amp;lt;tt&amp;gt;/sbin/control&amp;lt;/tt&amp;gt; is invoked.&lt;br /&gt;
&lt;br /&gt;
===ION ramdisk===&lt;br /&gt;
&lt;br /&gt;
Unlike the CN ramdisk, the range of customization is limited on the ION ramdisk. There is no control over file permission bits, one cannot create device nodes, etc. Currently we build the ION ramdisk using IBM's &amp;lt;tt&amp;gt;build-ramdisk&amp;lt;/tt&amp;gt; script by specifying an add-on tree which contains our extra files.&lt;br /&gt;
&lt;br /&gt;
Essentially, customization is limited to:&lt;br /&gt;
* adding new files,&lt;br /&gt;
* overwriting default ramdisk files by adding custom files with the same names.&lt;br /&gt;
&lt;br /&gt;
Once files have been added under &amp;lt;tt&amp;gt;ramdisk/ION/ramdisk-add/&amp;lt;/tt&amp;gt;, they will be automatically added to the ramdisk on the next rebuild.  Here is an example of how to add a file to the ION ramdisk:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
$ vi ramdisk/ION/ramdisk-add/etc/yourfile&lt;br /&gt;
$ make bgp-ion-ramdisk-cnl&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
If you need more than file adding, you might need to edit the &amp;lt;tt&amp;gt;build-ramdisk&amp;lt;/tt&amp;gt; script itself. The script is located in &amp;lt;tt&amp;gt;/bgsys/drivers/ppcfloor/&amp;lt;/tt&amp;gt;. Copy the script to a working directory, edit it and change the script path in &amp;lt;tt&amp;gt;ramdisk/ION/Makefile&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
====ION startup script====&lt;br /&gt;
&lt;br /&gt;
There is no &amp;lt;tt&amp;gt;rc.sysinit&amp;lt;/tt&amp;gt; in &amp;lt;tt&amp;gt;ramdisk/ION/ramdisk-add/&amp;lt;/tt&amp;gt;, because &amp;lt;tt&amp;gt;rc.sysinit&amp;lt;/tt&amp;gt; is provided in the IBM ramdisk tree (i.e., &amp;lt;tt&amp;gt;/bgsys/drivers/ppcfloor/ramdisk/etc/init.d/rc.sysinit&amp;lt;/tt&amp;gt; is default one).  If needed, one can copy the default one to the ZeptoOS &amp;lt;tt&amp;gt;ramdisk/etc/init.d/rc.sysinit&amp;lt;/tt&amp;gt; and modify it to change the startup behaviour, but this is in general not recommended.&lt;br /&gt;
&lt;br /&gt;
In most cases, what one is looking for is to start a process at the ION boot time.  For such purpose, one can add a custom ION RC script to &amp;lt;tt&amp;gt;ramdisk-add/etc/init.d/rc3.d/&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
RC scripts have the following naming convention:&lt;br /&gt;
&lt;br /&gt;
* S##xxxx : boot-time scripts&lt;br /&gt;
* K##xxxx : shut-down scripts&lt;br /&gt;
&lt;br /&gt;
They start with &amp;lt;tt&amp;gt;S&amp;lt;/tt&amp;gt; or &amp;lt;tt&amp;gt;K&amp;lt;/tt&amp;gt;; those starting with &amp;lt;tt&amp;gt;S&amp;lt;/tt&amp;gt; are the boot-time scripts and those starting with &amp;lt;tt&amp;gt;K&amp;lt;/tt&amp;gt; are the shut-down scripts.  The two-digit number following &amp;lt;tt&amp;gt;S&amp;lt;/tt&amp;gt; or &amp;lt;tt&amp;gt;K&amp;lt;/tt&amp;gt; is used to determine the execution order; scripts with lower numbers are executed earlier. The number is followed by the script name. On execution, &amp;quot;start&amp;quot; is passed as the first argument to boot-time scripts, and &amp;quot;stop&amp;quot; to shut-down scripts.  Here is a template of an RC script:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
#!/bin/sh&lt;br /&gt;
. /etc/rc.status&lt;br /&gt;
&lt;br /&gt;
rc_reset&lt;br /&gt;
case &amp;quot;$1&amp;quot; in&lt;br /&gt;
    start)&lt;br /&gt;
        # fill here #&lt;br /&gt;
        ;;&lt;br /&gt;
    stop)&lt;br /&gt;
        # fill here #&lt;br /&gt;
        ;;&lt;br /&gt;
    restart)&lt;br /&gt;
        # fill here #&lt;br /&gt;
        ;;&lt;br /&gt;
    status)&lt;br /&gt;
        # fill here #&lt;br /&gt;
        ;;&lt;br /&gt;
    *)&lt;br /&gt;
	echo &amp;quot;Usage: $0 {start|stop|restart|status}&amp;quot;&lt;br /&gt;
	exit 1&lt;br /&gt;
	;;&lt;br /&gt;
esac&lt;br /&gt;
rc_exit&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The ZeptoOS ION ramdisk contains the following RC scripts by default (some of these are ZeptoOS-specific, others come from the IBM ramdisk tree):&lt;br /&gt;
&lt;br /&gt;
'''boot''' scripts:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
S00zepto&lt;br /&gt;
S01bootsysctl&lt;br /&gt;
S02syslog&lt;br /&gt;
S05ntp&lt;br /&gt;
S11sshd&lt;br /&gt;
S12zepto&lt;br /&gt;
S40gpfs&lt;br /&gt;
S43ibmcmp&lt;br /&gt;
S46essl&lt;br /&gt;
S50ciod&lt;br /&gt;
S51zoid&lt;br /&gt;
S99zepto&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
'''shutdown''' scripts:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
K05ntp&lt;br /&gt;
K10sshd&lt;br /&gt;
K15ciod&lt;br /&gt;
K20gpfs&lt;br /&gt;
K30syslog&lt;br /&gt;
K50bgsys.64&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Ramdisk size limitation===&lt;br /&gt;
&lt;br /&gt;
In regular Linux environments, ramdisk size is limited by free memory size at the time when ramdisk is loaded into memory. However, on BGP, closed-source system software cannot handle images of arbitrary sizes. We do not have an exact number on the boot image size limitation, but we have seen with the current software stack that images of 100&amp;amp;nbsp;MB or larger might fail to boot. If one adds large files to the ramdisk, please check the size of the generated image files, specifically &amp;lt;tt&amp;gt;BGP-ION-ramdisk-for-CNL.elf&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;BGP-CN-zImage-with-initrd.elf&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
==Extracting files from an existing ramdisk image==&lt;br /&gt;
&lt;br /&gt;
To extract file from an existing ramdisk image, do the following (ION ramdisk only):&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
$ ./packages/tools/z-extract-cpio-from-ramdisk.sh  &amp;lt;existing_ramdisk_image&amp;gt; ramdisk.cpio&lt;br /&gt;
$ mkdir treeroot &amp;amp;&amp;amp; cd treeroot&lt;br /&gt;
$ cpio -idv &amp;lt; ../ramdisk.cpio&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
[[Kernel]] | [[ZeptoOS_Documentation|Top]] | [[ZOID]]&lt;/div&gt;</summary>
		<author><name>Iskra</name></author>
	</entry>
	<entry>
		<id> /zeptoos/index.php?title=Ramdisk&amp;diff=565</id>
		<title>Ramdisk</title>
		<link rel="alternate" type="text/html" href=" /zeptoos/index.php?title=Ramdisk&amp;diff=565"/>
		<updated>2009-05-06T22:07:02Z</updated>

		<summary type="html">&lt;p&gt;Iskra: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;[[Kernel]] | [[ZeptoOS_Documentation|Top]] | [[ZOID]]&lt;br /&gt;
----&lt;br /&gt;
&lt;br /&gt;
==Introduction==&lt;br /&gt;
&lt;br /&gt;
Both the CN and ION Linux kernels require a ramdisk to boot.  Ramdisk images contain minimal Linux utilities, init scripts, configuration files, kernel modules, etc, which are required by the OS boot process.&lt;br /&gt;
&lt;br /&gt;
ION ramdisk is an ELF file that contains a cpio archive of system files. Two ION ramdisk images are currently generated:&lt;br /&gt;
&lt;br /&gt;
; BGP-ION-ramdisk-for-CNL.elf&lt;br /&gt;
: Default ION ramdisk for ZeptoOS.&lt;br /&gt;
; BGP-ION-ramdisk-for-CNK.elf &lt;br /&gt;
: Use this one if you need to run IBM CNK on the compute nodes (uses IBM CIOD instead of ZOID)&lt;br /&gt;
&lt;br /&gt;
Our ION ramdisks are similar to the default ION ramdisk from IBM, but we add some extra files to support ZeptoOS features. The extra files are located in &amp;lt;tt&amp;gt;ramdisk/ION/ramdisk-add/&amp;lt;/tt&amp;gt;. The &amp;lt;tt&amp;gt;build-ramdisk&amp;lt;/tt&amp;gt; script from IBM BGP driver is used to create the ION ramdisks.&lt;br /&gt;
&lt;br /&gt;
The CN ramdisk is also a gzip'ed cpio archive of system files, but CN ramdisk is embedded into the CN kernel image (&amp;lt;tt&amp;gt;BGP-CN-zImage-with-initrd.elf&amp;lt;/tt&amp;gt;).  The CN ramdisk is created by a custom ramdisk build script (&amp;lt;tt&amp;gt;ramdisk/CN/create-bgp-cn-linux-ramdisk.pl&amp;lt;/tt&amp;gt;). Both &amp;lt;tt&amp;gt;build-ramdisk&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;create-bgp-cn-linux-ramdisk.pl&amp;lt;/tt&amp;gt; are wrappers of the Linux kernel's &amp;lt;tt&amp;gt;gen_init_cpio&amp;lt;/tt&amp;gt; command.&lt;br /&gt;
&lt;br /&gt;
==Creating ramdisk images==&lt;br /&gt;
&lt;br /&gt;
The ramdisk images are always (re-)created from prebuild objects if one types &amp;lt;tt&amp;gt;make&amp;lt;/tt&amp;gt; at the top level directory (without any make target).&lt;br /&gt;
&lt;br /&gt;
If one wants to create an ION ramdisk individually (without rebuilding other images), type:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
$ make bgp-ion-ramdisk-cnl&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
If one wants to create a CN ramdisk (technically, create a CN kernel image with new ramdisk contents), type:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
$ make bgp-cn-linux&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
'''Note:''' the newly built CN ramdisk can be found in &amp;lt;tt&amp;gt;ramdisk/CN/bgp-cn-ramdisk.cpio.gz&amp;lt;/tt&amp;gt;, but it is not useable until it is embedded into the kernel image.&lt;br /&gt;
&lt;br /&gt;
For other ramdisk-related make targets, please refer to [[Configuration#Building|Configuration]].&lt;br /&gt;
&lt;br /&gt;
==Modifying ramdisk contents==&lt;br /&gt;
&lt;br /&gt;
You can customize ramdisk contents for your purpose, i.e., debugging, running your custom system software on BGP, etc.&lt;br /&gt;
&lt;br /&gt;
===CN ramdisk===&lt;br /&gt;
&lt;br /&gt;
The CN ramdisk can be customized by editing the CN ramdisk build script, which is &amp;lt;tt&amp;gt;ramdisk/CN/create-bgp-cn-linux-ramdisk.pl&amp;lt;/tt&amp;gt;.  The build script allows to set the permission bits, create device files, etc.&lt;br /&gt;
&lt;br /&gt;
Most of the contents of the CN ramdisk is kept in &amp;lt;tt&amp;gt;ramdisk/CN/tree/&amp;lt;tt&amp;gt;, but this is not a hard rule.  Source files can reside anywhere as long as they are accessible from the script. It may be possible to use binaries and libraries from the login nodes, as long as they are a 32-bit PPC files (use the &amp;lt;tt&amp;gt;file&amp;lt;/tt&amp;gt; command to verify) and all their dependencies are also copied.&lt;br /&gt;
&lt;br /&gt;
Here is a practical example. Suppose that you need the &amp;lt;tt&amp;gt;od&amp;lt;/tt&amp;gt; command in CN ramdisk.  You could build the command from source code, but if you want to do something quick, you can try using the login node's version:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
$ file /usr/bin/od&lt;br /&gt;
/usr/bin/od: ELF 32-bit MSB executable, PowerPC or cisco 4500, version 1 (SYSV),&lt;br /&gt;
for GNU/Linux 2.6.4, dynamically linked (uses shared libs), for GNU/Linux 2.6.4, stripped&lt;br /&gt;
$ ldd /usr/bin/od&lt;br /&gt;
linux-vdso32.so.1 =&amp;gt;  (0x00100000)&lt;br /&gt;
libc.so.6 =&amp;gt; /lib/ppc970/libc.so.6 (0x0fe8b000)&lt;br /&gt;
/lib/ld.so.1 (0xf7fe1000)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
It is a 32-bit PPC executable and the current CN ramdisk has all the necessary shared libraries, so it can be used.  Now add the command to a perl array named &amp;lt;tt&amp;gt;@cmdlists&amp;lt;/tt&amp;gt; in &amp;lt;tt&amp;gt;ramdisk/CN/create-bgp-cn-linux-ramdisk.pl&amp;lt;/tt&amp;gt; script and type &amp;lt;tt&amp;gt;make&amp;lt;/tt&amp;gt; to recreate the CN ramdisk:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
$ vi ramdisk/CN/create-bgp-cn-linux-ramdisk.pl&lt;br /&gt;
# add the following line to @cmdlists &lt;br /&gt;
     &amp;quot;file /bin/od   /usr/bin/od 0755  0  0&amp;quot;,&lt;br /&gt;
$ make bgp-cn-linux&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Now the CN ramdisk has &amp;lt;tt&amp;gt;/bin/od&amp;lt;/tt&amp;gt; with file permissions &amp;lt;tt&amp;gt;0755&amp;lt;/tt&amp;gt;, uid=0, and gid=0.&lt;br /&gt;
&lt;br /&gt;
The added line is a command for the &amp;lt;tt&amp;gt;gen_init_cpio&amp;lt;/tt&amp;gt; tool. One can also create directories, device files, symbolick links, pipe files, socket files, etc:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
file &amp;lt;name&amp;gt; &amp;lt;location&amp;gt; &amp;lt;mode&amp;gt; &amp;lt;uid&amp;gt; &amp;lt;gid&amp;gt;&lt;br /&gt;
dir &amp;lt;name&amp;gt; &amp;lt;mode&amp;gt; &amp;lt;uid&amp;gt; &amp;lt;gid&amp;gt;&lt;br /&gt;
nod &amp;lt;name&amp;gt; &amp;lt;mode&amp;gt; &amp;lt;uid&amp;gt; &amp;lt;gid&amp;gt; &amp;lt;dev_type&amp;gt; &amp;lt;maj&amp;gt; &amp;lt;min&amp;gt;&lt;br /&gt;
slink &amp;lt;name&amp;gt; &amp;lt;target&amp;gt; &amp;lt;mode&amp;gt; &amp;lt;uid&amp;gt; &amp;lt;gid&amp;gt;&lt;br /&gt;
pipe &amp;lt;name&amp;gt; &amp;lt;mode&amp;gt; &amp;lt;uid&amp;gt; &amp;lt;gid&amp;gt;&lt;br /&gt;
sock &amp;lt;name&amp;gt; &amp;lt;mode&amp;gt; &amp;lt;uid&amp;gt; &amp;lt;gid&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;name&amp;gt;      name of the file/dir/nod/etc in the archive&lt;br /&gt;
&amp;lt;location&amp;gt;  location of the file in the current filesystem&lt;br /&gt;
&amp;lt;target&amp;gt;    link target&lt;br /&gt;
&amp;lt;mode&amp;gt;      mode/permissions of the file&lt;br /&gt;
&amp;lt;uid&amp;gt;       user id (0=root)&lt;br /&gt;
&amp;lt;gid&amp;gt;       group id (0=root)&lt;br /&gt;
&amp;lt;dev_type&amp;gt;  device type (b=block, c=character)&lt;br /&gt;
&amp;lt;maj&amp;gt;       major number of nod&lt;br /&gt;
&amp;lt;min&amp;gt;       minor number of nod&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The order of the commands in @cmdlists ''matters''.  They are executed from top to bottom, so one cannot add a file to a directory that has not yet been created.&lt;br /&gt;
&lt;br /&gt;
====CN Linux startup script====&lt;br /&gt;
&lt;br /&gt;
The first thing that the Linux kernel does after it boots is to execute the &amp;lt;tt&amp;gt;init&amp;lt;/tt&amp;gt; program.  The &amp;lt;tt&amp;gt;init&amp;lt;/tt&amp;gt; program is usually in &amp;lt;tt&amp;gt;/sbin/&amp;lt;/tt&amp;gt;, and in the CN ramdisk case it is part of the busybox. &amp;lt;tt&amp;gt;init&amp;lt;/tt&amp;gt; reads in a config file from &amp;lt;tt&amp;gt;/etc/inittab&amp;lt;/tt&amp;gt;, which in our case instructs it to execute the &amp;lt;tt&amp;gt;/etc/init.d/rc.sysinit&amp;lt;/tt&amp;gt; startup script.&lt;br /&gt;
&lt;br /&gt;
Our startup script is very minimalistic; its two most important actions are to start the telnet daemon to allow users to login from the I/O nodes and then to start the ZOID &amp;lt;tt&amp;gt;control&amp;lt;/tt&amp;gt; process which takes care of IP forwarding and job control.&lt;br /&gt;
&lt;br /&gt;
In case you need to start some process at the CN boot time, you can add its invocations to &amp;lt;tt&amp;gt;ramdisk/CN/tree/etc/init.d/rc.sysinit&amp;lt;/tt&amp;gt;, ''before'' &amp;lt;tt&amp;gt;/sbin/control&amp;lt;/tt&amp;gt; is invoked.&lt;br /&gt;
&lt;br /&gt;
===ION ramdisk===&lt;br /&gt;
&lt;br /&gt;
Unlike with the CN ramdisk, the range of customization is limited on the ION ramdisk. There is no control over file permission bits, one cannot create device nodes, etc. Currently we build the ION ramdisk using IBM's &amp;lt;tt&amp;gt;build-ramdisk&amp;lt;/tt&amp;gt; script by specifying an add-on tree which contains our extra files.&lt;br /&gt;
&lt;br /&gt;
What you can do are basically:&lt;br /&gt;
* add files,&lt;br /&gt;
* overwrite default ramdisk files by adding custom files with the same names.&lt;br /&gt;
&lt;br /&gt;
Once files have been added under &amp;lt;tt&amp;gt;ramdisk/ION/ramdisk-add/&amp;lt;/tt&amp;gt;, they will be automatically added to the ramdisk on the next rebuild.  Here is an example of how to add a file to the ION ramdisk:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
$ vi ramdisk/ION/ramdisk-add/etc/yourfile&lt;br /&gt;
$ make bgp-ion-ramdisk-cnl&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
If you need more than file adding, you might need to edit the &amp;lt;tt&amp;gt;build-ramdisk&amp;lt;/tt&amp;gt; script itself. The script is located in &amp;lt;tt&amp;gt;/bgsys/drivers/ppcfloor/&amp;lt;/tt&amp;gt;. Copy the script to your working directory, edit it and change the script path in &amp;lt;tt&amp;gt;ramdisk/ION/Makefile&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
====ION startup script====&lt;br /&gt;
&lt;br /&gt;
There is no rc.sysinit in ramdisk/ION/ramdisk-add/ since &lt;br /&gt;
rc.sysinit is provided from IBM ramdisk tree. &lt;br /&gt;
i.e., /bgsys/drivers/ppcfloor/ramdisk/etc/init.d/rc.sysinit is default one.&lt;br /&gt;
You can copy the default one to ramdisk/etc/init.d/rc.sysinit (local) and modify it &lt;br /&gt;
to change the startup behaviour but it is not recommended. &lt;br /&gt;
&lt;br /&gt;
In most cases, what you need is to start your software at ION boot time. &lt;br /&gt;
For such purpose, you can add your ION RC script to ramdisk-add/etc/init.d/rc3.d&lt;br /&gt;
to do some action.&lt;br /&gt;
&lt;br /&gt;
RC script has own naming convention. &lt;br /&gt;
&lt;br /&gt;
* S##xxxx : boot time scripts&lt;br /&gt;
* K##xxxx : shut down scripts&lt;br /&gt;
&lt;br /&gt;
It starts with S or K. Scritps with S are boot time script and scripts with K are shut down scripts.&lt;br /&gt;
A two-digit number is followed by 'S' or 'K' is used to decide execution order ; &lt;br /&gt;
a smaller number script is executed before a larger number script. Then script name follows. &lt;br /&gt;
The init scripts passes &amp;quot;start&amp;quot; as the 1st argument to boot time scripts when it is executed.  Similarly, &amp;quot;stop&amp;quot; is passed to shut down script.&lt;br /&gt;
If you parse the argument, one rc script can serve as both boot time and shut down script. &lt;br /&gt;
Here is a template of rc script. &lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
#!/bin/sh&lt;br /&gt;
. /etc/rc.status&lt;br /&gt;
&lt;br /&gt;
rc_reset&lt;br /&gt;
case &amp;quot;$1&amp;quot; in&lt;br /&gt;
    start)&lt;br /&gt;
        # fill here #&lt;br /&gt;
        ;;&lt;br /&gt;
    stop)&lt;br /&gt;
        # fill here #&lt;br /&gt;
        ;;&lt;br /&gt;
    restart)&lt;br /&gt;
        # fill here #&lt;br /&gt;
        ;;&lt;br /&gt;
    status)&lt;br /&gt;
        # fill here #&lt;br /&gt;
        ;;&lt;br /&gt;
    *)&lt;br /&gt;
	echo &amp;quot;Usage: $0 {start|stop|restart|status}&amp;quot;&lt;br /&gt;
	exit 1&lt;br /&gt;
	;;&lt;br /&gt;
esac&lt;br /&gt;
rc_exit&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Default Zepto ION ramdisk contains the following rc scripts.&lt;br /&gt;
&lt;br /&gt;
'''boot''' scripts&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
S00zepto&lt;br /&gt;
S01bootsysctl&lt;br /&gt;
S02syslog&lt;br /&gt;
S05ntp&lt;br /&gt;
S11sshd&lt;br /&gt;
S12zepto&lt;br /&gt;
S40gpfs&lt;br /&gt;
S43ibmcmp&lt;br /&gt;
S46essl&lt;br /&gt;
S50ciod&lt;br /&gt;
S51zoid&lt;br /&gt;
S99zepto&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
'''shutdown''' scripts&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
K05ntp&lt;br /&gt;
K10sshd&lt;br /&gt;
K15ciod&lt;br /&gt;
K20gpfs&lt;br /&gt;
K30syslog&lt;br /&gt;
K50bgsys.64&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Ramdisk size limitation===&lt;br /&gt;
&lt;br /&gt;
On regular Linux environment, ramdisk size is &lt;br /&gt;
basically limited by free memory size at the time when ramdisk is loaded into memory.&lt;br /&gt;
However, on BGP, the system software(non-opensource) can not handle bigger image. &lt;br /&gt;
We don't have the exact number on the boot image size limitation &lt;br /&gt;
but 100MB or bigger ramdisk might fail to boot with the current environment.&lt;br /&gt;
If you add bigger files to ramdisk, please make sure the ramdisk file size,&lt;br /&gt;
specifically, BGP-ION-ramdisk-for-CNL.elf and BGP-CN-zImage-with-initrd.elf.&lt;br /&gt;
&lt;br /&gt;
==Extracting files from an existing ramdisk image==&lt;br /&gt;
&lt;br /&gt;
To extract file from an existing ramdisk image, do the following (ION ramdisk only):&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
$ ./packages/tools/z-extract-cpio-from-ramdisk.sh  &amp;lt;existing_ramdisk_image&amp;gt; ramdisk.cpio&lt;br /&gt;
$ mkdir treeroot &amp;amp;&amp;amp; cd treeroot&lt;br /&gt;
$ cpio -idv &amp;lt; ../ramdisk.cpio&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
[[Kernel]] | [[ZeptoOS_Documentation|Top]] | [[ZOID]]&lt;/div&gt;</summary>
		<author><name>Iskra</name></author>
	</entry>
	<entry>
		<id> /zeptoos/index.php?title=Configuration&amp;diff=564</id>
		<title>Configuration</title>
		<link rel="alternate" type="text/html" href=" /zeptoos/index.php?title=Configuration&amp;diff=564"/>
		<updated>2009-05-06T21:32:07Z</updated>

		<summary type="html">&lt;p&gt;Iskra: /* Building */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;[[Introduction]] | [[ZeptoOS_Documentation|Top]] | [[Installation]]&lt;br /&gt;
----&lt;br /&gt;
&lt;br /&gt;
== Downloading ==&lt;br /&gt;
&lt;br /&gt;
* Log on one of the frontend nodes of the Blue Gene (a login node or a service node).&lt;br /&gt;
&lt;br /&gt;
* Download the ZeptoOS tarball from the ZeptoOS [http://press.mcs.anl.gov/zeptoos/download download page].&lt;br /&gt;
&lt;br /&gt;
* Extract the sources from the package:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
$ tar xjf ZeptoOS-*.tar.bz2&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Configuring ==&lt;br /&gt;
&lt;br /&gt;
Change to the top-level &amp;lt;tt&amp;gt;BGP&amp;lt;/tt&amp;gt; directory:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
$ cd BGP/&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
A &amp;lt;tt&amp;gt;configure&amp;lt;/tt&amp;gt; script is provided to set the pathnames to various system directories.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
$ ./configure&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
If invoked without any arguments, it will use the defaults, which should be appropriate if ZeptoOS is configured on a system with a supported BG/P driver version.  The pathnames can be changed with the help of a user interface by invoking the script as follows:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
$ ./configure --edit&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This will display the following menu:&lt;br /&gt;
&lt;br /&gt;
[[Image:Configure1.png|border|Main menu]]&lt;br /&gt;
&lt;br /&gt;
Please select the top item (&amp;lt;tt&amp;gt;BG/P DIST_DIR&amp;lt;/tt&amp;gt;).  The screen will change to:&lt;br /&gt;
&lt;br /&gt;
[[Image:Configure2.png|border|DIST_DIR menu]]&lt;br /&gt;
&lt;br /&gt;
The following options are available:&lt;br /&gt;
&lt;br /&gt;
; DRV_DIR&lt;br /&gt;
: The directory with the BG/P driver tree.  The default (&amp;lt;tt&amp;gt;/bgsys/drivers/ppcfloor/&amp;lt;/tt&amp;gt;) is a link pointing to the currently active driver.&lt;br /&gt;
; BGP_CROSS&lt;br /&gt;
: A prefix to the pathnames of the GNU cross-compilers used to build the compute node and I/O node software.&lt;br /&gt;
; BGCNS_H_PATH and BGCNS_H&lt;br /&gt;
: The location of a file needed to rebuild the kernel (these options are temporary and will be removed in the next version).&lt;br /&gt;
; OS_DIR&lt;br /&gt;
: The directory with the supplementary I/O node software used when booting the I/O nodes.  It needs to be set to match the BG/P driver version being used.&lt;br /&gt;
&lt;br /&gt;
The second top-level menu (&amp;lt;tt&amp;gt;Debugging&amp;lt;/tt&amp;gt;) has only one option:&lt;br /&gt;
&lt;br /&gt;
; ADD_DEBUG_TOOLS&lt;br /&gt;
: Check this option to include &amp;lt;tt&amp;gt;gdb&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;strace&amp;lt;/tt&amp;gt; in the compute node ramdisk.  They are not included by default because of their size.&lt;br /&gt;
&lt;br /&gt;
The third top-level menu (&amp;lt;tt&amp;gt;Kernel Profiling&amp;lt;/tt&amp;gt;) is discussed in the [[(K)TAU#Configure ZeptoOS to point to KTAU patch and path|(K)TAU section]]&lt;br /&gt;
&lt;br /&gt;
Select &amp;lt;tt&amp;gt;Exit&amp;lt;/tt&amp;gt; (multiple times if needed) and confirm if you want to save any changes made.&lt;br /&gt;
&lt;br /&gt;
== Building ==&lt;br /&gt;
&lt;br /&gt;
To start using the pre-built binaries simply type:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
$ make&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
On the first invocation, this will ask for a root password to use on I/O nodes:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
Create root password for I/O Node&lt;br /&gt;
   Leave the password field empty if you want to disable root login&lt;br /&gt;
   New password:&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
'''Security note: root-level access to I/O nodes should only be given to trusted individuals.  A root user can access and modify files of all users in the system.'''&lt;br /&gt;
&lt;br /&gt;
Once a password has been entered and confirmed, &amp;lt;tt&amp;gt;make&amp;lt;/tt&amp;gt; will use pre-built kernel images, and will build the ramdisks from pre-built tools and utilities.  The following generated files will be placed in the top-level directory:&lt;br /&gt;
&lt;br /&gt;
; BGP-CN-zImage-with-initrd.elf&lt;br /&gt;
: A merged ZeptoOS compute node Linux and compute node ramdisk file.&lt;br /&gt;
; BGP-ION-ramdisk-for-CNL.elf&lt;br /&gt;
: ZeptoOS I/O node ramdisk for use with the ZeptoOS compute node Linux.&lt;br /&gt;
; BGP-ION-ramdisk-for-CNK.elf&lt;br /&gt;
: ZeptoOS I/O node ramdisk for use with the IBM CNK (optional).&lt;br /&gt;
; BGP-ION-zImage.elf&lt;br /&gt;
: ZeptoOS I/O node kernel.&lt;br /&gt;
&lt;br /&gt;
It is possible to rebuild individual ZeptoOS components using one of the following &amp;lt;tt&amp;gt;make&amp;lt;/tt&amp;gt; targets (the list is also available by typing &amp;lt;tt&amp;gt;make help&amp;lt;/tt&amp;gt; or &amp;lt;tt&amp;gt;make menu&amp;lt;/tt&amp;gt;):&lt;br /&gt;
&lt;br /&gt;
; bgp-ion-ramdisk-cnk&lt;br /&gt;
: Rebuilds the I/O node ramdisk for the IBM CNK.&lt;br /&gt;
; bgp-ion-ramdisk-cnl&lt;br /&gt;
: Rebuilds the I/O node ramdisk for the ZeptoOS compute node Linux.&lt;br /&gt;
; bgp-cn-linux&lt;br /&gt;
: Rebuilds the compute node ramdisk and embeds it into a compute node kernel image.&lt;br /&gt;
; bgp-ion-linux-build&lt;br /&gt;
: Rebuilds the I/O node kernel.&lt;br /&gt;
; bgp-cn-linux-build&lt;br /&gt;
: Rebuilds the compute node kernel and ramdisk and merges them.&lt;br /&gt;
; bgp-all-pkg-rebuild&lt;br /&gt;
: Rebuilds all packages from sources.&lt;br /&gt;
(the following &amp;lt;tt&amp;gt;make&amp;lt;/tt&amp;gt;targets are mostly for internal use)&lt;br /&gt;
; bgp-ion-linux&lt;br /&gt;
: Copies a recently rebuilt I/O node kernel if one is available; otherwise, uses a prebuilt binary (will not rebuild the kernel).&lt;br /&gt;
; bgp-all-pkg-smart&lt;br /&gt;
: Copies recently rebuilt packages if available; otherwise, uses prebuilt binaries (used when preparing to rebuild ramdisks).&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
[[Introduction]] | [[ZeptoOS_Documentation|Top]] | [[Installation]]&lt;/div&gt;</summary>
		<author><name>Iskra</name></author>
	</entry>
	<entry>
		<id> /zeptoos/index.php?title=Configuration&amp;diff=563</id>
		<title>Configuration</title>
		<link rel="alternate" type="text/html" href=" /zeptoos/index.php?title=Configuration&amp;diff=563"/>
		<updated>2009-05-06T21:15:11Z</updated>

		<summary type="html">&lt;p&gt;Iskra: /* Building */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;[[Introduction]] | [[ZeptoOS_Documentation|Top]] | [[Installation]]&lt;br /&gt;
----&lt;br /&gt;
&lt;br /&gt;
== Downloading ==&lt;br /&gt;
&lt;br /&gt;
* Log on one of the frontend nodes of the Blue Gene (a login node or a service node).&lt;br /&gt;
&lt;br /&gt;
* Download the ZeptoOS tarball from the ZeptoOS [http://press.mcs.anl.gov/zeptoos/download download page].&lt;br /&gt;
&lt;br /&gt;
* Extract the sources from the package:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
$ tar xjf ZeptoOS-*.tar.bz2&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Configuring ==&lt;br /&gt;
&lt;br /&gt;
Change to the top-level &amp;lt;tt&amp;gt;BGP&amp;lt;/tt&amp;gt; directory:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
$ cd BGP/&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
A &amp;lt;tt&amp;gt;configure&amp;lt;/tt&amp;gt; script is provided to set the pathnames to various system directories.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
$ ./configure&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
If invoked without any arguments, it will use the defaults, which should be appropriate if ZeptoOS is configured on a system with a supported BG/P driver version.  The pathnames can be changed with the help of a user interface by invoking the script as follows:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
$ ./configure --edit&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This will display the following menu:&lt;br /&gt;
&lt;br /&gt;
[[Image:Configure1.png|border|Main menu]]&lt;br /&gt;
&lt;br /&gt;
Please select the top item (&amp;lt;tt&amp;gt;BG/P DIST_DIR&amp;lt;/tt&amp;gt;).  The screen will change to:&lt;br /&gt;
&lt;br /&gt;
[[Image:Configure2.png|border|DIST_DIR menu]]&lt;br /&gt;
&lt;br /&gt;
The following options are available:&lt;br /&gt;
&lt;br /&gt;
; DRV_DIR&lt;br /&gt;
: The directory with the BG/P driver tree.  The default (&amp;lt;tt&amp;gt;/bgsys/drivers/ppcfloor/&amp;lt;/tt&amp;gt;) is a link pointing to the currently active driver.&lt;br /&gt;
; BGP_CROSS&lt;br /&gt;
: A prefix to the pathnames of the GNU cross-compilers used to build the compute node and I/O node software.&lt;br /&gt;
; BGCNS_H_PATH and BGCNS_H&lt;br /&gt;
: The location of a file needed to rebuild the kernel (these options are temporary and will be removed in the next version).&lt;br /&gt;
; OS_DIR&lt;br /&gt;
: The directory with the supplementary I/O node software used when booting the I/O nodes.  It needs to be set to match the BG/P driver version being used.&lt;br /&gt;
&lt;br /&gt;
The second top-level menu (&amp;lt;tt&amp;gt;Debugging&amp;lt;/tt&amp;gt;) has only one option:&lt;br /&gt;
&lt;br /&gt;
; ADD_DEBUG_TOOLS&lt;br /&gt;
: Check this option to include &amp;lt;tt&amp;gt;gdb&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;strace&amp;lt;/tt&amp;gt; in the compute node ramdisk.  They are not included by default because of their size.&lt;br /&gt;
&lt;br /&gt;
The third top-level menu (&amp;lt;tt&amp;gt;Kernel Profiling&amp;lt;/tt&amp;gt;) is discussed in the [[(K)TAU#Configure ZeptoOS to point to KTAU patch and path|(K)TAU section]]&lt;br /&gt;
&lt;br /&gt;
Select &amp;lt;tt&amp;gt;Exit&amp;lt;/tt&amp;gt; (multiple times if needed) and confirm if you want to save any changes made.&lt;br /&gt;
&lt;br /&gt;
== Building ==&lt;br /&gt;
&lt;br /&gt;
To start using the pre-built binaries simply type:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
$ make&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
On the first invocation, this will ask for a root password to use on I/O nodes:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
Create root password for I/O Node&lt;br /&gt;
   Leave the password field empty if you want to disable root login&lt;br /&gt;
   New password:&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
'''Security note: root-level access to I/O nodes should only be given to trusted individuals.  A root user can access and modify files of all users in the system.'''&lt;br /&gt;
&lt;br /&gt;
Once a password has been entered and confirmed, &amp;lt;tt&amp;gt;make&amp;lt;/tt&amp;gt; will use pre-built kernel images, and will build the ramdisks from pre-built tools and utilities.  The following generated files will be placed in the top-level directory:&lt;br /&gt;
&lt;br /&gt;
; BGP-CN-zImage-with-initrd.elf&lt;br /&gt;
: A merged ZeptoOS compute node Linux and compute node ramdisk file.&lt;br /&gt;
; BGP-ION-ramdisk-for-CNL.elf&lt;br /&gt;
: ZeptoOS I/O node ramdisk for use with the ZeptoOS compute node Linux.&lt;br /&gt;
; BGP-ION-ramdisk-for-CNK.elf&lt;br /&gt;
: ZeptoOS I/O node ramdisk for use with the IBM CNK (optional).&lt;br /&gt;
; BGP-ION-zImage.elf&lt;br /&gt;
: ZeptoOS I/O node kernel.&lt;br /&gt;
&lt;br /&gt;
It is possible to rebuild individual ZeptoOS components using one of the following &amp;lt;tt&amp;gt;make&amp;lt;/tt&amp;gt; targets (the list is also available by typing &amp;lt;tt&amp;gt;make help&amp;lt;/tt&amp;gt; or &amp;lt;tt&amp;gt;make menu&amp;lt;/tt&amp;gt;):&lt;br /&gt;
&lt;br /&gt;
; bgp-ion-ramdisk-cnk&lt;br /&gt;
: Rebuilds the I/O node ramdisk for the IBM CNK.&lt;br /&gt;
; bgp-ion-ramdisk-cnl&lt;br /&gt;
: Rebuilds the I/O node ramdisk for the ZeptoOS compute node Linux.&lt;br /&gt;
; bgp-ion-linux-build&lt;br /&gt;
: Rebuilds the I/O node kernel.&lt;br /&gt;
; bgp-cn-linux-build&lt;br /&gt;
: Rebuilds the compute node kernel and ramdisk and merges them.&lt;br /&gt;
; bgp-all-pkg-rebuild&lt;br /&gt;
: Rebuilds all packages from sources.&lt;br /&gt;
(the following &amp;lt;tt&amp;gt;make&amp;lt;/tt&amp;gt;targets are mostly for internal use)&lt;br /&gt;
; bgp-ion-linux&lt;br /&gt;
: Copies a recently rebuilt I/O node kernel if one is available; otherwise, uses a prebuilt binary (will not rebuild the kernel).&lt;br /&gt;
; bgp-cn-linux&lt;br /&gt;
: Copies a recently rebuilt compute node kernel if one is available; otherwise, uses a prebuilt binary (will not rebuild the kernel), rebuilds the compute node ramdisk, and merges the kernel and ramdisk.&lt;br /&gt;
; bgp-all-pkg-smart&lt;br /&gt;
: Copies recently rebuilt packages if available; otherwise, uses prebuilt binaries (used when preparing to rebuild ramdisks).&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
[[Introduction]] | [[ZeptoOS_Documentation|Top]] | [[Installation]]&lt;/div&gt;</summary>
		<author><name>Iskra</name></author>
	</entry>
</feed>