int is_dir_inlined(char *dirent_name, unsigned long *i_size, unsigned int *id_count) { int ret; uint64_t workplace_blk_no = 1; uint64_t testdir_blk_no = 1; char *buf = NULL; struct ocfs2_dinode *di; struct ocfs2_super_block *sb = OCFS2_RAW_SB(fs->fs_super); sync(); ocfs2_malloc_block(fs->fs_io, &buf); /*lookup worksplace inode*/ ret = ocfs2_lookup(fs, sb->s_root_blkno, WORK_PLACE, strlen(WORK_PLACE), NULL, &workplace_blk_no); if (ret < 0) { fprintf(stderr, "failed to lookup work_place(%s)'s" " inode blkno\n", work_place); ocfs2_free(&buf); exit(ret); } /*lookup file inode,then read*/ ret = ocfs2_lookup(fs, workplace_blk_no, dirent_name, strlen(dirent_name), NULL, &testdir_blk_no); if (ret < 0) { fprintf(stderr, "failed to lookup file(%s/%s)'s" " inode blkno\n", work_place, dirent_name); ocfs2_free(&buf); exit(ret); } ret = ocfs2_read_inode(fs, testdir_blk_no, buf); if (ret < 0) { fprintf(stderr, "failed to read file(%s/%s/%s)'s" " inode.\n", mount_point, WORK_PLACE, dirent_name); ocfs2_free(&buf); exit(ret); } di = (struct ocfs2_dinode *)buf; *i_size = di->i_size; *id_count = ((di->id2).i_data).id_count; if (di->i_dyn_features & OCFS2_INLINE_DATA_FL) ret = 1; else ret = 0; ocfs2_free(&buf); return ret; }
static errcode_t create_system_file(ocfs2_filesys *fs, int type, int node) { char fname[OCFS2_MAX_FILENAME_LEN]; uint64_t blkno; errcode_t ret; ocfs2_sprintf_system_inode_name(fname, sizeof(fname), type, node); ret = ocfs2_lookup(fs, fs->fs_sysdir_blkno, fname, strlen(fname), NULL, &blkno); if (!ret) { verbosef(VL_APP, "System file \"%s\" already exists!\n", fname); return 0; } ret = ocfs2_new_system_inode(fs, &blkno, ocfs2_system_inodes[type].si_mode, ocfs2_system_inodes[type].si_iflags); if (ret) { tcom_err(ret, "while creating system file \"%s\"", fname); return ret; } ret = ocfs2_link(fs, fs->fs_sysdir_blkno, fname, blkno, OCFS2_FT_REG_FILE); if (ret) { tcom_err(ret, "while linking file \"%s\" in the system " "directory", fname); return ret; } return 0; }
static void create_named_directory(ocfs2_filesys *fs, char *dirname, uint64_t *blkno) { errcode_t ret; struct ocfs2_super_block *sb = OCFS2_RAW_SB(fs->fs_super); ret = ocfs2_lookup(fs, sb->s_root_blkno, dirname, strlen(dirname), NULL, blkno); if (!ret) return; else if (ret != OCFS2_ET_FILE_NOT_FOUND) FSWRK_COM_FATAL(progname, ret); ret = ocfs2_new_inode(fs, blkno, S_IFDIR | 0755); if (ret) FSWRK_COM_FATAL(progname, ret); ret = ocfs2_init_dir(fs, *blkno, fs->fs_root_blkno); if (ret) FSWRK_COM_FATAL(progname, ret); ret = ocfs2_link(fs, fs->fs_root_blkno, dirname, *blkno, OCFS2_FT_DIR); if (ret) FSWRK_COM_FATAL(progname, ret); return; }
void mess_up_local_alloc_used(ocfs2_filesys *fs, enum fsck_type type, uint16_t slotnum) { errcode_t ret; uint64_t blkno; char alloc_inode[OCFS2_MAX_FILENAME_LEN]; struct ocfs2_super_block *sb = OCFS2_RAW_SB(fs->fs_super); if (slotnum == UINT16_MAX) slotnum = 0; snprintf(alloc_inode, sizeof(alloc_inode), ocfs2_system_inodes[LOCAL_ALLOC_SYSTEM_INODE].si_name,slotnum); ret = ocfs2_lookup(fs, sb->s_system_dir_blkno, alloc_inode, strlen(alloc_inode), NULL, &blkno); if (ret) FSWRK_COM_FATAL(progname, ret); create_local_alloc(fs, blkno); damage_local_alloc(fs, blkno, type); return; }
static errcode_t create_orphan_file(ocfs2_filesys *fs, uint16_t slot) { errcode_t ret; uint64_t dir, tmp_blkno; char name[OCFS2_MAX_FILENAME_LEN]; int namelen; ret = ocfs2_lookup_system_inode(fs, ORPHAN_DIR_SYSTEM_INODE, slot, &dir); if (ret) return ret; namelen = sprintf(name, "test%ld", random()); ret = ocfs2_lookup(fs, dir, name, namelen, NULL, &tmp_blkno); if (!ret) return 0; else if (ret != OCFS2_ET_FILE_NOT_FOUND) return ret; ret = ocfs2_new_inode(fs, &tmp_blkno, S_IFREG | 0755); if (ret) return ret; ret = ocfs2_link(fs, dir, name, tmp_blkno, OCFS2_FT_REG_FILE); if (ret) return ret; return 0; }
void mess_up_inode_orphaned(ocfs2_filesys *fs, enum fsck_type type, uint16_t slotnum) { errcode_t ret; uint64_t blkno, tmpblkno; char parentdir[OCFS2_MAX_FILENAME_LEN]; struct ocfs2_super_block *sb = OCFS2_RAW_SB(fs->fs_super); if (slotnum == UINT16_MAX) slotnum = 0; snprintf(parentdir, sizeof(parentdir), ocfs2_system_inodes[ORPHAN_DIR_SYSTEM_INODE].si_name, slotnum); ret = ocfs2_lookup(fs, sb->s_system_dir_blkno, parentdir, strlen(parentdir), NULL, &blkno); if (ret) FSWRK_COM_FATAL(progname, ret); create_file(fs, blkno, &tmpblkno); fprintf(stdout, "INODE_ORPHANED: " "Create an inode#%"PRIu64" under directory %s\n", tmpblkno, parentdir); return; }
static void mess_up_sys_chains(ocfs2_filesys *fs, uint16_t slotnum, enum fsck_type type) { errcode_t ret; char sysfile[OCFS2_MAX_FILENAME_LEN]; uint64_t blkno; struct ocfs2_super_block *sb = OCFS2_RAW_SB(fs->fs_super); if (slotnum == UINT16_MAX) snprintf(sysfile, sizeof(sysfile), "%s", ocfs2_system_inodes[GLOBAL_BITMAP_SYSTEM_INODE].si_name); else snprintf(sysfile, sizeof(sysfile), ocfs2_system_inodes[INODE_ALLOC_SYSTEM_INODE].si_name, slotnum); ret = ocfs2_lookup(fs, sb->s_system_dir_blkno, sysfile, strlen(sysfile), NULL, &blkno); if (ret) FSWRK_COM_FATAL(progname, ret); mess_up_sys_file(fs, blkno, type); return ; }
/* * corrupt_chains() * */ void corrupt_chains(ocfs2_filesys *fs, int code, uint16_t slotnum) { errcode_t ret; uint64_t blkno; struct ocfs2_super_block *sb = OCFS2_RAW_SB(fs->fs_super); char sysfile[40]; switch (code) { case 3: case 4: case 5: case 6: case 7: case 8: case 10: case 11: case 12: snprintf(sysfile, sizeof(sysfile), ocfs2_system_inodes[GLOBAL_BITMAP_SYSTEM_INODE].si_name); break; #ifdef _LATER_ case X: snprintf(sysfile, sizeof(sysfile), ocfs2_system_inodes[GLOBAL_INODE_ALLOC_SYSTEM_INODE].si_name); break; case Y: snprintf(sysfile, sizeof(sysfile), ocfs2_system_inodes[EXTENT_ALLOC_SYSTEM_INODE].si_name, slotnum); break; case Z: snprintf(sysfile, sizeof(sysfile), ocfs2_system_inodes[INODE_ALLOC_SYSTEM_INODE].si_name, slotnum); break; #endif default: FSWRK_FATAL("Invalid code=%d", code); } ret = ocfs2_lookup(fs, sb->s_system_dir_blkno, sysfile, strlen(sysfile), NULL, &blkno); if (ret) FSWRK_FATAL(); mess_up_chains(fs, blkno, code); return ; }
static errcode_t fix_dirent_index(o2fsck_dirblock_entry *dbe, struct dirblock_data *dd, struct ocfs2_dir_entry *dirent, unsigned int *flags) { errcode_t ret = 0; struct ocfs2_dinode *di = (struct ocfs2_dinode *)dd->inoblock_buf; uint64_t ino; if (!ocfs2_supports_indexed_dirs(OCFS2_RAW_SB(dd->fs->fs_super))) goto out; if (di->i_dyn_features & OCFS2_INDEXED_DIR_FL) { ret = ocfs2_lookup(dd->fs, dbe->e_ino, dirent->name, dirent->name_len, NULL, &ino); if (ret) { if ((ret == OCFS2_ET_DIR_CORRUPTED) && prompt(dd->ost, PY, PR_DX_LOOKUP_FAILED, "Directory inode %"PRIu64" has invalid index. " "Rebuild index tree?", dbe->e_ino)) { *flags |= OCFS2_DIRENT_CHANGED; ret = 0; goto out; } if (ret != OCFS2_ET_FILE_NOT_FOUND) goto out; ret = 0; if (prompt(dd->ost, PY, PR_DX_LOOKUP_FAILED, "Directory inode %"PRIu64" is missing " "an index entry for the file \"%.*s\"" " (inode # %"PRIu64")\n. Repair this by " "rebuilding the directory index?", dbe->e_ino, dirent->name_len, dirent->name, ino)) *flags |= OCFS2_DIRENT_CHANGED; goto out; } } out: return ret; }
errcode_t ocfs2_lookup_system_inode(ocfs2_filesys *fs, int type, int slot_num, uint64_t *blkno) { errcode_t ret; char *buf; ret = ocfs2_malloc0(sizeof(char) * (OCFS2_MAX_FILENAME_LEN + 1), &buf); if (ret) return ret; ocfs2_sprintf_system_inode_name(buf, OCFS2_MAX_FILENAME_LEN, type, slot_num); ret = ocfs2_lookup(fs, fs->fs_sysdir_blkno, buf, strlen(buf), NULL, blkno); ocfs2_free(&buf); return ret; }
static void get_truncate_log(ocfs2_filesys *fs, uint16_t slotnum, uint64_t *blkno) { errcode_t ret; char truncate_log[OCFS2_MAX_FILENAME_LEN]; struct ocfs2_super_block *sb = OCFS2_RAW_SB(fs->fs_super); if (slotnum == UINT16_MAX) slotnum = 0; snprintf(truncate_log, sizeof(truncate_log), ocfs2_system_inodes[TRUNCATE_LOG_SYSTEM_INODE].si_name, slotnum); ret = ocfs2_lookup(fs, sb->s_system_dir_blkno, truncate_log, strlen(truncate_log), NULL, blkno); if (ret) FSWRK_COM_FATAL(progname, ret); return; }
static void fix_dot_dot(o2fsck_state *ost, o2fsck_dir_parent *dir) { errcode_t ret; struct fix_dot_dot_args args = { .ost = ost, .parent = dir->dp_dirent, .fixed = 0, }; ret = ocfs2_dir_iterate(ost->ost_fs, dir->dp_ino, OCFS2_DIRENT_FLAG_INCLUDE_EMPTY, NULL, fix_dot_dot_dirent, &args); if (ret) { com_err("fix_dot_dot", ret, "while iterating through dir " "inode %"PRIu64"'s directory entries.", dir->dp_dirent); /* XXX mark fs invalid */ return; } if (!args.fixed) { fprintf(stderr, "Didn't find a '..' entry to fix.\n"); /* XXX mark fs invalid */ return; } dir->dp_dot_dot = dir->dp_dirent; } /* add a directory entry that points to a given inode in lost+found. */ void o2fsck_reconnect_file(o2fsck_state *ost, uint64_t inode) { static char iname[NAME_MAX + 1]; char name[] = "lost+found"; int namelen = sizeof(name) - 1; o2fsck_dir_parent *dp; errcode_t ret; uint8_t type; int len; if (ost->ost_lostfound_ino == 0) { ret = ocfs2_lookup(ost->ost_fs, ost->ost_fs->fs_root_blkno, name, namelen, NULL, &ost->ost_lostfound_ino); if (ret) { com_err(whoami, ret, "while trying to find the " "/lost+found directory so that inode " "%"PRIu64" could be moved there.", inode); goto out; } } len = snprintf(iname, sizeof(iname), "#%"PRIu64, inode); if (len <= 0) { ret = OCFS2_ET_NO_MEMORY; com_err(whoami, ret, "while trying to build a new file name " "for inode %"PRIu64" to use in /lost+found", inode); goto out; } ret = o2fsck_type_from_dinode(ost, inode, &type); if (ret) goto out; ret = ocfs2_link(ost->ost_fs, ost->ost_lostfound_ino, iname, inode, type); if (ret) { com_err(whoami, ret, "while trying to link inode %"PRIu64" " "into /lost+found", inode); goto out; } /* add another ref to account for this new dirent */ o2fsck_icount_delta(ost->ost_icount_refs, inode, 1); /* if we just added a directory to l+f we need to track that * the new dirent points to the dir. we leave the dot_dot tracking * intact because we didn't change that in the dirblock.. */ if (type == OCFS2_FT_DIR) { dp = o2fsck_dir_parent_lookup(&ost->ost_dir_parents, inode); if (dp == NULL) { ret = OCFS2_ET_INTERNAL_FAILURE; com_err(whoami, ret, "while looking up the directory " "parent structure for inode %"PRIu64, inode); goto out; } dp->dp_dirent = ost->ost_lostfound_ino; } out: return; } static uint64_t loop_no = 0; static errcode_t connect_directory(o2fsck_state *ost, o2fsck_dir_parent *dir) { o2fsck_dir_parent *dp = dir, *par; errcode_t ret = 0; int fix; verbosef("checking dir inode %"PRIu64" parent %"PRIu64" dot_dot " "%"PRIu64"\n", dir->dp_ino, dp->dp_dirent, dp->dp_dot_dot); loop_no++; while(!dp->dp_connected) { /* we either will ascend to a parent that is connected or * we'll graft the subtree with this directory on to lost * and found. */ dp->dp_connected = 1; /* move on to the parent dir only if it exists and we haven't * already traversed it in this instance of parent walking */ if (dp->dp_dirent) { par = o2fsck_dir_parent_lookup(&ost->ost_dir_parents, dp->dp_dirent); if (par == NULL) { ret = OCFS2_ET_INTERNAL_FAILURE; com_err(whoami, ret, "no dir info for parent " "%"PRIu64, dp->dp_dirent); goto out; } if (par->dp_loop_no != loop_no) { par->dp_loop_no = loop_no; dp = par; continue; } } /* ok, we hit an orphan subtree with no parent or are at * the dir in a subtree that is the first to try to reference * a dir in its children */ fix = prompt(ost, PY, PR_DIR_NOT_CONNECTED, "Directory inode %"PRIu64" isn't " "connected to the filesystem. Move it to " "lost+found?", dp->dp_ino); if (fix) o2fsck_reconnect_file(ost, dp->dp_ino); break; } /* * orphan dirs are a magically awesome special case. they have * their i_link_count increased when subdirs are added but * the subdirs '..' entry isn't updated to point to the orphan * dir. we alter our book-keeping to it look like the '..' * was reasonable on disk. */ if (dir->dp_in_orphan_dir) { /* previous '..' entry is garbage */ if (dir->dp_dot_dot) o2fsck_icount_delta(ost->ost_icount_refs, dir->dp_dot_dot, -1); /* pretend '..' pointed to the orphan dir */ dir->dp_dot_dot = dir->dp_dirent; o2fsck_icount_delta(ost->ost_icount_refs, dir->dp_dot_dot, 1); } if (dir->dp_dirent != dir->dp_dot_dot) { fix = prompt(ost, PY, PR_DIR_DOTDOT, "Directory inode %"PRIu64" is " "referenced by a dirent in directory %"PRIu64" " "but its '..' entry points to inode %"PRIu64". " "Fix the '..' entry to reference %"PRIu64"?", dir->dp_ino, dir->dp_dirent, dir->dp_dot_dot, dir->dp_dirent); if (fix) fix_dot_dot(ost, dir); } out: return ret; }
static void check_lostfound(o2fsck_state *ost) { char name[] = "lost+found"; int namelen = sizeof(name) - 1; uint64_t blkno; errcode_t ret; ret = ocfs2_lookup(ost->ost_fs, ost->ost_fs->fs_root_blkno, name, namelen, NULL, &ost->ost_lostfound_ino); if (ret == 0) return; if (!prompt(ost, PY, PR_LOSTFOUND_MISSING, "/lost+found does not exist. Create it so " "that we can possibly fill it with orphaned inodes?")) return; ret = ocfs2_new_inode(ost->ost_fs, &blkno, 0755 | S_IFDIR); if (ret) { com_err(whoami, ret, "while trying to allocate a new inode " "for /lost+found"); return; } ret = ocfs2_init_dir(ost->ost_fs, blkno, ost->ost_fs->fs_root_blkno); if (ret) { com_err(whoami, ret, "while trying to expand a new " "/lost+found directory"); goto out; } ret = ocfs2_link(ost->ost_fs, ost->ost_fs->fs_root_blkno, name, blkno, OCFS2_FT_DIR); if (ret) { com_err(whoami, ret, "while linking inode %"PRIu64" as " "/lost+found", blkno); goto out; } /* XXX maybe this should be a helper to clean up the dir tracking * for any new dir. "2" for both the l+f dirent pointing to the * inode and the "." dirent in its dirblock */ o2fsck_icount_set(ost->ost_icount_in_inodes, blkno, 2); o2fsck_icount_set(ost->ost_icount_refs, blkno, 2); ret = o2fsck_add_dir_parent(&ost->ost_dir_parents, blkno, ost->ost_fs->fs_root_blkno, ost->ost_fs->fs_root_blkno, 0); if (ret) { com_err(whoami, ret, "while recording a new /lost+found " "directory"); goto out; } /* we've already iterated through the dirblocks in pass2 so there * is no need to register l+f's new dir block */ ost->ost_lostfound_ino = blkno; blkno = 0; out: if (blkno) { ret = ocfs2_delete_inode(ost->ost_fs, blkno); if (ret) { com_err(whoami, ret, "while trying to clean up an " "an allocated inode after linking /lost+found " "failed"); } } }
static errcode_t add_slots(ocfs2_filesys *fs, int num_slots) { errcode_t ret; uint16_t old_num = OCFS2_RAW_SB(fs->fs_super)->s_max_slots; char fname[OCFS2_MAX_FILENAME_LEN]; uint64_t blkno; int i, j, max_slots; int ftype; struct tools_progress *prog = NULL; if (ocfs2_uses_extended_slot_map(OCFS2_RAW_SB(fs->fs_super))) { ret = TUNEFS_ET_TOO_MANY_SLOTS_EXTENDED; max_slots = INT16_MAX; } else { ret = TUNEFS_ET_TOO_MANY_SLOTS_OLD; max_slots = OCFS2_MAX_SLOTS; } if (num_slots > max_slots) goto bail; prog = tools_progress_start("Adding slots", "addslots", (NUM_SYSTEM_INODES - OCFS2_LAST_GLOBAL_SYSTEM_INODE - 1) * (num_slots - old_num)); if (!prog) { ret = TUNEFS_ET_NO_MEMORY; goto bail; } ret = 0; for (i = OCFS2_LAST_GLOBAL_SYSTEM_INODE + 1; i < NUM_SYSTEM_INODES; ++i) { for (j = old_num; j < num_slots; ++j) { ocfs2_sprintf_system_inode_name(fname, OCFS2_MAX_FILENAME_LEN, i, j); verbosef(VL_APP, "Creating system file \"%s\"\n", fname); /* Goto next if file already exists */ ret = ocfs2_lookup(fs, fs->fs_sysdir_blkno, fname, strlen(fname), NULL, &blkno); if (!ret) { verbosef(VL_APP, "System file \"%s\" already exists\n", fname); tools_progress_step(prog, 1); continue; } /* create inode for system file */ ret = ocfs2_new_system_inode(fs, &blkno, ocfs2_system_inodes[i].si_mode, ocfs2_system_inodes[i].si_iflags); if (ret) { verbosef(VL_APP, "%s while creating inode for " "system file \"%s\"\n", error_message(ret), fname); goto bail; } ftype = (S_ISDIR(ocfs2_system_inodes[i].si_mode) ? OCFS2_FT_DIR : OCFS2_FT_REG_FILE); /* if dir, alloc space to it */ if (ftype == OCFS2_FT_DIR) { ret = ocfs2_init_dir(fs, blkno, fs->fs_sysdir_blkno); if (ret) { verbosef(VL_APP, "%s while initializing " "directory \"%s\"\n", error_message(ret), fname); goto bail; } } /* Add the inode to the system dir */ ret = ocfs2_link(fs, fs->fs_sysdir_blkno, fname, blkno, ftype); if (ret) { verbosef(VL_APP, "%s while linking inode %"PRIu64" " "as \"%s\" in the system " "directory\n", error_message(ret), blkno, fname); goto bail; } verbosef(VL_APP, "System file \"%s\" created\n", fname); tools_progress_step(prog, 1); } } bail: if (prog) tools_progress_stop(prog); return ret; }
int main(int argc, char *argv[]) { errcode_t ret; uint64_t blkno, result_blkno; int c, len; char *filename, *lookup_path, *buf; char *filebuf; char *p; char lookup_name[256]; ocfs2_filesys *fs; blkno = 0; initialize_ocfs_error_table(); while ((c = getopt(argc, argv, "i:")) != EOF) { switch (c) { case 'i': blkno = read_number(optarg); if (blkno <= OCFS2_SUPER_BLOCK_BLKNO) { fprintf(stderr, "Invalid inode block: %s\n", optarg); print_usage(); return 1; } break; default: print_usage(); return 1; break; } } if (optind >= argc) { fprintf(stderr, "Missing filename\n"); print_usage(); return 1; } filename = argv[optind]; optind++; if (optind >= argc) { fprintf(stdout, "Missing path to lookup\n"); print_usage(); return 1; } lookup_path = argv[optind]; ret = ocfs2_open(filename, OCFS2_FLAG_RO, 0, 0, &fs); if (ret) { com_err(argv[0], ret, "while opening file \"%s\"", filename); goto out; } ret = ocfs2_malloc_block(fs->fs_io, &buf); if (ret) { com_err(argv[0], ret, "while allocating inode buffer"); goto out_close; } if (!blkno) blkno = OCFS2_RAW_SB(fs->fs_super)->s_root_blkno; for (p = lookup_path; *p == '/'; p++); lookup_path = p; for (p = lookup_path; ; p++) { if (*p && *p != '/') continue; memcpy(lookup_name, lookup_path, p - lookup_path); lookup_name[p - lookup_path] = '\0'; ret = ocfs2_lookup(fs, blkno, lookup_name, strlen(lookup_name), NULL, &result_blkno); if (ret) { com_err(argv[0], ret, "while looking up \"%s\" in inode %"PRIu64 " on \"%s\"\n", lookup_name, blkno, filename); goto out_free; } blkno = result_blkno; for (; *p == '/'; p++); lookup_path = p; if (!*p) break; } if (ocfs2_check_directory(fs, blkno) != OCFS2_ET_NO_DIRECTORY) { com_err(argv[0], ret, "\"%s\" is not a file", filename); goto out_free; } ret = ocfs2_read_whole_file(fs, blkno, &filebuf, &len); if (ret) { com_err(argv[0], ret, "while reading file \"%s\" -- read %d bytes", filename, len); goto out_free_filebuf; } if (!len) fprintf(stderr, "boo!\n"); dump_filebuf(filebuf, len); out_free_filebuf: if (len) ocfs2_free(&filebuf); out_free: ocfs2_free(&buf); out_close: ret = ocfs2_close(fs); if (ret) { com_err(argv[0], ret, "while closing file \"%s\"", filename); } out: return 0; }
errcode_t ocfs2_fill_heartbeat_desc(ocfs2_filesys *fs, struct o2cb_region_desc *desc) { errcode_t ret; char *filename; char *buf = NULL; uint64_t blkno, blocks, start_block; uint32_t block_bits, cluster_bits; int sectsize, sectsize_bits; struct ocfs2_dinode *di; struct ocfs2_extent_rec *rec; ret = ocfs2_get_device_sectsize(fs->fs_devname, §size); if (ret) { if (ret == OCFS2_ET_CANNOT_DETERMINE_SECTOR_SIZE) sectsize = OCFS2_MIN_BLOCKSIZE; else goto leave; } sectsize_bits = ffs(sectsize) - 1; filename = ocfs2_system_inodes[HEARTBEAT_SYSTEM_INODE].si_name; ret = ocfs2_lookup(fs, fs->fs_sysdir_blkno, filename, strlen(filename), NULL, &blkno); if (ret) goto leave; ret = ocfs2_malloc_block(fs->fs_io, &buf); if (ret) goto leave; ret = ocfs2_read_inode(fs, blkno, buf); if (ret) goto leave; di = (struct ocfs2_dinode *)buf; if (di->id2.i_list.l_tree_depth || di->id2.i_list.l_next_free_rec != 1) { ret = OCFS2_ET_BAD_HEARTBEAT_FILE; goto leave; } rec = &(di->id2.i_list.l_recs[0]); block_bits = OCFS2_RAW_SB(fs->fs_super)->s_blocksize_bits; cluster_bits = OCFS2_RAW_SB(fs->fs_super)->s_clustersize_bits; if (block_bits < sectsize_bits) { ret = OCFS2_ET_BLOCK_SIZE_TOO_SMALL_FOR_HARDWARE; goto leave; } blocks = ocfs2_rec_clusters(0, rec) << cluster_bits; blocks >>= block_bits; if (blocks > O2NM_MAX_NODES) blocks = O2NM_MAX_NODES; start_block = rec->e_blkno << block_bits; start_block >>= sectsize_bits; desc->r_name = fs->uuid_str; desc->r_device_name = fs->fs_devname; desc->r_block_bytes = sectsize; desc->r_start_block = start_block; desc->r_blocks = blocks; leave: if (buf) ocfs2_free(&buf); return ret; }
int main(int argc, char *argv[]) { errcode_t ret; uint64_t blkno, sys_blkno; int c; char *filename, *buf; const char *bitmap_name = ocfs2_system_inodes[GLOBAL_BITMAP_SYSTEM_INODE].si_name; ocfs2_filesys *fs; struct ocfs2_dinode *di; struct walk_block wb; blkno = OCFS2_SUPER_BLOCK_BLKNO; initialize_ocfs_error_table(); while ((c = getopt(argc, argv, "i:")) != EOF) { switch (c) { case 'i': blkno = read_number(optarg); if (blkno <= OCFS2_SUPER_BLOCK_BLKNO) { fprintf(stderr, "Invalid inode block: %s\n", optarg); print_usage(); return 1; } break; default: print_usage(); return 1; break; } } if (optind >= argc) { fprintf(stderr, "Missing filename\n"); print_usage(); return 1; } filename = argv[optind]; ret = ocfs2_open(filename, OCFS2_FLAG_RW, 0, 0, &fs); if (ret) { com_err(argv[0], ret, "while opening file \"%s\"", filename); goto out; } if (blkno == OCFS2_SUPER_BLOCK_BLKNO) { sys_blkno = OCFS2_RAW_SB(fs->fs_super)->s_system_dir_blkno; ret = ocfs2_lookup(fs, sys_blkno, bitmap_name, strlen(bitmap_name), NULL, &blkno); if (ret) { com_err(argv[0], ret, "while looking up \"%s\"", bitmap_name); goto out; } } ret = ocfs2_malloc_block(fs->fs_io, &buf); if (ret) { com_err(argv[0], ret, "while allocating inode buffer"); goto out_close; } memset(&wb, 0, sizeof(wb)); ret = ocfs2_read_inode(fs, blkno, buf); if (ret) { com_err(argv[0], ret, "while reading inode %"PRIu64, blkno); goto out_free; } di = (struct ocfs2_dinode *)buf; wb.di = di; ret = ocfs2_malloc_block(fs->fs_io, &wb.buf); if (ret) { com_err(argv[0], ret, "while allocating block buffer"); goto out_free; } ret = ocfs2_block_iterate(fs, blkno, 0, walk_blocks_func, &wb); if (ret) { com_err(argv[0], ret, "while walking blocks"); goto out_free; } di->id1.bitmap1.i_used = wb.used; ret = ocfs2_write_inode(fs, blkno, buf); if (ret) { com_err(argv[0], ret, "while reading inode %"PRIu64, blkno); goto out_free; } out_free: if (wb.buf) ocfs2_free(&wb.buf); ocfs2_free(&buf); out_close: ret = ocfs2_close(fs); if (ret) { com_err(argv[0], ret, "while closing file \"%s\"", filename); } out: return 0; }