static void release_blocks(struct super_block *sb, int count) { if (count) { struct ext2_sb_info *sbi = EXT2_SB(sb); percpu_counter_add(&sbi->s_freeblocks_counter, count); } }
int ext4_claim_free_blocks(struct ext4_sb_info *sbi, s64 nblocks) { if (ext4_has_free_blocks(sbi, nblocks)) { percpu_counter_add(&sbi->s_dirtyblocks_counter, nblocks); return 0; } else return -ENOSPC; }
void increment_partitioned_counter(PARTITIONED_COUNTER pc, uint64_t amount) { percpu_counter_add(&pc->pcpu_counter, amount); }
/** * ext4_add_groupblocks() -- Add given blocks to an existing group * @handle: handle to this transaction * @sb: super block * @block: start physcial block to add to the block group * @count: number of blocks to free * * This marks the blocks as free in the bitmap. We ask the * mballoc to reload the buddy after this by setting group * EXT4_GROUP_INFO_NEED_INIT_BIT flag */ void ext4_add_groupblocks(handle_t *handle, struct super_block *sb, ext4_fsblk_t block, unsigned long count) { struct buffer_head *bitmap_bh = NULL; struct buffer_head *gd_bh; ext4_group_t block_group; ext4_grpblk_t bit; unsigned int i; struct ext4_group_desc *desc; struct ext4_super_block *es; struct ext4_sb_info *sbi; int err = 0, ret, blk_free_count; ext4_grpblk_t blocks_freed; struct ext4_group_info *grp; sbi = EXT4_SB(sb); es = sbi->s_es; ext4_debug("Adding block(s) %llu-%llu\n", block, block + count - 1); ext4_get_group_no_and_offset(sb, block, &block_group, &bit); grp = ext4_get_group_info(sb, block_group); /* * Check to see if we are freeing blocks across a group * boundary. */ if (bit + count > EXT4_BLOCKS_PER_GROUP(sb)) { goto error_return; } bitmap_bh = ext4_read_block_bitmap(sb, block_group); if (!bitmap_bh) goto error_return; desc = ext4_get_group_desc(sb, block_group, &gd_bh); if (!desc) goto error_return; if (in_range(ext4_block_bitmap(sb, desc), block, count) || in_range(ext4_inode_bitmap(sb, desc), block, count) || in_range(block, ext4_inode_table(sb, desc), sbi->s_itb_per_group) || in_range(block + count - 1, ext4_inode_table(sb, desc), sbi->s_itb_per_group)) { ext4_error(sb, __func__, "Adding blocks in system zones - " "Block = %llu, count = %lu", block, count); goto error_return; } /* * We are about to add blocks to the bitmap, * so we need undo access. */ BUFFER_TRACE(bitmap_bh, "getting undo access"); err = ext4_journal_get_undo_access(handle, bitmap_bh); if (err) goto error_return; /* * We are about to modify some metadata. Call the journal APIs * to unshare ->b_data if a currently-committing transaction is * using it */ BUFFER_TRACE(gd_bh, "get_write_access"); err = ext4_journal_get_write_access(handle, gd_bh); if (err) goto error_return; /* * make sure we don't allow a parallel init on other groups in the * same buddy cache */ down_write(&grp->alloc_sem); for (i = 0, blocks_freed = 0; i < count; i++) { BUFFER_TRACE(bitmap_bh, "clear bit"); if (!ext4_clear_bit_atomic(ext4_group_lock_ptr(sb, block_group), bit + i, bitmap_bh->b_data)) { ext4_error(sb, __func__, "bit already cleared for block %llu", (ext4_fsblk_t)(block + i)); BUFFER_TRACE(bitmap_bh, "bit already cleared"); } else { blocks_freed++; } } ext4_lock_group(sb, block_group); blk_free_count = blocks_freed + ext4_free_blks_count(sb, desc); ext4_free_blks_set(sb, desc, blk_free_count); desc->bg_checksum = ext4_group_desc_csum(sbi, block_group, desc); ext4_unlock_group(sb, block_group); percpu_counter_add(&sbi->s_freeblocks_counter, blocks_freed); if (sbi->s_log_groups_per_flex) { ext4_group_t flex_group = ext4_flex_group(sbi, block_group); atomic_add(blocks_freed, &sbi->s_flex_groups[flex_group].free_blocks); } /* * request to reload the buddy with the * new bitmap information */ set_bit(EXT4_GROUP_INFO_NEED_INIT_BIT, &(grp->bb_state)); grp->bb_free += blocks_freed; up_write(&grp->alloc_sem); /* We dirtied the bitmap block */ BUFFER_TRACE(bitmap_bh, "dirtied bitmap block"); err = ext4_handle_dirty_metadata(handle, NULL, bitmap_bh); /* And the group descriptor block */ BUFFER_TRACE(gd_bh, "dirtied group descriptor block"); ret = ext4_handle_dirty_metadata(handle, NULL, gd_bh); if (!err) err = ret; sb->s_dirt = 1; error_return: brelse(bitmap_bh); ext4_std_error(sb, err); return; }
/* _/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/ Function :me2fsAllocNewInode Input :struct inode *dir < vfs inode of directory > umode_t mode < file mode > const struct qstr *qstr < entry name for new inode > Output :void Return :struct inode* < new allocated inode > Description :allocate new inode _/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/ */ struct inode* me2fsAllocNewInode( struct inode *dir, umode_t mode, const struct qstr *qstr ) { struct super_block *sb; struct buffer_head *bitmap_bh; struct buffer_head *bh_gdesc; struct inode *inode; /* new inode */ ino_t ino; struct ext2_group_desc *gdesc; struct ext2_super_block *esb; struct me2fs_inode_info *mi; struct me2fs_sb_info *msi; unsigned long group; int i; int err; /* ------------------------------------------------------------------------ */ /* allocate vfs new inode */ /* ------------------------------------------------------------------------ */ sb = dir->i_sb; if( !( inode = new_inode( sb ) ) ) { return( ERR_PTR( -ENOMEM ) ); } bitmap_bh = NULL; ino = 0; msi = ME2FS_SB( sb ); if( S_ISDIR( mode ) ) { group = findDirectoryGroup( sb, dir ); } else { /* -------------------------------------------------------------------- */ /* as for now allocating inode for file is not support */ /* -------------------------------------------------------------------- */ err = -ENOSPC; goto fail; } if( group == -1 ) { err = -ENOSPC; goto fail; } for( i = 0 ; i < msi->s_groups_count ; i++ ) { brelse( bitmap_bh ); if( !( bitmap_bh = readInodeBitmap( sb, group ) ) ) { err = -EIO; goto fail; } ino = 0; /* -------------------------------------------------------------------- */ /* find free inode */ /* -------------------------------------------------------------------- */ repeat_in_this_group: ino = find_next_zero_bit_le( ( unsigned long* )bitmap_bh->b_data, msi->s_inodes_per_group, ino ); if( ME2FS_SB( sb )->s_inodes_per_group <= ino ) { /* cannot find ino. bitmap is already full */ group++; if( group <= msi->s_groups_count ) { group = 0; } continue; } /* -------------------------------------------------------------------- */ /* allocate inode atomically */ /* -------------------------------------------------------------------- */ if( ext2_set_bit_atomic( getSbBlockGroupLock( msi, group ), ( int )ino, bitmap_bh->b_data ) ) { /* ---------------------------------------------------------------- */ /* already set the bitmap */ /* ---------------------------------------------------------------- */ ino++; if( msi->s_inodes_per_group <= ino ) { /* the group has no entry, try next */ group++; if( msi->s_groups_count <= group ) { group = 0; } continue; } /* try to find in the same group */ goto repeat_in_this_group; } goto got; } /* ------------------------------------------------------------------------ */ /* cannot find free inode */ /* ------------------------------------------------------------------------ */ err = -ENOSPC; goto fail; /* ------------------------------------------------------------------------ */ /* found free inode */ /* ------------------------------------------------------------------------ */ got: mi = ME2FS_I( inode ); esb = msi->s_esb; mark_buffer_dirty( bitmap_bh ); if( sb->s_flags & MS_SYNCHRONOUS ) { sync_dirty_buffer( bitmap_bh ); } brelse( bitmap_bh ); /* ------------------------------------------------------------------------ */ /* get absolute inode number */ /* ------------------------------------------------------------------------ */ ino += ( group * ME2FS_SB( sb )->s_inodes_per_group ) + 1; if( ( ino < msi->s_first_ino ) || ( le32_to_cpu( esb->s_inodes_count ) < ino ) ) { ME2FS_ERROR( "<ME2FS>%s:insane inode number. ino=%lu,group=%lu\n", __func__, ( unsigned long )ino, group ); err = -EIO; goto fail; } /* ------------------------------------------------------------------------ */ /* update group descriptor */ /* ------------------------------------------------------------------------ */ gdesc = me2fsGetGroupDescriptor( sb, group ); bh_gdesc = me2fsGetGdescBufferCache( sb, group ); percpu_counter_add( &msi->s_freeinodes_counter, -1 ); if( S_ISDIR( mode ) ) { percpu_counter_inc( &msi->s_dirs_counter ); } spin_lock( getSbBlockGroupLock( msi, group ) ); { le16_add_cpu( &gdesc->bg_free_inodes_count, -1 ); if( S_ISDIR( mode ) ) { le16_add_cpu( &gdesc->bg_used_dirs_count, 1 ); } } spin_unlock( getSbBlockGroupLock( msi, group ) ); mark_buffer_dirty( bh_gdesc ); /* ------------------------------------------------------------------------ */ /* initialize vfs inode */ /* ------------------------------------------------------------------------ */ inode_init_owner( inode, dir, mode ); inode->i_ino = ino; inode->i_blocks = 0; inode->i_mtime = CURRENT_TIME_SEC; inode->i_atime = inode->i_mtime; inode->i_ctime = inode->i_mtime; /* ------------------------------------------------------------------------ */ /* initialize me2fs inode information */ /* ------------------------------------------------------------------------ */ memset( mi->i_data, 0, sizeof( mi->i_data ) ); mi->i_flags = ME2FS_I( dir )->i_flags & EXT2_FL_INHERITED; if( S_ISDIR( mode ) ) { /* do nothing */ } else if( S_ISREG( mode ) ) { mi->i_flags &= EXT2_REG_FLMASK; } else { mi->i_flags &= EXT2_OTHER_FLMASK; } mi->i_faddr = 0; mi->i_frag_no = 0; mi->i_frag_size = 0; mi->i_file_acl = 0; mi->i_dir_acl = 0; mi->i_dtime = 0; //mi->i_block_alloc_info = NULL; mi->i_state = EXT2_STATE_NEW; me2fsSetVfsInodeFlags( inode ); /* insert vfs inode to hash table */ if( insert_inode_locked( inode ) < 0 ) { ME2FS_ERROR( "<ME2FS>%s:inode number already in use[%lu]\n", __func__, ( unsigned long )ino ); err = -EIO; goto fail; } /* initialize quota */ #if 0 // quota dquot_initialize( inode ); if( dquot_alloc_inode( inode ) ) { goto fail_drop; } #endif #if 0 // acl /* initialize acl */ if( me2fsInitAcl( inde, dir ) ) { goto fail_free_drop; } #endif #if 0 // security /* initialize security */ if( me2fsInitSecurity( inode, dir, qstr ) ) { goto fail_free_drop; } #endif mark_inode_dirty( inode ); DBGPRINT( "<ME2FS>allocating new inode %lu\n", ( unsigned long )inode->i_ino ); #if 0 // preread me2fsPrereadInode( inode ); #endif return( inode ); /* ------------------------------------------------------------------------ */ /* allocation of new inode is failed */ /* ------------------------------------------------------------------------ */ fail: make_bad_inode( inode ); iput( inode ); return( ERR_PTR( err ) ); }