Messages in this thread Patch in this message |  | | Date | Sun, 3 Sep 2000 02:43:40 -0400 (EDT) | From | Alexander Viro <> |
| |
On Sat, 2 Sep 2000, Linus Torvalds wrote:
> > > On Sun, 3 Sep 2000, Alexander Viro wrote: > > > > > > Comments? Basically the "grab_cache_page()" would be a "read_cache_page()" > > > instead with all the wait-on-page etc stuff. > > > > Works for me. However, that way it looks like a fs/buffer.c fodder. > > Mind if I just call it block_zero_page(page, from, to) and export it? > > Not at all. In fact, I'd prefer it that way, because this same thing is > obviously going to be useful for any other block filesystem with the same > issue.
OK, after a bit of thinking it looks like we'll need slightly different prototype. How about the following? BTW, mem_is_zero() really asks for inclusion into string.h, IMO.
diff -urN rc8-2/fs/buffer.c linux-truncate/fs/buffer.c --- rc8-2/fs/buffer.c Sat Sep 2 21:10:37 2000 +++ linux-truncate/fs/buffer.c Sun Sep 3 02:34:56 2000 @@ -1721,6 +1721,54 @@ return 0; } +/* + * If it would be '74 that would go into libc... + */ +int mem_is_zero(char *p, unsigned len) +{ + while (len--) + if (*p++) + return 0; + return 1; +} + +int block_zero_page(struct address_space *mapping, loff_t from, unsigned length) +{ + unsigned long index = from >> PAGE_CACHE_SHIFT; + unsigned offset = from & (PAGE_CACHE_SIZE-1); + struct inode *inode = (struct inode *)mapping->host; + struct page *page; + char *kaddr; + int err; + + if (!length) + return 0; + + page = read_cache_page(mapping, index, + (filler_t *)mapping->a_ops->readpage, NULL); + err = PTR_ERR(page); + if (ERR_PTR(page)) + goto out; + lock_page(page); + err = -EIO; + if (!Page_Uptodate(page)) + goto unlock; + kaddr = (char*)kmap(page); + err = 0; + if (!mem_is_zero(kaddr+offset, length)) + goto unmap; + memset(kaddr+offset, 0, length); + flush_dcache_page(page); + __block_commit_write(inode, page, offset, offset+length); +unmap: + kunmap(page); +unlock: + UnlockPage(page); + page_cache_release(page); +out: + return err; +} + int block_write_full_page(struct page *page, get_block_t *get_block) { struct inode *inode = (struct inode*)page->mapping->host; diff -urN rc8-2/fs/ext2/inode.c linux-truncate/fs/ext2/inode.c --- rc8-2/fs/ext2/inode.c Sun Sep 3 02:26:35 2000 +++ linux-truncate/fs/ext2/inode.c Sun Sep 3 02:25:32 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,13 @@ 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 = (iblock << EXT2_BLOCK_SIZE_BITS(inode->i_sb)) - inode->i_size; + + if (block_zero_page(inode, inode->i_size, tail) != 0) + return; n = ext2_block_to_path(inode, iblock, offsets); if (n == 0) diff -urN rc8-2/include/linux/fs.h linux-truncate/include/linux/fs.h --- rc8-2/include/linux/fs.h Sat Sep 2 21:10:38 2000 +++ linux-truncate/include/linux/fs.h Sun Sep 3 02:20:04 2000 @@ -1162,6 +1162,7 @@ int generic_block_bmap(struct address_space *, long, get_block_t *); int generic_commit_write(struct file *, struct page *, unsigned, unsigned); +int block_zero_page(struct address_space *mapping, loff_t, unsigned); extern int generic_file_mmap(struct file *, struct vm_area_struct *); extern ssize_t generic_file_read(struct file *, char *, size_t, loff_t *); diff -urN rc8-2/kernel/ksyms.c linux-truncate/kernel/ksyms.c --- rc8-2/kernel/ksyms.c Sat Sep 2 21:10:39 2000 +++ linux-truncate/kernel/ksyms.c Sun Sep 3 02:20:33 2000 @@ -203,6 +203,7 @@ EXPORT_SYMBOL(block_sync_page); EXPORT_SYMBOL(cont_prepare_write); EXPORT_SYMBOL(generic_commit_write); +EXPORT_SYMBOL(block_zero_page); EXPORT_SYMBOL(generic_block_bmap); EXPORT_SYMBOL(generic_file_read); EXPORT_SYMBOL(do_generic_file_read); - To unsubscribe from this list: send the line "unsubscribe linux-kernel" in the body of a message to majordomo@vger.kernel.org Please read the FAQ at http://www.tux.org/lkml/
|  |