5 # The contents of this file are subject to the terms of the
6 # Common Development and Distribution License (the "License").
7 # You may not use this file except in compliance with the License.
9 # You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
10 # or http://www.opensolaris.org/os/licensing.
11 # See the License for the specific language governing permissions
12 # and limitations under the License.
14 # When distributing Covered Code, include this CDDL HEADER in each
15 # file and include the License file at usr/src/OPENSOLARIS.LICENSE.
16 # If applicable, add the following below this CDDL HEADER, with the
17 # fields enclosed by brackets "[]" replaced with your own identifying
18 # information: Portions Copyright [yyyy] [name of copyright owner]
24 # Copyright 2017, loli10K <ezomori.nozomu@gmail.com>. All rights reserved.
25 # Copyright 2019, 2020 by Christian Schwarz. All rights reserved.
28 . $STF_SUITE/include/libtest.shlib
32 # 'zfs bookmark' should work with both full and short arguments.
35 # 1. Create initial snapshot
37 # 2. Verify we can create a bookmark specifying snapshot and bookmark full paths
38 # 3. Verify we can create a bookmark specifying the short snapshot name
39 # 4. Verify we can create a bookmark specifying the short bookmark name
40 # 5. Verify at least a full dataset path is required and both snapshot and
41 # bookmark name must be valid
43 # 6. Verify we can copy a bookmark by specifying the source bookmark and new
44 # bookmark full paths.
45 # 7. Verify we can copy a bookmark specifying the short source name
46 # 8. Verify we can copy a bookmark specifying the short new name
47 # 9. Verify two short paths are not allowed, and test empty paths
48 # 10. Verify we cannot copy a bookmark if the new bookmark already exists
49 # 11. Verify that copying a bookmark only works if new and source name
50 # have the same dataset
53 verify_runnable "both"
57 if snapexists "$DATASET@$TESTSNAP"; then
58 log_must zfs destroy "$DATASET@$TESTSNAP"
60 if bkmarkexists "$DATASET#$TESTBM"; then
61 log_must zfs destroy "$DATASET#$TESTBM"
63 if bkmarkexists "$DATASET#$TESTBMCOPY"; then
64 log_must zfs destroy "$DATASET#$TESTBMCOPY"
68 log_assert "'zfs bookmark' should work only when passed valid arguments."
71 DATASET="$TESTPOOL/$TESTFS"
72 DATASET_TWO="$TESTPOOL/${TESTFS}_two"
76 TESTBMCOPY='bookmark_copy'
79 # Create initial snapshot
80 log_must zfs snapshot "$DATASET@$TESTSNAP"
83 # Bookmark creation tests
86 # Verify we can create a bookmark specifying snapshot and bookmark full paths
87 log_must zfs bookmark "$DATASET@$TESTSNAP" "$DATASET#$TESTBM"
88 log_must eval "bkmarkexists $DATASET#$TESTBM"
89 log_must zfs destroy "$DATASET#$TESTBM"
91 # Verify we can create a bookmark specifying the snapshot name
92 log_must zfs bookmark "@$TESTSNAP" "$DATASET#$TESTBM"
93 log_must eval "bkmarkexists $DATASET#$TESTBM"
94 log_must zfs destroy "$DATASET#$TESTBM"
96 # Verify we can create a bookmark specifying the bookmark name
97 log_must zfs bookmark "$DATASET@$TESTSNAP" "#$TESTBM"
98 log_must eval "bkmarkexists $DATASET#$TESTBM"
99 log_must zfs destroy "$DATASET#$TESTBM"
101 # Verify at least a full dataset path is required and both snapshot and
102 # bookmark name must be valid
103 log_mustnot zfs bookmark "@$TESTSNAP" "#$TESTBM"
104 log_mustnot zfs bookmark "$TESTSNAP" "#$TESTBM"
105 log_mustnot zfs bookmark "@$TESTSNAP" "$TESTBM"
106 log_mustnot zfs bookmark "$TESTSNAP" "$TESTBM"
107 log_mustnot zfs bookmark "$TESTSNAP" "$DATASET#$TESTBM"
108 log_mustnot zfs bookmark "$DATASET" "$TESTBM"
109 log_mustnot zfs bookmark "$DATASET@" "$TESTBM"
110 log_mustnot zfs bookmark "$DATASET" "#$TESTBM"
111 log_mustnot zfs bookmark "$DATASET@" "#$TESTBM"
112 log_mustnot zfs bookmark "$DATASET@$TESTSNAP" "$TESTBM"
113 log_mustnot zfs bookmark "@" "#$TESTBM"
114 log_mustnot zfs bookmark "@" "#"
115 log_mustnot zfs bookmark "@$TESTSNAP" "#"
116 log_mustnot zfs bookmark "@$TESTSNAP" "$DATASET#"
117 log_mustnot zfs bookmark "@$TESTSNAP" "$DATASET"
118 log_mustnot zfs bookmark "$TESTSNAP" "$DATASET#"
119 log_mustnot zfs bookmark "$TESTSNAP" "$DATASET"
120 log_mustnot eval "bkmarkexists $DATASET#$TESTBM"
122 # Verify that we can create a bookmarks on another origin filesystem
123 log_must zfs clone "$DATASET@$TESTSNAP" "$DATASET_TWO"
124 log_must zfs bookmark "$DATASET@$TESTSNAP" "$DATASET_TWO#$TESTBM"
125 log_must eval "destroy_dataset $DATASET_TWO"
127 # Verify that we can cannot create bookmarks on a non-origin filesystem
128 log_must zfs create "$DATASET_TWO"
129 log_mustnot_expect "source is not an ancestor of the new bookmark's dataset" zfs bookmark "$DATASET@$TESTSNAP" "$DATASET_TWO#$TESTBM"
130 log_must zfs destroy "$DATASET_TWO"
132 # Verify that we can create bookmarks of snapshots on the pool dataset
133 log_must zfs snapshot "$TESTPOOL@$TESTSNAP"
134 log_must zfs bookmark "$TESTPOOL@$TESTSNAP" "$TESTPOOL#$TESTBM"
135 log_must zfs destroy "$TESTPOOL#$TESTBM"
136 log_must zfs destroy "$TESTPOOL@$TESTSNAP"
139 # Bookmark copying tests
142 # create the source bookmark
143 log_must zfs bookmark "$DATASET@$TESTSNAP" "$DATASET#$TESTBM"
145 # Verify we can copy a bookmark by specifying the source bookmark
146 # and new bookmark full paths.
147 log_must eval "bkmarkexists $DATASET#$TESTBM"
148 log_must zfs bookmark "$DATASET#$TESTBM" "$DATASET#$TESTBMCOPY"
149 log_must eval "bkmarkexists $DATASET#$TESTBMCOPY"
150 ## validate destroy once (should be truly independent bookmarks)
151 log_must zfs destroy "$DATASET#$TESTBM"
152 log_mustnot eval "bkmarkexists $DATASET#$TESTBM"
153 log_must eval "bkmarkexists $DATASET#$TESTBMCOPY"
154 log_must zfs destroy "$DATASET#$TESTBMCOPY"
155 log_mustnot eval "bkmarkexists $DATASET#$TESTBMCOPY"
156 log_mustnot eval "bkmarkexists $DATASET#$TESTBM"
157 ## recreate the source bookmark
158 log_must zfs bookmark "$DATASET@$TESTSNAP" "$DATASET#$TESTBM"
160 # Verify we can copy a bookmark specifying the short source name
161 log_must zfs bookmark "#$TESTBM" "$DATASET#$TESTBMCOPY"
162 log_must eval "bkmarkexists $DATASET#$TESTBMCOPY"
163 log_must zfs destroy "$DATASET#$TESTBMCOPY"
165 # Verify we can copy a bookmark specifying the short bookmark name
166 log_must zfs bookmark "$DATASET#$TESTBM" "#$TESTBMCOPY"
167 log_must eval "bkmarkexists $DATASET#$TESTBMCOPY"
168 log_must zfs destroy "$DATASET#$TESTBMCOPY"
170 # Verify two short paths are not allowed, and test empty paths
171 log_mustnot zfs bookmark "#$TESTBM" "#$TESTBMCOPY"
172 log_mustnot zfs bookmark "#$TESTBM" "#"
173 log_mustnot zfs bookmark "#" "#$TESTBMCOPY"
174 log_mustnot zfs bookmark "#" "#"
175 log_mustnot zfs bookmark "#" ""
176 log_mustnot zfs bookmark "" "#"
177 log_mustnot zfs bookmark "" ""
179 # Verify that we can copy bookmarks on another origin filesystem
180 log_must zfs clone "$DATASET@$TESTSNAP" "$DATASET_TWO"
181 log_must zfs bookmark "$DATASET#$TESTBM" "$DATASET_TWO#$TESTBMCOPY"
182 log_must zfs destroy "$DATASET_TWO"
184 # Verify that we can cannot create bookmarks on another non-origin filesystem
185 log_must zfs create "$DATASET_TWO"
186 log_mustnot_expect "source is not an ancestor of the new bookmark's dataset" zfs bookmark "$DATASET#$TESTBM" "$DATASET_TWO#$TESTBMCOPY"
187 log_must zfs destroy "$DATASET_TWO"
189 # Verify that we can copy bookmarks on the pool dataset
190 log_must zfs snapshot "$TESTPOOL@$TESTSNAP"
191 log_must zfs bookmark "$TESTPOOL@$TESTSNAP" "$TESTPOOL#$TESTBM"
192 log_must zfs bookmark "$TESTPOOL#$TESTBM" "$TESTPOOL#$TESTBMCOPY"
193 log_must zfs destroy "$TESTPOOL#$TESTBM"
194 log_must zfs destroy "$TESTPOOL#$TESTBMCOPY"
195 log_must zfs destroy "$TESTPOOL@$TESTSNAP"
197 # Verify that copied 'normal' bookmarks are independent of the source bookmark
198 log_must zfs bookmark "$DATASET#$TESTBM" "$DATASET#$TESTBMCOPY"
199 log_must zfs destroy "$DATASET#$TESTBM"
200 log_must eval "zfs send $DATASET@$TESTSNAP > $TEST_BASE_DIR/zfstest_datastream.$$"
201 log_must eval "destroy_dataset $TESTPOOL/$TESTFS/recv"
202 log_must eval "zfs recv -o mountpoint=none $TESTPOOL/$TESTFS/recv < $TEST_BASE_DIR/zfstest_datastream.$$"
203 log_must zfs snapshot "$DATASET@$TESTSNAP2"
204 log_must eval "zfs send -i \#$TESTBMCOPY $DATASET@$TESTSNAP2 > $TEST_BASE_DIR/zfstest_datastream.$$"
205 log_must eval "zfs recv $TESTPOOL/$TESTFS/recv < $TEST_BASE_DIR/zfstest_datastream.$$"
207 log_must eval "destroy_dataset $DATASET@$TESTSNAP2"
208 log_must zfs destroy "$DATASET#$TESTBMCOPY"
209 log_must zfs bookmark "$DATASET@$TESTSNAP" "$DATASET#$TESTBM"
211 # Verify that copied redaction bookmarks are independent of the source bookmark
212 ## create redaction bookmark
213 log_must zfs destroy "$DATASET#$TESTBM"
214 log_must zfs destroy "$DATASET@$TESTSNAP"
215 log_must eval "echo secret > $TESTDIR/secret"
216 log_must zfs snapshot "$DATASET@$TESTSNAP"
217 log_must eval "echo redacted > $TESTDIR/secret"
218 log_must zfs snapshot "$DATASET@$TESTSNAP2" # TESTSNAP2 is the redaction snapshot
219 log_must zfs list -t all -o name,createtxg,guid,mountpoint,written
220 log_must zfs redact "$DATASET@$TESTSNAP" "$TESTBM" "$DATASET@$TESTSNAP2"
221 # ensure our primitive for testing whether a bookmark is a redaction bookmark works
222 log_must eval "zfs get all $DATASET#$TESTBM | grep redact_snaps"
223 ## copy the redaction bookmark
224 log_must zfs bookmark "$DATASET#$TESTBM" "#$TESTBMCOPY"
225 log_mustnot eval "zfs get all $DATASET#$TESTBMCOPY | grep redact_snaps"
226 log_must eval "zfs send --redact "$TESTBMCOPY" -i $DATASET@$TESTSNAP $DATASET@$TESTSNAP2 2>&1 | head -n 100 | grep 'not a redaction bookmark'"
227 # try the above again after destroying the source bookmark, preventive measure for future work
228 log_must zfs destroy "$DATASET#$TESTBM"
229 log_mustnot eval "zfs get all $DATASET#$TESTBMCOPY | grep redact_snaps"
230 log_must eval "zfs send --redact "$TESTBMCOPY" -i $DATASET@$TESTSNAP $DATASET@$TESTSNAP2 2>&1 | head -n 100 | grep 'not a redaction bookmark'"
232 log_must eval "destroy_dataset $DATASET@$TESTSNAP2"
233 log_must zfs destroy "$DATASET#$TESTBMCOPY"
234 log_must eval "destroy_dataset $DATASET@$TESTSNAP"
235 log_must zfs snapshot "$DATASET@$TESTSNAP"
236 log_must zfs bookmark "$DATASET@$TESTSNAP" "$DATASET#$TESTBM"
238 log_pass "'zfs bookmark' works as expected"