diff options
| author | Andrew Morton <akpm@digeo.com> | 2002-10-28 16:22:07 -0800 |
|---|---|---|
| committer | Jens Axboe <axboe@suse.de> | 2002-10-28 16:22:07 -0800 |
| commit | 303c9cf648d3e5f648afe89d624cc3e3c8d5ce71 (patch) | |
| tree | 2f83577b40e2a0abd54853934481b0f0a19c2fec | |
| parent | 3ee477f0d419d10cdd72ac9b7d7e9e7cc95e99f0 (diff) | |
[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.
| -rw-r--r-- | fs/libfs.c | 32 |
1 files changed, 17 insertions, 15 deletions
diff --git a/fs/libfs.c b/fs/libfs.c index 98c1968b7155..ea1ec8d09310 100644 --- a/fs/libfs.c +++ b/fs/libfs.c @@ -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 @@ out: 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; } |
