From: Edward Shishkin . Fix bugs introduced by Zam's reiser4-use-generic-file-read.patch: 1) jnode leak in a case when a file is built of tails: filemap_nopage->page_cache_readahead->reiser4_readpages-> ->readpages_unix_file->uf_readpages_filler->jnode_of_page, then jput() does not evict the jnode. 2) passing invalid address to jput() in the case of returned error. Signed-off-by: Edward Shishkin Cc: Alexander Zarochentsev Signed-off-by: Andrew Morton --- fs/reiser4/plugin/file/file.c | 50 ++++++++++++++++---------------- 1 file changed, 26 insertions(+), 24 deletions(-) diff -puN fs/reiser4/plugin/file/file.c~reiser4-use-generic-file-read-fix-readpages-unix-file fs/reiser4/plugin/file/file.c --- a/fs/reiser4/plugin/file/file.c~reiser4-use-generic-file-read-fix-readpages-unix-file +++ a/fs/reiser4/plugin/file/file.c @@ -1589,7 +1589,7 @@ struct uf_readpages_context { }; /* A callback function for readpages_unix_file/read_cache_pages. - * It assumes that the file is build of extents. + * If the file is build of tails, then return error (-ENOENT). * * @data -- a pointer to reiser4_readpages_context object, * to save the twig lock and the coord between @@ -1610,11 +1610,6 @@ static int uf_readpages_filler(void * da unlock_page(page); return 0; } - node = jnode_of_page(page); - if (unlikely(IS_ERR(node))) { - ret = PTR_ERR(node); - goto err; - } if (rc->lh.node == 0) { /* no twig lock - have to do tree search. */ reiser4_key key; @@ -1627,43 +1622,50 @@ static int uf_readpages_filler(void * da &key, &rc->coord, &rc->lh, ZNODE_READ_LOCK, FIND_EXACT, TWIG_LEVEL, TWIG_LEVEL, CBK_UNIQUE, NULL); + if (ret) + return ret; lock_page(page); cbk_done = 1; - if (ret != 0) - goto err; } ret = zload(rc->coord.node); - if (ret) - goto err; + if (ret) { + unlock_page(page); + return ret; + } if (!coord_is_existing_item(&rc->coord) || !item_is_extent(&rc->coord)) { zrelse(rc->coord.node); - ret = RETERR(-EIO); - goto err; + unlock_page(page); + return RETERR(-EIO); } ext = extent_by_coord(&rc->coord); ext_index = extent_unit_index(&rc->coord); - if (page->index < ext_index || page->index >= ext_index + extent_get_width(ext)) - { - /* the page index doesn't belong to the extent unit which the coord points to, - * -- release the lock and repeat with tree search. */ + if (page->index < ext_index || + page->index >= ext_index + extent_get_width(ext)) { + /* the page index doesn't belong to the extent unit + which the coord points to - release the lock and + repeat with tree search. */ zrelse(rc->coord.node); done_lh(&rc->lh); - /* we can be here after a CBK call only in case of corruption of the tree - * or the tree lookup algorithm bug. */ + /* we can be here after a CBK call only in case of + corruption of the tree or the tree lookup algorithm bug. */ if (unlikely(cbk_done)) { - ret = RETERR(-EIO); - goto err; + unlock_page(page); + return RETERR(-EIO); } goto repeat; } - ret = reiser4_do_readpage_extent(ext, page->index - ext_index, page); - zrelse(rc->coord.node); - if (ret) { -err: + node = jnode_of_page(page); + if (unlikely(IS_ERR(node))) { + zrelse(rc->coord.node); unlock_page(page); + return PTR_ERR(node); } + ret = reiser4_do_readpage_extent(ext, page->index - ext_index, page); jput(node); + zrelse(rc->coord.node); + if (ret) + unlock_page(page); return ret; } _