@@ -575,10 +575,10 @@ draw_snapshots() {
575
575
576
576
header=" $( header_wrap " [RETURN] duplicate" " [CTRL+C] clone only" " [CTRL+X] clone and promote" " " \
577
577
" [CTRL+N] create new snapshot" " [CTRL+J] jump into chroot" " [CTRL+D] show diff" " " \
578
- " [CTRL+L] view logs" " [CTRL+H] help" " [ESCAPE] back" ) "
578
+ " [CTRL+L] view logs" " " " [CTRL+H] help" " " " [ESCAPE] back" " " " [CTRL+R] rollback " ) "
579
579
context=" Note: for diff viewer, use tab to select/deselect up to two items"
580
580
581
- expects=" --expect=alt-x,alt-c,alt-j,alt-o,alt-n"
581
+ expects=" --expect=alt-x,alt-c,alt-j,alt-o,alt-n,alt-r "
582
582
583
583
# ${snapshots} must always be defined so that the mod-n handler can be executed
584
584
snapshots=" $( zfs list -t snapshot -H -o name " ${benv} " -S " ${sort_key} " ) "
@@ -979,6 +979,70 @@ create_snapshot() {
979
979
return 0
980
980
}
981
981
982
+ # arg1: snapshot name
983
+ # prints: nothing
984
+ # returns: 0 on success
985
+
986
+ rollback_snapshot () {
987
+ local snap pool
988
+
989
+ snap=" ${1} "
990
+ pool=" ${snap%%/* } "
991
+ if [ " ${pool} " = " ${snap} " ]; then
992
+ zerror " unable to determine pool for rollback"
993
+ return 1
994
+ fi
995
+
996
+ if ! find_be_kernels " ${snap} " > /dev/null; then
997
+ color=red delay=10 timed_prompt \
998
+ " Snapshot ${snap} has no kernels, will not roll back" \
999
+ " Use a recovery shell to manually force rollback"
1000
+ return 1
1001
+ fi
1002
+
1003
+ tput clear
1004
+ tput cnorm
1005
+ tput cup 0 0
1006
+
1007
+ cat << -EOF
1008
+ WARNING!!!
1009
+
1010
+ You are attempting to roll back to the snapshot
1011
+
1012
+ $( colorize " red" " ${snap} " )
1013
+
1014
+ This will DESTROY curent state and all newer snapshots.
1015
+
1016
+ Type $( colorize " red" " ROLLBACK" ) to proceed with the rollback.
1017
+
1018
+ Type any other text, or just press enter, to abort.
1019
+
1020
+ Proceed $( colorize " red" " [No]" ) ?
1021
+ EOF
1022
+
1023
+ decision=" $( /libexec/zfsbootmenu-input ) "
1024
+ if [ " ${decision} " != " ROLLBACK" ]; then
1025
+ zdebug " aborting rollback by user request"
1026
+ return 0
1027
+ fi
1028
+
1029
+ # Re-import pool read/write
1030
+ if ! set_rw_pool " ${pool} " ; then
1031
+ zerror " unable to set ${pool} read/write"
1032
+ return 1
1033
+ fi
1034
+
1035
+ # Make sure keys are loaded
1036
+ CLEAR_SCREEN=1 load_key " ${snap} "
1037
+
1038
+ zdebug " will roll back ${snap} "
1039
+ if ! output=" $( zfs rollback -r " ${snap} " ) " ; then
1040
+ zerror " failed to roll back snapshot ${snap} "
1041
+ zerror " ${output} "
1042
+ return 1
1043
+ fi
1044
+ }
1045
+
982
1046
# arg1: selected snapshot
983
1047
# arg2: subkey
984
1048
# prints: snapshot/filesystem creation prompt
@@ -1003,6 +1067,11 @@ snapshot_dispatcher() {
1003
1067
fi
1004
1068
zdebug " subkey: ${subkey} "
1005
1069
1070
+ if [ " ${subkey} " = " mod-r" ]; then
1071
+ rollback_snapshot " ${selected} "
1072
+ return
1073
+ fi
1074
+
1006
1075
parent_ds=" ${selected%/* } "
1007
1076
1008
1077
# Generally, stripping "/*" from $selected will also drop the snapshot part;
@@ -1016,9 +1085,8 @@ snapshot_dispatcher() {
1016
1085
fi
1017
1086
zdebug " parent_ds: ${parent_ds} "
1018
1087
1019
- # Do space calculations; bail early
1020
- case " ${subkey} " in
1021
- " enter" )
1088
+ if [ " ${subkey} " = " enter" ]; then
1089
+ # Do space calculations; bail early
1022
1090
avail_space_exact=" $( zfs list -p -H -o available " ${parent_ds} " ) "
1023
1091
be_size_exact=" $( zfs list -p -H -o refer " ${selected} " ) "
1024
1092
leftover_space=$(( avail_space_exact - be_size_exact ))
@@ -1030,8 +1098,7 @@ snapshot_dispatcher() {
1030
1098
" '${parent_ds} ' has ${avail_space} free but needs ${be_size} "
1031
1099
return 1
1032
1100
fi
1033
- ;;
1034
- esac
1101
+ fi
1035
1102
1036
1103
# Set prompt, header, existing check prefix
1037
1104
case " ${subkey} " in
0 commit comments