summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorKrishnendu Sadhukhan - Sun Microsystems <Krishnendu.Sadhukhan@Sun.COM>2008-10-16 10:02:23 -0700
committerKrishnendu Sadhukhan - Sun Microsystems <Krishnendu.Sadhukhan@Sun.COM>2008-10-16 10:02:23 -0700
commit1d7f3fadeebf3754e3f042d91e7a4439755dc598 (patch)
treec031aeaaf4bf0f84ed5b91791551f45a93c20525
parente66c2924ff28146fcc085fb48930b624cf64a36e (diff)
downloadillumos-joyent-1d7f3fadeebf3754e3f042d91e7a4439755dc598.tar.gz
6755292 Fast reboot should support failsafe
-rw-r--r--usr/src/cmd/boot/fiocompress/fiocompress.c10
-rw-r--r--usr/src/uts/common/fs/dcfs/dc_vnops.c5
-rw-r--r--usr/src/uts/common/krtld/kobj.c108
-rw-r--r--usr/src/uts/common/sys/fs/decomp.h7
-rw-r--r--usr/src/uts/common/zmod/zmod.c12
5 files changed, 120 insertions, 22 deletions
diff --git a/usr/src/cmd/boot/fiocompress/fiocompress.c b/usr/src/cmd/boot/fiocompress/fiocompress.c
index cef348b158..f63683c2e5 100644
--- a/usr/src/cmd/boot/fiocompress/fiocompress.c
+++ b/usr/src/cmd/boot/fiocompress/fiocompress.c
@@ -19,12 +19,10 @@
* CDDL HEADER END
*/
/*
- * Copyright 2007 Sun Microsystems, Inc. All rights reserved.
+ * Copyright 2008 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
-#pragma ident "%Z%%M% %I% %E% SMI"
-
/*
* fiocompress - a utility to compress files with a filesystem.
* Used to build compressed boot archives to reduce memory
@@ -188,7 +186,7 @@ do_comp(size_t blksize)
exit(-1);
}
- hdr->ch_magic = CH_MAGIC;
+ hdr->ch_magic = CH_MAGIC_ZLIB;
hdr->ch_version = CH_VERSION;
hdr->ch_algorithm = CH_ALG_ZLIB;
hdr->ch_fsize = srclen;
@@ -255,9 +253,9 @@ do_decomp()
int ret;
hdr = (struct comphdr *)(void *)srcaddr;
- if (hdr->ch_magic != CH_MAGIC) {
+ if (hdr->ch_magic != CH_MAGIC_ZLIB) {
(void) fprintf(stderr, BAD_MAGIC,
- srcfile, (uint64_t)hdr->ch_magic, CH_MAGIC);
+ srcfile, (uint64_t)hdr->ch_magic, CH_MAGIC_ZLIB);
exit(-1);
}
if (hdr->ch_version != CH_VERSION) {
diff --git a/usr/src/uts/common/fs/dcfs/dc_vnops.c b/usr/src/uts/common/fs/dcfs/dc_vnops.c
index f3cd915a49..1e30887d7f 100644
--- a/usr/src/uts/common/fs/dcfs/dc_vnops.c
+++ b/usr/src/uts/common/fs/dcfs/dc_vnops.c
@@ -37,9 +37,6 @@
* contributors.
*/
-
-#pragma ident "%Z%%M% %I% %E% SMI"
-
#include <sys/types.h>
#include <sys/thread.h>
#include <sys/t_lock.h>
@@ -930,7 +927,7 @@ decompvp(struct vnode *vp, cred_t *cred, caller_context_t *ctp)
hdr = &thdr;
error = vn_rdwr(UIO_READ, vp, (caddr_t)hdr, sizeof (struct comphdr), 0,
UIO_SYSSPACE, 0, 0, cred, NULL);
- if (error || hdr->ch_magic != CH_MAGIC ||
+ if (error || hdr->ch_magic != CH_MAGIC_ZLIB ||
hdr->ch_version != CH_VERSION || hdr->ch_algorithm != CH_ALG_ZLIB ||
hdr->ch_fsize == 0 || hdr->ch_blksize < PAGESIZE ||
hdr->ch_blksize > ptob(DCCACHESIZE) ||
diff --git a/usr/src/uts/common/krtld/kobj.c b/usr/src/uts/common/krtld/kobj.c
index 64a8ffecba..562c515279 100644
--- a/usr/src/uts/common/krtld/kobj.c
+++ b/usr/src/uts/common/krtld/kobj.c
@@ -23,8 +23,6 @@
* Use is subject to license terms.
*/
-#pragma ident "%Z%%M% %I% %E% SMI"
-
/*
* Kernel's linker/loader
*/
@@ -126,6 +124,7 @@ static Sym *sym_lookup(struct module *, Sym *);
static struct kobjopen_tctl *kobjopen_alloc(char *filename);
static void kobjopen_free(struct kobjopen_tctl *ltp);
static void kobjopen_thread(struct kobjopen_tctl *ltp);
+static int kobj_is_compressed(intptr_t);
extern int kcopy(const void *, void *, size_t);
extern int elf_mach_ok(Ehdr *);
@@ -213,7 +212,6 @@ struct lib_macro_info {
char *boot_cpu_compatible_list; /* make $CPU available */
-
char *kobj_module_path; /* module search path */
vmem_t *text_arena; /* module text arena */
static vmem_t *data_arena; /* module data & bss arena */
@@ -3728,6 +3726,11 @@ kobj_open_file(char *name)
if (_modrootloaded) {
file->_base = kobj_zalloc(MAXBSIZE, KM_WAIT);
file->_bsize = MAXBSIZE;
+
+ /* Check if the file is compressed */
+ if (kobj_is_compressed(fd)) {
+ file->_iscmp = 1;
+ }
} else {
if (kobj_boot_compinfo(fd, &cbuf) != 0) {
kobj_close_file(file);
@@ -3764,7 +3767,7 @@ kobj_comp_setup(struct _buf *file, struct compinfo *cip)
}
hdr = kobj_comphdr(file);
- if (hdr->ch_magic != CH_MAGIC || hdr->ch_version != CH_VERSION ||
+ if (hdr->ch_magic != CH_MAGIC_ZLIB || hdr->ch_version != CH_VERSION ||
hdr->ch_algorithm != CH_ALG_ZLIB || hdr->ch_fsize == 0 ||
(hdr->ch_blksize & (hdr->ch_blksize - 1)) != 0) {
kobj_free(file->_dbuf, cip->fsize);
@@ -3801,6 +3804,54 @@ kobj_read_file(struct _buf *file, char *buf, uint_t size, uint_t off)
_kobj_printf(ops, " buf=%x\n", buf);
}
+ /*
+ * Handle compressed (gzip for now) file here. First get the
+ * compressed size, then read the image into memory and finally
+ * call zlib to decompress the image at the supplied memory buffer.
+ */
+ if (file->_iscmp) {
+ ulong_t dlen;
+ vattr_t vattr;
+ struct vnode *vp = (struct vnode *)file->_fd;
+ ssize_t resid;
+ int err = 0;
+
+ if (VOP_GETATTR(vp, &vattr, 0, kcred, NULL) != 0)
+ return (-1);
+
+ file->_dbuf = kobj_alloc(vattr.va_size, KM_WAIT|KM_TMP);
+ file->_dsize = vattr.va_size;
+
+ /* Read the compressed file into memory */
+ if ((err = vn_rdwr(UIO_READ, vp, file->_dbuf, vattr.va_size,
+ (offset_t)(0), UIO_SYSSPACE, 0, (rlim64_t)0, CRED(),
+ &resid)) != 0) {
+
+ _kobj_printf(ops, "kobj_read_file :vn_rdwr() failed, "
+ "error code 0x%x\n", err);
+ return (-1);
+ }
+
+ dlen = size;
+
+ /* Decompress the image at the supplied memory buffer */
+ if ((err = z_uncompress(buf, &dlen, file->_dbuf,
+ vattr.va_size)) != Z_OK) {
+ _kobj_printf(ops, "kobj_read_file: z_uncompress "
+ "failed, error code : 0x%x\n", err);
+ return (-1);
+ }
+
+ if (dlen != size) {
+ _kobj_printf(ops, "kobj_read_file: z_uncompress "
+ "failed to uncompress (size returned 0x%x , "
+ "expected size: 0x%x)\n", dlen, size);
+ return (-1);
+ }
+
+ return (0);
+ }
+
while (size) {
page_addr = F_PAGE(file, off);
b_size = file->_size;
@@ -4107,12 +4158,34 @@ kobj_gethashsize(uint_t n)
int
kobj_get_filesize(struct _buf *file, uint64_t *size)
{
+ int err = 0;
+ ssize_t resid;
+ uint32_t buf;
+
if (_modrootloaded) {
struct bootstat bst;
if (kobj_fstat(file->_fd, &bst) != 0)
return (EIO);
*size = bst.st_size;
+
+ if (file->_iscmp) {
+ /*
+ * Read the last 4 bytes of the compressed (gzip)
+ * image to get the size of its uncompressed
+ * version.
+ */
+ if ((err = vn_rdwr(UIO_READ, (struct vnode *)file->_fd,
+ (char *)(&buf), 4, (offset_t)(*size - 4),
+ UIO_SYSSPACE, 0, (rlim64_t)0, CRED(), &resid))
+ != 0) {
+ _kobj_printf(ops, "kobj_get_filesize: "
+ "vn_rdwr() failed with error 0x%x\n", err);
+ return (-1);
+ }
+
+ *size = (uint64_t)buf;
+ }
} else {
#if defined(_OBP)
@@ -4548,3 +4621,30 @@ kobj_boot_compinfo(int fd, struct compinfo *cb)
{
return (boot_compinfo(fd, cb));
}
+
+/*
+ * Check if the file is compressed (for now we handle only gzip).
+ * It returns 1 if the file is compressed and 0 otherwise.
+ */
+static int
+kobj_is_compressed(intptr_t fd)
+{
+ struct vnode *vp = (struct vnode *)fd;
+ ssize_t resid;
+ uint16_t magic_buf;
+ int err = 0;
+
+ if ((err = vn_rdwr(UIO_READ, vp, (caddr_t)((intptr_t)&magic_buf),
+ sizeof (magic_buf), (offset_t)(0),
+ UIO_SYSSPACE, 0, (rlim64_t)0, CRED(), &resid)) != 0) {
+
+ _kobj_printf(ops, "kobj_is_compressed: vn_rdwr() failed, "
+ "error code 0x%x\n", err);
+ return (0);
+ }
+
+ if (magic_buf == CH_MAGIC_GZIP)
+ return (1);
+
+ return (0);
+}
diff --git a/usr/src/uts/common/sys/fs/decomp.h b/usr/src/uts/common/sys/fs/decomp.h
index 035a5ab6c8..81708156be 100644
--- a/usr/src/uts/common/sys/fs/decomp.h
+++ b/usr/src/uts/common/sys/fs/decomp.h
@@ -19,20 +19,19 @@
* CDDL HEADER END
*/
/*
- * Copyright 2007 Sun Microsystems, Inc. All rights reserved.
+ * Copyright 2008 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
#ifndef _SYS_DECOMP_H
#define _SYS_DECOMP_H
-#pragma ident "%Z%%M% %I% %E% SMI"
-
#ifdef __cplusplus
extern "C" {
#endif
-#define CH_MAGIC 0x5a636d70 /* Zcmp */
+#define CH_MAGIC_ZLIB 0x5a636d70 /* ZLIB compression */
+#define CH_MAGIC_GZIP 0x8B1F /* GZIP compression */
#define CH_VERSION 1
diff --git a/usr/src/uts/common/zmod/zmod.c b/usr/src/uts/common/zmod/zmod.c
index d1b0636a97..d22f595082 100644
--- a/usr/src/uts/common/zmod/zmod.c
+++ b/usr/src/uts/common/zmod/zmod.c
@@ -20,16 +20,15 @@
*/
/*
- * Copyright 2007 Sun Microsystems, Inc. All rights reserved.
+ * Copyright 2008 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
-#pragma ident "%Z%%M% %I% %E% SMI"
-
#include <sys/modctl.h>
#include <sys/zmod.h>
#include "zlib.h"
+#include "zutil.h"
/*
* Uncompress the buffer 'src' into the buffer 'dst'. The caller must store
@@ -49,7 +48,12 @@ z_uncompress(void *dst, size_t *dstlen, const void *src, size_t srclen)
zs.next_out = dst;
zs.avail_out = *dstlen;
- if ((err = inflateInit(&zs)) != Z_OK)
+ /*
+ * Call inflateInit2() specifying a window size of DEF_WBITS
+ * with the 6th bit set to indicate that the compression format
+ * type (zlib or gzip) should be automatically detected.
+ */
+ if ((err = inflateInit2(&zs, DEF_WBITS | 0x20)) != Z_OK)
return (err);
if ((err = inflate(&zs, Z_FINISH)) != Z_STREAM_END) {