aboutsummaryrefslogtreecommitdiffstats
path: root/fs/gfs2
diff options
context:
space:
mode:
authorSteven Whitehouse <swhiteho@redhat.com>2008-10-14 09:43:29 -0400
committerSteven Whitehouse <swhiteho@redhat.com>2009-01-05 02:38:46 -0500
commite9079cce201784632aed4b1a3121ee38c1ced0b6 (patch)
tree6d99fc45afb3889e5835d713948226d7548d6750 /fs/gfs2
parentfe0bdec68b77020281dc814805edfe594ae89e0f (diff)
GFS2: Support for FIEMAP ioctl
This patch implements the FIEMAP ioctl for GFS2. We can use the generic code (aside from a lock order issue, solved as per Ted Tso's suggestion) for which I've introduced a new variant of the generic function. We also have one exception to deal with, namely stuffed files, so we do that "by hand", setting all the required flags. This has been tested with a modified (I could only find an old version) of Eric's test program, and appears to work correctly. This patch does not currently support FIEMAP of xattrs, but the plan is to add that feature at some future point. Signed-off-by: Steven Whitehouse <swhiteho@redhat.com> Cc: Theodore Tso <tytso@mit.edu> Cc: Eric Sandeen <sandeen@redhat.com>
Diffstat (limited to 'fs/gfs2')
-rw-r--r--fs/gfs2/ops_inode.c46
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
1216static 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);
1253out:
1254 mutex_unlock(&inode->i_mutex);
1255 return ret;
1256}
1257
1215const struct inode_operations gfs2_file_iops = { 1258const 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
1225const struct inode_operations gfs2_dir_iops = { 1269const 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
1244const struct inode_operations gfs2_symlink_iops = { 1289const 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