2006-02-25 11:08:47

by Olaf Hering

[permalink] [raw]
Subject: cramfs mounts provide corrupted content since 2.6.15


Any ideas why a cramfs mount provides empty files since at least 2.6.15?
It worked ok in 2.6.13 at least. Bug is still present in Linus tree.

These files (from the current openSuSE beta) needed updating. But the results are random.
Right now, after the 3th try, most files are correct, Hostname.so is still zero...

building file list ... done
etc/nsswitch.conf
usr/lib/perl5/5.8.8/ppc-linux-thread-multi-64int/auto/Data/Dumper/Dumper.so
usr/lib/perl5/5.8.8/ppc-linux-thread-multi-64int/auto/Fcntl/Fcntl.so
usr/lib/perl5/5.8.8/ppc-linux-thread-multi-64int/auto/IO/IO.so
usr/lib/perl5/5.8.8/ppc-linux-thread-multi-64int/auto/POSIX/POSIX.so
usr/lib/perl5/5.8.8/ppc-linux-thread-multi-64int/auto/Sys/Hostname/Hostname.so
usr/lib/perl5/vendor_perl/5.8.8/ppc-linux-thread-multi-64int/auto/Compress/Zlib/Zlib.so
usr/lib/perl5/vendor_perl/5.8.8/ppc-linux-thread-multi-64int/auto/Locale/gettext/gettext.so
var/spool/locks -> ../lock


lrwxrwxrwx 1 root root 7 1970-01-01 01:00 /mnt/var/spool/locks -> ../lock
lrwxrwxrwx 1 root root 7 2006-02-25 11:55 inst-sys/var/spool/locks -> ../lock
-rw-r--r-- 1 root root 1220 1970-01-01 01:00 /mnt/etc/nsswitch.conf
-rw-r--r-- 1 root root 1220 1970-01-01 01:00 inst-sys/etc/nsswitch.conf
-r-xr-xr-x 1 root root 36236 1970-01-01 01:00 /mnt/usr/lib/perl5/5.8.8/ppc-linux-thread-multi-64int/auto/Data/Dumper/Dumper.so
-r-xr-xr-x 1 root root 36236 1970-01-01 01:00 inst-sys/usr/lib/perl5/5.8.8/ppc-linux-thread-multi-64int/auto/Data/Dumper/Dumper.so
-r-xr-xr-x 1 root root 21136 1970-01-01 01:00 /mnt/usr/lib/perl5/5.8.8/ppc-linux-thread-multi-64int/auto/Fcntl/Fcntl.so
-r-xr-xr-x 1 root root 21136 1970-01-01 01:00 inst-sys/usr/lib/perl5/5.8.8/ppc-linux-thread-multi-64int/auto/Fcntl/Fcntl.so
-r-xr-xr-x 1 root root 22644 1970-01-01 01:00 /mnt/usr/lib/perl5/5.8.8/ppc-linux-thread-multi-64int/auto/IO/IO.so
-r-xr-xr-x 1 root root 22644 1970-01-01 01:00 inst-sys/usr/lib/perl5/5.8.8/ppc-linux-thread-multi-64int/auto/IO/IO.so
-r-xr-xr-x 1 root root 140852 1970-01-01 01:00 /mnt/usr/lib/perl5/5.8.8/ppc-linux-thread-multi-64int/auto/POSIX/POSIX.so
-r-xr-xr-x 1 root root 140852 1970-01-01 01:00 inst-sys/usr/lib/perl5/5.8.8/ppc-linux-thread-multi-64int/auto/POSIX/POSIX.so
-r--r--r-- 1 root root 0 1970-01-01 01:00 /mnt/usr/lib/perl5/5.8.8/ppc-linux-thread-multi-64int/auto/Sys/Hostname/Hostname.so
-r-xr-xr-x 1 root root 11384 1970-01-01 01:00 inst-sys/usr/lib/perl5/5.8.8/ppc-linux-thread-multi-64int/auto/Sys/Hostname/Hostname.so
-r-xr-xr-x 1 root root 69844 1970-01-01 01:00 /mnt/usr/lib/perl5/vendor_perl/5.8.8/ppc-linux-thread-multi-64int/auto/Compress/Zlib/Zlib.so
-r-xr-xr-x 1 root root 69844 1970-01-01 01:00 inst-sys/usr/lib/perl5/vendor_perl/5.8.8/ppc-linux-thread-multi-64int/auto/Compress/Zlib/Zlib.so
-r-xr-xr-x 1 root root 24004 1970-01-01 01:00 /mnt/usr/lib/perl5/vendor_perl/5.8.8/ppc-linux-thread-multi-64int/auto/Locale/gettext/gettext.so
-r-xr-xr-x 1 root root 24004 1970-01-01 01:00 inst-sys/usr/lib/perl5/vendor_perl/5.8.8/ppc-linux-thread-multi-64int/auto/Locale/gettext/gettext.so


