Linux

Oxygen Is Not the Desktop

I tried the latest Oxygen icons today and immediately decided the whole desktop looked better. Then I used it for an hour and discovered that “looks better” and “is easier to read” are not synonyms.

My first attempt was to set every available Oxygen component at once: icons, window decoration, widget style and colours. The result was certainly consistent. It was also difficult to distinguish a few small toolbar actions, especially disabled ones. At 16 pixels, subtle gradients become subtle grey soup.

The mechanism is mundane. An icon theme must communicate shape at several fixed sizes, not merely survive being scaled down from a handsome drawing. The new SVG source helps artists produce multiple sizes and keeps larger icons crisp, but it does not remove the need for deliberate small variants. A tiny icon has almost no room for texture, perspective or philosophical nuance.

I switched the toolbar to larger icons and kept text beside the less obvious actions. That made Dolphin and the configuration tools much easier to scan. I also stopped blaming Oxygen for missing actions and unfinished panels. Artwork can make incomplete software pleasant to inspect, but it cannot implement a file operation through sheer shininess.

Oxygen already gives KDE 4 a strong identity, and I prefer its restrained colours to the louder themes I usually replace after five minutes. Still, visual consistency is only useful when the symbols remain distinct. My practical conclusion: judge icons at the size actually used, not in the preview window. The preview window is where all icons go to lie about their career prospects.

KDE 4 Alpha on a Spare Partition

I installed a pre-alpha KDE 4 SVN snapshot on a spare partition because running it beside my normal files seemed like a more entertaining mistake than merely reading about it. The announced alpha release was due the next day; this was still a snapshot from the day before. The packages installed cleanly, the session appeared in the login manager, and that was approximately where normality ended.

My naive plan was to reproduce my KDE 3 setup immediately: restore the same panel arrangement, point everything at the same home directory, and judge whether the new desktop was faster. That plan survived for perhaps ten minutes. Several settings had no equivalent, applications still looked inconsistent, and the desktop shell was plainly being assembled while I watched.

What does work is more interesting than the rough edges. Qt 4 painting feels noticeably less burdened when windows resize. The new artwork gives the session a coherent direction rather than the collection-of-themes appearance I feared. A few applications already show cleaner separation between their data and their widgets, which should matter long after the screenshots stop being novel.

What does not work is still substantial. The panel is not something I would trust for a working day. Desktop actions occasionally disappear. Some configuration modules are present but ineffective, a particularly refined form of optimism. Logging out once left processes behind, which then made the next login look broken until I killed them from a console.

This is not KDE 3 with fresh icons. KDE 4 is changing the toolkit, desktop shell, hardware and multimedia layers, and a fair amount of application plumbing at once. That explains why familiar checkboxes cannot simply be carried over. It also means measuring this snapshot as a replacement desktop misses the point.

After a second installation with a clean test user, many of the mysterious failures vanished. Sharing an old configuration directory had introduced stale service files and assumptions from KDE 3. The snapshot still crashes and still lacks ordinary conveniences, but at least those failures now belong to the new code rather than to my archaeological collection of dot files.

Don’t install it on the account used to earn money. Still, the architecture is visible enough to poke at, and a bug report from a clean account may help. Complaining that a pre-alpha snapshot is unfinished is accurate, but not exactly investigative journalism.

Qt Model/View Without the Magic

I added sorting to a log viewer with QSortFilterProxyModel, clicked the third visible row, and opened the wrong log entry. The view had done exactly what I asked. I had used a proxy row as an index into the source list.

A proxy has its own indexes and its own order. Once sorting or filtering is active, row 3 in the view says nothing useful about row 3 in the source. The handoff needs to be explicit:

QModelIndex proxyIndex = view->currentIndex();
QModelIndex sourceIndex = proxy->mapToSource(proxyIndex);
if (sourceIndex.isValid())
    openEntry(sourceIndex.row());

The reverse direction matters too. When the parser reports a source index that should be selected, mapFromSource() finds its current position in the proxy. Calling view->setCurrentIndex() with the source index may look plausible, but the index still belongs to a different model and should not be handed to that view.

