diff options
| -rw-r--r-- | fs/xfs/xfs_bmap.c | 52 |
1 files changed, 35 insertions, 17 deletions
diff --git a/fs/xfs/xfs_bmap.c b/fs/xfs/xfs_bmap.c index abe42448b1c0..ca7c6005a487 100644 --- a/fs/xfs/xfs_bmap.c +++ b/fs/xfs/xfs_bmap.c | |||
| @@ -5890,12 +5890,13 @@ xfs_getbmap( | |||
| 5890 | int nexleft; /* # of user extents left */ | 5890 | int nexleft; /* # of user extents left */ |
| 5891 | int subnex; /* # of bmapi's can do */ | 5891 | int subnex; /* # of bmapi's can do */ |
| 5892 | int nmap; /* number of map entries */ | 5892 | int nmap; /* number of map entries */ |
| 5893 | struct getbmapx out; /* output structure */ | 5893 | struct getbmapx *out; /* output structure */ |
| 5894 | int whichfork; /* data or attr fork */ | 5894 | int whichfork; /* data or attr fork */ |
| 5895 | int prealloced; /* this is a file with | 5895 | int prealloced; /* this is a file with |
| 5896 | * preallocated data space */ | 5896 | * preallocated data space */ |
| 5897 | int iflags; /* interface flags */ | 5897 | int iflags; /* interface flags */ |
| 5898 | int bmapi_flags; /* flags for xfs_bmapi */ | 5898 | int bmapi_flags; /* flags for xfs_bmapi */ |
| 5899 | int cur_ext = 0; | ||
| 5899 | 5900 | ||
| 5900 | mp = ip->i_mount; | 5901 | mp = ip->i_mount; |
| 5901 | iflags = bmv->bmv_iflags; | 5902 | iflags = bmv->bmv_iflags; |
| @@ -5971,6 +5972,13 @@ xfs_getbmap( | |||
| 5971 | return XFS_ERROR(EINVAL); | 5972 | return XFS_ERROR(EINVAL); |
| 5972 | bmvend = bmv->bmv_offset + bmv->bmv_length; | 5973 | bmvend = bmv->bmv_offset + bmv->bmv_length; |
| 5973 | 5974 | ||
| 5975 | |||
| 5976 | if (bmv->bmv_count > ULONG_MAX / sizeof(struct getbmapx)) | ||
| 5977 | return XFS_ERROR(ENOMEM); | ||
| 5978 | out = kmem_zalloc(bmv->bmv_count * sizeof(struct getbmapx), KM_MAYFAIL); | ||
| 5979 | if (!out) | ||
| 5980 | return XFS_ERROR(ENOMEM); | ||
| 5981 | |||
| 5974 | xfs_ilock(ip, XFS_IOLOCK_SHARED); | 5982 | xfs_ilock(ip, XFS_IOLOCK_SHARED); |
| 5975 | if (whichfork == XFS_DATA_FORK && !(iflags & BMV_IF_DELALLOC)) { | 5983 | if (whichfork == XFS_DATA_FORK && !(iflags & BMV_IF_DELALLOC)) { |
| 5976 | if (ip->i_delayed_blks || ip->i_size > ip->i_d.di_size) { | 5984 | if (ip->i_delayed_blks || ip->i_size > ip->i_d.di_size) { |
| @@ -6025,39 +6033,39 @@ xfs_getbmap( | |||
| 6025 | ASSERT(nmap <= subnex); | 6033 | ASSERT(nmap <= subnex); |
| 6026 | 6034 | ||
| 6027 | for (i = 0; i < nmap && nexleft && bmv->bmv_length; i++) { | 6035 | for (i = 0; i < nmap && nexleft && bmv->bmv_length; i++) { |
| 6028 | int full = 0; /* user array is full */ | 6036 | out[cur_ext].bmv_oflags = 0; |
| 6029 | |||
| 6030 | out.bmv_oflags = 0; | ||
| 6031 | if (map[i].br_state == XFS_EXT_UNWRITTEN) | 6037 | if (map[i].br_state == XFS_EXT_UNWRITTEN) |
| 6032 | out.bmv_oflags |= BMV_OF_PREALLOC; | 6038 | out[cur_ext].bmv_oflags |= BMV_OF_PREALLOC; |
| 6033 | else if (map[i].br_startblock == DELAYSTARTBLOCK) | 6039 | else if (map[i].br_startblock == DELAYSTARTBLOCK) |
| 6034 | out.bmv_oflags |= BMV_OF_DELALLOC; | 6040 | out[cur_ext].bmv_oflags |= BMV_OF_DELALLOC; |
| 6035 | out.bmv_offset = XFS_FSB_TO_BB(mp, map[i].br_startoff); | 6041 | out[cur_ext].bmv_offset = |
| 6036 | out.bmv_length = XFS_FSB_TO_BB(mp, map[i].br_blockcount); | 6042 | XFS_FSB_TO_BB(mp, map[i].br_startoff); |
| 6037 | out.bmv_unused1 = out.bmv_unused2 = 0; | 6043 | out[cur_ext].bmv_length = |
| 6044 | XFS_FSB_TO_BB(mp, map[i].br_blockcount); | ||
| 6045 | out[cur_ext].bmv_unused1 = 0; | ||
| 6046 | out[cur_ext].bmv_unused2 = 0; | ||
| 6038 | ASSERT(((iflags & BMV_IF_DELALLOC) != 0) || | 6047 | ASSERT(((iflags & BMV_IF_DELALLOC) != 0) || |
| 6039 | (map[i].br_startblock != DELAYSTARTBLOCK)); | 6048 | (map[i].br_startblock != DELAYSTARTBLOCK)); |
| 6040 | if (map[i].br_startblock == HOLESTARTBLOCK && | 6049 | if (map[i].br_startblock == HOLESTARTBLOCK && |
| 6041 | whichfork == XFS_ATTR_FORK) { | 6050 | whichfork == XFS_ATTR_FORK) { |
| 6042 | /* came to the end of attribute fork */ | 6051 | /* came to the end of attribute fork */ |
| 6043 | out.bmv_oflags |= BMV_OF_LAST; | 6052 | out[cur_ext].bmv_oflags |= BMV_OF_LAST; |
| 6044 | goto out_free_map; | 6053 | goto out_free_map; |
| 6045 | } | 6054 | } |
| 6046 | 6055 | ||
| 6047 | if (!xfs_getbmapx_fix_eof_hole(ip, &out, prealloced, | 6056 | if (!xfs_getbmapx_fix_eof_hole(ip, &out[cur_ext], |
| 6048 | bmvend, map[i].br_startblock)) | 6057 | prealloced, bmvend, |
| 6058 | map[i].br_startblock)) | ||
| 6049 | goto out_free_map; | 6059 | goto out_free_map; |
| 6050 | 6060 | ||
| 6051 | /* format results & advance arg */ | ||
| 6052 | error = formatter(&arg, &out, &full); | ||
| 6053 | if (error || full) | ||
| 6054 | goto out_free_map; | ||
| 6055 | nexleft--; | 6061 | nexleft--; |
| 6056 | bmv->bmv_offset = | 6062 | bmv->bmv_offset = |
| 6057 | out.bmv_offset + out.bmv_length; | 6063 | out[cur_ext].bmv_offset + |
| 6064 | out[cur_ext].bmv_length; | ||
| 6058 | bmv->bmv_length = | 6065 | bmv->bmv_length = |
| 6059 | max_t(__int64_t, 0, bmvend - bmv->bmv_offset); | 6066 | max_t(__int64_t, 0, bmvend - bmv->bmv_offset); |
| 6060 | bmv->bmv_entries++; | 6067 | bmv->bmv_entries++; |
| 6068 | cur_ext++; | ||
| 6061 | } | 6069 | } |
| 6062 | } while (nmap && nexleft && bmv->bmv_length); | 6070 | } while (nmap && nexleft && bmv->bmv_length); |
| 6063 | 6071 | ||
| @@ -6067,6 +6075,16 @@ xfs_getbmap( | |||
| 6067 | xfs_iunlock_map_shared(ip, lock); | 6075 | xfs_iunlock_map_shared(ip, lock); |
| 6068 | out_unlock_iolock: | 6076 | out_unlock_iolock: |
| 6069 | xfs_iunlock(ip, XFS_IOLOCK_SHARED); | 6077 | xfs_iunlock(ip, XFS_IOLOCK_SHARED); |
| 6078 | |||
| 6079 | for (i = 0; i < cur_ext; i++) { | ||
| 6080 | int full = 0; /* user array is full */ | ||
| 6081 | |||
| 6082 | /* format results & advance arg */ | ||
| 6083 | error = formatter(&arg, &out[i], &full); | ||
| 6084 | if (error || full) | ||
| 6085 | break; | ||
| 6086 | } | ||
| 6087 | |||
| 6070 | return error; | 6088 | return error; |
| 6071 | } | 6089 | } |
| 6072 | 6090 | ||
