1 /* $NetBSD: setup.c,v 1.26 2009/03/02 11:31:59 tsutsui Exp $ */
4 * Copyright (c) 1980, 1986, 1993
5 * The Regents of the University of California. All rights reserved.
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 * 3. Neither the name of the University nor the names of its contributors
16 * may be used to endorse or promote products derived from this software
17 * without specific prior written permission.
19 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
20 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
23 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
25 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
26 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
27 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
28 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
33 * Copyright (c) 1997 Manuel Bouyer.
35 * Redistribution and use in source and binary forms, with or without
36 * modification, are permitted provided that the following conditions
38 * 1. Redistributions of source code must retain the above copyright
39 * notice, this list of conditions and the following disclaimer.
40 * 2. Redistributions in binary form must reproduce the above copyright
41 * notice, this list of conditions and the following disclaimer in the
42 * documentation and/or other materials provided with the distribution.
44 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
45 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
46 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
47 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
48 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
49 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
50 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
51 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
52 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
53 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
56 #include <sys/cdefs.h>
59 static char sccsid
[] = "@(#)setup.c 8.5 (Berkeley) 11/23/94";
61 __RCSID("$NetBSD: setup.c,v 1.26 2009/03/02 11:31:59 tsutsui Exp $");
66 #include <sys/param.h>
68 #include <ufs/ext2fs/ext2fs_dinode.h>
69 #include <ufs/ext2fs/ext2fs.h>
71 #include <sys/ioctl.h>
72 #include <sys/disklabel.h>
84 #include "exitvalues.h"
86 void badsb(int, const char *);
87 int calcsb(const char *, int, struct m_ext2fs
*);
88 static struct disklabel
*getdisklabel(const char *, int);
89 static int readsb(int);
92 setup(const char *dev
)
99 struct m_ext2fs proto
;
101 u_int64_t maxfilesize
;
105 doskipclean
= skipclean
;
106 if (stat(dev
, &statb
) < 0) {
107 printf("Can't stat %s: %s\n", dev
, strerror(errno
));
110 if (!S_ISCHR(statb
.st_mode
)) {
111 pfatal("%s is not a character device", dev
);
112 if (reply("CONTINUE") == 0)
115 if ((fsreadfd
= open(dev
, O_RDONLY
)) < 0) {
116 printf("Can't open %s: %s\n", dev
, strerror(errno
));
120 printf("** %s", dev
);
121 if (nflag
|| (fswritefd
= open(dev
, O_WRONLY
)) < 0) {
124 pfatal("NO WRITE ACCESS");
125 printf(" (NO WRITE)");
133 sblk
.b_un
.b_buf
= malloc(SBSIZE
);
134 asblk
.b_un
.b_buf
= malloc(SBSIZE
);
135 if (sblk
.b_un
.b_buf
== NULL
|| asblk
.b_un
.b_buf
== NULL
)
136 errexit("cannot allocate space for superblock");
137 if ((lp
= getdisklabel((char *)NULL
, fsreadfd
)) != NULL
)
138 dev_bsize
= secsize
= lp
->d_secsize
;
140 dev_bsize
= secsize
= DEV_BSIZE
;
142 * Read in the superblock, looking for alternates if necessary
144 if (readsb(1) == 0) {
145 if (bflag
|| preen
|| calcsb(dev
, fsreadfd
, &proto
) == 0)
147 if (reply("LOOK FOR ALTERNATE SUPERBLOCKS") == 0)
149 for (cg
= 1; cg
< proto
.e2fs_ncg
; cg
++) {
150 bflag
= fsbtodb(&proto
,
151 cg
* proto
.e2fs
.e2fs_bpg
+
152 proto
.e2fs
.e2fs_first_dblock
);
156 if (cg
>= proto
.e2fs_ncg
) {
157 printf("%s %s\n%s %s\n%s %s\n",
158 "SEARCH FOR ALTERNATE SUPER-BLOCK",
159 "FAILED. YOU MUST USE THE",
160 "-b OPTION TO FSCK_FFS TO SPECIFY THE",
161 "LOCATION OF AN ALTERNATE",
162 "SUPER-BLOCK TO SUPPLY NEEDED",
163 "INFORMATION; SEE fsck_ext2fs(8).");
167 pwarn("USING ALTERNATE SUPERBLOCK AT %d\n", bflag
);
170 printf("state = %d\n", sblock
.e2fs
.e2fs_state
);
171 if (sblock
.e2fs
.e2fs_state
== E2FS_ISCLEAN
) {
173 pwarn("%sile system is clean; not checking\n",
174 preen
? "f" : "** F");
178 pwarn("** File system is already clean\n");
180 maxfsblock
= sblock
.e2fs
.e2fs_bcount
;
181 maxino
= sblock
.e2fs_ncg
* sblock
.e2fs
.e2fs_ipg
;
182 sizepb
= sblock
.e2fs_bsize
;
183 maxfilesize
= sblock
.e2fs_bsize
* NDADDR
- 1;
184 for (i
= 0; i
< NIADDR
; i
++) {
185 sizepb
*= NINDIR(&sblock
);
186 maxfilesize
+= sizepb
;
189 * Check and potentially fix certain fields in the super block.
191 if (/* (sblock.e2fs.e2fs_rbcount < 0) || */
192 (sblock
.e2fs
.e2fs_rbcount
> sblock
.e2fs
.e2fs_bcount
)) {
193 pfatal("IMPOSSIBLE RESERVED BLOCK COUNT=%d IN SUPERBLOCK",
194 sblock
.e2fs
.e2fs_rbcount
);
195 if (reply("SET TO DEFAULT") == 1) {
196 sblock
.e2fs
.e2fs_rbcount
=
197 sblock
.e2fs
.e2fs_bcount
* MINFREE
/ 100;
202 if (sblock
.e2fs
.e2fs_bpg
!= sblock
.e2fs
.e2fs_fpg
) {
203 pfatal("WRONG FPG=%d (BPG=%d) IN SUPERBLOCK",
204 sblock
.e2fs
.e2fs_fpg
, sblock
.e2fs
.e2fs_bpg
);
207 if (asblk
.b_dirty
&& !bflag
) {
209 flush(fswritefd
, &asblk
);
212 * read in the summary info.
215 sblock
.e2fs_gd
= malloc(sblock
.e2fs_ngdb
* sblock
.e2fs_bsize
);
216 if (sblock
.e2fs_gd
== NULL
)
217 errexit("out of memory");
219 for (i
= 0; i
< sblock
.e2fs_ngdb
; i
++) {
221 (char *)&sblock
.e2fs_gd
[i
* sblock
.e2fs_bsize
/
222 sizeof(struct ext2_gd
)],
223 fsbtodb(&sblock
, ((sblock
.e2fs_bsize
> 1024) ? 0 : 1) +
225 sblock
.e2fs_bsize
) != 0 && !asked
) {
226 pfatal("BAD SUMMARY INFORMATION");
227 if (reply("CONTINUE") == 0)
228 exit(FSCK_EXIT_CHECK_FAILED
);
233 * allocate and initialize the necessary maps
235 bmapsize
= roundup(howmany(maxfsblock
, NBBY
), sizeof(int16_t));
236 blockmap
= calloc((unsigned int)bmapsize
, sizeof(char));
237 if (blockmap
== NULL
) {
238 printf("cannot alloc %u bytes for blockmap\n",
239 (unsigned int)bmapsize
);
242 statemap
= calloc((unsigned int)(maxino
+ 2), sizeof(char));
243 if (statemap
== NULL
) {
244 printf("cannot alloc %u bytes for statemap\n",
245 (unsigned int)(maxino
+ 1));
248 typemap
= calloc((unsigned int)(maxino
+ 1), sizeof(char));
249 if (typemap
== NULL
) {
250 printf("cannot alloc %u bytes for typemap\n",
251 (unsigned int)(maxino
+ 1));
254 lncntp
= calloc((unsigned)(maxino
+ 1), sizeof(int16_t));
255 if (lncntp
== NULL
) {
256 printf("cannot alloc %u bytes for lncntp\n",
257 (unsigned int)((maxino
+ 1) * sizeof(int16_t)));
260 for (numdirs
= 0, cg
= 0; cg
< sblock
.e2fs_ncg
; cg
++) {
261 numdirs
+= fs2h16(sblock
.e2fs_gd
[cg
].ext2bgd_ndirs
);
264 listmax
= numdirs
+ 10;
265 inpsort
= calloc((unsigned int)listmax
, sizeof(struct inoinfo
*));
266 inphead
= calloc((unsigned int)numdirs
, sizeof(struct inoinfo
*));
267 if (inpsort
== NULL
|| inphead
== NULL
) {
268 printf("cannot alloc %u bytes for inphead\n",
269 (unsigned int)(numdirs
* sizeof(struct inoinfo
*)));
281 * Read in the super block and its summary info, convert to host byte order.
286 daddr_t super
= bflag
? bflag
: SBOFF
/ dev_bsize
;
288 if (bread(fsreadfd
, (char *)sblk
.b_un
.b_fs
, super
, (long)SBSIZE
) != 0)
291 sblk
.b_size
= SBSIZE
;
293 /* Copy the superblock in memory */
294 e2fs_sbload(sblk
.b_un
.b_fs
, &sblock
.e2fs
);
297 * run a few consistency checks of the super block
299 if (sblock
.e2fs
.e2fs_magic
!= E2FS_MAGIC
) {
300 badsb(listerr
, "MAGIC NUMBER WRONG");
303 if (sblock
.e2fs
.e2fs_log_bsize
> 2) {
304 badsb(listerr
, "BAD LOG_BSIZE");
307 if (sblock
.e2fs
.e2fs_rev
> E2FS_REV0
&&
308 (!powerof2(sblock
.e2fs
.e2fs_inode_size
) ||
309 sblock
.e2fs
.e2fs_inode_size
< sizeof(struct ext2fs_dinode
) ||
310 sblock
.e2fs
.e2fs_inode_size
>
311 (1024 << sblock
.e2fs
.e2fs_log_bsize
))) {
312 badsb(listerr
, "BAD INODE_SIZE");
316 /* compute the dynamic fields of the in-memory sb */
317 /* compute dynamic sb infos */
319 howmany(sblock
.e2fs
.e2fs_bcount
- sblock
.e2fs
.e2fs_first_dblock
,
320 sblock
.e2fs
.e2fs_bpg
);
321 /* XXX assume hw bsize = 512 */
322 sblock
.e2fs_fsbtodb
= sblock
.e2fs
.e2fs_log_bsize
+ 1;
323 sblock
.e2fs_bsize
= 1024 << sblock
.e2fs
.e2fs_log_bsize
;
324 sblock
.e2fs_bshift
= LOG_MINBSIZE
+ sblock
.e2fs
.e2fs_log_bsize
;
325 sblock
.e2fs_qbmask
= sblock
.e2fs_bsize
- 1;
326 sblock
.e2fs_bmask
= ~sblock
.e2fs_qbmask
;
327 sblock
.e2fs_ngdb
= howmany(sblock
.e2fs_ncg
,
328 sblock
.e2fs_bsize
/ sizeof(struct ext2_gd
));
329 sblock
.e2fs_ipb
= sblock
.e2fs_bsize
/ EXT2_DINODE_SIZE(&sblock
);
330 sblock
.e2fs_itpg
= howmany(sblock
.e2fs
.e2fs_ipg
, sblock
.e2fs_ipb
);
333 * Compute block size that the filesystem is based on,
334 * according to fsbtodb, and adjust superblock block number
335 * so we can tell if this is an alternate later.
338 dev_bsize
= sblock
.e2fs_bsize
/ fsbtodb(&sblock
, 1);
339 sblk
.b_bno
= super
/ dev_bsize
;
341 if (sblock
.e2fs_ncg
== 1) {
342 /* no alternate superblock; assume it's okay */
346 getblk(&asblk
, 1 * sblock
.e2fs
.e2fs_bpg
+ sblock
.e2fs
.e2fs_first_dblock
,
356 * Set all possible fields that could differ, then do check
357 * of whole super block against an alternate super block.
358 * When an alternate super-block is specified this check is skipped.
360 asblk
.b_un
.b_fs
->e2fs_rbcount
= sblk
.b_un
.b_fs
->e2fs_rbcount
;
361 asblk
.b_un
.b_fs
->e2fs_fbcount
= sblk
.b_un
.b_fs
->e2fs_fbcount
;
362 asblk
.b_un
.b_fs
->e2fs_ficount
= sblk
.b_un
.b_fs
->e2fs_ficount
;
363 asblk
.b_un
.b_fs
->e2fs_mtime
= sblk
.b_un
.b_fs
->e2fs_mtime
;
364 asblk
.b_un
.b_fs
->e2fs_wtime
= sblk
.b_un
.b_fs
->e2fs_wtime
;
365 asblk
.b_un
.b_fs
->e2fs_mnt_count
= sblk
.b_un
.b_fs
->e2fs_mnt_count
;
366 asblk
.b_un
.b_fs
->e2fs_max_mnt_count
=
367 sblk
.b_un
.b_fs
->e2fs_max_mnt_count
;
368 asblk
.b_un
.b_fs
->e2fs_state
= sblk
.b_un
.b_fs
->e2fs_state
;
369 asblk
.b_un
.b_fs
->e2fs_beh
= sblk
.b_un
.b_fs
->e2fs_beh
;
370 asblk
.b_un
.b_fs
->e2fs_lastfsck
= sblk
.b_un
.b_fs
->e2fs_lastfsck
;
371 asblk
.b_un
.b_fs
->e2fs_fsckintv
= sblk
.b_un
.b_fs
->e2fs_fsckintv
;
372 asblk
.b_un
.b_fs
->e2fs_ruid
= sblk
.b_un
.b_fs
->e2fs_ruid
;
373 asblk
.b_un
.b_fs
->e2fs_rgid
= sblk
.b_un
.b_fs
->e2fs_rgid
;
374 asblk
.b_un
.b_fs
->e2fs_block_group_nr
=
375 sblk
.b_un
.b_fs
->e2fs_block_group_nr
;
376 asblk
.b_un
.b_fs
->e2fs_features_rocompat
&= ~EXT2F_ROCOMPAT_LARGEFILE
;
377 asblk
.b_un
.b_fs
->e2fs_features_rocompat
|=
378 sblk
.b_un
.b_fs
->e2fs_features_rocompat
& EXT2F_ROCOMPAT_LARGEFILE
;
379 if (sblock
.e2fs
.e2fs_rev
> E2FS_REV0
&&
380 ((sblock
.e2fs
.e2fs_features_incompat
& ~EXT2F_INCOMPAT_SUPP
) ||
381 (sblock
.e2fs
.e2fs_features_rocompat
& ~EXT2F_ROCOMPAT_SUPP
))) {
383 printf("compat 0x%08x, incompat 0x%08x, compat_ro "
385 sblock
.e2fs
.e2fs_features_compat
,
386 sblock
.e2fs
.e2fs_features_incompat
,
387 sblock
.e2fs
.e2fs_features_rocompat
);
389 badsb(listerr
, "INCOMPATIBLE FEATURE BITS IN SUPER BLOCK");
392 if (memcmp(sblk
.b_un
.b_fs
, asblk
.b_un
.b_fs
, SBSIZE
)) {
394 u_int32_t
*nlp
, *olp
, *endlp
;
396 printf("superblock mismatches\n");
397 nlp
= (u_int32_t
*)asblk
.b_un
.b_fs
;
398 olp
= (u_int32_t
*)sblk
.b_un
.b_fs
;
399 endlp
= olp
+ (SBSIZE
/ sizeof(*olp
));
400 for ( ; olp
< endlp
; olp
++, nlp
++) {
403 printf("offset %ld, original %ld, "
405 (long)(olp
- (u_int32_t
*)sblk
.b_un
.b_fs
),
411 "VALUES IN SUPER BLOCK DISAGREE WITH "
412 "THOSE IN FIRST ALTERNATE");
420 copyback_sb(struct bufarea
*bp
)
422 /* Copy the in-memory superblock back to buffer */
423 bp
->b_un
.b_fs
->e2fs_icount
= h2fs32(sblock
.e2fs
.e2fs_icount
);
424 bp
->b_un
.b_fs
->e2fs_bcount
= h2fs32(sblock
.e2fs
.e2fs_bcount
);
425 bp
->b_un
.b_fs
->e2fs_rbcount
= h2fs32(sblock
.e2fs
.e2fs_rbcount
);
426 bp
->b_un
.b_fs
->e2fs_fbcount
= h2fs32(sblock
.e2fs
.e2fs_fbcount
);
427 bp
->b_un
.b_fs
->e2fs_ficount
= h2fs32(sblock
.e2fs
.e2fs_ficount
);
428 bp
->b_un
.b_fs
->e2fs_first_dblock
=
429 h2fs32(sblock
.e2fs
.e2fs_first_dblock
);
430 bp
->b_un
.b_fs
->e2fs_log_bsize
= h2fs32(sblock
.e2fs
.e2fs_log_bsize
);
431 bp
->b_un
.b_fs
->e2fs_fsize
= h2fs32(sblock
.e2fs
.e2fs_fsize
);
432 bp
->b_un
.b_fs
->e2fs_bpg
= h2fs32(sblock
.e2fs
.e2fs_bpg
);
433 bp
->b_un
.b_fs
->e2fs_fpg
= h2fs32(sblock
.e2fs
.e2fs_fpg
);
434 bp
->b_un
.b_fs
->e2fs_ipg
= h2fs32(sblock
.e2fs
.e2fs_ipg
);
435 bp
->b_un
.b_fs
->e2fs_mtime
= h2fs32(sblock
.e2fs
.e2fs_mtime
);
436 bp
->b_un
.b_fs
->e2fs_wtime
= h2fs32(sblock
.e2fs
.e2fs_wtime
);
437 bp
->b_un
.b_fs
->e2fs_lastfsck
= h2fs32(sblock
.e2fs
.e2fs_lastfsck
);
438 bp
->b_un
.b_fs
->e2fs_fsckintv
= h2fs32(sblock
.e2fs
.e2fs_fsckintv
);
439 bp
->b_un
.b_fs
->e2fs_creator
= h2fs32(sblock
.e2fs
.e2fs_creator
);
440 bp
->b_un
.b_fs
->e2fs_rev
= h2fs32(sblock
.e2fs
.e2fs_rev
);
441 bp
->b_un
.b_fs
->e2fs_mnt_count
= h2fs16(sblock
.e2fs
.e2fs_mnt_count
);
442 bp
->b_un
.b_fs
->e2fs_max_mnt_count
=
443 h2fs16(sblock
.e2fs
.e2fs_max_mnt_count
);
444 bp
->b_un
.b_fs
->e2fs_magic
= h2fs16(sblock
.e2fs
.e2fs_magic
);
445 bp
->b_un
.b_fs
->e2fs_state
= h2fs16(sblock
.e2fs
.e2fs_state
);
446 bp
->b_un
.b_fs
->e2fs_beh
= h2fs16(sblock
.e2fs
.e2fs_beh
);
447 bp
->b_un
.b_fs
->e2fs_ruid
= h2fs16(sblock
.e2fs
.e2fs_ruid
);
448 bp
->b_un
.b_fs
->e2fs_rgid
= h2fs16(sblock
.e2fs
.e2fs_rgid
);
452 badsb(int listerr
, const char *s
)
458 printf("%s: ", cdevname());
459 pfatal("BAD SUPER BLOCK: %s\n", s
);
463 * Calculate a prototype superblock based on information in the disk label.
464 * When done the cgsblock macro can be calculated and the fs_ncg field
465 * can be used. Do NOT attempt to use other macros without verifying that
466 * their needed information is available!
470 calcsb(const char *dev
, int devfd
, struct m_ext2fs
*fs
)
472 struct disklabel
*lp
;
473 struct partition
*pp
;
476 cp
= strchr(dev
, '\0');
478 ((*cp
< 'a' || *cp
> 'h') && !isdigit((unsigned char)*cp
))) {
479 pfatal("%s: CANNOT FIGURE OUT FILE SYSTEM PARTITION\n", dev
);
482 lp
= getdisklabel(dev
, devfd
);
483 if (isdigit((unsigned char)*cp
))
484 pp
= &lp
->d_partitions
[0];
486 pp
= &lp
->d_partitions
[*cp
- 'a'];
487 if (pp
->p_fstype
!= FS_EX2FS
) {
488 pfatal("%s: NOT LABELED AS A EXT2 FILE SYSTEM (%s)\n",
489 dev
, pp
->p_fstype
< FSMAXTYPES
?
490 fstypenames
[pp
->p_fstype
] : "unknown");
493 memset(fs
, 0, sizeof(struct m_ext2fs
));
494 fs
->e2fs_bsize
= pp
->p_fsize
;
495 fs
->e2fs
.e2fs_log_bsize
= pp
->p_fsize
/ 1024;
496 fs
->e2fs
.e2fs_bcount
= (pp
->p_size
* DEV_BSIZE
) / fs
->e2fs_bsize
;
497 fs
->e2fs
.e2fs_first_dblock
= (fs
->e2fs
.e2fs_log_bsize
== 0) ? 1 : 0;
498 fs
->e2fs
.e2fs_bpg
= fs
->e2fs_bsize
* NBBY
;
499 fs
->e2fs_bshift
= LOG_MINBSIZE
+ fs
->e2fs
.e2fs_log_bsize
;
500 fs
->e2fs_qbmask
= fs
->e2fs_bsize
- 1;
501 fs
->e2fs_bmask
= ~fs
->e2fs_qbmask
;
503 howmany(fs
->e2fs
.e2fs_bcount
- fs
->e2fs
.e2fs_first_dblock
,
505 fs
->e2fs_fsbtodb
= fs
->e2fs
.e2fs_log_bsize
+ 1;
506 fs
->e2fs_ngdb
= howmany(fs
->e2fs_ncg
,
507 fs
->e2fs_bsize
/ sizeof(struct ext2_gd
));
512 static struct disklabel
*
513 getdisklabel(const char *s
, int fd
)
515 static struct disklabel lab
;
517 if (ioctl(fd
, DIOCGDINFO
, (char *)&lab
) < 0) {
520 pwarn("ioctl (GCINFO): %s\n", strerror(errno
));
521 errexit("%s: can't read disk label", s
);
531 1 /* block bitmap */ +
532 1 /* inode bitmap */ +
534 if (sblock
.e2fs
.e2fs_rev
> E2FS_REV0
&&
535 sblock
.e2fs
.e2fs_features_rocompat
& EXT2F_ROCOMPAT_SPARSESUPER
) {
536 if (cg_has_sb(c
) == 0)
539 overh
+= 1 /* superblock */ + sblock
.e2fs_ngdb
;