errcode_t ocfs2_malloc_blocks(io_channel *channel, int num_blocks, void *ptr) { errcode_t ret; int blksize; size_t bytes; void **pp = (void **)ptr; void *tmp; blksize = io_get_blksize(channel); if (((unsigned long long)num_blocks * blksize) > SIZE_MAX) return OCFS2_ET_NO_MEMORY; bytes = (unsigned long long)num_blocks * blksize; /* * Older glibcs abort when they can't memalign() something. * Ugh! Check with malloc() first. */ tmp = malloc(bytes); if (!tmp) return OCFS2_ET_NO_MEMORY; free(tmp); ret = posix_memalign(pp, blksize, bytes); if (!ret) return 0; if (errno == ENOMEM) return OCFS2_ET_NO_MEMORY; /* blksize better be valid */ abort(); }
void o2fsck_print_resource_track(char *pass, o2fsck_state *ost, struct o2fsck_resource_track *rt, io_channel *channel) { struct ocfs2_io_stats *rtio = &rt->rt_io_stats; uint64_t total_io, cache_read; float rtime_s, utime_s, stime_s, walltime; uint32_t rtime_m, utime_m, stime_m; if (!ost->ost_show_stats) return ; if (pass && !ost->ost_show_extended_stats) return; #define split_time(_t, _m, _s) \ do { \ (_s) = timeval_in_secs(&_t); \ (_m) = (_s) / 60; \ (_s) -= ((_m) * 60); \ } while (0); split_time(rt->rt_real_time, rtime_m, rtime_s); split_time(rt->rt_user_time, utime_m, utime_s); split_time(rt->rt_sys_time, stime_m, stime_s); walltime = timeval_in_secs(&rt->rt_real_time) - timeval_in_secs(&rt->rt_user_time); /* TODO: Investigate why user time is sometimes > wall time*/ if (walltime < 0) walltime = 0; cache_read = (uint64_t)rtio->is_cache_hits * io_get_blksize(channel); total_io = rtio->is_bytes_read + rtio->is_bytes_written; if (!pass) printf(" Cache size: %luMB\n", mbytes(io_get_cache_size(channel))); printf(" I/O read disk/cache: %"PRIu64"MB / %"PRIu64"MB, " "write: %"PRIu64"MB, rate: %.2fMB/s\n", mbytes(rtio->is_bytes_read), mbytes(cache_read), mbytes(rtio->is_bytes_written), (double)(mbytes(total_io) / walltime)); printf(" Times real: %dm%.3fs, user: %dm%.3fs, sys: %dm%.3fs\n", rtime_m, rtime_s, utime_m, utime_s, stime_m, stime_s); }
errcode_t cmfs_malloc_blocks(io_channel *channel, int num_blocks, void *ptr) { errcode_t ret; int blksize; size_t bytes; void **pp = (void **)ptr; blksize = io_get_blksize(channel); if (((unsigned long long)num_blocks * blksize) > SIZE_MAX) return CMFS_ET_NO_MEMORY; bytes = num_blocks * blksize; ret = posix_memalign(pp, blksize, bytes); if (!ret) return 0; if (errno == ENOMEM) return CMFS_ET_NO_MEMORY; abort(); }
static errcode_t io_validate_o_direct(io_channel *channel) { errcode_t ret = OCFS2_ET_UNEXPECTED_BLOCK_SIZE; int block_size; char *blk; for (block_size = io_get_blksize(channel); block_size <= OCFS2_MAX_BLOCKSIZE; block_size <<= 1) { io_set_blksize(channel, block_size); ret = ocfs2_malloc_block(channel, &blk); if (ret) break; ret = unix_io_read_block(channel, 0, 1, blk); ocfs2_free(&blk); if (!ret) break; } return ret; }
errcode_t ocfs2_open(const char *name, int flags, unsigned int superblock, unsigned int block_size, ocfs2_filesys **ret_fs) { ocfs2_filesys *fs; errcode_t ret; int i, len; char *ptr; unsigned char *raw_uuid; ret = ocfs2_malloc0(sizeof(ocfs2_filesys), &fs); if (ret) return ret; fs->fs_flags = flags; fs->fs_umask = 022; ret = io_open(name, (flags & (OCFS2_FLAG_RO | OCFS2_FLAG_RW | OCFS2_FLAG_BUFFERED)), &fs->fs_io); if (ret) goto out; ret = ocfs2_malloc(strlen(name)+1, &fs->fs_devname); if (ret) goto out; strcpy(fs->fs_devname, name); /* * If OCFS2_FLAG_IMAGE_FILE is specified, it needs to be handled * differently */ if (flags & OCFS2_FLAG_IMAGE_FILE) { ret = ocfs2_image_load_bitmap(fs); if (ret) goto out; if (!superblock) superblock = fs->ost->ost_superblocks[0]; if (!block_size) block_size = fs->ost->ost_fsblksz; } /* image file is not a device */ if (!(flags & OCFS2_FLAG_IMAGE_FILE)) { if (io_is_device_readonly(fs->fs_io)) fs->fs_flags |= OCFS2_FLAG_HARD_RO; } /* * If OCFS2_FLAG_NO_REV_CHECK is specified, fsck (or someone * like it) is asking to ignore the OCFS vol_header at * block 0. */ if (!(flags & OCFS2_FLAG_NO_REV_CHECK)) { ret = ocfs2_validate_ocfs1_header(fs); if (ret) goto out; } if (superblock) { ret = OCFS2_ET_INVALID_ARGUMENT; if (!block_size) goto out; io_set_blksize(fs->fs_io, block_size); ret = ocfs2_read_super(fs, (uint64_t)superblock, NULL); } else { superblock = OCFS2_SUPER_BLOCK_BLKNO; if (block_size) { io_set_blksize(fs->fs_io, block_size); ret = ocfs2_read_super(fs, (uint64_t)superblock, NULL); } else { for (block_size = io_get_blksize(fs->fs_io); block_size <= OCFS2_MAX_BLOCKSIZE; block_size <<= 1) { io_set_blksize(fs->fs_io, block_size); ret = ocfs2_read_super(fs, (uint64_t)superblock, NULL); if ((ret == OCFS2_ET_BAD_MAGIC) || (ret == OCFS2_ET_IO)) continue; break; } } } if (ret) goto out; fs->fs_blocksize = block_size; if (superblock == OCFS2_SUPER_BLOCK_BLKNO) { ret = ocfs2_malloc_block(fs->fs_io, &fs->fs_orig_super); if (ret) goto out; memcpy((char *)fs->fs_orig_super, (char *)fs->fs_super, fs->fs_blocksize); } #if 0 ret = OCFS2_ET_REV_TOO_HIGH; if (fs->fs_super->id2.i_super.s_major_rev_level > OCFS2_LIB_CURRENT_REV) goto out; #endif if (flags & OCFS2_FLAG_STRICT_COMPAT_CHECK) { ret = OCFS2_ET_UNSUPP_FEATURE; if (OCFS2_RAW_SB(fs->fs_super)->s_feature_compat & ~OCFS2_LIB_FEATURE_COMPAT_SUPP) goto out; /* We need to check s_tunefs_flag also to make sure * fsck.ocfs2 won't try to clean up an aborted tunefs * that it doesn't know. */ if (OCFS2_HAS_INCOMPAT_FEATURE(OCFS2_RAW_SB(fs->fs_super), OCFS2_FEATURE_INCOMPAT_TUNEFS_INPROG) && (OCFS2_RAW_SB(fs->fs_super)->s_tunefs_flag & ~OCFS2_LIB_ABORTED_TUNEFS_SUPP)) goto out; } ret = OCFS2_ET_UNSUPP_FEATURE; if (OCFS2_RAW_SB(fs->fs_super)->s_feature_incompat & ~OCFS2_LIB_FEATURE_INCOMPAT_SUPP) goto out; ret = OCFS2_ET_RO_UNSUPP_FEATURE; if ((flags & OCFS2_FLAG_RW) && (OCFS2_RAW_SB(fs->fs_super)->s_feature_ro_compat & ~OCFS2_LIB_FEATURE_RO_COMPAT_SUPP)) goto out; ret = OCFS2_ET_UNSUPP_FEATURE; if (!(flags & OCFS2_FLAG_HEARTBEAT_DEV_OK) && (OCFS2_RAW_SB(fs->fs_super)->s_feature_incompat & OCFS2_FEATURE_INCOMPAT_HEARTBEAT_DEV)) goto out; ret = OCFS2_ET_CORRUPT_SUPERBLOCK; if (!OCFS2_RAW_SB(fs->fs_super)->s_blocksize_bits) goto out; if (fs->fs_super->i_blkno != superblock) goto out; if ((OCFS2_RAW_SB(fs->fs_super)->s_clustersize_bits < 12) || (OCFS2_RAW_SB(fs->fs_super)->s_clustersize_bits > 20)) goto out; if (!OCFS2_RAW_SB(fs->fs_super)->s_root_blkno || !OCFS2_RAW_SB(fs->fs_super)->s_system_dir_blkno) goto out; if (OCFS2_RAW_SB(fs->fs_super)->s_max_slots > OCFS2_MAX_SLOTS) goto out; ret = ocfs2_malloc0(OCFS2_RAW_SB(fs->fs_super)->s_max_slots * sizeof(ocfs2_cached_inode *), &fs->fs_inode_allocs); if (ret) goto out; ret = ocfs2_malloc0(OCFS2_RAW_SB(fs->fs_super)->s_max_slots * sizeof(ocfs2_cached_inode *), &fs->fs_eb_allocs); if (ret) goto out; ret = OCFS2_ET_UNEXPECTED_BLOCK_SIZE; if (block_size != (1U << OCFS2_RAW_SB(fs->fs_super)->s_blocksize_bits)) goto out; fs->fs_clustersize = 1 << OCFS2_RAW_SB(fs->fs_super)->s_clustersize_bits; /* FIXME: Read the system dir */ fs->fs_root_blkno = OCFS2_RAW_SB(fs->fs_super)->s_root_blkno; fs->fs_sysdir_blkno = OCFS2_RAW_SB(fs->fs_super)->s_system_dir_blkno; fs->fs_clusters = fs->fs_super->i_clusters; fs->fs_blocks = ocfs2_clusters_to_blocks(fs, fs->fs_clusters); fs->fs_first_cg_blkno = OCFS2_RAW_SB(fs->fs_super)->s_first_cluster_group; raw_uuid = OCFS2_RAW_SB(fs->fs_super)->s_uuid; for (i = 0, ptr = fs->uuid_str; i < OCFS2_VOL_UUID_LEN; i++) { /* print with null */ len = snprintf(ptr, 3, "%02X", raw_uuid[i]); if (len != 2) { ret = OCFS2_ET_INTERNAL_FAILURE; goto out; } /* then only advace past the last char */ ptr += 2; } *ret_fs = fs; return 0; out: if (fs->fs_inode_allocs) ocfs2_free(&fs->fs_inode_allocs); ocfs2_freefs(fs); return ret; }
errcode_t ocfs2_read_super(ocfs2_filesys *fs, uint64_t superblock, char *sb) { errcode_t ret; char *blk, *swapblk; struct ocfs2_dinode *di, *orig_super; int orig_blocksize; int blocksize = io_get_blksize(fs->fs_io); ret = ocfs2_malloc_block(fs->fs_io, &blk); if (ret) return ret; ret = ocfs2_read_blocks(fs, superblock, 1, blk); if (ret) goto out_blk; di = (struct ocfs2_dinode *)blk; ret = OCFS2_ET_BAD_MAGIC; if (memcmp(di->i_signature, OCFS2_SUPER_BLOCK_SIGNATURE, strlen(OCFS2_SUPER_BLOCK_SIGNATURE))) goto out_blk; /* * We want to use the latest superblock to validate. We need * a local-endian copy in fs->fs_super, and the unswapped copy to * check in blk. ocfs2_validate_meta_ecc() uses fs->fs_super and * fs->fs_blocksize. */ ret = ocfs2_malloc_block(fs->fs_io, &swapblk); if (ret) goto out_blk; memcpy(swapblk, blk, blocksize); orig_super = fs->fs_super; orig_blocksize = fs->fs_blocksize; fs->fs_super = (struct ocfs2_dinode *)swapblk; fs->fs_blocksize = blocksize; ocfs2_swap_inode_to_cpu(fs, fs->fs_super); ret = ocfs2_validate_meta_ecc(fs, blk, &di->i_check); fs->fs_super = orig_super; fs->fs_blocksize = orig_blocksize; ocfs2_free(&swapblk); if (ret) goto out_blk; ocfs2_swap_inode_to_cpu(fs, di); if (!sb) fs->fs_super = di; else { memcpy(sb, blk, fs->fs_blocksize); ocfs2_free(&blk); } return 0; out_blk: ocfs2_free(&blk); return ret; }
/* * allocate ocfs2_image_bitmap_arr and ocfs2 image bitmap blocks. o2image bitmap * block is of size OCFS2_IMAGE_BITMAP_BLOCKSIZE and ocfs2_image_bitmap_arr * tracks the bitmap blocks */ errcode_t ocfs2_image_alloc_bitmap(ocfs2_filesys *ofs) { uint64_t blks, allocsize, leftsize; struct ocfs2_image_state *ost = ofs->ost; int indx, i, n; errcode_t ret; char *buf; ost->ost_bmpblks = ((ost->ost_fsblkcnt - 1) / (OCFS2_IMAGE_BITS_IN_BLOCK)) + 1; ost->ost_bmpblksz = OCFS2_IMAGE_BITMAP_BLOCKSIZE; blks = ost->ost_bmpblks; /* allocate memory for an array to track bitmap blocks */ ret = ocfs2_malloc0((blks * sizeof(ocfs2_image_bitmap_arr)), &ost->ost_bmparr); if (ret) return ret; allocsize = blks * OCFS2_IMAGE_BITMAP_BLOCKSIZE; leftsize = allocsize; indx = 0; /* allocate bitmap blocks and assign blocks to above array */ while (leftsize) { ret = ocfs2_malloc_blocks(ofs->fs_io, allocsize/io_get_blksize(ofs->fs_io), &buf); if (ret && (ret != -ENOMEM)) goto out; if (ret == -ENOMEM) { if (allocsize == OCFS2_IMAGE_BITMAP_BLOCKSIZE) goto out; allocsize >>= 1; if (allocsize % OCFS2_IMAGE_BITMAP_BLOCKSIZE) { allocsize /= OCFS2_IMAGE_BITMAP_BLOCKSIZE; allocsize *= OCFS2_IMAGE_BITMAP_BLOCKSIZE; } continue; } n = allocsize / OCFS2_IMAGE_BITMAP_BLOCKSIZE; for (i = 0; i < n; i++) { ost->ost_bmparr[indx].arr_set_bit_cnt = 0; ost->ost_bmparr[indx].arr_map = ((char *)buf + (i * OCFS2_IMAGE_BITMAP_BLOCKSIZE)); /* remember buf address to free it later */ if (!i) ost->ost_bmparr[indx].arr_self = buf; indx++; } leftsize -= allocsize; if (leftsize <= allocsize) allocsize = leftsize; } out: /* If allocation failed free and return error */ if (leftsize) { for (i = 0; i < indx; i++) if (ost->ost_bmparr[i].arr_self) ocfs2_free(&ost->ost_bmparr[i].arr_self); ocfs2_free(&ost->ost_bmparr); } return ret; }