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