diff options
Diffstat (limited to 'fs/hpfs/file.c')
-rw-r--r-- | fs/hpfs/file.c | 44 |
1 files changed, 38 insertions, 6 deletions
diff --git a/fs/hpfs/file.c b/fs/hpfs/file.c index 3027f4dbbab..4e9dabcf1f4 100644 --- a/fs/hpfs/file.c +++ b/fs/hpfs/file.c @@ -7,6 +7,7 @@ */ #include "hpfs_fn.h" +#include <linux/mpage.h> #define BLOCKS(size) (((size) + 511) >> 9) @@ -34,7 +35,7 @@ int hpfs_file_fsync(struct file *file, loff_t start, loff_t end, int datasync) * so we must ignore such errors. */ -static secno hpfs_bmap(struct inode *inode, unsigned file_secno) +static secno hpfs_bmap(struct inode *inode, unsigned file_secno, unsigned *n_secs) { struct hpfs_inode_info *hpfs_inode = hpfs_i(inode); unsigned n, disk_secno; @@ -42,11 +43,20 @@ static secno hpfs_bmap(struct inode *inode, unsigned file_secno) struct buffer_head *bh; if (BLOCKS(hpfs_i(inode)->mmu_private) <= file_secno) return 0; n = file_secno - hpfs_inode->i_file_sec; - if (n < hpfs_inode->i_n_secs) return hpfs_inode->i_disk_sec + n; + if (n < hpfs_inode->i_n_secs) { + *n_secs = hpfs_inode->i_n_secs - n; + return hpfs_inode->i_disk_sec + n; + } if (!(fnode = hpfs_map_fnode(inode->i_sb, inode->i_ino, &bh))) return 0; disk_secno = hpfs_bplus_lookup(inode->i_sb, inode, &fnode->btree, file_secno, bh); if (disk_secno == -1) return 0; if (hpfs_chk_sectors(inode->i_sb, disk_secno, 1, "bmap")) return 0; + n = file_secno - hpfs_inode->i_file_sec; + if (n < hpfs_inode->i_n_secs) { + *n_secs = hpfs_inode->i_n_secs - n; + return hpfs_inode->i_disk_sec + n; + } + *n_secs = 1; return disk_secno; } @@ -67,10 +77,14 @@ static int hpfs_get_block(struct inode *inode, sector_t iblock, struct buffer_he { int r; secno s; + unsigned n_secs; hpfs_lock(inode->i_sb); - s = hpfs_bmap(inode, iblock); + s = hpfs_bmap(inode, iblock, &n_secs); if (s) { + if (bh_result->b_size >> 9 < n_secs) + n_secs = bh_result->b_size >> 9; map_bh(bh_result, inode->i_sb, s); + bh_result->b_size = n_secs << 9; goto ret_0; } if (!create) goto ret_0; @@ -95,24 +109,40 @@ static int hpfs_get_block(struct inode *inode, sector_t iblock, struct buffer_he return r; } +static int hpfs_readpage(struct file *file, struct page *page) +{ + return mpage_readpage(page, hpfs_get_block); +} + static int hpfs_writepage(struct page *page, struct writeback_control *wbc) { - return block_write_full_page(page,hpfs_get_block, wbc); + return block_write_full_page(page, hpfs_get_block, wbc); } -static int hpfs_readpage(struct file *file, struct page *page) +static int hpfs_readpages(struct file *file, struct address_space *mapping, + struct list_head *pages, unsigned nr_pages) { - return block_read_full_page(page,hpfs_get_block); + return mpage_readpages(mapping, pages, nr_pages, hpfs_get_block); +} + +static int hpfs_writepages(struct address_space *mapping, + struct writeback_control *wbc) +{ + return mpage_writepages(mapping, wbc, hpfs_get_block); } static void hpfs_write_failed(struct address_space *mapping, loff_t to) { struct inode *inode = mapping->host; + hpfs_lock(inode->i_sb); + if (to > inode->i_size) { truncate_pagecache(inode, to, inode->i_size); hpfs_truncate(inode); } + + hpfs_unlock(inode->i_sb); } static int hpfs_write_begin(struct file *file, struct address_space *mapping, @@ -157,6 +187,8 @@ static sector_t _hpfs_bmap(struct address_space *mapping, sector_t block) const struct address_space_operations hpfs_aops = { .readpage = hpfs_readpage, .writepage = hpfs_writepage, + .readpages = hpfs_readpages, + .writepages = hpfs_writepages, .write_begin = hpfs_write_begin, .write_end = hpfs_write_end, .bmap = _hpfs_bmap |