diff options
Diffstat (limited to 'fs/nilfs2/inode.c')
-rw-r--r-- | fs/nilfs2/inode.c | 180 |
1 files changed, 150 insertions, 30 deletions
diff --git a/fs/nilfs2/inode.c b/fs/nilfs2/inode.c index 77b48c8fab17..2fd440d8d6b8 100644 --- a/fs/nilfs2/inode.c +++ b/fs/nilfs2/inode.c | |||
@@ -58,7 +58,7 @@ int nilfs_get_block(struct inode *inode, sector_t blkoff, | |||
58 | struct nilfs_inode_info *ii = NILFS_I(inode); | 58 | struct nilfs_inode_info *ii = NILFS_I(inode); |
59 | __u64 blknum = 0; | 59 | __u64 blknum = 0; |
60 | int err = 0, ret; | 60 | int err = 0, ret; |
61 | struct inode *dat = nilfs_dat_inode(NILFS_I_NILFS(inode)); | 61 | struct inode *dat = NILFS_I_NILFS(inode)->ns_dat; |
62 | unsigned maxblocks = bh_result->b_size >> inode->i_blkbits; | 62 | unsigned maxblocks = bh_result->b_size >> inode->i_blkbits; |
63 | 63 | ||
64 | down_read(&NILFS_MDT(dat)->mi_sem); | 64 | down_read(&NILFS_MDT(dat)->mi_sem); |
@@ -96,11 +96,6 @@ int nilfs_get_block(struct inode *inode, sector_t blkoff, | |||
96 | inode->i_ino, | 96 | inode->i_ino, |
97 | (unsigned long long)blkoff); | 97 | (unsigned long long)blkoff); |
98 | err = 0; | 98 | err = 0; |
99 | } else if (err == -EINVAL) { | ||
100 | nilfs_error(inode->i_sb, __func__, | ||
101 | "broken bmap (inode=%lu)\n", | ||
102 | inode->i_ino); | ||
103 | err = -EIO; | ||
104 | } | 99 | } |
105 | nilfs_transaction_abort(inode->i_sb); | 100 | nilfs_transaction_abort(inode->i_sb); |
106 | goto out; | 101 | goto out; |
@@ -109,6 +104,7 @@ int nilfs_get_block(struct inode *inode, sector_t blkoff, | |||
109 | nilfs_transaction_commit(inode->i_sb); /* never fails */ | 104 | nilfs_transaction_commit(inode->i_sb); /* never fails */ |
110 | /* Error handling should be detailed */ | 105 | /* Error handling should be detailed */ |
111 | set_buffer_new(bh_result); | 106 | set_buffer_new(bh_result); |
107 | set_buffer_delay(bh_result); | ||
112 | map_bh(bh_result, inode->i_sb, 0); /* dbn must be changed | 108 | map_bh(bh_result, inode->i_sb, 0); /* dbn must be changed |
113 | to proper value */ | 109 | to proper value */ |
114 | } else if (ret == -ENOENT) { | 110 | } else if (ret == -ENOENT) { |
@@ -185,10 +181,9 @@ static int nilfs_set_page_dirty(struct page *page) | |||
185 | 181 | ||
186 | if (ret) { | 182 | if (ret) { |
187 | struct inode *inode = page->mapping->host; | 183 | struct inode *inode = page->mapping->host; |
188 | struct nilfs_sb_info *sbi = NILFS_SB(inode->i_sb); | ||
189 | unsigned nr_dirty = 1 << (PAGE_SHIFT - inode->i_blkbits); | 184 | unsigned nr_dirty = 1 << (PAGE_SHIFT - inode->i_blkbits); |
190 | 185 | ||
191 | nilfs_set_file_dirty(sbi, inode, nr_dirty); | 186 | nilfs_set_file_dirty(inode, nr_dirty); |
192 | } | 187 | } |
193 | return ret; | 188 | return ret; |
194 | } | 189 | } |
@@ -229,7 +224,7 @@ static int nilfs_write_end(struct file *file, struct address_space *mapping, | |||
229 | start + copied); | 224 | start + copied); |
230 | copied = generic_write_end(file, mapping, pos, len, copied, page, | 225 | copied = generic_write_end(file, mapping, pos, len, copied, page, |
231 | fsdata); | 226 | fsdata); |
232 | nilfs_set_file_dirty(NILFS_SB(inode->i_sb), inode, nr_dirty); | 227 | nilfs_set_file_dirty(inode, nr_dirty); |
233 | err = nilfs_transaction_commit(inode->i_sb); | 228 | err = nilfs_transaction_commit(inode->i_sb); |
234 | return err ? : copied; | 229 | return err ? : copied; |
235 | } | 230 | } |
@@ -425,13 +420,12 @@ static int __nilfs_read_inode(struct super_block *sb, | |||
425 | struct nilfs_root *root, unsigned long ino, | 420 | struct nilfs_root *root, unsigned long ino, |
426 | struct inode *inode) | 421 | struct inode *inode) |
427 | { | 422 | { |
428 | struct nilfs_sb_info *sbi = NILFS_SB(sb); | 423 | struct the_nilfs *nilfs = NILFS_SB(sb)->s_nilfs; |
429 | struct inode *dat = nilfs_dat_inode(sbi->s_nilfs); | ||
430 | struct buffer_head *bh; | 424 | struct buffer_head *bh; |
431 | struct nilfs_inode *raw_inode; | 425 | struct nilfs_inode *raw_inode; |
432 | int err; | 426 | int err; |
433 | 427 | ||
434 | down_read(&NILFS_MDT(dat)->mi_sem); /* XXX */ | 428 | down_read(&NILFS_MDT(nilfs->ns_dat)->mi_sem); |
435 | err = nilfs_ifile_get_inode_block(root->ifile, ino, &bh); | 429 | err = nilfs_ifile_get_inode_block(root->ifile, ino, &bh); |
436 | if (unlikely(err)) | 430 | if (unlikely(err)) |
437 | goto bad_inode; | 431 | goto bad_inode; |
@@ -461,7 +455,7 @@ static int __nilfs_read_inode(struct super_block *sb, | |||
461 | } | 455 | } |
462 | nilfs_ifile_unmap_inode(root->ifile, ino, bh); | 456 | nilfs_ifile_unmap_inode(root->ifile, ino, bh); |
463 | brelse(bh); | 457 | brelse(bh); |
464 | up_read(&NILFS_MDT(dat)->mi_sem); /* XXX */ | 458 | up_read(&NILFS_MDT(nilfs->ns_dat)->mi_sem); |
465 | nilfs_set_inode_flags(inode); | 459 | nilfs_set_inode_flags(inode); |
466 | return 0; | 460 | return 0; |
467 | 461 | ||
@@ -470,7 +464,7 @@ static int __nilfs_read_inode(struct super_block *sb, | |||
470 | brelse(bh); | 464 | brelse(bh); |
471 | 465 | ||
472 | bad_inode: | 466 | bad_inode: |
473 | up_read(&NILFS_MDT(dat)->mi_sem); /* XXX */ | 467 | up_read(&NILFS_MDT(nilfs->ns_dat)->mi_sem); |
474 | return err; | 468 | return err; |
475 | } | 469 | } |
476 | 470 | ||
@@ -629,7 +623,7 @@ static void nilfs_truncate_bmap(struct nilfs_inode_info *ii, | |||
629 | 623 | ||
630 | if (!test_bit(NILFS_I_BMAP, &ii->i_state)) | 624 | if (!test_bit(NILFS_I_BMAP, &ii->i_state)) |
631 | return; | 625 | return; |
632 | repeat: | 626 | repeat: |
633 | ret = nilfs_bmap_last_key(ii->i_bmap, &b); | 627 | ret = nilfs_bmap_last_key(ii->i_bmap, &b); |
634 | if (ret == -ENOENT) | 628 | if (ret == -ENOENT) |
635 | return; | 629 | return; |
@@ -646,14 +640,10 @@ static void nilfs_truncate_bmap(struct nilfs_inode_info *ii, | |||
646 | nilfs_bmap_truncate(ii->i_bmap, b) == 0)) | 640 | nilfs_bmap_truncate(ii->i_bmap, b) == 0)) |
647 | goto repeat; | 641 | goto repeat; |
648 | 642 | ||
649 | failed: | 643 | failed: |
650 | if (ret == -EINVAL) | 644 | nilfs_warning(ii->vfs_inode.i_sb, __func__, |
651 | nilfs_error(ii->vfs_inode.i_sb, __func__, | 645 | "failed to truncate bmap (ino=%lu, err=%d)", |
652 | "bmap is broken (ino=%lu)", ii->vfs_inode.i_ino); | 646 | ii->vfs_inode.i_ino, ret); |
653 | else | ||
654 | nilfs_warning(ii->vfs_inode.i_sb, __func__, | ||
655 | "failed to truncate bmap (ino=%lu, err=%d)", | ||
656 | ii->vfs_inode.i_ino, ret); | ||
657 | } | 647 | } |
658 | 648 | ||
659 | void nilfs_truncate(struct inode *inode) | 649 | void nilfs_truncate(struct inode *inode) |
@@ -682,7 +672,7 @@ void nilfs_truncate(struct inode *inode) | |||
682 | nilfs_set_transaction_flag(NILFS_TI_SYNC); | 672 | nilfs_set_transaction_flag(NILFS_TI_SYNC); |
683 | 673 | ||
684 | nilfs_mark_inode_dirty(inode); | 674 | nilfs_mark_inode_dirty(inode); |
685 | nilfs_set_file_dirty(NILFS_SB(sb), inode, 0); | 675 | nilfs_set_file_dirty(inode, 0); |
686 | nilfs_transaction_commit(sb); | 676 | nilfs_transaction_commit(sb); |
687 | /* May construct a logical segment and may fail in sync mode. | 677 | /* May construct a logical segment and may fail in sync mode. |
688 | But truncate has no return value. */ | 678 | But truncate has no return value. */ |
@@ -800,9 +790,9 @@ int nilfs_permission(struct inode *inode, int mask, unsigned int flags) | |||
800 | return generic_permission(inode, mask, flags, NULL); | 790 | return generic_permission(inode, mask, flags, NULL); |
801 | } | 791 | } |
802 | 792 | ||
803 | int nilfs_load_inode_block(struct nilfs_sb_info *sbi, struct inode *inode, | 793 | int nilfs_load_inode_block(struct inode *inode, struct buffer_head **pbh) |
804 | struct buffer_head **pbh) | ||
805 | { | 794 | { |
795 | struct nilfs_sb_info *sbi = NILFS_SB(inode->i_sb); | ||
806 | struct nilfs_inode_info *ii = NILFS_I(inode); | 796 | struct nilfs_inode_info *ii = NILFS_I(inode); |
807 | int err; | 797 | int err; |
808 | 798 | ||
@@ -843,9 +833,9 @@ int nilfs_inode_dirty(struct inode *inode) | |||
843 | return ret; | 833 | return ret; |
844 | } | 834 | } |
845 | 835 | ||
846 | int nilfs_set_file_dirty(struct nilfs_sb_info *sbi, struct inode *inode, | 836 | int nilfs_set_file_dirty(struct inode *inode, unsigned nr_dirty) |
847 | unsigned nr_dirty) | ||
848 | { | 837 | { |
838 | struct nilfs_sb_info *sbi = NILFS_SB(inode->i_sb); | ||
849 | struct nilfs_inode_info *ii = NILFS_I(inode); | 839 | struct nilfs_inode_info *ii = NILFS_I(inode); |
850 | 840 | ||
851 | atomic_add(nr_dirty, &sbi->s_nilfs->ns_ndirtyblks); | 841 | atomic_add(nr_dirty, &sbi->s_nilfs->ns_ndirtyblks); |
@@ -878,11 +868,10 @@ int nilfs_set_file_dirty(struct nilfs_sb_info *sbi, struct inode *inode, | |||
878 | 868 | ||
879 | int nilfs_mark_inode_dirty(struct inode *inode) | 869 | int nilfs_mark_inode_dirty(struct inode *inode) |
880 | { | 870 | { |
881 | struct nilfs_sb_info *sbi = NILFS_SB(inode->i_sb); | ||
882 | struct buffer_head *ibh; | 871 | struct buffer_head *ibh; |
883 | int err; | 872 | int err; |
884 | 873 | ||
885 | err = nilfs_load_inode_block(sbi, inode, &ibh); | 874 | err = nilfs_load_inode_block(inode, &ibh); |
886 | if (unlikely(err)) { | 875 | if (unlikely(err)) { |
887 | nilfs_warning(inode->i_sb, __func__, | 876 | nilfs_warning(inode->i_sb, __func__, |
888 | "failed to reget inode block.\n"); | 877 | "failed to reget inode block.\n"); |
@@ -924,3 +913,134 @@ void nilfs_dirty_inode(struct inode *inode) | |||
924 | nilfs_mark_inode_dirty(inode); | 913 | nilfs_mark_inode_dirty(inode); |
925 | nilfs_transaction_commit(inode->i_sb); /* never fails */ | 914 | nilfs_transaction_commit(inode->i_sb); /* never fails */ |
926 | } | 915 | } |
916 | |||
917 | int nilfs_fiemap(struct inode *inode, struct fiemap_extent_info *fieinfo, | ||
918 | __u64 start, __u64 len) | ||
919 | { | ||
920 | struct the_nilfs *nilfs = NILFS_I_NILFS(inode); | ||
921 | __u64 logical = 0, phys = 0, size = 0; | ||
922 | __u32 flags = 0; | ||
923 | loff_t isize; | ||
924 | sector_t blkoff, end_blkoff; | ||
925 | sector_t delalloc_blkoff; | ||
926 | unsigned long delalloc_blklen; | ||
927 | unsigned int blkbits = inode->i_blkbits; | ||
928 | int ret, n; | ||
929 | |||
930 | ret = fiemap_check_flags(fieinfo, FIEMAP_FLAG_SYNC); | ||
931 | if (ret) | ||
932 | return ret; | ||
933 | |||
934 | mutex_lock(&inode->i_mutex); | ||
935 | |||
936 | isize = i_size_read(inode); | ||
937 | |||
938 | blkoff = start >> blkbits; | ||
939 | end_blkoff = (start + len - 1) >> blkbits; | ||
940 | |||
941 | delalloc_blklen = nilfs_find_uncommitted_extent(inode, blkoff, | ||
942 | &delalloc_blkoff); | ||
943 | |||
944 | do { | ||
945 | __u64 blkphy; | ||
946 | unsigned int maxblocks; | ||
947 | |||
948 | if (delalloc_blklen && blkoff == delalloc_blkoff) { | ||
949 | if (size) { | ||
950 | /* End of the current extent */ | ||
951 | ret = fiemap_fill_next_extent( | ||
952 | fieinfo, logical, phys, size, flags); | ||
953 | if (ret) | ||
954 | break; | ||
955 | } | ||
956 | if (blkoff > end_blkoff) | ||
957 | break; | ||
958 | |||
959 | flags = FIEMAP_EXTENT_MERGED | FIEMAP_EXTENT_DELALLOC; | ||
960 | logical = blkoff << blkbits; | ||
961 | phys = 0; | ||
962 | size = delalloc_blklen << blkbits; | ||
963 | |||
964 | blkoff = delalloc_blkoff + delalloc_blklen; | ||
965 | delalloc_blklen = nilfs_find_uncommitted_extent( | ||
966 | inode, blkoff, &delalloc_blkoff); | ||
967 | continue; | ||
968 | } | ||
969 | |||
970 | /* | ||
971 | * Limit the number of blocks that we look up so as | ||
972 | * not to get into the next delayed allocation extent. | ||
973 | */ | ||
974 | maxblocks = INT_MAX; | ||
975 | if (delalloc_blklen) | ||
976 | maxblocks = min_t(sector_t, delalloc_blkoff - blkoff, | ||
977 | maxblocks); | ||
978 | blkphy = 0; | ||
979 | |||
980 | down_read(&NILFS_MDT(nilfs->ns_dat)->mi_sem); | ||
981 | n = nilfs_bmap_lookup_contig( | ||
982 | NILFS_I(inode)->i_bmap, blkoff, &blkphy, maxblocks); | ||
983 | up_read(&NILFS_MDT(nilfs->ns_dat)->mi_sem); | ||
984 | |||
985 | if (n < 0) { | ||
986 | int past_eof; | ||
987 | |||
988 | if (unlikely(n != -ENOENT)) | ||
989 | break; /* error */ | ||
990 | |||
991 | /* HOLE */ | ||
992 | blkoff++; | ||
993 | past_eof = ((blkoff << blkbits) >= isize); | ||
994 | |||
995 | if (size) { | ||
996 | /* End of the current extent */ | ||
997 | |||
998 | if (past_eof) | ||
999 | flags |= FIEMAP_EXTENT_LAST; | ||
1000 | |||
1001 | ret = fiemap_fill_next_extent( | ||
1002 | fieinfo, logical, phys, size, flags); | ||
1003 | if (ret) | ||
1004 | break; | ||
1005 | size = 0; | ||
1006 | } | ||
1007 | if (blkoff > end_blkoff || past_eof) | ||
1008 | break; | ||
1009 | } else { | ||
1010 | if (size) { | ||
1011 | if (phys && blkphy << blkbits == phys + size) { | ||
1012 | /* The current extent goes on */ | ||
1013 | size += n << blkbits; | ||
1014 | } else { | ||
1015 | /* Terminate the current extent */ | ||
1016 | ret = fiemap_fill_next_extent( | ||
1017 | fieinfo, logical, phys, size, | ||
1018 | flags); | ||
1019 | if (ret || blkoff > end_blkoff) | ||
1020 | break; | ||
1021 | |||
1022 | /* Start another extent */ | ||
1023 | flags = FIEMAP_EXTENT_MERGED; | ||
1024 | logical = blkoff << blkbits; | ||
1025 | phys = blkphy << blkbits; | ||
1026 | size = n << blkbits; | ||
1027 | } | ||
1028 | } else { | ||
1029 | /* Start a new extent */ | ||
1030 | flags = FIEMAP_EXTENT_MERGED; | ||
1031 | logical = blkoff << blkbits; | ||
1032 | phys = blkphy << blkbits; | ||
1033 | size = n << blkbits; | ||
1034 | } | ||
1035 | blkoff += n; | ||
1036 | } | ||
1037 | cond_resched(); | ||
1038 | } while (true); | ||
1039 | |||
1040 | /* If ret is 1 then we just hit the end of the extent array */ | ||
1041 | if (ret == 1) | ||
1042 | ret = 0; | ||
1043 | |||
1044 | mutex_unlock(&inode->i_mutex); | ||
1045 | return ret; | ||
1046 | } | ||