/* * ok, the uncertain inodes are a set of trees just like the * good inodes but all starting inode records are (arbitrarily) * aligned on XFS_CHUNK_PER_INODE boundaries to prevent overlaps. * this means we may have partials records in the tree (e.g. records * without 64 confirmed uncertain inodes). Tough. * * free is set to 1 if the inode is thought to be free, 0 if used */ void add_aginode_uncertain( struct xfs_mount *mp, xfs_agnumber_t agno, xfs_agino_t ino, int free) { ino_tree_node_t *ino_rec; xfs_agino_t s_ino; int offset; ASSERT(agno < glob_agcount); ASSERT(last_rec != NULL); s_ino = rounddown(ino, XFS_INODES_PER_CHUNK); /* * check for a cache hit */ if (last_rec[agno] != NULL && last_rec[agno]->ino_startnum == s_ino) { offset = ino - s_ino; if (free) set_inode_free(last_rec[agno], offset); else set_inode_used(last_rec[agno], offset); return; } /* * check to see if record containing inode is already in the tree. * if not, add it */ ino_rec = (ino_tree_node_t *) avl_findrange(inode_uncertain_tree_ptrs[agno], s_ino); if (!ino_rec) { ino_rec = alloc_ino_node(mp, s_ino); if (!avl_insert(inode_uncertain_tree_ptrs[agno], &ino_rec->avl_node)) do_error( _("add_aginode_uncertain - duplicate inode range\n")); } if (free) set_inode_free(ino_rec, ino - s_ino); else set_inode_used(ino_rec, ino - s_ino); /* * set cache entry */ last_rec[agno] = ino_rec; }
int get_free_inode(jfs_t *jfs) { int groups, i; if (jfs->d_img->size % (BLOCKSIZE * BLOCKS_PER_GROUP) == 0) { groups = jfs->d_img->size / (BLOCKSIZE * BLOCKS_PER_GROUP); } else { groups = 1 + jfs->d_img->size / (BLOCKSIZE * BLOCKS_PER_GROUP); } for (i = 0; i < groups; i++) { struct blockgroup *grp; char block[BLOCKSIZE]; int freeinode; /* read the blockgroup header */ jfs_read_block(jfs, block, i * BLOCKS_PER_GROUP); grp = (struct blockgroup *)block; freeinode = -1; freeinode = find_free_inode(grp->inode_bitmap); if (freeinode >= 0) { /* if there's a free block in this group, then return it */ set_inode_used(grp->inode_bitmap, freeinode); jfs_write_block(jfs, block, i * BLOCKS_PER_GROUP); freeinode += i * INODES_PER_GROUP; /* printf("allocating free inode: %d\n", freeinode);*/ return freeinode; } } return -1; }
/* * make sure the root and realtime inodes show up allocated * even if they've been freed. they get reinitialized in phase6. */ static void keep_fsinos(xfs_mount_t *mp) { ino_tree_node_t *irec; int i; irec = find_inode_rec(mp, XFS_INO_TO_AGNO(mp, mp->m_sb.sb_rootino), XFS_INO_TO_AGINO(mp, mp->m_sb.sb_rootino)); for (i = 0; i < 3; i++) set_inode_used(irec, i); }
/* * if ino doesn't exist, it must be properly aligned -- on a * filesystem block boundary or XFS_INODES_PER_CHUNK boundary, * whichever alignment is larger. */ ino_tree_node_t * set_inode_used_alloc(struct xfs_mount *mp, xfs_agnumber_t agno, xfs_agino_t ino) { ino_tree_node_t *ino_rec; /* * check alignment -- the only way to detect this * is too see if the chunk overlaps another chunk * already in the tree */ ino_rec = add_inode(mp, agno, ino); ASSERT(ino_rec != NULL); ASSERT(ino >= ino_rec->ino_startnum && ino - ino_rec->ino_startnum < XFS_INODES_PER_CHUNK); set_inode_used(ino_rec, ino - ino_rec->ino_startnum); return(ino_rec); }
void phase2( struct xfs_mount *mp, int scan_threads) { int j; ino_tree_node_t *ino_rec; /* now we can start using the buffer cache routines */ set_mp(mp); /* Check whether this fs has internal or external log */ if (mp->m_sb.sb_logstart == 0) { if (!x.logname) do_error(_("This filesystem has an external log. " "Specify log device with the -l option.\n")); do_log(_("Phase 2 - using external log on %s\n"), x.logname); } else do_log(_("Phase 2 - using internal log\n")); /* Zero log if applicable */ if (!no_modify) { do_log(_(" - zero log...\n")); zero_log(mp); } do_log(_(" - scan filesystem freespace and inode maps...\n")); bad_ino_btree = 0; set_progress_msg(PROG_FMT_SCAN_AG, (__uint64_t) glob_agcount); scan_ags(mp, scan_threads); print_final_rpt(); /* * make sure we know about the root inode chunk */ if ((ino_rec = find_inode_rec(0, mp->m_sb.sb_rootino)) == NULL) { ASSERT(mp->m_sb.sb_rbmino == mp->m_sb.sb_rootino + 1 && mp->m_sb.sb_rsumino == mp->m_sb.sb_rootino + 2); do_warn(_("root inode chunk not found\n")); /* * mark the first 3 used, the rest are free */ ino_rec = set_inode_used_alloc(0, (xfs_agino_t) mp->m_sb.sb_rootino); set_inode_used(ino_rec, 1); set_inode_used(ino_rec, 2); for (j = 3; j < XFS_INODES_PER_CHUNK; j++) set_inode_free(ino_rec, j); /* * also mark blocks */ set_bmap_ext(0, XFS_INO_TO_AGBNO(mp, mp->m_sb.sb_rootino), mp->m_ialloc_blks, XR_E_INO); } else { do_log(_(" - found root inode chunk\n")); /* * blocks are marked, just make sure they're in use */ if (is_inode_free(ino_rec, 0)) { do_warn(_("root inode marked free, ")); set_inode_used(ino_rec, 0); if (!no_modify) do_warn(_("correcting\n")); else do_warn(_("would correct\n")); } if (is_inode_free(ino_rec, 1)) { do_warn(_("realtime bitmap inode marked free, ")); set_inode_used(ino_rec, 1); if (!no_modify) do_warn(_("correcting\n")); else do_warn(_("would correct\n")); } if (is_inode_free(ino_rec, 2)) { do_warn(_("realtime summary inode marked free, ")); set_inode_used(ino_rec, 2); if (!no_modify) do_warn(_("correcting\n")); else do_warn(_("would correct\n")); } } }
void phase2(xfs_mount_t *mp, libxfs_init_t *args) { xfs_agnumber_t i; xfs_agblock_t b; int j; ino_tree_node_t *ino_rec; /* now we can start using the buffer cache routines */ set_mp(mp); /* Check whether this fs has internal or external log */ if (mp->m_sb.sb_logstart == 0) { if (!args->logname) { fprintf (stderr, "This filesystem has an external log. " "Specify log device with the -l option.\n"); exit (1); } fprintf (stderr, "Phase 2 - using external log on %s\n", args->logname); } else fprintf (stderr, "Phase 2 - using internal log\n"); /* Zero log if applicable */ if (!no_modify) { do_log(" - zero log...\n"); zero_log(mp, args); } do_log(" - scan filesystem freespace and inode maps...\n"); /* * account for space used by ag headers and log if internal */ set_bmap_log(mp); set_bmap_fs(mp); bad_ino_btree = 0; for (i = 0; i < mp->m_sb.sb_agcount; i++) { scan_ag(i); #ifdef XR_INODE_TRACE print_inode_list(i); #endif } /* * make sure we know about the root inode chunk */ if ((ino_rec = find_inode_rec(0, mp->m_sb.sb_rootino)) == NULL) { ASSERT(mp->m_sb.sb_rbmino == mp->m_sb.sb_rootino + 1 && mp->m_sb.sb_rsumino == mp->m_sb.sb_rootino + 2); do_warn("root inode chunk not found\n"); /* * mark the first 3 used, the rest are free */ ino_rec = set_inode_used_alloc(0, (xfs_agino_t) mp->m_sb.sb_rootino); set_inode_used(ino_rec, 1); set_inode_used(ino_rec, 2); for (j = 3; j < XFS_INODES_PER_CHUNK; j++) set_inode_free(ino_rec, j); /* * also mark blocks */ for (b = 0; b < mp->m_ialloc_blks; b++) { set_agbno_state(mp, 0, b + XFS_INO_TO_AGBNO(mp, mp->m_sb.sb_rootino), XR_E_INO); } } else { do_log(" - found root inode chunk\n"); /* * blocks are marked, just make sure they're in use */ if (is_inode_free(ino_rec, 0)) { do_warn("root inode marked free, "); set_inode_used(ino_rec, 0); if (!no_modify) do_warn("correcting\n"); else do_warn("would correct\n"); } if (is_inode_free(ino_rec, 1)) { do_warn("realtime bitmap inode marked free, "); set_inode_used(ino_rec, 1); if (!no_modify) do_warn("correcting\n"); else do_warn("would correct\n"); } if (is_inode_free(ino_rec, 2)) { do_warn("realtime summary inode marked free, "); set_inode_used(ino_rec, 2); if (!no_modify) do_warn("correcting\n"); else do_warn("would correct\n"); } } }