arm: make signal handlers work
[minix.git] / servers / ext2 / super.c
blob4c34af27d0ebb46a4251e9064b8227f5ad7718d1
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
7 * Created (MFS based):
8 * February 2010 (Evgeniy Ivanov)
9 */
11 #include "fs.h"
12 #include <string.h>
13 #include <stdlib.h>
14 #include <assert.h>
15 #include <minix/com.h>
16 #include <minix/u64.h>
17 #include <minix/bdev.h>
18 #include "buf.h"
19 #include "inode.h"
20 #include "super.h"
21 #include "const.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
30 ngroups);
32 static off_t super_block_offset;
35 /*===========================================================================*
36 * get_super *
37 *===========================================================================*/
38 struct super_block *get_super(
39 dev_t dev /* device number whose super_block is sought */
42 if (dev == NO_DEV)
43 panic("request for super_block of NO_DEV");
44 if (superblock->s_dev != dev)
45 panic("wrong superblock", (int) dev);
47 return(superblock);
51 /*===========================================================================*
52 * get_block_size *
53 *===========================================================================*/
54 unsigned int get_block_size(dev_t dev)
56 if (dev == NO_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 /*===========================================================================*
64 * read_super *
65 *===========================================================================*/
66 int read_super(sp)
67 register struct super_block *sp; /* pointer to a superblock */
69 /* Read a superblock. */
70 dev_t dev;
71 int r;
72 /* group descriptors, sp->s_group_desc points to this. */
73 static struct group_desc *group_descs;
74 char *buf;
75 block_t gd_size; /* group descriptors table size in blocks */
76 int gdt_position;
78 dev = sp->s_dev; /* save device (will be overwritten by copy) */
79 if (dev == NO_DEV)
80 panic("request for super_block of NO_DEV");
82 if (opt.block_with_super == 0) {
83 super_block_offset = SUPER_BLOCK_BYTES;
84 } else {
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)
99 return(EINVAL);
101 super_copy(sp, ondisk_superblock);
103 sp->s_dev = NO_DEV; /* restore later */
105 if (sp->s_magic != SUPER_MAGIC)
106 return(EINVAL);
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);
113 return(EINVAL);
116 if ((sp->s_block_size % 512) != 0)
117 return(EINVAL);
119 if (SUPER_SIZE_D > sp->s_block_size)
120 return(EINVAL);
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");
131 return(EINVAL);
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");
139 return(EINVAL);
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;
154 buf = 0;
155 STATICINIT(buf, gd_size);
156 group_descs = (struct group_desc *) buf;
158 buf = 0;
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;
176 } else {
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");
184 return(EINVAL);
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");
195 return(EINVAL);
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;
207 sp->s_igsearch = 0;
209 sp->s_dev = dev; /* restore device number */
210 return(OK);
214 /*===========================================================================*
215 * write_super *
216 *===========================================================================*/
217 void write_super(sp)
218 struct super_block *sp; /* pointer to a superblock */
220 /* Write a superblock and gdt. */
221 int r;
222 block_t gd_size; /* group descriptors table size in blocks */
223 int gdt_position;
225 if (sp->s_rd_only)
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;
244 } else {
245 gdt_position = (opt.block_with_super + 1) * 1024;
248 copy_group_descriptors(ondisk_group_descs, sp->s_group_desc,
249 sp->s_groups_count);
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 /*===========================================================================*
262 * get_group_desc *
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);
268 return NULL;
270 return &superblock->s_group_desc[bnum];
274 static u32_t ext2_count_dirs(struct super_block *sp)
276 u32_t count = 0;
277 unsigned int i;
279 for (i = 0; i < sp->s_groups_count; i++) {
280 struct group_desc *desc = get_group_desc(i);
281 if (!desc)
282 continue; /* TODO: fail? */
283 count += desc->used_dirs_count;
285 return count;
289 /*===========================================================================*
290 * ext2_max_size *
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
299 * arithmetics.
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!");
310 switch(block_size) {
311 case 1024: return LONG_MAX; /* actually 17247252480 */
312 case 2048: return LONG_MAX; /* 275415851008 */
313 case 4096: return LONG_MAX; /* 2194719883264 */
314 default: {
315 ext2_debug("ext2_max_size: Unsupported block_size! \
316 Assuming bs is 1024 bytes\n");
317 return 67383296L;
320 #if 0
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;
347 return max_bytes;
348 #endif
352 /*===========================================================================*
353 * super_copy *
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. */
362 if (le_CPU) {
363 /* Just use memcpy */
364 memcpy(dest, source, SUPER_SIZE_D);
365 return;
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 /*===========================================================================*
412 * gd_copy *
413 *===========================================================================*/
414 static void gd_copy(
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. */
420 if (le_CPU) {
421 /* Just use memcpy */
422 memcpy(dest, source, sizeof(struct group_desc));
423 return;
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,
440 unsigned int ngroups
443 unsigned int i;
444 for (i = 0; i < ngroups; i++)
445 gd_copy(&dest_array[i], &source_array[i]);