libsysprof-analyze: parse core mount namespace devices

We want to track the core mount namespace, for which the namespace we
use for processes will derive (to be done).
This commit is contained in:
Christian Hergert
2023-05-09 17:20:00 -07:00
parent f01346da90
commit 6290a1736d

View File

@ -32,8 +32,12 @@
#include "sysprof-document-frame-private.h" #include "sysprof-document-frame-private.h"
#include "sysprof-document-mmap.h" #include "sysprof-document-mmap.h"
#include "sysprof-document-symbols-private.h" #include "sysprof-document-symbols-private.h"
#include "sysprof-mount-device-private.h"
#include "sysprof-mount-namespace-private.h"
#include "sysprof-symbolizer-private.h" #include "sysprof-symbolizer-private.h"
#include "line-reader-private.h"
struct _SysprofDocument struct _SysprofDocument
{ {
GObject parent_instance; GObject parent_instance;
@ -50,6 +54,8 @@ struct _SysprofDocument
GHashTable *files_first_position; GHashTable *files_first_position;
GHashTable *pid_to_mmaps; GHashTable *pid_to_mmaps;
SysprofMountNamespace *mount_namespace;
GMutex strings_mutex; GMutex strings_mutex;
GHashTable *strings; GHashTable *strings;
@ -112,6 +118,18 @@ _sysprof_document_traceables (SysprofDocument *self)
return self->traceables; return self->traceables;
} }
static void
decode_space (gchar **str)
{
/* Replace encoded space "\040" with ' ' */
if (strstr (*str, "\\040"))
{
g_auto(GStrv) parts = g_strsplit (*str, "\\040", 0);
g_free (*str);
*str = g_strjoinv (" ", parts);
}
}
static inline gboolean static inline gboolean
has_null_byte (const char *str, has_null_byte (const char *str,
const char *endptr) const char *endptr)
@ -140,6 +158,8 @@ sysprof_document_finalize (GObject *object)
g_clear_pointer (&self->mmaps, gtk_bitset_unref); g_clear_pointer (&self->mmaps, gtk_bitset_unref);
g_clear_pointer (&self->file_chunks, gtk_bitset_unref); g_clear_pointer (&self->file_chunks, gtk_bitset_unref);
g_clear_object (&self->mount_namespace);
g_clear_pointer (&self->files_first_position, g_hash_table_unref); g_clear_pointer (&self->files_first_position, g_hash_table_unref);
g_mutex_clear (&self->strings_mutex); g_mutex_clear (&self->strings_mutex);
@ -170,6 +190,8 @@ sysprof_document_init (SysprofDocument *self)
self->files_first_position = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, NULL); self->files_first_position = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, NULL);
self->pid_to_mmaps = g_hash_table_new_full (NULL, NULL, NULL, (GDestroyNotify)g_ptr_array_unref); self->pid_to_mmaps = g_hash_table_new_full (NULL, NULL, NULL, (GDestroyNotify)g_ptr_array_unref);
self->mount_namespace = sysprof_mount_namespace_new ();
} }
static int static int
@ -226,6 +248,82 @@ sysprof_document_load_memory_maps (SysprofDocument *self)
} }
} }
static void
sysprof_document_load_mounts (SysprofDocument *self)
{
g_autoptr(SysprofDocumentFile) file = NULL;
g_autoptr(GBytes) bytes = NULL;
LineReader reader;
const char *contents;
gsize contents_len;
gsize line_len;
char *line;
g_assert (SYSPROF_IS_DOCUMENT (self));
if (!(file = sysprof_document_lookup_file (self, "/proc/mounts")) ||
!(bytes = sysprof_document_file_dup_bytes (file)))
return;
contents = g_bytes_get_data (bytes, &contents_len);
g_assert (contents != NULL);
g_assert (contents[contents_len] == 0);
line_reader_init (&reader, (char *)contents, contents_len);
while ((line = line_reader_next (&reader, &line_len)))
{
g_autoptr(SysprofMountDevice) mount_device = NULL;
g_auto(GStrv) parts = NULL;
g_autofree char *subvol = NULL;
const char *filesystem;
const char *mountpoint;
const char *device;
const char *options;
line[line_len] = 0;
parts = g_strsplit (line, " ", 5);
/* Field 0: device
* Field 1: mountpoint
* Field 2: filesystem
* Field 3: Options
* .. Ignored ..
*/
if (g_strv_length (parts) != 5)
continue;
for (guint j = 0; parts[j]; j++)
decode_space (&parts[j]);
device = parts[0];
mountpoint = parts[1];
filesystem = parts[2];
options = parts[3];
if (g_strcmp0 (filesystem, "btrfs") == 0)
{
g_auto(GStrv) opts = g_strsplit (options, ",", 0);
for (guint k = 0; opts[k]; k++)
{
if (g_str_has_prefix (opts[k], "subvol="))
{
subvol = g_strdup (opts[k] + strlen ("subvol="));
break;
}
}
}
mount_device = sysprof_mount_device_new ();
sysprof_mount_device_set_id (mount_device, device);
sysprof_mount_device_set_mount_path (mount_device, mountpoint);
sysprof_mount_device_set_subvolume (mount_device, subvol);
sysprof_mount_namespace_add_device (self->mount_namespace, g_steal_pointer (&mount_device));
}
}
static gboolean static gboolean
sysprof_document_load (SysprofDocument *self, sysprof_document_load (SysprofDocument *self,
int capture_fd, int capture_fd,
@ -306,6 +404,7 @@ sysprof_document_load (SysprofDocument *self,
g_array_append_val (self->frames, ptr); g_array_append_val (self->frames, ptr);
} }
sysprof_document_load_mounts (self);
sysprof_document_load_memory_maps (self); sysprof_document_load_memory_maps (self);
return TRUE; return TRUE;