Loading fs/affs/file.c +59 −42 Original line number Diff line number Diff line Loading @@ -395,25 +395,33 @@ static int affs_writepage(struct page *page, struct writeback_control *wbc) { return block_write_full_page(page, affs_get_block, wbc); } static int affs_readpage(struct file *file, struct page *page) { return block_read_full_page(page, affs_get_block); } static int affs_prepare_write(struct file *file, struct page *page, unsigned from, unsigned to) static int affs_write_begin(struct file *file, struct address_space *mapping, loff_t pos, unsigned len, unsigned flags, struct page **pagep, void **fsdata) { return cont_prepare_write(page, from, to, affs_get_block, &AFFS_I(page->mapping->host)->mmu_private); *pagep = NULL; return cont_write_begin(file, mapping, pos, len, flags, pagep, fsdata, affs_get_block, &AFFS_I(mapping->host)->mmu_private); } static sector_t _affs_bmap(struct address_space *mapping, sector_t block) { return generic_block_bmap(mapping,block,affs_get_block); } const struct address_space_operations affs_aops = { .readpage = affs_readpage, .writepage = affs_writepage, .sync_page = block_sync_page, .prepare_write = affs_prepare_write, .commit_write = generic_commit_write, .write_begin = affs_write_begin, .write_end = generic_write_end, .bmap = _affs_bmap }; Loading Loading @@ -603,54 +611,65 @@ affs_readpage_ofs(struct file *file, struct page *page) return err; } static int affs_prepare_write_ofs(struct file *file, struct page *page, unsigned from, unsigned to) static int affs_write_begin_ofs(struct file *file, struct address_space *mapping, loff_t pos, unsigned len, unsigned flags, struct page **pagep, void **fsdata) { struct inode *inode = page->mapping->host; u32 size, offset; u32 tmp; struct inode *inode = mapping->host; struct page *page; pgoff_t index; int err = 0; pr_debug("AFFS: prepare_write(%u, %ld, %d, %d)\n", (u32)inode->i_ino, page->index, from, to); offset = page->index << PAGE_CACHE_SHIFT; if (offset + from > AFFS_I(inode)->mmu_private) { err = affs_extent_file_ofs(inode, offset + from); pr_debug("AFFS: write_begin(%u, %llu, %llu)\n", (u32)inode->i_ino, (unsigned long long)pos, (unsigned long long)pos + len); if (pos > AFFS_I(inode)->mmu_private) { /* XXX: this probably leaves a too-big i_size in case of * failure. Should really be updating i_size at write_end time */ err = affs_extent_file_ofs(inode, pos); if (err) return err; } size = inode->i_size; index = pos >> PAGE_CACHE_SHIFT; page = __grab_cache_page(mapping, index); if (!page) return -ENOMEM; *pagep = page; if (PageUptodate(page)) return 0; if (from) { err = affs_do_readpage_ofs(file, page, 0, from); if (err) return err; } if (to < PAGE_CACHE_SIZE) { zero_user_page(page, to, PAGE_CACHE_SIZE - to, KM_USER0); if (size > offset + to) { if (size < offset + PAGE_CACHE_SIZE) tmp = size & ~PAGE_CACHE_MASK; else tmp = PAGE_CACHE_SIZE; err = affs_do_readpage_ofs(file, page, to, tmp); } /* XXX: inefficient but safe in the face of short writes */ err = affs_do_readpage_ofs(file, page, 0, PAGE_CACHE_SIZE); if (err) { unlock_page(page); page_cache_release(page); } return err; } static int affs_commit_write_ofs(struct file *file, struct page *page, unsigned from, unsigned to) static int affs_write_end_ofs(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; struct inode *inode = mapping->host; struct super_block *sb = inode->i_sb; struct buffer_head *bh, *prev_bh; char *data; u32 bidx, boff, bsize; unsigned from, to; u32 tmp; int written; pr_debug("AFFS: commit_write(%u, %ld, %d, %d)\n", (u32)inode->i_ino, page->index, from, to); from = pos & (PAGE_CACHE_SIZE - 1); to = pos + len; /* * XXX: not sure if this can handle short copies (len < copied), but * we don't have to, because the page should always be uptodate here, * due to write_begin. */ pr_debug("AFFS: write_begin(%u, %llu, %llu)\n", (u32)inode->i_ino, (unsigned long long)pos, (unsigned long long)pos + len); bsize = AFFS_SB(sb)->s_data_blksize; data = page_address(page); Loading Loading @@ -748,6 +767,9 @@ done: if (tmp > inode->i_size) inode->i_size = AFFS_I(inode)->mmu_private = tmp; unlock_page(page); page_cache_release(page); return written; out: Loading @@ -761,8 +783,8 @@ const struct address_space_operations affs_aops_ofs = { .readpage = affs_readpage_ofs, //.writepage = affs_writepage_ofs, //.sync_page = affs_sync_page_ofs, .prepare_write = affs_prepare_write_ofs, .commit_write = affs_commit_write_ofs .write_begin = affs_write_begin_ofs, .write_end = affs_write_end_ofs }; /* Free any preallocated blocks. */ Loading Loading @@ -805,18 +827,13 @@ affs_truncate(struct inode *inode) if (inode->i_size > AFFS_I(inode)->mmu_private) { struct address_space *mapping = inode->i_mapping; struct page *page; u32 size = inode->i_size - 1; void *fsdata; u32 size = inode->i_size; int res; page = grab_cache_page(mapping, size >> PAGE_CACHE_SHIFT); if (!page) return; size = (size & (PAGE_CACHE_SIZE - 1)) + 1; res = mapping->a_ops->prepare_write(NULL, page, size, size); res = mapping->a_ops->write_begin(NULL, mapping, size, 0, 0, &page, &fsdata); if (!res) res = mapping->a_ops->commit_write(NULL, page, size, size); unlock_page(page); page_cache_release(page); res = mapping->a_ops->write_end(NULL, mapping, size, 0, 0, page, fsdata); mark_inode_dirty(inode); return; } else if (inode->i_size == AFFS_I(inode)->mmu_private) Loading Loading
fs/affs/file.c +59 −42 Original line number Diff line number Diff line Loading @@ -395,25 +395,33 @@ static int affs_writepage(struct page *page, struct writeback_control *wbc) { return block_write_full_page(page, affs_get_block, wbc); } static int affs_readpage(struct file *file, struct page *page) { return block_read_full_page(page, affs_get_block); } static int affs_prepare_write(struct file *file, struct page *page, unsigned from, unsigned to) static int affs_write_begin(struct file *file, struct address_space *mapping, loff_t pos, unsigned len, unsigned flags, struct page **pagep, void **fsdata) { return cont_prepare_write(page, from, to, affs_get_block, &AFFS_I(page->mapping->host)->mmu_private); *pagep = NULL; return cont_write_begin(file, mapping, pos, len, flags, pagep, fsdata, affs_get_block, &AFFS_I(mapping->host)->mmu_private); } static sector_t _affs_bmap(struct address_space *mapping, sector_t block) { return generic_block_bmap(mapping,block,affs_get_block); } const struct address_space_operations affs_aops = { .readpage = affs_readpage, .writepage = affs_writepage, .sync_page = block_sync_page, .prepare_write = affs_prepare_write, .commit_write = generic_commit_write, .write_begin = affs_write_begin, .write_end = generic_write_end, .bmap = _affs_bmap }; Loading Loading @@ -603,54 +611,65 @@ affs_readpage_ofs(struct file *file, struct page *page) return err; } static int affs_prepare_write_ofs(struct file *file, struct page *page, unsigned from, unsigned to) static int affs_write_begin_ofs(struct file *file, struct address_space *mapping, loff_t pos, unsigned len, unsigned flags, struct page **pagep, void **fsdata) { struct inode *inode = page->mapping->host; u32 size, offset; u32 tmp; struct inode *inode = mapping->host; struct page *page; pgoff_t index; int err = 0; pr_debug("AFFS: prepare_write(%u, %ld, %d, %d)\n", (u32)inode->i_ino, page->index, from, to); offset = page->index << PAGE_CACHE_SHIFT; if (offset + from > AFFS_I(inode)->mmu_private) { err = affs_extent_file_ofs(inode, offset + from); pr_debug("AFFS: write_begin(%u, %llu, %llu)\n", (u32)inode->i_ino, (unsigned long long)pos, (unsigned long long)pos + len); if (pos > AFFS_I(inode)->mmu_private) { /* XXX: this probably leaves a too-big i_size in case of * failure. Should really be updating i_size at write_end time */ err = affs_extent_file_ofs(inode, pos); if (err) return err; } size = inode->i_size; index = pos >> PAGE_CACHE_SHIFT; page = __grab_cache_page(mapping, index); if (!page) return -ENOMEM; *pagep = page; if (PageUptodate(page)) return 0; if (from) { err = affs_do_readpage_ofs(file, page, 0, from); if (err) return err; } if (to < PAGE_CACHE_SIZE) { zero_user_page(page, to, PAGE_CACHE_SIZE - to, KM_USER0); if (size > offset + to) { if (size < offset + PAGE_CACHE_SIZE) tmp = size & ~PAGE_CACHE_MASK; else tmp = PAGE_CACHE_SIZE; err = affs_do_readpage_ofs(file, page, to, tmp); } /* XXX: inefficient but safe in the face of short writes */ err = affs_do_readpage_ofs(file, page, 0, PAGE_CACHE_SIZE); if (err) { unlock_page(page); page_cache_release(page); } return err; } static int affs_commit_write_ofs(struct file *file, struct page *page, unsigned from, unsigned to) static int affs_write_end_ofs(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; struct inode *inode = mapping->host; struct super_block *sb = inode->i_sb; struct buffer_head *bh, *prev_bh; char *data; u32 bidx, boff, bsize; unsigned from, to; u32 tmp; int written; pr_debug("AFFS: commit_write(%u, %ld, %d, %d)\n", (u32)inode->i_ino, page->index, from, to); from = pos & (PAGE_CACHE_SIZE - 1); to = pos + len; /* * XXX: not sure if this can handle short copies (len < copied), but * we don't have to, because the page should always be uptodate here, * due to write_begin. */ pr_debug("AFFS: write_begin(%u, %llu, %llu)\n", (u32)inode->i_ino, (unsigned long long)pos, (unsigned long long)pos + len); bsize = AFFS_SB(sb)->s_data_blksize; data = page_address(page); Loading Loading @@ -748,6 +767,9 @@ done: if (tmp > inode->i_size) inode->i_size = AFFS_I(inode)->mmu_private = tmp; unlock_page(page); page_cache_release(page); return written; out: Loading @@ -761,8 +783,8 @@ const struct address_space_operations affs_aops_ofs = { .readpage = affs_readpage_ofs, //.writepage = affs_writepage_ofs, //.sync_page = affs_sync_page_ofs, .prepare_write = affs_prepare_write_ofs, .commit_write = affs_commit_write_ofs .write_begin = affs_write_begin_ofs, .write_end = affs_write_end_ofs }; /* Free any preallocated blocks. */ Loading Loading @@ -805,18 +827,13 @@ affs_truncate(struct inode *inode) if (inode->i_size > AFFS_I(inode)->mmu_private) { struct address_space *mapping = inode->i_mapping; struct page *page; u32 size = inode->i_size - 1; void *fsdata; u32 size = inode->i_size; int res; page = grab_cache_page(mapping, size >> PAGE_CACHE_SHIFT); if (!page) return; size = (size & (PAGE_CACHE_SIZE - 1)) + 1; res = mapping->a_ops->prepare_write(NULL, page, size, size); res = mapping->a_ops->write_begin(NULL, mapping, size, 0, 0, &page, &fsdata); if (!res) res = mapping->a_ops->commit_write(NULL, page, size, size); unlock_page(page); page_cache_release(page); res = mapping->a_ops->write_end(NULL, mapping, size, 0, 0, page, fsdata); mark_inode_dirty(inode); return; } else if (inode->i_size == AFFS_I(inode)->mmu_private) Loading