Sat Jan 26 00:19:39 2013 UTC ()
make the buffer functions look exactly like the kernel ones and add other
cruft to make the kernel files compile.


(christos)
diff -r1.53 -r1.54 src/usr.sbin/makefs/ffs.c
diff -r1.12 -r1.13 src/usr.sbin/makefs/ffs/buf.c
diff -r1.2 -r1.3 src/usr.sbin/makefs/ffs/buf.h
diff -r1.20 -r1.21 src/usr.sbin/makefs/ffs/ffs_alloc.c
diff -r1.14 -r1.15 src/usr.sbin/makefs/ffs/ffs_balloc.c

cvs diff -r1.53 -r1.54 src/usr.sbin/makefs/ffs.c (switch to unified diff)

--- src/usr.sbin/makefs/ffs.c 2013/01/24 01:10:47 1.53
+++ src/usr.sbin/makefs/ffs.c 2013/01/26 00:19:39 1.54
@@ -1,1155 +1,1155 @@ @@ -1,1155 +1,1155 @@
1/* $NetBSD: ffs.c,v 1.53 2013/01/24 01:10:47 christos Exp $ */ 1/* $NetBSD: ffs.c,v 1.54 2013/01/26 00:19:39 christos Exp $ */
2 2
3/* 3/*
4 * Copyright (c) 2001 Wasabi Systems, Inc. 4 * Copyright (c) 2001 Wasabi Systems, Inc.
5 * All rights reserved. 5 * All rights reserved.
6 * 6 *
7 * Written by Luke Mewburn for Wasabi Systems, Inc. 7 * Written by Luke Mewburn for Wasabi Systems, Inc.
8 * 8 *
9 * Redistribution and use in source and binary forms, with or without 9 * Redistribution and use in source and binary forms, with or without
10 * modification, are permitted provided that the following conditions 10 * modification, are permitted provided that the following conditions
11 * are met: 11 * are met:
12 * 1. Redistributions of source code must retain the above copyright 12 * 1. Redistributions of source code must retain the above copyright
13 * notice, this list of conditions and the following disclaimer. 13 * notice, this list of conditions and the following disclaimer.
14 * 2. Redistributions in binary form must reproduce the above copyright 14 * 2. Redistributions in binary form must reproduce the above copyright
15 * notice, this list of conditions and the following disclaimer in the 15 * notice, this list of conditions and the following disclaimer in the
16 * documentation and/or other materials provided with the distribution. 16 * documentation and/or other materials provided with the distribution.
17 * 3. All advertising materials mentioning features or use of this software 17 * 3. All advertising materials mentioning features or use of this software
18 * must display the following acknowledgement: 18 * must display the following acknowledgement:
19 * This product includes software developed for the NetBSD Project by 19 * This product includes software developed for the NetBSD Project by
20 * Wasabi Systems, Inc. 20 * Wasabi Systems, Inc.
21 * 4. The name of Wasabi Systems, Inc. may not be used to endorse 21 * 4. The name of Wasabi Systems, Inc. may not be used to endorse
22 * or promote products derived from this software without specific prior 22 * or promote products derived from this software without specific prior
23 * written permission. 23 * written permission.
24 * 24 *
25 * THIS SOFTWARE IS PROVIDED BY WASABI SYSTEMS, INC. ``AS IS'' AND 25 * THIS SOFTWARE IS PROVIDED BY WASABI SYSTEMS, INC. ``AS IS'' AND
26 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 26 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
27 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 27 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
28 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL WASABI SYSTEMS, INC 28 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL WASABI SYSTEMS, INC
29 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 29 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
30 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 30 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
31 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 31 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
32 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 32 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
33 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 33 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
34 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 34 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
35 * POSSIBILITY OF SUCH DAMAGE. 35 * POSSIBILITY OF SUCH DAMAGE.
36 */ 36 */
37/* 37/*
38 * Copyright (c) 1982, 1986, 1989, 1993 38 * Copyright (c) 1982, 1986, 1989, 1993
39 * The Regents of the University of California. All rights reserved. 39 * The Regents of the University of California. All rights reserved.
40 * 40 *
41 * Redistribution and use in source and binary forms, with or without 41 * Redistribution and use in source and binary forms, with or without
42 * modification, are permitted provided that the following conditions 42 * modification, are permitted provided that the following conditions
43 * are met: 43 * are met:
44 * 1. Redistributions of source code must retain the above copyright 44 * 1. Redistributions of source code must retain the above copyright
45 * notice, this list of conditions and the following disclaimer. 45 * notice, this list of conditions and the following disclaimer.
46 * 2. Redistributions in binary form must reproduce the above copyright 46 * 2. Redistributions in binary form must reproduce the above copyright
47 * notice, this list of conditions and the following disclaimer in the 47 * notice, this list of conditions and the following disclaimer in the
48 * documentation and/or other materials provided with the distribution. 48 * documentation and/or other materials provided with the distribution.
49 * 3. Neither the name of the University nor the names of its contributors 49 * 3. Neither the name of the University nor the names of its contributors
50 * may be used to endorse or promote products derived from this software 50 * may be used to endorse or promote products derived from this software
51 * without specific prior written permission. 51 * without specific prior written permission.
52 * 52 *
53 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 53 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
54 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 54 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
55 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 55 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
56 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 56 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
57 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 57 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
58 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 58 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
59 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 59 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
60 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 60 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
61 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 61 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
62 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 62 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
63 * SUCH DAMAGE. 63 * SUCH DAMAGE.
64 * 64 *
65 * @(#)ffs_alloc.c 8.19 (Berkeley) 7/13/95 65 * @(#)ffs_alloc.c 8.19 (Berkeley) 7/13/95
66 */ 66 */
67 67
68#if HAVE_NBTOOL_CONFIG_H 68#if HAVE_NBTOOL_CONFIG_H
69#include "nbtool_config.h" 69#include "nbtool_config.h"
70#endif 70#endif
71 71
72#include <sys/cdefs.h> 72#include <sys/cdefs.h>
73#if defined(__RCSID) && !defined(__lint) 73#if defined(__RCSID) && !defined(__lint)
74__RCSID("$NetBSD: ffs.c,v 1.53 2013/01/24 01:10:47 christos Exp $"); 74__RCSID("$NetBSD: ffs.c,v 1.54 2013/01/26 00:19:39 christos Exp $");
75#endif /* !__lint */ 75#endif /* !__lint */
76 76
77#include <sys/param.h> 77#include <sys/param.h>
78 78
79#if !HAVE_NBTOOL_CONFIG_H 79#if !HAVE_NBTOOL_CONFIG_H
80#include <sys/mount.h> 80#include <sys/mount.h>
81#endif 81#endif
82 82
83#include <assert.h> 83#include <assert.h>
84#include <errno.h> 84#include <errno.h>
85#include <fcntl.h> 85#include <fcntl.h>
86#include <stdarg.h> 86#include <stdarg.h>
87#include <stdio.h> 87#include <stdio.h>
88#include <stdlib.h> 88#include <stdlib.h>
89#include <string.h> 89#include <string.h>
90#include <unistd.h> 90#include <unistd.h>
91 91
92#include "makefs.h" 92#include "makefs.h"
93#include "ffs.h" 93#include "ffs.h"
94 94
95#if HAVE_STRUCT_STATVFS_F_IOSIZE && HAVE_FSTATVFS 95#if HAVE_STRUCT_STATVFS_F_IOSIZE && HAVE_FSTATVFS
96#include <sys/statvfs.h> 96#include <sys/statvfs.h>
97#endif 97#endif
98 98
99#include <ufs/ufs/dinode.h> 99#include <ufs/ufs/dinode.h>
100#include <ufs/ufs/dir.h> 100#include <ufs/ufs/dir.h>
101#include <ufs/ffs/fs.h> 101#include <ufs/ffs/fs.h>
102#include <ufs/ufs/ufs_bswap.h> 102#include <ufs/ufs/ufs_bswap.h>
103 103
104#include "ffs/ufs_inode.h" 104#include "ffs/ufs_inode.h"
105#include "ffs/newfs_extern.h" 105#include "ffs/newfs_extern.h"
106#include "ffs/ffs_extern.h" 106#include "ffs/ffs_extern.h"
107 107
108#undef DIP 108#undef DIP
109#define DIP(dp, field) \ 109#define DIP(dp, field) \
110 ((ffs_opts->version == 1) ? \ 110 ((ffs_opts->version == 1) ? \
111 (dp)->ffs1_din.di_##field : (dp)->ffs2_din.di_##field) 111 (dp)->ffs1_din.di_##field : (dp)->ffs2_din.di_##field)
112 112
113/* 113/*
114 * Various file system defaults (cribbed from newfs(8)). 114 * Various file system defaults (cribbed from newfs(8)).
115 */ 115 */
116#define DFL_FRAGSIZE 1024 /* fragment size */ 116#define DFL_FRAGSIZE 1024 /* fragment size */
117#define DFL_BLKSIZE 8192 /* block size */ 117#define DFL_BLKSIZE 8192 /* block size */
118#define DFL_SECSIZE 512 /* sector size */ 118#define DFL_SECSIZE 512 /* sector size */
119#define DFL_CYLSPERGROUP 65536 /* cylinders per group */ 119#define DFL_CYLSPERGROUP 65536 /* cylinders per group */
120#define DFL_FRAGSPERINODE 4 /* fragments per inode */ 120#define DFL_FRAGSPERINODE 4 /* fragments per inode */
121#define DFL_ROTDELAY 0 /* rotational delay */ 121#define DFL_ROTDELAY 0 /* rotational delay */
122#define DFL_NRPOS 1 /* rotational positions */ 122#define DFL_NRPOS 1 /* rotational positions */
123#define DFL_RPM 3600 /* rpm of disk */ 123#define DFL_RPM 3600 /* rpm of disk */
124#define DFL_NSECTORS 64 /* # of sectors */ 124#define DFL_NSECTORS 64 /* # of sectors */
125#define DFL_NTRACKS 16 /* # of tracks */ 125#define DFL_NTRACKS 16 /* # of tracks */
126 126
127 127
128typedef struct { 128typedef struct {
129 u_char *buf; /* buf for directory */ 129 u_char *buf; /* buf for directory */
130 doff_t size; /* full size of buf */ 130 doff_t size; /* full size of buf */
131 doff_t cur; /* offset of current entry */ 131 doff_t cur; /* offset of current entry */
132} dirbuf_t; 132} dirbuf_t;
133 133
134 134
135static int ffs_create_image(const char *, fsinfo_t *); 135static int ffs_create_image(const char *, fsinfo_t *);
136static void ffs_dump_fsinfo(fsinfo_t *); 136static void ffs_dump_fsinfo(fsinfo_t *);
137static void ffs_dump_dirbuf(dirbuf_t *, const char *, int); 137static void ffs_dump_dirbuf(dirbuf_t *, const char *, int);
138static void ffs_make_dirbuf(dirbuf_t *, const char *, fsnode *, int); 138static void ffs_make_dirbuf(dirbuf_t *, const char *, fsnode *, int);
139static int ffs_populate_dir(const char *, fsnode *, fsinfo_t *); 139static int ffs_populate_dir(const char *, fsnode *, fsinfo_t *);
140static void ffs_size_dir(fsnode *, fsinfo_t *); 140static void ffs_size_dir(fsnode *, fsinfo_t *);
141static void ffs_validate(const char *, fsnode *, fsinfo_t *); 141static void ffs_validate(const char *, fsnode *, fsinfo_t *);
142static void ffs_write_file(union dinode *, uint32_t, void *, fsinfo_t *); 142static void ffs_write_file(union dinode *, uint32_t, void *, fsinfo_t *);
143static void ffs_write_inode(union dinode *, uint32_t, const fsinfo_t *); 143static void ffs_write_inode(union dinode *, uint32_t, const fsinfo_t *);
144static void *ffs_build_dinode1(struct ufs1_dinode *, dirbuf_t *, fsnode *, 144static void *ffs_build_dinode1(struct ufs1_dinode *, dirbuf_t *, fsnode *,
145 fsnode *, fsinfo_t *); 145 fsnode *, fsinfo_t *);
146static void *ffs_build_dinode2(struct ufs2_dinode *, dirbuf_t *, fsnode *, 146static void *ffs_build_dinode2(struct ufs2_dinode *, dirbuf_t *, fsnode *,
147 fsnode *, fsinfo_t *); 147 fsnode *, fsinfo_t *);
148 148
149 149
150 150
151int sectorsize; /* XXX: for buf.c::getblk() */ 151int sectorsize; /* XXX: for buf.c::getblk() */
152 152
153 /* publically visible functions */ 153 /* publically visible functions */
154 154
155void 155void
156ffs_prep_opts(fsinfo_t *fsopts) 156ffs_prep_opts(fsinfo_t *fsopts)
157{ 157{
158 ffs_opt_t *ffs_opts; 158 ffs_opt_t *ffs_opts;
159 159
160 if ((ffs_opts = calloc(1, sizeof(ffs_opt_t))) == NULL) 160 if ((ffs_opts = calloc(1, sizeof(ffs_opt_t))) == NULL)
161 err(1, "Allocating memory for ffs_options"); 161 err(1, "Allocating memory for ffs_options");
162 162
163 fsopts->fs_specific = ffs_opts; 163 fsopts->fs_specific = ffs_opts;
164 164
165 ffs_opts->bsize= -1; 165 ffs_opts->bsize= -1;
166 ffs_opts->fsize= -1; 166 ffs_opts->fsize= -1;
167 ffs_opts->cpg= -1; 167 ffs_opts->cpg= -1;
168 ffs_opts->density= -1; 168 ffs_opts->density= -1;
169 ffs_opts->minfree= -1; 169 ffs_opts->minfree= -1;
170 ffs_opts->optimization= -1; 170 ffs_opts->optimization= -1;
171 ffs_opts->maxcontig= -1; 171 ffs_opts->maxcontig= -1;
172 ffs_opts->maxbpg= -1; 172 ffs_opts->maxbpg= -1;
173 ffs_opts->avgfilesize= -1; 173 ffs_opts->avgfilesize= -1;
174 ffs_opts->avgfpdir= -1; 174 ffs_opts->avgfpdir= -1;
175 ffs_opts->version = 1; 175 ffs_opts->version = 1;
176} 176}
177 177
178void 178void
179ffs_cleanup_opts(fsinfo_t *fsopts) 179ffs_cleanup_opts(fsinfo_t *fsopts)
180{ 180{
181 if (fsopts->fs_specific) 181 if (fsopts->fs_specific)
182 free(fsopts->fs_specific); 182 free(fsopts->fs_specific);
183} 183}
184 184
185int 185int
186ffs_parse_opts(const char *option, fsinfo_t *fsopts) 186ffs_parse_opts(const char *option, fsinfo_t *fsopts)
187{ 187{
188 ffs_opt_t *ffs_opts = fsopts->fs_specific; 188 ffs_opt_t *ffs_opts = fsopts->fs_specific;
189 char optimization[24]; 189 char optimization[24];
190 190
191 option_t ffs_options[] = { 191 option_t ffs_options[] = {
192 { '\0', "bsize", &ffs_opts->bsize, OPT_INT32, 192 { '\0', "bsize", &ffs_opts->bsize, OPT_INT32,
193 1, INT_MAX, "block size" }, 193 1, INT_MAX, "block size" },
194 { '\0', "fsize", &ffs_opts->fsize, OPT_INT32, 194 { '\0', "fsize", &ffs_opts->fsize, OPT_INT32,
195 1, INT_MAX, "fragment size" }, 195 1, INT_MAX, "fragment size" },
196 { '\0', "density", &ffs_opts->density, OPT_INT32, 196 { '\0', "density", &ffs_opts->density, OPT_INT32,
197 1, INT_MAX, "bytes per inode" }, 197 1, INT_MAX, "bytes per inode" },
198 { '\0', "minfree", &ffs_opts->minfree, OPT_INT32, 198 { '\0', "minfree", &ffs_opts->minfree, OPT_INT32,
199 0, 99, "minfree" }, 199 0, 99, "minfree" },
200 { '\0', "maxbpf", &ffs_opts->maxbpg, OPT_INT32, 200 { '\0', "maxbpf", &ffs_opts->maxbpg, OPT_INT32,
201 1, INT_MAX, "max blocks per file in a cg" }, 201 1, INT_MAX, "max blocks per file in a cg" },
202 { '\0', "avgfilesize", &ffs_opts->avgfilesize, OPT_INT32, 202 { '\0', "avgfilesize", &ffs_opts->avgfilesize, OPT_INT32,
203 1, INT_MAX, "expected average file size" }, 203 1, INT_MAX, "expected average file size" },
204 { '\0', "avgfpdir", &ffs_opts->avgfpdir, OPT_INT32, 204 { '\0', "avgfpdir", &ffs_opts->avgfpdir, OPT_INT32,
205 1, INT_MAX, "expected # of files per directory" }, 205 1, INT_MAX, "expected # of files per directory" },
206 { '\0', "extent", &ffs_opts->maxbsize, OPT_INT32, 206 { '\0', "extent", &ffs_opts->maxbsize, OPT_INT32,
207 1, INT_MAX, "maximum # extent size" }, 207 1, INT_MAX, "maximum # extent size" },
208 { '\0', "maxbpcg", &ffs_opts->maxblkspercg, OPT_INT32, 208 { '\0', "maxbpcg", &ffs_opts->maxblkspercg, OPT_INT32,
209 1, INT_MAX, "max # of blocks per group" }, 209 1, INT_MAX, "max # of blocks per group" },
210 { '\0', "version", &ffs_opts->version, OPT_INT32, 210 { '\0', "version", &ffs_opts->version, OPT_INT32,
211 1, 2, "UFS version" }, 211 1, 2, "UFS version" },
212 { '\0', "optimization", optimization, OPT_STRARRAY, 212 { '\0', "optimization", optimization, OPT_STRARRAY,
213 1, sizeof(optimization), "Optimization (time|space)" }, 213 1, sizeof(optimization), "Optimization (time|space)" },
214 { '\0', "label", ffs_opts->label, OPT_STRARRAY, 214 { '\0', "label", ffs_opts->label, OPT_STRARRAY,
215 1, sizeof(ffs_opts->label), "UFS label" }, 215 1, sizeof(ffs_opts->label), "UFS label" },
216 { .name = NULL } 216 { .name = NULL }
217 }; 217 };
218 218
219 int rv; 219 int rv;
220 220
221 assert(option != NULL); 221 assert(option != NULL);
222 assert(fsopts != NULL); 222 assert(fsopts != NULL);
223 assert(ffs_opts != NULL); 223 assert(ffs_opts != NULL);
224 224
225 if (debug & DEBUG_FS_PARSE_OPTS) 225 if (debug & DEBUG_FS_PARSE_OPTS)
226 printf("ffs_parse_opts: got `%s'\n", option); 226 printf("ffs_parse_opts: got `%s'\n", option);
227 227
228 rv = set_option(ffs_options, option); 228 rv = set_option(ffs_options, option);
229 if (rv == -1) 229 if (rv == -1)
230 return 0; 230 return 0;
231 231
232 if (ffs_options[rv].name == NULL) 232 if (ffs_options[rv].name == NULL)
233 abort(); 233 abort();
234 234
235 if (strcmp(ffs_options[rv].name, "optimization") == 0) { 235 if (strcmp(ffs_options[rv].name, "optimization") == 0) {
236 if (strcmp(optimization, "time") == 0) { 236 if (strcmp(optimization, "time") == 0) {
237 ffs_opts->optimization = FS_OPTTIME; 237 ffs_opts->optimization = FS_OPTTIME;
238 } else if (strcmp(optimization, "space") == 0) { 238 } else if (strcmp(optimization, "space") == 0) {
239 ffs_opts->optimization = FS_OPTSPACE; 239 ffs_opts->optimization = FS_OPTSPACE;
240 } else { 240 } else {
241 warnx("Invalid optimization `%s'", optimization); 241 warnx("Invalid optimization `%s'", optimization);
242 return 0; 242 return 0;
243 } 243 }
244 } 244 }
245 return 1; 245 return 1;
246} 246}
247 247
248 248
249void 249void
250ffs_makefs(const char *image, const char *dir, fsnode *root, fsinfo_t *fsopts) 250ffs_makefs(const char *image, const char *dir, fsnode *root, fsinfo_t *fsopts)
251{ 251{
252 struct fs *superblock; 252 struct fs *superblock;
253 struct timeval start; 253 struct timeval start;
254 254
255 assert(image != NULL); 255 assert(image != NULL);
256 assert(dir != NULL); 256 assert(dir != NULL);
257 assert(root != NULL); 257 assert(root != NULL);
258 assert(fsopts != NULL); 258 assert(fsopts != NULL);
259 259
260 if (debug & DEBUG_FS_MAKEFS) 260 if (debug & DEBUG_FS_MAKEFS)
261 printf("ffs_makefs: image %s directory %s root %p\n", 261 printf("ffs_makefs: image %s directory %s root %p\n",
262 image, dir, root); 262 image, dir, root);
263 263
264 /* validate tree and options */ 264 /* validate tree and options */
265 TIMER_START(start); 265 TIMER_START(start);
266 ffs_validate(dir, root, fsopts); 266 ffs_validate(dir, root, fsopts);
267 TIMER_RESULTS(start, "ffs_validate"); 267 TIMER_RESULTS(start, "ffs_validate");
268 268
269 printf("Calculated size of `%s': %lld bytes, %lld inodes\n", 269 printf("Calculated size of `%s': %lld bytes, %lld inodes\n",
270 image, (long long)fsopts->size, (long long)fsopts->inodes); 270 image, (long long)fsopts->size, (long long)fsopts->inodes);
271 271
272 /* create image */ 272 /* create image */
273 TIMER_START(start); 273 TIMER_START(start);
274 if (ffs_create_image(image, fsopts) == -1) 274 if (ffs_create_image(image, fsopts) == -1)
275 errx(1, "Image file `%s' not created.", image); 275 errx(1, "Image file `%s' not created.", image);
276 TIMER_RESULTS(start, "ffs_create_image"); 276 TIMER_RESULTS(start, "ffs_create_image");
277 277
278 fsopts->curinode = UFS_ROOTINO; 278 fsopts->curinode = UFS_ROOTINO;
279 279
280 if (debug & DEBUG_FS_MAKEFS) 280 if (debug & DEBUG_FS_MAKEFS)
281 putchar('\n'); 281 putchar('\n');
282 282
283 /* populate image */ 283 /* populate image */
284 printf("Populating `%s'\n", image); 284 printf("Populating `%s'\n", image);
285 TIMER_START(start); 285 TIMER_START(start);
286 if (! ffs_populate_dir(dir, root, fsopts)) 286 if (! ffs_populate_dir(dir, root, fsopts))
287 errx(1, "Image file `%s' not populated.", image); 287 errx(1, "Image file `%s' not populated.", image);
288 TIMER_RESULTS(start, "ffs_populate_dir"); 288 TIMER_RESULTS(start, "ffs_populate_dir");
289 289
290 /* ensure no outstanding buffers remain */ 290 /* ensure no outstanding buffers remain */
291 if (debug & DEBUG_FS_MAKEFS) 291 if (debug & DEBUG_FS_MAKEFS)
292 bcleanup(); 292 bcleanup();
293 293
294 /* update various superblock parameters */ 294 /* update various superblock parameters */
295 superblock = fsopts->superblock; 295 superblock = fsopts->superblock;
296 superblock->fs_fmod = 0; 296 superblock->fs_fmod = 0;
297 superblock->fs_old_cstotal.cs_ndir = superblock->fs_cstotal.cs_ndir; 297 superblock->fs_old_cstotal.cs_ndir = superblock->fs_cstotal.cs_ndir;
298 superblock->fs_old_cstotal.cs_nbfree = superblock->fs_cstotal.cs_nbfree; 298 superblock->fs_old_cstotal.cs_nbfree = superblock->fs_cstotal.cs_nbfree;
299 superblock->fs_old_cstotal.cs_nifree = superblock->fs_cstotal.cs_nifree; 299 superblock->fs_old_cstotal.cs_nifree = superblock->fs_cstotal.cs_nifree;
300 superblock->fs_old_cstotal.cs_nffree = superblock->fs_cstotal.cs_nffree; 300 superblock->fs_old_cstotal.cs_nffree = superblock->fs_cstotal.cs_nffree;
301 301
302 /* write out superblock; image is now complete */ 302 /* write out superblock; image is now complete */
303 ffs_write_superblock(fsopts->superblock, fsopts); 303 ffs_write_superblock(fsopts->superblock, fsopts);
304 if (close(fsopts->fd) == -1) 304 if (close(fsopts->fd) == -1)
305 err(1, "Closing `%s'", image); 305 err(1, "Closing `%s'", image);
306 fsopts->fd = -1; 306 fsopts->fd = -1;
307 printf("Image `%s' complete\n", image); 307 printf("Image `%s' complete\n", image);
308} 308}
309 309
310 /* end of public functions */ 310 /* end of public functions */
311 311
312 312
313static void 313static void
314ffs_validate(const char *dir, fsnode *root, fsinfo_t *fsopts) 314ffs_validate(const char *dir, fsnode *root, fsinfo_t *fsopts)
315{ 315{
316 int32_t ncg = 1; 316 int32_t ncg = 1;
317#if notyet 317#if notyet
318 int32_t spc, nspf, ncyl, fssize; 318 int32_t spc, nspf, ncyl, fssize;
319#endif 319#endif
320 ffs_opt_t *ffs_opts = fsopts->fs_specific; 320 ffs_opt_t *ffs_opts = fsopts->fs_specific;
321 321
322 assert(dir != NULL); 322 assert(dir != NULL);
323 assert(root != NULL); 323 assert(root != NULL);
324 assert(fsopts != NULL); 324 assert(fsopts != NULL);
325 assert(ffs_opts != NULL); 325 assert(ffs_opts != NULL);
326 326
327 if (debug & DEBUG_FS_VALIDATE) { 327 if (debug & DEBUG_FS_VALIDATE) {
328 printf("ffs_validate: before defaults set:\n"); 328 printf("ffs_validate: before defaults set:\n");
329 ffs_dump_fsinfo(fsopts); 329 ffs_dump_fsinfo(fsopts);
330 } 330 }
331 331
332 /* set FFS defaults */ 332 /* set FFS defaults */
333 if (fsopts->sectorsize == -1) 333 if (fsopts->sectorsize == -1)
334 fsopts->sectorsize = DFL_SECSIZE; 334 fsopts->sectorsize = DFL_SECSIZE;
335 if (ffs_opts->fsize == -1) 335 if (ffs_opts->fsize == -1)
336 ffs_opts->fsize = MAX(DFL_FRAGSIZE, fsopts->sectorsize); 336 ffs_opts->fsize = MAX(DFL_FRAGSIZE, fsopts->sectorsize);
337 if (ffs_opts->bsize == -1) 337 if (ffs_opts->bsize == -1)
338 ffs_opts->bsize = MIN(DFL_BLKSIZE, 8 * ffs_opts->fsize); 338 ffs_opts->bsize = MIN(DFL_BLKSIZE, 8 * ffs_opts->fsize);
339 if (ffs_opts->cpg == -1) 339 if (ffs_opts->cpg == -1)
340 ffs_opts->cpg = DFL_CYLSPERGROUP; 340 ffs_opts->cpg = DFL_CYLSPERGROUP;
341 else 341 else
342 ffs_opts->cpgflg = 1; 342 ffs_opts->cpgflg = 1;
343 /* fsopts->density is set below */ 343 /* fsopts->density is set below */
344 if (ffs_opts->nsectors == -1) 344 if (ffs_opts->nsectors == -1)
345 ffs_opts->nsectors = DFL_NSECTORS; 345 ffs_opts->nsectors = DFL_NSECTORS;
346 if (ffs_opts->minfree == -1) 346 if (ffs_opts->minfree == -1)
347 ffs_opts->minfree = MINFREE; 347 ffs_opts->minfree = MINFREE;
348 if (ffs_opts->optimization == -1) 348 if (ffs_opts->optimization == -1)
349 ffs_opts->optimization = DEFAULTOPT; 349 ffs_opts->optimization = DEFAULTOPT;
350 if (ffs_opts->maxcontig == -1) 350 if (ffs_opts->maxcontig == -1)
351 ffs_opts->maxcontig = 351 ffs_opts->maxcontig =
352 MAX(1, MIN(MAXPHYS, FFS_MAXBSIZE) / ffs_opts->bsize); 352 MAX(1, MIN(MAXPHYS, FFS_MAXBSIZE) / ffs_opts->bsize);
353 /* XXX ondisk32 */ 353 /* XXX ondisk32 */
354 if (ffs_opts->maxbpg == -1) 354 if (ffs_opts->maxbpg == -1)
355 ffs_opts->maxbpg = ffs_opts->bsize / sizeof(int32_t); 355 ffs_opts->maxbpg = ffs_opts->bsize / sizeof(int32_t);
356 if (ffs_opts->avgfilesize == -1) 356 if (ffs_opts->avgfilesize == -1)
357 ffs_opts->avgfilesize = AVFILESIZ; 357 ffs_opts->avgfilesize = AVFILESIZ;
358 if (ffs_opts->avgfpdir == -1) 358 if (ffs_opts->avgfpdir == -1)
359 ffs_opts->avgfpdir = AFPDIR; 359 ffs_opts->avgfpdir = AFPDIR;
360 360
361 /* calculate size of tree */ 361 /* calculate size of tree */
362 ffs_size_dir(root, fsopts); 362 ffs_size_dir(root, fsopts);
363 fsopts->inodes += UFS_ROOTINO; /* include first two inodes */ 363 fsopts->inodes += UFS_ROOTINO; /* include first two inodes */
364 364
365 if (debug & DEBUG_FS_VALIDATE) 365 if (debug & DEBUG_FS_VALIDATE)
366 printf("ffs_validate: size of tree: %lld bytes, %lld inodes\n", 366 printf("ffs_validate: size of tree: %lld bytes, %lld inodes\n",
367 (long long)fsopts->size, (long long)fsopts->inodes); 367 (long long)fsopts->size, (long long)fsopts->inodes);
368 368
369 /* add requested slop */ 369 /* add requested slop */
370 fsopts->size += fsopts->freeblocks; 370 fsopts->size += fsopts->freeblocks;
371 fsopts->inodes += fsopts->freefiles; 371 fsopts->inodes += fsopts->freefiles;
372 if (fsopts->freefilepc > 0) 372 if (fsopts->freefilepc > 0)
373 fsopts->inodes = 373 fsopts->inodes =
374 fsopts->inodes * (100 + fsopts->freefilepc) / 100; 374 fsopts->inodes * (100 + fsopts->freefilepc) / 100;
375 if (fsopts->freeblockpc > 0) 375 if (fsopts->freeblockpc > 0)
376 fsopts->size = 376 fsopts->size =
377 fsopts->size * (100 + fsopts->freeblockpc) / 100; 377 fsopts->size * (100 + fsopts->freeblockpc) / 100;
378 378
379 /* add space needed for superblocks */ 379 /* add space needed for superblocks */
380 /* 380 /*
381 * The old SBOFF (SBLOCK_UFS1) is used here because makefs is 381 * The old SBOFF (SBLOCK_UFS1) is used here because makefs is
382 * typically used for small filesystems where space matters. 382 * typically used for small filesystems where space matters.
383 * XXX make this an option. 383 * XXX make this an option.
384 */ 384 */
385 fsopts->size += (SBLOCK_UFS1 + SBLOCKSIZE) * ncg; 385 fsopts->size += (SBLOCK_UFS1 + SBLOCKSIZE) * ncg;
386 /* add space needed to store inodes, x3 for blockmaps, etc */ 386 /* add space needed to store inodes, x3 for blockmaps, etc */
387 if (ffs_opts->version == 1) 387 if (ffs_opts->version == 1)
388 fsopts->size += ncg * DINODE1_SIZE * 388 fsopts->size += ncg * DINODE1_SIZE *
389 roundup(fsopts->inodes / ncg,  389 roundup(fsopts->inodes / ncg,
390 ffs_opts->bsize / DINODE1_SIZE); 390 ffs_opts->bsize / DINODE1_SIZE);
391 else 391 else
392 fsopts->size += ncg * DINODE2_SIZE * 392 fsopts->size += ncg * DINODE2_SIZE *
393 roundup(fsopts->inodes / ncg,  393 roundup(fsopts->inodes / ncg,
394 ffs_opts->bsize / DINODE2_SIZE); 394 ffs_opts->bsize / DINODE2_SIZE);
395 395
396 /* add minfree */ 396 /* add minfree */
397 if (ffs_opts->minfree > 0) 397 if (ffs_opts->minfree > 0)
398 fsopts->size = 398 fsopts->size =
399 fsopts->size * (100 + ffs_opts->minfree) / 100; 399 fsopts->size * (100 + ffs_opts->minfree) / 100;
400 /* 400 /*
401 * XXX any other fs slop to add, such as csum's, bitmaps, etc ?? 401 * XXX any other fs slop to add, such as csum's, bitmaps, etc ??
402 */ 402 */
403 403
404 if (fsopts->size < fsopts->minsize) /* ensure meets minimum size */ 404 if (fsopts->size < fsopts->minsize) /* ensure meets minimum size */
405 fsopts->size = fsopts->minsize; 405 fsopts->size = fsopts->minsize;
406 406
407 /* round up to the next block */ 407 /* round up to the next block */
408 fsopts->size = roundup(fsopts->size, ffs_opts->bsize); 408 fsopts->size = roundup(fsopts->size, ffs_opts->bsize);
409 409
410 /* calculate density if necessary */ 410 /* calculate density if necessary */
411 if (ffs_opts->density == -1) 411 if (ffs_opts->density == -1)
412 ffs_opts->density = fsopts->size / fsopts->inodes + 1; 412 ffs_opts->density = fsopts->size / fsopts->inodes + 1;
413 413
414 if (debug & DEBUG_FS_VALIDATE) { 414 if (debug & DEBUG_FS_VALIDATE) {
415 printf("ffs_validate: after defaults set:\n"); 415 printf("ffs_validate: after defaults set:\n");
416 ffs_dump_fsinfo(fsopts); 416 ffs_dump_fsinfo(fsopts);
417 printf("ffs_validate: dir %s; %lld bytes, %lld inodes\n", 417 printf("ffs_validate: dir %s; %lld bytes, %lld inodes\n",
418 dir, (long long)fsopts->size, (long long)fsopts->inodes); 418 dir, (long long)fsopts->size, (long long)fsopts->inodes);
419 } 419 }
420 sectorsize = fsopts->sectorsize; /* XXX - see earlier */ 420 sectorsize = fsopts->sectorsize; /* XXX - see earlier */
421 421
422 /* now check calculated sizes vs requested sizes */ 422 /* now check calculated sizes vs requested sizes */
423 if (fsopts->maxsize > 0 && fsopts->size > fsopts->maxsize) { 423 if (fsopts->maxsize > 0 && fsopts->size > fsopts->maxsize) {
424 errx(1, "`%s' size of %lld is larger than the maxsize of %lld.", 424 errx(1, "`%s' size of %lld is larger than the maxsize of %lld.",
425 dir, (long long)fsopts->size, (long long)fsopts->maxsize); 425 dir, (long long)fsopts->size, (long long)fsopts->maxsize);
426 } 426 }
427} 427}
428 428
429 429
430static void 430static void
431ffs_dump_fsinfo(fsinfo_t *f) 431ffs_dump_fsinfo(fsinfo_t *f)
432{ 432{
433 433
434 ffs_opt_t *fs = f->fs_specific; 434 ffs_opt_t *fs = f->fs_specific;
435 435
436 printf("fsopts at %p\n", f); 436 printf("fsopts at %p\n", f);
437 437
438 printf("\tsize %lld, inodes %lld, curinode %u\n", 438 printf("\tsize %lld, inodes %lld, curinode %u\n",
439 (long long)f->size, (long long)f->inodes, f->curinode); 439 (long long)f->size, (long long)f->inodes, f->curinode);
440 440
441 printf("\tminsize %lld, maxsize %lld\n", 441 printf("\tminsize %lld, maxsize %lld\n",
442 (long long)f->minsize, (long long)f->maxsize); 442 (long long)f->minsize, (long long)f->maxsize);
443 printf("\tfree files %lld, freefile %% %d\n", 443 printf("\tfree files %lld, freefile %% %d\n",
444 (long long)f->freefiles, f->freefilepc); 444 (long long)f->freefiles, f->freefilepc);
445 printf("\tfree blocks %lld, freeblock %% %d\n", 445 printf("\tfree blocks %lld, freeblock %% %d\n",
446 (long long)f->freeblocks, f->freeblockpc); 446 (long long)f->freeblocks, f->freeblockpc);
447 printf("\tneedswap %d, sectorsize %d\n", f->needswap, f->sectorsize); 447 printf("\tneedswap %d, sectorsize %d\n", f->needswap, f->sectorsize);
448 448
449 printf("\tbsize %d, fsize %d, cpg %d, density %d\n", 449 printf("\tbsize %d, fsize %d, cpg %d, density %d\n",
450 fs->bsize, fs->fsize, fs->cpg, fs->density); 450 fs->bsize, fs->fsize, fs->cpg, fs->density);
451 printf("\tnsectors %d, rpm %d, minfree %d\n", 451 printf("\tnsectors %d, rpm %d, minfree %d\n",
452 fs->nsectors, fs->rpm, fs->minfree); 452 fs->nsectors, fs->rpm, fs->minfree);
453 printf("\tmaxcontig %d, maxbpg %d\n", 453 printf("\tmaxcontig %d, maxbpg %d\n",
454 fs->maxcontig, fs->maxbpg); 454 fs->maxcontig, fs->maxbpg);
455 printf("\toptimization %s\n", 455 printf("\toptimization %s\n",
456 fs->optimization == FS_OPTSPACE ? "space" : "time"); 456 fs->optimization == FS_OPTSPACE ? "space" : "time");
457} 457}
458 458
459 459
460static int 460static int
461ffs_create_image(const char *image, fsinfo_t *fsopts) 461ffs_create_image(const char *image, fsinfo_t *fsopts)
462{ 462{
463#if HAVE_STRUCT_STATVFS_F_IOSIZE && HAVE_FSTATVFS 463#if HAVE_STRUCT_STATVFS_F_IOSIZE && HAVE_FSTATVFS
464 struct statvfs sfs; 464 struct statvfs sfs;
465#endif 465#endif
466 struct fs *fs; 466 struct fs *fs;
467 char *buf; 467 char *buf;
468 int i, bufsize; 468 int i, bufsize;
469 off_t bufrem; 469 off_t bufrem;
470 470
471 assert (image != NULL); 471 assert (image != NULL);
472 assert (fsopts != NULL); 472 assert (fsopts != NULL);
473 473
474 /* create image */ 474 /* create image */
475 if ((fsopts->fd = open(image, O_RDWR | O_CREAT | O_TRUNC, 0666)) 475 if ((fsopts->fd = open(image, O_RDWR | O_CREAT | O_TRUNC, 0666))
476 == -1) { 476 == -1) {
477 warn("Can't open `%s' for writing", image); 477 warn("Can't open `%s' for writing", image);
478 return (-1); 478 return (-1);
479 } 479 }
480 480
481 /* zero image */ 481 /* zero image */
482#if HAVE_STRUCT_STATVFS_F_IOSIZE && HAVE_FSTATVFS 482#if HAVE_STRUCT_STATVFS_F_IOSIZE && HAVE_FSTATVFS
483 if (fstatvfs(fsopts->fd, &sfs) == -1) { 483 if (fstatvfs(fsopts->fd, &sfs) == -1) {
484#endif 484#endif
485 bufsize = 8192; 485 bufsize = 8192;
486#if HAVE_STRUCT_STATVFS_F_IOSIZE && HAVE_FSTATVFS 486#if HAVE_STRUCT_STATVFS_F_IOSIZE && HAVE_FSTATVFS
487 warn("can't fstatvfs `%s', using default %d byte chunk", 487 warn("can't fstatvfs `%s', using default %d byte chunk",
488 image, bufsize); 488 image, bufsize);
489 } else 489 } else
490 bufsize = sfs.f_iosize; 490 bufsize = sfs.f_iosize;
491#endif 491#endif
492 bufrem = fsopts->size; 492 bufrem = fsopts->size;
493 493
494 if (fsopts->sparse) { 494 if (fsopts->sparse) {
495 if (ftruncate(fsopts->fd, bufrem) == -1) { 495 if (ftruncate(fsopts->fd, bufrem) == -1) {
496 printf ("ERROR in truncate. Sparse option disabled\n"); 496 printf ("ERROR in truncate. Sparse option disabled\n");
497 fsopts->sparse = 0; 497 fsopts->sparse = 0;
498 } else { 498 } else {
499 bufrem = 0; /* File truncated at bufrem. Remaining is 0 */ 499 bufrem = 0; /* File truncated at bufrem. Remaining is 0 */
500 buf = NULL; 500 buf = NULL;
501 } 501 }
502 } 502 }
503 503
504 if ((debug & DEBUG_FS_CREATE_IMAGE) && fsopts->sparse == 0) 504 if ((debug & DEBUG_FS_CREATE_IMAGE) && fsopts->sparse == 0)
505 printf( 505 printf(
506 "zero-ing image `%s', %lld sectors, using %d byte chunks\n", 506 "zero-ing image `%s', %lld sectors, using %d byte chunks\n",
507 image, (long long)bufrem, bufsize); 507 image, (long long)bufrem, bufsize);
508 if ((bufrem > 0) && ((buf = calloc(1, bufsize)) == NULL)) { 508 if ((bufrem > 0) && ((buf = calloc(1, bufsize)) == NULL)) {
509 warn("Can't create buffer for sector"); 509 warn("Can't create buffer for sector");
510 return (-1); 510 return (-1);
511 } 511 }
512 while (bufrem > 0) { 512 while (bufrem > 0) {
513 i = write(fsopts->fd, buf, MIN(bufsize, bufrem)); 513 i = write(fsopts->fd, buf, MIN(bufsize, bufrem));
514 if (i == -1) { 514 if (i == -1) {
515 warn("zeroing image, %lld bytes to go", 515 warn("zeroing image, %lld bytes to go",
516 (long long)bufrem); 516 (long long)bufrem);
517 free(buf); 517 free(buf);
518 return (-1); 518 return (-1);
519 } 519 }
520 bufrem -= i; 520 bufrem -= i;
521 } 521 }
522 if (buf) 522 if (buf)
523 free(buf); 523 free(buf);
524 524
525 /* make the file system */ 525 /* make the file system */
526 if (debug & DEBUG_FS_CREATE_IMAGE) 526 if (debug & DEBUG_FS_CREATE_IMAGE)
527 printf("calling mkfs(\"%s\", ...)\n", image); 527 printf("calling mkfs(\"%s\", ...)\n", image);
528 fs = ffs_mkfs(image, fsopts); 528 fs = ffs_mkfs(image, fsopts);
529 fsopts->superblock = (void *)fs; 529 fsopts->superblock = (void *)fs;
530 if (debug & DEBUG_FS_CREATE_IMAGE) { 530 if (debug & DEBUG_FS_CREATE_IMAGE) {
531 time_t t; 531 time_t t;
532 532
533 t = (time_t)((struct fs *)fsopts->superblock)->fs_time; 533 t = (time_t)((struct fs *)fsopts->superblock)->fs_time;
534 printf("mkfs returned %p; fs_time %s", 534 printf("mkfs returned %p; fs_time %s",
535 fsopts->superblock, ctime(&t)); 535 fsopts->superblock, ctime(&t));
536 printf("fs totals: nbfree %lld, nffree %lld, nifree %lld, ndir %lld\n", 536 printf("fs totals: nbfree %lld, nffree %lld, nifree %lld, ndir %lld\n",
537 (long long)fs->fs_cstotal.cs_nbfree, 537 (long long)fs->fs_cstotal.cs_nbfree,
538 (long long)fs->fs_cstotal.cs_nffree, 538 (long long)fs->fs_cstotal.cs_nffree,
539 (long long)fs->fs_cstotal.cs_nifree, 539 (long long)fs->fs_cstotal.cs_nifree,
540 (long long)fs->fs_cstotal.cs_ndir); 540 (long long)fs->fs_cstotal.cs_ndir);
541 } 541 }
542 542
543 if ((off_t)(fs->fs_cstotal.cs_nifree + UFS_ROOTINO) < fsopts->inodes) { 543 if ((off_t)(fs->fs_cstotal.cs_nifree + UFS_ROOTINO) < fsopts->inodes) {
544 warnx( 544 warnx(
545 "Image file `%s' has %lld free inodes; %lld are required.", 545 "Image file `%s' has %lld free inodes; %lld are required.",
546 image, 546 image,
547 (long long)(fs->fs_cstotal.cs_nifree + UFS_ROOTINO), 547 (long long)(fs->fs_cstotal.cs_nifree + UFS_ROOTINO),
548 (long long)fsopts->inodes); 548 (long long)fsopts->inodes);
549 return (-1); 549 return (-1);
550 } 550 }
551 return (fsopts->fd); 551 return (fsopts->fd);
552} 552}
553 553
554 554
555static void 555static void
556ffs_size_dir(fsnode *root, fsinfo_t *fsopts) 556ffs_size_dir(fsnode *root, fsinfo_t *fsopts)
557{ 557{
558 struct direct tmpdir; 558 struct direct tmpdir;
559 fsnode * node; 559 fsnode * node;
560 int curdirsize, this; 560 int curdirsize, this;
561 ffs_opt_t *ffs_opts = fsopts->fs_specific; 561 ffs_opt_t *ffs_opts = fsopts->fs_specific;
562 562
563 /* node may be NULL (empty directory) */ 563 /* node may be NULL (empty directory) */
564 assert(fsopts != NULL); 564 assert(fsopts != NULL);
565 assert(ffs_opts != NULL); 565 assert(ffs_opts != NULL);
566 566
567 if (debug & DEBUG_FS_SIZE_DIR) 567 if (debug & DEBUG_FS_SIZE_DIR)
568 printf("ffs_size_dir: entry: bytes %lld inodes %lld\n", 568 printf("ffs_size_dir: entry: bytes %lld inodes %lld\n",
569 (long long)fsopts->size, (long long)fsopts->inodes); 569 (long long)fsopts->size, (long long)fsopts->inodes);
570 570
571#define ADDDIRENT(e) do { \ 571#define ADDDIRENT(e) do { \
572 tmpdir.d_namlen = strlen((e)); \ 572 tmpdir.d_namlen = strlen((e)); \
573 this = DIRSIZ(0, &tmpdir, 0); \ 573 this = DIRSIZ(0, &tmpdir, 0); \
574 if (debug & DEBUG_FS_SIZE_DIR_ADD_DIRENT) \ 574 if (debug & DEBUG_FS_SIZE_DIR_ADD_DIRENT) \
575 printf("ADDDIRENT: was: %s (%d) this %d cur %d\n", \ 575 printf("ADDDIRENT: was: %s (%d) this %d cur %d\n", \
576 e, tmpdir.d_namlen, this, curdirsize); \ 576 e, tmpdir.d_namlen, this, curdirsize); \
577 if (this + curdirsize > roundup(curdirsize, DIRBLKSIZ)) \ 577 if (this + curdirsize > roundup(curdirsize, DIRBLKSIZ)) \
578 curdirsize = roundup(curdirsize, DIRBLKSIZ); \ 578 curdirsize = roundup(curdirsize, DIRBLKSIZ); \
579 curdirsize += this; \ 579 curdirsize += this; \
580 if (debug & DEBUG_FS_SIZE_DIR_ADD_DIRENT) \ 580 if (debug & DEBUG_FS_SIZE_DIR_ADD_DIRENT) \
581 printf("ADDDIRENT: now: %s (%d) this %d cur %d\n", \ 581 printf("ADDDIRENT: now: %s (%d) this %d cur %d\n", \
582 e, tmpdir.d_namlen, this, curdirsize); \ 582 e, tmpdir.d_namlen, this, curdirsize); \
583} while (0); 583} while (0);
584 584
585 /* 585 /*
586 * XXX this needs to take into account extra space consumed 586 * XXX this needs to take into account extra space consumed
587 * by indirect blocks, etc. 587 * by indirect blocks, etc.
588 */ 588 */
589#define ADDSIZE(x) do { \ 589#define ADDSIZE(x) do { \
590 fsopts->size += roundup((x), ffs_opts->fsize); \ 590 fsopts->size += roundup((x), ffs_opts->fsize); \
591} while (0); 591} while (0);
592 592
593 curdirsize = 0; 593 curdirsize = 0;
594 for (node = root; node != NULL; node = node->next) { 594 for (node = root; node != NULL; node = node->next) {
595 ADDDIRENT(node->name); 595 ADDDIRENT(node->name);
596 if (node == root) { /* we're at "." */ 596 if (node == root) { /* we're at "." */
597 assert(strcmp(node->name, ".") == 0); 597 assert(strcmp(node->name, ".") == 0);
598 ADDDIRENT(".."); 598 ADDDIRENT("..");
599 } else if ((node->inode->flags & FI_SIZED) == 0) { 599 } else if ((node->inode->flags & FI_SIZED) == 0) {
600 /* don't count duplicate names */ 600 /* don't count duplicate names */
601 node->inode->flags |= FI_SIZED; 601 node->inode->flags |= FI_SIZED;
602 if (debug & DEBUG_FS_SIZE_DIR_NODE) 602 if (debug & DEBUG_FS_SIZE_DIR_NODE)
603 printf("ffs_size_dir: `%s' size %lld\n", 603 printf("ffs_size_dir: `%s' size %lld\n",
604 node->name, 604 node->name,
605 (long long)node->inode->st.st_size); 605 (long long)node->inode->st.st_size);
606 fsopts->inodes++; 606 fsopts->inodes++;
607 if (node->type == S_IFREG) 607 if (node->type == S_IFREG)
608 ADDSIZE(node->inode->st.st_size); 608 ADDSIZE(node->inode->st.st_size);
609 if (node->type == S_IFLNK) { 609 if (node->type == S_IFLNK) {
610 size_t slen; 610 size_t slen;
611 611
612 slen = strlen(node->symlink) + 1; 612 slen = strlen(node->symlink) + 1;
613 if (slen >= (ffs_opts->version == 1 ? 613 if (slen >= (ffs_opts->version == 1 ?
614 UFS1_MAXSYMLINKLEN : 614 UFS1_MAXSYMLINKLEN :
615 UFS2_MAXSYMLINKLEN)) 615 UFS2_MAXSYMLINKLEN))
616 ADDSIZE(slen); 616 ADDSIZE(slen);
617 } 617 }
618 } 618 }
619 if (node->type == S_IFDIR) 619 if (node->type == S_IFDIR)
620 ffs_size_dir(node->child, fsopts); 620 ffs_size_dir(node->child, fsopts);
621 } 621 }
622 ADDSIZE(curdirsize); 622 ADDSIZE(curdirsize);
623 623
624 if (debug & DEBUG_FS_SIZE_DIR) 624 if (debug & DEBUG_FS_SIZE_DIR)
625 printf("ffs_size_dir: exit: size %lld inodes %lld\n", 625 printf("ffs_size_dir: exit: size %lld inodes %lld\n",
626 (long long)fsopts->size, (long long)fsopts->inodes); 626 (long long)fsopts->size, (long long)fsopts->inodes);
627} 627}
628 628
629static void * 629static void *
630ffs_build_dinode1(struct ufs1_dinode *dinp, dirbuf_t *dbufp, fsnode *cur, 630ffs_build_dinode1(struct ufs1_dinode *dinp, dirbuf_t *dbufp, fsnode *cur,
631 fsnode *root, fsinfo_t *fsopts) 631 fsnode *root, fsinfo_t *fsopts)
632{ 632{
633 size_t slen; 633 size_t slen;
634 void *membuf; 634 void *membuf;
635 635
636 memset(dinp, 0, sizeof(*dinp)); 636 memset(dinp, 0, sizeof(*dinp));
637 dinp->di_mode = cur->inode->st.st_mode; 637 dinp->di_mode = cur->inode->st.st_mode;
638 dinp->di_nlink = cur->inode->nlink; 638 dinp->di_nlink = cur->inode->nlink;
639 dinp->di_size = cur->inode->st.st_size; 639 dinp->di_size = cur->inode->st.st_size;
640 dinp->di_atime = cur->inode->st.st_atime; 640 dinp->di_atime = cur->inode->st.st_atime;
641 dinp->di_mtime = cur->inode->st.st_mtime; 641 dinp->di_mtime = cur->inode->st.st_mtime;
642 dinp->di_ctime = cur->inode->st.st_ctime; 642 dinp->di_ctime = cur->inode->st.st_ctime;
643#if HAVE_STRUCT_STAT_ST_MTIMENSEC 643#if HAVE_STRUCT_STAT_ST_MTIMENSEC
644 dinp->di_atimensec = cur->inode->st.st_atimensec; 644 dinp->di_atimensec = cur->inode->st.st_atimensec;
645 dinp->di_mtimensec = cur->inode->st.st_mtimensec; 645 dinp->di_mtimensec = cur->inode->st.st_mtimensec;
646 dinp->di_ctimensec = cur->inode->st.st_ctimensec; 646 dinp->di_ctimensec = cur->inode->st.st_ctimensec;
647#endif 647#endif
648#if HAVE_STRUCT_STAT_ST_FLAGS 648#if HAVE_STRUCT_STAT_ST_FLAGS
649 dinp->di_flags = cur->inode->st.st_flags; 649 dinp->di_flags = cur->inode->st.st_flags;
650#endif 650#endif
651#if HAVE_STRUCT_STAT_ST_GEN 651#if HAVE_STRUCT_STAT_ST_GEN
652 dinp->di_gen = cur->inode->st.st_gen; 652 dinp->di_gen = cur->inode->st.st_gen;
653#endif 653#endif
654 dinp->di_uid = cur->inode->st.st_uid; 654 dinp->di_uid = cur->inode->st.st_uid;
655 dinp->di_gid = cur->inode->st.st_gid; 655 dinp->di_gid = cur->inode->st.st_gid;
656 /* not set: di_db, di_ib, di_blocks, di_spare */ 656 /* not set: di_db, di_ib, di_blocks, di_spare */
657 657
658 membuf = NULL; 658 membuf = NULL;
659 if (cur == root) { /* "."; write dirbuf */ 659 if (cur == root) { /* "."; write dirbuf */
660 membuf = dbufp->buf; 660 membuf = dbufp->buf;
661 dinp->di_size = dbufp->size; 661 dinp->di_size = dbufp->size;
662 } else if (S_ISBLK(cur->type) || S_ISCHR(cur->type)) { 662 } else if (S_ISBLK(cur->type) || S_ISCHR(cur->type)) {
663 dinp->di_size = 0; /* a device */ 663 dinp->di_size = 0; /* a device */
664 dinp->di_rdev = 664 dinp->di_rdev =
665 ufs_rw32(cur->inode->st.st_rdev, fsopts->needswap); 665 ufs_rw32(cur->inode->st.st_rdev, fsopts->needswap);
666 } else if (S_ISLNK(cur->type)) { /* symlink */ 666 } else if (S_ISLNK(cur->type)) { /* symlink */
667 slen = strlen(cur->symlink); 667 slen = strlen(cur->symlink);
668 if (slen < UFS1_MAXSYMLINKLEN) { /* short link */ 668 if (slen < UFS1_MAXSYMLINKLEN) { /* short link */
669 memcpy(dinp->di_db, cur->symlink, slen); 669 memcpy(dinp->di_db, cur->symlink, slen);
670 } else 670 } else
671 membuf = cur->symlink; 671 membuf = cur->symlink;
672 dinp->di_size = slen; 672 dinp->di_size = slen;
673 } 673 }
674 return membuf; 674 return membuf;
675} 675}
676 676
677static void * 677static void *
678ffs_build_dinode2(struct ufs2_dinode *dinp, dirbuf_t *dbufp, fsnode *cur, 678ffs_build_dinode2(struct ufs2_dinode *dinp, dirbuf_t *dbufp, fsnode *cur,
679 fsnode *root, fsinfo_t *fsopts) 679 fsnode *root, fsinfo_t *fsopts)
680{ 680{
681 size_t slen; 681 size_t slen;
682 void *membuf; 682 void *membuf;
683 683
684 memset(dinp, 0, sizeof(*dinp)); 684 memset(dinp, 0, sizeof(*dinp));
685 dinp->di_mode = cur->inode->st.st_mode; 685 dinp->di_mode = cur->inode->st.st_mode;
686 dinp->di_nlink = cur->inode->nlink; 686 dinp->di_nlink = cur->inode->nlink;
687 dinp->di_size = cur->inode->st.st_size; 687 dinp->di_size = cur->inode->st.st_size;
688 dinp->di_atime = cur->inode->st.st_atime; 688 dinp->di_atime = cur->inode->st.st_atime;
689 dinp->di_mtime = cur->inode->st.st_mtime; 689 dinp->di_mtime = cur->inode->st.st_mtime;
690 dinp->di_ctime = cur->inode->st.st_ctime; 690 dinp->di_ctime = cur->inode->st.st_ctime;
691#if HAVE_STRUCT_STAT_ST_MTIMENSEC 691#if HAVE_STRUCT_STAT_ST_MTIMENSEC
692 dinp->di_atimensec = cur->inode->st.st_atimensec; 692 dinp->di_atimensec = cur->inode->st.st_atimensec;
693 dinp->di_mtimensec = cur->inode->st.st_mtimensec; 693 dinp->di_mtimensec = cur->inode->st.st_mtimensec;
694 dinp->di_ctimensec = cur->inode->st.st_ctimensec; 694 dinp->di_ctimensec = cur->inode->st.st_ctimensec;
695#endif 695#endif
696#if HAVE_STRUCT_STAT_ST_FLAGS 696#if HAVE_STRUCT_STAT_ST_FLAGS
697 dinp->di_flags = cur->inode->st.st_flags; 697 dinp->di_flags = cur->inode->st.st_flags;
698#endif 698#endif
699#if HAVE_STRUCT_STAT_ST_GEN 699#if HAVE_STRUCT_STAT_ST_GEN
700 dinp->di_gen = cur->inode->st.st_gen; 700 dinp->di_gen = cur->inode->st.st_gen;
701#endif 701#endif
702#if HAVE_STRUCT_STAT_BIRTHTIME 702#if HAVE_STRUCT_STAT_BIRTHTIME
703 dinp->di_birthtime = cur->inode->st.st_birthtime; 703 dinp->di_birthtime = cur->inode->st.st_birthtime;
704 dinp->di_birthnsec = cur->inode->st.st_birthtimensec; 704 dinp->di_birthnsec = cur->inode->st.st_birthtimensec;
705#endif 705#endif
706 dinp->di_uid = cur->inode->st.st_uid; 706 dinp->di_uid = cur->inode->st.st_uid;
707 dinp->di_gid = cur->inode->st.st_gid; 707 dinp->di_gid = cur->inode->st.st_gid;
708 /* not set: di_db, di_ib, di_blocks, di_spare */ 708 /* not set: di_db, di_ib, di_blocks, di_spare */
709 709
710 membuf = NULL; 710 membuf = NULL;
711 if (cur == root) { /* "."; write dirbuf */ 711 if (cur == root) { /* "."; write dirbuf */
712 membuf = dbufp->buf; 712 membuf = dbufp->buf;
713 dinp->di_size = dbufp->size; 713 dinp->di_size = dbufp->size;
714 } else if (S_ISBLK(cur->type) || S_ISCHR(cur->type)) { 714 } else if (S_ISBLK(cur->type) || S_ISCHR(cur->type)) {
715 dinp->di_size = 0; /* a device */ 715 dinp->di_size = 0; /* a device */
716 dinp->di_rdev = 716 dinp->di_rdev =
717 ufs_rw64(cur->inode->st.st_rdev, fsopts->needswap); 717 ufs_rw64(cur->inode->st.st_rdev, fsopts->needswap);
718 } else if (S_ISLNK(cur->type)) { /* symlink */ 718 } else if (S_ISLNK(cur->type)) { /* symlink */
719 slen = strlen(cur->symlink); 719 slen = strlen(cur->symlink);
720 if (slen < UFS2_MAXSYMLINKLEN) { /* short link */ 720 if (slen < UFS2_MAXSYMLINKLEN) { /* short link */
721 memcpy(dinp->di_db, cur->symlink, slen); 721 memcpy(dinp->di_db, cur->symlink, slen);
722 } else 722 } else
723 membuf = cur->symlink; 723 membuf = cur->symlink;
724 dinp->di_size = slen; 724 dinp->di_size = slen;
725 } 725 }
726 return membuf; 726 return membuf;
727} 727}
728 728
729static int 729static int
730ffs_populate_dir(const char *dir, fsnode *root, fsinfo_t *fsopts) 730ffs_populate_dir(const char *dir, fsnode *root, fsinfo_t *fsopts)
731{ 731{
732 fsnode *cur; 732 fsnode *cur;
733 dirbuf_t dirbuf; 733 dirbuf_t dirbuf;
734 union dinode din; 734 union dinode din;
735 void *membuf; 735 void *membuf;
736 char path[MAXPATHLEN + 1]; 736 char path[MAXPATHLEN + 1];
737 ffs_opt_t *ffs_opts = fsopts->fs_specific; 737 ffs_opt_t *ffs_opts = fsopts->fs_specific;
738 738
739 assert(dir != NULL); 739 assert(dir != NULL);
740 assert(root != NULL); 740 assert(root != NULL);
741 assert(fsopts != NULL); 741 assert(fsopts != NULL);
742 assert(ffs_opts != NULL); 742 assert(ffs_opts != NULL);
743 743
744 (void)memset(&dirbuf, 0, sizeof(dirbuf)); 744 (void)memset(&dirbuf, 0, sizeof(dirbuf));
745 745
746 if (debug & DEBUG_FS_POPULATE) 746 if (debug & DEBUG_FS_POPULATE)
747 printf("ffs_populate_dir: PASS 1 dir %s node %p\n", dir, root); 747 printf("ffs_populate_dir: PASS 1 dir %s node %p\n", dir, root);
748 748
749 /* 749 /*
750 * pass 1: allocate inode numbers, build directory `file' 750 * pass 1: allocate inode numbers, build directory `file'
751 */ 751 */
752 for (cur = root; cur != NULL; cur = cur->next) { 752 for (cur = root; cur != NULL; cur = cur->next) {
753 if ((cur->inode->flags & FI_ALLOCATED) == 0) { 753 if ((cur->inode->flags & FI_ALLOCATED) == 0) {
754 cur->inode->flags |= FI_ALLOCATED; 754 cur->inode->flags |= FI_ALLOCATED;
755 if (cur == root && cur->parent != NULL) 755 if (cur == root && cur->parent != NULL)
756 cur->inode->ino = cur->parent->inode->ino; 756 cur->inode->ino = cur->parent->inode->ino;
757 else { 757 else {
758 cur->inode->ino = fsopts->curinode; 758 cur->inode->ino = fsopts->curinode;
759 fsopts->curinode++; 759 fsopts->curinode++;
760 } 760 }
761 } 761 }
762 ffs_make_dirbuf(&dirbuf, cur->name, cur, fsopts->needswap); 762 ffs_make_dirbuf(&dirbuf, cur->name, cur, fsopts->needswap);
763 if (cur == root) { /* we're at "."; add ".." */ 763 if (cur == root) { /* we're at "."; add ".." */
764 ffs_make_dirbuf(&dirbuf, "..", 764 ffs_make_dirbuf(&dirbuf, "..",
765 cur->parent == NULL ? cur : cur->parent->first, 765 cur->parent == NULL ? cur : cur->parent->first,
766 fsopts->needswap); 766 fsopts->needswap);
767 root->inode->nlink++; /* count my parent's link */ 767 root->inode->nlink++; /* count my parent's link */
768 } else if (cur->child != NULL) 768 } else if (cur->child != NULL)
769 root->inode->nlink++; /* count my child's link */ 769 root->inode->nlink++; /* count my child's link */
770 770
771 /* 771 /*
772 * XXX possibly write file and long symlinks here, 772 * XXX possibly write file and long symlinks here,
773 * ensuring that blocks get written before inodes? 773 * ensuring that blocks get written before inodes?
774 * otoh, this isn't a real filesystem, so who 774 * otoh, this isn't a real filesystem, so who
775 * cares about ordering? :-) 775 * cares about ordering? :-)
776 */ 776 */
777 } 777 }
778 if (debug & DEBUG_FS_POPULATE_DIRBUF) 778 if (debug & DEBUG_FS_POPULATE_DIRBUF)
779 ffs_dump_dirbuf(&dirbuf, dir, fsopts->needswap); 779 ffs_dump_dirbuf(&dirbuf, dir, fsopts->needswap);
780 780
781 /* 781 /*
782 * pass 2: write out dirbuf, then non-directories at this level 782 * pass 2: write out dirbuf, then non-directories at this level
783 */ 783 */
784 if (debug & DEBUG_FS_POPULATE) 784 if (debug & DEBUG_FS_POPULATE)
785 printf("ffs_populate_dir: PASS 2 dir %s\n", dir); 785 printf("ffs_populate_dir: PASS 2 dir %s\n", dir);
786 for (cur = root; cur != NULL; cur = cur->next) { 786 for (cur = root; cur != NULL; cur = cur->next) {
787 if (cur->inode->flags & FI_WRITTEN) 787 if (cur->inode->flags & FI_WRITTEN)
788 continue; /* skip hard-linked entries */ 788 continue; /* skip hard-linked entries */
789 cur->inode->flags |= FI_WRITTEN; 789 cur->inode->flags |= FI_WRITTEN;
790 790
791 if ((size_t)snprintf(path, sizeof(path), "%s/%s/%s", cur->root, 791 if ((size_t)snprintf(path, sizeof(path), "%s/%s/%s", cur->root,
792 cur->path, cur->name) >= sizeof(path)) 792 cur->path, cur->name) >= sizeof(path))
793 errx(1, "Pathname too long."); 793 errx(1, "Pathname too long.");
794 794
795 if (cur->child != NULL) 795 if (cur->child != NULL)
796 continue; /* child creates own inode */ 796 continue; /* child creates own inode */
797 797
798 /* build on-disk inode */ 798 /* build on-disk inode */
799 if (ffs_opts->version == 1) 799 if (ffs_opts->version == 1)
800 membuf = ffs_build_dinode1(&din.ffs1_din, &dirbuf, cur, 800 membuf = ffs_build_dinode1(&din.ffs1_din, &dirbuf, cur,
801 root, fsopts); 801 root, fsopts);
802 else 802 else
803 membuf = ffs_build_dinode2(&din.ffs2_din, &dirbuf, cur, 803 membuf = ffs_build_dinode2(&din.ffs2_din, &dirbuf, cur,
804 root, fsopts); 804 root, fsopts);
805 805
806 if (debug & DEBUG_FS_POPULATE_NODE) { 806 if (debug & DEBUG_FS_POPULATE_NODE) {
807 printf("ffs_populate_dir: writing ino %d, %s", 807 printf("ffs_populate_dir: writing ino %d, %s",
808 cur->inode->ino, inode_type(cur->type)); 808 cur->inode->ino, inode_type(cur->type));
809 if (cur->inode->nlink > 1) 809 if (cur->inode->nlink > 1)
810 printf(", nlink %d", cur->inode->nlink); 810 printf(", nlink %d", cur->inode->nlink);
811 putchar('\n'); 811 putchar('\n');
812 } 812 }
813 813
814 if (membuf != NULL) { 814 if (membuf != NULL) {
815 ffs_write_file(&din, cur->inode->ino, membuf, fsopts); 815 ffs_write_file(&din, cur->inode->ino, membuf, fsopts);
816 } else if (S_ISREG(cur->type)) { 816 } else if (S_ISREG(cur->type)) {
817 ffs_write_file(&din, cur->inode->ino, path, fsopts); 817 ffs_write_file(&din, cur->inode->ino, path, fsopts);
818 } else { 818 } else {
819 assert (! S_ISDIR(cur->type)); 819 assert (! S_ISDIR(cur->type));
820 ffs_write_inode(&din, cur->inode->ino, fsopts); 820 ffs_write_inode(&din, cur->inode->ino, fsopts);
821 } 821 }
822 } 822 }
823 823
824 /* 824 /*
825 * pass 3: write out sub-directories 825 * pass 3: write out sub-directories
826 */ 826 */
827 if (debug & DEBUG_FS_POPULATE) 827 if (debug & DEBUG_FS_POPULATE)
828 printf("ffs_populate_dir: PASS 3 dir %s\n", dir); 828 printf("ffs_populate_dir: PASS 3 dir %s\n", dir);
829 for (cur = root; cur != NULL; cur = cur->next) { 829 for (cur = root; cur != NULL; cur = cur->next) {
830 if (cur->child == NULL) 830 if (cur->child == NULL)
831 continue; 831 continue;
832 if ((size_t)snprintf(path, sizeof(path), "%s/%s", dir, 832 if ((size_t)snprintf(path, sizeof(path), "%s/%s", dir,
833 cur->name) >= sizeof(path)) 833 cur->name) >= sizeof(path))
834 errx(1, "Pathname too long."); 834 errx(1, "Pathname too long.");
835 if (! ffs_populate_dir(path, cur->child, fsopts)) 835 if (! ffs_populate_dir(path, cur->child, fsopts))
836 return (0); 836 return (0);
837 } 837 }
838 838
839 if (debug & DEBUG_FS_POPULATE) 839 if (debug & DEBUG_FS_POPULATE)
840 printf("ffs_populate_dir: DONE dir %s\n", dir); 840 printf("ffs_populate_dir: DONE dir %s\n", dir);
841 841
842 /* cleanup */ 842 /* cleanup */
843 if (dirbuf.buf != NULL) 843 if (dirbuf.buf != NULL)
844 free(dirbuf.buf); 844 free(dirbuf.buf);
845 return (1); 845 return (1);
846} 846}
847 847
848 848
849static void 849static void
850ffs_write_file(union dinode *din, uint32_t ino, void *buf, fsinfo_t *fsopts) 850ffs_write_file(union dinode *din, uint32_t ino, void *buf, fsinfo_t *fsopts)
851{ 851{
852 int isfile, ffd; 852 int isfile, ffd;
853 char *fbuf, *p; 853 char *fbuf, *p;
854 off_t bufleft, chunk, offset; 854 off_t bufleft, chunk, offset;
855 ssize_t nread; 855 ssize_t nread;
856 struct inode in; 856 struct inode in;
857 struct buf * bp; 857 struct buf * bp;
858 ffs_opt_t *ffs_opts = fsopts->fs_specific; 858 ffs_opt_t *ffs_opts = fsopts->fs_specific;
859 859
860 assert (din != NULL); 860 assert (din != NULL);
861 assert (buf != NULL); 861 assert (buf != NULL);
862 assert (fsopts != NULL); 862 assert (fsopts != NULL);
863 assert (ffs_opts != NULL); 863 assert (ffs_opts != NULL);
864 864
865 isfile = S_ISREG(DIP(din, mode)); 865 isfile = S_ISREG(DIP(din, mode));
866 fbuf = NULL; 866 fbuf = NULL;
867 ffd = -1; 867 ffd = -1;
868 p = NULL; 868 p = NULL;
869 869
870 in.i_fs = (struct fs *)fsopts->superblock; 870 in.i_fs = (struct fs *)fsopts->superblock;
871 871
872 if (debug & DEBUG_FS_WRITE_FILE) { 872 if (debug & DEBUG_FS_WRITE_FILE) {
873 printf( 873 printf(
874 "ffs_write_file: ino %u, din %p, isfile %d, %s, size %lld", 874 "ffs_write_file: ino %u, din %p, isfile %d, %s, size %lld",
875 ino, din, isfile, inode_type(DIP(din, mode) & S_IFMT), 875 ino, din, isfile, inode_type(DIP(din, mode) & S_IFMT),
876 (long long)DIP(din, size)); 876 (long long)DIP(din, size));
877 if (isfile) 877 if (isfile)
878 printf(", file '%s'\n", (char *)buf); 878 printf(", file '%s'\n", (char *)buf);
879 else 879 else
880 printf(", buffer %p\n", buf); 880 printf(", buffer %p\n", buf);
881 } 881 }
882 882
883 in.i_number = ino; 883 in.i_number = ino;
884 in.i_size = DIP(din, size); 884 in.i_size = DIP(din, size);
885 if (ffs_opts->version == 1) 885 if (ffs_opts->version == 1)
886 memcpy(&in.i_din.ffs1_din, &din->ffs1_din, 886 memcpy(&in.i_din.ffs1_din, &din->ffs1_din,
887 sizeof(in.i_din.ffs1_din)); 887 sizeof(in.i_din.ffs1_din));
888 else 888 else
889 memcpy(&in.i_din.ffs2_din, &din->ffs2_din, 889 memcpy(&in.i_din.ffs2_din, &din->ffs2_din,
890 sizeof(in.i_din.ffs2_din)); 890 sizeof(in.i_din.ffs2_din));
891 in.i_fd = fsopts->fd; 891 in.i_fd = fsopts->fd;
892 892
893 if (DIP(din, size) == 0) 893 if (DIP(din, size) == 0)
894 goto write_inode_and_leave; /* mmm, cheating */ 894 goto write_inode_and_leave; /* mmm, cheating */
895 895
896 if (isfile) { 896 if (isfile) {
897 if ((fbuf = malloc(ffs_opts->bsize)) == NULL) 897 if ((fbuf = malloc(ffs_opts->bsize)) == NULL)
898 err(1, "Allocating memory for write buffer"); 898 err(1, "Allocating memory for write buffer");
899 if ((ffd = open((char *)buf, O_RDONLY, 0444)) == -1) { 899 if ((ffd = open((char *)buf, O_RDONLY, 0444)) == -1) {
900 warn("Can't open `%s' for reading", (char *)buf); 900 warn("Can't open `%s' for reading", (char *)buf);
901 goto leave_ffs_write_file; 901 goto leave_ffs_write_file;
902 } 902 }
903 } else { 903 } else {
904 p = buf; 904 p = buf;
905 } 905 }
906 906
907 chunk = 0; 907 chunk = 0;
908 for (bufleft = DIP(din, size); bufleft > 0; bufleft -= chunk) { 908 for (bufleft = DIP(din, size); bufleft > 0; bufleft -= chunk) {
909 chunk = MIN(bufleft, ffs_opts->bsize); 909 chunk = MIN(bufleft, ffs_opts->bsize);
910 if (!isfile) 910 if (!isfile)
911 ; 911 ;
912 else if ((nread = read(ffd, fbuf, chunk)) == -1) 912 else if ((nread = read(ffd, fbuf, chunk)) == -1)
913 err(EXIT_FAILURE, "Reading `%s', %lld bytes to go", 913 err(EXIT_FAILURE, "Reading `%s', %lld bytes to go",
914 (char *)buf, (long long)bufleft); 914 (char *)buf, (long long)bufleft);
915 else if (nread != chunk) 915 else if (nread != chunk)
916 errx(EXIT_FAILURE, "Reading `%s', %lld bytes to go, " 916 errx(EXIT_FAILURE, "Reading `%s', %lld bytes to go, "
917 "read %zd bytes, expected %ju bytes, does " 917 "read %zd bytes, expected %ju bytes, does "
918 "metalog size= attribute mismatch source size?", 918 "metalog size= attribute mismatch source size?",
919 (char *)buf, (long long)bufleft, nread, 919 (char *)buf, (long long)bufleft, nread,
920 (uintmax_t)chunk); 920 (uintmax_t)chunk);
921 else 921 else
922 p = fbuf; 922 p = fbuf;
923 offset = DIP(din, size) - bufleft; 923 offset = DIP(din, size) - bufleft;
924 if (debug & DEBUG_FS_WRITE_FILE_BLOCK) 924 if (debug & DEBUG_FS_WRITE_FILE_BLOCK)
925 printf( 925 printf(
926 "ffs_write_file: write %p offset %lld size %lld left %lld\n", 926 "ffs_write_file: write %p offset %lld size %lld left %lld\n",
927 p, (long long)offset, 927 p, (long long)offset,
928 (long long)chunk, (long long)bufleft); 928 (long long)chunk, (long long)bufleft);
929 /* 929 /*
930 * XXX if holey support is desired, do the check here 930 * XXX if holey support is desired, do the check here
931 * 931 *
932 * XXX might need to write out last bit in fragroundup 932 * XXX might need to write out last bit in fragroundup
933 * sized chunk. however, ffs_balloc() handles this for us 933 * sized chunk. however, ffs_balloc() handles this for us
934 */ 934 */
935 errno = ffs_balloc(&in, offset, chunk, &bp); 935 errno = ffs_balloc(&in, offset, chunk, &bp);
936 bad_ffs_write_file: 936 bad_ffs_write_file:
937 if (errno != 0) 937 if (errno != 0)
938 err(1, 938 err(1,
939 "Writing inode %d (%s), bytes %lld + %lld", 939 "Writing inode %d (%s), bytes %lld + %lld",
940 ino, 940 ino,
941 isfile ? (char *)buf : 941 isfile ? (char *)buf :
942 inode_type(DIP(din, mode) & S_IFMT), 942 inode_type(DIP(din, mode) & S_IFMT),
943 (long long)offset, (long long)chunk); 943 (long long)offset, (long long)chunk);
944 memcpy(bp->b_data, p, chunk); 944 memcpy(bp->b_data, p, chunk);
945 errno = bwrite(bp); 945 errno = bwrite(bp);
946 if (errno != 0) 946 if (errno != 0)
947 goto bad_ffs_write_file; 947 goto bad_ffs_write_file;
948 brelse(bp); 948 brelse(bp, 0);
949 if (!isfile) 949 if (!isfile)
950 p += chunk; 950 p += chunk;
951 } 951 }
952  952
953 write_inode_and_leave: 953 write_inode_and_leave:
954 ffs_write_inode(&in.i_din, in.i_number, fsopts); 954 ffs_write_inode(&in.i_din, in.i_number, fsopts);
955 955
956 leave_ffs_write_file: 956 leave_ffs_write_file:
957 if (fbuf) 957 if (fbuf)
958 free(fbuf); 958 free(fbuf);
959 if (ffd != -1) 959 if (ffd != -1)
960 close(ffd); 960 close(ffd);
961} 961}
962 962
963 963
964static void 964static void
965ffs_dump_dirbuf(dirbuf_t *dbuf, const char *dir, int needswap) 965ffs_dump_dirbuf(dirbuf_t *dbuf, const char *dir, int needswap)
966{ 966{
967 doff_t i; 967 doff_t i;
968 struct direct *de; 968 struct direct *de;
969 uint16_t reclen; 969 uint16_t reclen;
970 970
971 assert (dbuf != NULL); 971 assert (dbuf != NULL);
972 assert (dir != NULL); 972 assert (dir != NULL);
973 printf("ffs_dump_dirbuf: dir %s size %d cur %d\n", 973 printf("ffs_dump_dirbuf: dir %s size %d cur %d\n",
974 dir, dbuf->size, dbuf->cur); 974 dir, dbuf->size, dbuf->cur);
975 975
976 for (i = 0; i < dbuf->size; ) { 976 for (i = 0; i < dbuf->size; ) {
977 de = (struct direct *)(dbuf->buf + i); 977 de = (struct direct *)(dbuf->buf + i);
978 reclen = ufs_rw16(de->d_reclen, needswap); 978 reclen = ufs_rw16(de->d_reclen, needswap);
979 printf( 979 printf(
980 " inode %4d %7s offset %4d reclen %3d namlen %3d name %s\n", 980 " inode %4d %7s offset %4d reclen %3d namlen %3d name %s\n",
981 ufs_rw32(de->d_fileno, needswap), 981 ufs_rw32(de->d_fileno, needswap),
982 inode_type(DTTOIF(de->d_type)), i, reclen, 982 inode_type(DTTOIF(de->d_type)), i, reclen,
983 de->d_namlen, de->d_name); 983 de->d_namlen, de->d_name);
984 i += reclen; 984 i += reclen;
985 assert(reclen > 0); 985 assert(reclen > 0);
986 } 986 }
987} 987}
988 988
989static void 989static void
990ffs_make_dirbuf(dirbuf_t *dbuf, const char *name, fsnode *node, int needswap) 990ffs_make_dirbuf(dirbuf_t *dbuf, const char *name, fsnode *node, int needswap)
991{ 991{
992 struct direct de, *dp; 992 struct direct de, *dp;
993 uint16_t llen, reclen; 993 uint16_t llen, reclen;
994 u_char *newbuf; 994 u_char *newbuf;
995 995
996 assert (dbuf != NULL); 996 assert (dbuf != NULL);
997 assert (name != NULL); 997 assert (name != NULL);
998 assert (node != NULL); 998 assert (node != NULL);
999 /* create direct entry */ 999 /* create direct entry */
1000 (void)memset(&de, 0, sizeof(de)); 1000 (void)memset(&de, 0, sizeof(de));
1001 de.d_fileno = ufs_rw32(node->inode->ino, needswap); 1001 de.d_fileno = ufs_rw32(node->inode->ino, needswap);
1002 de.d_type = IFTODT(node->type); 1002 de.d_type = IFTODT(node->type);
1003 de.d_namlen = (uint8_t)strlen(name); 1003 de.d_namlen = (uint8_t)strlen(name);
1004 strcpy(de.d_name, name); 1004 strcpy(de.d_name, name);
1005 reclen = DIRSIZ(0, &de, needswap); 1005 reclen = DIRSIZ(0, &de, needswap);
1006 de.d_reclen = ufs_rw16(reclen, needswap); 1006 de.d_reclen = ufs_rw16(reclen, needswap);
1007 1007
1008 dp = (struct direct *)(dbuf->buf + dbuf->cur); 1008 dp = (struct direct *)(dbuf->buf + dbuf->cur);
1009 llen = 0; 1009 llen = 0;
1010 if (dp != NULL) 1010 if (dp != NULL)
1011 llen = DIRSIZ(0, dp, needswap); 1011 llen = DIRSIZ(0, dp, needswap);
1012 1012
1013 if (debug & DEBUG_FS_MAKE_DIRBUF) 1013 if (debug & DEBUG_FS_MAKE_DIRBUF)
1014 printf( 1014 printf(
1015 "ffs_make_dirbuf: dbuf siz %d cur %d lastlen %d\n" 1015 "ffs_make_dirbuf: dbuf siz %d cur %d lastlen %d\n"
1016 " ino %d type %d reclen %d namlen %d name %.30s\n", 1016 " ino %d type %d reclen %d namlen %d name %.30s\n",
1017 dbuf->size, dbuf->cur, llen, 1017 dbuf->size, dbuf->cur, llen,
1018 ufs_rw32(de.d_fileno, needswap), de.d_type, reclen, 1018 ufs_rw32(de.d_fileno, needswap), de.d_type, reclen,
1019 de.d_namlen, de.d_name); 1019 de.d_namlen, de.d_name);
1020 1020
1021 if (reclen + dbuf->cur + llen > roundup(dbuf->size, DIRBLKSIZ)) { 1021 if (reclen + dbuf->cur + llen > roundup(dbuf->size, DIRBLKSIZ)) {
1022 if (debug & DEBUG_FS_MAKE_DIRBUF) 1022 if (debug & DEBUG_FS_MAKE_DIRBUF)
1023 printf("ffs_make_dirbuf: growing buf to %d\n", 1023 printf("ffs_make_dirbuf: growing buf to %d\n",
1024 dbuf->size + DIRBLKSIZ); 1024 dbuf->size + DIRBLKSIZ);
1025 if ((newbuf = realloc(dbuf->buf, dbuf->size + DIRBLKSIZ)) == NULL) 1025 if ((newbuf = realloc(dbuf->buf, dbuf->size + DIRBLKSIZ)) == NULL)
1026 err(1, "Allocating memory for directory buffer"); 1026 err(1, "Allocating memory for directory buffer");
1027 dbuf->buf = newbuf; 1027 dbuf->buf = newbuf;
1028 dbuf->size += DIRBLKSIZ; 1028 dbuf->size += DIRBLKSIZ;
1029 memset(dbuf->buf + dbuf->size - DIRBLKSIZ, 0, DIRBLKSIZ); 1029 memset(dbuf->buf + dbuf->size - DIRBLKSIZ, 0, DIRBLKSIZ);
1030 dbuf->cur = dbuf->size - DIRBLKSIZ; 1030 dbuf->cur = dbuf->size - DIRBLKSIZ;
1031 } else if (dp) { /* shrink end of previous */ 1031 } else if (dp) { /* shrink end of previous */
1032 dp->d_reclen = ufs_rw16(llen,needswap); 1032 dp->d_reclen = ufs_rw16(llen,needswap);
1033 dbuf->cur += llen; 1033 dbuf->cur += llen;
1034 } 1034 }
1035 dp = (struct direct *)(dbuf->buf + dbuf->cur); 1035 dp = (struct direct *)(dbuf->buf + dbuf->cur);
1036 memcpy(dp, &de, reclen); 1036 memcpy(dp, &de, reclen);
1037 dp->d_reclen = ufs_rw16(dbuf->size - dbuf->cur, needswap); 1037 dp->d_reclen = ufs_rw16(dbuf->size - dbuf->cur, needswap);
1038} 1038}
1039 1039
1040/* 1040/*
1041 * cribbed from sys/ufs/ffs/ffs_alloc.c 1041 * cribbed from sys/ufs/ffs/ffs_alloc.c
1042 */ 1042 */
1043static void 1043static void
1044ffs_write_inode(union dinode *dp, uint32_t ino, const fsinfo_t *fsopts) 1044ffs_write_inode(union dinode *dp, uint32_t ino, const fsinfo_t *fsopts)
1045{ 1045{
1046 char *buf; 1046 char *buf;
1047 struct ufs1_dinode *dp1; 1047 struct ufs1_dinode *dp1;
1048 struct ufs2_dinode *dp2, *dip; 1048 struct ufs2_dinode *dp2, *dip;
1049 struct cg *cgp; 1049 struct cg *cgp;
1050 struct fs *fs; 1050 struct fs *fs;
1051 int cg, cgino, i; 1051 int cg, cgino, i;
1052 daddr_t d; 1052 daddr_t d;
1053 char sbbuf[FFS_MAXBSIZE]; 1053 char sbbuf[FFS_MAXBSIZE];
1054 uint32_t initediblk; 1054 uint32_t initediblk;
1055 ffs_opt_t *ffs_opts = fsopts->fs_specific; 1055 ffs_opt_t *ffs_opts = fsopts->fs_specific;
1056 1056
1057 assert (dp != NULL); 1057 assert (dp != NULL);
1058 assert (ino > 0); 1058 assert (ino > 0);
1059 assert (fsopts != NULL); 1059 assert (fsopts != NULL);
1060 assert (ffs_opts != NULL); 1060 assert (ffs_opts != NULL);
1061 1061
1062 fs = (struct fs *)fsopts->superblock; 1062 fs = (struct fs *)fsopts->superblock;
1063 cg = ino_to_cg(fs, ino); 1063 cg = ino_to_cg(fs, ino);
1064 cgino = ino % fs->fs_ipg; 1064 cgino = ino % fs->fs_ipg;
1065 if (debug & DEBUG_FS_WRITE_INODE) 1065 if (debug & DEBUG_FS_WRITE_INODE)
1066 printf("ffs_write_inode: din %p ino %u cg %d cgino %d\n", 1066 printf("ffs_write_inode: din %p ino %u cg %d cgino %d\n",
1067 dp, ino, cg, cgino); 1067 dp, ino, cg, cgino);
1068 1068
1069 ffs_rdfs(fsbtodb(fs, cgtod(fs, cg)), (int)fs->fs_cgsize, &sbbuf, 1069 ffs_rdfs(fsbtodb(fs, cgtod(fs, cg)), (int)fs->fs_cgsize, &sbbuf,
1070 fsopts); 1070 fsopts);
1071 cgp = (struct cg *)sbbuf; 1071 cgp = (struct cg *)sbbuf;
1072 if (!cg_chkmagic(cgp, fsopts->needswap)) 1072 if (!cg_chkmagic(cgp, fsopts->needswap))
1073 errx(1, "ffs_write_inode: cg %d: bad magic number", cg); 1073 errx(1, "ffs_write_inode: cg %d: bad magic number", cg);
1074 1074
1075 assert (isclr(cg_inosused(cgp, fsopts->needswap), cgino)); 1075 assert (isclr(cg_inosused(cgp, fsopts->needswap), cgino));
1076 1076
1077 buf = malloc(fs->fs_bsize); 1077 buf = malloc(fs->fs_bsize);
1078 if (buf == NULL) 1078 if (buf == NULL)
1079 errx(1, "ffs_write_inode: cg %d: can't alloc inode block", cg); 1079 errx(1, "ffs_write_inode: cg %d: can't alloc inode block", cg);
1080 1080
1081 dp1 = (struct ufs1_dinode *)buf; 1081 dp1 = (struct ufs1_dinode *)buf;
1082 dp2 = (struct ufs2_dinode *)buf; 1082 dp2 = (struct ufs2_dinode *)buf;
1083 1083
1084 if (fs->fs_cstotal.cs_nifree == 0) 1084 if (fs->fs_cstotal.cs_nifree == 0)
1085 errx(1, "ffs_write_inode: fs out of inodes for ino %u", 1085 errx(1, "ffs_write_inode: fs out of inodes for ino %u",
1086 ino); 1086 ino);
1087 if (fs->fs_cs(fs, cg).cs_nifree == 0) 1087 if (fs->fs_cs(fs, cg).cs_nifree == 0)
1088 errx(1, 1088 errx(1,
1089 "ffs_write_inode: cg %d out of inodes for ino %u", 1089 "ffs_write_inode: cg %d out of inodes for ino %u",
1090 cg, ino); 1090 cg, ino);
1091 setbit(cg_inosused(cgp, fsopts->needswap), cgino); 1091 setbit(cg_inosused(cgp, fsopts->needswap), cgino);
1092 ufs_add32(cgp->cg_cs.cs_nifree, -1, fsopts->needswap); 1092 ufs_add32(cgp->cg_cs.cs_nifree, -1, fsopts->needswap);
1093 fs->fs_cstotal.cs_nifree--; 1093 fs->fs_cstotal.cs_nifree--;
1094 fs->fs_cs(fs, cg).cs_nifree--; 1094 fs->fs_cs(fs, cg).cs_nifree--;
1095 if (S_ISDIR(DIP(dp, mode))) { 1095 if (S_ISDIR(DIP(dp, mode))) {
1096 ufs_add32(cgp->cg_cs.cs_ndir, 1, fsopts->needswap); 1096 ufs_add32(cgp->cg_cs.cs_ndir, 1, fsopts->needswap);
1097 fs->fs_cstotal.cs_ndir++; 1097 fs->fs_cstotal.cs_ndir++;
1098 fs->fs_cs(fs, cg).cs_ndir++;  1098 fs->fs_cs(fs, cg).cs_ndir++;
1099 } 1099 }
1100 1100
1101 /* 1101 /*
1102 * Initialize inode blocks on the fly for UFS2. 1102 * Initialize inode blocks on the fly for UFS2.
1103 */ 1103 */
1104 initediblk = ufs_rw32(cgp->cg_initediblk, fsopts->needswap); 1104 initediblk = ufs_rw32(cgp->cg_initediblk, fsopts->needswap);
1105 if (ffs_opts->version == 2 && 1105 if (ffs_opts->version == 2 &&
1106 (uint32_t)(cgino + INOPB(fs)) > initediblk && 1106 (uint32_t)(cgino + INOPB(fs)) > initediblk &&
1107 initediblk < ufs_rw32(cgp->cg_niblk, fsopts->needswap)) { 1107 initediblk < ufs_rw32(cgp->cg_niblk, fsopts->needswap)) {
1108 memset(buf, 0, fs->fs_bsize); 1108 memset(buf, 0, fs->fs_bsize);
1109 dip = (struct ufs2_dinode *)buf; 1109 dip = (struct ufs2_dinode *)buf;
1110 srandom(time(NULL)); 1110 srandom(time(NULL));
1111 for (i = 0; i < INOPB(fs); i++) { 1111 for (i = 0; i < INOPB(fs); i++) {
1112 dip->di_gen = random() / 2 + 1; 1112 dip->di_gen = random() / 2 + 1;
1113 dip++; 1113 dip++;
1114 } 1114 }
1115 ffs_wtfs(fsbtodb(fs, ino_to_fsba(fs, 1115 ffs_wtfs(fsbtodb(fs, ino_to_fsba(fs,
1116 cg * fs->fs_ipg + initediblk)), 1116 cg * fs->fs_ipg + initediblk)),
1117 fs->fs_bsize, buf, fsopts); 1117 fs->fs_bsize, buf, fsopts);
1118 initediblk += INOPB(fs); 1118 initediblk += INOPB(fs);
1119 cgp->cg_initediblk = ufs_rw32(initediblk, fsopts->needswap); 1119 cgp->cg_initediblk = ufs_rw32(initediblk, fsopts->needswap);
1120 } 1120 }
1121 1121
1122 1122
1123 ffs_wtfs(fsbtodb(fs, cgtod(fs, cg)), (int)fs->fs_cgsize, &sbbuf, 1123 ffs_wtfs(fsbtodb(fs, cgtod(fs, cg)), (int)fs->fs_cgsize, &sbbuf,
1124 fsopts); 1124 fsopts);
1125 1125
1126 /* now write inode */ 1126 /* now write inode */
1127 d = fsbtodb(fs, ino_to_fsba(fs, ino)); 1127 d = fsbtodb(fs, ino_to_fsba(fs, ino));
1128 ffs_rdfs(d, fs->fs_bsize, buf, fsopts); 1128 ffs_rdfs(d, fs->fs_bsize, buf, fsopts);
1129 if (fsopts->needswap) { 1129 if (fsopts->needswap) {
1130 if (ffs_opts->version == 1) 1130 if (ffs_opts->version == 1)
1131 ffs_dinode1_swap(&dp->ffs1_din, 1131 ffs_dinode1_swap(&dp->ffs1_din,
1132 &dp1[ino_to_fsbo(fs, ino)]); 1132 &dp1[ino_to_fsbo(fs, ino)]);
1133 else 1133 else
1134 ffs_dinode2_swap(&dp->ffs2_din, 1134 ffs_dinode2_swap(&dp->ffs2_din,
1135 &dp2[ino_to_fsbo(fs, ino)]); 1135 &dp2[ino_to_fsbo(fs, ino)]);
1136 } else { 1136 } else {
1137 if (ffs_opts->version == 1) 1137 if (ffs_opts->version == 1)
1138 dp1[ino_to_fsbo(fs, ino)] = dp->ffs1_din; 1138 dp1[ino_to_fsbo(fs, ino)] = dp->ffs1_din;
1139 else 1139 else
1140 dp2[ino_to_fsbo(fs, ino)] = dp->ffs2_din; 1140 dp2[ino_to_fsbo(fs, ino)] = dp->ffs2_din;
1141 } 1141 }
1142 ffs_wtfs(d, fs->fs_bsize, buf, fsopts); 1142 ffs_wtfs(d, fs->fs_bsize, buf, fsopts);
1143 free(buf); 1143 free(buf);
1144} 1144}
1145 1145
1146void 1146void
1147panic(const char *fmt, ...) 1147panic(const char *fmt, ...)
1148{ 1148{
1149 va_list ap; 1149 va_list ap;
1150 1150
1151 va_start(ap, fmt); 1151 va_start(ap, fmt);
1152 vwarnx(fmt, ap); 1152 vwarnx(fmt, ap);
1153 va_end(ap); 1153 va_end(ap);
1154 exit(1); 1154 exit(1);
1155} 1155}

