Commit 1d4795e7 authored by Christoph Hellwig's avatar Christoph Hellwig Committed by Dave Chinner

xfs: (re-)implement FIEMAP_FLAG_XATTR

Use a special read-only iomap_ops implementation to support fiemap on
the attr fork.
Signed-off-by: default avatarChristoph Hellwig <hch@lst.de>
Reviewed-by: default avatarDave Chinner <dchinner@redhat.com>
Signed-off-by: default avatarDave Chinner <david@fromorbit.com>
parent b95a2127
...@@ -1106,3 +1106,48 @@ struct iomap_ops xfs_iomap_ops = { ...@@ -1106,3 +1106,48 @@ struct iomap_ops xfs_iomap_ops = {
.iomap_begin = xfs_file_iomap_begin, .iomap_begin = xfs_file_iomap_begin,
.iomap_end = xfs_file_iomap_end, .iomap_end = xfs_file_iomap_end,
}; };
static int
xfs_xattr_iomap_begin(
struct inode *inode,
loff_t offset,
loff_t length,
unsigned flags,
struct iomap *iomap)
{
struct xfs_inode *ip = XFS_I(inode);
struct xfs_mount *mp = ip->i_mount;
xfs_fileoff_t offset_fsb = XFS_B_TO_FSBT(mp, offset);
xfs_fileoff_t end_fsb = XFS_B_TO_FSB(mp, offset + length);
struct xfs_bmbt_irec imap;
int nimaps = 1, error = 0;
unsigned lockmode;
if (XFS_FORCED_SHUTDOWN(mp))
return -EIO;
lockmode = xfs_ilock_data_map_shared(ip);
/* if there are no attribute fork or extents, return ENOENT */
if (XFS_IFORK_Q(ip) || !ip->i_d.di_anextents) {
error = -ENOENT;
goto out_unlock;
}
ASSERT(ip->i_d.di_aformat != XFS_DINODE_FMT_LOCAL);
error = xfs_bmapi_read(ip, offset_fsb, end_fsb - offset_fsb, &imap,
&nimaps, XFS_BMAPI_ENTIRE | XFS_BMAPI_ATTRFORK);
out_unlock:
xfs_iunlock(ip, lockmode);
if (!error) {
ASSERT(nimaps);
xfs_bmbt_to_iomap(ip, iomap, &imap);
}
return error;
}
struct iomap_ops xfs_xattr_iomap_ops = {
.iomap_begin = xfs_xattr_iomap_begin,
};
...@@ -35,5 +35,6 @@ void xfs_bmbt_to_iomap(struct xfs_inode *, struct iomap *, ...@@ -35,5 +35,6 @@ void xfs_bmbt_to_iomap(struct xfs_inode *, struct iomap *,
struct xfs_bmbt_irec *); struct xfs_bmbt_irec *);
extern struct iomap_ops xfs_iomap_ops; extern struct iomap_ops xfs_iomap_ops;
extern struct iomap_ops xfs_xattr_iomap_ops;
#endif /* __XFS_IOMAP_H__*/ #endif /* __XFS_IOMAP_H__*/
...@@ -1009,7 +1009,14 @@ xfs_vn_fiemap( ...@@ -1009,7 +1009,14 @@ xfs_vn_fiemap(
int error; int error;
xfs_ilock(XFS_I(inode), XFS_IOLOCK_SHARED); xfs_ilock(XFS_I(inode), XFS_IOLOCK_SHARED);
error = iomap_fiemap(inode, fieinfo, start, length, &xfs_iomap_ops); if (fieinfo->fi_flags & FIEMAP_FLAG_XATTR) {
fieinfo->fi_flags &= ~FIEMAP_FLAG_XATTR;
error = iomap_fiemap(inode, fieinfo, start, length,
&xfs_xattr_iomap_ops);
} else {
error = iomap_fiemap(inode, fieinfo, start, length,
&xfs_iomap_ops);
}
xfs_iunlock(XFS_I(inode), XFS_IOLOCK_SHARED); xfs_iunlock(XFS_I(inode), XFS_IOLOCK_SHARED);
return error; return error;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment