commit 37cf0257bf6298df38ca74ee8577bac5a40e6598 Author: Andrew Price Date: Thu Feb 6 04:25:27 2014 +0000 libgfs2: Superblock building and writing improvements build_sb was creating the sb, setting its fields from an sdp and then writing it, and also zeroing the gap before the sb on the device in a block-by-block way using buffer_heads. This patch splits the build_sb function into lgfs2_sb_init and lgfs2_sb_write which operate on gfs2_sb structures instead of gfs2_sbds. lgfs2_sb_write now uses pwritev to zero the initial blocks and write the sb to an fd. get_random_bytes has been moved into structures.c and made static as only lgfs2_sb_init now uses it. Resolves: rhbz#1063842 Signed-off-by: Andrew Price diff --git a/gfs2/convert/gfs2_convert.c b/gfs2/convert/gfs2_convert.c index 719ba9c..ce056a7 100644 --- a/gfs2/convert/gfs2_convert.c +++ b/gfs2/convert/gfs2_convert.c @@ -2374,7 +2374,8 @@ int main(int argc, char **argv) bh = bread(&sb2, sb2.sb_addr); sb2.sd_sb.sb_fs_format = GFS2_FORMAT_FS; sb2.sd_sb.sb_multihost_format = GFS2_FORMAT_MULTI; - gfs2_sb_out(&sb2.sd_sb, bh); + gfs2_sb_out(&sb2.sd_sb, bh->b_data); + bmodified(bh); brelse(bh); error = fsync(sb2.device_fd); diff --git a/gfs2/edit/hexedit.c b/gfs2/edit/hexedit.c index f0d9789..36f6600 100644 --- a/gfs2/edit/hexedit.c +++ b/gfs2/edit/hexedit.c @@ -2132,7 +2132,8 @@ static void process_field(const char *field, const char *nstr) gfs2_sb_assigns(&lsb, field, nstr); else gfs2_sb_assignval(&lsb, field, newval); - gfs2_sb_out(&lsb, rbh); + gfs2_sb_out(&lsb, rbh->b_data); + bmodified(rbh); if (!termlines) gfs2_sb_printval(&lsb, field); } else { diff --git a/gfs2/fsck/initialize.c b/gfs2/fsck/initialize.c index 5758607..0f33aa6 100644 --- a/gfs2/fsck/initialize.c +++ b/gfs2/fsck/initialize.c @@ -60,7 +60,7 @@ static int block_mounters(struct gfs2_sbd *sdp, int block_em) } } - if (write_sb(sdp)) { + if (lgfs2_sb_write(&sdp->sd_sb, sdp->device_fd, sdp->bsize)) { stack; return -1; } @@ -1130,7 +1130,6 @@ static int sb_repair(struct gfs2_sbd *sdp) { uint64_t half; uint32_t known_bsize = 0; - unsigned char uuid[16]; int error = 0; memset(&fix_md, 0, sizeof(fix_md)); @@ -1205,9 +1204,8 @@ static int sb_repair(struct gfs2_sbd *sdp) } } /* Step 3 - Rebuild the lock protocol and file system table name */ - strcpy(sdp->lockproto, GFS2_DEFAULT_LOCKPROTO); - strcpy(sdp->locktable, "unknown"); if (query(_("Okay to fix the GFS2 superblock? (y/n)"))) { + struct gfs2_sb sb; log_info(_("Found system master directory at: 0x%llx\n"), sdp->sd_sb.sb_master_dir.no_addr); sdp->master_dir = lgfs2_inode_read(sdp, @@ -1226,8 +1224,12 @@ static int sb_repair(struct gfs2_sbd *sdp) log_crit(_("Error reading root inode: %s\n"), strerror(errno)); return -1; } - get_random_bytes(uuid, sizeof(uuid)); - build_sb(sdp, uuid); + lgfs2_sb_init(&sb, sdp->bsize); + strcpy(sb.sb_lockproto, GFS2_DEFAULT_LOCKPROTO); + strcpy(sb.sb_locktable, "unknown"); + sb.sb_master_dir = sdp->master_dir->i_di.di_num; + sb.sb_root_dir = sdp->md.rooti->i_di.di_num; + lgfs2_sb_write(&sb, sdp->device_fd, sdp->bsize); inode_put(&sdp->md.rooti); inode_put(&sdp->master_dir); sb_fixed = 1; diff --git a/gfs2/libgfs2/libgfs2.h b/gfs2/libgfs2/libgfs2.h index e785017..6710e72 100644 --- a/gfs2/libgfs2/libgfs2.h +++ b/gfs2/libgfs2/libgfs2.h @@ -724,7 +724,6 @@ extern int mount_gfs2_meta(struct gfs2_sbd *sdp); extern void cleanup_metafs(struct gfs2_sbd *sdp); extern int set_sysfs(const char *fsname, const char *filename, const char *val); extern int is_fsname(char *name); -extern void get_random_bytes(void *buf, int nbytes); /* recovery.c */ extern void gfs2_replay_incr_blk(struct gfs2_inode *ip, unsigned int *blk); @@ -758,7 +757,8 @@ static inline unsigned int rgrp_size(struct rgrp_tree *rgrp) /* structures.c */ extern int build_master(struct gfs2_sbd *sdp); -extern void build_sb(struct gfs2_sbd *sdp, const unsigned char *uuid); +extern void lgfs2_sb_init(struct gfs2_sb *sb, unsigned bsize); +extern int lgfs2_sb_write(const struct gfs2_sb *sb, int fd, const unsigned bsize); extern int build_journal(struct gfs2_sbd *sdp, int j, struct gfs2_inode *jindex); extern int build_jindex(struct gfs2_sbd *sdp); @@ -794,14 +794,14 @@ extern void print_it(const char *label, const char *fmt, const char *fmt2, ...) /* Translation functions */ extern void gfs2_inum_in(struct gfs2_inum *no, char *buf); -extern void gfs2_inum_out(struct gfs2_inum *no, char *buf); +extern void gfs2_inum_out(const struct gfs2_inum *no, char *buf); extern void gfs2_meta_header_in(struct gfs2_meta_header *mh, struct gfs2_buffer_head *bh); extern void gfs2_meta_header_out(const struct gfs2_meta_header *mh, char *buf); extern void gfs2_meta_header_out_bh(const struct gfs2_meta_header *mh, struct gfs2_buffer_head *bh); extern void gfs2_sb_in(struct gfs2_sb *sb, struct gfs2_buffer_head *bh); -extern void gfs2_sb_out(struct gfs2_sb *sb, struct gfs2_buffer_head *bh); +extern void gfs2_sb_out(const struct gfs2_sb *sb, char *buf); extern void gfs2_rindex_in(struct gfs2_rindex *ri, char *buf); extern void gfs2_rindex_out(struct gfs2_rindex *ri, char *buf); extern void gfs2_rgrp_in(struct gfs2_rgrp *rg, struct gfs2_buffer_head *bh); diff --git a/gfs2/libgfs2/misc.c b/gfs2/libgfs2/misc.c index c4ed722..d707687 100644 --- a/gfs2/libgfs2/misc.c +++ b/gfs2/libgfs2/misc.c @@ -17,7 +17,6 @@ #include #include #include -#include #include #include "libgfs2.h" @@ -304,47 +303,3 @@ int set_sysfs(const char *fsname, const char *filename, const char *val) close(fd); return 0; } - -/* - * get_random_bytes - Generate a series of random bytes using /dev/urandom. - * - * Modified from original code in gen_uuid.c in e2fsprogs/lib - */ -void get_random_bytes(void *buf, int nbytes) -{ - int i, n = nbytes, fd; - int lose_counter = 0; - unsigned char *cp = (unsigned char *) buf; - struct timeval tv; - - gettimeofday(&tv, 0); - fd = open("/dev/urandom", O_RDONLY | O_CLOEXEC); - srand((getpid() << 16) ^ getuid() ^ tv.tv_sec ^ tv.tv_usec); - /* Crank the random number generator a few times */ - gettimeofday(&tv, 0); - for (i = (tv.tv_sec ^ tv.tv_usec) & 0x1F; i > 0; i--) - rand(); - if (fd >= 0) { - while (n > 0) { - i = read(fd, cp, n); - if (i <= 0) { - if (lose_counter++ > 16) - break; - continue; - } - n -= i; - cp += i; - lose_counter = 0; - } - close(fd); - } - - /* - * We do this all the time, but this is the only source of - * randomness if /dev/random/urandom is out to lunch. - */ - for (cp = buf, i = 0; i < nbytes; i++) - *cp++ ^= (rand() >> 7) & 0xFF; - - return; -} diff --git a/gfs2/libgfs2/ondisk.c b/gfs2/libgfs2/ondisk.c index 4baacc7..43618bc 100644 --- a/gfs2/libgfs2/ondisk.c +++ b/gfs2/libgfs2/ondisk.c @@ -48,7 +48,7 @@ void gfs2_inum_in(struct gfs2_inum *no, char *buf) CPIN_64(no, str, no_addr); } -void gfs2_inum_out(struct gfs2_inum *no, char *buf) +void gfs2_inum_out(const struct gfs2_inum *no, char *buf) { struct gfs2_inum *str = (struct gfs2_inum *)buf; @@ -124,11 +124,11 @@ void gfs2_sb_in(struct gfs2_sb *sb, struct gfs2_buffer_head *bh) #endif } -void gfs2_sb_out(struct gfs2_sb *sb, struct gfs2_buffer_head *bh) +void gfs2_sb_out(const struct gfs2_sb *sb, char *buf) { - struct gfs2_sb *str = (struct gfs2_sb *)bh->b_data; + struct gfs2_sb *str = (struct gfs2_sb *)buf; - gfs2_meta_header_out_bh(&sb->sb_header, bh); + gfs2_meta_header_out(&sb->sb_header, buf); CPOUT_32(sb, str, sb_fs_format); CPOUT_32(sb, str, sb_multihost_format); @@ -144,7 +144,6 @@ void gfs2_sb_out(struct gfs2_sb *sb, struct gfs2_buffer_head *bh) #ifdef GFS2_HAS_UUID memcpy(str->sb_uuid, sb->sb_uuid, 16); #endif - bmodified(bh); } const char *str_uuid(const unsigned char *uuid) diff --git a/gfs2/libgfs2/structures.c b/gfs2/libgfs2/structures.c index e888f1e..2c1939a 100644 --- a/gfs2/libgfs2/structures.c +++ b/gfs2/libgfs2/structures.c @@ -11,6 +11,7 @@ #include #include #include +#include #include "libgfs2.h" @@ -41,43 +42,102 @@ int build_master(struct gfs2_sbd *sdp) return 0; } -void build_sb(struct gfs2_sbd *sdp, const unsigned char *uuid) +#ifdef GFS2_HAS_UUID +/** + * Generate a series of random bytes using /dev/urandom. + * Modified from original code in gen_uuid.c in e2fsprogs/lib + */ +static void get_random_bytes(void *buf, int nbytes) { - unsigned int x; - struct gfs2_buffer_head *bh; - struct gfs2_sb sb; - - /* Zero out the beginning of the device up to the superblock */ - for (x = 0; x < sdp->sb_addr; x++) { - bh = bget(sdp, x); - memset(bh->b_data, 0, sdp->bsize); - bmodified(bh); - brelse(bh); + int i, n = nbytes, fd; + int lose_counter = 0; + unsigned char *cp = (unsigned char *) buf; + struct timeval tv; + + gettimeofday(&tv, 0); + fd = open("/dev/urandom", O_RDONLY | O_CLOEXEC); + srand((getpid() << 16) ^ getuid() ^ tv.tv_sec ^ tv.tv_usec); + /* Crank the random number generator a few times */ + gettimeofday(&tv, 0); + for (i = (tv.tv_sec ^ tv.tv_usec) & 0x1F; i > 0; i--) + rand(); + if (fd >= 0) { + while (n > 0) { + i = read(fd, cp, n); + if (i <= 0) { + if (lose_counter++ > 16) + break; + continue; + } + n -= i; + cp += i; + lose_counter = 0; + } + close(fd); } - memset(&sb, 0, sizeof(struct gfs2_sb)); - sb.sb_header.mh_magic = GFS2_MAGIC; - sb.sb_header.mh_type = GFS2_METATYPE_SB; - sb.sb_header.mh_format = GFS2_FORMAT_SB; - sb.sb_fs_format = GFS2_FORMAT_FS; - sb.sb_multihost_format = GFS2_FORMAT_MULTI; - sb.sb_bsize = sdp->bsize; - sb.sb_bsize_shift = ffs(sdp->bsize) - 1; - sb.sb_master_dir = sdp->master_dir->i_di.di_num; - sb.sb_root_dir = sdp->md.rooti->i_di.di_num; - strcpy(sb.sb_lockproto, sdp->lockproto); - strcpy(sb.sb_locktable, sdp->locktable); + /* + * We do this all the time, but this is the only source of + * randomness if /dev/random/urandom is out to lunch. + */ + for (cp = buf, i = 0; i < nbytes; i++) + *cp++ ^= (rand() >> 7) & 0xFF; + + return; +} +#endif + +/** + * Initialise a gfs2_sb structure with sensible defaults. + */ +void lgfs2_sb_init(struct gfs2_sb *sb, unsigned bsize) +{ + memset(sb, 0, sizeof(struct gfs2_sb)); + sb->sb_header.mh_magic = GFS2_MAGIC; + sb->sb_header.mh_type = GFS2_METATYPE_SB; + sb->sb_header.mh_format = GFS2_FORMAT_SB; + sb->sb_fs_format = GFS2_FORMAT_FS; + sb->sb_multihost_format = GFS2_FORMAT_MULTI; + sb->sb_bsize = bsize; + sb->sb_bsize_shift = ffs(bsize) - 1; #ifdef GFS2_HAS_UUID - memcpy(sb.sb_uuid, uuid, sizeof(sb.sb_uuid)); + get_random_bytes(&sb->sb_uuid, sizeof(sb->sb_uuid)); #endif - bh = bget(sdp, sdp->sb_addr); - gfs2_sb_out(&sb, bh); - brelse(bh); +} - if (sdp->debug) { - printf("\nSuper Block:\n"); - gfs2_sb_print(&sb); +int lgfs2_sb_write(const struct gfs2_sb *sb, int fd, const unsigned bsize) +{ + int i, err = -1; + struct iovec *iov; + const size_t sb_addr = GFS2_SB_ADDR * GFS2_BASIC_BLOCK / bsize; + const size_t len = sb_addr + 1; + + /* We only need 2 blocks: one for zeroing and a second for the superblock */ + char *buf = calloc(2, bsize); + if (buf == NULL) + return -1; + + iov = malloc(len * sizeof(*iov)); + if (iov == NULL) + goto out_buf; + + for (i = 0; i < len; i++) { + iov[i].iov_base = buf; + iov[i].iov_len = bsize; } + + gfs2_sb_out(sb, buf + bsize); + iov[sb_addr].iov_base = buf + bsize; + + if (pwritev(fd, iov, len, 0) < (len * bsize)) + goto out_iov; + + err = 0; +out_iov: + free(iov); +out_buf: + free(buf); + return err; } int write_journal(struct gfs2_sbd *sdp, unsigned int j, unsigned int blocks) diff --git a/gfs2/libgfs2/super.c b/gfs2/libgfs2/super.c index d074236..b956366 100644 --- a/gfs2/libgfs2/super.c +++ b/gfs2/libgfs2/super.c @@ -309,15 +309,3 @@ int gfs1_ri_update(struct gfs2_sbd *sdp, int fd, int *rgcount, int quiet) return __ri_update(sdp, fd, rgcount, &sane, quiet); } - -int write_sb(struct gfs2_sbd *sbp) -{ - struct gfs2_buffer_head *bh; - - bh = bread(sbp, GFS2_SB_ADDR >> sbp->sd_fsb2bb_shift); - gfs2_sb_out(&sbp->sd_sb, bh); - brelse(bh); - fsync(sbp->device_fd); /* make sure the change gets to disk ASAP */ - return 0; -} - diff --git a/gfs2/mkfs/main_mkfs.c b/gfs2/mkfs/main_mkfs.c index 0d84064..8bd396a 100644 --- a/gfs2/mkfs/main_mkfs.c +++ b/gfs2/mkfs/main_mkfs.c @@ -569,8 +569,8 @@ static void print_results(struct gfs2_sbd *sdp, uint64_t real_device_size, (unsigned long long)sdp->fssize, _("blocks")); printf("%-27s%u\n", _("Journals:"), sdp->md.journals); printf("%-27s%llu\n", _("Resource groups:"), (unsigned long long)sdp->rgrps); - printf("%-27s\"%s\"\n", _("Locking protocol:"), sdp->lockproto); - printf("%-27s\"%s\"\n", _("Lock table:"), sdp->locktable); + printf("%-27s\"%s\"\n", _("Locking protocol:"), opts->lockproto); + printf("%-27s\"%s\"\n", _("Lock table:"), opts->locktable); /* Translators: "UUID" = universally unique identifier. */ printf("%-27s%s\n", _("UUID:"), str_uuid(uuid)); } @@ -701,8 +701,6 @@ static void sbd_init(struct gfs2_sbd *sdp, struct mkfs_opts *opts, struct mkfs_d /* TODO: Check if the fssize is too small, somehow */ sdp->device.length = opts->fssize; } - strcpy(sdp->lockproto, opts->lockproto); - strcpy(sdp->locktable, opts->locktable); } static int probe_contents(struct mkfs_dev *dev) @@ -791,11 +789,11 @@ static void open_dev(const char *path, struct mkfs_dev *dev) void main_mkfs(int argc, char *argv[]) { struct gfs2_sbd sbd; + struct gfs2_sb sb; struct mkfs_opts opts; struct mkfs_dev dev; lgfs2_rgrps_t rgs; int error; - unsigned char uuid[16]; unsigned bsize; opts_init(&opts); @@ -810,15 +808,16 @@ void main_mkfs(int argc, char *argv[]) } sbd_init(&sbd, &opts, &dev, bsize); + lgfs2_sb_init(&sb, bsize); if (opts.debug) { printf(_("File system options:\n")); printf(" bsize = %u\n", sbd.bsize); printf(" qcsize = %u\n", sbd.qcsize); printf(" jsize = %u\n", sbd.jsize); printf(" journals = %u\n", sbd.md.journals); - printf(" proto = %s\n", sbd.lockproto); + printf(" proto = %s\n", opts.lockproto); + printf(" table = %s\n", opts.locktable); printf(" rgsize = %u\n", sbd.rgsize); - printf(" table = %s\n", sbd.locktable); printf(" fssize = %"PRIu64"\n", opts.fssize); printf(" sunit = %lu\n", opts.sunit); printf(" swidth = %lu\n", opts.swidth); @@ -838,8 +837,13 @@ void main_mkfs(int argc, char *argv[]) exit(1); } sbd.rgtree.osi_node = lgfs2_rgrps_root(rgs); // Temporary + build_root(&sbd); + sb.sb_root_dir = sbd.md.rooti->i_di.di_num; + build_master(&sbd); + sb.sb_master_dir = sbd.master_dir->i_di.di_num; + error = build_jindex(&sbd); if (error) { fprintf(stderr, _("Error building '%s': %s\n"), "jindex", strerror(errno)); @@ -872,8 +876,9 @@ void main_mkfs(int argc, char *argv[]) fprintf(stderr, _("Error building '%s': %s\n"), "quota", strerror(errno)); exit(EXIT_FAILURE); } - get_random_bytes(uuid, sizeof(uuid)); - build_sb(&sbd, uuid); + + strcpy(sb.sb_lockproto, opts.lockproto); + strcpy(sb.sb_locktable, opts.locktable); do_init_inum(&sbd); do_init_statfs(&sbd); @@ -884,6 +889,13 @@ void main_mkfs(int argc, char *argv[]) inode_put(&sbd.md.statfs); gfs2_rgrp_free(&sbd.rgtree); + + error = lgfs2_sb_write(&sb, dev.fd, sbd.bsize); + if (error) { + perror(_("Failed to write superblock\n")); + exit(EXIT_FAILURE); + } + error = fsync(dev.fd); if (error){ perror(opts.device); @@ -897,5 +909,5 @@ void main_mkfs(int argc, char *argv[]) } if (!opts.quiet) - print_results(&sbd, dev.size, &opts, uuid); + print_results(&sbd, dev.size, &opts, sb.sb_uuid); }