cvs diff -r1.12 -r1.13 src/usr.sbin/makefs/ffs/buf.c (switch to unified diff)

--- src/usr.sbin/makefs/ffs/buf.c 2004/06/20 22:20:18 1.12
+++ src/usr.sbin/makefs/ffs/buf.c 2013/01/26 00:19:39 1.13
@@ -1,228 +1,234 @@ @@ -1,228 +1,234 @@
1/* $NetBSD: buf.c,v 1.12 2004/06/20 22:20:18 jmc Exp $ */ 1/* $NetBSD: buf.c,v 1.13 2013/01/26 00:19:39 christos Exp $ */
2 2
3/* 3/*
4 * Copyright (c) 2001 Wasabi Systems, Inc. 4 * Copyright (c) 2001 Wasabi Systems, Inc.
5 * All rights reserved. 5 * All rights reserved.
6 * 6 *
7 * Written by Luke Mewburn for Wasabi Systems, Inc. 7 * Written by Luke Mewburn for Wasabi Systems, Inc.
8 * 8 *
9 * Redistribution and use in source and binary forms, with or without 9 * Redistribution and use in source and binary forms, with or without
10 * modification, are permitted provided that the following conditions 10 * modification, are permitted provided that the following conditions
11 * are met: 11 * are met:
12 * 1. Redistributions of source code must retain the above copyright 12 * 1. Redistributions of source code must retain the above copyright
13 * notice, this list of conditions and the following disclaimer. 13 * notice, this list of conditions and the following disclaimer.
14 * 2. Redistributions in binary form must reproduce the above copyright 14 * 2. Redistributions in binary form must reproduce the above copyright
15 * notice, this list of conditions and the following disclaimer in the 15 * notice, this list of conditions and the following disclaimer in the
16 * documentation and/or other materials provided with the distribution. 16 * documentation and/or other materials provided with the distribution.
17 * 3. All advertising materials mentioning features or use of this software 17 * 3. All advertising materials mentioning features or use of this software
18 * must display the following acknowledgement: 18 * must display the following acknowledgement:
19 * This product includes software developed for the NetBSD Project by 19 * This product includes software developed for the NetBSD Project by
20 * Wasabi Systems, Inc. 20 * Wasabi Systems, Inc.
21 * 4. The name of Wasabi Systems, Inc. may not be used to endorse 21 * 4. The name of Wasabi Systems, Inc. may not be used to endorse
22 * or promote products derived from this software without specific prior 22 * or promote products derived from this software without specific prior
23 * written permission. 23 * written permission.
24 * 24 *
25 * THIS SOFTWARE IS PROVIDED BY WASABI SYSTEMS, INC. ``AS IS'' AND 25 * THIS SOFTWARE IS PROVIDED BY WASABI SYSTEMS, INC. ``AS IS'' AND
26 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 26 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
27 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 27 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
28 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL WASABI SYSTEMS, INC 28 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL WASABI SYSTEMS, INC
29 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 29 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
30 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 30 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
31 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 31 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
32 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 32 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
33 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 33 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
34 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 34 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
35 * POSSIBILITY OF SUCH DAMAGE. 35 * POSSIBILITY OF SUCH DAMAGE.
36 */ 36 */
37 37
38#if HAVE_NBTOOL_CONFIG_H 38#if HAVE_NBTOOL_CONFIG_H
39#include "nbtool_config.h" 39#include "nbtool_config.h"
40#endif 40#endif
41 41
42#include <sys/cdefs.h> 42#include <sys/cdefs.h>
43#if defined(__RCSID) && !defined(__lint) 43#if defined(__RCSID) && !defined(__lint)
44__RCSID("$NetBSD: buf.c,v 1.12 2004/06/20 22:20:18 jmc Exp $"); 44__RCSID("$NetBSD: buf.c,v 1.13 2013/01/26 00:19:39 christos Exp $");
45#endif /* !__lint */ 45#endif /* !__lint */
46 46
47#include <sys/param.h> 47#include <sys/param.h>
48#include <sys/time.h> 48#include <sys/time.h>
49 49
50#include <assert.h> 50#include <assert.h>
51#include <errno.h> 51#include <errno.h>
52#include <stdio.h> 52#include <stdio.h>
53#include <stdlib.h> 53#include <stdlib.h>
54#include <unistd.h> 54#include <unistd.h>
55 55
56#include "makefs.h" 56#include "makefs.h"
57 57
58#include <ufs/ufs/dinode.h> 58#include <ufs/ufs/dinode.h>
59#include <ufs/ffs/fs.h> 59#include <ufs/ffs/fs.h>
60 60
61#include "ffs/buf.h" 61#include "ffs/buf.h"
62#include "ffs/ufs_inode.h" 62#include "ffs/ufs_inode.h"
63 63
64extern int sectorsize; /* XXX: from ffs.c & mkfs.c */ 64extern int sectorsize; /* XXX: from ffs.c & mkfs.c */
65 65
66TAILQ_HEAD(buftailhead,buf) buftail; 66TAILQ_HEAD(buftailhead,buf) buftail;
67 67
68int 68int
69bread(int fd, struct fs *fs, daddr_t blkno, int size, struct buf **bpp) 69bread(struct vnode *vp, daddr_t blkno, int size, struct kauth_cred *u1 __unused,
 70 int u2 __unused, struct buf **bpp)
