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