]> CyberLeo.Net >> Repos - FreeBSD/stable/9.git/blob - sbin/growfs/growfs.c
MFC r234178:
[FreeBSD/stable/9.git] / sbin / growfs / growfs.c
1 /*
2  * Copyright (c) 2000 Christoph Herrmann, Thomas-Henning von Kamptz
3  * Copyright (c) 1980, 1989, 1993 The Regents of the University of California.
4  * All rights reserved.
5  *
6  * This code is derived from software contributed to Berkeley by
7  * Christoph Herrmann and Thomas-Henning von Kamptz, Munich and Frankfurt.
8  *
9  * Redistribution and use in source and binary forms, with or without
10  * modification, are permitted provided that the following conditions
11  * are met:
12  * 1. Redistributions of source code must retain the above copyright
13  *    notice, this list of conditions and the following disclaimer.
14  * 2. Redistributions in binary form must reproduce the above copyright
15  *    notice, this list of conditions and the following disclaimer in the
16  *    documentation and/or other materials provided with the distribution.
17  * 3. All advertising materials mentioning features or use of this software
18  *    must display the following acknowledgment:
19  *      This product includes software developed by the University of
20  *      California, Berkeley and its contributors, as well as Christoph
21  *      Herrmann and Thomas-Henning von Kamptz.
22  * 4. Neither the name of the University nor the names of its contributors
23  *    may be used to endorse or promote products derived from this software
24  *    without specific prior written permission.
25  *
26  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
27  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
28  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
29  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
30  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
31  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
32  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
33  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
34  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
35  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
36  * SUCH DAMAGE.
37  *
38  * $TSHeader: src/sbin/growfs/growfs.c,v 1.5 2000/12/12 19:31:00 tomsoft Exp $
39  *
40  */
41
42 #ifndef lint
43 static const char copyright[] =
44 "@(#) Copyright (c) 2000 Christoph Herrmann, Thomas-Henning von Kamptz\n\
45 Copyright (c) 1980, 1989, 1993 The Regents of the University of California.\n\
46 All rights reserved.\n";
47 #endif /* not lint */
48
49 #include <sys/cdefs.h>
50 __FBSDID("$FreeBSD$");
51
52 #include <sys/param.h>
53 #include <sys/ioctl.h>
54 #include <sys/stat.h>
55 #include <sys/disk.h>
56
57 #include <stdio.h>
58 #include <paths.h>
59 #include <ctype.h>
60 #include <err.h>
61 #include <fcntl.h>
62 #include <limits.h>
63 #include <stdlib.h>
64 #include <stdint.h>
65 #include <string.h>
66 #include <time.h>
67 #include <unistd.h>
68 #include <ufs/ufs/dinode.h>
69 #include <ufs/ffs/fs.h>
70
71 #include "debug.h"
72
73 #ifdef FS_DEBUG
74 int     _dbg_lvl_ = (DL_INFO);  /* DL_TRC */
75 #endif /* FS_DEBUG */
76
77 static union {
78         struct fs       fs;
79         char    pad[SBLOCKSIZE];
80 } fsun1, fsun2;
81 #define sblock  fsun1.fs        /* the new superblock */
82 #define osblock fsun2.fs        /* the old superblock */
83
84 /*
85  * Possible superblock locations ordered from most to least likely.
86  */
87 static int sblock_try[] = SBLOCKSEARCH;
88 static ufs2_daddr_t sblockloc;
89
90 static union {
91         struct cg       cg;
92         char    pad[MAXBSIZE];
93 } cgun1, cgun2;
94 #define acg     cgun1.cg        /* a cylinder cgroup (new) */
95 #define aocg    cgun2.cg        /* an old cylinder group */
96
97 static struct csum      *fscs;  /* cylinder summary */
98
99 static void     growfs(int, int, unsigned int);
100 static void     rdfs(ufs2_daddr_t, size_t, void *, int);
101 static void     wtfs(ufs2_daddr_t, size_t, void *, int, unsigned int);
102 static int      charsperline(void);
103 static void     usage(void);
104 static int      isblock(struct fs *, unsigned char *, int);
105 static void     clrblock(struct fs *, unsigned char *, int);
106 static void     setblock(struct fs *, unsigned char *, int);
107 static void     initcg(int, time_t, int, unsigned int);
108 static void     updjcg(int, time_t, int, int, unsigned int);
109 static void     updcsloc(time_t, int, int, unsigned int);
110 static void     frag_adjust(ufs2_daddr_t, int);
111 static void     updclst(int);
112 static void     get_dev_size(int, int *);
113
114 /*
115  * Here we actually start growing the file system. We basically read the
116  * cylinder summary from the first cylinder group as we want to update
117  * this on the fly during our various operations. First we handle the
118  * changes in the former last cylinder group. Afterwards we create all new
119  * cylinder groups.  Now we handle the cylinder group containing the
120  * cylinder summary which might result in a relocation of the whole
121  * structure.  In the end we write back the updated cylinder summary, the
122  * new superblock, and slightly patched versions of the super block
123  * copies.
124  */
125 static void
126 growfs(int fsi, int fso, unsigned int Nflag)
127 {
128         DBG_FUNC("growfs")
129         time_t modtime;
130         uint cylno;
131         int i, j, width;
132         char tmpbuf[100];
133 #ifdef FSIRAND
134         static int randinit=0;
135
136         DBG_ENTER;
137
138         if (!randinit) {
139                 randinit = 1;
140                 srandomdev();
141         }
142 #else /* not FSIRAND */
143
144         DBG_ENTER;
145
146 #endif /* FSIRAND */
147         time(&modtime);
148
149         /*
150          * Get the cylinder summary into the memory.
151          */
152         fscs = (struct csum *)calloc((size_t)1, (size_t)sblock.fs_cssize);
153         if (fscs == NULL)
154                 errx(1, "calloc failed");
155         for (i = 0; i < osblock.fs_cssize; i += osblock.fs_bsize) {
156                 rdfs(fsbtodb(&osblock, osblock.fs_csaddr +
157                     numfrags(&osblock, i)), (size_t)MIN(osblock.fs_cssize - i,
158                     osblock.fs_bsize), (void *)(((char *)fscs) + i), fsi);
159         }
160
161 #ifdef FS_DEBUG
162         {
163                 struct csum *dbg_csp;
164                 int dbg_csc;
165                 char dbg_line[80];
166
167                 dbg_csp = fscs;
168
169                 for (dbg_csc = 0; dbg_csc < osblock.fs_ncg; dbg_csc++) {
170                         snprintf(dbg_line, sizeof(dbg_line),
171                             "%d. old csum in old location", dbg_csc);
172                         DBG_DUMP_CSUM(&osblock, dbg_line, dbg_csp++);
173                 }
174         }
175 #endif /* FS_DEBUG */
176         DBG_PRINT0("fscs read\n");
177
178         /*
179          * Do all needed changes in the former last cylinder group.
180          */
181         updjcg(osblock.fs_ncg - 1, modtime, fsi, fso, Nflag);
182
183         /*
184          * Dump out summary information about file system.
185          */
186 #       define B2MBFACTOR (1 / (1024.0 * 1024.0))
187         printf("growfs: %.1fMB (%jd sectors) block size %d, fragment size %d\n",
188             (float)sblock.fs_size * sblock.fs_fsize * B2MBFACTOR,
189             (intmax_t)fsbtodb(&sblock, sblock.fs_size), sblock.fs_bsize,
190             sblock.fs_fsize);
191         printf("\tusing %d cylinder groups of %.2fMB, %d blks, %d inodes.\n",
192             sblock.fs_ncg, (float)sblock.fs_fpg * sblock.fs_fsize * B2MBFACTOR,
193             sblock.fs_fpg / sblock.fs_frag, sblock.fs_ipg);
194         if (sblock.fs_flags & FS_DOSOFTDEP)
195                 printf("\twith soft updates\n");
196 #       undef B2MBFACTOR
197
198         /*
199          * Now build the cylinders group blocks and
200          * then print out indices of cylinder groups.
201          */
202         printf("super-block backups (for fsck -b #) at:\n");
203         i = 0;
204         width = charsperline();
205
206         /*
207          * Iterate for only the new cylinder groups.
208          */
209         for (cylno = osblock.fs_ncg; cylno < sblock.fs_ncg; cylno++) {
210                 initcg(cylno, modtime, fso, Nflag);
211                 j = sprintf(tmpbuf, " %jd%s",
212                     (intmax_t)fsbtodb(&sblock, cgsblock(&sblock, cylno)),
213                     cylno < (sblock.fs_ncg - 1) ? "," : "" );
214                 if (i + j >= width) {
215                         printf("\n");
216                         i = 0;
217                 }
218                 i += j;
219                 printf("%s", tmpbuf);
220                 fflush(stdout);
221         }
222         printf("\n");
223
224         /*
225          * Do all needed changes in the first cylinder group.
226          * allocate blocks in new location
227          */
228         updcsloc(modtime, fsi, fso, Nflag);
229
230         /*
231          * Now write the cylinder summary back to disk.
232          */
233         for (i = 0; i < sblock.fs_cssize; i += sblock.fs_bsize) {
234                 wtfs(fsbtodb(&sblock, sblock.fs_csaddr + numfrags(&sblock, i)),
235                     (size_t)MIN(sblock.fs_cssize - i, sblock.fs_bsize),
236                     (void *)(((char *)fscs) + i), fso, Nflag);
237         }
238         DBG_PRINT0("fscs written\n");
239
240 #ifdef FS_DEBUG
241         {
242                 struct csum     *dbg_csp;
243                 int     dbg_csc;
244                 char    dbg_line[80];
245
246                 dbg_csp = fscs;
247                 for (dbg_csc = 0; dbg_csc < sblock.fs_ncg; dbg_csc++) {
248                         snprintf(dbg_line, sizeof(dbg_line),
249                             "%d. new csum in new location", dbg_csc);
250                         DBG_DUMP_CSUM(&sblock, dbg_line, dbg_csp++);
251                 }
252         }
253 #endif /* FS_DEBUG */
254
255         /*
256          * Now write the new superblock back to disk.
257          */
258         sblock.fs_time = modtime;
259         wtfs(sblockloc, (size_t)SBLOCKSIZE, (void *)&sblock, fso, Nflag);
260         DBG_PRINT0("sblock written\n");
261         DBG_DUMP_FS(&sblock, "new initial sblock");
262
263         /*
264          * Clean up the dynamic fields in our superblock copies.
265          */
266         sblock.fs_fmod = 0;
267         sblock.fs_clean = 1;
268         sblock.fs_ronly = 0;
269         sblock.fs_cgrotor = 0;
270         sblock.fs_state = 0;
271         memset((void *)&sblock.fs_fsmnt, 0, sizeof(sblock.fs_fsmnt));
272         sblock.fs_flags &= FS_DOSOFTDEP;
273
274         /*
275          * XXX
276          * The following fields are currently distributed from the superblock
277          * to the copies:
278          *     fs_minfree
279          *     fs_rotdelay
280          *     fs_maxcontig
281          *     fs_maxbpg
282          *     fs_minfree,
283          *     fs_optim
284          *     fs_flags regarding SOFTPDATES
285          *
286          * We probably should rather change the summary for the cylinder group
287          * statistics here to the value of what would be in there, if the file
288          * system were created initially with the new size. Therefor we still
289          * need to find an easy way of calculating that.
290          * Possibly we can try to read the first superblock copy and apply the
291          * "diffed" stats between the old and new superblock by still copying
292          * certain parameters onto that.
293          */
294
295         /*
296          * Write out the duplicate super blocks.
297          */
298         for (cylno = 0; cylno < sblock.fs_ncg; cylno++) {
299                 wtfs(fsbtodb(&sblock, cgsblock(&sblock, cylno)),
300                     (size_t)SBLOCKSIZE, (void *)&sblock, fso, Nflag);
301         }
302         DBG_PRINT0("sblock copies written\n");
303         DBG_DUMP_FS(&sblock, "new other sblocks");
304
305         DBG_LEAVE;
306         return;
307 }
308
309 /*
310  * This creates a new cylinder group structure, for more details please see
311  * the source of newfs(8), as this function is taken over almost unchanged.
312  * As this is never called for the first cylinder group, the special
313  * provisions for that case are removed here.
314  */
315 static void
316 initcg(int cylno, time_t modtime, int fso, unsigned int Nflag)
317 {
318         DBG_FUNC("initcg")
319         static caddr_t iobuf;
320         long blkno, start;
321         ufs2_daddr_t i, cbase, dmax;
322 #ifdef FSIRAND
323         struct ufs1_dinode *dp1;
324 #endif
325         struct csum *cs;
326         uint d, dupper, dlower;
327
328         if (iobuf == NULL && (iobuf = malloc(sblock.fs_bsize * 3)) == NULL)
329                 errx(37, "panic: cannot allocate I/O buffer");
330
331         /*
332          * Determine block bounds for cylinder group.
333          * Allow space for super block summary information in first
334          * cylinder group.
335          */
336         cbase = cgbase(&sblock, cylno);
337         dmax = cbase + sblock.fs_fpg;
338         if (dmax > sblock.fs_size)
339                 dmax = sblock.fs_size;
340         dlower = cgsblock(&sblock, cylno) - cbase;
341         dupper = cgdmin(&sblock, cylno) - cbase;
342         if (cylno == 0) /* XXX fscs may be relocated */
343                 dupper += howmany(sblock.fs_cssize, sblock.fs_fsize);
344         cs = &fscs[cylno];
345         memset(&acg, 0, sblock.fs_cgsize);
346         acg.cg_time = modtime;
347         acg.cg_magic = CG_MAGIC;
348         acg.cg_cgx = cylno;
349         acg.cg_niblk = sblock.fs_ipg;
350         acg.cg_initediblk = sblock.fs_ipg < 2 * INOPB(&sblock) ?
351             sblock.fs_ipg : 2 * INOPB(&sblock);
352         acg.cg_ndblk = dmax - cbase;
353         if (sblock.fs_contigsumsize > 0)
354                 acg.cg_nclusterblks = acg.cg_ndblk / sblock.fs_frag;
355         start = &acg.cg_space[0] - (u_char *)(&acg.cg_firstfield);
356         if (sblock.fs_magic == FS_UFS2_MAGIC) {
357                 acg.cg_iusedoff = start;
358         } else {
359                 acg.cg_old_ncyl = sblock.fs_old_cpg;
360                 acg.cg_old_time = acg.cg_time;
361                 acg.cg_time = 0;
362                 acg.cg_old_niblk = acg.cg_niblk;
363                 acg.cg_niblk = 0;
364                 acg.cg_initediblk = 0;
365                 acg.cg_old_btotoff = start;
366                 acg.cg_old_boff = acg.cg_old_btotoff +
367                     sblock.fs_old_cpg * sizeof(int32_t);
368                 acg.cg_iusedoff = acg.cg_old_boff +
369                     sblock.fs_old_cpg * sizeof(u_int16_t);
370         }
371         acg.cg_freeoff = acg.cg_iusedoff + howmany(sblock.fs_ipg, CHAR_BIT);
372         acg.cg_nextfreeoff = acg.cg_freeoff + howmany(sblock.fs_fpg, CHAR_BIT);
373         if (sblock.fs_contigsumsize > 0) {
374                 acg.cg_clustersumoff =
375                     roundup(acg.cg_nextfreeoff, sizeof(u_int32_t));
376                 acg.cg_clustersumoff -= sizeof(u_int32_t);
377                 acg.cg_clusteroff = acg.cg_clustersumoff +
378                     (sblock.fs_contigsumsize + 1) * sizeof(u_int32_t);
379                 acg.cg_nextfreeoff = acg.cg_clusteroff +
380                     howmany(fragstoblks(&sblock, sblock.fs_fpg), CHAR_BIT);
381         }
382         if (acg.cg_nextfreeoff > (unsigned)sblock.fs_cgsize) {
383                 /*
384                  * This should never happen as we would have had that panic
385                  * already on file system creation
386                  */
387                 errx(37, "panic: cylinder group too big");
388         }
389         acg.cg_cs.cs_nifree += sblock.fs_ipg;
390         if (cylno == 0)
391                 for (i = 0; i < ROOTINO; i++) {
392                         setbit(cg_inosused(&acg), i);
393                         acg.cg_cs.cs_nifree--;
394                 }
395         /*
396          * For the old file system, we have to initialize all the inodes.
397          */
398         if (sblock.fs_magic == FS_UFS1_MAGIC) {
399                 bzero(iobuf, sblock.fs_bsize);
400                 for (i = 0; i < sblock.fs_ipg / INOPF(&sblock);
401                     i += sblock.fs_frag) {
402 #ifdef FSIRAND
403                         dp1 = (struct ufs1_dinode *)(void *)iobuf;
404                         for (j = 0; j < INOPB(&sblock); j++) {
405                                 dp1->di_gen = random();
406                                 dp1++;
407                         }
408 #endif
409                         wtfs(fsbtodb(&sblock, cgimin(&sblock, cylno) + i),
410                             sblock.fs_bsize, iobuf, fso, Nflag);
411                 }
412         }
413         if (cylno > 0) {
414                 /*
415                  * In cylno 0, beginning space is reserved
416                  * for boot and super blocks.
417                  */
418                 for (d = 0; d < dlower; d += sblock.fs_frag) {
419                         blkno = d / sblock.fs_frag;
420                         setblock(&sblock, cg_blksfree(&acg), blkno);
421                         if (sblock.fs_contigsumsize > 0)
422                                 setbit(cg_clustersfree(&acg), blkno);
423                         acg.cg_cs.cs_nbfree++;
424                 }
425                 sblock.fs_dsize += dlower;
426         }
427         sblock.fs_dsize += acg.cg_ndblk - dupper;
428         if ((i = dupper % sblock.fs_frag)) {
429                 acg.cg_frsum[sblock.fs_frag - i]++;
430                 for (d = dupper + sblock.fs_frag - i; dupper < d; dupper++) {
431                         setbit(cg_blksfree(&acg), dupper);
432                         acg.cg_cs.cs_nffree++;
433                 }
434         }
435         for (d = dupper; d + sblock.fs_frag <= acg.cg_ndblk;
436             d += sblock.fs_frag) {
437                 blkno = d / sblock.fs_frag;
438                 setblock(&sblock, cg_blksfree(&acg), blkno);
439                 if (sblock.fs_contigsumsize > 0)
440                         setbit(cg_clustersfree(&acg), blkno);
441                 acg.cg_cs.cs_nbfree++;
442         }
443         if (d < acg.cg_ndblk) {
444                 acg.cg_frsum[acg.cg_ndblk - d]++;
445                 for (; d < acg.cg_ndblk; d++) {
446                         setbit(cg_blksfree(&acg), d);
447                         acg.cg_cs.cs_nffree++;
448                 }
449         }
450         if (sblock.fs_contigsumsize > 0) {
451                 int32_t *sump = cg_clustersum(&acg);
452                 u_char *mapp = cg_clustersfree(&acg);
453                 int map = *mapp++;
454                 int bit = 1;
455                 int run = 0;
456
457                 for (i = 0; i < acg.cg_nclusterblks; i++) {
458                         if ((map & bit) != 0)
459                                 run++;
460                         else if (run != 0) {
461                                 if (run > sblock.fs_contigsumsize)
462                                         run = sblock.fs_contigsumsize;
463                                 sump[run]++;
464                                 run = 0;
465                         }
466                         if ((i & (CHAR_BIT - 1)) != CHAR_BIT - 1)
467                                 bit <<= 1;
468                         else {
469                                 map = *mapp++;
470                                 bit = 1;
471                         }
472                 }
473                 if (run != 0) {
474                         if (run > sblock.fs_contigsumsize)
475                                 run = sblock.fs_contigsumsize;
476                         sump[run]++;
477                 }
478         }
479         sblock.fs_cstotal.cs_ndir += acg.cg_cs.cs_ndir;
480         sblock.fs_cstotal.cs_nffree += acg.cg_cs.cs_nffree;
481         sblock.fs_cstotal.cs_nbfree += acg.cg_cs.cs_nbfree;
482         sblock.fs_cstotal.cs_nifree += acg.cg_cs.cs_nifree;
483         *cs = acg.cg_cs;
484
485         memcpy(iobuf, &acg, sblock.fs_cgsize);
486         memset(iobuf + sblock.fs_cgsize, '\0',
487             sblock.fs_bsize * 3 - sblock.fs_cgsize);
488
489         wtfs(fsbtodb(&sblock, cgtod(&sblock, cylno)),
490             sblock.fs_bsize * 3, iobuf, fso, Nflag);
491         DBG_DUMP_CG(&sblock, "new cg", &acg);
492
493         DBG_LEAVE;
494         return;
495 }
496
497 /*
498  * Here we add or subtract (sign +1/-1) the available fragments in a given
499  * block to or from the fragment statistics. By subtracting before and adding
500  * after an operation on the free frag map we can easy update the fragment
501  * statistic, which seems to be otherwise a rather complex operation.
502  */
503 static void
504 frag_adjust(ufs2_daddr_t frag, int sign)
505 {
506         DBG_FUNC("frag_adjust")
507         int fragsize;
508         int f;
509
510         DBG_ENTER;
511
512         fragsize=0;
513         /*
514          * Here frag only needs to point to any fragment in the block we want
515          * to examine.
516          */
517         for (f = rounddown(frag, sblock.fs_frag);
518             f < roundup(frag + 1, sblock.fs_frag); f++) {
519                 /*
520                  * Count contiguous free fragments.
521                  */
522                 if (isset(cg_blksfree(&acg), f)) {
523                         fragsize++;
524                 } else {
525                         if (fragsize && fragsize < sblock.fs_frag) {
526                                 /*
527                                  * We found something in between.
528                                  */
529                                 acg.cg_frsum[fragsize]+=sign;
530                                 DBG_PRINT2("frag_adjust [%d]+=%d\n",
531                                     fragsize, sign);
532                         }
533                         fragsize = 0;
534                 }
535         }
536         if (fragsize && fragsize < sblock.fs_frag) {
537                 /*
538                  * We found something.
539                  */
540                 acg.cg_frsum[fragsize] += sign;
541                 DBG_PRINT2("frag_adjust [%d]+=%d\n", fragsize, sign);
542         }
543         DBG_PRINT2("frag_adjust [[%d]]+=%d\n", fragsize, sign);
544
545         DBG_LEAVE;
546         return;
547 }
548
549 /*
550  * Here we do all needed work for the former last cylinder group. It has to be
551  * changed in any case, even if the file system ended exactly on the end of
552  * this group, as there is some slightly inconsistent handling of the number
553  * of cylinders in the cylinder group. We start again by reading the cylinder
554  * group from disk. If the last block was not fully available, we first handle
555  * the missing fragments, then we handle all new full blocks in that file
556  * system and finally we handle the new last fragmented block in the file
557  * system.  We again have to handle the fragment statistics rotational layout
558  * tables and cluster summary during all those operations.
559  */
560 static void
561 updjcg(int cylno, time_t modtime, int fsi, int fso, unsigned int Nflag)
562 {
563         DBG_FUNC("updjcg")
564         ufs2_daddr_t cbase, dmax, dupper;
565         struct csum *cs;
566         int i, k;
567         int j = 0;
568
569         DBG_ENTER;
570
571         /*
572          * Read the former last (joining) cylinder group from disk, and make
573          * a copy.
574          */
575         rdfs(fsbtodb(&osblock, cgtod(&osblock, cylno)),
576             (size_t)osblock.fs_cgsize, (void *)&aocg, fsi);
577         DBG_PRINT0("jcg read\n");
578         DBG_DUMP_CG(&sblock, "old joining cg", &aocg);
579
580         memcpy((void *)&cgun1, (void *)&cgun2, sizeof(cgun2));
581
582         /*
583          * If the cylinder group had already its new final size almost
584          * nothing is to be done ... except:
585          * For some reason the value of cg_ncyl in the last cylinder group has
586          * to be zero instead of fs_cpg. As this is now no longer the last
587          * cylinder group we have to change that value now to fs_cpg.
588          */
589
590         if (cgbase(&osblock, cylno + 1) == osblock.fs_size) {
591                 if (sblock.fs_magic == FS_UFS1_MAGIC)
592                         acg.cg_old_ncyl=sblock.fs_old_cpg;
593
594                 wtfs(fsbtodb(&sblock, cgtod(&sblock, cylno)),
595                     (size_t)sblock.fs_cgsize, (void *)&acg, fso, Nflag);
596                 DBG_PRINT0("jcg written\n");
597                 DBG_DUMP_CG(&sblock, "new joining cg", &acg);
598
599                 DBG_LEAVE;
600                 return;
601         }
602
603         /*
604          * Set up some variables needed later.
605          */
606         cbase = cgbase(&sblock, cylno);
607         dmax = cbase + sblock.fs_fpg;
608         if (dmax > sblock.fs_size)
609                 dmax = sblock.fs_size;
610         dupper = cgdmin(&sblock, cylno) - cbase;
611         if (cylno == 0) /* XXX fscs may be relocated */
612                 dupper += howmany(sblock.fs_cssize, sblock.fs_fsize);
613
614         /*
615          * Set pointer to the cylinder summary for our cylinder group.
616          */
617         cs = fscs + cylno;
618
619         /*
620          * Touch the cylinder group, update all fields in the cylinder group as
621          * needed, update the free space in the superblock.
622          */
623         acg.cg_time = modtime;
624         if ((unsigned)cylno == sblock.fs_ncg - 1) {
625                 /*
626                  * This is still the last cylinder group.
627                  */
628                 if (sblock.fs_magic == FS_UFS1_MAGIC)
629                         acg.cg_old_ncyl =
630                             sblock.fs_old_ncyl % sblock.fs_old_cpg;
631         } else {
632                 acg.cg_old_ncyl = sblock.fs_old_cpg;
633         }
634         DBG_PRINT2("jcg dbg: %d %u", cylno, sblock.fs_ncg);
635 #ifdef FS_DEBUG
636         if (sblock.fs_magic == FS_UFS1_MAGIC)
637                 DBG_PRINT2("%d %u", acg.cg_old_ncyl, sblock.fs_old_cpg);
638 #endif
639         DBG_PRINT0("\n");
640         acg.cg_ndblk = dmax - cbase;
641         sblock.fs_dsize += acg.cg_ndblk - aocg.cg_ndblk;
642         if (sblock.fs_contigsumsize > 0)
643                 acg.cg_nclusterblks = acg.cg_ndblk / sblock.fs_frag;
644
645         /*
646          * Now we have to update the free fragment bitmap for our new free
647          * space.  There again we have to handle the fragmentation and also
648          * the rotational layout tables and the cluster summary.  This is
649          * also done per fragment for the first new block if the old file
650          * system end was not on a block boundary, per fragment for the new
651          * last block if the new file system end is not on a block boundary,
652          * and per block for all space in between.
653          *
654          * Handle the first new block here if it was partially available
655          * before.
656          */
657         if (osblock.fs_size % sblock.fs_frag) {
658                 if (roundup(osblock.fs_size, sblock.fs_frag) <=
659                     sblock.fs_size) {
660                         /*
661                          * The new space is enough to fill at least this
662                          * block
663                          */
664                         j = 0;
665                         for (i = roundup(osblock.fs_size - cbase,
666                             sblock.fs_frag) - 1; i >= osblock.fs_size - cbase;
667                             i--) {
668                                 setbit(cg_blksfree(&acg), i);
669                                 acg.cg_cs.cs_nffree++;
670                                 j++;
671                         }
672
673                         /*
674                          * Check if the fragment just created could join an
675                          * already existing fragment at the former end of the
676                          * file system.
677                          */
678                         if (isblock(&sblock, cg_blksfree(&acg),
679                             ((osblock.fs_size - cgbase(&sblock, cylno)) /
680                              sblock.fs_frag))) {
681                                 /*
682                                  * The block is now completely available.
683                                  */
684                                 DBG_PRINT0("block was\n");
685                                 acg.cg_frsum[osblock.fs_size % sblock.fs_frag]--;
686                                 acg.cg_cs.cs_nbfree++;
687                                 acg.cg_cs.cs_nffree -= sblock.fs_frag;
688                                 k = rounddown(osblock.fs_size - cbase,
689                                     sblock.fs_frag);
690                                 updclst((osblock.fs_size - cbase) /
691                                     sblock.fs_frag);
692                         } else {
693                                 /*
694                                  * Lets rejoin a possible partially growed
695                                  * fragment.
696                                  */
697                                 k = 0;
698                                 while (isset(cg_blksfree(&acg), i) &&
699                                     (i >= rounddown(osblock.fs_size - cbase,
700                                     sblock.fs_frag))) {
701                                         i--;
702                                         k++;
703                                 }
704                                 if (k)
705                                         acg.cg_frsum[k]--;
706                                 acg.cg_frsum[k + j]++;
707                         }
708                 } else {
709                         /*
710                          * We only grow by some fragments within this last
711                          * block.
712                          */
713                         for (i = sblock.fs_size - cbase - 1;
714                             i >= osblock.fs_size - cbase; i--) {
715                                 setbit(cg_blksfree(&acg), i);
716                                 acg.cg_cs.cs_nffree++;
717                                 j++;
718                         }
719                         /*
720                          * Lets rejoin a possible partially growed fragment.
721                          */
722                         k = 0;
723                         while (isset(cg_blksfree(&acg), i) &&
724                             (i >= rounddown(osblock.fs_size - cbase,
725                             sblock.fs_frag))) {
726                                 i--;
727                                 k++;
728                         }
729                         if (k)
730                                 acg.cg_frsum[k]--;
731                         acg.cg_frsum[k + j]++;
732                 }
733         }
734
735         /*
736          * Handle all new complete blocks here.
737          */
738         for (i = roundup(osblock.fs_size - cbase, sblock.fs_frag);
739             i + sblock.fs_frag <= dmax - cbase; /* XXX <= or only < ? */
740             i += sblock.fs_frag) {
741                 j = i / sblock.fs_frag;
742                 setblock(&sblock, cg_blksfree(&acg), j);
743                 updclst(j);
744                 acg.cg_cs.cs_nbfree++;
745         }
746
747         /*
748          * Handle the last new block if there are stll some new fragments left.
749          * Here we don't have to bother about the cluster summary or the even
750          * the rotational layout table.
751          */
752         if (i < (dmax - cbase)) {
753                 acg.cg_frsum[dmax - cbase - i]++;
754                 for (; i < dmax - cbase; i++) {
755                         setbit(cg_blksfree(&acg), i);
756                         acg.cg_cs.cs_nffree++;
757                 }
758         }
759
760         sblock.fs_cstotal.cs_nffree +=
761             (acg.cg_cs.cs_nffree - aocg.cg_cs.cs_nffree);
762         sblock.fs_cstotal.cs_nbfree +=
763             (acg.cg_cs.cs_nbfree - aocg.cg_cs.cs_nbfree);
764         /*
765          * The following statistics are not changed here:
766          *     sblock.fs_cstotal.cs_ndir
767          *     sblock.fs_cstotal.cs_nifree
768          * As the statistics for this cylinder group are ready, copy it to
769          * the summary information array.
770          */
771         *cs = acg.cg_cs;
772
773         /*
774          * Write the updated "joining" cylinder group back to disk.
775          */
776         wtfs(fsbtodb(&sblock, cgtod(&sblock, cylno)), (size_t)sblock.fs_cgsize,
777             (void *)&acg, fso, Nflag);
778         DBG_PRINT0("jcg written\n");
779         DBG_DUMP_CG(&sblock, "new joining cg", &acg);
780
781         DBG_LEAVE;
782         return;
783 }
784
785 /*
786  * Here we update the location of the cylinder summary. We have two possible
787  * ways of growing the cylinder summary.
788  * (1)  We can try to grow the summary in the current location, and relocate
789  *      possibly used blocks within the current cylinder group.
790  * (2)  Alternatively we can relocate the whole cylinder summary to the first
791  *      new completely empty cylinder group. Once the cylinder summary is no
792  *      longer in the beginning of the first cylinder group you should never
793  *      use a version of fsck which is not aware of the possibility to have
794  *      this structure in a non standard place.
795  * Option (2) is considered to be less intrusive to the structure of the file-
796  * system, so that's the one being used.
797  */
798 static void
799 updcsloc(time_t modtime, int fsi, int fso, unsigned int Nflag)
800 {
801         DBG_FUNC("updcsloc")
802         struct csum *cs;
803         int ocscg, ncscg;
804         int blocks;
805         ufs2_daddr_t d;
806         int lcs = 0;
807         int block;
808
809         DBG_ENTER;
810
811         if (howmany(sblock.fs_cssize, sblock.fs_fsize) ==
812             howmany(osblock.fs_cssize, osblock.fs_fsize)) {
813                 /*
814                  * No new fragment needed.
815                  */
816                 DBG_LEAVE;
817                 return;
818         }
819         ocscg = dtog(&osblock, osblock.fs_csaddr);
820         cs = fscs + ocscg;
821         blocks = 1 + howmany(sblock.fs_cssize, sblock.fs_bsize) -
822             howmany(osblock.fs_cssize, osblock.fs_bsize);
823
824         /*
825          * Read original cylinder group from disk, and make a copy.
826          * XXX  If Nflag is set in some very rare cases we now miss
827          *      some changes done in updjcg by reading the unmodified
828          *      block from disk.
829          */
830         rdfs(fsbtodb(&osblock, cgtod(&osblock, ocscg)),
831             (size_t)osblock.fs_cgsize, (void *)&aocg, fsi);
832         DBG_PRINT0("oscg read\n");
833         DBG_DUMP_CG(&sblock, "old summary cg", &aocg);
834
835         memcpy((void *)&cgun1, (void *)&cgun2, sizeof(cgun2));
836
837         /*
838          * Touch the cylinder group, set up local variables needed later
839          * and update the superblock.
840          */
841         acg.cg_time = modtime;
842
843         /*
844          * XXX  In the case of having active snapshots we may need much more
845          *      blocks for the copy on write. We need each block twice, and
846          *      also up to 8*3 blocks for indirect blocks for all possible
847          *      references.
848          */
849         /*
850          * There is not enough space in the old cylinder group to
851          * relocate all blocks as needed, so we relocate the whole
852          * cylinder group summary to a new group. We try to use the
853          * first complete new cylinder group just created. Within the
854          * cylinder group we align the area immediately after the
855          * cylinder group information location in order to be as
856          * close as possible to the original implementation of ffs.
857          *
858          * First we have to make sure we'll find enough space in the
859          * new cylinder group. If not, then we currently give up.
860          * We start with freeing everything which was used by the
861          * fragments of the old cylinder summary in the current group.
862          * Now we write back the group meta data, read in the needed
863          * meta data from the new cylinder group, and start allocating
864          * within that group. Here we can assume, the group to be
865          * completely empty. Which makes the handling of fragments and
866          * clusters a lot easier.
867          */
868         DBG_TRC;
869         if (sblock.fs_ncg - osblock.fs_ncg < 2)
870                 errx(2, "panic: not enough space");
871
872         /*
873          * Point "d" to the first fragment not used by the cylinder
874          * summary.
875          */
876         d = osblock.fs_csaddr + (osblock.fs_cssize / osblock.fs_fsize);
877
878         /*
879          * Set up last cluster size ("lcs") already here. Calculate
880          * the size for the trailing cluster just behind where "d"
881          * points to.
882          */
883         if (sblock.fs_contigsumsize > 0) {
884                 for (block = howmany(d % sblock.fs_fpg, sblock.fs_frag),
885                     lcs = 0; lcs < sblock.fs_contigsumsize;
886                     block++, lcs++) {
887                         if (isclr(cg_clustersfree(&acg), block))
888                                 break;
889                 }
890         }
891
892         /*
893          * Point "d" to the last frag used by the cylinder summary.
894          */
895         d--;
896
897         DBG_PRINT1("d=%jd\n", (intmax_t)d);
898         if ((d + 1) % sblock.fs_frag) {
899                 /*
900                  * The end of the cylinder summary is not a complete
901                  * block.
902                  */
903                 DBG_TRC;
904                 frag_adjust(d % sblock.fs_fpg, -1);
905                 for (; (d + 1) % sblock.fs_frag; d--) {
906                         DBG_PRINT1("d=%jd\n", (intmax_t)d);
907                         setbit(cg_blksfree(&acg), d % sblock.fs_fpg);
908                         acg.cg_cs.cs_nffree++;
909                         sblock.fs_cstotal.cs_nffree++;
910                 }
911                 /*
912                  * Point "d" to the last fragment of the last
913                  * (incomplete) block of the cylinder summary.
914                  */
915                 d++;
916                 frag_adjust(d%sblock.fs_fpg, 1);
917
918                 if (isblock(&sblock, cg_blksfree(&acg),
919                     (d % sblock.fs_fpg) / sblock.fs_frag)) {
920                         DBG_PRINT1("d=%jd\n", (intmax_t)d);
921                         acg.cg_cs.cs_nffree -= sblock.fs_frag;
922                         acg.cg_cs.cs_nbfree++;
923                         sblock.fs_cstotal.cs_nffree -= sblock.fs_frag;
924                         sblock.fs_cstotal.cs_nbfree++;
925                         if (sblock.fs_contigsumsize > 0) {
926                                 setbit(cg_clustersfree(&acg),
927                                     (d % sblock.fs_fpg) /
928                                     sblock.fs_frag);
929                                 if (lcs < sblock.fs_contigsumsize) {
930                                         if (lcs)
931                                                 cg_clustersum(&acg)[lcs]--;
932                                         lcs++;
933                                         cg_clustersum(&acg)[lcs]++;
934                                 }
935                         }
936                 }
937                 /*
938                  * Point "d" to the first fragment of the block before
939                  * the last incomplete block.
940                  */
941                 d--;
942         }
943
944         DBG_PRINT1("d=%jd\n", (intmax_t)d);
945         for (d = rounddown(d, sblock.fs_frag); d >= osblock.fs_csaddr;
946             d -= sblock.fs_frag) {
947                 DBG_TRC;
948                 DBG_PRINT1("d=%jd\n", (intmax_t)d);
949                 setblock(&sblock, cg_blksfree(&acg),
950                     (d % sblock.fs_fpg) / sblock.fs_frag);
951                 acg.cg_cs.cs_nbfree++;
952                 sblock.fs_cstotal.cs_nbfree++;
953                 if (sblock.fs_contigsumsize > 0) {
954                         setbit(cg_clustersfree(&acg),
955                             (d % sblock.fs_fpg) / sblock.fs_frag);
956                         /*
957                          * The last cluster size is already set up.
958                          */
959                         if (lcs < sblock.fs_contigsumsize) {
960                                 if (lcs)
961                                         cg_clustersum(&acg)[lcs]--;
962                                 lcs++;
963                                 cg_clustersum(&acg)[lcs]++;
964                         }
965                 }
966         }
967         *cs = acg.cg_cs;
968
969         /*
970          * Now write the former cylinder group containing the cylinder
971          * summary back to disk.
972          */
973         wtfs(fsbtodb(&sblock, cgtod(&sblock, ocscg)),
974             (size_t)sblock.fs_cgsize, (void *)&acg, fso, Nflag);
975         DBG_PRINT0("oscg written\n");
976         DBG_DUMP_CG(&sblock, "old summary cg", &acg);
977
978         /*
979          * Find the beginning of the new cylinder group containing the
980          * cylinder summary.
981          */
982         sblock.fs_csaddr = cgdmin(&sblock, osblock.fs_ncg);
983         ncscg = dtog(&sblock, sblock.fs_csaddr);
984         cs = fscs + ncscg;
985
986         /*
987          * If Nflag is specified, we would now read random data instead
988          * of an empty cg structure from disk. So we can't simulate that
989          * part for now.
990          */
991         if (Nflag) {
992                 DBG_PRINT0("nscg update skipped\n");
993                 DBG_LEAVE;
994                 return;
995         }
996
997         /*
998          * Read the future cylinder group containing the cylinder
999          * summary from disk, and make a copy.
1000          */
1001         rdfs(fsbtodb(&sblock, cgtod(&sblock, ncscg)),
1002             (size_t)sblock.fs_cgsize, (void *)&aocg, fsi);
1003         DBG_PRINT0("nscg read\n");
1004         DBG_DUMP_CG(&sblock, "new summary cg", &aocg);
1005
1006         memcpy((void *)&cgun1, (void *)&cgun2, sizeof(cgun2));
1007
1008         /*
1009          * Allocate all complete blocks used by the new cylinder
1010          * summary.
1011          */
1012         for (d = sblock.fs_csaddr; d + sblock.fs_frag <=
1013             sblock.fs_csaddr + (sblock.fs_cssize / sblock.fs_fsize);
1014             d += sblock.fs_frag) {
1015                 clrblock(&sblock, cg_blksfree(&acg),
1016                     (d % sblock.fs_fpg) / sblock.fs_frag);
1017                 acg.cg_cs.cs_nbfree--;
1018                 sblock.fs_cstotal.cs_nbfree--;
1019                 if (sblock.fs_contigsumsize > 0) {
1020                         clrbit(cg_clustersfree(&acg),
1021                             (d % sblock.fs_fpg) / sblock.fs_frag);
1022                 }
1023         }
1024
1025         /*
1026          * Allocate all fragments used by the cylinder summary in the
1027          * last block.
1028          */
1029         if (d <
1030             sblock.fs_csaddr + (sblock.fs_cssize / sblock.fs_fsize)) {
1031                 for (; d - sblock.fs_csaddr <
1032                     sblock.fs_cssize/sblock.fs_fsize; d++) {
1033                         clrbit(cg_blksfree(&acg), d % sblock.fs_fpg);
1034                         acg.cg_cs.cs_nffree--;
1035                         sblock.fs_cstotal.cs_nffree--;
1036                 }
1037                 acg.cg_cs.cs_nbfree--;
1038                 acg.cg_cs.cs_nffree += sblock.fs_frag;
1039                 sblock.fs_cstotal.cs_nbfree--;
1040                 sblock.fs_cstotal.cs_nffree += sblock.fs_frag;
1041                 if (sblock.fs_contigsumsize > 0)
1042                         clrbit(cg_clustersfree(&acg),
1043                             (d % sblock.fs_fpg) / sblock.fs_frag);
1044
1045                 frag_adjust(d % sblock.fs_fpg, 1);
1046         }
1047         /*
1048          * XXX  Handle the cluster statistics here in the case this
1049          *      cylinder group is now almost full, and the remaining
1050          *      space is less then the maximum cluster size. This is
1051          *      probably not needed, as you would hardly find a file
1052          *      system which has only MAXCSBUFS+FS_MAXCONTIG of free
1053          *      space right behind the cylinder group information in
1054          *      any new cylinder group.
1055          */
1056
1057         /*
1058          * Update our statistics in the cylinder summary.
1059          */
1060         *cs = acg.cg_cs;
1061
1062         /*
1063          * Write the new cylinder group containing the cylinder summary
1064          * back to disk.
1065          */
1066         wtfs(fsbtodb(&sblock, cgtod(&sblock, ncscg)),
1067             (size_t)sblock.fs_cgsize, (void *)&acg, fso, Nflag);
1068         DBG_PRINT0("nscg written\n");
1069         DBG_DUMP_CG(&sblock, "new summary cg", &acg);
1070
1071         DBG_LEAVE;
1072         return;
1073 }
1074
1075 /*
1076  * Here we read some block(s) from disk.
1077  */
1078 static void
1079 rdfs(ufs2_daddr_t bno, size_t size, void *bf, int fsi)
1080 {
1081         DBG_FUNC("rdfs")
1082         ssize_t n;
1083
1084         DBG_ENTER;
1085
1086         if (bno < 0)
1087                 err(32, "rdfs: attempting to read negative block number");
1088         if (lseek(fsi, (off_t)bno * DEV_BSIZE, 0) < 0)
1089                 err(33, "rdfs: seek error: %jd", (intmax_t)bno);
1090         n = read(fsi, bf, size);
1091         if (n != (ssize_t)size)
1092                 err(34, "rdfs: read error: %jd", (intmax_t)bno);
1093
1094         DBG_LEAVE;
1095         return;
1096 }
1097
1098 /*
1099  * Here we write some block(s) to disk.
1100  */
1101 static void
1102 wtfs(ufs2_daddr_t bno, size_t size, void *bf, int fso, unsigned int Nflag)
1103 {
1104         DBG_FUNC("wtfs")
1105         ssize_t n;
1106
1107         DBG_ENTER;
1108
1109         if (Nflag) {
1110                 DBG_LEAVE;
1111                 return;
1112         }
1113         if (lseek(fso, (off_t)bno * DEV_BSIZE, SEEK_SET) < 0)
1114                 err(35, "wtfs: seek error: %ld", (long)bno);
1115         n = write(fso, bf, size);
1116         if (n != (ssize_t)size)
1117                 err(36, "wtfs: write error: %ld", (long)bno);
1118
1119         DBG_LEAVE;
1120         return;
1121 }
1122
1123 /*
1124  * Here we check if all frags of a block are free. For more details again
1125  * please see the source of newfs(8), as this function is taken over almost
1126  * unchanged.
1127  */
1128 static int
1129 isblock(struct fs *fs, unsigned char *cp, int h)
1130 {
1131         DBG_FUNC("isblock")
1132         unsigned char mask;
1133
1134         DBG_ENTER;
1135
1136         switch (fs->fs_frag) {
1137         case 8:
1138                 DBG_LEAVE;
1139                 return (cp[h] == 0xff);
1140         case 4:
1141                 mask = 0x0f << ((h & 0x1) << 2);
1142                 DBG_LEAVE;
1143                 return ((cp[h >> 1] & mask) == mask);
1144         case 2:
1145                 mask = 0x03 << ((h & 0x3) << 1);
1146                 DBG_LEAVE;
1147                 return ((cp[h >> 2] & mask) == mask);
1148         case 1:
1149                 mask = 0x01 << (h & 0x7);
1150                 DBG_LEAVE;
1151                 return ((cp[h >> 3] & mask) == mask);
1152         default:
1153                 fprintf(stderr, "isblock bad fs_frag %d\n", fs->fs_frag);
1154                 DBG_LEAVE;
1155                 return (0);
1156         }
1157 }
1158
1159 /*
1160  * Here we allocate a complete block in the block map. For more details again
1161  * please see the source of newfs(8), as this function is taken over almost
1162  * unchanged.
1163  */
1164 static void
1165 clrblock(struct fs *fs, unsigned char *cp, int h)
1166 {
1167         DBG_FUNC("clrblock")
1168
1169         DBG_ENTER;
1170
1171         switch ((fs)->fs_frag) {
1172         case 8:
1173                 cp[h] = 0;
1174                 break;
1175         case 4:
1176                 cp[h >> 1] &= ~(0x0f << ((h & 0x1) << 2));
1177                 break;
1178         case 2:
1179                 cp[h >> 2] &= ~(0x03 << ((h & 0x3) << 1));
1180                 break;
1181         case 1:
1182                 cp[h >> 3] &= ~(0x01 << (h & 0x7));
1183                 break;
1184         default:
1185                 warnx("clrblock bad fs_frag %d", fs->fs_frag);
1186                 break;
1187         }
1188
1189         DBG_LEAVE;
1190         return;
1191 }
1192
1193 /*
1194  * Here we free a complete block in the free block map. For more details again
1195  * please see the source of newfs(8), as this function is taken over almost
1196  * unchanged.
1197  */
1198 static void
1199 setblock(struct fs *fs, unsigned char *cp, int h)
1200 {
1201         DBG_FUNC("setblock")
1202
1203         DBG_ENTER;
1204
1205         switch (fs->fs_frag) {
1206         case 8:
1207                 cp[h] = 0xff;
1208                 break;
1209         case 4:
1210                 cp[h >> 1] |= (0x0f << ((h & 0x1) << 2));
1211                 break;
1212         case 2:
1213                 cp[h >> 2] |= (0x03 << ((h & 0x3) << 1));
1214                 break;
1215         case 1:
1216                 cp[h >> 3] |= (0x01 << (h & 0x7));
1217                 break;
1218         default:
1219                 warnx("setblock bad fs_frag %d", fs->fs_frag);
1220                 break;
1221         }
1222
1223         DBG_LEAVE;
1224         return;
1225 }
1226
1227 /*
1228  * Figure out how many lines our current terminal has. For more details again
1229  * please see the source of newfs(8), as this function is taken over almost
1230  * unchanged.
1231  */
1232 static int
1233 charsperline(void)
1234 {
1235         DBG_FUNC("charsperline")
1236         int columns;
1237         char *cp;
1238         struct winsize ws;
1239
1240         DBG_ENTER;
1241
1242         columns = 0;
1243         if (ioctl(0, TIOCGWINSZ, &ws) != -1)
1244                 columns = ws.ws_col;
1245         if (columns == 0 && (cp = getenv("COLUMNS")))
1246                 columns = atoi(cp);
1247         if (columns == 0)
1248                 columns = 80;   /* last resort */
1249
1250         DBG_LEAVE;
1251         return columns;
1252 }
1253
1254 /*
1255  * Get the size of the partition.
1256  */
1257 static void
1258 get_dev_size(int fd, int *size)
1259 {
1260         int sectorsize;
1261         off_t mediasize;
1262
1263         if (ioctl(fd, DIOCGSECTORSIZE, &sectorsize) == -1)
1264                 err(1,"DIOCGSECTORSIZE");
1265         if (ioctl(fd, DIOCGMEDIASIZE, &mediasize) == -1)
1266                 err(1,"DIOCGMEDIASIZE");
1267
1268         if (sectorsize <= 0)
1269                 errx(1, "bogus sectorsize: %d", sectorsize);
1270
1271         *size = mediasize / sectorsize;
1272 }
1273
1274 /*
1275  * growfs(8) is a utility which allows to increase the size of an existing
1276  * ufs file system. Currently this can only be done on unmounted file system.
1277  * It recognizes some command line options to specify the new desired size,
1278  * and it does some basic checkings. The old file system size is determined
1279  * and after some more checks like we can really access the new last block
1280  * on the disk etc. we calculate the new parameters for the superblock. After
1281  * having done this we just call growfs() which will do the work.
1282  * We still have to provide support for snapshots. Therefore we first have to
1283  * understand what data structures are always replicated in the snapshot on
1284  * creation, for all other blocks we touch during our procedure, we have to
1285  * keep the old blocks unchanged somewhere available for the snapshots. If we
1286  * are lucky, then we only have to handle our blocks to be relocated in that
1287  * way.
1288  * Also we have to consider in what order we actually update the critical
1289  * data structures of the file system to make sure, that in case of a disaster
1290  * fsck(8) is still able to restore any lost data.
1291  * The foreseen last step then will be to provide for growing even mounted
1292  * file systems. There we have to extend the mount() system call to provide
1293  * userland access to the file system locking facility.
1294  */
1295 int
1296 main(int argc, char **argv)
1297 {
1298         DBG_FUNC("main")
1299         char *device, *special;
1300         int ch;
1301         unsigned int size = 0;
1302         size_t len;
1303         unsigned int Nflag = 0;
1304         int ExpertFlag = 0;
1305         struct stat st;
1306         int i, fsi, fso;
1307         u_int32_t p_size;
1308         char reply[5];
1309 #ifdef FSMAXSNAP
1310         int j;
1311 #endif /* FSMAXSNAP */
1312
1313         DBG_ENTER;
1314
1315         while ((ch = getopt(argc, argv, "Ns:vy")) != -1) {
1316                 switch(ch) {
1317                 case 'N':
1318                         Nflag = 1;
1319                         break;
1320                 case 's':
1321                         size = (size_t)atol(optarg);
1322                         if (size < 1)
1323                                 usage();
1324                         break;
1325                 case 'v': /* for compatibility to newfs */
1326                         break;
1327                 case 'y':
1328                         ExpertFlag = 1;
1329                         break;
1330                 case '?':
1331                         /* FALLTHROUGH */
1332                 default:
1333                         usage();
1334                 }
1335         }
1336         argc -= optind;
1337         argv += optind;
1338
1339         if (argc != 1)
1340                 usage();
1341
1342         device = *argv;
1343
1344         /*
1345          * Now try to guess the (raw)device name.
1346          */
1347         if (0 == strrchr(device, '/')) {
1348                 /*
1349                  * No path prefix was given, so try in that order:
1350                  *     /dev/r%s
1351                  *     /dev/%s
1352                  *     /dev/vinum/r%s
1353                  *     /dev/vinum/%s.
1354                  *
1355                  * FreeBSD now doesn't distinguish between raw and block
1356                  * devices any longer, but it should still work this way.
1357                  */
1358                 len = strlen(device) + strlen(_PATH_DEV) + 2 + strlen("vinum/");
1359                 special = (char *)malloc(len);
1360                 if (special == NULL)
1361                         errx(1, "malloc failed");
1362                 snprintf(special, len, "%sr%s", _PATH_DEV, device);
1363                 if (stat(special, &st) == -1) {
1364                         snprintf(special, len, "%s%s", _PATH_DEV, device);
1365                         if (stat(special, &st) == -1) {
1366                                 snprintf(special, len, "%svinum/r%s",
1367                                     _PATH_DEV, device);
1368                                 if (stat(special, &st) == -1) {
1369                                         /* For now this is the 'last resort' */
1370                                         snprintf(special, len, "%svinum/%s",
1371                                             _PATH_DEV, device);
1372                                 }
1373                         }
1374                 }
1375                 device = special;
1376         }
1377
1378         /*
1379          * Try to access our devices for writing ...
1380          */
1381         if (Nflag) {
1382                 fso = -1;
1383         } else {
1384                 fso = open(device, O_WRONLY);
1385                 if (fso < 0)
1386                         err(1, "%s", device);
1387         }
1388
1389         /*
1390          * ... and reading.
1391          */
1392         fsi = open(device, O_RDONLY);
1393         if (fsi < 0)
1394                 err(1, "%s", device);
1395
1396         /*
1397          * Try to guess the slice if not specified. This code should guess
1398          * the right thing and avoid to bother the user with the task
1399          * of specifying the option -v on vinum volumes.
1400          */
1401         get_dev_size(fsi, &p_size);
1402
1403         /*
1404          * Check if that partition is suitable for growing a file system.
1405          */
1406         if (p_size < 1)
1407                 errx(1, "partition is unavailable");
1408
1409         /*
1410          * Read the current superblock, and take a backup.
1411          */
1412         for (i = 0; sblock_try[i] != -1; i++) {
1413                 sblockloc = sblock_try[i] / DEV_BSIZE;
1414                 rdfs(sblockloc, (size_t)SBLOCKSIZE, (void *)&(osblock), fsi);
1415                 if ((osblock.fs_magic == FS_UFS1_MAGIC ||
1416                     (osblock.fs_magic == FS_UFS2_MAGIC &&
1417                     osblock.fs_sblockloc == sblock_try[i])) &&
1418                     osblock.fs_bsize <= MAXBSIZE &&
1419                     osblock.fs_bsize >= (int32_t) sizeof(struct fs))
1420                         break;
1421         }
1422         if (sblock_try[i] == -1)
1423                 errx(1, "superblock not recognized");
1424         memcpy((void *)&fsun1, (void *)&fsun2, sizeof(fsun2));
1425
1426         DBG_OPEN("/tmp/growfs.debug"); /* already here we need a superblock */
1427         DBG_DUMP_FS(&sblock, "old sblock");
1428
1429         /*
1430          * Determine size to grow to. Default to the device size.
1431          */
1432         sblock.fs_size = dbtofsb(&osblock, p_size);
1433         if (size != 0) {
1434                 if (size > p_size)
1435                         errx(1, "there is not enough space (%d < %d)",
1436                             p_size, size);
1437                 sblock.fs_size = dbtofsb(&osblock, size);
1438         }
1439
1440         /*
1441          * Are we really growing ?
1442          */
1443         if (osblock.fs_size >= sblock.fs_size) {
1444                 errx(1, "we are not growing (%jd->%jd)",
1445                     (intmax_t)osblock.fs_size, (intmax_t)sblock.fs_size);
1446         }
1447
1448
1449 #ifdef FSMAXSNAP
1450         /*
1451          * Check if we find an active snapshot.
1452          */
1453         if (ExpertFlag == 0) {
1454                 for (j = 0; j < FSMAXSNAP; j++) {
1455                         if (sblock.fs_snapinum[j]) {
1456                                 errx(1, "active snapshot found in file system; "
1457                                     "please remove all snapshots before "
1458                                     "using growfs");
1459                         }
1460                         if (!sblock.fs_snapinum[j]) /* list is dense */
1461                                 break;
1462                 }
1463         }
1464 #endif
1465
1466         if (ExpertFlag == 0 && Nflag == 0) {
1467                 printf("We strongly recommend you to make a backup "
1468                     "before growing the file system.\n"
1469                     "Did you backup your data (Yes/No)? ");
1470                 fgets(reply, (int)sizeof(reply), stdin);
1471                 if (strcmp(reply, "Yes\n")){
1472                         printf("\nNothing done\n");
1473                         exit (0);
1474                 }
1475         }
1476
1477         printf("New file system size is %jd frags\n", (intmax_t)sblock.fs_size);
1478
1479         /*
1480          * Try to access our new last block in the file system. Even if we
1481          * later on realize we have to abort our operation, on that block
1482          * there should be no data, so we can't destroy something yet.
1483          */
1484         wtfs((ufs2_daddr_t)p_size - 1, (size_t)DEV_BSIZE, (void *)&sblock,
1485             fso, Nflag);
1486
1487         /*
1488          * Now calculate new superblock values and check for reasonable
1489          * bound for new file system size:
1490          *     fs_size:    is derived from user input
1491          *     fs_dsize:   should get updated in the routines creating or
1492          *                 updating the cylinder groups on the fly
1493          *     fs_cstotal: should get updated in the routines creating or
1494          *                 updating the cylinder groups
1495          */
1496
1497         /*
1498          * Update the number of cylinders and cylinder groups in the file system.
1499          */
1500         if (sblock.fs_magic == FS_UFS1_MAGIC) {
1501                 sblock.fs_old_ncyl =
1502                     sblock.fs_size * sblock.fs_old_nspf / sblock.fs_old_spc;
1503                 if (sblock.fs_size * sblock.fs_old_nspf >
1504                     sblock.fs_old_ncyl * sblock.fs_old_spc)
1505                         sblock.fs_old_ncyl++;
1506         }
1507         sblock.fs_ncg = howmany(sblock.fs_size, sblock.fs_fpg);
1508
1509         if (sblock.fs_size % sblock.fs_fpg != 0 &&
1510             sblock.fs_size % sblock.fs_fpg < cgdmin(&sblock, sblock.fs_ncg)) {
1511                 /*
1512                  * The space in the new last cylinder group is too small,
1513                  * so revert back.
1514                  */
1515                 sblock.fs_ncg--;
1516                 if (sblock.fs_magic == FS_UFS1_MAGIC)
1517                         sblock.fs_old_ncyl = sblock.fs_ncg * sblock.fs_old_cpg;
1518                 printf("Warning: %jd sector(s) cannot be allocated.\n",
1519                     (intmax_t)fsbtodb(&sblock, sblock.fs_size % sblock.fs_fpg));
1520                 sblock.fs_size = sblock.fs_ncg * sblock.fs_fpg;
1521         }
1522
1523         /*
1524          * Update the space for the cylinder group summary information in the
1525          * respective cylinder group data area.
1526          */
1527         sblock.fs_cssize =
1528             fragroundup(&sblock, sblock.fs_ncg * sizeof(struct csum));
1529
1530         if (osblock.fs_size >= sblock.fs_size)
1531                 errx(1, "not enough new space");
1532
1533         DBG_PRINT0("sblock calculated\n");
1534
1535         /*
1536          * Ok, everything prepared, so now let's do the tricks.
1537          */
1538         growfs(fsi, fso, Nflag);
1539
1540         close(fsi);
1541         if (fso > -1)
1542                 close(fso);
1543
1544         DBG_CLOSE;
1545
1546         DBG_LEAVE;
1547         return 0;
1548 }
1549
1550 /*
1551  * Dump a line of usage.
1552  */
1553 static void
1554 usage(void)
1555 {
1556         DBG_FUNC("usage")
1557
1558         DBG_ENTER;
1559
1560         fprintf(stderr, "usage: growfs [-Ny] [-s size] special\n");
1561
1562         DBG_LEAVE;
1563         exit(1);
1564 }
1565
1566 /*
1567  * This updates most parameters and the bitmap related to cluster. We have to
1568  * assume that sblock, osblock, acg are set up.
1569  */
1570 static void
1571 updclst(int block)
1572 {
1573         DBG_FUNC("updclst")
1574         static int lcs = 0;
1575
1576         DBG_ENTER;
1577
1578         if (sblock.fs_contigsumsize < 1) /* no clustering */
1579                 return;
1580         /*
1581          * update cluster allocation map
1582          */
1583         setbit(cg_clustersfree(&acg), block);
1584
1585         /*
1586          * update cluster summary table
1587          */
1588         if (!lcs) {
1589                 /*
1590                  * calculate size for the trailing cluster
1591                  */
1592                 for (block--; lcs < sblock.fs_contigsumsize; block--, lcs++ ) {
1593                         if (isclr(cg_clustersfree(&acg), block))
1594                                 break;
1595                 }
1596         }
1597         if (lcs < sblock.fs_contigsumsize) {
1598                 if (lcs)
1599                         cg_clustersum(&acg)[lcs]--;
1600                 lcs++;
1601                 cg_clustersum(&acg)[lcs]++;
1602         }
1603
1604         DBG_LEAVE;
1605         return;
1606 }