blob: 46249e4d1feaba62eec485e23376c2d3508f7440 [file] [log] [blame]
Linus Torvalds1da177e2005-04-16 15:20:36 -07001/*
Nathan Scott7b718762005-11-02 14:58:39 +11002 * Copyright (c) 2000-2002,2005 Silicon Graphics, Inc.
3 * All Rights Reserved.
Linus Torvalds1da177e2005-04-16 15:20:36 -07004 *
Nathan Scott7b718762005-11-02 14:58:39 +11005 * This program is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU General Public License as
Linus Torvalds1da177e2005-04-16 15:20:36 -07007 * published by the Free Software Foundation.
8 *
Nathan Scott7b718762005-11-02 14:58:39 +11009 * This program is distributed in the hope that it would be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
Linus Torvalds1da177e2005-04-16 15:20:36 -070013 *
Nathan Scott7b718762005-11-02 14:58:39 +110014 * You should have received a copy of the GNU General Public License
15 * along with this program; if not, write the Free Software Foundation,
16 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
Linus Torvalds1da177e2005-04-16 15:20:36 -070017 */
Linus Torvalds1da177e2005-04-16 15:20:36 -070018#include "xfs.h"
Nathan Scotta844f452005-11-02 14:38:42 +110019#include "xfs_fs.h"
Linus Torvalds1da177e2005-04-16 15:20:36 -070020#include "xfs_types.h"
Nathan Scotta844f452005-11-02 14:38:42 +110021#include "xfs_bit.h"
Linus Torvalds1da177e2005-04-16 15:20:36 -070022#include "xfs_log.h"
Nathan Scotta844f452005-11-02 14:38:42 +110023#include "xfs_inum.h"
Linus Torvalds1da177e2005-04-16 15:20:36 -070024#include "xfs_trans.h"
25#include "xfs_sb.h"
Nathan Scotta844f452005-11-02 14:38:42 +110026#include "xfs_ag.h"
Linus Torvalds1da177e2005-04-16 15:20:36 -070027#include "xfs_dir2.h"
28#include "xfs_dmapi.h"
29#include "xfs_mount.h"
Linus Torvalds1da177e2005-04-16 15:20:36 -070030#include "xfs_bmap_btree.h"
Nathan Scotta844f452005-11-02 14:38:42 +110031#include "xfs_alloc_btree.h"
Linus Torvalds1da177e2005-04-16 15:20:36 -070032#include "xfs_ialloc_btree.h"
Linus Torvalds1da177e2005-04-16 15:20:36 -070033#include "xfs_dir2_sf.h"
Nathan Scotta844f452005-11-02 14:38:42 +110034#include "xfs_attr_sf.h"
Linus Torvalds1da177e2005-04-16 15:20:36 -070035#include "xfs_dinode.h"
36#include "xfs_inode.h"
37#include "xfs_ialloc.h"
38#include "xfs_itable.h"
39#include "xfs_error.h"
Nathan Scotta844f452005-11-02 14:38:42 +110040#include "xfs_btree.h"
Linus Torvalds1da177e2005-04-16 15:20:36 -070041
Linus Torvalds1da177e2005-04-16 15:20:36 -070042STATIC int
43xfs_bulkstat_one_iget(
44 xfs_mount_t *mp, /* mount point for filesystem */
45 xfs_ino_t ino, /* inode number to get data for */
46 xfs_daddr_t bno, /* starting bno of inode cluster */
47 xfs_bstat_t *buf, /* return buffer */
48 int *stat) /* BULKSTAT_RV_... */
49{
50 xfs_dinode_core_t *dic; /* dinode core info pointer */
51 xfs_inode_t *ip; /* incore inode pointer */
Nathan Scott67fcaa72006-06-09 17:00:52 +100052 bhv_vnode_t *vp;
Linus Torvalds1da177e2005-04-16 15:20:36 -070053 int error;
54
55 error = xfs_iget(mp, NULL, ino, 0, XFS_ILOCK_SHARED, &ip, bno);
56 if (error) {
57 *stat = BULKSTAT_RV_NOTHING;
58 return error;
59 }
60
61 ASSERT(ip != NULL);
62 ASSERT(ip->i_blkno != (xfs_daddr_t)0);
63 if (ip->i_d.di_mode == 0) {
64 *stat = BULKSTAT_RV_NOTHING;
65 error = XFS_ERROR(ENOENT);
66 goto out_iput;
67 }
68
Christoph Hellwig42fe2b12006-01-11 15:35:17 +110069 vp = XFS_ITOV(ip);
Linus Torvalds1da177e2005-04-16 15:20:36 -070070 dic = &ip->i_d;
71
72 /* xfs_iget returns the following without needing
73 * further change.
74 */
75 buf->bs_nlink = dic->di_nlink;
76 buf->bs_projid = dic->di_projid;
77 buf->bs_ino = ino;
78 buf->bs_mode = dic->di_mode;
79 buf->bs_uid = dic->di_uid;
80 buf->bs_gid = dic->di_gid;
81 buf->bs_size = dic->di_size;
Nathan Scottca5ccbf2006-01-11 21:03:04 +110082 vn_atime_to_bstime(vp, &buf->bs_atime);
Linus Torvalds1da177e2005-04-16 15:20:36 -070083 buf->bs_mtime.tv_sec = dic->di_mtime.t_sec;
84 buf->bs_mtime.tv_nsec = dic->di_mtime.t_nsec;
85 buf->bs_ctime.tv_sec = dic->di_ctime.t_sec;
86 buf->bs_ctime.tv_nsec = dic->di_ctime.t_nsec;
87 buf->bs_xflags = xfs_ip2xflags(ip);
88 buf->bs_extsize = dic->di_extsize << mp->m_sb.sb_blocklog;
89 buf->bs_extents = dic->di_nextents;
90 buf->bs_gen = dic->di_gen;
91 memset(buf->bs_pad, 0, sizeof(buf->bs_pad));
92 buf->bs_dmevmask = dic->di_dmevmask;
93 buf->bs_dmstate = dic->di_dmstate;
94 buf->bs_aextents = dic->di_anextents;
95
96 switch (dic->di_format) {
97 case XFS_DINODE_FMT_DEV:
98 buf->bs_rdev = ip->i_df.if_u2.if_rdev;
99 buf->bs_blksize = BLKDEV_IOSIZE;
100 buf->bs_blocks = 0;
101 break;
102 case XFS_DINODE_FMT_LOCAL:
103 case XFS_DINODE_FMT_UUID:
104 buf->bs_rdev = 0;
105 buf->bs_blksize = mp->m_sb.sb_blocksize;
106 buf->bs_blocks = 0;
107 break;
108 case XFS_DINODE_FMT_EXTENTS:
109 case XFS_DINODE_FMT_BTREE:
110 buf->bs_rdev = 0;
111 buf->bs_blksize = mp->m_sb.sb_blocksize;
112 buf->bs_blocks = dic->di_nblocks + ip->i_delayed_blks;
113 break;
114 }
115
116 out_iput:
117 xfs_iput(ip, XFS_ILOCK_SHARED);
118 return error;
119}
120
121STATIC int
122xfs_bulkstat_one_dinode(
123 xfs_mount_t *mp, /* mount point for filesystem */
124 xfs_ino_t ino, /* inode number to get data for */
125 xfs_dinode_t *dip, /* dinode inode pointer */
126 xfs_bstat_t *buf) /* return buffer */
127{
128 xfs_dinode_core_t *dic; /* dinode core info pointer */
129
130 dic = &dip->di_core;
131
132 /*
133 * The inode format changed when we moved the link count and
134 * made it 32 bits long. If this is an old format inode,
135 * convert it in memory to look like a new one. If it gets
136 * flushed to disk we will convert back before flushing or
137 * logging it. We zero out the new projid field and the old link
138 * count field. We'll handle clearing the pad field (the remains
139 * of the old uuid field) when we actually convert the inode to
140 * the new format. We don't change the version number so that we
141 * can distinguish this from a real new format inode.
142 */
143 if (INT_GET(dic->di_version, ARCH_CONVERT) == XFS_DINODE_VERSION_1) {
144 buf->bs_nlink = INT_GET(dic->di_onlink, ARCH_CONVERT);
145 buf->bs_projid = 0;
146 } else {
147 buf->bs_nlink = INT_GET(dic->di_nlink, ARCH_CONVERT);
148 buf->bs_projid = INT_GET(dic->di_projid, ARCH_CONVERT);
149 }
150
151 buf->bs_ino = ino;
152 buf->bs_mode = INT_GET(dic->di_mode, ARCH_CONVERT);
153 buf->bs_uid = INT_GET(dic->di_uid, ARCH_CONVERT);
154 buf->bs_gid = INT_GET(dic->di_gid, ARCH_CONVERT);
155 buf->bs_size = INT_GET(dic->di_size, ARCH_CONVERT);
156 buf->bs_atime.tv_sec = INT_GET(dic->di_atime.t_sec, ARCH_CONVERT);
157 buf->bs_atime.tv_nsec = INT_GET(dic->di_atime.t_nsec, ARCH_CONVERT);
158 buf->bs_mtime.tv_sec = INT_GET(dic->di_mtime.t_sec, ARCH_CONVERT);
159 buf->bs_mtime.tv_nsec = INT_GET(dic->di_mtime.t_nsec, ARCH_CONVERT);
160 buf->bs_ctime.tv_sec = INT_GET(dic->di_ctime.t_sec, ARCH_CONVERT);
161 buf->bs_ctime.tv_nsec = INT_GET(dic->di_ctime.t_nsec, ARCH_CONVERT);
162 buf->bs_xflags = xfs_dic2xflags(dic);
163 buf->bs_extsize = INT_GET(dic->di_extsize, ARCH_CONVERT) << mp->m_sb.sb_blocklog;
164 buf->bs_extents = INT_GET(dic->di_nextents, ARCH_CONVERT);
165 buf->bs_gen = INT_GET(dic->di_gen, ARCH_CONVERT);
166 memset(buf->bs_pad, 0, sizeof(buf->bs_pad));
167 buf->bs_dmevmask = INT_GET(dic->di_dmevmask, ARCH_CONVERT);
168 buf->bs_dmstate = INT_GET(dic->di_dmstate, ARCH_CONVERT);
169 buf->bs_aextents = INT_GET(dic->di_anextents, ARCH_CONVERT);
170
171 switch (INT_GET(dic->di_format, ARCH_CONVERT)) {
172 case XFS_DINODE_FMT_DEV:
173 buf->bs_rdev = INT_GET(dip->di_u.di_dev, ARCH_CONVERT);
174 buf->bs_blksize = BLKDEV_IOSIZE;
175 buf->bs_blocks = 0;
176 break;
177 case XFS_DINODE_FMT_LOCAL:
178 case XFS_DINODE_FMT_UUID:
179 buf->bs_rdev = 0;
180 buf->bs_blksize = mp->m_sb.sb_blocksize;
181 buf->bs_blocks = 0;
182 break;
183 case XFS_DINODE_FMT_EXTENTS:
184 case XFS_DINODE_FMT_BTREE:
185 buf->bs_rdev = 0;
186 buf->bs_blksize = mp->m_sb.sb_blocksize;
187 buf->bs_blocks = INT_GET(dic->di_nblocks, ARCH_CONVERT);
188 break;
189 }
190
191 return 0;
192}
193
194/*
195 * Return stat information for one inode.
196 * Return 0 if ok, else errno.
197 */
198int /* error status */
199xfs_bulkstat_one(
200 xfs_mount_t *mp, /* mount point for filesystem */
201 xfs_ino_t ino, /* inode number to get data for */
202 void __user *buffer, /* buffer to place output in */
203 int ubsize, /* size of buffer */
204 void *private_data, /* my private data */
205 xfs_daddr_t bno, /* starting bno of inode cluster */
206 int *ubused, /* bytes used by me */
207 void *dibuff, /* on-disk inode buffer */
208 int *stat) /* BULKSTAT_RV_... */
209{
210 xfs_bstat_t *buf; /* return buffer */
211 int error = 0; /* error value */
212 xfs_dinode_t *dip; /* dinode inode pointer */
213
214 dip = (xfs_dinode_t *)dibuff;
215
216 if (!buffer || ino == mp->m_sb.sb_rbmino || ino == mp->m_sb.sb_rsumino ||
217 (XFS_SB_VERSION_HASQUOTA(&mp->m_sb) &&
218 (ino == mp->m_sb.sb_uquotino || ino == mp->m_sb.sb_gquotino))) {
219 *stat = BULKSTAT_RV_NOTHING;
220 return XFS_ERROR(EINVAL);
221 }
222 if (ubsize < sizeof(*buf)) {
223 *stat = BULKSTAT_RV_NOTHING;
224 return XFS_ERROR(ENOMEM);
225 }
226
227 buf = kmem_alloc(sizeof(*buf), KM_SLEEP);
228
229 if (dip == NULL) {
230 /* We're not being passed a pointer to a dinode. This happens
231 * if BULKSTAT_FG_IGET is selected. Do the iget.
232 */
233 error = xfs_bulkstat_one_iget(mp, ino, bno, buf, stat);
234 if (error)
235 goto out_free;
236 } else {
237 xfs_bulkstat_one_dinode(mp, ino, dip, buf);
238 }
239
240 if (copy_to_user(buffer, buf, sizeof(*buf))) {
241 *stat = BULKSTAT_RV_NOTHING;
242 error = EFAULT;
243 goto out_free;
244 }
245
246 *stat = BULKSTAT_RV_DIDONE;
247 if (ubused)
248 *ubused = sizeof(*buf);
249
250 out_free:
251 kmem_free(buf, sizeof(*buf));
252 return error;
253}
254
255/*
256 * Return stat information in bulk (by-inode) for the filesystem.
257 */
258int /* error status */
259xfs_bulkstat(
260 xfs_mount_t *mp, /* mount point for filesystem */
261 xfs_ino_t *lastinop, /* last inode returned */
262 int *ubcountp, /* size of buffer/count returned */
263 bulkstat_one_pf formatter, /* func that'd fill a single buf */
264 void *private_data,/* private data for formatter */
265 size_t statstruct_size, /* sizeof struct filling */
266 char __user *ubuffer, /* buffer with inode stats */
267 int flags, /* defined in xfs_itable.h */
Nathan Scottc41564b2006-03-29 08:55:14 +1000268 int *done) /* 1 if there are more stats to get */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700269{
270 xfs_agblock_t agbno=0;/* allocation group block number */
271 xfs_buf_t *agbp; /* agi header buffer */
272 xfs_agi_t *agi; /* agi header data */
273 xfs_agino_t agino; /* inode # in allocation group */
274 xfs_agnumber_t agno; /* allocation group number */
275 xfs_daddr_t bno; /* inode cluster start daddr */
276 int chunkidx; /* current index into inode chunk */
277 int clustidx; /* current index into inode cluster */
278 xfs_btree_cur_t *cur; /* btree cursor for ialloc btree */
279 int end_of_ag; /* set if we've seen the ag end */
280 int error; /* error code */
281 int fmterror;/* bulkstat formatter result */
282 __int32_t gcnt; /* current btree rec's count */
283 xfs_inofree_t gfree; /* current btree rec's free mask */
284 xfs_agino_t gino; /* current btree rec's start inode */
285 int i; /* loop index */
286 int icount; /* count of inodes good in irbuf */
287 xfs_ino_t ino; /* inode number (filesystem) */
288 xfs_inobt_rec_t *irbp; /* current irec buffer pointer */
289 xfs_inobt_rec_t *irbuf; /* start of irec buffer */
290 xfs_inobt_rec_t *irbufend; /* end of good irec buffer entries */
291 xfs_ino_t lastino=0; /* last inode number returned */
292 int nbcluster; /* # of blocks in a cluster */
293 int nicluster; /* # of inodes in a cluster */
294 int nimask; /* mask for inode clusters */
295 int nirbuf; /* size of irbuf */
296 int rval; /* return value error code */
297 int tmp; /* result value from btree calls */
298 int ubcount; /* size of user's buffer */
299 int ubleft; /* bytes left in user's buffer */
300 char __user *ubufp; /* pointer into user's buffer */
301 int ubelem; /* spaces used in user's buffer */
302 int ubused; /* bytes used by formatter */
303 xfs_buf_t *bp; /* ptr to on-disk inode cluster buf */
304 xfs_dinode_t *dip; /* ptr into bp for specific inode */
305 xfs_inode_t *ip; /* ptr to in-core inode struct */
306
307 /*
308 * Get the last inode value, see if there's nothing to do.
309 */
310 ino = (xfs_ino_t)*lastinop;
311 dip = NULL;
312 agno = XFS_INO_TO_AGNO(mp, ino);
313 agino = XFS_INO_TO_AGINO(mp, ino);
314 if (agno >= mp->m_sb.sb_agcount ||
315 ino != XFS_AGINO_TO_INO(mp, agno, agino)) {
316 *done = 1;
317 *ubcountp = 0;
318 return 0;
319 }
320 ubcount = *ubcountp; /* statstruct's */
321 ubleft = ubcount * statstruct_size; /* bytes */
322 *ubcountp = ubelem = 0;
323 *done = 0;
324 fmterror = 0;
325 ubufp = ubuffer;
326 nicluster = mp->m_sb.sb_blocksize >= XFS_INODE_CLUSTER_SIZE(mp) ?
327 mp->m_sb.sb_inopblock :
328 (XFS_INODE_CLUSTER_SIZE(mp) >> mp->m_sb.sb_inodelog);
329 nimask = ~(nicluster - 1);
330 nbcluster = nicluster >> mp->m_sb.sb_inopblog;
331 /*
Linus Torvalds1da177e2005-04-16 15:20:36 -0700332 * Allocate a page-sized buffer for inode btree records.
333 * We could try allocating something smaller, but for normal
334 * calls we'll always (potentially) need the whole page.
335 */
336 irbuf = kmem_alloc(NBPC, KM_SLEEP);
337 nirbuf = NBPC / sizeof(*irbuf);
338 /*
339 * Loop over the allocation groups, starting from the last
340 * inode returned; 0 means start of the allocation group.
341 */
342 rval = 0;
343 while (ubleft >= statstruct_size && agno < mp->m_sb.sb_agcount) {
344 bp = NULL;
345 down_read(&mp->m_peraglock);
346 error = xfs_ialloc_read_agi(mp, NULL, agno, &agbp);
347 up_read(&mp->m_peraglock);
348 if (error) {
349 /*
350 * Skip this allocation group and go to the next one.
351 */
352 agno++;
353 agino = 0;
354 continue;
355 }
356 agi = XFS_BUF_TO_AGI(agbp);
357 /*
358 * Allocate and initialize a btree cursor for ialloc btree.
359 */
360 cur = xfs_btree_init_cursor(mp, NULL, agbp, agno, XFS_BTNUM_INO,
361 (xfs_inode_t *)0, 0);
362 irbp = irbuf;
363 irbufend = irbuf + nirbuf;
364 end_of_ag = 0;
365 /*
366 * If we're returning in the middle of an allocation group,
367 * we need to get the remainder of the chunk we're in.
368 */
369 if (agino > 0) {
370 /*
371 * Lookup the inode chunk that this inode lives in.
372 */
373 error = xfs_inobt_lookup_le(cur, agino, 0, 0, &tmp);
374 if (!error && /* no I/O error */
375 tmp && /* lookup succeeded */
376 /* got the record, should always work */
377 !(error = xfs_inobt_get_rec(cur, &gino, &gcnt,
378 &gfree, &i)) &&
379 i == 1 &&
380 /* this is the right chunk */
381 agino < gino + XFS_INODES_PER_CHUNK &&
382 /* lastino was not last in chunk */
383 (chunkidx = agino - gino + 1) <
384 XFS_INODES_PER_CHUNK &&
385 /* there are some left allocated */
386 XFS_INOBT_MASKN(chunkidx,
387 XFS_INODES_PER_CHUNK - chunkidx) & ~gfree) {
388 /*
389 * Grab the chunk record. Mark all the
390 * uninteresting inodes (because they're
391 * before our start point) free.
392 */
393 for (i = 0; i < chunkidx; i++) {
394 if (XFS_INOBT_MASK(i) & ~gfree)
395 gcnt++;
396 }
397 gfree |= XFS_INOBT_MASKN(0, chunkidx);
398 INT_SET(irbp->ir_startino, ARCH_CONVERT, gino);
399 INT_SET(irbp->ir_freecount, ARCH_CONVERT, gcnt);
400 INT_SET(irbp->ir_free, ARCH_CONVERT, gfree);
401 irbp++;
402 agino = gino + XFS_INODES_PER_CHUNK;
403 icount = XFS_INODES_PER_CHUNK - gcnt;
404 } else {
405 /*
406 * If any of those tests failed, bump the
407 * inode number (just in case).
408 */
409 agino++;
410 icount = 0;
411 }
412 /*
413 * In any case, increment to the next record.
414 */
415 if (!error)
416 error = xfs_inobt_increment(cur, 0, &tmp);
417 } else {
418 /*
419 * Start of ag. Lookup the first inode chunk.
420 */
421 error = xfs_inobt_lookup_ge(cur, 0, 0, 0, &tmp);
422 icount = 0;
423 }
424 /*
425 * Loop through inode btree records in this ag,
426 * until we run out of inodes or space in the buffer.
427 */
428 while (irbp < irbufend && icount < ubcount) {
429 /*
430 * Loop as long as we're unable to read the
431 * inode btree.
432 */
433 while (error) {
434 agino += XFS_INODES_PER_CHUNK;
435 if (XFS_AGINO_TO_AGBNO(mp, agino) >=
Christoph Hellwig16259e72005-11-02 15:11:25 +1100436 be32_to_cpu(agi->agi_length))
Linus Torvalds1da177e2005-04-16 15:20:36 -0700437 break;
438 error = xfs_inobt_lookup_ge(cur, agino, 0, 0,
439 &tmp);
440 }
441 /*
442 * If ran off the end of the ag either with an error,
443 * or the normal way, set end and stop collecting.
444 */
445 if (error ||
446 (error = xfs_inobt_get_rec(cur, &gino, &gcnt,
447 &gfree, &i)) ||
448 i == 0) {
449 end_of_ag = 1;
450 break;
451 }
452 /*
453 * If this chunk has any allocated inodes, save it.
454 */
455 if (gcnt < XFS_INODES_PER_CHUNK) {
456 INT_SET(irbp->ir_startino, ARCH_CONVERT, gino);
457 INT_SET(irbp->ir_freecount, ARCH_CONVERT, gcnt);
458 INT_SET(irbp->ir_free, ARCH_CONVERT, gfree);
459 irbp++;
460 icount += XFS_INODES_PER_CHUNK - gcnt;
461 }
462 /*
463 * Set agino to after this chunk and bump the cursor.
464 */
465 agino = gino + XFS_INODES_PER_CHUNK;
466 error = xfs_inobt_increment(cur, 0, &tmp);
467 }
468 /*
469 * Drop the btree buffers and the agi buffer.
470 * We can't hold any of the locks these represent
471 * when calling iget.
472 */
473 xfs_btree_del_cursor(cur, XFS_BTREE_NOERROR);
474 xfs_buf_relse(agbp);
475 /*
476 * Now format all the good inodes into the user's buffer.
477 */
478 irbufend = irbp;
479 for (irbp = irbuf;
480 irbp < irbufend && ubleft >= statstruct_size; irbp++) {
481 /*
482 * Read-ahead the next chunk's worth of inodes.
483 */
484 if (&irbp[1] < irbufend) {
485 /*
486 * Loop over all clusters in the next chunk.
487 * Do a readahead if there are any allocated
488 * inodes in that cluster.
489 */
490 for (agbno = XFS_AGINO_TO_AGBNO(mp,
491 INT_GET(irbp[1].ir_startino, ARCH_CONVERT)),
492 chunkidx = 0;
493 chunkidx < XFS_INODES_PER_CHUNK;
494 chunkidx += nicluster,
495 agbno += nbcluster) {
496 if (XFS_INOBT_MASKN(chunkidx,
497 nicluster) &
498 ~(INT_GET(irbp[1].ir_free, ARCH_CONVERT)))
499 xfs_btree_reada_bufs(mp, agno,
500 agbno, nbcluster);
501 }
502 }
503 /*
504 * Now process this chunk of inodes.
505 */
506 for (agino = INT_GET(irbp->ir_startino, ARCH_CONVERT), chunkidx = 0, clustidx = 0;
507 ubleft > 0 &&
508 INT_GET(irbp->ir_freecount, ARCH_CONVERT) < XFS_INODES_PER_CHUNK;
509 chunkidx++, clustidx++, agino++) {
510 ASSERT(chunkidx < XFS_INODES_PER_CHUNK);
511 /*
512 * Recompute agbno if this is the
513 * first inode of the cluster.
514 *
515 * Careful with clustidx. There can be
516 * multple clusters per chunk, a single
517 * cluster per chunk or a cluster that has
518 * inodes represented from several different
519 * chunks (if blocksize is large).
520 *
521 * Because of this, the starting clustidx is
522 * initialized to zero in this loop but must
523 * later be reset after reading in the cluster
524 * buffer.
525 */
526 if ((chunkidx & (nicluster - 1)) == 0) {
527 agbno = XFS_AGINO_TO_AGBNO(mp,
528 INT_GET(irbp->ir_startino, ARCH_CONVERT)) +
529 ((chunkidx & nimask) >>
530 mp->m_sb.sb_inopblog);
531
532 if (flags & BULKSTAT_FG_QUICK) {
533 ino = XFS_AGINO_TO_INO(mp, agno,
534 agino);
535 bno = XFS_AGB_TO_DADDR(mp, agno,
536 agbno);
537
538 /*
539 * Get the inode cluster buffer
540 */
541 ASSERT(xfs_inode_zone != NULL);
542 ip = kmem_zone_zalloc(xfs_inode_zone,
543 KM_SLEEP);
544 ip->i_ino = ino;
545 ip->i_mount = mp;
546 if (bp)
547 xfs_buf_relse(bp);
548 error = xfs_itobp(mp, NULL, ip,
Nathan Scottb12dd342006-03-17 17:26:04 +1100549 &dip, &bp, bno,
550 XFS_IMAP_BULKSTAT);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700551 if (!error)
552 clustidx = ip->i_boffset / mp->m_sb.sb_inodesize;
553 kmem_zone_free(xfs_inode_zone, ip);
554 if (XFS_TEST_ERROR(error != 0,
555 mp, XFS_ERRTAG_BULKSTAT_READ_CHUNK,
556 XFS_RANDOM_BULKSTAT_READ_CHUNK)) {
557 bp = NULL;
Nathan Scottb12dd342006-03-17 17:26:04 +1100558 ubleft = 0;
559 rval = error;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700560 break;
561 }
562 }
563 }
564 /*
565 * Skip if this inode is free.
566 */
567 if (XFS_INOBT_MASK(chunkidx) & INT_GET(irbp->ir_free, ARCH_CONVERT))
568 continue;
569 /*
570 * Count used inodes as free so we can tell
571 * when the chunk is used up.
572 */
573 INT_MOD(irbp->ir_freecount, ARCH_CONVERT, +1);
574 ino = XFS_AGINO_TO_INO(mp, agno, agino);
575 bno = XFS_AGB_TO_DADDR(mp, agno, agbno);
576 if (flags & BULKSTAT_FG_QUICK) {
577 dip = (xfs_dinode_t *)xfs_buf_offset(bp,
578 (clustidx << mp->m_sb.sb_inodelog));
579
580 if (INT_GET(dip->di_core.di_magic, ARCH_CONVERT)
581 != XFS_DINODE_MAGIC
582 || !XFS_DINODE_GOOD_VERSION(
583 INT_GET(dip->di_core.di_version, ARCH_CONVERT)))
584 continue;
585 }
586
587 /*
588 * Get the inode and fill in a single buffer.
589 * BULKSTAT_FG_QUICK uses dip to fill it in.
590 * BULKSTAT_FG_IGET uses igets.
591 * See: xfs_bulkstat_one & xfs_dm_bulkstat_one.
592 * This is also used to count inodes/blks, etc
593 * in xfs_qm_quotacheck.
594 */
595 ubused = statstruct_size;
596 error = formatter(mp, ino, ubufp,
597 ubleft, private_data,
598 bno, &ubused, dip, &fmterror);
599 if (fmterror == BULKSTAT_RV_NOTHING) {
600 if (error == ENOMEM)
601 ubleft = 0;
602 continue;
603 }
604 if (fmterror == BULKSTAT_RV_GIVEUP) {
605 ubleft = 0;
606 ASSERT(error);
607 rval = error;
608 break;
609 }
610 if (ubufp)
611 ubufp += ubused;
612 ubleft -= ubused;
613 ubelem++;
614 lastino = ino;
615 }
616 }
617
618 if (bp)
619 xfs_buf_relse(bp);
620
621 /*
622 * Set up for the next loop iteration.
623 */
624 if (ubleft > 0) {
625 if (end_of_ag) {
626 agno++;
627 agino = 0;
628 } else
629 agino = XFS_INO_TO_AGINO(mp, lastino);
630 } else
631 break;
632 }
633 /*
634 * Done, we're either out of filesystem or space to put the data.
635 */
636 kmem_free(irbuf, NBPC);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700637 *ubcountp = ubelem;
638 if (agno >= mp->m_sb.sb_agcount) {
639 /*
640 * If we ran out of filesystem, mark lastino as off
641 * the end of the filesystem, so the next call
642 * will return immediately.
643 */
644 *lastinop = (xfs_ino_t)XFS_AGINO_TO_INO(mp, agno, 0);
645 *done = 1;
646 } else
647 *lastinop = (xfs_ino_t)lastino;
648
649 return rval;
650}
651
652/*
653 * Return stat information in bulk (by-inode) for the filesystem.
654 * Special case for non-sequential one inode bulkstat.
655 */
656int /* error status */
657xfs_bulkstat_single(
658 xfs_mount_t *mp, /* mount point for filesystem */
659 xfs_ino_t *lastinop, /* inode to return */
660 char __user *buffer, /* buffer with inode stats */
Nathan Scottc41564b2006-03-29 08:55:14 +1000661 int *done) /* 1 if there are more stats to get */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700662{
663 int count; /* count value for bulkstat call */
664 int error; /* return value */
665 xfs_ino_t ino; /* filesystem inode number */
666 int res; /* result from bs1 */
667
668 /*
669 * note that requesting valid inode numbers which are not allocated
670 * to inodes will most likely cause xfs_itobp to generate warning
671 * messages about bad magic numbers. This is ok. The fact that
672 * the inode isn't actually an inode is handled by the
673 * error check below. Done this way to make the usual case faster
674 * at the expense of the error case.
675 */
676
677 ino = (xfs_ino_t)*lastinop;
678 error = xfs_bulkstat_one(mp, ino, buffer, sizeof(xfs_bstat_t),
679 NULL, 0, NULL, NULL, &res);
680 if (error) {
681 /*
682 * Special case way failed, do it the "long" way
683 * to see if that works.
684 */
685 (*lastinop)--;
686 count = 1;
687 if (xfs_bulkstat(mp, lastinop, &count, xfs_bulkstat_one,
688 NULL, sizeof(xfs_bstat_t), buffer,
689 BULKSTAT_FG_IGET, done))
690 return error;
691 if (count == 0 || (xfs_ino_t)*lastinop != ino)
692 return error == EFSCORRUPTED ?
693 XFS_ERROR(EINVAL) : error;
694 else
695 return 0;
696 }
697 *done = 0;
698 return 0;
699}
700
701/*
702 * Return inode number table for the filesystem.
703 */
704int /* error status */
705xfs_inumbers(
706 xfs_mount_t *mp, /* mount point for filesystem */
707 xfs_ino_t *lastino, /* last inode returned */
708 int *count, /* size of buffer/count returned */
709 xfs_inogrp_t __user *ubuffer)/* buffer with inode descriptions */
710{
711 xfs_buf_t *agbp;
712 xfs_agino_t agino;
713 xfs_agnumber_t agno;
714 int bcount;
715 xfs_inogrp_t *buffer;
716 int bufidx;
717 xfs_btree_cur_t *cur;
718 int error;
719 __int32_t gcnt;
720 xfs_inofree_t gfree;
721 xfs_agino_t gino;
722 int i;
723 xfs_ino_t ino;
724 int left;
725 int tmp;
726
727 ino = (xfs_ino_t)*lastino;
728 agno = XFS_INO_TO_AGNO(mp, ino);
729 agino = XFS_INO_TO_AGINO(mp, ino);
730 left = *count;
731 *count = 0;
732 bcount = MIN(left, (int)(NBPP / sizeof(*buffer)));
733 buffer = kmem_alloc(bcount * sizeof(*buffer), KM_SLEEP);
734 error = bufidx = 0;
735 cur = NULL;
736 agbp = NULL;
737 while (left > 0 && agno < mp->m_sb.sb_agcount) {
738 if (agbp == NULL) {
739 down_read(&mp->m_peraglock);
740 error = xfs_ialloc_read_agi(mp, NULL, agno, &agbp);
741 up_read(&mp->m_peraglock);
742 if (error) {
743 /*
744 * If we can't read the AGI of this ag,
745 * then just skip to the next one.
746 */
747 ASSERT(cur == NULL);
748 agbp = NULL;
749 agno++;
750 agino = 0;
751 continue;
752 }
753 cur = xfs_btree_init_cursor(mp, NULL, agbp, agno,
754 XFS_BTNUM_INO, (xfs_inode_t *)0, 0);
755 error = xfs_inobt_lookup_ge(cur, agino, 0, 0, &tmp);
756 if (error) {
757 xfs_btree_del_cursor(cur, XFS_BTREE_ERROR);
758 cur = NULL;
759 xfs_buf_relse(agbp);
760 agbp = NULL;
761 /*
762 * Move up the the last inode in the current
763 * chunk. The lookup_ge will always get
764 * us the first inode in the next chunk.
765 */
766 agino += XFS_INODES_PER_CHUNK - 1;
767 continue;
768 }
769 }
770 if ((error = xfs_inobt_get_rec(cur, &gino, &gcnt, &gfree,
771 &i)) ||
772 i == 0) {
773 xfs_buf_relse(agbp);
774 agbp = NULL;
775 xfs_btree_del_cursor(cur, XFS_BTREE_NOERROR);
776 cur = NULL;
777 agno++;
778 agino = 0;
779 continue;
780 }
781 agino = gino + XFS_INODES_PER_CHUNK - 1;
782 buffer[bufidx].xi_startino = XFS_AGINO_TO_INO(mp, agno, gino);
783 buffer[bufidx].xi_alloccount = XFS_INODES_PER_CHUNK - gcnt;
784 buffer[bufidx].xi_allocmask = ~gfree;
785 bufidx++;
786 left--;
787 if (bufidx == bcount) {
788 if (copy_to_user(ubuffer, buffer,
789 bufidx * sizeof(*buffer))) {
790 error = XFS_ERROR(EFAULT);
791 break;
792 }
793 ubuffer += bufidx;
794 *count += bufidx;
795 bufidx = 0;
796 }
797 if (left) {
798 error = xfs_inobt_increment(cur, 0, &tmp);
799 if (error) {
800 xfs_btree_del_cursor(cur, XFS_BTREE_ERROR);
801 cur = NULL;
802 xfs_buf_relse(agbp);
803 agbp = NULL;
804 /*
805 * The agino value has already been bumped.
806 * Just try to skip up to it.
807 */
808 agino += XFS_INODES_PER_CHUNK;
809 continue;
810 }
811 }
812 }
813 if (!error) {
814 if (bufidx) {
815 if (copy_to_user(ubuffer, buffer,
816 bufidx * sizeof(*buffer)))
817 error = XFS_ERROR(EFAULT);
818 else
819 *count += bufidx;
820 }
821 *lastino = XFS_AGINO_TO_INO(mp, agno, agino);
822 }
823 kmem_free(buffer, bcount * sizeof(*buffer));
824 if (cur)
825 xfs_btree_del_cursor(cur, (error ? XFS_BTREE_ERROR :
826 XFS_BTREE_NOERROR));
827 if (agbp)
828 xfs_buf_relse(agbp);
829 return error;
830}