<?xml version="1.0" encoding="utf-8"?>
<!-- If you are running a bot please visit this policy page outlining rules you must respect. http://www.livejournal.com/bots/ -->
<feed xmlns="http://www.w3.org/2005/Atom" xmlns:lj="http://www.livejournal.com">
  <id>urn:lj:livejournal.com:atom1:jmmv</id>
  <title>jmmv's weblog</title>
  <subtitle>By Julio M. Merino Vidal</subtitle>
  <author>
    <name>jmmv</name>
  </author>
  <link rel="alternate" type="text/html" href="http://jmmv.livejournal.com/"/>
  <link rel="self" type="text/xml" href="http://jmmv.livejournal.com/data/atom"/>
  <updated>2007-04-29T08:16:34Z</updated>
  <lj:journal username="jmmv" type="personal"/>
  <link rel="service.feed" type="application/x.atom+xml" href="http://jmmv.livejournal.com/data/atom" title="jmmv's weblog"/>
  <entry>
    <id>urn:lj:livejournal.com:atom1:jmmv:46937</id>
    <link rel="alternate" type="text/html" href="http://jmmv.livejournal.com/46937.html"/>
    <link rel="self" type="text/xml" href="http://jmmv.livejournal.com/data/atom/?itemid=46937"/>
    <title>Blog migrated to Blogger</title>
    <published>2005-10-22T15:49:09Z</published>
    <updated>2007-04-29T08:16:34Z</updated>
    <content type="html">As I outlined &lt;a href="http://www.livejournal.com/users/jmmv/46555.html"&gt;a week ago&lt;/a&gt;, I was considering the migration of this blog from &lt;a href="http://www.livejournal.com/"&gt;Livejournal&lt;/a&gt; to &lt;a href="http://www.blogger.com/"&gt;Blogger&lt;/a&gt;... and I finally did it.&lt;br /&gt;&lt;br /&gt;The new address is &lt;a href="http://julipedia.blogspot.com/"&gt;http://julipedia.blogspot.com/&lt;/a&gt; and the blog is now named &lt;i&gt;The Julipedia&lt;/i&gt;.  Please see the &lt;a href="http://julipedia.blogspot.com/2005/10/blog-migrated-to-blogger-welcome.html"&gt;welcome message&lt;/a&gt; for more information.  &lt;b&gt;Remember to update your subscriptions&lt;/b&gt;!&lt;br /&gt;&lt;br /&gt;&lt;b&gt;This blog will no longer be updated.  Its contents will be kept intact for a long time.&lt;/b&gt;&lt;br /&gt;&lt;br /&gt;Thanks to Livejournal for their service during the life of this blog.</content>
  </entry>
  <entry>
    <id>urn:lj:livejournal.com:atom1:jmmv:46692</id>
    <link rel="alternate" type="text/html" href="http://jmmv.livejournal.com/46692.html"/>
    <link rel="self" type="text/xml" href="http://jmmv.livejournal.com/data/atom/?itemid=46692"/>
    <title>GNOME 2.12.1 hits pkgsrc</title>
    <published>2005-10-16T14:33:44Z</published>
    <updated>2005-10-16T14:33:44Z</updated>
    <content type="html">As usual, the latest stable version of the &lt;a href="http://www.gnome.org/"&gt;GNOME&lt;/a&gt; Platform and Desktop, &lt;a href="http://www.gnome.org/start/2.12/"&gt;2.12.1&lt;/a&gt;, has been integrated into &lt;a href="http://www.pkgsrc.org/"&gt;pkgsrc&lt;/a&gt;.  It has been a tough job due to all the affected packages and comes a bit late, compared to all the previous updates, but I hope you'll enjoy it.&lt;br /&gt;&lt;br /&gt;Please see the &lt;a href="http://mail-index.netbsd.org/tech-pkg/2005/10/16/0008.html"&gt;official announcement&lt;/a&gt; for more information.</content>
  </entry>
  <entry>
    <id>urn:lj:livejournal.com:atom1:jmmv:46555</id>
    <link rel="alternate" type="text/html" href="http://jmmv.livejournal.com/46555.html"/>
    <link rel="self" type="text/xml" href="http://jmmv.livejournal.com/data/atom/?itemid=46555"/>
    <title>Blogger</title>
    <published>2005-10-15T11:37:05Z</published>
    <updated>2005-10-15T16:09:54Z</updated>
    <content type="html">&lt;p&gt;Two years ago or so, I registered a weblog at &lt;a href="http://www.blogger.com/"&gt;Blogger&lt;/a&gt;, which only lasted a week (don't bother looking for it; it was deleted).  At that time, I didn't like that site much, specially because it lacked a very important feature: integrated support for comments.  Yes, you could use external utilities/sites to host comments, but that was complex.&lt;/p&gt;

&lt;p&gt;However, a few minutes ago, I discovered that they now have comments support; yay!  I spent some time surfing their site and found it very intuitive.  Also, I registered a new weblog (whose name I won't unveil yet, but a friend of mine will know which it is ;-) just to see which features they support now.&lt;/p&gt;

&lt;p&gt;And all I can say is that it seems better than &lt;a href="http://www.livejournal.com/"&gt;Livejournal&lt;/a&gt;...  Here are some reasons:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Blogger applies the weblog style to all pages: posts and comments.  Here at Livejournal, only the front page gets the look you design, but all comment ones have a standard, non-customizable and ugly look (I don't know about paid accounts).&lt;/li&gt;
&lt;li&gt;As regards the style, Blogger lets you customize it completely, editing the HTML code directly.  Livejournal does not let you do this unless you have a paid account.&lt;/li&gt;
&lt;li&gt;Blogger addresses are shorter and easier to remember: http://&amp;lt;blogname&amp;gt;.blogspot.com/ vs. http://www.livejournal.com/users/&amp;lt;user&amp;gt;.&lt;/li&gt;
&lt;li&gt;The blogger interface seems to be more intuitive than Livejournal's one.&lt;/li&gt;
&lt;li&gt;Blogger lets you post images on your blog (without external links).&lt;/li&gt;
&lt;li&gt;Blogger lets you post by e-mail.&lt;/li&gt;
&lt;li&gt;Neither Livejournal nor Blogger have support to track blog statistics.  However, Blogger lets you add statistics trackers from other sites, which is a plus.&lt;/li&gt;
&lt;li&gt;My beloved &lt;a href="http://www.dropline.net/drivel/"&gt;Drivel&lt;/a&gt; supports both systems, so easier migration from this POV.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;So... I'm seriously considering migrating this blog there, because the reasons mentioned above.  However, there are two things against this idea: people will have to update their address (though I don't think there are many readers out there ;) and, worst of all, I don't know if it's possible to easily migrate all the existing posts to the new site (and this is a must).&lt;/p&gt;

&lt;p&gt;Anyone has comments on this? Any counter-arguments or suggestions? :-)&lt;/p&gt;

&lt;p&gt;&lt;b&gt;Edit 18:08&lt;/b&gt;: The statistics item was added.&lt;/p&gt;</content>
  </entry>
  <entry>
    <id>urn:lj:livejournal.com:atom1:jmmv:46268</id>
    <link rel="alternate" type="text/html" href="http://jmmv.livejournal.com/46268.html"/>
    <link rel="self" type="text/xml" href="http://jmmv.livejournal.com/data/atom/?itemid=46268"/>
    <title>Articles: Lightweight web serving with thttpd</title>
    <published>2005-10-14T16:20:40Z</published>
    <updated>2005-10-14T16:20:40Z</updated>
    <content type="html">Several months ago I started writing an article about setting up and using the lightweight web server &lt;a href="http://www.acme.com/software/thttpd/"&gt;thttpd&lt;/a&gt;, focusing on the &lt;a href="http://www.NetBSD.org/"&gt;NetBSD&lt;/a&gt; operating system.  I finally decided to finish it a month ago and submitted it for publication.  You can now &lt;a href="http://www.onlamp.com/pub/a/bsd/2005/10/13/thttpd.html"&gt;read it on-line&lt;/a&gt; at &lt;a href="http://www.onlamp.com/"&gt;ONLamp&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;Hope you find it useful!</content>
  </entry>
  <entry>
    <id>urn:lj:livejournal.com:atom1:jmmv:45984</id>
    <link rel="alternate" type="text/html" href="http://jmmv.livejournal.com/45984.html"/>
    <link rel="self" type="text/xml" href="http://jmmv.livejournal.com/data/atom/?itemid=45984"/>
    <title>C++: Constructors and global data</title>
    <published>2005-10-12T11:44:08Z</published>
    <updated>2005-10-12T12:46:00Z</updated>
    <content type="html">&lt;p&gt;As a general rule of thumb, accessing global data from within class constructors is a dangerous operation and ought to be avoided.  The C++ specification does not describe the order in which global variables are initialized, so there are high chances that your constructor accesses uninitialized data, producing unexpected resultsn (e.g., crashes in some circumstances).&lt;/p&gt;

&lt;p&gt;It is important to remark this.  This behavior is undefined, so it can change across compilers and/or architectures.  If your code relies on it, it's broken: something that apparently works on one machine may not work on another one.&lt;/p&gt;

&lt;p&gt;Let's see an example.  First of all, consider an &lt;tt&gt;Integer&lt;/tt&gt; class that wraps an integer (like Java's one) and a &lt;tt&gt;Foo&lt;/tt&gt; class with a not-yet-specified constructor:&lt;/p&gt;

