1df57947fSPedro F. Giffuni /*-
2df57947fSPedro F. Giffuni * SPDX-License-Identifier: BSD-4-Clause
3df57947fSPedro F. Giffuni *
43d500078SThomas-Henning von Kamptz * Copyright (c) 1980, 1989, 1993 The Regents of the University of California.
5e35497f1SEdward Tomasz Napierala * Copyright (c) 2000 Christoph Herrmann, Thomas-Henning von Kamptz
6e35497f1SEdward Tomasz Napierala * Copyright (c) 2012 The FreeBSD Foundation
73d500078SThomas-Henning von Kamptz * All rights reserved.
83d500078SThomas-Henning von Kamptz *
93d500078SThomas-Henning von Kamptz * This code is derived from software contributed to Berkeley by
103d500078SThomas-Henning von Kamptz * Christoph Herrmann and Thomas-Henning von Kamptz, Munich and Frankfurt.
113d500078SThomas-Henning von Kamptz *
12e35497f1SEdward Tomasz Napierala * Portions of this software were developed by Edward Tomasz Napierala
13e35497f1SEdward Tomasz Napierala * under sponsorship from the FreeBSD Foundation.
14e35497f1SEdward Tomasz Napierala *
153d500078SThomas-Henning von Kamptz * Redistribution and use in source and binary forms, with or without
163d500078SThomas-Henning von Kamptz * modification, are permitted provided that the following conditions
173d500078SThomas-Henning von Kamptz * are met:
183d500078SThomas-Henning von Kamptz * 1. Redistributions of source code must retain the above copyright
193d500078SThomas-Henning von Kamptz * notice, this list of conditions and the following disclaimer.
203d500078SThomas-Henning von Kamptz * 2. Redistributions in binary form must reproduce the above copyright
213d500078SThomas-Henning von Kamptz * notice, this list of conditions and the following disclaimer in the
223d500078SThomas-Henning von Kamptz * documentation and/or other materials provided with the distribution.
233d500078SThomas-Henning von Kamptz * 3. All advertising materials mentioning features or use of this software
243d500078SThomas-Henning von Kamptz * must display the following acknowledgment:
253d500078SThomas-Henning von Kamptz * This product includes software developed by the University of
263d500078SThomas-Henning von Kamptz * California, Berkeley and its contributors, as well as Christoph
273d500078SThomas-Henning von Kamptz * Herrmann and Thomas-Henning von Kamptz.
283d500078SThomas-Henning von Kamptz * 4. Neither the name of the University nor the names of its contributors
293d500078SThomas-Henning von Kamptz * may be used to endorse or promote products derived from this software
303d500078SThomas-Henning von Kamptz * without specific prior written permission.
313d500078SThomas-Henning von Kamptz *
323d500078SThomas-Henning von Kamptz * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
333d500078SThomas-Henning von Kamptz * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
343d500078SThomas-Henning von Kamptz * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
353d500078SThomas-Henning von Kamptz * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
363d500078SThomas-Henning von Kamptz * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
373d500078SThomas-Henning von Kamptz * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
383d500078SThomas-Henning von Kamptz * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
393d500078SThomas-Henning von Kamptz * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
403d500078SThomas-Henning von Kamptz * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
413d500078SThomas-Henning von Kamptz * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
423d500078SThomas-Henning von Kamptz * SUCH DAMAGE.
433d500078SThomas-Henning von Kamptz *
444020c5bcSThomas-Henning von Kamptz * $TSHeader: src/sbin/growfs/growfs.c,v 1.5 2000/12/12 19:31:00 tomsoft Exp $
453d500078SThomas-Henning von Kamptz *
463d500078SThomas-Henning von Kamptz */
473d500078SThomas-Henning von Kamptz
483d500078SThomas-Henning von Kamptz #include <sys/param.h>
493d500078SThomas-Henning von Kamptz #include <sys/ioctl.h>
503d500078SThomas-Henning von Kamptz #include <sys/stat.h>
514b9748d4SGreg Lehey #include <sys/disk.h>
52e35497f1SEdward Tomasz Napierala #include <sys/ucred.h>
53e35497f1SEdward Tomasz Napierala #include <sys/mount.h>
543d500078SThomas-Henning von Kamptz
553d500078SThomas-Henning von Kamptz #include <stdio.h>
563d500078SThomas-Henning von Kamptz #include <paths.h>
573d500078SThomas-Henning von Kamptz #include <ctype.h>
583d500078SThomas-Henning von Kamptz #include <err.h>
59dffce215SKirk McKusick #include <errno.h>
603d500078SThomas-Henning von Kamptz #include <fcntl.h>
61e35497f1SEdward Tomasz Napierala #include <fstab.h>
62e35497f1SEdward Tomasz Napierala #include <inttypes.h>
6389fdc4e1SMike Barcroft #include <limits.h>
64e35497f1SEdward Tomasz Napierala #include <mntopts.h>
652ec1a006SEdward Tomasz Napierala #include <paths.h>
663d500078SThomas-Henning von Kamptz #include <stdlib.h>
6775d1ec91SLukas Ertl #include <stdint.h>
683d500078SThomas-Henning von Kamptz #include <string.h>
6935cf80deSBruce Evans #include <time.h>
703d500078SThomas-Henning von Kamptz #include <unistd.h>
713d500078SThomas-Henning von Kamptz #include <ufs/ufs/dinode.h>
723d500078SThomas-Henning von Kamptz #include <ufs/ffs/fs.h>
73e35497f1SEdward Tomasz Napierala #include <libutil.h>
743abf5d76SKirk McKusick #include <libufs.h>
753d500078SThomas-Henning von Kamptz
763d500078SThomas-Henning von Kamptz #include "debug.h"
773d500078SThomas-Henning von Kamptz
783d500078SThomas-Henning von Kamptz #ifdef FS_DEBUG
793d500078SThomas-Henning von Kamptz int _dbg_lvl_ = (DL_INFO); /* DL_TRC */
803d500078SThomas-Henning von Kamptz #endif /* FS_DEBUG */
813d500078SThomas-Henning von Kamptz
823d500078SThomas-Henning von Kamptz static union {
833d500078SThomas-Henning von Kamptz struct fs fs;
841c85e6a3SKirk McKusick char pad[SBLOCKSIZE];
853d500078SThomas-Henning von Kamptz } fsun1, fsun2;
863d500078SThomas-Henning von Kamptz #define sblock fsun1.fs /* the new superblock */
873d500078SThomas-Henning von Kamptz #define osblock fsun2.fs /* the old superblock */
883d500078SThomas-Henning von Kamptz
893d500078SThomas-Henning von Kamptz static union {
903d500078SThomas-Henning von Kamptz struct cg cg;
913d500078SThomas-Henning von Kamptz char pad[MAXBSIZE];
923d500078SThomas-Henning von Kamptz } cgun1, cgun2;
933d500078SThomas-Henning von Kamptz #define acg cgun1.cg /* a cylinder cgroup (new) */
943d500078SThomas-Henning von Kamptz #define aocg cgun2.cg /* an old cylinder group */
953d500078SThomas-Henning von Kamptz
963d500078SThomas-Henning von Kamptz static struct csum *fscs; /* cylinder summary */
973d500078SThomas-Henning von Kamptz
98adcaff07SThomas-Henning von Kamptz static void growfs(int, int, unsigned int);
991c85e6a3SKirk McKusick static void rdfs(ufs2_daddr_t, size_t, void *, int);
1001c85e6a3SKirk McKusick static void wtfs(ufs2_daddr_t, size_t, void *, int, unsigned int);
1013d500078SThomas-Henning von Kamptz static int charsperline(void);
1024020c5bcSThomas-Henning von Kamptz static void usage(void);
1033d500078SThomas-Henning von Kamptz static int isblock(struct fs *, unsigned char *, int);
1043d500078SThomas-Henning von Kamptz static void clrblock(struct fs *, unsigned char *, int);
1053d500078SThomas-Henning von Kamptz static void setblock(struct fs *, unsigned char *, int);
106adcaff07SThomas-Henning von Kamptz static void initcg(int, time_t, int, unsigned int);
107adcaff07SThomas-Henning von Kamptz static void updjcg(int, time_t, int, int, unsigned int);
108adcaff07SThomas-Henning von Kamptz static void updcsloc(time_t, int, int, unsigned int);
1091c85e6a3SKirk McKusick static void frag_adjust(ufs2_daddr_t, int);
1103d500078SThomas-Henning von Kamptz static void updclst(int);
1113abf5d76SKirk McKusick static void cgckhash(struct cg *);
1123d500078SThomas-Henning von Kamptz
1133d500078SThomas-Henning von Kamptz /*
1143d500078SThomas-Henning von Kamptz * Here we actually start growing the file system. We basically read the
1154020c5bcSThomas-Henning von Kamptz * cylinder summary from the first cylinder group as we want to update
1163d500078SThomas-Henning von Kamptz * this on the fly during our various operations. First we handle the
1173d500078SThomas-Henning von Kamptz * changes in the former last cylinder group. Afterwards we create all new
1183d500078SThomas-Henning von Kamptz * cylinder groups. Now we handle the cylinder group containing the
1193d500078SThomas-Henning von Kamptz * cylinder summary which might result in a relocation of the whole
1203d500078SThomas-Henning von Kamptz * structure. In the end we write back the updated cylinder summary, the
1213d500078SThomas-Henning von Kamptz * new superblock, and slightly patched versions of the super block
1223d500078SThomas-Henning von Kamptz * copies.
1233d500078SThomas-Henning von Kamptz */
1243d500078SThomas-Henning von Kamptz static void
growfs(int fsi,int fso,unsigned int Nflag)125adcaff07SThomas-Henning von Kamptz growfs(int fsi, int fso, unsigned int Nflag)
1263d500078SThomas-Henning von Kamptz {
1273d500078SThomas-Henning von Kamptz DBG_FUNC("growfs")
128ea6de5eeSMarcel Moolenaar time_t modtime;
12914a176a0SKirk McKusick uint cylno;
13014a176a0SKirk McKusick int i, j, width;
1313d500078SThomas-Henning von Kamptz char tmpbuf[100];
1323d500078SThomas-Henning von Kamptz
1333d500078SThomas-Henning von Kamptz DBG_ENTER;
1343d500078SThomas-Henning von Kamptz
135ea6de5eeSMarcel Moolenaar time(&modtime);
1363d500078SThomas-Henning von Kamptz
1373d500078SThomas-Henning von Kamptz /*
1383d500078SThomas-Henning von Kamptz * Get the cylinder summary into the memory.
1393d500078SThomas-Henning von Kamptz */
140adcaff07SThomas-Henning von Kamptz fscs = (struct csum *)calloc((size_t)1, (size_t)sblock.fs_cssize);
141a1da0740SEdward Tomasz Napierala if (fscs == NULL)
14270a0fb43SMina Galić errx(3, "calloc failed");
143dffce215SKirk McKusick memcpy(fscs, osblock.fs_csp, osblock.fs_cssize);
144dffce215SKirk McKusick free(osblock.fs_csp);
145dffce215SKirk McKusick osblock.fs_csp = NULL;
146dffce215SKirk McKusick sblock.fs_csp = fscs;
1473d500078SThomas-Henning von Kamptz
1483d500078SThomas-Henning von Kamptz #ifdef FS_DEBUG
1493d500078SThomas-Henning von Kamptz {
1503d500078SThomas-Henning von Kamptz struct csum *dbg_csp;
151a44ba043SEdward Tomasz Napierala u_int32_t dbg_csc;
1523d500078SThomas-Henning von Kamptz char dbg_line[80];
1533d500078SThomas-Henning von Kamptz
1543d500078SThomas-Henning von Kamptz dbg_csp = fscs;
155a1da0740SEdward Tomasz Napierala
1563d500078SThomas-Henning von Kamptz for (dbg_csc = 0; dbg_csc < osblock.fs_ncg; dbg_csc++) {
157adcaff07SThomas-Henning von Kamptz snprintf(dbg_line, sizeof(dbg_line),
158adcaff07SThomas-Henning von Kamptz "%d. old csum in old location", dbg_csc);
159a1da0740SEdward Tomasz Napierala DBG_DUMP_CSUM(&osblock, dbg_line, dbg_csp++);
1603d500078SThomas-Henning von Kamptz }
1613d500078SThomas-Henning von Kamptz }
1623d500078SThomas-Henning von Kamptz #endif /* FS_DEBUG */
1633d500078SThomas-Henning von Kamptz DBG_PRINT0("fscs read\n");
1643d500078SThomas-Henning von Kamptz
1653d500078SThomas-Henning von Kamptz /*
1663d500078SThomas-Henning von Kamptz * Do all needed changes in the former last cylinder group.
1673d500078SThomas-Henning von Kamptz */
168ea6de5eeSMarcel Moolenaar updjcg(osblock.fs_ncg - 1, modtime, fsi, fso, Nflag);
1693d500078SThomas-Henning von Kamptz
1703d500078SThomas-Henning von Kamptz /*
1713d500078SThomas-Henning von Kamptz * Dump out summary information about file system.
1723d500078SThomas-Henning von Kamptz */
173e35497f1SEdward Tomasz Napierala #ifdef FS_DEBUG
1743d500078SThomas-Henning von Kamptz #define B2MBFACTOR (1 / (1024.0 * 1024.0))
175760ea1faSMaxime Henrion printf("growfs: %.1fMB (%jd sectors) block size %d, fragment size %d\n",
1763d500078SThomas-Henning von Kamptz (float)sblock.fs_size * sblock.fs_fsize * B2MBFACTOR,
177760ea1faSMaxime Henrion (intmax_t)fsbtodb(&sblock, sblock.fs_size), sblock.fs_bsize,
178760ea1faSMaxime Henrion sblock.fs_fsize);
1791c85e6a3SKirk McKusick printf("\tusing %d cylinder groups of %.2fMB, %d blks, %d inodes.\n",
1801c85e6a3SKirk McKusick sblock.fs_ncg, (float)sblock.fs_fpg * sblock.fs_fsize * B2MBFACTOR,
1811c85e6a3SKirk McKusick sblock.fs_fpg / sblock.fs_frag, sblock.fs_ipg);
1821c85e6a3SKirk McKusick if (sblock.fs_flags & FS_DOSOFTDEP)
1831c85e6a3SKirk McKusick printf("\twith soft updates\n");
1843d500078SThomas-Henning von Kamptz #undef B2MBFACTOR
185e35497f1SEdward Tomasz Napierala #endif /* FS_DEBUG */
1863d500078SThomas-Henning von Kamptz
1873d500078SThomas-Henning von Kamptz /*
1883d500078SThomas-Henning von Kamptz * Now build the cylinders group blocks and
1893d500078SThomas-Henning von Kamptz * then print out indices of cylinder groups.
1903d500078SThomas-Henning von Kamptz */
191295a5bd7SChristian Brueffer printf("super-block backups (for fsck_ffs -b #) at:\n");
1923d500078SThomas-Henning von Kamptz i = 0;
1933d500078SThomas-Henning von Kamptz width = charsperline();
1943d500078SThomas-Henning von Kamptz
1953d500078SThomas-Henning von Kamptz /*
1963d500078SThomas-Henning von Kamptz * Iterate for only the new cylinder groups.
1973d500078SThomas-Henning von Kamptz */
1983d500078SThomas-Henning von Kamptz for (cylno = osblock.fs_ncg; cylno < sblock.fs_ncg; cylno++) {
199ea6de5eeSMarcel Moolenaar initcg(cylno, modtime, fso, Nflag);
200baa15be0SDavid Schultz j = sprintf(tmpbuf, " %jd%s",
201baa15be0SDavid Schultz (intmax_t)fsbtodb(&sblock, cgsblock(&sblock, cylno)),
2023d500078SThomas-Henning von Kamptz cylno < (sblock.fs_ncg - 1) ? "," : "" );
2033d500078SThomas-Henning von Kamptz if (i + j >= width) {
2043d500078SThomas-Henning von Kamptz printf("\n");
2053d500078SThomas-Henning von Kamptz i = 0;
2063d500078SThomas-Henning von Kamptz }
2073d500078SThomas-Henning von Kamptz i += j;
2083d500078SThomas-Henning von Kamptz printf("%s", tmpbuf);
2093d500078SThomas-Henning von Kamptz fflush(stdout);
2103d500078SThomas-Henning von Kamptz }
2113d500078SThomas-Henning von Kamptz printf("\n");
2123d500078SThomas-Henning von Kamptz
2133d500078SThomas-Henning von Kamptz /*
2143d500078SThomas-Henning von Kamptz * Do all needed changes in the first cylinder group.
2153d500078SThomas-Henning von Kamptz * allocate blocks in new location
2163d500078SThomas-Henning von Kamptz */
217ea6de5eeSMarcel Moolenaar updcsloc(modtime, fsi, fso, Nflag);
2183d500078SThomas-Henning von Kamptz
2193d500078SThomas-Henning von Kamptz /*
220dffce215SKirk McKusick * Clean up the dynamic fields in our superblock.
221dffce215SKirk McKusick *
222dffce215SKirk McKusick * XXX
223dffce215SKirk McKusick * The following fields are currently distributed from the superblock
224dffce215SKirk McKusick * to the copies:
225dffce215SKirk McKusick * fs_minfree
226dffce215SKirk McKusick * fs_rotdelay
227dffce215SKirk McKusick * fs_maxcontig
228dffce215SKirk McKusick * fs_maxbpg
229dffce215SKirk McKusick * fs_minfree,
230dffce215SKirk McKusick * fs_optim
231dffce215SKirk McKusick * fs_flags
232dffce215SKirk McKusick *
233dffce215SKirk McKusick * We probably should rather change the summary for the cylinder group
234dffce215SKirk McKusick * statistics here to the value of what would be in there, if the file
235*26c3d72eSHUANG,YU-JIA * system were created initially with the new size. Therefore we still
236dffce215SKirk McKusick * need to find an easy way of calculating that.
237dffce215SKirk McKusick * Possibly we can try to read the first superblock copy and apply the
238dffce215SKirk McKusick * "diffed" stats between the old and new superblock by still copying
239dffce215SKirk McKusick * certain parameters onto that.
2403d500078SThomas-Henning von Kamptz */
241dffce215SKirk McKusick sblock.fs_time = modtime;
242dffce215SKirk McKusick sblock.fs_fmod = 0;
243dffce215SKirk McKusick sblock.fs_clean = 1;
244dffce215SKirk McKusick sblock.fs_ronly = 0;
245dffce215SKirk McKusick sblock.fs_cgrotor = 0;
246dffce215SKirk McKusick sblock.fs_state = 0;
247dffce215SKirk McKusick memset((void *)&sblock.fs_fsmnt, 0, sizeof(sblock.fs_fsmnt));
248dffce215SKirk McKusick
249dffce215SKirk McKusick /*
250dffce215SKirk McKusick * Now write the new superblock, its summary information,
251dffce215SKirk McKusick * and all the alternates back to disk.
252dffce215SKirk McKusick */
253dffce215SKirk McKusick if (!Nflag && sbput(fso, &sblock, sblock.fs_ncg) != 0)
25470a0fb43SMina Galić errc(3, EIO, "could not write updated superblock");
2553d500078SThomas-Henning von Kamptz DBG_PRINT0("fscs written\n");
2563d500078SThomas-Henning von Kamptz
2573d500078SThomas-Henning von Kamptz #ifdef FS_DEBUG
2583d500078SThomas-Henning von Kamptz {
2593d500078SThomas-Henning von Kamptz struct csum *dbg_csp;
260a44ba043SEdward Tomasz Napierala u_int32_t dbg_csc;
2613d500078SThomas-Henning von Kamptz char dbg_line[80];
2623d500078SThomas-Henning von Kamptz
2633d500078SThomas-Henning von Kamptz dbg_csp = fscs;
2643d500078SThomas-Henning von Kamptz for (dbg_csc = 0; dbg_csc < sblock.fs_ncg; dbg_csc++) {
265adcaff07SThomas-Henning von Kamptz snprintf(dbg_line, sizeof(dbg_line),
266adcaff07SThomas-Henning von Kamptz "%d. new csum in new location", dbg_csc);
267a1da0740SEdward Tomasz Napierala DBG_DUMP_CSUM(&sblock, dbg_line, dbg_csp++);
2683d500078SThomas-Henning von Kamptz }
2693d500078SThomas-Henning von Kamptz }
2703d500078SThomas-Henning von Kamptz #endif /* FS_DEBUG */
2713d500078SThomas-Henning von Kamptz
2723d500078SThomas-Henning von Kamptz DBG_PRINT0("sblock written\n");
273a1da0740SEdward Tomasz Napierala DBG_DUMP_FS(&sblock, "new initial sblock");
2743d500078SThomas-Henning von Kamptz
2753d500078SThomas-Henning von Kamptz DBG_PRINT0("sblock copies written\n");
276a1da0740SEdward Tomasz Napierala DBG_DUMP_FS(&sblock, "new other sblocks");
2773d500078SThomas-Henning von Kamptz
2783d500078SThomas-Henning von Kamptz DBG_LEAVE;
2793d500078SThomas-Henning von Kamptz return;
2803d500078SThomas-Henning von Kamptz }
2813d500078SThomas-Henning von Kamptz
2823d500078SThomas-Henning von Kamptz /*
2833d500078SThomas-Henning von Kamptz * This creates a new cylinder group structure, for more details please see
2843d500078SThomas-Henning von Kamptz * the source of newfs(8), as this function is taken over almost unchanged.
2853d500078SThomas-Henning von Kamptz * As this is never called for the first cylinder group, the special
2863d500078SThomas-Henning von Kamptz * provisions for that case are removed here.
2873d500078SThomas-Henning von Kamptz */
2883d500078SThomas-Henning von Kamptz static void
initcg(int cylno,time_t modtime,int fso,unsigned int Nflag)289ea6de5eeSMarcel Moolenaar initcg(int cylno, time_t modtime, int fso, unsigned int Nflag)
2903d500078SThomas-Henning von Kamptz {
2913d500078SThomas-Henning von Kamptz DBG_FUNC("initcg")
2921ad5f80fSBrian Somers static caddr_t iobuf;
2939fc5d538SKirk McKusick static long iobufsize;
29414a176a0SKirk McKusick long blkno, start;
295e25a029eSMatthew D Fleming ino_t ino;
29675d1ec91SLukas Ertl ufs2_daddr_t i, cbase, dmax;
2971c85e6a3SKirk McKusick struct ufs1_dinode *dp1;
2989fc5d538SKirk McKusick struct ufs2_dinode *dp2;
2993d438ad6SDavid E. O'Brien struct csum *cs;
300b408e19cSEdward Tomasz Napierala uint j, d, dupper, dlower;
3013d500078SThomas-Henning von Kamptz
3029fc5d538SKirk McKusick if (iobuf == NULL) {
3039fc5d538SKirk McKusick iobufsize = 2 * sblock.fs_bsize;
3049fc5d538SKirk McKusick if ((iobuf = malloc(iobufsize)) == NULL)
3051c85e6a3SKirk McKusick errx(37, "panic: cannot allocate I/O buffer");
3069fc5d538SKirk McKusick memset(iobuf, '\0', iobufsize);
3079fc5d538SKirk McKusick }
3083d500078SThomas-Henning von Kamptz /*
3093d500078SThomas-Henning von Kamptz * Determine block bounds for cylinder group.
3101c85e6a3SKirk McKusick * Allow space for super block summary information in first
3111c85e6a3SKirk McKusick * cylinder group.
3123d500078SThomas-Henning von Kamptz */
3133d500078SThomas-Henning von Kamptz cbase = cgbase(&sblock, cylno);
3143d500078SThomas-Henning von Kamptz dmax = cbase + sblock.fs_fpg;
3151c85e6a3SKirk McKusick if (dmax > sblock.fs_size)
3163d500078SThomas-Henning von Kamptz dmax = sblock.fs_size;
3173d500078SThomas-Henning von Kamptz dlower = cgsblock(&sblock, cylno) - cbase;
3183d500078SThomas-Henning von Kamptz dupper = cgdmin(&sblock, cylno) - cbase;
3191c85e6a3SKirk McKusick if (cylno == 0) /* XXX fscs may be relocated */
3203d500078SThomas-Henning von Kamptz dupper += howmany(sblock.fs_cssize, sblock.fs_fsize);
3211c85e6a3SKirk McKusick cs = &fscs[cylno];
3221c85e6a3SKirk McKusick memset(&acg, 0, sblock.fs_cgsize);
323ea6de5eeSMarcel Moolenaar acg.cg_time = modtime;
3243d500078SThomas-Henning von Kamptz acg.cg_magic = CG_MAGIC;
3253d500078SThomas-Henning von Kamptz acg.cg_cgx = cylno;
3263d500078SThomas-Henning von Kamptz acg.cg_niblk = sblock.fs_ipg;
327e921a133SMarcelo Araujo acg.cg_initediblk = MIN(sblock.fs_ipg, 2 * INOPB(&sblock));
3283d500078SThomas-Henning von Kamptz acg.cg_ndblk = dmax - cbase;
3291c85e6a3SKirk McKusick if (sblock.fs_contigsumsize > 0)
3303d500078SThomas-Henning von Kamptz acg.cg_nclusterblks = acg.cg_ndblk / sblock.fs_frag;
3310a6e34e9SKirk McKusick start = sizeof(acg);
3321c85e6a3SKirk McKusick if (sblock.fs_magic == FS_UFS2_MAGIC) {
3331c85e6a3SKirk McKusick acg.cg_iusedoff = start;
3343d500078SThomas-Henning von Kamptz } else {
3351c85e6a3SKirk McKusick acg.cg_old_ncyl = sblock.fs_old_cpg;
3361c85e6a3SKirk McKusick acg.cg_old_time = acg.cg_time;
3371c85e6a3SKirk McKusick acg.cg_time = 0;
3381c85e6a3SKirk McKusick acg.cg_old_niblk = acg.cg_niblk;
3391c85e6a3SKirk McKusick acg.cg_niblk = 0;
3401ad5f80fSBrian Somers acg.cg_initediblk = 0;
3411c85e6a3SKirk McKusick acg.cg_old_btotoff = start;
3421c85e6a3SKirk McKusick acg.cg_old_boff = acg.cg_old_btotoff +
3431c85e6a3SKirk McKusick sblock.fs_old_cpg * sizeof(int32_t);
3441c85e6a3SKirk McKusick acg.cg_iusedoff = acg.cg_old_boff +
3451c85e6a3SKirk McKusick sblock.fs_old_cpg * sizeof(u_int16_t);
3461c85e6a3SKirk McKusick }
34789fdc4e1SMike Barcroft acg.cg_freeoff = acg.cg_iusedoff + howmany(sblock.fs_ipg, CHAR_BIT);
34889fdc4e1SMike Barcroft acg.cg_nextfreeoff = acg.cg_freeoff + howmany(sblock.fs_fpg, CHAR_BIT);
3491c85e6a3SKirk McKusick if (sblock.fs_contigsumsize > 0) {
3503d500078SThomas-Henning von Kamptz acg.cg_clustersumoff =
3511c85e6a3SKirk McKusick roundup(acg.cg_nextfreeoff, sizeof(u_int32_t));
3521c85e6a3SKirk McKusick acg.cg_clustersumoff -= sizeof(u_int32_t);
3533d500078SThomas-Henning von Kamptz acg.cg_clusteroff = acg.cg_clustersumoff +
3543d500078SThomas-Henning von Kamptz (sblock.fs_contigsumsize + 1) * sizeof(u_int32_t);
3551c85e6a3SKirk McKusick acg.cg_nextfreeoff = acg.cg_clusteroff +
35689fdc4e1SMike Barcroft howmany(fragstoblks(&sblock, sblock.fs_fpg), CHAR_BIT);
3573d500078SThomas-Henning von Kamptz }
35814a176a0SKirk McKusick if (acg.cg_nextfreeoff > (unsigned)sblock.fs_cgsize) {
3593d500078SThomas-Henning von Kamptz /*
3601c85e6a3SKirk McKusick * This should never happen as we would have had that panic
3613d500078SThomas-Henning von Kamptz * already on file system creation
3623d500078SThomas-Henning von Kamptz */
3634020c5bcSThomas-Henning von Kamptz errx(37, "panic: cylinder group too big");
3643d500078SThomas-Henning von Kamptz }
3653d500078SThomas-Henning von Kamptz acg.cg_cs.cs_nifree += sblock.fs_ipg;
3663d500078SThomas-Henning von Kamptz if (cylno == 0)
3671dc349abSEd Maste for (ino = 0; ino < UFS_ROOTINO; ino++) {
368e25a029eSMatthew D Fleming setbit(cg_inosused(&acg), ino);
3693d500078SThomas-Henning von Kamptz acg.cg_cs.cs_nifree--;
3703d500078SThomas-Henning von Kamptz }
371e7c46054SScott Long /*
3729fc5d538SKirk McKusick * Initialize the initial inode blocks.
3739fc5d538SKirk McKusick */
3749fc5d538SKirk McKusick dp1 = (struct ufs1_dinode *)(void *)iobuf;
3759fc5d538SKirk McKusick dp2 = (struct ufs2_dinode *)(void *)iobuf;
3769fc5d538SKirk McKusick for (i = 0; i < acg.cg_initediblk; i++) {
3779fc5d538SKirk McKusick if (sblock.fs_magic == FS_UFS1_MAGIC) {
3789fc5d538SKirk McKusick dp1->di_gen = arc4random();
3799fc5d538SKirk McKusick dp1++;
3809fc5d538SKirk McKusick } else {
3819fc5d538SKirk McKusick dp2->di_gen = arc4random();
3829fc5d538SKirk McKusick dp2++;
3839fc5d538SKirk McKusick }
3849fc5d538SKirk McKusick }
3859fc5d538SKirk McKusick wtfs(fsbtodb(&sblock, cgimin(&sblock, cylno)), iobufsize, iobuf,
3869fc5d538SKirk McKusick fso, Nflag);
3879fc5d538SKirk McKusick /*
38808f353ebSGavin Atkinson * For the old file system, we have to initialize all the inodes.
389e7c46054SScott Long */
3909fc5d538SKirk McKusick if (sblock.fs_magic == FS_UFS1_MAGIC &&
3919fc5d538SKirk McKusick sblock.fs_ipg > 2 * INOPB(&sblock)) {
3929fc5d538SKirk McKusick for (i = 2 * sblock.fs_frag;
3939fc5d538SKirk McKusick i < sblock.fs_ipg / INOPF(&sblock);
394e7c46054SScott Long i += sblock.fs_frag) {
39511dc4806SEd Schouten dp1 = (struct ufs1_dinode *)(void *)iobuf;
396eb747250SGavin Atkinson for (j = 0; j < INOPB(&sblock); j++) {
39744246b4cSXin LI dp1->di_gen = arc4random();
3981c85e6a3SKirk McKusick dp1++;
3993d500078SThomas-Henning von Kamptz }
4003d500078SThomas-Henning von Kamptz wtfs(fsbtodb(&sblock, cgimin(&sblock, cylno) + i),
4011c85e6a3SKirk McKusick sblock.fs_bsize, iobuf, fso, Nflag);
4023d500078SThomas-Henning von Kamptz }
403e7c46054SScott Long }
4041c85e6a3SKirk McKusick if (cylno > 0) {
4051c85e6a3SKirk McKusick /*
4061c85e6a3SKirk McKusick * In cylno 0, beginning space is reserved
4071c85e6a3SKirk McKusick * for boot and super blocks.
4081c85e6a3SKirk McKusick */
4093d500078SThomas-Henning von Kamptz for (d = 0; d < dlower; d += sblock.fs_frag) {
4103d500078SThomas-Henning von Kamptz blkno = d / sblock.fs_frag;
4113d500078SThomas-Henning von Kamptz setblock(&sblock, cg_blksfree(&acg), blkno);
4121c85e6a3SKirk McKusick if (sblock.fs_contigsumsize > 0)
4133d500078SThomas-Henning von Kamptz setbit(cg_clustersfree(&acg), blkno);
4143d500078SThomas-Henning von Kamptz acg.cg_cs.cs_nbfree++;
4153d500078SThomas-Henning von Kamptz }
4163d500078SThomas-Henning von Kamptz sblock.fs_dsize += dlower;
4171c85e6a3SKirk McKusick }
4183d500078SThomas-Henning von Kamptz sblock.fs_dsize += acg.cg_ndblk - dupper;
4192049cc32SKirk McKusick sblock.fs_old_dsize = sblock.fs_dsize;
4203d500078SThomas-Henning von Kamptz if ((i = dupper % sblock.fs_frag)) {
4213d500078SThomas-Henning von Kamptz acg.cg_frsum[sblock.fs_frag - i]++;
4223d500078SThomas-Henning von Kamptz for (d = dupper + sblock.fs_frag - i; dupper < d; dupper++) {
4233d500078SThomas-Henning von Kamptz setbit(cg_blksfree(&acg), dupper);
4243d500078SThomas-Henning von Kamptz acg.cg_cs.cs_nffree++;
4253d500078SThomas-Henning von Kamptz }
4263d500078SThomas-Henning von Kamptz }
4271c85e6a3SKirk McKusick for (d = dupper; d + sblock.fs_frag <= acg.cg_ndblk;
4281c85e6a3SKirk McKusick d += sblock.fs_frag) {
4293d500078SThomas-Henning von Kamptz blkno = d / sblock.fs_frag;
4303d500078SThomas-Henning von Kamptz setblock(&sblock, cg_blksfree(&acg), blkno);
4311c85e6a3SKirk McKusick if (sblock.fs_contigsumsize > 0)
4323d500078SThomas-Henning von Kamptz setbit(cg_clustersfree(&acg), blkno);
4333d500078SThomas-Henning von Kamptz acg.cg_cs.cs_nbfree++;
4343d500078SThomas-Henning von Kamptz }
4351c85e6a3SKirk McKusick if (d < acg.cg_ndblk) {
4361c85e6a3SKirk McKusick acg.cg_frsum[acg.cg_ndblk - d]++;
4371c85e6a3SKirk McKusick for (; d < acg.cg_ndblk; d++) {
4383d500078SThomas-Henning von Kamptz setbit(cg_blksfree(&acg), d);
4393d500078SThomas-Henning von Kamptz acg.cg_cs.cs_nffree++;
4403d500078SThomas-Henning von Kamptz }
4413d500078SThomas-Henning von Kamptz }
4423d500078SThomas-Henning von Kamptz if (sblock.fs_contigsumsize > 0) {
4433d500078SThomas-Henning von Kamptz int32_t *sump = cg_clustersum(&acg);
4443d500078SThomas-Henning von Kamptz u_char *mapp = cg_clustersfree(&acg);
4453d500078SThomas-Henning von Kamptz int map = *mapp++;
4463d500078SThomas-Henning von Kamptz int bit = 1;
4473d500078SThomas-Henning von Kamptz int run = 0;
4483d500078SThomas-Henning von Kamptz
4493d500078SThomas-Henning von Kamptz for (i = 0; i < acg.cg_nclusterblks; i++) {
4501c85e6a3SKirk McKusick if ((map & bit) != 0)
4513d500078SThomas-Henning von Kamptz run++;
4521c85e6a3SKirk McKusick else if (run != 0) {
4531c85e6a3SKirk McKusick if (run > sblock.fs_contigsumsize)
4543d500078SThomas-Henning von Kamptz run = sblock.fs_contigsumsize;
4553d500078SThomas-Henning von Kamptz sump[run]++;
4563d500078SThomas-Henning von Kamptz run = 0;
4573d500078SThomas-Henning von Kamptz }
45889fdc4e1SMike Barcroft if ((i & (CHAR_BIT - 1)) != CHAR_BIT - 1)
4593d500078SThomas-Henning von Kamptz bit <<= 1;
4601c85e6a3SKirk McKusick else {
4613d500078SThomas-Henning von Kamptz map = *mapp++;
4623d500078SThomas-Henning von Kamptz bit = 1;
4633d500078SThomas-Henning von Kamptz }
4643d500078SThomas-Henning von Kamptz }
4653d500078SThomas-Henning von Kamptz if (run != 0) {
4661c85e6a3SKirk McKusick if (run > sblock.fs_contigsumsize)
4673d500078SThomas-Henning von Kamptz run = sblock.fs_contigsumsize;
4683d500078SThomas-Henning von Kamptz sump[run]++;
4693d500078SThomas-Henning von Kamptz }
4703d500078SThomas-Henning von Kamptz }
4713d500078SThomas-Henning von Kamptz sblock.fs_cstotal.cs_ndir += acg.cg_cs.cs_ndir;
4723d500078SThomas-Henning von Kamptz sblock.fs_cstotal.cs_nffree += acg.cg_cs.cs_nffree;
4733d500078SThomas-Henning von Kamptz sblock.fs_cstotal.cs_nbfree += acg.cg_cs.cs_nbfree;
4743d500078SThomas-Henning von Kamptz sblock.fs_cstotal.cs_nifree += acg.cg_cs.cs_nifree;
4753d500078SThomas-Henning von Kamptz *cs = acg.cg_cs;
4761ad5f80fSBrian Somers
4773abf5d76SKirk McKusick cgckhash(&acg);
4789fc5d538SKirk McKusick wtfs(fsbtodb(&sblock, cgtod(&sblock, cylno)), sblock.fs_cgsize, &acg,
4799fc5d538SKirk McKusick fso, Nflag);
4801ad5f80fSBrian Somers DBG_DUMP_CG(&sblock, "new cg", &acg);
4813d500078SThomas-Henning von Kamptz
4823d500078SThomas-Henning von Kamptz DBG_LEAVE;
4833d500078SThomas-Henning von Kamptz return;
4843d500078SThomas-Henning von Kamptz }
4853d500078SThomas-Henning von Kamptz
4863d500078SThomas-Henning von Kamptz /*
4873d500078SThomas-Henning von Kamptz * Here we add or subtract (sign +1/-1) the available fragments in a given
4883d500078SThomas-Henning von Kamptz * block to or from the fragment statistics. By subtracting before and adding
4893d500078SThomas-Henning von Kamptz * after an operation on the free frag map we can easy update the fragment
490d64ada50SJens Schweikhardt * statistic, which seems to be otherwise a rather complex operation.
4913d500078SThomas-Henning von Kamptz */
4923d500078SThomas-Henning von Kamptz static void
frag_adjust(ufs2_daddr_t frag,int sign)4931c85e6a3SKirk McKusick frag_adjust(ufs2_daddr_t frag, int sign)
4943d500078SThomas-Henning von Kamptz {
4953d500078SThomas-Henning von Kamptz DBG_FUNC("frag_adjust")
4963d500078SThomas-Henning von Kamptz int fragsize;
4973d500078SThomas-Henning von Kamptz int f;
4983d500078SThomas-Henning von Kamptz
4993d500078SThomas-Henning von Kamptz DBG_ENTER;
5003d500078SThomas-Henning von Kamptz
5013d500078SThomas-Henning von Kamptz fragsize = 0;
5023d500078SThomas-Henning von Kamptz /*
5033d500078SThomas-Henning von Kamptz * Here frag only needs to point to any fragment in the block we want
5043d500078SThomas-Henning von Kamptz * to examine.
5053d500078SThomas-Henning von Kamptz */
5063d500078SThomas-Henning von Kamptz for (f = rounddown(frag, sblock.fs_frag);
507a1da0740SEdward Tomasz Napierala f < roundup(frag + 1, sblock.fs_frag); f++) {
5083d500078SThomas-Henning von Kamptz /*
5096ded0533SJens Schweikhardt * Count contiguous free fragments.
5103d500078SThomas-Henning von Kamptz */
5113d500078SThomas-Henning von Kamptz if (isset(cg_blksfree(&acg), f)) {
5123d500078SThomas-Henning von Kamptz fragsize++;
5133d500078SThomas-Henning von Kamptz } else {
5143d500078SThomas-Henning von Kamptz if (fragsize && fragsize < sblock.fs_frag) {
5153d500078SThomas-Henning von Kamptz /*
5163d500078SThomas-Henning von Kamptz * We found something in between.
5173d500078SThomas-Henning von Kamptz */
5183d500078SThomas-Henning von Kamptz acg.cg_frsum[fragsize] += sign;
5194020c5bcSThomas-Henning von Kamptz DBG_PRINT2("frag_adjust [%d]+=%d\n",
520a1da0740SEdward Tomasz Napierala fragsize, sign);
5213d500078SThomas-Henning von Kamptz }
5223d500078SThomas-Henning von Kamptz fragsize = 0;
5233d500078SThomas-Henning von Kamptz }
5243d500078SThomas-Henning von Kamptz }
5253d500078SThomas-Henning von Kamptz if (fragsize && fragsize < sblock.fs_frag) {
5263d500078SThomas-Henning von Kamptz /*
5273d500078SThomas-Henning von Kamptz * We found something.
5283d500078SThomas-Henning von Kamptz */
5293d500078SThomas-Henning von Kamptz acg.cg_frsum[fragsize] += sign;
530a1da0740SEdward Tomasz Napierala DBG_PRINT2("frag_adjust [%d]+=%d\n", fragsize, sign);
5313d500078SThomas-Henning von Kamptz }
532a1da0740SEdward Tomasz Napierala DBG_PRINT2("frag_adjust [[%d]]+=%d\n", fragsize, sign);
5333d500078SThomas-Henning von Kamptz
5343d500078SThomas-Henning von Kamptz DBG_LEAVE;
5353d500078SThomas-Henning von Kamptz return;
5363d500078SThomas-Henning von Kamptz }
5373d500078SThomas-Henning von Kamptz
5383d500078SThomas-Henning von Kamptz /*
5393d500078SThomas-Henning von Kamptz * Here we do all needed work for the former last cylinder group. It has to be
5403d500078SThomas-Henning von Kamptz * changed in any case, even if the file system ended exactly on the end of
5413d500078SThomas-Henning von Kamptz * this group, as there is some slightly inconsistent handling of the number
5423d500078SThomas-Henning von Kamptz * of cylinders in the cylinder group. We start again by reading the cylinder
5433d500078SThomas-Henning von Kamptz * group from disk. If the last block was not fully available, we first handle
5443d500078SThomas-Henning von Kamptz * the missing fragments, then we handle all new full blocks in that file
5453d500078SThomas-Henning von Kamptz * system and finally we handle the new last fragmented block in the file
5463d500078SThomas-Henning von Kamptz * system. We again have to handle the fragment statistics rotational layout
5473d500078SThomas-Henning von Kamptz * tables and cluster summary during all those operations.
5483d500078SThomas-Henning von Kamptz */
5493d500078SThomas-Henning von Kamptz static void
updjcg(int cylno,time_t modtime,int fsi,int fso,unsigned int Nflag)550ea6de5eeSMarcel Moolenaar updjcg(int cylno, time_t modtime, int fsi, int fso, unsigned int Nflag)
5513d500078SThomas-Henning von Kamptz {
5523d500078SThomas-Henning von Kamptz DBG_FUNC("updjcg")
55378dfcf25SKirk McKusick ufs2_daddr_t cbase, dmax;
5543d500078SThomas-Henning von Kamptz struct csum *cs;
5553d500078SThomas-Henning von Kamptz int i, k;
5563d500078SThomas-Henning von Kamptz int j = 0;
5573d500078SThomas-Henning von Kamptz
5583d500078SThomas-Henning von Kamptz DBG_ENTER;
5593d500078SThomas-Henning von Kamptz
5603d500078SThomas-Henning von Kamptz /*
5613d500078SThomas-Henning von Kamptz * Read the former last (joining) cylinder group from disk, and make
5623d500078SThomas-Henning von Kamptz * a copy.
5633d500078SThomas-Henning von Kamptz */
564adcaff07SThomas-Henning von Kamptz rdfs(fsbtodb(&osblock, cgtod(&osblock, cylno)),
565adcaff07SThomas-Henning von Kamptz (size_t)osblock.fs_cgsize, (void *)&aocg, fsi);
5663d500078SThomas-Henning von Kamptz DBG_PRINT0("jcg read\n");
567a1da0740SEdward Tomasz Napierala DBG_DUMP_CG(&sblock, "old joining cg", &aocg);
5683d500078SThomas-Henning von Kamptz
5693d500078SThomas-Henning von Kamptz memcpy((void *)&cgun1, (void *)&cgun2, sizeof(cgun2));
5703d500078SThomas-Henning von Kamptz
5713d500078SThomas-Henning von Kamptz /*
5726ded0533SJens Schweikhardt * If the cylinder group had already its new final size almost
5733d500078SThomas-Henning von Kamptz * nothing is to be done ... except:
5743d500078SThomas-Henning von Kamptz * For some reason the value of cg_ncyl in the last cylinder group has
5753d500078SThomas-Henning von Kamptz * to be zero instead of fs_cpg. As this is now no longer the last
5763d500078SThomas-Henning von Kamptz * cylinder group we have to change that value now to fs_cpg.
5773d500078SThomas-Henning von Kamptz */
5783d500078SThomas-Henning von Kamptz
5793d500078SThomas-Henning von Kamptz if (cgbase(&osblock, cylno + 1) == osblock.fs_size) {
5801c85e6a3SKirk McKusick if (sblock.fs_magic == FS_UFS1_MAGIC)
5811c85e6a3SKirk McKusick acg.cg_old_ncyl = sblock.fs_old_cpg;
5823d500078SThomas-Henning von Kamptz
58354fab0fbSKirk McKusick cgckhash(&acg);
584adcaff07SThomas-Henning von Kamptz wtfs(fsbtodb(&sblock, cgtod(&sblock, cylno)),
585adcaff07SThomas-Henning von Kamptz (size_t)sblock.fs_cgsize, (void *)&acg, fso, Nflag);
5863d500078SThomas-Henning von Kamptz DBG_PRINT0("jcg written\n");
587a1da0740SEdward Tomasz Napierala DBG_DUMP_CG(&sblock, "new joining cg", &acg);
5883d500078SThomas-Henning von Kamptz
5893d500078SThomas-Henning von Kamptz DBG_LEAVE;
5903d500078SThomas-Henning von Kamptz return;
5913d500078SThomas-Henning von Kamptz }
5923d500078SThomas-Henning von Kamptz
5933d500078SThomas-Henning von Kamptz /*
5943d500078SThomas-Henning von Kamptz * Set up some variables needed later.
5953d500078SThomas-Henning von Kamptz */
5963d500078SThomas-Henning von Kamptz cbase = cgbase(&sblock, cylno);
5973d500078SThomas-Henning von Kamptz dmax = cbase + sblock.fs_fpg;
5983d500078SThomas-Henning von Kamptz if (dmax > sblock.fs_size)
5993d500078SThomas-Henning von Kamptz dmax = sblock.fs_size;
6003d500078SThomas-Henning von Kamptz
6013d500078SThomas-Henning von Kamptz /*
6023d500078SThomas-Henning von Kamptz * Set pointer to the cylinder summary for our cylinder group.
6033d500078SThomas-Henning von Kamptz */
6043d500078SThomas-Henning von Kamptz cs = fscs + cylno;
6053d500078SThomas-Henning von Kamptz
6063d500078SThomas-Henning von Kamptz /*
6073d500078SThomas-Henning von Kamptz * Touch the cylinder group, update all fields in the cylinder group as
6083d500078SThomas-Henning von Kamptz * needed, update the free space in the superblock.
6093d500078SThomas-Henning von Kamptz */
610ea6de5eeSMarcel Moolenaar acg.cg_time = modtime;
61114a176a0SKirk McKusick if ((unsigned)cylno == sblock.fs_ncg - 1) {
6123d500078SThomas-Henning von Kamptz /*
6133d500078SThomas-Henning von Kamptz * This is still the last cylinder group.
6143d500078SThomas-Henning von Kamptz */
6151c85e6a3SKirk McKusick if (sblock.fs_magic == FS_UFS1_MAGIC)
6161c85e6a3SKirk McKusick acg.cg_old_ncyl =
6171c85e6a3SKirk McKusick sblock.fs_old_ncyl % sblock.fs_old_cpg;
6183d500078SThomas-Henning von Kamptz } else {
6191c85e6a3SKirk McKusick acg.cg_old_ncyl = sblock.fs_old_cpg;
6203d500078SThomas-Henning von Kamptz }
621a1da0740SEdward Tomasz Napierala DBG_PRINT2("jcg dbg: %d %u", cylno, sblock.fs_ncg);
62275d1ec91SLukas Ertl #ifdef FS_DEBUG
6231c85e6a3SKirk McKusick if (sblock.fs_magic == FS_UFS1_MAGIC)
624a1da0740SEdward Tomasz Napierala DBG_PRINT2("%d %u", acg.cg_old_ncyl, sblock.fs_old_cpg);
62575d1ec91SLukas Ertl #endif
6261c85e6a3SKirk McKusick DBG_PRINT0("\n");
6273d500078SThomas-Henning von Kamptz acg.cg_ndblk = dmax - cbase;
6283d500078SThomas-Henning von Kamptz sblock.fs_dsize += acg.cg_ndblk - aocg.cg_ndblk;
6292049cc32SKirk McKusick sblock.fs_old_dsize = sblock.fs_dsize;
630a1da0740SEdward Tomasz Napierala if (sblock.fs_contigsumsize > 0)
6313d500078SThomas-Henning von Kamptz acg.cg_nclusterblks = acg.cg_ndblk / sblock.fs_frag;
6323d500078SThomas-Henning von Kamptz
6333d500078SThomas-Henning von Kamptz /*
6343d500078SThomas-Henning von Kamptz * Now we have to update the free fragment bitmap for our new free
6353d500078SThomas-Henning von Kamptz * space. There again we have to handle the fragmentation and also
6363d500078SThomas-Henning von Kamptz * the rotational layout tables and the cluster summary. This is
6373d500078SThomas-Henning von Kamptz * also done per fragment for the first new block if the old file
6383d500078SThomas-Henning von Kamptz * system end was not on a block boundary, per fragment for the new
6393d500078SThomas-Henning von Kamptz * last block if the new file system end is not on a block boundary,
6403d500078SThomas-Henning von Kamptz * and per block for all space in between.
6413d500078SThomas-Henning von Kamptz *
6423d500078SThomas-Henning von Kamptz * Handle the first new block here if it was partially available
6433d500078SThomas-Henning von Kamptz * before.
6443d500078SThomas-Henning von Kamptz */
6453d500078SThomas-Henning von Kamptz if (osblock.fs_size % sblock.fs_frag) {
646a1da0740SEdward Tomasz Napierala if (roundup(osblock.fs_size, sblock.fs_frag) <=
647a1da0740SEdward Tomasz Napierala sblock.fs_size) {
6483d500078SThomas-Henning von Kamptz /*
6493d500078SThomas-Henning von Kamptz * The new space is enough to fill at least this
6503d500078SThomas-Henning von Kamptz * block
6513d500078SThomas-Henning von Kamptz */
6523d500078SThomas-Henning von Kamptz j = 0;
653a1da0740SEdward Tomasz Napierala for (i = roundup(osblock.fs_size - cbase,
654a1da0740SEdward Tomasz Napierala sblock.fs_frag) - 1; i >= osblock.fs_size - cbase;
6553d500078SThomas-Henning von Kamptz i--) {
6563d500078SThomas-Henning von Kamptz setbit(cg_blksfree(&acg), i);
6573d500078SThomas-Henning von Kamptz acg.cg_cs.cs_nffree++;
6583d500078SThomas-Henning von Kamptz j++;
6593d500078SThomas-Henning von Kamptz }
6603d500078SThomas-Henning von Kamptz
6613d500078SThomas-Henning von Kamptz /*
6623d500078SThomas-Henning von Kamptz * Check if the fragment just created could join an
6633d500078SThomas-Henning von Kamptz * already existing fragment at the former end of the
6643d500078SThomas-Henning von Kamptz * file system.
6653d500078SThomas-Henning von Kamptz */
6663d500078SThomas-Henning von Kamptz if (isblock(&sblock, cg_blksfree(&acg),
6673d500078SThomas-Henning von Kamptz ((osblock.fs_size - cgbase(&sblock, cylno)) /
6683d500078SThomas-Henning von Kamptz sblock.fs_frag))) {
6693d500078SThomas-Henning von Kamptz /*
6706ded0533SJens Schweikhardt * The block is now completely available.
6713d500078SThomas-Henning von Kamptz */
6723d500078SThomas-Henning von Kamptz DBG_PRINT0("block was\n");
6733d500078SThomas-Henning von Kamptz acg.cg_frsum[osblock.fs_size % sblock.fs_frag]--;
6743d500078SThomas-Henning von Kamptz acg.cg_cs.cs_nbfree++;
6753d500078SThomas-Henning von Kamptz acg.cg_cs.cs_nffree -= sblock.fs_frag;
6763d500078SThomas-Henning von Kamptz k = rounddown(osblock.fs_size - cbase,
6773d500078SThomas-Henning von Kamptz sblock.fs_frag);
678a1da0740SEdward Tomasz Napierala updclst((osblock.fs_size - cbase) /
679a1da0740SEdward Tomasz Napierala sblock.fs_frag);
6803d500078SThomas-Henning von Kamptz } else {
6813d500078SThomas-Henning von Kamptz /*
682*26c3d72eSHUANG,YU-JIA * Lets rejoin a possible partially grown
6833d500078SThomas-Henning von Kamptz * fragment.
6843d500078SThomas-Henning von Kamptz */
6853d500078SThomas-Henning von Kamptz k = 0;
6863d500078SThomas-Henning von Kamptz while (isset(cg_blksfree(&acg), i) &&
6873d500078SThomas-Henning von Kamptz (i >= rounddown(osblock.fs_size - cbase,
6883d500078SThomas-Henning von Kamptz sblock.fs_frag))) {
6893d500078SThomas-Henning von Kamptz i--;
6903d500078SThomas-Henning von Kamptz k++;
6913d500078SThomas-Henning von Kamptz }
692a1da0740SEdward Tomasz Napierala if (k)
6933d500078SThomas-Henning von Kamptz acg.cg_frsum[k]--;
6943d500078SThomas-Henning von Kamptz acg.cg_frsum[k + j]++;
6953d500078SThomas-Henning von Kamptz }
6963d500078SThomas-Henning von Kamptz } else {
6973d500078SThomas-Henning von Kamptz /*
6983d500078SThomas-Henning von Kamptz * We only grow by some fragments within this last
6993d500078SThomas-Henning von Kamptz * block.
7003d500078SThomas-Henning von Kamptz */
7013d500078SThomas-Henning von Kamptz for (i = sblock.fs_size - cbase - 1;
702a1da0740SEdward Tomasz Napierala i >= osblock.fs_size - cbase; i--) {
7033d500078SThomas-Henning von Kamptz setbit(cg_blksfree(&acg), i);
7043d500078SThomas-Henning von Kamptz acg.cg_cs.cs_nffree++;
7053d500078SThomas-Henning von Kamptz j++;
7063d500078SThomas-Henning von Kamptz }
7073d500078SThomas-Henning von Kamptz /*
708*26c3d72eSHUANG,YU-JIA * Lets rejoin a possible partially grown fragment.
7093d500078SThomas-Henning von Kamptz */
7103d500078SThomas-Henning von Kamptz k = 0;
7113d500078SThomas-Henning von Kamptz while (isset(cg_blksfree(&acg), i) &&
7123d500078SThomas-Henning von Kamptz (i >= rounddown(osblock.fs_size - cbase,
7133d500078SThomas-Henning von Kamptz sblock.fs_frag))) {
7143d500078SThomas-Henning von Kamptz i--;
7153d500078SThomas-Henning von Kamptz k++;
7163d500078SThomas-Henning von Kamptz }
717a1da0740SEdward Tomasz Napierala if (k)
7183d500078SThomas-Henning von Kamptz acg.cg_frsum[k]--;
7193d500078SThomas-Henning von Kamptz acg.cg_frsum[k + j]++;
7203d500078SThomas-Henning von Kamptz }
7213d500078SThomas-Henning von Kamptz }
7223d500078SThomas-Henning von Kamptz
7233d500078SThomas-Henning von Kamptz /*
7243d500078SThomas-Henning von Kamptz * Handle all new complete blocks here.
7253d500078SThomas-Henning von Kamptz */
7263d500078SThomas-Henning von Kamptz for (i = roundup(osblock.fs_size - cbase, sblock.fs_frag);
7273d500078SThomas-Henning von Kamptz i + sblock.fs_frag <= dmax - cbase; /* XXX <= or only < ? */
7283d500078SThomas-Henning von Kamptz i += sblock.fs_frag) {
7293d500078SThomas-Henning von Kamptz j = i / sblock.fs_frag;
7303d500078SThomas-Henning von Kamptz setblock(&sblock, cg_blksfree(&acg), j);
7313d500078SThomas-Henning von Kamptz updclst(j);
7323d500078SThomas-Henning von Kamptz acg.cg_cs.cs_nbfree++;
7333d500078SThomas-Henning von Kamptz }
7343d500078SThomas-Henning von Kamptz
7353d500078SThomas-Henning von Kamptz /*
736*26c3d72eSHUANG,YU-JIA * Handle the last new block if there are still some new fragments left.
7373d500078SThomas-Henning von Kamptz * Here we don't have to bother about the cluster summary or the even
7383d500078SThomas-Henning von Kamptz * the rotational layout table.
7393d500078SThomas-Henning von Kamptz */
7403d500078SThomas-Henning von Kamptz if (i < (dmax - cbase)) {
7413d500078SThomas-Henning von Kamptz acg.cg_frsum[dmax - cbase - i]++;
7423d500078SThomas-Henning von Kamptz for (; i < dmax - cbase; i++) {
7433d500078SThomas-Henning von Kamptz setbit(cg_blksfree(&acg), i);
7443d500078SThomas-Henning von Kamptz acg.cg_cs.cs_nffree++;
7453d500078SThomas-Henning von Kamptz }
7463d500078SThomas-Henning von Kamptz }
7473d500078SThomas-Henning von Kamptz
7483d500078SThomas-Henning von Kamptz sblock.fs_cstotal.cs_nffree +=
7493d500078SThomas-Henning von Kamptz (acg.cg_cs.cs_nffree - aocg.cg_cs.cs_nffree);
7503d500078SThomas-Henning von Kamptz sblock.fs_cstotal.cs_nbfree +=
7513d500078SThomas-Henning von Kamptz (acg.cg_cs.cs_nbfree - aocg.cg_cs.cs_nbfree);
7523d500078SThomas-Henning von Kamptz /*
7533d500078SThomas-Henning von Kamptz * The following statistics are not changed here:
7543d500078SThomas-Henning von Kamptz * sblock.fs_cstotal.cs_ndir
7553d500078SThomas-Henning von Kamptz * sblock.fs_cstotal.cs_nifree
7563d500078SThomas-Henning von Kamptz * As the statistics for this cylinder group are ready, copy it to
7573d500078SThomas-Henning von Kamptz * the summary information array.
7583d500078SThomas-Henning von Kamptz */
7593d500078SThomas-Henning von Kamptz *cs = acg.cg_cs;
7603d500078SThomas-Henning von Kamptz
7613d500078SThomas-Henning von Kamptz /*
7623d500078SThomas-Henning von Kamptz * Write the updated "joining" cylinder group back to disk.
7633d500078SThomas-Henning von Kamptz */
7643abf5d76SKirk McKusick cgckhash(&acg);
765adcaff07SThomas-Henning von Kamptz wtfs(fsbtodb(&sblock, cgtod(&sblock, cylno)), (size_t)sblock.fs_cgsize,
766adcaff07SThomas-Henning von Kamptz (void *)&acg, fso, Nflag);
7673d500078SThomas-Henning von Kamptz DBG_PRINT0("jcg written\n");
768a1da0740SEdward Tomasz Napierala DBG_DUMP_CG(&sblock, "new joining cg", &acg);
7693d500078SThomas-Henning von Kamptz
7703d500078SThomas-Henning von Kamptz DBG_LEAVE;
7713d500078SThomas-Henning von Kamptz return;
7723d500078SThomas-Henning von Kamptz }
7733d500078SThomas-Henning von Kamptz
7743d500078SThomas-Henning von Kamptz /*
7753d500078SThomas-Henning von Kamptz * Here we update the location of the cylinder summary. We have two possible
776e35497f1SEdward Tomasz Napierala * ways of growing the cylinder summary:
7773d500078SThomas-Henning von Kamptz * (1) We can try to grow the summary in the current location, and relocate
7783d500078SThomas-Henning von Kamptz * possibly used blocks within the current cylinder group.
7793d500078SThomas-Henning von Kamptz * (2) Alternatively we can relocate the whole cylinder summary to the first
7803d500078SThomas-Henning von Kamptz * new completely empty cylinder group. Once the cylinder summary is no
7813d500078SThomas-Henning von Kamptz * longer in the beginning of the first cylinder group you should never
7823d500078SThomas-Henning von Kamptz * use a version of fsck which is not aware of the possibility to have
7833d500078SThomas-Henning von Kamptz * this structure in a non standard place.
7849f2d8a38SEdward Tomasz Napierala * Option (2) is considered to be less intrusive to the structure of the file-
7859f2d8a38SEdward Tomasz Napierala * system, so that's the one being used.
7863d500078SThomas-Henning von Kamptz */
7873d500078SThomas-Henning von Kamptz static void
updcsloc(time_t modtime,int fsi,int fso,unsigned int Nflag)788ea6de5eeSMarcel Moolenaar updcsloc(time_t modtime, int fsi, int fso, unsigned int Nflag)
7893d500078SThomas-Henning von Kamptz {
7903d500078SThomas-Henning von Kamptz DBG_FUNC("updcsloc")
7913d500078SThomas-Henning von Kamptz struct csum *cs;
7923d500078SThomas-Henning von Kamptz int ocscg, ncscg;
7939f2d8a38SEdward Tomasz Napierala ufs2_daddr_t d;
7943d500078SThomas-Henning von Kamptz int lcs = 0;
7953d500078SThomas-Henning von Kamptz int block;
7963d500078SThomas-Henning von Kamptz
7973d500078SThomas-Henning von Kamptz DBG_ENTER;
7983d500078SThomas-Henning von Kamptz
7993d500078SThomas-Henning von Kamptz if (howmany(sblock.fs_cssize, sblock.fs_fsize) ==
8003d500078SThomas-Henning von Kamptz howmany(osblock.fs_cssize, osblock.fs_fsize)) {
8013d500078SThomas-Henning von Kamptz /*
8023d500078SThomas-Henning von Kamptz * No new fragment needed.
8033d500078SThomas-Henning von Kamptz */
8043d500078SThomas-Henning von Kamptz DBG_LEAVE;
8053d500078SThomas-Henning von Kamptz return;
8063d500078SThomas-Henning von Kamptz }
8072049cc32SKirk McKusick /* Adjust fs_dsize by added summary blocks */
8082049cc32SKirk McKusick sblock.fs_dsize -= howmany(sblock.fs_cssize, sblock.fs_fsize) -
8092049cc32SKirk McKusick howmany(osblock.fs_cssize, osblock.fs_fsize);
8102049cc32SKirk McKusick sblock.fs_old_dsize = sblock.fs_dsize;
8113d500078SThomas-Henning von Kamptz ocscg = dtog(&osblock, osblock.fs_csaddr);
8123d500078SThomas-Henning von Kamptz cs = fscs + ocscg;
8133d500078SThomas-Henning von Kamptz
8143d500078SThomas-Henning von Kamptz /*
8153d500078SThomas-Henning von Kamptz * Read original cylinder group from disk, and make a copy.
8165455cc1aSChristoph Herrmann * XXX If Nflag is set in some very rare cases we now miss
8175455cc1aSChristoph Herrmann * some changes done in updjcg by reading the unmodified
8185455cc1aSChristoph Herrmann * block from disk.
8193d500078SThomas-Henning von Kamptz */
820adcaff07SThomas-Henning von Kamptz rdfs(fsbtodb(&osblock, cgtod(&osblock, ocscg)),
821adcaff07SThomas-Henning von Kamptz (size_t)osblock.fs_cgsize, (void *)&aocg, fsi);
8223d500078SThomas-Henning von Kamptz DBG_PRINT0("oscg read\n");
823a1da0740SEdward Tomasz Napierala DBG_DUMP_CG(&sblock, "old summary cg", &aocg);
8243d500078SThomas-Henning von Kamptz
8253d500078SThomas-Henning von Kamptz memcpy((void *)&cgun1, (void *)&cgun2, sizeof(cgun2));
8263d500078SThomas-Henning von Kamptz
8273d500078SThomas-Henning von Kamptz /*
8283d500078SThomas-Henning von Kamptz * Touch the cylinder group, set up local variables needed later
8293d500078SThomas-Henning von Kamptz * and update the superblock.
8303d500078SThomas-Henning von Kamptz */
831ea6de5eeSMarcel Moolenaar acg.cg_time = modtime;
8323d500078SThomas-Henning von Kamptz
8333d500078SThomas-Henning von Kamptz /*
8343d500078SThomas-Henning von Kamptz * XXX In the case of having active snapshots we may need much more
8353d500078SThomas-Henning von Kamptz * blocks for the copy on write. We need each block twice, and
8363d500078SThomas-Henning von Kamptz * also up to 8*3 blocks for indirect blocks for all possible
8373d500078SThomas-Henning von Kamptz * references.
8383d500078SThomas-Henning von Kamptz */
8393d500078SThomas-Henning von Kamptz /*
8403d500078SThomas-Henning von Kamptz * There is not enough space in the old cylinder group to
8413d500078SThomas-Henning von Kamptz * relocate all blocks as needed, so we relocate the whole
8423d500078SThomas-Henning von Kamptz * cylinder group summary to a new group. We try to use the
8433d500078SThomas-Henning von Kamptz * first complete new cylinder group just created. Within the
8446ded0533SJens Schweikhardt * cylinder group we align the area immediately after the
8453d500078SThomas-Henning von Kamptz * cylinder group information location in order to be as
8463d500078SThomas-Henning von Kamptz * close as possible to the original implementation of ffs.
8473d500078SThomas-Henning von Kamptz *
8483d500078SThomas-Henning von Kamptz * First we have to make sure we'll find enough space in the
8493d500078SThomas-Henning von Kamptz * new cylinder group. If not, then we currently give up.
8503d500078SThomas-Henning von Kamptz * We start with freeing everything which was used by the
8513d500078SThomas-Henning von Kamptz * fragments of the old cylinder summary in the current group.
8523d500078SThomas-Henning von Kamptz * Now we write back the group meta data, read in the needed
8533d500078SThomas-Henning von Kamptz * meta data from the new cylinder group, and start allocating
8543d500078SThomas-Henning von Kamptz * within that group. Here we can assume, the group to be
8553d500078SThomas-Henning von Kamptz * completely empty. Which makes the handling of fragments and
8563d500078SThomas-Henning von Kamptz * clusters a lot easier.
8573d500078SThomas-Henning von Kamptz */
8583d500078SThomas-Henning von Kamptz DBG_TRC;
859a1da0740SEdward Tomasz Napierala if (sblock.fs_ncg - osblock.fs_ncg < 2)
8604020c5bcSThomas-Henning von Kamptz errx(2, "panic: not enough space");
8613d500078SThomas-Henning von Kamptz
8623d500078SThomas-Henning von Kamptz /*
8633d500078SThomas-Henning von Kamptz * Point "d" to the first fragment not used by the cylinder
8643d500078SThomas-Henning von Kamptz * summary.
8653d500078SThomas-Henning von Kamptz */
8663d500078SThomas-Henning von Kamptz d = osblock.fs_csaddr + (osblock.fs_cssize / osblock.fs_fsize);
8673d500078SThomas-Henning von Kamptz
8683d500078SThomas-Henning von Kamptz /*
8693d500078SThomas-Henning von Kamptz * Set up last cluster size ("lcs") already here. Calculate
8703d500078SThomas-Henning von Kamptz * the size for the trailing cluster just behind where "d"
8713d500078SThomas-Henning von Kamptz * points to.
8723d500078SThomas-Henning von Kamptz */
8733d500078SThomas-Henning von Kamptz if (sblock.fs_contigsumsize > 0) {
8743d500078SThomas-Henning von Kamptz for (block = howmany(d % sblock.fs_fpg, sblock.fs_frag),
8756ad07d53SEdward Tomasz Napierala lcs = 0; lcs < sblock.fs_contigsumsize; block++, lcs++) {
876a1da0740SEdward Tomasz Napierala if (isclr(cg_clustersfree(&acg), block))
8773d500078SThomas-Henning von Kamptz break;
8783d500078SThomas-Henning von Kamptz }
8793d500078SThomas-Henning von Kamptz }
8803d500078SThomas-Henning von Kamptz
8813d500078SThomas-Henning von Kamptz /*
8823d500078SThomas-Henning von Kamptz * Point "d" to the last frag used by the cylinder summary.
8833d500078SThomas-Henning von Kamptz */
8843d500078SThomas-Henning von Kamptz d--;
8853d500078SThomas-Henning von Kamptz
886a1da0740SEdward Tomasz Napierala DBG_PRINT1("d=%jd\n", (intmax_t)d);
8873d500078SThomas-Henning von Kamptz if ((d + 1) % sblock.fs_frag) {
8883d500078SThomas-Henning von Kamptz /*
8893d500078SThomas-Henning von Kamptz * The end of the cylinder summary is not a complete
8903d500078SThomas-Henning von Kamptz * block.
8913d500078SThomas-Henning von Kamptz */
8923d500078SThomas-Henning von Kamptz DBG_TRC;
8933d500078SThomas-Henning von Kamptz frag_adjust(d % sblock.fs_fpg, -1);
8943d500078SThomas-Henning von Kamptz for (; (d + 1) % sblock.fs_frag; d--) {
895a1da0740SEdward Tomasz Napierala DBG_PRINT1("d=%jd\n", (intmax_t)d);
8963d500078SThomas-Henning von Kamptz setbit(cg_blksfree(&acg), d % sblock.fs_fpg);
8973d500078SThomas-Henning von Kamptz acg.cg_cs.cs_nffree++;
8983d500078SThomas-Henning von Kamptz sblock.fs_cstotal.cs_nffree++;
8993d500078SThomas-Henning von Kamptz }
9003d500078SThomas-Henning von Kamptz /*
9013d500078SThomas-Henning von Kamptz * Point "d" to the last fragment of the last
9026ded0533SJens Schweikhardt * (incomplete) block of the cylinder summary.
9033d500078SThomas-Henning von Kamptz */
9043d500078SThomas-Henning von Kamptz d++;
9053d500078SThomas-Henning von Kamptz frag_adjust(d % sblock.fs_fpg, 1);
9063d500078SThomas-Henning von Kamptz
9073d500078SThomas-Henning von Kamptz if (isblock(&sblock, cg_blksfree(&acg),
9083d500078SThomas-Henning von Kamptz (d % sblock.fs_fpg) / sblock.fs_frag)) {
90975d1ec91SLukas Ertl DBG_PRINT1("d=%jd\n", (intmax_t)d);
9103d500078SThomas-Henning von Kamptz acg.cg_cs.cs_nffree -= sblock.fs_frag;
9113d500078SThomas-Henning von Kamptz acg.cg_cs.cs_nbfree++;
9123d500078SThomas-Henning von Kamptz sblock.fs_cstotal.cs_nffree -= sblock.fs_frag;
9133d500078SThomas-Henning von Kamptz sblock.fs_cstotal.cs_nbfree++;
9143d500078SThomas-Henning von Kamptz if (sblock.fs_contigsumsize > 0) {
9153d500078SThomas-Henning von Kamptz setbit(cg_clustersfree(&acg),
9166ad07d53SEdward Tomasz Napierala (d % sblock.fs_fpg) / sblock.fs_frag);
9173d500078SThomas-Henning von Kamptz if (lcs < sblock.fs_contigsumsize) {
918a1da0740SEdward Tomasz Napierala if (lcs)
919a1da0740SEdward Tomasz Napierala cg_clustersum(&acg)[lcs]--;
9203d500078SThomas-Henning von Kamptz lcs++;
9213d500078SThomas-Henning von Kamptz cg_clustersum(&acg)[lcs]++;
9223d500078SThomas-Henning von Kamptz }
9233d500078SThomas-Henning von Kamptz }
9243d500078SThomas-Henning von Kamptz }
9253d500078SThomas-Henning von Kamptz /*
9263d500078SThomas-Henning von Kamptz * Point "d" to the first fragment of the block before
9273d500078SThomas-Henning von Kamptz * the last incomplete block.
9283d500078SThomas-Henning von Kamptz */
9293d500078SThomas-Henning von Kamptz d--;
9303d500078SThomas-Henning von Kamptz }
9313d500078SThomas-Henning von Kamptz
93275d1ec91SLukas Ertl DBG_PRINT1("d=%jd\n", (intmax_t)d);
9333d500078SThomas-Henning von Kamptz for (d = rounddown(d, sblock.fs_frag); d >= osblock.fs_csaddr;
9343d500078SThomas-Henning von Kamptz d -= sblock.fs_frag) {
9353d500078SThomas-Henning von Kamptz DBG_TRC;
93675d1ec91SLukas Ertl DBG_PRINT1("d=%jd\n", (intmax_t)d);
9373d500078SThomas-Henning von Kamptz setblock(&sblock, cg_blksfree(&acg),
9383d500078SThomas-Henning von Kamptz (d % sblock.fs_fpg) / sblock.fs_frag);
9393d500078SThomas-Henning von Kamptz acg.cg_cs.cs_nbfree++;
9403d500078SThomas-Henning von Kamptz sblock.fs_cstotal.cs_nbfree++;
9413d500078SThomas-Henning von Kamptz if (sblock.fs_contigsumsize > 0) {
9423d500078SThomas-Henning von Kamptz setbit(cg_clustersfree(&acg),
9433d500078SThomas-Henning von Kamptz (d % sblock.fs_fpg) / sblock.fs_frag);
9443d500078SThomas-Henning von Kamptz /*
9453d500078SThomas-Henning von Kamptz * The last cluster size is already set up.
9463d500078SThomas-Henning von Kamptz */
9473d500078SThomas-Henning von Kamptz if (lcs < sblock.fs_contigsumsize) {
948a1da0740SEdward Tomasz Napierala if (lcs)
9493d500078SThomas-Henning von Kamptz cg_clustersum(&acg)[lcs]--;
9503d500078SThomas-Henning von Kamptz lcs++;
9513d500078SThomas-Henning von Kamptz cg_clustersum(&acg)[lcs]++;
9523d500078SThomas-Henning von Kamptz }
9533d500078SThomas-Henning von Kamptz }
9543d500078SThomas-Henning von Kamptz }
9553d500078SThomas-Henning von Kamptz *cs = acg.cg_cs;
9563d500078SThomas-Henning von Kamptz
9573d500078SThomas-Henning von Kamptz /*
9583d500078SThomas-Henning von Kamptz * Now write the former cylinder group containing the cylinder
9593d500078SThomas-Henning von Kamptz * summary back to disk.
9603d500078SThomas-Henning von Kamptz */
96154fab0fbSKirk McKusick cgckhash(&acg);
962adcaff07SThomas-Henning von Kamptz wtfs(fsbtodb(&sblock, cgtod(&sblock, ocscg)),
963adcaff07SThomas-Henning von Kamptz (size_t)sblock.fs_cgsize, (void *)&acg, fso, Nflag);
9643d500078SThomas-Henning von Kamptz DBG_PRINT0("oscg written\n");
965a1da0740SEdward Tomasz Napierala DBG_DUMP_CG(&sblock, "old summary cg", &acg);
9663d500078SThomas-Henning von Kamptz
9673d500078SThomas-Henning von Kamptz /*
9683d500078SThomas-Henning von Kamptz * Find the beginning of the new cylinder group containing the
9693d500078SThomas-Henning von Kamptz * cylinder summary.
9703d500078SThomas-Henning von Kamptz */
9713d500078SThomas-Henning von Kamptz sblock.fs_csaddr = cgdmin(&sblock, osblock.fs_ncg);
9723d500078SThomas-Henning von Kamptz ncscg = dtog(&sblock, sblock.fs_csaddr);
9733d500078SThomas-Henning von Kamptz cs = fscs + ncscg;
9743d500078SThomas-Henning von Kamptz
9755455cc1aSChristoph Herrmann /*
9765455cc1aSChristoph Herrmann * If Nflag is specified, we would now read random data instead
9775455cc1aSChristoph Herrmann * of an empty cg structure from disk. So we can't simulate that
9785455cc1aSChristoph Herrmann * part for now.
9795455cc1aSChristoph Herrmann */
9805455cc1aSChristoph Herrmann if (Nflag) {
9815455cc1aSChristoph Herrmann DBG_PRINT0("nscg update skipped\n");
9825455cc1aSChristoph Herrmann DBG_LEAVE;
9835455cc1aSChristoph Herrmann return;
9845455cc1aSChristoph Herrmann }
9855455cc1aSChristoph Herrmann
9863d500078SThomas-Henning von Kamptz /*
9873d500078SThomas-Henning von Kamptz * Read the future cylinder group containing the cylinder
9883d500078SThomas-Henning von Kamptz * summary from disk, and make a copy.
9893d500078SThomas-Henning von Kamptz */
9903d500078SThomas-Henning von Kamptz rdfs(fsbtodb(&sblock, cgtod(&sblock, ncscg)),
991adcaff07SThomas-Henning von Kamptz (size_t)sblock.fs_cgsize, (void *)&aocg, fsi);
9923d500078SThomas-Henning von Kamptz DBG_PRINT0("nscg read\n");
993a1da0740SEdward Tomasz Napierala DBG_DUMP_CG(&sblock, "new summary cg", &aocg);
9943d500078SThomas-Henning von Kamptz
9953d500078SThomas-Henning von Kamptz memcpy((void *)&cgun1, (void *)&cgun2, sizeof(cgun2));
9963d500078SThomas-Henning von Kamptz
9973d500078SThomas-Henning von Kamptz /*
9983d500078SThomas-Henning von Kamptz * Allocate all complete blocks used by the new cylinder
9993d500078SThomas-Henning von Kamptz * summary.
10003d500078SThomas-Henning von Kamptz */
10013d500078SThomas-Henning von Kamptz for (d = sblock.fs_csaddr; d + sblock.fs_frag <=
10023d500078SThomas-Henning von Kamptz sblock.fs_csaddr + (sblock.fs_cssize / sblock.fs_fsize);
10033d500078SThomas-Henning von Kamptz d += sblock.fs_frag) {
10043d500078SThomas-Henning von Kamptz clrblock(&sblock, cg_blksfree(&acg),
10053d500078SThomas-Henning von Kamptz (d % sblock.fs_fpg) / sblock.fs_frag);
10063d500078SThomas-Henning von Kamptz acg.cg_cs.cs_nbfree--;
10073d500078SThomas-Henning von Kamptz sblock.fs_cstotal.cs_nbfree--;
10083d500078SThomas-Henning von Kamptz if (sblock.fs_contigsumsize > 0) {
10093d500078SThomas-Henning von Kamptz clrbit(cg_clustersfree(&acg),
10103d500078SThomas-Henning von Kamptz (d % sblock.fs_fpg) / sblock.fs_frag);
10113d500078SThomas-Henning von Kamptz }
10123d500078SThomas-Henning von Kamptz }
10133d500078SThomas-Henning von Kamptz
10143d500078SThomas-Henning von Kamptz /*
10153d500078SThomas-Henning von Kamptz * Allocate all fragments used by the cylinder summary in the
10163d500078SThomas-Henning von Kamptz * last block.
10173d500078SThomas-Henning von Kamptz */
10186ad07d53SEdward Tomasz Napierala if (d < sblock.fs_csaddr + (sblock.fs_cssize / sblock.fs_fsize)) {
10193d500078SThomas-Henning von Kamptz for (; d - sblock.fs_csaddr <
1020a1da0740SEdward Tomasz Napierala sblock.fs_cssize/sblock.fs_fsize; d++) {
10213d500078SThomas-Henning von Kamptz clrbit(cg_blksfree(&acg), d % sblock.fs_fpg);
10223d500078SThomas-Henning von Kamptz acg.cg_cs.cs_nffree--;
10233d500078SThomas-Henning von Kamptz sblock.fs_cstotal.cs_nffree--;
10243d500078SThomas-Henning von Kamptz }
10253d500078SThomas-Henning von Kamptz acg.cg_cs.cs_nbfree--;
10263d500078SThomas-Henning von Kamptz acg.cg_cs.cs_nffree += sblock.fs_frag;
10273d500078SThomas-Henning von Kamptz sblock.fs_cstotal.cs_nbfree--;
10283d500078SThomas-Henning von Kamptz sblock.fs_cstotal.cs_nffree += sblock.fs_frag;
1029a1da0740SEdward Tomasz Napierala if (sblock.fs_contigsumsize > 0)
10303d500078SThomas-Henning von Kamptz clrbit(cg_clustersfree(&acg),
10313d500078SThomas-Henning von Kamptz (d % sblock.fs_fpg) / sblock.fs_frag);
10323d500078SThomas-Henning von Kamptz
1033a1da0740SEdward Tomasz Napierala frag_adjust(d % sblock.fs_fpg, 1);
10343d500078SThomas-Henning von Kamptz }
10353d500078SThomas-Henning von Kamptz /*
10363d500078SThomas-Henning von Kamptz * XXX Handle the cluster statistics here in the case this
10373d500078SThomas-Henning von Kamptz * cylinder group is now almost full, and the remaining
10383d500078SThomas-Henning von Kamptz * space is less then the maximum cluster size. This is
10393d500078SThomas-Henning von Kamptz * probably not needed, as you would hardly find a file
10403d500078SThomas-Henning von Kamptz * system which has only MAXCSBUFS+FS_MAXCONTIG of free
10413d500078SThomas-Henning von Kamptz * space right behind the cylinder group information in
10423d500078SThomas-Henning von Kamptz * any new cylinder group.
10433d500078SThomas-Henning von Kamptz */
10443d500078SThomas-Henning von Kamptz
10453d500078SThomas-Henning von Kamptz /*
10463d500078SThomas-Henning von Kamptz * Update our statistics in the cylinder summary.
10473d500078SThomas-Henning von Kamptz */
10483d500078SThomas-Henning von Kamptz *cs = acg.cg_cs;
10493d500078SThomas-Henning von Kamptz
10503d500078SThomas-Henning von Kamptz /*
10513d500078SThomas-Henning von Kamptz * Write the new cylinder group containing the cylinder summary
10523d500078SThomas-Henning von Kamptz * back to disk.
10533d500078SThomas-Henning von Kamptz */
105454fab0fbSKirk McKusick cgckhash(&acg);
1055adcaff07SThomas-Henning von Kamptz wtfs(fsbtodb(&sblock, cgtod(&sblock, ncscg)),
1056adcaff07SThomas-Henning von Kamptz (size_t)sblock.fs_cgsize, (void *)&acg, fso, Nflag);
10573d500078SThomas-Henning von Kamptz DBG_PRINT0("nscg written\n");
1058a1da0740SEdward Tomasz Napierala DBG_DUMP_CG(&sblock, "new summary cg", &acg);
10593d500078SThomas-Henning von Kamptz
10603d500078SThomas-Henning von Kamptz DBG_LEAVE;
10613d500078SThomas-Henning von Kamptz return;
10623d500078SThomas-Henning von Kamptz }
10633d500078SThomas-Henning von Kamptz
10643d500078SThomas-Henning von Kamptz /*
10653d500078SThomas-Henning von Kamptz * Here we read some block(s) from disk.
10663d500078SThomas-Henning von Kamptz */
10673d500078SThomas-Henning von Kamptz static void
rdfs(ufs2_daddr_t bno,size_t size,void * bf,int fsi)10681c85e6a3SKirk McKusick rdfs(ufs2_daddr_t bno, size_t size, void *bf, int fsi)
10693d500078SThomas-Henning von Kamptz {
10703d500078SThomas-Henning von Kamptz DBG_FUNC("rdfs")
1071adcaff07SThomas-Henning von Kamptz ssize_t n;
10723d500078SThomas-Henning von Kamptz
10733d500078SThomas-Henning von Kamptz DBG_ENTER;
10743d500078SThomas-Henning von Kamptz
1075a1da0740SEdward Tomasz Napierala if (bno < 0)
1076e3ec673eSPhilippe Charnier err(32, "rdfs: attempting to read negative block number");
1077a1da0740SEdward Tomasz Napierala if (lseek(fsi, (off_t)bno * DEV_BSIZE, 0) < 0)
107875d1ec91SLukas Ertl err(33, "rdfs: seek error: %jd", (intmax_t)bno);
1079adcaff07SThomas-Henning von Kamptz n = read(fsi, bf, size);
1080a1da0740SEdward Tomasz Napierala if (n != (ssize_t)size)
108175d1ec91SLukas Ertl err(34, "rdfs: read error: %jd", (intmax_t)bno);
10823d500078SThomas-Henning von Kamptz
10833d500078SThomas-Henning von Kamptz DBG_LEAVE;
10843d500078SThomas-Henning von Kamptz return;
10853d500078SThomas-Henning von Kamptz }
10863d500078SThomas-Henning von Kamptz
10873d500078SThomas-Henning von Kamptz /*
10883d500078SThomas-Henning von Kamptz * Here we write some block(s) to disk.
10893d500078SThomas-Henning von Kamptz */
10903d500078SThomas-Henning von Kamptz static void
wtfs(ufs2_daddr_t bno,size_t size,void * bf,int fso,unsigned int Nflag)10911c85e6a3SKirk McKusick wtfs(ufs2_daddr_t bno, size_t size, void *bf, int fso, unsigned int Nflag)
10923d500078SThomas-Henning von Kamptz {
10933d500078SThomas-Henning von Kamptz DBG_FUNC("wtfs")
1094adcaff07SThomas-Henning von Kamptz ssize_t n;
10953d500078SThomas-Henning von Kamptz
10963d500078SThomas-Henning von Kamptz DBG_ENTER;
10973d500078SThomas-Henning von Kamptz
10983d500078SThomas-Henning von Kamptz if (Nflag) {
10993d500078SThomas-Henning von Kamptz DBG_LEAVE;
11003d500078SThomas-Henning von Kamptz return;
11013d500078SThomas-Henning von Kamptz }
1102a1da0740SEdward Tomasz Napierala if (lseek(fso, (off_t)bno * DEV_BSIZE, SEEK_SET) < 0)
11034020c5bcSThomas-Henning von Kamptz err(35, "wtfs: seek error: %ld", (long)bno);
1104adcaff07SThomas-Henning von Kamptz n = write(fso, bf, size);
1105a1da0740SEdward Tomasz Napierala if (n != (ssize_t)size)
11064020c5bcSThomas-Henning von Kamptz err(36, "wtfs: write error: %ld", (long)bno);
11073d500078SThomas-Henning von Kamptz
11083d500078SThomas-Henning von Kamptz DBG_LEAVE;
11093d500078SThomas-Henning von Kamptz return;
11103d500078SThomas-Henning von Kamptz }
11113d500078SThomas-Henning von Kamptz
11123d500078SThomas-Henning von Kamptz /*
11133d500078SThomas-Henning von Kamptz * Here we check if all frags of a block are free. For more details again
11143d500078SThomas-Henning von Kamptz * please see the source of newfs(8), as this function is taken over almost
11153d500078SThomas-Henning von Kamptz * unchanged.
11163d500078SThomas-Henning von Kamptz */
11173d500078SThomas-Henning von Kamptz static int
isblock(struct fs * fs,unsigned char * cp,int h)11183d500078SThomas-Henning von Kamptz isblock(struct fs *fs, unsigned char *cp, int h)
11193d500078SThomas-Henning von Kamptz {
11203d500078SThomas-Henning von Kamptz DBG_FUNC("isblock")
11213d500078SThomas-Henning von Kamptz unsigned char mask;
11223d500078SThomas-Henning von Kamptz
11233d500078SThomas-Henning von Kamptz DBG_ENTER;
11243d500078SThomas-Henning von Kamptz
11253d500078SThomas-Henning von Kamptz switch (fs->fs_frag) {
11263d500078SThomas-Henning von Kamptz case 8:
11273d500078SThomas-Henning von Kamptz DBG_LEAVE;
11283d500078SThomas-Henning von Kamptz return (cp[h] == 0xff);
11293d500078SThomas-Henning von Kamptz case 4:
11303d500078SThomas-Henning von Kamptz mask = 0x0f << ((h & 0x1) << 2);
11313d500078SThomas-Henning von Kamptz DBG_LEAVE;
11323d500078SThomas-Henning von Kamptz return ((cp[h >> 1] & mask) == mask);
11333d500078SThomas-Henning von Kamptz case 2:
11343d500078SThomas-Henning von Kamptz mask = 0x03 << ((h & 0x3) << 1);
11353d500078SThomas-Henning von Kamptz DBG_LEAVE;
11363d500078SThomas-Henning von Kamptz return ((cp[h >> 2] & mask) == mask);
11373d500078SThomas-Henning von Kamptz case 1:
11383d500078SThomas-Henning von Kamptz mask = 0x01 << (h & 0x7);
11393d500078SThomas-Henning von Kamptz DBG_LEAVE;
11403d500078SThomas-Henning von Kamptz return ((cp[h >> 3] & mask) == mask);
11413d500078SThomas-Henning von Kamptz default:
11423d500078SThomas-Henning von Kamptz fprintf(stderr, "isblock bad fs_frag %d\n", fs->fs_frag);
11433d500078SThomas-Henning von Kamptz DBG_LEAVE;
11443d500078SThomas-Henning von Kamptz return (0);
11453d500078SThomas-Henning von Kamptz }
11463d500078SThomas-Henning von Kamptz }
11473d500078SThomas-Henning von Kamptz
11483d500078SThomas-Henning von Kamptz /*
11493d500078SThomas-Henning von Kamptz * Here we allocate a complete block in the block map. For more details again
11503d500078SThomas-Henning von Kamptz * please see the source of newfs(8), as this function is taken over almost
11513d500078SThomas-Henning von Kamptz * unchanged.
11523d500078SThomas-Henning von Kamptz */
11533d500078SThomas-Henning von Kamptz static void
clrblock(struct fs * fs,unsigned char * cp,int h)11543d500078SThomas-Henning von Kamptz clrblock(struct fs *fs, unsigned char *cp, int h)
11553d500078SThomas-Henning von Kamptz {
11563d500078SThomas-Henning von Kamptz DBG_FUNC("clrblock")
11573d500078SThomas-Henning von Kamptz
11583d500078SThomas-Henning von Kamptz DBG_ENTER;
11593d500078SThomas-Henning von Kamptz
11603d500078SThomas-Henning von Kamptz switch ((fs)->fs_frag) {
11613d500078SThomas-Henning von Kamptz case 8:
11623d500078SThomas-Henning von Kamptz cp[h] = 0;
11633d500078SThomas-Henning von Kamptz break;
11643d500078SThomas-Henning von Kamptz case 4:
11653d500078SThomas-Henning von Kamptz cp[h >> 1] &= ~(0x0f << ((h & 0x1) << 2));
11663d500078SThomas-Henning von Kamptz break;
11673d500078SThomas-Henning von Kamptz case 2:
11683d500078SThomas-Henning von Kamptz cp[h >> 2] &= ~(0x03 << ((h & 0x3) << 1));
11693d500078SThomas-Henning von Kamptz break;
11703d500078SThomas-Henning von Kamptz case 1:
11713d500078SThomas-Henning von Kamptz cp[h >> 3] &= ~(0x01 << (h & 0x7));
11723d500078SThomas-Henning von Kamptz break;
11733d500078SThomas-Henning von Kamptz default:
11744020c5bcSThomas-Henning von Kamptz warnx("clrblock bad fs_frag %d", fs->fs_frag);
11753d500078SThomas-Henning von Kamptz break;
11763d500078SThomas-Henning von Kamptz }
11773d500078SThomas-Henning von Kamptz
11783d500078SThomas-Henning von Kamptz DBG_LEAVE;
11793d500078SThomas-Henning von Kamptz return;
11803d500078SThomas-Henning von Kamptz }
11813d500078SThomas-Henning von Kamptz
11823d500078SThomas-Henning von Kamptz /*
11833d500078SThomas-Henning von Kamptz * Here we free a complete block in the free block map. For more details again
11843d500078SThomas-Henning von Kamptz * please see the source of newfs(8), as this function is taken over almost
11853d500078SThomas-Henning von Kamptz * unchanged.
11863d500078SThomas-Henning von Kamptz */
11873d500078SThomas-Henning von Kamptz static void
setblock(struct fs * fs,unsigned char * cp,int h)11883d500078SThomas-Henning von Kamptz setblock(struct fs *fs, unsigned char *cp, int h)
11893d500078SThomas-Henning von Kamptz {
11903d500078SThomas-Henning von Kamptz DBG_FUNC("setblock")
11913d500078SThomas-Henning von Kamptz
11923d500078SThomas-Henning von Kamptz DBG_ENTER;
11933d500078SThomas-Henning von Kamptz
11943d500078SThomas-Henning von Kamptz switch (fs->fs_frag) {
11953d500078SThomas-Henning von Kamptz case 8:
11963d500078SThomas-Henning von Kamptz cp[h] = 0xff;
11973d500078SThomas-Henning von Kamptz break;
11983d500078SThomas-Henning von Kamptz case 4:
11993d500078SThomas-Henning von Kamptz cp[h >> 1] |= (0x0f << ((h & 0x1) << 2));
12003d500078SThomas-Henning von Kamptz break;
12013d500078SThomas-Henning von Kamptz case 2:
12023d500078SThomas-Henning von Kamptz cp[h >> 2] |= (0x03 << ((h & 0x3) << 1));
12033d500078SThomas-Henning von Kamptz break;
12043d500078SThomas-Henning von Kamptz case 1:
12053d500078SThomas-Henning von Kamptz cp[h >> 3] |= (0x01 << (h & 0x7));
12063d500078SThomas-Henning von Kamptz break;
12073d500078SThomas-Henning von Kamptz default:
12084020c5bcSThomas-Henning von Kamptz warnx("setblock bad fs_frag %d", fs->fs_frag);
12093d500078SThomas-Henning von Kamptz break;
12103d500078SThomas-Henning von Kamptz }
12113d500078SThomas-Henning von Kamptz
12123d500078SThomas-Henning von Kamptz DBG_LEAVE;
12133d500078SThomas-Henning von Kamptz return;
12143d500078SThomas-Henning von Kamptz }
12153d500078SThomas-Henning von Kamptz
12163d500078SThomas-Henning von Kamptz /*
12173d500078SThomas-Henning von Kamptz * Figure out how many lines our current terminal has. For more details again
12183d500078SThomas-Henning von Kamptz * please see the source of newfs(8), as this function is taken over almost
12193d500078SThomas-Henning von Kamptz * unchanged.
12203d500078SThomas-Henning von Kamptz */
12213d500078SThomas-Henning von Kamptz static int
charsperline(void)12223d500078SThomas-Henning von Kamptz charsperline(void)
12233d500078SThomas-Henning von Kamptz {
12243d500078SThomas-Henning von Kamptz DBG_FUNC("charsperline")
12253d500078SThomas-Henning von Kamptz int columns;
12263d500078SThomas-Henning von Kamptz char *cp;
12273d500078SThomas-Henning von Kamptz struct winsize ws;
12283d500078SThomas-Henning von Kamptz
12293d500078SThomas-Henning von Kamptz DBG_ENTER;
12303d500078SThomas-Henning von Kamptz
12313d500078SThomas-Henning von Kamptz columns = 0;
1232a1da0740SEdward Tomasz Napierala if (ioctl(0, TIOCGWINSZ, &ws) != -1)
12333d500078SThomas-Henning von Kamptz columns = ws.ws_col;
1234a1da0740SEdward Tomasz Napierala if (columns == 0 && (cp = getenv("COLUMNS")))
12353d500078SThomas-Henning von Kamptz columns = atoi(cp);
1236a1da0740SEdward Tomasz Napierala if (columns == 0)
12373d500078SThomas-Henning von Kamptz columns = 80; /* last resort */
12383d500078SThomas-Henning von Kamptz
12393d500078SThomas-Henning von Kamptz DBG_LEAVE;
124091ac1479SEdward Tomasz Napierala return (columns);
12413d500078SThomas-Henning von Kamptz }
12423d500078SThomas-Henning von Kamptz
1243e35497f1SEdward Tomasz Napierala static int
is_dev(const char * name)1244e35497f1SEdward Tomasz Napierala is_dev(const char *name)
12454b9748d4SGreg Lehey {
1246e35497f1SEdward Tomasz Napierala struct stat devstat;
12474b9748d4SGreg Lehey
1248e35497f1SEdward Tomasz Napierala if (stat(name, &devstat) != 0)
1249e35497f1SEdward Tomasz Napierala return (0);
1250e35497f1SEdward Tomasz Napierala if (!S_ISCHR(devstat.st_mode))
1251e35497f1SEdward Tomasz Napierala return (0);
1252e35497f1SEdward Tomasz Napierala return (1);
1253e35497f1SEdward Tomasz Napierala }
12544b9748d4SGreg Lehey
1255e35497f1SEdward Tomasz Napierala static const char *
getdev(const char * name,struct statfs * statfsp)1256906c312bSKirk McKusick getdev(const char *name, struct statfs *statfsp)
1257e35497f1SEdward Tomasz Napierala {
1258e35497f1SEdward Tomasz Napierala static char device[MAXPATHLEN];
1259906c312bSKirk McKusick const char *cp;
1260e35497f1SEdward Tomasz Napierala
1261e35497f1SEdward Tomasz Napierala if (is_dev(name))
1262e35497f1SEdward Tomasz Napierala return (name);
1263e35497f1SEdward Tomasz Napierala
1264e35497f1SEdward Tomasz Napierala cp = strrchr(name, '/');
1265edf6b683SMarcelo Araujo if (cp == NULL) {
1266e35497f1SEdward Tomasz Napierala snprintf(device, sizeof(device), "%s%s", _PATH_DEV, name);
1267e35497f1SEdward Tomasz Napierala if (is_dev(device))
1268e35497f1SEdward Tomasz Napierala return (device);
1269e35497f1SEdward Tomasz Napierala }
1270e35497f1SEdward Tomasz Napierala
1271906c312bSKirk McKusick if (statfsp != NULL)
1272906c312bSKirk McKusick return (statfsp->f_mntfromname);
1273e35497f1SEdward Tomasz Napierala
1274e35497f1SEdward Tomasz Napierala return (NULL);
12754b9748d4SGreg Lehey }
12764b9748d4SGreg Lehey
12773d500078SThomas-Henning von Kamptz /*
12783d500078SThomas-Henning von Kamptz * growfs(8) is a utility which allows to increase the size of an existing
12793d500078SThomas-Henning von Kamptz * ufs file system. Currently this can only be done on unmounted file system.
12803d500078SThomas-Henning von Kamptz * It recognizes some command line options to specify the new desired size,
12813d500078SThomas-Henning von Kamptz * and it does some basic checkings. The old file system size is determined
12823d500078SThomas-Henning von Kamptz * and after some more checks like we can really access the new last block
12833d500078SThomas-Henning von Kamptz * on the disk etc. we calculate the new parameters for the superblock. After
128450c603c4SEdward Tomasz Napierala * having done this we just call growfs() which will do the work.
12853d500078SThomas-Henning von Kamptz * We still have to provide support for snapshots. Therefore we first have to
12863d500078SThomas-Henning von Kamptz * understand what data structures are always replicated in the snapshot on
12873d500078SThomas-Henning von Kamptz * creation, for all other blocks we touch during our procedure, we have to
12884020c5bcSThomas-Henning von Kamptz * keep the old blocks unchanged somewhere available for the snapshots. If we
12893d500078SThomas-Henning von Kamptz * are lucky, then we only have to handle our blocks to be relocated in that
12903d500078SThomas-Henning von Kamptz * way.
12913d500078SThomas-Henning von Kamptz * Also we have to consider in what order we actually update the critical
12924020c5bcSThomas-Henning von Kamptz * data structures of the file system to make sure, that in case of a disaster
12933d500078SThomas-Henning von Kamptz * fsck(8) is still able to restore any lost data.
12944020c5bcSThomas-Henning von Kamptz * The foreseen last step then will be to provide for growing even mounted
12953d500078SThomas-Henning von Kamptz * file systems. There we have to extend the mount() system call to provide
12963d500078SThomas-Henning von Kamptz * userland access to the file system locking facility.
12973d500078SThomas-Henning von Kamptz */
12983d500078SThomas-Henning von Kamptz int
main(int argc,char ** argv)12993d500078SThomas-Henning von Kamptz main(int argc, char **argv)
13003d500078SThomas-Henning von Kamptz {
13013d500078SThomas-Henning von Kamptz DBG_FUNC("main")
1302dffce215SKirk McKusick struct fs *fs;
1303e35497f1SEdward Tomasz Napierala const char *device;
1304906c312bSKirk McKusick struct statfs *statfsp;
1305e35497f1SEdward Tomasz Napierala uint64_t size = 0;
1306e35497f1SEdward Tomasz Napierala off_t mediasize;
1307dffce215SKirk McKusick int error, j, fsi, fso, ch, ret, Nflag = 0, yflag = 0;
1308e35497f1SEdward Tomasz Napierala char *p, reply[5], oldsizebuf[6], newsizebuf[6];
1309e35497f1SEdward Tomasz Napierala void *testbuf;
13103d500078SThomas-Henning von Kamptz
13113d500078SThomas-Henning von Kamptz DBG_ENTER;
13123d500078SThomas-Henning von Kamptz
13133d500078SThomas-Henning von Kamptz while ((ch = getopt(argc, argv, "Ns:vy")) != -1) {
13143d500078SThomas-Henning von Kamptz switch(ch) {
13153d500078SThomas-Henning von Kamptz case 'N':
13163d500078SThomas-Henning von Kamptz Nflag = 1;
13173d500078SThomas-Henning von Kamptz break;
13183d500078SThomas-Henning von Kamptz case 's':
1319e35497f1SEdward Tomasz Napierala size = (off_t)strtoumax(optarg, &p, 0);
1320e35497f1SEdward Tomasz Napierala if (p == NULL || *p == '\0')
1321e35497f1SEdward Tomasz Napierala size *= DEV_BSIZE;
1322e35497f1SEdward Tomasz Napierala else if (*p == 'b' || *p == 'B')
1323e35497f1SEdward Tomasz Napierala ; /* do nothing */
1324e35497f1SEdward Tomasz Napierala else if (*p == 'k' || *p == 'K')
1325e35497f1SEdward Tomasz Napierala size <<= 10;
1326e35497f1SEdward Tomasz Napierala else if (*p == 'm' || *p == 'M')
1327e35497f1SEdward Tomasz Napierala size <<= 20;
1328e35497f1SEdward Tomasz Napierala else if (*p == 'g' || *p == 'G')
1329e35497f1SEdward Tomasz Napierala size <<= 30;
1330e35497f1SEdward Tomasz Napierala else if (*p == 't' || *p == 'T') {
1331e35497f1SEdward Tomasz Napierala size <<= 30;
1332e35497f1SEdward Tomasz Napierala size <<= 10;
1333e35497f1SEdward Tomasz Napierala } else
133470a0fb43SMina Galić errx(2, "unknown suffix on -s argument");
13353d500078SThomas-Henning von Kamptz break;
13363d500078SThomas-Henning von Kamptz case 'v': /* for compatibility to newfs */
13373d500078SThomas-Henning von Kamptz break;
13383d500078SThomas-Henning von Kamptz case 'y':
1339e35497f1SEdward Tomasz Napierala yflag = 1;
13403d500078SThomas-Henning von Kamptz break;
13413d500078SThomas-Henning von Kamptz case '?':
13423d500078SThomas-Henning von Kamptz /* FALLTHROUGH */
13433d500078SThomas-Henning von Kamptz default:
13444020c5bcSThomas-Henning von Kamptz usage();
13453d500078SThomas-Henning von Kamptz }
13463d500078SThomas-Henning von Kamptz }
13473d500078SThomas-Henning von Kamptz argc -= optind;
13483d500078SThomas-Henning von Kamptz argv += optind;
13493d500078SThomas-Henning von Kamptz
1350a1da0740SEdward Tomasz Napierala if (argc != 1)
13514020c5bcSThomas-Henning von Kamptz usage();
1352a1da0740SEdward Tomasz Napierala
1353e35497f1SEdward Tomasz Napierala /*
1354e35497f1SEdward Tomasz Napierala * Now try to guess the device name.
1355e35497f1SEdward Tomasz Napierala */
1356906c312bSKirk McKusick statfsp = getmntpoint(*argv);
1357906c312bSKirk McKusick device = getdev(*argv, statfsp);
1358e35497f1SEdward Tomasz Napierala if (device == NULL)
135970a0fb43SMina Galić errx(2, "cannot find special device for %s", *argv);
13603d500078SThomas-Henning von Kamptz
13613d500078SThomas-Henning von Kamptz fsi = open(device, O_RDONLY);
1362a1da0740SEdward Tomasz Napierala if (fsi < 0)
136370a0fb43SMina Galić err(3, "%s", device);
13643d500078SThomas-Henning von Kamptz
13653d500078SThomas-Henning von Kamptz /*
1366e35497f1SEdward Tomasz Napierala * Try to guess the slice size if not specified.
13673d500078SThomas-Henning von Kamptz */
1368e35497f1SEdward Tomasz Napierala if (ioctl(fsi, DIOCGMEDIASIZE, &mediasize) == -1)
136970a0fb43SMina Galić err(3,"DIOCGMEDIASIZE");
13703d500078SThomas-Henning von Kamptz
13713d500078SThomas-Henning von Kamptz /*
13726ded0533SJens Schweikhardt * Check if that partition is suitable for growing a file system.
13733d500078SThomas-Henning von Kamptz */
1374e35497f1SEdward Tomasz Napierala if (mediasize < 1)
137570a0fb43SMina Galić errx(2, "partition is unavailable");
13763d500078SThomas-Henning von Kamptz
13773d500078SThomas-Henning von Kamptz /*
13783d500078SThomas-Henning von Kamptz * Read the current superblock, and take a backup.
13793d500078SThomas-Henning von Kamptz */
1380b21582eeSKirk McKusick if ((ret = sbget(fsi, &fs, UFS_STDSB, 0)) != 0) {
1381dffce215SKirk McKusick switch (ret) {
1382dffce215SKirk McKusick case ENOENT:
138370a0fb43SMina Galić errx(2, "superblock not recognized");
1384dffce215SKirk McKusick default:
138570a0fb43SMina Galić errc(3, ret, "unable to read superblock");
1386dffce215SKirk McKusick }
1387dffce215SKirk McKusick }
13886eb925f8SKirk McKusick /*
13890dcde5ccSEd Maste * Check for filesystem that was unclean at mount time.
13906eb925f8SKirk McKusick */
13910dcde5ccSEd Maste if ((fs->fs_flags & (FS_UNCLEAN | FS_NEEDSFSCK)) != 0)
139270a0fb43SMina Galić errx(2, "%s is not clean - run fsck.\n", *argv);
1393dffce215SKirk McKusick memcpy(&osblock, fs, fs->fs_sbsize);
1394dffce215SKirk McKusick free(fs);
1395dffce215SKirk McKusick memcpy((void *)&fsun1, (void *)&fsun2, osblock.fs_sbsize);
13963d500078SThomas-Henning von Kamptz
13973d500078SThomas-Henning von Kamptz DBG_OPEN("/tmp/growfs.debug"); /* already here we need a superblock */
1398a1da0740SEdward Tomasz Napierala DBG_DUMP_FS(&sblock, "old sblock");
13993d500078SThomas-Henning von Kamptz
14003d500078SThomas-Henning von Kamptz /*
140150c603c4SEdward Tomasz Napierala * Determine size to grow to. Default to the device size.
14023d500078SThomas-Henning von Kamptz */
1403e35497f1SEdward Tomasz Napierala if (size == 0)
1404e35497f1SEdward Tomasz Napierala size = mediasize;
1405e35497f1SEdward Tomasz Napierala else {
1406e35497f1SEdward Tomasz Napierala if (size > (uint64_t)mediasize) {
1407e35497f1SEdward Tomasz Napierala humanize_number(oldsizebuf, sizeof(oldsizebuf), size,
1408e35497f1SEdward Tomasz Napierala "B", HN_AUTOSCALE, HN_B | HN_NOSPACE | HN_DECIMAL);
1409e35497f1SEdward Tomasz Napierala humanize_number(newsizebuf, sizeof(newsizebuf),
1410e35497f1SEdward Tomasz Napierala mediasize,
1411e35497f1SEdward Tomasz Napierala "B", HN_AUTOSCALE, HN_B | HN_NOSPACE | HN_DECIMAL);
1412e35497f1SEdward Tomasz Napierala
141370a0fb43SMina Galić errx(2, "requested size %s is larger "
1414e35497f1SEdward Tomasz Napierala "than the available %s", oldsizebuf, newsizebuf);
14153d500078SThomas-Henning von Kamptz }
1416e35497f1SEdward Tomasz Napierala }
1417e35497f1SEdward Tomasz Napierala
1418cd379aafSEdward Tomasz Napierala /*
1419cd379aafSEdward Tomasz Napierala * Make sure the new size is a multiple of fs_fsize; /dev/ufssuspend
1420cd379aafSEdward Tomasz Napierala * only supports fragment-aligned IO requests.
1421cd379aafSEdward Tomasz Napierala */
1422cd379aafSEdward Tomasz Napierala size -= size % osblock.fs_fsize;
1423cd379aafSEdward Tomasz Napierala
1424e35497f1SEdward Tomasz Napierala if (size <= (uint64_t)(osblock.fs_size * osblock.fs_fsize)) {
1425e35497f1SEdward Tomasz Napierala humanize_number(oldsizebuf, sizeof(oldsizebuf),
1426e35497f1SEdward Tomasz Napierala osblock.fs_size * osblock.fs_fsize,
1427e35497f1SEdward Tomasz Napierala "B", HN_AUTOSCALE, HN_B | HN_NOSPACE | HN_DECIMAL);
1428e35497f1SEdward Tomasz Napierala humanize_number(newsizebuf, sizeof(newsizebuf), size,
1429e35497f1SEdward Tomasz Napierala "B", HN_AUTOSCALE, HN_B | HN_NOSPACE | HN_DECIMAL);
1430e35497f1SEdward Tomasz Napierala
14313f9acedbSEd Maste if (size == (uint64_t)(osblock.fs_size * osblock.fs_fsize))
14323f9acedbSEd Maste errx(0, "requested size %s is equal to the current "
14333f9acedbSEd Maste "filesystem size %s", newsizebuf, oldsizebuf);
143470a0fb43SMina Galić errx(2, "requested size %s is smaller than the current "
1435e35497f1SEdward Tomasz Napierala "filesystem size %s", newsizebuf, oldsizebuf);
1436e35497f1SEdward Tomasz Napierala }
1437e35497f1SEdward Tomasz Napierala
14382049cc32SKirk McKusick sblock.fs_old_size = sblock.fs_size =
14392049cc32SKirk McKusick dbtofsb(&osblock, size / DEV_BSIZE);
1440549f62faSEdward Tomasz Napierala sblock.fs_providersize = dbtofsb(&osblock, mediasize / DEV_BSIZE);
14413d500078SThomas-Henning von Kamptz
14423d500078SThomas-Henning von Kamptz /*
14433d500078SThomas-Henning von Kamptz * Are we really growing?
14443d500078SThomas-Henning von Kamptz */
14453d500078SThomas-Henning von Kamptz if (osblock.fs_size >= sblock.fs_size) {
144670a0fb43SMina Galić errx(3, "we are not growing (%jd->%jd)",
144775d1ec91SLukas Ertl (intmax_t)osblock.fs_size, (intmax_t)sblock.fs_size);
14483d500078SThomas-Henning von Kamptz }
14493d500078SThomas-Henning von Kamptz
14503d500078SThomas-Henning von Kamptz /*
14513d500078SThomas-Henning von Kamptz * Check if we find an active snapshot.
14523d500078SThomas-Henning von Kamptz */
1453e35497f1SEdward Tomasz Napierala if (yflag == 0) {
14543d500078SThomas-Henning von Kamptz for (j = 0; j < FSMAXSNAP; j++) {
14553d500078SThomas-Henning von Kamptz if (sblock.fs_snapinum[j]) {
145670a0fb43SMina Galić errx(2, "active snapshot found in file system; "
14573d500078SThomas-Henning von Kamptz "please remove all snapshots before "
1458e3ec673eSPhilippe Charnier "using growfs");
14593d500078SThomas-Henning von Kamptz }
1460a1da0740SEdward Tomasz Napierala if (!sblock.fs_snapinum[j]) /* list is dense */
14613d500078SThomas-Henning von Kamptz break;
14623d500078SThomas-Henning von Kamptz }
14633d500078SThomas-Henning von Kamptz }
14643d500078SThomas-Henning von Kamptz
1465e35497f1SEdward Tomasz Napierala if (yflag == 0 && Nflag == 0) {
1466e35497f1SEdward Tomasz Napierala if (statfsp != NULL && (statfsp->f_flags & MNT_RDONLY) == 0)
14672ec1a006SEdward Tomasz Napierala printf("Device is mounted read-write; resizing will "
14682ec1a006SEdward Tomasz Napierala "result in temporary write suspension for %s.\n",
14692ec1a006SEdward Tomasz Napierala statfsp->f_mntonname);
1470e35497f1SEdward Tomasz Napierala printf("It's strongly recommended to make a backup "
1471b2168df8SEdward Tomasz Napierala "before growing the file system.\n"
1472e35497f1SEdward Tomasz Napierala "OK to grow filesystem on %s", device);
1473e35497f1SEdward Tomasz Napierala if (statfsp != NULL)
1474e35497f1SEdward Tomasz Napierala printf(", mounted on %s,", statfsp->f_mntonname);
1475e35497f1SEdward Tomasz Napierala humanize_number(oldsizebuf, sizeof(oldsizebuf),
1476e35497f1SEdward Tomasz Napierala osblock.fs_size * osblock.fs_fsize,
1477e35497f1SEdward Tomasz Napierala "B", HN_AUTOSCALE, HN_B | HN_NOSPACE | HN_DECIMAL);
1478e35497f1SEdward Tomasz Napierala humanize_number(newsizebuf, sizeof(newsizebuf),
1479e35497f1SEdward Tomasz Napierala sblock.fs_size * sblock.fs_fsize,
1480e35497f1SEdward Tomasz Napierala "B", HN_AUTOSCALE, HN_B | HN_NOSPACE | HN_DECIMAL);
1481b8a1930fSEdward Tomasz Napierala printf(" from %s to %s? [yes/no] ", oldsizebuf, newsizebuf);
1482e35497f1SEdward Tomasz Napierala fflush(stdout);
1483adcaff07SThomas-Henning von Kamptz fgets(reply, (int)sizeof(reply), stdin);
1484b8a1930fSEdward Tomasz Napierala if (strcasecmp(reply, "yes\n")){
1485b8a1930fSEdward Tomasz Napierala printf("Response other than \"yes\"; aborting\n");
14863d500078SThomas-Henning von Kamptz exit(0);
14873d500078SThomas-Henning von Kamptz }
14883d500078SThomas-Henning von Kamptz }
14893d500078SThomas-Henning von Kamptz
1490e35497f1SEdward Tomasz Napierala /*
1491e35497f1SEdward Tomasz Napierala * Try to access our device for writing. If it's not mounted,
1492e35497f1SEdward Tomasz Napierala * or mounted read-only, simply open it; otherwise, use UFS
1493e35497f1SEdward Tomasz Napierala * suspension mechanism.
1494e35497f1SEdward Tomasz Napierala */
1495e35497f1SEdward Tomasz Napierala if (Nflag) {
1496e35497f1SEdward Tomasz Napierala fso = -1;
1497e35497f1SEdward Tomasz Napierala } else {
14982ec1a006SEdward Tomasz Napierala if (statfsp != NULL && (statfsp->f_flags & MNT_RDONLY) == 0) {
14992ec1a006SEdward Tomasz Napierala fso = open(_PATH_UFSSUSPEND, O_RDWR);
15002ec1a006SEdward Tomasz Napierala if (fso == -1)
150170a0fb43SMina Galić err(3, "unable to open %s", _PATH_UFSSUSPEND);
15022ec1a006SEdward Tomasz Napierala error = ioctl(fso, UFSSUSPEND, &statfsp->f_fsid);
15032ec1a006SEdward Tomasz Napierala if (error != 0)
150470a0fb43SMina Galić err(3, "UFSSUSPEND");
15052ec1a006SEdward Tomasz Napierala } else {
1506e35497f1SEdward Tomasz Napierala fso = open(device, O_WRONLY);
1507e35497f1SEdward Tomasz Napierala if (fso < 0)
150870a0fb43SMina Galić err(3, "%s", device);
1509e35497f1SEdward Tomasz Napierala }
15102ec1a006SEdward Tomasz Napierala }
15113d500078SThomas-Henning von Kamptz
15123d500078SThomas-Henning von Kamptz /*
1513e35497f1SEdward Tomasz Napierala * Try to access our new last block in the file system.
15143d500078SThomas-Henning von Kamptz */
1515e35497f1SEdward Tomasz Napierala testbuf = malloc(sblock.fs_fsize);
1516e35497f1SEdward Tomasz Napierala if (testbuf == NULL)
151770a0fb43SMina Galić err(3, "malloc");
1518deb35287SEdward Tomasz Napierala rdfs((ufs2_daddr_t)((size - sblock.fs_fsize) / DEV_BSIZE),
1519e35497f1SEdward Tomasz Napierala sblock.fs_fsize, testbuf, fsi);
1520deb35287SEdward Tomasz Napierala wtfs((ufs2_daddr_t)((size - sblock.fs_fsize) / DEV_BSIZE),
1521e35497f1SEdward Tomasz Napierala sblock.fs_fsize, testbuf, fso, Nflag);
1522e35497f1SEdward Tomasz Napierala free(testbuf);
15233d500078SThomas-Henning von Kamptz
15243d500078SThomas-Henning von Kamptz /*
15253d500078SThomas-Henning von Kamptz * Now calculate new superblock values and check for reasonable
15263d500078SThomas-Henning von Kamptz * bound for new file system size:
152750c603c4SEdward Tomasz Napierala * fs_size: is derived from user input
15283d500078SThomas-Henning von Kamptz * fs_dsize: should get updated in the routines creating or
15293d500078SThomas-Henning von Kamptz * updating the cylinder groups on the fly
15303d500078SThomas-Henning von Kamptz * fs_cstotal: should get updated in the routines creating or
15313d500078SThomas-Henning von Kamptz * updating the cylinder groups
15323d500078SThomas-Henning von Kamptz */
15333d500078SThomas-Henning von Kamptz
15343d500078SThomas-Henning von Kamptz /*
15351c85e6a3SKirk McKusick * Update the number of cylinders and cylinder groups in the file system.
15363d500078SThomas-Henning von Kamptz */
15371c85e6a3SKirk McKusick if (sblock.fs_magic == FS_UFS1_MAGIC) {
15381c85e6a3SKirk McKusick sblock.fs_old_ncyl =
15391c85e6a3SKirk McKusick sblock.fs_size * sblock.fs_old_nspf / sblock.fs_old_spc;
15401c85e6a3SKirk McKusick if (sblock.fs_size * sblock.fs_old_nspf >
15411c85e6a3SKirk McKusick sblock.fs_old_ncyl * sblock.fs_old_spc)
15421c85e6a3SKirk McKusick sblock.fs_old_ncyl++;
15433d500078SThomas-Henning von Kamptz }
15441c85e6a3SKirk McKusick sblock.fs_ncg = howmany(sblock.fs_size, sblock.fs_fpg);
15453d500078SThomas-Henning von Kamptz
15463d500078SThomas-Henning von Kamptz /*
1547be1bfa99SEdward Tomasz Napierala * Allocate last cylinder group only if there is enough room
1548be1bfa99SEdward Tomasz Napierala * for at least one data block.
15493d500078SThomas-Henning von Kamptz */
1550be1bfa99SEdward Tomasz Napierala if (sblock.fs_size % sblock.fs_fpg != 0 &&
1551be1bfa99SEdward Tomasz Napierala sblock.fs_size <= cgdmin(&sblock, sblock.fs_ncg - 1)) {
1552be1bfa99SEdward Tomasz Napierala humanize_number(oldsizebuf, sizeof(oldsizebuf),
1553be1bfa99SEdward Tomasz Napierala (sblock.fs_size % sblock.fs_fpg) * sblock.fs_fsize,
1554be1bfa99SEdward Tomasz Napierala "B", HN_AUTOSCALE, HN_B | HN_NOSPACE | HN_DECIMAL);
1555be1bfa99SEdward Tomasz Napierala warnx("no room to allocate last cylinder group; "
1556be1bfa99SEdward Tomasz Napierala "leaving %s unused", oldsizebuf);
15573d500078SThomas-Henning von Kamptz sblock.fs_ncg--;
15581c85e6a3SKirk McKusick if (sblock.fs_magic == FS_UFS1_MAGIC)
15591c85e6a3SKirk McKusick sblock.fs_old_ncyl = sblock.fs_ncg * sblock.fs_old_cpg;
15602049cc32SKirk McKusick sblock.fs_old_size = sblock.fs_size =
15612049cc32SKirk McKusick sblock.fs_ncg * sblock.fs_fpg;
15623d500078SThomas-Henning von Kamptz }
15633d500078SThomas-Henning von Kamptz
15643d500078SThomas-Henning von Kamptz /*
15653d500078SThomas-Henning von Kamptz * Update the space for the cylinder group summary information in the
15663d500078SThomas-Henning von Kamptz * respective cylinder group data area.
15673d500078SThomas-Henning von Kamptz */
15683d500078SThomas-Henning von Kamptz sblock.fs_cssize =
15693d500078SThomas-Henning von Kamptz fragroundup(&sblock, sblock.fs_ncg * sizeof(struct csum));
15703d500078SThomas-Henning von Kamptz
1571a1da0740SEdward Tomasz Napierala if (osblock.fs_size >= sblock.fs_size)
157270a0fb43SMina Galić errx(3, "not enough new space");
15733d500078SThomas-Henning von Kamptz
15743d500078SThomas-Henning von Kamptz DBG_PRINT0("sblock calculated\n");
15753d500078SThomas-Henning von Kamptz
15763d500078SThomas-Henning von Kamptz /*
15773d500078SThomas-Henning von Kamptz * Ok, everything prepared, so now let's do the tricks.
15783d500078SThomas-Henning von Kamptz */
15793d500078SThomas-Henning von Kamptz growfs(fsi, fso, Nflag);
15803d500078SThomas-Henning von Kamptz
15813d500078SThomas-Henning von Kamptz close(fsi);
1582e35497f1SEdward Tomasz Napierala if (fso > -1) {
15832ec1a006SEdward Tomasz Napierala if (statfsp != NULL && (statfsp->f_flags & MNT_RDONLY) == 0) {
15842ec1a006SEdward Tomasz Napierala error = ioctl(fso, UFSRESUME);
15852ec1a006SEdward Tomasz Napierala if (error != 0)
158670a0fb43SMina Galić err(3, "UFSRESUME");
15872ec1a006SEdward Tomasz Napierala }
1588e35497f1SEdward Tomasz Napierala error = close(fso);
1589e35497f1SEdward Tomasz Napierala if (error != 0)
159070a0fb43SMina Galić err(3, "close");
1591906c312bSKirk McKusick if (statfsp != NULL && (statfsp->f_flags & MNT_RDONLY) != 0 &&
1592906c312bSKirk McKusick chkdoreload(statfsp, warn) != 0)
1593906c312bSKirk McKusick exit(9);
15942ec1a006SEdward Tomasz Napierala }
15953d500078SThomas-Henning von Kamptz
15963d500078SThomas-Henning von Kamptz DBG_CLOSE;
15973d500078SThomas-Henning von Kamptz
15983d500078SThomas-Henning von Kamptz DBG_LEAVE;
159991ac1479SEdward Tomasz Napierala return (0);
16003d500078SThomas-Henning von Kamptz }
16013d500078SThomas-Henning von Kamptz
16023d500078SThomas-Henning von Kamptz /*
16033d500078SThomas-Henning von Kamptz * Dump a line of usage.
16043d500078SThomas-Henning von Kamptz */
16053d500078SThomas-Henning von Kamptz static void
usage(void)16064020c5bcSThomas-Henning von Kamptz usage(void)
16073d500078SThomas-Henning von Kamptz {
16083d500078SThomas-Henning von Kamptz DBG_FUNC("usage")
16093d500078SThomas-Henning von Kamptz
16103d500078SThomas-Henning von Kamptz DBG_ENTER;
16113d500078SThomas-Henning von Kamptz
1612e35497f1SEdward Tomasz Napierala fprintf(stderr, "usage: growfs [-Ny] [-s size] special | filesystem\n");
16134020c5bcSThomas-Henning von Kamptz
16143d500078SThomas-Henning von Kamptz DBG_LEAVE;
16154020c5bcSThomas-Henning von Kamptz exit(1);
16163d500078SThomas-Henning von Kamptz }
16173d500078SThomas-Henning von Kamptz
16183d500078SThomas-Henning von Kamptz /*
16196ded0533SJens Schweikhardt * This updates most parameters and the bitmap related to cluster. We have to
16206ded0533SJens Schweikhardt * assume that sblock, osblock, acg are set up.
16213d500078SThomas-Henning von Kamptz */
16223d500078SThomas-Henning von Kamptz static void
updclst(int block)16233d500078SThomas-Henning von Kamptz updclst(int block)
16243d500078SThomas-Henning von Kamptz {
16253d500078SThomas-Henning von Kamptz DBG_FUNC("updclst")
16263d500078SThomas-Henning von Kamptz static int lcs = 0;
16273d500078SThomas-Henning von Kamptz
16283d500078SThomas-Henning von Kamptz DBG_ENTER;
16293d500078SThomas-Henning von Kamptz
1630a1da0740SEdward Tomasz Napierala if (sblock.fs_contigsumsize < 1) /* no clustering */
16313d500078SThomas-Henning von Kamptz return;
16323d500078SThomas-Henning von Kamptz /*
16333d500078SThomas-Henning von Kamptz * update cluster allocation map
16343d500078SThomas-Henning von Kamptz */
16353d500078SThomas-Henning von Kamptz setbit(cg_clustersfree(&acg), block);
16363d500078SThomas-Henning von Kamptz
16373d500078SThomas-Henning von Kamptz /*
16383d500078SThomas-Henning von Kamptz * update cluster summary table
16393d500078SThomas-Henning von Kamptz */
16403d500078SThomas-Henning von Kamptz if (!lcs) {
16413d500078SThomas-Henning von Kamptz /*
16423d500078SThomas-Henning von Kamptz * calculate size for the trailing cluster
16433d500078SThomas-Henning von Kamptz */
16443d500078SThomas-Henning von Kamptz for (block--; lcs < sblock.fs_contigsumsize; block--, lcs++ ) {
1645a1da0740SEdward Tomasz Napierala if (isclr(cg_clustersfree(&acg), block))
16463d500078SThomas-Henning von Kamptz break;
16473d500078SThomas-Henning von Kamptz }
16483d500078SThomas-Henning von Kamptz }
16493d500078SThomas-Henning von Kamptz if (lcs < sblock.fs_contigsumsize) {
1650a1da0740SEdward Tomasz Napierala if (lcs)
16513d500078SThomas-Henning von Kamptz cg_clustersum(&acg)[lcs]--;
16523d500078SThomas-Henning von Kamptz lcs++;
16533d500078SThomas-Henning von Kamptz cg_clustersum(&acg)[lcs]++;
16543d500078SThomas-Henning von Kamptz }
16553d500078SThomas-Henning von Kamptz
16563d500078SThomas-Henning von Kamptz DBG_LEAVE;
16573d500078SThomas-Henning von Kamptz return;
16583d500078SThomas-Henning von Kamptz }
1659e35497f1SEdward Tomasz Napierala
16603abf5d76SKirk McKusick /*
16613abf5d76SKirk McKusick * Calculate the check-hash of the cylinder group.
16623abf5d76SKirk McKusick */
16633abf5d76SKirk McKusick static void
cgckhash(struct cg * cgp)16644887fa36SEd Maste cgckhash(struct cg *cgp)
16653abf5d76SKirk McKusick {
16663abf5d76SKirk McKusick
16673abf5d76SKirk McKusick if ((sblock.fs_metackhash & CK_CYLGRP) == 0)
16683abf5d76SKirk McKusick return;
16693abf5d76SKirk McKusick cgp->cg_ckhash = 0;
16703abf5d76SKirk McKusick cgp->cg_ckhash = calculate_crc32c(~0L, (void *)cgp, sblock.fs_cgsize);
16713abf5d76SKirk McKusick }
1672