70{ 71{
71 off_t offset; 72 off_t offset;
72 ssize_t rv; 73 ssize_t rv;
 74 struct fs *fs = vp->fs;
73 75
74 assert (fs != NULL); 76 assert (fs != NULL);
75 assert (bpp != NULL); 77 assert (bpp != NULL);
76 78
77 if (debug & DEBUG_BUF_BREAD) 79 if (debug & DEBUG_BUF_BREAD)
78 printf("bread: fs %p blkno %lld size %d\n", 80 printf("bread: fs %p blkno %lld size %d\n",
79 fs, (long long)blkno, size); 81 fs, (long long)blkno, size);
80 *bpp = getblk(fd, fs, blkno, size); 82 *bpp = getblk(vp, blkno, size, 0, 0);
81 offset = (*bpp)->b_blkno * sectorsize; /* XXX */ 83 offset = (*bpp)->b_blkno * sectorsize; /* XXX */
82 if (debug & DEBUG_BUF_BREAD) 84 if (debug & DEBUG_BUF_BREAD)
83 printf("bread: bp %p blkno %lld offset %lld bcount %ld\n", 85 printf("bread: bp %p blkno %lld offset %lld bcount %ld\n",
84 (*bpp), (long long)(*bpp)->b_blkno, (long long) offset, 86 (*bpp), (long long)(*bpp)->b_blkno, (long long) offset,
85 (*bpp)->b_bcount); 87 (*bpp)->b_bcount);
86 if (lseek((*bpp)->b_fd, offset, SEEK_SET) == -1) 88 if (lseek((*bpp)->b_fd, offset, SEEK_SET) == -1)
87 err(1, "bread: lseek %lld (%lld)", 89 err(1, "bread: lseek %lld (%lld)",
88 (long long)(*bpp)->b_blkno, (long long)offset); 90 (long long)(*bpp)->b_blkno, (long long)offset);
89 rv = read((*bpp)->b_fd, (*bpp)->b_data, (*bpp)->b_bcount); 91 rv = read((*bpp)->b_fd, (*bpp)->b_data, (*bpp)->b_bcount);
90 if (debug & DEBUG_BUF_BREAD) 92 if (debug & DEBUG_BUF_BREAD)
91 printf("bread: read %ld (%lld) returned %d\n", 93 printf("bread: read %ld (%lld) returned %d\n",
92 (*bpp)->b_bcount, (long long)offset, (int)rv); 94 (*bpp)->b_bcount, (long long)offset, (int)rv);
93 if (rv == -1) /* read error */ 95 if (rv == -1) /* read error */
94 err(1, "bread: read %ld (%lld) returned %d", 96 err(1, "bread: read %ld (%lld) returned %d",
95 (*bpp)->b_bcount, (long long)offset, (int)rv); 97 (*bpp)->b_bcount, (long long)offset, (int)rv);
96 else if (rv != (*bpp)->b_bcount) /* short read */ 98 else if (rv != (*bpp)->b_bcount) /* short read */
97 err(1, "bread: read %ld (%lld) returned %d", 99 err(1, "bread: read %ld (%lld) returned %d",
98 (*bpp)->b_bcount, (long long)offset, (int)rv); 100 (*bpp)->b_bcount, (long long)offset, (int)rv);
99 else 101 else
100 return (0); 102 return (0);
101} 103}
102 104
103void 105void
104brelse(struct buf *bp) 106brelse(struct buf *bp, int u1 __unused)
105{ 107{
106 108
107 assert (bp != NULL); 109 assert (bp != NULL);
108 assert (bp->b_data != NULL); 110 assert (bp->b_data != NULL);
109 111
110 if (bp->b_lblkno < 0) { 112 if (bp->b_lblkno < 0) {
111 /* 113 /*
112 * XXX don't remove any buffers with negative logical block 114 * XXX don't remove any buffers with negative logical block
113 * numbers (lblkno), so that we retain the mapping 115 * numbers (lblkno), so that we retain the mapping
114 * of negative lblkno -> real blkno that ffs_balloc() 116 * of negative lblkno -> real blkno that ffs_balloc()
115 * sets up. 117 * sets up.
116 * 118 *
117 * if we instead released these buffers, and implemented 119 * if we instead released these buffers, and implemented
118 * ufs_strategy() (and ufs_bmaparray()) and called those 120 * ufs_strategy() (and ufs_bmaparray()) and called those
119 * from bread() and bwrite() to convert the lblkno to 121 * from bread() and bwrite() to convert the lblkno to
120 * a real blkno, we'd add a lot more code & complexity 122 * a real blkno, we'd add a lot more code & complexity
121 * and reading off disk, for little gain, because this 123 * and reading off disk, for little gain, because this
122 * simple hack works for our purpose. 124 * simple hack works for our purpose.
123 */ 125 */
124 bp->b_bcount = 0; 126 bp->b_bcount = 0;
125 return; 127 return;
126 } 128 }
127  129
128 TAILQ_REMOVE(&buftail, bp, b_tailq); 130 TAILQ_REMOVE(&buftail, bp, b_tailq);
129 free(bp->b_data); 131 free(bp->b_data);
130 free(bp); 132 free(bp);
131} 133}
132 134
133int 135int
134bwrite(struct buf *bp) 136bwrite(struct buf *bp)
135{ 137{
136 off_t offset; 138 off_t offset;
137 ssize_t rv; 139 ssize_t rv;
138 140
139 assert (bp != NULL); 141 assert (bp != NULL);
140 offset = bp->b_blkno * sectorsize; /* XXX */ 142 offset = bp->b_blkno * sectorsize; /* XXX */
141 if (debug & DEBUG_BUF_BWRITE) 143 if (debug & DEBUG_BUF_BWRITE)
142 printf("bwrite: bp %p blkno %lld offset %lld bcount %ld\n", 144 printf("bwrite: bp %p blkno %lld offset %lld bcount %ld\n",
143 bp, (long long)bp->b_blkno, (long long) offset, 145 bp, (long long)bp->b_blkno, (long long) offset,
144 bp->b_bcount); 146 bp->b_bcount);
145 if (lseek(bp->b_fd, offset, SEEK_SET) == -1) 147 if (lseek(bp->b_fd, offset, SEEK_SET) == -1)
146 return (errno); 148 return (errno);
147 rv = write(bp->b_fd, bp->b_data, bp->b_bcount); 149 rv = write(bp->b_fd, bp->b_data, bp->b_bcount);
148 if (debug & DEBUG_BUF_BWRITE) 150 if (debug & DEBUG_BUF_BWRITE)
149 printf("bwrite: write %ld (offset %lld) returned %lld\n", 151 printf("bwrite: write %ld (offset %lld) returned %lld\n",
150 bp->b_bcount, (long long)offset, (long long)rv); 152 bp->b_bcount, (long long)offset, (long long)rv);
151 if (rv == bp->b_bcount) 153 if (rv == bp->b_bcount)
152 return (0); 154 return (0);
153 else if (rv == -1) /* write error */ 155 else if (rv == -1) /* write error */
154 return (errno); 156 return (errno);
155 else /* short write ? */ 157 else /* short write ? */
156 return (EAGAIN); 158 return (EAGAIN);
157} 159}
158 160
159void 161void
160bcleanup(void) 162bcleanup(void)
161{ 163{
162 struct buf *bp; 164 struct buf *bp;
163 165
164 /* 166 /*
165 * XXX this really shouldn't be necessary, but i'm curious to 167 * XXX this really shouldn't be necessary, but i'm curious to
166 * know why there's still some buffers lying around that 168 * know why there's still some buffers lying around that
167 * aren't brelse()d 169 * aren't brelse()d
168 */ 170 */
169  171
170 if (TAILQ_EMPTY(&buftail)) 172 if (TAILQ_EMPTY(&buftail))
171 return; 173 return;
172 174
173 printf("bcleanup: unflushed buffers:\n"); 175 printf("bcleanup: unflushed buffers:\n");
174 TAILQ_FOREACH(bp, &buftail, b_tailq) { 176 TAILQ_FOREACH(bp, &buftail, b_tailq) {
175 printf("\tlblkno %10lld blkno %10lld count %6ld bufsize %6ld\n", 177 printf("\tlblkno %10lld blkno %10lld count %6ld bufsize %6ld\n",
176 (long long)bp->b_lblkno, (long long)bp->b_blkno, 178 (long long)bp->b_lblkno, (long long)bp->b_blkno,
177 bp->b_bcount, bp->b_bufsize); 179 bp->b_bcount, bp->b_bufsize);
178 } 180 }
179 printf("bcleanup: done\n"); 181 printf("bcleanup: done\n");
180} 182}
181 183
182struct buf * 184struct buf *
183getblk(int fd, struct fs *fs, daddr_t blkno, int size) 185getblk(struct vnode *vp, daddr_t blkno, int size, int u1 __unused,
 186 int u2 __unused)