&lt;pre&gt;class Integer {
    int m_value;

public:
    Integer(int v) { m_value = v; }

    int get_value(void) { return m_value; }
};

class Foo {
public:
    Foo(void);
};&lt;/pre&gt;

&lt;p&gt;Up to this point, everything is correct.  Now, given that both classes are usable, we declare two global variables, one of each type:&lt;/p&gt;

&lt;pre&gt;static Integer Global_Integer(5);
static Foo Global_Foo;&lt;/pre&gt;

&lt;p&gt;As these are objects, the C++ runtime will call their constructors when initializing them, but we can't predict the order in which this will happen.&lt;/p&gt;

&lt;p&gt;Now we define &lt;tt&gt;Foo's&lt;/tt&gt; constructor body, which accesses and prints &lt;tt&gt;Global_Integer&lt;/tt&gt;'s value:&lt;/p&gt;

&lt;pre&gt;Foo::Foo(void)
{
    std::cout &amp;lt;&amp;lt; Global_Integer.get_value() &amp;lt;&amp;lt; std::endl;
}&lt;/pre&gt;

&lt;p&gt;With this done, if you add an empty &lt;tt&gt;main&lt;/tt&gt; function and run the program, you should see an integer; it will be &lt;i&gt;probably&lt;/i&gt; be 5 (at least with GNU G++ 4.0.1 on a Linux/powerpc box), but it may not.  Whichever value you get, try reversing the variable declaration lines, defining &lt;tt&gt;Global_Foo&lt;/tt&gt; first and see if the results change (I get 0 in this box).&lt;/p&gt;

&lt;p&gt;Clear?  OK, this example is extremely simple, but imagine if this same structure was split among multiple files and classes in a large project...  You couldn't easily predict what happens under the hood.&lt;/p&gt;</content>
  </entry>
  <entry>
    <id>urn:lj:livejournal.com:atom1:jmmv:45726</id>
    <link rel="alternate" type="text/html" href="http://jmmv.livejournal.com/45726.html"/>
    <link rel="self" type="text/xml" href="http://jmmv.livejournal.com/data/atom/?itemid=45726"/>
    <title>Monotone: Using mini-branches to apply patches</title>
    <published>2005-10-08T21:42:30Z</published>
    <updated>2005-10-08T21:42:30Z</updated>
    <content type="html">&lt;p&gt;The &lt;a href="http://www.venge.net/monotone/"&gt;Monotone&lt;/a&gt; VCS provides the concept of mini-branches.  A mini-branch is a lightweight branch created inside a formal branch whenever a commit causes "conflicts" with the actual contents of the repository.  For example, if your working copy is not up to date and you commit something, you will create a new head within the branch (that is, a mini-branch), that you will later need to (possibly manually) merge with the other head to remove the divergence.&lt;/p&gt;

&lt;p&gt;Mini-branches can be used to easily apply externally-provided patches to your software project.  Consider the following "collapsed" revision subgraph:&lt;/p&gt;

&lt;pre&gt;      tag: foo-2.1        tag: foo-3.0
          |                   |
A -&amp;gt; B -&amp;gt; C -&amp;gt; D -&amp;gt; E -&amp;gt; F -&amp;gt; G -&amp;gt; H -&amp;gt; I -&amp;gt; J&lt;/pre&gt;

&lt;p&gt;As you can see, some development happened in revisions A, B and C, at which point the program was considered stable and the 2.1 release was made.  Some time later, and after lots of changes, revision G was tagged as 3.0 and that release was made.&lt;/p&gt;

&lt;p&gt;One of this project's users notices a bug in the 2.1 version, tracks it down and fixes it.  For whatever reason, he cannot update to 3.0 to see if his changes work with the latest version, so he decides to submit his fix as a patch against 2.1 to the mainstream developers.&lt;/p&gt;

&lt;p&gt;So, how do they handle the patch?  It will doubtfully apply cleanly to their current code-base, which is far past 3.0.  Of course, they can inspect it, adjust it and apply it directly to revision J, but all this process won't be tracked anywhere.  Users and developers could later be confused when looking at the original patch and the patch that was really applied &amp;mdash; "why were those changes done?".&lt;/p&gt;

&lt;p&gt;Here is where mini-branches come to help.  The developers ask Monotone to check out a clean copy of C (the same that the user had), ensuring that the patch will apply cleanly.  At that point, they apply the fix and commit it to the tree, thus "storing" the original patch file in it.  As a result, the revision tree could look like:&lt;/p&gt;

&lt;pre&gt;      tag: foo-2.1        tag: foo-3.0
          |                   |
A -&amp;gt; B -&amp;gt; C -&amp;gt; D -&amp;gt; E -&amp;gt; F -&amp;gt; G -&amp;gt; H -&amp;gt; I -&amp;gt; J
           \
            \
             K&lt;/pre&gt;

&lt;p&gt;As you can see, the repository now has two heads (J and K) in the same branch (which can be inspected using &lt;tt&gt;monotone heads&lt;/tt&gt;).  J is a lot farther than K in terms of development, but that doesn't matter to the VCS system.  Note that, at this point, the revision K carries the code in 2.1 plus the changes submitted by the user verbatim; they still haven't been modified to apply to J, and J is not affected at all by that commit.&lt;/p&gt;

&lt;p&gt;Once this is done, and after inspecting why the patch does not apply, the developer decides to merge the heads (&lt;tt&gt;monotone merge&lt;/tt&gt;), thus creating a new revision L that holds all J's code plus the fix added in K:&lt;/p&gt;

&lt;pre&gt;      tag: foo-2.1        tag: foo-3.0
          |                   |
A -&amp;gt; B -&amp;gt; C -&amp;gt; D -&amp;gt; E -&amp;gt; F -&amp;gt; G -&amp;gt; H -&amp;gt; I -&amp;gt; J -&amp;gt; L
           \                                  /
            \                                /
             K -----------------------------'&lt;/pre&gt;

&lt;p&gt;Voila!  There is now a single head, L, which holds all your code plus the fix sent by the user.  Furthermore, the repository has kept track of all the patching process, storing the original and the modified versions of the changes.&lt;/p&gt;

