aboutsummaryrefslogtreecommitdiffstats
path: root/fs/xfs
diff options
context:
space:
mode:
authorChristoph Hellwig <hch@lst.de>2016-08-16 18:45:30 -0400
committerDave Chinner <david@fromorbit.com>2016-08-16 18:45:30 -0400
commit1d4795e7bde075588c90df2175349bb2251802d5 (patch)
tree109e17dfe043a88227e8cf17745ae46bfe0b9961 /fs/xfs
parentb95a21271b30544a9fb992269d79ed1e1978e023 (diff)
xfs: (re-)implement FIEMAP_FLAG_XATTR
Use a special read-only iomap_ops implementation to support fiemap on the attr fork. Signed-off-by: Christoph Hellwig <hch@lst.de> Reviewed-by: Dave Chinner <dchinner@redhat.com> Signed-off-by: Dave Chinner <david@fromorbit.com>
Diffstat (limited to 'fs/xfs')
-rw-r--r--fs/xfs/xfs_iomap.c45
-rw-r--r--fs/xfs/xfs_iomap.h1
-rw-r--r--fs/xfs/xfs_iops.c9
3 files changed, 54 insertions, 1 deletions
diff --git a/fs/xfs/xfs_iomap.c b/fs/xfs/xfs_iomap.c
index 1cce760399a2..697c8fd4200f 100644
--- a/fs/xfs/xfs_iomap.c
+++ b/fs/xfs/xfs_iomap.c
@@ -1106,3 +1106,48 @@ struct iomap_ops xfs_iomap_ops = {
1106 .iomap_begin = xfs_file_iomap_begin, 1106 .iomap_begin = xfs_file_iomap_begin,
1107 .iomap_end = xfs_file_iomap_end, 1107 .iomap_end = xfs_file_iomap_end,
1108}; 1108};
1109
1110static int
1111xfs_xattr_iomap_begin(
1112 struct inode *inode,
1113 loff_t offset,
1114 loff_t length,
1115 unsigned flags,
1116 struct iomap *iomap)
1117{
1118 struct xfs_inode *ip = XFS_I(inode);
1119 struct xfs_mount *mp = ip->i_mount;
1120 xfs_fileoff_t offset_fsb = XFS_B_TO_FSBT(mp, offset);
1121 xfs_fileoff_t end_fsb = XFS_B_TO_FSB(mp, offset + length);
1122 struct xfs_bmbt_irec imap;
1123 int nimaps = 1, error = 0;
1124 unsigned lockmode;
1125
1126 if (XFS_FORCED_SHUTDOWN(mp))
1127 return -EIO;
1128
1129 lockmode = xfs_ilock_data_map_shared(ip);
1130
1131 /* if there are no attribute fork or extents, return ENOENT */
1132 if (XFS_IFORK_Q(ip) || !ip->i_d.di_anextents) {
1133 error = -ENOENT;
1134 goto out_unlock;
1135 }
1136
1137 ASSERT(ip->i_d.di_aformat != XFS_DINODE_FMT_LOCAL);
1138 error = xfs_bmapi_read(ip, offset_fsb, end_fsb - offset_fsb, &imap,
1139 &nimaps, XFS_BMAPI_ENTIRE | XFS_BMAPI_ATTRFORK);
1140out_unlock:
1141 xfs_iunlock(ip, lockmode);
1142
1143 if (!error) {
1144 ASSERT(nimaps);
1145 xfs_bmbt_to_iomap(ip, iomap, &imap);
1146 }
1147
1148 return error;
1149}
1150
1151struct iomap_ops xfs_xattr_iomap_ops = {
1152 .iomap_begin = xfs_xattr_iomap_begin,
1153};
diff --git a/fs/xfs/xfs_iomap.h b/fs/xfs/xfs_iomap.h
index e066d045e2ff..fb8aca3d69ab 100644
--- a/fs/xfs/xfs_iomap.h
+++ b/fs/xfs/xfs_iomap.h
@@ -35,5 +35,6 @@ void xfs_bmbt_to_iomap(struct xfs_inode *, struct iomap *,
35 struct xfs_bmbt_irec *); 35 struct xfs_bmbt_irec *);
36 36
37extern struct iomap_ops xfs_iomap_ops; 37extern struct iomap_ops xfs_iomap_ops;
38extern struct iomap_ops xfs_xattr_iomap_ops;
38 39
39#endif /* __XFS_IOMAP_H__*/ 40#endif /* __XFS_IOMAP_H__*/
diff --git a/fs/xfs/xfs_iops.c b/fs/xfs/xfs_iops.c
index ab820f84ed50..b24c3102fa93 100644
--- a/fs/xfs/xfs_iops.c
+++ b/fs/xfs/xfs_iops.c
@@ -1009,7 +1009,14 @@ xfs_vn_fiemap(
1009 int error; 1009 int error;
1010 1010
1011 xfs_ilock(XFS_I(inode), XFS_IOLOCK_SHARED); 1011 xfs_ilock(XFS_I(inode), XFS_IOLOCK_SHARED);
1012 error = iomap_fiemap(inode, fieinfo, start, length, &xfs_iomap_ops); 1012 if (fieinfo->fi_flags & FIEMAP_FLAG_XATTR) {
1013 fieinfo->fi_flags &= ~FIEMAP_FLAG_XATTR;
1014 error = iomap_fiemap(inode, fieinfo, start, length,
1015 &xfs_xattr_iomap_ops);
1016 } else {
1017 error = iomap_fiemap(inode, fieinfo, start, length,
1018 &xfs_iomap_ops);
1019 }
1013 xfs_iunlock(XFS_I(inode), XFS_IOLOCK_SHARED); 1020 xfs_iunlock(XFS_I(inode), XFS_IOLOCK_SHARED);
1014 1021
1015 return error; 1022 return error;