xref: /dragonfly/sbin/growfs/growfs.c (revision ed183f8c2f9bb14cbccb8377f3cdd29e0971d8a0)
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  * @(#) Copyright (c) 2000 Christoph Herrmann, Thomas-Henning von Kamptz Copyright (c) 1980, 1989, 1993 The Regents of the University of California. All rights reserved.
41  * $FreeBSD: src/sbin/growfs/growfs.c,v 1.4.2.2 2001/08/14 12:45:11 chm Exp $
42  */
43 
44 /* ********************************************************** INCLUDES ***** */
45 #include <sys/param.h>
46 #include <sys/diskslice.h>
47 #include <sys/ioctl.h>
48 #include <sys/stat.h>
49 
50 #include <stdio.h>
51 #include <paths.h>
52 #include <ctype.h>
53 #include <err.h>
54 #include <fcntl.h>
55 #include <stdlib.h>
56 #include <string.h>
57 #include <unistd.h>
58 #include <vfs/ufs/dinode.h>
59 #include <vfs/ufs/fs.h>
60 
61 #include "debug.h"
62 
63 /* *************************************************** GLOBALS & TYPES ***** */
64 #ifdef FS_DEBUG
65 int       _dbg_lvl_ = (DL_INFO);        /* DL_TRC */
66 #endif /* FS_DEBUG */
67 
68 static union {
69           struct fs fs;
70           char      pad[SBSIZE];
71 } fsun1, fsun2;
72 #define   sblock    fsun1.fs  /* the new superblock */
73 #define   osblock   fsun2.fs  /* the old superblock */
74 
75 static union {
76           struct cg cg;
77           char      pad[MAXBSIZE];
78 } cgun1, cgun2;
79 #define   acg       cgun1.cg  /* a cylinder cgroup (new) */
80 #define   aocg      cgun2.cg  /* an old cylinder group */
81 
82 static char         ablk[MAXBSIZE];               /* a block */
83 static char         i1blk[MAXBSIZE];    /* some indirect blocks */
84 static char         i2blk[MAXBSIZE];
85 static char         i3blk[MAXBSIZE];
86 
87           /* where to write back updated blocks */
88 static daddr_t      in_src, i1_src, i2_src, i3_src;
89 
90           /* what object contains the reference */
91 enum pointer_source {
92           GFS_PS_INODE,
93           GFS_PS_IND_BLK_LVL1,
94           GFS_PS_IND_BLK_LVL2,
95           GFS_PS_IND_BLK_LVL3
96 };
97 
98 static struct csum  *fscs;              /* cylinder summary */
99 
100 static struct ufs1_dinode     zino[MAXBSIZE/sizeof(struct ufs1_dinode)]; /* some inodes */
101 
102 /*
103  * An  array of elements of type struct gfs_bpp describes all blocks  to
104  * be relocated in order to free the space needed for the cylinder group
105  * summary for all cylinder groups located in the first cylinder group.
106  */
107 struct gfs_bpp {
108           daddr_t   old;                /* old block number */
109           daddr_t   new;                /* new block number */
110 #define GFS_FL_FIRST          1
111 #define GFS_FL_LAST 2
112           unsigned int        flags;    /* special handling required */
113           int       found;              /* how many references were updated */
114 };
115 
116 /* ******************************************************** PROTOTYPES ***** */
117 static void         growfs(int, int, unsigned int);
118 static void         rdfs(daddr_t, size_t, void *, int);
119 static void         wtfs(daddr_t, size_t, void *, int, unsigned int);
120 static daddr_t      alloc(void);
121 static int          charsperline(void);
122 static void         usage(void);
123 static int          isblock(struct fs *, unsigned char *, int);
124 static void         clrblock(struct fs *, unsigned char *, int);
125 static void         setblock(struct fs *, unsigned char *, int);
126 static void         initcg(int, time_t, int, unsigned int);
127 static void         updjcg(int, time_t, int, int, unsigned int);
128 static void         updcsloc(time_t, int, int, unsigned int);
129 static struct ufs1_dinode     *ginode(ino_t, int, int);
130 static void         frag_adjust(daddr_t, int);
131 static void         cond_bl_upd(ufs_daddr_t *, struct gfs_bpp *,
132     enum pointer_source, int, unsigned int);
133 static void         updclst(int);
134 static void         updrefs(int, ino_t, struct gfs_bpp *, int, int, unsigned int);
135 
136 /* ************************************************************ growfs ***** */
137 /*
138  * Here  we actually start growing the filesystem. We basically  read  the
139  * cylinder  summary  from the first cylinder group as we want  to  update
140  * this  on  the fly during our various operations. First  we  handle  the
141  * changes in the former last cylinder group. Afterwards we create all new
142  * cylinder  groups.  Now  we handle the  cylinder  group  containing  the
143  * cylinder  summary  which  might result in a  relocation  of  the  whole
144  * structure.  In the end we write back the updated cylinder summary,  the
145  * new superblock, and slightly patched versions of the super block
146  * copies.
147  */
148 static void
growfs(int fsi,int fso,unsigned int Nflag)149 growfs(int fsi, int fso, unsigned int Nflag)
150 {
151           int       i;
152           int       cylno, j;
153           time_t    utime;
154           int       width;
155           char      tmpbuf[100];
156 #ifdef FSIRAND
157           static int          randinit=0;
158 
159           DBG_ENTER;
160 
161           if (!randinit) {
162                     randinit = 1;
163                     srandomdev();
164           }
165 #else /* not FSIRAND */
166 
167           DBG_ENTER;
168 
169 #endif /* FSIRAND */
170           time(&utime);
171 
172           /*
173            * Get the cylinder summary into the memory.
174            */
175           fscs = (struct csum *)calloc((size_t)1, (size_t)sblock.fs_cssize);
176           if(fscs == NULL) {
177                     errx(1, "calloc failed");
178           }
179           for (i = 0; i < osblock.fs_cssize; i += osblock.fs_bsize) {
180                     rdfs(fsbtodb(&osblock, osblock.fs_csaddr +
181                         numfrags(&osblock, i)), (size_t)MIN(osblock.fs_cssize - i,
182                         osblock.fs_bsize), (void *)(((char *)fscs)+i), fsi);
183           }
184 
185 #ifdef FS_DEBUG
186 {
187           struct csum         *dbg_csp;
188           int       dbg_csc;
189           char      dbg_line[80];
190 
191           dbg_csp=fscs;
192           for(dbg_csc=0; dbg_csc<osblock.fs_ncg; dbg_csc++) {
193                     snprintf(dbg_line, sizeof(dbg_line),
194                         "%d. old csum in old location", dbg_csc);
195                     DBG_DUMP_CSUM(&osblock,
196                         dbg_line,
197                         dbg_csp++);
198           }
199 }
200 #endif /* FS_DEBUG */
201           DBG_PRINT0("fscs read\n");
202 
203           /*
204            * Do all needed changes in the former last cylinder group.
205            */
206           updjcg(osblock.fs_ncg-1, utime, fsi, fso, Nflag);
207 
208           /*
209            * Dump out summary information about file system.
210            */
211           printf("growfs:\t%d sectors in %d %s of %d tracks, %d sectors\n",
212               sblock.fs_size * NSPF(&sblock), sblock.fs_ncyl,
213               "cylinders", sblock.fs_ntrak, sblock.fs_nsect);
214 #define B2MBFACTOR (1 / (1024.0 * 1024.0))
215           printf("\t%.1fMB in %d cyl groups (%d c/g, %.2fMB/g, %d i/g)\n",
216               (float)sblock.fs_size * sblock.fs_fsize * B2MBFACTOR,
217               sblock.fs_ncg, sblock.fs_cpg,
218               (float)sblock.fs_fpg * sblock.fs_fsize * B2MBFACTOR,
219               sblock.fs_ipg);
220 #undef B2MBFACTOR
221 
222           /*
223            * Now build the cylinders group blocks and
224            * then print out indices of cylinder groups.
225            */
226           printf("super-block backups (for fsck -b #) at:\n");
227           i = 0;
228           width = charsperline();
229 
230           /*
231            * Iterate for only the new cylinder groups.
232            */
233           for (cylno = osblock.fs_ncg; cylno < sblock.fs_ncg; cylno++) {
234                     initcg(cylno, utime, fso, Nflag);
235                     j = sprintf(tmpbuf, " %d%s",
236                         (int)fsbtodb(&sblock, cgsblock(&sblock, cylno)),
237                         cylno < (sblock.fs_ncg-1) ? "," : "" );
238                     if (i + j >= width) {
239                               printf("\n");
240                               i = 0;
241                     }
242                     i += j;
243                     printf("%s", tmpbuf);
244                     fflush(stdout);
245           }
246           printf("\n");
247 
248           /*
249            * Do all needed changes in the first cylinder group.
250            * allocate blocks in new location
251            */
252           updcsloc(utime, fsi, fso, Nflag);
253 
254           /*
255            * Now write the cylinder summary back to disk.
256            */
257           for (i = 0; i < sblock.fs_cssize; i += sblock.fs_bsize) {
258                     wtfs(fsbtodb(&sblock, sblock.fs_csaddr + numfrags(&sblock, i)),
259                         (size_t)MIN(sblock.fs_cssize - i, sblock.fs_bsize),
260                         (void *)(((char *)fscs) + i), fso, Nflag);
261           }
262           DBG_PRINT0("fscs written\n");
263 
264 #ifdef FS_DEBUG
265 {
266           struct csum         *dbg_csp;
267           int       dbg_csc;
268           char      dbg_line[80];
269 
270           dbg_csp=fscs;
271           for(dbg_csc=0; dbg_csc<sblock.fs_ncg; dbg_csc++) {
272                     snprintf(dbg_line, sizeof(dbg_line),
273                         "%d. new csum in new location", dbg_csc);
274                     DBG_DUMP_CSUM(&sblock,
275                         dbg_line,
276                         dbg_csp++);
277           }
278 }
279 #endif /* FS_DEBUG */
280 
281           /*
282            * Now write the new superblock back to disk.
283            */
284           sblock.fs_time = utime;
285           wtfs((daddr_t)(SBOFF / DEV_BSIZE), (size_t)SBSIZE, &sblock,
286               fso, Nflag);
287           DBG_PRINT0("sblock written\n");
288           DBG_DUMP_FS(&sblock,
289               "new initial sblock");
290 
291           /*
292            * Clean up the dynamic fields in our superblock copies.
293            */
294           sblock.fs_fmod = 0;
295           sblock.fs_clean = 1;
296           sblock.fs_ronly = 0;
297           sblock.fs_cgrotor = 0;
298           sblock.fs_state = 0;
299           memset((void *)&sblock.fs_fsmnt, 0, sizeof(sblock.fs_fsmnt));
300           sblock.fs_flags &= FS_DOSOFTDEP;
301 
302           /*
303            * XXX
304            * The following fields are currently distributed from the  superblock
305            * to the copies:
306            *     fs_minfree
307            *     fs_rotdelay
308            *     fs_maxcontig
309            *     fs_maxbpg
310            *     fs_minfree,
311            *     fs_optim
312            *     fs_flags regarding SOFTPDATES
313            *
314            * We probably should rather change the summary for the cylinder group
315            * statistics here to the value of what would be in there, if the file
316            * system were created initially with the new size. Therefor we  still
317            * need to find an easy way of calculating that.
318            * Possibly we can try to read the first superblock copy and apply the
319            * "diffed" stats between the old and new superblock by still  copying
320            * certain parameters onto that.
321            */
322 
323           /*
324            * Write out the duplicate super blocks.
325            */
326           for (cylno = 0; cylno < sblock.fs_ncg; cylno++) {
327                     wtfs(fsbtodb(&sblock, cgsblock(&sblock, cylno)),
328                         (size_t)SBSIZE, &sblock, fso, Nflag);
329           }
330           DBG_PRINT0("sblock copies written\n");
331           DBG_DUMP_FS(&sblock,
332               "new other sblocks");
333 
334           DBG_LEAVE;
335           return;
336 }
337 
338 /* ************************************************************ initcg ***** */
339 /*
340  * This creates a new cylinder group structure, for more details please  see
341  * the  source of newfs(8), as this function is taken over almost unchanged.
342  * As  this  is  never called for the  first  cylinder  group,  the  special
343  * provisions for that case are removed here.
344  */
345 static void
initcg(int cylno,time_t utime,int fso,unsigned int Nflag)346 initcg(int cylno, time_t utime, int fso, unsigned int Nflag)
347 {
348           daddr_t cbase, d, dlower, dupper, dmax, blkno;
349           int i;
350           struct csum *cs;
351 #ifdef FSIRAND
352           int j;
353 #endif
354 
355           DBG_ENTER;
356 
357           /*
358            * Determine block bounds for cylinder group.
359            */
360           cbase = cgbase(&sblock, cylno);
361           dmax = cbase + sblock.fs_fpg;
362           if (dmax > sblock.fs_size) {
363                     dmax = sblock.fs_size;
364           }
365           dlower = cgsblock(&sblock, cylno) - cbase;
366           dupper = cgdmin(&sblock, cylno) - cbase;
367           if (cylno == 0) { /* XXX fscs may be relocated */
368                     dupper += howmany(sblock.fs_cssize, sblock.fs_fsize);
369           }
370           cs = fscs + cylno;
371           memset(&acg, 0, (size_t)sblock.fs_cgsize);
372           acg.cg_time = utime;
373           acg.cg_magic = CG_MAGIC;
374           acg.cg_cgx = cylno;
375           if (cylno == sblock.fs_ncg - 1) {
376                     acg.cg_ncyl = sblock.fs_ncyl % sblock.fs_cpg;
377           } else {
378                     acg.cg_ncyl = sblock.fs_cpg;
379           }
380           acg.cg_niblk = sblock.fs_ipg;
381           acg.cg_ndblk = dmax - cbase;
382           if (sblock.fs_contigsumsize > 0) {
383                     acg.cg_nclusterblks = acg.cg_ndblk / sblock.fs_frag;
384           }
385           acg.cg_btotoff = &acg.cg_space[0] - (u_char *)(&acg.cg_firstfield);
386           acg.cg_boff = acg.cg_btotoff + sblock.fs_cpg * sizeof(int32_t);
387           acg.cg_iusedoff = acg.cg_boff +
388               sblock.fs_cpg * sblock.fs_nrpos * sizeof(u_int16_t);
389           acg.cg_freeoff = acg.cg_iusedoff + howmany(sblock.fs_ipg, NBBY);
390           if (sblock.fs_contigsumsize <= 0) {
391                     acg.cg_nextfreeoff = acg.cg_freeoff +
392                         howmany(sblock.fs_cpg* sblock.fs_spc/ NSPF(&sblock), NBBY);
393           } else {
394                     acg.cg_clustersumoff = acg.cg_freeoff + howmany
395                         (sblock.fs_cpg * sblock.fs_spc / NSPF(&sblock), NBBY) -
396                         sizeof(u_int32_t);
397                     acg.cg_clustersumoff =
398                         roundup(acg.cg_clustersumoff, sizeof(u_int32_t));
399                     acg.cg_clusteroff = acg.cg_clustersumoff +
400                         (sblock.fs_contigsumsize + 1) * sizeof(u_int32_t);
401                     acg.cg_nextfreeoff = acg.cg_clusteroff + howmany
402                         (sblock.fs_cpg * sblock.fs_spc / NSPB(&sblock), NBBY);
403           }
404           if (acg.cg_nextfreeoff-(intptr_t)(&acg.cg_firstfield) > sblock.fs_cgsize) {
405                     /*
406                      * XXX This should never happen as we would have had that panic
407                      *     already on filesystem creation
408                      */
409                     errx(37, "panic: cylinder group too big");
410           }
411           acg.cg_cs.cs_nifree += sblock.fs_ipg;
412           if (cylno == 0)
413                     for (i = 0; (size_t)i < UFS_ROOTINO; i++) {
414                               setbit(cg_inosused(&acg), i);
415                               acg.cg_cs.cs_nifree--;
416                     }
417           for (i = 0; i < sblock.fs_ipg / INOPF(&sblock); i += sblock.fs_frag) {
418 #ifdef FSIRAND
419                     for (j = 0; j < sblock.fs_bsize / sizeof(struct ufs1_dinode); j++) {
420                               zino[j].di_gen = random();
421                     }
422 #endif
423                     wtfs(fsbtodb(&sblock, cgimin(&sblock, cylno) + i),
424                         (size_t)sblock.fs_bsize, (void *)zino, fso, Nflag);
425           }
426           for (d = 0; d < dlower; 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                     }
432                     acg.cg_cs.cs_nbfree++;
433                     cg_blktot(&acg)[cbtocylno(&sblock, d)]++;
434                     cg_blks(&sblock, &acg, cbtocylno(&sblock, d))
435                         [cbtorpos(&sblock, d)]++;
436           }
437           sblock.fs_dsize += dlower;
438           sblock.fs_dsize += acg.cg_ndblk - dupper;
439           if ((i = dupper % sblock.fs_frag)) {
440                     acg.cg_frsum[sblock.fs_frag - i]++;
441                     for (d = dupper + sblock.fs_frag - i; dupper < d; dupper++) {
442                               setbit(cg_blksfree(&acg), dupper);
443                               acg.cg_cs.cs_nffree++;
444                     }
445           }
446           for (d = dupper; d + sblock.fs_frag <= dmax - cbase; ) {
447                     blkno = d / sblock.fs_frag;
448                     setblock(&sblock, cg_blksfree(&acg), blkno);
449                     if (sblock.fs_contigsumsize > 0) {
450                               setbit(cg_clustersfree(&acg), blkno);
451                     }
452                     acg.cg_cs.cs_nbfree++;
453                     cg_blktot(&acg)[cbtocylno(&sblock, d)]++;
454                     cg_blks(&sblock, &acg, cbtocylno(&sblock, d))
455                         [cbtorpos(&sblock, d)]++;
456                     d += sblock.fs_frag;
457           }
458           if (d < dmax - cbase) {
459                     acg.cg_frsum[dmax - cbase - d]++;
460                     for (; d < dmax - cbase; d++) {
461                               setbit(cg_blksfree(&acg), d);
462                               acg.cg_cs.cs_nffree++;
463                     }
464           }
465           if (sblock.fs_contigsumsize > 0) {
466                     int32_t   *sump = cg_clustersum(&acg);
467                     u_char    *mapp = cg_clustersfree(&acg);
468                     int       map = *mapp++;
469                     int       bit = 1;
470                     int       run = 0;
471 
472                     for (i = 0; i < acg.cg_nclusterblks; i++) {
473                               if ((map & bit) != 0) {
474                                         run++;
475                               } else if (run != 0) {
476                                         if (run > sblock.fs_contigsumsize) {
477                                                   run = sblock.fs_contigsumsize;
478                                         }
479                                         sump[run]++;
480                                         run = 0;
481                               }
482                               if ((i & (NBBY - 1)) != (NBBY - 1)) {
483                                         bit <<= 1;
484                               } else {
485                                         map = *mapp++;
486                                         bit = 1;
487                               }
488                     }
489                     if (run != 0) {
490                               if (run > sblock.fs_contigsumsize) {
491                                         run = sblock.fs_contigsumsize;
492                               }
493                               sump[run]++;
494                     }
495           }
496           sblock.fs_cstotal.cs_ndir += acg.cg_cs.cs_ndir;
497           sblock.fs_cstotal.cs_nffree += acg.cg_cs.cs_nffree;
498           sblock.fs_cstotal.cs_nbfree += acg.cg_cs.cs_nbfree;
499           sblock.fs_cstotal.cs_nifree += acg.cg_cs.cs_nifree;
500           *cs = acg.cg_cs;
501           wtfs(fsbtodb(&sblock, cgtod(&sblock, cylno)),
502               (size_t)sblock.fs_bsize, &acg, fso, Nflag);
503           DBG_DUMP_CG(&sblock,
504               "new cg",
505               &acg);
506 
507           DBG_LEAVE;
508           return;
509 }
510 
511 /* ******************************************************* frag_adjust ***** */
512 /*
513  * Here  we add or subtract (sign +1/-1) the available fragments in  a  given
514  * block to or from the fragment statistics. By subtracting before and adding
515  * after  an operation on the free frag map we can easy update  the  fragment
516  * statistic, which seems to be otherwise an rather complex operation.
517  */
518 static void
frag_adjust(daddr_t frag,int sign)519 frag_adjust(daddr_t frag, int sign)
520 {
521           int fragsize;
522           int f;
523 
524           DBG_ENTER;
525 
526           fragsize=0;
527           /*
528            * Here frag only needs to point to any fragment in the block we want
529            * to examine.
530            */
531           for(f=rounddown(frag, sblock.fs_frag);
532               f<roundup(frag+1, sblock.fs_frag);
533               f++) {
534                     /*
535                      * Count contiguos free fragments.
536                      */
537                     if(isset(cg_blksfree(&acg), f)) {
538                               fragsize++;
539                     } else {
540                               if(fragsize && fragsize<sblock.fs_frag) {
541                                         /*
542                                          * We found something in between.
543                                          */
544                                         acg.cg_frsum[fragsize]+=sign;
545                                         DBG_PRINT2("frag_adjust [%d]+=%d\n",
546                                             fragsize,
547                                             sign);
548                               }
549                               fragsize=0;
550                     }
551           }
552           if(fragsize && fragsize<sblock.fs_frag) {
553                     /*
554                      * We found something.
555                      */
556                     acg.cg_frsum[fragsize]+=sign;
557                     DBG_PRINT2("frag_adjust [%d]+=%d\n",
558                         fragsize,
559                         sign);
560           }
561           DBG_PRINT2("frag_adjust [[%d]]+=%d\n",
562               fragsize,
563               sign);
564 
565           DBG_LEAVE;
566           return;
567 }
568 
569 /* ******************************************************* cond_bl_upd ***** */
570 /*
571  * Here we conditionally update a pointer to a fragment. We check for all
572  * relocated blocks if any of it's fragments is referenced by the current
573  * field,  and update the pointer to the respective fragment in  our  new
574  * block.  If  we find a reference we write back the  block  immediately,
575  * as there is no easy way for our general block reading engine to figure
576  * out if a write back operation is needed.
577  */
578 static void
cond_bl_upd(ufs_daddr_t * block,struct gfs_bpp * field,enum pointer_source source,int fso,unsigned int Nflag)579 cond_bl_upd(ufs_daddr_t *block, struct gfs_bpp *field,
580     enum pointer_source source, int fso, unsigned int Nflag)
581 {
582           struct gfs_bpp      *f;
583           char *src;
584           daddr_t dst=0;
585 
586           DBG_ENTER;
587 
588           f=field;
589           while(f->old) { /* for all old blocks */
590                     if(*block/sblock.fs_frag == f->old) {
591                               /*
592                                * The fragment is part of the block, so update.
593                                */
594                               *block=(f->new*sblock.fs_frag+(*block%sblock.fs_frag));
595                               f->found++;
596                               DBG_PRINT3("scg (%d->%d)[%d] reference updated\n",
597                                   f->old,
598                                   f->new,
599                                   *block%sblock.fs_frag);
600 
601                               /* Write the block back to disk immediately */
602                               switch (source) {
603                               case GFS_PS_INODE:
604                                         src=ablk;
605                                         dst=in_src;
606                                         break;
607                               case GFS_PS_IND_BLK_LVL1:
608                                         src=i1blk;
609                                         dst=i1_src;
610                                         break;
611                               case GFS_PS_IND_BLK_LVL2:
612                                         src=i2blk;
613                                         dst=i2_src;
614                                         break;
615                               case GFS_PS_IND_BLK_LVL3:
616                                         src=i3blk;
617                                         dst=i3_src;
618                                         break;
619                               default:  /* error */
620                                         src=NULL;
621                                         break;
622                               }
623                               if(src) {
624                                         /*
625                                          * XXX    If src is not of type inode we have to
626                                          *        implement  copy on write here in  case
627                                          *        of active snapshots.
628                                          */
629                                         wtfs(dst, (size_t)sblock.fs_bsize, src,
630                                             fso, Nflag);
631                               }
632 
633                               /*
634                                * The same block can't be found again in this loop.
635                                */
636                               break;
637                     }
638                     f++;
639           }
640 
641           DBG_LEAVE;
642           return;
643 }
644 
645 /* ************************************************************ updjcg ***** */
646 /*
647  * Here we do all needed work for the former last cylinder group. It has to be
648  * changed  in  any case, even if the filesystem ended exactly on the  end  of
649  * this  group, as there is some slightly inconsistent handling of the  number
650  * of cylinders in the cylinder group. We start again by reading the  cylinder
651  * group from disk. If the last block was not fully available, we first handle
652  * the  missing  fragments, then we handle all new full blocks  in  that  file
653  * system  and  finally we handle the new last fragmented block  in  the  file
654  * system.  We again have to handle the fragment statistics rotational  layout
655  * tables and cluster summary during all those operations.
656  */
657 static void
updjcg(int cylno,time_t utime,int fsi,int fso,unsigned int Nflag)658 updjcg(int cylno, time_t utime, int fsi, int fso, unsigned int Nflag)
659 {
660           daddr_t   cbase, dmax, dupper;
661           struct csum         *cs;
662           int       i,k;
663           int       j=0;
664 
665           DBG_ENTER;
666 
667           /*
668            * Read the former last (joining) cylinder group from disk, and make
669            * a copy.
670            */
671           rdfs(fsbtodb(&osblock, cgtod(&osblock, cylno)),
672               (size_t)osblock.fs_cgsize, &aocg, fsi);
673           DBG_PRINT0("jcg read\n");
674           DBG_DUMP_CG(&sblock,
675               "old joining cg",
676               &aocg);
677 
678           memcpy((void *)&cgun1, (void *)&cgun2, sizeof(cgun2));
679 
680           /*
681            * If  the  cylinder  group had already it's  new  final  size  almost
682            * nothing is to be done ... except:
683            * For some reason the value of cg_ncyl in the last cylinder group has
684            * to  be  zero instead of fs_cpg. As this is now no longer  the  last
685            * cylinder group we have to change that value now to fs_cpg.
686            */
687 
688           if(cgbase(&osblock, cylno+1) == osblock.fs_size) {
689                     acg.cg_ncyl=sblock.fs_cpg;
690 
691                     wtfs(fsbtodb(&sblock, cgtod(&sblock, cylno)),
692                         (size_t)sblock.fs_cgsize, &acg, fso, Nflag);
693                     DBG_PRINT0("jcg written\n");
694                     DBG_DUMP_CG(&sblock,
695                         "new joining cg",
696                         &acg);
697 
698                     DBG_LEAVE;
699                     return;
700           }
701 
702           /*
703            * Set up some variables needed later.
704            */
705           cbase = cgbase(&sblock, cylno);
706           dmax = cbase + sblock.fs_fpg;
707           if (dmax > sblock.fs_size)
708                     dmax = sblock.fs_size;
709           dupper = cgdmin(&sblock, cylno) - cbase;
710           if (cylno == 0) { /* XXX fscs may be relocated */
711                     dupper += howmany(sblock.fs_cssize, sblock.fs_fsize);
712           }
713 
714           /*
715            * Set pointer to the cylinder summary for our cylinder group.
716            */
717           cs = fscs + cylno;
718 
719           /*
720            * Touch the cylinder group, update all fields in the cylinder group as
721            * needed, update the free space in the superblock.
722            */
723           acg.cg_time = utime;
724           if (cylno == sblock.fs_ncg - 1) {
725                     /*
726                      * This is still the last cylinder group.
727                      */
728                     acg.cg_ncyl = sblock.fs_ncyl % sblock.fs_cpg;
729           } else {
730                     acg.cg_ncyl = sblock.fs_cpg;
731           }
732           DBG_PRINT4("jcg dbg: %d %u %d %u\n",
733               cylno,
734               sblock.fs_ncg,
735               acg.cg_ncyl,
736               sblock.fs_cpg);
737           acg.cg_ndblk = dmax - cbase;
738           sblock.fs_dsize += acg.cg_ndblk-aocg.cg_ndblk;
739           if (sblock.fs_contigsumsize > 0) {
740                     acg.cg_nclusterblks = acg.cg_ndblk / sblock.fs_frag;
741           }
742 
743           /*
744            * Now  we have to update the free fragment bitmap for our new  free
745            * space.  There again we have to handle the fragmentation and  also
746            * the  rotational  layout tables and the cluster summary.  This  is
747            * also  done per fragment for the first new block if the  old  file
748            * system end was not on a block boundary, per fragment for the  new
749            * last block if the new file system end is not on a block boundary,
750            * and per block for all space in between.
751            *
752            * Handle the first new block here if it was partially available
753            * before.
754            */
755           if(osblock.fs_size % sblock.fs_frag) {
756                     if(roundup(osblock.fs_size, sblock.fs_frag)<=sblock.fs_size) {
757                               /*
758                                * The new space is enough to fill at least this
759                                * block
760                                */
761                               j=0;
762                               for(i=roundup(osblock.fs_size-cbase, sblock.fs_frag)-1;
763                                   i>=osblock.fs_size-cbase;
764                                   i--) {
765                                         setbit(cg_blksfree(&acg), i);
766                                         acg.cg_cs.cs_nffree++;
767                                         j++;
768                               }
769 
770                               /*
771                                * Check  if the fragment just created could join  an
772                                * already existing fragment at the former end of the
773                                * file system.
774                                */
775                               if(isblock(&sblock, cg_blksfree(&acg),
776                                   ((osblock.fs_size - cgbase(&sblock, cylno))/
777                                   sblock.fs_frag))) {
778                                         /*
779                                          * The block is now completely available
780                                          */
781                                         DBG_PRINT0("block was\n");
782                                         acg.cg_frsum[osblock.fs_size%sblock.fs_frag]--;
783                                         acg.cg_cs.cs_nbfree++;
784                                         acg.cg_cs.cs_nffree-=sblock.fs_frag;
785                                         k=rounddown(osblock.fs_size-cbase,
786                                             sblock.fs_frag);
787                                         cg_blktot(&acg)[cbtocylno(&sblock, k)]++;
788                                         cg_blks(&sblock, &acg, cbtocylno(&sblock, k))
789                                             [cbtorpos(&sblock, k)]++;
790                                         updclst((osblock.fs_size-cbase)/sblock.fs_frag);
791                               } else {
792                                         /*
793                                          * Lets rejoin a possible partially growed
794                                          * fragment.
795                                          */
796                                         k=0;
797                                         while(isset(cg_blksfree(&acg), i) &&
798                                             (i>=rounddown(osblock.fs_size-cbase,
799                                             sblock.fs_frag))) {
800                                                   i--;
801                                                   k++;
802                                         }
803                                         if(k) {
804                                                   acg.cg_frsum[k]--;
805                                         }
806                                         acg.cg_frsum[k+j]++;
807                               }
808                     } else {
809                               /*
810                                * We only grow by some fragments within this last
811                                * block.
812                                */
813                               for(i=sblock.fs_size-cbase-1;
814                                         i>=osblock.fs_size-cbase;
815                                         i--) {
816                                         setbit(cg_blksfree(&acg), i);
817                                         acg.cg_cs.cs_nffree++;
818                                         j++;
819                               }
820                               /*
821                                * Lets rejoin a possible partially growed fragment.
822                                */
823                               k=0;
824                               while(isset(cg_blksfree(&acg), i) &&
825                                   (i>=rounddown(osblock.fs_size-cbase,
826                                   sblock.fs_frag))) {
827                                         i--;
828                                         k++;
829                               }
830                               if(k) {
831                                         acg.cg_frsum[k]--;
832                               }
833                               acg.cg_frsum[k+j]++;
834                     }
835           }
836 
837           /*
838            * Handle all new complete blocks here.
839            */
840           for(i=roundup(osblock.fs_size-cbase, sblock.fs_frag);
841               i+sblock.fs_frag<=dmax-cbase;       /* XXX <= or only < ? */
842               i+=sblock.fs_frag) {
843                     j = i / sblock.fs_frag;
844                     setblock(&sblock, cg_blksfree(&acg), j);
845                     updclst(j);
846                     acg.cg_cs.cs_nbfree++;
847                     cg_blktot(&acg)[cbtocylno(&sblock, i)]++;
848                     cg_blks(&sblock, &acg, cbtocylno(&sblock, i))
849                         [cbtorpos(&sblock, i)]++;
850           }
851 
852           /*
853            * Handle the last new block if there are stll some new fragments left.
854            * Here  we don't have to bother about the cluster summary or the  even
855            * the rotational layout table.
856            */
857           if (i < (dmax - cbase)) {
858                     acg.cg_frsum[dmax - cbase - i]++;
859                     for (; i < dmax - cbase; i++) {
860                               setbit(cg_blksfree(&acg), i);
861                               acg.cg_cs.cs_nffree++;
862                     }
863           }
864 
865           sblock.fs_cstotal.cs_nffree +=
866               (acg.cg_cs.cs_nffree - aocg.cg_cs.cs_nffree);
867           sblock.fs_cstotal.cs_nbfree +=
868               (acg.cg_cs.cs_nbfree - aocg.cg_cs.cs_nbfree);
869           /*
870            * The following statistics are not changed here:
871            *     sblock.fs_cstotal.cs_ndir
872            *     sblock.fs_cstotal.cs_nifree
873            * As the statistics for this cylinder group are ready, copy it to
874            * the summary information array.
875            */
876           *cs = acg.cg_cs;
877 
878           /*
879            * Write the updated "joining" cylinder group back to disk.
880            */
881           wtfs(fsbtodb(&sblock, cgtod(&sblock, cylno)), (size_t)sblock.fs_cgsize,
882               &acg, fso, Nflag);
883           DBG_PRINT0("jcg written\n");
884           DBG_DUMP_CG(&sblock,
885               "new joining cg",
886               &acg);
887 
888           DBG_LEAVE;
889           return;
890 }
891 
892 /* ********************************************************** updcsloc ***** */
893 /*
894  * Here  we update the location of the cylinder summary. We have  two  possible
895  * ways of growing the cylinder summary.
896  * (1)    We can try to grow the summary in the current location, and  relocate
897  *        possibly used blocks within the current cylinder group.
898  * (2)    Alternatively we can relocate the whole cylinder summary to the first
899  *        new completely empty cylinder group. Once the cylinder summary is  no
900  *        longer in the beginning of the first cylinder group you should  never
901  *        use  a version of fsck which is not aware of the possibility to  have
902  *        this structure in a non standard place.
903  * Option (1) is considered to be less intrusive to the structure of the  file-
904  * system. So we try to stick to that whenever possible. If there is not enough
905  * space  in the cylinder group containing the cylinder summary we have to  use
906  * method  (2). In case of active snapshots in the filesystem we  probably  can
907  * completely avoid implementing copy on write if we stick to method (2) only.
908  */
909 static void
updcsloc(time_t utime,int fsi,int fso,unsigned int Nflag)910 updcsloc(time_t utime, int fsi, int fso, unsigned int Nflag)
911 {
912           struct csum         *cs;
913           int       ocscg, ncscg;
914           int       blocks;
915           daddr_t   cbase, dupper, odupper, d, f, g;
916           int       ind;
917           int       cylno, inc;
918           struct gfs_bpp      *bp;
919           int       i, l;
920           int       lcs=0;
921           int       block;
922 
923           DBG_ENTER;
924 
925           if(howmany(sblock.fs_cssize, sblock.fs_fsize) ==
926               howmany(osblock.fs_cssize, osblock.fs_fsize)) {
927                     /*
928                      * No new fragment needed.
929                      */
930                     DBG_LEAVE;
931                     return;
932           }
933           ocscg=dtog(&osblock, osblock.fs_csaddr);
934           cs=fscs+ocscg;
935           blocks = 1+howmany(sblock.fs_cssize, sblock.fs_bsize)-
936               howmany(osblock.fs_cssize, osblock.fs_bsize);
937 
938           /*
939            * Read original cylinder group from disk, and make a copy.
940            * XXX    If Nflag is set in some very rare cases we now miss
941            *        some changes done in updjcg by reading the unmodified
942            *        block from disk.
943            */
944           rdfs(fsbtodb(&osblock, cgtod(&osblock, ocscg)),
945               (size_t)osblock.fs_cgsize, &aocg, fsi);
946           DBG_PRINT0("oscg read\n");
947           DBG_DUMP_CG(&sblock,
948               "old summary cg",
949               &aocg);
950 
951           memcpy((void *)&cgun1, (void *)&cgun2, sizeof(cgun2));
952 
953           /*
954            * Touch the cylinder group, set up local variables needed later
955            * and update the superblock.
956            */
957           acg.cg_time = utime;
958 
959           /*
960            * XXX    In the case of having active snapshots we may need much more
961            *        blocks for the copy on write. We need each block twice,  and
962            *        also  up to 8*3 blocks for indirect blocks for all  possible
963            *        references.
964            */
965           if(/*((int)sblock.fs_time&0x3)>0||*/ cs->cs_nbfree < blocks) {
966                     /*
967                      * There  is  not enough space in the old cylinder  group  to
968                      * relocate  all blocks as needed, so we relocate  the  whole
969                      * cylinder  group summary to a new group. We try to use  the
970                      * first complete new cylinder group just created. Within the
971                      * cylinder  group we allign the area immediately  after  the
972                      * cylinder  group  information location in order  to  be  as
973                      * close as possible to the original implementation of ffs.
974                      *
975                      * First  we have to make sure we'll find enough space in  the
976                      * new  cylinder  group. If not, then we  currently  give  up.
977                      * We  start  with freeing everything which was  used  by  the
978                      * fragments of the old cylinder summary in the current group.
979                      * Now  we write back the group meta data, read in the  needed
980                      * meta data from the new cylinder group, and start allocating
981                      * within  that  group. Here we can assume, the  group  to  be
982                      * completely empty. Which makes the handling of fragments and
983                      * clusters a lot easier.
984                      */
985                     DBG_TRC;
986                     if(sblock.fs_ncg-osblock.fs_ncg < 2) {
987                               errx(2, "panic: not enough space");
988                     }
989 
990                     /*
991                      * Point "d" to the first fragment not used by the cylinder
992                      * summary.
993                      */
994                     d=osblock.fs_csaddr+(osblock.fs_cssize/osblock.fs_fsize);
995 
996                     /*
997                      * Set up last cluster size ("lcs") already here. Calculate
998                      * the size for the trailing cluster just behind where  "d"
999                      * points to.
1000                      */
1001                     if(sblock.fs_contigsumsize > 0) {
1002                               for(block=howmany(d%sblock.fs_fpg, sblock.fs_frag),
1003                                   lcs=0; lcs<sblock.fs_contigsumsize;
1004                                   block++, lcs++) {
1005                                         if(isclr(cg_clustersfree(&acg), block)){
1006                                                   break;
1007                                         }
1008                               }
1009                     }
1010 
1011                     /*
1012                      * Point "d" to the last frag used by the cylinder summary.
1013                      */
1014                     d--;
1015 
1016                     DBG_PRINT1("d=%d\n",
1017                         d);
1018                     if((d+1)%sblock.fs_frag) {
1019                               /*
1020                                * The end of the cylinder summary is not a complete
1021                                * block.
1022                                */
1023                               DBG_TRC;
1024                               frag_adjust(d%sblock.fs_fpg, -1);
1025                               for(; (d+1)%sblock.fs_frag; d--) {
1026                                         DBG_PRINT1("d=%d\n",
1027                                             d);
1028                                         setbit(cg_blksfree(&acg), d%sblock.fs_fpg);
1029                                         acg.cg_cs.cs_nffree++;
1030                                         sblock.fs_cstotal.cs_nffree++;
1031                               }
1032                               /*
1033                                * Point  "d" to the last fragment of the  last
1034                                * (incomplete) block of the clinder summary.
1035                                */
1036                               d++;
1037                               frag_adjust(d%sblock.fs_fpg, 1);
1038 
1039                               if(isblock(&sblock, cg_blksfree(&acg),
1040                                   (d%sblock.fs_fpg)/sblock.fs_frag)) {
1041                                         DBG_PRINT1("d=%d\n",
1042                                             d);
1043                                         acg.cg_cs.cs_nffree-=sblock.fs_frag;
1044                                         acg.cg_cs.cs_nbfree++;
1045                                         sblock.fs_cstotal.cs_nffree-=sblock.fs_frag;
1046                                         sblock.fs_cstotal.cs_nbfree++;
1047                                         cg_blktot(&acg)[cbtocylno(&sblock,
1048                                             d%sblock.fs_fpg)]++;
1049                                         cg_blks(&sblock, &acg, cbtocylno(&sblock,
1050                                             d%sblock.fs_fpg))[cbtorpos(&sblock,
1051                                             d%sblock.fs_fpg)]++;
1052                                         if(sblock.fs_contigsumsize > 0) {
1053                                                   setbit(cg_clustersfree(&acg),
1054                                                       (d%sblock.fs_fpg)/sblock.fs_frag);
1055                                                   if(lcs < sblock.fs_contigsumsize) {
1056                                                             if(lcs) {
1057                                                                       cg_clustersum(&acg)
1058                                                                           [lcs]--;
1059                                                             }
1060                                                             lcs++;
1061                                                             cg_clustersum(&acg)[lcs]++;
1062                                                   }
1063                                         }
1064                               }
1065                               /*
1066                                * Point "d" to the first fragment of the block before
1067                                * the last incomplete block.
1068                                */
1069                               d--;
1070                     }
1071 
1072                     DBG_PRINT1("d=%d\n",
1073                         d);
1074                     for(d=rounddown(d, sblock.fs_frag); d >= osblock.fs_csaddr;
1075                         d-=sblock.fs_frag) {
1076                               DBG_TRC;
1077                               DBG_PRINT1("d=%d\n",
1078                                   d);
1079                               setblock(&sblock, cg_blksfree(&acg),
1080                                   (d%sblock.fs_fpg)/sblock.fs_frag);
1081                               acg.cg_cs.cs_nbfree++;
1082                               sblock.fs_cstotal.cs_nbfree++;
1083                               cg_blktot(&acg)[cbtocylno(&sblock, d%sblock.fs_fpg)]++;
1084                               cg_blks(&sblock, &acg, cbtocylno(&sblock,
1085                                   d%sblock.fs_fpg))[cbtorpos(&sblock,
1086                                   d%sblock.fs_fpg)]++;
1087                               if(sblock.fs_contigsumsize > 0) {
1088                                         setbit(cg_clustersfree(&acg),
1089                                             (d%sblock.fs_fpg)/sblock.fs_frag);
1090                                         /*
1091                                          * The last cluster size is already set up.
1092                                          */
1093                                         if(lcs < sblock.fs_contigsumsize) {
1094                                                   if(lcs) {
1095                                                             cg_clustersum(&acg)[lcs]--;
1096                                                   }
1097                                                   lcs++;
1098                                                   cg_clustersum(&acg)[lcs]++;
1099                                         }
1100                               }
1101                     }
1102                     *cs = acg.cg_cs;
1103 
1104                     /*
1105                      * Now write the former cylinder group containing the cylinder
1106                      * summary back to disk.
1107                      */
1108                     wtfs(fsbtodb(&sblock, cgtod(&sblock, ocscg)),
1109                         (size_t)sblock.fs_cgsize, &acg, fso, Nflag);
1110                     DBG_PRINT0("oscg written\n");
1111                     DBG_DUMP_CG(&sblock,
1112                         "old summary cg",
1113                         &acg);
1114 
1115                     /*
1116                      * Find the beginning of the new cylinder group containing the
1117                      * cylinder summary.
1118                      */
1119                     sblock.fs_csaddr=cgdmin(&sblock, osblock.fs_ncg);
1120                     ncscg=dtog(&sblock, sblock.fs_csaddr);
1121                     cs=fscs+ncscg;
1122 
1123 
1124                     /*
1125                      * If Nflag is specified, we would now read random data instead
1126                      * of an empty cg structure from disk. So we can't simulate that
1127                      * part for now.
1128                      */
1129                     if(Nflag) {
1130                               DBG_PRINT0("nscg update skipped\n");
1131                               DBG_LEAVE;
1132                               return;
1133                     }
1134 
1135                     /*
1136                      * Read the future cylinder group containing the cylinder
1137                      * summary from disk, and make a copy.
1138                      */
1139                     rdfs(fsbtodb(&sblock, cgtod(&sblock, ncscg)),
1140                         (size_t)sblock.fs_cgsize, &aocg, fsi);
1141                     DBG_PRINT0("nscg read\n");
1142                     DBG_DUMP_CG(&sblock,
1143                         "new summary cg",
1144                         &aocg);
1145 
1146                     memcpy((void *)&cgun1, (void *)&cgun2, sizeof(cgun2));
1147 
1148                     /*
1149                      * Allocate all complete blocks used by the new cylinder
1150                      * summary.
1151                      */
1152                     for(d=sblock.fs_csaddr; d+sblock.fs_frag <=
1153                         sblock.fs_csaddr+(sblock.fs_cssize/sblock.fs_fsize);
1154                         d+=sblock.fs_frag) {
1155                               clrblock(&sblock, cg_blksfree(&acg),
1156                                   (d%sblock.fs_fpg)/sblock.fs_frag);
1157                               acg.cg_cs.cs_nbfree--;
1158                               sblock.fs_cstotal.cs_nbfree--;
1159                               cg_blktot(&acg)[cbtocylno(&sblock, d%sblock.fs_fpg)]--;
1160                               cg_blks(&sblock, &acg, cbtocylno(&sblock,
1161                                   d%sblock.fs_fpg))[cbtorpos(&sblock,
1162                                   d%sblock.fs_fpg)]--;
1163                               if(sblock.fs_contigsumsize > 0) {
1164                                         clrbit(cg_clustersfree(&acg),
1165                                             (d%sblock.fs_fpg)/sblock.fs_frag);
1166                               }
1167                     }
1168 
1169                     /*
1170                      * Allocate all fragments used by the cylinder summary in the
1171                      * last block.
1172                      */
1173                     if(d<sblock.fs_csaddr+(sblock.fs_cssize/sblock.fs_fsize)) {
1174                               for(; d-sblock.fs_csaddr<
1175                                   sblock.fs_cssize/sblock.fs_fsize;
1176                                   d++) {
1177                                         clrbit(cg_blksfree(&acg), d%sblock.fs_fpg);
1178                                         acg.cg_cs.cs_nffree--;
1179                                         sblock.fs_cstotal.cs_nffree--;
1180                               }
1181                               acg.cg_cs.cs_nbfree--;
1182                               acg.cg_cs.cs_nffree+=sblock.fs_frag;
1183                               sblock.fs_cstotal.cs_nbfree--;
1184                               sblock.fs_cstotal.cs_nffree+=sblock.fs_frag;
1185                               cg_blktot(&acg)[cbtocylno(&sblock, d%sblock.fs_fpg)]--;
1186                               cg_blks(&sblock, &acg, cbtocylno(&sblock,
1187                                   d%sblock.fs_fpg))[cbtorpos(&sblock,
1188                                   d%sblock.fs_fpg)]--;
1189                               if(sblock.fs_contigsumsize > 0) {
1190                                         clrbit(cg_clustersfree(&acg),
1191                                             (d%sblock.fs_fpg)/sblock.fs_frag);
1192                               }
1193 
1194                               frag_adjust(d%sblock.fs_fpg, +1);
1195                     }
1196                     /*
1197                      * XXX    Handle the cluster statistics here in the case  this
1198                      *        cylinder group is now almost full, and the remaining
1199                      *        space is less then the maximum cluster size. This is
1200                      *        probably not needed, as you would hardly find a file
1201                      *        system which has only MAXCSBUFS+FS_MAXCONTIG of free
1202                      *        space right behind the cylinder group information in
1203                      *        any new cylinder group.
1204                      */
1205 
1206                     /*
1207                      * Update our statistics in the cylinder summary.
1208                      */
1209                     *cs = acg.cg_cs;
1210 
1211                     /*
1212                      * Write the new cylinder group containing the cylinder summary
1213                      * back to disk.
1214                      */
1215                     wtfs(fsbtodb(&sblock, cgtod(&sblock, ncscg)),
1216                         (size_t)sblock.fs_cgsize, &acg, fso, Nflag);
1217                     DBG_PRINT0("nscg written\n");
1218                     DBG_DUMP_CG(&sblock,
1219                         "new summary cg",
1220                         &acg);
1221 
1222                     DBG_LEAVE;
1223                     return;
1224           }
1225           /*
1226            * We have got enough of space in the current cylinder group, so we
1227            * can relocate just a few blocks, and let the summary  information
1228            * grow in place where it is right now.
1229            */
1230           DBG_TRC;
1231 
1232           cbase = cgbase(&osblock, ocscg);        /* old and new are equal */
1233           dupper = sblock.fs_csaddr - cbase +
1234               howmany(sblock.fs_cssize, sblock.fs_fsize);
1235           odupper = osblock.fs_csaddr - cbase +
1236               howmany(osblock.fs_cssize, osblock.fs_fsize);
1237 
1238           sblock.fs_dsize -= dupper-odupper;
1239 
1240           /*
1241            * Allocate the space for the array of blocks to be relocated.
1242            */
1243           bp=(struct gfs_bpp *)malloc(((dupper-odupper)/sblock.fs_frag+2)*
1244               sizeof(struct gfs_bpp));
1245           if(bp == NULL) {
1246                     errx(1, "malloc failed");
1247           }
1248           memset((char *)bp, 0, ((dupper-odupper)/sblock.fs_frag+2)*
1249               sizeof(struct gfs_bpp));
1250 
1251           /*
1252            * Lock all new frags needed for the cylinder group summary. This  is
1253            * done per fragment in the first and last block of the new  required
1254            * area, and per block for all other blocks.
1255            *
1256            * Handle the first new  block here (but only if some fragments where
1257            * already used for the cylinder summary).
1258            */
1259           ind=0;
1260           frag_adjust(odupper, -1);
1261           for(d=odupper; ((d<dupper)&&(d%sblock.fs_frag)); d++) {
1262                     DBG_PRINT1("scg first frag check loop d=%d\n",
1263                         d);
1264                     if(isclr(cg_blksfree(&acg), d)) {
1265                               if (!ind) {
1266                                         bp[ind].old=d/sblock.fs_frag;
1267                                         bp[ind].flags|=GFS_FL_FIRST;
1268                                         if(roundup(d, sblock.fs_frag) >= dupper) {
1269                                                   bp[ind].flags|=GFS_FL_LAST;
1270                                         }
1271                                         ind++;
1272                               }
1273                     } else {
1274                               clrbit(cg_blksfree(&acg), d);
1275                               acg.cg_cs.cs_nffree--;
1276                               sblock.fs_cstotal.cs_nffree--;
1277                     }
1278                     /*
1279                      * No cluster handling is needed here, as there was at least
1280                      * one  fragment in use by the cylinder summary in  the  old
1281                      * file system.
1282                      * No block-free counter handling here as this block was not
1283                      * a free block.
1284                      */
1285           }
1286           frag_adjust(odupper, 1);
1287 
1288           /*
1289            * Handle all needed complete blocks here.
1290            */
1291           for(; d+sblock.fs_frag<=dupper; d+=sblock.fs_frag) {
1292                     DBG_PRINT1("scg block check loop d=%d\n",
1293                         d);
1294                     if(!isblock(&sblock, cg_blksfree(&acg), d/sblock.fs_frag)) {
1295                               for(f=d; f<d+sblock.fs_frag; f++) {
1296                                         if(isset(cg_blksfree(&aocg), f)) {
1297                                                   acg.cg_cs.cs_nffree--;
1298                                                   sblock.fs_cstotal.cs_nffree--;
1299                                         }
1300                               }
1301                               clrblock(&sblock, cg_blksfree(&acg), d/sblock.fs_frag);
1302                               bp[ind].old=d/sblock.fs_frag;
1303                               ind++;
1304                     } else {
1305                               clrblock(&sblock, cg_blksfree(&acg), d/sblock.fs_frag);
1306                               acg.cg_cs.cs_nbfree--;
1307                               sblock.fs_cstotal.cs_nbfree--;
1308                               cg_blktot(&acg)[cbtocylno(&sblock, d)]--;
1309                               cg_blks(&sblock, &acg, cbtocylno(&sblock, d))
1310                                   [cbtorpos(&sblock, d)]--;
1311                               if(sblock.fs_contigsumsize > 0) {
1312                                         clrbit(cg_clustersfree(&acg), d/sblock.fs_frag);
1313                                         for(lcs=0, l=(d/sblock.fs_frag)+1;
1314                                             lcs<sblock.fs_contigsumsize;
1315                                             l++, lcs++ ) {
1316                                                   if(isclr(cg_clustersfree(&acg),l)){
1317                                                             break;
1318                                                   }
1319                                         }
1320                                         if(lcs < sblock.fs_contigsumsize) {
1321                                                   cg_clustersum(&acg)[lcs+1]--;
1322                                                   if(lcs) {
1323                                                             cg_clustersum(&acg)[lcs]++;
1324                                                   }
1325                                         }
1326                               }
1327                     }
1328                     /*
1329                      * No fragment counter handling is needed here, as this finally
1330                      * doesn't change after the relocation.
1331                      */
1332           }
1333 
1334           /*
1335            * Handle all fragments needed in the last new affected block.
1336            */
1337           if(d<dupper) {
1338                     frag_adjust(dupper-1, -1);
1339 
1340                     if(isblock(&sblock, cg_blksfree(&acg), d/sblock.fs_frag)) {
1341                               acg.cg_cs.cs_nbfree--;
1342                               sblock.fs_cstotal.cs_nbfree--;
1343                               acg.cg_cs.cs_nffree+=sblock.fs_frag;
1344                               sblock.fs_cstotal.cs_nffree+=sblock.fs_frag;
1345                               cg_blktot(&acg)[cbtocylno(&sblock, d)]--;
1346                               cg_blks(&sblock, &acg, cbtocylno(&sblock, d))
1347                                   [cbtorpos(&sblock, d)]--;
1348                               if(sblock.fs_contigsumsize > 0) {
1349                                         clrbit(cg_clustersfree(&acg), d/sblock.fs_frag);
1350                                         for(lcs=0, l=(d/sblock.fs_frag)+1;
1351                                             lcs<sblock.fs_contigsumsize;
1352                                             l++, lcs++ ) {
1353                                                   if(isclr(cg_clustersfree(&acg),l)){
1354                                                             break;
1355                                                   }
1356                                         }
1357                                         if(lcs < sblock.fs_contigsumsize) {
1358                                                   cg_clustersum(&acg)[lcs+1]--;
1359                                                   if(lcs) {
1360                                                             cg_clustersum(&acg)[lcs]++;
1361                                                   }
1362                                         }
1363                               }
1364                     }
1365 
1366                     for(; d<dupper; d++) {
1367                               DBG_PRINT1("scg second frag check loop d=%d\n",
1368                                   d);
1369                               if(isclr(cg_blksfree(&acg), d)) {
1370                                         bp[ind].old=d/sblock.fs_frag;
1371                                         bp[ind].flags|=GFS_FL_LAST;
1372                               } else {
1373                                         clrbit(cg_blksfree(&acg), d);
1374                                         acg.cg_cs.cs_nffree--;
1375                                         sblock.fs_cstotal.cs_nffree--;
1376                               }
1377                     }
1378                     if(bp[ind].flags & GFS_FL_LAST) { /* we have to advance here */
1379                               ind++;
1380                     }
1381                     frag_adjust(dupper-1, 1);
1382           }
1383 
1384           /*
1385            * If we found a block to relocate just do so.
1386            */
1387           if(ind) {
1388                     for(i=0; i<ind; i++) {
1389                               if(!bp[i].old) { /* no more blocks listed */
1390                                         /*
1391                                          * XXX    A relative blocknumber should not be
1392                                          *        zero,   which  is   not   explicitly
1393                                          *        guaranteed by our code.
1394                                          */
1395                                         break;
1396                               }
1397                               /*
1398                                * Allocate a complete block in the same (current)
1399                                * cylinder group.
1400                                */
1401                               bp[i].new=alloc()/sblock.fs_frag;
1402 
1403                               /*
1404                                * There is no frag_adjust() needed for the new block
1405                                * as it will have no fragments yet :-).
1406                                */
1407                               for(f=bp[i].old*sblock.fs_frag,
1408                                   g=bp[i].new*sblock.fs_frag;
1409                                   f<(bp[i].old+1)*sblock.fs_frag;
1410                                   f++, g++) {
1411                                         if(isset(cg_blksfree(&aocg), f)) {
1412                                                   setbit(cg_blksfree(&acg), g);
1413                                                   acg.cg_cs.cs_nffree++;
1414                                                   sblock.fs_cstotal.cs_nffree++;
1415                                         }
1416                               }
1417 
1418                               /*
1419                                * Special handling is required if this was the  first
1420                                * block. We have to consider the fragments which were
1421                                * used by the cylinder summary in the original  block
1422                                * which  re to be free in the copy of our  block.  We
1423                                * have  to be careful if this first block happens  to
1424                                * be also the last block to be relocated.
1425                                */
1426                               if(bp[i].flags & GFS_FL_FIRST) {
1427                                         for(f=bp[i].old*sblock.fs_frag,
1428                                             g=bp[i].new*sblock.fs_frag;
1429                                             f<odupper;
1430                                             f++, g++) {
1431                                                   setbit(cg_blksfree(&acg), g);
1432                                                   acg.cg_cs.cs_nffree++;
1433                                                   sblock.fs_cstotal.cs_nffree++;
1434                                         }
1435                                         if(!(bp[i].flags & GFS_FL_LAST)) {
1436                                                   frag_adjust(bp[i].new*sblock.fs_frag,1);
1437                                         }
1438 
1439                               }
1440 
1441                               /*
1442                                * Special handling is required if this is the last
1443                                * block to be relocated.
1444                                */
1445                               if(bp[i].flags & GFS_FL_LAST) {
1446                                         frag_adjust(bp[i].new*sblock.fs_frag, 1);
1447                                         frag_adjust(bp[i].old*sblock.fs_frag, -1);
1448                                         for(f=dupper;
1449                                             f<roundup(dupper, sblock.fs_frag);
1450                                             f++) {
1451                                                   if(isclr(cg_blksfree(&acg), f)) {
1452                                                             setbit(cg_blksfree(&acg), f);
1453                                                             acg.cg_cs.cs_nffree++;
1454                                                             sblock.fs_cstotal.cs_nffree++;
1455                                                   }
1456                                         }
1457                                         frag_adjust(bp[i].old*sblock.fs_frag, 1);
1458                               }
1459 
1460                               /*
1461                                * !!! Attach the cylindergroup offset here.
1462                                */
1463                               bp[i].old+=cbase/sblock.fs_frag;
1464                               bp[i].new+=cbase/sblock.fs_frag;
1465 
1466                               /*
1467                                * Copy the content of the block.
1468                                */
1469                               /*
1470                                * XXX    Here we will have to implement a copy on write
1471                                *        in the case we have any active snapshots.
1472                                */
1473                               rdfs(fsbtodb(&sblock, bp[i].old*sblock.fs_frag),
1474                                   (size_t)sblock.fs_bsize, &ablk, fsi);
1475                               wtfs(fsbtodb(&sblock, bp[i].new*sblock.fs_frag),
1476                                   (size_t)sblock.fs_bsize, &ablk, fso, Nflag);
1477                               DBG_DUMP_HEX(&sblock,
1478                                   "copied full block",
1479                                   (unsigned char *)&ablk);
1480 
1481                               DBG_PRINT2("scg (%d->%d) block relocated\n",
1482                                   bp[i].old,
1483                                   bp[i].new);
1484                     }
1485 
1486                     /*
1487                      * Now we have to update all references to any fragment which
1488                      * belongs  to any block relocated. We iterate now  over  all
1489                      * cylinder  groups,  within those over all non  zero  length
1490                      * inodes.
1491                      */
1492                     for(cylno=0; cylno<osblock.fs_ncg; cylno++) {
1493                               DBG_PRINT1("scg doing cg (%d)\n",
1494                                   cylno);
1495                               for(inc=osblock.fs_ipg-1 ; inc>=0 ; inc--) {
1496                                         updrefs(cylno, (ino_t)inc, bp, fsi, fso, Nflag);
1497                               }
1498                     }
1499 
1500                     /*
1501                      * All inodes are checked, now make sure the number of
1502                      * references found make sense.
1503                      */
1504                     for(i=0; i<ind; i++) {
1505                               if(!bp[i].found || (bp[i].found>sblock.fs_frag)) {
1506                                         warnx("error: %d refs found for block %d.",
1507                                             bp[i].found, bp[i].old);
1508                               }
1509 
1510                     }
1511           }
1512           /*
1513            * The following statistics are not changed here:
1514            *     sblock.fs_cstotal.cs_ndir
1515            *     sblock.fs_cstotal.cs_nifree
1516            * The following statistics were already updated on the fly:
1517            *     sblock.fs_cstotal.cs_nffree
1518            *     sblock.fs_cstotal.cs_nbfree
1519            * As the statistics for this cylinder group are ready, copy it to
1520            * the summary information array.
1521            */
1522 
1523           *cs = acg.cg_cs;
1524 
1525           /*
1526            * Write summary cylinder group back to disk.
1527            */
1528           wtfs(fsbtodb(&sblock, cgtod(&sblock, ocscg)), (size_t)sblock.fs_cgsize,
1529               &acg, fso, Nflag);
1530           DBG_PRINT0("scg written\n");
1531           DBG_DUMP_CG(&sblock,
1532               "new summary cg",
1533               &acg);
1534 
1535           DBG_LEAVE;
1536           return;
1537 }
1538 
1539 /* ************************************************************** rdfs ***** */
1540 /*
1541  * Here we read some block(s) from disk.
1542  */
1543 static void
rdfs(daddr_t bno,size_t size,void * bf,int fsi)1544 rdfs(daddr_t bno, size_t size, void *bf, int fsi)
1545 {
1546           ssize_t   n;
1547 
1548           DBG_ENTER;
1549 
1550           if (lseek(fsi, (off_t)bno * DEV_BSIZE, 0) < 0) {
1551                     err(33, "rdfs: seek error: %ld", (long)bno);
1552           }
1553           n = read(fsi, bf, size);
1554           if (n != (ssize_t)size) {
1555                     err(34, "rdfs: read error: %ld", (long)bno);
1556           }
1557 
1558           DBG_LEAVE;
1559           return;
1560 }
1561 
1562 /* ************************************************************** wtfs ***** */
1563 /*
1564  * Here we write some block(s) to disk.
1565  */
1566 static void
wtfs(daddr_t bno,size_t size,void * bf,int fso,unsigned int Nflag)1567 wtfs(daddr_t bno, size_t size, void *bf, int fso, unsigned int Nflag)
1568 {
1569           ssize_t   n;
1570 
1571           DBG_ENTER;
1572 
1573           if (Nflag) {
1574                     DBG_LEAVE;
1575                     return;
1576           }
1577           if (lseek(fso, (off_t)bno * DEV_BSIZE, SEEK_SET) < 0) {
1578                     err(35, "wtfs: seek error: %ld", (long)bno);
1579           }
1580           n = write(fso, bf, size);
1581           if (n != (ssize_t)size) {
1582                     err(36, "wtfs: write error: %ld", (long)bno);
1583           }
1584 
1585           DBG_LEAVE;
1586           return;
1587 }
1588 
1589 /* ************************************************************* alloc ***** */
1590 /*
1591  * Here we allocate a free block in the current cylinder group. It is assumed,
1592  * that  acg contains the current cylinder group. As we may take a block  from
1593  * somewhere in the filesystem we have to handle cluster summary here.
1594  */
1595 static daddr_t
alloc(void)1596 alloc(void)
1597 {
1598           daddr_t   d, blkno;
1599           int       lcs1, lcs2;
1600           int       l;
1601           int       csmin, csmax;
1602           int       dlower, dupper, dmax;
1603 
1604           DBG_ENTER;
1605 
1606           if (acg.cg_magic != CG_MAGIC) {
1607                     warnx("acg: bad magic number");
1608                     DBG_LEAVE;
1609                     return (0);
1610           }
1611           if (acg.cg_cs.cs_nbfree == 0) {
1612                     warnx("error: cylinder group ran out of space");
1613                     DBG_LEAVE;
1614                     return (0);
1615           }
1616           /*
1617            * We start seeking for free blocks only from the space available after
1618            * the  end of the new grown cylinder summary. Otherwise we allocate  a
1619            * block here which we have to relocate a couple of seconds later again
1620            * again, and we are not prepared to to this anyway.
1621            */
1622           blkno=-1;
1623           dlower=cgsblock(&sblock, acg.cg_cgx)-cgbase(&sblock, acg.cg_cgx);
1624           dupper=cgdmin(&sblock, acg.cg_cgx)-cgbase(&sblock, acg.cg_cgx);
1625           dmax=cgbase(&sblock, acg.cg_cgx)+sblock.fs_fpg;
1626           if (dmax > sblock.fs_size) {
1627                     dmax = sblock.fs_size;
1628           }
1629           dmax-=cgbase(&sblock, acg.cg_cgx); /* retransform into cg */
1630           csmin=sblock.fs_csaddr-cgbase(&sblock, acg.cg_cgx);
1631           csmax=csmin+howmany(sblock.fs_cssize, sblock.fs_fsize);
1632           DBG_PRINT3("seek range: dl=%d, du=%d, dm=%d\n",
1633               dlower,
1634               dupper,
1635               dmax);
1636           DBG_PRINT2("range cont: csmin=%d, csmax=%d\n",
1637               csmin,
1638               csmax);
1639 
1640           for(d=0; (d<dlower && blkno==-1); d+=sblock.fs_frag) {
1641                     if(d>=csmin && d<=csmax) {
1642                               continue;
1643                     }
1644                     if(isblock(&sblock, cg_blksfree(&acg), fragstoblks(&sblock,
1645                         d))) {
1646                               blkno = fragstoblks(&sblock, d);/* Yeah found a block */
1647                               break;
1648                     }
1649           }
1650           for(d=dupper; (d<dmax && blkno==-1); d+=sblock.fs_frag) {
1651                     if(d>=csmin && d<=csmax) {
1652                               continue;
1653                     }
1654                     if(isblock(&sblock, cg_blksfree(&acg), fragstoblks(&sblock,
1655                         d))) {
1656                               blkno = fragstoblks(&sblock, d);/* Yeah found a block */
1657                               break;
1658                     }
1659           }
1660           if(blkno==-1) {
1661                     warnx("internal error: couldn't find promised block in cg");
1662                     DBG_LEAVE;
1663                     return (0);
1664           }
1665 
1666           /*
1667            * This is needed if the block was found already in the first loop.
1668            */
1669           d=blkstofrags(&sblock, blkno);
1670 
1671           clrblock(&sblock, cg_blksfree(&acg), blkno);
1672           if (sblock.fs_contigsumsize > 0) {
1673                     /*
1674                      * Handle the cluster allocation bitmap.
1675                      */
1676                     clrbit(cg_clustersfree(&acg), blkno);
1677                     /*
1678                      * We  possibly have split a cluster here, so we have  to  do
1679                      * recalculate the sizes of the remaining cluster halves now,
1680                      * and use them for updating the cluster summary information.
1681                      *
1682                      * Lets start with the blocks before our allocated block ...
1683                      */
1684                     for(lcs1=0, l=blkno-1; lcs1<sblock.fs_contigsumsize;
1685                         l--, lcs1++ ) {
1686                               if(isclr(cg_clustersfree(&acg),l)){
1687                                         break;
1688                               }
1689                     }
1690                     /*
1691                      * ... and continue with the blocks right after our allocated
1692                      * block.
1693                      */
1694                     for(lcs2=0, l=blkno+1; lcs2<sblock.fs_contigsumsize;
1695                         l++, lcs2++ ) {
1696                               if(isclr(cg_clustersfree(&acg),l)){
1697                                         break;
1698                               }
1699                     }
1700 
1701                     /*
1702                      * Now update all counters.
1703                      */
1704                     cg_clustersum(&acg)[MIN(lcs1+lcs2+1,sblock.fs_contigsumsize)]--;
1705                     if(lcs1) {
1706                               cg_clustersum(&acg)[lcs1]++;
1707                     }
1708                     if(lcs2) {
1709                               cg_clustersum(&acg)[lcs2]++;
1710                     }
1711           }
1712           /*
1713            * Update all statistics based on blocks.
1714            */
1715           acg.cg_cs.cs_nbfree--;
1716           sblock.fs_cstotal.cs_nbfree--;
1717           cg_blktot(&acg)[cbtocylno(&sblock, d)]--;
1718           cg_blks(&sblock, &acg, cbtocylno(&sblock, d))[cbtorpos(&sblock, d)]--;
1719 
1720           DBG_LEAVE;
1721           return (d);
1722 }
1723 
1724 /* *********************************************************** isblock ***** */
1725 /*
1726  * Here  we check if all frags of a block are free. For more details  again
1727  * please see the source of newfs(8), as this function is taken over almost
1728  * unchanged.
1729  */
1730 static int
isblock(struct fs * fs,unsigned char * cp,int h)1731 isblock(struct fs *fs, unsigned char *cp, int h)
1732 {
1733           unsigned char       mask;
1734 
1735           DBG_ENTER;
1736 
1737           switch (fs->fs_frag) {
1738           case 8:
1739                     DBG_LEAVE;
1740                     return (cp[h] == 0xff);
1741           case 4:
1742                     mask = 0x0f << ((h & 0x1) << 2);
1743                     DBG_LEAVE;
1744                     return ((cp[h >> 1] & mask) == mask);
1745           case 2:
1746                     mask = 0x03 << ((h & 0x3) << 1);
1747                     DBG_LEAVE;
1748                     return ((cp[h >> 2] & mask) == mask);
1749           case 1:
1750                     mask = 0x01 << (h & 0x7);
1751                     DBG_LEAVE;
1752                     return ((cp[h >> 3] & mask) == mask);
1753           default:
1754                     fprintf(stderr, "isblock bad fs_frag %d\n", fs->fs_frag);
1755                     DBG_LEAVE;
1756                     return (0);
1757           }
1758 }
1759 
1760 /* ********************************************************** clrblock ***** */
1761 /*
1762  * Here we allocate a complete block in the block map. For more details again
1763  * please  see the source of newfs(8), as this function is taken over  almost
1764  * unchanged.
1765  */
1766 static void
clrblock(struct fs * fs,unsigned char * cp,int h)1767 clrblock(struct fs *fs, unsigned char *cp, int h)
1768 {
1769           DBG_ENTER;
1770 
1771           switch ((fs)->fs_frag) {
1772           case 8:
1773                     cp[h] = 0;
1774                     break;
1775           case 4:
1776                     cp[h >> 1] &= ~(0x0f << ((h & 0x1) << 2));
1777                     break;
1778           case 2:
1779                     cp[h >> 2] &= ~(0x03 << ((h & 0x3) << 1));
1780                     break;
1781           case 1:
1782                     cp[h >> 3] &= ~(0x01 << (h & 0x7));
1783                     break;
1784           default:
1785                     warnx("clrblock bad fs_frag %d", fs->fs_frag);
1786                     break;
1787           }
1788 
1789           DBG_LEAVE;
1790           return;
1791 }
1792 
1793 /* ********************************************************** setblock ***** */
1794 /*
1795  * Here we free a complete block in the free block map. For more details again
1796  * please  see the source of newfs(8), as this function is taken  over  almost
1797  * unchanged.
1798  */
1799 static void
setblock(struct fs * fs,unsigned char * cp,int h)1800 setblock(struct fs *fs, unsigned char *cp, int h)
1801 {
1802           DBG_ENTER;
1803 
1804           switch (fs->fs_frag) {
1805           case 8:
1806                     cp[h] = 0xff;
1807                     break;
1808           case 4:
1809                     cp[h >> 1] |= (0x0f << ((h & 0x1) << 2));
1810                     break;
1811           case 2:
1812                     cp[h >> 2] |= (0x03 << ((h & 0x3) << 1));
1813                     break;
1814           case 1:
1815                     cp[h >> 3] |= (0x01 << (h & 0x7));
1816                     break;
1817           default:
1818                     warnx("setblock bad fs_frag %d", fs->fs_frag);
1819                     break;
1820           }
1821 
1822           DBG_LEAVE;
1823           return;
1824 }
1825 
1826 /* ************************************************************ ginode ***** */
1827 /*
1828  * This function provides access to an individual inode. We find out in which
1829  * block  the  requested inode is located, read it from disk if  needed,  and
1830  * return  the pointer into that block. We maintain a cache of one  block  to
1831  * not  read the same block again and again if we iterate linearly  over  all
1832  * inodes.
1833  */
1834 static struct ufs1_dinode *
ginode(ino_t inumber,int fsi,int cg)1835 ginode(ino_t inumber, int fsi, int cg)
1836 {
1837           ufs_daddr_t         iblk;
1838           static ino_t        startinum=0;        /* first inode in cached block */
1839           struct ufs1_dinode  *pi;
1840 
1841           DBG_ENTER;
1842 
1843           pi=(struct ufs1_dinode *)(void *)ablk;
1844           inumber+=(cg * sblock.fs_ipg);
1845           if (startinum == 0 || inumber < startinum ||
1846               inumber >= startinum + INOPB(&sblock)) {
1847                     /*
1848                      * The block needed is not cached, so we have to read it from
1849                      * disk now.
1850                      */
1851                     iblk = ino_to_fsba(&sblock, inumber);
1852                     in_src=fsbtodb(&sblock, iblk);
1853                     rdfs(in_src, (size_t)sblock.fs_bsize, &ablk, fsi);
1854                     startinum = rounddown(inumber, INOPB(&sblock));
1855           }
1856 
1857           DBG_LEAVE;
1858           return (&(pi[inumber % INOPB(&sblock)]));
1859 }
1860 
1861 /* ****************************************************** charsperline ***** */
1862 /*
1863  * Figure out how many lines our current terminal has. For more details again
1864  * please  see the source of newfs(8), as this function is taken over  almost
1865  * unchanged.
1866  */
1867 static int
charsperline(void)1868 charsperline(void)
1869 {
1870           int       columns;
1871           char      *cp;
1872           struct winsize      ws;
1873 
1874           DBG_ENTER;
1875 
1876           columns = 0;
1877           if (ioctl(0, TIOCGWINSZ, &ws) != -1) {
1878                     columns = ws.ws_col;
1879           }
1880           if (columns == 0 && (cp = getenv("COLUMNS"))) {
1881                     columns = atoi(cp);
1882           }
1883           if (columns == 0) {
1884                     columns = 80;       /* last resort */
1885           }
1886 
1887           DBG_LEAVE;
1888           return columns;
1889 }
1890 
1891 /* ************************************************************** main ***** */
1892 /*
1893  * growfs(8)  is a utility which allows to increase the size of  an  existing
1894  * ufs filesystem. Currently this can only be done on unmounted file  system.
1895  * It  recognizes some command line options to specify the new desired  size,
1896  * and  it does some basic checkings. The old file system size is  determined
1897  * and  after some more checks like we can really access the new  last  block
1898  * on the disk etc. we calculate the new parameters for the superblock. After
1899  * having  done  this we just call growfs() which will do  the  work.  Before
1900  * we finish the only thing left is to update the disklabel.
1901  * We still have to provide support for snapshots. Therefore we first have to
1902  * understand  what data structures are always replicated in the snapshot  on
1903  * creation,  for all other blocks we touch during our procedure, we have  to
1904  * keep the old blocks unchanged somewhere available for the snapshots. If we
1905  * are lucky, then we only have to handle our blocks to be relocated in  that
1906  * way.
1907  * Also  we  have to consider in what order we actually update  the  critical
1908  * data structures of the filesystem to make sure, that in case of a disaster
1909  * fsck(8) is still able to restore any lost data.
1910  * The  foreseen last step then will be to provide for growing  even  mounted
1911  * file  systems. There we have to extend the mount() system call to  provide
1912  * userland access to the file system locking facility.
1913  */
1914 int
main(int argc,char ** argv)1915 main(int argc, char **argv)
1916 {
1917           struct partinfo pinfo;
1918           char      *device, *special;
1919           char      ch;
1920           unsigned int        size=0;
1921           size_t    len;
1922           unsigned int        Nflag=0;
1923           int       ExpertFlag=0;
1924           struct stat         st;
1925           int       fsi,fso;
1926           char      reply[5];
1927 #ifdef FSMAXSNAP
1928           int       j;
1929 #endif /* FSMAXSNAP */
1930 
1931           DBG_ENTER;
1932 
1933           while((ch=getopt(argc, argv, "Ns:vy")) != -1) {
1934                     switch(ch) {
1935                     case 'N':
1936                               Nflag=1;
1937                               break;
1938                     case 's':
1939                               size=(size_t)atol(optarg);
1940                               if(size<1) {
1941                                         usage();
1942                               }
1943                               break;
1944                     case 'v': /* for compatibility to newfs */
1945                               break;
1946                     case 'y':
1947                               ExpertFlag=1;
1948                               break;
1949                     case '?':
1950                               /* FALLTHROUGH */
1951                     default:
1952                               usage();
1953                     }
1954           }
1955           argc -= optind;
1956           argv += optind;
1957 
1958           if(argc != 1) {
1959                     usage();
1960           }
1961           device=*argv;
1962 
1963           /*
1964            * Now try to guess the (raw)device name.
1965            */
1966           if (0 == strrchr(device, '/')) {
1967                     /*
1968                      * No path prefix was given, so try in that order:
1969                      *     /dev/r%s
1970                      *     /dev/%s
1971                      *     /dev/vinum/r%s
1972                      *     /dev/vinum/%s.
1973                      *
1974                      * FreeBSD now doesn't distinguish between raw and  block
1975                      * devices any longer, but it should still work this way.
1976                      */
1977                     len=strlen(device)+strlen(_PATH_DEV)+2+strlen("vinum/");
1978                     special=(char *)malloc(len);
1979                     if(special == NULL) {
1980                               errx(1, "malloc failed");
1981                     }
1982                     snprintf(special, len, "%sr%s", _PATH_DEV, device);
1983                     if (stat(special, &st) == -1) {
1984                               snprintf(special, len, "%s%s", _PATH_DEV, device);
1985                               if (stat(special, &st) == -1) {
1986                                         snprintf(special, len, "%svinum/r%s",
1987                                             _PATH_DEV, device);
1988                                         if (stat(special, &st) == -1) {
1989                                                   /* For now this is the 'last resort' */
1990                                                   snprintf(special, len, "%svinum/%s",
1991                                                       _PATH_DEV, device);
1992                                         }
1993                               }
1994                     }
1995                     device = special;
1996           }
1997 
1998           /*
1999            * Try to access our devices for writing ...
2000            */
2001           if (Nflag) {
2002                     fso = -1;
2003           } else {
2004                     fso = open(device, O_WRONLY);
2005                     if (fso < 0) {
2006                               err(1, "%s", device);
2007                     }
2008           }
2009 
2010           /*
2011            * ... and reading.
2012            */
2013           fsi = open(device, O_RDONLY);
2014           if (fsi < 0) {
2015                     err(1, "%s", device);
2016           }
2017 
2018           /*
2019            * Try  to read a label and gess the slice if not  specified.  This
2020            * code  should guess the right thing and avaid to bother the  user
2021            * user with the task of specifying the option -v on vinum volumes.
2022            */
2023           if (ioctl(fsi, DIOCGPART, &pinfo) < 0) {
2024                     if (fstat(fsi, &st) < 0)
2025                               err(1, "unable to figure out the partition size");
2026                     pinfo.media_blocks  = st.st_size / DEV_BSIZE;
2027                     pinfo.media_blksize = DEV_BSIZE;
2028           }
2029 
2030           /*
2031            * Check if that partition looks suited for growing a file system.
2032            */
2033           if (pinfo.media_blocks < 1) {
2034                     errx(1, "partition is unavailable");
2035           }
2036 
2037           /*
2038            * Read the current superblock, and take a backup.
2039            */
2040           rdfs((daddr_t)(SBOFF/DEV_BSIZE), (size_t)SBSIZE, &osblock, fsi);
2041           if (osblock.fs_magic != FS_MAGIC) {
2042                     errx(1, "superblock not recognized");
2043           }
2044           memcpy((void *)&fsun1, (void *)&fsun2, sizeof(fsun2));
2045 
2046           DBG_OPEN("/tmp/growfs.debug"); /* already here we need a superblock */
2047           DBG_DUMP_FS(&sblock,
2048               "old sblock");
2049 
2050           /*
2051            * Determine size to grow to. Default to the full size specified in
2052            * the disk label.
2053            */
2054           sblock.fs_size = dbtofsb(&osblock, pinfo.media_blocks);
2055           if (size != 0) {
2056                     if (size > pinfo.media_blocks){
2057                               errx(1, "There is not enough space (%ju < %d)",
2058                                    (intmax_t)pinfo.media_blocks, size);
2059                     }
2060                     sblock.fs_size = dbtofsb(&osblock, size);
2061           }
2062 
2063           /*
2064            * Are we really growing ?
2065            */
2066           if(osblock.fs_size >= sblock.fs_size) {
2067                     errx(1, "we are not growing (%d->%d)", osblock.fs_size,
2068                         sblock.fs_size);
2069           }
2070 
2071 
2072 #ifdef FSMAXSNAP
2073           /*
2074            * Check if we find an active snapshot.
2075            */
2076           if(ExpertFlag == 0) {
2077                     for(j=0; j<FSMAXSNAP; j++) {
2078                               if(sblock.fs_snapinum[j]) {
2079                                         errx(1, "active snapshot found in filesystem\n"
2080                                             "     please remove all snapshots before "
2081                                             "using growfs\n");
2082                               }
2083                               if(!sblock.fs_snapinum[j]) { /* list is dense */
2084                                         break;
2085                               }
2086                     }
2087           }
2088 #endif
2089 
2090           if (ExpertFlag == 0 && Nflag == 0) {
2091                     printf("We strongly recommend you to make a backup "
2092                         "before growing the Filesystem\n\n"
2093                         " Did you backup your data (Yes/No) ? ");
2094                     fgets(reply, (int)sizeof(reply), stdin);
2095                     if (strcmp(reply, "Yes\n")){
2096                               printf("\n Nothing done \n");
2097                               exit (0);
2098                     }
2099           }
2100 
2101           printf("new filesystemsize is: %d frags\n", sblock.fs_size);
2102 
2103           /*
2104            * Try to access our new last block in the filesystem. Even if we
2105            * later on realize we have to abort our operation, on that block
2106            * there should be no data, so we can't destroy something yet.
2107            */
2108           wtfs((daddr_t)pinfo.media_blocks-1, (size_t)DEV_BSIZE, &sblock, fso,
2109               Nflag);
2110 
2111           /*
2112            * Now calculate new superblock values and check for reasonable
2113            * bound for new file system size:
2114            *     fs_size:    is derived from label or user input
2115            *     fs_dsize:   should get updated in the routines creating or
2116            *                 updating the cylinder groups on the fly
2117            *     fs_cstotal: should get updated in the routines creating or
2118            *                 updating the cylinder groups
2119            */
2120 
2121           /*
2122            * Update the number of cylinders in the filesystem.
2123            */
2124           sblock.fs_ncyl = sblock.fs_size * NSPF(&sblock) / sblock.fs_spc;
2125           if (sblock.fs_size * NSPF(&sblock) > sblock.fs_ncyl * sblock.fs_spc) {
2126                     sblock.fs_ncyl++;
2127           }
2128 
2129           /*
2130            * Update the number of cylinder groups in the filesystem.
2131            */
2132           sblock.fs_ncg = sblock.fs_ncyl / sblock.fs_cpg;
2133           if (sblock.fs_ncyl % sblock.fs_cpg) {
2134                     sblock.fs_ncg++;
2135           }
2136 
2137           if ((sblock.fs_size - (sblock.fs_ncg-1) * sblock.fs_fpg) <
2138               sblock.fs_fpg && cgdmin(&sblock, (sblock.fs_ncg-1))-
2139               cgbase(&sblock, (sblock.fs_ncg-1)) > (sblock.fs_size -
2140               (sblock.fs_ncg-1) * sblock.fs_fpg )) {
2141                     /*
2142                      * The space in the new last cylinder group is too small,
2143                      * so revert back.
2144                      */
2145                     sblock.fs_ncg--;
2146 #if 1 /* this is a bit more safe */
2147                     sblock.fs_ncyl = sblock.fs_ncg * sblock.fs_cpg;
2148 #else
2149                     sblock.fs_ncyl -= sblock.fs_ncyl % sblock.fs_cpg;
2150 #endif
2151                     sblock.fs_ncyl -= sblock.fs_ncyl % sblock.fs_cpg;
2152                     printf( "Warning: %d sector(s) cannot be allocated.\n",
2153                         (sblock.fs_size-(sblock.fs_ncg)*sblock.fs_fpg) *
2154                         NSPF(&sblock));
2155                     sblock.fs_size = sblock.fs_ncyl * sblock.fs_spc / NSPF(&sblock);
2156           }
2157 
2158           /*
2159            * Update the space for the cylinder group summary information in the
2160            * respective cylinder group data area.
2161            */
2162           sblock.fs_cssize =
2163               fragroundup(&sblock, sblock.fs_ncg * sizeof(struct csum));
2164 
2165           if(osblock.fs_size >= sblock.fs_size) {
2166                     errx(1, "not enough new space");
2167           }
2168 
2169           DBG_PRINT0("sblock calculated\n");
2170 
2171           /*
2172            * Ok, everything prepared, so now let's do the tricks.
2173            */
2174           growfs(fsi, fso, Nflag);
2175 
2176           close(fsi);
2177           if(fso>-1) close(fso);
2178 
2179           DBG_CLOSE;
2180 
2181           DBG_LEAVE;
2182           return 0;
2183 }
2184 
2185 /* ************************************************************* usage ***** */
2186 /*
2187  * Dump a line of usage.
2188  */
2189 static void
usage(void)2190 usage(void)
2191 {
2192           DBG_ENTER;
2193 
2194           fprintf(stderr, "usage: growfs [-Ny] [-s size] special\n");
2195 
2196           DBG_LEAVE;
2197           exit(1);
2198 }
2199 
2200 /* *********************************************************** updclst ***** */
2201 /*
2202  * This updates most paramters and the bitmap related to cluster. We have to
2203  * assume, that sblock, osblock, acg are set up.
2204  */
2205 static void
updclst(int block)2206 updclst(int block)
2207 {
2208           static int          lcs=0;
2209 
2210           DBG_ENTER;
2211 
2212           if(sblock.fs_contigsumsize < 1) { /* no clustering */
2213                     return;
2214           }
2215           /*
2216            * update cluster allocation map
2217            */
2218           setbit(cg_clustersfree(&acg), block);
2219 
2220           /*
2221            * update cluster summary table
2222            */
2223           if(!lcs) {
2224                     /*
2225                      * calculate size for the trailing cluster
2226                      */
2227                     for(block--; lcs<sblock.fs_contigsumsize; block--, lcs++ ) {
2228                               if(isclr(cg_clustersfree(&acg), block)){
2229                                         break;
2230                               }
2231                     }
2232           }
2233           if(lcs < sblock.fs_contigsumsize) {
2234                     if(lcs) {
2235                               cg_clustersum(&acg)[lcs]--;
2236                     }
2237                     lcs++;
2238                     cg_clustersum(&acg)[lcs]++;
2239           }
2240 
2241           DBG_LEAVE;
2242           return;
2243 }
2244 
2245 /* *********************************************************** updrefs ***** */
2246 /*
2247  * This updates all references to relocated blocks for the given inode.  The
2248  * inode is given as number within the cylinder group, and the number of the
2249  * cylinder group.
2250  */
2251 static void
updrefs(int cg,ino_t in,struct gfs_bpp * bp,int fsi,int fso,unsigned int Nflag)2252 updrefs(int cg, ino_t in, struct gfs_bpp *bp, int fsi, int fso, unsigned int
2253     Nflag)
2254 {
2255           unsigned int        ictr, ind2ctr, ind3ctr;
2256           ufs_daddr_t         *iptr, *ind2ptr, *ind3ptr;
2257           struct ufs1_dinode  *ino;
2258           int       remaining_blocks;
2259 
2260           DBG_ENTER;
2261 
2262           /*
2263            * XXX We should skip unused inodes even from beeing read from disk
2264            *     here by using the bitmap.
2265            */
2266           ino=ginode(in, fsi, cg);
2267           if(!((ino->di_mode & IFMT)==IFDIR || (ino->di_mode & IFMT)==IFREG ||
2268               (ino->di_mode & IFMT)==IFLNK)) {
2269                     DBG_LEAVE;
2270                     return; /* only check DIR, FILE, LINK */
2271           }
2272           if(((ino->di_mode & IFMT)==IFLNK) && (ino->di_size<UFS1_MAXSYMLINKLEN)) {
2273                     DBG_LEAVE;
2274                     return;   /* skip short symlinks */
2275           }
2276           if(!ino->di_size) {
2277                     DBG_LEAVE;
2278                     return;   /* skip empty file */
2279           }
2280           if(!ino->di_blocks) {
2281                     DBG_LEAVE;
2282                     return;   /* skip empty swiss cheesy file or old fastlink */
2283           }
2284           DBG_PRINT2("scg checking inode (%ju in %d)\n",
2285               (uintmax_t)in,
2286               cg);
2287 
2288           /*
2289            * Start checking all direct blocks.
2290            */
2291           remaining_blocks=howmany(ino->di_size, sblock.fs_bsize);
2292           for(ictr=0; ictr < MIN(UFS_NDADDR, (unsigned int)remaining_blocks);
2293               ictr++) {
2294                     iptr=&(ino->di_db[ictr]);
2295                     if(*iptr) {
2296                               cond_bl_upd(iptr, bp, GFS_PS_INODE, fso, Nflag);
2297                     }
2298           }
2299           DBG_PRINT0("~~scg direct blocks checked\n");
2300 
2301           remaining_blocks-=UFS_NDADDR;
2302           if(remaining_blocks<0) {
2303                     DBG_LEAVE;
2304                     return;
2305           }
2306           if(ino->di_ib[0]) {
2307                     /*
2308                      * Start checking first indirect block
2309                      */
2310                     cond_bl_upd(&(ino->di_ib[0]), bp, GFS_PS_INODE, fso, Nflag);
2311                     i1_src=fsbtodb(&sblock, ino->di_ib[0]);
2312                     rdfs(i1_src, (size_t)sblock.fs_bsize, &i1blk, fsi);
2313                     for(ictr=0; ictr < MIN(howmany(sblock.fs_bsize,
2314                         sizeof(ufs_daddr_t)), (unsigned int)remaining_blocks);
2315                         ictr++) {
2316                               iptr=&((ufs_daddr_t *)(void *)&i1blk)[ictr];
2317                               if(*iptr) {
2318                                         cond_bl_upd(iptr, bp, GFS_PS_IND_BLK_LVL1,
2319                                             fso, Nflag);
2320                               }
2321                     }
2322           }
2323           DBG_PRINT0("scg indirect_1 blocks checked\n");
2324 
2325           remaining_blocks-= howmany(sblock.fs_bsize, sizeof(ufs_daddr_t));
2326           if(remaining_blocks<0) {
2327                     DBG_LEAVE;
2328                     return;
2329           }
2330           if(ino->di_ib[1]) {
2331                     /*
2332                      * Start checking second indirect block
2333                      */
2334                     cond_bl_upd(&(ino->di_ib[1]), bp, GFS_PS_INODE, fso, Nflag);
2335                     i2_src=fsbtodb(&sblock, ino->di_ib[1]);
2336                     rdfs(i2_src, (size_t)sblock.fs_bsize, &i2blk, fsi);
2337                     for(ind2ctr=0; ind2ctr < howmany(sblock.fs_bsize,
2338                         sizeof(ufs_daddr_t)); ind2ctr++) {
2339                               ind2ptr=&((ufs_daddr_t *)(void *)&i2blk)[ind2ctr];
2340                               if(!*ind2ptr) {
2341                                         continue;
2342                               }
2343                               cond_bl_upd(ind2ptr, bp, GFS_PS_IND_BLK_LVL2, fso,
2344                                   Nflag);
2345                               i1_src=fsbtodb(&sblock, *ind2ptr);
2346                               rdfs(i1_src, (size_t)sblock.fs_bsize, &i1blk,
2347                                   fsi);
2348                               for(ictr=0; ictr<MIN(howmany((unsigned int)
2349                                   sblock.fs_bsize, sizeof(ufs_daddr_t)),
2350                                   (unsigned int)remaining_blocks); ictr++) {
2351                                         iptr=&((ufs_daddr_t *)(void *)&i1blk)[ictr];
2352                                         if(*iptr) {
2353                                                   cond_bl_upd(iptr, bp,
2354                                                       GFS_PS_IND_BLK_LVL1, fso, Nflag);
2355                                         }
2356                               }
2357                     }
2358           }
2359           DBG_PRINT0("scg indirect_2 blocks checked\n");
2360 
2361 #define SQUARE(a) ((a)*(a))
2362           remaining_blocks-=SQUARE(howmany(sblock.fs_bsize, sizeof(ufs_daddr_t)));
2363 #undef SQUARE
2364           if(remaining_blocks<0) {
2365                     DBG_LEAVE;
2366                     return;
2367           }
2368 
2369           if(ino->di_ib[2]) {
2370                     /*
2371                      * Start checking third indirect block
2372                      */
2373                     cond_bl_upd(&(ino->di_ib[2]), bp, GFS_PS_INODE, fso, Nflag);
2374                     i3_src=fsbtodb(&sblock, ino->di_ib[2]);
2375                     rdfs(i3_src, (size_t)sblock.fs_bsize, &i3blk, fsi);
2376                     for(ind3ctr=0; ind3ctr < howmany(sblock.fs_bsize,
2377                         sizeof(ufs_daddr_t)); ind3ctr ++) {
2378                               ind3ptr=&((ufs_daddr_t *)(void *)&i3blk)[ind3ctr];
2379                               if(!*ind3ptr) {
2380                                         continue;
2381                               }
2382                               cond_bl_upd(ind3ptr, bp, GFS_PS_IND_BLK_LVL3, fso,
2383                                   Nflag);
2384                               i2_src=fsbtodb(&sblock, *ind3ptr);
2385                               rdfs(i2_src, (size_t)sblock.fs_bsize, &i2blk,
2386                                   fsi);
2387                               for(ind2ctr=0; ind2ctr < howmany(sblock.fs_bsize,
2388                                   sizeof(ufs_daddr_t)); ind2ctr ++) {
2389                                         ind2ptr=&((ufs_daddr_t *)(void *)&i2blk)
2390                                             [ind2ctr];
2391                                         if(!*ind2ptr) {
2392                                                   continue;
2393                                         }
2394                                         cond_bl_upd(ind2ptr, bp, GFS_PS_IND_BLK_LVL2,
2395                                             fso, Nflag);
2396                                         i1_src=fsbtodb(&sblock, *ind2ptr);
2397                                         rdfs(i1_src, (size_t)sblock.fs_bsize,
2398                                             &i1blk, fsi);
2399                                         for(ictr=0; ictr < MIN(howmany(sblock.fs_bsize,
2400                                             sizeof(ufs_daddr_t)),
2401                                             (unsigned int)remaining_blocks); ictr++) {
2402                                                   iptr=&((ufs_daddr_t *)(void *)&i1blk)
2403                                                       [ictr];
2404                                                   if(*iptr) {
2405                                                             cond_bl_upd(iptr, bp,
2406                                                                 GFS_PS_IND_BLK_LVL1, fso,
2407                                                                 Nflag);
2408                                                   }
2409                                         }
2410                               }
2411                     }
2412           }
2413 
2414           DBG_PRINT0("scg indirect_3 blocks checked\n");
2415 
2416           DBG_LEAVE;
2417           return;
2418 }
2419 
2420