blknum.c revision d62d218f118863322742093ceb938bcac6093f80
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_incompat & EXT4_FEATURE_INCOMPAT_64BIT ? 53 (__u64)inode->osd2.linux2.l_i_blocks_hi << 32 : 0)) - 54 (inode->i_file_acl ? fs->blocksize >> 9 : 0); 55} 56 57/* 58 * Return the inode i_blocks count 59 */ 60blk64_t ext2fs_inode_i_blocks(ext2_filsys fs, 61 struct ext2_inode *inode) 62{ 63 return (inode->i_blocks | 64 (fs->super->s_feature_incompat & EXT4_FEATURE_INCOMPAT_64BIT ? 65 (__u64)inode->osd2.linux2.l_i_blocks_hi << 32 : 0)); 66} 67 68/* 69 * Return the fs block count 70 */ 71blk64_t ext2fs_blocks_count(struct ext2_super_block *super) 72{ 73 return super->s_blocks_count | 74 (super->s_feature_incompat & EXT4_FEATURE_INCOMPAT_64BIT ? 75 (__u64) super->s_blocks_count_hi << 32 : 0); 76} 77 78/* 79 * Set the fs block count 80 */ 81void ext2fs_blocks_count_set(struct ext2_super_block *super, blk64_t blk) 82{ 83 super->s_blocks_count = blk; 84 if (super->s_feature_incompat & EXT4_FEATURE_INCOMPAT_64BIT) 85 super->s_blocks_count_hi = (__u64) blk >> 32; 86} 87 88/* 89 * Add to the current fs block count 90 */ 91void ext2fs_blocks_count_add(struct ext2_super_block *super, blk64_t blk) 92{ 93 blk64_t tmp; 94 tmp = ext2fs_blocks_count(super) + blk; 95 ext2fs_blocks_count_set(super, tmp); 96} 97 98/* 99 * Return the fs reserved block count 100 */ 101blk64_t ext2fs_r_blocks_count(struct ext2_super_block *super) 102{ 103 return super->s_r_blocks_count | 104 (super->s_feature_incompat & EXT4_FEATURE_INCOMPAT_64BIT ? 105 (__u64) super->s_r_blocks_count_hi << 32 : 0); 106} 107 108/* 109 * Set the fs reserved block count 110 */ 111void ext2fs_r_blocks_count_set(struct ext2_super_block *super, blk64_t blk) 112{ 113 super->s_r_blocks_count = blk; 114 if (super->s_feature_incompat & EXT4_FEATURE_INCOMPAT_64BIT) 115 super->s_r_blocks_count_hi = (__u64) blk >> 32; 116} 117 118/* 119 * Add to the current reserved fs block count 120 */ 121void ext2fs_r_blocks_count_add(struct ext2_super_block *super, blk64_t blk) 122{ 123 blk64_t tmp; 124 tmp = ext2fs_r_blocks_count(super) + blk; 125 ext2fs_r_blocks_count_set(super, tmp); 126} 127 128/* 129 * Return the fs free block count 130 */ 131blk64_t ext2fs_free_blocks_count(struct ext2_super_block *super) 132{ 133 return super->s_free_blocks_count | 134 (super->s_feature_incompat & EXT4_FEATURE_INCOMPAT_64BIT ? 135 (__u64) super->s_free_blocks_hi << 32 : 0); 136} 137 138/* 139 * Set the fs free block count 140 */ 141void ext2fs_free_blocks_count_set(struct ext2_super_block *super, blk64_t blk) 142{ 143 super->s_free_blocks_count = blk; 144 if (super->s_feature_incompat & EXT4_FEATURE_INCOMPAT_64BIT) 145 super->s_free_blocks_hi = (__u64) blk >> 32; 146} 147 148/* 149 * Add to the current free fs block count 150 */ 151void ext2fs_free_blocks_count_add(struct ext2_super_block *super, blk64_t blk) 152{ 153 blk64_t tmp; 154 tmp = ext2fs_free_blocks_count(super) + blk; 155 ext2fs_free_blocks_count_set(super, tmp); 156} 157 158/* 159 * Get a pointer to a block group descriptor. We need the explicit 160 * pointer to the group desc for code that swaps block group 161 * descriptors before writing them out, as it wants to make a copy and 162 * do the swap there. 163 */ 164struct ext2_group_desc *ext2fs_group_desc(ext2_filsys fs, 165 struct ext2_group_desc *gdp, 166 dgrp_t group) 167{ 168 if (fs->super->s_desc_size >= EXT2_MIN_DESC_SIZE_64BIT) 169 return (struct ext2_group_desc *) 170 ((struct ext4_group_desc *) gdp + group); 171 else 172 return (struct ext2_group_desc *) gdp + group; 173} 174 175/* 176 * Return the block bitmap block of a group 177 */ 178blk64_t ext2fs_block_bitmap_loc(ext2_filsys fs, dgrp_t group) 179{ 180 if (fs->super->s_desc_size >= EXT2_MIN_DESC_SIZE_64BIT) { 181 struct ext4_group_desc *gdp; 182 gdp = (struct ext4_group_desc *) (fs->group_desc) + group; 183 184 return gdp->bg_block_bitmap | 185 (fs->super->s_feature_incompat 186 & EXT4_FEATURE_INCOMPAT_64BIT ? 187 (__u64) gdp->bg_block_bitmap_hi << 32 : 0); 188 } 189 190 return fs->group_desc[group].bg_block_bitmap; 191} 192 193/* 194 * Set the block bitmap block of a group 195 */ 196void ext2fs_block_bitmap_loc_set(ext2_filsys fs, dgrp_t group, blk64_t blk) 197{ 198 if (fs->super->s_desc_size >= EXT2_MIN_DESC_SIZE_64BIT) { 199 struct ext4_group_desc *gdp; 200 gdp = (struct ext4_group_desc *) (fs->group_desc) + group; 201 gdp->bg_block_bitmap = blk; 202 if (fs->super->s_feature_incompat & EXT4_FEATURE_INCOMPAT_64BIT) 203 gdp->bg_block_bitmap_hi = (__u64) blk >> 32; 204 } else 205 fs->group_desc[group].bg_block_bitmap = blk; 206} 207 208/* 209 * Return the inode bitmap block of a group 210 */ 211blk64_t ext2fs_inode_bitmap_loc(ext2_filsys fs, dgrp_t group) 212{ 213 if (fs->super->s_desc_size >= EXT2_MIN_DESC_SIZE_64BIT) { 214 struct ext4_group_desc *gdp; 215 gdp = (struct ext4_group_desc *) (fs->group_desc) + group; 216 217 return gdp->bg_inode_bitmap | 218 (fs->super->s_feature_incompat 219 & EXT4_FEATURE_INCOMPAT_64BIT ? 220 (__u64) gdp->bg_inode_bitmap_hi << 32 : 0); 221 } 222 223 return fs->group_desc[group].bg_inode_bitmap; 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 if (fs->super->s_desc_size >= EXT2_MIN_DESC_SIZE_64BIT) { 232 struct ext4_group_desc *gdp; 233 gdp = (struct ext4_group_desc *) (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 } else 238 fs->group_desc[group].bg_inode_bitmap = blk; 239} 240 241/* 242 * Return the inode table block of a group 243 */ 244blk64_t ext2fs_inode_table_loc(ext2_filsys fs, dgrp_t group) 245{ 246 if (fs->super->s_desc_size >= EXT2_MIN_DESC_SIZE_64BIT) { 247 struct ext4_group_desc *gdp; 248 gdp = (struct ext4_group_desc *) (fs->group_desc) + group; 249 250 return gdp->bg_inode_table | 251 (fs->super->s_feature_incompat 252 & EXT4_FEATURE_INCOMPAT_64BIT ? 253 (__u64) gdp->bg_inode_table_hi << 32 : 0); 254 } 255 256 return fs->group_desc[group].bg_inode_table; 257} 258 259/* 260 * Set the inode table block of a group 261 */ 262void ext2fs_inode_table_loc_set(ext2_filsys fs, dgrp_t group, blk64_t blk) 263{ 264 if (fs->super->s_desc_size >= EXT2_MIN_DESC_SIZE_64BIT) { 265 struct ext4_group_desc *gdp; 266 gdp = (struct ext4_group_desc *) (fs->group_desc) + group; 267 gdp->bg_inode_table = blk; 268 if (fs->super->s_feature_incompat & EXT4_FEATURE_INCOMPAT_64BIT) 269 gdp->bg_inode_table_hi = (__u64) blk >> 32; 270 } else 271 fs->group_desc[group].bg_inode_table = blk; 272} 273 274/* 275 * Return the free blocks count of a group 276 */ 277__u32 ext2fs_bg_free_blocks_count(ext2_filsys fs, dgrp_t group) 278{ 279 if (fs->super->s_desc_size >= EXT2_MIN_DESC_SIZE_64BIT) { 280 struct ext4_group_desc *gdp; 281 gdp = (struct ext4_group_desc *) (fs->group_desc) + group; 282 283 return gdp->bg_free_blocks_count | 284 (fs->super->s_feature_incompat 285 & EXT4_FEATURE_INCOMPAT_64BIT ? 286 (__u32) gdp->bg_free_blocks_count_hi << 16 : 0); 287 } 288 289 return fs->group_desc[group].bg_free_blocks_count; 290} 291 292/* 293 * Set the free blocks count of a group 294 */ 295void ext2fs_bg_free_blocks_count_set(ext2_filsys fs, dgrp_t group, __u32 n) 296{ 297 if (fs->super->s_desc_size >= EXT2_MIN_DESC_SIZE_64BIT) { 298 struct ext4_group_desc *gdp; 299 gdp = (struct ext4_group_desc *) (fs->group_desc) + group; 300 gdp->bg_free_blocks_count = n; 301 if (fs->super->s_feature_incompat & EXT4_FEATURE_INCOMPAT_64BIT) 302 gdp->bg_free_blocks_count_hi = (__u32) n >> 16; 303 } else 304 fs->group_desc[group].bg_free_blocks_count = n; 305} 306 307/* 308 * Return the free inodes count of a group 309 */ 310__u32 ext2fs_bg_free_inodes_count(ext2_filsys fs, dgrp_t group) 311{ 312 if (fs->super->s_desc_size >= EXT2_MIN_DESC_SIZE_64BIT) { 313 struct ext4_group_desc *gdp; 314 gdp = (struct ext4_group_desc *) (fs->group_desc) + group; 315 316 return gdp->bg_free_inodes_count | 317 (fs->super->s_feature_incompat 318 & EXT4_FEATURE_INCOMPAT_64BIT ? 319 (__u32) gdp->bg_free_inodes_count_hi << 16 : 0); 320 } 321 322 return fs->group_desc[group].bg_free_inodes_count; 323} 324 325/* 326 * Set the free inodes count of a group 327 */ 328void ext2fs_bg_free_inodes_count_set(ext2_filsys fs, dgrp_t group, __u32 n) 329{ 330 if (fs->super->s_desc_size >= EXT2_MIN_DESC_SIZE_64BIT) { 331 struct ext4_group_desc *gdp; 332 gdp = (struct ext4_group_desc *) (fs->group_desc) + group; 333 gdp->bg_free_inodes_count = n; 334 if (fs->super->s_feature_incompat & EXT4_FEATURE_INCOMPAT_64BIT) 335 gdp->bg_free_inodes_count_hi = (__u32) n >> 16; 336 } else 337 fs->group_desc[group].bg_free_inodes_count = n; 338} 339 340/* 341 * Return the used dirs count of a group 342 */ 343__u32 ext2fs_bg_used_dirs_count(ext2_filsys fs, dgrp_t group) 344{ 345 if (fs->super->s_desc_size >= EXT2_MIN_DESC_SIZE_64BIT) { 346 struct ext4_group_desc *gdp; 347 gdp = (struct ext4_group_desc *) (fs->group_desc) + group; 348 349 return gdp->bg_used_dirs_count | 350 (fs->super->s_feature_incompat 351 & EXT4_FEATURE_INCOMPAT_64BIT ? 352 (__u32) gdp->bg_used_dirs_count_hi << 16 : 0); 353 } 354 355 return fs->group_desc[group].bg_used_dirs_count; 356} 357 358/* 359 * Set the used dirs count of a group 360 */ 361void ext2fs_bg_used_dirs_count_set(ext2_filsys fs, dgrp_t group, __u32 n) 362{ 363 if (fs->super->s_desc_size >= EXT2_MIN_DESC_SIZE_64BIT) { 364 struct ext4_group_desc *gdp; 365 gdp = (struct ext4_group_desc *) (fs->group_desc) + group; 366 gdp->bg_used_dirs_count = n; 367 if (fs->super->s_feature_incompat & EXT4_FEATURE_INCOMPAT_64BIT) 368 gdp->bg_used_dirs_count_hi = (__u32) n >> 16; 369 } else 370 fs->group_desc[group].bg_used_dirs_count = n; 371} 372 373/* 374 * Return the unused inodes count of a group 375 */ 376__u32 ext2fs_bg_itable_unused(ext2_filsys fs, dgrp_t group) 377{ 378 if (fs->super->s_desc_size >= EXT2_MIN_DESC_SIZE_64BIT) { 379 struct ext4_group_desc *gdp; 380 gdp = (struct ext4_group_desc *) (fs->group_desc) + group; 381 382 return gdp->bg_itable_unused | 383 (fs->super->s_feature_incompat 384 & EXT4_FEATURE_INCOMPAT_64BIT ? 385 (__u32) gdp->bg_itable_unused_hi << 16 : 0); 386 } 387 388 return fs->group_desc[group].bg_itable_unused; 389} 390 391/* 392 * Set the unused inodes count of a group 393 */ 394void ext2fs_bg_itable_unused_set(ext2_filsys fs, dgrp_t group, __u32 n) 395{ 396 if (fs->super->s_desc_size >= EXT2_MIN_DESC_SIZE_64BIT) { 397 struct ext4_group_desc *gdp; 398 gdp = (struct ext4_group_desc *) (fs->group_desc) + group; 399 gdp->bg_itable_unused = n; 400 if (fs->super->s_feature_incompat & EXT4_FEATURE_INCOMPAT_64BIT) 401 gdp->bg_itable_unused_hi = (__u32) n >> 16; 402 } else 403 fs->group_desc[group].bg_itable_unused = n; 404} 405 406/* 407 * Get the flags for this block group 408 */ 409__u16 ext2fs_bg_flags(ext2_filsys fs, dgrp_t group) 410{ 411 if (fs->super->s_desc_size >= EXT2_MIN_DESC_SIZE_64BIT) { 412 struct ext4_group_desc *gdp; 413 gdp = (struct ext4_group_desc *) (fs->group_desc) + group; 414 415 return gdp->bg_flags; 416 } 417 418 return fs->group_desc[group].bg_flags; 419} 420 421/* 422 * Set the flags for this block group 423 */ 424void ext2fs_bg_flags_set(ext2_filsys fs, dgrp_t group, __u16 bg_flags) 425{ 426 if (fs->super->s_desc_size >= EXT2_MIN_DESC_SIZE_64BIT) { 427 struct ext4_group_desc *gdp; 428 gdp = (struct ext4_group_desc *) (fs->group_desc) + group; 429 430 gdp->bg_flags = bg_flags; 431 return; 432 } 433 434 fs->group_desc[group].bg_flags = bg_flags; 435} 436 437/* 438 * Clear the flags for this block group 439 */ 440void ext2fs_bg_flags_clear(ext2_filsys fs, dgrp_t group, __u16 bg_flags) 441{ 442 if (fs->super->s_desc_size >= EXT2_MIN_DESC_SIZE_64BIT) { 443 struct ext4_group_desc *gdp; 444 gdp = (struct ext4_group_desc *) (fs->group_desc) + group; 445 446 gdp->bg_flags = 0; 447 return; 448 } 449 450 fs->group_desc[group].bg_flags = 0; 451} 452 453/* 454 * Get the value of a particular flag for this block group 455 */ 456int ext2fs_bg_flag_test(ext2_filsys fs, dgrp_t group, __u16 bg_flag) 457{ 458 if (fs->super->s_desc_size >= EXT2_MIN_DESC_SIZE_64BIT) { 459 struct ext4_group_desc *gdp; 460 gdp = (struct ext4_group_desc *) (fs->group_desc) + group; 461 462 return gdp->bg_flags & bg_flag; 463 } 464 465 return fs->group_desc[group].bg_flags & bg_flag; 466} 467 468/* 469 * Set a particular flag for this block group 470 */ 471void ext2fs_bg_flag_set(ext2_filsys fs, dgrp_t group, __u16 bg_flag) 472{ 473 if (fs->super->s_desc_size >= EXT2_MIN_DESC_SIZE_64BIT) { 474 struct ext4_group_desc *gdp; 475 gdp = (struct ext4_group_desc *) (fs->group_desc) + group; 476 477 gdp->bg_flags |= bg_flag; 478 return; 479 } 480 481 fs->group_desc[group].bg_flags |= bg_flag; 482} 483 484/* 485 * Clear a particular flag for this block group 486 */ 487void ext2fs_bg_flag_clear(ext2_filsys fs, dgrp_t group, __u16 bg_flag) 488{ 489 if (fs->super->s_desc_size >= EXT2_MIN_DESC_SIZE_64BIT) { 490 struct ext4_group_desc *gdp; 491 gdp = (struct ext4_group_desc *) (fs->group_desc) + group; 492 493 gdp->bg_flags &= ~bg_flag; 494 return; 495 } 496 497 fs->group_desc[group].bg_flags &= ~bg_flag; 498} 499 500/* 501 * Get the checksum for this block group 502 */ 503__u16 ext2fs_bg_checksum(ext2_filsys fs, dgrp_t group) 504{ 505 if (fs->super->s_desc_size >= EXT2_MIN_DESC_SIZE_64BIT) { 506 struct ext4_group_desc *gdp; 507 gdp = (struct ext4_group_desc *) (fs->group_desc) + group; 508 509 return gdp->bg_checksum; 510 } 511 512 return fs->group_desc[group].bg_checksum; 513} 514 515/* 516 * Set the checksum for this block group to a previously calculated value 517 */ 518void ext2fs_bg_checksum_set(ext2_filsys fs, dgrp_t group, __u16 checksum) 519{ 520 if (fs->super->s_desc_size >= EXT2_MIN_DESC_SIZE_64BIT) { 521 struct ext4_group_desc *gdp; 522 gdp = (struct ext4_group_desc *) (fs->group_desc) + group; 523 524 gdp->bg_checksum = checksum; 525 return; 526 } 527 528 fs->group_desc[group].bg_checksum = checksum; 529} 530 531/* 532 * Get the acl block of a file 533 * 534 * XXX Ignoring 64-bit file system flag - most places where this is 535 * called don't have access to the fs struct, and the high bits should 536 * be 0 in the non-64-bit case anyway. 537 */ 538blk64_t ext2fs_file_acl_block(const struct ext2_inode *inode) 539{ 540 return (inode->i_file_acl | 541 (__u64) inode->osd2.linux2.l_i_file_acl_high << 32); 542} 543 544/* 545 * Set the acl block of a file 546 */ 547void ext2fs_file_acl_block_set(struct ext2_inode *inode, blk64_t blk) 548{ 549 inode->i_file_acl = blk; 550 inode->osd2.linux2.l_i_file_acl_high = (__u64) blk >> 32; 551} 552 553