Implemented lock mechanism for hard disk images (fixes SF bug #605).

- Create a file with image name plus extension ".lock" if an image is opened
  in read/write mode. This file will be deleted after closing the image.
- Check for a lock file before opening an image and fail if it exists.
- Check for a lock file before creating a undoable/volatile redolog file and
  fail if it exists.
This commit is contained in:
Volker Ruppert 2017-01-30 19:08:37 +00:00
parent 124f521797
commit 7fd9194d81
6 changed files with 88 additions and 32 deletions

View File

@ -178,12 +178,30 @@ int bx_write_image(int fd, Bit64s offset, void *buf, int count)
return write(fd, buf, count); return write(fd, buf, count);
} }
int bx_close_image(int fd, const char *pathname)
{
#ifndef BXIMAGE
char lockfn[BX_PATHNAME_LEN];
sprintf(lockfn, "%s.lock", pathname);
if (access(lockfn, F_OK) == 0) {
unlink(lockfn);
}
#endif
return ::close(fd);
}
#ifndef WIN32 #ifndef WIN32
int hdimage_open_file(const char *pathname, int flags, Bit64u *fsize, time_t *mtime) int hdimage_open_file(const char *pathname, int flags, Bit64u *fsize, time_t *mtime)
#else #else
int hdimage_open_file(const char *pathname, int flags, Bit64u *fsize, FILETIME *mtime) int hdimage_open_file(const char *pathname, int flags, Bit64u *fsize, FILETIME *mtime)
#endif #endif
{ {
#ifndef BXIMAGE
char lockfn[BX_PATHNAME_LEN];
int lockfd;
#endif
#ifdef WIN32 #ifdef WIN32
if (fsize != NULL) { if (fsize != NULL) {
HANDLE hFile = CreateFile(pathname, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_FLAG_RANDOM_ACCESS, NULL); HANDLE hFile = CreateFile(pathname, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_FLAG_RANDOM_ACCESS, NULL);
@ -205,6 +223,17 @@ int hdimage_open_file(const char *pathname, int flags, Bit64u *fsize, FILETIME *
} }
#endif #endif
#ifndef BXIMAGE
sprintf(lockfn, "%s.lock", pathname);
lockfd = ::open(lockfn, O_RDONLY);
if (lockfd >= 0) {
// Opening image must fail if lock file exists.
::close(lockfd);
BX_ERROR(("image locked: '%s'", pathname));
return -1;
}
#endif
int fd = ::open(pathname, flags int fd = ::open(pathname, flags
#ifdef O_BINARY #ifdef O_BINARY
| O_BINARY | O_BINARY
@ -235,6 +264,19 @@ int hdimage_open_file(const char *pathname, int flags, Bit64u *fsize, FILETIME *
*mtime = stat_buf.st_mtime; *mtime = stat_buf.st_mtime;
} }
} }
#endif
#ifndef BXIMAGE
if ((flags & O_ACCMODE) != O_RDONLY) {
lockfd = ::open(lockfn, O_CREAT | O_RDWR
#ifdef O_BINARY
| O_BINARY
#endif
, S_IWUSR | S_IRUSR | S_IRGRP | S_IWGRP);
if (lockfd >= 0) {
// lock this image
::close(lockfd);
}
}
#endif #endif
return fd; return fd;
} }
@ -488,7 +530,7 @@ int flat_image_t::open(const char* _pathname, int flags)
void flat_image_t::close() void flat_image_t::close()
{ {
if (fd > -1) { if (fd > -1) {
::close(fd); bx_close_image(fd, pathname);
} }
} }
@ -569,11 +611,11 @@ int concat_image_t::open(const char* _pathname0, int flags)
{ {
UNUSED(flags); UNUSED(flags);
pathname0 = _pathname0; pathname0 = _pathname0;
char *pathname = strdup(pathname0); char *pathname1 = strdup(pathname0);
BX_DEBUG(("concat_image_t::open")); BX_DEBUG(("concat_image_t::open"));
Bit64s start_offset = 0; Bit64s start_offset = 0;
for (int i=0; i<BX_CONCAT_MAX_IMAGES; i++) { for (int i=0; i<BX_CONCAT_MAX_IMAGES; i++) {
fd_table[i] = hdimage_open_file(pathname, flags, &length_table[i], NULL); fd_table[i] = hdimage_open_file(pathname1, flags, &length_table[i], NULL);
if (fd_table[i] < 0) { if (fd_table[i] < 0) {
// open failed. // open failed.
// if no FD was opened successfully, return -1 (fail). // if no FD was opened successfully, return -1 (fail).
@ -583,7 +625,7 @@ int concat_image_t::open(const char* _pathname0, int flags)
maxfd = i; maxfd = i;
break; break;
} }
BX_INFO(("concat_image: open image #%d: '%s', (" FMT_LL "u bytes)", i, pathname, length_table[i])); BX_INFO(("concat_image: open image #%d: '%s', (" FMT_LL "u bytes)", i, pathname1, length_table[i]));
struct stat stat_buf; struct stat stat_buf;
int ret = fstat(fd_table[i], &stat_buf); int ret = fstat(fd_table[i], &stat_buf);
if (ret) { if (ret) {
@ -599,9 +641,9 @@ int concat_image_t::open(const char* _pathname0, int flags)
} }
start_offset_table[i] = start_offset; start_offset_table[i] = start_offset;
start_offset += length_table[i]; start_offset += length_table[i];
increment_string(pathname); increment_string(pathname1);
} }
free(pathname); free(pathname1);
// start up with first image selected // start up with first image selected
total_offset = 0; total_offset = 0;
index = 0; index = 0;
@ -616,11 +658,14 @@ int concat_image_t::open(const char* _pathname0, int flags)
void concat_image_t::close() void concat_image_t::close()
{ {
BX_DEBUG(("concat_image_t.close")); BX_DEBUG(("concat_image_t.close"));
char *pathname1 = strdup(pathname0);
for (int index = 0; index < maxfd; index++) { for (int index = 0; index < maxfd; index++) {
if (fd_table[index] > -1) { if (fd_table[index] > -1) {
::close(fd_table[index]); bx_close_image(fd_table[index], pathname1);
} }
increment_string(pathname1);
} }
free(pathname1);
} }
Bit64s concat_image_t::lseek(Bit64s offset, int whence) Bit64s concat_image_t::lseek(Bit64s offset, int whence)
@ -914,13 +959,8 @@ int sparse_image_t::open(const char* pathname0, int flags)
void sparse_image_t::close() void sparse_image_t::close()
{ {
BX_DEBUG(("concat_image_t.close")); BX_DEBUG(("concat_image_t.close"));
if (pathname != NULL)
{
free(pathname);
}
#ifdef _POSIX_MAPPED_FILES #ifdef _POSIX_MAPPED_FILES
if (mmap_header != NULL) if (mmap_header != NULL) {
{
int ret = munmap(mmap_header, mmap_length); int ret = munmap(mmap_header, mmap_length);
if (ret != 0) if (ret != 0)
BX_INFO(("failed to un-memory map sparse disk file")); BX_INFO(("failed to un-memory map sparse disk file"));
@ -928,14 +968,15 @@ void sparse_image_t::close()
pagetable = NULL; // We didn't malloc it pagetable = NULL; // We didn't malloc it
#endif #endif
if (fd > -1) { if (fd > -1) {
::close(fd); bx_close_image(fd, pathname);
} }
if (pagetable != NULL) if (pathname != NULL) {
{ free(pathname);
}
if (pagetable != NULL) {
delete [] pagetable; delete [] pagetable;
} }
if (parent_image != NULL) if (parent_image != NULL) {
{
delete parent_image; delete parent_image;
} }
} }
@ -1492,6 +1533,15 @@ int redolog_t::make_header(const char* type, Bit64u size)
int redolog_t::create(const char* filename, const char* type, Bit64u size) int redolog_t::create(const char* filename, const char* type, Bit64u size)
{ {
#ifndef BXIMAGE
char lockfn[BX_PATHNAME_LEN];
sprintf(lockfn, "%s.lock", filename);
if (access(lockfn, F_OK) == 0) {
return -1;
}
#endif
BX_INFO(("redolog : creating redolog %s", filename)); BX_INFO(("redolog : creating redolog %s", filename));
int filedes = ::open(filename, O_RDWR | O_CREAT | O_TRUNC int filedes = ::open(filename, O_RDWR | O_CREAT | O_TRUNC
@ -1541,6 +1591,7 @@ int redolog_t::open(const char* filename, const char *type, int flags)
FILETIME mtime; FILETIME mtime;
#endif #endif
pathname = strdup(filename);
fd = hdimage_open_file(filename, flags, &imgsize, &mtime); fd = hdimage_open_file(filename, flags, &imgsize, &mtime);
if (fd < 0) { if (fd < 0) {
BX_INFO(("redolog : could not open image %s", filename)); BX_INFO(("redolog : could not open image %s", filename));
@ -1624,7 +1675,10 @@ int redolog_t::open(const char* filename, const char *type, int flags)
void redolog_t::close() void redolog_t::close()
{ {
if (fd >= 0) if (fd >= 0)
::close(fd); bx_close_image(fd, pathname);
if (pathname != NULL)
free(pathname);
if (catalog != NULL) if (catalog != NULL)
free(catalog); free(catalog);

View File

@ -2,7 +2,7 @@
// $Id$ // $Id$
///////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////
// //
// Copyright (C) 2005-2015 The Bochs Project // Copyright (C) 2005-2017 The Bochs Project
// //
// This library is free software; you can redistribute it and/or // This library is free software; you can redistribute it and/or
// modify it under the terms of the GNU Lesser General Public // modify it under the terms of the GNU Lesser General Public
@ -143,6 +143,7 @@ class redolog_t;
int bx_read_image(int fd, Bit64s offset, void *buf, int count); int bx_read_image(int fd, Bit64s offset, void *buf, int count);
int bx_write_image(int fd, Bit64s offset, void *buf, int count); int bx_write_image(int fd, Bit64s offset, void *buf, int count);
int bx_close_image(int fd, const char *pathname);
#ifndef WIN32 #ifndef WIN32
int hdimage_open_file(const char *pathname, int flags, Bit64u *fsize, time_t *mtime); int hdimage_open_file(const char *pathname, int flags, Bit64u *fsize, time_t *mtime);
#else #else
@ -452,6 +453,7 @@ class redolog_t
private: private:
void print_header(); void print_header();
char *pathname;
int fd; int fd;
redolog_header_t header; // Header is kept in x86 (little) endianness redolog_header_t header; // Header is kept in x86 (little) endianness
Bit32u *catalog; Bit32u *catalog;

View File

@ -10,7 +10,7 @@
* Contact: fys [at] fysnet [dot] net * Contact: fys [at] fysnet [dot] net
* *
* Copyright (C) 2015 Benjamin D Lunt. * Copyright (C) 2015 Benjamin D Lunt.
* Copyright (C) 2006-2016 The Bochs Project * Copyright (C) 2006-2017 The Bochs Project
* *
* This library is free software; you can redistribute it and/or * This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public * modify it under the terms of the GNU Lesser General Public
@ -167,7 +167,7 @@ void vbox_image_t::close()
delete [] mtlb; mtlb = 0; delete [] mtlb; mtlb = 0;
delete [] block_data; block_data = 0; delete [] block_data; block_data = 0;
::close(file_descriptor); bx_close_image(file_descriptor, pathname);
file_descriptor = -1; file_descriptor = -1;
} }

View File

@ -10,7 +10,7 @@
* Contact: snrrrub@yahoo.com * Contact: snrrrub@yahoo.com
* *
* Copyright (C) 2003 Net Integration Technologies, Inc. * Copyright (C) 2003 Net Integration Technologies, Inc.
* Copyright (C) 2003-2015 The Bochs Project * Copyright (C) 2003-2017 The Bochs Project
* *
* This library is free software; you can redistribute it and/or * This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public * modify it under the terms of the GNU Lesser General Public
@ -224,7 +224,7 @@ int vmware3_image_t::open(const char* _pathname, int flags)
return -1; return -1;
} }
::close(file); bx_close_image(file, pathname);
tlb_size = header.tlb_size_sectors * 512; tlb_size = header.tlb_size_sectors * 512;
slb_count = (1 << FL_SHIFT) / tlb_size; slb_count = (1 << FL_SHIFT) / tlb_size;

View File

@ -10,7 +10,7 @@
* Contact: snrrrub@gmail.com * Contact: snrrrub@gmail.com
* *
* Copyright (C) 2006 Sharvil Nanavati. * Copyright (C) 2006 Sharvil Nanavati.
* Copyright (C) 2006-2016 The Bochs Project * Copyright (C) 2006-2017 The Bochs Project
* *
* This library is free software; you can redistribute it and/or * This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public * modify it under the terms of the GNU Lesser General Public
@ -112,7 +112,7 @@ void vmware4_image_t::close()
flush(); flush();
delete [] tlb; tlb = 0; delete [] tlb; tlb = 0;
::close(file_descriptor); bx_close_image(file_descriptor, pathname);
file_descriptor = -1; file_descriptor = -1;
} }

View File

@ -6,7 +6,7 @@
// //
// Copyright (c) 2005 Alex Beregszaszi // Copyright (c) 2005 Alex Beregszaszi
// Copyright (c) 2009 Kevin Wolf <kwolf@suse.de> // Copyright (c) 2009 Kevin Wolf <kwolf@suse.de>
// Copyright (C) 2012-2013 The Bochs Project // Copyright (C) 2012-2017 The Bochs Project
// //
// Permission is hereby granted, free of charge, to any person obtaining a copy // Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal // of this software and associated documentation files (the "Software"), to deal
@ -138,20 +138,20 @@ int vpc_image_t::open(const char* _pathname, int flags)
hd_size = sector_count * 512; hd_size = sector_count * 512;
if (sector_count >= 65535 * 16 * 255) { if (sector_count >= 65535 * 16 * 255) {
::close(fd); bx_close_image(fd, pathname);
return -EFBIG; return -EFBIG;
} }
if (disk_type == VHD_DYNAMIC) { if (disk_type == VHD_DYNAMIC) {
if (bx_read_image(fd, be64_to_cpu(footer->data_offset), buf, HEADER_SIZE) != HEADER_SIZE) { if (bx_read_image(fd, be64_to_cpu(footer->data_offset), buf, HEADER_SIZE) != HEADER_SIZE) {
::close(fd); bx_close_image(fd, pathname);
return -1; return -1;
} }
dyndisk_header = (vhd_dyndisk_header_t*)buf; dyndisk_header = (vhd_dyndisk_header_t*)buf;
if (strncmp((char*)dyndisk_header->magic, "cxsparse", 8)) { if (strncmp((char*)dyndisk_header->magic, "cxsparse", 8)) {
::close(fd); bx_close_image(fd, pathname);
return -1; return -1;
} }
@ -163,7 +163,7 @@ int vpc_image_t::open(const char* _pathname, int flags)
bat_offset = be64_to_cpu(dyndisk_header->table_offset); bat_offset = be64_to_cpu(dyndisk_header->table_offset);
if (bx_read_image(fd, bat_offset, (void*)pagetable, max_table_entries * 4) != (max_table_entries * 4)) { if (bx_read_image(fd, bat_offset, (void*)pagetable, max_table_entries * 4) != (max_table_entries * 4)) {
::close(fd); bx_close_image(fd, pathname);
return -1; return -1;
} }
@ -193,7 +193,7 @@ void vpc_image_t::close(void)
{ {
if (fd > -1) { if (fd > -1) {
delete [] pagetable; delete [] pagetable;
::close(fd); bx_close_image(fd, pathname);
} }
} }