1 /*
   2     ext2_mkfs.c -- ext2 fs creator
   3     Copyright (C) 1999, 2000, 2001, 2007 Free Software Foundation, Inc.
   4 
   5     This program is free software; you can redistribute it and/or modify
   6     it under the terms of the GNU General Public License as published by
   7     the Free Software Foundation; either version 3 of the License, or
   8     (at your option) any later version.
   9 
  10     This program is distributed in the hope that it will be useful,
  11     but WITHOUT ANY WARRANTY; without even the implied warranty of
  12     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  13     GNU General Public License for more details.
  14 
  15     You should have received a copy of the GNU General Public License
  16     along with this program.  If not, see <http://www.gnu.org/licenses/>.
  17 */
  18 
  19 #include <config.h>
  20 
  21 #ifndef DISCOVER_ONLY
  22 
  23 #define USE_EXT2_IS_DATA_BLOCK
  24 
  25 #include <stdio.h>
  26 #include <stdlib.h>
  27 #include <string.h>
  28 #include <sys/stat.h>
  29 #include <time.h>
  30 #include <unistd.h>
  31 #include <uuid/uuid.h>
  32 #include "ext2.h"
  33 
  34 /* formula grabbed from linux ext2 kernel source
  35  * 
  36  * returns 1 iff:
  37  *      x == y^N,       N is some natural number
  38  * OR   x == 0
  39  */
  40 static __inline__ int is_root(int x, int y)
  41 {
  42         if (!x) return 1;
  43 
  44         while (1)
  45         {
  46                 if (x == 1) return 1;
  47 
  48                 if (x % y) return 0;
  49 
  50                 x /= y;
  51         }
  52 }
  53 
  54 static __inline__ int is_group_sparse(int sparsesbfs, int group)
  55 {
  56         if (!sparsesbfs)
  57                 return 1;
  58 
  59         if (is_root(group, 3) || is_root(group, 5) || is_root(group, 7))
  60                 return 1;
  61 
  62         return 0;
  63 }
  64 
  65 /* has implicit parameter 'sb' !! */
  66 #define is_sparse(group) is_group_sparse(EXT2_SUPER_FEATURE_RO_COMPAT(*sb) \
  67                                 & EXT2_FEATURE_RO_COMPAT_SPARSE_SUPER, (group))
  68 
  69 static int ext2_mkfs_write_main(struct ext2_dev_handle *handle,
  70                                 struct ext2_super_block *sb,
  71                                 struct ext2_group_desc *gd)
  72 {
  73         int freeit;
  74         int i;
  75         int numgroups;
  76         int gdblocks;
  77         unsigned char *sbbuf;
  78         struct ext2_super_block *sb_for_io;
  79 
  80         freeit = 0;
  81         sbbuf = (unsigned char *)sb;
  82         sb_for_io = sb;
  83         if (EXT2_SUPER_LOG_BLOCK_SIZE(*sb))
  84         {
  85                 sbbuf = ped_malloc(1024 << EXT2_SUPER_LOG_BLOCK_SIZE(*sb));
  86                 if (!(handle->ops->read)(handle->cookie, sbbuf, 0, 1))
  87                         return 0;
  88                 memcpy (sbbuf+1024, sb, 1024);
  89                 freeit = 1;
  90                 sb_for_io = (struct ext2_super_block*) (sbbuf + 1024);
  91         }
  92 
  93         numgroups = ped_div_round_up (EXT2_SUPER_BLOCKS_COUNT(*sb)
  94                                 - EXT2_SUPER_FIRST_DATA_BLOCK(*sb),
  95                             EXT2_SUPER_BLOCKS_PER_GROUP(*sb));
  96         gdblocks = ped_div_round_up (numgroups * sizeof(struct ext2_group_desc),
  97                            1024 << EXT2_SUPER_LOG_BLOCK_SIZE(*sb));
  98 
  99         for (i=0;i<numgroups;i++)
 100         {
 101                 if (is_sparse(i))
 102                 {
 103                         int offset;
 104 
 105                         offset = EXT2_SUPER_FIRST_DATA_BLOCK(*sb)
 106                                  + i * EXT2_SUPER_BLOCKS_PER_GROUP(*sb);
 107 
 108                         sb_for_io->s_block_group_nr = PED_CPU_TO_LE16 (i);
 109 
 110                         if (!handle->ops->write(handle->cookie, sbbuf,
 111                                                 offset, 1))
 112                                 return 0;
 113                         if (!handle->ops->write(handle->cookie, gd, offset+1,
 114                                                 gdblocks))
 115                                 return 0;
 116                 }
 117         }
 118 
 119         sb_for_io->s_block_group_nr = 0;
 120 
 121         if (freeit)
 122                 ped_free(sbbuf);
 123         return 1;
 124 }
 125 
 126 static int ext2_mkfs_write_meta(struct ext2_dev_handle *handle,
 127                                 struct ext2_super_block *sb,
 128                                 struct ext2_group_desc *gd,
 129                                 PedTimer* timer)
 130 {
 131         int blocksize;
 132         int gdtsize;
 133         int i;
 134         int itsize;
 135         int numgroups;
 136         unsigned char *bb;
 137         unsigned char *ib;
 138         unsigned char *zero;
 139 
 140         blocksize = 1 << (EXT2_SUPER_LOG_BLOCK_SIZE(*sb) + 13);
 141 
 142         numgroups = ped_div_round_up (EXT2_SUPER_BLOCKS_COUNT(*sb)
 143                                 - EXT2_SUPER_FIRST_DATA_BLOCK(*sb),
 144                             EXT2_SUPER_BLOCKS_PER_GROUP(*sb));
 145         itsize = ped_div_round_up (sizeof(struct ext2_inode)
 146                                 * EXT2_SUPER_INODES_PER_GROUP(*sb),
 147                          (1024 << EXT2_SUPER_LOG_BLOCK_SIZE(*sb)));
 148         gdtsize = ped_div_round_up (sizeof(struct ext2_group_desc) * numgroups,
 149                           (1024 << EXT2_SUPER_LOG_BLOCK_SIZE(*sb)));
 150 
 151         bb = ped_malloc(1024 << EXT2_SUPER_LOG_BLOCK_SIZE(*sb));
 152         if (!bb) goto error;
 153         ib = ped_malloc(1024 << EXT2_SUPER_LOG_BLOCK_SIZE(*sb));
 154         if (!ib) goto error_free_bb;
 155         zero = ped_malloc((1024 << EXT2_SUPER_LOG_BLOCK_SIZE(*sb)) * itsize);
 156         if (!zero) goto error_free_zero;
 157 
 158         memset(zero, 0, (1024 << EXT2_SUPER_LOG_BLOCK_SIZE(*sb)) * itsize);
 159 
 160         ped_timer_reset (timer);
 161         ped_timer_set_state_name (timer, _("writing per-group metadata"));
 162 
 163         for (i=0;i<numgroups;i++)
 164         {
 165                 int admin;
 166                 blk_t bbblock;
 167                 int groupsize;
 168                 int groupoffset;
 169                 blk_t ibblock;
 170                 int j;
 171 
 172                 ped_timer_update (timer, 1.0 * i / numgroups);
 173 
 174                 groupoffset = i*EXT2_SUPER_BLOCKS_PER_GROUP(*sb)
 175                               + EXT2_SUPER_FIRST_DATA_BLOCK(*sb);
 176                 groupsize = PED_MIN(EXT2_SUPER_BLOCKS_COUNT(*sb) - groupoffset,
 177                                     EXT2_SUPER_BLOCKS_PER_GROUP(*sb));
 178 
 179                 admin = itsize + 2;
 180                 bbblock = groupoffset;
 181                 ibblock = groupoffset + 1;
 182                 if (is_sparse(i))
 183                 {
 184                         admin += gdtsize + 1;
 185                         bbblock = groupoffset + gdtsize + 1;
 186                         ibblock = groupoffset + gdtsize + 2;
 187                 }
 188 
 189                 {
 190                         memset(bb, 0, 1024 << EXT2_SUPER_LOG_BLOCK_SIZE(*sb));
 191                         if (is_sparse(i))
 192                                 for (j=0;j<gdtsize+1;j++)
 193                                         bb[j>>3] |= _bitmap[j&7];
 194 
 195                         j = bbblock - groupoffset;
 196                         bb[j>>3] |= _bitmap[j&7];
 197 
 198                         j = ibblock - groupoffset;
 199                         bb[j>>3] |= _bitmap[j&7];
 200 
 201                         for (j=0;j<itsize;j++)
 202                         {
 203                                 int k = j + gdtsize + 3;
 204 
 205                                 bb[k>>3] |= _bitmap[k&7];
 206                         }
 207 
 208                         for (j=groupsize;j<blocksize;j++)
 209                                 bb[j>>3] |= _bitmap[j&7];
 210 
 211                         if (!handle->ops->write(handle->cookie, bb, bbblock, 1))
 212                                 goto error_free_zero;
 213                 }
 214 
 215                 {
 216                         memset(ib, 0, 1024 << EXT2_SUPER_LOG_BLOCK_SIZE(*sb));
 217 
 218                         for (j=EXT2_SUPER_INODES_PER_GROUP(*sb);j<blocksize;j++)
 219                                 bb[j>>3] |= _bitmap[j&7];
 220 
 221                         if (!handle->ops->write(handle->cookie, ib, ibblock, 1))
 222                                 goto error_free_zero;
 223                 }
 224 
 225                 if (!handle->ops->write(handle->cookie, zero,
 226                                         groupoffset + gdtsize + 3, itsize))
 227                         goto error_free_zero;
 228 
 229                 gd[i].bg_block_bitmap = PED_CPU_TO_LE32(bbblock);
 230                 gd[i].bg_inode_bitmap = PED_CPU_TO_LE32(ibblock);
 231                 gd[i].bg_inode_table = PED_CPU_TO_LE32(groupoffset + gdtsize
 232                                                        + 3);
 233                 gd[i].bg_free_blocks_count = PED_CPU_TO_LE16(groupsize - admin);
 234                 gd[i].bg_free_inodes_count = PED_CPU_TO_LE16(
 235                         EXT2_SUPER_INODES_PER_GROUP(*sb));
 236                 gd[i].bg_used_dirs_count = 0;
 237                 gd[i].bg_used_dirs_count = 0;
 238                 gd[i].bg_pad = 0;
 239                 gd[i].bg_reserved[0] = 0;
 240                 gd[i].bg_reserved[1] = 0;
 241                 gd[i].bg_reserved[2] = 0;
 242 
 243                 sb->s_free_blocks_count = PED_CPU_TO_LE32 (
 244                         EXT2_SUPER_FREE_BLOCKS_COUNT(*sb)
 245                         + EXT2_GROUP_FREE_BLOCKS_COUNT(gd[i]));
 246         }
 247 
 248         ped_timer_update (timer, 1.0);
 249 
 250         ped_free(zero);
 251         ped_free(ib);
 252         ped_free(bb);
 253         return 1;
 254 
 255 error_free_zero:
 256         ped_free(zero);
 257         ped_free(ib);
 258 error_free_bb:
 259         ped_free(bb);
 260 error:
 261         return 0;
 262 }
 263 
 264 /* returns the offset into the buffer of the start of the next dir entry */
 265 static int _set_dirent(void* buf, int offset, int block_size, int is_last,
 266                        uint32_t inode, char* name, int file_type)
 267 {
 268         struct ext2_dir_entry_2 *dirent = (void*) (((char*)buf) + offset);
 269         int name_len = strlen(name);
 270         int rec_len;
 271 
 272         if (is_last)
 273                 rec_len = block_size - offset;
 274         else
 275                 rec_len = ped_round_up_to(name_len + 1 + 8, 4);
 276 
 277         memset (dirent, 0, rec_len);
 278 
 279         dirent->inode = PED_CPU_TO_LE32(inode);
 280         dirent->name_len = name_len;
 281         dirent->rec_len = PED_CPU_TO_LE16(rec_len);
 282         dirent->file_type = file_type;
 283         strcpy(dirent->name, name);
 284 
 285         return offset + rec_len;
 286 }
 287 
 288 static int ext2_mkfs_create_lost_and_found_inode(struct ext2_fs *fs)
 289 {
 290         struct ext2_buffer_head *bh;
 291         blk_t blocks[12];
 292         uint32_t* data = ped_malloc ((fs->blocksize / 4) * sizeof(uint32_t));
 293         int i;
 294         struct ext2_inode inode;
 295         int offset;
 296 
 297         for (i=0;i<12;i++)
 298         {
 299                 if (!(blocks[i] = ext2_find_free_block(fs)))
 300                         return 0;
 301 
 302                 if (!ext2_set_block_state(fs, blocks[i], 1, 1))
 303                         return 0;
 304         }
 305 
 306         /* create the directory entries, preallocating lots of blocks */
 307         /* first block contains . and .. */
 308         bh = ext2_bcreate(fs, blocks[0]);
 309         if (!bh)
 310                 return 0;
 311         memset(bh->data, 0, fs->blocksize);
 312         offset = _set_dirent(bh->data, 0, fs->blocksize, 0,
 313                              11, ".", EXT2_FT_DIR);
 314         offset = _set_dirent(bh->data, offset, fs->blocksize, 1,
 315                              EXT2_ROOT_INO, "..", EXT2_FT_DIR);
 316         bh->dirty = 1;
 317         ext2_brelse(bh, 1);
 318 
 319         /* subsequent blocks are empty */
 320         memset(data, 0, fs->blocksize);
 321         data[0] = 0;
 322         data[1] = PED_CPU_TO_LE32(fs->blocksize);
 323         for (i=1;i<12;i++)
 324         {
 325                 bh = ext2_bcreate(fs, blocks[i]);
 326                 memcpy(bh->data, data, fs->blocksize);
 327                 bh->dirty = 1;
 328                 ext2_brelse(bh, 1);
 329         }
 330 
 331         /* create inode */
 332         memset(&inode, 0, sizeof(struct ext2_inode));
 333         inode.i_mode = PED_CPU_TO_LE16(S_IFDIR | 0755);
 334         inode.i_uid = 0;
 335         inode.i_size = PED_CPU_TO_LE32(12 * fs->blocksize);
 336         inode.i_atime = PED_CPU_TO_LE32(time(NULL));
 337         inode.i_ctime = PED_CPU_TO_LE32(time(NULL));
 338         inode.i_mtime = PED_CPU_TO_LE32(time(NULL));
 339         inode.i_dtime = 0;
 340         inode.i_gid = 0;
 341         inode.i_links_count = PED_CPU_TO_LE16(2);
 342         inode.i_blocks = PED_CPU_TO_LE32((12 * fs->blocksize) >> 9);
 343         inode.i_flags = 0;
 344         for (i=0;i<12;i++)
 345                 inode.i_block[i] = PED_CPU_TO_LE32(blocks[i]);
 346 
 347         if (!ext2_write_inode(fs, 11, &inode))
 348                 return 0;
 349         fs->gd[0].bg_used_dirs_count = PED_CPU_TO_LE16(
 350                 EXT2_GROUP_USED_DIRS_COUNT(fs->gd[0]) + 1);
 351         fs->metadirty |= EXT2_META_GD;
 352 
 353         return 1;
 354 }
 355 
 356 static int ext2_mkfs_create_root_inode(struct ext2_fs *fs)
 357 {
 358         struct ext2_buffer_head *bh;
 359         blk_t block;
 360         struct ext2_inode inode;
 361         int offset;
 362 
 363         if (!(block = ext2_find_free_block(fs)))
 364                 return 0;
 365         if (!ext2_set_block_state(fs, block, 1, 1))
 366                 return 0;
 367 
 368         /* create directory entries */
 369         bh = ext2_bcreate(fs, block);
 370         memset(bh->data, 0, fs->blocksize);
 371         offset = _set_dirent(bh->data, 0, fs->blocksize, 0,
 372                              EXT2_ROOT_INO, ".", EXT2_FT_DIR);
 373         offset = _set_dirent(bh->data, offset, fs->blocksize, 0,
 374                              EXT2_ROOT_INO, "..", EXT2_FT_DIR);
 375         offset = _set_dirent(bh->data, offset, fs->blocksize, 1,
 376                              11, "lost+found", EXT2_FT_DIR);
 377         bh->dirty = 1;
 378         if (!ext2_brelse(bh, 1))
 379                 return 0;
 380 
 381         /* create inode */
 382         memset(&inode, 0, sizeof(struct ext2_inode));
 383         inode.i_mode = PED_CPU_TO_LE16(S_IFDIR | 0755);
 384         inode.i_uid = 0;
 385         inode.i_size = PED_CPU_TO_LE32(fs->blocksize);
 386         inode.i_atime = PED_CPU_TO_LE32(time(NULL));
 387         inode.i_ctime = PED_CPU_TO_LE32(time(NULL));
 388         inode.i_mtime = PED_CPU_TO_LE32(time(NULL));
 389         inode.i_dtime = 0;
 390         inode.i_gid = 0;
 391         inode.i_links_count = PED_CPU_TO_LE16(3);
 392         inode.i_blocks = PED_CPU_TO_LE32(fs->blocksize >> 9);
 393         inode.i_flags = 0;
 394         inode.i_block[0] = PED_CPU_TO_LE32(block);
 395 
 396         if (!ext2_write_inode(fs, 2, &inode))
 397                 return 0;
 398         fs->gd[0].bg_used_dirs_count = PED_CPU_TO_LE16 (
 399                 EXT2_GROUP_USED_DIRS_COUNT(fs->gd[0]) + 1);
 400         fs->metadirty |= EXT2_META_GD;
 401 
 402         return 1;
 403 }
 404 
 405 static int ext2_reserve_inodes(struct ext2_fs *fs)
 406 {
 407         int i;
 408 
 409         for (i=1;i<12;i++)
 410                 if (!ext2_set_inode_state(fs, i, 1, 1))
 411                         return 0;
 412         return 1;
 413 }
 414 
 415 static int ext2_mkfs_init_sb (struct ext2_super_block *sb, blk_t numblocks,
 416                               int numgroups, int first_block,
 417                               int log_block_size, blk_t blocks_per_group,
 418                               int inodes_per_group, int sparse_sb,
 419                               int reserved_block_percentage)
 420 {
 421         /* catch a bug in gcc 2.95.2 */
 422         PED_ASSERT(numgroups != 0, return 0);
 423 
 424         memset(sb, 0, 1024);
 425 
 426         sb->s_inodes_count = PED_CPU_TO_LE32(numgroups * inodes_per_group);
 427         sb->s_blocks_count = PED_CPU_TO_LE32(numblocks);
 428         sb->s_r_blocks_count = PED_CPU_TO_LE32(((uint64_t)numblocks
 429                                 * reserved_block_percentage) / 100);
 430 
 431         /* hack: this get's inc'd as we go through each group in
 432          * ext2_mkfs_write_meta()
 433          */
 434         sb->s_free_blocks_count = 0;
 435         sb->s_free_inodes_count = PED_CPU_TO_LE32 (numgroups
 436                                                         * inodes_per_group);
 437         sb->s_first_data_block = PED_CPU_TO_LE32(first_block);
 438         sb->s_log_block_size = PED_CPU_TO_LE32(log_block_size - 10);
 439         sb->s_log_frag_size = sb->s_log_block_size;
 440         sb->s_blocks_per_group = PED_CPU_TO_LE32(blocks_per_group);
 441         sb->s_frags_per_group = PED_CPU_TO_LE32(blocks_per_group);
 442         sb->s_inodes_per_group = PED_CPU_TO_LE32(inodes_per_group);
 443         sb->s_mtime = 0;
 444         sb->s_wtime = 0;
 445         sb->s_mnt_count = 0;
 446         sb->s_max_mnt_count = PED_CPU_TO_LE16(30);
 447         sb->s_magic = PED_CPU_TO_LE16(0xEF53);
 448         sb->s_state = PED_CPU_TO_LE16(EXT2_VALID_FS);
 449         sb->s_errors = PED_CPU_TO_LE16(EXT2_ERRORS_DEFAULT);
 450         sb->s_minor_rev_level = 0;
 451         sb->s_lastcheck = 0;
 452         sb->s_checkinterval = 0;
 453         sb->s_creator_os = 0;
 454         sb->s_rev_level = PED_CPU_TO_LE32(1);
 455         sb->s_def_resuid = 0;
 456         sb->s_def_resgid = 0;
 457         sb->s_first_ino = PED_CPU_TO_LE32(11);
 458         sb->s_inode_size = PED_CPU_TO_LE16(128);
 459         sb->s_block_group_nr = 0;
 460         sb->s_feature_compat = 0;
 461         sb->s_feature_incompat = 0;
 462         sb->s_feature_ro_compat = 0;
 463         if (sparse_sb)
 464                 sb->s_feature_ro_compat
 465                         |= PED_CPU_TO_LE32(EXT2_FEATURE_RO_COMPAT_SPARSE_SUPER);
 466 
 467 /* FIXME: let the user decide? _set_dirent() assumes FILETYPE */
 468         sb->s_feature_incompat
 469                 |= PED_CPU_TO_LE32(EXT2_FEATURE_INCOMPAT_FILETYPE);
 470 
 471         uuid_generate(sb->s_uuid);
 472         memset(sb->s_volume_name, 0, 16);
 473         memset(sb->s_last_mounted, 0, 64);
 474         sb->s_algorithm_usage_bitmap = 0;
 475         sb->s_prealloc_blocks = 0;
 476         sb->s_prealloc_dir_blocks = 0;
 477         sb->s_padding1 = 0;
 478 
 479         return 1;
 480 }
 481 
 482 /* Given these five inputs, compute the three outputs.  */
 483 static void
 484 compute_block_counts (blk_t numblocks, int numgroups, int log_block_size,
 485                       int sparse_sb, blk_t blocks_per_group,
 486                       int *last_group_blocks,
 487                       int *last_group_admin,
 488                       int *inodes_per_group)
 489 {
 490         int first_block = (log_block_size == 10) ? 1 : 0;
 491         size_t block_size = 1 << log_block_size;
 492 
 493         *last_group_blocks = ((numblocks - first_block) % blocks_per_group);
 494         if (!*last_group_blocks)
 495                 *last_group_blocks = blocks_per_group;
 496         *inodes_per_group = ped_round_up_to (numblocks / numgroups / 2,
 497                                              (block_size
 498                                               / sizeof(struct ext2_inode)));
 499         *last_group_admin = (2 + *inodes_per_group * sizeof(struct ext2_inode)
 500                              / block_size);
 501         if (is_group_sparse(sparse_sb, numgroups - 1)) {
 502                 *last_group_admin +=
 503                   (ped_div_round_up (numgroups * sizeof(struct ext2_group_desc),
 504                                      block_size));
 505         }
 506 }
 507 
 508 struct ext2_fs *ext2_mkfs(struct ext2_dev_handle *handle,
 509                           blk_t numblocks,
 510                           int log_block_size,
 511                           blk_t blocks_per_group,
 512                           int inodes_per_group,
 513                           int sparse_sb,
 514                           int reserved_block_percentage,
 515                           PedTimer* timer)
 516 {
 517         struct ext2_fs *fs;
 518         struct ext2_super_block sb;
 519         struct ext2_group_desc *gd;
 520         int numgroups;
 521         int first_block;
 522         int last_group_blocks;
 523         int last_group_admin;
 524         
 525         /* if the FS is > 512Mb, use 4k blocks, otherwise 1k blocks */
 526         if (log_block_size == 0) {
 527                 handle->ops->set_blocksize(handle->cookie, 12);
 528                 if (handle->ops->get_size(handle->cookie) > (512 * 1024))
 529                         log_block_size = 12;
 530                 else
 531                         log_block_size = 10;
 532         }
 533 
 534         /* FIXME: block size must be > MAX(logicalbs, physicalbs)
 535          * to avoid modify-on-write.
 536          *      -- Leslie
 537          */ 
 538 
 539         
 540         handle->ops->set_blocksize(handle->cookie, log_block_size);
 541 
 542         if (numblocks == 0)
 543                 numblocks = handle->ops->get_size(handle->cookie);
 544         if (numblocks == 0)
 545                 goto diagnose_fs_too_small;
 546 
 547         if (blocks_per_group == (unsigned int) 0)
 548                 blocks_per_group = 8 << log_block_size;
 549 
 550         first_block = (log_block_size == 10) ? 1 : 0;
 551 
 552         numgroups = ped_div_round_up (numblocks
 553                         - first_block, blocks_per_group);
 554 
 555         if (sparse_sb == -1)
 556                 sparse_sb = 1;
 557 
 558         /* FIXME: 5% not appropriate for modern drive sizes */
 559         if (reserved_block_percentage == -1)
 560                 reserved_block_percentage = 5;
 561 
 562         compute_block_counts (numblocks, numgroups, log_block_size, sparse_sb,
 563                               blocks_per_group, &last_group_blocks,
 564                               &last_group_admin, &inodes_per_group);
 565 
 566         int fs_too_small = 0;
 567         if (last_group_admin + 1 >= last_group_blocks)
 568           {
 569             numgroups--;
 570             if (numgroups == 0)
 571               fs_too_small = 1;
 572             else
 573               {
 574                 numblocks -= last_group_blocks;
 575                 compute_block_counts (numblocks, numgroups, log_block_size,
 576                                       sparse_sb, blocks_per_group,
 577                                       &last_group_blocks, &last_group_admin,
 578                                       &inodes_per_group);
 579               }
 580           }
 581 
 582         if (numgroups == 1
 583             && (last_group_blocks - last_group_admin < 8
 584                 || inodes_per_group < 16
 585                 /* This final term ensures that we detect
 586                    mkpartfs primary ext2 10KB 27650B as invalid.  */
 587                 || (inodes_per_group == 16
 588                     && last_group_blocks - last_group_admin < 14)))
 589           fs_too_small = 1;
 590 
 591         if (fs_too_small) {
 592         diagnose_fs_too_small:
 593                 ped_exception_throw (
 594                         PED_EXCEPTION_ERROR,
 595                         PED_EXCEPTION_CANCEL,
 596                         _("File system too small for ext2."));
 597                 goto error;
 598         }
 599 
 600         gd = ped_malloc(numgroups * sizeof(struct ext2_group_desc)
 601                         + (1 << log_block_size));
 602         if (!gd)
 603                 goto error;
 604 
 605         if (!ext2_mkfs_init_sb(&sb, numblocks, numgroups, first_block,
 606                                log_block_size, blocks_per_group,
 607                                inodes_per_group, sparse_sb,
 608                                reserved_block_percentage))
 609                 goto error_free_gd;
 610         if (!ext2_mkfs_write_meta(handle, &sb, gd, timer))
 611                 goto error_free_gd;
 612         if (!ext2_mkfs_write_main(handle, &sb, gd))
 613                 goto error_free_gd;
 614 
 615         fs = ext2_open(handle, 0);
 616         if (!fs) goto error_close_fs;
 617         if (!ext2_reserve_inodes(fs)) goto error_close_fs;
 618         if (!ext2_mkfs_create_root_inode(fs)) goto error_close_fs;
 619         if (!ext2_mkfs_create_lost_and_found_inode(fs))
 620                 goto error_close_fs;
 621         if (!ext2_sync(fs)) goto error_close_fs;
 622         ped_free(gd);
 623         return fs;
 624 
 625 error_close_fs:
 626         ext2_close(fs);
 627 error_free_gd:
 628         ped_free (gd);
 629 error:
 630         return NULL;
 631 }
 632 #endif /* !DISCOVER_ONLY */