unfs3 Paket erstellt - uclibc Probleme

poeschell

Neuer User
Mitglied seit
22 Nov 2010
Beiträge
6
Punkte für Reaktionen
0
Punkte
0
Hallo!

Ich habe eine Fritzbox 7390 und habe mittels des Entwicklerzweiges von Oliver ein Freetz erstellt.
Ich möchte nun den unfs3 benutzen und haben mir ein Paket dafür gebaut. Das compiled auch wunderbar und erstellt mir ein Freetz mit dem unfs3 drin.
Ein Problem war nun, dass sich NFS Freigaben von der Fritzbox zur Dreambox (Linux Satellitenreceiver) zwar wunderbar mounten ließen, aber sobald man eine Datei öffnete, wurden falsche Daten vom unfs3 ausgeliefert. Genauergesagt stimmte immer nur der erste gepufferte Teil (beim mounten angegebene rsize), alles was danach kam, war Müll.
Ich habe das Problem soweit identifiziert, dass der unfs3 die Funktion pread nutzt und als Offset in die Datei einen 64 Bit wert rein gibt, die Funktion in der uclibc aber offenbar einen 32 Bit Wert erwartet, obwohl die uclibc mit Large File Support gebaut ist.
Wenn ich nun im unfs3 Quellcode den pread Aufruf durch pread64 ersetze, funktioniert die Datenübertragung wunderbar. Also schein hier das Problem zu liegen.
Ich weiss nun nicht, wie ich die Sache fixen kann. In unistd.h der uclibc gibt es eine #ifdef Weiche in Zeile 334. Hier wird __USE_FILE_OFFSET64 abgeprüft und im Falle, dass es gesetzt ist (und __REDIRECT nicht) wird pread einfach auf pread64 define'd. Meines Erachtens ist das doch genau der Sinn des Large File Support und dieser Weg sollte vom Compiler genommen werden - wird aber offensichtlich nicht.
Während des compilens des unf3 Pakets sehe ich auch, wie mittles der -D Option das define _FILE_OFFSET_BITS=64 gesetzt wird, aber nicht __USE_FILE_OFFSET64, wie es die uclibc scheinbar braucht.
Hat jemand ne Idee, wie ich weiter machen kann um das Problem ordenlich zu beheben oder weiter einzugrenzen?

Danke schonmal,
poeschell
 
Nach Deiner Beschreibung Tritt das Problem schon bei Dateien kleiner 2GB auf. Kannst Du mal mit strace feststellen, welche Systemaufrufe tatsächlich verwendet werden?

Außerdem könntest Du ein Testprogramm erstellen, das die Aufrufe prüft.
 
Ja, das Problem tritt schon deutlich früher, als bei 2 GB auf. Wenn man beim mounten nichts angibt, ist die rsize 32kB, als tritt es immer bei Dateien größer 32 kB auf.

Ich hab mir gerade strace kompiliert und den unfs mit strac gestartet. Es wird tatsächlich nur pread und nicht pread64 benutzt. Interessant ist allerdings, dass lstat64, also die 64 Bit Version von lstat aufgerufen wird.

Ich habe eben folgendes Testprogramm geschrieben:
Code:
#include <unistd.h>
#include <fcntl.h>
#include <stdio.h>
#include <stdint.h>
#include <string.h>

int main(int argc, char **argv) {
	int fd,
	    bytes;
	char buf32[40000],
	     buf64[40000];
	uint32_t offset32;
	uint64_t offset64;

	fd = open(argv[1], O_RDONLY);
	offset32 = 0;
	offset64 = 0;

	bytes = pread(fd, buf32, 32768, offset32);
	printf("bytes32 1:%d\n", bytes);
	bytes = pread(fd, buf64, 32768, offset64);
	printf("bytes64 1:%d\n", bytes);
	printf("compare:%d\n", strncmp(buf32, buf64, 32768));

	offset32 = 32768;
	offset64 = 32768;
	bytes = pread(fd, buf32, 32768, offset32);
	printf("bytes32 2:%d\n", bytes);
	bytes = pread(fd, buf64, 32768, offset64);
	printf("bytes64 2:%d\n", bytes);
	printf("compare:%d\n", strncmp(buf32, buf64, 32768));

	close(fd);

	return 0;
}

