diff --git a/SOURCES/weak-modules b/SOURCES/weak-modules
index bc390f9..4df7642 100644
--- a/SOURCES/weak-modules
+++ b/SOURCES/weak-modules
@@ -3,15 +3,6 @@
 # weak-modules - determine which modules are kABI compatible with installed
 #                kernels and set up the symlinks in /lib/*/weak-updates.
 #
-# This is an updated version of the script which doesn't support
-# multiple installation of the same out-of-tree module (stored in the
-# 'extra' subdirectory) for multiple kernels. This assumption is
-# supposed to be verified at the rpm level of the packages delivering
-# these modules.  There are some checks for this assumption, however we
-# really don't solve this situation. This limitation allows for a much
-# simpler version of the script. Previous version tried to work in this
-# case but was incorrect in some cases.
-
 unset LANG LC_ALL LC_COLLATE
 
 tmpdir=$(mktemp -td ${0##*/}.XXXXXX)
@@ -32,6 +23,14 @@ declare -A weak_modules_before
 declare -A groups
 declare -A grouped_modules
 
+# output of validate_weak_links, one iteration
+# short_name -> path
+declare -A compatible_modules
+
+# state for update_modules_for_krel (needed for add_kernel case)
+# short_name -> path
+declare -A installed_modules
+
 # doit:
 # A wrapper used whenever we're going to perform a real operation.
 doit() {
@@ -464,7 +463,7 @@ prepare_sandbox() {
 
     #config
     echo "search external extra built-in weak-updates" >"$conf"
-    echo "external $krel $dir" >>"$conf"
+    echo "external * $dir" >>"$conf"
 
     depmod="$depmod_orig -C $conf"
 }
@@ -491,6 +490,29 @@ finish_sandbox() {
     cp -R "${override}"/* "$wa_dir" 2>/dev/null
 }
 
+# discard_installed:
+# remove installed_modules[] from modules[]
+discard_installed()
+{
+    local short_name
+
+    for m in "${!modules[@]}"; do
+        short_name="$(module_short_name "${modules[$m]}")"
+
+        [[ -z "${installed_modules[$short_name]}" ]] && continue
+
+        unset "modules[$m]"
+    done
+}
+
+# update_installed:
+# add compatible_modules[] to installed_modules[]
+update_installed()
+{
+    for m in "${!compatible_modules[@]}"; do
+        installed_modules[$m]="${compatible_modules[$m]}"
+    done
+}
 
 #### Main logic
 
@@ -506,6 +528,7 @@ finish_sandbox() {
 #   the given kernel)
 # - check the state after validation to produce needed messages
 #   and trigger initrd regeneration if the list changed.
+#
 update_modules_for_krel() {
     local krel="$1"
     local func="$2"
@@ -517,12 +540,24 @@ update_modules_for_krel() {
 
     global_link_state_save $krel
 
+    # remove already installed from modules[]
+    discard_installed
+
+    # do not run heavy validation procedure if no modules to install
+    if [[ "${#modules[@]}" -eq 0 ]]; then
+        finish_sandbox $krel
+        return
+    fi
+
     $func $krel
 
     if ! validate_weak_links $krel && [[ -z "$force_update" ]]; then
         global_link_state_restore $krel
     fi
 
+    # add compatible to installed
+    update_installed
+
     global_link_state_announce_changes $krel
 
     finish_sandbox $krel
@@ -538,12 +573,16 @@ update_modules() {
     local func="$1"
     local force_update="$2"
     local module_krel
+    declare -a saved_modules
 
     read_modules_list || exit 1
     [[ ${#modules[@]} -gt 0 ]] || return
+    saved_modules=("${modules[@]}")
 
     for krel in $(find_installed_kernels); do
         update_modules_for_krel $krel $func $force_update
+        modules=("${saved_modules[@]}")
+        installed_modules=()
     done
 
     for module in "${modules[@]}"; do
@@ -568,7 +607,7 @@ add_weak_links() {
         module_krel="$(krel_of_module $module)"
 
         case "$module" in
-            /lib/modules/$krel/*)
+            $BASEDIR/lib/modules/$krel/*)
                 # Module already installed to the current kernel
                 continue ;;
         esac
@@ -636,6 +675,7 @@ remove_weak_links() {
 #
 # Returns 0 (success) if proposal is fine or
 #         1 (false) if some incompatible symlinks were removed
+# initializes global hashmap compatible_modules with all the valid ones
 validate_weak_links() {
     local krel="$1"
     local basedir=${BASEDIR:+-b $BASEDIR}
@@ -653,6 +693,7 @@ validate_weak_links() {
     local is_configuration_valid=0
 
     tmp=$(mktemp -p $tmpdir)
+    compatible_modules=()
 
     if ! [[ -e $tmpdir/symvers-$krel ]]; then
         [[ -e $BASEDIR/boot/symvers-$krel.gz ]] || return
@@ -715,6 +756,9 @@ validate_weak_links() {
         module_krel=$(krel_of_module $target)
 
         if [[ "$module" == "$target" ]]; then
+            short_name="$(module_short_name "$module")"
+            compatible_modules+=([$short_name]="$module")
+
             pr_verbose "Module ${module##*/} from kernel $module_krel is compatible with kernel $krel"
         fi
     done
@@ -813,9 +857,12 @@ add_modules() {
 # do_make_groups:
 # Takes tmp file which contains preprocessed modules.dep
 # output (or modules.dep)
+#
 # reads modules.dep format information from stdin
 # produces groups associative array
 # the group is a maximum subset of modules having at least a link
+#
+# more fine tuned extra filtering.
 do_make_groups()
 {
     local tmp="$1"
@@ -826,6 +873,8 @@ do_make_groups()
     while read i; do
         mods=($i)
 
+        echo "${mods[0]}" |grep -q "extra/" || continue
+
         # if the module already met, then its dependencies already counted
         module_group="${grouped_modules[${mods[0]}]}"
         [[ -n $module_group ]] && continue
@@ -834,6 +883,8 @@ do_make_groups()
         group_name="${mods[0]}"
 
         for mod in "${mods[@]}"; do
+            echo "$mod" |grep -q "extra/" || continue
+
             # if there is already such group,
             # it is a subset of the one being created
             # due to depmod output
@@ -851,26 +902,32 @@ do_make_groups()
 # preprocess output for make_groups
 # depmod -n produces also aliases, so it cuts them off
 # also it removes colon after the first module
-filter_depmod_deps()
+cut_depmod_deps()
 {
     awk 'BEGIN { pr = 1 } /^#/{ pr = 0 } pr == 1 {sub(":",""); print $0}'
 }
 
-# make_abs_path:
+# filter_extra_absoluted:
 # Takes kernel version
 # makes full path from the relative module path
 # (produced by depmod for in-kernel-dir modules)
-make_abs_path()
+# filter only extra/ modules
+filter_extra_absoluted()
 {
     local kver="$1"
     local mod
     declare -a mods
 
     while read i; do
+        # skip non-extra. The check is not perfect, but ok
+        # to speed up handling in general cases
+        echo "$i" |grep -q "extra/" || continue
+
         mods=($i)
         for j in "${!mods[@]}"; do
             mod="${mods[$j]}"
-            [[ ${mod:0:1} == "/" ]] || mod="/lib/modules/$kver/$mod"
+
+            [[ ${mod:0:1} == "/" ]] || mod="$BASEDIR/lib/modules/$kver/$mod"
             mods[$j]="$mod"
         done
         echo "${mods[@]}"
@@ -878,20 +935,20 @@ make_abs_path()
 }
 
 # make_groups:
-# takes krel and a file with the list of modules,
+# takes k -- kernel version, we are installing extras from
 # prepares and feeds to do_make_groups
 # to create the module groups (global)
 make_groups()
 {
-    local krel="$1"
-    local tmp1="$2"
+    local k="$1"
     local tmp2=$(mktemp -p $tmpdir)
+    local basedir=${BASEDIR:+-b $BASEDIR}
 
     groups=()
     grouped_modules=()
 
-    $depmod -n $krel $(cat $tmp1) 2>/dev/null |
-        filter_depmod_deps | make_abs_path $krel > $tmp2
+    $depmod -n $basedir $k 2>/dev/null |
+        cut_depmod_deps | filter_extra_absoluted $k > $tmp2
 
     do_make_groups $tmp2
 
@@ -902,6 +959,7 @@ add_kernel() {
     local krel=${1:-$(uname -r)}
     local tmp
     local no_force_update=""
+    local num
 
     tmp=$(mktemp -p $tmpdir)
 
@@ -911,17 +969,36 @@ add_kernel() {
         exit 1
     fi
 
-    for k in $(find_kernels_with_extra | rpmsort); do
+    for k in $(find_kernels_with_extra | rpmsort -r); do
         [[ "$krel" == "$k" ]] && continue
         find_modules $k extra > $tmp
 
-        is_empty_file "$tmp" || make_groups $krel $tmp
+        is_empty_file "$tmp" || make_groups $k
 
         # reuse tmp
 
+	# optimization, check independent modules in one run.
+	# first try groups with one element in each.
+	# it means independent modules, so we can safely remove
+	# incompatible links
+	# some cut and paste here
+
+	echo > $tmp
         for g in "${groups[@]}"; do
+	    num="$(echo "$g" | wc -w)"
+	    [ "$num" -gt 1 ] && continue
+
+            printf '%s\n' $g >> $tmp
+	done
+        # to avoid subshell, see the read_modules_list comment
+        read_modules_list < $tmp
+        update_modules_for_krel $krel add_weak_links force_update
+
+        for g in "${groups[@]}"; do
+	    num="$(echo "$g" | wc -w)"
+	    [ "$num" -eq 1 ] && continue
+
             printf '%s\n' $g > $tmp
-            # to avoid subshell, see the read_modules_list comment
             read_modules_list < $tmp
             update_modules_for_krel $krel add_weak_links $no_force_update
         done
diff --git a/SPECS/kmod.spec b/SPECS/kmod.spec
index 651c716..cdab2f2 100644
--- a/SPECS/kmod.spec
+++ b/SPECS/kmod.spec
@@ -1,6 +1,6 @@
 Name:		kmod
 Version:	20
-Release:	25%{?dist}
+Release:	25%{?dist}.1
 Summary:	Linux kernel module management utilities
 
 Group:		System Environment/Kernel
@@ -138,6 +138,10 @@ install -m 0644 %{SOURCE2} $RPM_BUILD_ROOT%{_sysconfdir}/depmod.d/dist.conf
 %{_libdir}/libkmod.so
 
 %changelog
+* Thu Feb  6 2020 Yauheni Kaliuta <ykaliuta@redhat.com> - 20-25.el7_7.1
+- weak-modules: backport extra/ dups fix
+  Resolves: rhbz#1799046
+
 * Wed Nov 21 2018 Yauheni Kaliuta <ykaliuta@redhat.com> - 20-25
 - weak-modules: do not make groups if there are no extra modules
   Related: rhbz#1643299