2 * blknum.c --- Functions to handle blk64_t and high/low 64-bit block
5 * Copyright IBM Corporation, 2007
6 * Author Jose R. Santos <jrs@us.ibm.com>
9 * This file may be redistributed under the terms of the GNU Public
18 * Return the group # of a block
20 dgrp_t ext2fs_group_of_blk2(ext2_filsys fs, blk64_t blk)
22 return (blk - fs->super->s_first_data_block) /
23 fs->super->s_blocks_per_group;
27 * Return the first block (inclusive) in a group
29 blk64_t ext2fs_group_first_block2(ext2_filsys fs, dgrp_t group)
31 return fs->super->s_first_data_block +
32 EXT2_GROUPS_TO_BLOCKS(fs->super, group);
36 * Return the last block (inclusive) in a group
38 blk64_t ext2fs_group_last_block2(ext2_filsys fs, dgrp_t group)
40 return (group == fs->group_desc_count - 1 ?
41 ext2fs_blocks_count(fs->super) - 1 :
42 ext2fs_group_first_block2(fs, group) +
43 (fs->super->s_blocks_per_group - 1));
47 * Return the number of blocks in a group
49 int ext2fs_group_blocks_count(ext2_filsys fs, dgrp_t group)
53 if (group == fs->group_desc_count - 1) {
54 num_blocks = (ext2fs_blocks_count(fs->super) -
55 fs->super->s_first_data_block) %
56 fs->super->s_blocks_per_group;
58 num_blocks = fs->super->s_blocks_per_group;
60 num_blocks = fs->super->s_blocks_per_group;
66 * Return the inode data block count
68 blk64_t ext2fs_inode_data_blocks2(ext2_filsys fs,
69 struct ext2_inode *inode)
71 return (inode->i_blocks |
72 (ext2fs_has_feature_huge_file(fs->super) ?
73 (__u64) inode->osd2.linux2.l_i_blocks_hi << 32 : 0)) -
74 (inode->i_file_acl ? EXT2_CLUSTER_SIZE(fs->super) >> 9 : 0);
78 * Return the inode i_blocks count
80 blk64_t ext2fs_inode_i_blocks(ext2_filsys fs,
81 struct ext2_inode *inode)
83 return (inode->i_blocks |
84 (ext2fs_has_feature_huge_file(fs->super) ?
85 (__u64)inode->osd2.linux2.l_i_blocks_hi << 32 : 0));
89 * Return the inode i_blocks in stat (512 byte) units
91 blk64_t ext2fs_get_stat_i_blocks(ext2_filsys fs,
92 struct ext2_inode *inode)
94 blk64_t ret = inode->i_blocks;
96 if (ext2fs_has_feature_huge_file(fs->super)) {
97 ret += ((long long) inode->osd2.linux2.l_i_blocks_hi) << 32;
98 if (inode->i_flags & EXT4_HUGE_FILE_FL)
99 ret *= (fs->blocksize / 512);
105 * Return the fs block count
107 blk64_t ext2fs_blocks_count(struct ext2_super_block *super)
109 return super->s_blocks_count |
110 (ext2fs_has_feature_64bit(super) ?
111 (__u64) super->s_blocks_count_hi << 32 : 0);
115 * Set the fs block count
117 void ext2fs_blocks_count_set(struct ext2_super_block *super, blk64_t blk)
119 super->s_blocks_count = blk;
120 if (ext2fs_has_feature_64bit(super))
121 super->s_blocks_count_hi = (__u64) blk >> 32;
125 * Add to the current fs block count
127 void ext2fs_blocks_count_add(struct ext2_super_block *super, blk64_t blk)
130 tmp = ext2fs_blocks_count(super) + blk;
131 ext2fs_blocks_count_set(super, tmp);
135 * Return the fs reserved block count
137 blk64_t ext2fs_r_blocks_count(struct ext2_super_block *super)
139 return super->s_r_blocks_count |
140 (ext2fs_has_feature_64bit(super) ?
141 (__u64) super->s_r_blocks_count_hi << 32 : 0);
145 * Set the fs reserved block count
147 void ext2fs_r_blocks_count_set(struct ext2_super_block *super, blk64_t blk)
149 super->s_r_blocks_count = blk;
150 if (ext2fs_has_feature_64bit(super))
151 super->s_r_blocks_count_hi = (__u64) blk >> 32;
155 * Add to the current reserved fs block count
157 void ext2fs_r_blocks_count_add(struct ext2_super_block *super, blk64_t blk)
160 tmp = ext2fs_r_blocks_count(super) + blk;
161 ext2fs_r_blocks_count_set(super, tmp);
165 * Return the fs free block count
167 blk64_t ext2fs_free_blocks_count(struct ext2_super_block *super)
169 return super->s_free_blocks_count |
170 (ext2fs_has_feature_64bit(super) ?
171 (__u64) super->s_free_blocks_hi << 32 : 0);
175 * Set the fs free block count
177 void ext2fs_free_blocks_count_set(struct ext2_super_block *super, blk64_t blk)
179 super->s_free_blocks_count = blk;
180 if (ext2fs_has_feature_64bit(super))
181 super->s_free_blocks_hi = (__u64) blk >> 32;
185 * Add to the current free fs block count
187 void ext2fs_free_blocks_count_add(struct ext2_super_block *super, blk64_t blk)
190 tmp = ext2fs_free_blocks_count(super) + blk;
191 ext2fs_free_blocks_count_set(super, tmp);
195 * Get a pointer to a block group descriptor. We need the explicit
196 * pointer to the group desc for code that swaps block group
197 * descriptors before writing them out, as it wants to make a copy and
200 struct ext2_group_desc *ext2fs_group_desc(ext2_filsys fs,
201 struct opaque_ext2_group_desc *gdp,
204 struct ext2_group_desc *ret_gdp;
206 static char *buf = 0;
207 static unsigned bufsize = 0;
209 int desc_size = EXT2_DESC_SIZE(fs->super) & ~7;
210 int desc_per_blk = EXT2_DESC_PER_BLOCK(fs->super);
212 if (group > fs->group_desc_count)
215 return (struct ext2_group_desc *)((char *)gdp +
218 * If fs->group_desc wasn't read in when the file system was
219 * opened, then read it on demand here.
221 if (bufsize < fs->blocksize)
222 ext2fs_free_mem(&buf);
224 retval = ext2fs_get_mem(fs->blocksize, &buf);
227 bufsize = fs->blocksize;
229 blk = ext2fs_descriptor_block_loc2(fs, fs->super->s_first_data_block,
230 group / desc_per_blk);
231 retval = io_channel_read_blk(fs->io, blk, 1, buf);
234 ret_gdp = (struct ext2_group_desc *)
235 (buf + ((group % desc_per_blk) * desc_size));
236 #ifdef WORDS_BIGENDIAN
237 ext2fs_swap_group_desc2(fs, ret_gdp);
242 /* Do the same but as an ext4 group desc for internal use here */
243 static struct ext4_group_desc *ext4fs_group_desc(ext2_filsys fs,
244 struct opaque_ext2_group_desc *gdp,
247 return (struct ext4_group_desc *)ext2fs_group_desc(fs, gdp, group);
251 * Return the block bitmap checksum of a group
253 __u32 ext2fs_block_bitmap_checksum(ext2_filsys fs, dgrp_t group)
255 struct ext4_group_desc *gdp;
258 gdp = ext4fs_group_desc(fs, fs->group_desc, group);
259 csum = gdp->bg_block_bitmap_csum_lo;
260 if (EXT2_DESC_SIZE(fs->super) >= EXT4_BG_BLOCK_BITMAP_CSUM_HI_LOCATION)
261 csum |= ((__u32)gdp->bg_block_bitmap_csum_hi << 16);
266 * Return the block bitmap block of a group
268 blk64_t ext2fs_block_bitmap_loc(ext2_filsys fs, dgrp_t group)
270 struct ext4_group_desc *gdp;
272 gdp = ext4fs_group_desc(fs, fs->group_desc, group);
273 return gdp->bg_block_bitmap |
274 (ext2fs_has_feature_64bit(fs->super) ?
275 (__u64)gdp->bg_block_bitmap_hi << 32 : 0);
279 * Set the block bitmap block of a group
281 void ext2fs_block_bitmap_loc_set(ext2_filsys fs, dgrp_t group, blk64_t blk)
283 struct ext4_group_desc *gdp;
285 gdp = ext4fs_group_desc(fs, fs->group_desc, group);
286 gdp->bg_block_bitmap = blk;
287 if (ext2fs_has_feature_64bit(fs->super))
288 gdp->bg_block_bitmap_hi = (__u64) blk >> 32;
292 * Return the inode bitmap checksum of a group
294 __u32 ext2fs_inode_bitmap_checksum(ext2_filsys fs, dgrp_t group)
296 struct ext4_group_desc *gdp;
299 gdp = ext4fs_group_desc(fs, fs->group_desc, group);
300 csum = gdp->bg_inode_bitmap_csum_lo;
301 if (EXT2_DESC_SIZE(fs->super) >= EXT4_BG_INODE_BITMAP_CSUM_HI_END)
302 csum |= ((__u32)gdp->bg_inode_bitmap_csum_hi << 16);
307 * Return the inode bitmap block of a group
309 blk64_t ext2fs_inode_bitmap_loc(ext2_filsys fs, dgrp_t group)
311 struct ext4_group_desc *gdp;
313 gdp = ext4fs_group_desc(fs, fs->group_desc, group);
314 return gdp->bg_inode_bitmap |
315 (ext2fs_has_feature_64bit(fs->super) ?
316 (__u64) gdp->bg_inode_bitmap_hi << 32 : 0);
320 * Set the inode bitmap block of a group
322 void ext2fs_inode_bitmap_loc_set(ext2_filsys fs, dgrp_t group, blk64_t blk)
324 struct ext4_group_desc *gdp;
326 gdp = ext4fs_group_desc(fs, fs->group_desc, group);
327 gdp->bg_inode_bitmap = blk;
328 if (ext2fs_has_feature_64bit(fs->super))
329 gdp->bg_inode_bitmap_hi = (__u64) blk >> 32;
333 * Return the inode table block of a group
335 blk64_t ext2fs_inode_table_loc(ext2_filsys fs, dgrp_t group)
337 struct ext4_group_desc *gdp;
339 gdp = ext4fs_group_desc(fs, fs->group_desc, group);
340 return gdp->bg_inode_table |
341 (ext2fs_has_feature_64bit(fs->super) ?
342 (__u64) gdp->bg_inode_table_hi << 32 : 0);
346 * Set the inode table block of a group
348 void ext2fs_inode_table_loc_set(ext2_filsys fs, dgrp_t group, blk64_t blk)
350 struct ext4_group_desc *gdp;
352 gdp = ext4fs_group_desc(fs, fs->group_desc, group);
353 gdp->bg_inode_table = blk;
354 if (ext2fs_has_feature_64bit(fs->super))
355 gdp->bg_inode_table_hi = (__u64) blk >> 32;
359 * Return the free blocks count of a group
361 __u32 ext2fs_bg_free_blocks_count(ext2_filsys fs, dgrp_t group)
363 struct ext4_group_desc *gdp;
365 gdp = ext4fs_group_desc(fs, fs->group_desc, group);
366 return gdp->bg_free_blocks_count |
367 (ext2fs_has_feature_64bit(fs->super) ?
368 (__u32) gdp->bg_free_blocks_count_hi << 16 : 0);
372 * Set the free blocks count of a group
374 void ext2fs_bg_free_blocks_count_set(ext2_filsys fs, dgrp_t group, __u32 n)
376 struct ext4_group_desc *gdp;
378 gdp = ext4fs_group_desc(fs, fs->group_desc, group);
379 gdp->bg_free_blocks_count = n;
381 if (ext2fs_has_feature_64bit(fs->super))
382 gdp->bg_free_blocks_count_hi = (__u32) n >> 16;
386 * Return the free inodes count of a group
388 __u32 ext2fs_bg_free_inodes_count(ext2_filsys fs, dgrp_t group)
390 struct ext4_group_desc *gdp;
392 gdp = ext4fs_group_desc(fs, fs->group_desc, group);
393 return gdp->bg_free_inodes_count |
394 (ext2fs_has_feature_64bit(fs->super) ?
395 (__u32) gdp->bg_free_inodes_count_hi << 16 : 0);
399 * Set the free inodes count of a group
401 void ext2fs_bg_free_inodes_count_set(ext2_filsys fs, dgrp_t group, __u32 n)
403 struct ext4_group_desc *gdp;
405 gdp = ext4fs_group_desc(fs, fs->group_desc, group);
406 gdp->bg_free_inodes_count = n;
407 if (ext2fs_has_feature_64bit(fs->super))
408 gdp->bg_free_inodes_count_hi = (__u32) n >> 16;
412 * Return the used dirs count of a group
414 __u32 ext2fs_bg_used_dirs_count(ext2_filsys fs, dgrp_t group)
416 struct ext4_group_desc *gdp;
418 gdp = ext4fs_group_desc(fs, fs->group_desc, group);
419 return gdp->bg_used_dirs_count |
420 (ext2fs_has_feature_64bit(fs->super) ?
421 (__u32) gdp->bg_used_dirs_count_hi << 16 : 0);
425 * Set the used dirs count of a group
427 void ext2fs_bg_used_dirs_count_set(ext2_filsys fs, dgrp_t group, __u32 n)
429 struct ext4_group_desc *gdp;
431 gdp = ext4fs_group_desc(fs, fs->group_desc, group);
432 gdp->bg_used_dirs_count = n;
433 if (ext2fs_has_feature_64bit(fs->super))
434 gdp->bg_used_dirs_count_hi = (__u32) n >> 16;
438 * Return the unused inodes count of a group
440 __u32 ext2fs_bg_itable_unused(ext2_filsys fs, dgrp_t group)
442 struct ext4_group_desc *gdp;
444 gdp = ext4fs_group_desc(fs, fs->group_desc, group);
445 return gdp->bg_itable_unused |
446 (ext2fs_has_feature_64bit(fs->super) ?
447 (__u32) gdp->bg_itable_unused_hi << 16 : 0);
451 * Set the unused inodes count of a group
453 void ext2fs_bg_itable_unused_set(ext2_filsys fs, dgrp_t group, __u32 n)
455 struct ext4_group_desc *gdp;
457 gdp = ext4fs_group_desc(fs, fs->group_desc, group);
458 gdp->bg_itable_unused = n;
459 if (ext2fs_has_feature_64bit(fs->super))
460 gdp->bg_itable_unused_hi = (__u32) n >> 16;
464 * Get the flags for this block group
466 __u16 ext2fs_bg_flags(ext2_filsys fs, dgrp_t group)
468 struct ext4_group_desc *gdp;
470 gdp = ext4fs_group_desc(fs, fs->group_desc, group);
471 return gdp->bg_flags;
475 * Zero out the flags for this block group
477 void ext2fs_bg_flags_zap(ext2_filsys fs, dgrp_t group)
479 struct ext4_group_desc *gdp;
481 gdp = ext4fs_group_desc(fs, fs->group_desc, group);
487 * Get the value of a particular flag for this block group
489 int ext2fs_bg_flags_test(ext2_filsys fs, dgrp_t group, __u16 bg_flag)
491 struct ext4_group_desc *gdp;
493 gdp = ext4fs_group_desc(fs, fs->group_desc, group);
494 return gdp->bg_flags & bg_flag;
498 * Set a flag or set of flags for this block group
500 void ext2fs_bg_flags_set(ext2_filsys fs, dgrp_t group, __u16 bg_flags)
502 struct ext4_group_desc *gdp;
504 gdp = ext4fs_group_desc(fs, fs->group_desc, group);
505 gdp->bg_flags |= bg_flags;
510 * Clear a flag or set of flags for this block group
512 void ext2fs_bg_flags_clear(ext2_filsys fs, dgrp_t group, __u16 bg_flags)
514 struct ext4_group_desc *gdp;
516 gdp = ext4fs_group_desc(fs, fs->group_desc, group);
517 gdp->bg_flags &= ~bg_flags;
522 * Get the checksum for this block group
524 __u16 ext2fs_bg_checksum(ext2_filsys fs, dgrp_t group)
526 struct ext4_group_desc *gdp;
528 gdp = ext4fs_group_desc(fs, fs->group_desc, group);
529 return gdp->bg_checksum;
533 * Set the checksum for this block group to a previously calculated value
535 void ext2fs_bg_checksum_set(ext2_filsys fs, dgrp_t group, __u16 checksum)
537 struct ext4_group_desc *gdp;
539 gdp = ext4fs_group_desc(fs, fs->group_desc, group);
540 gdp->bg_checksum = checksum;
545 * Get the acl block of a file
547 blk64_t ext2fs_file_acl_block(ext2_filsys fs, const struct ext2_inode *inode)
549 blk64_t blk = inode->i_file_acl;
551 if (fs && ext2fs_has_feature_64bit(fs->super))
552 blk |= ((__u64) inode->osd2.linux2.l_i_file_acl_high) << 32;
557 * Set the acl block of a file
559 void ext2fs_file_acl_block_set(ext2_filsys fs, struct ext2_inode *inode,
562 inode->i_file_acl = blk;
563 if (fs && ext2fs_has_feature_64bit(fs->super))
564 inode->osd2.linux2.l_i_file_acl_high = (__u64) blk >> 32;
568 * Set the size of the inode
570 errcode_t ext2fs_inode_size_set(ext2_filsys fs, struct ext2_inode *inode,
576 /* If writing a large inode, set the large_file or large_dir flag */
577 if (ext2fs_needs_large_file_feature(size)) {
580 if (LINUX_S_ISREG(inode->i_mode)) {
581 if (!ext2fs_has_feature_large_file(fs->super)) {
582 ext2fs_set_feature_large_file(fs->super);
585 } else if (LINUX_S_ISDIR(inode->i_mode)) {
586 if (!ext2fs_has_feature_largedir(fs->super)) {
587 ext2fs_set_feature_largedir(fs->super);
591 /* Only regular files get to be larger than 4GB */
592 return EXT2_ET_FILE_TOO_BIG;
595 if (fs->super->s_rev_level == EXT2_GOOD_OLD_REV)
596 ext2fs_update_dynamic_rev(fs);
597 ext2fs_mark_super_dirty(fs);
601 inode->i_size = size & 0xffffffff;
602 inode->i_size_high = (size >> 32);