Chris Mason told me that page_mkwrite() has some works to do. On Wed, 17 Dec 2008 21:52:55 -0500, Chris Mason wrote: > nilfs_page_mkwrite doesn't seem to dirty the page? block_page_mkwrite > does more, including checks against i_size and others. This will insert i_size check, and hole block allocation code in the nilfs_page_mkwrite. Previously, the hole block allocation was delayed until just before writing for mmapped pages. This accompanies removal of the delayed allocation code. Cc: Chris Mason <chris.mason@xxxxxxxxxx> Signed-off-by: Ryusuke Konishi <konishi.ryusuke@xxxxxxxxxxxxx> --- fs/nilfs2/file.c | 59 +++++++++++++++++++++++++++++++++++++++++++++++++- fs/nilfs2/segment.c | 42 ++++-------------------------------- 2 files changed, 62 insertions(+), 39 deletions(-) diff --git a/fs/nilfs2/file.c b/fs/nilfs2/file.c index 7ddd42e..146dc23 100644 --- a/fs/nilfs2/file.c +++ b/fs/nilfs2/file.c @@ -75,11 +75,66 @@ nilfs_file_aio_write(struct kiocb *iocb, const struct iovec *iov, static int nilfs_page_mkwrite(struct vm_area_struct *vma, struct page *page) { - if (!(vma->vm_flags & (VM_WRITE | VM_MAYWRITE))) - return -EPERM; + struct inode *inode = vma->vm_file->f_dentry->d_inode; + struct address_space *mapping = inode->i_mapping; + struct nilfs_transaction_info ti; + struct buffer_head *bh, *head; + int fully_mapped = 1; + int ret = -EINVAL; + + /* + * use i_alloc_sem to stop truncate operations on the inode + */ + down_read(&inode->i_alloc_sem); + + if (page->mapping != mapping || + page_offset(page) >= i_size_read(inode) || !PageUptodate(page)) + goto failed; + + if (PageMappedToDisk(page)) + goto mapped; + + spin_lock(&mapping->private_lock); /* exclude try_to_free_buffers() */ + if (page_has_buffers(page)) { + bh = head = page_buffers(page); + do { + if (!buffer_mapped(bh)) { + fully_mapped = 0; + break; + } + } while (bh = bh->b_this_page, bh != head); + + if (fully_mapped) { + spin_unlock(&mapping->private_lock); + SetPageMappedToDisk(page); + goto mapped; + } + } + spin_unlock(&mapping->private_lock); + + /* + * Fill hole blocks. This accompanies a disk capacity check. + */ + ret = nilfs_transaction_begin(inode->i_sb, &ti, 1); + if (unlikely(ret)) + goto failed; + + ret = block_page_mkwrite(vma, page, nilfs_get_block); + if (unlikely(ret)) { + nilfs_transaction_abort(inode->i_sb); + goto failed; + } + nilfs_transaction_commit(inode->i_sb); + + mapped: + up_read(&inode->i_alloc_sem); SetPageChecked(page); wait_on_page_writeback(page); return 0; + + failed: + up_read(&inode->i_alloc_sem); + return ret; } struct vm_operations_struct nilfs_file_vm_ops = { diff --git a/fs/nilfs2/segment.c b/fs/nilfs2/segment.c index 182fb26..b5d28d2 100644 --- a/fs/nilfs2/segment.c +++ b/fs/nilfs2/segment.c @@ -667,42 +667,6 @@ struct nilfs_sc_operations nilfs_sc_dsync_ops = { .write_node_binfo = NULL, }; -static int nilfs_prepare_data_page(struct inode *inode, struct page *page) -{ - int err = 0; - - lock_page(page); - if (!page_has_buffers(page)) - create_empty_buffers(page, 1 << inode->i_blkbits, 0); - - if (!PageMappedToDisk(page)) { - struct buffer_head *bh, *head; - sector_t blkoff - = page->index << (PAGE_SHIFT - inode->i_blkbits); - - int non_mapped = 0; - - bh = head = page_buffers(page); - do { - if (!buffer_mapped(bh)) { - if (!buffer_dirty(bh)) { - non_mapped++; - continue; - } - err = nilfs_get_block(inode, blkoff, bh, 1); - if (unlikely(err)) - goto out_unlock; - } - } while (blkoff++, (bh = bh->b_this_page) != head); - if (!non_mapped) - SetPageMappedToDisk(page); - } - - out_unlock: - unlock_page(page); - return err; -} - static int nilfs_lookup_dirty_data_buffers(struct inode *inode, struct list_head *listp, struct nilfs_sc_info *sci) @@ -727,7 +691,11 @@ static int nilfs_lookup_dirty_data_buffers(struct inode *inode, struct page *page = pvec.pages[i]; if (mapping->host) { - err = nilfs_prepare_data_page(inode, page); + lock_page(page); + if (!page_has_buffers(page)) + create_empty_buffers(page, + 1 << inode->i_blkbits, 0); + unlock_page(page); if (unlikely(err)) break; } -- 1.5.6.5 -- To unsubscribe from this list: send the line "unsubscribe linux-fsdevel" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html