int btrfs_main(int argc, char **argv) { const struct cmd_struct *cmd; const char *bname; if ((bname = strrchr(argv[0], '/')) != NULL) bname++; else bname = argv[0]; if (!strcmp(bname, "btrfsck")) { argv[0] = "check"; } else { argc--; argv++; handle_options(&argc, &argv); if (argc > 0) { if (!prefixcmp(argv[0], "--")) argv[0] += 2; } else { usage_command_group(&btrfs_cmd_group, 0, 0); exit(1); } } cmd = parse_command_token(argv[0], &btrfs_cmd_group); handle_help_options_next_level(cmd, argc, argv); crc32c_optimization_init(); fixup_argv0(argv, cmd->token); exit(cmd->fn(argc, argv)); }
/** * Intialise and write the data blocks for a new journal as a contiguous * extent. The indirect blocks pointing to these data blocks should have been * written separately using lgfs2_write_filemeta() and the extent should have * been allocated using lgfs2_file_alloc(). * ip: The journal's inode * Returns 0 on success or -1 with errno set on error. */ int lgfs2_write_journal_data(struct gfs2_inode *ip) { struct gfs2_log_header lh = { .lh_header.mh_magic = GFS2_MAGIC, .lh_header.mh_type = GFS2_METATYPE_LH, .lh_header.mh_format = GFS2_FORMAT_LH, .lh_tail = 0, .lh_blkno = 0, .lh_hash = 0, #ifdef GFS2_HAS_LH_V2 .lh_flags = GFS2_LOG_HEAD_UNMOUNT | GFS2_LOG_HEAD_USERSPACE, .lh_crc = 0, .lh_nsec = 0, .lh_sec = 0, .lh_jinode = ip->i_di.di_num.no_addr, .lh_statfs_addr = 0, .lh_quota_addr = 0, .lh_local_total = 0, .lh_local_free = 0, .lh_local_dinodes = 0, #else .lh_flags = GFS2_LOG_HEAD_UNMOUNT, #endif }; struct gfs2_buffer_head *bh; struct gfs2_sbd *sdp = ip->i_sbd; unsigned blocks = (ip->i_di.di_size + sdp->bsize - 1) / sdp->bsize; uint64_t jext0 = ip->i_di.di_num.no_addr + ip->i_di.di_blocks - blocks; uint64_t seq = ((blocks) * (random() / (RAND_MAX + 1.0))); bh = bget(sdp, jext0); if (bh == NULL) return -1; crc32c_optimization_init(); do { struct gfs2_log_header *buflh = (struct gfs2_log_header *)bh->b_data; lh.lh_sequence = seq; lh.lh_blkno = bh->b_blocknr - jext0; gfs2_log_header_out(&lh, bh->b_data); buflh->lh_hash = cpu_to_be32(lgfs2_log_header_hash(bh->b_data)); #ifdef GFS2_HAS_LH_V2 buflh->lh_addr = cpu_to_be64(bh->b_blocknr); buflh->lh_crc = cpu_to_be32(lgfs2_log_header_crc(bh->b_data, sdp->bsize)); #endif if (bwrite(bh)) { free(bh); return -1; } if (++seq == blocks) seq = 0; } while (++bh->b_blocknr < jext0 + blocks); free(bh); return 0; } int write_journal(struct gfs2_inode *jnl, unsigned bsize, unsigned int blocks) { struct gfs2_log_header lh; unsigned int x; uint64_t seq = ((blocks) * (random() / (RAND_MAX + 1.0))); uint32_t hash; unsigned int height; /* Build the height up so our journal blocks will be contiguous and */ /* not broken up by indirect block pages. */ height = calc_tree_height(jnl, (blocks + 1) * bsize); build_height(jnl, height); memset(&lh, 0, sizeof(struct gfs2_log_header)); lh.lh_header.mh_magic = GFS2_MAGIC; lh.lh_header.mh_type = GFS2_METATYPE_LH; lh.lh_header.mh_format = GFS2_FORMAT_LH; lh.lh_flags = GFS2_LOG_HEAD_UNMOUNT; #ifdef GFS2_HAS_LH_V2 lh.lh_flags |= GFS2_LOG_HEAD_USERSPACE; lh.lh_jinode = jnl->i_di.di_num.no_addr; #endif for (x = 0; x < blocks; x++) { struct gfs2_buffer_head *bh = get_file_buf(jnl, x, TRUE); if (!bh) return -1; bmodified(bh); brelse(bh); } crc32c_optimization_init(); for (x = 0; x < blocks; x++) { struct gfs2_buffer_head *bh = get_file_buf(jnl, x, FALSE); if (!bh) return -1; memset(bh->b_data, 0, bsize); lh.lh_sequence = seq; lh.lh_blkno = x; gfs2_log_header_out(&lh, bh->b_data); hash = lgfs2_log_header_hash(bh->b_data); ((struct gfs2_log_header *)bh->b_data)->lh_hash = cpu_to_be32(hash); #ifdef GFS2_HAS_LH_V2 ((struct gfs2_log_header *)bh->b_data)->lh_addr = cpu_to_be64(bh->b_blocknr); hash = lgfs2_log_header_crc(bh->b_data, bsize); ((struct gfs2_log_header *)bh->b_data)->lh_crc = cpu_to_be32(hash); #endif bmodified(bh); brelse(bh); if (++seq == blocks) seq = 0; } return 0; } int build_journal(struct gfs2_sbd *sdp, int j, struct gfs2_inode *jindex) { char name[256]; int ret; sprintf(name, "journal%u", j); sdp->md.journal[j] = createi(jindex, name, S_IFREG | 0600, GFS2_DIF_SYSTEM); if (sdp->md.journal[j] == NULL) { return errno; } ret = write_journal(sdp->md.journal[j], sdp->bsize, sdp->jsize << 20 >> sdp->sd_sb.sb_bsize_shift); return ret; }