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