Skip to content

Commit

Permalink
rbd: disable reflink while creating XFS filesystems
Browse files Browse the repository at this point in the history
Current versions of the mkfs.xfs binary enable reflink support by
default. This causes problems on systems where the kernel does not
support this feature. When the kernel the feature does not support, but
the filesystem has it enabled, the following error is logged in `dmesg`:

    XFS: Superblock has unknown read-only compatible features (0x4) enabled

Introduce a check to see if mkfs.xfs supports the `-m reflink=` option.
In case it does, pass `-m reflink=0` while creating the filesystem.

The check is executed once during the first XFS filesystem creation. The
result of the check is cached until the nodeserver restarts.

Fixes: ceph#966
Signed-off-by: Niels de Vos <ndevos@redhat.com>
  • Loading branch information
nixpanic committed Jul 21, 2020
1 parent 71ddf51 commit fbd32e8
Showing 1 changed file with 41 additions and 0 deletions.
41 changes: 41 additions & 0 deletions internal/rbd/nodeserver.go
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ import (
"fmt"
"os"
"strconv"
"strings"

csicommon "github.com/ceph/ceph-csi/internal/csi-common"
"github.com/ceph/ceph-csi/internal/journal"
Expand Down Expand Up @@ -61,6 +62,13 @@ type stageTransaction struct {
devicePath string
}

const (
// values for xfsHasReflink
xfsReflinkUnset int = iota
xfsReflinkNoSupport
xfsReflinkSupport
)

var (
kernelRelease = ""
// deepFlattenSupport holds the list of kernel which support mapping rbd
Expand All @@ -84,6 +92,10 @@ var (
Backport: true,
}, // RHEL 8.2
}

// xfsHasReflink is set by xfsSupportsReflink(), use the function when
// checking the support for reflink
xfsHasReflink = xfsReflinkUnset
)

// NodeStageVolume mounts the volume to a staging path on the node.
Expand Down Expand Up @@ -460,6 +472,11 @@ func (ns *NodeServer) mountVolumeToStagePath(ctx context.Context, req *csi.NodeS
args = []string{"-m0", "-Enodiscard,lazy_itable_init=1,lazy_journal_init=1", devicePath}
} else if fsType == "xfs" {
args = []string{"-K", devicePath}
// always disable reflink
// TODO: make enabling an option, see ceph/ceph-csi#1256
if ns.xfsSupportsReflink() {
args = append(args, "-m", "reflink=0")
}
}
if len(args) > 0 {
cmdOut, cmdErr := diskMounter.Exec.Command("mkfs."+fsType, args...).CombinedOutput()
Expand Down Expand Up @@ -870,3 +887,27 @@ func openEncryptedDevice(ctx context.Context, volOptions *rbdVolume, devicePath

return mapperFilePath, nil
}

// xfsSupportsReflink checks if mkfs.xfs supports the "-m reflink=0|1"
// argument. In case it is supported, return true.
func (ns *NodeServer) xfsSupportsReflink() bool {
// return cached value, if set
if xfsHasReflink != xfsReflinkUnset {
return xfsHasReflink == xfsReflinkSupport
}

// run mkfs.xfs in the same namespace as formatting would be done in
// mountVolumeToStagePath()
diskMounter := &mount.SafeFormatAndMount{Interface: ns.mounter, Exec: utilexec.New()}
out, err := diskMounter.Exec.Command("mkfs.xfs").CombinedOutput()
if err != nil {
// mkfs.xfs should fail with an error message (and help text)
if strings.Contains(string(out), "reflink=0|1") {
xfsHasReflink = xfsReflinkSupport
return true
}
}

xfsHasReflink = xfsReflinkNoSupport
return false
}

0 comments on commit fbd32e8

Please sign in to comment.