Oh, and doing the md5sum thing shows even more errors.

olaf@ibook:/install/sles10/CD1/boot/ppc/inst-sys> sudo env -i md5sum -c /dev/shm/log | grep -wv OK$
olaf@ibook:/install/sles10/CD1/boot/ppc/inst-sys> cd /mnt/
olaf@ibook:/mnt> sudo env -i md5sum -c /dev/shm/log | grep -wv OK$
./etc/mtab: FAILED
./usr/lib/perl5/5.8.8/ppc-linux-thread-multi-64int/auto/Data/Dumper/Dumper.bs: FAILED
./usr/lib/perl5/5.8.8/ppc-linux-thread-multi-64int/auto/Fcntl/Fcntl.bs: FAILED
./usr/lib/perl5/5.8.8/ppc-linux-thread-multi-64int/auto/IO/IO.bs: FAILED
./usr/lib/perl5/5.8.8/ppc-linux-thread-multi-64int/auto/POSIX/POSIX.bs: FAILED
./usr/lib/perl5/5.8.8/ppc-linux-thread-multi-64int/auto/Sys/Hostname/Hostname.so: FAILED
./usr/lib/perl5/vendor_perl/5.8.8/ppc-linux-thread-multi-64int/auto/Compress/Zlib/Zlib.bs: FAILED
./usr/lib/perl5/vendor_perl/5.8.8/ppc-linux-thread-multi-64int/auto/Locale/gettext/gettext.bs: FAILED
md5sum: ./var/log/faillog: Is a directory
md5sum: ./var/log/lastlog: Is a directory
md5sum: ./var/log/mail: Is a directory
md5sum: ./var/log/messages: Is a directory
md5sum: ./var/log/news/news.crit: No such file or directory
md5sum: ./var/log/news/news.err: No such file or directory
md5sum: ./var/log/news/news.notice: No such file or directory
md5sum: ./var/log/sendmail.st: Is a directory
md5sum: ./var/log/wtmp: Is a directory
md5sum: ./var/log/xdm.errors: Is a directory
md5sum: WARNING: 10 of 6867 listed files could not be read
md5sum: WARNING: 8 of 6857 computed checksums did NOT match
./var/log/faillog: FAILED open or read
./var/log/lastlog: FAILED open or read
./var/log/mail: FAILED open or read
./var/log/messages: FAILED open or read
./var/log/news/news.crit: FAILED open or read
./var/log/news/news.err: FAILED open or read
./var/log/news/news.notice: FAILED open or read
./var/log/sendmail.st: FAILED open or read
./var/log/wtmp: FAILED open or read
./var/log/xdm.errors: FAILED open or read

Looking at the loopmount with a 2.6.13 kernel:

nectarine:~/inst-sys.orig # l ./var/log/lastlog
-rw-r--r-- 1 root tty 0 Jan 1 1970 ./var/log/lastlog

olaf@ibook:/mnt> l ./var/log/lastlog
lrwxrwxrwx 1 root root 7 1970-01-01 01:00 ./var/log/lastlog -> ../lock/


2006-02-25 12:55:59

by Olaf Hering

[permalink] [raw]
Subject: Re: cramfs mounts provide corrupted content since 2.6.15

On Sat, Feb 25, Olaf Hering wrote:
>
> Any ideas why a cramfs mount provides empty files since at least 2.6.15?
> It worked ok in 2.6.13 at least. Bug is still present in Linus tree.

