Linux

KDE 3.3 Feels Settled

I upgraded my main workstation to KDE 3.3 because I wanted the newer applications, not because I was looking for excitement. Desktop upgrades have supplied quite enough excitement already.

My first attempt was the usual impatient one: replace the packages, keep every old setting, and hope. The desktop started, but a couple of panels behaved oddly and Konqueror inherited some settings that no longer made much sense. I briefly blamed KDE. Then I tried a fresh user account and discovered that my carefully accumulated configuration was the real antique.

What impressed me was how little else needed attention. Session restoration brought back the applications I expected. The file manager, terminal, editor, and control modules felt like parts of one desktop rather than strangers sharing a theme. Even mundane details such as keyboard shortcuts were consistent enough that I stopped thinking about them.

That is what maturity looks like to me. It is not a spectacular new dialog. It is being able to spend the afternoon in C++ rather than repairing the environment used to write it.

I copied only the settings I understood into the fresh account and left the archaeological layers behind. KDE 3.3 may not make for dramatic dinner conversation, but a desktop that gets out of the way is doing its job very well.

Watching Latency on Linux 2.6

I have been comparing two Linux 2.6 configurations for a workstation: one with kernel preemption enabled and one without it. Looking only at total build time made them appear nearly identical, while using the machine made them feel different. The missing measurement was latency.

Throughput asks how much work finishes in an interval. Latency asks how long a particular piece of work waits. A kernel build is a reasonable throughput load, but its completion time does not reveal that an audio process waited long enough to miss a deadline or that keyboard input paused for a fraction of a second.

My crude but useful test runs the same build while playing audio, copying a large file, and interacting with KDE. I record build time, note audio underruns reported by the application, and repeat enough times to distinguish a pattern from one lucky run.

time make -j2 bzImage

The O(1) scheduler helps when many tasks are runnable. Its priority arrays and per-CPU run queues keep selection costs predictable, while interactive heuristics favour tasks that sleep and wake frequently. But the scheduler cannot run a task until the current execution context can be switched.

That is where kernel preemption matters. With it enabled, ordinary kernel code can be preempted when no lock or other critical condition forbids it. An interactive task awakened during a long system call may run sooner. Interrupt handlers and protected sections remain non-preemptible, so a poor driver can still dominate worst-case delay.

On my machine, enabling preemption does not materially improve the build time. It does reduce occasional input stalls and audio trouble under mixed I/O load. That is the result I expected: better responsiveness, not newly manufactured processor cycles.

Thread behaviour can alter the picture too. NPTL mutexes stay in userspace when uncontended and use futex operations when a thread must sleep or wake. A heavily contended threaded program may therefore create a very different scheduling load from one with mostly private work. Counting threads alone says little; runnable and blocked states matter.

I also test without excessive parallelism. Starting far more compile jobs than processors can turn the test into a contest between memory pressure, disk traffic, and scheduling. That may resemble a real workload, but it is a poor way to isolate one mechanism.

The caveat is that my observations are not hard real-time guarantees. General-purpose Linux still has sources of unbounded or hardware-dependent delay, and an average hides the worst pause. For desktop tuning, however, repeated underrun counts and interaction under a controlled load tell me more than one impressive jobs-per-minute number.

I am keeping preemption enabled on the workstation and evaluating it separately on servers. A server handling many requests may care about response-time distribution, but a batch machine may prefer the smallest scheduling overhead. There is no universally fast switch. First decide whether the itch is throughput or latency; only then does the benchmark know what question to answer.

Moving from XFree86 to X.Org

I moved a workstation from XFree86 to the X.Org server this week. The machine runs KDE all day and uses direct rendering, so my goal was not to celebrate a fork. It was to change the plumbing without making the desktop notice.

The reason for the move is now familiar. XFree86 4.4 adopted a licence clause that major free software distributors consider unacceptable or incompatible with how they combine software. X.Org X11R6.7 provides a continuation based on the earlier code and the broader development tree, under licences distributions are prepared to ship.

