Blame view
fs/xfs/xfs_itable.c
19.9 KB
1da177e4c
|
1 |
/* |
7b7187698
|
2 3 |
* Copyright (c) 2000-2002,2005 Silicon Graphics, Inc. * All Rights Reserved. |
1da177e4c
|
4 |
* |
7b7187698
|
5 6 |
* This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as |
1da177e4c
|
7 8 |
* published by the Free Software Foundation. * |
7b7187698
|
9 10 11 12 |
* This program is distributed in the hope that it would be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. |
1da177e4c
|
13 |
* |
7b7187698
|
14 15 16 |
* You should have received a copy of the GNU General Public License * along with this program; if not, write the Free Software Foundation, * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA |
1da177e4c
|
17 |
*/ |
1da177e4c
|
18 |
#include "xfs.h" |
a844f4510
|
19 |
#include "xfs_fs.h" |
1da177e4c
|
20 |
#include "xfs_types.h" |
a844f4510
|
21 |
#include "xfs_bit.h" |
1da177e4c
|
22 |
#include "xfs_log.h" |
a844f4510
|
23 |
#include "xfs_inum.h" |
1da177e4c
|
24 25 |
#include "xfs_trans.h" #include "xfs_sb.h" |
a844f4510
|
26 |
#include "xfs_ag.h" |
1da177e4c
|
27 |
#include "xfs_mount.h" |
1da177e4c
|
28 |
#include "xfs_bmap_btree.h" |
a844f4510
|
29 |
#include "xfs_alloc_btree.h" |
1da177e4c
|
30 |
#include "xfs_ialloc_btree.h" |
1da177e4c
|
31 32 33 34 35 |
#include "xfs_dinode.h" #include "xfs_inode.h" #include "xfs_ialloc.h" #include "xfs_itable.h" #include "xfs_error.h" |
a844f4510
|
36 |
#include "xfs_btree.h" |
f2d676143
|
37 |
#include "xfs_trace.h" |
1da177e4c
|
38 |
|
d96f8f891
|
39 |
STATIC int |
6f1f21684
|
40 41 42 43 44 |
xfs_internal_inum( xfs_mount_t *mp, xfs_ino_t ino) { return (ino == mp->m_sb.sb_rbmino || ino == mp->m_sb.sb_rsumino || |
621187099
|
45 |
(xfs_sb_version_hasquota(&mp->m_sb) && |
6f1f21684
|
46 47 |
(ino == mp->m_sb.sb_uquotino || ino == mp->m_sb.sb_gquotino))); } |
7dce11dba
|
48 49 50 51 52 53 54 55 56 57 58 |
/* * Return stat information for one inode. * Return 0 if ok, else errno. */ int xfs_bulkstat_one_int( struct xfs_mount *mp, /* mount point for filesystem */ xfs_ino_t ino, /* inode to get data for */ void __user *buffer, /* buffer to place output in */ int ubsize, /* size of buffer */ bulkstat_one_fmt_pf formatter, /* formatter, copy to user */ |
7dce11dba
|
59 60 |
int *ubused, /* bytes used by me */ int *stat) /* BULKSTAT_RV_... */ |
1da177e4c
|
61 |
{ |
7dce11dba
|
62 63 64 65 66 67 68 69 70 71 72 73 74 75 |
struct xfs_icdinode *dic; /* dinode core info pointer */ struct xfs_inode *ip; /* incore inode pointer */ struct inode *inode; struct xfs_bstat *buf; /* return buffer */ int error = 0; /* error value */ *stat = BULKSTAT_RV_NOTHING; if (!buffer || xfs_internal_inum(mp, ino)) return XFS_ERROR(EINVAL); buf = kmem_alloc(sizeof(*buf), KM_SLEEP | KM_MAYFAIL); if (!buf) return XFS_ERROR(ENOMEM); |
1da177e4c
|
76 |
|
745b1f47f
|
77 |
error = xfs_iget(mp, NULL, ino, |
7b6259e7a
|
78 |
XFS_IGET_UNTRUSTED, XFS_ILOCK_SHARED, &ip); |
1da177e4c
|
79 80 |
if (error) { *stat = BULKSTAT_RV_NOTHING; |
7dce11dba
|
81 |
goto out_free; |
1da177e4c
|
82 83 84 |
} ASSERT(ip != NULL); |
92bfc6e7c
|
85 |
ASSERT(ip->i_imap.im_blkno != 0); |
1da177e4c
|
86 87 |
dic = &ip->i_d; |
f9581b144
|
88 |
inode = VFS_I(ip); |
1da177e4c
|
89 90 91 92 93 |
/* xfs_iget returns the following without needing * further change. */ buf->bs_nlink = dic->di_nlink; |
6743099ce
|
94 95 |
buf->bs_projid_lo = dic->di_projid_lo; buf->bs_projid_hi = dic->di_projid_hi; |
1da177e4c
|
96 97 98 99 100 |
buf->bs_ino = ino; buf->bs_mode = dic->di_mode; buf->bs_uid = dic->di_uid; buf->bs_gid = dic->di_gid; buf->bs_size = dic->di_size; |
f9581b144
|
101 |
|
8fab451e3
|
102 |
/* |
f9581b144
|
103 104 105 |
* We need to read the timestamps from the Linux inode because * the VFS keeps writing directly into the inode structure instead * of telling us about the updates. |
8fab451e3
|
106 |
*/ |
f9581b144
|
107 108 109 110 111 112 |
buf->bs_atime.tv_sec = inode->i_atime.tv_sec; buf->bs_atime.tv_nsec = inode->i_atime.tv_nsec; buf->bs_mtime.tv_sec = inode->i_mtime.tv_sec; buf->bs_mtime.tv_nsec = inode->i_mtime.tv_nsec; buf->bs_ctime.tv_sec = inode->i_ctime.tv_sec; buf->bs_ctime.tv_nsec = inode->i_ctime.tv_nsec; |
1da177e4c
|
113 114 115 116 117 118 119 120 |
buf->bs_xflags = xfs_ip2xflags(ip); buf->bs_extsize = dic->di_extsize << mp->m_sb.sb_blocklog; buf->bs_extents = dic->di_nextents; buf->bs_gen = dic->di_gen; memset(buf->bs_pad, 0, sizeof(buf->bs_pad)); buf->bs_dmevmask = dic->di_dmevmask; buf->bs_dmstate = dic->di_dmstate; buf->bs_aextents = dic->di_anextents; |
07000ee68
|
121 |
buf->bs_forkoff = XFS_IFORK_BOFF(ip); |
1da177e4c
|
122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 |
switch (dic->di_format) { case XFS_DINODE_FMT_DEV: buf->bs_rdev = ip->i_df.if_u2.if_rdev; buf->bs_blksize = BLKDEV_IOSIZE; buf->bs_blocks = 0; break; case XFS_DINODE_FMT_LOCAL: case XFS_DINODE_FMT_UUID: buf->bs_rdev = 0; buf->bs_blksize = mp->m_sb.sb_blocksize; buf->bs_blocks = 0; break; case XFS_DINODE_FMT_EXTENTS: case XFS_DINODE_FMT_BTREE: buf->bs_rdev = 0; buf->bs_blksize = mp->m_sb.sb_blocksize; buf->bs_blocks = dic->di_nblocks + ip->i_delayed_blks; break; } |
f2d676143
|
142 143 |
xfs_iunlock(ip, XFS_ILOCK_SHARED); IRELE(ip); |
1da177e4c
|
144 |
|
7dce11dba
|
145 |
error = formatter(buffer, ubsize, ubused, buf); |
1da177e4c
|
146 |
|
7dce11dba
|
147 148 |
if (!error) *stat = BULKSTAT_RV_DIDONE; |
1da177e4c
|
149 |
|
7dce11dba
|
150 151 152 |
out_free: kmem_free(buf); return error; |
1da177e4c
|
153 |
} |
65fbaf248
|
154 |
/* Return 0 on success or positive error */ |
faa63e958
|
155 156 157 |
STATIC int xfs_bulkstat_one_fmt( void __user *ubuffer, |
65fbaf248
|
158 159 |
int ubsize, int *ubused, |
faa63e958
|
160 161 |
const xfs_bstat_t *buffer) { |
65fbaf248
|
162 163 |
if (ubsize < sizeof(*buffer)) return XFS_ERROR(ENOMEM); |
faa63e958
|
164 |
if (copy_to_user(ubuffer, buffer, sizeof(*buffer))) |
65fbaf248
|
165 166 167 168 |
return XFS_ERROR(EFAULT); if (ubused) *ubused = sizeof(*buffer); return 0; |
faa63e958
|
169 |
} |
2ee4fa5cb
|
170 171 172 173 174 175 |
int xfs_bulkstat_one( xfs_mount_t *mp, /* mount point for filesystem */ xfs_ino_t ino, /* inode number to get data for */ void __user *buffer, /* buffer to place output in */ int ubsize, /* size of buffer */ |
2ee4fa5cb
|
176 |
int *ubused, /* bytes used by me */ |
2ee4fa5cb
|
177 178 179 |
int *stat) /* BULKSTAT_RV_... */ { return xfs_bulkstat_one_int(mp, ino, buffer, ubsize, |
7b6259e7a
|
180 |
xfs_bulkstat_one_fmt, ubused, stat); |
8b56f083c
|
181 |
} |
cd57e594a
|
182 |
#define XFS_BULKSTAT_UBLEFT(ubleft) ((ubleft) >= statstruct_size) |
8b56f083c
|
183 |
/* |
1da177e4c
|
184 185 186 187 188 189 190 191 |
* Return stat information in bulk (by-inode) for the filesystem. */ int /* error status */ xfs_bulkstat( xfs_mount_t *mp, /* mount point for filesystem */ xfs_ino_t *lastinop, /* last inode returned */ int *ubcountp, /* size of buffer/count returned */ bulkstat_one_pf formatter, /* func that'd fill a single buf */ |
1da177e4c
|
192 193 |
size_t statstruct_size, /* sizeof struct filling */ char __user *ubuffer, /* buffer with inode stats */ |
c41564b5a
|
194 |
int *done) /* 1 if there are more stats to get */ |
1da177e4c
|
195 196 197 198 199 200 201 202 203 204 205 206 207 |
{ xfs_agblock_t agbno=0;/* allocation group block number */ xfs_buf_t *agbp; /* agi header buffer */ xfs_agi_t *agi; /* agi header data */ xfs_agino_t agino; /* inode # in allocation group */ xfs_agnumber_t agno; /* allocation group number */ xfs_daddr_t bno; /* inode cluster start daddr */ int chunkidx; /* current index into inode chunk */ int clustidx; /* current index into inode cluster */ xfs_btree_cur_t *cur; /* btree cursor for ialloc btree */ int end_of_ag; /* set if we've seen the ag end */ int error; /* error code */ int fmterror;/* bulkstat formatter result */ |
1da177e4c
|
208 209 |
int i; /* loop index */ int icount; /* count of inodes good in irbuf */ |
215101c36
|
210 |
size_t irbsize; /* size of irec buffer in bytes */ |
1da177e4c
|
211 |
xfs_ino_t ino; /* inode number (filesystem) */ |
262750933
|
212 213 214 |
xfs_inobt_rec_incore_t *irbp; /* current irec buffer pointer */ xfs_inobt_rec_incore_t *irbuf; /* start of irec buffer */ xfs_inobt_rec_incore_t *irbufend; /* end of good irec buffer entries */ |
cd57e594a
|
215 |
xfs_ino_t lastino; /* last inode number returned */ |
1da177e4c
|
216 217 218 219 220 221 222 223 224 225 226 227 |
int nbcluster; /* # of blocks in a cluster */ int nicluster; /* # of inodes in a cluster */ int nimask; /* mask for inode clusters */ int nirbuf; /* size of irbuf */ int rval; /* return value error code */ int tmp; /* result value from btree calls */ int ubcount; /* size of user's buffer */ int ubleft; /* bytes left in user's buffer */ char __user *ubufp; /* pointer into user's buffer */ int ubelem; /* spaces used in user's buffer */ int ubused; /* bytes used by formatter */ xfs_buf_t *bp; /* ptr to on-disk inode cluster buf */ |
1da177e4c
|
228 229 230 231 232 |
/* * Get the last inode value, see if there's nothing to do. */ ino = (xfs_ino_t)*lastinop; |
cd57e594a
|
233 |
lastino = ino; |
1da177e4c
|
234 235 236 237 238 239 240 241 |
agno = XFS_INO_TO_AGNO(mp, ino); agino = XFS_INO_TO_AGINO(mp, ino); if (agno >= mp->m_sb.sb_agcount || ino != XFS_AGINO_TO_INO(mp, agno, agino)) { *done = 1; *ubcountp = 0; return 0; } |
cd57e594a
|
242 243 244 |
if (!ubcountp || *ubcountp <= 0) { return EINVAL; } |
1da177e4c
|
245 246 247 248 249 250 251 252 253 254 255 |
ubcount = *ubcountp; /* statstruct's */ ubleft = ubcount * statstruct_size; /* bytes */ *ubcountp = ubelem = 0; *done = 0; fmterror = 0; ubufp = ubuffer; nicluster = mp->m_sb.sb_blocksize >= XFS_INODE_CLUSTER_SIZE(mp) ? mp->m_sb.sb_inopblock : (XFS_INODE_CLUSTER_SIZE(mp) >> mp->m_sb.sb_inodelog); nimask = ~(nicluster - 1); nbcluster = nicluster >> mp->m_sb.sb_inopblog; |
bdfb04301
|
256 257 258 |
irbuf = kmem_zalloc_greedy(&irbsize, PAGE_SIZE, PAGE_SIZE * 4); if (!irbuf) return ENOMEM; |
bb3c7d293
|
259 |
nirbuf = irbsize / sizeof(*irbuf); |
1da177e4c
|
260 261 262 263 264 |
/* * Loop over the allocation groups, starting from the last * inode returned; 0 means start of the allocation group. */ rval = 0; |
cd57e594a
|
265 266 |
while (XFS_BULKSTAT_UBLEFT(ubleft) && agno < mp->m_sb.sb_agcount) { cond_resched(); |
1da177e4c
|
267 |
bp = NULL; |
1da177e4c
|
268 |
error = xfs_ialloc_read_agi(mp, NULL, agno, &agbp); |
1da177e4c
|
269 270 271 272 273 274 275 276 277 278 279 280 |
if (error) { /* * Skip this allocation group and go to the next one. */ agno++; agino = 0; continue; } agi = XFS_BUF_TO_AGI(agbp); /* * Allocate and initialize a btree cursor for ialloc btree. */ |
561f7d173
|
281 |
cur = xfs_inobt_init_cursor(mp, NULL, agbp, agno); |
1da177e4c
|
282 283 284 285 286 287 288 289 |
irbp = irbuf; irbufend = irbuf + nirbuf; end_of_ag = 0; /* * If we're returning in the middle of an allocation group, * we need to get the remainder of the chunk we're in. */ if (agino > 0) { |
2e287a731
|
290 |
xfs_inobt_rec_incore_t r; |
1da177e4c
|
291 292 293 |
/* * Lookup the inode chunk that this inode lives in. */ |
218755052
|
294 295 |
error = xfs_inobt_lookup(cur, agino, XFS_LOOKUP_LE, &tmp); |
1da177e4c
|
296 297 298 |
if (!error && /* no I/O error */ tmp && /* lookup succeeded */ /* got the record, should always work */ |
2e287a731
|
299 |
!(error = xfs_inobt_get_rec(cur, &r, &i)) && |
1da177e4c
|
300 301 |
i == 1 && /* this is the right chunk */ |
2e287a731
|
302 |
agino < r.ir_startino + XFS_INODES_PER_CHUNK && |
1da177e4c
|
303 |
/* lastino was not last in chunk */ |
2e287a731
|
304 |
(chunkidx = agino - r.ir_startino + 1) < |
1da177e4c
|
305 306 |
XFS_INODES_PER_CHUNK && /* there are some left allocated */ |
9d87c3192
|
307 |
xfs_inobt_maskn(chunkidx, |
2e287a731
|
308 309 |
XFS_INODES_PER_CHUNK - chunkidx) & ~r.ir_free) { |
1da177e4c
|
310 311 312 313 314 315 |
/* * Grab the chunk record. Mark all the * uninteresting inodes (because they're * before our start point) free. */ for (i = 0; i < chunkidx; i++) { |
2e287a731
|
316 317 |
if (XFS_INOBT_MASK(i) & ~r.ir_free) r.ir_freecount++; |
1da177e4c
|
318 |
} |
2e287a731
|
319 320 321 322 |
r.ir_free |= xfs_inobt_maskn(0, chunkidx); irbp->ir_startino = r.ir_startino; irbp->ir_freecount = r.ir_freecount; irbp->ir_free = r.ir_free; |
1da177e4c
|
323 |
irbp++; |
2e287a731
|
324 325 |
agino = r.ir_startino + XFS_INODES_PER_CHUNK; icount = XFS_INODES_PER_CHUNK - r.ir_freecount; |
1da177e4c
|
326 327 328 329 330 331 332 333 334 335 336 337 |
} else { /* * If any of those tests failed, bump the * inode number (just in case). */ agino++; icount = 0; } /* * In any case, increment to the next record. */ if (!error) |
637aa50f4
|
338 |
error = xfs_btree_increment(cur, 0, &tmp); |
1da177e4c
|
339 340 341 342 |
} else { /* * Start of ag. Lookup the first inode chunk. */ |
218755052
|
343 |
error = xfs_inobt_lookup(cur, 0, XFS_LOOKUP_GE, &tmp); |
1da177e4c
|
344 345 346 347 348 349 350 |
icount = 0; } /* * Loop through inode btree records in this ag, * until we run out of inodes or space in the buffer. */ while (irbp < irbufend && icount < ubcount) { |
2e287a731
|
351 |
xfs_inobt_rec_incore_t r; |
1da177e4c
|
352 353 354 355 356 357 358 |
/* * Loop as long as we're unable to read the * inode btree. */ while (error) { agino += XFS_INODES_PER_CHUNK; if (XFS_AGINO_TO_AGBNO(mp, agino) >= |
16259e7d9
|
359 |
be32_to_cpu(agi->agi_length)) |
1da177e4c
|
360 |
break; |
218755052
|
361 362 |
error = xfs_inobt_lookup(cur, agino, XFS_LOOKUP_GE, &tmp); |
cd57e594a
|
363 |
cond_resched(); |
1da177e4c
|
364 365 366 367 368 |
} /* * If ran off the end of the ag either with an error, * or the normal way, set end and stop collecting. */ |
2e287a731
|
369 370 371 372 373 374 375 |
if (error) { end_of_ag = 1; break; } error = xfs_inobt_get_rec(cur, &r, &i); if (error || i == 0) { |
1da177e4c
|
376 377 378 |
end_of_ag = 1; break; } |
2e287a731
|
379 |
|
1da177e4c
|
380 381 |
/* * If this chunk has any allocated inodes, save it. |
262750933
|
382 |
* Also start read-ahead now for this chunk. |
1da177e4c
|
383 |
*/ |
2e287a731
|
384 |
if (r.ir_freecount < XFS_INODES_PER_CHUNK) { |
262750933
|
385 386 387 388 389 |
/* * Loop over all clusters in the next chunk. * Do a readahead if there are any allocated * inodes in that cluster. */ |
2e287a731
|
390 391 |
agbno = XFS_AGINO_TO_AGBNO(mp, r.ir_startino); for (chunkidx = 0; |
262750933
|
392 393 394 |
chunkidx < XFS_INODES_PER_CHUNK; chunkidx += nicluster, agbno += nbcluster) { |
2e287a731
|
395 396 |
if (xfs_inobt_maskn(chunkidx, nicluster) & ~r.ir_free) |
262750933
|
397 398 399 |
xfs_btree_reada_bufs(mp, agno, agbno, nbcluster); } |
2e287a731
|
400 401 402 |
irbp->ir_startino = r.ir_startino; irbp->ir_freecount = r.ir_freecount; irbp->ir_free = r.ir_free; |
1da177e4c
|
403 |
irbp++; |
2e287a731
|
404 |
icount += XFS_INODES_PER_CHUNK - r.ir_freecount; |
1da177e4c
|
405 406 407 408 |
} /* * Set agino to after this chunk and bump the cursor. */ |
2e287a731
|
409 |
agino = r.ir_startino + XFS_INODES_PER_CHUNK; |
637aa50f4
|
410 |
error = xfs_btree_increment(cur, 0, &tmp); |
cd57e594a
|
411 |
cond_resched(); |
1da177e4c
|
412 413 414 415 416 417 418 419 420 421 422 423 424 |
} /* * Drop the btree buffers and the agi buffer. * We can't hold any of the locks these represent * when calling iget. */ xfs_btree_del_cursor(cur, XFS_BTREE_NOERROR); xfs_buf_relse(agbp); /* * Now format all the good inodes into the user's buffer. */ irbufend = irbp; for (irbp = irbuf; |
cd57e594a
|
425 |
irbp < irbufend && XFS_BULKSTAT_UBLEFT(ubleft); irbp++) { |
1da177e4c
|
426 |
/* |
1da177e4c
|
427 428 |
* Now process this chunk of inodes. */ |
262750933
|
429 |
for (agino = irbp->ir_startino, chunkidx = clustidx = 0; |
cd57e594a
|
430 |
XFS_BULKSTAT_UBLEFT(ubleft) && |
262750933
|
431 |
irbp->ir_freecount < XFS_INODES_PER_CHUNK; |
1da177e4c
|
432 433 434 435 436 437 438 |
chunkidx++, clustidx++, agino++) { ASSERT(chunkidx < XFS_INODES_PER_CHUNK); /* * Recompute agbno if this is the * first inode of the cluster. * * Careful with clustidx. There can be |
9da096fd1
|
439 |
* multiple clusters per chunk, a single |
1da177e4c
|
440 441 442 443 444 445 446 447 448 449 450 |
* cluster per chunk or a cluster that has * inodes represented from several different * chunks (if blocksize is large). * * Because of this, the starting clustidx is * initialized to zero in this loop but must * later be reset after reading in the cluster * buffer. */ if ((chunkidx & (nicluster - 1)) == 0) { agbno = XFS_AGINO_TO_AGBNO(mp, |
262750933
|
451 |
irbp->ir_startino) + |
1da177e4c
|
452 453 |
((chunkidx & nimask) >> mp->m_sb.sb_inopblog); |
1da177e4c
|
454 |
} |
c2cba57e8
|
455 456 |
ino = XFS_AGINO_TO_INO(mp, agno, agino); bno = XFS_AGB_TO_DADDR(mp, agno, agbno); |
1da177e4c
|
457 458 459 |
/* * Skip if this inode is free. */ |
c2cba57e8
|
460 461 |
if (XFS_INOBT_MASK(chunkidx) & irbp->ir_free) { lastino = ino; |
1da177e4c
|
462 |
continue; |
c2cba57e8
|
463 |
} |
1da177e4c
|
464 465 466 467 |
/* * Count used inodes as free so we can tell * when the chunk is used up. */ |
262750933
|
468 |
irbp->ir_freecount++; |
1da177e4c
|
469 470 471 |
/* * Get the inode and fill in a single buffer. |
1da177e4c
|
472 473 |
*/ ubused = statstruct_size; |
7b6259e7a
|
474 |
error = formatter(mp, ino, ubufp, ubleft, |
7dce11dba
|
475 |
&ubused, &fmterror); |
1da177e4c
|
476 |
if (fmterror == BULKSTAT_RV_NOTHING) { |
cd57e594a
|
477 478 |
if (error && error != ENOENT && error != EINVAL) { |
e132f54ce
|
479 |
ubleft = 0; |
cd57e594a
|
480 481 482 483 |
rval = error; break; } lastino = ino; |
1da177e4c
|
484 485 486 487 488 489 490 491 492 493 494 495 496 497 |
continue; } if (fmterror == BULKSTAT_RV_GIVEUP) { ubleft = 0; ASSERT(error); rval = error; break; } if (ubufp) ubufp += ubused; ubleft -= ubused; ubelem++; lastino = ino; } |
cd57e594a
|
498 499 |
cond_resched(); |
1da177e4c
|
500 501 502 503 504 505 506 507 |
} if (bp) xfs_buf_relse(bp); /* * Set up for the next loop iteration. */ |
cd57e594a
|
508 |
if (XFS_BULKSTAT_UBLEFT(ubleft)) { |
1da177e4c
|
509 510 511 |
if (end_of_ag) { agno++; agino = 0; |
cd57e594a
|
512 513 |
} else agino = XFS_INO_TO_AGINO(mp, lastino); |
1da177e4c
|
514 515 516 517 518 519 |
} else break; } /* * Done, we're either out of filesystem or space to put the data. */ |
bdfb04301
|
520 |
kmem_free_large(irbuf); |
1da177e4c
|
521 |
*ubcountp = ubelem; |
cd57e594a
|
522 523 524 525 526 |
/* * Found some inodes, return them now and return the error next time. */ if (ubelem) rval = 0; |
1da177e4c
|
527 528 529 530 531 532 533 534 535 536 537 538 539 540 541 542 543 544 545 546 547 548 549 |
if (agno >= mp->m_sb.sb_agcount) { /* * If we ran out of filesystem, mark lastino as off * the end of the filesystem, so the next call * will return immediately. */ *lastinop = (xfs_ino_t)XFS_AGINO_TO_INO(mp, agno, 0); *done = 1; } else *lastinop = (xfs_ino_t)lastino; return rval; } /* * Return stat information in bulk (by-inode) for the filesystem. * Special case for non-sequential one inode bulkstat. */ int /* error status */ xfs_bulkstat_single( xfs_mount_t *mp, /* mount point for filesystem */ xfs_ino_t *lastinop, /* inode to return */ char __user *buffer, /* buffer with inode stats */ |
c41564b5a
|
550 |
int *done) /* 1 if there are more stats to get */ |
1da177e4c
|
551 552 553 554 555 556 557 558 559 560 561 562 563 564 565 566 |
{ int count; /* count value for bulkstat call */ int error; /* return value */ xfs_ino_t ino; /* filesystem inode number */ int res; /* result from bs1 */ /* * note that requesting valid inode numbers which are not allocated * to inodes will most likely cause xfs_itobp to generate warning * messages about bad magic numbers. This is ok. The fact that * the inode isn't actually an inode is handled by the * error check below. Done this way to make the usual case faster * at the expense of the error case. */ ino = (xfs_ino_t)*lastinop; |
7b6259e7a
|
567 |
error = xfs_bulkstat_one(mp, ino, buffer, sizeof(xfs_bstat_t), 0, &res); |
1da177e4c
|
568 569 570 571 572 573 574 575 |
if (error) { /* * Special case way failed, do it the "long" way * to see if that works. */ (*lastinop)--; count = 1; if (xfs_bulkstat(mp, lastinop, &count, xfs_bulkstat_one, |
7dce11dba
|
576 |
sizeof(xfs_bstat_t), buffer, done)) |
1da177e4c
|
577 578 579 580 581 582 583 584 585 586 |
return error; if (count == 0 || (xfs_ino_t)*lastinop != ino) return error == EFSCORRUPTED ? XFS_ERROR(EINVAL) : error; else return 0; } *done = 0; return 0; } |
faa63e958
|
587 588 589 590 591 592 593 594 595 596 597 598 |
int xfs_inumbers_fmt( void __user *ubuffer, /* buffer to write to */ const xfs_inogrp_t *buffer, /* buffer to read from */ long count, /* # of elements to read */ long *written) /* # of bytes written */ { if (copy_to_user(ubuffer, buffer, count * sizeof(*buffer))) return -EFAULT; *written = count * sizeof(*buffer); return 0; } |
1da177e4c
|
599 600 601 602 603 604 605 606 |
/* * Return inode number table for the filesystem. */ int /* error status */ xfs_inumbers( xfs_mount_t *mp, /* mount point for filesystem */ xfs_ino_t *lastino, /* last inode returned */ int *count, /* size of buffer/count returned */ |
faa63e958
|
607 608 |
void __user *ubuffer,/* buffer with inode descriptions */ inumbers_fmt_pf formatter) |
1da177e4c
|
609 610 611 612 613 614 615 616 617 |
{ xfs_buf_t *agbp; xfs_agino_t agino; xfs_agnumber_t agno; int bcount; xfs_inogrp_t *buffer; int bufidx; xfs_btree_cur_t *cur; int error; |
2e287a731
|
618 |
xfs_inobt_rec_incore_t r; |
1da177e4c
|
619 620 621 622 623 624 625 626 627 628 |
int i; xfs_ino_t ino; int left; int tmp; ino = (xfs_ino_t)*lastino; agno = XFS_INO_TO_AGNO(mp, ino); agino = XFS_INO_TO_AGINO(mp, ino); left = *count; *count = 0; |
e6a4b37f3
|
629 |
bcount = MIN(left, (int)(PAGE_SIZE / sizeof(*buffer))); |
1da177e4c
|
630 631 632 633 634 635 |
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) { |
1da177e4c
|
636 |
error = xfs_ialloc_read_agi(mp, NULL, agno, &agbp); |
1da177e4c
|
637 638 639 640 641 642 643 644 645 646 647 |
if (error) { /* * If we can't read the AGI of this ag, * then just skip to the next one. */ ASSERT(cur == NULL); agbp = NULL; agno++; agino = 0; continue; } |
561f7d173
|
648 |
cur = xfs_inobt_init_cursor(mp, NULL, agbp, agno); |
218755052
|
649 650 |
error = xfs_inobt_lookup(cur, agino, XFS_LOOKUP_GE, &tmp); |
1da177e4c
|
651 652 653 654 655 656 |
if (error) { xfs_btree_del_cursor(cur, XFS_BTREE_ERROR); cur = NULL; xfs_buf_relse(agbp); agbp = NULL; /* |
59c51591a
|
657 |
* Move up the last inode in the current |
1da177e4c
|
658 659 660 661 662 663 664 |
* chunk. The lookup_ge will always get * us the first inode in the next chunk. */ agino += XFS_INODES_PER_CHUNK - 1; continue; } } |
2e287a731
|
665 666 |
error = xfs_inobt_get_rec(cur, &r, &i); if (error || i == 0) { |
1da177e4c
|
667 668 669 670 671 672 673 674 |
xfs_buf_relse(agbp); agbp = NULL; xfs_btree_del_cursor(cur, XFS_BTREE_NOERROR); cur = NULL; agno++; agino = 0; continue; } |
2e287a731
|
675 676 677 678 679 680 |
agino = r.ir_startino + XFS_INODES_PER_CHUNK - 1; buffer[bufidx].xi_startino = XFS_AGINO_TO_INO(mp, agno, r.ir_startino); buffer[bufidx].xi_alloccount = XFS_INODES_PER_CHUNK - r.ir_freecount; buffer[bufidx].xi_allocmask = ~r.ir_free; |
1da177e4c
|
681 682 683 |
bufidx++; left--; if (bufidx == bcount) { |
faa63e958
|
684 685 |
long written; if (formatter(ubuffer, buffer, bufidx, &written)) { |
1da177e4c
|
686 687 688 |
error = XFS_ERROR(EFAULT); break; } |
faa63e958
|
689 |
ubuffer += written; |
1da177e4c
|
690 691 692 693 |
*count += bufidx; bufidx = 0; } if (left) { |
637aa50f4
|
694 |
error = xfs_btree_increment(cur, 0, &tmp); |
1da177e4c
|
695 696 697 698 699 700 701 702 703 704 705 706 707 708 709 710 |
if (error) { xfs_btree_del_cursor(cur, XFS_BTREE_ERROR); cur = NULL; xfs_buf_relse(agbp); agbp = NULL; /* * The agino value has already been bumped. * Just try to skip up to it. */ agino += XFS_INODES_PER_CHUNK; continue; } } } if (!error) { if (bufidx) { |
faa63e958
|
711 712 |
long written; if (formatter(ubuffer, buffer, bufidx, &written)) |
1da177e4c
|
713 714 715 716 717 718 |
error = XFS_ERROR(EFAULT); else *count += bufidx; } *lastino = XFS_AGINO_TO_INO(mp, agno, agino); } |
f0e2d93c2
|
719 |
kmem_free(buffer); |
1da177e4c
|
720 721 722 723 724 725 726 |
if (cur) xfs_btree_del_cursor(cur, (error ? XFS_BTREE_ERROR : XFS_BTREE_NOERROR)); if (agbp) xfs_buf_relse(agbp); return error; } |