Skip to content

Commit

Permalink
fix: recognize kernel mount failure when target already mounted. (pro…
Browse files Browse the repository at this point in the history
…ject-stacker#539)

In a single stacker file that used a squashfs image twice or more,
stacker would mount the layers the first time correctly.
The image build would fail.  The reason was that maybeKernelSquashMount
did not detected *why* the mount failed (it was already mounted), but
only that it did fail.  So the code then attempted to extract the
squashfs layer with unsquashfs and an error would occur like:

   FATAL ERROR: dir_scan: failed to change permissions for directory
      .../roots/sha256_52068a5d6c1...02caeb3a706cba3a/overlay,
      because Read-only file system
      Parallel unsquashfs: Using 32 processors
      691 inodes (966 blocks) to write

The error only actually occurs if:
 * user is priveleged (can do a kernel mount)
 * stacker is building squash images (--layer-type=squashfs)
 * user does not have squashfuse in their path.

This is fixed more correctly upstream in 565b032.

An example stacker file that would recreate:

    b1:
      build_only: true
      from:
        type: docker
        url: oci:my-ocidir:base:latest-squashfs
    run: |
      echo "hello world" > f1

    b2:
      from:
        type: docker
        url: oci:my-ocidir:base:latest-squashfs
      run: |
        echo "goodbye" > f2

The fix here is not great... effectively grepping the output of 'mount'
for 'is already mounted'.   We set the LANG environment variable to C
to avoid failures due to a translations.

Signed-off-by: Scott Moser <[email protected]>
  • Loading branch information
smoser authored Nov 9, 2023
1 parent e905172 commit 5c91928
Showing 1 changed file with 5 additions and 0 deletions.
5 changes: 5 additions & 0 deletions pkg/squashfs/squashfs.go
Original file line number Diff line number Diff line change
Expand Up @@ -190,6 +190,7 @@ func maybeKernelSquashMount(squashFile, extractDir string) (bool, error) {
ecmd := []string{"mount", "-tsquashfs", "-oloop,ro", squashFile, extractDir}
var output bytes.Buffer
cmd := exec.Command(ecmd[0], ecmd[1:]...)
cmd.Env = append(cmd.Environ(), "LANG=C")
cmd.Stdin = nil
cmd.Stdout = &output
cmd.Stderr = cmd.Stdout
Expand All @@ -209,6 +210,10 @@ func maybeKernelSquashMount(squashFile, extractDir string) (bool, error) {
return false, errors.Errorf("Unexpected error (no-status) in exec (%v): %v", ecmd, err)
}

if status.ExitStatus() == 1 && strings.Contains(output.String(), "is already mounted") {
return true, nil
}

// we can't really tell why the mount failed. mount(8) does not give a lot specific rc exits.
log.Debugf("maybeKernelSquashMount(%s) exited %d: %s\n", squashFile, status.ExitStatus(), output.String())
return false, kernelSquashMountFailed
Expand Down

0 comments on commit 5c91928

Please sign in to comment.