| .. | .. |
|---|
| 4 | 4 | * All Rights Reserved. |
|---|
| 5 | 5 | */ |
|---|
| 6 | 6 | #include "xfs.h" |
|---|
| 7 | +#include "xfs_shared.h" |
|---|
| 7 | 8 | #include "xfs_format.h" |
|---|
| 8 | 9 | #include "xfs_log_format.h" |
|---|
| 9 | 10 | #include "xfs_trans_resv.h" |
|---|
| 10 | 11 | #include "xfs_sb.h" |
|---|
| 11 | 12 | #include "xfs_mount.h" |
|---|
| 12 | | -#include "xfs_quota.h" |
|---|
| 13 | | -#include "xfs_inode.h" |
|---|
| 14 | 13 | #include "xfs_btree.h" |
|---|
| 15 | 14 | #include "xfs_alloc_btree.h" |
|---|
| 16 | 15 | #include "xfs_alloc.h" |
|---|
| 16 | +#include "xfs_discard.h" |
|---|
| 17 | 17 | #include "xfs_error.h" |
|---|
| 18 | 18 | #include "xfs_extent_busy.h" |
|---|
| 19 | | -#include "xfs_discard.h" |
|---|
| 20 | 19 | #include "xfs_trace.h" |
|---|
| 21 | 20 | #include "xfs_log.h" |
|---|
| 22 | 21 | |
|---|
| .. | .. |
|---|
| 32 | 31 | struct block_device *bdev = mp->m_ddev_targp->bt_bdev; |
|---|
| 33 | 32 | struct xfs_btree_cur *cur; |
|---|
| 34 | 33 | struct xfs_buf *agbp; |
|---|
| 34 | + struct xfs_agf *agf; |
|---|
| 35 | 35 | struct xfs_perag *pag; |
|---|
| 36 | 36 | int error; |
|---|
| 37 | 37 | int i; |
|---|
| .. | .. |
|---|
| 46 | 46 | xfs_log_force(mp, XFS_LOG_SYNC); |
|---|
| 47 | 47 | |
|---|
| 48 | 48 | error = xfs_alloc_read_agf(mp, NULL, agno, 0, &agbp); |
|---|
| 49 | | - if (error || !agbp) |
|---|
| 49 | + if (error) |
|---|
| 50 | 50 | goto out_put_perag; |
|---|
| 51 | + agf = agbp->b_addr; |
|---|
| 51 | 52 | |
|---|
| 52 | 53 | cur = xfs_allocbt_init_cursor(mp, NULL, agbp, agno, XFS_BTNUM_CNT); |
|---|
| 53 | 54 | |
|---|
| 54 | 55 | /* |
|---|
| 55 | 56 | * Look up the longest btree in the AGF and start with it. |
|---|
| 56 | 57 | */ |
|---|
| 57 | | - error = xfs_alloc_lookup_ge(cur, 0, |
|---|
| 58 | | - be32_to_cpu(XFS_BUF_TO_AGF(agbp)->agf_longest), &i); |
|---|
| 58 | + error = xfs_alloc_lookup_ge(cur, 0, be32_to_cpu(agf->agf_longest), &i); |
|---|
| 59 | 59 | if (error) |
|---|
| 60 | 60 | goto out_del_cursor; |
|---|
| 61 | 61 | |
|---|
| .. | .. |
|---|
| 72 | 72 | error = xfs_alloc_get_rec(cur, &fbno, &flen, &i); |
|---|
| 73 | 73 | if (error) |
|---|
| 74 | 74 | goto out_del_cursor; |
|---|
| 75 | | - XFS_WANT_CORRUPTED_GOTO(mp, i == 1, out_del_cursor); |
|---|
| 76 | | - ASSERT(flen <= be32_to_cpu(XFS_BUF_TO_AGF(agbp)->agf_longest)); |
|---|
| 75 | + if (XFS_IS_CORRUPT(mp, i != 1)) { |
|---|
| 76 | + error = -EFSCORRUPTED; |
|---|
| 77 | + goto out_del_cursor; |
|---|
| 78 | + } |
|---|
| 79 | + ASSERT(flen <= be32_to_cpu(agf->agf_longest)); |
|---|
| 77 | 80 | |
|---|
| 78 | 81 | /* |
|---|
| 79 | 82 | * use daddr format for all range/len calculations as that is |
|---|
| .. | .. |
|---|
| 161 | 164 | return -EPERM; |
|---|
| 162 | 165 | if (!blk_queue_discard(q)) |
|---|
| 163 | 166 | return -EOPNOTSUPP; |
|---|
| 167 | + |
|---|
| 168 | + /* |
|---|
| 169 | + * We haven't recovered the log, so we cannot use our bnobt-guided |
|---|
| 170 | + * storage zapping commands. |
|---|
| 171 | + */ |
|---|
| 172 | + if (mp->m_flags & XFS_MOUNT_NORECOVERY) |
|---|
| 173 | + return -EROFS; |
|---|
| 174 | + |
|---|
| 164 | 175 | if (copy_from_user(&range, urange, sizeof(range))) |
|---|
| 165 | 176 | return -EFAULT; |
|---|
| 166 | 177 | |
|---|
| 178 | + range.minlen = max_t(u64, granularity, range.minlen); |
|---|
| 179 | + minlen = BTOBB(range.minlen); |
|---|
| 167 | 180 | /* |
|---|
| 168 | 181 | * Truncating down the len isn't actually quite correct, but using |
|---|
| 169 | 182 | * BBTOB would mean we trivially get overflows for values |
|---|
| .. | .. |
|---|
| 178 | 191 | |
|---|
| 179 | 192 | start = BTOBB(range.start); |
|---|
| 180 | 193 | end = start + BTOBBT(range.len) - 1; |
|---|
| 181 | | - minlen = BTOBB(max_t(u64, granularity, range.minlen)); |
|---|
| 182 | 194 | |
|---|
| 183 | 195 | if (end > XFS_FSB_TO_BB(mp, mp->m_sb.sb_dblocks) - 1) |
|---|
| 184 | 196 | end = XFS_FSB_TO_BB(mp, mp->m_sb.sb_dblocks)- 1; |
|---|