Date: Mon, 26 May 2014 19:01:20 +0000 (UTC) From: Benedict Reuschling <bcr@FreeBSD.org> To: doc-committers@freebsd.org, svn-doc-all@freebsd.org, svn-doc-head@freebsd.org Subject: svn commit: r44964 - head/en_US.ISO8859-1/articles/geom-class Message-ID: <201405261901.s4QJ1KUD011473@svn.freebsd.org>
next in thread | raw e-mail | index | archive | help
Author: bcr Date: Mon May 26 19:01:20 2014 New Revision: 44964 URL: http://svnweb.freebsd.org/changeset/doc/44964 Log: Big whitespace cleanup, so that igor does not complain anymore. Translators, you can ignore this. Modified: head/en_US.ISO8859-1/articles/geom-class/article.xml Modified: head/en_US.ISO8859-1/articles/geom-class/article.xml ============================================================================== --- head/en_US.ISO8859-1/articles/geom-class/article.xml Mon May 26 18:28:36 2014 (r44963) +++ head/en_US.ISO8859-1/articles/geom-class/article.xml Mon May 26 19:01:20 2014 (r44964) @@ -1,15 +1,24 @@ <?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"> -<article xmlns="http://docbook.org/ns/docbook" xmlns:xlink="http://www.w3.org/1999/xlink" version="5.0" xml:lang="en"> - - <info><title>Writing a GEOM Class</title> +<article xmlns="http://docbook.org/ns/docbook" + xmlns:xlink="http://www.w3.org/1999/xlink" version="5.0" + xml:lang="en"> + <info> + <title>Writing a GEOM Class</title> <authorgroup> - <author><personname><firstname>Ivan</firstname><surname>Voras</surname></personname><affiliation> - <address><email>ivoras@FreeBSD.org</email> - </address> - </affiliation></author> + <author> + <personname> + <firstname>Ivan</firstname> + <surname>Voras</surname> + </personname> + <affiliation> + <address> + <email>ivoras@FreeBSD.org</email> + </address> + </affiliation> + </author> </authorgroup> <legalnotice xml:id="trademarks" role="trademarks"> @@ -23,65 +32,83 @@ <releaseinfo>$FreeBSD$</releaseinfo> <abstract> - <para>This text documents some starting points in developing - GEOM classes, and kernel modules in general. It is assumed - that the reader is familiar with C userland programming.</para> - + GEOM classes, and kernel modules in general. It is assumed + that the reader is familiar with C userland + programming.</para> </abstract> - </info> <!-- Introduction --> -<sect1 xml:id="intro"> - <title>Introduction</title> - - <sect2 xml:id="intro-docs"> - <title>Documentation</title> + <sect1 xml:id="intro"> + <title>Introduction</title> - <para>Documentation on kernel programming is scarce — it is one of - few areas where there is nearly nothing in the way of friendly - tutorials, and the phrase <quote>use the source!</quote> really - holds true. However, there are some bits and pieces (some of - them seriously outdated) floating around that should be studied - before beginning to code:</para> - - <itemizedlist> - - <listitem><para>The <link xlink:href="&url.books.developers-handbook;/index.html">FreeBSD - Developer's Handbook</link> — part of the documentation - project, it does not contain anything specific to kernel - programming, but rather some general useful information.</para></listitem> - - <listitem><para>The <link xlink:href="&url.books.arch-handbook;/index.html">FreeBSD - Architecture Handbook</link> — also from the documentation - project, contains descriptions of several low-level facilities - and procedures. The most important chapter is 13, <link xlink:href="&url.books.arch-handbook;/driverbasics.html">Writing - FreeBSD device drivers</link>.</para></listitem> - - <listitem><para>The Blueprints section of <link xlink:href="http://www.freebsddiary.org">FreeBSD Diary</link> web - site — contains several interesting articles on kernel - facilities.</para></listitem> - - <listitem><para>The man pages in section 9 — for important - documentation on kernel functions.</para></listitem> - - <listitem><para>The &man.geom.4; man page and <link xlink:href="http://phk.freebsd.dk/pubs/">PHK's GEOM slides</link> - — for general introduction of the GEOM - subsystem.</para></listitem> - - <listitem><para>Man pages &man.g.bio.9;, &man.g.event.9;, &man.g.data.9;, - &man.g.geom.9;, &man.g.provider.9; &man.g.consumer.9;, &man.g.access.9; - & others linked from those, for documentation on specific - functionalities. - </para></listitem> - - <listitem><para>The &man.style.9; man page — for documentation on - the coding-style conventions which must be followed for any code - which is to be committed to the FreeBSD Subversion tree.</para></listitem> - - </itemizedlist> + <sect2 xml:id="intro-docs"> + <title>Documentation</title> + <para>Documentation on kernel programming is scarce — it + is one of few areas where there is nearly nothing in the way + of friendly tutorials, and the phrase <quote>use the + source!</quote> really holds true. However, there are some + bits and pieces (some of them seriously outdated) floating + around that should be studied before beginning to code:</para> + + <itemizedlist> + <listitem> + <para>The <link + xlink:href="&url.books.developers-handbook;/index.html">FreeBSD + Developer's Handbook</link> — part of the + documentation project, it does not contain anything + specific to kernel programming, but rather some general + useful information.</para> + </listitem> + + <listitem> + <para>The <link + xlink:href="&url.books.arch-handbook;/index.html">FreeBSD + Architecture Handbook</link> — also from the + documentation project, contains descriptions of several + low-level facilities and procedures. The most important + chapter is 13, <link + xlink:href="&url.books.arch-handbook;/driverbasics.html">Writing + FreeBSD device drivers</link>.</para> + </listitem> + + <listitem> + <para>The Blueprints section of <link + xlink:href="http://www.freebsddiary.org">FreeBSD + Diary</link> web site — contains several + interesting articles on kernel + facilities.</para> + </listitem> + + <listitem> + <para>The man pages in section 9 — for important + documentation on kernel functions.</para> + </listitem> + + <listitem> + <para>The &man.geom.4; man page and <link + xlink:href="http://phk.freebsd.dk/pubs/">PHK's GEOM + slides</link> — for general introduction of the + GEOM subsystem.</para> + </listitem> + + <listitem> + <para>Man pages &man.g.bio.9;, &man.g.event.9;, + &man.g.data.9;, &man.g.geom.9;, &man.g.provider.9; + &man.g.consumer.9;, &man.g.access.9; & others linked + from those, for documentation on specific + functionalities.</para> + </listitem> + + <listitem> + <para>The &man.style.9; man page — for documentation + on the coding-style conventions which must be followed for + any code which is to be committed to the FreeBSD + Subversion tree.</para> + </listitem> + </itemizedlist> </sect2> </sect1> @@ -89,75 +116,77 @@ <title>Preliminaries</title> <para>The best way to do kernel development is to have (at least) - two separate computers. One of these would contain the + two separate computers. One of these would contain the development environment and sources, and the other would be used to test the newly written code by network-booting and network-mounting filesystems from the first one. This way if the new code contains bugs and crashes the machine, it will not - mess up the sources (and other <quote>live</quote> data). The - second system does not even require a proper display. Instead, it - could be connected with a serial cable or KVM to the first + mess up the sources (and other <quote>live</quote> data). The + second system does not even require a proper display. Instead, + it could be connected with a serial cable or KVM to the first one.</para> - <para>But, since not everybody has two or more computers handy, there are - a few things that can be done to prepare an otherwise <quote>live</quote> - system for developing kernel code. This setup is also applicable - for developing in a <link xlink:href="http://www.vmware.com/">VMWare</link> - or <link xlink:href="http://www.qemu.org/">QEmu</link> virtual machine (the - next best thing after a dedicated development machine).</para> + <para>But, since not everybody has two or more computers handy, + there are a few things that can be done to prepare an otherwise + <quote>live</quote> system for developing kernel code. This + setup is also applicable for developing in a <link + xlink:href="http://www.vmware.com/">VMWare</link> or <link + xlink:href="http://www.qemu.org/">QEmu</link> virtual machine + (the next best thing after a dedicated development + machine).</para> <sect2 xml:id="prelim-system"> <title>Modifying a System for Development</title> <para>For any kernel programming a kernel with - <option>INVARIANTS</option> enabled is a must-have. So enter - these in your kernel configuration file:</para> + <option>INVARIANTS</option> enabled is a must-have. So enter + these in your kernel configuration file:</para> - <programlisting>options INVARIANT_SUPPORT + <programlisting>options INVARIANT_SUPPORT options INVARIANTS</programlisting> - <para>For more debugging you should also include WITNESS support, - which will alert you of mistakes in locking:</para> + <para>For more debugging you should also include WITNESS + support, which will alert you of mistakes in locking:</para> - <programlisting>options WITNESS_SUPPORT + <programlisting>options WITNESS_SUPPORT options WITNESS</programlisting> <para>For debugging crash dumps, a kernel with debug symbols is - needed:</para> + needed:</para> <programlisting> makeoptions DEBUG=-g</programlisting> <para>With the usual way of installing the kernel (<command>make - installkernel</command>) the debug kernel will not be - automatically installed. It is called - <filename>kernel.debug</filename> and located in - <filename>/usr/obj/usr/src/sys/KERNELNAME/</filename>. For - convenience it should be copied to - <filename>/boot/kernel/</filename>.</para> + installkernel</command>) the debug kernel will not be + automatically installed. It is called + <filename>kernel.debug</filename> and located in + <filename>/usr/obj/usr/src/sys/KERNELNAME/</filename>. For + convenience it should be copied to + <filename>/boot/kernel/</filename>.</para> <para>Another convenience is enabling the kernel debugger so you - can examine a kernel panic when it happens. For this, enter - the following lines in your kernel configuration file:</para> + can examine a kernel panic when it happens. For this, enter + the following lines in your kernel configuration file:</para> <programlisting>options KDB options DDB options KDB_TRACE</programlisting> <para>For this to work you might need to set a sysctl (if it is - not on by default):</para> + not on by default):</para> <programlisting> debug.debugger_on_panic=1</programlisting> <para>Kernel panics will happen, so care should be taken with - the filesystem cache. In particular, having softupdates might - mean the latest file version could be lost if a panic occurs - before it is committed to storage. Disabling softupdates - yields a great performance hit, and still does not guarantee - data consistency. Mounting filesystem with the <quote>sync</quote> option - is needed for that. For a compromise, the softupdates cache delays can - be shortened. There are three sysctl's that are useful for - this (best to be set in - <filename>/etc/sysctl.conf</filename>):</para> + the filesystem cache. In particular, having softupdates might + mean the latest file version could be lost if a panic occurs + before it is committed to storage. Disabling softupdates + yields a great performance hit, and still does not guarantee + data consistency. Mounting filesystem with the + <quote>sync</quote> option is needed for that. For a + compromise, the softupdates cache delays can be shortened. + There are three sysctl's that are useful for this (best to be + set in <filename>/etc/sysctl.conf</filename>):</para> <programlisting>kern.filedelay=5 kern.dirdelay=4 @@ -166,76 +195,79 @@ kern.metadelay=3</programlisting> <para>The numbers represent seconds.</para> <para>For debugging kernel panics, kernel core dumps are - required. Since a kernel panic might make filesystems - unusable, this crash dump is first written to a raw - partition. Usually, this is the swap partition. This partition must be at - least as large as the physical RAM in the machine. On the - next boot, the dump is copied to a regular file. - This happens after filesystems are checked and mounted, and - before swap is enabled. This is controlled with two - <filename>/etc/rc.conf</filename> variables:</para> + required. Since a kernel panic might make filesystems + unusable, this crash dump is first written to a raw partition. + Usually, this is the swap partition. This partition must be + at least as large as the physical RAM in the machine. On the + next boot, the dump is copied to a regular file. This happens + after filesystems are checked and mounted, and before swap is + enabled. This is controlled with two + <filename>/etc/rc.conf</filename> variables:</para> <programlisting>dumpdev="/dev/ad0s4b" dumpdir="/usr/core </programlisting> <para>The <varname>dumpdev</varname> variable specifies the swap - partition and <varname>dumpdir</varname> tells the system - where in the filesystem to relocate the core dump on reboot.</para> + partition and <varname>dumpdir</varname> tells the system + where in the filesystem to relocate the core dump on + reboot.</para> <para>Writing kernel core dumps is slow and takes a long time so - if you have lots of memory (>256M) and lots of panics it could - be frustrating to sit and wait while it is done (twice — first - to write it to swap, then to relocate it to filesystem). It is - convenient then to limit the amount of RAM the system will use - via a <filename>/boot/loader.conf</filename> tunable:</para> + if you have lots of memory (>256M) and lots of panics it + could be frustrating to sit and wait while it is done (twice + — first to write it to swap, then to relocate it to + filesystem). It is convenient then to limit the amount of RAM + the system will use via a + <filename>/boot/loader.conf</filename> tunable:</para> <programlisting> hw.physmem="256M"</programlisting> <para>If the panics are frequent and filesystems large (or you - simply do not trust softupdates+background fsck) it is advisable - to turn background fsck off via - <filename>/etc/rc.conf</filename> variable:</para> + simply do not trust softupdates+background fsck) it is + advisable to turn background fsck off via + <filename>/etc/rc.conf</filename> variable:</para> <programlisting> background_fsck="NO"</programlisting> <para>This way, the filesystems will always get checked when - needed. Note that with background fsck, a new panic could happen while - it is checking the disks. Again, the safest way is not to have - many local filesystems by using another computer as an NFS - server.</para> + needed. Note that with background fsck, a new panic could + happen while it is checking the disks. Again, the safest way + is not to have many local filesystems by using another + computer as an NFS server.</para> </sect2> <sect2 xml:id="prelim-starting"> <title>Starting the Project</title> <para>For the purpose of creating a new GEOM class, an empty - subdirectory has to be created under an arbitrary user-accessible - directory. You do not have to create the module directory under - <filename>/usr/src</filename>.</para> + subdirectory has to be created under an arbitrary + user-accessible directory. You do not have to create the + module directory under <filename>/usr/src</filename>.</para> </sect2> <sect2 xml:id="prelim-makefile"> <title>The Makefile</title> <para>It is good practice to create - <filename>Makefile</filename>s for every nontrivial coding - project, which of course includes kernel modules.</para> + <filename>Makefile</filename>s for every nontrivial coding + project, which of course includes kernel modules.</para> <para>Creating the <filename>Makefile</filename> is simple - thanks to an extensive set of helper routines provided by the - system. In short, here is how a minimal <filename>Makefile</filename> - looks for a kernel module:</para> + thanks to an extensive set of helper routines provided by the + system. In short, here is how a minimal + <filename>Makefile</filename> looks for a kernel + module:</para> <programlisting>SRCS=g_journal.c KMOD=geom_journal .include <bsd.kmod.mk></programlisting> - <para>This <filename>Makefile</filename> (with changed filenames) - will do for any kernel module, and a GEOM class can reside in just - one kernel module. If more than one file is required, list it in the - <envar>SRCS</envar> variable, separated with whitespace from - other filenames.</para> + <para>This <filename>Makefile</filename> (with changed + filenames) will do for any kernel module, and a GEOM class can + reside in just one kernel module. If more than one file is + required, list it in the <envar>SRCS</envar> variable, + separated with whitespace from other filenames.</para> </sect2> </sect1> @@ -245,76 +277,77 @@ KMOD=geom_journal <sect2 xml:id="kernelprog-memalloc"> <title>Memory Allocation</title> - <para>See &man.malloc.9;. Basic memory allocation is only - slightly different than its userland equivalent. Most - notably, <function>malloc</function>() and - <function>free</function>() accept additional parameters as is - described in the man page.</para> + <para>See &man.malloc.9;. Basic memory allocation is only + slightly different than its userland equivalent. Most + notably, <function>malloc</function>() and + <function>free</function>() accept additional parameters as is + described in the man page.</para> <para>A <quote>malloc type</quote> must be declared in the - declaration section of a source file, like this:</para> + declaration section of a source file, like this:</para> <programlisting> static MALLOC_DEFINE(M_GJOURNAL, "gjournal data", "GEOM_JOURNAL Data");</programlisting> <para>To use this macro, <filename>sys/param.h</filename>, - <filename>sys/kernel.h</filename> and - <filename>sys/malloc.h</filename> headers must be - included.</para> + <filename>sys/kernel.h</filename> and + <filename>sys/malloc.h</filename> headers must be + included.</para> <para>There is another mechanism for allocating memory, the UMA - (Universal Memory Allocator). See &man.uma.9; for details, but - it is a special type of allocator mainly used for speedy - allocation of lists comprised of same-sized items (for - example, dynamic arrays of structs).</para> + (Universal Memory Allocator). See &man.uma.9; for details, + but it is a special type of allocator mainly used for speedy + allocation of lists comprised of same-sized items (for + example, dynamic arrays of structs).</para> </sect2> <sect2 xml:id="kernelprog-lists"> <title>Lists and Queues</title> - <para>See &man.queue.3;. There are a LOT of cases when a list of - things needs to be maintained. Fortunately, this data - structure is implemented (in several ways) by C macros - included in the system. The most used list type is TAILQ - because it is the most flexible. It is also the one with largest - memory requirements (its elements are doubly-linked) and - also the slowest (although the speed variation is on - the order of several CPU instructions more, so it should not be - taken seriously).</para> + <para>See &man.queue.3;. There are a LOT of cases when a list + of things needs to be maintained. Fortunately, this data + structure is implemented (in several ways) by C macros + included in the system. The most used list type is TAILQ + because it is the most flexible. It is also the one with + largest memory requirements (its elements are doubly-linked) + and also the slowest (although the speed variation is on the + order of several CPU instructions more, so it should not be + taken seriously).</para> <para>If data retrieval speed is very important, see - &man.tree.3; and &man.hashinit.9;.</para> + &man.tree.3; and &man.hashinit.9;.</para> </sect2> <sect2 xml:id="kernelprog-bios"> <title>BIOs</title> - <para>Structure <varname remap="structname">bio</varname> is used for any and - all Input/Output operations concerning GEOM. It basically - contains information about what device ('provider') should - satisfy the request, request type, offset, length, pointer to - a buffer, and a bunch of <quote>user-specific</quote> flags - and fields that can help implement various hacks.</para> - - <para>The important thing here is that <varname remap="structname">bio</varname>s - are handled asynchronously. That means that, in most parts of the code, - there is no analogue to userland's &man.read.2; and - &man.write.2; calls that do not return until a request is - done. Rather, a developer-supplied function is called as a - notification when the request gets completed (or results in - error).</para> - - <para>The asynchronous programming model (also - called <quote>event-driven</quote>) is somewhat harder - than the much more used imperative one used in userland - (at least it takes a - while to get used to it). In some cases the helper routines - <function>g_write_data</function>() and - <function>g_read_data</function>() can be used, but <emphasis>not - always</emphasis>. In particular, they cannot be used when - a mutex is held; for example, the GEOM topology mutex or - the internal mutex held during the <function>.start</function>() and - <function>.stop</function>() functions.</para> - + <para>Structure <varname remap="structname">bio</varname> is + used for any and all Input/Output operations concerning GEOM. + It basically contains information about what device + ('provider') should satisfy the request, request type, offset, + length, pointer to a buffer, and a bunch of + <quote>user-specific</quote> flags and fields that can help + implement various hacks.</para> + + <para>The important thing here is that <varname + remap="structname">bio</varname>s are handled + asynchronously. That means that, in most parts of the code, + there is no analogue to userland's &man.read.2; and + &man.write.2; calls that do not return until a request is + done. Rather, a developer-supplied function is called as a + notification when the request gets completed (or results in + error).</para> + + <para>The asynchronous programming model (also called + <quote>event-driven</quote>) is somewhat harder than the much + more used imperative one used in userland (at least it takes a + while to get used to it). In some cases the helper routines + <function>g_write_data</function>() and + <function>g_read_data</function>() can be used, but + <emphasis>not always</emphasis>. In particular, they cannot + be used when a mutex is held; for example, the GEOM topology + mutex or the internal mutex held during the + <function>.start</function>() and <function>.stop</function>() + functions.</para> </sect2> </sect1> @@ -325,109 +358,131 @@ KMOD=geom_journal <title>Ggate</title> <para>If maximum performance is not needed, a much simpler way - of making a data transformation is to implement it in userland - via the ggate (GEOM gate) facility. Unfortunately, there is no - easy way to convert between, or even share code between the - two approaches.</para> + of making a data transformation is to implement it in userland + via the ggate (GEOM gate) facility. Unfortunately, there is + no easy way to convert between, or even share code between the + two approaches.</para> </sect2> <sect2 xml:id="geom-class"> <title>GEOM Class</title> - <para>GEOM classes are transformations on the data. These transformations - can be combined in a tree-like fashion. Instances of GEOM classes are - called <emphasis>geoms</emphasis>.</para> - - <para>Each GEOM class has several <quote>class methods</quote> that get called - when there is no geom instance available (or they are simply not - bound to a single instance):</para> - - <itemizedlist> - - <listitem><para><function>.init</function> is called when GEOM - becomes aware of a GEOM class (when the kernel module - gets loaded.)</para></listitem> - - <listitem><para><function>.fini</function> gets called when GEOM - abandons the class (when the module gets - unloaded)</para></listitem> - - <listitem><para><function>.taste</function> is called next, once for - each provider the system has available. If applicable, this - function will usually create and start a geom - instance.</para></listitem> - - <listitem><para><function>.destroy_geom</function> is called when - the geom should be disbanded</para></listitem> - - <listitem><para><function>.ctlconf</function> is called when user - requests reconfiguration of existing geom</para></listitem> - + <para>GEOM classes are transformations on the data. These + transformations can be combined in a tree-like fashion. + Instances of GEOM classes are called + <emphasis>geoms</emphasis>.</para> + + <para>Each GEOM class has several <quote>class methods</quote> + that get called when there is no geom instance available (or + they are simply not bound to a single instance):</para> + + <itemizedlist> + <listitem> + <para><function>.init</function> is called when GEOM becomes + aware of a GEOM class (when the kernel module gets + loaded.)</para> + </listitem> + + <listitem> + <para><function>.fini</function> gets called when GEOM + abandons the class (when the module gets + unloaded)</para> + </listitem> + + <listitem> + <para><function>.taste</function> is called next, once for + each provider the system has available. If applicable, + this function will usually create and start a geom + instance.</para> + </listitem> + + <listitem> + <para><function>.destroy_geom</function> is called when the + geom should be disbanded</para> + </listitem> + + <listitem> + <para><function>.ctlconf</function> is called when user + requests reconfiguration of existing + geom</para> + </listitem> </itemizedlist> <para>Also defined are the GEOM event functions, which will get - copied to the geom instance.</para> + copied to the geom instance.</para> - <para>Field <function>.geom</function> in the - <varname remap="structname">g_class</varname> structure is a LIST of geoms - instantiated from the class.</para> - - <para>These functions are called from the g_event kernel thread.</para> + <para>Field <function>.geom</function> in the <varname + remap="structname">g_class</varname> structure is a LIST of + geoms instantiated from the class.</para> + <para>These functions are called from the g_event kernel + thread.</para> </sect2> <sect2 xml:id="geom-softc"> <title>Softc</title> <para>The name <quote>softc</quote> is a legacy term for - <quote>driver private data</quote>. The name most probably - comes from the archaic term <quote>software control block</quote>. - In GEOM, it is a structure (more precise: pointer to a - structure) that can be attached to a geom instance to hold - whatever data is private to the geom instance. Most GEOM classes - have the following members:</para> - - <itemizedlist> - <listitem><para><varname>struct g_provider *provider</varname> : The - <quote>provider</quote> this geom instantiates</para></listitem> - - <listitem><para><varname>uint16_t n_disks</varname> : Number of - consumer this geom consumes</para></listitem> - - <listitem><para><varname>struct g_consumer **disks</varname> : Array - of <varname>struct g_consumer*</varname>. (It is not possible - to use just single indirection because struct g_consumer* - are created on our behalf by GEOM).</para></listitem> - </itemizedlist> - - <para>The <varname remap="structname">softc</varname> structure contains all - the state of geom instance. Every geom instance has its own - softc.</para> + <quote>driver private data</quote>. The name most probably + comes from the archaic term <quote>software control + block</quote>. In GEOM, it is a structure (more precise: + pointer to a structure) that can be attached to a geom + instance to hold whatever data is private to the geom + instance. Most GEOM classes have the following + members:</para> + + <itemizedlist> + <listitem> + <para><varname>struct g_provider *provider</varname> : The + <quote>provider</quote> this geom + instantiates</para> + </listitem> + + <listitem> + <para><varname>uint16_t n_disks</varname> : Number of + consumer this geom consumes</para> + </listitem> + + <listitem> + <para><varname>struct g_consumer **disks</varname> : Array + of <varname>struct g_consumer*</varname>. (It is not + possible to use just single indirection because struct + g_consumer* are created on our behalf by + GEOM).</para> + </listitem> + </itemizedlist> + + <para>The <varname remap="structname">softc</varname> structure + contains all the state of geom instance. Every geom instance + has its own softc.</para> </sect2> <sect2 xml:id="geom-metadata"> <title>Metadata</title> <para>Format of metadata is more-or-less class-dependent, but - MUST start with:</para> + MUST start with:</para> <itemizedlist> + <listitem> + <para>16 byte buffer for null-terminated signature (usually + the class name)</para> + </listitem> - <listitem><para>16 byte buffer for null-terminated signature - (usually the class name)</para></listitem> - - <listitem><para>uint32 version ID</para></listitem> - + <listitem> + <para>uint32 version ID</para> + </listitem> </itemizedlist> - <para>It is assumed that geom classes know how to handle metadata - with version ID's lower than theirs.</para> + <para>It is assumed that geom classes know how to handle + metadata with version ID's lower than theirs.</para> <para>Metadata is located in the last sector of the provider - (and thus must fit in it).</para> + (and thus must fit in it).</para> <para>(All this is implementation-dependent but all existing - code works like that, and it is supported by libraries.)</para> + code works like that, and it is supported by + libraries.)</para> </sect2> <sect2 xml:id="geom-creating"> @@ -436,271 +491,327 @@ KMOD=geom_journal <para>The sequence of events is:</para> <itemizedlist> - - <listitem><para>user calls &man.geom.8; utility (or one of its - hardlinked friends)</para></listitem> - - <listitem><para>the utility figures out which geom class it is - supposed to handle and searches for - <filename>geom_<replaceable>CLASSNAME</replaceable>.so</filename> - library (usually in - <filename>/lib/geom</filename>).</para></listitem> - - <listitem><para>it &man.dlopen.3;-s the library, extracts the - definitions of command-line parameters and helper - functions.</para></listitem> - + <listitem> + <para>user calls &man.geom.8; utility (or one of its + hardlinked friends)</para> + </listitem> + + <listitem> + <para>the utility figures out which geom class it is + supposed to handle and searches for + <filename>geom_<replaceable>CLASSNAME</replaceable>.so</filename> + library (usually in + <filename>/lib/geom</filename>).</para> + </listitem> + + <listitem> + <para>it &man.dlopen.3;-s the library, extracts the + definitions of command-line parameters and helper + functions.</para> + </listitem> </itemizedlist> <para>In the case of creating/labeling a new geom, this is what - happens:</para> + happens:</para> <itemizedlist> - - <listitem><para>&man.geom.8; looks in the command-line argument - for the command (usually <option>label</option>), and calls a helper - function.</para></listitem> - - <listitem><para>The helper function checks parameters and gathers - metadata, which it proceeds to write to all concerned - providers.</para></listitem> - - <listitem><para>This <quote>spoils</quote> existing geoms (if any) and - initializes a new round of <quote>tasting</quote> of the providers. The - intended geom class recognizes the metadata and brings the - geom up.</para></listitem> - + <listitem> + <para>&man.geom.8; looks in the command-line argument for + the command (usually <option>label</option>), and calls a + helper function.</para> + </listitem> + + <listitem> + <para>The helper function checks parameters and gathers + metadata, which it proceeds to write to all concerned + providers.</para> + </listitem> + + <listitem> + <para>This <quote>spoils</quote> existing geoms (if any) and + initializes a new round of <quote>tasting</quote> of the + providers. The intended geom class recognizes the + metadata and brings the geom up.</para> + </listitem> </itemizedlist> <para>(The above sequence of events is implementation-dependent - but all existing code works like that, and it is supported by - libraries.)</para> - + but all existing code works like that, and it is supported by + libraries.)</para> </sect2> <sect2 xml:id="geom-command"> <title>GEOM Command Structure</title> <para>The helper <filename>geom_CLASSNAME.so</filename> library - exports <varname remap="structname">class_commands</varname> structure, - which is an array of <varname remap="structname">struct g_command</varname> - elements. Commands are of uniform format and look like:</para> + exports <varname remap="structname">class_commands</varname> + structure, which is an array of <varname + remap="structname">struct g_command</varname> elements. + Commands are of uniform format and look like:</para> <programlisting> verb [-options] geomname [other]</programlisting> <para>Common verbs are:</para> <itemizedlist> - - <listitem><para>label — to write metadata to devices so they can be - recognized at tasting and brought up in geoms</para></listitem> - - <listitem><para>destroy — to destroy metadata, so the geoms get - destroyed</para></listitem> - + <listitem> + <para>label — to write metadata to devices so they can + be recognized at tasting and brought up in + geoms</para> + </listitem> + + <listitem> + <para>destroy — to destroy metadata, so the geoms get + destroyed</para> + </listitem> </itemizedlist> <para>Common options are:</para> <itemizedlist> - <listitem><para><literal>-v</literal> : be verbose</para></listitem> - <listitem><para><literal>-f</literal> : force</para></listitem> + <listitem> + <para><literal>-v</literal> : be verbose</para> + </listitem> + + <listitem> + <para><literal>-f</literal> : force</para> + </listitem> </itemizedlist> <para>Many actions, such as labeling and destroying metadata can - be performed in userland. For this, <varname remap="structname">struct - g_command</varname> provides field - <varname>gc_func</varname> that can be set to a function (in - the same <filename>.so</filename>) that will be called to - process a verb. If <varname>gc_func</varname> is NULL, the - command will be passed to kernel module, to - <function>.ctlreq</function> function of the geom - class.</para> + be performed in userland. For this, <varname + remap="structname">struct g_command</varname> provides field + <varname>gc_func</varname> that can be set to a function (in + the same <filename>.so</filename>) that will be called to + process a verb. If <varname>gc_func</varname> is NULL, the + command will be passed to kernel module, to + <function>.ctlreq</function> function of the geom + class.</para> </sect2> <sect2 xml:id="geom-geoms"> <title>Geoms</title> - <para>Geoms are instances of GEOM classes. They have internal - data (a softc structure) and some functions with which they - respond to external events.</para> + <para>Geoms are instances of GEOM classes. They have internal + data (a softc structure) and some functions with which they + respond to external events.</para> <para>The event functions are:</para> <itemizedlist> - <listitem><para><function>.access</function> : calculates - permissions (read/write/exclusive)</para></listitem> - - <listitem><para><function>.dumpconf</function> : returns - XML-formatted information about the geom</para></listitem> - - <listitem><para><function>.orphan</function> : called when some - underlying provider gets disconnected</para></listitem> - - <listitem><para><function>.spoiled</function> : called when some - underlying provider gets written to</para></listitem> - - <listitem><para><function>.start</function> : handles I/O</para></listitem> - </itemizedlist> - - <para>These functions are called from the <function>g_down</function> - kernel thread and there can be no sleeping in this context, - (see definition of sleeping elsewhere) which limits what can be done - quite a bit, but forces the handling to be fast.</para> + <listitem> + <para><function>.access</function> : calculates permissions + (read/write/exclusive)</para> + </listitem> + + <listitem> + <para><function>.dumpconf</function> : returns XML-formatted + information about the geom</para> + </listitem> + + <listitem> + <para><function>.orphan</function> : called when some + underlying provider gets disconnected</para> + </listitem> + + <listitem> + <para><function>.spoiled</function> : called when some + underlying provider gets written to</para> + </listitem> + + <listitem> + <para><function>.start</function> : handles I/O</para> + </listitem> + </itemizedlist> + + <para>These functions are called from the + <function>g_down</function> kernel thread and there can be no + sleeping in this context, (see definition of sleeping + elsewhere) which limits what can be done quite a bit, but + forces the handling to be fast.</para> <para>Of these, the most important function for doing actual - useful work is the <function>.start</function>() function, - which is called when a BIO request arrives for a provider - managed by a instance of geom class.</para> + useful work is the <function>.start</function>() function, + which is called when a BIO request arrives for a provider + managed by a instance of geom class.</para> </sect2> <sect2 xml:id="geom-threads"> <title>GEOM Threads</title> <para>There are three kernel threads created and run by the GEOM - framework:</para> + framework:</para> <itemizedlist> - <listitem><para><literal>g_down</literal> : Handles requests coming - from high-level entities (such as a userland request) on the - way to physical devices</para></listitem> - - <listitem><para><literal>g_up</literal> : Handles responses from - device drivers to requests made by higher-level - entities</para></listitem> - - <listitem><para><literal>g_event</literal> : Handles all other - cases: creation of geom instances, access counting, <quote>spoil</quote> - events, etc.</para></listitem> + <listitem> + <para><literal>g_down</literal> : Handles requests coming + from high-level entities (such as a userland request) on + the way to physical devices</para> + </listitem> + + <listitem> + <para><literal>g_up</literal> : Handles responses from + device drivers to requests made by higher-level + entities</para> + </listitem> + + <listitem> + <para><literal>g_event</literal> : Handles all other cases: + creation of geom instances, access counting, + <quote>spoil</quote> events, etc.</para> + </listitem> </itemizedlist> <para>When a user process issues <quote>read data X at offset Y - of a file</quote> request, this is what happens:</para> + of a file</quote> request, this is what happens:</para> <itemizedlist> - *** DIFF OUTPUT TRUNCATED AT 1000 LINES ***
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201405261901.s4QJ1KUD011473>