diff options
author | Christoph Hellwig <hch@lst.de> | 2016-08-16 18:45:30 -0400 |
---|---|---|
committer | Dave Chinner <david@fromorbit.com> | 2016-08-16 18:45:30 -0400 |
commit | 1d4795e7bde075588c90df2175349bb2251802d5 (patch) | |
tree | 109e17dfe043a88227e8cf17745ae46bfe0b9961 /fs/xfs | |
parent | b95a21271b30544a9fb992269d79ed1e1978e023 (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.c | 45 | ||||
-rw-r--r-- | fs/xfs/xfs_iomap.h | 1 | ||||
-rw-r--r-- | fs/xfs/xfs_iops.c | 9 |
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 | |||
1110 | static int | ||
1111 | xfs_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); | ||
1140 | out_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 | |||
1151 | struct 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 | ||
37 | extern struct iomap_ops xfs_iomap_ops; | 37 | extern struct iomap_ops xfs_iomap_ops; |
38 | extern 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; |