diff mbox series

[v3,7/10] qemu-binfmt-conf.sh: add option --reset <ARCHS>

Message ID 20190306045252.GG75@03612eec87fc
State New
Headers show
Series qemu-binfmt-conf.sh | expand

Commit Message

Unai Martinez Corral March 6, 2019, 4:52 a.m. UTC
This is a partial implementation.

Allows to remove a single or a list of already registered binfmt
interpreters. If <ARCHS> is a list, it must be comma-separated.
Valid values are those in qemu_target_list. If <ARCHS> is 'ALL', all
the existing 'qemu-*' interpreters are removed.

This is partial because 'debian' and 'systemd' configurations are not
removed. If option 'reset' is provided before any of those, reset is
executed first and the configuration proceeds. However, if 'reset' is
provided after any of them, the script will exit with error 'option
reset not implemented for this mode yet'.

Removal is done by printing '-1' as explained at:
https://www.kernel.org/doc/Documentation/admin-guide/binfmt-misc.rst

Signed-off-by: Unai Martinez-Corral <unai.martinezcorral@ehu.eus>
---
 scripts/qemu-binfmt-conf.sh | 36 +++++++++++++++++++++++++++++++++---
 1 file changed, 33 insertions(+), 3 deletions(-)

--
2.20.1

Comments

Laurent Vivier March 10, 2019, 5:15 p.m. UTC | #1
On 06/03/2019 05:52, Unai Martinez-Corral wrote:
> This is a partial implementation.
> 
> Allows to remove a single or a list of already registered binfmt
> interpreters. If <ARCHS> is a list, it must be comma-separated.

I think ARCHS and CPUS are the same thing, so use the same word.

