[patch 3/3] fs: buffer_head page_lock i_size relax
From: Nick Piggin <hidden>
Date: 2009-07-10 09:35:10
Also in:
linux-fsdevel
The previous patch allows us to relax the buffer.c requirement that the page lock be held in order to avoid writepage zeroing out new data beyond isize. [actually as I said I think it still has a bug due to writepage requiring i_size_read] --- fs/buffer.c | 28 ++++++++-------------------- mm/shmem.c | 6 +++--- 2 files changed, 11 insertions(+), 23 deletions(-) Index: linux-2.6/fs/buffer.c ===================================================================
--- linux-2.6.orig/fs/buffer.c
+++ linux-2.6/fs/buffer.c@@ -2049,33 +2049,20 @@ int generic_write_end(struct file *file, struct page *page, void *fsdata) { struct inode *inode = mapping->host; - int i_size_changed = 0; copied = block_write_end(file, mapping, pos, len, copied, page, fsdata); + unlock_page(page); + page_cache_release(page); + /* * No need to use i_size_read() here, the i_size * cannot change under us because we hold i_mutex. - * - * But it's important to update i_size while still holding page lock: - * page writeout could otherwise come in and zero beyond i_size. */ if (pos+copied > inode->i_size) { i_size_write(inode, pos+copied); - i_size_changed = 1; - } - - unlock_page(page); - page_cache_release(page); - - /* - * Don't mark the inode dirty under page lock. First, it unnecessarily - * makes the holding time of page lock longer. Second, it forces lock - * ordering of page lock and transaction start for journaling - * filesystems. - */ - if (i_size_changed) mark_inode_dirty(inode); + } return copied; }
@@ -2624,14 +2611,15 @@ int nobh_write_end(struct file *file, st SetPageUptodate(page); set_page_dirty(page); + + unlock_page(page); + page_cache_release(page); + if (pos+copied > inode->i_size) { i_size_write(inode, pos+copied); mark_inode_dirty(inode); } - unlock_page(page); - page_cache_release(page); - while (head) { bh = head; head = head->b_this_page;
Index: linux-2.6/mm/shmem.c ===================================================================
--- linux-2.6.orig/mm/shmem.c
+++ linux-2.6/mm/shmem.c@@ -1631,13 +1631,13 @@ shmem_write_end(struct file *file, struc { struct inode *inode = mapping->host; - if (pos + copied > inode->i_size) - i_size_write(inode, pos + copied); - unlock_page(page); set_page_dirty(page); page_cache_release(page); + if (pos + copied > inode->i_size) + i_size_write(inode, pos + copied); + return copied; } --
To unsubscribe, send a message with 'unsubscribe linux-mm' in the body to majordomo@kvack.org. For more info on Linux MM, see: http://www.linux-mm.org/ . Don't email: <a href=mailto:"dont@kvack.org"> email@kvack.org </a>