0001
0002
0003
0004
0005
0006
0007 #include "xfs.h"
0008 #include "xfs_fs.h"
0009 #include "xfs_shared.h"
0010 #include "xfs_format.h"
0011 #include "xfs_log_format.h"
0012 #include "xfs_trans_resv.h"
0013 #include "xfs_mount.h"
0014 #include "xfs_inode.h"
0015 #include "xfs_trans.h"
0016 #include "xfs_bmap.h"
0017 #include "xfs_buf_item.h"
0018 #include "xfs_dir2.h"
0019 #include "xfs_dir2_priv.h"
0020 #include "xfs_error.h"
0021 #include "xfs_trace.h"
0022 #include "xfs_log.h"
0023
0024
0025
0026
0027 static void xfs_dir2_block_log_leaf(xfs_trans_t *tp, struct xfs_buf *bp,
0028 int first, int last);
0029 static void xfs_dir2_block_log_tail(xfs_trans_t *tp, struct xfs_buf *bp);
0030 static int xfs_dir2_block_lookup_int(xfs_da_args_t *args, struct xfs_buf **bpp,
0031 int *entno);
0032 static int xfs_dir2_block_sort(const void *a, const void *b);
0033
0034 static xfs_dahash_t xfs_dir_hash_dot, xfs_dir_hash_dotdot;
0035
0036
0037
0038
0039 void
0040 xfs_dir_startup(void)
0041 {
0042 xfs_dir_hash_dot = xfs_da_hashname((unsigned char *)".", 1);
0043 xfs_dir_hash_dotdot = xfs_da_hashname((unsigned char *)"..", 2);
0044 }
0045
0046 static xfs_failaddr_t
0047 xfs_dir3_block_verify(
0048 struct xfs_buf *bp)
0049 {
0050 struct xfs_mount *mp = bp->b_mount;
0051 struct xfs_dir3_blk_hdr *hdr3 = bp->b_addr;
0052
0053 if (!xfs_verify_magic(bp, hdr3->magic))
0054 return __this_address;
0055
0056 if (xfs_has_crc(mp)) {
0057 if (!uuid_equal(&hdr3->uuid, &mp->m_sb.sb_meta_uuid))
0058 return __this_address;
0059 if (be64_to_cpu(hdr3->blkno) != xfs_buf_daddr(bp))
0060 return __this_address;
0061 if (!xfs_log_check_lsn(mp, be64_to_cpu(hdr3->lsn)))
0062 return __this_address;
0063 }
0064 return __xfs_dir3_data_check(NULL, bp);
0065 }
0066
0067 static void
0068 xfs_dir3_block_read_verify(
0069 struct xfs_buf *bp)
0070 {
0071 struct xfs_mount *mp = bp->b_mount;
0072 xfs_failaddr_t fa;
0073
0074 if (xfs_has_crc(mp) &&
0075 !xfs_buf_verify_cksum(bp, XFS_DIR3_DATA_CRC_OFF))
0076 xfs_verifier_error(bp, -EFSBADCRC, __this_address);
0077 else {
0078 fa = xfs_dir3_block_verify(bp);
0079 if (fa)
0080 xfs_verifier_error(bp, -EFSCORRUPTED, fa);
0081 }
0082 }
0083
0084 static void
0085 xfs_dir3_block_write_verify(
0086 struct xfs_buf *bp)
0087 {
0088 struct xfs_mount *mp = bp->b_mount;
0089 struct xfs_buf_log_item *bip = bp->b_log_item;
0090 struct xfs_dir3_blk_hdr *hdr3 = bp->b_addr;
0091 xfs_failaddr_t fa;
0092
0093 fa = xfs_dir3_block_verify(bp);
0094 if (fa) {
0095 xfs_verifier_error(bp, -EFSCORRUPTED, fa);
0096 return;
0097 }
0098
0099 if (!xfs_has_crc(mp))
0100 return;
0101
0102 if (bip)
0103 hdr3->lsn = cpu_to_be64(bip->bli_item.li_lsn);
0104
0105 xfs_buf_update_cksum(bp, XFS_DIR3_DATA_CRC_OFF);
0106 }
0107
0108 const struct xfs_buf_ops xfs_dir3_block_buf_ops = {
0109 .name = "xfs_dir3_block",
0110 .magic = { cpu_to_be32(XFS_DIR2_BLOCK_MAGIC),
0111 cpu_to_be32(XFS_DIR3_BLOCK_MAGIC) },
0112 .verify_read = xfs_dir3_block_read_verify,
0113 .verify_write = xfs_dir3_block_write_verify,
0114 .verify_struct = xfs_dir3_block_verify,
0115 };
0116
0117 static xfs_failaddr_t
0118 xfs_dir3_block_header_check(
0119 struct xfs_inode *dp,
0120 struct xfs_buf *bp)
0121 {
0122 struct xfs_mount *mp = dp->i_mount;
0123
0124 if (xfs_has_crc(mp)) {
0125 struct xfs_dir3_blk_hdr *hdr3 = bp->b_addr;
0126
0127 if (be64_to_cpu(hdr3->owner) != dp->i_ino)
0128 return __this_address;
0129 }
0130
0131 return NULL;
0132 }
0133
0134 int
0135 xfs_dir3_block_read(
0136 struct xfs_trans *tp,
0137 struct xfs_inode *dp,
0138 struct xfs_buf **bpp)
0139 {
0140 struct xfs_mount *mp = dp->i_mount;
0141 xfs_failaddr_t fa;
0142 int err;
0143
0144 err = xfs_da_read_buf(tp, dp, mp->m_dir_geo->datablk, 0, bpp,
0145 XFS_DATA_FORK, &xfs_dir3_block_buf_ops);
0146 if (err || !*bpp)
0147 return err;
0148
0149
0150 fa = xfs_dir3_block_header_check(dp, *bpp);
0151 if (fa) {
0152 __xfs_buf_mark_corrupt(*bpp, fa);
0153 xfs_trans_brelse(tp, *bpp);
0154 *bpp = NULL;
0155 return -EFSCORRUPTED;
0156 }
0157
0158 xfs_trans_buf_set_type(tp, *bpp, XFS_BLFT_DIR_BLOCK_BUF);
0159 return err;
0160 }
0161
0162 static void
0163 xfs_dir3_block_init(
0164 struct xfs_mount *mp,
0165 struct xfs_trans *tp,
0166 struct xfs_buf *bp,
0167 struct xfs_inode *dp)
0168 {
0169 struct xfs_dir3_blk_hdr *hdr3 = bp->b_addr;
0170
0171 bp->b_ops = &xfs_dir3_block_buf_ops;
0172 xfs_trans_buf_set_type(tp, bp, XFS_BLFT_DIR_BLOCK_BUF);
0173
0174 if (xfs_has_crc(mp)) {
0175 memset(hdr3, 0, sizeof(*hdr3));
0176 hdr3->magic = cpu_to_be32(XFS_DIR3_BLOCK_MAGIC);
0177 hdr3->blkno = cpu_to_be64(xfs_buf_daddr(bp));
0178 hdr3->owner = cpu_to_be64(dp->i_ino);
0179 uuid_copy(&hdr3->uuid, &mp->m_sb.sb_meta_uuid);
0180 return;
0181
0182 }
0183 hdr3->magic = cpu_to_be32(XFS_DIR2_BLOCK_MAGIC);
0184 }
0185
0186 static void
0187 xfs_dir2_block_need_space(
0188 struct xfs_inode *dp,
0189 struct xfs_dir2_data_hdr *hdr,
0190 struct xfs_dir2_block_tail *btp,
0191 struct xfs_dir2_leaf_entry *blp,
0192 __be16 **tagpp,
0193 struct xfs_dir2_data_unused **dupp,
0194 struct xfs_dir2_data_unused **enddupp,
0195 int *compact,
0196 int len)
0197 {
0198 struct xfs_dir2_data_free *bf;
0199 __be16 *tagp = NULL;
0200 struct xfs_dir2_data_unused *dup = NULL;
0201 struct xfs_dir2_data_unused *enddup = NULL;
0202
0203 *compact = 0;
0204 bf = xfs_dir2_data_bestfree_p(dp->i_mount, hdr);
0205
0206
0207
0208
0209 if (btp->stale) {
0210 if (be16_to_cpu(bf[0].length) >= len) {
0211
0212
0213
0214 dup = (xfs_dir2_data_unused_t *)
0215 ((char *)hdr + be16_to_cpu(bf[0].offset));
0216 goto out;
0217 }
0218
0219
0220
0221
0222
0223 *compact = 1;
0224 tagp = (__be16 *)blp - 1;
0225
0226
0227 dup = (xfs_dir2_data_unused_t *)((char *)hdr + be16_to_cpu(*tagp));
0228
0229
0230
0231
0232
0233 if (be16_to_cpu(dup->freetag) == XFS_DIR2_DATA_FREE_TAG) {
0234 if (be16_to_cpu(dup->length) + (be32_to_cpu(btp->stale) - 1) *
0235 (uint)sizeof(*blp) < len)
0236 dup = NULL;
0237 } else if ((be32_to_cpu(btp->stale) - 1) * (uint)sizeof(*blp) < len)
0238 dup = NULL;
0239 else
0240 dup = (xfs_dir2_data_unused_t *)blp;
0241 goto out;
0242 }
0243
0244
0245
0246
0247
0248 tagp = (__be16 *)blp - 1;
0249
0250
0251 enddup = (xfs_dir2_data_unused_t *)((char *)hdr + be16_to_cpu(*tagp));
0252
0253
0254
0255
0256
0257
0258 if (be16_to_cpu(enddup->freetag) == XFS_DIR2_DATA_FREE_TAG) {
0259
0260
0261
0262 dup = (xfs_dir2_data_unused_t *)
0263 ((char *)hdr + be16_to_cpu(bf[0].offset));
0264 if (dup != enddup) {
0265
0266
0267
0268 if (be16_to_cpu(dup->length) < len)
0269 dup = NULL;
0270 goto out;
0271 }
0272
0273
0274
0275
0276 if (be16_to_cpu(dup->length) < len + (uint)sizeof(*blp)) {
0277
0278
0279
0280 if (be16_to_cpu(bf[1].length) >= len)
0281 dup = (xfs_dir2_data_unused_t *)
0282 ((char *)hdr + be16_to_cpu(bf[1].offset));
0283 else
0284 dup = NULL;
0285 }
0286 }
0287 out:
0288 *tagpp = tagp;
0289 *dupp = dup;
0290 *enddupp = enddup;
0291 }
0292
0293
0294
0295
0296
0297
0298 static void
0299 xfs_dir2_block_compact(
0300 struct xfs_da_args *args,
0301 struct xfs_buf *bp,
0302 struct xfs_dir2_data_hdr *hdr,
0303 struct xfs_dir2_block_tail *btp,
0304 struct xfs_dir2_leaf_entry *blp,
0305 int *needlog,
0306 int *lfloghigh,
0307 int *lfloglow)
0308 {
0309 int fromidx;
0310 int toidx;
0311 int needscan = 0;
0312 int highstale;
0313
0314 fromidx = toidx = be32_to_cpu(btp->count) - 1;
0315 highstale = *lfloghigh = -1;
0316 for (; fromidx >= 0; fromidx--) {
0317 if (blp[fromidx].address == cpu_to_be32(XFS_DIR2_NULL_DATAPTR)) {
0318 if (highstale == -1)
0319 highstale = toidx;
0320 else {
0321 if (*lfloghigh == -1)
0322 *lfloghigh = toidx;
0323 continue;
0324 }
0325 }
0326 if (fromidx < toidx)
0327 blp[toidx] = blp[fromidx];
0328 toidx--;
0329 }
0330 *lfloglow = toidx + 1 - (be32_to_cpu(btp->stale) - 1);
0331 *lfloghigh -= be32_to_cpu(btp->stale) - 1;
0332 be32_add_cpu(&btp->count, -(be32_to_cpu(btp->stale) - 1));
0333 xfs_dir2_data_make_free(args, bp,
0334 (xfs_dir2_data_aoff_t)((char *)blp - (char *)hdr),
0335 (xfs_dir2_data_aoff_t)((be32_to_cpu(btp->stale) - 1) * sizeof(*blp)),
0336 needlog, &needscan);
0337 btp->stale = cpu_to_be32(1);
0338
0339
0340
0341
0342 if (needscan)
0343 xfs_dir2_data_freescan(args->dp->i_mount, hdr, needlog);
0344 }
0345
0346
0347
0348
0349 int
0350 xfs_dir2_block_addname(
0351 xfs_da_args_t *args)
0352 {
0353 xfs_dir2_data_hdr_t *hdr;
0354 xfs_dir2_leaf_entry_t *blp;
0355 struct xfs_buf *bp;
0356 xfs_dir2_block_tail_t *btp;
0357 int compact;
0358 xfs_dir2_data_entry_t *dep;
0359 xfs_inode_t *dp;
0360 xfs_dir2_data_unused_t *dup;
0361 int error;
0362 xfs_dir2_data_unused_t *enddup=NULL;
0363 xfs_dahash_t hash;
0364 int high;
0365 int highstale;
0366 int lfloghigh=0;
0367 int lfloglow=0;
0368 int len;
0369 int low;
0370 int lowstale;
0371 int mid=0;
0372 int needlog;
0373 int needscan;
0374 __be16 *tagp;
0375 xfs_trans_t *tp;
0376
0377 trace_xfs_dir2_block_addname(args);
0378
0379 dp = args->dp;
0380 tp = args->trans;
0381
0382
0383 error = xfs_dir3_block_read(tp, dp, &bp);
0384 if (error)
0385 return error;
0386
0387 len = xfs_dir2_data_entsize(dp->i_mount, args->namelen);
0388
0389
0390
0391
0392 hdr = bp->b_addr;
0393 btp = xfs_dir2_block_tail_p(args->geo, hdr);
0394 blp = xfs_dir2_block_leaf_p(btp);
0395
0396
0397
0398
0399
0400 xfs_dir2_block_need_space(dp, hdr, btp, blp, &tagp, &dup,
0401 &enddup, &compact, len);
0402
0403
0404
0405
0406 if (args->op_flags & XFS_DA_OP_JUSTCHECK) {
0407 xfs_trans_brelse(tp, bp);
0408 if (!dup)
0409 return -ENOSPC;
0410 return 0;
0411 }
0412
0413
0414
0415
0416 if (!dup) {
0417
0418 if (args->total == 0)
0419 return -ENOSPC;
0420
0421
0422
0423
0424 error = xfs_dir2_block_to_leaf(args, bp);
0425 if (error)
0426 return error;
0427 return xfs_dir2_leaf_addname(args);
0428 }
0429
0430 needlog = needscan = 0;
0431
0432
0433
0434
0435 if (compact) {
0436 xfs_dir2_block_compact(args, bp, hdr, btp, blp, &needlog,
0437 &lfloghigh, &lfloglow);
0438
0439 blp = xfs_dir2_block_leaf_p(btp);
0440 } else if (btp->stale) {
0441
0442
0443
0444
0445 lfloglow = be32_to_cpu(btp->count);
0446 lfloghigh = -1;
0447 }
0448
0449
0450
0451
0452 for (low = 0, high = be32_to_cpu(btp->count) - 1; low <= high; ) {
0453 mid = (low + high) >> 1;
0454 if ((hash = be32_to_cpu(blp[mid].hashval)) == args->hashval)
0455 break;
0456 if (hash < args->hashval)
0457 low = mid + 1;
0458 else
0459 high = mid - 1;
0460 }
0461 while (mid >= 0 && be32_to_cpu(blp[mid].hashval) >= args->hashval) {
0462 mid--;
0463 }
0464
0465
0466
0467 if (!btp->stale) {
0468 xfs_dir2_data_aoff_t aoff;
0469
0470
0471
0472
0473 aoff = (xfs_dir2_data_aoff_t)((char *)enddup - (char *)hdr +
0474 be16_to_cpu(enddup->length) - sizeof(*blp));
0475 error = xfs_dir2_data_use_free(args, bp, enddup, aoff,
0476 (xfs_dir2_data_aoff_t)sizeof(*blp), &needlog,
0477 &needscan);
0478 if (error)
0479 return error;
0480
0481
0482
0483
0484 be32_add_cpu(&btp->count, 1);
0485
0486
0487
0488
0489 if (needscan) {
0490 xfs_dir2_data_freescan(dp->i_mount, hdr, &needlog);
0491 needscan = 0;
0492 }
0493
0494
0495
0496
0497
0498 blp--;
0499 mid++;
0500 if (mid)
0501 memmove(blp, &blp[1], mid * sizeof(*blp));
0502 lfloglow = 0;
0503 lfloghigh = mid;
0504 }
0505
0506
0507
0508 else {
0509 for (lowstale = mid;
0510 lowstale >= 0 &&
0511 blp[lowstale].address !=
0512 cpu_to_be32(XFS_DIR2_NULL_DATAPTR);
0513 lowstale--)
0514 continue;
0515 for (highstale = mid + 1;
0516 highstale < be32_to_cpu(btp->count) &&
0517 blp[highstale].address !=
0518 cpu_to_be32(XFS_DIR2_NULL_DATAPTR) &&
0519 (lowstale < 0 || mid - lowstale > highstale - mid);
0520 highstale++)
0521 continue;
0522
0523
0524
0525 if (lowstale >= 0 &&
0526 (highstale == be32_to_cpu(btp->count) ||
0527 mid - lowstale <= highstale - mid)) {
0528 if (mid - lowstale)
0529 memmove(&blp[lowstale], &blp[lowstale + 1],
0530 (mid - lowstale) * sizeof(*blp));
0531 lfloglow = min(lowstale, lfloglow);
0532 lfloghigh = max(mid, lfloghigh);
0533 }
0534
0535
0536
0537 else {
0538 ASSERT(highstale < be32_to_cpu(btp->count));
0539 mid++;
0540 if (highstale - mid)
0541 memmove(&blp[mid + 1], &blp[mid],
0542 (highstale - mid) * sizeof(*blp));
0543 lfloglow = min(mid, lfloglow);
0544 lfloghigh = max(highstale, lfloghigh);
0545 }
0546 be32_add_cpu(&btp->stale, -1);
0547 }
0548
0549
0550
0551 dep = (xfs_dir2_data_entry_t *)dup;
0552
0553
0554
0555 blp[mid].hashval = cpu_to_be32(args->hashval);
0556 blp[mid].address = cpu_to_be32(xfs_dir2_byte_to_dataptr(
0557 (char *)dep - (char *)hdr));
0558 xfs_dir2_block_log_leaf(tp, bp, lfloglow, lfloghigh);
0559
0560
0561
0562 error = xfs_dir2_data_use_free(args, bp, dup,
0563 (xfs_dir2_data_aoff_t)((char *)dup - (char *)hdr),
0564 (xfs_dir2_data_aoff_t)len, &needlog, &needscan);
0565 if (error)
0566 return error;
0567
0568
0569
0570 dep->inumber = cpu_to_be64(args->inumber);
0571 dep->namelen = args->namelen;
0572 memcpy(dep->name, args->name, args->namelen);
0573 xfs_dir2_data_put_ftype(dp->i_mount, dep, args->filetype);
0574 tagp = xfs_dir2_data_entry_tag_p(dp->i_mount, dep);
0575 *tagp = cpu_to_be16((char *)dep - (char *)hdr);
0576
0577
0578
0579 if (needscan)
0580 xfs_dir2_data_freescan(dp->i_mount, hdr, &needlog);
0581 if (needlog)
0582 xfs_dir2_data_log_header(args, bp);
0583 xfs_dir2_block_log_tail(tp, bp);
0584 xfs_dir2_data_log_entry(args, bp, dep);
0585 xfs_dir3_data_check(dp, bp);
0586 return 0;
0587 }
0588
0589
0590
0591
0592 static void
0593 xfs_dir2_block_log_leaf(
0594 xfs_trans_t *tp,
0595 struct xfs_buf *bp,
0596 int first,
0597 int last)
0598 {
0599 xfs_dir2_data_hdr_t *hdr = bp->b_addr;
0600 xfs_dir2_leaf_entry_t *blp;
0601 xfs_dir2_block_tail_t *btp;
0602
0603 btp = xfs_dir2_block_tail_p(tp->t_mountp->m_dir_geo, hdr);
0604 blp = xfs_dir2_block_leaf_p(btp);
0605 xfs_trans_log_buf(tp, bp, (uint)((char *)&blp[first] - (char *)hdr),
0606 (uint)((char *)&blp[last + 1] - (char *)hdr - 1));
0607 }
0608
0609
0610
0611
0612 static void
0613 xfs_dir2_block_log_tail(
0614 xfs_trans_t *tp,
0615 struct xfs_buf *bp)
0616 {
0617 xfs_dir2_data_hdr_t *hdr = bp->b_addr;
0618 xfs_dir2_block_tail_t *btp;
0619
0620 btp = xfs_dir2_block_tail_p(tp->t_mountp->m_dir_geo, hdr);
0621 xfs_trans_log_buf(tp, bp, (uint)((char *)btp - (char *)hdr),
0622 (uint)((char *)(btp + 1) - (char *)hdr - 1));
0623 }
0624
0625
0626
0627
0628
0629 int
0630 xfs_dir2_block_lookup(
0631 xfs_da_args_t *args)
0632 {
0633 xfs_dir2_data_hdr_t *hdr;
0634 xfs_dir2_leaf_entry_t *blp;
0635 struct xfs_buf *bp;
0636 xfs_dir2_block_tail_t *btp;
0637 xfs_dir2_data_entry_t *dep;
0638 xfs_inode_t *dp;
0639 int ent;
0640 int error;
0641
0642 trace_xfs_dir2_block_lookup(args);
0643
0644
0645
0646
0647
0648 if ((error = xfs_dir2_block_lookup_int(args, &bp, &ent)))
0649 return error;
0650 dp = args->dp;
0651 hdr = bp->b_addr;
0652 xfs_dir3_data_check(dp, bp);
0653 btp = xfs_dir2_block_tail_p(args->geo, hdr);
0654 blp = xfs_dir2_block_leaf_p(btp);
0655
0656
0657
0658 dep = (xfs_dir2_data_entry_t *)((char *)hdr +
0659 xfs_dir2_dataptr_to_off(args->geo,
0660 be32_to_cpu(blp[ent].address)));
0661
0662
0663
0664 args->inumber = be64_to_cpu(dep->inumber);
0665 args->filetype = xfs_dir2_data_get_ftype(dp->i_mount, dep);
0666 error = xfs_dir_cilookup_result(args, dep->name, dep->namelen);
0667 xfs_trans_brelse(args->trans, bp);
0668 return error;
0669 }
0670
0671
0672
0673
0674 static int
0675 xfs_dir2_block_lookup_int(
0676 xfs_da_args_t *args,
0677 struct xfs_buf **bpp,
0678 int *entno)
0679 {
0680 xfs_dir2_dataptr_t addr;
0681 xfs_dir2_data_hdr_t *hdr;
0682 xfs_dir2_leaf_entry_t *blp;
0683 struct xfs_buf *bp;
0684 xfs_dir2_block_tail_t *btp;
0685 xfs_dir2_data_entry_t *dep;
0686 xfs_inode_t *dp;
0687 int error;
0688 xfs_dahash_t hash;
0689 int high;
0690 int low;
0691 int mid;
0692 xfs_trans_t *tp;
0693 enum xfs_dacmp cmp;
0694
0695 dp = args->dp;
0696 tp = args->trans;
0697
0698 error = xfs_dir3_block_read(tp, dp, &bp);
0699 if (error)
0700 return error;
0701
0702 hdr = bp->b_addr;
0703 xfs_dir3_data_check(dp, bp);
0704 btp = xfs_dir2_block_tail_p(args->geo, hdr);
0705 blp = xfs_dir2_block_leaf_p(btp);
0706
0707
0708
0709
0710 for (low = 0, high = be32_to_cpu(btp->count) - 1; ; ) {
0711 ASSERT(low <= high);
0712 mid = (low + high) >> 1;
0713 if ((hash = be32_to_cpu(blp[mid].hashval)) == args->hashval)
0714 break;
0715 if (hash < args->hashval)
0716 low = mid + 1;
0717 else
0718 high = mid - 1;
0719 if (low > high) {
0720 ASSERT(args->op_flags & XFS_DA_OP_OKNOENT);
0721 xfs_trans_brelse(tp, bp);
0722 return -ENOENT;
0723 }
0724 }
0725
0726
0727
0728 while (mid > 0 && be32_to_cpu(blp[mid - 1].hashval) == args->hashval) {
0729 mid--;
0730 }
0731
0732
0733
0734
0735 do {
0736 if ((addr = be32_to_cpu(blp[mid].address)) == XFS_DIR2_NULL_DATAPTR)
0737 continue;
0738
0739
0740
0741 dep = (xfs_dir2_data_entry_t *)
0742 ((char *)hdr + xfs_dir2_dataptr_to_off(args->geo, addr));
0743
0744
0745
0746
0747
0748 cmp = xfs_dir2_compname(args, dep->name, dep->namelen);
0749 if (cmp != XFS_CMP_DIFFERENT && cmp != args->cmpresult) {
0750 args->cmpresult = cmp;
0751 *bpp = bp;
0752 *entno = mid;
0753 if (cmp == XFS_CMP_EXACT)
0754 return 0;
0755 }
0756 } while (++mid < be32_to_cpu(btp->count) &&
0757 be32_to_cpu(blp[mid].hashval) == hash);
0758
0759 ASSERT(args->op_flags & XFS_DA_OP_OKNOENT);
0760
0761
0762
0763
0764 if (args->cmpresult == XFS_CMP_CASE)
0765 return 0;
0766
0767
0768
0769 xfs_trans_brelse(tp, bp);
0770 return -ENOENT;
0771 }
0772
0773
0774
0775
0776
0777 int
0778 xfs_dir2_block_removename(
0779 xfs_da_args_t *args)
0780 {
0781 xfs_dir2_data_hdr_t *hdr;
0782 xfs_dir2_leaf_entry_t *blp;
0783 struct xfs_buf *bp;
0784 xfs_dir2_block_tail_t *btp;
0785 xfs_dir2_data_entry_t *dep;
0786 xfs_inode_t *dp;
0787 int ent;
0788 int error;
0789 int needlog;
0790 int needscan;
0791 xfs_dir2_sf_hdr_t sfh;
0792 int size;
0793 xfs_trans_t *tp;
0794
0795 trace_xfs_dir2_block_removename(args);
0796
0797
0798
0799
0800
0801 if ((error = xfs_dir2_block_lookup_int(args, &bp, &ent))) {
0802 return error;
0803 }
0804 dp = args->dp;
0805 tp = args->trans;
0806 hdr = bp->b_addr;
0807 btp = xfs_dir2_block_tail_p(args->geo, hdr);
0808 blp = xfs_dir2_block_leaf_p(btp);
0809
0810
0811
0812 dep = (xfs_dir2_data_entry_t *)((char *)hdr +
0813 xfs_dir2_dataptr_to_off(args->geo,
0814 be32_to_cpu(blp[ent].address)));
0815
0816
0817
0818 needlog = needscan = 0;
0819 xfs_dir2_data_make_free(args, bp,
0820 (xfs_dir2_data_aoff_t)((char *)dep - (char *)hdr),
0821 xfs_dir2_data_entsize(dp->i_mount, dep->namelen), &needlog,
0822 &needscan);
0823
0824
0825
0826 be32_add_cpu(&btp->stale, 1);
0827 xfs_dir2_block_log_tail(tp, bp);
0828
0829
0830
0831 blp[ent].address = cpu_to_be32(XFS_DIR2_NULL_DATAPTR);
0832 xfs_dir2_block_log_leaf(tp, bp, ent, ent);
0833
0834
0835
0836 if (needscan)
0837 xfs_dir2_data_freescan(dp->i_mount, hdr, &needlog);
0838 if (needlog)
0839 xfs_dir2_data_log_header(args, bp);
0840 xfs_dir3_data_check(dp, bp);
0841
0842
0843
0844 size = xfs_dir2_block_sfsize(dp, hdr, &sfh);
0845 if (size > xfs_inode_data_fork_size(dp))
0846 return 0;
0847
0848
0849
0850
0851 return xfs_dir2_block_to_sf(args, bp, size, &sfh);
0852 }
0853
0854
0855
0856
0857
0858 int
0859 xfs_dir2_block_replace(
0860 xfs_da_args_t *args)
0861 {
0862 xfs_dir2_data_hdr_t *hdr;
0863 xfs_dir2_leaf_entry_t *blp;
0864 struct xfs_buf *bp;
0865 xfs_dir2_block_tail_t *btp;
0866 xfs_dir2_data_entry_t *dep;
0867 xfs_inode_t *dp;
0868 int ent;
0869 int error;
0870
0871 trace_xfs_dir2_block_replace(args);
0872
0873
0874
0875
0876
0877 if ((error = xfs_dir2_block_lookup_int(args, &bp, &ent))) {
0878 return error;
0879 }
0880 dp = args->dp;
0881 hdr = bp->b_addr;
0882 btp = xfs_dir2_block_tail_p(args->geo, hdr);
0883 blp = xfs_dir2_block_leaf_p(btp);
0884
0885
0886
0887 dep = (xfs_dir2_data_entry_t *)((char *)hdr +
0888 xfs_dir2_dataptr_to_off(args->geo,
0889 be32_to_cpu(blp[ent].address)));
0890 ASSERT(be64_to_cpu(dep->inumber) != args->inumber);
0891
0892
0893
0894 dep->inumber = cpu_to_be64(args->inumber);
0895 xfs_dir2_data_put_ftype(dp->i_mount, dep, args->filetype);
0896 xfs_dir2_data_log_entry(args, bp, dep);
0897 xfs_dir3_data_check(dp, bp);
0898 return 0;
0899 }
0900
0901
0902
0903
0904 static int
0905 xfs_dir2_block_sort(
0906 const void *a,
0907 const void *b)
0908 {
0909 const xfs_dir2_leaf_entry_t *la;
0910 const xfs_dir2_leaf_entry_t *lb;
0911
0912 la = a;
0913 lb = b;
0914 return be32_to_cpu(la->hashval) < be32_to_cpu(lb->hashval) ? -1 :
0915 (be32_to_cpu(la->hashval) > be32_to_cpu(lb->hashval) ? 1 : 0);
0916 }
0917
0918
0919
0920
0921 int
0922 xfs_dir2_leaf_to_block(
0923 xfs_da_args_t *args,
0924 struct xfs_buf *lbp,
0925 struct xfs_buf *dbp)
0926 {
0927 __be16 *bestsp;
0928 xfs_dir2_data_hdr_t *hdr;
0929 xfs_dir2_block_tail_t *btp;
0930 xfs_inode_t *dp;
0931 xfs_dir2_data_unused_t *dup;
0932 int error;
0933 int from;
0934 xfs_dir2_leaf_t *leaf;
0935 xfs_dir2_leaf_entry_t *lep;
0936 xfs_dir2_leaf_tail_t *ltp;
0937 xfs_mount_t *mp;
0938 int needlog;
0939 int needscan;
0940 xfs_dir2_sf_hdr_t sfh;
0941 int size;
0942 __be16 *tagp;
0943 int to;
0944 xfs_trans_t *tp;
0945 struct xfs_dir3_icleaf_hdr leafhdr;
0946
0947 trace_xfs_dir2_leaf_to_block(args);
0948
0949 dp = args->dp;
0950 tp = args->trans;
0951 mp = dp->i_mount;
0952 leaf = lbp->b_addr;
0953 xfs_dir2_leaf_hdr_from_disk(mp, &leafhdr, leaf);
0954 ltp = xfs_dir2_leaf_tail_p(args->geo, leaf);
0955
0956 ASSERT(leafhdr.magic == XFS_DIR2_LEAF1_MAGIC ||
0957 leafhdr.magic == XFS_DIR3_LEAF1_MAGIC);
0958
0959
0960
0961
0962
0963
0964 while (dp->i_disk_size > args->geo->blksize) {
0965 int hdrsz;
0966
0967 hdrsz = args->geo->data_entry_offset;
0968 bestsp = xfs_dir2_leaf_bests_p(ltp);
0969 if (be16_to_cpu(bestsp[be32_to_cpu(ltp->bestcount) - 1]) ==
0970 args->geo->blksize - hdrsz) {
0971 if ((error =
0972 xfs_dir2_leaf_trim_data(args, lbp,
0973 (xfs_dir2_db_t)(be32_to_cpu(ltp->bestcount) - 1))))
0974 return error;
0975 } else
0976 return 0;
0977 }
0978
0979
0980
0981 if (!dbp) {
0982 error = xfs_dir3_data_read(tp, dp, args->geo->datablk, 0, &dbp);
0983 if (error)
0984 return error;
0985 }
0986 hdr = dbp->b_addr;
0987 ASSERT(hdr->magic == cpu_to_be32(XFS_DIR2_DATA_MAGIC) ||
0988 hdr->magic == cpu_to_be32(XFS_DIR3_DATA_MAGIC));
0989
0990
0991
0992
0993 size = (uint)sizeof(xfs_dir2_block_tail_t) +
0994 (uint)sizeof(*lep) * (leafhdr.count - leafhdr.stale);
0995
0996
0997
0998 tagp = (__be16 *)((char *)hdr + args->geo->blksize) - 1;
0999 dup = (xfs_dir2_data_unused_t *)((char *)hdr + be16_to_cpu(*tagp));
1000
1001
1002
1003 if (be16_to_cpu(dup->freetag) != XFS_DIR2_DATA_FREE_TAG ||
1004 be16_to_cpu(dup->length) < size)
1005 return 0;
1006
1007
1008
1009
1010 xfs_dir3_block_init(mp, tp, dbp, dp);
1011
1012 needlog = 1;
1013 needscan = 0;
1014
1015
1016
1017 error = xfs_dir2_data_use_free(args, dbp, dup,
1018 args->geo->blksize - size, size, &needlog, &needscan);
1019 if (error)
1020 return error;
1021
1022
1023
1024 btp = xfs_dir2_block_tail_p(args->geo, hdr);
1025 btp->count = cpu_to_be32(leafhdr.count - leafhdr.stale);
1026 btp->stale = 0;
1027 xfs_dir2_block_log_tail(tp, dbp);
1028
1029
1030
1031 lep = xfs_dir2_block_leaf_p(btp);
1032 for (from = to = 0; from < leafhdr.count; from++) {
1033 if (leafhdr.ents[from].address ==
1034 cpu_to_be32(XFS_DIR2_NULL_DATAPTR))
1035 continue;
1036 lep[to++] = leafhdr.ents[from];
1037 }
1038 ASSERT(to == be32_to_cpu(btp->count));
1039 xfs_dir2_block_log_leaf(tp, dbp, 0, be32_to_cpu(btp->count) - 1);
1040
1041
1042
1043 if (needscan)
1044 xfs_dir2_data_freescan(dp->i_mount, hdr, &needlog);
1045 if (needlog)
1046 xfs_dir2_data_log_header(args, dbp);
1047
1048
1049
1050 error = xfs_da_shrink_inode(args, args->geo->leafblk, lbp);
1051 if (error)
1052 return error;
1053
1054
1055
1056
1057 size = xfs_dir2_block_sfsize(dp, hdr, &sfh);
1058 if (size > xfs_inode_data_fork_size(dp))
1059 return 0;
1060
1061 return xfs_dir2_block_to_sf(args, dbp, size, &sfh);
1062 }
1063
1064
1065
1066
1067 int
1068 xfs_dir2_sf_to_block(
1069 struct xfs_da_args *args)
1070 {
1071 struct xfs_trans *tp = args->trans;
1072 struct xfs_inode *dp = args->dp;
1073 struct xfs_mount *mp = dp->i_mount;
1074 struct xfs_ifork *ifp = xfs_ifork_ptr(dp, XFS_DATA_FORK);
1075 struct xfs_da_geometry *geo = args->geo;
1076 xfs_dir2_db_t blkno;
1077 xfs_dir2_data_hdr_t *hdr;
1078 xfs_dir2_leaf_entry_t *blp;
1079 struct xfs_buf *bp;
1080 xfs_dir2_block_tail_t *btp;
1081 xfs_dir2_data_entry_t *dep;
1082 int dummy;
1083 xfs_dir2_data_unused_t *dup;
1084 int endoffset;
1085 int error;
1086 int i;
1087 int needlog;
1088 int needscan;
1089 int newoffset;
1090 unsigned int offset = geo->data_entry_offset;
1091 xfs_dir2_sf_entry_t *sfep;
1092 xfs_dir2_sf_hdr_t *oldsfp;
1093 xfs_dir2_sf_hdr_t *sfp;
1094 __be16 *tagp;
1095 struct xfs_name name;
1096
1097 trace_xfs_dir2_sf_to_block(args);
1098
1099 ASSERT(ifp->if_format == XFS_DINODE_FMT_LOCAL);
1100 ASSERT(dp->i_disk_size >= offsetof(struct xfs_dir2_sf_hdr, parent));
1101
1102 oldsfp = (xfs_dir2_sf_hdr_t *)ifp->if_u1.if_data;
1103
1104 ASSERT(ifp->if_bytes == dp->i_disk_size);
1105 ASSERT(ifp->if_u1.if_data != NULL);
1106 ASSERT(dp->i_disk_size >= xfs_dir2_sf_hdr_size(oldsfp->i8count));
1107 ASSERT(dp->i_df.if_nextents == 0);
1108
1109
1110
1111
1112
1113 sfp = kmem_alloc(ifp->if_bytes, 0);
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
1122
1123 error = xfs_dir2_grow_inode(args, XFS_DIR2_DATA_SPACE, &blkno);
1124 if (error)
1125 goto out_free;
1126
1127
1128
1129 error = xfs_dir3_data_init(args, blkno, &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
1137
1138 i = (uint)sizeof(*btp) +
1139 (sfp->count + 2) * (uint)sizeof(xfs_dir2_leaf_entry_t);
1140
1141
1142
1143
1144 dup = bp->b_addr + offset;
1145 needlog = needscan = 0;
1146 error = xfs_dir2_data_use_free(args, bp, dup, args->geo->blksize - i,
1147 i, &needlog, &needscan);
1148 if (error)
1149 goto out_free;
1150 ASSERT(needscan == 0);
1151
1152
1153
1154 btp = xfs_dir2_block_tail_p(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
1161
1162 error = xfs_dir2_data_use_free(args, bp, dup,
1163 (xfs_dir2_data_aoff_t)((char *)dup - (char *)hdr),
1164 be16_to_cpu(dup->length), &needlog, &needscan);
1165 if (error)
1166 goto out_free;
1167
1168
1169
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(offset));
1181 offset += xfs_dir2_data_entsize(mp, dep->namelen);
1182
1183
1184
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(offset));
1196 offset += xfs_dir2_data_entsize(mp, dep->namelen);
1197
1198
1199
1200
1201 i = 0;
1202 if (!sfp->count)
1203 sfep = NULL;
1204 else
1205 sfep = xfs_dir2_sf_firstentry(sfp);
1206
1207
1208
1209
1210
1211 while (offset < endoffset) {
1212
1213
1214
1215 if (sfep == NULL)
1216 newoffset = endoffset;
1217 else
1218 newoffset = xfs_dir2_sf_get_offset(sfep);
1219
1220
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 xfs_dir2_data_bestfree_p(mp, hdr),
1230 dup, &dummy);
1231 offset += be16_to_cpu(dup->length);
1232 continue;
1233 }
1234
1235
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(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, sfp, sfep);
1256 }
1257
1258 kmem_free(sfp);
1259
1260
1261
1262 xfs_sort(blp, be32_to_cpu(btp->count), sizeof(*blp), xfs_dir2_block_sort);
1263
1264
1265
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 kmem_free(sfp);
1274 return error;
1275 }