I let the distribution packages perform the replacement. This matters because the server is only one part of X: client libraries, fonts, loadable modules, drivers, and configuration paths must agree. Hand-installing a server over packaged files is an excellent way to create a system owned jointly by two package databases and nobody in particular.

Before upgrading, I saved the current X configuration and recorded the working video driver, horizontal and vertical monitor ranges, mouse protocol, keyboard layout, and enabled modules. I also made sure I could log in on a text console and knew how to stop the display manager.

The existing configuration required very little adjustment. Some installations use xorg.conf, while compatibility with an existing XF86Config may be provided. I prefer the new filename once the migration works; ambiguity is not a feature I need in emergency configuration.

The first test was a plain server start, followed by keyboard, mouse, resolution, and font checks. Then I tested KDE and direct rendering:

glxinfo | grep direct

That answer alone is not enough, but it quickly exposes a missing DRI module or mismatched userspace library. I also ran a 3D application and checked the X server log for modules that failed to load. A fast-looking spinning object is not a substitute for reading errors, though it is more festive.

Remote X clients and font paths deserve testing if the machine uses them. The wire protocol remains X11, but package changes can alter which font server or directories are configured. The migration should preserve capabilities, not just produce a local terminal window.

In normal use, KDE behaves exactly as it should: unexcited. Applications do not need to know whether the server came from XFree86 or X.Org. The visible result is deliberately boring.

The interesting change is organisational. Driver and extension work now has a development home tied more closely to the larger desktop community. That does not guarantee perfect engineering or rapid releases, but active collaboration is preferable to waiting behind a project boundary that many contributors had found difficult.

My advice remains to use distribution packages and retain a console escape route. This transition is technically conservative, but X sits underneath the entire graphical session. Even boring plumbing can flood the house when replaced casually.

Letting udev Name the Devices

I have been trying udev on a Linux 2.6 test installation because I want removable devices to receive useful permissions without maintaining a giant static /dev. The project is still young, so this is an experiment rather than my new universal recipe.

The mechanism is pleasantly divided. The kernel discovers hardware and emits a hotplug event. Sysfs exposes the device and its attributes under /sys. A userspace helper uses that information and its rules to create or remove the appropriate node in /dev.

This means policy lives in userspace. The kernel does not need to decide which local group may open a scanner or what friendly name I prefer for a particular disk. It reports identity and major/minor numbers; udev applies the administrator’s rule.

For debugging, I start with sysfs rather than guessing a rule from the device node:

find /sys/class -name dev -print

The dev attribute contains the major and minor number for devices that have one. Following the device links reveals parent hardware and useful attributes. The exact early rule syntax and available helper programs are changing, so I keep rules small and check the documentation shipped with the installed version instead of copying an example for some other release.

My test sequence is equally small. I boot with a conventional device setup available as a fallback, start udev, attach one known USB device, and watch both the system log and /dev. I verify the node type, major/minor number, owner, group, and mode before opening it from an application.

Permissions are the easiest part to get subtly wrong. Creating the correct node with mode 0666 may make the test pass while giving every local user access to hardware that should be restricted. A group-based rule is usually a better policy. Convenience should not arrive disguised as an accidental security decision.

Persistent naming is the more interesting promise. Kernel names can depend on discovery order. Userspace can use stable attributes to select a consistent name for a known device. But choose attributes that are genuinely stable and unique; a generic product string shared by every unit is neither.

I like the architecture because it keeps detection in the kernel and local policy outside it. I remain cautious because early boot needs device nodes before much userspace is running, and distributions must integrate the pieces carefully. For now I am testing one class of device at a time. Dynamic /dev is useful, but a missing root disk remains impressively dynamic in the wrong direction.

Moving a Real Machine from Linux 2.4 to 2.6

I have now moved a machine I actually depend upon from Linux 2.4 to 2.6. Test boxes are excellent for discovering that a kernel boots. A working machine is better at discovering the scanner, firewall rule, and obscure filesystem one forgot to test.

