From 49ffe1ae9125fec4dbe24ddfccb666f4c17dc7df Mon Sep 17 00:00:00 2001 From: Enrico Scholz Date: Fri, 18 Mar 2005 00:21:28 +0000 Subject: [PATCH] implemented copyReg() with mmap(2) instead of read(2)+write(2) sequences git-svn-id: http://svn.linux-vserver.org/svn/util-vserver/trunk@1916 94cd875c-1c1d-0410-91d2-eb244daf1a30 --- util-vserver/lib_internal/unify-copy.c | 82 +++++++++++++++++++++++++++++++++- 1 file changed, 80 insertions(+), 2 deletions(-) diff --git a/util-vserver/lib_internal/unify-copy.c b/util-vserver/lib_internal/unify-copy.c index 554c077..0264723 100644 --- a/util-vserver/lib_internal/unify-copy.c +++ b/util-vserver/lib_internal/unify-copy.c @@ -21,14 +21,22 @@ #endif #include "unify.h" -#include +#include "util.h" + #include #include #include +#include +#include +#include +#include #define ENSC_WRAPPERS_IO 1 #include + //#define MMAP_BLOCKSIZE 0x10000000 +#define MMAP_BLOCKSIZE 0x4000 + static inline bool verifySource(int fd, struct stat const *exp_stat) { @@ -58,6 +66,68 @@ copyLnk(char const *src, char const *dst) } } +static jmp_buf bus_error_restore; +static volatile sig_atomic_t bus_error; + +static void +handlerSIGBUS(int UNUSED num) +{ + bus_error = 1; + longjmp(bus_error_restore, 1); +} + +static UNUSED bool +copyMMap(int in_fd, int out_fd) +{ + off_t in_len = lseek(in_fd, 0, SEEK_END); + void volatile const *in_buf = 0; + void volatile *out_buf = 0; + + volatile loff_t in_size = 0; + volatile loff_t out_size = 0; + volatile bool res = false; + + if (in_len==-1) return false; + if (in_len>0 && + (lseek(out_fd, in_len-1, SEEK_SET)==-1 || + write(out_fd, "\0", 1)!=1)) // create sparse file + return false; + + bus_error = 0; + if (setjmp(bus_error_restore)==0) { + off_t offset = 0; + + while (offset < in_len) { + in_size = in_len - offset; + if (in_size > MMAP_BLOCKSIZE) in_size = MMAP_BLOCKSIZE; + + in_buf = mmap(0, in_size, PROT_READ, MAP_SHARED, in_fd, offset); + if (in_buf==0) goto out; + + out_size = in_size; + out_buf = mmap(0, out_size, PROT_WRITE, MAP_SHARED, out_fd, offset); + if (out_buf==0) goto out; + + offset += in_size; + madvise(const_cast(void *)(in_buf), in_size, MADV_SEQUENTIAL); + madvise(out_buf, out_size, MADV_SEQUENTIAL); + + memcpy(out_buf, in_buf, in_size); + + munmap(const_cast(void *)(in_buf), in_size); in_buf = 0; + munmap(out_buf, out_size); out_buf = 0; + } + + res = true; + } + + out: + if (in_buf!=0) munmap(const_cast(void *)(in_buf), in_size); + if (out_buf!=0) munmap(out_buf, out_size); + + return res; +} + static inline bool copyReg(char const *src, struct stat const *src_stat, char const *dst) @@ -69,6 +139,7 @@ copyReg(char const *src, struct stat const *src_stat, if (in_fd==-1 || out_fd==-1 || !verifySource(in_fd, src_stat)) goto err; +#if 0 for (;;) { char buf[2048]; ssize_t l = read(in_fd, buf, sizeof buf); @@ -78,7 +149,14 @@ copyReg(char const *src, struct stat const *src_stat, } res = true; - +#else + void (*old_handler)(int) = signal(SIGBUS, handlerSIGBUS); + + res = copyMMap(in_fd, out_fd); + + signal(SIGBUS, old_handler); +#endif + err: if (out_fd!=-1 && close(out_fd)==-1) res=false; if (in_fd!=-1 && close(in_fd)==-1) res=false; -- 1.8.1.5