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