Line data Source code
1 : // SPDX-License-Identifier: GPL-2.0
2 : /*
3 : * Copyright (c) 2000-2002,2005 Silicon Graphics, Inc.
4 : * All Rights Reserved.
5 : */
6 : #include "xfs.h"
7 : #include "xfs_fs.h"
8 : #include "xfs_shared.h"
9 : #include "xfs_format.h"
10 : #include "xfs_log_format.h"
11 : #include "xfs_trans_resv.h"
12 : #include "xfs_mount.h"
13 : #include "xfs_inode.h"
14 : #include "xfs_btree.h"
15 : #include "xfs_ialloc.h"
16 : #include "xfs_ialloc_btree.h"
17 : #include "xfs_iwalk.h"
18 : #include "xfs_itable.h"
19 : #include "xfs_error.h"
20 : #include "xfs_icache.h"
21 : #include "xfs_health.h"
22 : #include "xfs_trans.h"
23 :
24 : /*
25 : * Bulk Stat
26 : * =========
27 : *
28 : * Use the inode walking functions to fill out struct xfs_bulkstat for every
29 : * allocated inode, then pass the stat information to some externally provided
30 : * iteration function.
31 : */
32 :
33 : struct xfs_bstat_chunk {
34 : bulkstat_one_fmt_pf formatter;
35 : struct xfs_ibulk *breq;
36 : struct xfs_bulkstat *buf;
37 : };
38 :
39 : static inline bool
40 : want_metadir(
41 : struct xfs_inode *ip,
42 : struct xfs_ibulk *breq)
43 : {
44 69059838344 : return xfs_is_metadir_inode(ip) &&
45 69042443472 : S_ISDIR(VFS_I(ip)->i_mode) &&
46 4313871 : (breq->flags & XFS_IBULK_METADIR);
47 : }
48 :
49 : /*
50 : * Fill out the bulkstat info for a single inode and report it somewhere.
51 : *
52 : * bc->breq->lastino is effectively the inode cursor as we walk through the
53 : * filesystem. Therefore, we update it any time we need to move the cursor
54 : * forward, regardless of whether or not we're sending any bstat information
55 : * back to userspace. If the inode is internal metadata or, has been freed
56 : * out from under us, we just simply keep going.
57 : *
58 : * However, if any other type of error happens we want to stop right where we
59 : * are so that userspace will call back with exact number of the bad inode and
60 : * we can send back an error code.
61 : *
62 : * Note that if the formatter tells us there's no space left in the buffer we
63 : * move the cursor forward and abort the walk.
64 : */
65 : STATIC int
66 68710239324 : xfs_bulkstat_one_int(
67 : struct xfs_mount *mp,
68 : struct mnt_idmap *idmap,
69 : struct xfs_trans *tp,
70 : xfs_ino_t ino,
71 : struct xfs_bstat_chunk *bc)
72 : {
73 68710239324 : struct user_namespace *sb_userns = mp->m_super->s_user_ns;
74 68710239324 : struct xfs_inode *ip; /* incore inode pointer */
75 68710239324 : struct inode *inode;
76 68710239324 : struct xfs_bulkstat *buf = bc->buf;
77 68710239324 : xfs_extnum_t nextents;
78 68710239324 : int error = -EINVAL;
79 68710239324 : vfsuid_t vfsuid;
80 68710239324 : vfsgid_t vfsgid;
81 :
82 68710239324 : error = xfs_iget(mp, tp, ino,
83 : (XFS_IGET_DONTCACHE | XFS_IGET_UNTRUSTED),
84 : XFS_ILOCK_SHARED, &ip);
85 68597881350 : if (error == -ENOENT || error == -EINVAL)
86 1191786 : goto out_advance;
87 68596689564 : if (error)
88 2415 : goto out;
89 :
90 68596687149 : ASSERT(ip != NULL);
91 68596687149 : ASSERT(ip->i_imap.im_blkno != 0);
92 68596687149 : inode = VFS_I(ip);
93 68596687149 : vfsuid = i_uid_into_vfsuid(idmap, inode);
94 69066291548 : vfsgid = i_gid_into_vfsgid(idmap, inode);
95 :
96 : /* If we want metadata directories, push out the bare minimum. */
97 69059838344 : if (want_metadir(ip, bc->breq)) {
98 32965 : memset(buf, 0, sizeof(*buf));
99 32965 : buf->bs_ino = ino;
100 32965 : buf->bs_gen = inode->i_generation;
101 32965 : buf->bs_mode = inode->i_mode & S_IFMT;
102 32965 : xfs_bulkstat_health(ip, buf);
103 32965 : buf->bs_version = XFS_BULKSTAT_VERSION_V5;
104 32965 : xfs_iunlock(ip, XFS_ILOCK_SHARED);
105 32965 : xfs_irele(ip);
106 :
107 32965 : error = bc->formatter(bc->breq, buf);
108 32965 : if (!error || error == -ECANCELED)
109 32965 : goto out_advance;
110 0 : goto out;
111 : }
112 :
113 : /* If this is a private inode, don't leak its details to userspace. */
114 69042410507 : if (IS_PRIVATE(inode) || xfs_internal_inum(mp, ino)) {
115 510096912 : xfs_iunlock(ip, XFS_ILOCK_SHARED);
116 17452364 : xfs_irele(ip);
117 17452311 : error = -EINVAL;
118 17452311 : goto out_advance;
119 : }
120 :
121 : /* xfs_iget returns the following without needing
122 : * further change.
123 : */
124 68570200308 : buf->bs_projectid = ip->i_projid;
125 68570200308 : buf->bs_ino = ino;
126 68570200308 : buf->bs_uid = from_kuid(sb_userns, vfsuid_into_kuid(vfsuid));
127 69024763787 : buf->bs_gid = from_kgid(sb_userns, vfsgid_into_kgid(vfsgid));
128 68891312393 : buf->bs_size = ip->i_disk_size;
129 :
130 68891312393 : buf->bs_nlink = inode->i_nlink;
131 68891312393 : buf->bs_atime = inode->i_atime.tv_sec;
132 68891312393 : buf->bs_atime_nsec = inode->i_atime.tv_nsec;
133 68891312393 : buf->bs_mtime = inode->i_mtime.tv_sec;
134 68891312393 : buf->bs_mtime_nsec = inode->i_mtime.tv_nsec;
135 68891312393 : buf->bs_ctime = inode->i_ctime.tv_sec;
136 68891312393 : buf->bs_ctime_nsec = inode->i_ctime.tv_nsec;
137 68891312393 : buf->bs_gen = inode->i_generation;
138 68891312393 : buf->bs_mode = inode->i_mode;
139 :
140 68891312393 : buf->bs_xflags = xfs_ip2xflags(ip);
141 68925764725 : buf->bs_extsize_blks = ip->i_extsize;
142 :
143 68925764725 : nextents = xfs_ifork_nextents(&ip->i_df);
144 68925764725 : if (!(bc->breq->flags & XFS_IBULK_NREXT64))
145 68768538337 : buf->bs_extents = min(nextents, XFS_MAX_EXTCNT_DATA_FORK_SMALL);
146 : else
147 157226388 : buf->bs_extents64 = nextents;
148 :
149 68925764725 : xfs_bulkstat_health(ip, buf);
150 69069649374 : buf->bs_aextents = xfs_ifork_nextents(&ip->i_af);
151 69069649374 : buf->bs_forkoff = xfs_inode_fork_boff(ip);
152 69069649374 : buf->bs_version = XFS_BULKSTAT_VERSION_V5;
153 :
154 69069649374 : if (xfs_has_v3inodes(mp)) {
155 68378580461 : buf->bs_btime = ip->i_crtime.tv_sec;
156 68378580461 : buf->bs_btime_nsec = ip->i_crtime.tv_nsec;
157 68378580461 : if (ip->i_diflags2 & XFS_DIFLAG2_COWEXTSIZE)
158 6423 : buf->bs_cowextsize_blks = ip->i_cowextsize;
159 : }
160 :
161 69069649374 : switch (ip->i_df.if_format) {
162 25838360082 : case XFS_DINODE_FMT_DEV:
163 25838360082 : buf->bs_rdev = sysv_encode_dev(inode->i_rdev);
164 25838360082 : buf->bs_blksize = BLKDEV_IOSIZE;
165 25838360082 : buf->bs_blocks = 0;
166 25838360082 : break;
167 13440188417 : case XFS_DINODE_FMT_LOCAL:
168 13440188417 : buf->bs_rdev = 0;
169 13440188417 : buf->bs_blksize = mp->m_sb.sb_blocksize;
170 13440188417 : buf->bs_blocks = 0;
171 13440188417 : break;
172 29791100875 : case XFS_DINODE_FMT_EXTENTS:
173 : case XFS_DINODE_FMT_BTREE:
174 29791100875 : buf->bs_rdev = 0;
175 29791100875 : buf->bs_blksize = mp->m_sb.sb_blocksize;
176 29791100875 : buf->bs_blocks = ip->i_nblocks + ip->i_delayed_blks;
177 29791100875 : break;
178 : }
179 69069649374 : xfs_iunlock(ip, XFS_ILOCK_SHARED);
180 69045103213 : xfs_irele(ip);
181 :
182 68637786142 : error = bc->formatter(bc->breq, buf);
183 68962339157 : if (error == -ECANCELED)
184 452846291 : goto out_advance;
185 68509492866 : if (error)
186 0 : goto out;
187 :
188 68509492866 : out_advance:
189 : /*
190 : * Advance the cursor to the inode that comes after the one we just
191 : * looked at. We want the caller to move along if the bulkstat
192 : * information was copied successfully; if we tried to grab the inode
193 : * but it's no longer allocated; or if it's internal metadata.
194 : */
195 68981016219 : bc->breq->startino = ino + 1;
196 68981018634 : out:
197 68981018634 : return error;
198 : }
199 :
200 : /* Bulkstat a single inode. */
201 : int
202 1402961 : xfs_bulkstat_one(
203 : struct xfs_ibulk *breq,
204 : bulkstat_one_fmt_pf formatter)
205 : {
206 1402961 : struct xfs_bstat_chunk bc = {
207 : .formatter = formatter,
208 : .breq = breq,
209 : };
210 1402961 : struct xfs_trans *tp;
211 1402961 : int error;
212 :
213 1402961 : if (breq->idmap != &nop_mnt_idmap) {
214 0 : xfs_warn_ratelimited(breq->mp,
215 : "bulkstat not supported inside of idmapped mounts.");
216 0 : return -EINVAL;
217 : }
218 :
219 1402961 : ASSERT(breq->icount == 1);
220 :
221 1402961 : bc.buf = kmem_zalloc(sizeof(struct xfs_bulkstat),
222 : KM_MAYFAIL);
223 1402960 : if (!bc.buf)
224 : return -ENOMEM;
225 :
226 : /*
227 : * Grab an empty transaction so that we can use its recursive buffer
228 : * locking abilities to detect cycles in the inobt without deadlocking.
229 : */
230 1402960 : error = xfs_trans_alloc_empty(breq->mp, &tp);
231 1402962 : if (error)
232 0 : goto out;
233 :
234 1402962 : error = xfs_bulkstat_one_int(breq->mp, breq->idmap, tp,
235 : breq->startino, &bc);
236 1402961 : xfs_trans_cancel(tp);
237 1402963 : out:
238 1402963 : kmem_free(bc.buf);
239 :
240 : /*
241 : * If we reported one inode to userspace then we abort because we hit
242 : * the end of the buffer. Don't leak that back to userspace.
243 : */
244 1402962 : if (error == -ECANCELED)
245 672043 : error = 0;
246 :
247 : return error;
248 : }
249 :
250 : static int
251 68940471877 : xfs_bulkstat_iwalk(
252 : struct xfs_mount *mp,
253 : struct xfs_trans *tp,
254 : xfs_ino_t ino,
255 : void *data)
256 : {
257 68940471877 : struct xfs_bstat_chunk *bc = data;
258 68940471877 : int error;
259 :
260 68940471877 : error = xfs_bulkstat_one_int(mp, bc->breq->idmap, tp, ino, data);
261 : /* bulkstat just skips over missing inodes */
262 69007471463 : if (error == -ENOENT || error == -EINVAL)
263 17913155 : return 0;
264 : return error;
265 : }
266 :
267 : /*
268 : * Check the incoming lastino parameter.
269 : *
270 : * We allow any inode value that could map to physical space inside the
271 : * filesystem because if there are no inodes there, bulkstat moves on to the
272 : * next chunk. In other words, the magic agino value of zero takes us to the
273 : * first chunk in the AG, and an agino value past the end of the AG takes us to
274 : * the first chunk in the next AG.
275 : *
276 : * Therefore we can end early if the requested inode is beyond the end of the
277 : * filesystem or doesn't map properly.
278 : */
279 : static inline bool
280 457545285 : xfs_bulkstat_already_done(
281 : struct xfs_mount *mp,
282 : xfs_ino_t startino)
283 : {
284 457545285 : xfs_agnumber_t agno = XFS_INO_TO_AGNO(mp, startino);
285 457545285 : xfs_agino_t agino = XFS_INO_TO_AGINO(mp, startino);
286 :
287 457545285 : return agno >= mp->m_sb.sb_agcount ||
288 457545786 : startino != XFS_AGINO_TO_INO(mp, agno, agino);
289 : }
290 :
291 : /* Return stat information in bulk (by-inode) for the filesystem. */
292 : int
293 454915155 : xfs_bulkstat(
294 : struct xfs_ibulk *breq,
295 : bulkstat_one_fmt_pf formatter)
296 : {
297 454915155 : struct xfs_bstat_chunk bc = {
298 : .formatter = formatter,
299 : .breq = breq,
300 : };
301 454915155 : struct xfs_trans *tp;
302 454915155 : unsigned int iwalk_flags = 0;
303 454915155 : int error;
304 :
305 454915155 : if (breq->idmap != &nop_mnt_idmap) {
306 0 : xfs_warn_ratelimited(breq->mp,
307 : "bulkstat not supported inside of idmapped mounts.");
308 0 : return -EINVAL;
309 : }
310 454915155 : if (xfs_bulkstat_already_done(breq->mp, breq->startino))
311 : return 0;
312 :
313 454929281 : bc.buf = kmem_zalloc(sizeof(struct xfs_bulkstat),
314 : KM_MAYFAIL);
315 454927008 : if (!bc.buf)
316 : return -ENOMEM;
317 :
318 : /*
319 : * Grab an empty transaction so that we can use its recursive buffer
320 : * locking abilities to detect cycles in the inobt without deadlocking.
321 : */
322 454927008 : error = xfs_trans_alloc_empty(breq->mp, &tp);
323 454927838 : if (error)
324 0 : goto out;
325 :
326 454927838 : if (breq->flags & XFS_IBULK_SAME_AG)
327 15952 : iwalk_flags |= XFS_IWALK_SAME_AG;
328 :
329 454927838 : error = xfs_iwalk(breq->mp, tp, breq->startino, iwalk_flags,
330 : xfs_bulkstat_iwalk, breq->icount, &bc);
331 454932480 : xfs_trans_cancel(tp);
332 454938435 : out:
333 454938435 : kmem_free(bc.buf);
334 :
335 : /*
336 : * We found some inodes, so clear the error status and return them.
337 : * The lastino pointer will point directly at the inode that triggered
338 : * any error that occurred, so on the next call the error will be
339 : * triggered again and propagated to userspace as there will be no
340 : * formatted inodes in the buffer.
341 : */
342 454943180 : if (breq->ocount > 0)
343 453560062 : error = 0;
344 :
345 : return error;
346 : }
347 :
348 : /* Convert bulkstat (v5) to bstat (v1). */
349 : void
350 68822201303 : xfs_bulkstat_to_bstat(
351 : struct xfs_mount *mp,
352 : struct xfs_bstat *bs1,
353 : const struct xfs_bulkstat *bstat)
354 : {
355 : /* memset is needed here because of padding holes in the structure. */
356 68822201303 : memset(bs1, 0, sizeof(struct xfs_bstat));
357 68822201303 : bs1->bs_ino = bstat->bs_ino;
358 68822201303 : bs1->bs_mode = bstat->bs_mode;
359 68822201303 : bs1->bs_nlink = bstat->bs_nlink;
360 68822201303 : bs1->bs_uid = bstat->bs_uid;
361 68822201303 : bs1->bs_gid = bstat->bs_gid;
362 68822201303 : bs1->bs_rdev = bstat->bs_rdev;
363 68822201303 : bs1->bs_blksize = bstat->bs_blksize;
364 68822201303 : bs1->bs_size = bstat->bs_size;
365 68822201303 : bs1->bs_atime.tv_sec = bstat->bs_atime;
366 68822201303 : bs1->bs_mtime.tv_sec = bstat->bs_mtime;
367 68822201303 : bs1->bs_ctime.tv_sec = bstat->bs_ctime;
368 68822201303 : bs1->bs_atime.tv_nsec = bstat->bs_atime_nsec;
369 68822201303 : bs1->bs_mtime.tv_nsec = bstat->bs_mtime_nsec;
370 68822201303 : bs1->bs_ctime.tv_nsec = bstat->bs_ctime_nsec;
371 68822201303 : bs1->bs_blocks = bstat->bs_blocks;
372 68822201303 : bs1->bs_xflags = bstat->bs_xflags;
373 68822201303 : bs1->bs_extsize = XFS_FSB_TO_B(mp, bstat->bs_extsize_blks);
374 68822201303 : bs1->bs_extents = bstat->bs_extents;
375 68822201303 : bs1->bs_gen = bstat->bs_gen;
376 68822201303 : bs1->bs_projid_lo = bstat->bs_projectid & 0xFFFF;
377 68822201303 : bs1->bs_forkoff = bstat->bs_forkoff;
378 68822201303 : bs1->bs_projid_hi = bstat->bs_projectid >> 16;
379 68822201303 : bs1->bs_sick = bstat->bs_sick;
380 68822201303 : bs1->bs_checked = bstat->bs_checked;
381 68822201303 : bs1->bs_cowextsize = XFS_FSB_TO_B(mp, bstat->bs_cowextsize_blks);
382 68822201303 : bs1->bs_dmevmask = 0;
383 68822201303 : bs1->bs_dmstate = 0;
384 68822201303 : bs1->bs_aextents = bstat->bs_aextents;
385 68822201303 : }
386 :
387 : struct xfs_inumbers_chunk {
388 : inumbers_fmt_pf formatter;
389 : struct xfs_ibulk *breq;
390 : };
391 :
392 : /*
393 : * INUMBERS
394 : * ========
395 : * This is how we export inode btree records to userspace, so that XFS tools
396 : * can figure out where inodes are allocated.
397 : */
398 :
399 : /*
400 : * Format the inode group structure and report it somewhere.
401 : *
402 : * Similar to xfs_bulkstat_one_int, lastino is the inode cursor as we walk
403 : * through the filesystem so we move it forward unless there was a runtime
404 : * error. If the formatter tells us the buffer is now full we also move the
405 : * cursor forward and abort the walk.
406 : */
407 : STATIC int
408 3953512 : xfs_inumbers_walk(
409 : struct xfs_mount *mp,
410 : struct xfs_trans *tp,
411 : xfs_agnumber_t agno,
412 : const struct xfs_inobt_rec_incore *irec,
413 : void *data)
414 : {
415 3953512 : struct xfs_inumbers inogrp = {
416 3953512 : .xi_startino = XFS_AGINO_TO_INO(mp, agno, irec->ir_startino),
417 3953512 : .xi_alloccount = irec->ir_count - irec->ir_freecount,
418 3953512 : .xi_allocmask = ~irec->ir_free,
419 : .xi_version = XFS_INUMBERS_VERSION_V5,
420 : };
421 3953512 : struct xfs_inumbers_chunk *ic = data;
422 3953512 : int error;
423 :
424 3953512 : error = ic->formatter(ic->breq, &inogrp);
425 3953290 : if (error && error != -ECANCELED)
426 : return error;
427 :
428 3953290 : ic->breq->startino = XFS_AGINO_TO_INO(mp, agno, irec->ir_startino) +
429 : XFS_INODES_PER_CHUNK;
430 3953290 : return error;
431 : }
432 :
433 : /*
434 : * Return inode number table for the filesystem.
435 : */
436 : int
437 2614753 : xfs_inumbers(
438 : struct xfs_ibulk *breq,
439 : inumbers_fmt_pf formatter)
440 : {
441 2614753 : struct xfs_inumbers_chunk ic = {
442 : .formatter = formatter,
443 : .breq = breq,
444 : };
445 2614753 : struct xfs_trans *tp;
446 2614753 : int error = 0;
447 :
448 2614753 : if (xfs_bulkstat_already_done(breq->mp, breq->startino))
449 : return 0;
450 :
451 : /*
452 : * Grab an empty transaction so that we can use its recursive buffer
453 : * locking abilities to detect cycles in the inobt without deadlocking.
454 : */
455 2614740 : error = xfs_trans_alloc_empty(breq->mp, &tp);
456 2614516 : if (error)
457 0 : goto out;
458 :
459 2614516 : error = xfs_inobt_walk(breq->mp, tp, breq->startino, breq->flags,
460 : xfs_inumbers_walk, breq->icount, &ic);
461 2614213 : xfs_trans_cancel(tp);
462 2614654 : out:
463 :
464 : /*
465 : * We found some inode groups, so clear the error status and return
466 : * them. The lastino pointer will point directly at the inode that
467 : * triggered any error that occurred, so on the next call the error
468 : * will be triggered again and propagated to userspace as there will be
469 : * no formatted inode groups in the buffer.
470 : */
471 2614654 : if (breq->ocount > 0)
472 2479394 : error = 0;
473 :
474 : return error;
475 : }
476 :
477 : /* Convert an inumbers (v5) struct to a inogrp (v1) struct. */
478 : void
479 11596 : xfs_inumbers_to_inogrp(
480 : struct xfs_inogrp *ig1,
481 : const struct xfs_inumbers *ig)
482 : {
483 : /* memset is needed here because of padding holes in the structure. */
484 11596 : memset(ig1, 0, sizeof(struct xfs_inogrp));
485 11596 : ig1->xi_startino = ig->xi_startino;
486 11596 : ig1->xi_alloccount = ig->xi_alloccount;
487 11596 : ig1->xi_allocmask = ig->xi_allocmask;
488 11596 : }
|