184{ 187{
185 static int buftailinitted; 188 static int buftailinitted;
186 struct buf *bp; 189 struct buf *bp;
187 void *n; 190 void *n;
 191 int fd = vp->fd;
 192 struct fs *fs = vp->fs;
188 193
 194 blkno += vp->offset;
189 assert (fs != NULL); 195 assert (fs != NULL);
190 if (debug & DEBUG_BUF_GETBLK) 196 if (debug & DEBUG_BUF_GETBLK)
191 printf("getblk: fs %p blkno %lld size %d\n", fs, 197 printf("getblk: fs %p blkno %lld size %d\n", fs,
192 (long long)blkno, size); 198 (long long)blkno, size);
193 199
194 bp = NULL; 200 bp = NULL;
195 if (!buftailinitted) { 201 if (!buftailinitted) {
196 if (debug & DEBUG_BUF_GETBLK) 202 if (debug & DEBUG_BUF_GETBLK)
197 printf("getblk: initialising tailq\n"); 203 printf("getblk: initialising tailq\n");
198 TAILQ_INIT(&buftail); 204 TAILQ_INIT(&buftail);
199 buftailinitted = 1; 205 buftailinitted = 1;
200 } else { 206 } else {
201 TAILQ_FOREACH(bp, &buftail, b_tailq) { 207 TAILQ_FOREACH(bp, &buftail, b_tailq) {
202 if (bp->b_lblkno != blkno) 208 if (bp->b_lblkno != blkno)
203 continue; 209 continue;
204 break; 210 break;
205 } 211 }
206 } 212 }
207 if (bp == NULL) { 213 if (bp == NULL) {
208 if ((bp = calloc(1, sizeof(struct buf))) == NULL) 214 if ((bp = calloc(1, sizeof(struct buf))) == NULL)
209 err(1, "getblk: calloc"); 215 err(1, "getblk: calloc");
210  216
211 bp->b_bufsize = 0; 217 bp->b_bufsize = 0;
212 bp->b_blkno = bp->b_lblkno = blkno; 218 bp->b_blkno = bp->b_lblkno = blkno;
213 bp->b_fd = fd; 219 bp->b_fd = fd;
214 bp->b_fs = fs; 220 bp->b_fs = fs;
215 bp->b_data = NULL; 221 bp->b_data = NULL;
216 TAILQ_INSERT_HEAD(&buftail, bp, b_tailq); 222 TAILQ_INSERT_HEAD(&buftail, bp, b_tailq);
217 } 223 }
218 bp->b_bcount = size; 224 bp->b_bcount = size;
219 if (bp->b_data == NULL || bp->b_bcount > bp->b_bufsize) { 225 if (bp->b_data == NULL || bp->b_bcount > bp->b_bufsize) {
220 n = realloc(bp->b_data, size); 226 n = realloc(bp->b_data, size);
221 if (n == NULL) 227 if (n == NULL)
222 err(1, "getblk: realloc b_data %ld", bp->b_bcount); 228 err(1, "getblk: realloc b_data %ld", bp->b_bcount);
223 bp->b_data = n; 229 bp->b_data = n;
224 bp->b_bufsize = size; 230 bp->b_bufsize = size;
225 } 231 }
226 232
227 return (bp); 233 return (bp);
228} 234}

