]> git.ipfire.org Git - thirdparty/util-linux.git/commitdiff
libmount: report kernel message from new API
authorKarel Zak <kzak@redhat.com>
Mon, 26 Feb 2024 11:44:10 +0000 (12:44 +0100)
committerKarel Zak <kzak@redhat.com>
Tue, 27 Feb 2024 15:09:24 +0000 (16:09 +0100)
This is a very minimalistic implementation for v2.40 designed to print
error messages from the kernel. It exclusively displays errors, and
the patch does not introduce any new library interface for this
purpose. Instead, it simply replaces hardcoded messages within
libmount with kernel messages.

It's worth noting that the final implementation will necessitate
per-hook error handling in libmount and likely a new library API to
access other types of messages (warnings, notices, etc.).

Signed-off-by: Karel Zak <kzak@redhat.com>
libmount/src/context.c
libmount/src/context_mount.c
libmount/src/hook_mount.c
libmount/src/mountP.h

index d9310c453bd8437ba33a435faccbc9860e023fad..6a1b9957856bb49d3eaaa4ef43bf94f64471a5b2 100644 (file)
@@ -314,6 +314,8 @@ int mnt_context_reset_status(struct libmnt_context *cxt)
        if (!cxt)
                return -EINVAL;
 
+       reset_syscall_status(cxt);
+
        cxt->syscall_status = 1;                /* means not called yet */
        cxt->helper_exec_status = 1;
        cxt->helper_status = 0;