Man übergibt dem Programm als erstes Argument eine Datei, die es öffnen soll.
Auf meinem Linux i386 Rechner ist die Ausgabe, wie man erwarten würde:

bytes32 1:32768
bytes64 1:32768
compare:0
bytes32 2:32768
bytes64 2:32768
compare:0

Auf der Fritzbox lässt sich das Problem aber reproduzieren:

bytes32 1:32768
bytes64 1:32768
compare:0
bytes32 2:32768
bytes64 2:32768
compare:-181

Mit strace sieht man, dass im i386 Linux pread64 benutzt wird, auf der Fritzbox allerdings nur pread.
Liegt der Fehler tatsächlich in der uclibc ? Ich verwende übrigens die standardmässig eingestellte 0.9.29. Large File Support ist (wie standardmässig eingeschaltet).
Wie kann man weiter eingrenzen ?
Danke schonmal für eure Mühen!
 
Es scheint tatsächlich ein Problem mit der Library-Funktion zu sein. Es wundert mich allerdings, weil auch Samba pread verwendet und ich noch nichts davon gelesen habe, daß es da Probleme gibt.

Wie sieht denn die Ausgabe von strace auf der Box aus? Was wird als Offset übergeben? Übersetzte auch mal das Programm mit der Option "-Wall". Kommt dann eine Warnung, daß pread nicht bekannt ist? Welche sonstigen Optionen hast Du verwendet?
 
strace auf der Box:

