summaryrefslogtreecommitdiffstats
path: root/fs/jfs/inode.c
diff options
context:
space:
mode:
Diffstat (limited to 'fs/jfs/inode.c')
-rw-r--r--fs/jfs/inode.c63
1 files changed, 44 insertions, 19 deletions
diff --git a/fs/jfs/inode.c b/fs/jfs/inode.c
index ed9ba6f..9978803 100644
--- a/fs/jfs/inode.c
+++ b/fs/jfs/inode.c
@@ -145,31 +145,32 @@ int jfs_write_inode(struct inode *inode, struct writeback_control *wbc)
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))
+ if (!inode->i_nlink && !is_bad_inode(inode)) {
dquot_initialize(inode);
- if (!is_bad_inode(inode) &&
- (JFS_IP(inode)->fileset == FILESYSTEM_I)) {
- truncate_inode_pages(&inode->i_data, 0);
+ if (JFS_IP(inode)->fileset == FILESYSTEM_I) {
+ truncate_inode_pages(&inode->i_data, 0);
- if (test_cflag(COMMIT_Freewmap, inode))
- jfs_free_zero_link(inode);
+ if (test_cflag(COMMIT_Freewmap, inode))
+ jfs_free_zero_link(inode);
- diFree(inode);
+ diFree(inode);
- /*
- * Free the inode from the quota allocation.
- */
- dquot_initialize(inode);
- dquot_free_inode(inode);
- dquot_drop(inode);
+ /*
+ * Free the inode from the quota allocation.
+ */
+ dquot_initialize(inode);
+ dquot_free_inode(inode);
+ }
+ } else {
+ truncate_inode_pages(&inode->i_data, 0);
}
-
- clear_inode(inode);
+ end_writeback(inode);
+ dquot_drop(inode);
}
void jfs_dirty_inode(struct inode *inode)
@@ -303,8 +304,17 @@ 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)) {
+ loff_t isize = mapping->host->i_size;
+ if (pos + len > isize)
+ vmtruncate(mapping->host, isize);
+ }
+
+ return ret;
}
static sector_t jfs_bmap(struct address_space *mapping, sector_t block)
@@ -317,9 +327,24 @@ static ssize_t jfs_direct_IO(int rw, struct kiocb *iocb,
{
struct file *file = iocb->ki_filp;
struct inode *inode = file->f_mapping->host;
+ ssize_t ret;
- return blockdev_direct_IO(rw, iocb, inode, inode->i_sb->s_bdev, iov,
+ ret = blockdev_direct_IO(rw, iocb, inode, inode->i_sb->s_bdev, iov,
offset, nr_segs, jfs_get_block, NULL);
+
+ /*
+ * 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 + iov_length(iov, nr_segs);
+
+ if (end > isize)
+ vmtruncate(inode, isize);
+ }
+
+ return ret;
}
const struct address_space_operations jfs_aops = {
OpenPOWER on IntegriCloud