diff --git a/app/cmd/server.go b/app/cmd/server.go
index d649fe52..efdace5a 100644
--- a/app/cmd/server.go
+++ b/app/cmd/server.go
@@ -1,6 +1,7 @@
 package cmd
 
 import (
+	"fmt"
 	"net"
 	"os"
 	"os/signal"
@@ -16,6 +17,7 @@ import (
 
 	"github.com/longhorn/longhorn-share-manager/pkg/rpc"
 	"github.com/longhorn/longhorn-share-manager/pkg/server"
+	"github.com/longhorn/longhorn-share-manager/pkg/types"
 	"github.com/longhorn/longhorn-share-manager/pkg/util"
 	"github.com/longhorn/longhorn-share-manager/pkg/volume"
 )
@@ -33,6 +35,11 @@ func ServerCmd() cli.Command {
 				Usage:    "The volume to export via the nfs server",
 				Required: true,
 			},
+			cli.StringFlag{
+				Name:     "dataEngine",
+				Usage:    "The volume data engine",
+				Required: true,
+			},
 			cli.BoolFlag{
 				Name:     "encrypted",
 				Usage:    "signals that a volume is encrypted",
@@ -84,6 +91,7 @@ func ServerCmd() cli.Command {
 		Action: func(c *cli.Context) {
 			vol := volume.Volume{
 				Name:            c.String("volume"),
+				DataEngine:      c.String("dataEngine"),
 				Passphrase:      c.String("passphrase"),
 				CryptoKeyCipher: c.String("crytpokeycipher"),
 				CryptoKeyHash:   c.String("crytpokeyhash"),
@@ -106,6 +114,11 @@ func ServerCmd() cli.Command {
 
 func start(vol volume.Volume) error {
 	logger := util.NewLogger()
+	if vol.DataEngine != types.DataEngineTypeV1 && vol.DataEngine != types.DataEngineTypeV2 {
+		logger.Warnf("Invalid data engine value: %s", vol.DataEngine)
+		return fmt.Errorf("invalid data engine value: %s", vol.DataEngine)
+	}
+
 	manager, err := server.NewShareManager(logger, vol)
 	if err != nil {
 		return err
diff --git a/pkg/crypto/crypto.go b/pkg/crypto/crypto.go
index 213d20e7..212a3ae2 100644
--- a/pkg/crypto/crypto.go
+++ b/pkg/crypto/crypto.go
@@ -29,8 +29,9 @@ func EncryptVolume(devicePath, passphrase, keyCipher, keyHash, keySize, pbkdf st
 }
 
 // OpenVolume opens volume so that it can be used by the client.
-func OpenVolume(volume, devicePath, passphrase string) error {
-	devPath := types.GetVolumeDevicePath(volume, true)
+// devicePath is the path of the volume on the host that will be opened for instance '/dev/longhorn/volume1'
+func OpenVolume(volume, dataEngine, devicePath, passphrase string) error {
+	devPath := types.GetVolumeDevicePath(volume, dataEngine, true)
 	if isOpen, _ := IsDeviceOpen(devPath); isOpen {
 		logrus.Debugf("Device %s is already opened at %s", devicePath, devPath)
 		return nil
@@ -42,33 +43,35 @@ func OpenVolume(volume, devicePath, passphrase string) error {
 		return err
 	}
 
-	logrus.Debugf("Opening device %s with LUKS on %s", devicePath, volume)
-	_, err = nsexec.LuksOpen(volume, devicePath, passphrase, lhtypes.LuksTimeout)
+	encryptedDevName := types.GetEncryptVolumeName(volume, dataEngine)
+	logrus.Debugf("Opening device %s with LUKS on %s", devicePath, encryptedDevName)
+	_, err = nsexec.LuksOpen(encryptedDevName, devicePath, passphrase, lhtypes.LuksTimeout)
 	if err != nil {
-		logrus.WithError(err).Warnf("Failed to open LUKS device %s", devicePath)
+		logrus.WithError(err).Warnf("Failed to open LUKS device %s to %s", devicePath, encryptedDevName)
 	}
 	return err
 }
 
 // CloseVolume closes encrypted volume so it can be detached.
-func CloseVolume(volume string) error {
+func CloseVolume(volume, dataEngine string) error {
+	encryptedDevPath := types.GetVolumeDevicePath(volume, dataEngine, true)
 	namespaces := []lhtypes.Namespace{lhtypes.NamespaceMnt, lhtypes.NamespaceIpc}
 	nsexec, err := lhns.NewNamespaceExecutor(lhtypes.ProcessNone, lhtypes.HostProcDirectory, namespaces)
 	if err != nil {
 		return err
 	}
 
-	logrus.Debugf("Closing LUKS device %s", volume)
-	_, err = nsexec.LuksClose(volume, lhtypes.LuksTimeout)
+	logrus.Debugf("Closing LUKS device %s", encryptedDevPath)
+	_, err = nsexec.LuksClose(encryptedDevPath, lhtypes.LuksTimeout)
 	return err
 }
 
-func ResizeEncryptoDevice(volume, passphrase string) error {
-	devPath := types.GetVolumeDevicePath(volume, true)
-	if isOpen, err := IsDeviceOpen(devPath); err != nil {
+func ResizeEncryptoDevice(volume, dataEngine, passphrase string) error {
+	encryptedDevPath := types.GetVolumeDevicePath(volume, dataEngine, true)
+	if isOpen, err := IsDeviceOpen(encryptedDevPath); err != nil {
 		return err
 	} else if !isOpen {
-		return fmt.Errorf("volume %v encrypto device is closed for resizing", volume)
+		return fmt.Errorf("volume %v encrypto device %s is closed for resizing", volume, encryptedDevPath)
 	}
 
 	namespaces := []lhtypes.Namespace{lhtypes.NamespaceMnt, lhtypes.NamespaceIpc}
@@ -77,7 +80,7 @@ func ResizeEncryptoDevice(volume, passphrase string) error {
 		return err
 	}
 
-	_, err = nsexec.LuksResize(volume, passphrase, lhtypes.LuksTimeout)
+	_, err = nsexec.LuksResize(encryptedDevPath, passphrase, lhtypes.LuksTimeout)
 	return err
 }
 
diff --git a/pkg/rpc/server.go b/pkg/rpc/server.go
index d9798137..fd108ea7 100644
--- a/pkg/rpc/server.go
+++ b/pkg/rpc/server.go
@@ -69,7 +69,7 @@ func (s *ShareManagerServer) FilesystemTrim(ctx context.Context, req *smrpc.File
 		}
 	}()
 
-	devicePath := types.GetVolumeDevicePath(vol.Name, req.EncryptedDevice)
+	devicePath := types.GetVolumeDevicePath(vol.Name, vol.DataEngine, req.EncryptedDevice)
 	if !volume.CheckDeviceValid(devicePath) {
 		return &emptypb.Empty{}, grpcstatus.Errorf(grpccodes.FailedPrecondition, "volume %v is not valid", vol.Name)
 	}
@@ -134,7 +134,7 @@ func (s *ShareManagerServer) FilesystemResize(ctx context.Context, req *emptypb.
 		}
 	}()
 
-	devicePath := types.GetVolumeDevicePath(vol.Name, vol.IsEncrypted())
+	devicePath := types.GetVolumeDevicePath(vol.Name, vol.DataEngine, vol.IsEncrypted())
 	if !volume.CheckDeviceValid(devicePath) {
 		return &emptypb.Empty{}, grpcstatus.Errorf(grpccodes.FailedPrecondition, "volume %v is not valid", vol.Name)
 	}
@@ -161,7 +161,7 @@ func (s *ShareManagerServer) FilesystemResize(ctx context.Context, req *emptypb.
 			return &emptypb.Empty{}, grpcstatus.Errorf(grpccodes.InvalidArgument, "unsupported disk encryption format %v", diskFormat)
 		}
 
-		if err = crypto.ResizeEncryptoDevice(vol.Name, vol.Passphrase); err != nil {
+		if err = crypto.ResizeEncryptoDevice(vol.Name, vol.DataEngine, vol.Passphrase); err != nil {
 			return &emptypb.Empty{}, grpcstatus.Errorf(grpccodes.Internal, "failed to resize crypto device %v for volume %v node expansion: %v", devicePath, vol.Name, err)
 		}
 	}
@@ -309,7 +309,7 @@ func (s *ShareManagerServer) Mount(ctx context.Context, req *emptypb.Empty) (res
 
 	log.Info("Mounting and exporting volume")
 
-	devicePath := types.GetVolumeDevicePath(vol.Name, false)
+	devicePath := types.GetVolumeDevicePath(vol.Name, vol.DataEngine, false)
 	mountPath := types.GetMountPath(vol.Name)
 
 	defer func() {
diff --git a/pkg/server/share_manager.go b/pkg/server/share_manager.go
index 0b2d33cc..78e7a0b3 100644
--- a/pkg/server/share_manager.go
+++ b/pkg/server/share_manager.go
@@ -103,7 +103,7 @@ func NewShareManager(logger logrus.FieldLogger, volume volume.Volume) (*ShareMan
 func (m *ShareManager) Run() error {
 	vol := m.volume
 	mountPath := types.GetMountPath(vol.Name)
-	devicePath := types.GetVolumeDevicePath(vol.Name, false)
+	devicePath := types.GetVolumeDevicePath(vol.Name, vol.DataEngine, false)
 
 	defer func() {
 		// if the server is exiting, try to unmount & teardown device before we terminate the container
@@ -201,9 +201,9 @@ func (m *ShareManager) setupDevice(vol volume.Volume, devicePath string) (string
 			}
 		}
 
-		cryptoDevice := types.GetVolumeDevicePath(vol.Name, true)
+		cryptoDevice := types.GetVolumeDevicePath(vol.Name, vol.DataEngine, true)
 		m.logger.Infof("Volume %s requires crypto device %s", vol.Name, cryptoDevice)
-		if err := crypto.OpenVolume(vol.Name, devicePath, vol.Passphrase); err != nil {
+		if err := crypto.OpenVolume(vol.Name, vol.DataEngine, devicePath, vol.Passphrase); err != nil {
 			m.logger.WithError(err).Error("Failed to open encrypted volume")
 			return "", err
 		}
@@ -217,12 +217,12 @@ func (m *ShareManager) setupDevice(vol volume.Volume, devicePath string) (string
 
 func (m *ShareManager) tearDownDevice(vol volume.Volume) error {
 	// close any matching crypto device for this volume
-	cryptoDevice := types.GetVolumeDevicePath(vol.Name, true)
+	cryptoDevice := types.GetVolumeDevicePath(vol.Name, vol.DataEngine, true)
 	if isOpen, err := crypto.IsDeviceOpen(cryptoDevice); err != nil {
 		return err
 	} else if isOpen {
 		m.logger.Infof("Volume %s has active crypto device %s", vol.Name, cryptoDevice)
-		if err := crypto.CloseVolume(vol.Name); err != nil {
+		if err := crypto.CloseVolume(vol.Name, vol.DataEngine); err != nil {
 			return err
 		}
 		m.logger.Infof("Volume %s closed active crypto device %s", vol.Name, cryptoDevice)
diff --git a/pkg/types/types.go b/pkg/types/types.go
index 86aa5e08..d2bf167e 100644
--- a/pkg/types/types.go
+++ b/pkg/types/types.go
@@ -12,11 +12,29 @@ const (
 	DevPath       = "/dev"
 	MapperDevPath = "/dev/mapper"
 
+	// The suffix for dm device name of the encrypted v2 volume.
+	MapperV2VolumeSuffix = "-encrypted"
+
 	ExportPath = "/export"
+
+	DataEngineTypeV1 = "v1"
+	DataEngineTypeV2 = "v2"
 )
 
-func GetVolumeDevicePath(volumeName string, EncryptedDevice bool) string {
+func GetEncryptVolumeName(volume, dataEngine string) string {
+	if dataEngine == DataEngineTypeV2 {
+		return volume + MapperV2VolumeSuffix
+	}
+	return volume
+}
+
+func GetVolumeDevicePath(volumeName, dataEngine string, EncryptedDevice bool) string {
 	if EncryptedDevice {
+		if dataEngine == DataEngineTypeV2 {
+			// v2 volume will use a dm device as default to control IO path when attaching. This dm device will be created with the same name as the volume name.
+			// The encrypted volume will be created with the volume name with "-encrypted" suffix to resolve the naming conflict.
+			return path.Join(MapperDevPath, GetEncryptVolumeName(volumeName, dataEngine))
+		}
 		return path.Join(MapperDevPath, volumeName)
 	}
 	return filepath.Join(DevPath, "longhorn", volumeName)
diff --git a/pkg/volume/volume.go b/pkg/volume/volume.go
index d5d3404a..8e9fc654 100644
--- a/pkg/volume/volume.go
+++ b/pkg/volume/volume.go
@@ -11,6 +11,7 @@ import (
 
 type Volume struct {
 	Name            string
+	DataEngine      string
 	Passphrase      string
 	CryptoKeyCipher string
 	CryptoKeyHash   string