diff options
author | Eric Sandeen <sandeen@sandeen.net> | 2008-11-27 22:23:35 -0500 |
---|---|---|
committer | Niv Sardi <xaiki@sgi.com> | 2008-11-30 19:29:00 -0500 |
commit | 8a7141a8b931d60d42830432b82078cd6dace83b (patch) | |
tree | e5f1f2573b7e759e8d04b39757c1491689037485 /fs/xfs/xfs_bmap.c | |
parent | 0924b585fc49bf371bc700c23e516a538bf589af (diff) |
[XFS] convert xfs_getbmap to take formatter functions
Preliminary work to hook up fiemap, this allows us to pass in an
arbitrary formatter to copy extent data back to userspace.
The formatter takes info for 1 extent, a pointer to the user "thing*"
and a pointer to a "filled" variable to indicate whether a userspace
buffer did get filled in (for fiemap, hole "extents" are skipped).
I'm just using the getbmapx struct as a "common denominator" because
as far as I can see, it holds all info that any formatters will care
about.
("*thing" because fiemap doesn't pass the user pointer around, but rather
has a pointer to a fiemap info structure, and helpers associated with it)
Signed-off-by: Eric Sandeen <sandeen@sandeen.net>
Reviewed-by: Christoph Hellwig <hch@lst.de>
Signed-off-by: Niv Sardi <xaiki@sgi.com>
Diffstat (limited to 'fs/xfs/xfs_bmap.c')
-rw-r--r-- | fs/xfs/xfs_bmap.c | 62 |
1 files changed, 25 insertions, 37 deletions
diff --git a/fs/xfs/xfs_bmap.c b/fs/xfs/xfs_bmap.c index c3912213645c..8077580a7199 100644 --- a/fs/xfs/xfs_bmap.c +++ b/fs/xfs/xfs_bmap.c | |||
@@ -5811,9 +5811,9 @@ error0: | |||
5811 | STATIC int | 5811 | STATIC int |
5812 | xfs_getbmapx_fix_eof_hole( | 5812 | xfs_getbmapx_fix_eof_hole( |
5813 | xfs_inode_t *ip, /* xfs incore inode pointer */ | 5813 | xfs_inode_t *ip, /* xfs incore inode pointer */ |
5814 | struct getbmap *out, /* output structure */ | 5814 | struct getbmapx *out, /* output structure */ |
5815 | int prealloced, /* this is a file with | 5815 | int prealloced, /* this is a file with |
5816 | * preallocated data space */ | 5816 | * preallocated data space */ |
5817 | __int64_t end, /* last block requested */ | 5817 | __int64_t end, /* last block requested */ |
5818 | xfs_fsblock_t startblock) | 5818 | xfs_fsblock_t startblock) |
5819 | { | 5819 | { |
@@ -5839,14 +5839,18 @@ xfs_getbmapx_fix_eof_hole( | |||
5839 | } | 5839 | } |
5840 | 5840 | ||
5841 | /* | 5841 | /* |
5842 | * Fcntl interface to xfs_bmapi. | 5842 | * Get inode's extents as described in bmv, and format for output. |
5843 | * Calls formatter to fill the user's buffer until all extents | ||
5844 | * are mapped, until the passed-in bmv->bmv_count slots have | ||
5845 | * been filled, or until the formatter short-circuits the loop, | ||
5846 | * if it is tracking filled-in extents on its own. | ||
5843 | */ | 5847 | */ |
5844 | int /* error code */ | 5848 | int /* error code */ |
5845 | xfs_getbmap( | 5849 | xfs_getbmap( |
5846 | xfs_inode_t *ip, | 5850 | xfs_inode_t *ip, |
5847 | struct getbmap *bmv, /* user bmap structure */ | 5851 | struct getbmapx *bmv, /* user bmap structure */ |
5848 | void __user *ap, /* pointer to user's array */ | 5852 | xfs_bmap_format_t formatter, /* format to user */ |
5849 | int interface) /* interface flags */ | 5853 | void *arg) /* formatter arg */ |
5850 | { | 5854 | { |
5851 | __int64_t bmvend; /* last block requested */ | 5855 | __int64_t bmvend; /* last block requested */ |
5852 | int error; /* return value */ | 5856 | int error; /* return value */ |
@@ -5859,19 +5863,20 @@ xfs_getbmap( | |||
5859 | int nexleft; /* # of user extents left */ | 5863 | int nexleft; /* # of user extents left */ |
5860 | int subnex; /* # of bmapi's can do */ | 5864 | int subnex; /* # of bmapi's can do */ |
5861 | int nmap; /* number of map entries */ | 5865 | int nmap; /* number of map entries */ |
5862 | struct getbmap out; /* output structure */ | 5866 | struct getbmapx out; /* output structure */ |
5863 | int whichfork; /* data or attr fork */ | 5867 | int whichfork; /* data or attr fork */ |
5864 | int prealloced; /* this is a file with | 5868 | int prealloced; /* this is a file with |
5865 | * preallocated data space */ | 5869 | * preallocated data space */ |
5866 | int sh_unwritten; /* true, if unwritten */ | 5870 | int sh_unwritten; /* true, if unwritten */ |
5867 | /* extents listed separately */ | 5871 | /* extents listed separately */ |
5872 | int iflags; /* interface flags */ | ||
5868 | int bmapi_flags; /* flags for xfs_bmapi */ | 5873 | int bmapi_flags; /* flags for xfs_bmapi */ |
5869 | __int32_t oflags; /* getbmapx bmv_oflags field */ | ||
5870 | 5874 | ||
5871 | mp = ip->i_mount; | 5875 | mp = ip->i_mount; |
5876 | iflags = bmv->bmv_iflags; | ||
5872 | 5877 | ||
5873 | whichfork = interface & BMV_IF_ATTRFORK ? XFS_ATTR_FORK : XFS_DATA_FORK; | 5878 | whichfork = iflags & BMV_IF_ATTRFORK ? XFS_ATTR_FORK : XFS_DATA_FORK; |
5874 | sh_unwritten = (interface & BMV_IF_PREALLOC) != 0; | 5879 | sh_unwritten = (iflags & BMV_IF_PREALLOC) != 0; |
5875 | 5880 | ||
5876 | /* If the BMV_IF_NO_DMAPI_READ interface bit specified, do not | 5881 | /* If the BMV_IF_NO_DMAPI_READ interface bit specified, do not |
5877 | * generate a DMAPI read event. Otherwise, if the DM_EVENT_READ | 5882 | * generate a DMAPI read event. Otherwise, if the DM_EVENT_READ |
@@ -5886,7 +5891,7 @@ xfs_getbmap( | |||
5886 | * could misinterpret holes in a DMAPI file as true holes, | 5891 | * could misinterpret holes in a DMAPI file as true holes, |
5887 | * when in fact they may represent offline user data. | 5892 | * when in fact they may represent offline user data. |
5888 | */ | 5893 | */ |
5889 | if ((interface & BMV_IF_NO_DMAPI_READ) == 0 && | 5894 | if ((iflags & BMV_IF_NO_DMAPI_READ) == 0 && |
5890 | DM_EVENT_ENABLED(ip, DM_EVENT_READ) && | 5895 | DM_EVENT_ENABLED(ip, DM_EVENT_READ) && |
5891 | whichfork == XFS_DATA_FORK) { | 5896 | whichfork == XFS_DATA_FORK) { |
5892 | error = XFS_SEND_DATA(mp, DM_EVENT_READ, ip, 0, 0, 0, NULL); | 5897 | error = XFS_SEND_DATA(mp, DM_EVENT_READ, ip, 0, 0, 0, NULL); |
@@ -5993,52 +5998,35 @@ xfs_getbmap( | |||
5993 | ASSERT(nmap <= subnex); | 5998 | ASSERT(nmap <= subnex); |
5994 | 5999 | ||
5995 | for (i = 0; i < nmap && nexleft && bmv->bmv_length; i++) { | 6000 | for (i = 0; i < nmap && nexleft && bmv->bmv_length; i++) { |
5996 | nexleft--; | 6001 | out.bmv_oflags = (map[i].br_state == XFS_EXT_UNWRITTEN) ? |
5997 | oflags = (map[i].br_state == XFS_EXT_UNWRITTEN) ? | ||
5998 | BMV_OF_PREALLOC : 0; | 6002 | BMV_OF_PREALLOC : 0; |
5999 | out.bmv_offset = XFS_FSB_TO_BB(mp, map[i].br_startoff); | 6003 | out.bmv_offset = XFS_FSB_TO_BB(mp, map[i].br_startoff); |
6000 | out.bmv_length = XFS_FSB_TO_BB(mp, map[i].br_blockcount); | 6004 | out.bmv_length = XFS_FSB_TO_BB(mp, map[i].br_blockcount); |
6005 | out.bmv_unused1 = out.bmv_unused2 = 0; | ||
6001 | ASSERT(map[i].br_startblock != DELAYSTARTBLOCK); | 6006 | ASSERT(map[i].br_startblock != DELAYSTARTBLOCK); |
6002 | if (map[i].br_startblock == HOLESTARTBLOCK && | 6007 | if (map[i].br_startblock == HOLESTARTBLOCK && |
6003 | whichfork == XFS_ATTR_FORK) { | 6008 | whichfork == XFS_ATTR_FORK) { |
6004 | /* came to the end of attribute fork */ | 6009 | /* came to the end of attribute fork */ |
6005 | goto unlock_and_return; | 6010 | goto unlock_and_return; |
6006 | } else { | 6011 | } else { |
6012 | int full = 0; /* user array is full */ | ||
6013 | |||
6007 | if (!xfs_getbmapx_fix_eof_hole(ip, &out, | 6014 | if (!xfs_getbmapx_fix_eof_hole(ip, &out, |
6008 | prealloced, bmvend, | 6015 | prealloced, bmvend, |
6009 | map[i].br_startblock)) { | 6016 | map[i].br_startblock)) { |
6010 | goto unlock_and_return; | 6017 | goto unlock_and_return; |
6011 | } | 6018 | } |
6012 | 6019 | ||
6013 | /* return either getbmap/getbmapx structure. */ | 6020 | /* format results & advance arg */ |
6014 | if (interface & BMV_IF_EXTENDED) { | 6021 | error = formatter(&arg, &out, &full); |
6015 | struct getbmapx outx; | 6022 | if (error || full) |
6016 | 6023 | goto unlock_and_return; | |
6017 | GETBMAP_CONVERT(out,outx); | 6024 | nexleft--; |
6018 | outx.bmv_oflags = oflags; | ||
6019 | outx.bmv_unused1 = outx.bmv_unused2 = 0; | ||
6020 | if (copy_to_user(ap, &outx, | ||
6021 | sizeof(outx))) { | ||
6022 | error = XFS_ERROR(EFAULT); | ||
6023 | goto unlock_and_return; | ||
6024 | } | ||
6025 | } else { | ||
6026 | if (copy_to_user(ap, &out, | ||
6027 | sizeof(out))) { | ||
6028 | error = XFS_ERROR(EFAULT); | ||
6029 | goto unlock_and_return; | ||
6030 | } | ||
6031 | } | ||
6032 | bmv->bmv_offset = | 6025 | bmv->bmv_offset = |
6033 | out.bmv_offset + out.bmv_length; | 6026 | out.bmv_offset + out.bmv_length; |
6034 | bmv->bmv_length = MAX((__int64_t)0, | 6027 | bmv->bmv_length = MAX((__int64_t)0, |
6035 | (__int64_t)(bmvend - bmv->bmv_offset)); | 6028 | (__int64_t)(bmvend - bmv->bmv_offset)); |
6036 | bmv->bmv_entries++; | 6029 | bmv->bmv_entries++; |
6037 | ap = (interface & BMV_IF_EXTENDED) ? | ||
6038 | (void __user *) | ||
6039 | ((struct getbmapx __user *)ap + 1) : | ||
6040 | (void __user *) | ||
6041 | ((struct getbmap __user *)ap + 1); | ||
6042 | } | 6030 | } |
6043 | } | 6031 | } |
6044 | } while (nmap && nexleft && bmv->bmv_length); | 6032 | } while (nmap && nexleft && bmv->bmv_length); |