make the buffer functions look exactly like the kernel ones and add other cruft to make the kernel files compile.diff -r1.53 -r1.54 src/usr.sbin/makefs/ffs.c
(christos)
--- 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 | |||
128 | typedef struct { | 128 | typedef 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 | |||
135 | static int ffs_create_image(const char *, fsinfo_t *); | 135 | static int ffs_create_image(const char *, fsinfo_t *); | |
136 | static void ffs_dump_fsinfo(fsinfo_t *); | 136 | static void ffs_dump_fsinfo(fsinfo_t *); | |
137 | static void ffs_dump_dirbuf(dirbuf_t *, const char *, int); | 137 | static void ffs_dump_dirbuf(dirbuf_t *, const char *, int); | |
138 | static void ffs_make_dirbuf(dirbuf_t *, const char *, fsnode *, int); | 138 | static void ffs_make_dirbuf(dirbuf_t *, const char *, fsnode *, int); | |
139 | static int ffs_populate_dir(const char *, fsnode *, fsinfo_t *); | 139 | static int ffs_populate_dir(const char *, fsnode *, fsinfo_t *); | |
140 | static void ffs_size_dir(fsnode *, fsinfo_t *); | 140 | static void ffs_size_dir(fsnode *, fsinfo_t *); | |
141 | static void ffs_validate(const char *, fsnode *, fsinfo_t *); | 141 | static void ffs_validate(const char *, fsnode *, fsinfo_t *); | |
142 | static void ffs_write_file(union dinode *, uint32_t, void *, fsinfo_t *); | 142 | static void ffs_write_file(union dinode *, uint32_t, void *, fsinfo_t *); | |
143 | static void ffs_write_inode(union dinode *, uint32_t, const fsinfo_t *); | 143 | static void ffs_write_inode(union dinode *, uint32_t, const fsinfo_t *); | |
144 | static void *ffs_build_dinode1(struct ufs1_dinode *, dirbuf_t *, fsnode *, | 144 | static void *ffs_build_dinode1(struct ufs1_dinode *, dirbuf_t *, fsnode *, | |
145 | fsnode *, fsinfo_t *); | 145 | fsnode *, fsinfo_t *); | |
146 | static void *ffs_build_dinode2(struct ufs2_dinode *, dirbuf_t *, fsnode *, | 146 | static void *ffs_build_dinode2(struct ufs2_dinode *, dirbuf_t *, fsnode *, | |
147 | fsnode *, fsinfo_t *); | 147 | fsnode *, fsinfo_t *); | |
148 | 148 | |||
149 | 149 | |||
150 | 150 | |||
151 | int sectorsize; /* XXX: for buf.c::getblk() */ | 151 | int sectorsize; /* XXX: for buf.c::getblk() */ | |
152 | 152 | |||
153 | /* publically visible functions */ | 153 | /* publically visible functions */ | |
154 | 154 | |||
155 | void | 155 | void | |
156 | ffs_prep_opts(fsinfo_t *fsopts) | 156 | ffs_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 | |||
178 | void | 178 | void | |
179 | ffs_cleanup_opts(fsinfo_t *fsopts) | 179 | ffs_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 | |||
185 | int | 185 | int | |
186 | ffs_parse_opts(const char *option, fsinfo_t *fsopts) | 186 | ffs_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 | |||
249 | void | 249 | void | |
250 | ffs_makefs(const char *image, const char *dir, fsnode *root, fsinfo_t *fsopts) | 250 | ffs_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 | |||
313 | static void | 313 | static void | |
314 | ffs_validate(const char *dir, fsnode *root, fsinfo_t *fsopts) | 314 | ffs_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 | |||
430 | static void | 430 | static void | |
431 | ffs_dump_fsinfo(fsinfo_t *f) | 431 | ffs_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 | |||
460 | static int | 460 | static int | |
461 | ffs_create_image(const char *image, fsinfo_t *fsopts) | 461 | ffs_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 | |||
555 | static void | 555 | static void | |
556 | ffs_size_dir(fsnode *root, fsinfo_t *fsopts) | 556 | ffs_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 | |||
629 | static void * | 629 | static void * | |
630 | ffs_build_dinode1(struct ufs1_dinode *dinp, dirbuf_t *dbufp, fsnode *cur, | 630 | ffs_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 | |||
677 | static void * | 677 | static void * | |
678 | ffs_build_dinode2(struct ufs2_dinode *dinp, dirbuf_t *dbufp, fsnode *cur, | 678 | ffs_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 | |||
729 | static int | 729 | static int | |
730 | ffs_populate_dir(const char *dir, fsnode *root, fsinfo_t *fsopts) | 730 | ffs_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 | |||
849 | static void | 849 | static void | |
850 | ffs_write_file(union dinode *din, uint32_t ino, void *buf, fsinfo_t *fsopts) | 850 | ffs_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 | |||
964 | static void | 964 | static void | |
965 | ffs_dump_dirbuf(dirbuf_t *dbuf, const char *dir, int needswap) | 965 | ffs_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 | |||
989 | static void | 989 | static void | |
990 | ffs_make_dirbuf(dirbuf_t *dbuf, const char *name, fsnode *node, int needswap) | 990 | ffs_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 | */ | |
1043 | static void | 1043 | static void | |
1044 | ffs_write_inode(union dinode *dp, uint32_t ino, const fsinfo_t *fsopts) | 1044 | ffs_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 | |||
1146 | void | 1146 | void | |
1147 | panic(const char *fmt, ...) | 1147 | panic(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 | } |
--- 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 | |||
64 | extern int sectorsize; /* XXX: from ffs.c & mkfs.c */ | 64 | extern int sectorsize; /* XXX: from ffs.c & mkfs.c */ | |
65 | 65 | |||
66 | TAILQ_HEAD(buftailhead,buf) buftail; | 66 | TAILQ_HEAD(buftailhead,buf) buftail; | |
67 | 67 | |||
68 | int | 68 | int | |
69 | bread(int fd, struct fs *fs, daddr_t blkno, int size, struct buf **bpp) | 69 | bread(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 | |||
103 | void | 105 | void | |
104 | brelse(struct buf *bp) | 106 | brelse(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 | |||
133 | int | 135 | int | |
134 | bwrite(struct buf *bp) | 136 | bwrite(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 | |||
159 | void | 161 | void | |
160 | bcleanup(void) | 162 | bcleanup(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 | |||
182 | struct buf * | 184 | struct buf * | |
183 | getblk(int fd, struct fs *fs, daddr_t blkno, int size) | 185 | getblk(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 | } |
--- 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 | ||||
52 | struct componentname { | |||
53 | char *cn_nameptr; | |||
54 | size_t cn_namelen; | |||
55 | }; | |||
56 | ||||
57 | struct vnode { | |||
58 | int fd; | |||
59 | void *fs; | |||
60 | void *v_data; | |||
61 | int offset; | |||
62 | }; | |||
63 | ||||
64 | #define vput(a) ((void)(a)) | |||
65 | ||||
44 | struct buf { | 66 | struct 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 | |||
56 | void bcleanup(void); | 78 | void bcleanup(void); | |
57 | int bread(int, struct fs *, daddr_t, int, struct buf **); | 79 | int bread(struct vnode *, daddr_t, int, struct kauth_cred *, | |
58 | void brelse(struct buf *); | 80 | int, struct buf **); | |
81 | void brelse(struct buf *, int); | |||
59 | int bwrite(struct buf *); | 82 | int bwrite(struct buf *); | |
60 | struct buf * getblk(int, struct fs *, daddr_t, int); | 83 | struct 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 | ||||
96 | struct 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 */ |
--- 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 | |||
69 | static int scanc(u_int, const u_char *, const u_char *, int); | 69 | static int scanc(u_int, const u_char *, const u_char *, int); | |
70 | 70 | |||
71 | static daddr_t ffs_alloccg(struct inode *, int, daddr_t, int); | 71 | static daddr_t ffs_alloccg(struct inode *, int, daddr_t, int); | |
72 | static daddr_t ffs_alloccgblk(struct inode *, struct buf *, daddr_t); | 72 | static daddr_t ffs_alloccgblk(struct inode *, struct buf *, daddr_t); | |
73 | static daddr_t ffs_hashalloc(struct inode *, int, daddr_t, int, | 73 | static 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)); | |
75 | static int32_t ffs_mapsearch(struct fs *, struct cg *, daddr_t, int); | 75 | static int32_t ffs_mapsearch(struct fs *, struct cg *, daddr_t, int); | |
76 | 76 | |||
77 | /* in ffs_tables.c */ | 77 | /* in ffs_tables.c */ | |
78 | extern const int inside[], around[]; | 78 | extern const int inside[], around[]; | |
79 | extern const u_char * const fragtbl[]; | 79 | extern 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 | */ | |
100 | int | 100 | int | |
101 | ffs_alloc(struct inode *ip, daddr_t lbn __unused, daddr_t bpref, int size, | 101 | ffs_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 | } | |
127 | nospace: | 127 | nospace: | |
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 */ | |
158 | daddr_t | 158 | daddr_t | |
159 | ffs_blkpref_ufs1(struct inode *ip, daddr_t lbn, int indx, int32_t *bap) | 159 | ffs_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 | |||
197 | daddr_t | 197 | daddr_t | |
198 | ffs_blkpref_ufs2(struct inode *ip, daddr_t lbn, int indx, int64_t *bap) | 198 | ffs_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*/ | |
249 | static daddr_t | 249 | static daddr_t | |
250 | ffs_hashalloc(struct inode *ip, int cg, daddr_t pref, int size, | 250 | ffs_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 | */ | |
298 | static daddr_t | 298 | static daddr_t | |
299 | ffs_alloccg(struct inode *ip, int cg, daddr_t bpref, int size) | 299 | ffs_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 | */ | |
384 | static daddr_t | 385 | static daddr_t | |
385 | ffs_alloccgblk(struct inode *ip, struct buf *bp, daddr_t bpref) | 386 | ffs_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); | |
414 | gotit: | 415 | gotit: | |
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 | */ | |
433 | void | 434 | void | |
434 | ffs_blkfree(struct inode *ip, daddr_t bno, long size) | 435 | ffs_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 | |||
522 | static int | 524 | static int | |
523 | scanc(u_int size, const u_char *cp, const u_char table[], int mask) | 525 | scanc(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 | */ | |
538 | static int32_t | 540 | static int32_t | |
539 | ffs_mapsearch(struct fs *fs, struct cg *cgp, daddr_t bpref, int allocsiz) | 541 | ffs_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 | } |
--- 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 | |||
63 | static int ffs_balloc_ufs1(struct inode *, off_t, int, struct buf **); | 63 | static int ffs_balloc_ufs1(struct inode *, off_t, int, struct buf **); | |
64 | static int ffs_balloc_ufs2(struct inode *, off_t, int, struct buf **); | 64 | static 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 | |||
74 | int | 74 | int | |
75 | ffs_balloc(struct inode *ip, off_t offset, int bufsize, struct buf **bpp) | 75 | ffs_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 | |||
83 | static int | 83 | static int | |
84 | ffs_balloc_ufs1(struct inode *ip, off_t offset, int bufsize, struct buf **bpp) | 84 | ffs_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 | |||
335 | static int | 335 | static int | |
336 | ffs_balloc_ufs2(struct inode *ip, off_t offset, int bufsize, struct buf **bpp) | 336 | ffs_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 | } |