Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

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>

authored by

Chao Yu and committed by
Jaegeuk Kim
442a9dbd f1b43d4c

+68 -1
+68 -1
fs/f2fs/data.c
··· 1140 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 1205 int f2fs_fiemap(struct inode *inode, struct fiemap_extent_info *fieinfo, 1144 1206 u64 start, u64 len) 1145 1207 { ··· 1212 1150 u32 flags = 0; 1213 1151 int ret = 0; 1214 1152 1215 - ret = fiemap_check_flags(fieinfo, FIEMAP_FLAG_SYNC); 1153 + ret = fiemap_check_flags(fieinfo, FIEMAP_FLAG_SYNC | FIEMAP_FLAG_XATTR); 1216 1154 if (ret) 1217 1155 return ret; 1218 1156 1219 1157 inode_lock(inode); 1158 + 1159 + if (fieinfo->fi_flags & FIEMAP_FLAG_XATTR) { 1160 + ret = f2fs_xattr_fiemap(inode, fieinfo); 1161 + goto out; 1162 + } 1220 1163 1221 1164 if (f2fs_has_inline_data(inode)) { 1222 1165 ret = f2fs_inline_data_fiemap(inode, fieinfo, start, len);