diff options
Diffstat (limited to 'fs/xfs')
-rw-r--r-- | fs/xfs/xfs_bmap.c | 50 |
1 files changed, 40 insertions, 10 deletions
diff --git a/fs/xfs/xfs_bmap.c b/fs/xfs/xfs_bmap.c index 94b5c5fe2681..aa19e1fee11f 100644 --- a/fs/xfs/xfs_bmap.c +++ b/fs/xfs/xfs_bmap.c | |||
@@ -5743,6 +5743,39 @@ error0: | |||
5743 | } | 5743 | } |
5744 | 5744 | ||
5745 | /* | 5745 | /* |
5746 | * returns 1 for success, 0 if we failed to map the extent. | ||
5747 | */ | ||
5748 | STATIC int | ||
5749 | xfs_getbmapx_fix_eof_hole( | ||
5750 | xfs_inode_t *ip, /* xfs incore inode pointer */ | ||
5751 | struct getbmap *out, /* output structure */ | ||
5752 | int prealloced, /* this is a file with | ||
5753 | * preallocated data space */ | ||
5754 | __int64_t end, /* last block requested */ | ||
5755 | xfs_fsblock_t startblock) | ||
5756 | { | ||
5757 | __int64_t fixlen; | ||
5758 | xfs_mount_t *mp; /* file system mount point */ | ||
5759 | |||
5760 | if (startblock == HOLESTARTBLOCK) { | ||
5761 | mp = ip->i_mount; | ||
5762 | out->bmv_block = -1; | ||
5763 | fixlen = XFS_FSB_TO_BB(mp, XFS_B_TO_FSB(mp, ip->i_size)); | ||
5764 | fixlen -= out->bmv_offset; | ||
5765 | if (prealloced && out->bmv_offset + out->bmv_length == end) { | ||
5766 | /* Came to hole at EOF. Trim it. */ | ||
5767 | if (fixlen <= 0) | ||
5768 | return 0; | ||
5769 | out->bmv_length = fixlen; | ||
5770 | } | ||
5771 | } else { | ||
5772 | out->bmv_block = XFS_FSB_TO_DB(ip, startblock); | ||
5773 | } | ||
5774 | |||
5775 | return 1; | ||
5776 | } | ||
5777 | |||
5778 | /* | ||
5746 | * Fcntl interface to xfs_bmapi. | 5779 | * Fcntl interface to xfs_bmapi. |
5747 | */ | 5780 | */ |
5748 | int /* error code */ | 5781 | int /* error code */ |
@@ -5904,18 +5937,15 @@ xfs_getbmap( | |||
5904 | out.bmv_length = XFS_FSB_TO_BB(mp, map[i].br_blockcount); | 5937 | out.bmv_length = XFS_FSB_TO_BB(mp, map[i].br_blockcount); |
5905 | ASSERT(map[i].br_startblock != DELAYSTARTBLOCK); | 5938 | ASSERT(map[i].br_startblock != DELAYSTARTBLOCK); |
5906 | if (map[i].br_startblock == HOLESTARTBLOCK && | 5939 | if (map[i].br_startblock == HOLESTARTBLOCK && |
5907 | ((prealloced && out.bmv_offset + out.bmv_length == bmvend) || | 5940 | whichfork == XFS_ATTR_FORK) { |
5908 | whichfork == XFS_ATTR_FORK )) { | 5941 | /* came to the end of attribute fork */ |
5909 | /* | ||
5910 | * came to hole at end of file or the end of | ||
5911 | attribute fork | ||
5912 | */ | ||
5913 | goto unlock_and_return; | 5942 | goto unlock_and_return; |
5914 | } else { | 5943 | } else { |
5915 | out.bmv_block = | 5944 | if (!xfs_getbmapx_fix_eof_hole(ip, &out, |
5916 | (map[i].br_startblock == HOLESTARTBLOCK) ? | 5945 | prealloced, bmvend, |
5917 | -1 : | 5946 | map[i].br_startblock)) { |
5918 | XFS_FSB_TO_DB(ip, map[i].br_startblock); | 5947 | goto unlock_and_return; |
5948 | } | ||
5919 | 5949 | ||
5920 | /* return either getbmap/getbmapx structure. */ | 5950 | /* return either getbmap/getbmapx structure. */ |
5921 | if (interface & BMV_IF_EXTENDED) { | 5951 | if (interface & BMV_IF_EXTENDED) { |