- Cherry pick patches from qemu-kvm into the qemu package:
- 0033-Add-support-for-DictZip-enabled-gzi.patch - 0034-Add-tar-container-format.patch.patch - 0035-Legacy-Patch-kvm-qemu-preXX-dictzip.patch - 0036-Legacy-Patch-kvm-qemu-preXX-report-.patch - 0037-console-add-question-mark-escape-op.patch - 0038-Make-char-muxer-more-robust-wrt-sma.patch OBS-URL: https://build.opensuse.org/package/show/Virtualization/qemu?expand=0&rev=124
This commit is contained in:
parent
bb07fc12cf
commit
91a548c8b1
@ -29,7 +29,7 @@ hit is, which I never got round to. Feel free to do some :-)
|
||||
linux-user/main.c | 8 ++++++++
|
||||
qemu-options.hx | 9 +++++++++
|
||||
vl.c | 5 +++++
|
||||
6 Dateien geändert, 60 Zeilen hinzugefügt(+), 3 Zeilen entfernt(-)
|
||||
6 files changed, 60 insertions(+), 3 deletions(-)
|
||||
|
||||
diff --git a/cpu-exec.c b/cpu-exec.c
|
||||
index 904ee73..b83d43e 100644
|
||||
|
@ -5,7 +5,7 @@ Subject: [PATCH] XXX dont dump core on sigabort
|
||||
|
||||
---
|
||||
linux-user/signal.c | 6 ++++++
|
||||
1 Datei geändert, 6 Zeilen hinzugefügt(+)
|
||||
1 files changed, 6 insertions(+), 0 deletions(-)
|
||||
|
||||
diff --git a/linux-user/signal.c b/linux-user/signal.c
|
||||
index 95e2ffa..4758c11 100644
|
||||
|
@ -9,7 +9,7 @@ Subject: [PATCH] XXX work around SA_RESTART race with boehm-gc (ARM only)
|
||||
linux-user/qemu.h | 3 ++
|
||||
linux-user/signal.c | 22 ++++++++++++
|
||||
linux-user/syscall.c | 90 +++++++++++++++++++++++++++++++++++++++++++++++++-
|
||||
4 Dateien geändert, 130 Zeilen hinzugefügt(+), 10 Zeilen entfernt(-)
|
||||
4 files changed, 130 insertions(+), 10 deletions(-)
|
||||
|
||||
diff --git a/linux-user/main.c b/linux-user/main.c
|
||||
index c339af8..c4d10ac 100644
|
||||
|
@ -11,7 +11,7 @@ Fixes binfmt_misc setup script:
|
||||
Signed-off-by: Ulrich Hecht <uli@suse.de>
|
||||
---
|
||||
scripts/qemu-binfmt-conf.sh | 37 ++++++++++++++++++++-----------------
|
||||
1 Datei geändert, 20 Zeilen hinzugefügt(+), 17 Zeilen entfernt(-)
|
||||
1 files changed, 20 insertions(+), 17 deletions(-)
|
||||
|
||||
diff --git a/scripts/qemu-binfmt-conf.sh b/scripts/qemu-binfmt-conf.sh
|
||||
index 0da2618..dc652f0 100644
|
||||
|
@ -10,7 +10,7 @@ Signed-off-by: Ulrich Hecht <uli@suse.de>
|
||||
---
|
||||
thunk.c | 21 +++++++++++++++++++++
|
||||
thunk.h | 3 +++
|
||||
2 Dateien geändert, 24 Zeilen hinzugefügt(+)
|
||||
2 files changed, 24 insertions(+), 0 deletions(-)
|
||||
|
||||
diff --git a/thunk.c b/thunk.c
|
||||
index 8ebbbb4..bf43985 100644
|
||||
|
@ -14,7 +14,7 @@ Signed-off-by: Ulrich Hecht <uli@suse.de>
|
||||
linux-user/syscall_defs.h | 2 +
|
||||
linux-user/syscall_types.h | 5 +
|
||||
linux-user/syscall_types_alsa.h | 1336 +++++++++++++++++++++++++++++
|
||||
6 Dateien geändert, 3555 Zeilen hinzugefügt(+)
|
||||
6 files changed, 3555 insertions(+), 0 deletions(-)
|
||||
create mode 100644 linux-user/ioctls_alsa.h
|
||||
create mode 100644 linux-user/ioctls_alsa_structs.h
|
||||
create mode 100644 linux-user/syscall_types_alsa.h
|
||||
|
@ -9,7 +9,7 @@ Signed-off-by: Alexander Graf <agraf@suse.de>
|
||||
Signed-off-by: Ulrich Hecht <uli@suse.de>
|
||||
---
|
||||
linux-user/mmap.c | 14 ++++++++++++++
|
||||
1 Datei geändert, 14 Zeilen hinzugefügt(+)
|
||||
1 files changed, 14 insertions(+), 0 deletions(-)
|
||||
|
||||
diff --git a/linux-user/mmap.c b/linux-user/mmap.c
|
||||
index b412e3f..46523de 100644
|
||||
|
@ -6,7 +6,7 @@ Subject: [PATCH] qemu-cvs-gettimeofday
|
||||
No clue what this is for.
|
||||
---
|
||||
linux-user/syscall.c | 2 ++
|
||||
1 Datei geändert, 2 Zeilen hinzugefügt(+)
|
||||
1 files changed, 2 insertions(+), 0 deletions(-)
|
||||
|
||||
diff --git a/linux-user/syscall.c b/linux-user/syscall.c
|
||||
index 05d4809..edcc4c8 100644
|
||||
|
@ -9,7 +9,7 @@ Signed-off-by: Alexander Graf <agraf@suse.de>
|
||||
Signed-off-by: Ulrich Hecht <uli@suse.de>
|
||||
---
|
||||
linux-user/syscall.c | 7 ++++++-
|
||||
1 Datei geändert, 6 Zeilen hinzugefügt(+), 1 Zeile entfernt(-)
|
||||
1 files changed, 6 insertions(+), 1 deletions(-)
|
||||
|
||||
diff --git a/linux-user/syscall.c b/linux-user/syscall.c
|
||||
index edcc4c8..65246a1 100644
|
||||
|
@ -12,7 +12,7 @@ Signed-off-by: Alexander Graf <agraf@suse.de>
|
||||
Signed-off-by: Ulrich Hecht <uli@suse.de>
|
||||
---
|
||||
linux-user/syscall.c | 6 ++++++
|
||||
1 Datei geändert, 6 Zeilen hinzugefügt(+)
|
||||
1 files changed, 6 insertions(+), 0 deletions(-)
|
||||
|
||||
diff --git a/linux-user/syscall.c b/linux-user/syscall.c
|
||||
index 65246a1..d8d41c5 100644
|
||||
|
@ -3,7 +3,7 @@ From: Ulrich Hecht <uli@suse.de>
|
||||
Date: Tue, 14 Apr 2009 16:37:42 +0200
|
||||
Subject: [PATCH] block/vmdk: Support creation of SCSI VMDK images in qemu-img
|
||||
MIME-Version: 1.0
|
||||
Content-Type: text/plain; charset=UTF-8
|
||||
Content-Type: text/plain; charset=utf-8
|
||||
Content-Transfer-Encoding: 8bit
|
||||
|
||||
Signed-off-by: Ulrich Hecht <uli@suse.de>
|
||||
@ -14,7 +14,7 @@ Signed-off-by: Andreas Färber <afaerber@suse.de>
|
||||
block/vmdk.c | 12 ++++++++++--
|
||||
block_int.h | 2 ++
|
||||
qemu-img.c | 8 +++++++-
|
||||
4 Dateien geändert, 23 Zeilen hinzugefügt(+), 4 Zeilen entfernt(-)
|
||||
4 files changed, 23 insertions(+), 4 deletions(-)
|
||||
|
||||
diff --git a/block.c b/block.c
|
||||
index c05875f..07e271c 100644
|
||||
|
@ -3,7 +3,7 @@ From: Ulrich Hecht <uli@suse.de>
|
||||
Date: Wed, 25 Aug 2010 14:23:43 +0200
|
||||
Subject: [PATCH] configure: Enable mipsn32*-linux-user builds
|
||||
MIME-Version: 1.0
|
||||
Content-Type: text/plain; charset=UTF-8
|
||||
Content-Type: text/plain; charset=utf-8
|
||||
Content-Transfer-Encoding: 8bit
|
||||
|
||||
Signed-off-by: Ulrich Hecht <uli@suse.de>
|
||||
@ -12,7 +12,7 @@ Signed-off-by: Ulrich Hecht <uli@suse.de>
|
||||
Signed-off-by: Andreas Färber <afaerber@suse.de>
|
||||
---
|
||||
configure | 2 ++
|
||||
1 Datei geändert, 2 Zeilen hinzugefügt(+)
|
||||
1 files changed, 2 insertions(+), 0 deletions(-)
|
||||
|
||||
diff --git a/configure b/configure
|
||||
index 994f731..401f369 100755
|
||||
|
@ -3,7 +3,7 @@ From: Alexander Graf <agraf@suse.de>
|
||||
Date: Fri, 30 Sep 2011 19:40:36 +0200
|
||||
Subject: [PATCH] linux-user: add binfmt wrapper for argv[0] handling
|
||||
MIME-Version: 1.0
|
||||
Content-Type: text/plain; charset=UTF-8
|
||||
Content-Type: text/plain; charset=utf-8
|
||||
Content-Transfer-Encoding: 8bit
|
||||
|
||||
When using qemu's linux-user binaries through binfmt, argv[0] gets lost
|
||||
@ -31,7 +31,7 @@ Signed-off-by: Andreas Färber <afaerber@suse.de>
|
||||
linux-user/Makefile.objs | 2 ++
|
||||
linux-user/binfmt.c | 42 ++++++++++++++++++++++++++++++++++++++++++
|
||||
scripts/qemu-binfmt-conf.sh | 34 +++++++++++++++++-----------------
|
||||
4 Dateien geändert, 73 Zeilen hinzugefügt(+), 17 Zeilen entfernt(-)
|
||||
4 files changed, 73 insertions(+), 17 deletions(-)
|
||||
create mode 100644 linux-user/binfmt.c
|
||||
|
||||
diff --git a/Makefile.target b/Makefile.target
|
||||
|
@ -9,7 +9,7 @@ about it breaks some %check tests in OBS, so better ignore it silently.
|
||||
Signed-off-by: Alexander Graf <agraf@suse.de>
|
||||
---
|
||||
linux-user/syscall.c | 5 +++++
|
||||
1 Datei geändert, 5 Zeilen hinzugefügt(+)
|
||||
1 files changed, 5 insertions(+), 0 deletions(-)
|
||||
|
||||
diff --git a/linux-user/syscall.c b/linux-user/syscall.c
|
||||
index d8d41c5..1b8058c 100644
|
||||
|
@ -10,7 +10,7 @@ implementation and go on with life :)
|
||||
Signed-off-by: Alexander Graf <agraf@suse.de>
|
||||
---
|
||||
linux-user/syscall.c | 2 +-
|
||||
1 Datei geändert, 1 Zeile hinzugefügt(+), 1 Zeile entfernt(-)
|
||||
1 files changed, 1 insertions(+), 1 deletions(-)
|
||||
|
||||
diff --git a/linux-user/syscall.c b/linux-user/syscall.c
|
||||
index 1b8058c..30ee613 100644
|
||||
|
@ -10,7 +10,7 @@ So disable the check for mmu notifiers on PowerPC guests, making
|
||||
KVM guests work there, even if possibly racy in some odd circumstances.
|
||||
---
|
||||
exec.c | 2 ++
|
||||
1 Datei geändert, 2 Zeilen hinzugefügt(+)
|
||||
1 files changed, 2 insertions(+), 0 deletions(-)
|
||||
|
||||
diff --git a/exec.c b/exec.c
|
||||
index edb44fc..8971d61 100644
|
||||
|
@ -19,7 +19,7 @@ Signed-off-by: Alexander Graf <agraf@suse.de>
|
||||
---
|
||||
qemu-lock.h | 10 ++++++++++
|
||||
user-exec.c | 4 ++++
|
||||
2 Dateien geändert, 14 Zeilen hinzugefügt(+)
|
||||
2 files changed, 14 insertions(+), 0 deletions(-)
|
||||
|
||||
diff --git a/qemu-lock.h b/qemu-lock.h
|
||||
index a72edda..e460e12 100644
|
||||
|
@ -9,7 +9,7 @@ trying to run, let's just use that instead as it will be a lot faster.
|
||||
Signed-off-by: Alexander Graf <agraf@suse.de>
|
||||
---
|
||||
linux-user/binfmt.c | 25 +++++++++++++++++++++++++
|
||||
1 Datei geändert, 25 Zeilen hinzugefügt(+)
|
||||
1 files changed, 25 insertions(+), 0 deletions(-)
|
||||
|
||||
diff --git a/linux-user/binfmt.c b/linux-user/binfmt.c
|
||||
index cd1f513..87dc4c6 100644
|
||||
|
@ -11,7 +11,7 @@ So something in our thread creation is broken. But for now, let's revert the
|
||||
change to at least get a working build again.
|
||||
---
|
||||
target-arm/cpu.c | 4 ++++
|
||||
1 Datei geändert, 4 Zeilen hinzugefügt(+)
|
||||
1 files changed, 4 insertions(+), 0 deletions(-)
|
||||
|
||||
diff --git a/target-arm/cpu.c b/target-arm/cpu.c
|
||||
index b00f5fa..740dbc3 100644
|
||||
|
@ -15,7 +15,7 @@ Signed-off-by: Alexander Graf <agraf@suse.de>
|
||||
linux-user/linux_loop.h | 1 +
|
||||
linux-user/syscall.c | 7 +++++++
|
||||
linux-user/syscall_defs.h | 1 +
|
||||
4 Dateien geändert, 10 Zeilen hinzugefügt(+)
|
||||
4 files changed, 10 insertions(+), 0 deletions(-)
|
||||
|
||||
diff --git a/linux-user/ioctls.h b/linux-user/ioctls.h
|
||||
index 6af0cb7..bb76c56 100644
|
||||
|
@ -3,7 +3,7 @@ From: Alexander Graf <agraf@suse.de>
|
||||
Date: Mon, 25 Jun 2012 19:02:32 +0200
|
||||
Subject: [PATCH] linux-user: fix segmentation fault passing with g2h(x) != x
|
||||
MIME-Version: 1.0
|
||||
Content-Type: text/plain; charset=UTF-8
|
||||
Content-Type: text/plain; charset=utf-8
|
||||
Content-Transfer-Encoding: 8bit
|
||||
|
||||
When forwarding a segmentation fault into the guest process, we were passing
|
||||
@ -20,7 +20,7 @@ Signed-off-by: Alexander Graf <agraf@suse.de>
|
||||
Signed-off-by: Andreas Färber <afaerber@suse.de>
|
||||
---
|
||||
user-exec.c | 6 ++++++
|
||||
1 Datei geändert, 6 Zeilen hinzugefügt(+)
|
||||
1 files changed, 6 insertions(+), 0 deletions(-)
|
||||
|
||||
diff --git a/user-exec.c b/user-exec.c
|
||||
index 1ec5d9a..71afbf1 100644
|
||||
|
@ -11,7 +11,7 @@ Signed-off-by: Alexander Graf <agraf@suse.de>
|
||||
linux-user/mmap.c | 3 +++
|
||||
tcg/tcg.c | 36 ++++++++++++++++++++++++++++++++++--
|
||||
tcg/tcg.h | 6 ++++++
|
||||
3 Dateien geändert, 43 Zeilen hinzugefügt(+), 2 Zeilen entfernt(-)
|
||||
3 files changed, 43 insertions(+), 2 deletions(-)
|
||||
|
||||
diff --git a/linux-user/mmap.c b/linux-user/mmap.c
|
||||
index 46523de..59718b5 100644
|
||||
|
@ -16,7 +16,7 @@ This gets Java 1.7 working for me again on my test box.
|
||||
Signed-off-by: Alexander Graf <agraf@suse.de>
|
||||
---
|
||||
linux-user/syscall.c | 9 +++++++++
|
||||
1 Datei geändert, 9 Zeilen hinzugefügt(+)
|
||||
1 files changed, 9 insertions(+), 0 deletions(-)
|
||||
|
||||
diff --git a/linux-user/syscall.c b/linux-user/syscall.c
|
||||
index d62e9e6..5295afb 100644
|
||||
|
@ -6,7 +6,7 @@ Subject: [PATCH] linux-user: lock tb flushing too
|
||||
Signed-off-by: Alexander Graf <agraf@suse.de>
|
||||
---
|
||||
exec.c | 33 ++++++++++++++++++++++++++-------
|
||||
1 Datei geändert, 26 Zeilen hinzugefügt(+), 7 Zeilen entfernt(-)
|
||||
1 files changed, 26 insertions(+), 7 deletions(-)
|
||||
|
||||
diff --git a/exec.c b/exec.c
|
||||
index 8971d61..ee22e2c 100644
|
||||
|
@ -14,7 +14,7 @@ has happened.
|
||||
Signed-off-by: Alexander Graf <agraf@suse.de>
|
||||
---
|
||||
linux-user/syscall.c | 20 ++++++++++++++++++++
|
||||
1 Datei geändert, 20 Zeilen hinzugefügt(+)
|
||||
1 files changed, 20 insertions(+), 0 deletions(-)
|
||||
|
||||
diff --git a/linux-user/syscall.c b/linux-user/syscall.c
|
||||
index 5295afb..034cd5a 100644
|
||||
|
@ -7,7 +7,7 @@ Signed-off-by: Alexander Graf <agraf@suse.de>
|
||||
---
|
||||
linux-user/ioctls.h | 1 +
|
||||
linux-user/syscall_defs.h | 2 ++
|
||||
2 Dateien geändert, 3 Zeilen hinzugefügt(+)
|
||||
2 files changed, 3 insertions(+), 0 deletions(-)
|
||||
|
||||
diff --git a/linux-user/ioctls.h b/linux-user/ioctls.h
|
||||
index bb76c56..1b798b3 100644
|
||||
|
@ -7,7 +7,7 @@ Signed-off-by: Alexander Graf <agraf@suse.de>
|
||||
---
|
||||
linux-user/ioctls.h | 1 +
|
||||
linux-user/syscall_defs.h | 1 +
|
||||
2 Dateien geändert, 2 Zeilen hinzugefügt(+)
|
||||
2 files changed, 2 insertions(+), 0 deletions(-)
|
||||
|
||||
diff --git a/linux-user/ioctls.h b/linux-user/ioctls.h
|
||||
index 1b798b3..5027c74 100644
|
||||
|
@ -6,7 +6,7 @@ Subject: [PATCH] linux-user: XXX disable fiemap
|
||||
agraf: fiemap breaks in libarchive. Disable it for now.
|
||||
---
|
||||
linux-user/syscall.c | 5 +++++
|
||||
1 Datei geändert, 5 Zeilen hinzugefügt(+)
|
||||
1 files changed, 5 insertions(+), 0 deletions(-)
|
||||
|
||||
diff --git a/linux-user/syscall.c b/linux-user/syscall.c
|
||||
index 034cd5a..526e0f0 100644
|
||||
|
@ -1,5 +1,5 @@
|
||||
From ce4a86e1d33b1ca4fd3c3bd67a009e74a1dc5636 Mon Sep 17 00:00:00 2001
|
||||
From: =?UTF-8?q?Andreas=20F=C3=A4rber?= <afaerber@suse.de>
|
||||
From: =?utf-8?q?Andreas=20F=C3=A4rber?= <afaerber@suse.de>
|
||||
Date: Wed, 29 Aug 2012 18:42:56 +0200
|
||||
Subject: [PATCH] slirp: -nooutgoing
|
||||
|
||||
@ -9,7 +9,7 @@ TBD (from SUSE Studio team)
|
||||
slirp/socket.c | 8 ++++++++
|
||||
slirp/tcp_subr.c | 16 ++++++++++++++++
|
||||
vl.c | 9 +++++++++
|
||||
4 Dateien geändert, 43 Zeilen hinzugefügt(+)
|
||||
4 files changed, 43 insertions(+), 0 deletions(-)
|
||||
|
||||
diff --git a/qemu-options.hx b/qemu-options.hx
|
||||
index 94a1c50..9635327 100644
|
||||
|
@ -1,12 +1,12 @@
|
||||
From 1915e62ecadb41ebd1fcc563afe4f6c0dea8f43b Mon Sep 17 00:00:00 2001
|
||||
From: =?UTF-8?q?Andreas=20F=C3=A4rber?= <afaerber@suse.de>
|
||||
From: =?utf-8?q?Andreas=20F=C3=A4rber?= <afaerber@suse.de>
|
||||
Date: Wed, 29 Aug 2012 20:06:01 +0200
|
||||
Subject: [PATCH] vnc: password-file= and incoming-connections=
|
||||
|
||||
TBD (from SUSE Studio team)
|
||||
---
|
||||
ui/vnc.c | 71 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
|
||||
1 Datei geändert, 71 Zeilen hinzugefügt(+)
|
||||
1 files changed, 71 insertions(+), 0 deletions(-)
|
||||
|
||||
diff --git a/ui/vnc.c b/ui/vnc.c
|
||||
index ba30362..d99c1bd 100644
|
||||
|
@ -10,7 +10,7 @@ Signed-off-by: Alexander Graf <agraf@suse.de>
|
||||
linux-user/ioctls.h | 18 ++++++++++++++++++
|
||||
linux-user/syscall_defs.h | 6 ++++++
|
||||
linux-user/syscall_types.h | 3 +++
|
||||
3 Dateien geändert, 27 Zeilen hinzugefügt(+)
|
||||
3 files changed, 27 insertions(+), 0 deletions(-)
|
||||
|
||||
diff --git a/linux-user/ioctls.h b/linux-user/ioctls.h
|
||||
index 5027c74..4522c14 100644
|
||||
|
@ -14,7 +14,7 @@ Signed-off-by: Alexander Graf <agraf@suse.de>
|
||||
---
|
||||
linux-user/qemu.h | 8 ++++----
|
||||
linux-user/syscall.c | 8 ++++----
|
||||
2 Dateien geändert, 8 Zeilen hinzugefügt(+), 8 Zeilen entfernt(-)
|
||||
2 files changed, 8 insertions(+), 8 deletions(-)
|
||||
|
||||
diff --git a/linux-user/qemu.h b/linux-user/qemu.h
|
||||
index 7cc7b87..88de318 100644
|
||||
|
608
0033-Add-support-for-DictZip-enabled-gzi.patch
Normal file
608
0033-Add-support-for-DictZip-enabled-gzi.patch
Normal file
@ -0,0 +1,608 @@
|
||||
From 33b9fbeca1bc447fd6e353a8c5129f0d3a646b91 Mon Sep 17 00:00:00 2001
|
||||
From: Alexander Graf <agraf@suse.de>
|
||||
Date: Wed, 5 Aug 2009 09:49:37 +0200
|
||||
Subject: [PATCH] Add support for DictZip enabled gzip files
|
||||
|
||||
DictZip is an extension to the gzip format that allows random seeks in gzip
|
||||
compressed files by cutting the file into pieces and storing the piece offsets
|
||||
in the "extra" header of the gzip format.
|
||||
|
||||
Thanks to that extension, we can use gzip compressed files as block backend,
|
||||
though only in read mode.
|
||||
|
||||
This makes a lot of sense when stacked with tar files that can then be shipped
|
||||
to VM users. If a VM image is inside a tar file that is inside a DictZip
|
||||
enabled gzip file, the user can run the tar.gz file as is without having to
|
||||
extract the image first.
|
||||
|
||||
Tar patch follows.
|
||||
|
||||
Signed-off-by: Alexander Graf <agraf@suse.de>
|
||||
Signed-off-by: Bruce Rogers <brogers@novell.com>
|
||||
---
|
||||
block/Makefile.objs | 1 +
|
||||
block/dictzip.c | 566 +++++++++++++++++++++++++++++++++++++++++++++++++++
|
||||
2 files changed, 567 insertions(+), 0 deletions(-)
|
||||
create mode 100644 block/dictzip.c
|
||||
|
||||
diff --git a/block/Makefile.objs b/block/Makefile.objs
|
||||
index 7f01510..054b06e 100644
|
||||
--- a/block/Makefile.objs
|
||||
+++ b/block/Makefile.objs
|
||||
@@ -18,3 +18,4 @@ endif
|
||||
common-obj-y += stream.o
|
||||
common-obj-y += commit.o
|
||||
common-obj-y += mirror.o
|
||||
+common-obj-y += dictzip.o
|
||||
diff --git a/block/dictzip.c b/block/dictzip.c
|
||||
new file mode 100644
|
||||
index 0000000..b410dd6
|
||||
--- /dev/null
|
||||
+++ b/block/dictzip.c
|
||||
@@ -0,0 +1,566 @@
|
||||
+/*
|
||||
+ * DictZip Block driver for dictzip enabled gzip files
|
||||
+ *
|
||||
+ * Use the "dictzip" tool from the "dictd" package to create gzip files that
|
||||
+ * contain the extra DictZip headers.
|
||||
+ *
|
||||
+ * dictzip(1) is a compression program which creates compressed files in the
|
||||
+ * gzip format (see RFC 1952). However, unlike gzip(1), dictzip(1) compresses
|
||||
+ * the file in pieces and stores an index to the pieces in the gzip header.
|
||||
+ * This allows random access to the file at the granularity of the compressed
|
||||
+ * pieces (currently about 64kB) while maintaining good compression ratios
|
||||
+ * (within 5% of the expected ratio for dictionary data).
|
||||
+ * dictd(8) uses files stored in this format.
|
||||
+ *
|
||||
+ * For details on DictZip see http://dict.org/.
|
||||
+ *
|
||||
+ * Copyright (c) 2009 Alexander Graf <agraf@suse.de>
|
||||
+ *
|
||||
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
+ * of this software and associated documentation files (the "Software"), to deal
|
||||
+ * in the Software without restriction, including without limitation the rights
|
||||
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
+ * copies of the Software, and to permit persons to whom the Software is
|
||||
+ * furnished to do so, subject to the following conditions:
|
||||
+ *
|
||||
+ * The above copyright notice and this permission notice shall be included in
|
||||
+ * all copies or substantial portions of the Software.
|
||||
+ *
|
||||
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
||||
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
+ * THE SOFTWARE.
|
||||
+ */
|
||||
+
|
||||
+#include "qemu-common.h"
|
||||
+#include "block_int.h"
|
||||
+#include <zlib.h>
|
||||
+
|
||||
+// #define DEBUG
|
||||
+
|
||||
+#ifdef DEBUG
|
||||
+#define dprintf(fmt, ...) do { printf("dzip: " fmt, ## __VA_ARGS__); } while (0)
|
||||
+#else
|
||||
+#define dprintf(fmt, ...) do { } while (0)
|
||||
+#endif
|
||||
+
|
||||
+#define SECTOR_SIZE 512
|
||||
+#define Z_STREAM_COUNT 4
|
||||
+#define CACHE_COUNT 20
|
||||
+
|
||||
+/* magic values */
|
||||
+
|
||||
+#define GZ_MAGIC1 0x1f
|
||||
+#define GZ_MAGIC2 0x8b
|
||||
+#define DZ_MAGIC1 'R'
|
||||
+#define DZ_MAGIC2 'A'
|
||||
+
|
||||
+#define GZ_FEXTRA 0x04 /* Optional field (random access index) */
|
||||
+#define GZ_FNAME 0x08 /* Original name */
|
||||
+#define GZ_COMMENT 0x10 /* Zero-terminated, human-readable comment */
|
||||
+#define GZ_FHCRC 0x02 /* Header CRC16 */
|
||||
+
|
||||
+/* offsets */
|
||||
+
|
||||
+#define GZ_ID 0 /* GZ_MAGIC (16bit) */
|
||||
+#define GZ_FLG 3 /* FLaGs (see above) */
|
||||
+#define GZ_XLEN 10 /* eXtra LENgth (16bit) */
|
||||
+#define GZ_SI 12 /* Subfield ID (16bit) */
|
||||
+#define GZ_VERSION 16 /* Version for subfield format */
|
||||
+#define GZ_CHUNKSIZE 18 /* Chunk size (16bit) */
|
||||
+#define GZ_CHUNKCNT 20 /* Number of chunks (16bit) */
|
||||
+#define GZ_RNDDATA 22 /* Random access data (16bit) */
|
||||
+
|
||||
+#define GZ_99_CHUNKSIZE 18 /* Chunk size (32bit) */
|
||||
+#define GZ_99_CHUNKCNT 22 /* Number of chunks (32bit) */
|
||||
+#define GZ_99_FILESIZE 26 /* Size of unpacked file (64bit) */
|
||||
+#define GZ_99_RNDDATA 34 /* Random access data (32bit) */
|
||||
+
|
||||
+struct BDRVDictZipState;
|
||||
+
|
||||
+typedef struct DictZipAIOCB {
|
||||
+ BlockDriverAIOCB common;
|
||||
+ struct BDRVDictZipState *s;
|
||||
+ QEMUIOVector *qiov; /* QIOV of the original request */
|
||||
+ QEMUIOVector *qiov_gz; /* QIOV of the gz subrequest */
|
||||
+ QEMUBH *bh; /* BH for cache */
|
||||
+ z_stream *zStream; /* stream to use for decoding */
|
||||
+ int zStream_id; /* stream id of the above pointer */
|
||||
+ size_t start; /* offset into the uncompressed file */
|
||||
+ size_t len; /* uncompressed bytes to read */
|
||||
+ uint8_t *gzipped; /* the gzipped data */
|
||||
+ uint8_t *buf; /* cached result */
|
||||
+ size_t gz_len; /* amount of gzip data */
|
||||
+ size_t gz_start; /* uncompressed starting point of gzip data */
|
||||
+ uint64_t offset; /* offset for "start" into the uncompressed chunk */
|
||||
+ int chunks_len; /* amount of uncompressed data in all gzip data */
|
||||
+} DictZipAIOCB;
|
||||
+
|
||||
+typedef struct dict_cache {
|
||||
+ size_t start;
|
||||
+ size_t len;
|
||||
+ uint8_t *buf;
|
||||
+} DictCache;
|
||||
+
|
||||
+typedef struct BDRVDictZipState {
|
||||
+ BlockDriverState *hd;
|
||||
+ z_stream zStream[Z_STREAM_COUNT];
|
||||
+ DictCache cache[CACHE_COUNT];
|
||||
+ int cache_index;
|
||||
+ uint8_t stream_in_use;
|
||||
+ uint64_t chunk_len;
|
||||
+ uint32_t chunk_cnt;
|
||||
+ uint16_t *chunks;
|
||||
+ uint32_t *chunks32;
|
||||
+ uint64_t *offsets;
|
||||
+ int64_t file_len;
|
||||
+} BDRVDictZipState;
|
||||
+
|
||||
+static int dictzip_probe(const uint8_t *buf, int buf_size, const char *filename)
|
||||
+{
|
||||
+ if (buf_size < 2)
|
||||
+ return 0;
|
||||
+
|
||||
+ /* We match on every gzip file */
|
||||
+ if ((buf[0] == GZ_MAGIC1) && (buf[1] == GZ_MAGIC2))
|
||||
+ return 100;
|
||||
+
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
+static int start_zStream(z_stream *zStream)
|
||||
+{
|
||||
+ zStream->zalloc = NULL;
|
||||
+ zStream->zfree = NULL;
|
||||
+ zStream->opaque = NULL;
|
||||
+ zStream->next_in = 0;
|
||||
+ zStream->avail_in = 0;
|
||||
+ zStream->next_out = NULL;
|
||||
+ zStream->avail_out = 0;
|
||||
+
|
||||
+ return inflateInit2( zStream, -15 );
|
||||
+}
|
||||
+
|
||||
+static int dictzip_open(BlockDriverState *bs, const char *filename, int flags)
|
||||
+{
|
||||
+ BDRVDictZipState *s = bs->opaque;
|
||||
+ const char *err = "Unknown (read error?)";
|
||||
+ uint8_t magic[2];
|
||||
+ char buf[100];
|
||||
+ uint8_t header_flags;
|
||||
+ uint16_t chunk_len16;
|
||||
+ uint16_t chunk_cnt16;
|
||||
+ uint16_t header_ver;
|
||||
+ uint16_t tmp_short;
|
||||
+ uint64_t offset;
|
||||
+ int chunks_len;
|
||||
+ int headerLength = GZ_XLEN - 1;
|
||||
+ int rnd_offs;
|
||||
+ int ret;
|
||||
+ int i;
|
||||
+ const char *fname = filename;
|
||||
+
|
||||
+ if (!strncmp(filename, "dzip://", 7))
|
||||
+ fname += 7;
|
||||
+ else if (!strncmp(filename, "dzip:", 5))
|
||||
+ fname += 5;
|
||||
+
|
||||
+ ret = bdrv_file_open(&s->hd, fname, flags);
|
||||
+ if (ret < 0)
|
||||
+ return ret;
|
||||
+
|
||||
+ /* initialize zlib streams */
|
||||
+ for (i = 0; i < Z_STREAM_COUNT; i++) {
|
||||
+ if (start_zStream( &s->zStream[i] ) != Z_OK) {
|
||||
+ err = s->zStream[i].msg;
|
||||
+ goto fail;
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ /* gzip header */
|
||||
+ if (bdrv_pread(s->hd, GZ_ID, &magic, sizeof(magic)) != sizeof(magic))
|
||||
+ goto fail;
|
||||
+
|
||||
+ if (!((magic[0] == GZ_MAGIC1) && (magic[1] == GZ_MAGIC2))) {
|
||||
+ err = "No gzip file";
|
||||
+ goto fail;
|
||||
+ }
|
||||
+
|
||||
+ /* dzip header */
|
||||
+ if (bdrv_pread(s->hd, GZ_FLG, &header_flags, 1) != 1)
|
||||
+ goto fail;
|
||||
+
|
||||
+ if (!(header_flags & GZ_FEXTRA)) {
|
||||
+ err = "Not a dictzip file (wrong flags)";
|
||||
+ goto fail;
|
||||
+ }
|
||||
+
|
||||
+ /* extra length */
|
||||
+ if (bdrv_pread(s->hd, GZ_XLEN, &tmp_short, 2) != 2)
|
||||
+ goto fail;
|
||||
+
|
||||
+ headerLength += le16_to_cpu(tmp_short) + 2;
|
||||
+
|
||||
+ /* DictZip magic */
|
||||
+ if (bdrv_pread(s->hd, GZ_SI, &magic, 2) != 2)
|
||||
+ goto fail;
|
||||
+
|
||||
+ if (magic[0] != DZ_MAGIC1 || magic[1] != DZ_MAGIC2) {
|
||||
+ err = "Not a dictzip file (missing extra magic)";
|
||||
+ goto fail;
|
||||
+ }
|
||||
+
|
||||
+ /* DictZip version */
|
||||
+ if (bdrv_pread(s->hd, GZ_VERSION, &header_ver, 2) != 2)
|
||||
+ goto fail;
|
||||
+
|
||||
+ header_ver = le16_to_cpu(header_ver);
|
||||
+
|
||||
+ switch (header_ver) {
|
||||
+ case 1: /* Normal DictZip */
|
||||
+ /* number of chunks */
|
||||
+ if (bdrv_pread(s->hd, GZ_CHUNKSIZE, &chunk_len16, 2) != 2)
|
||||
+ goto fail;
|
||||
+
|
||||
+ s->chunk_len = le16_to_cpu(chunk_len16);
|
||||
+
|
||||
+ /* chunk count */
|
||||
+ if (bdrv_pread(s->hd, GZ_CHUNKCNT, &chunk_cnt16, 2) != 2)
|
||||
+ goto fail;
|
||||
+
|
||||
+ s->chunk_cnt = le16_to_cpu(chunk_cnt16);
|
||||
+ chunks_len = sizeof(short) * s->chunk_cnt;
|
||||
+ rnd_offs = GZ_RNDDATA;
|
||||
+ break;
|
||||
+ case 99: /* Special Alex pigz version */
|
||||
+ /* number of chunks */
|
||||
+ if (bdrv_pread(s->hd, GZ_99_CHUNKSIZE, &s->chunk_len, 4) != 4)
|
||||
+ goto fail;
|
||||
+
|
||||
+ dprintf("chunk len [%#x] = %d\n", GZ_99_CHUNKSIZE, s->chunk_len);
|
||||
+ s->chunk_len = le32_to_cpu(s->chunk_len);
|
||||
+
|
||||
+ /* chunk count */
|
||||
+ if (bdrv_pread(s->hd, GZ_99_CHUNKCNT, &s->chunk_cnt, 4) != 4)
|
||||
+ goto fail;
|
||||
+
|
||||
+ s->chunk_cnt = le32_to_cpu(s->chunk_cnt);
|
||||
+
|
||||
+ dprintf("chunk len | count = %d | %d\n", s->chunk_len, s->chunk_cnt);
|
||||
+
|
||||
+ /* file size */
|
||||
+ if (bdrv_pread(s->hd, GZ_99_FILESIZE, &s->file_len, 8) != 8)
|
||||
+ goto fail;
|
||||
+
|
||||
+ s->file_len = le64_to_cpu(s->file_len);
|
||||
+ chunks_len = sizeof(int) * s->chunk_cnt;
|
||||
+ rnd_offs = GZ_99_RNDDATA;
|
||||
+ break;
|
||||
+ default:
|
||||
+ err = "Invalid DictZip version";
|
||||
+ goto fail;
|
||||
+ }
|
||||
+
|
||||
+ /* random access data */
|
||||
+ s->chunks = g_malloc(chunks_len);
|
||||
+ if (header_ver == 99)
|
||||
+ s->chunks32 = (uint32_t *)s->chunks;
|
||||
+
|
||||
+ if (bdrv_pread(s->hd, rnd_offs, s->chunks, chunks_len) != chunks_len)
|
||||
+ goto fail;
|
||||
+
|
||||
+ /* orig filename */
|
||||
+ if (header_flags & GZ_FNAME) {
|
||||
+ if (bdrv_pread(s->hd, headerLength + 1, buf, sizeof(buf)) != sizeof(buf))
|
||||
+ goto fail;
|
||||
+
|
||||
+ buf[sizeof(buf) - 1] = '\0';
|
||||
+ headerLength += strlen(buf) + 1;
|
||||
+
|
||||
+ if (strlen(buf) == sizeof(buf))
|
||||
+ goto fail;
|
||||
+
|
||||
+ dprintf("filename: %s\n", buf);
|
||||
+ }
|
||||
+
|
||||
+ /* comment field */
|
||||
+ if (header_flags & GZ_COMMENT) {
|
||||
+ if (bdrv_pread(s->hd, headerLength, buf, sizeof(buf)) != sizeof(buf))
|
||||
+ goto fail;
|
||||
+
|
||||
+ buf[sizeof(buf) - 1] = '\0';
|
||||
+ headerLength += strlen(buf) + 1;
|
||||
+
|
||||
+ if (strlen(buf) == sizeof(buf))
|
||||
+ goto fail;
|
||||
+
|
||||
+ dprintf("comment: %s\n", buf);
|
||||
+ }
|
||||
+
|
||||
+ if (header_flags & GZ_FHCRC)
|
||||
+ headerLength += 2;
|
||||
+
|
||||
+ /* uncompressed file length*/
|
||||
+ if (!s->file_len) {
|
||||
+ uint32_t file_len;
|
||||
+
|
||||
+ if (bdrv_pread(s->hd, bdrv_getlength(s->hd) - 4, &file_len, 4) != 4)
|
||||
+ goto fail;
|
||||
+
|
||||
+ s->file_len = le32_to_cpu(file_len);
|
||||
+ }
|
||||
+
|
||||
+ /* compute offsets */
|
||||
+ s->offsets = g_malloc(sizeof( *s->offsets ) * s->chunk_cnt);
|
||||
+
|
||||
+ for (offset = headerLength + 1, i = 0; i < s->chunk_cnt; i++) {
|
||||
+ s->offsets[i] = offset;
|
||||
+ switch (header_ver) {
|
||||
+ case 1:
|
||||
+ offset += s->chunks[i];
|
||||
+ break;
|
||||
+ case 99:
|
||||
+ offset += s->chunks32[i];
|
||||
+ break;
|
||||
+ }
|
||||
+
|
||||
+ dprintf("chunk %#x - %#x = offset %#x -> %#x\n", i * s->chunk_len, (i+1) * s->chunk_len, s->offsets[i], offset);
|
||||
+ }
|
||||
+
|
||||
+ return 0;
|
||||
+
|
||||
+fail:
|
||||
+ fprintf(stderr, "DictZip: Error opening file: %s\n", err);
|
||||
+ bdrv_delete(s->hd);
|
||||
+ if (s->chunks)
|
||||
+ g_free(s->chunks);
|
||||
+ return -EINVAL;
|
||||
+}
|
||||
+
|
||||
+/* This callback gets invoked when we have the result in cache already */
|
||||
+static void dictzip_cache_cb(void *opaque)
|
||||
+{
|
||||
+ DictZipAIOCB *acb = (DictZipAIOCB *)opaque;
|
||||
+
|
||||
+ qemu_iovec_from_buf(acb->qiov, 0, acb->buf, acb->len);
|
||||
+ acb->common.cb(acb->common.opaque, 0);
|
||||
+ qemu_bh_delete(acb->bh);
|
||||
+ qemu_aio_release(acb);
|
||||
+}
|
||||
+
|
||||
+/* This callback gets invoked by the underlying block reader when we have
|
||||
+ * all compressed data. We uncompress in here. */
|
||||
+static void dictzip_read_cb(void *opaque, int ret)
|
||||
+{
|
||||
+ DictZipAIOCB *acb = (DictZipAIOCB *)opaque;
|
||||
+ struct BDRVDictZipState *s = acb->s;
|
||||
+ uint8_t *buf;
|
||||
+ DictCache *cache;
|
||||
+ int r;
|
||||
+
|
||||
+ buf = g_malloc(acb->chunks_len);
|
||||
+
|
||||
+ /* uncompress the chunk */
|
||||
+ acb->zStream->next_in = acb->gzipped;
|
||||
+ acb->zStream->avail_in = acb->gz_len;
|
||||
+ acb->zStream->next_out = buf;
|
||||
+ acb->zStream->avail_out = acb->chunks_len;
|
||||
+
|
||||
+ r = inflate( acb->zStream, Z_PARTIAL_FLUSH );
|
||||
+ if ( (r != Z_OK) && (r != Z_STREAM_END) )
|
||||
+ fprintf(stderr, "Error inflating: [%d] %s\n", r, acb->zStream->msg);
|
||||
+
|
||||
+ if ( r == Z_STREAM_END )
|
||||
+ inflateReset(acb->zStream);
|
||||
+
|
||||
+ dprintf("inflating [%d] left: %d | %d bytes\n", r, acb->zStream->avail_in, acb->zStream->avail_out);
|
||||
+ s->stream_in_use &= ~(1 << acb->zStream_id);
|
||||
+
|
||||
+ /* nofity the caller */
|
||||
+ qemu_iovec_from_buf(acb->qiov, 0, buf + acb->offset, acb->len);
|
||||
+ acb->common.cb(acb->common.opaque, 0);
|
||||
+
|
||||
+ /* fill the cache */
|
||||
+ cache = &s->cache[s->cache_index];
|
||||
+ s->cache_index++;
|
||||
+ if (s->cache_index == CACHE_COUNT)
|
||||
+ s->cache_index = 0;
|
||||
+
|
||||
+ cache->len = 0;
|
||||
+ if (cache->buf)
|
||||
+ g_free(cache->buf);
|
||||
+ cache->start = acb->gz_start;
|
||||
+ cache->buf = buf;
|
||||
+ cache->len = acb->chunks_len;
|
||||
+
|
||||
+ /* free occupied ressources */
|
||||
+ g_free(acb->qiov_gz);
|
||||
+ qemu_aio_release(acb);
|
||||
+}
|
||||
+
|
||||
+static void dictzip_aio_cancel(BlockDriverAIOCB *blockacb)
|
||||
+{
|
||||
+}
|
||||
+
|
||||
+static const AIOCBInfo dictzip_aiocb_info = {
|
||||
+ .aiocb_size = sizeof(DictZipAIOCB),
|
||||
+ .cancel = dictzip_aio_cancel,
|
||||
+};
|
||||
+
|
||||
+/* This is where we get a request from a caller to read something */
|
||||
+static BlockDriverAIOCB *dictzip_aio_readv(BlockDriverState *bs,
|
||||
+ int64_t sector_num, QEMUIOVector *qiov, int nb_sectors,
|
||||
+ BlockDriverCompletionFunc *cb, void *opaque)
|
||||
+{
|
||||
+ BDRVDictZipState *s = bs->opaque;
|
||||
+ DictZipAIOCB *acb;
|
||||
+ QEMUIOVector *qiov_gz;
|
||||
+ struct iovec *iov;
|
||||
+ uint8_t *buf;
|
||||
+ size_t start = sector_num * SECTOR_SIZE;
|
||||
+ size_t len = nb_sectors * SECTOR_SIZE;
|
||||
+ size_t end = start + len;
|
||||
+ size_t gz_start;
|
||||
+ size_t gz_len;
|
||||
+ int64_t gz_sector_num;
|
||||
+ int gz_nb_sectors;
|
||||
+ int first_chunk, last_chunk;
|
||||
+ int first_offset;
|
||||
+ int i;
|
||||
+
|
||||
+ acb = qemu_aio_get(&dictzip_aiocb_info, bs, cb, opaque);
|
||||
+ if (!acb)
|
||||
+ return NULL;
|
||||
+
|
||||
+ /* Search Cache */
|
||||
+ for (i = 0; i < CACHE_COUNT; i++) {
|
||||
+ if (!s->cache[i].len)
|
||||
+ continue;
|
||||
+
|
||||
+ if ((start >= s->cache[i].start) &&
|
||||
+ (end <= (s->cache[i].start + s->cache[i].len))) {
|
||||
+ acb->buf = s->cache[i].buf + (start - s->cache[i].start);
|
||||
+ acb->len = len;
|
||||
+ acb->qiov = qiov;
|
||||
+ acb->bh = qemu_bh_new(dictzip_cache_cb, acb);
|
||||
+ qemu_bh_schedule(acb->bh);
|
||||
+
|
||||
+ return &acb->common;
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ /* No cache, so let's decode */
|
||||
+ do {
|
||||
+ for (i = 0; i < Z_STREAM_COUNT; i++) {
|
||||
+ if (!(s->stream_in_use & (1 << i))) {
|
||||
+ s->stream_in_use |= (1 << i);
|
||||
+ acb->zStream_id = i;
|
||||
+ acb->zStream = &s->zStream[i];
|
||||
+ break;
|
||||
+ }
|
||||
+ }
|
||||
+ } while(!acb->zStream);
|
||||
+
|
||||
+ /* We need to read these chunks */
|
||||
+ first_chunk = start / s->chunk_len;
|
||||
+ first_offset = start - first_chunk * s->chunk_len;
|
||||
+ last_chunk = end / s->chunk_len;
|
||||
+
|
||||
+ gz_start = s->offsets[first_chunk];
|
||||
+ gz_len = 0;
|
||||
+ for (i = first_chunk; i <= last_chunk; i++) {
|
||||
+ if (s->chunks32)
|
||||
+ gz_len += s->chunks32[i];
|
||||
+ else
|
||||
+ gz_len += s->chunks[i];
|
||||
+ }
|
||||
+
|
||||
+ gz_sector_num = gz_start / SECTOR_SIZE;
|
||||
+ gz_nb_sectors = (gz_len / SECTOR_SIZE);
|
||||
+
|
||||
+ /* account for tail and heads */
|
||||
+ while ((gz_start + gz_len) > ((gz_sector_num + gz_nb_sectors) * SECTOR_SIZE))
|
||||
+ gz_nb_sectors++;
|
||||
+
|
||||
+ /* Allocate qiov, iov and buf in one chunk so we only need to free qiov */
|
||||
+ qiov_gz = g_malloc0(sizeof(QEMUIOVector) + sizeof(struct iovec) +
|
||||
+ (gz_nb_sectors * SECTOR_SIZE));
|
||||
+ iov = (struct iovec *)(((char *)qiov_gz) + sizeof(QEMUIOVector));
|
||||
+ buf = ((uint8_t *)iov) + sizeof(struct iovec *);
|
||||
+
|
||||
+ /* Kick off the read by the backing file, so we can start decompressing */
|
||||
+ iov->iov_base = (void *)buf;
|
||||
+ iov->iov_len = gz_nb_sectors * 512;
|
||||
+ qemu_iovec_init_external(qiov_gz, iov, 1);
|
||||
+
|
||||
+ dprintf("read %d - %d => %d - %d\n", start, end, gz_start, gz_start + gz_len);
|
||||
+
|
||||
+ acb->s = s;
|
||||
+ acb->qiov = qiov;
|
||||
+ acb->qiov_gz = qiov_gz;
|
||||
+ acb->start = start;
|
||||
+ acb->len = len;
|
||||
+ acb->gzipped = buf + (gz_start % SECTOR_SIZE);
|
||||
+ acb->gz_len = gz_len;
|
||||
+ acb->gz_start = first_chunk * s->chunk_len;
|
||||
+ acb->offset = first_offset;
|
||||
+ acb->chunks_len = (last_chunk - first_chunk + 1) * s->chunk_len;
|
||||
+
|
||||
+ return bdrv_aio_readv(s->hd, gz_sector_num, qiov_gz, gz_nb_sectors,
|
||||
+ dictzip_read_cb, acb);
|
||||
+}
|
||||
+
|
||||
+static void dictzip_close(BlockDriverState *bs)
|
||||
+{
|
||||
+ BDRVDictZipState *s = bs->opaque;
|
||||
+ int i;
|
||||
+
|
||||
+ for (i = 0; i < CACHE_COUNT; i++) {
|
||||
+ if (!s->cache[i].len)
|
||||
+ continue;
|
||||
+
|
||||
+ g_free(s->cache[i].buf);
|
||||
+ }
|
||||
+
|
||||
+ for (i = 0; i < Z_STREAM_COUNT; i++) {
|
||||
+ inflateEnd(&s->zStream[i]);
|
||||
+ }
|
||||
+
|
||||
+ if (s->chunks)
|
||||
+ g_free(s->chunks);
|
||||
+
|
||||
+ if (s->offsets)
|
||||
+ g_free(s->offsets);
|
||||
+
|
||||
+ dprintf("Close\n");
|
||||
+}
|
||||
+
|
||||
+static int64_t dictzip_getlength(BlockDriverState *bs)
|
||||
+{
|
||||
+ BDRVDictZipState *s = bs->opaque;
|
||||
+ dprintf("getlength -> %ld\n", s->file_len);
|
||||
+ return s->file_len;
|
||||
+}
|
||||
+
|
||||
+static BlockDriver bdrv_dictzip = {
|
||||
+ .format_name = "dzip",
|
||||
+ .protocol_name = "dzip",
|
||||
+
|
||||
+ .instance_size = sizeof(BDRVDictZipState),
|
||||
+ .bdrv_file_open = dictzip_open,
|
||||
+ .bdrv_close = dictzip_close,
|
||||
+ .bdrv_getlength = dictzip_getlength,
|
||||
+ .bdrv_probe = dictzip_probe,
|
||||
+
|
||||
+ .bdrv_aio_readv = dictzip_aio_readv,
|
||||
+};
|
||||
+
|
||||
+static void dictzip_block_init(void)
|
||||
+{
|
||||
+ bdrv_register(&bdrv_dictzip);
|
||||
+}
|
||||
+
|
||||
+block_init(dictzip_block_init);
|
399
0034-Add-tar-container-format.patch.patch
Normal file
399
0034-Add-tar-container-format.patch.patch
Normal file
@ -0,0 +1,399 @@
|
||||
From ea0fed7478adeeaf13696c23493c2c6d86d73889 Mon Sep 17 00:00:00 2001
|
||||
From: Alexander Graf <agraf@suse.de>
|
||||
Date: Wed, 5 Aug 2009 17:28:38 +0200
|
||||
Subject: [PATCH] Add tar container format
|
||||
|
||||
Tar is a very widely used format to store data in. Sometimes people even put
|
||||
virtual machine images in there.
|
||||
|
||||
So it makes sense for qemu to be able to read from tar files. I implemented a
|
||||
written from scratch reader that also knows about the GNU sparse format, which
|
||||
is what pigz creates.
|
||||
|
||||
This version checks for filenames that end on well-known extensions. The logic
|
||||
could be changed to search for filenames given on the command line, but that
|
||||
would require changes to more parts of qemu.
|
||||
|
||||
The tar reader in conjunctiuon with dzip gives us the chance to download
|
||||
tar'ed up virtual machine images (even via http) and instantly make use of
|
||||
them.
|
||||
|
||||
Signed-off-by: Alexander Graf <agraf@suse.de>
|
||||
Signed-off-by: Bruce Rogers <brogers@novell.com>
|
||||
---
|
||||
block/Makefile.objs | 1 +
|
||||
block/tar.c | 356 +++++++++++++++++++++++++++++++++++++++++++++++++++
|
||||
2 files changed, 357 insertions(+), 0 deletions(-)
|
||||
create mode 100644 block/tar.c
|
||||
|
||||
diff --git a/block/Makefile.objs b/block/Makefile.objs
|
||||
index 054b06e..34850e3 100644
|
||||
--- a/block/Makefile.objs
|
||||
+++ b/block/Makefile.objs
|
||||
@@ -19,3 +19,4 @@ common-obj-y += stream.o
|
||||
common-obj-y += commit.o
|
||||
common-obj-y += mirror.o
|
||||
common-obj-y += dictzip.o
|
||||
+common-obj-y += tar.o
|
||||
diff --git a/block/tar.c b/block/tar.c
|
||||
new file mode 100644
|
||||
index 0000000..27750c7
|
||||
--- /dev/null
|
||||
+++ b/block/tar.c
|
||||
@@ -0,0 +1,356 @@
|
||||
+/*
|
||||
+ * Tar block driver
|
||||
+ *
|
||||
+ * Copyright (c) 2009 Alexander Graf <agraf@suse.de>
|
||||
+ *
|
||||
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
+ * of this software and associated documentation files (the "Software"), to deal
|
||||
+ * in the Software without restriction, including without limitation the rights
|
||||
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
+ * copies of the Software, and to permit persons to whom the Software is
|
||||
+ * furnished to do so, subject to the following conditions:
|
||||
+ *
|
||||
+ * The above copyright notice and this permission notice shall be included in
|
||||
+ * all copies or substantial portions of the Software.
|
||||
+ *
|
||||
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
||||
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
+ * THE SOFTWARE.
|
||||
+ */
|
||||
+
|
||||
+#include "qemu-common.h"
|
||||
+#include "block_int.h"
|
||||
+
|
||||
+// #define DEBUG
|
||||
+
|
||||
+#ifdef DEBUG
|
||||
+#define dprintf(fmt, ...) do { printf("tar: " fmt, ## __VA_ARGS__); } while (0)
|
||||
+#else
|
||||
+#define dprintf(fmt, ...) do { } while (0)
|
||||
+#endif
|
||||
+
|
||||
+#define SECTOR_SIZE 512
|
||||
+
|
||||
+#define POSIX_TAR_MAGIC "ustar"
|
||||
+#define OFFS_LENGTH 0x7c
|
||||
+#define OFFS_TYPE 0x9c
|
||||
+#define OFFS_MAGIC 0x101
|
||||
+
|
||||
+#define OFFS_S_SP 0x182
|
||||
+#define OFFS_S_EXT 0x1e2
|
||||
+#define OFFS_S_LENGTH 0x1e3
|
||||
+#define OFFS_SX_EXT 0x1f8
|
||||
+
|
||||
+typedef struct SparseCache {
|
||||
+ uint64_t start;
|
||||
+ uint64_t end;
|
||||
+} SparseCache;
|
||||
+
|
||||
+typedef struct BDRVTarState {
|
||||
+ BlockDriverState *hd;
|
||||
+ size_t file_sec;
|
||||
+ uint64_t file_len;
|
||||
+ SparseCache *sparse;
|
||||
+ int sparse_num;
|
||||
+ uint64_t last_end;
|
||||
+ char longfile[2048];
|
||||
+} BDRVTarState;
|
||||
+
|
||||
+static int tar_probe(const uint8_t *buf, int buf_size, const char *filename)
|
||||
+{
|
||||
+ if (buf_size < OFFS_MAGIC + 5)
|
||||
+ return 0;
|
||||
+
|
||||
+ /* we only support newer tar */
|
||||
+ if (!strncmp((char*)buf + OFFS_MAGIC, POSIX_TAR_MAGIC, 5))
|
||||
+ return 100;
|
||||
+
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
+static int str_ends(char *str, const char *end)
|
||||
+{
|
||||
+ int end_len = strlen(end);
|
||||
+ int str_len = strlen(str);
|
||||
+
|
||||
+ if (str_len < end_len)
|
||||
+ return 0;
|
||||
+
|
||||
+ return !strncmp(str + str_len - end_len, end, end_len);
|
||||
+}
|
||||
+
|
||||
+static int is_target_file(BlockDriverState *bs, char *filename)
|
||||
+{
|
||||
+ int retval = 0;
|
||||
+
|
||||
+ if (str_ends(filename, ".raw"))
|
||||
+ retval = 1;
|
||||
+
|
||||
+ if (str_ends(filename, ".qcow"))
|
||||
+ retval = 1;
|
||||
+
|
||||
+ if (str_ends(filename, ".qcow2"))
|
||||
+ retval = 1;
|
||||
+
|
||||
+ if (str_ends(filename, ".vmdk"))
|
||||
+ retval = 1;
|
||||
+
|
||||
+ dprintf("does filename %s match? %s\n", filename, retval ? "yes" : "no");
|
||||
+
|
||||
+ /* make sure we're not using this name again */
|
||||
+ filename[0] = '\0';
|
||||
+ return retval;
|
||||
+}
|
||||
+
|
||||
+static uint64_t tar2u64(char *ptr)
|
||||
+{
|
||||
+ uint64_t retval;
|
||||
+ char oldend = ptr[12];
|
||||
+
|
||||
+ ptr[12] = '\0';
|
||||
+ if (*ptr & 0x80) {
|
||||
+ /* XXX we only support files up to 64 bit length */
|
||||
+ retval = be64_to_cpu(*(uint64_t *)(ptr+4));
|
||||
+ dprintf("Convert %lx -> %#lx\n", *(uint64_t*)(ptr+4), retval);
|
||||
+ } else {
|
||||
+ retval = strtol(ptr, NULL, 8);
|
||||
+ dprintf("Convert %s -> %#lx\n", ptr, retval);
|
||||
+ }
|
||||
+
|
||||
+ ptr[12] = oldend;
|
||||
+
|
||||
+ return retval;
|
||||
+}
|
||||
+
|
||||
+static void tar_sparse(BDRVTarState *s, uint64_t offs, uint64_t len)
|
||||
+{
|
||||
+ SparseCache *sparse;
|
||||
+
|
||||
+ if (!len)
|
||||
+ return;
|
||||
+ if (!(offs - s->last_end)) {
|
||||
+ s->last_end += len;
|
||||
+ return;
|
||||
+ }
|
||||
+ if (s->last_end > offs)
|
||||
+ return;
|
||||
+
|
||||
+ dprintf("Last chunk until %lx new chunk at %lx\n", s->last_end, offs);
|
||||
+
|
||||
+ s->sparse = g_realloc(s->sparse, (s->sparse_num + 1) * sizeof(SparseCache));
|
||||
+ sparse = &s->sparse[s->sparse_num];
|
||||
+ sparse->start = s->last_end;
|
||||
+ sparse->end = offs;
|
||||
+ s->last_end = offs + len;
|
||||
+ s->sparse_num++;
|
||||
+ dprintf("Sparse at %lx end=%lx\n", sparse->start,
|
||||
+ sparse->end);
|
||||
+}
|
||||
+
|
||||
+static int tar_open(BlockDriverState *bs, const char *filename, int flags)
|
||||
+{
|
||||
+ BDRVTarState *s = bs->opaque;
|
||||
+ char header[SECTOR_SIZE];
|
||||
+ char *real_file = header;
|
||||
+ char *magic;
|
||||
+ const char *fname = filename;
|
||||
+ size_t header_offs = 0;
|
||||
+ int ret;
|
||||
+
|
||||
+ if (!strncmp(filename, "tar://", 6))
|
||||
+ fname += 6;
|
||||
+ else if (!strncmp(filename, "tar:", 4))
|
||||
+ fname += 4;
|
||||
+
|
||||
+ ret = bdrv_file_open(&s->hd, fname, flags);
|
||||
+ if (ret < 0)
|
||||
+ return ret;
|
||||
+
|
||||
+ /* Search the file for an image */
|
||||
+
|
||||
+ do {
|
||||
+ /* tar header */
|
||||
+ if (bdrv_pread(s->hd, header_offs, header, SECTOR_SIZE) != SECTOR_SIZE)
|
||||
+ goto fail;
|
||||
+
|
||||
+ if ((header_offs > 1) && !header[0]) {
|
||||
+ fprintf(stderr, "Tar: No image file found in archive\n");
|
||||
+ goto fail;
|
||||
+ }
|
||||
+
|
||||
+ magic = &header[OFFS_MAGIC];
|
||||
+ if (strncmp(magic, POSIX_TAR_MAGIC, 5)) {
|
||||
+ fprintf(stderr, "Tar: Invalid magic: %s\n", magic);
|
||||
+ goto fail;
|
||||
+ }
|
||||
+
|
||||
+ dprintf("file type: %c\n", header[OFFS_TYPE]);
|
||||
+
|
||||
+ /* file length*/
|
||||
+ s->file_len = (tar2u64(&header[OFFS_LENGTH]) + (SECTOR_SIZE - 1)) &
|
||||
+ ~(SECTOR_SIZE - 1);
|
||||
+ s->file_sec = (header_offs / SECTOR_SIZE) + 1;
|
||||
+
|
||||
+ header_offs += s->file_len + SECTOR_SIZE;
|
||||
+
|
||||
+ if (header[OFFS_TYPE] == 'L') {
|
||||
+ bdrv_pread(s->hd, header_offs - s->file_len, s->longfile,
|
||||
+ sizeof(s->longfile));
|
||||
+ s->longfile[sizeof(s->longfile)-1] = '\0';
|
||||
+ } else if (s->longfile[0]) {
|
||||
+ real_file = s->longfile;
|
||||
+ } else {
|
||||
+ real_file = header;
|
||||
+ }
|
||||
+ } while(!is_target_file(bs, real_file));
|
||||
+
|
||||
+ /* We found an image! */
|
||||
+
|
||||
+ if (header[OFFS_TYPE] == 'S') {
|
||||
+ uint8_t isextended;
|
||||
+ int i;
|
||||
+
|
||||
+ for (i = OFFS_S_SP; i < (OFFS_S_SP + (4 * 24)); i += 24)
|
||||
+ tar_sparse(s, tar2u64(&header[i]), tar2u64(&header[i+12]));
|
||||
+
|
||||
+ s->file_len = tar2u64(&header[OFFS_S_LENGTH]);
|
||||
+ isextended = header[OFFS_S_EXT];
|
||||
+
|
||||
+ while (isextended) {
|
||||
+ if (bdrv_pread(s->hd, s->file_sec * SECTOR_SIZE, header,
|
||||
+ SECTOR_SIZE) != SECTOR_SIZE)
|
||||
+ goto fail;
|
||||
+
|
||||
+ for (i = 0; i < (21 * 24); i += 24)
|
||||
+ tar_sparse(s, tar2u64(&header[i]), tar2u64(&header[i+12]));
|
||||
+ isextended = header[OFFS_SX_EXT];
|
||||
+ s->file_sec++;
|
||||
+ }
|
||||
+ tar_sparse(s, s->file_len, 1);
|
||||
+ }
|
||||
+
|
||||
+ return 0;
|
||||
+
|
||||
+fail:
|
||||
+ fprintf(stderr, "Tar: Error opening file\n");
|
||||
+ bdrv_delete(s->hd);
|
||||
+ return -EINVAL;
|
||||
+}
|
||||
+
|
||||
+typedef struct TarAIOCB {
|
||||
+ BlockDriverAIOCB common;
|
||||
+ QEMUBH *bh;
|
||||
+} TarAIOCB;
|
||||
+
|
||||
+/* This callback gets invoked when we have pure sparseness */
|
||||
+static void tar_sparse_cb(void *opaque)
|
||||
+{
|
||||
+ TarAIOCB *acb = (TarAIOCB *)opaque;
|
||||
+
|
||||
+ acb->common.cb(acb->common.opaque, 0);
|
||||
+ qemu_bh_delete(acb->bh);
|
||||
+ qemu_aio_release(acb);
|
||||
+}
|
||||
+
|
||||
+static void tar_aio_cancel(BlockDriverAIOCB *blockacb)
|
||||
+{
|
||||
+}
|
||||
+
|
||||
+static AIOCBInfo tar_aiocb_info = {
|
||||
+ .aiocb_size = sizeof(TarAIOCB),
|
||||
+ .cancel = tar_aio_cancel,
|
||||
+};
|
||||
+
|
||||
+/* This is where we get a request from a caller to read something */
|
||||
+static BlockDriverAIOCB *tar_aio_readv(BlockDriverState *bs,
|
||||
+ int64_t sector_num, QEMUIOVector *qiov, int nb_sectors,
|
||||
+ BlockDriverCompletionFunc *cb, void *opaque)
|
||||
+{
|
||||
+ BDRVTarState *s = bs->opaque;
|
||||
+ SparseCache *sparse;
|
||||
+ int64_t sec_file = sector_num + s->file_sec;
|
||||
+ int64_t start = sector_num * SECTOR_SIZE;
|
||||
+ int64_t end = start + (nb_sectors * SECTOR_SIZE);
|
||||
+ int i;
|
||||
+ TarAIOCB *acb;
|
||||
+
|
||||
+ for (i = 0; i < s->sparse_num; i++) {
|
||||
+ sparse = &s->sparse[i];
|
||||
+ if (sparse->start > end) {
|
||||
+ /* We expect the cache to be start increasing */
|
||||
+ break;
|
||||
+ } else if ((sparse->start < start) && (sparse->end <= start)) {
|
||||
+ /* sparse before our offset */
|
||||
+ sec_file -= (sparse->end - sparse->start) / SECTOR_SIZE;
|
||||
+ } else if ((sparse->start <= start) && (sparse->end >= end)) {
|
||||
+ /* all our sectors are sparse */
|
||||
+ char *buf = g_malloc0(nb_sectors * SECTOR_SIZE);
|
||||
+
|
||||
+ acb = qemu_aio_get(&tar_aiocb_info, bs, cb, opaque);
|
||||
+ qemu_iovec_from_buf(qiov, 0, buf, nb_sectors * SECTOR_SIZE);
|
||||
+ g_free(buf);
|
||||
+ acb->bh = qemu_bh_new(tar_sparse_cb, acb);
|
||||
+ qemu_bh_schedule(acb->bh);
|
||||
+
|
||||
+ return &acb->common;
|
||||
+ } else if (((sparse->start >= start) && (sparse->start < end)) ||
|
||||
+ ((sparse->end >= start) && (sparse->end < end))) {
|
||||
+ /* we're semi-sparse (worst case) */
|
||||
+ /* let's go synchronous and read all sectors individually */
|
||||
+ char *buf = g_malloc(nb_sectors * SECTOR_SIZE);
|
||||
+ uint64_t offs;
|
||||
+
|
||||
+ for (offs = 0; offs < (nb_sectors * SECTOR_SIZE);
|
||||
+ offs += SECTOR_SIZE) {
|
||||
+ bdrv_pread(bs, (sector_num * SECTOR_SIZE) + offs,
|
||||
+ buf + offs, SECTOR_SIZE);
|
||||
+ }
|
||||
+
|
||||
+ qemu_iovec_from_buf(qiov, 0, buf, nb_sectors * SECTOR_SIZE);
|
||||
+ acb = qemu_aio_get(&tar_aiocb_info, bs, cb, opaque);
|
||||
+ acb->bh = qemu_bh_new(tar_sparse_cb, acb);
|
||||
+ qemu_bh_schedule(acb->bh);
|
||||
+
|
||||
+ return &acb->common;
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ return bdrv_aio_readv(s->hd, sec_file, qiov, nb_sectors,
|
||||
+ cb, opaque);
|
||||
+}
|
||||
+
|
||||
+static void tar_close(BlockDriverState *bs)
|
||||
+{
|
||||
+ dprintf("Close\n");
|
||||
+}
|
||||
+
|
||||
+static int64_t tar_getlength(BlockDriverState *bs)
|
||||
+{
|
||||
+ BDRVTarState *s = bs->opaque;
|
||||
+ dprintf("getlength -> %ld\n", s->file_len);
|
||||
+ return s->file_len;
|
||||
+}
|
||||
+
|
||||
+static BlockDriver bdrv_tar = {
|
||||
+ .format_name = "tar",
|
||||
+ .protocol_name = "tar",
|
||||
+
|
||||
+ .instance_size = sizeof(BDRVTarState),
|
||||
+ .bdrv_file_open = tar_open,
|
||||
+ .bdrv_close = tar_close,
|
||||
+ .bdrv_getlength = tar_getlength,
|
||||
+ .bdrv_probe = tar_probe,
|
||||
+
|
||||
+ .bdrv_aio_readv = tar_aio_readv,
|
||||
+};
|
||||
+
|
||||
+static void tar_block_init(void)
|
||||
+{
|
||||
+ bdrv_register(&bdrv_tar);
|
||||
+}
|
||||
+
|
||||
+block_init(tar_block_init);
|
56
0035-Legacy-Patch-kvm-qemu-preXX-dictzip.patch
Normal file
56
0035-Legacy-Patch-kvm-qemu-preXX-dictzip.patch
Normal file
@ -0,0 +1,56 @@
|
||||
From bd6cf9e4804b30c8212fe83ca3f08b12ab4f2d80 Mon Sep 17 00:00:00 2001
|
||||
From: Alexander Graf <agraf@suse.de>
|
||||
Date: Wed, 12 Dec 2012 19:11:30 +0100
|
||||
Subject: [PATCH] Legacy Patch kvm-qemu-preXX-dictzip3.patch
|
||||
|
||||
---
|
||||
block/tar.c | 13 +++++++++++--
|
||||
1 files changed, 11 insertions(+), 2 deletions(-)
|
||||
|
||||
diff --git a/block/tar.c b/block/tar.c
|
||||
index 27750c7..c5b75aa 100644
|
||||
--- a/block/tar.c
|
||||
+++ b/block/tar.c
|
||||
@@ -83,7 +83,8 @@ static int str_ends(char *str, const char *end)
|
||||
return !strncmp(str + str_len - end_len, end, end_len);
|
||||
}
|
||||
|
||||
-static int is_target_file(BlockDriverState *bs, char *filename)
|
||||
+static int is_target_file(BlockDriverState *bs, char *filename,
|
||||
+ char *header)
|
||||
{
|
||||
int retval = 0;
|
||||
|
||||
@@ -99,10 +100,17 @@ static int is_target_file(BlockDriverState *bs, char *filename)
|
||||
if (str_ends(filename, ".vmdk"))
|
||||
retval = 1;
|
||||
|
||||
+ if (retval &&
|
||||
+ (header[OFFS_TYPE] != '0') &&
|
||||
+ (header[OFFS_TYPE] != 'S')) {
|
||||
+ retval = 0;
|
||||
+ }
|
||||
+
|
||||
dprintf("does filename %s match? %s\n", filename, retval ? "yes" : "no");
|
||||
|
||||
/* make sure we're not using this name again */
|
||||
filename[0] = '\0';
|
||||
+
|
||||
return retval;
|
||||
}
|
||||
|
||||
@@ -201,12 +209,13 @@ static int tar_open(BlockDriverState *bs, const char *filename, int flags)
|
||||
bdrv_pread(s->hd, header_offs - s->file_len, s->longfile,
|
||||
sizeof(s->longfile));
|
||||
s->longfile[sizeof(s->longfile)-1] = '\0';
|
||||
+ real_file = header;
|
||||
} else if (s->longfile[0]) {
|
||||
real_file = s->longfile;
|
||||
} else {
|
||||
real_file = header;
|
||||
}
|
||||
- } while(!is_target_file(bs, real_file));
|
||||
+ } while(!is_target_file(bs, real_file, header));
|
||||
|
||||
/* We found an image! */
|
||||
|
49
0036-Legacy-Patch-kvm-qemu-preXX-report-.patch
Normal file
49
0036-Legacy-Patch-kvm-qemu-preXX-report-.patch
Normal file
@ -0,0 +1,49 @@
|
||||
From fba5b73038a98aa1fd602ed3f7bc5c09026afd4a Mon Sep 17 00:00:00 2001
|
||||
From: Alexander Graf <agraf@suse.de>
|
||||
Date: Wed, 12 Dec 2012 19:11:31 +0100
|
||||
Subject: [PATCH] Legacy Patch kvm-qemu-preXX-report-default-mac-used.patch
|
||||
|
||||
---
|
||||
net.c | 22 ++++++++++++++++++++++
|
||||
1 files changed, 22 insertions(+), 0 deletions(-)
|
||||
|
||||
diff --git a/net.c b/net.c
|
||||
index e8ae13e..e181e50 100644
|
||||
--- a/net.c
|
||||
+++ b/net.c
|
||||
@@ -138,6 +138,27 @@ void qemu_format_nic_info_str(NetClientState *nc, uint8_t macaddr[6])
|
||||
macaddr[3], macaddr[4], macaddr[5]);
|
||||
}
|
||||
|
||||
+static void default_mac_check(void)
|
||||
+{
|
||||
+ static const MACAddr def_mac = { .a = { 0x52,0x54,0x00,0x12,0x34,0x56 } };
|
||||
+ static int warned = 0;
|
||||
+ int i;
|
||||
+
|
||||
+ for (i = 0; i < MAX_NICS; i++)
|
||||
+ {
|
||||
+ if (!nd_table[i].used)
|
||||
+ continue;
|
||||
+ if (memcmp(nd_table[i].macaddr.a, def_mac.a, 5))
|
||||
+ continue;
|
||||
+ if (nd_table[i].macaddr.a[5] >= 0x56 &&
|
||||
+ nd_table[i].macaddr.a[5] < 0x56 + MAX_NICS && !warned) {
|
||||
+ warned = 1;
|
||||
+ fprintf(stderr, "Warning: default mac address being used, creating "
|
||||
+ "potential for address conflict\n");
|
||||
+ }
|
||||
+ }
|
||||
+}
|
||||
+
|
||||
void qemu_macaddr_default_if_unset(MACAddr *macaddr)
|
||||
{
|
||||
static int index = 0;
|
||||
@@ -1010,6 +1031,7 @@ int net_init_clients(void)
|
||||
if (qemu_opts_foreach(net, net_init_client, NULL, 1) == -1) {
|
||||
return -1;
|
||||
}
|
||||
+ default_mac_check();
|
||||
|
||||
return 0;
|
||||
}
|
30
0037-console-add-question-mark-escape-op.patch
Normal file
30
0037-console-add-question-mark-escape-op.patch
Normal file
@ -0,0 +1,30 @@
|
||||
From 45c73a5a93f98bf1264d6678648a6e7392a0c7b1 Mon Sep 17 00:00:00 2001
|
||||
From: Alexander Graf <agraf@suse.de>
|
||||
Date: Mon, 6 Jun 2011 06:53:52 +0200
|
||||
Subject: [PATCH] console: add question-mark escape operator
|
||||
|
||||
Some termcaps (found using SLES11SP1) use [? sequences. According to man
|
||||
console_codes (http://linux.die.net/man/4/console_codes) the question mark
|
||||
is a nop and should simply be ignored.
|
||||
|
||||
This patch does exactly that, rendering screen output readable when
|
||||
outputting guest serial consoles to the graphical console emulator.
|
||||
|
||||
Signed-off-by: Alexander Graf <agraf@suse.de>
|
||||
---
|
||||
console.c | 2 +-
|
||||
1 files changed, 1 insertions(+), 1 deletions(-)
|
||||
|
||||
diff --git a/console.c b/console.c
|
||||
index 048b48e..079f638 100644
|
||||
--- a/console.c
|
||||
+++ b/console.c
|
||||
@@ -950,7 +950,7 @@ static void console_putchar(QemuConsole *s, int ch)
|
||||
} else {
|
||||
if (s->nb_esc_params < MAX_ESC_PARAMS)
|
||||
s->nb_esc_params++;
|
||||
- if (ch == ';')
|
||||
+ if (ch == ';' || ch == '?')
|
||||
break;
|
||||
#ifdef DEBUG_CONSOLE
|
||||
fprintf(stderr, "escape sequence CSI%d;%d%c, %d parameters\n",
|
64
0038-Make-char-muxer-more-robust-wrt-sma.patch
Normal file
64
0038-Make-char-muxer-more-robust-wrt-sma.patch
Normal file
@ -0,0 +1,64 @@
|
||||
From afd30877ef2291d742fc1b57e24d80de8673b22c Mon Sep 17 00:00:00 2001
|
||||
From: Alexander Graf <agraf@suse.de>
|
||||
Date: Thu, 1 Apr 2010 17:36:23 +0200
|
||||
Subject: [PATCH] Make char muxer more robust wrt small FIFOs
|
||||
|
||||
Virtio-Console can only process one character at a time. Using it on S390
|
||||
gave me strage "lags" where I got the character I pressed before when
|
||||
pressing one. So I typed in "abc" and only received "a", then pressed "d"
|
||||
but the guest received "b" and so on.
|
||||
|
||||
While the stdio driver calls a poll function that just processes on its
|
||||
queue in case virtio-console can't take multiple characters at once, the
|
||||
muxer does not have such callbacks, so it can't empty its queue.
|
||||
|
||||
To work around that limitation, I introduced a new timer that only gets
|
||||
active when the guest can not receive any more characters. In that case
|
||||
it polls again after a while to check if the guest is now receiving input.
|
||||
|
||||
This patch fixes input when using -nographic on s390 for me.
|
||||
---
|
||||
qemu-char.c | 16 ++++++++++++++++
|
||||
1 files changed, 16 insertions(+), 0 deletions(-)
|
||||
|
||||
diff --git a/qemu-char.c b/qemu-char.c
|
||||
index 242b799..00e1b51 100644
|
||||
--- a/qemu-char.c
|
||||
+++ b/qemu-char.c
|
||||
@@ -241,6 +241,9 @@ typedef struct {
|
||||
IOEventHandler *chr_event[MAX_MUX];
|
||||
void *ext_opaque[MAX_MUX];
|
||||
CharDriverState *drv;
|
||||
+#if defined(TARGET_S390X)
|
||||
+ QEMUTimer *accept_timer;
|
||||
+#endif
|
||||
int focus;
|
||||
int mux_cnt;
|
||||
int term_got_escape;
|
||||
@@ -397,6 +400,15 @@ static void mux_chr_accept_input(CharDriverState *chr)
|
||||
d->chr_read[m](d->ext_opaque[m],
|
||||
&d->buffer[m][d->cons[m]++ & MUX_BUFFER_MASK], 1);
|
||||
}
|
||||
+
|
||||
+#if defined(TARGET_S390X)
|
||||
+ /* We're still not able to sync producer and consumer, so let's wait a bit
|
||||
+ and try again by then. */
|
||||
+ if (d->prod[m] != d->cons[m]) {
|
||||
+ qemu_mod_timer(d->accept_timer, qemu_get_clock_ns(vm_clock)
|
||||
+ + (int64_t)100000);
|
||||
+ }
|
||||
+#endif
|
||||
}
|
||||
|
||||
static int mux_chr_can_read(void *opaque)
|
||||
@@ -479,6 +491,10 @@ static CharDriverState *qemu_chr_open_mux(CharDriverState *drv)
|
||||
chr->opaque = d;
|
||||
d->drv = drv;
|
||||
d->focus = -1;
|
||||
+#if defined(TARGET_S390X)
|
||||
+ d->accept_timer = qemu_new_timer_ns(vm_clock,
|
||||
+ (QEMUTimerCB*)mux_chr_accept_input, chr);
|
||||
+#endif
|
||||
chr->chr_write = mux_chr_write;
|
||||
chr->chr_update_read_handler = mux_chr_update_read_handler;
|
||||
chr->chr_accept_input = mux_chr_accept_input;
|
11
qemu.changes
11
qemu.changes
@ -1,3 +1,14 @@
|
||||
-------------------------------------------------------------------
|
||||
Thu Dec 13 10:47:52 UTC 2012 - agraf@suse.com
|
||||
|
||||
- Cherry pick patches from qemu-kvm into the qemu package:
|
||||
- 0033-Add-support-for-DictZip-enabled-gzi.patch
|
||||
- 0034-Add-tar-container-format.patch.patch
|
||||
- 0035-Legacy-Patch-kvm-qemu-preXX-dictzip.patch
|
||||
- 0036-Legacy-Patch-kvm-qemu-preXX-report-.patch
|
||||
- 0037-console-add-question-mark-escape-op.patch
|
||||
- 0038-Make-char-muxer-more-robust-wrt-sma.patch
|
||||
|
||||
-------------------------------------------------------------------
|
||||
Wed Dec 5 13:25:31 UTC 2012 - afaerber@suse.de
|
||||
|
||||
|
12
qemu.spec
12
qemu.spec
@ -56,6 +56,12 @@ Patch0029: 0029-slirp-nooutgoing.patch.patch
|
||||
Patch0030: 0030-vnc-password-file-and-incoming-conn.patch
|
||||
Patch0031: 0031-linux-user-add-more-blk-ioctls.patc.patch
|
||||
Patch0032: 0032-linux-user-use-target_ulong.patch.patch
|
||||
Patch0033: 0033-Add-support-for-DictZip-enabled-gzi.patch
|
||||
Patch0034: 0034-Add-tar-container-format.patch.patch
|
||||
Patch0035: 0035-Legacy-Patch-kvm-qemu-preXX-dictzip.patch
|
||||
Patch0036: 0036-Legacy-Patch-kvm-qemu-preXX-report-.patch
|
||||
Patch0037: 0037-console-add-question-mark-escape-op.patch
|
||||
Patch0038: 0038-Make-char-muxer-more-robust-wrt-sma.patch
|
||||
# this is to make lint happy
|
||||
Source300: rpmlintrc
|
||||
Source302: bridge.conf
|
||||
@ -206,6 +212,12 @@ run cross-architecture builds.
|
||||
%patch0030 -p1
|
||||
%patch0031 -p1
|
||||
%patch0032 -p1
|
||||
%patch0033 -p1
|
||||
%patch0034 -p1
|
||||
%patch0035 -p1
|
||||
%patch0036 -p1
|
||||
%patch0037 -p1
|
||||
%patch0038 -p1
|
||||
|
||||
%build
|
||||
# build QEMU
|
||||
|
Loading…
Reference in New Issue
Block a user