diff options
Diffstat (limited to 'fs/xfs/xfs_dir2_leaf.c')
-rw-r--r-- | fs/xfs/xfs_dir2_leaf.c | 792 |
1 files changed, 504 insertions, 288 deletions
diff --git a/fs/xfs/xfs_dir2_leaf.c b/fs/xfs/xfs_dir2_leaf.c index c7dca950f768..7352e41d2aaa 100644 --- a/fs/xfs/xfs_dir2_leaf.c +++ b/fs/xfs/xfs_dir2_leaf.c | |||
@@ -1,5 +1,6 @@ | |||
1 | /* | 1 | /* |
2 | * Copyright (c) 2000-2003,2005 Silicon Graphics, Inc. | 2 | * Copyright (c) 2000-2003,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 |
@@ -33,77 +34,263 @@ | |||
33 | #include "xfs_dir2_priv.h" | 34 | #include "xfs_dir2_priv.h" |
34 | #include "xfs_error.h" | 35 | #include "xfs_error.h" |
35 | #include "xfs_trace.h" | 36 | #include "xfs_trace.h" |
37 | #include "xfs_buf_item.h" | ||
38 | #include "xfs_cksum.h" | ||
36 | 39 | ||
37 | /* | 40 | /* |
38 | * Local function declarations. | 41 | * Local function declarations. |
39 | */ | 42 | */ |
40 | #ifdef DEBUG | ||
41 | static void xfs_dir2_leaf_check(struct xfs_inode *dp, struct xfs_buf *bp); | ||
42 | #else | ||
43 | #define xfs_dir2_leaf_check(dp, bp) | ||
44 | #endif | ||
45 | static int xfs_dir2_leaf_lookup_int(xfs_da_args_t *args, struct xfs_buf **lbpp, | 43 | static int xfs_dir2_leaf_lookup_int(xfs_da_args_t *args, struct xfs_buf **lbpp, |
46 | int *indexp, struct xfs_buf **dbpp); | 44 | int *indexp, struct xfs_buf **dbpp); |
47 | static void xfs_dir2_leaf_log_bests(struct xfs_trans *tp, struct xfs_buf *bp, | 45 | static void xfs_dir3_leaf_log_bests(struct xfs_trans *tp, struct xfs_buf *bp, |
48 | int first, int last); | 46 | int first, int last); |
49 | static void xfs_dir2_leaf_log_tail(struct xfs_trans *tp, struct xfs_buf *bp); | 47 | static void xfs_dir3_leaf_log_tail(struct xfs_trans *tp, struct xfs_buf *bp); |
50 | 48 | ||
51 | static void | 49 | /* |
52 | xfs_dir2_leaf_verify( | 50 | * Check the internal consistency of a leaf1 block. |
51 | * Pop an assert if something is wrong. | ||
52 | */ | ||
53 | #ifdef DEBUG | ||
54 | #define xfs_dir3_leaf_check(mp, bp) \ | ||
55 | do { \ | ||
56 | if (!xfs_dir3_leaf1_check((mp), (bp))) \ | ||
57 | ASSERT(0); \ | ||
58 | } while (0); | ||
59 | |||
60 | STATIC bool | ||
61 | xfs_dir3_leaf1_check( | ||
62 | struct xfs_mount *mp, | ||
63 | struct xfs_buf *bp) | ||
64 | { | ||
65 | struct xfs_dir2_leaf *leaf = bp->b_addr; | ||
66 | struct xfs_dir3_icleaf_hdr leafhdr; | ||
67 | |||
68 | xfs_dir3_leaf_hdr_from_disk(&leafhdr, leaf); | ||
69 | |||
70 | if (leafhdr.magic == XFS_DIR3_LEAF1_MAGIC) { | ||
71 | struct xfs_dir3_leaf_hdr *leaf3 = bp->b_addr; | ||
72 | if (be64_to_cpu(leaf3->info.blkno) != bp->b_bn) | ||
73 | return false; | ||
74 | } else if (leafhdr.magic != XFS_DIR2_LEAF1_MAGIC) | ||
75 | return false; | ||
76 | |||
77 | return xfs_dir3_leaf_check_int(mp, &leafhdr, leaf); | ||
78 | } | ||
79 | #else | ||
80 | #define xfs_dir3_leaf_check(mp, bp) | ||
81 | #endif | ||
82 | |||
83 | void | ||
84 | xfs_dir3_leaf_hdr_from_disk( | ||
85 | struct xfs_dir3_icleaf_hdr *to, | ||
86 | struct xfs_dir2_leaf *from) | ||
87 | { | ||
88 | if (from->hdr.info.magic == cpu_to_be16(XFS_DIR2_LEAF1_MAGIC) || | ||
89 | from->hdr.info.magic == cpu_to_be16(XFS_DIR2_LEAFN_MAGIC)) { | ||
90 | to->forw = be32_to_cpu(from->hdr.info.forw); | ||
91 | to->back = be32_to_cpu(from->hdr.info.back); | ||
92 | to->magic = be16_to_cpu(from->hdr.info.magic); | ||
93 | to->count = be16_to_cpu(from->hdr.count); | ||
94 | to->stale = be16_to_cpu(from->hdr.stale); | ||
95 | } else { | ||
96 | struct xfs_dir3_leaf_hdr *hdr3 = (struct xfs_dir3_leaf_hdr *)from; | ||
97 | |||
98 | to->forw = be32_to_cpu(hdr3->info.hdr.forw); | ||
99 | to->back = be32_to_cpu(hdr3->info.hdr.back); | ||
100 | to->magic = be16_to_cpu(hdr3->info.hdr.magic); | ||
101 | to->count = be16_to_cpu(hdr3->count); | ||
102 | to->stale = be16_to_cpu(hdr3->stale); | ||
103 | } | ||
104 | |||
105 | ASSERT(to->magic == XFS_DIR2_LEAF1_MAGIC || | ||
106 | to->magic == XFS_DIR3_LEAF1_MAGIC || | ||
107 | to->magic == XFS_DIR2_LEAFN_MAGIC || | ||
108 | to->magic == XFS_DIR3_LEAFN_MAGIC); | ||
109 | } | ||
110 | |||
111 | void | ||
112 | xfs_dir3_leaf_hdr_to_disk( | ||
113 | struct xfs_dir2_leaf *to, | ||
114 | struct xfs_dir3_icleaf_hdr *from) | ||
115 | { | ||
116 | ASSERT(from->magic == XFS_DIR2_LEAF1_MAGIC || | ||
117 | from->magic == XFS_DIR3_LEAF1_MAGIC || | ||
118 | from->magic == XFS_DIR2_LEAFN_MAGIC || | ||
119 | from->magic == XFS_DIR3_LEAFN_MAGIC); | ||
120 | |||
121 | if (from->magic == XFS_DIR2_LEAF1_MAGIC || | ||
122 | from->magic == XFS_DIR2_LEAFN_MAGIC) { | ||
123 | to->hdr.info.forw = cpu_to_be32(from->forw); | ||
124 | to->hdr.info.back = cpu_to_be32(from->back); | ||
125 | to->hdr.info.magic = cpu_to_be16(from->magic); | ||
126 | to->hdr.count = cpu_to_be16(from->count); | ||
127 | to->hdr.stale = cpu_to_be16(from->stale); | ||
128 | } else { | ||
129 | struct xfs_dir3_leaf_hdr *hdr3 = (struct xfs_dir3_leaf_hdr *)to; | ||
130 | |||
131 | hdr3->info.hdr.forw = cpu_to_be32(from->forw); | ||
132 | hdr3->info.hdr.back = cpu_to_be32(from->back); | ||
133 | hdr3->info.hdr.magic = cpu_to_be16(from->magic); | ||
134 | hdr3->count = cpu_to_be16(from->count); | ||
135 | hdr3->stale = cpu_to_be16(from->stale); | ||
136 | } | ||
137 | } | ||
138 | |||
139 | bool | ||
140 | xfs_dir3_leaf_check_int( | ||
141 | struct xfs_mount *mp, | ||
142 | struct xfs_dir3_icleaf_hdr *hdr, | ||
143 | struct xfs_dir2_leaf *leaf) | ||
144 | { | ||
145 | struct xfs_dir2_leaf_entry *ents; | ||
146 | xfs_dir2_leaf_tail_t *ltp; | ||
147 | int stale; | ||
148 | int i; | ||
149 | |||
150 | ents = xfs_dir3_leaf_ents_p(leaf); | ||
151 | ltp = xfs_dir2_leaf_tail_p(mp, leaf); | ||
152 | |||
153 | /* | ||
154 | * XXX (dgc): This value is not restrictive enough. | ||
155 | * Should factor in the size of the bests table as well. | ||
156 | * We can deduce a value for that from di_size. | ||
157 | */ | ||
158 | if (hdr->count > xfs_dir3_max_leaf_ents(mp, leaf)) | ||
159 | return false; | ||
160 | |||
161 | /* Leaves and bests don't overlap in leaf format. */ | ||
162 | if ((hdr->magic == XFS_DIR2_LEAF1_MAGIC || | ||
163 | hdr->magic == XFS_DIR3_LEAF1_MAGIC) && | ||
164 | (char *)&ents[hdr->count] > (char *)xfs_dir2_leaf_bests_p(ltp)) | ||
165 | return false; | ||
166 | |||
167 | /* Check hash value order, count stale entries. */ | ||
168 | for (i = stale = 0; i < hdr->count; i++) { | ||
169 | if (i + 1 < hdr->count) { | ||
170 | if (be32_to_cpu(ents[i].hashval) > | ||
171 | be32_to_cpu(ents[i + 1].hashval)) | ||
172 | return false; | ||
173 | } | ||
174 | if (ents[i].address == cpu_to_be32(XFS_DIR2_NULL_DATAPTR)) | ||
175 | stale++; | ||
176 | } | ||
177 | if (hdr->stale != stale) | ||
178 | return false; | ||
179 | return true; | ||
180 | } | ||
181 | |||
182 | static bool | ||
183 | xfs_dir3_leaf_verify( | ||
53 | struct xfs_buf *bp, | 184 | struct xfs_buf *bp, |
54 | __be16 magic) | 185 | __uint16_t magic) |
186 | { | ||
187 | struct xfs_mount *mp = bp->b_target->bt_mount; | ||
188 | struct xfs_dir2_leaf *leaf = bp->b_addr; | ||
189 | struct xfs_dir3_icleaf_hdr leafhdr; | ||
190 | |||
191 | ASSERT(magic == XFS_DIR2_LEAF1_MAGIC || magic == XFS_DIR2_LEAFN_MAGIC); | ||
192 | |||
193 | xfs_dir3_leaf_hdr_from_disk(&leafhdr, leaf); | ||
194 | if (xfs_sb_version_hascrc(&mp->m_sb)) { | ||
195 | struct xfs_dir3_leaf_hdr *leaf3 = bp->b_addr; | ||
196 | |||
197 | if ((magic == XFS_DIR2_LEAF1_MAGIC && | ||
198 | leafhdr.magic != XFS_DIR3_LEAF1_MAGIC) || | ||
199 | (magic == XFS_DIR2_LEAFN_MAGIC && | ||
200 | leafhdr.magic != XFS_DIR3_LEAFN_MAGIC)) | ||
201 | return false; | ||
202 | |||
203 | if (!uuid_equal(&leaf3->info.uuid, &mp->m_sb.sb_uuid)) | ||
204 | return false; | ||
205 | if (be64_to_cpu(leaf3->info.blkno) != bp->b_bn) | ||
206 | return false; | ||
207 | } else { | ||
208 | if (leafhdr.magic != magic) | ||
209 | return false; | ||
210 | } | ||
211 | return xfs_dir3_leaf_check_int(mp, &leafhdr, leaf); | ||
212 | } | ||
213 | |||
214 | static void | ||
215 | __read_verify( | ||
216 | struct xfs_buf *bp, | ||
217 | __uint16_t magic) | ||
218 | { | ||
219 | struct xfs_mount *mp = bp->b_target->bt_mount; | ||
220 | |||
221 | if ((xfs_sb_version_hascrc(&mp->m_sb) && | ||
222 | !xfs_verify_cksum(bp->b_addr, BBTOB(bp->b_length), | ||
223 | XFS_DIR3_LEAF_CRC_OFF)) || | ||
224 | !xfs_dir3_leaf_verify(bp, magic)) { | ||
225 | XFS_CORRUPTION_ERROR(__func__, XFS_ERRLEVEL_LOW, mp, bp->b_addr); | ||
226 | xfs_buf_ioerror(bp, EFSCORRUPTED); | ||
227 | } | ||
228 | } | ||
229 | |||
230 | static void | ||
231 | __write_verify( | ||
232 | struct xfs_buf *bp, | ||
233 | __uint16_t magic) | ||
55 | { | 234 | { |
56 | struct xfs_mount *mp = bp->b_target->bt_mount; | 235 | struct xfs_mount *mp = bp->b_target->bt_mount; |
57 | struct xfs_dir2_leaf_hdr *hdr = bp->b_addr; | 236 | struct xfs_buf_log_item *bip = bp->b_fspriv; |
58 | int block_ok = 0; | 237 | struct xfs_dir3_leaf_hdr *hdr3 = bp->b_addr; |
59 | 238 | ||
60 | block_ok = hdr->info.magic == magic; | 239 | if (!xfs_dir3_leaf_verify(bp, magic)) { |
61 | if (!block_ok) { | 240 | XFS_CORRUPTION_ERROR(__func__, XFS_ERRLEVEL_LOW, mp, bp->b_addr); |
62 | XFS_CORRUPTION_ERROR(__func__, XFS_ERRLEVEL_LOW, mp, hdr); | ||
63 | xfs_buf_ioerror(bp, EFSCORRUPTED); | 241 | xfs_buf_ioerror(bp, EFSCORRUPTED); |
242 | return; | ||
64 | } | 243 | } |
244 | |||
245 | if (!xfs_sb_version_hascrc(&mp->m_sb)) | ||
246 | return; | ||
247 | |||
248 | if (bip) | ||
249 | hdr3->info.lsn = cpu_to_be64(bip->bli_item.li_lsn); | ||
250 | |||
251 | xfs_update_cksum(bp->b_addr, BBTOB(bp->b_length), XFS_DIR3_LEAF_CRC_OFF); | ||
65 | } | 252 | } |
66 | 253 | ||
67 | static void | 254 | static void |
68 | xfs_dir2_leaf1_read_verify( | 255 | xfs_dir3_leaf1_read_verify( |
69 | struct xfs_buf *bp) | 256 | struct xfs_buf *bp) |
70 | { | 257 | { |
71 | xfs_dir2_leaf_verify(bp, cpu_to_be16(XFS_DIR2_LEAF1_MAGIC)); | 258 | __read_verify(bp, XFS_DIR2_LEAF1_MAGIC); |
72 | } | 259 | } |
73 | 260 | ||
74 | static void | 261 | static void |
75 | xfs_dir2_leaf1_write_verify( | 262 | xfs_dir3_leaf1_write_verify( |
76 | struct xfs_buf *bp) | 263 | struct xfs_buf *bp) |
77 | { | 264 | { |
78 | xfs_dir2_leaf_verify(bp, cpu_to_be16(XFS_DIR2_LEAF1_MAGIC)); | 265 | __write_verify(bp, XFS_DIR2_LEAF1_MAGIC); |
79 | } | 266 | } |
80 | 267 | ||
81 | void | 268 | static void |
82 | xfs_dir2_leafn_read_verify( | 269 | xfs_dir3_leafn_read_verify( |
83 | struct xfs_buf *bp) | 270 | struct xfs_buf *bp) |
84 | { | 271 | { |
85 | xfs_dir2_leaf_verify(bp, cpu_to_be16(XFS_DIR2_LEAFN_MAGIC)); | 272 | __read_verify(bp, XFS_DIR2_LEAFN_MAGIC); |
86 | } | 273 | } |
87 | 274 | ||
88 | void | 275 | static void |
89 | xfs_dir2_leafn_write_verify( | 276 | xfs_dir3_leafn_write_verify( |
90 | struct xfs_buf *bp) | 277 | struct xfs_buf *bp) |
91 | { | 278 | { |
92 | xfs_dir2_leaf_verify(bp, cpu_to_be16(XFS_DIR2_LEAFN_MAGIC)); | 279 | __write_verify(bp, XFS_DIR2_LEAFN_MAGIC); |
93 | } | 280 | } |
94 | 281 | ||
95 | static const struct xfs_buf_ops xfs_dir2_leaf1_buf_ops = { | 282 | static const struct xfs_buf_ops xfs_dir3_leaf1_buf_ops = { |
96 | .verify_read = xfs_dir2_leaf1_read_verify, | 283 | .verify_read = xfs_dir3_leaf1_read_verify, |
97 | .verify_write = xfs_dir2_leaf1_write_verify, | 284 | .verify_write = xfs_dir3_leaf1_write_verify, |
98 | }; | 285 | }; |
99 | 286 | ||
100 | const struct xfs_buf_ops xfs_dir2_leafn_buf_ops = { | 287 | const struct xfs_buf_ops xfs_dir3_leafn_buf_ops = { |
101 | .verify_read = xfs_dir2_leafn_read_verify, | 288 | .verify_read = xfs_dir3_leafn_read_verify, |
102 | .verify_write = xfs_dir2_leafn_write_verify, | 289 | .verify_write = xfs_dir3_leafn_write_verify, |
103 | }; | 290 | }; |
104 | 291 | ||
105 | static int | 292 | static int |
106 | xfs_dir2_leaf_read( | 293 | xfs_dir3_leaf_read( |
107 | struct xfs_trans *tp, | 294 | struct xfs_trans *tp, |
108 | struct xfs_inode *dp, | 295 | struct xfs_inode *dp, |
109 | xfs_dablk_t fbno, | 296 | xfs_dablk_t fbno, |
@@ -111,11 +298,11 @@ xfs_dir2_leaf_read( | |||
111 | struct xfs_buf **bpp) | 298 | struct xfs_buf **bpp) |
112 | { | 299 | { |
113 | return xfs_da_read_buf(tp, dp, fbno, mappedbno, bpp, | 300 | return xfs_da_read_buf(tp, dp, fbno, mappedbno, bpp, |
114 | XFS_DATA_FORK, &xfs_dir2_leaf1_buf_ops); | 301 | XFS_DATA_FORK, &xfs_dir3_leaf1_buf_ops); |
115 | } | 302 | } |
116 | 303 | ||
117 | int | 304 | int |
118 | xfs_dir2_leafn_read( | 305 | xfs_dir3_leafn_read( |
119 | struct xfs_trans *tp, | 306 | struct xfs_trans *tp, |
120 | struct xfs_inode *dp, | 307 | struct xfs_inode *dp, |
121 | xfs_dablk_t fbno, | 308 | xfs_dablk_t fbno, |
@@ -123,7 +310,81 @@ xfs_dir2_leafn_read( | |||
123 | struct xfs_buf **bpp) | 310 | struct xfs_buf **bpp) |
124 | { | 311 | { |
125 | return xfs_da_read_buf(tp, dp, fbno, mappedbno, bpp, | 312 | return xfs_da_read_buf(tp, dp, fbno, mappedbno, bpp, |
126 | XFS_DATA_FORK, &xfs_dir2_leafn_buf_ops); | 313 | XFS_DATA_FORK, &xfs_dir3_leafn_buf_ops); |
314 | } | ||
315 | |||
316 | /* | ||
317 | * Initialize a new leaf block, leaf1 or leafn magic accepted. | ||
318 | */ | ||
319 | static void | ||
320 | xfs_dir3_leaf_init( | ||
321 | struct xfs_mount *mp, | ||
322 | struct xfs_buf *bp, | ||
323 | xfs_ino_t owner, | ||
324 | __uint16_t type) | ||
325 | { | ||
326 | struct xfs_dir2_leaf *leaf = bp->b_addr; | ||
327 | |||
328 | ASSERT(type == XFS_DIR2_LEAF1_MAGIC || type == XFS_DIR2_LEAFN_MAGIC); | ||
329 | |||
330 | if (xfs_sb_version_hascrc(&mp->m_sb)) { | ||
331 | struct xfs_dir3_leaf_hdr *leaf3 = bp->b_addr; | ||
332 | |||
333 | memset(leaf3, 0, sizeof(*leaf3)); | ||
334 | |||
335 | leaf3->info.hdr.magic = (type == XFS_DIR2_LEAF1_MAGIC) | ||
336 | ? cpu_to_be16(XFS_DIR3_LEAF1_MAGIC) | ||
337 | : cpu_to_be16(XFS_DIR3_LEAFN_MAGIC); | ||
338 | leaf3->info.blkno = cpu_to_be64(bp->b_bn); | ||
339 | leaf3->info.owner = cpu_to_be64(owner); | ||
340 | uuid_copy(&leaf3->info.uuid, &mp->m_sb.sb_uuid); | ||
341 | } else { | ||
342 | memset(leaf, 0, sizeof(*leaf)); | ||
343 | leaf->hdr.info.magic = cpu_to_be16(type); | ||
344 | } | ||
345 | |||
346 | /* | ||
347 | * If it's a leaf-format directory initialize the tail. | ||
348 | * Caller is responsible for initialising the bests table. | ||
349 | */ | ||
350 | if (type == XFS_DIR2_LEAF1_MAGIC) { | ||
351 | struct xfs_dir2_leaf_tail *ltp; | ||
352 | |||
353 | ltp = xfs_dir2_leaf_tail_p(mp, leaf); | ||
354 | ltp->bestcount = 0; | ||
355 | bp->b_ops = &xfs_dir3_leaf1_buf_ops; | ||
356 | } else | ||
357 | bp->b_ops = &xfs_dir3_leafn_buf_ops; | ||
358 | } | ||
359 | |||
360 | int | ||
361 | xfs_dir3_leaf_get_buf( | ||
362 | xfs_da_args_t *args, | ||
363 | xfs_dir2_db_t bno, | ||
364 | struct xfs_buf **bpp, | ||
365 | __uint16_t magic) | ||
366 | { | ||
367 | struct xfs_inode *dp = args->dp; | ||
368 | struct xfs_trans *tp = args->trans; | ||
369 | struct xfs_mount *mp = dp->i_mount; | ||
370 | struct xfs_buf *bp; | ||
371 | int error; | ||
372 | |||
373 | ASSERT(magic == XFS_DIR2_LEAF1_MAGIC || magic == XFS_DIR2_LEAFN_MAGIC); | ||
374 | ASSERT(bno >= XFS_DIR2_LEAF_FIRSTDB(mp) && | ||
375 | bno < XFS_DIR2_FREE_FIRSTDB(mp)); | ||
376 | |||
377 | error = xfs_da_get_buf(tp, dp, xfs_dir2_db_to_da(mp, bno), -1, &bp, | ||
378 | XFS_DATA_FORK); | ||
379 | if (error) | ||
380 | return error; | ||
381 | |||
382 | xfs_dir3_leaf_init(mp, bp, dp->i_ino, magic); | ||
383 | xfs_dir3_leaf_log_header(tp, bp); | ||
384 | if (magic == XFS_DIR2_LEAF1_MAGIC) | ||
385 | xfs_dir3_leaf_log_tail(tp, bp); | ||
386 | *bpp = bp; | ||
387 | return 0; | ||
127 | } | 388 | } |
128 | 389 | ||
129 | /* | 390 | /* |
@@ -150,6 +411,8 @@ xfs_dir2_block_to_leaf( | |||
150 | int needscan; /* need to rescan bestfree */ | 411 | int needscan; /* need to rescan bestfree */ |
151 | xfs_trans_t *tp; /* transaction pointer */ | 412 | xfs_trans_t *tp; /* transaction pointer */ |
152 | struct xfs_dir2_data_free *bf; | 413 | struct xfs_dir2_data_free *bf; |
414 | struct xfs_dir2_leaf_entry *ents; | ||
415 | struct xfs_dir3_icleaf_hdr leafhdr; | ||
153 | 416 | ||
154 | trace_xfs_dir2_block_to_leaf(args); | 417 | trace_xfs_dir2_block_to_leaf(args); |
155 | 418 | ||
@@ -169,27 +432,33 @@ xfs_dir2_block_to_leaf( | |||
169 | /* | 432 | /* |
170 | * Initialize the leaf block, get a buffer for it. | 433 | * Initialize the leaf block, get a buffer for it. |
171 | */ | 434 | */ |
172 | if ((error = xfs_dir2_leaf_init(args, ldb, &lbp, XFS_DIR2_LEAF1_MAGIC))) { | 435 | error = xfs_dir3_leaf_get_buf(args, ldb, &lbp, XFS_DIR2_LEAF1_MAGIC); |
436 | if (error) | ||
173 | return error; | 437 | return error; |
174 | } | 438 | |
175 | ASSERT(lbp != NULL); | ||
176 | leaf = lbp->b_addr; | 439 | leaf = lbp->b_addr; |
177 | hdr = dbp->b_addr; | 440 | hdr = dbp->b_addr; |
178 | xfs_dir3_data_check(dp, dbp); | 441 | xfs_dir3_data_check(dp, dbp); |
179 | btp = xfs_dir2_block_tail_p(mp, hdr); | 442 | btp = xfs_dir2_block_tail_p(mp, hdr); |
180 | blp = xfs_dir2_block_leaf_p(btp); | 443 | blp = xfs_dir2_block_leaf_p(btp); |
181 | bf = xfs_dir3_data_bestfree_p(hdr); | 444 | bf = xfs_dir3_data_bestfree_p(hdr); |
445 | ents = xfs_dir3_leaf_ents_p(leaf); | ||
446 | |||
182 | /* | 447 | /* |
183 | * Set the counts in the leaf header. | 448 | * Set the counts in the leaf header. |
184 | */ | 449 | */ |
185 | leaf->hdr.count = cpu_to_be16(be32_to_cpu(btp->count)); | 450 | xfs_dir3_leaf_hdr_from_disk(&leafhdr, leaf); |
186 | leaf->hdr.stale = cpu_to_be16(be32_to_cpu(btp->stale)); | 451 | leafhdr.count = be32_to_cpu(btp->count); |
452 | leafhdr.stale = be32_to_cpu(btp->stale); | ||
453 | xfs_dir3_leaf_hdr_to_disk(leaf, &leafhdr); | ||
454 | xfs_dir3_leaf_log_header(tp, lbp); | ||
455 | |||
187 | /* | 456 | /* |
188 | * Could compact these but I think we always do the conversion | 457 | * Could compact these but I think we always do the conversion |
189 | * after squeezing out stale entries. | 458 | * after squeezing out stale entries. |
190 | */ | 459 | */ |
191 | memcpy(leaf->ents, blp, be32_to_cpu(btp->count) * sizeof(xfs_dir2_leaf_entry_t)); | 460 | memcpy(ents, blp, be32_to_cpu(btp->count) * sizeof(xfs_dir2_leaf_entry_t)); |
192 | xfs_dir2_leaf_log_ents(tp, lbp, 0, be16_to_cpu(leaf->hdr.count) - 1); | 461 | xfs_dir3_leaf_log_ents(tp, lbp, 0, leafhdr.count - 1); |
193 | needscan = 0; | 462 | needscan = 0; |
194 | needlog = 1; | 463 | needlog = 1; |
195 | /* | 464 | /* |
@@ -224,15 +493,16 @@ xfs_dir2_block_to_leaf( | |||
224 | */ | 493 | */ |
225 | if (needlog) | 494 | if (needlog) |
226 | xfs_dir2_data_log_header(tp, dbp); | 495 | xfs_dir2_data_log_header(tp, dbp); |
227 | xfs_dir2_leaf_check(dp, lbp); | 496 | xfs_dir3_leaf_check(mp, lbp); |
228 | xfs_dir3_data_check(dp, dbp); | 497 | xfs_dir3_data_check(dp, dbp); |
229 | xfs_dir2_leaf_log_bests(tp, lbp, 0, 0); | 498 | xfs_dir3_leaf_log_bests(tp, lbp, 0, 0); |
230 | return 0; | 499 | return 0; |
231 | } | 500 | } |
232 | 501 | ||
233 | STATIC void | 502 | STATIC void |
234 | xfs_dir2_leaf_find_stale( | 503 | xfs_dir3_leaf_find_stale( |
235 | struct xfs_dir2_leaf *leaf, | 504 | struct xfs_dir3_icleaf_hdr *leafhdr, |
505 | struct xfs_dir2_leaf_entry *ents, | ||
236 | int index, | 506 | int index, |
237 | int *lowstale, | 507 | int *lowstale, |
238 | int *highstale) | 508 | int *highstale) |
@@ -241,7 +511,7 @@ xfs_dir2_leaf_find_stale( | |||
241 | * Find the first stale entry before our index, if any. | 511 | * Find the first stale entry before our index, if any. |
242 | */ | 512 | */ |
243 | for (*lowstale = index - 1; *lowstale >= 0; --*lowstale) { | 513 | for (*lowstale = index - 1; *lowstale >= 0; --*lowstale) { |
244 | if (leaf->ents[*lowstale].address == | 514 | if (ents[*lowstale].address == |
245 | cpu_to_be32(XFS_DIR2_NULL_DATAPTR)) | 515 | cpu_to_be32(XFS_DIR2_NULL_DATAPTR)) |
246 | break; | 516 | break; |
247 | } | 517 | } |
@@ -251,10 +521,8 @@ xfs_dir2_leaf_find_stale( | |||
251 | * Stop if the result would require moving more entries than using | 521 | * Stop if the result would require moving more entries than using |
252 | * lowstale. | 522 | * lowstale. |
253 | */ | 523 | */ |
254 | for (*highstale = index; | 524 | for (*highstale = index; *highstale < leafhdr->count; ++*highstale) { |
255 | *highstale < be16_to_cpu(leaf->hdr.count); | 525 | if (ents[*highstale].address == |
256 | ++*highstale) { | ||
257 | if (leaf->ents[*highstale].address == | ||
258 | cpu_to_be32(XFS_DIR2_NULL_DATAPTR)) | 526 | cpu_to_be32(XFS_DIR2_NULL_DATAPTR)) |
259 | break; | 527 | break; |
260 | if (*lowstale >= 0 && index - *lowstale <= *highstale - index) | 528 | if (*lowstale >= 0 && index - *lowstale <= *highstale - index) |
@@ -263,8 +531,9 @@ xfs_dir2_leaf_find_stale( | |||
263 | } | 531 | } |
264 | 532 | ||
265 | struct xfs_dir2_leaf_entry * | 533 | struct xfs_dir2_leaf_entry * |
266 | xfs_dir2_leaf_find_entry( | 534 | xfs_dir3_leaf_find_entry( |
267 | xfs_dir2_leaf_t *leaf, /* leaf structure */ | 535 | struct xfs_dir3_icleaf_hdr *leafhdr, |
536 | struct xfs_dir2_leaf_entry *ents, | ||
268 | int index, /* leaf table position */ | 537 | int index, /* leaf table position */ |
269 | int compact, /* need to compact leaves */ | 538 | int compact, /* need to compact leaves */ |
270 | int lowstale, /* index of prev stale leaf */ | 539 | int lowstale, /* index of prev stale leaf */ |
@@ -272,7 +541,7 @@ xfs_dir2_leaf_find_entry( | |||
272 | int *lfloglow, /* low leaf logging index */ | 541 | int *lfloglow, /* low leaf logging index */ |
273 | int *lfloghigh) /* high leaf logging index */ | 542 | int *lfloghigh) /* high leaf logging index */ |
274 | { | 543 | { |
275 | if (!leaf->hdr.stale) { | 544 | if (!leafhdr->stale) { |
276 | xfs_dir2_leaf_entry_t *lep; /* leaf entry table pointer */ | 545 | xfs_dir2_leaf_entry_t *lep; /* leaf entry table pointer */ |
277 | 546 | ||
278 | /* | 547 | /* |
@@ -280,18 +549,16 @@ xfs_dir2_leaf_find_entry( | |||
280 | * | 549 | * |
281 | * If there are no stale entries, just insert a hole at index. | 550 | * If there are no stale entries, just insert a hole at index. |
282 | */ | 551 | */ |
283 | lep = &leaf->ents[index]; | 552 | lep = &ents[index]; |
284 | if (index < be16_to_cpu(leaf->hdr.count)) | 553 | if (index < leafhdr->count) |
285 | memmove(lep + 1, lep, | 554 | memmove(lep + 1, lep, |
286 | (be16_to_cpu(leaf->hdr.count) - index) * | 555 | (leafhdr->count - index) * sizeof(*lep)); |
287 | sizeof(*lep)); | ||
288 | 556 | ||
289 | /* | 557 | /* |
290 | * Record low and high logging indices for the leaf. | 558 | * Record low and high logging indices for the leaf. |
291 | */ | 559 | */ |
292 | *lfloglow = index; | 560 | *lfloglow = index; |
293 | *lfloghigh = be16_to_cpu(leaf->hdr.count); | 561 | *lfloghigh = leafhdr->count++; |
294 | be16_add_cpu(&leaf->hdr.count, 1); | ||
295 | return lep; | 562 | return lep; |
296 | } | 563 | } |
297 | 564 | ||
@@ -305,16 +572,17 @@ xfs_dir2_leaf_find_entry( | |||
305 | * entries before and after our insertion point. | 572 | * entries before and after our insertion point. |
306 | */ | 573 | */ |
307 | if (compact == 0) | 574 | if (compact == 0) |
308 | xfs_dir2_leaf_find_stale(leaf, index, &lowstale, &highstale); | 575 | xfs_dir3_leaf_find_stale(leafhdr, ents, index, |
576 | &lowstale, &highstale); | ||
309 | 577 | ||
310 | /* | 578 | /* |
311 | * If the low one is better, use it. | 579 | * If the low one is better, use it. |
312 | */ | 580 | */ |
313 | if (lowstale >= 0 && | 581 | if (lowstale >= 0 && |
314 | (highstale == be16_to_cpu(leaf->hdr.count) || | 582 | (highstale == leafhdr->count || |
315 | index - lowstale - 1 < highstale - index)) { | 583 | index - lowstale - 1 < highstale - index)) { |
316 | ASSERT(index - lowstale - 1 >= 0); | 584 | ASSERT(index - lowstale - 1 >= 0); |
317 | ASSERT(leaf->ents[lowstale].address == | 585 | ASSERT(ents[lowstale].address == |
318 | cpu_to_be32(XFS_DIR2_NULL_DATAPTR)); | 586 | cpu_to_be32(XFS_DIR2_NULL_DATAPTR)); |
319 | 587 | ||
320 | /* | 588 | /* |
@@ -322,37 +590,34 @@ xfs_dir2_leaf_find_entry( | |||
322 | * for the new entry. | 590 | * for the new entry. |
323 | */ | 591 | */ |
324 | if (index - lowstale - 1 > 0) { | 592 | if (index - lowstale - 1 > 0) { |
325 | memmove(&leaf->ents[lowstale], | 593 | memmove(&ents[lowstale], &ents[lowstale + 1], |
326 | &leaf->ents[lowstale + 1], | ||
327 | (index - lowstale - 1) * | 594 | (index - lowstale - 1) * |
328 | sizeof(xfs_dir2_leaf_entry_t)); | 595 | sizeof(xfs_dir2_leaf_entry_t)); |
329 | } | 596 | } |
330 | *lfloglow = MIN(lowstale, *lfloglow); | 597 | *lfloglow = MIN(lowstale, *lfloglow); |
331 | *lfloghigh = MAX(index - 1, *lfloghigh); | 598 | *lfloghigh = MAX(index - 1, *lfloghigh); |
332 | be16_add_cpu(&leaf->hdr.stale, -1); | 599 | leafhdr->stale--; |
333 | return &leaf->ents[index - 1]; | 600 | return &ents[index - 1]; |
334 | } | 601 | } |
335 | 602 | ||
336 | /* | 603 | /* |
337 | * The high one is better, so use that one. | 604 | * The high one is better, so use that one. |
338 | */ | 605 | */ |
339 | ASSERT(highstale - index >= 0); | 606 | ASSERT(highstale - index >= 0); |
340 | ASSERT(leaf->ents[highstale].address == | 607 | ASSERT(ents[highstale].address == cpu_to_be32(XFS_DIR2_NULL_DATAPTR)); |
341 | cpu_to_be32(XFS_DIR2_NULL_DATAPTR)); | ||
342 | 608 | ||
343 | /* | 609 | /* |
344 | * Copy entries down to cover the stale entry and make room for the | 610 | * Copy entries down to cover the stale entry and make room for the |
345 | * new entry. | 611 | * new entry. |
346 | */ | 612 | */ |
347 | if (highstale - index > 0) { | 613 | if (highstale - index > 0) { |
348 | memmove(&leaf->ents[index + 1], | 614 | memmove(&ents[index + 1], &ents[index], |
349 | &leaf->ents[index], | ||
350 | (highstale - index) * sizeof(xfs_dir2_leaf_entry_t)); | 615 | (highstale - index) * sizeof(xfs_dir2_leaf_entry_t)); |
351 | } | 616 | } |
352 | *lfloglow = MIN(index, *lfloglow); | 617 | *lfloglow = MIN(index, *lfloglow); |
353 | *lfloghigh = MAX(highstale, *lfloghigh); | 618 | *lfloghigh = MAX(highstale, *lfloghigh); |
354 | be16_add_cpu(&leaf->hdr.stale, -1); | 619 | leafhdr->stale--; |
355 | return &leaf->ents[index]; | 620 | return &ents[index]; |
356 | } | 621 | } |
357 | 622 | ||
358 | /* | 623 | /* |
@@ -390,6 +655,8 @@ xfs_dir2_leaf_addname( | |||
390 | xfs_trans_t *tp; /* transaction pointer */ | 655 | xfs_trans_t *tp; /* transaction pointer */ |
391 | xfs_dir2_db_t use_block; /* data block number */ | 656 | xfs_dir2_db_t use_block; /* data block number */ |
392 | struct xfs_dir2_data_free *bf; /* bestfree table */ | 657 | struct xfs_dir2_data_free *bf; /* bestfree table */ |
658 | struct xfs_dir2_leaf_entry *ents; | ||
659 | struct xfs_dir3_icleaf_hdr leafhdr; | ||
393 | 660 | ||
394 | trace_xfs_dir2_leaf_addname(args); | 661 | trace_xfs_dir2_leaf_addname(args); |
395 | 662 | ||
@@ -397,7 +664,7 @@ xfs_dir2_leaf_addname( | |||
397 | tp = args->trans; | 664 | tp = args->trans; |
398 | mp = dp->i_mount; | 665 | mp = dp->i_mount; |
399 | 666 | ||
400 | error = xfs_dir2_leaf_read(tp, dp, mp->m_dirleafblk, -1, &lbp); | 667 | error = xfs_dir3_leaf_read(tp, dp, mp->m_dirleafblk, -1, &lbp); |
401 | if (error) | 668 | if (error) |
402 | return error; | 669 | return error; |
403 | 670 | ||
@@ -410,16 +677,19 @@ xfs_dir2_leaf_addname( | |||
410 | index = xfs_dir2_leaf_search_hash(args, lbp); | 677 | index = xfs_dir2_leaf_search_hash(args, lbp); |
411 | leaf = lbp->b_addr; | 678 | leaf = lbp->b_addr; |
412 | ltp = xfs_dir2_leaf_tail_p(mp, leaf); | 679 | ltp = xfs_dir2_leaf_tail_p(mp, leaf); |
680 | ents = xfs_dir3_leaf_ents_p(leaf); | ||
681 | xfs_dir3_leaf_hdr_from_disk(&leafhdr, leaf); | ||
413 | bestsp = xfs_dir2_leaf_bests_p(ltp); | 682 | bestsp = xfs_dir2_leaf_bests_p(ltp); |
414 | length = xfs_dir2_data_entsize(args->namelen); | 683 | length = xfs_dir2_data_entsize(args->namelen); |
684 | |||
415 | /* | 685 | /* |
416 | * See if there are any entries with the same hash value | 686 | * See if there are any entries with the same hash value |
417 | * and space in their block for the new entry. | 687 | * and space in their block for the new entry. |
418 | * This is good because it puts multiple same-hash value entries | 688 | * This is good because it puts multiple same-hash value entries |
419 | * in a data block, improving the lookup of those entries. | 689 | * in a data block, improving the lookup of those entries. |
420 | */ | 690 | */ |
421 | for (use_block = -1, lep = &leaf->ents[index]; | 691 | for (use_block = -1, lep = &ents[index]; |
422 | index < be16_to_cpu(leaf->hdr.count) && be32_to_cpu(lep->hashval) == args->hashval; | 692 | index < leafhdr.count && be32_to_cpu(lep->hashval) == args->hashval; |
423 | index++, lep++) { | 693 | index++, lep++) { |
424 | if (be32_to_cpu(lep->address) == XFS_DIR2_NULL_DATAPTR) | 694 | if (be32_to_cpu(lep->address) == XFS_DIR2_NULL_DATAPTR) |
425 | continue; | 695 | continue; |
@@ -452,7 +722,7 @@ xfs_dir2_leaf_addname( | |||
452 | * How many bytes do we need in the leaf block? | 722 | * How many bytes do we need in the leaf block? |
453 | */ | 723 | */ |
454 | needbytes = 0; | 724 | needbytes = 0; |
455 | if (!leaf->hdr.stale) | 725 | if (!leafhdr.stale) |
456 | needbytes += sizeof(xfs_dir2_leaf_entry_t); | 726 | needbytes += sizeof(xfs_dir2_leaf_entry_t); |
457 | if (use_block == -1) | 727 | if (use_block == -1) |
458 | needbytes += sizeof(xfs_dir2_data_off_t); | 728 | needbytes += sizeof(xfs_dir2_data_off_t); |
@@ -467,16 +737,15 @@ xfs_dir2_leaf_addname( | |||
467 | * If we don't have enough free bytes but we can make enough | 737 | * If we don't have enough free bytes but we can make enough |
468 | * by compacting out stale entries, we'll do that. | 738 | * by compacting out stale entries, we'll do that. |
469 | */ | 739 | */ |
470 | if ((char *)bestsp - (char *)&leaf->ents[be16_to_cpu(leaf->hdr.count)] < | 740 | if ((char *)bestsp - (char *)&ents[leafhdr.count] < needbytes && |
471 | needbytes && be16_to_cpu(leaf->hdr.stale) > 1) { | 741 | leafhdr.stale > 1) |
472 | compact = 1; | 742 | compact = 1; |
473 | } | 743 | |
474 | /* | 744 | /* |
475 | * Otherwise if we don't have enough free bytes we need to | 745 | * Otherwise if we don't have enough free bytes we need to |
476 | * convert to node form. | 746 | * convert to node form. |
477 | */ | 747 | */ |
478 | else if ((char *)bestsp - (char *)&leaf->ents[be16_to_cpu( | 748 | else if ((char *)bestsp - (char *)&ents[leafhdr.count] < needbytes) { |
479 | leaf->hdr.count)] < needbytes) { | ||
480 | /* | 749 | /* |
481 | * Just checking or no space reservation, give up. | 750 | * Just checking or no space reservation, give up. |
482 | */ | 751 | */ |
@@ -524,15 +793,15 @@ xfs_dir2_leaf_addname( | |||
524 | * point later. | 793 | * point later. |
525 | */ | 794 | */ |
526 | if (compact) { | 795 | if (compact) { |
527 | xfs_dir2_leaf_compact_x1(lbp, &index, &lowstale, &highstale, | 796 | xfs_dir3_leaf_compact_x1(&leafhdr, ents, &index, &lowstale, |
528 | &lfloglow, &lfloghigh); | 797 | &highstale, &lfloglow, &lfloghigh); |
529 | } | 798 | } |
530 | /* | 799 | /* |
531 | * There are stale entries, so we'll need log-low and log-high | 800 | * There are stale entries, so we'll need log-low and log-high |
532 | * impossibly bad values later. | 801 | * impossibly bad values later. |
533 | */ | 802 | */ |
534 | else if (be16_to_cpu(leaf->hdr.stale)) { | 803 | else if (leafhdr.stale) { |
535 | lfloglow = be16_to_cpu(leaf->hdr.count); | 804 | lfloglow = leafhdr.count; |
536 | lfloghigh = -1; | 805 | lfloghigh = -1; |
537 | } | 806 | } |
538 | /* | 807 | /* |
@@ -564,14 +833,14 @@ xfs_dir2_leaf_addname( | |||
564 | memmove(&bestsp[0], &bestsp[1], | 833 | memmove(&bestsp[0], &bestsp[1], |
565 | be32_to_cpu(ltp->bestcount) * sizeof(bestsp[0])); | 834 | be32_to_cpu(ltp->bestcount) * sizeof(bestsp[0])); |
566 | be32_add_cpu(<p->bestcount, 1); | 835 | be32_add_cpu(<p->bestcount, 1); |
567 | xfs_dir2_leaf_log_tail(tp, lbp); | 836 | xfs_dir3_leaf_log_tail(tp, lbp); |
568 | xfs_dir2_leaf_log_bests(tp, lbp, 0, be32_to_cpu(ltp->bestcount) - 1); | 837 | xfs_dir3_leaf_log_bests(tp, lbp, 0, be32_to_cpu(ltp->bestcount) - 1); |
569 | } | 838 | } |
570 | /* | 839 | /* |
571 | * If we're filling in a previously empty block just log it. | 840 | * If we're filling in a previously empty block just log it. |
572 | */ | 841 | */ |
573 | else | 842 | else |
574 | xfs_dir2_leaf_log_bests(tp, lbp, use_block, use_block); | 843 | xfs_dir3_leaf_log_bests(tp, lbp, use_block, use_block); |
575 | hdr = dbp->b_addr; | 844 | hdr = dbp->b_addr; |
576 | bf = xfs_dir3_data_bestfree_p(hdr); | 845 | bf = xfs_dir3_data_bestfree_p(hdr); |
577 | bestsp[use_block] = bf[0].length; | 846 | bestsp[use_block] = bf[0].length; |
@@ -632,10 +901,10 @@ xfs_dir2_leaf_addname( | |||
632 | if (be16_to_cpu(bestsp[use_block]) != be16_to_cpu(bf[0].length)) { | 901 | if (be16_to_cpu(bestsp[use_block]) != be16_to_cpu(bf[0].length)) { |
633 | bestsp[use_block] = bf[0].length; | 902 | bestsp[use_block] = bf[0].length; |
634 | if (!grown) | 903 | if (!grown) |
635 | xfs_dir2_leaf_log_bests(tp, lbp, use_block, use_block); | 904 | xfs_dir3_leaf_log_bests(tp, lbp, use_block, use_block); |
636 | } | 905 | } |
637 | 906 | ||
638 | lep = xfs_dir2_leaf_find_entry(leaf, index, compact, lowstale, | 907 | lep = xfs_dir3_leaf_find_entry(&leafhdr, ents, index, compact, lowstale, |
639 | highstale, &lfloglow, &lfloghigh); | 908 | highstale, &lfloglow, &lfloghigh); |
640 | 909 | ||
641 | /* | 910 | /* |
@@ -647,82 +916,40 @@ xfs_dir2_leaf_addname( | |||
647 | /* | 916 | /* |
648 | * Log the leaf fields and give up the buffers. | 917 | * Log the leaf fields and give up the buffers. |
649 | */ | 918 | */ |
650 | xfs_dir2_leaf_log_header(tp, lbp); | 919 | xfs_dir3_leaf_hdr_to_disk(leaf, &leafhdr); |
651 | xfs_dir2_leaf_log_ents(tp, lbp, lfloglow, lfloghigh); | 920 | xfs_dir3_leaf_log_header(tp, lbp); |
652 | xfs_dir2_leaf_check(dp, lbp); | 921 | xfs_dir3_leaf_log_ents(tp, lbp, lfloglow, lfloghigh); |
922 | xfs_dir3_leaf_check(mp, lbp); | ||
653 | xfs_dir3_data_check(dp, dbp); | 923 | xfs_dir3_data_check(dp, dbp); |
654 | return 0; | 924 | return 0; |
655 | } | 925 | } |
656 | 926 | ||
657 | #ifdef DEBUG | ||
658 | /* | ||
659 | * Check the internal consistency of a leaf1 block. | ||
660 | * Pop an assert if something is wrong. | ||
661 | */ | ||
662 | STATIC void | ||
663 | xfs_dir2_leaf_check( | ||
664 | struct xfs_inode *dp, /* incore directory inode */ | ||
665 | struct xfs_buf *bp) /* leaf's buffer */ | ||
666 | { | ||
667 | int i; /* leaf index */ | ||
668 | xfs_dir2_leaf_t *leaf; /* leaf structure */ | ||
669 | xfs_dir2_leaf_tail_t *ltp; /* leaf tail pointer */ | ||
670 | xfs_mount_t *mp; /* filesystem mount point */ | ||
671 | int stale; /* count of stale leaves */ | ||
672 | |||
673 | leaf = bp->b_addr; | ||
674 | mp = dp->i_mount; | ||
675 | ASSERT(leaf->hdr.info.magic == cpu_to_be16(XFS_DIR2_LEAF1_MAGIC)); | ||
676 | /* | ||
677 | * This value is not restrictive enough. | ||
678 | * Should factor in the size of the bests table as well. | ||
679 | * We can deduce a value for that from di_size. | ||
680 | */ | ||
681 | ASSERT(be16_to_cpu(leaf->hdr.count) <= xfs_dir2_max_leaf_ents(mp)); | ||
682 | ltp = xfs_dir2_leaf_tail_p(mp, leaf); | ||
683 | /* | ||
684 | * Leaves and bests don't overlap. | ||
685 | */ | ||
686 | ASSERT((char *)&leaf->ents[be16_to_cpu(leaf->hdr.count)] <= | ||
687 | (char *)xfs_dir2_leaf_bests_p(ltp)); | ||
688 | /* | ||
689 | * Check hash value order, count stale entries. | ||
690 | */ | ||
691 | for (i = stale = 0; i < be16_to_cpu(leaf->hdr.count); i++) { | ||
692 | if (i + 1 < be16_to_cpu(leaf->hdr.count)) | ||
693 | ASSERT(be32_to_cpu(leaf->ents[i].hashval) <= | ||
694 | be32_to_cpu(leaf->ents[i + 1].hashval)); | ||
695 | if (leaf->ents[i].address == cpu_to_be32(XFS_DIR2_NULL_DATAPTR)) | ||
696 | stale++; | ||
697 | } | ||
698 | ASSERT(be16_to_cpu(leaf->hdr.stale) == stale); | ||
699 | } | ||
700 | #endif /* DEBUG */ | ||
701 | |||
702 | /* | 927 | /* |
703 | * Compact out any stale entries in the leaf. | 928 | * Compact out any stale entries in the leaf. |
704 | * Log the header and changed leaf entries, if any. | 929 | * Log the header and changed leaf entries, if any. |
705 | */ | 930 | */ |
706 | void | 931 | void |
707 | xfs_dir2_leaf_compact( | 932 | xfs_dir3_leaf_compact( |
708 | xfs_da_args_t *args, /* operation arguments */ | 933 | xfs_da_args_t *args, /* operation arguments */ |
934 | struct xfs_dir3_icleaf_hdr *leafhdr, | ||
709 | struct xfs_buf *bp) /* leaf buffer */ | 935 | struct xfs_buf *bp) /* leaf buffer */ |
710 | { | 936 | { |
711 | int from; /* source leaf index */ | 937 | int from; /* source leaf index */ |
712 | xfs_dir2_leaf_t *leaf; /* leaf structure */ | 938 | xfs_dir2_leaf_t *leaf; /* leaf structure */ |
713 | int loglow; /* first leaf entry to log */ | 939 | int loglow; /* first leaf entry to log */ |
714 | int to; /* target leaf index */ | 940 | int to; /* target leaf index */ |
941 | struct xfs_dir2_leaf_entry *ents; | ||
715 | 942 | ||
716 | leaf = bp->b_addr; | 943 | leaf = bp->b_addr; |
717 | if (!leaf->hdr.stale) { | 944 | if (!leafhdr->stale) |
718 | return; | 945 | return; |
719 | } | 946 | |
720 | /* | 947 | /* |
721 | * Compress out the stale entries in place. | 948 | * Compress out the stale entries in place. |
722 | */ | 949 | */ |
723 | for (from = to = 0, loglow = -1; from < be16_to_cpu(leaf->hdr.count); from++) { | 950 | ents = xfs_dir3_leaf_ents_p(leaf); |
724 | if (leaf->ents[from].address == | 951 | for (from = to = 0, loglow = -1; from < leafhdr->count; from++) { |
725 | cpu_to_be32(XFS_DIR2_NULL_DATAPTR)) | 952 | if (ents[from].address == cpu_to_be32(XFS_DIR2_NULL_DATAPTR)) |
726 | continue; | 953 | continue; |
727 | /* | 954 | /* |
728 | * Only actually copy the entries that are different. | 955 | * Only actually copy the entries that are different. |
@@ -730,19 +957,21 @@ xfs_dir2_leaf_compact( | |||
730 | if (from > to) { | 957 | if (from > to) { |
731 | if (loglow == -1) | 958 | if (loglow == -1) |
732 | loglow = to; | 959 | loglow = to; |
733 | leaf->ents[to] = leaf->ents[from]; | 960 | ents[to] = ents[from]; |
734 | } | 961 | } |
735 | to++; | 962 | to++; |
736 | } | 963 | } |
737 | /* | 964 | /* |
738 | * Update and log the header, log the leaf entries. | 965 | * Update and log the header, log the leaf entries. |
739 | */ | 966 | */ |
740 | ASSERT(be16_to_cpu(leaf->hdr.stale) == from - to); | 967 | ASSERT(leafhdr->stale == from - to); |
741 | be16_add_cpu(&leaf->hdr.count, -(be16_to_cpu(leaf->hdr.stale))); | 968 | leafhdr->count -= leafhdr->stale; |
742 | leaf->hdr.stale = 0; | 969 | leafhdr->stale = 0; |
743 | xfs_dir2_leaf_log_header(args->trans, bp); | 970 | |
971 | xfs_dir3_leaf_hdr_to_disk(leaf, leafhdr); | ||
972 | xfs_dir3_leaf_log_header(args->trans, bp); | ||
744 | if (loglow != -1) | 973 | if (loglow != -1) |
745 | xfs_dir2_leaf_log_ents(args->trans, bp, loglow, to - 1); | 974 | xfs_dir3_leaf_log_ents(args->trans, bp, loglow, to - 1); |
746 | } | 975 | } |
747 | 976 | ||
748 | /* | 977 | /* |
@@ -754,8 +983,9 @@ xfs_dir2_leaf_compact( | |||
754 | * and leaf logging indices. | 983 | * and leaf logging indices. |
755 | */ | 984 | */ |
756 | void | 985 | void |
757 | xfs_dir2_leaf_compact_x1( | 986 | xfs_dir3_leaf_compact_x1( |
758 | struct xfs_buf *bp, /* leaf buffer */ | 987 | struct xfs_dir3_icleaf_hdr *leafhdr, |
988 | struct xfs_dir2_leaf_entry *ents, | ||
759 | int *indexp, /* insertion index */ | 989 | int *indexp, /* insertion index */ |
760 | int *lowstalep, /* out: stale entry before us */ | 990 | int *lowstalep, /* out: stale entry before us */ |
761 | int *highstalep, /* out: stale entry after us */ | 991 | int *highstalep, /* out: stale entry after us */ |
@@ -766,22 +996,20 @@ xfs_dir2_leaf_compact_x1( | |||
766 | int highstale; /* stale entry at/after index */ | 996 | int highstale; /* stale entry at/after index */ |
767 | int index; /* insertion index */ | 997 | int index; /* insertion index */ |
768 | int keepstale; /* source index of kept stale */ | 998 | int keepstale; /* source index of kept stale */ |
769 | xfs_dir2_leaf_t *leaf; /* leaf structure */ | ||
770 | int lowstale; /* stale entry before index */ | 999 | int lowstale; /* stale entry before index */ |
771 | int newindex=0; /* new insertion index */ | 1000 | int newindex=0; /* new insertion index */ |
772 | int to; /* destination copy index */ | 1001 | int to; /* destination copy index */ |
773 | 1002 | ||
774 | leaf = bp->b_addr; | 1003 | ASSERT(leafhdr->stale > 1); |
775 | ASSERT(be16_to_cpu(leaf->hdr.stale) > 1); | ||
776 | index = *indexp; | 1004 | index = *indexp; |
777 | 1005 | ||
778 | xfs_dir2_leaf_find_stale(leaf, index, &lowstale, &highstale); | 1006 | xfs_dir3_leaf_find_stale(leafhdr, ents, index, &lowstale, &highstale); |
779 | 1007 | ||
780 | /* | 1008 | /* |
781 | * Pick the better of lowstale and highstale. | 1009 | * Pick the better of lowstale and highstale. |
782 | */ | 1010 | */ |
783 | if (lowstale >= 0 && | 1011 | if (lowstale >= 0 && |
784 | (highstale == be16_to_cpu(leaf->hdr.count) || | 1012 | (highstale == leafhdr->count || |
785 | index - lowstale <= highstale - index)) | 1013 | index - lowstale <= highstale - index)) |
786 | keepstale = lowstale; | 1014 | keepstale = lowstale; |
787 | else | 1015 | else |
@@ -790,15 +1018,14 @@ xfs_dir2_leaf_compact_x1( | |||
790 | * Copy the entries in place, removing all the stale entries | 1018 | * Copy the entries in place, removing all the stale entries |
791 | * except keepstale. | 1019 | * except keepstale. |
792 | */ | 1020 | */ |
793 | for (from = to = 0; from < be16_to_cpu(leaf->hdr.count); from++) { | 1021 | for (from = to = 0; from < leafhdr->count; from++) { |
794 | /* | 1022 | /* |
795 | * Notice the new value of index. | 1023 | * Notice the new value of index. |
796 | */ | 1024 | */ |
797 | if (index == from) | 1025 | if (index == from) |
798 | newindex = to; | 1026 | newindex = to; |
799 | if (from != keepstale && | 1027 | if (from != keepstale && |
800 | leaf->ents[from].address == | 1028 | ents[from].address == cpu_to_be32(XFS_DIR2_NULL_DATAPTR)) { |
801 | cpu_to_be32(XFS_DIR2_NULL_DATAPTR)) { | ||
802 | if (from == to) | 1029 | if (from == to) |
803 | *lowlogp = to; | 1030 | *lowlogp = to; |
804 | continue; | 1031 | continue; |
@@ -812,7 +1039,7 @@ xfs_dir2_leaf_compact_x1( | |||
812 | * Copy only the entries that have moved. | 1039 | * Copy only the entries that have moved. |
813 | */ | 1040 | */ |
814 | if (from > to) | 1041 | if (from > to) |
815 | leaf->ents[to] = leaf->ents[from]; | 1042 | ents[to] = ents[from]; |
816 | to++; | 1043 | to++; |
817 | } | 1044 | } |
818 | ASSERT(from > to); | 1045 | ASSERT(from > to); |
@@ -826,8 +1053,8 @@ xfs_dir2_leaf_compact_x1( | |||
826 | /* | 1053 | /* |
827 | * Adjust the leaf header values. | 1054 | * Adjust the leaf header values. |
828 | */ | 1055 | */ |
829 | be16_add_cpu(&leaf->hdr.count, -(from - to)); | 1056 | leafhdr->count -= from - to; |
830 | leaf->hdr.stale = cpu_to_be16(1); | 1057 | leafhdr->stale = 1; |
831 | /* | 1058 | /* |
832 | * Remember the low/high stale value only in the "right" | 1059 | * Remember the low/high stale value only in the "right" |
833 | * direction. | 1060 | * direction. |
@@ -835,8 +1062,8 @@ xfs_dir2_leaf_compact_x1( | |||
835 | if (lowstale >= newindex) | 1062 | if (lowstale >= newindex) |
836 | lowstale = -1; | 1063 | lowstale = -1; |
837 | else | 1064 | else |
838 | highstale = be16_to_cpu(leaf->hdr.count); | 1065 | highstale = leafhdr->count; |
839 | *highlogp = be16_to_cpu(leaf->hdr.count) - 1; | 1066 | *highlogp = leafhdr->count - 1; |
840 | *lowstalep = lowstale; | 1067 | *lowstalep = lowstale; |
841 | *highstalep = highstale; | 1068 | *highstalep = highstale; |
842 | } | 1069 | } |
@@ -1229,69 +1456,12 @@ xfs_dir2_leaf_getdents( | |||
1229 | return error; | 1456 | return error; |
1230 | } | 1457 | } |
1231 | 1458 | ||
1232 | /* | ||
1233 | * Initialize a new leaf block, leaf1 or leafn magic accepted. | ||
1234 | */ | ||
1235 | int | ||
1236 | xfs_dir2_leaf_init( | ||
1237 | xfs_da_args_t *args, /* operation arguments */ | ||
1238 | xfs_dir2_db_t bno, /* directory block number */ | ||
1239 | struct xfs_buf **bpp, /* out: leaf buffer */ | ||
1240 | int magic) /* magic number for block */ | ||
1241 | { | ||
1242 | struct xfs_buf *bp; /* leaf buffer */ | ||
1243 | xfs_inode_t *dp; /* incore directory inode */ | ||
1244 | int error; /* error return code */ | ||
1245 | xfs_dir2_leaf_t *leaf; /* leaf structure */ | ||
1246 | xfs_dir2_leaf_tail_t *ltp; /* leaf tail structure */ | ||
1247 | xfs_mount_t *mp; /* filesystem mount point */ | ||
1248 | xfs_trans_t *tp; /* transaction pointer */ | ||
1249 | |||
1250 | dp = args->dp; | ||
1251 | ASSERT(dp != NULL); | ||
1252 | tp = args->trans; | ||
1253 | mp = dp->i_mount; | ||
1254 | ASSERT(bno >= XFS_DIR2_LEAF_FIRSTDB(mp) && | ||
1255 | bno < XFS_DIR2_FREE_FIRSTDB(mp)); | ||
1256 | /* | ||
1257 | * Get the buffer for the block. | ||
1258 | */ | ||
1259 | error = xfs_da_get_buf(tp, dp, xfs_dir2_db_to_da(mp, bno), -1, &bp, | ||
1260 | XFS_DATA_FORK); | ||
1261 | if (error) | ||
1262 | return error; | ||
1263 | |||
1264 | /* | ||
1265 | * Initialize the header. | ||
1266 | */ | ||
1267 | leaf = bp->b_addr; | ||
1268 | leaf->hdr.info.magic = cpu_to_be16(magic); | ||
1269 | leaf->hdr.info.forw = 0; | ||
1270 | leaf->hdr.info.back = 0; | ||
1271 | leaf->hdr.count = 0; | ||
1272 | leaf->hdr.stale = 0; | ||
1273 | xfs_dir2_leaf_log_header(tp, bp); | ||
1274 | /* | ||
1275 | * If it's a leaf-format directory initialize the tail. | ||
1276 | * In this case our caller has the real bests table to copy into | ||
1277 | * the block. | ||
1278 | */ | ||
1279 | if (magic == XFS_DIR2_LEAF1_MAGIC) { | ||
1280 | bp->b_ops = &xfs_dir2_leaf1_buf_ops; | ||
1281 | ltp = xfs_dir2_leaf_tail_p(mp, leaf); | ||
1282 | ltp->bestcount = 0; | ||
1283 | xfs_dir2_leaf_log_tail(tp, bp); | ||
1284 | } else | ||
1285 | bp->b_ops = &xfs_dir2_leafn_buf_ops; | ||
1286 | *bpp = bp; | ||
1287 | return 0; | ||
1288 | } | ||
1289 | 1459 | ||
1290 | /* | 1460 | /* |
1291 | * Log the bests entries indicated from a leaf1 block. | 1461 | * Log the bests entries indicated from a leaf1 block. |
1292 | */ | 1462 | */ |
1293 | static void | 1463 | static void |
1294 | xfs_dir2_leaf_log_bests( | 1464 | xfs_dir3_leaf_log_bests( |
1295 | xfs_trans_t *tp, /* transaction pointer */ | 1465 | xfs_trans_t *tp, /* transaction pointer */ |
1296 | struct xfs_buf *bp, /* leaf buffer */ | 1466 | struct xfs_buf *bp, /* leaf buffer */ |
1297 | int first, /* first entry to log */ | 1467 | int first, /* first entry to log */ |
@@ -1299,11 +1469,12 @@ xfs_dir2_leaf_log_bests( | |||
1299 | { | 1469 | { |
1300 | __be16 *firstb; /* pointer to first entry */ | 1470 | __be16 *firstb; /* pointer to first entry */ |
1301 | __be16 *lastb; /* pointer to last entry */ | 1471 | __be16 *lastb; /* pointer to last entry */ |
1302 | xfs_dir2_leaf_t *leaf; /* leaf structure */ | 1472 | struct xfs_dir2_leaf *leaf = bp->b_addr; |
1303 | xfs_dir2_leaf_tail_t *ltp; /* leaf tail structure */ | 1473 | xfs_dir2_leaf_tail_t *ltp; /* leaf tail structure */ |
1304 | 1474 | ||
1305 | leaf = bp->b_addr; | 1475 | ASSERT(leaf->hdr.info.magic == cpu_to_be16(XFS_DIR2_LEAF1_MAGIC) || |
1306 | ASSERT(leaf->hdr.info.magic == cpu_to_be16(XFS_DIR2_LEAF1_MAGIC)); | 1476 | leaf->hdr.info.magic == cpu_to_be16(XFS_DIR3_LEAF1_MAGIC)); |
1477 | |||
1307 | ltp = xfs_dir2_leaf_tail_p(tp->t_mountp, leaf); | 1478 | ltp = xfs_dir2_leaf_tail_p(tp->t_mountp, leaf); |
1308 | firstb = xfs_dir2_leaf_bests_p(ltp) + first; | 1479 | firstb = xfs_dir2_leaf_bests_p(ltp) + first; |
1309 | lastb = xfs_dir2_leaf_bests_p(ltp) + last; | 1480 | lastb = xfs_dir2_leaf_bests_p(ltp) + last; |
@@ -1315,7 +1486,7 @@ xfs_dir2_leaf_log_bests( | |||
1315 | * Log the leaf entries indicated from a leaf1 or leafn block. | 1486 | * Log the leaf entries indicated from a leaf1 or leafn block. |
1316 | */ | 1487 | */ |
1317 | void | 1488 | void |
1318 | xfs_dir2_leaf_log_ents( | 1489 | xfs_dir3_leaf_log_ents( |
1319 | xfs_trans_t *tp, /* transaction pointer */ | 1490 | xfs_trans_t *tp, /* transaction pointer */ |
1320 | struct xfs_buf *bp, /* leaf buffer */ | 1491 | struct xfs_buf *bp, /* leaf buffer */ |
1321 | int first, /* first entry to log */ | 1492 | int first, /* first entry to log */ |
@@ -1323,13 +1494,17 @@ xfs_dir2_leaf_log_ents( | |||
1323 | { | 1494 | { |
1324 | xfs_dir2_leaf_entry_t *firstlep; /* pointer to first entry */ | 1495 | xfs_dir2_leaf_entry_t *firstlep; /* pointer to first entry */ |
1325 | xfs_dir2_leaf_entry_t *lastlep; /* pointer to last entry */ | 1496 | xfs_dir2_leaf_entry_t *lastlep; /* pointer to last entry */ |
1326 | xfs_dir2_leaf_t *leaf; /* leaf structure */ | 1497 | struct xfs_dir2_leaf *leaf = bp->b_addr; |
1498 | struct xfs_dir2_leaf_entry *ents; | ||
1327 | 1499 | ||
1328 | leaf = bp->b_addr; | ||
1329 | ASSERT(leaf->hdr.info.magic == cpu_to_be16(XFS_DIR2_LEAF1_MAGIC) || | 1500 | ASSERT(leaf->hdr.info.magic == cpu_to_be16(XFS_DIR2_LEAF1_MAGIC) || |
1330 | leaf->hdr.info.magic == cpu_to_be16(XFS_DIR2_LEAFN_MAGIC)); | 1501 | leaf->hdr.info.magic == cpu_to_be16(XFS_DIR3_LEAF1_MAGIC) || |
1331 | firstlep = &leaf->ents[first]; | 1502 | leaf->hdr.info.magic == cpu_to_be16(XFS_DIR2_LEAFN_MAGIC) || |
1332 | lastlep = &leaf->ents[last]; | 1503 | leaf->hdr.info.magic == cpu_to_be16(XFS_DIR3_LEAFN_MAGIC)); |
1504 | |||
1505 | ents = xfs_dir3_leaf_ents_p(leaf); | ||
1506 | firstlep = &ents[first]; | ||
1507 | lastlep = &ents[last]; | ||
1333 | xfs_trans_log_buf(tp, bp, (uint)((char *)firstlep - (char *)leaf), | 1508 | xfs_trans_log_buf(tp, bp, (uint)((char *)firstlep - (char *)leaf), |
1334 | (uint)((char *)lastlep - (char *)leaf + sizeof(*lastlep) - 1)); | 1509 | (uint)((char *)lastlep - (char *)leaf + sizeof(*lastlep) - 1)); |
1335 | } | 1510 | } |
@@ -1338,34 +1513,38 @@ xfs_dir2_leaf_log_ents( | |||
1338 | * Log the header of the leaf1 or leafn block. | 1513 | * Log the header of the leaf1 or leafn block. |
1339 | */ | 1514 | */ |
1340 | void | 1515 | void |
1341 | xfs_dir2_leaf_log_header( | 1516 | xfs_dir3_leaf_log_header( |
1342 | struct xfs_trans *tp, | 1517 | struct xfs_trans *tp, |
1343 | struct xfs_buf *bp) | 1518 | struct xfs_buf *bp) |
1344 | { | 1519 | { |
1345 | xfs_dir2_leaf_t *leaf; /* leaf structure */ | 1520 | struct xfs_dir2_leaf *leaf = bp->b_addr; |
1346 | 1521 | ||
1347 | leaf = bp->b_addr; | ||
1348 | ASSERT(leaf->hdr.info.magic == cpu_to_be16(XFS_DIR2_LEAF1_MAGIC) || | 1522 | ASSERT(leaf->hdr.info.magic == cpu_to_be16(XFS_DIR2_LEAF1_MAGIC) || |
1349 | leaf->hdr.info.magic == cpu_to_be16(XFS_DIR2_LEAFN_MAGIC)); | 1523 | leaf->hdr.info.magic == cpu_to_be16(XFS_DIR3_LEAF1_MAGIC) || |
1524 | leaf->hdr.info.magic == cpu_to_be16(XFS_DIR2_LEAFN_MAGIC) || | ||
1525 | leaf->hdr.info.magic == cpu_to_be16(XFS_DIR3_LEAFN_MAGIC)); | ||
1526 | |||
1350 | xfs_trans_log_buf(tp, bp, (uint)((char *)&leaf->hdr - (char *)leaf), | 1527 | xfs_trans_log_buf(tp, bp, (uint)((char *)&leaf->hdr - (char *)leaf), |
1351 | (uint)(sizeof(leaf->hdr) - 1)); | 1528 | xfs_dir3_leaf_hdr_size(leaf) - 1); |
1352 | } | 1529 | } |
1353 | 1530 | ||
1354 | /* | 1531 | /* |
1355 | * Log the tail of the leaf1 block. | 1532 | * Log the tail of the leaf1 block. |
1356 | */ | 1533 | */ |
1357 | STATIC void | 1534 | STATIC void |
1358 | xfs_dir2_leaf_log_tail( | 1535 | xfs_dir3_leaf_log_tail( |
1359 | struct xfs_trans *tp, | 1536 | struct xfs_trans *tp, |
1360 | struct xfs_buf *bp) | 1537 | struct xfs_buf *bp) |
1361 | { | 1538 | { |
1362 | xfs_dir2_leaf_t *leaf; /* leaf structure */ | 1539 | struct xfs_dir2_leaf *leaf = bp->b_addr; |
1363 | xfs_dir2_leaf_tail_t *ltp; /* leaf tail structure */ | 1540 | xfs_dir2_leaf_tail_t *ltp; /* leaf tail structure */ |
1364 | xfs_mount_t *mp; /* filesystem mount point */ | 1541 | struct xfs_mount *mp = tp->t_mountp; |
1542 | |||
1543 | ASSERT(leaf->hdr.info.magic == cpu_to_be16(XFS_DIR2_LEAF1_MAGIC) || | ||
1544 | leaf->hdr.info.magic == cpu_to_be16(XFS_DIR3_LEAF1_MAGIC) || | ||
1545 | leaf->hdr.info.magic == cpu_to_be16(XFS_DIR2_LEAFN_MAGIC) || | ||
1546 | leaf->hdr.info.magic == cpu_to_be16(XFS_DIR3_LEAFN_MAGIC)); | ||
1365 | 1547 | ||
1366 | mp = tp->t_mountp; | ||
1367 | leaf = bp->b_addr; | ||
1368 | ASSERT(leaf->hdr.info.magic == cpu_to_be16(XFS_DIR2_LEAF1_MAGIC)); | ||
1369 | ltp = xfs_dir2_leaf_tail_p(mp, leaf); | 1548 | ltp = xfs_dir2_leaf_tail_p(mp, leaf); |
1370 | xfs_trans_log_buf(tp, bp, (uint)((char *)ltp - (char *)leaf), | 1549 | xfs_trans_log_buf(tp, bp, (uint)((char *)ltp - (char *)leaf), |
1371 | (uint)(mp->m_dirblksize - 1)); | 1550 | (uint)(mp->m_dirblksize - 1)); |
@@ -1389,6 +1568,7 @@ xfs_dir2_leaf_lookup( | |||
1389 | xfs_dir2_leaf_t *leaf; /* leaf structure */ | 1568 | xfs_dir2_leaf_t *leaf; /* leaf structure */ |
1390 | xfs_dir2_leaf_entry_t *lep; /* leaf entry */ | 1569 | xfs_dir2_leaf_entry_t *lep; /* leaf entry */ |
1391 | xfs_trans_t *tp; /* transaction pointer */ | 1570 | xfs_trans_t *tp; /* transaction pointer */ |
1571 | struct xfs_dir2_leaf_entry *ents; | ||
1392 | 1572 | ||
1393 | trace_xfs_dir2_leaf_lookup(args); | 1573 | trace_xfs_dir2_leaf_lookup(args); |
1394 | 1574 | ||
@@ -1400,12 +1580,14 @@ xfs_dir2_leaf_lookup( | |||
1400 | } | 1580 | } |
1401 | tp = args->trans; | 1581 | tp = args->trans; |
1402 | dp = args->dp; | 1582 | dp = args->dp; |
1403 | xfs_dir2_leaf_check(dp, lbp); | 1583 | xfs_dir3_leaf_check(dp->i_mount, lbp); |
1404 | leaf = lbp->b_addr; | 1584 | leaf = lbp->b_addr; |
1585 | ents = xfs_dir3_leaf_ents_p(leaf); | ||
1405 | /* | 1586 | /* |
1406 | * Get to the leaf entry and contained data entry address. | 1587 | * Get to the leaf entry and contained data entry address. |
1407 | */ | 1588 | */ |
1408 | lep = &leaf->ents[index]; | 1589 | lep = &ents[index]; |
1590 | |||
1409 | /* | 1591 | /* |
1410 | * Point to the data entry. | 1592 | * Point to the data entry. |
1411 | */ | 1593 | */ |
@@ -1449,18 +1631,23 @@ xfs_dir2_leaf_lookup_int( | |||
1449 | xfs_trans_t *tp; /* transaction pointer */ | 1631 | xfs_trans_t *tp; /* transaction pointer */ |
1450 | xfs_dir2_db_t cidb = -1; /* case match data block no. */ | 1632 | xfs_dir2_db_t cidb = -1; /* case match data block no. */ |
1451 | enum xfs_dacmp cmp; /* name compare result */ | 1633 | enum xfs_dacmp cmp; /* name compare result */ |
1634 | struct xfs_dir2_leaf_entry *ents; | ||
1635 | struct xfs_dir3_icleaf_hdr leafhdr; | ||
1452 | 1636 | ||
1453 | dp = args->dp; | 1637 | dp = args->dp; |
1454 | tp = args->trans; | 1638 | tp = args->trans; |
1455 | mp = dp->i_mount; | 1639 | mp = dp->i_mount; |
1456 | 1640 | ||
1457 | error = xfs_dir2_leaf_read(tp, dp, mp->m_dirleafblk, -1, &lbp); | 1641 | error = xfs_dir3_leaf_read(tp, dp, mp->m_dirleafblk, -1, &lbp); |
1458 | if (error) | 1642 | if (error) |
1459 | return error; | 1643 | return error; |
1460 | 1644 | ||
1461 | *lbpp = lbp; | 1645 | *lbpp = lbp; |
1462 | leaf = lbp->b_addr; | 1646 | leaf = lbp->b_addr; |
1463 | xfs_dir2_leaf_check(dp, lbp); | 1647 | xfs_dir3_leaf_check(mp, lbp); |
1648 | ents = xfs_dir3_leaf_ents_p(leaf); | ||
1649 | xfs_dir3_leaf_hdr_from_disk(&leafhdr, leaf); | ||
1650 | |||
1464 | /* | 1651 | /* |
1465 | * Look for the first leaf entry with our hash value. | 1652 | * Look for the first leaf entry with our hash value. |
1466 | */ | 1653 | */ |
@@ -1469,9 +1656,9 @@ xfs_dir2_leaf_lookup_int( | |||
1469 | * Loop over all the entries with the right hash value | 1656 | * Loop over all the entries with the right hash value |
1470 | * looking to match the name. | 1657 | * looking to match the name. |
1471 | */ | 1658 | */ |
1472 | for (lep = &leaf->ents[index]; index < be16_to_cpu(leaf->hdr.count) && | 1659 | for (lep = &ents[index]; |
1473 | be32_to_cpu(lep->hashval) == args->hashval; | 1660 | index < leafhdr.count && be32_to_cpu(lep->hashval) == args->hashval; |
1474 | lep++, index++) { | 1661 | lep++, index++) { |
1475 | /* | 1662 | /* |
1476 | * Skip over stale leaf entries. | 1663 | * Skip over stale leaf entries. |
1477 | */ | 1664 | */ |
@@ -1576,6 +1763,8 @@ xfs_dir2_leaf_removename( | |||
1576 | xfs_dir2_data_off_t oldbest; /* old value of best free */ | 1763 | xfs_dir2_data_off_t oldbest; /* old value of best free */ |
1577 | xfs_trans_t *tp; /* transaction pointer */ | 1764 | xfs_trans_t *tp; /* transaction pointer */ |
1578 | struct xfs_dir2_data_free *bf; /* bestfree table */ | 1765 | struct xfs_dir2_data_free *bf; /* bestfree table */ |
1766 | struct xfs_dir2_leaf_entry *ents; | ||
1767 | struct xfs_dir3_icleaf_hdr leafhdr; | ||
1579 | 1768 | ||
1580 | trace_xfs_dir2_leaf_removename(args); | 1769 | trace_xfs_dir2_leaf_removename(args); |
1581 | 1770 | ||
@@ -1590,12 +1779,14 @@ xfs_dir2_leaf_removename( | |||
1590 | mp = dp->i_mount; | 1779 | mp = dp->i_mount; |
1591 | leaf = lbp->b_addr; | 1780 | leaf = lbp->b_addr; |
1592 | hdr = dbp->b_addr; | 1781 | hdr = dbp->b_addr; |
1593 | bf = xfs_dir3_data_bestfree_p(hdr); | ||
1594 | xfs_dir3_data_check(dp, dbp); | 1782 | xfs_dir3_data_check(dp, dbp); |
1783 | bf = xfs_dir3_data_bestfree_p(hdr); | ||
1784 | xfs_dir3_leaf_hdr_from_disk(&leafhdr, leaf); | ||
1785 | ents = xfs_dir3_leaf_ents_p(leaf); | ||
1595 | /* | 1786 | /* |
1596 | * Point to the leaf entry, use that to point to the data entry. | 1787 | * Point to the leaf entry, use that to point to the data entry. |
1597 | */ | 1788 | */ |
1598 | lep = &leaf->ents[index]; | 1789 | lep = &ents[index]; |
1599 | db = xfs_dir2_dataptr_to_db(mp, be32_to_cpu(lep->address)); | 1790 | db = xfs_dir2_dataptr_to_db(mp, be32_to_cpu(lep->address)); |
1600 | dep = (xfs_dir2_data_entry_t *) | 1791 | dep = (xfs_dir2_data_entry_t *) |
1601 | ((char *)hdr + xfs_dir2_dataptr_to_off(mp, be32_to_cpu(lep->address))); | 1792 | ((char *)hdr + xfs_dir2_dataptr_to_off(mp, be32_to_cpu(lep->address))); |
@@ -1613,10 +1804,13 @@ xfs_dir2_leaf_removename( | |||
1613 | /* | 1804 | /* |
1614 | * We just mark the leaf entry stale by putting a null in it. | 1805 | * We just mark the leaf entry stale by putting a null in it. |
1615 | */ | 1806 | */ |
1616 | be16_add_cpu(&leaf->hdr.stale, 1); | 1807 | leafhdr.stale++; |
1617 | xfs_dir2_leaf_log_header(tp, lbp); | 1808 | xfs_dir3_leaf_hdr_to_disk(leaf, &leafhdr); |
1809 | xfs_dir3_leaf_log_header(tp, lbp); | ||
1810 | |||
1618 | lep->address = cpu_to_be32(XFS_DIR2_NULL_DATAPTR); | 1811 | lep->address = cpu_to_be32(XFS_DIR2_NULL_DATAPTR); |
1619 | xfs_dir2_leaf_log_ents(tp, lbp, index, index); | 1812 | xfs_dir3_leaf_log_ents(tp, lbp, index, index); |
1813 | |||
1620 | /* | 1814 | /* |
1621 | * Scan the freespace in the data block again if necessary, | 1815 | * Scan the freespace in the data block again if necessary, |
1622 | * log the data block header if necessary. | 1816 | * log the data block header if necessary. |
@@ -1631,7 +1825,7 @@ xfs_dir2_leaf_removename( | |||
1631 | */ | 1825 | */ |
1632 | if (be16_to_cpu(bf[0].length) != oldbest) { | 1826 | if (be16_to_cpu(bf[0].length) != oldbest) { |
1633 | bestsp[db] = bf[0].length; | 1827 | bestsp[db] = bf[0].length; |
1634 | xfs_dir2_leaf_log_bests(tp, lbp, db, db); | 1828 | xfs_dir3_leaf_log_bests(tp, lbp, db, db); |
1635 | } | 1829 | } |
1636 | xfs_dir3_data_check(dp, dbp); | 1830 | xfs_dir3_data_check(dp, dbp); |
1637 | /* | 1831 | /* |
@@ -1649,7 +1843,7 @@ xfs_dir2_leaf_removename( | |||
1649 | */ | 1843 | */ |
1650 | if (error == ENOSPC && args->total == 0) | 1844 | if (error == ENOSPC && args->total == 0) |
1651 | error = 0; | 1845 | error = 0; |
1652 | xfs_dir2_leaf_check(dp, lbp); | 1846 | xfs_dir3_leaf_check(mp, lbp); |
1653 | return error; | 1847 | return error; |
1654 | } | 1848 | } |
1655 | dbp = NULL; | 1849 | dbp = NULL; |
@@ -1672,8 +1866,8 @@ xfs_dir2_leaf_removename( | |||
1672 | memmove(&bestsp[db - i], bestsp, | 1866 | memmove(&bestsp[db - i], bestsp, |
1673 | (be32_to_cpu(ltp->bestcount) - (db - i)) * sizeof(*bestsp)); | 1867 | (be32_to_cpu(ltp->bestcount) - (db - i)) * sizeof(*bestsp)); |
1674 | be32_add_cpu(<p->bestcount, -(db - i)); | 1868 | be32_add_cpu(<p->bestcount, -(db - i)); |
1675 | xfs_dir2_leaf_log_tail(tp, lbp); | 1869 | xfs_dir3_leaf_log_tail(tp, lbp); |
1676 | xfs_dir2_leaf_log_bests(tp, lbp, 0, be32_to_cpu(ltp->bestcount) - 1); | 1870 | xfs_dir3_leaf_log_bests(tp, lbp, 0, be32_to_cpu(ltp->bestcount) - 1); |
1677 | } else | 1871 | } else |
1678 | bestsp[db] = cpu_to_be16(NULLDATAOFF); | 1872 | bestsp[db] = cpu_to_be16(NULLDATAOFF); |
1679 | } | 1873 | } |
@@ -1683,7 +1877,7 @@ xfs_dir2_leaf_removename( | |||
1683 | else if (db != mp->m_dirdatablk) | 1877 | else if (db != mp->m_dirdatablk) |
1684 | dbp = NULL; | 1878 | dbp = NULL; |
1685 | 1879 | ||
1686 | xfs_dir2_leaf_check(dp, lbp); | 1880 | xfs_dir3_leaf_check(mp, lbp); |
1687 | /* | 1881 | /* |
1688 | * See if we can convert to block form. | 1882 | * See if we can convert to block form. |
1689 | */ | 1883 | */ |
@@ -1706,6 +1900,7 @@ xfs_dir2_leaf_replace( | |||
1706 | xfs_dir2_leaf_t *leaf; /* leaf structure */ | 1900 | xfs_dir2_leaf_t *leaf; /* leaf structure */ |
1707 | xfs_dir2_leaf_entry_t *lep; /* leaf entry */ | 1901 | xfs_dir2_leaf_entry_t *lep; /* leaf entry */ |
1708 | xfs_trans_t *tp; /* transaction pointer */ | 1902 | xfs_trans_t *tp; /* transaction pointer */ |
1903 | struct xfs_dir2_leaf_entry *ents; | ||
1709 | 1904 | ||
1710 | trace_xfs_dir2_leaf_replace(args); | 1905 | trace_xfs_dir2_leaf_replace(args); |
1711 | 1906 | ||
@@ -1717,10 +1912,11 @@ xfs_dir2_leaf_replace( | |||
1717 | } | 1912 | } |
1718 | dp = args->dp; | 1913 | dp = args->dp; |
1719 | leaf = lbp->b_addr; | 1914 | leaf = lbp->b_addr; |
1915 | ents = xfs_dir3_leaf_ents_p(leaf); | ||
1720 | /* | 1916 | /* |
1721 | * Point to the leaf entry, get data address from it. | 1917 | * Point to the leaf entry, get data address from it. |
1722 | */ | 1918 | */ |
1723 | lep = &leaf->ents[index]; | 1919 | lep = &ents[index]; |
1724 | /* | 1920 | /* |
1725 | * Point to the data entry. | 1921 | * Point to the data entry. |
1726 | */ | 1922 | */ |
@@ -1734,7 +1930,7 @@ xfs_dir2_leaf_replace( | |||
1734 | dep->inumber = cpu_to_be64(args->inumber); | 1930 | dep->inumber = cpu_to_be64(args->inumber); |
1735 | tp = args->trans; | 1931 | tp = args->trans; |
1736 | xfs_dir2_data_log_entry(tp, dbp, dep); | 1932 | xfs_dir2_data_log_entry(tp, dbp, dep); |
1737 | xfs_dir2_leaf_check(dp, lbp); | 1933 | xfs_dir3_leaf_check(dp->i_mount, lbp); |
1738 | xfs_trans_brelse(tp, lbp); | 1934 | xfs_trans_brelse(tp, lbp); |
1739 | return 0; | 1935 | return 0; |
1740 | } | 1936 | } |
@@ -1756,17 +1952,22 @@ xfs_dir2_leaf_search_hash( | |||
1756 | xfs_dir2_leaf_t *leaf; /* leaf structure */ | 1952 | xfs_dir2_leaf_t *leaf; /* leaf structure */ |
1757 | xfs_dir2_leaf_entry_t *lep; /* leaf entry */ | 1953 | xfs_dir2_leaf_entry_t *lep; /* leaf entry */ |
1758 | int mid=0; /* current leaf index */ | 1954 | int mid=0; /* current leaf index */ |
1955 | struct xfs_dir2_leaf_entry *ents; | ||
1956 | struct xfs_dir3_icleaf_hdr leafhdr; | ||
1759 | 1957 | ||
1760 | leaf = lbp->b_addr; | 1958 | leaf = lbp->b_addr; |
1959 | ents = xfs_dir3_leaf_ents_p(leaf); | ||
1960 | xfs_dir3_leaf_hdr_from_disk(&leafhdr, leaf); | ||
1961 | |||
1761 | #ifndef __KERNEL__ | 1962 | #ifndef __KERNEL__ |
1762 | if (!leaf->hdr.count) | 1963 | if (!leafhdr.count) |
1763 | return 0; | 1964 | return 0; |
1764 | #endif | 1965 | #endif |
1765 | /* | 1966 | /* |
1766 | * Note, the table cannot be empty, so we have to go through the loop. | 1967 | * Note, the table cannot be empty, so we have to go through the loop. |
1767 | * Binary search the leaf entries looking for our hash value. | 1968 | * Binary search the leaf entries looking for our hash value. |
1768 | */ | 1969 | */ |
1769 | for (lep = leaf->ents, low = 0, high = be16_to_cpu(leaf->hdr.count) - 1, | 1970 | for (lep = ents, low = 0, high = leafhdr.count - 1, |
1770 | hashwant = args->hashval; | 1971 | hashwant = args->hashval; |
1771 | low <= high; ) { | 1972 | low <= high; ) { |
1772 | mid = (low + high) >> 1; | 1973 | mid = (low + high) >> 1; |
@@ -1852,23 +2053,29 @@ xfs_dir2_leaf_trim_data( | |||
1852 | bestsp = xfs_dir2_leaf_bests_p(ltp); | 2053 | bestsp = xfs_dir2_leaf_bests_p(ltp); |
1853 | be32_add_cpu(<p->bestcount, -1); | 2054 | be32_add_cpu(<p->bestcount, -1); |
1854 | memmove(&bestsp[1], &bestsp[0], be32_to_cpu(ltp->bestcount) * sizeof(*bestsp)); | 2055 | memmove(&bestsp[1], &bestsp[0], be32_to_cpu(ltp->bestcount) * sizeof(*bestsp)); |
1855 | xfs_dir2_leaf_log_tail(tp, lbp); | 2056 | xfs_dir3_leaf_log_tail(tp, lbp); |
1856 | xfs_dir2_leaf_log_bests(tp, lbp, 0, be32_to_cpu(ltp->bestcount) - 1); | 2057 | xfs_dir3_leaf_log_bests(tp, lbp, 0, be32_to_cpu(ltp->bestcount) - 1); |
1857 | return 0; | 2058 | return 0; |
1858 | } | 2059 | } |
1859 | 2060 | ||
1860 | static inline size_t | 2061 | static inline size_t |
1861 | xfs_dir2_leaf_size( | 2062 | xfs_dir3_leaf_size( |
1862 | struct xfs_dir2_leaf_hdr *hdr, | 2063 | struct xfs_dir3_icleaf_hdr *hdr, |
1863 | int counts) | 2064 | int counts) |
1864 | { | 2065 | { |
1865 | int entries; | 2066 | int entries; |
2067 | int hdrsize; | ||
2068 | |||
2069 | entries = hdr->count - hdr->stale; | ||
2070 | if (hdr->magic == XFS_DIR2_LEAF1_MAGIC || | ||
2071 | hdr->magic == XFS_DIR2_LEAFN_MAGIC) | ||
2072 | hdrsize = sizeof(struct xfs_dir2_leaf_hdr); | ||
2073 | else | ||
2074 | hdrsize = sizeof(struct xfs_dir3_leaf_hdr); | ||
1866 | 2075 | ||
1867 | entries = be16_to_cpu(hdr->count) - be16_to_cpu(hdr->stale); | 2076 | return hdrsize + entries * sizeof(xfs_dir2_leaf_entry_t) |
1868 | return sizeof(xfs_dir2_leaf_hdr_t) + | 2077 | + counts * sizeof(xfs_dir2_data_off_t) |
1869 | entries * sizeof(xfs_dir2_leaf_entry_t) + | 2078 | + sizeof(xfs_dir2_leaf_tail_t); |
1870 | counts * sizeof(xfs_dir2_data_off_t) + | ||
1871 | sizeof(xfs_dir2_leaf_tail_t); | ||
1872 | } | 2079 | } |
1873 | 2080 | ||
1874 | /* | 2081 | /* |
@@ -1892,6 +2099,7 @@ xfs_dir2_node_to_leaf( | |||
1892 | xfs_mount_t *mp; /* filesystem mount point */ | 2099 | xfs_mount_t *mp; /* filesystem mount point */ |
1893 | int rval; /* successful free trim? */ | 2100 | int rval; /* successful free trim? */ |
1894 | xfs_trans_t *tp; /* transaction pointer */ | 2101 | xfs_trans_t *tp; /* transaction pointer */ |
2102 | struct xfs_dir3_icleaf_hdr leafhdr; | ||
1895 | struct xfs_dir3_icfree_hdr freehdr; | 2103 | struct xfs_dir3_icfree_hdr freehdr; |
1896 | 2104 | ||
1897 | /* | 2105 | /* |
@@ -1942,7 +2150,11 @@ xfs_dir2_node_to_leaf( | |||
1942 | return 0; | 2150 | return 0; |
1943 | lbp = state->path.blk[0].bp; | 2151 | lbp = state->path.blk[0].bp; |
1944 | leaf = lbp->b_addr; | 2152 | leaf = lbp->b_addr; |
1945 | ASSERT(leaf->hdr.info.magic == cpu_to_be16(XFS_DIR2_LEAFN_MAGIC)); | 2153 | xfs_dir3_leaf_hdr_from_disk(&leafhdr, leaf); |
2154 | |||
2155 | ASSERT(leafhdr.magic == XFS_DIR2_LEAFN_MAGIC || | ||
2156 | leafhdr.magic == XFS_DIR3_LEAFN_MAGIC); | ||
2157 | |||
1946 | /* | 2158 | /* |
1947 | * Read the freespace block. | 2159 | * Read the freespace block. |
1948 | */ | 2160 | */ |
@@ -1958,36 +2170,40 @@ xfs_dir2_node_to_leaf( | |||
1958 | * Now see if the leafn and free data will fit in a leaf1. | 2170 | * Now see if the leafn and free data will fit in a leaf1. |
1959 | * If not, release the buffer and give up. | 2171 | * If not, release the buffer and give up. |
1960 | */ | 2172 | */ |
1961 | if (xfs_dir2_leaf_size(&leaf->hdr, freehdr.nvalid) > mp->m_dirblksize) { | 2173 | if (xfs_dir3_leaf_size(&leafhdr, freehdr.nvalid) > mp->m_dirblksize) { |
1962 | xfs_trans_brelse(tp, fbp); | 2174 | xfs_trans_brelse(tp, fbp); |
1963 | return 0; | 2175 | return 0; |
1964 | } | 2176 | } |
1965 | 2177 | ||
1966 | /* | 2178 | /* |
1967 | * If the leaf has any stale entries in it, compress them out. | 2179 | * If the leaf has any stale entries in it, compress them out. |
1968 | * The compact routine will log the header. | ||
1969 | */ | 2180 | */ |
1970 | if (be16_to_cpu(leaf->hdr.stale)) | 2181 | if (leafhdr.stale) |
1971 | xfs_dir2_leaf_compact(args, lbp); | 2182 | xfs_dir3_leaf_compact(args, &leafhdr, lbp); |
1972 | else | ||
1973 | xfs_dir2_leaf_log_header(tp, lbp); | ||
1974 | 2183 | ||
1975 | lbp->b_ops = &xfs_dir2_leaf1_buf_ops; | 2184 | lbp->b_ops = &xfs_dir3_leaf1_buf_ops; |
1976 | leaf->hdr.info.magic = cpu_to_be16(XFS_DIR2_LEAF1_MAGIC); | 2185 | leafhdr.magic = (leafhdr.magic == XFS_DIR2_LEAFN_MAGIC) |
2186 | ? XFS_DIR2_LEAF1_MAGIC | ||
2187 | : XFS_DIR3_LEAF1_MAGIC; | ||
1977 | 2188 | ||
1978 | /* | 2189 | /* |
1979 | * Set up the leaf tail from the freespace block. | 2190 | * Set up the leaf tail from the freespace block. |
1980 | */ | 2191 | */ |
1981 | ltp = xfs_dir2_leaf_tail_p(mp, leaf); | 2192 | ltp = xfs_dir2_leaf_tail_p(mp, leaf); |
1982 | ltp->bestcount = cpu_to_be32(freehdr.nvalid); | 2193 | ltp->bestcount = cpu_to_be32(freehdr.nvalid); |
2194 | |||
1983 | /* | 2195 | /* |
1984 | * Set up the leaf bests table. | 2196 | * Set up the leaf bests table. |
1985 | */ | 2197 | */ |
1986 | memcpy(xfs_dir2_leaf_bests_p(ltp), xfs_dir3_free_bests_p(mp, free), | 2198 | memcpy(xfs_dir2_leaf_bests_p(ltp), xfs_dir3_free_bests_p(mp, free), |
1987 | freehdr.nvalid * sizeof(xfs_dir2_data_off_t)); | 2199 | freehdr.nvalid * sizeof(xfs_dir2_data_off_t)); |
1988 | xfs_dir2_leaf_log_bests(tp, lbp, 0, be32_to_cpu(ltp->bestcount) - 1); | 2200 | |
1989 | xfs_dir2_leaf_log_tail(tp, lbp); | 2201 | xfs_dir3_leaf_hdr_to_disk(leaf, &leafhdr); |
1990 | xfs_dir2_leaf_check(dp, lbp); | 2202 | xfs_dir3_leaf_log_header(tp, lbp); |
2203 | xfs_dir3_leaf_log_bests(tp, lbp, 0, be32_to_cpu(ltp->bestcount) - 1); | ||
2204 | xfs_dir3_leaf_log_tail(tp, lbp); | ||
2205 | xfs_dir3_leaf_check(mp, lbp); | ||
2206 | |||
1991 | /* | 2207 | /* |
1992 | * Get rid of the freespace block. | 2208 | * Get rid of the freespace block. |
1993 | */ | 2209 | */ |