Tue Mar 3 17:46:39 2015 UTC ()
ffs_reload(): the current implementation blindly guesses critical fields
of the superblock didn't change. Add checks to ensure they didn't change
for real. This prevents several memory corruptions.


(maxv)
diff -r1.319 -r1.320 src/sys/ufs/ffs/ffs_vfsops.c

cvs diff -r1.319 -r1.320 src/sys/ufs/ffs/ffs_vfsops.c (switch to unified diff)

--- src/sys/ufs/ffs/ffs_vfsops.c 2015/02/23 13:38:54 1.319
+++ src/sys/ufs/ffs/ffs_vfsops.c 2015/03/03 17:46:39 1.320
@@ -1,1752 +1,1760 @@ @@ -1,1752 +1,1760 @@
1/* $NetBSD: ffs_vfsops.c,v 1.319 2015/02/23 13:38:54 maxv Exp $ */ 1/* $NetBSD: ffs_vfsops.c,v 1.320 2015/03/03 17:46:39 maxv Exp $ */
2 2
3/*- 3/*-
4 * Copyright (c) 2008, 2009 The NetBSD Foundation, Inc. 4 * Copyright (c) 2008, 2009 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 Wasabi Systems, Inc, and by Andrew Doran. 8 * by Wasabi Systems, Inc, and by Andrew Doran.
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/* 32/*
33 * Copyright (c) 1989, 1991, 1993, 1994 33 * Copyright (c) 1989, 1991, 1993, 1994
34 * The Regents of the University of California. All rights reserved. 34 * The Regents of the University of California. All rights reserved.
35 * 35 *
36 * Redistribution and use in source and binary forms, with or without 36 * Redistribution and use in source and binary forms, with or without
37 * modification, are permitted provided that the following conditions 37 * modification, are permitted provided that the following conditions
38 * are met: 38 * are met:
39 * 1. Redistributions of source code must retain the above copyright 39 * 1. Redistributions of source code must retain the above copyright
40 * notice, this list of conditions and the following disclaimer. 40 * notice, this list of conditions and the following disclaimer.
41 * 2. Redistributions in binary form must reproduce the above copyright 41 * 2. Redistributions in binary form must reproduce the above copyright
42 * notice, this list of conditions and the following disclaimer in the 42 * notice, this list of conditions and the following disclaimer in the
43 * documentation and/or other materials provided with the distribution. 43 * documentation and/or other materials provided with the distribution.
44 * 3. Neither the name of the University nor the names of its contributors 44 * 3. Neither the name of the University nor the names of its contributors
45 * may be used to endorse or promote products derived from this software 45 * may be used to endorse or promote products derived from this software
46 * without specific prior written permission. 46 * without specific prior written permission.
47 * 47 *
48 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 48 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
49 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 49 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
50 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 50 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
51 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 51 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
52 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 52 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
53 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 53 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
54 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 54 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
55 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 55 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
56 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 56 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
57 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 57 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
58 * SUCH DAMAGE. 58 * SUCH DAMAGE.
59 * 59 *
60 * @(#)ffs_vfsops.c 8.31 (Berkeley) 5/20/95 60 * @(#)ffs_vfsops.c 8.31 (Berkeley) 5/20/95
61 */ 61 */
62 62
63#include <sys/cdefs.h> 63#include <sys/cdefs.h>
64__KERNEL_RCSID(0, "$NetBSD: ffs_vfsops.c,v 1.319 2015/02/23 13:38:54 maxv Exp $"); 64__KERNEL_RCSID(0, "$NetBSD: ffs_vfsops.c,v 1.320 2015/03/03 17:46:39 maxv Exp $");
65 65
66#if defined(_KERNEL_OPT) 66#if defined(_KERNEL_OPT)
67#include "opt_ffs.h" 67#include "opt_ffs.h"
68#include "opt_quota.h" 68#include "opt_quota.h"
69#include "opt_wapbl.h" 69#include "opt_wapbl.h"
70#endif 70#endif
71 71
72#include <sys/param.h> 72#include <sys/param.h>
73#include <sys/systm.h> 73#include <sys/systm.h>
74#include <sys/namei.h> 74#include <sys/namei.h>
75#include <sys/proc.h> 75#include <sys/proc.h>
76#include <sys/kernel.h> 76#include <sys/kernel.h>
77#include <sys/vnode.h> 77#include <sys/vnode.h>
78#include <sys/socket.h> 78#include <sys/socket.h>
79#include <sys/mount.h> 79#include <sys/mount.h>
80#include <sys/buf.h> 80#include <sys/buf.h>
81#include <sys/device.h> 81#include <sys/device.h>
82#include <sys/disk.h> 82#include <sys/disk.h>
83#include <sys/mbuf.h> 83#include <sys/mbuf.h>
84#include <sys/file.h> 84#include <sys/file.h>
85#include <sys/disklabel.h> 85#include <sys/disklabel.h>
86#include <sys/ioctl.h> 86#include <sys/ioctl.h>
87#include <sys/errno.h> 87#include <sys/errno.h>
88#include <sys/kmem.h> 88#include <sys/kmem.h>
89#include <sys/pool.h> 89#include <sys/pool.h>
90#include <sys/lock.h> 90#include <sys/lock.h>
91#include <sys/sysctl.h> 91#include <sys/sysctl.h>
92#include <sys/conf.h> 92#include <sys/conf.h>
93#include <sys/kauth.h> 93#include <sys/kauth.h>
94#include <sys/wapbl.h> 94#include <sys/wapbl.h>
95#include <sys/fstrans.h> 95#include <sys/fstrans.h>
96#include <sys/module.h> 96#include <sys/module.h>
97 97
98#include <miscfs/genfs/genfs.h> 98#include <miscfs/genfs/genfs.h>
99#include <miscfs/specfs/specdev.h> 99#include <miscfs/specfs/specdev.h>
100 100
101#include <ufs/ufs/quota.h> 101#include <ufs/ufs/quota.h>
102#include <ufs/ufs/ufsmount.h> 102#include <ufs/ufs/ufsmount.h>
103#include <ufs/ufs/inode.h> 103#include <ufs/ufs/inode.h>
104#include <ufs/ufs/dir.h> 104#include <ufs/ufs/dir.h>
105#include <ufs/ufs/ufs_extern.h> 105#include <ufs/ufs/ufs_extern.h>
106#include <ufs/ufs/ufs_bswap.h> 106#include <ufs/ufs/ufs_bswap.h>
107#include <ufs/ufs/ufs_wapbl.h> 107#include <ufs/ufs/ufs_wapbl.h>
108 108
109#include <ufs/ffs/fs.h> 109#include <ufs/ffs/fs.h>
110#include <ufs/ffs/ffs_extern.h> 110#include <ufs/ffs/ffs_extern.h>
111 111
112MODULE(MODULE_CLASS_VFS, ffs, NULL); 112MODULE(MODULE_CLASS_VFS, ffs, NULL);
113 113
114static int ffs_vfs_fsync(vnode_t *, int); 114static int ffs_vfs_fsync(vnode_t *, int);
115static int ffs_superblock_validate(struct fs *); 115static int ffs_superblock_validate(struct fs *);
116 116
117static struct sysctllog *ffs_sysctl_log; 117static struct sysctllog *ffs_sysctl_log;
118 118
119static kauth_listener_t ffs_snapshot_listener; 119static kauth_listener_t ffs_snapshot_listener;
120 120
121/* how many times ffs_init() was called */ 121/* how many times ffs_init() was called */
122int ffs_initcount = 0; 122int ffs_initcount = 0;
123 123
124#ifdef DEBUG_FFS_MOUNT 124#ifdef DEBUG_FFS_MOUNT
125#define DPRINTF(_fmt, args...) printf("%s: " _fmt "\n", __func__, ##args) 125#define DPRINTF(_fmt, args...) printf("%s: " _fmt "\n", __func__, ##args)
126#else 126#else
127#define DPRINTF(_fmt, args...) do {} while (/*CONSTCOND*/0) 127#define DPRINTF(_fmt, args...) do {} while (/*CONSTCOND*/0)
128#endif 128#endif
129 129
130extern const struct vnodeopv_desc ffs_vnodeop_opv_desc; 130extern const struct vnodeopv_desc ffs_vnodeop_opv_desc;
131extern const struct vnodeopv_desc ffs_specop_opv_desc; 131extern const struct vnodeopv_desc ffs_specop_opv_desc;
132extern const struct vnodeopv_desc ffs_fifoop_opv_desc; 132extern const struct vnodeopv_desc ffs_fifoop_opv_desc;
133 133
134const struct vnodeopv_desc * const ffs_vnodeopv_descs[] = { 134const struct vnodeopv_desc * const ffs_vnodeopv_descs[] = {
135 &ffs_vnodeop_opv_desc, 135 &ffs_vnodeop_opv_desc,
136 &ffs_specop_opv_desc, 136 &ffs_specop_opv_desc,
137 &ffs_fifoop_opv_desc, 137 &ffs_fifoop_opv_desc,
138 NULL, 138 NULL,
139}; 139};
140 140
141struct vfsops ffs_vfsops = { 141struct vfsops ffs_vfsops = {
142 .vfs_name = MOUNT_FFS, 142 .vfs_name = MOUNT_FFS,
143 .vfs_min_mount_data = sizeof (struct ufs_args), 143 .vfs_min_mount_data = sizeof (struct ufs_args),
144 .vfs_mount = ffs_mount, 144 .vfs_mount = ffs_mount,
145 .vfs_start = ufs_start, 145 .vfs_start = ufs_start,
146 .vfs_unmount = ffs_unmount, 146 .vfs_unmount = ffs_unmount,
147 .vfs_root = ufs_root, 147 .vfs_root = ufs_root,
148 .vfs_quotactl = ufs_quotactl, 148 .vfs_quotactl = ufs_quotactl,
149 .vfs_statvfs = ffs_statvfs, 149 .vfs_statvfs = ffs_statvfs,
150 .vfs_sync = ffs_sync, 150 .vfs_sync = ffs_sync,
151 .vfs_vget = ufs_vget, 151 .vfs_vget = ufs_vget,
152 .vfs_loadvnode = ffs_loadvnode, 152 .vfs_loadvnode = ffs_loadvnode,
153 .vfs_fhtovp = ffs_fhtovp, 153 .vfs_fhtovp = ffs_fhtovp,
154 .vfs_vptofh = ffs_vptofh, 154 .vfs_vptofh = ffs_vptofh,
155 .vfs_init = ffs_init, 155 .vfs_init = ffs_init,
156 .vfs_reinit = ffs_reinit, 156 .vfs_reinit = ffs_reinit,
157 .vfs_done = ffs_done, 157 .vfs_done = ffs_done,
158 .vfs_mountroot = ffs_mountroot, 158 .vfs_mountroot = ffs_mountroot,
159 .vfs_snapshot = ffs_snapshot, 159 .vfs_snapshot = ffs_snapshot,
160 .vfs_extattrctl = ffs_extattrctl, 160 .vfs_extattrctl = ffs_extattrctl,
161 .vfs_suspendctl = ffs_suspendctl, 161 .vfs_suspendctl = ffs_suspendctl,
162 .vfs_renamelock_enter = genfs_renamelock_enter, 162 .vfs_renamelock_enter = genfs_renamelock_enter,
163 .vfs_renamelock_exit = genfs_renamelock_exit, 163 .vfs_renamelock_exit = genfs_renamelock_exit,
164 .vfs_fsync = ffs_vfs_fsync, 164 .vfs_fsync = ffs_vfs_fsync,
165 .vfs_opv_descs = ffs_vnodeopv_descs 165 .vfs_opv_descs = ffs_vnodeopv_descs
166}; 166};
167 167
168static const struct genfs_ops ffs_genfsops = { 168static const struct genfs_ops ffs_genfsops = {
169 .gop_size = ffs_gop_size, 169 .gop_size = ffs_gop_size,
170 .gop_alloc = ufs_gop_alloc, 170 .gop_alloc = ufs_gop_alloc,
171 .gop_write = genfs_gop_write, 171 .gop_write = genfs_gop_write,
172 .gop_markupdate = ufs_gop_markupdate, 172 .gop_markupdate = ufs_gop_markupdate,
173}; 173};
174 174
175static const struct ufs_ops ffs_ufsops = { 175static const struct ufs_ops ffs_ufsops = {
176 .uo_itimes = ffs_itimes, 176 .uo_itimes = ffs_itimes,
177 .uo_update = ffs_update, 177 .uo_update = ffs_update,
178 .uo_truncate = ffs_truncate, 178 .uo_truncate = ffs_truncate,
179 .uo_valloc = ffs_valloc, 179 .uo_valloc = ffs_valloc,
180 .uo_vfree = ffs_vfree, 180 .uo_vfree = ffs_vfree,
181 .uo_balloc = ffs_balloc, 181 .uo_balloc = ffs_balloc,
182 .uo_snapgone = ffs_snapgone, 182 .uo_snapgone = ffs_snapgone,
183}; 183};
184 184
185static int 185static int
186ffs_snapshot_cb(kauth_cred_t cred, kauth_action_t action, void *cookie, 186ffs_snapshot_cb(kauth_cred_t cred, kauth_action_t action, void *cookie,
187 void *arg0, void *arg1, void *arg2, void *arg3) 187 void *arg0, void *arg1, void *arg2, void *arg3)
188{ 188{
189 vnode_t *vp = arg2; 189 vnode_t *vp = arg2;
190 int result = KAUTH_RESULT_DEFER; 190 int result = KAUTH_RESULT_DEFER;
191 191
192 if (action != KAUTH_SYSTEM_FS_SNAPSHOT) 192 if (action != KAUTH_SYSTEM_FS_SNAPSHOT)
193 return result; 193 return result;
194 194
195 if (VTOI(vp)->i_uid == kauth_cred_geteuid(cred)) 195 if (VTOI(vp)->i_uid == kauth_cred_geteuid(cred))
196 result = KAUTH_RESULT_ALLOW; 196 result = KAUTH_RESULT_ALLOW;
197 197
198 return result; 198 return result;
199} 199}
200 200
201static int 201static int
202ffs_modcmd(modcmd_t cmd, void *arg) 202ffs_modcmd(modcmd_t cmd, void *arg)
203{ 203{
204 int error; 204 int error;
205 205
206#if 0 206#if 0
207 extern int doasyncfree; 207 extern int doasyncfree;
208#endif 208#endif
209#ifdef UFS_EXTATTR 209#ifdef UFS_EXTATTR
210 extern int ufs_extattr_autocreate; 210 extern int ufs_extattr_autocreate;
211#endif 211#endif
212 extern int ffs_log_changeopt; 212 extern int ffs_log_changeopt;
213 213
214 switch (cmd) { 214 switch (cmd) {
215 case MODULE_CMD_INIT: 215 case MODULE_CMD_INIT:
216 error = vfs_attach(&ffs_vfsops); 216 error = vfs_attach(&ffs_vfsops);
217 if (error != 0) 217 if (error != 0)
218 break; 218 break;
219 219
220 sysctl_createv(&ffs_sysctl_log, 0, NULL, NULL, 220 sysctl_createv(&ffs_sysctl_log, 0, NULL, NULL,
221 CTLFLAG_PERMANENT, 221 CTLFLAG_PERMANENT,
222 CTLTYPE_NODE, "ffs", 222 CTLTYPE_NODE, "ffs",
223 SYSCTL_DESCR("Berkeley Fast File System"), 223 SYSCTL_DESCR("Berkeley Fast File System"),
224 NULL, 0, NULL, 0, 224 NULL, 0, NULL, 0,
225 CTL_VFS, 1, CTL_EOL); 225 CTL_VFS, 1, CTL_EOL);
226 /* 226 /*
227 * @@@ should we even bother with these first three? 227 * @@@ should we even bother with these first three?
228 */ 228 */
229 sysctl_createv(&ffs_sysctl_log, 0, NULL, NULL, 229 sysctl_createv(&ffs_sysctl_log, 0, NULL, NULL,
230 CTLFLAG_PERMANENT|CTLFLAG_READWRITE, 230 CTLFLAG_PERMANENT|CTLFLAG_READWRITE,
231 CTLTYPE_INT, "doclusterread", NULL, 231 CTLTYPE_INT, "doclusterread", NULL,
232 sysctl_notavail, 0, NULL, 0, 232 sysctl_notavail, 0, NULL, 0,
233 CTL_VFS, 1, FFS_CLUSTERREAD, CTL_EOL); 233 CTL_VFS, 1, FFS_CLUSTERREAD, CTL_EOL);
234 sysctl_createv(&ffs_sysctl_log, 0, NULL, NULL, 234 sysctl_createv(&ffs_sysctl_log, 0, NULL, NULL,
235 CTLFLAG_PERMANENT|CTLFLAG_READWRITE, 235 CTLFLAG_PERMANENT|CTLFLAG_READWRITE,
236 CTLTYPE_INT, "doclusterwrite", NULL, 236 CTLTYPE_INT, "doclusterwrite", NULL,
237 sysctl_notavail, 0, NULL, 0, 237 sysctl_notavail, 0, NULL, 0,
238 CTL_VFS, 1, FFS_CLUSTERWRITE, CTL_EOL); 238 CTL_VFS, 1, FFS_CLUSTERWRITE, CTL_EOL);
239 sysctl_createv(&ffs_sysctl_log, 0, NULL, NULL, 239 sysctl_createv(&ffs_sysctl_log, 0, NULL, NULL,
240 CTLFLAG_PERMANENT|CTLFLAG_READWRITE, 240 CTLFLAG_PERMANENT|CTLFLAG_READWRITE,
241 CTLTYPE_INT, "doreallocblks", NULL, 241 CTLTYPE_INT, "doreallocblks", NULL,
242 sysctl_notavail, 0, NULL, 0, 242 sysctl_notavail, 0, NULL, 0,
243 CTL_VFS, 1, FFS_REALLOCBLKS, CTL_EOL); 243 CTL_VFS, 1, FFS_REALLOCBLKS, CTL_EOL);
244#if 0 244#if 0
245 sysctl_createv(&ffs_sysctl_log, 0, NULL, NULL, 245 sysctl_createv(&ffs_sysctl_log, 0, NULL, NULL,
246 CTLFLAG_PERMANENT|CTLFLAG_READWRITE, 246 CTLFLAG_PERMANENT|CTLFLAG_READWRITE,
247 CTLTYPE_INT, "doasyncfree", 247 CTLTYPE_INT, "doasyncfree",
248 SYSCTL_DESCR("Release dirty blocks asynchronously"), 248 SYSCTL_DESCR("Release dirty blocks asynchronously"),
249 NULL, 0, &doasyncfree, 0, 249 NULL, 0, &doasyncfree, 0,
250 CTL_VFS, 1, FFS_ASYNCFREE, CTL_EOL); 250 CTL_VFS, 1, FFS_ASYNCFREE, CTL_EOL);
251#endif 251#endif
252 sysctl_createv(&ffs_sysctl_log, 0, NULL, NULL, 252 sysctl_createv(&ffs_sysctl_log, 0, NULL, NULL,
253 CTLFLAG_PERMANENT|CTLFLAG_READWRITE, 253 CTLFLAG_PERMANENT|CTLFLAG_READWRITE,
254 CTLTYPE_INT, "log_changeopt", 254 CTLTYPE_INT, "log_changeopt",
255 SYSCTL_DESCR("Log changes in optimization strategy"), 255 SYSCTL_DESCR("Log changes in optimization strategy"),
256 NULL, 0, &ffs_log_changeopt, 0, 256 NULL, 0, &ffs_log_changeopt, 0,
257 CTL_VFS, 1, FFS_LOG_CHANGEOPT, CTL_EOL); 257 CTL_VFS, 1, FFS_LOG_CHANGEOPT, CTL_EOL);
258#ifdef UFS_EXTATTR 258#ifdef UFS_EXTATTR
259 sysctl_createv(&ffs_sysctl_log, 0, NULL, NULL, 259 sysctl_createv(&ffs_sysctl_log, 0, NULL, NULL,
260 CTLFLAG_PERMANENT|CTLFLAG_READWRITE, 260 CTLFLAG_PERMANENT|CTLFLAG_READWRITE,
261 CTLTYPE_INT, "extattr_autocreate", 261 CTLTYPE_INT, "extattr_autocreate",
262 SYSCTL_DESCR("Size of attribute for " 262 SYSCTL_DESCR("Size of attribute for "
263 "backing file autocreation"), 263 "backing file autocreation"),
264 NULL, 0, &ufs_extattr_autocreate, 0, 264 NULL, 0, &ufs_extattr_autocreate, 0,
265 CTL_VFS, 1, FFS_EXTATTR_AUTOCREATE, CTL_EOL); 265 CTL_VFS, 1, FFS_EXTATTR_AUTOCREATE, CTL_EOL);
266  266
267#endif /* UFS_EXTATTR */ 267#endif /* UFS_EXTATTR */
268 268
269 ffs_snapshot_listener = kauth_listen_scope(KAUTH_SCOPE_SYSTEM, 269 ffs_snapshot_listener = kauth_listen_scope(KAUTH_SCOPE_SYSTEM,
270 ffs_snapshot_cb, NULL); 270 ffs_snapshot_cb, NULL);
271 if (ffs_snapshot_listener == NULL) 271 if (ffs_snapshot_listener == NULL)
272 printf("ffs_modcmd: can't listen on system scope.\n"); 272 printf("ffs_modcmd: can't listen on system scope.\n");
273 273
274 break; 274 break;
275 case MODULE_CMD_FINI: 275 case MODULE_CMD_FINI:
276 error = vfs_detach(&ffs_vfsops); 276 error = vfs_detach(&ffs_vfsops);
277 if (error != 0) 277 if (error != 0)
278 break; 278 break;
279 sysctl_teardown(&ffs_sysctl_log); 279 sysctl_teardown(&ffs_sysctl_log);
280 if (ffs_snapshot_listener != NULL) 280 if (ffs_snapshot_listener != NULL)
281 kauth_unlisten_scope(ffs_snapshot_listener); 281 kauth_unlisten_scope(ffs_snapshot_listener);
282 break; 282 break;
283 default: 283 default:
284 error = ENOTTY; 284 error = ENOTTY;
285 break; 285 break;
286 } 286 }
287 287
288 return (error); 288 return (error);
289} 289}
290 290
291pool_cache_t ffs_inode_cache; 291pool_cache_t ffs_inode_cache;
292pool_cache_t ffs_dinode1_cache; 292pool_cache_t ffs_dinode1_cache;
293pool_cache_t ffs_dinode2_cache; 293pool_cache_t ffs_dinode2_cache;
294 294
295static void ffs_oldfscompat_read(struct fs *, struct ufsmount *, daddr_t); 295static void ffs_oldfscompat_read(struct fs *, struct ufsmount *, daddr_t);
296static void ffs_oldfscompat_write(struct fs *, struct ufsmount *); 296static void ffs_oldfscompat_write(struct fs *, struct ufsmount *);
297 297
298/* 298/*
299 * Called by main() when ffs is going to be mounted as root. 299 * Called by main() when ffs is going to be mounted as root.
300 */ 300 */
301 301
302int 302int
303ffs_mountroot(void) 303ffs_mountroot(void)
304{ 304{
305 struct fs *fs; 305 struct fs *fs;
306 struct mount *mp; 306 struct mount *mp;
307 struct lwp *l = curlwp; /* XXX */ 307 struct lwp *l = curlwp; /* XXX */
308 struct ufsmount *ump; 308 struct ufsmount *ump;
309 int error; 309 int error;
310 310
311 if (device_class(root_device) != DV_DISK) 311 if (device_class(root_device) != DV_DISK)
312 return (ENODEV); 312 return (ENODEV);
313 313
314 if ((error = vfs_rootmountalloc(MOUNT_FFS, "root_device", &mp))) { 314 if ((error = vfs_rootmountalloc(MOUNT_FFS, "root_device", &mp))) {
315 vrele(rootvp); 315 vrele(rootvp);
316 return (error); 316 return (error);
317 } 317 }
318 318
319 /* 319 /*
320 * We always need to be able to mount the root file system. 320 * We always need to be able to mount the root file system.
321 */ 321 */
322 mp->mnt_flag |= MNT_FORCE; 322 mp->mnt_flag |= MNT_FORCE;
323 if ((error = ffs_mountfs(rootvp, mp, l)) != 0) { 323 if ((error = ffs_mountfs(rootvp, mp, l)) != 0) {
324 vfs_unbusy(mp, false, NULL); 324 vfs_unbusy(mp, false, NULL);
325 vfs_destroy(mp); 325 vfs_destroy(mp);
326 return (error); 326 return (error);
327 } 327 }
328 mp->mnt_flag &= ~MNT_FORCE; 328 mp->mnt_flag &= ~MNT_FORCE;
329 mountlist_append(mp); 329 mountlist_append(mp);
330 ump = VFSTOUFS(mp); 330 ump = VFSTOUFS(mp);
331 fs = ump->um_fs; 331 fs = ump->um_fs;
332 memset(fs->fs_fsmnt, 0, sizeof(fs->fs_fsmnt)); 332 memset(fs->fs_fsmnt, 0, sizeof(fs->fs_fsmnt));
333 (void)copystr(mp->mnt_stat.f_mntonname, fs->fs_fsmnt, MNAMELEN - 1, 0); 333 (void)copystr(mp->mnt_stat.f_mntonname, fs->fs_fsmnt, MNAMELEN - 1, 0);
334 (void)ffs_statvfs(mp, &mp->mnt_stat); 334 (void)ffs_statvfs(mp, &mp->mnt_stat);
335 vfs_unbusy(mp, false, NULL); 335 vfs_unbusy(mp, false, NULL);
336 setrootfstime((time_t)fs->fs_time); 336 setrootfstime((time_t)fs->fs_time);
337 return (0); 337 return (0);
338} 338}
339 339
340/* 340/*
341 * VFS Operations. 341 * VFS Operations.
342 * 342 *
343 * mount system call 343 * mount system call
344 */ 344 */
345int 345int
346ffs_mount(struct mount *mp, const char *path, void *data, size_t *data_len) 346ffs_mount(struct mount *mp, const char *path, void *data, size_t *data_len)
347{ 347{
348 struct lwp *l = curlwp; 348 struct lwp *l = curlwp;
349 struct vnode *devvp = NULL; 349 struct vnode *devvp = NULL;
350 struct ufs_args *args = data; 350 struct ufs_args *args = data;
351 struct ufsmount *ump = NULL; 351 struct ufsmount *ump = NULL;
352 struct fs *fs; 352 struct fs *fs;
353 int error = 0, flags, update; 353 int error = 0, flags, update;
354 mode_t accessmode; 354 mode_t accessmode;
355 355
356 if (args == NULL) { 356 if (args == NULL) {
357 DPRINTF("NULL args"); 357 DPRINTF("NULL args");
358 return EINVAL; 358 return EINVAL;
359 } 359 }
360 if (*data_len < sizeof(*args)) { 360 if (*data_len < sizeof(*args)) {
361 DPRINTF("bad size args %zu != %zu", *data_len, sizeof(*args)); 361 DPRINTF("bad size args %zu != %zu", *data_len, sizeof(*args));
362 return EINVAL; 362 return EINVAL;
363 } 363 }
364 364
365 if (mp->mnt_flag & MNT_GETARGS) { 365 if (mp->mnt_flag & MNT_GETARGS) {
366 ump = VFSTOUFS(mp); 366 ump = VFSTOUFS(mp);
367 if (ump == NULL) { 367 if (ump == NULL) {
368 DPRINTF("no ump"); 368 DPRINTF("no ump");
369 return EIO; 369 return EIO;
370 } 370 }
371 args->fspec = NULL; 371 args->fspec = NULL;
372 *data_len = sizeof *args; 372 *data_len = sizeof *args;
373 return 0; 373 return 0;
374 } 374 }
375 375
376 update = mp->mnt_flag & MNT_UPDATE; 376 update = mp->mnt_flag & MNT_UPDATE;
377 377
378 /* Check arguments */ 378 /* Check arguments */
379 if (args->fspec != NULL) { 379 if (args->fspec != NULL) {
380 /* 380 /*
381 * Look up the name and verify that it's sane. 381 * Look up the name and verify that it's sane.
382 */ 382 */
383 error = namei_simple_user(args->fspec, 383 error = namei_simple_user(args->fspec,
384 NSM_FOLLOW_NOEMULROOT, &devvp); 384 NSM_FOLLOW_NOEMULROOT, &devvp);
385 if (error != 0) { 385 if (error != 0) {
386 DPRINTF("namei_simple_user returned %d", error); 386 DPRINTF("namei_simple_user returned %d", error);
387 return error; 387 return error;
388 } 388 }
389 389
390 if (!update) { 390 if (!update) {
391 /* 391 /*
392 * Be sure this is a valid block device 392 * Be sure this is a valid block device
393 */ 393 */
394 if (devvp->v_type != VBLK) { 394 if (devvp->v_type != VBLK) {
395 DPRINTF("non block device %d", devvp->v_type); 395 DPRINTF("non block device %d", devvp->v_type);
396 error = ENOTBLK; 396 error = ENOTBLK;
397 } else if (bdevsw_lookup(devvp->v_rdev) == NULL) { 397 } else if (bdevsw_lookup(devvp->v_rdev) == NULL) {
398 DPRINTF("can't find block device 0x%jx", 398 DPRINTF("can't find block device 0x%jx",
399 devvp->v_rdev); 399 devvp->v_rdev);
400 error = ENXIO; 400 error = ENXIO;
401 } 401 }
402 } else { 402 } else {
403 /* 403 /*
404 * Be sure we're still naming the same device 404 * Be sure we're still naming the same device
405 * used for our initial mount 405 * used for our initial mount
406 */ 406 */
407 ump = VFSTOUFS(mp); 407 ump = VFSTOUFS(mp);
408 if (devvp != ump->um_devvp) { 408 if (devvp != ump->um_devvp) {
409 if (devvp->v_rdev != ump->um_devvp->v_rdev) { 409 if (devvp->v_rdev != ump->um_devvp->v_rdev) {
410 DPRINTF("wrong device 0x%jx != 0x%jx", 410 DPRINTF("wrong device 0x%jx != 0x%jx",
411 (uintmax_t)devvp->v_rdev, 411 (uintmax_t)devvp->v_rdev,
412 (uintmax_t)ump->um_devvp->v_rdev); 412 (uintmax_t)ump->um_devvp->v_rdev);
413 error = EINVAL; 413 error = EINVAL;
414 } else { 414 } else {
415 vrele(devvp); 415 vrele(devvp);
416 devvp = ump->um_devvp; 416 devvp = ump->um_devvp;
417 vref(devvp); 417 vref(devvp);
418 } 418 }
419 } 419 }
420 } 420 }
421 } else { 421 } else {
422 if (!update) { 422 if (!update) {
423 /* New mounts must have a filename for the device */ 423 /* New mounts must have a filename for the device */
424 DPRINTF("no filename for mount"); 424 DPRINTF("no filename for mount");
425 return EINVAL; 425 return EINVAL;
426 } else { 426 } else {
427 /* Use the extant mount */ 427 /* Use the extant mount */
428 ump = VFSTOUFS(mp); 428 ump = VFSTOUFS(mp);
429 devvp = ump->um_devvp; 429 devvp = ump->um_devvp;
430 vref(devvp); 430 vref(devvp);
431 } 431 }
432 } 432 }
433 433
434 /* 434 /*
435 * If mount by non-root, then verify that user has necessary 435 * If mount by non-root, then verify that user has necessary
436 * permissions on the device. 436 * permissions on the device.
437 * 437 *
438 * Permission to update a mount is checked higher, so here we presume 438 * Permission to update a mount is checked higher, so here we presume
439 * updating the mount is okay (for example, as far as securelevel goes) 439 * updating the mount is okay (for example, as far as securelevel goes)
440 * which leaves us with the normal check. 440 * which leaves us with the normal check.
441 */ 441 */
442 if (error == 0) { 442 if (error == 0) {
443 accessmode = VREAD; 443 accessmode = VREAD;
444 if (update ? 444 if (update ?
445 (mp->mnt_iflag & IMNT_WANTRDWR) != 0 : 445 (mp->mnt_iflag & IMNT_WANTRDWR) != 0 :
446 (mp->mnt_flag & MNT_RDONLY) == 0) 446 (mp->mnt_flag & MNT_RDONLY) == 0)
447 accessmode |= VWRITE; 447 accessmode |= VWRITE;
448 vn_lock(devvp, LK_EXCLUSIVE | LK_RETRY); 448 vn_lock(devvp, LK_EXCLUSIVE | LK_RETRY);
449 error = kauth_authorize_system(l->l_cred, KAUTH_SYSTEM_MOUNT, 449 error = kauth_authorize_system(l->l_cred, KAUTH_SYSTEM_MOUNT,
450 KAUTH_REQ_SYSTEM_MOUNT_DEVICE, mp, devvp, 450 KAUTH_REQ_SYSTEM_MOUNT_DEVICE, mp, devvp,
451 KAUTH_ARG(accessmode)); 451 KAUTH_ARG(accessmode));
452 if (error) { 452 if (error) {
453 DPRINTF("kauth returned %d", error); 453 DPRINTF("kauth returned %d", error);
454 } 454 }
455 VOP_UNLOCK(devvp); 455 VOP_UNLOCK(devvp);
456 } 456 }
457 457
458 if (error) { 458 if (error) {
459 vrele(devvp); 459 vrele(devvp);
460 return (error); 460 return (error);
461 } 461 }
462 462
463#ifdef WAPBL 463#ifdef WAPBL
464 /* WAPBL can only be enabled on a r/w mount. */ 464 /* WAPBL can only be enabled on a r/w mount. */
465 if ((mp->mnt_flag & MNT_RDONLY) && !(mp->mnt_iflag & IMNT_WANTRDWR)) { 465 if ((mp->mnt_flag & MNT_RDONLY) && !(mp->mnt_iflag & IMNT_WANTRDWR)) {
466 mp->mnt_flag &= ~MNT_LOG; 466 mp->mnt_flag &= ~MNT_LOG;
467 } 467 }
468#else /* !WAPBL */ 468#else /* !WAPBL */
469 mp->mnt_flag &= ~MNT_LOG; 469 mp->mnt_flag &= ~MNT_LOG;
470#endif /* !WAPBL */ 470#endif /* !WAPBL */
471 471
472 if (!update) { 472 if (!update) {
473 int xflags; 473 int xflags;
474 474
475 if (mp->mnt_flag & MNT_RDONLY) 475 if (mp->mnt_flag & MNT_RDONLY)
476 xflags = FREAD; 476 xflags = FREAD;
477 else 477 else
478 xflags = FREAD | FWRITE; 478 xflags = FREAD | FWRITE;
479 vn_lock(devvp, LK_EXCLUSIVE | LK_RETRY); 479 vn_lock(devvp, LK_EXCLUSIVE | LK_RETRY);
480 error = VOP_OPEN(devvp, xflags, FSCRED); 480 error = VOP_OPEN(devvp, xflags, FSCRED);
481 VOP_UNLOCK(devvp); 481 VOP_UNLOCK(devvp);
482 if (error) {  482 if (error) {
483 DPRINTF("VOP_OPEN returned %d", error); 483 DPRINTF("VOP_OPEN returned %d", error);
484 goto fail; 484 goto fail;
485 } 485 }
486 error = ffs_mountfs(devvp, mp, l); 486 error = ffs_mountfs(devvp, mp, l);
487 if (error) { 487 if (error) {
488 DPRINTF("ffs_mountfs returned %d", error); 488 DPRINTF("ffs_mountfs returned %d", error);
489 vn_lock(devvp, LK_EXCLUSIVE | LK_RETRY); 489 vn_lock(devvp, LK_EXCLUSIVE | LK_RETRY);
490 (void)VOP_CLOSE(devvp, xflags, NOCRED); 490 (void)VOP_CLOSE(devvp, xflags, NOCRED);
491 VOP_UNLOCK(devvp); 491 VOP_UNLOCK(devvp);
492 goto fail; 492 goto fail;
493 } 493 }
494 494
495 ump = VFSTOUFS(mp); 495 ump = VFSTOUFS(mp);
496 fs = ump->um_fs; 496 fs = ump->um_fs;
497 } else { 497 } else {
498 /* 498 /*
499 * Update the mount. 499 * Update the mount.
500 */ 500 */
501 501
502 /* 502 /*
503 * The initial mount got a reference on this 503 * The initial mount got a reference on this
504 * device, so drop the one obtained via 504 * device, so drop the one obtained via
505 * namei(), above. 505 * namei(), above.
506 */ 506 */
507 vrele(devvp); 507 vrele(devvp);
508 508
509 ump = VFSTOUFS(mp); 509 ump = VFSTOUFS(mp);
510 fs = ump->um_fs; 510 fs = ump->um_fs;
511 if (fs->fs_ronly == 0 && (mp->mnt_flag & MNT_RDONLY)) { 511 if (fs->fs_ronly == 0 && (mp->mnt_flag & MNT_RDONLY)) {
512 /* 512 /*
513 * Changing from r/w to r/o 513 * Changing from r/w to r/o
514 */ 514 */
515 flags = WRITECLOSE; 515 flags = WRITECLOSE;
516 if (mp->mnt_flag & MNT_FORCE) 516 if (mp->mnt_flag & MNT_FORCE)
517 flags |= FORCECLOSE; 517 flags |= FORCECLOSE;
518 error = ffs_flushfiles(mp, flags, l); 518 error = ffs_flushfiles(mp, flags, l);
519 if (error == 0) 519 if (error == 0)
520 error = UFS_WAPBL_BEGIN(mp); 520 error = UFS_WAPBL_BEGIN(mp);
521 if (error == 0 && 521 if (error == 0 &&
522 ffs_cgupdate(ump, MNT_WAIT) == 0 && 522 ffs_cgupdate(ump, MNT_WAIT) == 0 &&
523 fs->fs_clean & FS_WASCLEAN) { 523 fs->fs_clean & FS_WASCLEAN) {
524 if (mp->mnt_flag & MNT_SOFTDEP) 524 if (mp->mnt_flag & MNT_SOFTDEP)
525 fs->fs_flags &= ~FS_DOSOFTDEP; 525 fs->fs_flags &= ~FS_DOSOFTDEP;
526 fs->fs_clean = FS_ISCLEAN; 526 fs->fs_clean = FS_ISCLEAN;
527 (void) ffs_sbupdate(ump, MNT_WAIT); 527 (void) ffs_sbupdate(ump, MNT_WAIT);
528 } 528 }
529 if (error) { 529 if (error) {
530 DPRINTF("wapbl %d", error); 530 DPRINTF("wapbl %d", error);
531 return error; 531 return error;
532 } 532 }
533 UFS_WAPBL_END(mp); 533 UFS_WAPBL_END(mp);
534 } 534 }
535 535
536#ifdef WAPBL 536#ifdef WAPBL
537 if ((mp->mnt_flag & MNT_LOG) == 0) { 537 if ((mp->mnt_flag & MNT_LOG) == 0) {
538 error = ffs_wapbl_stop(mp, mp->mnt_flag & MNT_FORCE); 538 error = ffs_wapbl_stop(mp, mp->mnt_flag & MNT_FORCE);
539 if (error) { 539 if (error) {
540 DPRINTF("ffs_wapbl_stop returned %d", error); 540 DPRINTF("ffs_wapbl_stop returned %d", error);
541 return error; 541 return error;
542 } 542 }
543 } 543 }
544#endif /* WAPBL */ 544#endif /* WAPBL */
545 545
546 if (fs->fs_ronly == 0 && (mp->mnt_flag & MNT_RDONLY)) { 546 if (fs->fs_ronly == 0 && (mp->mnt_flag & MNT_RDONLY)) {
547 /* 547 /*
548 * Finish change from r/w to r/o 548 * Finish change from r/w to r/o
549 */ 549 */
550 fs->fs_ronly = 1; 550 fs->fs_ronly = 1;
551 fs->fs_fmod = 0; 551 fs->fs_fmod = 0;
552 } 552 }
553 553
554 if (mp->mnt_flag & MNT_RELOAD) { 554 if (mp->mnt_flag & MNT_RELOAD) {
555 error = ffs_reload(mp, l->l_cred, l); 555 error = ffs_reload(mp, l->l_cred, l);
556 if (error) { 556 if (error) {
557 DPRINTF("ffs_reload returned %d", error); 557 DPRINTF("ffs_reload returned %d", error);
558 return error; 558 return error;
559 } 559 }
560 } 560 }
561 561
562 if (fs->fs_ronly && (mp->mnt_iflag & IMNT_WANTRDWR)) { 562 if (fs->fs_ronly && (mp->mnt_iflag & IMNT_WANTRDWR)) {
563 /* 563 /*
564 * Changing from read-only to read/write 564 * Changing from read-only to read/write
565 */ 565 */
566#ifndef QUOTA2 566#ifndef QUOTA2
567 if (fs->fs_flags & FS_DOQUOTA2) { 567 if (fs->fs_flags & FS_DOQUOTA2) {
568 ump->um_flags |= UFS_QUOTA2; 568 ump->um_flags |= UFS_QUOTA2;
569 uprintf("%s: options QUOTA2 not enabled%s\n", 569 uprintf("%s: options QUOTA2 not enabled%s\n",
570 mp->mnt_stat.f_mntonname, 570 mp->mnt_stat.f_mntonname,
571 (mp->mnt_flag & MNT_FORCE) ? "" : 571 (mp->mnt_flag & MNT_FORCE) ? "" :
572 ", not mounting"); 572 ", not mounting");
573 DPRINTF("ffs_quota2 %d", EINVAL); 573 DPRINTF("ffs_quota2 %d", EINVAL);
574 return EINVAL; 574 return EINVAL;
575 } 575 }
576#endif 576#endif
577 fs->fs_ronly = 0; 577 fs->fs_ronly = 0;
578 fs->fs_clean <<= 1; 578 fs->fs_clean <<= 1;
579 fs->fs_fmod = 1; 579 fs->fs_fmod = 1;
580#ifdef WAPBL 580#ifdef WAPBL
581 if (fs->fs_flags & FS_DOWAPBL) { 581 if (fs->fs_flags & FS_DOWAPBL) {
582 const char *nm = mp->mnt_stat.f_mntonname; 582 const char *nm = mp->mnt_stat.f_mntonname;
583 if (!mp->mnt_wapbl_replay) { 583 if (!mp->mnt_wapbl_replay) {
584 printf("%s: log corrupted;" 584 printf("%s: log corrupted;"
585 " replay cancelled\n", nm); 585 " replay cancelled\n", nm);
586 return EFTYPE; 586 return EFTYPE;
587 } 587 }
588 printf("%s: replaying log to disk\n", nm); 588 printf("%s: replaying log to disk\n", nm);
589 error = wapbl_replay_write(mp->mnt_wapbl_replay, 589 error = wapbl_replay_write(mp->mnt_wapbl_replay,
590 devvp); 590 devvp);
591 if (error) { 591 if (error) {
592 DPRINTF("%s: wapbl_replay_write %d", 592 DPRINTF("%s: wapbl_replay_write %d",
593 nm, error); 593 nm, error);
594 return error; 594 return error;
595 } 595 }
596 wapbl_replay_stop(mp->mnt_wapbl_replay); 596 wapbl_replay_stop(mp->mnt_wapbl_replay);
597 fs->fs_clean = FS_WASCLEAN; 597 fs->fs_clean = FS_WASCLEAN;
598 } 598 }
599#endif /* WAPBL */ 599#endif /* WAPBL */
600 if (fs->fs_snapinum[0] != 0) 600 if (fs->fs_snapinum[0] != 0)
601 ffs_snapshot_mount(mp); 601 ffs_snapshot_mount(mp);
602 } 602 }
603 603
604#ifdef WAPBL 604#ifdef WAPBL
605 error = ffs_wapbl_start(mp); 605 error = ffs_wapbl_start(mp);
606 if (error) { 606 if (error) {
607 DPRINTF("ffs_wapbl_start returned %d", error); 607 DPRINTF("ffs_wapbl_start returned %d", error);
608 return error; 608 return error;
609 } 609 }
610#endif /* WAPBL */ 610#endif /* WAPBL */
611 611
612#ifdef QUOTA2 612#ifdef QUOTA2
613 if (!fs->fs_ronly) { 613 if (!fs->fs_ronly) {
614 error = ffs_quota2_mount(mp); 614 error = ffs_quota2_mount(mp);
615 if (error) { 615 if (error) {
616 DPRINTF("ffs_quota2_mount returned %d", error); 616 DPRINTF("ffs_quota2_mount returned %d", error);
617 return error; 617 return error;
618 } 618 }
619 } 619 }
620#endif 620#endif
621 621
622 if ((mp->mnt_flag & MNT_DISCARD) && !(ump->um_discarddata)) 622 if ((mp->mnt_flag & MNT_DISCARD) && !(ump->um_discarddata))
623 ump->um_discarddata = ffs_discard_init(devvp, fs); 623 ump->um_discarddata = ffs_discard_init(devvp, fs);
624 624
625 if (args->fspec == NULL) 625 if (args->fspec == NULL)
626 return 0; 626 return 0;
627 } 627 }
628 628
629 error = set_statvfs_info(path, UIO_USERSPACE, args->fspec, 629 error = set_statvfs_info(path, UIO_USERSPACE, args->fspec,
630 UIO_USERSPACE, mp->mnt_op->vfs_name, mp, l); 630 UIO_USERSPACE, mp->mnt_op->vfs_name, mp, l);
631 if (error == 0) 631 if (error == 0)
632 (void)strncpy(fs->fs_fsmnt, mp->mnt_stat.f_mntonname, 632 (void)strncpy(fs->fs_fsmnt, mp->mnt_stat.f_mntonname,
633 sizeof(fs->fs_fsmnt)); 633 sizeof(fs->fs_fsmnt));
634 else { 634 else {
635 DPRINTF("set_statvfs_info returned %d", error); 635 DPRINTF("set_statvfs_info returned %d", error);
636 } 636 }
637 fs->fs_flags &= ~FS_DOSOFTDEP; 637 fs->fs_flags &= ~FS_DOSOFTDEP;
638 if (fs->fs_fmod != 0) { /* XXX */ 638 if (fs->fs_fmod != 0) { /* XXX */
639 int err; 639 int err;
640 640
641 fs->fs_fmod = 0; 641 fs->fs_fmod = 0;
642 if (fs->fs_clean & FS_WASCLEAN) 642 if (fs->fs_clean & FS_WASCLEAN)
643 fs->fs_time = time_second; 643 fs->fs_time = time_second;
644 else { 644 else {
645 printf("%s: file system not clean (fs_clean=%#x); " 645 printf("%s: file system not clean (fs_clean=%#x); "
646 "please fsck(8)\n", mp->mnt_stat.f_mntfromname, 646 "please fsck(8)\n", mp->mnt_stat.f_mntfromname,
647 fs->fs_clean); 647 fs->fs_clean);
648 printf("%s: lost blocks %" PRId64 " files %d\n", 648 printf("%s: lost blocks %" PRId64 " files %d\n",
649 mp->mnt_stat.f_mntfromname, fs->fs_pendingblocks, 649 mp->mnt_stat.f_mntfromname, fs->fs_pendingblocks,
650 fs->fs_pendinginodes); 650 fs->fs_pendinginodes);
651 } 651 }
652 err = UFS_WAPBL_BEGIN(mp); 652 err = UFS_WAPBL_BEGIN(mp);
653 if (err == 0) { 653 if (err == 0) {
654 (void) ffs_cgupdate(ump, MNT_WAIT); 654 (void) ffs_cgupdate(ump, MNT_WAIT);
655 UFS_WAPBL_END(mp); 655 UFS_WAPBL_END(mp);
656 } 656 }
657 } 657 }
658 if ((mp->mnt_flag & MNT_SOFTDEP) != 0) { 658 if ((mp->mnt_flag & MNT_SOFTDEP) != 0) {
659 printf("%s: `-o softdep' is no longer supported, " 659 printf("%s: `-o softdep' is no longer supported, "
660 "consider `-o log'\n", mp->mnt_stat.f_mntfromname); 660 "consider `-o log'\n", mp->mnt_stat.f_mntfromname);
661 mp->mnt_flag &= ~MNT_SOFTDEP; 661 mp->mnt_flag &= ~MNT_SOFTDEP;
662 } 662 }
663 663
664 return (error); 664 return (error);
665 665
666fail: 666fail:
667 vrele(devvp); 667 vrele(devvp);
668 return (error); 668 return (error);
669} 669}
670 670
671/* 671/*
672 * Reload all incore data for a filesystem (used after running fsck on 672 * Reload all incore data for a filesystem (used after running fsck on
673 * the root filesystem and finding things to fix). The filesystem must 673 * the root filesystem and finding things to fix). The filesystem must
674 * be mounted read-only. 674 * be mounted read-only.
675 * 675 *
676 * Things to do to update the mount: 676 * Things to do to update the mount:
677 * 1) invalidate all cached meta-data. 677 * 1) invalidate all cached meta-data.
678 * 2) re-read superblock from disk. 678 * 2) re-read superblock from disk.
679 * 3) re-read summary information from disk. 679 * 3) re-read summary information from disk.
680 * 4) invalidate all inactive vnodes. 680 * 4) invalidate all inactive vnodes.
681 * 5) invalidate all cached file data. 681 * 5) invalidate all cached file data.
682 * 6) re-read inode data for all active vnodes. 682 * 6) re-read inode data for all active vnodes.
683 */ 683 */
684int 684int
685ffs_reload(struct mount *mp, kauth_cred_t cred, struct lwp *l) 685ffs_reload(struct mount *mp, kauth_cred_t cred, struct lwp *l)
686{ 686{
687 struct vnode *vp, *devvp; 687 struct vnode *vp, *devvp;
688 struct inode *ip; 688 struct inode *ip;
689 void *space; 689 void *space;
690 struct buf *bp; 690 struct buf *bp;
691 struct fs *fs, *newfs; 691 struct fs *fs, *newfs;
692 struct dkwedge_info dkw; 692 struct dkwedge_info dkw;
693 int i, bsize, blks, error; 693 int i, bsize, blks, error;
694 int32_t *lp, fs_sbsize; 694 int32_t *lp, fs_sbsize;
695 struct ufsmount *ump; 695 struct ufsmount *ump;
696 daddr_t sblockloc; 696 daddr_t sblockloc;
697 struct vnode_iterator *marker; 697 struct vnode_iterator *marker;
698 698
699 if ((mp->mnt_flag & MNT_RDONLY) == 0) 699 if ((mp->mnt_flag & MNT_RDONLY) == 0)
700 return (EINVAL); 700 return (EINVAL);
701 701
702 ump = VFSTOUFS(mp); 702 ump = VFSTOUFS(mp);
703 703
704 /* 704 /*
705 * Step 1: invalidate all cached meta-data. 705 * Step 1: invalidate all cached meta-data.
706 */ 706 */
707 devvp = ump->um_devvp; 707 devvp = ump->um_devvp;
708 vn_lock(devvp, LK_EXCLUSIVE | LK_RETRY); 708 vn_lock(devvp, LK_EXCLUSIVE | LK_RETRY);
709 error = vinvalbuf(devvp, 0, cred, l, 0, 0); 709 error = vinvalbuf(devvp, 0, cred, l, 0, 0);
710 VOP_UNLOCK(devvp); 710 VOP_UNLOCK(devvp);
711 if (error) 711 if (error)
712 panic("ffs_reload: dirty1"); 712 panic("ffs_reload: dirty1");
713 713
714 /* 714 /*
715 * Step 2: re-read superblock from disk. XXX: We don't handle 715 * Step 2: re-read superblock from disk. XXX: We don't handle
716 * possibility that superblock moved. Which implies that we don't 716 * possibility that superblock moved. Which implies that we don't
717 * want its size to change either. 717 * want its size to change either.
718 */ 718 */
719 fs = ump->um_fs; 719 fs = ump->um_fs;
720 fs_sbsize = fs->fs_sbsize; 720 fs_sbsize = fs->fs_sbsize;
721 error = bread(devvp, fs->fs_sblockloc / DEV_BSIZE, fs_sbsize, 721 error = bread(devvp, fs->fs_sblockloc / DEV_BSIZE, fs_sbsize,
722 NOCRED, 0, &bp); 722 NOCRED, 0, &bp);
723 if (error) 723 if (error)
724 return (error); 724 return (error);
725 newfs = kmem_alloc(fs_sbsize, KM_SLEEP); 725 newfs = kmem_alloc(fs_sbsize, KM_SLEEP);
726 memcpy(newfs, bp->b_data, fs_sbsize); 726 memcpy(newfs, bp->b_data, fs_sbsize);
727 727
728#ifdef FFS_EI 728#ifdef FFS_EI
729 if (ump->um_flags & UFS_NEEDSWAP) { 729 if (ump->um_flags & UFS_NEEDSWAP) {
730 ffs_sb_swap((struct fs*)bp->b_data, newfs); 730 ffs_sb_swap((struct fs*)bp->b_data, newfs);
731 fs->fs_flags |= FS_SWAPPED; 731 fs->fs_flags |= FS_SWAPPED;
732 } else 732 } else
733#endif 733#endif
734 fs->fs_flags &= ~FS_SWAPPED; 734 fs->fs_flags &= ~FS_SWAPPED;
735 735
736 /* We don't want the superblock size to change. */ 
737 if (newfs->fs_sbsize != fs_sbsize) { 
738 brelse(bp, 0); 
739 kmem_free(newfs, fs_sbsize); 
740 return (EINVAL); 
741 } 
742 if ((newfs->fs_magic != FS_UFS1_MAGIC && 736 if ((newfs->fs_magic != FS_UFS1_MAGIC &&
743 newfs->fs_magic != FS_UFS2_MAGIC)) { 737 newfs->fs_magic != FS_UFS2_MAGIC)) {
744 brelse(bp, 0); 738 brelse(bp, 0);
745 kmem_free(newfs, fs_sbsize); 739 kmem_free(newfs, fs_sbsize);
746 return (EIO); /* XXX needs translation */ 740 return (EIO); /* XXX needs translation */
747 } 741 }
748 if (!ffs_superblock_validate(newfs)) { 742 if (!ffs_superblock_validate(newfs)) {
749 brelse(bp, 0); 743 brelse(bp, 0);
750 kmem_free(newfs, fs_sbsize); 744 kmem_free(newfs, fs_sbsize);
751 return (EINVAL); 745 return (EINVAL);
752 } 746 }
753 747
 748 /*
 749 * The current implementation doesn't handle the possibility that
 750 * these values may have changed.
 751 */
 752 if ((newfs->fs_sbsize != fs_sbsize) ||
 753 (newfs->fs_cssize != fs->fs_cssize) ||
 754 (newfs->fs_contigsumsize != fs->fs_contigsumsize) ||
 755 (newfs->fs_ncg != fs->fs_ncg)) {
 756 brelse(bp, 0);
 757 kmem_free(newfs, fs_sbsize);
 758 return (EINVAL);
 759 }
 760
 761
754 /* Store off old fs_sblockloc for fs_oldfscompat_read. */ 762 /* Store off old fs_sblockloc for fs_oldfscompat_read. */
755 sblockloc = fs->fs_sblockloc; 763 sblockloc = fs->fs_sblockloc;
756 /* 764 /*
757 * Copy pointer fields back into superblock before copying in XXX 765 * Copy pointer fields back into superblock before copying in XXX
758 * new superblock. These should really be in the ufsmount. XXX 766 * new superblock. These should really be in the ufsmount. XXX
759 * Note that important parameters (eg fs_ncg) are unchanged. 767 * Note that important parameters (eg fs_ncg) are unchanged.
760 */ 768 */
761 newfs->fs_csp = fs->fs_csp; 769 newfs->fs_csp = fs->fs_csp;
762 newfs->fs_maxcluster = fs->fs_maxcluster; 770 newfs->fs_maxcluster = fs->fs_maxcluster;
763 newfs->fs_contigdirs = fs->fs_contigdirs; 771 newfs->fs_contigdirs = fs->fs_contigdirs;
764 newfs->fs_ronly = fs->fs_ronly; 772 newfs->fs_ronly = fs->fs_ronly;
765 newfs->fs_active = fs->fs_active; 773 newfs->fs_active = fs->fs_active;
766 memcpy(fs, newfs, (u_int)fs_sbsize); 774 memcpy(fs, newfs, (u_int)fs_sbsize);
767 brelse(bp, 0); 775 brelse(bp, 0);
768 kmem_free(newfs, fs_sbsize); 776 kmem_free(newfs, fs_sbsize);
769 777
770 /* Recheck for apple UFS filesystem */ 778 /* Recheck for apple UFS filesystem */
771 ump->um_flags &= ~UFS_ISAPPLEUFS; 779 ump->um_flags &= ~UFS_ISAPPLEUFS;
772 /* First check to see if this is tagged as an Apple UFS filesystem 780 /* First check to see if this is tagged as an Apple UFS filesystem
773 * in the disklabel 781 * in the disklabel
774 */ 782 */
775 if (getdiskinfo(devvp, &dkw) == 0 && 783 if (getdiskinfo(devvp, &dkw) == 0 &&
776 strcmp(dkw.dkw_ptype, DKW_PTYPE_APPLEUFS) == 0) 784 strcmp(dkw.dkw_ptype, DKW_PTYPE_APPLEUFS) == 0)
777 ump->um_flags |= UFS_ISAPPLEUFS; 785 ump->um_flags |= UFS_ISAPPLEUFS;
778#ifdef APPLE_UFS 786#ifdef APPLE_UFS
779 else { 787 else {
780 /* Manually look for an apple ufs label, and if a valid one 788 /* Manually look for an apple ufs label, and if a valid one
781 * is found, then treat it like an Apple UFS filesystem anyway 789 * is found, then treat it like an Apple UFS filesystem anyway
782 * 790 *
783 * EINVAL is most probably a blocksize or alignment problem, 791 * EINVAL is most probably a blocksize or alignment problem,
784 * it is unlikely that this is an Apple UFS filesystem then. 792 * it is unlikely that this is an Apple UFS filesystem then.
785 */ 793 */
786 error = bread(devvp, 794 error = bread(devvp,
787 (daddr_t)(APPLEUFS_LABEL_OFFSET / DEV_BSIZE), 795 (daddr_t)(APPLEUFS_LABEL_OFFSET / DEV_BSIZE),
788 APPLEUFS_LABEL_SIZE, cred, 0, &bp); 796 APPLEUFS_LABEL_SIZE, cred, 0, &bp);
789 if (error && error != EINVAL) { 797 if (error && error != EINVAL) {
790 return error; 798 return error;
791 } 799 }
792 if (error == 0) { 800 if (error == 0) {
793 error = ffs_appleufs_validate(fs->fs_fsmnt, 801 error = ffs_appleufs_validate(fs->fs_fsmnt,
794 (struct appleufslabel *)bp->b_data, NULL); 802 (struct appleufslabel *)bp->b_data, NULL);
795 if (error == 0) 803 if (error == 0)
796 ump->um_flags |= UFS_ISAPPLEUFS; 804 ump->um_flags |= UFS_ISAPPLEUFS;
797 brelse(bp, 0); 805 brelse(bp, 0);
798 } 806 }
799 bp = NULL; 807 bp = NULL;
800 } 808 }
801#else 809#else
802 if (ump->um_flags & UFS_ISAPPLEUFS) 810 if (ump->um_flags & UFS_ISAPPLEUFS)
803 return (EIO); 811 return (EIO);
804#endif 812#endif
805 813
806 if (UFS_MPISAPPLEUFS(ump)) { 814 if (UFS_MPISAPPLEUFS(ump)) {
807 /* see comment about NeXT below */ 815 /* see comment about NeXT below */
808 ump->um_maxsymlinklen = APPLEUFS_MAXSYMLINKLEN; 816 ump->um_maxsymlinklen = APPLEUFS_MAXSYMLINKLEN;
809 ump->um_dirblksiz = APPLEUFS_DIRBLKSIZ; 817 ump->um_dirblksiz = APPLEUFS_DIRBLKSIZ;
810 mp->mnt_iflag |= IMNT_DTYPE; 818 mp->mnt_iflag |= IMNT_DTYPE;
811 } else { 819 } else {
812 ump->um_maxsymlinklen = fs->fs_maxsymlinklen; 820 ump->um_maxsymlinklen = fs->fs_maxsymlinklen;
813 ump->um_dirblksiz = UFS_DIRBLKSIZ; 821 ump->um_dirblksiz = UFS_DIRBLKSIZ;
814 if (ump->um_maxsymlinklen > 0) 822 if (ump->um_maxsymlinklen > 0)
815 mp->mnt_iflag |= IMNT_DTYPE; 823 mp->mnt_iflag |= IMNT_DTYPE;
816 else 824 else
817 mp->mnt_iflag &= ~IMNT_DTYPE; 825 mp->mnt_iflag &= ~IMNT_DTYPE;
818 } 826 }
819 ffs_oldfscompat_read(fs, ump, sblockloc); 827 ffs_oldfscompat_read(fs, ump, sblockloc);
820 828
821 mutex_enter(&ump->um_lock); 829 mutex_enter(&ump->um_lock);
822 ump->um_maxfilesize = fs->fs_maxfilesize; 830 ump->um_maxfilesize = fs->fs_maxfilesize;
823 if (fs->fs_flags & ~(FS_KNOWN_FLAGS | FS_INTERNAL)) { 831 if (fs->fs_flags & ~(FS_KNOWN_FLAGS | FS_INTERNAL)) {
824 uprintf("%s: unknown ufs flags: 0x%08"PRIx32"%s\n", 832 uprintf("%s: unknown ufs flags: 0x%08"PRIx32"%s\n",
825 mp->mnt_stat.f_mntonname, fs->fs_flags, 833 mp->mnt_stat.f_mntonname, fs->fs_flags,
826 (mp->mnt_flag & MNT_FORCE) ? "" : ", not mounting"); 834 (mp->mnt_flag & MNT_FORCE) ? "" : ", not mounting");
827 if ((mp->mnt_flag & MNT_FORCE) == 0) { 835 if ((mp->mnt_flag & MNT_FORCE) == 0) {
828 mutex_exit(&ump->um_lock); 836 mutex_exit(&ump->um_lock);
829 return (EINVAL); 837 return (EINVAL);
830 } 838 }
831 } 839 }
832 if (fs->fs_pendingblocks != 0 || fs->fs_pendinginodes != 0) { 840 if (fs->fs_pendingblocks != 0 || fs->fs_pendinginodes != 0) {
833 fs->fs_pendingblocks = 0; 841 fs->fs_pendingblocks = 0;
834 fs->fs_pendinginodes = 0; 842 fs->fs_pendinginodes = 0;
835 } 843 }
836 mutex_exit(&ump->um_lock); 844 mutex_exit(&ump->um_lock);
837 845
838 ffs_statvfs(mp, &mp->mnt_stat); 846 ffs_statvfs(mp, &mp->mnt_stat);
839 /* 847 /*
840 * Step 3: re-read summary information from disk. 848 * Step 3: re-read summary information from disk.
841 */ 849 */
842 blks = howmany(fs->fs_cssize, fs->fs_fsize); 850 blks = howmany(fs->fs_cssize, fs->fs_fsize);
843 space = fs->fs_csp; 851 space = fs->fs_csp;
844 for (i = 0; i < blks; i += fs->fs_frag) { 852 for (i = 0; i < blks; i += fs->fs_frag) {
845 bsize = fs->fs_bsize; 853 bsize = fs->fs_bsize;
846 if (i + fs->fs_frag > blks) 854 if (i + fs->fs_frag > blks)
847 bsize = (blks - i) * fs->fs_fsize; 855 bsize = (blks - i) * fs->fs_fsize;
848 error = bread(devvp, FFS_FSBTODB(fs, fs->fs_csaddr + i), bsize, 856 error = bread(devvp, FFS_FSBTODB(fs, fs->fs_csaddr + i), bsize,
849 NOCRED, 0, &bp); 857 NOCRED, 0, &bp);
850 if (error) { 858 if (error) {
851 return (error); 859 return (error);
852 } 860 }
853#ifdef FFS_EI 861#ifdef FFS_EI
854 if (UFS_FSNEEDSWAP(fs)) 862 if (UFS_FSNEEDSWAP(fs))
855 ffs_csum_swap((struct csum *)bp->b_data, 863 ffs_csum_swap((struct csum *)bp->b_data,
856 (struct csum *)space, bsize); 864 (struct csum *)space, bsize);
857 else 865 else
858#endif 866#endif
859 memcpy(space, bp->b_data, (size_t)bsize); 867 memcpy(space, bp->b_data, (size_t)bsize);
860 space = (char *)space + bsize; 868 space = (char *)space + bsize;
861 brelse(bp, 0); 869 brelse(bp, 0);
862 } 870 }
863 /* 871 /*
864 * We no longer know anything about clusters per cylinder group. 872 * We no longer know anything about clusters per cylinder group.
865 */ 873 */
866 if (fs->fs_contigsumsize > 0) { 874 if (fs->fs_contigsumsize > 0) {
867 lp = fs->fs_maxcluster; 875 lp = fs->fs_maxcluster;
868 for (i = 0; i < fs->fs_ncg; i++) 876 for (i = 0; i < fs->fs_ncg; i++)
869 *lp++ = fs->fs_contigsumsize; 877 *lp++ = fs->fs_contigsumsize;
870 } 878 }
871 879
872 vfs_vnode_iterator_init(mp, &marker); 880 vfs_vnode_iterator_init(mp, &marker);
873 while ((vp = vfs_vnode_iterator_next(marker, NULL, NULL))) { 881 while ((vp = vfs_vnode_iterator_next(marker, NULL, NULL))) {
874 /* 882 /*
875 * Step 4: invalidate all inactive vnodes. 883 * Step 4: invalidate all inactive vnodes.
876 */ 884 */
877 if (vrecycle(vp)) 885 if (vrecycle(vp))
878 continue; 886 continue;
879 /* 887 /*
880 * Step 5: invalidate all cached file data. 888 * Step 5: invalidate all cached file data.
881 */ 889 */
882 if (vn_lock(vp, LK_EXCLUSIVE)) { 890 if (vn_lock(vp, LK_EXCLUSIVE)) {
883 vrele(vp); 891 vrele(vp);
884 continue; 892 continue;
885 } 893 }
886 if (vinvalbuf(vp, 0, cred, l, 0, 0)) 894 if (vinvalbuf(vp, 0, cred, l, 0, 0))
887 panic("ffs_reload: dirty2"); 895 panic("ffs_reload: dirty2");
888 /* 896 /*
889 * Step 6: re-read inode data for all active vnodes. 897 * Step 6: re-read inode data for all active vnodes.
890 */ 898 */
891 ip = VTOI(vp); 899 ip = VTOI(vp);
892 error = bread(devvp, FFS_FSBTODB(fs, ino_to_fsba(fs, ip->i_number)), 900 error = bread(devvp, FFS_FSBTODB(fs, ino_to_fsba(fs, ip->i_number)),
893 (int)fs->fs_bsize, NOCRED, 0, &bp); 901 (int)fs->fs_bsize, NOCRED, 0, &bp);
894 if (error) { 902 if (error) {
895 vput(vp); 903 vput(vp);
896 break; 904 break;
897 } 905 }
898 ffs_load_inode(bp, ip, fs, ip->i_number); 906 ffs_load_inode(bp, ip, fs, ip->i_number);
899 brelse(bp, 0); 907 brelse(bp, 0);
900 vput(vp); 908 vput(vp);
901 } 909 }
902 vfs_vnode_iterator_destroy(marker); 910 vfs_vnode_iterator_destroy(marker);
903 return (error); 911 return (error);
904} 912}
905 913
906/* 914/*
907 * Possible superblock locations ordered from most to least likely. 915 * Possible superblock locations ordered from most to least likely.
908 */ 916 */
909static const int sblock_try[] = SBLOCKSEARCH; 917static const int sblock_try[] = SBLOCKSEARCH;
910 918
911 919
912static int 920static int
913ffs_superblock_validate(struct fs *fs) 921ffs_superblock_validate(struct fs *fs)
914{ 922{
915 int32_t i, fs_bshift = 0, fs_fshift = 0, fs_fragshift = 0, fs_frag; 923 int32_t i, fs_bshift = 0, fs_fshift = 0, fs_fragshift = 0, fs_frag;
916 924
917 /* Check the superblock size */ 925 /* Check the superblock size */
918 if (fs->fs_sbsize > SBLOCKSIZE || fs->fs_sbsize < sizeof(struct fs)) 926 if (fs->fs_sbsize > SBLOCKSIZE || fs->fs_sbsize < sizeof(struct fs))
919 return 0; 927 return 0;
920 928
921 /* Check the file system blocksize */ 929 /* Check the file system blocksize */
922 if (fs->fs_bsize > MAXBSIZE || fs->fs_bsize < MINBSIZE) 930 if (fs->fs_bsize > MAXBSIZE || fs->fs_bsize < MINBSIZE)
923 return 0; 931 return 0;
924 if (!powerof2(fs->fs_bsize)) 932 if (!powerof2(fs->fs_bsize))
925 return 0; 933 return 0;
926 934
927 /* Check the size of frag blocks */ 935 /* Check the size of frag blocks */
928 if (!powerof2(fs->fs_fsize)) 936 if (!powerof2(fs->fs_fsize))
929 return 0; 937 return 0;
930 if (fs->fs_fsize == 0) 938 if (fs->fs_fsize == 0)
931 return 0; 939 return 0;
932 940
933 if (fs->fs_size == 0) 941 if (fs->fs_size == 0)
934 return 0; 942 return 0;
935 if (fs->fs_cssize == 0) 943 if (fs->fs_cssize == 0)
936 return 0; 944 return 0;
937 945
938 /* Block size cannot be smaller than fragment size */ 946 /* Block size cannot be smaller than fragment size */
939 if (fs->fs_bsize < fs->fs_fsize) 947 if (fs->fs_bsize < fs->fs_fsize)
940 return 0; 948 return 0;
941 949
942 /* Compute fs_bshift and ensure it is consistent */ 950 /* Compute fs_bshift and ensure it is consistent */
943 for (i = fs->fs_bsize; i > 1; i >>= 1) 951 for (i = fs->fs_bsize; i > 1; i >>= 1)
944 fs_bshift++; 952 fs_bshift++;
945 if (fs->fs_bshift != fs_bshift) 953 if (fs->fs_bshift != fs_bshift)
946 return 0; 954 return 0;
947 955
948 /* Compute fs_fshift and ensure it is consistent */ 956 /* Compute fs_fshift and ensure it is consistent */
949 for (i = fs->fs_fsize; i > 1; i >>= 1) 957 for (i = fs->fs_fsize; i > 1; i >>= 1)
950 fs_fshift++; 958 fs_fshift++;
951 if (fs->fs_fshift != fs_fshift) 959 if (fs->fs_fshift != fs_fshift)
952 return 0; 960 return 0;
953 961
954 /* Compute fs_fragshift and ensure it is consistent */ 962 /* Compute fs_fragshift and ensure it is consistent */
955 for (i = fs->fs_frag; i > 1; i >>= 1) 963 for (i = fs->fs_frag; i > 1; i >>= 1)
956 fs_fragshift++; 964 fs_fragshift++;
957 if (fs->fs_fragshift != fs_fragshift) 965 if (fs->fs_fragshift != fs_fragshift)
958 return 0; 966 return 0;
959 967
960 /* Check the masks */ 968 /* Check the masks */
961 if (fs->fs_bmask != ~(fs->fs_bsize - 1)) 969 if (fs->fs_bmask != ~(fs->fs_bsize - 1))
962 return 0; 970 return 0;
963 if (fs->fs_fmask != ~(fs->fs_fsize - 1)) 971 if (fs->fs_fmask != ~(fs->fs_fsize - 1))
964 return 0; 972 return 0;
965 973
966 /* 974 /*
967 * Now that the shifts and masks are sanitized, we can use the ffs_ API. 975 * Now that the shifts and masks are sanitized, we can use the ffs_ API.
968 */ 976 */
969 977
970 /* Check the number of frag blocks */ 978 /* Check the number of frag blocks */
971 if ((fs_frag = ffs_numfrags(fs, fs->fs_bsize)) > MAXFRAG) 979 if ((fs_frag = ffs_numfrags(fs, fs->fs_bsize)) > MAXFRAG)
972 return 0; 980 return 0;
973 if (fs->fs_frag != fs_frag) 981 if (fs->fs_frag != fs_frag)
974 return 0; 982 return 0;
975 983
976 return 1; 984 return 1;
977} 985}
978 986
979/* 987/*
980 * Common code for mount and mountroot 988 * Common code for mount and mountroot
981 */ 989 */
982int 990int
983ffs_mountfs(struct vnode *devvp, struct mount *mp, struct lwp *l) 991ffs_mountfs(struct vnode *devvp, struct mount *mp, struct lwp *l)
984{ 992{
985 struct ufsmount *ump = NULL; 993 struct ufsmount *ump = NULL;
986 struct buf *bp = NULL; 994 struct buf *bp = NULL;
987 struct fs *fs = NULL; 995 struct fs *fs = NULL;
988 dev_t dev; 996 dev_t dev;
989 struct dkwedge_info dkw; 997 struct dkwedge_info dkw;
990 void *space; 998 void *space;
991 daddr_t sblockloc = 0; 999 daddr_t sblockloc = 0;
992 int blks, fstype = 0; 1000 int blks, fstype = 0;
993 int error, i, bsize, ronly, bset = 0; 1001 int error, i, bsize, ronly, bset = 0;
994#ifdef FFS_EI 1002#ifdef FFS_EI
995 int needswap = 0; /* keep gcc happy */ 1003 int needswap = 0; /* keep gcc happy */
996#endif 1004#endif
997 int32_t *lp; 1005 int32_t *lp;
998 kauth_cred_t cred; 1006 kauth_cred_t cred;
999 u_int32_t allocsbsize, fs_sbsize = 0; 1007 u_int32_t allocsbsize, fs_sbsize = 0;
1000 1008
1001 dev = devvp->v_rdev; 1009 dev = devvp->v_rdev;
1002 cred = l ? l->l_cred : NOCRED; 1010 cred = l ? l->l_cred : NOCRED;
1003 1011
1004 /* Flush out any old buffers remaining from a previous use. */ 1012 /* Flush out any old buffers remaining from a previous use. */
1005 vn_lock(devvp, LK_EXCLUSIVE | LK_RETRY); 1013 vn_lock(devvp, LK_EXCLUSIVE | LK_RETRY);
1006 error = vinvalbuf(devvp, V_SAVE, cred, l, 0, 0); 1014 error = vinvalbuf(devvp, V_SAVE, cred, l, 0, 0);
1007 VOP_UNLOCK(devvp); 1015 VOP_UNLOCK(devvp);
1008 if (error) { 1016 if (error) {
1009 DPRINTF("vinvalbuf returned %d", error); 1017 DPRINTF("vinvalbuf returned %d", error);
1010 return error; 1018 return error;
1011 } 1019 }
1012 1020
1013 ronly = (mp->mnt_flag & MNT_RDONLY) != 0; 1021 ronly = (mp->mnt_flag & MNT_RDONLY) != 0;
1014 1022
1015 error = fstrans_mount(mp); 1023 error = fstrans_mount(mp);
1016 if (error) { 1024 if (error) {
1017 DPRINTF("fstrans_mount returned %d", error); 1025 DPRINTF("fstrans_mount returned %d", error);
1018 return error; 1026 return error;
1019 } 1027 }
1020 1028
1021 ump = kmem_zalloc(sizeof(*ump), KM_SLEEP); 1029 ump = kmem_zalloc(sizeof(*ump), KM_SLEEP);
1022 mutex_init(&ump->um_lock, MUTEX_DEFAULT, IPL_NONE); 1030 mutex_init(&ump->um_lock, MUTEX_DEFAULT, IPL_NONE);
1023 error = ffs_snapshot_init(ump); 1031 error = ffs_snapshot_init(ump);
1024 if (error) { 1032 if (error) {
1025 DPRINTF("ffs_snapshot_init returned %d", error); 1033 DPRINTF("ffs_snapshot_init returned %d", error);
1026 goto out; 1034 goto out;
1027 } 1035 }
1028 ump->um_ops = &ffs_ufsops; 1036 ump->um_ops = &ffs_ufsops;
1029 1037
1030#ifdef WAPBL 1038#ifdef WAPBL
1031 sbagain: 1039 sbagain:
1032#endif 1040#endif
1033 /* 1041 /*
1034 * Try reading the superblock in each of its possible locations. 1042 * Try reading the superblock in each of its possible locations.
1035 */ 1043 */
1036 for (i = 0; ; i++) { 1044 for (i = 0; ; i++) {
1037 daddr_t fs_sblockloc; 1045 daddr_t fs_sblockloc;
1038 1046
1039 if (bp != NULL) { 1047 if (bp != NULL) {
1040 brelse(bp, BC_NOCACHE); 1048 brelse(bp, BC_NOCACHE);
1041 bp = NULL; 1049 bp = NULL;
1042 } 1050 }
1043 if (sblock_try[i] == -1) { 1051 if (sblock_try[i] == -1) {
1044 DPRINTF("no superblock found"); 1052 DPRINTF("no superblock found");
1045 error = EINVAL; 1053 error = EINVAL;
1046 fs = NULL; 1054 fs = NULL;
1047 goto out; 1055 goto out;
1048 } 1056 }
1049 1057
1050 error = bread(devvp, sblock_try[i] / DEV_BSIZE, SBLOCKSIZE, 1058 error = bread(devvp, sblock_try[i] / DEV_BSIZE, SBLOCKSIZE,
1051 cred, 0, &bp); 1059 cred, 0, &bp);
1052 if (error) { 1060 if (error) {
1053 DPRINTF("bread@0x%x returned %d", 1061 DPRINTF("bread@0x%x returned %d",
1054 sblock_try[i] / DEV_BSIZE, error); 1062 sblock_try[i] / DEV_BSIZE, error);
1055 fs = NULL; 1063 fs = NULL;
1056 goto out; 1064 goto out;
1057 } 1065 }
1058 fs = (struct fs *)bp->b_data; 1066 fs = (struct fs *)bp->b_data;
1059 1067
1060 sblockloc = sblock_try[i]; 1068 sblockloc = sblock_try[i];
1061 DPRINTF("fs_magic 0x%x", fs->fs_magic); 1069 DPRINTF("fs_magic 0x%x", fs->fs_magic);
1062 1070
1063 /* 1071 /*
1064 * Swap: here, we swap fs->fs_sbsize in order to get the correct 1072 * Swap: here, we swap fs->fs_sbsize in order to get the correct
1065 * size to read the superblock. Once read, we swap the whole 1073 * size to read the superblock. Once read, we swap the whole
1066 * superblock structure. 1074 * superblock structure.
1067 */ 1075 */
1068 if (fs->fs_magic == FS_UFS1_MAGIC) { 1076 if (fs->fs_magic == FS_UFS1_MAGIC) {
1069 fs_sbsize = fs->fs_sbsize; 1077 fs_sbsize = fs->fs_sbsize;
1070 fstype = UFS1; 1078 fstype = UFS1;
1071#ifdef FFS_EI 1079#ifdef FFS_EI
1072 needswap = 0; 1080 needswap = 0;
1073 } else if (fs->fs_magic == FS_UFS1_MAGIC_SWAPPED) { 1081 } else if (fs->fs_magic == FS_UFS1_MAGIC_SWAPPED) {
1074 fs_sbsize = bswap32(fs->fs_sbsize); 1082 fs_sbsize = bswap32(fs->fs_sbsize);
1075 fstype = UFS1; 1083 fstype = UFS1;
1076 needswap = 1; 1084 needswap = 1;
1077#endif 1085#endif
1078 } else if (fs->fs_magic == FS_UFS2_MAGIC) { 1086 } else if (fs->fs_magic == FS_UFS2_MAGIC) {
1079 fs_sbsize = fs->fs_sbsize; 1087 fs_sbsize = fs->fs_sbsize;
1080 fstype = UFS2; 1088 fstype = UFS2;
1081#ifdef FFS_EI 1089#ifdef FFS_EI
1082 needswap = 0; 1090 needswap = 0;
1083 } else if (fs->fs_magic == FS_UFS2_MAGIC_SWAPPED) { 1091 } else if (fs->fs_magic == FS_UFS2_MAGIC_SWAPPED) {
1084 fs_sbsize = bswap32(fs->fs_sbsize); 1092 fs_sbsize = bswap32(fs->fs_sbsize);
1085 fstype = UFS2; 1093 fstype = UFS2;
1086 needswap = 1; 1094 needswap = 1;
1087#endif 1095#endif
1088 } else 1096 } else
1089 continue; 1097 continue;
1090 1098
1091 /* fs->fs_sblockloc isn't defined for old filesystems */ 1099 /* fs->fs_sblockloc isn't defined for old filesystems */
1092 if (fstype == UFS1 && !(fs->fs_old_flags & FS_FLAGS_UPDATED)) { 1100 if (fstype == UFS1 && !(fs->fs_old_flags & FS_FLAGS_UPDATED)) {
1093 if (sblockloc == SBLOCK_UFS2) 1101 if (sblockloc == SBLOCK_UFS2)
1094 /* 1102 /*
1095 * This is likely to be the first alternate 1103 * This is likely to be the first alternate
1096 * in a filesystem with 64k blocks. 1104 * in a filesystem with 64k blocks.
1097 * Don't use it. 1105 * Don't use it.
1098 */ 1106 */
1099 continue; 1107 continue;
1100 fs_sblockloc = sblockloc; 1108 fs_sblockloc = sblockloc;
1101 } else { 1109 } else {
1102 fs_sblockloc = fs->fs_sblockloc; 1110 fs_sblockloc = fs->fs_sblockloc;
1103#ifdef FFS_EI 1111#ifdef FFS_EI
1104 if (needswap) 1112 if (needswap)
1105 fs_sblockloc = bswap64(fs_sblockloc); 1113 fs_sblockloc = bswap64(fs_sblockloc);
1106#endif 1114#endif
1107 } 1115 }
1108 1116
1109 /* Check we haven't found an alternate superblock */ 1117 /* Check we haven't found an alternate superblock */
1110 if (fs_sblockloc != sblockloc) 1118 if (fs_sblockloc != sblockloc)
1111 continue; 1119 continue;
1112 1120
1113 /* Check the superblock size */ 1121 /* Check the superblock size */
1114 if (fs_sbsize > SBLOCKSIZE || fs_sbsize < sizeof(struct fs)) 1122 if (fs_sbsize > SBLOCKSIZE || fs_sbsize < sizeof(struct fs))
1115 continue; 1123 continue;
1116 fs = kmem_alloc((u_long)fs_sbsize, KM_SLEEP); 1124 fs = kmem_alloc((u_long)fs_sbsize, KM_SLEEP);
1117 memcpy(fs, bp->b_data, fs_sbsize); 1125 memcpy(fs, bp->b_data, fs_sbsize);
1118 1126
1119 /* Swap the whole superblock structure, if necessary. */ 1127 /* Swap the whole superblock structure, if necessary. */
1120#ifdef FFS_EI 1128#ifdef FFS_EI
1121 if (needswap) { 1129 if (needswap) {
1122 ffs_sb_swap((struct fs*)bp->b_data, fs); 1130 ffs_sb_swap((struct fs*)bp->b_data, fs);
1123 fs->fs_flags |= FS_SWAPPED; 1131 fs->fs_flags |= FS_SWAPPED;
1124 } else 1132 } else
1125#endif 1133#endif
1126 fs->fs_flags &= ~FS_SWAPPED; 1134 fs->fs_flags &= ~FS_SWAPPED;
1127 1135
1128 /* 1136 /*
1129 * Now that everything is swapped, the superblock is ready to 1137 * Now that everything is swapped, the superblock is ready to
1130 * be sanitized. 1138 * be sanitized.
1131 */ 1139 */
1132 if (!ffs_superblock_validate(fs)) { 1140 if (!ffs_superblock_validate(fs)) {
1133 kmem_free(fs, fs_sbsize); 1141 kmem_free(fs, fs_sbsize);
1134 continue; 1142 continue;
1135 } 1143 }
1136 1144
1137 /* Ok seems to be a good superblock */ 1145 /* Ok seems to be a good superblock */
1138 break; 1146 break;
1139 } 1147 }
1140 1148
1141 ump->um_fs = fs; 1149 ump->um_fs = fs;
1142 1150
1143#ifdef WAPBL 1151#ifdef WAPBL
1144 if ((mp->mnt_wapbl_replay == 0) && (fs->fs_flags & FS_DOWAPBL)) { 1152 if ((mp->mnt_wapbl_replay == 0) && (fs->fs_flags & FS_DOWAPBL)) {
1145 error = ffs_wapbl_replay_start(mp, fs, devvp); 1153 error = ffs_wapbl_replay_start(mp, fs, devvp);
1146 if (error && (mp->mnt_flag & MNT_FORCE) == 0) { 1154 if (error && (mp->mnt_flag & MNT_FORCE) == 0) {
1147 DPRINTF("ffs_wapbl_replay_start returned %d", error); 1155 DPRINTF("ffs_wapbl_replay_start returned %d", error);
1148 goto out; 1156 goto out;
1149 } 1157 }
1150 if (!error) { 1158 if (!error) {
1151 if (!ronly) { 1159 if (!ronly) {
1152 /* XXX fsmnt may be stale. */ 1160 /* XXX fsmnt may be stale. */
1153 printf("%s: replaying log to disk\n", 1161 printf("%s: replaying log to disk\n",
1154 fs->fs_fsmnt); 1162 fs->fs_fsmnt);
1155 error = wapbl_replay_write(mp->mnt_wapbl_replay, 1163 error = wapbl_replay_write(mp->mnt_wapbl_replay,
1156 devvp); 1164 devvp);
1157 if (error) { 1165 if (error) {
1158 DPRINTF("wapbl_replay_write returned %d", 1166 DPRINTF("wapbl_replay_write returned %d",
1159 error); 1167 error);
1160 goto out; 1168 goto out;
1161 } 1169 }
1162 wapbl_replay_stop(mp->mnt_wapbl_replay); 1170 wapbl_replay_stop(mp->mnt_wapbl_replay);
1163 fs->fs_clean = FS_WASCLEAN; 1171 fs->fs_clean = FS_WASCLEAN;
1164 } else { 1172 } else {
1165 /* XXX fsmnt may be stale */ 1173 /* XXX fsmnt may be stale */
1166 printf("%s: replaying log to memory\n", 1174 printf("%s: replaying log to memory\n",
1167 fs->fs_fsmnt); 1175 fs->fs_fsmnt);
1168 } 1176 }
1169 1177
1170 /* Force a re-read of the superblock */ 1178 /* Force a re-read of the superblock */
1171 brelse(bp, BC_INVAL); 1179 brelse(bp, BC_INVAL);
1172 bp = NULL; 1180 bp = NULL;
1173 kmem_free(fs, fs_sbsize); 1181 kmem_free(fs, fs_sbsize);
1174 fs = NULL; 1182 fs = NULL;
1175 goto sbagain; 1183 goto sbagain;
1176 } 1184 }
1177 } 1185 }
1178#else /* !WAPBL */ 1186#else /* !WAPBL */
1179 if ((fs->fs_flags & FS_DOWAPBL) && (mp->mnt_flag & MNT_FORCE) == 0) { 1187 if ((fs->fs_flags & FS_DOWAPBL) && (mp->mnt_flag & MNT_FORCE) == 0) {
1180 error = EPERM; 1188 error = EPERM;
1181 DPRINTF("no force %d", error); 1189 DPRINTF("no force %d", error);
1182 goto out; 1190 goto out;
1183 } 1191 }
1184#endif /* !WAPBL */ 1192#endif /* !WAPBL */
1185 1193
1186 ffs_oldfscompat_read(fs, ump, sblockloc); 1194 ffs_oldfscompat_read(fs, ump, sblockloc);
1187 ump->um_maxfilesize = fs->fs_maxfilesize; 1195 ump->um_maxfilesize = fs->fs_maxfilesize;
1188 1196
1189 if (fs->fs_flags & ~(FS_KNOWN_FLAGS | FS_INTERNAL)) { 1197 if (fs->fs_flags & ~(FS_KNOWN_FLAGS | FS_INTERNAL)) {
1190 uprintf("%s: unknown ufs flags: 0x%08"PRIx32"%s\n", 1198 uprintf("%s: unknown ufs flags: 0x%08"PRIx32"%s\n",
1191 mp->mnt_stat.f_mntonname, fs->fs_flags, 1199 mp->mnt_stat.f_mntonname, fs->fs_flags,
1192 (mp->mnt_flag & MNT_FORCE) ? "" : ", not mounting"); 1200 (mp->mnt_flag & MNT_FORCE) ? "" : ", not mounting");
1193 if ((mp->mnt_flag & MNT_FORCE) == 0) { 1201 if ((mp->mnt_flag & MNT_FORCE) == 0) {
1194 error = EINVAL; 1202 error = EINVAL;
1195 DPRINTF("no force %d", error); 1203 DPRINTF("no force %d", error);
1196 goto out; 1204 goto out;
1197 } 1205 }
1198 } 1206 }
1199 1207
1200 if (fs->fs_pendingblocks != 0 || fs->fs_pendinginodes != 0) { 1208 if (fs->fs_pendingblocks != 0 || fs->fs_pendinginodes != 0) {
1201 fs->fs_pendingblocks = 0; 1209 fs->fs_pendingblocks = 0;
1202 fs->fs_pendinginodes = 0; 1210 fs->fs_pendinginodes = 0;
1203 } 1211 }
1204 1212
1205 ump->um_fstype = fstype; 1213 ump->um_fstype = fstype;
1206 if (fs->fs_sbsize < SBLOCKSIZE) 1214 if (fs->fs_sbsize < SBLOCKSIZE)
1207 brelse(bp, BC_INVAL); 1215 brelse(bp, BC_INVAL);
1208 else 1216 else
1209 brelse(bp, 0); 1217 brelse(bp, 0);
1210 bp = NULL; 1218 bp = NULL;
1211 1219
1212 /* 1220 /*
1213 * First check to see if this is tagged as an Apple UFS filesystem 1221 * First check to see if this is tagged as an Apple UFS filesystem
1214 * in the disklabel 1222 * in the disklabel
1215 */ 1223 */
1216 if (getdiskinfo(devvp, &dkw) == 0 && 1224 if (getdiskinfo(devvp, &dkw) == 0 &&
1217 strcmp(dkw.dkw_ptype, DKW_PTYPE_APPLEUFS) == 0) 1225 strcmp(dkw.dkw_ptype, DKW_PTYPE_APPLEUFS) == 0)
1218 ump->um_flags |= UFS_ISAPPLEUFS; 1226 ump->um_flags |= UFS_ISAPPLEUFS;
1219#ifdef APPLE_UFS 1227#ifdef APPLE_UFS
1220 else { 1228 else {
1221 /* 1229 /*
1222 * Manually look for an apple ufs label, and if a valid one 1230 * Manually look for an apple ufs label, and if a valid one
1223 * is found, then treat it like an Apple UFS filesystem anyway 1231 * is found, then treat it like an Apple UFS filesystem anyway
1224 */ 1232 */
1225 error = bread(devvp, 1233 error = bread(devvp,
1226 (daddr_t)(APPLEUFS_LABEL_OFFSET / DEV_BSIZE), 1234 (daddr_t)(APPLEUFS_LABEL_OFFSET / DEV_BSIZE),
1227 APPLEUFS_LABEL_SIZE, cred, 0, &bp); 1235 APPLEUFS_LABEL_SIZE, cred, 0, &bp);
1228 if (error) { 1236 if (error) {
1229 DPRINTF("apple bread@0x%jx returned %d", 1237 DPRINTF("apple bread@0x%jx returned %d",
1230 (intmax_t)(APPLEUFS_LABEL_OFFSET / DEV_BSIZE), 1238 (intmax_t)(APPLEUFS_LABEL_OFFSET / DEV_BSIZE),
1231 error); 1239 error);
1232 goto out; 1240 goto out;
1233 } 1241 }
1234 error = ffs_appleufs_validate(fs->fs_fsmnt, 1242 error = ffs_appleufs_validate(fs->fs_fsmnt,
1235 (struct appleufslabel *)bp->b_data, NULL); 1243 (struct appleufslabel *)bp->b_data, NULL);
1236 if (error == 0) 1244 if (error == 0)
1237 ump->um_flags |= UFS_ISAPPLEUFS; 1245 ump->um_flags |= UFS_ISAPPLEUFS;
1238 brelse(bp, 0); 1246 brelse(bp, 0);
1239 bp = NULL; 1247 bp = NULL;
1240 } 1248 }
1241#else 1249#else
1242 if (ump->um_flags & UFS_ISAPPLEUFS) { 1250 if (ump->um_flags & UFS_ISAPPLEUFS) {
1243 DPRINTF("AppleUFS not supported"); 1251 DPRINTF("AppleUFS not supported");
1244 error = EINVAL; 1252 error = EINVAL;
1245 goto out; 1253 goto out;
1246 } 1254 }
1247#endif 1255#endif
1248 1256
1249#if 0 1257#if 0
1250/* 1258/*
1251 * XXX This code changes the behaviour of mounting dirty filesystems, to 1259 * XXX This code changes the behaviour of mounting dirty filesystems, to
1252 * XXX require "mount -f ..." to mount them. This doesn't match what 1260 * XXX require "mount -f ..." to mount them. This doesn't match what
1253 * XXX mount(8) describes and is disabled for now. 1261 * XXX mount(8) describes and is disabled for now.
1254 */ 1262 */
1255 /* 1263 /*
1256 * If the file system is not clean, don't allow it to be mounted 1264 * If the file system is not clean, don't allow it to be mounted
1257 * unless MNT_FORCE is specified. (Note: MNT_FORCE is always set 1265 * unless MNT_FORCE is specified. (Note: MNT_FORCE is always set
1258 * for the root file system.) 1266 * for the root file system.)
1259 */ 1267 */
1260 if (fs->fs_flags & FS_DOWAPBL) { 1268 if (fs->fs_flags & FS_DOWAPBL) {
1261 /* 1269 /*
1262 * wapbl normally expects to be FS_WASCLEAN when the FS_DOWAPBL 1270 * wapbl normally expects to be FS_WASCLEAN when the FS_DOWAPBL
1263 * bit is set, although there's a window in unmount where it 1271 * bit is set, although there's a window in unmount where it
1264 * could be FS_ISCLEAN 1272 * could be FS_ISCLEAN
1265 */ 1273 */
1266 if ((mp->mnt_flag & MNT_FORCE) == 0 && 1274 if ((mp->mnt_flag & MNT_FORCE) == 0 &&
1267 (fs->fs_clean & (FS_WASCLEAN | FS_ISCLEAN)) == 0) { 1275 (fs->fs_clean & (FS_WASCLEAN | FS_ISCLEAN)) == 0) {
1268 error = EPERM; 1276 error = EPERM;
1269 goto out; 1277 goto out;
1270 } 1278 }
1271 } else 1279 } else
1272 if ((fs->fs_clean & FS_ISCLEAN) == 0 && 1280 if ((fs->fs_clean & FS_ISCLEAN) == 0 &&
1273 (mp->mnt_flag & MNT_FORCE) == 0) { 1281 (mp->mnt_flag & MNT_FORCE) == 0) {
1274 error = EPERM; 1282 error = EPERM;
1275 goto out; 1283 goto out;
1276 } 1284 }
1277#endif 1285#endif
1278 1286
1279 /* 1287 /*
1280 * Verify that we can access the last block in the fs 1288 * Verify that we can access the last block in the fs
1281 * if we're mounting read/write. 1289 * if we're mounting read/write.
1282 */ 1290 */
1283 if (!ronly) { 1291 if (!ronly) {
1284 error = bread(devvp, FFS_FSBTODB(fs, fs->fs_size - 1), 1292 error = bread(devvp, FFS_FSBTODB(fs, fs->fs_size - 1),
1285 fs->fs_fsize, cred, 0, &bp); 1293 fs->fs_fsize, cred, 0, &bp);
1286 if (error) { 1294 if (error) {
1287 DPRINTF("bread@0x%jx returned %d", 1295 DPRINTF("bread@0x%jx returned %d",
1288 (intmax_t)FFS_FSBTODB(fs, fs->fs_size - 1), 1296 (intmax_t)FFS_FSBTODB(fs, fs->fs_size - 1),
1289 error); 1297 error);
1290 bset = BC_INVAL; 1298 bset = BC_INVAL;
1291 goto out; 1299 goto out;
1292 } 1300 }
1293 if (bp->b_bcount != fs->fs_fsize) { 1301 if (bp->b_bcount != fs->fs_fsize) {
1294 DPRINTF("bcount %x != fsize %x", bp->b_bcount, 1302 DPRINTF("bcount %x != fsize %x", bp->b_bcount,
1295 fs->fs_fsize); 1303 fs->fs_fsize);
1296 error = EINVAL; 1304 error = EINVAL;
1297 } 1305 }
1298 brelse(bp, BC_INVAL); 1306 brelse(bp, BC_INVAL);
1299 bp = NULL; 1307 bp = NULL;
1300 } 1308 }
1301 1309
1302 fs->fs_ronly = ronly; 1310 fs->fs_ronly = ronly;
1303 /* Don't bump fs_clean if we're replaying journal */ 1311 /* Don't bump fs_clean if we're replaying journal */
1304 if (!((fs->fs_flags & FS_DOWAPBL) && (fs->fs_clean & FS_WASCLEAN))) { 1312 if (!((fs->fs_flags & FS_DOWAPBL) && (fs->fs_clean & FS_WASCLEAN))) {
1305 if (ronly == 0) { 1313 if (ronly == 0) {
1306 fs->fs_clean <<= 1; 1314 fs->fs_clean <<= 1;
1307 fs->fs_fmod = 1; 1315 fs->fs_fmod = 1;
1308 } 1316 }
1309 } 1317 }
1310 1318
1311 bsize = fs->fs_cssize; 1319 bsize = fs->fs_cssize;
1312 blks = howmany(bsize, fs->fs_fsize); 1320 blks = howmany(bsize, fs->fs_fsize);
1313 if (fs->fs_contigsumsize > 0) 1321 if (fs->fs_contigsumsize > 0)
1314 bsize += fs->fs_ncg * sizeof(int32_t); 1322 bsize += fs->fs_ncg * sizeof(int32_t);
1315 bsize += fs->fs_ncg * sizeof(*fs->fs_contigdirs); 1323 bsize += fs->fs_ncg * sizeof(*fs->fs_contigdirs);
1316 allocsbsize = bsize; 1324 allocsbsize = bsize;
1317 space = kmem_alloc((u_long)allocsbsize, KM_SLEEP); 1325 space = kmem_alloc((u_long)allocsbsize, KM_SLEEP);
1318 fs->fs_csp = space; 1326 fs->fs_csp = space;
1319 1327
1320 for (i = 0; i < blks; i += fs->fs_frag) { 1328 for (i = 0; i < blks; i += fs->fs_frag) {
1321 bsize = fs->fs_bsize; 1329 bsize = fs->fs_bsize;
1322 if (i + fs->fs_frag > blks) 1330 if (i + fs->fs_frag > blks)
1323 bsize = (blks - i) * fs->fs_fsize; 1331 bsize = (blks - i) * fs->fs_fsize;
1324 error = bread(devvp, FFS_FSBTODB(fs, fs->fs_csaddr + i), bsize, 1332 error = bread(devvp, FFS_FSBTODB(fs, fs->fs_csaddr + i), bsize,
1325 cred, 0, &bp); 1333 cred, 0, &bp);
1326 if (error) { 1334 if (error) {
1327 DPRINTF("bread@0x%jx %d", 1335 DPRINTF("bread@0x%jx %d",
1328 (intmax_t)FFS_FSBTODB(fs, fs->fs_csaddr + i), 1336 (intmax_t)FFS_FSBTODB(fs, fs->fs_csaddr + i),
1329 error); 1337 error);
1330 goto out1; 1338 goto out1;
1331 } 1339 }
1332#ifdef FFS_EI 1340#ifdef FFS_EI
1333 if (needswap) 1341 if (needswap)
1334 ffs_csum_swap((struct csum *)bp->b_data, 1342 ffs_csum_swap((struct csum *)bp->b_data,
1335 (struct csum *)space, bsize); 1343 (struct csum *)space, bsize);
1336 else 1344 else
1337#endif 1345#endif
1338 memcpy(space, bp->b_data, (u_int)bsize); 1346 memcpy(space, bp->b_data, (u_int)bsize);
1339 1347
1340 space = (char *)space + bsize; 1348 space = (char *)space + bsize;
1341 brelse(bp, 0); 1349 brelse(bp, 0);
1342 bp = NULL; 1350 bp = NULL;
1343 } 1351 }
1344 if (fs->fs_contigsumsize > 0) { 1352 if (fs->fs_contigsumsize > 0) {
1345 fs->fs_maxcluster = lp = space; 1353 fs->fs_maxcluster = lp = space;
1346 for (i = 0; i < fs->fs_ncg; i++) 1354 for (i = 0; i < fs->fs_ncg; i++)
1347 *lp++ = fs->fs_contigsumsize; 1355 *lp++ = fs->fs_contigsumsize;
1348 space = lp; 1356 space = lp;
1349 } 1357 }
1350 bsize = fs->fs_ncg * sizeof(*fs->fs_contigdirs); 1358 bsize = fs->fs_ncg * sizeof(*fs->fs_contigdirs);
1351 fs->fs_contigdirs = space; 1359 fs->fs_contigdirs = space;
1352 space = (char *)space + bsize; 1360 space = (char *)space + bsize;
1353 memset(fs->fs_contigdirs, 0, bsize); 1361 memset(fs->fs_contigdirs, 0, bsize);
1354 1362
1355 /* Compatibility for old filesystems - XXX */ 1363 /* Compatibility for old filesystems - XXX */
1356 if (fs->fs_avgfilesize <= 0) 1364 if (fs->fs_avgfilesize <= 0)
1357 fs->fs_avgfilesize = AVFILESIZ; 1365 fs->fs_avgfilesize = AVFILESIZ;
1358 if (fs->fs_avgfpdir <= 0) 1366 if (fs->fs_avgfpdir <= 0)
1359 fs->fs_avgfpdir = AFPDIR; 1367 fs->fs_avgfpdir = AFPDIR;
1360 fs->fs_active = NULL; 1368 fs->fs_active = NULL;
1361 1369
1362 mp->mnt_data = ump; 1370 mp->mnt_data = ump;
1363 mp->mnt_stat.f_fsidx.__fsid_val[0] = (long)dev; 1371 mp->mnt_stat.f_fsidx.__fsid_val[0] = (long)dev;
1364 mp->mnt_stat.f_fsidx.__fsid_val[1] = makefstype(MOUNT_FFS); 1372 mp->mnt_stat.f_fsidx.__fsid_val[1] = makefstype(MOUNT_FFS);
1365 mp->mnt_stat.f_fsid = mp->mnt_stat.f_fsidx.__fsid_val[0]; 1373 mp->mnt_stat.f_fsid = mp->mnt_stat.f_fsidx.__fsid_val[0];
1366 mp->mnt_stat.f_namemax = FFS_MAXNAMLEN; 1374 mp->mnt_stat.f_namemax = FFS_MAXNAMLEN;
1367 if (UFS_MPISAPPLEUFS(ump)) { 1375 if (UFS_MPISAPPLEUFS(ump)) {
1368 /* NeXT used to keep short symlinks in the inode even 1376 /* NeXT used to keep short symlinks in the inode even
1369 * when using FS_42INODEFMT. In that case fs->fs_maxsymlinklen 1377 * when using FS_42INODEFMT. In that case fs->fs_maxsymlinklen
1370 * is probably -1, but we still need to be able to identify 1378 * is probably -1, but we still need to be able to identify
1371 * short symlinks. 1379 * short symlinks.
1372 */ 1380 */
1373 ump->um_maxsymlinklen = APPLEUFS_MAXSYMLINKLEN; 1381 ump->um_maxsymlinklen = APPLEUFS_MAXSYMLINKLEN;
1374 ump->um_dirblksiz = APPLEUFS_DIRBLKSIZ; 1382 ump->um_dirblksiz = APPLEUFS_DIRBLKSIZ;
1375 mp->mnt_iflag |= IMNT_DTYPE; 1383 mp->mnt_iflag |= IMNT_DTYPE;
1376 } else { 1384 } else {
1377 ump->um_maxsymlinklen = fs->fs_maxsymlinklen; 1385 ump->um_maxsymlinklen = fs->fs_maxsymlinklen;
1378 ump->um_dirblksiz = UFS_DIRBLKSIZ; 1386 ump->um_dirblksiz = UFS_DIRBLKSIZ;
1379 if (ump->um_maxsymlinklen > 0) 1387 if (ump->um_maxsymlinklen > 0)
1380 mp->mnt_iflag |= IMNT_DTYPE; 1388 mp->mnt_iflag |= IMNT_DTYPE;
1381 else 1389 else
1382 mp->mnt_iflag &= ~IMNT_DTYPE; 1390 mp->mnt_iflag &= ~IMNT_DTYPE;
1383 } 1391 }
1384 mp->mnt_fs_bshift = fs->fs_bshift; 1392 mp->mnt_fs_bshift = fs->fs_bshift;
1385 mp->mnt_dev_bshift = DEV_BSHIFT; /* XXX */ 1393 mp->mnt_dev_bshift = DEV_BSHIFT; /* XXX */
1386 mp->mnt_flag |= MNT_LOCAL; 1394 mp->mnt_flag |= MNT_LOCAL;
1387 mp->mnt_iflag |= IMNT_MPSAFE; 1395 mp->mnt_iflag |= IMNT_MPSAFE;
1388#ifdef FFS_EI 1396#ifdef FFS_EI
1389 if (needswap) 1397 if (needswap)
1390 ump->um_flags |= UFS_NEEDSWAP; 1398 ump->um_flags |= UFS_NEEDSWAP;
1391#endif 1399#endif
1392 ump->um_mountp = mp; 1400 ump->um_mountp = mp;
1393 ump->um_dev = dev; 1401 ump->um_dev = dev;
1394 ump->um_devvp = devvp; 1402 ump->um_devvp = devvp;
1395 ump->um_nindir = fs->fs_nindir; 1403 ump->um_nindir = fs->fs_nindir;
1396 ump->um_lognindir = ffs(fs->fs_nindir) - 1; 1404 ump->um_lognindir = ffs(fs->fs_nindir) - 1;
1397 ump->um_bptrtodb = fs->fs_fshift - DEV_BSHIFT; 1405 ump->um_bptrtodb = fs->fs_fshift - DEV_BSHIFT;
1398 ump->um_seqinc = fs->fs_frag; 1406 ump->um_seqinc = fs->fs_frag;
1399 for (i = 0; i < MAXQUOTAS; i++) 1407 for (i = 0; i < MAXQUOTAS; i++)
1400 ump->um_quotas[i] = NULLVP; 1408 ump->um_quotas[i] = NULLVP;
1401 spec_node_setmountedfs(devvp, mp); 1409 spec_node_setmountedfs(devvp, mp);
1402 if (ronly == 0 && fs->fs_snapinum[0] != 0) 1410 if (ronly == 0 && fs->fs_snapinum[0] != 0)
1403 ffs_snapshot_mount(mp); 1411 ffs_snapshot_mount(mp);
1404#ifdef WAPBL 1412#ifdef WAPBL
1405 if (!ronly) { 1413 if (!ronly) {
1406 KDASSERT(fs->fs_ronly == 0); 1414 KDASSERT(fs->fs_ronly == 0);
1407 /* 1415 /*
1408 * ffs_wapbl_start() needs mp->mnt_stat initialised if it 1416 * ffs_wapbl_start() needs mp->mnt_stat initialised if it
1409 * needs to create a new log file in-filesystem. 1417 * needs to create a new log file in-filesystem.
1410 */ 1418 */
1411 error = ffs_statvfs(mp, &mp->mnt_stat); 1419 error = ffs_statvfs(mp, &mp->mnt_stat);
1412 if (error) { 1420 if (error) {
1413 DPRINTF("ffs_statvfs returned %d", error); 1421 DPRINTF("ffs_statvfs returned %d", error);
1414 goto out1; 1422 goto out1;
1415 } 1423 }
1416 1424
1417 error = ffs_wapbl_start(mp); 1425 error = ffs_wapbl_start(mp);
1418 if (error) { 1426 if (error) {
1419 DPRINTF("ffs_wapbl_start returned %d", error); 1427 DPRINTF("ffs_wapbl_start returned %d", error);
1420 goto out1; 1428 goto out1;
1421 } 1429 }
1422 } 1430 }
1423#endif /* WAPBL */ 1431#endif /* WAPBL */
1424 if (ronly == 0) { 1432 if (ronly == 0) {
1425#ifdef QUOTA2 1433#ifdef QUOTA2
1426 error = ffs_quota2_mount(mp); 1434 error = ffs_quota2_mount(mp);
1427 if (error) { 1435 if (error) {
1428 DPRINTF("ffs_quota2_mount returned %d", error); 1436 DPRINTF("ffs_quota2_mount returned %d", error);
1429 goto out1; 1437 goto out1;
1430 } 1438 }
1431#else 1439#else
1432 if (fs->fs_flags & FS_DOQUOTA2) { 1440 if (fs->fs_flags & FS_DOQUOTA2) {
1433 ump->um_flags |= UFS_QUOTA2; 1441 ump->um_flags |= UFS_QUOTA2;
1434 uprintf("%s: options QUOTA2 not enabled%s\n", 1442 uprintf("%s: options QUOTA2 not enabled%s\n",
1435 mp->mnt_stat.f_mntonname, 1443 mp->mnt_stat.f_mntonname,
1436 (mp->mnt_flag & MNT_FORCE) ? "" : ", not mounting"); 1444 (mp->mnt_flag & MNT_FORCE) ? "" : ", not mounting");
1437 if ((mp->mnt_flag & MNT_FORCE) == 0) { 1445 if ((mp->mnt_flag & MNT_FORCE) == 0) {
1438 error = EINVAL; 1446 error = EINVAL;
1439 DPRINTF("quota disabled %d", error); 1447 DPRINTF("quota disabled %d", error);
1440 goto out1; 1448 goto out1;
1441 } 1449 }
1442 } 1450 }
1443#endif 1451#endif
1444 } 1452 }
1445 1453
1446 if (mp->mnt_flag & MNT_DISCARD) 1454 if (mp->mnt_flag & MNT_DISCARD)
1447 ump->um_discarddata = ffs_discard_init(devvp, fs); 1455 ump->um_discarddata = ffs_discard_init(devvp, fs);
1448 1456
1449 return (0); 1457 return (0);
1450out1: 1458out1:
1451 kmem_free(fs->fs_csp, allocsbsize); 1459 kmem_free(fs->fs_csp, allocsbsize);
1452out: 1460out:
1453#ifdef WAPBL 1461#ifdef WAPBL
1454 if (mp->mnt_wapbl_replay) { 1462 if (mp->mnt_wapbl_replay) {
1455 wapbl_replay_stop(mp->mnt_wapbl_replay); 1463 wapbl_replay_stop(mp->mnt_wapbl_replay);
1456 wapbl_replay_free(mp->mnt_wapbl_replay); 1464 wapbl_replay_free(mp->mnt_wapbl_replay);
1457 mp->mnt_wapbl_replay = 0; 1465 mp->mnt_wapbl_replay = 0;
1458 } 1466 }
1459#endif 1467#endif
1460 1468
1461 fstrans_unmount(mp); 1469 fstrans_unmount(mp);
1462 if (fs) 1470 if (fs)
1463 kmem_free(fs, fs->fs_sbsize); 1471 kmem_free(fs, fs->fs_sbsize);
1464 spec_node_setmountedfs(devvp, NULL); 1472 spec_node_setmountedfs(devvp, NULL);
1465 if (bp) 1473 if (bp)
1466 brelse(bp, bset); 1474 brelse(bp, bset);
1467 if (ump) { 1475 if (ump) {
1468 if (ump->um_oldfscompat) 1476 if (ump->um_oldfscompat)
1469 kmem_free(ump->um_oldfscompat, 512 + 3*sizeof(int32_t)); 1477 kmem_free(ump->um_oldfscompat, 512 + 3*sizeof(int32_t));
1470 mutex_destroy(&ump->um_lock); 1478 mutex_destroy(&ump->um_lock);
1471 kmem_free(ump, sizeof(*ump)); 1479 kmem_free(ump, sizeof(*ump));
1472 mp->mnt_data = NULL; 1480 mp->mnt_data = NULL;
1473 } 1481 }
1474 return (error); 1482 return (error);
1475} 1483}
1476 1484
1477/* 1485/*
1478 * Sanity checks for loading old filesystem superblocks. 1486 * Sanity checks for loading old filesystem superblocks.
1479 * See ffs_oldfscompat_write below for unwound actions. 1487 * See ffs_oldfscompat_write below for unwound actions.
1480 * 1488 *
1481 * XXX - Parts get retired eventually. 1489 * XXX - Parts get retired eventually.
1482 * Unfortunately new bits get added. 1490 * Unfortunately new bits get added.
1483 */ 1491 */
1484static void 1492static void
1485ffs_oldfscompat_read(struct fs *fs, struct ufsmount *ump, daddr_t sblockloc) 1493ffs_oldfscompat_read(struct fs *fs, struct ufsmount *ump, daddr_t sblockloc)
1486{ 1494{
1487 off_t maxfilesize; 1495 off_t maxfilesize;
1488 int32_t *extrasave; 1496 int32_t *extrasave;
1489 1497
1490 if ((fs->fs_magic != FS_UFS1_MAGIC) || 1498 if ((fs->fs_magic != FS_UFS1_MAGIC) ||
1491 (fs->fs_old_flags & FS_FLAGS_UPDATED)) 1499 (fs->fs_old_flags & FS_FLAGS_UPDATED))
1492 return; 1500 return;
1493 1501
1494 if (!ump->um_oldfscompat) 1502 if (!ump->um_oldfscompat)
1495 ump->um_oldfscompat = kmem_alloc(512 + 3*sizeof(int32_t), 1503 ump->um_oldfscompat = kmem_alloc(512 + 3*sizeof(int32_t),
1496 KM_SLEEP); 1504 KM_SLEEP);
1497 1505
1498 memcpy(ump->um_oldfscompat, &fs->fs_old_postbl_start, 512); 1506 memcpy(ump->um_oldfscompat, &fs->fs_old_postbl_start, 512);
1499 extrasave = ump->um_oldfscompat; 1507 extrasave = ump->um_oldfscompat;
1500 extrasave += 512/sizeof(int32_t); 1508 extrasave += 512/sizeof(int32_t);
1501 extrasave[0] = fs->fs_old_npsect; 1509 extrasave[0] = fs->fs_old_npsect;
1502 extrasave[1] = fs->fs_old_interleave; 1510 extrasave[1] = fs->fs_old_interleave;
1503 extrasave[2] = fs->fs_old_trackskew; 1511 extrasave[2] = fs->fs_old_trackskew;
1504 1512
1505 /* These fields will be overwritten by their 1513 /* These fields will be overwritten by their
1506 * original values in fs_oldfscompat_write, so it is harmless 1514 * original values in fs_oldfscompat_write, so it is harmless
1507 * to modify them here. 1515 * to modify them here.
1508 */ 1516 */
1509 fs->fs_cstotal.cs_ndir = fs->fs_old_cstotal.cs_ndir; 1517 fs->fs_cstotal.cs_ndir = fs->fs_old_cstotal.cs_ndir;
1510 fs->fs_cstotal.cs_nbfree = fs->fs_old_cstotal.cs_nbfree; 1518 fs->fs_cstotal.cs_nbfree = fs->fs_old_cstotal.cs_nbfree;
1511 fs->fs_cstotal.cs_nifree = fs->fs_old_cstotal.cs_nifree; 1519 fs->fs_cstotal.cs_nifree = fs->fs_old_cstotal.cs_nifree;
1512 fs->fs_cstotal.cs_nffree = fs->fs_old_cstotal.cs_nffree; 1520 fs->fs_cstotal.cs_nffree = fs->fs_old_cstotal.cs_nffree;
1513 1521
1514 fs->fs_maxbsize = fs->fs_bsize; 1522 fs->fs_maxbsize = fs->fs_bsize;
1515 fs->fs_time = fs->fs_old_time; 1523 fs->fs_time = fs->fs_old_time;
1516 fs->fs_size = fs->fs_old_size; 1524 fs->fs_size = fs->fs_old_size;
1517 fs->fs_dsize = fs->fs_old_dsize; 1525 fs->fs_dsize = fs->fs_old_dsize;
1518 fs->fs_csaddr = fs->fs_old_csaddr; 1526 fs->fs_csaddr = fs->fs_old_csaddr;
1519 fs->fs_sblockloc = sblockloc; 1527 fs->fs_sblockloc = sblockloc;
1520 1528
1521 fs->fs_flags = fs->fs_old_flags | (fs->fs_flags & FS_INTERNAL); 1529 fs->fs_flags = fs->fs_old_flags | (fs->fs_flags & FS_INTERNAL);
1522 1530
1523 if (fs->fs_old_postblformat == FS_42POSTBLFMT) { 1531 if (fs->fs_old_postblformat == FS_42POSTBLFMT) {
1524 fs->fs_old_nrpos = 8; 1532 fs->fs_old_nrpos = 8;
1525 fs->fs_old_npsect = fs->fs_old_nsect; 1533 fs->fs_old_npsect = fs->fs_old_nsect;
1526 fs->fs_old_interleave = 1; 1534 fs->fs_old_interleave = 1;
1527 fs->fs_old_trackskew = 0; 1535 fs->fs_old_trackskew = 0;
1528 } 1536 }
1529 1537
1530 if (fs->fs_old_inodefmt < FS_44INODEFMT) { 1538 if (fs->fs_old_inodefmt < FS_44INODEFMT) {
1531 fs->fs_maxfilesize = (u_quad_t) 1LL << 39; 1539 fs->fs_maxfilesize = (u_quad_t) 1LL << 39;
1532 fs->fs_qbmask = ~fs->fs_bmask; 1540 fs->fs_qbmask = ~fs->fs_bmask;
1533 fs->fs_qfmask = ~fs->fs_fmask; 1541 fs->fs_qfmask = ~fs->fs_fmask;
1534 } 1542 }
1535 1543
1536 maxfilesize = (u_int64_t)0x80000000 * fs->fs_bsize - 1; 1544 maxfilesize = (u_int64_t)0x80000000 * fs->fs_bsize - 1;
1537 if (fs->fs_maxfilesize > maxfilesize) 1545 if (fs->fs_maxfilesize > maxfilesize)
1538 fs->fs_maxfilesize = maxfilesize; 1546 fs->fs_maxfilesize = maxfilesize;
1539 1547
1540 /* Compatibility for old filesystems */ 1548 /* Compatibility for old filesystems */
1541 if (fs->fs_avgfilesize <= 0) 1549 if (fs->fs_avgfilesize <= 0)
1542 fs->fs_avgfilesize = AVFILESIZ; 1550 fs->fs_avgfilesize = AVFILESIZ;
1543 if (fs->fs_avgfpdir <= 0) 1551 if (fs->fs_avgfpdir <= 0)
1544 fs->fs_avgfpdir = AFPDIR; 1552 fs->fs_avgfpdir = AFPDIR;
1545 1553
1546#if 0 1554#if 0
1547 if (bigcgs) { 1555 if (bigcgs) {
1548 fs->fs_save_cgsize = fs->fs_cgsize; 1556 fs->fs_save_cgsize = fs->fs_cgsize;
1549 fs->fs_cgsize = fs->fs_bsize; 1557 fs->fs_cgsize = fs->fs_bsize;
1550 } 1558 }
1551#endif 1559#endif
1552} 1560}
1553 1561
1554/* 1562/*
1555 * Unwinding superblock updates for old filesystems. 1563 * Unwinding superblock updates for old filesystems.
1556 * See ffs_oldfscompat_read above for details. 1564 * See ffs_oldfscompat_read above for details.
1557 * 1565 *
1558 * XXX - Parts get retired eventually. 1566 * XXX - Parts get retired eventually.
1559 * Unfortunately new bits get added. 1567 * Unfortunately new bits get added.
1560 */ 1568 */
1561static void 1569static void
1562ffs_oldfscompat_write(struct fs *fs, struct ufsmount *ump) 1570ffs_oldfscompat_write(struct fs *fs, struct ufsmount *ump)
1563{ 1571{
1564 int32_t *extrasave; 1572 int32_t *extrasave;
1565 1573
1566 if ((fs->fs_magic != FS_UFS1_MAGIC) || 1574 if ((fs->fs_magic != FS_UFS1_MAGIC) ||
1567 (fs->fs_old_flags & FS_FLAGS_UPDATED)) 1575 (fs->fs_old_flags & FS_FLAGS_UPDATED))
1568 return; 1576 return;
1569 1577
1570 fs->fs_old_time = fs->fs_time; 1578 fs->fs_old_time = fs->fs_time;
1571 fs->fs_old_cstotal.cs_ndir = fs->fs_cstotal.cs_ndir; 1579 fs->fs_old_cstotal.cs_ndir = fs->fs_cstotal.cs_ndir;
1572 fs->fs_old_cstotal.cs_nbfree = fs->fs_cstotal.cs_nbfree; 1580 fs->fs_old_cstotal.cs_nbfree = fs->fs_cstotal.cs_nbfree;
1573 fs->fs_old_cstotal.cs_nifree = fs->fs_cstotal.cs_nifree; 1581 fs->fs_old_cstotal.cs_nifree = fs->fs_cstotal.cs_nifree;
1574 fs->fs_old_cstotal.cs_nffree = fs->fs_cstotal.cs_nffree; 1582 fs->fs_old_cstotal.cs_nffree = fs->fs_cstotal.cs_nffree;
1575 fs->fs_old_flags = fs->fs_flags; 1583 fs->fs_old_flags = fs->fs_flags;
1576 1584
1577#if 0 1585#if 0
1578 if (bigcgs) { 1586 if (bigcgs) {
1579 fs->fs_cgsize = fs->fs_save_cgsize; 1587 fs->fs_cgsize = fs->fs_save_cgsize;
1580 } 1588 }
1581#endif 1589#endif
1582 1590
1583 memcpy(&fs->fs_old_postbl_start, ump->um_oldfscompat, 512); 1591 memcpy(&fs->fs_old_postbl_start, ump->um_oldfscompat, 512);
1584 extrasave = ump->um_oldfscompat; 1592 extrasave = ump->um_oldfscompat;
1585 extrasave += 512/sizeof(int32_t); 1593 extrasave += 512/sizeof(int32_t);
1586 fs->fs_old_npsect = extrasave[0]; 1594 fs->fs_old_npsect = extrasave[0];
1587 fs->fs_old_interleave = extrasave[1]; 1595 fs->fs_old_interleave = extrasave[1];
1588 fs->fs_old_trackskew = extrasave[2]; 1596 fs->fs_old_trackskew = extrasave[2];
1589 1597
1590} 1598}
1591 1599
1592/* 1600/*
1593 * unmount vfs operation 1601 * unmount vfs operation
1594 */ 1602 */
1595int 1603int
1596ffs_unmount(struct mount *mp, int mntflags) 1604ffs_unmount(struct mount *mp, int mntflags)
1597{ 1605{
1598 struct lwp *l = curlwp; 1606 struct lwp *l = curlwp;
1599 struct ufsmount *ump = VFSTOUFS(mp); 1607 struct ufsmount *ump = VFSTOUFS(mp);
1600 struct fs *fs = ump->um_fs; 1608 struct fs *fs = ump->um_fs;
1601 int error, flags; 1609 int error, flags;
1602 u_int32_t bsize; 1610 u_int32_t bsize;
1603#ifdef WAPBL 1611#ifdef WAPBL
1604 extern int doforce; 1612 extern int doforce;
1605#endif 1613#endif
1606 1614
1607 if (ump->um_discarddata) { 1615 if (ump->um_discarddata) {
1608 ffs_discard_finish(ump->um_discarddata, mntflags); 1616 ffs_discard_finish(ump->um_discarddata, mntflags);
1609 ump->um_discarddata = NULL; 1617 ump->um_discarddata = NULL;
1610 } 1618 }
1611 1619
1612 flags = 0; 1620 flags = 0;
1613 if (mntflags & MNT_FORCE) 1621 if (mntflags & MNT_FORCE)
1614 flags |= FORCECLOSE; 1622 flags |= FORCECLOSE;
1615 if ((error = ffs_flushfiles(mp, flags, l)) != 0) 1623 if ((error = ffs_flushfiles(mp, flags, l)) != 0)
1616 return (error); 1624 return (error);
1617 error = UFS_WAPBL_BEGIN(mp); 1625 error = UFS_WAPBL_BEGIN(mp);
1618 if (error == 0) 1626 if (error == 0)
1619 if (fs->fs_ronly == 0 && 1627 if (fs->fs_ronly == 0 &&
1620 ffs_cgupdate(ump, MNT_WAIT) == 0 && 1628 ffs_cgupdate(ump, MNT_WAIT) == 0 &&
1621 fs->fs_clean & FS_WASCLEAN) { 1629 fs->fs_clean & FS_WASCLEAN) {
1622 fs->fs_clean = FS_ISCLEAN; 1630 fs->fs_clean = FS_ISCLEAN;
1623 fs->fs_fmod = 0; 1631 fs->fs_fmod = 0;
1624 (void) ffs_sbupdate(ump, MNT_WAIT); 1632 (void) ffs_sbupdate(ump, MNT_WAIT);
1625 } 1633 }
1626 if (error == 0) 1634 if (error == 0)
1627 UFS_WAPBL_END(mp); 1635 UFS_WAPBL_END(mp);
1628#ifdef WAPBL 1636#ifdef WAPBL
1629 KASSERT(!(mp->mnt_wapbl_replay && mp->mnt_wapbl)); 1637 KASSERT(!(mp->mnt_wapbl_replay && mp->mnt_wapbl));
1630 if (mp->mnt_wapbl_replay) { 1638 if (mp->mnt_wapbl_replay) {
1631 KDASSERT(fs->fs_ronly); 1639 KDASSERT(fs->fs_ronly);
1632 wapbl_replay_stop(mp->mnt_wapbl_replay); 1640 wapbl_replay_stop(mp->mnt_wapbl_replay);
1633 wapbl_replay_free(mp->mnt_wapbl_replay); 1641 wapbl_replay_free(mp->mnt_wapbl_replay);
1634 mp->mnt_wapbl_replay = 0; 1642 mp->mnt_wapbl_replay = 0;
1635 } 1643 }
1636 error = ffs_wapbl_stop(mp, doforce && (mntflags & MNT_FORCE)); 1644 error = ffs_wapbl_stop(mp, doforce && (mntflags & MNT_FORCE));
1637 if (error) { 1645 if (error) {
1638 return error; 1646 return error;
1639 } 1647 }
1640#endif /* WAPBL */ 1648#endif /* WAPBL */
1641 1649
1642 if (ump->um_devvp->v_type != VBAD) 1650 if (ump->um_devvp->v_type != VBAD)
1643 spec_node_setmountedfs(ump->um_devvp, NULL); 1651 spec_node_setmountedfs(ump->um_devvp, NULL);
1644 vn_lock(ump->um_devvp, LK_EXCLUSIVE | LK_RETRY); 1652 vn_lock(ump->um_devvp, LK_EXCLUSIVE | LK_RETRY);
1645 (void)VOP_CLOSE(ump->um_devvp, fs->fs_ronly ? FREAD : FREAD | FWRITE, 1653 (void)VOP_CLOSE(ump->um_devvp, fs->fs_ronly ? FREAD : FREAD | FWRITE,
1646 NOCRED); 1654 NOCRED);
1647 vput(ump->um_devvp); 1655 vput(ump->um_devvp);
1648 1656
1649 bsize = fs->fs_cssize; 1657 bsize = fs->fs_cssize;
1650 if (fs->fs_contigsumsize > 0) 1658 if (fs->fs_contigsumsize > 0)
1651 bsize += fs->fs_ncg * sizeof(int32_t); 1659 bsize += fs->fs_ncg * sizeof(int32_t);
1652 bsize += fs->fs_ncg * sizeof(*fs->fs_contigdirs); 1660 bsize += fs->fs_ncg * sizeof(*fs->fs_contigdirs);
1653 kmem_free(fs->fs_csp, bsize); 1661 kmem_free(fs->fs_csp, bsize);
1654 1662
1655 kmem_free(fs, fs->fs_sbsize); 1663 kmem_free(fs, fs->fs_sbsize);
1656 if (ump->um_oldfscompat != NULL) 1664 if (ump->um_oldfscompat != NULL)
1657 kmem_free(ump->um_oldfscompat, 512 + 3*sizeof(int32_t)); 1665 kmem_free(ump->um_oldfscompat, 512 + 3*sizeof(int32_t));
1658 mutex_destroy(&ump->um_lock); 1666 mutex_destroy(&ump->um_lock);
1659 ffs_snapshot_fini(ump); 1667 ffs_snapshot_fini(ump);
1660 kmem_free(ump, sizeof(*ump)); 1668 kmem_free(ump, sizeof(*ump));
1661 mp->mnt_data = NULL; 1669 mp->mnt_data = NULL;
1662 mp->mnt_flag &= ~MNT_LOCAL; 1670 mp->mnt_flag &= ~MNT_LOCAL;
1663 fstrans_unmount(mp); 1671 fstrans_unmount(mp);
1664 return (0); 1672 return (0);
1665} 1673}
1666 1674
1667/* 1675/*
1668 * Flush out all the files in a filesystem. 1676 * Flush out all the files in a filesystem.
1669 */ 1677 */
1670int 1678int
1671ffs_flushfiles(struct mount *mp, int flags, struct lwp *l) 1679ffs_flushfiles(struct mount *mp, int flags, struct lwp *l)
1672{ 1680{
1673 extern int doforce; 1681 extern int doforce;
1674 struct ufsmount *ump; 1682 struct ufsmount *ump;
1675 int error; 1683 int error;
1676 1684
1677 if (!doforce) 1685 if (!doforce)
1678 flags &= ~FORCECLOSE; 1686 flags &= ~FORCECLOSE;
1679 ump = VFSTOUFS(mp); 1687 ump = VFSTOUFS(mp);
1680#ifdef QUOTA 1688#ifdef QUOTA
1681 if ((error = quota1_umount(mp, flags)) != 0) 1689 if ((error = quota1_umount(mp, flags)) != 0)
1682 return (error); 1690 return (error);
1683#endif 1691#endif
1684#ifdef QUOTA2 1692#ifdef QUOTA2
1685 if ((error = quota2_umount(mp, flags)) != 0) 1693 if ((error = quota2_umount(mp, flags)) != 0)
1686 return (error); 1694 return (error);
1687#endif 1695#endif
1688#ifdef UFS_EXTATTR 1696#ifdef UFS_EXTATTR
1689 if (ump->um_fstype == UFS1) { 1697 if (ump->um_fstype == UFS1) {
1690 if (ump->um_extattr.uepm_flags & UFS_EXTATTR_UEPM_STARTED) 1698 if (ump->um_extattr.uepm_flags & UFS_EXTATTR_UEPM_STARTED)
1691 ufs_extattr_stop(mp, l); 1699 ufs_extattr_stop(mp, l);
1692 if (ump->um_extattr.uepm_flags & UFS_EXTATTR_UEPM_INITIALIZED) 1700 if (ump->um_extattr.uepm_flags & UFS_EXTATTR_UEPM_INITIALIZED)
1693 ufs_extattr_uepm_destroy(&ump->um_extattr); 1701 ufs_extattr_uepm_destroy(&ump->um_extattr);
1694 mp->mnt_flag &= ~MNT_EXTATTR; 1702 mp->mnt_flag &= ~MNT_EXTATTR;
1695 } 1703 }
1696#endif 1704#endif
1697 if ((error = vflush(mp, 0, SKIPSYSTEM | flags)) != 0) 1705 if ((error = vflush(mp, 0, SKIPSYSTEM | flags)) != 0)
1698 return (error); 1706 return (error);
1699 ffs_snapshot_unmount(mp); 1707 ffs_snapshot_unmount(mp);
1700 /* 1708 /*
1701 * Flush all the files. 1709 * Flush all the files.
1702 */ 1710 */
1703 error = vflush(mp, NULLVP, flags); 1711 error = vflush(mp, NULLVP, flags);
1704 if (error) 1712 if (error)
1705 return (error); 1713 return (error);
1706 /* 1714 /*
1707 * Flush filesystem metadata. 1715 * Flush filesystem metadata.
1708 */ 1716 */
1709 vn_lock(ump->um_devvp, LK_EXCLUSIVE | LK_RETRY); 1717 vn_lock(ump->um_devvp, LK_EXCLUSIVE | LK_RETRY);
1710 error = VOP_FSYNC(ump->um_devvp, l->l_cred, FSYNC_WAIT, 0, 0); 1718 error = VOP_FSYNC(ump->um_devvp, l->l_cred, FSYNC_WAIT, 0, 0);
1711 VOP_UNLOCK(ump->um_devvp); 1719 VOP_UNLOCK(ump->um_devvp);
1712 if (flags & FORCECLOSE) /* XXXDBJ */ 1720 if (flags & FORCECLOSE) /* XXXDBJ */
1713 error = 0; 1721 error = 0;
1714 1722
1715#ifdef WAPBL 1723#ifdef WAPBL
1716 if (error) 1724 if (error)
1717 return error; 1725 return error;
1718 if (mp->mnt_wapbl) { 1726 if (mp->mnt_wapbl) {
1719 error = wapbl_flush(mp->mnt_wapbl, 1); 1727 error = wapbl_flush(mp->mnt_wapbl, 1);
1720 if (flags & FORCECLOSE) 1728 if (flags & FORCECLOSE)
1721 error = 0; 1729 error = 0;
1722 } 1730 }
1723#endif 1731#endif
1724 1732
1725 return (error); 1733 return (error);
1726} 1734}
1727 1735
1728/* 1736/*
1729 * Get file system statistics. 1737 * Get file system statistics.
1730 */ 1738 */
1731int 1739int
1732ffs_statvfs(struct mount *mp, struct statvfs *sbp) 1740ffs_statvfs(struct mount *mp, struct statvfs *sbp)
1733{ 1741{
1734 struct ufsmount *ump; 1742 struct ufsmount *ump;
1735 struct fs *fs; 1743 struct fs *fs;
1736 1744
1737 ump = VFSTOUFS(mp); 1745 ump = VFSTOUFS(mp);
1738 fs = ump->um_fs; 1746 fs = ump->um_fs;
1739 mutex_enter(&ump->um_lock); 1747 mutex_enter(&ump->um_lock);
1740 sbp->f_bsize = fs->fs_bsize; 1748 sbp->f_bsize = fs->fs_bsize;
1741 sbp->f_frsize = fs->fs_fsize; 1749 sbp->f_frsize = fs->fs_fsize;
1742 sbp->f_iosize = fs->fs_bsize; 1750 sbp->f_iosize = fs->fs_bsize;
1743 sbp->f_blocks = fs->fs_dsize; 1751 sbp->f_blocks = fs->fs_dsize;
1744 sbp->f_bfree = ffs_blkstofrags(fs, fs->fs_cstotal.cs_nbfree) + 1752 sbp->f_bfree = ffs_blkstofrags(fs, fs->fs_cstotal.cs_nbfree) +
1745 fs->fs_cstotal.cs_nffree + FFS_DBTOFSB(fs, fs->fs_pendingblocks); 1753 fs->fs_cstotal.cs_nffree + FFS_DBTOFSB(fs, fs->fs_pendingblocks);
1746 sbp->f_bresvd = ((u_int64_t) fs->fs_dsize * (u_int64_t) 1754 sbp->f_bresvd = ((u_int64_t) fs->fs_dsize * (u_int64_t)
1747 fs->fs_minfree) / (u_int64_t) 100; 1755 fs->fs_minfree) / (u_int64_t) 100;
1748 if (sbp->f_bfree > sbp->f_bresvd) 1756 if (sbp->f_bfree > sbp->f_bresvd)
1749 sbp->f_bavail = sbp->f_bfree - sbp->f_bresvd; 1757 sbp->f_bavail = sbp->f_bfree - sbp->f_bresvd;
1750 else 1758 else
1751 sbp->f_bavail = 0; 1759 sbp->f_bavail = 0;
1752 sbp->f_files = fs->fs_ncg * fs->fs_ipg - UFS_ROOTINO; 1760 sbp->f_files = fs->fs_ncg * fs->fs_ipg - UFS_ROOTINO;