commit 4fbd5fa224b6dbcf0998c4cb352a92c4b49f6cdc Author: Bob Peterson <bob@ganesha.peterson> Date: Wed Nov 25 14:31:51 2009 -0600 Remove nvbuf_list and use fewer buffers This preliminary patch is a starting point for disentangling the issues fsck has with libgfs2/buf.c. Rather than read in all the rgrp bitmaps into memory, all in a non-volatile linked list, this patch keeps the same linked list of rgrps, but only reads in the bitmaps on an as-needed basis, and only for short-term. This is also an attempt to eliminate the fairly new non-volatile linked buffer list and change all the code in gfs2-utils so that they should not depend on the list being non-volatile. The whole non-volatile thing was a stop-gap temporary solution so that we could minimize the possibility of regression. In addition to getting rid of the non-volatile linked list, it also reduces the remaining linked list of buffers from 128MB to 1MB so that much fewer buffers will be kept in memory. That could drive a lot of bugs out of their hiding places. rhbz#455300 diff --git a/gfs2/convert/gfs2_convert.c b/gfs2/convert/gfs2_convert.c index 48b4087..028913b 100644 --- a/gfs2/convert/gfs2_convert.c +++ b/gfs2/convert/gfs2_convert.c @@ -167,34 +167,29 @@ void print_it(const char *label, const char *fmt, const char *fmt2, ...) /* valid in gfs1 but invalid in gfs2). */ /* ------------------------------------------------------------------------- */ static void convert_bitmaps(struct gfs2_sbd *sdp, struct rgrp_list *rgd2, - int read_disk) + struct gfs2_buffer_head **rgbh) { uint32_t blk; int x, y; struct gfs2_rindex *ri; unsigned char state; - struct gfs2_buffer_head *bh; ri = &rgd2->ri; - if (gfs2_compute_bitstructs(sdp, rgd2)) { /* mallocs bh as array */ + if (gfs2_compute_bitstructs(sdp, rgd2)) { log_crit("gfs2_convert: Error converting bitmaps.\n"); exit(-1); } for (blk = 0; blk < ri->ri_length; blk++) { - bh = bget_generic(&sdp->nvbuf_list, ri->ri_addr + blk, - read_disk, read_disk); - if (!rgd2->bh[blk]) - rgd2->bh[blk] = bh; - x = (blk) ? sizeof(struct gfs2_meta_header) : sizeof(struct gfs2_rgrp); + x = (blk) ? sizeof(struct gfs2_meta_header) : + sizeof(struct gfs2_rgrp); for (; x < sdp->bsize; x++) for (y = 0; y < GFS2_NBBY; y++) { - state = (rgd2->bh[blk]->b_data[x] >> - (GFS2_BIT_SIZE * y)) & 0x03; + state = (rgbh[blk]->b_data[x] >> + (GFS2_BIT_SIZE * y)) & 0x03; if (state == 0x02) /* unallocated metadata state invalid */ - rgd2->bh[blk]->b_data[x] &= ~(0x02 << (GFS2_BIT_SIZE * y)); + rgbh[blk]->b_data[x] &= ~(0x02 << (GFS2_BIT_SIZE * y)); } - brelse(bh, updated); } }/* convert_bitmaps */ @@ -205,38 +200,49 @@ static void convert_bitmaps(struct gfs2_sbd *sdp, struct rgrp_list *rgd2, static int convert_rgs(struct gfs2_sbd *sbp) { struct rgrp_list *rgd; + struct gfs2_rgrp rg; osi_list_t *tmp; - struct gfs2_buffer_head *bh; struct gfs1_rgrp *rgd1; int rgs = 0; + struct gfs2_buffer_head **rgbh; /* --------------------------------- */ /* Now convert its rgs into gfs2 rgs */ /* --------------------------------- */ osi_list_foreach(tmp, &sbp->rglist) { rgd = osi_list_entry(tmp, struct rgrp_list, list); - rgd1 = (struct gfs1_rgrp *)&rgd->rg; /* recast as gfs1 structure */ + if(!(rgbh = (struct gfs2_buffer_head **) + malloc(rgd->ri.ri_length * + sizeof(struct gfs2_buffer_head *)))) + return -1; + if(!memset(rgbh, 0, rgd->ri.ri_length * + sizeof(struct gfs2_buffer_head *))) { + free(rgbh); + return -1; + } + + gfs2_rgrp_read(sbp, rgd, rgbh, &rg); + rgd1 = (struct gfs1_rgrp *)&rg; /* recast as gfs1 structure */ /* rg_freemeta is a gfs1 structure, so libgfs2 doesn't know to */ /* convert from be to cpu. We must do it now. */ - rgd->rg.rg_free = rgd1->rg_free + be32_to_cpu(rgd1->rg_freemeta); + rg.rg_free = rgd1->rg_free + be32_to_cpu(rgd1->rg_freemeta); + rgd->rg_free = rg.rg_free; /* Zero it out so we don't add it again in case something breaks */ /* later on in the process and we have to re-run convert */ rgd1->rg_freemeta = 0; sbp->blks_total += rgd->ri.ri_data; - sbp->blks_alloced += (rgd->ri.ri_data - rgd->rg.rg_free); + sbp->blks_alloced += (rgd->ri.ri_data - rg.rg_free); sbp->dinodes_alloced += rgd1->rg_useddi; - convert_bitmaps(sbp, rgd, TRUE); + convert_bitmaps(sbp, rgd, rgbh); /* Write the updated rgrp to the gfs2 buffer */ - bh = bget(&sbp->nvbuf_list, - rgd->ri.ri_addr); /* get a gfs2 buffer for the rg */ - gfs2_rgrp_out(&rgd->rg, rgd->bh[0]->b_data); - brelse(bh, updated); /* release the buffer */ + gfs2_rgrp_out(&rg, rgbh[0]->b_data); rgs++; if (rgs % 100 == 0) { printf("."); fflush(stdout); } + free(rgbh); } return 0; }/* superblock_cvt */ @@ -983,6 +989,8 @@ static int inode_renumber(struct gfs2_sbd *sbp, uint64_t root_inode_addr) int first; int error = 0; int rgs_processed = 0; + struct gfs2_buffer_head **rgbh; + struct gfs2_rgrp rg; log_notice("Converting inodes.\n"); sbp->md.next_inum = 1; /* starting inode numbering */ @@ -996,8 +1004,18 @@ static int inode_renumber(struct gfs2_sbd *sbp, uint64_t root_inode_addr) rgs_processed++; rgd = osi_list_entry(tmp, struct rgrp_list, list); first = 1; - if (gfs2_rgrp_read(sbp, rgd)) { + if(!(rgbh = (struct gfs2_buffer_head **) + malloc(rgd->ri.ri_length * + sizeof(struct gfs2_buffer_head *)))) + return -1; + if(!memset(rgbh, 0, rgd->ri.ri_length * + sizeof(struct gfs2_buffer_head *))) { + free(rgbh); + return -1; + } + if (gfs2_rgrp_read(sbp, rgd, rgbh, &rg)) { log_crit("Unable to read rgrp.\n"); + free(rgbh); return -1; } while (1) { /* for all inodes in the resource group */ @@ -1042,9 +1060,9 @@ static int inode_renumber(struct gfs2_sbd *sbp, uint64_t root_inode_addr) sizeof(struct gfs2_rgrp); /* if it's on this page */ if (buf_offset + bitmap_byte < sbp->bsize) { - rgd->bh[blk]->b_data[buf_offset + bitmap_byte] &= + rgbh[blk]->b_data[buf_offset + bitmap_byte] &= ~(0x03 << (GFS2_BIT_SIZE * byte_bit)); - rgd->bh[blk]->b_data[buf_offset + bitmap_byte] |= + rgbh[blk]->b_data[buf_offset + bitmap_byte] |= (0x01 << (GFS2_BIT_SIZE * byte_bit)); break; } @@ -1054,7 +1072,8 @@ static int inode_renumber(struct gfs2_sbd *sbp, uint64_t root_inode_addr) brelse(bh, updated); first = 0; } /* while 1 */ - gfs2_rgrp_relse(rgd, updated); + gfs2_rgrp_relse(rgd, updated, rgbh); + free(rgbh); } /* for all rgs */ log_notice("\r%" PRIu64" inodes from %d rgs converted.", sbp->md.next_inum, rgs_processed); @@ -1379,8 +1398,7 @@ static int init(struct gfs2_sbd *sbp) sbp->sd_sb.sb_bsize = GFS2_DEFAULT_BSIZE; sbp->bsize = sbp->sd_sb.sb_bsize; osi_list_init(&sbp->rglist); - init_buf_list(sbp, &sbp->buf_list, 128 << 20); - init_buf_list(sbp, &sbp->nvbuf_list, 0xffffffff); + init_buf_list(sbp, &sbp->buf_list, 1 << 20); /* only use 1MB of bufs */ compute_constants(sbp); bh = bread(&sbp->buf_list, GFS2_SB_ADDR >> sbp->sd_fsb2bb_shift); @@ -1596,6 +1614,8 @@ static int journ_space_to_rg(struct gfs2_sbd *sdp) struct rgrp_list *rgd, *rgdhigh; osi_list_t *tmp; struct gfs2_meta_header mh; + struct gfs2_rgrp rg; + struct gfs2_buffer_head **rgbh; mh.mh_magic = GFS2_MAGIC; mh.mh_type = GFS2_METATYPE_RB; @@ -1606,12 +1626,12 @@ static int journ_space_to_rg(struct gfs2_sbd *sdp) uint64_t size; jndx = &sd_jindex[j]; - /* go through all rg index entries, keeping track of the highest */ - /* that's still in the first subdevice. */ - /* Note: we really should go through all of the rgindex because */ - /* we might have had rg's added by gfs_grow, and journals added */ - /* by jadd. gfs_grow adds rgs out of order, so we can't count */ - /* on them being in ascending order. */ + /* go through all rg index entries, keeping track of the + highest that's still in the first subdevice. + Note: we really should go through all of the rgindex because + we might have had rg's added by gfs_grow, and journals added + by jadd. gfs_grow adds rgs out of order, so we can't count + on them being in ascending order. */ rgdhigh = NULL; osi_list_foreach(tmp, &sdp->rglist) { rgd = osi_list_entry(tmp, struct rgrp_list, list); @@ -1635,11 +1655,11 @@ static int journ_space_to_rg(struct gfs2_sbd *sdp) } memset(rgd, 0, sizeof(struct rgrp_list)); size = jndx->ji_nsegment * be32_to_cpu(raw_gfs1_ondisk_sb.sb_seg_size); - rgd->rg.rg_header.mh_magic = GFS2_MAGIC; - rgd->rg.rg_header.mh_type = GFS2_METATYPE_RG; - rgd->rg.rg_header.mh_format = GFS2_FORMAT_RG; - rgd->rg.rg_flags = 0; - rgd->rg.rg_dinodes = 0; + rg.rg_header.mh_magic = GFS2_MAGIC; + rg.rg_header.mh_type = GFS2_METATYPE_RG; + rg.rg_header.mh_format = GFS2_FORMAT_RG; + rg.rg_flags = 0; + rg.rg_dinodes = 0; rgd->ri.ri_addr = jndx->ji_addr; /* new rg addr becomes ji addr */ rgd->ri.ri_length = rgrp_length(size, sdp); /* aka bitblocks */ @@ -1650,19 +1670,31 @@ static int journ_space_to_rg(struct gfs2_sbd *sdp) while (rgd->ri.ri_data & 0x03) rgd->ri.ri_data--; sdp->blks_total += rgd->ri.ri_data; /* For statfs file update */ - rgd->rg.rg_free = rgd->ri.ri_data; + rg.rg_free = rgd->ri.ri_data; rgd->ri.ri_bitbytes = rgd->ri.ri_data / GFS2_NBBY; - convert_bitmaps(sdp, rgd, FALSE); /* allocates rgd->bh */ + + if(!(rgbh = (struct gfs2_buffer_head **) + malloc(rgd->ri.ri_length * + sizeof(struct gfs2_buffer_head *)))) + return -1; + if(!memset(rgbh, 0, rgd->ri.ri_length * + sizeof(struct gfs2_buffer_head *))) { + free(rgbh); + return -1; + } + + convert_bitmaps(sdp, rgd, rgbh); for (x = 0; x < rgd->ri.ri_length; x++) { - rgd->bh[x]->b_count++; + rgbh[x]->b_count++; if (x) - gfs2_meta_header_out(&mh, rgd->bh[x]->b_data); + gfs2_meta_header_out(&mh, rgbh[x]->b_data); else - gfs2_rgrp_out(&rgd->rg, rgd->bh[x]->b_data); + gfs2_rgrp_out(&rg, rgbh[x]->b_data); } /* Add the new gfs2 rg to our list: We'll output the rg index later. */ osi_list_add_prev((osi_list_t *)&rgd->list, (osi_list_t *)&sdp->rglist); + free(rgbh); } /* for each journal */ return error; }/* journ_space_to_rg */ @@ -1803,7 +1835,7 @@ int main(int argc, char **argv) if (error) log_crit("%s: Unable to convert resource groups.\n", device); - bcommit(&sb2.nvbuf_list); /* write the buffers to disk */ + bcommit(&sb2.buf_list); /* write the buffers to disk */ } /* ---------------------------------------------- */ /* Renumber the inodes consecutively. */ @@ -1870,10 +1902,9 @@ int main(int argc, char **argv) inode_put(sb2.md.statfs, updated); bcommit(&sb2.buf_list); /* write the buffers to disk */ - bcommit(&sb2.nvbuf_list); /* write the buffers to disk */ /* Now free all the in memory */ - gfs2_rgrp_free(&sb2.rglist, updated); + gfs2_rgrp_free(&sb2.rglist); log_notice("Committing changes to disk.\n"); fflush(stdout); /* Set filesystem type in superblock to gfs2. We do this at the */ @@ -1887,7 +1918,6 @@ int main(int argc, char **argv) brelse(bh, updated); bsync(&sb2.buf_list); /* write the buffers to disk */ - bsync(&sb2.nvbuf_list); /* write the buffers to disk */ error = fsync(sb2.device_fd); if (error) perror(device); diff --git a/gfs2/edit/hexedit.c b/gfs2/edit/hexedit.c index 99b42bf..d6fb7fe 100644 --- a/gfs2/edit/hexedit.c +++ b/gfs2/edit/hexedit.c @@ -580,10 +580,9 @@ int display_block_type(const char *lpBuffer, int from_restore) struct rgrp_list *rgd; rgd = gfs2_blk2rgrpd(&sbd, block); - if (rgd) { + if (rgd) type = gfs2_get_bitmap(&sbd, block, rgd); - gfs2_rgrp_relse(rgd, not_updated); - } else + else type = 4; screen_chunk_size = ((termlines - 4) * 16) >> 8 << 8; if (!screen_chunk_size) @@ -801,7 +800,7 @@ static void rgcount(void) printf("%lld RGs in this file system.\n", (unsigned long long)sbd.md.riinode->i_di.di_size / risize()); inode_put(sbd.md.riinode, not_updated); - gfs2_rgrp_free(&sbd.rglist, not_updated); + gfs2_rgrp_free(&sbd.rglist); exit(EXIT_SUCCESS); } @@ -1004,7 +1003,7 @@ static int parse_rindex(struct gfs2_inode *dip, int print_rindex) else { struct gfs2_buffer_head *tmp_bh; - tmp_bh = bread(&sbd.nvbuf_list, ri.ri_addr); + tmp_bh = bread(&sbd.buf_list, ri.ri_addr); if (gfs1) { struct gfs_rgrp rg1; gfs_rgrp_in(&rg1, tmp_bh->b_data); @@ -1707,7 +1706,7 @@ static int display_extended(void) /* ------------------------------------------------------------------------ */ static void read_superblock(int fd) { - int count; + int count, bitmap_blocks = 0; sbd1 = (struct gfs_sb *)&sbd.sd_sb; ioctl(fd, BLKFLSBUF, 0); @@ -1726,8 +1725,7 @@ static void read_superblock(int fd) sbd.qcsize = GFS2_DEFAULT_QCSIZE; sbd.time = time(NULL); osi_list_init(&sbd.rglist); - init_buf_list(&sbd, &sbd.buf_list, 128 << 20); - init_buf_list(&sbd, &sbd.nvbuf_list, 0xffffffff); + init_buf_list(&sbd, &sbd.buf_list, 1 << 20); gfs2_sb_in(&sbd.sd_sb, buf); /* parse it out into the sb structure */ /* Check to see if this is really gfs1 */ if (sbd1->sb_fs_format == GFS_FORMAT_FS && @@ -1760,7 +1758,8 @@ static void read_superblock(int fd) sbd.md.riinode = gfs2_load_inode(&sbd, sbd1->sb_rindex_di.no_addr); sbd.fssize = sbd.device.length; - gfs1_ri_update(&sbd, 0, &count, 1); + gfs1_rindex_read(&sbd, fd, &count, &bitmap_blocks); + /*gfs1_ri_update(&sbd, 0, &count, 1);*/ } else { sbd.sd_inptrs = (sbd.bsize - sizeof(struct gfs2_meta_header)) / sizeof(uint64_t); @@ -1770,7 +1769,8 @@ static void read_superblock(int fd) sbd.sd_sb.sb_master_dir.no_addr); gfs2_lookupi(sbd.master_dir, "rindex", 6, &sbd.md.riinode); sbd.fssize = sbd.device.length; - ri_update(&sbd, 0, &count); + rindex_read(&sbd, fd, &count, &bitmap_blocks); + /*ri_update(&sbd, 0, &count);*/ } } @@ -2040,7 +2040,7 @@ static uint64_t find_metablockoftype_slow(uint64_t startblk, int metatype, int p else printf("%llu\n", (unsigned long long)blk); } - gfs2_rgrp_free(&sbd.rglist, not_updated); + gfs2_rgrp_free(&sbd.rglist); if (print) exit(0); return blk; @@ -2079,7 +2079,7 @@ static uint64_t find_metablockoftype_rg(uint64_t startblk, int metatype, int pri if (!rgd) { if (print) printf("0\n"); - gfs2_rgrp_free(&sbd.rglist, not_updated); + gfs2_rgrp_free(&sbd.rglist); if (print) exit(-1); } @@ -2105,7 +2105,7 @@ static uint64_t find_metablockoftype_rg(uint64_t startblk, int metatype, int pri else printf("%llu\n", (unsigned long long)blk); } - gfs2_rgrp_free(&sbd.rglist, not_updated); + gfs2_rgrp_free(&sbd.rglist); if (print) exit(0); return blk; @@ -2139,7 +2139,7 @@ static uint64_t find_metablockoftype(const char *strtype, int print) "specified: must be one of:\n"); fprintf(stderr, "sb rg rb di in lf jd lh ld" " ea ed lb 13 qc\n"); - gfs2_rgrp_free(&sbd.rglist, not_updated); + gfs2_rgrp_free(&sbd.rglist); exit(-1); } return blk; @@ -2448,7 +2448,7 @@ static void find_print_block_type(void) type = get_block_type(bh->b_data); print_block_type(tblock, type, ""); brelse(bh, NOT_UPDATED); - gfs2_rgrp_free(&sbd.rglist, not_updated); + gfs2_rgrp_free(&sbd.rglist); exit(0); } @@ -2491,7 +2491,7 @@ static void find_print_block_rg(int bitmap) printf("-1 (block invalid or part of an rgrp).\n"); } } - gfs2_rgrp_free(&sbd.rglist, not_updated); + gfs2_rgrp_free(&sbd.rglist); exit(0); } @@ -2512,7 +2512,7 @@ static void find_change_block_alloc(int *newval) *newval); for (i = GFS2_BLKST_FREE; i <= GFS2_BLKST_DINODE; i++) printf("%d - %s\n", i, allocdesc[gfs1][i]); - gfs2_rgrp_free(&sbd.rglist, not_updated); + gfs2_rgrp_free(&sbd.rglist); exit(-1); } ablock = blockstack[blockhist % BLOCK_STACK_SIZE].block; @@ -2529,17 +2529,16 @@ static void find_change_block_alloc(int *newval) if (rgd) { type = gfs2_get_bitmap(&sbd, ablock, rgd); printf("%d (%s)\n", type, allocdesc[gfs1][type]); - gfs2_rgrp_relse(rgd, not_updated); } else { - gfs2_rgrp_free(&sbd.rglist, not_updated); + gfs2_rgrp_free(&sbd.rglist); printf("-1 (block invalid or part of an rgrp).\n"); exit(-1); } } } - gfs2_rgrp_free(&sbd.rglist, (newval) ? updated : not_updated); + gfs2_rgrp_free(&sbd.rglist); if (newval) - bcommit(&sbd.nvbuf_list); + bcommit(&sbd.buf_list); exit(0); } @@ -3343,7 +3342,7 @@ static void process_parameters(int argc, char *argv[], int pass) printf("Error: field not specified.\n"); printf("Format is: %s -p <block> field " "<field> [newvalue]\n", argv[0]); - gfs2_rgrp_free(&sbd.rglist, not_updated); + gfs2_rgrp_free(&sbd.rglist); exit(EXIT_FAILURE); } if (isdigit(argv[i + 1][0])) { @@ -3353,11 +3352,11 @@ static void process_parameters(int argc, char *argv[], int pass) else newval = (uint64_t)atoll(argv[i + 1]); process_field(argv[i], &newval, 1); - gfs2_rgrp_free(&sbd.rglist, not_updated); + gfs2_rgrp_free(&sbd.rglist); exit(0); } else { process_field(argv[i], NULL, 1); - gfs2_rgrp_free(&sbd.rglist, not_updated); + gfs2_rgrp_free(&sbd.rglist); exit(0); } } else if (!strcmp(argv[i], "blocktype")) { @@ -3389,7 +3388,7 @@ static void process_parameters(int argc, char *argv[], int pass) printf("Error: rg # not specified.\n"); printf("Format is: %s rgflags rgnum" "[newvalue]\n", argv[0]); - gfs2_rgrp_free(&sbd.rglist, not_updated); + gfs2_rgrp_free(&sbd.rglist); exit(EXIT_FAILURE); } if (argv[i][0]=='0' && argv[i][1]=='x') @@ -3406,7 +3405,7 @@ static void process_parameters(int argc, char *argv[], int pass) new_flags = atoi(argv[i]); } set_rgrp_flags(rg, new_flags, set, FALSE); - gfs2_rgrp_free(&sbd.rglist, not_updated); + gfs2_rgrp_free(&sbd.rglist); exit(EXIT_SUCCESS); } else if (!strcmp(argv[i], "rg")) { int rg; @@ -3415,7 +3414,7 @@ static void process_parameters(int argc, char *argv[], int pass) if (i >= argc - 1) { printf("Error: rg # not specified.\n"); printf("Format is: %s rg rgnum\n", argv[0]); - gfs2_rgrp_free(&sbd.rglist, not_updated); + gfs2_rgrp_free(&sbd.rglist); exit(EXIT_FAILURE); } rg = atoi(argv[i]); @@ -3424,7 +3423,7 @@ static void process_parameters(int argc, char *argv[], int pass) push_block(temp_blk); } else { set_rgrp_flags(rg, 0, FALSE, TRUE); - gfs2_rgrp_free(&sbd.rglist, not_updated); + gfs2_rgrp_free(&sbd.rglist); exit(EXIT_SUCCESS); } } @@ -3536,6 +3535,6 @@ int main(int argc, char *argv[]) free(buf); if (indirect) free(indirect); - gfs2_rgrp_free(&sbd.rglist, not_updated); + gfs2_rgrp_free(&sbd.rglist); exit(EXIT_SUCCESS); } diff --git a/gfs2/edit/savemeta.c b/gfs2/edit/savemeta.c index 1983ba3..8959442 100644 --- a/gfs2/edit/savemeta.c +++ b/gfs2/edit/savemeta.c @@ -449,12 +449,14 @@ static void get_journal_inode_blocks(void) } } -static int next_rg_freemeta(struct rgrp_list *rgd, uint64_t *nrfblock, int first) +static int next_rg_freemeta(struct gfs2_sbd *sdp, struct rgrp_list *rgd, + uint64_t *nrfblock, int first) { struct gfs2_bitmap *bits = NULL; uint32_t length = rgd->ri.ri_length; uint32_t blk = (first)? 0: (uint32_t)((*nrfblock+1)-rgd->ri.ri_data0); int i; + struct gfs2_buffer_head *bh; if(!first && (*nrfblock < rgd->ri.ri_data0)) { log_err("next_rg_freemeta: Start block is outside rgrp " @@ -469,9 +471,11 @@ static int next_rg_freemeta(struct rgrp_list *rgd, uint64_t *nrfblock, int first } for(; i < length; i++){ bits = &rgd->bits[i]; - blk = gfs2_bitfit((unsigned char *)rgd->bh[i]->b_data + + bh = bread(&sdp->buf_list, rgd->ri.ri_addr + i); + blk = gfs2_bitfit((unsigned char *)bh->b_data + bits->bi_offset, bits->bi_len, blk, GFS2_BLKST_UNLINKED); + brelse(bh, not_updated); if(blk != BFITNOENT){ *nrfblock = blk + (bits->bi_start * GFS2_NBBY) + rgd->ri.ri_data0; @@ -493,6 +497,8 @@ void savemeta(char *out_fn, int saveoption) int rgcount; uint64_t jindex_block; struct gfs2_buffer_head *bh; + struct gfs2_rgrp rg; + struct gfs2_buffer_head **rgbh; slow = (saveoption == 1); sbd.md.journals = 1; @@ -522,8 +528,7 @@ void savemeta(char *out_fn, int saveoption) device_geometry(&sbd); fix_device_geometry(&sbd); osi_list_init(&sbd.rglist); - init_buf_list(&sbd, &sbd.buf_list, 128 << 20); - init_buf_list(&sbd, &sbd.nvbuf_list, 0xffffffff); + init_buf_list(&sbd, &sbd.buf_list, 1 << 20); if (!gfs1) sbd.sd_sb.sb_bsize = GFS2_DEFAULT_BSIZE; compute_constants(&sbd); @@ -617,7 +622,16 @@ void savemeta(char *out_fn, int saveoption) int i, first; rgd = osi_list_entry(tmp, struct rgrp_list, list); - slow = gfs2_rgrp_read(&sbd, rgd); + if(!(rgbh = (struct gfs2_buffer_head **) + malloc(rgd->ri.ri_length * + sizeof(struct gfs2_buffer_head *)))) + break; + if(!memset(rgbh, 0, rgd->ri.ri_length * + sizeof(struct gfs2_buffer_head *))) { + free(rgbh); + break; + } + slow = gfs2_rgrp_read(&sbd, rgd, rgbh, &rg); if (slow) continue; log_debug("RG at %"PRIu64" is %u long\n", @@ -639,7 +653,8 @@ void savemeta(char *out_fn, int saveoption) if (saveoption != 2) { int blktype; - while (!gfs2_next_rg_meta(rgd, &block, first)) { + while (!gfs2_next_rg_meta(&sbd, rgd, &block, + first)) { warm_fuzzy_stuff(block, FALSE, TRUE); blktype = save_block(sbd.device_fd, out_fd, block); @@ -650,13 +665,15 @@ void savemeta(char *out_fn, int saveoption) /* Save off the free/unlinked meta blocks too. If we don't, we may run into metadata allocation issues. */ - while (!next_rg_freemeta(rgd, &block, first)) { + while (!next_rg_freemeta(&sbd, rgd, &block, + first)) { blktype = save_block(sbd.device_fd, out_fd, block); first = 0; } } - gfs2_rgrp_relse(rgd, not_updated); + gfs2_rgrp_relse(rgd, not_updated, rgbh); + free(rgbh); } } if (slow) { diff --git a/gfs2/fsck/fs_recovery.c b/gfs2/fsck/fs_recovery.c index a225eb1..3225c26 100644 --- a/gfs2/fsck/fs_recovery.c +++ b/gfs2/fsck/fs_recovery.c @@ -589,6 +589,5 @@ int replay_journals(struct gfs2_sbd *sdp, int preen, int force_check, inode_put(sdp->md.jiinode, not_updated); /* Sync the buffers to disk so we get a fresh start. */ bsync(&sdp->buf_list); - bsync(&sdp->nvbuf_list); return error; } diff --git a/gfs2/fsck/initialize.c b/gfs2/fsck/initialize.c index a12deed..67fa1fb 100644 --- a/gfs2/fsck/initialize.c +++ b/gfs2/fsck/initialize.c @@ -303,9 +303,8 @@ static int fill_super_block(struct gfs2_sbd *sdp) ********************************************************************/ log_info( _("Initializing lists...\n")); osi_list_init(&sdp->rglist); - init_buf_list(sdp, &sdp->buf_list, 128 << 20); - init_buf_list(sdp, &sdp->nvbuf_list, 0xffffffff); - for(i = 0; i < BUF_HASH_SIZE; i++) { + init_buf_list(sdp, &sdp->buf_list, 1 << 20); + for(i = 0; i < FSCK_HASH_SIZE; i++) { osi_list_init(&dir_hash[i]); osi_list_init(&inode_hash[i]); } diff --git a/gfs2/fsck/main.c b/gfs2/fsck/main.c index 718aa8f..56ac943 100644 --- a/gfs2/fsck/main.c +++ b/gfs2/fsck/main.c @@ -276,10 +276,12 @@ void check_statfs(struct gfs2_sbd *sdp) { osi_list_t *tmp; struct rgrp_list *rgd; + struct gfs2_rgrp rg; struct gfs2_rindex *ri; struct gfs2_statfs_change sc; char buf[sizeof(struct gfs2_statfs_change)]; int count; + struct gfs2_buffer_head **rgbh; /* Read the current statfs values */ count = gfs2_readi(sdp->md.statfs, buf, 0, @@ -295,9 +297,24 @@ void check_statfs(struct gfs2_sbd *sdp) for (tmp = sdp->rglist.next; tmp != &sdp->rglist; tmp = tmp->next) { rgd = osi_list_entry(tmp, struct rgrp_list, list); ri = &rgd->ri; + if(!(rgbh = (struct gfs2_buffer_head **) + malloc(rgd->ri.ri_length * + sizeof(struct gfs2_buffer_head *)))) { + log_err( _("Error: can't allocate memory to check statfs.\n")); + return; + } + if(!memset(rgbh, 0, rgd->ri.ri_length * + sizeof(struct gfs2_buffer_head *))) { + free(rgbh); + log_err( _("Error: can't allocate memory to check statfs.\n")); + return; + } + gfs2_rgrp_read(sdp, rgd, rgbh, &rg); sdp->blks_total += ri->ri_data; - sdp->blks_alloced += (ri->ri_data - rgd->rg.rg_free); - sdp->dinodes_alloced += rgd->rg.rg_dinodes; + sdp->blks_alloced += (ri->ri_data - rg.rg_free); + sdp->dinodes_alloced += rg.rg_dinodes; + gfs2_rgrp_relse(rgd, not_updated, rgbh); + free(rgbh); } /* See if they match */ @@ -482,7 +499,6 @@ int main(int argc, char **argv) log_notice( _("Writing changes to disk\n")); bsync(&sbp->buf_list); - bsync(&sbp->nvbuf_list); destroy(sbp); log_notice( _("gfs2_fsck complete \n")); diff --git a/gfs2/fsck/pass1.c b/gfs2/fsck/pass1.c index a23da46..f011c64 100644 --- a/gfs2/fsck/pass1.c +++ b/gfs2/fsck/pass1.c @@ -995,6 +995,8 @@ int pass1(struct gfs2_sbd *sbp) uint64_t blk_count; uint64_t offset; uint64_t rg_count = 0; + struct gfs2_rgrp rg; + struct gfs2_buffer_head **rgbh; /* FIXME: In the gfs fsck, we had to mark things like the * journals and indices and such as 'other_meta' - in gfs2, @@ -1017,8 +1019,18 @@ int pass1(struct gfs2_sbd *sbp) log_info( _("Checking metadata in Resource Group #%" PRIu64 "\n"), rg_count); rgd = osi_list_entry(tmp, struct rgrp_list, list); - if(gfs2_rgrp_read(sbp, rgd)){ + if(!(rgbh = (struct gfs2_buffer_head **) + malloc(rgd->ri.ri_length * + sizeof(struct gfs2_buffer_head *)))) + return FSCK_ERROR; + if(!memset(rgbh, 0, rgd->ri.ri_length * + sizeof(struct gfs2_buffer_head *))) { + free(rgbh); + return FSCK_ERROR; + } + if(gfs2_rgrp_read(sbp, rgd, rgbh, &rg)){ stack; + free(rgbh); return FSCK_ERROR; } log_debug( _("RG at %llu (0x%llx) is %u long\n"), @@ -1029,6 +1041,7 @@ int pass1(struct gfs2_sbd *sbp) if(gfs2_block_set(sbp, bl, rgd->ri.ri_addr + i, gfs2_meta_other)){ stack; + free(rgbh); return FSCK_ERROR; } } @@ -1039,11 +1052,12 @@ int pass1(struct gfs2_sbd *sbp) while (1) { /* "block" is relative to the entire file system */ - if (gfs2_next_rg_meta(rgd, &block, first)) + if (gfs2_next_rg_meta(sbp, rgd, &block, first)) break; warm_fuzzy_stuff(block); if (fsck_abort) { /* if asked to abort */ - gfs2_rgrp_relse(rgd, not_updated); + gfs2_rgrp_relse(rgd, not_updated, rgbh); + free(rgbh); return FSCK_OK; } if (skip_this_pass) { @@ -1056,13 +1070,15 @@ int pass1(struct gfs2_sbd *sbp) if (scan_meta(sbp, bh, block)) { stack; brelse(bh, not_updated); - gfs2_rgrp_relse(rgd, not_updated); + gfs2_rgrp_relse(rgd, not_updated, rgbh); + free(rgbh); return FSCK_ERROR; } brelse(bh, not_updated); first = 0; } - gfs2_rgrp_relse(rgd, not_updated); + gfs2_rgrp_relse(rgd, not_updated, rgbh); + free(rgbh); } return FSCK_OK; } diff --git a/gfs2/fsck/pass5.c b/gfs2/fsck/pass5.c index a533536..98cdeef 100644 --- a/gfs2/fsck/pass5.c +++ b/gfs2/fsck/pass5.c @@ -166,7 +166,8 @@ static int check_block_status(struct gfs2_sbd *sbp, char *buffer, unsigned int b } static enum update_flags update_rgrp(struct gfs2_sbd *sbp, struct rgrp_list *rgp, - uint32_t *count) + uint32_t *count, struct gfs2_buffer_head **rgbh, + struct gfs2_rgrp *rg) { uint32_t i; struct gfs2_bitmap *bits; @@ -177,26 +178,26 @@ static enum update_flags update_rgrp(struct gfs2_sbd *sbp, struct rgrp_list *rgp bits = &rgp->bits[i]; /* update the bitmaps */ - check_block_status(sbp, rgp->bh[i]->b_data + bits->bi_offset, + check_block_status(sbp, rgbh[i]->b_data + bits->bi_offset, bits->bi_len, &rg_block, rgp->ri.ri_data0, count); if (skip_this_pass || fsck_abort) /* if asked to skip the rest */ return 0; } /* actually adjust counters and write out to disk */ - if(rgp->rg.rg_free != count[0]) { + if(rgp->rg_free != count[0]) { log_err( _("RG #%llu (0x%llx) free count inconsistent: " "is %u should be %u\n"), (unsigned long long)rgp->ri.ri_addr, (unsigned long long)rgp->ri.ri_addr, - rgp->rg.rg_free, count[0]); - rgp->rg.rg_free = count[0]; + rgp->rg_free, count[0]); + rgp->rg_free = count[0]; update = 1; } - if(rgp->rg.rg_dinodes != count[1]) { + if(rg->rg_dinodes != count[1]) { log_err( _("Inode count inconsistent: is %u should be %u\n"), - rgp->rg.rg_dinodes, count[1]); - rgp->rg.rg_dinodes = count[1]; + rg->rg_dinodes, count[1]); + rg->rg_dinodes = count[1]; update = 1; } if((rgp->ri.ri_data - count[0] - count[1]) != count[2]) { @@ -212,7 +213,7 @@ static enum update_flags update_rgrp(struct gfs2_sbd *sbp, struct rgrp_list *rgp errors_corrected++; log_warn( _("Resource group counts updated\n")); /* write out the rgrp */ - gfs2_rgrp_out(&rgp->rg, rgp->bh[0]->b_data); + gfs2_rgrp_out(rg, rgbh[0]->b_data); return updated; } else log_err( _("Resource group counts left inconsistent\n")); @@ -229,9 +230,11 @@ static enum update_flags update_rgrp(struct gfs2_sbd *sbp, struct rgrp_list *rgp int pass5(struct gfs2_sbd *sbp) { osi_list_t *tmp; - struct rgrp_list *rgp = NULL; + struct rgrp_list *rgd = NULL; uint32_t count[3]; uint64_t rg_count = 0; + struct gfs2_rgrp rg; + struct gfs2_buffer_head **rgbh; /* Reconcile RG bitmaps with fsck bitmap */ for(tmp = sbp->rglist.next; tmp != &sbp->rglist; tmp = tmp->next){ @@ -241,16 +244,27 @@ int pass5(struct gfs2_sbd *sbp) return FSCK_OK; log_info( _("Verifying Resource Group #%" PRIu64 "\n"), rg_count); memset(count, 0, sizeof(count)); - rgp = osi_list_entry(tmp, struct rgrp_list, list); + rgd = osi_list_entry(tmp, struct rgrp_list, list); - if(gfs2_rgrp_read(sbp, rgp)){ + if(!(rgbh = (struct gfs2_buffer_head **) + malloc(rgd->ri.ri_length * + sizeof(struct gfs2_buffer_head *)))) + return FSCK_ERROR; + if(!memset(rgbh, 0, rgd->ri.ri_length * + sizeof(struct gfs2_buffer_head *))) { + free(rgbh); + return FSCK_ERROR; + } + if(gfs2_rgrp_read(sbp, rgd, rgbh, &rg)){ stack; + free(rgbh); return FSCK_ERROR; } rg_count++; /* Compare the bitmaps and report the differences */ - f = update_rgrp(sbp, rgp, count); - gfs2_rgrp_relse(rgp, f); + f = update_rgrp(sbp, rgd, count, rgbh, &rg); + gfs2_rgrp_relse(rgd, f, rgbh); + free(rgbh); } /* Fix up superblock info based on this - don't think there's * anything to do here... */ diff --git a/gfs2/fsck/rgrepair.c b/gfs2/fsck/rgrepair.c index 9d28b1a..cc5b2ca 100644 --- a/gfs2/fsck/rgrepair.c +++ b/gfs2/fsck/rgrepair.c @@ -142,7 +142,7 @@ static int gfs2_rindex_rebuild(struct gfs2_sbd *sdp, osi_list_t *ret_list, for (blk = sdp->sb_addr + 1; blk < sdp->device.length && number_of_rgs < 6; blk++) { - bh = bread(&sdp->nvbuf_list, blk); + bh = bread(&sdp->buf_list, blk); if (((blk == sdp->sb_addr + 1) || (!gfs2_check_meta(bh, GFS2_METATYPE_RG))) && !is_false_rg(blk)) { @@ -220,7 +220,7 @@ static int gfs2_rindex_rebuild(struct gfs2_sbd *sdp, osi_list_t *ret_list, for (blk = sdp->sb_addr + 1; blk <= sdp->device.length; blk += block_bump) { log_debug( _("Block 0x%" PRIx64 "\n"), blk); - bh = bread(&sdp->nvbuf_list, blk); + bh = bread(&sdp->buf_list, blk); rg_was_fnd = (!gfs2_check_meta(bh, GFS2_METATYPE_RG)); brelse(bh, not_updated); /* Allocate a new RG and index. */ @@ -254,7 +254,7 @@ static int gfs2_rindex_rebuild(struct gfs2_sbd *sdp, osi_list_t *ret_list, for (fwd_block = blk + 1; fwd_block < sdp->device.length; fwd_block++) { - bh = bread(&sdp->nvbuf_list, fwd_block); + bh = bread(&sdp->buf_list, fwd_block); bitmap_was_fnd = (!gfs2_check_meta(bh, GFS2_METATYPE_RB)); brelse(bh, not_updated); @@ -265,13 +265,6 @@ static int gfs2_rindex_rebuild(struct gfs2_sbd *sdp, osi_list_t *ret_list, } /* for subsequent bitmaps */ gfs2_compute_bitstructs(sdp, calc_rgd); - log_debug( _("Memory allocated for rg at 0x%llx, bh: %p\n"), - (unsigned long long)calc_rgd->ri.ri_addr, - calc_rgd->bh); - if (!calc_rgd->bh) { - log_crit( _("Can't allocate memory for bitmap repair.\n")); - return -1; - } calc_rgd->ri.ri_data0 = calc_rgd->ri.ri_addr + calc_rgd->ri.ri_length; if (prev_rgd) { @@ -386,37 +379,38 @@ static int gfs2_rindex_calculate(struct gfs2_sbd *sdp, osi_list_t *ret_list, * rewrite_rg_block - rewrite ("fix") a buffer with rg or bitmap data * returns: 0 if the rg was repaired, otherwise 1 */ -static int rewrite_rg_block(struct gfs2_sbd *sdp, struct rgrp_list *rg, - uint64_t errblock) +static int rewrite_rg_block(struct gfs2_sbd *sdp, struct rgrp_list *rgd, + uint64_t errblock, struct gfs2_buffer_head **rgbh, + struct gfs2_rgrp *rg) { - int x = errblock - rg->ri.ri_addr; + int x = errblock - rgd->ri.ri_addr; log_err( _("Block #%"PRIu64" (0x%" PRIx64") (%d of %d) is neither" " GFS2_METATYPE_RB nor GFS2_METATYPE_RG.\n"), - rg->bh[x]->b_blocknr, rg->bh[x]->b_blocknr, - (int)x+1, (int)rg->ri.ri_length); + rgbh[x]->b_blocknr, rgbh[x]->b_blocknr, + (int)x+1, (int)rgd->ri.ri_length); errors_found++; if (query(&opts, "Fix the RG? (y/n)")) { errors_corrected++; log_err( _("Attempting to repair the RG.\n")); - rg->bh[x] = bread(&sdp->nvbuf_list, rg->ri.ri_addr + x); + rgbh[x] = bread(&sdp->buf_list, rgd->ri.ri_addr + x); if (x) { struct gfs2_meta_header mh; mh.mh_magic = GFS2_MAGIC; mh.mh_type = GFS2_METATYPE_RB; mh.mh_format = GFS2_FORMAT_RB; - gfs2_meta_header_out(&mh, rg->bh[x]->b_data); + gfs2_meta_header_out(&mh, rgbh[x]->b_data); } else { - memset(&rg->rg, 0, sizeof(struct gfs2_rgrp)); - rg->rg.rg_header.mh_magic = GFS2_MAGIC; - rg->rg.rg_header.mh_type = GFS2_METATYPE_RG; - rg->rg.rg_header.mh_format = GFS2_FORMAT_RG; - rg->rg.rg_free = rg->ri.ri_data; - gfs2_rgrp_out(&rg->rg, rg->bh[x]->b_data); + memset(rg, 0, sizeof(struct gfs2_rgrp)); + rg->rg_header.mh_magic = GFS2_MAGIC; + rg->rg_header.mh_type = GFS2_METATYPE_RG; + rg->rg_header.mh_format = GFS2_FORMAT_RG; + rg->rg_free = rgd->ri.ri_data; + gfs2_rgrp_out(rg, rgbh[x]->b_data); } - brelse(rg->bh[x], updated); + brelse(rgbh[x], updated); return 0; } return 1; @@ -437,6 +431,7 @@ int rg_repair(struct gfs2_sbd *sdp, int trust_lvl, int *rg_count) int calc_rg_count = 0, rgcount_from_index, rg; osi_list_t *exp, *act; /* expected, actual */ struct gfs2_rindex buf; + int bitmap_blocks; if (trust_lvl == blind_faith) return 0; @@ -445,7 +440,7 @@ int rg_repair(struct gfs2_sbd *sdp, int trust_lvl, int *rg_count) error = gfs2_rindex_calculate(sdp, &expected_rglist, &calc_rg_count); if (error) { /* If calculated RGs don't match the fs */ - gfs2_rgrp_free(&expected_rglist, not_updated); + gfs2_rgrp_free(&expected_rglist); return -1; } } @@ -454,18 +449,18 @@ int rg_repair(struct gfs2_sbd *sdp, int trust_lvl, int *rg_count) &calc_rg_count); if (error) { log_crit( _("Error rebuilding rg list.\n")); - gfs2_rgrp_free(&expected_rglist, not_updated); + gfs2_rgrp_free(&expected_rglist); return -1; } sdp->rgrps = calc_rg_count; } /* Read in the rindex */ osi_list_init(&sdp->rglist); /* Just to be safe */ - rindex_read(sdp, 0, &rgcount_from_index); + rindex_read(sdp, 0, &rgcount_from_index, &bitmap_blocks); if (sdp->md.riinode->i_di.di_size % sizeof(struct gfs2_rindex)) { log_warn( _("WARNING: rindex file is corrupt.\n")); - gfs2_rgrp_free(&expected_rglist, not_updated); - gfs2_rgrp_free(&sdp->rglist, not_updated); + gfs2_rgrp_free(&expected_rglist); + gfs2_rgrp_free(&sdp->rglist); return -1; } log_warn( _("L%d: number of rgs expected = %lld.\n"), trust_lvl + 1, @@ -473,8 +468,8 @@ int rg_repair(struct gfs2_sbd *sdp, int trust_lvl, int *rg_count) if (calc_rg_count != sdp->rgrps) { log_warn( _("L%d: They don't match; either (1) the fs was extended, (2) an odd\n"), trust_lvl + 1); log_warn( _("L%d: rg size was used, or (3) we have a corrupt rg index.\n"), trust_lvl + 1); - gfs2_rgrp_free(&expected_rglist, not_updated); - gfs2_rgrp_free(&sdp->rglist, not_updated); + gfs2_rgrp_free(&expected_rglist); + gfs2_rgrp_free(&sdp->rglist); return -1; } /* ------------------------------------------------------------- */ @@ -505,8 +500,8 @@ int rg_repair(struct gfs2_sbd *sdp, int trust_lvl, int *rg_count) trust_lvl + 1); log_warn( _("%d out of %d RGs did not match what was expected.\n"), descrepencies, rg); - gfs2_rgrp_free(&expected_rglist, not_updated); - gfs2_rgrp_free(&sdp->rglist, not_updated); + gfs2_rgrp_free(&expected_rglist); + gfs2_rgrp_free(&sdp->rglist); return -1; } /* ------------------------------------------------------------- */ @@ -546,8 +541,6 @@ int rg_repair(struct gfs2_sbd *sdp, int trust_lvl, int *rg_count) /* Therefore, gfs2_compute_bitstructs might */ /* have malloced the wrong length for bitmap */ /* buffers. So we have to redo it. */ - if (actual->bh) - free(actual->bh); if (actual->bits) free(actual->bits); } @@ -567,28 +560,46 @@ int rg_repair(struct gfs2_sbd *sdp, int trust_lvl, int *rg_count) struct rgrp_list *rgd; uint64_t prev_err = 0, errblock; int i; + struct gfs2_rgrp rgrp; + struct gfs2_buffer_head **rgbh; /* Now we try repeatedly to read in the rg. For every block */ /* we encounter that has errors, repair it and try again. */ i = 0; do { rgd = osi_list_entry(act, struct rgrp_list, list); - errblock = gfs2_rgrp_read(sdp, rgd); + + if(!(rgbh = (struct gfs2_buffer_head **) + malloc(rgd->ri.ri_length * + sizeof(struct gfs2_buffer_head *)))) + return -1; + if(!memset(rgbh, 0, bitmap_blocks * + sizeof(struct gfs2_buffer_head *))) { + free(rgbh); + return -1; + } + + errblock = gfs2_rgrp_read(sdp, rgd, rgbh, &rgrp); if (errblock) { - if (errblock == prev_err) + if (errblock == prev_err) { + free(rgbh); break; + } prev_err = errblock; - rewrite_rg_block(sdp, rgd, errblock); + rewrite_rg_block(sdp, rgd, errblock, rgbh, + &rgrp); } else { - gfs2_rgrp_relse(rgd, not_updated); + gfs2_rgrp_relse(rgd, not_updated, rgbh); + free(rgbh); break; } + free(rgbh); i++; } while (i < rgd->ri.ri_length); } *rg_count = rg; - gfs2_rgrp_free(&expected_rglist, not_updated); - gfs2_rgrp_free(&sdp->rglist, not_updated); + gfs2_rgrp_free(&expected_rglist); + gfs2_rgrp_free(&sdp->rglist); return 0; } diff --git a/gfs2/libgfs2/block_list.c b/gfs2/libgfs2/block_list.c index b0d7000..5d1851b 100644 --- a/gfs2/libgfs2/block_list.c +++ b/gfs2/libgfs2/block_list.c @@ -40,8 +40,8 @@ struct gfs2_block_list *gfs2_block_list_create(struct gfs2_sbd *sdp, if (!il || !memset(il, 0, sizeof(*il))) return NULL; - if(gfs2_bitmap_create(&il->list.gbmap.group_map, size, 4)) { - *addl_mem_needed = il->list.gbmap.group_map.mapsize; + if(gfs2_bitmap_create(&il->list.gbmap, size, 4)) { + *addl_mem_needed = il->list.gbmap.mapsize; free(il); il = NULL; } @@ -169,7 +169,7 @@ int gfs2_block_mark(struct gfs2_sbd *sdp, struct gfs2_block_list *il, else if(mark == gfs2_eattr_block) gfs2_special_set(&sdp->eattr_blocks, block); else - err = gfs2_bitmap_set(&il->list.gbmap.group_map, block, + err = gfs2_bitmap_set(&il->list.gbmap, block, mark_to_gbmap[mark]); return err; } @@ -192,7 +192,7 @@ int gfs2_block_unmark(struct gfs2_sbd *sdp, struct gfs2_block_list *il, break; default: /* FIXME: check types */ - err = gfs2_bitmap_clear(&il->list.gbmap.group_map, block); + err = gfs2_bitmap_clear(&il->list.gbmap, block); break; } return err; @@ -207,7 +207,7 @@ int gfs2_block_clear(struct gfs2_sbd *sdp, struct gfs2_block_list *il, gfs2_dup_clear(&sdp->dup_blocks, block); gfs2_special_clear(&sdp->bad_blocks, block); gfs2_special_clear(&sdp->eattr_blocks, block); - err = gfs2_bitmap_clear(&il->list.gbmap.group_map, block); + err = gfs2_bitmap_clear(&il->list.gbmap, block); return err; } @@ -236,8 +236,7 @@ int gfs2_block_check(struct gfs2_sbd *sdp, struct gfs2_block_list *il, val->dup_block = 1; if (blockfind(&sdp->eattr_blocks, block)) val->eattr_block = 1; - if((err = gfs2_bitmap_get(&il->list.gbmap.group_map, block, - &val->block_type))) + if((err = gfs2_bitmap_get(&il->list.gbmap, block, &val->block_type))) return err; return 0; } @@ -245,7 +244,7 @@ int gfs2_block_check(struct gfs2_sbd *sdp, struct gfs2_block_list *il, void *gfs2_block_list_destroy(struct gfs2_sbd *sdp, struct gfs2_block_list *il) { if(il) { - gfs2_bitmap_destroy(&il->list.gbmap.group_map); + gfs2_bitmap_destroy(&il->list.gbmap); free(il); il = NULL; } diff --git a/gfs2/libgfs2/buf.c b/gfs2/libgfs2/buf.c index 6c7e181..48b1f5c 100644 --- a/gfs2/libgfs2/buf.c +++ b/gfs2/libgfs2/buf.c @@ -44,6 +44,10 @@ static void write_buffer(struct buf_list *bl, struct gfs2_buffer_head *bh) do_write(sdp->device_fd, bh->b_data, sdp->bsize); sdp->writes++; } + bh->b_blocknr = -1; + bh->b_data = NULL; + bh->b_count = -1; + bh->b_changed = -1; free(bh); } diff --git a/gfs2/libgfs2/fs_bits.c b/gfs2/libgfs2/fs_bits.c index b295261..2183aa5 100644 --- a/gfs2/libgfs2/fs_bits.c +++ b/gfs2/libgfs2/fs_bits.c @@ -13,6 +13,7 @@ #include <inttypes.h> #include <stdlib.h> +#include <string.h> #include <unistd.h> #include "libgfs2.h" @@ -171,6 +172,8 @@ int gfs2_set_bitmap(struct gfs2_sbd *sdp, uint64_t blkno, int state) struct rgrp_list *rgd; unsigned char *byte, cur_state; unsigned int bit; + struct gfs2_rgrp rg; + struct gfs2_buffer_head **rgbh; /* FIXME: should GFS2_BLKST_INVALID be allowed */ if ((state < GFS2_BLKST_FREE) || (state > GFS2_BLKST_DINODE)) @@ -181,8 +184,20 @@ int gfs2_set_bitmap(struct gfs2_sbd *sdp, uint64_t blkno, int state) if(!rgd) return -1; - if(gfs2_rgrp_read(sdp, rgd)) + if(!(rgbh = (struct gfs2_buffer_head **) + malloc(rgd->ri.ri_length * + sizeof(struct gfs2_buffer_head *)))) return -1; + if(!memset(rgbh, 0, rgd->ri.ri_length * + sizeof(struct gfs2_buffer_head *))) { + free(rgbh); + return -1; + } + + if(gfs2_rgrp_read(sdp, rgd, rgbh, &rg)) { + free(rgbh); + return -1; + } rgrp_block = (uint32_t)(blkno - rgd->ri.ri_data0); for(buf= 0; buf < rgd->ri.ri_length; buf++){ bits = &(rgd->bits[buf]); @@ -190,7 +205,7 @@ int gfs2_set_bitmap(struct gfs2_sbd *sdp, uint64_t blkno, int state) break; } - byte = (unsigned char *)(rgd->bh[buf]->b_data + bits->bi_offset) + + byte = (unsigned char *)(rgbh[buf]->b_data + bits->bi_offset) + (rgrp_block/GFS2_NBBY - bits->bi_start); bit = (rgrp_block % GFS2_NBBY) * GFS2_BIT_SIZE; @@ -198,12 +213,13 @@ int gfs2_set_bitmap(struct gfs2_sbd *sdp, uint64_t blkno, int state) *byte ^= cur_state << bit; *byte |= state << bit; - gfs2_rgrp_relse(rgd, updated); + gfs2_rgrp_relse(rgd, updated, rgbh); + free(rgbh); return 0; } /* - * fs_get_bitmap - get value of FS bitmap + * gfs2_get_bitmap - get value of FS bitmap * @sdp: super block * @blkno: block number relative to file system * @@ -220,12 +236,15 @@ int gfs2_set_bitmap(struct gfs2_sbd *sdp, uint64_t blkno, int state) int gfs2_get_bitmap(struct gfs2_sbd *sdp, uint64_t blkno, struct rgrp_list *rgd) { - int buf, val; + int i, val; uint32_t rgrp_block; struct gfs2_bitmap *bits = NULL; unsigned int bit; unsigned char *byte; int local_rgd = 0; + struct gfs2_rgrp rg; + struct gfs2_buffer_head **rgbh; + int bitmap_blocks = rgd->length; if(gfs2_check_range(sdp, blkno)) return -1; @@ -235,30 +254,39 @@ int gfs2_get_bitmap(struct gfs2_sbd *sdp, uint64_t blkno, } if(rgd == NULL) return -1; - if(gfs2_rgrp_read(sdp, rgd)) + if(!(rgbh = (struct gfs2_buffer_head **) + malloc(bitmap_blocks * sizeof(struct gfs2_buffer_head *)))) + return -1; + if(!memset(rgbh, 0, bitmap_blocks * + sizeof(struct gfs2_buffer_head *))) { + free(rgbh); + return -1; + } + + if(gfs2_rgrp_read(sdp, rgd, rgbh, &rg)) return -1; rgrp_block = (uint32_t)(blkno - rgd->ri.ri_data0); - for(buf= 0; buf < rgd->ri.ri_length; buf++){ - bits = &(rgd->bits[buf]); + for(i= 0; i < rgd->ri.ri_length; i++){ + bits = &(rgd->bits[i]); if(rgrp_block < ((bits->bi_start + bits->bi_len)*GFS2_NBBY)){ break; } } - if(buf >= rgd->ri.ri_length){ - gfs2_rgrp_relse(rgd, not_updated); + if(i >= rgd->ri.ri_length){ + gfs2_rgrp_relse(rgd, not_updated, rgbh); return -1; } - byte = (unsigned char *)(rgd->bh[buf]->b_data + bits->bi_offset) + + byte = (unsigned char *)(rgbh[i]->b_data + bits->bi_offset) + (rgrp_block/GFS2_NBBY - bits->bi_start); bit = (rgrp_block % GFS2_NBBY) * GFS2_BIT_SIZE; val = ((*byte >> bit) & GFS2_BIT_MASK); if(local_rgd) - gfs2_rgrp_relse(rgd, not_updated); + gfs2_rgrp_relse(rgd, not_updated, rgbh); return val; } diff --git a/gfs2/libgfs2/fs_geometry.c b/gfs2/libgfs2/fs_geometry.c index 0ad7df4..86e50f9 100644 --- a/gfs2/libgfs2/fs_geometry.c +++ b/gfs2/libgfs2/fs_geometry.c @@ -120,7 +120,6 @@ void compute_rgrp_layout(struct gfs2_sbd *sdp, int rgsize_specified) rl->length = dev->length - (nrgrp - 1) * (dev->length / nrgrp); } - rl->rgf_flags = dev->rgf_flags; log_info("%d: start: %" PRIu64 " (0x%" PRIx64 "), length = %"PRIu64" (0x%" @@ -191,7 +190,7 @@ void build_rgrps(struct gfs2_sbd *sdp, int do_write) struct rgrp_list *rl; uint32_t rgblocks, bitblocks; struct gfs2_rindex *ri; - struct gfs2_rgrp *rg; + struct gfs2_rgrp rg; struct gfs2_meta_header mh; unsigned int x; struct gfs2_buffer_head *bh; @@ -205,7 +204,6 @@ void build_rgrps(struct gfs2_sbd *sdp, int do_write) tmp = tmp->next) { rl = osi_list_entry(tmp, struct rgrp_list, list); ri = &rl->ri; - rg = &rl->rg; rgblocks = rl->length; rgblocks2bitblocks(sdp->bsize, &rgblocks, &bitblocks); @@ -216,19 +214,20 @@ void build_rgrps(struct gfs2_sbd *sdp, int do_write) ri->ri_data = rgblocks; ri->ri_bitbytes = rgblocks / GFS2_NBBY; - rg->rg_header.mh_magic = GFS2_MAGIC; - rg->rg_header.mh_type = GFS2_METATYPE_RG; - rg->rg_header.mh_format = GFS2_FORMAT_RG; - rg->rg_flags = rl->rgf_flags; - rg->rg_free = rgblocks; + memset(&rg, 0, sizeof(rg)); + rg.rg_header.mh_magic = GFS2_MAGIC; + rg.rg_header.mh_type = GFS2_METATYPE_RG; + rg.rg_header.mh_format = GFS2_FORMAT_RG; + rg.rg_free = rgblocks; + rl->rg_free = rgblocks; if (do_write) { for (x = 0; x < bitblocks; x++) { - bh = bget(&sdp->nvbuf_list, rl->start + x); + bh = bget(&sdp->buf_list, rl->start + x); if (x) gfs2_meta_header_out(&mh, bh->b_data); else - gfs2_rgrp_out(rg, bh->b_data); + gfs2_rgrp_out(&rg, bh->b_data); brelse(bh, updated); } } diff --git a/gfs2/libgfs2/fs_ops.c b/gfs2/libgfs2/fs_ops.c index 7dacd43..4b13d5c 100644 --- a/gfs2/libgfs2/fs_ops.c +++ b/gfs2/libgfs2/fs_ops.c @@ -55,16 +55,17 @@ static uint64_t blk_alloc_i(struct gfs2_sbd *sdp, unsigned int type) osi_list_t *tmp, *head; struct rgrp_list *rl = NULL; struct gfs2_rindex *ri; - struct gfs2_rgrp *rg; + struct gfs2_rgrp rg; + struct gfs2_buffer_head **rgbh; unsigned int block, bn = 0, x = 0, y = 0; - struct gfs2_buffer_head *bh; unsigned int state; + memset(&rg, 0, sizeof(rg)); for (head = &sdp->rglist, tmp = head->next; tmp != head; tmp = tmp->next) { rl = osi_list_entry(tmp, struct rgrp_list, list); - if (rl->rg.rg_free) + if (rl->rg_free) break; } @@ -72,31 +73,43 @@ static uint64_t blk_alloc_i(struct gfs2_sbd *sdp, unsigned int type) die("out of space\n"); ri = &rl->ri; - rg = &rl->rg; + + if(!(rgbh = (struct gfs2_buffer_head **) + malloc(rl->ri.ri_length * + sizeof(struct gfs2_buffer_head *)))) + return -1; + if(!memset(rgbh, 0, rl->ri.ri_length * + sizeof(struct gfs2_buffer_head *))) { + free(rgbh); + return -1; + } for (block = 0; block < ri->ri_length; block++) { - bh = bread(&sdp->nvbuf_list, ri->ri_addr + block); + rgbh[block] = bread(&sdp->buf_list, ri->ri_addr + block); x = (block) ? sizeof(struct gfs2_meta_header) : sizeof(struct gfs2_rgrp); + if (!block) + gfs2_rgrp_in(&rg, rgbh[0]->b_data); for (; x < sdp->bsize; x++) for (y = 0; y < GFS2_NBBY; y++) { - state = (bh->b_data[x] >> (GFS2_BIT_SIZE * y)) & 0x03; + state = (rgbh[block]->b_data[x] >> + (GFS2_BIT_SIZE * y)) & 0x03; if (state == GFS2_BLKST_FREE) goto found; bn++; } - brelse(bh, FALSE); + brelse(rgbh[block], FALSE); } die("allocation is broken (1): %"PRIu64" %u\n", - (uint64_t)rl->ri.ri_addr, rl->rg.rg_free); + (uint64_t)rl->ri.ri_addr, rl->rg_free); found: if (bn >= ri->ri_bitbytes * GFS2_NBBY) die("allocation is broken (2): %u %u %"PRIu64" %u\n", bn, ri->ri_bitbytes * GFS2_NBBY, - (uint64_t)rl->ri.ri_addr, rl->rg.rg_free); + (uint64_t)rl->ri.ri_addr, rl->rg_free); switch (type) { case DATA: @@ -105,24 +118,25 @@ static uint64_t blk_alloc_i(struct gfs2_sbd *sdp, unsigned int type) break; case DINODE: state = GFS2_BLKST_DINODE; - rg->rg_dinodes++; + rg.rg_dinodes++; break; default: die("bad state\n"); } - bh->b_data[x] &= ~(0x03 << (GFS2_BIT_SIZE * y)); - bh->b_data[x] |= state << (GFS2_BIT_SIZE * y); - rg->rg_free--; + rgbh[block]->b_data[x] &= ~(0x03 << (GFS2_BIT_SIZE * y)); + rgbh[block]->b_data[x] |= state << (GFS2_BIT_SIZE * y); + rg.rg_free--; + rl->rg_free--; - brelse(bh, updated); + brelse(rgbh[block], updated); - bh = bread(&sdp->nvbuf_list, ri->ri_addr); - gfs2_rgrp_out(rg, bh->b_data); - brelse(bh, updated); + rgbh[0] = bread(&sdp->buf_list, ri->ri_addr); + gfs2_rgrp_out(&rg, rgbh[0]->b_data); + brelse(rgbh[0], updated); sdp->blks_alloced++; - + free(rgbh); return ri->ri_data0 + bn; } @@ -927,7 +941,7 @@ static int get_first_leaf(struct gfs2_inode *dip, uint32_t lindex, */ static int get_next_leaf(struct gfs2_inode *dip,struct gfs2_buffer_head *bh_in, - struct gfs2_buffer_head **bh_out) + struct gfs2_buffer_head **bh_out) { struct gfs2_leaf *leaf; @@ -1563,13 +1577,16 @@ void gfs2_free_block(struct gfs2_sbd *sdp, uint64_t block) { struct gfs2_buffer_head *bh; struct rgrp_list *rgd; + struct gfs2_rgrp rg; gfs2_set_bitmap(sdp, block, GFS2_BLKST_FREE); /* Adjust the free space count for the freed block */ rgd = gfs2_blk2rgrpd(sdp, block); /* find the rg for indir block */ - bh = bget(&sdp->nvbuf_list, rgd->ri.ri_addr); /* get the rg buffer */ - rgd->rg.rg_free++; /* adjust the free count */ - gfs2_rgrp_out(&rgd->rg, bh->b_data); /* back to the buffer */ + bh = bget(&sdp->buf_list, rgd->ri.ri_addr); /* get the rg buffer */ + gfs2_rgrp_in(&rg, bh->b_data); /* back to the buffer */ + rg.rg_free++; /* adjust the free count */ + rgd->rg_free++; + gfs2_rgrp_out(&rg, bh->b_data); /* back to the buffer */ brelse(bh, updated); /* release the buffer */ sdp->blks_alloced--; } @@ -1588,6 +1605,7 @@ int gfs2_freedi(struct gfs2_sbd *sdp, uint64_t diblock) uint32_t height; osi_list_t metalist[GFS2_MAX_META_HEIGHT]; osi_list_t *cur_list, *next_list, *tmp; + struct gfs2_rgrp rg; for (h = 0; h < GFS2_MAX_META_HEIGHT; h++) osi_list_init(&metalist[h]); @@ -1616,11 +1634,8 @@ int gfs2_freedi(struct gfs2_sbd *sdp, uint64_t diblock) gfs2_free_block(sdp, block); if (h == height - 1) /* if not metadata */ continue; /* don't queue it up */ - /* Read the next metadata block in the chain. - First see if it's on the nvbuf_list. */ - nbh = bfind(&sdp->nvbuf_list, block); - if (!nbh) - nbh = bread(&sdp->buf_list, block); + /* Read the next metadata block in the chain */ + nbh = bread(&sdp->buf_list, block); osi_list_add(&nbh->b_altlist, next_list); brelse(nbh, not_updated); } @@ -1634,13 +1649,12 @@ int gfs2_freedi(struct gfs2_sbd *sdp, uint64_t diblock) sdp->blks_alloced--; /* Now we have to adjust the rg freespace count and inode count: */ rgd = gfs2_blk2rgrpd(sdp, diblock); - /* The rg itself is in memory as rgd->rg, but there's most likely a */ - /* buffer in memory for the rg on disk because we used it to fix the */ - /* bitmaps, some of which are on the same block on disk. */ - bh = bread(&sdp->nvbuf_list, rgd->ri.ri_addr); /* get the buffer */ - rgd->rg.rg_free++; - rgd->rg.rg_dinodes--; /* one less inode in use */ - gfs2_rgrp_out(&rgd->rg, bh->b_data); + bh = bread(&sdp->buf_list, rgd->ri.ri_addr); /* get the buffer */ + gfs2_rgrp_in(&rg, bh->b_data); + rg.rg_free++; + rgd->rg_free++; + rg.rg_dinodes--; /* one less inode in use */ + gfs2_rgrp_out(&rg, bh->b_data); brelse(bh, updated); /* release the buffer */ sdp->dinodes_alloced--; return 0; diff --git a/gfs2/libgfs2/gfs1.c b/gfs2/libgfs2/gfs1.c index f9e5a6e..e783fdd 100644 --- a/gfs2/libgfs2/gfs1.c +++ b/gfs2/libgfs2/gfs1.c @@ -232,7 +232,8 @@ int gfs1_readi(struct gfs2_inode *ip, void *bufin, * * Returns: 0 on success, -1 on failure */ -int gfs1_rindex_read(struct gfs2_sbd *sdp, int fd, int *count1) +int gfs1_rindex_read(struct gfs2_sbd *sdp, int fd, int *count1, + int *bitmap_blocks) { unsigned int rg; int error; @@ -242,6 +243,7 @@ int gfs1_rindex_read(struct gfs2_sbd *sdp, int fd, int *count1) *count1 = 0; prev_rgd = NULL; + *bitmap_blocks = 0; for (rg = 0; ; rg++) { if (fd > 0) error = read(fd, &buf, sizeof(struct gfs2_rindex)); @@ -264,6 +266,8 @@ int gfs1_rindex_read(struct gfs2_sbd *sdp, int fd, int *count1) gfs2_rindex_in(&rgd->ri, (char *)&buf); + if (rgd->ri.ri_length > *bitmap_blocks) + *bitmap_blocks = rgd->ri.ri_length; rgd->start = rgd->ri.ri_addr; if (prev_rgd) { prev_length = rgd->start - prev_rgd->start; @@ -297,14 +301,28 @@ int gfs1_ri_update(struct gfs2_sbd *sdp, int fd, int *rgcount, int quiet) osi_list_t *tmp; int count1 = 0, count2 = 0; uint64_t errblock = 0; + struct gfs2_rgrp rg; + struct gfs2_buffer_head **rgbh = NULL; + int bitmap_blocks; - if (gfs1_rindex_read(sdp, fd, &count1)) + if (gfs1_rindex_read(sdp, fd, &count1, &bitmap_blocks)) goto fail; + + if(!(rgbh = (struct gfs2_buffer_head **) + malloc(bitmap_blocks * sizeof(struct gfs2_buffer_head *)))) + return -1; + if(!memset(rgbh, 0, bitmap_blocks * + sizeof(struct gfs2_buffer_head *))) { + free(rgbh); + return -1; + } for (tmp = sdp->rglist.next; tmp != &sdp->rglist; tmp = tmp->next) { rgd = osi_list_entry(tmp, struct rgrp_list, list); - errblock = gfs2_rgrp_read(sdp, rgd); - if (errblock) + errblock = gfs2_rgrp_read(sdp, rgd, rgbh, &rg); + if (errblock) { + free(rgbh); return errblock; + } count2++; if (!quiet && count2 % 100 == 0) { printf("."); @@ -316,10 +334,12 @@ int gfs1_ri_update(struct gfs2_sbd *sdp, int fd, int *rgcount, int quiet) if (count1 != count2) goto fail; + free(rgbh); return 0; fail: - gfs2_rgrp_free(&sdp->rglist, not_updated); + gfs2_rgrp_free(&sdp->rglist); + free(rgbh); return -1; } diff --git a/gfs2/libgfs2/libgfs2.h b/gfs2/libgfs2/libgfs2.h index ffd673c..70cf6cf 100644 --- a/gfs2/libgfs2/libgfs2.h +++ b/gfs2/libgfs2/libgfs2.h @@ -103,12 +103,10 @@ struct rgrp_list { osi_list_t list; uint64_t start; /* The offset of the beginning of this resource group */ uint64_t length; /* The length of this resource group */ - uint32_t rgf_flags; + uint32_t rg_free; /* Free blocks */ struct gfs2_rindex ri; - struct gfs2_rgrp rg; - gfs2_bitmap_t *bits; - struct gfs2_buffer_head **bh; + struct gfs2_bitmap *bits; }; struct gfs2_buffer_head { @@ -250,7 +248,6 @@ struct gfs2_sbd { unsigned int orig_journals; struct buf_list buf_list; /* transient buffer list */ - struct buf_list nvbuf_list; /* non-volatile buffer list */ struct gfs2_inode *master_dir; struct master_dir md; @@ -360,15 +357,8 @@ struct gfs2_block_query { uint8_t eattr_block; }; -struct gfs2_gbmap { - struct gfs2_bmap group_map; - struct gfs2_bmap bad_map; - struct gfs2_bmap dup_map; - struct gfs2_bmap eattr_map; -}; - union gfs2_block_lists { - struct gfs2_gbmap gbmap; + struct gfs2_bmap gbmap; }; /* bitmap implementation */ @@ -571,20 +561,19 @@ struct gfs_dinode { char di_reserved[56]; }; -void gfs1_lookup_block(struct gfs2_inode *ip, struct gfs2_buffer_head *bh, - unsigned int height, struct metapath *mp, - int create, int *new, uint64_t *block); -void gfs1_block_map(struct gfs2_inode *ip, uint64_t lblock, int *new, - uint64_t *dblock, uint32_t *extlen, int prealloc); -int gfs1_readi(struct gfs2_inode *ip, void *buf, uint64_t offset, - unsigned int size); -int gfs1_rindex_read(struct gfs2_sbd *sdp, int fd, int *count1); -int gfs1_ri_update(struct gfs2_sbd *sdp, int fd, int *rgcount, int quiet); -struct gfs2_inode *gfs_inode_get(struct gfs2_sbd *sdp, - struct gfs2_buffer_head *bh); - -/* locking.c */ -void test_locking(char *lockproto, char *locktable); +extern void gfs1_lookup_block(struct gfs2_inode *ip, + struct gfs2_buffer_head *bh, + unsigned int height, struct metapath *mp, + int create, int *new, uint64_t *block); +extern void gfs1_block_map(struct gfs2_inode *ip, uint64_t lblock, int *new, + uint64_t *dblock, uint32_t *extlen, int prealloc); +extern int gfs1_readi(struct gfs2_inode *ip, void *buf, uint64_t offset, + unsigned int size); +extern int gfs1_rindex_read(struct gfs2_sbd *sdp, int fd, int *count1, + int *bitmap_blocks); +extern int gfs1_ri_update(struct gfs2_sbd *sdp, int fd, int *rgcount, int quiet); +extern struct gfs2_inode *gfs_inode_get(struct gfs2_sbd *sdp, + struct gfs2_buffer_head *bh); /* gfs2_log.c */ struct gfs2_options { @@ -696,38 +685,40 @@ int gfs2_find_jhead(struct gfs2_inode *ip, struct gfs2_log_header *head); int clean_journal(struct gfs2_inode *ip, struct gfs2_log_header *head); /* rgrp.c */ -int gfs2_compute_bitstructs(struct gfs2_sbd *sdp, struct rgrp_list *rgd); -struct rgrp_list *gfs2_blk2rgrpd(struct gfs2_sbd *sdp, uint64_t blk); -uint64_t gfs2_rgrp_read(struct gfs2_sbd *sdp, struct rgrp_list *rgd); -void gfs2_rgrp_relse(struct rgrp_list *rgd, enum update_flags updated); -void gfs2_rgrp_free(osi_list_t *rglist, enum update_flags updated); +extern int gfs2_compute_bitstructs(struct gfs2_sbd *sdp, struct rgrp_list *rgd); +extern struct rgrp_list *gfs2_blk2rgrpd(struct gfs2_sbd *sdp, uint64_t blk); +extern uint64_t gfs2_rgrp_read(struct gfs2_sbd *sdp, struct rgrp_list *rgd, + struct gfs2_buffer_head **bh, + struct gfs2_rgrp *rg); +extern void gfs2_rgrp_relse(struct rgrp_list *rgd, enum update_flags updated, + struct gfs2_buffer_head **bh); +extern void gfs2_rgrp_free(osi_list_t *rglist); /* structures.c */ -void build_master(struct gfs2_sbd *sdp); -void build_sb(struct gfs2_sbd *sdp, const unsigned char *uuid); -void build_jindex(struct gfs2_sbd *sdp); -void build_per_node(struct gfs2_sbd *sdp); -void build_inum(struct gfs2_sbd *sdp); -void build_statfs(struct gfs2_sbd *sdp); -void build_rindex(struct gfs2_sbd *sdp); -void build_quota(struct gfs2_sbd *sdp); -void build_root(struct gfs2_sbd *sdp); -void do_init_inum(struct gfs2_sbd *sdp); -void do_init_statfs(struct gfs2_sbd *sdp); -int gfs2_check_meta(struct gfs2_buffer_head *bh, int type); -int gfs2_set_meta(struct gfs2_buffer_head *bh, int type, int format); -int gfs2_next_rg_meta(struct rgrp_list *rgd, uint64_t *block, int first); -int gfs2_next_rg_meta_free(struct rgrp_list *rgd, uint64_t *block, int first, - int *mfree); -int gfs2_next_rg_metatype(struct gfs2_sbd *sdp, struct rgrp_list *rgd, - uint64_t *block, uint32_t type, int first); +extern void build_master(struct gfs2_sbd *sdp); +extern void build_sb(struct gfs2_sbd *sdp, const unsigned char *uuid); +extern void build_jindex(struct gfs2_sbd *sdp); +extern void build_per_node(struct gfs2_sbd *sdp); +extern void build_inum(struct gfs2_sbd *sdp); +extern void build_statfs(struct gfs2_sbd *sdp); +extern void build_rindex(struct gfs2_sbd *sdp); +extern void build_quota(struct gfs2_sbd *sdp); +extern void build_root(struct gfs2_sbd *sdp); +extern void do_init_inum(struct gfs2_sbd *sdp); +extern void do_init_statfs(struct gfs2_sbd *sdp); +extern int gfs2_check_meta(struct gfs2_buffer_head *bh, int type); +extern int gfs2_next_rg_meta(struct gfs2_sbd *sdp, struct rgrp_list *rgd, + uint64_t *block, int first); +extern int gfs2_next_rg_metatype(struct gfs2_sbd *sdp, struct rgrp_list *rgd, + uint64_t *block, uint32_t type, int first); /* super.c */ -int check_sb(struct gfs2_sb *sb); -int read_sb(struct gfs2_sbd *sdp); -int ji_update(struct gfs2_sbd *sdp); -int rindex_read(struct gfs2_sbd *sdp, int fd, int *count1); -int ri_update(struct gfs2_sbd *sdp, int fd, int *rgcount); -int write_sb(struct gfs2_sbd *sdp); +extern int check_sb(struct gfs2_sb *sb); +extern int read_sb(struct gfs2_sbd *sdp); +extern int ji_update(struct gfs2_sbd *sdp); +extern int rindex_read(struct gfs2_sbd *sdp, int fd, int *count1, + int *bitmap_blocks); +extern int ri_update(struct gfs2_sbd *sdp, int fd, int *rgcount); +extern int write_sb(struct gfs2_sbd *sdp); /* ondisk.c */ uint32_t gfs2_disk_hash(const char *data, int len); diff --git a/gfs2/libgfs2/rgrp.c b/gfs2/libgfs2/rgrp.c index 7bebb3f..9027909 100644 --- a/gfs2/libgfs2/rgrp.c +++ b/gfs2/libgfs2/rgrp.c @@ -85,14 +85,6 @@ int gfs2_compute_bitstructs(struct gfs2_sbd *sdp, struct rgrp_list *rgd) rgd->bits[length - 1].bi_len) * GFS2_NBBY != rgd->ri.ri_data) return -1; - if (rgd->bh) /* If we already have a bh allocated */ - return 0; /* don't want to allocate another */ - if(!(rgd->bh = (struct gfs2_buffer_head **) - malloc(length * sizeof(struct gfs2_buffer_head *)))) - return -1; - if(!memset(rgd->bh, 0, length * sizeof(struct gfs2_buffer_head *))) - return -1; - return 0; } @@ -127,51 +119,47 @@ struct rgrp_list *gfs2_blk2rgrpd(struct gfs2_sbd *sdp, uint64_t blk) * @rgd - resource group structure * returns: 0 if no error, otherwise the block number that failed */ -uint64_t gfs2_rgrp_read(struct gfs2_sbd *sdp, struct rgrp_list *rgd) +uint64_t gfs2_rgrp_read(struct gfs2_sbd *sdp, struct rgrp_list *rgd, + struct gfs2_buffer_head **bh, struct gfs2_rgrp *rg) { int x, length = rgd->ri.ri_length; for (x = 0; x < length; x++){ - rgd->bh[x] = bread(&sdp->nvbuf_list, rgd->ri.ri_addr + x); - if(gfs2_check_meta(rgd->bh[x], + bh[x] = bread(&sdp->buf_list, rgd->ri.ri_addr + x); + if(gfs2_check_meta(bh[x], (x) ? GFS2_METATYPE_RB : GFS2_METATYPE_RG)) { uint64_t error; error = rgd->ri.ri_addr + x; for (; x >= 0; x--) - brelse(rgd->bh[x], not_updated); + brelse(bh[x], not_updated); return error; } } - gfs2_rgrp_in(&rgd->rg, rgd->bh[0]->b_data); + gfs2_rgrp_in(rg, bh[0]->b_data); + rgd->rg_free = rg->rg_free; return 0; } -void gfs2_rgrp_relse(struct rgrp_list *rgd, enum update_flags is_updated) +void gfs2_rgrp_relse(struct rgrp_list *rgd, enum update_flags is_updated, + struct gfs2_buffer_head **bh) { int x, length = rgd->ri.ri_length; for (x = 0; x < length; x++) - brelse(rgd->bh[x], is_updated); + brelse(bh[x], is_updated); } -void gfs2_rgrp_free(osi_list_t *rglist, enum update_flags is_updated) +void gfs2_rgrp_free(osi_list_t *rglist) { struct rgrp_list *rgd; while(!osi_list_empty(rglist->next)){ rgd = osi_list_entry(rglist->next, struct rgrp_list, list); - if (rgd->bh && rgd->bh[0] && /* if a buffer exists and */ - rgd->bh[0]->b_count) /* the 1st buffer is allocated */ - gfs2_rgrp_relse(rgd, is_updated); /* free them all. */ if(rgd->bits) free(rgd->bits); - if(rgd->bh) { - free(rgd->bh); - rgd->bh = NULL; - } osi_list_del(&rgd->list); free(rgd); } diff --git a/gfs2/libgfs2/structures.c b/gfs2/libgfs2/structures.c index 43a7e0f..2b63ad2 100644 --- a/gfs2/libgfs2/structures.c +++ b/gfs2/libgfs2/structures.c @@ -475,12 +475,14 @@ int gfs2_set_meta(struct gfs2_buffer_head *bh, int type, int format) * * Returns: 0 on success, -1 when finished */ -int gfs2_next_rg_meta(struct rgrp_list *rgd, uint64_t *block, int first) +int gfs2_next_rg_meta(struct gfs2_sbd *sdp, struct rgrp_list *rgd, + uint64_t *block, int first) { struct gfs2_bitmap *bits = NULL; uint32_t length = rgd->ri.ri_length; uint32_t blk = (first)? 0: (uint32_t)((*block+1)-rgd->ri.ri_data0); int i; + struct gfs2_buffer_head *bh; if(!first && (*block < rgd->ri.ri_data0)) { log_err("next_rg_meta: Start block is outside rgrp bounds.\n"); @@ -494,14 +496,17 @@ int gfs2_next_rg_meta(struct rgrp_list *rgd, uint64_t *block, int first) } for(; i < length; i++){ bits = &rgd->bits[i]; - blk = gfs2_bitfit((unsigned char *)rgd->bh[i]->b_data + + bh = bread(&sdp->buf_list, rgd->ri.ri_addr + i); + blk = gfs2_bitfit((unsigned char *)bh->b_data + bits->bi_offset, bits->bi_len, blk, GFS2_BLKST_DINODE); if(blk != BFITNOENT){ *block = blk + (bits->bi_start * GFS2_NBBY) + rgd->ri.ri_data0; + brelse(bh, not_updated); break; } blk=0; + brelse(bh, not_updated); } if(i == length) return -1; @@ -509,71 +514,6 @@ int gfs2_next_rg_meta(struct rgrp_list *rgd, uint64_t *block, int first) } /** - * gfs2_next_rg_meta_free - finds free or used metadata - * @rgd: - * @block: - * @first: if set, start at zero and ignore block - * - * The position to start looking from is *block. When a block - * is found, it is returned in block. - * - * Returns: 0 on success, -1 when finished - */ -int gfs2_next_rg_meta_free(struct rgrp_list *rgd, uint64_t *block, int first, - int *mfree) -{ - gfs2_bitmap_t *bits = NULL; - uint32_t length = rgd->ri.ri_length; - uint32_t blk = (first)? 0: (uint32_t)((*block+1)-rgd->ri.ri_data0); - uint32_t iblk, ublk, fblk; - int i; - - if(!first && (*block < rgd->ri.ri_data0)) { - log_err("next_rg_meta_free: Start block is outside rgrp bounds.\n"); - exit(1); - } - for(i=0; i < length; i++){ - bits = &rgd->bits[i]; - if(blk < bits->bi_len*GFS2_NBBY) - break; - blk -= bits->bi_len*GFS2_NBBY; - } - for(; i < length; i++){ - bits = &rgd->bits[i]; - - iblk = gfs2_bitfit((unsigned char *)rgd->bh[i]->b_data + - bits->bi_offset, bits->bi_len, blk, - GFS2_BLKST_DINODE); - ublk = gfs2_bitfit((unsigned char *)rgd->bh[i]->b_data + - bits->bi_offset, bits->bi_len, blk, - GFS2_BLKST_USED); - fblk = gfs2_bitfit((unsigned char *)rgd->bh[i]->b_data + - bits->bi_offset, bits->bi_len, blk, - GFS2_BLKST_FREE); - if(ublk < fblk) { - blk = ublk; - *mfree = 0; - } - else if(iblk < fblk) { - blk = iblk; - *mfree = 0; - } else { - blk = fblk; - *mfree = 1; - } - if(blk != BFITNOENT){ - *block = blk + (bits->bi_start * GFS2_NBBY) + rgd->ri.ri_data0; - break; - } - blk=0; - } - - if(i == length) - return -1; - return 0; -} - -/** * next_rg_metatype * @rgd: * @block: @@ -590,7 +530,7 @@ int gfs2_next_rg_metatype(struct gfs2_sbd *sdp, struct rgrp_list *rgd, do{ if (bh) brelse(bh, not_updated); - if (gfs2_next_rg_meta(rgd, block, first)) + if (gfs2_next_rg_meta(sdp, rgd, block, first)) return -1; bh = bread(&sdp->buf_list, *block); first = 0; diff --git a/gfs2/libgfs2/super.c b/gfs2/libgfs2/super.c index 9a42021..e31268e 100644 --- a/gfs2/libgfs2/super.c +++ b/gfs2/libgfs2/super.c @@ -175,7 +175,7 @@ int ji_update(struct gfs2_sbd *sdp) * * Returns: 0 on success, -1 on failure */ -int rindex_read(struct gfs2_sbd *sdp, int fd, int *count1) +int rindex_read(struct gfs2_sbd *sdp, int fd, int *count1, int *bitmap_blocks) { unsigned int rg; int error; @@ -185,6 +185,7 @@ int rindex_read(struct gfs2_sbd *sdp, int fd, int *count1) *count1 = 0; prev_rgd = NULL; + *bitmap_blocks = 0; for (rg = 0; ; rg++) { if (fd > 0) error = read(fd, &buf, sizeof(struct gfs2_rindex)); @@ -207,6 +208,8 @@ int rindex_read(struct gfs2_sbd *sdp, int fd, int *count1) gfs2_rindex_in(&rgd->ri, (char *)&buf); + if (rgd->ri.ri_length > *bitmap_blocks) + *bitmap_blocks = rgd->ri.ri_length; rgd->start = rgd->ri.ri_addr; if (prev_rgd) { prev_length = rgd->start - prev_rgd->start; @@ -241,19 +244,33 @@ int ri_update(struct gfs2_sbd *sdp, int fd, int *rgcount) osi_list_t *tmp; int count1 = 0, count2 = 0; uint64_t errblock = 0; + struct gfs2_rgrp rg; + struct gfs2_buffer_head **rgbh = NULL; + int bitmap_blocks; - if (rindex_read(sdp, fd, &count1)) + if (rindex_read(sdp, fd, &count1, &bitmap_blocks)) goto fail; + + if(!(rgbh = (struct gfs2_buffer_head **) + malloc(bitmap_blocks * sizeof(struct gfs2_buffer_head *)))) + return -1; + if(!memset(rgbh, 0, bitmap_blocks * + sizeof(struct gfs2_buffer_head *))) { + free(rgbh); + return -1; + } + for (tmp = sdp->rglist.next; tmp != &sdp->rglist; tmp = tmp->next) { enum update_flags f; f = not_updated; rgd = osi_list_entry(tmp, struct rgrp_list, list); - errblock = gfs2_rgrp_read(sdp, rgd); - if (errblock) + errblock = gfs2_rgrp_read(sdp, rgd, rgbh, &rg); + if (errblock) { + free(rgbh); return errblock; - else - gfs2_rgrp_relse(rgd, f); + } else + gfs2_rgrp_relse(rgd, f, rgbh); count2++; } @@ -261,10 +278,12 @@ int ri_update(struct gfs2_sbd *sdp, int fd, int *rgcount) if (count1 != count2) goto fail; + free(rgbh); return 0; fail: - gfs2_rgrp_free(&sdp->rglist, not_updated); + gfs2_rgrp_free(&sdp->rglist); + free(rgbh); return -1; } @@ -276,7 +295,6 @@ int write_sb(struct gfs2_sbd *sbp) gfs2_sb_out(&sbp->sd_sb, bh->b_data); brelse(bh, updated); bcommit(&sbp->buf_list); /* make sure the change gets to disk ASAP */ - bcommit(&sbp->nvbuf_list); /* make sure the change gets to disk ASAP */ return 0; } diff --git a/gfs2/mkfs/main_grow.c b/gfs2/mkfs/main_grow.c index 879f399..60082a9 100644 --- a/gfs2/mkfs/main_grow.c +++ b/gfs2/mkfs/main_grow.c @@ -187,7 +187,6 @@ static void initialize_new_portion(struct gfs2_sbd *sdp, int *old_rg_count) /* We're done with the libgfs portion, so commit it to disk. */ bsync(&sdp->buf_list); - bsync(&sdp->nvbuf_list); } /** @@ -286,8 +285,7 @@ main_grow(int argc, char *argv[]) device_geometry(sdp); log_info( _("Initializing lists...\n")); osi_list_init(&sdp->rglist); - init_buf_list(sdp, &sdp->buf_list, 128 << 20); - init_buf_list(sdp, &sdp->nvbuf_list, 0xffffffff); + init_buf_list(sdp, &sdp->buf_list, 1 << 20); sdp->sd_sb.sb_bsize = GFS2_DEFAULT_BSIZE; sdp->bsize = sdp->sd_sb.sb_bsize; diff --git a/gfs2/mkfs/main_mkfs.c b/gfs2/mkfs/main_mkfs.c index 9eb4761..67b552b 100644 --- a/gfs2/mkfs/main_mkfs.c +++ b/gfs2/mkfs/main_mkfs.c @@ -437,8 +437,7 @@ main_mkfs(int argc, char *argv[]) strcpy(sdp->lockproto, GFS2_DEFAULT_LOCKPROTO); sdp->time = time(NULL); osi_list_init(&sdp->rglist); - init_buf_list(sdp, &sdp->buf_list, 128 << 20); - init_buf_list(sdp, &sdp->nvbuf_list, 0xffffffff); + init_buf_list(sdp, &sdp->buf_list, 1 << 20); decode_arguments(argc, argv, sdp); if (sdp->rgsize == -1) /* if rg size not specified */ @@ -509,7 +508,6 @@ main_mkfs(int argc, char *argv[]) inode_put(sdp->md.inum, updated); inode_put(sdp->md.statfs, updated); bsync(&sdp->buf_list); - bsync(&sdp->nvbuf_list); error = fsync(sdp->device_fd); if (error) diff --git a/gfs2/tool/df.c b/gfs2/tool/df.c index 3dbfd46..025fc85 100644 --- a/gfs2/tool/df.c +++ b/gfs2/tool/df.c @@ -113,7 +113,6 @@ do_df_one(char *path) sbd.qcsize = GFS2_DEFAULT_QCSIZE; osi_list_init(&sbd.rglist); init_buf_list(&sbd, &sbd.buf_list, 128 << 20); - init_buf_list(&sbd, &sbd.nvbuf_list, 0xffffffff); do_lseek(sbd.device_fd, 0x10 * sbd.bsize); do_read(sbd.device_fd, buf, sbd.bsize); /* read in the superblock */