Hi, While trying to get affs working again, I noticed that the current cont_prepare_write is hardly working, if you write to a file in steps of 1024, the bytes pointer is never updated resulting in an endless loop. Below is a fixed version, that also removes the bogus tricks to the bytes ptr. I also "fixed" the comment, any reason we have to be insulting like this? Anyway, does anyone see a problem with the fix before I send it to Linus? bye, Roman
Index: fs/buffer.c =================================================================== RCS file: /dump/cvs/linux-2.4/fs/buffer.c,v retrieving revision 1.1.1.3 diff -u -r1.1.1.3 buffer.c --- fs/buffer.c 2000/07/17 10:46:49 1.1.1.3 +++ fs/buffer.c 2000/07/24 11:45:54 @@ -1585,7 +1585,7 @@ } /* - * For moronic filesystems that do not allow holes in file. + * For filesystems that do not allow holes in file. * We may have to extend the file. */ @@ -1600,7 +1600,15 @@ unsigned blocksize = inode->i_sb->s_blocksize; char *kaddr; - while(page->index > (pgpos = *bytes>>PAGE_CACHE_SHIFT)) { +restart: + zerofrom = offset; + pgpos = *bytes; + if (page->index < (pgpos >> PAGE_CACHE_SHIFT)) + goto skip_extend; + + zerofrom = pgpos & ~PAGE_CACHE_MASK; + pgpos >>= PAGE_CACHE_SHIFT; + while (page->index > pgpos) { status = -ENOMEM; new_page = grab_cache_page(mapping, pgpos); if (!new_page) @@ -1609,12 +1617,7 @@ if (*bytes>>PAGE_CACHE_SHIFT != pgpos) { UnlockPage(new_page); page_cache_release(new_page); - continue; - } - zerofrom = *bytes & ~PAGE_CACHE_MASK; - if (zerofrom & (blocksize-1)) { - *bytes |= (blocksize-1); - (*bytes)++; + goto restart; } status = __block_prepare_write(inode, new_page, zerofrom, PAGE_CACHE_SIZE, get_block); @@ -1626,35 +1629,26 @@ kunmap(new_page); UnlockPage(new_page); page_cache_release(new_page); + zerofrom = 0; + *bytes = ++pgpos << PAGE_CACHE_SHIFT; } - if (page->index < pgpos) { - /* completely inside the area */ - zerofrom = offset; - } else { - /* page covers the boundary, find the boundary offset */ - zerofrom = *bytes & ~PAGE_CACHE_MASK; - - /* if we will expand the thing last block will be filled */ - if (to > zerofrom && (zerofrom & (blocksize-1))) { - *bytes |= (blocksize-1); - (*bytes)++; - } + pgpos <<= PAGE_CACHE_SHIFT; + if (zerofrom < to) + *bytes = pgpos + to; - /* starting below the boundary? Nothing to zero out */ - if (offset <= zerofrom) - zerofrom = offset; - } +skip_extend: status = __block_prepare_write(inode, page, zerofrom, to, get_block); - if (status) - goto out1; - kaddr = (char*)page_address(page); - if (zerofrom < offset) { - memset(kaddr+zerofrom, 0, offset-zerofrom); - __block_commit_write(inode, page, zerofrom, offset); + if (!status) { + if (zerofrom < offset) { + kaddr = (char*)page_address(page); + memset(kaddr+zerofrom, 0, offset-zerofrom); + __block_commit_write(inode, page, zerofrom, offset); + *bytes = pgpos + to; + } + return 0; } - return 0; -out1: + ClearPageUptodate(page); kunmap(page); return status;