Whamcloud - gitweb
libext2fs: Fix counting routines in blknum.c to take/return __u32 counts
[tools/e2fsprogs.git] / lib / ext2fs / blknum.c
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  */
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 inode data block count
47  */
48 blk64_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  */
60 blk64_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  */
71 blk64_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  */
81 void 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  */
91 void 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  */
101 blk64_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  */
111 void 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  */
121 void 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  */
131 blk64_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  */
141 void 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  */
151 void 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  */
164 struct 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  */
178 blk64_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  */
196 void 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  */
211 blk64_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  */
229 void 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  */
244 blk64_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  */
262 void 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  */
295 void 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  */
328 void 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  */
361 void 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  */
394 void 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  */
424 void 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  */
440 void 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  */
456 int 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  */
471 void 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  */
487 void 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  */
518 void 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  */
538 blk64_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  */
547 void 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