xref: /aosp_15_r20/external/e2fsprogs/lib/ext2fs/alloc_stats.c (revision 6a54128f25917bfc36a8a6e9d722c04a0b4641b6)
1*6a54128fSAndroid Build Coastguard Worker /*
2*6a54128fSAndroid Build Coastguard Worker  * alloc_stats.c --- Update allocation statistics for ext2fs
3*6a54128fSAndroid Build Coastguard Worker  *
4*6a54128fSAndroid Build Coastguard Worker  * Copyright (C) 2001 Theodore Ts'o.
5*6a54128fSAndroid Build Coastguard Worker  *
6*6a54128fSAndroid Build Coastguard Worker  * %Begin-Header%
7*6a54128fSAndroid Build Coastguard Worker  * This file may be redistributed under the terms of the GNU Library
8*6a54128fSAndroid Build Coastguard Worker  * General Public License, version 2.
9*6a54128fSAndroid Build Coastguard Worker  * %End-Header%
10*6a54128fSAndroid Build Coastguard Worker  */
11*6a54128fSAndroid Build Coastguard Worker 
12*6a54128fSAndroid Build Coastguard Worker #include "config.h"
13*6a54128fSAndroid Build Coastguard Worker #include <stdio.h>
14*6a54128fSAndroid Build Coastguard Worker 
15*6a54128fSAndroid Build Coastguard Worker #include "ext2_fs.h"
16*6a54128fSAndroid Build Coastguard Worker #include "ext2fs.h"
17*6a54128fSAndroid Build Coastguard Worker 
ext2fs_inode_alloc_stats2(ext2_filsys fs,ext2_ino_t ino,int inuse,int isdir)18*6a54128fSAndroid Build Coastguard Worker void ext2fs_inode_alloc_stats2(ext2_filsys fs, ext2_ino_t ino,
19*6a54128fSAndroid Build Coastguard Worker 			       int inuse, int isdir)
20*6a54128fSAndroid Build Coastguard Worker {
21*6a54128fSAndroid Build Coastguard Worker 	int	group = ext2fs_group_of_ino(fs, ino);
22*6a54128fSAndroid Build Coastguard Worker 
23*6a54128fSAndroid Build Coastguard Worker 	if (ino > fs->super->s_inodes_count) {
24*6a54128fSAndroid Build Coastguard Worker #ifndef OMIT_COM_ERR
25*6a54128fSAndroid Build Coastguard Worker 		com_err("ext2fs_inode_alloc_stats2", 0,
26*6a54128fSAndroid Build Coastguard Worker 			"Illegal inode number: %lu", (unsigned long) ino);
27*6a54128fSAndroid Build Coastguard Worker #endif
28*6a54128fSAndroid Build Coastguard Worker 		return;
29*6a54128fSAndroid Build Coastguard Worker 	}
30*6a54128fSAndroid Build Coastguard Worker 	if (inuse > 0)
31*6a54128fSAndroid Build Coastguard Worker 		ext2fs_mark_inode_bitmap2(fs->inode_map, ino);
32*6a54128fSAndroid Build Coastguard Worker 	else
33*6a54128fSAndroid Build Coastguard Worker 		ext2fs_unmark_inode_bitmap2(fs->inode_map, ino);
34*6a54128fSAndroid Build Coastguard Worker 	ext2fs_bg_free_inodes_count_set(fs, group, ext2fs_bg_free_inodes_count(fs, group) - inuse);
35*6a54128fSAndroid Build Coastguard Worker 	if (isdir)
36*6a54128fSAndroid Build Coastguard Worker 		ext2fs_bg_used_dirs_count_set(fs, group, ext2fs_bg_used_dirs_count(fs, group) + inuse);
37*6a54128fSAndroid Build Coastguard Worker 
38*6a54128fSAndroid Build Coastguard Worker 	/* We don't strictly need to be clearing the uninit flag if inuse < 0
39*6a54128fSAndroid Build Coastguard Worker 	 * (i.e. freeing inodes) but it also means something is bad. */
40*6a54128fSAndroid Build Coastguard Worker 	ext2fs_bg_flags_clear(fs, group, EXT2_BG_INODE_UNINIT);
41*6a54128fSAndroid Build Coastguard Worker 	if (ext2fs_has_group_desc_csum(fs)) {
42*6a54128fSAndroid Build Coastguard Worker 		ext2_ino_t first_unused_inode =	fs->super->s_inodes_per_group -
43*6a54128fSAndroid Build Coastguard Worker 			ext2fs_bg_itable_unused(fs, group) +
44*6a54128fSAndroid Build Coastguard Worker 			group * fs->super->s_inodes_per_group + 1;
45*6a54128fSAndroid Build Coastguard Worker 
46*6a54128fSAndroid Build Coastguard Worker 		if (ino >= first_unused_inode)
47*6a54128fSAndroid Build Coastguard Worker 			ext2fs_bg_itable_unused_set(fs, group, group * fs->super->s_inodes_per_group + fs->super->s_inodes_per_group - ino);
48*6a54128fSAndroid Build Coastguard Worker 		ext2fs_group_desc_csum_set(fs, group);
49*6a54128fSAndroid Build Coastguard Worker 	}
50*6a54128fSAndroid Build Coastguard Worker 
51*6a54128fSAndroid Build Coastguard Worker 	fs->super->s_free_inodes_count -= inuse;
52*6a54128fSAndroid Build Coastguard Worker 	ext2fs_mark_super_dirty(fs);
53*6a54128fSAndroid Build Coastguard Worker 	ext2fs_mark_ib_dirty(fs);
54*6a54128fSAndroid Build Coastguard Worker }
55*6a54128fSAndroid Build Coastguard Worker 
ext2fs_inode_alloc_stats(ext2_filsys fs,ext2_ino_t ino,int inuse)56*6a54128fSAndroid Build Coastguard Worker void ext2fs_inode_alloc_stats(ext2_filsys fs, ext2_ino_t ino, int inuse)
57*6a54128fSAndroid Build Coastguard Worker {
58*6a54128fSAndroid Build Coastguard Worker 	ext2fs_inode_alloc_stats2(fs, ino, inuse, 0);
59*6a54128fSAndroid Build Coastguard Worker }
60*6a54128fSAndroid Build Coastguard Worker 
ext2fs_block_alloc_stats2(ext2_filsys fs,blk64_t blk,int inuse)61*6a54128fSAndroid Build Coastguard Worker void ext2fs_block_alloc_stats2(ext2_filsys fs, blk64_t blk, int inuse)
62*6a54128fSAndroid Build Coastguard Worker {
63*6a54128fSAndroid Build Coastguard Worker 	int	group = ext2fs_group_of_blk2(fs, blk);
64*6a54128fSAndroid Build Coastguard Worker 
65*6a54128fSAndroid Build Coastguard Worker 	if (blk < fs->super->s_first_data_block ||
66*6a54128fSAndroid Build Coastguard Worker 	    blk >= ext2fs_blocks_count(fs->super)) {
67*6a54128fSAndroid Build Coastguard Worker #ifndef OMIT_COM_ERR
68*6a54128fSAndroid Build Coastguard Worker 		com_err("ext2fs_block_alloc_stats", 0,
69*6a54128fSAndroid Build Coastguard Worker 			"Illegal block number: %lu", (unsigned long) blk);
70*6a54128fSAndroid Build Coastguard Worker #endif
71*6a54128fSAndroid Build Coastguard Worker 		return;
72*6a54128fSAndroid Build Coastguard Worker 	}
73*6a54128fSAndroid Build Coastguard Worker 	if (inuse > 0)
74*6a54128fSAndroid Build Coastguard Worker 		ext2fs_mark_block_bitmap2(fs->block_map, blk);
75*6a54128fSAndroid Build Coastguard Worker 	else
76*6a54128fSAndroid Build Coastguard Worker 		ext2fs_unmark_block_bitmap2(fs->block_map, blk);
77*6a54128fSAndroid Build Coastguard Worker 	ext2fs_bg_free_blocks_count_set(fs, group, ext2fs_bg_free_blocks_count(fs, group) - inuse);
78*6a54128fSAndroid Build Coastguard Worker 	ext2fs_bg_flags_clear(fs, group, EXT2_BG_BLOCK_UNINIT);
79*6a54128fSAndroid Build Coastguard Worker 	ext2fs_group_desc_csum_set(fs, group);
80*6a54128fSAndroid Build Coastguard Worker 
81*6a54128fSAndroid Build Coastguard Worker 	ext2fs_free_blocks_count_add(fs->super,
82*6a54128fSAndroid Build Coastguard Worker 			     -inuse * (blk64_t) EXT2FS_CLUSTER_RATIO(fs));
83*6a54128fSAndroid Build Coastguard Worker 	ext2fs_mark_super_dirty(fs);
84*6a54128fSAndroid Build Coastguard Worker 	ext2fs_mark_bb_dirty(fs);
85*6a54128fSAndroid Build Coastguard Worker 	if (fs->block_alloc_stats)
86*6a54128fSAndroid Build Coastguard Worker 		(fs->block_alloc_stats)(fs, (blk64_t) blk, inuse);
87*6a54128fSAndroid Build Coastguard Worker }
88*6a54128fSAndroid Build Coastguard Worker 
ext2fs_block_alloc_stats(ext2_filsys fs,blk_t blk,int inuse)89*6a54128fSAndroid Build Coastguard Worker void ext2fs_block_alloc_stats(ext2_filsys fs, blk_t blk, int inuse)
90*6a54128fSAndroid Build Coastguard Worker {
91*6a54128fSAndroid Build Coastguard Worker 	ext2fs_block_alloc_stats2(fs, blk, inuse);
92*6a54128fSAndroid Build Coastguard Worker }
93*6a54128fSAndroid Build Coastguard Worker 
ext2fs_set_block_alloc_stats_callback(ext2_filsys fs,void (* func)(ext2_filsys fs,blk64_t blk,int inuse),void (** old)(ext2_filsys fs,blk64_t blk,int inuse))94*6a54128fSAndroid Build Coastguard Worker void ext2fs_set_block_alloc_stats_callback(ext2_filsys fs,
95*6a54128fSAndroid Build Coastguard Worker 					   void (*func)(ext2_filsys fs,
96*6a54128fSAndroid Build Coastguard Worker 							blk64_t blk,
97*6a54128fSAndroid Build Coastguard Worker 							int inuse),
98*6a54128fSAndroid Build Coastguard Worker 					   void (**old)(ext2_filsys fs,
99*6a54128fSAndroid Build Coastguard Worker 							blk64_t blk,
100*6a54128fSAndroid Build Coastguard Worker 							int inuse))
101*6a54128fSAndroid Build Coastguard Worker {
102*6a54128fSAndroid Build Coastguard Worker 	if (!fs || fs->magic != EXT2_ET_MAGIC_EXT2FS_FILSYS)
103*6a54128fSAndroid Build Coastguard Worker 		return;
104*6a54128fSAndroid Build Coastguard Worker 	if (old)
105*6a54128fSAndroid Build Coastguard Worker 		*old = fs->block_alloc_stats;
106*6a54128fSAndroid Build Coastguard Worker 
107*6a54128fSAndroid Build Coastguard Worker 	fs->block_alloc_stats = func;
108*6a54128fSAndroid Build Coastguard Worker }
109*6a54128fSAndroid Build Coastguard Worker 
ext2fs_block_alloc_stats_range(ext2_filsys fs,blk64_t blk,blk_t num,int inuse)110*6a54128fSAndroid Build Coastguard Worker void ext2fs_block_alloc_stats_range(ext2_filsys fs, blk64_t blk,
111*6a54128fSAndroid Build Coastguard Worker 				    blk_t num, int inuse)
112*6a54128fSAndroid Build Coastguard Worker {
113*6a54128fSAndroid Build Coastguard Worker #ifndef OMIT_COM_ERR
114*6a54128fSAndroid Build Coastguard Worker 	if (blk + num > ext2fs_blocks_count(fs->super)) {
115*6a54128fSAndroid Build Coastguard Worker 		com_err("ext2fs_block_alloc_stats_range", 0,
116*6a54128fSAndroid Build Coastguard Worker 			"Illegal block range: %llu (%u) ",
117*6a54128fSAndroid Build Coastguard Worker 			(unsigned long long) blk, num);
118*6a54128fSAndroid Build Coastguard Worker 		return;
119*6a54128fSAndroid Build Coastguard Worker 	}
120*6a54128fSAndroid Build Coastguard Worker #endif
121*6a54128fSAndroid Build Coastguard Worker 	if (inuse == 0)
122*6a54128fSAndroid Build Coastguard Worker 		return;
123*6a54128fSAndroid Build Coastguard Worker 	if (inuse > 0) {
124*6a54128fSAndroid Build Coastguard Worker 		ext2fs_mark_block_bitmap_range2(fs->block_map, blk, num);
125*6a54128fSAndroid Build Coastguard Worker 		inuse = 1;
126*6a54128fSAndroid Build Coastguard Worker 	} else {
127*6a54128fSAndroid Build Coastguard Worker 		ext2fs_unmark_block_bitmap_range2(fs->block_map, blk, num);
128*6a54128fSAndroid Build Coastguard Worker 		inuse = -1;
129*6a54128fSAndroid Build Coastguard Worker 	}
130*6a54128fSAndroid Build Coastguard Worker 	while (num) {
131*6a54128fSAndroid Build Coastguard Worker 		int group = ext2fs_group_of_blk2(fs, blk);
132*6a54128fSAndroid Build Coastguard Worker 		blk64_t last_blk = ext2fs_group_last_block2(fs, group);
133*6a54128fSAndroid Build Coastguard Worker 		blk64_t n = num;
134*6a54128fSAndroid Build Coastguard Worker 
135*6a54128fSAndroid Build Coastguard Worker 		if (blk + num > last_blk)
136*6a54128fSAndroid Build Coastguard Worker 			n = last_blk - blk + 1;
137*6a54128fSAndroid Build Coastguard Worker 
138*6a54128fSAndroid Build Coastguard Worker 		ext2fs_bg_free_blocks_count_set(fs, group,
139*6a54128fSAndroid Build Coastguard Worker 			ext2fs_bg_free_blocks_count(fs, group) -
140*6a54128fSAndroid Build Coastguard Worker 			inuse*n/EXT2FS_CLUSTER_RATIO(fs));
141*6a54128fSAndroid Build Coastguard Worker 		ext2fs_bg_flags_clear(fs, group, EXT2_BG_BLOCK_UNINIT);
142*6a54128fSAndroid Build Coastguard Worker 		ext2fs_group_desc_csum_set(fs, group);
143*6a54128fSAndroid Build Coastguard Worker 		ext2fs_free_blocks_count_add(fs->super, -inuse * (blk64_t) n);
144*6a54128fSAndroid Build Coastguard Worker 		blk += n;
145*6a54128fSAndroid Build Coastguard Worker 		num -= n;
146*6a54128fSAndroid Build Coastguard Worker 	}
147*6a54128fSAndroid Build Coastguard Worker 	ext2fs_mark_super_dirty(fs);
148*6a54128fSAndroid Build Coastguard Worker 	ext2fs_mark_bb_dirty(fs);
149*6a54128fSAndroid Build Coastguard Worker 	if (fs->block_alloc_stats_range)
150*6a54128fSAndroid Build Coastguard Worker 		(fs->block_alloc_stats_range)(fs, blk, num, inuse);
151*6a54128fSAndroid Build Coastguard Worker }
152*6a54128fSAndroid Build Coastguard Worker 
ext2fs_set_block_alloc_stats_range_callback(ext2_filsys fs,void (* func)(ext2_filsys fs,blk64_t blk,blk_t num,int inuse),void (** old)(ext2_filsys fs,blk64_t blk,blk_t num,int inuse))153*6a54128fSAndroid Build Coastguard Worker void ext2fs_set_block_alloc_stats_range_callback(ext2_filsys fs,
154*6a54128fSAndroid Build Coastguard Worker 	void (*func)(ext2_filsys fs, blk64_t blk,
155*6a54128fSAndroid Build Coastguard Worker 				    blk_t num, int inuse),
156*6a54128fSAndroid Build Coastguard Worker 	void (**old)(ext2_filsys fs, blk64_t blk,
157*6a54128fSAndroid Build Coastguard Worker 				    blk_t num, int inuse))
158*6a54128fSAndroid Build Coastguard Worker {
159*6a54128fSAndroid Build Coastguard Worker 	if (!fs || fs->magic != EXT2_ET_MAGIC_EXT2FS_FILSYS)
160*6a54128fSAndroid Build Coastguard Worker 		return;
161*6a54128fSAndroid Build Coastguard Worker 	if (old)
162*6a54128fSAndroid Build Coastguard Worker 		*old = fs->block_alloc_stats_range;
163*6a54128fSAndroid Build Coastguard Worker 
164*6a54128fSAndroid Build Coastguard Worker 	fs->block_alloc_stats_range = func;
165*6a54128fSAndroid Build Coastguard Worker }
166