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