&lt;p&gt;Note that this has assumed that revisions are marked as tags rather than as formal branches.  Of course, a similar process could be followed if each version was on its own branch (as done with any other VCS).&lt;/p&gt;</content>
  </entry>
  <entry>
    <id>urn:lj:livejournal.com:atom1:jmmv:45551</id>
    <link rel="alternate" type="text/html" href="http://jmmv.livejournal.com/45551.html"/>
    <link rel="self" type="text/xml" href="http://jmmv.livejournal.com/data/atom/?itemid=45551"/>
    <title>Games: Half-Life 2</title>
    <published>2005-10-06T15:21:44Z</published>
    <updated>2005-10-06T15:22:52Z</updated>
    <content type="html">&lt;a href="http://www.half-life2.com/"&gt;Half-Life 2&lt;/a&gt;'s Game Of The Year edition was published past Friday.  I finally bought it (have been waiting for this since I threw away my illegal copy several months ago); this edition is cheaper than the original game and comes with some goodies.&lt;br /&gt;&lt;br /&gt;And just a few minutes ago, I completed it :-)  (had started with my old saved game, which was almost at the end).  All I can say is that the game is really stunning.  If you like FPSs, this is The One.&lt;br /&gt;&lt;br /&gt;There is a lot of variety in the game, as opposed to &lt;a href="http://www.doom3.com/"&gt;Doom 3&lt;/a&gt;, which I find quite repetitive.  Each chapter has its own style and suits the story well.  There are also multiple weapons and, as you know, the physics are really well done.&lt;br /&gt;&lt;br /&gt;Now, it's time to play it again at a higher difficulty level.  I think I'll wait until I renew my video card, though.  And also, time to play Half-Life: Source, no matter I've already finished the first game three times :-)</content>
  </entry>
  <entry>
    <id>urn:lj:livejournal.com:atom1:jmmv:45190</id>
    <link rel="alternate" type="text/html" href="http://jmmv.livejournal.com/45190.html"/>
    <link rel="self" type="text/xml" href="http://jmmv.livejournal.com/data/atom/?itemid=45190"/>
    <title>C++: Templates and the ABI</title>
    <published>2005-10-03T11:24:53Z</published>
    <updated>2005-10-03T11:25:32Z</updated>
    <content type="html">&lt;p&gt;In the &lt;a href="http://www.livejournal.com/users/jmmv/44985.html"&gt;previous post&lt;/a&gt;, we saw why inlined code is dangerous in a public API.  Unfortunately, I carelessly put templates in the same bag in an attempt to generalize the idea too much, giving an incorrect impression of how they work.  A reader (&lt;a href="http://www.livejournal.com/users/fellow_traveler/"&gt;fellow_traveler&lt;/a&gt;) spotted the mistake and here is this new post to clarify what's up with templates and an ABI... if one can relate the two concepts at all.&lt;/p&gt;

&lt;p&gt;C++ makes intensive use (or abuse?) of templates to achieve genericity; one can quickly notice this in the STL, where each container is parametrized based on one or more types.  Other libraries, such as &lt;a href="http://www.boost.org/"&gt;Boost&lt;/a&gt;, go further and use templates in a lot of situations where one couldn't have ever imagined so.&lt;/p&gt;

&lt;p&gt;In order to understand what goes on with templates, let's remind how they work.  A template defines a piece of code (be it a class or a function) that is parametrized by a type given by the developer.  The template does not exist as binary code, because, simply put, that is impossible: it lacks type information to be compiled.&lt;/p&gt;

&lt;p&gt;Here is a trivial function that returns the sum of two objects whose type is defined by &lt;tt&gt;Type&lt;/tt&gt;; we will use it to illustrate some examples below.  Also, and to focus on the ABI, let's assume that this code is part of a public library; therefore, it must be placed in a header file (e.g., &lt;tt&gt;foo.hpp&lt;/tt&gt;) to be useful to other users (if it were in a &lt;tt&gt;foo.cpp&lt;/tt&gt; file, it'd simply be private and not usable outside that file).&lt;/p&gt;

&lt;pre&gt;template &amp;lt;class Type&amp;gt;
Type
add(const Type&amp; p1, const Type&amp; p2)
{
    return p1 + p2;
}&lt;/pre&gt;

&lt;p&gt;When the template is used in someone else's code &amp;mdash; in other words, it is instantiated &amp;mdash; the compiler grabs the template's source code, fills in the parametrized gaps with the type given by the developer and creates the final object code.  For example, given:&lt;/p&gt;

&lt;pre&gt;int foo = add&amp;lt;int&amp;gt;(2, 3);
float bar = add&amp;lt;float&amp;gt;(2.4, 3.5);&lt;/pre&gt;

&lt;p&gt;The compiler gets the verbatim &lt;tt&gt;add&lt;/tt&gt; function's code from the header file, replaces &lt;tt&gt;Type&lt;/tt&gt; with &lt;tt&gt;int&lt;/tt&gt;, generates the object code for the resulting function and stores it alongside the user's binary.  The same happens with the &lt;tt&gt;float&lt;/tt&gt; instance.  Notice how the binary code is &lt;i&gt;not&lt;/i&gt; in the library where the template came from, and also notice that the user's binary has gained two new functions, one for each instantiation.&lt;/p&gt;

&lt;p&gt;So what happens?  Templates cannot take advantage of (binary) shared libraries.  Whenever the code in a template changes, the template's user is forced to rebuild his code (if he wants to get the new changes, of course).  Imagine that there was a security bug (or any other serious bug) in the template's code: you'd need to make sure to rebuild all its uses to fix the issue, something well-known by users of static binaries.&lt;/p&gt;

&lt;p&gt;Of course, the library developer could explicitly instantiate some common types in his library's binary so that the user needn't duplicate the code.  This could work in some cases, but as he cannot predict what types will the developer use, this is not a complete solution.&lt;/p&gt;

&lt;p&gt;Other developers create templates in a two-layered design.  The public template is a very thin wrapper over a private class that achieves genericity by using &lt;tt&gt;void *&lt;/tt&gt; types.  This way, the public template is unlikely to change, and the developers can safely change their internal code without requiring external rebuilds.  I think I saw this in the STL itself, or maybe in &lt;a href="http://www.trolltech.com/"&gt;QT&lt;/a&gt;, cannot remember.&lt;/p&gt;

&lt;p&gt;Summarizing: as my reader said, it makes no sense to talk about templates and ABIs, because a template never has an ABI.  It is only an API that, once compiled in third-party code, becomes part of it.  I'm now wondering how Java 1.5's templates work or if they suffer from these issues too...&lt;/p&gt;</content>
  </entry>
  <entry>
    <id>urn:lj:livejournal.com:atom1:jmmv:44985</id>
    <link rel="alternate" type="text/html" href="http://jmmv.livejournal.com/44985.html"/>
    <link rel="self" type="text/xml" href="http://jmmv.livejournal.com/data/atom/?itemid=44985"/>
    <title>C++: Inlined code and the ABI</title>
    <published>2005-10-02T13:54:49Z</published>
    <updated>2005-10-03T10:46:50Z</updated>
    <content type="html">&lt;p&gt;There are many development libraries that provide inline functions (or macros) as part of their public API.  This is often done for efficiency reasons, although some times it's done because developers don't know the consequences of doing such things (this last thing is just a guess, but it can perfectly happen).  Providing such inlined functions breaks the whole idea of encapsulation and shared libraries.  Let's see why.&lt;/p&gt;

&lt;p&gt;Consider the following simple class:&lt;/p&gt;

&lt;pre&gt; /* In foo.h. */

class foo {
    int m_value;

public:
    int get_value(void) { return m_value; }
    void set_value(int v);
    /* ... */
};

/* In foo.c; this is _not_ inlined. */
void
foo::set_value(int v)
{
    m_value = v;
}&lt;/pre&gt;

&lt;p&gt;Now imagine that this class belongs to a shared library, say &lt;tt&gt;libbar.so.1.0&lt;/tt&gt;.  Given this, our Joe user does this in his code, which is perfectly legal:&lt;/p&gt;

&lt;pre&gt;foo a;
a.set_value(5);
/* ... do whatever with 'a' ... */
int b = a.get_value();&lt;/pre&gt;

&lt;p&gt;When this code is compiled, the compiler replaces the call to &lt;tt&gt;foo::get_value()&lt;/tt&gt; with the method's code, avoiding a function call, a return and all the stack set up; all the action takes place in the user's code, not in the library.  Typically, getting a value from a structure means reading a concrete position of memory within it, described by its offset from the beginning.  OTOH, the call to &lt;tt&gt;foo::set_value()&lt;/tt&gt; is correctly made into a regular function call inside the shared library's text.&lt;/p&gt;

