<?xml version="1.0"?>
<feed xmlns="http://www.w3.org/2005/Atom" xml:lang="en">
	<id>http://wiki.old.lustre.org/api.php?action=feedcontributions&amp;feedformat=atom&amp;user=Nathan</id>
	<title>Obsolete Lustre Wiki - User contributions [en]</title>
	<link rel="self" type="application/atom+xml" href="http://wiki.old.lustre.org/api.php?action=feedcontributions&amp;feedformat=atom&amp;user=Nathan"/>
	<link rel="alternate" type="text/html" href="http://wiki.old.lustre.org/index.php?title=Special:Contributions/Nathan"/>
	<updated>2026-04-12T21:13:50Z</updated>
	<subtitle>User contributions</subtitle>
	<generator>MediaWiki 1.39.7</generator>
	<entry>
		<id>http://wiki.old.lustre.org/index.php?title=Configuring_Lustre_File_Striping&amp;diff=12325</id>
		<title>Configuring Lustre File Striping</title>
		<link rel="alternate" type="text/html" href="http://wiki.old.lustre.org/index.php?title=Configuring_Lustre_File_Striping&amp;diff=12325"/>
		<updated>2012-02-02T00:10:50Z</updated>

		<summary type="html">&lt;p&gt;Nathan: -c and -i options were swapped&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&amp;lt;small&amp;gt;&#039;&#039;(Updated: Oct 2009)&#039;&#039;&amp;lt;/small&amp;gt;&lt;br /&gt;
__TOC__&lt;br /&gt;
One of the main factors leading to the high performance of Lustre™ file systems is the ability to stripe data over multiple OSTs. The stripe count can be set on a file system, directory, or file level.  An example showing the use of striping is provided below. &lt;br /&gt;
&lt;br /&gt;
For additional information, see [http://wiki.lustre.org/manual/LustreManual20_HTML/ManagingStripingFreeSpace.html#50438209_pgfId-5529 Chapter 18: &#039;&#039;Managing File Striping and Free Space&#039;&#039;] in the [http://wiki.lustre.org/manual/LustreManual20_HTML/index.html &#039;&#039;Lustre Operations Manual&#039;&#039;]&lt;br /&gt;
&lt;br /&gt;
== Setting Up Striping ==&lt;br /&gt;
&lt;br /&gt;
To see the current stripe size, use the command &#039;&#039;lfs getstripe [file, dir, fs]&#039;&#039;. This command will produce output similar to the following:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
root@LustreClient01 lustre]# lfs getstripe /mnt/lustre&lt;br /&gt;
OBDS:&lt;br /&gt;
0: lustre-OST0000_UUID ACTIVE&lt;br /&gt;
1: lustre-OST0001_UUID ACTIVE&lt;br /&gt;
2: lustre-OST0002_UUID ACTIVE&lt;br /&gt;
3: lustre-OST0003_UUID ACTIVE&lt;br /&gt;
4: lustre-OST0004_UUID ACTIVE&lt;br /&gt;
5: lustre-OST0005_UUID ACTIVE&lt;br /&gt;
/mnt/lustre&lt;br /&gt;
(Default) stripe_count: 2 stripe_size: 4M stripe_offset: 0&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
In this example, the default stripe count is 2 (that is, data blocks are striped over two OSTs), the default stripe size is 4 MB (the stripe size can be set in K, M or G), and all writes start from the first OST.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;&#039;&#039;Note:&#039;&#039;&#039;&#039;&#039; When setting the stripe, the offset is set before the stripe count.&lt;br /&gt;
&lt;br /&gt;
The command to set a new stripe pattern on the file system may look like this:&lt;br /&gt;
&lt;br /&gt;
 [root@LustreClient01 lustre]# lfs setstripe -s 4M -i 0 -c 1 /mnt/lustre&lt;br /&gt;
&lt;br /&gt;
This example command sets the stripe of &#039;&#039;/mnt/lustre&#039;&#039; to 4 MB blocks starting at OST0 and spanning over one OST. If a new file is created with these settings, the following results are seen:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
[root@LustreClient01 lustre]# dd if=/dev/zero of=/mnt/lustre/test1 bs=10M count=100&lt;br /&gt;
&lt;br /&gt;
root@LustreClient01 lustre]# lfs df -h&lt;br /&gt;
UUID                  bytes     Used  Available   Use%   Mounted on&lt;br /&gt;
lustre-MDT0000_UUID    4.4G   214.5M       3.9G     4%   /mnt/lustre[MDT:0]&lt;br /&gt;
lustre-OST0000_UUID    2.0G     1.1G     830.1M    53%   /mnt/lustre[OST:0]&lt;br /&gt;
lustre-OST0001_UUID    2.0G    83.3M       1.8G     4%   /mnt/lustre[OST:1]&lt;br /&gt;
lustre-OST0002_UUID    2.0G    83.3M       1.8G     4%   /mnt/lustre[OST:2]&lt;br /&gt;
lustre-OST0003_UUID    2.0G    83.3M       1.8G     4%   /mnt/lustre[OST:3]&lt;br /&gt;
lustre-OST0004_UUID    2.0G    83.3M       1.8G     4%   /mnt/lustre[OST:4]&lt;br /&gt;
lustre-OST0005_UUID    2.0G    83.3M       1.8G     4%   /mnt/lustre[OST:5]&lt;br /&gt;
&lt;br /&gt;
filesystem summary:   11.8G     1.5G       9.7G    12%   /mnt/lustre&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
In this example, the entire file was written to the first OST with a very uneven distribution of data blocks.&lt;br /&gt;
&lt;br /&gt;
Continuing with this example, the file is removed and the stripe count is changed to a value of &#039;&#039;-1&#039;&#039; to specify striping over all available OSTs:&lt;br /&gt;
&lt;br /&gt;
 [root@LustreClient01 lustre]# lfs setstripe -s 4M -i 0 -c -1 /mnt/lustre&lt;br /&gt;
&lt;br /&gt;
Now, when a file is created, the new stripe setting evenly distributes the data over all the available OSTs:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
[root@LustreClient01 lustre]# dd if=/dev/zero of=/mnt/lustre/test1 bs=10M count=100&lt;br /&gt;
100+0 records in&lt;br /&gt;
100+0 records out&lt;br /&gt;
1048576000 bytes (1.0 GB) copied, 20.2589 seconds, 51.8 MB/s&lt;br /&gt;
&lt;br /&gt;
[root@LustreClient01 lustre]# lfs df -h&lt;br /&gt;
UUID                  bytes     Used  Available   Use%   Mounted on&lt;br /&gt;
lustre-MDT0000_UUID    4.4G   214.5M       3.9G     4%  /mnt/lustre[MDT:0]&lt;br /&gt;
lustre-OST0000_UUID    2.0G   251.3M       1.6G    12%  /mnt/lustre[OST:0]&lt;br /&gt;
lustre-OST0001_UUID    2.0G   251.3M       1.6G    12%  /mnt/lustre[OST:1]&lt;br /&gt;
lustre-OST0002_UUID    2.0G   251.3M       1.6G    12%  /mnt/lustre[OST:2]&lt;br /&gt;
lustre-OST0003_UUID    2.0G   251.3M       1.6G    12%  /mnt/lustre[OST:3]&lt;br /&gt;
lustre-OST0004_UUID    2.0G   247.3M       1.6G    12%  /mnt/lustre[OST:4]&lt;br /&gt;
lustre-OST0005_UUID    2.0G   247.3M       1.6G    12%  /mnt/lustre[OST:5]&lt;br /&gt;
&lt;br /&gt;
filesystem summary:   11.8G     1.5G       9.7G    12%  /mnt/lustre&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Displaying Stripe Information for a File ==&lt;br /&gt;
&lt;br /&gt;
The &#039;&#039;lfs getstripe&#039;&#039; command can be used to display information that shows over which OSTs a file is distributed. For example, the output from the following command (showing multiple &#039;&#039;obdidx&#039;&#039; entries) indicates that the file &#039;&#039;test1&#039;&#039; is striped over all six active OSTs in the configuration:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
[root@LustreClient01 ~]# lfs getstripe /mnt/lustre/test1&lt;br /&gt;
OBDS:&lt;br /&gt;
0: lustre-OST0000_UUID ACTIVE&lt;br /&gt;
1: lustre-OST0001_UUID ACTIVE&lt;br /&gt;
2: lustre-OST0002_UUID ACTIVE&lt;br /&gt;
3: lustre-OST0003_UUID ACTIVE&lt;br /&gt;
4: lustre-OST0004_UUID ACTIVE&lt;br /&gt;
5: lustre-OST0005_UUID ACTIVE&lt;br /&gt;
/mnt/lustre/test1&lt;br /&gt;
     obdidx      objid     objid      group&lt;br /&gt;
          0          8       0x8          0&lt;br /&gt;
          1          4       0x4          0&lt;br /&gt;
          2          5       0x5          0&lt;br /&gt;
          3          5       0x5          0&lt;br /&gt;
          4          4       0x4          0&lt;br /&gt;
          5          2       0x2          0&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
In contrast, the output from the following command, which lists just a single &#039;&#039;obdidx&#039;&#039; entry, indicates that the file &#039;&#039;test2&#039;&#039; is contained on a single OST:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
[root@LustreClient01 ~]# lfs getstripe /mnt/lustre/test_2&lt;br /&gt;
OBDS:&lt;br /&gt;
0: lustre-OST0000_UUID ACTIVE&lt;br /&gt;
1: lustre-OST0001_UUID ACTIVE&lt;br /&gt;
2: lustre-OST0002_UUID ACTIVE&lt;br /&gt;
3: lustre-OST0003_UUID ACTIVE&lt;br /&gt;
4: lustre-OST0004_UUID ACTIVE&lt;br /&gt;
5: lustre-OST0005_UUID ACTIVE&lt;br /&gt;
/mnt/lustre/test_2&lt;br /&gt;
   obdidx      objid     objid      group&lt;br /&gt;
        2          8       0x8          0&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;/div&gt;</summary>
		<author><name>Nathan</name></author>
	</entry>
	<entry>
		<id>http://wiki.old.lustre.org/index.php?title=Subsystem_Map&amp;diff=9067</id>
		<title>Subsystem Map</title>
		<link rel="alternate" type="text/html" href="http://wiki.old.lustre.org/index.php?title=Subsystem_Map&amp;diff=9067"/>
		<updated>2009-12-15T22:36:58Z</updated>

		<summary type="html">&lt;p&gt;Nathan: /* build */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;The Lustre subsystems are listed below. For each subsystem, a summary description and code is provided.&lt;br /&gt;
&lt;br /&gt;
==libcfs==&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Summary&#039;&#039;&#039;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
Libcfs provides an API comprising fundamental primitives and subsystems - e.g. process management and debugging support which is used throughout LNET, Lustre, and associated utilities. This API defines a portable runtime environment that is implemented consistently on all supported build targets.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Code&#039;&#039;&#039;&lt;br /&gt;
 lustre/lnet/libcfs/**/*.[ch]&lt;br /&gt;
&lt;br /&gt;
==lnet==&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Summary&#039;&#039;&#039;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
See the [http://www.sun.com/software/products/lustre/docs/Lustre-networking.pdf Lustre Networking] white paper for details. &lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Code&#039;&#039;&#039;&lt;br /&gt;
 lustre/lnet/**/*.[ch]&lt;br /&gt;
&lt;br /&gt;
==ptlrpc==&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Summary&#039;&#039;&#039;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
Ptlrpc implements Lustre communications over LNET.&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
All communication between Lustre processes are handled by RPCs, in which a request is sent to an advertised service, and the service processes the request and returns a reply. Note that a service may be offered by any Lustre process - e.g. the OST service on an OSS processes I/O requests and the AST service on a client processes notifications of lock conflicts.&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
The initial request message of an RPC is special - it is received into the first available request buffer at the destination. All other communications involved in an RPC are like RDMAs - the peer targets them specifically. For example, in a bulk read, the OSC posts reply and bulk buffers and sends descriptors for them (the LNET matchbits used to post them) in the RPC request. After the server has received the request, it GETs or PUTs the bulk data and PUTs the RPC reply directly.&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
Ptlrpc ensures all resources involved in an RPC are freed in finite time. If the RPC does not complete within a timeout, all buffers associated with the RPC must be unlinked. These buffers are still accessible to the network until their completion events have been delivered.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Code&#039;&#039;&#039;&lt;br /&gt;
 lustre/ptlrpc/*.[ch]&lt;br /&gt;
 lustre/ldlm/ldlm_lib.c&lt;br /&gt;
&lt;br /&gt;
==llog==&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Summary&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Overview&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
LLog is the generic logging mechanism in Lustre. It allows Lustre to store records in an appropriate format and access them later using a reasonable API.&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
LLog is used is various cases. The main LLog use cases are the following:&lt;br /&gt;
&lt;br /&gt;
* mountconf - entire cluster configuration is stored on the MGS in a special configuration llog. A client may access it via an llog API working over ptlrpc; &lt;br /&gt;
&lt;br /&gt;
* MDS_OST llog - contains records for unlink and setattr operations, performed on the MDS in the last, not committed transaction. This is needed to preserve consistency between MDS and OST nodes for failure cases. General case: If the MDS does not have an inode for some file, then the OST also should not have object for the same file. So, when the OST fails in the middle of unlink and loses the last transaction containing unlink for the OST object, this may cause the object to be lost on the OST. On the MDS, the current transaction with the unlinked object has finished and the MDS has no inode for the file. This means that the file cannot be accessed later and it just eats up space on the OST. The solution is to maintain the unlink log on the MDS and process it at MDS-OST connect time to make sure the OST has all objects unlinked; &lt;br /&gt;
&lt;br /&gt;
* Size llog - this is not yet used, but is planned to log object size changes on the OST so the MDS can later check if it has object size coherence with the MDS (SOM case); &lt;br /&gt;
&lt;br /&gt;
* LOVEA llog - joins the file LOV EA merge log. &lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;General design&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Each llog type has two main parts:&lt;br /&gt;
&lt;br /&gt;
* ORIG llog - &amp;quot;server&amp;quot; part, the site where llog records are stored. It provides an API for local and/or network llog access (read, modify). Examples of ORIG logs: MDS is orig for MDS_OST llog and MGS is orig for config logs; &lt;br /&gt;
&lt;br /&gt;
* REPL llog - &amp;quot;client&amp;quot; part, the site where llog records may be used. Examples of REPL logs: OST is repl for MDS_OST llog and MGC is repl for config logs.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Code&#039;&#039;&#039;&lt;br /&gt;
 obdclass/llog.c&lt;br /&gt;
 obdclass/llog_cat.c&lt;br /&gt;
 obdclass/llog_lvfs.c&lt;br /&gt;
 obdclass/llog_obd.c&lt;br /&gt;
 obdclass/llog_swab.c&lt;br /&gt;
 obdclass/llog_test.c&lt;br /&gt;
 lov/lov_log.c&lt;br /&gt;
 ptlrpc/llog_client.c&lt;br /&gt;
 ptlrpc/llog_server.c&lt;br /&gt;
 ptlrpc/llog_net.c&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
For more information, see [[Logging API]].&lt;br /&gt;
&lt;br /&gt;
==obdclass==&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Summary&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
The obdclass code is generic Lustre configuration and device handling. Different functional parts of the Lustre code are split into obd devices which can be configured and connected in various ways to form a server or client filesystem.&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
Several examples of obd devices include:&lt;br /&gt;
&lt;br /&gt;
* OSC - object storage client (connects over network to OST)&lt;br /&gt;
* OST - object storage target&lt;br /&gt;
* LOV - logical object volume (aggregates multipe OSCs into a single virtual device)&lt;br /&gt;
* MDC - meta data client (connects over network to MDT)&lt;br /&gt;
* MDT - meta data target &lt;br /&gt;
&lt;br /&gt;
The obdclass code provides services used by all Lustre devices for configuration, memory allocation, generic hashing, kernel interface routines, random number generation, etc. &lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Code&#039;&#039;&#039;&lt;br /&gt;
 lustre/obdclass/class_hash.c        - scalable hash code for imports&lt;br /&gt;
 lustre/obdclass/class_obd.c         - base device handling code&lt;br /&gt;
 lustre/obdclass/debug.c             - helper routines for dumping data structs&lt;br /&gt;
 lustre/obdclass/genops.c            - device allocation/configuration/connection&lt;br /&gt;
 lustre/obdclass/linux-module.       - linux kernel module handling&lt;br /&gt;
 lustre/obdclass/linux-obdo.c        - pack/unpack obdo and other IO structs&lt;br /&gt;
 lustre/obdclass/linux-sysctl.c      - /proc/sys configuration parameters &lt;br /&gt;
 lustre/obdclass/lprocfs_status.c    - /proc/fs/lustre configuration/stats, helpers&lt;br /&gt;
 lustre/obdclass/lustre_handles.c    - wire opaque pointer handlers&lt;br /&gt;
 lustre/obdclass/lustre_peer.c       - peer target identification by UUID&lt;br /&gt;
 lustre/obdclass/obd_config.c        - configuration file parsing&lt;br /&gt;
 lustre/obdclass/obd_mount.c         - server filesystem mounting&lt;br /&gt;
 lustre/obdclass/obdo.c              - more obdo handling helpers&lt;br /&gt;
 lustre/obdclass/statfs_pack.c       - statfs helpers for wire pack/unpack&lt;br /&gt;
 lustre/obdclass/uuid.c              - UUID pack/unpack&lt;br /&gt;
 lustre/lvfs/lvfs_common.c           - kernel interface helpers&lt;br /&gt;
 lustre/lvfs/lvfs_darwin.c           - darwin kernel helper routines&lt;br /&gt;
 lustre/lvfs/lvfs_internal.h         - lvfs internal function prototypes&lt;br /&gt;
 lustre/lvfs/lvfs_lib.c              - statistics&lt;br /&gt;
 lustre/lvfs/lvfs_linux.c            - linux kernel helper routines&lt;br /&gt;
 lustre/lvfs/lvfs_userfs.c           - userspace helper routines&lt;br /&gt;
 lustre/lvfs/prng.c                  - long period pseudo-random number generator&lt;br /&gt;
 lustre/lvfs/upcall_cache.c          - supplementary group upcall for MDS&lt;br /&gt;
&lt;br /&gt;
==luclass==&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Summary&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
luclass is a body of data-type definitions and functions implementing support for a layered object, that is an entity where every layer in the Lustre device stack (both data and meta-data, and both client and server side) can maintain its own private state, and modify a behavior of a compound object in a systematic way.&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
Specifically, data-types are introduced, representing a device type (struct lu_device_type, layer in the Lustre stack), a device (struct lu_device, a specific instance of the type), and object (struct lu_object). Following lu_object functionality is implemented by a generic code:&lt;br /&gt;
&lt;br /&gt;
* Compound object is uniquely identified by a FID, and is stored in a hash table, indexed by a FID; &lt;br /&gt;
&lt;br /&gt;
* Objects are kept in a LRU list, and a method to purge least recently accessed objects in reaction to the memory pressure is provided; &lt;br /&gt;
&lt;br /&gt;
* Objects are reference counted, and cached; &lt;br /&gt;
&lt;br /&gt;
* Every object has a list of &#039;&#039;layers&#039;&#039; (also known as slices), where devices can store their private state. Also, every slice comes with a pointer to an operations vector, allowing device to modify object&#039;s behavior. &lt;br /&gt;
&lt;br /&gt;
In addition to objects and devices, luclass includes lu_context, which is a way to efficiently allocate space, without consuming stack space.&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
luclass design is specified in the [http://arch.lustre.org/images/a/aa/Md-api-dld.pdf MD API] DLD.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Code&#039;&#039;&#039;&lt;br /&gt;
 include/lu_object.h&lt;br /&gt;
 obdclass/lu_object.c&lt;br /&gt;
&lt;br /&gt;
==ldlm==&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Summary&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
The Lustre Distributed Lock Manager (LDLM) is the Lustre locking infrastructure; it handles locks between clients and servers and locks local to a node. Different kinds of locks are available with different properties. Also as a historic heritage, ldlm happens to have some of the generic connection service code (both server and client).&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Code&#039;&#039;&#039; &lt;br /&gt;
 interval_tree.c           - This is used by extent locks to maintain interval trees (bug 11300)&lt;br /&gt;
 l_lock.c                  - Resourse locking primitives. &lt;br /&gt;
 ldlm_extent.c             - Extents locking code used for locking regions inside objects&lt;br /&gt;
 ldlm_flock.c              - Bsd and posix locking lock types&lt;br /&gt;
 ldlm_inodebits.c          - Inodebis locks used for metadata locking&lt;br /&gt;
 ldlm_lib.c                - Target and client connecting/reconnecting/recovery code.&lt;br /&gt;
                             Does not really belong to ldlm, but is historically placed &lt;br /&gt;
                             there. Should be in ptlrpc instead.&lt;br /&gt;
 ldlm_lock.c               - This source file mostly has functions dealing with struct&lt;br /&gt;
 ldlm_lock ldlm_lockd.c    - Functions that imply replying to incoming lock-related rpcs &lt;br /&gt;
                             (that could be both on server (lock enq/cancel/...) and client &lt;br /&gt;
                             (ast handling)).&lt;br /&gt;
 ldlm_plain.c              - Plain locks, predecessor to inodebits locks; not widely used now.&lt;br /&gt;
 ldlm_pool.c               - Pools of locks, related to dynamic lrus and freeing locks on demand.&lt;br /&gt;
 ldlm_request.c            - Collection of functions to work with locks based handles as opposed &lt;br /&gt;
                             to lock structures themselves.&lt;br /&gt;
 ldlm_resource.c           - Functions operating on namespaces and lock resources.&lt;br /&gt;
 include/lustre_dlm.h      - Important defines and declarations for ldlm.&lt;br /&gt;
&lt;br /&gt;
==fids==&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Summary&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
FID is unique object identifier in cluster since 1.7. It has few properties, main of them are the following:&lt;br /&gt;
&lt;br /&gt;
* FID is unique and not reused object identifier;&lt;br /&gt;
* FID is allocated by client inside of the sequence granted by server;&lt;br /&gt;
* FID is base for ldlm resource used for issuing ldlm locks. This is because FID is unique and as such good for this using;&lt;br /&gt;
* FID is base for building client side inode numbers as we can&#039;t use server inode+generation anymore, in CMD this is not unique combination;&lt;br /&gt;
* FID does not contain store information like inode number or generation and as such easy to migrate; &lt;br /&gt;
&lt;br /&gt;
FID consists of 3 fields:&lt;br /&gt;
&lt;br /&gt;
* f_seq - sequence number&lt;br /&gt;
* f_oid - object identifier inside sequence&lt;br /&gt;
* f_ver - object version &lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Code&#039;&#039;&#039;&lt;br /&gt;
 fid/fid_request.c&lt;br /&gt;
 fid/fid_lib.c&lt;br /&gt;
 fld/*.[ch]&lt;br /&gt;
&lt;br /&gt;
==seq==&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Summary&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Overview&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Sequence management is a basic mechanism in new MDS server which is related to managing FIDs.&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
FID is an unique object identifier in Lustre starting from version 1.7. All FIDs are organized into sequences. One sequence is number of FIDs. Sequences are granted/allocated to clients by servers. FIDs are allocated by clients inside granted sequence. All FIDs inside one sequence live on same MDS server and as such are one &amp;quot;migration unit&amp;quot; and one &amp;quot;indexing unit&amp;quot;, meaning that FLD (FIDs Location Database) indexes them all using one sequence and thus has only one mapping entry for all FIDs in sequence. Please read section devoted to FIDs bellow in the root table to find more info on FLD service and FIDs.&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
A sequence has the limit of FIDs to be allocated in it. When this limit is reached, new sequence is allocated. Upon disconnect, server allocates new sequence to the client when it comes back. Previously used sequence is abandoned even if it was not exhausted. Sequences are valuable resource but in the case of recovery, using new sequence makes things easier and also allows to group FIDs and objects by working sessions, new connection - new sequence.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Code description&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Server side code is divided into two parts:&lt;br /&gt;
&lt;br /&gt;
* Sequence controller - allocates super-sequences, that is, sequences of sequences to all servers in cluster (currently only to MDSes as only they are new FIDs aware). Usually first MDS in cluster is sequence controller &lt;br /&gt;
&lt;br /&gt;
* Sequence manager - allocates meta-sequences (smaller range of sequences inside a super-sequence) to all clients, using granted super-sequence from the sequence controller. All MDSs in the cluster (all servers in the future) are sequence managers. The first MDS is, simultaneously, a sequence controller and a sequence manager.&lt;br /&gt;
&lt;br /&gt;
Client side code allocates new sequences from granted meta-sequence. When meta-sequence is exhausted, new one is allocated on server and sent to the client.&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
Client code consists of API for working with both server side parts, not only with sequence manager as all servers need to talk to sequence controller, they also use client API for this.&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
One important part of client API is FIDs allocation. New FID is allocated in currently granted sequence until sequence is exhausted. &lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Code&#039;&#039;&#039;&lt;br /&gt;
 fid/fid_handler.c    - server side sequence management code;&lt;br /&gt;
 fid/fid_request.c    - client side sequence management code;&lt;br /&gt;
 fid/fid_lib.c        - fids related miscellaneous stuff.&lt;br /&gt;
&lt;br /&gt;
==mountconf==&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Summary&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
MountConf is how servers and clients are set up, started, and configured. A MountConf usage document is [http://wiki.lustre.org/index.php?title=Mount_Conf here].&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
The major subsystems are the MGS, MGC, and the userspace tools mount.lustre and mkfs.lustre.&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
The basic idea is:&lt;br /&gt;
&lt;br /&gt;
# Whenever any Lustre component is mount(2)ed, we start a MGC.&lt;br /&gt;
# This establishes a connection to the MGS and downloads a configuration llog.&lt;br /&gt;
# The MGC passes the configuration log through the parser to set up the other OBDs.&lt;br /&gt;
# The MGC holds a CR configuration lock, which the MGS recalls whenever a live configuration change is made. &lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Code&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
MountConf file areas:&lt;br /&gt;
&lt;br /&gt;
 lustre/mgs/*&lt;br /&gt;
 lustre/mgc/*&lt;br /&gt;
 lustre/obdclass/obd_mount.c&lt;br /&gt;
 lustre/utils/mount_lustre.c&lt;br /&gt;
 lustre/utils/mkfs_lustre.c&lt;br /&gt;
&lt;br /&gt;
==liblustre==&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Summary&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Liblustre is a userspace library, used along with libsysio (developed by Sandia), that allows Lustre usage just by linking (or ld_preload&#039;ing) applications with it. Liblustre does not require any kernel support. It is also used on old Cray XT3 machines (and not so old, in the case of Sandia), where all applications are just linked with the library and loaded into memory as the only code to run. Liblustre does not support async operations of any kind due to a lack of interrupts and other notifiers from lower levels to Lustre. Liblustre includes another set of LNDs that are able to work from userspace.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Code&#039;&#039;&#039;&lt;br /&gt;
 dir.c          - Directory operations&lt;br /&gt;
 file.c         - File handling operations (like open)&lt;br /&gt;
 llite_lib.c    - General support (init/cleanp/parse options)&lt;br /&gt;
 lutil.c        - Supplementary code to get IP addresses and init various structures &lt;br /&gt;
                  needed to emulate the normal Linux process from other layers&#039; perspective.&lt;br /&gt;
 namei.c        - Metadata operations code.&lt;br /&gt;
 rw.c           - I/O code, including read/write&lt;br /&gt;
 super.c        - &amp;quot;Superblock&amp;quot; operation - mounting/umounting, inode operations.&lt;br /&gt;
 tests          - directory with liblustre-specific tests.&lt;br /&gt;
&lt;br /&gt;
==echo client/server==&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Summary&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
The echo_client and obdecho are OBD devices which help testing and performance measurement.&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
They were implemented originally for network testing - obdecho can replace obdfilter and echo_client can exercise any downstream configurations. They are normally used in the following configurations:&lt;br /&gt;
&lt;br /&gt;
* echo_client -&amp;gt; obdfilter. This is used to measure raw backend performance without any network I/O. &lt;br /&gt;
* echo_client -&amp;gt; OSC -&amp;gt; &amp;lt;network&amp;gt; -&amp;gt; OST -&amp;gt; obdecho. This is used to measure network and ptlrpc performance. &lt;br /&gt;
* echo_client -&amp;gt; OSC -&amp;gt; &amp;lt;network&amp;gt; -&amp;gt; OST -&amp;gt; obdfilter. This is used to measure performance available to the Lustre client. &lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Code&#039;&#039;&#039;&lt;br /&gt;
 lustre/obdecho/&lt;br /&gt;
&lt;br /&gt;
==client vfs==&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Summary&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
The client VFS interface, also called &#039;&#039;&#039;llite&#039;&#039;&#039;, is the bridge between the Linux kernel and the underlying Lustre infrastructure represented by the [https://wikis.clusterfs.com/intra/index.php/Lov_summary LOV], [https://wikis.clusterfs.com/intra/index.php/Client_metadata_summary MDC], and [https://wikis.clusterfs.com/intra/index.php/Ldlm_summary LDLM] subsystems. This includes mounting the client filesystem, handling name lookups, starting file I/O, and handling file permissions.&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
The Linux VFS interface shares a lot in common with the liblustre interface, which is used in the Catamount environment; as of yet, the code for these two subsystems is not common and contains a lot of duplication.  &lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Code&#039;&#039;&#039;&lt;br /&gt;
 lustre/llite/dcache.c            - Interface with Linux dentry cache/intents&lt;br /&gt;
 lustre/llite/dir.c               - readdir handling, filetype in dir, dir ioctl&lt;br /&gt;
 lustre/llite/file.c              - File handles, file ioctl, DLM extent locks&lt;br /&gt;
 lustre/llite/llite_close.c       - File close for opencache&lt;br /&gt;
 lustre/llite/llite_internal.h    - Llite internal function prototypes, structures&lt;br /&gt;
 lustre/llite/llite_lib.c         - Majority of request handling, client mount&lt;br /&gt;
 lustre/llite/llite_mmap.c        - Memory-mapped I/O&lt;br /&gt;
 lustre/llite/llite_nfs.c         - NFS export from clients&lt;br /&gt;
 lustre/llite/lloop.c             - Loop-like block device export from object&lt;br /&gt;
 lustre/llite/lproc_llite.c       - /proc interface for tunables, statistics&lt;br /&gt;
 lustre/llite/namei.c             - Filename lookup, intent handling&lt;br /&gt;
 lustre/llite/rw24.c              - Linux 2.4 IO handling routines&lt;br /&gt;
 lustre/llite/rw26.c              - Linux 2.6 IO handling routines&lt;br /&gt;
 lustre/llite/rw.c                - Linux generic IO handling routines&lt;br /&gt;
 lustre/llite/statahead.c         - Directory statahead for &amp;quot;ls -l&amp;quot; and &amp;quot;rm -r&amp;quot;&lt;br /&gt;
 lustre/llite/super25.c           - Linux 2.6 VFS file method registration&lt;br /&gt;
 lustre/llite/super.c             - Linux 2.4 VFS file method registration&lt;br /&gt;
 lustre/llite/symlink.c           - Symbolic links&lt;br /&gt;
 lustre/llite/xattr.c             - User-extended attributes&lt;br /&gt;
&lt;br /&gt;
==client vm==&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Summary&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Client code interacts with VM/MM subsystems of the host OS kernel to cache data (in the form of pages), and to react to various memory-related events, like memory pressure.&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
Two key components of this interaction are:&lt;br /&gt;
&lt;br /&gt;
* cfs_page_t data-type representing MM page. It comes together with the interface to map/unmap page to/from kernel virtual address space, access various per-page bits, like &#039;dirty&#039;, &#039;uptodate&#039;, etc., lock/unlock page. Currently, this data-type closely matches the Linux kernel page. It has to be straightened out, formalized, and expanded to include functionality like querying about total number of pages on a node, etc. &lt;br /&gt;
* MM page operations in cl_page (part of new client I/O interface). &lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Code&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
This describes the &#039;&#039;next generation&#039;&#039; Lustre client I/O code, which is expected to appear in Lustre 2.0. Code location is not finalized.&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
cfs_page_t interface is defined and implemented in:&lt;br /&gt;
&lt;br /&gt;
 lnet/include/libcfs/ARCH/ARCH-mem.h&lt;br /&gt;
 lnet/libcfs/ARCH/ARCH-mem.c &lt;br /&gt;
&lt;br /&gt;
Generic part of cl-page will be located in:&lt;br /&gt;
&lt;br /&gt;
 include/cl_object.h&lt;br /&gt;
 obdclass/cl_page.c&lt;br /&gt;
 obdclass/cl_object.c &lt;br /&gt;
&lt;br /&gt;
Linux kernel implementation is currently in:&lt;br /&gt;
&lt;br /&gt;
 llite/llite_cl.c&lt;br /&gt;
&lt;br /&gt;
==client I/O==&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Summary&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Client I/O is a group of interfaces used by various layers of a Lustre client to manage file data (as opposed to metadata). Main functions of these interfaces are:&lt;br /&gt;
&lt;br /&gt;
* Cache data, respecting limitations imposed both by hosting MM/VM, and by cluster-wide caching policies, and &lt;br /&gt;
* Form a stream of efficient I/O RPCs, respecting both ordering/timing constraints imposed by the hosting VFS (e.g., POSIX guarantees, O_SYNC, etc.), and cluster-wide IO scheduling policies. &lt;br /&gt;
&lt;br /&gt;
Client I/O subsystem interacts with VFS, VM/MM, DLM, and PTLRPC.&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
Client I/O interfaces are based on the following data-types:&lt;br /&gt;
&lt;br /&gt;
* cl_object: represents a file system object, both a file, and a stripe; &lt;br /&gt;
* cl_page: represents a cached data page; &lt;br /&gt;
* cl_lock: represents an extent DLM lock; &lt;br /&gt;
* cl_io: represents an ongoing high-level IO activity, like read(2)/write(2) system call, or sub-io of another IO; &lt;br /&gt;
* cl_req: represents a network RPC. &lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Code&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
This describes the &#039;&#039;next generation&#039;&#039; Lustre client I/O code. The code location is not finalized. The generic part is at:&lt;br /&gt;
&lt;br /&gt;
 include/cl_object.h&lt;br /&gt;
 obdclass/cl_object.c&lt;br /&gt;
 obdclass/cl_page.c&lt;br /&gt;
 obdclass/cl_lock.c&lt;br /&gt;
 obdclass/cl_io.c &lt;br /&gt;
&lt;br /&gt;
Layer-specific methods are currently at:&lt;br /&gt;
&lt;br /&gt;
 lustre/LAYER/LAYER_cl.c &lt;br /&gt;
&lt;br /&gt;
where LAYER is one of llite, lov, osc.&lt;br /&gt;
&lt;br /&gt;
==client metadata==&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Summary&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
The Meta Data Client (MDC) is the client-side interface for all operations related to the Meta Data Server  MDS. In current configurations there is a single MDC on the client for each filesystem mounted on the client. The MDC is responsible for enqueueing metadata locks (via  LDLM), and packing and unpacking messages on the wire.&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
In order to ensure a recoverable system, the MDC is limited at the client to only a single filesystem-modifying operation in flight at one time. This includes operations like create, rename, link, unlink, setattr.&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
For non-modifying operations like getattr and statfs the client can multiple RPC requests in flight at one time, limited by a tunable on the client, to avoid overwhelming the MDS. &lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Code&#039;&#039;&#039; &lt;br /&gt;
 lustre/mdc/lproc_mdc.c       - /proc interface for stats/tuning&lt;br /&gt;
 lustre/mdc/mdc_internal.h    - Internal header for prototypes/structs&lt;br /&gt;
 lustre/mdc/mdc_lib.c         - Packing of requests to MDS&lt;br /&gt;
 lustre/mdc/mdc_locks.c       - Interface to LDLM and client VFS intents&lt;br /&gt;
 lustre/mdc/mdc_reint.c       - Modifying requests to MDS&lt;br /&gt;
 lustre/mdc/mdc_request.c     - Non-modifying requests to MDS&lt;br /&gt;
&lt;br /&gt;
==client lmv== &lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Summary&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
LMV is a module which implements CMD client-side abstraction device. It allows client to work with many MDSes without any changes in Llite module and even without knowing that CMD is supported. Llite just translates Linux VFS requests into metadata API calls and forwards them down to the stack.&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
As LMV needs to know which MDS to talk for any particular operation, it uses some new services introduced in CMD3 times. They are:&lt;br /&gt;
&lt;br /&gt;
* FLD (Fids Location Database) - having FID or rather its sequence, lookup MDS number where this FID is located;&lt;br /&gt;
* SEQ (Client Sequence Manager) - LMV uses this via children MDCs for allocating new sequences and FIDs. &lt;br /&gt;
&lt;br /&gt;
LMV supports split objects. This means that for every split directory it creates special in-memory structure which contains information about object stripes. This includes MDS number, FID, etc. All consequent operations use these structures for determining what MDS should be used for particular action (create, take lock, etc).&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Code&#039;&#039;&#039;&lt;br /&gt;
 lmv/*.[ch]&lt;br /&gt;
&lt;br /&gt;
==lov==&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Summary&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
The LOV device presents a single virtual device interface to upper layers (llite, liblustre, MDS). The LOV code is responsible for splitting of requests to the correct OSTs based on striping information (lsm), and the merging of the replies to a single result to pass back to the higher layer.&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
It calculates per-object membership and offsets for read/write/truncate based on the virtual file offset passed from the upper layer. It is also responsible for splitting the locking across all servers as needed.&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
The LOV on the MDS is also involved in object allocation. &lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Code&#039;&#039;&#039;&lt;br /&gt;
 lustre/lov/lov_ea.c          - Striping attributes pack/unpack/verify&lt;br /&gt;
 lustre/lov/lov_internal.h    - Header for internal function prototypes/structs&lt;br /&gt;
 lustre/lov/lov_merge.c       - Struct aggregation from many objects&lt;br /&gt;
 lustre/lov/lov_obd.c         - Base LOV device configuration&lt;br /&gt;
 lustre/lov/lov_offset.c      - File offset and object calculations&lt;br /&gt;
 lustre/lov/lov_pack.c        - Pack/unpack of striping attributes&lt;br /&gt;
 lustre/lov/lov_qos.c         - Object allocation for different OST loading&lt;br /&gt;
 lustre/lov/lov_request.c     - Request handling/splitting/merging&lt;br /&gt;
 lustre/lov/lproc_lov.c       - /proc/fs/lustre/lov tunables/statistics&lt;br /&gt;
&lt;br /&gt;
==quota==&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Summary&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Quotas allow a system administrator to limit the maximum amount of disk space a user or group can consume. Quotas are set by root, and can be specified for individual users and/or groups. Quota limits can be set on both blocks and inodes.&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
Lustre quota enforcement differs from standard Linux quota support in several ways:&lt;br /&gt;
&lt;br /&gt;
* Lustre quota are administered via the lfs command, whereas standard Linux quota uses the quotactl interface.&lt;br /&gt;
* As Lustre is a distributed filesystem, lustre quotas are also distributed in order to limit the impact on performance.&lt;br /&gt;
* Quotas are allocated and consumed in a quantized fashion. &lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Code&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Quota core:&lt;br /&gt;
&lt;br /&gt;
 lustre/quota/quota_adjust_qunit.c&lt;br /&gt;
 lustre/quota/quota_check.c&lt;br /&gt;
 lustre/quota/quotacheck_test.c&lt;br /&gt;
 lustre/quota/quota_context.c&lt;br /&gt;
 lustre/quota/quota_ctl.c&lt;br /&gt;
 lustre/quota/quota_interface.c&lt;br /&gt;
 lustre/quota/quota_internal.h&lt;br /&gt;
 lustre/quota/quota_master.c &lt;br /&gt;
&lt;br /&gt;
Interactions with the underlying ldiskfs filesystem:&lt;br /&gt;
&lt;br /&gt;
 lustre/lvfs/fsfilt_ext3.c&lt;br /&gt;
 lustre/lvfs/lustre_quota_fmt.c&lt;br /&gt;
 lustre/lvfs/lustre_quota_fmt_convert.c &lt;br /&gt;
&lt;br /&gt;
Hooks under:&lt;br /&gt;
&lt;br /&gt;
 lustre/mds&lt;br /&gt;
 lustre/obdfilter &lt;br /&gt;
&lt;br /&gt;
Regression tests:&lt;br /&gt;
&lt;br /&gt;
 lustre/tests/sanity-quota.sh&lt;br /&gt;
&lt;br /&gt;
==security-gss==&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Summary&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
The secure ptlrpc (sptlrpc) is a framework inside of ptlrpc layer. It act upon both side of each ptlrpc connection between 2 nodes, doing transformation on every RPC message, turn this into a secure communication link. By using GSS, sptlrpc is able to support multiple authentication mechanism, but currently we only support Kerberos 5.&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
Supported security flavors:&lt;br /&gt;
&lt;br /&gt;
* null: no authentication, no data transform, thus no performance overhead; compatible with 1.6;&lt;br /&gt;
* plain: no authentication, simple data transform, minimal performance overhead;&lt;br /&gt;
* krb5x: per-user basis client-server mutual authentication using Kerberos 5, sign or encrypt data, could have substantial CPU overhead. &lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Code&#039;&#039;&#039;&lt;br /&gt;
 lustre/ptlrpc/sec*.c&lt;br /&gt;
 lustre/ptlrpc/gss/&lt;br /&gt;
 lustre/utils/gss/&lt;br /&gt;
&lt;br /&gt;
==security-capa==&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Summary&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Capabilities are pieces of data generated by one service - the master service, passed to a client and presented by the client to another service - the slave service, to authorize an action. It is independent from the R/W/X permission based file operation authorization.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Code&#039;&#039;&#039;&lt;br /&gt;
 lustre/llite/llite_capa.c&lt;br /&gt;
 lustre/mdt/mdt_capa.c&lt;br /&gt;
 lustre/obdfilter/filter_capa.c&lt;br /&gt;
 lustre/obdclass/capa.c&lt;br /&gt;
 lustre/include/lustre_capa.h&lt;br /&gt;
&lt;br /&gt;
==security-identity== &lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Summary&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Lustre identity is a miscellaneous framework for lustre file operation authorization. Generally, it can be divided into two parts:&lt;br /&gt;
&lt;br /&gt;
* User-identity parse / upcall / mapping.&lt;br /&gt;
* File operation permission maintenance and check, includes the traditional file mode based permission and ACL based permission.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Code&#039;&#039;&#039; &lt;br /&gt;
 /llite/llite_rmtacl.c&lt;br /&gt;
 lustre/mdt/mdt_identity.c&lt;br /&gt;
 lustre/mdt/mdt_idmap.c&lt;br /&gt;
 lustre/mdt/mdt_lib.c&lt;br /&gt;
 lustre/obdclass/idmap.c&lt;br /&gt;
 lustre/utils/l_getidentity.c&lt;br /&gt;
 lustre/include/lustre_idmap.h &lt;br /&gt;
&lt;br /&gt;
 lustre/llite/xattr.c&lt;br /&gt;
 lustre/mdt/mdt_xattr.c&lt;br /&gt;
 lustre/cmm/cmm_object.c&lt;br /&gt;
 lustre/cmm/mdc_object.c&lt;br /&gt;
 lustre/mdd/mdd_permission.c&lt;br /&gt;
 lustre/mdd/mdd_object.c&lt;br /&gt;
 lustre/mdd/mdd_dir.c&lt;br /&gt;
 lustre/obdclass/acl.c&lt;br /&gt;
 lustre/include/lustre_eacl.h&lt;br /&gt;
&lt;br /&gt;
==OST== &lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Summary&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
OST is a very thin layer of data server. Its main responsibility is to translate RPCs to local calls of obdfilter, i.e. RPC parsing.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Code&#039;&#039;&#039; &lt;br /&gt;
 lustre/ost/*.[ch]&lt;br /&gt;
&lt;br /&gt;
==ldiskfs== &lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Summary&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
ldiskfs is local disk filesystem built on top of ext3. it adds extents support to ext3, multiblock allocator, multimount protection and iopen features.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Code&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
There is no ldiskfs source code in the Lustre repositories (only patches). Instead, ext3 code is copied from your build kernel, the patches are applied and then whole thing gets renamed to ldiskfs. For details, go to ldiskfs/.&lt;br /&gt;
&lt;br /&gt;
==fsfilt== &lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Summary&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
The fsfilt layer abstracts the backing filesystem specifics away from the obdfilter and mds code in 1.4 and 1.6 lustre. This avoids linking the obdfilter and mds directly against the filesystem module, and in theory allows different backing filesystems, but in practise this was never implemented. In Lustre 1.8 and later this code is replaced by the OSD layer.&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
There is a core fsfilt module which can auto-load the backing filesystem type based on the type specified during configuration. This loads a filesystem-specific fsfilt_{fstype} module with a set of methods for that filesystem.&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
There are a number of different kinds of methods:&lt;br /&gt;
&lt;br /&gt;
* Get/set filesystem label and UUID for identifying the backing filesystem&lt;br /&gt;
* Start, extend, commit compound filesystem transactions to allow multi-file updates to be atomic for recovery&lt;br /&gt;
* Set a journal callback for transaction disk commit (for Lustre recovery)&lt;br /&gt;
* Store attributes in the inode (possibly avoiding side-effects like truncation when setting the inode size to zero)&lt;br /&gt;
* Get/set file attributes (EAs) for storing LOV and OST info (e.g. striping)&lt;br /&gt;
* Perform low-level IO on the file (avoiding cache)&lt;br /&gt;
* Get/set file version (for future recovery mechanisms)&lt;br /&gt;
* Access quota information &lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Code&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
The files used for the fsfilt code reside in:&lt;br /&gt;
&lt;br /&gt;
 lustre/lvfs/fsfilt.c         - Interface used by obdfilter/MDS, module autoloading&lt;br /&gt;
 lustre/lvfs/fsfilt_ext3.c    - Interface to ext3/ldiskfs filesystem&lt;br /&gt;
&lt;br /&gt;
The &#039;&#039;fsfilt_ldiskfs.c&#039;&#039; file is auto-generated from &#039;&#039;fsfilt_ext3.c&#039;&#039; in &#039;&#039;lustre/lvfs/autoMakefile.am&#039;&#039; using sed to replace instances of ext3 and EXT3 with ldiskfs, and a few other replacements to avoid symbol clashes.&lt;br /&gt;
&lt;br /&gt;
==ldiskfs OSD==&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Summary&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
ldiskfs-OSD is an implementation of dt_{device,object} interfaces on top of (modified) ldiskfs file-system.&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
It uses standard ldiskfs/ext3 code to do file I/O.&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
It supports 2 types of indices (in the same file system):&lt;br /&gt;
&lt;br /&gt;
* iam-based index: this is an extension of ext3 htree directory format with support for more general keys and values, and with relaxed size restrictions, and &lt;br /&gt;
* compatibility index: this is usual ldiskfs directory, accessible through dt_index_operations. &lt;br /&gt;
&lt;br /&gt;
ldiskfs-OSD uses read-write mutex to serialize compound operations. &lt;br /&gt;
&amp;lt;/blockquote&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Code&#039;&#039;&#039; &lt;br /&gt;
 lustre/include/dt_object.h&lt;br /&gt;
 lustre/osd/osd_internal.h&lt;br /&gt;
 lustre/osd/osd_handler.c&lt;br /&gt;
&lt;br /&gt;
==DMU OSD== &lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Summary&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
This is another implementation of the OSD API for userspace DMU. It uses DMU&#039;s ZAP for indices.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Code&#039;&#039;&#039;&lt;br /&gt;
 dmu-osd/*.[ch] in b_hd_dmu branch&lt;br /&gt;
&lt;br /&gt;
==DMU== &lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Summary&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
The DMU is one of the layers in Sun&#039;s ZFS filesystem which is responsible for presenting a transactional object store to its consumers. It is used as Lustre&#039;s backend object storage mechanism for the userspace MDSs and OSSs.&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
The ZFS community page has a source tour which is useful as an introduction to the several ZFS layers: [http://www.opensolaris.org/os/community/zfs/source/ ZFS source]&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
There are many useful resources in that community page.&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
For reference, here&#039;s a list of DMU features:&lt;br /&gt;
&lt;br /&gt;
* Atomic transactions&lt;br /&gt;
* End-to-end data and metadata checksumming (currently supports fletcher2, fletcher4 and sha-256)&lt;br /&gt;
* Compression (currently supports lzjb and gzip with compression levels 1..9)&lt;br /&gt;
* Snapshots and clones&lt;br /&gt;
* Variable block sizes (currently supports sector sizes from 512 bytes to 128KB)&lt;br /&gt;
* Integrated volume management with support for RAID-1, RAID-Z and RAID-Z2 and striping&lt;br /&gt;
* Metadata and optional data redundancy (ditto blocks) atop the inherent storage pool redundancy for high resilience&lt;br /&gt;
* Self-healing, which works due to checksumming, ditto blocks and pool redundancy&lt;br /&gt;
* Storage devices that act as level-2 caches (designed for flash storage)&lt;br /&gt;
* Hot spares&lt;br /&gt;
* Designed with scalability in mind - supports up to 2^64 bytes per object, 2^48 objects per filesystem, 2^64 filesystems per pool, 2^64 bytes per device, 2^64 devices per pool, ..&lt;br /&gt;
* Very easy to use admin interface (zfs and zpool commands) &lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Code&#039;&#039;&#039; &lt;br /&gt;
 src/&lt;br /&gt;
 source code&lt;br /&gt;
 &lt;br /&gt;
 src/cmd/              - ZFS/DMU related programs&lt;br /&gt;
 src/cmd/lzfs/         - lzfs, the filesystem administration utility&lt;br /&gt;
 src/cmd/lzpool/       - lzpool, the pool administration utility&lt;br /&gt;
 src/cmd/lzdb/         - lzdb, the zfs debugger&lt;br /&gt;
 src/cmd/lztest/       - lztest, the DMU test suite&lt;br /&gt;
 src/cmd/lzfsd/        - lzfsd, the ZFS daemon&lt;br /&gt;
 &lt;br /&gt;
 src/lib/              - Libraries&lt;br /&gt;
 src/lib/port/         - Portability layer&lt;br /&gt;
 src/lib/solcompat/    - Solaris -&amp;gt; Linux portability layer (deprecated, use libport instead)&lt;br /&gt;
 src/lib/avl/          - AVL trees, used in many places in the DMU code&lt;br /&gt;
 src/lib/nvpair/       - Name-value pairs, used in many places in the DMU code&lt;br /&gt;
 src/lib/umem/         - Memory management library&lt;br /&gt;
 src/lib/zpool/        - Main ZFS/DMU code&lt;br /&gt;
 src/lib/zfs/          - ZFS library used by the lzfs and lzpool utilities&lt;br /&gt;
 src/lib/zfscommon/    - Common ZFS code between libzpool and libzfs&lt;br /&gt;
 src/lib/ctl/          - Userspace control/management interface&lt;br /&gt;
 src/lib/udmu/         - Lustre uDMU code (thin library around the DMU)&lt;br /&gt;
 &lt;br /&gt;
 src/scons/            - local copy of SCons&lt;br /&gt;
 &lt;br /&gt;
 tests/regression/     - Regression tests&lt;br /&gt;
 &lt;br /&gt;
 misc/                 - miscellaneous files/scripts&lt;br /&gt;
&lt;br /&gt;
==obdfilter==&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Summary&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
obdfilter is a core component of OST (data server) making underlying disk filesystem a part of distributed system:&lt;br /&gt;
&lt;br /&gt;
* Maintains cluster-wide coherency for data&lt;br /&gt;
* Maintains space reservation for data in client&#039;s cache (grants)&lt;br /&gt;
* Maintains quota &lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Code&#039;&#039;&#039; &lt;br /&gt;
 lustre/obdfilter/*.[ch]&lt;br /&gt;
&lt;br /&gt;
==MDS==&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Summary&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
The MDS service in Lustre 1.4 and 1.6 is a monolithic body of code that provides multiple functions related to filesystem metadata. It handles the incoming RPCs and service threads for metadata operations (create, rename, unlink, readdir, etc), interfaces with the Lustre lock manager ([https://wikis.clusterfs.com/intra/index.php/Ldlm_summary DLM]), and also manages the underlying filesystem (via the [https://wikis.clusterfs.com/intra/index.php/Fsfilt_summary interface fsfilt] interface).&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
The MDS is the primary point of access control for clients, allocates the objects belonging to a file (in conjunction with [https://wikis.clusterfs.com/intra/index.php/Lov_summary LOV]) and passing that information to the clients when they access a file.&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
The MDS is also ultimately responsible for deleting objects on the OSTs, either by passing object information for destroy to the client removing the last link or open reference on a file and having the client do it, or by destroying the objects on the OSTs itself in case the client fails to do so.&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
In the 1.8 and later releases, the functionality provided by the MDS code has been split into multiple parts ([https://wikis.clusterfs.com/intra/index.php/Mdt_summary MDT], [https://wikis.clusterfs.com/intra/index.php/Mdd_summary MDD], OSD) in order to allow stacking of the metadata devices for clustered metadata.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Code&#039;&#039;&#039; &lt;br /&gt;
 lustre/mds/commit_confd.c&lt;br /&gt;
 lustre/mds/handler.c            - RPC request handler&lt;br /&gt;
 lustre/mds/lproc_mds.c          - /proc interface for stats/control&lt;br /&gt;
 lustre/mds/mds_fs.c             - Mount/configuration of underlying filesystem&lt;br /&gt;
 lustre/mds/mds_internal.h       - Header for internal declarations&lt;br /&gt;
 lustre/mds/mds_join.c           - Handle join_file operations&lt;br /&gt;
 lustre/mds/mds_lib.c            - Unpack of wire structs from requests&lt;br /&gt;
 lustre/mds/mds_log.c            - Lustre log interface (llog) for unlink/setattr&lt;br /&gt;
 lustre/mds/mds_lov.c            - Interface to LOV for create and orphan&lt;br /&gt;
 lustre/mds/mds_open.c           - File open/close handling&lt;br /&gt;
 lustre/mds/mds_reint.c          - Reintegration of changes made by clients&lt;br /&gt;
 lustre/mds/mds_unlink_open.c    - Handling of open-unlinked files (PENDING dir)&lt;br /&gt;
 lustre/mds/mds_xattr.c          - User-extended attribute handling&lt;br /&gt;
&lt;br /&gt;
==MDT==&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Summary&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
MDT stands for MetaData Target. This is a top-most layer in the MD server device stack. Responsibility of MDT are all this networking, as far as meta-data are concerned:&lt;br /&gt;
&lt;br /&gt;
* Managing PTLRPC services and threads;&lt;br /&gt;
* Receiving incoming requests, unpacking them and checking their validity;&lt;br /&gt;
* Sending replies;&lt;br /&gt;
* Handling recovery;&lt;br /&gt;
* Using DLM to guarantee cluster-wide meta-data consistency;&lt;br /&gt;
* Handling intents;&lt;br /&gt;
* Handling credential translation. &lt;br /&gt;
&lt;br /&gt;
Theoretically MDT is an optional layer: completely local Lustre setup, with single mete-data server, and locally mounted client can exist without MDT (and still use networking for non-metadata access). &lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Code&#039;&#039;&#039;&lt;br /&gt;
 lustre/mdt/mdt.mod.c&lt;br /&gt;
 lustre/mdt/mdt_capa.c&lt;br /&gt;
 lustre/mdt/mdt_handler.c&lt;br /&gt;
 lustre/mdt/mdt_identity.c&lt;br /&gt;
 lustre/mdt/mdt_idmap.c&lt;br /&gt;
 lustre/mdt/mdt_internal.h&lt;br /&gt;
 lustre/mdt/mdt_lib.c&lt;br /&gt;
 lustre/mdt/mdt_lproc.c&lt;br /&gt;
 lustre/mdt/mdt_open.c&lt;br /&gt;
 lustre/mdt/mdt_recovery.c&lt;br /&gt;
 lustre/mdt/mdt_reint.c&lt;br /&gt;
 lustre/mdt/mdt_xattr.c&lt;br /&gt;
&lt;br /&gt;
==CMM== &lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Summary&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Overview&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
The CMM is a new layer in the MDS which cares about all clustered metadata issues and relationships. The CMM does the following:&lt;br /&gt;
&lt;br /&gt;
* Acts as layer between the MDT and MDD.&lt;br /&gt;
* Provides MDS-MDS interaction.&lt;br /&gt;
* Queries and updates FLD.&lt;br /&gt;
* Does the local or remote operation if needed.&lt;br /&gt;
* Will do rollback - epoch control, undo logging. &lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;CMM functionality&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
CMM chooses all servers involved in operation and sends depended request if needed. The calling of remote MDS is a new feature related to the CMD. CMM mantain the list of MDC to connect with all other MDS.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Objects&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
The CMM can allocate two types of object - local and remote. Remote object can occur during metadata operations with more than one object involved. Such operation is called as cross-ref operation. &lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Code&#039;&#039;&#039; &lt;br /&gt;
 lustre/cmm&lt;br /&gt;
&lt;br /&gt;
==MDD== &lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Summary&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
MDD is metadata layer in the new MDS stack, which is the only layer operating the metadata in MDS. The implementation is similar as VFS meta operation but based on OSD storage. MDD API is currently only used in new MDS stack, called by CMM layer.&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
In theory, MDD should be local metadata layer, but for compatibility with old MDS stack and reuse some mds codes(llog and lov), a mds device is created and connected to the mdd. So the llog and lov in mdd still use original code through this temporary mds device. And it will be removed when the new llog and lov layer in the new MDS stack are implemented. &lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Code&#039;&#039;&#039;&lt;br /&gt;
 lustre/lustre/mdd/&lt;br /&gt;
&lt;br /&gt;
==recovery==&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Summary&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Overview&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Client recovery starts in case when no server reply is received within given timeout or when server tells to client that it is not connected (client was evicted on server earlier for whatever reason).&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
The recovery consists of trying to connect to server and then step through several recovery states during which various client-server data is synchronized, namely all requests that were already sent to server but not yet confirmed as received and DLM locks. Should any problems arise during recovery process (be it a timeout or server’s refuse to recognise client again), the recovery is restarted from the very beginning.&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
During recovery all new requests to the server are not sent to the server, but added to special delayed requests queue that is then sent once if recovery completes succesfully.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Replay and Resend&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
* Clients will go through all the requests in the sending and replay lists and determine the recovery action needed - replay request, resend request, cleanup up associated state for committed requests.&lt;br /&gt;
* The client replays requests which were not committed on the server, but for which the client saw reply from server before it failed. This allows the server to replay the changes to the persistent store.&lt;br /&gt;
* The client resends requests that were committed on the server, but the client did not see a reply for them, maybe due to server failure or network failure that caused the reply to be lost. This allows the server to reconstruct the reply and send it to the client.&lt;br /&gt;
* The client resends requests that the server has not seen at all, these would be all requests with transid higher than the last_rcvd value from the server and the last_committed transno, and the reply seen flag is not set.&lt;br /&gt;
* The client gets the last_committed transno information from the server and cleans up the state associated with requests that were committed on the server. &lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Code&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Recovery code is scattered through all code almost. Though important code:&lt;br /&gt;
 ldlm/ldlm_lib.c    - generic server recovery code &lt;br /&gt;
 ptlrpc/            - client recovery code&lt;br /&gt;
&lt;br /&gt;
==version recovery== &lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Summary&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Version Based Recovery&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
This recovery technique is based on using versions of objects (inodes) to allow clients to recover later than ordinary server recovery timeframe.&lt;br /&gt;
&lt;br /&gt;
# The server changes the version of object during any change and return that data to client. The version may be checked during replay to be sure that object is the same state during replay as it was originally.&lt;br /&gt;
# After failure the server starts recovery as usual but if some client miss the version check will be used for replays.&lt;br /&gt;
# Missed client can connect later and try to recover. This is &#039;delayed recovery&#039; and version check is used during it always.&lt;br /&gt;
# The client which missed main recovery window will not be evicted and can connect later to initiate recovery. In that case the versions will checked to determine was that object changed by someone else or not.&lt;br /&gt;
# When finished with replay, client and server check if any replay failed on any request because of version mismatch. If not, the client will get a successful reintegration message. If a version mismatch was encountered, the client must be evicted.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Code&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Recovery code is scattered through all code almost. Though important code:&lt;br /&gt;
 ldlm/ldlm_lib.c    - generic server recovery code &lt;br /&gt;
 ptlrpc/            - client recovery code&lt;br /&gt;
&lt;br /&gt;
==IAM== &lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Summary&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
IAM stands for &#039;Index Access Module&#039;: it is an extension to the ldiskfs directory code, adding generic indexing capability.&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
File system directory can be thought of as an index mapping keys, which are strings (file names), to the records which are integers (inode numbers). IAM removes limitations on key and record size and format, providing an abstraction of a transactional container, mapping arbitrary opaque keys into opaque records.&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
Implementation notes:&lt;br /&gt;
&lt;br /&gt;
* IAM is implemented as a set of patches to the ldiskfs;&lt;br /&gt;
* IAM is an extension of ldiskfs directory code that uses htree data-structure for scalable indexing;&lt;br /&gt;
* IAM uses fine-grained key-level and node-level locking (pdirops locking, designed and implemented by Alex Tomas);&lt;br /&gt;
* IAM doesn&#039;t assume any internal format keys. Keys are compared by memcmp() function (which dictates BE order for scalars);&lt;br /&gt;
* IAM supports different flavors of containers:&lt;br /&gt;
** lfix: fixed size record and fixed size keys,&lt;br /&gt;
** lvar: variable sized records and keys,&lt;br /&gt;
** htree: compatibility mode, allowing normal htree directory to be accessed as an IAM container; &lt;br /&gt;
* IAM comes with ioctl(2) based user-level interface. &lt;br /&gt;
&lt;br /&gt;
IAM is used by ldiskfs-OSD to implement dt_index_operations interface. &lt;br /&gt;
&amp;lt;/blockquote&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Code&#039;&#039;&#039;&lt;br /&gt;
 lustre/ldiskfs/kernel_patches/patches/ext3-iam-2.6-sles10.patch&lt;br /&gt;
 lustre/ldiskfs/kernel_patches/patches/ext3-iam-ops.patch&lt;br /&gt;
 lustre/ldiskfs/kernel_patches/patches/ext3-iam-2.6.18-rhel5.patch&lt;br /&gt;
 lustre/ldiskfs/kernel_patches/patches/ext3-iam-rhel4.patch&lt;br /&gt;
 lustre/ldiskfs/kernel_patches/patches/ext3-iam-2.6.18-vanilla.patch&lt;br /&gt;
 lustre/ldiskfs/kernel_patches/patches/ext3-iam-separate.patch&lt;br /&gt;
 lustre/ldiskfs/kernel_patches/patches/ext3-iam-2.6.9-rhel4.patch&lt;br /&gt;
 lustre/ldiskfs/kernel_patches/patches/ext3-iam-sles10.patch&lt;br /&gt;
 lustre/ldiskfs/kernel_patches/patches/ext3-iam-common.patch&lt;br /&gt;
 lustre/ldiskfs/kernel_patches/patches/ext3-iam-uapi.patch&lt;br /&gt;
&lt;br /&gt;
==SOM== &lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Summary&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Size-on-MDS is a metadata improvement, which includes the caching of the inode size, blocks, ctime and mtime on MDS. Such an attribute caching allows clients to avoid making RPCs to the OSTs to find the attributes encoded in the file objects kept on those OSTs what results in the significantly improved performance of listing directories.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Code&#039;&#039;&#039;&lt;br /&gt;
 llite/llite_close.c       - client-side SOM code&lt;br /&gt;
 liblustre/file.c          - liblustre SOM code&lt;br /&gt;
 mdt/mdt_handler.c         - general handling of SOM-related rpc&lt;br /&gt;
 mdt/mdt_open.c            - MDS side SOM code &lt;br /&gt;
 mdt/mdt_recovery.c        - MDS side SOM recovery code&lt;br /&gt;
 obdfilter/filter_log.c    - OST side IO epoch lloging code;&lt;br /&gt;
&lt;br /&gt;
==tests== &lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Summary&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
The &amp;quot;tests&amp;quot; subsystem is a set of scripts and programs which is used to test other lustre subsystems. It contains:&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;&#039;&#039;runtests&#039;&#039;&#039;&#039;&#039;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
Simple basic regression test&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&#039;&#039;&#039;&#039;&#039;sanity&#039;&#039;&#039;&#039;&#039;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
A set of regression tests that verify operation under normal operating &lt;br /&gt;
conditions&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&#039;&#039;&#039;&#039;&#039;fsx&#039;&#039;&#039;&#039;&#039;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
file system exerciser&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&#039;&#039;&#039;&#039;&#039;sanityn&#039;&#039;&#039;&#039;&#039;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
Tests that verify operations from two clients under normal operating conditions&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&#039;&#039;&#039;&#039;&#039;lfsck&#039;&#039;&#039;&#039;&#039;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
Tests e2fsck and lfsck to detect and fix filesystem corruption&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&#039;&#039;&#039;&#039;&#039;liblustre&#039;&#039;&#039;&#039;&#039;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
Runs a test linked to a liblustre client library&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&#039;&#039;&#039;&#039;&#039;replay-single&#039;&#039;&#039;&#039;&#039;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
A set of unit tests that verify recovery after MDS failure&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&#039;&#039;&#039;&#039;&#039;conf-sanity&#039;&#039;&#039;&#039;&#039;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
A set of unit tests that verify the configuration&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&#039;&#039;&#039;&#039;&#039;recovery-small&#039;&#039;&#039;&#039;&#039;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
A set of unit tests that verify RPC replay after communications failure&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&#039;&#039;&#039;&#039;&#039;replay-ost-single&#039;&#039;&#039;&#039;&#039;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
A set of unit tests that verify recovery after OST failure&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&#039;&#039;&#039;&#039;&#039;replay-dual&#039;&#039;&#039;&#039;&#039;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
A set of unit tests that verify the recovery from two clients after server failure&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&#039;&#039;&#039;&#039;&#039;insanity&#039;&#039;&#039;&#039;&#039;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
A set of tests that verify the multiple concurrent failure conditions&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&#039;&#039;&#039;&#039;&#039;sanity-quota&#039;&#039;&#039;&#039;&#039;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
A set of tests that verify filesystem quotas&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
The acceptance-small.sh is a wrapper which is normally used to run all (or any) of these scripts. In additional it is used to run the following pre-installed benchmarks:&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&#039;&#039;&#039;&#039;&#039;dbench&#039;&#039;&#039;&#039;&#039;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
Dbench benchmark for simulating N clients to produce the filesystem load&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&#039;&#039;&#039;&#039;&#039;bonnie&#039;&#039;&#039;&#039;&#039;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
Bonnie++ benchmark for creation, reading, and deleting many small files&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&#039;&#039;&#039;&#039;&#039;iozone&#039;&#039;&#039;&#039;&#039;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
Iozone benchmark for generating and measuring a variety of file operations.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Code&#039;&#039;&#039;&lt;br /&gt;
 lustre/tests/acl/run&lt;br /&gt;
 lustre/tests/acl/make-tree&lt;br /&gt;
 lustre/tests/acl/README&lt;br /&gt;
 lustre/tests/acl/setfacl.test&lt;br /&gt;
 lustre/tests/acl/getfacl-noacl.test&lt;br /&gt;
 lustre/tests/acl/permissions.test&lt;br /&gt;
 lustre/tests/acl/inheritance.test&lt;br /&gt;
 lustre/tests/acl/misc.test&lt;br /&gt;
 lustre/tests/acl/cp.test&lt;br /&gt;
 lustre/tests/cfg/local.sh&lt;br /&gt;
 lustre/tests/cfg/insanity-local.sh&lt;br /&gt;
 lustre/tests/ll_sparseness_write.c&lt;br /&gt;
 lustre/tests/writeme.c&lt;br /&gt;
 lustre/tests/cobd.sh&lt;br /&gt;
 lustre/tests/test_brw.c&lt;br /&gt;
 lustre/tests/ll_getstripe_info.c&lt;br /&gt;
 lustre/tests/lov-sanity.sh&lt;br /&gt;
 lustre/tests/sleeptest.c&lt;br /&gt;
 lustre/tests/flocks_test.c&lt;br /&gt;
 lustre/tests/getdents.c&lt;br /&gt;
 lustre/tests/ll_dirstripe_verify.c&lt;br /&gt;
 lustre/tests/sanity.sh&lt;br /&gt;
 lustre/tests/multifstat.c&lt;br /&gt;
 lustre/tests/sanityN.sh&lt;br /&gt;
 lustre/tests/liblustre_sanity_uml.sh&lt;br /&gt;
 lustre/tests/fsx.c&lt;br /&gt;
 lustre/tests/small_write.c&lt;br /&gt;
 lustre/tests/socketserver&lt;br /&gt;
 lustre/tests/cmknod.c&lt;br /&gt;
 lustre/tests/README&lt;br /&gt;
 lustre/tests/acceptance-metadata-double.sh&lt;br /&gt;
 lustre/tests/writemany.c&lt;br /&gt;
 lustre/tests/llecho.sh&lt;br /&gt;
 lustre/tests/lfscktest.sh&lt;br /&gt;
 lustre/tests/run-llog.sh&lt;br /&gt;
 lustre/tests/conf-sanity.sh&lt;br /&gt;
 lustre/tests/mmap_sanity.c&lt;br /&gt;
 lustre/tests/write_disjoint.c&lt;br /&gt;
 lustre/tests/ldaptest.c&lt;br /&gt;
 lustre/tests/acceptance-metadata-single.sh&lt;br /&gt;
 lustre/tests/compile.sh&lt;br /&gt;
 lustre/tests/mcreate.c&lt;br /&gt;
 lustre/tests/runas.c&lt;br /&gt;
 lustre/tests/replay-single.sh&lt;br /&gt;
 lustre/tests/lockorder.sh&lt;br /&gt;
 lustre/tests/test2.c&lt;br /&gt;
 lustre/tests/llog-test.sh&lt;br /&gt;
 lustre/tests/fchdir_test.c&lt;br /&gt;
 lustre/tests/mkdirdeep.c&lt;br /&gt;
 lustre/tests/runtests&lt;br /&gt;
 lustre/tests/flock.c&lt;br /&gt;
 lustre/tests/mlink.c&lt;br /&gt;
 lustre/tests/checkstat.c&lt;br /&gt;
 lustre/tests/crash-mod.sh&lt;br /&gt;
 lustre/tests/multiop.c&lt;br /&gt;
 lustre/tests/random-reads.c&lt;br /&gt;
 lustre/tests/disk1_4.zip&lt;br /&gt;
 lustre/tests/rundbench&lt;br /&gt;
 lustre/tests/wantedi.c&lt;br /&gt;
 lustre/tests/rename_many.c&lt;br /&gt;
 lustre/tests/leak_finder.pl&lt;br /&gt;
 lustre/tests/Makefile.am&lt;br /&gt;
 lustre/tests/parallel_grouplock.c&lt;br /&gt;
 lustre/tests/chownmany.c&lt;br /&gt;
 lustre/tests/ost_oos.sh&lt;br /&gt;
 lustre/tests/mkdirmany.c&lt;br /&gt;
 lustre/tests/directio.c&lt;br /&gt;
 lustre/tests/insanity.sh&lt;br /&gt;
 lustre/tests/createmany-mpi.c&lt;br /&gt;
 lustre/tests/createmany.c&lt;br /&gt;
 lustre/tests/runiozone&lt;br /&gt;
 lustre/tests/rmdirmany.c&lt;br /&gt;
 lustre/tests/replay-ost-single.sh&lt;br /&gt;
 lustre/tests/mcr.sh&lt;br /&gt;
 lustre/tests/mrename.c&lt;br /&gt;
 lustre/tests/sanity-quota.sh&lt;br /&gt;
 lustre/tests/lp_utils.c&lt;br /&gt;
 lustre/tests/lp_utils.h&lt;br /&gt;
 lustre/tests/acceptance-metadata-parallel.sh&lt;br /&gt;
 lustre/tests/oos.sh&lt;br /&gt;
 lustre/tests/createdestroy.c&lt;br /&gt;
 lustre/tests/toexcl.c&lt;br /&gt;
 lustre/tests/replay-dual.sh&lt;br /&gt;
 lustre/tests/createtest.c&lt;br /&gt;
 lustre/tests/munlink.c&lt;br /&gt;
 lustre/tests/iopentest1.c&lt;br /&gt;
 lustre/tests/iopentest2.c&lt;br /&gt;
 lustre/tests/openme.c&lt;br /&gt;
 lustre/tests/openclose.c&lt;br /&gt;
 lustre/tests/test-framework.sh&lt;br /&gt;
 lustre/tests/ll_sparseness_verify.c&lt;br /&gt;
 lustre/tests/it_test.c&lt;br /&gt;
 lustre/tests/unlinkmany.c&lt;br /&gt;
 lustre/tests/opendirunlink.c&lt;br /&gt;
 lustre/tests/filter_survey.sh&lt;br /&gt;
 lustre/tests/utime.c&lt;br /&gt;
 lustre/tests/openunlink.c&lt;br /&gt;
 lustre/tests/runvmstat&lt;br /&gt;
 lustre/tests/statmany.c&lt;br /&gt;
 lustre/tests/create.pl&lt;br /&gt;
 lustre/tests/oos2.sh&lt;br /&gt;
 lustre/tests/statone.c&lt;br /&gt;
 lustre/tests/rename.pl&lt;br /&gt;
 lustre/tests/set_dates.sh&lt;br /&gt;
 lustre/tests/openfilleddirunlink.c&lt;br /&gt;
 lustre/tests/openfile.c&lt;br /&gt;
 lustre/tests/llmountcleanup.sh&lt;br /&gt;
 lustre/tests/llmount.sh&lt;br /&gt;
 lustre/tests/acceptance-small.sh&lt;br /&gt;
 lustre/tests/truncate.c&lt;br /&gt;
 lustre/tests/recovery-small.sh&lt;br /&gt;
 lustre/tests/2ost.sh&lt;br /&gt;
 lustre/tests/tchmod.c&lt;br /&gt;
 lustre/tests/socketclient&lt;br /&gt;
 lustre/tests/runobdstat&lt;br /&gt;
 lustre/tests/memhog.c&lt;br /&gt;
 lustre/tests/flock_test.c&lt;br /&gt;
 lustre/tests/busy.sh&lt;br /&gt;
 lustre/tests/write_append_truncate.c&lt;br /&gt;
 lustre/tests/opendevunlink.c&lt;br /&gt;
 lustre/tests/o_directory.c&lt;br /&gt;
&lt;br /&gt;
==build== &lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Summary&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
The build system is responsible for building Lustre and related components (ldiskfs is normally included in the Lustre tree but can also live completely separately).&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
The main build process is managed using GNU Autoconf and Automake. Here is a brief outline of how a Lustre binary build from a fresh Git checkout works. User commands are shown in &#039;&#039;&#039;bold&#039;&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;sh autogen.sh&#039;&#039;&#039; - autogen performs a few checks and bootstraps the build system using automake and autoconf. It should only need to be called once for a fresh Git clone, but sometimes it needs to be run again. See [https://bugzilla.lustre.org/show_bug.cgi?id=12580 bug 12580].&lt;br /&gt;
**Each component (Lustre and ldiskfs) has an autoMakefile.am in its toplevel directory that sets some variables and includes build/autoMakefile.am.toplevel. It also contains any toplevel autoMake code unique to that component.&lt;br /&gt;
** configure.ac is used by autoconf to generate a configure script. The Lustre configure.ac mostly relies on the macros defined in */autoconf/*.m4 to do its work. The ldiskfs configure.ac is more self-contained and relies only on build/autoconf/*.m4. &lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;./configure --with-linux=/root/cfs/kernels/linux-2.6.9-55.EL.HEAD&#039;&#039;&#039; - Configure performs extensive checks of the underlying system and kernel, then produces autoMakefiles and Makefiles. &lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;make&#039;&#039;&#039; - This is where things get really interesting.&lt;br /&gt;
** The @INCLUDE_RULES@ directive in most Makefile.in files includes a whole set of build rules from build/Makefile. See the top of that file for a description of all cases.&lt;br /&gt;
** Normally, it will include autoMakefile, so commands from that file will run.&lt;br /&gt;
** build/autoMakefile.am.toplevel is the basis of the autoMakefile produced in the toplevel directory. It includes the &amp;quot;modules&amp;quot; target.&lt;br /&gt;
** The modules target in turn calls the appropriate Linux make system if we are building on Linux.&lt;br /&gt;
** This build system once again reads the Makefile in each directory, and case 2 from build/Makefile is followed. &lt;br /&gt;
&lt;br /&gt;
So essentially, the Makefile.in controls the kernel build process, and the autoMakefile.am controls the userland build process as well as preparing the sources if necessary.&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
The build system can also be used to produce Lustre-patched kernels and binaries built against these kernels. The &#039;&#039;&#039;build/lbuild&#039;&#039;&#039; script does this - this is used by customers as well as the LTS. This script is in need of some serious cleanup, unfortunately.&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
Coding style note: as mentioned in [http://wiki.lustre.org/index.php?title=Coding_Guidelines Coding Guidelines], autoconf macros must follow the style specified in the [http://www.gnu.org/software/autoconf/manual/html_node/Coding-Style.html GNU Autoconf manual]. A lot of the older code has inconsistent style and is hard to follow - feel free to reformat when needed. New code &#039;&#039;&#039;must&#039;&#039;&#039; be styled correctly. &lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Code&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Lustre build system:&lt;br /&gt;
&lt;br /&gt;
* build/* (shared with ldiskfs)&lt;br /&gt;
* autogen.sh&lt;br /&gt;
* autoMakefile.am&lt;br /&gt;
* configure.ac&lt;br /&gt;
* lustre.spec.in&lt;br /&gt;
* Makefile.in&lt;br /&gt;
* all autoMakefile.am files&lt;br /&gt;
* all Makefile.in files &lt;br /&gt;
&lt;br /&gt;
ldiskfs build system:&lt;br /&gt;
&lt;br /&gt;
* build/* (shared with Lustre)&lt;br /&gt;
* autogen.sh&lt;br /&gt;
* autoMakefile.am&lt;br /&gt;
* configure.ac&lt;br /&gt;
* lustre-ldiskfs.spec.in&lt;br /&gt;
* Makefile.in&lt;br /&gt;
* all autoMakefile.am files&lt;br /&gt;
* all Makefile.in files&lt;/div&gt;</summary>
		<author><name>Nathan</name></author>
	</entry>
	<entry>
		<id>http://wiki.old.lustre.org/index.php?title=Subsystem_Map&amp;diff=9066</id>
		<title>Subsystem Map</title>
		<link rel="alternate" type="text/html" href="http://wiki.old.lustre.org/index.php?title=Subsystem_Map&amp;diff=9066"/>
		<updated>2009-12-15T22:36:38Z</updated>

		<summary type="html">&lt;p&gt;Nathan: /* build */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;The Lustre subsystems are listed below. For each subsystem, a summary description and code is provided.&lt;br /&gt;
&lt;br /&gt;
==libcfs==&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Summary&#039;&#039;&#039;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
Libcfs provides an API comprising fundamental primitives and subsystems - e.g. process management and debugging support which is used throughout LNET, Lustre, and associated utilities. This API defines a portable runtime environment that is implemented consistently on all supported build targets.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Code&#039;&#039;&#039;&lt;br /&gt;
 lustre/lnet/libcfs/**/*.[ch]&lt;br /&gt;
&lt;br /&gt;
==lnet==&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Summary&#039;&#039;&#039;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
See the [http://www.sun.com/software/products/lustre/docs/Lustre-networking.pdf Lustre Networking] white paper for details. &lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Code&#039;&#039;&#039;&lt;br /&gt;
 lustre/lnet/**/*.[ch]&lt;br /&gt;
&lt;br /&gt;
==ptlrpc==&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Summary&#039;&#039;&#039;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
Ptlrpc implements Lustre communications over LNET.&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
All communication between Lustre processes are handled by RPCs, in which a request is sent to an advertised service, and the service processes the request and returns a reply. Note that a service may be offered by any Lustre process - e.g. the OST service on an OSS processes I/O requests and the AST service on a client processes notifications of lock conflicts.&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
The initial request message of an RPC is special - it is received into the first available request buffer at the destination. All other communications involved in an RPC are like RDMAs - the peer targets them specifically. For example, in a bulk read, the OSC posts reply and bulk buffers and sends descriptors for them (the LNET matchbits used to post them) in the RPC request. After the server has received the request, it GETs or PUTs the bulk data and PUTs the RPC reply directly.&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
Ptlrpc ensures all resources involved in an RPC are freed in finite time. If the RPC does not complete within a timeout, all buffers associated with the RPC must be unlinked. These buffers are still accessible to the network until their completion events have been delivered.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Code&#039;&#039;&#039;&lt;br /&gt;
 lustre/ptlrpc/*.[ch]&lt;br /&gt;
 lustre/ldlm/ldlm_lib.c&lt;br /&gt;
&lt;br /&gt;
==llog==&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Summary&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Overview&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
LLog is the generic logging mechanism in Lustre. It allows Lustre to store records in an appropriate format and access them later using a reasonable API.&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
LLog is used is various cases. The main LLog use cases are the following:&lt;br /&gt;
&lt;br /&gt;
* mountconf - entire cluster configuration is stored on the MGS in a special configuration llog. A client may access it via an llog API working over ptlrpc; &lt;br /&gt;
&lt;br /&gt;
* MDS_OST llog - contains records for unlink and setattr operations, performed on the MDS in the last, not committed transaction. This is needed to preserve consistency between MDS and OST nodes for failure cases. General case: If the MDS does not have an inode for some file, then the OST also should not have object for the same file. So, when the OST fails in the middle of unlink and loses the last transaction containing unlink for the OST object, this may cause the object to be lost on the OST. On the MDS, the current transaction with the unlinked object has finished and the MDS has no inode for the file. This means that the file cannot be accessed later and it just eats up space on the OST. The solution is to maintain the unlink log on the MDS and process it at MDS-OST connect time to make sure the OST has all objects unlinked; &lt;br /&gt;
&lt;br /&gt;
* Size llog - this is not yet used, but is planned to log object size changes on the OST so the MDS can later check if it has object size coherence with the MDS (SOM case); &lt;br /&gt;
&lt;br /&gt;
* LOVEA llog - joins the file LOV EA merge log. &lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;General design&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Each llog type has two main parts:&lt;br /&gt;
&lt;br /&gt;
* ORIG llog - &amp;quot;server&amp;quot; part, the site where llog records are stored. It provides an API for local and/or network llog access (read, modify). Examples of ORIG logs: MDS is orig for MDS_OST llog and MGS is orig for config logs; &lt;br /&gt;
&lt;br /&gt;
* REPL llog - &amp;quot;client&amp;quot; part, the site where llog records may be used. Examples of REPL logs: OST is repl for MDS_OST llog and MGC is repl for config logs.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Code&#039;&#039;&#039;&lt;br /&gt;
 obdclass/llog.c&lt;br /&gt;
 obdclass/llog_cat.c&lt;br /&gt;
 obdclass/llog_lvfs.c&lt;br /&gt;
 obdclass/llog_obd.c&lt;br /&gt;
 obdclass/llog_swab.c&lt;br /&gt;
 obdclass/llog_test.c&lt;br /&gt;
 lov/lov_log.c&lt;br /&gt;
 ptlrpc/llog_client.c&lt;br /&gt;
 ptlrpc/llog_server.c&lt;br /&gt;
 ptlrpc/llog_net.c&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
For more information, see [[Logging API]].&lt;br /&gt;
&lt;br /&gt;
==obdclass==&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Summary&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
The obdclass code is generic Lustre configuration and device handling. Different functional parts of the Lustre code are split into obd devices which can be configured and connected in various ways to form a server or client filesystem.&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
Several examples of obd devices include:&lt;br /&gt;
&lt;br /&gt;
* OSC - object storage client (connects over network to OST)&lt;br /&gt;
* OST - object storage target&lt;br /&gt;
* LOV - logical object volume (aggregates multipe OSCs into a single virtual device)&lt;br /&gt;
* MDC - meta data client (connects over network to MDT)&lt;br /&gt;
* MDT - meta data target &lt;br /&gt;
&lt;br /&gt;
The obdclass code provides services used by all Lustre devices for configuration, memory allocation, generic hashing, kernel interface routines, random number generation, etc. &lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Code&#039;&#039;&#039;&lt;br /&gt;
 lustre/obdclass/class_hash.c        - scalable hash code for imports&lt;br /&gt;
 lustre/obdclass/class_obd.c         - base device handling code&lt;br /&gt;
 lustre/obdclass/debug.c             - helper routines for dumping data structs&lt;br /&gt;
 lustre/obdclass/genops.c            - device allocation/configuration/connection&lt;br /&gt;
 lustre/obdclass/linux-module.       - linux kernel module handling&lt;br /&gt;
 lustre/obdclass/linux-obdo.c        - pack/unpack obdo and other IO structs&lt;br /&gt;
 lustre/obdclass/linux-sysctl.c      - /proc/sys configuration parameters &lt;br /&gt;
 lustre/obdclass/lprocfs_status.c    - /proc/fs/lustre configuration/stats, helpers&lt;br /&gt;
 lustre/obdclass/lustre_handles.c    - wire opaque pointer handlers&lt;br /&gt;
 lustre/obdclass/lustre_peer.c       - peer target identification by UUID&lt;br /&gt;
 lustre/obdclass/obd_config.c        - configuration file parsing&lt;br /&gt;
 lustre/obdclass/obd_mount.c         - server filesystem mounting&lt;br /&gt;
 lustre/obdclass/obdo.c              - more obdo handling helpers&lt;br /&gt;
 lustre/obdclass/statfs_pack.c       - statfs helpers for wire pack/unpack&lt;br /&gt;
 lustre/obdclass/uuid.c              - UUID pack/unpack&lt;br /&gt;
 lustre/lvfs/lvfs_common.c           - kernel interface helpers&lt;br /&gt;
 lustre/lvfs/lvfs_darwin.c           - darwin kernel helper routines&lt;br /&gt;
 lustre/lvfs/lvfs_internal.h         - lvfs internal function prototypes&lt;br /&gt;
 lustre/lvfs/lvfs_lib.c              - statistics&lt;br /&gt;
 lustre/lvfs/lvfs_linux.c            - linux kernel helper routines&lt;br /&gt;
 lustre/lvfs/lvfs_userfs.c           - userspace helper routines&lt;br /&gt;
 lustre/lvfs/prng.c                  - long period pseudo-random number generator&lt;br /&gt;
 lustre/lvfs/upcall_cache.c          - supplementary group upcall for MDS&lt;br /&gt;
&lt;br /&gt;
==luclass==&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Summary&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
luclass is a body of data-type definitions and functions implementing support for a layered object, that is an entity where every layer in the Lustre device stack (both data and meta-data, and both client and server side) can maintain its own private state, and modify a behavior of a compound object in a systematic way.&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
Specifically, data-types are introduced, representing a device type (struct lu_device_type, layer in the Lustre stack), a device (struct lu_device, a specific instance of the type), and object (struct lu_object). Following lu_object functionality is implemented by a generic code:&lt;br /&gt;
&lt;br /&gt;
* Compound object is uniquely identified by a FID, and is stored in a hash table, indexed by a FID; &lt;br /&gt;
&lt;br /&gt;
* Objects are kept in a LRU list, and a method to purge least recently accessed objects in reaction to the memory pressure is provided; &lt;br /&gt;
&lt;br /&gt;
* Objects are reference counted, and cached; &lt;br /&gt;
&lt;br /&gt;
* Every object has a list of &#039;&#039;layers&#039;&#039; (also known as slices), where devices can store their private state. Also, every slice comes with a pointer to an operations vector, allowing device to modify object&#039;s behavior. &lt;br /&gt;
&lt;br /&gt;
In addition to objects and devices, luclass includes lu_context, which is a way to efficiently allocate space, without consuming stack space.&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
luclass design is specified in the [http://arch.lustre.org/images/a/aa/Md-api-dld.pdf MD API] DLD.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Code&#039;&#039;&#039;&lt;br /&gt;
 include/lu_object.h&lt;br /&gt;
 obdclass/lu_object.c&lt;br /&gt;
&lt;br /&gt;
==ldlm==&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Summary&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
The Lustre Distributed Lock Manager (LDLM) is the Lustre locking infrastructure; it handles locks between clients and servers and locks local to a node. Different kinds of locks are available with different properties. Also as a historic heritage, ldlm happens to have some of the generic connection service code (both server and client).&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Code&#039;&#039;&#039; &lt;br /&gt;
 interval_tree.c           - This is used by extent locks to maintain interval trees (bug 11300)&lt;br /&gt;
 l_lock.c                  - Resourse locking primitives. &lt;br /&gt;
 ldlm_extent.c             - Extents locking code used for locking regions inside objects&lt;br /&gt;
 ldlm_flock.c              - Bsd and posix locking lock types&lt;br /&gt;
 ldlm_inodebits.c          - Inodebis locks used for metadata locking&lt;br /&gt;
 ldlm_lib.c                - Target and client connecting/reconnecting/recovery code.&lt;br /&gt;
                             Does not really belong to ldlm, but is historically placed &lt;br /&gt;
                             there. Should be in ptlrpc instead.&lt;br /&gt;
 ldlm_lock.c               - This source file mostly has functions dealing with struct&lt;br /&gt;
 ldlm_lock ldlm_lockd.c    - Functions that imply replying to incoming lock-related rpcs &lt;br /&gt;
                             (that could be both on server (lock enq/cancel/...) and client &lt;br /&gt;
                             (ast handling)).&lt;br /&gt;
 ldlm_plain.c              - Plain locks, predecessor to inodebits locks; not widely used now.&lt;br /&gt;
 ldlm_pool.c               - Pools of locks, related to dynamic lrus and freeing locks on demand.&lt;br /&gt;
 ldlm_request.c            - Collection of functions to work with locks based handles as opposed &lt;br /&gt;
                             to lock structures themselves.&lt;br /&gt;
 ldlm_resource.c           - Functions operating on namespaces and lock resources.&lt;br /&gt;
 include/lustre_dlm.h      - Important defines and declarations for ldlm.&lt;br /&gt;
&lt;br /&gt;
==fids==&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Summary&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
FID is unique object identifier in cluster since 1.7. It has few properties, main of them are the following:&lt;br /&gt;
&lt;br /&gt;
* FID is unique and not reused object identifier;&lt;br /&gt;
* FID is allocated by client inside of the sequence granted by server;&lt;br /&gt;
* FID is base for ldlm resource used for issuing ldlm locks. This is because FID is unique and as such good for this using;&lt;br /&gt;
* FID is base for building client side inode numbers as we can&#039;t use server inode+generation anymore, in CMD this is not unique combination;&lt;br /&gt;
* FID does not contain store information like inode number or generation and as such easy to migrate; &lt;br /&gt;
&lt;br /&gt;
FID consists of 3 fields:&lt;br /&gt;
&lt;br /&gt;
* f_seq - sequence number&lt;br /&gt;
* f_oid - object identifier inside sequence&lt;br /&gt;
* f_ver - object version &lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Code&#039;&#039;&#039;&lt;br /&gt;
 fid/fid_request.c&lt;br /&gt;
 fid/fid_lib.c&lt;br /&gt;
 fld/*.[ch]&lt;br /&gt;
&lt;br /&gt;
==seq==&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Summary&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Overview&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Sequence management is a basic mechanism in new MDS server which is related to managing FIDs.&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
FID is an unique object identifier in Lustre starting from version 1.7. All FIDs are organized into sequences. One sequence is number of FIDs. Sequences are granted/allocated to clients by servers. FIDs are allocated by clients inside granted sequence. All FIDs inside one sequence live on same MDS server and as such are one &amp;quot;migration unit&amp;quot; and one &amp;quot;indexing unit&amp;quot;, meaning that FLD (FIDs Location Database) indexes them all using one sequence and thus has only one mapping entry for all FIDs in sequence. Please read section devoted to FIDs bellow in the root table to find more info on FLD service and FIDs.&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
A sequence has the limit of FIDs to be allocated in it. When this limit is reached, new sequence is allocated. Upon disconnect, server allocates new sequence to the client when it comes back. Previously used sequence is abandoned even if it was not exhausted. Sequences are valuable resource but in the case of recovery, using new sequence makes things easier and also allows to group FIDs and objects by working sessions, new connection - new sequence.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Code description&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Server side code is divided into two parts:&lt;br /&gt;
&lt;br /&gt;
* Sequence controller - allocates super-sequences, that is, sequences of sequences to all servers in cluster (currently only to MDSes as only they are new FIDs aware). Usually first MDS in cluster is sequence controller &lt;br /&gt;
&lt;br /&gt;
* Sequence manager - allocates meta-sequences (smaller range of sequences inside a super-sequence) to all clients, using granted super-sequence from the sequence controller. All MDSs in the cluster (all servers in the future) are sequence managers. The first MDS is, simultaneously, a sequence controller and a sequence manager.&lt;br /&gt;
&lt;br /&gt;
Client side code allocates new sequences from granted meta-sequence. When meta-sequence is exhausted, new one is allocated on server and sent to the client.&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
Client code consists of API for working with both server side parts, not only with sequence manager as all servers need to talk to sequence controller, they also use client API for this.&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
One important part of client API is FIDs allocation. New FID is allocated in currently granted sequence until sequence is exhausted. &lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Code&#039;&#039;&#039;&lt;br /&gt;
 fid/fid_handler.c    - server side sequence management code;&lt;br /&gt;
 fid/fid_request.c    - client side sequence management code;&lt;br /&gt;
 fid/fid_lib.c        - fids related miscellaneous stuff.&lt;br /&gt;
&lt;br /&gt;
==mountconf==&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Summary&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
MountConf is how servers and clients are set up, started, and configured. A MountConf usage document is [http://wiki.lustre.org/index.php?title=Mount_Conf here].&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
The major subsystems are the MGS, MGC, and the userspace tools mount.lustre and mkfs.lustre.&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
The basic idea is:&lt;br /&gt;
&lt;br /&gt;
# Whenever any Lustre component is mount(2)ed, we start a MGC.&lt;br /&gt;
# This establishes a connection to the MGS and downloads a configuration llog.&lt;br /&gt;
# The MGC passes the configuration log through the parser to set up the other OBDs.&lt;br /&gt;
# The MGC holds a CR configuration lock, which the MGS recalls whenever a live configuration change is made. &lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Code&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
MountConf file areas:&lt;br /&gt;
&lt;br /&gt;
 lustre/mgs/*&lt;br /&gt;
 lustre/mgc/*&lt;br /&gt;
 lustre/obdclass/obd_mount.c&lt;br /&gt;
 lustre/utils/mount_lustre.c&lt;br /&gt;
 lustre/utils/mkfs_lustre.c&lt;br /&gt;
&lt;br /&gt;
==liblustre==&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Summary&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Liblustre is a userspace library, used along with libsysio (developed by Sandia), that allows Lustre usage just by linking (or ld_preload&#039;ing) applications with it. Liblustre does not require any kernel support. It is also used on old Cray XT3 machines (and not so old, in the case of Sandia), where all applications are just linked with the library and loaded into memory as the only code to run. Liblustre does not support async operations of any kind due to a lack of interrupts and other notifiers from lower levels to Lustre. Liblustre includes another set of LNDs that are able to work from userspace.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Code&#039;&#039;&#039;&lt;br /&gt;
 dir.c          - Directory operations&lt;br /&gt;
 file.c         - File handling operations (like open)&lt;br /&gt;
 llite_lib.c    - General support (init/cleanp/parse options)&lt;br /&gt;
 lutil.c        - Supplementary code to get IP addresses and init various structures &lt;br /&gt;
                  needed to emulate the normal Linux process from other layers&#039; perspective.&lt;br /&gt;
 namei.c        - Metadata operations code.&lt;br /&gt;
 rw.c           - I/O code, including read/write&lt;br /&gt;
 super.c        - &amp;quot;Superblock&amp;quot; operation - mounting/umounting, inode operations.&lt;br /&gt;
 tests          - directory with liblustre-specific tests.&lt;br /&gt;
&lt;br /&gt;
==echo client/server==&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Summary&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
The echo_client and obdecho are OBD devices which help testing and performance measurement.&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
They were implemented originally for network testing - obdecho can replace obdfilter and echo_client can exercise any downstream configurations. They are normally used in the following configurations:&lt;br /&gt;
&lt;br /&gt;
* echo_client -&amp;gt; obdfilter. This is used to measure raw backend performance without any network I/O. &lt;br /&gt;
* echo_client -&amp;gt; OSC -&amp;gt; &amp;lt;network&amp;gt; -&amp;gt; OST -&amp;gt; obdecho. This is used to measure network and ptlrpc performance. &lt;br /&gt;
* echo_client -&amp;gt; OSC -&amp;gt; &amp;lt;network&amp;gt; -&amp;gt; OST -&amp;gt; obdfilter. This is used to measure performance available to the Lustre client. &lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Code&#039;&#039;&#039;&lt;br /&gt;
 lustre/obdecho/&lt;br /&gt;
&lt;br /&gt;
==client vfs==&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Summary&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
The client VFS interface, also called &#039;&#039;&#039;llite&#039;&#039;&#039;, is the bridge between the Linux kernel and the underlying Lustre infrastructure represented by the [https://wikis.clusterfs.com/intra/index.php/Lov_summary LOV], [https://wikis.clusterfs.com/intra/index.php/Client_metadata_summary MDC], and [https://wikis.clusterfs.com/intra/index.php/Ldlm_summary LDLM] subsystems. This includes mounting the client filesystem, handling name lookups, starting file I/O, and handling file permissions.&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
The Linux VFS interface shares a lot in common with the liblustre interface, which is used in the Catamount environment; as of yet, the code for these two subsystems is not common and contains a lot of duplication.  &lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Code&#039;&#039;&#039;&lt;br /&gt;
 lustre/llite/dcache.c            - Interface with Linux dentry cache/intents&lt;br /&gt;
 lustre/llite/dir.c               - readdir handling, filetype in dir, dir ioctl&lt;br /&gt;
 lustre/llite/file.c              - File handles, file ioctl, DLM extent locks&lt;br /&gt;
 lustre/llite/llite_close.c       - File close for opencache&lt;br /&gt;
 lustre/llite/llite_internal.h    - Llite internal function prototypes, structures&lt;br /&gt;
 lustre/llite/llite_lib.c         - Majority of request handling, client mount&lt;br /&gt;
 lustre/llite/llite_mmap.c        - Memory-mapped I/O&lt;br /&gt;
 lustre/llite/llite_nfs.c         - NFS export from clients&lt;br /&gt;
 lustre/llite/lloop.c             - Loop-like block device export from object&lt;br /&gt;
 lustre/llite/lproc_llite.c       - /proc interface for tunables, statistics&lt;br /&gt;
 lustre/llite/namei.c             - Filename lookup, intent handling&lt;br /&gt;
 lustre/llite/rw24.c              - Linux 2.4 IO handling routines&lt;br /&gt;
 lustre/llite/rw26.c              - Linux 2.6 IO handling routines&lt;br /&gt;
 lustre/llite/rw.c                - Linux generic IO handling routines&lt;br /&gt;
 lustre/llite/statahead.c         - Directory statahead for &amp;quot;ls -l&amp;quot; and &amp;quot;rm -r&amp;quot;&lt;br /&gt;
 lustre/llite/super25.c           - Linux 2.6 VFS file method registration&lt;br /&gt;
 lustre/llite/super.c             - Linux 2.4 VFS file method registration&lt;br /&gt;
 lustre/llite/symlink.c           - Symbolic links&lt;br /&gt;
 lustre/llite/xattr.c             - User-extended attributes&lt;br /&gt;
&lt;br /&gt;
==client vm==&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Summary&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Client code interacts with VM/MM subsystems of the host OS kernel to cache data (in the form of pages), and to react to various memory-related events, like memory pressure.&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
Two key components of this interaction are:&lt;br /&gt;
&lt;br /&gt;
* cfs_page_t data-type representing MM page. It comes together with the interface to map/unmap page to/from kernel virtual address space, access various per-page bits, like &#039;dirty&#039;, &#039;uptodate&#039;, etc., lock/unlock page. Currently, this data-type closely matches the Linux kernel page. It has to be straightened out, formalized, and expanded to include functionality like querying about total number of pages on a node, etc. &lt;br /&gt;
* MM page operations in cl_page (part of new client I/O interface). &lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Code&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
This describes the &#039;&#039;next generation&#039;&#039; Lustre client I/O code, which is expected to appear in Lustre 2.0. Code location is not finalized.&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
cfs_page_t interface is defined and implemented in:&lt;br /&gt;
&lt;br /&gt;
 lnet/include/libcfs/ARCH/ARCH-mem.h&lt;br /&gt;
 lnet/libcfs/ARCH/ARCH-mem.c &lt;br /&gt;
&lt;br /&gt;
Generic part of cl-page will be located in:&lt;br /&gt;
&lt;br /&gt;
 include/cl_object.h&lt;br /&gt;
 obdclass/cl_page.c&lt;br /&gt;
 obdclass/cl_object.c &lt;br /&gt;
&lt;br /&gt;
Linux kernel implementation is currently in:&lt;br /&gt;
&lt;br /&gt;
 llite/llite_cl.c&lt;br /&gt;
&lt;br /&gt;
==client I/O==&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Summary&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Client I/O is a group of interfaces used by various layers of a Lustre client to manage file data (as opposed to metadata). Main functions of these interfaces are:&lt;br /&gt;
&lt;br /&gt;
* Cache data, respecting limitations imposed both by hosting MM/VM, and by cluster-wide caching policies, and &lt;br /&gt;
* Form a stream of efficient I/O RPCs, respecting both ordering/timing constraints imposed by the hosting VFS (e.g., POSIX guarantees, O_SYNC, etc.), and cluster-wide IO scheduling policies. &lt;br /&gt;
&lt;br /&gt;
Client I/O subsystem interacts with VFS, VM/MM, DLM, and PTLRPC.&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
Client I/O interfaces are based on the following data-types:&lt;br /&gt;
&lt;br /&gt;
* cl_object: represents a file system object, both a file, and a stripe; &lt;br /&gt;
* cl_page: represents a cached data page; &lt;br /&gt;
* cl_lock: represents an extent DLM lock; &lt;br /&gt;
* cl_io: represents an ongoing high-level IO activity, like read(2)/write(2) system call, or sub-io of another IO; &lt;br /&gt;
* cl_req: represents a network RPC. &lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Code&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
This describes the &#039;&#039;next generation&#039;&#039; Lustre client I/O code. The code location is not finalized. The generic part is at:&lt;br /&gt;
&lt;br /&gt;
 include/cl_object.h&lt;br /&gt;
 obdclass/cl_object.c&lt;br /&gt;
 obdclass/cl_page.c&lt;br /&gt;
 obdclass/cl_lock.c&lt;br /&gt;
 obdclass/cl_io.c &lt;br /&gt;
&lt;br /&gt;
Layer-specific methods are currently at:&lt;br /&gt;
&lt;br /&gt;
 lustre/LAYER/LAYER_cl.c &lt;br /&gt;
&lt;br /&gt;
where LAYER is one of llite, lov, osc.&lt;br /&gt;
&lt;br /&gt;
==client metadata==&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Summary&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
The Meta Data Client (MDC) is the client-side interface for all operations related to the Meta Data Server  MDS. In current configurations there is a single MDC on the client for each filesystem mounted on the client. The MDC is responsible for enqueueing metadata locks (via  LDLM), and packing and unpacking messages on the wire.&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
In order to ensure a recoverable system, the MDC is limited at the client to only a single filesystem-modifying operation in flight at one time. This includes operations like create, rename, link, unlink, setattr.&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
For non-modifying operations like getattr and statfs the client can multiple RPC requests in flight at one time, limited by a tunable on the client, to avoid overwhelming the MDS. &lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Code&#039;&#039;&#039; &lt;br /&gt;
 lustre/mdc/lproc_mdc.c       - /proc interface for stats/tuning&lt;br /&gt;
 lustre/mdc/mdc_internal.h    - Internal header for prototypes/structs&lt;br /&gt;
 lustre/mdc/mdc_lib.c         - Packing of requests to MDS&lt;br /&gt;
 lustre/mdc/mdc_locks.c       - Interface to LDLM and client VFS intents&lt;br /&gt;
 lustre/mdc/mdc_reint.c       - Modifying requests to MDS&lt;br /&gt;
 lustre/mdc/mdc_request.c     - Non-modifying requests to MDS&lt;br /&gt;
&lt;br /&gt;
==client lmv== &lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Summary&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
LMV is a module which implements CMD client-side abstraction device. It allows client to work with many MDSes without any changes in Llite module and even without knowing that CMD is supported. Llite just translates Linux VFS requests into metadata API calls and forwards them down to the stack.&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
As LMV needs to know which MDS to talk for any particular operation, it uses some new services introduced in CMD3 times. They are:&lt;br /&gt;
&lt;br /&gt;
* FLD (Fids Location Database) - having FID or rather its sequence, lookup MDS number where this FID is located;&lt;br /&gt;
* SEQ (Client Sequence Manager) - LMV uses this via children MDCs for allocating new sequences and FIDs. &lt;br /&gt;
&lt;br /&gt;
LMV supports split objects. This means that for every split directory it creates special in-memory structure which contains information about object stripes. This includes MDS number, FID, etc. All consequent operations use these structures for determining what MDS should be used for particular action (create, take lock, etc).&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Code&#039;&#039;&#039;&lt;br /&gt;
 lmv/*.[ch]&lt;br /&gt;
&lt;br /&gt;
==lov==&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Summary&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
The LOV device presents a single virtual device interface to upper layers (llite, liblustre, MDS). The LOV code is responsible for splitting of requests to the correct OSTs based on striping information (lsm), and the merging of the replies to a single result to pass back to the higher layer.&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
It calculates per-object membership and offsets for read/write/truncate based on the virtual file offset passed from the upper layer. It is also responsible for splitting the locking across all servers as needed.&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
The LOV on the MDS is also involved in object allocation. &lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Code&#039;&#039;&#039;&lt;br /&gt;
 lustre/lov/lov_ea.c          - Striping attributes pack/unpack/verify&lt;br /&gt;
 lustre/lov/lov_internal.h    - Header for internal function prototypes/structs&lt;br /&gt;
 lustre/lov/lov_merge.c       - Struct aggregation from many objects&lt;br /&gt;
 lustre/lov/lov_obd.c         - Base LOV device configuration&lt;br /&gt;
 lustre/lov/lov_offset.c      - File offset and object calculations&lt;br /&gt;
 lustre/lov/lov_pack.c        - Pack/unpack of striping attributes&lt;br /&gt;
 lustre/lov/lov_qos.c         - Object allocation for different OST loading&lt;br /&gt;
 lustre/lov/lov_request.c     - Request handling/splitting/merging&lt;br /&gt;
 lustre/lov/lproc_lov.c       - /proc/fs/lustre/lov tunables/statistics&lt;br /&gt;
&lt;br /&gt;
==quota==&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Summary&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Quotas allow a system administrator to limit the maximum amount of disk space a user or group can consume. Quotas are set by root, and can be specified for individual users and/or groups. Quota limits can be set on both blocks and inodes.&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
Lustre quota enforcement differs from standard Linux quota support in several ways:&lt;br /&gt;
&lt;br /&gt;
* Lustre quota are administered via the lfs command, whereas standard Linux quota uses the quotactl interface.&lt;br /&gt;
* As Lustre is a distributed filesystem, lustre quotas are also distributed in order to limit the impact on performance.&lt;br /&gt;
* Quotas are allocated and consumed in a quantized fashion. &lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Code&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Quota core:&lt;br /&gt;
&lt;br /&gt;
 lustre/quota/quota_adjust_qunit.c&lt;br /&gt;
 lustre/quota/quota_check.c&lt;br /&gt;
 lustre/quota/quotacheck_test.c&lt;br /&gt;
 lustre/quota/quota_context.c&lt;br /&gt;
 lustre/quota/quota_ctl.c&lt;br /&gt;
 lustre/quota/quota_interface.c&lt;br /&gt;
 lustre/quota/quota_internal.h&lt;br /&gt;
 lustre/quota/quota_master.c &lt;br /&gt;
&lt;br /&gt;
Interactions with the underlying ldiskfs filesystem:&lt;br /&gt;
&lt;br /&gt;
 lustre/lvfs/fsfilt_ext3.c&lt;br /&gt;
 lustre/lvfs/lustre_quota_fmt.c&lt;br /&gt;
 lustre/lvfs/lustre_quota_fmt_convert.c &lt;br /&gt;
&lt;br /&gt;
Hooks under:&lt;br /&gt;
&lt;br /&gt;
 lustre/mds&lt;br /&gt;
 lustre/obdfilter &lt;br /&gt;
&lt;br /&gt;
Regression tests:&lt;br /&gt;
&lt;br /&gt;
 lustre/tests/sanity-quota.sh&lt;br /&gt;
&lt;br /&gt;
==security-gss==&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Summary&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
The secure ptlrpc (sptlrpc) is a framework inside of ptlrpc layer. It act upon both side of each ptlrpc connection between 2 nodes, doing transformation on every RPC message, turn this into a secure communication link. By using GSS, sptlrpc is able to support multiple authentication mechanism, but currently we only support Kerberos 5.&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
Supported security flavors:&lt;br /&gt;
&lt;br /&gt;
* null: no authentication, no data transform, thus no performance overhead; compatible with 1.6;&lt;br /&gt;
* plain: no authentication, simple data transform, minimal performance overhead;&lt;br /&gt;
* krb5x: per-user basis client-server mutual authentication using Kerberos 5, sign or encrypt data, could have substantial CPU overhead. &lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Code&#039;&#039;&#039;&lt;br /&gt;
 lustre/ptlrpc/sec*.c&lt;br /&gt;
 lustre/ptlrpc/gss/&lt;br /&gt;
 lustre/utils/gss/&lt;br /&gt;
&lt;br /&gt;
==security-capa==&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Summary&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Capabilities are pieces of data generated by one service - the master service, passed to a client and presented by the client to another service - the slave service, to authorize an action. It is independent from the R/W/X permission based file operation authorization.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Code&#039;&#039;&#039;&lt;br /&gt;
 lustre/llite/llite_capa.c&lt;br /&gt;
 lustre/mdt/mdt_capa.c&lt;br /&gt;
 lustre/obdfilter/filter_capa.c&lt;br /&gt;
 lustre/obdclass/capa.c&lt;br /&gt;
 lustre/include/lustre_capa.h&lt;br /&gt;
&lt;br /&gt;
==security-identity== &lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Summary&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Lustre identity is a miscellaneous framework for lustre file operation authorization. Generally, it can be divided into two parts:&lt;br /&gt;
&lt;br /&gt;
* User-identity parse / upcall / mapping.&lt;br /&gt;
* File operation permission maintenance and check, includes the traditional file mode based permission and ACL based permission.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Code&#039;&#039;&#039; &lt;br /&gt;
 /llite/llite_rmtacl.c&lt;br /&gt;
 lustre/mdt/mdt_identity.c&lt;br /&gt;
 lustre/mdt/mdt_idmap.c&lt;br /&gt;
 lustre/mdt/mdt_lib.c&lt;br /&gt;
 lustre/obdclass/idmap.c&lt;br /&gt;
 lustre/utils/l_getidentity.c&lt;br /&gt;
 lustre/include/lustre_idmap.h &lt;br /&gt;
&lt;br /&gt;
 lustre/llite/xattr.c&lt;br /&gt;
 lustre/mdt/mdt_xattr.c&lt;br /&gt;
 lustre/cmm/cmm_object.c&lt;br /&gt;
 lustre/cmm/mdc_object.c&lt;br /&gt;
 lustre/mdd/mdd_permission.c&lt;br /&gt;
 lustre/mdd/mdd_object.c&lt;br /&gt;
 lustre/mdd/mdd_dir.c&lt;br /&gt;
 lustre/obdclass/acl.c&lt;br /&gt;
 lustre/include/lustre_eacl.h&lt;br /&gt;
&lt;br /&gt;
==OST== &lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Summary&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
OST is a very thin layer of data server. Its main responsibility is to translate RPCs to local calls of obdfilter, i.e. RPC parsing.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Code&#039;&#039;&#039; &lt;br /&gt;
 lustre/ost/*.[ch]&lt;br /&gt;
&lt;br /&gt;
==ldiskfs== &lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Summary&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
ldiskfs is local disk filesystem built on top of ext3. it adds extents support to ext3, multiblock allocator, multimount protection and iopen features.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Code&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
There is no ldiskfs source code in the Lustre repositories (only patches). Instead, ext3 code is copied from your build kernel, the patches are applied and then whole thing gets renamed to ldiskfs. For details, go to ldiskfs/.&lt;br /&gt;
&lt;br /&gt;
==fsfilt== &lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Summary&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
The fsfilt layer abstracts the backing filesystem specifics away from the obdfilter and mds code in 1.4 and 1.6 lustre. This avoids linking the obdfilter and mds directly against the filesystem module, and in theory allows different backing filesystems, but in practise this was never implemented. In Lustre 1.8 and later this code is replaced by the OSD layer.&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
There is a core fsfilt module which can auto-load the backing filesystem type based on the type specified during configuration. This loads a filesystem-specific fsfilt_{fstype} module with a set of methods for that filesystem.&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
There are a number of different kinds of methods:&lt;br /&gt;
&lt;br /&gt;
* Get/set filesystem label and UUID for identifying the backing filesystem&lt;br /&gt;
* Start, extend, commit compound filesystem transactions to allow multi-file updates to be atomic for recovery&lt;br /&gt;
* Set a journal callback for transaction disk commit (for Lustre recovery)&lt;br /&gt;
* Store attributes in the inode (possibly avoiding side-effects like truncation when setting the inode size to zero)&lt;br /&gt;
* Get/set file attributes (EAs) for storing LOV and OST info (e.g. striping)&lt;br /&gt;
* Perform low-level IO on the file (avoiding cache)&lt;br /&gt;
* Get/set file version (for future recovery mechanisms)&lt;br /&gt;
* Access quota information &lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Code&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
The files used for the fsfilt code reside in:&lt;br /&gt;
&lt;br /&gt;
 lustre/lvfs/fsfilt.c         - Interface used by obdfilter/MDS, module autoloading&lt;br /&gt;
 lustre/lvfs/fsfilt_ext3.c    - Interface to ext3/ldiskfs filesystem&lt;br /&gt;
&lt;br /&gt;
The &#039;&#039;fsfilt_ldiskfs.c&#039;&#039; file is auto-generated from &#039;&#039;fsfilt_ext3.c&#039;&#039; in &#039;&#039;lustre/lvfs/autoMakefile.am&#039;&#039; using sed to replace instances of ext3 and EXT3 with ldiskfs, and a few other replacements to avoid symbol clashes.&lt;br /&gt;
&lt;br /&gt;
==ldiskfs OSD==&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Summary&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
ldiskfs-OSD is an implementation of dt_{device,object} interfaces on top of (modified) ldiskfs file-system.&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
It uses standard ldiskfs/ext3 code to do file I/O.&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
It supports 2 types of indices (in the same file system):&lt;br /&gt;
&lt;br /&gt;
* iam-based index: this is an extension of ext3 htree directory format with support for more general keys and values, and with relaxed size restrictions, and &lt;br /&gt;
* compatibility index: this is usual ldiskfs directory, accessible through dt_index_operations. &lt;br /&gt;
&lt;br /&gt;
ldiskfs-OSD uses read-write mutex to serialize compound operations. &lt;br /&gt;
&amp;lt;/blockquote&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Code&#039;&#039;&#039; &lt;br /&gt;
 lustre/include/dt_object.h&lt;br /&gt;
 lustre/osd/osd_internal.h&lt;br /&gt;
 lustre/osd/osd_handler.c&lt;br /&gt;
&lt;br /&gt;
==DMU OSD== &lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Summary&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
This is another implementation of the OSD API for userspace DMU. It uses DMU&#039;s ZAP for indices.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Code&#039;&#039;&#039;&lt;br /&gt;
 dmu-osd/*.[ch] in b_hd_dmu branch&lt;br /&gt;
&lt;br /&gt;
==DMU== &lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Summary&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
The DMU is one of the layers in Sun&#039;s ZFS filesystem which is responsible for presenting a transactional object store to its consumers. It is used as Lustre&#039;s backend object storage mechanism for the userspace MDSs and OSSs.&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
The ZFS community page has a source tour which is useful as an introduction to the several ZFS layers: [http://www.opensolaris.org/os/community/zfs/source/ ZFS source]&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
There are many useful resources in that community page.&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
For reference, here&#039;s a list of DMU features:&lt;br /&gt;
&lt;br /&gt;
* Atomic transactions&lt;br /&gt;
* End-to-end data and metadata checksumming (currently supports fletcher2, fletcher4 and sha-256)&lt;br /&gt;
* Compression (currently supports lzjb and gzip with compression levels 1..9)&lt;br /&gt;
* Snapshots and clones&lt;br /&gt;
* Variable block sizes (currently supports sector sizes from 512 bytes to 128KB)&lt;br /&gt;
* Integrated volume management with support for RAID-1, RAID-Z and RAID-Z2 and striping&lt;br /&gt;
* Metadata and optional data redundancy (ditto blocks) atop the inherent storage pool redundancy for high resilience&lt;br /&gt;
* Self-healing, which works due to checksumming, ditto blocks and pool redundancy&lt;br /&gt;
* Storage devices that act as level-2 caches (designed for flash storage)&lt;br /&gt;
* Hot spares&lt;br /&gt;
* Designed with scalability in mind - supports up to 2^64 bytes per object, 2^48 objects per filesystem, 2^64 filesystems per pool, 2^64 bytes per device, 2^64 devices per pool, ..&lt;br /&gt;
* Very easy to use admin interface (zfs and zpool commands) &lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Code&#039;&#039;&#039; &lt;br /&gt;
 src/&lt;br /&gt;
 source code&lt;br /&gt;
 &lt;br /&gt;
 src/cmd/              - ZFS/DMU related programs&lt;br /&gt;
 src/cmd/lzfs/         - lzfs, the filesystem administration utility&lt;br /&gt;
 src/cmd/lzpool/       - lzpool, the pool administration utility&lt;br /&gt;
 src/cmd/lzdb/         - lzdb, the zfs debugger&lt;br /&gt;
 src/cmd/lztest/       - lztest, the DMU test suite&lt;br /&gt;
 src/cmd/lzfsd/        - lzfsd, the ZFS daemon&lt;br /&gt;
 &lt;br /&gt;
 src/lib/              - Libraries&lt;br /&gt;
 src/lib/port/         - Portability layer&lt;br /&gt;
 src/lib/solcompat/    - Solaris -&amp;gt; Linux portability layer (deprecated, use libport instead)&lt;br /&gt;
 src/lib/avl/          - AVL trees, used in many places in the DMU code&lt;br /&gt;
 src/lib/nvpair/       - Name-value pairs, used in many places in the DMU code&lt;br /&gt;
 src/lib/umem/         - Memory management library&lt;br /&gt;
 src/lib/zpool/        - Main ZFS/DMU code&lt;br /&gt;
 src/lib/zfs/          - ZFS library used by the lzfs and lzpool utilities&lt;br /&gt;
 src/lib/zfscommon/    - Common ZFS code between libzpool and libzfs&lt;br /&gt;
 src/lib/ctl/          - Userspace control/management interface&lt;br /&gt;
 src/lib/udmu/         - Lustre uDMU code (thin library around the DMU)&lt;br /&gt;
 &lt;br /&gt;
 src/scons/            - local copy of SCons&lt;br /&gt;
 &lt;br /&gt;
 tests/regression/     - Regression tests&lt;br /&gt;
 &lt;br /&gt;
 misc/                 - miscellaneous files/scripts&lt;br /&gt;
&lt;br /&gt;
==obdfilter==&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Summary&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
obdfilter is a core component of OST (data server) making underlying disk filesystem a part of distributed system:&lt;br /&gt;
&lt;br /&gt;
* Maintains cluster-wide coherency for data&lt;br /&gt;
* Maintains space reservation for data in client&#039;s cache (grants)&lt;br /&gt;
* Maintains quota &lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Code&#039;&#039;&#039; &lt;br /&gt;
 lustre/obdfilter/*.[ch]&lt;br /&gt;
&lt;br /&gt;
==MDS==&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Summary&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
The MDS service in Lustre 1.4 and 1.6 is a monolithic body of code that provides multiple functions related to filesystem metadata. It handles the incoming RPCs and service threads for metadata operations (create, rename, unlink, readdir, etc), interfaces with the Lustre lock manager ([https://wikis.clusterfs.com/intra/index.php/Ldlm_summary DLM]), and also manages the underlying filesystem (via the [https://wikis.clusterfs.com/intra/index.php/Fsfilt_summary interface fsfilt] interface).&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
The MDS is the primary point of access control for clients, allocates the objects belonging to a file (in conjunction with [https://wikis.clusterfs.com/intra/index.php/Lov_summary LOV]) and passing that information to the clients when they access a file.&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
The MDS is also ultimately responsible for deleting objects on the OSTs, either by passing object information for destroy to the client removing the last link or open reference on a file and having the client do it, or by destroying the objects on the OSTs itself in case the client fails to do so.&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
In the 1.8 and later releases, the functionality provided by the MDS code has been split into multiple parts ([https://wikis.clusterfs.com/intra/index.php/Mdt_summary MDT], [https://wikis.clusterfs.com/intra/index.php/Mdd_summary MDD], OSD) in order to allow stacking of the metadata devices for clustered metadata.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Code&#039;&#039;&#039; &lt;br /&gt;
 lustre/mds/commit_confd.c&lt;br /&gt;
 lustre/mds/handler.c            - RPC request handler&lt;br /&gt;
 lustre/mds/lproc_mds.c          - /proc interface for stats/control&lt;br /&gt;
 lustre/mds/mds_fs.c             - Mount/configuration of underlying filesystem&lt;br /&gt;
 lustre/mds/mds_internal.h       - Header for internal declarations&lt;br /&gt;
 lustre/mds/mds_join.c           - Handle join_file operations&lt;br /&gt;
 lustre/mds/mds_lib.c            - Unpack of wire structs from requests&lt;br /&gt;
 lustre/mds/mds_log.c            - Lustre log interface (llog) for unlink/setattr&lt;br /&gt;
 lustre/mds/mds_lov.c            - Interface to LOV for create and orphan&lt;br /&gt;
 lustre/mds/mds_open.c           - File open/close handling&lt;br /&gt;
 lustre/mds/mds_reint.c          - Reintegration of changes made by clients&lt;br /&gt;
 lustre/mds/mds_unlink_open.c    - Handling of open-unlinked files (PENDING dir)&lt;br /&gt;
 lustre/mds/mds_xattr.c          - User-extended attribute handling&lt;br /&gt;
&lt;br /&gt;
==MDT==&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Summary&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
MDT stands for MetaData Target. This is a top-most layer in the MD server device stack. Responsibility of MDT are all this networking, as far as meta-data are concerned:&lt;br /&gt;
&lt;br /&gt;
* Managing PTLRPC services and threads;&lt;br /&gt;
* Receiving incoming requests, unpacking them and checking their validity;&lt;br /&gt;
* Sending replies;&lt;br /&gt;
* Handling recovery;&lt;br /&gt;
* Using DLM to guarantee cluster-wide meta-data consistency;&lt;br /&gt;
* Handling intents;&lt;br /&gt;
* Handling credential translation. &lt;br /&gt;
&lt;br /&gt;
Theoretically MDT is an optional layer: completely local Lustre setup, with single mete-data server, and locally mounted client can exist without MDT (and still use networking for non-metadata access). &lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Code&#039;&#039;&#039;&lt;br /&gt;
 lustre/mdt/mdt.mod.c&lt;br /&gt;
 lustre/mdt/mdt_capa.c&lt;br /&gt;
 lustre/mdt/mdt_handler.c&lt;br /&gt;
 lustre/mdt/mdt_identity.c&lt;br /&gt;
 lustre/mdt/mdt_idmap.c&lt;br /&gt;
 lustre/mdt/mdt_internal.h&lt;br /&gt;
 lustre/mdt/mdt_lib.c&lt;br /&gt;
 lustre/mdt/mdt_lproc.c&lt;br /&gt;
 lustre/mdt/mdt_open.c&lt;br /&gt;
 lustre/mdt/mdt_recovery.c&lt;br /&gt;
 lustre/mdt/mdt_reint.c&lt;br /&gt;
 lustre/mdt/mdt_xattr.c&lt;br /&gt;
&lt;br /&gt;
==CMM== &lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Summary&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Overview&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
The CMM is a new layer in the MDS which cares about all clustered metadata issues and relationships. The CMM does the following:&lt;br /&gt;
&lt;br /&gt;
* Acts as layer between the MDT and MDD.&lt;br /&gt;
* Provides MDS-MDS interaction.&lt;br /&gt;
* Queries and updates FLD.&lt;br /&gt;
* Does the local or remote operation if needed.&lt;br /&gt;
* Will do rollback - epoch control, undo logging. &lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;CMM functionality&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
CMM chooses all servers involved in operation and sends depended request if needed. The calling of remote MDS is a new feature related to the CMD. CMM mantain the list of MDC to connect with all other MDS.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Objects&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
The CMM can allocate two types of object - local and remote. Remote object can occur during metadata operations with more than one object involved. Such operation is called as cross-ref operation. &lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Code&#039;&#039;&#039; &lt;br /&gt;
 lustre/cmm&lt;br /&gt;
&lt;br /&gt;
==MDD== &lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Summary&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
MDD is metadata layer in the new MDS stack, which is the only layer operating the metadata in MDS. The implementation is similar as VFS meta operation but based on OSD storage. MDD API is currently only used in new MDS stack, called by CMM layer.&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
In theory, MDD should be local metadata layer, but for compatibility with old MDS stack and reuse some mds codes(llog and lov), a mds device is created and connected to the mdd. So the llog and lov in mdd still use original code through this temporary mds device. And it will be removed when the new llog and lov layer in the new MDS stack are implemented. &lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Code&#039;&#039;&#039;&lt;br /&gt;
 lustre/lustre/mdd/&lt;br /&gt;
&lt;br /&gt;
==recovery==&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Summary&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Overview&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Client recovery starts in case when no server reply is received within given timeout or when server tells to client that it is not connected (client was evicted on server earlier for whatever reason).&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
The recovery consists of trying to connect to server and then step through several recovery states during which various client-server data is synchronized, namely all requests that were already sent to server but not yet confirmed as received and DLM locks. Should any problems arise during recovery process (be it a timeout or server’s refuse to recognise client again), the recovery is restarted from the very beginning.&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
During recovery all new requests to the server are not sent to the server, but added to special delayed requests queue that is then sent once if recovery completes succesfully.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Replay and Resend&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
* Clients will go through all the requests in the sending and replay lists and determine the recovery action needed - replay request, resend request, cleanup up associated state for committed requests.&lt;br /&gt;
* The client replays requests which were not committed on the server, but for which the client saw reply from server before it failed. This allows the server to replay the changes to the persistent store.&lt;br /&gt;
* The client resends requests that were committed on the server, but the client did not see a reply for them, maybe due to server failure or network failure that caused the reply to be lost. This allows the server to reconstruct the reply and send it to the client.&lt;br /&gt;
* The client resends requests that the server has not seen at all, these would be all requests with transid higher than the last_rcvd value from the server and the last_committed transno, and the reply seen flag is not set.&lt;br /&gt;
* The client gets the last_committed transno information from the server and cleans up the state associated with requests that were committed on the server. &lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Code&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Recovery code is scattered through all code almost. Though important code:&lt;br /&gt;
 ldlm/ldlm_lib.c    - generic server recovery code &lt;br /&gt;
 ptlrpc/            - client recovery code&lt;br /&gt;
&lt;br /&gt;
==version recovery== &lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Summary&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Version Based Recovery&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
This recovery technique is based on using versions of objects (inodes) to allow clients to recover later than ordinary server recovery timeframe.&lt;br /&gt;
&lt;br /&gt;
# The server changes the version of object during any change and return that data to client. The version may be checked during replay to be sure that object is the same state during replay as it was originally.&lt;br /&gt;
# After failure the server starts recovery as usual but if some client miss the version check will be used for replays.&lt;br /&gt;
# Missed client can connect later and try to recover. This is &#039;delayed recovery&#039; and version check is used during it always.&lt;br /&gt;
# The client which missed main recovery window will not be evicted and can connect later to initiate recovery. In that case the versions will checked to determine was that object changed by someone else or not.&lt;br /&gt;
# When finished with replay, client and server check if any replay failed on any request because of version mismatch. If not, the client will get a successful reintegration message. If a version mismatch was encountered, the client must be evicted.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Code&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Recovery code is scattered through all code almost. Though important code:&lt;br /&gt;
 ldlm/ldlm_lib.c    - generic server recovery code &lt;br /&gt;
 ptlrpc/            - client recovery code&lt;br /&gt;
&lt;br /&gt;
==IAM== &lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Summary&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
IAM stands for &#039;Index Access Module&#039;: it is an extension to the ldiskfs directory code, adding generic indexing capability.&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
File system directory can be thought of as an index mapping keys, which are strings (file names), to the records which are integers (inode numbers). IAM removes limitations on key and record size and format, providing an abstraction of a transactional container, mapping arbitrary opaque keys into opaque records.&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
Implementation notes:&lt;br /&gt;
&lt;br /&gt;
* IAM is implemented as a set of patches to the ldiskfs;&lt;br /&gt;
* IAM is an extension of ldiskfs directory code that uses htree data-structure for scalable indexing;&lt;br /&gt;
* IAM uses fine-grained key-level and node-level locking (pdirops locking, designed and implemented by Alex Tomas);&lt;br /&gt;
* IAM doesn&#039;t assume any internal format keys. Keys are compared by memcmp() function (which dictates BE order for scalars);&lt;br /&gt;
* IAM supports different flavors of containers:&lt;br /&gt;
** lfix: fixed size record and fixed size keys,&lt;br /&gt;
** lvar: variable sized records and keys,&lt;br /&gt;
** htree: compatibility mode, allowing normal htree directory to be accessed as an IAM container; &lt;br /&gt;
* IAM comes with ioctl(2) based user-level interface. &lt;br /&gt;
&lt;br /&gt;
IAM is used by ldiskfs-OSD to implement dt_index_operations interface. &lt;br /&gt;
&amp;lt;/blockquote&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Code&#039;&#039;&#039;&lt;br /&gt;
 lustre/ldiskfs/kernel_patches/patches/ext3-iam-2.6-sles10.patch&lt;br /&gt;
 lustre/ldiskfs/kernel_patches/patches/ext3-iam-ops.patch&lt;br /&gt;
 lustre/ldiskfs/kernel_patches/patches/ext3-iam-2.6.18-rhel5.patch&lt;br /&gt;
 lustre/ldiskfs/kernel_patches/patches/ext3-iam-rhel4.patch&lt;br /&gt;
 lustre/ldiskfs/kernel_patches/patches/ext3-iam-2.6.18-vanilla.patch&lt;br /&gt;
 lustre/ldiskfs/kernel_patches/patches/ext3-iam-separate.patch&lt;br /&gt;
 lustre/ldiskfs/kernel_patches/patches/ext3-iam-2.6.9-rhel4.patch&lt;br /&gt;
 lustre/ldiskfs/kernel_patches/patches/ext3-iam-sles10.patch&lt;br /&gt;
 lustre/ldiskfs/kernel_patches/patches/ext3-iam-common.patch&lt;br /&gt;
 lustre/ldiskfs/kernel_patches/patches/ext3-iam-uapi.patch&lt;br /&gt;
&lt;br /&gt;
==SOM== &lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Summary&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Size-on-MDS is a metadata improvement, which includes the caching of the inode size, blocks, ctime and mtime on MDS. Such an attribute caching allows clients to avoid making RPCs to the OSTs to find the attributes encoded in the file objects kept on those OSTs what results in the significantly improved performance of listing directories.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Code&#039;&#039;&#039;&lt;br /&gt;
 llite/llite_close.c       - client-side SOM code&lt;br /&gt;
 liblustre/file.c          - liblustre SOM code&lt;br /&gt;
 mdt/mdt_handler.c         - general handling of SOM-related rpc&lt;br /&gt;
 mdt/mdt_open.c            - MDS side SOM code &lt;br /&gt;
 mdt/mdt_recovery.c        - MDS side SOM recovery code&lt;br /&gt;
 obdfilter/filter_log.c    - OST side IO epoch lloging code;&lt;br /&gt;
&lt;br /&gt;
==tests== &lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Summary&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
The &amp;quot;tests&amp;quot; subsystem is a set of scripts and programs which is used to test other lustre subsystems. It contains:&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;&#039;&#039;runtests&#039;&#039;&#039;&#039;&#039;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
Simple basic regression test&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&#039;&#039;&#039;&#039;&#039;sanity&#039;&#039;&#039;&#039;&#039;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
A set of regression tests that verify operation under normal operating &lt;br /&gt;
conditions&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&#039;&#039;&#039;&#039;&#039;fsx&#039;&#039;&#039;&#039;&#039;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
file system exerciser&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&#039;&#039;&#039;&#039;&#039;sanityn&#039;&#039;&#039;&#039;&#039;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
Tests that verify operations from two clients under normal operating conditions&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&#039;&#039;&#039;&#039;&#039;lfsck&#039;&#039;&#039;&#039;&#039;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
Tests e2fsck and lfsck to detect and fix filesystem corruption&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&#039;&#039;&#039;&#039;&#039;liblustre&#039;&#039;&#039;&#039;&#039;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
Runs a test linked to a liblustre client library&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&#039;&#039;&#039;&#039;&#039;replay-single&#039;&#039;&#039;&#039;&#039;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
A set of unit tests that verify recovery after MDS failure&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&#039;&#039;&#039;&#039;&#039;conf-sanity&#039;&#039;&#039;&#039;&#039;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
A set of unit tests that verify the configuration&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&#039;&#039;&#039;&#039;&#039;recovery-small&#039;&#039;&#039;&#039;&#039;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
A set of unit tests that verify RPC replay after communications failure&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&#039;&#039;&#039;&#039;&#039;replay-ost-single&#039;&#039;&#039;&#039;&#039;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
A set of unit tests that verify recovery after OST failure&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&#039;&#039;&#039;&#039;&#039;replay-dual&#039;&#039;&#039;&#039;&#039;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
A set of unit tests that verify the recovery from two clients after server failure&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&#039;&#039;&#039;&#039;&#039;insanity&#039;&#039;&#039;&#039;&#039;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
A set of tests that verify the multiple concurrent failure conditions&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&#039;&#039;&#039;&#039;&#039;sanity-quota&#039;&#039;&#039;&#039;&#039;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
A set of tests that verify filesystem quotas&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
The acceptance-small.sh is a wrapper which is normally used to run all (or any) of these scripts. In additional it is used to run the following pre-installed benchmarks:&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&#039;&#039;&#039;&#039;&#039;dbench&#039;&#039;&#039;&#039;&#039;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
Dbench benchmark for simulating N clients to produce the filesystem load&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&#039;&#039;&#039;&#039;&#039;bonnie&#039;&#039;&#039;&#039;&#039;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
Bonnie++ benchmark for creation, reading, and deleting many small files&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&#039;&#039;&#039;&#039;&#039;iozone&#039;&#039;&#039;&#039;&#039;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
Iozone benchmark for generating and measuring a variety of file operations.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Code&#039;&#039;&#039;&lt;br /&gt;
 lustre/tests/acl/run&lt;br /&gt;
 lustre/tests/acl/make-tree&lt;br /&gt;
 lustre/tests/acl/README&lt;br /&gt;
 lustre/tests/acl/setfacl.test&lt;br /&gt;
 lustre/tests/acl/getfacl-noacl.test&lt;br /&gt;
 lustre/tests/acl/permissions.test&lt;br /&gt;
 lustre/tests/acl/inheritance.test&lt;br /&gt;
 lustre/tests/acl/misc.test&lt;br /&gt;
 lustre/tests/acl/cp.test&lt;br /&gt;
 lustre/tests/cfg/local.sh&lt;br /&gt;
 lustre/tests/cfg/insanity-local.sh&lt;br /&gt;
 lustre/tests/ll_sparseness_write.c&lt;br /&gt;
 lustre/tests/writeme.c&lt;br /&gt;
 lustre/tests/cobd.sh&lt;br /&gt;
 lustre/tests/test_brw.c&lt;br /&gt;
 lustre/tests/ll_getstripe_info.c&lt;br /&gt;
 lustre/tests/lov-sanity.sh&lt;br /&gt;
 lustre/tests/sleeptest.c&lt;br /&gt;
 lustre/tests/flocks_test.c&lt;br /&gt;
 lustre/tests/getdents.c&lt;br /&gt;
 lustre/tests/ll_dirstripe_verify.c&lt;br /&gt;
 lustre/tests/sanity.sh&lt;br /&gt;
 lustre/tests/multifstat.c&lt;br /&gt;
 lustre/tests/sanityN.sh&lt;br /&gt;
 lustre/tests/liblustre_sanity_uml.sh&lt;br /&gt;
 lustre/tests/fsx.c&lt;br /&gt;
 lustre/tests/small_write.c&lt;br /&gt;
 lustre/tests/socketserver&lt;br /&gt;
 lustre/tests/cmknod.c&lt;br /&gt;
 lustre/tests/README&lt;br /&gt;
 lustre/tests/acceptance-metadata-double.sh&lt;br /&gt;
 lustre/tests/writemany.c&lt;br /&gt;
 lustre/tests/llecho.sh&lt;br /&gt;
 lustre/tests/lfscktest.sh&lt;br /&gt;
 lustre/tests/run-llog.sh&lt;br /&gt;
 lustre/tests/conf-sanity.sh&lt;br /&gt;
 lustre/tests/mmap_sanity.c&lt;br /&gt;
 lustre/tests/write_disjoint.c&lt;br /&gt;
 lustre/tests/ldaptest.c&lt;br /&gt;
 lustre/tests/acceptance-metadata-single.sh&lt;br /&gt;
 lustre/tests/compile.sh&lt;br /&gt;
 lustre/tests/mcreate.c&lt;br /&gt;
 lustre/tests/runas.c&lt;br /&gt;
 lustre/tests/replay-single.sh&lt;br /&gt;
 lustre/tests/lockorder.sh&lt;br /&gt;
 lustre/tests/test2.c&lt;br /&gt;
 lustre/tests/llog-test.sh&lt;br /&gt;
 lustre/tests/fchdir_test.c&lt;br /&gt;
 lustre/tests/mkdirdeep.c&lt;br /&gt;
 lustre/tests/runtests&lt;br /&gt;
 lustre/tests/flock.c&lt;br /&gt;
 lustre/tests/mlink.c&lt;br /&gt;
 lustre/tests/checkstat.c&lt;br /&gt;
 lustre/tests/crash-mod.sh&lt;br /&gt;
 lustre/tests/multiop.c&lt;br /&gt;
 lustre/tests/random-reads.c&lt;br /&gt;
 lustre/tests/disk1_4.zip&lt;br /&gt;
 lustre/tests/rundbench&lt;br /&gt;
 lustre/tests/wantedi.c&lt;br /&gt;
 lustre/tests/rename_many.c&lt;br /&gt;
 lustre/tests/leak_finder.pl&lt;br /&gt;
 lustre/tests/Makefile.am&lt;br /&gt;
 lustre/tests/parallel_grouplock.c&lt;br /&gt;
 lustre/tests/chownmany.c&lt;br /&gt;
 lustre/tests/ost_oos.sh&lt;br /&gt;
 lustre/tests/mkdirmany.c&lt;br /&gt;
 lustre/tests/directio.c&lt;br /&gt;
 lustre/tests/insanity.sh&lt;br /&gt;
 lustre/tests/createmany-mpi.c&lt;br /&gt;
 lustre/tests/createmany.c&lt;br /&gt;
 lustre/tests/runiozone&lt;br /&gt;
 lustre/tests/rmdirmany.c&lt;br /&gt;
 lustre/tests/replay-ost-single.sh&lt;br /&gt;
 lustre/tests/mcr.sh&lt;br /&gt;
 lustre/tests/mrename.c&lt;br /&gt;
 lustre/tests/sanity-quota.sh&lt;br /&gt;
 lustre/tests/lp_utils.c&lt;br /&gt;
 lustre/tests/lp_utils.h&lt;br /&gt;
 lustre/tests/acceptance-metadata-parallel.sh&lt;br /&gt;
 lustre/tests/oos.sh&lt;br /&gt;
 lustre/tests/createdestroy.c&lt;br /&gt;
 lustre/tests/toexcl.c&lt;br /&gt;
 lustre/tests/replay-dual.sh&lt;br /&gt;
 lustre/tests/createtest.c&lt;br /&gt;
 lustre/tests/munlink.c&lt;br /&gt;
 lustre/tests/iopentest1.c&lt;br /&gt;
 lustre/tests/iopentest2.c&lt;br /&gt;
 lustre/tests/openme.c&lt;br /&gt;
 lustre/tests/openclose.c&lt;br /&gt;
 lustre/tests/test-framework.sh&lt;br /&gt;
 lustre/tests/ll_sparseness_verify.c&lt;br /&gt;
 lustre/tests/it_test.c&lt;br /&gt;
 lustre/tests/unlinkmany.c&lt;br /&gt;
 lustre/tests/opendirunlink.c&lt;br /&gt;
 lustre/tests/filter_survey.sh&lt;br /&gt;
 lustre/tests/utime.c&lt;br /&gt;
 lustre/tests/openunlink.c&lt;br /&gt;
 lustre/tests/runvmstat&lt;br /&gt;
 lustre/tests/statmany.c&lt;br /&gt;
 lustre/tests/create.pl&lt;br /&gt;
 lustre/tests/oos2.sh&lt;br /&gt;
 lustre/tests/statone.c&lt;br /&gt;
 lustre/tests/rename.pl&lt;br /&gt;
 lustre/tests/set_dates.sh&lt;br /&gt;
 lustre/tests/openfilleddirunlink.c&lt;br /&gt;
 lustre/tests/openfile.c&lt;br /&gt;
 lustre/tests/llmountcleanup.sh&lt;br /&gt;
 lustre/tests/llmount.sh&lt;br /&gt;
 lustre/tests/acceptance-small.sh&lt;br /&gt;
 lustre/tests/truncate.c&lt;br /&gt;
 lustre/tests/recovery-small.sh&lt;br /&gt;
 lustre/tests/2ost.sh&lt;br /&gt;
 lustre/tests/tchmod.c&lt;br /&gt;
 lustre/tests/socketclient&lt;br /&gt;
 lustre/tests/runobdstat&lt;br /&gt;
 lustre/tests/memhog.c&lt;br /&gt;
 lustre/tests/flock_test.c&lt;br /&gt;
 lustre/tests/busy.sh&lt;br /&gt;
 lustre/tests/write_append_truncate.c&lt;br /&gt;
 lustre/tests/opendevunlink.c&lt;br /&gt;
 lustre/tests/o_directory.c&lt;br /&gt;
&lt;br /&gt;
==build== &lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Summary&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
The build system is responsible for building Lustre and related components (ldiskfs is normally included in the Lustre tree but can also live completely separately).&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
The main build process is managed using GNU Autoconf and Automake. Here is a brief outline of how a Lustre binary build from a fresh Git checkout works. User commands are shown in &#039;&#039;&#039;bold&#039;&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;sh autogen.sh&#039;&#039;&#039; - autogen performs a few checks and bootstraps the build system using automake and autoconf. It should only need to be called once for a fresh Git cloning, but sometimes it needs to be run again. See [https://bugzilla.lustre.org/show_bug.cgi?id=12580 bug 12580].&lt;br /&gt;
**Each component (Lustre and ldiskfs) has an autoMakefile.am in its toplevel directory that sets some variables and includes build/autoMakefile.am.toplevel. It also contains any toplevel autoMake code unique to that component.&lt;br /&gt;
** configure.ac is used by autoconf to generate a configure script. The Lustre configure.ac mostly relies on the macros defined in */autoconf/*.m4 to do its work. The ldiskfs configure.ac is more self-contained and relies only on build/autoconf/*.m4. &lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;./configure --with-linux=/root/cfs/kernels/linux-2.6.9-55.EL.HEAD&#039;&#039;&#039; - Configure performs extensive checks of the underlying system and kernel, then produces autoMakefiles and Makefiles. &lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;make&#039;&#039;&#039; - This is where things get really interesting.&lt;br /&gt;
** The @INCLUDE_RULES@ directive in most Makefile.in files includes a whole set of build rules from build/Makefile. See the top of that file for a description of all cases.&lt;br /&gt;
** Normally, it will include autoMakefile, so commands from that file will run.&lt;br /&gt;
** build/autoMakefile.am.toplevel is the basis of the autoMakefile produced in the toplevel directory. It includes the &amp;quot;modules&amp;quot; target.&lt;br /&gt;
** The modules target in turn calls the appropriate Linux make system if we are building on Linux.&lt;br /&gt;
** This build system once again reads the Makefile in each directory, and case 2 from build/Makefile is followed. &lt;br /&gt;
&lt;br /&gt;
So essentially, the Makefile.in controls the kernel build process, and the autoMakefile.am controls the userland build process as well as preparing the sources if necessary.&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
The build system can also be used to produce Lustre-patched kernels and binaries built against these kernels. The &#039;&#039;&#039;build/lbuild&#039;&#039;&#039; script does this - this is used by customers as well as the LTS. This script is in need of some serious cleanup, unfortunately.&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
Coding style note: as mentioned in [http://wiki.lustre.org/index.php?title=Coding_Guidelines Coding Guidelines], autoconf macros must follow the style specified in the [http://www.gnu.org/software/autoconf/manual/html_node/Coding-Style.html GNU Autoconf manual]. A lot of the older code has inconsistent style and is hard to follow - feel free to reformat when needed. New code &#039;&#039;&#039;must&#039;&#039;&#039; be styled correctly. &lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Code&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Lustre build system:&lt;br /&gt;
&lt;br /&gt;
* build/* (shared with ldiskfs)&lt;br /&gt;
* autogen.sh&lt;br /&gt;
* autoMakefile.am&lt;br /&gt;
* configure.ac&lt;br /&gt;
* lustre.spec.in&lt;br /&gt;
* Makefile.in&lt;br /&gt;
* all autoMakefile.am files&lt;br /&gt;
* all Makefile.in files &lt;br /&gt;
&lt;br /&gt;
ldiskfs build system:&lt;br /&gt;
&lt;br /&gt;
* build/* (shared with Lustre)&lt;br /&gt;
* autogen.sh&lt;br /&gt;
* autoMakefile.am&lt;br /&gt;
* configure.ac&lt;br /&gt;
* lustre-ldiskfs.spec.in&lt;br /&gt;
* Makefile.in&lt;br /&gt;
* all autoMakefile.am files&lt;br /&gt;
* all Makefile.in files&lt;/div&gt;</summary>
		<author><name>Nathan</name></author>
	</entry>
	<entry>
		<id>http://wiki.old.lustre.org/index.php?title=Subsystem_Map&amp;diff=9065</id>
		<title>Subsystem Map</title>
		<link rel="alternate" type="text/html" href="http://wiki.old.lustre.org/index.php?title=Subsystem_Map&amp;diff=9065"/>
		<updated>2009-12-15T22:34:34Z</updated>

		<summary type="html">&lt;p&gt;Nathan: /* ldiskfs */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;The Lustre subsystems are listed below. For each subsystem, a summary description and code is provided.&lt;br /&gt;
&lt;br /&gt;
==libcfs==&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Summary&#039;&#039;&#039;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
Libcfs provides an API comprising fundamental primitives and subsystems - e.g. process management and debugging support which is used throughout LNET, Lustre, and associated utilities. This API defines a portable runtime environment that is implemented consistently on all supported build targets.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Code&#039;&#039;&#039;&lt;br /&gt;
 lustre/lnet/libcfs/**/*.[ch]&lt;br /&gt;
&lt;br /&gt;
==lnet==&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Summary&#039;&#039;&#039;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
See the [http://www.sun.com/software/products/lustre/docs/Lustre-networking.pdf Lustre Networking] white paper for details. &lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Code&#039;&#039;&#039;&lt;br /&gt;
 lustre/lnet/**/*.[ch]&lt;br /&gt;
&lt;br /&gt;
==ptlrpc==&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Summary&#039;&#039;&#039;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
Ptlrpc implements Lustre communications over LNET.&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
All communication between Lustre processes are handled by RPCs, in which a request is sent to an advertised service, and the service processes the request and returns a reply. Note that a service may be offered by any Lustre process - e.g. the OST service on an OSS processes I/O requests and the AST service on a client processes notifications of lock conflicts.&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
The initial request message of an RPC is special - it is received into the first available request buffer at the destination. All other communications involved in an RPC are like RDMAs - the peer targets them specifically. For example, in a bulk read, the OSC posts reply and bulk buffers and sends descriptors for them (the LNET matchbits used to post them) in the RPC request. After the server has received the request, it GETs or PUTs the bulk data and PUTs the RPC reply directly.&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
Ptlrpc ensures all resources involved in an RPC are freed in finite time. If the RPC does not complete within a timeout, all buffers associated with the RPC must be unlinked. These buffers are still accessible to the network until their completion events have been delivered.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Code&#039;&#039;&#039;&lt;br /&gt;
 lustre/ptlrpc/*.[ch]&lt;br /&gt;
 lustre/ldlm/ldlm_lib.c&lt;br /&gt;
&lt;br /&gt;
==llog==&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Summary&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Overview&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
LLog is the generic logging mechanism in Lustre. It allows Lustre to store records in an appropriate format and access them later using a reasonable API.&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
LLog is used is various cases. The main LLog use cases are the following:&lt;br /&gt;
&lt;br /&gt;
* mountconf - entire cluster configuration is stored on the MGS in a special configuration llog. A client may access it via an llog API working over ptlrpc; &lt;br /&gt;
&lt;br /&gt;
* MDS_OST llog - contains records for unlink and setattr operations, performed on the MDS in the last, not committed transaction. This is needed to preserve consistency between MDS and OST nodes for failure cases. General case: If the MDS does not have an inode for some file, then the OST also should not have object for the same file. So, when the OST fails in the middle of unlink and loses the last transaction containing unlink for the OST object, this may cause the object to be lost on the OST. On the MDS, the current transaction with the unlinked object has finished and the MDS has no inode for the file. This means that the file cannot be accessed later and it just eats up space on the OST. The solution is to maintain the unlink log on the MDS and process it at MDS-OST connect time to make sure the OST has all objects unlinked; &lt;br /&gt;
&lt;br /&gt;
* Size llog - this is not yet used, but is planned to log object size changes on the OST so the MDS can later check if it has object size coherence with the MDS (SOM case); &lt;br /&gt;
&lt;br /&gt;
* LOVEA llog - joins the file LOV EA merge log. &lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;General design&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Each llog type has two main parts:&lt;br /&gt;
&lt;br /&gt;
* ORIG llog - &amp;quot;server&amp;quot; part, the site where llog records are stored. It provides an API for local and/or network llog access (read, modify). Examples of ORIG logs: MDS is orig for MDS_OST llog and MGS is orig for config logs; &lt;br /&gt;
&lt;br /&gt;
* REPL llog - &amp;quot;client&amp;quot; part, the site where llog records may be used. Examples of REPL logs: OST is repl for MDS_OST llog and MGC is repl for config logs.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Code&#039;&#039;&#039;&lt;br /&gt;
 obdclass/llog.c&lt;br /&gt;
 obdclass/llog_cat.c&lt;br /&gt;
 obdclass/llog_lvfs.c&lt;br /&gt;
 obdclass/llog_obd.c&lt;br /&gt;
 obdclass/llog_swab.c&lt;br /&gt;
 obdclass/llog_test.c&lt;br /&gt;
 lov/lov_log.c&lt;br /&gt;
 ptlrpc/llog_client.c&lt;br /&gt;
 ptlrpc/llog_server.c&lt;br /&gt;
 ptlrpc/llog_net.c&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
For more information, see [[Logging API]].&lt;br /&gt;
&lt;br /&gt;
==obdclass==&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Summary&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
The obdclass code is generic Lustre configuration and device handling. Different functional parts of the Lustre code are split into obd devices which can be configured and connected in various ways to form a server or client filesystem.&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
Several examples of obd devices include:&lt;br /&gt;
&lt;br /&gt;
* OSC - object storage client (connects over network to OST)&lt;br /&gt;
* OST - object storage target&lt;br /&gt;
* LOV - logical object volume (aggregates multipe OSCs into a single virtual device)&lt;br /&gt;
* MDC - meta data client (connects over network to MDT)&lt;br /&gt;
* MDT - meta data target &lt;br /&gt;
&lt;br /&gt;
The obdclass code provides services used by all Lustre devices for configuration, memory allocation, generic hashing, kernel interface routines, random number generation, etc. &lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Code&#039;&#039;&#039;&lt;br /&gt;
 lustre/obdclass/class_hash.c        - scalable hash code for imports&lt;br /&gt;
 lustre/obdclass/class_obd.c         - base device handling code&lt;br /&gt;
 lustre/obdclass/debug.c             - helper routines for dumping data structs&lt;br /&gt;
 lustre/obdclass/genops.c            - device allocation/configuration/connection&lt;br /&gt;
 lustre/obdclass/linux-module.       - linux kernel module handling&lt;br /&gt;
 lustre/obdclass/linux-obdo.c        - pack/unpack obdo and other IO structs&lt;br /&gt;
 lustre/obdclass/linux-sysctl.c      - /proc/sys configuration parameters &lt;br /&gt;
 lustre/obdclass/lprocfs_status.c    - /proc/fs/lustre configuration/stats, helpers&lt;br /&gt;
 lustre/obdclass/lustre_handles.c    - wire opaque pointer handlers&lt;br /&gt;
 lustre/obdclass/lustre_peer.c       - peer target identification by UUID&lt;br /&gt;
 lustre/obdclass/obd_config.c        - configuration file parsing&lt;br /&gt;
 lustre/obdclass/obd_mount.c         - server filesystem mounting&lt;br /&gt;
 lustre/obdclass/obdo.c              - more obdo handling helpers&lt;br /&gt;
 lustre/obdclass/statfs_pack.c       - statfs helpers for wire pack/unpack&lt;br /&gt;
 lustre/obdclass/uuid.c              - UUID pack/unpack&lt;br /&gt;
 lustre/lvfs/lvfs_common.c           - kernel interface helpers&lt;br /&gt;
 lustre/lvfs/lvfs_darwin.c           - darwin kernel helper routines&lt;br /&gt;
 lustre/lvfs/lvfs_internal.h         - lvfs internal function prototypes&lt;br /&gt;
 lustre/lvfs/lvfs_lib.c              - statistics&lt;br /&gt;
 lustre/lvfs/lvfs_linux.c            - linux kernel helper routines&lt;br /&gt;
 lustre/lvfs/lvfs_userfs.c           - userspace helper routines&lt;br /&gt;
 lustre/lvfs/prng.c                  - long period pseudo-random number generator&lt;br /&gt;
 lustre/lvfs/upcall_cache.c          - supplementary group upcall for MDS&lt;br /&gt;
&lt;br /&gt;
==luclass==&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Summary&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
luclass is a body of data-type definitions and functions implementing support for a layered object, that is an entity where every layer in the Lustre device stack (both data and meta-data, and both client and server side) can maintain its own private state, and modify a behavior of a compound object in a systematic way.&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
Specifically, data-types are introduced, representing a device type (struct lu_device_type, layer in the Lustre stack), a device (struct lu_device, a specific instance of the type), and object (struct lu_object). Following lu_object functionality is implemented by a generic code:&lt;br /&gt;
&lt;br /&gt;
* Compound object is uniquely identified by a FID, and is stored in a hash table, indexed by a FID; &lt;br /&gt;
&lt;br /&gt;
* Objects are kept in a LRU list, and a method to purge least recently accessed objects in reaction to the memory pressure is provided; &lt;br /&gt;
&lt;br /&gt;
* Objects are reference counted, and cached; &lt;br /&gt;
&lt;br /&gt;
* Every object has a list of &#039;&#039;layers&#039;&#039; (also known as slices), where devices can store their private state. Also, every slice comes with a pointer to an operations vector, allowing device to modify object&#039;s behavior. &lt;br /&gt;
&lt;br /&gt;
In addition to objects and devices, luclass includes lu_context, which is a way to efficiently allocate space, without consuming stack space.&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
luclass design is specified in the [http://arch.lustre.org/images/a/aa/Md-api-dld.pdf MD API] DLD.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Code&#039;&#039;&#039;&lt;br /&gt;
 include/lu_object.h&lt;br /&gt;
 obdclass/lu_object.c&lt;br /&gt;
&lt;br /&gt;
==ldlm==&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Summary&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
The Lustre Distributed Lock Manager (LDLM) is the Lustre locking infrastructure; it handles locks between clients and servers and locks local to a node. Different kinds of locks are available with different properties. Also as a historic heritage, ldlm happens to have some of the generic connection service code (both server and client).&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Code&#039;&#039;&#039; &lt;br /&gt;
 interval_tree.c           - This is used by extent locks to maintain interval trees (bug 11300)&lt;br /&gt;
 l_lock.c                  - Resourse locking primitives. &lt;br /&gt;
 ldlm_extent.c             - Extents locking code used for locking regions inside objects&lt;br /&gt;
 ldlm_flock.c              - Bsd and posix locking lock types&lt;br /&gt;
 ldlm_inodebits.c          - Inodebis locks used for metadata locking&lt;br /&gt;
 ldlm_lib.c                - Target and client connecting/reconnecting/recovery code.&lt;br /&gt;
                             Does not really belong to ldlm, but is historically placed &lt;br /&gt;
                             there. Should be in ptlrpc instead.&lt;br /&gt;
 ldlm_lock.c               - This source file mostly has functions dealing with struct&lt;br /&gt;
 ldlm_lock ldlm_lockd.c    - Functions that imply replying to incoming lock-related rpcs &lt;br /&gt;
                             (that could be both on server (lock enq/cancel/...) and client &lt;br /&gt;
                             (ast handling)).&lt;br /&gt;
 ldlm_plain.c              - Plain locks, predecessor to inodebits locks; not widely used now.&lt;br /&gt;
 ldlm_pool.c               - Pools of locks, related to dynamic lrus and freeing locks on demand.&lt;br /&gt;
 ldlm_request.c            - Collection of functions to work with locks based handles as opposed &lt;br /&gt;
                             to lock structures themselves.&lt;br /&gt;
 ldlm_resource.c           - Functions operating on namespaces and lock resources.&lt;br /&gt;
 include/lustre_dlm.h      - Important defines and declarations for ldlm.&lt;br /&gt;
&lt;br /&gt;
==fids==&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Summary&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
FID is unique object identifier in cluster since 1.7. It has few properties, main of them are the following:&lt;br /&gt;
&lt;br /&gt;
* FID is unique and not reused object identifier;&lt;br /&gt;
* FID is allocated by client inside of the sequence granted by server;&lt;br /&gt;
* FID is base for ldlm resource used for issuing ldlm locks. This is because FID is unique and as such good for this using;&lt;br /&gt;
* FID is base for building client side inode numbers as we can&#039;t use server inode+generation anymore, in CMD this is not unique combination;&lt;br /&gt;
* FID does not contain store information like inode number or generation and as such easy to migrate; &lt;br /&gt;
&lt;br /&gt;
FID consists of 3 fields:&lt;br /&gt;
&lt;br /&gt;
* f_seq - sequence number&lt;br /&gt;
* f_oid - object identifier inside sequence&lt;br /&gt;
* f_ver - object version &lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Code&#039;&#039;&#039;&lt;br /&gt;
 fid/fid_request.c&lt;br /&gt;
 fid/fid_lib.c&lt;br /&gt;
 fld/*.[ch]&lt;br /&gt;
&lt;br /&gt;
==seq==&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Summary&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Overview&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Sequence management is a basic mechanism in new MDS server which is related to managing FIDs.&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
FID is an unique object identifier in Lustre starting from version 1.7. All FIDs are organized into sequences. One sequence is number of FIDs. Sequences are granted/allocated to clients by servers. FIDs are allocated by clients inside granted sequence. All FIDs inside one sequence live on same MDS server and as such are one &amp;quot;migration unit&amp;quot; and one &amp;quot;indexing unit&amp;quot;, meaning that FLD (FIDs Location Database) indexes them all using one sequence and thus has only one mapping entry for all FIDs in sequence. Please read section devoted to FIDs bellow in the root table to find more info on FLD service and FIDs.&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
A sequence has the limit of FIDs to be allocated in it. When this limit is reached, new sequence is allocated. Upon disconnect, server allocates new sequence to the client when it comes back. Previously used sequence is abandoned even if it was not exhausted. Sequences are valuable resource but in the case of recovery, using new sequence makes things easier and also allows to group FIDs and objects by working sessions, new connection - new sequence.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Code description&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Server side code is divided into two parts:&lt;br /&gt;
&lt;br /&gt;
* Sequence controller - allocates super-sequences, that is, sequences of sequences to all servers in cluster (currently only to MDSes as only they are new FIDs aware). Usually first MDS in cluster is sequence controller &lt;br /&gt;
&lt;br /&gt;
* Sequence manager - allocates meta-sequences (smaller range of sequences inside a super-sequence) to all clients, using granted super-sequence from the sequence controller. All MDSs in the cluster (all servers in the future) are sequence managers. The first MDS is, simultaneously, a sequence controller and a sequence manager.&lt;br /&gt;
&lt;br /&gt;
Client side code allocates new sequences from granted meta-sequence. When meta-sequence is exhausted, new one is allocated on server and sent to the client.&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
Client code consists of API for working with both server side parts, not only with sequence manager as all servers need to talk to sequence controller, they also use client API for this.&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
One important part of client API is FIDs allocation. New FID is allocated in currently granted sequence until sequence is exhausted. &lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Code&#039;&#039;&#039;&lt;br /&gt;
 fid/fid_handler.c    - server side sequence management code;&lt;br /&gt;
 fid/fid_request.c    - client side sequence management code;&lt;br /&gt;
 fid/fid_lib.c        - fids related miscellaneous stuff.&lt;br /&gt;
&lt;br /&gt;
==mountconf==&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Summary&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
MountConf is how servers and clients are set up, started, and configured. A MountConf usage document is [http://wiki.lustre.org/index.php?title=Mount_Conf here].&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
The major subsystems are the MGS, MGC, and the userspace tools mount.lustre and mkfs.lustre.&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
The basic idea is:&lt;br /&gt;
&lt;br /&gt;
# Whenever any Lustre component is mount(2)ed, we start a MGC.&lt;br /&gt;
# This establishes a connection to the MGS and downloads a configuration llog.&lt;br /&gt;
# The MGC passes the configuration log through the parser to set up the other OBDs.&lt;br /&gt;
# The MGC holds a CR configuration lock, which the MGS recalls whenever a live configuration change is made. &lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Code&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
MountConf file areas:&lt;br /&gt;
&lt;br /&gt;
 lustre/mgs/*&lt;br /&gt;
 lustre/mgc/*&lt;br /&gt;
 lustre/obdclass/obd_mount.c&lt;br /&gt;
 lustre/utils/mount_lustre.c&lt;br /&gt;
 lustre/utils/mkfs_lustre.c&lt;br /&gt;
&lt;br /&gt;
==liblustre==&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Summary&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Liblustre is a userspace library, used along with libsysio (developed by Sandia), that allows Lustre usage just by linking (or ld_preload&#039;ing) applications with it. Liblustre does not require any kernel support. It is also used on old Cray XT3 machines (and not so old, in the case of Sandia), where all applications are just linked with the library and loaded into memory as the only code to run. Liblustre does not support async operations of any kind due to a lack of interrupts and other notifiers from lower levels to Lustre. Liblustre includes another set of LNDs that are able to work from userspace.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Code&#039;&#039;&#039;&lt;br /&gt;
 dir.c          - Directory operations&lt;br /&gt;
 file.c         - File handling operations (like open)&lt;br /&gt;
 llite_lib.c    - General support (init/cleanp/parse options)&lt;br /&gt;
 lutil.c        - Supplementary code to get IP addresses and init various structures &lt;br /&gt;
                  needed to emulate the normal Linux process from other layers&#039; perspective.&lt;br /&gt;
 namei.c        - Metadata operations code.&lt;br /&gt;
 rw.c           - I/O code, including read/write&lt;br /&gt;
 super.c        - &amp;quot;Superblock&amp;quot; operation - mounting/umounting, inode operations.&lt;br /&gt;
 tests          - directory with liblustre-specific tests.&lt;br /&gt;
&lt;br /&gt;
==echo client/server==&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Summary&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
The echo_client and obdecho are OBD devices which help testing and performance measurement.&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
They were implemented originally for network testing - obdecho can replace obdfilter and echo_client can exercise any downstream configurations. They are normally used in the following configurations:&lt;br /&gt;
&lt;br /&gt;
* echo_client -&amp;gt; obdfilter. This is used to measure raw backend performance without any network I/O. &lt;br /&gt;
* echo_client -&amp;gt; OSC -&amp;gt; &amp;lt;network&amp;gt; -&amp;gt; OST -&amp;gt; obdecho. This is used to measure network and ptlrpc performance. &lt;br /&gt;
* echo_client -&amp;gt; OSC -&amp;gt; &amp;lt;network&amp;gt; -&amp;gt; OST -&amp;gt; obdfilter. This is used to measure performance available to the Lustre client. &lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Code&#039;&#039;&#039;&lt;br /&gt;
 lustre/obdecho/&lt;br /&gt;
&lt;br /&gt;
==client vfs==&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Summary&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
The client VFS interface, also called &#039;&#039;&#039;llite&#039;&#039;&#039;, is the bridge between the Linux kernel and the underlying Lustre infrastructure represented by the [https://wikis.clusterfs.com/intra/index.php/Lov_summary LOV], [https://wikis.clusterfs.com/intra/index.php/Client_metadata_summary MDC], and [https://wikis.clusterfs.com/intra/index.php/Ldlm_summary LDLM] subsystems. This includes mounting the client filesystem, handling name lookups, starting file I/O, and handling file permissions.&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
The Linux VFS interface shares a lot in common with the liblustre interface, which is used in the Catamount environment; as of yet, the code for these two subsystems is not common and contains a lot of duplication.  &lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Code&#039;&#039;&#039;&lt;br /&gt;
 lustre/llite/dcache.c            - Interface with Linux dentry cache/intents&lt;br /&gt;
 lustre/llite/dir.c               - readdir handling, filetype in dir, dir ioctl&lt;br /&gt;
 lustre/llite/file.c              - File handles, file ioctl, DLM extent locks&lt;br /&gt;
 lustre/llite/llite_close.c       - File close for opencache&lt;br /&gt;
 lustre/llite/llite_internal.h    - Llite internal function prototypes, structures&lt;br /&gt;
 lustre/llite/llite_lib.c         - Majority of request handling, client mount&lt;br /&gt;
 lustre/llite/llite_mmap.c        - Memory-mapped I/O&lt;br /&gt;
 lustre/llite/llite_nfs.c         - NFS export from clients&lt;br /&gt;
 lustre/llite/lloop.c             - Loop-like block device export from object&lt;br /&gt;
 lustre/llite/lproc_llite.c       - /proc interface for tunables, statistics&lt;br /&gt;
 lustre/llite/namei.c             - Filename lookup, intent handling&lt;br /&gt;
 lustre/llite/rw24.c              - Linux 2.4 IO handling routines&lt;br /&gt;
 lustre/llite/rw26.c              - Linux 2.6 IO handling routines&lt;br /&gt;
 lustre/llite/rw.c                - Linux generic IO handling routines&lt;br /&gt;
 lustre/llite/statahead.c         - Directory statahead for &amp;quot;ls -l&amp;quot; and &amp;quot;rm -r&amp;quot;&lt;br /&gt;
 lustre/llite/super25.c           - Linux 2.6 VFS file method registration&lt;br /&gt;
 lustre/llite/super.c             - Linux 2.4 VFS file method registration&lt;br /&gt;
 lustre/llite/symlink.c           - Symbolic links&lt;br /&gt;
 lustre/llite/xattr.c             - User-extended attributes&lt;br /&gt;
&lt;br /&gt;
==client vm==&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Summary&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Client code interacts with VM/MM subsystems of the host OS kernel to cache data (in the form of pages), and to react to various memory-related events, like memory pressure.&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
Two key components of this interaction are:&lt;br /&gt;
&lt;br /&gt;
* cfs_page_t data-type representing MM page. It comes together with the interface to map/unmap page to/from kernel virtual address space, access various per-page bits, like &#039;dirty&#039;, &#039;uptodate&#039;, etc., lock/unlock page. Currently, this data-type closely matches the Linux kernel page. It has to be straightened out, formalized, and expanded to include functionality like querying about total number of pages on a node, etc. &lt;br /&gt;
* MM page operations in cl_page (part of new client I/O interface). &lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Code&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
This describes the &#039;&#039;next generation&#039;&#039; Lustre client I/O code, which is expected to appear in Lustre 2.0. Code location is not finalized.&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
cfs_page_t interface is defined and implemented in:&lt;br /&gt;
&lt;br /&gt;
 lnet/include/libcfs/ARCH/ARCH-mem.h&lt;br /&gt;
 lnet/libcfs/ARCH/ARCH-mem.c &lt;br /&gt;
&lt;br /&gt;
Generic part of cl-page will be located in:&lt;br /&gt;
&lt;br /&gt;
 include/cl_object.h&lt;br /&gt;
 obdclass/cl_page.c&lt;br /&gt;
 obdclass/cl_object.c &lt;br /&gt;
&lt;br /&gt;
Linux kernel implementation is currently in:&lt;br /&gt;
&lt;br /&gt;
 llite/llite_cl.c&lt;br /&gt;
&lt;br /&gt;
==client I/O==&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Summary&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Client I/O is a group of interfaces used by various layers of a Lustre client to manage file data (as opposed to metadata). Main functions of these interfaces are:&lt;br /&gt;
&lt;br /&gt;
* Cache data, respecting limitations imposed both by hosting MM/VM, and by cluster-wide caching policies, and &lt;br /&gt;
* Form a stream of efficient I/O RPCs, respecting both ordering/timing constraints imposed by the hosting VFS (e.g., POSIX guarantees, O_SYNC, etc.), and cluster-wide IO scheduling policies. &lt;br /&gt;
&lt;br /&gt;
Client I/O subsystem interacts with VFS, VM/MM, DLM, and PTLRPC.&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
Client I/O interfaces are based on the following data-types:&lt;br /&gt;
&lt;br /&gt;
* cl_object: represents a file system object, both a file, and a stripe; &lt;br /&gt;
* cl_page: represents a cached data page; &lt;br /&gt;
* cl_lock: represents an extent DLM lock; &lt;br /&gt;
* cl_io: represents an ongoing high-level IO activity, like read(2)/write(2) system call, or sub-io of another IO; &lt;br /&gt;
* cl_req: represents a network RPC. &lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Code&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
This describes the &#039;&#039;next generation&#039;&#039; Lustre client I/O code. The code location is not finalized. The generic part is at:&lt;br /&gt;
&lt;br /&gt;
 include/cl_object.h&lt;br /&gt;
 obdclass/cl_object.c&lt;br /&gt;
 obdclass/cl_page.c&lt;br /&gt;
 obdclass/cl_lock.c&lt;br /&gt;
 obdclass/cl_io.c &lt;br /&gt;
&lt;br /&gt;
Layer-specific methods are currently at:&lt;br /&gt;
&lt;br /&gt;
 lustre/LAYER/LAYER_cl.c &lt;br /&gt;
&lt;br /&gt;
where LAYER is one of llite, lov, osc.&lt;br /&gt;
&lt;br /&gt;
==client metadata==&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Summary&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
The Meta Data Client (MDC) is the client-side interface for all operations related to the Meta Data Server  MDS. In current configurations there is a single MDC on the client for each filesystem mounted on the client. The MDC is responsible for enqueueing metadata locks (via  LDLM), and packing and unpacking messages on the wire.&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
In order to ensure a recoverable system, the MDC is limited at the client to only a single filesystem-modifying operation in flight at one time. This includes operations like create, rename, link, unlink, setattr.&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
For non-modifying operations like getattr and statfs the client can multiple RPC requests in flight at one time, limited by a tunable on the client, to avoid overwhelming the MDS. &lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Code&#039;&#039;&#039; &lt;br /&gt;
 lustre/mdc/lproc_mdc.c       - /proc interface for stats/tuning&lt;br /&gt;
 lustre/mdc/mdc_internal.h    - Internal header for prototypes/structs&lt;br /&gt;
 lustre/mdc/mdc_lib.c         - Packing of requests to MDS&lt;br /&gt;
 lustre/mdc/mdc_locks.c       - Interface to LDLM and client VFS intents&lt;br /&gt;
 lustre/mdc/mdc_reint.c       - Modifying requests to MDS&lt;br /&gt;
 lustre/mdc/mdc_request.c     - Non-modifying requests to MDS&lt;br /&gt;
&lt;br /&gt;
==client lmv== &lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Summary&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
LMV is a module which implements CMD client-side abstraction device. It allows client to work with many MDSes without any changes in Llite module and even without knowing that CMD is supported. Llite just translates Linux VFS requests into metadata API calls and forwards them down to the stack.&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
As LMV needs to know which MDS to talk for any particular operation, it uses some new services introduced in CMD3 times. They are:&lt;br /&gt;
&lt;br /&gt;
* FLD (Fids Location Database) - having FID or rather its sequence, lookup MDS number where this FID is located;&lt;br /&gt;
* SEQ (Client Sequence Manager) - LMV uses this via children MDCs for allocating new sequences and FIDs. &lt;br /&gt;
&lt;br /&gt;
LMV supports split objects. This means that for every split directory it creates special in-memory structure which contains information about object stripes. This includes MDS number, FID, etc. All consequent operations use these structures for determining what MDS should be used for particular action (create, take lock, etc).&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Code&#039;&#039;&#039;&lt;br /&gt;
 lmv/*.[ch]&lt;br /&gt;
&lt;br /&gt;
==lov==&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Summary&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
The LOV device presents a single virtual device interface to upper layers (llite, liblustre, MDS). The LOV code is responsible for splitting of requests to the correct OSTs based on striping information (lsm), and the merging of the replies to a single result to pass back to the higher layer.&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
It calculates per-object membership and offsets for read/write/truncate based on the virtual file offset passed from the upper layer. It is also responsible for splitting the locking across all servers as needed.&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
The LOV on the MDS is also involved in object allocation. &lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Code&#039;&#039;&#039;&lt;br /&gt;
 lustre/lov/lov_ea.c          - Striping attributes pack/unpack/verify&lt;br /&gt;
 lustre/lov/lov_internal.h    - Header for internal function prototypes/structs&lt;br /&gt;
 lustre/lov/lov_merge.c       - Struct aggregation from many objects&lt;br /&gt;
 lustre/lov/lov_obd.c         - Base LOV device configuration&lt;br /&gt;
 lustre/lov/lov_offset.c      - File offset and object calculations&lt;br /&gt;
 lustre/lov/lov_pack.c        - Pack/unpack of striping attributes&lt;br /&gt;
 lustre/lov/lov_qos.c         - Object allocation for different OST loading&lt;br /&gt;
 lustre/lov/lov_request.c     - Request handling/splitting/merging&lt;br /&gt;
 lustre/lov/lproc_lov.c       - /proc/fs/lustre/lov tunables/statistics&lt;br /&gt;
&lt;br /&gt;
==quota==&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Summary&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Quotas allow a system administrator to limit the maximum amount of disk space a user or group can consume. Quotas are set by root, and can be specified for individual users and/or groups. Quota limits can be set on both blocks and inodes.&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
Lustre quota enforcement differs from standard Linux quota support in several ways:&lt;br /&gt;
&lt;br /&gt;
* Lustre quota are administered via the lfs command, whereas standard Linux quota uses the quotactl interface.&lt;br /&gt;
* As Lustre is a distributed filesystem, lustre quotas are also distributed in order to limit the impact on performance.&lt;br /&gt;
* Quotas are allocated and consumed in a quantized fashion. &lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Code&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Quota core:&lt;br /&gt;
&lt;br /&gt;
 lustre/quota/quota_adjust_qunit.c&lt;br /&gt;
 lustre/quota/quota_check.c&lt;br /&gt;
 lustre/quota/quotacheck_test.c&lt;br /&gt;
 lustre/quota/quota_context.c&lt;br /&gt;
 lustre/quota/quota_ctl.c&lt;br /&gt;
 lustre/quota/quota_interface.c&lt;br /&gt;
 lustre/quota/quota_internal.h&lt;br /&gt;
 lustre/quota/quota_master.c &lt;br /&gt;
&lt;br /&gt;
Interactions with the underlying ldiskfs filesystem:&lt;br /&gt;
&lt;br /&gt;
 lustre/lvfs/fsfilt_ext3.c&lt;br /&gt;
 lustre/lvfs/lustre_quota_fmt.c&lt;br /&gt;
 lustre/lvfs/lustre_quota_fmt_convert.c &lt;br /&gt;
&lt;br /&gt;
Hooks under:&lt;br /&gt;
&lt;br /&gt;
 lustre/mds&lt;br /&gt;
 lustre/obdfilter &lt;br /&gt;
&lt;br /&gt;
Regression tests:&lt;br /&gt;
&lt;br /&gt;
 lustre/tests/sanity-quota.sh&lt;br /&gt;
&lt;br /&gt;
==security-gss==&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Summary&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
The secure ptlrpc (sptlrpc) is a framework inside of ptlrpc layer. It act upon both side of each ptlrpc connection between 2 nodes, doing transformation on every RPC message, turn this into a secure communication link. By using GSS, sptlrpc is able to support multiple authentication mechanism, but currently we only support Kerberos 5.&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
Supported security flavors:&lt;br /&gt;
&lt;br /&gt;
* null: no authentication, no data transform, thus no performance overhead; compatible with 1.6;&lt;br /&gt;
* plain: no authentication, simple data transform, minimal performance overhead;&lt;br /&gt;
* krb5x: per-user basis client-server mutual authentication using Kerberos 5, sign or encrypt data, could have substantial CPU overhead. &lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Code&#039;&#039;&#039;&lt;br /&gt;
 lustre/ptlrpc/sec*.c&lt;br /&gt;
 lustre/ptlrpc/gss/&lt;br /&gt;
 lustre/utils/gss/&lt;br /&gt;
&lt;br /&gt;
==security-capa==&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Summary&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Capabilities are pieces of data generated by one service - the master service, passed to a client and presented by the client to another service - the slave service, to authorize an action. It is independent from the R/W/X permission based file operation authorization.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Code&#039;&#039;&#039;&lt;br /&gt;
 lustre/llite/llite_capa.c&lt;br /&gt;
 lustre/mdt/mdt_capa.c&lt;br /&gt;
 lustre/obdfilter/filter_capa.c&lt;br /&gt;
 lustre/obdclass/capa.c&lt;br /&gt;
 lustre/include/lustre_capa.h&lt;br /&gt;
&lt;br /&gt;
==security-identity== &lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Summary&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Lustre identity is a miscellaneous framework for lustre file operation authorization. Generally, it can be divided into two parts:&lt;br /&gt;
&lt;br /&gt;
* User-identity parse / upcall / mapping.&lt;br /&gt;
* File operation permission maintenance and check, includes the traditional file mode based permission and ACL based permission.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Code&#039;&#039;&#039; &lt;br /&gt;
 /llite/llite_rmtacl.c&lt;br /&gt;
 lustre/mdt/mdt_identity.c&lt;br /&gt;
 lustre/mdt/mdt_idmap.c&lt;br /&gt;
 lustre/mdt/mdt_lib.c&lt;br /&gt;
 lustre/obdclass/idmap.c&lt;br /&gt;
 lustre/utils/l_getidentity.c&lt;br /&gt;
 lustre/include/lustre_idmap.h &lt;br /&gt;
&lt;br /&gt;
 lustre/llite/xattr.c&lt;br /&gt;
 lustre/mdt/mdt_xattr.c&lt;br /&gt;
 lustre/cmm/cmm_object.c&lt;br /&gt;
 lustre/cmm/mdc_object.c&lt;br /&gt;
 lustre/mdd/mdd_permission.c&lt;br /&gt;
 lustre/mdd/mdd_object.c&lt;br /&gt;
 lustre/mdd/mdd_dir.c&lt;br /&gt;
 lustre/obdclass/acl.c&lt;br /&gt;
 lustre/include/lustre_eacl.h&lt;br /&gt;
&lt;br /&gt;
==OST== &lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Summary&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
OST is a very thin layer of data server. Its main responsibility is to translate RPCs to local calls of obdfilter, i.e. RPC parsing.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Code&#039;&#039;&#039; &lt;br /&gt;
 lustre/ost/*.[ch]&lt;br /&gt;
&lt;br /&gt;
==ldiskfs== &lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Summary&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
ldiskfs is local disk filesystem built on top of ext3. it adds extents support to ext3, multiblock allocator, multimount protection and iopen features.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Code&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
There is no ldiskfs source code in the Lustre repositories (only patches). Instead, ext3 code is copied from your build kernel, the patches are applied and then whole thing gets renamed to ldiskfs. For details, go to ldiskfs/.&lt;br /&gt;
&lt;br /&gt;
==fsfilt== &lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Summary&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
The fsfilt layer abstracts the backing filesystem specifics away from the obdfilter and mds code in 1.4 and 1.6 lustre. This avoids linking the obdfilter and mds directly against the filesystem module, and in theory allows different backing filesystems, but in practise this was never implemented. In Lustre 1.8 and later this code is replaced by the OSD layer.&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
There is a core fsfilt module which can auto-load the backing filesystem type based on the type specified during configuration. This loads a filesystem-specific fsfilt_{fstype} module with a set of methods for that filesystem.&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
There are a number of different kinds of methods:&lt;br /&gt;
&lt;br /&gt;
* Get/set filesystem label and UUID for identifying the backing filesystem&lt;br /&gt;
* Start, extend, commit compound filesystem transactions to allow multi-file updates to be atomic for recovery&lt;br /&gt;
* Set a journal callback for transaction disk commit (for Lustre recovery)&lt;br /&gt;
* Store attributes in the inode (possibly avoiding side-effects like truncation when setting the inode size to zero)&lt;br /&gt;
* Get/set file attributes (EAs) for storing LOV and OST info (e.g. striping)&lt;br /&gt;
* Perform low-level IO on the file (avoiding cache)&lt;br /&gt;
* Get/set file version (for future recovery mechanisms)&lt;br /&gt;
* Access quota information &lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Code&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
The files used for the fsfilt code reside in:&lt;br /&gt;
&lt;br /&gt;
 lustre/lvfs/fsfilt.c         - Interface used by obdfilter/MDS, module autoloading&lt;br /&gt;
 lustre/lvfs/fsfilt_ext3.c    - Interface to ext3/ldiskfs filesystem&lt;br /&gt;
&lt;br /&gt;
The &#039;&#039;fsfilt_ldiskfs.c&#039;&#039; file is auto-generated from &#039;&#039;fsfilt_ext3.c&#039;&#039; in &#039;&#039;lustre/lvfs/autoMakefile.am&#039;&#039; using sed to replace instances of ext3 and EXT3 with ldiskfs, and a few other replacements to avoid symbol clashes.&lt;br /&gt;
&lt;br /&gt;
==ldiskfs OSD==&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Summary&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
ldiskfs-OSD is an implementation of dt_{device,object} interfaces on top of (modified) ldiskfs file-system.&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
It uses standard ldiskfs/ext3 code to do file I/O.&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
It supports 2 types of indices (in the same file system):&lt;br /&gt;
&lt;br /&gt;
* iam-based index: this is an extension of ext3 htree directory format with support for more general keys and values, and with relaxed size restrictions, and &lt;br /&gt;
* compatibility index: this is usual ldiskfs directory, accessible through dt_index_operations. &lt;br /&gt;
&lt;br /&gt;
ldiskfs-OSD uses read-write mutex to serialize compound operations. &lt;br /&gt;
&amp;lt;/blockquote&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Code&#039;&#039;&#039; &lt;br /&gt;
 lustre/include/dt_object.h&lt;br /&gt;
 lustre/osd/osd_internal.h&lt;br /&gt;
 lustre/osd/osd_handler.c&lt;br /&gt;
&lt;br /&gt;
==DMU OSD== &lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Summary&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
This is another implementation of the OSD API for userspace DMU. It uses DMU&#039;s ZAP for indices.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Code&#039;&#039;&#039;&lt;br /&gt;
 dmu-osd/*.[ch] in b_hd_dmu branch&lt;br /&gt;
&lt;br /&gt;
==DMU== &lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Summary&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
The DMU is one of the layers in Sun&#039;s ZFS filesystem which is responsible for presenting a transactional object store to its consumers. It is used as Lustre&#039;s backend object storage mechanism for the userspace MDSs and OSSs.&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
The ZFS community page has a source tour which is useful as an introduction to the several ZFS layers: [http://www.opensolaris.org/os/community/zfs/source/ ZFS source]&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
There are many useful resources in that community page.&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
For reference, here&#039;s a list of DMU features:&lt;br /&gt;
&lt;br /&gt;
* Atomic transactions&lt;br /&gt;
* End-to-end data and metadata checksumming (currently supports fletcher2, fletcher4 and sha-256)&lt;br /&gt;
* Compression (currently supports lzjb and gzip with compression levels 1..9)&lt;br /&gt;
* Snapshots and clones&lt;br /&gt;
* Variable block sizes (currently supports sector sizes from 512 bytes to 128KB)&lt;br /&gt;
* Integrated volume management with support for RAID-1, RAID-Z and RAID-Z2 and striping&lt;br /&gt;
* Metadata and optional data redundancy (ditto blocks) atop the inherent storage pool redundancy for high resilience&lt;br /&gt;
* Self-healing, which works due to checksumming, ditto blocks and pool redundancy&lt;br /&gt;
* Storage devices that act as level-2 caches (designed for flash storage)&lt;br /&gt;
* Hot spares&lt;br /&gt;
* Designed with scalability in mind - supports up to 2^64 bytes per object, 2^48 objects per filesystem, 2^64 filesystems per pool, 2^64 bytes per device, 2^64 devices per pool, ..&lt;br /&gt;
* Very easy to use admin interface (zfs and zpool commands) &lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Code&#039;&#039;&#039; &lt;br /&gt;
 src/&lt;br /&gt;
 source code&lt;br /&gt;
 &lt;br /&gt;
 src/cmd/              - ZFS/DMU related programs&lt;br /&gt;
 src/cmd/lzfs/         - lzfs, the filesystem administration utility&lt;br /&gt;
 src/cmd/lzpool/       - lzpool, the pool administration utility&lt;br /&gt;
 src/cmd/lzdb/         - lzdb, the zfs debugger&lt;br /&gt;
 src/cmd/lztest/       - lztest, the DMU test suite&lt;br /&gt;
 src/cmd/lzfsd/        - lzfsd, the ZFS daemon&lt;br /&gt;
 &lt;br /&gt;
 src/lib/              - Libraries&lt;br /&gt;
 src/lib/port/         - Portability layer&lt;br /&gt;
 src/lib/solcompat/    - Solaris -&amp;gt; Linux portability layer (deprecated, use libport instead)&lt;br /&gt;
 src/lib/avl/          - AVL trees, used in many places in the DMU code&lt;br /&gt;
 src/lib/nvpair/       - Name-value pairs, used in many places in the DMU code&lt;br /&gt;
 src/lib/umem/         - Memory management library&lt;br /&gt;
 src/lib/zpool/        - Main ZFS/DMU code&lt;br /&gt;
 src/lib/zfs/          - ZFS library used by the lzfs and lzpool utilities&lt;br /&gt;
 src/lib/zfscommon/    - Common ZFS code between libzpool and libzfs&lt;br /&gt;
 src/lib/ctl/          - Userspace control/management interface&lt;br /&gt;
 src/lib/udmu/         - Lustre uDMU code (thin library around the DMU)&lt;br /&gt;
 &lt;br /&gt;
 src/scons/            - local copy of SCons&lt;br /&gt;
 &lt;br /&gt;
 tests/regression/     - Regression tests&lt;br /&gt;
 &lt;br /&gt;
 misc/                 - miscellaneous files/scripts&lt;br /&gt;
&lt;br /&gt;
==obdfilter==&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Summary&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
obdfilter is a core component of OST (data server) making underlying disk filesystem a part of distributed system:&lt;br /&gt;
&lt;br /&gt;
* Maintains cluster-wide coherency for data&lt;br /&gt;
* Maintains space reservation for data in client&#039;s cache (grants)&lt;br /&gt;
* Maintains quota &lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Code&#039;&#039;&#039; &lt;br /&gt;
 lustre/obdfilter/*.[ch]&lt;br /&gt;
&lt;br /&gt;
==MDS==&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Summary&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
The MDS service in Lustre 1.4 and 1.6 is a monolithic body of code that provides multiple functions related to filesystem metadata. It handles the incoming RPCs and service threads for metadata operations (create, rename, unlink, readdir, etc), interfaces with the Lustre lock manager ([https://wikis.clusterfs.com/intra/index.php/Ldlm_summary DLM]), and also manages the underlying filesystem (via the [https://wikis.clusterfs.com/intra/index.php/Fsfilt_summary interface fsfilt] interface).&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
The MDS is the primary point of access control for clients, allocates the objects belonging to a file (in conjunction with [https://wikis.clusterfs.com/intra/index.php/Lov_summary LOV]) and passing that information to the clients when they access a file.&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
The MDS is also ultimately responsible for deleting objects on the OSTs, either by passing object information for destroy to the client removing the last link or open reference on a file and having the client do it, or by destroying the objects on the OSTs itself in case the client fails to do so.&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
In the 1.8 and later releases, the functionality provided by the MDS code has been split into multiple parts ([https://wikis.clusterfs.com/intra/index.php/Mdt_summary MDT], [https://wikis.clusterfs.com/intra/index.php/Mdd_summary MDD], OSD) in order to allow stacking of the metadata devices for clustered metadata.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Code&#039;&#039;&#039; &lt;br /&gt;
 lustre/mds/commit_confd.c&lt;br /&gt;
 lustre/mds/handler.c            - RPC request handler&lt;br /&gt;
 lustre/mds/lproc_mds.c          - /proc interface for stats/control&lt;br /&gt;
 lustre/mds/mds_fs.c             - Mount/configuration of underlying filesystem&lt;br /&gt;
 lustre/mds/mds_internal.h       - Header for internal declarations&lt;br /&gt;
 lustre/mds/mds_join.c           - Handle join_file operations&lt;br /&gt;
 lustre/mds/mds_lib.c            - Unpack of wire structs from requests&lt;br /&gt;
 lustre/mds/mds_log.c            - Lustre log interface (llog) for unlink/setattr&lt;br /&gt;
 lustre/mds/mds_lov.c            - Interface to LOV for create and orphan&lt;br /&gt;
 lustre/mds/mds_open.c           - File open/close handling&lt;br /&gt;
 lustre/mds/mds_reint.c          - Reintegration of changes made by clients&lt;br /&gt;
 lustre/mds/mds_unlink_open.c    - Handling of open-unlinked files (PENDING dir)&lt;br /&gt;
 lustre/mds/mds_xattr.c          - User-extended attribute handling&lt;br /&gt;
&lt;br /&gt;
==MDT==&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Summary&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
MDT stands for MetaData Target. This is a top-most layer in the MD server device stack. Responsibility of MDT are all this networking, as far as meta-data are concerned:&lt;br /&gt;
&lt;br /&gt;
* Managing PTLRPC services and threads;&lt;br /&gt;
* Receiving incoming requests, unpacking them and checking their validity;&lt;br /&gt;
* Sending replies;&lt;br /&gt;
* Handling recovery;&lt;br /&gt;
* Using DLM to guarantee cluster-wide meta-data consistency;&lt;br /&gt;
* Handling intents;&lt;br /&gt;
* Handling credential translation. &lt;br /&gt;
&lt;br /&gt;
Theoretically MDT is an optional layer: completely local Lustre setup, with single mete-data server, and locally mounted client can exist without MDT (and still use networking for non-metadata access). &lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Code&#039;&#039;&#039;&lt;br /&gt;
 lustre/mdt/mdt.mod.c&lt;br /&gt;
 lustre/mdt/mdt_capa.c&lt;br /&gt;
 lustre/mdt/mdt_handler.c&lt;br /&gt;
 lustre/mdt/mdt_identity.c&lt;br /&gt;
 lustre/mdt/mdt_idmap.c&lt;br /&gt;
 lustre/mdt/mdt_internal.h&lt;br /&gt;
 lustre/mdt/mdt_lib.c&lt;br /&gt;
 lustre/mdt/mdt_lproc.c&lt;br /&gt;
 lustre/mdt/mdt_open.c&lt;br /&gt;
 lustre/mdt/mdt_recovery.c&lt;br /&gt;
 lustre/mdt/mdt_reint.c&lt;br /&gt;
 lustre/mdt/mdt_xattr.c&lt;br /&gt;
&lt;br /&gt;
==CMM== &lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Summary&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Overview&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
The CMM is a new layer in the MDS which cares about all clustered metadata issues and relationships. The CMM does the following:&lt;br /&gt;
&lt;br /&gt;
* Acts as layer between the MDT and MDD.&lt;br /&gt;
* Provides MDS-MDS interaction.&lt;br /&gt;
* Queries and updates FLD.&lt;br /&gt;
* Does the local or remote operation if needed.&lt;br /&gt;
* Will do rollback - epoch control, undo logging. &lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;CMM functionality&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
CMM chooses all servers involved in operation and sends depended request if needed. The calling of remote MDS is a new feature related to the CMD. CMM mantain the list of MDC to connect with all other MDS.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Objects&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
The CMM can allocate two types of object - local and remote. Remote object can occur during metadata operations with more than one object involved. Such operation is called as cross-ref operation. &lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Code&#039;&#039;&#039; &lt;br /&gt;
 lustre/cmm&lt;br /&gt;
&lt;br /&gt;
==MDD== &lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Summary&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
MDD is metadata layer in the new MDS stack, which is the only layer operating the metadata in MDS. The implementation is similar as VFS meta operation but based on OSD storage. MDD API is currently only used in new MDS stack, called by CMM layer.&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
In theory, MDD should be local metadata layer, but for compatibility with old MDS stack and reuse some mds codes(llog and lov), a mds device is created and connected to the mdd. So the llog and lov in mdd still use original code through this temporary mds device. And it will be removed when the new llog and lov layer in the new MDS stack are implemented. &lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Code&#039;&#039;&#039;&lt;br /&gt;
 lustre/lustre/mdd/&lt;br /&gt;
&lt;br /&gt;
==recovery==&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Summary&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Overview&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Client recovery starts in case when no server reply is received within given timeout or when server tells to client that it is not connected (client was evicted on server earlier for whatever reason).&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
The recovery consists of trying to connect to server and then step through several recovery states during which various client-server data is synchronized, namely all requests that were already sent to server but not yet confirmed as received and DLM locks. Should any problems arise during recovery process (be it a timeout or server’s refuse to recognise client again), the recovery is restarted from the very beginning.&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
During recovery all new requests to the server are not sent to the server, but added to special delayed requests queue that is then sent once if recovery completes succesfully.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Replay and Resend&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
* Clients will go through all the requests in the sending and replay lists and determine the recovery action needed - replay request, resend request, cleanup up associated state for committed requests.&lt;br /&gt;
* The client replays requests which were not committed on the server, but for which the client saw reply from server before it failed. This allows the server to replay the changes to the persistent store.&lt;br /&gt;
* The client resends requests that were committed on the server, but the client did not see a reply for them, maybe due to server failure or network failure that caused the reply to be lost. This allows the server to reconstruct the reply and send it to the client.&lt;br /&gt;
* The client resends requests that the server has not seen at all, these would be all requests with transid higher than the last_rcvd value from the server and the last_committed transno, and the reply seen flag is not set.&lt;br /&gt;
* The client gets the last_committed transno information from the server and cleans up the state associated with requests that were committed on the server. &lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Code&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Recovery code is scattered through all code almost. Though important code:&lt;br /&gt;
 ldlm/ldlm_lib.c    - generic server recovery code &lt;br /&gt;
 ptlrpc/            - client recovery code&lt;br /&gt;
&lt;br /&gt;
==version recovery== &lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Summary&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Version Based Recovery&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
This recovery technique is based on using versions of objects (inodes) to allow clients to recover later than ordinary server recovery timeframe.&lt;br /&gt;
&lt;br /&gt;
# The server changes the version of object during any change and return that data to client. The version may be checked during replay to be sure that object is the same state during replay as it was originally.&lt;br /&gt;
# After failure the server starts recovery as usual but if some client miss the version check will be used for replays.&lt;br /&gt;
# Missed client can connect later and try to recover. This is &#039;delayed recovery&#039; and version check is used during it always.&lt;br /&gt;
# The client which missed main recovery window will not be evicted and can connect later to initiate recovery. In that case the versions will checked to determine was that object changed by someone else or not.&lt;br /&gt;
# When finished with replay, client and server check if any replay failed on any request because of version mismatch. If not, the client will get a successful reintegration message. If a version mismatch was encountered, the client must be evicted.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Code&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Recovery code is scattered through all code almost. Though important code:&lt;br /&gt;
 ldlm/ldlm_lib.c    - generic server recovery code &lt;br /&gt;
 ptlrpc/            - client recovery code&lt;br /&gt;
&lt;br /&gt;
==IAM== &lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Summary&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
IAM stands for &#039;Index Access Module&#039;: it is an extension to the ldiskfs directory code, adding generic indexing capability.&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
File system directory can be thought of as an index mapping keys, which are strings (file names), to the records which are integers (inode numbers). IAM removes limitations on key and record size and format, providing an abstraction of a transactional container, mapping arbitrary opaque keys into opaque records.&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
Implementation notes:&lt;br /&gt;
&lt;br /&gt;
* IAM is implemented as a set of patches to the ldiskfs;&lt;br /&gt;
* IAM is an extension of ldiskfs directory code that uses htree data-structure for scalable indexing;&lt;br /&gt;
* IAM uses fine-grained key-level and node-level locking (pdirops locking, designed and implemented by Alex Tomas);&lt;br /&gt;
* IAM doesn&#039;t assume any internal format keys. Keys are compared by memcmp() function (which dictates BE order for scalars);&lt;br /&gt;
* IAM supports different flavors of containers:&lt;br /&gt;
** lfix: fixed size record and fixed size keys,&lt;br /&gt;
** lvar: variable sized records and keys,&lt;br /&gt;
** htree: compatibility mode, allowing normal htree directory to be accessed as an IAM container; &lt;br /&gt;
* IAM comes with ioctl(2) based user-level interface. &lt;br /&gt;
&lt;br /&gt;
IAM is used by ldiskfs-OSD to implement dt_index_operations interface. &lt;br /&gt;
&amp;lt;/blockquote&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Code&#039;&#039;&#039;&lt;br /&gt;
 lustre/ldiskfs/kernel_patches/patches/ext3-iam-2.6-sles10.patch&lt;br /&gt;
 lustre/ldiskfs/kernel_patches/patches/ext3-iam-ops.patch&lt;br /&gt;
 lustre/ldiskfs/kernel_patches/patches/ext3-iam-2.6.18-rhel5.patch&lt;br /&gt;
 lustre/ldiskfs/kernel_patches/patches/ext3-iam-rhel4.patch&lt;br /&gt;
 lustre/ldiskfs/kernel_patches/patches/ext3-iam-2.6.18-vanilla.patch&lt;br /&gt;
 lustre/ldiskfs/kernel_patches/patches/ext3-iam-separate.patch&lt;br /&gt;
 lustre/ldiskfs/kernel_patches/patches/ext3-iam-2.6.9-rhel4.patch&lt;br /&gt;
 lustre/ldiskfs/kernel_patches/patches/ext3-iam-sles10.patch&lt;br /&gt;
 lustre/ldiskfs/kernel_patches/patches/ext3-iam-common.patch&lt;br /&gt;
 lustre/ldiskfs/kernel_patches/patches/ext3-iam-uapi.patch&lt;br /&gt;
&lt;br /&gt;
==SOM== &lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Summary&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Size-on-MDS is a metadata improvement, which includes the caching of the inode size, blocks, ctime and mtime on MDS. Such an attribute caching allows clients to avoid making RPCs to the OSTs to find the attributes encoded in the file objects kept on those OSTs what results in the significantly improved performance of listing directories.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Code&#039;&#039;&#039;&lt;br /&gt;
 llite/llite_close.c       - client-side SOM code&lt;br /&gt;
 liblustre/file.c          - liblustre SOM code&lt;br /&gt;
 mdt/mdt_handler.c         - general handling of SOM-related rpc&lt;br /&gt;
 mdt/mdt_open.c            - MDS side SOM code &lt;br /&gt;
 mdt/mdt_recovery.c        - MDS side SOM recovery code&lt;br /&gt;
 obdfilter/filter_log.c    - OST side IO epoch lloging code;&lt;br /&gt;
&lt;br /&gt;
==tests== &lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Summary&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
The &amp;quot;tests&amp;quot; subsystem is a set of scripts and programs which is used to test other lustre subsystems. It contains:&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;&#039;&#039;runtests&#039;&#039;&#039;&#039;&#039;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
Simple basic regression test&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&#039;&#039;&#039;&#039;&#039;sanity&#039;&#039;&#039;&#039;&#039;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
A set of regression tests that verify operation under normal operating &lt;br /&gt;
conditions&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&#039;&#039;&#039;&#039;&#039;fsx&#039;&#039;&#039;&#039;&#039;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
file system exerciser&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&#039;&#039;&#039;&#039;&#039;sanityn&#039;&#039;&#039;&#039;&#039;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
Tests that verify operations from two clients under normal operating conditions&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&#039;&#039;&#039;&#039;&#039;lfsck&#039;&#039;&#039;&#039;&#039;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
Tests e2fsck and lfsck to detect and fix filesystem corruption&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&#039;&#039;&#039;&#039;&#039;liblustre&#039;&#039;&#039;&#039;&#039;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
Runs a test linked to a liblustre client library&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&#039;&#039;&#039;&#039;&#039;replay-single&#039;&#039;&#039;&#039;&#039;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
A set of unit tests that verify recovery after MDS failure&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&#039;&#039;&#039;&#039;&#039;conf-sanity&#039;&#039;&#039;&#039;&#039;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
A set of unit tests that verify the configuration&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&#039;&#039;&#039;&#039;&#039;recovery-small&#039;&#039;&#039;&#039;&#039;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
A set of unit tests that verify RPC replay after communications failure&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&#039;&#039;&#039;&#039;&#039;replay-ost-single&#039;&#039;&#039;&#039;&#039;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
A set of unit tests that verify recovery after OST failure&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&#039;&#039;&#039;&#039;&#039;replay-dual&#039;&#039;&#039;&#039;&#039;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
A set of unit tests that verify the recovery from two clients after server failure&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&#039;&#039;&#039;&#039;&#039;insanity&#039;&#039;&#039;&#039;&#039;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
A set of tests that verify the multiple concurrent failure conditions&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&#039;&#039;&#039;&#039;&#039;sanity-quota&#039;&#039;&#039;&#039;&#039;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
A set of tests that verify filesystem quotas&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
The acceptance-small.sh is a wrapper which is normally used to run all (or any) of these scripts. In additional it is used to run the following pre-installed benchmarks:&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&#039;&#039;&#039;&#039;&#039;dbench&#039;&#039;&#039;&#039;&#039;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
Dbench benchmark for simulating N clients to produce the filesystem load&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&#039;&#039;&#039;&#039;&#039;bonnie&#039;&#039;&#039;&#039;&#039;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
Bonnie++ benchmark for creation, reading, and deleting many small files&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&#039;&#039;&#039;&#039;&#039;iozone&#039;&#039;&#039;&#039;&#039;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
Iozone benchmark for generating and measuring a variety of file operations.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Code&#039;&#039;&#039;&lt;br /&gt;
 lustre/tests/acl/run&lt;br /&gt;
 lustre/tests/acl/make-tree&lt;br /&gt;
 lustre/tests/acl/README&lt;br /&gt;
 lustre/tests/acl/setfacl.test&lt;br /&gt;
 lustre/tests/acl/getfacl-noacl.test&lt;br /&gt;
 lustre/tests/acl/permissions.test&lt;br /&gt;
 lustre/tests/acl/inheritance.test&lt;br /&gt;
 lustre/tests/acl/misc.test&lt;br /&gt;
 lustre/tests/acl/cp.test&lt;br /&gt;
 lustre/tests/cfg/local.sh&lt;br /&gt;
 lustre/tests/cfg/insanity-local.sh&lt;br /&gt;
 lustre/tests/ll_sparseness_write.c&lt;br /&gt;
 lustre/tests/writeme.c&lt;br /&gt;
 lustre/tests/cobd.sh&lt;br /&gt;
 lustre/tests/test_brw.c&lt;br /&gt;
 lustre/tests/ll_getstripe_info.c&lt;br /&gt;
 lustre/tests/lov-sanity.sh&lt;br /&gt;
 lustre/tests/sleeptest.c&lt;br /&gt;
 lustre/tests/flocks_test.c&lt;br /&gt;
 lustre/tests/getdents.c&lt;br /&gt;
 lustre/tests/ll_dirstripe_verify.c&lt;br /&gt;
 lustre/tests/sanity.sh&lt;br /&gt;
 lustre/tests/multifstat.c&lt;br /&gt;
 lustre/tests/sanityN.sh&lt;br /&gt;
 lustre/tests/liblustre_sanity_uml.sh&lt;br /&gt;
 lustre/tests/fsx.c&lt;br /&gt;
 lustre/tests/small_write.c&lt;br /&gt;
 lustre/tests/socketserver&lt;br /&gt;
 lustre/tests/cmknod.c&lt;br /&gt;
 lustre/tests/README&lt;br /&gt;
 lustre/tests/acceptance-metadata-double.sh&lt;br /&gt;
 lustre/tests/writemany.c&lt;br /&gt;
 lustre/tests/llecho.sh&lt;br /&gt;
 lustre/tests/lfscktest.sh&lt;br /&gt;
 lustre/tests/run-llog.sh&lt;br /&gt;
 lustre/tests/conf-sanity.sh&lt;br /&gt;
 lustre/tests/mmap_sanity.c&lt;br /&gt;
 lustre/tests/write_disjoint.c&lt;br /&gt;
 lustre/tests/ldaptest.c&lt;br /&gt;
 lustre/tests/acceptance-metadata-single.sh&lt;br /&gt;
 lustre/tests/compile.sh&lt;br /&gt;
 lustre/tests/mcreate.c&lt;br /&gt;
 lustre/tests/runas.c&lt;br /&gt;
 lustre/tests/replay-single.sh&lt;br /&gt;
 lustre/tests/lockorder.sh&lt;br /&gt;
 lustre/tests/test2.c&lt;br /&gt;
 lustre/tests/llog-test.sh&lt;br /&gt;
 lustre/tests/fchdir_test.c&lt;br /&gt;
 lustre/tests/mkdirdeep.c&lt;br /&gt;
 lustre/tests/runtests&lt;br /&gt;
 lustre/tests/flock.c&lt;br /&gt;
 lustre/tests/mlink.c&lt;br /&gt;
 lustre/tests/checkstat.c&lt;br /&gt;
 lustre/tests/crash-mod.sh&lt;br /&gt;
 lustre/tests/multiop.c&lt;br /&gt;
 lustre/tests/random-reads.c&lt;br /&gt;
 lustre/tests/disk1_4.zip&lt;br /&gt;
 lustre/tests/rundbench&lt;br /&gt;
 lustre/tests/wantedi.c&lt;br /&gt;
 lustre/tests/rename_many.c&lt;br /&gt;
 lustre/tests/leak_finder.pl&lt;br /&gt;
 lustre/tests/Makefile.am&lt;br /&gt;
 lustre/tests/parallel_grouplock.c&lt;br /&gt;
 lustre/tests/chownmany.c&lt;br /&gt;
 lustre/tests/ost_oos.sh&lt;br /&gt;
 lustre/tests/mkdirmany.c&lt;br /&gt;
 lustre/tests/directio.c&lt;br /&gt;
 lustre/tests/insanity.sh&lt;br /&gt;
 lustre/tests/createmany-mpi.c&lt;br /&gt;
 lustre/tests/createmany.c&lt;br /&gt;
 lustre/tests/runiozone&lt;br /&gt;
 lustre/tests/rmdirmany.c&lt;br /&gt;
 lustre/tests/replay-ost-single.sh&lt;br /&gt;
 lustre/tests/mcr.sh&lt;br /&gt;
 lustre/tests/mrename.c&lt;br /&gt;
 lustre/tests/sanity-quota.sh&lt;br /&gt;
 lustre/tests/lp_utils.c&lt;br /&gt;
 lustre/tests/lp_utils.h&lt;br /&gt;
 lustre/tests/acceptance-metadata-parallel.sh&lt;br /&gt;
 lustre/tests/oos.sh&lt;br /&gt;
 lustre/tests/createdestroy.c&lt;br /&gt;
 lustre/tests/toexcl.c&lt;br /&gt;
 lustre/tests/replay-dual.sh&lt;br /&gt;
 lustre/tests/createtest.c&lt;br /&gt;
 lustre/tests/munlink.c&lt;br /&gt;
 lustre/tests/iopentest1.c&lt;br /&gt;
 lustre/tests/iopentest2.c&lt;br /&gt;
 lustre/tests/openme.c&lt;br /&gt;
 lustre/tests/openclose.c&lt;br /&gt;
 lustre/tests/test-framework.sh&lt;br /&gt;
 lustre/tests/ll_sparseness_verify.c&lt;br /&gt;
 lustre/tests/it_test.c&lt;br /&gt;
 lustre/tests/unlinkmany.c&lt;br /&gt;
 lustre/tests/opendirunlink.c&lt;br /&gt;
 lustre/tests/filter_survey.sh&lt;br /&gt;
 lustre/tests/utime.c&lt;br /&gt;
 lustre/tests/openunlink.c&lt;br /&gt;
 lustre/tests/runvmstat&lt;br /&gt;
 lustre/tests/statmany.c&lt;br /&gt;
 lustre/tests/create.pl&lt;br /&gt;
 lustre/tests/oos2.sh&lt;br /&gt;
 lustre/tests/statone.c&lt;br /&gt;
 lustre/tests/rename.pl&lt;br /&gt;
 lustre/tests/set_dates.sh&lt;br /&gt;
 lustre/tests/openfilleddirunlink.c&lt;br /&gt;
 lustre/tests/openfile.c&lt;br /&gt;
 lustre/tests/llmountcleanup.sh&lt;br /&gt;
 lustre/tests/llmount.sh&lt;br /&gt;
 lustre/tests/acceptance-small.sh&lt;br /&gt;
 lustre/tests/truncate.c&lt;br /&gt;
 lustre/tests/recovery-small.sh&lt;br /&gt;
 lustre/tests/2ost.sh&lt;br /&gt;
 lustre/tests/tchmod.c&lt;br /&gt;
 lustre/tests/socketclient&lt;br /&gt;
 lustre/tests/runobdstat&lt;br /&gt;
 lustre/tests/memhog.c&lt;br /&gt;
 lustre/tests/flock_test.c&lt;br /&gt;
 lustre/tests/busy.sh&lt;br /&gt;
 lustre/tests/write_append_truncate.c&lt;br /&gt;
 lustre/tests/opendevunlink.c&lt;br /&gt;
 lustre/tests/o_directory.c&lt;br /&gt;
&lt;br /&gt;
==build== &lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Summary&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
The build system is responsible for building Lustre and related components (ldiskfs is normally included in the Lustre tree but can also live completely separately).&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
The main build process is managed using GNU Autoconf and Automake. Here is a brief outline of how a Lustre binary build from a fresh Git checkout works. User commands are shown in &#039;&#039;&#039;bold&#039;&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;sh autogen.sh&#039;&#039;&#039; - autogen performs a few checks and bootstraps the build system using automake and autoconf. It should only need to be called once after a fresh Git checkout, but sometimes it needs to be run again. See [https://bugzilla.lustre.org/show_bug.cgi?id=12580 bug 12580].&lt;br /&gt;
**Each component (Lustre and ldiskfs) has an autoMakefile.am in its toplevel directory that sets some variables and includes build/autoMakefile.am.toplevel. It also contains any toplevel autoMake code unique to that component.&lt;br /&gt;
** configure.ac is used by autoconf to generate a configure script. The Lustre configure.ac mostly relies on the macros defined in */autoconf/*.m4 to do its work. The ldiskfs configure.ac is more self-contained and relies only on build/autoconf/*.m4. &lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;./configure --with-linux=/root/cfs/kernels/linux-2.6.9-55.EL.HEAD&#039;&#039;&#039; - Configure performs extensive checks of the underlying system and kernel, then produces autoMakefiles and Makefiles. &lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;make&#039;&#039;&#039; - This is where things get really interesting.&lt;br /&gt;
** The @INCLUDE_RULES@ directive in most Makefile.in files includes a whole set of build rules from build/Makefile. See the top of that file for a description of all cases.&lt;br /&gt;
** Normally, it will include autoMakefile, so commands from that file will run.&lt;br /&gt;
** build/autoMakefile.am.toplevel is the basis of the autoMakefile produced in the toplevel directory. It includes the &amp;quot;modules&amp;quot; target.&lt;br /&gt;
** The modules target in turn calls the appropriate Linux make system if we are building on Linux.&lt;br /&gt;
** This build system once again reads the Makefile in each directory, and case 2 from build/Makefile is followed. &lt;br /&gt;
&lt;br /&gt;
So essentially, the Makefile.in controls the kernel build process, and the autoMakefile.am controls the userland build process as well as preparing the sources if necessary.&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
The build system can also be used to produce Lustre-patched kernels and binaries built against these kernels. The &#039;&#039;&#039;build/lbuild&#039;&#039;&#039; script does this - this is used by customers as well as the LTS. This script is in need of some serious cleanup, unfortunately.&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
Coding style note: as mentioned in [http://wiki.lustre.org/index.php?title=Coding_Guidelines Coding Guidelines], autoconf macros must follow the style specified in the [http://www.gnu.org/software/autoconf/manual/html_node/Coding-Style.html GNU Autoconf manual]. A lot of the older code has inconsistent style and is hard to follow - feel free to reformat when needed. New code &#039;&#039;&#039;must&#039;&#039;&#039; be styled correctly. &lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Code&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Lustre build system:&lt;br /&gt;
&lt;br /&gt;
* build/* (shared with ldiskfs)&lt;br /&gt;
* autogen.sh&lt;br /&gt;
* autoMakefile.am&lt;br /&gt;
* configure.ac&lt;br /&gt;
* lustre.spec.in&lt;br /&gt;
* Makefile.in&lt;br /&gt;
* all autoMakefile.am files&lt;br /&gt;
* all Makefile.in files &lt;br /&gt;
&lt;br /&gt;
ldiskfs build system:&lt;br /&gt;
&lt;br /&gt;
* build/* (shared with Lustre)&lt;br /&gt;
* autogen.sh&lt;br /&gt;
* autoMakefile.am&lt;br /&gt;
* configure.ac&lt;br /&gt;
* lustre-ldiskfs.spec.in&lt;br /&gt;
* Makefile.in&lt;br /&gt;
* all autoMakefile.am files&lt;br /&gt;
* all Makefile.in files&lt;/div&gt;</summary>
		<author><name>Nathan</name></author>
	</entry>
	<entry>
		<id>http://wiki.old.lustre.org/index.php?title=Acceptance_Small_(acc-sm)_Testing_on_Lustre&amp;diff=9064</id>
		<title>Acceptance Small (acc-sm) Testing on Lustre</title>
		<link rel="alternate" type="text/html" href="http://wiki.old.lustre.org/index.php?title=Acceptance_Small_(acc-sm)_Testing_on_Lustre&amp;diff=9064"/>
		<updated>2009-12-15T22:32:55Z</updated>

		<summary type="html">&lt;p&gt;Nathan: /* How do you get the acc-sm tests? */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;__TOC__&lt;br /&gt;
The Lustre™ QE group and developers use acceptance-small (acc-sm) tests to catch bugs early in the development cycle. Within the Lustre group, acc-sm tests are run on YALA, an automated test system. This information is being published to describe the steps to perform acceptance small testing and encourage wider acc-sm testing in the Lustre community.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;NOTE&#039;&#039;&#039;: For your convenience, this document is also available as a [http://wiki.lustre.org/images/c/c6/AccSm_Testing.pdf PDF].&lt;br /&gt;
&lt;br /&gt;
==What is acc-sm testing and why do we use it for Lustre?==&lt;br /&gt;
&lt;br /&gt;
Acceptance small (acc-sm) testing is a suite of test cases used to verify different aspects of Lustre functionality.&lt;br /&gt;
&lt;br /&gt;
* These tests are run using the acceptance-small.sh script. &lt;br /&gt;
* The script is run from the lustre/tests directory in a compiled Lustre tree. &lt;br /&gt;
* The acceptance-small.sh script runs a number of test scripts that are also run by the ltest (Buffalo) test harness on Lustre test clusters.&lt;br /&gt;
&lt;br /&gt;
==What tests comprise the acc-sm test suite?==&lt;br /&gt;
&lt;br /&gt;
Each Lustre tree contains a lustre/tests sub-directory; all acc-sm tests are stored here. The acceptance-small.sh file contains a list of all tests in the acc-sm suite. To get the list, run:&lt;br /&gt;
&lt;br /&gt;
 $ grep TESTSUITE_LIST acceptance-small.sh&lt;br /&gt;
&lt;br /&gt;
The acc-sm tests are listed below, by branch.&lt;br /&gt;
&lt;br /&gt;
====b1_6 branch====&lt;br /&gt;
&lt;br /&gt;
This branch includes 17 acc-sm test suites.&lt;br /&gt;
&lt;br /&gt;
 $ grep TESTSUITE_LIST acceptance-small.sh&lt;br /&gt;
 export TESTSUITE_LIST=&amp;quot;RUNTESTS SANITY DBENCH BONNIE IOZONE FSX SANITYN LFSCK&lt;br /&gt;
 LIBLUSTRE REPLAY_SINGLE CONF_SANITY RECOVERY_SMALL REPLAY_OST_SINGLE&lt;br /&gt;
 REPLAY_DUAL INSANITY SANITY_QUOTA PERFORMANCE_SANITY&amp;quot;&lt;br /&gt;
&lt;br /&gt;
====b1_8_gate branch====&lt;br /&gt;
&lt;br /&gt;
This branch includes 18 acc-sm test suites.&lt;br /&gt;
&lt;br /&gt;
 $ grep TESTSUITE_LIST acceptance-small.sh&lt;br /&gt;
 export TESTSUITE_LIST=&amp;quot;RUNTESTS SANITY DBENCH BONNIE IOZONE FSX SANITYN LFSCK&lt;br /&gt;
 LIBLUSTRE REPLAY_SINGLE CONF_SANITY RECOVERY_SMALL REPLAY_OST_SINGLE&lt;br /&gt;
 REPLAY_DUAL REPLAY_VBR INSANITY SANITY_QUOTA PERFORMANCE_SANITY&amp;quot;&lt;br /&gt;
&lt;br /&gt;
====HEAD branch====&lt;br /&gt;
&lt;br /&gt;
This branch includes 19 acc-sm test suites.&lt;br /&gt;
&lt;br /&gt;
 $ grep TESTSUITE_LIST acceptance-small.sh&lt;br /&gt;
 export TESTSUITE_LIST=&amp;quot;RUNTESTS SANITY DBENCH BONNIE IOZONE FSX SANITYN LFSCK&lt;br /&gt;
 LIBLUSTRE REPLAY_SINGLE CONF_SANITY RECOVERY_SMALL REPLAY_OST_SINGLE&lt;br /&gt;
 REPLAY_DUAL INSANITY SANITY_QUOTA SANITY_SEC SANITY_GSS&lt;br /&gt;
 PERFORMANCE_SANITY&amp;quot;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
To see the test cases in a particular acc-sm test, run:&lt;br /&gt;
&lt;br /&gt;
 $ grep run_ &amp;lt;test suite script&amp;gt;&lt;br /&gt;
&lt;br /&gt;
For example, to see the last 3 test cases that comprise the SANITY test:&lt;br /&gt;
&lt;br /&gt;
 $ grep run_ sanity.sh | tail -3&lt;br /&gt;
&lt;br /&gt;
 run_test 130c &amp;quot;FIEMAP (2-stripe file with hole)&amp;quot;&lt;br /&gt;
 run_test 130d &amp;quot;FIEMAP (N-stripe file)&amp;quot;&lt;br /&gt;
 run_test 130e &amp;quot;FIEMAP (test continuation FIEMAP calls)&amp;quot;&lt;br /&gt;
&lt;br /&gt;
==What does each acc-sm test measure or show?==&lt;br /&gt;
&lt;br /&gt;
The acc-sm test suite are described below.&lt;br /&gt;
&lt;br /&gt;
;&#039;&#039;&#039;RUNTESTS&#039;&#039;&#039;&lt;br /&gt;
: A basic regression test with unmount/remount.&lt;br /&gt;
&lt;br /&gt;
;&#039;&#039;&#039;SANITY&#039;&#039;&#039;&lt;br /&gt;
: Verifies Lustre operation under normal operating conditions.&lt;br /&gt;
&lt;br /&gt;
;&#039;&#039;&#039;DBENCH&#039;&#039;&#039;&lt;br /&gt;
:Dbench benchmark for simulating N clients to produce the filesystem load.&lt;br /&gt;
&lt;br /&gt;
;&#039;&#039;&#039;BONNIE&#039;&#039;&#039;&lt;br /&gt;
:Bonnie++ benchmark for creation, reading and deleting many small files&lt;br /&gt;
&lt;br /&gt;
;&#039;&#039;&#039;IOZONE&#039;&#039;&#039;&lt;br /&gt;
:IOzone benchmark for generating and measuring a variety of file operations.&lt;br /&gt;
&lt;br /&gt;
;&#039;&#039;&#039;FSX&#039;&#039;&#039;&lt;br /&gt;
:Filesystem exerciser.&lt;br /&gt;
&lt;br /&gt;
;&#039;&#039;&#039;SANITYN&#039;&#039;&#039;&lt;br /&gt;
:Verifies operations from two clients under normal operating conditions.&lt;br /&gt;
&lt;br /&gt;
;&#039;&#039;&#039;LFSCK&#039;&#039;&#039;&lt;br /&gt;
:Tests e2fsck and lfsck to detect and fix filesystm corruption.&lt;br /&gt;
&lt;br /&gt;
;&#039;&#039;&#039;LIBLUSTRE&#039;&#039;&#039;&lt;br /&gt;
:Runs a test linked to a liblustre client library.&lt;br /&gt;
&lt;br /&gt;
;&#039;&#039;&#039;REPLAY_SINGLE&#039;&#039;&#039;&lt;br /&gt;
:Verifies recovery after an MDS failure.&lt;br /&gt;
&lt;br /&gt;
;&#039;&#039;&#039;CONF_SANITY&#039;&#039;&#039;&lt;br /&gt;
:Verifies various Lustre configurations (including wrong ones), where the system must behave correctly.&lt;br /&gt;
&lt;br /&gt;
;&#039;&#039;&#039;RECOVERY_SMALL&#039;&#039;&#039;&lt;br /&gt;
:Verifies RPC replay after a communications failure (message loss).&lt;br /&gt;
&lt;br /&gt;
;&#039;&#039;&#039;REPLAY_OST_SINGLE&#039;&#039;&#039;&lt;br /&gt;
:Verifies recovery after an OST failure.&lt;br /&gt;
&lt;br /&gt;
;&#039;&#039;&#039;REPLAY_DUAL&#039;&#039;&#039;&lt;br /&gt;
:Verifies recovery from two clients after a server failure.&lt;br /&gt;
&lt;br /&gt;
;&#039;&#039;&#039;INSANITY&#039;&#039;&#039;&lt;br /&gt;
:Tests multiple concurrent failure conditions.&lt;br /&gt;
&lt;br /&gt;
;&#039;&#039;&#039;SANITY_QUOTA&#039;&#039;&#039;&lt;br /&gt;
:Verifies filesystem quotas.&lt;br /&gt;
&lt;br /&gt;
==How do you get the acc-sm tests?==&lt;br /&gt;
&lt;br /&gt;
The acc-sm test suite is stored in the lustre/tests subdirectory.&lt;br /&gt;
&lt;br /&gt;
==Do you have to run every acc-sm test?==&lt;br /&gt;
&lt;br /&gt;
No. You can choose to run only specified acc-sm tests. Tests can be run either with or without the acceptance-sm.sh (acc-sm.sh) wrapper script. Here are several examples:&lt;br /&gt;
&lt;br /&gt;
To only run the RUNTESTS and SANITY tests:&lt;br /&gt;
&lt;br /&gt;
 ACC_SM_ONLY=”RUNTESTS SANITY” sh acceptance-small.sh&lt;br /&gt;
&lt;br /&gt;
To only run test_1 and test_2 of the SANITYN tests:&lt;br /&gt;
&lt;br /&gt;
 ACC_SM_ONLY=”SANITYN” ONLY=”1 2” sh acceptance-small.sh&lt;br /&gt;
&lt;br /&gt;
To only run the replay-single.sh test and except (not run) the test_3* and test_4* tests: &lt;br /&gt;
&lt;br /&gt;
 ACC_SM_ONLY=”REPLAY_SINGLE” REPLAY_SINGLE_EXCEPT=”3 4” sh acceptance-small.sh&lt;br /&gt;
&lt;br /&gt;
To only run conf-sanity.sh tests after #15 (without the acceptance-small.sh wrapper script):&lt;br /&gt;
&lt;br /&gt;
 CONF_SANITY_EXCEPT=”$(seq 15)“ sh conf-sanity.sh&lt;br /&gt;
&lt;br /&gt;
==Do the acc-sm tests have to be run in a specific order?==&lt;br /&gt;
&lt;br /&gt;
The test order is defined in the acceptance-small.sh script and in each test script. Users do not have to (and should not) do anything to change the order of tests.&lt;br /&gt;
&lt;br /&gt;
==Who runs the acc-sm tests?==&lt;br /&gt;
&lt;br /&gt;
Currently, the QE group and Lustre developers run acc-sm as the main test suite for Lustre testing. Acc-sm tests are run on YALA, the automated test system, with test reports submitted to Buffalo (a web interface that allows for browsing various Lustre test results). We welcome external contributions to the Lustre acc-sm test efforts – either of the Lustre code base or new testing platforms.&lt;br /&gt;
&lt;br /&gt;
==What type of Lustre environment is needed to run the acc-sm tests? Is anything special needed?==&lt;br /&gt;
&lt;br /&gt;
The default Lustre configuration for acc-sm testing is a single node setup with one MDS and two OSTs. All devices are loop-back devices. YALA, the automated test system, uses a non-default configuration.&lt;br /&gt;
&lt;br /&gt;
To run the acc-sm test suite on a non-default Lustre configuration, you have to modify the default settings in the acc-sm configuration file, lustre/tests/cfg/local.sh. The configuration variables include mds_HOST, ost_HOST, OSTCOUNT, MDS_MOUNT_OPTS and OST_MOUNT_OPTS, among others.&lt;br /&gt;
&lt;br /&gt;
To create your own configuration file, copy cfg/local.sh to cfg/my_config.sh:&lt;br /&gt;
&lt;br /&gt;
 cp cfg/local.sh cfg/my_config.sh&lt;br /&gt;
&lt;br /&gt;
Edit the necessary variables in the configuration file (my_config.sh) and run acc-sm as: NAME=my_config sh acceptance-small.sh&lt;br /&gt;
&lt;br /&gt;
==What are the steps to run acc-sm?==&lt;br /&gt;
&lt;br /&gt;
There are two methods to run the acc-sm tests.&lt;br /&gt;
&lt;br /&gt;
1. Check out a Lustre branch (b1_6, b1_8 or HEAD).&lt;br /&gt;
&lt;br /&gt;
2. Change directory to lustre/tests:&lt;br /&gt;
&lt;br /&gt;
 cd lustre/tests&lt;br /&gt;
&lt;br /&gt;
3. Build lustre/tests.&lt;br /&gt;
&lt;br /&gt;
4. Run acc-sm on a local, default Lustre configuration (1 MGS/MDT, 1 OST and 1 client):&lt;br /&gt;
&lt;br /&gt;
 sh acceptance-small.sh 2&amp;gt;&amp;amp;1 | tee /tmp/output&lt;br /&gt;
&lt;br /&gt;
- OR -&lt;br /&gt;
&lt;br /&gt;
1. Install the lustre-tests RPM (available at lts-head:/var/cache/cfs/PACKAGE/rpm/lustre).&lt;br /&gt;
&lt;br /&gt;
2. Change directory to lustre/tests:&lt;br /&gt;
&lt;br /&gt;
 cd /usr/lib/lustre/tests&lt;br /&gt;
&lt;br /&gt;
3. Create your own configuration file and edit it for your configuration.&lt;br /&gt;
&lt;br /&gt;
 cp cfg/local.sh cfg/my_config.sh&lt;br /&gt;
&lt;br /&gt;
4. Run acc-sm on a local Lustre configuration.&lt;br /&gt;
&lt;br /&gt;
Here is an example of running acc-sm on a non-default Lustre configuration (MDS is sfire7, OST is sfire8, OSCOUNT=1, etc). In this example, only the SANITY test cases are being run.&lt;br /&gt;
&lt;br /&gt;
 ACC_SM_ONLY=SANITY mds_HOST=sfire7 ost8_HOST=sfire8 MDSDEV1=/dev/sda1&lt;br /&gt;
 OSTCOUNT=1 OSTDEV1=/dev/sda1 MDSSIZE=5000000 OSTSIZE=5000000&lt;br /&gt;
 MDS_MOUNT_OPTS=&amp;quot;-o user_xattr&amp;quot; OST_MOUNT_OPTS=&amp;quot; -o user_xattr&amp;quot;&lt;br /&gt;
 REFORMAT=&amp;quot;--reformat&amp;quot; PDSH=&amp;quot;pdsh -S -w&amp;quot; sh acceptance-small.sh&lt;br /&gt;
&lt;br /&gt;
==What if I hit a failure on an acc-sm test?==&lt;br /&gt;
&lt;br /&gt;
* If you regularly hit a failure in any of these tests, check if a bug has been reported on the failure or file a new bug if one has not yet been opened.&lt;br /&gt;
* If the bug prevents you from completing the tests, set the environment variables to skip the specific test(s) until you or someone else fixes them.&lt;br /&gt;
:* For example, to skip sanity.sh subtest 36g and 65, replay-single.sh subtest 42, and all of insanity.sh set in your environment:&lt;br /&gt;
 &lt;br /&gt;
:&amp;lt;pre&amp;gt;&lt;br /&gt;
;export SANITY_EXCEPT=&amp;quot;36g 65&amp;quot;&lt;br /&gt;
;export REPLAY_SINGLE_EXCEPT=42&lt;br /&gt;
;export INSANITY=no&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
:* You can also skip tests on the command line. For example, when running acceptance-small:&lt;br /&gt;
 &lt;br /&gt;
:&amp;lt;pre&amp;gt;&lt;br /&gt;
;SANITY_EXCEPT=&amp;quot;36g 65&amp;quot; REPLAY_SINGLE_EXCEPT=42 INSANITY=no ./acceptance-small.sh&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
:* The test framework is very flexible, and it is a very easy &amp;quot;hands-off&amp;quot; way of running testing while you are doing other things, like coding.&lt;br /&gt;
:* Questions/problems with the test framework should be emailed to the [http://wiki.lustre.org/index.php/Mailing_Lists lustre-discuss mailing list], so all Lustre users can benefit from improving and documenting it.&lt;br /&gt;
* If you do not run the entire test suite regularly, you will have no idea whether a bug is added from your code or not, and you will waste a lot of time looking.&lt;br /&gt;
&lt;br /&gt;
==How do you run acc-sm on a mounted Lustre system?==&lt;br /&gt;
&lt;br /&gt;
To run acc-sm on a Lustre system that is already mounted, you need to use the correct configuration file (according to the mounted Lustre system) and run acc-sm as: &lt;br /&gt;
&lt;br /&gt;
 SETUP=: CLEANUP=: FORMAT=: NAME=&amp;lt;config&amp;gt; sh acceptance-small.sh&lt;br /&gt;
&lt;br /&gt;
==How do you run acc-sm with and without reformat?==&lt;br /&gt;
&lt;br /&gt;
By default, the acc-sm test suite does not reformat Lustre. If this is a new system or if you are using new devices and want to reformat Lustre, run acc-sm with REFORMAT=&amp;quot;--reformat&amp;quot;:&lt;br /&gt;
&lt;br /&gt;
 REFORMAT=&amp;quot;--reformat&amp;quot; sh acceptance-small.sh&lt;br /&gt;
&lt;br /&gt;
If needed, you can specify WRITECONF=&amp;quot;writeconf&amp;quot;, and then run acc-sm with WRITECONF=&amp;quot;writeconf&amp;quot;:&lt;br /&gt;
&lt;br /&gt;
 WRITECONF=&amp;quot;writeconf&amp;quot; sh acceptance-small.sh&lt;br /&gt;
&lt;br /&gt;
==How do you run acc-sm in a Lustre configuration with several clients?==&lt;br /&gt;
&lt;br /&gt;
The default configuration file for acc-sm is cfg/local.sh, which uses only one client (local). To use additional remote clients, specify the RCLIENTS list and use the cfg/ncli.sh configuration file (or your own copy of ncli configuration).&lt;br /&gt;
&lt;br /&gt;
 NAME=ncli RCLIENT=&amp;lt;space-separated list of remote clients&amp;gt; sh acceptance-small.sh&lt;br /&gt;
&lt;br /&gt;
For example:&lt;br /&gt;
&lt;br /&gt;
 NAME=ncli RCLIENT=&amp;quot;client2 client3 client11&amp;quot; sh acceptance-small.sh&lt;br /&gt;
&lt;br /&gt;
==What is the SLOW variable and how is it used with acc-sm?==&lt;br /&gt;
&lt;br /&gt;
The SLOW variable is used to run a subset of acc-sm tests. By default, the variable is set to SLOW=no, which causes some of the longer acc-sm tests to be skipped and acc-sm test run to complete in less than 2 hours. To run all of the acc-sm tests, set the variable to SLOW=yes:&lt;br /&gt;
&lt;br /&gt;
 SLOW=yes sh acceptance-small.sh&lt;br /&gt;
&lt;br /&gt;
==What is the FAIL_ON_ERROR variable and how is it used with acc-sm?==&lt;br /&gt;
&lt;br /&gt;
The FAIL_ON_ERROR variable is used to &amp;quot;stop&amp;quot; or &amp;quot;continue&amp;quot; running acc-sm tests after a test failure occurs. If the variable is set to &amp;quot;true&amp;quot; (FAIL_ON_ERROR=true), then acc-sm stops after test_N fails and test_N+1 does not run. If the variable is set to &amp;quot;false&amp;quot; (FAIL_ON_ERROR=false), then acc-sm continues after test_N fails and test_N+1 does run.&lt;br /&gt;
&lt;br /&gt;
FALSE_ON_ERROR=false, by default, for the sanity, sanityn and sanity-quota tests. FALSE_ON_ERROR=true for the replay/recovery tests.&lt;br /&gt;
&lt;br /&gt;
==What is the PDSH variable and how it is used with acc-sm?==&lt;br /&gt;
&lt;br /&gt;
The PDSH variable is used to provide remote shell access. If acc-sm is run on a Lustre configuration with remote servers, specify PDSH like this:&lt;br /&gt;
&lt;br /&gt;
 PDSH=&amp;quot;pdsh -S w&amp;quot; sh acceptance-small.sh&lt;br /&gt;
&lt;br /&gt;
If the client has no access to the servers, you can run acc-sm without PDSH, but the tests which need PDSH access are skipped. A summary report is generated which lists the skipped tests.&lt;br /&gt;
&lt;br /&gt;
==What is the LOAD_MODULES_REMOTE variable and how is it used with acc-sm?==&lt;br /&gt;
&lt;br /&gt;
The LOAD_MODULES_REMOTE variable is used to load/unload modules on remote nodes. By default, the variable is set to LOAD_MODULES_REMOTE=false, and modules are not loaded or unloaded on remote nodes during acceptance small testing. &lt;br /&gt;
&lt;br /&gt;
To load/unload modules on remote nodes, set the variable to LOAD_MODULES_REMOTE=true when running the acc-sm tests:&lt;br /&gt;
&lt;br /&gt;
 LOAD_MODULES_REMOTE=true sh acceptance-small.sh&lt;br /&gt;
&lt;br /&gt;
==What is the EXCEPT_LIST_FILE variable and how is it used with acc-sm?==&lt;br /&gt;
&lt;br /&gt;
In Lustre 1.8.2 and later, the EXCEPT_LIST_FILE variable can be used to specify the tests-to-skip file, which tracks the tests to skip during acc-sm runs. To specify the EXCEPT_LIST_FILE parameter, set the following in your Lustre environment: &lt;br /&gt;
&lt;br /&gt;
 EXCEPT_LIST_FILE=/full/path/to/skip/file #  &lt;br /&gt;
&lt;br /&gt;
The tests-to-skip file can also be specified by having a file named tests-to-skip.sh in the LUSTRE/tests/cfg directory. The EXCEPT_LIST_FILE variable will be used if it is defined. Otherwise, the script looks for LUSTRE/tests/cfg/tests-to-skip.sh and uses this file, if it exists. &lt;br /&gt;
&lt;br /&gt;
If a tests-to-skip file is found, its contents are dumped to stdout before it is read into the t-f environment so the file&#039;s contents are visible in the rest results. By following a structured format of commenting skip entries, the tests-to-skip.sh file can serve as a log of test failures and help track bugs associated with those failures (for easy reference).&lt;br /&gt;
&lt;br /&gt;
This is a sample tests-to-skip file: &lt;br /&gt;
&lt;br /&gt;
 ## SAMPLES for ONLYs &lt;br /&gt;
 #export ACC_SM_ONLY=&amp;quot;METADATA_UPDATES&amp;quot; &lt;br /&gt;
 #export ONLY=&amp;quot;25 26 27 28 29&amp;quot; &lt;br /&gt;
 &lt;br /&gt;
 export SANITY_EXCEPT=&amp;quot;${SANITY_EXCEPT} 71&amp;quot; # requires dbench &lt;br /&gt;
 export SANITY_EXCEPT=&amp;quot;${SANITY_EXCEPT} 117&amp;quot; # bz-21361 crashes on raven, single-node acc-sm &lt;br /&gt;
 export SANITY_EXCEPT=&amp;quot;${SANITY_EXCEPT} 900&amp;quot; # does not seem to work on raven &lt;br /&gt;
 &lt;br /&gt;
 export SANITYN_EXCEPT=&amp;quot;${SANITYN_EXCEPT} 16&amp;quot; # bz-21173 test_16 fails with 120 running fsx &lt;br /&gt;
 &lt;br /&gt;
 export REPLAY_SINGLE_EXCEPT=&amp;quot;${REPLAY_SINGLE_EXCEPT} 70b&amp;quot; # bz-19480 - hitting on raven &lt;br /&gt;
 export OST_POOLS_EXCEPT=&amp;quot;${OST_POOLS_EXCEPT} 23&amp;quot;        # bz-21224 - uses lfs quotacheck which crashes the node &lt;br /&gt;
 &lt;br /&gt;
 # entries may be commented out to test fixes when available like this line below &lt;br /&gt;
 #export REPLAY_DUAL_EXCEPT=&amp;quot;${REPLAY_DUAL_EXCEPT} 14b&amp;quot; # bz-19884 &lt;br /&gt;
 &lt;br /&gt;
 # the lines above turn on/off individual test cases &lt;br /&gt;
 # the lines below turn on/off entire test suites &lt;br /&gt;
 # lines preceded by comments will be run &lt;br /&gt;
 # lines which are not commented and set the name of the test suite to &amp;quot;no&amp;quot; will be skipped. &lt;br /&gt;
 &lt;br /&gt;
 export SLOW=&amp;quot;no&amp;quot; &lt;br /&gt;
 # export RUNTESTS=&amp;quot;no&amp;quot; &lt;br /&gt;
 # export SANITY=&amp;quot;no&amp;quot; &lt;br /&gt;
 # export FSX=&amp;quot;no&amp;quot; &lt;br /&gt;
 # export DBENCH=&amp;quot;no&amp;quot; &lt;br /&gt;
 # export BONNIE=&amp;quot;no&amp;quot; &lt;br /&gt;
 # export IOZONE=&amp;quot;no&amp;quot; &lt;br /&gt;
 # export SANITYN=&amp;quot;no&amp;quot; &lt;br /&gt;
 export LFSCK=&amp;quot;no&amp;quot;               # 1.8.1: bz 19477 &lt;br /&gt;
 # export LIBLUSTRE=&amp;quot;no&amp;quot; &lt;br /&gt;
 # export RACER=&amp;quot;no&amp;quot; &lt;br /&gt;
 # export REPLAY_SINGLE=&amp;quot;no&amp;quot; &lt;br /&gt;
 # export CONF_SANITY=&amp;quot;no&amp;quot; &lt;br /&gt;
 # export RECOVERY_SMALL=&amp;quot;no&amp;quot; &lt;br /&gt;
 # export REPLAY_OST_SINGLE=&amp;quot;no&amp;quot; &lt;br /&gt;
 # export REPLAY_DUAL=&amp;quot;no&amp;quot; &lt;br /&gt;
 # export REPLAY_VBR=&amp;quot;no&amp;quot; &lt;br /&gt;
 # export INSANITY=&amp;quot;no&amp;quot; &lt;br /&gt;
 # export LARGE_SCALE=&amp;quot;no&amp;quot; &lt;br /&gt;
 export SANITY_QUOTA=&amp;quot;no&amp;quot;        # bz-21224 &lt;br /&gt;
 # export RECOVERY_MDS_SCALE=&amp;quot;no&amp;quot; &lt;br /&gt;
 # export RECOVERY_DOUBLE_SCALE=&amp;quot;no&amp;quot; &lt;br /&gt;
 # export RECOVERY_RANDOM_SCALE=&amp;quot;no&amp;quot; &lt;br /&gt;
 # export PARALLEL_SCALE=&amp;quot;no&amp;quot; &lt;br /&gt;
 # export METADATA_UPDATES=&amp;quot;no&amp;quot; &lt;br /&gt;
 # export OST_POOLS=&amp;quot;no&amp;quot;&lt;br /&gt;
&lt;br /&gt;
==What is the CMD configuration for HEAD?==&lt;br /&gt;
&lt;br /&gt;
For the HEAD branch, specify the MDSCOUNT variable (number of MDTs). By default, the variable is set to 1. If you have a Lustre configuration with several MDT nodes, they need to be specified in the configuration file as mds1_HOST, mds2_HOST, ...&lt;br /&gt;
&lt;br /&gt;
By default, all of these variables are set to the mds_HOST value.&lt;br /&gt;
&lt;br /&gt;
==What do we do with the acc-sm test results?==&lt;br /&gt;
&lt;br /&gt;
If an acc-sm test fails, the failure is investigated. If the investigation reveals there is a Lustre defect, a bug is opened in [https://bugzilla.lustre.org/ Bugzilla] to fix the problem and also the acc-sm issue.&lt;/div&gt;</summary>
		<author><name>Nathan</name></author>
	</entry>
	<entry>
		<id>http://wiki.old.lustre.org/index.php?title=Acceptance_Small_(acc-sm)_Testing_on_Lustre&amp;diff=9063</id>
		<title>Acceptance Small (acc-sm) Testing on Lustre</title>
		<link rel="alternate" type="text/html" href="http://wiki.old.lustre.org/index.php?title=Acceptance_Small_(acc-sm)_Testing_on_Lustre&amp;diff=9063"/>
		<updated>2009-12-15T22:32:21Z</updated>

		<summary type="html">&lt;p&gt;Nathan: /* What tests comprise the acc-sm test suite? */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;__TOC__&lt;br /&gt;
The Lustre™ QE group and developers use acceptance-small (acc-sm) tests to catch bugs early in the development cycle. Within the Lustre group, acc-sm tests are run on YALA, an automated test system. This information is being published to describe the steps to perform acceptance small testing and encourage wider acc-sm testing in the Lustre community.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;NOTE&#039;&#039;&#039;: For your convenience, this document is also available as a [http://wiki.lustre.org/images/c/c6/AccSm_Testing.pdf PDF].&lt;br /&gt;
&lt;br /&gt;
==What is acc-sm testing and why do we use it for Lustre?==&lt;br /&gt;
&lt;br /&gt;
Acceptance small (acc-sm) testing is a suite of test cases used to verify different aspects of Lustre functionality.&lt;br /&gt;
&lt;br /&gt;
* These tests are run using the acceptance-small.sh script. &lt;br /&gt;
* The script is run from the lustre/tests directory in a compiled Lustre tree. &lt;br /&gt;
* The acceptance-small.sh script runs a number of test scripts that are also run by the ltest (Buffalo) test harness on Lustre test clusters.&lt;br /&gt;
&lt;br /&gt;
==What tests comprise the acc-sm test suite?==&lt;br /&gt;
&lt;br /&gt;
Each Lustre tree contains a lustre/tests sub-directory; all acc-sm tests are stored here. The acceptance-small.sh file contains a list of all tests in the acc-sm suite. To get the list, run:&lt;br /&gt;
&lt;br /&gt;
 $ grep TESTSUITE_LIST acceptance-small.sh&lt;br /&gt;
&lt;br /&gt;
The acc-sm tests are listed below, by branch.&lt;br /&gt;
&lt;br /&gt;
====b1_6 branch====&lt;br /&gt;
&lt;br /&gt;
This branch includes 17 acc-sm test suites.&lt;br /&gt;
&lt;br /&gt;
 $ grep TESTSUITE_LIST acceptance-small.sh&lt;br /&gt;
 export TESTSUITE_LIST=&amp;quot;RUNTESTS SANITY DBENCH BONNIE IOZONE FSX SANITYN LFSCK&lt;br /&gt;
 LIBLUSTRE REPLAY_SINGLE CONF_SANITY RECOVERY_SMALL REPLAY_OST_SINGLE&lt;br /&gt;
 REPLAY_DUAL INSANITY SANITY_QUOTA PERFORMANCE_SANITY&amp;quot;&lt;br /&gt;
&lt;br /&gt;
====b1_8_gate branch====&lt;br /&gt;
&lt;br /&gt;
This branch includes 18 acc-sm test suites.&lt;br /&gt;
&lt;br /&gt;
 $ grep TESTSUITE_LIST acceptance-small.sh&lt;br /&gt;
 export TESTSUITE_LIST=&amp;quot;RUNTESTS SANITY DBENCH BONNIE IOZONE FSX SANITYN LFSCK&lt;br /&gt;
 LIBLUSTRE REPLAY_SINGLE CONF_SANITY RECOVERY_SMALL REPLAY_OST_SINGLE&lt;br /&gt;
 REPLAY_DUAL REPLAY_VBR INSANITY SANITY_QUOTA PERFORMANCE_SANITY&amp;quot;&lt;br /&gt;
&lt;br /&gt;
====HEAD branch====&lt;br /&gt;
&lt;br /&gt;
This branch includes 19 acc-sm test suites.&lt;br /&gt;
&lt;br /&gt;
 $ grep TESTSUITE_LIST acceptance-small.sh&lt;br /&gt;
 export TESTSUITE_LIST=&amp;quot;RUNTESTS SANITY DBENCH BONNIE IOZONE FSX SANITYN LFSCK&lt;br /&gt;
 LIBLUSTRE REPLAY_SINGLE CONF_SANITY RECOVERY_SMALL REPLAY_OST_SINGLE&lt;br /&gt;
 REPLAY_DUAL INSANITY SANITY_QUOTA SANITY_SEC SANITY_GSS&lt;br /&gt;
 PERFORMANCE_SANITY&amp;quot;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
To see the test cases in a particular acc-sm test, run:&lt;br /&gt;
&lt;br /&gt;
 $ grep run_ &amp;lt;test suite script&amp;gt;&lt;br /&gt;
&lt;br /&gt;
For example, to see the last 3 test cases that comprise the SANITY test:&lt;br /&gt;
&lt;br /&gt;
 $ grep run_ sanity.sh | tail -3&lt;br /&gt;
&lt;br /&gt;
 run_test 130c &amp;quot;FIEMAP (2-stripe file with hole)&amp;quot;&lt;br /&gt;
 run_test 130d &amp;quot;FIEMAP (N-stripe file)&amp;quot;&lt;br /&gt;
 run_test 130e &amp;quot;FIEMAP (test continuation FIEMAP calls)&amp;quot;&lt;br /&gt;
&lt;br /&gt;
==What does each acc-sm test measure or show?==&lt;br /&gt;
&lt;br /&gt;
The acc-sm test suite are described below.&lt;br /&gt;
&lt;br /&gt;
;&#039;&#039;&#039;RUNTESTS&#039;&#039;&#039;&lt;br /&gt;
: A basic regression test with unmount/remount.&lt;br /&gt;
&lt;br /&gt;
;&#039;&#039;&#039;SANITY&#039;&#039;&#039;&lt;br /&gt;
: Verifies Lustre operation under normal operating conditions.&lt;br /&gt;
&lt;br /&gt;
;&#039;&#039;&#039;DBENCH&#039;&#039;&#039;&lt;br /&gt;
:Dbench benchmark for simulating N clients to produce the filesystem load.&lt;br /&gt;
&lt;br /&gt;
;&#039;&#039;&#039;BONNIE&#039;&#039;&#039;&lt;br /&gt;
:Bonnie++ benchmark for creation, reading and deleting many small files&lt;br /&gt;
&lt;br /&gt;
;&#039;&#039;&#039;IOZONE&#039;&#039;&#039;&lt;br /&gt;
:IOzone benchmark for generating and measuring a variety of file operations.&lt;br /&gt;
&lt;br /&gt;
;&#039;&#039;&#039;FSX&#039;&#039;&#039;&lt;br /&gt;
:Filesystem exerciser.&lt;br /&gt;
&lt;br /&gt;
;&#039;&#039;&#039;SANITYN&#039;&#039;&#039;&lt;br /&gt;
:Verifies operations from two clients under normal operating conditions.&lt;br /&gt;
&lt;br /&gt;
;&#039;&#039;&#039;LFSCK&#039;&#039;&#039;&lt;br /&gt;
:Tests e2fsck and lfsck to detect and fix filesystm corruption.&lt;br /&gt;
&lt;br /&gt;
;&#039;&#039;&#039;LIBLUSTRE&#039;&#039;&#039;&lt;br /&gt;
:Runs a test linked to a liblustre client library.&lt;br /&gt;
&lt;br /&gt;
;&#039;&#039;&#039;REPLAY_SINGLE&#039;&#039;&#039;&lt;br /&gt;
:Verifies recovery after an MDS failure.&lt;br /&gt;
&lt;br /&gt;
;&#039;&#039;&#039;CONF_SANITY&#039;&#039;&#039;&lt;br /&gt;
:Verifies various Lustre configurations (including wrong ones), where the system must behave correctly.&lt;br /&gt;
&lt;br /&gt;
;&#039;&#039;&#039;RECOVERY_SMALL&#039;&#039;&#039;&lt;br /&gt;
:Verifies RPC replay after a communications failure (message loss).&lt;br /&gt;
&lt;br /&gt;
;&#039;&#039;&#039;REPLAY_OST_SINGLE&#039;&#039;&#039;&lt;br /&gt;
:Verifies recovery after an OST failure.&lt;br /&gt;
&lt;br /&gt;
;&#039;&#039;&#039;REPLAY_DUAL&#039;&#039;&#039;&lt;br /&gt;
:Verifies recovery from two clients after a server failure.&lt;br /&gt;
&lt;br /&gt;
;&#039;&#039;&#039;INSANITY&#039;&#039;&#039;&lt;br /&gt;
:Tests multiple concurrent failure conditions.&lt;br /&gt;
&lt;br /&gt;
;&#039;&#039;&#039;SANITY_QUOTA&#039;&#039;&#039;&lt;br /&gt;
:Verifies filesystem quotas.&lt;br /&gt;
&lt;br /&gt;
==How do you get the acc-sm tests?==&lt;br /&gt;
&lt;br /&gt;
The acc-sm test suite is stored in the lustre/tests sub-directory on each Git branch (b1_6, b1_8, and HEAD).&lt;br /&gt;
&lt;br /&gt;
==Do you have to run every acc-sm test?==&lt;br /&gt;
&lt;br /&gt;
No. You can choose to run only specified acc-sm tests. Tests can be run either with or without the acceptance-sm.sh (acc-sm.sh) wrapper script. Here are several examples:&lt;br /&gt;
&lt;br /&gt;
To only run the RUNTESTS and SANITY tests:&lt;br /&gt;
&lt;br /&gt;
 ACC_SM_ONLY=”RUNTESTS SANITY” sh acceptance-small.sh&lt;br /&gt;
&lt;br /&gt;
To only run test_1 and test_2 of the SANITYN tests:&lt;br /&gt;
&lt;br /&gt;
 ACC_SM_ONLY=”SANITYN” ONLY=”1 2” sh acceptance-small.sh&lt;br /&gt;
&lt;br /&gt;
To only run the replay-single.sh test and except (not run) the test_3* and test_4* tests: &lt;br /&gt;
&lt;br /&gt;
 ACC_SM_ONLY=”REPLAY_SINGLE” REPLAY_SINGLE_EXCEPT=”3 4” sh acceptance-small.sh&lt;br /&gt;
&lt;br /&gt;
To only run conf-sanity.sh tests after #15 (without the acceptance-small.sh wrapper script):&lt;br /&gt;
&lt;br /&gt;
 CONF_SANITY_EXCEPT=”$(seq 15)“ sh conf-sanity.sh&lt;br /&gt;
&lt;br /&gt;
==Do the acc-sm tests have to be run in a specific order?==&lt;br /&gt;
&lt;br /&gt;
The test order is defined in the acceptance-small.sh script and in each test script. Users do not have to (and should not) do anything to change the order of tests.&lt;br /&gt;
&lt;br /&gt;
==Who runs the acc-sm tests?==&lt;br /&gt;
&lt;br /&gt;
Currently, the QE group and Lustre developers run acc-sm as the main test suite for Lustre testing. Acc-sm tests are run on YALA, the automated test system, with test reports submitted to Buffalo (a web interface that allows for browsing various Lustre test results). We welcome external contributions to the Lustre acc-sm test efforts – either of the Lustre code base or new testing platforms.&lt;br /&gt;
&lt;br /&gt;
==What type of Lustre environment is needed to run the acc-sm tests? Is anything special needed?==&lt;br /&gt;
&lt;br /&gt;
The default Lustre configuration for acc-sm testing is a single node setup with one MDS and two OSTs. All devices are loop-back devices. YALA, the automated test system, uses a non-default configuration.&lt;br /&gt;
&lt;br /&gt;
To run the acc-sm test suite on a non-default Lustre configuration, you have to modify the default settings in the acc-sm configuration file, lustre/tests/cfg/local.sh. The configuration variables include mds_HOST, ost_HOST, OSTCOUNT, MDS_MOUNT_OPTS and OST_MOUNT_OPTS, among others.&lt;br /&gt;
&lt;br /&gt;
To create your own configuration file, copy cfg/local.sh to cfg/my_config.sh:&lt;br /&gt;
&lt;br /&gt;
 cp cfg/local.sh cfg/my_config.sh&lt;br /&gt;
&lt;br /&gt;
Edit the necessary variables in the configuration file (my_config.sh) and run acc-sm as: NAME=my_config sh acceptance-small.sh&lt;br /&gt;
&lt;br /&gt;
==What are the steps to run acc-sm?==&lt;br /&gt;
&lt;br /&gt;
There are two methods to run the acc-sm tests.&lt;br /&gt;
&lt;br /&gt;
1. Check out a Lustre branch (b1_6, b1_8 or HEAD).&lt;br /&gt;
&lt;br /&gt;
2. Change directory to lustre/tests:&lt;br /&gt;
&lt;br /&gt;
 cd lustre/tests&lt;br /&gt;
&lt;br /&gt;
3. Build lustre/tests.&lt;br /&gt;
&lt;br /&gt;
4. Run acc-sm on a local, default Lustre configuration (1 MGS/MDT, 1 OST and 1 client):&lt;br /&gt;
&lt;br /&gt;
 sh acceptance-small.sh 2&amp;gt;&amp;amp;1 | tee /tmp/output&lt;br /&gt;
&lt;br /&gt;
- OR -&lt;br /&gt;
&lt;br /&gt;
1. Install the lustre-tests RPM (available at lts-head:/var/cache/cfs/PACKAGE/rpm/lustre).&lt;br /&gt;
&lt;br /&gt;
2. Change directory to lustre/tests:&lt;br /&gt;
&lt;br /&gt;
 cd /usr/lib/lustre/tests&lt;br /&gt;
&lt;br /&gt;
3. Create your own configuration file and edit it for your configuration.&lt;br /&gt;
&lt;br /&gt;
 cp cfg/local.sh cfg/my_config.sh&lt;br /&gt;
&lt;br /&gt;
4. Run acc-sm on a local Lustre configuration.&lt;br /&gt;
&lt;br /&gt;
Here is an example of running acc-sm on a non-default Lustre configuration (MDS is sfire7, OST is sfire8, OSCOUNT=1, etc). In this example, only the SANITY test cases are being run.&lt;br /&gt;
&lt;br /&gt;
 ACC_SM_ONLY=SANITY mds_HOST=sfire7 ost8_HOST=sfire8 MDSDEV1=/dev/sda1&lt;br /&gt;
 OSTCOUNT=1 OSTDEV1=/dev/sda1 MDSSIZE=5000000 OSTSIZE=5000000&lt;br /&gt;
 MDS_MOUNT_OPTS=&amp;quot;-o user_xattr&amp;quot; OST_MOUNT_OPTS=&amp;quot; -o user_xattr&amp;quot;&lt;br /&gt;
 REFORMAT=&amp;quot;--reformat&amp;quot; PDSH=&amp;quot;pdsh -S -w&amp;quot; sh acceptance-small.sh&lt;br /&gt;
&lt;br /&gt;
==What if I hit a failure on an acc-sm test?==&lt;br /&gt;
&lt;br /&gt;
* If you regularly hit a failure in any of these tests, check if a bug has been reported on the failure or file a new bug if one has not yet been opened.&lt;br /&gt;
* If the bug prevents you from completing the tests, set the environment variables to skip the specific test(s) until you or someone else fixes them.&lt;br /&gt;
:* For example, to skip sanity.sh subtest 36g and 65, replay-single.sh subtest 42, and all of insanity.sh set in your environment:&lt;br /&gt;
 &lt;br /&gt;
:&amp;lt;pre&amp;gt;&lt;br /&gt;
;export SANITY_EXCEPT=&amp;quot;36g 65&amp;quot;&lt;br /&gt;
;export REPLAY_SINGLE_EXCEPT=42&lt;br /&gt;
;export INSANITY=no&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
:* You can also skip tests on the command line. For example, when running acceptance-small:&lt;br /&gt;
 &lt;br /&gt;
:&amp;lt;pre&amp;gt;&lt;br /&gt;
;SANITY_EXCEPT=&amp;quot;36g 65&amp;quot; REPLAY_SINGLE_EXCEPT=42 INSANITY=no ./acceptance-small.sh&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
:* The test framework is very flexible, and it is a very easy &amp;quot;hands-off&amp;quot; way of running testing while you are doing other things, like coding.&lt;br /&gt;
:* Questions/problems with the test framework should be emailed to the [http://wiki.lustre.org/index.php/Mailing_Lists lustre-discuss mailing list], so all Lustre users can benefit from improving and documenting it.&lt;br /&gt;
* If you do not run the entire test suite regularly, you will have no idea whether a bug is added from your code or not, and you will waste a lot of time looking.&lt;br /&gt;
&lt;br /&gt;
==How do you run acc-sm on a mounted Lustre system?==&lt;br /&gt;
&lt;br /&gt;
To run acc-sm on a Lustre system that is already mounted, you need to use the correct configuration file (according to the mounted Lustre system) and run acc-sm as: &lt;br /&gt;
&lt;br /&gt;
 SETUP=: CLEANUP=: FORMAT=: NAME=&amp;lt;config&amp;gt; sh acceptance-small.sh&lt;br /&gt;
&lt;br /&gt;
==How do you run acc-sm with and without reformat?==&lt;br /&gt;
&lt;br /&gt;
By default, the acc-sm test suite does not reformat Lustre. If this is a new system or if you are using new devices and want to reformat Lustre, run acc-sm with REFORMAT=&amp;quot;--reformat&amp;quot;:&lt;br /&gt;
&lt;br /&gt;
 REFORMAT=&amp;quot;--reformat&amp;quot; sh acceptance-small.sh&lt;br /&gt;
&lt;br /&gt;
If needed, you can specify WRITECONF=&amp;quot;writeconf&amp;quot;, and then run acc-sm with WRITECONF=&amp;quot;writeconf&amp;quot;:&lt;br /&gt;
&lt;br /&gt;
 WRITECONF=&amp;quot;writeconf&amp;quot; sh acceptance-small.sh&lt;br /&gt;
&lt;br /&gt;
==How do you run acc-sm in a Lustre configuration with several clients?==&lt;br /&gt;
&lt;br /&gt;
The default configuration file for acc-sm is cfg/local.sh, which uses only one client (local). To use additional remote clients, specify the RCLIENTS list and use the cfg/ncli.sh configuration file (or your own copy of ncli configuration).&lt;br /&gt;
&lt;br /&gt;
 NAME=ncli RCLIENT=&amp;lt;space-separated list of remote clients&amp;gt; sh acceptance-small.sh&lt;br /&gt;
&lt;br /&gt;
For example:&lt;br /&gt;
&lt;br /&gt;
 NAME=ncli RCLIENT=&amp;quot;client2 client3 client11&amp;quot; sh acceptance-small.sh&lt;br /&gt;
&lt;br /&gt;
==What is the SLOW variable and how is it used with acc-sm?==&lt;br /&gt;
&lt;br /&gt;
The SLOW variable is used to run a subset of acc-sm tests. By default, the variable is set to SLOW=no, which causes some of the longer acc-sm tests to be skipped and acc-sm test run to complete in less than 2 hours. To run all of the acc-sm tests, set the variable to SLOW=yes:&lt;br /&gt;
&lt;br /&gt;
 SLOW=yes sh acceptance-small.sh&lt;br /&gt;
&lt;br /&gt;
==What is the FAIL_ON_ERROR variable and how is it used with acc-sm?==&lt;br /&gt;
&lt;br /&gt;
The FAIL_ON_ERROR variable is used to &amp;quot;stop&amp;quot; or &amp;quot;continue&amp;quot; running acc-sm tests after a test failure occurs. If the variable is set to &amp;quot;true&amp;quot; (FAIL_ON_ERROR=true), then acc-sm stops after test_N fails and test_N+1 does not run. If the variable is set to &amp;quot;false&amp;quot; (FAIL_ON_ERROR=false), then acc-sm continues after test_N fails and test_N+1 does run.&lt;br /&gt;
&lt;br /&gt;
FALSE_ON_ERROR=false, by default, for the sanity, sanityn and sanity-quota tests. FALSE_ON_ERROR=true for the replay/recovery tests.&lt;br /&gt;
&lt;br /&gt;
==What is the PDSH variable and how it is used with acc-sm?==&lt;br /&gt;
&lt;br /&gt;
The PDSH variable is used to provide remote shell access. If acc-sm is run on a Lustre configuration with remote servers, specify PDSH like this:&lt;br /&gt;
&lt;br /&gt;
 PDSH=&amp;quot;pdsh -S w&amp;quot; sh acceptance-small.sh&lt;br /&gt;
&lt;br /&gt;
If the client has no access to the servers, you can run acc-sm without PDSH, but the tests which need PDSH access are skipped. A summary report is generated which lists the skipped tests.&lt;br /&gt;
&lt;br /&gt;
==What is the LOAD_MODULES_REMOTE variable and how is it used with acc-sm?==&lt;br /&gt;
&lt;br /&gt;
The LOAD_MODULES_REMOTE variable is used to load/unload modules on remote nodes. By default, the variable is set to LOAD_MODULES_REMOTE=false, and modules are not loaded or unloaded on remote nodes during acceptance small testing. &lt;br /&gt;
&lt;br /&gt;
To load/unload modules on remote nodes, set the variable to LOAD_MODULES_REMOTE=true when running the acc-sm tests:&lt;br /&gt;
&lt;br /&gt;
 LOAD_MODULES_REMOTE=true sh acceptance-small.sh&lt;br /&gt;
&lt;br /&gt;
==What is the EXCEPT_LIST_FILE variable and how is it used with acc-sm?==&lt;br /&gt;
&lt;br /&gt;
In Lustre 1.8.2 and later, the EXCEPT_LIST_FILE variable can be used to specify the tests-to-skip file, which tracks the tests to skip during acc-sm runs. To specify the EXCEPT_LIST_FILE parameter, set the following in your Lustre environment: &lt;br /&gt;
&lt;br /&gt;
 EXCEPT_LIST_FILE=/full/path/to/skip/file #  &lt;br /&gt;
&lt;br /&gt;
The tests-to-skip file can also be specified by having a file named tests-to-skip.sh in the LUSTRE/tests/cfg directory. The EXCEPT_LIST_FILE variable will be used if it is defined. Otherwise, the script looks for LUSTRE/tests/cfg/tests-to-skip.sh and uses this file, if it exists. &lt;br /&gt;
&lt;br /&gt;
If a tests-to-skip file is found, its contents are dumped to stdout before it is read into the t-f environment so the file&#039;s contents are visible in the rest results. By following a structured format of commenting skip entries, the tests-to-skip.sh file can serve as a log of test failures and help track bugs associated with those failures (for easy reference).&lt;br /&gt;
&lt;br /&gt;
This is a sample tests-to-skip file: &lt;br /&gt;
&lt;br /&gt;
 ## SAMPLES for ONLYs &lt;br /&gt;
 #export ACC_SM_ONLY=&amp;quot;METADATA_UPDATES&amp;quot; &lt;br /&gt;
 #export ONLY=&amp;quot;25 26 27 28 29&amp;quot; &lt;br /&gt;
 &lt;br /&gt;
 export SANITY_EXCEPT=&amp;quot;${SANITY_EXCEPT} 71&amp;quot; # requires dbench &lt;br /&gt;
 export SANITY_EXCEPT=&amp;quot;${SANITY_EXCEPT} 117&amp;quot; # bz-21361 crashes on raven, single-node acc-sm &lt;br /&gt;
 export SANITY_EXCEPT=&amp;quot;${SANITY_EXCEPT} 900&amp;quot; # does not seem to work on raven &lt;br /&gt;
 &lt;br /&gt;
 export SANITYN_EXCEPT=&amp;quot;${SANITYN_EXCEPT} 16&amp;quot; # bz-21173 test_16 fails with 120 running fsx &lt;br /&gt;
 &lt;br /&gt;
 export REPLAY_SINGLE_EXCEPT=&amp;quot;${REPLAY_SINGLE_EXCEPT} 70b&amp;quot; # bz-19480 - hitting on raven &lt;br /&gt;
 export OST_POOLS_EXCEPT=&amp;quot;${OST_POOLS_EXCEPT} 23&amp;quot;        # bz-21224 - uses lfs quotacheck which crashes the node &lt;br /&gt;
 &lt;br /&gt;
 # entries may be commented out to test fixes when available like this line below &lt;br /&gt;
 #export REPLAY_DUAL_EXCEPT=&amp;quot;${REPLAY_DUAL_EXCEPT} 14b&amp;quot; # bz-19884 &lt;br /&gt;
 &lt;br /&gt;
 # the lines above turn on/off individual test cases &lt;br /&gt;
 # the lines below turn on/off entire test suites &lt;br /&gt;
 # lines preceded by comments will be run &lt;br /&gt;
 # lines which are not commented and set the name of the test suite to &amp;quot;no&amp;quot; will be skipped. &lt;br /&gt;
 &lt;br /&gt;
 export SLOW=&amp;quot;no&amp;quot; &lt;br /&gt;
 # export RUNTESTS=&amp;quot;no&amp;quot; &lt;br /&gt;
 # export SANITY=&amp;quot;no&amp;quot; &lt;br /&gt;
 # export FSX=&amp;quot;no&amp;quot; &lt;br /&gt;
 # export DBENCH=&amp;quot;no&amp;quot; &lt;br /&gt;
 # export BONNIE=&amp;quot;no&amp;quot; &lt;br /&gt;
 # export IOZONE=&amp;quot;no&amp;quot; &lt;br /&gt;
 # export SANITYN=&amp;quot;no&amp;quot; &lt;br /&gt;
 export LFSCK=&amp;quot;no&amp;quot;               # 1.8.1: bz 19477 &lt;br /&gt;
 # export LIBLUSTRE=&amp;quot;no&amp;quot; &lt;br /&gt;
 # export RACER=&amp;quot;no&amp;quot; &lt;br /&gt;
 # export REPLAY_SINGLE=&amp;quot;no&amp;quot; &lt;br /&gt;
 # export CONF_SANITY=&amp;quot;no&amp;quot; &lt;br /&gt;
 # export RECOVERY_SMALL=&amp;quot;no&amp;quot; &lt;br /&gt;
 # export REPLAY_OST_SINGLE=&amp;quot;no&amp;quot; &lt;br /&gt;
 # export REPLAY_DUAL=&amp;quot;no&amp;quot; &lt;br /&gt;
 # export REPLAY_VBR=&amp;quot;no&amp;quot; &lt;br /&gt;
 # export INSANITY=&amp;quot;no&amp;quot; &lt;br /&gt;
 # export LARGE_SCALE=&amp;quot;no&amp;quot; &lt;br /&gt;
 export SANITY_QUOTA=&amp;quot;no&amp;quot;        # bz-21224 &lt;br /&gt;
 # export RECOVERY_MDS_SCALE=&amp;quot;no&amp;quot; &lt;br /&gt;
 # export RECOVERY_DOUBLE_SCALE=&amp;quot;no&amp;quot; &lt;br /&gt;
 # export RECOVERY_RANDOM_SCALE=&amp;quot;no&amp;quot; &lt;br /&gt;
 # export PARALLEL_SCALE=&amp;quot;no&amp;quot; &lt;br /&gt;
 # export METADATA_UPDATES=&amp;quot;no&amp;quot; &lt;br /&gt;
 # export OST_POOLS=&amp;quot;no&amp;quot;&lt;br /&gt;
&lt;br /&gt;
==What is the CMD configuration for HEAD?==&lt;br /&gt;
&lt;br /&gt;
For the HEAD branch, specify the MDSCOUNT variable (number of MDTs). By default, the variable is set to 1. If you have a Lustre configuration with several MDT nodes, they need to be specified in the configuration file as mds1_HOST, mds2_HOST, ...&lt;br /&gt;
&lt;br /&gt;
By default, all of these variables are set to the mds_HOST value.&lt;br /&gt;
&lt;br /&gt;
==What do we do with the acc-sm test results?==&lt;br /&gt;
&lt;br /&gt;
If an acc-sm test fails, the failure is investigated. If the investigation reveals there is a Lustre defect, a bug is opened in [https://bugzilla.lustre.org/ Bugzilla] to fix the problem and also the acc-sm issue.&lt;/div&gt;</summary>
		<author><name>Nathan</name></author>
	</entry>
	<entry>
		<id>http://wiki.old.lustre.org/index.php?title=Documenting_Code&amp;diff=9062</id>
		<title>Documenting Code</title>
		<link rel="alternate" type="text/html" href="http://wiki.old.lustre.org/index.php?title=Documenting_Code&amp;diff=9062"/>
		<updated>2009-12-15T22:30:38Z</updated>

		<summary type="html">&lt;p&gt;Nathan: /* Publishing Documention */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Lustre code documentation helps engineers working on the code to read and correctly modify the code.  The reader is expected to have a good overall grasp of the [[Lustre_Internals|Lustre architecture and internals]]. The code documentation provides reference information on the application programming interfaces (APIs) and describes significant internal features of each [[Subsystem Map|Lustre subsystem]]. &lt;br /&gt;
&lt;br /&gt;
Lustre code documentation consists of stylized comments embedded in the source code, which helps to keep the documentation consistent as the code is developed. The embedded comments can be processed by [http://www.doxygen.org doxygen] into online, browse-able (HTML) documentation.&lt;br /&gt;
&lt;br /&gt;
== Requirements ==&lt;br /&gt;
&lt;br /&gt;
The minimum requirement for documenting Lustre code is to describe subsystem APIs - the datatypes, procedures and globals subsystem exports to the rest of Lustre - and significant internal datatypes.  These should be described as follows:&lt;br /&gt;
&lt;br /&gt;
* Datatypes (structs, typedefs, enums)&lt;br /&gt;
** What it is for&lt;br /&gt;
** Structure members&lt;br /&gt;
** Usage constraints&lt;br /&gt;
* Procedures&lt;br /&gt;
** What it does&lt;br /&gt;
** Parameters&lt;br /&gt;
** Return values&lt;br /&gt;
** Usage constraints&lt;br /&gt;
** Subtle implementation details&lt;br /&gt;
* Globals&lt;br /&gt;
** What it is for&lt;br /&gt;
** Usage constraints&lt;br /&gt;
&lt;br /&gt;
The &#039;&#039;most important&#039;&#039; information to include are &amp;quot;Usage constraints&amp;quot; and &amp;quot;Subtle implementation details&amp;quot;.  &lt;br /&gt;
&lt;br /&gt;
&amp;quot;Usage constraints&amp;quot; are restrictions on how and when you call a procedure or operate on a datastructure.  These include concurrency control, reference counting, permitted caller context etc. etc.  &lt;br /&gt;
&lt;br /&gt;
&amp;quot;Subtle implementation details&amp;quot; are anything done in the code that might not be transparently obvious, such as code that ensures the last thread in a pool of workers is held in reserve for deadlock avoidance.  &lt;br /&gt;
&lt;br /&gt;
A well-chosen descriptive name can allow other information, such as what the procedure does or what a parameter means, to be quite brief or even omitted.  But usage constraints and implementation subtleties must always be spelled out, e.g. by describing an object&#039;s entire lifecycle from creation through to destruction, so that the next engineer to maintain or use the code does it safely and correctly.  &lt;br /&gt;
&lt;br /&gt;
Each time you make a change to the Lustre code or inspect a patch, you must review the changes to ensure:&lt;br /&gt;
&lt;br /&gt;
* Sufficient documentation exists.&lt;br /&gt;
* The documentation is accurate and up to date.&lt;br /&gt;
&lt;br /&gt;
== Examples ==&lt;br /&gt;
&lt;br /&gt;
Doxygen comments start with [http://www.doxygen.org/docblocks.html &#039;&#039;/**&#039;&#039;] (like in [http://en.wikipedia.org/wiki/Javadoc javadoc]).  &lt;br /&gt;
&lt;br /&gt;
Doxygen commands are placed in doxygen comments to control how doxygen formats the output.  Commands start with a backslash (&#039;&#039;\&#039;&#039;) or at-sign (&#039;&#039;@&#039;&#039;), but we typically use the backslash and reserve the at-sign for group blocks (see below).  Don&#039;t use doxygen commands unnecessarily.  &lt;br /&gt;
&lt;br /&gt;
The main purpose of code documentation is to be available in the code for you to read when you&#039;re working on the code. So it&#039;s important that the comments read like real C comments and not formatting gibberish.&lt;br /&gt;
&lt;br /&gt;
===Procedures and Globals===&lt;br /&gt;
Document procedures and globals in the &#039;&#039;.c&#039;&#039; files, rather than in headers.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
/**&lt;br /&gt;
 * Owns a page by IO.&lt;br /&gt;
 *&lt;br /&gt;
 * Waits until \a pg is in cl_page_state::CPS_CACHED state, and then switch it&lt;br /&gt;
 * into cl_page_state::CPS_OWNED state.&lt;br /&gt;
 *&lt;br /&gt;
 * \param io IO context which wants to own the page&lt;br /&gt;
 * \param pg page to be owned&lt;br /&gt;
 *&lt;br /&gt;
 * \pre  !cl_page_is_owned(pg, io)&lt;br /&gt;
 * \post result == 0 iff cl_page_is_owned(pg, io)&lt;br /&gt;
 *&lt;br /&gt;
 * \retval 0   success&lt;br /&gt;
 *&lt;br /&gt;
 * \retval -ve failure, e.g., page was destroyed (and landed in&lt;br /&gt;
 *             cl_page_state::CPS_FREEING instead of cl_page_state::CPS_CACHED).&lt;br /&gt;
 *&lt;br /&gt;
 * \see cl_page_disown()&lt;br /&gt;
 * \see cl_page_operations::cpo_own()&lt;br /&gt;
 */&lt;br /&gt;
int cl_page_own(const struct lu_env *env, struct cl_io *io, struct cl_page *pg)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;Notes:&#039;&#039;&lt;br /&gt;
* Start with a brief description, which continues to the first &#039;.&#039; (period or full stop).&lt;br /&gt;
* Follow the brief description with a detailed description.&lt;br /&gt;
* Descriptions are written in the third person singular,  e.g. &amp;quot;&amp;lt;this function&amp;gt; does this and that&amp;quot;, &amp;quot;&amp;lt;this datatype&amp;gt; represents such and such a concept&amp;quot;.&lt;br /&gt;
* To refer to a function argument, use the [http://www.doxygen.org/commands.html#cmda &#039;&#039;\a argname&#039;&#039;] syntax.&lt;br /&gt;
* To refer to another function, use the [http://www.doxygen.org/autolink.html &#039;&#039;funcname()&#039;&#039;] syntax.  This will produce a cross-reference.&lt;br /&gt;
* To refer to a field or an enum value use the [http://www.doxygen.org/autolink.html &#039;&#039;SCOPE::NAME&#039;&#039;] syntax.&lt;br /&gt;
* Describe possible return values with [http://www.doxygen.org/commands.html#cmdretval &#039;&#039;\retval&#039;&#039;].&lt;br /&gt;
* Mention all concurrency control restrictions here (such as locks that the function expects to be held, or holds on exit).&lt;br /&gt;
* If possible, specify a (weakest) pre-condition and (strongest) post-condition for the function. If conditions cannot be expressed as a C language expression, provide an informal description.&lt;br /&gt;
* Enumerate related functions and datatypes in the [http://www.doxygen.org/commands.html#cmdsee &#039;&#039;\see&#039;&#039;] section. Note, that doxygen will automatically cross-reference all places where a given function is called (but not through a function pointer) and all functions that it calls, so there is no need to enumerate all this.&lt;br /&gt;
&lt;br /&gt;
===Datatypes===&lt;br /&gt;
Document datatypes where they are declared.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
/**&lt;br /&gt;
 * &amp;quot;Compound&amp;quot; object, consisting of multiple layers.&lt;br /&gt;
 *&lt;br /&gt;
 * Compound object with given fid is unique with given lu_site.&lt;br /&gt;
 *&lt;br /&gt;
 * Note, that object does *not* necessary correspond to the real object in the&lt;br /&gt;
 * persistent storage: object is an anchor for locking and method calling, so&lt;br /&gt;
 * it is created for things like not-yet-existing child created by mkdir or&lt;br /&gt;
 * create calls. lu_object_operations::loo_exists() can be used to check&lt;br /&gt;
 * whether object is backed by persistent storage entity.&lt;br /&gt;
 */&lt;br /&gt;
struct lu_object_header {&lt;br /&gt;
        /**&lt;br /&gt;
         * Object flags from enum lu_object_header_flags. Set and checked&lt;br /&gt;
         * atomically.&lt;br /&gt;
         */&lt;br /&gt;
        unsigned long     loh_flags;&lt;br /&gt;
        /**&lt;br /&gt;
         * Object reference count. Protected by lu_site::ls_guard.&lt;br /&gt;
         */&lt;br /&gt;
        atomic_t          loh_ref;&lt;br /&gt;
        /**&lt;br /&gt;
         * Fid, uniquely identifying this object.&lt;br /&gt;
         */&lt;br /&gt;
        struct lu_fid     loh_fid;&lt;br /&gt;
        /**&lt;br /&gt;
         * Common object attributes, cached for efficiency. From enum&lt;br /&gt;
         * lu_object_header_attr.&lt;br /&gt;
         */&lt;br /&gt;
        __u32             loh_attr;&lt;br /&gt;
        /**&lt;br /&gt;
         * Linkage into per-site hash table. Protected by lu_site::ls_guard.&lt;br /&gt;
         */&lt;br /&gt;
        struct hlist_node loh_hash;&lt;br /&gt;
        /**&lt;br /&gt;
         * Linkage into per-site LRU list. Protected by lu_site::ls_guard.&lt;br /&gt;
         */&lt;br /&gt;
        struct list_head  loh_lru;&lt;br /&gt;
        /**&lt;br /&gt;
         * Linkage into list of layers. Never modified once set (except lately&lt;br /&gt;
         * during object destruction). No locking is necessary.&lt;br /&gt;
         */&lt;br /&gt;
        struct list_head  loh_layers;&lt;br /&gt;
};&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Describe datatype invariants (preferably formally).&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
/**&lt;br /&gt;
 * Fields are protected by the lock on cfs_page_t, except for atomics and&lt;br /&gt;
 * immutables.&lt;br /&gt;
 *&lt;br /&gt;
 * \invariant Datatype invariants are in cl_page_invariant(). Basically:&lt;br /&gt;
 * cl_page::cp_parent and cl_page::cp_child are a well-formed double-linked&lt;br /&gt;
 * list, consistent with the parent/child pointers in the cl_page::cp_obj and&lt;br /&gt;
 * cl_page::cp_owner (when set).&lt;br /&gt;
 */&lt;br /&gt;
struct cl_page {&lt;br /&gt;
        /** Reference counter. */&lt;br /&gt;
        atomic_t           cp_ref;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Describe concurrency control mechanisms for structure fields.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
        /** An object this page is a part of. Immutable after creation. */&lt;br /&gt;
        struct cl_object  *cp_obj;&lt;br /&gt;
        /** Logical page index within the object. Immutable after creation. */&lt;br /&gt;
        pgoff_t            cp_index;&lt;br /&gt;
        /** List of slices. Immutable after creation. */&lt;br /&gt;
        struct list_head   cp_layers;&lt;br /&gt;
        ...&lt;br /&gt;
};&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Specify when fields are valid.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
        /**&lt;br /&gt;
         * Owning IO in cl_page_state::CPS_OWNED state. Sub-page can be owned&lt;br /&gt;
         * by sub-io.&lt;br /&gt;
         */&lt;br /&gt;
        struct cl_io      *cp_owner;&lt;br /&gt;
        /**&lt;br /&gt;
         * Owning IO request in cl_page_state::CPS_PAGEOUT and&lt;br /&gt;
         * cl_page_state::CPS_PAGEIN states. This field is maintained only in&lt;br /&gt;
         * the top-level pages.&lt;br /&gt;
         */&lt;br /&gt;
        struct cl_req     *cp_req;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
You can use [http://www.doxygen.org/grouping.html#memgroup &#039;&#039;@{&#039;&#039;&#039;...&#039;&#039;&#039;@}&#039;&#039;] syntax to define a subset of fields or &#039;&#039;enum&#039;&#039; values, which should be grouped together.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
struct cl_object_header {&lt;br /&gt;
        /** Standard lu_object_header. cl_object::co_lu::lo_header points&lt;br /&gt;
         * here. */&lt;br /&gt;
        struct lu_object_header  coh_lu;&lt;br /&gt;
        /** \name locks&lt;br /&gt;
         * \todo XXX move locks below to the separate cache-lines, they are&lt;br /&gt;
         * mostly useless otherwise.&lt;br /&gt;
         */&lt;br /&gt;
        /** @{ */&lt;br /&gt;
        /** Lock protecting page tree. */&lt;br /&gt;
        spinlock_t               coh_page_guard;&lt;br /&gt;
        /** Lock protecting lock list. */&lt;br /&gt;
        spinlock_t               coh_lock_guard;&lt;br /&gt;
        /** @} locks */&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
By default, a documenting comment goes immediately before the entity being commented.  If it is necessary to place this comment separately (e.g., to streamline comments in the header file), use the following syntax.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
/** \struct cl_page&lt;br /&gt;
 * Layered client page.&lt;br /&gt;
 *&lt;br /&gt;
 * cl_page: represents a portion of a file, cached in the memory. All pages&lt;br /&gt;
 *    of the given file are of the same size, and are kept in the radix tree&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Subsystem Overview===&lt;br /&gt;
&lt;br /&gt;
To document a subsystem, add the following comment to the header file that contains the definitions of its key datatypes.  This will group all the documentation in the &#039;&#039;@{&#039;&#039;...&#039;&#039;@}&#039;&#039; block.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
/** \defgroup component_name Component Name&lt;br /&gt;
 *&lt;br /&gt;
 * overall module documentation&lt;br /&gt;
 * ...&lt;br /&gt;
 *&lt;br /&gt;
 * @{ &lt;br /&gt;
 */&lt;br /&gt;
datatype definitions...&lt;br /&gt;
exported functions...&lt;br /&gt;
/** @} component_name */&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The single-word name &#039;&#039;component_name&#039;&#039; identifies a group to doxygen.  &#039;&#039;Component Name&#039;&#039; is the printable title of the group.  It extends to the end of the line.  See [http://doxygen.org/commands.html#cmddefgroup \defgroup] for more details.&lt;br /&gt;
&lt;br /&gt;
To separate a logical part of a larger component, add the following somewhere within the &#039;&#039;\defgroup&#039;&#039; of the component:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
/**&lt;br /&gt;
 * \name Printable Title of sub-component&lt;br /&gt;
 *&lt;br /&gt;
 * Description of a sub-component&lt;br /&gt;
 */&lt;br /&gt;
/** @{ */&lt;br /&gt;
datatype definitions...&lt;br /&gt;
exported functions...&lt;br /&gt;
/** @} */&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
If an exported function prototype in a header is located within some group, the appropriate function definition in a &#039;&#039;.c&#039;&#039; file is automatically assigned to the same group.&lt;br /&gt;
&lt;br /&gt;
A set of comments that is not lexically a part of a group can be included into it with the &#039;&#039;\addtogroup&#039;&#039; command.  It works just like &#039;&#039;\defgroup&#039;&#039;, but the printable group title is optional.  See [http://doxygen.org/commands.html#cmdaddtogroup \addtogroup] for full details.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
/** \addtogroup cl_object&lt;br /&gt;
 * @{ */&lt;br /&gt;
/**&lt;br /&gt;
 * &amp;quot;Data attributes&amp;quot; of cl_object. Data attributes can be updated&lt;br /&gt;
 * independently for a sub-object, and top-object&#039;s attributes are calculated&lt;br /&gt;
 * from sub-objects&#039; ones.&lt;br /&gt;
 */&lt;br /&gt;
struct cl_attr {&lt;br /&gt;
        /** Object size, in bytes */&lt;br /&gt;
        loff_t cat_size;&lt;br /&gt;
        ...&lt;br /&gt;
};&lt;br /&gt;
...&lt;br /&gt;
/** @} cl_object */&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Running Doxygen ==&lt;br /&gt;
You need to install the Graphviz package before you can run doxygen.&lt;br /&gt;
&lt;br /&gt;
Doxygen uses a &#039;&#039;configuration file&#039;&#039; to control how it builds documentation. See [http://www.doxygen.org/config.html Doxygen Configuration] for details.&lt;br /&gt;
&lt;br /&gt;
Lustre comes with two configuration files:&lt;br /&gt;
* &#039;&#039;build/doxyfile.ref&#039;&#039; produces a &#039;&#039;short&#039;&#039; form of the documentation set, suitable as a reference. Output is placed into the &#039;&#039;doxygen.ref/&#039;&#039; directory.&lt;br /&gt;
* &#039;&#039;build/doxyfile.api&#039;&#039; produces a full documentation set, more suitable for learning code structure. In addition to the short form, this set includes call-graphs and source code excerpts. Output is placed into the &#039;&#039;doxygen.api/&#039;&#039; directory.&lt;br /&gt;
&lt;br /&gt;
If the version of doxygen you are running is newer than the one last used to generate the configuration files, run the following commands to upgrade:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
doxygen -s -u build/doxyfile.api&lt;br /&gt;
doxygen -s -u build/doxyfile.ref&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
To build all the documentation, in the top-level lustre directory, run:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
doxygen build/doxyfile.api&lt;br /&gt;
doxygen build/doxyfile.ref&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
There are also phony Makefile targets &#039;&#039;doxygen-api&#039;&#039; and &#039;&#039;doxygen-ref&#039;&#039; to run these commands and &#039;&#039;doxygen&#039;&#039; to run both.&lt;br /&gt;
&lt;br /&gt;
Note that doxygen currently gives many warnings about undocumented entities.  These should abate as we improve the code documentation.&lt;br /&gt;
&lt;br /&gt;
== Publishing Documention ==&lt;br /&gt;
&lt;br /&gt;
The &#039;&#039;build/publish_doxygen&#039;&#039; script publishes a local version of the documentation at &amp;quot;http://wiki.lustre.org/doxygen&amp;quot;:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
build/publish_doxygen [-b branchname] [-l additional-label] [-d] [-u user] [-p port]&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The default branch is &amp;quot;master&amp;quot;.  The user and port are used to &#039;&#039;ssh&#039;&#039; into &#039;&#039;shell.lustre.sun.com&#039;&#039;.  &#039;&#039;User&#039;&#039; defaults to your &#039;&#039;$USER&#039;&#039; environment variable and &#039;&#039;port&#039;&#039; defaults to 922. The &#039;&#039;-d&#039;&#039; option instructs the script to use the current date as a label. &lt;br /&gt;
&lt;br /&gt;
Documentation is uploaded into...&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
user@shell.lustre.sun.com:/home/www/doxygen/$branch$label&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
where &#039;&#039;$label&#039;&#039; is a concatenation of all labels given on the command line in order.  The parent directory is &#039;&#039;rsync&#039;&#039;-ed to wiki.lustre.org regularly and the documentation can be browsed at...&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
http://wiki.lustre.org:/doxygen&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
When adding a new branch/label, you have to edit &#039;&#039;index.html&#039;&#039; in the doxygen directory on shell.lustre.sun.com.&lt;br /&gt;
&lt;br /&gt;
== Doxygen References ==&lt;br /&gt;
&lt;br /&gt;
[http://www.doxygen.org/ Doxygen Home]&lt;br /&gt;
&lt;br /&gt;
[http://www.doxygen.org/manual.html/ Doxygen Manual]&lt;br /&gt;
&lt;br /&gt;
[http://www.doxygen.org/commands.html/ Doxygen Special Commands]&lt;/div&gt;</summary>
		<author><name>Nathan</name></author>
	</entry>
	<entry>
		<id>http://wiki.old.lustre.org/index.php?title=Documenting_Code&amp;diff=9061</id>
		<title>Documenting Code</title>
		<link rel="alternate" type="text/html" href="http://wiki.old.lustre.org/index.php?title=Documenting_Code&amp;diff=9061"/>
		<updated>2009-12-15T22:29:31Z</updated>

		<summary type="html">&lt;p&gt;Nathan: /* Publishing Documention */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Lustre code documentation helps engineers working on the code to read and correctly modify the code.  The reader is expected to have a good overall grasp of the [[Lustre_Internals|Lustre architecture and internals]]. The code documentation provides reference information on the application programming interfaces (APIs) and describes significant internal features of each [[Subsystem Map|Lustre subsystem]]. &lt;br /&gt;
&lt;br /&gt;
Lustre code documentation consists of stylized comments embedded in the source code, which helps to keep the documentation consistent as the code is developed. The embedded comments can be processed by [http://www.doxygen.org doxygen] into online, browse-able (HTML) documentation.&lt;br /&gt;
&lt;br /&gt;
== Requirements ==&lt;br /&gt;
&lt;br /&gt;
The minimum requirement for documenting Lustre code is to describe subsystem APIs - the datatypes, procedures and globals subsystem exports to the rest of Lustre - and significant internal datatypes.  These should be described as follows:&lt;br /&gt;
&lt;br /&gt;
* Datatypes (structs, typedefs, enums)&lt;br /&gt;
** What it is for&lt;br /&gt;
** Structure members&lt;br /&gt;
** Usage constraints&lt;br /&gt;
* Procedures&lt;br /&gt;
** What it does&lt;br /&gt;
** Parameters&lt;br /&gt;
** Return values&lt;br /&gt;
** Usage constraints&lt;br /&gt;
** Subtle implementation details&lt;br /&gt;
* Globals&lt;br /&gt;
** What it is for&lt;br /&gt;
** Usage constraints&lt;br /&gt;
&lt;br /&gt;
The &#039;&#039;most important&#039;&#039; information to include are &amp;quot;Usage constraints&amp;quot; and &amp;quot;Subtle implementation details&amp;quot;.  &lt;br /&gt;
&lt;br /&gt;
&amp;quot;Usage constraints&amp;quot; are restrictions on how and when you call a procedure or operate on a datastructure.  These include concurrency control, reference counting, permitted caller context etc. etc.  &lt;br /&gt;
&lt;br /&gt;
&amp;quot;Subtle implementation details&amp;quot; are anything done in the code that might not be transparently obvious, such as code that ensures the last thread in a pool of workers is held in reserve for deadlock avoidance.  &lt;br /&gt;
&lt;br /&gt;
A well-chosen descriptive name can allow other information, such as what the procedure does or what a parameter means, to be quite brief or even omitted.  But usage constraints and implementation subtleties must always be spelled out, e.g. by describing an object&#039;s entire lifecycle from creation through to destruction, so that the next engineer to maintain or use the code does it safely and correctly.  &lt;br /&gt;
&lt;br /&gt;
Each time you make a change to the Lustre code or inspect a patch, you must review the changes to ensure:&lt;br /&gt;
&lt;br /&gt;
* Sufficient documentation exists.&lt;br /&gt;
* The documentation is accurate and up to date.&lt;br /&gt;
&lt;br /&gt;
== Examples ==&lt;br /&gt;
&lt;br /&gt;
Doxygen comments start with [http://www.doxygen.org/docblocks.html &#039;&#039;/**&#039;&#039;] (like in [http://en.wikipedia.org/wiki/Javadoc javadoc]).  &lt;br /&gt;
&lt;br /&gt;
Doxygen commands are placed in doxygen comments to control how doxygen formats the output.  Commands start with a backslash (&#039;&#039;\&#039;&#039;) or at-sign (&#039;&#039;@&#039;&#039;), but we typically use the backslash and reserve the at-sign for group blocks (see below).  Don&#039;t use doxygen commands unnecessarily.  &lt;br /&gt;
&lt;br /&gt;
The main purpose of code documentation is to be available in the code for you to read when you&#039;re working on the code. So it&#039;s important that the comments read like real C comments and not formatting gibberish.&lt;br /&gt;
&lt;br /&gt;
===Procedures and Globals===&lt;br /&gt;
Document procedures and globals in the &#039;&#039;.c&#039;&#039; files, rather than in headers.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
/**&lt;br /&gt;
 * Owns a page by IO.&lt;br /&gt;
 *&lt;br /&gt;
 * Waits until \a pg is in cl_page_state::CPS_CACHED state, and then switch it&lt;br /&gt;
 * into cl_page_state::CPS_OWNED state.&lt;br /&gt;
 *&lt;br /&gt;
 * \param io IO context which wants to own the page&lt;br /&gt;
 * \param pg page to be owned&lt;br /&gt;
 *&lt;br /&gt;
 * \pre  !cl_page_is_owned(pg, io)&lt;br /&gt;
 * \post result == 0 iff cl_page_is_owned(pg, io)&lt;br /&gt;
 *&lt;br /&gt;
 * \retval 0   success&lt;br /&gt;
 *&lt;br /&gt;
 * \retval -ve failure, e.g., page was destroyed (and landed in&lt;br /&gt;
 *             cl_page_state::CPS_FREEING instead of cl_page_state::CPS_CACHED).&lt;br /&gt;
 *&lt;br /&gt;
 * \see cl_page_disown()&lt;br /&gt;
 * \see cl_page_operations::cpo_own()&lt;br /&gt;
 */&lt;br /&gt;
int cl_page_own(const struct lu_env *env, struct cl_io *io, struct cl_page *pg)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;Notes:&#039;&#039;&lt;br /&gt;
* Start with a brief description, which continues to the first &#039;.&#039; (period or full stop).&lt;br /&gt;
* Follow the brief description with a detailed description.&lt;br /&gt;
* Descriptions are written in the third person singular,  e.g. &amp;quot;&amp;lt;this function&amp;gt; does this and that&amp;quot;, &amp;quot;&amp;lt;this datatype&amp;gt; represents such and such a concept&amp;quot;.&lt;br /&gt;
* To refer to a function argument, use the [http://www.doxygen.org/commands.html#cmda &#039;&#039;\a argname&#039;&#039;] syntax.&lt;br /&gt;
* To refer to another function, use the [http://www.doxygen.org/autolink.html &#039;&#039;funcname()&#039;&#039;] syntax.  This will produce a cross-reference.&lt;br /&gt;
* To refer to a field or an enum value use the [http://www.doxygen.org/autolink.html &#039;&#039;SCOPE::NAME&#039;&#039;] syntax.&lt;br /&gt;
* Describe possible return values with [http://www.doxygen.org/commands.html#cmdretval &#039;&#039;\retval&#039;&#039;].&lt;br /&gt;
* Mention all concurrency control restrictions here (such as locks that the function expects to be held, or holds on exit).&lt;br /&gt;
* If possible, specify a (weakest) pre-condition and (strongest) post-condition for the function. If conditions cannot be expressed as a C language expression, provide an informal description.&lt;br /&gt;
* Enumerate related functions and datatypes in the [http://www.doxygen.org/commands.html#cmdsee &#039;&#039;\see&#039;&#039;] section. Note, that doxygen will automatically cross-reference all places where a given function is called (but not through a function pointer) and all functions that it calls, so there is no need to enumerate all this.&lt;br /&gt;
&lt;br /&gt;
===Datatypes===&lt;br /&gt;
Document datatypes where they are declared.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
/**&lt;br /&gt;
 * &amp;quot;Compound&amp;quot; object, consisting of multiple layers.&lt;br /&gt;
 *&lt;br /&gt;
 * Compound object with given fid is unique with given lu_site.&lt;br /&gt;
 *&lt;br /&gt;
 * Note, that object does *not* necessary correspond to the real object in the&lt;br /&gt;
 * persistent storage: object is an anchor for locking and method calling, so&lt;br /&gt;
 * it is created for things like not-yet-existing child created by mkdir or&lt;br /&gt;
 * create calls. lu_object_operations::loo_exists() can be used to check&lt;br /&gt;
 * whether object is backed by persistent storage entity.&lt;br /&gt;
 */&lt;br /&gt;
struct lu_object_header {&lt;br /&gt;
        /**&lt;br /&gt;
         * Object flags from enum lu_object_header_flags. Set and checked&lt;br /&gt;
         * atomically.&lt;br /&gt;
         */&lt;br /&gt;
        unsigned long     loh_flags;&lt;br /&gt;
        /**&lt;br /&gt;
         * Object reference count. Protected by lu_site::ls_guard.&lt;br /&gt;
         */&lt;br /&gt;
        atomic_t          loh_ref;&lt;br /&gt;
        /**&lt;br /&gt;
         * Fid, uniquely identifying this object.&lt;br /&gt;
         */&lt;br /&gt;
        struct lu_fid     loh_fid;&lt;br /&gt;
        /**&lt;br /&gt;
         * Common object attributes, cached for efficiency. From enum&lt;br /&gt;
         * lu_object_header_attr.&lt;br /&gt;
         */&lt;br /&gt;
        __u32             loh_attr;&lt;br /&gt;
        /**&lt;br /&gt;
         * Linkage into per-site hash table. Protected by lu_site::ls_guard.&lt;br /&gt;
         */&lt;br /&gt;
        struct hlist_node loh_hash;&lt;br /&gt;
        /**&lt;br /&gt;
         * Linkage into per-site LRU list. Protected by lu_site::ls_guard.&lt;br /&gt;
         */&lt;br /&gt;
        struct list_head  loh_lru;&lt;br /&gt;
        /**&lt;br /&gt;
         * Linkage into list of layers. Never modified once set (except lately&lt;br /&gt;
         * during object destruction). No locking is necessary.&lt;br /&gt;
         */&lt;br /&gt;
        struct list_head  loh_layers;&lt;br /&gt;
};&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Describe datatype invariants (preferably formally).&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
/**&lt;br /&gt;
 * Fields are protected by the lock on cfs_page_t, except for atomics and&lt;br /&gt;
 * immutables.&lt;br /&gt;
 *&lt;br /&gt;
 * \invariant Datatype invariants are in cl_page_invariant(). Basically:&lt;br /&gt;
 * cl_page::cp_parent and cl_page::cp_child are a well-formed double-linked&lt;br /&gt;
 * list, consistent with the parent/child pointers in the cl_page::cp_obj and&lt;br /&gt;
 * cl_page::cp_owner (when set).&lt;br /&gt;
 */&lt;br /&gt;
struct cl_page {&lt;br /&gt;
        /** Reference counter. */&lt;br /&gt;
        atomic_t           cp_ref;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Describe concurrency control mechanisms for structure fields.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
        /** An object this page is a part of. Immutable after creation. */&lt;br /&gt;
        struct cl_object  *cp_obj;&lt;br /&gt;
        /** Logical page index within the object. Immutable after creation. */&lt;br /&gt;
        pgoff_t            cp_index;&lt;br /&gt;
        /** List of slices. Immutable after creation. */&lt;br /&gt;
        struct list_head   cp_layers;&lt;br /&gt;
        ...&lt;br /&gt;
};&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Specify when fields are valid.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
        /**&lt;br /&gt;
         * Owning IO in cl_page_state::CPS_OWNED state. Sub-page can be owned&lt;br /&gt;
         * by sub-io.&lt;br /&gt;
         */&lt;br /&gt;
        struct cl_io      *cp_owner;&lt;br /&gt;
        /**&lt;br /&gt;
         * Owning IO request in cl_page_state::CPS_PAGEOUT and&lt;br /&gt;
         * cl_page_state::CPS_PAGEIN states. This field is maintained only in&lt;br /&gt;
         * the top-level pages.&lt;br /&gt;
         */&lt;br /&gt;
        struct cl_req     *cp_req;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
You can use [http://www.doxygen.org/grouping.html#memgroup &#039;&#039;@{&#039;&#039;&#039;...&#039;&#039;&#039;@}&#039;&#039;] syntax to define a subset of fields or &#039;&#039;enum&#039;&#039; values, which should be grouped together.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
struct cl_object_header {&lt;br /&gt;
        /** Standard lu_object_header. cl_object::co_lu::lo_header points&lt;br /&gt;
         * here. */&lt;br /&gt;
        struct lu_object_header  coh_lu;&lt;br /&gt;
        /** \name locks&lt;br /&gt;
         * \todo XXX move locks below to the separate cache-lines, they are&lt;br /&gt;
         * mostly useless otherwise.&lt;br /&gt;
         */&lt;br /&gt;
        /** @{ */&lt;br /&gt;
        /** Lock protecting page tree. */&lt;br /&gt;
        spinlock_t               coh_page_guard;&lt;br /&gt;
        /** Lock protecting lock list. */&lt;br /&gt;
        spinlock_t               coh_lock_guard;&lt;br /&gt;
        /** @} locks */&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
By default, a documenting comment goes immediately before the entity being commented.  If it is necessary to place this comment separately (e.g., to streamline comments in the header file), use the following syntax.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
/** \struct cl_page&lt;br /&gt;
 * Layered client page.&lt;br /&gt;
 *&lt;br /&gt;
 * cl_page: represents a portion of a file, cached in the memory. All pages&lt;br /&gt;
 *    of the given file are of the same size, and are kept in the radix tree&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Subsystem Overview===&lt;br /&gt;
&lt;br /&gt;
To document a subsystem, add the following comment to the header file that contains the definitions of its key datatypes.  This will group all the documentation in the &#039;&#039;@{&#039;&#039;...&#039;&#039;@}&#039;&#039; block.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
/** \defgroup component_name Component Name&lt;br /&gt;
 *&lt;br /&gt;
 * overall module documentation&lt;br /&gt;
 * ...&lt;br /&gt;
 *&lt;br /&gt;
 * @{ &lt;br /&gt;
 */&lt;br /&gt;
datatype definitions...&lt;br /&gt;
exported functions...&lt;br /&gt;
/** @} component_name */&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The single-word name &#039;&#039;component_name&#039;&#039; identifies a group to doxygen.  &#039;&#039;Component Name&#039;&#039; is the printable title of the group.  It extends to the end of the line.  See [http://doxygen.org/commands.html#cmddefgroup \defgroup] for more details.&lt;br /&gt;
&lt;br /&gt;
To separate a logical part of a larger component, add the following somewhere within the &#039;&#039;\defgroup&#039;&#039; of the component:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
/**&lt;br /&gt;
 * \name Printable Title of sub-component&lt;br /&gt;
 *&lt;br /&gt;
 * Description of a sub-component&lt;br /&gt;
 */&lt;br /&gt;
/** @{ */&lt;br /&gt;
datatype definitions...&lt;br /&gt;
exported functions...&lt;br /&gt;
/** @} */&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
If an exported function prototype in a header is located within some group, the appropriate function definition in a &#039;&#039;.c&#039;&#039; file is automatically assigned to the same group.&lt;br /&gt;
&lt;br /&gt;
A set of comments that is not lexically a part of a group can be included into it with the &#039;&#039;\addtogroup&#039;&#039; command.  It works just like &#039;&#039;\defgroup&#039;&#039;, but the printable group title is optional.  See [http://doxygen.org/commands.html#cmdaddtogroup \addtogroup] for full details.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
/** \addtogroup cl_object&lt;br /&gt;
 * @{ */&lt;br /&gt;
/**&lt;br /&gt;
 * &amp;quot;Data attributes&amp;quot; of cl_object. Data attributes can be updated&lt;br /&gt;
 * independently for a sub-object, and top-object&#039;s attributes are calculated&lt;br /&gt;
 * from sub-objects&#039; ones.&lt;br /&gt;
 */&lt;br /&gt;
struct cl_attr {&lt;br /&gt;
        /** Object size, in bytes */&lt;br /&gt;
        loff_t cat_size;&lt;br /&gt;
        ...&lt;br /&gt;
};&lt;br /&gt;
...&lt;br /&gt;
/** @} cl_object */&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Running Doxygen ==&lt;br /&gt;
You need to install the Graphviz package before you can run doxygen.&lt;br /&gt;
&lt;br /&gt;
Doxygen uses a &#039;&#039;configuration file&#039;&#039; to control how it builds documentation. See [http://www.doxygen.org/config.html Doxygen Configuration] for details.&lt;br /&gt;
&lt;br /&gt;
Lustre comes with two configuration files:&lt;br /&gt;
* &#039;&#039;build/doxyfile.ref&#039;&#039; produces a &#039;&#039;short&#039;&#039; form of the documentation set, suitable as a reference. Output is placed into the &#039;&#039;doxygen.ref/&#039;&#039; directory.&lt;br /&gt;
* &#039;&#039;build/doxyfile.api&#039;&#039; produces a full documentation set, more suitable for learning code structure. In addition to the short form, this set includes call-graphs and source code excerpts. Output is placed into the &#039;&#039;doxygen.api/&#039;&#039; directory.&lt;br /&gt;
&lt;br /&gt;
If the version of doxygen you are running is newer than the one last used to generate the configuration files, run the following commands to upgrade:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
doxygen -s -u build/doxyfile.api&lt;br /&gt;
doxygen -s -u build/doxyfile.ref&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
To build all the documentation, in the top-level lustre directory, run:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
doxygen build/doxyfile.api&lt;br /&gt;
doxygen build/doxyfile.ref&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
There are also phony Makefile targets &#039;&#039;doxygen-api&#039;&#039; and &#039;&#039;doxygen-ref&#039;&#039; to run these commands and &#039;&#039;doxygen&#039;&#039; to run both.&lt;br /&gt;
&lt;br /&gt;
Note that doxygen currently gives many warnings about undocumented entities.  These should abate as we improve the code documentation.&lt;br /&gt;
&lt;br /&gt;
== Publishing Documention ==&lt;br /&gt;
&lt;br /&gt;
The &#039;&#039;build/publish_doxygen&#039;&#039; script publishes a local version of the documentation at &amp;quot;http://wiki.lustre.org/doxygen&amp;quot;:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
build/publish_doxygen [-b branchname] [-l additional-label] [-d] [-u user] [-p port]&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The script tries to guess the branchname by looking at the current branch.  The user and port are used to &#039;&#039;ssh&#039;&#039; into &#039;&#039;shell.lustre.sun.com&#039;&#039;.  &#039;&#039;User&#039;&#039; defaults to your &#039;&#039;$USER&#039;&#039; environment variable and &#039;&#039;port&#039;&#039; defaults to 922. The &#039;&#039;-d&#039;&#039; option instructs the script to use the current date as a label. &lt;br /&gt;
&lt;br /&gt;
Documentation is uploaded into...&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
user@shell.lustre.sun.com:/home/www/doxygen/$branch$label&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
where &#039;&#039;$label&#039;&#039; is a concatenation of all labels given on the command line in order.  The parent directory is &#039;&#039;rsync&#039;&#039;-ed to wiki.lustre.org regularly and the documentation can be browsed at...&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
http://wiki.lustre.org:/doxygen&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
When adding a new branch/label, you have to edit &#039;&#039;index.html&#039;&#039; in the doxygen directory on shell.lustre.sun.com.&lt;br /&gt;
&lt;br /&gt;
== Doxygen References ==&lt;br /&gt;
&lt;br /&gt;
[http://www.doxygen.org/ Doxygen Home]&lt;br /&gt;
&lt;br /&gt;
[http://www.doxygen.org/manual.html/ Doxygen Manual]&lt;br /&gt;
&lt;br /&gt;
[http://www.doxygen.org/commands.html/ Doxygen Special Commands]&lt;/div&gt;</summary>
		<author><name>Nathan</name></author>
	</entry>
	<entry>
		<id>http://wiki.old.lustre.org/index.php?title=Migrating_to_Git&amp;diff=9037</id>
		<title>Migrating to Git</title>
		<link rel="alternate" type="text/html" href="http://wiki.old.lustre.org/index.php?title=Migrating_to_Git&amp;diff=9037"/>
		<updated>2009-12-14T20:13:23Z</updated>

		<summary type="html">&lt;p&gt;Nathan: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;To migrate ongoing work from CVS to git SCM, first convert your work to a patch, then apply that patch to a git tree.&lt;br /&gt;
== Convert your work to patches ==&lt;br /&gt;
=== Work that does &#039;&#039;NOT&#039;&#039; live in a private CVS branch ===&lt;br /&gt;
If you maintain your development code with quilt or something else other than a CVS private branch, generate patches for any current work.&lt;br /&gt;
 cvs diff &amp;gt; my.patch&lt;br /&gt;
&lt;br /&gt;
=== Work from a private CVS branch ===&lt;br /&gt;
1. In your branch CVS working tree, use &#039;cvs diff&#039; against the base tree divergence point.  Since you&#039;ve been using the build/merge scripts, this is quite easy.  For example, params tree branch:&lt;br /&gt;
 cvs diff -r HD_PARAMS_TREE_BASE &amp;gt; hd_params_tree.patch&lt;br /&gt;
The merge scripts have kept the &amp;lt;branchname&amp;gt;_BASE tag updated to reflect the latest merge (don&#039;t use an old dated tag, use the one ending in _BASE).&lt;br /&gt;
&lt;br /&gt;
This cvs diff will include uncommitted changes in your working tree as well as all your committed code, so make sure your working directory tree is in the state you want. &lt;br /&gt;
&lt;br /&gt;
2. Inspect your patch to make sure it is correct.  It will be a patch against the divergence point, so realize that the base branch may have moved on and your patch may have to be updated when you apply it.&lt;br /&gt;
&lt;br /&gt;
== Apply your patches to a git repo ==&lt;br /&gt;
Obtain a clone of the [https://wikis.lustre.org/intra/index.php/Lustre_GIT#Getting_the_Lustre_repository lustre repository].&lt;br /&gt;
 git clone --origin prime git@git.lustre.org:prime/lustre &amp;lt;mydir&amp;gt;&lt;br /&gt;
 cd &amp;lt;mydir&amp;gt;&lt;br /&gt;
Create your own private branch.  For example, a branch for bug 20000 based off of HEAD:&lt;br /&gt;
 git checkout -b bug20000 master&lt;br /&gt;
Apply the patch to that branch&lt;br /&gt;
 patch -p1 &amp;lt; hd_params_tree.patch&lt;br /&gt;
Resolve any merge conflicts, and commit the patch (to your branch)&lt;br /&gt;
 git commit -a -v&lt;br /&gt;
&lt;br /&gt;
== Continue development ==&lt;br /&gt;
Sun employees should continue development under git as per the [https://wikis.lustre.org/intra/index.php/Lustre_GIT Lustre GIT page].&lt;br /&gt;
&lt;br /&gt;
External contributors should follow the procedure for [http://wiki.lustre.org/index.php/Submitting_Patches submitting patches].&lt;/div&gt;</summary>
		<author><name>Nathan</name></author>
	</entry>
	<entry>
		<id>http://wiki.old.lustre.org/index.php?title=Migrating_to_Git&amp;diff=9036</id>
		<title>Migrating to Git</title>
		<link rel="alternate" type="text/html" href="http://wiki.old.lustre.org/index.php?title=Migrating_to_Git&amp;diff=9036"/>
		<updated>2009-12-14T20:08:31Z</updated>

		<summary type="html">&lt;p&gt;Nathan: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;To migrate ongoing work from CVS to git SCM, first convert your work to a patch, then apply that patch to a git tree.&lt;br /&gt;
== Convert your work to patches ==&lt;br /&gt;
=== Work that does &#039;&#039;NOT&#039;&#039; live in a private CVS branch ===&lt;br /&gt;
If you maintain your development code with quilt or something else other than a CVS private branch, generate patches for any current work.&lt;br /&gt;
 cvs diff &amp;gt; my.patch&lt;br /&gt;
&lt;br /&gt;
=== Work from a private CVS branch ===&lt;br /&gt;
1. In your branch CVS working tree, use &#039;cvs diff&#039; against the base tree divergence point.  Since you&#039;ve been using the build/merge scripts, this is quite easy.  For example, params tree branch:&lt;br /&gt;
 cvs diff -r HD_PARAMS_TREE_BASE &amp;gt; hd_params_tree.patch&lt;br /&gt;
The merge scripts have kept the &amp;lt;branchname&amp;gt;_BASE tag updated to reflect the latest merge (don&#039;t use an old dated tag, use the one ending in _BASE).&lt;br /&gt;
&lt;br /&gt;
This cvs diff will include uncommitted changes in your working tree as well as all your committed code, so make sure your working directory tree is in the state you want. &lt;br /&gt;
&lt;br /&gt;
2. Inspect your patch to make sure it is correct.  It will be a patch against the divergence point, so realize that the base branch may have moved on and your patch may have to be updated when you apply it.&lt;br /&gt;
&lt;br /&gt;
== Apply your patches to a git repo ==&lt;br /&gt;
Obtain a clone of the [https://wikis.lustre.org/intra/index.php/Lustre_GIT#Getting_the_Lustre_repository lustre repository].&lt;br /&gt;
 git clone --origin prime git@git.lustre.org:prime/lustre &amp;lt;mydir&amp;gt;&lt;br /&gt;
 cd &amp;lt;mydir&amp;gt;&lt;br /&gt;
Create your own private branch.  For example, a branch for bug 20000 based off of HEAD:&lt;br /&gt;
 git checkout -b bug20000 master&lt;br /&gt;
Apply the patch to that branch&lt;br /&gt;
 patch -p1 &amp;lt; hd_params_tree.patch&lt;br /&gt;
Resolve any merge conflicts, and commit the patch (to your branch)&lt;br /&gt;
 git commit -a -v&lt;br /&gt;
&lt;br /&gt;
Sun employees should continue development under git as per the [https://wikis.lustre.org/intra/index.php/Lustre_GIT Lustre GIT page]&lt;/div&gt;</summary>
		<author><name>Nathan</name></author>
	</entry>
	<entry>
		<id>http://wiki.old.lustre.org/index.php?title=Migrating_to_Git&amp;diff=9035</id>
		<title>Migrating to Git</title>
		<link rel="alternate" type="text/html" href="http://wiki.old.lustre.org/index.php?title=Migrating_to_Git&amp;diff=9035"/>
		<updated>2009-12-14T19:58:08Z</updated>

		<summary type="html">&lt;p&gt;Nathan: add content&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;To migrate ongoing work from CVS to git SCM, first convert your work to a patch, then apply that patch to a git tree.&lt;br /&gt;
== Convert your work to patches ==&lt;br /&gt;
=== Work that does &#039;&#039;NOT&#039;&#039; live in a private CVS branch ===&lt;br /&gt;
If you maintain your development code with quilt or something else other than a CVS private branch, generate patches for any current work.&lt;br /&gt;
 cvs diff &amp;gt; my.patch&lt;br /&gt;
&lt;br /&gt;
=== Work from a private CVS branch ===&lt;br /&gt;
1. In your branch CVS working tree, use &#039;cvs diff&#039; against the base tree divergence point.  Since you&#039;ve been using the build/merge scripts, this is quite easy.  For example, params tree branch:&lt;br /&gt;
 cvs diff -r HD_PARAMS_TREE_BASE &amp;gt; hd_params_tree.patch&lt;br /&gt;
The merge scripts have kept the &amp;lt;branchname&amp;gt;_BASE tag updated to reflect the latest merge (don&#039;t use an old dated tag, use the one ending in _BASE).&lt;br /&gt;
&lt;br /&gt;
This cvs diff will include uncommitted changes in your working tree as well as all your committed code, so make sure your working directory tree is in the state you want. &lt;br /&gt;
&lt;br /&gt;
2. Inspect your patch to make sure it is correct.  It will be a patch against the divergence point, so realize that the base branch may have moved on and your patch may have to be updated when you apply it.&lt;br /&gt;
&lt;br /&gt;
== Apply your patches to a git repo ==&lt;br /&gt;
Obtain a clone of the [https://wikis.lustre.org/intra/index.php/Lustre_GIT#Getting_the_Lustre_repository lustre repository].&lt;br /&gt;
 git clone --origin prime git@git.lustre.org:prime/lustre &amp;lt;mydir&amp;gt;&lt;br /&gt;
 cd &amp;lt;mydir&amp;gt;&lt;br /&gt;
Create your own private branch.  For example, a branch for bug 20000 based off of HEAD:&lt;br /&gt;
 git checkout -b bug20000 master&lt;br /&gt;
Apply the patch to that branch&lt;br /&gt;
 patch -p1 &amp;lt; hd_params_tree.patch&lt;br /&gt;
Resolve any merge conflicts, and commit the patch (to your branch)&lt;br /&gt;
 git commit -a -v&lt;br /&gt;
&lt;br /&gt;
Now continue development under git as per the [https://wikis.lustre.org/intra/index.php/Lustre_GIT Lustre GIT page]&lt;/div&gt;</summary>
		<author><name>Nathan</name></author>
	</entry>
	<entry>
		<id>http://wiki.old.lustre.org/index.php?title=Architecture_-_HSM_Migration&amp;diff=9727</id>
		<title>Architecture - HSM Migration</title>
		<link rel="alternate" type="text/html" href="http://wiki.old.lustre.org/index.php?title=Architecture_-_HSM_Migration&amp;diff=9727"/>
		<updated>2009-04-21T20:31:35Z</updated>

		<summary type="html">&lt;p&gt;Nathan: /* Version 1 (&amp;quot;simple&amp;quot;): &amp;quot;Migration on open&amp;quot; policy */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Purpose ==&lt;br /&gt;
&lt;br /&gt;
This page describes use cases and high-level architecture for migrating files between Lustre and a HSM system.&lt;br /&gt;
&lt;br /&gt;
== Definitions ==&lt;br /&gt;
&lt;br /&gt;
; Trigger : A process or event in the file system which causes a migration to take place (or be denied).&lt;br /&gt;
; Coordinator : A service coordinating migration of data.&lt;br /&gt;
; Agent : A service used by coordinators to move data or cancel such movement.&lt;br /&gt;
; Mover : The userspace component of the &#039;&#039;&#039;agent&#039;&#039;&#039; which copies the file between Lustre and the HSM storage.&lt;br /&gt;
; Copy tool : HSM-specific component of the &#039;&#039;&#039;mover&#039;&#039;&#039;. (May be the entire mover.)&lt;br /&gt;
; I/O request : This term groups read requests, write requests and other metadata accesses like truncate or unlink.&lt;br /&gt;
; Resident : A file whose working copy is in Lustre.&lt;br /&gt;
; Release : A released file&#039;s data has been removed by Lustre after being copied to the HSM.  The MDT retains metadata info for the file.&lt;br /&gt;
; Archive : An archived file&#039;s data resides in the HSM.  File data may or may not also reside in Lustre.  The MDT retains metadata info for the file. &lt;br /&gt;
; Restore : Copy a file from the HSM back into Lustre to make an Archived file Resident.&lt;br /&gt;
; Prestage : An explicit call (from User or Policy Engine) to Restore a Released file &lt;br /&gt;
 &lt;br /&gt;
== Use cases ==&lt;br /&gt;
&lt;br /&gt;
=== Summary ===&lt;br /&gt;
&lt;br /&gt;
{| border=1 cellspacing=0&lt;br /&gt;
|-&lt;br /&gt;
!id !! quality attribute !! summary&lt;br /&gt;
|-&lt;br /&gt;
|Restore || availability || If a file is accessed from the primary storage system (Lustre), but resides in the backend storage system (HSM) it can be relocated in the primary storage system and made available.&lt;br /&gt;
|-&lt;br /&gt;
|Archive || availability, usability || The system can copy files from the primary to the backend storage system.&lt;br /&gt;
|-&lt;br /&gt;
|access-during-archive || performance, usability || When a file is migrating and   is accessed, the migration may be aborted.&lt;br /&gt;
|-&lt;br /&gt;
|component-failure || availability || If a migration component suffers a failure. The migration is resumed or aborted depending on the migration state and the failing component.&lt;br /&gt;
|-&lt;br /&gt;
|unlink || availability || When a Lustre object is deleted, the MDTs or the OSTs request the needed removal from the HSM when needed, depending on policy.&lt;br /&gt;
|-&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== Restore (aka cache-miss aka copyin) ===&lt;br /&gt;
&lt;br /&gt;
{|border=1  cellspacing=&amp;quot;0&amp;quot;&lt;br /&gt;
|-align=&amp;quot;left&amp;quot; &lt;br /&gt;
|colspan=2|&#039;&#039;&#039;Scenario:&#039;&#039;&#039; || File data is copied from a HSM into Lustre transparently &lt;br /&gt;
|-align=&amp;quot;left&amp;quot; &lt;br /&gt;
|colspan=2|&#039;&#039;&#039;Business Goals:&#039;&#039;&#039; || Automatically provides filesystem access to all files in the HSM&lt;br /&gt;
|-align=&amp;quot;left&amp;quot; &lt;br /&gt;
|colspan=2|&#039;&#039;&#039;Relevant QA&#039;s:&#039;&#039;&#039;|| Availability&lt;br /&gt;
|-align=&amp;quot;left&amp;quot;&lt;br /&gt;
|rowspan=&amp;quot;6&amp;quot; writing-mode=&amp;quot;vertical&amp;quot;|&#039;&#039;&#039;details&#039;&#039;&#039;&lt;br /&gt;
| &#039;&#039;&#039;Stimulus:&#039;&#039;&#039;|| A released file is accessed&lt;br /&gt;
|-align=&amp;quot;left&amp;quot;&lt;br /&gt;
|&#039;&#039;&#039;Stimulus source:&#039;&#039;&#039;|| A client tries to open a released file, or an explicit call to prestage&lt;br /&gt;
|-align=&amp;quot;left&amp;quot;&lt;br /&gt;
|&#039;&#039;&#039;Environment:&#039;&#039;&#039;|| Released and restored files in Lustre &lt;br /&gt;
|-align=&amp;quot;left&amp;quot;&lt;br /&gt;
|&#039;&#039;&#039;Artifact:&#039;&#039;&#039;|| Released file&lt;br /&gt;
|-align=&amp;quot;left&amp;quot;&lt;br /&gt;
|&#039;&#039;&#039;Response:&#039;&#039;&#039;|| Block the client open request. Start a file transfer from the HSM to Lustre using the dedicated copy tool. As soon as the data are fully available, reply to the client. Tag the file as resident.&lt;br /&gt;
|-align=&amp;quot;left&amp;quot;&lt;br /&gt;
|&#039;&#039;&#039;Response measure:&#039;&#039;&#039;|| The file is 100 % resident in Lustre, the open completes without error or timeout.&lt;br /&gt;
|-align=&amp;quot;left&amp;quot;&lt;br /&gt;
|colspan=2|&#039;&#039;&#039;Questions:&#039;&#039;&#039;|| None.&lt;br /&gt;
|-align=&amp;quot;left&amp;quot;&lt;br /&gt;
|colspan=2|&#039;&#039;&#039;Issues:&#039;&#039;&#039;|| None.&lt;br /&gt;
|-&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== Archive (aka copyout) ===&lt;br /&gt;
&lt;br /&gt;
{|border=1  cellspacing=&amp;quot;0&amp;quot;&lt;br /&gt;
|-align=&amp;quot;left&amp;quot; &lt;br /&gt;
|colspan=2|&#039;&#039;&#039;Scenario:&#039;&#039;&#039; || Some files are copied to the HSM from Lustre.&lt;br /&gt;
|-align=&amp;quot;left&amp;quot; &lt;br /&gt;
|colspan=2|&#039;&#039;&#039;Business Goals:&#039;&#039;&#039; || Provides a large capacity archiving system for Lustre transparently.&lt;br /&gt;
|-align=&amp;quot;left&amp;quot; &lt;br /&gt;
|colspan=2|&#039;&#039;&#039;Relevant QA&#039;s:&#039;&#039;&#039;|| Availability, usability.&lt;br /&gt;
|-align=&amp;quot;left&amp;quot;&lt;br /&gt;
|rowspan=&amp;quot;6&amp;quot; writing-mode=&amp;quot;vertical&amp;quot;|&#039;&#039;&#039;details&#039;&#039;&#039;&lt;br /&gt;
| &#039;&#039;&#039;Stimulus:&#039;&#039;&#039;|| Explicit request&lt;br /&gt;
|-align=&amp;quot;left&amp;quot;&lt;br /&gt;
|&#039;&#039;&#039;Stimulus source:&#039;&#039;&#039;|| Administrator/User or policy engine.&lt;br /&gt;
|-align=&amp;quot;left&amp;quot;&lt;br /&gt;
|&#039;&#039;&#039;Environment:&#039;&#039;&#039;|| Candidate files from the policy.&lt;br /&gt;
|-align=&amp;quot;left&amp;quot;&lt;br /&gt;
|&#039;&#039;&#039;Artifact:&#039;&#039;&#039;|| Files matching the policy.&lt;br /&gt;
|-align=&amp;quot;left&amp;quot;&lt;br /&gt;
|&#039;&#039;&#039;Response:&#039;&#039;&#039;|| The coordinator, receiving the request, starts a transfer between Lustre and the HSM for selected files. A dedicated agent is called and will spawn the copy tool to manage the transfer. When the transfer is completed, the Lustre file is tagged as Archived and Not Dirty on the MDT.&lt;br /&gt;
|-align=&amp;quot;left&amp;quot;&lt;br /&gt;
|&#039;&#039;&#039;Response measure:&#039;&#039;&#039;|| Policy compliance.&lt;br /&gt;
|-align=&amp;quot;left&amp;quot;&lt;br /&gt;
|colspan=2|&#039;&#039;&#039;Questions:&#039;&#039;&#039;|| None.&lt;br /&gt;
|-align=&amp;quot;left&amp;quot;&lt;br /&gt;
|colspan=2|&#039;&#039;&#039;Issues:&#039;&#039;&#039;|| None.&lt;br /&gt;
|-&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== access-during-archive ===&lt;br /&gt;
&lt;br /&gt;
{|border=1  cellspacing=&amp;quot;0&amp;quot;&lt;br /&gt;
|-align=&amp;quot;left&amp;quot; &lt;br /&gt;
|colspan=2|&#039;&#039;&#039;Scenario:&#039;&#039;&#039; || The file being archived is accessed during the archival process.&lt;br /&gt;
|-align=&amp;quot;left&amp;quot; &lt;br /&gt;
|colspan=2|&#039;&#039;&#039;Business Goals:&#039;&#039;&#039; || Optimize file accesses.&lt;br /&gt;
|-align=&amp;quot;left&amp;quot; &lt;br /&gt;
|colspan=2|&#039;&#039;&#039;Relevant QA&#039;s:&#039;&#039;&#039;|| Usability.&lt;br /&gt;
|-align=&amp;quot;left&amp;quot;&lt;br /&gt;
|rowspan=&amp;quot;6&amp;quot; writing-mode=&amp;quot;vertical&amp;quot;|&#039;&#039;&#039;details&#039;&#039;&#039;&lt;br /&gt;
| &#039;&#039;&#039;Stimulus:&#039;&#039;&#039;|| File access on migrating file.&lt;br /&gt;
|-align=&amp;quot;left&amp;quot;&lt;br /&gt;
|&#039;&#039;&#039;Stimulus source:&#039;&#039;&#039;|| A process on any client opens a file or requests some specific actions.&lt;br /&gt;
|-align=&amp;quot;left&amp;quot;&lt;br /&gt;
|&#039;&#039;&#039;Environment:&#039;&#039;&#039;|| File currently undergoing archival.&lt;br /&gt;
|-align=&amp;quot;left&amp;quot;&lt;br /&gt;
|&#039;&#039;&#039;Artifact:&#039;&#039;&#039;|| File metadata.&lt;br /&gt;
|-align=&amp;quot;left&amp;quot;&lt;br /&gt;
|&#039;&#039;&#039;Response:&#039;&#039;&#039;|| Files that are modified during archival must at no point be marked as up-to-date in the HSM until it is copied completely and coherently.&lt;br /&gt;
|-align=&amp;quot;left&amp;quot;&lt;br /&gt;
|&#039;&#039;&#039;Response measure:&#039;&#039;&#039;|| Policy engine must re-queue file for archival.  MDT disallows release of the file.&lt;br /&gt;
|-align=&amp;quot;left&amp;quot;&lt;br /&gt;
|colspan=2|&#039;&#039;&#039;Questions:&#039;&#039;&#039;|| None.&lt;br /&gt;
|-align=&amp;quot;left&amp;quot;&lt;br /&gt;
|colspan=2|&#039;&#039;&#039;Issues:&#039;&#039;&#039;|| None.&lt;br /&gt;
|-&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== component-failure ===&lt;br /&gt;
&lt;br /&gt;
{|border=1  cellspacing=&amp;quot;0&amp;quot;&lt;br /&gt;
|-align=&amp;quot;left&amp;quot; &lt;br /&gt;
|colspan=2|&#039;&#039;&#039;Scenario:&#039;&#039;&#039; || A transfer component fails during a migration.&lt;br /&gt;
|-align=&amp;quot;left&amp;quot; &lt;br /&gt;
|colspan=2|&#039;&#039;&#039;Business Goals:&#039;&#039;&#039; || Interrupted jobs should be restarted.  Filesystem and HSM must remain coherent.&lt;br /&gt;
|-align=&amp;quot;left&amp;quot; &lt;br /&gt;
|colspan=2|&#039;&#039;&#039;Relevant QA&#039;s:&#039;&#039;&#039;|| Availability.&lt;br /&gt;
|-align=&amp;quot;left&amp;quot;&lt;br /&gt;
|rowspan=&amp;quot;6&amp;quot; writing-mode=&amp;quot;vertical&amp;quot;|&#039;&#039;&#039;details&#039;&#039;&#039;&lt;br /&gt;
| &#039;&#039;&#039;Stimulus:&#039;&#039;&#039;|| A component peer reaches a timeout exchanging data with a specific component.&lt;br /&gt;
|-align=&amp;quot;left&amp;quot;&lt;br /&gt;
|&#039;&#039;&#039;Stimulus source:&#039;&#039;&#039;|| Any component failure (client, MDT, agent).&lt;br /&gt;
|-align=&amp;quot;left&amp;quot;&lt;br /&gt;
|&#039;&#039;&#039;Environment:&#039;&#039;&#039;|| Lustre components used for file migration.&lt;br /&gt;
|-align=&amp;quot;left&amp;quot;&lt;br /&gt;
|&#039;&#039;&#039;Artifact:&#039;&#039;&#039;|| One component could not be reached anymore.&lt;br /&gt;
|-align=&amp;quot;left&amp;quot;&lt;br /&gt;
|&#039;&#039;&#039;Response:&#039;&#039;&#039;|| On client failure, the migration is finished anyway. On MDT/coordinator failure, a recovery mechanism using persistent state must be applied. On agent failure, the archive process is aborted and the coordinator will respawn it when necessary. On OST failure, the archive process is delayed and managed like a traditional I/O.&lt;br /&gt;
|-align=&amp;quot;left&amp;quot;&lt;br /&gt;
|&#039;&#039;&#039;Response measure:&#039;&#039;&#039;|| The system is coherent, no data transfer process is hung.&lt;br /&gt;
|-align=&amp;quot;left&amp;quot;&lt;br /&gt;
|colspan=2|&#039;&#039;&#039;Questions:&#039;&#039;&#039;|| None.&lt;br /&gt;
|-align=&amp;quot;left&amp;quot;&lt;br /&gt;
|colspan=2|&#039;&#039;&#039;Issues:&#039;&#039;&#039;|| None.&lt;br /&gt;
|-&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== unlink ===&lt;br /&gt;
&lt;br /&gt;
{|border=1  cellspacing=&amp;quot;0&amp;quot;&lt;br /&gt;
|-align=&amp;quot;left&amp;quot; &lt;br /&gt;
|colspan=2|&#039;&#039;&#039;Scenario:&#039;&#039;&#039; || A client unlinks a file in Lustre.&lt;br /&gt;
|-align=&amp;quot;left&amp;quot; &lt;br /&gt;
|colspan=2|&#039;&#039;&#039;Business Goals:&#039;&#039;&#039; || Do not limit Lustre unlink speed to HSM speed.&lt;br /&gt;
|-align=&amp;quot;left&amp;quot; &lt;br /&gt;
|colspan=2|&#039;&#039;&#039;Relevant QA&#039;s:&#039;&#039;&#039;|| Availability.&lt;br /&gt;
|-align=&amp;quot;left&amp;quot;&lt;br /&gt;
|rowspan=&amp;quot;6&amp;quot; writing-mode=&amp;quot;vertical&amp;quot;|&#039;&#039;&#039;details&#039;&#039;&#039;&lt;br /&gt;
| &#039;&#039;&#039;Stimulus:&#039;&#039;&#039;|| A client issues a unlink request on a file in Lustre.&lt;br /&gt;
|-align=&amp;quot;left&amp;quot;&lt;br /&gt;
|&#039;&#039;&#039;Stimulus source:&#039;&#039;&#039;|| A Lustre client.&lt;br /&gt;
|-align=&amp;quot;left&amp;quot;&lt;br /&gt;
|&#039;&#039;&#039;Environment:&#039;&#039;&#039;|| A Lustre filesystem with objects archived in the HSM.&lt;br /&gt;
|-align=&amp;quot;left&amp;quot;&lt;br /&gt;
|&#039;&#039;&#039;Artifact:&#039;&#039;&#039;|| A file archived in the HSM.&lt;br /&gt;
|-align=&amp;quot;left&amp;quot;&lt;br /&gt;
|&#039;&#039;&#039;Response:&#039;&#039;&#039;|| The file is unlinked normally in Lustre. For each Lustre object removed this way, an unlink request is sent to the coordinator for the corresponding removal.  This should be asynchronous and may be delayed by a large time period.&lt;br /&gt;
|-align=&amp;quot;left&amp;quot;&lt;br /&gt;
|&#039;&#039;&#039;Response measure:&#039;&#039;&#039;|| No file object exists anymore in Lustre or the archive.&lt;br /&gt;
|-align=&amp;quot;left&amp;quot;&lt;br /&gt;
|colspan=2|&#039;&#039;&#039;Questions:&#039;&#039;&#039;|| None.&lt;br /&gt;
|-align=&amp;quot;left&amp;quot;&lt;br /&gt;
|colspan=2|&#039;&#039;&#039;Issues:&#039;&#039;&#039;|| None.&lt;br /&gt;
|-&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== Components ==&lt;br /&gt;
&lt;br /&gt;
===Coordinator===&lt;br /&gt;
# dispatches requests to agents; chooses agents&lt;br /&gt;
## restore &amp;lt;FIDlist&amp;gt;&lt;br /&gt;
## archive &amp;lt;FIDlist&amp;gt;&lt;br /&gt;
## unlink &amp;lt;FIDlist&amp;gt;&lt;br /&gt;
## abort_action &amp;lt;cookie&amp;gt;&lt;br /&gt;
# consolidates repeat requests&lt;br /&gt;
# re-queues requests to a new agent if an agent becomes unresponsive (aborts old request)&lt;br /&gt;
## agents send regular progress updates to coordinator (e.g. current extent)&lt;br /&gt;
## coordinator periodically checks for stuck threads&lt;br /&gt;
# coordinator requests are persistent&lt;br /&gt;
## all requests coming to the coordinator are kept in llog, cancelled when complete or aborted &lt;br /&gt;
# kernel-space service, MDT acts as initiator for copyin&lt;br /&gt;
# ioctl interface for all requests.  Initiators are policy engine, administrator tool, or MDT for cache-miss.&lt;br /&gt;
# Location: a coordinator will be directly integrated with each MDT&lt;br /&gt;
## Agents will communicate via MDC&lt;br /&gt;
## Connection/reconnection already taken care of; no additional pinging, config&lt;br /&gt;
## Client mount option will indicate &amp;quot;agent&amp;quot;, connect flag will inform MDT&lt;br /&gt;
## MDT already has intimate knowledge of HSM bits (see below) and needs to communicate with coordinator anyhow&lt;br /&gt;
## HSM comms can use a new portal and reuse MDT threads.&lt;br /&gt;
## Coordinators will handle the same namespace segment as each MDT under CMD&lt;br /&gt;
&lt;br /&gt;
===MDT changes===&lt;br /&gt;
# Per-file layout lock&lt;br /&gt;
## A new layout lock is created for every file.  The lock contains a layout version number.&lt;br /&gt;
## Private writer lock is taken by the MDT when allocating/changing file layout (LOV EA). &lt;br /&gt;
### The lock is not released until the layout change is complete and the data exist in the new layout.  &lt;br /&gt;
### The MDT will take group extent locks for the entire file.  The group ID will be passed to the agent performing the data transfer.&lt;br /&gt;
### The current layout version is stored by the OSTs for each object in the layout.&lt;br /&gt;
## Shared reader locks are taken by anyone reading the layout (client opens, lfs getstripe) to get the layout version.&lt;br /&gt;
## Anyone taking a new extent lock anywhere in the file includes the layout version. The OST will grant an extent lock only if the layout version included in the RPC matches the object layout version.&lt;br /&gt;
# lov EA changes&lt;br /&gt;
## flags&lt;br /&gt;
### hsm_released: file is not resident on OSTs; only in HSM&lt;br /&gt;
### hsm_exists: some version of this fid exists in HSM; maybe partial or outdated&lt;br /&gt;
### hsm_dirty: file in HSM is out of date&lt;br /&gt;
### hsm_archived: a full copy of this file exists in HSM; if not hsm_dirty, then the HSM copy is current.  &lt;br /&gt;
## The hsm_released flag is always manipulated under a write layout lock, the other flags are not.&lt;br /&gt;
# new ioctls for HSM control: &lt;br /&gt;
## HSM_REQUEST: policy engine or admin requests (archive, release, restore, remove, cancel) &amp;lt;FIDlist&amp;gt;&lt;br /&gt;
## HSM_STATE_GET: user requests HSM status information on a single file&lt;br /&gt;
## HSM_STATE_SET: user sets HSM policy flags for a single file (HSM_NORELEASE, HSM_NOARCHIVE)&lt;br /&gt;
## HSM_PROGRESS: copytool reports periodic state of a single request (current extent, error)&lt;br /&gt;
## HSM_TAPEFILE_ADD: add an existing archived file into the Lustre filesystem (only metadata is copied).&lt;br /&gt;
# changelogs:&lt;br /&gt;
## new events for HSM event completion&lt;br /&gt;
### restore_complete&lt;br /&gt;
### archive_complete&lt;br /&gt;
### unlink_complete&lt;br /&gt;
## per-event flags used by HSM&lt;br /&gt;
### setattr: data_changed (actually mtime_changed for V1)&lt;br /&gt;
### archive_complete: hsm_dirty&lt;br /&gt;
### all HSM events: hsm_failed&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
===Agent===&lt;br /&gt;
&lt;br /&gt;
An &#039;&#039;&#039;agent&#039;&#039;&#039; manages local HSM requests on a client.&lt;br /&gt;
# one agent per client max; most clients will not have agents&lt;br /&gt;
# consists of two parts&lt;br /&gt;
## kernel component receives messages from the coordinator (LNET comms)&lt;br /&gt;
### agents and coordinator piggyback comms on MDC/MDT: connections, recovery, etc.&lt;br /&gt;
### coordinator uses reverse imports to send RPCs to agents&lt;br /&gt;
## userspace process copies data between Lustre and HSM backend&lt;br /&gt;
### will use special fid directory for file access (.lustre/fid/XXXX)&lt;br /&gt;
### interfaces with hardware-specific copytool to access HSM files&lt;br /&gt;
# kernel process passes requests to userspace process via socket&lt;br /&gt;
&lt;br /&gt;
===Copytool===&lt;br /&gt;
&lt;br /&gt;
The copytool copies data between Lustre and the HSM backend, and deletes the HSM object when necessary.&lt;br /&gt;
# userspace; runs on a Lustre client with HSM i/o access&lt;br /&gt;
# opens objects by fid &lt;br /&gt;
# may manipulate HSM mode flags in an EA.  &lt;br /&gt;
# uses ioctl calls on the (opened-by-fid) file to report progress to MDT.  Note MDT must pass some messages on to Coordinator.&lt;br /&gt;
## updates progress regularly while waiting for HSM (e.g. every X seconds)&lt;br /&gt;
## reports error conditions&lt;br /&gt;
## reports current extent&lt;br /&gt;
# copytool is HSM-specific, since they must move data to the HSM archive&lt;br /&gt;
## version 1 will include tools for HPSS and SAM-QFS&lt;br /&gt;
## other, vendor-proprietary (binary) tools may be wrapped in order to include Lustre ioctl progress calls. &lt;br /&gt;
&lt;br /&gt;
===Policy Engine===&lt;br /&gt;
&lt;br /&gt;
# makes policy decisions for archive, release (which files and when)&lt;br /&gt;
## policy engine will provide the functionality of the [[Space Manager|Space_Manager]] and any other archive/release policies&lt;br /&gt;
## may be based on space available per filesystem, OST, or pool&lt;br /&gt;
## may be based on any filesystem or per-file attributes (last access time, file size, file type, etc)&lt;br /&gt;
## policy engine will therefore require access to various user-available info: changelogs, getstripe, lfs df, stat, lctl get_param, etc.&lt;br /&gt;
# normally uses changelogs and &#039;df&#039; for input; rarely is allowed to scan filesystem&lt;br /&gt;
## changelogs are available to superuser on Lustre clients&lt;br /&gt;
## filesystem scans are expensive; allowed only at initial HSM setup time or other rate events&lt;br /&gt;
# the policy engine runs as a userspace process; requests archive and release via file ioctl to coordinator (through MDT).&lt;br /&gt;
# policy engine may be packaged separately from Lustre&lt;br /&gt;
# the policy engine may use HSM-backend specific features (e.g. HPSS storage class) for policy optimizations, but these will be kept modularized so they are easily removed for other systems.&lt;br /&gt;
# API can pass an opaque arbitrary chunk of data (char array, size) from policy engine ioctl call through coordinator and agent to copytool.&lt;br /&gt;
&lt;br /&gt;
===Configuration===&lt;br /&gt;
# policy engine has it&#039;s own external configuration&lt;br /&gt;
# coordinator starts as part of MDT; tracks agents registrations as clients connect&lt;br /&gt;
## connect flag to indicate agent should run on this MDC&lt;br /&gt;
## mdt_set_info RPC for setting agent status using &#039;remount&#039;&lt;br /&gt;
&lt;br /&gt;
 &lt;br /&gt;
== Scenarios ==&lt;br /&gt;
&lt;br /&gt;
=== restore (aka cache-miss, copyin) ===&lt;br /&gt;
&lt;br /&gt;
====Version 1 (&amp;quot;simple&amp;quot;): &amp;quot;Migration on open&amp;quot; policy ====&lt;br /&gt;
Clients block at open for read and write.  OSTs are not involved.&lt;br /&gt;
# Client layout-intent enqueues layout read lock on the MDT.&lt;br /&gt;
# MDT checks hsm_released bit; if released, the MDT takes PW lock on the layout&lt;br /&gt;
# MDT creates a new layout with a similar stripe pattern as the original, increasing the layout version, and allocating new objects on new OSTs with the new version. &lt;br /&gt;
#: (We should try to respect specific layout settings (pool, stripecount, stripesize), but be flexible if e.g. pool doesn&#039;t exist anymore.&lt;br /&gt;
#: Maybe we want to ignore stripe offset and/or specific OST allocations in order to rebalance.)&lt;br /&gt;
# MDT enqueues group write lock on extents 0-EOF&lt;br /&gt;
#: Extents lock enqueue timeout must be very long while group lock is held (need proc tunable here)&lt;br /&gt;
# MDT releases PW layout lock&lt;br /&gt;
#: Client open succeeds at this point, but r/w is blocked on extent locks&lt;br /&gt;
# MDT sends request to coordinator requesting restore of the file to .lustre/fid/XXXX with group lock id and extents 0-EOF. (Extents may be used in the future to (a) copy in part of a file, in low-disk-space situations; (b) copy in individual stripes simultaneously on multiple OSTs.)&lt;br /&gt;
# Coordinator distributes that request to an appropriate &#039;&#039;&#039;agent&#039;&#039;&#039;.&lt;br /&gt;
# &#039;&#039;&#039;Agent&#039;&#039;&#039; starts copytool&lt;br /&gt;
# Copytool opens .lustre/fid/&amp;lt;fid&amp;gt;&lt;br /&gt;
# Copytool takes group extents lock&lt;br /&gt;
# Copytool copies data from HSM, reporting progress via ioctl&lt;br /&gt;
# When finished, copytool reports progress of 0-EOF and closes the file, releasing group extents lock.&lt;br /&gt;
# MDT clears hsm_released bit&lt;br /&gt;
# MDT releases group extents lock&lt;br /&gt;
#: This sends a completion AST to the original client, who now receives his extents lock.&lt;br /&gt;
# MDT adds FID &amp;lt;fid&amp;gt; HSM_copyin_complete record to changelog (flags: failed)&lt;br /&gt;
&lt;br /&gt;
[[Image:hsm_copyin.png|HSM Copy-in schema]]&lt;br /&gt;
&lt;br /&gt;
====Version 2 (&amp;quot;complex&amp;quot;): &amp;quot;Migration on first I/O&amp;quot; policy ====&lt;br /&gt;
Clients are able to read/write the file data as soon as possible and the OSTs need to prevent access to the parts&lt;br /&gt;
of the file which have not yet been restored.&lt;br /&gt;
# getattr: attributes can be returned from MDT with no HSM involvement&lt;br /&gt;
## MDS holds file size[*]&lt;br /&gt;
## client may get MDS attribute read locks, but not layout lock&lt;br /&gt;
&lt;br /&gt;
# Client open intent enqueues layout read lock.&lt;br /&gt;
# MDT checks &amp;quot;purged&amp;quot; bit&lt;br /&gt;
# MDT creates a new layout with a similar stripe pattern as the original, allocating new objects on new OSTs with per-object &amp;quot;purged&amp;quot; bits set.&lt;br /&gt;
# MDT grants layout lock to client and open completes&lt;br /&gt;
# ?Should we pre-stage:  MDT sends request to coordinator requesting copyin of the file to .lustre/fid/XXXX with extents 0-EOF. &lt;br /&gt;
# client enqueues extent lock on OST. Must wait forever.&lt;br /&gt;
# check OST object is marked fully/partly invalid &lt;br /&gt;
## object may have persistent invalid map of extent(s) that indicate which parts of object require copy-in&lt;br /&gt;
# access to invalid parts of object trigger copy-in upcall to &#039;&#039;&#039;coordinator&#039;&#039;&#039; for those extents&lt;br /&gt;
## coordinator consolidates repeat requests for the same range (e.g. if entire file has already been queued for copyin, ignore specific range requests??)&lt;br /&gt;
# ? group locks on invalid part of file block writes to missing data&lt;br /&gt;
# clients block waiting on extent locks for invalid parts of objects&lt;br /&gt;
## OST crash at this time will restart enqueue process during replay&lt;br /&gt;
# &#039;&#039;&#039;coordinator&#039;&#039;&#039; contacts &#039;&#039;&#039;agent(s)&#039;&#039;&#039; to retrieve FID N extents X-Y from HSM&lt;br /&gt;
# copytool writes to actual object to be restored with &amp;quot;clear invalid&amp;quot; flag (special write)&lt;br /&gt;
## writes by agent shrink invalid extent, periodically update on-disk invalid extent and release locks on that part of file (on commit?)&lt;br /&gt;
## note changing lock extents (lock conversion) is not currently possible but is a long-term Lustre performance improvement goal.&lt;br /&gt;
# client is granted extent lock when that part of file is copied in&lt;br /&gt;
&lt;br /&gt;
=== copyout ===&lt;br /&gt;
# Policy engine (or administrator) decides to copy a file to HSM, executes HSMCopyOut ioctl on file&lt;br /&gt;
# ioctl caught by MDT, which passes request to Coordinator&lt;br /&gt;
# coordinator dispatches request to mover.  Request includes file extents (for future purposes)&lt;br /&gt;
# normal extents read lock is taken by mover running on client&lt;br /&gt;
# mover sends &amp;quot;copyout begin&amp;quot; message to coordinator via ioctl on the file&lt;br /&gt;
## coordinator/MDT sets &amp;quot;hsm_exists&amp;quot; bit and clears &amp;quot;hsm_dirty&amp;quot; bit.  &lt;br /&gt;
##: &amp;quot;hsm_exists&amp;quot; bit is never cleared, and indicates a copy (maybe partial/out of date) exists in the HSM &lt;br /&gt;
# any writes to the file cause the MDT to set the &amp;quot;hsm_dirty&amp;quot; bit (may be lazy/delayed with mtime or filesize change updates on MDT for V1).  &lt;br /&gt;
## file writes need not cancel copyout (settable via policy?  Implementation in V2.)&lt;br /&gt;
# mover sends status update to coordinator via periodic ioctl calls on the file (e.g % complete)&lt;br /&gt;
# mover sends &amp;quot;copyout done&amp;quot; message to coordinator via ioctl&lt;br /&gt;
# coordinator/MDT checks hsm_dirty bit.  &lt;br /&gt;
## If not dirty, MDT sets &amp;quot;copyout_complete&amp;quot; bit.  &lt;br /&gt;
## If dirty, coordinator dispatches another copyout request; goto step 3&lt;br /&gt;
# MDT adds FID X HSM_copyout_complete record to changelog&lt;br /&gt;
# Policy engine notes HSM_copyout_complete record from changelog (flags: failed, dirty)&lt;br /&gt;
&lt;br /&gt;
(Note: files modifications after copyout is complete will have both copyout_complete and hsm_dirty bits set.)&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Image:hsm_copyout.png|HSM Copy-out schema]]&lt;br /&gt;
&lt;br /&gt;
=== purge (aka punch) ===&lt;br /&gt;
==== V1: full file purge ====&lt;br /&gt;
# Policy engine (or administrator) decides to purge a file, executes HSMPurge ioctl on file&lt;br /&gt;
# ioctl handled by MDT&lt;br /&gt;
# MDT takes a write lock on the file layout lock&lt;br /&gt;
# MDT enques write locks on all extents of the file.  After these are granted, then no client has any dirty cache and no child can take new extent locks until layout lock is released.  MDT drops all extent locks.&lt;br /&gt;
# MDT verifies that hsm_dirty bit is clear and copyout_complete bit is set&lt;br /&gt;
## if not, the file cannot be purged, return EPERM&lt;br /&gt;
# MDT marks the LOV EA as &amp;quot;purged&amp;quot;&lt;br /&gt;
# MDT sends destroys to the OST objects, using destroy llog entries to guard against object leakage during OST failover&lt;br /&gt;
## the OSTs should eventually purge the objects during orphan recovery&lt;br /&gt;
# MDT drops layout lock.&lt;br /&gt;
&lt;br /&gt;
==== V2: partial purge ====&lt;br /&gt;
Partially purged files hopefully allows graphical file browsers to retrieve file header info or icons stored at the beginning or end of a file. &lt;br /&gt;
&#039;&#039;&#039;Note: determine exactly which parts of a file that Windows Explorer reads to generate it&#039;s icons&#039;&#039;&#039;&lt;br /&gt;
# MDT sends purge range to first and last objects, and destroys to all intermediate objects, using llog entries for recovery.&lt;br /&gt;
# First and last OSTs record purge range&lt;br /&gt;
# When requesting copyin of the entire file (first access to the middle of a partially purged file), MDT destroys old partial objects before allocating new layout. (Or: we keep old first and last objects, just allocate new &amp;quot;middle object&amp;quot; striping - yuck.)&lt;br /&gt;
&lt;br /&gt;
=== unlink ===&lt;br /&gt;
&lt;br /&gt;
# A client issues an unlink for a file to the MDT.&lt;br /&gt;
# The MDT includes the &amp;quot;hsm_exists&amp;quot; bit in the changelog unlink entry&lt;br /&gt;
# The policy engine determines if the file should be removed from HSM&lt;br /&gt;
# Policy engine sends HSMunlink FID to coordinator via MDT ioctl&lt;br /&gt;
## ioctl will be on the directory .lustre/fid&lt;br /&gt;
##: or perhaps on a new .lustre/dev/XXX where any lustre device may be listed, and act as stub files for handling ioctls.&lt;br /&gt;
# The coordinator sends a request to one of its agent for the corresponding removal.&lt;br /&gt;
# The agent spawns the HSM tool to do this removal.&lt;br /&gt;
# HSM tool reports completion via another MDT ioctl&lt;br /&gt;
# Coordinator cancels unlink request record&lt;br /&gt;
## In case of agent crash, unlink request will remain uncancelled and coordinator will eventually requeue&lt;br /&gt;
## In case of coordinator crash, agent ioctl will proceed after recovery&lt;br /&gt;
# Policy engine notes HSM_unlink_complete record from changelog (flags: failed)&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== abort ===&lt;br /&gt;
# abort dead agent&lt;br /&gt;
#: the coordinator must send an abort signal to an agent to abort a copyout/copyin if it determines the migration is stuck/crashed.  The coordinator can then re-queue the migration request elsewhere.&lt;br /&gt;
# dirty-while-copyout&lt;br /&gt;
#: If a file is written to while it is being copied out, the copyout will have an incoherent copy in some cases.&lt;br /&gt;
## We could send abort signal, but: &lt;br /&gt;
## If a filesystem has a single massive file that is used all the time, it will never get backed up if we abort.&lt;br /&gt;
## Not a problem if just appending to a file&lt;br /&gt;
## Most backup systems work this way with relatively little harm.&lt;br /&gt;
## V1: don&#039;t abort this case&lt;br /&gt;
## V2: abort in this case is a settable policy&lt;br /&gt;
&lt;br /&gt;
== Recovery ==&lt;br /&gt;
=== MDT crash ===&lt;br /&gt;
# MDT crashes and is restarted.&lt;br /&gt;
# The coordinator recreates its migration list, reading the its llog.&lt;br /&gt;
# The client, when doing its recovery with the MDT, reconnects to the coordinator. &lt;br /&gt;
## Copytool eventually sends its periodic status update for migrating files (asynchronously from reconnect).&lt;br /&gt;
## As far as the copytools/agent is concerned, the MDT restart is invisible.&lt;br /&gt;
&lt;br /&gt;
Note: The migration list is simply the list of unfinished migrations which may be read from the llog &lt;br /&gt;
at any time (no need to keep it in memory all the time, if there are many open migration requests).&lt;br /&gt;
&lt;br /&gt;
Logs should contain:&lt;br /&gt;
# fid, request type, agent_id (for aborts)&lt;br /&gt;
# if the list is not kept in memory: last_status_update_time, last_status.&lt;br /&gt;
&lt;br /&gt;
=== Client crash ===&lt;br /&gt;
# Client stops communicating with MDT&lt;br /&gt;
# MDT evicts client&lt;br /&gt;
# Eviction triggers coordinator to re-dispatch immediately all of the migrations from that agent&lt;br /&gt;
# For copyin, it is desireable that any existing agent I/O is stopped&lt;br /&gt;
## Ghost client and copytool may still be alive and communicating with OSTs, but not MDT.  Can&#039;t send abort.&lt;br /&gt;
## Taking file extent locks will only temporarily stop ghost.&lt;br /&gt;
## It&#039;s not so bad if new agent and ghost are racing trying to copyin the file at the same time.&lt;br /&gt;
### Regular extent locks prevent file corruption&lt;br /&gt;
### The file data being copied in is the same&lt;br /&gt;
### Ghost copyin may still be ongoing after new copyin has finished, in which case ghost may&lt;br /&gt;
overwrite newly-modified data (data modified by regular clients after HSM/Lustre think copyin is complete.)&lt;br /&gt;
&lt;br /&gt;
=== Copytool crash ===&lt;br /&gt;
Copytool crash is different from a client crash, since the client will not get evicted&lt;br /&gt;
# Copytool crashes&lt;br /&gt;
# Coordinator notices no status updates&lt;br /&gt;
# Coordinator sends abort signal to old agent&lt;br /&gt;
# Coordinator re-dispatches migration&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Implementation constraints ==&lt;br /&gt;
&lt;br /&gt;
# all single-file coherency issues are in kernel space (file locking, recovery)&lt;br /&gt;
# all policy decisions are in user space (using changelogs, df, etc)&lt;br /&gt;
# coordinator/mover communication will use LNET&lt;br /&gt;
# Version 1 HSM is a simplified implementation:&lt;br /&gt;
## integration with HPSS only&lt;br /&gt;
## depends on changelog for policy decisions&lt;br /&gt;
## restore on file open, not data read/write&lt;br /&gt;
# HSM tracks entire files, not stripe objects&lt;br /&gt;
# HSM namespace is flat, all files are addressed by FID only&lt;br /&gt;
# Coordinator and movers can be reused by (non-HSM) replication &lt;br /&gt;
&lt;br /&gt;
== HSM Migration components &amp;amp; interactions ==&lt;br /&gt;
Note: for V1, copyin initiators are on MDT only (file open).&lt;br /&gt;
[[Image:hsm_migration.png]]&lt;br /&gt;
&lt;br /&gt;
== For further review/detail ==&lt;br /&gt;
&lt;br /&gt;
# &amp;quot;complex&amp;quot; HSM roadmap&lt;br /&gt;
## partial access to files during restore&lt;br /&gt;
## partial purging for file type identification, image thumbnails, ??&lt;br /&gt;
## integration with other HSM backends (ADM, ??)&lt;br /&gt;
# How can layout locks be held in liblustre&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
= References =&lt;br /&gt;
[[Category:Architecture|HSM migration]]&lt;br /&gt;
&lt;br /&gt;
[https://bugzilla.lustre.org/show_bug.cgi?id=15599 HSM implementation 15599]&lt;br /&gt;
[https://bugzilla.lustre.org/show_bug.cgi?id=15699 changelogs 15699]&lt;/div&gt;</summary>
		<author><name>Nathan</name></author>
	</entry>
	<entry>
		<id>http://wiki.old.lustre.org/index.php?title=Main_Page&amp;diff=4577</id>
		<title>Main Page</title>
		<link rel="alternate" type="text/html" href="http://wiki.old.lustre.org/index.php?title=Main_Page&amp;diff=4577"/>
		<updated>2008-05-06T18:06:01Z</updated>

		<summary type="html">&lt;p&gt;Nathan: fix mailing list link&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== What is Lustre? ==&lt;br /&gt;
&lt;br /&gt;
Lustre is a scalable, secure, robust, highly-available cluster file system. It is designed, developed and maintained by Sun Microsystems, Inc.&lt;br /&gt;
&lt;br /&gt;
The central goal is the development of a next-generation cluster file system which can serve clusters with 10,000&#039;s of nodes, provide petabytes of storage, and move 100&#039;s of GB/sec with state-of-the-art security and management infrastructure.&lt;br /&gt;
&lt;br /&gt;
Lustre runs on many of the largest Linux clusters in the world, and is included by Suns&#039;s partners as a core component of their cluster offering (examples include HP StorageWorks SFS, and the Cray XT3 and XD1 supercomputers). Today&#039;s users have also demonstrated that Lustre scales down as well as it scales up, and runs in production on clusters as small as 4 and as large as 25,000 nodes.&lt;br /&gt;
&lt;br /&gt;
The latest version of Lustre is always available from Sun Microsystems, Inc. Public Open Source releases of Lustre are available under the GNU General Public License. These releases are found here, and are used in production supercomputing environments worldwide.&lt;br /&gt;
&lt;br /&gt;
To be informed of Lustre releases, subscribe to the [http://wiki.lustre.org/index.php?title=Mailing_Lists lustre-announce] mailing list.&lt;br /&gt;
&lt;br /&gt;
Lustre development would not have been possible without funding and guidance from many organizations, including several U.S. National Laboratories, early adopters, and product partners.&lt;br /&gt;
&lt;br /&gt;
== User Resources == &lt;br /&gt;
&lt;br /&gt;
* [http://www.sun.com/software/products/lustre/get.jsp Lustre Downloads]&lt;br /&gt;
* [http://wiki.lustre.org/index.php?title=Lustre_Quick_Start Lustre Quick Start]&lt;br /&gt;
* [http://wiki.lustre.org/index.php?title=Mailing_Lists Mailing Lists]&lt;br /&gt;
* [http://manual.lustre.org/index.php?title=Main_Page Lustre Operations Manual]&lt;br /&gt;
* [http://wiki.lustre.org/index.php?title=Bug_Filing Filing Bugs]&lt;br /&gt;
* [https://bugzilla.lustre.org/showdependencytree.cgi?id=2374 Lustre Knowledge Base]&lt;br /&gt;
&lt;br /&gt;
== Advanced User Resources == &lt;br /&gt;
&lt;br /&gt;
*[http://wiki.lustre.org/index.php?title=BuildLustre How to build Lustre]&lt;br /&gt;
* [http://wiki.lustre.org/index.php?title=Kerb_Lustre Kerberos]&lt;br /&gt;
* [http://wiki.lustre.org/index.php?title=LustreTuning Lustre Tuning]&lt;br /&gt;
* [http://wiki.lustre.org/images/7/78/LustreManual.html#Chapter_III-2._LustreProc LustreProc] - A guide on the proc tunable parameters for Lustre and their usage. It describes several of the proc tunables including those that effect the client&#039;s RPC behavior and prepare for a substantial reorganization of proc entries.&lt;br /&gt;
* [http://wiki.lustre.org/index.php?title=LibLustre_HowTo Liblustre HowTo]&lt;br /&gt;
&lt;br /&gt;
== Lustre Centres of Excellence™ ==&lt;br /&gt;
&lt;br /&gt;
* [http://ornl-lce.clusterfs.com/index.php?title=Main_Page ORNL]&lt;br /&gt;
* [http://www.clusterfs-mwiki.com/cea-lce CEA]&lt;br /&gt;
* [http://www.clusterfs-mwiki.com/llnl-lce LLNL]&lt;br /&gt;
* [http://www.clusterfs-mwiki.com/psc-lce/index.php?title=Main_Page PSC]&lt;br /&gt;
* [http://www.clusterfs-mwiki.com/tsinghua-lce Tsinghua]&lt;br /&gt;
&lt;br /&gt;
== Developer Resources ==&lt;br /&gt;
* [http://arch.lustre.org Lustre Architecture]&lt;br /&gt;
* [http://wiki.lustre.org/index.php?title=Contribution_Policy Contribution Policy]&lt;br /&gt;
* [http://lists.lustre.org/mailman/listinfo Developer Mailing List]&lt;br /&gt;
* CVS usage&lt;br /&gt;
** [http://wiki.lustre.org/index.php?title=Open_CVS CVS access to Lustre Source]&lt;br /&gt;
** [http://wiki.lustre.org/index.php?title=Cvs_Branches CVS Branches] - How to manage branches with CVS.&lt;br /&gt;
** [http://wiki.lustre.org/index.php?title=Cvs_Tips CVS Tips] - Helpful things to know while using Lustre CVS.&lt;br /&gt;
* [http://wiki.lustre.org/index.php?title=Lustre_Debugging Debugging Lustre] - A guide to debugging Lustre.&lt;br /&gt;
* [http://wiki.lustre.org/index.php?title=ZFS_Resources ZFS Resources] - Learn about ZFS.&lt;br /&gt;
* [http://wiki.lustre.org/index.php?title=Coding_Guidelines Coding Guidelines] - Developer guidelines to avoid problems during Lustre code merges.&lt;br /&gt;
* [http://wiki.lustre.org/index.php?title=Documenting_Code Documenting Code with Doxygen]&lt;br /&gt;
&lt;br /&gt;
== CFS Development Projects ==&lt;br /&gt;
&lt;br /&gt;
* [http://wiki.lustre.org/index.php?title=IOPerformanceProject I/O Performance]&lt;br /&gt;
* [http://wiki.lustre.org/index.php?title=Lustre_OSS/MDS_with_ZFS_DMU Lustre OSS/MDS with ZFS DMU]&lt;br /&gt;
&lt;br /&gt;
== Community Development Projects ==&lt;br /&gt;
* [http://wiki.lustre.org/index.php?title=Networking_Development Networking Development]&lt;br /&gt;
* [http://wiki.lustre.org/index.php?title=Diskless_Booting Diskless Booting]&lt;br /&gt;
* [http://wiki.lustre.org/index.php?title=Drbd_And_Lustre DRBD and Lustre]&lt;br /&gt;
* [http://www.bullopensource.org/lustre Bull- Open Source tools for Lustre]&lt;br /&gt;
* [http://www.sourceforge.net/projects/lmt LLNL- Lustre Monitoring Tool]&lt;br /&gt;
&lt;br /&gt;
== Other Resources ==&lt;br /&gt;
&lt;br /&gt;
* [http://wiki.lustre.org/index.php?title=Lustre_Publications Lustre Publications] - Papers and presentations about Lustre&lt;br /&gt;
* Lustre User Group&lt;br /&gt;
** [http://wiki.lustre.org/index.php?title=Lug_08 &#039;&#039;&#039;VIDEOS&#039;&#039;&#039;] and [http://picasaweb.google.com/overheardinpdx/LustreUserGroup2008 PHOTOS] from LUG2008 are now posted.&lt;br /&gt;
** [http://wiki.lustre.org/index.php?title=Lug_08 Lustre User Group 2008]&lt;br /&gt;
** [http://wiki.lustre.org/index.php?title=Lug_07 Lustre User Group 2007]&lt;br /&gt;
** [http://wiki.lustre.org/index.php?title=Lug_06 Lustre User Group 2006]&lt;br /&gt;
** LUG Requirements Forum - [http://wiki.lustre.org/images/7/78/LUG-Requirements-060420-final.pdf LUG-Requirements-060420-final.pdf] | [http://wiki.lustre.org/images/7/78/LUG-Requirements-060420-final.xls LUG-Requirements-060420-final.xls]&lt;/div&gt;</summary>
		<author><name>Nathan</name></author>
	</entry>
	<entry>
		<id>http://wiki.old.lustre.org/index.php?title=Architecture_-_Feature_FS_Replication&amp;diff=10448</id>
		<title>Architecture - Feature FS Replication</title>
		<link rel="alternate" type="text/html" href="http://wiki.old.lustre.org/index.php?title=Architecture_-_Feature_FS_Replication&amp;diff=10448"/>
		<updated>2008-04-09T21:27:04Z</updated>

		<summary type="html">&lt;p&gt;Nathan: /* Exported Interfaces */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Summary ==&lt;br /&gt;
&lt;br /&gt;
This article describes a feature to facilitate efficient replication of large Lustre filesystems.  Target filesystems may be Lustre or any other.  This article does not address replication in the presence of clustered metadata.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Requirements ==&lt;br /&gt;
&lt;br /&gt;
# The solution must scale to large file systems and will avoid full file system scans&lt;br /&gt;
# The algorithm must be exact - no modified files will be missed &lt;br /&gt;
# If the file system is static and the replication is performed the target will equal the source, barring errors arising during the synchronization&lt;br /&gt;
# The algorithms is safe when run repeatedly or run after an aborted attempt, will lead to understandable results when applied to a file system that is being modified during synchronization &lt;br /&gt;
# The solutions will use a list of modified files for synchronization&lt;br /&gt;
# The solution should have a suitable architecture to synchronize flash caches or object replicas&lt;br /&gt;
# The architecture of this solution will be suitable for (i) ldiskfs (ii) Lustre 1.8 (ldiskfs with MDS&amp;amp;OSS) (iii) Lustre 1.10 (new MDS with OSD based fids)&lt;br /&gt;
# The solution will address future changes of log record formats (since these will contain rollback &amp;amp; audit information also in due course)&lt;br /&gt;
# The solution may initially only work on file system without hard links (regular files with link count &amp;gt; 1).&lt;br /&gt;
# The synchronization mechanism has a facility to switch the role of source and target to perform failover and failback of services.&lt;br /&gt;
# The solution must be able to deal with different (future) record formats&lt;br /&gt;
# The solution must provide for reverse replication for the recovery case&lt;br /&gt;
&lt;br /&gt;
== Critical use cases ==&lt;br /&gt;
&lt;br /&gt;
{| border=1&lt;br /&gt;
| &#039;&#039;&#039;identifier&#039;&#039;&#039; || &#039;&#039;&#039;attribute&#039;&#039;&#039; || &#039;&#039;&#039;summary&#039;&#039;&#039; &lt;br /&gt;
|-&lt;br /&gt;
| restart ||availability || Metadata synchronization is aborted and restarted. The outcome needs to be correct.&lt;br /&gt;
|-&lt;br /&gt;
| file system full || correctness || Replication logs can cause the file system to be full.  Correct messaging to user space is included in the solution.&lt;br /&gt;
|-&lt;br /&gt;
| MDT/OST log sync || correctness || OST records new file creation in log, but the event took place after the last MDT log sync &lt;br /&gt;
|-&lt;br /&gt;
| reverse replication || correctness || A master filesystem that is restarted after a failover to a backup filesystem must be made consistent with the backup &lt;br /&gt;
|-&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== restart ===&lt;br /&gt;
# Namespace changes may not be repeated (e.g. rm a, mv b a)&lt;br /&gt;
# Rename operations may be half-finished on target (e.g. rename, but haven&#039;t updated mtime of parent dir yet when power fails, so mtime is &#039;now&#039; on target, but should be &#039;rename time&#039; instead)&lt;br /&gt;
&lt;br /&gt;
=== MDT/OST log sync ===&lt;br /&gt;
Correctly deal with the following cases: after a namespace log sync (epoch 1):&lt;br /&gt;
# New file is created&lt;br /&gt;
#: Ignore OST updates to files that were created after the epoch. The creation will be noted in the next MDT epoch, at which point the entire file (data and md) must be copied.  &lt;br /&gt;
#* Sync namespace epoch 1&lt;br /&gt;
#* (data record a) Modify file foo, ino=1&lt;br /&gt;
#* (namespace record b) mv foo bar&lt;br /&gt;
#* (namespace record c) Create file foo, ino=2&lt;br /&gt;
#* (data record d) Modify file foo, ino=2&lt;br /&gt;
#* Sync data&lt;br /&gt;
#** (record a) lookup destname of ino=1: it is foo, so copy ino=1 to dest:/foo&lt;br /&gt;
#** (record d) lookup destname of ino=2: when computing destname, we determine it did not exist at epoch 1 (we see create record in the active namespace log); return a special code and don&#039;t sync this file. Old &amp;quot;foo&amp;quot; on target is not modified.&lt;br /&gt;
#* Sync namespace epoch 2&lt;br /&gt;
#** (record b) move dest:/foo to dest:/bar&lt;br /&gt;
#** (record c) create dest:/foo; copy ino=2 to dest:/foo &lt;br /&gt;
# File is deleted&lt;br /&gt;
#: Leave the old version on dest alone.  File will be deleted on dest in epoch 2; any recent data changes made on the source before the delete will be lost.&lt;br /&gt;
#* See Solution Limitation A&lt;br /&gt;
# File moved off of OST (archive, space balance, ?)&lt;br /&gt;
#* for file-level replication, this is a non-event&lt;br /&gt;
#* for object-level replication, ?? leave special redirect record stub file&lt;br /&gt;
&lt;br /&gt;
=== Reverse Replication ===&lt;br /&gt;
filesystem A is &amp;quot;failed over&amp;quot; to a backup system B that was current as of some epoch.  When failing back, updates from B must be replicated on A such that A is consistent with B.   &lt;br /&gt;
&lt;br /&gt;
FIXME We need to decide something here&lt;br /&gt;
Options: Changes on A after the epoch should be:&lt;br /&gt;
# reverted&lt;br /&gt;
## deleted files can be resurrected from B&lt;br /&gt;
## created files should be deleted&lt;br /&gt;
## namespace moves are undone&lt;br /&gt;
## ? files with mtimes after the epoch are recopied from B&lt;br /&gt;
## this assumes we have complete up-to-date changelogs&lt;br /&gt;
# kept, except in the case of conflicts&lt;br /&gt;
## conflict policy: new master always wins&lt;br /&gt;
## conflict policy: latest update wins&lt;br /&gt;
## conflict policy: ? something else&lt;br /&gt;
## changes since the epoch must be replicated back to B as well&lt;br /&gt;
&lt;br /&gt;
== Definitions ==&lt;br /&gt;
&lt;br /&gt;
; &#039;&#039;&#039;Source File System&#039;&#039;&#039; : The file system that is being changed and that we want to replicate.&lt;br /&gt;
; &#039;&#039;&#039;Target File System&#039;&#039;&#039; : The file system that we wish to update to be identical to the source file system.&lt;br /&gt;
; &#039;&#039;&#039;Parent Tracker&#039;&#039;&#039; : a subsystem responsible for recording the parent inode in disk file systems inodes, for pathname reconstruction. &lt;br /&gt;
; &#039;&#039;&#039;Changelog Generator&#039;&#039;&#039; : a subsystem used by the MDS and OSS systems to generate changelog entries transactionally when the file system changes.&lt;br /&gt;
; &#039;&#039;&#039;Changelog Notifier&#039;&#039;&#039; : subsystem responsible for notifying that a certain number of entries have been made, OR a certain amount of time has elapsed since changelog entries were made available, OR a large amount of changelog entries remains unprocessed.&lt;br /&gt;
; &#039;&#039;&#039;Changelog Consumer&#039;&#039;&#039; : subsystem reading changelog entries for further processing.&lt;br /&gt;
; &#039;&#039;&#039;File Data &amp;amp; Attribute Synchronizer&#039;&#039;&#039; : subsystem responsible for opening the correct source and target file and synchronizing the data/attributes in the file.&lt;br /&gt;
; &#039;&#039;&#039;Namespace Synchronizer&#039;&#039;&#039; : subsystem responsible for synchronizing the namespace.  This subsystem executes creation, deletion and rename operations.&lt;br /&gt;
; &#039;&#039;&#039;Layout Manager&#039;&#039;&#039; : changes MDS object layout information associated with the replicated file data.&lt;br /&gt;
; &#039;&#039;&#039;Namespace Operation&#039;&#039;&#039; : creation (open with create, mknod, symlink, mkdir, link), deletion (unlink, rmdir) or change (rename) of a name&lt;br /&gt;
; &#039;&#039;&#039;Replication Epoch&#039;&#039;&#039; : A sequence of namespace operations, a set of inodes with attribute and file data changes, bracketed by an initial and final time and record number.&lt;br /&gt;
; &#039;&#039;&#039;Active log&#039;&#039;&#039; : The changelog to which the filesystem is currently appending change records.&lt;br /&gt;
; &#039;&#039;&#039;Staged log&#039;&#039;&#039; : One of zero or more &#039;closed&#039; logs, no longer active. &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Components ==&lt;br /&gt;
[[Image:components.png|600px]]&lt;br /&gt;
&lt;br /&gt;
[[Image:deployments.png|600px]]&lt;br /&gt;
=== Parent Tracker ===&lt;br /&gt;
&lt;br /&gt;
==== Uses relationships ====&lt;br /&gt;
; Used for : current full path lookup given an inode or fid&lt;br /&gt;
; Requires : the disk file system extended attribute interfaces to record primary parent inode.  An indexed file to record pairs of inodes and secondary parents.&lt;br /&gt;
&lt;br /&gt;
==== Logic ====&lt;br /&gt;
&lt;br /&gt;
* When a new inode is created (creat, mknod, mkdir, open(O_CREAT), symlink, (link)), the parent directory inode number (inum) is automatically added as an EA. On Lustre, since OST inodes are precreated, we will modify the EA in filter_update_fidea.  This means that an EA update is now required for these operations, which may change the transaction size by one block.&lt;br /&gt;
&lt;br /&gt;
* Upon rename the parent inode is changed.&lt;br /&gt;
&lt;br /&gt;
* The initial implementation may ignore multiple parents (hardlinks); for replication purposes synchronizing any one of the hardlinks is sufficient.&lt;br /&gt;
&lt;br /&gt;
; modifications : obdfilter (filter_update_fidea), ldiskfs (ldiskfs_new_inode)&lt;br /&gt;
&lt;br /&gt;
=== Changelog Generator ===&lt;br /&gt;
&lt;br /&gt;
==== Uses relationships ====&lt;br /&gt;
; Used for : The disk file system on MDS or OSS to record changes in the file system.&lt;br /&gt;
; Requires : llog or another transactional efficient logging mechanism to record changes, the file system or VFS api&#039;s to create logs&lt;br /&gt;
&lt;br /&gt;
==== Exported Interfaces ====&lt;br /&gt;
# changelog accessor&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
===== Changelog Accessor =====&lt;br /&gt;
Changelogs are stored in a hidden directory at the filesystem root (/.changelog/).  They are (mode 440 user &amp;quot;audit) files generated automatically by the filesystem when a special mount option is supplied (-o changelog).  Only completed (&amp;quot;staged&amp;quot;) log files are visible in the directory. Files are named with their changelog file sequence number.  The current sequence number is stored on disk in a separate file (/.changelog/sequence).&lt;br /&gt;
&lt;br /&gt;
; modifications : ldiskfs; mdt/ost to allow serve special non-MDT-managed OST files to Lustre clients, mdt to serve special files directly to lustre clients without using OSTs&lt;br /&gt;
&lt;br /&gt;
==== Interactions ====&lt;br /&gt;
&lt;br /&gt;
[[Image:changelog.png|500px]]&lt;br /&gt;
&lt;br /&gt;
==== Features and Limitations ====&lt;br /&gt;
* Log records are placed into a special changelog file.&lt;br /&gt;
* The records contain fids of existing objects and names of new objects&lt;br /&gt;
* The records contain the parent fid&lt;br /&gt;
* Changelog records are recorded within the filesystem transaction&lt;br /&gt;
* Modified files are noted in the changelog log only once (not at every transaction)&lt;br /&gt;
* Every instance of a namespace change operation (rename, create, delete) is recorded in the log&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Theorem:&#039;&#039;&#039; Given a changelog with the properties described above a correct synchronization can be performed.&lt;br /&gt;
&#039;&#039;&#039;Proof:&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
==== Logic ====&lt;br /&gt;
# Global changelog_active_start_time is set to the active changelog&#039;s crtime at startup and every time a new active changelog is created.&lt;br /&gt;
# When an inode is first read from disk (or created), save the old mtime, so we can easily detect when it changes&lt;br /&gt;
# Every time an inode is dirtied, check old_mtime.  &lt;br /&gt;
## If old_mtime is after changelog_active_start_time, then inode has already been added to changelog; don&#039;t add it again.  &lt;br /&gt;
## If old_mtime is earlier, then add the change record to the active changelog&lt;br /&gt;
## Update old_mtime to current mtime. If mtime is not later than changelog_active_start_time, we can use ctime, dtime, or current time instead of mtime; it just needs to be a time after changelog_active_start_time.&lt;br /&gt;
# Record every namespace change operation in the log for path reconstruction of a live filesystem.  &#039;&#039;Record every instance&#039;&#039;, not just once per log.  To simplify the log format, move/rename operations may be broken up into two log records (the first with the old name/parent, the second with the new).&lt;br /&gt;
## Include full path information in these records&lt;br /&gt;
&lt;br /&gt;
; modifications : ldiskfs (ldiskfs_mark_inode_dirty, ldiskfs_new_inode, ldiskfs_link, ldiskfs_unlink, ldiskfs_rmdir, ldiskfs_rename, ldiskfs_ioctl, ldiskfs_truncate, ldiskfs_xattr_set, ldiskfs_setattr)&lt;br /&gt;
&lt;br /&gt;
=== Pathname Lookup ===&lt;br /&gt;
&lt;br /&gt;
==== Uses relationships ====&lt;br /&gt;
; Used for : Data Replicator&lt;br /&gt;
; Requires : Parent Tracker, Changelog Accessor, ability to temporarily lock filesystem against namespace changes&lt;br /&gt;
&lt;br /&gt;
==== Exported Interfaces ====&lt;br /&gt;
; source_path(ino, *sourcepath, *end_rec)&lt;br /&gt;
: ino : inode or fid from data changelog record&lt;br /&gt;
: sourcepath : current path on source, as of end_rec&lt;br /&gt;
: end_rec : latest namespace record number&lt;br /&gt;
* may return ENOENT: file has been deleted from source&lt;br /&gt;
&lt;br /&gt;
; target_path(sourcepath, end_rec, namespace_log, *targetpath)&lt;br /&gt;
: namespace_log : the name of the namespace log that we have last synced on the target&lt;br /&gt;
: targetpath : the path for this inode on the target system, as of the end of namespace_log&lt;br /&gt;
* may return ENOENT: file does not exist (yet) on target&lt;br /&gt;
&lt;br /&gt;
==== Features and Limitations ====&lt;br /&gt;
* Lives on MDT, exported interface to Lustre clients&lt;br /&gt;
&lt;br /&gt;
==== Logic ====&lt;br /&gt;
source_path&lt;br /&gt;
# lock filesystem against renames&lt;br /&gt;
# lookup current full path name on MDT from ino/fid&lt;br /&gt;
#* open inode.  Return ENOENT if doesn&#039;t exist&lt;br /&gt;
#* open parent ino&#039;s as stored in EA&lt;br /&gt;
#* likely that path elements will not be cached on the MDT during this lookup&lt;br /&gt;
# return full path in sourcepath&lt;br /&gt;
# return last record number in the active namespace changelog in end_rec&lt;br /&gt;
# unlock filesystem against renames&lt;br /&gt;
&lt;br /&gt;
target_path&lt;br /&gt;
# generate a list of parent path elements from sourcepath (names or inodes)&lt;br /&gt;
# search backward through the namespace logs (active and staged) from end_rec, replacing any renamed path elements with their old (previous) version, until either:&lt;br /&gt;
## we reach the first record after end of the given namespace_log&lt;br /&gt;
## a create record for this inode is encountered; return ENOENT&lt;br /&gt;
# return targetpath&lt;br /&gt;
&lt;br /&gt;
; Hardlinks&lt;br /&gt;
: source_path() will always return a single path.  The path need not be consistent.  target_path() will always return a single valid path on the target to one of the hardlinks (renames along this &amp;quot;chosen&amp;quot; path will be undone.)  Renames along any other hardlinked paths may be ignored: target_path is used to update &#039;&#039;file data and attributes&#039;&#039;, which are shared between all the hardlinked files on the target.  The renames of the other hardlinked paths themselves are synchronized by the Namespace Synchronizer.&lt;br /&gt;
&lt;br /&gt;
=== Changelog Notifier ===&lt;br /&gt;
&lt;br /&gt;
==== Uses relationships ====&lt;br /&gt;
; Used for : The disk file system, to notify the Changelog Consumer of available data&lt;br /&gt;
; Requires : Changelog Generator&lt;br /&gt;
&lt;br /&gt;
==== Exported Interfaces ====&lt;br /&gt;
&lt;br /&gt;
* notification of new or excessive changelog&lt;br /&gt;
** updates sequence file&lt;br /&gt;
&lt;br /&gt;
==== Features and Limitations ====&lt;br /&gt;
&lt;br /&gt;
* When an active changelog has reached a preset limit of size, record count, or active time, the notifier:&lt;br /&gt;
*# increases the sequence number (changelog identifier)&lt;br /&gt;
*# creates a new active changelog with the new identifier&lt;br /&gt;
*# marks the old changelog as staged (unhidden).  &lt;br /&gt;
* A Changelog Consumer could poll the sequence file for mtime changes, signalling a new staged file.&lt;br /&gt;
&lt;br /&gt;
==== Logic ====&lt;br /&gt;
Multiple logs are kept on each disk file system volume; zero or more non-active (&amp;quot;finished&amp;quot;) logs and exactly 1 active log.  Finished logs will be stored in a special directory (i.e. /.changelog).  Staged logs are named with a monotonically increasing sequence number. The sequence number of the latest staged log is stored on disk in a separate file (/.changelog/sequence).&lt;br /&gt;
&lt;br /&gt;
# Begin recording into the active log.  We append to this file until some trigger criteria is met (either time or log size).  The active log is not visible to filesystem users.&lt;br /&gt;
# When the trigger criteria is met&lt;br /&gt;
## stop writing into the active log&lt;br /&gt;
## create a new active log&lt;br /&gt;
## thenceforth record all subsequent changes into the new active log&lt;br /&gt;
## indicate that the old log is now staged by marking it as visible and updating the sequence file&lt;br /&gt;
# When a user process has finished processing the files referred to in the staged log (including synchronizing the files remotely), it signals its completion by deleting the staged log (which may act as part of a new trigger criteria.)  &lt;br /&gt;
# The cycle begins again from step 2.  &lt;br /&gt;
# If the number of staged logs exceeds some threshold, the Notifier records a warning in the syslog (D_WARNING)&lt;br /&gt;
&lt;br /&gt;
A user process is signaled that a new changelog is ready by polling the sequence file mtime.&lt;br /&gt;
&lt;br /&gt;
If the user process dies, upon restart it re-reads the staged log, perhaps repeating old actions (sync).  If the server dies, upon restart it continues recording into the active log.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
; modifications : ldiskfs&lt;br /&gt;
&lt;br /&gt;
=== Changelog Consumer ===&lt;br /&gt;
&lt;br /&gt;
[[Image:sync.png|500px]]&lt;br /&gt;
&lt;br /&gt;
==== Uses relationships ====&lt;br /&gt;
; Used for : Managing filesystem replication&lt;br /&gt;
; Requires : Namespace Synchronizer, File Data &amp;amp; Attribute Synchronizer, Changelog Notifier&lt;br /&gt;
&lt;br /&gt;
==== Exported Interfaces ====&lt;br /&gt;
; replicate(lustre_root_path, target_root_path, [implicit target sync file])&lt;br /&gt;
: lustre_root_path : path to root of Lustre source fs&lt;br /&gt;
: target_root_path : path to root of target (must be locally mounted!) &lt;br /&gt;
&lt;br /&gt;
The last namespace log record processed is stored in a sync file on the target. This file is read at the beginning of replicate() to determine the next start record.&lt;br /&gt;
&lt;br /&gt;
==== Features and Limitations ====&lt;br /&gt;
&lt;br /&gt;
The consumer uses the changelogs to coordinate filesystem replication using the Namespace Synchronizer and the File Data Synchronizer described below. &lt;br /&gt;
&lt;br /&gt;
* Multiple replica filesystems may exist at different sync points.&lt;br /&gt;
&lt;br /&gt;
==== Logic ==== &lt;br /&gt;
A synchronization cycle consists of synchronizing the namespace and file data for each changed file/dir.  Special care is needed because a file/dir may be renamed at any time during the synchronization cycle, changing the path name resolution.&lt;br /&gt;
&lt;br /&gt;
Synchronization for Lustre requires both OST and MDT logs, with path lookup on the MDT for any files changed on the OSTs.&lt;br /&gt;
&lt;br /&gt;
# Synchronize the namespace change operations from a staged log using the Namespace Synchronizer (MDT)&lt;br /&gt;
#* Now destination namespace mirrors source, but file contents/md may not match&lt;br /&gt;
# For all other ops (md and data) in the staged log(s on the MDT and all OSTs), call the Data/MD Synchronizer&lt;br /&gt;
# Data/MD synchronization should be carried out in parallel for each OST and the MDT.&lt;br /&gt;
#* Now destination filesystem namespace matches, but data/md may be newer than a theoretical snapshot of the source taken at Namespace Sync time.&lt;br /&gt;
&lt;br /&gt;
; modifications : new userspace utility&lt;br /&gt;
&lt;br /&gt;
=== File Data &amp;amp; Attribute Synchronizer ===&lt;br /&gt;
&lt;br /&gt;
==== Uses relationships ====&lt;br /&gt;
; Used for : Changelog Consumer - data replication&lt;br /&gt;
; Requires : Changelog Accessor, Path Lookup, VFS api to open file by ino/fid, remote filesystem access&lt;br /&gt;
&lt;br /&gt;
==== Features and Limitations ====&lt;br /&gt;
* Multiple data change logs exist and these can be synchronized in parallel.&lt;br /&gt;
* Individual changes are NOT recorded; only the fact that an inode is dirty.  The data and metadata of the file on the target filesystem will match the source &#039;&#039;&#039;at the time of the copy&#039;&#039;&#039;, not as of the namespace sync. In other words, the target is &#039;&#039;&#039;not&#039;&#039;&#039; an exact snapshot of the source filesystem at a single point.&lt;br /&gt;
* Open-by-fid requires root privileges&lt;br /&gt;
&lt;br /&gt;
==== Logic ====&lt;br /&gt;
; &#039;&#039;&#039;Find pathnames in the destination&#039;&#039;&#039; : Data records are recorded with inode/fids on the source.  To transform this into an operation that can be applied to the destination file system we find the target file name using:&lt;br /&gt;
# read data record&lt;br /&gt;
# source_path(ino, *sourcepath, *end_rec)&lt;br /&gt;
#* if ENOENT: file has been deleted from source; don&#039;t synchronize&lt;br /&gt;
# target_path(sourcepath, end_rec, namespace_change_log, *targetpath)&lt;br /&gt;
#* if ENOENT: file does not exist (yet) on target; don&#039;t synchronize&lt;br /&gt;
&lt;br /&gt;
; &#039;&#039;&#039;Synchronize file data and attributes&#039;&#039;&#039; : &lt;br /&gt;
# iopen(ino) on source for reading&lt;br /&gt;
#* requires root privileges on the source&lt;br /&gt;
# open(targetpath) on target for writing&lt;br /&gt;
# copy file data and attributes from source to target&lt;br /&gt;
#* may require temporary access permission changes on the target&lt;br /&gt;
#* ownership changes may require root privileges on the target&lt;br /&gt;
#* data copy may be predicated on mtime change, checksum, etc.  May use rsync as a primitive here.&lt;br /&gt;
#* data changes should be made before attribute changes (mtime), in case of power failure&lt;br /&gt;
&lt;br /&gt;
; &#039;&#039;&#039;Parallel file processing&#039;&#039;&#039;&lt;br /&gt;
: if multiple OSTs (and/or the MDT) all note that a file needs to be synced, they may race.  Normal locking should insure no inconsistent results, but copying the same file multiple times should be avoided for efficiency.  Simple rules like &amp;quot;don&#039;t copy if target mtime is later than source mtime&amp;quot; will help, but the open(target)&#039;s may still race after such checks.  Possible solutions include using a lockfile on the target (difficult to determine if lockfile is still valid after a crash bec. possible distributed lockers), or interprocess communications on the sources, or perhaps a special &amp;quot;sync_in_progress&amp;quot; bit on the MDT inode set in the open-by-fid path.  FIXME nonfatal, performance&lt;br /&gt;
&lt;br /&gt;
; modifications : new userspace component (data syncer), ldiskfs/mdt (ioctl open by inode)&lt;br /&gt;
&lt;br /&gt;
=== Namespace Synchronizer ===&lt;br /&gt;
&lt;br /&gt;
==== Uses relationships ====&lt;br /&gt;
; Used for : Changelog Consumer - namespace replicator&lt;br /&gt;
; Requires : Changelog Accessor, remote filesystem access&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==== Logic ====&lt;br /&gt;
&lt;br /&gt;
; &#039;&#039;&#039;Path lookup at namespace change time&#039;&#039;&#039; :  Records are recorded with inode/fids and full path (up to the filesystem root) on the source at the time of the change.  At this point the path is likely to be cached so this should be cheap.  The old (mvFrom) and the new (mvTo) paths are recorded&lt;br /&gt;
&lt;br /&gt;
; &#039;&#039;&#039;Implementing a record&#039;&#039;&#039; : The metadata synchronizer processes all namespace change records in the changelog such that target filesystem namespace matches the source namespace as of the close of this changelog, including the mtime of the affected directories.&lt;br /&gt;
&lt;br /&gt;
; &#039;&#039;&#039;Finding the first valid record to implement&#039;&#039;&#039; : The synchronizer performs an ordered write on the target filesystem.  This records the record number (transno) of the namespace record that it is currently working on in a special file on the target, as well as a full copy of the transaction record, before it makes the namespace changes to the target.  This leads to a re-do operation that is understandable:&lt;br /&gt;
;* a deletion is repeated if the name is still there. The mtime is updated if the name is not there and the mtime does not match the post-mtime in the record.&lt;br /&gt;
;* a creation is repeated if the name is not yet there.&lt;br /&gt;
;* a rename is repeated if the names or parent mtimes are not what they should be.&lt;br /&gt;
;* the full transaction record on the replica is used for recovery in case of master-to-replica failover.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
; modifications : new userspace utility&lt;br /&gt;
&lt;br /&gt;
== Solution Limitations ==&lt;br /&gt;
&lt;br /&gt;
Notable limitations to the proposed solution:&lt;br /&gt;
&lt;br /&gt;
A. A replicated file system is not a snapshot taken at a single point in time on a live filesystem.  It is a namespace snapshot, combined with data and metadata contents that may be &#039;&#039;&#039;later than&#039;&#039;&#039; the snapshot time.  In the case of deleted files, we may miss some data/md updates.&lt;br /&gt;
&lt;br /&gt;
B. Data and attribute synchronization may require temporary access permission changes on the target.&lt;br /&gt;
&lt;br /&gt;
C. Open-by-inode may require root permission on source&lt;br /&gt;
&lt;br /&gt;
D. A new record is not created for every data/md change; at most one per file per epoch is recorded.  (However, every namespace change is recorded).  This may have implications for potential audit, undo future features.&lt;br /&gt;
&lt;br /&gt;
== States and Transitions ==&lt;br /&gt;
&lt;br /&gt;
=== Source File System ===&lt;br /&gt;
&lt;br /&gt;
* A directory for changelog files (per MDT/OST)&lt;br /&gt;
* Staged and active changelogs&lt;br /&gt;
** header: start record, start mtime&lt;br /&gt;
** records: transno, ino, parent ino, mtime (see Changelog Format above) &lt;br /&gt;
** footer: final record, final mtime, (future) ZFS snapshot name associated with the final state&lt;br /&gt;
* Sequence file&lt;br /&gt;
** active changelog filename&lt;br /&gt;
&lt;br /&gt;
==== Changelog Format ====&lt;br /&gt;
Changelogs are packed binary data files.  The first record is a header; subsequent records use the following structure:&lt;br /&gt;
* magic (_u32)&lt;br /&gt;
* flags (_u32)&lt;br /&gt;
* record_num (__u64) (transno)&lt;br /&gt;
* record_type(_u16) &lt;br /&gt;
* ino(long) &lt;br /&gt;
* parent_ino(long)&lt;br /&gt;
* namespace changes only:&lt;br /&gt;
** old mtime (struct timespec)&lt;br /&gt;
**: note: post-op mtime is in the next namespace change rec, or current mtime&lt;br /&gt;
** strlen(_u16) &lt;br /&gt;
** pathname(string)&lt;br /&gt;
**: note: for renames, &amp;quot;from&amp;quot; is in the mvFrom rec, &amp;quot;to&amp;quot; is in the mvTo rec&lt;br /&gt;
&lt;br /&gt;
; record_types : Create, Link, Unlink, Rmdir, mvFrom, mvTo, Ioctl, Trunc, Xattr, Setattr, *unknown&lt;br /&gt;
&lt;br /&gt;
The header record:&lt;br /&gt;
* magic (_u32)&lt;br /&gt;
* flags (_u32)&lt;br /&gt;
* start_record_num (__u64)&lt;br /&gt;
* changelog_file_seqno(long)&lt;br /&gt;
* log start time (struct timespec)&lt;br /&gt;
* strlen(_u16)&lt;br /&gt;
* note(string)&lt;br /&gt;
&lt;br /&gt;
Tail record:&lt;br /&gt;
* magic (_u32)&lt;br /&gt;
* flags (_u32)&lt;br /&gt;
* end_record_num (__u64)&lt;br /&gt;
* next_changelog_seqno(long)&lt;br /&gt;
* log end time (struct timespec)&lt;br /&gt;
* strlen(_u16)&lt;br /&gt;
* snapshot name(string) (future)&lt;br /&gt;
&lt;br /&gt;
=== Target file system ===&lt;br /&gt;
&lt;br /&gt;
* Last attempted namespace record (entire record)&lt;br /&gt;
* Last attempted data / metadata records for each replicator&lt;br /&gt;
*: optional, allows for faster recovery&lt;br /&gt;
** OST index&lt;br /&gt;
** replication start &lt;br /&gt;
** replication last completed&lt;br /&gt;
&lt;br /&gt;
=== State Changes in the Source File System ===&lt;br /&gt;
* Some file system transactions result in changelog records recorded in the active changelog&lt;br /&gt;
** file data or metadata modifications in files that have not already been added to the active changelog&lt;br /&gt;
** any namespace change operations&lt;br /&gt;
* Active changelogs are occasionally staged. Multiple staged logs may exist.&lt;br /&gt;
* The sequence file is updated to reflect the latest staged log. &lt;br /&gt;
* &amp;quot;Completed&amp;quot; changelogs may be deleted at will (after synchronization)&lt;br /&gt;
&lt;br /&gt;
[[image:source_state.png]]&lt;br /&gt;
&lt;br /&gt;
=== State Changes in the Target File System ===&lt;br /&gt;
&lt;br /&gt;
* Each time a namespace operation is attempted the last attempted record is recorded.  This may also be done for attribute and file synchronization operations, for efficient restarts (note that this would require a separate file per replication &#039;chunk&#039;).&lt;br /&gt;
&lt;br /&gt;
* Namespace operations are recorded on the target filesystem using user-level filesystem commands (mv, rm, mknod, touch) or the posix file API (open, creat, unlink, ioctl) to adjust file, directory, and parent directory names and metadata.&lt;br /&gt;
&lt;br /&gt;
* Data / metadata operations are recorded on the target filesystem using user-level filesystem commands (cp, rsync, touch) or the posix file API (read, write, ioctl) to synchronize file content and metadata&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Related Applications ==&lt;br /&gt;
&lt;br /&gt;
The mechanisms to use a list containing fids of modified files for synchronization  hinges on opening files by fid or correctly computing the pathname on a previously synced replica.  This mechanism has applications elsewhere in Lustre which we discuss here.&lt;br /&gt;
&lt;br /&gt;
=== Flash Cache Sync demo ===&lt;br /&gt;
&lt;br /&gt;
[[Image:flash-cache-sync-demo.png|700px]]&lt;br /&gt;
&lt;br /&gt;
=== Fast Incremental Backup ===&lt;br /&gt;
&lt;br /&gt;
[[Image:incremental-backup.png|700px]]&lt;br /&gt;
&lt;br /&gt;
=== Space Balancing Migration ===&lt;br /&gt;
&lt;br /&gt;
[[Image:space-balancing-migration.png|700px]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Hadoop File System style Server Network Stripes ===&lt;br /&gt;
&lt;br /&gt;
[[Image:Hdfs-sns.png|700px]]&lt;br /&gt;
&lt;br /&gt;
== Alternatives ==&lt;br /&gt;
=== mtime on MDT ===&lt;br /&gt;
A always-current mtime on the MDT allows us to record changed files on the MDT only (no OST logging).  Bug 11063 has an update-mtime-on-close patch, but this is unsafe in case of client crash. We could use full SOM-style recovery to guarantee mtime (backport from HEAD), but this may be very complicated given MDT changes.  Arguably the changelog we are creating on the OSS nodes is similar to the recovery mechanisms used by SOM.&lt;br /&gt;
&lt;br /&gt;
NOTE: on HEAD (with SOM), we need only record file (metadata) changes on the MDT, since every OST change will result in an updated mtime on the MDT inode.  This eliminates the logging requirement for replication on the OSTs, removing possible racing OST syncs.  The synchronizer on the MDT would be responsible for distributing chunks of the data synchronization to multiple clients and insuring their completion.&lt;br /&gt;
&lt;br /&gt;
=== ZFS snapshots ===&lt;br /&gt;
By taking a snapshot on the MDT at the end of each epoch, the target pathname reconstruction step can be avoided.  &amp;quot;Current&amp;quot; pathname of the inode is looked up on the snapshot; this gives the target pathname directly.&lt;br /&gt;
&lt;br /&gt;
Potentially, if cluster-wide synchronized snapshots were available, then true snapshot backups could be made.&lt;br /&gt;
&lt;br /&gt;
== References ==&lt;br /&gt;
&lt;br /&gt;
[https://bugzilla.lustre.org/show_bug.cgi?id=14169 bug 14169]&lt;br /&gt;
[[Category:Feature|FS Replication]]&lt;br /&gt;
[[Category:Team_Rabbit]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== to be removed: HLD reqs ==&lt;br /&gt;
Entry Criteria&lt;br /&gt;
&lt;br /&gt;
You need to have on hand&lt;br /&gt;
    1. Architecture document&lt;br /&gt;
    2. Quality Attribute Scenarios &amp;amp; Use cases&lt;br /&gt;
    3. LOGT, LOGD&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
1. External Functional specifications&lt;br /&gt;
      Following the architecture, define prototypes for all externally&lt;br /&gt;
      visible interfaces (library functions, methods etc) of all&lt;br /&gt;
      modules changed by the program.  Be sufficiently detailed in the&lt;br /&gt;
      specification to cover:&lt;br /&gt;
      a. Layering of API&#039;s&lt;br /&gt;
      b. How memory for variables / parameters is allocated&lt;br /&gt;
      c. In what context the functions run&lt;br /&gt;
    &lt;br /&gt;
&lt;br /&gt;
2. High level logic&lt;br /&gt;
      Use high level pseudocode to indicate how all elements of the&lt;br /&gt;
      program will be implemented.&lt;br /&gt;
&lt;br /&gt;
3. Use case scenarios&lt;br /&gt;
    a. Write use cases for all normal and abnormal uses of externally&lt;br /&gt;
        visible functions.&lt;br /&gt;
    b. Write use cases demonstrating interoperability between the&lt;br /&gt;
        software with and without this module&lt;br /&gt;
    c. Write use cases demonstrating the scalability use cases&lt;br /&gt;
       mentioned in the architecture.&lt;br /&gt;
    d. Include use case scenarios for all locking situations and &lt;br /&gt;
       describe how likely they are.&lt;br /&gt;
&lt;br /&gt;
4. State machine design&lt;br /&gt;
    With great care describe state machines included, used or affected&lt;br /&gt;
    by the module.   Describe the transitions between states.   Be&lt;br /&gt;
    alert to the fact that any function called by the module can&lt;br /&gt;
    change a state machine in the environment and this may interact&lt;br /&gt;
    with state machines in your model.&lt;br /&gt;
&lt;br /&gt;
    Pay particular attention to:&lt;br /&gt;
    a. locking (ordering, lock/unlock)&lt;br /&gt;
    b. cache usage&lt;br /&gt;
    c. recovery (connect, disconnect, export/import/request state&lt;br /&gt;
       machines)&lt;br /&gt;
    d. disk state changes&lt;br /&gt;
&lt;br /&gt;
5. High Level Logic Design&lt;br /&gt;
    a What synchronization primitives (lock types etc) need to be chosen &lt;br /&gt;
         to handle locking use cases most efficiently.&lt;br /&gt;
&lt;br /&gt;
6. Test plan&lt;br /&gt;
   Give a high level design of all tests and describe test cases to&lt;br /&gt;
   cover/verify all critical use cases and quality attribute scenarios&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
7. Plan review&lt;br /&gt;
   Review the estimates in the TSP cycle plan based on the information&lt;br /&gt;
   obtained during the work on the HLD.  Bring wrong estimates to the&lt;br /&gt;
   attention of the planning manager in the weekly meeting.&lt;br /&gt;
&lt;br /&gt;
8. EXIT CRITERIA&lt;br /&gt;
   A well formed design with prototypes, state machines, use cases,&lt;br /&gt;
   logic.&lt;/div&gt;</summary>
		<author><name>Nathan</name></author>
	</entry>
	<entry>
		<id>http://wiki.old.lustre.org/index.php?title=Architecture_-_Changelogs_1.6&amp;diff=9797</id>
		<title>Architecture - Changelogs 1.6</title>
		<link rel="alternate" type="text/html" href="http://wiki.old.lustre.org/index.php?title=Architecture_-_Changelogs_1.6&amp;diff=9797"/>
		<updated>2008-03-12T19:11:33Z</updated>

		<summary type="html">&lt;p&gt;Nathan: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;= Replication Changelogs for Lustre 1.6 =&lt;br /&gt;
&lt;br /&gt;
Intended as a short-term feature to facilitate efficient replication of large Lustre 1.6 filesystems.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Requirements ==&lt;br /&gt;
1. Generate a list of modified files for syncronization via an external tool&lt;br /&gt;
2. List must by complete, but may be conservative.  &lt;br /&gt;
3. List must be persistent, and may be repeated on failover.&lt;br /&gt;
4. After original filesystem quiesces, replica must become an exact mirror&lt;br /&gt;
&lt;br /&gt;
== List generation ==&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== References ==&lt;br /&gt;
&lt;br /&gt;
[https://bugzilla.lustre.org/show_bug.cgi?id=14169 bug 14169]&lt;br /&gt;
[[Category:Architecture|Changelogs]]&lt;br /&gt;
[[Category:Architecture|Replication]]&lt;br /&gt;
[[Category:QAS|Changelogs]]&lt;br /&gt;
[[Category:Team_Rabbit]]&lt;/div&gt;</summary>
		<author><name>Nathan</name></author>
	</entry>
	<entry>
		<id>http://wiki.old.lustre.org/index.php?title=Architecture_-_Fileset&amp;diff=9771</id>
		<title>Architecture - Fileset</title>
		<link rel="alternate" type="text/html" href="http://wiki.old.lustre.org/index.php?title=Architecture_-_Fileset&amp;diff=9771"/>
		<updated>2007-12-14T18:56:03Z</updated>

		<summary type="html">&lt;p&gt;Nathan: add multiple filesets&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Summary ==&lt;br /&gt;
&lt;br /&gt;
A user application (or Lustre internal features) may want to perform an action on a very large set of files.  Such actions might include migration to slower storage, purging of old files, or replication to a proxy server.  A &#039;&#039;&#039;fileset&#039;&#039;&#039; is an efficient representation of these file identifiers (fids).&lt;br /&gt;
&lt;br /&gt;
The definition of any particular fileset is left to an external agent; no search features will be included in Lustre itself (excluding Least Recently Used files, which is probably only efficiently tracked within Lustre).  Typically searches for files with particular metadata characteristics will be done a database that mirrors the Lustre file tree via a [http://arch.lustre.org/index.php?title=Server_Changelogs ChangeLog].  The files matching these criteria will be added to a fileset via a Lustre fileset API.&lt;br /&gt;
&lt;br /&gt;
Filesets will generally come in two flavors: arbitrary collections of files, or a full file tree.  See Enumeration below.&lt;br /&gt;
&lt;br /&gt;
== Definitions ==&lt;br /&gt;
&lt;br /&gt;
; &#039;&#039;&#039;Fileset&#039;&#039;&#039; : an arbitrary subset of files from within a single filesystem&#039;s namespace.&lt;br /&gt;
; &#039;&#039;&#039;Consumer&#039;&#039;&#039; : an entity acting on the contents of a fileset&lt;br /&gt;
; &#039;&#039;&#039;Internal consumer&#039;&#039;&#039; : a Lustre internal feature using a fileset (e.g. fileset client mount, maybe replicator, migrator)&lt;br /&gt;
; &#039;&#039;&#039;External consumer&#039;&#039;&#039; : an entity external to Lustre using a fileset.  This may be limited to a user of a fileset client mount, and no access to any other representation of a fileset is needed. see Client Access below.&lt;br /&gt;
; &#039;&#039;&#039;type&#039;&#039;&#039; : fileset type, see Enumeration below&lt;br /&gt;
&lt;br /&gt;
== Qualities ==&lt;br /&gt;
&lt;br /&gt;
{|cellspacing=&amp;quot;0&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
!Description&lt;br /&gt;
!Quality&lt;br /&gt;
!Semantics&lt;br /&gt;
|-&lt;br /&gt;
|coherence||usability||file modifications are reflected in the fileset (e.g. unlink, rename)&lt;br /&gt;
|-&lt;br /&gt;
|permanence||usability, scalability||when filesets are discarded.&lt;br /&gt;
|-&lt;br /&gt;
|synchronization||usability||the list of files in the set may change.&lt;br /&gt;
|-&lt;br /&gt;
|physiology||scalability||internal representation must be used efficiently&lt;br /&gt;
|-&lt;br /&gt;
|hashing||scalability||actions on a fileset may need to be distributed across multiple servers for scalability&lt;br /&gt;
|-&lt;br /&gt;
|modification||usability||the contents of a fileset may be modified over time to add or remove items&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== Use Cases ==&lt;br /&gt;
&lt;br /&gt;
{| border=1 cellspacing=0&lt;br /&gt;
|-&lt;br /&gt;
!id !! quality attribute !! summary&lt;br /&gt;
|-&lt;br /&gt;
|compliance || usability, scalability || delete all files modified in 2002&lt;br /&gt;
|-&lt;br /&gt;
|workset || availability || the files in the fileset are available on a remote proxy server &lt;br /&gt;
|-&lt;br /&gt;
|backup || scalability || filesystem must be subdivided into manageable chunks for backup / replication&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
;compliance&lt;br /&gt;
{|border=1  cellspacing=&amp;quot;0&amp;quot;&lt;br /&gt;
|-align=&amp;quot;left&amp;quot; &lt;br /&gt;
|colspan=2|&#039;&#039;&#039;Scenario:&#039;&#039;&#039; || delete all files modified in 2002&lt;br /&gt;
|-align=&amp;quot;left&amp;quot; &lt;br /&gt;
|colspan=2|&#039;&#039;&#039;Business Goals:&#039;&#039;&#039; || Provide an API to facilitate filesystem operations based on database search output&lt;br /&gt;
|-align=&amp;quot;left&amp;quot; &lt;br /&gt;
|colspan=2|&#039;&#039;&#039;Relevant QA&#039;s:&#039;&#039;&#039;|| Usability, scalability&lt;br /&gt;
|-align=&amp;quot;left&amp;quot;&lt;br /&gt;
|rowspan=&amp;quot;6&amp;quot; writing-mode=&amp;quot;vertical&amp;quot;|&#039;&#039;&#039;details&#039;&#039;&#039;&lt;br /&gt;
| &#039;&#039;&#039;Stimulus:&#039;&#039;&#039;|| The fileset and requested operation are fed to the API&lt;br /&gt;
|-align=&amp;quot;left&amp;quot;&lt;br /&gt;
|&#039;&#039;&#039;Stimulus source:&#039;&#039;&#039;|| Compliance policy dictates removal of old files&lt;br /&gt;
|-align=&amp;quot;left&amp;quot;&lt;br /&gt;
|&#039;&#039;&#039;Environment:&#039;&#039;&#039;|| Database has recent FS information (from watching a [http://arch.lustre.org/index.php?title=Server_Changelogs ChangeLog])&lt;br /&gt;
|-align=&amp;quot;left&amp;quot;&lt;br /&gt;
|&#039;&#039;&#039;Artifact:&#039;&#039;&#039;|| Fileset, type 1&lt;br /&gt;
|-align=&amp;quot;left&amp;quot;&lt;br /&gt;
|&#039;&#039;&#039;Response:&#039;&#039;&#039;|| Lustre performs the requested operation on each of the files in the fileset&lt;br /&gt;
|-align=&amp;quot;left&amp;quot;&lt;br /&gt;
|&#039;&#039;&#039;Response measure:&#039;&#039;&#039;|| fileset is created, operation is completed on all elements of the fileset&lt;br /&gt;
|-align=&amp;quot;left&amp;quot;&lt;br /&gt;
|colspan=2|&#039;&#039;&#039;Questions:&#039;&#039;&#039;|| Are all operations executed from userspace on a client (external), or some directly on Lustre via an API?&lt;br /&gt;
|-align=&amp;quot;left&amp;quot;&lt;br /&gt;
|colspan=2|&#039;&#039;&#039;Issues:&#039;&#039;&#039;|| &lt;br /&gt;
|-&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
;workset&lt;br /&gt;
{|border=1  cellspacing=&amp;quot;0&amp;quot;&lt;br /&gt;
|-align=&amp;quot;left&amp;quot; &lt;br /&gt;
|colspan=2|&#039;&#039;&#039;Scenario:&#039;&#039;&#039; || all files with the words &amp;quot;bunny rabbit&amp;quot; are replicated at a dozen remote analysis clusters&lt;br /&gt;
|-align=&amp;quot;left&amp;quot; &lt;br /&gt;
|colspan=2|&#039;&#039;&#039;Business Goals:&#039;&#039;&#039; || Provide current access to dynamic set of files on a proxy server&lt;br /&gt;
|-align=&amp;quot;left&amp;quot; &lt;br /&gt;
|colspan=2|&#039;&#039;&#039;Relevant QA&#039;s:&#039;&#039;&#039;|| Availability&lt;br /&gt;
|-align=&amp;quot;left&amp;quot;&lt;br /&gt;
|rowspan=&amp;quot;6&amp;quot; writing-mode=&amp;quot;vertical&amp;quot;|&#039;&#039;&#039;details&#039;&#039;&#039;&lt;br /&gt;
| &#039;&#039;&#039;Stimulus:&#039;&#039;&#039;|| Search results are fed to the API&lt;br /&gt;
|-align=&amp;quot;left&amp;quot;&lt;br /&gt;
|&#039;&#039;&#039;Stimulus source:&#039;&#039;&#039;|| External search or project directory&lt;br /&gt;
|-align=&amp;quot;left&amp;quot;&lt;br /&gt;
|&#039;&#039;&#039;Environment:&#039;&#039;&#039;|| Database has recent FS information (e.g. from watching a ChangeLog)&lt;br /&gt;
|-align=&amp;quot;left&amp;quot;&lt;br /&gt;
|&#039;&#039;&#039;Artifact:&#039;&#039;&#039;|| Fileset, type 1 or type 2&lt;br /&gt;
|-align=&amp;quot;left&amp;quot;&lt;br /&gt;
|&#039;&#039;&#039;Response:&#039;&#039;&#039;|| Lustre creates an internal representation of the fileset and makes it available for export.&lt;br /&gt;
|-align=&amp;quot;left&amp;quot;&lt;br /&gt;
|&#039;&#039;&#039;Response measure:&#039;&#039;&#039;|| Fileset is created&lt;br /&gt;
|-align=&amp;quot;left&amp;quot;&lt;br /&gt;
|colspan=2|&#039;&#039;&#039;Questions:&#039;&#039;&#039;|| Is a small time lag acceptable, or must proxies / filesets be absolutely synchronous&lt;br /&gt;
|-align=&amp;quot;left&amp;quot;&lt;br /&gt;
|colspan=2|&#039;&#039;&#039;Issues:&#039;&#039;&#039;|| &lt;br /&gt;
|-&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
;backup&lt;br /&gt;
{|border=1  cellspacing=&amp;quot;0&amp;quot;&lt;br /&gt;
|-align=&amp;quot;left&amp;quot; &lt;br /&gt;
|colspan=2|&#039;&#039;&#039;Scenario:&#039;&#039;&#039; ||filesystem must be subdivided into manageable chunks for backup / replication&lt;br /&gt;
|-align=&amp;quot;left&amp;quot; &lt;br /&gt;
|colspan=2|&#039;&#039;&#039;Business Goals:&#039;&#039;&#039; || User requires particular backup policies on particular sets of files&lt;br /&gt;
|-align=&amp;quot;left&amp;quot; &lt;br /&gt;
|colspan=2|&#039;&#039;&#039;Relevant QA&#039;s:&#039;&#039;&#039;|| Feature, Scalability&lt;br /&gt;
|-align=&amp;quot;left&amp;quot;&lt;br /&gt;
|rowspan=&amp;quot;6&amp;quot; writing-mode=&amp;quot;vertical&amp;quot;|&#039;&#039;&#039;details&#039;&#039;&#039;&lt;br /&gt;
| &#039;&#039;&#039;Stimulus:&#039;&#039;&#039;|| External app reads all files in a fileset&lt;br /&gt;
|-align=&amp;quot;left&amp;quot;&lt;br /&gt;
|&#039;&#039;&#039;Stimulus source:&#039;&#039;&#039;|| External HSM or backup application&lt;br /&gt;
|-align=&amp;quot;left&amp;quot;&lt;br /&gt;
|&#039;&#039;&#039;Environment:&#039;&#039;&#039;|| Client access to a limited, defined list of files&lt;br /&gt;
|-align=&amp;quot;left&amp;quot;&lt;br /&gt;
|&#039;&#039;&#039;Artifact:&#039;&#039;&#039;|| Fileset, type 2&lt;br /&gt;
|-align=&amp;quot;left&amp;quot;&lt;br /&gt;
|&#039;&#039;&#039;Response:&#039;&#039;&#039;|| All files in fileset are backed up&lt;br /&gt;
|-align=&amp;quot;left&amp;quot;&lt;br /&gt;
|&#039;&#039;&#039;Response measure:&#039;&#039;&#039;|| Backup time, minor filesystem load during backup&lt;br /&gt;
|-align=&amp;quot;left&amp;quot;&lt;br /&gt;
|colspan=2|&#039;&#039;&#039;Questions:&#039;&#039;&#039;||Subdivision of migration work seems like it should be handled by migration architecture; doesn&#039;t seem to really have anything to do with filesets&lt;br /&gt;
|-align=&amp;quot;left&amp;quot;&lt;br /&gt;
|colspan=2|&#039;&#039;&#039;Issues:&#039;&#039;&#039;|| &lt;br /&gt;
|-&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== Requirements ==&lt;br /&gt;
=== Dynamic ===&lt;br /&gt;
Search results may be returned slowly, or new files that meet the search criteria may be added to the filesystem.  In those cases, it should be possible to add (or remove) items to an existing fileset.  The fileset should in turn notify consumers of the fileset.  &lt;br /&gt;
Alternately, some filesets may be defined to be static.&lt;br /&gt;
&lt;br /&gt;
=== Persistence ===&lt;br /&gt;
The workset case implies a fileset must be persistent across server / client reboots.&lt;br /&gt;
&lt;br /&gt;
=== Specification ===&lt;br /&gt;
It may be desirable for a remote site to specify a fileset that should be locally proxied (i.e. pull instead of push).  A fileset &#039;&#039;name&#039;&#039; is probably useful for this.  (e.g. a client requests mirror fileset &#039;bunnyrabbit&#039; on local proxy servers)&lt;br /&gt;
&lt;br /&gt;
=== Coherence ===&lt;br /&gt;
Files referenced in the fileset must be coherent with the original file.  E.g. if a file referenced by a fileset is moved, the fileset should reflect the new file location.  If a file in a fileset is deleted, the file should disappear from the fileset.  Maybe this can be achieved by having the fileset take appropriate &#039;&#039;&#039;locks&#039;&#039;&#039; on the original files.&lt;br /&gt;
&lt;br /&gt;
Coherence requirements:&lt;br /&gt;
  - unlink&lt;br /&gt;
  - rename&lt;br /&gt;
  - move to a new directory&lt;br /&gt;
  - file metadata (access time, perms, owner, etc.)&lt;br /&gt;
&lt;br /&gt;
Note that if changing the above would cause a file to no longer meet the original search criteria that generated that fileset, it is up to the search generator to (eventually) remove it from the fileset.  There are two exception to this rule, where the file should be removed from the fileset automatically: &lt;br /&gt;
;1. unlink&lt;br /&gt;
;2. move of a file included by virtue of its location in a file tree to a location outside of that tree (see Enumeration below)&lt;br /&gt;
&lt;br /&gt;
=== Fileset as Object === &lt;br /&gt;
Depending on the intended use, some filesets may be represented more efficiently than others, or may require different descriptors or methods.  Implementing filesets as objects with variable attributes and methods may provide broad but efficient coverage of the range of uses.  For example, one common type of fileset may be &amp;quot;a user&#039;s home directory&amp;quot;, which could be efficiently represented as a single directory fid.&lt;br /&gt;
&lt;br /&gt;
=== Hashing ===&lt;br /&gt;
When performing an action on large filesets or large numbers of filesets, we must be able to distribute load across multiple servers to insure performant operation.  This is true for internal consumers, but perhaps this function should be offloaded to a distributed application for external consumers.&lt;br /&gt;
&lt;br /&gt;
For example, 10,000 filesets are to be replicated independently.  A changelog per fileset may not scale well, and instead we may need a scalable algorithm to find the results for each fileset from a global changelog.&lt;br /&gt;
&lt;br /&gt;
=== ChangeLog ===&lt;br /&gt;
It may be useful to have a per-fileset [http://arch.lustre.org/index.php?title=Server_Changelogs changelog] maintained for audit or replication purposes.  A fileset-specific changelog could be used to provide migration/replication-related events specific to the fileset to migration agents.  The agents would then use this information e.g. to abort / commence copying a file.&lt;br /&gt;
&lt;br /&gt;
However, maintaining a per-fileset changelog may not scale.  At some point, it make make more sense to process a common global changelog.&lt;br /&gt;
&lt;br /&gt;
=== Multiple Membership ===&lt;br /&gt;
A file may be part of multiple filesets.  A type 2 fileset may implicitly include other type 2 filesets.  Operations on a file should affect all filesets it belongs to, and vice-versa. &lt;br /&gt;
&lt;br /&gt;
=== Fileset API ===&lt;br /&gt;
The user API for filesets should include the following functionality:&lt;br /&gt;
   - Start a new fileset &lt;br /&gt;
   - Add items to a fileset&lt;br /&gt;
   - Remove items from a fileset&lt;br /&gt;
   - Delete a fileset&lt;br /&gt;
   - Initiate activity of an internal consumer (e.g. migrate fileset bunny from poolA to poolB)&lt;br /&gt;
   - Provide client access to a fileset (see Client Access below)&lt;br /&gt;
&lt;br /&gt;
== Implementation Notes ==&lt;br /&gt;
&lt;br /&gt;
=== Enumeration ===&lt;br /&gt;
Fileset enumeration should be handled in two ways:&lt;br /&gt;
;Type 1. An explicit enumeration of files or directories.  Files within directories are &#039;&#039;not&#039;&#039; included in the fileset unless explicitly listed as well.&lt;br /&gt;
;Type 2. Inclusive file trees.  &#039;&#039;All&#039;&#039; files / subdirectories below enumerated directories are included in the fileset.&lt;br /&gt;
&lt;br /&gt;
We should have provision for using both types of filesets.  In fact, with some per-entry flags, we can define &amp;quot;mixed&amp;quot; filesets including both of the above (each entry in a fileset may be type 1 (flat=single file) or type 2 (tree).  Perhaps a 3rd type; &amp;quot;not_included&amp;quot; would be a useful definition as well, to specifically exclude a particular subdirectory from a type 2 fileset.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Storage ===&lt;br /&gt;
Permanent fileset definitions would probably be stored on the MDT (as opposed to the MGS) for scalability and namespace-related locking.   &lt;br /&gt;
&lt;br /&gt;
=== UI ===&lt;br /&gt;
==== Maintenance ====&lt;br /&gt;
The UI for maintaining filesets might reasonably be run through lfs similar to &lt;br /&gt;
[http://arch.lustre.org/index.php?title=Pools_of_targets pools]:&lt;br /&gt;
# lfs fileset_new &amp;lt;fileset name&amp;gt;  Define a new fileset&lt;br /&gt;
# lfs fileset_add &amp;lt;fileset name&amp;gt; &amp;lt;options&amp;gt; &amp;lt;filename1&amp;gt; &amp;lt;filename2&amp;gt; ...  Add the named files to the fileset; define type 1 or type 2&lt;br /&gt;
# lfs fileset_remove &amp;lt;fileset name&amp;gt; &amp;lt;filename&amp;gt;  Remove the named file from the fileset&lt;br /&gt;
# lfs fileset_destroy &amp;lt;fileset name&amp;gt; Remove the definition of the fileset&lt;br /&gt;
&lt;br /&gt;
==== Client Access ====&lt;br /&gt;
For arbitrary user access to the files in a fileset, a mechanism like &#039;&#039;&#039;mount(8)&#039;&#039;&#039; seems like it would provide a clear, simple way to retrieve a fileset.  (Command format might be &amp;quot;mount -t lustre mgs://fsname/fileset mntpt&amp;quot;)&lt;br /&gt;
&lt;br /&gt;
For type 1 filesets, a hierarchical namespace defined by the files and directories in the fileset would be constructed locally.   Directories would all be &#039;&#039;read/execute-only&#039;&#039;; a client cannot add new entries into the fileset by creating files in the fileset hierarchy.  Regular files would keep their normal access permissions.&lt;br /&gt;
&lt;br /&gt;
For type 2 filesets, the mount point would act exactly like a subtree of the full lustre fs.&lt;br /&gt;
&lt;br /&gt;
== References ==&lt;br /&gt;
; [https://bugzilla.lustre.org/show_bug.cgi?id=14168 bug 14168]&lt;br /&gt;
; [http://arch.lustre.org/index.php?title=Server_Changelogs server changelogs]&lt;br /&gt;
[[Category:Architecture|Fileset]]&lt;br /&gt;
[[Category:Team_Rabbit]]&lt;/div&gt;</summary>
		<author><name>Nathan</name></author>
	</entry>
	<entry>
		<id>http://wiki.old.lustre.org/index.php?title=Architecture_-_Adaptive_Timeouts_-_Use_Cases&amp;diff=9980</id>
		<title>Architecture - Adaptive Timeouts - Use Cases</title>
		<link rel="alternate" type="text/html" href="http://wiki.old.lustre.org/index.php?title=Architecture_-_Adaptive_Timeouts_-_Use_Cases&amp;diff=9980"/>
		<updated>2007-08-27T22:53:01Z</updated>

		<summary type="html">&lt;p&gt;Nathan: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;= Adaptive Timeouts =&lt;br /&gt;
== Terminology ==&lt;br /&gt;
&lt;br /&gt;
{|border=1 cellspacing=&amp;quot;0&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
|&#039;&#039;&#039;Adaptive Timeout (AT)&#039;&#039;&#039;||Network RPC timeouts based on server and network loading.&lt;br /&gt;
|-&lt;br /&gt;
|&#039;&#039;&#039;Early reply&#039;&#039;&#039;||A response sent immediately by the server informing the client of a predicted slower-than-expected final response.&lt;br /&gt;
|-&lt;br /&gt;
|&#039;&#039;&#039;Service estimate&#039;&#039;&#039;||The expected worst-case time a request on a given portal to a given service will take.  This value changes depending on server loading.&lt;br /&gt;
|-&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== Architecture ==&lt;br /&gt;
&lt;br /&gt;
{| border=1 cellspacing=0&lt;br /&gt;
|-&lt;br /&gt;
|A. Report service times :|| Replies are annotated with the RPC&#039;s service time and the service estimate.  The service estimate is updated upon every &#039;success&#039; reply. Clients use the measured round-trip time and the reported service time to determine the round-trip network latency. Clients use the service estimate and network latency to set the timeout for future RPCs.&lt;br /&gt;
|-&lt;br /&gt;
|B. Early replies :|| Servers compare the timeout encoded in the RPC with the current service estimate and send early replies to all queued RPCs that they expect to time out before being serviced, reporting the new service estimate.  Clients receiving early replies adjust the RPCs local timeout to reflect the new service estimate.  This process is repeated whenever an RPC is near its deadline.   &lt;br /&gt;
|-&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== Use cases ==&lt;br /&gt;
&lt;br /&gt;
=== Summary ===&lt;br /&gt;
&lt;br /&gt;
{| border=1 cellspacing=0&lt;br /&gt;
|-&lt;br /&gt;
!id !! quality attribute !! summary&lt;br /&gt;
|-&lt;br /&gt;
|congested_server_new || recovery || server congestion causes client timeouts to adapt, not fail (new rpc)&lt;br /&gt;
|-&lt;br /&gt;
|congested_server_pending || recovery || server congestion causes client timeouts to adapt, not fail (pending or in-progress rpcs)&lt;br /&gt;
|-&lt;br /&gt;
|timeouts_recover || performance || timeouts decrease when load decreases&lt;br /&gt;
|-&lt;br /&gt;
|new_clients_learn || performance || new clients learn about server/network timing immediately &lt;br /&gt;
|-&lt;br /&gt;
|lock_timeouts || recovery || lock timeouts are based only on lock processing history, per target&lt;br /&gt;
|-&lt;br /&gt;
|busy_client_not_evicted || recovery || a responding client is not evicted for failing to return a lock quickly&lt;br /&gt;
|-&lt;br /&gt;
|server_down_client_start || performance || client starts while server is down.&lt;br /&gt;
|-&lt;br /&gt;
|liblustre_client_joins_late || recovery || a liblustre client computes for 20 min, then discovers the server has rebooted.&lt;br /&gt;
|-&lt;br /&gt;
|client_collection_timeout || recovery || Heavily loaded server fails over; clients have long AT already, and so don&#039;t try to reconnect for a long time.&lt;br /&gt;
|-&lt;br /&gt;
|replay_timeout || recovery || Client replaying lost reqs after server failover must wait for the server&#039;s recovery client collection phase to complete before they will see responses.&lt;br /&gt;
|-&lt;br /&gt;
|communications_failure || availability, performance || Lustre handling of communications failures&lt;br /&gt;
|-&lt;br /&gt;
|redundant_router_failure || availability, performance || Lustre handling of redundant router failure&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== server_down_client_start ===&lt;br /&gt;
&lt;br /&gt;
{|border=1  cellspacing=&amp;quot;0&amp;quot;&lt;br /&gt;
|-align=&amp;quot;left&amp;quot; &lt;br /&gt;
|colspan=2|&#039;&#039;&#039;Scenario:&#039;&#039;&#039; || New client starts or restarts while a server is down or unresponsive&lt;br /&gt;
|-align=&amp;quot;left&amp;quot; &lt;br /&gt;
|colspan=2|&#039;&#039;&#039;Business Goals:&#039;&#039;&#039; ||Maximize performance &lt;br /&gt;
|-align=&amp;quot;left&amp;quot; &lt;br /&gt;
|colspan=2|&#039;&#039;&#039;Relevant QA&#039;s:&#039;&#039;&#039;||Performance&lt;br /&gt;
|-align=&amp;quot;left&amp;quot;&lt;br /&gt;
|rowspan=&amp;quot;6&amp;quot; writing-mode=&amp;quot;vertical&amp;quot;|&#039;&#039;&#039;details&#039;&#039;&#039;&lt;br /&gt;
| &#039;&#039;&#039;Stimulus:&#039;&#039;&#039;||New client tries to connect to an unresponsive server&lt;br /&gt;
|-align=&amp;quot;left&amp;quot;&lt;br /&gt;
|&#039;&#039;&#039;Stimulus source:&#039;&#039;&#039;||client (re)boot&lt;br /&gt;
|-align=&amp;quot;left&amp;quot;&lt;br /&gt;
|&#039;&#039;&#039;Environment:&#039;&#039;&#039;||server or network failures&lt;br /&gt;
|-align=&amp;quot;left&amp;quot;&lt;br /&gt;
|&#039;&#039;&#039;Artifact:&#039;&#039;&#039;||Client connect time&lt;br /&gt;
|-align=&amp;quot;left&amp;quot;&lt;br /&gt;
|&#039;&#039;&#039;Response:&#039;&#039;&#039;||After the obd_connect RPC request timeout, a new connect is attempted, on either the same network or a different network.&lt;br /&gt;
|-align=&amp;quot;left&amp;quot;&lt;br /&gt;
|&#039;&#039;&#039;Response measure:&#039;&#039;&#039;||Time to successfully connect once the server/network becomes available. &lt;br /&gt;
|-align=&amp;quot;left&amp;quot;&lt;br /&gt;
|colspan=2|&#039;&#039;&#039;Questions:&#039;&#039;&#039;||None&lt;br /&gt;
|-align=&amp;quot;left&amp;quot;&lt;br /&gt;
|colspan=2|&#039;&#039;&#039;Issues:&#039;&#039;&#039;||We want obd_connect attempts on different connections (networks) to happen quickly, so that we try alternate routes in the case that one network fails.  But we want attempts on the same network to happen at LND-timeout speed (e.g. 50s), so we don&#039;t just pile up PUTs that are stuck.  But the problem is there is only a single RPC timeout number that we can specify, and it doesn&#039;t know what connection the next attempt will be on (decided in import_select_connection). Perhaps we need to do this: if we are at the end of the imp_conn_list, set the connect rpc timeout to slow (i.e. max(50s, adaptive timeout)), otherwise set the timeout fast (adaptive timeout).  &lt;br /&gt;
|-&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== liblustre_client_joins_late ===&lt;br /&gt;
&lt;br /&gt;
{|border=1 cellspacing=&amp;quot;0&amp;quot;&lt;br /&gt;
|-align=&amp;quot;left&amp;quot; &lt;br /&gt;
|colspan=2|&#039;&#039;&#039;Scenario:&#039;&#039;&#039; || A liblustre client computes for 20 min, then discovers the server has rebooted.&lt;br /&gt;
|-align=&amp;quot;left&amp;quot; &lt;br /&gt;
|colspan=2|&#039;&#039;&#039;Business Goals:&#039;&#039;&#039; ||Minimize evictions&lt;br /&gt;
|-align=&amp;quot;left&amp;quot; &lt;br /&gt;
|colspan=2|&#039;&#039;&#039;Relevant QA&#039;s:&#039;&#039;&#039;||Recovery&lt;br /&gt;
|-align=&amp;quot;left&amp;quot;&lt;br /&gt;
|rowspan=&amp;quot;6&amp;quot; writing-mode=&amp;quot;vertical&amp;quot;|&#039;&#039;&#039;details&#039;&#039;&#039;&lt;br /&gt;
| &#039;&#039;&#039;Stimulus:&#039;&#039;&#039;||Liblustre doesn&#039;t utilize pinger to verify server availability; attempts reconnection only when application tries to write.&lt;br /&gt;
|-align=&amp;quot;left&amp;quot;&lt;br /&gt;
|&#039;&#039;&#039;Stimulus source:&#039;&#039;&#039;||Actively computing client&lt;br /&gt;
|-align=&amp;quot;left&amp;quot;&lt;br /&gt;
|&#039;&#039;&#039;Environment:&#039;&#039;&#039;||server failures&lt;br /&gt;
|-align=&amp;quot;left&amp;quot;&lt;br /&gt;
|&#039;&#039;&#039;Artifact:&#039;&#039;&#039;||recoverable state in the cluster&lt;br /&gt;
|-align=&amp;quot;left&amp;quot;&lt;br /&gt;
|&#039;&#039;&#039;Response:&#039;&#039;&#039;||eviction of client determined by version recovery&lt;br /&gt;
|-align=&amp;quot;left&amp;quot;&lt;br /&gt;
|&#039;&#039;&#039;Response measure:&#039;&#039;&#039;||Availability&lt;br /&gt;
|-align=&amp;quot;left&amp;quot;&lt;br /&gt;
|colspan=2|&#039;&#039;&#039;Questions:&#039;&#039;&#039;||None&lt;br /&gt;
|-align=&amp;quot;left&amp;quot;&lt;br /&gt;
|colspan=2|&#039;&#039;&#039;Issues:&#039;&#039;&#039;||Version recovery makes it possible to rejoin after recovery period in some conditions; unrelated to AT.&lt;br /&gt;
|-&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== client_collection_timeout ===&lt;br /&gt;
&lt;br /&gt;
{|border=1 cellspacing=&amp;quot;0&amp;quot;&lt;br /&gt;
|-align=&amp;quot;left&amp;quot; &lt;br /&gt;
|colspan=2|&#039;&#039;&#039;Scenario:&#039;&#039;&#039; || Heavily loaded server fails over; clients have long AT already, and so don&#039;t try to reconnect for a long time.&lt;br /&gt;
|-align=&amp;quot;left&amp;quot; &lt;br /&gt;
|colspan=2|&#039;&#039;&#039;Business Goals:&#039;&#039;&#039; ||Minimize evictions&lt;br /&gt;
|-align=&amp;quot;left&amp;quot; &lt;br /&gt;
|colspan=2|&#039;&#039;&#039;Relevant QA&#039;s:&#039;&#039;&#039;||Recovery&lt;br /&gt;
|-align=&amp;quot;left&amp;quot;&lt;br /&gt;
|rowspan=&amp;quot;6&amp;quot; writing-mode=&amp;quot;vertical&amp;quot;|&#039;&#039;&#039;details&#039;&#039;&#039;&lt;br /&gt;
| &#039;&#039;&#039;Stimulus:&#039;&#039;&#039;||Client with a long AT waits a long time to try to reconnect to a rebooting server. The server has no idea how long to wait for the (first) client during the recovery client collection phase.&lt;br /&gt;
|-align=&amp;quot;left&amp;quot;&lt;br /&gt;
|&#039;&#039;&#039;Stimulus source:&#039;&#039;&#039;||Client reconnect attempt&lt;br /&gt;
|-align=&amp;quot;left&amp;quot;&lt;br /&gt;
|&#039;&#039;&#039;Environment:&#039;&#039;&#039;||slow server / network conditons, then server failover&lt;br /&gt;
|-align=&amp;quot;left&amp;quot;&lt;br /&gt;
|&#039;&#039;&#039;Artifact:&#039;&#039;&#039;||recoverable state in the cluster&lt;br /&gt;
|-align=&amp;quot;left&amp;quot;&lt;br /&gt;
|&#039;&#039;&#039;Response:&#039;&#039;&#039;||eviction of client(s) if client collection timeout is too short&lt;br /&gt;
|-align=&amp;quot;left&amp;quot;&lt;br /&gt;
|&#039;&#039;&#039;Response measure:&#039;&#039;&#039;||Availability&lt;br /&gt;
|-align=&amp;quot;left&amp;quot;&lt;br /&gt;
|colspan=2|&#039;&#039;&#039;Questions:&#039;&#039;&#039;||None&lt;br /&gt;
|-align=&amp;quot;left&amp;quot;&lt;br /&gt;
|colspan=2|&#039;&#039;&#039;Issues:&#039;&#039;&#039;||Because a newly rebooted server has no idea of previous network/server load, a fixed timeout must be used when waiting for the first client to reconnect during the client collection phase.  Once the first client has reconnected, the server can keep track of the maximum expected AT as reported by the client in the connect RPC.  This information can then be used to adjust how much longer the server will wait for client collection to complete.&lt;br /&gt;
|-&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== replay_timeout ===&lt;br /&gt;
&lt;br /&gt;
{|border=1 cellspacing=&amp;quot;0&amp;quot;&lt;br /&gt;
|-align=&amp;quot;left&amp;quot; &lt;br /&gt;
|colspan=2|&#039;&#039;&#039;Scenario:&#039;&#039;&#039; || Client replaying lost reqs after server failover must wait for the server&#039;s recovery client collection phase to complete before they will see responses.&lt;br /&gt;
|-align=&amp;quot;left&amp;quot; &lt;br /&gt;
|colspan=2|&#039;&#039;&#039;Business Goals:&#039;&#039;&#039; ||Minimize recovery time&lt;br /&gt;
|-align=&amp;quot;left&amp;quot; &lt;br /&gt;
|colspan=2|&#039;&#039;&#039;Relevant QA&#039;s:&#039;&#039;&#039;||Performance, Recovery&lt;br /&gt;
|-align=&amp;quot;left&amp;quot;&lt;br /&gt;
|rowspan=&amp;quot;6&amp;quot; writing-mode=&amp;quot;vertical&amp;quot;|&#039;&#039;&#039;details&#039;&#039;&#039;&lt;br /&gt;
|&#039;&#039;&#039;Stimulus:&#039;&#039;&#039;||Client replay request&lt;br /&gt;
|-align=&amp;quot;left&amp;quot;&lt;br /&gt;
|&#039;&#039;&#039;Stimulus source:&#039;&#039;&#039;||Server failover&lt;br /&gt;
|-align=&amp;quot;left&amp;quot;&lt;br /&gt;
|&#039;&#039;&#039;Environment:&#039;&#039;&#039;||server failure&lt;br /&gt;
|-align=&amp;quot;left&amp;quot;&lt;br /&gt;
|&#039;&#039;&#039;Artifact:&#039;&#039;&#039;||replay request timeout&lt;br /&gt;
|-align=&amp;quot;left&amp;quot;&lt;br /&gt;
|&#039;&#039;&#039;Response:&#039;&#039;&#039;||When a client tries to reconnect after failover, the replay req timeout is set to the AT expected processing time plus the fixed client collection timeout.&lt;br /&gt;
|-align=&amp;quot;left&amp;quot;&lt;br /&gt;
|&#039;&#039;&#039;Response measure:&#039;&#039;&#039;||Performance&lt;br /&gt;
|-align=&amp;quot;left&amp;quot;&lt;br /&gt;
|colspan=2|&#039;&#039;&#039;Questions:&#039;&#039;&#039;||Is it possible for version recovery to start recovery of certain files before the client collection period has finished?&lt;br /&gt;
|-align=&amp;quot;left&amp;quot;&lt;br /&gt;
|colspan=2|&#039;&#039;&#039;Issues:&#039;&#039;&#039;||Could have c1, recov period, c2, recov period, c3, in which case c1 would time out and resend the replay request until either c3 joins or recovery is aborted because it never showed up.&lt;br /&gt;
It would of course be desirable for c1, c2 to be able to start recovery before waiting a long time for c3 to arrive, to avoid wasting all that time.&lt;br /&gt;
&lt;br /&gt;
Maybe version based recovery can help us in this case, so that c1, c2 know&lt;br /&gt;
the files they are operating on have the same preop version and it is safe&lt;br /&gt;
for them to begin recovery without waiting for c3.  Then, either c1, c2&lt;br /&gt;
will have completed recovery and wait recov_period before normal recovery&lt;br /&gt;
is closed, or c3 will join in time if there are dependencies.&lt;br /&gt;
|-&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== communications_failure ===&lt;br /&gt;
&lt;br /&gt;
{|border=1 cellspacing=&amp;quot;0&amp;quot;&lt;br /&gt;
|-align=&amp;quot;left&amp;quot; &lt;br /&gt;
|colspan=2|&#039;&#039;&#039;Scenario:&#039;&#039;&#039; || Lustre handling of communications failures&lt;br /&gt;
|-align=&amp;quot;left&amp;quot; &lt;br /&gt;
|colspan=2|&#039;&#039;&#039;Business Goals:&#039;&#039;&#039; || Fault isolation&lt;br /&gt;
|-align=&amp;quot;left&amp;quot; &lt;br /&gt;
|colspan=2|&#039;&#039;&#039;Relevant QA&#039;s:&#039;&#039;&#039;|| Availability, performance&lt;br /&gt;
|-align=&amp;quot;left&amp;quot;&lt;br /&gt;
|rowspan=&amp;quot;6&amp;quot; writing-mode=&amp;quot;vertical&amp;quot;|&#039;&#039;&#039;details&#039;&#039;&#039;&lt;br /&gt;
|&#039;&#039;&#039;Stimulus:&#039;&#039;&#039;||  Peer node crash / hang / reboot or network failure&lt;br /&gt;
|-align=&amp;quot;left&amp;quot;&lt;br /&gt;
|&#039;&#039;&#039;Stimulus source:&#039;&#039;&#039;|| Hardware/software failure.  Sysadmin&lt;br /&gt;
|-align=&amp;quot;left&amp;quot;&lt;br /&gt;
|&#039;&#039;&#039;Environment:&#039;&#039;&#039;|| Operation under all loads&lt;br /&gt;
|-align=&amp;quot;left&amp;quot;&lt;br /&gt;
|&#039;&#039;&#039;Artifact:&#039;&#039;&#039;|| ptlrpc (both client and server), OST/OSC, MDC/MDS&lt;br /&gt;
|-align=&amp;quot;left&amp;quot;&lt;br /&gt;
|&#039;&#039;&#039;Response:&#039;&#039;&#039;|| Failed RPCs are completed cleanly.  The number of uncompleted RPCs to any peer is bounded.&lt;br /&gt;
|-align=&amp;quot;left&amp;quot;&lt;br /&gt;
|&#039;&#039;&#039;Response measure:&#039;&#039;&#039;|| No effect on communications other peers.&lt;br /&gt;
|-align=&amp;quot;left&amp;quot;&lt;br /&gt;
|colspan=2|&#039;&#039;&#039;Questions:&#039;&#039;&#039;|| None&lt;br /&gt;
|-align=&amp;quot;left&amp;quot;&lt;br /&gt;
|colspan=2|&#039;&#039;&#039;Issues:&#039;&#039;&#039;||&lt;br /&gt;
&lt;br /&gt;
An RPC, whether on the client or the server is a compound communication (e.g. request, bulk, reply).  Each&lt;br /&gt;
individual communication has an associated buffer which may be active (posted with LNetPut() or LNetGet()) or&lt;br /&gt;
passive (posted with LNetMEAttach()).  An RPC is only complete when the MDs for all its successfully posted&lt;br /&gt;
communications have been unlinked.  LNET may access these buffers at any time until the &amp;quot;unlinked&amp;quot; event has&lt;br /&gt;
been received.  RPCs must be completed in all circumstances, even if it is to be abandoned because of a&lt;br /&gt;
timeout or a component communication failed.&lt;br /&gt;
&lt;br /&gt;
Uncompleted RPCs consume resources in LNET, the relevant LND and its underlying network stack.  Further RPCs&lt;br /&gt;
may fail if the number of uncompleted RPCs is allowed to grow without limit - for example if all network&lt;br /&gt;
resources are tied up waiting for RPCs to a failed peer, new RPCs to working, responsive peers may fail.&lt;br /&gt;
&lt;br /&gt;
Calling LNetMDUnlink() on a posted MD ensures delivery of the &amp;quot;unlink&amp;quot; event at the earliest opportunity.  The&lt;br /&gt;
time to deliver this event is guaranteed finite, but may be determined by the underlying network stack.  Note&lt;br /&gt;
the fundamental race with normal completion - LNET handles this so that it is safe to call at any time or&lt;br /&gt;
indeed any number of times, however it only returns success on the first call and only if the MD hasn&#039;t&lt;br /&gt;
auto-unlinked already.&lt;br /&gt;
&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== redundant_router_failure ===&lt;br /&gt;
&lt;br /&gt;
{|border=1 cellspacing=&amp;quot;0&amp;quot;&lt;br /&gt;
|-align=&amp;quot;left&amp;quot; &lt;br /&gt;
|colspan=2|&#039;&#039;&#039;Scenario:&#039;&#039;&#039; || Lustre handling of redundant LNET router failure&lt;br /&gt;
|-align=&amp;quot;left&amp;quot; &lt;br /&gt;
|colspan=2|&#039;&#039;&#039;Business Goals:&#039;&#039;&#039; || Transparent handling of the failure&lt;br /&gt;
|-align=&amp;quot;left&amp;quot; &lt;br /&gt;
|colspan=2|&#039;&#039;&#039;Relevant QA&#039;s:&#039;&#039;&#039;|| Availability, performance&lt;br /&gt;
|-align=&amp;quot;left&amp;quot;&lt;br /&gt;
|rowspan=&amp;quot;6&amp;quot; writing-mode=&amp;quot;vertical&amp;quot;|&#039;&#039;&#039;details&#039;&#039;&#039;&lt;br /&gt;
|&#039;&#039;&#039;Stimulus:&#039;&#039;&#039;||  Redundant router crashes or hangs&lt;br /&gt;
|-align=&amp;quot;left&amp;quot;&lt;br /&gt;
|&#039;&#039;&#039;Stimulus source:&#039;&#039;&#039;|| hardware/software failure or sysadmin reboot&lt;br /&gt;
|-align=&amp;quot;left&amp;quot;&lt;br /&gt;
|&#039;&#039;&#039;Environment:&#039;&#039;&#039;|| operation under all loads with LNET router failure detection enabled&lt;br /&gt;
|-align=&amp;quot;left&amp;quot;&lt;br /&gt;
|&#039;&#039;&#039;Artifact:&#039;&#039;&#039;|| ptlrpc (both client and server), OST/OSC, MDC/MDS&lt;br /&gt;
|-align=&amp;quot;left&amp;quot;&lt;br /&gt;
|&#039;&#039;&#039;Response:&#039;&#039;&#039;|| Router fails transparently to applications using the file system.  Minimum performance impact.&lt;br /&gt;
|-align=&amp;quot;left&amp;quot;&lt;br /&gt;
|&#039;&#039;&#039;Response measure:&#039;&#039;&#039;|| No errors returned to the application.  Performance impact no worse than server failover. &lt;br /&gt;
|-align=&amp;quot;left&amp;quot;&lt;br /&gt;
|colspan=2|&#039;&#039;&#039;Questions:&#039;&#039;&#039;|| None&lt;br /&gt;
|-align=&amp;quot;left&amp;quot;&lt;br /&gt;
|colspan=2|&#039;&#039;&#039;Issues:&#039;&#039;&#039;|| &lt;br /&gt;
&lt;br /&gt;
When a router fails, many communications, either buffered in the router or committed to be routed via the&lt;br /&gt;
router, will fail.  This fails all relevant RPCs, however further intermittent RPC failure is possible until&lt;br /&gt;
all nodes on all paths from client to server and back have detected and avoided the failed router.&lt;br /&gt;
&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== References ==&lt;br /&gt;
&lt;br /&gt;
The parent tracking bug for Adaptive Timeouts is 3055.&lt;br /&gt;
 &lt;br /&gt;
[[Category:QAS|Recovery Failures]]&lt;/div&gt;</summary>
		<author><name>Nathan</name></author>
	</entry>
	<entry>
		<id>http://wiki.old.lustre.org/index.php?title=Help:Editing&amp;diff=2056</id>
		<title>Help:Editing</title>
		<link rel="alternate" type="text/html" href="http://wiki.old.lustre.org/index.php?title=Help:Editing&amp;diff=2056"/>
		<updated>2007-05-11T22:24:59Z</updated>

		<summary type="html">&lt;p&gt;Nathan: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;see Mediawiki [http://meta.wikimedia.org/wiki/Help:Editing editing help]&lt;br /&gt;
and [http://meta.wikimedia.org/wiki/Help:Wikitext_examples examples]&lt;/div&gt;</summary>
		<author><name>Nathan</name></author>
	</entry>
	<entry>
		<id>http://wiki.old.lustre.org/index.php?title=Help:Editing&amp;diff=2055</id>
		<title>Help:Editing</title>
		<link rel="alternate" type="text/html" href="http://wiki.old.lustre.org/index.php?title=Help:Editing&amp;diff=2055"/>
		<updated>2007-05-11T22:22:53Z</updated>

		<summary type="html">&lt;p&gt;Nathan: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;see [http://meta.wikimedia.org/wiki/Help:Editing Mediawiki]&lt;/div&gt;</summary>
		<author><name>Nathan</name></author>
	</entry>
	<entry>
		<id>http://wiki.old.lustre.org/index.php?title=Patchless_Client&amp;diff=1780</id>
		<title>Patchless Client</title>
		<link rel="alternate" type="text/html" href="http://wiki.old.lustre.org/index.php?title=Patchless_Client&amp;diff=1780"/>
		<updated>2007-05-08T14:45:29Z</updated>

		<summary type="html">&lt;p&gt;Nathan: /* Versions */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Patchless Client ==&lt;br /&gt;
As of Lustre 1.6.0, Lustre supports running the client modules on some unpatched &amp;quot;stock&amp;quot; kernels.&lt;br /&gt;
This results in some small performance losses, but may be worthwhile to some users for maintenance or contract reasons.  &lt;br /&gt;
&lt;br /&gt;
We will typically post a &amp;quot;patchless&amp;quot; RPM at the [http://www.lustre.org/downloads.html download site]. Instead, if building from source, the Lustre configure script will automatically detect the unpatched kernel and disable building the servers.&lt;br /&gt;
{{{&lt;br /&gt;
[lustre]$ ./configure --with-linux=/unpatched/kernel/source&lt;br /&gt;
}}}&lt;br /&gt;
&lt;br /&gt;
=== Versions ===&lt;br /&gt;
Currently, the patchless client works with these kernel versions&lt;br /&gt;
&lt;br /&gt;
Vanilla kernel:&lt;br /&gt;
 * 2.6.15    (1.6.0)&lt;br /&gt;
 * 2.6.16    (1.6.0)&lt;br /&gt;
 * 2.6.17    (1.6.0) Mandriva&#039;s 2.6.17 is also reported working.&lt;br /&gt;
 * 2.6.18    (1.6.0)&lt;br /&gt;
 * 2.6.19    (1.6.0)&lt;br /&gt;
 * 2.6.20    (1.6.1 [https://bugzilla.lustre.org/show_bug.cgi?id=11647 bug 11647])&lt;br /&gt;
 * 2.6.21    (1.6.1 [https://bugzilla.lustre.org/show_bug.cgi?id=11647 bug 11647])&lt;br /&gt;
&lt;br /&gt;
Red Hat Enterprise Linux:&lt;br /&gt;
 * RHEL4 [2.6.9-42.0.8EL] (1.6.0) with the following caveats:&lt;br /&gt;
  - Nested Symlinks: due to improper lookup_continue logic with unpatched 2.6.15&lt;br /&gt;
    kernels and earlier, nested symlinks will lead to unpredictable results&lt;br /&gt;
  - FMODE_EXEC missing: Lustre will incorrectly allow a user from one client to&lt;br /&gt;
    write/truncate a binary simultaneously while a user from a different client&lt;br /&gt;
    executes the same binary &lt;br /&gt;
 * RHEL4U5 [2.6.9-55EL]   (1.6.0) Red Hat has includesd a Lustre-specific patch&lt;br /&gt;
   with RHEL4U5 which resolves the above issues.&lt;br /&gt;
&lt;br /&gt;
 * RHEL5     (1.6.1 [https://bugzilla.lustre.org/show_bug.cgi?id=11647 bug 11647])&lt;br /&gt;
&lt;br /&gt;
Fedora Core:&lt;br /&gt;
 * FC6       (1.6.1 [https://bugzilla.lustre.org/show_bug.cgi?id=11647 bug 11647])&lt;br /&gt;
&lt;br /&gt;
Suse:&lt;br /&gt;
 * SLES 10   (tbd)&lt;br /&gt;
&lt;br /&gt;
=== Known Issues ===&lt;br /&gt;
&lt;br /&gt;
many NFS-related bugs are also addressed by the patchless client fixes.&lt;/div&gt;</summary>
		<author><name>Nathan</name></author>
	</entry>
	<entry>
		<id>http://wiki.old.lustre.org/index.php?title=Patchless_Client&amp;diff=1770</id>
		<title>Patchless Client</title>
		<link rel="alternate" type="text/html" href="http://wiki.old.lustre.org/index.php?title=Patchless_Client&amp;diff=1770"/>
		<updated>2007-05-07T17:08:52Z</updated>

		<summary type="html">&lt;p&gt;Nathan: /* Versions */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Patchless Client ==&lt;br /&gt;
As of Lustre 1.6.0, Lustre supports running the client modules on some unpatched &amp;quot;stock&amp;quot; kernels.&lt;br /&gt;
This results in some small performance losses, but may be worthwhile to some users for maintenance or contract reasons.  &lt;br /&gt;
&lt;br /&gt;
We will typically post a &amp;quot;patchless&amp;quot; RPM at the [http://www.lustre.org/downloads.html download site]. Instead, if building from source, the Lustre configure script will automatically detect the unpatched kernel and disable building the servers.&lt;br /&gt;
{{{&lt;br /&gt;
[lustre]$ ./configure --with-linux=/unpatched/kernel/source&lt;br /&gt;
}}}&lt;br /&gt;
&lt;br /&gt;
=== Versions ===&lt;br /&gt;
Currently, the patchless client works with these kernel versions&lt;br /&gt;
&lt;br /&gt;
Vanilla kernel:&lt;br /&gt;
 * 2.6.15    (1.6.0)&lt;br /&gt;
 * 2.6.16    (1.6.0)&lt;br /&gt;
 * 2.6.17    (1.6.0) Mandriva&#039;s 2.6.17 is also reported working.&lt;br /&gt;
 * 2.6.18    (1.6.0)&lt;br /&gt;
 * 2.6.19    (1.6.0)&lt;br /&gt;
 * 2.6.20    (1.6.1 [https://bugzilla.lustre.org/show_bug.cgi?id=11647 bug 11647])&lt;br /&gt;
 * 2.6.21    (1.6.1 [https://bugzilla.lustre.org/show_bug.cgi?id=11647 bug 11647])&lt;br /&gt;
&lt;br /&gt;
Red Hat Enterprise Linux:&lt;br /&gt;
 * RHEL4 [2.6.9-42.0.8EL]   (1.6.0) with the following caveats:&lt;br /&gt;
  - Nested Symlinks: due to improper lookup_continue logic with unpatched 2.6.15 kernels and earlier, nested symlinks will lead to unpredictable results&lt;br /&gt;
  - FMODE_EXEC missing: Lustre will incorrectly allow a user from one client to write/truncate a binary simultaneously while a user from a different client executes the same binary &lt;br /&gt;
 * RHEL4U5 (1.6.0) Red Hat has includesd a Lustre-specific patch with RHEL4U5 which resolves the above issues.&lt;br /&gt;
&lt;br /&gt;
 * RHEL5 (1.6.1 [https://bugzilla.lustre.org/show_bug.cgi?id=11647 bug 11647])&lt;br /&gt;
&lt;br /&gt;
Fedora Core:&lt;br /&gt;
 * FC6 (1.6.1 [https://bugzilla.lustre.org/show_bug.cgi?id=11647 bug 11647])&lt;br /&gt;
&lt;br /&gt;
Suse:&lt;br /&gt;
 * SLES 10 (tbd)&lt;br /&gt;
&lt;br /&gt;
=== Known Issues ===&lt;br /&gt;
&lt;br /&gt;
many NFS-related bugs are also addressed by the patchless client fixes.&lt;/div&gt;</summary>
		<author><name>Nathan</name></author>
	</entry>
</feed>