| @@ -1,851 +1,853 @@ | | | @@ -1,851 +1,853 @@ |
1 | /* $NetBSD: make_lfs.c,v 1.16 2010/02/16 23:20:30 mlelstv Exp $ */ | | 1 | /* $NetBSD: make_lfs.c,v 1.17 2012/01/17 16:27:19 perseant Exp $ */ |
2 | | | 2 | |
3 | /*- | | 3 | /*- |
4 | * Copyright (c) 2003 The NetBSD Foundation, Inc. | | 4 | * Copyright (c) 2003 The NetBSD Foundation, Inc. |
5 | * All rights reserved. | | 5 | * All rights reserved. |
6 | * | | 6 | * |
7 | * This code is derived from software contributed to The NetBSD Foundation | | 7 | * This code is derived from software contributed to The NetBSD Foundation |
8 | * by Konrad E. Schroder <perseant@hhhh.org>. | | 8 | * by Konrad E. Schroder <perseant@hhhh.org>. |
9 | * | | 9 | * |
10 | * Redistribution and use in source and binary forms, with or without | | 10 | * Redistribution and use in source and binary forms, with or without |
11 | * modification, are permitted provided that the following conditions | | 11 | * modification, are permitted provided that the following conditions |
12 | * are met: | | 12 | * are met: |
13 | * 1. Redistributions of source code must retain the above copyright | | 13 | * 1. Redistributions of source code must retain the above copyright |
14 | * notice, this list of conditions and the following disclaimer. | | 14 | * notice, this list of conditions and the following disclaimer. |
15 | * 2. Redistributions in binary form must reproduce the above copyright | | 15 | * 2. Redistributions in binary form must reproduce the above copyright |
16 | * notice, this list of conditions and the following disclaimer in the | | 16 | * notice, this list of conditions and the following disclaimer in the |
17 | * documentation and/or other materials provided with the distribution. | | 17 | * documentation and/or other materials provided with the distribution. |
18 | * | | 18 | * |
19 | * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS | | 19 | * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS |
20 | * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED | | 20 | * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED |
21 | * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR | | 21 | * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR |
22 | * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS | | 22 | * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS |
23 | * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR | | 23 | * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR |
24 | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF | | 24 | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF |
25 | * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS | | 25 | * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS |
26 | * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN | | 26 | * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN |
27 | * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) | | 27 | * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) |
28 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE | | 28 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE |
29 | * POSSIBILITY OF SUCH DAMAGE. | | 29 | * POSSIBILITY OF SUCH DAMAGE. |
30 | */ | | 30 | */ |
31 | /*- | | 31 | /*- |
32 | * Copyright (c) 1991, 1993 | | 32 | * Copyright (c) 1991, 1993 |
33 | * The Regents of the University of California. All rights reserved. | | 33 | * The Regents of the University of California. All rights reserved. |
34 | * | | 34 | * |
35 | * Redistribution and use in source and binary forms, with or without | | 35 | * Redistribution and use in source and binary forms, with or without |
36 | * modification, are permitted provided that the following conditions | | 36 | * modification, are permitted provided that the following conditions |
37 | * are met: | | 37 | * are met: |
38 | * 1. Redistributions of source code must retain the above copyright | | 38 | * 1. Redistributions of source code must retain the above copyright |
39 | * notice, this list of conditions and the following disclaimer. | | 39 | * notice, this list of conditions and the following disclaimer. |
40 | * 2. Redistributions in binary form must reproduce the above copyright | | 40 | * 2. Redistributions in binary form must reproduce the above copyright |
41 | * notice, this list of conditions and the following disclaimer in the | | 41 | * notice, this list of conditions and the following disclaimer in the |
42 | * documentation and/or other materials provided with the distribution. | | 42 | * documentation and/or other materials provided with the distribution. |
43 | * 3. Neither the name of the University nor the names of its contributors | | 43 | * 3. Neither the name of the University nor the names of its contributors |
44 | * may be used to endorse or promote products derived from this software | | 44 | * may be used to endorse or promote products derived from this software |
45 | * without specific prior written permission. | | 45 | * without specific prior written permission. |
46 | * | | 46 | * |
47 | * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND | | 47 | * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND |
48 | * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE | | 48 | * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE |
49 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE | | 49 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE |
50 | * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE | | 50 | * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE |
51 | * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL | | 51 | * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL |
52 | * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS | | 52 | * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS |
53 | * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) | | 53 | * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) |
54 | * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT | | 54 | * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT |
55 | * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY | | 55 | * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY |
56 | * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF | | 56 | * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF |
57 | * SUCH DAMAGE. | | 57 | * SUCH DAMAGE. |
58 | */ | | 58 | */ |
59 | | | 59 | |
60 | #include <sys/cdefs.h> | | 60 | #include <sys/cdefs.h> |
61 | #ifndef lint | | 61 | #ifndef lint |
62 | #if 0 | | 62 | #if 0 |
63 | static char sccsid[] = "@(#)lfs.c 8.5 (Berkeley) 5/24/95"; | | 63 | static char sccsid[] = "@(#)lfs.c 8.5 (Berkeley) 5/24/95"; |
64 | #else | | 64 | #else |
65 | __RCSID("$NetBSD: make_lfs.c,v 1.16 2010/02/16 23:20:30 mlelstv Exp $"); | | 65 | __RCSID("$NetBSD: make_lfs.c,v 1.17 2012/01/17 16:27:19 perseant Exp $"); |
66 | #endif | | 66 | #endif |
67 | #endif /* not lint */ | | 67 | #endif /* not lint */ |
68 | | | 68 | |
69 | #include <sys/param.h> | | 69 | #include <sys/param.h> |
70 | #include <sys/disk.h> | | 70 | #include <sys/disk.h> |
71 | #include <sys/time.h> | | 71 | #include <sys/time.h> |
72 | #include <sys/mount.h> | | 72 | #include <sys/mount.h> |
73 | #include <sys/stat.h> | | 73 | #include <sys/stat.h> |
74 | | | 74 | |
75 | #include <ufs/ufs/dir.h> | | 75 | #include <ufs/ufs/dir.h> |
76 | #include <ufs/ufs/quota.h> | | 76 | #include <ufs/ufs/quota.h> |
77 | #include <ufs/ufs/inode.h> | | 77 | #include <ufs/ufs/inode.h> |
78 | | | 78 | |
79 | /* Override certain things to make <ufs/lfs/lfs.h> work */ | | 79 | /* Override certain things to make <ufs/lfs/lfs.h> work */ |
80 | # undef simple_lock | | 80 | # undef simple_lock |
81 | # define simple_lock(x) | | 81 | # define simple_lock(x) |
82 | # undef simple_unlock | | 82 | # undef simple_unlock |
83 | # define simple_unlock(x) | | 83 | # define simple_unlock(x) |
84 | # define vnode uvnode | | 84 | # define vnode uvnode |
85 | # define buf ubuf | | 85 | # define buf ubuf |
86 | # define panic call_panic | | 86 | # define panic call_panic |
87 | #include <ufs/lfs/lfs.h> | | 87 | #include <ufs/lfs/lfs.h> |
88 | | | 88 | |
89 | #include <err.h> | | 89 | #include <err.h> |
90 | #include <errno.h> | | 90 | #include <errno.h> |
91 | #include <stdio.h> | | 91 | #include <stdio.h> |
92 | #include <stdlib.h> | | 92 | #include <stdlib.h> |
93 | #include <string.h> | | 93 | #include <string.h> |
94 | #include <time.h> | | 94 | #include <time.h> |
95 | #include <unistd.h> | | 95 | #include <unistd.h> |
96 | | | 96 | |
97 | #include "config.h" | | 97 | #include "config.h" |
98 | #include "extern.h" | | 98 | #include "extern.h" |
99 | | | 99 | |
100 | #include "bufcache.h" | | 100 | #include "bufcache.h" |
101 | #include "vnode.h" | | 101 | #include "vnode.h" |
102 | #include "lfs_user.h" | | 102 | #include "lfs_user.h" |
103 | #include "segwrite.h" | | 103 | #include "segwrite.h" |
104 | | | 104 | |
105 | extern int Nflag; /* Don't write anything */ | | 105 | extern int Nflag; /* Don't write anything */ |
106 | ufs_daddr_t ifibc; /* How many indirect blocks */ | | 106 | ufs_daddr_t ifibc; /* How many indirect blocks */ |
107 | | | 107 | |
108 | #ifdef MAKE_LF_DIR | | 108 | #ifdef MAKE_LF_DIR |
109 | # define HIGHEST_USED_INO LOSTFOUNDINO | | 109 | # define HIGHEST_USED_INO LOSTFOUNDINO |
110 | #else | | 110 | #else |
111 | # define HIGHEST_USED_INO ROOTINO | | 111 | # define HIGHEST_USED_INO ROOTINO |
112 | #endif | | 112 | #endif |
113 | | | 113 | |
114 | static struct lfs lfs_default = { | | 114 | static struct lfs lfs_default = { |
115 | .lfs_dlfs = { /* lfs_dlfs */ | | 115 | .lfs_dlfs = { /* lfs_dlfs */ |
116 | /* dlfs_magic */ LFS_MAGIC, | | 116 | /* dlfs_magic */ LFS_MAGIC, |
117 | /* dlfs_version */ LFS_VERSION, | | 117 | /* dlfs_version */ LFS_VERSION, |
118 | /* dlfs_size */ 0, | | 118 | /* dlfs_size */ 0, |
119 | /* dlfs_ssize */ DFL_LFSSEG, | | 119 | /* dlfs_ssize */ DFL_LFSSEG, |
120 | /* dlfs_dsize */ 0, | | 120 | /* dlfs_dsize */ 0, |
121 | /* dlfs_bsize */ DFL_LFSBLOCK, | | 121 | /* dlfs_bsize */ DFL_LFSBLOCK, |
122 | /* dlfs_fsize */ DFL_LFSFRAG, | | 122 | /* dlfs_fsize */ DFL_LFSFRAG, |
123 | /* dlfs_frag */ DFL_LFSBLOCK/DFL_LFSFRAG, | | 123 | /* dlfs_frag */ DFL_LFSBLOCK/DFL_LFSFRAG, |
124 | /* dlfs_freehd */ HIGHEST_USED_INO + 1, | | 124 | /* dlfs_freehd */ HIGHEST_USED_INO + 1, |
125 | /* dlfs_bfree */ 0, | | 125 | /* dlfs_bfree */ 0, |
126 | /* dlfs_nfiles */ 0, | | 126 | /* dlfs_nfiles */ 0, |
127 | /* dlfs_avail */ 0, | | 127 | /* dlfs_avail */ 0, |
128 | /* dlfs_uinodes */ 0, | | 128 | /* dlfs_uinodes */ 0, |
129 | /* dlfs_idaddr */ 0, | | 129 | /* dlfs_idaddr */ 0, |
130 | /* dlfs_ifile */ LFS_IFILE_INUM, | | 130 | /* dlfs_ifile */ LFS_IFILE_INUM, |
131 | /* dlfs_lastseg */ 0, | | 131 | /* dlfs_lastseg */ 0, |
132 | /* dlfs_nextseg */ 0, | | 132 | /* dlfs_nextseg */ 0, |
133 | /* dlfs_curseg */ 0, | | 133 | /* dlfs_curseg */ 0, |
134 | /* dlfs_offset */ 0, | | 134 | /* dlfs_offset */ 0, |
135 | /* dlfs_lastpseg */ 0, | | 135 | /* dlfs_lastpseg */ 0, |
136 | /* dlfs_inopf */ 0, | | 136 | /* dlfs_inopf */ 0, |
137 | /* dlfs_minfree */ MINFREE, | | 137 | /* dlfs_minfree */ MINFREE, |
138 | /* dlfs_maxfilesize */ 0, | | 138 | /* dlfs_maxfilesize */ 0, |
139 | /* dlfs_fsbpseg */ 0, | | 139 | /* dlfs_fsbpseg */ 0, |
140 | /* dlfs_inopb */ DFL_LFSBLOCK/sizeof(struct ufs1_dinode), | | 140 | /* dlfs_inopb */ DFL_LFSBLOCK/sizeof(struct ufs1_dinode), |
141 | /* dlfs_ifpb */ DFL_LFSBLOCK/sizeof(IFILE), | | 141 | /* dlfs_ifpb */ DFL_LFSBLOCK/sizeof(IFILE), |
142 | /* dlfs_sepb */ DFL_LFSBLOCK/sizeof(SEGUSE), | | 142 | /* dlfs_sepb */ DFL_LFSBLOCK/sizeof(SEGUSE), |
143 | /* XXX ondisk32 */ | | 143 | /* XXX ondisk32 */ |
144 | /* dlfs_nindir */ DFL_LFSBLOCK/sizeof(int32_t), | | 144 | /* dlfs_nindir */ DFL_LFSBLOCK/sizeof(int32_t), |
145 | /* dlfs_nseg */ 0, | | 145 | /* dlfs_nseg */ 0, |
146 | /* dlfs_nspf */ 0, | | 146 | /* dlfs_nspf */ 0, |
147 | /* dlfs_cleansz */ 0, | | 147 | /* dlfs_cleansz */ 0, |
148 | /* dlfs_segtabsz */ 0, | | 148 | /* dlfs_segtabsz */ 0, |
149 | /* dlfs_segmask */ DFL_LFSSEG_MASK, | | 149 | /* dlfs_segmask */ DFL_LFSSEG_MASK, |
150 | /* dlfs_segshift */ DFL_LFSSEG_SHIFT, | | 150 | /* dlfs_segshift */ DFL_LFSSEG_SHIFT, |
151 | /* dlfs_bshift */ DFL_LFSBLOCK_SHIFT, | | 151 | /* dlfs_bshift */ DFL_LFSBLOCK_SHIFT, |
152 | /* dlfs_ffshift */ DFL_LFS_FFSHIFT, | | 152 | /* dlfs_ffshift */ DFL_LFS_FFSHIFT, |
153 | /* dlfs_fbshift */ DFL_LFS_FBSHIFT, | | 153 | /* dlfs_fbshift */ DFL_LFS_FBSHIFT, |
154 | /* dlfs_bmask */ DFL_LFSBLOCK_MASK, | | 154 | /* dlfs_bmask */ DFL_LFSBLOCK_MASK, |
155 | /* dlfs_ffmask */ DFL_LFS_FFMASK, | | 155 | /* dlfs_ffmask */ DFL_LFS_FFMASK, |
156 | /* dlfs_fbmask */ DFL_LFS_FBMASK, | | 156 | /* dlfs_fbmask */ DFL_LFS_FBMASK, |
157 | /* dlfs_blktodb */ 0, | | 157 | /* dlfs_blktodb */ 0, |
158 | /* dlfs_sushift */ 0, | | 158 | /* dlfs_sushift */ 0, |
159 | /* dlfs_maxsymlinklen */ MAXSYMLINKLEN_UFS1, | | 159 | /* dlfs_maxsymlinklen */ MAXSYMLINKLEN_UFS1, |
160 | /* dlfs_sboffs */ { 0 }, | | 160 | /* dlfs_sboffs */ { 0 }, |
161 | /* dlfs_nclean */ 0, | | 161 | /* dlfs_nclean */ 0, |
162 | /* dlfs_fsmnt */ { 0 }, | | 162 | /* dlfs_fsmnt */ { 0 }, |
163 | /* dlfs_pflags */ LFS_PF_CLEAN, | | 163 | /* dlfs_pflags */ LFS_PF_CLEAN, |
164 | /* dlfs_dmeta */ 0, | | 164 | /* dlfs_dmeta */ 0, |
165 | /* dlfs_minfreeseg */ 0, | | 165 | /* dlfs_minfreeseg */ 0, |
166 | /* dlfs_sumsize */ 0, | | 166 | /* dlfs_sumsize */ 0, |
167 | /* dlfs_serial */ 0, | | 167 | /* dlfs_serial */ 0, |
168 | /* dlfs_ibsize */ DFL_LFSFRAG, | | 168 | /* dlfs_ibsize */ DFL_LFSFRAG, |
169 | /* dlfs_start */ 0, | | 169 | /* dlfs_start */ 0, |
170 | /* dlfs_tstamp */ 0, | | 170 | /* dlfs_tstamp */ 0, |
171 | /* dlfs_inodefmt */ LFS_44INODEFMT, | | 171 | /* dlfs_inodefmt */ LFS_44INODEFMT, |
172 | /* dlfs_interleave */ 0, | | 172 | /* dlfs_interleave */ 0, |
173 | /* dlfs_ident */ 0, | | 173 | /* dlfs_ident */ 0, |
174 | /* dlfs_fsbtodb */ 0, | | 174 | /* dlfs_fsbtodb */ 0, |
175 | /* dlfs_resvseg */ 0, | | 175 | /* dlfs_resvseg */ 0, |
176 | | | 176 | |
177 | /* dlfs_pad */ { 0 }, | | 177 | /* dlfs_pad */ { 0 }, |
178 | /* dlfs_cksum */ 0 | | 178 | /* dlfs_cksum */ 0 |
179 | }, | | 179 | }, |
180 | }; | | 180 | }; |
181 | | | 181 | |
182 | #define UMASK 0755 | | 182 | #define UMASK 0755 |
183 | | | 183 | |
184 | struct direct lfs_root_dir[] = { | | 184 | struct direct lfs_root_dir[] = { |
185 | { ROOTINO, sizeof(struct direct), DT_DIR, 1, "."}, | | 185 | { ROOTINO, sizeof(struct direct), DT_DIR, 1, "."}, |
186 | { ROOTINO, sizeof(struct direct), DT_DIR, 2, ".."}, | | 186 | { ROOTINO, sizeof(struct direct), DT_DIR, 2, ".."}, |
187 | /* { LFS_IFILE_INUM, sizeof(struct direct), DT_REG, 5, "ifile"}, */ | | 187 | /* { LFS_IFILE_INUM, sizeof(struct direct), DT_REG, 5, "ifile"}, */ |
188 | #ifdef MAKE_LF_DIR | | 188 | #ifdef MAKE_LF_DIR |
189 | { LOSTFOUNDINO, sizeof(struct direct), DT_DIR, 10, "lost+found"}, | | 189 | { LOSTFOUNDINO, sizeof(struct direct), DT_DIR, 10, "lost+found"}, |
190 | #endif | | 190 | #endif |
191 | }; | | 191 | }; |
192 | | | 192 | |
193 | #ifdef MAKE_LF_DIR | | 193 | #ifdef MAKE_LF_DIR |
194 | struct direct lfs_lf_dir[] = { | | 194 | struct direct lfs_lf_dir[] = { |
195 | { LOSTFOUNDINO, sizeof(struct direct), DT_DIR, 1, "." }, | | 195 | { LOSTFOUNDINO, sizeof(struct direct), DT_DIR, 1, "." }, |
196 | { ROOTINO, sizeof(struct direct), DT_DIR, 2, ".." }, | | 196 | { ROOTINO, sizeof(struct direct), DT_DIR, 2, ".." }, |
197 | }; | | 197 | }; |
198 | #endif | | 198 | #endif |
199 | | | 199 | |
200 | void pwarn(const char *, ...); | | 200 | void pwarn(const char *, ...); |
201 | static void make_dinode(ino_t, struct ufs1_dinode *, int, struct lfs *); | | 201 | static void make_dinode(ino_t, struct ufs1_dinode *, int, struct lfs *); |
202 | static void make_dir( void *, struct direct *, int); | | 202 | static void make_dir( void *, struct direct *, int); |
203 | static uint64_t maxfilesize(int); | | 203 | static uint64_t maxfilesize(int); |
204 | | | 204 | |
205 | /* | | 205 | /* |
206 | * calculate the maximum file size allowed with the specified block shift. | | 206 | * calculate the maximum file size allowed with the specified block shift. |
207 | */ | | 207 | */ |
208 | static uint64_t | | 208 | static uint64_t |
209 | maxfilesize(int bshift) | | 209 | maxfilesize(int bshift) |
210 | { | | 210 | { |
211 | uint64_t nptr; /* number of block pointers per block */ | | 211 | uint64_t nptr; /* number of block pointers per block */ |
212 | uint64_t maxblock; | | 212 | uint64_t maxblock; |
213 | | | 213 | |
214 | nptr = (1 << bshift) / sizeof(uint32_t); | | 214 | nptr = (1 << bshift) / sizeof(uint32_t); |
215 | maxblock = NDADDR + nptr + nptr * nptr + nptr * nptr * nptr; | | 215 | maxblock = NDADDR + nptr + nptr * nptr + nptr * nptr * nptr; |
216 | | | 216 | |
217 | return maxblock << bshift; | | 217 | return maxblock << bshift; |
218 | } | | 218 | } |
219 | | | 219 | |
220 | /* | | 220 | /* |
221 | * Create the root directory for this file system and the lost+found | | 221 | * Create the root directory for this file system and the lost+found |
222 | * directory. | | 222 | * directory. |
223 | */ | | 223 | */ |
224 | static void | | 224 | static void |
225 | make_dinode(ino_t ino, struct ufs1_dinode *dip, int nfrags, struct lfs *fs) | | 225 | make_dinode(ino_t ino, struct ufs1_dinode *dip, int nfrags, struct lfs *fs) |
226 | { | | 226 | { |
227 | int fsb_per_blk, i; | | 227 | int fsb_per_blk, i; |
228 | int nblocks, bb, base, factor, lvl; | | 228 | int nblocks, bb, base, factor, lvl; |
229 | | | 229 | |
230 | nblocks = howmany(nfrags, fs->lfs_frag); | | 230 | nblocks = howmany(nfrags, fs->lfs_frag); |
231 | if(nblocks >= NDADDR) | | 231 | if(nblocks >= NDADDR) |
232 | nfrags = roundup(nfrags, fs->lfs_frag); | | 232 | nfrags = roundup(nfrags, fs->lfs_frag); |
233 | | | 233 | |
234 | dip->di_nlink = 1; | | 234 | dip->di_nlink = 1; |
235 | dip->di_blocks = nfrags; | | 235 | dip->di_blocks = nfrags; |
236 | | | 236 | |
237 | dip->di_size = (nfrags << fs->lfs_ffshift); | | 237 | dip->di_size = (nfrags << fs->lfs_ffshift); |
238 | dip->di_atime = dip->di_mtime = dip->di_ctime = fs->lfs_tstamp; | | 238 | dip->di_atime = dip->di_mtime = dip->di_ctime = fs->lfs_tstamp; |
239 | dip->di_atimensec = dip->di_mtimensec = dip->di_ctimensec = 0; | | 239 | dip->di_atimensec = dip->di_mtimensec = dip->di_ctimensec = 0; |
240 | dip->di_inumber = ino; | | 240 | dip->di_inumber = ino; |
241 | dip->di_gen = 1; | | 241 | dip->di_gen = 1; |
242 | | | 242 | |
243 | fsb_per_blk = blkstofrags(fs, 1); | | 243 | fsb_per_blk = blkstofrags(fs, 1); |
244 | | | 244 | |
245 | if (NDADDR < nblocks) { | | 245 | if (NDADDR < nblocks) { |
246 | /* Count up how many indirect blocks we need, recursively */ | | 246 | /* Count up how many indirect blocks we need, recursively */ |
247 | /* XXX We are only called with nblocks > 1 for Ifile */ | | 247 | /* XXX We are only called with nblocks > 1 for Ifile */ |
248 | bb = nblocks - NDADDR; | | 248 | bb = nblocks - NDADDR; |
249 | while (bb > 0) { | | 249 | while (bb > 0) { |
250 | bb = howmany(bb, NINDIR(fs)); | | 250 | bb = howmany(bb, NINDIR(fs)); |
251 | ifibc += bb; | | 251 | ifibc += bb; |
252 | --bb; | | 252 | --bb; |
253 | } | | 253 | } |
254 | dip->di_blocks += blkstofrags(fs, ifibc); | | 254 | dip->di_blocks += blkstofrags(fs, ifibc); |
255 | } | | 255 | } |
256 | | | 256 | |
257 | /* Assign the block addresses for the ifile */ | | 257 | /* Assign the block addresses for the ifile */ |
258 | for (i = 0; i < MIN(nblocks,NDADDR); i++) { | | 258 | for (i = 0; i < MIN(nblocks,NDADDR); i++) { |
259 | dip->di_db[i] = 0x0; | | 259 | dip->di_db[i] = 0x0; |
260 | } | | 260 | } |
261 | if(nblocks > NDADDR) { | | 261 | if(nblocks > NDADDR) { |
262 | dip->di_ib[0] = 0x0; | | 262 | dip->di_ib[0] = 0x0; |
263 | bb = howmany(nblocks - NDADDR, NINDIR(fs)) - 1; | | 263 | bb = howmany(nblocks - NDADDR, NINDIR(fs)) - 1; |
264 | factor = NINDIR(fs); | | 264 | factor = NINDIR(fs); |
265 | base = -NDADDR - factor; | | 265 | base = -NDADDR - factor; |
266 | lvl = 1; | | 266 | lvl = 1; |
267 | while (bb > 0) { | | 267 | while (bb > 0) { |
268 | dip->di_ib[lvl] = 0x0; | | 268 | dip->di_ib[lvl] = 0x0; |
269 | bb = howmany(bb, NINDIR(fs)); | | 269 | bb = howmany(bb, NINDIR(fs)); |
270 | --bb; | | 270 | --bb; |
271 | factor *= NINDIR(fs); | | 271 | factor *= NINDIR(fs); |
272 | base -= factor; | | 272 | base -= factor; |
273 | ++lvl; | | 273 | ++lvl; |
274 | } | | 274 | } |
275 | } | | 275 | } |
276 | } | | 276 | } |
277 | | | 277 | |
278 | /* | | 278 | /* |
279 | * Construct a set of directory entries in "bufp". We assume that all the | | 279 | * Construct a set of directory entries in "bufp". We assume that all the |
280 | * entries in protodir fir in the first DIRBLKSIZ. | | 280 | * entries in protodir fir in the first DIRBLKSIZ. |
281 | */ | | 281 | */ |
282 | static void | | 282 | static void |
283 | make_dir(void *bufp, struct direct *protodir, int entries) | | 283 | make_dir(void *bufp, struct direct *protodir, int entries) |
284 | { | | 284 | { |
285 | char *cp; | | 285 | char *cp; |
286 | int i, spcleft; | | 286 | int i, spcleft; |
287 | | | 287 | |
288 | spcleft = DIRBLKSIZ; | | 288 | spcleft = DIRBLKSIZ; |
289 | for (cp = bufp, i = 0; i < entries - 1; i++) { | | 289 | for (cp = bufp, i = 0; i < entries - 1; i++) { |
290 | protodir[i].d_reclen = DIRSIZ(NEWDIRFMT, &protodir[i], 0); | | 290 | protodir[i].d_reclen = DIRSIZ(NEWDIRFMT, &protodir[i], 0); |
291 | memmove(cp, &protodir[i], protodir[i].d_reclen); | | 291 | memmove(cp, &protodir[i], protodir[i].d_reclen); |
292 | cp += protodir[i].d_reclen; | | 292 | cp += protodir[i].d_reclen; |
293 | if ((spcleft -= protodir[i].d_reclen) < 0) | | 293 | if ((spcleft -= protodir[i].d_reclen) < 0) |
294 | fatal("%s: %s", special, "directory too big"); | | 294 | fatal("%s: %s", special, "directory too big"); |
295 | } | | 295 | } |
296 | protodir[i].d_reclen = spcleft; | | 296 | protodir[i].d_reclen = spcleft; |
297 | memmove(cp, &protodir[i], DIRSIZ(NEWDIRFMT, &protodir[i], 0)); | | 297 | memmove(cp, &protodir[i], DIRSIZ(NEWDIRFMT, &protodir[i], 0)); |
298 | } | | 298 | } |
299 | | | 299 | |
300 | int | | 300 | int |
301 | make_lfs(int devfd, uint secsize, struct dkwedge_info *dkw, int minfree, | | 301 | make_lfs(int devfd, uint secsize, struct dkwedge_info *dkw, int minfree, |
302 | int block_size, int frag_size, int seg_size, int minfreeseg, | | 302 | int block_size, int frag_size, int seg_size, int minfreeseg, |
303 | int resvseg, int version, daddr_t start, int ibsize, int interleave, | | 303 | int resvseg, int version, daddr_t start, int ibsize, int interleave, |
304 | u_int32_t roll_id) | | 304 | u_int32_t roll_id) |
305 | { | | 305 | { |
306 | struct ufs1_dinode *dip; /* Pointer to a disk inode */ | | 306 | struct ufs1_dinode *dip; /* Pointer to a disk inode */ |
307 | CLEANERINFO *cip; /* Segment cleaner information table */ | | 307 | CLEANERINFO *cip; /* Segment cleaner information table */ |
308 | IFILE *ip; /* Pointer to array of ifile structures */ | | 308 | IFILE *ip; /* Pointer to array of ifile structures */ |
309 | IFILE_V1 *ip_v1 = NULL; | | 309 | IFILE_V1 *ip_v1 = NULL; |
310 | struct lfs *fs; /* Superblock */ | | 310 | struct lfs *fs; /* Superblock */ |
311 | SEGUSE *segp; /* Segment usage table */ | | 311 | SEGUSE *segp; /* Segment usage table */ |
312 | daddr_t sb_addr; /* Address of superblocks */ | | 312 | daddr_t sb_addr; /* Address of superblocks */ |
313 | daddr_t seg_addr; /* Address of current segment */ | | 313 | daddr_t seg_addr; /* Address of current segment */ |
314 | int bsize; /* Block size */ | | 314 | int bsize; /* Block size */ |
315 | int fsize; /* Fragment size */ | | 315 | int fsize; /* Fragment size */ |
316 | int db_per_blk; /* Disk blocks per file block */ | | 316 | int db_per_blk; /* Disk blocks per file block */ |
317 | int i, j; | | 317 | int i, j; |
318 | int sb_interval; /* number of segs between super blocks */ | | 318 | int sb_interval; /* number of segs between super blocks */ |
319 | int ssize; /* Segment size */ | | 319 | int ssize; /* Segment size */ |
320 | double fssize; | | 320 | double fssize; |
321 | int warned_segtoobig=0; | | 321 | int warned_segtoobig=0; |
322 | int label_fsb, sb_fsb; | | 322 | int label_fsb, sb_fsb; |
323 | int curw, ww; | | 323 | int curw, ww; |
324 | char tbuf[BUFSIZ]; | | 324 | char tbuf[BUFSIZ]; |
325 | struct ubuf *bp; | | 325 | struct ubuf *bp; |
326 | struct uvnode *vp, *save_devvp; | | 326 | struct uvnode *vp, *save_devvp; |
327 | int bb, ubb, dmeta, labelskew; | | 327 | int bb, ubb, dmeta, labelskew; |
328 | u_int64_t tsepb, tnseg; | | 328 | u_int64_t tsepb, tnseg; |
329 | | | 329 | |
330 | /* | | 330 | /* |
331 | * Initialize buffer cache. Use a ballpark guess of the length of | | 331 | * Initialize buffer cache. Use a ballpark guess of the length of |
332 | * the segment table for the number of hash chains. | | 332 | * the segment table for the number of hash chains. |
333 | */ | | 333 | */ |
334 | tnseg = dkw->dkw_size / ((seg_size ? seg_size : DFL_LFSSEG) / secsize); | | 334 | tnseg = dkw->dkw_size / ((seg_size ? seg_size : DFL_LFSSEG) / secsize); |
335 | tsepb = (block_size ? block_size : DFL_LFSBLOCK) / sizeof(SEGSUM); | | 335 | tsepb = (block_size ? block_size : DFL_LFSBLOCK) / sizeof(SEGSUM); |
336 | if (tnseg == 0) | | 336 | if (tnseg == 0) |
337 | fatal("zero size partition"); | | 337 | fatal("zero size partition"); |
338 | bufinit(tnseg / tsepb); | | 338 | bufinit(tnseg / tsepb); |
339 | | | 339 | |
340 | /* Initialize LFS subsystem with blank superblock and ifile. */ | | 340 | /* Initialize LFS subsystem with blank superblock and ifile. */ |
341 | fs = lfs_init(devfd, start, (ufs_daddr_t)0, 1, 1/* XXX debug*/); | | 341 | fs = lfs_init(devfd, start, (ufs_daddr_t)0, 1, 1/* XXX debug*/); |
342 | save_devvp = fs->lfs_devvp; | | 342 | save_devvp = fs->lfs_devvp; |
343 | vp = fs->lfs_ivnode; | | 343 | vp = fs->lfs_ivnode; |
344 | *fs = lfs_default; | | 344 | *fs = lfs_default; |
345 | fs->lfs_ivnode = vp; | | 345 | fs->lfs_ivnode = vp; |
346 | fs->lfs_devvp = save_devvp; | | 346 | fs->lfs_devvp = save_devvp; |
347 | | | 347 | |
348 | | | 348 | |
349 | /* Set version first of all since it is used to compute other fields */ | | 349 | /* Set version first of all since it is used to compute other fields */ |
350 | fs->lfs_version = version; | | 350 | fs->lfs_version = version; |
351 | | | 351 | |
352 | /* If partition is not an LFS partition, warn that that is the case */ | | 352 | /* If partition is not an LFS partition, warn that that is the case */ |
353 | if (strcmp(dkw->dkw_ptype, DKW_PTYPE_LFS) != 0) { | | 353 | if (strcmp(dkw->dkw_ptype, DKW_PTYPE_LFS) != 0) { |
354 | fatal("partition label indicated fs type \"%s\", " | | 354 | fatal("partition label indicated fs type \"%s\", " |
355 | "expected \"%s\"", dkw->dkw_ptype, DKW_PTYPE_LFS); | | 355 | "expected \"%s\"", dkw->dkw_ptype, DKW_PTYPE_LFS); |
356 | } | | 356 | } |
357 | | | 357 | |
358 | if (!(bsize = block_size)) | | 358 | if (!(bsize = block_size)) |
359 | bsize = DFL_LFSBLOCK; | | 359 | bsize = DFL_LFSBLOCK; |
360 | if (!(fsize = frag_size)) | | 360 | if (!(fsize = frag_size)) |
361 | fsize = DFL_LFSFRAG; | | 361 | fsize = DFL_LFSFRAG; |
362 | if (!(ssize = seg_size)) { | | 362 | if (!(ssize = seg_size)) { |
363 | ssize = DFL_LFSSEG; | | 363 | ssize = DFL_LFSSEG; |
364 | } | | 364 | } |
365 | if (version > 1) { | | 365 | if (version > 1) { |
366 | if (ibsize == 0) | | 366 | if (ibsize == 0) |
367 | ibsize = fsize; | | 367 | ibsize = fsize; |
368 | if (ibsize <= 0 || ibsize % fsize) | | 368 | if (ibsize <= 0 || ibsize % fsize) |
369 | fatal("illegal inode block size: %d\n", ibsize); | | 369 | fatal("illegal inode block size: %d\n", ibsize); |
370 | } else if (ibsize && ibsize != bsize) | | 370 | } else if (ibsize && ibsize != bsize) |
371 | fatal("cannot specify inode block size when version == 1\n"); | | 371 | fatal("cannot specify inode block size when version == 1\n"); |
372 | | | 372 | |
373 | /* Sanity check: fsize<=bsize<ssize */ | | 373 | /* Sanity check: fsize<=bsize<ssize */ |
374 | if (fsize > bsize) { | | 374 | if (fsize > bsize) { |
375 | /* Only complain if fsize was explicitly set */ | | 375 | /* Only complain if fsize was explicitly set */ |
376 | if(frag_size) | | 376 | if(frag_size) |
377 | fatal("fragment size must be <= block size %d", bsize); | | 377 | fatal("fragment size must be <= block size %d", bsize); |
378 | fsize = bsize; | | 378 | fsize = bsize; |
379 | } | | 379 | } |
380 | if (bsize >= ssize) { | | 380 | if (bsize >= ssize) { |
381 | /* Only fatal if ssize was explicitly set */ | | 381 | /* Only fatal if ssize was explicitly set */ |
382 | if(seg_size) | | 382 | if(seg_size) |
383 | fatal("block size must be < segment size"); | | 383 | fatal("block size must be < segment size"); |
384 | warnx("%s: disklabel segment size (%d) too small, using default (%d)", | | 384 | warnx("%s: disklabel segment size (%d) too small, using default (%d)", |
385 | progname, ssize, DFL_LFSSEG); | | 385 | progname, ssize, DFL_LFSSEG); |
386 | ssize = DFL_LFSSEG; | | 386 | ssize = DFL_LFSSEG; |
387 | } | | 387 | } |
388 | if (start < 0 || start >= dkw->dkw_size) | | 388 | if (start < 0 || start >= dkw->dkw_size) |
389 | fatal("filesystem offset %ld out of range", (long)start); | | 389 | fatal("filesystem offset %ld out of range", (long)start); |
390 | if (version == 1) { | | 390 | if (version == 1) { |
391 | if (start) | | 391 | if (start) |
392 | warnx("filesystem offset ignored for version 1 filesystem"); | | 392 | warnx("filesystem offset ignored for version 1 filesystem"); |
393 | start = LFS_LABELPAD / secsize; | | 393 | start = LFS_LABELPAD / secsize; |
394 | } | | 394 | } |
395 | | | 395 | |
396 | tryagain: | | 396 | tryagain: |
397 | /* Modify parts of superblock overridden by command line arguments */ | | 397 | /* Modify parts of superblock overridden by command line arguments */ |
398 | if (bsize != DFL_LFSBLOCK || fsize != DFL_LFSFRAG) { | | 398 | if (bsize != DFL_LFSBLOCK || fsize != DFL_LFSFRAG) { |
399 | fs->lfs_bshift = lfs_log2(bsize); | | 399 | fs->lfs_bshift = lfs_log2(bsize); |
400 | if (1 << fs->lfs_bshift != bsize) | | 400 | if (1 << fs->lfs_bshift != bsize) |
401 | fatal("%d: block size not a power of 2", bsize); | | 401 | fatal("%d: block size not a power of 2", bsize); |
402 | fs->lfs_bsize = bsize; | | 402 | fs->lfs_bsize = bsize; |
403 | fs->lfs_fsize = fsize; | | 403 | fs->lfs_fsize = fsize; |
404 | fs->lfs_bmask = bsize - 1; | | 404 | fs->lfs_bmask = bsize - 1; |
405 | fs->lfs_ffmask = fsize - 1; | | 405 | fs->lfs_ffmask = fsize - 1; |
406 | fs->lfs_ffshift = lfs_log2(fsize); | | 406 | fs->lfs_ffshift = lfs_log2(fsize); |
407 | if (1 << fs->lfs_ffshift != fsize) | | 407 | if (1 << fs->lfs_ffshift != fsize) |
408 | fatal("%d: frag size not a power of 2", fsize); | | 408 | fatal("%d: frag size not a power of 2", fsize); |
409 | fs->lfs_frag = numfrags(fs, bsize); | | 409 | fs->lfs_frag = numfrags(fs, bsize); |
410 | fs->lfs_fbmask = fs->lfs_frag - 1; | | 410 | fs->lfs_fbmask = fs->lfs_frag - 1; |
411 | fs->lfs_fbshift = lfs_log2(fs->lfs_frag); | | 411 | fs->lfs_fbshift = lfs_log2(fs->lfs_frag); |
412 | fs->lfs_ifpb = bsize / sizeof(IFILE); | | 412 | fs->lfs_ifpb = bsize / sizeof(IFILE); |
413 | /* XXX ondisk32 */ | | 413 | /* XXX ondisk32 */ |
414 | fs->lfs_nindir = bsize / sizeof(int32_t); | | 414 | fs->lfs_nindir = bsize / sizeof(int32_t); |
415 | } | | 415 | } |
416 | | | 416 | |
417 | if (fs->lfs_version == 1) { | | 417 | if (fs->lfs_version == 1) { |
418 | fs->lfs_sumsize = LFS_V1_SUMMARY_SIZE; | | 418 | fs->lfs_sumsize = LFS_V1_SUMMARY_SIZE; |
419 | fs->lfs_segshift = lfs_log2(ssize); | | 419 | fs->lfs_segshift = lfs_log2(ssize); |
420 | if (1 << fs->lfs_segshift != ssize) | | 420 | if (1 << fs->lfs_segshift != ssize) |
421 | fatal("%d: segment size not power of 2", ssize); | | 421 | fatal("%d: segment size not power of 2", ssize); |
422 | fs->lfs_segmask = ssize - 1; | | 422 | fs->lfs_segmask = ssize - 1; |
423 | fs->lfs_ifpb = fs->lfs_bsize / sizeof(IFILE_V1); | | 423 | fs->lfs_ifpb = fs->lfs_bsize / sizeof(IFILE_V1); |
424 | fs->lfs_ibsize = fs->lfs_bsize; | | 424 | fs->lfs_ibsize = fs->lfs_bsize; |
425 | fs->lfs_sepb = bsize / sizeof(SEGUSE_V1); | | 425 | fs->lfs_sepb = bsize / sizeof(SEGUSE_V1); |
426 | fs->lfs_ssize = ssize >> fs->lfs_bshift; | | 426 | fs->lfs_ssize = ssize >> fs->lfs_bshift; |
427 | } else { | | 427 | } else { |
428 | if (ssize % fsize) { | | 428 | if (ssize % fsize) { |
429 | fprintf(stderr, | | 429 | fprintf(stderr, |
430 | "Segment size %d is not a multiple of frag size; ", | | 430 | "Segment size %d is not a multiple of frag size; ", |
431 | ssize); | | 431 | ssize); |
432 | ssize = roundup(ssize, fsize); | | 432 | ssize = roundup(ssize, fsize); |
433 | fprintf(stderr, "trying size %d.\n", ssize); | | 433 | fprintf(stderr, "trying size %d.\n", ssize); |
434 | goto tryagain; | | 434 | goto tryagain; |
435 | } | | 435 | } |
436 | fs->lfs_sumsize = fsize; | | 436 | fs->lfs_sumsize = fsize; |
437 | fs->lfs_segshift = 0; | | 437 | fs->lfs_segshift = 0; |
438 | fs->lfs_segmask = 0; | | 438 | fs->lfs_segmask = 0; |
439 | fs->lfs_sepb = bsize / sizeof(SEGUSE); | | 439 | fs->lfs_sepb = bsize / sizeof(SEGUSE); |
440 | fs->lfs_ssize = ssize; | | 440 | fs->lfs_ssize = ssize; |
441 | fs->lfs_ibsize = ibsize; | | 441 | fs->lfs_ibsize = ibsize; |
442 | } | | 442 | } |
443 | fs->lfs_inopb = fs->lfs_ibsize / sizeof(struct ufs1_dinode); | | 443 | fs->lfs_inopb = fs->lfs_ibsize / sizeof(struct ufs1_dinode); |
444 | fs->lfs_minfree = minfree; | | 444 | fs->lfs_minfree = minfree; |
445 | | | 445 | |
446 | if (version > 1) { | | 446 | if (version > 1) { |
447 | fs->lfs_inopf = secsize/DINODE1_SIZE; | | 447 | fs->lfs_inopf = secsize/DINODE1_SIZE; |
448 | fs->lfs_interleave = interleave; | | 448 | fs->lfs_interleave = interleave; |
449 | if (roll_id == 0) | | 449 | if (roll_id == 0) |
450 | roll_id = arc4random(); | | 450 | roll_id = arc4random(); |
451 | fs->lfs_ident = roll_id; | | 451 | fs->lfs_ident = roll_id; |
452 | } | | 452 | } |
453 | | | 453 | |
454 | /* | | 454 | /* |
455 | * Fill in parts of superblock that can be computed from file system | | 455 | * Fill in parts of superblock that can be computed from file system |
456 | * size, disk geometry and current time. | | 456 | * size, disk geometry and current time. |
457 | */ | | 457 | */ |
458 | db_per_blk = bsize/secsize; | | 458 | db_per_blk = bsize/secsize; |
459 | fs->lfs_blktodb = lfs_log2(db_per_blk); | | 459 | fs->lfs_blktodb = lfs_log2(db_per_blk); |
460 | fs->lfs_fsbtodb = lfs_log2(fsize / secsize); | | 460 | fs->lfs_fsbtodb = lfs_log2(fsize / secsize); |
461 | if (version == 1) { | | 461 | if (version == 1) { |
462 | fs->lfs_sushift = lfs_log2(fs->lfs_sepb); | | 462 | fs->lfs_sushift = lfs_log2(fs->lfs_sepb); |
463 | fs->lfs_fsbtodb = 0; | | 463 | fs->lfs_fsbtodb = 0; |
464 | fs->lfs_size = dkw->dkw_size >> fs->lfs_blktodb; | | 464 | fs->lfs_size = dkw->dkw_size >> fs->lfs_blktodb; |
465 | } | | 465 | } |
466 | label_fsb = btofsb(fs, roundup(LFS_LABELPAD, fsize)); | | 466 | label_fsb = btofsb(fs, roundup(LFS_LABELPAD, fsize)); |
467 | sb_fsb = btofsb(fs, roundup(LFS_SBPAD, fsize)); | | 467 | sb_fsb = btofsb(fs, roundup(LFS_SBPAD, fsize)); |
468 | fs->lfs_fsbpseg = dbtofsb(fs, ssize / secsize); | | 468 | fs->lfs_fsbpseg = dbtofsb(fs, ssize / secsize); |
469 | fs->lfs_size = dkw->dkw_size >> fs->lfs_fsbtodb; | | 469 | fs->lfs_size = dkw->dkw_size >> fs->lfs_fsbtodb; |
470 | fs->lfs_dsize = dbtofsb(fs, dkw->dkw_size) - | | 470 | fs->lfs_dsize = dbtofsb(fs, dkw->dkw_size) - |
471 | MAX(label_fsb, dbtofsb(fs, start)); | | 471 | MAX(label_fsb, dbtofsb(fs, start)); |
472 | fs->lfs_nseg = fs->lfs_dsize / segtod(fs, 1); | | 472 | fs->lfs_nseg = fs->lfs_dsize / segtod(fs, 1); |
473 | | | 473 | |
474 | fs->lfs_nclean = fs->lfs_nseg - 1; | | 474 | fs->lfs_nclean = fs->lfs_nseg - 1; |
475 | fs->lfs_maxfilesize = maxfilesize(fs->lfs_bshift); | | 475 | fs->lfs_maxfilesize = maxfilesize(fs->lfs_bshift); |
476 | | | 476 | |
477 | if (minfreeseg == 0) | | 477 | if (minfreeseg == 0) |
478 | fs->lfs_minfreeseg = fs->lfs_nseg / DFL_MIN_FREE_SEGS; | | 478 | fs->lfs_minfreeseg = fs->lfs_nseg / DFL_MIN_FREE_SEGS; |
479 | else | | 479 | else |
480 | fs->lfs_minfreeseg = minfreeseg; | | 480 | fs->lfs_minfreeseg = minfreeseg; |
481 | if (fs->lfs_minfreeseg < MIN_FREE_SEGS) | | 481 | if (fs->lfs_minfreeseg < MIN_FREE_SEGS) |
482 | fs->lfs_minfreeseg = MIN_FREE_SEGS; | | 482 | fs->lfs_minfreeseg = MIN_FREE_SEGS; |
483 | | | 483 | |
484 | if (resvseg == 0) | | 484 | if (resvseg == 0) |
485 | fs->lfs_resvseg = fs->lfs_minfreeseg / 2 + 1; | | 485 | fs->lfs_resvseg = fs->lfs_minfreeseg / 2 + 1; |
486 | else | | 486 | else |
487 | fs->lfs_resvseg = resvseg; | | 487 | fs->lfs_resvseg = resvseg; |
488 | if (fs->lfs_resvseg < MIN_RESV_SEGS) | | 488 | if (fs->lfs_resvseg < MIN_RESV_SEGS) |
489 | fs->lfs_resvseg = MIN_RESV_SEGS; | | 489 | fs->lfs_resvseg = MIN_RESV_SEGS; |
490 | | | 490 | |
491 | if(fs->lfs_nseg < fs->lfs_minfreeseg + 1 | | 491 | if(fs->lfs_nseg < (3 * CM_MAG_NUM * fs->lfs_minfreeseg) / CM_MAG_DEN + 1 |
492 | || fs->lfs_nseg < LFS_MIN_SBINTERVAL + 1) | | 492 | || fs->lfs_nseg < LFS_MIN_SBINTERVAL + 1) |
493 | { | | 493 | { |
494 | if(seg_size == 0 && ssize > (bsize<<1)) { | | 494 | if(seg_size == 0 && ssize > (bsize<<1)) { |
495 | if(!warned_segtoobig) { | | 495 | if(!warned_segtoobig) { |
496 | fprintf(stderr,"Segment size %d is too large; " | | 496 | fprintf(stderr,"Segment size %d is too large; " |
497 | "trying smaller sizes.\n", ssize); | | 497 | "trying smaller sizes.\n", ssize); |
498 | if (ssize == (bsize << 16)) { | | 498 | if (ssize == (bsize << 16)) { |
499 | fprintf(stderr, "(Did you perhaps " | | 499 | fprintf(stderr, "(Did you perhaps " |
500 | "accidentally leave \"16\" " | | 500 | "accidentally leave \"16\" " |
501 | "in the disklabel's sgs " | | 501 | "in the disklabel's sgs " |
502 | "field?)\n"); | | 502 | "field?)\n"); |
503 | } | | 503 | } |
504 | } | | 504 | } |
505 | ++warned_segtoobig; | | 505 | ++warned_segtoobig; |
506 | ssize >>= 1; | | 506 | ssize >>= 1; |
507 | goto tryagain; | | 507 | goto tryagain; |
508 | } | | 508 | } |
509 | fatal("Could not allocate enough segments with segment " | | 509 | fatal("Could not allocate enough segments with segment " |
510 | "size %d and block size %d;\nplease decrease the " | | 510 | "size %d and block size %d;\nplease decrease the " |
511 | "segment size.\n", ssize, fs->lfs_bsize); | | 511 | "segment size.\n", ssize, fs->lfs_bsize); |
512 | } | | 512 | } |
| | | 513 | if(warned_segtoobig) |
| | | 514 | fprintf(stderr,"Using segment size %d.\n", ssize); |
513 | | | 515 | |
514 | /* | | 516 | /* |
515 | * Now that we've determined what we're going to do, announce it | | 517 | * Now that we've determined what we're going to do, announce it |
516 | * to the user. | | 518 | * to the user. |
517 | */ | | 519 | */ |
518 | printf("Creating a version %d LFS", fs->lfs_version); | | 520 | printf("Creating a version %d LFS", fs->lfs_version); |
519 | if (fs->lfs_version > 1) | | 521 | if (fs->lfs_version > 1) |
520 | printf(" with roll-forward ident 0x%x", fs->lfs_ident); | | 522 | printf(" with roll-forward ident 0x%x", fs->lfs_ident); |
521 | printf("\n"); | | 523 | printf("\n"); |
522 | fssize = (double)fs->lfs_nseg; | | 524 | fssize = (double)fs->lfs_nseg; |
523 | fssize *= (double)ssize; | | 525 | fssize *= (double)ssize; |
524 | fssize /= 1048576.0; | | 526 | fssize /= 1048576.0; |
525 | printf("%.1fMB in %d segments of size %d\n", fssize, | | 527 | printf("%.1fMB in %d segments of size %d\n", fssize, |
526 | fs->lfs_nseg, ssize); | | 528 | fs->lfs_nseg, ssize); |
527 | | | 529 | |
528 | /* | | 530 | /* |
529 | * The number of free blocks is set from the number of segments | | 531 | * The number of free blocks is set from the number of segments |
530 | * times the segment size - lfs_minfreesegs (that we never write | | 532 | * times the segment size - lfs_minfreesegs (that we never write |
531 | * because we need to make sure the cleaner can run). Then | | 533 | * because we need to make sure the cleaner can run). Then |
532 | * we'll subtract off the room for the superblocks ifile entries | | 534 | * we'll subtract off the room for the superblocks ifile entries |
533 | * and segment usage table, and half a block per segment that can't | | 535 | * and segment usage table, and half a block per segment that can't |
534 | * be written due to fragmentation. | | 536 | * be written due to fragmentation. |
535 | */ | | 537 | */ |
536 | fs->lfs_dsize = (fs->lfs_nseg - fs->lfs_minfreeseg) * | | 538 | fs->lfs_dsize = (fs->lfs_nseg - fs->lfs_minfreeseg) * |
537 | segtod(fs, 1); | | 539 | segtod(fs, 1); |
538 | fs->lfs_bfree = fs->lfs_dsize; | | 540 | fs->lfs_bfree = fs->lfs_dsize; |
539 | fs->lfs_bfree -= dbtofsb(fs, ((fs->lfs_nseg / 2) << | | 541 | fs->lfs_bfree -= dbtofsb(fs, ((fs->lfs_nseg / 2) << |
540 | fs->lfs_blktodb)); | | 542 | fs->lfs_blktodb)); |
541 | | | 543 | |
542 | fs->lfs_segtabsz = SEGTABSIZE_SU(fs); | | 544 | fs->lfs_segtabsz = SEGTABSIZE_SU(fs); |
543 | fs->lfs_cleansz = CLEANSIZE_SU(fs); | | 545 | fs->lfs_cleansz = CLEANSIZE_SU(fs); |
544 | if ((fs->lfs_tstamp = time(NULL)) == -1) | | 546 | if ((fs->lfs_tstamp = time(NULL)) == -1) |
545 | fatal("time: %s", strerror(errno)); | | 547 | fatal("time: %s", strerror(errno)); |
546 | if (version == 1) | | 548 | if (version == 1) |
547 | fs->lfs_otstamp = fs->lfs_tstamp; | | 549 | fs->lfs_otstamp = fs->lfs_tstamp; |
548 | | | 550 | |
549 | if ((sb_interval = fs->lfs_nseg / LFS_MAXNUMSB) < LFS_MIN_SBINTERVAL) | | 551 | if ((sb_interval = fs->lfs_nseg / LFS_MAXNUMSB) < LFS_MIN_SBINTERVAL) |
550 | sb_interval = LFS_MIN_SBINTERVAL; | | 552 | sb_interval = LFS_MIN_SBINTERVAL; |
551 | | | 553 | |
552 | /* | | 554 | /* |
553 | * Figure out where the superblocks are going to live. | | 555 | * Figure out where the superblocks are going to live. |
554 | * | | 556 | * |
555 | * Make segment 0 start at either zero, or LFS_LABELPAD, or | | 557 | * Make segment 0 start at either zero, or LFS_LABELPAD, or |
556 | * >= LFS_SBPAD+LFS_LABELPAD, in order to prevent segment 0 | | 558 | * >= LFS_SBPAD+LFS_LABELPAD, in order to prevent segment 0 |
557 | * from having half a superblock in it. | | 559 | * from having half a superblock in it. |
558 | */ | | 560 | */ |
559 | if (fsbtodb(fs, dbtofsb(fs, start)) != start) | | 561 | if (fsbtodb(fs, dbtofsb(fs, start)) != start) |
560 | fatal("Segment 0 offset is not multiple of frag size\n"); | | 562 | fatal("Segment 0 offset is not multiple of frag size\n"); |
561 | if (start != 0 && dbtob(start) != LFS_LABELPAD && | | 563 | if (start != 0 && dbtob(start) != LFS_LABELPAD && |
562 | dbtob(start) < LFS_SBPAD + LFS_LABELPAD) { | | 564 | dbtob(start) < LFS_SBPAD + LFS_LABELPAD) { |
563 | fatal("Using flags \"-O %" PRId64 "\" would result in the " | | 565 | fatal("Using flags \"-O %" PRId64 "\" would result in the " |
564 | "first segment containing only\npart of a superblock. " | | 566 | "first segment containing only\npart of a superblock. " |
565 | "Please choose an offset of 0, %d, or %d or more,\n", | | 567 | "Please choose an offset of 0, %d, or %d or more,\n", |
566 | start, btodb(LFS_LABELPAD), | | 568 | start, btodb(LFS_LABELPAD), |
567 | btodb(LFS_LABELPAD + LFS_SBPAD)); | | 569 | btodb(LFS_LABELPAD + LFS_SBPAD)); |
568 | } | | 570 | } |
569 | fs->lfs_sboffs[0] = label_fsb; | | 571 | fs->lfs_sboffs[0] = label_fsb; |
570 | if (version == 1) | | 572 | if (version == 1) |
571 | fs->lfs_start = fs->lfs_sboffs[0]; | | 573 | fs->lfs_start = fs->lfs_sboffs[0]; |
572 | else | | 574 | else |
573 | fs->lfs_start = dbtofsb(fs, start); | | 575 | fs->lfs_start = dbtofsb(fs, start); |
574 | fs->lfs_dsize -= sb_fsb; | | 576 | fs->lfs_dsize -= sb_fsb; |
575 | for (i = 1; i < LFS_MAXNUMSB; i++) { | | 577 | for (i = 1; i < LFS_MAXNUMSB; i++) { |
576 | sb_addr = ((i * sb_interval) * segtod(fs, 1)) | | 578 | sb_addr = ((i * sb_interval) * segtod(fs, 1)) |
577 | + fs->lfs_sboffs[0]; | | 579 | + fs->lfs_sboffs[0]; |
578 | /* Segment 0 eats the label, except for version 1 */ | | 580 | /* Segment 0 eats the label, except for version 1 */ |
579 | if (fs->lfs_version > 1 && fs->lfs_start < label_fsb) | | 581 | if (fs->lfs_version > 1 && fs->lfs_start < label_fsb) |
580 | sb_addr -= label_fsb - start; | | 582 | sb_addr -= label_fsb - start; |
581 | if (sb_addr + sizeof(struct dlfs) | | 583 | if (sb_addr + sizeof(struct dlfs) |
582 | >= dbtofsb(fs, dkw->dkw_size)) | | 584 | >= dbtofsb(fs, dkw->dkw_size)) |
583 | break; | | 585 | break; |
584 | fs->lfs_sboffs[i] = sb_addr; | | 586 | fs->lfs_sboffs[i] = sb_addr; |
585 | fs->lfs_dsize -= sb_fsb; | | 587 | fs->lfs_dsize -= sb_fsb; |
586 | } | | 588 | } |
587 | | | 589 | |
588 | /* We need >= 2 superblocks */ | | 590 | /* We need >= 2 superblocks */ |
589 | if(fs->lfs_sboffs[1] == 0x0) { | | 591 | if(fs->lfs_sboffs[1] == 0x0) { |
590 | fatal("Could not assign a disk address for the second " | | 592 | fatal("Could not assign a disk address for the second " |
591 | "superblock.\nPlease decrease the segment size.\n"); | | 593 | "superblock.\nPlease decrease the segment size.\n"); |
592 | } | | 594 | } |
593 | | | 595 | |
594 | fs->lfs_lastseg = sntod(fs, fs->lfs_nseg - 2); | | 596 | fs->lfs_lastseg = sntod(fs, fs->lfs_nseg - 2); |
595 | fs->lfs_curseg = sntod(fs, fs->lfs_nseg - 1); | | 597 | fs->lfs_curseg = sntod(fs, fs->lfs_nseg - 1); |
596 | fs->lfs_offset = sntod(fs, fs->lfs_nseg); | | 598 | fs->lfs_offset = sntod(fs, fs->lfs_nseg); |
597 | fs->lfs_nextseg = sntod(fs, 0); | | 599 | fs->lfs_nextseg = sntod(fs, 0); |
598 | | | 600 | |
599 | /* | | 601 | /* |
600 | * Initialize the Ifile inode. Do this before we do anything | | 602 | * Initialize the Ifile inode. Do this before we do anything |
601 | * with the Ifile or segment tables. | | 603 | * with the Ifile or segment tables. |
602 | */ | | 604 | */ |
603 | dip = VTOI(fs->lfs_ivnode)->i_din.ffs1_din = (struct ufs1_dinode *) | | 605 | dip = VTOI(fs->lfs_ivnode)->i_din.ffs1_din = (struct ufs1_dinode *) |
604 | malloc(sizeof(*dip)); | | 606 | malloc(sizeof(*dip)); |
605 | if (dip == NULL) | | 607 | if (dip == NULL) |
606 | err(1, NULL); | | 608 | err(1, NULL); |
607 | memset(dip, 0, sizeof(*dip)); | | 609 | memset(dip, 0, sizeof(*dip)); |
608 | dip->di_mode = IFREG|IREAD|IWRITE; | | 610 | dip->di_mode = IFREG|IREAD|IWRITE; |
609 | dip->di_flags = SF_IMMUTABLE; | | 611 | dip->di_flags = SF_IMMUTABLE; |
610 | make_dinode(LFS_IFILE_INUM, dip, | | 612 | make_dinode(LFS_IFILE_INUM, dip, |
611 | blkstofrags(fs, fs->lfs_cleansz + fs->lfs_segtabsz + 1), fs); | | 613 | blkstofrags(fs, fs->lfs_cleansz + fs->lfs_segtabsz + 1), fs); |
612 | dip->di_size = (fs->lfs_cleansz + fs->lfs_segtabsz + 1) << fs->lfs_bshift; | | 614 | dip->di_size = (fs->lfs_cleansz + fs->lfs_segtabsz + 1) << fs->lfs_bshift; |
613 | for (i = 0; i < NDADDR && i < (dip->di_size >> fs->lfs_bshift); i++) | | 615 | for (i = 0; i < NDADDR && i < (dip->di_size >> fs->lfs_bshift); i++) |
614 | VTOI(fs->lfs_ivnode)->i_lfs_fragsize[i] = fs->lfs_bsize; | | 616 | VTOI(fs->lfs_ivnode)->i_lfs_fragsize[i] = fs->lfs_bsize; |
615 | | | 617 | |
616 | /* | | 618 | /* |
617 | * Set up in-superblock segment usage cache | | 619 | * Set up in-superblock segment usage cache |
618 | */ | | 620 | */ |
619 | fs->lfs_suflags = (u_int32_t **) malloc(2 * sizeof(u_int32_t *)); | | 621 | fs->lfs_suflags = (u_int32_t **) malloc(2 * sizeof(u_int32_t *)); |
620 | if (fs->lfs_suflags == NULL) | | 622 | if (fs->lfs_suflags == NULL) |
621 | err(1, NULL); | | 623 | err(1, NULL); |
622 | fs->lfs_suflags[0] = (u_int32_t *) malloc(fs->lfs_nseg * sizeof(u_int32_t)); | | 624 | fs->lfs_suflags[0] = (u_int32_t *) malloc(fs->lfs_nseg * sizeof(u_int32_t)); |
623 | if (fs->lfs_suflags[0] == NULL) | | 625 | if (fs->lfs_suflags[0] == NULL) |
624 | err(1, NULL); | | 626 | err(1, NULL); |
625 | fs->lfs_suflags[1] = (u_int32_t *) malloc(fs->lfs_nseg * sizeof(u_int32_t)); | | 627 | fs->lfs_suflags[1] = (u_int32_t *) malloc(fs->lfs_nseg * sizeof(u_int32_t)); |
626 | if (fs->lfs_suflags[1] == NULL) | | 628 | if (fs->lfs_suflags[1] == NULL) |
627 | err(1, NULL); | | 629 | err(1, NULL); |
628 | | | 630 | |
629 | /* | | 631 | /* |
630 | * Initialize the cleanerinfo block | | 632 | * Initialize the cleanerinfo block |
631 | */ | | 633 | */ |
632 | LFS_CLEANERINFO(cip, fs, bp); | | 634 | LFS_CLEANERINFO(cip, fs, bp); |
633 | cip->clean = fs->lfs_nseg; | | 635 | cip->clean = fs->lfs_nseg; |
634 | cip->dirty = 0; | | 636 | cip->dirty = 0; |
635 | if (version > 1) { | | 637 | if (version > 1) { |
636 | cip->free_head = HIGHEST_USED_INO + 1; | | 638 | cip->free_head = HIGHEST_USED_INO + 1; |
637 | cip->free_tail = fs->lfs_ifpb - 1; | | 639 | cip->free_tail = fs->lfs_ifpb - 1; |
638 | } | | 640 | } |
639 | LFS_SYNC_CLEANERINFO(cip, fs, bp, 1); | | 641 | LFS_SYNC_CLEANERINFO(cip, fs, bp, 1); |
640 | | | 642 | |
641 | /* | | 643 | /* |
642 | * Run through segment table and initialize that | | 644 | * Run through segment table and initialize that |
643 | */ | | 645 | */ |
644 | for (i = j = 0; i < fs->lfs_nseg; i++) { | | 646 | for (i = j = 0; i < fs->lfs_nseg; i++) { |
645 | LFS_SEGENTRY(segp, fs, i, bp); | | 647 | LFS_SEGENTRY(segp, fs, i, bp); |
646 | | | 648 | |
647 | if (i == 0 && | | 649 | if (i == 0 && |
648 | fs->lfs_start < btofsb(fs, LFS_LABELPAD + LFS_SBPAD)) { | | 650 | fs->lfs_start < btofsb(fs, LFS_LABELPAD + LFS_SBPAD)) { |
649 | segp->su_flags = SEGUSE_SUPERBLOCK; | | 651 | segp->su_flags = SEGUSE_SUPERBLOCK; |
650 | fs->lfs_bfree -= sb_fsb; | | 652 | fs->lfs_bfree -= sb_fsb; |
651 | ++j; | | 653 | ++j; |
652 | } | | 654 | } |
653 | if (i > 0) { | | 655 | if (i > 0) { |
654 | if ((i % sb_interval) == 0 && j < LFS_MAXNUMSB) { | | 656 | if ((i % sb_interval) == 0 && j < LFS_MAXNUMSB) { |
655 | segp->su_flags = SEGUSE_SUPERBLOCK; | | 657 | segp->su_flags = SEGUSE_SUPERBLOCK; |
656 | fs->lfs_bfree -= sb_fsb; | | 658 | fs->lfs_bfree -= sb_fsb; |
657 | ++j; | | 659 | ++j; |
658 | } else | | 660 | } else |
659 | segp->su_flags = 0; | | 661 | segp->su_flags = 0; |
660 | } | | 662 | } |
661 | segp->su_lastmod = 0; | | 663 | segp->su_lastmod = 0; |
662 | segp->su_nbytes = 0; | | 664 | segp->su_nbytes = 0; |
663 | segp->su_ninos = 0; | | 665 | segp->su_ninos = 0; |
664 | segp->su_nsums = 0; | | 666 | segp->su_nsums = 0; |
665 | | | 667 | |
666 | LFS_WRITESEGENTRY(segp, fs, i, bp); | | 668 | LFS_WRITESEGENTRY(segp, fs, i, bp); |
667 | } | | 669 | } |
668 | | | 670 | |
669 | /* Initialize root directory */ | | 671 | /* Initialize root directory */ |
670 | vp = lfs_raw_vget(fs, ROOTINO, devfd, 0x0); | | 672 | vp = lfs_raw_vget(fs, ROOTINO, devfd, 0x0); |
671 | dip = VTOI(vp)->i_din.ffs1_din; | | 673 | dip = VTOI(vp)->i_din.ffs1_din; |
672 | make_dinode(ROOTINO, dip, howmany(DIRBLKSIZ,fs->lfs_fsize), fs); | | 674 | make_dinode(ROOTINO, dip, howmany(DIRBLKSIZ,fs->lfs_fsize), fs); |
673 | dip->di_mode = IFDIR | UMASK; | | 675 | dip->di_mode = IFDIR | UMASK; |
674 | VTOI(vp)->i_lfs_osize = dip->di_size = DIRBLKSIZ; | | 676 | VTOI(vp)->i_lfs_osize = dip->di_size = DIRBLKSIZ; |
675 | #ifdef MAKE_LF_DIR | | 677 | #ifdef MAKE_LF_DIR |
676 | VTOI(vp)->i_nlink = dip->di_nlink = 3; | | 678 | VTOI(vp)->i_nlink = dip->di_nlink = 3; |
677 | #else | | 679 | #else |
678 | VTOI(vp)->i_nlink = dip->di_nlink = 2; | | 680 | VTOI(vp)->i_nlink = dip->di_nlink = 2; |
679 | #endif | | 681 | #endif |
680 | VTOI(vp)->i_lfs_effnblks = dip->di_blocks = | | 682 | VTOI(vp)->i_lfs_effnblks = dip->di_blocks = |
681 | btofsb(fs, roundup(DIRBLKSIZ,fs->lfs_fsize)); | | 683 | btofsb(fs, roundup(DIRBLKSIZ,fs->lfs_fsize)); |
682 | for (i = 0; i < NDADDR && i < howmany(DIRBLKSIZ, fs->lfs_bsize); i++) | | 684 | for (i = 0; i < NDADDR && i < howmany(DIRBLKSIZ, fs->lfs_bsize); i++) |
683 | VTOI(vp)->i_lfs_fragsize[i] = fs->lfs_bsize; | | 685 | VTOI(vp)->i_lfs_fragsize[i] = fs->lfs_bsize; |
684 | if (DIRBLKSIZ < fs->lfs_bsize) | | 686 | if (DIRBLKSIZ < fs->lfs_bsize) |
685 | VTOI(vp)->i_lfs_fragsize[i - 1] = | | 687 | VTOI(vp)->i_lfs_fragsize[i - 1] = |
686 | roundup(DIRBLKSIZ,fs->lfs_fsize); | | 688 | roundup(DIRBLKSIZ,fs->lfs_fsize); |
687 | bread(vp, 0, fs->lfs_fsize, NOCRED, 0, &bp); | | 689 | bread(vp, 0, fs->lfs_fsize, NOCRED, 0, &bp); |
688 | make_dir(bp->b_data, lfs_root_dir, | | 690 | make_dir(bp->b_data, lfs_root_dir, |
689 | sizeof(lfs_root_dir) / sizeof(struct direct)); | | 691 | sizeof(lfs_root_dir) / sizeof(struct direct)); |
690 | VOP_BWRITE(bp); | | 692 | VOP_BWRITE(bp); |
691 | | | 693 | |
692 | #ifdef MAKE_LF_DIR | | 694 | #ifdef MAKE_LF_DIR |
693 | /* Initialize lost+found directory */ | | 695 | /* Initialize lost+found directory */ |
694 | vp = lfs_raw_vget(fs, LOSTFOUNDINO, devfd, 0x0); | | 696 | vp = lfs_raw_vget(fs, LOSTFOUNDINO, devfd, 0x0); |
695 | dip = VTOI(vp)->i_din.ffs1_din; | | 697 | dip = VTOI(vp)->i_din.ffs1_din; |
696 | make_dinode(LOSTFOUNDINO, dip, howmany(DIRBLKSIZ,fs->lfs_fsize), fs); | | 698 | make_dinode(LOSTFOUNDINO, dip, howmany(DIRBLKSIZ,fs->lfs_fsize), fs); |
697 | dip->di_mode = IFDIR | UMASK; | | 699 | dip->di_mode = IFDIR | UMASK; |
698 | VTOI(vp)->i_lfs_osize = dip->di_size = DIRBLKSIZ; | | 700 | VTOI(vp)->i_lfs_osize = dip->di_size = DIRBLKSIZ; |
699 | VTOI(vp)->i_nlink = dip->di_nlink = 2; | | 701 | VTOI(vp)->i_nlink = dip->di_nlink = 2; |
700 | VTOI(vp)->i_lfs_effnblks = dip->di_blocks = | | 702 | VTOI(vp)->i_lfs_effnblks = dip->di_blocks = |
701 | btofsb(fs, roundup(DIRBLKSIZ,fs->lfs_fsize)); | | 703 | btofsb(fs, roundup(DIRBLKSIZ,fs->lfs_fsize)); |
702 | for (i = 0; i < NDADDR && i < howmany(DIRBLKSIZ, fs->lfs_bsize); i++) | | 704 | for (i = 0; i < NDADDR && i < howmany(DIRBLKSIZ, fs->lfs_bsize); i++) |
703 | VTOI(vp)->i_lfs_fragsize[i] = fs->lfs_bsize; | | 705 | VTOI(vp)->i_lfs_fragsize[i] = fs->lfs_bsize; |
704 | if (DIRBLKSIZ < fs->lfs_bsize) | | 706 | if (DIRBLKSIZ < fs->lfs_bsize) |
705 | VTOI(vp)->i_lfs_fragsize[i - 1] = | | 707 | VTOI(vp)->i_lfs_fragsize[i - 1] = |
706 | roundup(DIRBLKSIZ,fs->lfs_fsize); | | 708 | roundup(DIRBLKSIZ,fs->lfs_fsize); |
707 | bread(vp, 0, fs->lfs_fsize, NOCRED, 0, &bp); | | 709 | bread(vp, 0, fs->lfs_fsize, NOCRED, 0, &bp); |
708 | make_dir(bp->b_data, lfs_lf_dir, | | 710 | make_dir(bp->b_data, lfs_lf_dir, |
709 | sizeof(lfs_lf_dir) / sizeof(struct direct)); | | 711 | sizeof(lfs_lf_dir) / sizeof(struct direct)); |
710 | VOP_BWRITE(bp); | | 712 | VOP_BWRITE(bp); |
711 | #endif /* MAKE_LF_DIR */ | | 713 | #endif /* MAKE_LF_DIR */ |
712 | | | 714 | |
713 | /* Set their IFILE entry version numbers to 1 */ | | 715 | /* Set their IFILE entry version numbers to 1 */ |
714 | LFS_IENTRY(ip, fs, 1, bp); | | 716 | LFS_IENTRY(ip, fs, 1, bp); |
715 | if (version == 1) { | | 717 | if (version == 1) { |
716 | ip_v1 = (IFILE_V1 *)ip; | | 718 | ip_v1 = (IFILE_V1 *)ip; |
717 | for (i = LFS_IFILE_INUM; i <= HIGHEST_USED_INO; i++) { | | 719 | for (i = LFS_IFILE_INUM; i <= HIGHEST_USED_INO; i++) { |
718 | ip_v1->if_version = 1; | | 720 | ip_v1->if_version = 1; |
719 | ip_v1->if_daddr = 0x0; | | 721 | ip_v1->if_daddr = 0x0; |
720 | ip_v1->if_nextfree = 0; | | 722 | ip_v1->if_nextfree = 0; |
721 | ++ip_v1; | | 723 | ++ip_v1; |
722 | } | | 724 | } |
723 | } else { | | 725 | } else { |
724 | for (i = LFS_IFILE_INUM; i <= HIGHEST_USED_INO; i++) { | | 726 | for (i = LFS_IFILE_INUM; i <= HIGHEST_USED_INO; i++) { |
725 | ip->if_version = 1; | | 727 | ip->if_version = 1; |
726 | ip->if_daddr = 0x0; | | 728 | ip->if_daddr = 0x0; |
727 | ip->if_nextfree = 0; | | 729 | ip->if_nextfree = 0; |
728 | ++ip; | | 730 | ++ip; |
729 | } | | 731 | } |
730 | } | | 732 | } |
731 | /* Link remaining IFILE entries in free list */ | | 733 | /* Link remaining IFILE entries in free list */ |
732 | if (version == 1) { | | 734 | if (version == 1) { |
733 | for (; | | 735 | for (; |
734 | i < fs->lfs_ifpb; ++ip_v1) { | | 736 | i < fs->lfs_ifpb; ++ip_v1) { |
735 | ip_v1->if_version = 1; | | 737 | ip_v1->if_version = 1; |
736 | ip_v1->if_daddr = LFS_UNUSED_DADDR; | | 738 | ip_v1->if_daddr = LFS_UNUSED_DADDR; |
737 | ip_v1->if_nextfree = ++i; | | 739 | ip_v1->if_nextfree = ++i; |
738 | } | | 740 | } |
739 | --ip_v1; | | 741 | --ip_v1; |
740 | ip_v1->if_nextfree = LFS_UNUSED_INUM; | | 742 | ip_v1->if_nextfree = LFS_UNUSED_INUM; |
741 | } else { | | 743 | } else { |
742 | for (; | | 744 | for (; |
743 | i < fs->lfs_ifpb; ++ip) { | | 745 | i < fs->lfs_ifpb; ++ip) { |
744 | ip->if_version = 1; | | 746 | ip->if_version = 1; |
745 | ip->if_daddr = LFS_UNUSED_DADDR; | | 747 | ip->if_daddr = LFS_UNUSED_DADDR; |
746 | ip->if_nextfree = ++i; | | 748 | ip->if_nextfree = ++i; |
747 | } | | 749 | } |
748 | --ip; | | 750 | --ip; |
749 | ip->if_nextfree = LFS_UNUSED_INUM; | | 751 | ip->if_nextfree = LFS_UNUSED_INUM; |
750 | } | | 752 | } |
751 | VOP_BWRITE(bp); | | 753 | VOP_BWRITE(bp); |
752 | | | 754 | |
753 | /* Write it all to disk. */ | | 755 | /* Write it all to disk. */ |
754 | if (!Nflag) | | 756 | if (!Nflag) |
755 | lfs_segwrite(fs, SEGM_CKP); | | 757 | lfs_segwrite(fs, SEGM_CKP); |
756 | | | 758 | |
757 | /* | | 759 | /* |
758 | * Now that we've written everything, look to see what's available | | 760 | * Now that we've written everything, look to see what's available |
759 | * for writing. | | 761 | * for writing. |
760 | */ | | 762 | */ |
761 | fs->lfs_avail = 0; | | 763 | fs->lfs_avail = 0; |
762 | bb = ubb = dmeta = 0; | | 764 | bb = ubb = dmeta = 0; |
763 | for (i = 0; i < fs->lfs_nseg; i++) { | | 765 | for (i = 0; i < fs->lfs_nseg; i++) { |
764 | LFS_SEGENTRY(segp, fs, i, bp); | | 766 | LFS_SEGENTRY(segp, fs, i, bp); |
765 | if (segp->su_flags & SEGUSE_DIRTY) { | | 767 | if (segp->su_flags & SEGUSE_DIRTY) { |
766 | bb += btofsb(fs, segp->su_nbytes + | | 768 | bb += btofsb(fs, segp->su_nbytes + |
767 | segp->su_nsums * fs->lfs_sumsize); | | 769 | segp->su_nsums * fs->lfs_sumsize); |
768 | ubb += btofsb(fs, segp->su_nbytes + | | 770 | ubb += btofsb(fs, segp->su_nbytes + |
769 | segp->su_nsums * fs->lfs_sumsize + | | 771 | segp->su_nsums * fs->lfs_sumsize + |
770 | segp->su_ninos * fs->lfs_ibsize); | | 772 | segp->su_ninos * fs->lfs_ibsize); |
771 | dmeta += btofsb(fs, | | 773 | dmeta += btofsb(fs, |
772 | fs->lfs_sumsize * segp->su_nsums); | | 774 | fs->lfs_sumsize * segp->su_nsums); |
773 | dmeta += btofsb(fs, | | 775 | dmeta += btofsb(fs, |
774 | fs->lfs_ibsize * segp->su_ninos); | | 776 | fs->lfs_ibsize * segp->su_ninos); |
775 | } else { | | 777 | } else { |
776 | fs->lfs_avail += segtod(fs, 1); | | 778 | fs->lfs_avail += segtod(fs, 1); |
777 | if (segp->su_flags & SEGUSE_SUPERBLOCK) | | 779 | if (segp->su_flags & SEGUSE_SUPERBLOCK) |
778 | fs->lfs_avail -= btofsb(fs, LFS_SBPAD); | | 780 | fs->lfs_avail -= btofsb(fs, LFS_SBPAD); |
779 | if (i == 0 && fs->lfs_version > 1 && | | 781 | if (i == 0 && fs->lfs_version > 1 && |
780 | fs->lfs_start < btofsb(fs, LFS_LABELPAD)) | | 782 | fs->lfs_start < btofsb(fs, LFS_LABELPAD)) |
781 | fs->lfs_avail -= btofsb(fs, LFS_LABELPAD) - | | 783 | fs->lfs_avail -= btofsb(fs, LFS_LABELPAD) - |
782 | fs->lfs_start; | | 784 | fs->lfs_start; |
783 | } | | 785 | } |
784 | brelse(bp, 0); | | 786 | brelse(bp, 0); |
785 | } | | 787 | } |
786 | /* Also may be available bytes in current seg */ | | 788 | /* Also may be available bytes in current seg */ |
787 | i = dtosn(fs, fs->lfs_offset); | | 789 | i = dtosn(fs, fs->lfs_offset); |
788 | fs->lfs_avail += sntod(fs, i + 1) - fs->lfs_offset; | | 790 | fs->lfs_avail += sntod(fs, i + 1) - fs->lfs_offset; |
789 | /* But do not count minfreesegs */ | | 791 | /* But do not count minfreesegs */ |
790 | fs->lfs_avail -= segtod(fs, (fs->lfs_minfreeseg - (fs->lfs_minfreeseg / 2))); | | 792 | fs->lfs_avail -= segtod(fs, (fs->lfs_minfreeseg - (fs->lfs_minfreeseg / 2))); |
791 | | | 793 | |
792 | labelskew = 0; | | 794 | labelskew = 0; |
793 | if (fs->lfs_version > 1 && fs->lfs_start < btofsb(fs, LFS_LABELPAD)) | | 795 | if (fs->lfs_version > 1 && fs->lfs_start < btofsb(fs, LFS_LABELPAD)) |
794 | labelskew = btofsb(fs, LFS_LABELPAD); | | 796 | labelskew = btofsb(fs, LFS_LABELPAD); |
795 | fs->lfs_bfree = fs->lfs_dsize - labelskew - (ubb + bb) / 2; | | 797 | fs->lfs_bfree = fs->lfs_dsize - labelskew - (ubb + bb) / 2; |
796 | | | 798 | |
797 | /* Put that in the Ifile version too, and write it */ | | 799 | /* Put that in the Ifile version too, and write it */ |
798 | LFS_CLEANERINFO(cip, fs, bp); | | 800 | LFS_CLEANERINFO(cip, fs, bp); |
799 | cip->bfree = fs->lfs_bfree; | | 801 | cip->bfree = fs->lfs_bfree; |
800 | cip->avail = fs->lfs_avail; | | 802 | cip->avail = fs->lfs_avail; |
801 | LFS_SYNC_CLEANERINFO(cip, fs, bp, 1); | | 803 | LFS_SYNC_CLEANERINFO(cip, fs, bp, 1); |
802 | if (!Nflag) | | 804 | if (!Nflag) |
803 | lfs_segwrite(fs, SEGM_CKP); | | 805 | lfs_segwrite(fs, SEGM_CKP); |
804 | | | 806 | |
805 | /* | | 807 | /* |
806 | * Finally write out superblocks. | | 808 | * Finally write out superblocks. |
807 | */ | | 809 | */ |
808 | printf("super-block backups (for fsck -b #) at:\n"); | | 810 | printf("super-block backups (for fsck -b #) at:\n"); |
809 | curw = 0; | | 811 | curw = 0; |
810 | for (i = 0; i < LFS_MAXNUMSB; i++) { | | 812 | for (i = 0; i < LFS_MAXNUMSB; i++) { |
811 | seg_addr = fs->lfs_sboffs[i]; | | 813 | seg_addr = fs->lfs_sboffs[i]; |
812 | if (seg_addr == 0) | | 814 | if (seg_addr == 0) |
813 | break; | | 815 | break; |
814 | | | 816 | |
815 | if (i != 0) | | 817 | if (i != 0) |
816 | curw += printf(", "); | | 818 | curw += printf(", "); |
817 | ww = snprintf(tbuf, sizeof(tbuf), "%lld", | | 819 | ww = snprintf(tbuf, sizeof(tbuf), "%lld", |
818 | (long long)fsbtodb(fs, seg_addr)); | | 820 | (long long)fsbtodb(fs, seg_addr)); |
819 | curw += ww; | | 821 | curw += ww; |
820 | if (curw >= 78) { | | 822 | if (curw >= 78) { |
821 | printf("\n%s", tbuf); | | 823 | printf("\n%s", tbuf); |
822 | curw = ww; | | 824 | curw = ww; |
823 | } else | | 825 | } else |
824 | printf("%s", tbuf); | | 826 | printf("%s", tbuf); |
825 | fflush(stdout); | | 827 | fflush(stdout); |
826 | | | 828 | |
827 | /* Leave the time stamp on the alt sb, zero the rest */ | | 829 | /* Leave the time stamp on the alt sb, zero the rest */ |
828 | if (i == 2) { | | 830 | if (i == 2) { |
829 | fs->lfs_tstamp = 0; | | 831 | fs->lfs_tstamp = 0; |
830 | fs->lfs_cksum = lfs_sb_cksum(&(fs->lfs_dlfs)); | | 832 | fs->lfs_cksum = lfs_sb_cksum(&(fs->lfs_dlfs)); |
831 | } | | 833 | } |
832 | if (!Nflag) | | 834 | if (!Nflag) |
833 | lfs_writesuper(fs, seg_addr); | | 835 | lfs_writesuper(fs, seg_addr); |
834 | } | | 836 | } |
835 | printf(".\n"); | | 837 | printf(".\n"); |
836 | | | 838 | |
837 | return 0; | | 839 | return 0; |
838 | } | | 840 | } |
839 | | | 841 | |
840 | /* | | 842 | /* |
841 | * Compatibility with fsck_lfs, since the "generic" LFS userland code uses it. | | 843 | * Compatibility with fsck_lfs, since the "generic" LFS userland code uses it. |
842 | */ | | 844 | */ |
843 | void | | 845 | void |
844 | pwarn(const char *fmt, ...) | | 846 | pwarn(const char *fmt, ...) |
845 | { | | 847 | { |
846 | va_list ap; | | 848 | va_list ap; |
847 | | | 849 | |
848 | va_start(ap, fmt); | | 850 | va_start(ap, fmt); |
849 | vfprintf(stderr, fmt, ap); | | 851 | vfprintf(stderr, fmt, ap); |
850 | va_end(ap); | | 852 | va_end(ap); |
851 | } | | 853 | } |