diff --git a/SOURCES/kdump-lib.sh b/SOURCES/kdump-lib.sh
index 8ae8617..034638c 100755
--- a/SOURCES/kdump-lib.sh
+++ b/SOURCES/kdump-lib.sh
@@ -819,3 +819,187 @@ prepare_cmdline()
 
     echo ${cmdline}
 }
+
+#get system memory size in the unit of GB
+get_system_size()
+{
+    result=$(cat /proc/iomem  | grep "System RAM" | awk -F ":" '{ print $1 }' | tr [:lower:] [:upper:] | paste -sd+)
+    result="+$result"
+    # replace '-' with '+0x' and '+' with '-0x'
+    sum=$( echo $result | sed -e 's/-/K0x/g' | sed -e 's/+/-0x/g' | sed -e 's/K/+/g' )
+    size=$(printf "%d\n" $(($sum)))
+
+    # in MB unit
+    let size=$size/1024/1024
+    # since RHEL-8.5 kernel round up total memory to 128M, so should user space
+    let size=($size+127)/128
+    let size=$size*128
+    # in GB unit
+    let size=$size/1024
+
+    echo $size
+}
+
+get_recommend_size()
+{
+    local mem_size=$1
+    local _ck_cmdline=$2
+    local OLDIFS="$IFS"
+
+    last_sz=""
+    last_unit=""
+
+    IFS=','
+    for i in $_ck_cmdline; do
+        end=$(echo $i | awk -F "-" '{ print $2 }' | awk -F ":" '{ print $1 }')
+        recommend=$(echo $i | awk -F "-" '{ print $2 }' | awk -F ":" '{ print $2 }')
+        size=${end: : -1}
+        unit=${end: -1}
+        if [ $unit == 'T' ]; then
+            let size=$size*1024
+        fi
+        if [ $mem_size -lt $size ]; then
+            echo $recommend
+            IFS="$OLDIFS"
+            return
+        fi
+    done
+    IFS="$OLDIFS"
+}
+
+# return recommended size based on current system RAM size
+kdump_get_arch_recommend_size()
+{
+    if ! [[ -r "/proc/iomem" ]] ; then
+        echo "Error, can not access /proc/iomem."
+        return 1
+    fi
+    arch=$(lscpu | grep Architecture | awk -F ":" '{ print $2 }' | tr [:lower:] [:upper:])
+
+    if [ $arch == "X86_64" ] || [ $arch == "S390" ]; then
+        ck_cmdline="1G-4G:160M,4G-64G:192M,64G-1T:256M,1T-:512M"
+    elif [ $arch == "ARM64" ]; then
+        ck_cmdline="2G-:448M"
+    elif [ $arch == "PPC64LE" ]; then
+        if is_fadump_capable; then
+            ck_cmdline="4G-16G:768M,16G-64G:1G,64G-128G:2G,128G-1T:4G,1T-2T:6G,2T-4T:12G,4T-8T:20G,8T-16T:36G,16T-32T:64G,32T-64T:128G,64T-:180G"
+        else
+            ck_cmdline="2G-4G:384M,4G-16G:512M,16G-64G:1G,64G-128G:2G,128G-:4G"
+        fi
+    fi
+
+    ck_cmdline=$(echo $ck_cmdline | sed -e 's/-:/-102400T:/g')
+    sys_mem=$(get_system_size)
+    result=$(get_recommend_size $sys_mem "$ck_cmdline")
+    echo $result
+    return 0
+}
+
+# Print all underlying crypt devices of a block device
+# print nothing if device is not on top of a crypt device
+# $1: the block device to be checked in maj:min format
+get_luks_crypt_dev()
+{
+    [[ -b /dev/block/$1 ]] || return 1
+
+    local _type=$(eval "$(blkid -u filesystem,crypto -o export -- /dev/block/$1); echo \$TYPE")
+    [[ $_type == "crypto_LUKS" ]] && echo $1
+
+    for _x in /sys/dev/block/$1/slaves/*; do
+        [[ -f $_x/dev ]] || continue
+        [[ $_x/subsystem -ef /sys/class/block ]] || continue
+        get_luks_crypt_dev "$(< "$_x/dev")"
+    done
+}
+
+# kdump_get_maj_min <device>
+# Prints the major and minor of a device node.
+# Example:
+# $ get_maj_min /dev/sda2
+# 8:2
+kdump_get_maj_min() {
+    local _majmin
+    _majmin="$(stat -L -c '%t:%T' "$1" 2> /dev/null)"
+    printf "%s" "$((0x${_majmin%:*})):$((0x${_majmin#*:}))"
+}
+
+get_all_kdump_crypt_dev()
+{
+    local _dev _crypt
+
+    for _dev in $(get_block_dump_target); do
+        _crypt=$(get_luks_crypt_dev $(kdump_get_maj_min "$_dev"))
+        [[ -n "$_crypt" ]] && echo $_crypt
+    done
+}
+
+check_vmlinux()
+{
+    # Use readelf to check if it's a valid ELF
+    readelf -h $1 &>/dev/null || return 1
+}
+
+get_vmlinux_size()
+{
+    local size=0
+
+    while read _type _offset _virtaddr _physaddr _fsize _msize _flg _aln; do
+        size=$(( $size + $_msize ))
+    done <<< $(readelf -l -W $1 | grep "^  LOAD" 2>/dev/stderr)
+
+    echo $size
+}
+
+try_decompress()
+{
+    # The obscure use of the "tr" filter is to work around older versions of
+    # "grep" that report the byte offset of the line instead of the pattern.
+
+    # Try to find the header ($1) and decompress from here
+    for pos in `tr "$1\n$2" "\n$2=" < "$4" | grep -abo "^$2"`
+    do
+        if ! type -P $3 > /dev/null; then
+            ddebug "Signiature detected but '$3' is missing, skip this decompressor"
+            break
+        fi
+
+        pos=${pos%%:*}
+        tail -c+$pos "$img" | $3 > $5 2> /dev/null
+        if check_vmlinux $5; then
+            ddebug "Kernel is extracted with '$3'"
+            return 0
+        fi
+    done
+
+    return 1
+}
+
+# Borrowed from linux/scripts/extract-vmlinux
+get_kernel_size()
+{
+    # Prepare temp files:
+    local img=$1 tmp=$(mktemp /tmp/vmlinux-XXX)
+    trap "rm -f $tmp" 0
+
+    # Try to check if it's a vmlinux already
+    check_vmlinux $img && get_vmlinux_size $img && return 0
+
+    # That didn't work, so retry after decompression.
+    try_decompress '\037\213\010' xy    gunzip    $img $tmp || \
+    try_decompress '\3757zXZ\000' abcde unxz      $img $tmp || \
+    try_decompress 'BZh'          xy    bunzip2   $img $tmp || \
+    try_decompress '\135\0\0\0'   xxx   unlzma    $img $tmp || \
+    try_decompress '\211\114\132' xy    'lzop -d' $img $tmp || \
+    try_decompress '\002!L\030'   xxx   'lz4 -d'  $img $tmp || \
+    try_decompress '(\265/\375'   xxx   unzstd    $img $tmp
+
+    # Finally check for uncompressed images or objects:
+    [[ $? -eq 0 ]] && get_vmlinux_size $tmp && return 0
+
+    # Fallback to use iomem
+    local _size=0
+    for _seg in $(cat /proc/iomem  | grep -E "Kernel (code|rodata|data|bss)" | cut -d ":" -f 1); do
+	    _size=$(( $_size + 0x${_seg#*-} - 0x${_seg%-*} ))
+    done
+    echo $_size
+}
diff --git a/SOURCES/kdumpctl b/SOURCES/kdumpctl
index c3ada0d..7bdbf6f 100755
--- a/SOURCES/kdumpctl
+++ b/SOURCES/kdumpctl
@@ -1217,6 +1217,97 @@ rebuild() {
 	return $?
 }
 
+do_estimate() {
+	local kdump_mods
+	local -A large_mods
+	local baseline
+	local kernel_size mod_size initrd_size baseline_size runtime_size reserved_size estimated_size recommanded_size
+	local size_mb=$(( 1024 * 1024 ))
+
+	setup_initrd
+	if [ ! -f "$TARGET_INITRD" ]; then
+		derror "kdumpctl estimate: kdump initramfs is not built yet."
+		exit 1
+	fi
+
+	kdump_mods="$(lsinitrd "$TARGET_INITRD" -f /usr/lib/dracut/loaded-kernel-modules.txt | tr '\n' ' ')"
+	baseline=$(kdump_get_arch_recommend_size)
+	if [[ "${baseline: -1}" == "M" ]]; then
+		baseline=${baseline%M}
+	elif [[ "${baseline: -1}" == "G" ]]; then
+		baseline=$(( ${baseline%G} * 1024 ))
+	elif [[ "${baseline: -1}" == "T" ]]; then
+		baseline=$(( ${baseline%Y} * 1048576 ))
+	fi
+
+	# The default value when using crashkernel=auto
+	baseline_size=$((baseline * size_mb))
+	# Current reserved crashkernel size
+	reserved_size=$(cat /sys/kernel/kexec_crash_size)
+	# A pre-estimated value for userspace usage and kernel
+	# runtime allocation, 64M should good for most cases
+	runtime_size=$((64 * size_mb))
+	# Kernel image size
+	kernel_size=$(get_kernel_size "$KDUMP_KERNEL")
+	# Kdump initramfs size
+	initrd_size=$(du -b "$TARGET_INITRD" | awk '{print $1}')
+	# Kernel modules static size after loaded
+	mod_size=0
+	while read -r _name _size _; do
+		if [[ ! " $kdump_mods " == *" $_name "* ]]; then
+			continue
+		fi
+		mod_size=$((mod_size + _size))
+
+		# Mark module with static size larger than 2M as large module
+		if [[ $((_size / size_mb)) -ge 1 ]]; then
+			large_mods[$_name]=$_size
+		fi
+	done <<< "$(< /proc/modules)"
+
+	# Extra memory usage required for LUKS2 decryption
+	crypt_size=0
+	for _dev in $(get_all_kdump_crypt_dev); do
+		_crypt_info=$(cryptsetup luksDump "/dev/block/$_dev")
+		[[ $(echo "$_crypt_info" | sed -n "s/^Version:\s*\(.*\)/\1/p" ) == "2" ]] || continue
+		for _mem in $(echo "$_crypt_info" | sed -n "s/\sMemory:\s*\(.*\)/\1/p" | sort -n ); do
+			crypt_size=$((crypt_size + _mem * 1024))
+			break
+		done
+	done
+	[[ $crypt_size -ne 0 ]] && echo -e "Encrypted kdump target requires extra memory, assuming using the keyslot with minimun memory requirement\n"
+
+	estimated_size=$((kernel_size + mod_size + initrd_size + runtime_size + crypt_size))
+	if [[ $baseline_size -gt $estimated_size ]]; then
+		recommanded_size=$baseline_size
+	else
+		recommanded_size=$estimated_size
+	fi
+
+	echo "Reserved crashkernel:    $((reserved_size / size_mb))M"
+	echo "Recommanded crashkernel: $((recommanded_size / size_mb))M"
+	echo
+	echo "Kernel image size:   $((kernel_size / size_mb))M"
+	echo "Kernel modules size: $((mod_size / size_mb))M"
+	echo "Initramfs size:      $((initrd_size / size_mb))M"
+	echo "Runtime reservation: $((runtime_size / size_mb))M"
+	[[ $crypt_size -ne 0 ]] && \
+	echo "LUKS required size:  $((crypt_size / size_mb))M"
+	echo -n "Large modules:"
+	if [[ "${#large_mods[@]}" -eq 0 ]]; then
+		echo " <none>"
+	else
+		echo ""
+		for _mod in "${!large_mods[@]}"; do
+			echo "    $_mod: ${large_mods[$_mod]}"
+		done
+	fi
+
+	if [[ $reserved_size -lt $recommanded_size ]]; then
+		echo "WARNING: Current crashkernel size is lower than recommanded size $((recommanded_size / size_mb))M."
+	fi
+}
+
 if [ ! -f "$KDUMP_CONFIG_FILE" ]; then
 	derror "Error: No kdump config file found!"
 	exit 1
@@ -1272,8 +1363,11 @@ main ()
 	  showmem)
 		show_reserved_mem
 		;;
+	  estimate)
+		do_estimate
+		;;
 	  *)
-		dinfo $"Usage: $0 {start|stop|status|restart|reload|rebuild|propagate|showmem}"
+		dinfo $"Usage: $0 {estimate|start|stop|status|restart|reload|rebuild|propagate|showmem}"
 		exit 1
 	esac
 }
diff --git a/SOURCES/kdumpctl.8 b/SOURCES/kdumpctl.8
index ae97af7..a32a972 100644
--- a/SOURCES/kdumpctl.8
+++ b/SOURCES/kdumpctl.8
@@ -44,6 +44,11 @@ impossible to use password authentication during kdump.
 .TP
 .I showmem
 Prints the size of reserved memory for crash kernel in megabytes.
+.TP
+.I estimate
+Estimate a suitable crashkernel value for current machine. This is a
+best-effort estimate. It will print a recommanded crashkernel value
+based on current kdump setup, and list some details of memory usage.
 
 .SH "SEE ALSO"
 .BR kdump.conf (5),
diff --git a/SOURCES/kexec-tools-2.0.20-makedumpfile-Add-dry-run-option-to-prevent-writing.patch b/SOURCES/kexec-tools-2.0.20-makedumpfile-Add-dry-run-option-to-prevent-writing.patch
new file mode 100644
index 0000000..631d039
--- /dev/null
+++ b/SOURCES/kexec-tools-2.0.20-makedumpfile-Add-dry-run-option-to-prevent-writing.patch
@@ -0,0 +1,177 @@
+From 3422e1d6bc3511c5af9cb05ba74ad97dd93ffd7f Mon Sep 17 00:00:00 2001
+From: Julien Thierry <jthierry@redhat.com>
+Date: Tue, 24 Nov 2020 10:45:24 +0000
+Subject: [PATCH] [PATCH 1/2] Add --dry-run option to prevent writing the
+ dumpfile
+
+Add a --dry-run option to run all operations without writing the
+dump to the output file.
+
+Signed-off-by: Julien Thierry <jthierry@redhat.com>
+Signed-off-by: Kazuhito Hagio <k-hagio-ab@nec.com>
+---
+ makedumpfile.8 |  6 ++++++
+ makedumpfile.c | 37 ++++++++++++++++++++++++++++++-------
+ makedumpfile.h |  2 ++
+ print_info.c   |  3 +++
+ 4 files changed, 41 insertions(+), 7 deletions(-)
+
+diff --git a/makedumpfile-1.6.8/makedumpfile.8 b/makedumpfile-1.6.8/makedumpfile.8
+index b68a7e3..5e902cd 100644
+--- a/makedumpfile-1.6.8/makedumpfile.8
++++ b/makedumpfile-1.6.8/makedumpfile.8
+@@ -637,6 +637,12 @@ Show the version of makedumpfile.
+ Only check whether the command-line parameters are valid or not, and exit.
+ Preferable to be given as the first parameter.
+ 
++.TP
++\fB\-\-dry-run\fR
++Do not write the output dump file while still performing operations specified
++by other options.
++This option cannot be used with the --dump-dmesg, --reassemble and -g options.
++
+ .SH ENVIRONMENT VARIABLES
+ 
+ .TP 8
+diff --git a/makedumpfile-1.6.8/makedumpfile.c b/makedumpfile-1.6.8/makedumpfile.c
+index ecd63fa..8c80c49 100644
+--- a/makedumpfile-1.6.8/makedumpfile.c
++++ b/makedumpfile-1.6.8/makedumpfile.c
+@@ -1372,6 +1372,8 @@ open_dump_file(void)
+ 	if (info->flag_flatten) {
+ 		fd = STDOUT_FILENO;
+ 		info->name_dumpfile = filename_stdout;
++	} else if (info->flag_dry_run) {
++		fd = -1;
+ 	} else if ((fd = open(info->name_dumpfile, open_flags,
+ 	    S_IRUSR|S_IWUSR)) < 0) {
+ 		ERRMSG("Can't open the dump file(%s). %s\n",
+@@ -4711,6 +4713,9 @@ write_and_check_space(int fd, void *buf, size_t buf_size, char *file_name)
+ {
+ 	int status, written_size = 0;
+ 
++	if (info->flag_dry_run)
++		return TRUE;
++
+ 	while (written_size < buf_size) {
+ 		status = write(fd, buf + written_size,
+ 				   buf_size - written_size);
+@@ -4748,13 +4753,12 @@ write_buffer(int fd, off_t offset, void *buf, size_t buf_size, char *file_name)
+ 		}
+ 		if (!write_and_check_space(fd, &fdh, sizeof(fdh), file_name))
+ 			return FALSE;
+-	} else {
+-		if (lseek(fd, offset, SEEK_SET) == failed) {
+-			ERRMSG("Can't seek the dump file(%s). %s\n",
+-			    file_name, strerror(errno));
+-			return FALSE;
+-		}
++	} else if (!info->flag_dry_run &&
++		    lseek(fd, offset, SEEK_SET) == failed) {
++		ERRMSG("Can't seek the dump file(%s). %s\n", file_name, strerror(errno));
++		return FALSE;
+ 	}
++
+ 	if (!write_and_check_space(fd, buf, buf_size, file_name))
+ 		return FALSE;
+ 
+@@ -9112,7 +9116,7 @@ close_dump_memory(void)
+ void
+ close_dump_file(void)
+ {
+-	if (info->flag_flatten)
++	if (info->flag_flatten || info->flag_dry_run)
+ 		return;
+ 
+ 	if (close(info->fd_dumpfile) < 0)
+@@ -10985,6 +10989,11 @@ check_param_for_generating_vmcoreinfo(int argc, char *argv[])
+ 
+ 		return FALSE;
+ 
++	if (info->flag_dry_run) {
++		MSG("--dry-run cannot be used with -g.\n");
++		return FALSE;
++	}
++
+ 	return TRUE;
+ }
+ 
+@@ -11029,6 +11038,11 @@ check_param_for_reassembling_dumpfile(int argc, char *argv[])
+ 	    || info->flag_exclude_xen_dom || info->flag_split)
+ 		return FALSE;
+ 
++	if (info->flag_dry_run) {
++		MSG("--dry-run cannot be used with --reassemble.\n");
++		return FALSE;
++	}
++
+ 	if ((info->splitting_info
+ 	    = malloc(sizeof(struct splitting_info) * info->num_dumpfile))
+ 	    == NULL) {
+@@ -11057,6 +11071,11 @@ check_param_for_creating_dumpfile(int argc, char *argv[])
+ 	    || (info->flag_read_vmcoreinfo && info->name_xen_syms))
+ 		return FALSE;
+ 
++	if (info->flag_dry_run && info->flag_dmesg) {
++		MSG("--dry-run cannot be used with --dump-dmesg.\n");
++		return FALSE;
++	}
++
+ 	if (info->flag_flatten && info->flag_split)
+ 		return FALSE;
+ 
+@@ -11520,6 +11539,7 @@ static struct option longopts[] = {
+ 	{"work-dir", required_argument, NULL, OPT_WORKING_DIR},
+ 	{"num-threads", required_argument, NULL, OPT_NUM_THREADS},
+ 	{"check-params", no_argument, NULL, OPT_CHECK_PARAMS},
++	{"dry-run", no_argument, NULL, OPT_DRY_RUN},
+ 	{0, 0, 0, 0}
+ };
+ 
+@@ -11686,6 +11706,9 @@ main(int argc, char *argv[])
+ 			info->flag_check_params = TRUE;
+ 			message_level = DEFAULT_MSG_LEVEL;
+ 			break;
++		case OPT_DRY_RUN:
++			info->flag_dry_run = TRUE;
++			break;
+ 		case '?':
+ 			MSG("Commandline parameter is invalid.\n");
+ 			MSG("Try `makedumpfile --help' for more information.\n");
+diff --git a/makedumpfile-1.6.8/makedumpfile.h b/makedumpfile-1.6.8/makedumpfile.h
+index 5f50080..4c4222c 100644
+--- a/makedumpfile-1.6.8/makedumpfile.h
++++ b/makedumpfile-1.6.8/makedumpfile.h
+@@ -1322,6 +1322,7 @@ struct DumpInfo {
+ 	int		flag_vmemmap;        /* kernel supports vmemmap address space */
+ 	int		flag_excludevm;      /* -e - excluding unused vmemmap pages */
+ 	int		flag_use_count;      /* _refcount is named _count in struct page */
++	int		flag_dry_run;        /* do not create a vmcore file */
+ 	unsigned long	vaddr_for_vtop;      /* virtual address for debugging */
+ 	long		page_size;           /* size of page */
+ 	long		page_shift;
+@@ -2425,6 +2426,7 @@ struct elf_prstatus {
+ #define OPT_NUM_THREADS         OPT_START+16
+ #define OPT_PARTIAL_DMESG       OPT_START+17
+ #define OPT_CHECK_PARAMS        OPT_START+18
++#define OPT_DRY_RUN             OPT_START+19
+ 
+ /*
+  * Function Prototype.
+diff --git a/makedumpfile-1.6.8/print_info.c b/makedumpfile-1.6.8/print_info.c
+index e0c38b4..d2b0cb7 100644
+--- a/makedumpfile-1.6.8/print_info.c
++++ b/makedumpfile-1.6.8/print_info.c
+@@ -308,6 +308,9 @@ print_usage(void)
+ 	MSG("      the crashkernel range, then calculates the page number of different kind per\n");
+ 	MSG("      vmcoreinfo. So currently /proc/kcore need be specified explicitly.\n");
+ 	MSG("\n");
++	MSG("  [--dry-run]:\n");
++	MSG("      This option runs makedumpfile without writting output dump file.\n");
++	MSG("\n");
+ 	MSG("  [-D]:\n");
+ 	MSG("      Print debugging message.\n");
+ 	MSG("\n");
+-- 
+2.29.2
+
diff --git a/SOURCES/kexec-tools-2.0.20-makedumpfile-Add-shorthand-show-stats-option-to-show.patch b/SOURCES/kexec-tools-2.0.20-makedumpfile-Add-shorthand-show-stats-option-to-show.patch
new file mode 100644
index 0000000..5e935f0
--- /dev/null
+++ b/SOURCES/kexec-tools-2.0.20-makedumpfile-Add-shorthand-show-stats-option-to-show.patch
@@ -0,0 +1,107 @@
+From 6f3e75a558ed50d6ff0b42e3f61c099b2005b7bb Mon Sep 17 00:00:00 2001
+From: Julien Thierry <jthierry@redhat.com>
+Date: Tue, 24 Nov 2020 10:45:25 +0000
+Subject: [PATCH] [PATCH 2/2] Add shorthand --show-stats option to show report
+ stats
+
+Provide shorthand --show-stats option to enable report messages
+without needing to set a particular value for message-level.
+
+Signed-off-by: Julien Thierry <jthierry@redhat.com>
+Signed-off-by: Kazuhito Hagio <k-hagio-ab@nec.com>
+---
+ makedumpfile.8 | 5 +++++
+ makedumpfile.c | 9 ++++++++-
+ makedumpfile.h | 1 +
+ print_info.c   | 7 ++++++-
+ 4 files changed, 20 insertions(+), 2 deletions(-)
+
+diff --git a/makedumpfile-1.6.8/makedumpfile.8 b/makedumpfile-1.6.8/makedumpfile.8
+index 5e902cd..dcca2dd 100644
+--- a/makedumpfile-1.6.8/makedumpfile.8
++++ b/makedumpfile-1.6.8/makedumpfile.8
+@@ -643,6 +643,11 @@ Do not write the output dump file while still performing operations specified
+ by other options.
+ This option cannot be used with the --dump-dmesg, --reassemble and -g options.
+ 
++.TP
++\fB\-\-show-stats\fR
++Display report messages. This is an alternative to enabling bit 4 in the level
++provided to --message-level.
++
+ .SH ENVIRONMENT VARIABLES
+ 
+ .TP 8
+diff --git a/makedumpfile-1.6.8/makedumpfile.c b/makedumpfile-1.6.8/makedumpfile.c
+index 8c80c49..ba0003a 100644
+--- a/makedumpfile-1.6.8/makedumpfile.c
++++ b/makedumpfile-1.6.8/makedumpfile.c
+@@ -11540,13 +11540,14 @@ static struct option longopts[] = {
+ 	{"num-threads", required_argument, NULL, OPT_NUM_THREADS},
+ 	{"check-params", no_argument, NULL, OPT_CHECK_PARAMS},
+ 	{"dry-run", no_argument, NULL, OPT_DRY_RUN},
++	{"show-stats", no_argument, NULL, OPT_SHOW_STATS},
+ 	{0, 0, 0, 0}
+ };
+ 
+ int
+ main(int argc, char *argv[])
+ {
+-	int i, opt, flag_debug = FALSE;
++	int i, opt, flag_debug = FALSE, flag_show_stats = FALSE;
+ 
+ 	if ((info = calloc(1, sizeof(struct DumpInfo))) == NULL) {
+ 		ERRMSG("Can't allocate memory for the pagedesc cache. %s.\n",
+@@ -11709,6 +11710,9 @@ main(int argc, char *argv[])
+ 		case OPT_DRY_RUN:
+ 			info->flag_dry_run = TRUE;
+ 			break;
++		case OPT_SHOW_STATS:
++			flag_show_stats = TRUE;
++			break;
+ 		case '?':
+ 			MSG("Commandline parameter is invalid.\n");
+ 			MSG("Try `makedumpfile --help' for more information.\n");
+@@ -11718,6 +11722,9 @@ main(int argc, char *argv[])
+ 	if (flag_debug)
+ 		message_level |= ML_PRINT_DEBUG_MSG;
+ 
++	if (flag_show_stats)
++		message_level |= ML_PRINT_REPORT_MSG;
++
+ 	if (info->flag_check_params)
+ 		/* suppress debugging messages */
+ 		message_level = DEFAULT_MSG_LEVEL;
+diff --git a/makedumpfile-1.6.8/makedumpfile.h b/makedumpfile-1.6.8/makedumpfile.h
+index 4c4222c..2fcb62e 100644
+--- a/makedumpfile-1.6.8/makedumpfile.h
++++ b/makedumpfile-1.6.8/makedumpfile.h
+@@ -2427,6 +2427,7 @@ struct elf_prstatus {
+ #define OPT_PARTIAL_DMESG       OPT_START+17
+ #define OPT_CHECK_PARAMS        OPT_START+18
+ #define OPT_DRY_RUN             OPT_START+19
++#define OPT_SHOW_STATS          OPT_START+20
+ 
+ /*
+  * Function Prototype.
+diff --git a/makedumpfile-1.6.8/print_info.c b/makedumpfile-1.6.8/print_info.c
+index d2b0cb7..ad4184e 100644
+--- a/makedumpfile-1.6.8/print_info.c
++++ b/makedumpfile-1.6.8/print_info.c
+@@ -309,7 +309,12 @@ print_usage(void)
+ 	MSG("      vmcoreinfo. So currently /proc/kcore need be specified explicitly.\n");
+ 	MSG("\n");
+ 	MSG("  [--dry-run]:\n");
+-	MSG("      This option runs makedumpfile without writting output dump file.\n");
++	MSG("      Do not write the output dump file while still performing operations specified\n");
++	MSG("      by other options.  This option cannot be used with --dump-dmesg, --reassemble\n");
++	MSG("      and -g options.\n");
++	MSG("\n");
++	MSG("  [--show-stats]:\n");
++	MSG("      Set message-level to print report messages\n");
+ 	MSG("\n");
+ 	MSG("  [-D]:\n");
+ 	MSG("      Print debugging message.\n");
+-- 
+2.29.2
+
diff --git a/SOURCES/kexec-tools-2.0.20-makedumpfile-Show-write-byte-size-in-report-messages.patch b/SOURCES/kexec-tools-2.0.20-makedumpfile-Show-write-byte-size-in-report-messages.patch
new file mode 100644
index 0000000..337288e
--- /dev/null
+++ b/SOURCES/kexec-tools-2.0.20-makedumpfile-Show-write-byte-size-in-report-messages.patch
@@ -0,0 +1,59 @@
+From 0ef2ca6c9fa2f61f217a4bf5d7fd70f24e12b2eb Mon Sep 17 00:00:00 2001
+From: Kazuhito Hagio <k-hagio-ab@nec.com>
+Date: Thu, 4 Feb 2021 16:29:06 +0900
+Subject: [PATCH] [PATCH] Show write byte size in report messages
+
+Show write byte size in report messages.  This value can be different
+from the size of the actual file because of some holes on dumpfile
+data structure.
+
+  $ makedumpfile --show-stats -l -d 1 vmcore dump.ld1
+  ...
+  Total pages     : 0x0000000000080000
+  Write bytes     : 377686445
+  ...
+  # ls -l dump.ld1
+  -rw------- 1 root root 377691573 Feb  4 16:28 dump.ld1
+
+Note that this value should not be used with /proc/kcore to determine
+how much disk space is needed for crash dump, because the real memory
+usage when a crash occurs can vary widely.
+
+Signed-off-by: Kazuhito Hagio <k-hagio-ab@nec.com>
+---
+ makedumpfile.c | 5 +++++
+ 1 file changed, 5 insertions(+)
+
+diff --git a/makedumpfile-1.6.8/makedumpfile.c b/makedumpfile-1.6.8/makedumpfile.c
+index fcd766b..894c88e 100644
+--- a/makedumpfile-1.6.8/makedumpfile.c
++++ b/makedumpfile-1.6.8/makedumpfile.c
+@@ -48,6 +48,8 @@ char filename_stdout[] = FILENAME_STDOUT;
+ static unsigned long long	cache_hit;
+ static unsigned long long	cache_miss;
+ 
++static unsigned long long	write_bytes;
++
+ static void first_cycle(mdf_pfn_t start, mdf_pfn_t max, struct cycle *cycle)
+ {
+ 	cycle->start_pfn = round(start, info->pfn_cyclic);
+@@ -4715,6 +4717,8 @@ write_and_check_space(int fd, void *buf, size_t buf_size, char *file_name)
+ {
+ 	int status, written_size = 0;
+ 
++	write_bytes += buf_size;
++
+ 	if (info->flag_dry_run)
+ 		return TRUE;
+ 
+@@ -10002,6 +10006,7 @@ print_report(void)
+ 	REPORT_MSG("Memory Hole     : 0x%016llx\n", pfn_memhole);
+ 	REPORT_MSG("--------------------------------------------------\n");
+ 	REPORT_MSG("Total pages     : 0x%016llx\n", info->max_mapnr);
++	REPORT_MSG("Write bytes     : %llu\n", write_bytes);
+ 	REPORT_MSG("\n");
+ 	REPORT_MSG("Cache hit: %lld, miss: %lld", cache_hit, cache_miss);
+ 	if (cache_hit + cache_miss)
+-- 
+2.29.2
+
diff --git a/SOURCES/mkdumprd b/SOURCES/mkdumprd
index 6e923fe..13945ab 100644
--- a/SOURCES/mkdumprd
+++ b/SOURCES/mkdumprd
@@ -305,7 +305,6 @@ get_override_resettable()
     fi
 }
 
-
 # $1: function name
 for_each_block_target()
 {
@@ -320,8 +319,6 @@ for_each_block_target()
     return 0
 }
 
-
-
 #judge if a specific device with $1 is unresettable
 #return false if unresettable.
 is_unresettable()
@@ -358,32 +355,15 @@ check_resettable()
     return 1
 }
 
-# $1: maj:min
-is_crypt()
-{
-    local majmin=$1 dev line ID_FS_TYPE=""
-
-    line=$(udevadm info --query=property --path=/sys/dev/block/$majmin \
-            | grep "^ID_FS_TYPE")
-    eval "$line"
-    [[ "$ID_FS_TYPE" = "crypto_LUKS" ]] && {
-        dev=$(udevadm info --query=all --path=/sys/dev/block/$majmin | awk -F= '/DEVNAME/{print $2}')
-        derror "Device $dev is encrypted."
-        return 0
-    }
-    return 1
-}
-
 check_crypt()
 {
-    local _ret _target
-
-    for_each_block_target is_crypt
-    _ret=$?
-
-    [ $_ret -eq 0 ] && return
+    local _dev
 
-    return 1
+    for _dev in $(get_kdump_targets); do
+        if [[ -n $(get_luks_crypt_dev "$(get_maj_min "$_dev")") ]]; then
+            derror "Device $_dev is encrypted." && return 1
+        fi
+    done
 }
 
 if ! check_resettable; then
diff --git a/SPECS/kexec-tools.spec b/SPECS/kexec-tools.spec
index 47df50f..f0c50f1 100644
--- a/SPECS/kexec-tools.spec
+++ b/SPECS/kexec-tools.spec
@@ -1,6 +1,6 @@
 Name: kexec-tools
 Version: 2.0.20
-Release: 47%{?dist}
+Release: 48%{?dist}
 License: GPLv2
 Group: Applications/System
 Summary: The kexec/kdump userspace component
@@ -111,7 +111,9 @@ Patch613: kexec-tools-2.0.20-eppic-Remove-duplicated-variable-declaration.patch
 
 # Patches 701 onward for makedumpfile
 Patch701: rhelonly-kexec-tools-2.0.20-makedumpfile-arm64-Add-support-for-ARMv8.2-LVA-52-bi.patch
-
+Patch702: kexec-tools-2.0.20-makedumpfile-Add-dry-run-option-to-prevent-writing.patch
+Patch703: kexec-tools-2.0.20-makedumpfile-Add-shorthand-show-stats-option-to-show.patch
+Patch704: kexec-tools-2.0.20-makedumpfile-Show-write-byte-size-in-report-messages.patch
 
 %description
 kexec-tools provides /usr/sbin/kexec binary that facilitates a new
@@ -141,6 +143,9 @@ tar -z -x -v -f %{SOURCE19}
 %patch612 -p1
 %patch613 -p1
 %patch701 -p1
+%patch702 -p1
+%patch703 -p1
+%patch704 -p1
 
 %ifarch ppc
 %define archdef ARCH=ppc
@@ -378,6 +383,17 @@ done
 %endif
 
 %changelog
+* Thu May 20 2021 Pingfan Liu <piliu@redhat.com> - 2.0.20-48
+- kdumpctl: Add kdumpctl estimate
+- mkdumprd: make use of the new get_luks_crypt_dev helper
+- kdump-lib.sh: introduce a helper to get all crypt dev used by kdump
+- kdump-lib.sh: introduce a helper to get underlying crypt device
+- RHEL-only: keep total memory size coherent to RHEL-only kernel patch
+- Show write byte size in report messages
+- Add shorthand --show-stats option to show report stats
+- Add --dry-run option to prevent writing the dumpfile
+- kdump-lib.sh: introduce functions to return recommened mem size
+
 * Mon May 10 2021 Pingfan Liu <piliu@redhat.com> - 2.0.20-47
 - Implement IP netmask calculation to replace "ipcalc -m"
 - kdumpctl: fix check_config error when kdump.conf is empty