Reverting a97c9bf33f4612e2aed6f000f6b1d268b6814f3c (from 2.6.14-rc1)
does appearently fix it:
[PATCH] fix cramfs making duplicate entries in inode cache

http://lkml.org/lkml/2006/2/25/48 for details

2006-02-25 16:38:18

by Dave Johnson

[permalink] [raw]
Subject: Re: cramfs mounts provide corrupted content since 2.6.15

Olaf Hering writes:
> On Sat, Feb 25, Olaf Hering wrote:
> >
> > Any ideas why a cramfs mount provides empty files since at least 2.6.15?
> > It worked ok in 2.6.13 at least. Bug is still present in Linus tree.
>
> Reverting a97c9bf33f4612e2aed6f000f6b1d268b6814f3c (from 2.6.14-rc1)
> does appearently fix it:
> [PATCH] fix cramfs making duplicate entries in inode cache

Humm, I've retested my patch against 2.6.12.6 (it was originally
created for 2.6.12) as well as 2.6.15.4 (no patch needed).

Appears fine with both kernel versions with an image containing a
variety of file types. Test was on ix86 not ppc though.

Looking at your output it's definitely getting inodes confused with
each other so the checks in cramfs_iget5_test() aren't working.

Can you stat the files in question to make sure they are actually
inode #1 on a working as well as non-working kernel? If your mkcramfs
isn't using #1 for empty files/links/dirs that'd be the problem.

Guess it could be endian issues, however cramfs is always host order
so that shouldn't matter as long as mkcramfs is run on the same
machine.


My test:
-------

Source material:

wallowa2:/localdisk/root/cramtest# find . |sort |xargs ls -ldi |sort
1520737 drwxr-xr-x 2 root root 4096 Feb 25 11:23 ./emptydir1
1520738 drwxrwxr-x 2 root root 4096 Feb 25 11:23 ./emptydir2
1520739 drwxr-xrwx 2 root root 4096 Feb 25 11:23 ./emptydir3
1520740 -rwxr-xr-x 1 root root 33 Feb 25 11:29 ./fulldir1/filea
1520741 drwxr-xr-x 2 root root 4096 Feb 25 11:29 ./fulldir1
1520742 drwxrwxr-x 2 root root 4096 Feb 25 11:29 ./fulldir2
1520743 drwxr-xrwx 2 root root 4096 Feb 25 11:30 ./fulldir3
1520744 brw-r--r-- 1 root root 1, 2 Feb 25 11:24 ./block1
1520745 brw-rw-r-- 1 root root 3, 4 Feb 25 11:24 ./block2
1520746 brw-r--rw- 1 root root 5, 6 Feb 25 11:24 ./block3
1520747 crw-r--r-- 1 root root 7, 8 Feb 25 11:25 ./char1
1520748 crw-rw-r-- 1 root root 9, 10 Feb 25 11:25 ./char2
1520749 crw-r--rw- 1 root root 11, 12 Feb 25 11:25 ./char3
1520750 lrwxrwxrwx 1 root root 6 Feb 25 11:25 ./link1 -> stuff1
1520751 lrwxrwxrwx 1 root root 6 Feb 25 11:25 ./link2 -> stuff2
1520752 lrwxrwxrwx 1 root root 6 Feb 25 11:25 ./link3 -> stuff3
1520753 -rwxr-xr-x 1 root root 628684 Feb 25 11:26 ./file1
1520754 -rwxrwxr-x 1 root root 31724 Feb 25 11:26 ./file2
1520755 -rwxr-xrwx 1 root root 113880 Feb 25 11:26 ./file3
1520756 -rwxrwxrwx 3 root root 4124 Feb 25 11:27 ./hardlink1
1520756 -rwxrwxrwx 3 root root 4124 Feb 25 11:27 ./hardlink2
1520756 -rwxrwxrwx 3 root root 4124 Feb 25 11:27 ./hardlink3
1520757 lrwxrwxrwx 1 root root 5 Feb 25 11:29 ./fulldir1/linka -> filea
1520758 -rwxr-xr-x 1 root root 53676 Feb 25 11:29 ./fulldir2/fileb
1520759 -rw-r--r-- 1 root root 3228 Feb 25 11:30 ./fulldir3/filec
1523357 drwxr-xr-x 8 root root 4096 Feb 25 11:29 .


