114 lines
3.0 KiB
Diff
114 lines
3.0 KiB
Diff
|
From 758be4f1c9cda8eefb2fd241835521462196e16c Mon Sep 17 00:00:00 2001
|
||
|
From: Lukasz Dorau <lukasz.dorau@intel.com>
|
||
|
Date: Mon, 19 Sep 2011 13:26:05 +1000
|
||
|
Subject: [PATCH] Fix serious memory leak
|
||
|
|
||
|
During reshape function restore_stripes is called periodically
|
||
|
and every time the buffer stripe_buf (of size raid_disks*chunk_size)
|
||
|
is allocated but is not freed. It happens also upon successful completion.
|
||
|
In case of huge arrays it can lead to the seizure of the entire
|
||
|
system memory (even of the order of gigabytes).
|
||
|
|
||
|
Signed-off-by: Lukasz Dorau <lukasz.dorau@intel.com>
|
||
|
Signed-off-by: NeilBrown <neilb@suse.de>
|
||
|
---
|
||
|
restripe.c | 50 +++++++++++++++++++++++++++++++++-----------------
|
||
|
1 files changed, 33 insertions(+), 17 deletions(-)
|
||
|
|
||
|
diff --git a/restripe.c b/restripe.c
|
||
|
index 9c83e2e..00e7a82 100644
|
||
|
--- a/restripe.c
|
||
|
+++ b/restripe.c
|
||
|
@@ -687,6 +687,7 @@ int restore_stripes(int *dest, unsigned long long *offsets,
|
||
|
char **stripes = malloc(raid_disks * sizeof(char*));
|
||
|
char **blocks = malloc(raid_disks * sizeof(char*));
|
||
|
int i;
|
||
|
+ int rv;
|
||
|
|
||
|
int data_disks = raid_disks - (level == 0 ? 0 : level <= 5 ? 1 : 2);
|
||
|
|
||
|
@@ -704,11 +705,8 @@ int restore_stripes(int *dest, unsigned long long *offsets,
|
||
|
|
||
|
if (stripe_buf == NULL || stripes == NULL || blocks == NULL
|
||
|
|| zero == NULL) {
|
||
|
- free(stripe_buf);
|
||
|
- free(stripes);
|
||
|
- free(blocks);
|
||
|
- free(zero);
|
||
|
- return -2;
|
||
|
+ rv = -2;
|
||
|
+ goto abort;
|
||
|
}
|
||
|
for (i = 0; i < raid_disks; i++)
|
||
|
stripes[i] = stripe_buf + i * chunk_size;
|
||
|
@@ -717,20 +715,26 @@ int restore_stripes(int *dest, unsigned long long *offsets,
|
||
|
unsigned long long offset;
|
||
|
int disk, qdisk;
|
||
|
int syndrome_disks;
|
||
|
- if (length < len)
|
||
|
- return -3;
|
||
|
+ if (length < len) {
|
||
|
+ rv = -3;
|
||
|
+ goto abort;
|
||
|
+ }
|
||
|
for (i = 0; i < data_disks; i++) {
|
||
|
int disk = geo_map(i, start/chunk_size/data_disks,
|
||
|
raid_disks, level, layout);
|
||
|
if (src_buf == NULL) {
|
||
|
/* read from file */
|
||
|
- if (lseek64(source,
|
||
|
- read_offset, 0) != (off64_t)read_offset)
|
||
|
- return -1;
|
||
|
+ if (lseek64(source, read_offset, 0) !=
|
||
|
+ (off64_t)read_offset) {
|
||
|
+ rv = -1;
|
||
|
+ goto abort;
|
||
|
+ }
|
||
|
if (read(source,
|
||
|
stripes[disk],
|
||
|
- chunk_size) != chunk_size)
|
||
|
- return -1;
|
||
|
+ chunk_size) != chunk_size) {
|
||
|
+ rv = -1;
|
||
|
+ goto abort;
|
||
|
+ }
|
||
|
} else {
|
||
|
/* read from input buffer */
|
||
|
memcpy(stripes[disk],
|
||
|
@@ -782,15 +786,27 @@ int restore_stripes(int *dest, unsigned long long *offsets,
|
||
|
}
|
||
|
for (i=0; i < raid_disks ; i++)
|
||
|
if (dest[i] >= 0) {
|
||
|
- if (lseek64(dest[i], offsets[i]+offset, 0) < 0)
|
||
|
- return -1;
|
||
|
- if (write(dest[i], stripes[i], chunk_size) != chunk_size)
|
||
|
- return -1;
|
||
|
+ if (lseek64(dest[i],
|
||
|
+ offsets[i]+offset, 0) < 0) {
|
||
|
+ rv = -1;
|
||
|
+ goto abort;
|
||
|
+ }
|
||
|
+ if (write(dest[i], stripes[i],
|
||
|
+ chunk_size) != chunk_size) {
|
||
|
+ rv = -1;
|
||
|
+ goto abort;
|
||
|
+ }
|
||
|
}
|
||
|
length -= len;
|
||
|
start += len;
|
||
|
}
|
||
|
- return 0;
|
||
|
+ rv = 0;
|
||
|
+
|
||
|
+abort:
|
||
|
+ free(stripe_buf);
|
||
|
+ free(stripes);
|
||
|
+ free(blocks);
|
||
|
+ return rv;
|
||
|
}
|
||
|
|
||
|
#ifdef MAIN
|
||
|
--
|
||
|
1.7.7.3
|
||
|
|