diff options
Diffstat (limited to 'fs/nilfs2/inode.c')
-rw-r--r-- | fs/nilfs2/inode.c | 78 |
1 files changed, 64 insertions, 14 deletions
diff --git a/fs/nilfs2/inode.c b/fs/nilfs2/inode.c index 39e038ac8fcb..eccb2f2e2315 100644 --- a/fs/nilfs2/inode.c +++ b/fs/nilfs2/inode.c | |||
@@ -27,6 +27,7 @@ | |||
27 | #include <linux/writeback.h> | 27 | #include <linux/writeback.h> |
28 | #include <linux/uio.h> | 28 | #include <linux/uio.h> |
29 | #include "nilfs.h" | 29 | #include "nilfs.h" |
30 | #include "btnode.h" | ||
30 | #include "segment.h" | 31 | #include "segment.h" |
31 | #include "page.h" | 32 | #include "page.h" |
32 | #include "mdt.h" | 33 | #include "mdt.h" |
@@ -197,11 +198,15 @@ static int nilfs_write_begin(struct file *file, struct address_space *mapping, | |||
197 | if (unlikely(err)) | 198 | if (unlikely(err)) |
198 | return err; | 199 | return err; |
199 | 200 | ||
200 | *pagep = NULL; | 201 | err = block_write_begin(mapping, pos, len, flags, pagep, |
201 | err = block_write_begin(file, mapping, pos, len, flags, pagep, | 202 | nilfs_get_block); |
202 | fsdata, nilfs_get_block); | 203 | if (unlikely(err)) { |
203 | if (unlikely(err)) | 204 | loff_t isize = mapping->host->i_size; |
205 | if (pos + len > isize) | ||
206 | vmtruncate(mapping->host, isize); | ||
207 | |||
204 | nilfs_transaction_abort(inode->i_sb); | 208 | nilfs_transaction_abort(inode->i_sb); |
209 | } | ||
205 | return err; | 210 | return err; |
206 | } | 211 | } |
207 | 212 | ||
@@ -237,6 +242,19 @@ nilfs_direct_IO(int rw, struct kiocb *iocb, const struct iovec *iov, | |||
237 | /* Needs synchronization with the cleaner */ | 242 | /* Needs synchronization with the cleaner */ |
238 | size = blockdev_direct_IO(rw, iocb, inode, inode->i_sb->s_bdev, iov, | 243 | size = blockdev_direct_IO(rw, iocb, inode, inode->i_sb->s_bdev, iov, |
239 | offset, nr_segs, nilfs_get_block, NULL); | 244 | offset, nr_segs, nilfs_get_block, NULL); |
245 | |||
246 | /* | ||
247 | * In case of error extending write may have instantiated a few | ||
248 | * blocks outside i_size. Trim these off again. | ||
249 | */ | ||
250 | if (unlikely((rw & WRITE) && size < 0)) { | ||
251 | loff_t isize = i_size_read(inode); | ||
252 | loff_t end = offset + iov_length(iov, nr_segs); | ||
253 | |||
254 | if (end > isize) | ||
255 | vmtruncate(inode, isize); | ||
256 | } | ||
257 | |||
240 | return size; | 258 | return size; |
241 | } | 259 | } |
242 | 260 | ||
@@ -337,7 +355,6 @@ void nilfs_free_inode(struct inode *inode) | |||
337 | struct super_block *sb = inode->i_sb; | 355 | struct super_block *sb = inode->i_sb; |
338 | struct nilfs_sb_info *sbi = NILFS_SB(sb); | 356 | struct nilfs_sb_info *sbi = NILFS_SB(sb); |
339 | 357 | ||
340 | clear_inode(inode); | ||
341 | /* XXX: check error code? Is there any thing I can do? */ | 358 | /* XXX: check error code? Is there any thing I can do? */ |
342 | (void) nilfs_ifile_delete_inode(sbi->s_ifile, inode->i_ino); | 359 | (void) nilfs_ifile_delete_inode(sbi->s_ifile, inode->i_ino); |
343 | atomic_dec(&sbi->s_inodes_count); | 360 | atomic_dec(&sbi->s_inodes_count); |
@@ -597,16 +614,34 @@ void nilfs_truncate(struct inode *inode) | |||
597 | But truncate has no return value. */ | 614 | But truncate has no return value. */ |
598 | } | 615 | } |
599 | 616 | ||
600 | void nilfs_delete_inode(struct inode *inode) | 617 | static void nilfs_clear_inode(struct inode *inode) |
618 | { | ||
619 | struct nilfs_inode_info *ii = NILFS_I(inode); | ||
620 | |||
621 | /* | ||
622 | * Free resources allocated in nilfs_read_inode(), here. | ||
623 | */ | ||
624 | BUG_ON(!list_empty(&ii->i_dirty)); | ||
625 | brelse(ii->i_bh); | ||
626 | ii->i_bh = NULL; | ||
627 | |||
628 | if (test_bit(NILFS_I_BMAP, &ii->i_state)) | ||
629 | nilfs_bmap_clear(ii->i_bmap); | ||
630 | |||
631 | nilfs_btnode_cache_clear(&ii->i_btnode_cache); | ||
632 | } | ||
633 | |||
634 | void nilfs_evict_inode(struct inode *inode) | ||
601 | { | 635 | { |
602 | struct nilfs_transaction_info ti; | 636 | struct nilfs_transaction_info ti; |
603 | struct super_block *sb = inode->i_sb; | 637 | struct super_block *sb = inode->i_sb; |
604 | struct nilfs_inode_info *ii = NILFS_I(inode); | 638 | struct nilfs_inode_info *ii = NILFS_I(inode); |
605 | 639 | ||
606 | if (unlikely(is_bad_inode(inode))) { | 640 | if (inode->i_nlink || unlikely(is_bad_inode(inode))) { |
607 | if (inode->i_data.nrpages) | 641 | if (inode->i_data.nrpages) |
608 | truncate_inode_pages(&inode->i_data, 0); | 642 | truncate_inode_pages(&inode->i_data, 0); |
609 | clear_inode(inode); | 643 | end_writeback(inode); |
644 | nilfs_clear_inode(inode); | ||
610 | return; | 645 | return; |
611 | } | 646 | } |
612 | nilfs_transaction_begin(sb, &ti, 0); /* never fails */ | 647 | nilfs_transaction_begin(sb, &ti, 0); /* never fails */ |
@@ -616,6 +651,8 @@ void nilfs_delete_inode(struct inode *inode) | |||
616 | 651 | ||
617 | nilfs_truncate_bmap(ii, 0); | 652 | nilfs_truncate_bmap(ii, 0); |
618 | nilfs_mark_inode_dirty(inode); | 653 | nilfs_mark_inode_dirty(inode); |
654 | end_writeback(inode); | ||
655 | nilfs_clear_inode(inode); | ||
619 | nilfs_free_inode(inode); | 656 | nilfs_free_inode(inode); |
620 | /* nilfs_free_inode() marks inode buffer dirty */ | 657 | /* nilfs_free_inode() marks inode buffer dirty */ |
621 | if (IS_SYNC(inode)) | 658 | if (IS_SYNC(inode)) |
@@ -639,14 +676,27 @@ int nilfs_setattr(struct dentry *dentry, struct iattr *iattr) | |||
639 | err = nilfs_transaction_begin(sb, &ti, 0); | 676 | err = nilfs_transaction_begin(sb, &ti, 0); |
640 | if (unlikely(err)) | 677 | if (unlikely(err)) |
641 | return err; | 678 | return err; |
642 | err = inode_setattr(inode, iattr); | 679 | |
643 | if (!err && (iattr->ia_valid & ATTR_MODE)) | 680 | if ((iattr->ia_valid & ATTR_SIZE) && |
681 | iattr->ia_size != i_size_read(inode)) { | ||
682 | err = vmtruncate(inode, iattr->ia_size); | ||
683 | if (unlikely(err)) | ||
684 | goto out_err; | ||
685 | } | ||
686 | |||
687 | setattr_copy(inode, iattr); | ||
688 | mark_inode_dirty(inode); | ||
689 | |||
690 | if (iattr->ia_valid & ATTR_MODE) { | ||
644 | err = nilfs_acl_chmod(inode); | 691 | err = nilfs_acl_chmod(inode); |
645 | if (likely(!err)) | 692 | if (unlikely(err)) |
646 | err = nilfs_transaction_commit(sb); | 693 | goto out_err; |
647 | else | 694 | } |
648 | nilfs_transaction_abort(sb); | 695 | |
696 | return nilfs_transaction_commit(sb); | ||
649 | 697 | ||
698 | out_err: | ||
699 | nilfs_transaction_abort(sb); | ||
650 | return err; | 700 | return err; |
651 | } | 701 | } |
652 | 702 | ||