#ident "$Revision$"
#include <sys/param.h>
#include <sys/buf.h>
#include <sys/errno.h>
#include <sys/immu.h>
#include <sys/kmem.h>
#include <sys/sema.h>
#include <sys/time.h>
#ifndef SIM
#include <sys/systm.h>
#endif
#include "xfs_types.h"
#include "xfs_inum.h"
#include "xfs_log.h"
#include "xfs_trans.h"
#include "xfs_sb.h"
#include "xfs_mount.h"
#include "xfs_ag.h"
#include "xfs_alloc_btree.h"
#include "xfs_bmap_btree.h"
#include "xfs_ialloc_btree.h"
#include "xfs_btree.h"
#include "xfs_dinode.h"
#include "xfs_inode_item.h"
#include "xfs_inode.h"
#include "xfs_ialloc.h"
#include "xfs_itable.h"
#ifdef SIM
#include "sim.h"
#endif
/*
* Return stat information in bulk (by-inode) for the filesystem.
*/
int /* error status */
xfs_bulkstat(
xfs_mount_t *mp, /* mount point for filesystem */
xfs_trans_t *tp, /* transaction pointer */
ino64_t *lastino, /* last inode returned */
int *count, /* size of buffer/count returned */
caddr_t ubuffer) /* buffer with inode stats */
{
return EINVAL; /* not yet implemented */
}
/*
* Return inode number table for the filesystem.
*/
int /* error status */
xfs_inumbers(
xfs_mount_t *mp, /* mount point for filesystem */
xfs_trans_t *tp, /* transaction pointer */
ino64_t *lastino, /* last inode returned */
int *count, /* size of buffer/count returned */
caddr_t ubuffer) /* buffer with inode descriptions */
{
buf_t *agbp;
xfs_agi_t *agi;
xfs_agino_t agino;
xfs_agnumber_t agno;
int bcount;
xfs_inogrp_t *buffer;
int bufidx;
xfs_btree_cur_t *cur;
int error;
__int32_t gcnt;
xfs_inofree_t gfree;
xfs_agino_t gino;
xfs_ino_t ino;
int left;
ino = (xfs_ino_t)*lastino;
agno = XFS_INO_TO_AGNO(mp, ino);
agino = XFS_INO_TO_AGINO(mp, ino);
left = *count;
*count = 0;
bcount = MIN(left, NBPP / sizeof(*buffer));
buffer = kmem_alloc(bcount * sizeof(*buffer), KM_SLEEP);
error = bufidx = 0;
cur = NULL;
agbp = NULL;
while (left > 0 && agno < mp->m_sb.sb_agcount) {
if (agbp == NULL) {
agbp = xfs_ialloc_read_agi(mp, tp, agno);
cur = xfs_btree_init_cursor(mp, tp, agbp, agno,
XFS_BTNUM_INO, (xfs_inode_t *)0);
(void)xfs_inobt_lookup_ge(cur, agino, 0, 0);
}
if (!xfs_inobt_get_rec(cur, &gino, &gcnt, &gfree)) {
xfs_trans_brelse(tp, agbp);
agbp = NULL;
xfs_btree_del_cursor(cur);
cur = NULL;
agno++;
agino = 0;
continue;
}
agino = gino + XFS_INODES_PER_CHUNK - 1;
buffer[bufidx].xi_startino = XFS_AGINO_TO_INO(mp, agno, gino);
buffer[bufidx].xi_alloccount = XFS_INODES_PER_CHUNK - gcnt;
buffer[bufidx].xi_allocmask = ~gfree;
bufidx++;
left--;
if (bufidx == bcount) {
if (copyout((caddr_t)buffer, ubuffer, bufidx * sizeof(*buffer))) {
error = EFAULT;
break;
}
ubuffer += bufidx * sizeof(*buffer);
*count += bufidx;
bufidx = 0;
}
(void)xfs_inobt_increment(cur, 0);
}
if (bufidx) {
if (copyout((caddr_t)buffer, ubuffer, bufidx * sizeof(*buffer)))
error = EFAULT;
else
*count += bufidx;
}
if (!error)
*lastino = XFS_AGINO_TO_INO(mp, agno, agino);
kmem_free(buffer, bcount * sizeof(*buffer));
if (cur)
xfs_btree_del_cursor(cur);
if (agbp)
xfs_trans_brelse(tp, agbp);
return error;
}