<?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=Shadow</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=Shadow"/>
	<link rel="alternate" type="text/html" href="http://wiki.old.lustre.org/index.php?title=Special:Contributions/Shadow"/>
	<updated>2026-04-14T23:52:31Z</updated>
	<subtitle>User contributions</subtitle>
	<generator>MediaWiki 1.39.7</generator>
	<entry>
		<id>http://wiki.old.lustre.org/index.php?title=Documenting_Code&amp;diff=4827</id>
		<title>Documenting Code</title>
		<link rel="alternate" type="text/html" href="http://wiki.old.lustre.org/index.php?title=Documenting_Code&amp;diff=4827"/>
		<updated>2008-06-09T09:03:52Z</updated>

		<summary type="html">&lt;p&gt;Shadow: add reference to doxygen tags&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;In addition to the architecture and design documentation, certain amount of documentation has to be maintained in the Lustre source code. Main reason for this is that it is very difficult to constantly keep separate documentation up to date with the changing code. &lt;br /&gt;
&lt;br /&gt;
The best way to document the code is to make its so simple and clear that no additional documentation is necessary. As [http://en.wikipedia.org/wiki/Rob_Pike R. Pike, Esq.] put it: &#039;&#039;[http://www.lysator.liu.se/c/pikestyle.html Basically, avoid comments]&#039;&#039;. Failing to reach this ideal, code has to be commented. There are two broad categories of the comments:&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;how&#039;&#039;: describes how this particular piece of code achieves its function;&lt;br /&gt;
* &#039;&#039;what&#039;&#039;: describes what is the purpose of this function or data-type or module, and how it fits into larger picture. These are &#039;&#039;interface&#039;&#039; comments.&lt;br /&gt;
&lt;br /&gt;
This page deals only with the latter type. Lustre is using (will use) [http://en.wikipedia.org/wiki/Doxygen doxygen] to automatically generate cross-linked interface descriptions from source code. As a result, interface comments have to follow certain template, which has advantages on its own.&lt;br /&gt;
&lt;br /&gt;
Below are few examples:&lt;br /&gt;
&lt;br /&gt;
===commenting a function===&lt;br /&gt;
&amp;lt;pre style=&amp;quot;background:lightgrey;&amp;quot;&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;
Note that:&lt;br /&gt;
* doxygen comment starts with /** (like in [http://en.wikipedia.org/wiki/Javadoc javadoc])&lt;br /&gt;
* it opens with a brief description of what this function is doing. Brief description runs up to the first full-stop mark (.)&lt;br /&gt;
* brief description is followed by the detailed description.&lt;br /&gt;
* descriptions are written in active voice with indicative mood verbs in third person singular: &amp;quot;[This function] does this and that&amp;quot;, &amp;quot;[This data-type represents] such and such concepts&amp;quot;.&lt;br /&gt;
* to refer to a function argument use \a argname syntax.&lt;br /&gt;
* to refer to another function use funcname() syntax---it will produce a cross-reference.&lt;br /&gt;
* to refer to a field or an enum value use SCOPE::NAME syntax.&lt;br /&gt;
* if possible, specify a (weakest) precondition and (strongest) postcondition for the function. If conditions cannot be expressed as a C language expression, provide informal description. Use &#039;&#039;result&#039;&#039; to refer to the function return value. Mention all concurrency control restrictions (such as locks that function expects to he held, or holds on exit) here.&lt;br /&gt;
* describe possible return values with \retval.&lt;br /&gt;
* enumerate related functions and data-types in \see section. Note, that doxygen will automatically cross-reference all places where given function is called (but not through function pointer), and all functions that it calls, there is no need to enumerate all this.&lt;br /&gt;
* optionally use \author tag, so that the world knows whom to praise.&lt;br /&gt;
&lt;br /&gt;
===data-type===&lt;br /&gt;
&amp;lt;pre style=&amp;quot;background:lightgrey;&amp;quot;&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;
* describe data-type invariants (again, preferably formally).&lt;br /&gt;
&amp;lt;pre style=&amp;quot;background:lightgrey;&amp;quot;&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 Data type 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;
* describe concurrency control mechanisms for structure fields:&lt;br /&gt;
&amp;lt;pre style=&amp;quot;background:lightgrey;&amp;quot;&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;
* specify when fields are valid:&lt;br /&gt;
&amp;lt;pre style=&amp;quot;background:lightgrey;&amp;quot;&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;
* a sub-set of fields of enum values can be grouped together with @{...@} block:&lt;br /&gt;
&amp;lt;pre style=&amp;quot;background:lightgrey;&amp;quot;&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;
* by default documenting comment goes immediately before an entity being commented. Sometimes to streamline comments in the header file it&#039;s necessary to place comment separately. Use following syntax for this:&lt;br /&gt;
&amp;lt;pre style=&amp;quot;background:lightgrey;&amp;quot;&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;
===files and modules===&lt;br /&gt;
&lt;br /&gt;
* document functions in the .c files, rather than headers.&lt;br /&gt;
* to document a software component add the following to the header file with definitions of the key data-types for this module:&lt;br /&gt;
&amp;lt;pre style=&amp;quot;background:lightgrey;&amp;quot;&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;
type definitions...&lt;br /&gt;
exported functions...&lt;br /&gt;
/** @} component_name */&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
* to separate a logical part of larger component add the following somewhere withing components&#039;s \defgroup:&lt;br /&gt;
&amp;lt;pre style=&amp;quot;background:lightgrey;&amp;quot;&amp;gt;&lt;br /&gt;
/**&lt;br /&gt;
 * \name subcomponent_name subcomponent_name&lt;br /&gt;
 *&lt;br /&gt;
 * Description of a sub-component&lt;br /&gt;
 */&lt;br /&gt;
/** @{ */&lt;br /&gt;
type definitions...&lt;br /&gt;
exported functions...&lt;br /&gt;
/** @} subcomponent_name */&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
* if exported function prototype in a header is located within some group, appropriate function definition in a .c file is automatically assigned to the same group.&lt;br /&gt;
* a set of comments which is not lexically a part of a group, can be included into it with \addtogroup command:&lt;br /&gt;
&amp;lt;pre style=&amp;quot;background:lightgrey;&amp;quot;&amp;gt;&lt;br /&gt;
/** \addtogroup cl_object 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;
Doxygen uses a &#039;&#039;template file&#039;&#039; to control documentation build. Lustre comes with two templates:&lt;br /&gt;
* build/doxyfile.ref: produces a &#039;&#039;short&#039;&#039; form of documentation set, suitable as a reference. Output is placed into apidoc.ref/ directory.&lt;br /&gt;
* build/doxyfile.api: produces full documentation set, more suitable for learning code structure. In addition to apidoc.ref/ version this includes call-graphs, source code excerpts, and non-html forms of documentation (rtf, latex, troff, and rtf). Output is placed into apidoc.api/ directory.&lt;br /&gt;
&lt;br /&gt;
To build documentation, run&lt;br /&gt;
&amp;lt;pre style=&amp;quot;background:lightgrey;&amp;quot;&amp;gt;&lt;br /&gt;
doxygen build/$TEMPLATE&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
in the top-level lustre directory.&lt;br /&gt;
&lt;br /&gt;
=== publishing ===&lt;br /&gt;
&lt;br /&gt;
build/apidoc.publish scripts publishes your local version of documentation on the http://wiki.lustre.org/apidoc:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
build/apidoc.publish [-b branchname] [-l additional-label] [-d] [-u user]&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
build/apidoc.publish tries to guess branchname by looking into CVS/Tag. -d instructs script to use current date as a label. Documentation will be uploaded into&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
user@shell.lustre.sun.com:/home/www/apidoc/$branch$label&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
where $label is a concatenation of all labels given on the command line in order.&lt;br /&gt;
&lt;br /&gt;
=== Refer to Doxygen tags ===&lt;br /&gt;
&lt;br /&gt;
[http://www.stack.nl/~dimitri/doxygen/commands.html]&lt;/div&gt;</summary>
		<author><name>Shadow</name></author>
	</entry>
	<entry>
		<id>http://wiki.old.lustre.org/index.php?title=Patchless_Client&amp;diff=3615</id>
		<title>Patchless Client</title>
		<link rel="alternate" type="text/html" href="http://wiki.old.lustre.org/index.php?title=Patchless_Client&amp;diff=3615"/>
		<updated>2007-06-23T05:45:43Z</updated>

		<summary type="html">&lt;p&gt;Shadow: add vanila 2.6.22 into supported list&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://downloads.clusterfs.com/customer 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;
{| border=1 cellspacing=0&lt;br /&gt;
|-&lt;br /&gt;
|&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
 [lustre]$ ./configure --with-linux=/unpatched/kernel/source &lt;br /&gt;
&amp;lt;/pre&amp;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) Debian 4.0 2.6.18 is also reported working&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;
* 2.6.22    (1.6.1 [https://bugzilla.lustre.org/show_bug.cgi?id=11647 bug 12764])&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 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>Shadow</name></author>
	</entry>
</feed>