aboutsummaryrefslogtreecommitdiffstats
path: root/fs/nilfs2/inode.c
diff options
context:
space:
mode:
authorRyusuke Konishi <konishi.ryusuke@lab.ntt.co.jp>2010-12-26 02:38:43 -0500
committerRyusuke Konishi <konishi.ryusuke@lab.ntt.co.jp>2011-01-10 00:05:46 -0500
commit622daaff0a8975fb5c5b95f24f3234550ba32e92 (patch)
tree5ae5de9044f962471fa2694654134f5b58f73ace /fs/nilfs2/inode.c
parent27e6c7a3ce29ae5fa5bec4ed5917f8508bfac120 (diff)
nilfs2: fiemap support
This adds fiemap to nilfs. Two new functions, nilfs_fiemap and nilfs_find_uncommitted_extent are added. nilfs_fiemap() implements the fiemap inode operation, and nilfs_find_uncommitted_extent() helps to get a range of data blocks whose physical location has not been determined. nilfs_fiemap() collects extent information by looping through nilfs_bmap_lookup_contig and nilfs_find_uncommitted_extent routines. Signed-off-by: Ryusuke Konishi <konishi.ryusuke@lab.ntt.co.jp>
Diffstat (limited to 'fs/nilfs2/inode.c')
-rw-r--r--fs/nilfs2/inode.c131
1 files changed, 131 insertions, 0 deletions
diff --git a/fs/nilfs2/inode.c b/fs/nilfs2/inode.c
index 1a546a86d7a7..b2a815033ee3 100644
--- a/fs/nilfs2/inode.c
+++ b/fs/nilfs2/inode.c
@@ -916,3 +916,134 @@ void nilfs_dirty_inode(struct inode *inode)
916 nilfs_mark_inode_dirty(inode); 916 nilfs_mark_inode_dirty(inode);
917 nilfs_transaction_commit(inode->i_sb); /* never fails */ 917 nilfs_transaction_commit(inode->i_sb); /* never fails */
918} 918}
919
920int nilfs_fiemap(struct inode *inode, struct fiemap_extent_info *fieinfo,
921 __u64 start, __u64 len)
922{
923 struct the_nilfs *nilfs = NILFS_I_NILFS(inode);
924 __u64 logical = 0, phys = 0, size = 0;
925 __u32 flags = 0;
926 loff_t isize;
927 sector_t blkoff, end_blkoff;
928 sector_t delalloc_blkoff;
929 unsigned long delalloc_blklen;
930 unsigned int blkbits = inode->i_blkbits;
931 int ret, n;
932
933 ret = fiemap_check_flags(fieinfo, FIEMAP_FLAG_SYNC);
934 if (ret)
935 return ret;
936
937 mutex_lock(&inode->i_mutex);
938
939 isize = i_size_read(inode);
940
941 blkoff = start >> blkbits;
942 end_blkoff = (start + len - 1) >> blkbits;
943
944 delalloc_blklen = nilfs_find_uncommitted_extent(inode, blkoff,
945 &delalloc_blkoff);
946
947 do {
948 __u64 blkphy;
949 unsigned int maxblocks;
950
951 if (delalloc_blklen && blkoff == delalloc_blkoff) {
952 if (size) {
953 /* End of the current extent */
954 ret = fiemap_fill_next_extent(
955 fieinfo, logical, phys, size, flags);
956 if (ret)
957 break;
958 }
959 if (blkoff > end_blkoff)
960 break;
961
962 flags = FIEMAP_EXTENT_MERGED | FIEMAP_EXTENT_DELALLOC;
963 logical = blkoff << blkbits;
964 phys = 0;
965 size = delalloc_blklen << blkbits;
966
967 blkoff = delalloc_blkoff + delalloc_blklen;
968 delalloc_blklen = nilfs_find_uncommitted_extent(
969 inode, blkoff, &delalloc_blkoff);
970 continue;
971 }
972
973 /*
974 * Limit the number of blocks that we look up so as
975 * not to get into the next delayed allocation extent.
976 */
977 maxblocks = INT_MAX;
978 if (delalloc_blklen)
979 maxblocks = min_t(sector_t, delalloc_blkoff - blkoff,
980 maxblocks);
981 blkphy = 0;
982
983 down_read(&NILFS_MDT(nilfs->ns_dat)->mi_sem);
984 n = nilfs_bmap_lookup_contig(
985 NILFS_I(inode)->i_bmap, blkoff, &blkphy, maxblocks);
986 up_read(&NILFS_MDT(nilfs->ns_dat)->mi_sem);
987
988 if (n < 0) {
989 int past_eof;
990
991 if (unlikely(n != -ENOENT))
992 break; /* error */
993
994 /* HOLE */
995 blkoff++;
996 past_eof = ((blkoff << blkbits) >= isize);
997
998 if (size) {
999 /* End of the current extent */
1000
1001 if (past_eof)
1002 flags |= FIEMAP_EXTENT_LAST;
1003
1004 ret = fiemap_fill_next_extent(
1005 fieinfo, logical, phys, size, flags);
1006 if (ret)
1007 break;
1008 size = 0;
1009 }
1010 if (blkoff > end_blkoff || past_eof)
1011 break;
1012 } else {
1013 if (size) {
1014 if (phys && blkphy << blkbits == phys + size) {
1015 /* The current extent goes on */
1016 size += n << blkbits;
1017 } else {
1018 /* Terminate the current extent */
1019 ret = fiemap_fill_next_extent(
1020 fieinfo, logical, phys, size,
1021 flags);
1022 if (ret || blkoff > end_blkoff)
1023 break;
1024
1025 /* Start another extent */
1026 flags = FIEMAP_EXTENT_MERGED;
1027 logical = blkoff << blkbits;
1028 phys = blkphy << blkbits;
1029 size = n << blkbits;
1030 }
1031 } else {
1032 /* Start a new extent */
1033 flags = FIEMAP_EXTENT_MERGED;
1034 logical = blkoff << blkbits;
1035 phys = blkphy << blkbits;
1036 size = n << blkbits;
1037 }
1038 blkoff += n;
1039 }
1040 cond_resched();
1041 } while (true);
1042
1043 /* If ret is 1 then we just hit the end of the extent array */
1044 if (ret == 1)
1045 ret = 0;
1046
1047 mutex_unlock(&inode->i_mutex);
1048 return ret;
1049}