summaryrefslogtreecommitdiff
path: root/kernel-devel
diff options
context:
space:
mode:
authorManuel Traut <manut@linutronix.de>2011-07-18 14:04:20 +0200
committerManuel Traut <manut@linutronix.de>2011-07-18 14:04:20 +0200
commit5cd3321d946c14cd99d6a23cffa09a8316aadceb (patch)
treeee42f905f7e62edd61103d4965a0aa037d861ffc /kernel-devel
parentf9f7f47856be59b1e446a846d4b0306c39a6186c (diff)
parenta794d7231410f16747e44b690fcc03a96274894c (diff)
Merge ../../../vorlesung into vorlesung
Diffstat (limited to 'kernel-devel')
-rw-r--r--kernel-devel/kernel-basics/pres_kernel-basics_de.tex263
-rw-r--r--kernel-devel/kernel-best-practices/handout_kernel-best-practices_en.tex498
2 files changed, 761 insertions, 0 deletions
diff --git a/kernel-devel/kernel-basics/pres_kernel-basics_de.tex b/kernel-devel/kernel-basics/pres_kernel-basics_de.tex
index 372ada2..1cfb985 100644
--- a/kernel-devel/kernel-basics/pres_kernel-basics_de.tex
+++ b/kernel-devel/kernel-basics/pres_kernel-basics_de.tex
@@ -56,6 +56,61 @@
\end{itemize}
\end{frame}
+\begin{frame}
+\includegraphics[height=7cm]{images/linus7.jpg}
+
+Maintains: THE REST
+
+Company: linuxfoundation
+\end{frame}
+
+\begin{frame}
+\includegraphics[height=7cm]{images/alan.png}
+
+Credits: NET2Debugged/NET3 author, Network layer debugging, Initial AX.25 and
+IPX releases, Original Linux netatalk patches, Current 3c501 hacker, Watchdog
+timer drivers, Linux/SMP
+
+Company: intel
+\end{frame}
+
+\begin{frame}
+\includegraphics[height=7cm]{images/morton.jpg}
+
+Maintains: EXT3, JOURNALLING LAYER FOR BLOCK DEVICES (JBD)
+
+Credits: Linux Quality Management
+
+Company: Google
+\end{frame}
+
+\begin{frame}
+\includegraphics[height=7cm]{images/greg.jpg}
+
+Maintains: SERIAL DRIVER, DRIVER CORE, KOBJECTS, DEBUGFS AND SYSFS, STABLE
+BRANCH, STAGING SUBSYSTEM, TTY LAYER, USB SERIAL DRIVER, USB SUBSYSTEM,
+USERSPACE I/O
+
+Company: SuSE
+\end{frame}
+
+\begin{frame}
+\includegraphics[height=7cm]{images/hch.jpg}
+
+Maintains: FREEVXFS FILESYSTEM, PERSONALITY HANDLING, SYSV FILESYSTEM, XFS
+FILESYSTEM
+Company: ??
+\end{frame}
+
+\begin{frame}
+\includegraphics[height=7cm]{images/tglx.jpg}
+
+Maintains: HIGH-RESOLUTION TIMERS, CLOCKEVENTS, DYNTICKS, POSIX CLOCKS and
+TIMERS, X86 ARCHITECTURE (32-BIT AND 64-BIT), PREEMPT RT
+
+Company: linutronix
+\end{frame}
+
\subsubsection{Entwicklungsprozess}
\begin{frame}
\frametitle{Entwicklungsprozess}
@@ -63,13 +118,221 @@
\item Änderungsvorschläge in Form von Patchen
\pause
\item Review und Diskussion auf Mailinglisten
+\item z.B. Subsystem Mailinglisten und LKML
\pause
\item strenge Richtlinien für Coding Style
+\item siehe Documentation/CodingStyle im Kernel Source Tree
\pause
\item strenge Richtlinien für Form und Weitergabe von Patchen
+\item scripts/checkpatch.pl zur Kontrolle verwenden!
\pause
\item Nur technische Argumente zählen!
+\pause
+\item Dokumentation siehe MAINTAINER Datei im Kernel Source Tree
+\end{itemize}
+\end{frame}
+
+\subsubsection{Versionierung}
+\begin{frame}
+\frametitle{Versionierung}
+\begin{itemize}
+\item 2.6.38.1 oder 2.6.39-rc1
+\pause
+\item 2.6 - historisch gegeben (aus altem Schema)
+\pause
+\item .38 - aktuelle Version
+\pause
+\item .1 - Security Fix
+\pause
+\item .rc1 - Release Candidate
+\end{itemize}
+\end{frame}
+
+\subsubsection{Entwicklungstempo}
+\begin{frame}
+\frametitle{Entwicklungstempo}
+\begin{itemize}
+\item 2 \dots 3 months release cycle
+\item \dots about 10,000 patches each cycle
+\item \dots from over 1000 developers
+\item \dots about 200 companies
+\end{itemize}
+Quelle: http://www.linuxfoundation.org/docs/lf\_linux\_kernel\_development\_2010.pdf
+\end{frame}
+
+\begin{frame}
+\includegraphics[height=7cm]{images/linux-found-devel-cycle.png}
+
+Source: Linux Foundation
+\end{frame}
+
+\begin{frame}
+\includegraphics[height=6.5cm]{images/linux-found-changes-version.png}
+\begin{tabular}{ l | l| }
+2.6.25 & 12,243 \\
+2.6.26 & 9,941 \\
+2.6.27 & 10,628 \\
+2.6.28 & 9,048 \\
+2.6.29 & 11,678 \\
+2.6.30 & 11,989 \\
+2.6.31 & 10,883 \\
+2.6.32 & 10,989 \\
+2.6.33 & 10,871 \\
+2.6.34 & 9,443 \\
+2.6.35 & 9,801 \\
+\end{tabular}
+
+Source: Linux Foundation
+\end{frame}
+
+\begin{frame}
+\includegraphics[height=6.5cm]{images/linux-found-changes-hour.png}
+\begin{tabular}{ l | l| }
+2.6.25 & 6.15 \\
+2.6.26 & 4.71 \\
+2.6.27 & 5.03 \\
+2.6.28 & 4.96 \\
+2.6.29 & 5.47 \\
+2.6.30 & 6.40 \\
+2.6.31 & 4.93 \\
+2.6.32 & 5.46 \\
+2.6.33 & 5.39 \\
+2.6.34 & 4.86 \\
+2.6.35 & 5.30 \\
+\end{tabular}
+
+Source: Linux Foundation
+\end{frame}
+
+\begin{frame}
+\frametitle{Kernel size}
+\begin{tabular}{ l | l | r }
+Version & Files & Lines \\
+\hline
+2.6.11 & 17,090 & 6,624,076 \\
+2.6.13 & 18,090 & 6,988,800 \\
+2.6.15 & 18,811 & 7,290,070 \\
+2.6.17 & 19,553 & 7,588,014 \\
+2.6.19 & 20,936 & 7,976,221 \\
+2.6.21 & 21,614 & 8,246,517 \\
+2.6.23 & 22,530 & 8,566,606 \\
+2.6.25 & 23,813 & 9,232,592 \\
+2.6.27 & 24,356 & 9,630,074 \\
+2.6.29 & 26,702 & 10,934,554 \\
+2.6.31 & 29,143 & 11,970,124 \\
+2.6.33 & 31,584 & 12,912,684 \\
+2.6.35 & 33,335 & 13,468,253 \\
+\end{tabular}
+
+Source: Linux Foundation
+\end{frame}
+
+\begin{frame}
+\frametitle{Kernel lines per day}
+\begin{tabular}{ l | r | l | r }
+Version & Added & Deleted & Modified \\
+\hline
+2.6.11 & 3,224 & 1,360 & 1,290 \\
+2.6.13 & 4,443 & 1,553 & 1,711 \\
+2.6.15 & 5,614 & 3,454 & 2,219 \\
+2.6.17 & 3,635 & 2,469 & 1,329 \\
+2.6.19 & 6,013 & 2,900 & 1,862 \\
+2.6.21 & 3,256 & 1,479 & 982 \\
+2.6.23 & 3,747 & 3,034 & 1,343 \\
+2.6.25 & 7,980 & 3,488 & 2,430 \\
+2.6.27 & 12,270 & 9,791 & 2,102 \\
+2.6.29 & 14,678 & 5,516 & 2,454 \\
+2.6.31 & 9,408 & 4,962 & 1,635 \\
+2.6.33 & 8,925 & 4,379 & 2,841 \\
+2.6.35 & 7,896 & 5,037 & 1,802 \\
+\end{tabular}
+
+Source: Linux Foundation
+\end{frame}
+
+\begin{frame}
+\frametitle{Linux Companies}
+contribution between 2.6.11 and 2.6.35
+\begin{tabular}{ l | r | r }
+Company & Changes & Percent of Total \\
+\hline
+None & 35,663 & 18.9 \\
+Red Hat & 23,356 & 12.4 \\
+Novell & 13,120 & 7.0 \\
+IBM & 13,026 & 6.9 \\
+Unknown & 12,060 & 6.4 \\
+Intel & 11,028 & 5.8 \\
+consultants & 4,817 & 2.6 \\
+Oracle & 4,367 & 2.3 \\
+Renesas Technology & 2,621 & 1.4 \\
+The Linux Foundation & 2,488 & 1.3 \\
+academics & 2,464 & 1.3 \\
+SGI & 2,450 & 1.3 \\
+Fujitsu & 2,293 & 1.2 \\
+Parallels & 2,226 & 1.2 \\
+Analog Devices & 1,955 & 1.0 \\
+Nokia & 1,896 & 1.0 \\
+\end{tabular}
+\end{frame}
+
+\begin{frame}
+\frametitle{Linux Companies (cont.)}
+contribution between 2.6.11 and 2.6.35
+\begin{tabular}{ l | r | r }
+Company & Changes & Percent of Total \\
+\hline
+HP & 1,854 & 1.0 \\
+MontaVista & 1,821 & 1.0 \\
+Google & 1,565 & 0.8 \\
+AMD & 1,518 & 0.8 \\
+Freescale & 1,501 & 0.8 \\
+linutronix & 1,470 & 0.8 \\
+MIPS Technologies & 1,410 & 0.7 \\
+NetApp & 1,322 & 0.7 \\
+Marvell & 1,241 & 0.7 \\
+Atheros Communications & 1,234 & 0.7 \\
+Astaro & 1,222 & 0.6 \\
+Broadcom & 1,130 & 0.6 \\
+QLogic & 1,076 & 0.6 \\
+NTT & 1,068 & 0.6 \\
+\end{tabular}
+
+Source: Linux Foundation
+\end{frame}
+
+\subsubsection{staging und next}
+\begin{frame}
+\frametitle{staging}
+\begin{itemize}
+\item Verzeichnis im Kernelsourcetree
+\pause
+\item erm\"oglicht Entwicklung im Mainline Tree
+\pause
+\item enth\"alt haupts\"achlich Treiber
+\pause
+\item Voraussetzung: aktive Weiterentwicklung im Code
+\end{itemize}
+\end{frame}
+
+\begin{frame}[fragile]
+\frametitle{next}
+\begin{itemize}
+\item \"Anderungen welche vermutlich in die n\"achste Version aufgenommen
+werden
+\item tracked andere Trees und quilt queues
\end{itemize}
+\begin{lstlisting}
+Feb-2008, Stephen Rothwell:
+I hope to recreate this tree every day automatically.
+In order to do this, any tree that has a conflict will
+be dropped from that days tree.
+The maintainer will be notified. I hope to provide some
+clue as to what the conflict is with, but probably not
+initially. I will attempt to build the tree between each
+merge (and a failed build will again cause the offending
+tree to be dropped). These builds will be necessarily
+restricted to probably one architecture/config.
+\end{lstlisting}
\end{frame}
\subsubsection{Konfiguration}
diff --git a/kernel-devel/kernel-best-practices/handout_kernel-best-practices_en.tex b/kernel-devel/kernel-best-practices/handout_kernel-best-practices_en.tex
new file mode 100644
index 0000000..bd1140b
--- /dev/null
+++ b/kernel-devel/kernel-best-practices/handout_kernel-best-practices_en.tex
@@ -0,0 +1,498 @@
+\input{confighandout}
+
+\subsection{Kernel Best-Practices}
+
+Linux development is heavily distributed. There are many powerful tools, which
+assist the distributed development. The most important and powerful ones, will
+be presented in this chapter.
+
+\subsubsection{diff and patch - the basics}
+
+Linux kernel development is based on patches. A patch is a file which describes
+the changes between an original version of a source tree and a modified one.
+
+For simplicity, a source tree with only one file will be used as example:
+
+orig/hello.c
+
+\begin{lstlisting}
+int main (int argc, char **argv)
+{
+ return 0;
+}
+\end{lstlisting}
+
+This source tree will be copied:
+
+\begin{lstlisting}
+cp -a orig new
+\end{lstlisting}
+
+The new source tree be modified:
+
+new/hello.c
+
+\begin{lstlisting}
+#include <stdio.h>
+
+int main (int argc, char **argv)
+{
+ printf ("Huhu World\n");
+ return 0;
+}
+\end{lstlisting}
+
+The diff commands generates a patch file:
+
+\begin{lstlisting}
+diff -Nur orig new > hello.patch
+\end{lstlisting}
+
+The content of hello.patch is:
+
+\begin{lstlisting}
+--- orig/hello.c 2011-03-22 22:38:40.796426752 +0100
++++ new/hello.c 2011-03-22 22:39:02.472155769 +0100
+@@ -1,4 +1,7 @@
++#include <stdio.h>
++
+ int main (int argc, char **argv)
+ {
++ printf ("Huhu World\n");
+ return 0;
+ }
+\end{lstlisting}
+
+The newly added lines are prefixed with a '+', removed lines with a '-'.
+
+If the patch file is more complex, diffstat informs you about the content:
+
+\begin{lstlisting}
+diffstat hello.patch
+ hello.c | 3 +++
+ 1 file changed, 3 insertions(+)
+\end{lstlisting}
+
+Anyone who has the original source version, can apply the generated patch. The
+result is an updated version of the source tree:
+
+\begin{lstlisting}
+cd orig
+patch -p1 < ../hello.patch
+\end{lstlisting}
+
+With the argument -pX the numbers of stripped directories (in our case new) can be defined.
+
+With the argument -R a patch can be 'reverse applied' aka removed. The result
+will be the original source tree.
+
+Don't apply or remove the same patch more then once. If you have more than one
+patch, apply and revert the patches in the right order. Else the resulting
+source tree will be undefined.
+
+If the original source differs from the one, the patch was created. The patch
+may apply with 'HUNKS'. This means, the changes can be applied, but the line
+numbers, given after the @@@ tag don't fit exactly.
+
+If the original source differs from the one, the patch was created. It is
+possible, that the patch won't apply anymore. Then all rejects are saved in a
+file called <original file name>.rej
+
+\subsubsection{quilt}
+
+diff and patch work fine for one patch. But if you have to handle a queuqe of
+patches it will be hard to keep the order of the patches, update a single patch,etc. quilt is a tool, for managing patch queques.
+
+The above example, using quilt:
+
+orig/hello.c
+
+\begin{lstlisting}
+int main (int argc, char **argv)
+{
+ return 0;
+}
+\end{lstlisting}
+
+create a new patch:
+
+\begin{lstlisting}
+cd orig
+quilt new hello.patch
+quilt edit hello.c
+\end{lstlisting}
+
+your default editor will be opened, make your changes to the source:
+
+\begin{lstlisting}
+#include <stdio.h>
+
+int main (int argc, char **argv)
+{
+ printf ("Huhu World\n");
+ return 0;
+}
+\end{lstlisting}
+
+write the changes into the patch file:
+
+\begin{lstlisting}
+quilt refresh
+\end{lstlisting}
+
+two files will be generated:
+
+\begin{lstlisting}
+ls patches/
+hello.patch series
+\end{lstlisting}
+
+hello.patch is our well-known patch. series contains the name of our patch.
+
+The patch can be applied
+
+\begin{lstlisting}
+quilt push
+File series fully applied, ends at patch patches/hello.patch
+\end{lstlisting}
+
+Then we create a new patch on top of our current queque:
+
+\begin{lstlisting}
+quilt new seperate-print-in-own-function.patch
+quilt edit hello.c
+\end{lstlisting}
+
+\begin{lstlisting}
+#include <stdio.h>
+
+void print ()
+{
+ printf ("Huhu World\n");
+}
+
+int main (int argc, char **argv)
+{
+ print ();
+ return 0;
+}
+\end{lstlisting}
+
+both patches are now listed in the series file:
+
+\begin{lstlisting}
+cat patches/series
+hello.patch
+seperate-print-in-own-function.patch
+\end{lstlisting}
+
+All patches can be reverted at once:
+
+\begin{lstlisting}
+quilt pop -a
+Removing patch patches/seperate-print-in-own-function.patch
+Restoring hello.c
+
+Removing patch patches/hello.patch
+Restoring hello.c
+
+No patches applied
+\end{lstlisting}
+
+You can zip the quilt queque and share it with other programmers.
+
+\subsubsection{git}
+
+But if they modify the quilt queque at the same time, as you. Merging the
+queques by hand may be hard. In projects like the linux kernel, it is a no go.
+
+Currently Linus' (and many others) Kernel trees are managed by git. Git is a
+very powerful version control system. The most important difference to other
+systems, like subversion, is that the hole history of a project is held local.
+Nobody should commit into your git tree. In git you pull the changes from other
+people into your tree.
+
+Let's have a look at git:
+
+orig/hello.c
+
+\begin{lstlisting}
+int main (int argc, char **argv)
+{
+ return 0;
+}
+\end{lstlisting}
+
+init git:
+
+\begin{lstlisting}
+$cd orig
+$git init .
+Initialized empty Git repository in /home/manut/vorlesung.git/orig/.git/
+$git config user.email "manut@mecka.net"
+$git config user.name "Manuel Traut"
+\end{lstlisting}
+
+The configuration is saved at .git/config
+If git config --global is used the configuration will be used by all
+repositories which don't have a own configuration. Then it is saved at
+~/.gitconfig
+
+Now add the files to version control and commit your initial code.
+
+\begin{lstlisting}
+$git add hello.c
+$git commit -sa
+\end{lstlisting}
+
+The default editor will be opened, to enter a commit message:
+
+\begin{lstlisting}
+initial import of the hello world source
+
+this projects is aimed to show the use of git.
+
+Signed-off-by: Manuel Traut <manut@mecka.net>
+
+# Please enter the commit message for your changes. Lines starting
+# with '#' will be ignored, and an empty message aborts the commit.
+# On branch master
+#
+# Initial commit
+#
+# Changes to be committed:
+# (use "git rm --cached <file>..." to unstage)
+#
+# new file: hello.c
+#
+
+[master (root-commit) 473cf10] initial import of the hello world source
+ 1 files changed, 4 insertions(+), 0 deletions(-)
+ create mode 100644 hello.c
+
+\end{lstlisting}
+
+Now edit the source tree and generate commit your changes:
+
+\begin{lstlisting}
+$patch -p1 < ../hello.patch
+$git commit -sa
+
+add stdio include, print hello world
+
+prints 'Huhu World' to stdout
+
+Signed-off-by: Manuel Traut <manut@mecka.net>
+
+# Please enter the commit message for your changes. Lines starting
+# with '#' will be ignored, and an empty message aborts the commit.
+# On branch master
+# Changes to be committed:
+# (use "git reset HEAD <file>..." to unstage)
+#
+# modified: hello.c
+
+[master 6ea27e6] add stdio include, print hello world
+ 1 files changed, 3 insertions(+), 0 deletions(-)
+
+\end{lstlisting}
+
+A hash will be generated that can be used to identify each patch. A history
+and a single patch can be displayed with these commands:
+
+\begin{lstlisting}
+$git log
+commit 6ea27e6199aeac63055d845ef40fecd4b594f1d7
+Author: Manuel Traut <manut@mecka.net>
+Date: Tue Mar 22 23:37:13 2011 +0100
+
+ add stdio include, print hello world
+
+ prints 'Huhu World' to stdout
+
+ Signed-off-by: Manuel Traut <manut@mecka.net>
+
+commit 473cf10e95778c54d49fc6ea368e196f1347ac8a
+Author: Manuel Traut <manut@mecka.net>
+Date: Tue Mar 22 23:31:50 2011 +0100
+
+ initial import of the hello world source
+
+ this projects is aimed to show the use of git.
+
+ Signed-off-by: Manuel Traut <manut@mecka.net>
+
+
+$git shortlog
+Manuel Traut (2):
+ initial import of the hello world source
+ add stdio include, print hello world
+
+$git show 473cf10e95778c54d49fc6ea368e196f1347ac8a
+commit 473cf10e95778c54d49fc6ea368e196f1347ac8a
+Author: Manuel Traut <manut@mecka.net>
+Date: Tue Mar 22 23:31:50 2011 +0100
+
+ initial import of the hello world source
+
+ this projects is aimed to show the use of git.
+
+ Signed-off-by: Manuel Traut <manut@mecka.net>
+
+diff --git a/hello.c b/hello.c
+new file mode 100644
+index 0000000..b891504
+--- /dev/null
++++ b/hello.c
+@@ -0,0 +1,4 @@
++int main (int argc, char **argv)
++{
++ return 0;
++}
+
+\end{lstlisting}
+
+To add some new functionality it's a good idea to temporarily create a new
+branch:
+
+\begin{lstlisting}
+$git branch fancy-new-stuff
+$git checkout fancy-new-stuff
+Switched to branch 'fance-new-stuff'
+\end{lstlisting}
+
+It's possible to go back in history:
+
+\begin{lstlisting}
+git reset --hard 473cf10e95778c54d49fc6ea368e196f1347ac8a
+HEAD is now at 473cf10 initial import of the hello world source
+\end{lstlisting}
+
+Make changes:
+
+\begin{lstlisting}
+#include <stdio.h>
+
+int main (int argc, char **argv)
+{
+ printf ("Hello World\n");
+ return 0;
+}
+\end{lstlisting}
+
+and commit them:
+
+\begin{lstlisting}
+$git commit -sa
+
+HELLO world
+
+..not huhu world
+
+Signed-off-by: Manuel Traut <manut@mecka.net>
+
+[fance-new-stuff 72e3346] HELLO world
+ 1 files changed, 3 insertions(+), 0 deletions(-)
+
+\end{lstlisting}
+
+You like the new version and want to merge it into your master tree:
+
+\begin{lstlisting}
+$git checkout master
+Switched to branch 'master'
+$git merge fancy-new-stuff
+Auto-merging hello.c
+CONFLICT (content): Merge conflict in hello.c
+Automatic merge failed; fix conflicts and then commit the result.
+\end{lstlisting}
+
+Git reports an CONFLICT because an automatic merge is not possible. The same
+line (printf) has different content in master and fancy-new-stuff. So the merge
+conflict has to be resolved by hand.
+
+hello.c
+
+\begin{lstlisting}
+#include <stdio.h>
+
+int main (int argc, char **argv)
+{
+<<<<<<< HEAD
+ printf ("Huhu World\n");
+=======
+ printf ("Hello World\n");
+>>>>>>> fancy-new-stuff
+ return 0;
+}
+\end{lstlisting}
+
+All lines which shouldn't be there can be removed by hand. This result needs
+to be commited:
+
+\begin{lstlisting}
+$git commit -sa
+
+Merge branch 'fance-new-stuff'
+
+Conflicts:
+ hello.c
+
+Signed-off-by: Manuel Traut <manut@mecka.net>
+#
+# It looks like you may be committing a MERGE.
+# If this is not correct, please remove the file
+# .git/MERGE_HEAD
+# and try again.
+#
+
+# Please enter the commit message for your changes. Lines starting
+# with '#' will be ignored, and an empty message aborts the commit.
+# On branch master
+# Changes to be committed:
+#
+# modified: hello.c
+#
+
+[master 1815151] Merge branch 'fance-new-stuff'
+
+$git log
+
+commit 1815151a08537bd2403605f8adb22852cfdb2d23
+Merge: 6ea27e6 72e3346
+Author: Manuel Traut <manut@mecka.net>
+Date: Tue Mar 22 23:57:19 2011 +0100
+
+ Merge branch 'fance-new-stuff'
+
+ Conflicts:
+ hello.c
+
+ Signed-off-by: Manuel Traut <manut@mecka.net>
+
+commit 72e3346872ec9298f2b582e2859b1dbf1304f77e
+Author: Manuel Traut <manut@mecka.net>
+Date: Tue Mar 22 23:49:58 2011 +0100
+
+ HELLO world
+
+ ..not huhu world
+
+ Signed-off-by: Manuel Traut <manut@mecka.net>
+
+...
+\end{lstlisting}
+
+Further exercises:
+
+\begin{itemize}
+\item pull from another repository
+\item track a repository
+\item what is a bare repository?
+\item find bugs with git bisect
+\item extract a patch queque from your git branch
+\item send mails with git
+\item build a svn - git bridge
+\end{itemize}
+
+\input{tailhandout}