diff --git a/cinder/tests/unit/volume/drivers/test_remotefs.py b/cinder/tests/unit/volume/drivers/test_remotefs.py
index 3f276305a3d..c36e8a70d67 100644
--- a/cinder/tests/unit/volume/drivers/test_remotefs.py
+++ b/cinder/tests/unit/volume/drivers/test_remotefs.py
@@ -460,8 +460,65 @@ class RemoteFsSnapDriverTestCase(test.TestCase):
                                  basedir=basedir,
                                  valid_backing_file=False)
 
+    @mock.patch.object(remotefs.RemoteFSSnapDriver, '_local_volume_dir')
     @mock.patch.object(remotefs.RemoteFSSnapDriver,
-                       '_validate_state')
+                       'get_active_image_from_info')
+    def test_local_path_active_image(self, mock_get_active_img,
+                                     mock_local_vol_dir):
+        fake_vol_dir = 'fake_vol_dir'
+        fake_active_img = 'fake_active_img_fname'
+
+        mock_get_active_img.return_value = fake_active_img
+        mock_local_vol_dir.return_value = fake_vol_dir
+
+        active_img_path = self._driver._local_path_active_image(
+            mock.sentinel.volume)
+        exp_act_img_path = os.path.join(fake_vol_dir, fake_active_img)
+
+        self.assertEqual(exp_act_img_path, active_img_path)
+        mock_get_active_img.assert_called_once_with(mock.sentinel.volume)
+        mock_local_vol_dir.assert_called_once_with(mock.sentinel.volume)
+
+    @ddt.data({},
+              {'provider_location': None},
+              {'active_fpath': 'last_snap_img',
+               'expect_snaps': True})
+    @ddt.unpack
+    @mock.patch.object(remotefs.RemoteFSSnapDriver,
+                       '_local_path_active_image')
+    @mock.patch.object(remotefs.RemoteFSSnapDriver,
+                       'local_path')
+    def test_snapshots_exist(self, mock_local_path,
+                             mock_local_path_active_img,
+                             provider_location='fake_share',
+                             active_fpath='base_img_path',
+                             base_vol_path='base_img_path',
+                             expect_snaps=False):
+        self._fake_volume.provider_location = provider_location
+
+        mock_local_path.return_value = base_vol_path
+        mock_local_path_active_img.return_value = active_fpath
+
+        snaps_exist = self._driver._snapshots_exist(self._fake_volume)
+
+        self.assertEqual(expect_snaps, snaps_exist)
+
+        if provider_location:
+            mock_local_path.assert_called_once_with(self._fake_volume)
+            mock_local_path_active_img.assert_called_once_with(
+                self._fake_volume)
+        else:
+            self.assertFalse(mock_local_path.called)
+
+    @ddt.data({},
+              {'snapshots_exist': True},
+              {'force_temp_snap': True})
+    @ddt.unpack
+    @mock.patch.object(remotefs.RemoteFSSnapDriver, 'local_path')
+    @mock.patch.object(remotefs.RemoteFSSnapDriver, '_snapshots_exist')
+    @mock.patch.object(remotefs.RemoteFSSnapDriver, '_copy_volume_image')
+    @mock.patch.object(remotefs.RemoteFSSnapDriver, '_extend_volume')
+    @mock.patch.object(remotefs.RemoteFSSnapDriver, '_validate_state')
     @mock.patch.object(remotefs.RemoteFSSnapDriver, '_create_snapshot')
     @mock.patch.object(remotefs.RemoteFSSnapDriver, '_delete_snapshot')
     @mock.patch.object(remotefs.RemoteFSSnapDriver,
@@ -469,7 +526,13 @@ class RemoteFsSnapDriverTestCase(test.TestCase):
     def test_create_cloned_volume(self, mock_copy_volume_from_snapshot,
                                   mock_delete_snapshot,
                                   mock_create_snapshot,
-                                  mock_validate_state):
+                                  mock_validate_state,
+                                  mock_extend_volme,
+                                  mock_copy_volume_image,
+                                  mock_snapshots_exist,
+                                  mock_local_path,
+                                  snapshots_exist=False,
+                                  force_temp_snap=False):
         drv = self._driver
 
         volume = fake_volume.fake_volume_obj(self.context)