2.6.12.6 (with my patch applied) cramfs:

wallowa2:/tmp/cramtest# find . |sort |xargs ls -ldi |sort
1 brw-r--r-- 1 root root 1, 2 Dec 31 1969 ./block1
1 brw-r--rw- 1 root root 5, 6 Dec 31 1969 ./block3
1 brw-rw-r-- 1 root root 3, 4 Dec 31 1969 ./block2
1 crw-r--r-- 1 root root 7, 8 Dec 31 1969 ./char1
1 crw-r--rw- 1 root root 11, 12 Dec 31 1969 ./char3
1 crw-rw-r-- 1 root root 9, 10 Dec 31 1969 ./char2
1 drwxr-xr-x 1 root root 0 Dec 31 1969 ./emptydir1
1 drwxr-xrwx 1 root root 0 Dec 31 1969 ./emptydir3
1 drwxrwxr-x 1 root root 0 Dec 31 1969 ./emptydir2
76 drwxr-xr-x 1 root root 444 Dec 31 1969 .
520 drwxr-xr-x 1 root root 40 Dec 31 1969 ./fulldir1
560 drwxrwxr-x 1 root root 20 Dec 31 1969 ./fulldir2
580 drwxr-xrwx 1 root root 20 Dec 31 1969 ./fulldir3
600 -rwxr-xr-x 1 root root 628684 Dec 31 1969 ./file1
332096 -rwxrwxr-x 1 root root 31724 Dec 31 1969 ./file2
349944 -rwxr-xrwx 1 root root 113880 Dec 31 1969 ./file3
408876 -rwxr-xr-x 1 root root 33 Dec 31 1969 ./fulldir1/filea
408924 lrwxrwxrwx 1 root root 5 Dec 31 1969 ./fulldir1/linka -> filea
408944 -rwxr-xr-x 1 root root 53676 Dec 31 1969 ./fulldir2/fileb
438440 -rw-r--r-- 1 root root 3228 Dec 31 1969 ./fulldir3/filec
439152 -rwxrwxrwx 1 root root 4124 Dec 31 1969 ./hardlink1
439152 -rwxrwxrwx 1 root root 4124 Dec 31 1969 ./hardlink2
439152 -rwxrwxrwx 1 root root 4124 Dec 31 1969 ./hardlink3
441280 lrwxrwxrwx 1 root root 6 Dec 31 1969 ./link1 -> stuff1
441300 lrwxrwxrwx 1 root root 6 Dec 31 1969 ./link2 -> stuff2
441320 lrwxrwxrwx 1 root root 6 Dec 31 1969 ./link3 -> stuff3


2.6.15.4 cramfs:

wallowa2:/tmp/cramtest# find . |sort |xargs ls -ldi |sort
1 brw-r--r-- 1 root root 1, 2 Dec 31 1969 ./block1
1 brw-r--rw- 1 root root 5, 6 Dec 31 1969 ./block3
1 brw-rw-r-- 1 root root 3, 4 Dec 31 1969 ./block2
1 crw-r--r-- 1 root root 7, 8 Dec 31 1969 ./char1
1 crw-r--rw- 1 root root 11, 12 Dec 31 1969 ./char3
1 crw-rw-r-- 1 root root 9, 10 Dec 31 1969 ./char2
1 drwxr-xr-x 1 root root 0 Dec 31 1969 ./emptydir1
1 drwxr-xrwx 1 root root 0 Dec 31 1969 ./emptydir3
1 drwxrwxr-x 1 root root 0 Dec 31 1969 ./emptydir2
76 drwxr-xr-x 1 root root 444 Dec 31 1969 .
520 drwxr-xr-x 1 root root 40 Dec 31 1969 ./fulldir1
560 drwxrwxr-x 1 root root 20 Dec 31 1969 ./fulldir2
580 drwxr-xrwx 1 root root 20 Dec 31 1969 ./fulldir3
600 -rwxr-xr-x 1 root root 628684 Dec 31 1969 ./file1
332096 -rwxrwxr-x 1 root root 31724 Dec 31 1969 ./file2
349944 -rwxr-xrwx 1 root root 113880 Dec 31 1969 ./file3
408876 -rwxr-xr-x 1 root root 33 Dec 31 1969 ./fulldir1/filea
408924 lrwxrwxrwx 1 root root 5 Dec 31 1969 ./fulldir1/linka -> filea
408944 -rwxr-xr-x 1 root root 53676 Dec 31 1969 ./fulldir2/fileb
438440 -rw-r--r-- 1 root root 3228 Dec 31 1969 ./fulldir3/filec
439152 -rwxrwxrwx 1 root root 4124 Dec 31 1969 ./hardlink1
439152 -rwxrwxrwx 1 root root 4124 Dec 31 1969 ./hardlink2
439152 -rwxrwxrwx 1 root root 4124 Dec 31 1969 ./hardlink3
441280 lrwxrwxrwx 1 root root 6 Dec 31 1969 ./link1 -> stuff1
441300 lrwxrwxrwx 1 root root 6 Dec 31 1969 ./link2 -> stuff2
441320 lrwxrwxrwx 1 root root 6 Dec 31 1969 ./link3 -> stuff3


