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