comparison sbin/ftjail @ 241:acf16a85900f

Mount and unmount template datasets
author Franz Glasner <fzglas.hg@dom66.de>
date Sat, 10 Sep 2022 10:09:42 +0200
parents 04fde1941966
children 59e933b81dcf
comparison
equal deleted inserted replaced
240:04fde1941966 241:acf16a85900f
35 35
36 PARENT-BASE and PARENT-SKELETON must exist already and NAME must 36 PARENT-BASE and PARENT-SKELETON must exist already and NAME must
37 not exist. 37 not exist.
38 38
39 The datasets will not be mounted. 39 The datasets will not be mounted.
40
41 mount-tmpl [ OPTIONS ] BASE-RO SKELETON-RW MOUNTPOINT
42
43 Canonically mount the RO base and the RW skeleton into MOUNTPOINT and
44 MOUNTPOINT/skeleton
45
46 -n Do not really mount but show what would be mounted where
47 -u Alias of -n
48
49 umount-tmpl BASE-RO SKELETON_RW
50
51 Unmount mounted datasets BASE-RO and SKELETON-RW
40 52
41 ENVIRONMENT: 53 ENVIRONMENT:
42 54
43 All environment variables that affect "zfs" are effective also. 55 All environment variables that affect "zfs" are effective also.
44 56
263 find "${_mp}/boot" -type f -delete 275 find "${_mp}/boot" -type f -delete
264 } 276 }
265 277
266 278
267 # 279 #
268 # "mount" -- recursively mount a dataset including subordinate datasets 280 # _do_mount dataset mountpoint dry-run mount-natural
269 # 281 #
270 # command_mount dataset mountpoint 282 _do_mount() {
271 # 283 local _dsname _mountpoint _dry_run _mount_natural
272 command_mount() {
273 local _dsname _mountpoint
274 local _name _mp _canmount _mounted 284 local _name _mp _canmount _mounted
275 local _rootds_mountpoint _relative_mp _real_mp 285 local _rootds_mountpoint _relative_mp _real_mp
276 local _dry_run _mount_outside _mount_natural 286
277 287 _dsname="${1}"
278 _dry_run="" 288 _mountpoint="${2}"
279 _mount_outside="" 289 _dry_run="${3}"
280 _mount_natural="" 290 _mount_natural="${4}"
281 while getopts "ONnu" _opt ; do
282 case ${_opt} in
283 O)
284 _mount_outside="yes"
285 ;;
286 N)
287 _mount_natural="yes"
288 ;;
289 n|u)
290 _dry_run="yes"
291 ;;
292 \?|:)
293 return 2;
294 ;;
295 esac
296 done
297 shift $((OPTIND-1))
298 OPTIND=1
299
300 _dsname="${1-}"
301 _mountpoint="${2-}"
302 291
303 if [ -z "${_dsname}" ]; then 292 if [ -z "${_dsname}" ]; then
304 echo "ERROR: no dataset given" >&2 293 echo "ERROR: no dataset given" >&2
305 return 2 294 return 2
306 fi 295 fi
307 296
308 _rootds_mountpoint="$(zfs list -H -o mountpoint -t filesystem "${_dsname}")" || \ 297 _rootds_mountpoint="$(zfs list -H -o mountpoint -t filesystem "${_dsname}")" || \
309 { echo "ERROR: root dataset does not exist" >&2; return 1; } 298 { echo "ERROR: root dataset \`${_dsname}' does not exist" >&2; return 1; }
310 299
311 if [ -z "${_mountpoint}" ]; then 300 if [ -z "${_mountpoint}" ]; then
312 if [ "${_mount_natural}" = "yes" ]; then 301 if [ "${_mount_natural}" = "yes" ]; then
313 _mountpoint="${_rootds_mountpoint}" 302 _mountpoint="${_rootds_mountpoint}"
314 else 303 else
315 echo "ERROR: no mountpoint given" >&2 304 echo "ERROR: no mountpoint given" >&2
316 return 2 305 return 2
317 fi 306 fi
318 else 307 else
319 if [ "${_mount_natural}" = "yes" ]; then 308 if [ "${_mount_natural}" = "yes" ]; then
320 echo "ERROR: Cannot have a custom mountpoint when \"-O\" is given" >&2 309 echo "ERROR: Cannot have a custom mountpoint when mount-natural is activated" >&2
321 return 2 310 return 2
322 fi 311 fi
323 fi 312 fi
324 313
325 # Eventually remove a trailing slash 314 # Eventually remove a trailing slash
373 echo "Mounting ${_name} on ${_real_mp}" 362 echo "Mounting ${_name} on ${_real_mp}"
374 mount -t zfs "${_name}" "${_real_mp}" || return 1 363 mount -t zfs "${_name}" "${_real_mp}" || return 1
375 fi 364 fi
376 ;; 365 ;;
377 *) 366 *)
378 if [ "${_mount_outside}" = "yes" ]; then 367 echo "Skipping ${_name} because its configured ZFS mountpoint is not relative to given root dataset" 2>&1
379 if [ "${_dry_run}" = "yes" ]; then
380 echo "Would mount ${_name} on configured ZFS dataset mountpoint ${_mp}"
381 else
382 echo "Mounting ${_name} on configured ZFS dataset mountpoint ${_mp}"
383 zfs mount "${_name}" || return 1
384 fi
385 else
386 echo "Skipping ${_name} because its configured ZFS mountpoint is not relative to given root dataset" 2>&1
387 fi
388 ;; 368 ;;
389 esac 369 esac
390 done 370 done
391 371
392 return 0 372 return 0
393 } 373 }
394 } 374 }
395 375
396 376
397 # 377 #
398 # "umount" -- Recursively unmount ZFS datasets 378 # "mount-tmpl" -- recursively mount a base and skeleton datasets including subordinate datasets
399 # 379 #
400 # command_umount dataset 380 # command_mount_tmpl base-ro skeleton-rw mountpoint
401 # 381 #
402 command_umount() { 382 command_mount_tmpl() {
383 local _ds_base _ds_skel _mountpoint
384
385 local _dry_run _opt
386
387 _dry_run=""
388
389 while getopts "nu" _opt ; do
390 case ${_opt} in
391 n|u)
392 _dry_run="yes"
393 ;;
394 \?|:)
395 return 2;
396 ;;
397 esac
398 done
399 shift $((OPTIND-1))
400 OPTIND=1
401
402 _ds_base="${1-}"
403 _ds_skel="${2-}"
404 _mountpoint="${3-}"
405
406 _do_mount "${_ds_base}" "${_mountpoint}" "${_dry_run}" "" || return
407 if [ "${_dry_run}" != "yes" ]; then
408 if [ ! -d "${_mountpoint}/skeleton" ]; then
409 mkdir "${_mountpoint}/skeleton" || return
410 fi
411 fi
412 _do_mount "${_ds_skel}" "${_mountpoint}/skeleton" "${_dry_run}" "" || return
413
414 return 0
415 }
416
417
418 #
419 # _do_umount dataset
420 #
421 _do_umount() {
403 local _dsname 422 local _dsname
404 local _name _mp _rest 423 local _name _mp _rest
405 local _rootds_mountpoint 424 local _rootds_mountpoint
406 425
407 _dsname="${1-}" 426 _dsname="${1}"
408 [ -z "${_dsname}" ] && \ 427 [ -z "${_dsname}" ] && { echo "ERROR: no dataset given" >&2; return 2; }
409 { echo "ERROR: no dataset given" >&2; return 2; }
410 428
411 # Just determine whether the given dataset name exists 429 # Just determine whether the given dataset name exists
412 _rootds_mountpoint="$(zfs list -H -o mountpoint -t filesystem "${_dsname}")" || { echo "ERROR: dataset not found" >&2; return 1; } 430 _rootds_mountpoint="$(zfs list -H -o mountpoint -t filesystem "${_dsname}")" || \
431 { echo "ERROR: dataset not found" >&2; return 1; }
413 432
414 mount -t zfs -p \ 433 mount -t zfs -p \
415 | grep -E "^${_dsname}(/|\s)" \ 434 | grep -E "^${_dsname}(/|\s)" \
416 | sort -n -r \ 435 | sort -n -r \
417 | { 436 | {
419 echo "Umounting ${_name} on ${_mp}" 438 echo "Umounting ${_name} on ${_mp}"
420 umount "${_mp}" || return 1 439 umount "${_mp}" || return 1
421 done 440 done
422 return 0 441 return 0
423 } 442 }
443 }
444
445
446 #
447 # "umount-tmpl" -- umount skeleton and base datasets
448 #
449 # command_umount_tmpl ds-base ds-skeleton
450 #
451 command_umount_tmpl() {
452 local _ds_base _ds_skel
453
454 _ds_base="${1-}"
455 _ds_skel="${2-}"
456
457 [ -z "${_ds_base}" ] && { echo "ERROR: no RO base dataset given" >&2; return 2; }
458 [ -z "${_ds_skel}" ] && { echo "ERROR: no RW skeleton dataset given" >&2; return 2; }
459
460 _do_umount "${_ds_skel}" || return
461 _do_umount "${_ds_base}" || return
462
463 return 0
424 } 464 }
425 465
426 466
427 # 467 #
428 # Global option handling 468 # Global option handling
461 501
462 case "${command}" in 502 case "${command}" in
463 datasets-tmpl) 503 datasets-tmpl)
464 command_datasets_tmpl "$@" 504 command_datasets_tmpl "$@"
465 ;; 505 ;;
506 mount-tmpl)
507 command_mount_tmpl "$@"
508 ;;
509 umount-tmpl|unmount-tmpl)
510 command_umount_tmpl "$@"
511 ;;
466 populate) 512 populate)
467 command_populate "$@" 513 command_populate "$@"
468 ;; 514 ;;
469 *) 515 *)
470 echo "ERROR: unknown command \`${command}'" >&2 516 echo "ERROR: unknown command \`${command}'" >&2