2005-12-10 18:02:26 +03:00
|
|
|
/////////////////////////////////////////////////////////////////////////
|
2011-02-25 01:05:47 +03:00
|
|
|
// $Id$
|
2005-12-10 18:02:26 +03:00
|
|
|
/////////////////////////////////////////////////////////////////////////
|
|
|
|
//
|
2012-09-20 01:05:18 +04:00
|
|
|
// Copyright (C) 2002-2012 The Bochs Project
|
2005-12-10 18:02:26 +03:00
|
|
|
//
|
|
|
|
// This library is free software; you can redistribute it and/or
|
|
|
|
// modify it under the terms of the GNU Lesser General Public
|
|
|
|
// License as published by the Free Software Foundation; either
|
|
|
|
// version 2 of the License, or (at your option) any later version.
|
|
|
|
//
|
|
|
|
// This library is distributed in the hope that it will be useful,
|
|
|
|
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
|
|
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
|
|
// Lesser General Public License for more details.
|
|
|
|
//
|
|
|
|
// You should have received a copy of the GNU Lesser General Public
|
|
|
|
// License along with this library; if not, write to the Free Software
|
2009-02-08 12:05:52 +03:00
|
|
|
// Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
2008-01-27 01:24:03 +03:00
|
|
|
/////////////////////////////////////////////////////////////////////////
|
2005-12-10 18:02:26 +03:00
|
|
|
|
|
|
|
// Define BX_PLUGGABLE in files that can be compiled into plugins. For
|
|
|
|
// platforms that require a special tag on exported symbols, BX_PLUGGABLE
|
|
|
|
// is used to know when we are exporting symbols and when we are importing.
|
|
|
|
#define BX_PLUGGABLE
|
|
|
|
|
|
|
|
#include "iodev.h"
|
2011-07-17 21:23:12 +04:00
|
|
|
#include "cdrom.h"
|
2005-12-10 18:02:26 +03:00
|
|
|
#include "hdimage.h"
|
2010-12-10 20:02:18 +03:00
|
|
|
#include "vmware3.h"
|
|
|
|
#include "vmware4.h"
|
2010-12-23 19:17:12 +03:00
|
|
|
#include "vvfat.h"
|
2012-08-05 13:33:33 +04:00
|
|
|
#include "vpc-img.h"
|
2005-12-10 18:02:26 +03:00
|
|
|
|
|
|
|
#if BX_HAVE_SYS_MMAN_H
|
|
|
|
#include <sys/mman.h>
|
|
|
|
#endif
|
2011-11-26 19:09:00 +04:00
|
|
|
#ifdef linux
|
|
|
|
#include <linux/fs.h>
|
|
|
|
#include <sys/ioctl.h>
|
|
|
|
#endif
|
2005-12-10 18:02:26 +03:00
|
|
|
|
2011-01-14 19:43:55 +03:00
|
|
|
#define LOG_THIS theHDImageCtl->
|
2005-12-10 18:02:26 +03:00
|
|
|
|
2011-01-13 01:34:42 +03:00
|
|
|
bx_hdimage_ctl_c* theHDImageCtl = NULL;
|
|
|
|
|
|
|
|
int libhdimage_LTX_plugin_init(plugin_t *plugin, plugintype_t type, int argc, char *argv[])
|
|
|
|
{
|
2011-12-25 12:52:34 +04:00
|
|
|
if (type == PLUGTYPE_CORE) {
|
|
|
|
theHDImageCtl = new bx_hdimage_ctl_c;
|
|
|
|
bx_devices.pluginHDImageCtl = theHDImageCtl;
|
|
|
|
return 0; // Success
|
|
|
|
} else {
|
|
|
|
return -1;
|
|
|
|
}
|
2011-01-13 01:34:42 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
void libhdimage_LTX_plugin_fini(void)
|
|
|
|
{
|
|
|
|
delete theHDImageCtl;
|
|
|
|
}
|
|
|
|
|
2011-01-14 19:43:55 +03:00
|
|
|
bx_hdimage_ctl_c::bx_hdimage_ctl_c()
|
|
|
|
{
|
2011-12-30 15:13:37 +04:00
|
|
|
put("hdimage", "IMG");
|
2011-01-14 19:43:55 +03:00
|
|
|
}
|
|
|
|
|
2011-01-13 01:34:42 +03:00
|
|
|
device_image_t* bx_hdimage_ctl_c::init_image(Bit8u image_mode, Bit64u disk_size, const char *journal)
|
|
|
|
{
|
|
|
|
device_image_t *hdimage = NULL;
|
|
|
|
|
|
|
|
// instantiate the right class
|
|
|
|
switch (image_mode) {
|
|
|
|
|
|
|
|
case BX_HDIMAGE_MODE_FLAT:
|
|
|
|
hdimage = new default_image_t();
|
|
|
|
break;
|
|
|
|
|
|
|
|
case BX_HDIMAGE_MODE_CONCAT:
|
|
|
|
hdimage = new concat_image_t();
|
|
|
|
break;
|
|
|
|
|
|
|
|
#if EXTERNAL_DISK_SIMULATOR
|
|
|
|
case BX_HDIMAGE_MODE_EXTDISKSIM:
|
|
|
|
hdimage = new EXTERNAL_DISK_SIMULATOR_CLASS();
|
|
|
|
break;
|
|
|
|
#endif //EXTERNAL_DISK_SIMULATOR
|
|
|
|
|
|
|
|
#if DLL_HD_SUPPORT
|
|
|
|
case BX_HDIMAGE_MODE_DLL_HD:
|
|
|
|
hdimage = new dll_image_t();
|
|
|
|
break;
|
|
|
|
#endif //DLL_HD_SUPPORT
|
|
|
|
|
|
|
|
case BX_HDIMAGE_MODE_SPARSE:
|
|
|
|
hdimage = new sparse_image_t();
|
|
|
|
break;
|
|
|
|
|
|
|
|
case BX_HDIMAGE_MODE_VMWARE3:
|
|
|
|
hdimage = new vmware3_image_t();
|
|
|
|
break;
|
|
|
|
|
|
|
|
case BX_HDIMAGE_MODE_VMWARE4:
|
|
|
|
hdimage = new vmware4_image_t();
|
|
|
|
break;
|
|
|
|
|
|
|
|
case BX_HDIMAGE_MODE_UNDOABLE:
|
|
|
|
hdimage = new undoable_image_t(journal);
|
|
|
|
break;
|
|
|
|
|
|
|
|
case BX_HDIMAGE_MODE_GROWING:
|
|
|
|
hdimage = new growing_image_t();
|
|
|
|
break;
|
|
|
|
|
|
|
|
case BX_HDIMAGE_MODE_VOLATILE:
|
|
|
|
hdimage = new volatile_image_t(journal);
|
|
|
|
break;
|
|
|
|
|
|
|
|
case BX_HDIMAGE_MODE_VVFAT:
|
|
|
|
hdimage = new vvfat_image_t(disk_size, journal);
|
|
|
|
break;
|
|
|
|
|
2012-08-05 13:33:33 +04:00
|
|
|
case BX_HDIMAGE_MODE_VPC:
|
|
|
|
hdimage = new vpc_image_t();
|
|
|
|
break;
|
|
|
|
|
2011-01-13 01:34:42 +03:00
|
|
|
default:
|
|
|
|
BX_PANIC(("unsupported HD mode : '%s'", hdimage_mode_names[image_mode]));
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
return hdimage;
|
|
|
|
}
|
|
|
|
|
2011-07-17 21:23:12 +04:00
|
|
|
#ifdef LOWLEVEL_CDROM
|
|
|
|
LOWLEVEL_CDROM* bx_hdimage_ctl_c::init_cdrom(const char *dev)
|
|
|
|
{
|
|
|
|
return new LOWLEVEL_CDROM(dev);
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
2012-08-05 13:33:33 +04:00
|
|
|
// helper functions
|
|
|
|
int bx_read_image(int fd, Bit64s offset, void *buf, int count)
|
|
|
|
{
|
|
|
|
if (lseek(fd, offset, SEEK_SET) == -1) {
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
return read(fd, buf, count);
|
|
|
|
}
|
|
|
|
|
|
|
|
int bx_write_image(int fd, Bit64s offset, void *buf, int count)
|
|
|
|
{
|
|
|
|
if (lseek(fd, offset, SEEK_SET) == -1) {
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
return write(fd, buf, count);
|
|
|
|
}
|
|
|
|
|
2012-09-16 23:51:30 +04:00
|
|
|
Bit64s hdimage_save_handler(void *class_ptr, bx_param_c *param)
|
|
|
|
{
|
|
|
|
char imgname[BX_PATHNAME_LEN];
|
|
|
|
char path[BX_PATHNAME_LEN];
|
|
|
|
|
|
|
|
param->get_param_path(imgname, BX_PATHNAME_LEN);
|
|
|
|
if (!strncmp(imgname, "bochs.", 6)) {
|
|
|
|
strcpy(imgname, imgname+6);
|
|
|
|
}
|
|
|
|
sprintf(path, "%s/%s", SIM->get_param_string(BXPN_RESTORE_PATH)->getptr(), imgname);
|
|
|
|
return ((device_image_t*)class_ptr)->save_state(path);
|
|
|
|
}
|
|
|
|
|
2012-09-20 01:05:18 +04:00
|
|
|
void hdimage_restore_handler(void *class_ptr, bx_param_c *param, Bit64s value)
|
|
|
|
{
|
|
|
|
char imgname[BX_PATHNAME_LEN];
|
|
|
|
char path[BX_PATHNAME_LEN];
|
|
|
|
|
|
|
|
if (value != 0) {
|
|
|
|
param->get_param_path(imgname, BX_PATHNAME_LEN);
|
|
|
|
if (!strncmp(imgname, "bochs.", 6)) {
|
|
|
|
strcpy(imgname, imgname+6);
|
|
|
|
}
|
|
|
|
sprintf(path, "%s/%s", SIM->get_param_string(BXPN_RESTORE_PATH)->getptr(), imgname);
|
|
|
|
((device_image_t*)class_ptr)->restore_state(path);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2012-09-17 23:30:40 +04:00
|
|
|
bx_bool hdimage_backup_file(int fd, const char *backup_fname)
|
|
|
|
{
|
|
|
|
char *buf;
|
|
|
|
off_t offset;
|
|
|
|
int nread, size;
|
|
|
|
bx_bool ret = 1;
|
|
|
|
|
|
|
|
int backup_fd = ::open(backup_fname, O_RDWR | O_CREAT | O_TRUNC
|
|
|
|
#ifdef O_BINARY
|
|
|
|
| O_BINARY
|
|
|
|
#endif
|
|
|
|
, S_IWUSR | S_IRUSR | S_IRGRP | S_IWGRP);
|
|
|
|
if (backup_fd >= 0) {
|
|
|
|
offset = 0;
|
|
|
|
size = 0x20000;
|
|
|
|
buf = (char*)malloc(size);
|
|
|
|
if (buf == NULL) {
|
|
|
|
::close(backup_fd);
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
while ((nread = bx_read_image(fd, offset, buf, size)) > 0) {
|
|
|
|
if (bx_write_image(backup_fd, offset, buf, nread) < 0) {
|
|
|
|
ret = 0;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
if (nread < size) {
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
offset += size;
|
|
|
|
};
|
|
|
|
if (nread < 0) {
|
|
|
|
ret = 0;
|
|
|
|
}
|
|
|
|
free(buf);
|
|
|
|
::close(backup_fd);
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2012-09-22 14:04:28 +04:00
|
|
|
bx_bool hdimage_copy_file(const char *src, const char *dst)
|
|
|
|
{
|
|
|
|
#ifdef WIN32
|
|
|
|
return (bx_bool)CopyFile(src, dst, FALSE);
|
|
|
|
#else
|
|
|
|
int fd1, fd2;
|
|
|
|
char *buf;
|
|
|
|
off_t offset;
|
|
|
|
int nread, size;
|
|
|
|
bx_bool ret = 1;
|
|
|
|
|
|
|
|
fd1 = ::open(src, O_RDONLY
|
|
|
|
#ifdef O_BINARY
|
|
|
|
| O_BINARY
|
|
|
|
#endif
|
|
|
|
);
|
|
|
|
if (fd1 < 0) return 0;
|
|
|
|
fd2 = ::open(dst, O_RDWR | O_CREAT | O_TRUNC
|
|
|
|
#ifdef O_BINARY
|
|
|
|
| O_BINARY
|
|
|
|
#endif
|
|
|
|
, S_IWUSR | S_IRUSR | S_IRGRP | S_IWGRP);
|
|
|
|
if (fd2 < 0) return 0;
|
|
|
|
offset = 0;
|
|
|
|
size = 0x20000;
|
|
|
|
buf = (char*)malloc(size);
|
|
|
|
if (buf == NULL) {
|
|
|
|
::close(fd1);
|
|
|
|
::close(fd2);
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
while ((nread = bx_read_image(fd1, offset, buf, size)) > 0) {
|
|
|
|
if (bx_write_image(fd2, offset, buf, nread) < 0) {
|
|
|
|
ret = 0;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
if (nread < size) {
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
offset += size;
|
|
|
|
};
|
|
|
|
if (nread < 0) {
|
|
|
|
ret = 0;
|
|
|
|
}
|
|
|
|
free(buf);
|
|
|
|
::close(fd1);
|
|
|
|
::close(fd2);
|
|
|
|
return ret;
|
|
|
|
#endif
|
|
|
|
}
|
|
|
|
|
2006-06-16 11:29:33 +04:00
|
|
|
/*** base class device_image_t ***/
|
|
|
|
|
|
|
|
device_image_t::device_image_t()
|
|
|
|
{
|
|
|
|
hd_size = 0;
|
|
|
|
}
|
|
|
|
|
2010-12-22 00:47:41 +03:00
|
|
|
Bit32u device_image_t::get_capabilities()
|
|
|
|
{
|
2011-01-21 19:00:38 +03:00
|
|
|
return (cylinders == 0) ? HDIMAGE_AUTO_GEOMETRY : 0;
|
2010-12-22 00:47:41 +03:00
|
|
|
}
|
|
|
|
|
2012-09-16 23:51:30 +04:00
|
|
|
void device_image_t::register_state(bx_list_c *parent)
|
|
|
|
{
|
|
|
|
bx_param_bool_c *image = new bx_param_bool_c(parent, "image", NULL, NULL, 0);
|
|
|
|
// TODO: restore image
|
2012-09-20 01:05:18 +04:00
|
|
|
image->set_sr_handlers(this, hdimage_save_handler, hdimage_restore_handler);
|
2012-09-16 23:51:30 +04:00
|
|
|
}
|
|
|
|
|
2005-12-10 18:02:26 +03:00
|
|
|
/*** default_image_t function definitions ***/
|
|
|
|
|
2006-06-09 00:32:00 +04:00
|
|
|
int default_image_t::open(const char* pathname)
|
2005-12-10 18:02:26 +03:00
|
|
|
{
|
|
|
|
return open(pathname, O_RDWR);
|
|
|
|
}
|
|
|
|
|
2006-06-09 00:32:00 +04:00
|
|
|
int default_image_t::open(const char* pathname, int flags)
|
2005-12-10 18:02:26 +03:00
|
|
|
{
|
2007-08-10 21:34:01 +04:00
|
|
|
#ifdef WIN32
|
2008-01-27 01:24:03 +03:00
|
|
|
HANDLE hFile = CreateFile(pathname, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_FLAG_RANDOM_ACCESS, NULL);
|
2007-08-10 21:34:01 +04:00
|
|
|
if (hFile != INVALID_HANDLE_VALUE) {
|
|
|
|
ULARGE_INTEGER FileSize;
|
|
|
|
FileSize.LowPart = GetFileSize(hFile, &FileSize.HighPart);
|
2012-07-21 16:00:46 +04:00
|
|
|
GetFileTime(hFile, NULL, NULL, &mtime);
|
2007-08-10 21:34:01 +04:00
|
|
|
CloseHandle(hFile);
|
|
|
|
if ((FileSize.LowPart != INVALID_FILE_SIZE) || (GetLastError() == NO_ERROR)) {
|
|
|
|
hd_size = FileSize.QuadPart;
|
|
|
|
} else {
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
2005-12-10 18:02:26 +03:00
|
|
|
fd = ::open(pathname, flags
|
|
|
|
#ifdef O_BINARY
|
|
|
|
| O_BINARY
|
|
|
|
#endif
|
|
|
|
);
|
|
|
|
|
|
|
|
if (fd < 0) {
|
|
|
|
return fd;
|
|
|
|
}
|
|
|
|
|
2007-08-10 21:34:01 +04:00
|
|
|
#ifndef WIN32
|
2005-12-10 18:02:26 +03:00
|
|
|
/* look at size of image file to calculate disk geometry */
|
|
|
|
struct stat stat_buf;
|
2011-11-26 19:09:00 +04:00
|
|
|
if (fstat(fd, &stat_buf)) {
|
2005-12-10 18:02:26 +03:00
|
|
|
BX_PANIC(("fstat() returns error!"));
|
|
|
|
}
|
2011-11-26 19:09:00 +04:00
|
|
|
#ifdef linux
|
|
|
|
if (stat_buf.st_rdev) { // Is this a special device file (e.g. /dev/sde) ?
|
|
|
|
ioctl(fd, BLKGETSIZE64, &hd_size); // yes it's!
|
|
|
|
}
|
|
|
|
else
|
2007-08-10 21:34:01 +04:00
|
|
|
#endif
|
2011-11-26 19:09:00 +04:00
|
|
|
{
|
|
|
|
hd_size = (Bit64u)stat_buf.st_size; // standard unix procedure to get size of regular files
|
2005-12-10 18:02:26 +03:00
|
|
|
}
|
2012-07-21 16:00:46 +04:00
|
|
|
mtime = stat_buf.st_mtime;
|
2011-11-26 19:09:00 +04:00
|
|
|
#endif
|
|
|
|
BX_INFO(("hd_size: "FMT_LL"u", hd_size));
|
|
|
|
if (hd_size <= 0) BX_PANIC(("size of disk image not detected / invalid"));
|
|
|
|
if ((hd_size % 512) != 0) BX_PANIC(("size of disk image must be multiple of 512 bytes"));
|
2012-09-22 14:04:28 +04:00
|
|
|
imgpath = pathname;
|
2005-12-10 18:02:26 +03:00
|
|
|
return fd;
|
|
|
|
}
|
|
|
|
|
2006-06-09 00:32:00 +04:00
|
|
|
void default_image_t::close()
|
2005-12-10 18:02:26 +03:00
|
|
|
{
|
|
|
|
if (fd > -1) {
|
|
|
|
::close(fd);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2006-11-18 14:51:07 +03:00
|
|
|
Bit64s default_image_t::lseek(Bit64s offset, int whence)
|
2005-12-10 18:02:26 +03:00
|
|
|
{
|
2006-11-18 14:51:07 +03:00
|
|
|
return (Bit64s)::lseek(fd, (off_t)offset, whence);
|
2005-12-10 18:02:26 +03:00
|
|
|
}
|
|
|
|
|
2006-06-09 00:32:00 +04:00
|
|
|
ssize_t default_image_t::read(void* buf, size_t count)
|
2005-12-10 18:02:26 +03:00
|
|
|
{
|
|
|
|
return ::read(fd, (char*) buf, count);
|
|
|
|
}
|
|
|
|
|
2006-06-09 00:32:00 +04:00
|
|
|
ssize_t default_image_t::write(const void* buf, size_t count)
|
2005-12-10 18:02:26 +03:00
|
|
|
{
|
|
|
|
return ::write(fd, (char*) buf, count);
|
|
|
|
}
|
|
|
|
|
2012-07-21 16:00:46 +04:00
|
|
|
Bit32u default_image_t::get_timestamp()
|
|
|
|
{
|
|
|
|
return (fat_datetime(mtime, 1) | (fat_datetime(mtime, 0) << 16));
|
|
|
|
}
|
|
|
|
|
2012-09-16 23:51:30 +04:00
|
|
|
bx_bool default_image_t::save_state(const char *backup_fname)
|
|
|
|
{
|
2012-09-17 23:30:40 +04:00
|
|
|
return hdimage_backup_file(fd, backup_fname);
|
2012-09-16 23:51:30 +04:00
|
|
|
}
|
|
|
|
|
2012-09-22 14:04:28 +04:00
|
|
|
void default_image_t::restore_state(const char *backup_fname)
|
|
|
|
{
|
|
|
|
close();
|
|
|
|
if (hdimage_copy_file(backup_fname, imgpath)) {
|
|
|
|
BX_PANIC(("Failed to restore image '%s'", imgpath));
|
|
|
|
}
|
|
|
|
if (open(imgpath) < 0) {
|
|
|
|
BX_PANIC(("Failed to oprn restored image '%s'", imgpath));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2012-09-16 23:51:30 +04:00
|
|
|
// helper function for concat and sparse mode images
|
|
|
|
|
2006-06-05 01:49:17 +04:00
|
|
|
char increment_string(char *str, int diff)
|
2005-12-10 18:02:26 +03:00
|
|
|
{
|
|
|
|
// find the last character of the string, and increment it.
|
|
|
|
char *p = str;
|
|
|
|
while (*p != 0) p++;
|
2006-06-05 01:49:17 +04:00
|
|
|
BX_ASSERT(p>str); // choke on zero length strings
|
2005-12-10 18:02:26 +03:00
|
|
|
p--; // point to last character of the string
|
|
|
|
(*p) += diff; // increment to next/previous ascii code.
|
|
|
|
BX_DEBUG(("increment string returning '%s'", str));
|
|
|
|
return (*p);
|
|
|
|
}
|
|
|
|
|
|
|
|
/*** concat_image_t function definitions ***/
|
|
|
|
|
2006-06-05 01:49:17 +04:00
|
|
|
concat_image_t::concat_image_t()
|
2005-12-10 18:02:26 +03:00
|
|
|
{
|
|
|
|
fd = -1;
|
|
|
|
}
|
|
|
|
|
2006-06-05 01:49:17 +04:00
|
|
|
void concat_image_t::increment_string(char *str)
|
2005-12-10 18:02:26 +03:00
|
|
|
{
|
|
|
|
::increment_string(str, +1);
|
|
|
|
}
|
|
|
|
|
2006-06-05 01:49:17 +04:00
|
|
|
int concat_image_t::open(const char* pathname0)
|
2005-12-10 18:02:26 +03:00
|
|
|
{
|
2006-06-09 00:32:00 +04:00
|
|
|
char *pathname = strdup(pathname0);
|
2005-12-10 18:02:26 +03:00
|
|
|
BX_DEBUG(("concat_image_t.open"));
|
2006-06-09 00:32:00 +04:00
|
|
|
Bit64s start_offset = 0;
|
2005-12-10 18:02:26 +03:00
|
|
|
for (int i=0; i<BX_CONCAT_MAX_IMAGES; i++) {
|
|
|
|
fd_table[i] = ::open(pathname, O_RDWR
|
|
|
|
#ifdef O_BINARY
|
2012-09-18 23:00:25 +04:00
|
|
|
| O_BINARY
|
2005-12-10 18:02:26 +03:00
|
|
|
#endif
|
2012-09-18 23:00:25 +04:00
|
|
|
);
|
2005-12-10 18:02:26 +03:00
|
|
|
if (fd_table[i] < 0) {
|
|
|
|
// open failed.
|
|
|
|
// if no FD was opened successfully, return -1 (fail).
|
|
|
|
if (i==0) return -1;
|
2008-01-27 01:24:03 +03:00
|
|
|
// otherwise, it only means that all images in the series have
|
2005-12-10 18:02:26 +03:00
|
|
|
// been opened. Record the number of fds opened successfully.
|
2008-01-27 01:24:03 +03:00
|
|
|
maxfd = i;
|
2005-12-10 18:02:26 +03:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
BX_DEBUG(("concat_image: open image %s, fd[%d] = %d", pathname, i, fd_table[i]));
|
|
|
|
/* look at size of image file to calculate disk geometry */
|
|
|
|
struct stat stat_buf;
|
|
|
|
int ret = fstat(fd_table[i], &stat_buf);
|
|
|
|
if (ret) {
|
|
|
|
BX_PANIC(("fstat() returns error!"));
|
|
|
|
}
|
|
|
|
#ifdef S_ISBLK
|
|
|
|
if (S_ISBLK(stat_buf.st_mode)) {
|
2006-06-05 01:49:17 +04:00
|
|
|
BX_PANIC(("block devices should REALLY NOT be used as concat images"));
|
2005-12-10 18:02:26 +03:00
|
|
|
}
|
|
|
|
#endif
|
|
|
|
if ((stat_buf.st_size % 512) != 0) {
|
|
|
|
BX_PANIC(("size of disk image must be multiple of 512 bytes"));
|
|
|
|
}
|
|
|
|
length_table[i] = stat_buf.st_size;
|
|
|
|
start_offset_table[i] = start_offset;
|
|
|
|
start_offset += stat_buf.st_size;
|
2006-06-05 01:49:17 +04:00
|
|
|
increment_string(pathname);
|
2005-12-10 18:02:26 +03:00
|
|
|
}
|
|
|
|
// start up with first image selected
|
|
|
|
index = 0;
|
|
|
|
fd = fd_table[0];
|
|
|
|
thismin = 0;
|
|
|
|
thismax = length_table[0]-1;
|
|
|
|
seek_was_last_op = 0;
|
2006-06-05 01:49:17 +04:00
|
|
|
hd_size = start_offset;
|
2005-12-10 18:02:26 +03:00
|
|
|
return 0; // success.
|
|
|
|
}
|
|
|
|
|
2006-06-05 01:49:17 +04:00
|
|
|
void concat_image_t::close()
|
2005-12-10 18:02:26 +03:00
|
|
|
{
|
|
|
|
BX_DEBUG(("concat_image_t.close"));
|
2012-09-18 23:00:25 +04:00
|
|
|
for (int index = 0; index < maxfd; index++) {
|
|
|
|
if (fd_table[index] > -1) {
|
|
|
|
::close(fd_table[index]);
|
|
|
|
}
|
2005-12-10 18:02:26 +03:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2006-06-09 00:32:00 +04:00
|
|
|
Bit64s concat_image_t::lseek(Bit64s offset, int whence)
|
2005-12-10 18:02:26 +03:00
|
|
|
{
|
2008-01-27 01:24:03 +03:00
|
|
|
if ((offset % 512) != 0)
|
2008-02-16 01:05:43 +03:00
|
|
|
BX_PANIC(("lseek HD with offset not multiple of 512"));
|
2005-12-10 18:02:26 +03:00
|
|
|
BX_DEBUG(("concat_image_t.lseek(%d)", whence));
|
|
|
|
// is this offset in this disk image?
|
|
|
|
if (offset < thismin) {
|
|
|
|
// no, look at previous images
|
|
|
|
for (int i=index-1; i>=0; i--) {
|
|
|
|
if (offset >= start_offset_table[i]) {
|
2012-09-18 23:00:25 +04:00
|
|
|
index = i;
|
|
|
|
fd = fd_table[i];
|
|
|
|
thismin = start_offset_table[i];
|
|
|
|
thismax = thismin + length_table[i] - 1;
|
|
|
|
BX_DEBUG(("concat_image_t.lseek to earlier image, index=%d", index));
|
|
|
|
break;
|
2005-12-10 18:02:26 +03:00
|
|
|
}
|
|
|
|
}
|
|
|
|
} else if (offset > thismax) {
|
|
|
|
// no, look at later images
|
|
|
|
for (int i=index+1; i<maxfd; i++) {
|
|
|
|
if (offset < start_offset_table[i] + length_table[i]) {
|
2012-09-18 23:00:25 +04:00
|
|
|
index = i;
|
|
|
|
fd = fd_table[i];
|
|
|
|
thismin = start_offset_table[i];
|
|
|
|
thismax = thismin + length_table[i] - 1;
|
|
|
|
BX_DEBUG(("concat_image_t.lseek to earlier image, index=%d", index));
|
|
|
|
break;
|
2005-12-10 18:02:26 +03:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
// now offset should be within the current image.
|
|
|
|
offset -= start_offset_table[index];
|
|
|
|
if (offset < 0 || offset >= length_table[index]) {
|
|
|
|
BX_PANIC(("concat_image_t.lseek to byte %ld failed", (long)offset));
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
seek_was_last_op = 1;
|
2006-11-18 14:51:07 +03:00
|
|
|
return (Bit64s)::lseek(fd, (off_t)offset, whence);
|
2005-12-10 18:02:26 +03:00
|
|
|
}
|
|
|
|
|
2006-06-09 00:32:00 +04:00
|
|
|
ssize_t concat_image_t::read(void* buf, size_t count)
|
2005-12-10 18:02:26 +03:00
|
|
|
{
|
2009-04-25 12:06:32 +04:00
|
|
|
BX_DEBUG(("concat_image_t.read %ld bytes", (long)count));
|
2005-12-10 18:02:26 +03:00
|
|
|
// notice if anyone does sequential read or write without seek in between.
|
|
|
|
// This can be supported pretty easily, but needs additional checks for
|
|
|
|
// end of a partial image.
|
|
|
|
if (!seek_was_last_op)
|
2008-02-16 01:05:43 +03:00
|
|
|
BX_PANIC(("no seek before read"));
|
2005-12-10 18:02:26 +03:00
|
|
|
return ::read(fd, (char*) buf, count);
|
|
|
|
}
|
|
|
|
|
2006-06-09 00:32:00 +04:00
|
|
|
ssize_t concat_image_t::write(const void* buf, size_t count)
|
2005-12-10 18:02:26 +03:00
|
|
|
{
|
|
|
|
BX_DEBUG(("concat_image_t.write %ld bytes", (long)count));
|
|
|
|
// notice if anyone does sequential read or write without seek in between.
|
|
|
|
// This can be supported pretty easily, but needs additional checks for
|
|
|
|
// end of a partial image.
|
|
|
|
if (!seek_was_last_op)
|
2008-02-16 01:05:43 +03:00
|
|
|
BX_PANIC(("no seek before write"));
|
2005-12-10 18:02:26 +03:00
|
|
|
return ::write(fd, (char*) buf, count);
|
|
|
|
}
|
|
|
|
|
2012-09-18 23:00:25 +04:00
|
|
|
bx_bool concat_image_t::save_state(const char *backup_fname)
|
|
|
|
{
|
|
|
|
bx_bool ret = 1;
|
|
|
|
char tempfn[BX_PATHNAME_LEN];
|
|
|
|
|
|
|
|
for (int index = 0; index < maxfd; index++) {
|
|
|
|
sprintf(tempfn, "%s%d", backup_fname, index);
|
|
|
|
ret &= hdimage_backup_file(fd_table[index], tempfn);
|
|
|
|
if (ret == 0) break;
|
|
|
|
}
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
2005-12-10 18:02:26 +03:00
|
|
|
/*** sparse_image_t function definitions ***/
|
|
|
|
|
2012-07-24 23:27:22 +04:00
|
|
|
sparse_image_t::sparse_image_t()
|
2005-12-10 18:02:26 +03:00
|
|
|
{
|
|
|
|
fd = -1;
|
|
|
|
pathname = NULL;
|
|
|
|
#ifdef _POSIX_MAPPED_FILES
|
2007-03-10 15:53:54 +03:00
|
|
|
mmap_header = NULL;
|
2005-12-10 18:02:26 +03:00
|
|
|
#endif
|
2007-03-10 15:53:54 +03:00
|
|
|
pagetable = NULL;
|
2011-09-08 01:34:15 +04:00
|
|
|
parent_image = NULL;
|
2005-12-10 18:02:26 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
void showpagetable(Bit32u * pagetable, size_t numpages)
|
|
|
|
{
|
|
|
|
printf("Non null pages: ");
|
|
|
|
for (int i = 0; i < numpages; i++)
|
|
|
|
{
|
|
|
|
if (pagetable[i] != 0xffffffff)
|
|
|
|
{
|
|
|
|
printf("%d ", i);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
printf("\n");
|
|
|
|
}
|
|
|
|
*/
|
|
|
|
|
|
|
|
void sparse_image_t::read_header()
|
|
|
|
{
|
|
|
|
BX_ASSERT(sizeof(header) == SPARSE_HEADER_SIZE);
|
|
|
|
|
|
|
|
int ret = ::read(fd, &header, sizeof(header));
|
|
|
|
|
|
|
|
if (-1 == ret)
|
|
|
|
{
|
|
|
|
panic(strerror(errno));
|
|
|
|
}
|
|
|
|
|
|
|
|
if (sizeof(header) != ret)
|
|
|
|
{
|
|
|
|
panic("could not read entire header");
|
|
|
|
}
|
|
|
|
|
|
|
|
if (dtoh32(header.magic) != SPARSE_HEADER_MAGIC)
|
|
|
|
{
|
|
|
|
panic("failed header magic check");
|
|
|
|
}
|
|
|
|
|
2006-06-16 11:29:33 +04:00
|
|
|
if ((dtoh32(header.version) != SPARSE_HEADER_VERSION) &&
|
|
|
|
(dtoh32(header.version) != SPARSE_HEADER_V1))
|
2005-12-10 18:02:26 +03:00
|
|
|
{
|
|
|
|
panic("unknown version in header");
|
|
|
|
}
|
|
|
|
|
|
|
|
pagesize = dtoh32(header.pagesize);
|
|
|
|
Bit32u numpages = dtoh32(header.numpages);
|
|
|
|
|
|
|
|
total_size = pagesize;
|
|
|
|
total_size *= numpages;
|
|
|
|
|
|
|
|
pagesize_shift = 0;
|
|
|
|
while ((pagesize >> pagesize_shift) > 1) pagesize_shift++;
|
|
|
|
|
|
|
|
if ((Bit32u)(1 << pagesize_shift) != pagesize)
|
|
|
|
{
|
|
|
|
panic("failed block size header check");
|
|
|
|
}
|
|
|
|
|
|
|
|
pagesize_mask = pagesize - 1;
|
|
|
|
|
|
|
|
size_t preamble_size = (sizeof(Bit32u) * numpages) + sizeof(header);
|
|
|
|
data_start = 0;
|
2007-10-25 03:17:42 +04:00
|
|
|
while ((size_t)data_start < preamble_size) data_start += pagesize;
|
2005-12-10 18:02:26 +03:00
|
|
|
|
|
|
|
bx_bool did_mmap = 0;
|
|
|
|
|
|
|
|
#ifdef _POSIX_MAPPED_FILES
|
|
|
|
// Try to memory map from the beginning of the file (0 is trivially a page multiple)
|
2011-09-11 20:27:56 +04:00
|
|
|
void *mmap_header = mmap(NULL, preamble_size, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);
|
2005-12-10 18:02:26 +03:00
|
|
|
if (mmap_header == MAP_FAILED)
|
|
|
|
{
|
|
|
|
BX_INFO(("failed to mmap sparse disk file - using conventional file access"));
|
|
|
|
mmap_header = NULL;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
mmap_length = preamble_size;
|
|
|
|
did_mmap = 1;
|
|
|
|
pagetable = ((Bit32u *) (((Bit8u *) mmap_header) + sizeof(header)));
|
|
|
|
system_pagesize_mask = getpagesize() - 1;
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
|
|
|
if (!did_mmap)
|
|
|
|
{
|
|
|
|
pagetable = new Bit32u[numpages];
|
|
|
|
|
|
|
|
if (pagetable == NULL)
|
|
|
|
{
|
|
|
|
panic("could not allocate memory for sparse disk block table");
|
|
|
|
}
|
|
|
|
|
|
|
|
ret = ::read(fd, pagetable, sizeof(Bit32u) * numpages);
|
|
|
|
|
|
|
|
if (-1 == ret)
|
|
|
|
{
|
|
|
|
panic(strerror(errno));
|
|
|
|
}
|
|
|
|
|
|
|
|
if ((int)(sizeof(Bit32u) * numpages) != ret)
|
|
|
|
{
|
|
|
|
panic("could not read entire block table");
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2012-07-24 23:27:22 +04:00
|
|
|
int sparse_image_t::open(const char* pathname0)
|
2005-12-10 18:02:26 +03:00
|
|
|
{
|
2008-01-27 01:24:03 +03:00
|
|
|
pathname = strdup(pathname0);
|
|
|
|
BX_DEBUG(("sparse_image_t.open"));
|
2005-12-10 18:02:26 +03:00
|
|
|
|
2008-01-27 01:24:03 +03:00
|
|
|
fd = ::open(pathname, O_RDWR
|
2005-12-10 18:02:26 +03:00
|
|
|
#ifdef O_BINARY
|
|
|
|
| O_BINARY
|
|
|
|
#endif
|
|
|
|
);
|
|
|
|
|
2008-01-27 01:24:03 +03:00
|
|
|
if (fd < 0)
|
|
|
|
{
|
|
|
|
return -1; // open failed
|
|
|
|
}
|
|
|
|
BX_DEBUG(("sparse_image: open image %s", pathname));
|
2005-12-10 18:02:26 +03:00
|
|
|
|
2008-01-27 01:24:03 +03:00
|
|
|
read_header();
|
2005-12-10 18:02:26 +03:00
|
|
|
|
2008-01-27 01:24:03 +03:00
|
|
|
struct stat stat_buf;
|
|
|
|
if (fstat(fd, &stat_buf) != 0) panic(("fstat() returns error!"));
|
2005-12-10 18:02:26 +03:00
|
|
|
|
2008-01-27 01:24:03 +03:00
|
|
|
underlying_filesize = stat_buf.st_size;
|
2005-12-10 18:02:26 +03:00
|
|
|
|
2008-01-27 01:24:03 +03:00
|
|
|
if ((underlying_filesize % pagesize) != 0)
|
|
|
|
panic("size of sparse disk image is not multiple of page size");
|
2005-12-10 18:02:26 +03:00
|
|
|
|
2008-01-27 01:24:03 +03:00
|
|
|
underlying_current_filepos = 0;
|
|
|
|
if (-1 == ::lseek(fd, 0, SEEK_SET))
|
|
|
|
panic("error while seeking to start of file");
|
2005-12-10 18:02:26 +03:00
|
|
|
|
2008-01-27 01:24:03 +03:00
|
|
|
lseek(0, SEEK_SET);
|
2005-12-10 18:02:26 +03:00
|
|
|
|
2008-01-27 01:24:03 +03:00
|
|
|
//showpagetable(pagetable, header.numpages);
|
2005-12-10 18:02:26 +03:00
|
|
|
|
2008-01-27 01:24:03 +03:00
|
|
|
char * parentpathname = strdup(pathname);
|
|
|
|
char lastchar = ::increment_string(parentpathname, -1);
|
2005-12-10 18:02:26 +03:00
|
|
|
|
2008-01-27 01:24:03 +03:00
|
|
|
if ((lastchar >= '0') && (lastchar <= '9'))
|
|
|
|
{
|
|
|
|
struct stat stat_buf;
|
|
|
|
if (0 == stat(parentpathname, &stat_buf))
|
|
|
|
{
|
|
|
|
parent_image = new sparse_image_t();
|
|
|
|
int ret = parent_image->open(parentpathname);
|
|
|
|
if (ret != 0) return ret;
|
|
|
|
if ( (parent_image->pagesize != pagesize)
|
|
|
|
|| (parent_image->total_size != total_size))
|
|
|
|
{
|
|
|
|
panic("child drive image does not have same page count/page size configuration");
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2005-12-10 18:02:26 +03:00
|
|
|
|
2008-01-27 01:24:03 +03:00
|
|
|
if (parentpathname != NULL) free(parentpathname);
|
2005-12-10 18:02:26 +03:00
|
|
|
|
2008-01-27 01:24:03 +03:00
|
|
|
if (dtoh32(header.version) == SPARSE_HEADER_VERSION) {
|
|
|
|
hd_size = dtoh64(header.disk);
|
2012-07-24 23:27:22 +04:00
|
|
|
BX_INFO(("sparse: pagesize = 0x%x, data_start = 0x" FMT_LL "x", pagesize, data_start));
|
2008-01-27 01:24:03 +03:00
|
|
|
}
|
2007-10-25 03:17:42 +04:00
|
|
|
|
2008-01-27 01:24:03 +03:00
|
|
|
return 0; // success
|
2005-12-10 18:02:26 +03:00
|
|
|
}
|
|
|
|
|
2006-06-16 12:56:13 +04:00
|
|
|
void sparse_image_t::close()
|
2005-12-10 18:02:26 +03:00
|
|
|
{
|
2008-01-27 01:24:03 +03:00
|
|
|
BX_DEBUG(("concat_image_t.close"));
|
|
|
|
if (pathname != NULL)
|
|
|
|
{
|
|
|
|
free(pathname);
|
|
|
|
}
|
2005-12-10 18:02:26 +03:00
|
|
|
#ifdef _POSIX_MAPPED_FILES
|
2008-01-27 01:24:03 +03:00
|
|
|
if (mmap_header != NULL)
|
|
|
|
{
|
|
|
|
int ret = munmap(mmap_header, mmap_length);
|
|
|
|
if (ret != 0)
|
|
|
|
BX_INFO(("failed to un-memory map sparse disk file"));
|
|
|
|
}
|
|
|
|
pagetable = NULL; // We didn't malloc it
|
2005-12-10 18:02:26 +03:00
|
|
|
#endif
|
2008-01-27 01:24:03 +03:00
|
|
|
if (fd > -1) {
|
2005-12-10 18:02:26 +03:00
|
|
|
::close(fd);
|
2008-01-27 01:24:03 +03:00
|
|
|
}
|
|
|
|
if (pagetable != NULL)
|
|
|
|
{
|
|
|
|
delete [] pagetable;
|
|
|
|
}
|
|
|
|
if (parent_image != NULL)
|
|
|
|
{
|
|
|
|
delete parent_image;
|
|
|
|
}
|
2005-12-10 18:02:26 +03:00
|
|
|
}
|
|
|
|
|
2006-11-18 14:51:07 +03:00
|
|
|
Bit64s sparse_image_t::lseek(Bit64s offset, int whence)
|
2005-12-10 18:02:26 +03:00
|
|
|
{
|
2008-01-27 01:24:03 +03:00
|
|
|
//showpagetable(pagetable, header.numpages);
|
2005-12-10 18:02:26 +03:00
|
|
|
|
2008-01-27 01:24:03 +03:00
|
|
|
if ((offset % 512) != 0)
|
2008-02-16 01:05:43 +03:00
|
|
|
BX_PANIC(("lseek HD with offset not multiple of 512"));
|
2008-01-27 01:24:03 +03:00
|
|
|
if (whence != SEEK_SET)
|
2008-02-16 01:05:43 +03:00
|
|
|
BX_PANIC(("lseek HD with whence not SEEK_SET"));
|
2005-12-10 18:02:26 +03:00
|
|
|
|
2008-01-27 01:24:03 +03:00
|
|
|
BX_DEBUG(("sparse_image_t.lseek(%d)", whence));
|
2005-12-10 18:02:26 +03:00
|
|
|
|
2008-01-27 01:24:03 +03:00
|
|
|
if (offset > total_size)
|
|
|
|
{
|
|
|
|
BX_PANIC(("sparse_image_t.lseek to byte %ld failed", (long)offset));
|
2005-12-10 18:02:26 +03:00
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
2008-01-27 01:24:03 +03:00
|
|
|
//printf("Seeking to position %ld\n", (long) offset);
|
2005-12-10 18:02:26 +03:00
|
|
|
|
2008-01-27 01:24:03 +03:00
|
|
|
set_virtual_page((Bit32u)(offset >> pagesize_shift));
|
|
|
|
position_page_offset = (Bit32u)(offset & pagesize_mask);
|
2005-12-10 18:02:26 +03:00
|
|
|
|
2008-01-27 01:24:03 +03:00
|
|
|
return 0;
|
2005-12-10 18:02:26 +03:00
|
|
|
}
|
|
|
|
|
2006-11-18 14:51:07 +03:00
|
|
|
inline Bit64s sparse_image_t::get_physical_offset()
|
2005-12-10 18:02:26 +03:00
|
|
|
{
|
2008-01-27 01:24:03 +03:00
|
|
|
Bit64s physical_offset = data_start;
|
|
|
|
physical_offset += ((Bit64s)position_physical_page << pagesize_shift);
|
|
|
|
physical_offset += position_page_offset;
|
|
|
|
return physical_offset;
|
2005-12-10 18:02:26 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
void sparse_image_t::set_virtual_page(Bit32u new_virtual_page)
|
|
|
|
{
|
2008-01-27 01:24:03 +03:00
|
|
|
position_virtual_page = new_virtual_page;
|
|
|
|
position_physical_page = dtoh32(pagetable[position_virtual_page]);
|
2005-12-10 18:02:26 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
ssize_t sparse_image_t::read_page_fragment(Bit32u read_virtual_page, Bit32u read_page_offset, size_t read_size, void * buf)
|
|
|
|
{
|
2008-01-27 01:24:03 +03:00
|
|
|
if (read_virtual_page != position_virtual_page)
|
|
|
|
{
|
|
|
|
set_virtual_page(read_virtual_page);
|
|
|
|
}
|
2005-12-10 18:02:26 +03:00
|
|
|
|
2008-01-27 01:24:03 +03:00
|
|
|
position_page_offset = read_page_offset;
|
2005-12-10 18:02:26 +03:00
|
|
|
|
2008-01-27 01:24:03 +03:00
|
|
|
if (position_physical_page == SPARSE_PAGE_NOT_ALLOCATED)
|
|
|
|
{
|
|
|
|
if (parent_image != NULL)
|
|
|
|
{
|
|
|
|
return parent_image->read_page_fragment(read_virtual_page, read_page_offset, read_size, buf);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
memset(buf, 0, read_size);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
Bit64s physical_offset = get_physical_offset();
|
2005-12-10 18:02:26 +03:00
|
|
|
|
2008-01-27 01:24:03 +03:00
|
|
|
if (physical_offset != underlying_current_filepos)
|
|
|
|
{
|
|
|
|
off_t ret = ::lseek(fd, (off_t)physical_offset, SEEK_SET);
|
|
|
|
// underlying_current_filepos update deferred
|
|
|
|
if (ret == -1)
|
|
|
|
panic(strerror(errno));
|
|
|
|
}
|
2005-12-10 18:02:26 +03:00
|
|
|
|
2008-01-27 01:24:03 +03:00
|
|
|
//printf("Reading %s at position %ld size %d\n", pathname, (long) physical_offset, (long) read_size);
|
|
|
|
ssize_t readret = ::read(fd, buf, read_size);
|
2005-12-10 18:02:26 +03:00
|
|
|
|
2008-01-27 01:24:03 +03:00
|
|
|
if (readret == -1)
|
|
|
|
{
|
|
|
|
panic(strerror(errno));
|
|
|
|
}
|
2005-12-10 18:02:26 +03:00
|
|
|
|
2008-01-27 01:24:03 +03:00
|
|
|
if ((size_t)readret != read_size)
|
|
|
|
{
|
|
|
|
panic("could not read block contents from file");
|
|
|
|
}
|
2005-12-10 18:02:26 +03:00
|
|
|
|
2008-01-27 01:24:03 +03:00
|
|
|
underlying_current_filepos = physical_offset + read_size;
|
|
|
|
}
|
2005-12-10 18:02:26 +03:00
|
|
|
|
2008-01-27 01:24:03 +03:00
|
|
|
return read_size;
|
2005-12-10 18:02:26 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
ssize_t sparse_image_t::read(void* buf, size_t count)
|
|
|
|
{
|
2008-01-27 01:24:03 +03:00
|
|
|
//showpagetable(pagetable, header.numpages);
|
|
|
|
ssize_t total_read = 0;
|
2005-12-10 18:02:26 +03:00
|
|
|
|
2009-04-25 12:06:32 +04:00
|
|
|
BX_DEBUG(("sparse_image_t.read %ld bytes", (long)count));
|
2005-12-10 18:02:26 +03:00
|
|
|
|
2008-01-27 01:24:03 +03:00
|
|
|
while (count != 0)
|
|
|
|
{
|
|
|
|
size_t can_read = pagesize - position_page_offset;
|
|
|
|
if (count < can_read) can_read = count;
|
2005-12-10 18:02:26 +03:00
|
|
|
|
2008-01-27 01:24:03 +03:00
|
|
|
BX_ASSERT (can_read != 0);
|
2005-12-10 18:02:26 +03:00
|
|
|
|
2008-01-27 01:24:03 +03:00
|
|
|
size_t was_read = read_page_fragment(position_virtual_page, position_page_offset, can_read, buf);
|
2012-07-24 23:27:22 +04:00
|
|
|
|
|
|
|
if (was_read != can_read) {
|
|
|
|
BX_PANIC(("could not read from sparse disk"));
|
|
|
|
}
|
2005-12-10 18:02:26 +03:00
|
|
|
|
2008-01-27 01:24:03 +03:00
|
|
|
total_read += can_read;
|
2005-12-10 18:02:26 +03:00
|
|
|
|
2008-01-27 01:24:03 +03:00
|
|
|
position_page_offset += can_read;
|
|
|
|
if (position_page_offset == pagesize)
|
|
|
|
{
|
|
|
|
position_page_offset = 0;
|
|
|
|
set_virtual_page(position_virtual_page + 1);
|
|
|
|
}
|
2005-12-10 18:02:26 +03:00
|
|
|
|
2008-01-27 01:24:03 +03:00
|
|
|
BX_ASSERT(position_page_offset < pagesize);
|
2005-12-10 18:02:26 +03:00
|
|
|
|
2008-01-27 01:24:03 +03:00
|
|
|
buf = (((Bit8u *) buf) + can_read);
|
|
|
|
count -= can_read;
|
|
|
|
}
|
2005-12-10 18:02:26 +03:00
|
|
|
|
2008-01-27 01:24:03 +03:00
|
|
|
return total_read;
|
2005-12-10 18:02:26 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
void sparse_image_t::panic(const char * message)
|
|
|
|
{
|
2008-01-27 01:24:03 +03:00
|
|
|
char buffer[1024];
|
|
|
|
if (message == NULL)
|
|
|
|
{
|
|
|
|
snprintf(buffer, sizeof(buffer), "error with sparse disk image %s", pathname);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
snprintf(buffer, sizeof(buffer), "error with sparse disk image %s - %s", pathname, message);
|
|
|
|
}
|
2010-03-02 10:07:57 +03:00
|
|
|
BX_PANIC(("%s", buffer));
|
2005-12-10 18:02:26 +03:00
|
|
|
}
|
|
|
|
|
2012-07-24 23:27:22 +04:00
|
|
|
ssize_t sparse_image_t::write(const void* buf, size_t count)
|
2005-12-10 18:02:26 +03:00
|
|
|
{
|
2008-01-27 01:24:03 +03:00
|
|
|
//showpagetable(pagetable, header.numpages);
|
2005-12-10 18:02:26 +03:00
|
|
|
|
2008-01-27 01:24:03 +03:00
|
|
|
ssize_t total_written = 0;
|
2005-12-10 18:02:26 +03:00
|
|
|
|
2008-01-27 01:24:03 +03:00
|
|
|
Bit32u update_pagetable_start = position_virtual_page;
|
|
|
|
Bit32u update_pagetable_count = 0;
|
2005-12-10 18:02:26 +03:00
|
|
|
|
2009-04-25 12:06:32 +04:00
|
|
|
BX_DEBUG(("sparse_image_t.write %ld bytes", (long)count));
|
2005-12-10 18:02:26 +03:00
|
|
|
|
2008-01-27 01:24:03 +03:00
|
|
|
while (count != 0)
|
|
|
|
{
|
|
|
|
size_t can_write = pagesize - position_page_offset;
|
|
|
|
if (count < can_write) can_write = count;
|
2005-12-10 18:02:26 +03:00
|
|
|
|
2008-01-27 01:24:03 +03:00
|
|
|
BX_ASSERT (can_write != 0);
|
2005-12-10 18:02:26 +03:00
|
|
|
|
2008-01-27 01:24:03 +03:00
|
|
|
if (position_physical_page == SPARSE_PAGE_NOT_ALLOCATED)
|
|
|
|
{
|
|
|
|
// We just add on another page at the end of the file
|
|
|
|
// Reclamation, compaction etc should currently be done off-line
|
2005-12-10 18:02:26 +03:00
|
|
|
|
2008-01-27 01:24:03 +03:00
|
|
|
Bit64s data_size = underlying_filesize - data_start;
|
|
|
|
BX_ASSERT((data_size % pagesize) == 0);
|
2005-12-10 18:02:26 +03:00
|
|
|
|
2008-01-27 01:24:03 +03:00
|
|
|
Bit32u data_size_pages = (Bit32u)(data_size / pagesize);
|
|
|
|
Bit32u next_data_page = data_size_pages;
|
2005-12-10 18:02:26 +03:00
|
|
|
|
2008-01-27 01:24:03 +03:00
|
|
|
pagetable[position_virtual_page] = htod32(next_data_page);
|
|
|
|
position_physical_page = next_data_page;
|
2005-12-10 18:02:26 +03:00
|
|
|
|
2008-01-27 01:24:03 +03:00
|
|
|
Bit64s page_file_start = data_start + ((Bit64s)position_physical_page << pagesize_shift);
|
2005-12-10 18:02:26 +03:00
|
|
|
|
2008-01-27 01:24:03 +03:00
|
|
|
if (parent_image != NULL)
|
|
|
|
{
|
|
|
|
// If we have a parent, we must merge our portion with the parent
|
|
|
|
void *writebuffer = NULL;
|
2005-12-10 18:02:26 +03:00
|
|
|
|
2008-01-27 01:24:03 +03:00
|
|
|
if (can_write == pagesize)
|
|
|
|
{
|
|
|
|
writebuffer = (void *) buf;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
writebuffer = malloc(pagesize);
|
|
|
|
if (writebuffer == NULL)
|
|
|
|
panic("Cannot allocate sufficient memory for page-merge in write");
|
2005-12-10 18:02:26 +03:00
|
|
|
|
2008-01-27 01:24:03 +03:00
|
|
|
// Read entire page - could optimize, but simple for now
|
|
|
|
parent_image->read_page_fragment(position_virtual_page, 0, pagesize, writebuffer);
|
2005-12-10 18:02:26 +03:00
|
|
|
|
2008-01-27 01:24:03 +03:00
|
|
|
void *dest_start = ((Bit8u *) writebuffer) + position_page_offset;
|
|
|
|
memcpy(dest_start, buf, can_write);
|
|
|
|
}
|
2005-12-10 18:02:26 +03:00
|
|
|
|
2008-01-27 01:24:03 +03:00
|
|
|
int ret = (int)::lseek(fd, page_file_start, SEEK_SET);
|
|
|
|
// underlying_current_filepos update deferred
|
|
|
|
if (ret == -1) panic(strerror(errno));
|
2005-12-10 18:02:26 +03:00
|
|
|
|
2008-01-27 01:24:03 +03:00
|
|
|
ret = ::write(fd, writebuffer, pagesize);
|
|
|
|
if (ret == -1) panic(strerror(errno));
|
2005-12-10 18:02:26 +03:00
|
|
|
|
2008-01-27 01:24:03 +03:00
|
|
|
if (pagesize != (Bit32u)ret) panic("failed to write entire merged page to disk");
|
2005-12-10 18:02:26 +03:00
|
|
|
|
2008-01-27 01:24:03 +03:00
|
|
|
if (can_write != pagesize)
|
|
|
|
{
|
|
|
|
free(writebuffer);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
// We need to write a zero page because read has been returning zeroes
|
|
|
|
// We seek as close to the page end as possible, and then write a little
|
|
|
|
// This produces a sparse file which has blanks
|
|
|
|
// Also very quick, even when pagesize is massive
|
|
|
|
int ret = (int)::lseek(fd, page_file_start + pagesize - 4, SEEK_SET);
|
|
|
|
// underlying_current_filepos update deferred
|
|
|
|
if (ret == -1) panic(strerror(errno));
|
|
|
|
|
|
|
|
Bit32u zero = 0;
|
|
|
|
ret = ::write(fd, &zero, 4);
|
|
|
|
if (ret == -1) panic(strerror(errno));
|
|
|
|
|
|
|
|
if (ret != 4) panic("failed to write entire blank page to disk");
|
|
|
|
}
|
2005-12-10 18:02:26 +03:00
|
|
|
|
2008-01-27 01:24:03 +03:00
|
|
|
update_pagetable_count = (position_virtual_page - update_pagetable_start) + 1;
|
|
|
|
underlying_filesize = underlying_current_filepos = page_file_start + pagesize;
|
|
|
|
}
|
2005-12-10 18:02:26 +03:00
|
|
|
|
2008-01-27 01:24:03 +03:00
|
|
|
BX_ASSERT(position_physical_page != SPARSE_PAGE_NOT_ALLOCATED);
|
2005-12-10 18:02:26 +03:00
|
|
|
|
2008-01-27 01:24:03 +03:00
|
|
|
Bit64s physical_offset = get_physical_offset();
|
2005-12-10 18:02:26 +03:00
|
|
|
|
2008-01-27 01:24:03 +03:00
|
|
|
if (physical_offset != underlying_current_filepos)
|
|
|
|
{
|
|
|
|
off_t ret = ::lseek(fd, (off_t)physical_offset, SEEK_SET);
|
|
|
|
// underlying_current_filepos update deferred
|
|
|
|
if (ret == -1)
|
|
|
|
panic(strerror(errno));
|
|
|
|
}
|
2005-12-10 18:02:26 +03:00
|
|
|
|
2008-01-27 01:24:03 +03:00
|
|
|
//printf("Writing at position %ld size %d\n", (long) physical_offset, can_write);
|
|
|
|
ssize_t writeret = ::write(fd, buf, can_write);
|
2005-12-10 18:02:26 +03:00
|
|
|
|
2008-01-27 01:24:03 +03:00
|
|
|
if (writeret == -1)
|
|
|
|
{
|
|
|
|
panic(strerror(errno));
|
|
|
|
}
|
2005-12-10 18:02:26 +03:00
|
|
|
|
2008-01-27 01:24:03 +03:00
|
|
|
if ((size_t)writeret != can_write)
|
|
|
|
{
|
|
|
|
panic("could not write block contents to file");
|
|
|
|
}
|
2005-12-10 18:02:26 +03:00
|
|
|
|
2008-01-27 01:24:03 +03:00
|
|
|
underlying_current_filepos = physical_offset + can_write;
|
2008-02-06 01:57:43 +03:00
|
|
|
|
2008-01-27 01:24:03 +03:00
|
|
|
total_written += can_write;
|
2005-12-10 18:02:26 +03:00
|
|
|
|
2008-01-27 01:24:03 +03:00
|
|
|
position_page_offset += can_write;
|
|
|
|
if (position_page_offset == pagesize)
|
|
|
|
{
|
|
|
|
position_page_offset = 0;
|
|
|
|
set_virtual_page(position_virtual_page + 1);
|
|
|
|
}
|
2005-12-10 18:02:26 +03:00
|
|
|
|
2008-01-27 01:24:03 +03:00
|
|
|
BX_ASSERT(position_page_offset < pagesize);
|
2005-12-10 18:02:26 +03:00
|
|
|
|
2008-01-27 01:24:03 +03:00
|
|
|
buf = (((Bit8u *) buf) + can_write);
|
|
|
|
count -= can_write;
|
|
|
|
}
|
2005-12-10 18:02:26 +03:00
|
|
|
|
2008-01-27 01:24:03 +03:00
|
|
|
if (update_pagetable_count != 0)
|
|
|
|
{
|
|
|
|
bx_bool done = 0;
|
|
|
|
off_t pagetable_write_from = sizeof(header) + (sizeof(Bit32u) * update_pagetable_start);
|
|
|
|
size_t write_bytecount = update_pagetable_count * sizeof(Bit32u);
|
2005-12-10 18:02:26 +03:00
|
|
|
|
|
|
|
#ifdef _POSIX_MAPPED_FILES
|
2008-01-27 01:24:03 +03:00
|
|
|
if (mmap_header != NULL)
|
|
|
|
{
|
|
|
|
// Sync from the beginning of the page
|
|
|
|
size_t system_page_offset = pagetable_write_from & system_pagesize_mask;
|
|
|
|
void *start = ((Bit8u *) mmap_header + pagetable_write_from - system_page_offset);
|
2005-12-10 18:02:26 +03:00
|
|
|
|
2008-01-27 01:24:03 +03:00
|
|
|
int ret = msync(start, system_page_offset + write_bytecount, MS_ASYNC);
|
2005-12-10 18:02:26 +03:00
|
|
|
|
2008-01-27 01:24:03 +03:00
|
|
|
if (ret != 0)
|
|
|
|
panic(strerror(errno));
|
2005-12-10 18:02:26 +03:00
|
|
|
|
2008-01-27 01:24:03 +03:00
|
|
|
done = 1;
|
|
|
|
}
|
2005-12-10 18:02:26 +03:00
|
|
|
#endif
|
|
|
|
|
2008-01-27 01:24:03 +03:00
|
|
|
if (!done)
|
|
|
|
{
|
|
|
|
int ret = (int)::lseek(fd, pagetable_write_from, SEEK_SET);
|
|
|
|
// underlying_current_filepos update deferred
|
|
|
|
if (ret == -1) panic(strerror(errno));
|
2005-12-10 18:02:26 +03:00
|
|
|
|
2008-01-27 01:24:03 +03:00
|
|
|
//printf("Writing header at position %ld size %ld\n", (long) pagetable_write_from, (long) write_bytecount);
|
|
|
|
ret = ::write(fd, &pagetable[update_pagetable_start], write_bytecount);
|
|
|
|
if (ret == -1) panic(strerror(errno));
|
|
|
|
if ((size_t)ret != write_bytecount) panic("could not write entire updated block header");
|
2005-12-10 18:02:26 +03:00
|
|
|
|
2008-01-27 01:24:03 +03:00
|
|
|
underlying_current_filepos = pagetable_write_from + write_bytecount;
|
|
|
|
}
|
|
|
|
}
|
2005-12-10 18:02:26 +03:00
|
|
|
|
2008-01-27 01:24:03 +03:00
|
|
|
return total_written;
|
2005-12-10 18:02:26 +03:00
|
|
|
}
|
|
|
|
|
2012-09-18 23:00:25 +04:00
|
|
|
bx_bool sparse_image_t::save_state(const char *backup_fname)
|
|
|
|
{
|
2012-09-21 00:41:14 +04:00
|
|
|
return hdimage_backup_file(fd, backup_fname);
|
2012-09-18 23:00:25 +04:00
|
|
|
}
|
|
|
|
|
2005-12-10 18:02:26 +03:00
|
|
|
#if DLL_HD_SUPPORT
|
|
|
|
|
|
|
|
/*** dll_image_t function definitions ***/
|
|
|
|
|
|
|
|
/*
|
|
|
|
function vdisk_open(path:PChar;numclusters,clustersize:integer):integer;
|
|
|
|
procedure vdisk_read(vunit:integer;blk:integer;var buf:TBlock);
|
|
|
|
procedure vdisk_write(vunit:integer;blk:integer;var buf:TBlock);
|
|
|
|
procedure vdisk_close(vunit:integer);
|
|
|
|
*/
|
|
|
|
|
|
|
|
HINSTANCE hlib_vdisk = 0;
|
|
|
|
|
|
|
|
int (*vdisk_open) (const char *path,int numclusters,int clustersize);
|
|
|
|
void (*vdisk_read) (int vunit,int blk,void *buf);
|
|
|
|
void (*vdisk_write) (int vunit,int blk,const void *buf);
|
|
|
|
void (*vdisk_close) (int vunit);
|
|
|
|
|
|
|
|
int dll_image_t::open (const char* pathname)
|
|
|
|
{
|
2008-01-27 01:24:03 +03:00
|
|
|
if (hlib_vdisk == 0) {
|
|
|
|
hlib_vdisk = LoadLibrary("vdisk.dll");
|
2005-12-10 18:02:26 +03:00
|
|
|
if (hlib_vdisk != 0) {
|
2008-01-27 01:24:03 +03:00
|
|
|
vdisk_read = (void (*)(int,int,void*)) GetProcAddress(hlib_vdisk,"vdisk_read");
|
|
|
|
vdisk_write = (void (*)(int,int,const void*)) GetProcAddress(hlib_vdisk,"vdisk_write");
|
|
|
|
vdisk_open = (int (*)(const char *,int,int)) GetProcAddress(hlib_vdisk,"vdisk_open");
|
|
|
|
vdisk_close = (void (*)(int)) GetProcAddress(hlib_vdisk,"vdisk_close");
|
2005-12-10 18:02:26 +03:00
|
|
|
}
|
2008-01-27 01:24:03 +03:00
|
|
|
}
|
|
|
|
if (hlib_vdisk != 0) {
|
|
|
|
vunit = vdisk_open(pathname,0x10000,64);
|
|
|
|
vblk = 0;
|
|
|
|
} else {
|
|
|
|
vunit = -2;
|
|
|
|
}
|
|
|
|
return vunit;
|
2005-12-10 18:02:26 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
void dll_image_t::close ()
|
|
|
|
{
|
2008-01-27 01:24:03 +03:00
|
|
|
if (vunit >= 0 && hlib_vdisk != 0) {
|
|
|
|
vdisk_close(vunit);
|
|
|
|
}
|
2005-12-10 18:02:26 +03:00
|
|
|
}
|
|
|
|
|
2006-11-18 14:51:07 +03:00
|
|
|
Bit64s dll_image_t::lseek(Bit64s offset, int whence)
|
2005-12-10 18:02:26 +03:00
|
|
|
{
|
2008-01-27 01:24:03 +03:00
|
|
|
vblk = (int)(offset >> 9);
|
|
|
|
return 0;
|
2005-12-10 18:02:26 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
ssize_t dll_image_t::read (void* buf, size_t count)
|
|
|
|
{
|
2008-01-27 01:24:03 +03:00
|
|
|
if (vunit >= 0 && hlib_vdisk != 0) {
|
|
|
|
vdisk_read(vunit,vblk,buf);
|
|
|
|
return count;
|
|
|
|
} else {
|
|
|
|
return -1;
|
|
|
|
}
|
2005-12-10 18:02:26 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
ssize_t dll_image_t::write (const void* buf, size_t count)
|
|
|
|
{
|
2008-01-27 01:24:03 +03:00
|
|
|
if (vunit >= 0 && hlib_vdisk != 0) {
|
|
|
|
vdisk_write(vunit,vblk,buf);
|
|
|
|
return count;
|
|
|
|
} else {
|
|
|
|
return -1;
|
|
|
|
}
|
2005-12-10 18:02:26 +03:00
|
|
|
}
|
|
|
|
#endif // DLL_HD_SUPPORT
|
|
|
|
|
|
|
|
// redolog implementation
|
2006-06-05 12:00:21 +04:00
|
|
|
redolog_t::redolog_t()
|
2005-12-10 18:02:26 +03:00
|
|
|
{
|
2006-06-05 12:00:21 +04:00
|
|
|
fd = -1;
|
|
|
|
catalog = NULL;
|
|
|
|
bitmap = NULL;
|
|
|
|
extent_index = (Bit32u)0;
|
|
|
|
extent_offset = (Bit32u)0;
|
|
|
|
extent_next = (Bit32u)0;
|
2005-12-10 18:02:26 +03:00
|
|
|
}
|
|
|
|
|
2008-01-27 01:24:03 +03:00
|
|
|
void redolog_t::print_header()
|
2005-12-10 18:02:26 +03:00
|
|
|
{
|
2006-05-15 01:15:33 +04:00
|
|
|
BX_INFO(("redolog : Standard Header : magic='%s', type='%s', subtype='%s', version = %d.%d",
|
|
|
|
header.standard.magic, header.standard.type, header.standard.subtype,
|
|
|
|
dtoh32(header.standard.version)/0x10000,
|
|
|
|
dtoh32(header.standard.version)%0x10000));
|
|
|
|
if (dtoh32(header.standard.version) == STANDARD_HEADER_VERSION) {
|
|
|
|
BX_INFO(("redolog : Specific Header : #entries=%d, bitmap size=%d, exent size = %d disk size = " FMT_LL "d",
|
|
|
|
dtoh32(header.specific.catalog),
|
|
|
|
dtoh32(header.specific.bitmap),
|
|
|
|
dtoh32(header.specific.extent),
|
|
|
|
dtoh64(header.specific.disk)));
|
|
|
|
} else if (dtoh32(header.standard.version) == STANDARD_HEADER_V1) {
|
|
|
|
redolog_header_v1_t header_v1;
|
|
|
|
memcpy(&header_v1, &header, STANDARD_HEADER_SIZE);
|
|
|
|
BX_INFO(("redolog : Specific Header : #entries=%d, bitmap size=%d, exent size = %d disk size = " FMT_LL "d",
|
|
|
|
dtoh32(header_v1.specific.catalog),
|
|
|
|
dtoh32(header_v1.specific.bitmap),
|
|
|
|
dtoh32(header_v1.specific.extent),
|
|
|
|
dtoh64(header_v1.specific.disk)));
|
|
|
|
}
|
2005-12-10 18:02:26 +03:00
|
|
|
}
|
|
|
|
|
2008-01-27 01:24:03 +03:00
|
|
|
int redolog_t::make_header(const char* type, Bit64u size)
|
2005-12-10 18:02:26 +03:00
|
|
|
{
|
2008-01-27 01:24:03 +03:00
|
|
|
Bit32u entries, extent_size, bitmap_size;
|
|
|
|
Bit64u maxsize;
|
|
|
|
Bit32u flip=0;
|
2005-12-10 18:02:26 +03:00
|
|
|
|
2008-01-27 01:24:03 +03:00
|
|
|
// Set standard header values
|
2012-02-10 22:08:17 +04:00
|
|
|
memset(&header, 0, sizeof(redolog_header_t));
|
2008-01-27 01:24:03 +03:00
|
|
|
strcpy((char*)header.standard.magic, STANDARD_HEADER_MAGIC);
|
|
|
|
strcpy((char*)header.standard.type, REDOLOG_TYPE);
|
|
|
|
strcpy((char*)header.standard.subtype, type);
|
|
|
|
header.standard.version = htod32(STANDARD_HEADER_VERSION);
|
|
|
|
header.standard.header = htod32(STANDARD_HEADER_SIZE);
|
2005-12-10 18:02:26 +03:00
|
|
|
|
2008-01-27 01:24:03 +03:00
|
|
|
entries = 512;
|
|
|
|
bitmap_size = 1;
|
2005-12-10 18:02:26 +03:00
|
|
|
|
2008-01-27 01:24:03 +03:00
|
|
|
// Compute #entries and extent size values
|
|
|
|
do {
|
|
|
|
extent_size = 8 * bitmap_size * 512;
|
2005-12-10 18:02:26 +03:00
|
|
|
|
2008-01-27 01:24:03 +03:00
|
|
|
header.specific.catalog = htod32(entries);
|
|
|
|
header.specific.bitmap = htod32(bitmap_size);
|
|
|
|
header.specific.extent = htod32(extent_size);
|
2005-12-10 18:02:26 +03:00
|
|
|
|
2008-01-27 01:24:03 +03:00
|
|
|
maxsize = (Bit64u)entries * (Bit64u)extent_size;
|
2005-12-10 18:02:26 +03:00
|
|
|
|
2008-01-27 01:24:03 +03:00
|
|
|
flip++;
|
2005-12-10 18:02:26 +03:00
|
|
|
|
2008-01-27 01:24:03 +03:00
|
|
|
if(flip&0x01) bitmap_size *= 2;
|
|
|
|
else entries *= 2;
|
|
|
|
} while (maxsize < size);
|
2005-12-10 18:02:26 +03:00
|
|
|
|
2012-07-21 16:00:46 +04:00
|
|
|
header.specific.timestamp = 0;
|
2008-01-27 01:24:03 +03:00
|
|
|
header.specific.disk = htod64(size);
|
2005-12-10 18:02:26 +03:00
|
|
|
|
2008-01-27 01:24:03 +03:00
|
|
|
print_header();
|
2005-12-10 18:02:26 +03:00
|
|
|
|
2008-01-27 01:24:03 +03:00
|
|
|
catalog = (Bit32u*)malloc(dtoh32(header.specific.catalog) * sizeof(Bit32u));
|
|
|
|
bitmap = (Bit8u*)malloc(dtoh32(header.specific.bitmap));
|
2005-12-10 18:02:26 +03:00
|
|
|
|
2008-01-27 01:24:03 +03:00
|
|
|
if ((catalog == NULL) || (bitmap==NULL))
|
|
|
|
BX_PANIC(("redolog : could not malloc catalog or bitmap"));
|
2005-12-10 18:02:26 +03:00
|
|
|
|
2008-01-27 01:24:03 +03:00
|
|
|
for (Bit32u i=0; i<dtoh32(header.specific.catalog); i++)
|
|
|
|
catalog[i] = htod32(REDOLOG_PAGE_NOT_ALLOCATED);
|
2005-12-10 18:02:26 +03:00
|
|
|
|
2011-01-07 21:35:34 +03:00
|
|
|
bitmap_blocks = 1 + (dtoh32(header.specific.bitmap) - 1) / 512;
|
|
|
|
extent_blocks = 1 + (dtoh32(header.specific.extent) - 1) / 512;
|
2008-01-27 01:24:03 +03:00
|
|
|
|
2011-01-07 21:35:34 +03:00
|
|
|
BX_DEBUG(("redolog : each bitmap is %d blocks", bitmap_blocks));
|
|
|
|
BX_DEBUG(("redolog : each extent is %d blocks", extent_blocks));
|
2008-01-27 01:24:03 +03:00
|
|
|
|
|
|
|
return 0;
|
2005-12-10 18:02:26 +03:00
|
|
|
}
|
|
|
|
|
2008-01-27 01:24:03 +03:00
|
|
|
int redolog_t::create(const char* filename, const char* type, Bit64u size)
|
2005-12-10 18:02:26 +03:00
|
|
|
{
|
2008-01-27 01:24:03 +03:00
|
|
|
BX_INFO(("redolog : creating redolog %s", filename));
|
2005-12-10 18:02:26 +03:00
|
|
|
|
2008-01-27 01:24:03 +03:00
|
|
|
int filedes = ::open(filename, O_RDWR | O_CREAT | O_TRUNC
|
2005-12-10 18:02:26 +03:00
|
|
|
#ifdef O_BINARY
|
|
|
|
| O_BINARY
|
|
|
|
#endif
|
2008-01-27 01:24:03 +03:00
|
|
|
, S_IWUSR | S_IRUSR | S_IRGRP | S_IWGRP);
|
2005-12-10 18:02:26 +03:00
|
|
|
|
2008-01-27 01:24:03 +03:00
|
|
|
return create(filedes, type, size);
|
2005-12-10 18:02:26 +03:00
|
|
|
}
|
|
|
|
|
2008-01-27 01:24:03 +03:00
|
|
|
int redolog_t::create(int filedes, const char* type, Bit64u size)
|
2005-12-10 18:02:26 +03:00
|
|
|
{
|
2008-01-27 01:24:03 +03:00
|
|
|
fd = filedes;
|
2005-12-10 18:02:26 +03:00
|
|
|
|
2008-01-27 01:24:03 +03:00
|
|
|
if (fd < 0)
|
|
|
|
{
|
|
|
|
return -1; // open failed
|
|
|
|
}
|
2005-12-10 18:02:26 +03:00
|
|
|
|
2008-01-27 01:24:03 +03:00
|
|
|
if (make_header(type, size) < 0)
|
|
|
|
{
|
|
|
|
return -1;
|
|
|
|
}
|
2005-12-10 18:02:26 +03:00
|
|
|
|
2008-01-27 01:24:03 +03:00
|
|
|
// Write header
|
|
|
|
::write(fd, &header, dtoh32(header.standard.header));
|
2005-12-10 18:02:26 +03:00
|
|
|
|
2008-01-27 01:24:03 +03:00
|
|
|
// Write catalog
|
|
|
|
// FIXME could mmap
|
|
|
|
::write(fd, catalog, dtoh32(header.specific.catalog) * sizeof (Bit32u));
|
2005-12-10 18:02:26 +03:00
|
|
|
|
2008-01-27 01:24:03 +03:00
|
|
|
return 0;
|
2005-12-10 18:02:26 +03:00
|
|
|
}
|
|
|
|
|
2008-01-27 01:24:03 +03:00
|
|
|
int redolog_t::open(const char* filename, const char *type)
|
2005-12-10 18:02:26 +03:00
|
|
|
{
|
2006-06-05 12:00:21 +04:00
|
|
|
fd = ::open(filename, O_RDWR
|
2005-12-10 18:02:26 +03:00
|
|
|
#ifdef O_BINARY
|
2006-06-05 12:00:21 +04:00
|
|
|
| O_BINARY
|
2005-12-10 18:02:26 +03:00
|
|
|
#endif
|
|
|
|
);
|
2006-06-05 12:00:21 +04:00
|
|
|
if (fd < 0)
|
|
|
|
{
|
|
|
|
BX_INFO(("redolog : could not open image %s", filename));
|
|
|
|
// open failed.
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
BX_INFO(("redolog : open image %s", filename));
|
2005-12-10 18:02:26 +03:00
|
|
|
|
2012-08-05 18:42:37 +04:00
|
|
|
int res = bx_read_image(fd, 0, &header, sizeof(header));
|
2006-06-05 12:00:21 +04:00
|
|
|
if (res != STANDARD_HEADER_SIZE)
|
|
|
|
{
|
2008-01-27 01:24:03 +03:00
|
|
|
BX_PANIC(("redolog : could not read header"));
|
2006-06-05 12:00:21 +04:00
|
|
|
return -1;
|
|
|
|
}
|
2005-12-10 18:02:26 +03:00
|
|
|
|
2006-06-05 12:00:21 +04:00
|
|
|
print_header();
|
2005-12-10 18:02:26 +03:00
|
|
|
|
2006-06-05 12:00:21 +04:00
|
|
|
if (strcmp((char*)header.standard.magic, STANDARD_HEADER_MAGIC) != 0)
|
|
|
|
{
|
2008-01-27 01:24:03 +03:00
|
|
|
BX_PANIC(("redolog : Bad header magic"));
|
2006-06-05 12:00:21 +04:00
|
|
|
return -1;
|
|
|
|
}
|
2005-12-10 18:02:26 +03:00
|
|
|
|
2006-06-05 12:00:21 +04:00
|
|
|
if (strcmp((char*)header.standard.type, REDOLOG_TYPE) != 0)
|
|
|
|
{
|
2008-01-27 01:24:03 +03:00
|
|
|
BX_PANIC(("redolog : Bad header type"));
|
2006-06-05 12:00:21 +04:00
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
if (strcmp((char*)header.standard.subtype, type) != 0)
|
|
|
|
{
|
2008-01-27 01:24:03 +03:00
|
|
|
BX_PANIC(("redolog : Bad header subtype"));
|
2006-06-05 12:00:21 +04:00
|
|
|
return -1;
|
|
|
|
}
|
2005-12-10 18:02:26 +03:00
|
|
|
|
2006-06-05 12:00:21 +04:00
|
|
|
if ((dtoh32(header.standard.version) != STANDARD_HEADER_VERSION) &&
|
|
|
|
(dtoh32(header.standard.version) != STANDARD_HEADER_V1))
|
|
|
|
{
|
2008-01-27 01:24:03 +03:00
|
|
|
BX_PANIC(("redolog : Bad header version"));
|
2006-06-05 12:00:21 +04:00
|
|
|
return -1;
|
|
|
|
}
|
2006-05-15 01:15:33 +04:00
|
|
|
|
2006-06-05 12:00:21 +04:00
|
|
|
if (dtoh32(header.standard.version) == STANDARD_HEADER_V1) {
|
|
|
|
redolog_header_v1_t header_v1;
|
2006-05-15 01:15:33 +04:00
|
|
|
|
2006-06-05 12:00:21 +04:00
|
|
|
memcpy(&header_v1, &header, STANDARD_HEADER_SIZE);
|
|
|
|
header.specific.disk = header_v1.specific.disk;
|
|
|
|
}
|
|
|
|
|
|
|
|
catalog = (Bit32u*)malloc(dtoh32(header.specific.catalog) * sizeof(Bit32u));
|
2008-01-27 01:24:03 +03:00
|
|
|
|
2006-06-05 12:00:21 +04:00
|
|
|
// FIXME could mmap
|
2012-08-05 18:42:37 +04:00
|
|
|
res = bx_read_image(fd, dtoh32(header.standard.header), catalog, dtoh32(header.specific.catalog) * sizeof(Bit32u));
|
2005-12-10 18:02:26 +03:00
|
|
|
|
2006-06-05 12:00:21 +04:00
|
|
|
if (res != (ssize_t)(dtoh32(header.specific.catalog) * sizeof(Bit32u)))
|
|
|
|
{
|
2008-01-27 01:24:03 +03:00
|
|
|
BX_PANIC(("redolog : could not read catalog %d=%d",res, dtoh32(header.specific.catalog)));
|
2006-06-05 12:00:21 +04:00
|
|
|
return -1;
|
|
|
|
}
|
2005-12-10 18:02:26 +03:00
|
|
|
|
2006-06-05 12:00:21 +04:00
|
|
|
// check last used extent
|
|
|
|
extent_next = 0;
|
|
|
|
for (Bit32u i=0; i < dtoh32(header.specific.catalog); i++)
|
|
|
|
{
|
|
|
|
if (dtoh32(catalog[i]) != REDOLOG_PAGE_NOT_ALLOCATED)
|
|
|
|
{
|
|
|
|
if (dtoh32(catalog[i]) >= extent_next)
|
|
|
|
extent_next = dtoh32(catalog[i]) + 1;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
BX_INFO(("redolog : next extent will be at index %d",extent_next));
|
2005-12-10 18:02:26 +03:00
|
|
|
|
2006-06-05 12:00:21 +04:00
|
|
|
// memory used for storing bitmaps
|
|
|
|
bitmap = (Bit8u *)malloc(dtoh32(header.specific.bitmap));
|
2005-12-10 18:02:26 +03:00
|
|
|
|
2011-01-07 21:35:34 +03:00
|
|
|
bitmap_blocks = 1 + (dtoh32(header.specific.bitmap) - 1) / 512;
|
|
|
|
extent_blocks = 1 + (dtoh32(header.specific.extent) - 1) / 512;
|
2005-12-10 18:02:26 +03:00
|
|
|
|
2011-01-07 21:35:34 +03:00
|
|
|
BX_DEBUG(("redolog : each bitmap is %d blocks", bitmap_blocks));
|
|
|
|
BX_DEBUG(("redolog : each extent is %d blocks", extent_blocks));
|
|
|
|
|
|
|
|
imagepos = 0;
|
2012-08-05 18:42:37 +04:00
|
|
|
bitmap_update = 1;
|
2006-06-05 12:00:21 +04:00
|
|
|
|
|
|
|
return 0;
|
2005-12-10 18:02:26 +03:00
|
|
|
}
|
|
|
|
|
2006-06-05 12:00:21 +04:00
|
|
|
void redolog_t::close()
|
2005-12-10 18:02:26 +03:00
|
|
|
{
|
2006-06-05 12:00:21 +04:00
|
|
|
if (fd >= 0)
|
|
|
|
::close(fd);
|
2005-12-10 18:02:26 +03:00
|
|
|
|
2006-06-05 12:00:21 +04:00
|
|
|
if (catalog != NULL)
|
|
|
|
free(catalog);
|
2005-12-10 18:02:26 +03:00
|
|
|
|
2006-06-05 12:00:21 +04:00
|
|
|
if (bitmap != NULL)
|
|
|
|
free(bitmap);
|
2005-12-10 18:02:26 +03:00
|
|
|
}
|
|
|
|
|
2006-06-05 12:00:21 +04:00
|
|
|
Bit64u redolog_t::get_size()
|
2005-12-10 18:02:26 +03:00
|
|
|
{
|
2006-06-05 12:00:21 +04:00
|
|
|
return dtoh64(header.specific.disk);
|
|
|
|
}
|
|
|
|
|
2012-07-21 16:00:46 +04:00
|
|
|
Bit32u redolog_t::get_timestamp()
|
|
|
|
{
|
|
|
|
return dtoh32(header.specific.timestamp);
|
|
|
|
}
|
|
|
|
|
|
|
|
bx_bool redolog_t::set_timestamp(Bit32u timestamp)
|
|
|
|
{
|
|
|
|
header.specific.timestamp = htod32(timestamp);
|
|
|
|
// Update header
|
2012-08-05 18:42:37 +04:00
|
|
|
bx_write_image(fd, 0, &header, dtoh32(header.standard.header));
|
2012-07-21 16:00:46 +04:00
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
|
2006-06-09 00:32:00 +04:00
|
|
|
Bit64s redolog_t::lseek(Bit64s offset, int whence)
|
2006-06-05 12:00:21 +04:00
|
|
|
{
|
|
|
|
if ((offset % 512) != 0) {
|
2011-01-07 21:35:34 +03:00
|
|
|
BX_PANIC(("redolog : lseek() offset not multiple of 512"));
|
2006-06-05 12:00:21 +04:00
|
|
|
return -1;
|
|
|
|
}
|
2011-01-07 21:35:34 +03:00
|
|
|
if (whence == SEEK_SET) {
|
|
|
|
imagepos = offset;
|
|
|
|
} else if (whence == SEEK_CUR) {
|
|
|
|
imagepos += offset;
|
|
|
|
} else {
|
|
|
|
BX_PANIC(("redolog: lseek() mode not supported yet"));
|
2006-06-05 12:00:21 +04:00
|
|
|
return -1;
|
|
|
|
}
|
2011-01-07 21:35:34 +03:00
|
|
|
if (imagepos > (Bit64s)dtoh64(header.specific.disk)) {
|
|
|
|
BX_PANIC(("redolog : lseek() to byte %ld failed", (long)offset));
|
2006-06-05 12:00:21 +04:00
|
|
|
return -1;
|
|
|
|
}
|
2005-12-10 18:02:26 +03:00
|
|
|
|
2012-08-05 18:42:37 +04:00
|
|
|
Bit32u old_extent_index = extent_index;
|
2011-01-07 21:35:34 +03:00
|
|
|
extent_index = (Bit32u)(imagepos / dtoh32(header.specific.extent));
|
2012-08-05 18:42:37 +04:00
|
|
|
if (extent_index != old_extent_index) {
|
|
|
|
bitmap_update = 1;
|
|
|
|
}
|
2011-01-07 21:35:34 +03:00
|
|
|
extent_offset = (Bit32u)((imagepos % dtoh32(header.specific.extent)) / 512);
|
2005-12-10 18:02:26 +03:00
|
|
|
|
2006-06-05 12:00:21 +04:00
|
|
|
BX_DEBUG(("redolog : lseeking extent index %d, offset %d",extent_index, extent_offset));
|
2005-12-10 18:02:26 +03:00
|
|
|
|
2011-01-07 21:35:34 +03:00
|
|
|
return imagepos;
|
2005-12-10 18:02:26 +03:00
|
|
|
}
|
|
|
|
|
2006-11-18 14:51:07 +03:00
|
|
|
ssize_t redolog_t::read(void* buf, size_t count)
|
2005-12-10 18:02:26 +03:00
|
|
|
{
|
2011-01-14 19:43:55 +03:00
|
|
|
Bit64s block_offset, bitmap_offset;
|
|
|
|
ssize_t ret;
|
2005-12-10 18:02:26 +03:00
|
|
|
|
2011-01-07 21:35:34 +03:00
|
|
|
if (count != 512) {
|
|
|
|
BX_PANIC(("redolog : read() with count not 512"));
|
|
|
|
return -1;
|
|
|
|
}
|
2005-12-10 18:02:26 +03:00
|
|
|
|
2006-11-18 14:51:07 +03:00
|
|
|
BX_DEBUG(("redolog : reading index %d, mapping to %d", extent_index, dtoh32(catalog[extent_index])));
|
2005-12-10 18:02:26 +03:00
|
|
|
|
2011-01-07 21:35:34 +03:00
|
|
|
if (dtoh32(catalog[extent_index]) == REDOLOG_PAGE_NOT_ALLOCATED) {
|
2006-11-18 14:51:07 +03:00
|
|
|
// page not allocated
|
|
|
|
return 0;
|
|
|
|
}
|
2005-12-10 18:02:26 +03:00
|
|
|
|
2006-11-18 14:51:07 +03:00
|
|
|
bitmap_offset = (Bit64s)STANDARD_HEADER_SIZE + (dtoh32(header.specific.catalog) * sizeof(Bit32u));
|
2011-01-07 21:35:34 +03:00
|
|
|
bitmap_offset += (Bit64s)512 * dtoh32(catalog[extent_index]) * (extent_blocks + bitmap_blocks);
|
|
|
|
block_offset = bitmap_offset + ((Bit64s)512 * (bitmap_blocks + extent_offset));
|
2005-12-10 18:02:26 +03:00
|
|
|
|
2006-11-18 14:51:07 +03:00
|
|
|
BX_DEBUG(("redolog : bitmap offset is %x", (Bit32u)bitmap_offset));
|
2011-01-07 21:35:34 +03:00
|
|
|
BX_DEBUG(("redolog : block offset is %x", (Bit32u)block_offset));
|
2005-12-10 18:02:26 +03:00
|
|
|
|
2012-08-05 18:42:37 +04:00
|
|
|
if (bitmap_update) {
|
|
|
|
if (bx_read_image(fd, (off_t)bitmap_offset, bitmap, dtoh32(header.specific.bitmap)) != (ssize_t)dtoh32(header.specific.bitmap)) {
|
|
|
|
BX_PANIC(("redolog : failed to read bitmap for extent %d", extent_index));
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
bitmap_update = 0;
|
2006-11-18 14:51:07 +03:00
|
|
|
}
|
2005-12-10 18:02:26 +03:00
|
|
|
|
2011-01-07 21:35:34 +03:00
|
|
|
if (((bitmap[extent_offset/8] >> (extent_offset%8)) & 0x01) == 0x00) {
|
2006-11-18 14:51:07 +03:00
|
|
|
BX_DEBUG(("read not in redolog"));
|
2005-12-10 18:02:26 +03:00
|
|
|
|
2011-01-07 21:35:34 +03:00
|
|
|
// bitmap says block not in redolog
|
2006-11-18 14:51:07 +03:00
|
|
|
return 0;
|
|
|
|
}
|
2005-12-10 18:02:26 +03:00
|
|
|
|
2012-08-05 18:42:37 +04:00
|
|
|
ret = bx_read_image(fd, (off_t)block_offset, buf, count);
|
2011-01-07 21:35:34 +03:00
|
|
|
if (ret >= 0) lseek(512, SEEK_CUR);
|
2005-12-10 18:02:26 +03:00
|
|
|
|
2011-01-07 21:35:34 +03:00
|
|
|
return ret;
|
2005-12-10 18:02:26 +03:00
|
|
|
}
|
|
|
|
|
2006-11-18 14:51:07 +03:00
|
|
|
ssize_t redolog_t::write(const void* buf, size_t count)
|
2005-12-10 18:02:26 +03:00
|
|
|
{
|
2006-11-18 14:51:07 +03:00
|
|
|
Bit32u i;
|
2011-01-07 21:35:34 +03:00
|
|
|
Bit64s block_offset, bitmap_offset, catalog_offset;
|
2006-11-18 14:51:07 +03:00
|
|
|
ssize_t written;
|
|
|
|
bx_bool update_catalog = 0;
|
2005-12-10 18:02:26 +03:00
|
|
|
|
2011-01-07 21:35:34 +03:00
|
|
|
if (count != 512) {
|
|
|
|
BX_PANIC(("redolog : write() with count not 512"));
|
|
|
|
return -1;
|
|
|
|
}
|
2005-12-10 18:02:26 +03:00
|
|
|
|
2006-11-18 14:51:07 +03:00
|
|
|
BX_DEBUG(("redolog : writing index %d, mapping to %d", extent_index, dtoh32(catalog[extent_index])));
|
2011-01-07 21:35:34 +03:00
|
|
|
|
|
|
|
if (dtoh32(catalog[extent_index]) == REDOLOG_PAGE_NOT_ALLOCATED) {
|
|
|
|
if (extent_next >= dtoh32(header.specific.catalog)) {
|
2006-11-18 14:51:07 +03:00
|
|
|
BX_PANIC(("redolog : can't allocate new extent... catalog is full"));
|
2011-01-07 21:35:34 +03:00
|
|
|
return -1;
|
2006-11-18 14:51:07 +03:00
|
|
|
}
|
2005-12-10 18:02:26 +03:00
|
|
|
|
2006-11-18 14:51:07 +03:00
|
|
|
BX_DEBUG(("redolog : allocating new extent at %d", extent_next));
|
2005-12-10 18:02:26 +03:00
|
|
|
|
2006-11-18 14:51:07 +03:00
|
|
|
// Extent not allocated, allocate new
|
|
|
|
catalog[extent_index] = htod32(extent_next);
|
2005-12-10 18:02:26 +03:00
|
|
|
|
2006-11-18 14:51:07 +03:00
|
|
|
extent_next += 1;
|
2005-12-10 18:02:26 +03:00
|
|
|
|
2006-11-18 14:51:07 +03:00
|
|
|
char *zerobuffer = (char*)malloc(512);
|
|
|
|
memset(zerobuffer, 0, 512);
|
2005-12-10 18:02:26 +03:00
|
|
|
|
2006-11-18 14:51:07 +03:00
|
|
|
// Write bitmap
|
|
|
|
bitmap_offset = (Bit64s)STANDARD_HEADER_SIZE + (dtoh32(header.specific.catalog) * sizeof(Bit32u));
|
2011-01-07 21:35:34 +03:00
|
|
|
bitmap_offset += (Bit64s)512 * dtoh32(catalog[extent_index]) * (extent_blocks + bitmap_blocks);
|
2006-11-18 14:51:07 +03:00
|
|
|
::lseek(fd, (off_t)bitmap_offset, SEEK_SET);
|
2011-01-07 21:35:34 +03:00
|
|
|
for (i=0; i<bitmap_blocks; i++) {
|
2006-11-18 14:51:07 +03:00
|
|
|
::write(fd, zerobuffer, 512);
|
|
|
|
}
|
|
|
|
// Write extent
|
2011-01-07 21:35:34 +03:00
|
|
|
for (i=0; i<extent_blocks; i++) {
|
2006-11-18 14:51:07 +03:00
|
|
|
::write(fd, zerobuffer, 512);
|
|
|
|
}
|
2005-12-10 18:02:26 +03:00
|
|
|
|
2006-11-18 14:51:07 +03:00
|
|
|
free(zerobuffer);
|
2005-12-10 18:02:26 +03:00
|
|
|
|
2006-11-18 14:51:07 +03:00
|
|
|
update_catalog = 1;
|
|
|
|
}
|
2005-12-10 18:02:26 +03:00
|
|
|
|
2006-11-18 14:51:07 +03:00
|
|
|
bitmap_offset = (Bit64s)STANDARD_HEADER_SIZE + (dtoh32(header.specific.catalog) * sizeof(Bit32u));
|
2011-01-07 21:35:34 +03:00
|
|
|
bitmap_offset += (Bit64s)512 * dtoh32(catalog[extent_index]) * (extent_blocks + bitmap_blocks);
|
|
|
|
block_offset = bitmap_offset + ((Bit64s)512 * (bitmap_blocks + extent_offset));
|
2005-12-10 18:02:26 +03:00
|
|
|
|
2006-11-18 14:51:07 +03:00
|
|
|
BX_DEBUG(("redolog : bitmap offset is %x", (Bit32u)bitmap_offset));
|
2011-01-07 21:35:34 +03:00
|
|
|
BX_DEBUG(("redolog : block offset is %x", (Bit32u)block_offset));
|
2005-12-10 18:02:26 +03:00
|
|
|
|
2011-01-07 21:35:34 +03:00
|
|
|
// Write block
|
2012-08-05 18:42:37 +04:00
|
|
|
written = bx_write_image(fd, (off_t)block_offset, (void*)buf, count);
|
2005-12-10 18:02:26 +03:00
|
|
|
|
2006-11-18 14:51:07 +03:00
|
|
|
// Write bitmap
|
2012-08-05 18:42:37 +04:00
|
|
|
if (bitmap_update) {
|
|
|
|
if (bx_read_image(fd, (off_t)bitmap_offset, bitmap, dtoh32(header.specific.bitmap)) != (ssize_t)dtoh32(header.specific.bitmap)) {
|
|
|
|
BX_PANIC(("redolog : failed to read bitmap for extent %d", extent_index));
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
bitmap_update = 0;
|
2006-11-18 14:51:07 +03:00
|
|
|
}
|
2005-12-10 18:02:26 +03:00
|
|
|
|
2006-11-18 14:51:07 +03:00
|
|
|
// If bloc does not belong to extent yet
|
2011-01-07 21:35:34 +03:00
|
|
|
if (((bitmap[extent_offset/8] >> (extent_offset%8)) & 0x01) == 0x00) {
|
2006-11-18 14:51:07 +03:00
|
|
|
bitmap[extent_offset/8] |= 1 << (extent_offset%8);
|
2012-08-05 18:42:37 +04:00
|
|
|
bx_write_image(fd, (off_t)bitmap_offset, bitmap, dtoh32(header.specific.bitmap));
|
2006-11-18 14:51:07 +03:00
|
|
|
}
|
2005-12-10 18:02:26 +03:00
|
|
|
|
2006-11-18 14:51:07 +03:00
|
|
|
// Write catalog
|
2011-01-07 21:35:34 +03:00
|
|
|
if (update_catalog) {
|
2006-11-18 14:51:07 +03:00
|
|
|
// FIXME if mmap
|
|
|
|
catalog_offset = (Bit64s)STANDARD_HEADER_SIZE + (extent_index * sizeof(Bit32u));
|
2005-12-10 18:02:26 +03:00
|
|
|
|
2006-11-18 14:51:07 +03:00
|
|
|
BX_DEBUG(("redolog : writing catalog at offset %x", (Bit32u)catalog_offset));
|
2005-12-10 18:02:26 +03:00
|
|
|
|
2012-08-05 18:42:37 +04:00
|
|
|
bx_write_image(fd, (off_t)catalog_offset, &catalog[extent_index], sizeof(Bit32u));
|
2006-11-18 14:51:07 +03:00
|
|
|
}
|
|
|
|
|
2011-01-07 21:35:34 +03:00
|
|
|
if (written >= 0) lseek(512, SEEK_CUR);
|
|
|
|
|
2006-11-18 14:51:07 +03:00
|
|
|
return written;
|
2005-12-10 18:02:26 +03:00
|
|
|
}
|
|
|
|
|
2012-09-17 23:30:40 +04:00
|
|
|
bx_bool redolog_t::save_state(const char *backup_fname)
|
|
|
|
{
|
|
|
|
return hdimage_backup_file(fd, backup_fname);
|
|
|
|
}
|
|
|
|
|
2005-12-10 18:02:26 +03:00
|
|
|
/*** growing_image_t function definitions ***/
|
|
|
|
|
2006-06-09 00:32:00 +04:00
|
|
|
growing_image_t::growing_image_t()
|
2005-12-10 18:02:26 +03:00
|
|
|
{
|
2006-06-05 12:00:21 +04:00
|
|
|
redolog = new redolog_t();
|
2005-12-10 18:02:26 +03:00
|
|
|
}
|
|
|
|
|
2007-03-10 15:53:54 +03:00
|
|
|
growing_image_t::~growing_image_t()
|
|
|
|
{
|
|
|
|
delete redolog;
|
|
|
|
}
|
|
|
|
|
2006-06-05 12:00:21 +04:00
|
|
|
int growing_image_t::open(const char* pathname)
|
2005-12-10 18:02:26 +03:00
|
|
|
{
|
2006-06-09 00:32:00 +04:00
|
|
|
int filedes = redolog->open(pathname, REDOLOG_SUBTYPE_GROWING);
|
|
|
|
hd_size = redolog->get_size();
|
2006-06-05 12:00:21 +04:00
|
|
|
BX_INFO(("'growing' disk opened, growing file is '%s'", pathname));
|
|
|
|
return filedes;
|
2005-12-10 18:02:26 +03:00
|
|
|
}
|
|
|
|
|
2006-06-05 12:00:21 +04:00
|
|
|
void growing_image_t::close()
|
2005-12-10 18:02:26 +03:00
|
|
|
{
|
2006-06-05 12:00:21 +04:00
|
|
|
redolog->close();
|
2005-12-10 18:02:26 +03:00
|
|
|
}
|
|
|
|
|
2006-06-09 00:32:00 +04:00
|
|
|
Bit64s growing_image_t::lseek(Bit64s offset, int whence)
|
2005-12-10 18:02:26 +03:00
|
|
|
{
|
2006-06-05 12:00:21 +04:00
|
|
|
return redolog->lseek(offset, whence);
|
2005-12-10 18:02:26 +03:00
|
|
|
}
|
|
|
|
|
2006-06-05 12:00:21 +04:00
|
|
|
ssize_t growing_image_t::read(void* buf, size_t count)
|
2005-12-10 18:02:26 +03:00
|
|
|
{
|
2011-01-14 19:43:55 +03:00
|
|
|
size_t n = 0;
|
|
|
|
ssize_t ret = 0;
|
|
|
|
|
2006-06-05 12:00:21 +04:00
|
|
|
memset(buf, 0, count);
|
2011-01-14 19:43:55 +03:00
|
|
|
while (n < count) {
|
|
|
|
ret = redolog->read((char*) buf, 512);
|
|
|
|
if (ret < 0) break;
|
|
|
|
n += 512;
|
|
|
|
}
|
|
|
|
return (ret < 0) ? ret : count;
|
2005-12-10 18:02:26 +03:00
|
|
|
}
|
|
|
|
|
2006-06-05 12:00:21 +04:00
|
|
|
ssize_t growing_image_t::write(const void* buf, size_t count)
|
2005-12-10 18:02:26 +03:00
|
|
|
{
|
2011-01-14 19:43:55 +03:00
|
|
|
size_t n = 0;
|
|
|
|
ssize_t ret = 0;
|
|
|
|
|
|
|
|
while (n < count) {
|
|
|
|
ret = redolog->write((char*) buf, 512);
|
|
|
|
if (ret < 0) break;
|
|
|
|
n += 512;
|
|
|
|
}
|
|
|
|
return (ret < 0) ? ret : count;
|
2005-12-10 18:02:26 +03:00
|
|
|
}
|
|
|
|
|
2012-09-17 23:30:40 +04:00
|
|
|
bx_bool growing_image_t::save_state(const char *backup_fname)
|
|
|
|
{
|
|
|
|
return redolog->save_state(backup_fname);
|
|
|
|
}
|
|
|
|
|
2012-09-22 00:25:23 +04:00
|
|
|
// compare hd_size and modification time of r/o disk and journal
|
|
|
|
|
|
|
|
bx_bool coherency_check(default_image_t *ro_disk, redolog_t *redolog)
|
|
|
|
{
|
|
|
|
Bit32u timestamp1, timestamp2;
|
|
|
|
|
|
|
|
if (ro_disk->hd_size != redolog->get_size()) {
|
|
|
|
BX_PANIC(("size reported by redolog doesn't match r/o disk size"));
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
timestamp1 = ro_disk->get_timestamp();
|
|
|
|
timestamp2 = redolog->get_timestamp();
|
|
|
|
if (timestamp2 != 0) {
|
|
|
|
if (timestamp1 != timestamp2) {
|
|
|
|
BX_PANIC(("unexpected modification time of the r/o disk"));
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
} else if (timestamp1 != 0) {
|
|
|
|
redolog->set_timestamp(timestamp1);
|
|
|
|
}
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
|
2005-12-10 18:02:26 +03:00
|
|
|
/*** undoable_image_t function definitions ***/
|
|
|
|
|
2006-06-09 00:32:00 +04:00
|
|
|
undoable_image_t::undoable_image_t(const char* _redolog_name)
|
2005-12-10 18:02:26 +03:00
|
|
|
{
|
2006-06-09 00:32:00 +04:00
|
|
|
redolog = new redolog_t();
|
|
|
|
ro_disk = new default_image_t();
|
|
|
|
redolog_name = NULL;
|
|
|
|
if (_redolog_name != NULL) {
|
|
|
|
if (strcmp(_redolog_name,"") != 0) {
|
|
|
|
redolog_name = strdup(_redolog_name);
|
|
|
|
}
|
|
|
|
}
|
2005-12-10 18:02:26 +03:00
|
|
|
}
|
|
|
|
|
2007-03-10 15:53:54 +03:00
|
|
|
undoable_image_t::~undoable_image_t()
|
|
|
|
{
|
|
|
|
delete redolog;
|
|
|
|
delete ro_disk;
|
|
|
|
}
|
|
|
|
|
2006-06-09 00:32:00 +04:00
|
|
|
int undoable_image_t::open(const char* pathname)
|
2005-12-10 18:02:26 +03:00
|
|
|
{
|
2012-09-22 14:04:28 +04:00
|
|
|
if (ro_disk->open(pathname, O_RDONLY) < 0)
|
2006-06-09 00:32:00 +04:00
|
|
|
return -1;
|
2005-12-10 18:02:26 +03:00
|
|
|
|
2006-06-09 00:32:00 +04:00
|
|
|
hd_size = ro_disk->hd_size;
|
2005-12-10 18:02:26 +03:00
|
|
|
|
2012-09-22 14:04:28 +04:00
|
|
|
// If not set, we make up the redolog filename from the pathname
|
|
|
|
if (redolog_name == NULL) {
|
|
|
|
redolog_name = (char*)malloc(strlen(pathname) + UNDOABLE_REDOLOG_EXTENSION_LENGTH + 1);
|
|
|
|
sprintf(redolog_name, "%s%s", pathname, UNDOABLE_REDOLOG_EXTENSION);
|
2006-06-09 00:32:00 +04:00
|
|
|
}
|
2005-12-10 18:02:26 +03:00
|
|
|
|
2012-09-22 14:04:28 +04:00
|
|
|
if (redolog->open(redolog_name, REDOLOG_SUBTYPE_UNDOABLE) < 0) {
|
|
|
|
if (redolog->create(redolog_name, REDOLOG_SUBTYPE_UNDOABLE, hd_size) < 0) {
|
|
|
|
BX_PANIC(("Can't open or create redolog '%s'",redolog_name));
|
2006-06-09 00:32:00 +04:00
|
|
|
return -1;
|
|
|
|
}
|
2012-07-21 16:00:46 +04:00
|
|
|
}
|
2012-09-22 00:25:23 +04:00
|
|
|
if (!coherency_check(ro_disk, redolog)) {
|
2012-07-21 16:00:46 +04:00
|
|
|
return -1;
|
|
|
|
}
|
2005-12-10 18:02:26 +03:00
|
|
|
|
2012-09-22 14:04:28 +04:00
|
|
|
BX_INFO(("'undoable' disk opened: ro-file is '%s', redolog is '%s'", pathname, redolog_name));
|
2005-12-10 18:02:26 +03:00
|
|
|
|
2006-06-09 00:32:00 +04:00
|
|
|
return 0;
|
2005-12-10 18:02:26 +03:00
|
|
|
}
|
|
|
|
|
2012-07-21 16:00:46 +04:00
|
|
|
void undoable_image_t::close()
|
2005-12-10 18:02:26 +03:00
|
|
|
{
|
2006-06-09 00:32:00 +04:00
|
|
|
redolog->close();
|
|
|
|
ro_disk->close();
|
2005-12-10 18:02:26 +03:00
|
|
|
|
2012-09-22 14:04:28 +04:00
|
|
|
if (redolog_name != NULL)
|
2006-06-09 00:32:00 +04:00
|
|
|
free(redolog_name);
|
2005-12-10 18:02:26 +03:00
|
|
|
}
|
|
|
|
|
2006-06-09 00:32:00 +04:00
|
|
|
Bit64s undoable_image_t::lseek(Bit64s offset, int whence)
|
2005-12-10 18:02:26 +03:00
|
|
|
{
|
2006-06-09 00:32:00 +04:00
|
|
|
redolog->lseek(offset, whence);
|
2006-11-18 14:51:07 +03:00
|
|
|
return ro_disk->lseek(offset, whence);
|
2005-12-10 18:02:26 +03:00
|
|
|
}
|
|
|
|
|
2006-06-09 00:32:00 +04:00
|
|
|
ssize_t undoable_image_t::read(void* buf, size_t count)
|
2005-12-10 18:02:26 +03:00
|
|
|
{
|
2011-01-07 21:35:34 +03:00
|
|
|
size_t n = 0;
|
|
|
|
ssize_t ret = 0;
|
|
|
|
|
|
|
|
while (n < count) {
|
|
|
|
if ((size_t)redolog->read((char*) buf, 512) != 512) {
|
|
|
|
ret = ro_disk->read((char*) buf, 512);
|
|
|
|
if (ret < 0) break;
|
|
|
|
}
|
|
|
|
n += 512;
|
|
|
|
}
|
|
|
|
return (ret < 0) ? ret : count;
|
2005-12-10 18:02:26 +03:00
|
|
|
}
|
|
|
|
|
2006-06-09 00:32:00 +04:00
|
|
|
ssize_t undoable_image_t::write(const void* buf, size_t count)
|
2005-12-10 18:02:26 +03:00
|
|
|
{
|
2011-01-07 21:35:34 +03:00
|
|
|
size_t n = 0;
|
|
|
|
ssize_t ret = 0;
|
|
|
|
|
|
|
|
while (n < count) {
|
|
|
|
ret = redolog->write((char*) buf, 512);
|
|
|
|
if (ret < 0) break;
|
|
|
|
n += 512;
|
|
|
|
}
|
|
|
|
return (ret < 0) ? ret : count;
|
2005-12-10 18:02:26 +03:00
|
|
|
}
|
|
|
|
|
2012-09-17 23:30:40 +04:00
|
|
|
bx_bool undoable_image_t::save_state(const char *backup_fname)
|
|
|
|
{
|
|
|
|
return redolog->save_state(backup_fname);
|
|
|
|
}
|
|
|
|
|
2012-09-22 00:25:23 +04:00
|
|
|
void undoable_image_t::restore_state(const char *backup_fname)
|
|
|
|
{
|
|
|
|
redolog_t *temp_redolog = new redolog_t();
|
2012-09-22 14:04:28 +04:00
|
|
|
if (temp_redolog->open(backup_fname, REDOLOG_SUBTYPE_UNDOABLE) < 0) {
|
2012-09-22 00:25:23 +04:00
|
|
|
delete temp_redolog;
|
|
|
|
BX_PANIC(("Can't open redolog backup '%s'", backup_fname));
|
|
|
|
return;
|
|
|
|
} else {
|
|
|
|
if (!coherency_check(ro_disk, temp_redolog)) {
|
|
|
|
delete temp_redolog;
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
delete temp_redolog;
|
|
|
|
}
|
2012-09-22 14:04:28 +04:00
|
|
|
redolog->close();
|
|
|
|
if (!hdimage_copy_file(backup_fname, redolog_name)) {
|
|
|
|
BX_PANIC(("Failed to restore redolog '%s'", redolog_name));
|
|
|
|
} else {
|
|
|
|
if (redolog->open(redolog_name, REDOLOG_SUBTYPE_UNDOABLE) < 0) {
|
|
|
|
BX_PANIC(("Can't open restored redolog '%s'", redolog_name));
|
|
|
|
}
|
|
|
|
}
|
2012-09-22 00:25:23 +04:00
|
|
|
}
|
|
|
|
|
2005-12-10 18:02:26 +03:00
|
|
|
/*** volatile_image_t function definitions ***/
|
|
|
|
|
2006-06-09 00:32:00 +04:00
|
|
|
volatile_image_t::volatile_image_t(const char* _redolog_name)
|
2005-12-10 18:02:26 +03:00
|
|
|
{
|
2006-06-09 00:32:00 +04:00
|
|
|
redolog = new redolog_t();
|
|
|
|
ro_disk = new default_image_t();
|
|
|
|
redolog_temp = NULL;
|
|
|
|
redolog_name = NULL;
|
|
|
|
if (_redolog_name != NULL) {
|
|
|
|
if (strcmp(_redolog_name,"") != 0) {
|
|
|
|
redolog_name = strdup(_redolog_name);
|
|
|
|
}
|
|
|
|
}
|
2005-12-10 18:02:26 +03:00
|
|
|
}
|
|
|
|
|
2007-03-10 15:53:54 +03:00
|
|
|
volatile_image_t::~volatile_image_t()
|
|
|
|
{
|
|
|
|
delete redolog;
|
|
|
|
delete ro_disk;
|
|
|
|
}
|
|
|
|
|
2006-06-09 00:32:00 +04:00
|
|
|
int volatile_image_t::open(const char* pathname)
|
2005-12-10 18:02:26 +03:00
|
|
|
{
|
2006-06-09 00:32:00 +04:00
|
|
|
int filedes;
|
|
|
|
const char *logname=NULL;
|
2012-09-18 23:00:25 +04:00
|
|
|
Bit32u timestamp;
|
2005-12-10 18:02:26 +03:00
|
|
|
|
2006-06-09 00:32:00 +04:00
|
|
|
if (ro_disk->open(pathname, O_RDONLY)<0)
|
|
|
|
return -1;
|
2005-12-10 18:02:26 +03:00
|
|
|
|
2006-06-09 00:32:00 +04:00
|
|
|
hd_size = ro_disk->hd_size;
|
2008-01-27 01:24:03 +03:00
|
|
|
// if redolog name was set
|
2008-02-16 01:05:43 +03:00
|
|
|
if (redolog_name != NULL) {
|
|
|
|
if (strcmp(redolog_name, "") != 0) {
|
2006-06-09 00:32:00 +04:00
|
|
|
logname = redolog_name;
|
|
|
|
}
|
|
|
|
}
|
2005-12-10 18:02:26 +03:00
|
|
|
|
2006-06-09 00:32:00 +04:00
|
|
|
// otherwise use pathname as template
|
|
|
|
if (logname == NULL) {
|
|
|
|
logname = pathname;
|
|
|
|
}
|
2005-12-10 18:02:26 +03:00
|
|
|
|
2006-06-09 00:32:00 +04:00
|
|
|
redolog_temp = (char*)malloc(strlen(logname) + VOLATILE_REDOLOG_EXTENSION_LENGTH + 1);
|
|
|
|
sprintf (redolog_temp, "%s%s", logname, VOLATILE_REDOLOG_EXTENSION);
|
2005-12-10 18:02:26 +03:00
|
|
|
|
2006-06-09 00:32:00 +04:00
|
|
|
filedes = mkstemp (redolog_temp);
|
2005-12-10 18:02:26 +03:00
|
|
|
|
2006-06-09 00:32:00 +04:00
|
|
|
if (filedes < 0)
|
|
|
|
{
|
|
|
|
BX_PANIC(("Can't create volatile redolog '%s'", redolog_temp));
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
if (redolog->create(filedes, REDOLOG_SUBTYPE_VOLATILE, hd_size) < 0)
|
|
|
|
{
|
|
|
|
BX_PANIC(("Can't create volatile redolog '%s'", redolog_temp));
|
|
|
|
return -1;
|
|
|
|
}
|
2008-01-27 01:24:03 +03:00
|
|
|
|
2005-12-10 18:02:26 +03:00
|
|
|
#if (!defined(WIN32)) && !BX_WITH_MACOS
|
2006-06-09 00:32:00 +04:00
|
|
|
// on unix it is legal to delete an open file
|
|
|
|
unlink(redolog_temp);
|
2005-12-10 18:02:26 +03:00
|
|
|
#endif
|
|
|
|
|
2012-09-18 23:00:25 +04:00
|
|
|
// timestamp required for save/restore support
|
|
|
|
timestamp = ro_disk->get_timestamp();
|
|
|
|
redolog->set_timestamp(timestamp);
|
|
|
|
|
2006-06-09 00:32:00 +04:00
|
|
|
BX_INFO(("'volatile' disk opened: ro-file is '%s', redolog is '%s'", pathname, redolog_temp));
|
2005-12-10 18:02:26 +03:00
|
|
|
|
2006-06-09 00:32:00 +04:00
|
|
|
return 0;
|
2005-12-10 18:02:26 +03:00
|
|
|
}
|
|
|
|
|
2006-06-09 00:32:00 +04:00
|
|
|
void volatile_image_t::close()
|
2005-12-10 18:02:26 +03:00
|
|
|
{
|
2006-06-09 00:32:00 +04:00
|
|
|
redolog->close();
|
|
|
|
ro_disk->close();
|
2005-12-10 18:02:26 +03:00
|
|
|
|
|
|
|
#if defined(WIN32) || BX_WITH_MACOS
|
2006-06-09 00:32:00 +04:00
|
|
|
// on non-unix we have to wait till the file is closed to delete it
|
|
|
|
unlink(redolog_temp);
|
2005-12-10 18:02:26 +03:00
|
|
|
#endif
|
2006-06-09 00:32:00 +04:00
|
|
|
if (redolog_temp!=NULL)
|
|
|
|
free(redolog_temp);
|
2005-12-10 18:02:26 +03:00
|
|
|
|
2006-06-09 00:32:00 +04:00
|
|
|
if (redolog_name!=NULL)
|
|
|
|
free(redolog_name);
|
2005-12-10 18:02:26 +03:00
|
|
|
}
|
|
|
|
|
2006-06-09 00:32:00 +04:00
|
|
|
Bit64s volatile_image_t::lseek(Bit64s offset, int whence)
|
2005-12-10 18:02:26 +03:00
|
|
|
{
|
2006-06-09 00:32:00 +04:00
|
|
|
redolog->lseek(offset, whence);
|
|
|
|
return ro_disk->lseek(offset, whence);
|
2005-12-10 18:02:26 +03:00
|
|
|
}
|
|
|
|
|
2006-06-09 00:32:00 +04:00
|
|
|
ssize_t volatile_image_t::read(void* buf, size_t count)
|
2005-12-10 18:02:26 +03:00
|
|
|
{
|
2011-01-07 21:35:34 +03:00
|
|
|
size_t n = 0;
|
|
|
|
ssize_t ret = 0;
|
|
|
|
|
|
|
|
while (n < count) {
|
|
|
|
if ((size_t)redolog->read((char*) buf, 512) != 512) {
|
|
|
|
ret = ro_disk->read((char*) buf, 512);
|
|
|
|
if (ret < 0) break;
|
|
|
|
}
|
|
|
|
n += 512;
|
|
|
|
}
|
|
|
|
return (ret < 0) ? ret : count;
|
2005-12-10 18:02:26 +03:00
|
|
|
}
|
|
|
|
|
2006-06-09 00:32:00 +04:00
|
|
|
ssize_t volatile_image_t::write(const void* buf, size_t count)
|
2005-12-10 18:02:26 +03:00
|
|
|
{
|
2011-01-07 21:35:34 +03:00
|
|
|
size_t n = 0;
|
|
|
|
ssize_t ret = 0;
|
|
|
|
|
|
|
|
while (n < count) {
|
|
|
|
ret = redolog->write((char*) buf, 512);
|
|
|
|
if (ret < 0) break;
|
|
|
|
n += 512;
|
|
|
|
}
|
|
|
|
return (ret < 0) ? ret : count;
|
2005-12-10 18:02:26 +03:00
|
|
|
}
|
2012-09-17 23:30:40 +04:00
|
|
|
|
|
|
|
bx_bool volatile_image_t::save_state(const char *backup_fname)
|
|
|
|
{
|
|
|
|
return redolog->save_state(backup_fname);
|
|
|
|
}
|
2012-09-22 00:25:23 +04:00
|
|
|
|
|
|
|
void volatile_image_t::restore_state(const char *backup_fname)
|
|
|
|
{
|
|
|
|
redolog_t *temp_redolog = new redolog_t();
|
2012-09-22 14:04:28 +04:00
|
|
|
if (temp_redolog->open(backup_fname, REDOLOG_SUBTYPE_VOLATILE) < 0) {
|
2012-09-22 00:25:23 +04:00
|
|
|
delete temp_redolog;
|
|
|
|
BX_PANIC(("Can't open redolog backup '%s'", backup_fname));
|
|
|
|
return;
|
|
|
|
} else {
|
|
|
|
if (!coherency_check(ro_disk, temp_redolog)) {
|
|
|
|
delete temp_redolog;
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
delete temp_redolog;
|
|
|
|
}
|
|
|
|
BX_ERROR(("volatile_image_t::restore_state(): UNIMPLEMENTED"));
|
|
|
|
}
|