diff options
author | Chao Yu <yuchao0@huawei.com> | 2018-01-11 01:39:57 -0500 |
---|---|---|
committer | Jaegeuk Kim <jaegeuk@kernel.org> | 2018-01-19 01:09:11 -0500 |
commit | 442a9dbd577e38211d296f35443b5e257bb5a9b3 (patch) | |
tree | 2aa9200f2c8997e9a1a12c710b3b535eb94f508e | |
parent | f1b43d4cd5f2563f0f1bb2c84eff94faa4c2853b (diff) |
f2fs: support FIEMAP_FLAG_XATTR
This patch enables ->fiemap to handle FIEMAP_FLAG_XATTR flag for xattr
mapping info lookup purpose.
It makes f2fs passing generic/425 test in fstest.
Signed-off-by: Chao Yu <yuchao0@huawei.com>
Signed-off-by: Jaegeuk Kim <jaegeuk@kernel.org>
-rw-r--r-- | fs/f2fs/data.c | 69 |
1 files changed, 68 insertions, 1 deletions
diff --git a/fs/f2fs/data.c b/fs/f2fs/data.c index 664fe0aa18bb..cde2a3264b4c 100644 --- a/fs/f2fs/data.c +++ b/fs/f2fs/data.c | |||
@@ -1140,6 +1140,68 @@ static inline loff_t blk_to_logical(struct inode *inode, sector_t blk) | |||
1140 | return (blk << inode->i_blkbits); | 1140 | return (blk << inode->i_blkbits); |
1141 | } | 1141 | } |
1142 | 1142 | ||
1143 | static int f2fs_xattr_fiemap(struct inode *inode, | ||
1144 | struct fiemap_extent_info *fieinfo) | ||
1145 | { | ||
1146 | struct f2fs_sb_info *sbi = F2FS_I_SB(inode); | ||
1147 | struct page *page; | ||
1148 | struct node_info ni; | ||
1149 | __u64 phys = 0, len; | ||
1150 | __u32 flags; | ||
1151 | nid_t xnid = F2FS_I(inode)->i_xattr_nid; | ||
1152 | int err = 0; | ||
1153 | |||
1154 | if (f2fs_has_inline_xattr(inode)) { | ||
1155 | int offset; | ||
1156 | |||
1157 | page = f2fs_grab_cache_page(NODE_MAPPING(sbi), | ||
1158 | inode->i_ino, false); | ||
1159 | if (!page) | ||
1160 | return -ENOMEM; | ||
1161 | |||
1162 | get_node_info(sbi, inode->i_ino, &ni); | ||
1163 | |||
1164 | phys = (__u64)blk_to_logical(inode, ni.blk_addr); | ||
1165 | offset = offsetof(struct f2fs_inode, i_addr) + | ||
1166 | sizeof(__le32) * (DEF_ADDRS_PER_INODE - | ||
1167 | F2FS_INLINE_XATTR_ADDRS(inode)); | ||
1168 | |||
1169 | phys += offset; | ||
1170 | len = inline_xattr_size(inode); | ||
1171 | |||
1172 | f2fs_put_page(page, 1); | ||
1173 | |||
1174 | flags = FIEMAP_EXTENT_DATA_INLINE | FIEMAP_EXTENT_NOT_ALIGNED; | ||
1175 | |||
1176 | if (!xnid) | ||
1177 | flags |= FIEMAP_EXTENT_LAST; | ||
1178 | |||
1179 | err = fiemap_fill_next_extent(fieinfo, 0, phys, len, flags); | ||
1180 | if (err || err == 1) | ||
1181 | return err; | ||
1182 | } | ||
1183 | |||
1184 | if (xnid) { | ||
1185 | page = f2fs_grab_cache_page(NODE_MAPPING(sbi), xnid, false); | ||
1186 | if (!page) | ||
1187 | return -ENOMEM; | ||
1188 | |||
1189 | get_node_info(sbi, xnid, &ni); | ||
1190 | |||
1191 | phys = (__u64)blk_to_logical(inode, ni.blk_addr); | ||
1192 | len = inode->i_sb->s_blocksize; | ||
1193 | |||
1194 | f2fs_put_page(page, 1); | ||
1195 | |||
1196 | flags = FIEMAP_EXTENT_LAST; | ||
1197 | } | ||
1198 | |||
1199 | if (phys) | ||
1200 | err = fiemap_fill_next_extent(fieinfo, 0, phys, len, flags); | ||
1201 | |||
1202 | return (err < 0 ? err : 0); | ||
1203 | } | ||
1204 | |||
1143 | int f2fs_fiemap(struct inode *inode, struct fiemap_extent_info *fieinfo, | 1205 | int f2fs_fiemap(struct inode *inode, struct fiemap_extent_info *fieinfo, |
1144 | u64 start, u64 len) | 1206 | u64 start, u64 len) |
1145 | { | 1207 | { |
@@ -1150,12 +1212,17 @@ int f2fs_fiemap(struct inode *inode, struct fiemap_extent_info *fieinfo, | |||
1150 | u32 flags = 0; | 1212 | u32 flags = 0; |
1151 | int ret = 0; | 1213 | int ret = 0; |
1152 | 1214 | ||
1153 | ret = fiemap_check_flags(fieinfo, FIEMAP_FLAG_SYNC); | 1215 | ret = fiemap_check_flags(fieinfo, FIEMAP_FLAG_SYNC | FIEMAP_FLAG_XATTR); |
1154 | if (ret) | 1216 | if (ret) |
1155 | return ret; | 1217 | return ret; |
1156 | 1218 | ||
1157 | inode_lock(inode); | 1219 | inode_lock(inode); |
1158 | 1220 | ||
1221 | if (fieinfo->fi_flags & FIEMAP_FLAG_XATTR) { | ||
1222 | ret = f2fs_xattr_fiemap(inode, fieinfo); | ||
1223 | goto out; | ||
1224 | } | ||
1225 | |||
1159 | if (f2fs_has_inline_data(inode)) { | 1226 | if (f2fs_has_inline_data(inode)) { |
1160 | ret = f2fs_inline_data_fiemap(inode, fieinfo, start, len); | 1227 | ret = f2fs_inline_data_fiemap(inode, fieinfo, start, len); |
1161 | if (ret != -EAGAIN) | 1228 | if (ret != -EAGAIN) |