errcode_t ocfs2_write_super(ocfs2_filesys *fs) { errcode_t ret; ret = ocfs2_write_primary_super(fs); if (!ret) ret = ocfs2_refresh_backup_supers(fs); return ret; }
static errcode_t recover_backup_super(o2fsck_state *ost, char* device, int sb_num) { errcode_t ret; uint64_t offsets[OCFS2_MAX_BACKUP_SUPERBLOCKS], blksize, sb; ocfs2_filesys *fs = NULL; if (sb_num < 1 || sb_num > OCFS2_MAX_BACKUP_SUPERBLOCKS) return -1; ocfs2_get_backup_super_offsets(NULL, offsets, ARRAY_SIZE(offsets)); /* iterate all the blocksize to get the right one. */ for (blksize = OCFS2_MIN_BLOCKSIZE; blksize <= OCFS2_MAX_BLOCKSIZE; blksize <<= 1) { sb = offsets[sb_num - 1] / blksize; /* Here we just give the possible value of block num and * block size to ocfs2_open and this function will check * them and return '0' if they meet the right one. */ ret = ocfs2_open(device, OCFS2_FLAG_RW, sb, blksize, &fs); if (!ret) break; } if (ret) goto bail; /* recover the backup information to superblock. */ if (prompt(ost, PN, PR_RECOVER_BACKUP_SUPERBLOCK, "Recover superblock information from backup block" "#%"PRIu64"?", sb)) { fs->fs_super->i_blkno = OCFS2_SUPER_BLOCK_BLKNO; ret = ocfs2_write_primary_super(fs); if (ret) goto bail; } /* no matter whether the user recover the superblock or not above, * we should return 0 in case the superblock can be opened * without the recovery. */ ret = 0; bail: if (fs) ocfs2_close(fs); return ret; }
static void check_root(o2fsck_state *ost) { struct ocfs2_super_block *sb = OCFS2_RAW_SB(ost->ost_fs->fs_super); errcode_t ret; uint64_t blkno, old_root; int was_set; if (o2fsck_test_inode_allocated(ost, ost->ost_fs->fs_root_blkno)) { ocfs2_bitmap_test(ost->ost_dir_inodes, ost->ost_fs->fs_root_blkno, &was_set); if (!was_set) printf("The root inode exists but isn't a " "directory.\n"); return; } if (!prompt(ost, PY, PR_ROOT_DIR_MISSING, "The super block claims that inode %"PRIu64" is the root " "directory but it isn't allocated. Create a new root " "directory and update the super block?", ost->ost_fs->fs_root_blkno)) 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 the root directory\n"); return; } ret = ocfs2_init_dir(ost->ost_fs, blkno, blkno); if (ret) { com_err(whoami, ret, "while trying to expand a new root " "directory"); goto out; } o2fsck_icount_set(ost->ost_icount_in_inodes, blkno, 1); o2fsck_icount_set(ost->ost_icount_refs, blkno, 1); 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 root directory"); goto out; } old_root = sb->s_root_blkno; ost->ost_fs->fs_root_blkno = blkno; sb->s_root_blkno = blkno; ret = ocfs2_write_primary_super(ost->ost_fs); if (ret) { com_err(whoami, ret, "while writing the super block with a " "new root directory inode"); ost->ost_fs->fs_root_blkno = old_root; sb->s_root_blkno = old_root; goto out; } 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 remove_slots(ocfs2_filesys *fs, int num_slots) { errcode_t ret; uint16_t old_num = OCFS2_RAW_SB(fs->fs_super)->s_max_slots; uint16_t removed_slot = old_num - 1; struct tools_progress *prog = NULL; ret = remove_slot_check(fs, num_slots); if (ret) goto bail; /* We have seven steps in removing each slot */ prog = tools_progress_start("Removing slots", "rmslots", (old_num - num_slots) * 7); if (!prog) { ret = TUNEFS_ET_NO_MEMORY; goto bail; } /* This is cleared up in update_slot_count() if everything works */ ret = tunefs_set_in_progress(fs, OCFS2_TUNEFS_INPROG_REMOVE_SLOT); if (ret) goto bail; /* we will remove the slots once at a time so that fsck.ocfs2 can work * well and we can continue our work easily in case of any panic. */ while (removed_slot >= num_slots) { /* Link the specified extent alloc file to others. */ ret = relink_system_alloc(fs, removed_slot, num_slots, EXTENT_ALLOC_SYSTEM_INODE); if (ret) goto bail; tools_progress_step(prog, 1); /* Link the specified inode alloc file to others. */ ret = relink_system_alloc(fs, removed_slot, num_slots, INODE_ALLOC_SYSTEM_INODE); if (ret) goto bail; tools_progress_step(prog, 1); /* Truncate the orphan dir to release its clusters * to the global bitmap. */ ret = truncate_orphan_dir(fs, removed_slot); if (ret) goto bail; tools_progress_step(prog, 1); /* empty the content of journal and truncate its clusters. */ ret = empty_and_truncate_journal(fs, removed_slot); if (ret) goto bail; tools_progress_step(prog, 1); /* Now, we decrease the max_slots first and then remove the * slots for the reason that: * * 1. ocfs2_lock_down_clusters needs to lock all the journal * files. so if we delete the journal entry first and fail * to decrease the max_slots, the whole cluster can't be * locked any more due to the loss of journals. * * 2. Now all the resources except the inodes are freed * so it is safe to decrease the slots first, and if any * panic happens after we decrease the slots, we can ignore * them, and actually if we want to increase the slot in the * future, we can reuse these inodes. */ /* The slot number is updated in the super block.*/ OCFS2_RAW_SB(fs->fs_super)->s_max_slots--; ret = ocfs2_write_primary_super(fs); if (ret) goto bail; tools_progress_step(prog, 1); /* The extra system dir entries should be removed. */ ret = remove_slot_entry(fs, removed_slot); if (ret) goto bail; tools_progress_step(prog, 1); /* Decrease the i_links_count in system file directory * since the orphan_dir is removed. */ ret = decrease_link_count(fs, fs->fs_sysdir_blkno); if (ret) goto bail; tools_progress_step(prog, 1); removed_slot--; } bail: if (prog) tools_progress_stop(prog); return ret; }