LimHD:Fuse: Difference between revisions
No edit summary |
No edit summary |
||
(7 intermediate revisions by the same user not shown) | |||
Line 80: | Line 80: | ||
.. and it panics.. so .. shame I can't read the output from "dmesg" before then :) | .. and it panics.. so .. shame I can't read the output from "dmesg" before then :) | ||
=== Retrying Fuse-2.5.3 === | |||
Fresh start, from compiling. Top level configure: | |||
./configure CFLAGS="-DPATH_MAX=4096 -DMAX_LFS_FILESIZE=0x7fffffffffffffff -DFUSE_DEV_NEW=\"/tmp/dev/fuse\"" LDFLAGS=-Wl,-elf2flt --host=arm-elf --enable-static --enable-kernel-module --with-kernel=/home/lundman/uClinux-2.4 --disable-mtab | |||
vi libtool | |||
#version_type=none => =linux | |||
Lots of small changes in .C, Makefile.am and Makefiles in general. Mostly to take out all multi-threaded things. | |||
The do the same for '''kernel/''' directory, but notice that the Makefile is not generated correctly. | |||
vi kernel/Makefile | |||
#CC=arm-elf-gcc | |||
#LD=arm-elf-ld | |||
And compile that. The first error we get is: | |||
inode.c:584: error: unknown field `alloc_inode" specified in initializer | |||
inode.c:584: warning: initialization from incompatible pointer type | |||
inode.c:585: error: unknown field `destroy_inode" specified in initializer | |||
inode.c:585: warning: initialization from incompatible pointer type | |||
Basically, around 2.4.20 - 2.4.24 kernel versions, they added support to '''alloc_inode''' inside the | |||
'''super_operation''' structure. Without that we are stuck. However, the same patch [[http://lkml.org/lkml/2003/1/3/265]] also define a new function called '''inode_init_once'''. | |||
# grep inode_init_once /proc/ksyms | |||
900ddcf8 inode_init_once | |||
So the Lim kernel has this patch. We need to add it to our kernel tree. | |||
vi +871 /home/lundman/uClinux-2.4/include/linux/fs.h | |||
struct super_operations { | |||
+ struct inode *(*alloc_inode)(struct super_block *sb); | |||
+ void (*destroy_inode)(struct inode *); | |||
+ | |||
void (*read_inode) (struct inode *); | |||
and suddenly it all compiles. Here it comes, loading the module will reveal the same missing functions: | |||
uclibc[/tmp]# insmod /mnt/smbfs1/fuse.o | |||
Using /mnt/smbfs1/fuse.o | |||
insmod: unresolved symbol page_cache_release | |||
insmod: unresolved symbol get_user_pages | |||
insmod: unresolved symbol grab_cache_page | |||
As it happens, we have a '''grab_cache_page_nowait''' so we can use that instead. The other two I take of by adding this to '''file.c''' | |||
#define page_cache_release(x) __free_page(x) | |||
int get_user_pages(struct task_struct *tsk, struct mm_struct *mm, | |||
unsigned long start, int len, int write, int force, | |||
struct page **pages, struct vm_area_struct **vmas) | |||
{ | |||
int i; | |||
static struct vm_area_struct dummy_vma; | |||
for (i = 0; i < len; i++) { | |||
if (pages) { | |||
pages[i] = virt_to_page(start); | |||
if (pages[i]) | |||
page_cache_get(pages[i]); | |||
} | |||
if (vmas) | |||
vmas[i] = &dummy_vma; | |||
start += PAGE_SIZE; | |||
} | |||
return(i); | |||
} | |||
Now it compiles, and loads. | |||
'''insmod /mnt/smbfs1/fuse.o''' | |||
Using /mnt/smbfs1/fuse.o | |||
'''lsmod''' | |||
Module Size Used by Tainted: P | |||
fuse 25720 0 (unused) | |||
'''mkdir /tmp/dev/''' | |||
'''mknod /tmp/dev/fuse -m 0666 c 10 229''' | |||
'''export PATH=$PATH:/mnt/smbfs1''' | |||
'''which fusermount''' | |||
/mnt/smbfs1/fusermount | |||
'''mkdir /tmp/test''' | |||
'''fusexmp /tmp/test/ -d -s &''' | |||
172 | |||
and panic. Bugger. So this time I'm sure I did no hacky things and yet it just plain panics. Since I can not get the kernel debug messages when something goes wrong, there is nothing much I can do to work out what is wrong. | |||
== SUCCESS == | |||
I have finally managed to get fuse to work. For some reason the fuse_init message hangs in '''down_read()''' semaphore lock. It is possible that something is holding, for now I comment that one call out and the rest works. | |||
'''insmod /mnt/smbfs1/fuse.o''' | |||
Using /mnt/smbfs1/fuse.o | |||
<4>fuse init (API version 7.5) | |||
<4>fuse distribution version: 2.5.3 | |||
<4>In fuse_dev_init | |||
<4>out fuse_dev_init | |||
'''hello /tmp/test''' | |||
unique: 1, opcode: INIT (26), nodeid: 0, insize: 48 | |||
INIT: 7.5 | |||
INIT: 7.5 | |||
unique: 1, error: 0 (Success), outsize: 40 | |||
'''ls -l /tmp/test/''' | |||
-r--r--r-- 1 root root 13 Dec 31 17:00 hello | |||
'''cat /tmp/test/hello''' | |||
Hello World! | |||
'''fusermount -u /tmp/test''' | |||
'''rmmod fuse''' | |||
<7>fuse exit | |||
== ntfs-3g == | |||
'''ntfs-3g /dev/ide/host0/bus0/target0/lun0/part1 /tmp/test''' | |||
Sorry, no daemon function | |||
Failed to daemonize. | |||
'''df -h''' | |||
/dev/ide/host0/bus0/target0/lun0/part1 39.1G 4.3G 34.8G 11% /tmp/test | |||
'''ls -l /tmp/test/''' | |||
drwxrwxrwx 1 root root 0 Oct 18 2007 System Volume Information | |||
-rwxrwxrwx 2 root root 4511754240 Jul 25 2007 Zathura-trailer.xvid.dd51.avi | |||
drwxrwxrwx 1 root root 0 Oct 18 2007 update | |||
'''mkdir test-directory''' | |||
'''ls -l''' | |||
drwxrwxrwx 1 root root 0 Jan 4 13:18 test-directory | |||
'''fusermount -u /tmp/test''' | |||
A word of warning, the reason that '''ntfs-3g''' now requires fuse-3.0 is due to: | |||
That's to do with umount on shutdown: if the ntfs-3g process is killed | |||
by the shutdown scripts before it can flush all data to disk, there | |||
can be some data loss. But otherwise this doesn't affect the | |||
operation. |
Latest revision as of 07:29, 23 October 2007
FUSE
As it turns out, there are at least two FUSE filesystems that sits on libdvdread / libdvdcss. I could use one of those, or a more raw one that only uses libdvdcss. However, first we will need FUSE compiled, and that is not easy. It seems only Fuse-1.4 will compile against such an old kernel. Most Fuse filesystems will not work against the old FUSE.
I have tried a few versions of FUSE.
Fuse-2.0b from [[1]]
uclibc[/tmp]# insmod fuse.ko Using fuse.ko insmod: unresolved symbol match_octal insmod: unresolved symbol page_cache_release insmod: unresolved symbol sema_init insmod: unresolved symbol match_token insmod: unresolved symbol BUG_ON insmod: unresolved symbol down insmod: unresolved symbol down_interruptible insmod: unresolved symbol down_trylock insmod: unresolved symbol match_int insmod: unresolved symbol grab_cache_page insmod: unresolved symbol up insmod: unresolved symbol test_bit
Fuse-2.5.3:
uclibc[/tmp]# insmod fuse.o Using fuse.o insmod: unresolved symbol page_cache_release insmod: unresolved symbol get_user_pages insmod: unresolved symbol grab_cache_page
Fuse-1.4:
uclibc[/tmp]# insmod fuse.o Using fuse.o insmod: unresolved symbol page_cache_release insmod: unresolved symbol BUG_ON insmod: unresolved symbol grab_cache_page
As it happens, grab_cache_page call can be replaced by a find_get_page. I have not found a replacement for page_cache_release but as a proof of concept I can go without it (and leak memory).
get_user_pages would be trickiest in 2.5.3, otherwise 1.4 should run if the BUG_ON thing isn't hard.
Trying Fuse
Ok tried 2.5.3 and patched my way around things with some serious hacks:
uclibc[/tmp]# insmod fuse-25.o Using fuse-25.o uclibc[/tmp]# lsmod Module Size Used by Tainted: P fuse-25 25664 0 (unused) uclibc[/tmp]# ./hello-25 /mnt/USB2 -d -s & 25157
But unfortunately df shows no mounts, and there is nothing to see in there. Oh well. It is possible the userland patches never gets to the kernel, as we can't daemonize, nor fork.
It is basically due to pthreads as it replaced vfork and blocks it all. Porting fuse not to be multi-threaded, and changing it to use /tmp/dev/fuse since /dev/ is read-only:
uclibc[/tmp]# dmesg fuse init (API version 7.5) fuse distribution version: 2.5.3 uclibc[/tmp]# mknod /tmp/dev/fuse -m 0666 c 10 229 uclibc[/tmp]# ./hello-25 /tmp/mnt -d -s I am HERE ibefore parsing before mount in mount, before socketpair before vfork after vfork 0 executing fusermount after vfork 262 Common 0x90ec6028
.. and it panics.. so .. shame I can't read the output from "dmesg" before then :)
Retrying Fuse-2.5.3
Fresh start, from compiling. Top level configure:
./configure CFLAGS="-DPATH_MAX=4096 -DMAX_LFS_FILESIZE=0x7fffffffffffffff -DFUSE_DEV_NEW=\"/tmp/dev/fuse\"" LDFLAGS=-Wl,-elf2flt --host=arm-elf --enable-static --enable-kernel-module --with-kernel=/home/lundman/uClinux-2.4 --disable-mtab vi libtool #version_type=none => =linux
Lots of small changes in .C, Makefile.am and Makefiles in general. Mostly to take out all multi-threaded things.
The do the same for kernel/ directory, but notice that the Makefile is not generated correctly.
vi kernel/Makefile #CC=arm-elf-gcc #LD=arm-elf-ld
And compile that. The first error we get is:
inode.c:584: error: unknown field `alloc_inode" specified in initializer inode.c:584: warning: initialization from incompatible pointer type inode.c:585: error: unknown field `destroy_inode" specified in initializer inode.c:585: warning: initialization from incompatible pointer type
Basically, around 2.4.20 - 2.4.24 kernel versions, they added support to alloc_inode inside the super_operation structure. Without that we are stuck. However, the same patch [[2]] also define a new function called inode_init_once.
# grep inode_init_once /proc/ksyms 900ddcf8 inode_init_once
So the Lim kernel has this patch. We need to add it to our kernel tree.
vi +871 /home/lundman/uClinux-2.4/include/linux/fs.h struct super_operations { + struct inode *(*alloc_inode)(struct super_block *sb); + void (*destroy_inode)(struct inode *); + void (*read_inode) (struct inode *);
and suddenly it all compiles. Here it comes, loading the module will reveal the same missing functions:
uclibc[/tmp]# insmod /mnt/smbfs1/fuse.o Using /mnt/smbfs1/fuse.o insmod: unresolved symbol page_cache_release insmod: unresolved symbol get_user_pages insmod: unresolved symbol grab_cache_page
As it happens, we have a grab_cache_page_nowait so we can use that instead. The other two I take of by adding this to file.c
#define page_cache_release(x) __free_page(x) int get_user_pages(struct task_struct *tsk, struct mm_struct *mm, unsigned long start, int len, int write, int force, struct page **pages, struct vm_area_struct **vmas) { int i; static struct vm_area_struct dummy_vma; for (i = 0; i < len; i++) { if (pages) { pages[i] = virt_to_page(start); if (pages[i]) page_cache_get(pages[i]); } if (vmas) vmas[i] = &dummy_vma; start += PAGE_SIZE; } return(i); }
Now it compiles, and loads.
insmod /mnt/smbfs1/fuse.o Using /mnt/smbfs1/fuse.o lsmod Module Size Used by Tainted: P fuse 25720 0 (unused) mkdir /tmp/dev/ mknod /tmp/dev/fuse -m 0666 c 10 229 export PATH=$PATH:/mnt/smbfs1 which fusermount /mnt/smbfs1/fusermount mkdir /tmp/test fusexmp /tmp/test/ -d -s & 172
and panic. Bugger. So this time I'm sure I did no hacky things and yet it just plain panics. Since I can not get the kernel debug messages when something goes wrong, there is nothing much I can do to work out what is wrong.
SUCCESS
I have finally managed to get fuse to work. For some reason the fuse_init message hangs in down_read() semaphore lock. It is possible that something is holding, for now I comment that one call out and the rest works.
insmod /mnt/smbfs1/fuse.o Using /mnt/smbfs1/fuse.o <4>fuse init (API version 7.5) <4>fuse distribution version: 2.5.3 <4>In fuse_dev_init <4>out fuse_dev_init hello /tmp/test unique: 1, opcode: INIT (26), nodeid: 0, insize: 48 INIT: 7.5 INIT: 7.5 unique: 1, error: 0 (Success), outsize: 40 ls -l /tmp/test/ -r--r--r-- 1 root root 13 Dec 31 17:00 hello cat /tmp/test/hello Hello World! fusermount -u /tmp/test rmmod fuse <7>fuse exit
ntfs-3g
ntfs-3g /dev/ide/host0/bus0/target0/lun0/part1 /tmp/test Sorry, no daemon function Failed to daemonize. df -h /dev/ide/host0/bus0/target0/lun0/part1 39.1G 4.3G 34.8G 11% /tmp/test ls -l /tmp/test/ drwxrwxrwx 1 root root 0 Oct 18 2007 System Volume Information -rwxrwxrwx 2 root root 4511754240 Jul 25 2007 Zathura-trailer.xvid.dd51.avi drwxrwxrwx 1 root root 0 Oct 18 2007 update mkdir test-directory ls -l drwxrwxrwx 1 root root 0 Jan 4 13:18 test-directory fusermount -u /tmp/test
A word of warning, the reason that ntfs-3g now requires fuse-3.0 is due to:
That's to do with umount on shutdown: if the ntfs-3g process is killed by the shutdown scripts before it can flush all data to disk, there can be some data loss. But otherwise this doesn't affect the operation.