&lt;p&gt;Some time later, the libbar developers decide to change the internal representation of the &lt;tt&gt;foo&lt;/tt&gt; class for whatever reason.  According to the encapsulation principle used in object oriented designs, they should be able to, after all.  Let's suppose they add a new integer before the &lt;tt&gt;m_value&lt;/tt&gt; field, called &lt;tt&gt;m_id&lt;/tt&gt;.  Unwillingly, the developers have just changed the ABI of their library and, if they don't take care to update the library's major number, seriuos problems will arise.  But, why?&lt;/p&gt;

&lt;p&gt;Our Joe user again sees a new release of libbar, say 1.1, so he rebuilds and updates it in his machine, replacing &lt;tt&gt;libbar.so.1.0&lt;/tt&gt; with &lt;tt&gt;libbar.so.1.1&lt;/tt&gt;; these two libraries typically share the same soname, &lt;tt&gt;libbar.so.1&lt;/tt&gt;, because they are compatible in theory.  According to how shared libraries work, he oughtn't rebuild his application.&lt;/p&gt;

&lt;p&gt;The &lt;tt&gt;set_value()&lt;/tt&gt; call will continue to work correctly because the application will call the new function in the updated shared library.  However, the execution of &lt;tt&gt;get_value()&lt;/tt&gt; will be broken; oops!  Remember the sample code shown above?  It was compiled as an offset within the class, which is now different!  This getter will return an incorrect value, no matter what he does.  He'll be forced to rebuild his application to adjust to the new ABI.&lt;/p&gt;

&lt;p&gt;Conclusion: be very careful when defining inlined methods and macros.  If you need to fix a mistake or modify the internal representation of your code in the future, you will be unable to.  Personally, I avoid inlined code in all public interfaces, despite this introduces a small performance degradation; however, they are perfectly fine for internal code.&lt;/p&gt;

&lt;p&gt;It's a pity that careless C++ developers make so intensive use of such inlined code.  BTW, note that although this has focused on C++, the same is true for, e.g., C99, which provides an &lt;tt&gt;inline&lt;/tt&gt; keyword.&lt;/p&gt;

&lt;p&gt;&lt;b&gt;Edit (Oct 3rd)&lt;/b&gt;: Based on &lt;a href="http://www.livejournal.com/users/jmmv/44985.html?thread=43193#t43193"&gt;this reply&lt;/a&gt;, I've removed some (really minor) references to templated code from the article; they certainly didn't belong here.&lt;/p&gt;</content>
  </entry>
  <entry>
    <id>urn:lj:livejournal.com:atom1:jmmv:44629</id>
    <link rel="alternate" type="text/html" href="http://jmmv.livejournal.com/44629.html"/>
    <link rel="self" type="text/xml" href="http://jmmv.livejournal.com/data/atom/?itemid=44629"/>
    <title>New utility: verifypc</title>
    <published>2005-10-01T13:59:48Z</published>
    <updated>2005-10-01T13:59:48Z</updated>
    <content type="html">After five months or so of not touching the code, I've finally cleaned up my verifypc utility and imported it into &lt;a href="http://www.pkgsrc.org/"&gt;pkgsrc&lt;/a&gt;.  Its purpose is to sanity check the dependencies of a given package based on its calls to the &lt;a href="http://pkgconfig.freedesktop.org/wiki/"&gt;pkg-config&lt;/a&gt; program.&lt;br /&gt;&lt;br /&gt;For more information see the &lt;a href="http://mail-index.netbsd.org/tech-pkg/2005/10/01/0007.html"&gt;announcement&lt;/a&gt; in the tech-pkg@ mailing list or &lt;a href="http://www.livejournal.com/users/jmmv/32844.html"&gt;this past post&lt;/a&gt; in which I detailed the idea.</content>
  </entry>
  <entry>
    <id>urn:lj:livejournal.com:atom1:jmmv:44381</id>
    <link rel="alternate" type="text/html" href="http://jmmv.livejournal.com/44381.html"/>
    <link rel="self" type="text/xml" href="http://jmmv.livejournal.com/data/atom/?itemid=44381"/>
    <title>Lose vs. loose</title>
    <published>2005-09-30T20:55:08Z</published>
    <updated>2005-09-30T20:55:08Z</updated>
    <content type="html">Some days ago, I misspelled &lt;i&gt;lose&lt;/i&gt; as &lt;i&gt;loose&lt;/i&gt; in one of my posts.  One of the readers pointed me out the error and suggested to look at &lt;a href="http://www.queenofwands.net/d/20050909.html"&gt;this comic strip&lt;/a&gt; from &lt;a href="http://www.queenofwands.net/"&gt;Queen of Wands&lt;/a&gt; (never read it before).  I think I'll never make the same mistake again ;-)&lt;br /&gt;&lt;br /&gt;Oh, and BTW, &lt;a href="http://www.queenofwands.net/d/20050929.html"&gt;yesterday's strip&lt;/a&gt; is kind of funny too; you ought to read it.</content>
  </entry>
  <entry>
    <id>urn:lj:livejournal.com:atom1:jmmv:44131</id>
    <link rel="alternate" type="text/html" href="http://jmmv.livejournal.com/44131.html"/>
    <link rel="self" type="text/xml" href="http://jmmv.livejournal.com/data/atom/?itemid=44131"/>
    <title>Cleaning up a Debian box</title>
    <published>2005-09-26T19:27:14Z</published>
    <updated>2005-09-26T19:29:54Z</updated>
    <content type="html">I have to confess that, for a long time, I was a big &lt;a href="http://www.debian.org/"&gt;Debian&lt;/a&gt; fan; this changed when I switched to the BSDs, but I still think that it is (one of) the best GNU/Linux distribution.  This, and because its excellent hardware support, is why it's the main system on my iBook G3.&lt;br /&gt;&lt;br /&gt;As a user, it's very common to install lots of packages just to try them, followed by a quick deinstallation when you realize they don't suit your needs.  Unfortunately, following common procedures often leaves useless garbage in the file system.&lt;br /&gt;&lt;br /&gt;The first annoying thing are installed packages that provide libraries but which aren't used by any other package.  These are often called &lt;i&gt;orphan packages&lt;/i&gt; and can be listed by using the &lt;tt&gt;deborphan&lt;/tt&gt; utility (which must be installed first).  Assuming you have it, do the following to remove all orphaned libraries:&lt;br /&gt;&lt;br /&gt;&lt;tt&gt;# dpkg --purge $(deborphan)&lt;/tt&gt;&lt;br /&gt;&lt;br /&gt;Note that this in turn may obsolete other libraries, so rerun this command until &lt;tt&gt;deborphan&lt;/tt&gt; prints nothing.  Also, please bear in mind that this is dangerous if you have installed software from other means &amp;mdash; not from Debian packages &amp;mdash; as those libraries may still be used.&lt;br /&gt;&lt;br /&gt;Then we have obsolete configuration files.  Whenever you remove a package, all its files are removed except the configuration ones, in case you did some modification you want to preserve during an eventual reinstallation.  This may be OK in some scenarios but, personally, when I delete something I want it really gone.  Here comes &lt;tt&gt;dpkg&lt;/tt&gt;'s &lt;tt&gt;--purge&lt;/tt&gt; option to help, which removes all leftovers of a previously installed package.&lt;br /&gt;&lt;br /&gt;But how to purge all configuration files from packages that were once installed?  Just do the following:&lt;br /&gt;&lt;br /&gt;&lt;tt&gt;dpkg --purge $(dpkg --list | grep ^rc | awk '{ print $2; }')&lt;/tt&gt;&lt;br /&gt;&lt;br /&gt;This constructs a list of packages which are removed but still have their configuration files installed (denoted by the &lt;tt&gt;^rc&lt;/tt&gt; pattern) and passes this list to the package management utility to purge all obsolete files.</content>
  </entry>
  <entry>
    <id>urn:lj:livejournal.com:atom1:jmmv:43821</id>
    <link rel="alternate" type="text/html" href="http://jmmv.livejournal.com/43821.html"/>
    <link rel="self" type="text/xml" href="http://jmmv.livejournal.com/data/atom/?itemid=43821"/>
    <title>NFS exports lists rototill</title>
    <published>2005-09-23T12:35:34Z</published>
    <updated>2005-09-23T12:39:08Z</updated>
    <content type="html">After two weeks of work, the NFS exports lists rototill that I briefly outlined in &lt;a href="http://www.livejournal.com/users/jmmv/43121.html"&gt;this past post&lt;/a&gt; is finished and committed into &lt;a href="http://www.NetBSD.org/"&gt;NetBSD&lt;/a&gt;'s source tree.  Believe it or not, the whole set of changes was triggered by a XXX mark in mountd(8)'s code (in other words, fixing code marked as such is not always trivial).&lt;br /&gt;&lt;br /&gt;In the past, when a file system wanted to support NFS, it had to include two fields in a fixed position of its mount arguments structure due to the broken way in which mountd(8) handled the mount(2) calls.  Furthermore, each file system had to deal internally with the NFS exports list, duplicating code among all NFS-aware file systems; this feature was clearly generic, so it had to be placed in an upper generalization level.  At last, you had to use the mount(2) system call in a wired way to change the exports.&lt;br /&gt;&lt;br /&gt;This was wrong because it broke extensibility and &lt;a href="http://www.netbsd.org/Goals/system.html"&gt;code cleanliness&lt;/a&gt;: you couldn't add a new NFS-aware file system without modifying and rebuilding mountd(8).  There was also a lot of code duplication and the interface was just ugly from a design point of view.  It looked like a quick band-aid over old code to add support for more than one NFS-aware file system.&lt;br /&gt;&lt;br /&gt;The changes I just committed have centralized all NFS exports lists handling in a single place and it has been removed from the kernel's core.  This stuff is now only compiled in when the &lt;tt&gt;NFSSERVER&lt;/tt&gt; option is enabled, reducing the final kernel size by around 5KB.&lt;br /&gt;&lt;br /&gt;The next logical step is to rework mountd(8) to update the whole exports list for a given mount point atomically; this wasn't possible at all before.  The new kernel interface, introduced as a new command to the nfssvc(2), has been designed to support this functionality, although it's not used yet due to the big changes required in the userland utility.  I won't be working on this anytime soon, as I have other stuff to do before it (hence the entry I added to src/TODO).&lt;br /&gt;&lt;br /&gt;If you want to know a bit more, the &lt;a href="http://mail-index.netbsd.org/source-changes/2005/09/23/0002.html"&gt;commit message&lt;/a&gt; contains a detailed list of all the changes.&lt;br /&gt;&lt;br /&gt;PS: I have to thank Google's Summer of Code 2005 again.  I couldn't have found this issue nor had enough knowledge to fix it if I hadn't been working on tmpfs during the summer.</content>
  </entry>
  <entry>
    <id>urn:lj:livejournal.com:atom1:jmmv:43737</id>
    <link rel="alternate" type="text/html" href="http://jmmv.livejournal.com/43737.html"/>
    <link rel="self" type="text/xml" href="http://jmmv.livejournal.com/data/atom/?itemid=43737"/>
    <title>Quality of digital signals</title>
    <published>2005-09-22T20:58:14Z</published>
    <updated>2005-09-23T18:53:53Z</updated>
    <content type="html">I have seen many times people thinking that a signal has better quality if it's in digital form rather than in analog form, yet this is false.  When you convert an analog signal to a digital format, you &lt;i&gt;always&lt;/i&gt; lose quality because you are converting a continuous signal to a discrete one.  Let's see a little example:&lt;br /&gt;&lt;br /&gt;Suppose we want to digitize a 20KHz analog audio signal so that we can store it on disk.  Following the &lt;a href="http://en.wikipedia.org/wiki/Nyquist-Shannon_sampling_theorem"&gt;Nyquist theorem&lt;/a&gt;, we must take a minimum of 40K samples per second; this guarantees that we can recreate the original signal in its exact form (i.e., maximum quality).&lt;br /&gt;&lt;br /&gt;The lost of quality arises at this point: how can we represent each sample without losing precision (assuming, of course, that the sample is accurate)?  Samples are measured in a continuous scale, but in order to store them we must round their value up or down to a discrete value we can represent (think about representing a real number, which leads to the same problem).  We'd need infinite precision to store each sample in its exact form, which means infinite disk space.  Not possible.&lt;br /&gt;&lt;br /&gt;Note that the example above assumes a PCM modulation technique where each sample is codified and stored in a fixed amount of bits.  As you can imagine, any other technique will suffer from this problem.&lt;br /&gt;&lt;br /&gt;This post comes after today's &lt;a href="http://www.fib.upc.es/ca/Estudis/Assignatures/SPD.html"&gt;SPD&lt;/a&gt; class, an optional course I'm taking this semester at university.  It's all about the low level details of public data networks.  Amazing stuff, IMHO ;-)</content>
  </entry>
  <entry>
    <id>urn:lj:livejournal.com:atom1:jmmv:43398</id>
    <link rel="alternate" type="text/html" href="http://jmmv.livejournal.com/43398.html"/>
    <link rel="self" type="text/xml" href="http://jmmv.livejournal.com/data/atom/?itemid=43398"/>
    <title>Linker's link sets</title>
    <published>2005-09-18T12:20:00Z</published>
    <updated>2005-09-18T12:20:15Z</updated>
    <content type="html">&lt;p&gt;I don't know about other linkers, but GNU ld provides a very useful feature: &lt;i&gt;link sets&lt;/i&gt;.  A link set is a list of symbols constructed during &lt;i&gt;link time&lt;/i&gt; which can then be inspected in regular code.  This is very interesting in situations when you want to initialize several subsystems from a centralized place but don't know which of these will be available; that is, you don't know which ones will be in the final binary.&lt;/p&gt;

