--On 09/12/00 15:19:04 +0200 Daniel Phillips <[EMAIL PROTECTED]> wrote:
> Chris Mason wrote:
>> [ buffer cache aliases with page cache for file tails ]
>>
>> If you unmerge inside ext2_get_block, you get passed bh_result. Just
>> change bh_result->b_blocknr to your new block, set b_dev, and set it
>> mapped, and copy the tail into bh_result. Then block_write_full_page or
>> block_commit_write are the ones that dirty bh_result for you, no alias
>> created.
>
> The fly in the ointment is that the file size may have changed by this
> time. I rely on the file size to tell me which block is the tail
> block and when the file size changes I unmerge the tail - nice simple
> idea, right? I could keep my own "blocks" field to tell me where the
> tail is, but that road descends to hell.
>
That is where tail locking comes in. If you can't deal with the tail
moving beneath you, don't let it move ;-)
The reiserfs code is far from perfect here, because we also have btree
balances to deal with. The end result is that if the tail moves during a
reiserfs_get_block, it searches for it again.
> After thinking about it last night I saw the correct approach. I need
> a new page cache primitive:
>
> struct page *getpage (struct address_space *mapping, unsigned long
> index)
>
> This is getblk, except for pages. It finds or sets up a page in a
> mapping. It puts buffers on the page if necessary but doesn't cause
> any I/O action.
>
Take a look at what you get when you call block_prepare_write with from and
to both set to 0.
> I also need another function, and I'll write it right now:
>
> struct buffer_head *page_buffer (struct page *page, int i)
> {
> struct buffer_head *bh = page->buffers;
> while (i--)
> bh = bh->b_this_page;
> return bh;
> }
>
> Getpage isn't as easy as this, but it's not that hard either. A
> gutted version of do_generic_read_page serves the purpose; the result
> is fairly pleasing to the eye (but is for my eyes only until I've
> tested it).
>
Al Viro was mentioning a generic version of these two calls last week. It
is a pretty common operation.
> Now I can unmerge this way:
>
> - Fix up various inode fields
> - getpage the tail page from the mapping
> - bread the shared tail block
> - get the appropriate page buffer using page_buffer
> - copy the tail fragment to that buffer and dirty it
>
> I can do this at a high level - the place where the unmerge conditions
> are most easily and accurately detected - as opposed to deep in the
> guts of the page I/O. The page is left in a state that already makes
> sense to read_page, write_page and friends.
>
Sorry, I don't see how this saves you from the file size changing in
file_write or truncate. While you are breading the tail, file_write might
be trying to unmerge it.
-chris
-
To unsubscribe from this list: send the line "unsubscribe linux-fsdevel" in
the body of a message to [EMAIL PROTECTED]