summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorjdike <jdike>2003-06-05 19:54:35 +0000
committerjdike <jdike>2003-06-05 19:54:35 +0000
commit7771f218836973c48f042b52fc08cdcffbf987c1 (patch)
tree340204918d070f876d8f7d71d91727165e553e8e
parent8aab25f7247e784e6bff78cc4bd049fd8cde8fc7 (diff)
downloaduml-history-7771f218836973c48f042b52fc08cdcffbf987c1.tar.gz
Split the COW code into separate files which are now shared with uml_moo.
-rw-r--r--arch/um/drivers/Makefile2
-rw-r--r--arch/um/drivers/cow.h34
-rw-r--r--arch/um/drivers/cow_sys.h48
-rw-r--r--arch/um/drivers/cow_user.c287
-rw-r--r--arch/um/drivers/ubd_user.c274
5 files changed, 380 insertions, 265 deletions
diff --git a/arch/um/drivers/Makefile b/arch/um/drivers/Makefile
index 3e79b29..06f8a92 100644
--- a/arch/um/drivers/Makefile
+++ b/arch/um/drivers/Makefile
@@ -18,7 +18,7 @@ pcap-objs := pcap_kern.o pcap_user.o -lpcap -L/usr/lib
net-objs := net_kern.o net_user.o
mconsole-objs := mconsole_kern.o mconsole_user.o
hostaudio-objs := hostaudio_kern.o hostaudio_user.o
-ubd-objs := ubd_kern.o ubd_user.o
+ubd-objs := ubd_kern.o ubd_user.o cow_user.o
port-objs := port_kern.o port_user.o
harddog-objs := harddog_kern.o harddog_user.o
diff --git a/arch/um/drivers/cow.h b/arch/um/drivers/cow.h
new file mode 100644
index 0000000..e354d28
--- /dev/null
+++ b/arch/um/drivers/cow.h
@@ -0,0 +1,34 @@
+#ifndef __COW_H__
+#define __COW_H__
+
+#include <asm/types.h>
+
+#if __BYTE_ORDER == __BIG_ENDIAN
+# define ntohll(x) (x)
+# define htonll(x) (x)
+#elif __BYTE_ORDER == __LITTLE_ENDIAN
+# define ntohll(x) bswap_64(x)
+# define htonll(x) bswap_64(x)
+#else
+#error "__BYTE_ORDER not defined"
+#endif
+
+extern int init_cow_file(int fd, char *cow_file, char *backing_file,
+ int sectorsize, int *bitmap_offset_out,
+ unsigned long *bitmap_len_out, int *data_offset_out);
+extern int read_cow_header(int fd, __u32 *magic_out, char **backing_file_out,
+ time_t *mtime_out, __u64 *size_out,
+ int *sectorsize_out, int *bitmap_offset_out);
+extern int write_cow_header(char *cow_file, int fd, char *backing_file,
+ int sectorsize, long long *size);
+extern void cow_sizes(__u64 size, int sectorsize, int bitmap_offset,
+ unsigned long *bitmap_len_out, int *data_offset_out);
+
+#endif
+
+/*
+ * ---------------------------------------------------------------------------
+ * Local variables:
+ * c-file-style: "linux"
+ * End:
+ */
diff --git a/arch/um/drivers/cow_sys.h b/arch/um/drivers/cow_sys.h
new file mode 100644
index 0000000..ce251f0
--- /dev/null
+++ b/arch/um/drivers/cow_sys.h
@@ -0,0 +1,48 @@
+#ifndef __COW_SYS_H__
+#define __COW_SYS_H__
+
+#include "kern_util.h"
+#include "user_util.h"
+#include "os.h"
+#include "user.h"
+
+static inline void *cow_malloc(int size)
+{
+ return(um_kmalloc(size));
+}
+
+static inline void cow_free(void *ptr)
+{
+ kfree(ptr);
+}
+
+#define cow_printf printk
+
+static inline char *cow_strdup(char *str)
+{
+ return(uml_strdup(str));
+}
+
+static inline int cow_seek_file(int fd, __u64 offset)
+{
+ return(os_seek_file(fd, offset));
+}
+
+static inline int cow_file_size(char *file, __u64 *size_out)
+{
+ return(os_file_size(file, size_out));
+}
+
+static inline int cow_write_file(int fd, char *buf, int size)
+{
+ return(os_write_file(fd, buf, size));
+}
+
+#endif
+
+/*
+ * ---------------------------------------------------------------------------
+ * Local variables:
+ * c-file-style: "linux"
+ * End:
+ */
diff --git a/arch/um/drivers/cow_user.c b/arch/um/drivers/cow_user.c
new file mode 100644
index 0000000..d3ed767
--- /dev/null
+++ b/arch/um/drivers/cow_user.c
@@ -0,0 +1,287 @@
+#include <stddef.h>
+#include <string.h>
+#include <errno.h>
+#include <unistd.h>
+#include <byteswap.h>
+#include <sys/stat.h>
+#include <sys/time.h>
+#include <sys/param.h>
+#include <netinet/in.h>
+
+#include "cow.h"
+#include "cow_sys.h"
+
+#define PATH_LEN_V1 256
+
+struct cow_header_v1 {
+ int magic;
+ int version;
+ char backing_file[PATH_LEN_V1];
+ time_t mtime;
+ __u64 size;
+ int sectorsize;
+};
+
+#define PATH_LEN_V2 MAXPATHLEN
+
+struct cow_header_v2 {
+ unsigned long magic;
+ unsigned long version;
+ char backing_file[PATH_LEN_V2];
+ time_t mtime;
+ __u64 size;
+ int sectorsize;
+};
+
+union cow_header {
+ struct cow_header_v1 v1;
+ struct cow_header_v2 v2;
+};
+
+#define COW_MAGIC 0x4f4f4f4d /* MOOO */
+#define COW_VERSION 2
+
+void cow_sizes(__u64 size, int sectorsize, int bitmap_offset,
+ unsigned long *bitmap_len_out, int *data_offset_out)
+{
+ *bitmap_len_out = (size + sectorsize - 1) / (8 * sectorsize);
+
+ *data_offset_out = bitmap_offset + *bitmap_len_out;
+ *data_offset_out = (*data_offset_out + sectorsize - 1) / sectorsize;
+ *data_offset_out *= sectorsize;
+}
+
+static int absolutize(char *to, int size, char *from)
+{
+ char save_cwd[256], *slash;
+ int remaining;
+
+ if(getcwd(save_cwd, sizeof(save_cwd)) == NULL) {
+ cow_printf("absolutize : unable to get cwd - errno = %d\n",
+ errno);
+ return(-1);
+ }
+ slash = strrchr(from, '/');
+ if(slash != NULL){
+ *slash = '\0';
+ if(chdir(from)){
+ *slash = '/';
+ cow_printf("absolutize : Can't cd to '%s' - "
+ "errno = %d\n", from, errno);
+ return(-1);
+ }
+ *slash = '/';
+ if(getcwd(to, size) == NULL){
+ cow_printf("absolutize : unable to get cwd of '%s' - "
+ "errno = %d\n", from, errno);
+ return(-1);
+ }
+ remaining = size - strlen(to);
+ if(strlen(slash) + 1 > remaining){
+ cow_printf("absolutize : unable to fit '%s' into %d "
+ "chars\n", from, size);
+ return(-1);
+ }
+ strcat(to, slash);
+ }
+ else {
+ if(strlen(save_cwd) + 1 + strlen(from) + 1 > size){
+ cow_printf("absolutize : unable to fit '%s' into %d "
+ "chars\n", from, size);
+ return(-1);
+ }
+ strcpy(to, save_cwd);
+ strcat(to, "/");
+ strcat(to, from);
+ }
+ chdir(save_cwd);
+ return(0);
+}
+
+int write_cow_header(char *cow_file, int fd, char *backing_file,
+ int sectorsize, long long *size)
+{
+ struct cow_header_v2 *header;
+ struct stat64 buf;
+ int err;
+
+ err = cow_seek_file(fd, 0);
+ if(err != 0){
+ cow_printf("write_cow_header - lseek failed, errno = %d\n",
+ errno);
+ return(-errno);
+ }
+
+ err = -ENOMEM;
+ header = cow_malloc(sizeof(*header));
+ if(header == NULL){
+ cow_printf("Failed to allocate COW V2 header\n");
+ goto out;
+ }
+ header->magic = htonl(COW_MAGIC);
+ header->version = htonl(COW_VERSION);
+
+ err = -EINVAL;
+ if(strlen(backing_file) > sizeof(header->backing_file) - 1){
+ cow_printf("Backing file name \"%s\" is too long - names are "
+ "limited to %d characters\n", backing_file,
+ sizeof(header->backing_file) - 1);
+ goto out_free;
+ }
+
+ if(absolutize(header->backing_file, sizeof(header->backing_file),
+ backing_file))
+ goto out_free;
+
+ err = stat64(header->backing_file, &buf);
+ if(err < 0){
+ cow_printf("Stat of backing file '%s' failed, errno = %d\n",
+ header->backing_file, errno);
+ err = -errno;
+ goto out_free;
+ }
+
+ err = cow_file_size(header->backing_file, size);
+ if(err){
+ cow_printf("Couldn't get size of backing file '%s', "
+ "errno = %d\n", header->backing_file, -*size);
+ goto out_free;
+ }
+
+ header->mtime = htonl(buf.st_mtime);
+ header->size = htonll(*size);
+ header->sectorsize = htonl(sectorsize);
+
+ err = write(fd, header, sizeof(*header));
+ if(err != sizeof(*header)){
+ cow_printf("Write of header to new COW file '%s' failed, "
+ "errno = %d\n", cow_file, errno);
+ goto out_free;
+ }
+ err = 0;
+ out_free:
+ cow_free(header);
+ out:
+ return(err);
+}
+
+int read_cow_header(int fd, __u32 *magic_out, char **backing_file_out,
+ time_t *mtime_out, __u64 *size_out,
+ int *sectorsize_out, int *bitmap_offset_out)
+{
+ union cow_header *header;
+ char *file;
+ int err, n;
+ unsigned long version, magic;
+
+ header = cow_malloc(sizeof(*header));
+ if(header == NULL){
+ cow_printf("read_cow_header - Failed to allocate header\n");
+ return(-ENOMEM);
+ }
+ err = -EINVAL;
+ n = read(fd, header, sizeof(*header));
+ if(n < offsetof(typeof(header->v1), backing_file)){
+ cow_printf("read_cow_header - short header\n");
+ goto out;
+ }
+
+ magic = header->v1.magic;
+ if(magic == COW_MAGIC) {
+ version = header->v1.version;
+ }
+ else if(magic == ntohl(COW_MAGIC)){
+ version = ntohl(header->v1.version);
+ }
+ else goto out;
+
+ *magic_out = COW_MAGIC;
+
+ if(version == 1){
+ if(n < sizeof(header->v1)){
+ cow_printf("read_cow_header - failed to read V1 "
+ "header\n");
+ goto out;
+ }
+ *mtime_out = header->v1.mtime;
+ *size_out = header->v1.size;
+ *sectorsize_out = header->v1.sectorsize;
+ *bitmap_offset_out = sizeof(header->v1);
+ file = header->v1.backing_file;
+ }
+ else if(version == 2){
+ if(n < sizeof(header->v2)){
+ cow_printf("read_cow_header - failed to read V2 "
+ "header\n");
+ goto out;
+ }
+ *mtime_out = ntohl(header->v2.mtime);
+ *size_out = ntohll(header->v2.size);
+ *sectorsize_out = ntohl(header->v2.sectorsize);
+ *bitmap_offset_out = sizeof(header->v2);
+ file = header->v2.backing_file;
+ }
+ else {
+ cow_printf("read_cow_header - invalid COW version\n");
+ goto out;
+ }
+ err = -ENOMEM;
+ *backing_file_out = cow_strdup(file);
+ if(*backing_file_out == NULL){
+ cow_printf("read_cow_header - failed to allocate backing "
+ "file\n");
+ goto out;
+ }
+ err = 0;
+ out:
+ cow_free(header);
+ return(err);
+}
+
+int init_cow_file(int fd, char *cow_file, char *backing_file, int sectorsize,
+ int *bitmap_offset_out, unsigned long *bitmap_len_out,
+ int *data_offset_out)
+{
+ __u64 size, offset;
+ char zero = 0;
+ int err;
+
+ err = write_cow_header(cow_file, fd, backing_file, sectorsize, &size);
+ if(err)
+ goto out;
+
+ cow_sizes(size, sectorsize, sizeof(struct cow_header_v2),
+ bitmap_len_out, data_offset_out);
+ *bitmap_offset_out = sizeof(struct cow_header_v2);
+
+ offset = *data_offset_out + size - sizeof(zero);
+ err = cow_seek_file(fd, offset);
+ if(err != 0){
+ cow_printf("cow bitmap lseek failed : errno = %d\n", errno);
+ goto out;
+ }
+
+ /* does not really matter how much we write it is just to set EOF
+ * this also sets the entire COW bitmap
+ * to zero without having to allocate it
+ */
+ err = cow_write_file(fd, &zero, sizeof(zero));
+ if(err != sizeof(zero)){
+ err = -EINVAL;
+ cow_printf("Write of bitmap to new COW file '%s' failed, "
+ "errno = %d\n", cow_file, errno);
+ goto out;
+ }
+
+ return(0);
+
+ out:
+ return(err);
+}
+
+/*
+ * ---------------------------------------------------------------------------
+ * Local variables:
+ * c-file-style: "linux"
+ * End:
+ */
diff --git a/arch/um/drivers/ubd_user.c b/arch/um/drivers/ubd_user.c
index 70ecf82..81b8437 100644
--- a/arch/um/drivers/ubd_user.c
+++ b/arch/um/drivers/ubd_user.c
@@ -24,128 +24,10 @@
#include "user.h"
#include "ubd_user.h"
#include "os.h"
+#include "cow.h"
#include <endian.h>
#include <byteswap.h>
-#if __BYTE_ORDER == __BIG_ENDIAN
-# define ntohll(x) (x)
-# define htonll(x) (x)
-#elif __BYTE_ORDER == __LITTLE_ENDIAN
-# define ntohll(x) bswap_64(x)
-# define htonll(x) bswap_64(x)
-#else
-#error "__BYTE_ORDER not defined"
-#endif
-
-#define PATH_LEN_V1 256
-
-struct cow_header_v1 {
- int magic;
- int version;
- char backing_file[PATH_LEN_V1];
- time_t mtime;
- __u64 size;
- int sectorsize;
-};
-
-#define PATH_LEN_V2 MAXPATHLEN
-
-struct cow_header_v2 {
- unsigned long magic;
- unsigned long version;
- char backing_file[PATH_LEN_V2];
- time_t mtime;
- __u64 size;
- int sectorsize;
-};
-
-union cow_header {
- struct cow_header_v1 v1;
- struct cow_header_v2 v2;
-};
-
-#define COW_MAGIC 0x4f4f4f4d /* MOOO */
-#define COW_VERSION 2
-
-static void sizes(__u64 size, int sectorsize, int bitmap_offset,
- unsigned long *bitmap_len_out, int *data_offset_out)
-{
- *bitmap_len_out = (size + sectorsize - 1) / (8 * sectorsize);
-
- *data_offset_out = bitmap_offset + *bitmap_len_out;
- *data_offset_out = (*data_offset_out + sectorsize - 1) / sectorsize;
- *data_offset_out *= sectorsize;
-}
-
-static int read_cow_header(int fd, int *magic_out, char **backing_file_out,
- time_t *mtime_out, __u64 *size_out,
- int *sectorsize_out, int *bitmap_offset_out)
-{
- union cow_header *header;
- char *file;
- int err, n;
- unsigned long version, magic;
-
- header = um_kmalloc(sizeof(*header));
- if(header == NULL){
- printk("read_cow_header - Failed to allocate header\n");
- return(-ENOMEM);
- }
- err = -EINVAL;
- n = read(fd, header, sizeof(*header));
- if(n < offsetof(typeof(header->v1), backing_file)){
- printk("read_cow_header - short header\n");
- goto out;
- }
-
- magic = header->v1.magic;
- if(magic == COW_MAGIC) {
- version = header->v1.version;
- }
- else if(magic == ntohl(COW_MAGIC)){
- version = ntohl(header->v1.version);
- }
- else goto out;
-
- *magic_out = COW_MAGIC;
-
- if(version == 1){
- if(n < sizeof(header->v1)){
- printk("read_cow_header - failed to read V1 header\n");
- goto out;
- }
- *mtime_out = header->v1.mtime;
- *size_out = header->v1.size;
- *sectorsize_out = header->v1.sectorsize;
- *bitmap_offset_out = sizeof(header->v1);
- file = header->v1.backing_file;
- }
- else if(version == 2){
- if(n < sizeof(header->v2)){
- printk("read_cow_header - failed to read V2 header\n");
- goto out;
- }
- *mtime_out = ntohl(header->v2.mtime);
- *size_out = ntohll(header->v2.size);
- *sectorsize_out = ntohl(header->v2.sectorsize);
- *bitmap_offset_out = sizeof(header->v2);
- file = header->v2.backing_file;
- }
- else {
- printk("read_cow_header - invalid COW version\n");
- goto out;
- }
- err = -ENOMEM;
- *backing_file_out = uml_strdup(file);
- if(*backing_file_out == NULL){
- printk("read_cow_header - failed to allocate backing file\n");
- goto out;
- }
- err = 0;
- out:
- kfree(header);
- return(err);
-}
static int same_backing_files(char *from_cmdline, char *from_cow, char *cow)
{
@@ -178,6 +60,7 @@ static int backing_file_mismatch(char *file, __u64 size, time_t mtime)
long long actual;
int err;
+ printk("%ld", htonll(size));
if(stat64(file, &buf) < 0){
printk("Failed to stat backing file \"%s\", errno = %d\n",
file, errno);
@@ -215,118 +98,6 @@ int read_cow_bitmap(int fd, void *buf, int offset, int len)
return(0);
}
-static int absolutize(char *to, int size, char *from)
-{
- char save_cwd[256], *slash;
- int remaining;
-
- if(getcwd(save_cwd, sizeof(save_cwd)) == NULL) {
- printk("absolutize : unable to get cwd - errno = %d\n", errno);
- return(-1);
- }
- slash = strrchr(from, '/');
- if(slash != NULL){
- *slash = '\0';
- if(chdir(from)){
- *slash = '/';
- printk("absolutize : Can't cd to '%s' - errno = %d\n",
- from, errno);
- return(-1);
- }
- *slash = '/';
- if(getcwd(to, size) == NULL){
- printk("absolutize : unable to get cwd of '%s' - "
- "errno = %d\n", from, errno);
- return(-1);
- }
- remaining = size - strlen(to);
- if(strlen(slash) + 1 > remaining){
- printk("absolutize : unable to fit '%s' into %d "
- "chars\n", from, size);
- return(-1);
- }
- strcat(to, slash);
- }
- else {
- if(strlen(save_cwd) + 1 + strlen(from) + 1 > size){
- printk("absolutize : unable to fit '%s' into %d "
- "chars\n", from, size);
- return(-1);
- }
- strcpy(to, save_cwd);
- strcat(to, "/");
- strcat(to, from);
- }
- chdir(save_cwd);
- return(0);
-}
-
-static int write_cow_header(char *cow_file, int fd, char *backing_file,
- int sectorsize, long long *size)
-{
- struct cow_header_v2 *header;
- struct stat64 buf;
- int err;
-
- err = os_seek_file(fd, 0);
- if(err != 0){
- printk("write_cow_header - lseek failed, errno = %d\n", errno);
- return(-errno);
- }
-
- err = -ENOMEM;
- header = um_kmalloc(sizeof(*header));
- if(header == NULL){
- printk("Failed to allocate COW V2 header\n");
- goto out;
- }
- header->magic = htonl(COW_MAGIC);
- header->version = htonl(COW_VERSION);
-
- err = -EINVAL;
- if(strlen(backing_file) > sizeof(header->backing_file) - 1){
- printk("Backing file name \"%s\" is too long - names are "
- "limited to %d characters\n", backing_file,
- sizeof(header->backing_file) - 1);
- goto out_free;
- }
-
- if(absolutize(header->backing_file, sizeof(header->backing_file),
- backing_file))
- goto out_free;
-
- err = stat64(header->backing_file, &buf);
- if(err < 0){
- printk("Stat of backing file '%s' failed, errno = %d\n",
- header->backing_file, errno);
- err = -errno;
- goto out_free;
- }
-
- err = os_file_size(header->backing_file, size);
- if(err){
- printk("Couldn't get size of backing file '%s', errno = %d\n",
- header->backing_file, -*size);
- goto out_free;
- }
-
- header->mtime = htonl(buf.st_mtime);
- header->size = htonll(*size);
- header->sectorsize = htonl(sectorsize);
-
- err = write(fd, header, sizeof(*header));
- if(err != sizeof(*header)){
- printk("Write of header to new COW file '%s' failed, "
- "errno = %d\n", cow_file, errno);
- goto out_free;
- }
- err = 0;
- out_free:
- kfree(header);
- out:
- return(err);
-}
-
int open_ubd_file(char *file, struct openflags *openflags,
char **backing_file_out, int *bitmap_offset_out,
unsigned long *bitmap_len_out, int *data_offset_out,
@@ -383,8 +154,8 @@ int open_ubd_file(char *file, struct openflags *openflags,
if(err) goto error;
}
- sizes(size, sectorsize, *bitmap_offset_out, bitmap_len_out,
- data_offset_out);
+ cow_sizes(size, sectorsize, *bitmap_offset_out, bitmap_len_out,
+ data_offset_out);
return(fd);
error:
@@ -396,10 +167,7 @@ int create_cow_file(char *cow_file, char *backing_file, struct openflags flags,
int sectorsize, int *bitmap_offset_out,
unsigned long *bitmap_len_out, int *data_offset_out)
{
- __u64 offset;
int err, fd;
- long long size;
- char zero = 0;
flags.c = 1;
fd = open_ubd_file(cow_file, &flags, NULL, NULL, NULL, NULL, NULL);
@@ -410,35 +178,13 @@ int create_cow_file(char *cow_file, char *backing_file, struct openflags flags,
goto out;
}
- err = write_cow_header(cow_file, fd, backing_file, sectorsize, &size);
- if(err) goto out_close;
-
- sizes(size, sectorsize, sizeof(struct cow_header_v2),
- bitmap_len_out, data_offset_out);
- *bitmap_offset_out = sizeof(struct cow_header_v2);
-
- offset = *data_offset_out + size - sizeof(zero);
- err = os_seek_file(fd, offset);
- if(err != 0){
- printk("cow bitmap lseek failed : errno = %d\n", errno);
- goto out_close;
- }
-
- /* does not really matter how much we write it is just to set EOF
- * this also sets the entire COW bitmap
- * to zero without having to allocate it
- */
- err = os_write_file(fd, &zero, sizeof(zero));
- if(err != sizeof(zero)){
- printk("Write of bitmap to new COW file '%s' failed, "
- "errno = %d\n", cow_file, errno);
- goto out_close;
- }
+ err = init_cow_file(fd, cow_file, backing_file, sectorsize,
+ bitmap_offset_out, bitmap_len_out,
+ data_offset_out);
+ if(!err)
+ return(fd);
- return(fd);
-
- out_close:
- close(fd);
+ os_close_file(fd);
out:
return(err);
}