&lt;p&gt;To illustrate this feature, let's see how NetBSD manages file system initialization.  In NetBSD, you can configure which file systems you want in your kernel binary and which not.  Each file system has a &lt;tt&gt;vfs_init&lt;/tt&gt; hook that must be called during system initialization but... how to do this in a clean and extensible way?  For a moment, imagine we didn't have link sets.  In this case, NetBSD would need a function similar to the following:&lt;/p&gt;

&lt;pre&gt;void
init_file_systems(void)
{
#ifdef UFS
    ufs_init();
#endif
#ifdef MSDOSFS
    msdosfs_init();
#endif
...
#ifdef TMPFS
    tmpfs_init();
#endif
}&lt;/pre&gt;

&lt;p&gt;Isn't this ugly?  Very much, although one might support the visual ugliness.  However, the real problem is that, in order to add a new file system, you need to edit other parts of the system; this might seem acceptable in an open source project, but what if the initialization code was closed source?  You couldn't add your file system.  This clearly goes against extensibility.&lt;/p&gt;

&lt;p&gt;Using link sets, this problem goes away: each independent module is able to add itself to a global list of symbols.  Continuing our file systems example, take a look to the &lt;tt&gt;vfsinit&lt;/tt&gt; function in &lt;tt&gt;kern/vfs_init.c&lt;/tt&gt;.  The first thing you see there is the declaration (&lt;tt&gt;__link_set_decl&lt;/tt&gt;) of a new link set, called &lt;tt&gt;vfsops&lt;/tt&gt;, that will hold pointers to &lt;tt&gt;struct vfsops&lt;/tt&gt; objects.  Then, the code uses the &lt;tt&gt;__link_set_foreach&lt;/tt&gt; construction to iterate over the list, correctly initializing all the file systems.  The following is an extract of this, with &lt;i&gt;many&lt;/i&gt; details removed:&lt;/p&gt;

&lt;pre&gt;void
vfsinit(void)
{
    __link_set_decl(vfsops, struct vfsops);
    struct vfsops * const *vfsp;  /* Iterator */

    __link_set_foreach(vfsp, vfsops) {
        (*vfsp)-&amp;gt;vfs_init();
    }
}&lt;/pre&gt;

&lt;p&gt;At last, how does a module add itself to the link set?  Using the &lt;tt&gt;__link_set_add_data&lt;/tt&gt; operation, which takes the name of the link set as its first argument and the object to be added as the second one.  E.g.:&lt;/p&gt;

&lt;pre&gt;struct vfsops barops = {
    ...
    ufs_init,
    ...
};
__link_set_add_data(vfsops, barops);&lt;/pre&gt;

