2001-07-12 12:15:54

by Mario 'BitKoenig' Holbe

[permalink] [raw]
Subject: vfat: attempt to access beyond end of device

Hello,

I wrote this mail to [email protected] as suggested
in Documentation/filesystems/vfat.txt, but it seems, this
address is not valid (550 <[email protected]>...
Host unknown), so I try here :)

I have a 76Gig FAT32 Partition and mount it under Linux using
the vfat filesystem.

The filesystem is filled up to 85% at the moment and I
experience problems in writing new files on it under Linux.

Filesystem Size Used Avail Use% Mounted on
/dev/hdc1 76G 65G 12G 85% /data

When I try to write new files on it, I get:
kernel: attempt to access beyond end of device
kernel: 16:01: rw=0, want=2081231810, limit=80035798
kernel: dev = 16:01, ino = -2120058812
kernel: Filesystem panic (dev 16:01).
kernel: msdos_write_inode: unable to read i-node block
kernel: File system has been set read-only
kernel: attempt to access beyond end of device
kernel: 16:01: rw=0, want=2081231810, limit=80035798
kernel: dev = 16:01, ino = -2120058812
kernel: Filesystem panic (dev 16:01).
kernel: msdos_write_inode: unable to read i-node block

or (with 2.2.19):
kernel: attempt to access beyond end of device
kernel: 16:01: rw=0, want=2080939906, limit=80035798
kernel: dev 16:01 blksize=512 blocknr=-133087484 sector=-133087484 size=512 count=1
kernel: dev = 16:01, ino = -2129399739
kernel: Filesystem panic (dev 16:01).
kernel: msdos_write_inode: unable to read i-node block
kernel: File system has been set read-only
kernel: attempt to access beyond end of device
kernel: 16:01: rw=0, want=2080939906, limit=80035798
kernel: dev 16:01 blksize=512 blocknr=-133087484 sector=-133087484 size=512 count=1
kernel: dev = 16:01, ino = -2129399739
kernel: Filesystem panic (dev 16:01).
kernel: msdos_write_inode: unable to read i-node block

Copying the same files under Windows works fine and I'm able
to access them under Linux after copying them under Windows.

I found, that this ever happen, if the Filesystem is filled
up to 12G free space - last time i removed some other files
and defragmented the filesystem and then everything worked
fine up to this magic 65G border. Now it happens again.

Windows scandisk and Linux dosfsck don't report any errors
on the filesystem (of course, after the error they do, but
not before), but the write error is reproduceable for me.

I tried to copy a large file from the disk to itself - first
under Windows, next under Linux and this both worked fine, but
copying other files to other directories doesn't work
either.

It seems, when I copy some files under Windows, I'm able to
copy some more files under Linux too (something around 50
or 100 Megs) and then the problem occures again.

I'm using a 2.4.6 kernel at the moment, but the same problem
occured with 2.4.5 and 2.2.19 kernel too.

I guess, it's something like a bit overflow in some variable
while creating new meta structures or something, dunno what
vfat has there :)

Can you help me / can I help you to trace this down?


Thanks for your work.


regards,
Mario
--
Mario 'BitKoenig' Holbe <[email protected]>

So long and thanks for all the books.


2001-07-12 19:29:33

by OGAWA Hirofumi

[permalink] [raw]
Subject: Re: vfat: attempt to access beyond end of device

Hi,

This bug will be fixed by the following change.

diff -urN linux-2.4.7-pre6.orig/fs/fat/inode.c linux-2.4.7-pre6/fs/fat/inode.c
--- linux-2.4.7-pre6.orig/fs/fat/inode.c Tue Jun 12 11:15:27 2001
+++ linux-2.4.7-pre6/fs/fat/inode.c Fri Jul 13 04:20:04 2001
@@ -842,7 +842,7 @@
struct super_block *sb = inode->i_sb;
struct buffer_head *bh;
struct msdos_dir_entry *raw_entry;
- int i_pos;
+ unsigned int i_pos;

retry:
i_pos = MSDOS_I(inode)->i_location;


But, should change ino/i_location/i_pos to unsigned long in
fat/vfat/msdos/umsdos, IMHO.

Thanks.
--
OGAWA Hirofumi <[email protected]>

2001-07-12 21:15:09

by Alexander Griesser

[permalink] [raw]
Subject: Re: vfat: attempt to access beyond end of device

