blknum.c revision 4fca2b9c07981abca16d337b2e57f78569cbbe05
1/* 2 * blknum.c --- Functions to handle blk64_t and high/low 64-bit block 3 * number. 4 * 5 * Copyright IBM Corporation, 2007 6 * Author Jose R. Santos <jrs@us.ibm.com> 7 * 8 * %Begin-Header% 9 * This file may be redistributed under the terms of the GNU Public 10 * License. 11 * %End-Header% 12 */ 13 14#include "ext2fs.h" 15 16/* 17 * Return the group # of a block 18 */ 19dgrp_t ext2fs_group_of_blk2(ext2_filsys fs, blk64_t blk) 20{ 21 return (blk - fs->super->s_first_data_block) / 22 fs->super->s_blocks_per_group; 23} 24 25/* 26 * Return the first block (inclusive) in a group 27 */ 28blk64_t ext2fs_group_first_block2(ext2_filsys fs, dgrp_t group) 29{ 30 return fs->super->s_first_data_block + 31 ((blk64_t)group * fs->super->s_blocks_per_group); 32} 33 34/* 35 * Return the last block (inclusive) in a group 36 */ 37blk64_t ext2fs_group_last_block2(ext2_filsys fs, dgrp_t group) 38{ 39 return (group == fs->group_desc_count - 1 ? 40 ext2fs_blocks_count(fs->super) - 1 : 41 ext2fs_group_first_block2(fs, group) + 42 (fs->super->s_blocks_per_group - 1)); 43} 44 45/* 46 * Return the inode data block count 47 */ 48blk64_t ext2fs_inode_data_blocks2(ext2_filsys fs, 49 struct ext2_inode *inode) 50{ 51 return (inode->i_blocks | 52 ((fs->super->s_feature_ro_compat & 53 EXT4_FEATURE_RO_COMPAT_HUGE_FILE) ? 54 (__u64) inode->osd2.linux2.l_i_blocks_hi << 32 : 0)) - 55 (inode->i_file_acl ? fs->blocksize >> 9 : 0); 56} 57 58/* 59 * Return the inode i_blocks count 60 */ 61blk64_t ext2fs_inode_i_blocks(ext2_filsys fs, 62 struct ext2_inode *inode) 63{ 64 return (inode->i_blocks | 65 ((fs->super->s_feature_ro_compat & 66 EXT4_FEATURE_RO_COMPAT_HUGE_FILE) ? 67 (__u64)inode->osd2.linux2.l_i_blocks_hi << 32 : 0)); 68} 69 70/* 71 * Return the fs block count 72 */ 73blk64_t ext2fs_blocks_count(struct ext2_super_block *super) 74{ 75 return super->s_blocks_count | 76 (super->s_feature_incompat & EXT4_FEATURE_INCOMPAT_64BIT ? 77 (__u64) super->s_blocks_count_hi << 32 : 0); 78} 79 80/* 81 * Set the fs block count 82 */ 83void ext2fs_blocks_count_set(struct ext2_super_block *super, blk64_t blk) 84{ 85 super->s_blocks_count = blk; 86 if (super->s_feature_incompat & EXT4_FEATURE_INCOMPAT_64BIT) 87 super->s_blocks_count_hi = (__u64) blk >> 32; 88} 89 90/* 91 * Add to the current fs block count 92 */ 93void ext2fs_blocks_count_add(struct ext2_super_block *super, blk64_t blk) 94{ 95 blk64_t tmp; 96 tmp = ext2fs_blocks_count(super) + blk; 97 ext2fs_blocks_count_set(super, tmp); 98} 99 100/* 101 * Return the fs reserved block count 102 */ 103blk64_t ext2fs_r_blocks_count(struct ext2_super_block *super) 104{ 105 return super->s_r_blocks_count | 106 (super->s_feature_incompat & EXT4_FEATURE_INCOMPAT_64BIT ? 107 (__u64) super->s_r_blocks_count_hi << 32 : 0); 108} 109 110/* 111 * Set the fs reserved block count 112 */ 113void ext2fs_r_blocks_count_set(struct ext2_super_block *super, blk64_t blk) 114{ 115 super->s_r_blocks_count = blk; 116 if (super->s_feature_incompat & EXT4_FEATURE_INCOMPAT_64BIT) 117 super->s_r_blocks_count_hi = (__u64) blk >> 32; 118} 119 120/* 121 * Add to the current reserved fs block count 122 */ 123void ext2fs_r_blocks_count_add(struct ext2_super_block *super, blk64_t blk) 124{ 125 blk64_t tmp; 126 tmp = ext2fs_r_blocks_count(super) + blk; 127 ext2fs_r_blocks_count_set(super, tmp); 128} 129 130/* 131 * Return the fs free block count 132 */ 133blk64_t ext2fs_free_blocks_count(struct ext2_super_block *super) 134{ 135 return super->s_free_blocks_count | 136 (super->s_feature_incompat & EXT4_FEATURE_INCOMPAT_64BIT ? 137 (__u64) super->s_free_blocks_hi << 32 : 0); 138} 139 140/* 141 * Set the fs free block count 142 */ 143void ext2fs_free_blocks_count_set(struct ext2_super_block *super, blk64_t blk) 144{ 145 super->s_free_blocks_count = blk; 146 if (super->s_feature_incompat & EXT4_FEATURE_INCOMPAT_64BIT) 147 super->s_free_blocks_hi = (__u64) blk >> 32; 148} 149 150/* 151 * Add to the current free fs block count 152 */ 153void ext2fs_free_blocks_count_add(struct ext2_super_block *super, blk64_t blk) 154{ 155 blk64_t tmp; 156 tmp = ext2fs_free_blocks_count(super) + blk; 157 ext2fs_free_blocks_count_set(super, tmp); 158} 159 160/* 161 * Get a pointer to a block group descriptor. We need the explicit 162 * pointer to the group desc for code that swaps block group 163 * descriptors before writing them out, as it wants to make a copy and 164 * do the swap there. 165 */ 166struct ext2_group_desc *ext2fs_group_desc(ext2_filsys fs, 167 struct opaque_ext2_group_desc *gdp, 168 dgrp_t group) 169{ 170 if (fs->super->s_desc_size >= EXT2_MIN_DESC_SIZE_64BIT) 171 return (struct ext2_group_desc *) 172 ((struct ext4_group_desc *) gdp + group); 173 else 174 return (struct ext2_group_desc *) gdp + group; 175} 176 177/* Do the same but as an ext4 group desc for internal use here */ 178static struct ext4_group_desc *ext4fs_group_desc(ext2_filsys fs, 179 struct opaque_ext2_group_desc *gdp, 180 dgrp_t group) 181{ 182 return (struct ext4_group_desc *)ext2fs_group_desc(fs, gdp, group); 183} 184 185/* 186 * Return the block bitmap block of a group 187 */ 188blk64_t ext2fs_block_bitmap_loc(ext2_filsys fs, dgrp_t group) 189{ 190 struct ext4_group_desc *gdp; 191 192 gdp = ext4fs_group_desc(fs, fs->group_desc, group); 193 return gdp->bg_block_bitmap | 194 (fs->super->s_feature_incompat 195 & EXT4_FEATURE_INCOMPAT_64BIT ? 196 (__u64)gdp->bg_block_bitmap_hi << 32 : 0); 197} 198 199/* 200 * Set the block bitmap block of a group 201 */ 202void ext2fs_block_bitmap_loc_set(ext2_filsys fs, dgrp_t group, blk64_t blk) 203{ 204 struct ext4_group_desc *gdp; 205 206 gdp = ext4fs_group_desc(fs, fs->group_desc, group); 207 gdp->bg_block_bitmap = blk; 208 if (fs->super->s_feature_incompat & EXT4_FEATURE_INCOMPAT_64BIT) 209 gdp->bg_block_bitmap_hi = (__u64) blk >> 32; 210} 211 212/* 213 * Return the inode bitmap block of a group 214 */ 215blk64_t ext2fs_inode_bitmap_loc(ext2_filsys fs, dgrp_t group) 216{ 217 struct ext4_group_desc *gdp; 218 219 gdp = ext4fs_group_desc(fs, fs->group_desc, group); 220 return gdp->bg_inode_bitmap | 221 (fs->super->s_feature_incompat 222 & EXT4_FEATURE_INCOMPAT_64BIT ? 223 (__u64) gdp->bg_inode_bitmap_hi << 32 : 0); 224} 225 226/* 227 * Set the inode bitmap block of a group 228 */ 229void ext2fs_inode_bitmap_loc_set(ext2_filsys fs, dgrp_t group, blk64_t blk) 230{ 231 struct ext4_group_desc *gdp; 232 233 gdp = ext4fs_group_desc(fs, fs->group_desc, group); 234 gdp->bg_inode_bitmap = blk; 235 if (fs->super->s_feature_incompat & EXT4_FEATURE_INCOMPAT_64BIT) 236 gdp->bg_inode_bitmap_hi = (__u64) blk >> 32; 237} 238 239/* 240 * Return the inode table block of a group 241 */ 242blk64_t ext2fs_inode_table_loc(ext2_filsys fs, dgrp_t group) 243{ 244 struct ext4_group_desc *gdp; 245 246 gdp = ext4fs_group_desc(fs, fs->group_desc, group); 247 return gdp->bg_inode_table | 248 (fs->super->s_feature_incompat 249 & EXT4_FEATURE_INCOMPAT_64BIT ? 250 (__u64) gdp->bg_inode_table_hi << 32 : 0); 251} 252 253/* 254 * Set the inode table block of a group 255 */ 256void ext2fs_inode_table_loc_set(ext2_filsys fs, dgrp_t group, blk64_t blk) 257{ 258 struct ext4_group_desc *gdp; 259 260 gdp = ext4fs_group_desc(fs, fs->group_desc, group); 261 gdp->bg_inode_table = blk; 262 if (fs->super->s_feature_incompat & EXT4_FEATURE_INCOMPAT_64BIT) 263 gdp->bg_inode_table_hi = (__u64) blk >> 32; 264} 265 266/* 267 * Return the free blocks count of a group 268 */ 269__u32 ext2fs_bg_free_blocks_count(ext2_filsys fs, dgrp_t group) 270{ 271 struct ext4_group_desc *gdp; 272 273 gdp = ext4fs_group_desc(fs, fs->group_desc, group); 274 return gdp->bg_free_blocks_count | 275 (fs->super->s_feature_incompat 276 & EXT4_FEATURE_INCOMPAT_64BIT ? 277 (__u32) gdp->bg_free_blocks_count_hi << 16 : 0); 278} 279 280/* 281 * Set the free blocks count of a group 282 */ 283void ext2fs_bg_free_blocks_count_set(ext2_filsys fs, dgrp_t group, __u32 n) 284{ 285 struct ext4_group_desc *gdp; 286 287 gdp = ext4fs_group_desc(fs, fs->group_desc, group); 288 gdp->bg_free_blocks_count = n; 289 290 if (fs->super->s_feature_incompat & EXT4_FEATURE_INCOMPAT_64BIT) 291 gdp->bg_free_blocks_count_hi = (__u32) n >> 16; 292} 293 294/* 295 * Return the free inodes count of a group 296 */ 297__u32 ext2fs_bg_free_inodes_count(ext2_filsys fs, dgrp_t group) 298{ 299 struct ext4_group_desc *gdp; 300 301 gdp = ext4fs_group_desc(fs, fs->group_desc, group); 302 return gdp->bg_free_inodes_count | 303 (fs->super->s_feature_incompat 304 & EXT4_FEATURE_INCOMPAT_64BIT ? 305 (__u32) gdp->bg_free_inodes_count_hi << 16 : 0); 306} 307 308/* 309 * Set the free inodes count of a group 310 */ 311void ext2fs_bg_free_inodes_count_set(ext2_filsys fs, dgrp_t group, __u32 n) 312{ 313 struct ext4_group_desc *gdp; 314 315 gdp = ext4fs_group_desc(fs, fs->group_desc, group); 316 gdp->bg_free_inodes_count = n; 317 if (fs->super->s_feature_incompat & EXT4_FEATURE_INCOMPAT_64BIT) 318 gdp->bg_free_inodes_count_hi = (__u32) n >> 16; 319} 320 321/* 322 * Return the used dirs count of a group 323 */ 324__u32 ext2fs_bg_used_dirs_count(ext2_filsys fs, dgrp_t group) 325{ 326 struct ext4_group_desc *gdp; 327 328 gdp = ext4fs_group_desc(fs, fs->group_desc, group); 329 return gdp->bg_used_dirs_count | 330 (fs->super->s_feature_incompat 331 & EXT4_FEATURE_INCOMPAT_64BIT ? 332 (__u32) gdp->bg_used_dirs_count_hi << 16 : 0); 333} 334 335/* 336 * Set the used dirs count of a group 337 */ 338void ext2fs_bg_used_dirs_count_set(ext2_filsys fs, dgrp_t group, __u32 n) 339{ 340 struct ext4_group_desc *gdp; 341 342 gdp = ext4fs_group_desc(fs, fs->group_desc, group); 343 gdp->bg_used_dirs_count = n; 344 if (fs->super->s_feature_incompat & EXT4_FEATURE_INCOMPAT_64BIT) 345 gdp->bg_used_dirs_count_hi = (__u32) n >> 16; 346} 347 348/* 349 * Return the unused inodes count of a group 350 */ 351__u32 ext2fs_bg_itable_unused(ext2_filsys fs, dgrp_t group) 352{ 353 struct ext4_group_desc *gdp; 354 355 gdp = ext4fs_group_desc(fs, fs->group_desc, group); 356 return gdp->bg_itable_unused | 357 (fs->super->s_feature_incompat 358 & EXT4_FEATURE_INCOMPAT_64BIT ? 359 (__u32) gdp->bg_itable_unused_hi << 16 : 0); 360} 361 362/* 363 * Set the unused inodes count of a group 364 */ 365void ext2fs_bg_itable_unused_set(ext2_filsys fs, dgrp_t group, __u32 n) 366{ 367 struct ext4_group_desc *gdp; 368 369 gdp = ext4fs_group_desc(fs, fs->group_desc, group); 370 gdp->bg_itable_unused = n; 371 if (fs->super->s_feature_incompat & EXT4_FEATURE_INCOMPAT_64BIT) 372 gdp->bg_itable_unused_hi = (__u32) n >> 16; 373} 374 375/* 376 * Get the flags for this block group 377 */ 378__u16 ext2fs_bg_flags(ext2_filsys fs, dgrp_t group) 379{ 380 struct ext4_group_desc *gdp; 381 382 gdp = ext4fs_group_desc(fs, fs->group_desc, group); 383 return gdp->bg_flags; 384} 385 386/* 387 * Zero out the flags for this block group 388 */ 389void ext2fs_bg_flags_zap(ext2_filsys fs, dgrp_t group) 390{ 391 struct ext4_group_desc *gdp; 392 393 gdp = ext4fs_group_desc(fs, fs->group_desc, group); 394 gdp->bg_flags = 0; 395 return; 396} 397 398/* 399 * Get the value of a particular flag for this block group 400 */ 401int ext2fs_bg_flags_test(ext2_filsys fs, dgrp_t group, __u16 bg_flag) 402{ 403 struct ext4_group_desc *gdp; 404 405 gdp = ext4fs_group_desc(fs, fs->group_desc, group); 406 return gdp->bg_flags & bg_flag; 407} 408 409/* 410 * Set a flag or set of flags for this block group 411 */ 412void ext2fs_bg_flags_set(ext2_filsys fs, dgrp_t group, __u16 bg_flags) 413{ 414 struct ext4_group_desc *gdp; 415 416 gdp = ext4fs_group_desc(fs, fs->group_desc, group); 417 gdp->bg_flags |= bg_flags; 418 return; 419} 420 421/* 422 * Clear a flag or set of flags for this block group 423 */ 424void ext2fs_bg_flags_clear(ext2_filsys fs, dgrp_t group, __u16 bg_flags) 425{ 426 struct ext4_group_desc *gdp; 427 428 gdp = ext4fs_group_desc(fs, fs->group_desc, group); 429 gdp->bg_flags &= ~bg_flags; 430 return; 431} 432 433/* 434 * Get the checksum for this block group 435 */ 436__u16 ext2fs_bg_checksum(ext2_filsys fs, dgrp_t group) 437{ 438 struct ext4_group_desc *gdp; 439 440 gdp = ext4fs_group_desc(fs, fs->group_desc, group); 441 return gdp->bg_checksum; 442} 443 444/* 445 * Set the checksum for this block group to a previously calculated value 446 */ 447void ext2fs_bg_checksum_set(ext2_filsys fs, dgrp_t group, __u16 checksum) 448{ 449 struct ext4_group_desc *gdp; 450 451 gdp = ext4fs_group_desc(fs, fs->group_desc, group); 452 gdp->bg_checksum = checksum; 453 return; 454} 455 456/* 457 * Get the acl block of a file 458 * 459 * XXX Ignoring 64-bit file system flag - most places where this is 460 * called don't have access to the fs struct, and the high bits should 461 * be 0 in the non-64-bit case anyway. 462 */ 463blk64_t ext2fs_file_acl_block(const struct ext2_inode *inode) 464{ 465 return (inode->i_file_acl | 466 (__u64) inode->osd2.linux2.l_i_file_acl_high << 32); 467} 468 469/* 470 * Set the acl block of a file 471 */ 472void ext2fs_file_acl_block_set(struct ext2_inode *inode, blk64_t blk) 473{ 474 inode->i_file_acl = blk; 475 inode->osd2.linux2.l_i_file_acl_high = (__u64) blk >> 32; 476} 477 478