1 | // SPDX-License-Identifier: GPL-2.0 |
2 | /* |
3 | * Copyright (c) 2000-2003,2005 Silicon Graphics, Inc. |
4 | * Copyright (c) 2013 Red Hat, Inc. |
5 | * All Rights Reserved. |
6 | */ |
7 | #include "xfs.h" |
8 | #include "xfs_fs.h" |
9 | #include "xfs_shared.h" |
10 | #include "xfs_format.h" |
11 | #include "xfs_log_format.h" |
12 | #include "xfs_trans_resv.h" |
13 | #include "xfs_mount.h" |
14 | #include "xfs_inode.h" |
15 | #include "xfs_trans.h" |
16 | #include "xfs_bmap.h" |
17 | #include "xfs_buf_item.h" |
18 | #include "xfs_dir2.h" |
19 | #include "xfs_dir2_priv.h" |
20 | #include "xfs_error.h" |
21 | #include "xfs_trace.h" |
22 | #include "xfs_log.h" |
23 | #include "xfs_health.h" |
24 | |
25 | /* |
26 | * Local function prototypes. |
27 | */ |
28 | static void xfs_dir2_block_log_leaf(xfs_trans_t *tp, struct xfs_buf *bp, |
29 | int first, int last); |
30 | static void xfs_dir2_block_log_tail(xfs_trans_t *tp, struct xfs_buf *bp); |
31 | static int xfs_dir2_block_lookup_int(xfs_da_args_t *args, struct xfs_buf **bpp, |
32 | int *entno); |
33 | static int xfs_dir2_block_sort(const void *a, const void *b); |
34 | |
35 | static xfs_dahash_t xfs_dir_hash_dot, xfs_dir_hash_dotdot; |
36 | |
37 | /* |
38 | * One-time startup routine called from xfs_init(). |
39 | */ |
40 | void |
41 | xfs_dir_startup(void) |
42 | { |
43 | xfs_dir_hash_dot = xfs_da_hashname((unsigned char *)"." , 1); |
44 | xfs_dir_hash_dotdot = xfs_da_hashname((unsigned char *)".." , 2); |
45 | } |
46 | |
47 | static xfs_failaddr_t |
48 | xfs_dir3_block_verify( |
49 | struct xfs_buf *bp) |
50 | { |
51 | struct xfs_mount *mp = bp->b_mount; |
52 | struct xfs_dir3_blk_hdr *hdr3 = bp->b_addr; |
53 | |
54 | if (!xfs_verify_magic(bp, hdr3->magic)) |
55 | return __this_address; |
56 | |
57 | if (xfs_has_crc(mp)) { |
58 | if (!uuid_equal(&hdr3->uuid, &mp->m_sb.sb_meta_uuid)) |
59 | return __this_address; |
60 | if (be64_to_cpu(hdr3->blkno) != xfs_buf_daddr(bp)) |
61 | return __this_address; |
62 | if (!xfs_log_check_lsn(mp, be64_to_cpu(hdr3->lsn))) |
63 | return __this_address; |
64 | } |
65 | return __xfs_dir3_data_check(NULL, bp); |
66 | } |
67 | |
68 | static void |
69 | xfs_dir3_block_read_verify( |
70 | struct xfs_buf *bp) |
71 | { |
72 | struct xfs_mount *mp = bp->b_mount; |
73 | xfs_failaddr_t fa; |
74 | |
75 | if (xfs_has_crc(mp) && |
76 | !xfs_buf_verify_cksum(bp, XFS_DIR3_DATA_CRC_OFF)) |
77 | xfs_verifier_error(bp, -EFSBADCRC, __this_address); |
78 | else { |
79 | fa = xfs_dir3_block_verify(bp); |
80 | if (fa) |
81 | xfs_verifier_error(bp, -EFSCORRUPTED, fa); |
82 | } |
83 | } |
84 | |
85 | static void |
86 | xfs_dir3_block_write_verify( |
87 | struct xfs_buf *bp) |
88 | { |
89 | struct xfs_mount *mp = bp->b_mount; |
90 | struct xfs_buf_log_item *bip = bp->b_log_item; |
91 | struct xfs_dir3_blk_hdr *hdr3 = bp->b_addr; |
92 | xfs_failaddr_t fa; |
93 | |
94 | fa = xfs_dir3_block_verify(bp); |
95 | if (fa) { |
96 | xfs_verifier_error(bp, -EFSCORRUPTED, fa); |
97 | return; |
98 | } |
99 | |
100 | if (!xfs_has_crc(mp)) |
101 | return; |
102 | |
103 | if (bip) |
104 | hdr3->lsn = cpu_to_be64(bip->bli_item.li_lsn); |
105 | |
106 | xfs_buf_update_cksum(bp, XFS_DIR3_DATA_CRC_OFF); |
107 | } |
108 | |
109 | const struct xfs_buf_ops xfs_dir3_block_buf_ops = { |
110 | .name = "xfs_dir3_block" , |
111 | .magic = { cpu_to_be32(XFS_DIR2_BLOCK_MAGIC), |
112 | cpu_to_be32(XFS_DIR3_BLOCK_MAGIC) }, |
113 | .verify_read = xfs_dir3_block_read_verify, |
114 | .verify_write = xfs_dir3_block_write_verify, |
115 | .verify_struct = xfs_dir3_block_verify, |
116 | }; |
117 | |
118 | static xfs_failaddr_t |
119 | ( |
120 | struct xfs_inode *dp, |
121 | struct xfs_buf *bp) |
122 | { |
123 | struct xfs_mount *mp = dp->i_mount; |
124 | |
125 | if (xfs_has_crc(mp)) { |
126 | struct xfs_dir3_blk_hdr *hdr3 = bp->b_addr; |
127 | |
128 | if (be64_to_cpu(hdr3->owner) != dp->i_ino) |
129 | return __this_address; |
130 | } |
131 | |
132 | return NULL; |
133 | } |
134 | |
135 | int |
136 | xfs_dir3_block_read( |
137 | struct xfs_trans *tp, |
138 | struct xfs_inode *dp, |
139 | struct xfs_buf **bpp) |
140 | { |
141 | struct xfs_mount *mp = dp->i_mount; |
142 | xfs_failaddr_t fa; |
143 | int err; |
144 | |
145 | err = xfs_da_read_buf(tp, dp, mp->m_dir_geo->datablk, 0, bpp, |
146 | XFS_DATA_FORK, &xfs_dir3_block_buf_ops); |
147 | if (err || !*bpp) |
148 | return err; |
149 | |
150 | /* Check things that we can't do in the verifier. */ |
151 | fa = xfs_dir3_block_header_check(dp, *bpp); |
152 | if (fa) { |
153 | __xfs_buf_mark_corrupt(*bpp, fa); |
154 | xfs_trans_brelse(tp, *bpp); |
155 | *bpp = NULL; |
156 | xfs_dirattr_mark_sick(dp, XFS_DATA_FORK); |
157 | return -EFSCORRUPTED; |
158 | } |
159 | |
160 | xfs_trans_buf_set_type(tp, *bpp, XFS_BLFT_DIR_BLOCK_BUF); |
161 | return err; |
162 | } |
163 | |
164 | static void |
165 | xfs_dir3_block_init( |
166 | struct xfs_mount *mp, |
167 | struct xfs_trans *tp, |
168 | struct xfs_buf *bp, |
169 | struct xfs_inode *dp) |
170 | { |
171 | struct xfs_dir3_blk_hdr *hdr3 = bp->b_addr; |
172 | |
173 | bp->b_ops = &xfs_dir3_block_buf_ops; |
174 | xfs_trans_buf_set_type(tp, bp, XFS_BLFT_DIR_BLOCK_BUF); |
175 | |
176 | if (xfs_has_crc(mp)) { |
177 | memset(hdr3, 0, sizeof(*hdr3)); |
178 | hdr3->magic = cpu_to_be32(XFS_DIR3_BLOCK_MAGIC); |
179 | hdr3->blkno = cpu_to_be64(xfs_buf_daddr(bp)); |
180 | hdr3->owner = cpu_to_be64(dp->i_ino); |
181 | uuid_copy(&hdr3->uuid, &mp->m_sb.sb_meta_uuid); |
182 | return; |
183 | |
184 | } |
185 | hdr3->magic = cpu_to_be32(XFS_DIR2_BLOCK_MAGIC); |
186 | } |
187 | |
188 | static void |
189 | xfs_dir2_block_need_space( |
190 | struct xfs_inode *dp, |
191 | struct xfs_dir2_data_hdr *hdr, |
192 | struct xfs_dir2_block_tail *btp, |
193 | struct xfs_dir2_leaf_entry *blp, |
194 | __be16 **tagpp, |
195 | struct xfs_dir2_data_unused **dupp, |
196 | struct xfs_dir2_data_unused **enddupp, |
197 | int *compact, |
198 | int len) |
199 | { |
200 | struct xfs_dir2_data_free *bf; |
201 | __be16 *tagp = NULL; |
202 | struct xfs_dir2_data_unused *dup = NULL; |
203 | struct xfs_dir2_data_unused *enddup = NULL; |
204 | |
205 | *compact = 0; |
206 | bf = xfs_dir2_data_bestfree_p(mp: dp->i_mount, hdr); |
207 | |
208 | /* |
209 | * If there are stale entries we'll use one for the leaf. |
210 | */ |
211 | if (btp->stale) { |
212 | if (be16_to_cpu(bf[0].length) >= len) { |
213 | /* |
214 | * The biggest entry enough to avoid compaction. |
215 | */ |
216 | dup = (xfs_dir2_data_unused_t *) |
217 | ((char *)hdr + be16_to_cpu(bf[0].offset)); |
218 | goto out; |
219 | } |
220 | |
221 | /* |
222 | * Will need to compact to make this work. |
223 | * Tag just before the first leaf entry. |
224 | */ |
225 | *compact = 1; |
226 | tagp = (__be16 *)blp - 1; |
227 | |
228 | /* Data object just before the first leaf entry. */ |
229 | dup = (xfs_dir2_data_unused_t *)((char *)hdr + be16_to_cpu(*tagp)); |
230 | |
231 | /* |
232 | * If it's not free then the data will go where the |
233 | * leaf data starts now, if it works at all. |
234 | */ |
235 | if (be16_to_cpu(dup->freetag) == XFS_DIR2_DATA_FREE_TAG) { |
236 | if (be16_to_cpu(dup->length) + (be32_to_cpu(btp->stale) - 1) * |
237 | (uint)sizeof(*blp) < len) |
238 | dup = NULL; |
239 | } else if ((be32_to_cpu(btp->stale) - 1) * (uint)sizeof(*blp) < len) |
240 | dup = NULL; |
241 | else |
242 | dup = (xfs_dir2_data_unused_t *)blp; |
243 | goto out; |
244 | } |
245 | |
246 | /* |
247 | * no stale entries, so just use free space. |
248 | * Tag just before the first leaf entry. |
249 | */ |
250 | tagp = (__be16 *)blp - 1; |
251 | |
252 | /* Data object just before the first leaf entry. */ |
253 | enddup = (xfs_dir2_data_unused_t *)((char *)hdr + be16_to_cpu(*tagp)); |
254 | |
255 | /* |
256 | * If it's not free then can't do this add without cleaning up: |
257 | * the space before the first leaf entry needs to be free so it |
258 | * can be expanded to hold the pointer to the new entry. |
259 | */ |
260 | if (be16_to_cpu(enddup->freetag) == XFS_DIR2_DATA_FREE_TAG) { |
261 | /* |
262 | * Check out the biggest freespace and see if it's the same one. |
263 | */ |
264 | dup = (xfs_dir2_data_unused_t *) |
265 | ((char *)hdr + be16_to_cpu(bf[0].offset)); |
266 | if (dup != enddup) { |
267 | /* |
268 | * Not the same free entry, just check its length. |
269 | */ |
270 | if (be16_to_cpu(dup->length) < len) |
271 | dup = NULL; |
272 | goto out; |
273 | } |
274 | |
275 | /* |
276 | * It is the biggest freespace, can it hold the leaf too? |
277 | */ |
278 | if (be16_to_cpu(dup->length) < len + (uint)sizeof(*blp)) { |
279 | /* |
280 | * Yes, use the second-largest entry instead if it works. |
281 | */ |
282 | if (be16_to_cpu(bf[1].length) >= len) |
283 | dup = (xfs_dir2_data_unused_t *) |
284 | ((char *)hdr + be16_to_cpu(bf[1].offset)); |
285 | else |
286 | dup = NULL; |
287 | } |
288 | } |
289 | out: |
290 | *tagpp = tagp; |
291 | *dupp = dup; |
292 | *enddupp = enddup; |
293 | } |
294 | |
295 | /* |
296 | * compact the leaf entries. |
297 | * Leave the highest-numbered stale entry stale. |
298 | * XXX should be the one closest to mid but mid is not yet computed. |
299 | */ |
300 | static void |
301 | xfs_dir2_block_compact( |
302 | struct xfs_da_args *args, |
303 | struct xfs_buf *bp, |
304 | struct xfs_dir2_data_hdr *hdr, |
305 | struct xfs_dir2_block_tail *btp, |
306 | struct xfs_dir2_leaf_entry *blp, |
307 | int *needlog, |
308 | int *lfloghigh, |
309 | int *lfloglow) |
310 | { |
311 | int fromidx; /* source leaf index */ |
312 | int toidx; /* target leaf index */ |
313 | int needscan = 0; |
314 | int highstale; /* high stale index */ |
315 | |
316 | fromidx = toidx = be32_to_cpu(btp->count) - 1; |
317 | highstale = *lfloghigh = -1; |
318 | for (; fromidx >= 0; fromidx--) { |
319 | if (blp[fromidx].address == cpu_to_be32(XFS_DIR2_NULL_DATAPTR)) { |
320 | if (highstale == -1) |
321 | highstale = toidx; |
322 | else { |
323 | if (*lfloghigh == -1) |
324 | *lfloghigh = toidx; |
325 | continue; |
326 | } |
327 | } |
328 | if (fromidx < toidx) |
329 | blp[toidx] = blp[fromidx]; |
330 | toidx--; |
331 | } |
332 | *lfloglow = toidx + 1 - (be32_to_cpu(btp->stale) - 1); |
333 | *lfloghigh -= be32_to_cpu(btp->stale) - 1; |
334 | be32_add_cpu(&btp->count, -(be32_to_cpu(btp->stale) - 1)); |
335 | xfs_dir2_data_make_free(args, bp, |
336 | offset: (xfs_dir2_data_aoff_t)((char *)blp - (char *)hdr), |
337 | len: (xfs_dir2_data_aoff_t)((be32_to_cpu(btp->stale) - 1) * sizeof(*blp)), |
338 | needlogp: needlog, needscanp: &needscan); |
339 | btp->stale = cpu_to_be32(1); |
340 | /* |
341 | * If we now need to rebuild the bestfree map, do so. |
342 | * This needs to happen before the next call to use_free. |
343 | */ |
344 | if (needscan) |
345 | xfs_dir2_data_freescan(mp: args->dp->i_mount, hdr, loghead: needlog); |
346 | } |
347 | |
348 | /* |
349 | * Add an entry to a block directory. |
350 | */ |
351 | int /* error */ |
352 | xfs_dir2_block_addname( |
353 | xfs_da_args_t *args) /* directory op arguments */ |
354 | { |
355 | xfs_dir2_data_hdr_t *hdr; /* block header */ |
356 | xfs_dir2_leaf_entry_t *blp; /* block leaf entries */ |
357 | struct xfs_buf *bp; /* buffer for block */ |
358 | xfs_dir2_block_tail_t *btp; /* block tail */ |
359 | int compact; /* need to compact leaf ents */ |
360 | xfs_dir2_data_entry_t *dep; /* block data entry */ |
361 | xfs_inode_t *dp; /* directory inode */ |
362 | xfs_dir2_data_unused_t *dup; /* block unused entry */ |
363 | int error; /* error return value */ |
364 | xfs_dir2_data_unused_t *enddup=NULL; /* unused at end of data */ |
365 | xfs_dahash_t hash; /* hash value of found entry */ |
366 | int high; /* high index for binary srch */ |
367 | int highstale; /* high stale index */ |
368 | int lfloghigh=0; /* last final leaf to log */ |
369 | int lfloglow=0; /* first final leaf to log */ |
370 | int len; /* length of the new entry */ |
371 | int low; /* low index for binary srch */ |
372 | int lowstale; /* low stale index */ |
373 | int mid=0; /* midpoint for binary srch */ |
374 | int needlog; /* need to log header */ |
375 | int needscan; /* need to rescan freespace */ |
376 | __be16 *tagp; /* pointer to tag value */ |
377 | xfs_trans_t *tp; /* transaction structure */ |
378 | |
379 | trace_xfs_dir2_block_addname(args); |
380 | |
381 | dp = args->dp; |
382 | tp = args->trans; |
383 | |
384 | /* Read the (one and only) directory block into bp. */ |
385 | error = xfs_dir3_block_read(tp, dp, &bp); |
386 | if (error) |
387 | return error; |
388 | |
389 | len = xfs_dir2_data_entsize(dp->i_mount, args->namelen); |
390 | |
391 | /* |
392 | * Set up pointers to parts of the block. |
393 | */ |
394 | hdr = bp->b_addr; |
395 | btp = xfs_dir2_block_tail_p(geo: args->geo, hdr); |
396 | blp = xfs_dir2_block_leaf_p(btp); |
397 | |
398 | /* |
399 | * Find out if we can reuse stale entries or whether we need extra |
400 | * space for entry and new leaf. |
401 | */ |
402 | xfs_dir2_block_need_space(dp, hdr, btp, blp, &tagp, &dup, |
403 | &enddup, &compact, len); |
404 | |
405 | /* |
406 | * Done everything we need for a space check now. |
407 | */ |
408 | if (args->op_flags & XFS_DA_OP_JUSTCHECK) { |
409 | xfs_trans_brelse(tp, bp); |
410 | if (!dup) |
411 | return -ENOSPC; |
412 | return 0; |
413 | } |
414 | |
415 | /* |
416 | * If we don't have space for the new entry & leaf ... |
417 | */ |
418 | if (!dup) { |
419 | /* Don't have a space reservation: return no-space. */ |
420 | if (args->total == 0) |
421 | return -ENOSPC; |
422 | /* |
423 | * Convert to the next larger format. |
424 | * Then add the new entry in that format. |
425 | */ |
426 | error = xfs_dir2_block_to_leaf(args, dbp: bp); |
427 | if (error) |
428 | return error; |
429 | return xfs_dir2_leaf_addname(args); |
430 | } |
431 | |
432 | needlog = needscan = 0; |
433 | |
434 | /* |
435 | * If need to compact the leaf entries, do it now. |
436 | */ |
437 | if (compact) { |
438 | xfs_dir2_block_compact(args, bp, hdr, btp, blp, needlog: &needlog, |
439 | lfloghigh: &lfloghigh, lfloglow: &lfloglow); |
440 | /* recalculate blp post-compaction */ |
441 | blp = xfs_dir2_block_leaf_p(btp); |
442 | } else if (btp->stale) { |
443 | /* |
444 | * Set leaf logging boundaries to impossible state. |
445 | * For the no-stale case they're set explicitly. |
446 | */ |
447 | lfloglow = be32_to_cpu(btp->count); |
448 | lfloghigh = -1; |
449 | } |
450 | |
451 | /* |
452 | * Find the slot that's first lower than our hash value, -1 if none. |
453 | */ |
454 | for (low = 0, high = be32_to_cpu(btp->count) - 1; low <= high; ) { |
455 | mid = (low + high) >> 1; |
456 | if ((hash = be32_to_cpu(blp[mid].hashval)) == args->hashval) |
457 | break; |
458 | if (hash < args->hashval) |
459 | low = mid + 1; |
460 | else |
461 | high = mid - 1; |
462 | } |
463 | while (mid >= 0 && be32_to_cpu(blp[mid].hashval) >= args->hashval) { |
464 | mid--; |
465 | } |
466 | /* |
467 | * No stale entries, will use enddup space to hold new leaf. |
468 | */ |
469 | if (!btp->stale) { |
470 | xfs_dir2_data_aoff_t aoff; |
471 | |
472 | /* |
473 | * Mark the space needed for the new leaf entry, now in use. |
474 | */ |
475 | aoff = (xfs_dir2_data_aoff_t)((char *)enddup - (char *)hdr + |
476 | be16_to_cpu(enddup->length) - sizeof(*blp)); |
477 | error = xfs_dir2_data_use_free(args, bp, dup: enddup, offset: aoff, |
478 | len: (xfs_dir2_data_aoff_t)sizeof(*blp), needlogp: &needlog, |
479 | needscanp: &needscan); |
480 | if (error) |
481 | return error; |
482 | |
483 | /* |
484 | * Update the tail (entry count). |
485 | */ |
486 | be32_add_cpu(&btp->count, 1); |
487 | /* |
488 | * If we now need to rebuild the bestfree map, do so. |
489 | * This needs to happen before the next call to use_free. |
490 | */ |
491 | if (needscan) { |
492 | xfs_dir2_data_freescan(dp->i_mount, hdr, &needlog); |
493 | needscan = 0; |
494 | } |
495 | /* |
496 | * Adjust pointer to the first leaf entry, we're about to move |
497 | * the table up one to open up space for the new leaf entry. |
498 | * Then adjust our index to match. |
499 | */ |
500 | blp--; |
501 | mid++; |
502 | if (mid) |
503 | memmove(blp, &blp[1], mid * sizeof(*blp)); |
504 | lfloglow = 0; |
505 | lfloghigh = mid; |
506 | } |
507 | /* |
508 | * Use a stale leaf for our new entry. |
509 | */ |
510 | else { |
511 | for (lowstale = mid; |
512 | lowstale >= 0 && |
513 | blp[lowstale].address != |
514 | cpu_to_be32(XFS_DIR2_NULL_DATAPTR); |
515 | lowstale--) |
516 | continue; |
517 | for (highstale = mid + 1; |
518 | highstale < be32_to_cpu(btp->count) && |
519 | blp[highstale].address != |
520 | cpu_to_be32(XFS_DIR2_NULL_DATAPTR) && |
521 | (lowstale < 0 || mid - lowstale > highstale - mid); |
522 | highstale++) |
523 | continue; |
524 | /* |
525 | * Move entries toward the low-numbered stale entry. |
526 | */ |
527 | if (lowstale >= 0 && |
528 | (highstale == be32_to_cpu(btp->count) || |
529 | mid - lowstale <= highstale - mid)) { |
530 | if (mid - lowstale) |
531 | memmove(&blp[lowstale], &blp[lowstale + 1], |
532 | (mid - lowstale) * sizeof(*blp)); |
533 | lfloglow = min(lowstale, lfloglow); |
534 | lfloghigh = max(mid, lfloghigh); |
535 | } |
536 | /* |
537 | * Move entries toward the high-numbered stale entry. |
538 | */ |
539 | else { |
540 | ASSERT(highstale < be32_to_cpu(btp->count)); |
541 | mid++; |
542 | if (highstale - mid) |
543 | memmove(&blp[mid + 1], &blp[mid], |
544 | (highstale - mid) * sizeof(*blp)); |
545 | lfloglow = min(mid, lfloglow); |
546 | lfloghigh = max(highstale, lfloghigh); |
547 | } |
548 | be32_add_cpu(&btp->stale, -1); |
549 | } |
550 | /* |
551 | * Point to the new data entry. |
552 | */ |
553 | dep = (xfs_dir2_data_entry_t *)dup; |
554 | /* |
555 | * Fill in the leaf entry. |
556 | */ |
557 | blp[mid].hashval = cpu_to_be32(args->hashval); |
558 | blp[mid].address = cpu_to_be32(xfs_dir2_byte_to_dataptr( |
559 | by: (char *)dep - (char *)hdr)); |
560 | xfs_dir2_block_log_leaf(tp, bp, lfloglow, lfloghigh); |
561 | /* |
562 | * Mark space for the data entry used. |
563 | */ |
564 | error = xfs_dir2_data_use_free(args, bp, dup, |
565 | offset: (xfs_dir2_data_aoff_t)((char *)dup - (char *)hdr), |
566 | len: (xfs_dir2_data_aoff_t)len, needlogp: &needlog, needscanp: &needscan); |
567 | if (error) |
568 | return error; |
569 | /* |
570 | * Create the new data entry. |
571 | */ |
572 | dep->inumber = cpu_to_be64(args->inumber); |
573 | dep->namelen = args->namelen; |
574 | memcpy(dep->name, args->name, args->namelen); |
575 | xfs_dir2_data_put_ftype(dp->i_mount, dep, args->filetype); |
576 | tagp = xfs_dir2_data_entry_tag_p(dp->i_mount, dep); |
577 | *tagp = cpu_to_be16((char *)dep - (char *)hdr); |
578 | /* |
579 | * Clean up the bestfree array and log the header, tail, and entry. |
580 | */ |
581 | if (needscan) |
582 | xfs_dir2_data_freescan(dp->i_mount, hdr, &needlog); |
583 | if (needlog) |
584 | xfs_dir2_data_log_header(args, bp); |
585 | xfs_dir2_block_log_tail(tp, bp); |
586 | xfs_dir2_data_log_entry(args, bp, dep); |
587 | xfs_dir3_data_check(dp, bp); |
588 | return 0; |
589 | } |
590 | |
591 | /* |
592 | * Log leaf entries from the block. |
593 | */ |
594 | static void |
595 | xfs_dir2_block_log_leaf( |
596 | xfs_trans_t *tp, /* transaction structure */ |
597 | struct xfs_buf *bp, /* block buffer */ |
598 | int first, /* index of first logged leaf */ |
599 | int last) /* index of last logged leaf */ |
600 | { |
601 | xfs_dir2_data_hdr_t *hdr = bp->b_addr; |
602 | xfs_dir2_leaf_entry_t *blp; |
603 | xfs_dir2_block_tail_t *btp; |
604 | |
605 | btp = xfs_dir2_block_tail_p(geo: tp->t_mountp->m_dir_geo, hdr); |
606 | blp = xfs_dir2_block_leaf_p(btp); |
607 | xfs_trans_log_buf(tp, bp, (uint)((char *)&blp[first] - (char *)hdr), |
608 | (uint)((char *)&blp[last + 1] - (char *)hdr - 1)); |
609 | } |
610 | |
611 | /* |
612 | * Log the block tail. |
613 | */ |
614 | static void |
615 | xfs_dir2_block_log_tail( |
616 | xfs_trans_t *tp, /* transaction structure */ |
617 | struct xfs_buf *bp) /* block buffer */ |
618 | { |
619 | xfs_dir2_data_hdr_t *hdr = bp->b_addr; |
620 | xfs_dir2_block_tail_t *btp; |
621 | |
622 | btp = xfs_dir2_block_tail_p(geo: tp->t_mountp->m_dir_geo, hdr); |
623 | xfs_trans_log_buf(tp, bp, (uint)((char *)btp - (char *)hdr), |
624 | (uint)((char *)(btp + 1) - (char *)hdr - 1)); |
625 | } |
626 | |
627 | /* |
628 | * Look up an entry in the block. This is the external routine, |
629 | * xfs_dir2_block_lookup_int does the real work. |
630 | */ |
631 | int /* error */ |
632 | xfs_dir2_block_lookup( |
633 | xfs_da_args_t *args) /* dir lookup arguments */ |
634 | { |
635 | xfs_dir2_data_hdr_t *hdr; /* block header */ |
636 | xfs_dir2_leaf_entry_t *blp; /* block leaf entries */ |
637 | struct xfs_buf *bp; /* block buffer */ |
638 | xfs_dir2_block_tail_t *btp; /* block tail */ |
639 | xfs_dir2_data_entry_t *dep; /* block data entry */ |
640 | xfs_inode_t *dp; /* incore inode */ |
641 | int ent; /* entry index */ |
642 | int error; /* error return value */ |
643 | |
644 | trace_xfs_dir2_block_lookup(args); |
645 | |
646 | /* |
647 | * Get the buffer, look up the entry. |
648 | * If not found (ENOENT) then return, have no buffer. |
649 | */ |
650 | if ((error = xfs_dir2_block_lookup_int(args, bpp: &bp, entno: &ent))) |
651 | return error; |
652 | dp = args->dp; |
653 | hdr = bp->b_addr; |
654 | xfs_dir3_data_check(dp, bp); |
655 | btp = xfs_dir2_block_tail_p(geo: args->geo, hdr); |
656 | blp = xfs_dir2_block_leaf_p(btp); |
657 | /* |
658 | * Get the offset from the leaf entry, to point to the data. |
659 | */ |
660 | dep = (xfs_dir2_data_entry_t *)((char *)hdr + |
661 | xfs_dir2_dataptr_to_off(geo: args->geo, |
662 | dp: be32_to_cpu(blp[ent].address))); |
663 | /* |
664 | * Fill in inode number, CI name if appropriate, release the block. |
665 | */ |
666 | args->inumber = be64_to_cpu(dep->inumber); |
667 | args->filetype = xfs_dir2_data_get_ftype(dp->i_mount, dep); |
668 | error = xfs_dir_cilookup_result(args, name: dep->name, len: dep->namelen); |
669 | xfs_trans_brelse(args->trans, bp); |
670 | return error; |
671 | } |
672 | |
673 | /* |
674 | * Internal block lookup routine. |
675 | */ |
676 | static int /* error */ |
677 | xfs_dir2_block_lookup_int( |
678 | xfs_da_args_t *args, /* dir lookup arguments */ |
679 | struct xfs_buf **bpp, /* returned block buffer */ |
680 | int *entno) /* returned entry number */ |
681 | { |
682 | xfs_dir2_dataptr_t addr; /* data entry address */ |
683 | xfs_dir2_data_hdr_t *hdr; /* block header */ |
684 | xfs_dir2_leaf_entry_t *blp; /* block leaf entries */ |
685 | struct xfs_buf *bp; /* block buffer */ |
686 | xfs_dir2_block_tail_t *btp; /* block tail */ |
687 | xfs_dir2_data_entry_t *dep; /* block data entry */ |
688 | xfs_inode_t *dp; /* incore inode */ |
689 | int error; /* error return value */ |
690 | xfs_dahash_t hash; /* found hash value */ |
691 | int high; /* binary search high index */ |
692 | int low; /* binary search low index */ |
693 | int mid; /* binary search current idx */ |
694 | xfs_trans_t *tp; /* transaction pointer */ |
695 | enum xfs_dacmp cmp; /* comparison result */ |
696 | |
697 | dp = args->dp; |
698 | tp = args->trans; |
699 | |
700 | error = xfs_dir3_block_read(tp, dp, &bp); |
701 | if (error) |
702 | return error; |
703 | |
704 | hdr = bp->b_addr; |
705 | xfs_dir3_data_check(dp, bp); |
706 | btp = xfs_dir2_block_tail_p(geo: args->geo, hdr); |
707 | blp = xfs_dir2_block_leaf_p(btp); |
708 | /* |
709 | * Loop doing a binary search for our hash value. |
710 | * Find our entry, ENOENT if it's not there. |
711 | */ |
712 | for (low = 0, high = be32_to_cpu(btp->count) - 1; ; ) { |
713 | ASSERT(low <= high); |
714 | mid = (low + high) >> 1; |
715 | if ((hash = be32_to_cpu(blp[mid].hashval)) == args->hashval) |
716 | break; |
717 | if (hash < args->hashval) |
718 | low = mid + 1; |
719 | else |
720 | high = mid - 1; |
721 | if (low > high) { |
722 | ASSERT(args->op_flags & XFS_DA_OP_OKNOENT); |
723 | xfs_trans_brelse(tp, bp); |
724 | return -ENOENT; |
725 | } |
726 | } |
727 | /* |
728 | * Back up to the first one with the right hash value. |
729 | */ |
730 | while (mid > 0 && be32_to_cpu(blp[mid - 1].hashval) == args->hashval) { |
731 | mid--; |
732 | } |
733 | /* |
734 | * Now loop forward through all the entries with the |
735 | * right hash value looking for our name. |
736 | */ |
737 | do { |
738 | if ((addr = be32_to_cpu(blp[mid].address)) == XFS_DIR2_NULL_DATAPTR) |
739 | continue; |
740 | /* |
741 | * Get pointer to the entry from the leaf. |
742 | */ |
743 | dep = (xfs_dir2_data_entry_t *) |
744 | ((char *)hdr + xfs_dir2_dataptr_to_off(geo: args->geo, dp: addr)); |
745 | /* |
746 | * Compare name and if it's an exact match, return the index |
747 | * and buffer. If it's the first case-insensitive match, store |
748 | * the index and buffer and continue looking for an exact match. |
749 | */ |
750 | cmp = xfs_dir2_compname(args, name: dep->name, len: dep->namelen); |
751 | if (cmp != XFS_CMP_DIFFERENT && cmp != args->cmpresult) { |
752 | args->cmpresult = cmp; |
753 | *bpp = bp; |
754 | *entno = mid; |
755 | if (cmp == XFS_CMP_EXACT) |
756 | return 0; |
757 | } |
758 | } while (++mid < be32_to_cpu(btp->count) && |
759 | be32_to_cpu(blp[mid].hashval) == hash); |
760 | |
761 | ASSERT(args->op_flags & XFS_DA_OP_OKNOENT); |
762 | /* |
763 | * Here, we can only be doing a lookup (not a rename or replace). |
764 | * If a case-insensitive match was found earlier, return success. |
765 | */ |
766 | if (args->cmpresult == XFS_CMP_CASE) |
767 | return 0; |
768 | /* |
769 | * No match, release the buffer and return ENOENT. |
770 | */ |
771 | xfs_trans_brelse(tp, bp); |
772 | return -ENOENT; |
773 | } |
774 | |
775 | /* |
776 | * Remove an entry from a block format directory. |
777 | * If that makes the block small enough to fit in shortform, transform it. |
778 | */ |
779 | int /* error */ |
780 | xfs_dir2_block_removename( |
781 | xfs_da_args_t *args) /* directory operation args */ |
782 | { |
783 | xfs_dir2_data_hdr_t *hdr; /* block header */ |
784 | xfs_dir2_leaf_entry_t *blp; /* block leaf pointer */ |
785 | struct xfs_buf *bp; /* block buffer */ |
786 | xfs_dir2_block_tail_t *btp; /* block tail */ |
787 | xfs_dir2_data_entry_t *dep; /* block data entry */ |
788 | xfs_inode_t *dp; /* incore inode */ |
789 | int ent; /* block leaf entry index */ |
790 | int error; /* error return value */ |
791 | int needlog; /* need to log block header */ |
792 | int needscan; /* need to fixup bestfree */ |
793 | xfs_dir2_sf_hdr_t sfh; /* shortform header */ |
794 | int size; /* shortform size */ |
795 | xfs_trans_t *tp; /* transaction pointer */ |
796 | |
797 | trace_xfs_dir2_block_removename(args); |
798 | |
799 | /* |
800 | * Look up the entry in the block. Gets the buffer and entry index. |
801 | * It will always be there, the vnodeops level does a lookup first. |
802 | */ |
803 | if ((error = xfs_dir2_block_lookup_int(args, bpp: &bp, entno: &ent))) { |
804 | return error; |
805 | } |
806 | dp = args->dp; |
807 | tp = args->trans; |
808 | hdr = bp->b_addr; |
809 | btp = xfs_dir2_block_tail_p(geo: args->geo, hdr); |
810 | blp = xfs_dir2_block_leaf_p(btp); |
811 | /* |
812 | * Point to the data entry using the leaf entry. |
813 | */ |
814 | dep = (xfs_dir2_data_entry_t *)((char *)hdr + |
815 | xfs_dir2_dataptr_to_off(geo: args->geo, |
816 | dp: be32_to_cpu(blp[ent].address))); |
817 | /* |
818 | * Mark the data entry's space free. |
819 | */ |
820 | needlog = needscan = 0; |
821 | xfs_dir2_data_make_free(args, bp, |
822 | (xfs_dir2_data_aoff_t)((char *)dep - (char *)hdr), |
823 | xfs_dir2_data_entsize(dp->i_mount, dep->namelen), &needlog, |
824 | &needscan); |
825 | /* |
826 | * Fix up the block tail. |
827 | */ |
828 | be32_add_cpu(&btp->stale, 1); |
829 | xfs_dir2_block_log_tail(tp, bp); |
830 | /* |
831 | * Remove the leaf entry by marking it stale. |
832 | */ |
833 | blp[ent].address = cpu_to_be32(XFS_DIR2_NULL_DATAPTR); |
834 | xfs_dir2_block_log_leaf(tp, bp, ent, ent); |
835 | /* |
836 | * Fix up bestfree, log the header if necessary. |
837 | */ |
838 | if (needscan) |
839 | xfs_dir2_data_freescan(dp->i_mount, hdr, &needlog); |
840 | if (needlog) |
841 | xfs_dir2_data_log_header(args, bp); |
842 | xfs_dir3_data_check(dp, bp); |
843 | /* |
844 | * See if the size as a shortform is good enough. |
845 | */ |
846 | size = xfs_dir2_block_sfsize(dp, hdr, &sfh); |
847 | if (size > xfs_inode_data_fork_size(dp)) |
848 | return 0; |
849 | |
850 | /* |
851 | * If it works, do the conversion. |
852 | */ |
853 | return xfs_dir2_block_to_sf(args, bp, size, sfhp: &sfh); |
854 | } |
855 | |
856 | /* |
857 | * Replace an entry in a V2 block directory. |
858 | * Change the inode number to the new value. |
859 | */ |
860 | int /* error */ |
861 | xfs_dir2_block_replace( |
862 | xfs_da_args_t *args) /* directory operation args */ |
863 | { |
864 | xfs_dir2_data_hdr_t *hdr; /* block header */ |
865 | xfs_dir2_leaf_entry_t *blp; /* block leaf entries */ |
866 | struct xfs_buf *bp; /* block buffer */ |
867 | xfs_dir2_block_tail_t *btp; /* block tail */ |
868 | xfs_dir2_data_entry_t *dep; /* block data entry */ |
869 | xfs_inode_t *dp; /* incore inode */ |
870 | int ent; /* leaf entry index */ |
871 | int error; /* error return value */ |
872 | |
873 | trace_xfs_dir2_block_replace(args); |
874 | |
875 | /* |
876 | * Lookup the entry in the directory. Get buffer and entry index. |
877 | * This will always succeed since the caller has already done a lookup. |
878 | */ |
879 | if ((error = xfs_dir2_block_lookup_int(args, bpp: &bp, entno: &ent))) { |
880 | return error; |
881 | } |
882 | dp = args->dp; |
883 | hdr = bp->b_addr; |
884 | btp = xfs_dir2_block_tail_p(geo: args->geo, hdr); |
885 | blp = xfs_dir2_block_leaf_p(btp); |
886 | /* |
887 | * Point to the data entry we need to change. |
888 | */ |
889 | dep = (xfs_dir2_data_entry_t *)((char *)hdr + |
890 | xfs_dir2_dataptr_to_off(geo: args->geo, |
891 | dp: be32_to_cpu(blp[ent].address))); |
892 | ASSERT(be64_to_cpu(dep->inumber) != args->inumber); |
893 | /* |
894 | * Change the inode number to the new value. |
895 | */ |
896 | dep->inumber = cpu_to_be64(args->inumber); |
897 | xfs_dir2_data_put_ftype(dp->i_mount, dep, args->filetype); |
898 | xfs_dir2_data_log_entry(args, bp, dep); |
899 | xfs_dir3_data_check(dp, bp); |
900 | return 0; |
901 | } |
902 | |
903 | /* |
904 | * Qsort comparison routine for the block leaf entries. |
905 | */ |
906 | static int /* sort order */ |
907 | xfs_dir2_block_sort( |
908 | const void *a, /* first leaf entry */ |
909 | const void *b) /* second leaf entry */ |
910 | { |
911 | const xfs_dir2_leaf_entry_t *la; /* first leaf entry */ |
912 | const xfs_dir2_leaf_entry_t *lb; /* second leaf entry */ |
913 | |
914 | la = a; |
915 | lb = b; |
916 | return be32_to_cpu(la->hashval) < be32_to_cpu(lb->hashval) ? -1 : |
917 | (be32_to_cpu(la->hashval) > be32_to_cpu(lb->hashval) ? 1 : 0); |
918 | } |
919 | |
920 | /* |
921 | * Convert a V2 leaf directory to a V2 block directory if possible. |
922 | */ |
923 | int /* error */ |
924 | xfs_dir2_leaf_to_block( |
925 | xfs_da_args_t *args, /* operation arguments */ |
926 | struct xfs_buf *lbp, /* leaf buffer */ |
927 | struct xfs_buf *dbp) /* data buffer */ |
928 | { |
929 | __be16 *bestsp; /* leaf bests table */ |
930 | xfs_dir2_data_hdr_t *hdr; /* block header */ |
931 | xfs_dir2_block_tail_t *btp; /* block tail */ |
932 | xfs_inode_t *dp; /* incore directory inode */ |
933 | xfs_dir2_data_unused_t *dup; /* unused data entry */ |
934 | int error; /* error return value */ |
935 | int from; /* leaf from index */ |
936 | xfs_dir2_leaf_t *leaf; /* leaf structure */ |
937 | xfs_dir2_leaf_entry_t *lep; /* leaf entry */ |
938 | xfs_dir2_leaf_tail_t *ltp; /* leaf tail structure */ |
939 | xfs_mount_t *mp; /* file system mount point */ |
940 | int needlog; /* need to log data header */ |
941 | int needscan; /* need to scan for bestfree */ |
942 | xfs_dir2_sf_hdr_t sfh; /* shortform header */ |
943 | int size; /* bytes used */ |
944 | __be16 *tagp; /* end of entry (tag) */ |
945 | int to; /* block/leaf to index */ |
946 | xfs_trans_t *tp; /* transaction pointer */ |
947 | struct xfs_dir3_icleaf_hdr leafhdr; |
948 | |
949 | trace_xfs_dir2_leaf_to_block(args); |
950 | |
951 | dp = args->dp; |
952 | tp = args->trans; |
953 | mp = dp->i_mount; |
954 | leaf = lbp->b_addr; |
955 | xfs_dir2_leaf_hdr_from_disk(mp, &leafhdr, leaf); |
956 | ltp = xfs_dir2_leaf_tail_p(geo: args->geo, lp: leaf); |
957 | |
958 | ASSERT(leafhdr.magic == XFS_DIR2_LEAF1_MAGIC || |
959 | leafhdr.magic == XFS_DIR3_LEAF1_MAGIC); |
960 | /* |
961 | * If there are data blocks other than the first one, take this |
962 | * opportunity to remove trailing empty data blocks that may have |
963 | * been left behind during no-space-reservation operations. |
964 | * These will show up in the leaf bests table. |
965 | */ |
966 | while (dp->i_disk_size > args->geo->blksize) { |
967 | int hdrsz; |
968 | |
969 | hdrsz = args->geo->data_entry_offset; |
970 | bestsp = xfs_dir2_leaf_bests_p(ltp); |
971 | if (be16_to_cpu(bestsp[be32_to_cpu(ltp->bestcount) - 1]) == |
972 | args->geo->blksize - hdrsz) { |
973 | if ((error = |
974 | xfs_dir2_leaf_trim_data(args, lbp, |
975 | db: (xfs_dir2_db_t)(be32_to_cpu(ltp->bestcount) - 1)))) |
976 | return error; |
977 | } else |
978 | return 0; |
979 | } |
980 | /* |
981 | * Read the data block if we don't already have it, give up if it fails. |
982 | */ |
983 | if (!dbp) { |
984 | error = xfs_dir3_data_read(tp, dp, args->geo->datablk, 0, &dbp); |
985 | if (error) |
986 | return error; |
987 | } |
988 | hdr = dbp->b_addr; |
989 | ASSERT(hdr->magic == cpu_to_be32(XFS_DIR2_DATA_MAGIC) || |
990 | hdr->magic == cpu_to_be32(XFS_DIR3_DATA_MAGIC)); |
991 | |
992 | /* |
993 | * Size of the "leaf" area in the block. |
994 | */ |
995 | size = (uint)sizeof(xfs_dir2_block_tail_t) + |
996 | (uint)sizeof(*lep) * (leafhdr.count - leafhdr.stale); |
997 | /* |
998 | * Look at the last data entry. |
999 | */ |
1000 | tagp = (__be16 *)((char *)hdr + args->geo->blksize) - 1; |
1001 | dup = (xfs_dir2_data_unused_t *)((char *)hdr + be16_to_cpu(*tagp)); |
1002 | /* |
1003 | * If it's not free or is too short we can't do it. |
1004 | */ |
1005 | if (be16_to_cpu(dup->freetag) != XFS_DIR2_DATA_FREE_TAG || |
1006 | be16_to_cpu(dup->length) < size) |
1007 | return 0; |
1008 | |
1009 | /* |
1010 | * Start converting it to block form. |
1011 | */ |
1012 | xfs_dir3_block_init(mp, tp, dbp, dp); |
1013 | |
1014 | needlog = 1; |
1015 | needscan = 0; |
1016 | /* |
1017 | * Use up the space at the end of the block (blp/btp). |
1018 | */ |
1019 | error = xfs_dir2_data_use_free(args, bp: dbp, dup, |
1020 | offset: args->geo->blksize - size, len: size, needlogp: &needlog, needscanp: &needscan); |
1021 | if (error) |
1022 | return error; |
1023 | /* |
1024 | * Initialize the block tail. |
1025 | */ |
1026 | btp = xfs_dir2_block_tail_p(geo: args->geo, hdr); |
1027 | btp->count = cpu_to_be32(leafhdr.count - leafhdr.stale); |
1028 | btp->stale = 0; |
1029 | xfs_dir2_block_log_tail(tp, dbp); |
1030 | /* |
1031 | * Initialize the block leaf area. We compact out stale entries. |
1032 | */ |
1033 | lep = xfs_dir2_block_leaf_p(btp); |
1034 | for (from = to = 0; from < leafhdr.count; from++) { |
1035 | if (leafhdr.ents[from].address == |
1036 | cpu_to_be32(XFS_DIR2_NULL_DATAPTR)) |
1037 | continue; |
1038 | lep[to++] = leafhdr.ents[from]; |
1039 | } |
1040 | ASSERT(to == be32_to_cpu(btp->count)); |
1041 | xfs_dir2_block_log_leaf(tp, dbp, 0, be32_to_cpu(btp->count) - 1); |
1042 | /* |
1043 | * Scan the bestfree if we need it and log the data block header. |
1044 | */ |
1045 | if (needscan) |
1046 | xfs_dir2_data_freescan(dp->i_mount, hdr, &needlog); |
1047 | if (needlog) |
1048 | xfs_dir2_data_log_header(args, bp: dbp); |
1049 | /* |
1050 | * Pitch the old leaf block. |
1051 | */ |
1052 | error = xfs_da_shrink_inode(args, args->geo->leafblk, lbp); |
1053 | if (error) |
1054 | return error; |
1055 | |
1056 | /* |
1057 | * Now see if the resulting block can be shrunken to shortform. |
1058 | */ |
1059 | size = xfs_dir2_block_sfsize(dp, hdr, &sfh); |
1060 | if (size > xfs_inode_data_fork_size(dp)) |
1061 | return 0; |
1062 | |
1063 | return xfs_dir2_block_to_sf(args, bp: dbp, size, sfhp: &sfh); |
1064 | } |
1065 | |
1066 | /* |
1067 | * Convert the shortform directory to block form. |
1068 | */ |
1069 | int /* error */ |
1070 | xfs_dir2_sf_to_block( |
1071 | struct xfs_da_args *args) |
1072 | { |
1073 | struct xfs_trans *tp = args->trans; |
1074 | struct xfs_inode *dp = args->dp; |
1075 | struct xfs_mount *mp = dp->i_mount; |
1076 | struct xfs_ifork *ifp = xfs_ifork_ptr(dp, XFS_DATA_FORK); |
1077 | struct xfs_da_geometry *geo = args->geo; |
1078 | xfs_dir2_db_t blkno; /* dir-relative block # (0) */ |
1079 | xfs_dir2_data_hdr_t *hdr; /* block header */ |
1080 | xfs_dir2_leaf_entry_t *blp; /* block leaf entries */ |
1081 | struct xfs_buf *bp; /* block buffer */ |
1082 | xfs_dir2_block_tail_t *btp; /* block tail pointer */ |
1083 | xfs_dir2_data_entry_t *dep; /* data entry pointer */ |
1084 | int dummy; /* trash */ |
1085 | xfs_dir2_data_unused_t *dup; /* unused entry pointer */ |
1086 | int endoffset; /* end of data objects */ |
1087 | int error; /* error return value */ |
1088 | int i; /* index */ |
1089 | int needlog; /* need to log block header */ |
1090 | int needscan; /* need to scan block freespc */ |
1091 | int newoffset; /* offset from current entry */ |
1092 | unsigned int offset = geo->data_entry_offset; |
1093 | xfs_dir2_sf_entry_t *sfep; /* sf entry pointer */ |
1094 | struct xfs_dir2_sf_hdr *oldsfp = ifp->if_data; |
1095 | xfs_dir2_sf_hdr_t *sfp; /* shortform header */ |
1096 | __be16 *tagp; /* end of data entry */ |
1097 | struct xfs_name name; |
1098 | |
1099 | trace_xfs_dir2_sf_to_block(args); |
1100 | |
1101 | ASSERT(ifp->if_format == XFS_DINODE_FMT_LOCAL); |
1102 | ASSERT(dp->i_disk_size >= offsetof(struct xfs_dir2_sf_hdr, parent)); |
1103 | |
1104 | ASSERT(ifp->if_bytes == dp->i_disk_size); |
1105 | ASSERT(oldsfp != NULL); |
1106 | ASSERT(dp->i_disk_size >= xfs_dir2_sf_hdr_size(i8count: oldsfp->i8count)); |
1107 | ASSERT(dp->i_df.if_nextents == 0); |
1108 | |
1109 | /* |
1110 | * Copy the directory into a temporary buffer. |
1111 | * Then pitch the incore inode data so we can make extents. |
1112 | */ |
1113 | sfp = kmalloc(ifp->if_bytes, GFP_KERNEL | __GFP_NOFAIL); |
1114 | memcpy(sfp, oldsfp, ifp->if_bytes); |
1115 | |
1116 | xfs_idata_realloc(dp, -ifp->if_bytes, XFS_DATA_FORK); |
1117 | xfs_bmap_local_to_extents_empty(tp, dp, XFS_DATA_FORK); |
1118 | dp->i_disk_size = 0; |
1119 | |
1120 | /* |
1121 | * Add block 0 to the inode. |
1122 | */ |
1123 | error = xfs_dir2_grow_inode(args, XFS_DIR2_DATA_SPACE, dbp: &blkno); |
1124 | if (error) |
1125 | goto out_free; |
1126 | /* |
1127 | * Initialize the data block, then convert it to block format. |
1128 | */ |
1129 | error = xfs_dir3_data_init(args, blkno, bpp: &bp); |
1130 | if (error) |
1131 | goto out_free; |
1132 | xfs_dir3_block_init(mp, tp, bp, dp); |
1133 | hdr = bp->b_addr; |
1134 | |
1135 | /* |
1136 | * Compute size of block "tail" area. |
1137 | */ |
1138 | i = (uint)sizeof(*btp) + |
1139 | (sfp->count + 2) * (uint)sizeof(xfs_dir2_leaf_entry_t); |
1140 | /* |
1141 | * The whole thing is initialized to free by the init routine. |
1142 | * Say we're using the leaf and tail area. |
1143 | */ |
1144 | dup = bp->b_addr + offset; |
1145 | needlog = needscan = 0; |
1146 | error = xfs_dir2_data_use_free(args, bp, dup, offset: args->geo->blksize - i, |
1147 | len: i, needlogp: &needlog, needscanp: &needscan); |
1148 | if (error) |
1149 | goto out_free; |
1150 | ASSERT(needscan == 0); |
1151 | /* |
1152 | * Fill in the tail. |
1153 | */ |
1154 | btp = xfs_dir2_block_tail_p(geo: args->geo, hdr); |
1155 | btp->count = cpu_to_be32(sfp->count + 2); /* ., .. */ |
1156 | btp->stale = 0; |
1157 | blp = xfs_dir2_block_leaf_p(btp); |
1158 | endoffset = (uint)((char *)blp - (char *)hdr); |
1159 | /* |
1160 | * Remove the freespace, we'll manage it. |
1161 | */ |
1162 | error = xfs_dir2_data_use_free(args, bp, dup, |
1163 | offset: (xfs_dir2_data_aoff_t)((char *)dup - (char *)hdr), |
1164 | len: be16_to_cpu(dup->length), needlogp: &needlog, needscanp: &needscan); |
1165 | if (error) |
1166 | goto out_free; |
1167 | |
1168 | /* |
1169 | * Create entry for . |
1170 | */ |
1171 | dep = bp->b_addr + offset; |
1172 | dep->inumber = cpu_to_be64(dp->i_ino); |
1173 | dep->namelen = 1; |
1174 | dep->name[0] = '.'; |
1175 | xfs_dir2_data_put_ftype(mp, dep, XFS_DIR3_FT_DIR); |
1176 | tagp = xfs_dir2_data_entry_tag_p(mp, dep); |
1177 | *tagp = cpu_to_be16(offset); |
1178 | xfs_dir2_data_log_entry(args, bp, dep); |
1179 | blp[0].hashval = cpu_to_be32(xfs_dir_hash_dot); |
1180 | blp[0].address = cpu_to_be32(xfs_dir2_byte_to_dataptr(by: offset)); |
1181 | offset += xfs_dir2_data_entsize(mp, namelen: dep->namelen); |
1182 | |
1183 | /* |
1184 | * Create entry for .. |
1185 | */ |
1186 | dep = bp->b_addr + offset; |
1187 | dep->inumber = cpu_to_be64(xfs_dir2_sf_get_parent_ino(sfp)); |
1188 | dep->namelen = 2; |
1189 | dep->name[0] = dep->name[1] = '.'; |
1190 | xfs_dir2_data_put_ftype(mp, dep, XFS_DIR3_FT_DIR); |
1191 | tagp = xfs_dir2_data_entry_tag_p(mp, dep); |
1192 | *tagp = cpu_to_be16(offset); |
1193 | xfs_dir2_data_log_entry(args, bp, dep); |
1194 | blp[1].hashval = cpu_to_be32(xfs_dir_hash_dotdot); |
1195 | blp[1].address = cpu_to_be32(xfs_dir2_byte_to_dataptr(by: offset)); |
1196 | offset += xfs_dir2_data_entsize(mp, namelen: dep->namelen); |
1197 | |
1198 | /* |
1199 | * Loop over existing entries, stuff them in. |
1200 | */ |
1201 | i = 0; |
1202 | if (!sfp->count) |
1203 | sfep = NULL; |
1204 | else |
1205 | sfep = xfs_dir2_sf_firstentry(hdr: sfp); |
1206 | |
1207 | /* |
1208 | * Need to preserve the existing offset values in the sf directory. |
1209 | * Insert holes (unused entries) where necessary. |
1210 | */ |
1211 | while (offset < endoffset) { |
1212 | /* |
1213 | * sfep is null when we reach the end of the list. |
1214 | */ |
1215 | if (sfep == NULL) |
1216 | newoffset = endoffset; |
1217 | else |
1218 | newoffset = xfs_dir2_sf_get_offset(sfep); |
1219 | /* |
1220 | * There should be a hole here, make one. |
1221 | */ |
1222 | if (offset < newoffset) { |
1223 | dup = bp->b_addr + offset; |
1224 | dup->freetag = cpu_to_be16(XFS_DIR2_DATA_FREE_TAG); |
1225 | dup->length = cpu_to_be16(newoffset - offset); |
1226 | *xfs_dir2_data_unused_tag_p(dup) = cpu_to_be16(offset); |
1227 | xfs_dir2_data_log_unused(args, bp, dup); |
1228 | xfs_dir2_data_freeinsert(hdr, |
1229 | bf: xfs_dir2_data_bestfree_p(mp, hdr), |
1230 | dup, loghead: &dummy); |
1231 | offset += be16_to_cpu(dup->length); |
1232 | continue; |
1233 | } |
1234 | /* |
1235 | * Copy a real entry. |
1236 | */ |
1237 | dep = bp->b_addr + newoffset; |
1238 | dep->inumber = cpu_to_be64(xfs_dir2_sf_get_ino(mp, sfp, sfep)); |
1239 | dep->namelen = sfep->namelen; |
1240 | xfs_dir2_data_put_ftype(mp, dep, |
1241 | xfs_dir2_sf_get_ftype(mp, sfep)); |
1242 | memcpy(dep->name, sfep->name, dep->namelen); |
1243 | tagp = xfs_dir2_data_entry_tag_p(mp, dep); |
1244 | *tagp = cpu_to_be16(newoffset); |
1245 | xfs_dir2_data_log_entry(args, bp, dep); |
1246 | name.name = sfep->name; |
1247 | name.len = sfep->namelen; |
1248 | blp[2 + i].hashval = cpu_to_be32(xfs_dir2_hashname(mp, &name)); |
1249 | blp[2 + i].address = |
1250 | cpu_to_be32(xfs_dir2_byte_to_dataptr(by: newoffset)); |
1251 | offset = (int)((char *)(tagp + 1) - (char *)hdr); |
1252 | if (++i == sfp->count) |
1253 | sfep = NULL; |
1254 | else |
1255 | sfep = xfs_dir2_sf_nextentry(mp, hdr: sfp, sfep); |
1256 | } |
1257 | /* Done with the temporary buffer */ |
1258 | kfree(sfp); |
1259 | /* |
1260 | * Sort the leaf entries by hash value. |
1261 | */ |
1262 | xfs_sort(blp, be32_to_cpu(btp->count), sizeof(*blp), xfs_dir2_block_sort); |
1263 | /* |
1264 | * Log the leaf entry area and tail. |
1265 | * Already logged the header in data_init, ignore needlog. |
1266 | */ |
1267 | ASSERT(needscan == 0); |
1268 | xfs_dir2_block_log_leaf(tp, bp, 0, be32_to_cpu(btp->count) - 1); |
1269 | xfs_dir2_block_log_tail(tp, bp); |
1270 | xfs_dir3_data_check(dp, bp); |
1271 | return 0; |
1272 | out_free: |
1273 | kfree(sfp); |
1274 | return error; |
1275 | } |
1276 | |