diff options
Diffstat (limited to 'fs/jfs/inode.c')
| -rw-r--r-- | fs/jfs/inode.c | 87 |
1 files changed, 63 insertions, 24 deletions
diff --git a/fs/jfs/inode.c b/fs/jfs/inode.c index b2ae190a77b..bd3df1ca3c9 100644 --- a/fs/jfs/inode.c +++ b/fs/jfs/inode.c @@ -22,6 +22,8 @@ #include <linux/buffer_head.h> #include <linux/pagemap.h> #include <linux/quotaops.h> +#include <linux/writeback.h> +#include <linux/aio.h> #include "jfs_incore.h" #include "jfs_inode.h" #include "jfs_filsys.h" @@ -60,7 +62,7 @@ struct inode *jfs_iget(struct super_block *sb, unsigned long ino) inode->i_op = &page_symlink_inode_operations; inode->i_mapping->a_ops = &jfs_aops; } else { - inode->i_op = &jfs_symlink_inode_operations; + inode->i_op = &jfs_fast_symlink_inode_operations; /* * The inline data should be null-terminated, but * don't let on-disk corruption crash the kernel @@ -120,9 +122,11 @@ int jfs_commit_inode(struct inode *inode, int wait) return rc; } -int jfs_write_inode(struct inode *inode, int wait) +int jfs_write_inode(struct inode *inode, struct writeback_control *wbc) { - if (test_cflag(COMMIT_Nolink, inode)) + int wait = wbc->sync_mode == WB_SYNC_ALL; + + if (inode->i_nlink == 0) return 0; /* * If COMMIT_DIRTY is not set, the inode isn't really dirty. @@ -142,31 +146,35 @@ int jfs_write_inode(struct inode *inode, int wait) return 0; } -void jfs_delete_inode(struct inode *inode) +void jfs_evict_inode(struct inode *inode) { - jfs_info("In jfs_delete_inode, inode = 0x%p", inode); + jfs_info("In jfs_evict_inode, inode = 0x%p", inode); - if (!is_bad_inode(inode) && - (JFS_IP(inode)->fileset == FILESYSTEM_I)) { - truncate_inode_pages(&inode->i_data, 0); + if (!inode->i_nlink && !is_bad_inode(inode)) { + dquot_initialize(inode); - if (test_cflag(COMMIT_Freewmap, inode)) - jfs_free_zero_link(inode); + if (JFS_IP(inode)->fileset == FILESYSTEM_I) { + truncate_inode_pages_final(&inode->i_data); - diFree(inode); + if (test_cflag(COMMIT_Freewmap, inode)) + jfs_free_zero_link(inode); - /* - * Free the inode from the quota allocation. - */ - vfs_dq_init(inode); - vfs_dq_free_inode(inode); - vfs_dq_drop(inode); - } + diFree(inode); + /* + * Free the inode from the quota allocation. + */ + dquot_initialize(inode); + dquot_free_inode(inode); + } + } else { + truncate_inode_pages_final(&inode->i_data); + } clear_inode(inode); + dquot_drop(inode); } -void jfs_dirty_inode(struct inode *inode) +void jfs_dirty_inode(struct inode *inode, int flags) { static int noisy = 5; @@ -293,12 +301,28 @@ static int jfs_readpages(struct file *file, struct address_space *mapping, return mpage_readpages(mapping, pages, nr_pages, jfs_get_block); } +static void jfs_write_failed(struct address_space *mapping, loff_t to) +{ + struct inode *inode = mapping->host; + + if (to > inode->i_size) { + truncate_pagecache(inode, inode->i_size); + jfs_truncate(inode); + } +} + static int jfs_write_begin(struct file *file, struct address_space *mapping, loff_t pos, unsigned len, unsigned flags, struct page **pagep, void **fsdata) { - return nobh_write_begin(file, mapping, pos, len, flags, pagep, fsdata, + int ret; + + ret = nobh_write_begin(mapping, pos, len, flags, pagep, fsdata, jfs_get_block); + if (unlikely(ret)) + jfs_write_failed(mapping, pos + len); + + return ret; } static sector_t jfs_bmap(struct address_space *mapping, sector_t block) @@ -307,13 +331,29 @@ static sector_t jfs_bmap(struct address_space *mapping, sector_t block) } static ssize_t jfs_direct_IO(int rw, struct kiocb *iocb, - const struct iovec *iov, loff_t offset, unsigned long nr_segs) + struct iov_iter *iter, loff_t offset) { struct file *file = iocb->ki_filp; + struct address_space *mapping = file->f_mapping; struct inode *inode = file->f_mapping->host; + size_t count = iov_iter_count(iter); + ssize_t ret; + + ret = blockdev_direct_IO(rw, iocb, inode, iter, offset, jfs_get_block); + + /* + * In case of error extending write may have instantiated a few + * blocks outside i_size. Trim these off again. + */ + if (unlikely((rw & WRITE) && ret < 0)) { + loff_t isize = i_size_read(inode); + loff_t end = offset + count; + + if (end > isize) + jfs_write_failed(mapping, end); + } - return blockdev_direct_IO(rw, iocb, inode, inode->i_sb->s_bdev, iov, - offset, nr_segs, jfs_get_block, NULL); + return ret; } const struct address_space_operations jfs_aops = { @@ -321,7 +361,6 @@ const struct address_space_operations jfs_aops = { .readpages = jfs_readpages, .writepage = jfs_writepage, .writepages = jfs_writepages, - .sync_page = block_sync_page, .write_begin = jfs_write_begin, .write_end = nobh_write_end, .bmap = jfs_bmap, |
