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