Skip to content

Commit

Permalink
lxd/storage/drivers: Revert to filepath traversal if subvolume list f…
Browse files Browse the repository at this point in the history
…ails.

Signed-off-by: Mark Laing <mark.laing@canonical.com>
  • Loading branch information
markylaing committed Nov 28, 2023
1 parent b373fce commit 14d96a3
Showing 1 changed file with 46 additions and 17 deletions.
63 changes: 46 additions & 17 deletions lxd/storage/drivers/driver_btrfs_utils.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import (
"context"
"fmt"
"io"
"io/fs"
"os"
"os/exec"
"path/filepath"
Expand Down Expand Up @@ -107,39 +108,67 @@ func (d *btrfs) hasSubvolumes(path string) (bool, error) {
}

func (d *btrfs) getSubvolumes(path string) ([]string, error) {
// Make sure the path has a trailing slash.
if !strings.HasSuffix(path, "/") {
path = path + "/"
}

poolMountPath := GetPoolMountPath(d.name)
if !strings.HasPrefix(path, poolMountPath+"/") {
return nil, fmt.Errorf("%q is outside pool mount path %q", path, poolMountPath)
}

path = strings.TrimPrefix(path, poolMountPath+"/")

// Make sure the path has a trailing slash.
if !strings.HasSuffix(path, "/") {
path = path + "/"
}
var result []string

// Attempt to run `btrfs subvolume list`. This may fail inside a nested container, where the container does not have
// sufficient permission to run the command.
var stdout bytes.Buffer
err := shared.RunCommandWithFds(d.state.ShutdownCtx, nil, &stdout, "btrfs", "subvolume", "list", poolMountPath)
if err != nil {
return nil, err
if err == nil {
path = strings.TrimPrefix(path, poolMountPath+"/")
scanner := bufio.NewScanner(&stdout)
for scanner.Scan() {
fields := strings.Fields(scanner.Text())

if len(fields) != 9 {
continue
}

if !strings.HasPrefix(fields[8], path) {
continue
}

result = append(result, strings.TrimPrefix(fields[8], path))
}

return result, nil
}

result := []string{}
// Revert to walking the directory tree looking for subvolumes.
err = filepath.Walk(path, func(fpath string, entry fs.FileInfo, err error) error {
if err != nil {
return err
}

scanner := bufio.NewScanner(&stdout)
for scanner.Scan() {
fields := strings.Fields(scanner.Text())
// Ignore the base path.
if strings.TrimRight(fpath, "/") == strings.TrimRight(path, "/") {
return nil
}

if len(fields) != 9 {
continue
// Subvolumes can only be directories.
if !entry.IsDir() {
return nil
}

if !strings.HasPrefix(fields[8], path) {
continue
// Check if directory is a subvolume.
if d.isSubvolume(fpath) {
result = append(result, strings.TrimPrefix(fpath, path))
}

result = append(result, strings.TrimPrefix(fields[8], path))
return nil
})
if err != nil {
return nil, err
}

return result, nil
Expand Down

0 comments on commit 14d96a3

Please sign in to comment.