0001
0002
0003
0004
0005
0006 #include "xfs.h"
0007 #include "xfs_fs.h"
0008 #include "xfs_shared.h"
0009 #include "xfs_format.h"
0010 #include "xfs_log_format.h"
0011 #include "xfs_trans_resv.h"
0012 #include "xfs_mount.h"
0013 #include "xfs_inode.h"
0014 #include "xfs_trans.h"
0015 #include "xfs_bmap.h"
0016 #include "xfs_dir2.h"
0017 #include "xfs_dir2_priv.h"
0018 #include "xfs_errortag.h"
0019 #include "xfs_error.h"
0020 #include "xfs_trace.h"
0021
0022 const struct xfs_name xfs_name_dotdot = {
0023 .name = (const unsigned char *)"..",
0024 .len = 2,
0025 .type = XFS_DIR3_FT_DIR,
0026 };
0027
0028
0029
0030
0031 unsigned char
0032 xfs_mode_to_ftype(
0033 int mode)
0034 {
0035 switch (mode & S_IFMT) {
0036 case S_IFREG:
0037 return XFS_DIR3_FT_REG_FILE;
0038 case S_IFDIR:
0039 return XFS_DIR3_FT_DIR;
0040 case S_IFCHR:
0041 return XFS_DIR3_FT_CHRDEV;
0042 case S_IFBLK:
0043 return XFS_DIR3_FT_BLKDEV;
0044 case S_IFIFO:
0045 return XFS_DIR3_FT_FIFO;
0046 case S_IFSOCK:
0047 return XFS_DIR3_FT_SOCK;
0048 case S_IFLNK:
0049 return XFS_DIR3_FT_SYMLINK;
0050 default:
0051 return XFS_DIR3_FT_UNKNOWN;
0052 }
0053 }
0054
0055
0056
0057
0058
0059 xfs_dahash_t
0060 xfs_ascii_ci_hashname(
0061 const struct xfs_name *name)
0062 {
0063 xfs_dahash_t hash;
0064 int i;
0065
0066 for (i = 0, hash = 0; i < name->len; i++)
0067 hash = tolower(name->name[i]) ^ rol32(hash, 7);
0068
0069 return hash;
0070 }
0071
0072 enum xfs_dacmp
0073 xfs_ascii_ci_compname(
0074 struct xfs_da_args *args,
0075 const unsigned char *name,
0076 int len)
0077 {
0078 enum xfs_dacmp result;
0079 int i;
0080
0081 if (args->namelen != len)
0082 return XFS_CMP_DIFFERENT;
0083
0084 result = XFS_CMP_EXACT;
0085 for (i = 0; i < len; i++) {
0086 if (args->name[i] == name[i])
0087 continue;
0088 if (tolower(args->name[i]) != tolower(name[i]))
0089 return XFS_CMP_DIFFERENT;
0090 result = XFS_CMP_CASE;
0091 }
0092
0093 return result;
0094 }
0095
0096 int
0097 xfs_da_mount(
0098 struct xfs_mount *mp)
0099 {
0100 struct xfs_da_geometry *dageo;
0101
0102
0103 ASSERT(mp->m_sb.sb_versionnum & XFS_SB_VERSION_DIRV2BIT);
0104 ASSERT(xfs_dir2_dirblock_bytes(&mp->m_sb) <= XFS_MAX_BLOCKSIZE);
0105
0106 mp->m_dir_geo = kmem_zalloc(sizeof(struct xfs_da_geometry),
0107 KM_MAYFAIL);
0108 mp->m_attr_geo = kmem_zalloc(sizeof(struct xfs_da_geometry),
0109 KM_MAYFAIL);
0110 if (!mp->m_dir_geo || !mp->m_attr_geo) {
0111 kmem_free(mp->m_dir_geo);
0112 kmem_free(mp->m_attr_geo);
0113 return -ENOMEM;
0114 }
0115
0116
0117 dageo = mp->m_dir_geo;
0118 dageo->blklog = mp->m_sb.sb_blocklog + mp->m_sb.sb_dirblklog;
0119 dageo->fsblog = mp->m_sb.sb_blocklog;
0120 dageo->blksize = xfs_dir2_dirblock_bytes(&mp->m_sb);
0121 dageo->fsbcount = 1 << mp->m_sb.sb_dirblklog;
0122 if (xfs_has_crc(mp)) {
0123 dageo->node_hdr_size = sizeof(struct xfs_da3_node_hdr);
0124 dageo->leaf_hdr_size = sizeof(struct xfs_dir3_leaf_hdr);
0125 dageo->free_hdr_size = sizeof(struct xfs_dir3_free_hdr);
0126 dageo->data_entry_offset =
0127 sizeof(struct xfs_dir3_data_hdr);
0128 } else {
0129 dageo->node_hdr_size = sizeof(struct xfs_da_node_hdr);
0130 dageo->leaf_hdr_size = sizeof(struct xfs_dir2_leaf_hdr);
0131 dageo->free_hdr_size = sizeof(struct xfs_dir2_free_hdr);
0132 dageo->data_entry_offset =
0133 sizeof(struct xfs_dir2_data_hdr);
0134 }
0135 dageo->leaf_max_ents = (dageo->blksize - dageo->leaf_hdr_size) /
0136 sizeof(struct xfs_dir2_leaf_entry);
0137 dageo->free_max_bests = (dageo->blksize - dageo->free_hdr_size) /
0138 sizeof(xfs_dir2_data_off_t);
0139
0140 dageo->data_first_offset = dageo->data_entry_offset +
0141 xfs_dir2_data_entsize(mp, 1) +
0142 xfs_dir2_data_entsize(mp, 2);
0143
0144
0145
0146
0147
0148 dageo->datablk = xfs_dir2_byte_to_da(dageo, XFS_DIR2_DATA_OFFSET);
0149 dageo->leafblk = xfs_dir2_byte_to_da(dageo, XFS_DIR2_LEAF_OFFSET);
0150 dageo->freeblk = xfs_dir2_byte_to_da(dageo, XFS_DIR2_FREE_OFFSET);
0151 dageo->node_ents = (dageo->blksize - dageo->node_hdr_size) /
0152 (uint)sizeof(xfs_da_node_entry_t);
0153 dageo->max_extents = (XFS_DIR2_MAX_SPACES * XFS_DIR2_SPACE_SIZE) >>
0154 mp->m_sb.sb_blocklog;
0155 dageo->magicpct = (dageo->blksize * 37) / 100;
0156
0157
0158 dageo = mp->m_attr_geo;
0159 dageo->blklog = mp->m_sb.sb_blocklog;
0160 dageo->fsblog = mp->m_sb.sb_blocklog;
0161 dageo->blksize = 1 << dageo->blklog;
0162 dageo->fsbcount = 1;
0163 dageo->node_hdr_size = mp->m_dir_geo->node_hdr_size;
0164 dageo->node_ents = (dageo->blksize - dageo->node_hdr_size) /
0165 (uint)sizeof(xfs_da_node_entry_t);
0166
0167 if (xfs_has_large_extent_counts(mp))
0168 dageo->max_extents = XFS_MAX_EXTCNT_ATTR_FORK_LARGE;
0169 else
0170 dageo->max_extents = XFS_MAX_EXTCNT_ATTR_FORK_SMALL;
0171
0172 dageo->magicpct = (dageo->blksize * 37) / 100;
0173 return 0;
0174 }
0175
0176 void
0177 xfs_da_unmount(
0178 struct xfs_mount *mp)
0179 {
0180 kmem_free(mp->m_dir_geo);
0181 kmem_free(mp->m_attr_geo);
0182 }
0183
0184
0185
0186
0187 int
0188 xfs_dir_isempty(
0189 xfs_inode_t *dp)
0190 {
0191 xfs_dir2_sf_hdr_t *sfp;
0192
0193 ASSERT(S_ISDIR(VFS_I(dp)->i_mode));
0194 if (dp->i_disk_size == 0)
0195 return 1;
0196 if (dp->i_disk_size > xfs_inode_data_fork_size(dp))
0197 return 0;
0198 sfp = (xfs_dir2_sf_hdr_t *)dp->i_df.if_u1.if_data;
0199 return !sfp->count;
0200 }
0201
0202
0203
0204
0205 int
0206 xfs_dir_ino_validate(
0207 xfs_mount_t *mp,
0208 xfs_ino_t ino)
0209 {
0210 bool ino_ok = xfs_verify_dir_ino(mp, ino);
0211
0212 if (XFS_IS_CORRUPT(mp, !ino_ok) ||
0213 XFS_TEST_ERROR(false, mp, XFS_ERRTAG_DIR_INO_VALIDATE)) {
0214 xfs_warn(mp, "Invalid inode number 0x%Lx",
0215 (unsigned long long) ino);
0216 return -EFSCORRUPTED;
0217 }
0218 return 0;
0219 }
0220
0221
0222
0223
0224 int
0225 xfs_dir_init(
0226 xfs_trans_t *tp,
0227 xfs_inode_t *dp,
0228 xfs_inode_t *pdp)
0229 {
0230 struct xfs_da_args *args;
0231 int error;
0232
0233 ASSERT(S_ISDIR(VFS_I(dp)->i_mode));
0234 error = xfs_dir_ino_validate(tp->t_mountp, pdp->i_ino);
0235 if (error)
0236 return error;
0237
0238 args = kmem_zalloc(sizeof(*args), KM_NOFS);
0239 if (!args)
0240 return -ENOMEM;
0241
0242 args->geo = dp->i_mount->m_dir_geo;
0243 args->dp = dp;
0244 args->trans = tp;
0245 error = xfs_dir2_sf_create(args, pdp->i_ino);
0246 kmem_free(args);
0247 return error;
0248 }
0249
0250
0251
0252
0253
0254 int
0255 xfs_dir_createname(
0256 struct xfs_trans *tp,
0257 struct xfs_inode *dp,
0258 const struct xfs_name *name,
0259 xfs_ino_t inum,
0260 xfs_extlen_t total)
0261 {
0262 struct xfs_da_args *args;
0263 int rval;
0264 int v;
0265
0266 ASSERT(S_ISDIR(VFS_I(dp)->i_mode));
0267
0268 if (inum) {
0269 rval = xfs_dir_ino_validate(tp->t_mountp, inum);
0270 if (rval)
0271 return rval;
0272 XFS_STATS_INC(dp->i_mount, xs_dir_create);
0273 }
0274
0275 args = kmem_zalloc(sizeof(*args), KM_NOFS);
0276 if (!args)
0277 return -ENOMEM;
0278
0279 args->geo = dp->i_mount->m_dir_geo;
0280 args->name = name->name;
0281 args->namelen = name->len;
0282 args->filetype = name->type;
0283 args->hashval = xfs_dir2_hashname(dp->i_mount, name);
0284 args->inumber = inum;
0285 args->dp = dp;
0286 args->total = total;
0287 args->whichfork = XFS_DATA_FORK;
0288 args->trans = tp;
0289 args->op_flags = XFS_DA_OP_ADDNAME | XFS_DA_OP_OKNOENT;
0290 if (!inum)
0291 args->op_flags |= XFS_DA_OP_JUSTCHECK;
0292
0293 if (dp->i_df.if_format == XFS_DINODE_FMT_LOCAL) {
0294 rval = xfs_dir2_sf_addname(args);
0295 goto out_free;
0296 }
0297
0298 rval = xfs_dir2_isblock(args, &v);
0299 if (rval)
0300 goto out_free;
0301 if (v) {
0302 rval = xfs_dir2_block_addname(args);
0303 goto out_free;
0304 }
0305
0306 rval = xfs_dir2_isleaf(args, &v);
0307 if (rval)
0308 goto out_free;
0309 if (v)
0310 rval = xfs_dir2_leaf_addname(args);
0311 else
0312 rval = xfs_dir2_node_addname(args);
0313
0314 out_free:
0315 kmem_free(args);
0316 return rval;
0317 }
0318
0319
0320
0321
0322
0323 int
0324 xfs_dir_cilookup_result(
0325 struct xfs_da_args *args,
0326 const unsigned char *name,
0327 int len)
0328 {
0329 if (args->cmpresult == XFS_CMP_DIFFERENT)
0330 return -ENOENT;
0331 if (args->cmpresult != XFS_CMP_CASE ||
0332 !(args->op_flags & XFS_DA_OP_CILOOKUP))
0333 return -EEXIST;
0334
0335 args->value = kmem_alloc(len, KM_NOFS | KM_MAYFAIL);
0336 if (!args->value)
0337 return -ENOMEM;
0338
0339 memcpy(args->value, name, len);
0340 args->valuelen = len;
0341 return -EEXIST;
0342 }
0343
0344
0345
0346
0347
0348
0349
0350 int
0351 xfs_dir_lookup(
0352 struct xfs_trans *tp,
0353 struct xfs_inode *dp,
0354 const struct xfs_name *name,
0355 xfs_ino_t *inum,
0356 struct xfs_name *ci_name)
0357 {
0358 struct xfs_da_args *args;
0359 int rval;
0360 int v;
0361 int lock_mode;
0362
0363 ASSERT(S_ISDIR(VFS_I(dp)->i_mode));
0364 XFS_STATS_INC(dp->i_mount, xs_dir_lookup);
0365
0366
0367
0368
0369
0370
0371
0372
0373
0374 args = kmem_zalloc(sizeof(*args), KM_NOFS);
0375 args->geo = dp->i_mount->m_dir_geo;
0376 args->name = name->name;
0377 args->namelen = name->len;
0378 args->filetype = name->type;
0379 args->hashval = xfs_dir2_hashname(dp->i_mount, name);
0380 args->dp = dp;
0381 args->whichfork = XFS_DATA_FORK;
0382 args->trans = tp;
0383 args->op_flags = XFS_DA_OP_OKNOENT;
0384 if (ci_name)
0385 args->op_flags |= XFS_DA_OP_CILOOKUP;
0386
0387 lock_mode = xfs_ilock_data_map_shared(dp);
0388 if (dp->i_df.if_format == XFS_DINODE_FMT_LOCAL) {
0389 rval = xfs_dir2_sf_lookup(args);
0390 goto out_check_rval;
0391 }
0392
0393 rval = xfs_dir2_isblock(args, &v);
0394 if (rval)
0395 goto out_free;
0396 if (v) {
0397 rval = xfs_dir2_block_lookup(args);
0398 goto out_check_rval;
0399 }
0400
0401 rval = xfs_dir2_isleaf(args, &v);
0402 if (rval)
0403 goto out_free;
0404 if (v)
0405 rval = xfs_dir2_leaf_lookup(args);
0406 else
0407 rval = xfs_dir2_node_lookup(args);
0408
0409 out_check_rval:
0410 if (rval == -EEXIST)
0411 rval = 0;
0412 if (!rval) {
0413 *inum = args->inumber;
0414 if (ci_name) {
0415 ci_name->name = args->value;
0416 ci_name->len = args->valuelen;
0417 }
0418 }
0419 out_free:
0420 xfs_iunlock(dp, lock_mode);
0421 kmem_free(args);
0422 return rval;
0423 }
0424
0425
0426
0427
0428 int
0429 xfs_dir_removename(
0430 struct xfs_trans *tp,
0431 struct xfs_inode *dp,
0432 struct xfs_name *name,
0433 xfs_ino_t ino,
0434 xfs_extlen_t total)
0435 {
0436 struct xfs_da_args *args;
0437 int rval;
0438 int v;
0439
0440 ASSERT(S_ISDIR(VFS_I(dp)->i_mode));
0441 XFS_STATS_INC(dp->i_mount, xs_dir_remove);
0442
0443 args = kmem_zalloc(sizeof(*args), KM_NOFS);
0444 if (!args)
0445 return -ENOMEM;
0446
0447 args->geo = dp->i_mount->m_dir_geo;
0448 args->name = name->name;
0449 args->namelen = name->len;
0450 args->filetype = name->type;
0451 args->hashval = xfs_dir2_hashname(dp->i_mount, name);
0452 args->inumber = ino;
0453 args->dp = dp;
0454 args->total = total;
0455 args->whichfork = XFS_DATA_FORK;
0456 args->trans = tp;
0457
0458 if (dp->i_df.if_format == XFS_DINODE_FMT_LOCAL) {
0459 rval = xfs_dir2_sf_removename(args);
0460 goto out_free;
0461 }
0462
0463 rval = xfs_dir2_isblock(args, &v);
0464 if (rval)
0465 goto out_free;
0466 if (v) {
0467 rval = xfs_dir2_block_removename(args);
0468 goto out_free;
0469 }
0470
0471 rval = xfs_dir2_isleaf(args, &v);
0472 if (rval)
0473 goto out_free;
0474 if (v)
0475 rval = xfs_dir2_leaf_removename(args);
0476 else
0477 rval = xfs_dir2_node_removename(args);
0478 out_free:
0479 kmem_free(args);
0480 return rval;
0481 }
0482
0483
0484
0485
0486 int
0487 xfs_dir_replace(
0488 struct xfs_trans *tp,
0489 struct xfs_inode *dp,
0490 const struct xfs_name *name,
0491 xfs_ino_t inum,
0492 xfs_extlen_t total)
0493 {
0494 struct xfs_da_args *args;
0495 int rval;
0496 int v;
0497
0498 ASSERT(S_ISDIR(VFS_I(dp)->i_mode));
0499
0500 rval = xfs_dir_ino_validate(tp->t_mountp, inum);
0501 if (rval)
0502 return rval;
0503
0504 args = kmem_zalloc(sizeof(*args), KM_NOFS);
0505 if (!args)
0506 return -ENOMEM;
0507
0508 args->geo = dp->i_mount->m_dir_geo;
0509 args->name = name->name;
0510 args->namelen = name->len;
0511 args->filetype = name->type;
0512 args->hashval = xfs_dir2_hashname(dp->i_mount, name);
0513 args->inumber = inum;
0514 args->dp = dp;
0515 args->total = total;
0516 args->whichfork = XFS_DATA_FORK;
0517 args->trans = tp;
0518
0519 if (dp->i_df.if_format == XFS_DINODE_FMT_LOCAL) {
0520 rval = xfs_dir2_sf_replace(args);
0521 goto out_free;
0522 }
0523
0524 rval = xfs_dir2_isblock(args, &v);
0525 if (rval)
0526 goto out_free;
0527 if (v) {
0528 rval = xfs_dir2_block_replace(args);
0529 goto out_free;
0530 }
0531
0532 rval = xfs_dir2_isleaf(args, &v);
0533 if (rval)
0534 goto out_free;
0535 if (v)
0536 rval = xfs_dir2_leaf_replace(args);
0537 else
0538 rval = xfs_dir2_node_replace(args);
0539 out_free:
0540 kmem_free(args);
0541 return rval;
0542 }
0543
0544
0545
0546
0547 int
0548 xfs_dir_canenter(
0549 xfs_trans_t *tp,
0550 xfs_inode_t *dp,
0551 struct xfs_name *name)
0552 {
0553 return xfs_dir_createname(tp, dp, name, 0, 0);
0554 }
0555
0556
0557
0558
0559
0560
0561
0562
0563
0564
0565
0566 int
0567 xfs_dir2_grow_inode(
0568 struct xfs_da_args *args,
0569 int space,
0570 xfs_dir2_db_t *dbp)
0571 {
0572 struct xfs_inode *dp = args->dp;
0573 struct xfs_mount *mp = dp->i_mount;
0574 xfs_fileoff_t bno;
0575 int count;
0576 int error;
0577
0578 trace_xfs_dir2_grow_inode(args, space);
0579
0580
0581
0582
0583 bno = XFS_B_TO_FSBT(mp, space * XFS_DIR2_SPACE_SIZE);
0584 count = args->geo->fsbcount;
0585
0586 error = xfs_da_grow_inode_int(args, &bno, count);
0587 if (error)
0588 return error;
0589
0590 *dbp = xfs_dir2_da_to_db(args->geo, (xfs_dablk_t)bno);
0591
0592
0593
0594
0595 if (space == XFS_DIR2_DATA_SPACE) {
0596 xfs_fsize_t size;
0597
0598 size = XFS_FSB_TO_B(mp, bno + count);
0599 if (size > dp->i_disk_size) {
0600 dp->i_disk_size = size;
0601 xfs_trans_log_inode(args->trans, dp, XFS_ILOG_CORE);
0602 }
0603 }
0604 return 0;
0605 }
0606
0607
0608
0609
0610 int
0611 xfs_dir2_isblock(
0612 struct xfs_da_args *args,
0613 int *vp)
0614 {
0615 xfs_fileoff_t last;
0616 int rval;
0617
0618 if ((rval = xfs_bmap_last_offset(args->dp, &last, XFS_DATA_FORK)))
0619 return rval;
0620 rval = XFS_FSB_TO_B(args->dp->i_mount, last) == args->geo->blksize;
0621 if (XFS_IS_CORRUPT(args->dp->i_mount,
0622 rval != 0 &&
0623 args->dp->i_disk_size != args->geo->blksize))
0624 return -EFSCORRUPTED;
0625 *vp = rval;
0626 return 0;
0627 }
0628
0629
0630
0631
0632 int
0633 xfs_dir2_isleaf(
0634 struct xfs_da_args *args,
0635 int *vp)
0636 {
0637 xfs_fileoff_t last;
0638 int rval;
0639
0640 if ((rval = xfs_bmap_last_offset(args->dp, &last, XFS_DATA_FORK)))
0641 return rval;
0642 *vp = last == args->geo->leafblk + args->geo->fsbcount;
0643 return 0;
0644 }
0645
0646
0647
0648
0649
0650
0651 int
0652 xfs_dir2_shrink_inode(
0653 struct xfs_da_args *args,
0654 xfs_dir2_db_t db,
0655 struct xfs_buf *bp)
0656 {
0657 xfs_fileoff_t bno;
0658 xfs_dablk_t da;
0659 int done;
0660 struct xfs_inode *dp;
0661 int error;
0662 struct xfs_mount *mp;
0663 struct xfs_trans *tp;
0664
0665 trace_xfs_dir2_shrink_inode(args, db);
0666
0667 dp = args->dp;
0668 mp = dp->i_mount;
0669 tp = args->trans;
0670 da = xfs_dir2_db_to_da(args->geo, db);
0671
0672
0673 error = xfs_bunmapi(tp, dp, da, args->geo->fsbcount, 0, 0, &done);
0674 if (error) {
0675
0676
0677
0678
0679
0680
0681
0682
0683
0684
0685
0686
0687 return error;
0688 }
0689 ASSERT(done);
0690
0691
0692
0693 xfs_trans_binval(tp, bp);
0694
0695
0696
0697 if (db >= xfs_dir2_byte_to_db(args->geo, XFS_DIR2_LEAF_OFFSET))
0698 return 0;
0699
0700
0701
0702 if (dp->i_disk_size > xfs_dir2_db_off_to_byte(args->geo, db + 1, 0))
0703 return 0;
0704 bno = da;
0705 if ((error = xfs_bmap_last_before(tp, dp, &bno, XFS_DATA_FORK))) {
0706
0707
0708
0709 return error;
0710 }
0711 if (db == args->geo->datablk)
0712 ASSERT(bno == 0);
0713 else
0714 ASSERT(bno > 0);
0715
0716
0717
0718 dp->i_disk_size = XFS_FSB_TO_B(mp, bno);
0719 xfs_trans_log_inode(tp, dp, XFS_ILOG_CORE);
0720 return 0;
0721 }
0722
0723
0724 bool
0725 xfs_dir2_namecheck(
0726 const void *name,
0727 size_t length)
0728 {
0729
0730
0731
0732
0733 if (length >= MAXNAMELEN)
0734 return false;
0735
0736
0737 return !memchr(name, '/', length) && !memchr(name, 0, length);
0738 }
0739
0740 xfs_dahash_t
0741 xfs_dir2_hashname(
0742 struct xfs_mount *mp,
0743 const struct xfs_name *name)
0744 {
0745 if (unlikely(xfs_has_asciici(mp)))
0746 return xfs_ascii_ci_hashname(name);
0747 return xfs_da_hashname(name->name, name->len);
0748 }
0749
0750 enum xfs_dacmp
0751 xfs_dir2_compname(
0752 struct xfs_da_args *args,
0753 const unsigned char *name,
0754 int len)
0755 {
0756 if (unlikely(xfs_has_asciici(args->dp->i_mount)))
0757 return xfs_ascii_ci_compname(args, name, len);
0758 return xfs_da_compname(args, name, len);
0759 }