]> git.ipfire.org Git - thirdparty/xfsprogs-dev.git/blame - scrub/descr.c
xfs_scrub: don't use statvfs to collect filesystem summary counts
[thirdparty/xfsprogs-dev.git] / scrub / descr.c
CommitLineData
b3f76f94
DW
1// SPDX-License-Identifier: GPL-2.0-or-later
2/*
3 * Copyright (C) 2019 Oracle. All Rights Reserved.
4 * Author: Darrick J. Wong <darrick.wong@oracle.com>
5 */
6#include "xfs.h"
7#include <assert.h>
8#include <sys/statvfs.h>
9#include "platform_defs.h"
10#include "input.h"
11#include "libfrog/paths.h"
12#include "libfrog/ptvar.h"
13#include "xfs_scrub.h"
14#include "common.h"
15#include "descr.h"
16
17/*
18 * Deferred String Description Renderer
19 * ====================================
20 * There are many places in xfs_scrub where some event occurred and we'd like
21 * to be able to print some sort of message describing what happened, and
22 * where. However, we don't know whether we're going to need the description
23 * of where ahead of time and there's little point in spending any time looking
24 * up gettext strings and formatting buffers until we actually need to.
25 *
26 * This code provides enough of a function closure that we are able to record
27 * some information about the program status but defer rendering the textual
28 * description until we know that we need it. Once we've rendered the string
29 * we can skip it for subsequent calls. We use per-thread storage for the
30 * message buffer to amortize the memory allocation across calls.
31 *
32 * On a clean filesystem this can reduce the xfs_scrub runtime by 7-10% by
33 * avoiding unnecessary work.
34 */
35
36static struct ptvar *descr_ptvar;
37
38/* Global buffer for when we aren't running in threaded mode. */
39static char global_dsc_buf[DESCR_BUFSZ];
40
41/*
42 * Render a textual description string using the function and location stored
43 * in the description context.
44 */
45const char *
46__descr_render(
47 struct descr *dsc,
48 const char *file,
49 int line)
50{
51 char *dsc_buf;
52 int ret;
53
54 if (descr_ptvar) {
55 dsc_buf = ptvar_get(descr_ptvar, &ret);
56 if (ret)
57 return _("error finding description buffer");
58 } else
59 dsc_buf = global_dsc_buf;
60
61 ret = dsc->fn(dsc->ctx, dsc_buf, DESCR_BUFSZ, dsc->where);
62 if (ret < 0) {
63 snprintf(dsc_buf, DESCR_BUFSZ,
64_("error %d while rendering description at %s line %d\n"),
65 ret, file, line);
66 }
67
68 return dsc_buf;
69}
70
71/*
72 * Set a new location context for this deferred-rendering string.
73 * The caller is responsible for freeing the old context, if any.
74 */
75void
76descr_set(
77 struct descr *dsc,
78 void *where)
79{
80 dsc->where = where;
81}
82
83/* Allocate all the description string buffers. */
84int
85descr_init_phase(
86 struct scrub_ctx *ctx,
87 unsigned int nr_threads)
88{
89 int ret;
90
91 assert(descr_ptvar == NULL);
2f4422f4 92 ret = -ptvar_alloc(nr_threads, DESCR_BUFSZ, &descr_ptvar);
b3f76f94
DW
93 if (ret)
94 str_liberror(ctx, ret, _("creating description buffer"));
95
96 return ret;
97}
98
99/* Free all the description string buffers. */
100void
101descr_end_phase(void)
102{
103 if (descr_ptvar)
104 ptvar_free(descr_ptvar);
105 descr_ptvar = NULL;
106}