&lt;p&gt;As you can see, using link sets the kernel does not need to know at all which file systems are compiled into it, yet the initialization code will be executed.&lt;/p&gt;</content>
  </entry>
  <entry>
    <id>urn:lj:livejournal.com:atom1:jmmv:43121</id>
    <link rel="alternate" type="text/html" href="http://jmmv.livejournal.com/43121.html"/>
    <link rel="self" type="text/xml" href="http://jmmv.livejournal.com/data/atom/?itemid=43121"/>
    <title>Interface to change NFS exports</title>
    <published>2005-09-11T11:48:28Z</published>
    <updated>2005-09-11T11:48:28Z</updated>
    <content type="html">While adding NFS support to tmpfs, I found how &lt;a href="http://www.NetBSD.org/"&gt;NetBSD&lt;/a&gt; currently manages NFS exports from userland.  The interface is, IMHO, scary.  As NetBSD aims for clean code and design, it must be fixed.&lt;br /&gt;&lt;br /&gt;See my &lt;a href="http://mail-index.netbsd.org/tech-kern/2005/09/11/0001.html"&gt;mail to the tech-kern@ mailing list&lt;/a&gt; for more details on the issue and a preliminary patch.</content>
  </entry>
  <entry>
    <id>urn:lj:livejournal.com:atom1:jmmv:42981</id>
    <link rel="alternate" type="text/html" href="http://jmmv.livejournal.com/42981.html"/>
    <link rel="self" type="text/xml" href="http://jmmv.livejournal.com/data/atom/?itemid=42981"/>
    <title>tmpfs: Project merged into NetBSD</title>
    <published>2005-09-10T21:13:54Z</published>
    <updated>2005-09-10T21:13:54Z</updated>
    <content type="html">After listening to many queries from developers asking when tmpfs could be integrated into &lt;a href="http://www.NetBSD.org/"&gt;NetBSD&lt;/a&gt;, I finally imported the code into the CVS repository.  I'm really happy about this :-)  Development will be simplified from now on and it will be a lot easier for interested parties to test the code.  Please &lt;a href="http://mail-index.netbsd.org/tech-kern/2005/09/10/0004.html"&gt;read the announcement&lt;/a&gt; for more information.&lt;br /&gt;&lt;br /&gt;I'd like to comment now some of the improvements I've been doing during the past days, which mostly addressed optimization.  I started by removing the storage of &lt;tt&gt;.&lt;/tt&gt; and &lt;tt&gt;..&lt;/tt&gt; directory entries from directories, generating them on the fly when requested.  This was done for three reasons.  First, to remove redundancy: as &lt;tt&gt;.&lt;/tt&gt; points to the directory itself, the entry can always be generated; similarly, &lt;tt&gt;..&lt;/tt&gt; can be generated from the pointer to the parent directory stored in the nodes.  Secondly, to simplify the code: there were multiple assertions to ensure that these entries were correct and there was code to update them on file-system changes; this code was hard to understand and, as you can see, avoidable.  Lastly, to reduce memory consumption: this removed around 1KB of storage from each directory (given to a change I've done recently, this gain is lower, because entries are now a lot smaller, but still this saves 40 bytes from each directory).&lt;br /&gt;&lt;br /&gt;Then I fixed a long-standing and very important issue: the assignment of unique node numbers and generation numbers to nodes.  Among other reasons, this was done to be NFS-friendly.  See &lt;a href="http://www.livejournal.com/users/jmmv/42564.html"&gt;my previous post on NFS file handles&lt;/a&gt; for more details.&lt;br /&gt;&lt;br /&gt;At last, I removed fixed-size string buffers from nodes and directory entries, replacing them with dynamically allocated memory from a string pool.  Strings are now stored more efficiently and waste far less space.  Note that, before this change, each directory entry occupied around 255 bytes and each node took more than 1KB. As an example, the simple creation of 10K empty files previously required around 20MB of memory, whereas it now needs 1.5MB.  This should be reduced even more, but, as you can see, this is a lot better than before.&lt;br /&gt;&lt;br /&gt;And of course, several bug fixes and miscellaneous improvements were done all around.</content>
  </entry>
  <entry>
    <id>urn:lj:livejournal.com:atom1:jmmv:42564</id>
    <link rel="alternate" type="text/html" href="http://jmmv.livejournal.com/42564.html"/>
    <link rel="self" type="text/xml" href="http://jmmv.livejournal.com/data/atom/?itemid=42564"/>
    <title>NFS file handles</title>
    <published>2005-09-10T09:31:26Z</published>
    <updated>2005-09-10T09:31:26Z</updated>
    <content type="html">NFS uses a structure called a &lt;i&gt;file handle&lt;/i&gt; to uniquely identify exported files.  When a client requests to access a file, the server constructs a file handle that identifies it; from this point on, this identifier will be used in all communications between the server and the client to access that specific file.  (Look at the &lt;tt&gt;fs_vptofh&lt;/tt&gt; and &lt;tt&gt;fs_fhtovp&lt;/tt&gt; hooks in &lt;a href="http://www.NetBSD.org/"&gt;NetBSD&lt;/a&gt;'s VFS layer to see how this mapping works.)&lt;br /&gt;&lt;br /&gt;In order to identify a file univocally, you need three things: the file-system identifier (i.e., something unique to each mount point), the node number (e.g., the inode number in FFS terminology) and a generation number.  It is clear why the first two are needed, but the generation number may be confusing.  In order to explain this last concept, let's see an example:&lt;br /&gt;&lt;br /&gt;Suppose you have a file using the 1234 inode of the root file-system; let's call this &lt;tt&gt;foo&lt;/tt&gt;.  Now, you delete &lt;tt&gt;foo&lt;/tt&gt; and create a new file, called &lt;tt&gt;bar&lt;/tt&gt;, which ends up &lt;i&gt;reusing&lt;/i&gt; the 1234 inode.  These two files are clearly different, but they could look the same from the point of view of a file handle if you used the file-system number and the inode number exclusively.  Therefore, we need a third component, the generation number, that makes these two files different.  This component is incremented each time an inode is reused for a different file.&lt;br /&gt;&lt;br /&gt;So far, so good.  But now we get to the ugly part: given a file-system number, a node number and a generation number, you can generate a file handle that refers to any file within the exported file-system.  If these values were available to everybody, a malicious client could easily generate file handles to access files he is not allowed to touch.  This is why the generation number is hidden to user space: if you apply &lt;tt&gt;stat(2)&lt;/tt&gt; to a file, you'll always get a zero value in the &lt;tt&gt;st_gen&lt;/tt&gt; field (some systems may return the correct number if you are root).  Similarly, the &lt;tt&gt;getfh(2)&lt;/tt&gt; system call is restricted to the super-user.&lt;br /&gt;&lt;br /&gt;But can't a user guess the generation number?  Yes, he can.  This is why they are often generated based on a random seed, which makes the guessing difficult.  See &lt;tt&gt;fsirand(8)&lt;/tt&gt; for more information.&lt;br /&gt;&lt;br /&gt;All this explains why there is no such thing as exporting a subtree in the NFS world.  When you export a directory from a file-system, you are implicitly exporting the whole mount point because malicious file handles could be used to access files outside the subtree.&lt;br /&gt;&lt;br /&gt;Thanks go to William Studenmund for explaining me this during &lt;a href="http://NetBSD-SoC.sourceforge.net/projects/tmpfs/"&gt;tmpfs&lt;/a&gt; development.</content>
  </entry>
  <entry>
    <id>urn:lj:livejournal.com:atom1:jmmv:42455</id>
    <link rel="alternate" type="text/html" href="http://jmmv.livejournal.com/42455.html"/>
    <link rel="self" type="text/xml" href="http://jmmv.livejournal.com/data/atom/?itemid=42455"/>
    <title>FFS, LFS and MFS</title>
    <published>2005-09-09T09:05:21Z</published>
    <updated>2005-09-09T09:08:13Z</updated>
    <content type="html">&lt;p&gt;The designers of the Fast File System (FFS) organized it in two different layers aiming for flexibility and code reuse; this happened in 4.4BSD (or maybe earlier, I don't know for sure).  The upper layer communicates with the VFS and vnode code while the lower layer accesses the underlying devices and only receives requests from the upper layer.  It goes like this:&lt;/p&gt;

&lt;p&gt;&lt;tt&gt;VFS/vnode calls &amp;lt;-&amp;gt; FFS upper layer &amp;lt;-&amp;gt; FFS lower layer &amp;lt;-&amp;gt; backing device&lt;/tt&gt;&lt;/p&gt;

&lt;p&gt;The upper layer handles all logical details of a Unix file-system, abstracting, among many other things, inode representation and management, tree manipulations and verification of credentials.  It also lays out data in different blocks and passes them to the lower layer.&lt;/p&gt;

&lt;p&gt;The lower layer receives the blocks generated by the upper layer and lays them out on the physical device (e.g., a disk).  It is also responsible of reading the blocks requested by the upper layer and transferring them to it.&lt;/p&gt;

&lt;p&gt;Thanks to this design, three different lower layers were implemented, providing three file-systems:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Fast File System (FFS): It assumes that the average file size is small and that some files (those in the same directory) will be accessed all at once.  Given these assumptions, it divides the disk surface in different cylinder groups and lays out blocks that may be accessed together in the same group.  This reduces expensive seeks.&lt;/li&gt;

&lt;li&gt;Log-structured File System (LFS): It assumes that the system bottleneck are writes to the disk, so it packs all writes in a concrete area of the disk, treating the overall space as an append-only log (no seeks required).&lt;/li&gt;

&lt;li&gt;Memory File System (MFS): Reserves a contiguous region of memory and lays out blocks in it.  This is why MFS is considered inefficient, because it is using the concepts of an on-disk file-system over memory.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The different layers are clearly visible in the source code.  The &lt;a href="http://cvsweb.netbsd.org/bsdweb.cgi/src/sys/ufs/ufs/"&gt;&lt;tt&gt;src/sys/ufs/ufs&lt;/tt&gt;&lt;/a&gt; directory contains the upper layer's code while &lt;a href="http://cvsweb.netbsd.org/bsdweb.cgi/src/sys/ufs/ffs/"&gt;&lt;tt&gt;src/sys/ufs/ffs&lt;/tt&gt;&lt;/a&gt;, &lt;a href="http://cvsweb.netbsd.org/bsdweb.cgi/src/sys/ufs/lfs/"&gt;&lt;tt&gt;src/sys/ufs/lfs&lt;/tt&gt;&lt;/a&gt; and &lt;a href="http://cvsweb.netbsd.org/bsdweb.cgi/src/sys/ufs/mfs/"&gt;&lt;tt&gt;src/sys/ufs/mfs&lt;/tt&gt;&lt;/a&gt; contain the three respective lower layers.&lt;/p&gt;

&lt;p&gt;Note that the above is an over-simplification of the Real Thing (TM).  If you want detailed information, read Chapter 6 of &lt;i&gt;The Design and Implementation of the 4.4 BSD Operating System&lt;/i&gt;.&lt;/p&gt;</content>
  </entry>
  <entry>
    <id>urn:lj:livejournal.com:atom1:jmmv:42210</id>
    <link rel="alternate" type="text/html" href="http://jmmv.livejournal.com/42210.html"/>
    <link rel="self" type="text/xml" href="http://jmmv.livejournal.com/data/atom/?itemid=42210"/>
    <title>SoC: The end</title>
    <published>2005-09-01T14:58:23Z</published>
    <updated>2005-09-01T15:06:23Z</updated>
    <content type="html">So... the deadline for &lt;a href="http://www.google.com/"&gt;Google&lt;/a&gt;'s &lt;a href="http://code.google.com/summerofcode.html"&gt;Summer of Code&lt;/a&gt; 2005 program arrived some time between yesterday and today (don't know exactly due to timezones).  The final results from my side: a functional memory file-system (not efficient yet) for &lt;a href="http://www.NetBSD.org/"&gt;NetBSD&lt;/a&gt; named &lt;a href="http://NetBSD-SoC.sourceforge.net/projects/tmpfs/"&gt;tmpfs&lt;/a&gt;, as well as the beginnings of a book/article on file-system development under NetBSD.&lt;br /&gt;&lt;br /&gt;As regards the file-system itself, its code can be found in the &lt;a href="http://cvs.sourceforge.net/viewcvs.py/netbsd-soc/tmpfs/"&gt;CVS repository&lt;/a&gt;.  Despite it has some bugs and misfeatures, it is functional from the user's point of view.  The file-system's code is around 4000 lines (plus 500 from the mount utility) and the regression test suite around 2000 (half of which are license texts).  I know these numbers are low, but man... this is the hardest code I've ever written (mostly due to lack of documentation and having to reverse engineer existing stuff).  I've also written a document describing tmpfs' internals (as said in the initial proposal), which is available in the form of a manual page in the repository and is around 700 lines long.&lt;br /&gt;&lt;br /&gt;With respect to the documentation, it is not yet available online.  I'm still discussing with my mentor (Bill Studenmund) how it shall be published and I don't like it in its current form to make it public (still has many mistakes and is heavily disorganized... and is already 2500 lines long).  It looks like we both agree that it should be in the form of a (online) book, leaving room for future additions (e.g., UVM, device drivers, etc.).  However, I will also try to write a little article explaining all the steps I followed to write tmpfs.  Writing an independent article will be better because it'll let me focus on a single task and it'll be possible to mix information from several subsystems without making it look messy.  But there is still a long way to go to have these done.&lt;br /&gt;&lt;br /&gt;I would like to make it clear that despite the program has ended, I will continue working on all this stuff until it is ready to be integrated into NetBSD's source tree; all this work musn't have been in vain!  Oh, and having been part of this program has been great.  It has forced me to work on something I've always wanted to do (kernel development) but never found time to learn about it... and I've done paid development for the best free operating system! ;-)  I have to say that I've learned a &lt;i&gt;damn&lt;/i&gt; lot in these two months.&lt;br /&gt;&lt;br /&gt;And today, just as a little prize for the program's completion, I've bought myself a copy of &lt;a href="http://www.doom3.com/"&gt;Doom 3&lt;/a&gt; (because I decided to go legal a while ago, yay!) and this month's &lt;a href="http://www.ddj.com/"&gt;Dr. Dobb's Journal&lt;/a&gt; edition.  This is the first time I buy this magazine.  Why?  They will be publishing a set of articles describing SoC projects, so I want to know about their style &amp;mdash; which, as far as I've seen, is very technical, something that is nice.  Furthermore, this edition has some articles that I found interesting when I first saw them in the web site; i.e., &lt;i&gt;C++, STL, and custom pool allocators&lt;/i&gt; and &lt;i&gt;C++ exceptions and the Linux kernel&lt;/i&gt;.</content>
  </entry>
  <entry>
    <id>urn:lj:livejournal.com:atom1:jmmv:41855</id>
    <link rel="alternate" type="text/html" href="http://jmmv.livejournal.com/41855.html"/>
    <link rel="self" type="text/xml" href="http://jmmv.livejournal.com/data/atom/?itemid=41855"/>
    <title>A prompt that does not get in the way</title>
    <published>2005-08-31T12:19:01Z</published>
    <updated>2005-08-31T12:19:01Z</updated>
    <content type="html">Yesterday, I saw a screenshot of a developer's box.  His prompt was composed of two characters only: a colon and a semicolon (&lt;tt&gt;:;&lt;/tt&gt;).  This looks wired, doesn't it?  Yes, it does, but there is a rationale behind it: using this prompt, you can copy and paste complete lines from a terminal into another one and they will just work.  Why? Because those characters are ignored by the shell (the colon returns success and the semicolon starts another command).&lt;br /&gt;&lt;br /&gt;Oh yes, this prompt does not provide useful information, but that's a matter of preference.  E.g., I used a simple &lt;tt&gt;$&lt;/tt&gt; prompt for a long while, so &lt;tt&gt;:;&lt;/tt&gt; is not any worse than it.</content>
  </entry>
  <entry>
    <id>urn:lj:livejournal.com:atom1:jmmv:41488</id>
    <link rel="alternate" type="text/html" href="http://jmmv.livejournal.com/41488.html"/>
    <link rel="self" type="text/xml" href="http://jmmv.livejournal.com/data/atom/?itemid=41488"/>
    <title>SoC: Project announced</title>
    <published>2005-08-26T09:23:17Z</published>
    <updated>2005-08-26T09:23:17Z</updated>
    <content type="html">Despite I don't like doing premature announcements of my projects, I've been kind of forced to do it for &lt;a href="http://NetBSD-SoC.sourceforge.net/projects/tmpfs/"&gt;tmpfs&lt;/a&gt;.  The reason is that SoC's deadline is really close now and people should have a chance to test it.  Not to mention that the code won't suffer any serious improvements in the subsequent days, so delaying the announcement is not worth it either.&lt;br /&gt;&lt;br /&gt;You can read the announcement in &lt;a href="http://mail-index.netbsd.org/tech-kern/2005/08/26/0006.html"&gt;my mail to the tech-kern@ mailing list&lt;/a&gt;, which also includes a step-by-step guide to test tmpfs.</content>
  </entry>
  <entry>
    <id>urn:lj:livejournal.com:atom1:jmmv:41428</id>
    <link rel="alternate" type="text/html" href="http://jmmv.livejournal.com/41428.html"/>
    <link rel="self" type="text/xml" href="http://jmmv.livejournal.com/data/atom/?itemid=41428"/>
    <title>pkgsrc's strengths</title>
    <published>2005-08-24T22:07:49Z</published>
    <updated>2005-08-24T22:07:49Z</updated>
    <content type="html">Jeremy C. Reed has collected an excellent list of &lt;a href="http://www.pkgsrc.org/"&gt;pkgsrc&lt;/a&gt;'s strengths.  I encourage you to read his &lt;a href="http://mail-index.netbsd.org/tech-pkg/2005/08/24/0013.html"&gt;post to tech-pkg@&lt;/a&gt; in case you still had doubts about why to use pkgsrc ;-)&lt;br /&gt;&lt;br /&gt;His mail contains also some bad things about this packaging system, although the list is very short.  Followups to this email list some more items on the negative side.</content>
  </entry>
  <entry>
    <id>urn:lj:livejournal.com:atom1:jmmv:41037</id>
    <link rel="alternate" type="text/html" href="http://jmmv.livejournal.com/41037.html"/>
    <link rel="self" type="text/xml" href="http://jmmv.livejournal.com/data/atom/?itemid=41037"/>
    <title>Local sockets' permissions</title>
    <published>2005-08-24T12:58:53Z</published>
    <updated>2005-08-24T12:58:53Z</updated>
    <content type="html">A few days ago, I was trying &lt;a href="http://www.gnome.org/~veillard/gamin/"&gt;gamin&lt;/a&gt; under &lt;a href="http://www.NetBSD.org/"&gt;NetBSD&lt;/a&gt; which unfortunately didn't work at all.  The first problem I encountered was that it complained about the excessive permissions given to newly created local sockets (those stored in the file-system, also known as "Unix sockets" historically).  After analyzing the issue, I saw that those files were given 777 permissions, regardless of the user's umask.  Strangely, the code was explicitly checking for this mode after creation, so I was probably missing something.&lt;br /&gt;&lt;br /&gt;I wrote a little test program that creates a local socket and ran it under Linux, &lt;a href="http://www.FreeBSD.org/"&gt;FreeBSD&lt;/a&gt; and &lt;a href="http://www.OpenBSD.org/"&gt;OpenBSD&lt;/a&gt;.  All of them correctly respected the user's umask (setting the permissions to 755).  So, what was going on with NetBSD?&lt;br /&gt;&lt;br /&gt;After asking in the tech-kern@ mailing list, I was told the following: the traditional Unix behavior when creating local sockets was to give them 777 permissions to mimic real sockets (i.e., everybody can connect to them).  Therefore, the &lt;i&gt;portable&lt;/i&gt; way to create them in a secure way is to first make a directory with safe permissions (say, 700) and then create the socket inside it.&lt;br /&gt;&lt;br /&gt;However, I'm thinking about changing NetBSD to honor the user's mask in this case too (it's a trivial fix).  It does not hurt in any way and it may improve portability of some "non-portable" programs.  (Though, this will hide portability bugs in some programs, which makes me dubious about the change...)&lt;br /&gt;&lt;br /&gt;By the way, gamin was doing the right thing (creating sockets inside secure directories) so I don't know why it wanted to ensure that the sockets were "safe".</content>
  </entry>
  <entry>
    <id>urn:lj:livejournal.com:atom1:jmmv:40911</id>
    <link rel="alternate" type="text/html" href="http://jmmv.livejournal.com/40911.html"/>
    <link rel="self" type="text/xml" href="http://jmmv.livejournal.com/data/atom/?itemid=40911"/>
    <title>SoC: Status report 6</title>
    <published>2005-08-23T16:17:14Z</published>
    <updated>2005-08-23T16:17:14Z</updated>
    <content type="html">This past week has not been excessively productive because I spent some time dealing with long overdue &lt;a href="http://www.pkgsrc.org/"&gt;pkgsrc&lt;/a&gt; tasks (mainly updating &lt;a href="http://www.gnome.org/"&gt;GNOME&lt;/a&gt; to 2.10.2, the latest stable version) and was away from computer more time than usual.  Anyway, I have done a bunch of things, although they are not as visible as the work from other weeks (this is, in part, why I felt less productive).&lt;br /&gt;&lt;br /&gt;I started by adding support for local sockets, which was easy enough to do but caused panics (specially when switching &lt;tt&gt;/tmp&lt;/tt&gt; to tmpfs and starting an X session).&lt;br /&gt;&lt;br /&gt;Then I tried to switch memory pools to use anonymous memory, so that all file meta-data was pageable.  I did several clumsy tests and, while it mostly worked, the system crashed after intensive usage of the file-system (such as decompressing pkgsrc over it).  I had to give this up because I had some other stuff to do (see below) and this was consuming much time.&lt;br /&gt;&lt;br /&gt;The next thing I did was to rework the way pools were handled by making them file-system specific and by implementing a tmpfs-specific extension of them.  There are several benefits from this change, but the most important one is that tmpfs is now able to control memory usage in a fine-grained manner.&lt;br /&gt;&lt;br /&gt;Later on I added NFS support by defining the VFS operations I was missing.  This was harder than I thought, mostly because the lack of documentation, but after some time I got something that basically works.  There are still some some serious issues, so I'd not call tmpfs as NFS-ready yet.  I'm afraid that these problems are not specific to NFS; i.e., NFS is only exposing some real bugs in the code.  We'll see.&lt;br /&gt;&lt;br /&gt;Related to the previous, I was disappointed to see that I had to modify mountd's code to be able to export tmpfs file-systems.  I have some ideas to improve this, thus making mountd file-system independent, but I'll delay them until SoC's deadline has passed.&lt;br /&gt;&lt;br /&gt;Furthermore, I cleaned up some parts of the code: split the different vnode operations vectors into different source files (&lt;tt&gt;tmpfs_vnops.c&lt;/tt&gt;, &lt;tt&gt;tmpfs_fifoops.c&lt;/tt&gt; and &lt;tt&gt;tmpfs_specops.c&lt;/tt&gt;) for better readability and to get shorter files, split the main &lt;tt&gt;tmpfs.h&lt;/tt&gt; file into several headers, cleaned up inclusions and centralized some code.&lt;br /&gt;&lt;br /&gt;At last, I wrote the document describing tmpfs internals.  This is in the form of a manual page in the 9th section, and can be found in the CVS.  If you want to visualize it, you can run the following command: &lt;tt&gt;groff -Tascii -mdoc tmpfs.9 | less&lt;/tt&gt; after fetching the file.  It may lack some details, but I feel it is quite complete, though it assumes prior knowledge of how file-systems work within NetBSD.&lt;br /&gt;&lt;br /&gt;What I'm going to target this week (after prior agreement with my mentors) is the other so-promised document I've been talking about: a complete document that describes how to write file-systems for NetBSD.  I started it yesterday, and it is proving to be very difficult to explain things in a clean and well-structured way (mostly because I want to avoid big code examples without real explanations).</content>
  </entry>
</feed>