@@ -479,6 +542,9 @@ class RemoteFsSnapDriverTestCase(test.TestCase):
             id=src_vref_id,
             name='volume-%s' % src_vref_id)
 
+        mock_snapshots_exist.return_value = snapshots_exist
+        drv._always_use_temp_snap_when_cloning = force_temp_snap
+
         vol_attrs = ['provider_location', 'size', 'id', 'name', 'status',
                      'volume_type', 'metadata']
         Volume = collections.namedtuple('Volume', vol_attrs)
@@ -509,10 +575,33 @@ class RemoteFsSnapDriverTestCase(test.TestCase):
             src_vref.status,
             exp_acceptable_states,
             obj_description='source volume')
-        mock_create_snapshot.assert_called_once_with(snap_ref)
-        mock_copy_volume_from_snapshot.assert_called_once_with(
-            snap_ref, volume_ref, volume['size'])
-        self.assertTrue(mock_delete_snapshot.called)
+
+        if snapshots_exist or force_temp_snap:
+            mock_create_snapshot.assert_called_once_with(snap_ref)
+            mock_copy_volume_from_snapshot.assert_called_once_with(
+                snap_ref, volume_ref, volume['size'])
+            self.assertTrue(mock_delete_snapshot.called)
+        else:
+            self.assertFalse(mock_create_snapshot.called)
+
+            mock_snapshots_exist.assert_called_once_with(src_vref)
+
+            mock_copy_volume_image.assert_called_once_with(
+                mock_local_path.return_value,
+                mock_local_path.return_value)
+            mock_local_path.assert_has_calls(
+                [mock.call(src_vref), mock.call(volume_ref)])
+            mock_extend_volme.assert_called_once_with(volume_ref,
+                                                      volume.size)
+
+    @mock.patch('shutil.copyfile')
+    @mock.patch.object(remotefs.RemoteFSSnapDriver, '_set_rw_permissions')
+    def test_copy_volume_image(self, mock_set_perm, mock_copyfile):
+        self._driver._copy_volume_image(mock.sentinel.src, mock.sentinel.dest)
+
+        mock_copyfile.assert_called_once_with(mock.sentinel.src,
+                                              mock.sentinel.dest)
+        mock_set_perm.assert_called_once_with(mock.sentinel.dest)
 
     def test_create_regular_file(self):
         self._driver._create_regular_file('/path', 1)
diff --git a/cinder/tests/unit/windows/test_smbfs.py b/cinder/tests/unit/windows/test_smbfs.py
index ab7e76b50c5..aedefcf394e 100644
--- a/cinder/tests/unit/windows/test_smbfs.py
+++ b/cinder/tests/unit/windows/test_smbfs.py
@@ -719,6 +719,12 @@ class WindowsSmbFsTestCase(test.TestCase):
         drv._vhdutils.reconnect_parent_vhd.assert_called_once_with(
             self._FAKE_SNAPSHOT_PATH, self._FAKE_VOLUME_PATH)
 
+    def test_copy_volume_image(self):
+        self._smbfs_driver._copy_volume_image(mock.sentinel.src,
+                                              mock.sentinel.dest)
+        self._smbfs_driver._pathutils.copy.assert_called_once_with(
+            mock.sentinel.src, mock.sentinel.dest)
+
     def test_get_pool_name_from_share(self):
         self._smbfs_driver._pool_mappings = {
             mock.sentinel.share: mock.sentinel.pool}
diff --git a/cinder/volume/drivers/remotefs.py b/cinder/volume/drivers/remotefs.py
index d771f50b464..0052c16ce5f 100644
--- a/cinder/volume/drivers/remotefs.py
+++ b/cinder/volume/drivers/remotefs.py
@@ -20,6 +20,7 @@ import inspect
 import json
 import os
 import re
