LimHD:Fuse

From Lundman Wiki
Revision as of 16:29, 23 October 2007 by Lundman (talk | contribs) (ntfs-3g)

(diff) ← Older revision | Latest revision (diff) | Newer revision → (diff)
Jump to: navigation, search

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.