--
Dave Johnson
Starent Networks

2006-02-25 22:01:33

by Olaf Hering

[permalink] [raw]
Subject: Re: cramfs mounts provide corrupted content since 2.6.15

On Sat, Feb 25, Dave Johnson wrote:

> Looking at your output it's definitely getting inodes confused with
> each other so the checks in cramfs_iget5_test() aren't working.
>
> Can you stat the files in question to make sure they are actually
> inode #1 on a working as well as non-working kernel? If your mkcramfs
> isn't using #1 for empty files/links/dirs that'd be the problem.

Another try, and different results again:

./etc/nsswitch.conf: FAILED
./usr/lib/perl5/5.8.8/ppc-linux-thread-multi-64int/auto/Data/Dumper/Dumper.so: FAILED
./usr/lib/perl5/5.8.8/ppc-linux-thread-multi-64int/auto/Fcntl/Fcntl.so: FAILED
./usr/lib/perl5/5.8.8/ppc-linux-thread-multi-64int/auto/IO/IO.so: FAILED
./usr/lib/perl5/5.8.8/ppc-linux-thread-multi-64int/auto/POSIX/POSIX.so: FAILED
./usr/lib/perl5/5.8.8/ppc-linux-thread-multi-64int/auto/Sys/Hostname/Hostname.so: FAILED
./usr/lib/perl5/vendor_perl/5.8.8/ppc-linux-thread-multi-64int/auto/Compress/Zlib/Zlib.so: FAILED
./usr/lib/perl5/vendor_perl/5.8.8/ppc-linux-thread-multi-64int/auto/Locale/gettext/gettext.so: FAILED

inode numbers match in both cases, just the filesize is zero and they have only one block.


File: `./usr/lib/perl5/vendor_perl/5.8.8/ppc-linux-thread-multi-64int/auto/Locale/gettext/gettext.so'
Size: 0 Blocks: 1 IO Block: 4096 regular empty file
Device: 701h/1793d Inode: 53053956 Links: 1
Access: (0444/-r--r--r--) Uid: ( 0/ root) Gid: ( 0/ root)
Access: 1970-01-01 01:00:00.000000000 +0100
Modify: 1970-01-01 01:00:00.000000000 +0100
Change: 1970-01-01 01:00:00.000000000 +0100

File: `./usr/lib/perl5/vendor_perl/5.8.8/ppc-linux-thread-multi-64int/auto/Locale/gettext/gettext.so'
Size: 24004 Blocks: 47 IO Block: 4096 regular file
Device: 702h/1794d Inode: 53053956 Links: 1
Access: (0555/-r-xr-xr-x) Uid: ( 0/ root) Gid: ( 0/ root)
Access: 1970-01-01 01:00:00.000000000 +0100
Modify: 1970-01-01 01:00:00.000000000 +0100
Change: 1970-01-01 01:00:00.000000000 +0100


./var/spool/locks turned into a file:

