From: Nick Piggin Implement new aops for some of the simpler filesystems. Signed-off-by: Nick Piggin Signed-off-by: Andrew Morton --- fs/configfs/inode.c | 4 ++-- fs/hugetlbfs/inode.c | 16 ++++++++++------ fs/ramfs/file-mmu.c | 4 ++-- fs/ramfs/file-nommu.c | 4 ++-- fs/sysfs/inode.c | 4 ++-- mm/shmem.c | 35 ++++++++++++++++++++++++++++------- 6 files changed, 46 insertions(+), 21 deletions(-) diff -puN fs/configfs/inode.c~implement-simple-fs-aops fs/configfs/inode.c --- a/fs/configfs/inode.c~implement-simple-fs-aops +++ a/fs/configfs/inode.c @@ -41,8 +41,8 @@ extern struct super_block * configfs_sb; static const struct address_space_operations configfs_aops = { .readpage = simple_readpage, - .prepare_write = simple_prepare_write, - .commit_write = simple_commit_write + .write_begin = simple_write_begin, + .write_end = simple_write_end, }; static struct backing_dev_info configfs_backing_dev_info = { diff -puN fs/hugetlbfs/inode.c~implement-simple-fs-aops fs/hugetlbfs/inode.c --- a/fs/hugetlbfs/inode.c~implement-simple-fs-aops +++ a/fs/hugetlbfs/inode.c @@ -166,15 +166,19 @@ static int hugetlbfs_readpage(struct fil return -EINVAL; } -static int hugetlbfs_prepare_write(struct file *file, - struct page *page, unsigned offset, unsigned to) +static int hugetlbfs_write_begin(struct file *file, + struct address_space *mapping, + loff_t pos, unsigned len, unsigned flags, + struct page **pagep, void **fsdata) { return -EINVAL; } -static int hugetlbfs_commit_write(struct file *file, - struct page *page, unsigned offset, unsigned to) +static int hugetlbfs_write_end(struct file *file, struct address_space *mapping, + loff_t pos, unsigned len, unsigned copied, + struct page *page, void *fsdata) { + BUG(); return -EINVAL; } @@ -546,8 +550,8 @@ static void hugetlbfs_destroy_inode(stru static const struct address_space_operations hugetlbfs_aops = { .readpage = hugetlbfs_readpage, - .prepare_write = hugetlbfs_prepare_write, - .commit_write = hugetlbfs_commit_write, + .write_begin = hugetlbfs_write_begin, + .write_end = hugetlbfs_write_end, .set_page_dirty = hugetlbfs_set_page_dirty, }; diff -puN fs/ramfs/file-mmu.c~implement-simple-fs-aops fs/ramfs/file-mmu.c --- a/fs/ramfs/file-mmu.c~implement-simple-fs-aops +++ a/fs/ramfs/file-mmu.c @@ -29,8 +29,8 @@ const struct address_space_operations ramfs_aops = { .readpage = simple_readpage, - .prepare_write = simple_prepare_write, - .commit_write = simple_commit_write, + .write_begin = simple_write_begin, + .write_end = simple_write_end, .set_page_dirty = __set_page_dirty_no_writeback, }; diff -puN fs/ramfs/file-nommu.c~implement-simple-fs-aops fs/ramfs/file-nommu.c --- a/fs/ramfs/file-nommu.c~implement-simple-fs-aops +++ a/fs/ramfs/file-nommu.c @@ -29,8 +29,8 @@ static int ramfs_nommu_setattr(struct de const struct address_space_operations ramfs_aops = { .readpage = simple_readpage, - .prepare_write = simple_prepare_write, - .commit_write = simple_commit_write, + .write_begin = simple_write_begin, + .write_end = simple_write_end, .set_page_dirty = __set_page_dirty_no_writeback, }; diff -puN fs/sysfs/inode.c~implement-simple-fs-aops fs/sysfs/inode.c --- a/fs/sysfs/inode.c~implement-simple-fs-aops +++ a/fs/sysfs/inode.c @@ -21,8 +21,8 @@ extern struct super_block * sysfs_sb; static const struct address_space_operations sysfs_aops = { .readpage = simple_readpage, - .prepare_write = simple_prepare_write, - .commit_write = simple_commit_write + .write_begin = simple_write_begin, + .write_end = simple_write_end, }; static struct backing_dev_info sysfs_backing_dev_info = { diff -puN mm/shmem.c~implement-simple-fs-aops mm/shmem.c --- a/mm/shmem.c~implement-simple-fs-aops +++ a/mm/shmem.c @@ -1105,7 +1105,7 @@ static int shmem_getpage(struct inode *i * Normally, filepage is NULL on entry, and either found * uptodate immediately, or allocated and zeroed, or read * in under swappage, which is then assigned to filepage. - * But shmem_prepare_write passes in a locked filepage, + * But shmem_write_begin passes in a locked filepage, * which may be found not uptodate by other callers too, * and may need to be copied from the swappage read in. */ @@ -1450,14 +1450,35 @@ static const struct inode_operations shm static const struct inode_operations shmem_symlink_inline_operations; /* - * Normally tmpfs makes no use of shmem_prepare_write, but it + * Normally tmpfs makes no use of shmem_write_begin, but it * lets a tmpfs file be used read-write below the loop driver. */ static int -shmem_prepare_write(struct file *file, struct page *page, unsigned offset, unsigned to) +shmem_write_begin(struct file *file, struct address_space *mapping, + loff_t pos, unsigned len, unsigned flags, + struct page **pagep, void **fsdata) +{ + struct inode *inode = mapping->host; + pgoff_t index = pos >> PAGE_CACHE_SHIFT; + *pagep = NULL; + return shmem_getpage(inode, index, pagep, SGP_WRITE, NULL); +} + +static int +shmem_write_end(struct file *file, struct address_space *mapping, + loff_t pos, unsigned len, unsigned copied, + struct page *page, void *fsdata) { - struct inode *inode = page->mapping->host; - return shmem_getpage(inode, page->index, &page, SGP_WRITE, NULL); + struct inode *inode = mapping->host; + + set_page_dirty(page); + mark_page_accessed(page); + page_cache_release(page); + + if (pos+copied > inode->i_size) + i_size_write(inode, pos+copied); + + return copied; } static ssize_t @@ -2351,8 +2372,8 @@ static const struct address_space_operat .writepage = shmem_writepage, .set_page_dirty = __set_page_dirty_no_writeback, #ifdef CONFIG_TMPFS - .prepare_write = shmem_prepare_write, - .commit_write = simple_commit_write, + .write_begin = shmem_write_begin, + .write_end = shmem_write_end, #endif .migratepage = migrate_page, }; _