119dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project/*
219dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project * alloc_stats.c --- Update allocation statistics for ext2fs
319dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project *
419dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project * Copyright (C) 2001 Theodore Ts'o.
519dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project *
619dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project * %Begin-Header%
719dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project * This file may be redistributed under the terms of the GNU Public
819dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project * License.
919dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project * %End-Header%
103984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt *
1119dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project */
1219dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project
1319dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project#include <stdio.h>
1419dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project
1519dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project#include "ext2_fs.h"
1619dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project#include "ext2fs.h"
1719dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project
1819dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Projectvoid ext2fs_inode_alloc_stats2(ext2_filsys fs, ext2_ino_t ino,
1919dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project			       int inuse, int isdir)
2019dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project{
2119dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	int	group = ext2fs_group_of_ino(fs, ino);
2219dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project
233984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt#ifndef OMIT_COM_ERR
243984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt	if (ino > fs->super->s_inodes_count) {
253984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt		com_err("ext2fs_inode_alloc_stats2", 0,
263984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt			"Illegal inode number: %lu", (unsigned long) ino);
273984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt		return;
283984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt	}
293984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt#endif
3019dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	if (inuse > 0)
3119dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project		ext2fs_mark_inode_bitmap(fs->inode_map, ino);
3219dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	else
3319dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project		ext2fs_unmark_inode_bitmap(fs->inode_map, ino);
3419dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	fs->group_desc[group].bg_free_inodes_count -= inuse;
3519dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	if (isdir)
3619dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project		fs->group_desc[group].bg_used_dirs_count += inuse;
373984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt
383984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt	/* We don't strictly need to be clearing the uninit flag if inuse < 0
393984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt	 * (i.e. freeing inodes) but it also means something is bad. */
403984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt	fs->group_desc[group].bg_flags &= ~EXT2_BG_INODE_UNINIT;
413984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt	if (EXT2_HAS_RO_COMPAT_FEATURE(fs->super,
423984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt				       EXT4_FEATURE_RO_COMPAT_GDT_CSUM)) {
433984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt		ext2_ino_t first_unused_inode =	fs->super->s_inodes_per_group -
443984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt			fs->group_desc[group].bg_itable_unused +
453984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt			group * fs->super->s_inodes_per_group + 1;
463984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt
473984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt		if (ino >= first_unused_inode)
483984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt			fs->group_desc[group].bg_itable_unused =
493984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt				group * fs->super->s_inodes_per_group +
503984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt				fs->super->s_inodes_per_group - ino;
513984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt		ext2fs_group_desc_csum_set(fs, group);
523984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt	}
533984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt
5419dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	fs->super->s_free_inodes_count -= inuse;
5519dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	ext2fs_mark_super_dirty(fs);
5619dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	ext2fs_mark_ib_dirty(fs);
5719dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project}
5819dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project
5919dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Projectvoid ext2fs_inode_alloc_stats(ext2_filsys fs, ext2_ino_t ino, int inuse)
6019dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project{
6119dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	ext2fs_inode_alloc_stats2(fs, ino, inuse, 0);
6219dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project}
6319dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project
6419dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Projectvoid ext2fs_block_alloc_stats(ext2_filsys fs, blk_t blk, int inuse)
6519dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project{
6619dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	int	group = ext2fs_group_of_blk(fs, blk);
6719dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project
683984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt#ifndef OMIT_COM_ERR
693984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt	if (blk >= fs->super->s_blocks_count) {
703984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt		com_err("ext2fs_block_alloc_stats", 0,
713984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt			"Illegal block number: %lu", (unsigned long) blk);
723984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt		return;
733984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt	}
743984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt#endif
7519dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	if (inuse > 0)
7619dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project		ext2fs_mark_block_bitmap(fs->block_map, blk);
7719dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	else
7819dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project		ext2fs_unmark_block_bitmap(fs->block_map, blk);
7919dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	fs->group_desc[group].bg_free_blocks_count -= inuse;
803984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt	fs->group_desc[group].bg_flags &= ~EXT2_BG_BLOCK_UNINIT;
813984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt	ext2fs_group_desc_csum_set(fs, group);
823984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt
8319dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	fs->super->s_free_blocks_count -= inuse;
8419dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	ext2fs_mark_super_dirty(fs);
8519dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	ext2fs_mark_bb_dirty(fs);
863984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt	if (fs->block_alloc_stats)
873984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt		(fs->block_alloc_stats)(fs, (blk64_t) blk, inuse);
883984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt}
893984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt
903984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidtvoid ext2fs_set_block_alloc_stats_callback(ext2_filsys fs,
913984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt					   void (*func)(ext2_filsys fs,
923984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt							blk64_t blk,
933984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt							int inuse),
943984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt					   void (**old)(ext2_filsys fs,
953984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt							blk64_t blk,
963984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt							int inuse))
973984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt{
983984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt	if (!fs || fs->magic != EXT2_ET_MAGIC_EXT2FS_FILSYS)
993984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt		return;
1003984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt	if (old)
1013984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt		*old = fs->block_alloc_stats;
1023984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt
1033984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt	fs->block_alloc_stats = func;
10419dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project}
105