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 */