diff options
Diffstat (limited to 'fs/nilfs2/inode.c')
-rw-r--r-- | fs/nilfs2/inode.c | 93 |
1 files changed, 67 insertions, 26 deletions
diff --git a/fs/nilfs2/inode.c b/fs/nilfs2/inode.c index 0957b58f909d..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 | ||
@@ -280,16 +298,7 @@ struct inode *nilfs_new_inode(struct inode *dir, int mode) | |||
280 | /* reference count of i_bh inherits from nilfs_mdt_read_block() */ | 298 | /* reference count of i_bh inherits from nilfs_mdt_read_block() */ |
281 | 299 | ||
282 | atomic_inc(&sbi->s_inodes_count); | 300 | atomic_inc(&sbi->s_inodes_count); |
283 | 301 | inode_init_owner(inode, dir, mode); | |
284 | inode->i_uid = current_fsuid(); | ||
285 | if (dir->i_mode & S_ISGID) { | ||
286 | inode->i_gid = dir->i_gid; | ||
287 | if (S_ISDIR(mode)) | ||
288 | mode |= S_ISGID; | ||
289 | } else | ||
290 | inode->i_gid = current_fsgid(); | ||
291 | |||
292 | inode->i_mode = mode; | ||
293 | inode->i_ino = ino; | 302 | inode->i_ino = ino; |
294 | inode->i_mtime = inode->i_atime = inode->i_ctime = CURRENT_TIME; | 303 | inode->i_mtime = inode->i_atime = inode->i_ctime = CURRENT_TIME; |
295 | 304 | ||
@@ -346,7 +355,6 @@ void nilfs_free_inode(struct inode *inode) | |||
346 | struct super_block *sb = inode->i_sb; | 355 | struct super_block *sb = inode->i_sb; |
347 | struct nilfs_sb_info *sbi = NILFS_SB(sb); | 356 | struct nilfs_sb_info *sbi = NILFS_SB(sb); |
348 | 357 | ||
349 | clear_inode(inode); | ||
350 | /* XXX: check error code? Is there any thing I can do? */ | 358 | /* XXX: check error code? Is there any thing I can do? */ |
351 | (void) nilfs_ifile_delete_inode(sbi->s_ifile, inode->i_ino); | 359 | (void) nilfs_ifile_delete_inode(sbi->s_ifile, inode->i_ino); |
352 | atomic_dec(&sbi->s_inodes_count); | 360 | atomic_dec(&sbi->s_inodes_count); |
@@ -451,7 +459,7 @@ static int __nilfs_read_inode(struct super_block *sb, unsigned long ino, | |||
451 | inode->i_op = &nilfs_special_inode_operations; | 459 | inode->i_op = &nilfs_special_inode_operations; |
452 | init_special_inode( | 460 | init_special_inode( |
453 | inode, inode->i_mode, | 461 | inode, inode->i_mode, |
454 | new_decode_dev(le64_to_cpu(raw_inode->i_device_code))); | 462 | huge_decode_dev(le64_to_cpu(raw_inode->i_device_code))); |
455 | } | 463 | } |
456 | nilfs_ifile_unmap_inode(sbi->s_ifile, ino, bh); | 464 | nilfs_ifile_unmap_inode(sbi->s_ifile, ino, bh); |
457 | brelse(bh); | 465 | brelse(bh); |
@@ -511,7 +519,7 @@ void nilfs_write_inode_common(struct inode *inode, | |||
511 | nilfs_bmap_write(ii->i_bmap, raw_inode); | 519 | nilfs_bmap_write(ii->i_bmap, raw_inode); |
512 | else if (S_ISCHR(inode->i_mode) || S_ISBLK(inode->i_mode)) | 520 | else if (S_ISCHR(inode->i_mode) || S_ISBLK(inode->i_mode)) |
513 | raw_inode->i_device_code = | 521 | raw_inode->i_device_code = |
514 | cpu_to_le64(new_encode_dev(inode->i_rdev)); | 522 | cpu_to_le64(huge_encode_dev(inode->i_rdev)); |
515 | /* When extending inode, nilfs->ns_inode_size should be checked | 523 | /* When extending inode, nilfs->ns_inode_size should be checked |
516 | for substitutions of appended fields */ | 524 | for substitutions of appended fields */ |
517 | } | 525 | } |
@@ -606,16 +614,34 @@ void nilfs_truncate(struct inode *inode) | |||
606 | But truncate has no return value. */ | 614 | But truncate has no return value. */ |
607 | } | 615 | } |
608 | 616 | ||
609 | 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) | ||
610 | { | 635 | { |
611 | struct nilfs_transaction_info ti; | 636 | struct nilfs_transaction_info ti; |
612 | struct super_block *sb = inode->i_sb; | 637 | struct super_block *sb = inode->i_sb; |
613 | struct nilfs_inode_info *ii = NILFS_I(inode); | 638 | struct nilfs_inode_info *ii = NILFS_I(inode); |
614 | 639 | ||
615 | if (unlikely(is_bad_inode(inode))) { | 640 | if (inode->i_nlink || unlikely(is_bad_inode(inode))) { |
616 | if (inode->i_data.nrpages) | 641 | if (inode->i_data.nrpages) |
617 | truncate_inode_pages(&inode->i_data, 0); | 642 | truncate_inode_pages(&inode->i_data, 0); |
618 | clear_inode(inode); | 643 | end_writeback(inode); |
644 | nilfs_clear_inode(inode); | ||
619 | return; | 645 | return; |
620 | } | 646 | } |
621 | nilfs_transaction_begin(sb, &ti, 0); /* never fails */ | 647 | nilfs_transaction_begin(sb, &ti, 0); /* never fails */ |
@@ -625,6 +651,8 @@ void nilfs_delete_inode(struct inode *inode) | |||
625 | 651 | ||
626 | nilfs_truncate_bmap(ii, 0); | 652 | nilfs_truncate_bmap(ii, 0); |
627 | nilfs_mark_inode_dirty(inode); | 653 | nilfs_mark_inode_dirty(inode); |
654 | end_writeback(inode); | ||
655 | nilfs_clear_inode(inode); | ||
628 | nilfs_free_inode(inode); | 656 | nilfs_free_inode(inode); |
629 | /* nilfs_free_inode() marks inode buffer dirty */ | 657 | /* nilfs_free_inode() marks inode buffer dirty */ |
630 | if (IS_SYNC(inode)) | 658 | if (IS_SYNC(inode)) |
@@ -648,14 +676,27 @@ int nilfs_setattr(struct dentry *dentry, struct iattr *iattr) | |||
648 | err = nilfs_transaction_begin(sb, &ti, 0); | 676 | err = nilfs_transaction_begin(sb, &ti, 0); |
649 | if (unlikely(err)) | 677 | if (unlikely(err)) |
650 | return err; | 678 | return err; |
651 | err = inode_setattr(inode, iattr); | 679 | |
652 | 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) { | ||
653 | err = nilfs_acl_chmod(inode); | 691 | err = nilfs_acl_chmod(inode); |
654 | if (likely(!err)) | 692 | if (unlikely(err)) |
655 | err = nilfs_transaction_commit(sb); | 693 | goto out_err; |
656 | else | 694 | } |
657 | nilfs_transaction_abort(sb); | 695 | |
696 | return nilfs_transaction_commit(sb); | ||
658 | 697 | ||
698 | out_err: | ||
699 | nilfs_transaction_abort(sb); | ||
659 | return err; | 700 | return err; |
660 | } | 701 | } |
661 | 702 | ||