diff options
author | loli10K <[email protected]> | 2019-02-09 00:44:15 +0100 |
---|---|---|
committer | Matthew Ahrens <[email protected]> | 2019-02-08 15:44:15 -0800 |
commit | d8d418ff0cc90776182534bce10b01e9487b63e4 (patch) | |
tree | b7db149cf6bfc701f7b3637359c192b2575c83c8 /contrib/pyzfs | |
parent | 4417096956f7439322c65d9e70a4526df45ea8d0 (diff) |
ZVOLs should not be allowed to have children
zfs create, receive and rename can bypass this hierarchy rule. Update
both userland and kernel module to prevent this issue and use pyzfs
unit tests to exercise the ioctls directly.
Note: this commit slightly changes zfs_ioc_create() ABI. This allow to
differentiate a generic error (EINVAL) from the specific case where we
tried to create a dataset below a ZVOL (ZFS_ERR_WRONG_PARENT).
Reviewed-by: Paul Dagnelie <[email protected]>
Reviewed-by: Matt Ahrens <[email protected]>
Reviewed-by: Brian Behlendorf <[email protected]>
Reviewed-by: Tom Caputi <[email protected]>
Signed-off-by: loli10K <[email protected]>
Diffstat (limited to 'contrib/pyzfs')
-rw-r--r-- | contrib/pyzfs/libzfs_core/_constants.py | 1 | ||||
-rw-r--r-- | contrib/pyzfs/libzfs_core/_error_translation.py | 10 | ||||
-rw-r--r-- | contrib/pyzfs/libzfs_core/_libzfs_core.py | 4 | ||||
-rw-r--r-- | contrib/pyzfs/libzfs_core/exceptions.py | 5 | ||||
-rw-r--r-- | contrib/pyzfs/libzfs_core/test/test_libzfs_core.py | 184 |
5 files changed, 139 insertions, 65 deletions
diff --git a/contrib/pyzfs/libzfs_core/_constants.py b/contrib/pyzfs/libzfs_core/_constants.py index 917feee01..55de55d42 100644 --- a/contrib/pyzfs/libzfs_core/_constants.py +++ b/contrib/pyzfs/libzfs_core/_constants.py @@ -65,6 +65,7 @@ ZFS_ERR_DISCARDING_CHECKPOINT = 1025 ZFS_ERR_NO_CHECKPOINT = 1026 ZFS_ERR_DEVRM_IN_PROGRESS = 1027 ZFS_ERR_VDEV_TOO_BIG = 1028 +ZFS_ERR_WRONG_PARENT = 1033 # vim: softtabstop=4 tabstop=4 expandtab shiftwidth=4 diff --git a/contrib/pyzfs/libzfs_core/_error_translation.py b/contrib/pyzfs/libzfs_core/_error_translation.py index b5f4bebce..b888fd725 100644 --- a/contrib/pyzfs/libzfs_core/_error_translation.py +++ b/contrib/pyzfs/libzfs_core/_error_translation.py @@ -38,7 +38,8 @@ from ._constants import ( ZFS_ERR_DISCARDING_CHECKPOINT, ZFS_ERR_NO_CHECKPOINT, ZFS_ERR_DEVRM_IN_PROGRESS, - ZFS_ERR_VDEV_TOO_BIG + ZFS_ERR_VDEV_TOO_BIG, + ZFS_ERR_WRONG_PARENT ) @@ -46,13 +47,14 @@ def lzc_create_translate_error(ret, name, ds_type, props): if ret == 0: return if ret == errno.EINVAL: - # XXX: should raise lzc_exc.WrongParent if parent is ZVOL _validate_fs_name(name) raise lzc_exc.PropertyInvalid(name) if ret == errno.EEXIST: raise lzc_exc.FilesystemExists(name) if ret == errno.ENOENT: raise lzc_exc.ParentNotFound(name) + if ret == ZFS_ERR_WRONG_PARENT: + raise lzc_exc.WrongParent(_fs_name(name)) raise _generic_exception(ret, name, "Failed to create filesystem") @@ -444,6 +446,8 @@ def lzc_receive_translate_errors( raise lzc_exc.SuspendedPool(_pool_name(snapname)) if ret == errno.EBADE: # ECKSUM raise lzc_exc.BadStream() + if ret == ZFS_ERR_WRONG_PARENT: + raise lzc_exc.WrongParent(_fs_name(snapname)) raise lzc_exc.StreamIOError(ret) @@ -596,6 +600,8 @@ def lzc_rename_translate_error(ret, source, target): raise lzc_exc.FilesystemExists(target) if ret == errno.ENOENT: raise lzc_exc.FilesystemNotFound(source) + if ret == ZFS_ERR_WRONG_PARENT: + raise lzc_exc.WrongParent(target) raise _generic_exception(ret, source, "Failed to rename dataset") diff --git a/contrib/pyzfs/libzfs_core/_libzfs_core.py b/contrib/pyzfs/libzfs_core/_libzfs_core.py index 589926ba8..5c8a1f5e6 100644 --- a/contrib/pyzfs/libzfs_core/_libzfs_core.py +++ b/contrib/pyzfs/libzfs_core/_libzfs_core.py @@ -754,6 +754,8 @@ def lzc_receive(snapname, fd, force=False, raw=False, origin=None, props=None): supported on this side. :raises NameInvalid: if the name of either snapshot is invalid. :raises NameTooLong: if the name of either snapshot is too long. + :raises WrongParent: if the parent dataset of the received destination is + not a filesystem (e.g. ZVOL) .. note:: The ``origin`` is ignored if the actual stream is an incremental stream @@ -1621,6 +1623,8 @@ def lzc_rename(source, target): :raises FilesystemNotFound: if the target's parent does not exist. :raises FilesystemExists: if the target already exists. :raises PoolsDiffer: if the source and target belong to different pools. + :raises WrongParent: if the "new" parent dataset is not a filesystem + (e.g. ZVOL) ''' ret = _lib.lzc_rename(source, target) errors.lzc_rename_translate_error(ret, source, target) diff --git a/contrib/pyzfs/libzfs_core/exceptions.py b/contrib/pyzfs/libzfs_core/exceptions.py index c54459ec8..f465cd3d9 100644 --- a/contrib/pyzfs/libzfs_core/exceptions.py +++ b/contrib/pyzfs/libzfs_core/exceptions.py @@ -25,7 +25,8 @@ from ._constants import ( ZFS_ERR_DISCARDING_CHECKPOINT, ZFS_ERR_NO_CHECKPOINT, ZFS_ERR_DEVRM_IN_PROGRESS, - ZFS_ERR_VDEV_TOO_BIG + ZFS_ERR_VDEV_TOO_BIG, + ZFS_ERR_WRONG_PARENT ) @@ -140,7 +141,7 @@ class ParentNotFound(ZFSError): class WrongParent(ZFSError): - errno = errno.EINVAL + errno = ZFS_ERR_WRONG_PARENT message = "Parent dataset is not a filesystem" def __init__(self, name): diff --git a/contrib/pyzfs/libzfs_core/test/test_libzfs_core.py b/contrib/pyzfs/libzfs_core/test/test_libzfs_core.py index 97fd36ce7..25f20a4ae 100644 --- a/contrib/pyzfs/libzfs_core/test/test_libzfs_core.py +++ b/contrib/pyzfs/libzfs_core/test/test_libzfs_core.py @@ -193,11 +193,11 @@ def make_snapshots(fs, before, modified, after): @contextlib.contextmanager def streams(fs, first, second): (filename, snaps) = make_snapshots(fs, None, first, second) - with tempfile.TemporaryFile(suffix='.ztream') as full: + with tempfile.TemporaryFile(suffix='.zstream') as full: lzc.lzc_send(snaps[1], None, full.fileno()) full.seek(0) if snaps[2] is not None: - with tempfile.TemporaryFile(suffix='.ztream') as incremental: + with tempfile.TemporaryFile(suffix='.zstream') as incremental: lzc.lzc_send(snaps[2], snaps[1], incremental.fileno()) incremental.seek(0) yield (filename, (full, incremental)) @@ -357,8 +357,6 @@ class ZFSTest(unittest.TestCase): with self.assertRaises(lzc_exc.DatasetTypeInvalid): lzc.lzc_create(name, ds_type='wrong') - # XXX: we should have a way to raise lzc_exc.WrongParent from lzc_create() - @unittest.expectedFailure def test_create_fs_below_zvol(self): name = ZFSTest.pool.makeName(b"fs1/fs/zvol") props = {b"volsize": 1024 * 1024} @@ -367,6 +365,14 @@ class ZFSTest(unittest.TestCase): with self.assertRaises(lzc_exc.WrongParent): lzc.lzc_create(name + b'/fs') + def test_create_zvol_below_zvol(self): + name = ZFSTest.pool.makeName(b"fs1/fs/zvol") + props = {b"volsize": 1024 * 1024} + + lzc.lzc_create(name, ds_type='zvol', props=props) + with self.assertRaises(lzc_exc.WrongParent): + lzc.lzc_create(name + b'/zvol', ds_type='zvol', props=props) + def test_create_fs_duplicate(self): name = ZFSTest.pool.makeName(b"fs1/fs/test6") @@ -1590,7 +1596,7 @@ class ZFSTest(unittest.TestCase): f.flush() lzc.lzc_snapshot([snap]) - with tempfile.TemporaryFile(suffix='.ztream') as output: + with tempfile.TemporaryFile(suffix='.zstream') as output: estimate = lzc.lzc_send_space(snap) fd = output.fileno() @@ -1611,7 +1617,7 @@ class ZFSTest(unittest.TestCase): f.flush() lzc.lzc_snapshot([snap2]) - with tempfile.TemporaryFile(suffix='.ztream') as output: + with tempfile.TemporaryFile(suffix='.zstream') as output: estimate = lzc.lzc_send_space(snap2, snap1) fd = output.fileno() @@ -1640,7 +1646,7 @@ class ZFSTest(unittest.TestCase): def test_send_same_snap(self): snap1 = ZFSTest.pool.makeName(b"fs1@snap1") lzc.lzc_snapshot([snap1]) - with tempfile.TemporaryFile(suffix='.ztream') as output: + with tempfile.TemporaryFile(suffix='.zstream') as output: fd = output.fileno() with self.assertRaises(lzc_exc.SnapshotMismatch): lzc.lzc_send(snap1, snap1, fd) @@ -1652,7 +1658,7 @@ class ZFSTest(unittest.TestCase): lzc.lzc_snapshot([snap1]) lzc.lzc_snapshot([snap2]) - with tempfile.TemporaryFile(suffix='.ztream') as output: + with tempfile.TemporaryFile(suffix='.zstream') as output: fd = output.fileno() with self.assertRaises(lzc_exc.SnapshotMismatch): lzc.lzc_send(snap1, snap2, fd) @@ -1664,7 +1670,7 @@ class ZFSTest(unittest.TestCase): lzc.lzc_snapshot([snap1]) lzc.lzc_snapshot([snap2]) - with tempfile.TemporaryFile(suffix='.ztream') as output: + with tempfile.TemporaryFile(suffix='.zstream') as output: fd = output.fileno() with self.assertRaises(lzc_exc.SnapshotMismatch): lzc.lzc_send(snap1, snap2, fd) @@ -1676,7 +1682,7 @@ class ZFSTest(unittest.TestCase): lzc.lzc_snapshot([snap1]) lzc.lzc_snapshot([snap2]) - with tempfile.TemporaryFile(suffix='.ztream') as output: + with tempfile.TemporaryFile(suffix='.zstream') as output: fd = output.fileno() with self.assertRaises(lzc_exc.PoolsDiffer): lzc.lzc_send(snap1, snap2, fd) @@ -1687,7 +1693,7 @@ class ZFSTest(unittest.TestCase): lzc.lzc_snapshot([snap1]) - with tempfile.TemporaryFile(suffix='.ztream') as output: + with tempfile.TemporaryFile(suffix='.zstream') as output: fd = output.fileno() with self.assertRaises(lzc_exc.SnapshotNotFound) as ctx: lzc.lzc_send(snap1, snap2, fd) @@ -1707,7 +1713,7 @@ class ZFSTest(unittest.TestCase): lzc.lzc_snapshot([snap1]) - with tempfile.TemporaryFile(suffix='.ztream') as output: + with tempfile.TemporaryFile(suffix='.zstream') as output: fd = output.fileno() with self.assertRaises(lzc_exc.NameInvalid) as ctx: lzc.lzc_send(snap2, snap1, fd) @@ -1729,7 +1735,7 @@ class ZFSTest(unittest.TestCase): lzc.lzc_snapshot([snap]) - with tempfile.TemporaryFile(suffix='.ztream') as output: + with tempfile.TemporaryFile(suffix='.zstream') as output: fd = output.fileno() lzc.lzc_send(fs, snap, fd) lzc.lzc_send(fs, None, fd) @@ -1740,7 +1746,7 @@ class ZFSTest(unittest.TestCase): lzc.lzc_snapshot([snap]) - with tempfile.TemporaryFile(suffix='.ztream') as output: + with tempfile.TemporaryFile(suffix='.zstream') as output: fd = output.fileno() with self.assertRaises(lzc_exc.NameInvalid): lzc.lzc_send(snap, fs, fd) @@ -1756,7 +1762,7 @@ class ZFSTest(unittest.TestCase): lzc.lzc_bookmark({bmark: snap2}) lzc.lzc_destroy_snaps([snap2], defer=False) - with tempfile.TemporaryFile(suffix='.ztream') as output: + with tempfile.TemporaryFile(suffix='.zstream') as output: fd = output.fileno() with self.assertRaises(lzc_exc.NameInvalid): lzc.lzc_send(bmark, snap1, fd) @@ -1774,7 +1780,7 @@ class ZFSTest(unittest.TestCase): lzc.lzc_bookmark({bmark: snap1}) lzc.lzc_destroy_snaps([snap1], defer=False) - with tempfile.TemporaryFile(suffix='.ztream') as output: + with tempfile.TemporaryFile(suffix='.zstream') as output: fd = output.fileno() lzc.lzc_send(snap2, bmark, fd) @@ -1854,7 +1860,7 @@ class ZFSTest(unittest.TestCase): lzc.lzc_snapshot([snap]) with tempfile.NamedTemporaryFile( - suffix='.ztream', delete=False) as output: + suffix='.zstream', delete=False) as output: # tempfile always opens a temporary file in read-write mode # regardless of the specified mode, so we have to open it again. os.chmod(output.name, stat.S_IRUSR) @@ -1871,7 +1877,7 @@ class ZFSTest(unittest.TestCase): with temp_file_in_fs(ZFSTest.pool.makeName(b"fs1")) as name: lzc.lzc_snapshot([src]) - with tempfile.TemporaryFile(suffix='.ztream') as stream: + with tempfile.TemporaryFile(suffix='.zstream') as stream: lzc.lzc_send(src, None, stream.fileno()) stream.seek(0) lzc.lzc_receive(dst, stream.fileno()) @@ -1892,11 +1898,11 @@ class ZFSTest(unittest.TestCase): with temp_file_in_fs(ZFSTest.pool.makeName(b"fs1")) as name: lzc.lzc_snapshot([src2]) - with tempfile.TemporaryFile(suffix='.ztream') as stream: + with tempfile.TemporaryFile(suffix='.zstream') as stream: lzc.lzc_send(src1, None, stream.fileno()) stream.seek(0) lzc.lzc_receive(dst1, stream.fileno()) - with tempfile.TemporaryFile(suffix='.ztream') as stream: + with tempfile.TemporaryFile(suffix='.zstream') as stream: lzc.lzc_send(src2, src1, stream.fileno()) stream.seek(0) lzc.lzc_receive(dst2, stream.fileno()) @@ -1933,14 +1939,14 @@ class ZFSTest(unittest.TestCase): clone_dst = ZFSTest.pool.makeName(b"fs1/fs/recv-clone@snap") lzc.lzc_snapshot([orig_src]) - with tempfile.TemporaryFile(suffix='.ztream') as stream: + with tempfile.TemporaryFile(suffix='.zstream') as stream: lzc.lzc_send(orig_src, None, stream.fileno()) stream.seek(0) lzc.lzc_receive(orig_dst, stream.fileno()) lzc.lzc_clone(clone, orig_src) lzc.lzc_snapshot([clone_snap]) - with tempfile.TemporaryFile(suffix='.ztream') as stream: + with tempfile.TemporaryFile(suffix='.zstream') as stream: lzc.lzc_send(clone_snap, orig_src, stream.fileno()) stream.seek(0) lzc.lzc_receive(clone_dst, stream.fileno(), origin=orig_dst) @@ -1953,7 +1959,7 @@ class ZFSTest(unittest.TestCase): with temp_file_in_fs(ZFSTest.pool.makeName(b"fs1")): lzc.lzc_snapshot([src]) lzc.lzc_create(dstfs) - with tempfile.TemporaryFile(suffix='.ztream') as stream: + with tempfile.TemporaryFile(suffix='.zstream') as stream: lzc.lzc_send(src, None, stream.fileno()) stream.seek(0) with self.assertRaises(( @@ -1992,7 +1998,7 @@ class ZFSTest(unittest.TestCase): lzc.lzc_snapshot([src]) lzc.lzc_create(dstfs) with temp_file_in_fs(dstfs): - with tempfile.TemporaryFile(suffix='.ztream') as stream: + with tempfile.TemporaryFile(suffix='.zstream') as stream: lzc.lzc_send(src, None, stream.fileno()) stream.seek(0) with self.assertRaises(( @@ -2008,7 +2014,7 @@ class ZFSTest(unittest.TestCase): lzc.lzc_snapshot([src]) lzc.lzc_create(dstfs) lzc.lzc_snapshot([dstfs + b"@snap1"]) - with tempfile.TemporaryFile(suffix='.ztream') as stream: + with tempfile.TemporaryFile(suffix='.zstream') as stream: lzc.lzc_send(src, None, stream.fileno()) stream.seek(0) with self.assertRaises(( @@ -2024,7 +2030,7 @@ class ZFSTest(unittest.TestCase): lzc.lzc_snapshot([src]) lzc.lzc_create(dstfs) lzc.lzc_snapshot([dst]) - with tempfile.TemporaryFile(suffix='.ztream') as stream: + with tempfile.TemporaryFile(suffix='.zstream') as stream: lzc.lzc_send(src, None, stream.fileno()) stream.seek(0) with self.assertRaises(lzc_exc.DatasetExists): @@ -2036,7 +2042,7 @@ class ZFSTest(unittest.TestCase): with temp_file_in_fs(ZFSTest.pool.makeName(b"fs1")): lzc.lzc_snapshot([src]) - with tempfile.TemporaryFile(suffix='.ztream') as stream: + with tempfile.TemporaryFile(suffix='.zstream') as stream: lzc.lzc_send(src, None, stream.fileno()) stream.seek(0) with self.assertRaises(lzc_exc.DatasetNotFound): @@ -2251,14 +2257,14 @@ class ZFSTest(unittest.TestCase): clone_dst = ZFSTest.pool.makeName(b"fs1/fs/recv-clone-2@snap") lzc.lzc_snapshot([orig_src]) - with tempfile.TemporaryFile(suffix='.ztream') as stream: + with tempfile.TemporaryFile(suffix='.zstream') as stream: lzc.lzc_send(orig_src, None, stream.fileno()) stream.seek(0) lzc.lzc_receive(orig_dst, stream.fileno()) lzc.lzc_clone(clone, orig_src) lzc.lzc_snapshot([clone_snap]) - with tempfile.TemporaryFile(suffix='.ztream') as stream: + with tempfile.TemporaryFile(suffix='.zstream') as stream: lzc.lzc_send(clone_snap, orig_src, stream.fileno()) stream.seek(0) with self.assertRaises(lzc_exc.BadStream): @@ -2272,14 +2278,14 @@ class ZFSTest(unittest.TestCase): clone_dst = ZFSTest.pool.makeName(b"fs1/fs/recv-clone-3@snap") lzc.lzc_snapshot([orig_src]) - with tempfile.TemporaryFile(suffix='.ztream') as stream: + with tempfile.TemporaryFile(suffix='.zstream') as stream: lzc.lzc_send(orig_src, None, stream.fileno()) stream.seek(0) lzc.lzc_receive(orig_dst, stream.fileno()) lzc.lzc_clone(clone, orig_src) lzc.lzc_snapshot([clone_snap]) - with tempfile.TemporaryFile(suffix='.ztream') as stream: + with tempfile.TemporaryFile(suffix='.zstream') as stream: lzc.lzc_send(clone_snap, orig_src, stream.fileno()) stream.seek(0) with self.assertRaises(lzc_exc.NameInvalid): @@ -2296,7 +2302,7 @@ class ZFSTest(unittest.TestCase): wrong_origin = ZFSTest.pool.makeName(b"fs1/fs@snap") lzc.lzc_snapshot([orig_src]) - with tempfile.TemporaryFile(suffix='.ztream') as stream: + with tempfile.TemporaryFile(suffix='.zstream') as stream: lzc.lzc_send(orig_src, None, stream.fileno()) stream.seek(0) lzc.lzc_receive(orig_dst, stream.fileno()) @@ -2304,7 +2310,7 @@ class ZFSTest(unittest.TestCase): lzc.lzc_clone(clone, orig_src) lzc.lzc_snapshot([clone_snap]) lzc.lzc_snapshot([wrong_origin]) - with tempfile.TemporaryFile(suffix='.ztream') as stream: + with tempfile.TemporaryFile(suffix='.zstream') as stream: lzc.lzc_send(clone_snap, orig_src, stream.fileno()) stream.seek(0) with self.assertRaises(lzc_exc.StreamMismatch): @@ -2320,14 +2326,14 @@ class ZFSTest(unittest.TestCase): wrong_origin = ZFSTest.pool.makeName(b"fs1/fs@snap") lzc.lzc_snapshot([orig_src]) - with tempfile.TemporaryFile(suffix='.ztream') as stream: + with tempfile.TemporaryFile(suffix='.zstream') as stream: lzc.lzc_send(orig_src, None, stream.fileno()) stream.seek(0) lzc.lzc_receive(orig_dst, stream.fileno()) lzc.lzc_clone(clone, orig_src) lzc.lzc_snapshot([clone_snap]) - with tempfile.TemporaryFile(suffix='.ztream') as stream: + with tempfile.TemporaryFile(suffix='.zstream') as stream: lzc.lzc_send(clone_snap, orig_src, stream.fileno()) stream.seek(0) with self.assertRaises(lzc_exc.DatasetNotFound): @@ -2346,7 +2352,7 @@ class ZFSTest(unittest.TestCase): with temp_file_in_fs(dstfs): pass # enough to taint the fs - with tempfile.TemporaryFile(suffix='.ztream') as stream: + with tempfile.TemporaryFile(suffix='.zstream') as stream: lzc.lzc_send(src, None, stream.fileno()) stream.seek(0) lzc.lzc_receive(dst, stream.fileno(), force=True) @@ -2361,7 +2367,7 @@ class ZFSTest(unittest.TestCase): lzc.lzc_create(dstfs) - with tempfile.TemporaryFile(suffix='.ztream') as stream: + with tempfile.TemporaryFile(suffix='.zstream') as stream: lzc.lzc_send(src, None, stream.fileno()) stream.seek(0) with zfs_mount(dstfs) as mntdir: @@ -2391,7 +2397,7 @@ class ZFSTest(unittest.TestCase): pass # enough to taint the fs lzc.lzc_snapshot([dstfs + b"@snap1"]) - with tempfile.TemporaryFile(suffix='.ztream') as stream: + with tempfile.TemporaryFile(suffix='.zstream') as stream: lzc.lzc_send(src, None, stream.fileno()) stream.seek(0) lzc.lzc_receive(dst, stream.fileno(), force=True) @@ -2409,7 +2415,7 @@ class ZFSTest(unittest.TestCase): pass # enough to taint the fs lzc.lzc_snapshot([dst]) - with tempfile.TemporaryFile(suffix='.ztream') as stream: + with tempfile.TemporaryFile(suffix='.zstream') as stream: lzc.lzc_send(src, None, stream.fileno()) stream.seek(0) with self.assertRaises(lzc_exc.DatasetExists): @@ -2421,7 +2427,7 @@ class ZFSTest(unittest.TestCase): with temp_file_in_fs(ZFSTest.pool.makeName(b"fs1")): lzc.lzc_snapshot([src]) - with tempfile.TemporaryFile(suffix='.ztream') as stream: + with tempfile.TemporaryFile(suffix='.zstream') as stream: lzc.lzc_send(src, None, stream.fileno()) stream.seek(0) with self.assertRaises(lzc_exc.DatasetNotFound): @@ -2569,7 +2575,7 @@ class ZFSTest(unittest.TestCase): with temp_file_in_fs(ZFSTest.pool.makeName(b"fs1")) as name: lzc.lzc_snapshot([src]) - with tempfile.TemporaryFile(suffix='.ztream') as stream: + with tempfile.TemporaryFile(suffix='.zstream') as stream: lzc.lzc_send(src, None, stream.fileno()) stream.seek(0) @@ -2585,6 +2591,50 @@ class ZFSTest(unittest.TestCase): filecmp.cmp( os.path.join(mnt1, name), os.path.join(mnt2, name), False)) + def test_recv_fs_below_zvol(self): + send = ZFSTest.pool.makeName(b"fs1@snap") + zvol = ZFSTest.pool.makeName(b"fs1/zvol") + dest = zvol + b"/fs@snap" + props = {b"volsize": 1024 * 1024} + + lzc.lzc_snapshot([send]) + lzc.lzc_create(zvol, ds_type='zvol', props=props) + with tempfile.TemporaryFile(suffix='.zstream') as stream: + lzc.lzc_send(send, None, stream.fileno()) + stream.seek(0) + with self.assertRaises(lzc_exc.WrongParent): + lzc.lzc_receive(dest, stream.fileno()) + + def test_recv_zvol_over_fs_with_children(self): + parent = ZFSTest.pool.makeName(b"fs1") + child = parent + b"subfs" + zvol = ZFSTest.pool.makeName(b"fs1/zvol") + send = zvol + b"@snap" + props = {b"volsize": 1024 * 1024} + + lzc.lzc_create(child) + lzc.lzc_create(zvol, ds_type='zvol', props=props) + lzc.lzc_snapshot([send]) + with tempfile.TemporaryFile(suffix='.zstream') as stream: + lzc.lzc_send(send, None, stream.fileno()) + stream.seek(0) + with self.assertRaises(lzc_exc.WrongParent): + lzc.lzc_receive(parent + b"@snap", stream.fileno(), force=True) + + def test_recv_zvol_overwrite_rootds(self): + zvol = ZFSTest.pool.makeName(b"fs1/zvol") + snap = zvol + b"@snap" + rootds = ZFSTest.pool.getRoot().getName() + props = {b"volsize": 1024 * 1024} + + lzc.lzc_create(zvol, ds_type='zvol', props=props) + lzc.lzc_snapshot([snap]) + with tempfile.TemporaryFile(suffix='.zstream') as stream: + lzc.lzc_send(snap, None, stream.fileno()) + stream.seek(0) + with self.assertRaises(lzc_exc.WrongParent): + lzc.lzc_receive(rootds + b"@snap", stream.fileno(), force=True) + def test_send_full_across_clone_branch_point(self): origfs = ZFSTest.pool.makeName(b"fs2") @@ -2596,7 +2646,7 @@ class ZFSTest(unittest.TestCase): (_, (_, tosnap, _)) = make_snapshots(clonefs, None, b"snap", None) - with tempfile.TemporaryFile(suffix='.ztream') as stream: + with tempfile.TemporaryFile(suffix='.zstream') as stream: lzc.lzc_send(tosnap, None, stream.fileno()) def test_send_incr_across_clone_branch_point(self): @@ -2610,7 +2660,7 @@ class ZFSTest(unittest.TestCase): (_, (_, tosnap, _)) = make_snapshots(clonefs, None, b"snap", None) - with tempfile.TemporaryFile(suffix='.ztream') as stream: + with tempfile.TemporaryFile(suffix='.zstream') as stream: lzc.lzc_send(tosnap, fromsnap, stream.fileno()) def test_send_resume_token_full(self): @@ -2625,7 +2675,7 @@ class ZFSTest(unittest.TestCase): f.flush() lzc.lzc_snapshot([src]) - with tempfile.NamedTemporaryFile(suffix='.ztream') as stream: + with tempfile.NamedTemporaryFile(suffix='.zstream') as stream: lzc.lzc_send(src, None, stream.fileno()) stream.seek(0) stream.truncate(1024 * 3) @@ -2656,7 +2706,7 @@ class ZFSTest(unittest.TestCase): resume_values = packed_nvlist_out(payload, packed_size) resumeobj = resume_values.get(b'object') resumeoff = resume_values.get(b'offset') - with tempfile.NamedTemporaryFile(suffix='.ztream') as rstream: + with tempfile.NamedTemporaryFile(suffix='.zstream') as rstream: lzc.lzc_send_resume( src, None, rstream.fileno(), None, resumeobj, resumeoff) rstream.seek(0) @@ -2670,7 +2720,7 @@ class ZFSTest(unittest.TestCase): dst2 = dstfs.getSnap() lzc.lzc_snapshot([snap1]) - with tempfile.NamedTemporaryFile(suffix='.ztream') as stream: + with tempfile.NamedTemporaryFile(suffix='.zstream') as stream: lzc.lzc_send(snap1, None, stream.fileno()) stream.seek(0) lzc.lzc_receive(dst1, stream.fileno()) @@ -2682,7 +2732,7 @@ class ZFSTest(unittest.TestCase): f.flush() lzc.lzc_snapshot([snap2]) - with tempfile.NamedTemporaryFile(suffix='.ztream') as stream: + with tempfile.NamedTemporaryFile(suffix='.zstream') as stream: lzc.lzc_send(snap2, snap1, stream.fileno()) stream.seek(0) stream.truncate(1024 * 3) @@ -2712,7 +2762,7 @@ class ZFSTest(unittest.TestCase): resume_values = packed_nvlist_out(payload, packed_size) resumeobj = resume_values.get(b'object') resumeoff = resume_values.get(b'offset') - with tempfile.NamedTemporaryFile(suffix='.ztream') as rstream: + with tempfile.NamedTemporaryFile(suffix='.zstream') as rstream: lzc.lzc_send_resume( snap2, snap1, rstream.fileno(), None, resumeobj, resumeoff) rstream.seek(0) @@ -2731,7 +2781,7 @@ class ZFSTest(unittest.TestCase): recvfs = ZFSTest.pool.makeName(b"fs1/recv-clone-30") recvsnap = recvfs + b"@snap" - with tempfile.TemporaryFile(suffix='.ztream') as stream: + with tempfile.TemporaryFile(suffix='.zstream') as stream: lzc.lzc_send(tosnap, None, stream.fileno()) stream.seek(0) lzc.lzc_receive(recvsnap, stream.fileno()) @@ -2741,7 +2791,7 @@ class ZFSTest(unittest.TestCase): tosnap = ZFSTest.pool.makeName(b"recv@snap1") lzc.lzc_snapshot([fromsnap]) - with tempfile.TemporaryFile(suffix='.ztream') as stream: + with tempfile.TemporaryFile(suffix='.zstream') as stream: lzc.lzc_send(fromsnap, None, stream.fileno()) stream.seek(0) (header, c_header) = lzc.receive_header(stream.fileno()) @@ -2752,7 +2802,7 @@ class ZFSTest(unittest.TestCase): tosnap = ZFSTest.pool.makeName(b"recv@snap1") lzc.lzc_snapshot([fromsnap]) - with tempfile.TemporaryFile(suffix='.ztream') as stream: + with tempfile.TemporaryFile(suffix='.zstream') as stream: lzc.lzc_send(fromsnap, None, stream.fileno()) size = os.fstat(stream.fileno()).st_size stream.seek(0) @@ -2770,7 +2820,7 @@ class ZFSTest(unittest.TestCase): } lzc.lzc_snapshot([fromsnap]) - with tempfile.TemporaryFile(suffix='.ztream') as stream: + with tempfile.TemporaryFile(suffix='.zstream') as stream: lzc.lzc_send(fromsnap, None, stream.fileno()) stream.seek(0) (header, c_header) = lzc.receive_header(stream.fileno()) @@ -2789,7 +2839,7 @@ class ZFSTest(unittest.TestCase): } lzc.lzc_snapshot([fromsnap]) - with tempfile.TemporaryFile(suffix='.ztream') as stream: + with tempfile.TemporaryFile(suffix='.zstream') as stream: lzc.lzc_send(fromsnap, None, stream.fileno()) stream.seek(0) (header, c_header) = lzc.receive_header(stream.fileno()) @@ -2813,7 +2863,7 @@ class ZFSTest(unittest.TestCase): } lzc.lzc_snapshot([fromsnap]) - with tempfile.TemporaryFile(suffix='.ztream') as stream: + with tempfile.TemporaryFile(suffix='.zstream') as stream: lzc.lzc_send(fromsnap, None, stream.fileno()) stream.seek(0) (header, c_header) = lzc.receive_header(stream.fileno()) @@ -2840,7 +2890,7 @@ class ZFSTest(unittest.TestCase): } lzc.lzc_snapshot([fromsnap]) - with tempfile.TemporaryFile(suffix='.ztream') as stream: + with tempfile.TemporaryFile(suffix='.zstream') as stream: lzc.lzc_send(fromsnap, None, stream.fileno()) stream.seek(0) (header, c_header) = lzc.receive_header(stream.fileno()) @@ -2869,11 +2919,11 @@ class ZFSTest(unittest.TestCase): recvfs = ZFSTest.pool.makeName(b"fs1/recv-clone-32") recvsnap1 = recvfs + b"@snap1" recvsnap2 = recvfs + b"@snap2" - with tempfile.TemporaryFile(suffix='.ztream') as stream: + with tempfile.TemporaryFile(suffix='.zstream') as stream: lzc.lzc_send(fromsnap, None, stream.fileno()) stream.seek(0) lzc.lzc_receive(recvsnap1, stream.fileno()) - with tempfile.TemporaryFile(suffix='.ztream') as stream: + with tempfile.TemporaryFile(suffix='.zstream') as stream: lzc.lzc_send(tosnap, fromsnap, stream.fileno()) stream.seek(0) with self.assertRaises(lzc_exc.BadStream): @@ -2893,11 +2943,11 @@ class ZFSTest(unittest.TestCase): recvfs = ZFSTest.pool.makeName(b"fs1/recv-clone-31") recvsnap1 = recvfs + b"@snap1" recvsnap2 = recvfs + b"@snap2" - with tempfile.TemporaryFile(suffix='.ztream') as stream: + with tempfile.TemporaryFile(suffix='.zstream') as stream: lzc.lzc_send(fromsnap, None, stream.fileno()) stream.seek(0) lzc.lzc_receive(recvsnap1, stream.fileno()) - with tempfile.TemporaryFile(suffix='.ztream') as stream: + with tempfile.TemporaryFile(suffix='.zstream') as stream: lzc.lzc_send(tosnap, fromsnap, stream.fileno()) stream.seek(0) with self.assertRaises(lzc_exc.BadStream): @@ -2918,11 +2968,11 @@ class ZFSTest(unittest.TestCase): recvsnap1 = recvfs1 + b"@snap" recvfs2 = ZFSTest.pool.makeName(b"fs1/recv-clone-33_2") recvsnap2 = recvfs2 + b"@snap" - with tempfile.TemporaryFile(suffix='.ztream') as stream: + with tempfile.TemporaryFile(suffix='.zstream') as stream: lzc.lzc_send(fromsnap, None, stream.fileno()) stream.seek(0) lzc.lzc_receive(recvsnap1, stream.fileno()) - with tempfile.TemporaryFile(suffix='.ztream') as stream: + with tempfile.TemporaryFile(suffix='.zstream') as stream: lzc.lzc_send(tosnap, fromsnap, stream.fileno()) stream.seek(0) lzc.lzc_receive(recvsnap2, stream.fileno(), origin=recvsnap1) @@ -3856,6 +3906,18 @@ zfs.sync.snapshot('""" + pool + b"""@zcp') with self.assertRaises(lzc_exc.FilesystemNotFound): lzc.lzc_rename(src, tgt) + @needs_support(lzc.lzc_rename) + def test_rename_parent_is_zvol(self): + src = ZFSTest.pool.makeName(b"source") + zvol = ZFSTest.pool.makeName(b"parent") + tgt = zvol + b"/target" + props = {b"volsize": 1024 * 1024} + + lzc.lzc_create(src) + lzc.lzc_create(zvol, ds_type='zvol', props=props) + with self.assertRaises(lzc_exc.WrongParent): + lzc.lzc_rename(src, tgt) + @needs_support(lzc.lzc_destroy) def test_destroy(self): fs = ZFSTest.pool.makeName(b"test-fs") |