]> git.ipfire.org Git - thirdparty/systemd.git/commitdiff
bootctl: do not fail on removing unfied kernel image
authorYu Watanabe <watanabe.yu+github@gmail.com>
Mon, 25 Aug 2025 16:43:10 +0000 (01:43 +0900)
committerZbigniew Jędrzejewski-Szmek <zbyszek@in.waw.pl>
Wed, 3 Sep 2025 10:10:48 +0000 (12:10 +0200)
A boot loader entry for a unified kernel image has
BootEntry.kernel : path to the image relative to ESP or XBOOTLDR,
BootEntry.path   : path to the image.
Hence, these two effectively point to the same file.

Hence, by unlink command, the image is removed by
```
deref_unlink_file(&known_files, e->kernel, e->root);
```
then later tried again by
```
r = chase_and_unlink(e->path, root, ...);
```
and of course it fails with -ENOENT.

Let's ignore the failure there. We already ignore ENOENT on removal
at various places, especially in deref_unlink_file().

Fixes #38706.
Follow-ups for 8702496bfb0205764569782a9a2ebd11fd80e5e8.

(cherry picked from commit 37d1f1573b859e61df46bed4648fa60da5b60102)

src/bootctl/bootctl-status.c

index bd788e6df877a32aa2645da7eb57257d74094776..e2147de91bcedfb789901234e7f1ba3441c46c55 100644 (file)
@@ -730,7 +730,7 @@ static int unlink_entry(const BootConfig *config, const char *root, const char *
 
         r = boot_config_find_in(config, root, id);
         if (r < 0)
-                return r;
+                return 0; /* There is nothing to remove. */
 
         if (r == config->default_entry)
                 log_warning("%s is the default boot entry", id);
@@ -751,6 +751,8 @@ static int unlink_entry(const BootConfig *config, const char *root, const char *
                 log_info("Would remove \"%s\"", e->path);
         else {
                 r = chase_and_unlink(e->path, root, CHASE_PROHIBIT_SYMLINKS, 0, NULL);
+                if (r == -ENOENT)
+                        return 0; /* Already removed? */
                 if (r < 0)
                         return log_error_errno(r, "Failed to remove \"%s\": %m", e->path);
 
@@ -783,7 +785,8 @@ static int list_remove_orphaned_file(
         if (arg_dry_run)
                 log_info("Would remove %s", path);
         else if (unlinkat(dir_fd, de->d_name, 0) < 0)
-                log_warning_errno(errno, "Failed to remove \"%s\", ignoring: %m", path);
+                log_full_errno(errno == ENOENT ? LOG_DEBUG : LOG_WARNING, errno,
+                               "Failed to remove \"%s\", ignoring: %m", path);
         else
                 log_info("Removed %s", path);
 
@@ -870,12 +873,9 @@ int verb_list(int argc, char *argv[], void *userdata) {
                 return cleanup_orphaned_files(&config, arg_esp_path);
         } else {
                 assert(streq(argv[0], "unlink"));
-                if (arg_xbootldr_path && xbootldr_devid != esp_devid) {
+                if (arg_xbootldr_path && xbootldr_devid != esp_devid)
                         r = unlink_entry(&config, arg_xbootldr_path, argv[1]);
-                        if (r == 0 || r != -ENOENT)
-                                return r;
-                }
-                return unlink_entry(&config, arg_esp_path, argv[1]);
+                return RET_GATHER(r, unlink_entry(&config, arg_esp_path, argv[1]));
         }
 }