xref: /minix3/minix/fs/ext2/super.c (revision 433d6423c39e34ec4b79c950597bb2d236f886be)
1 /* This file manages the super block structure.
2  *
3  * The entry points into this file are
4  *   get_super:       search the 'superblock' table for a device
5  *   read_super:      read a superblock
6  *
7  * Created (MFS based):
8  *   February 2010 (Evgeniy Ivanov)
9  */
10 
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 <machine/param.h>
19 #include <machine/vmparam.h>
20 #include "buf.h"
21 #include "inode.h"
22 #include "super.h"
23 #include "const.h"
24 
25 static off_t ext2_max_size(int block_size);
26 static u32_t ext2_count_dirs(struct super_block *sp);
27 
28 static void super_copy(register struct super_block *dest, register
29 	struct super_block *source);
30 static void copy_group_descriptors(register struct group_desc
31 	*dest_array, register struct group_desc *source_array, unsigned int
32 	ngroups);
33 
34 static off_t super_block_offset;
35 
36 
37 /*===========================================================================*
38  *                              get_super                                    *
39  *===========================================================================*/
40 struct super_block *get_super(
41   dev_t dev           /* device number whose super_block is sought */
42 )
43 {
44   if (dev == NO_DEV)
45 	panic("request for super_block of NO_DEV");
46   if (superblock->s_dev != dev)
47 	panic("wrong superblock: 0x%x", (int) dev);
48 
49   return(superblock);
50 }
51 
52 
53 /*===========================================================================*
54  *                              get_block_size                               *
55  *===========================================================================*/
56 unsigned int get_block_size(dev_t dev)
57 {
58   if (dev == NO_DEV)
59 	panic("request for block size of NO_DEV");
60   return(lmfs_fs_block_size());
61 }
62 
63 static struct group_desc *ondisk_group_descs;
64 
65 /*===========================================================================*
66  *                              read_super                                   *
67  *===========================================================================*/
68 int read_super(sp)
69 register struct super_block *sp; /* pointer to a superblock */
70 {
71   /* Read a superblock. */
72   dev_t dev;
73   int r;
74   /* group descriptors, sp->s_group_desc points to this. */
75   static struct group_desc *group_descs;
76   char *buf;
77   block_t gd_size; /* group descriptors table size in blocks */
78   int gdt_position;
79   static char superblock_buf[1024];
80 
81   ondisk_superblock = (struct super_block *) superblock_buf;
82 
83   dev = sp->s_dev;              /* save device (will be overwritten by copy) */
84   if (dev == NO_DEV)
85 	panic("request for super_block of NO_DEV");
86 
87   if (opt.block_with_super == 0) {
88 	super_block_offset = SUPER_BLOCK_BYTES;
89   } else {
90 	/* The block number here uses 1k units */
91 	super_block_offset = opt.block_with_super * 1024;
92   }
93 
94   r = bdev_read(dev, ((u64_t)(super_block_offset)), (char*) ondisk_superblock,
95 	sizeof(superblock_buf), BDEV_NOFLAGS);
96 
97   if (r != sizeof(superblock_buf))
98 	return(EINVAL);
99 
100   super_copy(sp, ondisk_superblock);
101 
102   sp->s_dev = NO_DEV;           /* restore later */
103 
104   if (sp->s_magic != SUPER_MAGIC)
105 	return(EINVAL);
106 
107   sp->s_block_size = 1024*(1<<sp->s_log_block_size);
108 
109   if (sp->s_block_size < PAGE_SIZE) {
110 	printf("data block size (%u) is invalid\n", sp->s_block_size);
111 	return(EINVAL);
112   }
113 
114   if ((sp->s_block_size % 512) != 0)
115 	return(EINVAL);
116 
117   if (SUPER_SIZE_D > sp->s_block_size)
118 	return(EINVAL);
119 
120   /* Variable added for convinience (i_blocks counts 512-byte blocks). */
121   sp->s_sectors_in_block = sp->s_block_size / 512;
122 
123   /* TODO: this code is for revision 1 (but bw compatible with 0)
124    * inode must be power of 2 and smaller, than block size.
125    */
126   if ((EXT2_INODE_SIZE(sp) & (EXT2_INODE_SIZE(sp) - 1)) != 0
127       || EXT2_INODE_SIZE(sp) > sp->s_block_size) {
128 	printf("superblock->s_inode_size is incorrect...\n");
129 	return(EINVAL);
130   }
131 
132   sp->s_blocksize_bits = sp->s_log_block_size + 10;
133   sp->s_max_size = ext2_max_size(sp->s_block_size);
134   sp->s_inodes_per_block = sp->s_block_size / EXT2_INODE_SIZE(sp);
135   if (sp->s_inodes_per_block == 0 || sp->s_inodes_per_group == 0) {
136 	printf("either inodes_per_block or inodes_per_group count is 0\n");
137 	return(EINVAL);
138   }
139 
140   sp->s_itb_per_group = sp->s_inodes_per_group / sp->s_inodes_per_block;
141   sp->s_desc_per_block = sp->s_block_size / sizeof(struct group_desc);
142 
143   sp->s_groups_count = ((sp->s_blocks_count - sp->s_first_data_block - 1)
144 				/ sp->s_blocks_per_group) + 1;
145 
146   /* ceil(groups_count/desc_per_block) */
147   sp->s_gdb_count = (sp->s_groups_count + sp->s_desc_per_block - 1)
148 			/ sp->s_desc_per_block;
149 
150   gd_size = sp->s_gdb_count * sp->s_block_size;
151 
152   buf = 0;
153   STATICINIT(buf, gd_size);
154   group_descs = (struct group_desc *) buf;
155 
156   buf = 0;
157   STATICINIT(buf, gd_size);
158   ondisk_group_descs = (struct group_desc *) buf;
159 
160   if (!group_descs || !ondisk_group_descs)
161 	panic("can't allocate memory for gdt buffer");
162 
163   /* s_first_data_block (block number, where superblock is stored)
164    * is 1 for 1Kb blocks and 0 for larger blocks.
165    * For fs with 1024-byte blocks first 1024 bytes (block0) used by MBR,
166    * and block1 stores superblock. When block size is larger, block0 stores
167    * both MBR and superblock, but gdt lives in next block anyway.
168    * If sb=N was specified, then gdt is stored in N+1 block, the block number
169    * here uses 1k units.
170    *
171    */
172   if (opt.block_with_super == 0) {
173 	gdt_position = (sp->s_first_data_block + 1) * sp->s_block_size;
174   } else {
175 	gdt_position = (opt.block_with_super + 1) * 1024;
176   }
177 
178   r = bdev_read(dev, ((u64_t)(gdt_position)), (char*) ondisk_group_descs,
179 	gd_size, BDEV_NOFLAGS);
180   if (r != (ssize_t) gd_size) {
181 	printf("Can not read group descriptors\n");
182 	return(EINVAL);
183   }
184 
185   /* TODO: check descriptors we just read */
186 
187   copy_group_descriptors(group_descs, ondisk_group_descs, sp->s_groups_count);
188   sp->s_group_desc = group_descs;
189 
190   /* Make a few basic checks to see if super block looks reasonable. */
191   if (sp->s_inodes_count < 1 || sp->s_blocks_count < 1) {
192 	printf("not enough inodes or data blocks, \n");
193 	return(EINVAL);
194   }
195 
196   sp->s_dirs_counter = ext2_count_dirs(sp);
197 
198   /* Start block search from this block.
199    * We skip superblock (1 block), group descriptors blocks (sp->s_gdb_count)
200    * block and inode bitmaps (2 blocks) and inode table.
201    */
202   sp->s_bsearch = sp->s_first_data_block + 1 + sp->s_gdb_count + 2
203 			+ sp->s_itb_per_group;
204 
205   sp->s_igsearch = 0;
206 
207   sp->s_dev = dev; /* restore device number */
208   return(OK);
209 }
210 
211 
212 /*===========================================================================*
213  *                              write_super				     *
214  *===========================================================================*/
215 void write_super(sp)
216 struct super_block *sp; /* pointer to a superblock */
217 {
218 /* Write a superblock and gdt. */
219   int r;
220   block_t gd_size; /* group descriptors table size in blocks */
221   int gdt_position;
222 
223   if (sp->s_rd_only)
224 	panic("can't write superblock on read-only filesys.");
225 
226   if (sp->s_dev == NO_DEV)
227 	panic("request to write super_block, but NO_DEV");
228 
229   super_copy(ondisk_superblock, sp);
230 
231   r = bdev_write(sp->s_dev, ((u64_t)(super_block_offset)), (char *) sp,
232 	SUPER_SIZE_D, BDEV_NOFLAGS);
233   if (r != SUPER_SIZE_D)
234 	printf("ext2: Warning, failed to write superblock to the disk!\n");
235 
236   if (group_descriptors_dirty) {
237 	/* Locate the appropriate super_block. */
238 	gd_size = sp->s_gdb_count * sp->s_block_size;
239 
240 	if (opt.block_with_super == 0) {
241 		gdt_position = (sp->s_first_data_block + 1) * sp->s_block_size;
242 	} else {
243 		gdt_position = (opt.block_with_super + 1) * 1024;
244 	}
245 
246         copy_group_descriptors(ondisk_group_descs, sp->s_group_desc,
247 			       sp->s_groups_count);
248 
249 	r = bdev_write(sp->s_dev, ((u64_t)(gdt_position)),
250 		(char*) ondisk_group_descs, gd_size, BDEV_NOFLAGS);
251 	if (r != (ssize_t) gd_size) {
252 		printf("Can not write group descriptors\n");
253 	}
254 	group_descriptors_dirty = 0;
255   }
256 }
257 
258 
259 /*===========================================================================*
260  *                              get_group_desc                               *
261  *===========================================================================*/
262 struct group_desc* get_group_desc(unsigned int bnum)
263 {
264   if (bnum >= superblock->s_groups_count) {
265 	printf("ext2, get_group_desc: wrong bnum (%d) requested\n", bnum);
266 	return NULL;
267   }
268   return &superblock->s_group_desc[bnum];
269 }
270 
271 
272 static u32_t ext2_count_dirs(struct super_block *sp)
273 {
274   u32_t count = 0;
275   unsigned int i;
276 
277   for (i = 0; i < sp->s_groups_count; i++) {
278 	struct group_desc *desc = get_group_desc(i);
279 	if (!desc)
280 		continue; /* TODO: fail? */
281 	count += desc->used_dirs_count;
282   }
283   return count;
284 }
285 
286 
287 /*===========================================================================*
288  *                              ext2_max_size                                *
289  *===========================================================================*/
290 /* There are several things, which affect max filesize:
291  * - inode.i_blocks (512-byte blocks) is limited to (2^32 - 1).
292  * - number of addressed direct, single, double and triple indirect blocks.
293  * Number of addressed blocks depends on block_size only, thus unlike in
294  * linux (ext2_max_size) we do not make calculations, but use constants
295  * for different block sizes. Calculations (gcc code) are commented.
296  * Note: linux ext2_max_size makes calculated based on shifting, not
297  * arithmetics.
298  * (!!!)Note: constants hardly tight to EXT2_NDIR_BLOCKS, but I doubt its value
299  * will be changed someday. So if it's changed, then just recalculate constatns.
300  * Anyway this function is safe for any change.
301  * Note: there is also limitation from VFS (to LONG_MAX, i.e. 2GB).
302  */
303 static off_t ext2_max_size(int block_size)
304 {
305   /* 12 is EXT2_NDIR_BLOCKS used in calculations. */
306   if (EXT2_NDIR_BLOCKS != 12)
307 	panic("ext2_max_size needs modification!");
308   switch(block_size) {
309 	case 1024: return LONG_MAX; /* actually 17247252480 */
310 	case 2048: return LONG_MAX; /* 275415851008 */
311 	case 4096: return LONG_MAX; /* 2194719883264 */
312 	default: {
313 		ext2_debug("ext2_max_size: Unsupported block_size! \
314 				Assuming bs is 1024 bytes\n");
315 		return 67383296L;
316 	}
317   }
318 #if 0
319   long addr_in_block = block_size/4; /* 4 bytes per addr */
320   long sectors_in_block = block_size/512;
321   long long meta_blocks; /* single, double and triple indirect blocks */
322   unsigned long long out_range_s; /* max blocks addressed by inode */
323   unsigned long long max_bytes;
324   unsigned long long upper_limit;
325 
326   /* 1 indirect block, 1 + addr_in_block dindirect and 1 + addr_in_block +
327    * + addr_in_block*addr_in_block triple indirect blocks */
328   meta_blocks = 2*addr_in_block + addr_in_block*addr_in_block + 3;
329   out_range_s = EXT2_NDIR_BLOCKS + addr_in_block + addr_in_block * addr_in_block
330                 + addr_in_block * addr_in_block * addr_in_block;
331   max_bytes = out_range_s * block_size;
332 
333   upper_limit = (1LL << 32) - 1; /* max 512-byte blocks by i_blocks */
334   upper_limit /= sectors_in_block; /* total block_size blocks */
335   upper_limit -= meta_blocks; /* total data blocks */
336   upper_limit *= (long long)block_size; /* max size in bytes */
337 
338   if (max_bytes > upper_limit)
339 	max_bytes = upper_limit;
340 
341   /* Limit s_max_size to LONG_MAX */
342   if (max_bytes > LONG_MAX)
343 	max_bytes = LONG_MAX;
344 
345   return max_bytes;
346 #endif
347 }
348 
349 
350 /*===========================================================================*
351  *				super_copy				     *
352  *===========================================================================*/
353 static void super_copy(
354   register struct super_block *dest,
355   register struct super_block *source
356 )
357 /* Note: we don't convert stuff, used in ext3. */
358 {
359 /* Copy super_block to the in-core table, swapping bytes if need be. */
360   if (le_CPU) {
361 	/* Just use memcpy */
362 	memcpy(dest, source, SUPER_SIZE_D);
363 	return;
364   }
365   dest->s_inodes_count = conv4(le_CPU, source->s_inodes_count);
366   dest->s_blocks_count = conv4(le_CPU, source->s_blocks_count);
367   dest->s_r_blocks_count = conv4(le_CPU, source->s_r_blocks_count);
368   dest->s_free_blocks_count = conv4(le_CPU, source->s_free_blocks_count);
369   dest->s_free_inodes_count = conv4(le_CPU, source->s_free_inodes_count);
370   dest->s_first_data_block = conv4(le_CPU, source->s_first_data_block);
371   dest->s_log_block_size = conv4(le_CPU, source->s_log_block_size);
372   dest->s_log_frag_size = conv4(le_CPU, source->s_log_frag_size);
373   dest->s_blocks_per_group = conv4(le_CPU, source->s_blocks_per_group);
374   dest->s_frags_per_group = conv4(le_CPU, source->s_frags_per_group);
375   dest->s_inodes_per_group = conv4(le_CPU, source->s_inodes_per_group);
376   dest->s_mtime = conv4(le_CPU, source->s_mtime);
377   dest->s_wtime = conv4(le_CPU, source->s_wtime);
378   dest->s_mnt_count = conv2(le_CPU, source->s_mnt_count);
379   dest->s_max_mnt_count = conv2(le_CPU, source->s_max_mnt_count);
380   dest->s_magic = conv2(le_CPU, source->s_magic);
381   dest->s_state = conv2(le_CPU, source->s_state);
382   dest->s_errors = conv2(le_CPU, source->s_errors);
383   dest->s_minor_rev_level = conv2(le_CPU, source->s_minor_rev_level);
384   dest->s_lastcheck = conv4(le_CPU, source->s_lastcheck);
385   dest->s_checkinterval = conv4(le_CPU, source->s_checkinterval);
386   dest->s_creator_os = conv4(le_CPU, source->s_creator_os);
387   dest->s_rev_level = conv4(le_CPU, source->s_rev_level);
388   dest->s_def_resuid = conv2(le_CPU, source->s_def_resuid);
389   dest->s_def_resgid = conv2(le_CPU, source->s_def_resgid);
390   dest->s_first_ino = conv4(le_CPU, source->s_first_ino);
391   dest->s_inode_size = conv2(le_CPU, source->s_inode_size);
392   dest->s_block_group_nr = conv2(le_CPU, source->s_block_group_nr);
393   dest->s_feature_compat = conv4(le_CPU, source->s_feature_compat);
394   dest->s_feature_incompat = conv4(le_CPU, source->s_feature_incompat);
395   dest->s_feature_ro_compat = conv4(le_CPU, source->s_feature_ro_compat);
396   memcpy(dest->s_uuid, source->s_uuid, sizeof(dest->s_uuid));
397   memcpy(dest->s_volume_name, source->s_volume_name,
398 	 sizeof(dest->s_volume_name));
399   memcpy(dest->s_last_mounted, source->s_last_mounted,
400 	 sizeof(dest->s_last_mounted));
401   dest->s_algorithm_usage_bitmap =
402 			conv4(le_CPU, source->s_algorithm_usage_bitmap);
403   dest->s_prealloc_blocks = source->s_prealloc_blocks;
404   dest->s_prealloc_dir_blocks = source->s_prealloc_dir_blocks;
405   dest->s_padding1 = conv2(le_CPU, source->s_padding1);
406 }
407 
408 
409 /*===========================================================================*
410  *				gd_copy 				     *
411  *===========================================================================*/
412 static void gd_copy(
413   register struct group_desc *dest,
414   register struct group_desc *source
415 )
416 {
417   /* Copy super_block to the in-core table, swapping bytes if need be. */
418   if (le_CPU) {
419 	/* Just use memcpy */
420 	memcpy(dest, source, sizeof(struct group_desc));
421 	return;
422   }
423   dest->block_bitmap = conv4(le_CPU, source->block_bitmap);
424   dest->inode_bitmap = conv4(le_CPU, source->inode_bitmap);
425   dest->inode_table = conv4(le_CPU, source->inode_table);
426   dest->free_blocks_count = conv2(le_CPU, source->free_blocks_count);
427   dest->free_inodes_count = conv2(le_CPU, source->free_inodes_count);
428   dest->used_dirs_count = conv2(le_CPU, source->used_dirs_count);
429 }
430 
431 
432 /*===========================================================================*
433  *			copy_group_descriptors  			     *
434  *===========================================================================*/
435 static void copy_group_descriptors(
436   register struct group_desc *dest_array,
437   register struct group_desc *source_array,
438   unsigned int ngroups
439 )
440 {
441   unsigned int i;
442   for (i = 0; i < ngroups; i++)
443 	gd_copy(&dest_array[i], &source_array[i]);
444 }
445