* [PATCH] ROMFS 0 byte file read error @ 2008-07-30 16:10 Chris Fester 2008-07-30 18:06 ` Linus Torvalds 0 siblings, 1 reply; 3+ messages in thread From: Chris Fester @ 2008-07-30 16:10 UTC (permalink / raw) To: lkml; +Cc: Alexander Viro, Linus Torvalds, Matt Waddel, Greg Ungerer I've verified that the git tree at: git://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux-2.6.git also has the zero byte file problem for romfs. This patch fixes the problem. Avoids calling romfs_copyfrom when in the 0 size case. Thanks! Chris Fester Signed-off-by: Chris Fester <cfester@wms.com> --- diff --git a/fs/romfs/inode.c b/fs/romfs/inode.c index 8e51a2a..5d24113 100644 --- a/fs/romfs/inode.c +++ b/fs/romfs/inode.c @@ -430,10 +430,10 @@ romfs_readpage(struct file *file, struct page * page) /* 32 bit warning -- but not for us :) */ offset = page_offset(page); - if (offset < i_size_read(inode)) { + if (offset <= i_size_read(inode)) { avail = inode->i_size-offset; readlen = min_t(unsigned long, avail, PAGE_SIZE); - if (romfs_copyfrom(inode, buf, ROMFS_I(inode)->i_dataoffset+offset, readlen) == readlen) { + if (!readlen || romfs_copyfrom(inode, buf, ROMFS_I(inode)->i_dataoffset+offset, readlen) == readlen) { if (readlen < PAGE_SIZE) { memset(buf + readlen,0,PAGE_SIZE-readlen); } ^ permalink raw reply [flat|nested] 3+ messages in thread
* Re: [PATCH] ROMFS 0 byte file read error 2008-07-30 16:10 [PATCH] ROMFS 0 byte file read error Chris Fester @ 2008-07-30 18:06 ` Linus Torvalds 2008-07-30 21:25 ` Chris Fester 0 siblings, 1 reply; 3+ messages in thread From: Linus Torvalds @ 2008-07-30 18:06 UTC (permalink / raw) To: Chris Fester; +Cc: lkml, Alexander Viro, Matt Waddel, Greg Ungerer On Wed, 30 Jul 2008, Chris Fester wrote: > > I've verified that the git tree at: > git://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux-2.6.git > > also has the zero byte file problem for romfs. This patch > fixes the problem. Avoids calling romfs_copyfrom when in > the 0 size case. Hmm. Who calls 'readpage()' with an offset past the end of the file anyway? This _really_ shouldn't matter. But regardless, isn't the bug that 'romfs_readpage()' sets an error bit by default - ie even if there was no actual IO error? The thing is also very confused about types: if it really wants to be safe in "loff_t, then it had bettr not do the "min_t()" in just "unsigned long". So this whole routine really seems to be much more broken than your patch implies, and your patch just works around some brokenness. Of course, I think it's all 32-bit and some of these problems cannot actually happen, but wouldn't it be more obvious to rewrite it to have a separate error return ("result") and a variable saying how much of the page was filled ("filled")? Something like this. UNTESTED. Pls verify and send back if this is ok. The patch is certainly bigger, but I think that the end result is more obvious. Linus --- fs/romfs/inode.c | 37 +++++++++++++++++++++++-------------- 1 files changed, 23 insertions(+), 14 deletions(-) diff --git a/fs/romfs/inode.c b/fs/romfs/inode.c index 8e51a2a..60d2f82 100644 --- a/fs/romfs/inode.c +++ b/fs/romfs/inode.c @@ -418,7 +418,8 @@ static int romfs_readpage(struct file *file, struct page * page) { struct inode *inode = page->mapping->host; - loff_t offset, avail, readlen; + loff_t offset, size; + unsigned long filled; void *buf; int result = -EIO; @@ -430,21 +431,29 @@ romfs_readpage(struct file *file, struct page * page) /* 32 bit warning -- but not for us :) */ offset = page_offset(page); - if (offset < i_size_read(inode)) { - avail = inode->i_size-offset; - readlen = min_t(unsigned long, avail, PAGE_SIZE); - if (romfs_copyfrom(inode, buf, ROMFS_I(inode)->i_dataoffset+offset, readlen) == readlen) { - if (readlen < PAGE_SIZE) { - memset(buf + readlen,0,PAGE_SIZE-readlen); - } - SetPageUptodate(page); - result = 0; + size = i_size_read(inode); + filled = 0; + result = 0; + if (offset < size) { + unsigned long readlen; + + size -= offset; + readlen = size > PAGE_SIZE ? PAGE_SIZE : size; + + filled = romfs_copyfrom(inode, buf, ROMFS_I(inode)->i_dataoffset+offset, readlen); + + if (filled != readlen) { + SetPageError(page); + filled = 0; + result = -EIO; } } - if (result) { - memset(buf, 0, PAGE_SIZE); - SetPageError(page); - } + + if (filled < PAGE_SIZE) + memset(buf + filled, 0, PAGE_SIZE-filled); + + if (!result) + SetPageUptodate(page); flush_dcache_page(page); unlock_page(page); ^ permalink raw reply [flat|nested] 3+ messages in thread
* Re: [PATCH] ROMFS 0 byte file read error 2008-07-30 18:06 ` Linus Torvalds @ 2008-07-30 21:25 ` Chris Fester 0 siblings, 0 replies; 3+ messages in thread From: Chris Fester @ 2008-07-30 21:25 UTC (permalink / raw) To: Linus Torvalds; +Cc: lkml, Alexander Viro, Matt Waddel, Greg Ungerer On Wed, Jul 30, 2008 at 11:06:29AM -0700, Linus Torvalds wrote: > Something like this. UNTESTED. Pls verify and send back if this is ok. The > patch is certainly bigger, but I think that the end result is more > obvious. > > Linus I tested this patch by: 1.) cat'ing the 0 length file. 2.) doing a diff between the loop mounted filesystem and the source directory for the romfs image. 3.) cp -rdp'ing the contents of the loop mounted filesystem to another directory, diffing that directory to the source directory. All of those tests pass. The image I'm testing with is about 23MB, with 900 files and directories. I agree that your patch generates far more straightforward code than the original. Coolbeans! Let me know if there's anything else I should do to test. Also, let me know if there's other pressing work to be done to this driver and I'll try my best at de-crustifying it. Thanks, Chris Fester > > --- > fs/romfs/inode.c | 37 +++++++++++++++++++++++-------------- > 1 files changed, 23 insertions(+), 14 deletions(-) > > diff --git a/fs/romfs/inode.c b/fs/romfs/inode.c > index 8e51a2a..60d2f82 100644 > --- a/fs/romfs/inode.c > +++ b/fs/romfs/inode.c > @@ -418,7 +418,8 @@ static int > romfs_readpage(struct file *file, struct page * page) > { > struct inode *inode = page->mapping->host; > - loff_t offset, avail, readlen; > + loff_t offset, size; > + unsigned long filled; > void *buf; > int result = -EIO; > > @@ -430,21 +431,29 @@ romfs_readpage(struct file *file, struct page * page) > > /* 32 bit warning -- but not for us :) */ > offset = page_offset(page); > - if (offset < i_size_read(inode)) { > - avail = inode->i_size-offset; > - readlen = min_t(unsigned long, avail, PAGE_SIZE); > - if (romfs_copyfrom(inode, buf, ROMFS_I(inode)->i_dataoffset+offset, readlen) == readlen) { > - if (readlen < PAGE_SIZE) { > - memset(buf + readlen,0,PAGE_SIZE-readlen); > - } > - SetPageUptodate(page); > - result = 0; > + size = i_size_read(inode); > + filled = 0; > + result = 0; > + if (offset < size) { > + unsigned long readlen; > + > + size -= offset; > + readlen = size > PAGE_SIZE ? PAGE_SIZE : size; > + > + filled = romfs_copyfrom(inode, buf, ROMFS_I(inode)->i_dataoffset+offset, readlen); > + > + if (filled != readlen) { > + SetPageError(page); > + filled = 0; > + result = -EIO; > } > } > - if (result) { > - memset(buf, 0, PAGE_SIZE); > - SetPageError(page); > - } > + > + if (filled < PAGE_SIZE) > + memset(buf + filled, 0, PAGE_SIZE-filled); > + > + if (!result) > + SetPageUptodate(page); > flush_dcache_page(page); > > unlock_page(page); ^ permalink raw reply [flat|nested] 3+ messages in thread
end of thread, other threads:[~2008-07-30 21:26 UTC | newest] Thread overview: 3+ messages (download: mbox.gz / follow: Atom feed) -- links below jump to the message on this page -- 2008-07-30 16:10 [PATCH] ROMFS 0 byte file read error Chris Fester 2008-07-30 18:06 ` Linus Torvalds 2008-07-30 21:25 ` Chris Fester
This is a public inbox, see mirroring instructions for how to clone and mirror all data and code used for this inbox
all inboxes | Powered by JetHome®