Code:
execve("../../media/ftp/Generic-USBSDReader-01/pread_test_mips", ["../../media/ftp/Generic-USBSDRea"..., "../../media/ftp/Generic-USBSDRea"...], [/* 216 vars */]) = 0
old_mmap(NULL, 20, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0x2aaad000
open("/mod/lib/libgcc_s.so.1", O_RDONLY) = -1 ENOENT (No such file or directory)
open("/lib/libgcc_s.so.1", O_RDONLY)    = 3
fstat(3, {st_mode=S_IFREG|0644, st_size=73196, ...}) = 0
old_mmap(NULL, 4096, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0x2aaae000
read(3, "\177ELF\1\2\1\0\0\0\0\0\0\0\0\0\0\3\0\10\0\0\0\1\0\0\34\20\0\0\0004"..., 4096) = 4096
old_mmap(NULL, 139264, PROT_NONE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0x2aabe000
old_mmap(0x2aabe000, 68892, PROT_READ|PROT_EXEC, MAP_PRIVATE|MAP_FIXED, 3, 0) = 0x2aabe000
old_mmap(0x2aadf000, 2284, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_FIXED, 3, 0x11000) = 0x2aadf000
close(3)                                = 0
munmap(0x2aaae000, 4096)                = 0
open("/mod/lib/libc.so.0", O_RDONLY)    = -1 ENOENT (No such file or directory)
open("/lib/libc.so.0", O_RDONLY)        = 3
fstat(3, {st_mode=S_IFREG|0644, st_size=693696, ...}) = 0
old_mmap(NULL, 4096, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0x2aaae000
read(3, "\177ELF\1\2\1\0\0\0\0\0\0\0\0\0\0\3\0\10\0\0\0\1\0\0\2540\0\0\0004"..., 4096) = 4096
old_mmap(NULL, 737280, PROT_NONE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0x2aae0000
old_mmap(0x2aae0000, 638740, PROT_READ|PROT_EXEC, MAP_PRIVATE|MAP_FIXED, 3, 0) = 0x2aae0000
old_mmap(0x2ab8c000, 8244, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_FIXED, 3, 0x9c000) = 0x2ab8c000
old_mmap(0x2ab8f000, 18768, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_FIXED|MAP_ANONYMOUS, -1, 0) = 0x2ab8f000
close(3)                                = 0
munmap(0x2aaae000, 4096)                = 0
open("/mod/lib/libc.so.0", O_RDONLY)    = -1 ENOENT (No such file or directory)
open("/lib/libc.so.0", O_RDONLY)        = 3
fstat(3, {st_mode=S_IFREG|0644, st_size=693696, ...}) = 0
close(3)                                = 0
stat("/lib/ld-uClibc.so.0", {st_mode=S_IFREG|0755, st_size=22536, ...}) = 0
mprotect(0x2ab8c000, 4096, PROT_READ)   = 0
mprotect(0x2aabc000, 4096, PROT_READ)   = 0
ioctl(0, TIOCNXCL, {B38400 opost isig icanon echo ...}) = 0
ioctl(1, TIOCNXCL, {B38400 opost isig icanon echo ...}) = 0
open("../../media/ftp/Generic-USBSDReader-01/09012010305.jpg", O_RDONLY) = 3
pread(3, "\377\330\377\341\30+Exif\0\0II*\0\10\0\0\0\10\0\17\1\2\0\6\0\0\0n\0"..., 32768, 0) = 32768
write(1, "bytes32 1:32768\n", 16bytes32 1:32768
)       = 16
pread(3, "\377\330\377\341\30+Exif\0\0II*\0\10\0\0\0\10\0\17\1\2\0\6\0\0\0n\0"..., 32768, 0) = 32768
write(1, "bytes64 1:32768\n", 16bytes64 1:32768
)       = 16
write(1, "compare:0\n", 10compare:0
)             = 10
pread(3, "J\247\255\254I\31\v\226<\23\375\356\364\221\361\310\25\276\310\t\2439\311\350MH\30\16\265\216\340\4"..., 32768, 32768) = 32768
write(1, "bytes32 2:32768\n", 16bytes32 2:32768
)       = 16
pread(3, "\377\330\377\341\30+Exif\0\0II*\0\10\0\0\0\10\0\17\1\2\0\6\0\0\0n\0"..., 32768, 0) = 32768
write(1, "bytes64 2:32768\n", 16bytes64 2:32768
)       = 16
write(1, "compare:-181\n", 13compare:-181
)          = 13
close(3)                                = 0
exit(0)                                 = ?

Wie man sieht wird im 2. Fall bei 64 Bit 0 als Offset übergeben, dementsprechend wird ab 0 gelesen und die Daten stimmen mit dem 1. Fall überein.
Wie gesagt, die Box ist eine 7390, also Big Endian. Vielleicht liegt es auch daran, dass das Problem nicht so häufig auffällt.
Ich habe, wie von dir vorgeschlagen folgendermassen compiliert:

7390/toolchain/target/bin/mips-linux-gcc -o pread_test_mips -Wall pread_test.c
pread_test.c: In function 'main':
pread_test.c:21: warning: implicit declaration of function 'pread'

Und tatsächlich beschwert er sich, dass pread nicht da ist!
Was heisst das jetzt ?

Ich vermute, dass das Problem bei Samba nicht auftritt ist, dass Samba 32 Bit Offsets für pread verwendet. Ich baue mal ein Samba Packet und werfe mal einen kurzen Blick in die Quellen.
 
Zuletzt bearbeitet:
Bitte für die Ausgabe von strace auch CODE-Tags, so wie auch oben beim Programm.

Interessanterweise funktioniert bei Dir pread aber nicht pread64. Ich hätte es eher anders herum vermutet.
Da die Funktion nicht deklariert wurde, weiß auch der Compiler nicht, welche Argument-Typen er übergeben soll.
Möglicherweise liegt das Problem darin, daß die Byte-Reihenfolge hier anders ist. Jedenfalls funktioniert bei mir weder weder pread noch pread64. Oder strace zeigt die Werte nicht richtig an.
 
Ich kann das Programm mit folgender Erweiterung korrekt ausführen:
Code:
--- pread_test.c.orig   2010-11-22 17:46:33.798774383 +0100
+++ pread_test.c        2010-11-22 17:46:37.008773983 +0100
@@ -1,3 +1,5 @@
+#define _XOPEN_SOURCE 500
+
 #include <unistd.h>
 #include <fcntl.h>
 #include <stdio.h>
Gruß
Oliver
 
Ich hab das Testprogramm mal um pread64 erweitert, damit ein wenig klarer ist, was funktioniert und was nicht:
Code:
#include <unistd.h>
#include <fcntl.h>
#include <stdio.h>
#include <stdint.h>
#include <string.h>

int main(int argc, char **argv) {
	int fd,
	    bytes;
	char buf32[40000],
	     buf64[40000],
	     buf642[40000];
	uint32_t offset32;
	uint64_t offset64;

	fd = open(argv[1], O_RDONLY);
	offset32 = 0;
	offset64 = 0;

	bytes = pread(fd, buf32, 32768, offset32);
	printf("bytes32 1:%d\n", bytes);
	bytes = pread(fd, buf64, 32768, offset64);
	printf("bytes64 1:%d\n", bytes);
	bytes = pread64(fd, buf642, 32768, offset64);
	printf("bytes642 1:%d\n", bytes);
	printf("compare:%d\n", strncmp(buf32, buf64, 32768));
	printf("compare2:%d\n", strncmp(buf32, buf642, 32768));

	offset32 = 32768;
	offset64 = 32768;
	bytes = pread(fd, buf32, 32768, offset32);
	printf("bytes32 2:%d\n", bytes);
	bytes = pread(fd, buf64, 32768, offset64);
	printf("bytes64 2:%d\n", bytes);
	bytes = pread64(fd, buf642, 32768, offset64);
	printf("bytes642 2:%d\n", bytes);
	printf("compare:%d\n", strncmp(buf32, buf64, 32768));
	printf("compare2:%d\n", strncmp(buf32, buf642, 32768));

	close(fd);

	return 0;
}

Ausgabe beim compilieren:
Code:
toolchain/target/bin/mips-linux-gcc -o pread_test_mips -Wall pread_test.c
pread_test.c: In function 'main':
pread_test.c:20: warning: implicit declaration of function 'pread'
pread_test.c:24: warning: implicit declaration of function 'pread64'

Ausgabe auf der Box:
Code:
bytes32 1:32768
bytes64 1:32768
bytes642 1:32768
compare:0
compare2:0
bytes32 2:32768
bytes64 2:32768
bytes642 2:32768
compare:-181
compare2:0

Und der relevante Teil mit strace auf der Box:
Code:
open("../../media/ftp/Generic-USBSDReader-01/09012010305.jpg", O_RDONLY) = 3
pread(3, "\377\330\377\341\30+Exif\0\0II*\0\10\0\0\0\10\0\17\1\2\0\6\0\0\0n\0"..., 32768, 0) = 32768
write(1, "bytes32 1:32768\n", 16bytes32 1:32768
)       = 16
pread(3, "\377\330\377\341\30+Exif\0\0II*\0\10\0\0\0\10\0\17\1\2\0\6\0\0\0n\0"..., 32768, 0) = 32768
write(1, "bytes64 1:32768\n", 16bytes64 1:32768
)       = 16
pread(3, "\377\330\377\341\30+Exif\0\0II*\0\10\0\0\0\10\0\17\1\2\0\6\0\0\0n\0"..., 32768, 0) = 32768
write(1, "bytes642 1:32768\n", 17bytes642 1:32768
)      = 17
write(1, "compare:0\n", 10compare:0
)             = 10
write(1, "compare2:0\n", 11compare2:0
)            = 11
pread(3, "J\247\255\254I\31\v\226<\23\375\356\364\221\361\310\25\276\310\t\2439\311\350MH\30\16\265\216\340\4"..., 32768, 32768) = 32768
write(1, "bytes32 2:32768\n", 16bytes32 2:32768
)       = 16
pread(3, "\377\330\377\341\30+Exif\0\0II*\0\10\0\0\0\10\0\17\1\2\0\6\0\0\0n\0"..., 32768, 0) = 32768
write(1, "bytes64 2:32768\n", 16bytes64 2:32768
)       = 16
pread(3, "J\247\255\254I\31\v\226<\23\375\356\364\221\361\310\25\276\310\t\2439\311\350MH\30\16\265\216\340\4"..., 32768, 32768) = 32768
write(1, "bytes642 2:32768\n", 17bytes642 2:32768
)      = 17
write(1, "compare:-181\n", 13compare:-181
)          = 13
write(1, "compare2:0\n", 11compare2:0
)            = 11
close(3)                                = 0
exit(0)                                 = ?

Merkwürdig ist für mich, dass auch der pread64 Aufruf in strace zu einem pread wird, aber letztendlich richtig funktioniert.

Bezüglich Samba kann ich erstmal soviel sagen:
Samba prüft im configure Vorgang auf pread und pread64 und kann damit natürlich immer den auf JEDEN Fall funktionierenden Aufruf auswählen.
 
Ich vermute, dass du in deinem Makefile die CFLAGS von unfs3 überschreibst?
Code:
CFLAGS = @CFLAGS@ -D_GNU_SOURCE
Gruß
Oliver
 
Hallo Oliver!

Vielen Dank!
Ich war schon begeistert, denn schon das
Code:
#define _XOPEN_SOURCE 500
funktionierte, aber auch mit den CFLAGS hast du vollkommen Recht!
Ich habe das Makefile template vom empty Paket übernommen und da werden die CFLAGS überschrieben. Das habe ich jetzt raus genommen und es funktioniert!
Danke nochmal, auch an Ralf!

Habt ihr Interesse den unfs3 in Freetz aufzunehmen ?
Es gibt zwar noch ein paar Problemchen, ich bin aber gerne bereit zu contributen.
z.B. krallt sich der ctlmgr Port 2049, den unfs3 standardmässig auch gerne hätte.

Code:
ctlmgr -s
unfsd
ctlmgr

funktionieren aber.
Weiss man, was der ctlmgr auf Port 2049 macht ?
 
Im Kernel ändern wir den Port:
Code:
--- linux-2.6.13.1/fs/nfsd/nfsctl.c.orig	2010-02-04 12:04:15.000000000 +0100
+++ linux-2.6.13.1/fs/nfsd/nfsctl.c	2010-02-04 11:40:07.000000000 +0100
@@ -321,7 +321,7 @@
 			return rv;
 		if (newthreads <0)
 			return -EINVAL;
-		rv = nfsd_svc(2049, newthreads);
+		rv = nfsd_svc(2047, newthreads);
 		if (rv)
 			return rv;
 	}
Zumindest für 2.6.13.1.

Gruß
Oliver
 
Samba prüft nur auf die Existenz der entsprechenden pread Funktionen. Aufrufen kann es sie nicht, weil configure auf dem Host-System läuft.

Der Port 2049 wird zwar üblicherweise für NFS verwendet, aber über den Portmapper sollte jeder Port möglich sein.
 
Es hat zwar eine Weile gedauert, aber ich habe nun ein Paket fertig. Ich würde das Paket gerne einreichen und in den freetz trunk integrieren lassen. Man findet zwar eine Anleitung, wie man den Patch erstellt. Wo oder an wen ich den Patch einreichen muss, habe ich nicht so richtig gefunden. Wo kann ich den Patch einreichen ?
Danke!
 
Du kannst den Patch auf freetz.org an ein Ticket (Neues Ticket->Hinweise durchlesen) anhängen.

Gruß
Oliver
 
Wie bekomme ich diesen unfs in den aktuellen trunk? patch habe ich ausgeführt. dann make unfs2 precompiled. aber in der menu config finde ich den leider nicht.
 
Wahrscheinlich musst du das Paket noch hier hinzufügen.

Gruß
Oliver
 
Danke olli. der nfsd macht nämlich im aktuellen trunk immer noch probleme. Beim schreiben ist er recht flott. aber beim lesen bin ich unter 3 MBit
 
Gib mal Bescheid wie die Speeds des unnfs im Vergleich sind.

Gruß
Oliver
 
Kriege ihn nicht mehr compiled :-(

if test -d make/unfs3/files; then tar -c -C make/unfs3/files --exclude=.svn . | tar -x -C packages/unfs3-0.9.22 ; fi
rm -f -r source/unfs3-0.9.22
tar -C source -xzf dl/unfs3-0.9.22.tar.gz
set -e; shopt -s nullglob; for i in make/unfs3/patches/*.patch; do tools/freetz_patch source/unfs3-0.9.22 $i; done
ERROR: modpatch: Error in patch-file make/unfs3/patches/100-noyywrap.patch
make: *** [source/unfs3-0.9.22/.unpacked] Fehler 2
 
Bei mir hat's mit dem Patch aus dem Ticket funktioniert. Baust du das mit Freetz-1.1.x?

Gruß
Oliver
 
Holen Sie sich 3CX - völlig kostenlos!
Verbinden Sie Ihr Team und Ihre Kunden Telefonie Livechat Videokonferenzen

Gehostet oder selbst-verwaltet. Für bis zu 10 Nutzer dauerhaft kostenlos. Keine Kreditkartendetails erforderlich. Ohne Risiko testen.

3CX
Für diese E-Mail-Adresse besteht bereits ein 3CX-Konto. Sie werden zum Kundenportal weitergeleitet, wo Sie sich anmelden oder Ihr Passwort zurücksetzen können, falls Sie dieses vergessen haben.