Dear Martin, On 11/09/16 00:45, Martin K. Petersen wrote:
"Paul" == Paul Menzel <pmenzel@xxxxxxxxxxxxx> writes:
Paul> Updating from Linux 4.4.X to Linux 4.8.4, we noticed that the Paul> 3ware devices under `/dev` – `/dev/twa0`, `/dev/twa1`, … – map to Paul> the controllers differently. Paul> This unfortunately breaks quite a lot of our scripts, as we depend Paul> on the fact that the first controller is also in the front. It's not the 3ware drivers since they have not been updated in a long time (since way before 4.4).
Yes, that’s what made me wonder too.
Linux does not provide device discovery ordering guarantees. You need to fix your scripts to use UUIDs, filesystem labels, or DM devices to get stable naming.
Indeed. But it worked for several years, so that *something* must have changed that the ordering of the result of `getdents64` is different now.
Fixing the scripts is unfortunately not that easy, as `tw_cli` is a proprietary tool [1], and we do not have the sources. It does a `readdir()`.
open("/proc/scsi/3w-9xxx", O_RDONLY|O_NONBLOCK|O_DIRECTORY) = -1 ENOENT (No such file or directory) open("/sys/class/scsi_host", O_RDONLY|O_NONBLOCK|O_DIRECTORY) = 3 fstat(3, {st_mode=S_IFDIR|0755, st_size=0, ...}) = 0 fcntl(3, F_SETFD, FD_CLOEXEC) = 0 getdents64(3, /* 12 entries */, 4096) = 368 stat("/sys/class/scsi_host/host0/stats", 0x7fffafd05290) = -1 ENOENT (No such file or directory) stat("/sys/class/scsi_host/host9/stats", {st_mode=S_IFREG|0444, st_size=4096, ...}) = 0 open("/sys/class/scsi_host/host9/stats", O_RDONLY) = 4 read(4, "3w-9xxx Driver v", 16) = 16 close(4) = 0 open("/dev/twa0", O_RDWR) = 4 close(4) = 0 stat("/sys/class/scsi_host/host7/stats", 0x7fffafd05290) = -1 ENOENT (No such file or directory) stat("/sys/class/scsi_host/host5/stats", 0x7fffafd05290) = -1 ENOENT (No such file or directory) stat("/sys/class/scsi_host/host3/stats", 0x7fffafd05290) = -1 ENOENT (No such file or directory) stat("/sys/class/scsi_host/host1/stats", 0x7fffafd05290) = -1 ENOENT (No such file or directory) stat("/sys/class/scsi_host/host8/stats", {st_mode=S_IFREG|0444, st_size=4096, ...}) = 0 open("/sys/class/scsi_host/host8/stats", O_RDONLY) = 4 read(4, "3w-9xxx Driver v", 16) = 16 close(4) = 0 open("/dev/twa1", O_RDWR) = 4 close(4) = 0 stat("/sys/class/scsi_host/host6/stats", 0x7fffafd05290) = -1 ENOENT (No such file or directory) stat("/sys/class/scsi_host/host4/stats", 0x7fffafd05290) = -1 ENOENT (No such file or directory) stat("/sys/class/scsi_host/host2/stats", 0x7fffafd05290) = -1 ENOENT (No such file or directory) getdents64(3, /* 0 entries */, 4096) = 0 close(3) = 0 open("/proc/devices", O_RDONLY) = 3
Please find attached a wrapper from my colleague, using name spaces to ensure the ordering, that `tw_cli` expects.
Kind regards, Paul [1] https://wiki.hetzner.de/index.php/3Ware_RAID_Controller/en
#! /usr/bin/perl use strict; use warnings; sub sort_host { my ($n1,$n2); ($n1)=$a=~/^host(\d+)$/ and ($n2)=$b=~/^host(\d+)$/ and return $n1 <=> $n2; return $a cmp $b; } our $SYS_unshare=272; # /usr/include/asm/unistd_64.h our $CLONE_NEWNS=0x20000; # /usr/include/linux/sched.h my $pid=fork; defined $pid or die "$!\n"; unless ($pid) { opendir my $d,"/sys/class/scsi_host"; my @names=sort sort_host grep !/^\.\.?$/,readdir $d; syscall($SYS_unshare,$CLONE_NEWNS) and die "$!\n"; -d '/tmp/sysfs' or mkdir("/tmp/sysfs") or die "/tmp/sysfs: $!\n"; system 'mount','-tsysfs','BLA','/tmp/sysfs' and exit 1; system 'mount','-ttmpfs','BLA','/sys/class/scsi_host' and exit 1; for my $name (reverse @names) { symlink("/tmp/sysfs/class/scsi_host/$name","/sys/class/scsi_host/$name") or die "/sys/class/scsi_host/$name: $!\n"; } exec '/root/bin/tw_cli.exe',@ARGV; die "$!\n"; } wait; $? and exit 1;