1153323Srodrigc/* 2159451Srodrigc * Copyright (c) 2000-2002,2005 Silicon Graphics, Inc. 3159451Srodrigc * All Rights Reserved. 4153323Srodrigc * 5159451Srodrigc * This program is free software; you can redistribute it and/or 6159451Srodrigc * modify it under the terms of the GNU General Public License as 7153323Srodrigc * published by the Free Software Foundation. 8153323Srodrigc * 9159451Srodrigc * This program is distributed in the hope that it would be useful, 10159451Srodrigc * but WITHOUT ANY WARRANTY; without even the implied warranty of 11159451Srodrigc * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12159451Srodrigc * GNU General Public License for more details. 13153323Srodrigc * 14159451Srodrigc * You should have received a copy of the GNU General Public License 15159451Srodrigc * along with this program; if not, write the Free Software Foundation, 16159451Srodrigc * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA 17153323Srodrigc */ 18153323Srodrigc#include "xfs.h" 19159451Srodrigc#include "xfs_fs.h" 20153323Srodrigc#include "xfs_types.h" 21159451Srodrigc#include "xfs_bit.h" 22159451Srodrigc#include "xfs_log.h" 23153323Srodrigc#include "xfs_inum.h" 24153323Srodrigc#include "xfs_trans.h" 25153323Srodrigc#include "xfs_sb.h" 26159451Srodrigc#include "xfs_ag.h" 27153323Srodrigc#include "xfs_dir.h" 28153323Srodrigc#include "xfs_dir2.h" 29153323Srodrigc#include "xfs_dmapi.h" 30153323Srodrigc#include "xfs_mount.h" 31159451Srodrigc#include "xfs_bmap_btree.h" 32153323Srodrigc#include "xfs_alloc_btree.h" 33153323Srodrigc#include "xfs_ialloc_btree.h" 34153323Srodrigc#include "xfs_dir_sf.h" 35153323Srodrigc#include "xfs_dir2_sf.h" 36159451Srodrigc#include "xfs_attr_sf.h" 37153323Srodrigc#include "xfs_dinode.h" 38153323Srodrigc#include "xfs_inode.h" 39153323Srodrigc#include "xfs_ialloc.h" 40153323Srodrigc#include "xfs_itable.h" 41153323Srodrigc#include "xfs_error.h" 42159451Srodrigc#include "xfs_btree.h" 43153323Srodrigc 44159451Srodrigc#ifndef HAVE_USERACC 45159451Srodrigc#define useracc(ubuffer, size, flags, foo) (0) 46159451Srodrigc#define unuseracc(ubuffer, size, flags) 47159451Srodrigc#endif 48159451Srodrigc 49159451SrodrigcSTATIC int 50159451Srodrigcxfs_bulkstat_one_iget( 51153323Srodrigc xfs_mount_t *mp, /* mount point for filesystem */ 52153323Srodrigc xfs_ino_t ino, /* inode number to get data for */ 53153323Srodrigc xfs_daddr_t bno, /* starting bno of inode cluster */ 54159451Srodrigc xfs_bstat_t *buf, /* return buffer */ 55153323Srodrigc int *stat) /* BULKSTAT_RV_... */ 56153323Srodrigc{ 57153323Srodrigc xfs_dinode_core_t *dic; /* dinode core info pointer */ 58159451Srodrigc xfs_inode_t *ip; /* incore inode pointer */ 59159451Srodrigc xfs_vnode_t *vp; 60159451Srodrigc int error; 61153323Srodrigc 62159451Srodrigc error = xfs_iget(mp, NULL, ino, 0, XFS_ILOCK_SHARED, &ip, bno); 63159451Srodrigc if (error) { 64153323Srodrigc *stat = BULKSTAT_RV_NOTHING; 65159451Srodrigc return error; 66153323Srodrigc } 67159451Srodrigc 68159451Srodrigc ASSERT(ip != NULL); 69159451Srodrigc ASSERT(ip->i_blkno != (xfs_daddr_t)0); 70159451Srodrigc if (ip->i_d.di_mode == 0) { 71153323Srodrigc *stat = BULKSTAT_RV_NOTHING; 72159451Srodrigc error = XFS_ERROR(ENOENT); 73159451Srodrigc goto out_iput; 74153323Srodrigc } 75153323Srodrigc 76159451Srodrigc vp = XFS_ITOV(ip); 77159451Srodrigc dic = &ip->i_d; 78153323Srodrigc 79159451Srodrigc /* xfs_iget returns the following without needing 80159451Srodrigc * further change. 81159451Srodrigc */ 82159451Srodrigc buf->bs_nlink = dic->di_nlink; 83159451Srodrigc buf->bs_projid = dic->di_projid; 84159451Srodrigc buf->bs_ino = ino; 85159451Srodrigc buf->bs_mode = dic->di_mode; 86159451Srodrigc buf->bs_uid = dic->di_uid; 87159451Srodrigc buf->bs_gid = dic->di_gid; 88159451Srodrigc buf->bs_size = dic->di_size; 89159451Srodrigc vn_atime_to_bstime(vp, &buf->bs_atime); 90159451Srodrigc buf->bs_mtime.tv_sec = dic->di_mtime.t_sec; 91159451Srodrigc buf->bs_mtime.tv_nsec = dic->di_mtime.t_nsec; 92159451Srodrigc buf->bs_ctime.tv_sec = dic->di_ctime.t_sec; 93159451Srodrigc buf->bs_ctime.tv_nsec = dic->di_ctime.t_nsec; 94159451Srodrigc buf->bs_xflags = xfs_ip2xflags(ip); 95159451Srodrigc buf->bs_extsize = dic->di_extsize << mp->m_sb.sb_blocklog; 96159451Srodrigc buf->bs_extents = dic->di_nextents; 97159451Srodrigc buf->bs_gen = dic->di_gen; 98159451Srodrigc memset(buf->bs_pad, 0, sizeof(buf->bs_pad)); 99159451Srodrigc buf->bs_dmevmask = dic->di_dmevmask; 100159451Srodrigc buf->bs_dmstate = dic->di_dmstate; 101159451Srodrigc buf->bs_aextents = dic->di_anextents; 102153323Srodrigc 103159451Srodrigc switch (dic->di_format) { 104159451Srodrigc case XFS_DINODE_FMT_DEV: 105159451Srodrigc buf->bs_rdev = ip->i_df.if_u2.if_rdev; 106159451Srodrigc buf->bs_blksize = BLKDEV_IOSIZE; 107159451Srodrigc buf->bs_blocks = 0; 108159451Srodrigc break; 109159451Srodrigc case XFS_DINODE_FMT_LOCAL: 110159451Srodrigc case XFS_DINODE_FMT_UUID: 111159451Srodrigc buf->bs_rdev = 0; 112159451Srodrigc buf->bs_blksize = mp->m_sb.sb_blocksize; 113159451Srodrigc buf->bs_blocks = 0; 114159451Srodrigc break; 115159451Srodrigc case XFS_DINODE_FMT_EXTENTS: 116159451Srodrigc case XFS_DINODE_FMT_BTREE: 117159451Srodrigc buf->bs_rdev = 0; 118159451Srodrigc buf->bs_blksize = mp->m_sb.sb_blocksize; 119159451Srodrigc buf->bs_blocks = dic->di_nblocks + ip->i_delayed_blks; 120159451Srodrigc break; 121159451Srodrigc } 122153323Srodrigc 123159451Srodrigc out_iput: 124159451Srodrigc xfs_iput(ip, XFS_ILOCK_SHARED); 125159451Srodrigc return error; 126159451Srodrigc} 127153323Srodrigc 128159451SrodrigcSTATIC int 129159451Srodrigcxfs_bulkstat_one_dinode( 130159451Srodrigc xfs_mount_t *mp, /* mount point for filesystem */ 131159451Srodrigc xfs_ino_t ino, /* inode number to get data for */ 132159451Srodrigc xfs_dinode_t *dip, /* dinode inode pointer */ 133159451Srodrigc xfs_bstat_t *buf) /* return buffer */ 134159451Srodrigc{ 135159451Srodrigc xfs_dinode_core_t *dic; /* dinode core info pointer */ 136153323Srodrigc 137159451Srodrigc dic = &dip->di_core; 138153323Srodrigc 139153323Srodrigc /* 140159451Srodrigc * The inode format changed when we moved the link count and 141159451Srodrigc * made it 32 bits long. If this is an old format inode, 142159451Srodrigc * convert it in memory to look like a new one. If it gets 143159451Srodrigc * flushed to disk we will convert back before flushing or 144159451Srodrigc * logging it. We zero out the new projid field and the old link 145159451Srodrigc * count field. We'll handle clearing the pad field (the remains 146159451Srodrigc * of the old uuid field) when we actually convert the inode to 147159451Srodrigc * the new format. We don't change the version number so that we 148159451Srodrigc * can distinguish this from a real new format inode. 149153323Srodrigc */ 150159451Srodrigc if (INT_GET(dic->di_version, ARCH_CONVERT) == XFS_DINODE_VERSION_1) { 151159451Srodrigc buf->bs_nlink = INT_GET(dic->di_onlink, ARCH_CONVERT); 152159451Srodrigc buf->bs_projid = 0; 153159451Srodrigc } else { 154159451Srodrigc buf->bs_nlink = INT_GET(dic->di_nlink, ARCH_CONVERT); 155159451Srodrigc buf->bs_projid = INT_GET(dic->di_projid, ARCH_CONVERT); 156159451Srodrigc } 157153323Srodrigc 158159451Srodrigc buf->bs_ino = ino; 159159451Srodrigc buf->bs_mode = INT_GET(dic->di_mode, ARCH_CONVERT); 160159451Srodrigc buf->bs_uid = INT_GET(dic->di_uid, ARCH_CONVERT); 161159451Srodrigc buf->bs_gid = INT_GET(dic->di_gid, ARCH_CONVERT); 162159451Srodrigc buf->bs_size = INT_GET(dic->di_size, ARCH_CONVERT); 163159451Srodrigc buf->bs_atime.tv_sec = INT_GET(dic->di_atime.t_sec, ARCH_CONVERT); 164159451Srodrigc buf->bs_atime.tv_nsec = INT_GET(dic->di_atime.t_nsec, ARCH_CONVERT); 165159451Srodrigc buf->bs_mtime.tv_sec = INT_GET(dic->di_mtime.t_sec, ARCH_CONVERT); 166159451Srodrigc buf->bs_mtime.tv_nsec = INT_GET(dic->di_mtime.t_nsec, ARCH_CONVERT); 167159451Srodrigc buf->bs_ctime.tv_sec = INT_GET(dic->di_ctime.t_sec, ARCH_CONVERT); 168159451Srodrigc buf->bs_ctime.tv_nsec = INT_GET(dic->di_ctime.t_nsec, ARCH_CONVERT); 169159451Srodrigc buf->bs_xflags = xfs_dic2xflags(dic); 170159451Srodrigc buf->bs_extsize = INT_GET(dic->di_extsize, ARCH_CONVERT) << mp->m_sb.sb_blocklog; 171159451Srodrigc buf->bs_extents = INT_GET(dic->di_nextents, ARCH_CONVERT); 172159451Srodrigc buf->bs_gen = INT_GET(dic->di_gen, ARCH_CONVERT); 173153323Srodrigc memset(buf->bs_pad, 0, sizeof(buf->bs_pad)); 174159451Srodrigc buf->bs_dmevmask = INT_GET(dic->di_dmevmask, ARCH_CONVERT); 175159451Srodrigc buf->bs_dmstate = INT_GET(dic->di_dmstate, ARCH_CONVERT); 176159451Srodrigc buf->bs_aextents = INT_GET(dic->di_anextents, ARCH_CONVERT); 177153323Srodrigc 178159451Srodrigc switch (INT_GET(dic->di_format, ARCH_CONVERT)) { 179153323Srodrigc case XFS_DINODE_FMT_DEV: 180159451Srodrigc buf->bs_rdev = INT_GET(dip->di_u.di_dev, ARCH_CONVERT); 181153323Srodrigc buf->bs_blksize = BLKDEV_IOSIZE; 182153323Srodrigc buf->bs_blocks = 0; 183153323Srodrigc break; 184153323Srodrigc case XFS_DINODE_FMT_LOCAL: 185153323Srodrigc case XFS_DINODE_FMT_UUID: 186153323Srodrigc buf->bs_rdev = 0; 187153323Srodrigc buf->bs_blksize = mp->m_sb.sb_blocksize; 188153323Srodrigc buf->bs_blocks = 0; 189153323Srodrigc break; 190153323Srodrigc case XFS_DINODE_FMT_EXTENTS: 191153323Srodrigc case XFS_DINODE_FMT_BTREE: 192153323Srodrigc buf->bs_rdev = 0; 193153323Srodrigc buf->bs_blksize = mp->m_sb.sb_blocksize; 194159451Srodrigc buf->bs_blocks = INT_GET(dic->di_nblocks, ARCH_CONVERT); 195153323Srodrigc break; 196153323Srodrigc } 197153323Srodrigc 198159451Srodrigc return 0; 199159451Srodrigc} 200159451Srodrigc 201159451Srodrigc/* 202159451Srodrigc * Return stat information for one inode. 203159451Srodrigc * Return 0 if ok, else errno. 204159451Srodrigc */ 205159451Srodrigcint /* error status */ 206159451Srodrigcxfs_bulkstat_one( 207159451Srodrigc xfs_mount_t *mp, /* mount point for filesystem */ 208159451Srodrigc xfs_ino_t ino, /* inode number to get data for */ 209159451Srodrigc void __user *buffer, /* buffer to place output in */ 210159451Srodrigc int ubsize, /* size of buffer */ 211159451Srodrigc void *private_data, /* my private data */ 212159451Srodrigc xfs_daddr_t bno, /* starting bno of inode cluster */ 213159451Srodrigc int *ubused, /* bytes used by me */ 214159451Srodrigc void *dibuff, /* on-disk inode buffer */ 215159451Srodrigc int *stat) /* BULKSTAT_RV_... */ 216159451Srodrigc{ 217159451Srodrigc xfs_bstat_t *buf; /* return buffer */ 218159451Srodrigc int error = 0; /* error value */ 219159451Srodrigc xfs_dinode_t *dip; /* dinode inode pointer */ 220159451Srodrigc 221159451Srodrigc dip = (xfs_dinode_t *)dibuff; 222159451Srodrigc 223159451Srodrigc if (!buffer || ino == mp->m_sb.sb_rbmino || ino == mp->m_sb.sb_rsumino || 224159451Srodrigc (XFS_SB_VERSION_HASQUOTA(&mp->m_sb) && 225159451Srodrigc (ino == mp->m_sb.sb_uquotino || ino == mp->m_sb.sb_gquotino))) { 226159451Srodrigc *stat = BULKSTAT_RV_NOTHING; 227159451Srodrigc return XFS_ERROR(EINVAL); 228153323Srodrigc } 229159451Srodrigc if (ubsize < sizeof(*buf)) { 230159451Srodrigc *stat = BULKSTAT_RV_NOTHING; 231159451Srodrigc return XFS_ERROR(ENOMEM); 232159451Srodrigc } 233153323Srodrigc 234159451Srodrigc buf = kmem_alloc(sizeof(*buf), KM_SLEEP); 235159451Srodrigc 236159451Srodrigc if (dip == NULL) { 237159451Srodrigc /* We're not being passed a pointer to a dinode. This happens 238159451Srodrigc * if BULKSTAT_FG_IGET is selected. Do the iget. 239159451Srodrigc */ 240159451Srodrigc error = xfs_bulkstat_one_iget(mp, ino, bno, buf, stat); 241159451Srodrigc if (error) 242159451Srodrigc goto out_free; 243159451Srodrigc } else { 244159451Srodrigc xfs_bulkstat_one_dinode(mp, ino, dip, buf); 245159451Srodrigc } 246159451Srodrigc 247159451Srodrigc if (copy_to_user(buffer, buf, sizeof(*buf))) { 248159451Srodrigc *stat = BULKSTAT_RV_NOTHING; 249159451Srodrigc error = EFAULT; 250159451Srodrigc goto out_free; 251159451Srodrigc } 252159451Srodrigc 253153323Srodrigc *stat = BULKSTAT_RV_DIDONE; 254153323Srodrigc if (ubused) 255153323Srodrigc *ubused = sizeof(*buf); 256159451Srodrigc 257159451Srodrigc out_free: 258159451Srodrigc kmem_free(buf, sizeof(*buf)); 259159451Srodrigc return error; 260153323Srodrigc} 261153323Srodrigc 262153323Srodrigc/* 263153323Srodrigc * Return stat information in bulk (by-inode) for the filesystem. 264153323Srodrigc */ 265153323Srodrigcint /* error status */ 266153323Srodrigcxfs_bulkstat( 267153323Srodrigc xfs_mount_t *mp, /* mount point for filesystem */ 268153323Srodrigc xfs_ino_t *lastinop, /* last inode returned */ 269153323Srodrigc int *ubcountp, /* size of buffer/count returned */ 270153323Srodrigc bulkstat_one_pf formatter, /* func that'd fill a single buf */ 271153323Srodrigc void *private_data,/* private data for formatter */ 272153323Srodrigc size_t statstruct_size, /* sizeof struct filling */ 273159451Srodrigc char __user *ubuffer, /* buffer with inode stats */ 274153323Srodrigc int flags, /* defined in xfs_itable.h */ 275159451Srodrigc int *done) /* 1 if there are more stats to get */ 276153323Srodrigc{ 277153323Srodrigc xfs_agblock_t agbno=0;/* allocation group block number */ 278153323Srodrigc xfs_buf_t *agbp; /* agi header buffer */ 279153323Srodrigc xfs_agi_t *agi; /* agi header data */ 280153323Srodrigc xfs_agino_t agino; /* inode # in allocation group */ 281153323Srodrigc xfs_agnumber_t agno; /* allocation group number */ 282153323Srodrigc xfs_daddr_t bno; /* inode cluster start daddr */ 283153323Srodrigc int chunkidx; /* current index into inode chunk */ 284153323Srodrigc int clustidx; /* current index into inode cluster */ 285153323Srodrigc xfs_btree_cur_t *cur; /* btree cursor for ialloc btree */ 286153323Srodrigc int end_of_ag; /* set if we've seen the ag end */ 287153323Srodrigc int error; /* error code */ 288153323Srodrigc int fmterror;/* bulkstat formatter result */ 289153323Srodrigc __int32_t gcnt; /* current btree rec's count */ 290153323Srodrigc xfs_inofree_t gfree; /* current btree rec's free mask */ 291153323Srodrigc xfs_agino_t gino; /* current btree rec's start inode */ 292153323Srodrigc int i; /* loop index */ 293153323Srodrigc int icount; /* count of inodes good in irbuf */ 294153323Srodrigc xfs_ino_t ino; /* inode number (filesystem) */ 295153323Srodrigc xfs_inobt_rec_t *irbp; /* current irec buffer pointer */ 296153323Srodrigc xfs_inobt_rec_t *irbuf; /* start of irec buffer */ 297153323Srodrigc xfs_inobt_rec_t *irbufend; /* end of good irec buffer entries */ 298153323Srodrigc xfs_ino_t lastino=0; /* last inode number returned */ 299153323Srodrigc int nbcluster; /* # of blocks in a cluster */ 300153323Srodrigc int nicluster; /* # of inodes in a cluster */ 301153323Srodrigc int nimask; /* mask for inode clusters */ 302153323Srodrigc int nirbuf; /* size of irbuf */ 303153323Srodrigc int rval; /* return value error code */ 304153323Srodrigc int tmp; /* result value from btree calls */ 305153323Srodrigc int ubcount; /* size of user's buffer */ 306153323Srodrigc int ubleft; /* bytes left in user's buffer */ 307159451Srodrigc char __user *ubufp; /* pointer into user's buffer */ 308153323Srodrigc int ubelem; /* spaces used in user's buffer */ 309153323Srodrigc int ubused; /* bytes used by formatter */ 310153323Srodrigc xfs_buf_t *bp; /* ptr to on-disk inode cluster buf */ 311153323Srodrigc xfs_dinode_t *dip; /* ptr into bp for specific inode */ 312153323Srodrigc xfs_inode_t *ip; /* ptr to in-core inode struct */ 313153323Srodrigc 314153323Srodrigc /* 315153323Srodrigc * Get the last inode value, see if there's nothing to do. 316153323Srodrigc */ 317153323Srodrigc ino = (xfs_ino_t)*lastinop; 318153323Srodrigc dip = NULL; 319153323Srodrigc agno = XFS_INO_TO_AGNO(mp, ino); 320153323Srodrigc agino = XFS_INO_TO_AGINO(mp, ino); 321153323Srodrigc if (agno >= mp->m_sb.sb_agcount || 322153323Srodrigc ino != XFS_AGINO_TO_INO(mp, agno, agino)) { 323153323Srodrigc *done = 1; 324153323Srodrigc *ubcountp = 0; 325153323Srodrigc return 0; 326153323Srodrigc } 327153323Srodrigc ubcount = *ubcountp; /* statstruct's */ 328153323Srodrigc ubleft = ubcount * statstruct_size; /* bytes */ 329153323Srodrigc *ubcountp = ubelem = 0; 330153323Srodrigc *done = 0; 331153323Srodrigc fmterror = 0; 332153323Srodrigc ubufp = ubuffer; 333153323Srodrigc nicluster = mp->m_sb.sb_blocksize >= XFS_INODE_CLUSTER_SIZE(mp) ? 334153323Srodrigc mp->m_sb.sb_inopblock : 335153323Srodrigc (XFS_INODE_CLUSTER_SIZE(mp) >> mp->m_sb.sb_inodelog); 336153323Srodrigc nimask = ~(nicluster - 1); 337153323Srodrigc nbcluster = nicluster >> mp->m_sb.sb_inopblog; 338153323Srodrigc /* 339153323Srodrigc * Lock down the user's buffer. If a buffer was not sent, as in the case 340153323Srodrigc * disk quota code calls here, we skip this. 341153323Srodrigc */ 342153323Srodrigc if (ubuffer && 343153323Srodrigc (error = useracc(ubuffer, ubcount * statstruct_size, 344153323Srodrigc (B_READ|B_PHYS), NULL))) { 345153323Srodrigc return error; 346153323Srodrigc } 347153323Srodrigc /* 348153323Srodrigc * Allocate a page-sized buffer for inode btree records. 349153323Srodrigc * We could try allocating something smaller, but for normal 350153323Srodrigc * calls we'll always (potentially) need the whole page. 351153323Srodrigc */ 352153323Srodrigc irbuf = kmem_alloc(NBPC, KM_SLEEP); 353153323Srodrigc nirbuf = NBPC / sizeof(*irbuf); 354153323Srodrigc /* 355153323Srodrigc * Loop over the allocation groups, starting from the last 356153323Srodrigc * inode returned; 0 means start of the allocation group. 357153323Srodrigc */ 358153323Srodrigc rval = 0; 359153323Srodrigc while (ubleft >= statstruct_size && agno < mp->m_sb.sb_agcount) { 360153323Srodrigc bp = NULL; 361153323Srodrigc down_read(&mp->m_peraglock); 362159451Srodrigc error = xfs_ialloc_read_agi(mp, NULL, agno, &agbp); 363153323Srodrigc up_read(&mp->m_peraglock); 364153323Srodrigc if (error) { 365153323Srodrigc /* 366153323Srodrigc * Skip this allocation group and go to the next one. 367153323Srodrigc */ 368153323Srodrigc agno++; 369153323Srodrigc agino = 0; 370153323Srodrigc continue; 371153323Srodrigc } 372153323Srodrigc agi = XFS_BUF_TO_AGI(agbp); 373153323Srodrigc /* 374153323Srodrigc * Allocate and initialize a btree cursor for ialloc btree. 375153323Srodrigc */ 376159451Srodrigc cur = xfs_btree_init_cursor(mp, NULL, agbp, agno, XFS_BTNUM_INO, 377153323Srodrigc (xfs_inode_t *)0, 0); 378153323Srodrigc irbp = irbuf; 379153323Srodrigc irbufend = irbuf + nirbuf; 380153323Srodrigc end_of_ag = 0; 381153323Srodrigc /* 382153323Srodrigc * If we're returning in the middle of an allocation group, 383153323Srodrigc * we need to get the remainder of the chunk we're in. 384153323Srodrigc */ 385153323Srodrigc if (agino > 0) { 386153323Srodrigc /* 387153323Srodrigc * Lookup the inode chunk that this inode lives in. 388153323Srodrigc */ 389153323Srodrigc error = xfs_inobt_lookup_le(cur, agino, 0, 0, &tmp); 390153323Srodrigc if (!error && /* no I/O error */ 391153323Srodrigc tmp && /* lookup succeeded */ 392153323Srodrigc /* got the record, should always work */ 393153323Srodrigc !(error = xfs_inobt_get_rec(cur, &gino, &gcnt, 394159451Srodrigc &gfree, &i)) && 395153323Srodrigc i == 1 && 396153323Srodrigc /* this is the right chunk */ 397153323Srodrigc agino < gino + XFS_INODES_PER_CHUNK && 398153323Srodrigc /* lastino was not last in chunk */ 399153323Srodrigc (chunkidx = agino - gino + 1) < 400153323Srodrigc XFS_INODES_PER_CHUNK && 401153323Srodrigc /* there are some left allocated */ 402153323Srodrigc XFS_INOBT_MASKN(chunkidx, 403153323Srodrigc XFS_INODES_PER_CHUNK - chunkidx) & ~gfree) { 404153323Srodrigc /* 405153323Srodrigc * Grab the chunk record. Mark all the 406153323Srodrigc * uninteresting inodes (because they're 407153323Srodrigc * before our start point) free. 408153323Srodrigc */ 409153323Srodrigc for (i = 0; i < chunkidx; i++) { 410153323Srodrigc if (XFS_INOBT_MASK(i) & ~gfree) 411153323Srodrigc gcnt++; 412153323Srodrigc } 413153323Srodrigc gfree |= XFS_INOBT_MASKN(0, chunkidx); 414153323Srodrigc INT_SET(irbp->ir_startino, ARCH_CONVERT, gino); 415153323Srodrigc INT_SET(irbp->ir_freecount, ARCH_CONVERT, gcnt); 416153323Srodrigc INT_SET(irbp->ir_free, ARCH_CONVERT, gfree); 417153323Srodrigc irbp++; 418153323Srodrigc agino = gino + XFS_INODES_PER_CHUNK; 419153323Srodrigc icount = XFS_INODES_PER_CHUNK - gcnt; 420153323Srodrigc } else { 421153323Srodrigc /* 422153323Srodrigc * If any of those tests failed, bump the 423153323Srodrigc * inode number (just in case). 424153323Srodrigc */ 425153323Srodrigc agino++; 426153323Srodrigc icount = 0; 427153323Srodrigc } 428153323Srodrigc /* 429153323Srodrigc * In any case, increment to the next record. 430153323Srodrigc */ 431153323Srodrigc if (!error) 432153323Srodrigc error = xfs_inobt_increment(cur, 0, &tmp); 433153323Srodrigc } else { 434153323Srodrigc /* 435153323Srodrigc * Start of ag. Lookup the first inode chunk. 436153323Srodrigc */ 437153323Srodrigc error = xfs_inobt_lookup_ge(cur, 0, 0, 0, &tmp); 438153323Srodrigc icount = 0; 439153323Srodrigc } 440153323Srodrigc /* 441153323Srodrigc * Loop through inode btree records in this ag, 442153323Srodrigc * until we run out of inodes or space in the buffer. 443153323Srodrigc */ 444153323Srodrigc while (irbp < irbufend && icount < ubcount) { 445153323Srodrigc /* 446153323Srodrigc * Loop as long as we're unable to read the 447153323Srodrigc * inode btree. 448153323Srodrigc */ 449153323Srodrigc while (error) { 450153323Srodrigc agino += XFS_INODES_PER_CHUNK; 451153323Srodrigc if (XFS_AGINO_TO_AGBNO(mp, agino) >= 452159451Srodrigc be32_to_cpu(agi->agi_length)) 453153323Srodrigc break; 454153323Srodrigc error = xfs_inobt_lookup_ge(cur, agino, 0, 0, 455153323Srodrigc &tmp); 456153323Srodrigc } 457153323Srodrigc /* 458153323Srodrigc * If ran off the end of the ag either with an error, 459153323Srodrigc * or the normal way, set end and stop collecting. 460153323Srodrigc */ 461153323Srodrigc if (error || 462153323Srodrigc (error = xfs_inobt_get_rec(cur, &gino, &gcnt, 463159451Srodrigc &gfree, &i)) || 464153323Srodrigc i == 0) { 465153323Srodrigc end_of_ag = 1; 466153323Srodrigc break; 467153323Srodrigc } 468153323Srodrigc /* 469153323Srodrigc * If this chunk has any allocated inodes, save it. 470153323Srodrigc */ 471153323Srodrigc if (gcnt < XFS_INODES_PER_CHUNK) { 472153323Srodrigc INT_SET(irbp->ir_startino, ARCH_CONVERT, gino); 473153323Srodrigc INT_SET(irbp->ir_freecount, ARCH_CONVERT, gcnt); 474153323Srodrigc INT_SET(irbp->ir_free, ARCH_CONVERT, gfree); 475153323Srodrigc irbp++; 476153323Srodrigc icount += XFS_INODES_PER_CHUNK - gcnt; 477153323Srodrigc } 478153323Srodrigc /* 479153323Srodrigc * Set agino to after this chunk and bump the cursor. 480153323Srodrigc */ 481153323Srodrigc agino = gino + XFS_INODES_PER_CHUNK; 482153323Srodrigc error = xfs_inobt_increment(cur, 0, &tmp); 483153323Srodrigc } 484153323Srodrigc /* 485153323Srodrigc * Drop the btree buffers and the agi buffer. 486153323Srodrigc * We can't hold any of the locks these represent 487153323Srodrigc * when calling iget. 488153323Srodrigc */ 489153323Srodrigc xfs_btree_del_cursor(cur, XFS_BTREE_NOERROR); 490159451Srodrigc xfs_buf_relse(agbp); 491153323Srodrigc /* 492153323Srodrigc * Now format all the good inodes into the user's buffer. 493153323Srodrigc */ 494153323Srodrigc irbufend = irbp; 495153323Srodrigc for (irbp = irbuf; 496153323Srodrigc irbp < irbufend && ubleft >= statstruct_size; irbp++) { 497153323Srodrigc /* 498153323Srodrigc * Read-ahead the next chunk's worth of inodes. 499153323Srodrigc */ 500153323Srodrigc if (&irbp[1] < irbufend) { 501153323Srodrigc /* 502153323Srodrigc * Loop over all clusters in the next chunk. 503153323Srodrigc * Do a readahead if there are any allocated 504153323Srodrigc * inodes in that cluster. 505153323Srodrigc */ 506153323Srodrigc for (agbno = XFS_AGINO_TO_AGBNO(mp, 507153323Srodrigc INT_GET(irbp[1].ir_startino, ARCH_CONVERT)), 508153323Srodrigc chunkidx = 0; 509153323Srodrigc chunkidx < XFS_INODES_PER_CHUNK; 510153323Srodrigc chunkidx += nicluster, 511153323Srodrigc agbno += nbcluster) { 512153323Srodrigc if (XFS_INOBT_MASKN(chunkidx, 513153323Srodrigc nicluster) & 514153323Srodrigc ~(INT_GET(irbp[1].ir_free, ARCH_CONVERT))) 515153323Srodrigc xfs_btree_reada_bufs(mp, agno, 516153323Srodrigc agbno, nbcluster); 517153323Srodrigc } 518153323Srodrigc } 519153323Srodrigc /* 520153323Srodrigc * Now process this chunk of inodes. 521153323Srodrigc */ 522153323Srodrigc for (agino = INT_GET(irbp->ir_startino, ARCH_CONVERT), chunkidx = 0, clustidx = 0; 523153323Srodrigc ubleft > 0 && 524153323Srodrigc INT_GET(irbp->ir_freecount, ARCH_CONVERT) < XFS_INODES_PER_CHUNK; 525153323Srodrigc chunkidx++, clustidx++, agino++) { 526153323Srodrigc ASSERT(chunkidx < XFS_INODES_PER_CHUNK); 527153323Srodrigc /* 528153323Srodrigc * Recompute agbno if this is the 529153323Srodrigc * first inode of the cluster. 530153323Srodrigc * 531153323Srodrigc * Careful with clustidx. There can be 532153323Srodrigc * multple clusters per chunk, a single 533153323Srodrigc * cluster per chunk or a cluster that has 534153323Srodrigc * inodes represented from several different 535153323Srodrigc * chunks (if blocksize is large). 536153323Srodrigc * 537153323Srodrigc * Because of this, the starting clustidx is 538153323Srodrigc * initialized to zero in this loop but must 539153323Srodrigc * later be reset after reading in the cluster 540153323Srodrigc * buffer. 541153323Srodrigc */ 542153323Srodrigc if ((chunkidx & (nicluster - 1)) == 0) { 543153323Srodrigc agbno = XFS_AGINO_TO_AGBNO(mp, 544153323Srodrigc INT_GET(irbp->ir_startino, ARCH_CONVERT)) + 545153323Srodrigc ((chunkidx & nimask) >> 546153323Srodrigc mp->m_sb.sb_inopblog); 547153323Srodrigc 548153323Srodrigc if (flags & BULKSTAT_FG_QUICK) { 549153323Srodrigc ino = XFS_AGINO_TO_INO(mp, agno, 550153323Srodrigc agino); 551153323Srodrigc bno = XFS_AGB_TO_DADDR(mp, agno, 552153323Srodrigc agbno); 553153323Srodrigc 554153323Srodrigc /* 555153323Srodrigc * Get the inode cluster buffer 556153323Srodrigc */ 557153323Srodrigc ASSERT(xfs_inode_zone != NULL); 558153323Srodrigc ip = kmem_zone_zalloc(xfs_inode_zone, 559153323Srodrigc KM_SLEEP); 560153323Srodrigc ip->i_ino = ino; 561153323Srodrigc ip->i_mount = mp; 562153323Srodrigc if (bp) 563159451Srodrigc xfs_buf_relse(bp); 564159451Srodrigc error = xfs_itobp(mp, NULL, ip, 565159451Srodrigc &dip, &bp, bno, 566159451Srodrigc XFS_IMAP_BULKSTAT); 567153323Srodrigc if (!error) 568153323Srodrigc clustidx = ip->i_boffset / mp->m_sb.sb_inodesize; 569153323Srodrigc kmem_zone_free(xfs_inode_zone, ip); 570153323Srodrigc if (XFS_TEST_ERROR(error != 0, 571153323Srodrigc mp, XFS_ERRTAG_BULKSTAT_READ_CHUNK, 572153323Srodrigc XFS_RANDOM_BULKSTAT_READ_CHUNK)) { 573153323Srodrigc bp = NULL; 574159451Srodrigc ubleft = 0; 575159451Srodrigc rval = error; 576153323Srodrigc break; 577153323Srodrigc } 578153323Srodrigc } 579153323Srodrigc } 580153323Srodrigc /* 581153323Srodrigc * Skip if this inode is free. 582153323Srodrigc */ 583153323Srodrigc if (XFS_INOBT_MASK(chunkidx) & INT_GET(irbp->ir_free, ARCH_CONVERT)) 584153323Srodrigc continue; 585153323Srodrigc /* 586153323Srodrigc * Count used inodes as free so we can tell 587153323Srodrigc * when the chunk is used up. 588153323Srodrigc */ 589153323Srodrigc INT_MOD(irbp->ir_freecount, ARCH_CONVERT, +1); 590153323Srodrigc ino = XFS_AGINO_TO_INO(mp, agno, agino); 591153323Srodrigc bno = XFS_AGB_TO_DADDR(mp, agno, agbno); 592153323Srodrigc if (flags & BULKSTAT_FG_QUICK) { 593153323Srodrigc dip = (xfs_dinode_t *)xfs_buf_offset(bp, 594153323Srodrigc (clustidx << mp->m_sb.sb_inodelog)); 595153323Srodrigc 596153323Srodrigc if (INT_GET(dip->di_core.di_magic, ARCH_CONVERT) 597153323Srodrigc != XFS_DINODE_MAGIC 598153323Srodrigc || !XFS_DINODE_GOOD_VERSION( 599153323Srodrigc INT_GET(dip->di_core.di_version, ARCH_CONVERT))) 600153323Srodrigc continue; 601153323Srodrigc } 602153323Srodrigc 603153323Srodrigc /* 604153323Srodrigc * Get the inode and fill in a single buffer. 605153323Srodrigc * BULKSTAT_FG_QUICK uses dip to fill it in. 606153323Srodrigc * BULKSTAT_FG_IGET uses igets. 607153323Srodrigc * See: xfs_bulkstat_one & xfs_dm_bulkstat_one. 608153323Srodrigc * This is also used to count inodes/blks, etc 609153323Srodrigc * in xfs_qm_quotacheck. 610153323Srodrigc */ 611153323Srodrigc ubused = statstruct_size; 612159451Srodrigc error = formatter(mp, ino, ubufp, 613153323Srodrigc ubleft, private_data, 614153323Srodrigc bno, &ubused, dip, &fmterror); 615153323Srodrigc if (fmterror == BULKSTAT_RV_NOTHING) { 616153323Srodrigc if (error == ENOMEM) 617153323Srodrigc ubleft = 0; 618153323Srodrigc continue; 619153323Srodrigc } 620153323Srodrigc if (fmterror == BULKSTAT_RV_GIVEUP) { 621153323Srodrigc ubleft = 0; 622153323Srodrigc ASSERT(error); 623153323Srodrigc rval = error; 624153323Srodrigc break; 625153323Srodrigc } 626153323Srodrigc if (ubufp) 627153323Srodrigc ubufp += ubused; 628153323Srodrigc ubleft -= ubused; 629153323Srodrigc ubelem++; 630153323Srodrigc lastino = ino; 631153323Srodrigc } 632153323Srodrigc } 633153323Srodrigc 634153323Srodrigc if (bp) 635159451Srodrigc xfs_buf_relse(bp); 636153323Srodrigc 637153323Srodrigc /* 638153323Srodrigc * Set up for the next loop iteration. 639153323Srodrigc */ 640153323Srodrigc if (ubleft > 0) { 641153323Srodrigc if (end_of_ag) { 642153323Srodrigc agno++; 643153323Srodrigc agino = 0; 644153323Srodrigc } else 645153323Srodrigc agino = XFS_INO_TO_AGINO(mp, lastino); 646153323Srodrigc } else 647153323Srodrigc break; 648153323Srodrigc } 649153323Srodrigc /* 650153323Srodrigc * Done, we're either out of filesystem or space to put the data. 651153323Srodrigc */ 652153323Srodrigc kmem_free(irbuf, NBPC); 653153323Srodrigc if (ubuffer) 654153323Srodrigc unuseracc(ubuffer, ubcount * statstruct_size, (B_READ|B_PHYS)); 655153323Srodrigc *ubcountp = ubelem; 656153323Srodrigc if (agno >= mp->m_sb.sb_agcount) { 657153323Srodrigc /* 658153323Srodrigc * If we ran out of filesystem, mark lastino as off 659153323Srodrigc * the end of the filesystem, so the next call 660153323Srodrigc * will return immediately. 661153323Srodrigc */ 662153323Srodrigc *lastinop = (xfs_ino_t)XFS_AGINO_TO_INO(mp, agno, 0); 663153323Srodrigc *done = 1; 664153323Srodrigc } else 665153323Srodrigc *lastinop = (xfs_ino_t)lastino; 666153323Srodrigc 667153323Srodrigc return rval; 668153323Srodrigc} 669153323Srodrigc 670153323Srodrigc/* 671153323Srodrigc * Return stat information in bulk (by-inode) for the filesystem. 672153323Srodrigc * Special case for non-sequential one inode bulkstat. 673153323Srodrigc */ 674153323Srodrigcint /* error status */ 675153323Srodrigcxfs_bulkstat_single( 676153323Srodrigc xfs_mount_t *mp, /* mount point for filesystem */ 677153323Srodrigc xfs_ino_t *lastinop, /* inode to return */ 678159451Srodrigc char __user *buffer, /* buffer with inode stats */ 679159451Srodrigc int *done) /* 1 if there are more stats to get */ 680153323Srodrigc{ 681153323Srodrigc int count; /* count value for bulkstat call */ 682153323Srodrigc int error; /* return value */ 683153323Srodrigc xfs_ino_t ino; /* filesystem inode number */ 684153323Srodrigc int res; /* result from bs1 */ 685153323Srodrigc 686153323Srodrigc /* 687153323Srodrigc * note that requesting valid inode numbers which are not allocated 688153323Srodrigc * to inodes will most likely cause xfs_itobp to generate warning 689153323Srodrigc * messages about bad magic numbers. This is ok. The fact that 690153323Srodrigc * the inode isn't actually an inode is handled by the 691153323Srodrigc * error check below. Done this way to make the usual case faster 692153323Srodrigc * at the expense of the error case. 693153323Srodrigc */ 694153323Srodrigc 695153323Srodrigc ino = (xfs_ino_t)*lastinop; 696159451Srodrigc error = xfs_bulkstat_one(mp, ino, buffer, sizeof(xfs_bstat_t), 697153323Srodrigc NULL, 0, NULL, NULL, &res); 698153323Srodrigc if (error) { 699153323Srodrigc /* 700153323Srodrigc * Special case way failed, do it the "long" way 701153323Srodrigc * to see if that works. 702153323Srodrigc */ 703153323Srodrigc (*lastinop)--; 704153323Srodrigc count = 1; 705159451Srodrigc if (xfs_bulkstat(mp, lastinop, &count, xfs_bulkstat_one, 706159451Srodrigc NULL, sizeof(xfs_bstat_t), buffer, 707159451Srodrigc BULKSTAT_FG_IGET, done)) 708153323Srodrigc return error; 709153323Srodrigc if (count == 0 || (xfs_ino_t)*lastinop != ino) 710153323Srodrigc return error == EFSCORRUPTED ? 711153323Srodrigc XFS_ERROR(EINVAL) : error; 712153323Srodrigc else 713153323Srodrigc return 0; 714153323Srodrigc } 715153323Srodrigc *done = 0; 716153323Srodrigc return 0; 717153323Srodrigc} 718153323Srodrigc 719153323Srodrigc/* 720153323Srodrigc * Return inode number table for the filesystem. 721153323Srodrigc */ 722153323Srodrigcint /* error status */ 723153323Srodrigcxfs_inumbers( 724153323Srodrigc xfs_mount_t *mp, /* mount point for filesystem */ 725153323Srodrigc xfs_ino_t *lastino, /* last inode returned */ 726153323Srodrigc int *count, /* size of buffer/count returned */ 727159451Srodrigc xfs_inogrp_t __user *ubuffer)/* buffer with inode descriptions */ 728153323Srodrigc{ 729153323Srodrigc xfs_buf_t *agbp; 730153323Srodrigc xfs_agino_t agino; 731153323Srodrigc xfs_agnumber_t agno; 732153323Srodrigc int bcount; 733153323Srodrigc xfs_inogrp_t *buffer; 734153323Srodrigc int bufidx; 735153323Srodrigc xfs_btree_cur_t *cur; 736153323Srodrigc int error; 737153323Srodrigc __int32_t gcnt; 738153323Srodrigc xfs_inofree_t gfree; 739153323Srodrigc xfs_agino_t gino; 740153323Srodrigc int i; 741153323Srodrigc xfs_ino_t ino; 742153323Srodrigc int left; 743153323Srodrigc int tmp; 744153323Srodrigc 745153323Srodrigc ino = (xfs_ino_t)*lastino; 746153323Srodrigc agno = XFS_INO_TO_AGNO(mp, ino); 747153323Srodrigc agino = XFS_INO_TO_AGINO(mp, ino); 748153323Srodrigc left = *count; 749153323Srodrigc *count = 0; 750153323Srodrigc bcount = MIN(left, (int)(NBPP / sizeof(*buffer))); 751153323Srodrigc buffer = kmem_alloc(bcount * sizeof(*buffer), KM_SLEEP); 752153323Srodrigc error = bufidx = 0; 753153323Srodrigc cur = NULL; 754153323Srodrigc agbp = NULL; 755153323Srodrigc while (left > 0 && agno < mp->m_sb.sb_agcount) { 756153323Srodrigc if (agbp == NULL) { 757153323Srodrigc down_read(&mp->m_peraglock); 758159451Srodrigc error = xfs_ialloc_read_agi(mp, NULL, agno, &agbp); 759153323Srodrigc up_read(&mp->m_peraglock); 760153323Srodrigc if (error) { 761153323Srodrigc /* 762153323Srodrigc * If we can't read the AGI of this ag, 763153323Srodrigc * then just skip to the next one. 764153323Srodrigc */ 765153323Srodrigc ASSERT(cur == NULL); 766153323Srodrigc agbp = NULL; 767153323Srodrigc agno++; 768153323Srodrigc agino = 0; 769153323Srodrigc continue; 770153323Srodrigc } 771159451Srodrigc cur = xfs_btree_init_cursor(mp, NULL, agbp, agno, 772153323Srodrigc XFS_BTNUM_INO, (xfs_inode_t *)0, 0); 773153323Srodrigc error = xfs_inobt_lookup_ge(cur, agino, 0, 0, &tmp); 774153323Srodrigc if (error) { 775153323Srodrigc xfs_btree_del_cursor(cur, XFS_BTREE_ERROR); 776153323Srodrigc cur = NULL; 777159451Srodrigc xfs_buf_relse(agbp); 778153323Srodrigc agbp = NULL; 779153323Srodrigc /* 780218909Sbrucec * Move up the last inode in the current 781153323Srodrigc * chunk. The lookup_ge will always get 782153323Srodrigc * us the first inode in the next chunk. 783153323Srodrigc */ 784153323Srodrigc agino += XFS_INODES_PER_CHUNK - 1; 785153323Srodrigc continue; 786153323Srodrigc } 787153323Srodrigc } 788153323Srodrigc if ((error = xfs_inobt_get_rec(cur, &gino, &gcnt, &gfree, 789159451Srodrigc &i)) || 790153323Srodrigc i == 0) { 791159451Srodrigc xfs_buf_relse(agbp); 792153323Srodrigc agbp = NULL; 793153323Srodrigc xfs_btree_del_cursor(cur, XFS_BTREE_NOERROR); 794153323Srodrigc cur = NULL; 795153323Srodrigc agno++; 796153323Srodrigc agino = 0; 797153323Srodrigc continue; 798153323Srodrigc } 799153323Srodrigc agino = gino + XFS_INODES_PER_CHUNK - 1; 800153323Srodrigc buffer[bufidx].xi_startino = XFS_AGINO_TO_INO(mp, agno, gino); 801153323Srodrigc buffer[bufidx].xi_alloccount = XFS_INODES_PER_CHUNK - gcnt; 802153323Srodrigc buffer[bufidx].xi_allocmask = ~gfree; 803153323Srodrigc bufidx++; 804153323Srodrigc left--; 805153323Srodrigc if (bufidx == bcount) { 806153323Srodrigc if (copy_to_user(ubuffer, buffer, 807153323Srodrigc bufidx * sizeof(*buffer))) { 808153323Srodrigc error = XFS_ERROR(EFAULT); 809153323Srodrigc break; 810153323Srodrigc } 811159451Srodrigc ubuffer += bufidx; 812153323Srodrigc *count += bufidx; 813153323Srodrigc bufidx = 0; 814153323Srodrigc } 815153323Srodrigc if (left) { 816153323Srodrigc error = xfs_inobt_increment(cur, 0, &tmp); 817153323Srodrigc if (error) { 818153323Srodrigc xfs_btree_del_cursor(cur, XFS_BTREE_ERROR); 819153323Srodrigc cur = NULL; 820159451Srodrigc xfs_buf_relse(agbp); 821153323Srodrigc agbp = NULL; 822153323Srodrigc /* 823153323Srodrigc * The agino value has already been bumped. 824153323Srodrigc * Just try to skip up to it. 825153323Srodrigc */ 826153323Srodrigc agino += XFS_INODES_PER_CHUNK; 827153323Srodrigc continue; 828153323Srodrigc } 829153323Srodrigc } 830153323Srodrigc } 831153323Srodrigc if (!error) { 832153323Srodrigc if (bufidx) { 833153323Srodrigc if (copy_to_user(ubuffer, buffer, 834153323Srodrigc bufidx * sizeof(*buffer))) 835153323Srodrigc error = XFS_ERROR(EFAULT); 836153323Srodrigc else 837153323Srodrigc *count += bufidx; 838153323Srodrigc } 839153323Srodrigc *lastino = XFS_AGINO_TO_INO(mp, agno, agino); 840153323Srodrigc } 841153323Srodrigc kmem_free(buffer, bcount * sizeof(*buffer)); 842153323Srodrigc if (cur) 843153323Srodrigc xfs_btree_del_cursor(cur, (error ? XFS_BTREE_ERROR : 844153323Srodrigc XFS_BTREE_NOERROR)); 845153323Srodrigc if (agbp) 846159451Srodrigc xfs_buf_relse(agbp); 847153323Srodrigc return error; 848153323Srodrigc} 849