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