1 // SPDX-License-Identifier: GPL-2.0 2 /* 3 * Copyright (c) 2000-2003,2005 Silicon Graphics, Inc. 4 * All Rights Reserved. 5 */ 6 #include "xfs.h" 7 #include "xfs_fs.h" 8 #include "xfs_format.h" 9 #include "xfs_log_format.h" 10 #include "xfs_trans_resv.h" 11 #include "xfs_mount.h" 12 #include "xfs_da_format.h" 13 #include "xfs_da_btree.h" 14 #include "xfs_inode.h" 15 #include "xfs_trans.h" 16 #include "xfs_inode_item.h" 17 #include "xfs_error.h" 18 #include "xfs_dir2.h" 19 #include "xfs_dir2_priv.h" 20 #include "xfs_trace.h" 21 22 /* 23 * Prototypes for internal functions. 24 */ 25 static void xfs_dir2_sf_addname_easy(xfs_da_args_t *args, 26 xfs_dir2_sf_entry_t *sfep, 27 xfs_dir2_data_aoff_t offset, 28 int new_isize); 29 static void xfs_dir2_sf_addname_hard(xfs_da_args_t *args, int objchange, 30 int new_isize); 31 static int xfs_dir2_sf_addname_pick(xfs_da_args_t *args, int objchange, 32 xfs_dir2_sf_entry_t **sfepp, 33 xfs_dir2_data_aoff_t *offsetp); 34 #ifdef DEBUG 35 static void xfs_dir2_sf_check(xfs_da_args_t *args); 36 #else 37 #define xfs_dir2_sf_check(args) 38 #endif /* DEBUG */ 39 40 static void xfs_dir2_sf_toino4(xfs_da_args_t *args); 41 static void xfs_dir2_sf_toino8(xfs_da_args_t *args); 42 43 /* 44 * Given a block directory (dp/block), calculate its size as a shortform (sf) 45 * directory and a header for the sf directory, if it will fit it the 46 * space currently present in the inode. If it won't fit, the output 47 * size is too big (but not accurate). 48 */ 49 int /* size for sf form */ 50 xfs_dir2_block_sfsize( 51 xfs_inode_t *dp, /* incore inode pointer */ 52 xfs_dir2_data_hdr_t *hdr, /* block directory data */ 53 xfs_dir2_sf_hdr_t *sfhp) /* output: header for sf form */ 54 { 55 xfs_dir2_dataptr_t addr; /* data entry address */ 56 xfs_dir2_leaf_entry_t *blp; /* leaf area of the block */ 57 xfs_dir2_block_tail_t *btp; /* tail area of the block */ 58 int count; /* shortform entry count */ 59 xfs_dir2_data_entry_t *dep; /* data entry in the block */ 60 int i; /* block entry index */ 61 int i8count; /* count of big-inode entries */ 62 int isdot; /* entry is "." */ 63 int isdotdot; /* entry is ".." */ 64 xfs_mount_t *mp; /* mount structure pointer */ 65 int namelen; /* total name bytes */ 66 xfs_ino_t parent = 0; /* parent inode number */ 67 int size=0; /* total computed size */ 68 int has_ftype; 69 struct xfs_da_geometry *geo; 70 71 mp = dp->i_mount; 72 geo = mp->m_dir_geo; 73 74 /* 75 * if there is a filetype field, add the extra byte to the namelen 76 * for each entry that we see. 77 */ 78 has_ftype = xfs_sb_version_hasftype(&mp->m_sb) ? 1 : 0; 79 80 count = i8count = namelen = 0; 81 btp = xfs_dir2_block_tail_p(geo, hdr); 82 blp = xfs_dir2_block_leaf_p(btp); 83 84 /* 85 * Iterate over the block's data entries by using the leaf pointers. 86 */ 87 for (i = 0; i < be32_to_cpu(btp->count); i++) { 88 if ((addr = be32_to_cpu(blp[i].address)) == XFS_DIR2_NULL_DATAPTR) 89 continue; 90 /* 91 * Calculate the pointer to the entry at hand. 92 */ 93 dep = (xfs_dir2_data_entry_t *)((char *)hdr + 94 xfs_dir2_dataptr_to_off(geo, addr)); 95 /* 96 * Detect . and .., so we can special-case them. 97 * . is not included in sf directories. 98 * .. is included by just the parent inode number. 99 */ 100 isdot = dep->namelen == 1 && dep->name[0] == '.'; 101 isdotdot = 102 dep->namelen == 2 && 103 dep->name[0] == '.' && dep->name[1] == '.'; 104 105 if (!isdot) 106 i8count += be64_to_cpu(dep->inumber) > XFS_DIR2_MAX_SHORT_INUM; 107 108 /* take into account the file type field */ 109 if (!isdot && !isdotdot) { 110 count++; 111 namelen += dep->namelen + has_ftype; 112 } else if (isdotdot) 113 parent = be64_to_cpu(dep->inumber); 114 /* 115 * Calculate the new size, see if we should give up yet. 116 */ 117 size = xfs_dir2_sf_hdr_size(i8count) + /* header */ 118 count * 3 * sizeof(u8) + /* namelen + offset */ 119 namelen + /* name */ 120 (i8count ? /* inumber */ 121 count * XFS_INO64_SIZE : 122 count * XFS_INO32_SIZE); 123 if (size > XFS_IFORK_DSIZE(dp)) 124 return size; /* size value is a failure */ 125 } 126 /* 127 * Create the output header, if it worked. 128 */ 129 sfhp->count = count; 130 sfhp->i8count = i8count; 131 dp->d_ops->sf_put_parent_ino(sfhp, parent); 132 return size; 133 } 134 135 /* 136 * Convert a block format directory to shortform. 137 * Caller has already checked that it will fit, and built us a header. 138 */ 139 int /* error */ 140 xfs_dir2_block_to_sf( 141 xfs_da_args_t *args, /* operation arguments */ 142 struct xfs_buf *bp, 143 int size, /* shortform directory size */ 144 xfs_dir2_sf_hdr_t *sfhp) /* shortform directory hdr */ 145 { 146 xfs_dir2_data_hdr_t *hdr; /* block header */ 147 xfs_dir2_data_entry_t *dep; /* data entry pointer */ 148 xfs_inode_t *dp; /* incore directory inode */ 149 xfs_dir2_data_unused_t *dup; /* unused data pointer */ 150 char *endptr; /* end of data entries */ 151 int error; /* error return value */ 152 int logflags; /* inode logging flags */ 153 xfs_mount_t *mp; /* filesystem mount point */ 154 char *ptr; /* current data pointer */ 155 xfs_dir2_sf_entry_t *sfep; /* shortform entry */ 156 xfs_dir2_sf_hdr_t *sfp; /* shortform directory header */ 157 xfs_dir2_sf_hdr_t *dst; /* temporary data buffer */ 158 159 trace_xfs_dir2_block_to_sf(args); 160 161 dp = args->dp; 162 mp = dp->i_mount; 163 164 /* 165 * allocate a temporary destination buffer the size of the inode 166 * to format the data into. Once we have formatted the data, we 167 * can free the block and copy the formatted data into the inode literal 168 * area. 169 */ 170 dst = kmem_alloc(mp->m_sb.sb_inodesize, KM_SLEEP); 171 hdr = bp->b_addr; 172 173 /* 174 * Copy the header into the newly allocate local space. 175 */ 176 sfp = (xfs_dir2_sf_hdr_t *)dst; 177 memcpy(sfp, sfhp, xfs_dir2_sf_hdr_size(sfhp->i8count)); 178 179 /* 180 * Set up to loop over the block's entries. 181 */ 182 ptr = (char *)dp->d_ops->data_entry_p(hdr); 183 endptr = xfs_dir3_data_endp(args->geo, hdr); 184 sfep = xfs_dir2_sf_firstentry(sfp); 185 /* 186 * Loop over the active and unused entries. 187 * Stop when we reach the leaf/tail portion of the block. 188 */ 189 while (ptr < endptr) { 190 /* 191 * If it's unused, just skip over it. 192 */ 193 dup = (xfs_dir2_data_unused_t *)ptr; 194 if (be16_to_cpu(dup->freetag) == XFS_DIR2_DATA_FREE_TAG) { 195 ptr += be16_to_cpu(dup->length); 196 continue; 197 } 198 dep = (xfs_dir2_data_entry_t *)ptr; 199 /* 200 * Skip . 201 */ 202 if (dep->namelen == 1 && dep->name[0] == '.') 203 ASSERT(be64_to_cpu(dep->inumber) == dp->i_ino); 204 /* 205 * Skip .., but make sure the inode number is right. 206 */ 207 else if (dep->namelen == 2 && 208 dep->name[0] == '.' && dep->name[1] == '.') 209 ASSERT(be64_to_cpu(dep->inumber) == 210 dp->d_ops->sf_get_parent_ino(sfp)); 211 /* 212 * Normal entry, copy it into shortform. 213 */ 214 else { 215 sfep->namelen = dep->namelen; 216 xfs_dir2_sf_put_offset(sfep, 217 (xfs_dir2_data_aoff_t) 218 ((char *)dep - (char *)hdr)); 219 memcpy(sfep->name, dep->name, dep->namelen); 220 dp->d_ops->sf_put_ino(sfp, sfep, 221 be64_to_cpu(dep->inumber)); 222 dp->d_ops->sf_put_ftype(sfep, 223 dp->d_ops->data_get_ftype(dep)); 224 225 sfep = dp->d_ops->sf_nextentry(sfp, sfep); 226 } 227 ptr += dp->d_ops->data_entsize(dep->namelen); 228 } 229 ASSERT((char *)sfep - (char *)sfp == size); 230 231 /* now we are done with the block, we can shrink the inode */ 232 logflags = XFS_ILOG_CORE; 233 error = xfs_dir2_shrink_inode(args, args->geo->datablk, bp); 234 if (error) { 235 ASSERT(error != -ENOSPC); 236 goto out; 237 } 238 239 /* 240 * The buffer is now unconditionally gone, whether 241 * xfs_dir2_shrink_inode worked or not. 242 * 243 * Convert the inode to local format and copy the data in. 244 */ 245 ASSERT(dp->i_df.if_bytes == 0); 246 xfs_init_local_fork(dp, XFS_DATA_FORK, dst, size); 247 dp->i_d.di_format = XFS_DINODE_FMT_LOCAL; 248 dp->i_d.di_size = size; 249 250 logflags |= XFS_ILOG_DDATA; 251 xfs_dir2_sf_check(args); 252 out: 253 xfs_trans_log_inode(args->trans, dp, logflags); 254 kmem_free(dst); 255 return error; 256 } 257 258 /* 259 * Add a name to a shortform directory. 260 * There are two algorithms, "easy" and "hard" which we decide on 261 * before changing anything. 262 * Convert to block form if necessary, if the new entry won't fit. 263 */ 264 int /* error */ 265 xfs_dir2_sf_addname( 266 xfs_da_args_t *args) /* operation arguments */ 267 { 268 xfs_inode_t *dp; /* incore directory inode */ 269 int error; /* error return value */ 270 int incr_isize; /* total change in size */ 271 int new_isize; /* di_size after adding name */ 272 int objchange; /* changing to 8-byte inodes */ 273 xfs_dir2_data_aoff_t offset = 0; /* offset for new entry */ 274 int pick; /* which algorithm to use */ 275 xfs_dir2_sf_hdr_t *sfp; /* shortform structure */ 276 xfs_dir2_sf_entry_t *sfep = NULL; /* shortform entry */ 277 278 trace_xfs_dir2_sf_addname(args); 279 280 ASSERT(xfs_dir2_sf_lookup(args) == -ENOENT); 281 dp = args->dp; 282 ASSERT(dp->i_df.if_flags & XFS_IFINLINE); 283 /* 284 * Make sure the shortform value has some of its header. 285 */ 286 if (dp->i_d.di_size < offsetof(xfs_dir2_sf_hdr_t, parent)) { 287 ASSERT(XFS_FORCED_SHUTDOWN(dp->i_mount)); 288 return -EIO; 289 } 290 ASSERT(dp->i_df.if_bytes == dp->i_d.di_size); 291 ASSERT(dp->i_df.if_u1.if_data != NULL); 292 sfp = (xfs_dir2_sf_hdr_t *)dp->i_df.if_u1.if_data; 293 ASSERT(dp->i_d.di_size >= xfs_dir2_sf_hdr_size(sfp->i8count)); 294 /* 295 * Compute entry (and change in) size. 296 */ 297 incr_isize = dp->d_ops->sf_entsize(sfp, args->namelen); 298 objchange = 0; 299 300 /* 301 * Do we have to change to 8 byte inodes? 302 */ 303 if (args->inumber > XFS_DIR2_MAX_SHORT_INUM && sfp->i8count == 0) { 304 /* 305 * Yes, adjust the inode size. old count + (parent + new) 306 */ 307 incr_isize += (sfp->count + 2) * XFS_INO64_DIFF; 308 objchange = 1; 309 } 310 311 new_isize = (int)dp->i_d.di_size + incr_isize; 312 /* 313 * Won't fit as shortform any more (due to size), 314 * or the pick routine says it won't (due to offset values). 315 */ 316 if (new_isize > XFS_IFORK_DSIZE(dp) || 317 (pick = 318 xfs_dir2_sf_addname_pick(args, objchange, &sfep, &offset)) == 0) { 319 /* 320 * Just checking or no space reservation, it doesn't fit. 321 */ 322 if ((args->op_flags & XFS_DA_OP_JUSTCHECK) || args->total == 0) 323 return -ENOSPC; 324 /* 325 * Convert to block form then add the name. 326 */ 327 error = xfs_dir2_sf_to_block(args); 328 if (error) 329 return error; 330 return xfs_dir2_block_addname(args); 331 } 332 /* 333 * Just checking, it fits. 334 */ 335 if (args->op_flags & XFS_DA_OP_JUSTCHECK) 336 return 0; 337 /* 338 * Do it the easy way - just add it at the end. 339 */ 340 if (pick == 1) 341 xfs_dir2_sf_addname_easy(args, sfep, offset, new_isize); 342 /* 343 * Do it the hard way - look for a place to insert the new entry. 344 * Convert to 8 byte inode numbers first if necessary. 345 */ 346 else { 347 ASSERT(pick == 2); 348 if (objchange) 349 xfs_dir2_sf_toino8(args); 350 xfs_dir2_sf_addname_hard(args, objchange, new_isize); 351 } 352 xfs_trans_log_inode(args->trans, dp, XFS_ILOG_CORE | XFS_ILOG_DDATA); 353 return 0; 354 } 355 356 /* 357 * Add the new entry the "easy" way. 358 * This is copying the old directory and adding the new entry at the end. 359 * Since it's sorted by "offset" we need room after the last offset 360 * that's already there, and then room to convert to a block directory. 361 * This is already checked by the pick routine. 362 */ 363 static void 364 xfs_dir2_sf_addname_easy( 365 xfs_da_args_t *args, /* operation arguments */ 366 xfs_dir2_sf_entry_t *sfep, /* pointer to new entry */ 367 xfs_dir2_data_aoff_t offset, /* offset to use for new ent */ 368 int new_isize) /* new directory size */ 369 { 370 int byteoff; /* byte offset in sf dir */ 371 xfs_inode_t *dp; /* incore directory inode */ 372 xfs_dir2_sf_hdr_t *sfp; /* shortform structure */ 373 374 dp = args->dp; 375 376 sfp = (xfs_dir2_sf_hdr_t *)dp->i_df.if_u1.if_data; 377 byteoff = (int)((char *)sfep - (char *)sfp); 378 /* 379 * Grow the in-inode space. 380 */ 381 xfs_idata_realloc(dp, dp->d_ops->sf_entsize(sfp, args->namelen), 382 XFS_DATA_FORK); 383 /* 384 * Need to set up again due to realloc of the inode data. 385 */ 386 sfp = (xfs_dir2_sf_hdr_t *)dp->i_df.if_u1.if_data; 387 sfep = (xfs_dir2_sf_entry_t *)((char *)sfp + byteoff); 388 /* 389 * Fill in the new entry. 390 */ 391 sfep->namelen = args->namelen; 392 xfs_dir2_sf_put_offset(sfep, offset); 393 memcpy(sfep->name, args->name, sfep->namelen); 394 dp->d_ops->sf_put_ino(sfp, sfep, args->inumber); 395 dp->d_ops->sf_put_ftype(sfep, args->filetype); 396 397 /* 398 * Update the header and inode. 399 */ 400 sfp->count++; 401 if (args->inumber > XFS_DIR2_MAX_SHORT_INUM) 402 sfp->i8count++; 403 dp->i_d.di_size = new_isize; 404 xfs_dir2_sf_check(args); 405 } 406 407 /* 408 * Add the new entry the "hard" way. 409 * The caller has already converted to 8 byte inode numbers if necessary, 410 * in which case we need to leave the i8count at 1. 411 * Find a hole that the new entry will fit into, and copy 412 * the first part of the entries, the new entry, and the last part of 413 * the entries. 414 */ 415 /* ARGSUSED */ 416 static void 417 xfs_dir2_sf_addname_hard( 418 xfs_da_args_t *args, /* operation arguments */ 419 int objchange, /* changing inode number size */ 420 int new_isize) /* new directory size */ 421 { 422 int add_datasize; /* data size need for new ent */ 423 char *buf; /* buffer for old */ 424 xfs_inode_t *dp; /* incore directory inode */ 425 int eof; /* reached end of old dir */ 426 int nbytes; /* temp for byte copies */ 427 xfs_dir2_data_aoff_t new_offset; /* next offset value */ 428 xfs_dir2_data_aoff_t offset; /* current offset value */ 429 int old_isize; /* previous di_size */ 430 xfs_dir2_sf_entry_t *oldsfep; /* entry in original dir */ 431 xfs_dir2_sf_hdr_t *oldsfp; /* original shortform dir */ 432 xfs_dir2_sf_entry_t *sfep; /* entry in new dir */ 433 xfs_dir2_sf_hdr_t *sfp; /* new shortform dir */ 434 435 /* 436 * Copy the old directory to the stack buffer. 437 */ 438 dp = args->dp; 439 440 sfp = (xfs_dir2_sf_hdr_t *)dp->i_df.if_u1.if_data; 441 old_isize = (int)dp->i_d.di_size; 442 buf = kmem_alloc(old_isize, KM_SLEEP); 443 oldsfp = (xfs_dir2_sf_hdr_t *)buf; 444 memcpy(oldsfp, sfp, old_isize); 445 /* 446 * Loop over the old directory finding the place we're going 447 * to insert the new entry. 448 * If it's going to end up at the end then oldsfep will point there. 449 */ 450 for (offset = dp->d_ops->data_first_offset, 451 oldsfep = xfs_dir2_sf_firstentry(oldsfp), 452 add_datasize = dp->d_ops->data_entsize(args->namelen), 453 eof = (char *)oldsfep == &buf[old_isize]; 454 !eof; 455 offset = new_offset + dp->d_ops->data_entsize(oldsfep->namelen), 456 oldsfep = dp->d_ops->sf_nextentry(oldsfp, oldsfep), 457 eof = (char *)oldsfep == &buf[old_isize]) { 458 new_offset = xfs_dir2_sf_get_offset(oldsfep); 459 if (offset + add_datasize <= new_offset) 460 break; 461 } 462 /* 463 * Get rid of the old directory, then allocate space for 464 * the new one. We do this so xfs_idata_realloc won't copy 465 * the data. 466 */ 467 xfs_idata_realloc(dp, -old_isize, XFS_DATA_FORK); 468 xfs_idata_realloc(dp, new_isize, XFS_DATA_FORK); 469 /* 470 * Reset the pointer since the buffer was reallocated. 471 */ 472 sfp = (xfs_dir2_sf_hdr_t *)dp->i_df.if_u1.if_data; 473 /* 474 * Copy the first part of the directory, including the header. 475 */ 476 nbytes = (int)((char *)oldsfep - (char *)oldsfp); 477 memcpy(sfp, oldsfp, nbytes); 478 sfep = (xfs_dir2_sf_entry_t *)((char *)sfp + nbytes); 479 /* 480 * Fill in the new entry, and update the header counts. 481 */ 482 sfep->namelen = args->namelen; 483 xfs_dir2_sf_put_offset(sfep, offset); 484 memcpy(sfep->name, args->name, sfep->namelen); 485 dp->d_ops->sf_put_ino(sfp, sfep, args->inumber); 486 dp->d_ops->sf_put_ftype(sfep, args->filetype); 487 sfp->count++; 488 if (args->inumber > XFS_DIR2_MAX_SHORT_INUM && !objchange) 489 sfp->i8count++; 490 /* 491 * If there's more left to copy, do that. 492 */ 493 if (!eof) { 494 sfep = dp->d_ops->sf_nextentry(sfp, sfep); 495 memcpy(sfep, oldsfep, old_isize - nbytes); 496 } 497 kmem_free(buf); 498 dp->i_d.di_size = new_isize; 499 xfs_dir2_sf_check(args); 500 } 501 502 /* 503 * Decide if the new entry will fit at all. 504 * If it will fit, pick between adding the new entry to the end (easy) 505 * or somewhere else (hard). 506 * Return 0 (won't fit), 1 (easy), 2 (hard). 507 */ 508 /*ARGSUSED*/ 509 static int /* pick result */ 510 xfs_dir2_sf_addname_pick( 511 xfs_da_args_t *args, /* operation arguments */ 512 int objchange, /* inode # size changes */ 513 xfs_dir2_sf_entry_t **sfepp, /* out(1): new entry ptr */ 514 xfs_dir2_data_aoff_t *offsetp) /* out(1): new offset */ 515 { 516 xfs_inode_t *dp; /* incore directory inode */ 517 int holefit; /* found hole it will fit in */ 518 int i; /* entry number */ 519 xfs_dir2_data_aoff_t offset; /* data block offset */ 520 xfs_dir2_sf_entry_t *sfep; /* shortform entry */ 521 xfs_dir2_sf_hdr_t *sfp; /* shortform structure */ 522 int size; /* entry's data size */ 523 int used; /* data bytes used */ 524 525 dp = args->dp; 526 527 sfp = (xfs_dir2_sf_hdr_t *)dp->i_df.if_u1.if_data; 528 size = dp->d_ops->data_entsize(args->namelen); 529 offset = dp->d_ops->data_first_offset; 530 sfep = xfs_dir2_sf_firstentry(sfp); 531 holefit = 0; 532 /* 533 * Loop over sf entries. 534 * Keep track of data offset and whether we've seen a place 535 * to insert the new entry. 536 */ 537 for (i = 0; i < sfp->count; i++) { 538 if (!holefit) 539 holefit = offset + size <= xfs_dir2_sf_get_offset(sfep); 540 offset = xfs_dir2_sf_get_offset(sfep) + 541 dp->d_ops->data_entsize(sfep->namelen); 542 sfep = dp->d_ops->sf_nextentry(sfp, sfep); 543 } 544 /* 545 * Calculate data bytes used excluding the new entry, if this 546 * was a data block (block form directory). 547 */ 548 used = offset + 549 (sfp->count + 3) * (uint)sizeof(xfs_dir2_leaf_entry_t) + 550 (uint)sizeof(xfs_dir2_block_tail_t); 551 /* 552 * If it won't fit in a block form then we can't insert it, 553 * we'll go back, convert to block, then try the insert and convert 554 * to leaf. 555 */ 556 if (used + (holefit ? 0 : size) > args->geo->blksize) 557 return 0; 558 /* 559 * If changing the inode number size, do it the hard way. 560 */ 561 if (objchange) 562 return 2; 563 /* 564 * If it won't fit at the end then do it the hard way (use the hole). 565 */ 566 if (used + size > args->geo->blksize) 567 return 2; 568 /* 569 * Do it the easy way. 570 */ 571 *sfepp = sfep; 572 *offsetp = offset; 573 return 1; 574 } 575 576 #ifdef DEBUG 577 /* 578 * Check consistency of shortform directory, assert if bad. 579 */ 580 static void 581 xfs_dir2_sf_check( 582 xfs_da_args_t *args) /* operation arguments */ 583 { 584 xfs_inode_t *dp; /* incore directory inode */ 585 int i; /* entry number */ 586 int i8count; /* number of big inode#s */ 587 xfs_ino_t ino; /* entry inode number */ 588 int offset; /* data offset */ 589 xfs_dir2_sf_entry_t *sfep; /* shortform dir entry */ 590 xfs_dir2_sf_hdr_t *sfp; /* shortform structure */ 591 592 dp = args->dp; 593 594 sfp = (xfs_dir2_sf_hdr_t *)dp->i_df.if_u1.if_data; 595 offset = dp->d_ops->data_first_offset; 596 ino = dp->d_ops->sf_get_parent_ino(sfp); 597 i8count = ino > XFS_DIR2_MAX_SHORT_INUM; 598 599 for (i = 0, sfep = xfs_dir2_sf_firstentry(sfp); 600 i < sfp->count; 601 i++, sfep = dp->d_ops->sf_nextentry(sfp, sfep)) { 602 ASSERT(xfs_dir2_sf_get_offset(sfep) >= offset); 603 ino = dp->d_ops->sf_get_ino(sfp, sfep); 604 i8count += ino > XFS_DIR2_MAX_SHORT_INUM; 605 offset = 606 xfs_dir2_sf_get_offset(sfep) + 607 dp->d_ops->data_entsize(sfep->namelen); 608 ASSERT(dp->d_ops->sf_get_ftype(sfep) < XFS_DIR3_FT_MAX); 609 } 610 ASSERT(i8count == sfp->i8count); 611 ASSERT((char *)sfep - (char *)sfp == dp->i_d.di_size); 612 ASSERT(offset + 613 (sfp->count + 2) * (uint)sizeof(xfs_dir2_leaf_entry_t) + 614 (uint)sizeof(xfs_dir2_block_tail_t) <= args->geo->blksize); 615 } 616 #endif /* DEBUG */ 617 618 /* Verify the consistency of an inline directory. */ 619 xfs_failaddr_t 620 xfs_dir2_sf_verify( 621 struct xfs_inode *ip) 622 { 623 struct xfs_mount *mp = ip->i_mount; 624 struct xfs_dir2_sf_hdr *sfp; 625 struct xfs_dir2_sf_entry *sfep; 626 struct xfs_dir2_sf_entry *next_sfep; 627 char *endp; 628 const struct xfs_dir_ops *dops; 629 struct xfs_ifork *ifp; 630 xfs_ino_t ino; 631 int i; 632 int i8count; 633 int offset; 634 int size; 635 int error; 636 uint8_t filetype; 637 638 ASSERT(ip->i_d.di_format == XFS_DINODE_FMT_LOCAL); 639 /* 640 * xfs_iread calls us before xfs_setup_inode sets up ip->d_ops, 641 * so we can only trust the mountpoint to have the right pointer. 642 */ 643 dops = xfs_dir_get_ops(mp, NULL); 644 645 ifp = XFS_IFORK_PTR(ip, XFS_DATA_FORK); 646 sfp = (struct xfs_dir2_sf_hdr *)ifp->if_u1.if_data; 647 size = ifp->if_bytes; 648 649 /* 650 * Give up if the directory is way too short. 651 */ 652 if (size <= offsetof(struct xfs_dir2_sf_hdr, parent) || 653 size < xfs_dir2_sf_hdr_size(sfp->i8count)) 654 return __this_address; 655 656 endp = (char *)sfp + size; 657 658 /* Check .. entry */ 659 ino = dops->sf_get_parent_ino(sfp); 660 i8count = ino > XFS_DIR2_MAX_SHORT_INUM; 661 error = xfs_dir_ino_validate(mp, ino); 662 if (error) 663 return __this_address; 664 offset = dops->data_first_offset; 665 666 /* Check all reported entries */ 667 sfep = xfs_dir2_sf_firstentry(sfp); 668 for (i = 0; i < sfp->count; i++) { 669 /* 670 * struct xfs_dir2_sf_entry has a variable length. 671 * Check the fixed-offset parts of the structure are 672 * within the data buffer. 673 */ 674 if (((char *)sfep + sizeof(*sfep)) >= endp) 675 return __this_address; 676 677 /* Don't allow names with known bad length. */ 678 if (sfep->namelen == 0) 679 return __this_address; 680 681 /* 682 * Check that the variable-length part of the structure is 683 * within the data buffer. The next entry starts after the 684 * name component, so nextentry is an acceptable test. 685 */ 686 next_sfep = dops->sf_nextentry(sfp, sfep); 687 if (endp < (char *)next_sfep) 688 return __this_address; 689 690 /* Check that the offsets always increase. */ 691 if (xfs_dir2_sf_get_offset(sfep) < offset) 692 return __this_address; 693 694 /* Check the inode number. */ 695 ino = dops->sf_get_ino(sfp, sfep); 696 i8count += ino > XFS_DIR2_MAX_SHORT_INUM; 697 error = xfs_dir_ino_validate(mp, ino); 698 if (error) 699 return __this_address; 700 701 /* Check the file type. */ 702 filetype = dops->sf_get_ftype(sfep); 703 if (filetype >= XFS_DIR3_FT_MAX) 704 return __this_address; 705 706 offset = xfs_dir2_sf_get_offset(sfep) + 707 dops->data_entsize(sfep->namelen); 708 709 sfep = next_sfep; 710 } 711 if (i8count != sfp->i8count) 712 return __this_address; 713 if ((void *)sfep != (void *)endp) 714 return __this_address; 715 716 /* Make sure this whole thing ought to be in local format. */ 717 if (offset + (sfp->count + 2) * (uint)sizeof(xfs_dir2_leaf_entry_t) + 718 (uint)sizeof(xfs_dir2_block_tail_t) > mp->m_dir_geo->blksize) 719 return __this_address; 720 721 return NULL; 722 } 723 724 /* 725 * Create a new (shortform) directory. 726 */ 727 int /* error, always 0 */ 728 xfs_dir2_sf_create( 729 xfs_da_args_t *args, /* operation arguments */ 730 xfs_ino_t pino) /* parent inode number */ 731 { 732 xfs_inode_t *dp; /* incore directory inode */ 733 int i8count; /* parent inode is an 8-byte number */ 734 xfs_dir2_sf_hdr_t *sfp; /* shortform structure */ 735 int size; /* directory size */ 736 737 trace_xfs_dir2_sf_create(args); 738 739 dp = args->dp; 740 741 ASSERT(dp != NULL); 742 ASSERT(dp->i_d.di_size == 0); 743 /* 744 * If it's currently a zero-length extent file, 745 * convert it to local format. 746 */ 747 if (dp->i_d.di_format == XFS_DINODE_FMT_EXTENTS) { 748 dp->i_df.if_flags &= ~XFS_IFEXTENTS; /* just in case */ 749 dp->i_d.di_format = XFS_DINODE_FMT_LOCAL; 750 xfs_trans_log_inode(args->trans, dp, XFS_ILOG_CORE); 751 dp->i_df.if_flags |= XFS_IFINLINE; 752 } 753 ASSERT(dp->i_df.if_flags & XFS_IFINLINE); 754 ASSERT(dp->i_df.if_bytes == 0); 755 i8count = pino > XFS_DIR2_MAX_SHORT_INUM; 756 size = xfs_dir2_sf_hdr_size(i8count); 757 /* 758 * Make a buffer for the data. 759 */ 760 xfs_idata_realloc(dp, size, XFS_DATA_FORK); 761 /* 762 * Fill in the header, 763 */ 764 sfp = (xfs_dir2_sf_hdr_t *)dp->i_df.if_u1.if_data; 765 sfp->i8count = i8count; 766 /* 767 * Now can put in the inode number, since i8count is set. 768 */ 769 dp->d_ops->sf_put_parent_ino(sfp, pino); 770 sfp->count = 0; 771 dp->i_d.di_size = size; 772 xfs_dir2_sf_check(args); 773 xfs_trans_log_inode(args->trans, dp, XFS_ILOG_CORE | XFS_ILOG_DDATA); 774 return 0; 775 } 776 777 /* 778 * Lookup an entry in a shortform directory. 779 * Returns EEXIST if found, ENOENT if not found. 780 */ 781 int /* error */ 782 xfs_dir2_sf_lookup( 783 xfs_da_args_t *args) /* operation arguments */ 784 { 785 xfs_inode_t *dp; /* incore directory inode */ 786 int i; /* entry index */ 787 int error; 788 xfs_dir2_sf_entry_t *sfep; /* shortform directory entry */ 789 xfs_dir2_sf_hdr_t *sfp; /* shortform structure */ 790 enum xfs_dacmp cmp; /* comparison result */ 791 xfs_dir2_sf_entry_t *ci_sfep; /* case-insens. entry */ 792 793 trace_xfs_dir2_sf_lookup(args); 794 795 xfs_dir2_sf_check(args); 796 dp = args->dp; 797 798 ASSERT(dp->i_df.if_flags & XFS_IFINLINE); 799 /* 800 * Bail out if the directory is way too short. 801 */ 802 if (dp->i_d.di_size < offsetof(xfs_dir2_sf_hdr_t, parent)) { 803 ASSERT(XFS_FORCED_SHUTDOWN(dp->i_mount)); 804 return -EIO; 805 } 806 ASSERT(dp->i_df.if_bytes == dp->i_d.di_size); 807 ASSERT(dp->i_df.if_u1.if_data != NULL); 808 sfp = (xfs_dir2_sf_hdr_t *)dp->i_df.if_u1.if_data; 809 ASSERT(dp->i_d.di_size >= xfs_dir2_sf_hdr_size(sfp->i8count)); 810 /* 811 * Special case for . 812 */ 813 if (args->namelen == 1 && args->name[0] == '.') { 814 args->inumber = dp->i_ino; 815 args->cmpresult = XFS_CMP_EXACT; 816 args->filetype = XFS_DIR3_FT_DIR; 817 return -EEXIST; 818 } 819 /* 820 * Special case for .. 821 */ 822 if (args->namelen == 2 && 823 args->name[0] == '.' && args->name[1] == '.') { 824 args->inumber = dp->d_ops->sf_get_parent_ino(sfp); 825 args->cmpresult = XFS_CMP_EXACT; 826 args->filetype = XFS_DIR3_FT_DIR; 827 return -EEXIST; 828 } 829 /* 830 * Loop over all the entries trying to match ours. 831 */ 832 ci_sfep = NULL; 833 for (i = 0, sfep = xfs_dir2_sf_firstentry(sfp); i < sfp->count; 834 i++, sfep = dp->d_ops->sf_nextentry(sfp, sfep)) { 835 /* 836 * Compare name and if it's an exact match, return the inode 837 * number. If it's the first case-insensitive match, store the 838 * inode number and continue looking for an exact match. 839 */ 840 cmp = dp->i_mount->m_dirnameops->compname(args, sfep->name, 841 sfep->namelen); 842 if (cmp != XFS_CMP_DIFFERENT && cmp != args->cmpresult) { 843 args->cmpresult = cmp; 844 args->inumber = dp->d_ops->sf_get_ino(sfp, sfep); 845 args->filetype = dp->d_ops->sf_get_ftype(sfep); 846 if (cmp == XFS_CMP_EXACT) 847 return -EEXIST; 848 ci_sfep = sfep; 849 } 850 } 851 ASSERT(args->op_flags & XFS_DA_OP_OKNOENT); 852 /* 853 * Here, we can only be doing a lookup (not a rename or replace). 854 * If a case-insensitive match was not found, return -ENOENT. 855 */ 856 if (!ci_sfep) 857 return -ENOENT; 858 /* otherwise process the CI match as required by the caller */ 859 error = xfs_dir_cilookup_result(args, ci_sfep->name, ci_sfep->namelen); 860 return error; 861 } 862 863 /* 864 * Remove an entry from a shortform directory. 865 */ 866 int /* error */ 867 xfs_dir2_sf_removename( 868 xfs_da_args_t *args) 869 { 870 int byteoff; /* offset of removed entry */ 871 xfs_inode_t *dp; /* incore directory inode */ 872 int entsize; /* this entry's size */ 873 int i; /* shortform entry index */ 874 int newsize; /* new inode size */ 875 int oldsize; /* old inode size */ 876 xfs_dir2_sf_entry_t *sfep; /* shortform directory entry */ 877 xfs_dir2_sf_hdr_t *sfp; /* shortform structure */ 878 879 trace_xfs_dir2_sf_removename(args); 880 881 dp = args->dp; 882 883 ASSERT(dp->i_df.if_flags & XFS_IFINLINE); 884 oldsize = (int)dp->i_d.di_size; 885 /* 886 * Bail out if the directory is way too short. 887 */ 888 if (oldsize < offsetof(xfs_dir2_sf_hdr_t, parent)) { 889 ASSERT(XFS_FORCED_SHUTDOWN(dp->i_mount)); 890 return -EIO; 891 } 892 ASSERT(dp->i_df.if_bytes == oldsize); 893 ASSERT(dp->i_df.if_u1.if_data != NULL); 894 sfp = (xfs_dir2_sf_hdr_t *)dp->i_df.if_u1.if_data; 895 ASSERT(oldsize >= xfs_dir2_sf_hdr_size(sfp->i8count)); 896 /* 897 * Loop over the old directory entries. 898 * Find the one we're deleting. 899 */ 900 for (i = 0, sfep = xfs_dir2_sf_firstentry(sfp); i < sfp->count; 901 i++, sfep = dp->d_ops->sf_nextentry(sfp, sfep)) { 902 if (xfs_da_compname(args, sfep->name, sfep->namelen) == 903 XFS_CMP_EXACT) { 904 ASSERT(dp->d_ops->sf_get_ino(sfp, sfep) == 905 args->inumber); 906 break; 907 } 908 } 909 /* 910 * Didn't find it. 911 */ 912 if (i == sfp->count) 913 return -ENOENT; 914 /* 915 * Calculate sizes. 916 */ 917 byteoff = (int)((char *)sfep - (char *)sfp); 918 entsize = dp->d_ops->sf_entsize(sfp, args->namelen); 919 newsize = oldsize - entsize; 920 /* 921 * Copy the part if any after the removed entry, sliding it down. 922 */ 923 if (byteoff + entsize < oldsize) 924 memmove((char *)sfp + byteoff, (char *)sfp + byteoff + entsize, 925 oldsize - (byteoff + entsize)); 926 /* 927 * Fix up the header and file size. 928 */ 929 sfp->count--; 930 dp->i_d.di_size = newsize; 931 /* 932 * Reallocate, making it smaller. 933 */ 934 xfs_idata_realloc(dp, newsize - oldsize, XFS_DATA_FORK); 935 sfp = (xfs_dir2_sf_hdr_t *)dp->i_df.if_u1.if_data; 936 /* 937 * Are we changing inode number size? 938 */ 939 if (args->inumber > XFS_DIR2_MAX_SHORT_INUM) { 940 if (sfp->i8count == 1) 941 xfs_dir2_sf_toino4(args); 942 else 943 sfp->i8count--; 944 } 945 xfs_dir2_sf_check(args); 946 xfs_trans_log_inode(args->trans, dp, XFS_ILOG_CORE | XFS_ILOG_DDATA); 947 return 0; 948 } 949 950 /* 951 * Replace the inode number of an entry in a shortform directory. 952 */ 953 int /* error */ 954 xfs_dir2_sf_replace( 955 xfs_da_args_t *args) /* operation arguments */ 956 { 957 xfs_inode_t *dp; /* incore directory inode */ 958 int i; /* entry index */ 959 xfs_ino_t ino=0; /* entry old inode number */ 960 int i8elevated; /* sf_toino8 set i8count=1 */ 961 xfs_dir2_sf_entry_t *sfep; /* shortform directory entry */ 962 xfs_dir2_sf_hdr_t *sfp; /* shortform structure */ 963 964 trace_xfs_dir2_sf_replace(args); 965 966 dp = args->dp; 967 968 ASSERT(dp->i_df.if_flags & XFS_IFINLINE); 969 /* 970 * Bail out if the shortform directory is way too small. 971 */ 972 if (dp->i_d.di_size < offsetof(xfs_dir2_sf_hdr_t, parent)) { 973 ASSERT(XFS_FORCED_SHUTDOWN(dp->i_mount)); 974 return -EIO; 975 } 976 ASSERT(dp->i_df.if_bytes == dp->i_d.di_size); 977 ASSERT(dp->i_df.if_u1.if_data != NULL); 978 sfp = (xfs_dir2_sf_hdr_t *)dp->i_df.if_u1.if_data; 979 ASSERT(dp->i_d.di_size >= xfs_dir2_sf_hdr_size(sfp->i8count)); 980 981 /* 982 * New inode number is large, and need to convert to 8-byte inodes. 983 */ 984 if (args->inumber > XFS_DIR2_MAX_SHORT_INUM && sfp->i8count == 0) { 985 int error; /* error return value */ 986 int newsize; /* new inode size */ 987 988 newsize = dp->i_df.if_bytes + (sfp->count + 1) * XFS_INO64_DIFF; 989 /* 990 * Won't fit as shortform, convert to block then do replace. 991 */ 992 if (newsize > XFS_IFORK_DSIZE(dp)) { 993 error = xfs_dir2_sf_to_block(args); 994 if (error) { 995 return error; 996 } 997 return xfs_dir2_block_replace(args); 998 } 999 /* 1000 * Still fits, convert to 8-byte now. 1001 */ 1002 xfs_dir2_sf_toino8(args); 1003 i8elevated = 1; 1004 sfp = (xfs_dir2_sf_hdr_t *)dp->i_df.if_u1.if_data; 1005 } else 1006 i8elevated = 0; 1007 1008 ASSERT(args->namelen != 1 || args->name[0] != '.'); 1009 /* 1010 * Replace ..'s entry. 1011 */ 1012 if (args->namelen == 2 && 1013 args->name[0] == '.' && args->name[1] == '.') { 1014 ino = dp->d_ops->sf_get_parent_ino(sfp); 1015 ASSERT(args->inumber != ino); 1016 dp->d_ops->sf_put_parent_ino(sfp, args->inumber); 1017 } 1018 /* 1019 * Normal entry, look for the name. 1020 */ 1021 else { 1022 for (i = 0, sfep = xfs_dir2_sf_firstentry(sfp); i < sfp->count; 1023 i++, sfep = dp->d_ops->sf_nextentry(sfp, sfep)) { 1024 if (xfs_da_compname(args, sfep->name, sfep->namelen) == 1025 XFS_CMP_EXACT) { 1026 ino = dp->d_ops->sf_get_ino(sfp, sfep); 1027 ASSERT(args->inumber != ino); 1028 dp->d_ops->sf_put_ino(sfp, sfep, args->inumber); 1029 dp->d_ops->sf_put_ftype(sfep, args->filetype); 1030 break; 1031 } 1032 } 1033 /* 1034 * Didn't find it. 1035 */ 1036 if (i == sfp->count) { 1037 ASSERT(args->op_flags & XFS_DA_OP_OKNOENT); 1038 if (i8elevated) 1039 xfs_dir2_sf_toino4(args); 1040 return -ENOENT; 1041 } 1042 } 1043 /* 1044 * See if the old number was large, the new number is small. 1045 */ 1046 if (ino > XFS_DIR2_MAX_SHORT_INUM && 1047 args->inumber <= XFS_DIR2_MAX_SHORT_INUM) { 1048 /* 1049 * And the old count was one, so need to convert to small. 1050 */ 1051 if (sfp->i8count == 1) 1052 xfs_dir2_sf_toino4(args); 1053 else 1054 sfp->i8count--; 1055 } 1056 /* 1057 * See if the old number was small, the new number is large. 1058 */ 1059 if (ino <= XFS_DIR2_MAX_SHORT_INUM && 1060 args->inumber > XFS_DIR2_MAX_SHORT_INUM) { 1061 /* 1062 * add to the i8count unless we just converted to 8-byte 1063 * inodes (which does an implied i8count = 1) 1064 */ 1065 ASSERT(sfp->i8count != 0); 1066 if (!i8elevated) 1067 sfp->i8count++; 1068 } 1069 xfs_dir2_sf_check(args); 1070 xfs_trans_log_inode(args->trans, dp, XFS_ILOG_DDATA); 1071 return 0; 1072 } 1073 1074 /* 1075 * Convert from 8-byte inode numbers to 4-byte inode numbers. 1076 * The last 8-byte inode number is gone, but the count is still 1. 1077 */ 1078 static void 1079 xfs_dir2_sf_toino4( 1080 xfs_da_args_t *args) /* operation arguments */ 1081 { 1082 char *buf; /* old dir's buffer */ 1083 xfs_inode_t *dp; /* incore directory inode */ 1084 int i; /* entry index */ 1085 int newsize; /* new inode size */ 1086 xfs_dir2_sf_entry_t *oldsfep; /* old sf entry */ 1087 xfs_dir2_sf_hdr_t *oldsfp; /* old sf directory */ 1088 int oldsize; /* old inode size */ 1089 xfs_dir2_sf_entry_t *sfep; /* new sf entry */ 1090 xfs_dir2_sf_hdr_t *sfp; /* new sf directory */ 1091 1092 trace_xfs_dir2_sf_toino4(args); 1093 1094 dp = args->dp; 1095 1096 /* 1097 * Copy the old directory to the buffer. 1098 * Then nuke it from the inode, and add the new buffer to the inode. 1099 * Don't want xfs_idata_realloc copying the data here. 1100 */ 1101 oldsize = dp->i_df.if_bytes; 1102 buf = kmem_alloc(oldsize, KM_SLEEP); 1103 oldsfp = (xfs_dir2_sf_hdr_t *)dp->i_df.if_u1.if_data; 1104 ASSERT(oldsfp->i8count == 1); 1105 memcpy(buf, oldsfp, oldsize); 1106 /* 1107 * Compute the new inode size. 1108 */ 1109 newsize = oldsize - (oldsfp->count + 1) * XFS_INO64_DIFF; 1110 xfs_idata_realloc(dp, -oldsize, XFS_DATA_FORK); 1111 xfs_idata_realloc(dp, newsize, XFS_DATA_FORK); 1112 /* 1113 * Reset our pointers, the data has moved. 1114 */ 1115 oldsfp = (xfs_dir2_sf_hdr_t *)buf; 1116 sfp = (xfs_dir2_sf_hdr_t *)dp->i_df.if_u1.if_data; 1117 /* 1118 * Fill in the new header. 1119 */ 1120 sfp->count = oldsfp->count; 1121 sfp->i8count = 0; 1122 dp->d_ops->sf_put_parent_ino(sfp, dp->d_ops->sf_get_parent_ino(oldsfp)); 1123 /* 1124 * Copy the entries field by field. 1125 */ 1126 for (i = 0, sfep = xfs_dir2_sf_firstentry(sfp), 1127 oldsfep = xfs_dir2_sf_firstentry(oldsfp); 1128 i < sfp->count; 1129 i++, sfep = dp->d_ops->sf_nextentry(sfp, sfep), 1130 oldsfep = dp->d_ops->sf_nextentry(oldsfp, oldsfep)) { 1131 sfep->namelen = oldsfep->namelen; 1132 memcpy(sfep->offset, oldsfep->offset, sizeof(sfep->offset)); 1133 memcpy(sfep->name, oldsfep->name, sfep->namelen); 1134 dp->d_ops->sf_put_ino(sfp, sfep, 1135 dp->d_ops->sf_get_ino(oldsfp, oldsfep)); 1136 dp->d_ops->sf_put_ftype(sfep, dp->d_ops->sf_get_ftype(oldsfep)); 1137 } 1138 /* 1139 * Clean up the inode. 1140 */ 1141 kmem_free(buf); 1142 dp->i_d.di_size = newsize; 1143 xfs_trans_log_inode(args->trans, dp, XFS_ILOG_CORE | XFS_ILOG_DDATA); 1144 } 1145 1146 /* 1147 * Convert existing entries from 4-byte inode numbers to 8-byte inode numbers. 1148 * The new entry w/ an 8-byte inode number is not there yet; we leave with 1149 * i8count set to 1, but no corresponding 8-byte entry. 1150 */ 1151 static void 1152 xfs_dir2_sf_toino8( 1153 xfs_da_args_t *args) /* operation arguments */ 1154 { 1155 char *buf; /* old dir's buffer */ 1156 xfs_inode_t *dp; /* incore directory inode */ 1157 int i; /* entry index */ 1158 int newsize; /* new inode size */ 1159 xfs_dir2_sf_entry_t *oldsfep; /* old sf entry */ 1160 xfs_dir2_sf_hdr_t *oldsfp; /* old sf directory */ 1161 int oldsize; /* old inode size */ 1162 xfs_dir2_sf_entry_t *sfep; /* new sf entry */ 1163 xfs_dir2_sf_hdr_t *sfp; /* new sf directory */ 1164 1165 trace_xfs_dir2_sf_toino8(args); 1166 1167 dp = args->dp; 1168 1169 /* 1170 * Copy the old directory to the buffer. 1171 * Then nuke it from the inode, and add the new buffer to the inode. 1172 * Don't want xfs_idata_realloc copying the data here. 1173 */ 1174 oldsize = dp->i_df.if_bytes; 1175 buf = kmem_alloc(oldsize, KM_SLEEP); 1176 oldsfp = (xfs_dir2_sf_hdr_t *)dp->i_df.if_u1.if_data; 1177 ASSERT(oldsfp->i8count == 0); 1178 memcpy(buf, oldsfp, oldsize); 1179 /* 1180 * Compute the new inode size (nb: entry count + 1 for parent) 1181 */ 1182 newsize = oldsize + (oldsfp->count + 1) * XFS_INO64_DIFF; 1183 xfs_idata_realloc(dp, -oldsize, XFS_DATA_FORK); 1184 xfs_idata_realloc(dp, newsize, XFS_DATA_FORK); 1185 /* 1186 * Reset our pointers, the data has moved. 1187 */ 1188 oldsfp = (xfs_dir2_sf_hdr_t *)buf; 1189 sfp = (xfs_dir2_sf_hdr_t *)dp->i_df.if_u1.if_data; 1190 /* 1191 * Fill in the new header. 1192 */ 1193 sfp->count = oldsfp->count; 1194 sfp->i8count = 1; 1195 dp->d_ops->sf_put_parent_ino(sfp, dp->d_ops->sf_get_parent_ino(oldsfp)); 1196 /* 1197 * Copy the entries field by field. 1198 */ 1199 for (i = 0, sfep = xfs_dir2_sf_firstentry(sfp), 1200 oldsfep = xfs_dir2_sf_firstentry(oldsfp); 1201 i < sfp->count; 1202 i++, sfep = dp->d_ops->sf_nextentry(sfp, sfep), 1203 oldsfep = dp->d_ops->sf_nextentry(oldsfp, oldsfep)) { 1204 sfep->namelen = oldsfep->namelen; 1205 memcpy(sfep->offset, oldsfep->offset, sizeof(sfep->offset)); 1206 memcpy(sfep->name, oldsfep->name, sfep->namelen); 1207 dp->d_ops->sf_put_ino(sfp, sfep, 1208 dp->d_ops->sf_get_ino(oldsfp, oldsfep)); 1209 dp->d_ops->sf_put_ftype(sfep, dp->d_ops->sf_get_ftype(oldsfep)); 1210 } 1211 /* 1212 * Clean up the inode. 1213 */ 1214 kmem_free(buf); 1215 dp->i_d.di_size = newsize; 1216 xfs_trans_log_inode(args->trans, dp, XFS_ILOG_CORE | XFS_ILOG_DDATA); 1217 } 1218