diff options
Diffstat (limited to 'fs/xfs/xfs_dir2_node.c')
-rw-r--r-- | fs/xfs/xfs_dir2_node.c | 474 |
1 files changed, 323 insertions, 151 deletions
diff --git a/fs/xfs/xfs_dir2_node.c b/fs/xfs/xfs_dir2_node.c index 985d70bc391d..0fe39b9fde7e 100644 --- a/fs/xfs/xfs_dir2_node.c +++ b/fs/xfs/xfs_dir2_node.c | |||
@@ -1,5 +1,6 @@ | |||
1 | /* | 1 | /* |
2 | * Copyright (c) 2000-2005 Silicon Graphics, Inc. | 2 | * Copyright (c) 2000-2005 Silicon Graphics, Inc. |
3 | * Copyright (c) 2013 Red Hat, Inc. | ||
3 | * All Rights Reserved. | 4 | * All Rights Reserved. |
4 | * | 5 | * |
5 | * This program is free software; you can redistribute it and/or | 6 | * This program is free software; you can redistribute it and/or |
@@ -32,6 +33,8 @@ | |||
32 | #include "xfs_dir2_priv.h" | 33 | #include "xfs_dir2_priv.h" |
33 | #include "xfs_error.h" | 34 | #include "xfs_error.h" |
34 | #include "xfs_trace.h" | 35 | #include "xfs_trace.h" |
36 | #include "xfs_buf_item.h" | ||
37 | #include "xfs_cksum.h" | ||
35 | 38 | ||
36 | /* | 39 | /* |
37 | * Function declarations. | 40 | * Function declarations. |
@@ -55,44 +58,78 @@ static int xfs_dir2_leafn_remove(xfs_da_args_t *args, struct xfs_buf *bp, | |||
55 | static int xfs_dir2_node_addname_int(xfs_da_args_t *args, | 58 | static int xfs_dir2_node_addname_int(xfs_da_args_t *args, |
56 | xfs_da_state_blk_t *fblk); | 59 | xfs_da_state_blk_t *fblk); |
57 | 60 | ||
58 | static void | 61 | static bool |
59 | xfs_dir2_free_verify( | 62 | xfs_dir3_free_verify( |
60 | struct xfs_buf *bp) | 63 | struct xfs_buf *bp) |
61 | { | 64 | { |
62 | struct xfs_mount *mp = bp->b_target->bt_mount; | 65 | struct xfs_mount *mp = bp->b_target->bt_mount; |
63 | struct xfs_dir2_free_hdr *hdr = bp->b_addr; | 66 | struct xfs_dir2_free_hdr *hdr = bp->b_addr; |
64 | int block_ok = 0; | ||
65 | 67 | ||
66 | block_ok = hdr->magic == cpu_to_be32(XFS_DIR2_FREE_MAGIC); | 68 | if (xfs_sb_version_hascrc(&mp->m_sb)) { |
67 | if (!block_ok) { | 69 | struct xfs_dir3_blk_hdr *hdr3 = bp->b_addr; |
68 | XFS_CORRUPTION_ERROR("xfs_dir2_free_verify magic", | 70 | |
69 | XFS_ERRLEVEL_LOW, mp, hdr); | 71 | if (hdr3->magic != cpu_to_be32(XFS_DIR3_FREE_MAGIC)) |
70 | xfs_buf_ioerror(bp, EFSCORRUPTED); | 72 | return false; |
73 | if (!uuid_equal(&hdr3->uuid, &mp->m_sb.sb_uuid)) | ||
74 | return false; | ||
75 | if (be64_to_cpu(hdr3->blkno) != bp->b_bn) | ||
76 | return false; | ||
77 | } else { | ||
78 | if (hdr->magic != cpu_to_be32(XFS_DIR2_FREE_MAGIC)) | ||
79 | return false; | ||
71 | } | 80 | } |
81 | |||
82 | /* XXX: should bounds check the xfs_dir3_icfree_hdr here */ | ||
83 | |||
84 | return true; | ||
72 | } | 85 | } |
73 | 86 | ||
74 | static void | 87 | static void |
75 | xfs_dir2_free_read_verify( | 88 | xfs_dir3_free_read_verify( |
76 | struct xfs_buf *bp) | 89 | struct xfs_buf *bp) |
77 | { | 90 | { |
78 | xfs_dir2_free_verify(bp); | 91 | struct xfs_mount *mp = bp->b_target->bt_mount; |
92 | |||
93 | if ((xfs_sb_version_hascrc(&mp->m_sb) && | ||
94 | !xfs_verify_cksum(bp->b_addr, BBTOB(bp->b_length), | ||
95 | XFS_DIR3_FREE_CRC_OFF)) || | ||
96 | !xfs_dir3_free_verify(bp)) { | ||
97 | XFS_CORRUPTION_ERROR(__func__, XFS_ERRLEVEL_LOW, mp, bp->b_addr); | ||
98 | xfs_buf_ioerror(bp, EFSCORRUPTED); | ||
99 | } | ||
79 | } | 100 | } |
80 | 101 | ||
81 | static void | 102 | static void |
82 | xfs_dir2_free_write_verify( | 103 | xfs_dir3_free_write_verify( |
83 | struct xfs_buf *bp) | 104 | struct xfs_buf *bp) |
84 | { | 105 | { |
85 | xfs_dir2_free_verify(bp); | 106 | struct xfs_mount *mp = bp->b_target->bt_mount; |
107 | struct xfs_buf_log_item *bip = bp->b_fspriv; | ||
108 | struct xfs_dir3_blk_hdr *hdr3 = bp->b_addr; | ||
109 | |||
110 | if (!xfs_dir3_free_verify(bp)) { | ||
111 | XFS_CORRUPTION_ERROR(__func__, XFS_ERRLEVEL_LOW, mp, bp->b_addr); | ||
112 | xfs_buf_ioerror(bp, EFSCORRUPTED); | ||
113 | return; | ||
114 | } | ||
115 | |||
116 | if (!xfs_sb_version_hascrc(&mp->m_sb)) | ||
117 | return; | ||
118 | |||
119 | if (bip) | ||
120 | hdr3->lsn = cpu_to_be64(bip->bli_item.li_lsn); | ||
121 | |||
122 | xfs_update_cksum(bp->b_addr, BBTOB(bp->b_length), XFS_DIR3_FREE_CRC_OFF); | ||
86 | } | 123 | } |
87 | 124 | ||
88 | static const struct xfs_buf_ops xfs_dir2_free_buf_ops = { | 125 | static const struct xfs_buf_ops xfs_dir3_free_buf_ops = { |
89 | .verify_read = xfs_dir2_free_read_verify, | 126 | .verify_read = xfs_dir3_free_read_verify, |
90 | .verify_write = xfs_dir2_free_write_verify, | 127 | .verify_write = xfs_dir3_free_write_verify, |
91 | }; | 128 | }; |
92 | 129 | ||
93 | 130 | ||
94 | static int | 131 | static int |
95 | __xfs_dir2_free_read( | 132 | __xfs_dir3_free_read( |
96 | struct xfs_trans *tp, | 133 | struct xfs_trans *tp, |
97 | struct xfs_inode *dp, | 134 | struct xfs_inode *dp, |
98 | xfs_dablk_t fbno, | 135 | xfs_dablk_t fbno, |
@@ -100,7 +137,7 @@ __xfs_dir2_free_read( | |||
100 | struct xfs_buf **bpp) | 137 | struct xfs_buf **bpp) |
101 | { | 138 | { |
102 | return xfs_da_read_buf(tp, dp, fbno, mappedbno, bpp, | 139 | return xfs_da_read_buf(tp, dp, fbno, mappedbno, bpp, |
103 | XFS_DATA_FORK, &xfs_dir2_free_buf_ops); | 140 | XFS_DATA_FORK, &xfs_dir3_free_buf_ops); |
104 | } | 141 | } |
105 | 142 | ||
106 | int | 143 | int |
@@ -110,7 +147,7 @@ xfs_dir2_free_read( | |||
110 | xfs_dablk_t fbno, | 147 | xfs_dablk_t fbno, |
111 | struct xfs_buf **bpp) | 148 | struct xfs_buf **bpp) |
112 | { | 149 | { |
113 | return __xfs_dir2_free_read(tp, dp, fbno, -1, bpp); | 150 | return __xfs_dir3_free_read(tp, dp, fbno, -1, bpp); |
114 | } | 151 | } |
115 | 152 | ||
116 | static int | 153 | static int |
@@ -120,7 +157,94 @@ xfs_dir2_free_try_read( | |||
120 | xfs_dablk_t fbno, | 157 | xfs_dablk_t fbno, |
121 | struct xfs_buf **bpp) | 158 | struct xfs_buf **bpp) |
122 | { | 159 | { |
123 | return __xfs_dir2_free_read(tp, dp, fbno, -2, bpp); | 160 | return __xfs_dir3_free_read(tp, dp, fbno, -2, bpp); |
161 | } | ||
162 | |||
163 | |||
164 | void | ||
165 | xfs_dir3_free_hdr_from_disk( | ||
166 | struct xfs_dir3_icfree_hdr *to, | ||
167 | struct xfs_dir2_free *from) | ||
168 | { | ||
169 | if (from->hdr.magic == cpu_to_be32(XFS_DIR2_FREE_MAGIC)) { | ||
170 | to->magic = be32_to_cpu(from->hdr.magic); | ||
171 | to->firstdb = be32_to_cpu(from->hdr.firstdb); | ||
172 | to->nvalid = be32_to_cpu(from->hdr.nvalid); | ||
173 | to->nused = be32_to_cpu(from->hdr.nused); | ||
174 | } else { | ||
175 | struct xfs_dir3_free_hdr *hdr3 = (struct xfs_dir3_free_hdr *)from; | ||
176 | |||
177 | to->magic = be32_to_cpu(hdr3->hdr.magic); | ||
178 | to->firstdb = be32_to_cpu(hdr3->firstdb); | ||
179 | to->nvalid = be32_to_cpu(hdr3->nvalid); | ||
180 | to->nused = be32_to_cpu(hdr3->nused); | ||
181 | } | ||
182 | |||
183 | ASSERT(to->magic == XFS_DIR2_FREE_MAGIC || | ||
184 | to->magic == XFS_DIR3_FREE_MAGIC); | ||
185 | } | ||
186 | |||
187 | static void | ||
188 | xfs_dir3_free_hdr_to_disk( | ||
189 | struct xfs_dir2_free *to, | ||
190 | struct xfs_dir3_icfree_hdr *from) | ||
191 | { | ||
192 | ASSERT(from->magic == XFS_DIR2_FREE_MAGIC || | ||
193 | from->magic == XFS_DIR3_FREE_MAGIC); | ||
194 | |||
195 | if (from->magic == XFS_DIR2_FREE_MAGIC) { | ||
196 | to->hdr.magic = cpu_to_be32(from->magic); | ||
197 | to->hdr.firstdb = cpu_to_be32(from->firstdb); | ||
198 | to->hdr.nvalid = cpu_to_be32(from->nvalid); | ||
199 | to->hdr.nused = cpu_to_be32(from->nused); | ||
200 | } else { | ||
201 | struct xfs_dir3_free_hdr *hdr3 = (struct xfs_dir3_free_hdr *)to; | ||
202 | |||
203 | hdr3->hdr.magic = cpu_to_be32(from->magic); | ||
204 | hdr3->firstdb = cpu_to_be32(from->firstdb); | ||
205 | hdr3->nvalid = cpu_to_be32(from->nvalid); | ||
206 | hdr3->nused = cpu_to_be32(from->nused); | ||
207 | } | ||
208 | } | ||
209 | |||
210 | static int | ||
211 | xfs_dir3_free_get_buf( | ||
212 | struct xfs_trans *tp, | ||
213 | struct xfs_inode *dp, | ||
214 | xfs_dir2_db_t fbno, | ||
215 | struct xfs_buf **bpp) | ||
216 | { | ||
217 | struct xfs_mount *mp = dp->i_mount; | ||
218 | struct xfs_buf *bp; | ||
219 | int error; | ||
220 | struct xfs_dir3_icfree_hdr hdr; | ||
221 | |||
222 | error = xfs_da_get_buf(tp, dp, xfs_dir2_db_to_da(mp, fbno), | ||
223 | -1, &bp, XFS_DATA_FORK); | ||
224 | if (error) | ||
225 | return error; | ||
226 | |||
227 | bp->b_ops = &xfs_dir3_free_buf_ops; | ||
228 | |||
229 | /* | ||
230 | * Initialize the new block to be empty, and remember | ||
231 | * its first slot as our empty slot. | ||
232 | */ | ||
233 | hdr.magic = XFS_DIR2_FREE_MAGIC; | ||
234 | hdr.firstdb = 0; | ||
235 | hdr.nused = 0; | ||
236 | hdr.nvalid = 0; | ||
237 | if (xfs_sb_version_hascrc(&mp->m_sb)) { | ||
238 | struct xfs_dir3_free_hdr *hdr3 = bp->b_addr; | ||
239 | |||
240 | hdr.magic = XFS_DIR3_FREE_MAGIC; | ||
241 | hdr3->hdr.blkno = cpu_to_be64(bp->b_bn); | ||
242 | hdr3->hdr.owner = cpu_to_be64(dp->i_ino); | ||
243 | uuid_copy(&hdr3->hdr.uuid, &mp->m_sb.sb_uuid); | ||
244 | } | ||
245 | xfs_dir3_free_hdr_to_disk(bp->b_addr, &hdr); | ||
246 | *bpp = bp; | ||
247 | return 0; | ||
124 | } | 248 | } |
125 | 249 | ||
126 | /* | 250 | /* |
@@ -134,13 +258,16 @@ xfs_dir2_free_log_bests( | |||
134 | int last) /* last entry to log */ | 258 | int last) /* last entry to log */ |
135 | { | 259 | { |
136 | xfs_dir2_free_t *free; /* freespace structure */ | 260 | xfs_dir2_free_t *free; /* freespace structure */ |
261 | __be16 *bests; | ||
137 | 262 | ||
138 | free = bp->b_addr; | 263 | free = bp->b_addr; |
139 | ASSERT(free->hdr.magic == cpu_to_be32(XFS_DIR2_FREE_MAGIC)); | 264 | bests = xfs_dir3_free_bests_p(tp->t_mountp, free); |
265 | ASSERT(free->hdr.magic == cpu_to_be32(XFS_DIR2_FREE_MAGIC) || | ||
266 | free->hdr.magic == cpu_to_be32(XFS_DIR3_FREE_MAGIC)); | ||
140 | xfs_trans_log_buf(tp, bp, | 267 | xfs_trans_log_buf(tp, bp, |
141 | (uint)((char *)&free->bests[first] - (char *)free), | 268 | (uint)((char *)&bests[first] - (char *)free), |
142 | (uint)((char *)&free->bests[last] - (char *)free + | 269 | (uint)((char *)&bests[last] - (char *)free + |
143 | sizeof(free->bests[0]) - 1)); | 270 | sizeof(bests[0]) - 1)); |
144 | } | 271 | } |
145 | 272 | ||
146 | /* | 273 | /* |
@@ -154,9 +281,9 @@ xfs_dir2_free_log_header( | |||
154 | xfs_dir2_free_t *free; /* freespace structure */ | 281 | xfs_dir2_free_t *free; /* freespace structure */ |
155 | 282 | ||
156 | free = bp->b_addr; | 283 | free = bp->b_addr; |
157 | ASSERT(free->hdr.magic == cpu_to_be32(XFS_DIR2_FREE_MAGIC)); | 284 | ASSERT(free->hdr.magic == cpu_to_be32(XFS_DIR2_FREE_MAGIC) || |
158 | xfs_trans_log_buf(tp, bp, (uint)((char *)&free->hdr - (char *)free), | 285 | free->hdr.magic == cpu_to_be32(XFS_DIR3_FREE_MAGIC)); |
159 | (uint)(sizeof(xfs_dir2_free_hdr_t) - 1)); | 286 | xfs_trans_log_buf(tp, bp, 0, xfs_dir3_free_hdr_size(tp->t_mountp) - 1); |
160 | } | 287 | } |
161 | 288 | ||
162 | /* | 289 | /* |
@@ -183,6 +310,7 @@ xfs_dir2_leaf_to_node( | |||
183 | xfs_dir2_data_off_t off; /* freespace entry value */ | 310 | xfs_dir2_data_off_t off; /* freespace entry value */ |
184 | __be16 *to; /* pointer to freespace entry */ | 311 | __be16 *to; /* pointer to freespace entry */ |
185 | xfs_trans_t *tp; /* transaction pointer */ | 312 | xfs_trans_t *tp; /* transaction pointer */ |
313 | struct xfs_dir3_icfree_hdr freehdr; | ||
186 | 314 | ||
187 | trace_xfs_dir2_leaf_to_node(args); | 315 | trace_xfs_dir2_leaf_to_node(args); |
188 | 316 | ||
@@ -199,43 +327,43 @@ xfs_dir2_leaf_to_node( | |||
199 | /* | 327 | /* |
200 | * Get the buffer for the new freespace block. | 328 | * Get the buffer for the new freespace block. |
201 | */ | 329 | */ |
202 | error = xfs_da_get_buf(tp, dp, xfs_dir2_db_to_da(mp, fdb), -1, &fbp, | 330 | error = xfs_dir3_free_get_buf(tp, dp, fdb, &fbp); |
203 | XFS_DATA_FORK); | ||
204 | if (error) | 331 | if (error) |
205 | return error; | 332 | return error; |
206 | fbp->b_ops = &xfs_dir2_free_buf_ops; | ||
207 | 333 | ||
208 | free = fbp->b_addr; | 334 | free = fbp->b_addr; |
335 | xfs_dir3_free_hdr_from_disk(&freehdr, free); | ||
209 | leaf = lbp->b_addr; | 336 | leaf = lbp->b_addr; |
210 | ltp = xfs_dir2_leaf_tail_p(mp, leaf); | 337 | ltp = xfs_dir2_leaf_tail_p(mp, leaf); |
211 | /* | 338 | ASSERT(be32_to_cpu(ltp->bestcount) <= |
212 | * Initialize the freespace block header. | 339 | (uint)dp->i_d.di_size / mp->m_dirblksize); |
213 | */ | 340 | |
214 | free->hdr.magic = cpu_to_be32(XFS_DIR2_FREE_MAGIC); | ||
215 | free->hdr.firstdb = 0; | ||
216 | ASSERT(be32_to_cpu(ltp->bestcount) <= (uint)dp->i_d.di_size / mp->m_dirblksize); | ||
217 | free->hdr.nvalid = ltp->bestcount; | ||
218 | /* | 341 | /* |
219 | * Copy freespace entries from the leaf block to the new block. | 342 | * Copy freespace entries from the leaf block to the new block. |
220 | * Count active entries. | 343 | * Count active entries. |
221 | */ | 344 | */ |
222 | for (i = n = 0, from = xfs_dir2_leaf_bests_p(ltp), to = free->bests; | 345 | from = xfs_dir2_leaf_bests_p(ltp); |
223 | i < be32_to_cpu(ltp->bestcount); i++, from++, to++) { | 346 | to = xfs_dir3_free_bests_p(mp, free); |
347 | for (i = n = 0; i < be32_to_cpu(ltp->bestcount); i++, from++, to++) { | ||
224 | if ((off = be16_to_cpu(*from)) != NULLDATAOFF) | 348 | if ((off = be16_to_cpu(*from)) != NULLDATAOFF) |
225 | n++; | 349 | n++; |
226 | *to = cpu_to_be16(off); | 350 | *to = cpu_to_be16(off); |
227 | } | 351 | } |
228 | free->hdr.nused = cpu_to_be32(n); | ||
229 | |||
230 | lbp->b_ops = &xfs_dir2_leafn_buf_ops; | ||
231 | leaf->hdr.info.magic = cpu_to_be16(XFS_DIR2_LEAFN_MAGIC); | ||
232 | 352 | ||
233 | /* | 353 | /* |
234 | * Log everything. | 354 | * Now initialize the freespace block header. |
235 | */ | 355 | */ |
236 | xfs_dir2_leaf_log_header(tp, lbp); | 356 | freehdr.nused = n; |
357 | freehdr.nvalid = be32_to_cpu(ltp->bestcount); | ||
358 | |||
359 | xfs_dir3_free_hdr_to_disk(fbp->b_addr, &freehdr); | ||
360 | xfs_dir2_free_log_bests(tp, fbp, 0, freehdr.nvalid - 1); | ||
237 | xfs_dir2_free_log_header(tp, fbp); | 361 | xfs_dir2_free_log_header(tp, fbp); |
238 | xfs_dir2_free_log_bests(tp, fbp, 0, be32_to_cpu(free->hdr.nvalid) - 1); | 362 | |
363 | /* convert the leaf to a leafnode */ | ||
364 | leaf->hdr.info.magic = cpu_to_be16(XFS_DIR2_LEAFN_MAGIC); | ||
365 | lbp->b_ops = &xfs_dir2_leafn_buf_ops; | ||
366 | xfs_dir2_leaf_log_header(tp, lbp); | ||
239 | xfs_dir2_leafn_check(dp, lbp); | 367 | xfs_dir2_leafn_check(dp, lbp); |
240 | return 0; | 368 | return 0; |
241 | } | 369 | } |
@@ -354,6 +482,23 @@ xfs_dir2_leafn_check( | |||
354 | } | 482 | } |
355 | ASSERT(be16_to_cpu(leaf->hdr.stale) == stale); | 483 | ASSERT(be16_to_cpu(leaf->hdr.stale) == stale); |
356 | } | 484 | } |
485 | |||
486 | static void | ||
487 | xfs_dir2_free_hdr_check( | ||
488 | struct xfs_mount *mp, | ||
489 | struct xfs_buf *bp, | ||
490 | xfs_dir2_db_t db) | ||
491 | { | ||
492 | struct xfs_dir3_icfree_hdr hdr; | ||
493 | |||
494 | xfs_dir3_free_hdr_from_disk(&hdr, bp->b_addr); | ||
495 | |||
496 | ASSERT((hdr.firstdb % xfs_dir3_free_max_bests(mp)) == 0); | ||
497 | ASSERT(hdr.firstdb <= db); | ||
498 | ASSERT(db < hdr.firstdb + hdr.nvalid); | ||
499 | } | ||
500 | #else | ||
501 | #define xfs_dir2_free_hdr_check(mp, dp, db) | ||
357 | #endif /* DEBUG */ | 502 | #endif /* DEBUG */ |
358 | 503 | ||
359 | /* | 504 | /* |
@@ -424,7 +569,8 @@ xfs_dir2_leafn_lookup_for_addname( | |||
424 | curbp = state->extrablk.bp; | 569 | curbp = state->extrablk.bp; |
425 | curfdb = state->extrablk.blkno; | 570 | curfdb = state->extrablk.blkno; |
426 | free = curbp->b_addr; | 571 | free = curbp->b_addr; |
427 | ASSERT(free->hdr.magic == cpu_to_be32(XFS_DIR2_FREE_MAGIC)); | 572 | ASSERT(free->hdr.magic == cpu_to_be32(XFS_DIR2_FREE_MAGIC) || |
573 | free->hdr.magic == cpu_to_be32(XFS_DIR3_FREE_MAGIC)); | ||
428 | } | 574 | } |
429 | length = xfs_dir2_data_entsize(args->namelen); | 575 | length = xfs_dir2_data_entsize(args->namelen); |
430 | /* | 576 | /* |
@@ -451,6 +597,8 @@ xfs_dir2_leafn_lookup_for_addname( | |||
451 | * in hand, take a look at it. | 597 | * in hand, take a look at it. |
452 | */ | 598 | */ |
453 | if (newdb != curdb) { | 599 | if (newdb != curdb) { |
600 | __be16 *bests; | ||
601 | |||
454 | curdb = newdb; | 602 | curdb = newdb; |
455 | /* | 603 | /* |
456 | * Convert the data block to the free block | 604 | * Convert the data block to the free block |
@@ -473,13 +621,8 @@ xfs_dir2_leafn_lookup_for_addname( | |||
473 | if (error) | 621 | if (error) |
474 | return error; | 622 | return error; |
475 | free = curbp->b_addr; | 623 | free = curbp->b_addr; |
476 | ASSERT(be32_to_cpu(free->hdr.magic) == | 624 | |
477 | XFS_DIR2_FREE_MAGIC); | 625 | xfs_dir2_free_hdr_check(mp, curbp, curdb); |
478 | ASSERT((be32_to_cpu(free->hdr.firstdb) % | ||
479 | xfs_dir2_free_max_bests(mp)) == 0); | ||
480 | ASSERT(be32_to_cpu(free->hdr.firstdb) <= curdb); | ||
481 | ASSERT(curdb < be32_to_cpu(free->hdr.firstdb) + | ||
482 | be32_to_cpu(free->hdr.nvalid)); | ||
483 | } | 626 | } |
484 | /* | 627 | /* |
485 | * Get the index for our entry. | 628 | * Get the index for our entry. |
@@ -488,8 +631,8 @@ xfs_dir2_leafn_lookup_for_addname( | |||
488 | /* | 631 | /* |
489 | * If it has room, return it. | 632 | * If it has room, return it. |
490 | */ | 633 | */ |
491 | if (unlikely(free->bests[fi] == | 634 | bests = xfs_dir3_free_bests_p(mp, free); |
492 | cpu_to_be16(NULLDATAOFF))) { | 635 | if (unlikely(bests[fi] == cpu_to_be16(NULLDATAOFF))) { |
493 | XFS_ERROR_REPORT("xfs_dir2_leafn_lookup_int", | 636 | XFS_ERROR_REPORT("xfs_dir2_leafn_lookup_int", |
494 | XFS_ERRLEVEL_LOW, mp); | 637 | XFS_ERRLEVEL_LOW, mp); |
495 | if (curfdb != newfdb) | 638 | if (curfdb != newfdb) |
@@ -497,7 +640,7 @@ xfs_dir2_leafn_lookup_for_addname( | |||
497 | return XFS_ERROR(EFSCORRUPTED); | 640 | return XFS_ERROR(EFSCORRUPTED); |
498 | } | 641 | } |
499 | curfdb = newfdb; | 642 | curfdb = newfdb; |
500 | if (be16_to_cpu(free->bests[fi]) >= length) | 643 | if (be16_to_cpu(bests[fi]) >= length) |
501 | goto out; | 644 | goto out; |
502 | } | 645 | } |
503 | } | 646 | } |
@@ -511,6 +654,12 @@ out: | |||
511 | state->extrablk.bp = curbp; | 654 | state->extrablk.bp = curbp; |
512 | state->extrablk.index = fi; | 655 | state->extrablk.index = fi; |
513 | state->extrablk.blkno = curfdb; | 656 | state->extrablk.blkno = curfdb; |
657 | |||
658 | /* | ||
659 | * Important: this magic number is not in the buffer - it's for | ||
660 | * buffer type information and therefore only the free/data type | ||
661 | * matters here, not whether CRCs are enabled or not. | ||
662 | */ | ||
514 | state->extrablk.magic = XFS_DIR2_FREE_MAGIC; | 663 | state->extrablk.magic = XFS_DIR2_FREE_MAGIC; |
515 | } else { | 664 | } else { |
516 | state->extravalid = 0; | 665 | state->extravalid = 0; |
@@ -898,7 +1047,7 @@ xfs_dir2_leafn_rebalance( | |||
898 | } | 1047 | } |
899 | 1048 | ||
900 | static int | 1049 | static int |
901 | xfs_dir2_data_block_free( | 1050 | xfs_dir3_data_block_free( |
902 | xfs_da_args_t *args, | 1051 | xfs_da_args_t *args, |
903 | struct xfs_dir2_data_hdr *hdr, | 1052 | struct xfs_dir2_data_hdr *hdr, |
904 | struct xfs_dir2_free *free, | 1053 | struct xfs_dir2_free *free, |
@@ -909,57 +1058,66 @@ xfs_dir2_data_block_free( | |||
909 | { | 1058 | { |
910 | struct xfs_trans *tp = args->trans; | 1059 | struct xfs_trans *tp = args->trans; |
911 | int logfree = 0; | 1060 | int logfree = 0; |
1061 | __be16 *bests; | ||
1062 | struct xfs_dir3_icfree_hdr freehdr; | ||
912 | 1063 | ||
913 | if (!hdr) { | 1064 | xfs_dir3_free_hdr_from_disk(&freehdr, free); |
914 | /* One less used entry in the free table. */ | ||
915 | be32_add_cpu(&free->hdr.nused, -1); | ||
916 | xfs_dir2_free_log_header(tp, fbp); | ||
917 | 1065 | ||
1066 | bests = xfs_dir3_free_bests_p(tp->t_mountp, free); | ||
1067 | if (hdr) { | ||
918 | /* | 1068 | /* |
919 | * If this was the last entry in the table, we can trim the | 1069 | * Data block is not empty, just set the free entry to the new |
920 | * table size back. There might be other entries at the end | 1070 | * value. |
921 | * referring to non-existent data blocks, get those too. | ||
922 | */ | 1071 | */ |
923 | if (findex == be32_to_cpu(free->hdr.nvalid) - 1) { | 1072 | bests[findex] = cpu_to_be16(longest); |
924 | int i; /* free entry index */ | 1073 | xfs_dir2_free_log_bests(tp, fbp, findex, findex); |
1074 | return 0; | ||
1075 | } | ||
925 | 1076 | ||
926 | for (i = findex - 1; i >= 0; i--) { | 1077 | /* One less used entry in the free table. */ |
927 | if (free->bests[i] != cpu_to_be16(NULLDATAOFF)) | 1078 | freehdr.nused--; |
928 | break; | ||
929 | } | ||
930 | free->hdr.nvalid = cpu_to_be32(i + 1); | ||
931 | logfree = 0; | ||
932 | } else { | ||
933 | /* Not the last entry, just punch it out. */ | ||
934 | free->bests[findex] = cpu_to_be16(NULLDATAOFF); | ||
935 | logfree = 1; | ||
936 | } | ||
937 | /* | ||
938 | * If there are no useful entries left in the block, | ||
939 | * get rid of the block if we can. | ||
940 | */ | ||
941 | if (!free->hdr.nused) { | ||
942 | int error; | ||
943 | 1079 | ||
944 | error = xfs_dir2_shrink_inode(args, fdb, fbp); | 1080 | /* |
945 | if (error == 0) { | 1081 | * If this was the last entry in the table, we can trim the table size |
946 | fbp = NULL; | 1082 | * back. There might be other entries at the end referring to |
947 | logfree = 0; | 1083 | * non-existent data blocks, get those too. |
948 | } else if (error != ENOSPC || args->total != 0) | 1084 | */ |
949 | return error; | 1085 | if (findex == freehdr.nvalid - 1) { |
950 | /* | 1086 | int i; /* free entry index */ |
951 | * It's possible to get ENOSPC if there is no | 1087 | |
952 | * space reservation. In this case some one | 1088 | for (i = findex - 1; i >= 0; i--) { |
953 | * else will eventually get rid of this block. | 1089 | if (bests[i] != cpu_to_be16(NULLDATAOFF)) |
954 | */ | 1090 | break; |
955 | } | 1091 | } |
1092 | freehdr.nvalid = i + 1; | ||
1093 | logfree = 0; | ||
956 | } else { | 1094 | } else { |
1095 | /* Not the last entry, just punch it out. */ | ||
1096 | bests[findex] = cpu_to_be16(NULLDATAOFF); | ||
1097 | logfree = 1; | ||
1098 | } | ||
1099 | |||
1100 | xfs_dir3_free_hdr_to_disk(free, &freehdr); | ||
1101 | xfs_dir2_free_log_header(tp, fbp); | ||
1102 | |||
1103 | /* | ||
1104 | * If there are no useful entries left in the block, get rid of the | ||
1105 | * block if we can. | ||
1106 | */ | ||
1107 | if (!freehdr.nused) { | ||
1108 | int error; | ||
1109 | |||
1110 | error = xfs_dir2_shrink_inode(args, fdb, fbp); | ||
1111 | if (error == 0) { | ||
1112 | fbp = NULL; | ||
1113 | logfree = 0; | ||
1114 | } else if (error != ENOSPC || args->total != 0) | ||
1115 | return error; | ||
957 | /* | 1116 | /* |
958 | * Data block is not empty, just set the free entry to the new | 1117 | * It's possible to get ENOSPC if there is no |
959 | * value. | 1118 | * space reservation. In this case some one |
1119 | * else will eventually get rid of this block. | ||
960 | */ | 1120 | */ |
961 | free->bests[findex] = cpu_to_be16(longest); | ||
962 | logfree = 1; | ||
963 | } | 1121 | } |
964 | 1122 | ||
965 | /* Log the free entry that changed, unless we got rid of it. */ | 1123 | /* Log the free entry that changed, unless we got rid of it. */ |
@@ -1062,10 +1220,14 @@ xfs_dir2_leafn_remove( | |||
1062 | if (error) | 1220 | if (error) |
1063 | return error; | 1221 | return error; |
1064 | free = fbp->b_addr; | 1222 | free = fbp->b_addr; |
1065 | ASSERT(free->hdr.magic == cpu_to_be32(XFS_DIR2_FREE_MAGIC)); | 1223 | #ifdef DEBUG |
1066 | ASSERT(be32_to_cpu(free->hdr.firstdb) == | 1224 | { |
1067 | xfs_dir2_free_max_bests(mp) * | 1225 | struct xfs_dir3_icfree_hdr freehdr; |
1068 | (fdb - XFS_DIR2_FREE_FIRSTDB(mp))); | 1226 | xfs_dir3_free_hdr_from_disk(&freehdr, free); |
1227 | ASSERT(freehdr.firstdb == xfs_dir3_free_max_bests(mp) * | ||
1228 | (fdb - XFS_DIR2_FREE_FIRSTDB(mp))); | ||
1229 | } | ||
1230 | #endif | ||
1069 | /* | 1231 | /* |
1070 | * Calculate which entry we need to fix. | 1232 | * Calculate which entry we need to fix. |
1071 | */ | 1233 | */ |
@@ -1096,7 +1258,7 @@ xfs_dir2_leafn_remove( | |||
1096 | * If we got rid of the data block, we can eliminate that entry | 1258 | * If we got rid of the data block, we can eliminate that entry |
1097 | * in the free block. | 1259 | * in the free block. |
1098 | */ | 1260 | */ |
1099 | error = xfs_dir2_data_block_free(args, hdr, free, | 1261 | error = xfs_dir3_data_block_free(args, hdr, free, |
1100 | fdb, findex, fbp, longest); | 1262 | fdb, findex, fbp, longest); |
1101 | if (error) | 1263 | if (error) |
1102 | return error; | 1264 | return error; |
@@ -1447,6 +1609,8 @@ xfs_dir2_node_addname_int( | |||
1447 | int needscan; /* need to rescan data frees */ | 1609 | int needscan; /* need to rescan data frees */ |
1448 | __be16 *tagp; /* data entry tag pointer */ | 1610 | __be16 *tagp; /* data entry tag pointer */ |
1449 | xfs_trans_t *tp; /* transaction pointer */ | 1611 | xfs_trans_t *tp; /* transaction pointer */ |
1612 | __be16 *bests; | ||
1613 | struct xfs_dir3_icfree_hdr freehdr; | ||
1450 | 1614 | ||
1451 | dp = args->dp; | 1615 | dp = args->dp; |
1452 | mp = dp->i_mount; | 1616 | mp = dp->i_mount; |
@@ -1464,36 +1628,37 @@ xfs_dir2_node_addname_int( | |||
1464 | */ | 1628 | */ |
1465 | ifbno = fblk->blkno; | 1629 | ifbno = fblk->blkno; |
1466 | free = fbp->b_addr; | 1630 | free = fbp->b_addr; |
1467 | ASSERT(free->hdr.magic == cpu_to_be32(XFS_DIR2_FREE_MAGIC)); | ||
1468 | findex = fblk->index; | 1631 | findex = fblk->index; |
1632 | bests = xfs_dir3_free_bests_p(mp, free); | ||
1633 | xfs_dir3_free_hdr_from_disk(&freehdr, free); | ||
1634 | |||
1469 | /* | 1635 | /* |
1470 | * This means the free entry showed that the data block had | 1636 | * This means the free entry showed that the data block had |
1471 | * space for our entry, so we remembered it. | 1637 | * space for our entry, so we remembered it. |
1472 | * Use that data block. | 1638 | * Use that data block. |
1473 | */ | 1639 | */ |
1474 | if (findex >= 0) { | 1640 | if (findex >= 0) { |
1475 | ASSERT(findex < be32_to_cpu(free->hdr.nvalid)); | 1641 | ASSERT(findex < freehdr.nvalid); |
1476 | ASSERT(be16_to_cpu(free->bests[findex]) != NULLDATAOFF); | 1642 | ASSERT(be16_to_cpu(bests[findex]) != NULLDATAOFF); |
1477 | ASSERT(be16_to_cpu(free->bests[findex]) >= length); | 1643 | ASSERT(be16_to_cpu(bests[findex]) >= length); |
1478 | dbno = be32_to_cpu(free->hdr.firstdb) + findex; | 1644 | dbno = freehdr.firstdb + findex; |
1479 | } | 1645 | } else { |
1480 | /* | 1646 | /* |
1481 | * The data block looked at didn't have enough room. | 1647 | * The data block looked at didn't have enough room. |
1482 | * We'll start at the beginning of the freespace entries. | 1648 | * We'll start at the beginning of the freespace entries. |
1483 | */ | 1649 | */ |
1484 | else { | ||
1485 | dbno = -1; | 1650 | dbno = -1; |
1486 | findex = 0; | 1651 | findex = 0; |
1487 | } | 1652 | } |
1488 | } | 1653 | } else { |
1489 | /* | 1654 | /* |
1490 | * Didn't come in with a freespace block, so don't have a data block. | 1655 | * Didn't come in with a freespace block, so no data block. |
1491 | */ | 1656 | */ |
1492 | else { | ||
1493 | ifbno = dbno = -1; | 1657 | ifbno = dbno = -1; |
1494 | fbp = NULL; | 1658 | fbp = NULL; |
1495 | findex = 0; | 1659 | findex = 0; |
1496 | } | 1660 | } |
1661 | |||
1497 | /* | 1662 | /* |
1498 | * If we don't have a data block yet, we're going to scan the | 1663 | * If we don't have a data block yet, we're going to scan the |
1499 | * freespace blocks looking for one. Figure out what the | 1664 | * freespace blocks looking for one. Figure out what the |
@@ -1547,20 +1712,26 @@ xfs_dir2_node_addname_int( | |||
1547 | if (!fbp) | 1712 | if (!fbp) |
1548 | continue; | 1713 | continue; |
1549 | free = fbp->b_addr; | 1714 | free = fbp->b_addr; |
1550 | ASSERT(free->hdr.magic == cpu_to_be32(XFS_DIR2_FREE_MAGIC)); | ||
1551 | findex = 0; | 1715 | findex = 0; |
1552 | } | 1716 | } |
1553 | /* | 1717 | /* |
1554 | * Look at the current free entry. Is it good enough? | 1718 | * Look at the current free entry. Is it good enough? |
1719 | * | ||
1720 | * The bests initialisation should be where the bufer is read in | ||
1721 | * the above branch. But gcc is too stupid to realise that bests | ||
1722 | * and the freehdr are actually initialised if they are placed | ||
1723 | * there, so we have to do it here to avoid warnings. Blech. | ||
1555 | */ | 1724 | */ |
1556 | if (be16_to_cpu(free->bests[findex]) != NULLDATAOFF && | 1725 | bests = xfs_dir3_free_bests_p(mp, free); |
1557 | be16_to_cpu(free->bests[findex]) >= length) | 1726 | xfs_dir3_free_hdr_from_disk(&freehdr, free); |
1558 | dbno = be32_to_cpu(free->hdr.firstdb) + findex; | 1727 | if (be16_to_cpu(bests[findex]) != NULLDATAOFF && |
1728 | be16_to_cpu(bests[findex]) >= length) | ||
1729 | dbno = freehdr.firstdb + findex; | ||
1559 | else { | 1730 | else { |
1560 | /* | 1731 | /* |
1561 | * Are we done with the freeblock? | 1732 | * Are we done with the freeblock? |
1562 | */ | 1733 | */ |
1563 | if (++findex == be32_to_cpu(free->hdr.nvalid)) { | 1734 | if (++findex == freehdr.nvalid) { |
1564 | /* | 1735 | /* |
1565 | * Drop the block. | 1736 | * Drop the block. |
1566 | */ | 1737 | */ |
@@ -1614,11 +1785,11 @@ xfs_dir2_node_addname_int( | |||
1614 | * If there wasn't a freespace block, the read will | 1785 | * If there wasn't a freespace block, the read will |
1615 | * return a NULL fbp. Allocate and initialize a new one. | 1786 | * return a NULL fbp. Allocate and initialize a new one. |
1616 | */ | 1787 | */ |
1617 | if( fbp == NULL ) { | 1788 | if (!fbp) { |
1618 | if ((error = xfs_dir2_grow_inode(args, XFS_DIR2_FREE_SPACE, | 1789 | error = xfs_dir2_grow_inode(args, XFS_DIR2_FREE_SPACE, |
1619 | &fbno))) { | 1790 | &fbno); |
1791 | if (error) | ||
1620 | return error; | 1792 | return error; |
1621 | } | ||
1622 | 1793 | ||
1623 | if (unlikely(xfs_dir2_db_to_fdb(mp, dbno) != fbno)) { | 1794 | if (unlikely(xfs_dir2_db_to_fdb(mp, dbno) != fbno)) { |
1624 | xfs_alert(mp, | 1795 | xfs_alert(mp, |
@@ -1646,27 +1817,24 @@ xfs_dir2_node_addname_int( | |||
1646 | /* | 1817 | /* |
1647 | * Get a buffer for the new block. | 1818 | * Get a buffer for the new block. |
1648 | */ | 1819 | */ |
1649 | error = xfs_da_get_buf(tp, dp, | 1820 | error = xfs_dir3_free_get_buf(tp, dp, fbno, &fbp); |
1650 | xfs_dir2_db_to_da(mp, fbno), | ||
1651 | -1, &fbp, XFS_DATA_FORK); | ||
1652 | if (error) | 1821 | if (error) |
1653 | return error; | 1822 | return error; |
1654 | fbp->b_ops = &xfs_dir2_free_buf_ops; | 1823 | free = fbp->b_addr; |
1824 | bests = xfs_dir3_free_bests_p(mp, free); | ||
1825 | xfs_dir3_free_hdr_from_disk(&freehdr, free); | ||
1655 | 1826 | ||
1656 | /* | 1827 | /* |
1657 | * Initialize the new block to be empty, and remember | 1828 | * Remember the first slot as our empty slot. |
1658 | * its first slot as our empty slot. | ||
1659 | */ | 1829 | */ |
1660 | free = fbp->b_addr; | 1830 | freehdr.firstdb = (fbno - XFS_DIR2_FREE_FIRSTDB(mp)) * |
1661 | free->hdr.magic = cpu_to_be32(XFS_DIR2_FREE_MAGIC); | 1831 | xfs_dir3_free_max_bests(mp); |
1662 | free->hdr.firstdb = cpu_to_be32( | ||
1663 | (fbno - XFS_DIR2_FREE_FIRSTDB(mp)) * | ||
1664 | xfs_dir2_free_max_bests(mp)); | ||
1665 | free->hdr.nvalid = 0; | 1832 | free->hdr.nvalid = 0; |
1666 | free->hdr.nused = 0; | 1833 | free->hdr.nused = 0; |
1667 | } else { | 1834 | } else { |
1668 | free = fbp->b_addr; | 1835 | free = fbp->b_addr; |
1669 | ASSERT(free->hdr.magic == cpu_to_be32(XFS_DIR2_FREE_MAGIC)); | 1836 | bests = xfs_dir3_free_bests_p(mp, free); |
1837 | xfs_dir3_free_hdr_from_disk(&freehdr, free); | ||
1670 | } | 1838 | } |
1671 | 1839 | ||
1672 | /* | 1840 | /* |
@@ -1677,20 +1845,21 @@ xfs_dir2_node_addname_int( | |||
1677 | * If it's after the end of the current entries in the | 1845 | * If it's after the end of the current entries in the |
1678 | * freespace block, extend that table. | 1846 | * freespace block, extend that table. |
1679 | */ | 1847 | */ |
1680 | if (findex >= be32_to_cpu(free->hdr.nvalid)) { | 1848 | if (findex >= freehdr.nvalid) { |
1681 | ASSERT(findex < xfs_dir2_free_max_bests(mp)); | 1849 | ASSERT(findex < xfs_dir3_free_max_bests(mp)); |
1682 | free->hdr.nvalid = cpu_to_be32(findex + 1); | 1850 | freehdr.nvalid = findex + 1; |
1683 | /* | 1851 | /* |
1684 | * Tag new entry so nused will go up. | 1852 | * Tag new entry so nused will go up. |
1685 | */ | 1853 | */ |
1686 | free->bests[findex] = cpu_to_be16(NULLDATAOFF); | 1854 | bests[findex] = cpu_to_be16(NULLDATAOFF); |
1687 | } | 1855 | } |
1688 | /* | 1856 | /* |
1689 | * If this entry was for an empty data block | 1857 | * If this entry was for an empty data block |
1690 | * (this should always be true) then update the header. | 1858 | * (this should always be true) then update the header. |
1691 | */ | 1859 | */ |
1692 | if (free->bests[findex] == cpu_to_be16(NULLDATAOFF)) { | 1860 | if (bests[findex] == cpu_to_be16(NULLDATAOFF)) { |
1693 | be32_add_cpu(&free->hdr.nused, 1); | 1861 | freehdr.nused++; |
1862 | xfs_dir3_free_hdr_to_disk(fbp->b_addr, &freehdr); | ||
1694 | xfs_dir2_free_log_header(tp, fbp); | 1863 | xfs_dir2_free_log_header(tp, fbp); |
1695 | } | 1864 | } |
1696 | /* | 1865 | /* |
@@ -1699,7 +1868,7 @@ xfs_dir2_node_addname_int( | |||
1699 | * change again. | 1868 | * change again. |
1700 | */ | 1869 | */ |
1701 | hdr = dbp->b_addr; | 1870 | hdr = dbp->b_addr; |
1702 | free->bests[findex] = hdr->bestfree[0].length; | 1871 | bests[findex] = hdr->bestfree[0].length; |
1703 | logfree = 1; | 1872 | logfree = 1; |
1704 | } | 1873 | } |
1705 | /* | 1874 | /* |
@@ -1758,8 +1927,9 @@ xfs_dir2_node_addname_int( | |||
1758 | /* | 1927 | /* |
1759 | * If the freespace entry is now wrong, update it. | 1928 | * If the freespace entry is now wrong, update it. |
1760 | */ | 1929 | */ |
1761 | if (be16_to_cpu(free->bests[findex]) != be16_to_cpu(hdr->bestfree[0].length)) { | 1930 | bests = xfs_dir3_free_bests_p(mp, free); /* gcc is so stupid */ |
1762 | free->bests[findex] = hdr->bestfree[0].length; | 1931 | if (be16_to_cpu(bests[findex]) != be16_to_cpu(hdr->bestfree[0].length)) { |
1932 | bests[findex] = hdr->bestfree[0].length; | ||
1763 | logfree = 1; | 1933 | logfree = 1; |
1764 | } | 1934 | } |
1765 | /* | 1935 | /* |
@@ -1995,6 +2165,7 @@ xfs_dir2_node_trim_free( | |||
1995 | xfs_dir2_free_t *free; /* freespace structure */ | 2165 | xfs_dir2_free_t *free; /* freespace structure */ |
1996 | xfs_mount_t *mp; /* filesystem mount point */ | 2166 | xfs_mount_t *mp; /* filesystem mount point */ |
1997 | xfs_trans_t *tp; /* transaction pointer */ | 2167 | xfs_trans_t *tp; /* transaction pointer */ |
2168 | struct xfs_dir3_icfree_hdr freehdr; | ||
1998 | 2169 | ||
1999 | dp = args->dp; | 2170 | dp = args->dp; |
2000 | mp = dp->i_mount; | 2171 | mp = dp->i_mount; |
@@ -2012,11 +2183,12 @@ xfs_dir2_node_trim_free( | |||
2012 | if (!bp) | 2183 | if (!bp) |
2013 | return 0; | 2184 | return 0; |
2014 | free = bp->b_addr; | 2185 | free = bp->b_addr; |
2015 | ASSERT(free->hdr.magic == cpu_to_be32(XFS_DIR2_FREE_MAGIC)); | 2186 | xfs_dir3_free_hdr_from_disk(&freehdr, free); |
2187 | |||
2016 | /* | 2188 | /* |
2017 | * If there are used entries, there's nothing to do. | 2189 | * If there are used entries, there's nothing to do. |
2018 | */ | 2190 | */ |
2019 | if (be32_to_cpu(free->hdr.nused) > 0) { | 2191 | if (freehdr.nused > 0) { |
2020 | xfs_trans_brelse(tp, bp); | 2192 | xfs_trans_brelse(tp, bp); |
2021 | *rvalp = 0; | 2193 | *rvalp = 0; |
2022 | return 0; | 2194 | return 0; |