]> CyberLeo.Net >> Repos - FreeBSD/releng/10.0.git/blob - sbin/fsck_ffs/pass5.c
- Copy stable/10 (r259064) to releng/10.0 as part of the
[FreeBSD/releng/10.0.git] / sbin / fsck_ffs / pass5.c
1 /*
2  * Copyright (c) 1980, 1986, 1993
3  *      The Regents of the University of California.  All rights reserved.
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions
7  * are met:
8  * 1. Redistributions of source code must retain the above copyright
9  *    notice, this list of conditions and the following disclaimer.
10  * 2. Redistributions in binary form must reproduce the above copyright
11  *    notice, this list of conditions and the following disclaimer in the
12  *    documentation and/or other materials provided with the distribution.
13  * 4. Neither the name of the University nor the names of its contributors
14  *    may be used to endorse or promote products derived from this software
15  *    without specific prior written permission.
16  *
17  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
18  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
19  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
20  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
21  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
22  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
23  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
24  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
25  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
26  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
27  * SUCH DAMAGE.
28  */
29
30 #if 0
31 #ifndef lint
32 static const char sccsid[] = "@(#)pass5.c       8.9 (Berkeley) 4/28/95";
33 #endif /* not lint */
34 #endif
35 #include <sys/cdefs.h>
36 __FBSDID("$FreeBSD$");
37
38 #include <sys/param.h>
39 #include <sys/sysctl.h>
40
41 #include <ufs/ufs/dinode.h>
42 #include <ufs/ffs/fs.h>
43
44 #include <err.h>
45 #include <inttypes.h>
46 #include <limits.h>
47 #include <string.h>
48 #include <libufs.h>
49
50 #include "fsck.h"
51
52 static void check_maps(u_char *, u_char *, int, ufs2_daddr_t, const char *,
53                         int *, int, int, int);
54 static void clear_blocks(ufs2_daddr_t start, ufs2_daddr_t end);
55
56 void
57 pass5(void)
58 {
59         int c, i, j, blk, frags, basesize, mapsize;
60         int inomapsize, blkmapsize;
61         struct fs *fs = &sblock;
62         ufs2_daddr_t d, dbase, dmax, start;
63         int rewritecg = 0;
64         struct csum *cs;
65         struct csum_total cstotal;
66         struct inodesc idesc[3];
67         char buf[MAXBSIZE];
68         struct cg *cg, *newcg = (struct cg *)buf;
69         struct bufarea *cgbp;
70
71         inoinfo(WINO)->ino_state = USTATE;
72         memset(newcg, 0, (size_t)fs->fs_cgsize);
73         newcg->cg_niblk = fs->fs_ipg;
74         if (cvtlevel >= 3) {
75                 if (fs->fs_maxcontig < 2 && fs->fs_contigsumsize > 0) {
76                         if (preen)
77                                 pwarn("DELETING CLUSTERING MAPS\n");
78                         if (preen || reply("DELETE CLUSTERING MAPS")) {
79                                 fs->fs_contigsumsize = 0;
80                                 rewritecg = 1;
81                                 sbdirty();
82                         }
83                 }
84                 if (fs->fs_maxcontig > 1) {
85                         const char *doit = 0;
86
87                         if (fs->fs_contigsumsize < 1) {
88                                 doit = "CREAT";
89                         } else if (fs->fs_contigsumsize < fs->fs_maxcontig &&
90                                    fs->fs_contigsumsize < FS_MAXCONTIG) {
91                                 doit = "EXPAND";
92                         }
93                         if (doit) {
94                                 i = fs->fs_contigsumsize;
95                                 fs->fs_contigsumsize =
96                                     MIN(fs->fs_maxcontig, FS_MAXCONTIG);
97                                 if (CGSIZE(fs) > (u_int)fs->fs_bsize) {
98                                         pwarn("CANNOT %s CLUSTER MAPS\n", doit);
99                                         fs->fs_contigsumsize = i;
100                                 } else if (preen ||
101                                     reply("CREATE CLUSTER MAPS")) {
102                                         if (preen)
103                                                 pwarn("%sING CLUSTER MAPS\n",
104                                                     doit);
105                                         fs->fs_cgsize =
106                                             fragroundup(fs, CGSIZE(fs));
107                                         rewritecg = 1;
108                                         sbdirty();
109                                 }
110                         }
111                 }
112         }
113         basesize = &newcg->cg_space[0] - (u_char *)(&newcg->cg_firstfield);
114         if (sblock.fs_magic == FS_UFS2_MAGIC) {
115                 newcg->cg_iusedoff = basesize;
116         } else {
117                 /*
118                  * We reserve the space for the old rotation summary
119                  * tables for the benefit of old kernels, but do not
120                  * maintain them in modern kernels. In time, they can
121                  * go away.
122                  */
123                 newcg->cg_old_btotoff = basesize;
124                 newcg->cg_old_boff = newcg->cg_old_btotoff +
125                     fs->fs_old_cpg * sizeof(int32_t);
126                 newcg->cg_iusedoff = newcg->cg_old_boff +
127                     fs->fs_old_cpg * fs->fs_old_nrpos * sizeof(u_int16_t);
128                 memset(&newcg->cg_space[0], 0, newcg->cg_iusedoff - basesize);
129         }
130         inomapsize = howmany(fs->fs_ipg, CHAR_BIT);
131         newcg->cg_freeoff = newcg->cg_iusedoff + inomapsize;
132         blkmapsize = howmany(fs->fs_fpg, CHAR_BIT);
133         newcg->cg_nextfreeoff = newcg->cg_freeoff + blkmapsize;
134         if (fs->fs_contigsumsize > 0) {
135                 newcg->cg_clustersumoff = newcg->cg_nextfreeoff -
136                     sizeof(u_int32_t);
137                 newcg->cg_clustersumoff =
138                     roundup(newcg->cg_clustersumoff, sizeof(u_int32_t));
139                 newcg->cg_clusteroff = newcg->cg_clustersumoff +
140                     (fs->fs_contigsumsize + 1) * sizeof(u_int32_t);
141                 newcg->cg_nextfreeoff = newcg->cg_clusteroff +
142                     howmany(fragstoblks(fs, fs->fs_fpg), CHAR_BIT);
143         }
144         newcg->cg_magic = CG_MAGIC;
145         mapsize = newcg->cg_nextfreeoff - newcg->cg_iusedoff;
146         memset(&idesc[0], 0, sizeof idesc);
147         for (i = 0; i < 3; i++)
148                 idesc[i].id_type = ADDR;
149         memset(&cstotal, 0, sizeof(struct csum_total));
150         dmax = blknum(fs, fs->fs_size + fs->fs_frag - 1);
151         for (d = fs->fs_size; d < dmax; d++)
152                 setbmap(d);
153         for (c = 0; c < fs->fs_ncg; c++) {
154                 if (got_siginfo) {
155                         printf("%s: phase 5: cyl group %d of %d (%d%%)\n",
156                             cdevname, c, sblock.fs_ncg,
157                             c * 100 / sblock.fs_ncg);
158                         got_siginfo = 0;
159                 }
160                 if (got_sigalarm) {
161                         setproctitle("%s p5 %d%%", cdevname,
162                             c * 100 / sblock.fs_ncg);
163                         got_sigalarm = 0;
164                 }
165                 cgbp = cgget(c);
166                 cg = cgbp->b_un.b_cg;
167                 if (!cg_chkmagic(cg))
168                         pfatal("CG %d: BAD MAGIC NUMBER\n", c);
169                 newcg->cg_time = cg->cg_time;
170                 newcg->cg_old_time = cg->cg_old_time;
171                 newcg->cg_unrefs = cg->cg_unrefs;
172                 newcg->cg_cgx = c;
173                 dbase = cgbase(fs, c);
174                 dmax = dbase + fs->fs_fpg;
175                 if (dmax > fs->fs_size)
176                         dmax = fs->fs_size;
177                 newcg->cg_ndblk = dmax - dbase;
178                 if (fs->fs_magic == FS_UFS1_MAGIC) {
179                         if (c == fs->fs_ncg - 1)
180                                 newcg->cg_old_ncyl = howmany(newcg->cg_ndblk,
181                                     fs->fs_fpg / fs->fs_old_cpg);
182                         else
183                                 newcg->cg_old_ncyl = fs->fs_old_cpg;
184                         newcg->cg_old_niblk = fs->fs_ipg;
185                         newcg->cg_niblk = 0;
186                 }
187                 if (fs->fs_contigsumsize > 0)
188                         newcg->cg_nclusterblks = newcg->cg_ndblk / fs->fs_frag;
189                 newcg->cg_cs.cs_ndir = 0;
190                 newcg->cg_cs.cs_nffree = 0;
191                 newcg->cg_cs.cs_nbfree = 0;
192                 newcg->cg_cs.cs_nifree = fs->fs_ipg;
193                 if (cg->cg_rotor >= 0 && cg->cg_rotor < newcg->cg_ndblk)
194                         newcg->cg_rotor = cg->cg_rotor;
195                 else
196                         newcg->cg_rotor = 0;
197                 if (cg->cg_frotor >= 0 && cg->cg_frotor < newcg->cg_ndblk)
198                         newcg->cg_frotor = cg->cg_frotor;
199                 else
200                         newcg->cg_frotor = 0;
201                 if (cg->cg_irotor >= 0 && cg->cg_irotor < fs->fs_ipg)
202                         newcg->cg_irotor = cg->cg_irotor;
203                 else
204                         newcg->cg_irotor = 0;
205                 if (fs->fs_magic == FS_UFS1_MAGIC) {
206                         newcg->cg_initediblk = 0;
207                 } else {
208                         if ((unsigned)cg->cg_initediblk > fs->fs_ipg)
209                                 newcg->cg_initediblk = fs->fs_ipg;
210                         else
211                                 newcg->cg_initediblk = cg->cg_initediblk;
212                 }
213                 memset(&newcg->cg_frsum[0], 0, sizeof newcg->cg_frsum);
214                 memset(cg_inosused(newcg), 0, (size_t)(mapsize));
215                 j = fs->fs_ipg * c;
216                 for (i = 0; i < inostathead[c].il_numalloced; j++, i++) {
217                         switch (inoinfo(j)->ino_state) {
218
219                         case USTATE:
220                                 break;
221
222                         case DSTATE:
223                         case DCLEAR:
224                         case DFOUND:
225                         case DZLINK:
226                                 newcg->cg_cs.cs_ndir++;
227                                 /* FALLTHROUGH */
228
229                         case FSTATE:
230                         case FCLEAR:
231                         case FZLINK:
232                                 newcg->cg_cs.cs_nifree--;
233                                 setbit(cg_inosused(newcg), i);
234                                 break;
235
236                         default:
237                                 if (j < (int)ROOTINO)
238                                         break;
239                                 errx(EEXIT, "BAD STATE %d FOR INODE I=%d",
240                                     inoinfo(j)->ino_state, j);
241                         }
242                 }
243                 if (c == 0)
244                         for (i = 0; i < (int)ROOTINO; i++) {
245                                 setbit(cg_inosused(newcg), i);
246                                 newcg->cg_cs.cs_nifree--;
247                         }
248                 start = -1;
249                 for (i = 0, d = dbase;
250                      d < dmax;
251                      d += fs->fs_frag, i += fs->fs_frag) {
252                         frags = 0;
253                         for (j = 0; j < fs->fs_frag; j++) {
254                                 if (testbmap(d + j)) {
255                                         if ((Eflag || Zflag) && start != -1) {
256                                                 clear_blocks(start, d + j - 1);
257                                                 start = -1;
258                                         }
259                                         continue;
260                                 }
261                                 if (start == -1)
262                                         start = d + j;
263                                 setbit(cg_blksfree(newcg), i + j);
264                                 frags++;
265                         }
266                         if (frags == fs->fs_frag) {
267                                 newcg->cg_cs.cs_nbfree++;
268                                 if (fs->fs_contigsumsize > 0)
269                                         setbit(cg_clustersfree(newcg),
270                                             i / fs->fs_frag);
271                         } else if (frags > 0) {
272                                 newcg->cg_cs.cs_nffree += frags;
273                                 blk = blkmap(fs, cg_blksfree(newcg), i);
274                                 ffs_fragacct(fs, blk, newcg->cg_frsum, 1);
275                         }
276                 }
277                 if ((Eflag || Zflag) && start != -1)
278                         clear_blocks(start, d - 1);
279                 if (fs->fs_contigsumsize > 0) {
280                         int32_t *sump = cg_clustersum(newcg);
281                         u_char *mapp = cg_clustersfree(newcg);
282                         int map = *mapp++;
283                         int bit = 1;
284                         int run = 0;
285
286                         for (i = 0; i < newcg->cg_nclusterblks; i++) {
287                                 if ((map & bit) != 0) {
288                                         run++;
289                                 } else if (run != 0) {
290                                         if (run > fs->fs_contigsumsize)
291                                                 run = fs->fs_contigsumsize;
292                                         sump[run]++;
293                                         run = 0;
294                                 }
295                                 if ((i & (CHAR_BIT - 1)) != (CHAR_BIT - 1)) {
296                                         bit <<= 1;
297                                 } else {
298                                         map = *mapp++;
299                                         bit = 1;
300                                 }
301                         }
302                         if (run != 0) {
303                                 if (run > fs->fs_contigsumsize)
304                                         run = fs->fs_contigsumsize;
305                                 sump[run]++;
306                         }
307                 }
308                 if (bkgrdflag != 0) {
309                         cstotal.cs_nffree += cg->cg_cs.cs_nffree;
310                         cstotal.cs_nbfree += cg->cg_cs.cs_nbfree;
311                         cstotal.cs_nifree += cg->cg_cs.cs_nifree;
312                         cstotal.cs_ndir += cg->cg_cs.cs_ndir;
313                 } else {
314                         cstotal.cs_nffree += newcg->cg_cs.cs_nffree;
315                         cstotal.cs_nbfree += newcg->cg_cs.cs_nbfree;
316                         cstotal.cs_nifree += newcg->cg_cs.cs_nifree;
317                         cstotal.cs_ndir += newcg->cg_cs.cs_ndir;
318                 }
319                 cs = &fs->fs_cs(fs, c);
320                 if (cursnapshot == 0 &&
321                     memcmp(&newcg->cg_cs, cs, sizeof *cs) != 0 &&
322                     dofix(&idesc[0], "FREE BLK COUNT(S) WRONG IN SUPERBLK")) {
323                         memmove(cs, &newcg->cg_cs, sizeof *cs);
324                         sbdirty();
325                 }
326                 if (rewritecg) {
327                         memmove(cg, newcg, (size_t)fs->fs_cgsize);
328                         dirty(cgbp);
329                         continue;
330                 }
331                 if (cursnapshot == 0 &&
332                     memcmp(newcg, cg, basesize) != 0 &&
333                     dofix(&idesc[2], "SUMMARY INFORMATION BAD")) {
334                         memmove(cg, newcg, (size_t)basesize);
335                         dirty(cgbp);
336                 }
337                 if (bkgrdflag != 0 || usedsoftdep || debug)
338                         update_maps(cg, newcg, bkgrdflag);
339                 if (cursnapshot == 0 &&
340                     memcmp(cg_inosused(newcg), cg_inosused(cg), mapsize) != 0 &&
341                     dofix(&idesc[1], "BLK(S) MISSING IN BIT MAPS")) {
342                         memmove(cg_inosused(cg), cg_inosused(newcg),
343                               (size_t)mapsize);
344                         dirty(cgbp);
345                 }
346         }
347         if (cursnapshot == 0 &&
348             memcmp(&cstotal, &fs->fs_cstotal, sizeof cstotal) != 0
349             && dofix(&idesc[0], "SUMMARY BLK COUNT(S) WRONG IN SUPERBLK")) {
350                 memmove(&fs->fs_cstotal, &cstotal, sizeof cstotal);
351                 fs->fs_ronly = 0;
352                 fs->fs_fmod = 0;
353                 sbdirty();
354         }
355
356         /*
357          * When doing background fsck on a snapshot, figure out whether
358          * the superblock summary is inaccurate and correct it when
359          * necessary.
360          */
361         if (cursnapshot != 0) {
362                 cmd.size = 1;
363
364                 cmd.value = cstotal.cs_ndir - fs->fs_cstotal.cs_ndir;
365                 if (cmd.value != 0) {
366                         if (debug)
367                                 printf("adjndir by %+" PRIi64 "\n", cmd.value);
368                         if (bkgrdsumadj == 0 || sysctl(adjndir, MIBSIZE, 0, 0,
369                             &cmd, sizeof cmd) == -1)
370                                 rwerror("ADJUST NUMBER OF DIRECTORIES", cmd.value);
371                 }
372
373                 cmd.value = cstotal.cs_nbfree - fs->fs_cstotal.cs_nbfree;
374                 if (cmd.value != 0) {
375                         if (debug)
376                                 printf("adjnbfree by %+" PRIi64 "\n", cmd.value);
377                         if (bkgrdsumadj == 0 || sysctl(adjnbfree, MIBSIZE, 0, 0,
378                             &cmd, sizeof cmd) == -1)
379                                 rwerror("ADJUST NUMBER OF FREE BLOCKS", cmd.value);
380                 }
381
382                 cmd.value = cstotal.cs_nifree - fs->fs_cstotal.cs_nifree;
383                 if (cmd.value != 0) {
384                         if (debug)
385                                 printf("adjnifree by %+" PRIi64 "\n", cmd.value);
386                         if (bkgrdsumadj == 0 || sysctl(adjnifree, MIBSIZE, 0, 0,
387                             &cmd, sizeof cmd) == -1)
388                                 rwerror("ADJUST NUMBER OF FREE INODES", cmd.value);
389                 }
390
391                 cmd.value = cstotal.cs_nffree - fs->fs_cstotal.cs_nffree;
392                 if (cmd.value != 0) {
393                         if (debug)
394                                 printf("adjnffree by %+" PRIi64 "\n", cmd.value);
395                         if (bkgrdsumadj == 0 || sysctl(adjnffree, MIBSIZE, 0, 0,
396                             &cmd, sizeof cmd) == -1)
397                                 rwerror("ADJUST NUMBER OF FREE FRAGS", cmd.value);
398                 }
399
400                 cmd.value = cstotal.cs_numclusters - fs->fs_cstotal.cs_numclusters;
401                 if (cmd.value != 0) {
402                         if (debug)
403                                 printf("adjnumclusters by %+" PRIi64 "\n", cmd.value);
404                         if (bkgrdsumadj == 0 || sysctl(adjnumclusters, MIBSIZE, 0, 0,
405                             &cmd, sizeof cmd) == -1)
406                                 rwerror("ADJUST NUMBER OF FREE CLUSTERS", cmd.value);
407                 }
408         }
409 }
410
411 /*
412  * Compare the original cylinder group inode and block bitmaps with the
413  * updated cylinder group inode and block bitmaps. Free inodes and blocks
414  * that have been added. Complain if any previously freed inodes blocks
415  * are now allocated.
416  */
417 void
418 update_maps(
419         struct cg *oldcg,       /* cylinder group of claimed allocations */
420         struct cg *newcg,       /* cylinder group of determined allocations */
421         int usesysctl)          /* 1 => use sysctl interface to update maps */
422 {
423         int inomapsize, excessdirs;
424         struct fs *fs = &sblock;
425
426         inomapsize = howmany(fs->fs_ipg, CHAR_BIT);
427         excessdirs = oldcg->cg_cs.cs_ndir - newcg->cg_cs.cs_ndir;
428         if (excessdirs < 0) {
429                 pfatal("LOST %d DIRECTORIES\n", -excessdirs);
430                 excessdirs = 0;
431         }
432         if (excessdirs > 0)
433                 check_maps(cg_inosused(newcg), cg_inosused(oldcg), inomapsize,
434                     oldcg->cg_cgx * (ufs2_daddr_t)fs->fs_ipg, "DIR", freedirs,
435                     0, excessdirs, usesysctl);
436         check_maps(cg_inosused(newcg), cg_inosused(oldcg), inomapsize,
437             oldcg->cg_cgx * (ufs2_daddr_t)fs->fs_ipg, "FILE", freefiles,
438             excessdirs, fs->fs_ipg, usesysctl);
439         check_maps(cg_blksfree(oldcg), cg_blksfree(newcg),
440             howmany(fs->fs_fpg, CHAR_BIT),
441             oldcg->cg_cgx * (ufs2_daddr_t)fs->fs_fpg, "FRAG",
442             freeblks, 0, fs->fs_fpg, usesysctl);
443 }
444
445 static void
446 check_maps(
447         u_char *map1,   /* map of claimed allocations */
448         u_char *map2,   /* map of determined allocations */
449         int mapsize,    /* size of above two maps */
450         ufs2_daddr_t startvalue, /* resource value for first element in map */
451         const char *name,       /* name of resource found in maps */
452         int *opcode,    /* sysctl opcode to free resource */
453         int skip,       /* number of entries to skip before starting to free */
454         int limit,      /* limit on number of entries to free */
455         int usesysctl)  /* 1 => use sysctl interface to update maps */
456 {
457 #       define BUFSIZE 16
458         char buf[BUFSIZE];
459         long i, j, k, l, m, size;
460         ufs2_daddr_t n, astart, aend, ustart, uend;
461         void (*msg)(const char *fmt, ...);
462
463         if (usesysctl)
464                 msg = pfatal;
465         else
466                 msg = pwarn;
467         astart = ustart = aend = uend = -1;
468         for (i = 0; i < mapsize; i++) {
469                 j = *map1++;
470                 k = *map2++;
471                 if (j == k)
472                         continue;
473                 for (m = 0, l = 1; m < CHAR_BIT; m++, l <<= 1) {
474                         if ((j & l) == (k & l))
475                                 continue;
476                         n = startvalue + i * CHAR_BIT + m;
477                         if ((j & l) != 0) {
478                                 if (astart == -1) {
479                                         astart = aend = n;
480                                         continue;
481                                 }
482                                 if (aend + 1 == n) {
483                                         aend = n;
484                                         continue;
485                                 }
486                                 if (astart == aend)
487                                         (*msg)("ALLOCATED %s %" PRId64
488                                             " MARKED FREE\n",
489                                             name, astart);
490                                 else
491                                         (*msg)("%s %sS %" PRId64 "-%" PRId64
492                                             " MARKED FREE\n",
493                                             "ALLOCATED", name, astart, aend);
494                                 astart = aend = n;
495                         } else {
496                                 if (ustart == -1) {
497                                         ustart = uend = n;
498                                         continue;
499                                 }
500                                 if (uend + 1 == n) {
501                                         uend = n;
502                                         continue;
503                                 }
504                                 size = uend - ustart + 1;
505                                 if (size <= skip) {
506                                         skip -= size;
507                                         ustart = uend = n;
508                                         continue;
509                                 }
510                                 if (skip > 0) {
511                                         ustart += skip;
512                                         size -= skip;
513                                         skip = 0;
514                                 }
515                                 if (size > limit)
516                                         size = limit;
517                                 if (debug && size == 1)
518                                         pwarn("%s %s %" PRId64
519                                             " MARKED USED\n",
520                                             "UNALLOCATED", name, ustart);
521                                 else if (debug)
522                                         pwarn("%s %sS %" PRId64 "-%" PRId64
523                                             " MARKED USED\n",
524                                             "UNALLOCATED", name, ustart,
525                                             ustart + size - 1);
526                                 if (usesysctl != 0) {
527                                         cmd.value = ustart;
528                                         cmd.size = size;
529                                         if (sysctl(opcode, MIBSIZE, 0, 0,
530                                             &cmd, sizeof cmd) == -1) {
531                                                 snprintf(buf, BUFSIZE,
532                                                     "FREE %s", name);
533                                                 rwerror(buf, cmd.value);
534                                         }
535                                 }
536                                 limit -= size;
537                                 if (limit <= 0)
538                                         return;
539                                 ustart = uend = n;
540                         }
541                 }
542         }
543         if (astart != -1) {
544                 if (astart == aend)
545                         (*msg)("ALLOCATED %s %" PRId64
546                             " MARKED FREE\n", name, astart);
547                 else
548                         (*msg)("ALLOCATED %sS %" PRId64 "-%" PRId64
549                             " MARKED FREE\n",
550                             name, astart, aend);
551         }
552         if (ustart != -1) {
553                 size = uend - ustart + 1;
554                 if (size <= skip)
555                         return;
556                 if (skip > 0) {
557                         ustart += skip;
558                         size -= skip;
559                 }
560                 if (size > limit)
561                         size = limit;
562                 if (debug) {
563                         if (size == 1)
564                                 pwarn("UNALLOCATED %s %" PRId64
565                                     " MARKED USED\n",
566                                     name, ustart);
567                         else
568                                 pwarn("UNALLOCATED %sS %" PRId64 "-%" PRId64
569                                     " MARKED USED\n",
570                                     name, ustart, ustart + size - 1);
571                 }
572                 if (usesysctl != 0) {
573                         cmd.value = ustart;
574                         cmd.size = size;
575                         if (sysctl(opcode, MIBSIZE, 0, 0, &cmd,
576                             sizeof cmd) == -1) {
577                                 snprintf(buf, BUFSIZE, "FREE %s", name);
578                                 rwerror(buf, cmd.value);
579                         }
580                 }
581         }
582 }
583
584 static void
585 clear_blocks(ufs2_daddr_t start, ufs2_daddr_t end)
586 {
587
588         if (debug)
589                 printf("Zero frags %jd to %jd\n", start, end);
590         if (Zflag)
591                 blzero(fswritefd, fsbtodb(&sblock, start),
592                     lfragtosize(&sblock, end - start + 1));
593         if (Eflag)
594                 blerase(fswritefd, fsbtodb(&sblock, start),
595                     lfragtosize(&sblock, end - start + 1));
596 }