diff options
author | jdike <jdike> | 2003-06-05 19:54:35 +0000 |
---|---|---|
committer | jdike <jdike> | 2003-06-05 19:54:35 +0000 |
commit | 7771f218836973c48f042b52fc08cdcffbf987c1 (patch) | |
tree | 340204918d070f876d8f7d71d91727165e553e8e | |
parent | 8aab25f7247e784e6bff78cc4bd049fd8cde8fc7 (diff) | |
download | uml-history-7771f218836973c48f042b52fc08cdcffbf987c1.tar.gz |
Split the COW code into separate files which are now shared with uml_moo.
-rw-r--r-- | arch/um/drivers/Makefile | 2 | ||||
-rw-r--r-- | arch/um/drivers/cow.h | 34 | ||||
-rw-r--r-- | arch/um/drivers/cow_sys.h | 48 | ||||
-rw-r--r-- | arch/um/drivers/cow_user.c | 287 | ||||
-rw-r--r-- | arch/um/drivers/ubd_user.c | 274 |
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); } |