File: `./var/spool/locks'
Size: 0 Blocks: 1 IO Block: 4096 regular empty file
Device: 701h/1793d Inode: 85741484 Links: 1
Access: (0600/-rw-------) Uid: ( 0/ root) Gid: ( 0/ root)
Access: 1970-01-01 01:00:00.000000000 +0100
Modify: 1970-01-01 01:00:00.000000000 +0100
Change: 1970-01-01 01:00:00.000000000 +0100

File: `./var/spool/locks' -> `../lock'
Size: 7 Blocks: 1 IO Block: 4096 symbolic link
Device: 702h/1794d Inode: 85741484 Links: 1
Access: (0777/lrwxrwxrwx) Uid: ( 0/ root) Gid: ( 0/ root)
Access: 1970-01-01 01:00:00.000000000 +0100
Modify: 1970-01-01 01:00:00.000000000 +0100
Change: 1970-01-01 01:00:00.000000000 +0100

2006-02-27 16:31:30

by Dave Johnson

[permalink] [raw]
Subject: Re: cramfs mounts provide corrupted content since 2.6.15

Olaf Hering writes:
> On Sat, Feb 25, Dave Johnson wrote:
>
> > Looking at your output it's definitely getting inodes confused with
> > each other so the checks in cramfs_iget5_test() aren't working.
> >
> > Can you stat the files in question to make sure they are actually
> > inode #1 on a working as well as non-working kernel? If your mkcramfs
> > isn't using #1 for empty files/links/dirs that'd be the problem.
>
> Another try, and different results again:

Is it the same files every time you mount/umount the image?


I think I've spotted an issue.

Both ifind() and find_inode() will call the test function on inodes
that still have I_LOCK|I_NEW set. This means everything that the
test function needs _must_ be set in the set function (which is called
while the inode_lock is still held).

This could cause issues for inodes of 1 (only i_ino is getting set
right now).

However since you're seeing issues for inodes != 1, it could indicate
code elsewhere that isn't checking for I_LOCK|I_NEW.

Anyway, can you give the following patch a try?

--
Dave Johnson
Starent Networks

======================================


Fill out inode contents in cramfs_iget5_set() instead of get_cramfs_inode() to
prevent issues if cramfs_iget5_test() is called with I_LOCK|I_NEW still set.

Signed-off-by: Dave Johnson <[email protected]>

diff -Naur linux-2.6.15.4.orig/fs/cramfs/inode.c linux-2.6.15.4/fs/cramfs/inode.c
--- linux-2.6.15.4.orig/fs/cramfs/inode.c 2006-02-10 07:22:48.000000000 +0000
+++ linux-2.6.15.4/fs/cramfs/inode.c 2006-02-27 15:16:52.000000000 +0000
@@ -66,8 +66,36 @@

static int cramfs_iget5_set(struct inode *inode, void *opaque)
{
+ static struct timespec zerotime;
struct cramfs_inode *cramfs_inode = opaque;
+ inode->i_mode = cramfs_inode->mode;
+ inode->i_uid = cramfs_inode->uid;
+ inode->i_size = cramfs_inode->size;
+ inode->i_blocks = (cramfs_inode->size - 1) / 512 + 1;
+ inode->i_blksize = PAGE_CACHE_SIZE;
+ inode->i_gid = cramfs_inode->gid;
+ /* Struct copy intentional */
+ inode->i_mtime = inode->i_atime = inode->i_ctime = zerotime;
inode->i_ino = CRAMINO(cramfs_inode);
+ /* inode->i_nlink is left 1 - arguably wrong for directories,
+ but it's the best we can do without reading the directory
+ contents. 1 yields the right result in GNU find, even
+ without -noleaf option. */
+ if (S_ISREG(inode->i_mode)) {
+ inode->i_fop = &generic_ro_fops;
+ inode->i_data.a_ops = &cramfs_aops;
+ } else if (S_ISDIR(inode->i_mode)) {
+ inode->i_op = &cramfs_dir_inode_operations;
+ inode->i_fop = &cramfs_directory_operations;
+ } else if (S_ISLNK(inode->i_mode)) {
+ inode->i_op = &page_symlink_inode_operations;
+ inode->i_data.a_ops = &cramfs_aops;
+ } else {
+ inode->i_size = 0;
+ inode->i_blocks = 0;
+ init_special_inode(inode, inode->i_mode,
+ old_decode_dev(cramfs_inode->size));
+ }
return 0;
}

