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