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 /include/linux | |
| 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 'include/linux')
| -rw-r--r-- | include/linux/buffer_head.h | 10 | ||||
| -rw-r--r-- | include/linux/fs.h | 30 | ||||
| -rw-r--r-- | include/linux/pagemap.h | 2 |
3 files changed, 41 insertions, 1 deletions
diff --git a/include/linux/buffer_head.h b/include/linux/buffer_head.h index 35cadad84b..a562ecfb1a 100644 --- a/include/linux/buffer_head.h +++ b/include/linux/buffer_head.h | |||
| @@ -203,6 +203,16 @@ void block_invalidatepage(struct page *page, unsigned long offset); | |||
| 203 | int block_write_full_page(struct page *page, get_block_t *get_block, | 203 | int block_write_full_page(struct page *page, get_block_t *get_block, |
| 204 | struct writeback_control *wbc); | 204 | struct writeback_control *wbc); |
| 205 | int block_read_full_page(struct page*, get_block_t*); | 205 | int block_read_full_page(struct page*, get_block_t*); |
| 206 | int block_write_begin(struct file *, struct address_space *, | ||
| 207 | loff_t, unsigned, unsigned, | ||
| 208 | struct page **, void **, get_block_t*); | ||
| 209 | int block_write_end(struct file *, struct address_space *, | ||
| 210 | loff_t, unsigned, unsigned, | ||
| 211 | struct page *, void *); | ||
| 212 | int generic_write_end(struct file *, struct address_space *, | ||
| 213 | loff_t, unsigned, unsigned, | ||
| 214 | struct page *, void *); | ||
| 215 | void page_zero_new_buffers(struct page *page, unsigned from, unsigned to); | ||
| 206 | int block_prepare_write(struct page*, unsigned, unsigned, get_block_t*); | 216 | int block_prepare_write(struct page*, unsigned, unsigned, get_block_t*); |
| 207 | int cont_prepare_write(struct page*, unsigned, unsigned, get_block_t*, | 217 | int cont_prepare_write(struct page*, unsigned, unsigned, get_block_t*, |
| 208 | loff_t *); | 218 | loff_t *); |
diff --git a/include/linux/fs.h b/include/linux/fs.h index 86ce27c725..e9344e6f87 100644 --- a/include/linux/fs.h +++ b/include/linux/fs.h | |||
| @@ -394,6 +394,8 @@ enum positive_aop_returns { | |||
| 394 | AOP_TRUNCATED_PAGE = 0x80001, | 394 | AOP_TRUNCATED_PAGE = 0x80001, |
| 395 | }; | 395 | }; |
| 396 | 396 | ||
| 397 | #define AOP_FLAG_UNINTERRUPTIBLE 0x0001 /* will not do a short write */ | ||
| 398 | |||
| 397 | /* | 399 | /* |
| 398 | * oh the beauties of C type declarations. | 400 | * oh the beauties of C type declarations. |
| 399 | */ | 401 | */ |
| @@ -413,7 +415,7 @@ size_t iov_iter_copy_from_user_atomic(struct page *page, | |||
| 413 | size_t iov_iter_copy_from_user(struct page *page, | 415 | size_t iov_iter_copy_from_user(struct page *page, |
| 414 | struct iov_iter *i, unsigned long offset, size_t bytes); | 416 | struct iov_iter *i, unsigned long offset, size_t bytes); |
| 415 | void iov_iter_advance(struct iov_iter *i, size_t bytes); | 417 | void iov_iter_advance(struct iov_iter *i, size_t bytes); |
| 416 | int iov_iter_fault_in_readable(struct iov_iter *i); | 418 | int iov_iter_fault_in_readable(struct iov_iter *i, size_t bytes); |
| 417 | size_t iov_iter_single_seg_count(struct iov_iter *i); | 419 | size_t iov_iter_single_seg_count(struct iov_iter *i); |
| 418 | 420 | ||
| 419 | static inline void iov_iter_init(struct iov_iter *i, | 421 | static inline void iov_iter_init(struct iov_iter *i, |
| @@ -454,6 +456,14 @@ struct address_space_operations { | |||
| 454 | */ | 456 | */ |
| 455 | int (*prepare_write)(struct file *, struct page *, unsigned, unsigned); | 457 | int (*prepare_write)(struct file *, struct page *, unsigned, unsigned); |
| 456 | int (*commit_write)(struct file *, struct page *, unsigned, unsigned); | 458 | int (*commit_write)(struct file *, struct page *, unsigned, unsigned); |
| 459 | |||
| 460 | int (*write_begin)(struct file *, struct address_space *mapping, | ||
| 461 | loff_t pos, unsigned len, unsigned flags, | ||
| 462 | struct page **pagep, void **fsdata); | ||
| 463 | int (*write_end)(struct file *, struct address_space *mapping, | ||
| 464 | loff_t pos, unsigned len, unsigned copied, | ||
| 465 | struct page *page, void *fsdata); | ||
| 466 | |||
| 457 | /* Unfortunately this kludge is needed for FIBMAP. Don't use it */ | 467 | /* Unfortunately this kludge is needed for FIBMAP. Don't use it */ |
| 458 | sector_t (*bmap)(struct address_space *, sector_t); | 468 | sector_t (*bmap)(struct address_space *, sector_t); |
| 459 | void (*invalidatepage) (struct page *, unsigned long); | 469 | void (*invalidatepage) (struct page *, unsigned long); |
| @@ -468,6 +478,18 @@ struct address_space_operations { | |||
| 468 | int (*launder_page) (struct page *); | 478 | int (*launder_page) (struct page *); |
| 469 | }; | 479 | }; |
| 470 | 480 | ||
| 481 | /* | ||
| 482 | * pagecache_write_begin/pagecache_write_end must be used by general code | ||
| 483 | * to write into the pagecache. | ||
| 484 | */ | ||
| 485 | int pagecache_write_begin(struct file *, struct address_space *mapping, | ||
| 486 | loff_t pos, unsigned len, unsigned flags, | ||
| 487 | struct page **pagep, void **fsdata); | ||
| 488 | |||
| 489 | int pagecache_write_end(struct file *, struct address_space *mapping, | ||
| 490 | loff_t pos, unsigned len, unsigned copied, | ||
| 491 | struct page *page, void *fsdata); | ||
| 492 | |||
| 471 | struct backing_dev_info; | 493 | struct backing_dev_info; |
| 472 | struct address_space { | 494 | struct address_space { |
| 473 | struct inode *host; /* owner: inode, block_device */ | 495 | struct inode *host; /* owner: inode, block_device */ |
| @@ -1866,6 +1888,12 @@ extern int simple_prepare_write(struct file *file, struct page *page, | |||
| 1866 | unsigned offset, unsigned to); | 1888 | unsigned offset, unsigned to); |
| 1867 | extern int simple_commit_write(struct file *file, struct page *page, | 1889 | extern int simple_commit_write(struct file *file, struct page *page, |
| 1868 | unsigned offset, unsigned to); | 1890 | unsigned offset, unsigned to); |
| 1891 | extern int simple_write_begin(struct file *file, struct address_space *mapping, | ||
| 1892 | loff_t pos, unsigned len, unsigned flags, | ||
| 1893 | struct page **pagep, void **fsdata); | ||
| 1894 | extern int simple_write_end(struct file *file, struct address_space *mapping, | ||
| 1895 | loff_t pos, unsigned len, unsigned copied, | ||
| 1896 | struct page *page, void *fsdata); | ||
| 1869 | 1897 | ||
| 1870 | extern struct dentry *simple_lookup(struct inode *, struct dentry *, struct nameidata *); | 1898 | extern struct dentry *simple_lookup(struct inode *, struct dentry *, struct nameidata *); |
| 1871 | extern ssize_t generic_read_dir(struct file *, char __user *, size_t, loff_t *); | 1899 | extern ssize_t generic_read_dir(struct file *, char __user *, size_t, loff_t *); |
diff --git a/include/linux/pagemap.h b/include/linux/pagemap.h index 8f1e390fd7..db8a410ae9 100644 --- a/include/linux/pagemap.h +++ b/include/linux/pagemap.h | |||
| @@ -96,6 +96,8 @@ unsigned find_get_pages_contig(struct address_space *mapping, pgoff_t start, | |||
| 96 | unsigned find_get_pages_tag(struct address_space *mapping, pgoff_t *index, | 96 | unsigned find_get_pages_tag(struct address_space *mapping, pgoff_t *index, |
| 97 | int tag, unsigned int nr_pages, struct page **pages); | 97 | int tag, unsigned int nr_pages, struct page **pages); |
| 98 | 98 | ||
| 99 | struct page *__grab_cache_page(struct address_space *mapping, pgoff_t index); | ||
| 100 | |||
| 99 | /* | 101 | /* |
| 100 | * Returns locked page at given index in given cache, creating it if needed. | 102 | * Returns locked page at given index in given cache, creating it if needed. |
| 101 | */ | 103 | */ |
