diff options
-rw-r--r-- | fs/ext4/inode.c | 20 |
1 files changed, 18 insertions, 2 deletions
diff --git a/fs/ext4/inode.c b/fs/ext4/inode.c index babf4480c4ae..90077ec8fc21 100644 --- a/fs/ext4/inode.c +++ b/fs/ext4/inode.c @@ -2670,13 +2670,27 @@ static int __ext4_journalled_writepage(struct page *page, page_bufs = page_buffers(page); BUG_ON(!page_bufs); walk_page_buffers(handle, page_bufs, 0, len, NULL, bget_one); - /* As soon as we unlock the page, it can go away, but we have - * references to buffers so we are safe */ + /* + * We need to release the page lock before we start the + * journal, so grab a reference so the page won't disappear + * out from under us. + */ + get_page(page); unlock_page(page); handle = ext4_journal_start(inode, ext4_writepage_trans_blocks(inode)); if (IS_ERR(handle)) { ret = PTR_ERR(handle); + put_page(page); + goto out_no_pagelock; + } + + lock_page(page); + put_page(page); + if (page->mapping != mapping) { + /* The page got truncated from under us */ + ext4_journal_stop(handle); + ret = 0; goto out; } @@ -2694,6 +2708,8 @@ static int __ext4_journalled_writepage(struct page *page, walk_page_buffers(handle, page_bufs, 0, len, NULL, bput_one); ext4_set_inode_state(inode, EXT4_STATE_JDATA); out: + unlock_page(page); +out_no_pagelock: return ret; } |