cvs diff -r1.2 -r1.3 src/usr.sbin/makefs/ffs/buf.h (switch to unified diff)

--- src/usr.sbin/makefs/ffs/buf.h 2001/11/02 03:12:49 1.2
+++ src/usr.sbin/makefs/ffs/buf.h 2013/01/26 00:19:39 1.3
@@ -1,65 +1,116 @@ @@ -1,65 +1,116 @@
1/* $NetBSD: buf.h,v 1.2 2001/11/02 03:12:49 lukem Exp $ */ 1/* $NetBSD: buf.h,v 1.3 2013/01/26 00:19:39 christos Exp $ */
2 2
3/* 3/*
4 * Copyright (c) 2001 Wasabi Systems, Inc. 4 * Copyright (c) 2001 Wasabi Systems, Inc.
5 * All rights reserved. 5 * All rights reserved.
6 * 6 *
7 * Written by Luke Mewburn for Wasabi Systems, Inc. 7 * Written by Luke Mewburn for Wasabi Systems, Inc.
8 * 8 *
9 * Redistribution and use in source and binary forms, with or without 9 * Redistribution and use in source and binary forms, with or without
10 * modification, are permitted provided that the following conditions 10 * modification, are permitted provided that the following conditions
11 * are met: 11 * are met:
12 * 1. Redistributions of source code must retain the above copyright 12 * 1. Redistributions of source code must retain the above copyright
13 * notice, this list of conditions and the following disclaimer. 13 * notice, this list of conditions and the following disclaimer.
14 * 2. Redistributions in binary form must reproduce the above copyright 14 * 2. Redistributions in binary form must reproduce the above copyright
15 * notice, this list of conditions and the following disclaimer in the 15 * notice, this list of conditions and the following disclaimer in the
16 * documentation and/or other materials provided with the distribution. 16 * documentation and/or other materials provided with the distribution.
17 * 3. All advertising materials mentioning features or use of this software 17 * 3. All advertising materials mentioning features or use of this software
18 * must display the following acknowledgement: 18 * must display the following acknowledgement:
19 * This product includes software developed for the NetBSD Project by 19 * This product includes software developed for the NetBSD Project by
20 * Wasabi Systems, Inc. 20 * Wasabi Systems, Inc.
21 * 4. The name of Wasabi Systems, Inc. may not be used to endorse 21 * 4. The name of Wasabi Systems, Inc. may not be used to endorse
22 * or promote products derived from this software without specific prior 22 * or promote products derived from this software without specific prior
23 * written permission. 23 * written permission.
24 * 24 *
25 * THIS SOFTWARE IS PROVIDED BY WASABI SYSTEMS, INC. ``AS IS'' AND 25 * THIS SOFTWARE IS PROVIDED BY WASABI SYSTEMS, INC. ``AS IS'' AND
26 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 26 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
27 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 27 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
28 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL WASABI SYSTEMS, INC 28 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL WASABI SYSTEMS, INC
29 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 29 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
30 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 30 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
31 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 31 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
32 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 32 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
33 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 33 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
34 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 34 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
35 * POSSIBILITY OF SUCH DAMAGE. 35 * POSSIBILITY OF SUCH DAMAGE.
36 */ 36 */
37 37
38#ifndef _FFS_BUF_H 38#ifndef _FFS_BUF_H
39#define _FFS_BUF_H 39#define _FFS_BUF_H
40 40
41#include <sys/param.h> 41#include <sys/param.h>
42#include <sys/queue.h> 42#include <sys/queue.h>
43 43
 44#include <stdio.h>
 45#include <string.h>
 46#include <errno.h>
 47#include <time.h>
 48#include <stddef.h>
 49#include <stdlib.h>
 50#include <err.h>
 51
 52struct componentname {
 53 char *cn_nameptr;
 54 size_t cn_namelen;
 55};
 56
 57struct vnode {
 58 int fd;
 59 void *fs;
 60 void *v_data;
 61 int offset;
 62};
 63
 64#define vput(a) ((void)(a))
 65
44struct buf { 66struct buf {
45 void * b_data; 67 void * b_data;
46 long b_bufsize; 68 long b_bufsize;
47 long b_bcount; 69 long b_bcount;
48 daddr_t b_blkno; 70 daddr_t b_blkno;
49 daddr_t b_lblkno; 71 daddr_t b_lblkno;
50 int b_fd; 72 int b_fd;
51 struct fs * b_fs; 73 struct fs * b_fs;
52 74
53 TAILQ_ENTRY(buf) b_tailq; 75 TAILQ_ENTRY(buf) b_tailq;
54}; 76};
55 77
56void bcleanup(void); 78void bcleanup(void);
57int bread(int, struct fs *, daddr_t, int, struct buf **); 79int bread(struct vnode *, daddr_t, int, struct kauth_cred *,
58void brelse(struct buf *); 80 int, struct buf **);
 81void brelse(struct buf *, int);
59int bwrite(struct buf *); 82int bwrite(struct buf *);
60struct buf * getblk(int, struct fs *, daddr_t, int); 83struct buf * getblk(struct vnode *, daddr_t, int, int, int);
61 84
62#define bdwrite(bp) bwrite(bp) 85#define bdwrite(bp) bwrite(bp)
63#define clrbuf(bp) memset((bp)->b_data, 0, (u_int)(bp)->b_bcount) 86#define clrbuf(bp) memset((bp)->b_data, 0, (u_int)(bp)->b_bcount)
64 87
 88#define B_MODIFY 0
 89#define BC_AGE 0
 90
 91#define min(a, b) MIN((a), (b))
 92#define microtime(tv) gettimeofday((tv), NULL)
 93#define KASSERT(a)
 94#define IO_SYNC 1
 95
 96struct pool {
 97 size_t size;
 98};
 99
 100#define pool_init(p, s, a1, a2, a3, a4, a5, a6) (p)->size = (s)
 101#define pool_get(p, f) malloc((p)->size)
 102#define pool_put(p, a) free(a)
 103#define pool_destroy(p)
 104
 105#define MALLOC_DECLARE(a)
 106#define malloc_type_attach(a)
 107#define malloc_type_detach(a)
 108
 109#define mutex_enter(m)
 110#define mutex_exit(m)
 111#define mutex_init(m, t, i)
 112#define mutex_destroy(m)
 113
 114#define desiredvnodes 10000
 115
65#endif /* _FFS_BUF_H */ 116#endif /* _FFS_BUF_H */

cvs diff -r1.20 -r1.21 src/usr.sbin/makefs/ffs/ffs_alloc.c (switch to unified diff)

