<?xml version="1.0" encoding="utf-8"?>
<chapter xmlns="http://docbook.org/ns/docbook"
-xmlns:xl="http://www.w3.org/1999/xlink" version="5.0" xml:lang="en-US"
-xml:id="userutilities"
-xmlns:xi="http://www.w3.org/2001/XInclude">
+ xmlns:xl="http://www.w3.org/1999/xlink" version="5.0" xml:lang="en-US"
+ xmlns:xi="http://www.w3.org/2001/XInclude" xml:id="userutilities">
<title xml:id="userutilities.title">User Utilities</title>
<para>This chapter describes user utilities.</para>
- <section xml:id="dbdoclet.50438206_94597">
+ <section xml:id="userutilities.lfs">
<title>
<indexterm>
<primary>lfs</primary>
lfs changelog [--follow] <replaceable>mdt_name</replaceable> [startrec [endrec]]
lfs changelog_clear <replaceable>mdt_name id endrec</replaceable>
lfs check <replaceable>mds|osts|servers</replaceable>
+lfs data_version [-nrw] <replaceable>filename</replaceable>
lfs df [-i] [-h] [--pool]-p <replaceable>fsname</replaceable>[.<replaceable>pool</replaceable>] [<replaceable>path</replaceable>] [--lazy]
lfs find [[!] --atime|-A [-+]N] [[!] --mtime|-M [-+]N]
[[!] --ctime|-C [-+]N] [--maxdepth|-D N] [--name|-n <replaceable>pattern</replaceable>]
<replaceable>dirname|filename</replaceable>
lfs getname [-h]|[path...]
lfs getstripe [--obd|-O <replaceable>ost_name</replaceable>] [--quiet|-q] [--verbose|-v]
- [--count|-c] [--index|-i | --offset|-o]
- [--size|-s] [--pool|-p] [--directory|-d]
- [--recursive|-r] [--raw|-R] [-M]
+ [--stripe-count|-c] [--stripe-index|-i]
+ [--stripe-size|-s] [--pool|-p] [--directory|-d]
+ [--mdt-index|-M] [--recursive|-r] [--raw|-R]
+ [--layout|-L]
<replaceable>dirname|filename</replaceable> ...
-lfs setstripe [--size|-s stripe_size] [--count|-c <replaceable>stripe_count</replaceable>]
+lfs setstripe [--size|-s stripe_size] [--stripe-count|-c <replaceable>stripe_count</replaceable>]
+ [--overstripe-count|-C <replaceable>stripe_count</replaceable>]
[--stripe-index|-i <replaceable>start_ost_index</replaceable>]
[--ost-list|-o <replaceable>ost_indicies</replaceable>]
[--pool|-p <replaceable>pool</replaceable>]
lfs osts [path]
lfs pool_list <replaceable>filesystem</replaceable>[.<replaceable>pool</replaceable>]| <replaceable>pathname</replaceable>
lfs quota [-q] [-v] [-h] [-o <replaceable>obd_uuid</replaceable>|-I <replaceable>ost_idx</replaceable>|-i <replaceable>mdt_idx</replaceable>]
- [-u <replaceable>username|uid|-g</replaceable> <replaceable>group|gid</replaceable>] <replaceable>/mount_point</replaceable>
-lfs quota -t -u|-g <replaceable>/mount_point</replaceable>
-lfs quotacheck [-ug] <replaceable>/mount_point</replaceable>
-lfs quotachown [-i] <replaceable>/mount_point</replaceable>
-lfs quotainv [-ug] [-f] <replaceable>/mount_point</replaceable>
-lfs quotaon [-ugf] <replaceable>/mount_point</replaceable>
-lfs quotaoff [-ug] <replaceable>/mount_point</replaceable>
-lfs setquota {-u|--user|-g|--group} <replaceable>uname|uid|gname|gid</replaceable>
+ [-u <replaceable>username|uid|-g</replaceable> <replaceable>group|gid</replaceable>|-p <replaceable>projid</replaceable>] <replaceable>/mount_point</replaceable>
+lfs quota -t -u|-g|-p <replaceable>/mount_point</replaceable>
+lfs setquota {-u|--user|-g|--group|-p|--project} <replaceable>uname|uid|gname|gid|projid</replaceable>
[--block-softlimit <replaceable>block_softlimit</replaceable>]
[--block-hardlimit <replaceable>block_hardlimit</replaceable>]
[--inode-softlimit <replaceable>inode_softlimit</replaceable>]
[--inode-hardlimit <replaceable>inode_hardlimit</replaceable>]
<replaceable>/mount_point</replaceable>
-lfs setquota -u|--user|-g|--group <replaceable>uname|uid|gname|gid</replaceable>
+lfs setquota -u|--user|-g|--group|-p|--project <replaceable>uname|uid|gname|gid|projid</replaceable>
[-b <replaceable>block_softlimit</replaceable>] [-B <replaceable>block_hardlimit</replaceable>]
[-i <replaceable>inode-softlimit</replaceable>] [-I <replaceable>inode_hardlimit</replaceable>]
<replaceable>/mount_point</replaceable>
-lfs setquota -t -u|-g [--block-grace <replaceable>block_grace</replaceable>]
+lfs setquota -t -u|-g|-p [--block-grace <replaceable>block_grace</replaceable>]
[--inode-grace <replaceable>inode_grace</replaceable>]
<replaceable>/mount_point</replaceable>
-lfs setquota -t -u|-g [-b <replaceable>block_grace</replaceable>] [-i <replaceable>inode_grace</replaceable>]
+lfs setquota -t -u|-g|-p [-b <replaceable>block_grace</replaceable>] [-i <replaceable>inode_grace</replaceable>]
<replaceable>/mount_point</replaceable>
lfs help
</screen>
<literal>-v</literal> option with
<literal>lfs quota</literal>.</para>
</note>
+ <para condition="l28">
+ The <literal>quotacheck</literal>, <literal>quotaon</literal> and
+ <literal>quotaoff</literal> sub-commands were deprecated in the
+ Lustre 2.4 release, and removed completely in the Lustre 2.8 release.
+ See <xref linkend="enabling_disk_quotas"/> for details on
+ configuring and checking quotas.
+ </para>
</section>
<section remap="h5">
<title>Description</title>
</row>
<row>
<entry nameend="c2" namest="c1">
+ <para>
+ <literal>data_version [-nrw]
+ <replaceable>filename</replaceable></literal>
+ </para>
+ </entry>
+ <entry>
+ <para>Displays the current version of file data. If
+ <literal>-n</literal> is specified, the data version is read
+ without taking a lock. As a consequence, the data version could
+ be outdated if there are dirty caches on filesystem clients, but
+ this option will not force data flushes and has less of an
+ impact on the filesystem. If <literal>-r</literal> is specified,
+ the data version is read after dirty pages on clients are
+ flushed. If <literal>-w</literal> is specified, the data version
+ is read after all caching pages on clients are flushed.
+ </para>
+ <para>
+ Even with <literal>-r</literal> or <literal>-w</literal>, race
+ conditions are possible and the data version should be checked
+ before and after an operation to be confident the data did not
+ change during it.
+ </para>
+ <para>
+ The data version is the sum of the last committed transaction
+ numbers of all data objects of a file. It is used by HSM policy
+ engines for verifying that file data has not been changed during
+ an archive operation or before a release operation, and by OST
+ migration, primarily for verifying that file data has not been
+ changed during a data copy, when done in non-blocking mode.
+ </para>
+ </entry>
+ </row>
+ <row>
+ <entry nameend="c2" namest="c1">
<literal>df [-i] [-h] [--pool|-p
<replaceable>fsname</replaceable>[.
<replaceable>pool</replaceable>] [
guarantee that
<literal>atime</literal> is kept coherent across the
cluster.)</para>
- <para>OSTs store a transient
+ <para>OSTs by default only hold a transient
<literal>atime</literal> that is updated when clients do read
requests. Permanent
- <literal>atime</literal> is written to the MDS when the file is
+ <literal>atime</literal> is written to the MDT when the file is
closed. However, on-disk atime is only updated if it is more
than 60 seconds old (
- <literal>/proc/fs/lustre/mds/*/max_atime_diff</literal>). The
- Lustre software considers the latest
- <literal>atime</literal> from all OSTs. If a
+ <literal>mdd.*.atime_diff</literal>).
+ </para>
+ <para condition='l2D'>In Lustre 2.14, it is possible to set
+ the OSTs to persistently store atime with each object, in
+ order to get more accurate persistent atime updates for files
+ that are open for a long time via the similarly-named
+ <literal>obdfilter.*.atime_diff</literal> parameter.
+ </para>
+ <para>
+ The client considers the latest <literal>atime</literal> from
+ all OSTs and MDTs. If a
<literal>setattr</literal> is set by user, then it is updated on
- both the MDS and OST, allowing the
+ both the MDT and OST, allowing the
<literal>atime</literal> to go backward.</para>
</entry>
</row>
are returned.</para>
<para>If you only want specific striping information, then the
options of
- <literal>--count</literal>,
- <literal>--size</literal>,
- <literal>--index</literal> or
- <literal>--offset</literal> plus various combinations of these
+ <literal>--stripe-count</literal>,
+ <literal>--stripe-size</literal>,
+ <literal>--stripe-index</literal>,
+ <literal>--layout</literal>, or
+ <literal>--pool</literal> plus various combinations of these
options can be used to retrieve specific information.</para>
<para>If the
<literal>--raw</literal> option is specified, the stripe
default values for unspecified fields. If the striping EA is
not set, 0, 0, and -1 will be printed for the stripe count,
size, and offset respectively.</para>
- <para condition="l24">The
- <literal>-M</literal> prints the index of the MDT for a given
- directory. See
- <xref linkend="dbdoclet.rmremotedir" />.</para>
+ <para>The <literal>--mdt-index</literal> prints the index of
+ the MDT for a given directory. See
+ <xref linkend="lustremaint.rmremotedir" />.</para>
</entry>
</row>
<row>
</entry>
<entry>
<para>
- <literal>--count</literal>
+ <literal>--stripe-count</literal>
</para>
</entry>
<entry>
</entry>
<entry>
<para>
- <literal>--count stripe_cnt</literal>
+ <literal>--stripe-count stripe_cnt</literal>
</para>
</entry>
<entry>
</entry>
<entry>
<para>
+ <literal>--overstripe-count stripe_cnt</literal>
+ </para>
+ </entry>
+ <entry>
+ <para>The same as --stripe-count, but allows overstriping,
+ which will place more than one stripe per OST if
+ <literal>stripe_cnt</literal> is greater than the number of
+ OSTs. Overstriping is useful for matching the number of stripes
+ to the number of processes, or with very fast OSTs, where one
+ stripe per OST is not enough to get full performance.</para>
+ </entry>
+ </row>
+ <row>
+ <entry>
+ <para> </para>
+ </entry>
+ <entry>
+ <para>
<literal>--size stripe_size</literal>
<footnote>
<para>The default stripe-size is 0. The default start-ost is
</entry>
<entry>
<para>Name of the pre-defined pool of OSTs (see
- <xref linkend="dbdoclet.50438219_38274" />) that will be used
+ <xref linkend="lctl" />) that will be used
for striping. The
<literal>stripe_cnt</literal>,
<literal>stripe_size</literal> and
<literal>quota [-q] [-v] [-o
<replaceable>obd_uuid</replaceable>|-i
<replaceable>mdt_idx</replaceable>|-I
- <replaceable>ost_idx</replaceable>] [-u|-g
- <replaceable>uname|uid|gname|gid]</replaceable>
+ <replaceable>ost_idx</replaceable>] [-u|-g|-p
+ <replaceable>uname|uid|gname|gid|projid]</replaceable>
<replaceable>/mount_point</replaceable></literal>
</para>
<para> </para>
<entry>
<para>Displays disk usage and limits, either for the full file
system or for objects on a specific OBD. A user or group name
- or an ID can be specified. If both user and group are omitted,
- quotas for the current UID/GID are shown. The
- <literal>-q</literal> option disables printing of additional
- descriptions (including column titles). It fills in blank
- spaces in the
+ or an usr, group and project ID can be specified. If all user,
+ group project ID are omitted, quotas for the current UID/GID
+ are shown. The <literal>-q</literal> option disables printing
+ of additional descriptions (including column titles). It fills
+ in blank spaces in the
<literal>grace</literal> column with zeros (when there is no
grace period set), to ensure that the number of columns is
consistent. The
<entry nameend="c2" namest="c1">
<para>
<literal>quota -t
- <replaceable>-u|-g</replaceable>
+ <replaceable>-u|-g|-p</replaceable>
<replaceable>/mount_point</replaceable></literal>
</para>
</entry>
<entry>
<para>Displays block and inode grace times for user (
<literal>-u</literal>) or group (
- <literal>-g</literal>) quotas.</para>
- </entry>
- </row>
- <row>
- <entry nameend="c2" namest="c1">
- <para>
- <literal>quotachown</literal>
- </para>
- </entry>
- <entry>
- <para>Changes the file's owner and group on OSTs of the
- specified file system.</para>
- </entry>
- </row>
- <row>
- <entry nameend="c2" namest="c1">
- <para>
- <literal>quotacheck [-ugf]
- <replaceable>/mount_point</replaceable></literal>
- </para>
- </entry>
- <entry>
- <para>Scans the specified file system for disk usage, and
- creates or updates quota files. Options specify quota for users
- (
- <literal>-u</literal>), groups (
- <literal>-g</literal>), and force (
- <literal>-f</literal>).</para>
- </entry>
- </row>
- <row>
- <entry nameend="c2" namest="c1">
- <para>
- <literal>quotaon [-ugf]
- <replaceable>/mount_point</replaceable></literal>
- </para>
- </entry>
- <entry>
- <para>Turns on file system quotas. Options specify quota for
- users (
- <literal>-u</literal>), groups (
- <literal>-g</literal>), and force (
- <literal>-f</literal>).</para>
- </entry>
- </row>
- <row>
- <entry nameend="c2" namest="c1">
- <para>
- <literal>quotaoff [-ugf]
- <replaceable>/mount_point</replaceable></literal>
- </para>
- </entry>
- <entry>
- <para>Turns off file system quotas. Options specify quota for
- users (
- <literal>-u</literal>), groups (
- <literal>-g</literal>), and force (
- <literal>-f</literal>).</para>
- </entry>
- </row>
- <row>
- <entry nameend="c2" namest="c1">
- <para>
- <literal>quotainv [-ug] [-f]
- <replaceable>/mount_point</replaceable></literal>
- </para>
- </entry>
- <entry>
- <para>Clears quota files (administrative quota files if used
- without
- <literal>-f</literal>, operational quota files otherwise), all
- of their quota entries for users (
- <literal>-u</literal>) or groups (
- <literal>-g</literal>). After running
- <literal>quotainv</literal>, you must run
- <literal>quotacheck</literal> before using quotas.</para>
- <caution>
- <para>Use extreme caution when using this command; its
- results cannot be undone.</para>
- </caution>
+ <literal>-g</literal>) or project (
+ <literal>-p</literal>) quotas.</para>
</entry>
</row>
<row>
<entry nameend="c2" namest="c1">
<para>
- <literal>setquota -u|-g
- <replaceable>
- uname|uid|gname|gid}</replaceable>[--block-softlimit
+ <literal>setquota {-u|-g|-p
+ <replaceable>uname|uid|gname|gid|projid}</replaceable>
+ [--block-softlimit
<replaceable>block_softlimit</replaceable>]
[--block-hardlimit
<replaceable>block_hardlimit</replaceable>]
</para>
</entry>
<entry>
- <para>Sets file system quotas for users or groups. Limits can
- be specified with
+ <para>Sets file system quotas for users, groups or one project.
+ Limits can be specified with
<literal>--{block|inode}-{softlimit|hardlimit}</literal> or
their short equivalents
<literal>-b</literal>,
2^30, 2^40 and 2^50, respectively. By default, the block limits
unit is 1 kilobyte (1,024), and block limits are always
kilobyte-grained (even if specified in bytes). See
- <xref linkend="dbdoclet.50438206_11903" />.</para>
+ <xref linkend="setquota_grace_time_example" />.</para>
</entry>
</row>
<row>
<entry nameend="c2" namest="c1">
<para>
- <literal>setquota -t -u|-g [--block-grace
+ <literal>setquota -t -u|-g|-p [--block-grace
<replaceable>block_grace</replaceable>] [--inode-grace
<replaceable>inode_grace</replaceable>]
<replaceable>/mount_point</replaceable></literal>
groups. Grace time is specified in '
<literal>XXwXXdXXhXXmXXs</literal>' format or as an integer
seconds value. See
- <xref linkend="dbdoclet.50438206_11903" />.</para>
+ <xref linkend="setquota_grace_time_example" />.</para>
</entry>
</row>
<row>
</tgroup>
</informaltable>
</section>
- <section remap="h5">
- <title xml:id="dbdoclet.50438206_11903">Examples</title>
+ <section remap="h5" xml:id="setquota_grace_time_example">
+ <title>Examples</title>
<para>Creates a file striped on two OSTs with 128 KB on each
stripe.</para>
<screen>
<screen>
$ lfs quota -u bob /mnt/lustre
</screen>
+ <para>List quotas of project ID '1'.</para>
+ <screen>
+$ lfs quota -p 1 /mnt/lustre
+</screen>
<para>Show grace times for user quotas on
<literal>/mnt/lustre</literal>.</para>
<screen>
$ lfs quota -t -u /mnt/lustre
</screen>
- <para>Changes file owner and group.</para>
- <screen>
-$ lfs quotachown -i /mnt/lustre
-</screen>
- <para>Checks quotas for user and group. Turns on quotas after making the
- check.</para>
- <screen>
-$ lfs quotacheck -ug /mnt/lustre
-</screen>
- <para>Turns on quotas of user and group.</para>
- <screen>
-$ lfs quotaon -ug /mnt/lustre
-</screen>
- <para>Turns off quotas of user and group.</para>
- <screen>
-$ lfs quotaoff -ug /mnt/lustre
-</screen>
<para>Sets quotas of user 'bob', with a 1 GB block quota hardlimit and a
2 GB block quota softlimit.</para>
<screen>
<section remap="h5">
<title>See Also</title>
<para>
- <xref linkend="dbdoclet.50438219_38274" />
+ <xref linkend="lctl" />
</para>
</section>
</section>
- <section xml:id="dbdoclet.50438206_42260">
+ <section xml:id="lfs_migrate">
<title>
<indexterm>
<primary>lfs_migrate</primary>
<literal>lfs_migrate</literal>
</title>
<para>The
- <literal>lfs_migrate</literal> utility is a simple tool to migrate files
- between Lustre OSTs.</para>
+ <literal>lfs_migrate</literal> utility is a simple to migrate file
+ <emphasis>data</emphasis> between OSTs.</para>
<section remap="h5">
<title>Synopsis</title>
<screen>
-lfs_migrate [-c <replaceable>stripecount</replaceable>] [-h] [-l] [-n] [-q] [-R] [-s] [-y]
-[file|directory ...]
+lfs_migrate [<replaceable>lfs_setstripe_options</replaceable>]
+ [-h] [-n] [-q] [-R] [-s] [-y] [-0] [file|directory ...]
</screen>
</section>
<section remap="h5">
<title>Description</title>
<para>The
- <literal>lfs_migrate</literal> utility is a simple tool to assist
- migration of files between Lustre OSTs. The utility copies each specified
- file to a new file, verifies the file contents have not changed, and then
- renames the new file to the original filename. This allows balanced space
- usage between OSTs, moving files off OSTs that are starting to show
- hardware problems (though are still functional) or OSTs that will be
- discontinued.</para>
+ <literal>lfs_migrate</literal> utility is a tool to assist migration
+ of file data between Lustre OSTs. The utility copies each specified
+ file to a temporary file using supplied <literal>lfs setstripe</literal>
+ options, if any, optionally verifies the file contents have not changed,
+ and then swaps the layout (OST objects) from the temporary file and the
+ original file (for Lustre 2.5 and later), or renames the temporary file
+ to the original filename. This allows the user/administrator to balance
+ space usage between OSTs, or move files off OSTs that are starting to show
+ hardware problems (though are still functional) or will be removed.</para>
<warning>
<para>For versions of Lustre before 2.5,
- <literal>lfs_migrate</literal> is not closely integrated with the MDS,
- it cannot determine whether a file is currently open and/or in-use by
- other applications or nodes. This makes it UNSAFE for use on files that
- might be modified by other applications, since the migrated file is
- only a copy of the current file. This results in the old file becoming
- an open-unlinked file and any modifications to that file are
- lost.</para>
+ <literal>lfs_migrate</literal> was not integrated with the MDS at all.
+ That made it UNSAFE for use on files that were being modified by other
+ applications, since the file was migrated through a copy and rename of
+ the file. With Lustre 2.5 and later, the new file layout is swapped
+ with the existing file layout, which ensures that the user-visible
+ inode number is kept, and open file handles and locks on the file are
+ kept.</para>
</warning>
<para>Files to be migrated can be specified as command-line arguments. If
a directory is specified on the command-line then all files within the
directory are migrated. If no files are specified on the command-line,
then a list of files is read from the standard input, making
<literal>lfs_migrate</literal> suitable for use with
- <literal>lfs</literal> find to locate files on specific OSTs and/or
- matching other file attributes.</para>
- <para>The current file allocation policies on the MDS dictate where the
- new files are placed, taking into account whether specific OSTs have been
- disabled on the MDS via
- <literal>lctl</literal>(preventing new files from being allocated there),
- whether some OSTs are overly full (reducing the number of files placed on
- those OSTs), or if there is a specific default file striping for the
- target directory (potentially changing the stripe count, stripe size, OST
- pool, or OST index of a new file).</para>
+ <literal>lfs find</literal> to locate files on specific OSTs and/or
+ matching other file attributes, and other tools that generate a list
+ of files on standard output.</para>
+ <para>Unless otherwise specified through command-line options, the
+ file allocation policies on the MDS dictate where the new files
+ are placed, taking into account whether specific OSTs have been
+ disabled on the MDS via <literal>lctl</literal> (preventing new
+ files from being allocated there), whether some OSTs are overly full
+ (reducing the number of files placed on those OSTs), or if there is
+ a specific default file striping for the parent directory (potentially
+ changing the stripe count, stripe size, OST pool, or OST index of a
+ new file).</para>
<note>
<para>The
<literal>lfs_migrate</literal> utility can also be used in some cases to
reduced fragmentation. The tool
<literal>filefrag</literal> can be used to report file fragmentation.
See
- <xref linkend="dbdoclet.50438206_75125" /></para>
+ <xref linkend="filefrag" /></para>
</note>
<note>
<para>As long as a file has extent lengths of tens of megabytes (
scripts, use with caution).</para>
</entry>
</row>
+ <row>
+ <entry>
+ <literal>-0</literal>
+ </entry>
+ <entry>Expect NUL-terminated filenames on standard input, as
+ generated by <literal>lfs find -print0</literal> or
+ <literal>find -print0</literal>. This allows filenames with
+ embedded newlines to be handled correctly.
+ </entry>
+ </row>
</tbody>
</tgroup>
</informaltable>
</section>
<section remap="h5">
<title>Examples</title>
- <para>Rebalances all files in
- <literal>/mnt/lustre/dir</literal>.</para>
+ <para>Rebalance all files in
+ <literal>/mnt/lustre/dir</literal>:</para>
<screen>
-$ lfs_migrate /mnt/lustre/file
+$ lfs_migrate /mnt/lustre/dir
</screen>
- <para>Migrates files in /test filesystem on OST004 larger than 4 GB in
- size.</para>
+ <para>Migrate files in /test filesystem on OST0004 larger than 4 GB in
+ size and older than a day old:</para>
<screen>
-$ lfs find /test -obd test-OST004 -size +4G | lfs_migrate -y
+$ lfs find /test -obd test-OST0004 -size +4G -mtime +1 | lfs_migrate -y
</screen>
</section>
<section remap="h5">
<title>See Also</title>
<para>
- <xref linkend="dbdoclet.50438206_94597" />
+ <xref linkend="userutilities.lfs" />
</para>
</section>
</section>
- <section xml:id="dbdoclet.50438206_75125">
+ <section xml:id="filefrag">
<title>
<indexterm>
<primary>filefrag</primary>
</screen>
</section>
</section>
- <section xml:id="dbdoclet.50438206_86244">
+ <section xml:id="mount">
<title>
<indexterm>
<primary>mount</primary>
</para>
</entry>
<entry>
- <para condition="l23">Enables/disables FID to path translation by
+ <para>Enables/disables FID to path translation by
regular users</para>
</entry>
</row>
</tgroup>
</informaltable>
</section>
- <section xml:id="dbdoclet.50438206_56217">
+ <section xml:id="handling_timeouts">
<title>Handling Timeouts</title>
<para>Timeouts are the most common cause of hung applications. After a
timeout involving an MDS or failover OST, applications attempting to access
</screen>
</section>
</chapter>
+<!--
+ vim:expandtab:shiftwidth=2:tabstop=8:
+ -->