1
0
Fork 0
util-linux/libmount/samples/listmount.c
Daniel Baumann c36e531662
Adding upstream version 2.41.
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
2025-06-21 11:26:35 +02:00

168 lines
4.3 KiB
C

/*
* Copyright (C) 2024 Karel Zak <kzak@redhat.com>
*
* This file may be redistributed under the terms of the
* GNU Lesser General Public License.
*/
#include <stdlib.h>
#include "c.h"
#include "strutils.h"
#include "timeutils.h"
#include "pathnames.h"
#include "libmount.h"
#include "mount-api-utils.h" /* fallback for old linux/mount.h */
static void __iter_table( struct libmnt_table *tb,
struct libmnt_iter *itr, int output, int reverse)
{
struct libmnt_fs *fs = NULL;
int rc;
mnt_reset_iter(itr, reverse ? MNT_ITER_BACKWARD : MNT_ITER_FORWARD);
while ((rc = mnt_table_next_fs(tb, itr, &fs)) == 0) {
const char *tgt = mnt_fs_get_target(fs);
const char *type = mnt_fs_get_fstype(fs);
if (output)
printf (" %15s %s\n", type, tgt);
}
if (rc < 0)
warn("cannot iterate on filesystems");
}
#define fetch_data(t, i) __iter_table(t, i, 0, 0)
#define print_table(t, i) __iter_table(t, i, 1, 0)
#define print_table_reverse(t, i) __iter_table(t, i, 1, 1)
int main(int argc, char *argv[])
{
struct libmnt_table *tb;
struct libmnt_statmnt *sm;
struct libmnt_iter *itr;
struct timeval start, end;
uint64_t id = 0;
double sec_lsmnt, sec_lsstmnt, sec_mountinfo;
mnt_init_debug(0);
if (argc == 2) {
const char *arg = argv[1];
if (!isdigit_string(arg))
mnt_id_from_path(arg, &id, NULL);
else
id = strtou64_or_err(arg, "cannot ID");
}
itr = mnt_new_iter(MNT_ITER_FORWARD);
if (!itr)
err(MNT_EX_SYSERR, "failed to initialize libmount iterator");
tb = mnt_new_table();
if (!tb)
err(EXIT_FAILURE, "failed to allocate table handler");
if (id)
mnt_table_listmount_set_id(tb, id);
/*
* A) listmount() and statmount() based table
*/
sm = mnt_new_statmnt();
if (!sm)
err(EXIT_FAILURE, "failed to allocate statmnt handler");
/* Without this mask setting, the library will make two statmount() calls
* for each node. */
#if defined(STATMOUNT_MNT_POINT) && defined(STATMOUNT_FS_TYPE)
mnt_statmnt_set_mask(sm, STATMOUNT_MNT_POINT | STATMOUNT_FS_TYPE);
#endif
/* force fetch all data
mnt_statmnt_set_mask(sm,
STATMOUNT_SB_BASIC |
STATMOUNT_MNT_BASIC |
STATMOUNT_PROPAGATE_FROM |
STATMOUNT_MNT_ROOT |
STATMOUNT_MNT_POINT |
STATMOUNT_FS_TYPE
STATMOUNT_MNT_OPTS);
*/
/* enable don-demand statmount() call for all filesystems in the table */
mnt_table_refer_statmnt(tb, sm);
/* listmount() only */
gettimeofday(&start, NULL);
if (mnt_table_fetch_listmount(tb) != 0)
warn("failed to read mount table by listmount()");
gettimeofday(&end, NULL);
sec_lsmnt = time_diff(&end, &start);
/* force statmount() for all nodes */
fetch_data(tb, itr);
gettimeofday(&end, NULL);
sec_lsstmnt = time_diff(&end, &start);
fprintf(stdout, "listmount() based table:\n");
print_table(tb, itr);
/* disable statmount() and listmount(); reset table */
mnt_statmnt_disable_fetching(sm, 1);
mnt_table_enable_listmount(tb, 0);
mnt_reset_table(tb);
/*
* B) /proc/self/mountinfo based table
*/
gettimeofday(&start, NULL);
mnt_table_parse_file(tb, _PATH_PROC_MOUNTINFO);
gettimeofday(&end, NULL);
sec_mountinfo = time_diff(&end, &start);
fprintf(stdout, "\nprocfs based table:\n");
print_table(tb, itr);
fprintf(stdout, "\n"
"%f sec listmount()\n"
"%f sec listmount()+statmount()\n"
"%f sec /proc/sef/mountinfo"
"\n\n",
sec_lsmnt, sec_lsstmnt, sec_mountinfo);
mnt_reset_table(tb);
/*
* C) Instead of reading the entire mount table with one listmount() call, read
* it in smaller steps. This is particularly useful for systems with large
* mount tables, where we may only need to access one specific node (usually the
* last one).
*
* By default, libmount reads 512 nodes in one call. To test this sample
* on normal systems, we will reduce this number to 5 nodes. The listmount()
* function is used as a backend for regular mnt_table_next_fs().
* There is no need to make any changes to the application, just enable
* on-demand listmount() by using mnt_table_enable_listmount().
*/
if (mnt_table_listmount_set_stepsiz(tb, 5) != 0)
warn("failed to initialize listmount()");
mnt_table_enable_listmount(tb, 1);
/* enable also statmount() */
mnt_statmnt_disable_fetching(sm, 0);
fprintf(stdout, "\nlistmount() - small steps (reverse):\n");
print_table_reverse(tb, itr);
mnt_unref_table(tb);
mnt_unref_statmnt(sm);
mnt_free_iter(itr);
return EXIT_SUCCESS;
}