Message ID | 1249213404-6277-1-git-send-email-bergwolf@gmail.com |
---|---|
State | Superseded, archived |
Headers | show |
Hi Peng, Peng Tao wrote: > move_extent_par_page calls a_ops->write_begin() to increase journal handler's > reference count. However, if either mext_replace_branches() or ext4_get_block > fails, the increased reference count isn't decreased. This will cause later > umounting of the fs forever hangs. The patch addresses the issue by calling > ext4_journal_stop() if page is not NULL (which means a_ops->write_end() isn't > invoked). In case mext_replaced_branches() or ext4_get_block failed, ext4_journal_stop() is called at out2 label(*) and then journal reference counter is decreased. Therefore I think this fix is not necessary. static int move_extent_par_page(struct file *o_filp, struct inode *donor_inode, pgoff_t orig_page_offset, int data_offset_in_page, int block_len_in_page, int uninit) <snip> out: if (unlikely(page)) { if (PageLocked(page)) unlock_page(page); page_cache_release(page); } out2: * ext4_journal_stop(handle); return ret < 0 ? ret : 0; } Regards, Akira Fujita -- To unsubscribe from this list: send the line "unsubscribe linux-ext4" in the body of a message to majordomo@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
Hi, Akira, 2009/8/3 Akira Fujita <a-fujita@rs.jp.nec.com>: > Hi Peng, > > Peng Tao wrote: >> move_extent_par_page calls a_ops->write_begin() to increase journal handler's >> reference count. However, if either mext_replace_branches() or ext4_get_block >> fails, the increased reference count isn't decreased. This will cause later >> umounting of the fs forever hangs. The patch addresses the issue by calling >> ext4_journal_stop() if page is not NULL (which means a_ops->write_end() isn't >> invoked). > > In case mext_replaced_branches() or ext4_get_block failed, > ext4_journal_stop() is called at out2 label(*) > and then journal reference counter is decreased. > Therefore I think this fix is not necessary. well, the orginal code calls both ext4_journal_start and a_ops->write_begin(). So the journal reference was increased twice but only gets decreased once in case of failure. This can be simply verified by returning -1 at the begining of mext_replaced_branches(). With such modification, the fs cannot be umounted because of the wrong reference count. > > static int > move_extent_par_page(struct file *o_filp, struct inode *donor_inode, > pgoff_t orig_page_offset, int data_offset_in_page, > int block_len_in_page, int uninit) > <snip> > > out: > if (unlikely(page)) { > if (PageLocked(page)) > unlock_page(page); > page_cache_release(page); > } > out2: > * ext4_journal_stop(handle); > > return ret < 0 ? ret : 0; > } > > Regards, > Akira Fujita >
Peng Tao wrote: > Hi, Akira, > > 2009/8/3 Akira Fujita <a-fujita@rs.jp.nec.com>: >> Hi Peng, >> >> Peng Tao wrote: >>> move_extent_par_page calls a_ops->write_begin() to increase journal handler's >>> reference count. However, if either mext_replace_branches() or ext4_get_block >>> fails, the increased reference count isn't decreased. This will cause later >>> umounting of the fs forever hangs. The patch addresses the issue by calling >>> ext4_journal_stop() if page is not NULL (which means a_ops->write_end() isn't >>> invoked). >> In case mext_replaced_branches() or ext4_get_block failed, >> ext4_journal_stop() is called at out2 label(*) >> and then journal reference counter is decreased. >> Therefore I think this fix is not necessary. > well, the orginal code calls both ext4_journal_start and > a_ops->write_begin(). So the journal reference was increased twice but > only gets decreased once in case of failure. This can be simply > verified by returning -1 at the begining of mext_replaced_branches(). > With such modification, the fs cannot be umounted because of the wrong > reference count. Ah, I missed. Sorry for the noise. The patch looks good to me. Regards, Akira Fujita -- To unsubscribe from this list: send the line "unsubscribe linux-ext4" in the body of a message to majordomo@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
diff --git a/fs/ext4/move_extent.c b/fs/ext4/move_extent.c index bbf2dd9..5821e0b 100644 --- a/fs/ext4/move_extent.c +++ b/fs/ext4/move_extent.c @@ -871,6 +871,7 @@ out: if (PageLocked(page)) unlock_page(page); page_cache_release(page); + ext4_journal_stop(handle); } out2: ext4_journal_stop(handle);
move_extent_par_page calls a_ops->write_begin() to increase journal handler's reference count. However, if either mext_replace_branches() or ext4_get_block fails, the increased reference count isn't decreased. This will cause later umounting of the fs forever hangs. The patch addresses the issue by calling ext4_journal_stop() if page is not NULL (which means a_ops->write_end() isn't invoked). Signed-off-by: Peng Tao <bergwolf@gmail.com> --- fs/ext4/move_extent.c | 1 + 1 files changed, 1 insertions(+), 0 deletions(-)