ino_t minixfs_new_inode (void) { char *bh = bptr (I_MAP_BOFFS); ino_t inum; unsigned long bits = sblock->s_ninodes; spin_lock (&global_lock); repeat: inum = find_first_zero_bit ((unsigned long *) bh, bits); if (inum < bits) { assert (sblock_info->s_free_inodes_count > 0); minixfs_debug ("eligible bit found at position %Lu", inum); if (set_bit (inum, bh)) { /* shouldn't happen */ minixfs_warning ("bit already set for inode %Lu", inum); goto repeat; } record_global_poke (bh); } else { assert (sblock_info->s_free_inodes_count == 0); minixfs_debug ("no more free inodes"); inum = 0; goto sync_out; } if (inum < MINIXFS_FIRST_INO) { minixfs_error ("reserved inode"); inum = 0; goto sync_out; } sblock_info->s_free_inodes_count--; sync_out: spin_unlock (&global_lock); alloc_sync (0); return inum; }
static inline void _free_zone_run_flush (struct free_zone_run *fzr, unsigned long count) { fzr->node->dn_stat.st_blocks -= count << (log2_stat_blocks_per_fs_block + log2_fs_blocks_per_zone); fzr->node->dn_stat_dirty = 1; minixfs_debug ("flushing freed zones %u-%u (node %Ld)", fzr->first_zone, (zone_t) (fzr->first_zone + count), fzr->node->cache_id); minixfs_free_zones (fzr->first_zone, count); }
/* Free any direct zones starting with zone at node index END. */ static void trunc_direct_V1 (struct node *node, zone_t end, struct free_zone_run *fzr) { uint16_t *zones = (uint16_t *) (node->dn->info.i_zone_V1); minixfs_debug ("truncating direct zones starting at node index %u " "(node %Ld)", end, node->cache_id); while (end < MINIXFS_NDIR_ZONES) free_zone_run_free_ptr (fzr, (zone_t *) (zones + (int) end++)); }
/* Free node NP; the on disk copy has already been synced with diskfs_node_update (where NP->dn_stat.st_mode was 0). Its mode used to be OLD_MODE. */ void diskfs_free_node (struct node *np, mode_t old_mode) { char *bh; ino_t inum = np->cache_id; block_t imap_block; assert (!diskfs_readonly); spin_lock (&global_lock); if (inum < MINIXFS_FIRST_INO || inum > sblock->s_ninodes) { minixfs_error ("trying to free a reserved or nonexistent inode: %Lu", inum); spin_unlock (&global_lock); return; } minixfs_debug ("freeing inode %Lu", inum); imap_block = inum >> LOG2_BITS_PER_BLOCK; if (imap_block >= sblock->s_imap_blocks) { minixfs_error ("nonexistent imap in superblock: %u", imap_block); spin_unlock (&global_lock); return; } bh = bptr (I_MAP_BOFFS + imap_block); if (! clear_bit (inum & (BITS_PER_BLOCK - 1), bh)) minixfs_warning ("bit already cleared for inode %Lu", inum); else { record_global_poke (bh); sblock_info->s_free_inodes_count++; } spin_unlock (&global_lock); alloc_sync (0); }