--- src/usr.sbin/makefs/ffs/ffs_alloc.c 2013/01/22 09:39:19 1.20
+++ src/usr.sbin/makefs/ffs/ffs_alloc.c 2013/01/26 00:19:39 1.21
@@ -1,598 +1,600 @@ @@ -1,598 +1,600 @@
1/* $NetBSD: ffs_alloc.c,v 1.20 2013/01/22 09:39:19 dholland Exp $ */ 1/* $NetBSD: ffs_alloc.c,v 1.21 2013/01/26 00:19:39 christos Exp $ */
2/* From: NetBSD: ffs_alloc.c,v 1.50 2001/09/06 02:16:01 lukem Exp */ 2/* From: NetBSD: ffs_alloc.c,v 1.50 2001/09/06 02:16:01 lukem Exp */
3 3
4/* 4/*
5 * Copyright (c) 2002 Networks Associates Technology, Inc. 5 * Copyright (c) 2002 Networks Associates Technology, Inc.
6 * All rights reserved. 6 * All rights reserved.
7 * 7 *
8 * This software was developed for the FreeBSD Project by Marshall 8 * This software was developed for the FreeBSD Project by Marshall
9 * Kirk McKusick and Network Associates Laboratories, the Security 9 * Kirk McKusick and Network Associates Laboratories, the Security
10 * Research Division of Network Associates, Inc. under DARPA/SPAWAR 10 * Research Division of Network Associates, Inc. under DARPA/SPAWAR
11 * contract N66001-01-C-8035 ("CBOSS"), as part of the DARPA CHATS 11 * contract N66001-01-C-8035 ("CBOSS"), as part of the DARPA CHATS
12 * research program 12 * research program
13 * 13 *
14 * Copyright (c) 1982, 1986, 1989, 1993 14 * Copyright (c) 1982, 1986, 1989, 1993
15 * The Regents of the University of California. All rights reserved. 15 * The Regents of the University of California. All rights reserved.
16 * 16 *
17 * Redistribution and use in source and binary forms, with or without 17 * Redistribution and use in source and binary forms, with or without
18 * modification, are permitted provided that the following conditions 18 * modification, are permitted provided that the following conditions
19 * are met: 19 * are met:
20 * 1. Redistributions of source code must retain the above copyright 20 * 1. Redistributions of source code must retain the above copyright
21 * notice, this list of conditions and the following disclaimer. 21 * notice, this list of conditions and the following disclaimer.
22 * 2. Redistributions in binary form must reproduce the above copyright 22 * 2. Redistributions in binary form must reproduce the above copyright
23 * notice, this list of conditions and the following disclaimer in the 23 * notice, this list of conditions and the following disclaimer in the
24 * documentation and/or other materials provided with the distribution. 24 * documentation and/or other materials provided with the distribution.
25 * 3. Neither the name of the University nor the names of its contributors 25 * 3. Neither the name of the University nor the names of its contributors
26 * may be used to endorse or promote products derived from this software 26 * may be used to endorse or promote products derived from this software
27 * without specific prior written permission. 27 * without specific prior written permission.
28 * 28 *
29 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 29 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
30 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 30 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
31 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 31 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
32 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 32 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
33 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 33 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
34 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 34 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
35 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 35 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
36 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 36 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
37 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 37 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
38 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 38 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
39 * SUCH DAMAGE. 39 * SUCH DAMAGE.
40 * 40 *
41 * @(#)ffs_alloc.c 8.19 (Berkeley) 7/13/95 41 * @(#)ffs_alloc.c 8.19 (Berkeley) 7/13/95
42 */ 42 */
43 43
44#if HAVE_NBTOOL_CONFIG_H 44#if HAVE_NBTOOL_CONFIG_H
45#include "nbtool_config.h" 45#include "nbtool_config.h"
46#endif 46#endif
47 47
48#include <sys/cdefs.h> 48#include <sys/cdefs.h>
49#if defined(__RCSID) && !defined(__lint) 49#if defined(__RCSID) && !defined(__lint)
50__RCSID("$NetBSD: ffs_alloc.c,v 1.20 2013/01/22 09:39:19 dholland Exp $"); 50__RCSID("$NetBSD: ffs_alloc.c,v 1.21 2013/01/26 00:19:39 christos Exp $");
51#endif /* !__lint */ 51#endif /* !__lint */
52 52
53#include <sys/param.h> 53#include <sys/param.h>
54#include <sys/time.h> 54#include <sys/time.h>
55 55
56#include <errno.h> 56#include <errno.h>
57 57
58#include "makefs.h" 58#include "makefs.h"
59 59
60#include <ufs/ufs/dinode.h> 60#include <ufs/ufs/dinode.h>
61#include <ufs/ufs/ufs_bswap.h> 61#include <ufs/ufs/ufs_bswap.h>
62#include <ufs/ffs/fs.h> 62#include <ufs/ffs/fs.h>
63 63
64#include "ffs/buf.h" 64#include "ffs/buf.h"
65#include "ffs/ufs_inode.h" 65#include "ffs/ufs_inode.h"
66#include "ffs/ffs_extern.h" 66#include "ffs/ffs_extern.h"
67 67
68 68
69static int scanc(u_int, const u_char *, const u_char *, int); 69static int scanc(u_int, const u_char *, const u_char *, int);
70 70
71static daddr_t ffs_alloccg(struct inode *, int, daddr_t, int); 71static daddr_t ffs_alloccg(struct inode *, int, daddr_t, int);
72static daddr_t ffs_alloccgblk(struct inode *, struct buf *, daddr_t); 72static daddr_t ffs_alloccgblk(struct inode *, struct buf *, daddr_t);
73static daddr_t ffs_hashalloc(struct inode *, int, daddr_t, int, 73static daddr_t ffs_hashalloc(struct inode *, int, daddr_t, int,
74 daddr_t (*)(struct inode *, int, daddr_t, int)); 74 daddr_t (*)(struct inode *, int, daddr_t, int));
75static int32_t ffs_mapsearch(struct fs *, struct cg *, daddr_t, int); 75static int32_t ffs_mapsearch(struct fs *, struct cg *, daddr_t, int);
76 76
77/* in ffs_tables.c */ 77/* in ffs_tables.c */
78extern const int inside[], around[]; 78extern const int inside[], around[];
79extern const u_char * const fragtbl[]; 79extern const u_char * const fragtbl[];
80 80
81/* 81/*
82 * Allocate a block in the file system. 82 * Allocate a block in the file system.
83 *  83 *
84 * The size of the requested block is given, which must be some 84 * The size of the requested block is given, which must be some
85 * multiple of fs_fsize and <= fs_bsize. 85 * multiple of fs_fsize and <= fs_bsize.
86 * A preference may be optionally specified. If a preference is given 86 * A preference may be optionally specified. If a preference is given
87 * the following hierarchy is used to allocate a block: 87 * the following hierarchy is used to allocate a block:
88 * 1) allocate the requested block. 88 * 1) allocate the requested block.
89 * 2) allocate a rotationally optimal block in the same cylinder. 89 * 2) allocate a rotationally optimal block in the same cylinder.
90 * 3) allocate a block in the same cylinder group. 90 * 3) allocate a block in the same cylinder group.
91 * 4) quadradically rehash into other cylinder groups, until an 91 * 4) quadradically rehash into other cylinder groups, until an
92 * available block is located. 92 * available block is located.
93 * If no block preference is given the following hierarchy is used 93 * If no block preference is given the following hierarchy is used
94 * to allocate a block: 94 * to allocate a block:
95 * 1) allocate a block in the cylinder group that contains the 95 * 1) allocate a block in the cylinder group that contains the
96 * inode for the file. 96 * inode for the file.
97 * 2) quadradically rehash into other cylinder groups, until an 97 * 2) quadradically rehash into other cylinder groups, until an
98 * available block is located. 98 * available block is located.
99 */ 99 */
100int 100int
101ffs_alloc(struct inode *ip, daddr_t lbn __unused, daddr_t bpref, int size, 101ffs_alloc(struct inode *ip, daddr_t lbn __unused, daddr_t bpref, int size,
102 daddr_t *bnp) 102 daddr_t *bnp)
103{ 103{
104 struct fs *fs = ip->i_fs; 104 struct fs *fs = ip->i_fs;
105 daddr_t bno; 105 daddr_t bno;
106 int cg; 106 int cg;
107  107
108 *bnp = 0; 108 *bnp = 0;
109 if (size > fs->fs_bsize || fragoff(fs, size) != 0) { 109 if (size > fs->fs_bsize || fragoff(fs, size) != 0) {
110 errx(1, "ffs_alloc: bad size: bsize %d size %d", 110 errx(1, "ffs_alloc: bad size: bsize %d size %d",
111 fs->fs_bsize, size); 111 fs->fs_bsize, size);
112 } 112 }
113 if (size == fs->fs_bsize && fs->fs_cstotal.cs_nbfree == 0) 113 if (size == fs->fs_bsize && fs->fs_cstotal.cs_nbfree == 0)
114 goto nospace; 114 goto nospace;
115 if (bpref >= fs->fs_size) 115 if (bpref >= fs->fs_size)
116 bpref = 0; 116 bpref = 0;
117 if (bpref == 0) 117 if (bpref == 0)
118 cg = ino_to_cg(fs, ip->i_number); 118 cg = ino_to_cg(fs, ip->i_number);
119 else 119 else
120 cg = dtog(fs, bpref); 120 cg = dtog(fs, bpref);
121 bno = ffs_hashalloc(ip, cg, bpref, size, ffs_alloccg); 121 bno = ffs_hashalloc(ip, cg, bpref, size, ffs_alloccg);
122 if (bno > 0) { 122 if (bno > 0) {
123 DIP_ADD(ip, blocks, size / DEV_BSIZE); 123 DIP_ADD(ip, blocks, size / DEV_BSIZE);
124 *bnp = bno; 124 *bnp = bno;
125 return (0); 125 return (0);
126 } 126 }
127nospace: 127nospace:
128 return (ENOSPC); 128 return (ENOSPC);
129} 129}
130 130
131/* 131/*
132 * Select the desired position for the next block in a file. The file is 132 * Select the desired position for the next block in a file. The file is
133 * logically divided into sections. The first section is composed of the 133 * logically divided into sections. The first section is composed of the
134 * direct blocks. Each additional section contains fs_maxbpg blocks. 134 * direct blocks. Each additional section contains fs_maxbpg blocks.
135 *  135 *
136 * If no blocks have been allocated in the first section, the policy is to 136 * If no blocks have been allocated in the first section, the policy is to
137 * request a block in the same cylinder group as the inode that describes 137 * request a block in the same cylinder group as the inode that describes
138 * the file. If no blocks have been allocated in any other section, the 138 * the file. If no blocks have been allocated in any other section, the
139 * policy is to place the section in a cylinder group with a greater than 139 * policy is to place the section in a cylinder group with a greater than
140 * average number of free blocks. An appropriate cylinder group is found 140 * average number of free blocks. An appropriate cylinder group is found
141 * by using a rotor that sweeps the cylinder groups. When a new group of 141 * by using a rotor that sweeps the cylinder groups. When a new group of
142 * blocks is needed, the sweep begins in the cylinder group following the 142 * blocks is needed, the sweep begins in the cylinder group following the
143 * cylinder group from which the previous allocation was made. The sweep 143 * cylinder group from which the previous allocation was made. The sweep
144 * continues until a cylinder group with greater than the average number 144 * continues until a cylinder group with greater than the average number
145 * of free blocks is found. If the allocation is for the first block in an 145 * of free blocks is found. If the allocation is for the first block in an
146 * indirect block, the information on the previous allocation is unavailable; 146 * indirect block, the information on the previous allocation is unavailable;
147 * here a best guess is made based upon the logical block number being 147 * here a best guess is made based upon the logical block number being
148 * allocated. 148 * allocated.
149 *  149 *
150 * If a section is already partially allocated, the policy is to 150 * If a section is already partially allocated, the policy is to
151 * contiguously allocate fs_maxcontig blocks. The end of one of these 151 * contiguously allocate fs_maxcontig blocks. The end of one of these
152 * contiguous blocks and the beginning of the next is physically separated 152 * contiguous blocks and the beginning of the next is physically separated
153 * so that the disk head will be in transit between them for at least 153 * so that the disk head will be in transit between them for at least
154 * fs_rotdelay milliseconds. This is to allow time for the processor to 154 * fs_rotdelay milliseconds. This is to allow time for the processor to
155 * schedule another I/O transfer. 155 * schedule another I/O transfer.
156 */ 156 */
157/* XXX ondisk32 */ 157/* XXX ondisk32 */
158daddr_t 158daddr_t
159ffs_blkpref_ufs1(struct inode *ip, daddr_t lbn, int indx, int32_t *bap) 159ffs_blkpref_ufs1(struct inode *ip, daddr_t lbn, int indx, int32_t *bap)
160{ 160{
161 struct fs *fs; 161 struct fs *fs;
162 int cg; 162 int cg;
163 int avgbfree, startcg; 163 int avgbfree, startcg;
164 164
165 fs = ip->i_fs; 165 fs = ip->i_fs;
166 if (indx % fs->fs_maxbpg == 0 || bap[indx - 1] == 0) { 166 if (indx % fs->fs_maxbpg == 0 || bap[indx - 1] == 0) {
167 if (lbn < UFS_NDADDR + NINDIR(fs)) { 167 if (lbn < UFS_NDADDR + NINDIR(fs)) {
168 cg = ino_to_cg(fs, ip->i_number); 168 cg = ino_to_cg(fs, ip->i_number);
169 return (fs->fs_fpg * cg + fs->fs_frag); 169 return (fs->fs_fpg * cg + fs->fs_frag);
170 } 170 }
171 /* 171 /*
172 * Find a cylinder with greater than average number of 172 * Find a cylinder with greater than average number of
173 * unused data blocks. 173 * unused data blocks.
174 */ 174 */
175 if (indx == 0 || bap[indx - 1] == 0) 175 if (indx == 0 || bap[indx - 1] == 0)
176 startcg = 176 startcg =
177 ino_to_cg(fs, ip->i_number) + lbn / fs->fs_maxbpg; 177 ino_to_cg(fs, ip->i_number) + lbn / fs->fs_maxbpg;
178 else 178 else
179 startcg = dtog(fs, 179 startcg = dtog(fs,
180 ufs_rw32(bap[indx - 1], UFS_FSNEEDSWAP(fs)) + 1); 180 ufs_rw32(bap[indx - 1], UFS_FSNEEDSWAP(fs)) + 1);
181 startcg %= fs->fs_ncg; 181 startcg %= fs->fs_ncg;
182 avgbfree = fs->fs_cstotal.cs_nbfree / fs->fs_ncg; 182 avgbfree = fs->fs_cstotal.cs_nbfree / fs->fs_ncg;
183 for (cg = startcg; cg < fs->fs_ncg; cg++) 183 for (cg = startcg; cg < fs->fs_ncg; cg++)
184 if (fs->fs_cs(fs, cg).cs_nbfree >= avgbfree) 184 if (fs->fs_cs(fs, cg).cs_nbfree >= avgbfree)
185 return (fs->fs_fpg * cg + fs->fs_frag); 185 return (fs->fs_fpg * cg + fs->fs_frag);
186 for (cg = 0; cg <= startcg; cg++) 186 for (cg = 0; cg <= startcg; cg++)
187 if (fs->fs_cs(fs, cg).cs_nbfree >= avgbfree) 187 if (fs->fs_cs(fs, cg).cs_nbfree >= avgbfree)
188 return (fs->fs_fpg * cg + fs->fs_frag); 188 return (fs->fs_fpg * cg + fs->fs_frag);
189 return (0); 189 return (0);
190 } 190 }
191 /* 191 /*
192 * We just always try to lay things out contiguously. 192 * We just always try to lay things out contiguously.
193 */ 193 */
194 return ufs_rw32(bap[indx - 1], UFS_FSNEEDSWAP(fs)) + fs->fs_frag; 194 return ufs_rw32(bap[indx - 1], UFS_FSNEEDSWAP(fs)) + fs->fs_frag;
195} 195}
196 196
197daddr_t 197daddr_t
198ffs_blkpref_ufs2(struct inode *ip, daddr_t lbn, int indx, int64_t *bap) 198ffs_blkpref_ufs2(struct inode *ip, daddr_t lbn, int indx, int64_t *bap)
199{ 199{
200 struct fs *fs; 200 struct fs *fs;
201 int cg; 201 int cg;
202 int avgbfree, startcg; 202 int avgbfree, startcg;
203 203
204 fs = ip->i_fs; 204 fs = ip->i_fs;
205 if (indx % fs->fs_maxbpg == 0 || bap[indx - 1] == 0) { 205 if (indx % fs->fs_maxbpg == 0 || bap[indx - 1] == 0) {
206 if (lbn < UFS_NDADDR + NINDIR(fs)) { 206 if (lbn < UFS_NDADDR + NINDIR(fs)) {
207 cg = ino_to_cg(fs, ip->i_number); 207 cg = ino_to_cg(fs, ip->i_number);
208 return (fs->fs_fpg * cg + fs->fs_frag); 208 return (fs->fs_fpg * cg + fs->fs_frag);
209 } 209 }
210 /* 210 /*
211 * Find a cylinder with greater than average number of 211 * Find a cylinder with greater than average number of
212 * unused data blocks. 212 * unused data blocks.
213 */ 213 */
214 if (indx == 0 || bap[indx - 1] == 0) 214 if (indx == 0 || bap[indx - 1] == 0)
215 startcg = 215 startcg =
216 ino_to_cg(fs, ip->i_number) + lbn / fs->fs_maxbpg; 216 ino_to_cg(fs, ip->i_number) + lbn / fs->fs_maxbpg;
217 else 217 else
218 startcg = dtog(fs, 218 startcg = dtog(fs,
219 ufs_rw64(bap[indx - 1], UFS_FSNEEDSWAP(fs)) + 1); 219 ufs_rw64(bap[indx - 1], UFS_FSNEEDSWAP(fs)) + 1);
220 startcg %= fs->fs_ncg; 220 startcg %= fs->fs_ncg;
221 avgbfree = fs->fs_cstotal.cs_nbfree / fs->fs_ncg; 221 avgbfree = fs->fs_cstotal.cs_nbfree / fs->fs_ncg;
222 for (cg = startcg; cg < fs->fs_ncg; cg++) 222 for (cg = startcg; cg < fs->fs_ncg; cg++)
223 if (fs->fs_cs(fs, cg).cs_nbfree >= avgbfree) { 223 if (fs->fs_cs(fs, cg).cs_nbfree >= avgbfree) {
224 return (fs->fs_fpg * cg + fs->fs_frag); 224 return (fs->fs_fpg * cg + fs->fs_frag);
225 } 225 }
226 for (cg = 0; cg < startcg; cg++) 226 for (cg = 0; cg < startcg; cg++)
227 if (fs->fs_cs(fs, cg).cs_nbfree >= avgbfree) { 227 if (fs->fs_cs(fs, cg).cs_nbfree >= avgbfree) {
228 return (fs->fs_fpg * cg + fs->fs_frag); 228 return (fs->fs_fpg * cg + fs->fs_frag);
229 } 229 }
230 return (0); 230 return (0);
231 } 231 }
232 /* 232 /*
233 * We just always try to lay things out contiguously. 233 * We just always try to lay things out contiguously.
234 */ 234 */
235 return ufs_rw64(bap[indx - 1], UFS_FSNEEDSWAP(fs)) + fs->fs_frag; 235 return ufs_rw64(bap[indx - 1], UFS_FSNEEDSWAP(fs)) + fs->fs_frag;
236} 236}
237 237
238/* 238/*
239 * Implement the cylinder overflow algorithm. 239 * Implement the cylinder overflow algorithm.
240 * 240 *
241 * The policy implemented by this algorithm is: 241 * The policy implemented by this algorithm is:
242 * 1) allocate the block in its requested cylinder group. 242 * 1) allocate the block in its requested cylinder group.
243 * 2) quadradically rehash on the cylinder group number. 243 * 2) quadradically rehash on the cylinder group number.
244 * 3) brute force search for a free block. 244 * 3) brute force search for a free block.
245 * 245 *
246 * `size': size for data blocks, mode for inodes 246 * `size': size for data blocks, mode for inodes
247 */ 247 */
248/*VARARGS5*/ 248/*VARARGS5*/
249static daddr_t 249static daddr_t
250ffs_hashalloc(struct inode *ip, int cg, daddr_t pref, int size, 250ffs_hashalloc(struct inode *ip, int cg, daddr_t pref, int size,
251 daddr_t (*allocator)(struct inode *, int, daddr_t, int)) 251 daddr_t (*allocator)(struct inode *, int, daddr_t, int))
252{ 252{
253 struct fs *fs; 253 struct fs *fs;
254 daddr_t result; 254 daddr_t result;
255 int i, icg = cg; 255 int i, icg = cg;
256 256
257 fs = ip->i_fs; 257 fs = ip->i_fs;
258 /* 258 /*
259 * 1: preferred cylinder group 259 * 1: preferred cylinder group
260 */ 260 */
261 result = (*allocator)(ip, cg, pref, size); 261 result = (*allocator)(ip, cg, pref, size);
262 if (result) 262 if (result)
263 return (result); 263 return (result);
264 /* 264 /*
265 * 2: quadratic rehash 265 * 2: quadratic rehash
266 */ 266 */
267 for (i = 1; i < fs->fs_ncg; i *= 2) { 267 for (i = 1; i < fs->fs_ncg; i *= 2) {
268 cg += i; 268 cg += i;
269 if (cg >= fs->fs_ncg) 269 if (cg >= fs->fs_ncg)
270 cg -= fs->fs_ncg; 270 cg -= fs->fs_ncg;
271 result = (*allocator)(ip, cg, 0, size); 271 result = (*allocator)(ip, cg, 0, size);
272 if (result) 272 if (result)
273 return (result); 273 return (result);
274 } 274 }
275 /* 275 /*
276 * 3: brute force search 276 * 3: brute force search
277 * Note that we start at i == 2, since 0 was checked initially, 277 * Note that we start at i == 2, since 0 was checked initially,
278 * and 1 is always checked in the quadratic rehash. 278 * and 1 is always checked in the quadratic rehash.
279 */ 279 */
280 cg = (icg + 2) % fs->fs_ncg; 280 cg = (icg + 2) % fs->fs_ncg;
281 for (i = 2; i < fs->fs_ncg; i++) { 281 for (i = 2; i < fs->fs_ncg; i++) {
282 result = (*allocator)(ip, cg, 0, size); 282 result = (*allocator)(ip, cg, 0, size);
283 if (result) 283 if (result)
284 return (result); 284 return (result);
285 cg++; 285 cg++;
286 if (cg == fs->fs_ncg) 286 if (cg == fs->fs_ncg)
287 cg = 0; 287 cg = 0;
288 } 288 }
289 return (0); 289 return (0);
290} 290}
291 291
292/* 292/*
293 * Determine whether a block can be allocated. 293 * Determine whether a block can be allocated.
294 * 294 *
295 * Check to see if a block of the appropriate size is available, 295 * Check to see if a block of the appropriate size is available,
296 * and if it is, allocate it. 296 * and if it is, allocate it.
297 */ 297 */
298static daddr_t 298static daddr_t
299ffs_alloccg(struct inode *ip, int cg, daddr_t bpref, int size) 299ffs_alloccg(struct inode *ip, int cg, daddr_t bpref, int size)
300{ 300{
301 struct cg *cgp; 301 struct cg *cgp;
302 struct buf *bp; 302 struct buf *bp;
303 daddr_t bno, blkno; 303 daddr_t bno, blkno;
304 int error, frags, allocsiz, i; 304 int error, frags, allocsiz, i;
305 struct fs *fs = ip->i_fs; 305 struct fs *fs = ip->i_fs;
306 const int needswap = UFS_FSNEEDSWAP(fs); 306 const int needswap = UFS_FSNEEDSWAP(fs);
 307 struct vnode vp = { ip->i_fd, ip->i_fs, NULL, 0 };
307 308
308 if (fs->fs_cs(fs, cg).cs_nbfree == 0 && size == fs->fs_bsize) 309 if (fs->fs_cs(fs, cg).cs_nbfree == 0 && size == fs->fs_bsize)
309 return (0); 310 return (0);
310 error = bread(ip->i_fd, ip->i_fs, fsbtodb(fs, cgtod(fs, cg)), 311 error = bread(&vp, fsbtodb(fs, cgtod(fs, cg)), (int)fs->fs_cgsize,
311 (int)fs->fs_cgsize, &bp); 312 NULL, 0, &bp);
312 if (error) { 313 if (error) {
313 brelse(bp); 314 brelse(bp, 0);
314 return (0); 315 return (0);
315 } 316 }
316 cgp = (struct cg *)bp->b_data; 317 cgp = (struct cg *)bp->b_data;
317 if (!cg_chkmagic(cgp, needswap) || 318 if (!cg_chkmagic(cgp, needswap) ||
318 (cgp->cg_cs.cs_nbfree == 0 && size == fs->fs_bsize)) { 319 (cgp->cg_cs.cs_nbfree == 0 && size == fs->fs_bsize)) {
319 brelse(bp); 320 brelse(bp, 0);
320 return (0); 321 return (0);
321 } 322 }
322 if (size == fs->fs_bsize) { 323 if (size == fs->fs_bsize) {
323 bno = ffs_alloccgblk(ip, bp, bpref); 324 bno = ffs_alloccgblk(ip, bp, bpref);
324 bdwrite(bp); 325 bdwrite(bp);
325 return (bno); 326 return (bno);
326 } 327 }
327 /* 328 /*
328 * check to see if any fragments are already available 329 * check to see if any fragments are already available
329 * allocsiz is the size which will be allocated, hacking 330 * allocsiz is the size which will be allocated, hacking
330 * it down to a smaller size if necessary 331 * it down to a smaller size if necessary
331 */ 332 */
332 frags = numfrags(fs, size); 333 frags = numfrags(fs, size);
333 for (allocsiz = frags; allocsiz < fs->fs_frag; allocsiz++) 334 for (allocsiz = frags; allocsiz < fs->fs_frag; allocsiz++)
334 if (cgp->cg_frsum[allocsiz] != 0) 335 if (cgp->cg_frsum[allocsiz] != 0)
335 break; 336 break;
336 if (allocsiz == fs->fs_frag) { 337 if (allocsiz == fs->fs_frag) {
337 /* 338 /*
338 * no fragments were available, so a block will be  339 * no fragments were available, so a block will be
339 * allocated, and hacked up 340 * allocated, and hacked up
340 */ 341 */
341 if (cgp->cg_cs.cs_nbfree == 0) { 342 if (cgp->cg_cs.cs_nbfree == 0) {
342 brelse(bp); 343 brelse(bp, 0);
343 return (0); 344 return (0);
344 } 345 }
345 bno = ffs_alloccgblk(ip, bp, bpref); 346 bno = ffs_alloccgblk(ip, bp, bpref);
346 bpref = dtogd(fs, bno); 347 bpref = dtogd(fs, bno);
347 for (i = frags; i < fs->fs_frag; i++) 348 for (i = frags; i < fs->fs_frag; i++)
348 setbit(cg_blksfree(cgp, needswap), bpref + i); 349 setbit(cg_blksfree(cgp, needswap), bpref + i);
349 i = fs->fs_frag - frags; 350 i = fs->fs_frag - frags;
350 ufs_add32(cgp->cg_cs.cs_nffree, i, needswap); 351 ufs_add32(cgp->cg_cs.cs_nffree, i, needswap);
351 fs->fs_cstotal.cs_nffree += i; 352 fs->fs_cstotal.cs_nffree += i;
352 fs->fs_cs(fs, cg).cs_nffree += i; 353 fs->fs_cs(fs, cg).cs_nffree += i;
353 fs->fs_fmod = 1; 354 fs->fs_fmod = 1;
354 ufs_add32(cgp->cg_frsum[i], 1, needswap); 355 ufs_add32(cgp->cg_frsum[i], 1, needswap);
355 bdwrite(bp); 356 bdwrite(bp);
356 return (bno); 357 return (bno);
357 } 358 }
358 bno = ffs_mapsearch(fs, cgp, bpref, allocsiz); 359 bno = ffs_mapsearch(fs, cgp, bpref, allocsiz);
359 for (i = 0; i < frags; i++) 360 for (i = 0; i < frags; i++)
360 clrbit(cg_blksfree(cgp, needswap), bno + i); 361 clrbit(cg_blksfree(cgp, needswap), bno + i);
361 ufs_add32(cgp->cg_cs.cs_nffree, -frags, needswap); 362 ufs_add32(cgp->cg_cs.cs_nffree, -frags, needswap);
362 fs->fs_cstotal.cs_nffree -= frags; 363 fs->fs_cstotal.cs_nffree -= frags;
363 fs->fs_cs(fs, cg).cs_nffree -= frags; 364 fs->fs_cs(fs, cg).cs_nffree -= frags;
364 fs->fs_fmod = 1; 365 fs->fs_fmod = 1;
365 ufs_add32(cgp->cg_frsum[allocsiz], -1, needswap); 366 ufs_add32(cgp->cg_frsum[allocsiz], -1, needswap);
366 if (frags != allocsiz) 367 if (frags != allocsiz)
367 ufs_add32(cgp->cg_frsum[allocsiz - frags], 1, needswap); 368 ufs_add32(cgp->cg_frsum[allocsiz - frags], 1, needswap);
368 blkno = cg * fs->fs_fpg + bno; 369 blkno = cg * fs->fs_fpg + bno;
369 bdwrite(bp); 370 bdwrite(bp);
370 return blkno; 371 return blkno;
371} 372}
372 373
373/* 374/*
374 * Allocate a block in a cylinder group. 375 * Allocate a block in a cylinder group.
375 * 376 *
376 * This algorithm implements the following policy: 377 * This algorithm implements the following policy:
377 * 1) allocate the requested block. 378 * 1) allocate the requested block.
378 * 2) allocate a rotationally optimal block in the same cylinder. 379 * 2) allocate a rotationally optimal block in the same cylinder.
379 * 3) allocate the next available block on the block rotor for the 380 * 3) allocate the next available block on the block rotor for the
380 * specified cylinder group. 381 * specified cylinder group.
381 * Note that this routine only allocates fs_bsize blocks; these 382 * Note that this routine only allocates fs_bsize blocks; these
382 * blocks may be fragmented by the routine that allocates them. 383 * blocks may be fragmented by the routine that allocates them.
383 */ 384 */
384static daddr_t 385static daddr_t
385ffs_alloccgblk(struct inode *ip, struct buf *bp, daddr_t bpref) 386ffs_alloccgblk(struct inode *ip, struct buf *bp, daddr_t bpref)
386{ 387{
387 struct cg *cgp; 388 struct cg *cgp;
388 daddr_t blkno; 389 daddr_t blkno;
389 int32_t bno; 390 int32_t bno;
390 struct fs *fs = ip->i_fs; 391 struct fs *fs = ip->i_fs;
391 const int needswap = UFS_FSNEEDSWAP(fs); 392 const int needswap = UFS_FSNEEDSWAP(fs);
392 u_int8_t *blksfree; 393 u_int8_t *blksfree;
393 394
394 cgp = (struct cg *)bp->b_data; 395 cgp = (struct cg *)bp->b_data;
395 blksfree = cg_blksfree(cgp, needswap); 396 blksfree = cg_blksfree(cgp, needswap);
396 if (bpref == 0 || dtog(fs, bpref) != ufs_rw32(cgp->cg_cgx, needswap)) { 397 if (bpref == 0 || dtog(fs, bpref) != ufs_rw32(cgp->cg_cgx, needswap)) {
397 bpref = ufs_rw32(cgp->cg_rotor, needswap); 398 bpref = ufs_rw32(cgp->cg_rotor, needswap);
398 } else { 399 } else {
399 bpref = blknum(fs, bpref); 400 bpref = blknum(fs, bpref);
400 bno = dtogd(fs, bpref); 401 bno = dtogd(fs, bpref);
401 /* 402 /*
402 * if the requested block is available, use it 403 * if the requested block is available, use it
403 */ 404 */
404 if (ffs_isblock(fs, blksfree, fragstoblks(fs, bno))) 405 if (ffs_isblock(fs, blksfree, fragstoblks(fs, bno)))
405 goto gotit; 406 goto gotit;
406 } 407 }
407 /* 408 /*
408 * Take the next available one in this cylinder group. 409 * Take the next available one in this cylinder group.
409 */ 410 */
410 bno = ffs_mapsearch(fs, cgp, bpref, (int)fs->fs_frag); 411 bno = ffs_mapsearch(fs, cgp, bpref, (int)fs->fs_frag);
411 if (bno < 0) 412 if (bno < 0)
412 return (0); 413 return (0);
413 cgp->cg_rotor = ufs_rw32(bno, needswap); 414 cgp->cg_rotor = ufs_rw32(bno, needswap);
414gotit: 415gotit:
415 blkno = fragstoblks(fs, bno); 416 blkno = fragstoblks(fs, bno);
416 ffs_clrblock(fs, blksfree, (long)blkno); 417 ffs_clrblock(fs, blksfree, (long)blkno);
417 ffs_clusteracct(fs, cgp, blkno, -1); 418 ffs_clusteracct(fs, cgp, blkno, -1);
418 ufs_add32(cgp->cg_cs.cs_nbfree, -1, needswap); 419 ufs_add32(cgp->cg_cs.cs_nbfree, -1, needswap);
419 fs->fs_cstotal.cs_nbfree--; 420 fs->fs_cstotal.cs_nbfree--;
420 fs->fs_cs(fs, ufs_rw32(cgp->cg_cgx, needswap)).cs_nbfree--; 421 fs->fs_cs(fs, ufs_rw32(cgp->cg_cgx, needswap)).cs_nbfree--;
421 fs->fs_fmod = 1; 422 fs->fs_fmod = 1;
422 blkno = ufs_rw32(cgp->cg_cgx, needswap) * fs->fs_fpg + bno; 423 blkno = ufs_rw32(cgp->cg_cgx, needswap) * fs->fs_fpg + bno;
423 return (blkno); 424 return (blkno);
424} 425}
425 426
426/* 427/*
427 * Free a block or fragment. 428 * Free a block or fragment.
428 * 429 *
429 * The specified block or fragment is placed back in the 430 * The specified block or fragment is placed back in the
430 * free map. If a fragment is deallocated, a possible  431 * free map. If a fragment is deallocated, a possible
431 * block reassembly is checked. 432 * block reassembly is checked.
432 */ 433 */
433void 434void
434ffs_blkfree(struct inode *ip, daddr_t bno, long size) 435ffs_blkfree(struct inode *ip, daddr_t bno, long size)
435{ 436{
436 struct cg *cgp; 437 struct cg *cgp;
437 struct buf *bp; 438 struct buf *bp;
438 int32_t fragno, cgbno; 439 int32_t fragno, cgbno;
439 int i, error, cg, blk, frags, bbase; 440 int i, error, cg, blk, frags, bbase;
440 struct fs *fs = ip->i_fs; 441 struct fs *fs = ip->i_fs;
441 const int needswap = UFS_FSNEEDSWAP(fs); 442 const int needswap = UFS_FSNEEDSWAP(fs);
 443 struct vnode vp = { ip->i_fd, ip->i_fs, NULL, 0 };
442 444
443 if (size > fs->fs_bsize || fragoff(fs, size) != 0 || 445 if (size > fs->fs_bsize || fragoff(fs, size) != 0 ||
444 fragnum(fs, bno) + numfrags(fs, size) > fs->fs_frag) { 446 fragnum(fs, bno) + numfrags(fs, size) > fs->fs_frag) {
445 errx(1, "blkfree: bad size: bno %lld bsize %d size %ld", 447 errx(1, "blkfree: bad size: bno %lld bsize %d size %ld",
446 (long long)bno, fs->fs_bsize, size); 448 (long long)bno, fs->fs_bsize, size);
447 } 449 }
448 cg = dtog(fs, bno); 450 cg = dtog(fs, bno);
449 if (bno >= fs->fs_size) { 451 if (bno >= fs->fs_size) {
450 warnx("bad block %lld, ino %llu", (long long)bno, 452 warnx("bad block %lld, ino %llu", (long long)bno,
451 (unsigned long long)ip->i_number); 453 (unsigned long long)ip->i_number);
452 return; 454 return;
453 } 455 }
454 error = bread(ip->i_fd, ip->i_fs, fsbtodb(fs, cgtod(fs, cg)), 456 error = bread(&vp, fsbtodb(fs, cgtod(fs, cg)), (int)fs->fs_cgsize,
455 (int)fs->fs_cgsize, &bp); 457 NULL, 0, &bp);
456 if (error) { 458 if (error) {
457 brelse(bp); 459 brelse(bp, 0);
458 return; 460 return;
459 } 461 }
460 cgp = (struct cg *)bp->b_data; 462 cgp = (struct cg *)bp->b_data;
461 if (!cg_chkmagic(cgp, needswap)) { 463 if (!cg_chkmagic(cgp, needswap)) {
462 brelse(bp); 464 brelse(bp, 0);
463 return; 465 return;
464 } 466 }
465 cgbno = dtogd(fs, bno); 467 cgbno = dtogd(fs, bno);
466 if (size == fs->fs_bsize) { 468 if (size == fs->fs_bsize) {
467 fragno = fragstoblks(fs, cgbno); 469 fragno = fragstoblks(fs, cgbno);
468 if (!ffs_isfreeblock(fs, cg_blksfree(cgp, needswap), fragno)) { 470 if (!ffs_isfreeblock(fs, cg_blksfree(cgp, needswap), fragno)) {
469 errx(1, "blkfree: freeing free block %lld", 471 errx(1, "blkfree: freeing free block %lld",
470 (long long)bno); 472 (long long)bno);
471 } 473 }
472 ffs_setblock(fs, cg_blksfree(cgp, needswap), fragno); 474 ffs_setblock(fs, cg_blksfree(cgp, needswap), fragno);
473 ffs_clusteracct(fs, cgp, fragno, 1); 475 ffs_clusteracct(fs, cgp, fragno, 1);
474 ufs_add32(cgp->cg_cs.cs_nbfree, 1, needswap); 476 ufs_add32(cgp->cg_cs.cs_nbfree, 1, needswap);
475 fs->fs_cstotal.cs_nbfree++; 477 fs->fs_cstotal.cs_nbfree++;
476 fs->fs_cs(fs, cg).cs_nbfree++; 478 fs->fs_cs(fs, cg).cs_nbfree++;
477 } else { 479 } else {
478 bbase = cgbno - fragnum(fs, cgbno); 480 bbase = cgbno - fragnum(fs, cgbno);
479 /* 481 /*
480 * decrement the counts associated with the old frags 482 * decrement the counts associated with the old frags
481 */ 483 */
482 blk = blkmap(fs, cg_blksfree(cgp, needswap), bbase); 484 blk = blkmap(fs, cg_blksfree(cgp, needswap), bbase);
483 ffs_fragacct(fs, blk, cgp->cg_frsum, -1, needswap); 485 ffs_fragacct(fs, blk, cgp->cg_frsum, -1, needswap);
484 /* 486 /*
485 * deallocate the fragment 487 * deallocate the fragment
486 */ 488 */
487 frags = numfrags(fs, size); 489 frags = numfrags(fs, size);
488 for (i = 0; i < frags; i++) { 490 for (i = 0; i < frags; i++) {
489 if (isset(cg_blksfree(cgp, needswap), cgbno + i)) { 491 if (isset(cg_blksfree(cgp, needswap), cgbno + i)) {
490 errx(1, "blkfree: freeing free frag: block %lld", 492 errx(1, "blkfree: freeing free frag: block %lld",
491 (long long)(cgbno + i)); 493 (long long)(cgbno + i));
492 } 494 }
493 setbit(cg_blksfree(cgp, needswap), cgbno + i); 495 setbit(cg_blksfree(cgp, needswap), cgbno + i);
494 } 496 }
495 ufs_add32(cgp->cg_cs.cs_nffree, i, needswap); 497 ufs_add32(cgp->cg_cs.cs_nffree, i, needswap);
496 fs->fs_cstotal.cs_nffree += i; 498 fs->fs_cstotal.cs_nffree += i;
497 fs->fs_cs(fs, cg).cs_nffree += i; 499 fs->fs_cs(fs, cg).cs_nffree += i;
498 /* 500 /*
499 * add back in counts associated with the new frags 501 * add back in counts associated with the new frags
500 */ 502 */
501 blk = blkmap(fs, cg_blksfree(cgp, needswap), bbase); 503 blk = blkmap(fs, cg_blksfree(cgp, needswap), bbase);
502 ffs_fragacct(fs, blk, cgp->cg_frsum, 1, needswap); 504 ffs_fragacct(fs, blk, cgp->cg_frsum, 1, needswap);
503 /* 505 /*
504 * if a complete block has been reassembled, account for it 506 * if a complete block has been reassembled, account for it
505 */ 507 */
506 fragno = fragstoblks(fs, bbase); 508 fragno = fragstoblks(fs, bbase);
507 if (ffs_isblock(fs, cg_blksfree(cgp, needswap), fragno)) { 509 if (ffs_isblock(fs, cg_blksfree(cgp, needswap), fragno)) {
508 ufs_add32(cgp->cg_cs.cs_nffree, -fs->fs_frag, needswap); 510 ufs_add32(cgp->cg_cs.cs_nffree, -fs->fs_frag, needswap);
509 fs->fs_cstotal.cs_nffree -= fs->fs_frag; 511 fs->fs_cstotal.cs_nffree -= fs->fs_frag;
510 fs->fs_cs(fs, cg).cs_nffree -= fs->fs_frag; 512 fs->fs_cs(fs, cg).cs_nffree -= fs->fs_frag;
511 ffs_clusteracct(fs, cgp, fragno, 1); 513 ffs_clusteracct(fs, cgp, fragno, 1);
512 ufs_add32(cgp->cg_cs.cs_nbfree, 1, needswap); 514 ufs_add32(cgp->cg_cs.cs_nbfree, 1, needswap);
513 fs->fs_cstotal.cs_nbfree++; 515 fs->fs_cstotal.cs_nbfree++;
514 fs->fs_cs(fs, cg).cs_nbfree++; 516 fs->fs_cs(fs, cg).cs_nbfree++;
515 } 517 }
516 } 518 }
517 fs->fs_fmod = 1; 519 fs->fs_fmod = 1;
518 bdwrite(bp); 520 bdwrite(bp);
519} 521}
520 522
521 523
522static int 524static int
523scanc(u_int size, const u_char *cp, const u_char table[], int mask) 525scanc(u_int size, const u_char *cp, const u_char table[], int mask)
524{ 526{
525 const u_char *end = &cp[size]; 527 const u_char *end = &cp[size];
526 528
527 while (cp < end && (table[*cp] & mask) == 0) 529 while (cp < end && (table[*cp] & mask) == 0)
528 cp++; 530 cp++;
529 return (end - cp); 531 return (end - cp);
530} 532}
531 533
532/* 534/*
533 * Find a block of the specified size in the specified cylinder group. 535 * Find a block of the specified size in the specified cylinder group.
534 * 536 *
535 * It is a panic if a request is made to find a block if none are 537 * It is a panic if a request is made to find a block if none are
536 * available. 538 * available.
537 */ 539 */
538static int32_t 540static int32_t
539ffs_mapsearch(struct fs *fs, struct cg *cgp, daddr_t bpref, int allocsiz) 541ffs_mapsearch(struct fs *fs, struct cg *cgp, daddr_t bpref, int allocsiz)
540{ 542{
541 int32_t bno; 543 int32_t bno;
542 int start, len, loc, i; 544 int start, len, loc, i;
543 int blk, field, subfield, pos; 545 int blk, field, subfield, pos;
544 int ostart, olen; 546 int ostart, olen;
545 const int needswap = UFS_FSNEEDSWAP(fs); 547 const int needswap = UFS_FSNEEDSWAP(fs);
546 548
547 /* 549 /*
548 * find the fragment by searching through the free block 550 * find the fragment by searching through the free block
549 * map for an appropriate bit pattern 551 * map for an appropriate bit pattern
550 */ 552 */
551 if (bpref) 553 if (bpref)
552 start = dtogd(fs, bpref) / NBBY; 554 start = dtogd(fs, bpref) / NBBY;
553 else 555 else
554 start = ufs_rw32(cgp->cg_frotor, needswap) / NBBY; 556 start = ufs_rw32(cgp->cg_frotor, needswap) / NBBY;
555 len = howmany(fs->fs_fpg, NBBY) - start; 557 len = howmany(fs->fs_fpg, NBBY) - start;
556 ostart = start; 558 ostart = start;
557 olen = len; 559 olen = len;
558 loc = scanc((u_int)len, 560 loc = scanc((u_int)len,
559 (const u_char *)&cg_blksfree(cgp, needswap)[start], 561 (const u_char *)&cg_blksfree(cgp, needswap)[start],
560 (const u_char *)fragtbl[fs->fs_frag], 562 (const u_char *)fragtbl[fs->fs_frag],
561 (1 << (allocsiz - 1 + (fs->fs_frag % NBBY)))); 563 (1 << (allocsiz - 1 + (fs->fs_frag % NBBY))));
562 if (loc == 0) { 564 if (loc == 0) {
563 len = start + 1; 565 len = start + 1;
564 start = 0; 566 start = 0;
565 loc = scanc((u_int)len, 567 loc = scanc((u_int)len,
566 (const u_char *)&cg_blksfree(cgp, needswap)[0], 568 (const u_char *)&cg_blksfree(cgp, needswap)[0],
567 (const u_char *)fragtbl[fs->fs_frag], 569 (const u_char *)fragtbl[fs->fs_frag],
568 (1 << (allocsiz - 1 + (fs->fs_frag % NBBY)))); 570 (1 << (allocsiz - 1 + (fs->fs_frag % NBBY))));
569 if (loc == 0) { 571 if (loc == 0) {
570 errx(1, 572 errx(1,
571 "ffs_alloccg: map corrupted: start %d len %d offset %d %ld", 573 "ffs_alloccg: map corrupted: start %d len %d offset %d %ld",
572 ostart, olen, 574 ostart, olen,
573 ufs_rw32(cgp->cg_freeoff, needswap), 575 ufs_rw32(cgp->cg_freeoff, needswap),
574 (long)cg_blksfree(cgp, needswap) - (long)cgp); 576 (long)cg_blksfree(cgp, needswap) - (long)cgp);
575 /* NOTREACHED */ 577 /* NOTREACHED */
576 } 578 }
577 } 579 }
578 bno = (start + len - loc) * NBBY; 580 bno = (start + len - loc) * NBBY;
579 cgp->cg_frotor = ufs_rw32(bno, needswap); 581 cgp->cg_frotor = ufs_rw32(bno, needswap);
580 /* 582 /*
581 * found the byte in the map 583 * found the byte in the map
582 * sift through the bits to find the selected frag 584 * sift through the bits to find the selected frag
583 */ 585 */
584 for (i = bno + NBBY; bno < i; bno += fs->fs_frag) { 586 for (i = bno + NBBY; bno < i; bno += fs->fs_frag) {
585 blk = blkmap(fs, cg_blksfree(cgp, needswap), bno); 587 blk = blkmap(fs, cg_blksfree(cgp, needswap), bno);
586 blk <<= 1; 588 blk <<= 1;
587 field = around[allocsiz]; 589 field = around[allocsiz];
588 subfield = inside[allocsiz]; 590 subfield = inside[allocsiz];
589 for (pos = 0; pos <= fs->fs_frag - allocsiz; pos++) { 591 for (pos = 0; pos <= fs->fs_frag - allocsiz; pos++) {
590 if ((blk & field) == subfield) 592 if ((blk & field) == subfield)
591 return (bno + pos); 593 return (bno + pos);
592 field <<= 1; 594 field <<= 1;
593 subfield <<= 1; 595 subfield <<= 1;
594 } 596 }
595 } 597 }
596 errx(1, "ffs_alloccg: block not in map: bno %lld", (long long)bno); 598 errx(1, "ffs_alloccg: block not in map: bno %lld", (long long)bno);
597 return (-1); 599 return (-1);
598} 600}

