Re: fragmentation && blocks "realloc"

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



On Fri, 20 Jan 2006, Jan Koss wrote:
> In fact, I expected yes for the first abbility and no for the second :)
> 
> Now code looks like:
> bh = sb_bread(sb, oldblock);
> if (!bh)
>   goto err;
> bh->b_blocknr = newblk;				
> mark_buffer_dirty (bh);
> unmap_underlying_metadata(bh->b_bdev, bh->b_blocknr);

No, no, no!!!  You cannot do this.  You are not using the page cache for 
your file system (why not?) so you cannot remap buffers like I suggested.

Even if you could your code is wrong.  You need the 
unmap_underlying_metadata() _before_ mark_buffer_dirty().

> Let's suppose such test case:
> after situation, which I described in the first email,
> user resize file and new size 5 blocks,
> and there are no free blocks except 2 blocks which we deallocated in
> the frist email,
> so we have to allocate them.
> 
> When I reproduced this test case, I got such messages from kernel:
> __find_get_block_slow failed block=oldblock...
> 
> So as I can see I missed something in "art of changing b_blocknr".
> 
> Error in __find_get_block_slow may happen only if all buffers on page mapped.
> 
> May be this is because of buffer_head change b_blocknr, but didn't
> change b_this_page?

You cannot touch b_this_page on buffers you access via sb_bread().  The 
correct solution for a file system like yours would be to copy the buffer 
data to the correct buffer and write that and release the old one.  I.e. 
your first suggestion, i.e. do not touch b_blocknr or b_this_page.  And 
you do not need to call unmap_underlying_metadata() either or invalidate 
any pages.

You are working with the block device directly.  Bypassing the per file 
page cache thus you cannot do anything to the buffers at all other than 
read/write them.

It would be far better if you start using the page cache (via ->readpage, 
->writepage, and probably ->prepare_write and ->commit_write as well) and 
then from inside readpage/writepage/prepare_write/commit_write you can do 
with the buffers as I suggested...

Best regards,

	Anton
-- 
Anton Altaparmakov <aia21 at cam.ac.uk> (replace at with @)
Unix Support, Computing Service, University of Cambridge, CB2 3QH, UK
Linux NTFS maintainer / IRC: #ntfs on irc.freenode.net
WWW: http://linux-ntfs.sf.net/ & http://www-stu.christs.cam.ac.uk/~aia21/

--
Kernelnewbies: Help each other learn about the Linux kernel.
Archive:       http://mail.nl.linux.org/kernelnewbies/
FAQ:           http://kernelnewbies.org/faq/


[Index of Archives]     [Newbies FAQ]     [Linux Kernel Mentors]     [Linux Kernel Development]     [IETF Annouce]     [Git]     [Networking]     [Security]     [Bugtraq]     [Yosemite]     [MIPS Linux]     [ARM Linux]     [Linux RAID]     [Linux SCSI]     [Linux ACPI]
  Powered by Linux