The obvious approach is to install the new kernel and reboot. The correct approach begins with an inventory. I wrote down the storage controller, root filesystem, network devices, sound hardware, mounted filesystems, firewall setup, and every module not supplied by the kernel tree. If a component is required to boot or reach the network, I want its exact name before changing anything.

I then upgraded the required userspace while still running 2.4. module-init-tools understands 2.6 modules and supplies compatibility behaviour for a 2.4 boot. Recent procps tools understand newer /proc details and NPTL process presentation. Filesystem utilities must support the on-disk filesystems regardless of which kernel initiated the repair.

The important point is coexistence. I did not overwrite the old kernel image, old modules, or boot entry. My boot loader contains distinct choices, and I tested selecting 2.4 after installing the new tools. A rollback that has never been attempted is a comforting theory.

Building the first kernel

I used the 2.4 configuration as a reference, not scripture. make oldconfig carries choices forward and asks about new options, but subsystems changed between the series. I read the help for storage, input, sound, device filesystems, networking, and processor options instead of accepting every default at speed.

For the first build, the disk controller and root filesystem went directly into the kernel. This avoids depending on a new module loader and a new initial ramdisk during the same boot. Once the plain configuration worked, I made less essential drivers modular.

make oldconfig
make bzImage
make modules
make modules_install

The exact image installation is distribution and architecture dependent, so I copied it using the same procedure as the existing packaged kernel and created a separate boot-loader stanza. I also saved .config beside the image with a matching name.

Linux 2.6 uses sysfs for its device model. My startup scripts mount it at /sys:

mount -t sysfs none /sys

I kept the existing /dev arrangement for the first migration. Early udev is interesting and I intend to test it, but changing kernel, module format, device discovery, and device-node management in one reboot produces a beautiful failure with too many suspects.

The first boot is only the start

The machine reached a login prompt immediately, which proved almost nothing. I checked dmesg from beginning to end for timeouts, unknown options, and drivers claiming the wrong hardware. I mounted every local filesystem, activated swap, transferred data over each network interface, and exercised packet filtering.

Sound moved to ALSA, now part of the kernel tree. Applications using OSS interfaces can often use ALSA’s compatibility modules, but mixer state and device permissions still need checking. Silence may mean the channel is muted rather than the driver is broken, an ancient audio tradition maintained for compatibility with human suffering.

Threaded programs deserve a run under the new combination of kernel and C library. NPTL relies on facilities available in 2.6 and improves both performance and POSIX behaviour, but old monitoring scripts may interpret the changed process display incorrectly. I checked services by function rather than by expecting the old number of ps lines.

The firewall required careful review. The netfilter framework remains, but kernel configuration symbols and available matches can differ. Loading an old saved rule set is useful only if all required modules exist and the restore command reports success. A script that ignores errors can leave a machine less protected while printing reassuring startup messages.

Out-of-tree modules were the only serious obstacle. Internal kernel interfaces changed, and source written for 2.4 often needs a real port rather than a version-number adjustment. I found replacements in the 2.6 tree where possible. For the remaining hardware, I verified current source before making the migration permanent. Binary-only drivers put the schedule entirely in the vendor’s hands, which is one reason I avoid depending on them.

What changed in use

Under a compile and interactive desktop load, the machine is more responsive. The O(1) scheduler’s per-CPU run queues and priority arrays make task selection predictable as load grows. Kernel preemption, enabled on this workstation, reduces the delay before an awakened interactive task can run when another process is in preemptible kernel code.

This does not mean every benchmark is faster. Responsiveness concerns latency; throughput concerns completed work over time. I measured both and accepted a tiny difference in build time in exchange for fewer audio skips and shorter input pauses.

Sysfs is already useful for diagnosis. Following links from /sys/class to a device and its driver is clearer than assembling the relationship from several /proc files and boot messages. It also provides the structured device information that userspace managers such as udev need.

My migration rule is now simple: preserve 2.4, upgrade userspace first, boot a minimally clever 2.6 configuration, and add new mechanisms one at a time. Linux 2.6 is ready for this machine, but it did not become ready merely because uname -r printed the desired number. It became ready when every required workload passed and the old kernel remained one menu selection away.