Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

at v3.15-rc5 726 lines 17 kB view raw
1/* 2 * Copyright (c) 2000-2001,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_inum.h" 24#include "xfs_sb.h" 25#include "xfs_ag.h" 26#include "xfs_mount.h" 27#include "xfs_da_format.h" 28#include "xfs_da_btree.h" 29#include "xfs_inode.h" 30#include "xfs_trans.h" 31#include "xfs_inode_item.h" 32#include "xfs_bmap.h" 33#include "xfs_dir2.h" 34#include "xfs_dir2_priv.h" 35#include "xfs_error.h" 36#include "xfs_trace.h" 37#include "xfs_dinode.h" 38 39struct xfs_name xfs_name_dotdot = { (unsigned char *)"..", 2, XFS_DIR3_FT_DIR }; 40 41 42/* 43 * ASCII case-insensitive (ie. A-Z) support for directories that was 44 * used in IRIX. 45 */ 46STATIC xfs_dahash_t 47xfs_ascii_ci_hashname( 48 struct xfs_name *name) 49{ 50 xfs_dahash_t hash; 51 int i; 52 53 for (i = 0, hash = 0; i < name->len; i++) 54 hash = tolower(name->name[i]) ^ rol32(hash, 7); 55 56 return hash; 57} 58 59STATIC enum xfs_dacmp 60xfs_ascii_ci_compname( 61 struct xfs_da_args *args, 62 const unsigned char *name, 63 int len) 64{ 65 enum xfs_dacmp result; 66 int i; 67 68 if (args->namelen != len) 69 return XFS_CMP_DIFFERENT; 70 71 result = XFS_CMP_EXACT; 72 for (i = 0; i < len; i++) { 73 if (args->name[i] == name[i]) 74 continue; 75 if (tolower(args->name[i]) != tolower(name[i])) 76 return XFS_CMP_DIFFERENT; 77 result = XFS_CMP_CASE; 78 } 79 80 return result; 81} 82 83static struct xfs_nameops xfs_ascii_ci_nameops = { 84 .hashname = xfs_ascii_ci_hashname, 85 .compname = xfs_ascii_ci_compname, 86}; 87 88void 89xfs_dir_mount( 90 xfs_mount_t *mp) 91{ 92 int nodehdr_size; 93 94 95 ASSERT(xfs_sb_version_hasdirv2(&mp->m_sb)); 96 ASSERT((1 << (mp->m_sb.sb_blocklog + mp->m_sb.sb_dirblklog)) <= 97 XFS_MAX_BLOCKSIZE); 98 99 mp->m_dir_inode_ops = xfs_dir_get_ops(mp, NULL); 100 mp->m_nondir_inode_ops = xfs_nondir_get_ops(mp, NULL); 101 102 mp->m_dirblksize = 1 << (mp->m_sb.sb_blocklog + mp->m_sb.sb_dirblklog); 103 mp->m_dirblkfsbs = 1 << mp->m_sb.sb_dirblklog; 104 mp->m_dirdatablk = xfs_dir2_db_to_da(mp, XFS_DIR2_DATA_FIRSTDB(mp)); 105 mp->m_dirleafblk = xfs_dir2_db_to_da(mp, XFS_DIR2_LEAF_FIRSTDB(mp)); 106 mp->m_dirfreeblk = xfs_dir2_db_to_da(mp, XFS_DIR2_FREE_FIRSTDB(mp)); 107 108 nodehdr_size = mp->m_dir_inode_ops->node_hdr_size; 109 mp->m_attr_node_ents = (mp->m_sb.sb_blocksize - nodehdr_size) / 110 (uint)sizeof(xfs_da_node_entry_t); 111 mp->m_dir_node_ents = (mp->m_dirblksize - nodehdr_size) / 112 (uint)sizeof(xfs_da_node_entry_t); 113 114 mp->m_dir_magicpct = (mp->m_dirblksize * 37) / 100; 115 if (xfs_sb_version_hasasciici(&mp->m_sb)) 116 mp->m_dirnameops = &xfs_ascii_ci_nameops; 117 else 118 mp->m_dirnameops = &xfs_default_nameops; 119 120} 121 122/* 123 * Return 1 if directory contains only "." and "..". 124 */ 125int 126xfs_dir_isempty( 127 xfs_inode_t *dp) 128{ 129 xfs_dir2_sf_hdr_t *sfp; 130 131 ASSERT(S_ISDIR(dp->i_d.di_mode)); 132 if (dp->i_d.di_size == 0) /* might happen during shutdown. */ 133 return 1; 134 if (dp->i_d.di_size > XFS_IFORK_DSIZE(dp)) 135 return 0; 136 sfp = (xfs_dir2_sf_hdr_t *)dp->i_df.if_u1.if_data; 137 return !sfp->count; 138} 139 140/* 141 * Validate a given inode number. 142 */ 143int 144xfs_dir_ino_validate( 145 xfs_mount_t *mp, 146 xfs_ino_t ino) 147{ 148 xfs_agblock_t agblkno; 149 xfs_agino_t agino; 150 xfs_agnumber_t agno; 151 int ino_ok; 152 int ioff; 153 154 agno = XFS_INO_TO_AGNO(mp, ino); 155 agblkno = XFS_INO_TO_AGBNO(mp, ino); 156 ioff = XFS_INO_TO_OFFSET(mp, ino); 157 agino = XFS_OFFBNO_TO_AGINO(mp, agblkno, ioff); 158 ino_ok = 159 agno < mp->m_sb.sb_agcount && 160 agblkno < mp->m_sb.sb_agblocks && 161 agblkno != 0 && 162 ioff < (1 << mp->m_sb.sb_inopblog) && 163 XFS_AGINO_TO_INO(mp, agno, agino) == ino; 164 if (unlikely(XFS_TEST_ERROR(!ino_ok, mp, XFS_ERRTAG_DIR_INO_VALIDATE, 165 XFS_RANDOM_DIR_INO_VALIDATE))) { 166 xfs_warn(mp, "Invalid inode number 0x%Lx", 167 (unsigned long long) ino); 168 XFS_ERROR_REPORT("xfs_dir_ino_validate", XFS_ERRLEVEL_LOW, mp); 169 return XFS_ERROR(EFSCORRUPTED); 170 } 171 return 0; 172} 173 174/* 175 * Initialize a directory with its "." and ".." entries. 176 */ 177int 178xfs_dir_init( 179 xfs_trans_t *tp, 180 xfs_inode_t *dp, 181 xfs_inode_t *pdp) 182{ 183 struct xfs_da_args *args; 184 int error; 185 186 ASSERT(S_ISDIR(dp->i_d.di_mode)); 187 error = xfs_dir_ino_validate(tp->t_mountp, pdp->i_ino); 188 if (error) 189 return error; 190 191 args = kmem_zalloc(sizeof(*args), KM_SLEEP | KM_NOFS); 192 if (!args) 193 return ENOMEM; 194 195 args->dp = dp; 196 args->trans = tp; 197 error = xfs_dir2_sf_create(args, pdp->i_ino); 198 kmem_free(args); 199 return error; 200} 201 202/* 203 Enter a name in a directory. 204 */ 205int 206xfs_dir_createname( 207 xfs_trans_t *tp, 208 xfs_inode_t *dp, 209 struct xfs_name *name, 210 xfs_ino_t inum, /* new entry inode number */ 211 xfs_fsblock_t *first, /* bmap's firstblock */ 212 xfs_bmap_free_t *flist, /* bmap's freeblock list */ 213 xfs_extlen_t total) /* bmap's total block count */ 214{ 215 struct xfs_da_args *args; 216 int rval; 217 int v; /* type-checking value */ 218 219 ASSERT(S_ISDIR(dp->i_d.di_mode)); 220 rval = xfs_dir_ino_validate(tp->t_mountp, inum); 221 if (rval) 222 return rval; 223 XFS_STATS_INC(xs_dir_create); 224 225 args = kmem_zalloc(sizeof(*args), KM_SLEEP | KM_NOFS); 226 if (!args) 227 return ENOMEM; 228 229 args->name = name->name; 230 args->namelen = name->len; 231 args->filetype = name->type; 232 args->hashval = dp->i_mount->m_dirnameops->hashname(name); 233 args->inumber = inum; 234 args->dp = dp; 235 args->firstblock = first; 236 args->flist = flist; 237 args->total = total; 238 args->whichfork = XFS_DATA_FORK; 239 args->trans = tp; 240 args->op_flags = XFS_DA_OP_ADDNAME | XFS_DA_OP_OKNOENT; 241 242 if (dp->i_d.di_format == XFS_DINODE_FMT_LOCAL) { 243 rval = xfs_dir2_sf_addname(args); 244 goto out_free; 245 } 246 247 rval = xfs_dir2_isblock(tp, dp, &v); 248 if (rval) 249 goto out_free; 250 if (v) { 251 rval = xfs_dir2_block_addname(args); 252 goto out_free; 253 } 254 255 rval = xfs_dir2_isleaf(tp, dp, &v); 256 if (rval) 257 goto out_free; 258 if (v) 259 rval = xfs_dir2_leaf_addname(args); 260 else 261 rval = xfs_dir2_node_addname(args); 262 263out_free: 264 kmem_free(args); 265 return rval; 266} 267 268/* 269 * If doing a CI lookup and case-insensitive match, dup actual name into 270 * args.value. Return EEXIST for success (ie. name found) or an error. 271 */ 272int 273xfs_dir_cilookup_result( 274 struct xfs_da_args *args, 275 const unsigned char *name, 276 int len) 277{ 278 if (args->cmpresult == XFS_CMP_DIFFERENT) 279 return ENOENT; 280 if (args->cmpresult != XFS_CMP_CASE || 281 !(args->op_flags & XFS_DA_OP_CILOOKUP)) 282 return EEXIST; 283 284 args->value = kmem_alloc(len, KM_NOFS | KM_MAYFAIL); 285 if (!args->value) 286 return ENOMEM; 287 288 memcpy(args->value, name, len); 289 args->valuelen = len; 290 return EEXIST; 291} 292 293/* 294 * Lookup a name in a directory, give back the inode number. 295 * If ci_name is not NULL, returns the actual name in ci_name if it differs 296 * to name, or ci_name->name is set to NULL for an exact match. 297 */ 298 299int 300xfs_dir_lookup( 301 xfs_trans_t *tp, 302 xfs_inode_t *dp, 303 struct xfs_name *name, 304 xfs_ino_t *inum, /* out: inode number */ 305 struct xfs_name *ci_name) /* out: actual name if CI match */ 306{ 307 struct xfs_da_args *args; 308 int rval; 309 int v; /* type-checking value */ 310 311 ASSERT(S_ISDIR(dp->i_d.di_mode)); 312 XFS_STATS_INC(xs_dir_lookup); 313 314 /* 315 * We need to use KM_NOFS here so that lockdep will not throw false 316 * positive deadlock warnings on a non-transactional lookup path. It is 317 * safe to recurse into inode recalim in that case, but lockdep can't 318 * easily be taught about it. Hence KM_NOFS avoids having to add more 319 * lockdep Doing this avoids having to add a bunch of lockdep class 320 * annotations into the reclaim path for the ilock. 321 */ 322 args = kmem_zalloc(sizeof(*args), KM_SLEEP | KM_NOFS); 323 args->name = name->name; 324 args->namelen = name->len; 325 args->filetype = name->type; 326 args->hashval = dp->i_mount->m_dirnameops->hashname(name); 327 args->dp = dp; 328 args->whichfork = XFS_DATA_FORK; 329 args->trans = tp; 330 args->op_flags = XFS_DA_OP_OKNOENT; 331 if (ci_name) 332 args->op_flags |= XFS_DA_OP_CILOOKUP; 333 334 if (dp->i_d.di_format == XFS_DINODE_FMT_LOCAL) { 335 rval = xfs_dir2_sf_lookup(args); 336 goto out_check_rval; 337 } 338 339 rval = xfs_dir2_isblock(tp, dp, &v); 340 if (rval) 341 goto out_free; 342 if (v) { 343 rval = xfs_dir2_block_lookup(args); 344 goto out_check_rval; 345 } 346 347 rval = xfs_dir2_isleaf(tp, dp, &v); 348 if (rval) 349 goto out_free; 350 if (v) 351 rval = xfs_dir2_leaf_lookup(args); 352 else 353 rval = xfs_dir2_node_lookup(args); 354 355out_check_rval: 356 if (rval == EEXIST) 357 rval = 0; 358 if (!rval) { 359 *inum = args->inumber; 360 if (ci_name) { 361 ci_name->name = args->value; 362 ci_name->len = args->valuelen; 363 } 364 } 365out_free: 366 kmem_free(args); 367 return rval; 368} 369 370/* 371 * Remove an entry from a directory. 372 */ 373int 374xfs_dir_removename( 375 xfs_trans_t *tp, 376 xfs_inode_t *dp, 377 struct xfs_name *name, 378 xfs_ino_t ino, 379 xfs_fsblock_t *first, /* bmap's firstblock */ 380 xfs_bmap_free_t *flist, /* bmap's freeblock list */ 381 xfs_extlen_t total) /* bmap's total block count */ 382{ 383 struct xfs_da_args *args; 384 int rval; 385 int v; /* type-checking value */ 386 387 ASSERT(S_ISDIR(dp->i_d.di_mode)); 388 XFS_STATS_INC(xs_dir_remove); 389 390 args = kmem_zalloc(sizeof(*args), KM_SLEEP | KM_NOFS); 391 if (!args) 392 return ENOMEM; 393 394 args->name = name->name; 395 args->namelen = name->len; 396 args->filetype = name->type; 397 args->hashval = dp->i_mount->m_dirnameops->hashname(name); 398 args->inumber = ino; 399 args->dp = dp; 400 args->firstblock = first; 401 args->flist = flist; 402 args->total = total; 403 args->whichfork = XFS_DATA_FORK; 404 args->trans = tp; 405 406 if (dp->i_d.di_format == XFS_DINODE_FMT_LOCAL) { 407 rval = xfs_dir2_sf_removename(args); 408 goto out_free; 409 } 410 411 rval = xfs_dir2_isblock(tp, dp, &v); 412 if (rval) 413 goto out_free; 414 if (v) { 415 rval = xfs_dir2_block_removename(args); 416 goto out_free; 417 } 418 419 rval = xfs_dir2_isleaf(tp, dp, &v); 420 if (rval) 421 goto out_free; 422 if (v) 423 rval = xfs_dir2_leaf_removename(args); 424 else 425 rval = xfs_dir2_node_removename(args); 426out_free: 427 kmem_free(args); 428 return rval; 429} 430 431/* 432 * Replace the inode number of a directory entry. 433 */ 434int 435xfs_dir_replace( 436 xfs_trans_t *tp, 437 xfs_inode_t *dp, 438 struct xfs_name *name, /* name of entry to replace */ 439 xfs_ino_t inum, /* new inode number */ 440 xfs_fsblock_t *first, /* bmap's firstblock */ 441 xfs_bmap_free_t *flist, /* bmap's freeblock list */ 442 xfs_extlen_t total) /* bmap's total block count */ 443{ 444 struct xfs_da_args *args; 445 int rval; 446 int v; /* type-checking value */ 447 448 ASSERT(S_ISDIR(dp->i_d.di_mode)); 449 450 rval = xfs_dir_ino_validate(tp->t_mountp, inum); 451 if (rval) 452 return rval; 453 454 args = kmem_zalloc(sizeof(*args), KM_SLEEP | KM_NOFS); 455 if (!args) 456 return ENOMEM; 457 458 args->name = name->name; 459 args->namelen = name->len; 460 args->filetype = name->type; 461 args->hashval = dp->i_mount->m_dirnameops->hashname(name); 462 args->inumber = inum; 463 args->dp = dp; 464 args->firstblock = first; 465 args->flist = flist; 466 args->total = total; 467 args->whichfork = XFS_DATA_FORK; 468 args->trans = tp; 469 470 if (dp->i_d.di_format == XFS_DINODE_FMT_LOCAL) { 471 rval = xfs_dir2_sf_replace(args); 472 goto out_free; 473 } 474 475 rval = xfs_dir2_isblock(tp, dp, &v); 476 if (rval) 477 goto out_free; 478 if (v) { 479 rval = xfs_dir2_block_replace(args); 480 goto out_free; 481 } 482 483 rval = xfs_dir2_isleaf(tp, dp, &v); 484 if (rval) 485 goto out_free; 486 if (v) 487 rval = xfs_dir2_leaf_replace(args); 488 else 489 rval = xfs_dir2_node_replace(args); 490out_free: 491 kmem_free(args); 492 return rval; 493} 494 495/* 496 * See if this entry can be added to the directory without allocating space. 497 * First checks that the caller couldn't reserve enough space (resblks = 0). 498 */ 499int 500xfs_dir_canenter( 501 xfs_trans_t *tp, 502 xfs_inode_t *dp, 503 struct xfs_name *name, /* name of entry to add */ 504 uint resblks) 505{ 506 struct xfs_da_args *args; 507 int rval; 508 int v; /* type-checking value */ 509 510 if (resblks) 511 return 0; 512 513 ASSERT(S_ISDIR(dp->i_d.di_mode)); 514 515 args = kmem_zalloc(sizeof(*args), KM_SLEEP | KM_NOFS); 516 if (!args) 517 return ENOMEM; 518 519 args->name = name->name; 520 args->namelen = name->len; 521 args->filetype = name->type; 522 args->hashval = dp->i_mount->m_dirnameops->hashname(name); 523 args->dp = dp; 524 args->whichfork = XFS_DATA_FORK; 525 args->trans = tp; 526 args->op_flags = XFS_DA_OP_JUSTCHECK | XFS_DA_OP_ADDNAME | 527 XFS_DA_OP_OKNOENT; 528 529 if (dp->i_d.di_format == XFS_DINODE_FMT_LOCAL) { 530 rval = xfs_dir2_sf_addname(args); 531 goto out_free; 532 } 533 534 rval = xfs_dir2_isblock(tp, dp, &v); 535 if (rval) 536 goto out_free; 537 if (v) { 538 rval = xfs_dir2_block_addname(args); 539 goto out_free; 540 } 541 542 rval = xfs_dir2_isleaf(tp, dp, &v); 543 if (rval) 544 goto out_free; 545 if (v) 546 rval = xfs_dir2_leaf_addname(args); 547 else 548 rval = xfs_dir2_node_addname(args); 549out_free: 550 kmem_free(args); 551 return rval; 552} 553 554/* 555 * Utility routines. 556 */ 557 558/* 559 * Add a block to the directory. 560 * 561 * This routine is for data and free blocks, not leaf/node blocks which are 562 * handled by xfs_da_grow_inode. 563 */ 564int 565xfs_dir2_grow_inode( 566 struct xfs_da_args *args, 567 int space, /* v2 dir's space XFS_DIR2_xxx_SPACE */ 568 xfs_dir2_db_t *dbp) /* out: block number added */ 569{ 570 struct xfs_inode *dp = args->dp; 571 struct xfs_mount *mp = dp->i_mount; 572 xfs_fileoff_t bno; /* directory offset of new block */ 573 int count; /* count of filesystem blocks */ 574 int error; 575 576 trace_xfs_dir2_grow_inode(args, space); 577 578 /* 579 * Set lowest possible block in the space requested. 580 */ 581 bno = XFS_B_TO_FSBT(mp, space * XFS_DIR2_SPACE_SIZE); 582 count = mp->m_dirblkfsbs; 583 584 error = xfs_da_grow_inode_int(args, &bno, count); 585 if (error) 586 return error; 587 588 *dbp = xfs_dir2_da_to_db(mp, (xfs_dablk_t)bno); 589 590 /* 591 * Update file's size if this is the data space and it grew. 592 */ 593 if (space == XFS_DIR2_DATA_SPACE) { 594 xfs_fsize_t size; /* directory file (data) size */ 595 596 size = XFS_FSB_TO_B(mp, bno + count); 597 if (size > dp->i_d.di_size) { 598 dp->i_d.di_size = size; 599 xfs_trans_log_inode(args->trans, dp, XFS_ILOG_CORE); 600 } 601 } 602 return 0; 603} 604 605/* 606 * See if the directory is a single-block form directory. 607 */ 608int 609xfs_dir2_isblock( 610 xfs_trans_t *tp, 611 xfs_inode_t *dp, 612 int *vp) /* out: 1 is block, 0 is not block */ 613{ 614 xfs_fileoff_t last; /* last file offset */ 615 xfs_mount_t *mp; 616 int rval; 617 618 mp = dp->i_mount; 619 if ((rval = xfs_bmap_last_offset(tp, dp, &last, XFS_DATA_FORK))) 620 return rval; 621 rval = XFS_FSB_TO_B(mp, last) == mp->m_dirblksize; 622 ASSERT(rval == 0 || dp->i_d.di_size == mp->m_dirblksize); 623 *vp = rval; 624 return 0; 625} 626 627/* 628 * See if the directory is a single-leaf form directory. 629 */ 630int 631xfs_dir2_isleaf( 632 xfs_trans_t *tp, 633 xfs_inode_t *dp, 634 int *vp) /* out: 1 is leaf, 0 is not leaf */ 635{ 636 xfs_fileoff_t last; /* last file offset */ 637 xfs_mount_t *mp; 638 int rval; 639 640 mp = dp->i_mount; 641 if ((rval = xfs_bmap_last_offset(tp, dp, &last, XFS_DATA_FORK))) 642 return rval; 643 *vp = last == mp->m_dirleafblk + (1 << mp->m_sb.sb_dirblklog); 644 return 0; 645} 646 647/* 648 * Remove the given block from the directory. 649 * This routine is used for data and free blocks, leaf/node are done 650 * by xfs_da_shrink_inode. 651 */ 652int 653xfs_dir2_shrink_inode( 654 xfs_da_args_t *args, 655 xfs_dir2_db_t db, 656 struct xfs_buf *bp) 657{ 658 xfs_fileoff_t bno; /* directory file offset */ 659 xfs_dablk_t da; /* directory file offset */ 660 int done; /* bunmap is finished */ 661 xfs_inode_t *dp; 662 int error; 663 xfs_mount_t *mp; 664 xfs_trans_t *tp; 665 666 trace_xfs_dir2_shrink_inode(args, db); 667 668 dp = args->dp; 669 mp = dp->i_mount; 670 tp = args->trans; 671 da = xfs_dir2_db_to_da(mp, db); 672 /* 673 * Unmap the fsblock(s). 674 */ 675 if ((error = xfs_bunmapi(tp, dp, da, mp->m_dirblkfsbs, 676 XFS_BMAPI_METADATA, 0, args->firstblock, args->flist, 677 &done))) { 678 /* 679 * ENOSPC actually can happen if we're in a removename with 680 * no space reservation, and the resulting block removal 681 * would cause a bmap btree split or conversion from extents 682 * to btree. This can only happen for un-fragmented 683 * directory blocks, since you need to be punching out 684 * the middle of an extent. 685 * In this case we need to leave the block in the file, 686 * and not binval it. 687 * So the block has to be in a consistent empty state 688 * and appropriately logged. 689 * We don't free up the buffer, the caller can tell it 690 * hasn't happened since it got an error back. 691 */ 692 return error; 693 } 694 ASSERT(done); 695 /* 696 * Invalidate the buffer from the transaction. 697 */ 698 xfs_trans_binval(tp, bp); 699 /* 700 * If it's not a data block, we're done. 701 */ 702 if (db >= XFS_DIR2_LEAF_FIRSTDB(mp)) 703 return 0; 704 /* 705 * If the block isn't the last one in the directory, we're done. 706 */ 707 if (dp->i_d.di_size > xfs_dir2_db_off_to_byte(mp, db + 1, 0)) 708 return 0; 709 bno = da; 710 if ((error = xfs_bmap_last_before(tp, dp, &bno, XFS_DATA_FORK))) { 711 /* 712 * This can't really happen unless there's kernel corruption. 713 */ 714 return error; 715 } 716 if (db == mp->m_dirdatablk) 717 ASSERT(bno == 0); 718 else 719 ASSERT(bno > 0); 720 /* 721 * Set the size to the new last block. 722 */ 723 dp->i_d.di_size = XFS_FSB_TO_B(mp, bno); 724 xfs_trans_log_inode(tp, dp, XFS_ILOG_CORE); 725 return 0; 726}