diff options
author | Nick Piggin <npiggin@suse.de> | 2007-10-16 04:25:01 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@woody.linux-foundation.org> | 2007-10-16 12:42:55 -0400 |
commit | afddba49d18f346e5cc2938b6ed7c512db18ca68 (patch) | |
tree | 4726e3d3b0e9e8e5b5d3b2b0cccb36446bbdf3ca /fs/libfs.c | |
parent | 637aff46f94a754207c80c8c64bf1b74f24b967d (diff) |
fs: introduce write_begin, write_end, and perform_write aops
These are intended to replace prepare_write and commit_write with more
flexible alternatives that are also able to avoid the buffered write
deadlock problems efficiently (which prepare_write is unable to do).
[mark.fasheh@oracle.com: API design contributions, code review and fixes]
[akpm@linux-foundation.org: various fixes]
[dmonakhov@sw.ru: new aop block_write_begin fix]
Signed-off-by: Nick Piggin <npiggin@suse.de>
Signed-off-by: Mark Fasheh <mark.fasheh@oracle.com>
Signed-off-by: Dmitriy Monakhov <dmonakhov@openvz.org>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Diffstat (limited to 'fs/libfs.c')
-rw-r--r-- | fs/libfs.c | 44 |
1 files changed, 44 insertions, 0 deletions
diff --git a/fs/libfs.c b/fs/libfs.c index 5294de1f40c4..f2b32d3a9093 100644 --- a/fs/libfs.c +++ b/fs/libfs.c | |||
@@ -351,6 +351,26 @@ int simple_prepare_write(struct file *file, struct page *page, | |||
351 | return 0; | 351 | return 0; |
352 | } | 352 | } |
353 | 353 | ||
354 | int simple_write_begin(struct file *file, struct address_space *mapping, | ||
355 | loff_t pos, unsigned len, unsigned flags, | ||
356 | struct page **pagep, void **fsdata) | ||
357 | { | ||
358 | struct page *page; | ||
359 | pgoff_t index; | ||
360 | unsigned from; | ||
361 | |||
362 | index = pos >> PAGE_CACHE_SHIFT; | ||
363 | from = pos & (PAGE_CACHE_SIZE - 1); | ||
364 | |||
365 | page = __grab_cache_page(mapping, index); | ||
366 | if (!page) | ||
367 | return -ENOMEM; | ||
368 | |||
369 | *pagep = page; | ||
370 | |||
371 | return simple_prepare_write(file, page, from, from+len); | ||
372 | } | ||
373 | |||
354 | int simple_commit_write(struct file *file, struct page *page, | 374 | int simple_commit_write(struct file *file, struct page *page, |
355 | unsigned from, unsigned to) | 375 | unsigned from, unsigned to) |
356 | { | 376 | { |
@@ -369,6 +389,28 @@ int simple_commit_write(struct file *file, struct page *page, | |||
369 | return 0; | 389 | return 0; |
370 | } | 390 | } |
371 | 391 | ||
392 | int simple_write_end(struct file *file, struct address_space *mapping, | ||
393 | loff_t pos, unsigned len, unsigned copied, | ||
394 | struct page *page, void *fsdata) | ||
395 | { | ||
396 | unsigned from = pos & (PAGE_CACHE_SIZE - 1); | ||
397 | |||
398 | /* zero the stale part of the page if we did a short copy */ | ||
399 | if (copied < len) { | ||
400 | void *kaddr = kmap_atomic(page, KM_USER0); | ||
401 | memset(kaddr + from + copied, 0, len - copied); | ||
402 | flush_dcache_page(page); | ||
403 | kunmap_atomic(kaddr, KM_USER0); | ||
404 | } | ||
405 | |||
406 | simple_commit_write(file, page, from, from+copied); | ||
407 | |||
408 | unlock_page(page); | ||
409 | page_cache_release(page); | ||
410 | |||
411 | return copied; | ||
412 | } | ||
413 | |||
372 | /* | 414 | /* |
373 | * the inodes created here are not hashed. If you use iunique to generate | 415 | * the inodes created here are not hashed. If you use iunique to generate |
374 | * unique inode values later for this filesystem, then you must take care | 416 | * unique inode values later for this filesystem, then you must take care |
@@ -642,6 +684,8 @@ EXPORT_SYMBOL(dcache_dir_open); | |||
642 | EXPORT_SYMBOL(dcache_readdir); | 684 | EXPORT_SYMBOL(dcache_readdir); |
643 | EXPORT_SYMBOL(generic_read_dir); | 685 | EXPORT_SYMBOL(generic_read_dir); |
644 | EXPORT_SYMBOL(get_sb_pseudo); | 686 | EXPORT_SYMBOL(get_sb_pseudo); |
687 | EXPORT_SYMBOL(simple_write_begin); | ||
688 | EXPORT_SYMBOL(simple_write_end); | ||
645 | EXPORT_SYMBOL(simple_commit_write); | 689 | EXPORT_SYMBOL(simple_commit_write); |
646 | EXPORT_SYMBOL(simple_dir_inode_operations); | 690 | EXPORT_SYMBOL(simple_dir_inode_operations); |
647 | EXPORT_SYMBOL(simple_dir_operations); | 691 | EXPORT_SYMBOL(simple_dir_operations); |