On Sat, 2 Sep 2000, Alexander Viro wrote:
> IOW, bug in question _does_ give the same kind of behaviour, but whether
> innd is hitting it or something different that happens to act like that...
> The only way to know is to try it.
>
> I'll send rediffed patch in half an hour.
All right, it took longer than half an hour (RL sh*t in exactly wrong moment)
but here it is. Give it a try, folks.
diff -urN rc8-pre2/fs/ext2/inode.c rc8-pre2-truncate/fs/ext2/inode.c
--- rc8-pre2/fs/ext2/inode.c Sat Sep 2 23:14:35 2000
+++ rc8-pre2-truncate/fs/ext2/inode.c Sun Sep 3 00:03:57 2000
@@ -904,6 +904,7 @@
int nr = 0;
int n;
long iblock;
+ unsigned blocksize, tail;
if (!(S_ISREG(inode->i_mode) || S_ISDIR(inode->i_mode) ||
S_ISLNK(inode->i_mode)))
@@ -913,8 +914,33 @@
ext2_discard_prealloc(inode);
- iblock = (inode->i_size + inode->i_sb->s_blocksize-1)
+ blocksize = inode->i_sb->s_blocksize;
+ iblock = (inode->i_size + blocksize-1)
>> EXT2_BLOCK_SIZE_BITS(inode->i_sb);
+ tail = blocksize - (inode->i_size & (blocksize-1));
+
+ /*
+ * So truncate in the middle of a hole not on a block boundary will
+ * allocate a block. BFD. Everything is still consistent, so trying
+ * to be smart is not worth the trouble.
+ */
+ if (tail != blocksize) {
+ unsigned long index = inode->i_size >> PAGE_CACHE_SHIFT;
+ unsigned offset = (inode->i_size & (PAGE_CACHE_SIZE-1));
+ struct page *page = grab_cache_page(inode->i_mapping, index);
+ int err;
+ if (!page)
+ return; /* -ENOMEM */
+ err = block_prepare_write(page, offset, offset+tail,
+ ext2_get_block);
+ if (!err) {
+ memset(page_address(page)+offset, 0, tail);
+ flush_dcache_page(page);
+ generic_commit_write(NULL, page, offset, offset+tail);
+ }
+ UnlockPage(page);
+ page_cache_release(page);
+ }
n = ext2_block_to_path(inode, iblock, offsets);
if (n == 0)
-
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to [EMAIL PROTECTED]
Please read the FAQ at http://www.tux.org/lkml/