blknum.c revision cd65a24e756b8f6770a5961fd94c67eb00dd7baa
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 & 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_incompat & 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 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/* 178 * Return the block bitmap block of a group 179 */ 180blk64_t ext2fs_block_bitmap_loc(ext2_filsys fs, dgrp_t group) 181{ 182 if (fs->super->s_desc_size >= EXT2_MIN_DESC_SIZE_64BIT) { 183 struct ext4_group_desc *gdp; 184 gdp = (struct ext4_group_desc *) (fs->group_desc) + group; 185 186 return gdp->bg_block_bitmap | 187 (fs->super->s_feature_incompat 188 & EXT4_FEATURE_INCOMPAT_64BIT ? 189 (__u64) gdp->bg_block_bitmap_hi << 32 : 0); 190 } 191 192 return fs->group_desc[group].bg_block_bitmap; 193} 194 195/* 196 * Set the block bitmap block of a group 197 */ 198void ext2fs_block_bitmap_loc_set(ext2_filsys fs, dgrp_t group, blk64_t blk) 199{ 200 if (fs->super->s_desc_size >= EXT2_MIN_DESC_SIZE_64BIT) { 201 struct ext4_group_desc *gdp; 202 gdp = (struct ext4_group_desc *) (fs->group_desc) + group; 203 gdp->bg_block_bitmap = blk; 204 if (fs->super->s_feature_incompat & EXT4_FEATURE_INCOMPAT_64BIT) 205 gdp->bg_block_bitmap_hi = (__u64) blk >> 32; 206 } else 207 fs->group_desc[group].bg_block_bitmap = blk; 208} 209 210/* 211 * Return the inode bitmap block of a group 212 */ 213blk64_t ext2fs_inode_bitmap_loc(ext2_filsys fs, dgrp_t group) 214{ 215 if (fs->super->s_desc_size >= EXT2_MIN_DESC_SIZE_64BIT) { 216 struct ext4_group_desc *gdp; 217 gdp = (struct ext4_group_desc *) (fs->group_desc) + group; 218 219 return gdp->bg_inode_bitmap | 220 (fs->super->s_feature_incompat 221 & EXT4_FEATURE_INCOMPAT_64BIT ? 222 (__u64) gdp->bg_inode_bitmap_hi << 32 : 0); 223 } 224 225 return fs->group_desc[group].bg_inode_bitmap; 226} 227 228/* 229 * Set the inode bitmap block of a group 230 */ 231void ext2fs_inode_bitmap_loc_set(ext2_filsys fs, dgrp_t group, blk64_t blk) 232{ 233 if (fs->super->s_desc_size >= EXT2_MIN_DESC_SIZE_64BIT) { 234 struct ext4_group_desc *gdp; 235 gdp = (struct ext4_group_desc *) (fs->group_desc) + group; 236 gdp->bg_inode_bitmap = blk; 237 if (fs->super->s_feature_incompat & EXT4_FEATURE_INCOMPAT_64BIT) 238 gdp->bg_inode_bitmap_hi = (__u64) blk >> 32; 239 } else 240 fs->group_desc[group].bg_inode_bitmap = blk; 241} 242 243/* 244 * Return the inode table block of a group 245 */ 246blk64_t ext2fs_inode_table_loc(ext2_filsys fs, dgrp_t group) 247{ 248 if (fs->super->s_desc_size >= EXT2_MIN_DESC_SIZE_64BIT) { 249 struct ext4_group_desc *gdp; 250 gdp = (struct ext4_group_desc *) (fs->group_desc) + group; 251 252 return gdp->bg_inode_table | 253 (fs->super->s_feature_incompat 254 & EXT4_FEATURE_INCOMPAT_64BIT ? 255 (__u64) gdp->bg_inode_table_hi << 32 : 0); 256 } 257 258 return fs->group_desc[group].bg_inode_table; 259} 260 261/* 262 * Set the inode table block of a group 263 */ 264void ext2fs_inode_table_loc_set(ext2_filsys fs, dgrp_t group, blk64_t blk) 265{ 266 if (fs->super->s_desc_size >= EXT2_MIN_DESC_SIZE_64BIT) { 267 struct ext4_group_desc *gdp; 268 gdp = (struct ext4_group_desc *) (fs->group_desc) + group; 269 gdp->bg_inode_table = blk; 270 if (fs->super->s_feature_incompat & EXT4_FEATURE_INCOMPAT_64BIT) 271 gdp->bg_inode_table_hi = (__u64) blk >> 32; 272 } else 273 fs->group_desc[group].bg_inode_table = blk; 274} 275 276/* 277 * Return the free blocks count of a group 278 */ 279__u32 ext2fs_bg_free_blocks_count(ext2_filsys fs, dgrp_t group) 280{ 281 if (fs->super->s_desc_size >= EXT2_MIN_DESC_SIZE_64BIT) { 282 struct ext4_group_desc *gdp; 283 gdp = (struct ext4_group_desc *) (fs->group_desc) + group; 284 285 return gdp->bg_free_blocks_count | 286 (fs->super->s_feature_incompat 287 & EXT4_FEATURE_INCOMPAT_64BIT ? 288 (__u32) gdp->bg_free_blocks_count_hi << 16 : 0); 289 } 290 291 return fs->group_desc[group].bg_free_blocks_count; 292} 293 294/* 295 * Set the free blocks count of a group 296 */ 297void ext2fs_bg_free_blocks_count_set(ext2_filsys fs, dgrp_t group, __u32 n) 298{ 299 if (fs->super->s_desc_size >= EXT2_MIN_DESC_SIZE_64BIT) { 300 struct ext4_group_desc *gdp; 301 gdp = (struct ext4_group_desc *) (fs->group_desc) + group; 302 gdp->bg_free_blocks_count = n; 303 if (fs->super->s_feature_incompat & EXT4_FEATURE_INCOMPAT_64BIT) 304 gdp->bg_free_blocks_count_hi = (__u32) n >> 16; 305 } else 306 fs->group_desc[group].bg_free_blocks_count = n; 307} 308 309/* 310 * Return the free inodes count of a group 311 */ 312__u32 ext2fs_bg_free_inodes_count(ext2_filsys fs, dgrp_t group) 313{ 314 if (fs->super->s_desc_size >= EXT2_MIN_DESC_SIZE_64BIT) { 315 struct ext4_group_desc *gdp; 316 gdp = (struct ext4_group_desc *) (fs->group_desc) + group; 317 318 return gdp->bg_free_inodes_count | 319 (fs->super->s_feature_incompat 320 & EXT4_FEATURE_INCOMPAT_64BIT ? 321 (__u32) gdp->bg_free_inodes_count_hi << 16 : 0); 322 } 323 324 return fs->group_desc[group].bg_free_inodes_count; 325} 326 327/* 328 * Set the free inodes count of a group 329 */ 330void ext2fs_bg_free_inodes_count_set(ext2_filsys fs, dgrp_t group, __u32 n) 331{ 332 if (fs->super->s_desc_size >= EXT2_MIN_DESC_SIZE_64BIT) { 333 struct ext4_group_desc *gdp; 334 gdp = (struct ext4_group_desc *) (fs->group_desc) + group; 335 gdp->bg_free_inodes_count = n; 336 if (fs->super->s_feature_incompat & EXT4_FEATURE_INCOMPAT_64BIT) 337 gdp->bg_free_inodes_count_hi = (__u32) n >> 16; 338 } else 339 fs->group_desc[group].bg_free_inodes_count = n; 340} 341 342/* 343 * Return the used dirs count of a group 344 */ 345__u32 ext2fs_bg_used_dirs_count(ext2_filsys fs, dgrp_t group) 346{ 347 if (fs->super->s_desc_size >= EXT2_MIN_DESC_SIZE_64BIT) { 348 struct ext4_group_desc *gdp; 349 gdp = (struct ext4_group_desc *) (fs->group_desc) + group; 350 351 return gdp->bg_used_dirs_count | 352 (fs->super->s_feature_incompat 353 & EXT4_FEATURE_INCOMPAT_64BIT ? 354 (__u32) gdp->bg_used_dirs_count_hi << 16 : 0); 355 } 356 357 return fs->group_desc[group].bg_used_dirs_count; 358} 359 360/* 361 * Set the used dirs count of a group 362 */ 363void ext2fs_bg_used_dirs_count_set(ext2_filsys fs, dgrp_t group, __u32 n) 364{ 365 if (fs->super->s_desc_size >= EXT2_MIN_DESC_SIZE_64BIT) { 366 struct ext4_group_desc *gdp; 367 gdp = (struct ext4_group_desc *) (fs->group_desc) + group; 368 gdp->bg_used_dirs_count = n; 369 if (fs->super->s_feature_incompat & EXT4_FEATURE_INCOMPAT_64BIT) 370 gdp->bg_used_dirs_count_hi = (__u32) n >> 16; 371 } else 372 fs->group_desc[group].bg_used_dirs_count = n; 373} 374 375/* 376 * Return the unused inodes count of a group 377 */ 378__u32 ext2fs_bg_itable_unused(ext2_filsys fs, dgrp_t group) 379{ 380 if (fs->super->s_desc_size >= EXT2_MIN_DESC_SIZE_64BIT) { 381 struct ext4_group_desc *gdp; 382 gdp = (struct ext4_group_desc *) (fs->group_desc) + group; 383 384 return gdp->bg_itable_unused | 385 (fs->super->s_feature_incompat 386 & EXT4_FEATURE_INCOMPAT_64BIT ? 387 (__u32) gdp->bg_itable_unused_hi << 16 : 0); 388 } 389 390 return fs->group_desc[group].bg_itable_unused; 391} 392 393/* 394 * Set the unused inodes count of a group 395 */ 396void ext2fs_bg_itable_unused_set(ext2_filsys fs, dgrp_t group, __u32 n) 397{ 398 if (fs->super->s_desc_size >= EXT2_MIN_DESC_SIZE_64BIT) { 399 struct ext4_group_desc *gdp; 400 gdp = (struct ext4_group_desc *) (fs->group_desc) + group; 401 gdp->bg_itable_unused = n; 402 if (fs->super->s_feature_incompat & EXT4_FEATURE_INCOMPAT_64BIT) 403 gdp->bg_itable_unused_hi = (__u32) n >> 16; 404 } else 405 fs->group_desc[group].bg_itable_unused = n; 406} 407 408/* 409 * Get the flags for this block group 410 */ 411__u16 ext2fs_bg_flags(ext2_filsys fs, dgrp_t group) 412{ 413 if (fs->super->s_desc_size >= EXT2_MIN_DESC_SIZE_64BIT) { 414 struct ext4_group_desc *gdp; 415 gdp = (struct ext4_group_desc *) (fs->group_desc) + group; 416 417 return gdp->bg_flags; 418 } 419 420 return fs->group_desc[group].bg_flags; 421} 422 423/* 424 * Zero out the flags for this block group 425 */ 426void ext2fs_bg_flags_zap(ext2_filsys fs, dgrp_t group) 427{ 428 if (fs->super->s_desc_size >= EXT2_MIN_DESC_SIZE_64BIT) { 429 struct ext4_group_desc *gdp; 430 gdp = (struct ext4_group_desc *) (fs->group_desc) + group; 431 432 gdp->bg_flags = 0; 433 return; 434 } 435 436 fs->group_desc[group].bg_flags = 0; 437} 438 439/* 440 * Get the value of a particular flag for this block group 441 */ 442int ext2fs_bg_flags_test(ext2_filsys fs, dgrp_t group, __u16 bg_flag) 443{ 444 if (fs->super->s_desc_size >= EXT2_MIN_DESC_SIZE_64BIT) { 445 struct ext4_group_desc *gdp; 446 gdp = (struct ext4_group_desc *) (fs->group_desc) + group; 447 448 return gdp->bg_flags & bg_flag; 449 } 450 451 return fs->group_desc[group].bg_flags & bg_flag; 452} 453 454/* 455 * Set a flag or set of flags for this block group 456 */ 457void ext2fs_bg_flags_set(ext2_filsys fs, dgrp_t group, __u16 bg_flags) 458{ 459 if (fs->super->s_desc_size >= EXT2_MIN_DESC_SIZE_64BIT) { 460 struct ext4_group_desc *gdp; 461 gdp = (struct ext4_group_desc *) (fs->group_desc) + group; 462 463 gdp->bg_flags |= bg_flags; 464 return; 465 } 466 467 fs->group_desc[group].bg_flags |= bg_flags; 468} 469 470/* 471 * Clear a flag or set of flags for this block group 472 */ 473void ext2fs_bg_flags_clear(ext2_filsys fs, dgrp_t group, __u16 bg_flags) 474{ 475 if (fs->super->s_desc_size >= EXT2_MIN_DESC_SIZE_64BIT) { 476 struct ext4_group_desc *gdp; 477 gdp = (struct ext4_group_desc *) (fs->group_desc) + group; 478 479 gdp->bg_flags &= ~bg_flags; 480 return; 481 } 482 483 fs->group_desc[group].bg_flags &= ~bg_flags; 484} 485 486/* 487 * Get the checksum for this block group 488 */ 489__u16 ext2fs_bg_checksum(ext2_filsys fs, dgrp_t group) 490{ 491 if (fs->super->s_desc_size >= EXT2_MIN_DESC_SIZE_64BIT) { 492 struct ext4_group_desc *gdp; 493 gdp = (struct ext4_group_desc *) (fs->group_desc) + group; 494 495 return gdp->bg_checksum; 496 } 497 498 return fs->group_desc[group].bg_checksum; 499} 500 501/* 502 * Set the checksum for this block group to a previously calculated value 503 */ 504void ext2fs_bg_checksum_set(ext2_filsys fs, dgrp_t group, __u16 checksum) 505{ 506 if (fs->super->s_desc_size >= EXT2_MIN_DESC_SIZE_64BIT) { 507 struct ext4_group_desc *gdp; 508 gdp = (struct ext4_group_desc *) (fs->group_desc) + group; 509 510 gdp->bg_checksum = checksum; 511 return; 512 } 513 514 fs->group_desc[group].bg_checksum = checksum; 515} 516 517/* 518 * Get the acl block of a file 519 * 520 * XXX Ignoring 64-bit file system flag - most places where this is 521 * called don't have access to the fs struct, and the high bits should 522 * be 0 in the non-64-bit case anyway. 523 */ 524blk64_t ext2fs_file_acl_block(const struct ext2_inode *inode) 525{ 526 return (inode->i_file_acl | 527 (__u64) inode->osd2.linux2.l_i_file_acl_high << 32); 528} 529 530/* 531 * Set the acl block of a file 532 */ 533void ext2fs_file_acl_block_set(struct ext2_inode *inode, blk64_t blk) 534{ 535 inode->i_file_acl = blk; 536 inode->osd2.linux2.l_i_file_acl_high = (__u64) blk >> 32; 537} 538 539