From: Joel & Rebecca VanderZee Date: Fri, 29 Sep 2006 09:00:30 +0000 (-0700) Subject: [PATCH] I/O Error attempting to read last partial block of a file in an ISO9660 file... X-Git-Tag: v2.6.19-rc1~741 X-Git-Url: https://err.no/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=fb50ae7446abb35184be029c51f825e45a4e0670;p=linux-2.6 [PATCH] I/O Error attempting to read last partial block of a file in an ISO9660 file system There was an I/O error that prevented reading the last partial block of large files in an ISO9660 filesystem. The error was generated when a file comprised more than one section and had a size that was not an exact multiple of the filesystem block size. This patch removes the check (and failure) for reading into the last partial block (and possibly beyond) for multiple-section files. It worked in my testing to prevent reading beyond the end of the section; my first patch just incremented the sect_size block count for a partial block and continued doing the check. But there is a commment in the source code about reading beyond the end of the file to fill a page cache. Failing to access beyond the section would prevent reading beyond the end of the file. Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- diff --git a/fs/isofs/inode.c b/fs/isofs/inode.c index 4527692f43..c34b862cdb 100644 --- a/fs/isofs/inode.c +++ b/fs/isofs/inode.c @@ -960,30 +960,30 @@ int isofs_get_blocks(struct inode *inode, sector_t iblock_s, goto abort; } - if (nextblk) { - while (b_off >= (offset + sect_size)) { - struct inode *ninode; - - offset += sect_size; - if (nextblk == 0) - goto abort; - ninode = isofs_iget(inode->i_sb, nextblk, nextoff); - if (!ninode) - goto abort; - firstext = ISOFS_I(ninode)->i_first_extent; - sect_size = ISOFS_I(ninode)->i_section_size >> ISOFS_BUFFER_BITS(ninode); - nextblk = ISOFS_I(ninode)->i_next_section_block; - nextoff = ISOFS_I(ninode)->i_next_section_offset; - iput(ninode); - - if (++section > 100) { - printk("isofs_get_blocks: More than 100 file sections ?!?, aborting...\n"); - printk("isofs_get_blocks: block=%ld firstext=%u sect_size=%u " - "nextblk=%lu nextoff=%lu\n", - iblock, firstext, (unsigned) sect_size, - nextblk, nextoff); - goto abort; - } + /* On the last section, nextblk == 0, section size is likely to + * exceed sect_size by a partial block, and access beyond the + * end of the file will reach beyond the section size, too. + */ + while (nextblk && (b_off >= (offset + sect_size))) { + struct inode *ninode; + + offset += sect_size; + ninode = isofs_iget(inode->i_sb, nextblk, nextoff); + if (!ninode) + goto abort; + firstext = ISOFS_I(ninode)->i_first_extent; + sect_size = ISOFS_I(ninode)->i_section_size >> ISOFS_BUFFER_BITS(ninode); + nextblk = ISOFS_I(ninode)->i_next_section_block; + nextoff = ISOFS_I(ninode)->i_next_section_offset; + iput(ninode); + + if (++section > 100) { + printk("isofs_get_blocks: More than 100 file sections ?!?, aborting...\n"); + printk("isofs_get_blocks: block=%ld firstext=%u sect_size=%u " + "nextblk=%lu nextoff=%lu\n", + iblock, firstext, (unsigned) sect_size, + nextblk, nextoff); + goto abort; } }