Commit 303c9cf6 authored by Andrew Morton's avatar Andrew Morton Committed by Jens Axboe

[PATCH] libfs a_ops correctnes

simple_prepare_write() currently memsets the entire page.  It only
needs to clear the parts which are outside the to-be-written region.
This change makes no difference to performance - that memset was just a
cache preload for the copy_from_user() in generic_file_write().  But
it's more correct.

Also, mark the page dirty in simple_commit_write(), not in
simple_prepare_write().  Because the page's contents are changed after
prepare_write().  This doesn't matter in practice, but it is setting a
bad example.

Also, add a flush_dcache_page() to simple_prepare_write().  Again, not
really needed because the page cannot be mapped into pagetables if it
is not uptodate.  But it is example code and should not be missing such
things.
parent 3ee477f0
......@@ -260,7 +260,8 @@ int simple_rmdir(struct inode *dir, struct dentry *dentry)
return 0;
}
int simple_rename(struct inode *old_dir, struct dentry *old_dentry, struct inode *new_dir, struct dentry *new_dentry)
int simple_rename(struct inode *old_dir, struct dentry *old_dentry,
struct inode *new_dir, struct dentry *new_dentry)
{
int they_are_dirs = S_ISDIR(old_dentry->d_inode->i_mode);
......@@ -295,29 +296,30 @@ int simple_readpage(struct file *file, struct page *page)
return 0;
}
int simple_prepare_write(struct file *file, struct page *page, unsigned offset, unsigned to)
int simple_prepare_write(struct file *file, struct page *page,
unsigned from, unsigned to)
{
void *kaddr;
if (PageUptodate(page))
goto out;
kaddr = kmap_atomic(page, KM_USER0);
memset(kaddr, 0, PAGE_CACHE_SIZE);
kunmap_atomic(kaddr, KM_USER0);
SetPageUptodate(page);
out:
set_page_dirty(page);
if (!PageUptodate(page)) {
if (to - from != PAGE_CACHE_SIZE) {
void *kaddr = kmap_atomic(page, KM_USER0);
memset(kaddr, 0, from);
memset(kaddr + to, 0, PAGE_CACHE_SIZE - to);
flush_dcache_page(page);
kunmap_atomic(kaddr, KM_USER0);
}
SetPageUptodate(page);
}
return 0;
}
int simple_commit_write(struct file *file, struct page *page, unsigned offset, unsigned to)
int simple_commit_write(struct file *file, struct page *page,
unsigned offset, unsigned to)
{
struct inode *inode = page->mapping->host;
loff_t pos = ((loff_t)page->index << PAGE_CACHE_SHIFT) + to;
if (pos > inode->i_size)
inode->i_size = pos;
set_page_dirty(page);
return 0;
}
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment