And here is my code for converting the tail when appending a hole to the
file. It is called from reiserfs_get_block, where we have the page for the
hole locked. Since I want to convert the tail into the page cache, that
means I also need to lock the page for the tail.
I don't see anywhere in reiserfs this could be a problem, but if anyone
knows it will deadlock elsewhere, please let me know.
-chris
static int convert_tail_for_hole(struct inode *inode,
struct buffer_head *bh_result,
loff_t tail_offset) {
unsigned long index ;
unsigned long tail_end ;
unsigned long tail_start ;
struct page * tail_page ;
struct page * hole_page = bh_result->b_page ;
int retval = 0 ;
/* always try to read until the end of the block */
tail_start = tail_offset & (bh_result->b_size - 1) ;
tail_end = bh_result->b_size ;
/* our tails should always start on the block boundary. reiserfs_get_block
** sends us the offset from the key, which has been incremented by 1.
*/
if (tail_start != 1)
return -EIO ;
index = tail_offset >> PAGE_CACHE_SHIFT ;
if (index != hole_page->index) {
tail_page = grab_cache_page(inode->i_mapping, index) ;
retval = PTR_ERR(tail_page) ;
if (IS_ERR(tail_page)) {
goto out ;
}
} else {
tail_page = hole_page ;
}
/* we don't have to make sure the conversion did not happen while
** we were locking the page because anyone that could convert
** must first take i_sem
*/
retval = block_prepare_write(tail_page, tail_start, tail_end,
reiserfs_get_block) ;
if (retval)
goto unlock ;
flush_dcache_page(tail_page) ;
retval = generic_commit_write(NULL, tail_page, tail_start, tail_end) ;
unlock:
if (tail_page != hole_page) {
UnlockPage(tail_page) ;
page_cache_release(tail_page) ;
}
out:
return retval ;
}