--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]

Reply via email to