My next bug was staler. I changed a severity threshold stored by the proxy, emitted a signal from the dialog, and nothing disappeared. The filter result was cached. After changing the threshold, the proxy had to invalidate its filtering so that filterAcceptsRow() ran again:

void LogProxy::setMinimumLevel(int level)
{
    if (minimumLevel == level)
        return;

    minimumLevel = level;
    invalidateFilter();
}

Resetting the source model also made the screen update, but it was the wrong hammer. It discarded selections and told every attached view that the source structure had vanished when only the proxy’s mapping was stale.

Dynamic sorting has a similar edge. If a source value used by the sort or filter changes, the source must emit dataChanged() for that value. The proxy can then reconsider the affected mapping. Without that notification, asking the proxy to repaint merely gives it another chance to use the same old answer.

Selections and drag-and-drop code are where I now look first for mapping mistakes. Anything crossing the proxy boundary should say which side its index belongs to. That small bit of bookkeeping beats opening the wrong error at two in the morning.

KVM After 2.6.20

Linux 2.6.20 was released this week with KVM included, so I tried booting a small guest rather than merely reading patches. The first attempt failed immediately because the processor’s virtualisation support was disabled in the firmware. Progress began with entering setup, which keeps systems programming humble.

KVM uses the processor’s hardware virtualisation extensions and exposes a kernel interface through /dev/kvm. A user-space program supplies the virtual machine’s device model and asks the kernel to run virtual CPUs. This is not a complete machine monitor appearing from one kernel option; kernel and user space divide the work.

The basic checks on this Intel test box were:

grep vmx /proc/cpuinfo
modprobe kvm
modprobe kvm-intel
ls -l /dev/kvm

On an AMD processor I would look for svm and use the corresponding module. Seeing the flag is necessary but not always sufficient, because firmware can still disable the facility.

After loading the modules, I launched a guest image with the available QEMU KVM support and watched the kernel log in another terminal. The guest booted, though virtual disk and network performance are not conclusions I can draw from ten minutes and one ageing drive.

I prefer this architecture because putting CPU execution support behind a kernel interface lets normal Linux scheduling and memory management participate, while device emulation remains in user space where a failure is less likely to take the host with it. The caveat is that the boundary can impose overhead, hardware support varies, and young interfaces may change as use exposes mistakes.

Security deserves restraint too. Hardware isolation is not a promise that a hostile guest can never escape. Device emulation processes parse guest-controlled input, and kernel code now manages another complicated processor mode. I am treating guests as isolated test systems, not as magical bags into which all risk disappears.

The useful result today is narrow: with 2.6.20, suitable hardware, enabled firmware support, kernel modules, and matching user space, a Linux host can run a hardware-assisted guest. Whether KVM becomes the preferred general solution will depend on performance, management tools, and how gracefully it handles less cooperative machines.

For now it boots. In infrastructure experiments, reaching a login prompt is the traditional point at which confidence rises faster than evidence.

Lock Before Looking

I reviewed a kernel path today that checked a pointer, acquired a spinlock, then used the pointer. It looked economical. It was also wrong.

if (device->queue) {
    spin_lock(&device->lock);
    flush_queue(device->queue);
    spin_unlock(&device->lock);
}

Another CPU can clear and free queue between the check and the lock. The check does not reserve anything; it merely records a fact that may expire immediately.

The simple repair is to protect both observation and use with the same lock:

spin_lock(&device->lock);
if (device->queue)
    flush_queue(device->queue);
spin_unlock(&device->lock);

This is safe only if flush_queue cannot sleep and does not acquire locks in an incompatible order. Spinlocks disable preemption in the relevant context; they are not permission to perform leisurely work. If flushing can block, I need a different design, perhaps detach the queue under the spinlock and process it later with appropriate lifetime ownership.

I prefer establishing ownership under one clearly documented lock rather than scattering “probably still valid” checks. The caveat is contention: a correct giant critical section can turn several processors into an expensive single processor.

The lesson is not “add locks.” It is “name the invariant, then guard every transition that can violate it.” Locks without an invariant are just punctuation with cache-line traffic.