Re: [RFC][PATCH 2/3] Move the file data to the new blocks
From: Andrew Morton <akpm@linux-foundation.org>
Date: 2007-02-08 09:46:10
Also in:
linux-fsdevel
On Thu, 8 Feb 2007 10:29:45 +0100 Jan Kara [off-list ref] wrote:
On Wed 07-02-07 12:56:59, Andrew Morton wrote:quoted
On Wed, 7 Feb 2007 13:46:57 -0700 Andreas Dilger [off-list ref] wrote:quoted
On Feb 06, 2007 17:35 -0800, Andrew Morton wrote:quoted
On Mon, 5 Feb 2007 14:12:04 +0100 Jan Kara [off-list ref] wrote:quoted
quoted
Move the blocks on the temporary inode to the original inode by a page. 1. Read the file data from the old blocks to the page 2. Move the block on the temporary inode to the original inode 3. Write the file data on the page into the new blocksI have one thing - it's probably not good to use page cache for defragmentation.Then it is no longer online defragmentation. The issues with maintaining correctness and coherency with ongoing VFS activity would be truly ghastly. If we're worried about pagecache pollution then it would be better to control that from userspace via fadvise().It should be possible to have the online defrag tool lock the inode against any changes,Sounds easy when you say it fast. But how do we "lock" against, say, a read pagefault? Only by writing back then removing the pagecache page then reinstantiating it as a locked, not-uptodate page and then removing it from pagecache afterwards prior to unlocking it. Or something. I don't think we want to go there.I though Andreas meant "any write changes" - i.e. you check that noone has open file descriptor for writing and block any new open for writing. That can be done quite easily. Anyway, I agree with you that userspace solution to a possible page cache pollution is preferable after thinking about it for a while. As I've been thinking about it, we could actually do the copying from user space. We could do something like: block any writes to file (as I described above) craft new inode with blocks allocated as we want (using preallocation, we should mostly have the kernel infrastructure we need) copy data using splice syscall call the kernel to switch data
I don't think we need to block any writes to any file or anything.
To move a page within a file:
fd = open(file);
p = mmap(fd);
the_page_was_in_core = mincore(p, offset);
munmap(p);
ioctl(fd, ..., new_block);
<kernel>
read_cache_page(inode, offset);
lock_page(page);
if (try_to_free_buffers(page)) {
<relocate the page>
set_page_dirty(page);
}
unlock_page(page);
if (the_page_was_in_core) {
sync_file_range(fd, offset SYNC_FILE_RANGE_WAIT_BEFORE|
SYNC_FILE_RANGE_WRITE|
SYNC_FILE_RANGE_WAIT_AFTER);
fadvise(fd, offset, FADV_DONTNEED);
}
completely coherent with pagecache, quite safe in the presence of mmap,
mlock, O_DIRECT, everything else. Also fully journallable in-kernel.