.. | .. |
---|
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; |
---|