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