+import shutil
 import tempfile
 import time
 
@@ -671,6 +672,11 @@ class RemoteFSSnapDriverBase(RemoteFSDriver):
     """
 
     _VALID_IMAGE_EXTENSIONS = []
+    # The following flag may be overriden by the concrete drivers in order
+    # to avoid using temporary volume snapshots when creating volume clones,
+    # when possible.
+
+    _always_use_temp_snap_when_cloning = True
 
     def __init__(self, *args, **kwargs):
         self._remotefsclient = None
@@ -955,6 +961,22 @@ class RemoteFSSnapDriverBase(RemoteFSDriver):
 
         return snap_info['active']
 
+    def _local_path_active_image(self, volume):
+        active_fname = self.get_active_image_from_info(volume)
+        vol_dir = self._local_volume_dir(volume)
+
+        active_fpath = os.path.join(vol_dir, active_fname)
+        return active_fpath
+
+    def _snapshots_exist(self, volume):
+        if not volume.provider_location:
+            return False
+
+        active_fpath = self._local_path_active_image(volume)
+        base_vol_path = self.local_path(volume)
+
+        return not utils.paths_normcase_equal(active_fpath, base_vol_path)
+
     def _create_cloned_volume(self, volume, src_vref):
         LOG.info('Cloning volume %(src)s to volume %(dst)s',
                  {'src': src_vref.id,
@@ -972,10 +994,6 @@ class RemoteFSSnapDriverBase(RemoteFSDriver):
                      'volume_type', 'metadata']
         Volume = collections.namedtuple('Volume', vol_attrs)
 
-        snap_attrs = ['volume_name', 'volume_size', 'name',
-                      'volume_id', 'id', 'volume']
-        Snapshot = collections.namedtuple('Snapshot', snap_attrs)
-
         volume_info = Volume(provider_location=src_vref.provider_location,
                              size=src_vref.size,
                              id=volume.id,
@@ -984,24 +1002,38 @@ class RemoteFSSnapDriverBase(RemoteFSDriver):
                              volume_type=src_vref.volume_type,
                              metadata=src_vref.metadata)
 
-        temp_snapshot = Snapshot(volume_name=volume_name,
-                                 volume_size=src_vref.size,
-                                 name='clone-snap-%s' % src_vref.id,
-                                 volume_id=src_vref.id,
-                                 id='tmp-snap-%s' % src_vref.id,
-                                 volume=src_vref)
+        if (self._always_use_temp_snap_when_cloning or
+                self._snapshots_exist(src_vref)):
+            snap_attrs = ['volume_name', 'volume_size', 'name',
+                          'volume_id', 'id', 'volume']
+            Snapshot = collections.namedtuple('Snapshot', snap_attrs)
 
-        self._create_snapshot(temp_snapshot)
-        try:
-            self._copy_volume_from_snapshot(temp_snapshot,
-                                            volume_info,
-                                            volume.size)
+            temp_snapshot = Snapshot(volume_name=volume_name,
+                                     volume_size=src_vref.size,
+                                     name='clone-snap-%s' % src_vref.id,
+                                     volume_id=src_vref.id,
+                                     id='tmp-snap-%s' % src_vref.id,
+                                     volume=src_vref)
 
-        finally:
-            self._delete_snapshot(temp_snapshot)
+            self._create_snapshot(temp_snapshot)
+            try:
+                self._copy_volume_from_snapshot(temp_snapshot,
+                                                volume_info,
+                                                volume.size)
+
+            finally:
+                self._delete_snapshot(temp_snapshot)
+        else:
+            self._copy_volume_image(self.local_path(src_vref),
+                                    self.local_path(volume_info))
+            self._extend_volume(volume_info, volume.size)
 
         return {'provider_location': src_vref.provider_location}
 
+    def _copy_volume_image(self, src_path, dest_path):
+        shutil.copyfile(src_path, dest_path)
+        self._set_rw_permissions(dest_path)
+
     def _delete_stale_snapshot(self, snapshot):
         info_path = self._local_path_volume_info(snapshot.volume)
         snap_info = self._read_info_file(info_path)
@@ -1544,6 +1576,9 @@ class RemoteFSSnapDriverBase(RemoteFSDriver):
                     {'id': snapshot.id}
                 raise exception.RemoteFSException(msg)
 
+    def _extend_volume(self, volume, size_gb):
+        raise NotImplementedError()
+
 
 class RemoteFSSnapDriver(RemoteFSSnapDriverBase):
     @locked_volume_id_operation
@@ -1575,6 +1610,10 @@ class RemoteFSSnapDriver(RemoteFSSnapDriverBase):
         return self._copy_volume_to_image(context, volume, image_service,
                                           image_meta)
 
+    @locked_volume_id_operation
+    def extend_volume(self, volume, size_gb):
+        return self._extend_volume(volume, size_gb)
+
 
 class RemoteFSSnapDriverDistributed(RemoteFSSnapDriverBase):
     @coordination.synchronized('{self.driver_prefix}-{snapshot.volume.id}')
@@ -1606,6 +1645,10 @@ class RemoteFSSnapDriverDistributed(RemoteFSSnapDriverBase):
         return self._copy_volume_to_image(context, volume, image_service,
                                           image_meta)
 
+    @coordination.synchronized('{self.driver_prefix}-{volume.id}')
+    def extend_volume(self, volume, size_gb):
+        return self._extend_volume(volume, size_gb)
+
 
 class RemoteFSPoolMixin(object):
     """Drivers inheriting this will report each share as a pool."""
diff --git a/cinder/volume/drivers/windows/smbfs.py b/cinder/volume/drivers/windows/smbfs.py
index f44b0922acc..2abb630df2b 100644
--- a/cinder/volume/drivers/windows/smbfs.py
+++ b/cinder/volume/drivers/windows/smbfs.py
@@ -105,6 +105,8 @@ class WindowsSmbfsDriver(remotefs_drv.RemoteFSPoolMixin,
     _SUPPORTED_IMAGE_FORMATS = [_DISK_FORMAT_VHD, _DISK_FORMAT_VHDX]
     _VALID_IMAGE_EXTENSIONS = _SUPPORTED_IMAGE_FORMATS
 
+    _always_use_temp_snap_when_cloning = False
+
     def __init__(self, *args, **kwargs):
         self._remotefsclient = None
         super(WindowsSmbfsDriver, self).__init__(*args, **kwargs)
@@ -398,14 +400,9 @@ class WindowsSmbfsDriver(remotefs_drv.RemoteFSPoolMixin,
         self._vhdutils.create_differencing_vhd(new_snap_path,
                                                backing_file_full_path)
 
-    @coordination.synchronized('{self.driver_prefix}-{volume.id}')
-    def extend_volume(self, volume, size_gb):
-        LOG.info('Extending volume %s.', volume.id)
-
-        self._check_extend_volume_support(volume, size_gb)
-        self._extend_volume(volume, size_gb)
-
     def _extend_volume(self, volume, size_gb):
+        self._check_extend_volume_support(volume, size_gb)
+
         volume_path = self.local_path(volume)
 
         LOG.info('Resizing file %(volume_path)s to %(size_gb)sGB.',
@@ -544,6 +541,9 @@ class WindowsSmbfsDriver(remotefs_drv.RemoteFSPoolMixin,
         self._vhdutils.resize_vhd(volume_path, volume_size * units.Gi,
                                   is_file_max_size=False)
 
+    def _copy_volume_image(self, src_path, dest_path):
+        self._pathutils.copy(src_path, dest_path)
+
     def _get_share_name(self, share):
         return share.replace('/', '\\').lstrip('\\').split('\\', 1)[1]