doc/en_US.ISO8859-1/articles/solid-state/article.xml
2013-11-13 07:52:45 +00:00

484 lines
22 KiB
XML

<?xml version="1.0" encoding="iso-8859-1"?>
<!DOCTYPE article PUBLIC "-//FreeBSD//DTD DocBook XML V5.0-Based Extension//EN"
"http://www.FreeBSD.org/XML/share/xml/freebsd50.dtd">
<!-- Copyright (c) 2001 The FreeBSD Documentation Project
Redistribution and use in source (SGML DocBook) and 'compiled' forms
(SGML, HTML, PDF, PostScript, RTF and so forth) with or without
modification, are permitted provided that the following conditions
are met:
1. Redistributions of source code (SGML DocBook) must retain the above
copyright notice, this list of conditions and the following
disclaimer as the first lines of this file unmodified.
2. Redistributions in compiled form (transformed to other DTDs,
converted to PDF, PostScript, RTF and other formats) must reproduce
the above copyright notice, this list of conditions and the
following disclaimer in the documentation and/or other materials
provided with the distribution.
THIS DOCUMENTATION IS PROVIDED BY THE FREEBSD DOCUMENTATION PROJECT "AS
IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL NIK CLAYTON BE LIABLE FOR ANY
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
ANY WAY OUT OF THE USE OF THIS DOCUMENTATION, EVEN IF ADVISED OF THE
POSSIBILITY OF SUCH DAMAGE.
$FreeBSD$
-->
<article xmlns="http://docbook.org/ns/docbook" xmlns:xlink="http://www.w3.org/1999/xlink" version="5.0" xml:lang="en">
<info><title>&os; and Solid State Devices</title>
<authorgroup>
<author><personname><firstname>John</firstname><surname>Kozubik</surname></personname><affiliation>
<address><email>john@kozubik.com</email></address>
</affiliation></author>
</authorgroup>
<copyright>
<year>2001</year>
<year>2009</year>
<holder>The FreeBSD Documentation Project</holder>
</copyright>
<legalnotice xml:id="trademarks" role="trademarks">
&tm-attrib.freebsd;
&tm-attrib.general;
</legalnotice>
&legalnotice;
<pubdate>$FreeBSD$</pubdate>
<releaseinfo>$FreeBSD$</releaseinfo>
<abstract>
<para>This article covers the use of solid state disk devices in
&os; to create embedded systems.</para>
<para>Embedded systems have the advantage of increased stability
due to the lack of integral moving parts (hard drives).
Account must be taken, however, for the generally low disk
space available in the system and the durability of the
storage medium.</para>
<para>Specific topics to be covered include the types and
attributes of solid state media suitable for disk use in &os;,
kernel options that are of interest in such an environment,
the <filename>rc.initdiskless</filename> mechanisms that
automate the initialization of such systems and the need for
read-only filesystems, and building filesystems from scratch.
The article will conclude with some general strategies for
small and read-only &os; environments.</para>
</abstract>
</info>
<sect1 xml:id="intro">
<title>Solid State Disk Devices</title>
<para>The scope of this article will be limited to solid state
disk devices made from flash memory. Flash memory is a solid
state memory (no moving parts) that is non-volatile (the memory
maintains data even after all power sources have been
disconnected). Flash memory can withstand tremendous physical
shock and is reasonably fast (the flash memory solutions covered
in this article are slightly slower than a EIDE hard disk for
write operations, and much faster for read operations). One
very important aspect of flash memory, the ramifications of
which will be discussed later in this article, is that each
sector has a limited rewrite capacity. You can only write,
erase, and write again to a sector of flash memory a certain
number of times before the sector becomes permanently unusable.
Although many flash memory products automatically map bad
blocks, and although some even distribute write operations
evenly throughout the unit, the fact remains that there exists a
limit to the amount of writing that can be done to the device.
Competitive units have between 1,000,000 and 10,000,000 writes
per sector in their specification. This figure varies due to
the temperature of the environment.</para>
<para>Specifically, we will be discussing ATA compatible
compact-flash units, which are quite popular as storage media
for digital cameras. Of particular interest is the fact that
they pin out directly to the IDE bus and are compatible with the
ATA command set. Therefore, with a very simple and low-cost
adaptor, these devices can be attached directly to an IDE bus in
a computer. Once implemented in this manner, operating systems
such as &os; see the device as a normal hard disk (albeit
small).</para>
<para>Other solid state disk solutions do exist, but their
expense, obscurity, and relative unease of use places them
beyond the scope of this article.</para>
</sect1>
<sect1 xml:id="kernel">
<title>Kernel Options</title>
<para>A few kernel options are of specific interest to those
creating an embedded &os; system.</para>
<para>All embedded &os; systems that use flash memory as system
disk will be interested in memory disks and memory filesystems.
Because of the limited number of writes that can be done to
flash memory, the disk and the filesystems on the disk will most
likely be mounted read-only. In this environment, filesystems
such as <filename>/tmp</filename> and <filename>/var</filename>
are mounted as memory filesystems to allow the system to create
logs and update counters and temporary files. Memory
filesystems are a critical component to a successful solid state
&os; implementation.</para>
<para>You should make sure the following lines exist in your
kernel configuration file:</para>
<programlisting>options MFS # Memory Filesystem
options MD_ROOT # md device usable as a potential root device
pseudo-device md # memory disk</programlisting>
</sect1>
<sect1 xml:id="ro-fs">
<title>The <literal>rc</literal> Subsystem and Read-Only
Filesystems</title>
<para>The post-boot initialization of an embedded &os; system is
controlled by <filename>/etc/rc.initdiskless</filename>.</para>
<para><filename>/etc/rc.d/var</filename> mounts
<filename>/var</filename> as a memory filesystem, makes a
configurable list of directories in <filename>/var</filename>
with the &man.mkdir.1; command, and changes modes on some of
those directories. In the execution of
<filename>/etc/rc.d/var</filename>, one other
<filename>rc.conf</filename> variable comes into play &ndash;
<literal>varsize</literal>. The
<filename>/etc/rc.d/var</filename> file creates a
<filename>/var</filename> partition based on the value of
this variable in <filename>rc.conf</filename>:</para>
<programlisting>varsize=8192</programlisting>
<para>Remember that this value is in sectors by default.</para>
<para>The fact that <filename>/var</filename> is a read-write
filesystem is an important distinction, as the
<filename>/</filename> partition (and any other partitions you
may have on your flash media) should be mounted read-only.
Remember that in <xref linkend="intro"/> we detailed the
limitations of flash memory - specifically the limited write
capability. The importance of not mounting filesystems on flash
media read-write, and the importance of not using a swap file,
cannot be overstated. A swap file on a busy system can burn
through a piece of flash media in less than one year. Heavy
logging or temporary file creation and destruction can do the
same. Therefore, in addition to removing the
<literal>swap</literal> entry from your
<filename>/etc/fstab</filename> file, you should also change the
Options field for each filesystem to <literal>ro</literal> as
follows:</para>
<programlisting># Device Mountpoint FStype Options Dump Pass#
/dev/ad0s1a / ufs ro 1 1</programlisting>
<para>A few applications in the average system will immediately
begin to fail as a result of this change. For instance, cron
will not run properly as a result of missing cron tabs in the
<filename>/var</filename> created by
<filename>/etc/rc.d/var</filename>, and syslog and dhcp will
encounter problems as well as a result of the read-only
filesystem and missing items in the <filename>/var</filename>
that <filename>/etc/rc.d/var</filename> has created. These are
only temporary problems though, and are addressed, along with
solutions to the execution of other common software packages in
<xref linkend="strategies"/>.</para>
<para>An important thing to remember is that a filesystem that was
mounted read-only with <filename>/etc/fstab</filename> can be
made read-write at any time by issuing the command:</para>
<screen>&prompt.root; <userinput>/sbin/mount -uw partition</userinput></screen>
<para>and can be toggled back to read-only with the command:</para>
<screen>&prompt.root; <userinput>/sbin/mount -ur partition</userinput></screen>
</sect1>
<sect1>
<title>Building a File System From Scratch</title>
<para>Because ATA compatible compact-flash cards are seen by &os;
as normal IDE hard drives, you could theoretically install &os;
from the network using the kern and mfsroot floppies or from a
CD.</para>
<para>However, even a small installation of &os; using normal
installation procedures can produce a system in size of greater
than 200 megabytes. Because most people will be using smaller
flash memory devices (128 megabytes is considered fairly large -
32 or even 16 megabytes is common) an installation using normal
mechanisms is not possible&mdash;there is simply not enough disk
space for even the smallest of conventional
installations.</para>
<para>The easiest way to overcome this space limitation is to
install &os; using conventional means to a normal hard disk.
After the installation is complete, pare down the operating
system to a size that will fit onto your flash media, then tar
the entire filesystem. The following steps will guide you
through the process of preparing a piece of flash memory for
your tarred filesystem. Remember, because a normal installation
is not being performed, operations such as partitioning,
labeling, file-system creation, etc. need to be performed by
hand. In addition to the kern and mfsroot floppy disks, you
will also need to use the fixit floppy.</para>
<procedure>
<step>
<title>Partitioning your flash media device</title>
<para>After booting with the kern and mfsroot floppies, choose
<literal>custom</literal> from the installation menu. In
the custom installation menu, choose
<literal>partition</literal>. In the partition menu, you
should delete all existing partitions using the
<keycap>d</keycap> key. After deleting all existing
partitions, create a partition using the <keycap>c</keycap>
key and accept the default value for the size of the
partition. When asked for the type of the partition, make
sure the value is set to <literal>165</literal>. Now write
this partition table to the disk by pressing the
<keycap>w</keycap> key (this is a hidden option on this
screen). If you are using an ATA compatible compact flash
card, you should choose the &os; Boot Manager. Now press
the <keycap>q</keycap> key to quit the partition menu. You
will be shown the boot manager menu once more - repeat the
choice you made earlier.</para>
</step>
<step>
<title>Creating filesystems on your flash memory
device</title>
<para>Exit the custom installation menu, and from the main
installation menu choose the <literal>fixit</literal>
option. After entering the fixit environment, enter the
following command:</para>
<screen>&prompt.root; <userinput>disklabel -e /dev/ad0c</userinput></screen>
<para>At this point you will have entered the vi editor under
the auspices of the disklabel command. Next, you need to
add an <literal>a:</literal> line at the end of the file.
This <literal>a:</literal> line should look like:</para>
<programlisting>a: <replaceable>123456</replaceable> 0 4.2BSD 0 0</programlisting>
<para>Where <replaceable>123456</replaceable> is a number that
is exactly the same as the number in the existing
<literal>c:</literal> entry for size. Basically you are
duplicating the existing <literal>c:</literal> line as an
<literal>a:</literal> line, making sure that fstype is
<literal>4.2BSD</literal>. Save the file and exit.</para>
<screen>&prompt.root; <userinput>disklabel -B -r /dev/ad0c</userinput>
&prompt.root; <userinput>newfs /dev/ad0a</userinput></screen>
</step>
<step>
<title>Placing your filesystem on the flash media</title>
<para>Mount the newly prepared flash media:</para>
<screen>&prompt.root; <userinput>mount /dev/ad0a /flash</userinput></screen>
<para>Bring this machine up on the network so we may transfer
our tar file and explode it onto our flash media filesystem.
One example of how to do this is:</para>
<screen>&prompt.root; <userinput>ifconfig xl0 192.168.0.10 netmask 255.255.255.0</userinput>
&prompt.root; <userinput>route add default 192.168.0.1</userinput></screen>
<para>Now that the machine is on the network, transfer your
tar file. You may be faced with a bit of a dilemma at this
point - if your flash memory part is 128 megabytes, for
instance, and your tar file is larger than 64 megabytes, you
cannot have your tar file on the flash media at the same
time as you explode it - you will run out of
space. One solution to this problem, if you are using FTP,
is to untar the file while it is transferred over FTP. If
you perform your transfer in this manner, you will never
have the tar file and the tar contents on your disk at the
same time:</para>
<screen><prompt>ftp&gt;</prompt> <userinput>get tarfile.tar "| tar xvf -"</userinput></screen>
<para>If your tarfile is gzipped, you can accomplish this as
well:</para>
<screen><prompt>ftp&gt;</prompt> <userinput>get tarfile.tar "| zcat | tar xvf -"</userinput></screen>
<para>After the contents of your tarred filesystem are on your
flash memory filesystem, you can unmount the flash memory
and reboot:</para>
<screen>&prompt.root; <userinput>cd /</userinput>
&prompt.root; <userinput>umount /flash</userinput>
&prompt.root; <userinput>exit</userinput></screen>
<para>Assuming that you configured your filesystem correctly
when it was built on the normal hard disk (with your
filesystems mounted read-only, and with the necessary
options compiled into the kernel) you should now be
successfully booting your &os; embedded system.</para>
</step>
</procedure>
</sect1>
<sect1 xml:id="strategies">
<title>System Strategies for Small and Read Only
Environments</title>
<para>In <xref linkend="ro-fs"/>, it was pointed out that the
<filename>/var</filename> filesystem constructed by
<filename>/etc/rc.d/var</filename> and the presence of a
read-only root filesystem causes problems with many common
software packages used with &os;. In this article, suggestions
for successfully running cron, syslog, ports installations, and
the Apache web server will be provided.</para>
<sect2>
<title>cron</title>
<para>Upon boot, <filename>/var</filename>
gets populated by <filename>/etc/rc.d/var</filename> using the
list from <filename>/etc/mtree/BSD.var.dist</filename>, so the
<filename>cron</filename>, <filename>cron/tabs</filename>, <filename>at</filename>, and a few other standard
directories get created.</para>
<para>However, this does not solve the problem of maintaining
cron tabs across reboots. When the system reboots, the
<filename>/var</filename> filesystem that is in memory will
disappear and any cron tabs you may have had in it will also
disappear. Therefore, one solution would be to create cron
tabs for the users that need them, mount your
<filename>/</filename> filesystem as read-write and copy those
cron tabs to somewhere safe, like
<filename>/etc/tabs</filename>, then add a line to the end of
<filename>/etc/rc.initdiskless</filename> that copies those
crontabs into <filename>/var/cron/tabs</filename> after that
directory has been created during system initialization. You
may also need to add a line that changes modes and permissions
on the directories you create and the files you copy with
<filename>/etc/rc.initdiskless</filename>.</para>
</sect2>
<sect2>
<title>syslog</title>
<para><filename>syslog.conf</filename> specifies the locations
of certain log files that exist in
<filename>/var/log</filename>. These files are not created by
<filename>/etc/rc.d/var</filename> upon system initialization.
Therefore, somewhere in <filename>/etc/rc.d/var</filename>,
after the section that creates the directories in
<filename>/var</filename>, you will need to add something like
this:</para>
<screen>&prompt.root; <userinput>touch /var/log/security /var/log/maillog /var/log/cron /var/log/messages</userinput>
&prompt.root; <userinput>chmod 0644 /var/log/*</userinput></screen>
</sect2>
<sect2>
<title>Ports Installation</title>
<para>Before discussing the changes necessary to successfully
use the ports tree, a reminder is necessary regarding the
read-only nature of your filesystems on the flash media.
Since they are read-only, you will need to temporarily mount
them read-write using the mount syntax shown in <xref linkend="ro-fs"/>. You should always remount those
filesystems read-only when you are done with any maintenance -
unnecessary writes to the flash media could considerably
shorten its lifespan.</para>
<para>To make it possible to enter a ports directory and
successfully run
<command>make</command> <buildtarget>install</buildtarget>, we
must create a packages directory on a non-memory filesystem
that will keep track of our packages across reboots. Because
it is necessary to mount your filesystems as read-write for
the installation of a package anyway, it is sensible to assume
that an area on the flash media can also be used for package
information to be written to.</para>
<para>First, create a package database directory. This is
normally in <filename>/var/db/pkg</filename>, but we cannot
place it there as it will disappear every time the system is
booted.</para>
<screen>&prompt.root; <userinput>mkdir /etc/pkg</userinput></screen>
<para>Now, add a line to <filename>/etc/rc.d/var</filename> that
links the <filename>/etc/pkg</filename> directory to
<filename>/var/db/pkg</filename>. An example:</para>
<screen>&prompt.root; <userinput>ln -s /etc/pkg /var/db/pkg</userinput></screen>
<para>Now, any time that you mount your filesystems as
read-write and install a package, the
<command>make</command> <buildtarget>install</buildtarget> will
work, and package information will be written successfully to
<filename>/etc/pkg</filename> (because the filesystem will, at
that time, be mounted read-write) which will always be
available to the operating system as
<filename>/var/db/pkg</filename>.</para>
</sect2>
<sect2>
<title>Apache Web Server</title>
<note>
<para>The steps in this section are only necessary if Apache
is set up to write its pid or log information outside of
<filename>/var</filename>. By default,
Apache keeps its pid file in <filename>/var/run/httpd.pid</filename> and its
log files in <filename>/var/log</filename>.</para>
</note>
<para>It is now assumed that Apache keeps its log files in a
directory <filename>apache_log_dir</filename>
outside of <filename>/var</filename>.
When this directory lives on a read-only filesystem, Apache
will not be able to save any log files, and may have problems
working. If so, it is necessary to add a new directory to the
list of directories in <filename>/etc/rc.d/var</filename> to
create in <filename>/var</filename>, and to link
<filename>apache_log_dir</filename>
to <filename>/var/log/apache</filename>. It is also necessary
to set permissions and ownership on this new directory.</para>
<para>First, add the directory <literal>log/apache</literal> to
the list of directories to be created in
<filename>/etc/rc.d/var</filename>.</para>
<para>Second, add these commands to
<filename>/etc/rc.d/var</filename> after the directory
creation section:</para>
<screen>&prompt.root; <userinput>chmod 0774 /var/log/apache</userinput>
&prompt.root; <userinput>chown nobody:nobody /var/log/apache</userinput></screen>
<para>Finally, remove the existing <filename>apache_log_dir</filename>
directory, and replace it with a link:</para>
<screen>&prompt.root; <userinput>rm -rf apache_log_dir</userinput>
&prompt.root; <userinput>ln -s /var/log/apache apache_log_dir</userinput></screen>
</sect2>
</sect1>
</article>