Hello
When I use the compression with uswsusp, the suspend step take longer than
without. This is in fact because uswsusp write the data synchronously to the
disk. So while it take time to compress the data the disk is idle, and while
it take time to write to disk the processor wait ...
I've hacked a quick'n dirty AIO patch for uswsusp. This is based on glibc aio,
without any special care, you have been warned. The speedup is about 10
seconds ( witout 36 sec, with 24-26 sec ) on my PC (1Gb ram, pentium D 820,
58Mo/s sustained harddisk bandwidth).
I suspect I have done it wrong because I don't know if a process can allocate
memory or spawn new threads (glibc may does this behind my back) while
suspending. But it works here, maybe I'm lucky.
I'm still not entirely happy about this implementation because:
- glibc hide us a lot of works
- the code is not really clean
- The harddisk led is not "always on", so we don't write at maximum speed
- We no more detect write error
So maybe someone more experimented can improve it !
Regards
Couriousous
Index: Makefile
===================================================================
--- Makefile
+++ Makefile 2007-03-19 21:17:23.000000000 +0100
@@ -6,7 +6,7 @@
ARCH:=$(shell uname -m)
CC_FLAGS=-I/usr/local/include
-LD_FLAGS=-L/usr/local/lib
+LD_FLAGS=-L/usr/local/lib -lrt
CFLAGS := -O2 -Wall
Index: suspend.c
===================================================================
--- suspend.c
+++ suspend.c 2007-03-19 21:16:54.000000000 +0100
@@ -33,6 +33,7 @@
#include <signal.h>
#include <termios.h>
#include <getopt.h>
+#include <aio.h>
#ifdef CONFIG_COMPRESS
#include <lzf.h>
#else
@@ -83,6 +84,11 @@
static struct vt_mode orig_vtm;
static int vfd;
+#define NB_AIO 50
+
+static struct aiocb acb[NB_AIO];
+static const struct aiocb *acbl[NB_AIO];
+
static struct config_par parameters[PARAM_NO] = {
{
.name = "snapshot device",
@@ -212,6 +218,14 @@
return error;
}
+void aio_sync(void) {
+ int i;
+ for(i = 0; i < NB_AIO; i++) {
+ const struct aiocb * t[1] = {&(acb[i])};
+ while(aio_suspend(t,1,NULL) < 0);
+ }
+}
+
/**
* write_area - Write data to given swap location.
* @fd: File handle of the resume partition
@@ -220,20 +234,25 @@
* @size: The number of bytes to save
*/
-static int write_area(int fd, void *buf, loff_t offset, unsigned int size)
+static int write_area(int fd, void *buf, loff_t offset, unsigned int size, char *aio_buffer)
{
- int res = -EINVAL;
- ssize_t cnt = 0;
+ int i = 0;
+
+aio_retry:
+ while(aio_suspend(acbl,NB_AIO,NULL) < 0);
+
+ while(aio_error(&(acb[i])) == EINPROGRESS && i < NB_AIO) i++;
- if (offset) {
- if (lseek64(fd, offset, SEEK_SET) == offset)
- cnt = write(fd, buf, size);
- if (cnt == size)
- res = 0;
- else
- res = cnt < 0 ? cnt : -EIO;
+ if(i == NB_AIO) {
+ printf("error while waiting aio ! retrying \n");
+ goto aio_retry;
}
- return res;
+
+ memcpy(aio_buffer + buffer_size*i,buf,size);
+
+ acb[i].aio_nbytes = size;
+ acb[i].aio_offset = offset;
+ return aio_write(&(acb[i]));
}
/*
@@ -244,6 +263,7 @@
struct swap_map_handle {
char *page_buffer;
char *write_buffer;
+ char *aio_buffer;
struct swap_area *areas;
unsigned short areas_per_page;
loff_t *next_swap;
@@ -261,6 +281,7 @@
static int
init_swap_writer(struct swap_map_handle *handle, int dev, int fd, void *buf)
{
+ int i;
if (!buf)
return -EINVAL;
handle->areas = buf;
@@ -269,11 +290,20 @@
handle->next_swap = (loff_t *)(handle->areas + handle->areas_per_page);
handle->page_buffer = (char *)buf + page_size;
handle->write_buffer = handle->page_buffer + page_size;
+ handle->aio_buffer = handle->write_buffer + buffer_size;
#ifdef CONFIG_ENCRYPT
- handle->encrypt_buffer = (unsigned char *)(handle->write_buffer +
- buffer_size);
+ handle->encrypt_buffer = (unsigned char *)(handle->aio_buffer +
+ buffer_size*NB_AIO);
#endif
memset(handle->areas, 0, page_size);
+ memset(acb, 0, sizeof(struct aiocb) * NB_AIO);
+
+ for(i = 0; i < NB_AIO; i++) {
+ acbl[i] = &(acb[i]);
+ acb[i].aio_buf = handle->aio_buffer + i*buffer_size;
+ acb[i].aio_fildes = fd;
+ }
+
handle->cur_swap = get_swap_page(dev);
if (!handle->cur_swap)
return -ENOSPC;
@@ -349,7 +379,7 @@
#endif
if (!error)
error = write_area(handle->fd, src, handle->cur_area.offset,
- handle->cur_area.size);
+ handle->cur_area.size,handle->aio_buffer);
if (error)
return error;
handle->areas[handle->k].offset = handle->cur_area.offset;
@@ -409,7 +439,7 @@
return -ENOSPC;
*handle->next_swap = offset;
error = write_area(handle->fd, handle->areas, handle->cur_swap,
- page_size);
+ page_size,handle->aio_buffer);
if (error)
return error;
memset(handle->areas, 0, page_size);
@@ -431,7 +461,7 @@
if (!error)
/* Save the last swap map page */
error = write_area(handle->fd, handle->areas, handle->cur_swap,
- page_size);
+ page_size,handle->aio_buffer);
return error;
}
@@ -655,6 +685,7 @@
if (compute_checksum)
md5_finish_ctx(&handle.ctx, header->checksum);
}
+ aio_sync();
fsync(resume_fd);
if (!error) {
struct timeval end;
@@ -663,7 +694,7 @@
header->writeout_time = end.tv_usec / 1000000.0 + end.tv_sec;
}
if (!error)
- error = write_area(resume_fd, header, start, page_size);
+ error = write_area(resume_fd, header, start, page_size,handle.aio_buffer);
if (!error) {
if (compress) {
double delta = header->size - compr_diff;
@@ -674,6 +705,7 @@
printf( "S" );
error = mark_swap(resume_fd, start);
}
+ aio_sync();
fsync(resume_fd);
if (!error)
printf( "|" );
@@ -1296,7 +1328,8 @@
page_size = getpagesize();
buffer_size = BUFFER_PAGES * page_size;
- mem_size = 3 * page_size + buffer_size;
+
+ mem_size = 3 * page_size + (2+NB_AIO)*buffer_size;
#ifdef CONFIG_ENCRYPT
if (encrypt)
mem_size += buffer_size;
-------------------------------------------------------------------------
Take Surveys. Earn Cash. Influence the Future of IT
Join SourceForge.net's Techsay panel and you'll get the chance to share your
opinions on IT & business topics through brief surveys-and earn cash
http://www.techsay.com/default.php?page=join.php&p=sourceforge&CID=DEVDEV
_______________________________________________
Suspend-devel mailing list
Suspend-devel@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/suspend-devel