From: Vladimir Saveliev - missing long term lock unlock on read' error handling code path is added - truncate_inode_pages is now called with embedded mapping. It is needed to deal properly with block device special files. - copy_to_user might be called for more bytes than was prefaulted with fault_in_pages_writeable. That caused undesirable major page faults. - readdir bug similar to the previous one: call to filldir might lead to deadlock due to major page fault. Signed-off-by: Vladimir Saveliev Signed-off-by: Hans Reiser Signed-off-by: Andrew Morton --- fs/reiser4/plugin/file/file.c | 21 ++++++++++++++++----- fs/reiser4/plugin/file_ops_readdir.c | 3 ++- fs/reiser4/super_ops.c | 2 +- 3 files changed, 19 insertions(+), 7 deletions(-) diff -puN fs/reiser4/plugin/file/file.c~reiser4-bug-fixes fs/reiser4/plugin/file/file.c --- a/fs/reiser4/plugin/file/file.c~reiser4-bug-fixes +++ a/fs/reiser4/plugin/file/file.c @@ -783,9 +783,12 @@ int find_or_create_extent(struct page *p lock_page(page); node = jnode_of_page(page); - unlock_page(page); - if (IS_ERR(node)) + if (IS_ERR(node)) { + unlock_page(page); return PTR_ERR(node); + } + JF_SET(node, JNODE_WRITE_PREPARED); + unlock_page(page); if (node->blocknr == 0) { plugged_hole = 0; @@ -793,6 +796,7 @@ int find_or_create_extent(struct page *p (loff_t)page->index << PAGE_CACHE_SHIFT, &plugged_hole); if (result) { + JF_CLR(node, JNODE_WRITE_PREPARED); jput(node); warning("", "update_extent failed: %d", result); return result; @@ -808,6 +812,7 @@ int find_or_create_extent(struct page *p } BUG_ON(node->atom == NULL); + JF_CLR(node, JNODE_WRITE_PREPARED); jput(node); if (get_current_context()->entd) { @@ -1633,14 +1638,18 @@ static size_t read_file(hint_t * hint, s /* error happened */ break; - if (coord->between != AT_UNIT) + if (coord->between != AT_UNIT) { /* there were no items corresponding to given offset */ + done_lh(hint->ext_coord.lh); break; + } loaded = coord->node; result = zload(loaded); - if (unlikely(result)) + if (unlikely(result)) { + done_lh(hint->ext_coord.lh); break; + } if (hint->ext_coord.valid == 0) validate_extended_coord(&hint->ext_coord, @@ -1731,7 +1740,9 @@ ssize_t read_unix_file(struct file *file return RETERR(-EFAULT); } - read = read_file(hint, file, buf, left, off); + read = read_file(hint, file, buf, + left > PAGE_CACHE_SIZE ? PAGE_CACHE_SIZE : left, + off); drop_nonexclusive_access(uf_info); diff -puN fs/reiser4/plugin/file_ops_readdir.c~reiser4-bug-fixes fs/reiser4/plugin/file_ops_readdir.c --- a/fs/reiser4/plugin/file_ops_readdir.c~reiser4-bug-fixes +++ a/fs/reiser4/plugin/file_ops_readdir.c @@ -349,6 +349,7 @@ feed_entry(struct file *f, */ assert("nikita-3436", lock_stack_isclean(get_current_lock_stack())); + txn_restart_current(); result = filldir(dirent, name, (int)strlen(name), /* offset of this entry */ f->f_pos, @@ -630,7 +631,7 @@ int readdir_common(struct file *f /* dir detach_fsdata(f); /* try to update directory's atime */ - if (reiser4_grab_space(inode_file_plugin(inode)->estimate.update(inode), + if (reiser4_grab_space_force(inode_file_plugin(inode)->estimate.update(inode), BA_CAN_COMMIT) != 0) warning("", "failed to update atime on readdir: %llu", get_inode_oid(inode)); diff -puN fs/reiser4/super_ops.c~reiser4-bug-fixes fs/reiser4/super_ops.c --- a/fs/reiser4/super_ops.c~reiser4-bug-fixes +++ a/fs/reiser4/super_ops.c @@ -200,7 +200,7 @@ static void reiser4_delete_inode(struct fplug->delete_object(inode); } - truncate_inode_pages(inode->i_mapping, 0); + truncate_inode_pages(&inode->i_data, 0); inode->i_blocks = 0; clear_inode(inode); reiser4_exit_context(ctx); _