@@ -77,37 +105,7 @@
struct inode *inode = iget5_locked(sb, CRAMINO(cramfs_inode),
cramfs_iget5_test, cramfs_iget5_set,
cramfs_inode);
- static struct timespec zerotime;
-
if (inode && (inode->i_state & I_NEW)) {
- inode->i_mode = cramfs_inode->mode;
- inode->i_uid = cramfs_inode->uid;
- inode->i_size = cramfs_inode->size;
- inode->i_blocks = (cramfs_inode->size - 1) / 512 + 1;
- inode->i_blksize = PAGE_CACHE_SIZE;
- inode->i_gid = cramfs_inode->gid;
- /* Struct copy intentional */
- inode->i_mtime = inode->i_atime = inode->i_ctime = zerotime;
- inode->i_ino = CRAMINO(cramfs_inode);
- /* inode->i_nlink is left 1 - arguably wrong for directories,
- but it's the best we can do without reading the directory
- contents. 1 yields the right result in GNU find, even
- without -noleaf option. */
- if (S_ISREG(inode->i_mode)) {
- inode->i_fop = &generic_ro_fops;
- inode->i_data.a_ops = &cramfs_aops;
- } else if (S_ISDIR(inode->i_mode)) {
- inode->i_op = &cramfs_dir_inode_operations;
- inode->i_fop = &cramfs_directory_operations;
- } else if (S_ISLNK(inode->i_mode)) {
- inode->i_op = &page_symlink_inode_operations;
- inode->i_data.a_ops = &cramfs_aops;
- } else {
- inode->i_size = 0;
- inode->i_blocks = 0;
- init_special_inode(inode, inode->i_mode,
- old_decode_dev(cramfs_inode->size));
- }
unlock_new_inode(inode);
}
return inode;

2006-02-28 19:15:09

by Chris Mason

[permalink] [raw]
Subject: Re: cramfs mounts provide corrupted content since 2.6.15

On Monday 27 February 2006 11:31, Dave Johnson wrote:

> I think I've spotted an issue.
>
> Both ifind() and find_inode() will call the test function on inodes
> that still have I_LOCK|I_NEW set. This means everything that the
> test function needs _must_ be set in the set function (which is called
> while the inode_lock is still held).
>
> This could cause issues for inodes of 1 (only i_ino is getting set
> right now).

The problem is that two files are getting the same inode number because
their offsets are the same.

ls -lai:
3412140 -rw-r--r-- 1 root root 0 Jan 1 1970 ./etc/mtab
3412140 -rw-r--r-- 1 root root 1220 Jan 1 1970 ./etc/nsswitch.conf

So, if /etc/mtab is read first, /etc/nsswitch.conf ends up with size zero,
because it uses the mtab inode.

Andreas Gruenbacher suggested this change. Along with your patch, things
are working here again:

-chris

diff -r 0f4fc87886c2 fs/cramfs/inode.c
--- a/fs/cramfs/inode.c Fri Feb 24 16:18:23 2006 -0500
+++ b/fs/cramfs/inode.c Tue Feb 28 14:00:11 2006 -0500
@@ -36,7 +36,7 @@ static DECLARE_MUTEX(read_mutex);

/* These two macros may change in future, to provide better st_ino
semantics. */
-#define CRAMINO(x) ((x)->offset?(x)->offset<<2:1)
+#define CRAMINO(x) (((x)->offset && (x)->size)?(x)->offset<<2:1)
#define OFFSET(x) ((x)->i_ino)


2006-02-28 20:40:32

by Dave Johnson

[permalink] [raw]
Subject: Re: cramfs mounts provide corrupted content since 2.6.15