On Fri, Jul 13, 2001 at 04:29:02AM +0900, you wrote:
> This bug will be fixed by the following change.
>
> diff -urN linux-2.4.7-pre6.orig/fs/fat/inode.c linux-2.4.7-pre6/fs/fat/inode.c
> --- linux-2.4.7-pre6.orig/fs/fat/inode.c Tue Jun 12 11:15:27 2001
> +++ linux-2.4.7-pre6/fs/fat/inode.c Fri Jul 13 04:20:04 2001
> @@ -842,7 +842,7 @@
> struct super_block *sb = inode->i_sb;
> struct buffer_head *bh;
> struct msdos_dir_entry *raw_entry;
> - int i_pos;
> + unsigned int i_pos;
>
> retry:
> i_pos = MSDOS_I(inode)->i_location;
>
>
> But, should change ino/i_location/i_pos to unsigned long in
> fat/vfat/msdos/umsdos, IMHO.

When I try to write new files on it, I get:
kernel: attempt to access beyond end of device
kernel: 16:01: rw=0, want=2081231810, limit=80035798

According to his Problewm:
Shouldn't an "int" be enough?

2^31 = 2147483648
And he "wants": 2081231810

Should do, or did I miss something?



When I was tracking down this bug, I found some maybe interesting stuff
in /usr/src/linux-2.4.6/drivers/block/ll_rw_blk.c:


void generic_make_request (int rw, struct buffer_head * bh)
{
int major = MAJOR(bh->b_rdev);
int minorsize = 0;
request_queue_t *q;

if (!bh->b_end_io)
BUG();

/* Test device size, when known. */
if (blk_size[major])
minorsize = blk_size[major][MINOR(bh->b_rdev)];
if (minorsize) {
unsigned long maxsector = (minorsize << 1) + 1;
unsigned long sector = bh->b_rsector;
unsigned int count = bh->b_size >> 9;
^^^^^
/************** Shouldn't that be long? *****************/

if (maxsector < count || maxsector - count < sector) {
/* Yecch */
bh->b_state &= (1 << BH_Lock) | (1 << BH_Mapped);

/* This may well happen - the kernel calls bread()
without checking the size of the device, e.g.,
when mounting a device. */


/************** Here's his error message ****************/
printk(KERN_INFO
"attempt to access beyond end of device\n");
printk(KERN_INFO "%s: rw=%d, want=%ld, limit=%d\n",
kdevname(bh->b_rdev), rw,
(sector + count)>>1, minorsize);

/* Yecch again */
bh->b_end_io(bh, 0);
return;
}
}


regards, alexx
PS.: Please don't flame, if this is absolutely crap ;)
--
| .-. | CCNAIA Alexander Griesser <[email protected]> | .''`. |
| /v\ | http://www.tuxx-home.at -=- ICQ:63180135 | : :' : |
| /( )\ | echo "K..?f{1,2}e[nr]b?ck" >>~/.score | `. `' |
| ^^ ^^ | Linux Version 2.4.6 - Debian Unstable | `- |

2001-07-13 15:14:27

by OGAWA Hirofumi

[permalink] [raw]
Subject: Re: vfat: attempt to access beyond end of device

Hi,

Alexander Griesser <[email protected]> writes:

> When I try to write new files on it, I get:
> kernel: attempt to access beyond end of device
> kernel: 16:01: rw=0, want=2081231810, limit=80035798
>
> According to his Problewm:
> Shouldn't an "int" be enough?
>
> 2^31 = 2147483648
> And he "wants": 2081231810
>
> Should do, or did I miss something?

kernel: attempt to access beyond end of device
kernel: 16:01: rw=0, want=2081231810, limit=80035798
kernel: dev = 16:01, ino = -2120058812
^^^^^^^^^^^^
kernel: Filesystem panic (dev 16:01).

i_pos is -2120058812.

fat_write_inode()
i_pos = -2120058812; /* -2120058812 */
fat_bread(sb, i_pos >> 4); /* -132503676 */
...
getblk()
blocknr = block; /* 4162463620 */
...
submit_bh()
bh->b_rsector = bh->b_blocknr * count;
generic_make_request()
unsigned long sector = bh->b_rsector;

printk(KERN_INFO "%s: rw=%d, want=%ld, limit=%d\n",
kdevname(bh->b_rdev), rw,
(sector + count)>>1, minorsize); /* 2081231810 */

Thanks.
--
OGAWA Hirofumi <[email protected]>