Es ist manchmal ein Trauerspiel mit Linux. Viel zu oft hab ich schon nerviges Tearing erlebt, mit verschiedenen Ursachen. Aktuell mit Intel iGPU und der Gnome Shell. Ich bin mir nicht sicher, ob das Problem auch mit anderen GPUs auftritt. Sicher bin ich mir dabei, dass bei mir die Gnome Shell der Schuldige ist.
Daher hier ein (temporärer) Fix für eins der vielen Tearing-Probleme.
-
Öffnen des Gnome Shell Debugger (Looking Glass): Drücke Alt-F2 und gib lg ein
-
Dort muss folgender Befehl eingegeben werden:
Meta.disable_unredirect_for_screen(global.screen)
Eine Alternative ist diese Gnome Extension.
Wenn man ein Verzeichnis liest und von allen enthaltenen Dateien die Extended Attributes erhalten will, gibt es zwei Möglichkeiten:
- Man fügt zum Verzeichnispfad den Dateinamen hinzu und nutzt den neu erhaltenen Pfad mit den Syscalls
listxattr
oder getxattr
.
- Mit dem Filedescriptor des Verzeichnisses und
openat
öffnet man die Dateien und nutzt dann flistxattr
und getxattr
.
Ich hab mich gefragt was schneller ist. Dazu habe ich ein kleines Testprogramm geschrieben. Dieses kann mit unterschiedlichen Preprocessor-Optionen kompiliert werden. So habe ich 4 Testprogramme erstellt. Für getxattr
und fgetxattr
jeweils ein Programm, das ein Attribut liest und eines das 32 Attribute liest.
Bei einem Verzeichnis mit 128.000 Dateien hab ich folgende Werte erhalten:
getxattr:1 getxattr:32 fgetattr:1 fgetattr:32
------------------------------------------------
246100055 654704421 456172044 749849574
230183311 663632162 457183706 769223423
247109480 654775136 440397212 743349119
Die Datei erst zu öffnen um dann fgetxattr
zu nutzen ist also langsamer. Erst als ich das Programm so modifiziert habe, dass es mehrere hundert Attribute liest, war es etwas schneller. Das ist jedoch ein eher unrealistisches Szenario. Allerdings war das ganze generell sehr schnell, so dass es eigentlich egal ist, welche Methode man anwendet.
Es scheint jetzt offenbar doch sehr schlecht für die Zukunft von Solaris auszusehen. Vor ein paar Monaten hat Oracle noch einige neue Solaris-Features angekündigt. Ein Entwickler hat sogar Screenshots von Gnome 3 unter Solaris veröffentlicht. Offenbar hat Oracle sich aber kurzfristig komplett umentschieden und holzt jetzt einiges ab.
Ihr Cloud-Geschäft läuft ziemlich gut, und dort kommt auch Solaris zum Einsatz. Daher wird es wohl noch irgendwie erhalten bleiben. Aber wie genau wird sich erst zeigen müssen. Server mit Solaris hat offenbar keine Priorität mehr, es sollen stattdessen alle auf Cloud-Produkte umsteigen.
Linux ist mitlerweile das dominierende Betriebsystem im Unix-Segment. Es gibt viele Gründe dafür, warum dies so ist, technisch gesehen ist Solaris aber mehr als konkurrenzfähig. Features, die jetzt erst langsam zu Linux wandern gibt es schon seit mehr als 10 Jahren bei Solaris:
- Mit systemd wurden unter Linux die alten Sys V init-Skripte abgelöst. Seit Solaris 10 kommt dort dafür smf zum Einsatz, was auch das Vorbild für systemd war.
- Linux hat mitlerweile auch Container, Solaris hat die schon wesentlich länger und auch deutlich ausgereifter. FreeBSD Jails sind sogar noch älter.
- Btrfs ist immer noch nicht production ready, auf jedenfall nicht, wenn man Raid5/6 will. Wichtige Daten vertraue ich nur noch ZFS an (auch unter Linux), alles andere ist nicht mehr zeitgemäß (oder unfertig).
- Seit Linux 4.9 gibt es endlich eine Dtrace-Alternative. Ja, jetzt erst im Jahr 2016.
Es gibt auch sehr viele Kleinigkeiten, die mir unter Solaris besser gefallen.
- Dank Boot Environments muss man keine Angst vor Upgrades haben. Außerdem müssen auch nie Upgrades beim Booten oder Shutdown installiert werden.
- NFS kann kein Betriebsystem besser als Solaris.
- Linux hat immer noch keine NFSv4 ACLs. Selbst btrfs unterstützt nur Posix-ACLs. Und unter vielen Distris sind die Dateisysteme standardmäßig auch ohne ACL-Support gemounted.
- Solaris hat Event Ports als Alternative für poll, die wesentlich mächtiger sind als die Linux Alternative epoll.
Vor allem sind bei Solaris viele Dinge schöner integriert und arbeiten wunderbar zusammen, wärend Linux ein wenig mehr Gefrickel ist.
Das soll jetzt kein Linux-Bashing werden, aber es ist meiner Meinung nach nicht das völlig überlegene Betriebsystem. Wenn Solaris stirbt wäre das einfach ein Technologie-Verlust. Vor allem will ich mich nicht mit Problem rumschlagen, die schon vor Jahren gelöst wurden. Es gibt natürlich noch IllumOS, den OpenSolaris-Fork, das müsste ich mir mal genauer anschauen.
Düstere Zukunftsaussichten
Nicht nur um Solaris wäre es schade. Generell verschwinden die guten Produkte.
Von 2009 bis Ende 2013 war ich Apple-User. Mich hat damals sowohl OS X überzeugt als auch die Hardware. Heute überzeugt mich von Apple leider gar nichts mehr. Ich bin immer bereit für hohe Qualität mehr Geld zu bezahlen. Apple liefert aber nicht mal mehr ansatzweise etwas wie Qualität. Nach jeder Einführung eines neuen Mac häufen sich Berichte über Probleme damit. Wann kam eigentlich der letzte Mac raus, der keine Grafik-Probleme hatte? Und auf verlöteten RAM hab ich auch keine Lust. Ich hab wenig Hoffnung, dass zukünftige Desktop-Macs wieder besser werden.
Als Smartphone hatte ich schon immer Nexus-Geräte. Erst das Nexus One, dann ein Nexus 4. Ein neues Smartphone könnte ich langsam mal gebrauchen. Leider hat Google die Nexus-Reihe beerdigt, und das Pixel ist einfach lächerlich überteuert und überzeugt generell nicht.
Irgendwann brauch ich auch mal einen neuen Desktop-Computer. Ich bin ein bisschen ein Fan der HP Z-Workstations. Leider entwickelt sich HP immer mehr zur völligen Idioten-Firma. Ich bin auch sehr überzeugt von Fujitsu. Die halte ich eigentlich für den aktuell besten Hersteller. Dumm nur, dass es da Gerüchte gibt, dass sie ihre PC-Sparte verkaufen wollen.
Zu guter Letzt veraltet die von mir bevorzugte Linux-Distribution CentOS 7 leider immer mehr. Kurz nach Release ist die Software schon nicht top aktuell, für mich jedoch neu genug. Mit den Jahren wird das leider nicht besser. Da ein EL8 noch nicht in Sicht ist, muss ich mich möglicherweise nach einer neuen Distri umschauen.
Diesmal geht es nicht um Extended Attributes, jedoch um eine andere Art von Dateiattributen, die auch für den Kernel von Bedeutung sind. Mit diesen kann man beispielsweise Dateien unveränderbar machen oder einstellen, dass an die Datei nur neue Daten angehangen werden können, aber nicht der bisherige Inhalt überschrieben werden kann. Das ganze ist völlig unabhängig von den eigentlichen Rechten der Datei.
Beispiel unter Linux:
# chattr +i myfile
Danach ist die Datei unveränderbar. Selbst root kann die Datei nicht verändern, solange das Attribut gesetzt ist. Natürlich könnte root es entfernen und danach die Datei verändern.
Unter Solaris verändert man diese Attribute mit chmod. Interessant ist da z.B. das nounlink-Attribut.
# chmod S+vnounlink myfile
rm: myfile not removed: Not owner
# echo newcontent > myfile
# chmod S-vnounlink myfile
# rm myfile
#
Das verhindert effektiv, dass man sich wichtige Dateien versehentlich löscht.
Applying Special Attributes to ZFS Files
chattr (ubuntuusers Wiki)
Im vorherigen Teil ging es darum, wie man unter Linux Extended Attributes auf der Kommandozeile bearbeitet. Das Thema diesmal ist, mit welchen Syscalls man dies in C erledigen kann.
Für die 4 verschiedenen Operationen die man benötigt, nämlich listxattr, getxattr, setxattr und removexattr, gibt es jeweils 3 Syscalls.
#include <sys/types.h>
#include <sys/xattr.h>
ssize_t listxattr(const char *path, char *list, size_t size);
ssize_t llistxattr(const char *path, char *list, size_t size);
ssize_t flistxattr(int fd, char *list, size_t size);
ssize_t getxattr(const char *path, const char *name,
void *value, size_t size);
ssize_t lgetxattr(const char *path, const char *name,
void *value, size_t size);
ssize_t fgetxattr(int fd, const char *name,
void *value, size_t size);
int setxattr(const char *path, const char *name,
const void *value, size_t size, int flags);
int lsetxattr(const char *path, const char *name,
const void *value, size_t size, int flags);
int fsetxattr(int fd, const char *name,
const void *value, size_t size, int flags);
int removexattr(const char *path, const char *name);
int lremovexattr(const char *path, const char *name);
int fremovexattr(int fd, const char *name);
Die Syscalls mit dem l-Prefix liefern für den Fall dass path
ein Symlink ist die Attribute des Symlinks selber, und nicht von der Datei, auf die der Symlink zeigt.
Bei den Syscalls mit dem f-Prefix übergibt man statt des Pfades einen Filedescriptor, den man mit open erhält.
Mit listxattr
erhält man eine komplette Liste aller Extended Attributes für die Datei. Man muss einen vorher allozierten Buffer und seine Größe übergeben. Die Namen der Extended Attributes werden dann in diesen Buffer geschrieben, getrennt immer durch ein 0-Byte. Falls der Buffer zu klein ist, liefert die Funktion -1 zurück und setzt errno
auf ERANGE
. Man kann auch abfragen, wie groß der Buffer sein müsste, in dem man als size
0 übergibt. Der Rückgabewert ist dann die benötigte Größe des Buffers.
Hier ist ein Beispielprogramm, dass alle Extended Attributes einer Datei auflistet. Der Code um die Liste der Namen zu erhalten ist:
char *list = malloc(BUF_LEN);
ssize_t len = listxattr(path, list, BUF_LEN);
Wenn wir die Namen der Attribute haben, können wir den Wert mit getxattr
erhalten. Diese Funktion erwartet ebenfalls einen Buffer, in den der Wert dann geschrieben wird. Auch hier kann man für size
0 angeben, um die Länge des Attributwerts zu erhalten.
Um das Beispielprogramm zu erweitern, dass es auch die Werte der Attribute ausgibt, könnte man die for-Schleife am Ende durch diesen Code ersetzen:
// print attributes
int begin = 0;
for(int i=0;i<len;i++) {
if(list[i] == '\0') {
char *xattr_name = list + begin;
char value[0x10000];
ssize_t vallen = getxattr(path, xattr_name, value, 0x10000);
printf("%s: %.*s\n", xattr_name, (int)vallen, value);
begin = i + 1;
}
}
Es fehlt zwar die Fehlerbehandlung, es sollte jedoch immer funktionieren. Die Größe ist eh auf 64kb beschränkt, bei vielen Dateisystemen sogar noch weniger.
Kommen wir zu setxattr
, mit dem man ein Extended Attribute setzt. Die Funktion erwartet als letzten Parameter ein flag. Ist dies 0, wird der Wert gesetzt, egal ob er schon existiert oder nicht. Bei XATTR_CREATE
liefert die Funktion einen Fehler, wenn das Attribut schon existiert und bei XATTR_REPLACE
gibt es einen Fehler, wenn der Wert nicht existiert.
xsetattr(path, "user.myattrname", value, valuelen, 0);
Bleibt zuletzt noch removexattr
, dem man einfach nur den Dateipfad und den Attribut-Namen gibt, und der wird dann entfernt.