From mboxrd@z Thu Jan 1 00:00:00 1970 From: rpeterso@sourceware.org Date: 20 Sep 2006 15:23:35 -0000 Subject: [Cluster-devel] cluster/gfs2 fsck/initialize.c libgfs2/bitmap. ... Message-ID: <20060920152335.13285.qmail@sourceware.org> List-Id: To: cluster-devel.redhat.com MIME-Version: 1.0 Content-Type: text/plain; charset="us-ascii" Content-Transfer-Encoding: 7bit CVSROOT: /cvs/cluster Module name: cluster Changes by: rpeterso at sourceware.org 2006-09-20 15:23:34 Modified files: gfs2/fsck : initialize.c gfs2/libgfs2 : bitmap.c block_list.c libgfs2.h Log message: This is a crosswrite from gfs1 for bugzilla bz 200883: gfs_fsck segfaults on very large file systems. The same problem existed and is now fixed in gfs2_fsck and libgfs2. Patches: http://sourceware.org/cgi-bin/cvsweb.cgi/cluster/gfs2/fsck/initialize.c.diff?cvsroot=cluster&r1=1.4&r2=1.5 http://sourceware.org/cgi-bin/cvsweb.cgi/cluster/gfs2/libgfs2/bitmap.c.diff?cvsroot=cluster&r1=1.1&r2=1.2 http://sourceware.org/cgi-bin/cvsweb.cgi/cluster/gfs2/libgfs2/block_list.c.diff?cvsroot=cluster&r1=1.1&r2=1.2 http://sourceware.org/cgi-bin/cvsweb.cgi/cluster/gfs2/libgfs2/libgfs2.h.diff?cvsroot=cluster&r1=1.6&r2=1.7 --- cluster/gfs2/fsck/initialize.c 2006/06/15 18:48:45 1.4 +++ cluster/gfs2/fsck/initialize.c 2006/09/20 15:23:34 1.5 @@ -196,6 +196,7 @@ uint64_t inumbuf; struct gfs2_statfs_change sc; int rgcount; + uint64_t addl_mem_needed; sync(); @@ -290,8 +291,13 @@ goto fail; } - bl = gfs2_block_list_create(last_fs_block+1); - + bl = gfs2_block_list_create(last_fs_block+1, &addl_mem_needed); + if (!bl) { + log_crit("This system doesn't have enough memory + swap space to fsck this file system.\n"); + log_crit("Additional memory needed is approximately: %ldMB\n", addl_mem_needed / 1048576); + log_crit("Please increase your swap space by that amount and run gfs_fsck again.\n"); + goto fail; + } return 0; fail: --- cluster/gfs2/libgfs2/bitmap.c 2006/06/08 20:50:24 1.1 +++ cluster/gfs2/libgfs2/bitmap.c 2006/09/20 15:23:34 1.2 @@ -48,11 +48,11 @@ bmap->mapsize = BITMAP_SIZE(size, bmap->chunks_per_byte)+1; if(!(bmap->map = malloc(sizeof(char) * bmap->mapsize))) - return ENOMEM; + return -ENOMEM; if(!memset(bmap->map, 0, sizeof(char) * bmap->mapsize)) { free(bmap->map); bmap->map = NULL; - return ENOMEM; + return -ENOMEM; } return 0; } --- cluster/gfs2/libgfs2/block_list.c 2006/06/08 20:50:54 1.1 +++ cluster/gfs2/libgfs2/block_list.c 2006/09/20 15:23:34 1.2 @@ -46,27 +46,45 @@ INVALID_META, INVALID_META }; -struct gfs2_block_list *gfs2_block_list_create(uint64_t size) +struct gfs2_block_list *gfs2_block_list_create(uint64_t size, + uint64_t *addl_mem_needed) { struct gfs2_block_list *il; + *addl_mem_needed = 0L; if ((il = malloc(sizeof(*il)))) { if(!memset(il, 0, sizeof(*il))) return NULL; if(gfs2_bitmap_create(&il->list.gbmap.group_map, size, 4)) { + /* Note on addl_mem_needed: We've tried to allocate ram */ + /* for our bitmaps, but we failed. The fs is too big. */ + /* We should tell them how much to allocate. This first */ + /* bitmap is the biggest, but we need three more smaller */ + /* for the code that immediately follows. I'm rounding */ + /* up to twice the memory for this bitmap, even though */ + /* it's actually 1 + 3/4. That will allow for future */ + /* mallocs that happen after this point in the code. */ + /* For the bad_map, we have two more to go (total of 3) */ + /* but again I'm rounding it up to 4 smaller ones. */ + /* For the dup_map, I'm rounding from 2 to 3, and for */ + /* eattr_map, I'm rounding up from 1 to 2. */ + *addl_mem_needed = il->list.gbmap.group_map.mapsize * 2; free(il); il = NULL; } - if(gfs2_bitmap_create(&il->list.gbmap.bad_map, size, 1)) { + else if(gfs2_bitmap_create(&il->list.gbmap.bad_map, size, 1)) { + *addl_mem_needed = il->list.gbmap.group_map.mapsize * 4; free(il); il = NULL; } - if(gfs2_bitmap_create(&il->list.gbmap.dup_map, size, 1)) { + else if(gfs2_bitmap_create(&il->list.gbmap.dup_map, size, 1)) { + *addl_mem_needed = il->list.gbmap.group_map.mapsize * 3; free(il); il = NULL; } - if(gfs2_bitmap_create(&il->list.gbmap.eattr_map, size, 1)) { + else if(gfs2_bitmap_create(&il->list.gbmap.eattr_map, size, 1)) { + *addl_mem_needed = il->list.gbmap.group_map.mapsize * 2; free(il); il = NULL; } --- cluster/gfs2/libgfs2/libgfs2.h 2006/06/19 20:45:15 1.6 +++ cluster/gfs2/libgfs2/libgfs2.h 2006/09/20 15:23:34 1.7 @@ -318,7 +318,8 @@ union gfs2_block_lists list; }; -struct gfs2_block_list *gfs2_block_list_create(uint64_t size); +struct gfs2_block_list *gfs2_block_list_create(uint64_t size, + uint64_t *addl_mem_needed); int gfs2_block_mark(struct gfs2_block_list *il, uint64_t block, enum gfs2_mark_block mark); int gfs2_block_set(struct gfs2_block_list *il, uint64_t block,