Chris Mason writes:
> On Monday 27 February 2006 11:31, Dave Johnson wrote:
>
> > I think I've spotted an issue.
> >
> > Both ifind() and find_inode() will call the test function on inodes
> > that still have I_LOCK|I_NEW set. This means everything that the
> > test function needs _must_ be set in the set function (which is called
> > while the inode_lock is still held).
> >
> > This could cause issues for inodes of 1 (only i_ino is getting set
> > right now).
>
> The problem is that two files are getting the same inode number because
> their offsets are the same.
>
> ls -lai:
> 3412140 -rw-r--r-- 1 root root 0 Jan 1 1970 ./etc/mtab
> 3412140 -rw-r--r-- 1 root root 1220 Jan 1 1970 ./etc/nsswitch.conf
>
> So, if /etc/mtab is read first, /etc/nsswitch.conf ends up with size zero,
> because it uses the mtab inode.
>
> Andreas Gruenbacher suggested this change. Along with your patch, things
> are working here again:
>
> -chris
>
> diff -r 0f4fc87886c2 fs/cramfs/inode.c
> --- a/fs/cramfs/inode.c Fri Feb 24 16:18:23 2006 -0500
> +++ b/fs/cramfs/inode.c Tue Feb 28 14:00:11 2006 -0500
> @@ -36,7 +36,7 @@ static DECLARE_MUTEX(read_mutex);
>
> /* These two macros may change in future, to provide better st_ino
> semantics. */
> -#define CRAMINO(x) ((x)->offset?(x)->offset<<2:1)
> +#define CRAMINO(x) (((x)->offset && (x)->size)?(x)->offset<<2:1)
> #define OFFSET(x) ((x)->i_ino)


What version of mkcramfs are you using? Empty regular files should
have offset set to 0 already.


--
Dave Johnson
Starent Networks

2006-02-28 20:53:11

by Chris Mason

[permalink] [raw]
Subject: Re: cramfs mounts provide corrupted content since 2.6.15

On Tuesday 28 February 2006 15:40, Dave Johnson wrote:

> What version of mkcramfs are you using? Empty regular files should
> have offset set to 0 already.

The image is being generated by util-linux 2.12r (this is the root disk for
the SUSE 10.1 install).

I checked via hexdump, the offset for mtab is definitely not zero.

-chris


2006-02-28 21:08:24

by Dave Johnson

[permalink] [raw]
Subject: Re: cramfs mounts provide corrupted content since 2.6.15

Chris Mason writes:
> On Tuesday 28 February 2006 15:40, Dave Johnson wrote:
>
> > What version of mkcramfs are you using? Empty regular files should
> > have offset set to 0 already.
>
> The image is being generated by util-linux 2.12r (this is the root disk for
> the SUSE 10.1 install).
>
> I checked via hexdump, the offset for mtab is definitely not zero.
>
> -chris
>

Ah, that makes sense now.

parse_directory() is different between util-linux 2.12r and
cramfstools 1.1:

util-linux 2.12r:

} else if (S_ISREG(st.st_mode)) {
entry->path = strdup(path);
if (entry->size) {
if (entry->size >= (1 << CRAMFS_SIZE_WIDTH)) {
warn_size = 1;
entry->size = (1 << CRAMFS_SIZE_WIDTH) - 1;
}
}


cramfstools 1.1:

} else if (S_ISREG(st.st_mode)) {
if (entry->size) {
if (access(path, R_OK) < 0) {
warn_skip = 1;
continue;
}
entry->path = strdup(path);
if (!entry->path) {
die(MKFS_ERROR, 1, "strdup failed");
}
if ((entry->size >= 1 << CRAMFS_SIZE_WIDTH)) {
warn_size = 1;
entry->size = (1 << CRAMFS_SIZE_WIDTH) - 1;
}
}


in cramfstools entry->path is not set for empty files causing
write_data() to keep offset set to 0.


--
Dave Johnson
Starent Networks

2006-02-28 21:14:04

by Chris Mason

[permalink] [raw]
Subject: Re: cramfs mounts provide corrupted content since 2.6.15

On Tuesday 28 February 2006 16:08, Dave Johnson wrote:

> Ah, that makes sense now.
>
> parse_directory() is different between util-linux 2.12r and
> cramfstools 1.1:

Great, I knew this was a userland bug as well, but since we've clearly got
broken cramfs images out there, I think it makes sense to add the fix in the
kernel too.

-chris