diff options
Diffstat (limited to 'fs/gfs2/ops_inode.c')
-rw-r--r-- | fs/gfs2/ops_inode.c | 46 |
1 files changed, 46 insertions, 0 deletions
diff --git a/fs/gfs2/ops_inode.c b/fs/gfs2/ops_inode.c index d232991b9046..1e24b65e1d23 100644 --- a/fs/gfs2/ops_inode.c +++ b/fs/gfs2/ops_inode.c | |||
@@ -19,6 +19,7 @@ | |||
19 | #include <linux/gfs2_ondisk.h> | 19 | #include <linux/gfs2_ondisk.h> |
20 | #include <linux/crc32.h> | 20 | #include <linux/crc32.h> |
21 | #include <linux/lm_interface.h> | 21 | #include <linux/lm_interface.h> |
22 | #include <linux/fiemap.h> | ||
22 | #include <asm/uaccess.h> | 23 | #include <asm/uaccess.h> |
23 | 24 | ||
24 | #include "gfs2.h" | 25 | #include "gfs2.h" |
@@ -1212,6 +1213,48 @@ static int gfs2_removexattr(struct dentry *dentry, const char *name) | |||
1212 | return gfs2_ea_remove(GFS2_I(dentry->d_inode), &er); | 1213 | return gfs2_ea_remove(GFS2_I(dentry->d_inode), &er); |
1213 | } | 1214 | } |
1214 | 1215 | ||
1216 | static int gfs2_fiemap(struct inode *inode, struct fiemap_extent_info *fieinfo, | ||
1217 | u64 start, u64 len) | ||
1218 | { | ||
1219 | struct gfs2_inode *ip = GFS2_I(inode); | ||
1220 | struct gfs2_holder gh; | ||
1221 | int ret; | ||
1222 | |||
1223 | ret = fiemap_check_flags(fieinfo, FIEMAP_FLAG_SYNC); | ||
1224 | if (ret) | ||
1225 | return ret; | ||
1226 | |||
1227 | mutex_lock(&inode->i_mutex); | ||
1228 | |||
1229 | ret = gfs2_glock_nq_init(ip->i_gl, LM_ST_SHARED, 0, &gh); | ||
1230 | if (ret) | ||
1231 | goto out; | ||
1232 | |||
1233 | if (gfs2_is_stuffed(ip)) { | ||
1234 | u64 phys = ip->i_no_addr << inode->i_blkbits; | ||
1235 | u64 size = i_size_read(inode); | ||
1236 | u32 flags = FIEMAP_EXTENT_LAST|FIEMAP_EXTENT_NOT_ALIGNED| | ||
1237 | FIEMAP_EXTENT_DATA_INLINE; | ||
1238 | phys += sizeof(struct gfs2_dinode); | ||
1239 | phys += start; | ||
1240 | if (start + len > size) | ||
1241 | len = size - start; | ||
1242 | if (start < size) | ||
1243 | ret = fiemap_fill_next_extent(fieinfo, start, phys, | ||
1244 | len, flags); | ||
1245 | if (ret == 1) | ||
1246 | ret = 0; | ||
1247 | } else { | ||
1248 | ret = __generic_block_fiemap(inode, fieinfo, start, len, | ||
1249 | gfs2_block_map); | ||
1250 | } | ||
1251 | |||
1252 | gfs2_glock_dq_uninit(&gh); | ||
1253 | out: | ||
1254 | mutex_unlock(&inode->i_mutex); | ||
1255 | return ret; | ||
1256 | } | ||
1257 | |||
1215 | const struct inode_operations gfs2_file_iops = { | 1258 | const struct inode_operations gfs2_file_iops = { |
1216 | .permission = gfs2_permission, | 1259 | .permission = gfs2_permission, |
1217 | .setattr = gfs2_setattr, | 1260 | .setattr = gfs2_setattr, |
@@ -1220,6 +1263,7 @@ const struct inode_operations gfs2_file_iops = { | |||
1220 | .getxattr = gfs2_getxattr, | 1263 | .getxattr = gfs2_getxattr, |
1221 | .listxattr = gfs2_listxattr, | 1264 | .listxattr = gfs2_listxattr, |
1222 | .removexattr = gfs2_removexattr, | 1265 | .removexattr = gfs2_removexattr, |
1266 | .fiemap = gfs2_fiemap, | ||
1223 | }; | 1267 | }; |
1224 | 1268 | ||
1225 | const struct inode_operations gfs2_dir_iops = { | 1269 | const struct inode_operations gfs2_dir_iops = { |
@@ -1239,6 +1283,7 @@ const struct inode_operations gfs2_dir_iops = { | |||
1239 | .getxattr = gfs2_getxattr, | 1283 | .getxattr = gfs2_getxattr, |
1240 | .listxattr = gfs2_listxattr, | 1284 | .listxattr = gfs2_listxattr, |
1241 | .removexattr = gfs2_removexattr, | 1285 | .removexattr = gfs2_removexattr, |
1286 | .fiemap = gfs2_fiemap, | ||
1242 | }; | 1287 | }; |
1243 | 1288 | ||
1244 | const struct inode_operations gfs2_symlink_iops = { | 1289 | const struct inode_operations gfs2_symlink_iops = { |
@@ -1251,5 +1296,6 @@ const struct inode_operations gfs2_symlink_iops = { | |||
1251 | .getxattr = gfs2_getxattr, | 1296 | .getxattr = gfs2_getxattr, |
1252 | .listxattr = gfs2_listxattr, | 1297 | .listxattr = gfs2_listxattr, |
1253 | .removexattr = gfs2_removexattr, | 1298 | .removexattr = gfs2_removexattr, |
1299 | .fiemap = gfs2_fiemap, | ||
1254 | }; | 1300 | }; |
1255 | 1301 | ||