cvs diff -r1.14 -r1.15 src/usr.sbin/makefs/ffs/ffs_balloc.c (switch to unified diff)

--- src/usr.sbin/makefs/ffs/ffs_balloc.c 2013/01/22 09:39:19 1.14
+++ src/usr.sbin/makefs/ffs/ffs_balloc.c 2013/01/26 00:19:39 1.15
@@ -1,584 +1,584 @@ @@ -1,584 +1,584 @@
1/* $NetBSD: ffs_balloc.c,v 1.14 2013/01/22 09:39:19 dholland Exp $ */ 1/* $NetBSD: ffs_balloc.c,v 1.15 2013/01/26 00:19:39 christos Exp $ */
2/* From NetBSD: ffs_balloc.c,v 1.25 2001/08/08 08:36:36 lukem Exp */ 2/* From NetBSD: ffs_balloc.c,v 1.25 2001/08/08 08:36:36 lukem Exp */
3 3
4/* 4/*
5 * Copyright (c) 1982, 1986, 1989, 1993 5 * Copyright (c) 1982, 1986, 1989, 1993
6 * The Regents of the University of California. All rights reserved. 6 * The Regents of the University of California. All rights reserved.
7 * 7 *
8 * Redistribution and use in source and binary forms, with or without 8 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted provided that the following conditions 9 * modification, are permitted provided that the following conditions
10 * are met: 10 * are met:
11 * 1. Redistributions of source code must retain the above copyright 11 * 1. Redistributions of source code must retain the above copyright
12 * notice, this list of conditions and the following disclaimer. 12 * notice, this list of conditions and the following disclaimer.
13 * 2. Redistributions in binary form must reproduce the above copyright 13 * 2. Redistributions in binary form must reproduce the above copyright
14 * notice, this list of conditions and the following disclaimer in the 14 * notice, this list of conditions and the following disclaimer in the
15 * documentation and/or other materials provided with the distribution. 15 * documentation and/or other materials provided with the distribution.
16 * 3. Neither the name of the University nor the names of its contributors 16 * 3. Neither the name of the University nor the names of its contributors
17 * may be used to endorse or promote products derived from this software 17 * may be used to endorse or promote products derived from this software
18 * without specific prior written permission. 18 * without specific prior written permission.
19 * 19 *
20 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 20 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
21 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 21 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
22 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 22 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
23 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 23 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
24 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 24 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
25 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 25 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
26 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 26 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
27 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 27 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
28 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 28 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
29 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 29 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
30 * SUCH DAMAGE. 30 * SUCH DAMAGE.
31 * 31 *
32 * @(#)ffs_balloc.c 8.8 (Berkeley) 6/16/95 32 * @(#)ffs_balloc.c 8.8 (Berkeley) 6/16/95
33 */ 33 */
34 34
35#if HAVE_NBTOOL_CONFIG_H 35#if HAVE_NBTOOL_CONFIG_H
36#include "nbtool_config.h" 36#include "nbtool_config.h"
37#endif 37#endif
38 38
39#include <sys/cdefs.h> 39#include <sys/cdefs.h>
40#if defined(__RCSID) && !defined(__lint) 40#if defined(__RCSID) && !defined(__lint)
41__RCSID("$NetBSD: ffs_balloc.c,v 1.14 2013/01/22 09:39:19 dholland Exp $"); 41__RCSID("$NetBSD: ffs_balloc.c,v 1.15 2013/01/26 00:19:39 christos Exp $");
42#endif /* !__lint */ 42#endif /* !__lint */
43 43
44#include <sys/param.h> 44#include <sys/param.h>
45#include <sys/time.h> 45#include <sys/time.h>
46 46
47#include <assert.h> 47#include <assert.h>
48#include <errno.h> 48#include <errno.h>
49#include <stdio.h> 49#include <stdio.h>
50#include <stdlib.h> 50#include <stdlib.h>
51#include <string.h> 51#include <string.h>
52 52
53#include "makefs.h" 53#include "makefs.h"
54 54
55#include <ufs/ufs/dinode.h> 55#include <ufs/ufs/dinode.h>
56#include <ufs/ufs/ufs_bswap.h> 56#include <ufs/ufs/ufs_bswap.h>
57#include <ufs/ffs/fs.h> 57#include <ufs/ffs/fs.h>
58 58
59#include "ffs/buf.h" 59#include "ffs/buf.h"
60#include "ffs/ufs_inode.h" 60#include "ffs/ufs_inode.h"
61#include "ffs/ffs_extern.h" 61#include "ffs/ffs_extern.h"
62 62
63static int ffs_balloc_ufs1(struct inode *, off_t, int, struct buf **); 63static int ffs_balloc_ufs1(struct inode *, off_t, int, struct buf **);
64static int ffs_balloc_ufs2(struct inode *, off_t, int, struct buf **); 64static int ffs_balloc_ufs2(struct inode *, off_t, int, struct buf **);
65 65
66/* 66/*
67 * Balloc defines the structure of file system storage 67 * Balloc defines the structure of file system storage
68 * by allocating the physical blocks on a device given 68 * by allocating the physical blocks on a device given
69 * the inode and the logical block number in a file. 69 * the inode and the logical block number in a file.
70 * 70 *
71 * Assume: flags == B_SYNC | B_CLRBUF 71 * Assume: flags == B_SYNC | B_CLRBUF
72 */ 72 */
73 73
74int 74int
75ffs_balloc(struct inode *ip, off_t offset, int bufsize, struct buf **bpp) 75ffs_balloc(struct inode *ip, off_t offset, int bufsize, struct buf **bpp)
76{ 76{
77 if (ip->i_fs->fs_magic == FS_UFS2_MAGIC) 77 if (ip->i_fs->fs_magic == FS_UFS2_MAGIC)
78 return ffs_balloc_ufs2(ip, offset, bufsize, bpp); 78 return ffs_balloc_ufs2(ip, offset, bufsize, bpp);
79 else 79 else
80 return ffs_balloc_ufs1(ip, offset, bufsize, bpp); 80 return ffs_balloc_ufs1(ip, offset, bufsize, bpp);
81} 81}
82 82
83static int 83static int
84ffs_balloc_ufs1(struct inode *ip, off_t offset, int bufsize, struct buf **bpp) 84ffs_balloc_ufs1(struct inode *ip, off_t offset, int bufsize, struct buf **bpp)
85{ 85{
86 daddr_t lbn, lastlbn; 86 daddr_t lbn, lastlbn;
87 int size; 87 int size;
88 int32_t nb; 88 int32_t nb;
89 struct buf *bp, *nbp; 89 struct buf *bp, *nbp;
90 struct fs *fs = ip->i_fs; 90 struct fs *fs = ip->i_fs;
91 struct indir indirs[UFS_NIADDR + 2]; 91 struct indir indirs[UFS_NIADDR + 2];
92 daddr_t newb, pref; 92 daddr_t newb, pref;
93 int32_t *bap; 93 int32_t *bap;
94 int osize, nsize, num, i, error; 94 int osize, nsize, num, i, error;
95 int32_t *allocblk, allociblk[UFS_NIADDR + 1]; 95 int32_t *allocblk, allociblk[UFS_NIADDR + 1];
96 int32_t *allocib; 96 int32_t *allocib;
97 const int needswap = UFS_FSNEEDSWAP(fs); 97 const int needswap = UFS_FSNEEDSWAP(fs);
 98 struct vnode vp = { ip->i_fd, ip->i_fs, NULL, 0 };
98 99
99 lbn = lblkno(fs, offset); 100 lbn = lblkno(fs, offset);
100 size = blkoff(fs, offset) + bufsize; 101 size = blkoff(fs, offset) + bufsize;
101 if (bpp != NULL) { 102 if (bpp != NULL) {
102 *bpp = NULL; 103 *bpp = NULL;
103 } 104 }
104 105
105 assert(size <= fs->fs_bsize); 106 assert(size <= fs->fs_bsize);
106 if (lbn < 0) 107 if (lbn < 0)
107 return (EFBIG); 108 return (EFBIG);
108 109
109 /* 110 /*
110 * If the next write will extend the file into a new block, 111 * If the next write will extend the file into a new block,
111 * and the file is currently composed of a fragment 112 * and the file is currently composed of a fragment
112 * this fragment has to be extended to be a full block. 113 * this fragment has to be extended to be a full block.
113 */ 114 */
114 115
115 lastlbn = lblkno(fs, ip->i_ffs1_size); 116 lastlbn = lblkno(fs, ip->i_ffs1_size);
116 if (lastlbn < UFS_NDADDR && lastlbn < lbn) { 117 if (lastlbn < UFS_NDADDR && lastlbn < lbn) {
117 nb = lastlbn; 118 nb = lastlbn;
118 osize = blksize(fs, ip, nb); 119 osize = blksize(fs, ip, nb);
119 if (osize < fs->fs_bsize && osize > 0) { 120 if (osize < fs->fs_bsize && osize > 0) {
120 warnx("need to ffs_realloccg; not supported!"); 121 warnx("need to ffs_realloccg; not supported!");
121 abort(); 122 abort();
122 } 123 }
123 } 124 }
124 125
125 /* 126 /*
126 * The first UFS_NDADDR blocks are direct blocks 127 * The first UFS_NDADDR blocks are direct blocks
127 */ 128 */
128 129
129 if (lbn < UFS_NDADDR) { 130 if (lbn < UFS_NDADDR) {
130 nb = ufs_rw32(ip->i_ffs1_db[lbn], needswap); 131 nb = ufs_rw32(ip->i_ffs1_db[lbn], needswap);
131 if (nb != 0 && ip->i_ffs1_size >= lblktosize(fs, lbn + 1)) { 132 if (nb != 0 && ip->i_ffs1_size >= lblktosize(fs, lbn + 1)) {
132 133
133 /* 134 /*
134 * The block is an already-allocated direct block 135 * The block is an already-allocated direct block
135 * and the file already extends past this block, 136 * and the file already extends past this block,
136 * thus this must be a whole block. 137 * thus this must be a whole block.
137 * Just read the block (if requested). 138 * Just read the block (if requested).
138 */ 139 */
139 140
140 if (bpp != NULL) { 141 if (bpp != NULL) {
141 error = bread(ip->i_fd, ip->i_fs, lbn, 142 error = bread(&vp, lbn, fs->fs_bsize, NULL, 0,
142 fs->fs_bsize, bpp); 143 bpp);
143 if (error) { 144 if (error) {
144 brelse(*bpp); 145 brelse(*bpp, 0);
145 return (error); 146 return (error);
146 } 147 }
147 } 148 }
148 return (0); 149 return (0);
149 } 150 }
150 if (nb != 0) { 151 if (nb != 0) {
151 152
152 /* 153 /*
153 * Consider need to reallocate a fragment. 154 * Consider need to reallocate a fragment.
154 */ 155 */
155 156
156 osize = fragroundup(fs, blkoff(fs, ip->i_ffs1_size)); 157 osize = fragroundup(fs, blkoff(fs, ip->i_ffs1_size));
157 nsize = fragroundup(fs, size); 158 nsize = fragroundup(fs, size);
158 if (nsize <= osize) { 159 if (nsize <= osize) {
159 160
160 /* 161 /*
161 * The existing block is already 162 * The existing block is already
162 * at least as big as we want. 163 * at least as big as we want.
163 * Just read the block (if requested). 164 * Just read the block (if requested).
164 */ 165 */
165 166
166 if (bpp != NULL) { 167 if (bpp != NULL) {
167 error = bread(ip->i_fd, ip->i_fs, lbn, 168 error = bread(&vp, lbn, osize, NULL, 0,
168 osize, bpp); 169 bpp);
169 if (error) { 170 if (error) {
170 brelse(*bpp); 171 brelse(*bpp, 0);
171 return (error); 172 return (error);
172 } 173 }
173 } 174 }
174 return 0; 175 return 0;
175 } else { 176 } else {
176 warnx("need to ffs_realloccg; not supported!"); 177 warnx("need to ffs_realloccg; not supported!");
177 abort(); 178 abort();
178 } 179 }
179 } else { 180 } else {
180 181
181 /* 182 /*
182 * the block was not previously allocated, 183 * the block was not previously allocated,
183 * allocate a new block or fragment. 184 * allocate a new block or fragment.
184 */ 185 */
185 186
186 if (ip->i_ffs1_size < lblktosize(fs, lbn + 1)) 187 if (ip->i_ffs1_size < lblktosize(fs, lbn + 1))
187 nsize = fragroundup(fs, size); 188 nsize = fragroundup(fs, size);
188 else 189 else
189 nsize = fs->fs_bsize; 190 nsize = fs->fs_bsize;
190 error = ffs_alloc(ip, lbn, 191 error = ffs_alloc(ip, lbn,
191 ffs_blkpref_ufs1(ip, lbn, (int)lbn, 192 ffs_blkpref_ufs1(ip, lbn, (int)lbn,
192 &ip->i_ffs1_db[0]), 193 &ip->i_ffs1_db[0]),
193 nsize, &newb); 194 nsize, &newb);
194 if (error) 195 if (error)
195 return (error); 196 return (error);
196 if (bpp != NULL) { 197 if (bpp != NULL) {
197 bp = getblk(ip->i_fd, ip->i_fs, lbn, nsize); 198 bp = getblk(&vp, lbn, nsize, 0, 0);
198 bp->b_blkno = fsbtodb(fs, newb); 199 bp->b_blkno = fsbtodb(fs, newb);
199 clrbuf(bp); 200 clrbuf(bp);
200 *bpp = bp; 201 *bpp = bp;
201 } 202 }
202 } 203 }
203 ip->i_ffs1_db[lbn] = ufs_rw32((int32_t)newb, needswap); 204 ip->i_ffs1_db[lbn] = ufs_rw32((int32_t)newb, needswap);
204 return (0); 205 return (0);
205 } 206 }
206 207
207 /* 208 /*
208 * Determine the number of levels of indirection. 209 * Determine the number of levels of indirection.
209 */ 210 */
210 211
211 pref = 0; 212 pref = 0;
212 if ((error = ufs_getlbns(ip, lbn, indirs, &num)) != 0) 213 if ((error = ufs_getlbns(ip, lbn, indirs, &num)) != 0)
213 return (error); 214 return (error);
214 215
215 if (num < 1) { 216 if (num < 1) {
216 warnx("ffs_balloc: ufs_getlbns returned indirect block"); 217 warnx("ffs_balloc: ufs_getlbns returned indirect block");
217 abort(); 218 abort();
218 } 219 }
219 220
220 /* 221 /*
221 * Fetch the first indirect block allocating if necessary. 222 * Fetch the first indirect block allocating if necessary.
222 */ 223 */
223 224
224 --num; 225 --num;
225 nb = ufs_rw32(ip->i_ffs1_ib[indirs[0].in_off], needswap); 226 nb = ufs_rw32(ip->i_ffs1_ib[indirs[0].in_off], needswap);
226 allocib = NULL; 227 allocib = NULL;
227 allocblk = allociblk; 228 allocblk = allociblk;
228 if (nb == 0) { 229 if (nb == 0) {
229 pref = ffs_blkpref_ufs1(ip, lbn, 0, (int32_t *)0); 230 pref = ffs_blkpref_ufs1(ip, lbn, 0, (int32_t *)0);
230 error = ffs_alloc(ip, lbn, pref, (int)fs->fs_bsize, &newb); 231 error = ffs_alloc(ip, lbn, pref, (int)fs->fs_bsize, &newb);
231 if (error) 232 if (error)
232 return error; 233 return error;
233 nb = newb; 234 nb = newb;
234 *allocblk++ = nb; 235 *allocblk++ = nb;
235 bp = getblk(ip->i_fd, ip->i_fs, indirs[1].in_lbn, fs->fs_bsize); 236 bp = getblk(&vp, indirs[1].in_lbn, fs->fs_bsize, 0, 0);
236 bp->b_blkno = fsbtodb(fs, nb); 237 bp->b_blkno = fsbtodb(fs, nb);
237 clrbuf(bp); 238 clrbuf(bp);
238 /* 239 /*
239 * Write synchronously so that indirect blocks 240 * Write synchronously so that indirect blocks
240 * never point at garbage. 241 * never point at garbage.
241 */ 242 */
242 if ((error = bwrite(bp)) != 0) 243 if ((error = bwrite(bp)) != 0)
243 return error; 244 return error;
244 allocib = &ip->i_ffs1_ib[indirs[0].in_off]; 245 allocib = &ip->i_ffs1_ib[indirs[0].in_off];
245 *allocib = ufs_rw32((int32_t)nb, needswap); 246 *allocib = ufs_rw32((int32_t)nb, needswap);
246 } 247 }
247 248
248 /* 249 /*
249 * Fetch through the indirect blocks, allocating as necessary. 250 * Fetch through the indirect blocks, allocating as necessary.
250 */ 251 */
251 252
252 for (i = 1;;) { 253 for (i = 1;;) {
253 error = bread(ip->i_fd, ip->i_fs, indirs[i].in_lbn,  254 error = bread(&vp, indirs[i].in_lbn, fs->fs_bsize, NULL, 0,
254 fs->fs_bsize, &bp); 255 &bp);
255 if (error) { 256 if (error) {
256 brelse(bp); 257 brelse(bp, 0);
257 return error; 258 return error;
258 } 259 }
259 bap = (int32_t *)bp->b_data; 260 bap = (int32_t *)bp->b_data;
260 nb = ufs_rw32(bap[indirs[i].in_off], needswap); 261 nb = ufs_rw32(bap[indirs[i].in_off], needswap);
261 if (i == num) 262 if (i == num)
262 break; 263 break;
263 i++; 264 i++;
264 if (nb != 0) { 265 if (nb != 0) {
265 brelse(bp); 266 brelse(bp, 0);
266 continue; 267 continue;
267 } 268 }
268 if (pref == 0) 269 if (pref == 0)
269 pref = ffs_blkpref_ufs1(ip, lbn, 0, (int32_t *)0); 270 pref = ffs_blkpref_ufs1(ip, lbn, 0, (int32_t *)0);
270 error = ffs_alloc(ip, lbn, pref, (int)fs->fs_bsize, &newb); 271 error = ffs_alloc(ip, lbn, pref, (int)fs->fs_bsize, &newb);
271 if (error) { 272 if (error) {
272 brelse(bp); 273 brelse(bp, 0);
273 return error; 274 return error;
274 } 275 }
275 nb = newb; 276 nb = newb;
276 *allocblk++ = nb; 277 *allocblk++ = nb;
277 nbp = getblk(ip->i_fd, ip->i_fs, indirs[i].in_lbn, 278 nbp = getblk(&vp, indirs[i].in_lbn, fs->fs_bsize, 0, 0);
278 fs->fs_bsize); 
279 nbp->b_blkno = fsbtodb(fs, nb); 279 nbp->b_blkno = fsbtodb(fs, nb);
280 clrbuf(nbp); 280 clrbuf(nbp);
281 /* 281 /*
282 * Write synchronously so that indirect blocks 282 * Write synchronously so that indirect blocks
283 * never point at garbage. 283 * never point at garbage.
284 */ 284 */
285 285
286 if ((error = bwrite(nbp)) != 0) { 286 if ((error = bwrite(nbp)) != 0) {
287 brelse(bp); 287 brelse(bp, 0);
288 return error; 288 return error;
289 } 289 }
290 bap[indirs[i - 1].in_off] = ufs_rw32(nb, needswap); 290 bap[indirs[i - 1].in_off] = ufs_rw32(nb, needswap);
291 291
292 bwrite(bp); 292 bwrite(bp);
293 } 293 }
294 294
295 /* 295 /*
296 * Get the data block, allocating if necessary. 296 * Get the data block, allocating if necessary.
297 */ 297 */
298 298
299 if (nb == 0) { 299 if (nb == 0) {
300 pref = ffs_blkpref_ufs1(ip, lbn, indirs[num].in_off, &bap[0]); 300 pref = ffs_blkpref_ufs1(ip, lbn, indirs[num].in_off, &bap[0]);
301 error = ffs_alloc(ip, lbn, pref, (int)fs->fs_bsize, &newb); 301 error = ffs_alloc(ip, lbn, pref, (int)fs->fs_bsize, &newb);
302 if (error) { 302 if (error) {
303 brelse(bp); 303 brelse(bp, 0);
304 return error; 304 return error;
305 } 305 }
306 nb = newb; 306 nb = newb;
307 *allocblk++ = nb; 307 *allocblk++ = nb;
308 if (bpp != NULL) { 308 if (bpp != NULL) {
309 nbp = getblk(ip->i_fd, ip->i_fs, lbn, fs->fs_bsize); 309 nbp = getblk(&vp, lbn, fs->fs_bsize, 0, 0);
310 nbp->b_blkno = fsbtodb(fs, nb); 310 nbp->b_blkno = fsbtodb(fs, nb);
311 clrbuf(nbp); 311 clrbuf(nbp);
312 *bpp = nbp; 312 *bpp = nbp;
313 } 313 }
314 bap[indirs[num].in_off] = ufs_rw32(nb, needswap); 314 bap[indirs[num].in_off] = ufs_rw32(nb, needswap);
315 315
316 /* 316 /*
317 * If required, write synchronously, otherwise use 317 * If required, write synchronously, otherwise use
318 * delayed write. 318 * delayed write.
319 */ 319 */
320 bwrite(bp); 320 bwrite(bp);
321 return (0); 321 return (0);
322 } 322 }
323 brelse(bp); 323 brelse(bp, 0);
324 if (bpp != NULL) { 324 if (bpp != NULL) {
325 error = bread(ip->i_fd, ip->i_fs, lbn, (int)fs->fs_bsize, &nbp); 325 error = bread(&vp, lbn, (int)fs->fs_bsize, NULL, 0, &nbp);
326 if (error) { 326 if (error) {
327 brelse(nbp); 327 brelse(nbp, 0);
328 return error; 328 return error;
329 } 329 }
330 *bpp = nbp; 330 *bpp = nbp;
331 } 331 }
332 return (0); 332 return (0);
333} 333}
334 334
335static int 335static int
336ffs_balloc_ufs2(struct inode *ip, off_t offset, int bufsize, struct buf **bpp) 336ffs_balloc_ufs2(struct inode *ip, off_t offset, int bufsize, struct buf **bpp)
337{ 337{
338 daddr_t lbn, lastlbn; 338 daddr_t lbn, lastlbn;
339 int size; 339 int size;
340 struct buf *bp, *nbp; 340 struct buf *bp, *nbp;
341 struct fs *fs = ip->i_fs; 341 struct fs *fs = ip->i_fs;
342 struct indir indirs[UFS_NIADDR + 2]; 342 struct indir indirs[UFS_NIADDR + 2];
343 daddr_t newb, pref, nb; 343 daddr_t newb, pref, nb;
344 int64_t *bap; 344 int64_t *bap;
345 int osize, nsize, num, i, error; 345 int osize, nsize, num, i, error;
346 int64_t *allocblk, allociblk[UFS_NIADDR + 1]; 346 int64_t *allocblk, allociblk[UFS_NIADDR + 1];
347 int64_t *allocib; 347 int64_t *allocib;
348 const int needswap = UFS_FSNEEDSWAP(fs); 348 const int needswap = UFS_FSNEEDSWAP(fs);
 349 struct vnode vp = { ip->i_fd, ip->i_fs, NULL, 0 };
349 350
350 lbn = lblkno(fs, offset); 351 lbn = lblkno(fs, offset);
351 size = blkoff(fs, offset) + bufsize; 352 size = blkoff(fs, offset) + bufsize;
352 if (bpp != NULL) { 353 if (bpp != NULL) {
353 *bpp = NULL; 354 *bpp = NULL;
354 } 355 }
355 356
356 assert(size <= fs->fs_bsize); 357 assert(size <= fs->fs_bsize);
357 if (lbn < 0) 358 if (lbn < 0)
358 return (EFBIG); 359 return (EFBIG);
359 360
360 /* 361 /*
361 * If the next write will extend the file into a new block, 362 * If the next write will extend the file into a new block,
362 * and the file is currently composed of a fragment 363 * and the file is currently composed of a fragment
363 * this fragment has to be extended to be a full block. 364 * this fragment has to be extended to be a full block.
364 */ 365 */
365 366
366 lastlbn = lblkno(fs, ip->i_ffs2_size); 367 lastlbn = lblkno(fs, ip->i_ffs2_size);
367 if (lastlbn < UFS_NDADDR && lastlbn < lbn) { 368 if (lastlbn < UFS_NDADDR && lastlbn < lbn) {
368 nb = lastlbn; 369 nb = lastlbn;
369 osize = blksize(fs, ip, nb); 370 osize = blksize(fs, ip, nb);
370 if (osize < fs->fs_bsize && osize > 0) { 371 if (osize < fs->fs_bsize && osize > 0) {
371 warnx("need to ffs_realloccg; not supported!"); 372 warnx("need to ffs_realloccg; not supported!");
372 abort(); 373 abort();
373 } 374 }
374 } 375 }
375 376
376 /* 377 /*
377 * The first UFS_NDADDR blocks are direct blocks 378 * The first UFS_NDADDR blocks are direct blocks
378 */ 379 */
379 380
380 if (lbn < UFS_NDADDR) { 381 if (lbn < UFS_NDADDR) {
381 nb = ufs_rw64(ip->i_ffs2_db[lbn], needswap); 382 nb = ufs_rw64(ip->i_ffs2_db[lbn], needswap);
382 if (nb != 0 && ip->i_ffs2_size >= lblktosize(fs, lbn + 1)) { 383 if (nb != 0 && ip->i_ffs2_size >= lblktosize(fs, lbn + 1)) {
383 384
384 /* 385 /*
385 * The block is an already-allocated direct block 386 * The block is an already-allocated direct block
386 * and the file already extends past this block, 387 * and the file already extends past this block,
387 * thus this must be a whole block. 388 * thus this must be a whole block.
388 * Just read the block (if requested). 389 * Just read the block (if requested).
389 */ 390 */
390 391
391 if (bpp != NULL) { 392 if (bpp != NULL) {
392 error = bread(ip->i_fd, ip->i_fs, lbn, 393 error = bread(&vp, lbn, fs->fs_bsize, NULL, 0,
393 fs->fs_bsize, bpp); 394 bpp);
394 if (error) { 395 if (error) {
395 brelse(*bpp); 396 brelse(*bpp, 0);
396 return (error); 397 return (error);
397 } 398 }
398 } 399 }
399 return (0); 400 return (0);
400 } 401 }
401 if (nb != 0) { 402 if (nb != 0) {
402 403
403 /* 404 /*
404 * Consider need to reallocate a fragment. 405 * Consider need to reallocate a fragment.
405 */ 406 */
406 407
407 osize = fragroundup(fs, blkoff(fs, ip->i_ffs2_size)); 408 osize = fragroundup(fs, blkoff(fs, ip->i_ffs2_size));
408 nsize = fragroundup(fs, size); 409 nsize = fragroundup(fs, size);
409 if (nsize <= osize) { 410 if (nsize <= osize) {
410 411
411 /* 412 /*
412 * The existing block is already 413 * The existing block is already
413 * at least as big as we want. 414 * at least as big as we want.
414 * Just read the block (if requested). 415 * Just read the block (if requested).
415 */ 416 */
416 417
417 if (bpp != NULL) { 418 if (bpp != NULL) {
418 error = bread(ip->i_fd, ip->i_fs, lbn, 419 error = bread(&vp, lbn, osize, NULL, 0,
419 osize, bpp); 420 bpp);
420 if (error) { 421 if (error) {
421 brelse(*bpp); 422 brelse(*bpp, 0);
422 return (error); 423 return (error);
423 } 424 }
424 } 425 }
425 return 0; 426 return 0;
426 } else { 427 } else {
427 warnx("need to ffs_realloccg; not supported!"); 428 warnx("need to ffs_realloccg; not supported!");
428 abort(); 429 abort();
429 } 430 }
430 } else { 431 } else {
431 432
432 /* 433 /*
433 * the block was not previously allocated, 434 * the block was not previously allocated,
434 * allocate a new block or fragment. 435 * allocate a new block or fragment.
435 */ 436 */
436 437
437 if (ip->i_ffs2_size < lblktosize(fs, lbn + 1)) 438 if (ip->i_ffs2_size < lblktosize(fs, lbn + 1))
438 nsize = fragroundup(fs, size); 439 nsize = fragroundup(fs, size);
439 else 440 else
440 nsize = fs->fs_bsize; 441 nsize = fs->fs_bsize;
441 error = ffs_alloc(ip, lbn, 442 error = ffs_alloc(ip, lbn,
442 ffs_blkpref_ufs2(ip, lbn, (int)lbn, 443 ffs_blkpref_ufs2(ip, lbn, (int)lbn,
443 &ip->i_ffs2_db[0]), 444 &ip->i_ffs2_db[0]),
444 nsize, &newb); 445 nsize, &newb);
445 if (error) 446 if (error)
446 return (error); 447 return (error);
447 if (bpp != NULL) { 448 if (bpp != NULL) {
448 bp = getblk(ip->i_fd, ip->i_fs, lbn, nsize); 449 bp = getblk(&vp, lbn, nsize, 0, 0);
449 bp->b_blkno = fsbtodb(fs, newb); 450 bp->b_blkno = fsbtodb(fs, newb);
450 clrbuf(bp); 451 clrbuf(bp);
451 *bpp = bp; 452 *bpp = bp;
452 } 453 }
453 } 454 }
454 ip->i_ffs2_db[lbn] = ufs_rw64(newb, needswap); 455 ip->i_ffs2_db[lbn] = ufs_rw64(newb, needswap);
455 return (0); 456 return (0);
456 } 457 }
457 458
458 /* 459 /*
459 * Determine the number of levels of indirection. 460 * Determine the number of levels of indirection.
460 */ 461 */
461 462
462 pref = 0; 463 pref = 0;
463 if ((error = ufs_getlbns(ip, lbn, indirs, &num)) != 0) 464 if ((error = ufs_getlbns(ip, lbn, indirs, &num)) != 0)
464 return (error); 465 return (error);
465 466
466 if (num < 1) { 467 if (num < 1) {
467 warnx("ffs_balloc: ufs_getlbns returned indirect block"); 468 warnx("ffs_balloc: ufs_getlbns returned indirect block");
468 abort(); 469 abort();
469 } 470 }
470 471
471 /* 472 /*
472 * Fetch the first indirect block allocating if necessary. 473 * Fetch the first indirect block allocating if necessary.
473 */ 474 */
474 475
475 --num; 476 --num;
476 nb = ufs_rw64(ip->i_ffs2_ib[indirs[0].in_off], needswap); 477 nb = ufs_rw64(ip->i_ffs2_ib[indirs[0].in_off], needswap);
477 allocib = NULL; 478 allocib = NULL;
478 allocblk = allociblk; 479 allocblk = allociblk;
479 if (nb == 0) { 480 if (nb == 0) {
480 pref = ffs_blkpref_ufs2(ip, lbn, 0, (int64_t *)0); 481 pref = ffs_blkpref_ufs2(ip, lbn, 0, (int64_t *)0);
481 error = ffs_alloc(ip, lbn, pref, (int)fs->fs_bsize, &newb); 482 error = ffs_alloc(ip, lbn, pref, (int)fs->fs_bsize, &newb);
482 if (error) 483 if (error)
483 return error; 484 return error;
484 nb = newb; 485 nb = newb;
485 *allocblk++ = nb; 486 *allocblk++ = nb;
486 bp = getblk(ip->i_fd, ip->i_fs, indirs[1].in_lbn, fs->fs_bsize); 487 bp = getblk(&vp, indirs[1].in_lbn, fs->fs_bsize, 0, 0);
487 bp->b_blkno = fsbtodb(fs, nb); 488 bp->b_blkno = fsbtodb(fs, nb);
488 clrbuf(bp); 489 clrbuf(bp);
489 /* 490 /*
490 * Write synchronously so that indirect blocks 491 * Write synchronously so that indirect blocks
491 * never point at garbage. 492 * never point at garbage.
492 */ 493 */
493 if ((error = bwrite(bp)) != 0) 494 if ((error = bwrite(bp)) != 0)
494 return error; 495 return error;
495 allocib = &ip->i_ffs2_ib[indirs[0].in_off]; 496 allocib = &ip->i_ffs2_ib[indirs[0].in_off];
496 *allocib = ufs_rw64(nb, needswap); 497 *allocib = ufs_rw64(nb, needswap);
497 } 498 }
498 499
499 /* 500 /*
500 * Fetch through the indirect blocks, allocating as necessary. 501 * Fetch through the indirect blocks, allocating as necessary.
501 */ 502 */
502 503
503 for (i = 1;;) { 504 for (i = 1;;) {
504 error = bread(ip->i_fd, ip->i_fs, indirs[i].in_lbn,  505 error = bread(&vp, indirs[i].in_lbn, fs->fs_bsize, NULL, 0,
505 fs->fs_bsize, &bp); 506 &bp);
506 if (error) { 507 if (error) {
507 brelse(bp); 508 brelse(bp, 0);
508 return error; 509 return error;
509 } 510 }
510 bap = (int64_t *)bp->b_data; 511 bap = (int64_t *)bp->b_data;
511 nb = ufs_rw64(bap[indirs[i].in_off], needswap); 512 nb = ufs_rw64(bap[indirs[i].in_off], needswap);
512 if (i == num) 513 if (i == num)
513 break; 514 break;
514 i++; 515 i++;
515 if (nb != 0) { 516 if (nb != 0) {
516 brelse(bp); 517 brelse(bp, 0);
517 continue; 518 continue;
518 } 519 }
519 if (pref == 0) 520 if (pref == 0)
520 pref = ffs_blkpref_ufs2(ip, lbn, 0, (int64_t *)0); 521 pref = ffs_blkpref_ufs2(ip, lbn, 0, (int64_t *)0);
521 error = ffs_alloc(ip, lbn, pref, (int)fs->fs_bsize, &newb); 522 error = ffs_alloc(ip, lbn, pref, (int)fs->fs_bsize, &newb);
522 if (error) { 523 if (error) {
523 brelse(bp); 524 brelse(bp, 0);
524 return error; 525 return error;
525 } 526 }
526 nb = newb; 527 nb = newb;
527 *allocblk++ = nb; 528 *allocblk++ = nb;
528 nbp = getblk(ip->i_fd, ip->i_fs, indirs[i].in_lbn, 529 nbp = getblk(&vp, indirs[i].in_lbn, fs->fs_bsize, 0, 0);
529 fs->fs_bsize); 
530 nbp->b_blkno = fsbtodb(fs, nb); 530 nbp->b_blkno = fsbtodb(fs, nb);
531 clrbuf(nbp); 531 clrbuf(nbp);
532 /* 532 /*
533 * Write synchronously so that indirect blocks 533 * Write synchronously so that indirect blocks
534 * never point at garbage. 534 * never point at garbage.
535 */ 535 */
536 536
537 if ((error = bwrite(nbp)) != 0) { 537 if ((error = bwrite(nbp)) != 0) {
538 brelse(bp); 538 brelse(bp, 0);
539 return error; 539 return error;
540 } 540 }
541 bap[indirs[i - 1].in_off] = ufs_rw64(nb, needswap); 541 bap[indirs[i - 1].in_off] = ufs_rw64(nb, needswap);
542 542
543 bwrite(bp); 543 bwrite(bp);
544 } 544 }
545 545
546 /* 546 /*
547 * Get the data block, allocating if necessary. 547 * Get the data block, allocating if necessary.
548 */ 548 */
549 549
550 if (nb == 0) { 550 if (nb == 0) {
551 pref = ffs_blkpref_ufs2(ip, lbn, indirs[num].in_off, &bap[0]); 551 pref = ffs_blkpref_ufs2(ip, lbn, indirs[num].in_off, &bap[0]);
552 error = ffs_alloc(ip, lbn, pref, (int)fs->fs_bsize, &newb); 552 error = ffs_alloc(ip, lbn, pref, (int)fs->fs_bsize, &newb);
553 if (error) { 553 if (error) {
554 brelse(bp); 554 brelse(bp, 0);
555 return error; 555 return error;
556 } 556 }
557 nb = newb; 557 nb = newb;
558 *allocblk++ = nb; 558 *allocblk++ = nb;
559 if (bpp != NULL) { 559 if (bpp != NULL) {
560 nbp = getblk(ip->i_fd, ip->i_fs, lbn, fs->fs_bsize); 560 nbp = getblk(&vp, lbn, fs->fs_bsize, 0, 0);
561 nbp->b_blkno = fsbtodb(fs, nb); 561 nbp->b_blkno = fsbtodb(fs, nb);
562 clrbuf(nbp); 562 clrbuf(nbp);
563 *bpp = nbp; 563 *bpp = nbp;
564 } 564 }
565 bap[indirs[num].in_off] = ufs_rw64(nb, needswap); 565 bap[indirs[num].in_off] = ufs_rw64(nb, needswap);
566 566
567 /* 567 /*
568 * If required, write synchronously, otherwise use 568 * If required, write synchronously, otherwise use
569 * delayed write. 569 * delayed write.
570 */ 570 */
571 bwrite(bp); 571 bwrite(bp);
572 return (0); 572 return (0);
573 } 573 }
574 brelse(bp); 574 brelse(bp, 0);
575 if (bpp != NULL) { 575 if (bpp != NULL) {
576 error = bread(ip->i_fd, ip->i_fs, lbn, (int)fs->fs_bsize, &nbp); 576 error = bread(&vp, lbn, (int)fs->fs_bsize, NULL, 0, &nbp);
577 if (error) { 577 if (error) {
578 brelse(nbp); 578 brelse(nbp, 0);
579 return error; 579 return error;
580 } 580 }
581 *bpp = nbp; 581 *bpp = nbp;
582 } 582 }
583 return (0); 583 return (0);
584} 584}