linux/fs/xfs/xfs_dir2_readdir.c
<<
>>
Prefs
   1/*
   2 * Copyright (c) 2000-2005 Silicon Graphics, Inc.
   3 * Copyright (c) 2013 Red Hat, Inc.
   4 * All Rights Reserved.
   5 *
   6 * This program is free software; you can redistribute it and/or
   7 * modify it under the terms of the GNU General Public License as
   8 * published by the Free Software Foundation.
   9 *
  10 * This program is distributed in the hope that it would be useful,
  11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
  12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  13 * GNU General Public License for more details.
  14 *
  15 * You should have received a copy of the GNU General Public License
  16 * along with this program; if not, write the Free Software Foundation,
  17 * Inc.,  51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
  18 */
  19#include "xfs.h"
  20#include "xfs_fs.h"
  21#include "xfs_format.h"
  22#include "xfs_log_format.h"
  23#include "xfs_trans_resv.h"
  24#include "xfs_bit.h"
  25#include "xfs_sb.h"
  26#include "xfs_ag.h"
  27#include "xfs_mount.h"
  28#include "xfs_da_format.h"
  29#include "xfs_da_btree.h"
  30#include "xfs_inode.h"
  31#include "xfs_dir2.h"
  32#include "xfs_dir2_priv.h"
  33#include "xfs_error.h"
  34#include "xfs_trace.h"
  35#include "xfs_bmap.h"
  36#include "xfs_trans.h"
  37#include "xfs_dinode.h"
  38
  39/*
  40 * Directory file type support functions
  41 */
  42static unsigned char xfs_dir3_filetype_table[] = {
  43        DT_UNKNOWN, DT_REG, DT_DIR, DT_CHR, DT_BLK,
  44        DT_FIFO, DT_SOCK, DT_LNK, DT_WHT,
  45};
  46
  47unsigned char
  48xfs_dir3_get_dtype(
  49        struct xfs_mount        *mp,
  50        __uint8_t               filetype)
  51{
  52        if (!xfs_sb_version_hasftype(&mp->m_sb))
  53                return DT_UNKNOWN;
  54
  55        if (filetype >= XFS_DIR3_FT_MAX)
  56                return DT_UNKNOWN;
  57
  58        return xfs_dir3_filetype_table[filetype];
  59}
  60/*
  61 * @mode, if set, indicates that the type field needs to be set up.
  62 * This uses the transformation from file mode to DT_* as defined in linux/fs.h
  63 * for file type specification. This will be propagated into the directory
  64 * structure if appropriate for the given operation and filesystem config.
  65 */
  66const unsigned char xfs_mode_to_ftype[S_IFMT >> S_SHIFT] = {
  67        [0]                     = XFS_DIR3_FT_UNKNOWN,
  68        [S_IFREG >> S_SHIFT]    = XFS_DIR3_FT_REG_FILE,
  69        [S_IFDIR >> S_SHIFT]    = XFS_DIR3_FT_DIR,
  70        [S_IFCHR >> S_SHIFT]    = XFS_DIR3_FT_CHRDEV,
  71        [S_IFBLK >> S_SHIFT]    = XFS_DIR3_FT_BLKDEV,
  72        [S_IFIFO >> S_SHIFT]    = XFS_DIR3_FT_FIFO,
  73        [S_IFSOCK >> S_SHIFT]   = XFS_DIR3_FT_SOCK,
  74        [S_IFLNK >> S_SHIFT]    = XFS_DIR3_FT_SYMLINK,
  75};
  76
  77STATIC int
  78xfs_dir2_sf_getdents(
  79        xfs_inode_t             *dp,            /* incore directory inode */
  80        struct dir_context      *ctx)
  81{
  82        int                     i;              /* shortform entry number */
  83        xfs_mount_t             *mp;            /* filesystem mount point */
  84        xfs_dir2_dataptr_t      off;            /* current entry's offset */
  85        xfs_dir2_sf_entry_t     *sfep;          /* shortform directory entry */
  86        xfs_dir2_sf_hdr_t       *sfp;           /* shortform structure */
  87        xfs_dir2_dataptr_t      dot_offset;
  88        xfs_dir2_dataptr_t      dotdot_offset;
  89        xfs_ino_t               ino;
  90
  91        mp = dp->i_mount;
  92
  93        ASSERT(dp->i_df.if_flags & XFS_IFINLINE);
  94        /*
  95         * Give up if the directory is way too short.
  96         */
  97        if (dp->i_d.di_size < offsetof(xfs_dir2_sf_hdr_t, parent)) {
  98                ASSERT(XFS_FORCED_SHUTDOWN(mp));
  99                return XFS_ERROR(EIO);
 100        }
 101
 102        ASSERT(dp->i_df.if_bytes == dp->i_d.di_size);
 103        ASSERT(dp->i_df.if_u1.if_data != NULL);
 104
 105        sfp = (xfs_dir2_sf_hdr_t *)dp->i_df.if_u1.if_data;
 106
 107        ASSERT(dp->i_d.di_size >= xfs_dir2_sf_hdr_size(sfp->i8count));
 108
 109        /*
 110         * If the block number in the offset is out of range, we're done.
 111         */
 112        if (xfs_dir2_dataptr_to_db(mp, ctx->pos) > mp->m_dirdatablk)
 113                return 0;
 114
 115        /*
 116         * Precalculate offsets for . and .. as we will always need them.
 117         *
 118         * XXX(hch): the second argument is sometimes 0 and sometimes
 119         * mp->m_dirdatablk.
 120         */
 121        dot_offset = xfs_dir2_db_off_to_dataptr(mp, mp->m_dirdatablk,
 122                                                dp->d_ops->data_dot_offset);
 123        dotdot_offset = xfs_dir2_db_off_to_dataptr(mp, mp->m_dirdatablk,
 124                                                dp->d_ops->data_dotdot_offset);
 125
 126        /*
 127         * Put . entry unless we're starting past it.
 128         */
 129        if (ctx->pos <= dot_offset) {
 130                ctx->pos = dot_offset & 0x7fffffff;
 131                if (!dir_emit(ctx, ".", 1, dp->i_ino, DT_DIR))
 132                        return 0;
 133        }
 134
 135        /*
 136         * Put .. entry unless we're starting past it.
 137         */
 138        if (ctx->pos <= dotdot_offset) {
 139                ino = dp->d_ops->sf_get_parent_ino(sfp);
 140                ctx->pos = dotdot_offset & 0x7fffffff;
 141                if (!dir_emit(ctx, "..", 2, ino, DT_DIR))
 142                        return 0;
 143        }
 144
 145        /*
 146         * Loop while there are more entries and put'ing works.
 147         */
 148        sfep = xfs_dir2_sf_firstentry(sfp);
 149        for (i = 0; i < sfp->count; i++) {
 150                __uint8_t filetype;
 151
 152                off = xfs_dir2_db_off_to_dataptr(mp, mp->m_dirdatablk,
 153                                xfs_dir2_sf_get_offset(sfep));
 154
 155                if (ctx->pos > off) {
 156                        sfep = dp->d_ops->sf_nextentry(sfp, sfep);
 157                        continue;
 158                }
 159
 160                ino = dp->d_ops->sf_get_ino(sfp, sfep);
 161                filetype = dp->d_ops->sf_get_ftype(sfep);
 162                ctx->pos = off & 0x7fffffff;
 163                if (!dir_emit(ctx, (char *)sfep->name, sfep->namelen, ino,
 164                            xfs_dir3_get_dtype(mp, filetype)))
 165                        return 0;
 166                sfep = dp->d_ops->sf_nextentry(sfp, sfep);
 167        }
 168
 169        ctx->pos = xfs_dir2_db_off_to_dataptr(mp, mp->m_dirdatablk + 1, 0) &
 170                        0x7fffffff;
 171        return 0;
 172}
 173
 174/*
 175 * Readdir for block directories.
 176 */
 177STATIC int
 178xfs_dir2_block_getdents(
 179        xfs_inode_t             *dp,            /* incore inode */
 180        struct dir_context      *ctx)
 181{
 182        xfs_dir2_data_hdr_t     *hdr;           /* block header */
 183        struct xfs_buf          *bp;            /* buffer for block */
 184        xfs_dir2_block_tail_t   *btp;           /* block tail */
 185        xfs_dir2_data_entry_t   *dep;           /* block data entry */
 186        xfs_dir2_data_unused_t  *dup;           /* block unused entry */
 187        char                    *endptr;        /* end of the data entries */
 188        int                     error;          /* error return value */
 189        xfs_mount_t             *mp;            /* filesystem mount point */
 190        char                    *ptr;           /* current data entry */
 191        int                     wantoff;        /* starting block offset */
 192        xfs_off_t               cook;
 193
 194        mp = dp->i_mount;
 195        /*
 196         * If the block number in the offset is out of range, we're done.
 197         */
 198        if (xfs_dir2_dataptr_to_db(mp, ctx->pos) > mp->m_dirdatablk)
 199                return 0;
 200
 201        error = xfs_dir3_block_read(NULL, dp, &bp);
 202        if (error)
 203                return error;
 204
 205        /*
 206         * Extract the byte offset we start at from the seek pointer.
 207         * We'll skip entries before this.
 208         */
 209        wantoff = xfs_dir2_dataptr_to_off(mp, ctx->pos);
 210        hdr = bp->b_addr;
 211        xfs_dir3_data_check(dp, bp);
 212        /*
 213         * Set up values for the loop.
 214         */
 215        btp = xfs_dir2_block_tail_p(mp, hdr);
 216        ptr = (char *)dp->d_ops->data_entry_p(hdr);
 217        endptr = (char *)xfs_dir2_block_leaf_p(btp);
 218
 219        /*
 220         * Loop over the data portion of the block.
 221         * Each object is a real entry (dep) or an unused one (dup).
 222         */
 223        while (ptr < endptr) {
 224                __uint8_t filetype;
 225
 226                dup = (xfs_dir2_data_unused_t *)ptr;
 227                /*
 228                 * Unused, skip it.
 229                 */
 230                if (be16_to_cpu(dup->freetag) == XFS_DIR2_DATA_FREE_TAG) {
 231                        ptr += be16_to_cpu(dup->length);
 232                        continue;
 233                }
 234
 235                dep = (xfs_dir2_data_entry_t *)ptr;
 236
 237                /*
 238                 * Bump pointer for the next iteration.
 239                 */
 240                ptr += dp->d_ops->data_entsize(dep->namelen);
 241                /*
 242                 * The entry is before the desired starting point, skip it.
 243                 */
 244                if ((char *)dep - (char *)hdr < wantoff)
 245                        continue;
 246
 247                cook = xfs_dir2_db_off_to_dataptr(mp, mp->m_dirdatablk,
 248                                            (char *)dep - (char *)hdr);
 249
 250                ctx->pos = cook & 0x7fffffff;
 251                filetype = dp->d_ops->data_get_ftype(dep);
 252                /*
 253                 * If it didn't fit, set the final offset to here & return.
 254                 */
 255                if (!dir_emit(ctx, (char *)dep->name, dep->namelen,
 256                            be64_to_cpu(dep->inumber),
 257                            xfs_dir3_get_dtype(mp, filetype))) {
 258                        xfs_trans_brelse(NULL, bp);
 259                        return 0;
 260                }
 261        }
 262
 263        /*
 264         * Reached the end of the block.
 265         * Set the offset to a non-existent block 1 and return.
 266         */
 267        ctx->pos = xfs_dir2_db_off_to_dataptr(mp, mp->m_dirdatablk + 1, 0) &
 268                        0x7fffffff;
 269        xfs_trans_brelse(NULL, bp);
 270        return 0;
 271}
 272
 273struct xfs_dir2_leaf_map_info {
 274        xfs_extlen_t    map_blocks;     /* number of fsbs in map */
 275        xfs_dablk_t     map_off;        /* last mapped file offset */
 276        int             map_size;       /* total entries in *map */
 277        int             map_valid;      /* valid entries in *map */
 278        int             nmap;           /* mappings to ask xfs_bmapi */
 279        xfs_dir2_db_t   curdb;          /* db for current block */
 280        int             ra_current;     /* number of read-ahead blks */
 281        int             ra_index;       /* *map index for read-ahead */
 282        int             ra_offset;      /* map entry offset for ra */
 283        int             ra_want;        /* readahead count wanted */
 284        struct xfs_bmbt_irec map[];     /* map vector for blocks */
 285};
 286
 287STATIC int
 288xfs_dir2_leaf_readbuf(
 289        struct xfs_inode        *dp,
 290        size_t                  bufsize,
 291        struct xfs_dir2_leaf_map_info *mip,
 292        xfs_dir2_off_t          *curoff,
 293        struct xfs_buf          **bpp)
 294{
 295        struct xfs_mount        *mp = dp->i_mount;
 296        struct xfs_buf          *bp = *bpp;
 297        struct xfs_bmbt_irec    *map = mip->map;
 298        struct blk_plug         plug;
 299        int                     error = 0;
 300        int                     length;
 301        int                     i;
 302        int                     j;
 303
 304        /*
 305         * If we have a buffer, we need to release it and
 306         * take it out of the mapping.
 307         */
 308
 309        if (bp) {
 310                xfs_trans_brelse(NULL, bp);
 311                bp = NULL;
 312                mip->map_blocks -= mp->m_dirblkfsbs;
 313                /*
 314                 * Loop to get rid of the extents for the
 315                 * directory block.
 316                 */
 317                for (i = mp->m_dirblkfsbs; i > 0; ) {
 318                        j = min_t(int, map->br_blockcount, i);
 319                        map->br_blockcount -= j;
 320                        map->br_startblock += j;
 321                        map->br_startoff += j;
 322                        /*
 323                         * If mapping is done, pitch it from
 324                         * the table.
 325                         */
 326                        if (!map->br_blockcount && --mip->map_valid)
 327                                memmove(&map[0], &map[1],
 328                                        sizeof(map[0]) * mip->map_valid);
 329                        i -= j;
 330                }
 331        }
 332
 333        /*
 334         * Recalculate the readahead blocks wanted.
 335         */
 336        mip->ra_want = howmany(bufsize + mp->m_dirblksize,
 337                               mp->m_sb.sb_blocksize) - 1;
 338        ASSERT(mip->ra_want >= 0);
 339
 340        /*
 341         * If we don't have as many as we want, and we haven't
 342         * run out of data blocks, get some more mappings.
 343         */
 344        if (1 + mip->ra_want > mip->map_blocks &&
 345            mip->map_off < xfs_dir2_byte_to_da(mp, XFS_DIR2_LEAF_OFFSET)) {
 346                /*
 347                 * Get more bmaps, fill in after the ones
 348                 * we already have in the table.
 349                 */
 350                mip->nmap = mip->map_size - mip->map_valid;
 351                error = xfs_bmapi_read(dp, mip->map_off,
 352                                xfs_dir2_byte_to_da(mp, XFS_DIR2_LEAF_OFFSET) -
 353                                                                mip->map_off,
 354                                &map[mip->map_valid], &mip->nmap, 0);
 355
 356                /*
 357                 * Don't know if we should ignore this or try to return an
 358                 * error.  The trouble with returning errors is that readdir
 359                 * will just stop without actually passing the error through.
 360                 */
 361                if (error)
 362                        goto out;       /* XXX */
 363
 364                /*
 365                 * If we got all the mappings we asked for, set the final map
 366                 * offset based on the last bmap value received.  Otherwise,
 367                 * we've reached the end.
 368                 */
 369                if (mip->nmap == mip->map_size - mip->map_valid) {
 370                        i = mip->map_valid + mip->nmap - 1;
 371                        mip->map_off = map[i].br_startoff + map[i].br_blockcount;
 372                } else
 373                        mip->map_off = xfs_dir2_byte_to_da(mp,
 374                                                        XFS_DIR2_LEAF_OFFSET);
 375
 376                /*
 377                 * Look for holes in the mapping, and eliminate them.  Count up
 378                 * the valid blocks.
 379                 */
 380                for (i = mip->map_valid; i < mip->map_valid + mip->nmap; ) {
 381                        if (map[i].br_startblock == HOLESTARTBLOCK) {
 382                                mip->nmap--;
 383                                length = mip->map_valid + mip->nmap - i;
 384                                if (length)
 385                                        memmove(&map[i], &map[i + 1],
 386                                                sizeof(map[i]) * length);
 387                        } else {
 388                                mip->map_blocks += map[i].br_blockcount;
 389                                i++;
 390                        }
 391                }
 392                mip->map_valid += mip->nmap;
 393        }
 394
 395        /*
 396         * No valid mappings, so no more data blocks.
 397         */
 398        if (!mip->map_valid) {
 399                *curoff = xfs_dir2_da_to_byte(mp, mip->map_off);
 400                goto out;
 401        }
 402
 403        /*
 404         * Read the directory block starting at the first mapping.
 405         */
 406        mip->curdb = xfs_dir2_da_to_db(mp, map->br_startoff);
 407        error = xfs_dir3_data_read(NULL, dp, map->br_startoff,
 408                        map->br_blockcount >= mp->m_dirblkfsbs ?
 409                            XFS_FSB_TO_DADDR(mp, map->br_startblock) : -1, &bp);
 410
 411        /*
 412         * Should just skip over the data block instead of giving up.
 413         */
 414        if (error)
 415                goto out;       /* XXX */
 416
 417        /*
 418         * Adjust the current amount of read-ahead: we just read a block that
 419         * was previously ra.
 420         */
 421        if (mip->ra_current)
 422                mip->ra_current -= mp->m_dirblkfsbs;
 423
 424        /*
 425         * Do we need more readahead?
 426         */
 427        blk_start_plug(&plug);
 428        for (mip->ra_index = mip->ra_offset = i = 0;
 429             mip->ra_want > mip->ra_current && i < mip->map_blocks;
 430             i += mp->m_dirblkfsbs) {
 431                ASSERT(mip->ra_index < mip->map_valid);
 432                /*
 433                 * Read-ahead a contiguous directory block.
 434                 */
 435                if (i > mip->ra_current &&
 436                    map[mip->ra_index].br_blockcount >= mp->m_dirblkfsbs) {
 437                        xfs_dir3_data_readahead(NULL, dp,
 438                                map[mip->ra_index].br_startoff + mip->ra_offset,
 439                                XFS_FSB_TO_DADDR(mp,
 440                                        map[mip->ra_index].br_startblock +
 441                                                        mip->ra_offset));
 442                        mip->ra_current = i;
 443                }
 444
 445                /*
 446                 * Read-ahead a non-contiguous directory block.  This doesn't
 447                 * use our mapping, but this is a very rare case.
 448                 */
 449                else if (i > mip->ra_current) {
 450                        xfs_dir3_data_readahead(NULL, dp,
 451                                        map[mip->ra_index].br_startoff +
 452                                                        mip->ra_offset, -1);
 453                        mip->ra_current = i;
 454                }
 455
 456                /*
 457                 * Advance offset through the mapping table.
 458                 */
 459                for (j = 0; j < mp->m_dirblkfsbs; j++) {
 460                        /*
 461                         * The rest of this extent but not more than a dir
 462                         * block.
 463                         */
 464                        length = min_t(int, mp->m_dirblkfsbs,
 465                                        map[mip->ra_index].br_blockcount -
 466                                                        mip->ra_offset);
 467                        j += length;
 468                        mip->ra_offset += length;
 469
 470                        /*
 471                         * Advance to the next mapping if this one is used up.
 472                         */
 473                        if (mip->ra_offset == map[mip->ra_index].br_blockcount) {
 474                                mip->ra_offset = 0;
 475                                mip->ra_index++;
 476                        }
 477                }
 478        }
 479        blk_finish_plug(&plug);
 480
 481out:
 482        *bpp = bp;
 483        return error;
 484}
 485
 486/*
 487 * Getdents (readdir) for leaf and node directories.
 488 * This reads the data blocks only, so is the same for both forms.
 489 */
 490STATIC int
 491xfs_dir2_leaf_getdents(
 492        xfs_inode_t             *dp,            /* incore directory inode */
 493        struct dir_context      *ctx,
 494        size_t                  bufsize)
 495{
 496        struct xfs_buf          *bp = NULL;     /* data block buffer */
 497        xfs_dir2_data_hdr_t     *hdr;           /* data block header */
 498        xfs_dir2_data_entry_t   *dep;           /* data entry */
 499        xfs_dir2_data_unused_t  *dup;           /* unused entry */
 500        int                     error = 0;      /* error return value */
 501        int                     length;         /* temporary length value */
 502        xfs_mount_t             *mp;            /* filesystem mount point */
 503        int                     byteoff;        /* offset in current block */
 504        xfs_dir2_off_t          curoff;         /* current overall offset */
 505        xfs_dir2_off_t          newoff;         /* new curoff after new blk */
 506        char                    *ptr = NULL;    /* pointer to current data */
 507        struct xfs_dir2_leaf_map_info *map_info;
 508
 509        /*
 510         * If the offset is at or past the largest allowed value,
 511         * give up right away.
 512         */
 513        if (ctx->pos >= XFS_DIR2_MAX_DATAPTR)
 514                return 0;
 515
 516        mp = dp->i_mount;
 517
 518        /*
 519         * Set up to bmap a number of blocks based on the caller's
 520         * buffer size, the directory block size, and the filesystem
 521         * block size.
 522         */
 523        length = howmany(bufsize + mp->m_dirblksize,
 524                                     mp->m_sb.sb_blocksize);
 525        map_info = kmem_zalloc(offsetof(struct xfs_dir2_leaf_map_info, map) +
 526                                (length * sizeof(struct xfs_bmbt_irec)),
 527                               KM_SLEEP | KM_NOFS);
 528        map_info->map_size = length;
 529
 530        /*
 531         * Inside the loop we keep the main offset value as a byte offset
 532         * in the directory file.
 533         */
 534        curoff = xfs_dir2_dataptr_to_byte(mp, ctx->pos);
 535
 536        /*
 537         * Force this conversion through db so we truncate the offset
 538         * down to get the start of the data block.
 539         */
 540        map_info->map_off = xfs_dir2_db_to_da(mp,
 541                                              xfs_dir2_byte_to_db(mp, curoff));
 542
 543        /*
 544         * Loop over directory entries until we reach the end offset.
 545         * Get more blocks and readahead as necessary.
 546         */
 547        while (curoff < XFS_DIR2_LEAF_OFFSET) {
 548                __uint8_t filetype;
 549
 550                /*
 551                 * If we have no buffer, or we're off the end of the
 552                 * current buffer, need to get another one.
 553                 */
 554                if (!bp || ptr >= (char *)bp->b_addr + mp->m_dirblksize) {
 555
 556                        error = xfs_dir2_leaf_readbuf(dp, bufsize, map_info,
 557                                                      &curoff, &bp);
 558                        if (error || !map_info->map_valid)
 559                                break;
 560
 561                        /*
 562                         * Having done a read, we need to set a new offset.
 563                         */
 564                        newoff = xfs_dir2_db_off_to_byte(mp, map_info->curdb, 0);
 565                        /*
 566                         * Start of the current block.
 567                         */
 568                        if (curoff < newoff)
 569                                curoff = newoff;
 570                        /*
 571                         * Make sure we're in the right block.
 572                         */
 573                        else if (curoff > newoff)
 574                                ASSERT(xfs_dir2_byte_to_db(mp, curoff) ==
 575                                       map_info->curdb);
 576                        hdr = bp->b_addr;
 577                        xfs_dir3_data_check(dp, bp);
 578                        /*
 579                         * Find our position in the block.
 580                         */
 581                        ptr = (char *)dp->d_ops->data_entry_p(hdr);
 582                        byteoff = xfs_dir2_byte_to_off(mp, curoff);
 583                        /*
 584                         * Skip past the header.
 585                         */
 586                        if (byteoff == 0)
 587                                curoff += dp->d_ops->data_entry_offset;
 588                        /*
 589                         * Skip past entries until we reach our offset.
 590                         */
 591                        else {
 592                                while ((char *)ptr - (char *)hdr < byteoff) {
 593                                        dup = (xfs_dir2_data_unused_t *)ptr;
 594
 595                                        if (be16_to_cpu(dup->freetag)
 596                                                  == XFS_DIR2_DATA_FREE_TAG) {
 597
 598                                                length = be16_to_cpu(dup->length);
 599                                                ptr += length;
 600                                                continue;
 601                                        }
 602                                        dep = (xfs_dir2_data_entry_t *)ptr;
 603                                        length =
 604                                           dp->d_ops->data_entsize(dep->namelen);
 605                                        ptr += length;
 606                                }
 607                                /*
 608                                 * Now set our real offset.
 609                                 */
 610                                curoff =
 611                                        xfs_dir2_db_off_to_byte(mp,
 612                                            xfs_dir2_byte_to_db(mp, curoff),
 613                                            (char *)ptr - (char *)hdr);
 614                                if (ptr >= (char *)hdr + mp->m_dirblksize) {
 615                                        continue;
 616                                }
 617                        }
 618                }
 619                /*
 620                 * We have a pointer to an entry.
 621                 * Is it a live one?
 622                 */
 623                dup = (xfs_dir2_data_unused_t *)ptr;
 624                /*
 625                 * No, it's unused, skip over it.
 626                 */
 627                if (be16_to_cpu(dup->freetag) == XFS_DIR2_DATA_FREE_TAG) {
 628                        length = be16_to_cpu(dup->length);
 629                        ptr += length;
 630                        curoff += length;
 631                        continue;
 632                }
 633
 634                dep = (xfs_dir2_data_entry_t *)ptr;
 635                length = dp->d_ops->data_entsize(dep->namelen);
 636                filetype = dp->d_ops->data_get_ftype(dep);
 637
 638                ctx->pos = xfs_dir2_byte_to_dataptr(mp, curoff) & 0x7fffffff;
 639                if (!dir_emit(ctx, (char *)dep->name, dep->namelen,
 640                            be64_to_cpu(dep->inumber),
 641                            xfs_dir3_get_dtype(mp, filetype)))
 642                        break;
 643
 644                /*
 645                 * Advance to next entry in the block.
 646                 */
 647                ptr += length;
 648                curoff += length;
 649                /* bufsize may have just been a guess; don't go negative */
 650                bufsize = bufsize > length ? bufsize - length : 0;
 651        }
 652
 653        /*
 654         * All done.  Set output offset value to current offset.
 655         */
 656        if (curoff > xfs_dir2_dataptr_to_byte(mp, XFS_DIR2_MAX_DATAPTR))
 657                ctx->pos = XFS_DIR2_MAX_DATAPTR & 0x7fffffff;
 658        else
 659                ctx->pos = xfs_dir2_byte_to_dataptr(mp, curoff) & 0x7fffffff;
 660        kmem_free(map_info);
 661        if (bp)
 662                xfs_trans_brelse(NULL, bp);
 663        return error;
 664}
 665
 666/*
 667 * Read a directory.
 668 */
 669int
 670xfs_readdir(
 671        xfs_inode_t     *dp,
 672        struct dir_context *ctx,
 673        size_t          bufsize)
 674{
 675        int             rval;           /* return value */
 676        int             v;              /* type-checking value */
 677
 678        trace_xfs_readdir(dp);
 679
 680        if (XFS_FORCED_SHUTDOWN(dp->i_mount))
 681                return XFS_ERROR(EIO);
 682
 683        ASSERT(S_ISDIR(dp->i_d.di_mode));
 684        XFS_STATS_INC(xs_dir_getdents);
 685
 686        if (dp->i_d.di_format == XFS_DINODE_FMT_LOCAL)
 687                rval = xfs_dir2_sf_getdents(dp, ctx);
 688        else if ((rval = xfs_dir2_isblock(NULL, dp, &v)))
 689                ;
 690        else if (v)
 691                rval = xfs_dir2_block_getdents(dp, ctx);
 692        else
 693                rval = xfs_dir2_leaf_getdents(dp, ctx, bufsize);
 694        return rval;
 695}
 696