Re: [PATCH v2 1/3] kmod: modprobe: Remove holders recursively

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



On Wed, Mar 29, 2023 at 03:51:35PM +0200 Nicolas Schier wrote:
> Remove holders recursively when removal of module holders is requested.
> 
> Extend commit 42b32d30c38e ("modprobe: Fix holders removal") by removing
> also indirect holders if --remove-holders is set.  For a simple module
> dependency chain like
> 
>   module3 depends on module2
>   module2 depends on module1
> 
> 'modprobe -r --remove-holders module1' will remove module3, module2 and
> module1 in correct order:
> 
>   $ modprobe -r --remove-holders module1 --verbose
>   rmmod module3
>   rmmod module2
>   rmmod module1
> 
> (Actually, it will do the same when specifying module2 or module3 for
> removal instead of module1.)
> 
> As a side-effect, 'modprobe -r module3' (w/o --remove-holders) will also
> remove all three modules from the example above, as after removal of
> module3, module2 does not have any holders and the same holds for
> module1 after removal of module2:
> 
>   $ modprobe -r module3 --verbose
>   rmmod module3
>   rmmod module2
>   rmmod module1
> 
> Without recursive evaluation of holders, modprobe leaves module1 loaded.
> 
> Unfortunately, '--dry-run --remove-holders' breaks with indirect
> dependencies.

Ups.  This is not true anymore, I forgot to remove this sentence from the
commit message.

Kind regards,
Nicolas


> 
> Signed-off-by: Nicolas Schier <n.schier@xxxxxx>
> ---
> I am a bit unhappy about the introduction of the 'recursive' parameter
> to rmmod_do_modlist() as it always holds the same value as
> stop_on_errors; is re-using (and renaming) possibly a better option?
> 
> modprobe --remove --remove-holders --dry-run now ignores current
> refcounts of loaded modules when simulating removal of holders.
> 
> Changes in v2:
>   * Handle modules that have just been removed, gently
>   * Fix --dry-run by ignoring module refcounts (_only_ for --dry-run)
>   * Add missing kmod_module_unref_list() calls
> ---
>  tools/modprobe.c | 44 +++++++++++++++++++++++++++++++++++---------
>  1 file changed, 35 insertions(+), 9 deletions(-)
> 
> diff --git a/tools/modprobe.c b/tools/modprobe.c
> index 3b7897c..a705f88 100644
> --- a/tools/modprobe.c
> +++ b/tools/modprobe.c
> @@ -390,13 +390,27 @@ static int rmmod_do_remove_module(struct kmod_module *mod)
>  static int rmmod_do_module(struct kmod_module *mod, int flags);
>  
>  /* Remove modules in reverse order */
> -static int rmmod_do_modlist(struct kmod_list *list, bool stop_on_errors)
> +static int rmmod_do_modlist(struct kmod_list *list, bool stop_on_errors,
> +			    bool recursive)
>  {
>  	struct kmod_list *l;
>  
>  	kmod_list_foreach_reverse(l, list) {
>  		struct kmod_module *m = kmod_module_get_module(l);
> -		int r = rmmod_do_module(m, RMMOD_FLAG_IGNORE_BUILTIN);
> +		int r = 0;
> +
> +		if (recursive && kmod_module_get_initstate(m) >= 0) {
> +			struct kmod_list *holders = kmod_module_get_holders(m);
> +
> +			r = rmmod_do_modlist(holders, stop_on_errors,
> +					     recursive);
> +
> +			kmod_module_unref_list(holders);
> +		}
> +
> +		if (!r)
> +			r = rmmod_do_module(m, RMMOD_FLAG_IGNORE_BUILTIN);
> +
>  		kmod_module_unref(m);
>  
>  		if (r < 0 && stop_on_errors)
> @@ -448,15 +462,17 @@ static int rmmod_do_module(struct kmod_module *mod, int flags)
>  	}
>  
>  	/* 1. @mod's post-softdeps in reverse order */
> -	rmmod_do_modlist(post, false);
> +	rmmod_do_modlist(post, false, false);
>  
>  	/* 2. Other modules holding @mod */
>  	if (flags & RMMOD_FLAG_REMOVE_HOLDERS) {
>  		struct kmod_list *holders = kmod_module_get_holders(mod);
>  
> -		err = rmmod_do_modlist(holders, true);
> +		err = rmmod_do_modlist(holders, true, true);
>  		if (err < 0)
>  			goto error;
> +
> +		kmod_module_unref_list(holders);
>  	}
>  
>  	/* 3. @mod itself, but check for refcnt first */
> @@ -472,9 +488,16 @@ static int rmmod_do_module(struct kmod_module *mod, int flags)
>  		}
>  	}
>  
> -	if (!cmd)
> -		err = rmmod_do_remove_module(mod);
> -	else
> +	if (!cmd) {
> +		int state = kmod_module_get_initstate(mod);
> +
> +		if (state < 0) {
> +			/* Module was removed during recursive holder removal */
> +			err = 0;
> +		} else {
> +			err = rmmod_do_remove_module(mod);
> +		}
> +	} else
>  		err = command_do(mod, "remove", cmd, NULL);
>  
>  	if (err < 0)
> @@ -488,14 +511,14 @@ static int rmmod_do_module(struct kmod_module *mod, int flags)
>  		kmod_list_foreach(itr, deps) {
>  			struct kmod_module *dep = kmod_module_get_module(itr);
>  			if (kmod_module_get_refcnt(dep) == 0)
> -				rmmod_do_remove_module(dep);
> +				rmmod_do_module(dep, flags);
>  			kmod_module_unref(dep);
>  		}
>  		kmod_module_unref_list(deps);
>  	}
>  
>  	/* 5. @mod's pre-softdeps in reverse order: errors are non-fatal */
> -	rmmod_do_modlist(pre, false);
> +	rmmod_do_modlist(pre, false, false);
>  
>  error:
>  	kmod_module_unref_list(pre);
> @@ -975,6 +998,9 @@ static int do_modprobe(int argc, char **orig_argv)
>  	     fstat(fileno(stderr), &stat_buf)))
>  		use_syslog = 1;
>  
> +	if (remove_holders && dry_run)
> +		ignore_loaded = 1;
> +
>  	log_open(use_syslog);
>  
>  	if (!do_show_config) {
> 
> -- 
> 2.40.0



[Index of Archives]     [Linux USB Devel]     [Video for Linux]     [Linux Audio Users]     [Yosemite News]     [Linux Kernel]     [Linux SCSI]     [Big List of Linux Books]

  Powered by Linux