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 ;
}

Reply via email to