> Valid values are those in qemu_target_list. If <ARCHS> is 'ALL', all
> the existing 'qemu-*' interpreters are removed.
> 
> This is partial because 'debian' and 'systemd' configurations are not
> removed. If option 'reset' is provided before any of those, reset is
> executed first and the configuration proceeds. However, if 'reset' is
> provided after any of them, the script will exit with error 'option
> reset not implemented for this mode yet'.
> 
> Removal is done by printing '-1' as explained at:
> https://www.kernel.org/doc/Documentation/admin-guide/binfmt-misc.rst
> 
> Signed-off-by: Unai Martinez-Corral <unai.martinezcorral@ehu.eus>
> ---
>  scripts/qemu-binfmt-conf.sh | 36 +++++++++++++++++++++++++++++++++---
>  1 file changed, 33 insertions(+), 3 deletions(-)
> 
> diff --git a/scripts/qemu-binfmt-conf.sh b/scripts/qemu-binfmt-conf.sh
> index 2751363089..824e3c4c34 100755
> --- a/scripts/qemu-binfmt-conf.sh
> +++ b/scripts/qemu-binfmt-conf.sh
> @@ -197,8 +197,8 @@ qemu_get_family() {
> 
>  usage() {
>      cat <<EOF
> -Usage: qemu-binfmt-conf.sh [--path PATH][--debian][--systemd]
> -                           [--help][--credential][--exportdir PATH]
> +Usage: qemu-binfmt-conf.sh [--help][--path PATH][--debian][--systemd]
> +                           [--reset ARCHS][--credential][--exportdir PATH]
>                             [--persistent][--suffix SUFFIX][CPUS]

I don't like the idea of being able to set and reset different
interpretes with same command line call.

Make "--reset" exclusive without parameter to be able to use the common
cpu list at the end of the command line (this way, I think you would be
able to share more common code between setting an resetting).

You could have a look to Alex Bennée's patch:

  https://patchwork.ozlabs.org/patch/938796/

I think this is the good way to do this and it should merge easily with
your series.

Thanks,
Laurent
Unai Martinez Corral March 11, 2019, 5:03 a.m. UTC | #2
2019/3/10 18:15, Laurent Vivier:
> On 06/03/2019 05:52, Unai Martinez-Corral wrote:
> > Allows to remove a single or a list of already registered binfmt
> > interpreters. If <ARCHS> is a list, it must be comma-separated.
>
> I think ARCHS and CPUS are the same thing, so use the same word.

They are similar, but the syntax is not the same. ARCHS supports a
single word or a comma separated list. CPUS supports also using
spaces, tabs, etc. as separators.

> > -Usage: qemu-binfmt-conf.sh [--path PATH][--debian][--systemd]
> > -                           [--help][--credential][--exportdir PATH]
> > +Usage: qemu-binfmt-conf.sh [--help][--path PATH][--debian][--systemd]
> > +                           [--reset ARCHS][--credential][--exportdir PATH]
> >                             [--persistent][--suffix SUFFIX][CPUS]
>
> I don't like the idea of being able to set and reset different
> interpretes with same command line call.

> Make "--reset" exclusive without parameter to be able to use the common
> cpu list at the end of the command line

It is useful in order to replace a single interpreter or a few of them
in a single call to the script. Anyway, I think that your comment
makes sense. It is enough if we support to reset a subset. Any user
can then wrap two consecutive calls in a helper function.

So, in the next version '--reset' will be 'exclusive', i.e., it will
prevent registration.

> (this way, I think you would be
> able to share more common code between setting an resetting).

The shared code is the same, because 'qemu_check_target_list' was
already being used in both. The simplification comes from the fact
that we do not support commas anymore, since ARCHS and CPUS are now
only positional.

> You could have a look to Alex Bennée's patch:
>
>   https://patchwork.ozlabs.org/patch/938796/
>
> I think this is the good way to do this and it should merge easily with
> your series.

Thanks for the reference; I had skipped it. Upon further inspection, I
think that the features proposed by Alex are already implemented in
this patch, or they will be in the next version:

- I am already checking with '$CHECK', which will use the
corresponding procedure depending on 'systemd' or 'debian'.
- I am using printf instead of 'echo -1', as suggested by Eric Blake
in v1 of the patch.
- I will rename the option from '--reset' to '--clear', as I find it
to be more descriptive.
- None of us support neither '--debian' nor '--systemd'. See comments below.
- I support providing a subset of targets, while Alex' approach
targeted all of them.
- Overall, I think that 'BINFMT_SET=qemu_clear_interpreter' is ok for
a proof of concept, but it is not as clean as it could be. Precisely,
all the magic, mask, family values are computed in the loop inside
qemu_set_binfmts. That should be avoided if we only want to remove
them. Nonetheless, I will try to integrate both approaches.

Regarding this comment:

> I think it would be also useful to remove the files from $EXPORTDIR.
> So could you also manage something like "--debian --clear" and "--systemd CPU --clear"?

ATM, this patchset supports '--reset --debian' or '--reset --systemd',
but it will proceed by updating /proc directly, which might not be
effective at all.
Furthermore, when '--debian --reset' or '--systemd --reset' are used,
a error message is shown: 'ERROR: option reset not implemented for
this mode yet'.

On the one hand, I can make '--reset --debian|systemd' and
'--debian|systemd --reset' consistent, by delaying the execution of
the reset/clear function after all the options are parsed.

On the other hand, I'd really like to have patches 6 and 7 available
in QEMU 4.0, if possible. So, I'd like to know if the partial
implementation of this feature is a stopper. If so, I'd be so glad to
have some help. These are the prototypes that I have not added to the
patchset because I am not sure about them:

For the debian case, after the comments in 'usage()', I think that the
procedure should be:

for t in $qemu_check_target_list ; do
  sudo update-binfmts --package "qemu-$t" --remove "qemu-$t" "$QEMU_PATH"
  rm "$EXPORTDIR/qemu-$t"
done

And for systemd:

sudo systemctl stop systemd-binfmt.service
for t in $qemu_check_target_list ; do
   rm -rf $EXPORTDIR/qemu-$t.conf"
do
sudo systemctl start systemd-binfmt.service

Thanks,
Unai
diff mbox series

Patch

diff --git a/scripts/qemu-binfmt-conf.sh b/scripts/qemu-binfmt-conf.sh
index 2751363089..824e3c4c34 100755
--- a/scripts/qemu-binfmt-conf.sh
+++ b/scripts/qemu-binfmt-conf.sh
@@ -197,8 +197,8 @@  qemu_get_family() {

 usage() {
     cat <<EOF
-Usage: qemu-binfmt-conf.sh [--path PATH][--debian][--systemd]
-                           [--help][--credential][--exportdir PATH]
+Usage: qemu-binfmt-conf.sh [--help][--path PATH][--debian][--systemd]
+                           [--reset ARCHS][--credential][--exportdir PATH]
                            [--persistent][--suffix SUFFIX][CPUS]

        Configure binfmt_misc to use qemu interpreter for the given CPUS.
@@ -219,6 +219,9 @@  Usage: qemu-binfmt-conf.sh [--path PATH][--debian][--systemd]
                       architecture than the current one.
        --exportdir:   define where to write configuration files
                       (default: $SYSTEMDDIR or $DEBIANDIR)
+       --reset:       remove registered interpreter for target ARCHS (comma
+                      separated list). If ARCHS is 'ALL', remove all registered
+                      'qemu-*' interpreters.
        --credential:  if present, credential and security tokens are
                       calculated according to the binary to interpret
                       ($QEMU_CREDENTIAL=yes)
@@ -353,8 +356,28 @@  qemu_set_binfmts() {
     done
 }

+qemu_remove_notimplemented() {
+    echo "ERROR: option reset not implemented for this mode yet" 1>&2
+    usage
+    exit 1
+}
+
+qemu_remove_interpreter() {
+    names='qemu-*'
+    if [ "x$1" != "xALL" ] ; then
+        qemu_check_target_list $1
+        unset names pre
+        for t in $checked_target_list ; do
+            names="${names}${pre}qemu-$t"
+            pre=' -o -name '
+        done
+    fi
+    find /proc/sys/fs/binfmt_misc/ -type f -name $names -exec sh -c 'printf %s -1 > {}' \;
+}
+
 CHECK=qemu_check_bintfmt_misc
 BINFMT_SET=qemu_register_interpreter
+BINFMT_REMOVE=qemu_remove_interpreter

 SYSTEMDDIR="/etc/binfmt.d"
 DEBIANDIR="/usr/share/binfmts"
@@ -364,19 +387,26 @@  QEMU_SUFFIX="${QEMU_SUFFIX:-}"
 QEMU_CREDENTIAL="${QEMU_CREDENTIAL:-no}"
 QEMU_PERSISTENT="${QEMU_PERSISTENT:-no}"

-options=$(getopt -o :dsQ:S:e:hcp -l debian,systemd,path:,suffix:,exportdir:,help,credential,persistent -- "$@")
+options=$(getopt -o r:dsQ:S:e:hcp -l reset:,debian,systemd,path:,suffix:,exportdir:,help,credential,persistent -- "$@")
 eval set -- "$options"

 while true ; do
     case "$1" in
+    -r|--reset)
+        shift
+        $CHECK
+        qemu_remove_interpreter $1
+        ;;
     -d|--debian)
         CHECK=qemu_check_debian
         BINFMT_SET=qemu_generate_debian
+        BINFMT_REMOVE=qemu_remove_notimplemented
         EXPORTDIR=${EXPORTDIR:-$DEBIANDIR}
         ;;
     -s|--systemd)
         CHECK=qemu_check_systemd
         BINFMT_SET=qemu_generate_systemd
+        BINFMT_REMOVE=qemu_remove_notimplemented
         EXPORTDIR=${EXPORTDIR:-$SYSTEMDDIR}
         ;;
     -Q|--path)