linux/fs/xfs/xfs_itable.c
<<
>>
Prefs
   1// SPDX-License-Identifier: GPL-2.0
   2/*
   3 * Copyright (c) 2000-2002,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_btree.h"
  15#include "xfs_ialloc.h"
  16#include "xfs_ialloc_btree.h"
  17#include "xfs_itable.h"
  18#include "xfs_error.h"
  19#include "xfs_trace.h"
  20#include "xfs_icache.h"
  21#include "xfs_health.h"
  22
  23/*
  24 * Return stat information for one inode.
  25 * Return 0 if ok, else errno.
  26 */
  27int
  28xfs_bulkstat_one_int(
  29        struct xfs_mount        *mp,            /* mount point for filesystem */
  30        xfs_ino_t               ino,            /* inode to get data for */
  31        void __user             *buffer,        /* buffer to place output in */
  32        int                     ubsize,         /* size of buffer */
  33        bulkstat_one_fmt_pf     formatter,      /* formatter, copy to user */
  34        int                     *ubused,        /* bytes used by me */
  35        int                     *stat)          /* BULKSTAT_RV_... */
  36{
  37        struct xfs_icdinode     *dic;           /* dinode core info pointer */
  38        struct xfs_inode        *ip;            /* incore inode pointer */
  39        struct inode            *inode;
  40        struct xfs_bstat        *buf;           /* return buffer */
  41        int                     error = 0;      /* error value */
  42
  43        *stat = BULKSTAT_RV_NOTHING;
  44
  45        if (!buffer || xfs_internal_inum(mp, ino))
  46                return -EINVAL;
  47
  48        buf = kmem_zalloc(sizeof(*buf), KM_SLEEP | KM_MAYFAIL);
  49        if (!buf)
  50                return -ENOMEM;
  51
  52        error = xfs_iget(mp, NULL, ino,
  53                         (XFS_IGET_DONTCACHE | XFS_IGET_UNTRUSTED),
  54                         XFS_ILOCK_SHARED, &ip);
  55        if (error)
  56                goto out_free;
  57
  58        ASSERT(ip != NULL);
  59        ASSERT(ip->i_imap.im_blkno != 0);
  60        inode = VFS_I(ip);
  61
  62        dic = &ip->i_d;
  63
  64        /* xfs_iget returns the following without needing
  65         * further change.
  66         */
  67        buf->bs_projid_lo = dic->di_projid_lo;
  68        buf->bs_projid_hi = dic->di_projid_hi;
  69        buf->bs_ino = ino;
  70        buf->bs_uid = dic->di_uid;
  71        buf->bs_gid = dic->di_gid;
  72        buf->bs_size = dic->di_size;
  73
  74        buf->bs_nlink = inode->i_nlink;
  75        buf->bs_atime.tv_sec = inode->i_atime.tv_sec;
  76        buf->bs_atime.tv_nsec = inode->i_atime.tv_nsec;
  77        buf->bs_mtime.tv_sec = inode->i_mtime.tv_sec;
  78        buf->bs_mtime.tv_nsec = inode->i_mtime.tv_nsec;
  79        buf->bs_ctime.tv_sec = inode->i_ctime.tv_sec;
  80        buf->bs_ctime.tv_nsec = inode->i_ctime.tv_nsec;
  81        buf->bs_gen = inode->i_generation;
  82        buf->bs_mode = inode->i_mode;
  83
  84        buf->bs_xflags = xfs_ip2xflags(ip);
  85        buf->bs_extsize = dic->di_extsize << mp->m_sb.sb_blocklog;
  86        buf->bs_extents = dic->di_nextents;
  87        memset(buf->bs_pad, 0, sizeof(buf->bs_pad));
  88        xfs_bulkstat_health(ip, buf);
  89        buf->bs_dmevmask = dic->di_dmevmask;
  90        buf->bs_dmstate = dic->di_dmstate;
  91        buf->bs_aextents = dic->di_anextents;
  92        buf->bs_forkoff = XFS_IFORK_BOFF(ip);
  93
  94        if (dic->di_version == 3) {
  95                if (dic->di_flags2 & XFS_DIFLAG2_COWEXTSIZE)
  96                        buf->bs_cowextsize = dic->di_cowextsize <<
  97                                        mp->m_sb.sb_blocklog;
  98        }
  99
 100        switch (dic->di_format) {
 101        case XFS_DINODE_FMT_DEV:
 102                buf->bs_rdev = sysv_encode_dev(inode->i_rdev);
 103                buf->bs_blksize = BLKDEV_IOSIZE;
 104                buf->bs_blocks = 0;
 105                break;
 106        case XFS_DINODE_FMT_LOCAL:
 107                buf->bs_rdev = 0;
 108                buf->bs_blksize = mp->m_sb.sb_blocksize;
 109                buf->bs_blocks = 0;
 110                break;
 111        case XFS_DINODE_FMT_EXTENTS:
 112        case XFS_DINODE_FMT_BTREE:
 113                buf->bs_rdev = 0;
 114                buf->bs_blksize = mp->m_sb.sb_blocksize;
 115                buf->bs_blocks = dic->di_nblocks + ip->i_delayed_blks;
 116                break;
 117        }
 118        xfs_iunlock(ip, XFS_ILOCK_SHARED);
 119        xfs_irele(ip);
 120
 121        error = formatter(buffer, ubsize, ubused, buf);
 122        if (!error)
 123                *stat = BULKSTAT_RV_DIDONE;
 124
 125 out_free:
 126        kmem_free(buf);
 127        return error;
 128}
 129
 130/* Return 0 on success or positive error */
 131STATIC int
 132xfs_bulkstat_one_fmt(
 133        void                    __user *ubuffer,
 134        int                     ubsize,
 135        int                     *ubused,
 136        const xfs_bstat_t       *buffer)
 137{
 138        if (ubsize < sizeof(*buffer))
 139                return -ENOMEM;
 140        if (copy_to_user(ubuffer, buffer, sizeof(*buffer)))
 141                return -EFAULT;
 142        if (ubused)
 143                *ubused = sizeof(*buffer);
 144        return 0;
 145}
 146
 147int
 148xfs_bulkstat_one(
 149        xfs_mount_t     *mp,            /* mount point for filesystem */
 150        xfs_ino_t       ino,            /* inode number to get data for */
 151        void            __user *buffer, /* buffer to place output in */
 152        int             ubsize,         /* size of buffer */
 153        int             *ubused,        /* bytes used by me */
 154        int             *stat)          /* BULKSTAT_RV_... */
 155{
 156        return xfs_bulkstat_one_int(mp, ino, buffer, ubsize,
 157                                    xfs_bulkstat_one_fmt, ubused, stat);
 158}
 159
 160/*
 161 * Loop over all clusters in a chunk for a given incore inode allocation btree
 162 * record.  Do a readahead if there are any allocated inodes in that cluster.
 163 */
 164STATIC void
 165xfs_bulkstat_ichunk_ra(
 166        struct xfs_mount                *mp,
 167        xfs_agnumber_t                  agno,
 168        struct xfs_inobt_rec_incore     *irec)
 169{
 170        xfs_agblock_t                   agbno;
 171        struct blk_plug                 plug;
 172        int                             i;      /* inode chunk index */
 173
 174        agbno = XFS_AGINO_TO_AGBNO(mp, irec->ir_startino);
 175
 176        blk_start_plug(&plug);
 177        for (i = 0; i < XFS_INODES_PER_CHUNK;
 178             i += mp->m_inodes_per_cluster, agbno += mp->m_blocks_per_cluster) {
 179                if (xfs_inobt_maskn(i, mp->m_inodes_per_cluster) &
 180                    ~irec->ir_free) {
 181                        xfs_btree_reada_bufs(mp, agno, agbno,
 182                                        mp->m_blocks_per_cluster,
 183                                        &xfs_inode_buf_ops);
 184                }
 185        }
 186        blk_finish_plug(&plug);
 187}
 188
 189/*
 190 * Lookup the inode chunk that the given inode lives in and then get the record
 191 * if we found the chunk.  If the inode was not the last in the chunk and there
 192 * are some left allocated, update the data for the pointed-to record as well as
 193 * return the count of grabbed inodes.
 194 */
 195STATIC int
 196xfs_bulkstat_grab_ichunk(
 197        struct xfs_btree_cur            *cur,   /* btree cursor */
 198        xfs_agino_t                     agino,  /* starting inode of chunk */
 199        int                             *icount,/* return # of inodes grabbed */
 200        struct xfs_inobt_rec_incore     *irec)  /* btree record */
 201{
 202        int                             idx;    /* index into inode chunk */
 203        int                             stat;
 204        int                             error = 0;
 205
 206        /* Lookup the inode chunk that this inode lives in */
 207        error = xfs_inobt_lookup(cur, agino, XFS_LOOKUP_LE, &stat);
 208        if (error)
 209                return error;
 210        if (!stat) {
 211                *icount = 0;
 212                return error;
 213        }
 214
 215        /* Get the record, should always work */
 216        error = xfs_inobt_get_rec(cur, irec, &stat);
 217        if (error)
 218                return error;
 219        XFS_WANT_CORRUPTED_RETURN(cur->bc_mp, stat == 1);
 220
 221        /* Check if the record contains the inode in request */
 222        if (irec->ir_startino + XFS_INODES_PER_CHUNK <= agino) {
 223                *icount = 0;
 224                return 0;
 225        }
 226
 227        idx = agino - irec->ir_startino + 1;
 228        if (idx < XFS_INODES_PER_CHUNK &&
 229            (xfs_inobt_maskn(idx, XFS_INODES_PER_CHUNK - idx) & ~irec->ir_free)) {
 230                int     i;
 231
 232                /* We got a right chunk with some left inodes allocated at it.
 233                 * Grab the chunk record.  Mark all the uninteresting inodes
 234                 * free -- because they're before our start point.
 235                 */
 236                for (i = 0; i < idx; i++) {
 237                        if (XFS_INOBT_MASK(i) & ~irec->ir_free)
 238                                irec->ir_freecount++;
 239                }
 240
 241                irec->ir_free |= xfs_inobt_maskn(0, idx);
 242                *icount = irec->ir_count - irec->ir_freecount;
 243        }
 244
 245        return 0;
 246}
 247
 248#define XFS_BULKSTAT_UBLEFT(ubleft)     ((ubleft) >= statstruct_size)
 249
 250struct xfs_bulkstat_agichunk {
 251        char            __user **ac_ubuffer;/* pointer into user's buffer */
 252        int             ac_ubleft;      /* bytes left in user's buffer */
 253        int             ac_ubelem;      /* spaces used in user's buffer */
 254};
 255
 256/*
 257 * Process inodes in chunk with a pointer to a formatter function
 258 * that will iget the inode and fill in the appropriate structure.
 259 */
 260static int
 261xfs_bulkstat_ag_ichunk(
 262        struct xfs_mount                *mp,
 263        xfs_agnumber_t                  agno,
 264        struct xfs_inobt_rec_incore     *irbp,
 265        bulkstat_one_pf                 formatter,
 266        size_t                          statstruct_size,
 267        struct xfs_bulkstat_agichunk    *acp,
 268        xfs_agino_t                     *last_agino)
 269{
 270        char                            __user **ubufp = acp->ac_ubuffer;
 271        int                             chunkidx;
 272        int                             error = 0;
 273        xfs_agino_t                     agino = irbp->ir_startino;
 274
 275        for (chunkidx = 0; chunkidx < XFS_INODES_PER_CHUNK;
 276             chunkidx++, agino++) {
 277                int             fmterror;
 278                int             ubused;
 279
 280                /* inode won't fit in buffer, we are done */
 281                if (acp->ac_ubleft < statstruct_size)
 282                        break;
 283
 284                /* Skip if this inode is free */
 285                if (XFS_INOBT_MASK(chunkidx) & irbp->ir_free)
 286                        continue;
 287
 288                /* Get the inode and fill in a single buffer */
 289                ubused = statstruct_size;
 290                error = formatter(mp, XFS_AGINO_TO_INO(mp, agno, agino),
 291                                  *ubufp, acp->ac_ubleft, &ubused, &fmterror);
 292
 293                if (fmterror == BULKSTAT_RV_GIVEUP ||
 294                    (error && error != -ENOENT && error != -EINVAL)) {
 295                        acp->ac_ubleft = 0;
 296                        ASSERT(error);
 297                        break;
 298                }
 299
 300                /* be careful not to leak error if at end of chunk */
 301                if (fmterror == BULKSTAT_RV_NOTHING || error) {
 302                        error = 0;
 303                        continue;
 304                }
 305
 306                *ubufp += ubused;
 307                acp->ac_ubleft -= ubused;
 308                acp->ac_ubelem++;
 309        }
 310
 311        /*
 312         * Post-update *last_agino. At this point, agino will always point one
 313         * inode past the last inode we processed successfully. Hence we
 314         * substract that inode when setting the *last_agino cursor so that we
 315         * return the correct cookie to userspace. On the next bulkstat call,
 316         * the inode under the lastino cookie will be skipped as we have already
 317         * processed it here.
 318         */
 319        *last_agino = agino - 1;
 320
 321        return error;
 322}
 323
 324/*
 325 * Return stat information in bulk (by-inode) for the filesystem.
 326 */
 327int                                     /* error status */
 328xfs_bulkstat(
 329        xfs_mount_t             *mp,    /* mount point for filesystem */
 330        xfs_ino_t               *lastinop, /* last inode returned */
 331        int                     *ubcountp, /* size of buffer/count returned */
 332        bulkstat_one_pf         formatter, /* func that'd fill a single buf */
 333        size_t                  statstruct_size, /* sizeof struct filling */
 334        char                    __user *ubuffer, /* buffer with inode stats */
 335        int                     *done)  /* 1 if there are more stats to get */
 336{
 337        xfs_buf_t               *agbp;  /* agi header buffer */
 338        xfs_agino_t             agino;  /* inode # in allocation group */
 339        xfs_agnumber_t          agno;   /* allocation group number */
 340        xfs_btree_cur_t         *cur;   /* btree cursor for ialloc btree */
 341        xfs_inobt_rec_incore_t  *irbuf; /* start of irec buffer */
 342        int                     nirbuf; /* size of irbuf */
 343        int                     ubcount; /* size of user's buffer */
 344        struct xfs_bulkstat_agichunk ac;
 345        int                     error = 0;
 346
 347        /*
 348         * Get the last inode value, see if there's nothing to do.
 349         */
 350        agno = XFS_INO_TO_AGNO(mp, *lastinop);
 351        agino = XFS_INO_TO_AGINO(mp, *lastinop);
 352        if (agno >= mp->m_sb.sb_agcount ||
 353            *lastinop != XFS_AGINO_TO_INO(mp, agno, agino)) {
 354                *done = 1;
 355                *ubcountp = 0;
 356                return 0;
 357        }
 358
 359        ubcount = *ubcountp; /* statstruct's */
 360        ac.ac_ubuffer = &ubuffer;
 361        ac.ac_ubleft = ubcount * statstruct_size; /* bytes */;
 362        ac.ac_ubelem = 0;
 363
 364        *ubcountp = 0;
 365        *done = 0;
 366
 367        irbuf = kmem_zalloc_large(PAGE_SIZE * 4, KM_SLEEP);
 368        if (!irbuf)
 369                return -ENOMEM;
 370        nirbuf = (PAGE_SIZE * 4) / sizeof(*irbuf);
 371
 372        /*
 373         * Loop over the allocation groups, starting from the last
 374         * inode returned; 0 means start of the allocation group.
 375         */
 376        while (agno < mp->m_sb.sb_agcount) {
 377                struct xfs_inobt_rec_incore     *irbp = irbuf;
 378                struct xfs_inobt_rec_incore     *irbufend = irbuf + nirbuf;
 379                bool                            end_of_ag = false;
 380                int                             icount = 0;
 381                int                             stat;
 382
 383                error = xfs_ialloc_read_agi(mp, NULL, agno, &agbp);
 384                if (error)
 385                        break;
 386                /*
 387                 * Allocate and initialize a btree cursor for ialloc btree.
 388                 */
 389                cur = xfs_inobt_init_cursor(mp, NULL, agbp, agno,
 390                                            XFS_BTNUM_INO);
 391                if (agino > 0) {
 392                        /*
 393                         * In the middle of an allocation group, we need to get
 394                         * the remainder of the chunk we're in.
 395                         */
 396                        struct xfs_inobt_rec_incore     r;
 397
 398                        error = xfs_bulkstat_grab_ichunk(cur, agino, &icount, &r);
 399                        if (error)
 400                                goto del_cursor;
 401                        if (icount) {
 402                                irbp->ir_startino = r.ir_startino;
 403                                irbp->ir_holemask = r.ir_holemask;
 404                                irbp->ir_count = r.ir_count;
 405                                irbp->ir_freecount = r.ir_freecount;
 406                                irbp->ir_free = r.ir_free;
 407                                irbp++;
 408                        }
 409                        /* Increment to the next record */
 410                        error = xfs_btree_increment(cur, 0, &stat);
 411                } else {
 412                        /* Start of ag.  Lookup the first inode chunk */
 413                        error = xfs_inobt_lookup(cur, 0, XFS_LOOKUP_GE, &stat);
 414                }
 415                if (error || stat == 0) {
 416                        end_of_ag = true;
 417                        goto del_cursor;
 418                }
 419
 420                /*
 421                 * Loop through inode btree records in this ag,
 422                 * until we run out of inodes or space in the buffer.
 423                 */
 424                while (irbp < irbufend && icount < ubcount) {
 425                        struct xfs_inobt_rec_incore     r;
 426
 427                        error = xfs_inobt_get_rec(cur, &r, &stat);
 428                        if (error || stat == 0) {
 429                                end_of_ag = true;
 430                                goto del_cursor;
 431                        }
 432
 433                        /*
 434                         * If this chunk has any allocated inodes, save it.
 435                         * Also start read-ahead now for this chunk.
 436                         */
 437                        if (r.ir_freecount < r.ir_count) {
 438                                xfs_bulkstat_ichunk_ra(mp, agno, &r);
 439                                irbp->ir_startino = r.ir_startino;
 440                                irbp->ir_holemask = r.ir_holemask;
 441                                irbp->ir_count = r.ir_count;
 442                                irbp->ir_freecount = r.ir_freecount;
 443                                irbp->ir_free = r.ir_free;
 444                                irbp++;
 445                                icount += r.ir_count - r.ir_freecount;
 446                        }
 447                        error = xfs_btree_increment(cur, 0, &stat);
 448                        if (error || stat == 0) {
 449                                end_of_ag = true;
 450                                goto del_cursor;
 451                        }
 452                        cond_resched();
 453                }
 454
 455                /*
 456                 * Drop the btree buffers and the agi buffer as we can't hold any
 457                 * of the locks these represent when calling iget. If there is a
 458                 * pending error, then we are done.
 459                 */
 460del_cursor:
 461                xfs_btree_del_cursor(cur, error);
 462                xfs_buf_relse(agbp);
 463                if (error)
 464                        break;
 465                /*
 466                 * Now format all the good inodes into the user's buffer. The
 467                 * call to xfs_bulkstat_ag_ichunk() sets up the agino pointer
 468                 * for the next loop iteration.
 469                 */
 470                irbufend = irbp;
 471                for (irbp = irbuf;
 472                     irbp < irbufend && ac.ac_ubleft >= statstruct_size;
 473                     irbp++) {
 474                        error = xfs_bulkstat_ag_ichunk(mp, agno, irbp,
 475                                        formatter, statstruct_size, &ac,
 476                                        &agino);
 477                        if (error)
 478                                break;
 479
 480                        cond_resched();
 481                }
 482
 483                /*
 484                 * If we've run out of space or had a formatting error, we
 485                 * are now done
 486                 */
 487                if (ac.ac_ubleft < statstruct_size || error)
 488                        break;
 489
 490                if (end_of_ag) {
 491                        agno++;
 492                        agino = 0;
 493                }
 494        }
 495        /*
 496         * Done, we're either out of filesystem or space to put the data.
 497         */
 498        kmem_free(irbuf);
 499        *ubcountp = ac.ac_ubelem;
 500
 501        /*
 502         * We found some inodes, so clear the error status and return them.
 503         * The lastino pointer will point directly at the inode that triggered
 504         * any error that occurred, so on the next call the error will be
 505         * triggered again and propagated to userspace as there will be no
 506         * formatted inodes in the buffer.
 507         */
 508        if (ac.ac_ubelem)
 509                error = 0;
 510
 511        /*
 512         * If we ran out of filesystem, lastino will point off the end of
 513         * the filesystem so the next call will return immediately.
 514         */
 515        *lastinop = XFS_AGINO_TO_INO(mp, agno, agino);
 516        if (agno >= mp->m_sb.sb_agcount)
 517                *done = 1;
 518
 519        return error;
 520}
 521
 522int
 523xfs_inumbers_fmt(
 524        void                    __user *ubuffer, /* buffer to write to */
 525        const struct xfs_inogrp *buffer,        /* buffer to read from */
 526        long                    count,          /* # of elements to read */
 527        long                    *written)       /* # of bytes written */
 528{
 529        if (copy_to_user(ubuffer, buffer, count * sizeof(*buffer)))
 530                return -EFAULT;
 531        *written = count * sizeof(*buffer);
 532        return 0;
 533}
 534
 535/*
 536 * Return inode number table for the filesystem.
 537 */
 538int                                     /* error status */
 539xfs_inumbers(
 540        struct xfs_mount        *mp,/* mount point for filesystem */
 541        xfs_ino_t               *lastino,/* last inode returned */
 542        int                     *count,/* size of buffer/count returned */
 543        void                    __user *ubuffer,/* buffer with inode descriptions */
 544        inumbers_fmt_pf         formatter)
 545{
 546        xfs_agnumber_t          agno = XFS_INO_TO_AGNO(mp, *lastino);
 547        xfs_agino_t             agino = XFS_INO_TO_AGINO(mp, *lastino);
 548        struct xfs_btree_cur    *cur = NULL;
 549        struct xfs_buf          *agbp = NULL;
 550        struct xfs_inogrp       *buffer;
 551        int                     bcount;
 552        int                     left = *count;
 553        int                     bufidx = 0;
 554        int                     error = 0;
 555
 556        *count = 0;
 557        if (agno >= mp->m_sb.sb_agcount ||
 558            *lastino != XFS_AGINO_TO_INO(mp, agno, agino))
 559                return error;
 560
 561        bcount = min(left, (int)(PAGE_SIZE / sizeof(*buffer)));
 562        buffer = kmem_zalloc(bcount * sizeof(*buffer), KM_SLEEP);
 563        do {
 564                struct xfs_inobt_rec_incore     r;
 565                int                             stat;
 566
 567                if (!agbp) {
 568                        error = xfs_ialloc_read_agi(mp, NULL, agno, &agbp);
 569                        if (error)
 570                                break;
 571
 572                        cur = xfs_inobt_init_cursor(mp, NULL, agbp, agno,
 573                                                    XFS_BTNUM_INO);
 574                        error = xfs_inobt_lookup(cur, agino, XFS_LOOKUP_GE,
 575                                                 &stat);
 576                        if (error)
 577                                break;
 578                        if (!stat)
 579                                goto next_ag;
 580                }
 581
 582                error = xfs_inobt_get_rec(cur, &r, &stat);
 583                if (error)
 584                        break;
 585                if (!stat)
 586                        goto next_ag;
 587
 588                agino = r.ir_startino + XFS_INODES_PER_CHUNK - 1;
 589                buffer[bufidx].xi_startino =
 590                        XFS_AGINO_TO_INO(mp, agno, r.ir_startino);
 591                buffer[bufidx].xi_alloccount = r.ir_count - r.ir_freecount;
 592                buffer[bufidx].xi_allocmask = ~r.ir_free;
 593                if (++bufidx == bcount) {
 594                        long    written;
 595
 596                        error = formatter(ubuffer, buffer, bufidx, &written);
 597                        if (error)
 598                                break;
 599                        ubuffer += written;
 600                        *count += bufidx;
 601                        bufidx = 0;
 602                }
 603                if (!--left)
 604                        break;
 605
 606                error = xfs_btree_increment(cur, 0, &stat);
 607                if (error)
 608                        break;
 609                if (stat)
 610                        continue;
 611
 612next_ag:
 613                xfs_btree_del_cursor(cur, XFS_BTREE_ERROR);
 614                cur = NULL;
 615                xfs_buf_relse(agbp);
 616                agbp = NULL;
 617                agino = 0;
 618                agno++;
 619        } while (agno < mp->m_sb.sb_agcount);
 620
 621        if (!error) {
 622                if (bufidx) {
 623                        long    written;
 624
 625                        error = formatter(ubuffer, buffer, bufidx, &written);
 626                        if (!error)
 627                                *count += bufidx;
 628                }
 629                *lastino = XFS_AGINO_TO_INO(mp, agno, agino);
 630        }
 631
 632        kmem_free(buffer);
 633        if (cur)
 634                xfs_btree_del_cursor(cur, error);
 635        if (agbp)
 636                xfs_buf_relse(agbp);
 637
 638        return error;
 639}
 640