1 /* This file manages the super block structure.
3 * The entry points into this file are
4 * get_super: search the 'superblock' table for a device
5 * read_super: read a superblock
8 * February 2010 (Evgeniy Ivanov)
15 #include <minix/com.h>
16 #include <minix/u64.h>
17 #include <minix/bdev.h>
23 static off_t
ext2_max_size(int block_size
);
24 static u32_t
ext2_count_dirs(struct super_block
*sp
);
26 static void super_copy(register struct super_block
*dest
, register
27 struct super_block
*source
);
28 static void copy_group_descriptors(register struct group_desc
29 *dest_array
, register struct group_desc
*source_array
, unsigned int
32 static off_t super_block_offset
;
35 /*===========================================================================*
37 *===========================================================================*/
38 struct super_block
*get_super(
39 dev_t dev
/* device number whose super_block is sought */
43 panic("request for super_block of NO_DEV");
44 if (superblock
->s_dev
!= dev
)
45 panic("wrong superblock", (int) dev
);
51 /*===========================================================================*
53 *===========================================================================*/
54 unsigned int get_block_size(dev_t dev
)
57 panic("request for block size of NO_DEV");
58 return(lmfs_fs_block_size());
61 static struct group_desc
*ondisk_group_descs
;
63 /*===========================================================================*
65 *===========================================================================*/
67 register struct super_block
*sp
; /* pointer to a superblock */
69 /* Read a superblock. */
72 /* group descriptors, sp->s_group_desc points to this. */
73 static struct group_desc
*group_descs
;
75 block_t gd_size
; /* group descriptors table size in blocks */
78 dev
= sp
->s_dev
; /* save device (will be overwritten by copy) */
80 panic("request for super_block of NO_DEV");
82 if (opt
.block_with_super
== 0) {
83 super_block_offset
= SUPER_BLOCK_BYTES
;
85 /* The block number here uses 1k units */
86 super_block_offset
= opt
.block_with_super
* 1024;
89 STATICINIT(ondisk_superblock
, 1);
91 if (!ondisk_superblock
)
92 panic("can't allocate memory for super_block buffers");
94 assert(_MIN_BLOCK_SIZE
<= sizeof(*ondisk_superblock
));
95 r
= bdev_read(dev
, cvu64(super_block_offset
), (char*) ondisk_superblock
,
96 _MIN_BLOCK_SIZE
, BDEV_NOFLAGS
);
98 if (r
!= _MIN_BLOCK_SIZE
)
101 super_copy(sp
, ondisk_superblock
);
103 sp
->s_dev
= NO_DEV
; /* restore later */
105 if (sp
->s_magic
!= SUPER_MAGIC
)
108 sp
->s_block_size
= 1024*(1<<sp
->s_log_block_size
);
110 if (sp
->s_block_size
< _MIN_BLOCK_SIZE
111 || sp
->s_block_size
>_MAX_BLOCK_SIZE
) {
112 printf("data block size (%u) is invalid\n", sp
->s_block_size
);
116 if ((sp
->s_block_size
% 512) != 0)
119 if (SUPER_SIZE_D
> sp
->s_block_size
)
122 /* Variable added for convinience (i_blocks counts 512-byte blocks). */
123 sp
->s_sectors_in_block
= sp
->s_block_size
/ 512;
125 /* TODO: this code is for revision 1 (but bw compatible with 0)
126 * inode must be power of 2 and smaller, than block size.
128 if ((EXT2_INODE_SIZE(sp
) & (EXT2_INODE_SIZE(sp
) - 1)) != 0
129 || EXT2_INODE_SIZE(sp
) > sp
->s_block_size
) {
130 printf("superblock->s_inode_size is incorrect...\n");
134 sp
->s_blocksize_bits
= sp
->s_log_block_size
+ 10;
135 sp
->s_max_size
= ext2_max_size(sp
->s_block_size
);
136 sp
->s_inodes_per_block
= sp
->s_block_size
/ EXT2_INODE_SIZE(sp
);
137 if (sp
->s_inodes_per_block
== 0 || sp
->s_inodes_per_group
== 0) {
138 printf("either inodes_per_block or inodes_per_group count is 0\n");
142 sp
->s_itb_per_group
= sp
->s_inodes_per_group
/ sp
->s_inodes_per_block
;
143 sp
->s_desc_per_block
= sp
->s_block_size
/ sizeof(struct group_desc
);
145 sp
->s_groups_count
= ((sp
->s_blocks_count
- sp
->s_first_data_block
- 1)
146 / sp
->s_blocks_per_group
) + 1;
148 /* ceil(groups_count/desc_per_block) */
149 sp
->s_gdb_count
= (sp
->s_groups_count
+ sp
->s_desc_per_block
- 1)
150 / sp
->s_desc_per_block
;
152 gd_size
= sp
->s_gdb_count
* sp
->s_block_size
;
155 STATICINIT(buf
, gd_size
);
156 group_descs
= (struct group_desc
*) buf
;
159 STATICINIT(buf
, gd_size
);
160 ondisk_group_descs
= (struct group_desc
*) buf
;
162 if (!group_descs
|| !ondisk_group_descs
)
163 panic("can't allocate memory for gdt buffer");
165 /* s_first_data_block (block number, where superblock is stored)
166 * is 1 for 1Kb blocks and 0 for larger blocks.
167 * For fs with 1024-byte blocks first 1024 bytes (block0) used by MBR,
168 * and block1 stores superblock. When block size is larger, block0 stores
169 * both MBR and superblock, but gdt lives in next block anyway.
170 * If sb=N was specified, then gdt is stored in N+1 block, the block number
171 * here uses 1k units.
174 if (opt
.block_with_super
== 0) {
175 gdt_position
= (sp
->s_first_data_block
+ 1) * sp
->s_block_size
;
177 gdt_position
= (opt
.block_with_super
+ 1) * 1024;
180 r
= bdev_read(dev
, cvu64(gdt_position
), (char*) ondisk_group_descs
,
181 gd_size
, BDEV_NOFLAGS
);
182 if (r
!= (ssize_t
) gd_size
) {
183 printf("Can not read group descriptors\n");
187 /* TODO: check descriptors we just read */
189 copy_group_descriptors(group_descs
, ondisk_group_descs
, sp
->s_groups_count
);
190 sp
->s_group_desc
= group_descs
;
192 /* Make a few basic checks to see if super block looks reasonable. */
193 if (sp
->s_inodes_count
< 1 || sp
->s_blocks_count
< 1) {
194 printf("not enough inodes or data blocks, \n");
198 sp
->s_dirs_counter
= ext2_count_dirs(sp
);
200 /* Start block search from this block.
201 * We skip superblock (1 block), group descriptors blocks (sp->s_gdb_count)
202 * block and inode bitmaps (2 blocks) and inode table.
204 sp
->s_bsearch
= sp
->s_first_data_block
+ 1 + sp
->s_gdb_count
+ 2
205 + sp
->s_itb_per_group
;
209 sp
->s_dev
= dev
; /* restore device number */
214 /*===========================================================================*
216 *===========================================================================*/
218 struct super_block
*sp
; /* pointer to a superblock */
220 /* Write a superblock and gdt. */
222 block_t gd_size
; /* group descriptors table size in blocks */
226 panic("can't write superblock on read-only filesys.");
228 if (sp
->s_dev
== NO_DEV
)
229 panic("request to write super_block, but NO_DEV");
231 super_copy(ondisk_superblock
, sp
);
233 r
= bdev_write(sp
->s_dev
, cvu64(super_block_offset
), (char *) sp
,
234 SUPER_SIZE_D
, BDEV_NOFLAGS
);
235 if (r
!= SUPER_SIZE_D
)
236 printf("ext2: Warning, failed to write superblock to the disk!\n");
238 if (group_descriptors_dirty
) {
239 /* Locate the appropriate super_block. */
240 gd_size
= sp
->s_gdb_count
* sp
->s_block_size
;
242 if (opt
.block_with_super
== 0) {
243 gdt_position
= (sp
->s_first_data_block
+ 1) * sp
->s_block_size
;
245 gdt_position
= (opt
.block_with_super
+ 1) * 1024;
248 copy_group_descriptors(ondisk_group_descs
, sp
->s_group_desc
,
251 r
= bdev_write(sp
->s_dev
, cvu64(gdt_position
),
252 (char*) ondisk_group_descs
, gd_size
, BDEV_NOFLAGS
);
253 if (r
!= (ssize_t
) gd_size
) {
254 printf("Can not write group descriptors\n");
256 group_descriptors_dirty
= 0;
261 /*===========================================================================*
263 *===========================================================================*/
264 struct group_desc
* get_group_desc(unsigned int bnum
)
266 if (bnum
>= superblock
->s_groups_count
) {
267 printf("ext2, get_group_desc: wrong bnum (%d) requested\n", bnum
);
270 return &superblock
->s_group_desc
[bnum
];
274 static u32_t
ext2_count_dirs(struct super_block
*sp
)
279 for (i
= 0; i
< sp
->s_groups_count
; i
++) {
280 struct group_desc
*desc
= get_group_desc(i
);
282 continue; /* TODO: fail? */
283 count
+= desc
->used_dirs_count
;
289 /*===========================================================================*
291 *===========================================================================*/
292 /* There are several things, which affect max filesize:
293 * - inode.i_blocks (512-byte blocks) is limited to (2^32 - 1).
294 * - number of addressed direct, single, double and triple indirect blocks.
295 * Number of addressed blocks depends on block_size only, thus unlike in
296 * linux (ext2_max_size) we do not make calculations, but use constants
297 * for different block sizes. Calculations (gcc code) are commented.
298 * Note: linux ext2_max_size makes calculated based on shifting, not
300 * (!!!)Note: constants hardly tight to EXT2_NDIR_BLOCKS, but I doubt its value
301 * will be changed someday. So if it's changed, then just recalculate constatns.
302 * Anyway this function is safe for any change.
303 * Note: there is also limitation from VFS (to LONG_MAX, i.e. 2GB).
305 static off_t
ext2_max_size(int block_size
)
307 /* 12 is EXT2_NDIR_BLOCKS used in calculations. */
308 if (EXT2_NDIR_BLOCKS
!= 12)
309 panic("ext2_max_size needs modification!");
311 case 1024: return LONG_MAX
; /* actually 17247252480 */
312 case 2048: return LONG_MAX
; /* 275415851008 */
313 case 4096: return LONG_MAX
; /* 2194719883264 */
315 ext2_debug("ext2_max_size: Unsupported block_size! \
316 Assuming bs is 1024 bytes\n");
321 long addr_in_block
= block_size
/4; /* 4 bytes per addr */
322 long sectors_in_block
= block_size
/512;
323 long long meta_blocks
; /* single, double and triple indirect blocks */
324 unsigned long long out_range_s
; /* max blocks addressed by inode */
325 unsigned long long max_bytes
;
326 unsigned long long upper_limit
;
328 /* 1 indirect block, 1 + addr_in_block dindirect and 1 + addr_in_block +
329 * + addr_in_block*addr_in_block triple indirect blocks */
330 meta_blocks
= 2*addr_in_block
+ addr_in_block
*addr_in_block
+ 3;
331 out_range_s
= EXT2_NDIR_BLOCKS
+ addr_in_block
+ addr_in_block
* addr_in_block
332 + addr_in_block
* addr_in_block
* addr_in_block
;
333 max_bytes
= out_range_s
* block_size
;
335 upper_limit
= (1LL << 32) - 1; /* max 512-byte blocks by i_blocks */
336 upper_limit
/= sectors_in_block
; /* total block_size blocks */
337 upper_limit
-= meta_blocks
; /* total data blocks */
338 upper_limit
*= (long long)block_size
; /* max size in bytes */
340 if (max_bytes
> upper_limit
)
341 max_bytes
= upper_limit
;
343 /* Limit s_max_size to LONG_MAX */
344 if (max_bytes
> LONG_MAX
)
345 max_bytes
= LONG_MAX
;
352 /*===========================================================================*
354 *===========================================================================*/
355 static void super_copy(
356 register struct super_block
*dest
,
357 register struct super_block
*source
359 /* Note: we don't convert stuff, used in ext3. */
361 /* Copy super_block to the in-core table, swapping bytes if need be. */
363 /* Just use memcpy */
364 memcpy(dest
, source
, SUPER_SIZE_D
);
367 dest
->s_inodes_count
= conv4(le_CPU
, source
->s_inodes_count
);
368 dest
->s_blocks_count
= conv4(le_CPU
, source
->s_blocks_count
);
369 dest
->s_r_blocks_count
= conv4(le_CPU
, source
->s_r_blocks_count
);
370 dest
->s_free_blocks_count
= conv4(le_CPU
, source
->s_free_blocks_count
);
371 dest
->s_free_inodes_count
= conv4(le_CPU
, source
->s_free_inodes_count
);
372 dest
->s_first_data_block
= conv4(le_CPU
, source
->s_first_data_block
);
373 dest
->s_log_block_size
= conv4(le_CPU
, source
->s_log_block_size
);
374 dest
->s_log_frag_size
= conv4(le_CPU
, source
->s_log_frag_size
);
375 dest
->s_blocks_per_group
= conv4(le_CPU
, source
->s_blocks_per_group
);
376 dest
->s_frags_per_group
= conv4(le_CPU
, source
->s_frags_per_group
);
377 dest
->s_inodes_per_group
= conv4(le_CPU
, source
->s_inodes_per_group
);
378 dest
->s_mtime
= conv4(le_CPU
, source
->s_mtime
);
379 dest
->s_wtime
= conv4(le_CPU
, source
->s_wtime
);
380 dest
->s_mnt_count
= conv2(le_CPU
, source
->s_mnt_count
);
381 dest
->s_max_mnt_count
= conv2(le_CPU
, source
->s_max_mnt_count
);
382 dest
->s_magic
= conv2(le_CPU
, source
->s_magic
);
383 dest
->s_state
= conv2(le_CPU
, source
->s_state
);
384 dest
->s_errors
= conv2(le_CPU
, source
->s_errors
);
385 dest
->s_minor_rev_level
= conv2(le_CPU
, source
->s_minor_rev_level
);
386 dest
->s_lastcheck
= conv4(le_CPU
, source
->s_lastcheck
);
387 dest
->s_checkinterval
= conv4(le_CPU
, source
->s_checkinterval
);
388 dest
->s_creator_os
= conv4(le_CPU
, source
->s_creator_os
);
389 dest
->s_rev_level
= conv4(le_CPU
, source
->s_rev_level
);
390 dest
->s_def_resuid
= conv2(le_CPU
, source
->s_def_resuid
);
391 dest
->s_def_resgid
= conv2(le_CPU
, source
->s_def_resgid
);
392 dest
->s_first_ino
= conv4(le_CPU
, source
->s_first_ino
);
393 dest
->s_inode_size
= conv2(le_CPU
, source
->s_inode_size
);
394 dest
->s_block_group_nr
= conv2(le_CPU
, source
->s_block_group_nr
);
395 dest
->s_feature_compat
= conv4(le_CPU
, source
->s_feature_compat
);
396 dest
->s_feature_incompat
= conv4(le_CPU
, source
->s_feature_incompat
);
397 dest
->s_feature_ro_compat
= conv4(le_CPU
, source
->s_feature_ro_compat
);
398 memcpy(dest
->s_uuid
, source
->s_uuid
, sizeof(dest
->s_uuid
));
399 memcpy(dest
->s_volume_name
, source
->s_volume_name
,
400 sizeof(dest
->s_volume_name
));
401 memcpy(dest
->s_last_mounted
, source
->s_last_mounted
,
402 sizeof(dest
->s_last_mounted
));
403 dest
->s_algorithm_usage_bitmap
=
404 conv4(le_CPU
, source
->s_algorithm_usage_bitmap
);
405 dest
->s_prealloc_blocks
= source
->s_prealloc_blocks
;
406 dest
->s_prealloc_dir_blocks
= source
->s_prealloc_dir_blocks
;
407 dest
->s_padding1
= conv2(le_CPU
, source
->s_padding1
);
411 /*===========================================================================*
413 *===========================================================================*/
415 register struct group_desc
*dest
,
416 register struct group_desc
*source
419 /* Copy super_block to the in-core table, swapping bytes if need be. */
421 /* Just use memcpy */
422 memcpy(dest
, source
, sizeof(struct group_desc
));
425 dest
->block_bitmap
= conv4(le_CPU
, source
->block_bitmap
);
426 dest
->inode_bitmap
= conv4(le_CPU
, source
->inode_bitmap
);
427 dest
->inode_table
= conv4(le_CPU
, source
->inode_table
);
428 dest
->free_blocks_count
= conv2(le_CPU
, source
->free_blocks_count
);
429 dest
->free_inodes_count
= conv2(le_CPU
, source
->free_inodes_count
);
430 dest
->used_dirs_count
= conv2(le_CPU
, source
->used_dirs_count
);
434 /*===========================================================================*
435 * copy_group_descriptors *
436 *===========================================================================*/
437 static void copy_group_descriptors(
438 register struct group_desc
*dest_array
,
439 register struct group_desc
*source_array
,
444 for (i
= 0; i
< ngroups
; i
++)
445 gd_copy(&dest_array
[i
], &source_array
[i
]);