Re: oops if free a locked page

Andrea Arcangeli (andrea@suse.de)
Wed, 23 Jun 1999 00:43:53 +0200 (CEST)


On Wed, 23 Jun 1999, Ingo Molnar wrote:

>yes thats a useful optimization indeed - was in my queue :). Although
>put_page(page,2) in truncate_inode_pages() is a bug if you look harder,
>the last put_page() is the 'final' one as well.

No, I don't free_page in try_to_free_buffers. Here it is my current code:

relevant part of try_to_free_buffers:

("int shared" is set if the buffer heads had the BH_Shared bitflag set)

[..]
/* And free the page */
page->buffers = NULL;
if (!shared) {
buffermem -= PAGE_SIZE;
return FREE_BUFFER_SUCCESS_LOCAL;
}
return FREE_BUFFER_SUCCESS_SHARED;
[..]

relevant part of flushpage:

[..]
if (!page->buffers)
return 1;
[..]
if (!offset)
{
int ret;
ret = try_to_free_buffers(page);
if (!(ret & (FREE_BUFFER_SUCCESS_SHARED|FREE_BUFFER_BUSY)))
goto weird;
unlock_kernel();
return ret == FREE_BUFFER_SUCCESS_SHARED;
weird:
printk(KERN_DEBUG "flushpage: free_buffers retval %d\n", ret);
}
[..]

relevant part of truncate_inode_pages:

int additional_refcount;
get_page(page);
spin_unlock(&pagecache_lock);

lock_page(page);

additional_refcount = 1;
if (inode->i_op->flushpage)
if (inode->i_op->flushpage(inode, page, 0))
{
additional_refcount = 2;
lru_pages_del(page);
}

/*
* We remove the page from the page cache
* _after_ we have destroyed all buffer-cache
* references to it. Otherwise some other process
* might think this inode page is not in the
* page cache and creates a buffer-cache alias
* to it causing all sorts of fun problems ...
*/
remove_inode_page(page);

UnlockPage(page);
put_page_refcount(additional_refcount, page);

page_cache_release(page);

Andrea Arcangeli

-
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@vger.rutgers.edu
Please read the FAQ at http://www.tux.org/lkml/