Hard lock when mounting loopback file
I have a digital camera flash card that is locking up my machine (stock redhat 7.2 w/2.4.9-13 kernel).
I can mount the card, but as soon as I browse the filesystem, the machine locks hard. I successfully copied the file system from the raw device to a file and tried mounting it as:
mount -o loop flash.img /mnt/flash
and it still locks up the machine just as before. This makes me think it has nothing to do with the USB reader or the SCSI emulation, etc.
My guess is I have a corrupt filesystem on the flash that the filesystem handler (vfat) is intolerant of (all my other flash cards work fine).
This seems like a possible kernel bug to me. I'm not much of a kernel expert but I have a copy of the offending image if anyone wants to or can look at it. (ftp://actarg.com/pub/misc/flash.img) Is there someone that knows how to figure out if the driver can spit out a harmless message about filesystem corruption rather than taking the whole kernel down?
Kyle Bateman
Quoted 16 lines · Kyle
I have a digital camera flash card that is locking up my machine (stock redhat 7.2 w/2.4.9-13 kernel).
I can mount the card, but as soon as I browse the filesystem, the machine locks hard. I successfully copied the file system from the raw device to a file and tried mounting it as:
mount -o loop flash.img
/mnt/flashand it still locks up the machine just as before. This makes me think it has nothing to do with the USB reader or the SCSI emulation, etc.
My guess is I have a corrupt filesystem on the flash that the filesystem handler (vfat) is intolerant of (all my other flash cards work fine).
Quoted 7 lines
This seems like a possible kernel bug to me. I'm not much of a kernel expert but I have a copy of the offending image if anyone wants to or can look at it. (ftp://actarg.com/pub/misc/flash.img) Is there someone that knows how to figure out if the driver can spit out a harmless message about filesystem corruption rather than taking the whole kernel down?
I don't know a thing about fat layout, but it appears that it uses a linked list of blocks, and if that list ends up pointing back onto itself, the kernel goes into an infinite loop in several places chasing its way to the end of the list.
The below patch fixed it for me, and I was able to mount and read your filesystem image.
Unless someone has a smarter fix, I'll send this to the kernel maintainers in a week or two.
fs/fat/misc.c +7 -0
@@ -478,6 +478,8 @@ static int raw_scan_nonroot(struct super printk("raw_scan_nonroot: start=%d\n",start); #endif do { + int old_start = start; + for (count = 0; count < MSDOS_SB(sb)->cluster_size; count++) { if ((cluster = raw_scan_sector(sb,(start-2)* MSDOS_SB(sb)->cluster_size+MSDOS_SB(sb)->data_start+
@@ -486,6 +488,11 @@ static int raw_scan_nonroot(struct super }if (!(start =fat_access (sb,start,-1 ))) {fat_fs_panic (sb,"FAT error" ); +break ; + } +if (start == old_start) { +/* Prevent infinite loop on corrupt fs */ +fat_fs_panic (sb,"FAT loop" );break ; }#ifdef DEBUG
fs/fat/inode.c +12 -0
@@ -392,12 +392,18 @@ static void fat_read_root(struct inode *MSDOS_I (inode)->i_start = sbi->root_cluster;if ((nr =MSDOS_I (inode)->i_start) !=0 ) {while (nr !=-1 ) { +int old_nr = nr; inode->i_size +=1 << sbi->cluster_bits;if (!(nr =fat_access (sb, nr,-1 ))) {printk ("Directory %ld: bad FAT\n" , inode->i_ino);break ; } +if (nr == old_nr) { +printk ("Directory %ld: FAT loop\n" , + inode->i_ino); +break ; + } } } }else {
@@ -918,9 +924,15 @@ static void fat_fill_inode(struct inode#endif if ((nr =MSDOS_I (inode)->i_start) !=0 )while (nr !=-1 ) { +int old_nr = nr; inode->i_size +=1 << sbi->cluster_bits;if (!(nr =fat_access (sb, nr,-1 ))) {printk ("Directory %ld: bad FAT\n" , + inode->i_ino); +break ; + } +if (nr == old_nr) { +printk ("Directory %ld: FAT loop\n" , inode->i_ino);break ; }
Quoted 10 lines · Andrew Morton
I don't know a thing about fat layout, but it appears that it uses a linked list of blocks, and if that list ends up pointing back onto itself, the kernel goes into an infinite loop in several places chasing its way to the end of the list.
The below patch fixed it for me, and I was able to mount and read your filesystem image.
Unless someone has a smarter fix, I'll send this to the kernel maintainers in a week or two.
It seems to me that this patch will find only those infinite loops where the last link of the chain points to itself. But there could be loops where the last link points to the middle of the chain.
Additional check on the number of followed links could be useful there. No chain should be longer than the number of clusters on the fs. Although on large FAT32 filesystems the number of clusters can be high, a very long loop is still better than an infinite one. (In cases where we know the file size, this limit can be reduced to file_size/cluster_size + 1 links).
Marius Gedminas
Signature · 2 lines
This company has performed an illegal operation and will be shut down. If the problem persists, contact your vendor or appeal to a higher court.
Quoted 10 lines · Marius Gedminas
Quoted 8 lines · Andrew Morton
I don't know a thing about fat layout, but it appears that it uses a linked list of blocks, and if that list ends up pointing back onto itself, the kernel goes into an infinite loop in several places chasing its way to the end of the list.
The below patch fixed it for me, and I was able to mount and read your filesystem image.
Quoted 6 lines
Quoted 2 lines
Unless someone has a smarter fix, I'll send this to the kernel maintainers in a week or two.
It seems to me that this patch will find only those infinite loops where the last link of the chain points to itself. But there could be loops where the last link points to the middle of the chain.
Agree.
Quoted 6 lines
Additional check on the number of followed links could be useful there. No chain should be longer than the number of clusters on the fs. Although on large FAT32 filesystems the number of clusters can be high, a very long loop is still better than an infinite one. (In cases where we know the file size, this limit can be reduced to file_size/cluster_size + 1 links).
hmm.. OK, I'll take a look at that approach.
-
OGAWA Hirofumi
maintainerQuoted 8 lines · Andrew Morton
Quoted 6 lines
Additional check on the number of followed links could be useful there. No chain should be longer than the number of clusters on the fs. Although on large FAT32 filesystems the number of clusters can be high, a very long loop is still better than an infinite one. (In cases where we know the file size, this limit can be reduced to file_size/cluster_size + 1 links).
hmm.. OK, I'll take a look at that approach.
The maximum number of directory entries is 65536 in ordinarily. The following patch prevents the infinite loop of a directory (include the limit to added directory).
I think the following patch is a bit useful.
Signature · 213 lines
OGAWA Hirofumi <[email protected]> diff -urN linux-2.5.2-pre11/fs/fat/dir.c fat_loop/fs/fat/dir.c --- linux-2.5.2-pre11/fs/fat/dir.c Sat Oct 13 05:48:42 2001 +++ fat_loop/fs/fat/dir.c Mon Jan 14 17:40:48 2002 @@ -727,7 +727,13 @@ offset = curr = 0; *bh = NULL; row = 0; - while (fat_get_entry(dir,&curr,bh,de,ino) > -1) { + while (fat_get_entry(dir, &curr, bh, de, ino) > -1) { + /* check the maximum size of directory */ + if (curr >= FAT_MAX_DIR_SIZE) { + fat_brelse(sb, *bh); + return -ENOSPC; + } + if (IS_FREE((*de)->name)) { if (++row == slots) return offset; @@ -742,7 +748,10 @@ if (!new_bh) return -ENOSPC; fat_brelse(sb, new_bh); - do fat_get_entry(dir,&curr,bh,de,ino); while (++row<slots); + do { + fat_get_entry(dir, &curr, bh, de, ino); + } while (++row < slots); + return offset; } diff -urN linux-2.5.2-pre11/fs/fat/inode.c fat_loop/fs/fat/inode.c --- linux-2.5.2-pre11/fs/fat/inode.c Mon Jan 14 18:35:34 2002 +++ fat_loop/fs/fat/inode.c Mon Jan 14 03:45:33 2002 @@ -373,11 +373,37 @@ return ret; } +static void fat_calc_dir_size(struct inode *inode) +{ + struct super_block *sb = inode->i_sb; + int nr; + + inode->i_size = 0; + if (MSDOS_I(inode)->i_start == 0) + return; + + nr = MSDOS_I(inode)->i_start; + do { + inode->i_size += 1 << MSDOS_SB(sb)->cluster_bits; + if (!(nr = fat_access(sb, nr, -1))) { + printk("FAT: Directory %ld: bad FAT\n", + inode->i_ino); + break; + } + if (inode->i_size > FAT_MAX_DIR_SIZE) { + fat_fs_panic(sb, "Directory %ld: " + "exceeded the maximum size of directory", + inode->i_ino); + inode->i_size = FAT_MAX_DIR_SIZE; + break; + } + } while (nr != -1); +} + static void fat_read_root(struct inode *inode) { struct super_block *sb = inode->i_sb; struct msdos_sb_info *sbi = MSDOS_SB(sb); - int nr; INIT_LIST_HEAD(&MSDOS_I(inode)->i_fat_hash); MSDOS_I(inode)->i_location = 0; @@ -391,16 +417,7 @@ inode->i_fop = &fat_dir_operations; if (sbi->fat_bits == 32) { MSDOS_I(inode)->i_start = sbi->root_cluster; - if ((nr = MSDOS_I(inode)->i_start) != 0) { - while (nr != -1) { - inode->i_size += 1 << sbi->cluster_bits; - if (!(nr = fat_access(sb, nr, -1))) { - printk("Directory %ld: bad FAT\n", - inode->i_ino); - break; - } - } - } + fat_calc_dir_size(inode); } else { MSDOS_I(inode)->i_start = 0; inode->i_size = sbi->dir_entries * sizeof(struct msdos_dir_entry); @@ -882,7 +899,6 @@ { struct super_block *sb = inode->i_sb; struct msdos_sb_info *sbi = MSDOS_SB(sb); - int nr; INIT_LIST_HEAD(&MSDOS_I(inode)->i_fat_hash); MSDOS_I(inode)->i_location = 0; @@ -913,15 +929,7 @@ inode->i_nlink = 1; } #endif - if ((nr = MSDOS_I(inode)->i_start) != 0) - while (nr != -1) { - inode->i_size += 1 << sbi->cluster_bits; - if (!(nr = fat_access(sb, nr, -1))) { - printk("Directory %ld: bad FAT\n", - inode->i_ino); - break; - } - } + fat_calc_dir_size(inode); MSDOS_I(inode)->mmu_private = inode->i_size; } else { /* not a directory */ inode->i_generation |= 1; diff -urN linux-2.5.2-pre11/fs/fat/misc.c fat_loop/fs/fat/misc.c --- linux-2.5.2-pre11/fs/fat/misc.c Mon Jan 14 18:35:34 2002 +++ fat_loop/fs/fat/misc.c Mon Jan 14 06:13:24 2002 @@ -38,15 +38,25 @@ * read-only. The file system can be made writable again by remounting it. */ -void fat_fs_panic(struct super_block *s,const char *msg) +static char panic_msg[512]; + +void fat_fs_panic(struct super_block *s, const char *fmt, ...) { int not_ro; + va_list args; + + va_start (args, fmt); + vsnprintf (panic_msg, sizeof(panic_msg), fmt, args); + va_end (args); not_ro = !(s->s_flags & MS_RDONLY); - if (not_ro) s->s_flags |= MS_RDONLY; - printk("Filesystem panic (dev %s).\n %s\n", s->s_id, msg); if (not_ro) - printk(" File system has been set read-only\n"); + s->s_flags |= MS_RDONLY; + + printk("FAT: Filesystem panic (dev %s)\n" + " %s\n", s->s_id, panic_msg); + if (not_ro) + printk(" File system has been set read-only\n"); } @@ -472,11 +482,13 @@ int *number,int *ino,struct buffer_head **res_bh,struct msdos_dir_entry **res_de) { - int count,cluster; + int count, cluster; + unsigned long dir_size; #ifdef DEBUG printk("raw_scan_nonroot: start=%d\n",start); #endif + dir_size = 0; do { for (count = 0; count < MSDOS_SB(sb)->cluster_size; count++) { if ((cluster = raw_scan_sector(sb,(start-2)* @@ -484,6 +496,13 @@ count,name,number,ino,res_bh,res_de)) >= 0) return cluster; } + dir_size += 1 << MSDOS_SB(sb)->cluster_bits; + if (dir_size > FAT_MAX_DIR_SIZE) { + fat_fs_panic(sb, "Directory %d: " + "exceeded the maximum size of directory", + start); + break; + } if (!(start = fat_access(sb,start,-1))) { fat_fs_panic(sb,"FAT error"); break; @@ -491,8 +510,8 @@ #ifdef DEBUG printk("next start: %d\n",start); #endif - } - while (start != -1); + } while (start != -1); + return -ENOENT; } diff -urN linux-2.5.2-pre11/include/linux/msdos_fs.h fat_loop/include/linux/msdos_fs.h --- linux-2.5.2-pre11/include/linux/msdos_fs.h Mon Jan 14 18:35:41 2002 +++ fat_loop/include/linux/msdos_fs.h Mon Jan 14 05:33:06 2002 @@ -19,6 +19,10 @@ #define MSDOS_DPS_BITS 4 /* log2(MSDOS_DPS) */ #define MSDOS_DIR_BITS 5 /* log2(sizeof(struct msdos_dir_entry)) */ +/* directory limit */ +#define FAT_MAX_DIR_ENTRIES (65536) +#define FAT_MAX_DIR_SIZE (FAT_MAX_DIR_ENTRIES << MSDOS_DIR_BITS) + #define MSDOS_SUPER_MAGIC 0x4d44 /* MD */ #define FAT_CACHE 8 /* FAT cache size */ @@ -297,7 +301,7 @@ extern int fat_notify_change(struct dentry * dentry, struct iattr * attr); /* fat/misc.c */ -extern void fat_fs_panic(struct super_block *s, const char *msg); +extern void fat_fs_panic(struct super_block *s, const char *fmt, ...); extern int fat_is_binary(char conversion, char *extension); extern void lock_fat(struct super_block *sb); extern void unlock_fat(struct super_block *sb);
Quoted 10 lines · OGAWA Hirofumi
Quoted 7 lines · Andrew Morton
Quoted 6 lines
Additional check on the number of followed links could be useful there. No chain should be longer than the number of clusters on the fs. Although on large FAT32 filesystems the number of clusters can be high, a very long loop is still better than an infinite one. (In cases where we know the file size, this limit can be reduced to file_size/cluster_size + 1 links).
Quoted 7 lines
Quoted 1 line
hmm.. OK, I'll take a look at that approach.
The maximum number of directory entries is 65536 in ordinarily. The following patch prevents the infinite loop of a directory (include the limit to added directory).
I think the following patch is a bit useful.
Ah lovely. I was looking for your email address when this came up, but couldn't find it.
Here's the 2.4.18-pre3 version of your patch. I've tested it against the corrupted filesystem image and it works fine:
Jan 14 02:40:50 mnm kernel: FAT: Filesystem panic (dev 07:00) Jan 14 02:40:50 mnm kernel: Directory 3329: exceeded the maximum size of directory Jan 14 02:40:50 mnm kernel: File system has been set read-only Jan 14 02:40:50 mnm kernel: FAT: Filesystem panic (dev 07:00) Jan 14 02:40:50 mnm kernel: Directory 5: exceeded the maximum size of directory
If you're satisfied that everything is OK, I'd suggest that you send the diff to Marcelo.
Thanks.
fs/fat/dir.c +11 -2
@@ -727,7 +727,13 @@ int fat_add_entries(struct inode *dir,in offset = curr =0 ; *bh =NULL ; row =0 ; -while (fat_get_entry (dir,&curr,bh,de,ino) >-1 ) { +while (fat_get_entry (dir, &curr, bh, de, ino) >-1 ) { +/* check the maximum size of directory */ +if (curr >=FAT_MAX_DIR_SIZE ) { +fat_brelse (sb, *bh); +return -ENOSPC ; + } +if (IS_FREE ((*de)->name)) {if (++row == slots)return offset;
@@ -742,7 +748,10 @@ int fat_add_entries(struct inode *dir,inif (!new_bh)return -ENOSPC ;fat_brelse (sb, new_bh); -do fat_get_entry (dir,&curr,bh,de,ino);while (++row<slots); +do { +fat_get_entry (dir, &curr, bh, de, ino); + }while (++row < slots); +return offset; }
fs/fat/inode.c +29 -21
78 lines not on this page · raw message
fs/fat/misc.c +25 -7
@@ -38,15 +38,24 @@ static char ascii_extensions[] =* read-only. The file system can be made writable again by remounting it. */ -void fat_fs_panic (struct super_block *s,const char *msg) +static char panic_msg[512 ]; + +void fat_fs_panic (struct super_block *s,const char *fmt, ...) {int not_ro; +va_list args; + +va_start (args, fmt); +vsnprintf (panic_msg,sizeof (panic_msg), fmt, args); +va_end (args); not_ro = !(s->s_flags &MS_RDONLY ); -if (not_ro) s->s_flags |=MS_RDONLY ; -printk ("Filesystem panic (dev %s).\n %s\n" ,kdevname (s->s_dev), msg);if (not_ro) -printk (" File system has been set read-only\n" ); + s->s_flags |=MS_RDONLY ; +printk ("FAT: Filesystem panic (dev %s)\n" +" %s\n" ,kdevname (s->s_dev), panic_msg); +if (not_ro) +printk (" File system has been set read-only\n" ); }
@@ -472,11 +481,13 @@ static int raw_scan_nonroot(struct super int *number,int *ino,struct buffer_head **res_bh,struct msdos_dir_entry **res_de) { - int count,cluster; + int count, cluster; + unsigned long dir_size; #ifdef DEBUG printk("raw_scan_nonroot: start=%d\n",start); #endif + dir_size = 0; do { for (count = 0; count < MSDOS_SB(sb)->cluster_size; count++) { if ((cluster = raw_scan_sector(sb,(start-2)*
@@ -484,6 +495,13 @@ static int raw_scan_nonroot(struct super count,name,number,ino,res_bh,res_de)) >= 0)return cluster; } + dir_size +=1 <<MSDOS_SB (sb)->cluster_bits; +if (dir_size >FAT_MAX_DIR_SIZE ) { +fat_fs_panic (sb,"Directory %d: " +"exceeded the maximum size of directory" , + start); +break ; + }if (!(start =fat_access (sb,start,-1 ))) {fat_fs_panic (sb,"FAT error" );break ;
@@ -491,8 +509,8 @@ static int raw_scan_nonroot(struct super#ifdef DEBUG printk ("next start: %d\n" ,start);#endif - } -while (start !=-1 ); + }while (start !=-1 ); +return -ENOENT ; }
include/linux/msdos_fs.h +5 -1
@@ -19,6 +19,10 @@#define MSDOS_DPS_BITS 4/* log2(MSDOS_DPS) */ #define MSDOS_DIR_BITS 5/* log2(sizeof(struct msdos_dir_entry)) */ +/* directory limit */ +#define FAT_MAX_DIR_ENTRIES (65536) +#define FAT_MAX_DIR_SIZE (FAT_MAX_DIR_ENTRIES << MSDOS_DIR_BITS) +#define MSDOS_SUPER_MAGIC 0x4d44/* MD */ #define FAT_CACHE 8/* FAT cache size */
@@ -297,7 +301,7 @@ extern void fat_write_inode(struct inodeextern int fat_notify_change (struct dentry * dentry,struct iattr * attr);/* fat/misc.c */ -extern void fat_fs_panic (struct super_block *s,const char *msg); +extern void fat_fs_panic (struct super_block *s,const char *fmt, ...);extern int fat_is_binary (char conversion,char *extension);extern void lock_fat (struct super_block *sb);extern void unlock_fat (struct super_block *sb);
Andrew Morton <[email protected]> said:
[...]
Quoted 4 lines
I don't know a thing about fat layout, but it appears that it uses a linked list of blocks, and if that list ends up pointing back onto itself, the kernel goes into an infinite loop in several places chasing its way to the end of the list.
Right.
Quoted 2 lines
The below patch fixed it for me, and I was able to mount and read your filesystem image.
AFAIKS, this just cures the case where the wild pointer points to the first block of the offending file. You should perhaps count the blocks you go through, so a file something like:
-------+-----+
^ |
| |
+-----+or other strange pointer messups don't get you.
BTW, is fsck (the Linux or the Win32 variety) able to fix this?
Signature · 1 line
Horst von Brand http://counter.li.org # 22616
OGAWA Hirofumi
maintainerQuoted 13 lines · Andrew Morton
Quoted 12 lines · OGAWA Hirofumi
Quoted 8 lines · Andrew Morton
Quoted 6 lines
Additional check on the number of followed links could be useful there. No chain should be longer than the number of clusters on the fs. Although on large FAT32 filesystems the number of clusters can be high, a very long loop is still better than an infinite one. (In cases where we know the file size, this limit can be reduced to file_size/cluster_size + 1 links).
hmm.. OK, I'll take a look at that approach.
Quoted 8 lines
Quoted 5 lines
The maximum number of directory entries is 65536 in ordinarily. The following patch prevents the infinite loop of a directory (include the limit to added directory).
I think the following patch is a bit useful.
Ah lovely. I was looking for your email address when this came up, but couldn't find it.
Sorry, that patch is first post.
Quoted 11 lines
Here's the 2.4.18-pre3 version of your patch. I've tested it against the corrupted filesystem image and it works fine:
Jan 14 02:40:50 mnm kernel: FAT: Filesystem panic (dev 07:00) Jan 14 02:40:50 mnm kernel: Directory 3329: exceeded the maximum size of directory Jan 14 02:40:50 mnm kernel: File system has been set read-only Jan 14 02:40:50 mnm kernel: FAT: Filesystem panic (dev 07:00) Jan 14 02:40:50 mnm kernel: Directory 5: exceeded the maximum size of directoryIf you're satisfied that everything is OK, I'd suggest that you send the diff to Marcelo.
Thanks. That patch doesn't completely prevent the infinite loop (regular file), but I think the following patch is useful (directory).
Marcelo, please apply the following patch.
fs/fat/dir.c +11 -2
@@ -727,7 +727,13 @@ int fat_add_entries(struct inode *dir,in offset = curr =0 ; *bh =NULL ; row =0 ; -while (fat_get_entry (dir,&curr,bh,de,ino) >-1 ) { +while (fat_get_entry (dir, &curr, bh, de, ino) >-1 ) { +/* check the maximum size of directory */ +if (curr >=FAT_MAX_DIR_SIZE ) { +fat_brelse (sb, *bh); +return -ENOSPC ; + } +if (IS_FREE ((*de)->name)) {if (++row == slots)return offset;
@@ -742,7 +748,10 @@ int fat_add_entries(struct inode *dir,inif (!new_bh)return -ENOSPC ;fat_brelse (sb, new_bh); -do fat_get_entry (dir,&curr,bh,de,ino);while (++row<slots); +do { +fat_get_entry (dir, &curr, bh, de, ino); + }while (++row < slots); +return offset; }
fs/fat/inode.c +29 -21
78 lines not on this page · raw message
fs/fat/misc.c +25 -7
@@ -38,15 +38,24 @@ static char ascii_extensions[] =* read-only. The file system can be made writable again by remounting it. */ -void fat_fs_panic (struct super_block *s,const char *msg) +static char panic_msg[512 ]; + +void fat_fs_panic (struct super_block *s,const char *fmt, ...) {int not_ro; +va_list args; + +va_start (args, fmt); +vsnprintf (panic_msg,sizeof (panic_msg), fmt, args); +va_end (args); not_ro = !(s->s_flags &MS_RDONLY ); -if (not_ro) s->s_flags |=MS_RDONLY ; -printk ("Filesystem panic (dev %s).\n %s\n" ,kdevname (s->s_dev), msg);if (not_ro) -printk (" File system has been set read-only\n" ); + s->s_flags |=MS_RDONLY ; +printk ("FAT: Filesystem panic (dev %s)\n" +" %s\n" ,kdevname (s->s_dev), panic_msg); +if (not_ro) +printk (" File system has been set read-only\n" ); }
@@ -472,11 +481,13 @@ static int raw_scan_nonroot(struct super int *number,int *ino,struct buffer_head **res_bh,struct msdos_dir_entry **res_de) { - int count,cluster; + int count, cluster; + unsigned long dir_size; #ifdef DEBUG printk("raw_scan_nonroot: start=%d\n",start); #endif + dir_size = 0; do { for (count = 0; count < MSDOS_SB(sb)->cluster_size; count++) { if ((cluster = raw_scan_sector(sb,(start-2)*
@@ -484,6 +495,13 @@ static int raw_scan_nonroot(struct super count,name,number,ino,res_bh,res_de)) >= 0)return cluster; } + dir_size +=1 <<MSDOS_SB (sb)->cluster_bits; +if (dir_size >FAT_MAX_DIR_SIZE ) { +fat_fs_panic (sb,"Directory %d: " +"exceeded the maximum size of directory" , + start); +break ; + }if (!(start =fat_access (sb,start,-1 ))) {fat_fs_panic (sb,"FAT error" );break ;
@@ -491,8 +509,8 @@ static int raw_scan_nonroot(struct super#ifdef DEBUG printk ("next start: %d\n" ,start);#endif - } -while (start !=-1 ); + }while (start !=-1 ); +return -ENOENT ; }
include/linux/msdos_fs.h +5 -1
@@ -19,6 +19,10 @@#define MSDOS_DPS_BITS 4/* log2(MSDOS_DPS) */ #define MSDOS_DIR_BITS 5/* log2(sizeof(struct msdos_dir_entry)) */ +/* directory limit */ +#define FAT_MAX_DIR_ENTRIES (65536) +#define FAT_MAX_DIR_SIZE (FAT_MAX_DIR_ENTRIES << MSDOS_DIR_BITS) +#define MSDOS_SUPER_MAGIC 0x4d44/* MD */ #define FAT_CACHE 8/* FAT cache size */
@@ -297,7 +301,7 @@ extern void fat_write_inode(struct inodeextern int fat_notify_change (struct dentry * dentry,struct iattr * attr);/* fat/misc.c */ -extern void fat_fs_panic (struct super_block *s,const char *msg); +extern void fat_fs_panic (struct super_block *s,const char *fmt, ...);extern int fat_is_binary (char conversion,char *extension);extern void lock_fat (struct super_block *sb);extern void unlock_fat (struct super_block *sb);
Signature · 1 line
OGAWA Hirofumi <[email protected]>