index b8302f9fc7082c0991dfb27fef64cf3059a23a02..478a9fde4e15c20a24480396113cc1f3189999be 100644 (file)
@@ -1571,6 +1571,13 @@ int mnt_context_get_mount_excode(
         */
        syserr = mnt_context_get_syscall_errno(cxt);
 
+       if (buf && cxt->syscall_errmsg) {
+               snprintf(buf, bufsz, _("%s system call failed: %s"),
+                                       cxt->syscall_name ? : "mount",
+                                       cxt->syscall_errmsg);
+               return MNT_EX_FAIL;
+       }
+
        switch(syserr) {
        case EPERM:
                if (!buf)
index 961cc8745d0f5f25d2dea6b0a017f1987b0ee8d3..92438966c0e1a09e11dd1c53fe4a42c3eceb5815 100644 (file)
@@ -65,19 +65,29 @@ static void close_sysapi_fds(struct libmnt_sysapi *api)
        api->fd_tree = api->fd_fs = -1;
 }
 
-static void debug_fs_fd_messages(int fd)
+static void save_fd_messages(struct libmnt_context *cxt, int fd)
 {
        uint8_t buf[BUFSIZ];
        int rc;
 
+       free(cxt->syscall_errmsg);
+       cxt->syscall_errmsg = NULL;
+
        while ((rc = read(fd, buf, sizeof(buf))) != -1) {
                if (rc > 0 && buf[rc - 1] == '\n')
                        buf[rc - 1] = '\0';
-               DBG(CXT, ul_debug("message from kernel: %*s", rc, buf));
+               DBG(CXT, ul_debug("message from kernel: \"%*s\"", rc, buf));
+
+               if (rc < 3 || strncmp((char *) buf, "e ", 2) != 0)
+                       continue;
+               if (cxt->syscall_errmsg)
+                       strappend(&cxt->syscall_errmsg, "; ");
+
+               strappend(&cxt->syscall_errmsg, ((char *) buf) + 2);
        }
 }
 
-static void set_syscall_status_cxt_log(struct libmnt_context *cxt,
+static void hookset_set_syscall_status(struct libmnt_context *cxt,
                                       const char *name, int x)
 {
        struct libmnt_sysapi *api;
@@ -86,13 +96,11 @@ static void set_syscall_status_cxt_log(struct libmnt_context *cxt,
 
        if (!x) {
                api = get_sysapi(cxt);
-               if (api)
-                       debug_fs_fd_messages(api->fd_fs);
+               if (api && api->fd_fs >= 0)
+                       save_fd_messages(cxt, api->fd_fs);
        }
 }
 
-#define set_syscall_status set_syscall_status_cxt_log
-
 /*
  * This hookset uses 'struct libmnt_sysapi' (mountP.h) as hookset data.
  */
@@ -176,7 +184,7 @@ static inline int fsconfig_set_value(
        } else
                rc = fsconfig(fd, FSCONFIG_SET_FLAG, name, NULL, 0);
 
-       set_syscall_status(cxt, "fsconfig", rc == 0);
+       hookset_set_syscall_status(cxt, "fsconfig", rc == 0);
        return rc;
 }
 
@@ -241,7 +249,7 @@ static int open_fs_configuration_context(struct libmnt_context *cxt,
        DBG(HOOK, ul_debug(" fsopen(%s)", type));
 
        api->fd_fs = fsopen(type, FSOPEN_CLOEXEC);
-       set_syscall_status(cxt, "fsopen", api->fd_fs >= 0);
+       hookset_set_syscall_status(cxt, "fsopen", api->fd_fs >= 0);
        if (api->fd_fs < 0)
                return -errno;
        api->is_new_fs = 1;
@@ -280,7 +288,7 @@ static int open_mount_tree(struct libmnt_context *cxt, const char *path, unsigne
                                oflg & OPEN_TREE_CLONE ? " clone" : "",
                                oflg & AT_RECURSIVE ? " recursive" : ""));
        fd = open_tree(AT_FDCWD, path, oflg);
-       set_syscall_status(cxt, "open_tree", fd >= 0);
+       hookset_set_syscall_status(cxt, "open_tree", fd >= 0);
 
        return fd;
 }
@@ -320,19 +328,19 @@ static int hook_create_mount(struct libmnt_context *cxt,
        DBG(HOOK, ul_debugobj(hs, "init FS"));
 
        rc = fsconfig(api->fd_fs, FSCONFIG_SET_STRING, "source", src, 0);
-       set_syscall_status(cxt, "fsconfig", rc == 0);
+       hookset_set_syscall_status(cxt, "fsconfig", rc == 0);
 
        if (!rc)
                rc = configure_superblock(cxt, hs, api->fd_fs, 0);
        if (!rc) {
                DBG(HOOK, ul_debugobj(hs, "create FS"));
                rc = fsconfig(api->fd_fs, FSCONFIG_CMD_CREATE, NULL, NULL, 0);
-               set_syscall_status(cxt, "fsconfig", rc == 0);
+               hookset_set_syscall_status(cxt, "fsconfig", rc == 0);
        }
 
        if (!rc) {
                api->fd_tree = fsmount(api->fd_fs, FSMOUNT_CLOEXEC, 0);
-               set_syscall_status(cxt, "fsmount", api->fd_tree >= 0);
+               hookset_set_syscall_status(cxt, "fsmount", api->fd_tree >= 0);
                if (api->fd_tree < 0)
                        rc = -errno;
        }
@@ -381,7 +389,7 @@ static int hook_reconfigure_mount(struct libmnt_context *cxt,
        if (api->fd_fs < 0) {
                api->fd_fs = fspick(api->fd_tree, "", FSPICK_EMPTY_PATH |
                                                      FSPICK_NO_AUTOMOUNT);
-               set_syscall_status(cxt, "fspick", api->fd_fs >= 0);
+               hookset_set_syscall_status(cxt, "fspick", api->fd_fs >= 0);
                if (api->fd_fs < 0)
                        return -errno;
        }
@@ -390,7 +398,7 @@ static int hook_reconfigure_mount(struct libmnt_context *cxt,
        if (!rc) {
                DBG(HOOK, ul_debugobj(hs, "re-configurate FS"));
                rc = fsconfig(api->fd_fs, FSCONFIG_CMD_RECONFIGURE, NULL, NULL, 0);
-               set_syscall_status(cxt, "fsconfig", rc == 0);
+               hookset_set_syscall_status(cxt, "fsconfig", rc == 0);
        }
 
        DBG(HOOK, ul_debugobj(hs, "reconf FS done [rc=%d]", rc));
@@ -428,7 +436,7 @@ static int set_vfsflags(struct libmnt_context *cxt,
 
        errno = 0;
        rc = mount_setattr(api->fd_tree, "", callflags, &attr, sizeof(attr));
-       set_syscall_status(cxt, "mount_setattr", rc == 0);
+       hookset_set_syscall_status(cxt, "mount_setattr", rc == 0);
 
        if (rc && errno == EINVAL)
                return -MNT_ERR_APPLYFLAGS;
@@ -520,7 +528,7 @@ static int hook_set_propagation(struct libmnt_context *cxt,
                        (uint64_t) attr.propagation));
 
                rc = mount_setattr(api->fd_tree, "", flgs, &attr, sizeof(attr));
-               set_syscall_status(cxt, "mount_setattr", rc == 0);
+               hookset_set_syscall_status(cxt, "mount_setattr", rc == 0);
 
                if (rc && errno == EINVAL)
                        return -MNT_ERR_APPLYFLAGS;
@@ -562,7 +570,7 @@ static int hook_attach_target(struct libmnt_context *cxt,
        }
 
        rc = move_mount(api->fd_tree, "", AT_FDCWD, target, MOVE_MOUNT_F_EMPTY_PATH);
-       set_syscall_status(cxt, "move_mount", rc == 0);
+       hookset_set_syscall_status(cxt, "move_mount", rc == 0);
 
        return rc == 0 ? 0 : -errno;
 }
@@ -648,7 +656,7 @@ static int init_sysapi(struct libmnt_context *cxt,
                else if (!fsopen_is_supported()) {
                        errno = ENOSYS;
                        rc = -errno;
-                       set_syscall_status(cxt, "fsopen", rc == 0);
+                       hookset_set_syscall_status(cxt, "fsopen", rc == 0);
                }
                if (rc < 0)
                        goto fail;
index 9bca4ea770227b19537f91d0104ea8593f0a1baa..458aa1a00d02d0c40b35aea5db68899a3f8bc9a2 100644 (file)
@@ -432,6 +432,7 @@ struct libmnt_context
 
        int     syscall_status; /* 1: not called yet, 0: success, <0: -errno */
        const char *syscall_name;       /* failed syscall name */
+       char    *syscall_errmsg;        /* message from kernel */
 
        struct libmnt_ns        ns_orig;        /* original namespace */
        struct libmnt_ns        ns_tgt;         /* target namespace */
@@ -496,6 +497,9 @@ static inline void reset_syscall_status(struct libmnt_context *cxt)
        DBG(CXT, ul_debug("reset syscall status"));
        cxt->syscall_status = 0;
        cxt->syscall_name = NULL;
+
+       free(cxt->syscall_errmsg);
+       cxt->syscall_errmsg = NULL;
 }
 
 /* optmap.c */