Feature removal sparks Git flamewar
By Jake Edge
September 3, 2008
Removing features from a tool is never easy. Once there is enough of a
user base to complain about annoyances, there is also a vocal group that
uses and likes those same annoyances. The recent removal of the
git-foo
style commands from Git is just such a case, but many of those
using those commands did not find out
about the removal until after the change was made, which only served to
increase their outrage.
Until version 1.6.0, Git has always had two ways to invoke the same
functionality: git foo and git-foo. This was done by
installing many—usually more than 100—different entries into
/usr/bin for all of the different git subcommands. Some were
concerned that Git was polluting that directory, but the bigger issue was
the effect on new users. Partially because of shell autocompletion, a new
user might be overwhelmed by the number of different Git commands
available; even regular users might find it difficult to find the command
they are looking for if they have to sort through 100 or more.
Many of the Git subcommands that exist are not necessarily regularly used.
There are quite a number of "plumbing" commands that rarely, if ever,
should be invoked by users. Those are best hidden from view, which can be
done by moving them out of /usr/bin. This has been done for the
1.6.0 release, but Junio Hamano opened up a can of worms when he posted a
request for discussion about taking the
next step to the Git mailing list.
In the 1.6.0 release, the only things exposed in /usr/bin are the
git binary itself along with a few other utilities; the rest have been
moved to /usr/libexec/git-core. The hard links for each of the
git-foo commands have been maintained in the new location, which
allows folks that
still want the old behavior to get it by adding:
PATH="$PATH:$(git --exec-path)"
to
.bashrc (or some other startup file, depending on the shell).
This would allow users—especially scripts—to continue using the
dash versions of commands.
Unfortunately, for many users, the first they heard about this change was when
things stopped working after they installed 1.6.0. The Git team admittedly
did not get the word out very well; by trying to be nice, they missed an
opportunity to make users notice the change. As Hamano puts it:
But that niceness backfired. Many people seem to argue now that we should
have annoyed people by throwing loud deprecation notices to stderr when
they typed "git-foo", and we should have risked breaking their scripts iff
they relied on not seeing anything extra on the stderr.
Hamano got caught in the middle to some extent as he wasn't particularly in
favor of the original change, but at the time it was decided, there were
few advocates for keeping 100+ commands in /usr/bin. There were
several complaints about having that many commands, but chief amongst them
was confusion for new users. By removing them from /usr/bin and
providing an autocompletion script for bash that completes only a subset of
the git
subcommands, users will have fewer options to scan through—and to be
scared of.
The original plan called for moving the dash-style commands out, which has
been done, but also eventually removing the links for any of the
git-foo commands that are implemented in the core git
binary. Over time, much of the functionality that was handled by external
commands has migrated into the main git program.
It is the eventual removal of the links that Hamano is asking about in his
message, but
much of the response was flames about the step already taken; some
could not see any advantage to moving the git-foo commands out of
/usr/bin.
David Woodhouse is one of those who wants
things to remain the same:
Just don't do it. Leave the git-foo commands as they were. They
weren't actually hurting anyone, and you don't actually _gain_
anything by removing them. For those occasional nutters who
_really_ care about the size of /usr/bin, give them the _option_
of a 'make install' without installing the aliases.
Several others agreed, but that particular horse had already left the
barn. Throughout the thread, Linus Torvalds was increasingly strident about the
$PATH-based workaround, which effectively ends the discussion that
Hamano was trying to have. For that workaround to continue working, the links must be
installed in /usr/libexec/git-core. Though it strays from the
original intent, it is a reasonable compromise, one that will serve
git-traditionalists as well as new users and others who no longer want the
git-foo syntax.
Two things have helped keep the controversy alive: some documentation,
test, and example scripts still refer to dash-style commands, but worse
than that, one must do man git-foo to get the man page for that
subcommand. It is a convention within the Git community to use the
dash style when referring to commands in text, which explains some of the
usage. Because man requires a single argument, the dash style is
used there as well, though git help foo is a reasonable
alternative. For users who started relatively early with Git, and are aware of
the dash style commands, these examples further muddy the water.
It is a difficult problem. Projects must have room to change, but once
users become used to a particular way of doing things, they will resist
changing—sometimes quite loudly. As Petr "Pasky" Baudis points out, though, Git
is still evolving:
You can't ask us to stop making any incompatible changes - Git is still
too young for that and it's UI got evolved, not designed. But we do
document the changes we do, even though we might do a better job
*spreading* the word.
The Git developers still see it as a young tool that may still undergo some
fairly substantial modifications, while the hardcore users see it is a
fixed tool that they use daily—or more frequently—to get work
done. The tension between those two views is what leads to flamewars like
we have seen here. Certainly the Git folks could have done a much better
job in getting the word out—Hamano was looking for suggestions on how to
do that better in his original post—but users are going to have to be
flexible as well.
Comments (22 posted)
DRI, BSD, and Linux
By Jonathan Corbet
September 2, 2008
The
Direct Rendering
Infrastructure project has long been working toward improved 3D
graphics support in free operating systems. It is a crucial part of the
desktop Linux experience, but, thus far, DRI development has been done in
a relatively isolated manner. Development process changes which have the potential
to make life better for Linux users are in the works, but, sometimes,
that's not the only thing that matters.
The DRI project makes its home at freedesktop.org. Among other
things, the project maintains a set of git repositories representing
various views of the current state of DRI development (and the direct
rendering manager (DRM) work in particular). This much is not unusual;
most Linux kernel subsystems have their own repository at this point. The
DRM repository is different, though, in that it is not based on any Linux
kernel tree; it is, instead, an entirely separate line of development.
That separation is important; it means that its development is almost
entirely disconnected from mainline kernel development. DRM patches going
into the kernel must be pulled out of the DRM tree and put into a form
suitable for merging, and any changes made within the kernel tree must be
carefully carried back to the DRM tree by hand. So this work is not just
an out-of-tree project; it's an entirely separate project producing code
which is occasionally turned into a patch for the Linux kernel. It is
not surprising that DRM and the mainline tend not to follow each other
well. As Jesse
Barnes put it recently:
Things are actually worse than I thought. There are some fairly
large differences between linux-core and upstream, some of which
have been in linux-core for a long time. It's one thing to have an
out-of-tree development process but another entirely to let stuff
rot for months & years there.
The result of all this has been a lot of developer frustration, trouble getting code merged, concerns that the
project is hard for new developers to join, and more. As the DRM
developers look to merge more significant chunks of code (GEM, for example), the pressure
for changes to the development process has been growing.
So Dave Airlie's recent announcement
of a proposed new DRM development process did not entirely come as a
surprise. There are a number of changes being contemplated, but the core
ones are these:
- The DRM tree will be based on the mainline kernel, allowing for the
easy flow of patches in both directions. The old tree will be no
more.
- A more standard process for getting patches to the upstream kernel
will be adopted; these will include standard techniques like topic
branches and review of patches on the relevant mailing lists.
- Users of the DRM interface will not ship any releases depending on DRM
features which are not yet present in the mainline kernel.
The result of all this, it is hoped, will be a development process which is
more efficient, more tightly coupled to the upstream kernel, and more
accessible for developers outside of the current "DRM cabal." These are
all worthy objectives, but there may also be a cost associated with these
changes resulting from the unique role the DRI/DRM project has in the free
software community.
There is clearly a great deal of code shared between Linux and other free
operating systems, and with the BSD variants in particular. But that
sharing tends not to happen at the kernel level. The Linux kernel is vastly
different from anything BSD-derived, so moving code between them is never a
straightforward task. GPL-licensed code is not welcome in
BSD-licensed kernels, naturally, making it hard for code move from Linux
to BSD even when it makes sense from a technical point of view. When
code moves from BSD to Linux, it often brings a certain amount of acrimony
with it. So, while ideas can and do move freely, there is little sharing
of code between free kernels.
One significant exception is the DRM project, which is also used in most versions
of BSD. One of the reasons behind the DRM project's current repository
organization is the facilitation of that cooperation; there are separate
directories for Linux code, BSD code, and code which is common to both.
Developers from all systems contribute to the code (though the BSD
developers are far outnumbered by their Linux counterparts), and they are
all able to use the code in their kernels. When working in the common code
directory, developers know to be careful about not breaking other systems.
All told, it is a bit of welcome collaboration in an area where development
resources have tended to be in short supply - even if it benefits the BSD
side more than Linux.
Changing the organization of the DRM tree to be more directly based on
Linux seems unlikely to make life easier for the BSD developers. Space for
BSD-specific code will remain available in the DRM repository, but turning
the "shared-code" directory into code in the Linux driver tree will make
its shared status less clear, and, thus, easier for Linux developers to
break on BSD. Additionally, it seems clear that this code
may become more Linux-specific; Dave Airlie says:
However I am sure that we will see more of a push towards using
Linux constructs in dri drivers, things like idr, list.h, locking
constructs are too much of a pain to reinvent for every driver.
Much of this functionality can be reproduced through compatibility layers
on the BSD side, but it must carry a bit of a second-class citizen feel.
Dave has, in fact, made that state of affairs clear:
The thing is you can't expect equality, its just not possible,
there are about 10-15 Linux developers, and 1 Free and 1 Open BSD
developer working on DRM stuff at any one time, so you cannot
expect the Linux developers to know what the BSD requirements are.
The fact that fewer people will be able to commit to the new repository -
in fact, it may be limited to Dave Airlie - also does not help. So FreeBSD
developer Robert Noland, while calling this proposal "the most fair" of any
he has heard, is far from sure that he will
be able to work with it:
I am having a really difficult time seeing what benefit I get from
continuing to work in drm.git with this proposed model. While all
commits to master going through the mailing list, I don't
anticipate that I have any veto power or even delay powers until I
can at least prevent imports from breaking BSD. Then once I do get
it squared away, I'm still left having to send those to the ML and
wait for approval to push the fixes. I can just save myself that
part of the hassle and work privately. If I'm going to have to
hand edit and merge every change, I don't see how it is really any
harder to do that in my own repo, where I'm only subject to FreeBSD
rules.
On the other hand, it's worth noting that OpenBSD developer Owain Ainsworth
already works in his own repository and seems
generally supportive of these changes.
Given the difference between the numbers of Linux-based
and BSD-based developers, it seems almost certain that a more
Linux-friendly process will win over. There is one rumored change which
will not be happening, though: nobody is proposing to relicense the DRM
code to the GPL. The DRM developers are only willing to support BSD to a
certain point, but they certainly are not looking to make life harder for
the BSD community. So they will try to accommodate the BSD developers
while moving to a more Linux-centric development model; that is how things
are likely to go until such a time as the BSD community is able to bring
more developers to the party.
Comments (27 posted)
The Kernel Hacker's Bookshelf: UNIX Internals
September 3, 2008
This article was contributed by Valerie Henson
Back in 2001, I landed my (then) dream job as a full-time Linux kernel
developer and distribution maintainer for a small embedded systems company.
I was thrilled - and horrified. I'd only been working as a programmer
for a couple of years and I was sure it was only a matter of time
before my new employer figured out they'd hired an idiot. The only
solution was to learn more about operating systems, and quickly. So I
pulled out my favorite operating systems textbook and read and re-read
it obsessively over the course of the next year. It worked well
enough that my company tried very hard to convince me not to quit when
I got bored with my "dream job" and left to work at Sun.
That operating systems textbook was
UNIX
Internals by Uresh Vahalia. UNIX Internals is a careful, detailed
examination of multiple UNIX implementations as they evolved over
time, from the perspective of both the academic theorist and the
practical kernel developer. What makes this book particularly
valuable to the practicing operating systems developer is that the
review of each operating systems concept - say, processes and threads
- is accompanied by descriptions of specific implementations and their
histories - say, threading in Solaris, Mach, and Digital UNIX. Each
implementation is then compared on a number of practical levels,
including performance, effect on programming interfaces, portability,
and long-term maintenance burden - factors that Linux developers care
passionately about, but are seldom considered in the academic
operating systems literature.
UNIX Internals was published in 1996. A valid question is whether a
book on the implementation details of UNIX operating systems published
so long ago is still useful today. For example, Linux is only
mentioned briefly in the introduction, and many of the UNIX variants
described are now defunct. It is true that UNIX Internals holds
relatively little value for the developer actively staying up to date
with the latest research and development in a particular area.
However, my personal experience has been that many of the problems
facing today's Linux developers are described in this book - and so
are many of the proposed solutions, complete with the unsolved
implementation problems. More importantly, the analysis is often
detailed enough that it describes exactly the changes needed to
improve the technique, if only anyone took the time to implement them.
In the rest of this review, we'll cover two chapters of UNIX Internals
in detail, "Kernel Memory Allocation" and "File System
Implementations." The chapter on kernel memory allocation is an
example of the historical, cross-platform review and analysis that
sets this book apart, covering eight popular allocators from several
different flavors of UNIX. The chapter on file system implementations
shows how lessons learned from the oldest and most basic file system
implementations can be useful when solving the latest and hottest file
system design problems.
Kernel Memory Allocation
The kernel memory allocator (KMA) is one of the most
performance-critical kernel subsystems. A poor KMA implementation
will hurt performance in every code path that needs to allocate or free
memory. Worse, it will fragment and waste precious kernel memory -
memory that can't be easily freed or paged out - and pollute hardware
caches with instructions and data used for allocation management.
Historically, a KMA was considered pretty good if it only wasted 50%
of the total memory allocated by the kernel.
Vahalia begins with a short conceptual description of kernel memory
allocation and then immediately dives into practical implementation,
starting with page-level allocation in BSD. Next, he describes memory
allocation in the very earliest UNIX systems: a collection of
fixed-size tables for structures like inodes and process table
entries, occasional "borrowing" of blocks from the buffer cache, and a
few subsystem-specific ad hoc allocators. This primitive approach
required a great deal of tuning, wasted a lot of memory, and made the
system fragile.
What constitutes a good KMA? After a quick review of the functional
requirements, Vahalia lays out the criteria he'll use to judge the
allocators: low waste (fragmentation), good performance, simple
interface appropriate for many different users, good alignment,
efficient under changing workloads, reassignment of memory allocated
for one buffer size to another, and integration with the paging
system. He also takes into consideration more subtle points, such as
the cache and TLB footprint of the KMA's code, along with cache and
lock contention in multi-processor systems.
[PULL QUOTE:
This is an
example of how even the oldest and clunkiest algorithms can influence the
design of the latest and greatest.
END QUOTE]
The first KMA reviewed is the resource map allocator, an extremely
simple allocator using a list of <base, size> pairs
describing each free segment of memory, sorted by base address. The
charms of the resource map allocator include simplicity and allocation
of exactly the size requested; the vices include high fragmentation
and poor performance under nearly every workload. Even this
allocation algorithm is useful under the right circumstances; Vahalia
describes several subsystems that still use it (System V semaphore
allocation and management of free space in directory blocks on some
systems) and some minor tweaks that improve the algorithm. One tweak
to the resource map allocator keeps the description of each free
region in the first few bytes of the region, a technique later used in
the state-of-the-art SLUB allocator in the Linux kernel. This is an
example of how even the oldest and clunkiest algorithms can influence the
design of the latest and greatest.
Each following KMA is discussed in terms of the problems it solves
from previous allocators, along with the problems it introduces. The
resource map's sorted list of base/size pairs is followed by
power-of-two free lists with a one-word in-buffer header (better
performance, low external fragmentation, but high internal
fragmentation, esp. for exact power-of-two allocations), the
McKusick-Karels allocator (power-of-two free lists optimized for
power-of-two allocation; extremely fast, but prone to external
fragmentation), the buddy allocator (buffer splitting on power-of-two
boundaries plus coalescing of adjacent free buffers; poor performance
due to unnecessary splitting and coalescing), and the lazy buddy
allocator (buddy plus delayed buffer coalescing; good steady-state
performance but unpredictable under changing workloads). The
accompanying diagrams of the data structures and buffers used to
implement each allocator are particularly helpful in understanding the
structure of the allocators.
After covering the simpler KMAs, we get into more interesting
territory: the zone allocator from Mach, the hierarchical allocator
from Dynix, and the SLAB allocator, originally implemented on Solaris
and later adopted by several UNIXes, including Linux and the BSDs.
Mach's zone allocator is the only fully garbage-collected KMA studied,
with the concomitant unpredictable system-wide performance slowdowns
during garbage collection, which would strike it from most developers'
lists of useful KMAs. But as with the resource map allocator, we
still have lessons to learn from the zone allocator. Many of the
features of the zone allocator also appear in the SLAB allocator,
commonly considered the current best-of-breed KMA.
The zone allocator creates a "zone" of memory reserved for each class
of object allocated (e.g., inodes), similar to kmem caches in the
later SLAB allocator. Pages are allocated to a zone as needed, up to
a limit set at zone allocation time. Objects are packed tightly
within each zone, even across pages, for very low internal
fragmentation. Anonymous power-of-two zones are also available. Each
zone has its own free list and once a zone is set up, allocation and
freeing simply add and remove items from the per-zone free list (free
list structures are also allocated from a zone). Memory is reclaimed
on a per-page basis by the garbage collector, which runs as part of
the swapper task. It uses a two-pass algorithm: the first pass counts
up the number of free objects in each page, and the second pass frees
empty pages. Overall, the zone allocator was a major improvement on
previous KMAs: fast, space efficient, and easy to use, marred only by
the inefficient and unpredictable garbage collection algorithm.
The next KMA on the list is the hierarchical memory allocator for
Dynix, which ran on the highly parallel Sequent S2000. One of the
major designers and implementers is our own Paul McKenney, familiar to
many LWN readers as the progenitor of the read-copy-update (RCU)
system used in many places in the Linux kernel. The goal of the Dynix allocator was
efficient parallel memory allocation, in particular avoiding lock
contention between processors. The solution was to create several
layers in the memory allocation system, with per-cpu caches at the
bottom and collections of large free segments at the top. As memory
is freed or allocated, regions move up and down one level of the
hierarchy in batches. For example, each per-cpu cache has two free
lists, one in active use and the other in reserve. When the active
list runs out of free buffers, the free buffers from the reserve list
are moved onto it, and the reserve list replenishes itself with
buffers from the global list. All the work requiring synchronization
between multiple CPUs happens in one big transaction, rather than
incurring synchronization overhead on each buffer allocation.
The Dynix allocator was a major advance: 3 - 5 times faster than the
BSD allocator even on a single CPU. Its memory reclamation system was
far more efficient than the zone allocator's, performed on an on-going
basis with bounded worst case performance on each operation.
Performance on SMP systems was unparalleled.
The final KMA in this chapter is the SLAB allocator, initially
implemented on Solaris and later re-implemented on Linux and BSD. The
SLAB allocator refined some existing techniques (simple allocation/free
computations for small cache footprint, per-object caches) and
introduced several new ones (cache coloring, efficient object reuse).
The result is an allocator that was both the best performing and the
most efficient by a wide margin - only 14% fragmentation versus 27%
for the SunOS 4.1.3 sequential-fit allocator, 45% for the 4.4BSD
McKusick-Karel allocator, and 46% for the SunOS 5.x buddy allocator.
Like the zone allocator, SLAB allocates per-object caches (along with
anonymous caches in useful sizes) called kmem caches. Each cache has
an associated optional constructor and destructor function run on the
objects in a newly allocated and newly freed page, respectively (though the
destructor has since been removed in the Linux allocator).
Each cache is a doubly-linked list of slabs - large contiguous chunks
of memory. Each slab keeps its slab data structure at the end of the
slab, and divides the rest of the space into objects. Any leftover
free space in the slab is divided between the beginning and end of the
objects in order to vary the offset of objects with respect to the CPU
cache, improving cache utilization (in other words, cache coloring).
Each object has an associated 4-byte free list pointer.
The slabs within each kmem cache are in a doubly linked list, sorted
so that free slabs are located at one end, fully allocated slabs at
the other, and partially allocated slabs in the middle. Allocations
always come from partially allocated slabs before touching free
slabs. Freeing an object is simple: since slabs are always the same
size and alignment, the base address of the slab can be calculated
from the address of the object being freed. This address is used to
find the slab on the doubly linked list. Free counts are maintained
on an on-going basis. When memory pressure occurs, the slab allocator
walks the kmem caches freeing the free slabs at the end of the cache's
slab list. Slabs for larger objects are organized differently, with
the slab management structure allocated separately and additional
buffer management data included.
This section of UNIX Internals has aged particularly well, partly
because the SLAB allocator continues to work well on modern systems.
As Vahalia notes, the SLAB allocator initially lacked optimizations
for multi-processor systems, but these were added shortly afterward,
using many of the same techniques as the Dynix hierarchical allocator.
Since then, most production kernel memory allocators have been
SLAB-based. Recently, Christoph Lameter rewrote SLAB
to get the SLUB allocator for Linux; both are available as kernel
configuration options. (The third option, the SLOB allocator, is not
related to SLAB - it is a simple allocator optimized for small
embedded systems.) When viewed in isolation, the SLAB allocator may
appear arbitrary or over-complex; when viewed in the context of
previous memory allocators and their problems, the motivation behind
each design decision is intuitive and clear.
File Systems Implementations
UNIX Internals includes four chapters on file systems, covering the
user and kernel file system interface (VFS/vnode), implementations of
on-disk and in-memory file systems, distributed/network file systems,
and "advanced" file system topics - journaling, log-structured file
systems, etc. Despite the intervening years, these four chapters are
the most comprehensive and practical description of file systems
design and implementation I have yet seen. I definitely recommend it
over
UNIX
File System Design and Implementation - a massive sprawling book
which lacks the focus and advanced implementation details of UNIX
Internals.
The chapter on file systems implementations is too packed with useful
detail to review fully in this article, so I'll focus on the points
that are relevant to current hot file system design problems. The
chapter describes the System V File System (s5fs) and Berkeley Fast
File System (FFS) implementations in great detail, followed by a
survey of useful in-memory file systems, including tmpfs, procfs
(a.k.a. /proc file system), an early variant of a device file
system called specfs, and a sysfs-style interface for managing
processors. This chapter also covers the implementation of buffer
caches, inode caches, directory entry caches, etc. One of the
features of this chapter (as elsewhere in the book) is the carefully
chosen bibliography. Bibliographies in research papers serve a double
purpose as demonstrations of the authors' breadth of knowledge in the
area and tend to be cluttered with more marginal references; the
per-chapter bibliographies in UNIX Internals list only the most
relevant publications and make excellent supplementary reading guides.
System V File System (s5fs) evolved from the first UNIX file system. The
on-disk layout consisted of a boot block followed by a superblock
followed by a single monolithic inode table. The remainder of the
disk is used for data and indirect blocks. File data blocks are
located via a standard single/double/triple indirect block scheme.
s5fs has no block or inode allocation bitmaps; instead it maintains
on-disk free lists. The inode free list is partial; when no more free
inodes are on the list, it is replenished by scanning the inode table.
Free blocks are tracked in a singly linked list rooted in the
superblock - a truly terrifying design from the point of view of file
system repair, especially given the lack of backup superblocks.
In many respects, s5fs is simultaneously the simplest and the worst
UNIX file system possible: its throughput was commonly as little as 5%
of the raw disk bandwidth, it was easily corrupted, it had a 14
character limit on file names, and so on. On the other hand, elements
of the s5fs design have come back into vogue, often without addressing
the inherent drawbacks still unsolved in the intervening decades.
The most striking example of a new/old design principle illustrated by
s5fs is the placement of most of the metadata in one spot. This
turned out to be a key performance problem for s5fs, as every uncached
file read virtually guaranteed a disk seek of non-trivial magnitude
between the location of the metadata at the beginning of the disk and
the file data, located anywhere except the beginning of the disk. One
of the major advances of FFS was to distribute inodes and bitmaps
evenly across the disk and allocate associated file data and indirect
blocks nearby. Recently, collecting metadata in one place has
returned as a way to optimize file system check and repair time as
well as other metadata-intensive operations. It also appears in
designs that keep metadata on a separate high-performance device
(usually solid state storage).
The problems with these schemes are the same as the first time around.
For the fsck optimization case, most normal workloads will suffer from
the required seek for reads of file data from uncached inodes (in
particular, system boot time would suffer greatly). In the separate
metadata device case, the problem of keeping a single,
easily-corrupted copy of important metadata returns. Currently, most
solid-state storage is less reliable than disk, yet most proposals to
move file system metadata to solid state storage make no provision for
backup copies on disk.
Another cutting edge file system design issue first encountered in
s5fs is backup, restore, and general manipulation of sparse files.
System administrators quickly discovered that it was possible to
create a user-level backup that could not be restored because the
tools would attempt to actually write (and allocate) the zero-filled
unallocated portions of sparse files. Even more intelligent tools
that do not explicitly write zero-filled portions of files still had
to pointlessly copy pages of zeroes out of the kernel when reading
sparse files. In general, the file and socket I/O interface requires
a lot of ultimately unnecessary copying of file data into and out of
the kernel for common operations. It has only been in the last few
years that more sophisticated file system interfaces have been
proposed and implemented, including SEEK_HOLE/SEEK_DATA
and splice() and friends.
The chapters on file systems are definitely frustratingly out of date,
especially with regard to advances in on-disk file system design.
You'll find little or no discussion of copy-on-write file systems,
extents, btrees, or file system repair outside of the context of
non-journaled file systems. Unfortunately, I can't offer much in the
way of a follow-up reading list; most of the papers in my
file systems reading list
are covered in this book (exceptions include the papers on soft
updates, WAFL, and XFS). File systems developers seem to publish less
often than they used to; often the options for learning about the
cutting edge are reading the code, browsing the project wiki, and
attending presentations from the developers. Your next opportunity
for the latter is the Linux
Plumbers Conference, which has a number of file system-related
talks.
Another major flaw in the book, and one of the few places where
Vahalia was charmed by an on-going OS design fad, is the near-complete
lack of coverage of TCP/IP and other networking topics (the index
entry for TCP/IP lists only two pages!). Instead, we get an entire
chapter devoted to streams, at the time considered the obvious next
step in UNIX I/O. If you want to learn more about UNIX networking
design and implementation, this is the wrong book; buy some of the
Stevens and Comer networking books instead.
Summary
UNIX Internals was the original inspiration for the Kernel Hacker's
Bookshelf series, simply because you could always find it on the
bookshelf of every serious kernel hacker I knew. As the age of the
book is its most serious weakness, I originally intended to wait until
the planned second edition was released before reviewing it. To my
intense regret, the planned release date came and went and the second
edition now appears to have been canceled.
UNIX Internals is not the right operating systems book for everyone;
in particular, it is not a good textbook for an introductory operating
systems course (although I don't think I suffered too much from the
experience). However, UNIX Internals remains a valuable reference book
for the practicing kernel developer and a good starting point for
the aspiring kernel developer.
Comments (38 posted)
Page editor: Jonathan Corbet
Inside this week's LWN.net Weekly Edition
- Security: Find SQL injection vulnerabilities with sqlmap; New vulnerabilities in ruby, slash, wordnet.
- Kernel: Linux 3.0?; High-resolution timeouts; SCHED_FIFO and realtime throttling.
- Distributions: Spinning Fedora; PLD Live 2.0 beta3; Webconverger update; Tin Hat Linux
- Development: Cinelerra 4 arrives, KDE development changes, Google Chrome comic book, Kuchling on Python 2.6, new versions of Rivendell, rsplib, MySQL Admin Tools, SQLite, ClamAV, oVirt, Apache Lenya, Senayan 3, Jokosher, Openbravo POS, KDE, Elisa, VMPK, SABnzbdPlus, Roundup, GCC, ftputil, LEO.
- Press: Strip mining of open source, CSI Stick grabs cell phone data, Intel acquires Opened Hand, interviews with Krita developers and Sam Ramji, reviews of Fermi Linux, iRex iLiad and Linux Twitter clients, Red Hat's Perl bug.
- Announcements: GNU Project's 25th anniversary, Perl Summer of Code status, Perl Grant results, World Day Against Software Patents, Novell and SGI financials, MySQL Conf cfp, LF end user summit, MontaVista Vision 2008.
Next page:
Security>>