~ubuntu-branches/debian/jessie/ufsutils/jessie

« back to all changes in this revision

Viewing changes to growfs.ufs/growfs.c

  • Committer: Bazaar Package Importer
  • Author(s): Guillem Jover, Robert Millan, Guillem Jover, Peter Pentchev
  • Date: 2011-05-31 03:50:05 UTC
  • mfrom: (1.1.4 upstream)
  • Revision ID: james.westby@ubuntu.com-20110531035005-wyiyk25p99ivd0k0
Tags: 8.2-1
[ Robert Millan ]
* Set ufsutils-udeb to kfreebsd-any.

[ Guillem Jover ]
* New upstream version (based on FreeBSD 8.2)
* Now using Standards-Version 3.9.2 (no changes needed).
* Switch to source format “3.0 (quilt)”.
  - Remove quilt from Build-Depends.
  - Remove patch target in debian/rules.
  - Remove now unneeded README.source.
  - Refresh all patches.
* Reorganize source code:
  - Switch from debian/upstream.sh to debian/rules get-orig-source target.
  - Switch from CVS to Subversion to retrieve the source code.
  - Use the same source layout as upstream (no more relocations),
    i.e. lib/, sbin/, sys/sys, sys/ufs.
  - Move libport/ to port/.
  - Merge libdisklabel/ into port/.
* Remove unneeded linking against libtermcap, thus removing the need for
  ncurses.
* Add an empty debian/watch file explaining that there's no packaged
  upstream releases. Suggested by Peter Pentchev.
* Update CVS to Subversion reference to upstream source code in
  debian/copyright.
* Remove unused lib variable from debian/rules.
* Use dpkg-buildflags to set CPPFLAGS, CFLAGS and LDFLAGS.
  Based on a patch by Peter Pentchev.
* Remove bogus reference to BSD license in /usr/share/common-licenses.
* Always set -I../../sys, even on GNU/kFreeBSD systems.

[ Peter Pentchev ]
* Remove duplicate section “utils” from ufsutils binary package.
* Remove XC- prefix from Package-Type.
* Honour CPPFLAGS and LDFLAGS and do not link with CFLAGS.

Show diffs side-by-side

added added

removed removed

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