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