ffs_vfsops.c revision 1.207.4.2 1 1.207.4.2 pooka /* $NetBSD: ffs_vfsops.c,v 1.207.4.2 2007/07/31 21:14:21 pooka Exp $ */
2 1.207.4.2 pooka
3 1.207.4.2 pooka /*
4 1.207.4.2 pooka * Copyright (c) 1989, 1991, 1993, 1994
5 1.207.4.2 pooka * The Regents of the University of California. All rights reserved.
6 1.207.4.2 pooka *
7 1.207.4.2 pooka * Redistribution and use in source and binary forms, with or without
8 1.207.4.2 pooka * modification, are permitted provided that the following conditions
9 1.207.4.2 pooka * are met:
10 1.207.4.2 pooka * 1. Redistributions of source code must retain the above copyright
11 1.207.4.2 pooka * notice, this list of conditions and the following disclaimer.
12 1.207.4.2 pooka * 2. Redistributions in binary form must reproduce the above copyright
13 1.207.4.2 pooka * notice, this list of conditions and the following disclaimer in the
14 1.207.4.2 pooka * documentation and/or other materials provided with the distribution.
15 1.207.4.2 pooka * 3. Neither the name of the University nor the names of its contributors
16 1.207.4.2 pooka * may be used to endorse or promote products derived from this software
17 1.207.4.2 pooka * without specific prior written permission.
18 1.207.4.2 pooka *
19 1.207.4.2 pooka * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
20 1.207.4.2 pooka * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21 1.207.4.2 pooka * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22 1.207.4.2 pooka * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
23 1.207.4.2 pooka * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24 1.207.4.2 pooka * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
25 1.207.4.2 pooka * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
26 1.207.4.2 pooka * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
27 1.207.4.2 pooka * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
28 1.207.4.2 pooka * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
29 1.207.4.2 pooka * SUCH DAMAGE.
30 1.207.4.2 pooka *
31 1.207.4.2 pooka * @(#)ffs_vfsops.c 8.31 (Berkeley) 5/20/95
32 1.207.4.2 pooka */
33 1.207.4.2 pooka
34 1.207.4.2 pooka #include <sys/cdefs.h>
35 1.207.4.2 pooka __KERNEL_RCSID(0, "$NetBSD: ffs_vfsops.c,v 1.207.4.2 2007/07/31 21:14:21 pooka Exp $");
36 1.207.4.2 pooka
37 1.207.4.2 pooka #if defined(_KERNEL_OPT)
38 1.207.4.2 pooka #include "opt_ffs.h"
39 1.207.4.2 pooka #include "opt_quota.h"
40 1.207.4.2 pooka #include "opt_softdep.h"
41 1.207.4.2 pooka #endif
42 1.207.4.2 pooka
43 1.207.4.2 pooka #include <sys/param.h>
44 1.207.4.2 pooka #include <sys/systm.h>
45 1.207.4.2 pooka #include <sys/namei.h>
46 1.207.4.2 pooka #include <sys/proc.h>
47 1.207.4.2 pooka #include <sys/kernel.h>
48 1.207.4.2 pooka #include <sys/vnode.h>
49 1.207.4.2 pooka #include <sys/socket.h>
50 1.207.4.2 pooka #include <sys/mount.h>
51 1.207.4.2 pooka #include <sys/buf.h>
52 1.207.4.2 pooka #include <sys/device.h>
53 1.207.4.2 pooka #include <sys/mbuf.h>
54 1.207.4.2 pooka #include <sys/file.h>
55 1.207.4.2 pooka #include <sys/disklabel.h>
56 1.207.4.2 pooka #include <sys/ioctl.h>
57 1.207.4.2 pooka #include <sys/errno.h>
58 1.207.4.2 pooka #include <sys/malloc.h>
59 1.207.4.2 pooka #include <sys/pool.h>
60 1.207.4.2 pooka #include <sys/lock.h>
61 1.207.4.2 pooka #include <sys/sysctl.h>
62 1.207.4.2 pooka #include <sys/conf.h>
63 1.207.4.2 pooka #include <sys/kauth.h>
64 1.207.4.2 pooka #include <sys/fstrans.h>
65 1.207.4.2 pooka
66 1.207.4.2 pooka #include <miscfs/specfs/specdev.h>
67 1.207.4.2 pooka
68 1.207.4.2 pooka #include <ufs/ufs/quota.h>
69 1.207.4.2 pooka #include <ufs/ufs/ufsmount.h>
70 1.207.4.2 pooka #include <ufs/ufs/inode.h>
71 1.207.4.2 pooka #include <ufs/ufs/dir.h>
72 1.207.4.2 pooka #include <ufs/ufs/ufs_extern.h>
73 1.207.4.2 pooka #include <ufs/ufs/ufs_bswap.h>
74 1.207.4.2 pooka
75 1.207.4.2 pooka #include <ufs/ffs/fs.h>
76 1.207.4.2 pooka #include <ufs/ffs/ffs_extern.h>
77 1.207.4.2 pooka
78 1.207.4.2 pooka /* how many times ffs_init() was called */
79 1.207.4.2 pooka int ffs_initcount = 0;
80 1.207.4.2 pooka
81 1.207.4.2 pooka extern kmutex_t ufs_hashlock;
82 1.207.4.2 pooka
83 1.207.4.2 pooka extern const struct vnodeopv_desc ffs_vnodeop_opv_desc;
84 1.207.4.2 pooka extern const struct vnodeopv_desc ffs_specop_opv_desc;
85 1.207.4.2 pooka extern const struct vnodeopv_desc ffs_fifoop_opv_desc;
86 1.207.4.2 pooka
87 1.207.4.2 pooka const struct vnodeopv_desc * const ffs_vnodeopv_descs[] = {
88 1.207.4.2 pooka &ffs_vnodeop_opv_desc,
89 1.207.4.2 pooka &ffs_specop_opv_desc,
90 1.207.4.2 pooka &ffs_fifoop_opv_desc,
91 1.207.4.2 pooka NULL,
92 1.207.4.2 pooka };
93 1.207.4.2 pooka
94 1.207.4.2 pooka struct vfsops ffs_vfsops = {
95 1.207.4.2 pooka MOUNT_FFS,
96 1.207.4.2 pooka sizeof (struct ufs_args),
97 1.207.4.2 pooka ffs_mount,
98 1.207.4.2 pooka ufs_start,
99 1.207.4.2 pooka ffs_unmount,
100 1.207.4.2 pooka ufs_root,
101 1.207.4.2 pooka ufs_quotactl,
102 1.207.4.2 pooka ffs_statvfs,
103 1.207.4.2 pooka ffs_sync,
104 1.207.4.2 pooka ffs_vget,
105 1.207.4.2 pooka ffs_fhtovp,
106 1.207.4.2 pooka ffs_vptofh,
107 1.207.4.2 pooka ffs_init,
108 1.207.4.2 pooka ffs_reinit,
109 1.207.4.2 pooka ffs_done,
110 1.207.4.2 pooka ffs_mountroot,
111 1.207.4.2 pooka ffs_snapshot,
112 1.207.4.2 pooka ffs_extattrctl,
113 1.207.4.2 pooka ffs_suspendctl,
114 1.207.4.2 pooka ffs_vnodeopv_descs,
115 1.207.4.2 pooka 0,
116 1.207.4.2 pooka { NULL, NULL },
117 1.207.4.2 pooka };
118 1.207.4.2 pooka VFS_ATTACH(ffs_vfsops);
119 1.207.4.2 pooka
120 1.207.4.2 pooka static const struct genfs_ops ffs_genfsops = {
121 1.207.4.2 pooka .gop_size = ffs_gop_size,
122 1.207.4.2 pooka .gop_alloc = ufs_gop_alloc,
123 1.207.4.2 pooka .gop_write = genfs_gop_write,
124 1.207.4.2 pooka .gop_markupdate = ufs_gop_markupdate,
125 1.207.4.2 pooka };
126 1.207.4.2 pooka
127 1.207.4.2 pooka static const struct ufs_ops ffs_ufsops = {
128 1.207.4.2 pooka .uo_itimes = ffs_itimes,
129 1.207.4.2 pooka .uo_update = ffs_update,
130 1.207.4.2 pooka .uo_truncate = ffs_truncate,
131 1.207.4.2 pooka .uo_valloc = ffs_valloc,
132 1.207.4.2 pooka .uo_vfree = ffs_vfree,
133 1.207.4.2 pooka .uo_balloc = ffs_balloc,
134 1.207.4.2 pooka };
135 1.207.4.2 pooka
136 1.207.4.2 pooka struct pool ffs_inode_pool;
137 1.207.4.2 pooka struct pool ffs_dinode1_pool;
138 1.207.4.2 pooka struct pool ffs_dinode2_pool;
139 1.207.4.2 pooka
140 1.207.4.2 pooka static void ffs_oldfscompat_read(struct fs *, struct ufsmount *, daddr_t);
141 1.207.4.2 pooka static void ffs_oldfscompat_write(struct fs *, struct ufsmount *);
142 1.207.4.2 pooka
143 1.207.4.2 pooka /*
144 1.207.4.2 pooka * Called by main() when ffs is going to be mounted as root.
145 1.207.4.2 pooka */
146 1.207.4.2 pooka
147 1.207.4.2 pooka int
148 1.207.4.2 pooka ffs_mountroot(void)
149 1.207.4.2 pooka {
150 1.207.4.2 pooka struct fs *fs;
151 1.207.4.2 pooka struct mount *mp;
152 1.207.4.2 pooka struct lwp *l = curlwp; /* XXX */
153 1.207.4.2 pooka struct ufsmount *ump;
154 1.207.4.2 pooka int error;
155 1.207.4.2 pooka
156 1.207.4.2 pooka if (device_class(root_device) != DV_DISK)
157 1.207.4.2 pooka return (ENODEV);
158 1.207.4.2 pooka
159 1.207.4.2 pooka if ((error = vfs_rootmountalloc(MOUNT_FFS, "root_device", &mp))) {
160 1.207.4.2 pooka vrele(rootvp);
161 1.207.4.2 pooka return (error);
162 1.207.4.2 pooka }
163 1.207.4.2 pooka if ((error = ffs_mountfs(rootvp, mp, l)) != 0) {
164 1.207.4.2 pooka mp->mnt_op->vfs_refcount--;
165 1.207.4.2 pooka vfs_unbusy(mp);
166 1.207.4.2 pooka free(mp, M_MOUNT);
167 1.207.4.2 pooka return (error);
168 1.207.4.2 pooka }
169 1.207.4.2 pooka simple_lock(&mountlist_slock);
170 1.207.4.2 pooka CIRCLEQ_INSERT_TAIL(&mountlist, mp, mnt_list);
171 1.207.4.2 pooka simple_unlock(&mountlist_slock);
172 1.207.4.2 pooka ump = VFSTOUFS(mp);
173 1.207.4.2 pooka fs = ump->um_fs;
174 1.207.4.2 pooka memset(fs->fs_fsmnt, 0, sizeof(fs->fs_fsmnt));
175 1.207.4.2 pooka (void)copystr(mp->mnt_stat.f_mntonname, fs->fs_fsmnt, MNAMELEN - 1, 0);
176 1.207.4.2 pooka (void)ffs_statvfs(mp, &mp->mnt_stat, l);
177 1.207.4.2 pooka vfs_unbusy(mp);
178 1.207.4.2 pooka setrootfstime((time_t)fs->fs_time);
179 1.207.4.2 pooka return (0);
180 1.207.4.2 pooka }
181 1.207.4.2 pooka
182 1.207.4.2 pooka /*
183 1.207.4.2 pooka * VFS Operations.
184 1.207.4.2 pooka *
185 1.207.4.2 pooka * mount system call
186 1.207.4.2 pooka */
187 1.207.4.2 pooka int
188 1.207.4.2 pooka ffs_mount(struct mount *mp, const char *path, void *data, size_t *data_len,
189 1.207.4.2 pooka struct lwp *l)
190 1.207.4.2 pooka {
191 1.207.4.2 pooka struct nameidata nd;
192 1.207.4.2 pooka struct vnode *devvp = NULL;
193 1.207.4.2 pooka struct ufs_args *args = data;
194 1.207.4.2 pooka struct ufsmount *ump = NULL;
195 1.207.4.2 pooka struct fs *fs;
196 1.207.4.2 pooka int error = 0, flags, update;
197 1.207.4.2 pooka mode_t accessmode;
198 1.207.4.2 pooka
199 1.207.4.2 pooka if (*data_len < sizeof *args)
200 1.207.4.2 pooka return EINVAL;
201 1.207.4.2 pooka
202 1.207.4.2 pooka if (mp->mnt_flag & MNT_GETARGS) {
203 1.207.4.2 pooka ump = VFSTOUFS(mp);
204 1.207.4.2 pooka if (ump == NULL)
205 1.207.4.2 pooka return EIO;
206 1.207.4.2 pooka args->fspec = NULL;
207 1.207.4.2 pooka *data_len = sizeof *args;
208 1.207.4.2 pooka return 0;
209 1.207.4.2 pooka }
210 1.207.4.2 pooka
211 1.207.4.2 pooka #if !defined(SOFTDEP)
212 1.207.4.2 pooka mp->mnt_flag &= ~MNT_SOFTDEP;
213 1.207.4.2 pooka #endif
214 1.207.4.2 pooka
215 1.207.4.2 pooka update = mp->mnt_flag & MNT_UPDATE;
216 1.207.4.2 pooka
217 1.207.4.2 pooka /* Check arguments */
218 1.207.4.2 pooka if (args->fspec != NULL) {
219 1.207.4.2 pooka /*
220 1.207.4.2 pooka * Look up the name and verify that it's sane.
221 1.207.4.2 pooka */
222 1.207.4.2 pooka NDINIT(&nd, LOOKUP, FOLLOW, UIO_USERSPACE, args->fspec, l);
223 1.207.4.2 pooka if ((error = namei(&nd)) != 0)
224 1.207.4.2 pooka return (error);
225 1.207.4.2 pooka devvp = nd.ni_vp;
226 1.207.4.2 pooka
227 1.207.4.2 pooka if (!update) {
228 1.207.4.2 pooka /*
229 1.207.4.2 pooka * Be sure this is a valid block device
230 1.207.4.2 pooka */
231 1.207.4.2 pooka if (devvp->v_type != VBLK)
232 1.207.4.2 pooka error = ENOTBLK;
233 1.207.4.2 pooka else if (bdevsw_lookup(devvp->v_rdev) == NULL)
234 1.207.4.2 pooka error = ENXIO;
235 1.207.4.2 pooka } else {
236 1.207.4.2 pooka /*
237 1.207.4.2 pooka * Be sure we're still naming the same device
238 1.207.4.2 pooka * used for our initial mount
239 1.207.4.2 pooka */
240 1.207.4.2 pooka ump = VFSTOUFS(mp);
241 1.207.4.2 pooka if (devvp != ump->um_devvp) {
242 1.207.4.2 pooka if (devvp->v_rdev != ump->um_devvp->v_rdev)
243 1.207.4.2 pooka error = EINVAL;
244 1.207.4.2 pooka else {
245 1.207.4.2 pooka vrele(devvp);
246 1.207.4.2 pooka devvp = ump->um_devvp;
247 1.207.4.2 pooka vref(devvp);
248 1.207.4.2 pooka }
249 1.207.4.2 pooka }
250 1.207.4.2 pooka }
251 1.207.4.2 pooka } else {
252 1.207.4.2 pooka if (!update) {
253 1.207.4.2 pooka /* New mounts must have a filename for the device */
254 1.207.4.2 pooka return (EINVAL);
255 1.207.4.2 pooka } else {
256 1.207.4.2 pooka /* Use the extant mount */
257 1.207.4.2 pooka ump = VFSTOUFS(mp);
258 1.207.4.2 pooka devvp = ump->um_devvp;
259 1.207.4.2 pooka vref(devvp);
260 1.207.4.2 pooka }
261 1.207.4.2 pooka }
262 1.207.4.2 pooka
263 1.207.4.2 pooka /*
264 1.207.4.2 pooka * If mount by non-root, then verify that user has necessary
265 1.207.4.2 pooka * permissions on the device.
266 1.207.4.2 pooka */
267 1.207.4.2 pooka if (error == 0 && kauth_authorize_generic(l->l_cred,
268 1.207.4.2 pooka KAUTH_GENERIC_ISSUSER, NULL) != 0) {
269 1.207.4.2 pooka accessmode = VREAD;
270 1.207.4.2 pooka if (update ?
271 1.207.4.2 pooka (mp->mnt_iflag & IMNT_WANTRDWR) != 0 :
272 1.207.4.2 pooka (mp->mnt_flag & MNT_RDONLY) == 0)
273 1.207.4.2 pooka accessmode |= VWRITE;
274 1.207.4.2 pooka vn_lock(devvp, LK_EXCLUSIVE | LK_RETRY);
275 1.207.4.2 pooka error = VOP_ACCESS(devvp, accessmode, l->l_cred, l);
276 1.207.4.2 pooka VOP_UNLOCK(devvp, 0);
277 1.207.4.2 pooka }
278 1.207.4.2 pooka
279 1.207.4.2 pooka if (error) {
280 1.207.4.2 pooka vrele(devvp);
281 1.207.4.2 pooka return (error);
282 1.207.4.2 pooka }
283 1.207.4.2 pooka
284 1.207.4.2 pooka if (!update) {
285 1.207.4.2 pooka int xflags;
286 1.207.4.2 pooka
287 1.207.4.2 pooka /*
288 1.207.4.2 pooka * Disallow multiple mounts of the same device.
289 1.207.4.2 pooka * Disallow mounting of a device that is currently in use
290 1.207.4.2 pooka * (except for root, which might share swap device for
291 1.207.4.2 pooka * miniroot).
292 1.207.4.2 pooka */
293 1.207.4.2 pooka error = vfs_mountedon(devvp);
294 1.207.4.2 pooka if (error)
295 1.207.4.2 pooka goto fail;
296 1.207.4.2 pooka if (vcount(devvp) > 1 && devvp != rootvp) {
297 1.207.4.2 pooka error = EBUSY;
298 1.207.4.2 pooka goto fail;
299 1.207.4.2 pooka }
300 1.207.4.2 pooka if (mp->mnt_flag & MNT_RDONLY)
301 1.207.4.2 pooka xflags = FREAD;
302 1.207.4.2 pooka else
303 1.207.4.2 pooka xflags = FREAD|FWRITE;
304 1.207.4.2 pooka error = VOP_OPEN(devvp, xflags, FSCRED, l);
305 1.207.4.2 pooka if (error)
306 1.207.4.2 pooka goto fail;
307 1.207.4.2 pooka error = ffs_mountfs(devvp, mp, l);
308 1.207.4.2 pooka if (error) {
309 1.207.4.2 pooka vn_lock(devvp, LK_EXCLUSIVE | LK_RETRY);
310 1.207.4.2 pooka (void)VOP_CLOSE(devvp, xflags, NOCRED, l);
311 1.207.4.2 pooka VOP_UNLOCK(devvp, 0);
312 1.207.4.2 pooka goto fail;
313 1.207.4.2 pooka }
314 1.207.4.2 pooka
315 1.207.4.2 pooka ump = VFSTOUFS(mp);
316 1.207.4.2 pooka fs = ump->um_fs;
317 1.207.4.2 pooka if ((mp->mnt_flag & (MNT_SOFTDEP | MNT_ASYNC)) ==
318 1.207.4.2 pooka (MNT_SOFTDEP | MNT_ASYNC)) {
319 1.207.4.2 pooka printf("%s fs uses soft updates, "
320 1.207.4.2 pooka "ignoring async mode\n",
321 1.207.4.2 pooka fs->fs_fsmnt);
322 1.207.4.2 pooka mp->mnt_flag &= ~MNT_ASYNC;
323 1.207.4.2 pooka }
324 1.207.4.2 pooka } else {
325 1.207.4.2 pooka /*
326 1.207.4.2 pooka * Update the mount.
327 1.207.4.2 pooka */
328 1.207.4.2 pooka
329 1.207.4.2 pooka /*
330 1.207.4.2 pooka * The initial mount got a reference on this
331 1.207.4.2 pooka * device, so drop the one obtained via
332 1.207.4.2 pooka * namei(), above.
333 1.207.4.2 pooka */
334 1.207.4.2 pooka vrele(devvp);
335 1.207.4.2 pooka
336 1.207.4.2 pooka ump = VFSTOUFS(mp);
337 1.207.4.2 pooka fs = ump->um_fs;
338 1.207.4.2 pooka if (fs->fs_ronly == 0 && (mp->mnt_flag & MNT_RDONLY)) {
339 1.207.4.2 pooka /*
340 1.207.4.2 pooka * Changing from r/w to r/o
341 1.207.4.2 pooka */
342 1.207.4.2 pooka flags = WRITECLOSE;
343 1.207.4.2 pooka if (mp->mnt_flag & MNT_FORCE)
344 1.207.4.2 pooka flags |= FORCECLOSE;
345 1.207.4.2 pooka if (mp->mnt_flag & MNT_SOFTDEP)
346 1.207.4.2 pooka error = softdep_flushfiles(mp, flags, l);
347 1.207.4.2 pooka else
348 1.207.4.2 pooka error = ffs_flushfiles(mp, flags, l);
349 1.207.4.2 pooka if (fs->fs_pendingblocks != 0 ||
350 1.207.4.2 pooka fs->fs_pendinginodes != 0) {
351 1.207.4.2 pooka printf("%s: update error: blocks %" PRId64
352 1.207.4.2 pooka " files %d\n",
353 1.207.4.2 pooka fs->fs_fsmnt, fs->fs_pendingblocks,
354 1.207.4.2 pooka fs->fs_pendinginodes);
355 1.207.4.2 pooka fs->fs_pendingblocks = 0;
356 1.207.4.2 pooka fs->fs_pendinginodes = 0;
357 1.207.4.2 pooka }
358 1.207.4.2 pooka if (error == 0 &&
359 1.207.4.2 pooka ffs_cgupdate(ump, MNT_WAIT) == 0 &&
360 1.207.4.2 pooka fs->fs_clean & FS_WASCLEAN) {
361 1.207.4.2 pooka if (mp->mnt_flag & MNT_SOFTDEP)
362 1.207.4.2 pooka fs->fs_flags &= ~FS_DOSOFTDEP;
363 1.207.4.2 pooka fs->fs_clean = FS_ISCLEAN;
364 1.207.4.2 pooka (void) ffs_sbupdate(ump, MNT_WAIT);
365 1.207.4.2 pooka }
366 1.207.4.2 pooka if (error)
367 1.207.4.2 pooka return (error);
368 1.207.4.2 pooka fs->fs_ronly = 1;
369 1.207.4.2 pooka fs->fs_fmod = 0;
370 1.207.4.2 pooka }
371 1.207.4.2 pooka
372 1.207.4.2 pooka /*
373 1.207.4.2 pooka * Flush soft dependencies if disabling it via an update
374 1.207.4.2 pooka * mount. This may leave some items to be processed,
375 1.207.4.2 pooka * so don't do this yet XXX.
376 1.207.4.2 pooka */
377 1.207.4.2 pooka if ((fs->fs_flags & FS_DOSOFTDEP) &&
378 1.207.4.2 pooka !(mp->mnt_flag & MNT_SOFTDEP) && fs->fs_ronly == 0) {
379 1.207.4.2 pooka #ifdef notyet
380 1.207.4.2 pooka flags = WRITECLOSE;
381 1.207.4.2 pooka if (mp->mnt_flag & MNT_FORCE)
382 1.207.4.2 pooka flags |= FORCECLOSE;
383 1.207.4.2 pooka error = softdep_flushfiles(mp, flags, l);
384 1.207.4.2 pooka if (error == 0 && ffs_cgupdate(ump, MNT_WAIT) == 0)
385 1.207.4.2 pooka fs->fs_flags &= ~FS_DOSOFTDEP;
386 1.207.4.2 pooka (void) ffs_sbupdate(ump, MNT_WAIT);
387 1.207.4.2 pooka #elif defined(SOFTDEP)
388 1.207.4.2 pooka mp->mnt_flag |= MNT_SOFTDEP;
389 1.207.4.2 pooka #endif
390 1.207.4.2 pooka }
391 1.207.4.2 pooka
392 1.207.4.2 pooka /*
393 1.207.4.2 pooka * When upgrading to a softdep mount, we must first flush
394 1.207.4.2 pooka * all vnodes. (not done yet -- see above)
395 1.207.4.2 pooka */
396 1.207.4.2 pooka if (!(fs->fs_flags & FS_DOSOFTDEP) &&
397 1.207.4.2 pooka (mp->mnt_flag & MNT_SOFTDEP) && fs->fs_ronly == 0) {
398 1.207.4.2 pooka #ifdef notyet
399 1.207.4.2 pooka flags = WRITECLOSE;
400 1.207.4.2 pooka if (mp->mnt_flag & MNT_FORCE)
401 1.207.4.2 pooka flags |= FORCECLOSE;
402 1.207.4.2 pooka error = ffs_flushfiles(mp, flags, l);
403 1.207.4.2 pooka #else
404 1.207.4.2 pooka mp->mnt_flag &= ~MNT_SOFTDEP;
405 1.207.4.2 pooka #endif
406 1.207.4.2 pooka }
407 1.207.4.2 pooka
408 1.207.4.2 pooka if (mp->mnt_flag & MNT_RELOAD) {
409 1.207.4.2 pooka error = ffs_reload(mp, l->l_cred, l);
410 1.207.4.2 pooka if (error)
411 1.207.4.2 pooka return (error);
412 1.207.4.2 pooka }
413 1.207.4.2 pooka
414 1.207.4.2 pooka if (fs->fs_ronly && (mp->mnt_iflag & IMNT_WANTRDWR)) {
415 1.207.4.2 pooka /*
416 1.207.4.2 pooka * Changing from read-only to read/write
417 1.207.4.2 pooka */
418 1.207.4.2 pooka fs->fs_ronly = 0;
419 1.207.4.2 pooka fs->fs_clean <<= 1;
420 1.207.4.2 pooka fs->fs_fmod = 1;
421 1.207.4.2 pooka if ((fs->fs_flags & FS_DOSOFTDEP)) {
422 1.207.4.2 pooka error = softdep_mount(devvp, mp, fs,
423 1.207.4.2 pooka l->l_cred);
424 1.207.4.2 pooka if (error)
425 1.207.4.2 pooka return (error);
426 1.207.4.2 pooka }
427 1.207.4.2 pooka if (fs->fs_snapinum[0] != 0)
428 1.207.4.2 pooka ffs_snapshot_mount(mp);
429 1.207.4.2 pooka }
430 1.207.4.2 pooka if (args->fspec == NULL)
431 1.207.4.2 pooka return EINVAL;
432 1.207.4.2 pooka if ((mp->mnt_flag & (MNT_SOFTDEP | MNT_ASYNC)) ==
433 1.207.4.2 pooka (MNT_SOFTDEP | MNT_ASYNC)) {
434 1.207.4.2 pooka printf("%s fs uses soft updates, ignoring async mode\n",
435 1.207.4.2 pooka fs->fs_fsmnt);
436 1.207.4.2 pooka mp->mnt_flag &= ~MNT_ASYNC;
437 1.207.4.2 pooka }
438 1.207.4.2 pooka }
439 1.207.4.2 pooka
440 1.207.4.2 pooka error = set_statvfs_info(path, UIO_USERSPACE, args->fspec,
441 1.207.4.2 pooka UIO_USERSPACE, mp->mnt_op->vfs_name, mp, l);
442 1.207.4.2 pooka if (error == 0)
443 1.207.4.2 pooka (void)strncpy(fs->fs_fsmnt, mp->mnt_stat.f_mntonname,
444 1.207.4.2 pooka sizeof(fs->fs_fsmnt));
445 1.207.4.2 pooka if (mp->mnt_flag & MNT_SOFTDEP)
446 1.207.4.2 pooka fs->fs_flags |= FS_DOSOFTDEP;
447 1.207.4.2 pooka else
448 1.207.4.2 pooka fs->fs_flags &= ~FS_DOSOFTDEP;
449 1.207.4.2 pooka if (fs->fs_fmod != 0) { /* XXX */
450 1.207.4.2 pooka fs->fs_fmod = 0;
451 1.207.4.2 pooka if (fs->fs_clean & FS_WASCLEAN)
452 1.207.4.2 pooka fs->fs_time = time_second;
453 1.207.4.2 pooka else {
454 1.207.4.2 pooka printf("%s: file system not clean (fs_clean=%x); please fsck(8)\n",
455 1.207.4.2 pooka mp->mnt_stat.f_mntfromname, fs->fs_clean);
456 1.207.4.2 pooka printf("%s: lost blocks %" PRId64 " files %d\n",
457 1.207.4.2 pooka mp->mnt_stat.f_mntfromname, fs->fs_pendingblocks,
458 1.207.4.2 pooka fs->fs_pendinginodes);
459 1.207.4.2 pooka }
460 1.207.4.2 pooka (void) ffs_cgupdate(ump, MNT_WAIT);
461 1.207.4.2 pooka }
462 1.207.4.2 pooka return (error);
463 1.207.4.2 pooka
464 1.207.4.2 pooka fail:
465 1.207.4.2 pooka vrele(devvp);
466 1.207.4.2 pooka return (error);
467 1.207.4.2 pooka }
468 1.207.4.2 pooka
469 1.207.4.2 pooka /*
470 1.207.4.2 pooka * Reload all incore data for a filesystem (used after running fsck on
471 1.207.4.2 pooka * the root filesystem and finding things to fix). The filesystem must
472 1.207.4.2 pooka * be mounted read-only.
473 1.207.4.2 pooka *
474 1.207.4.2 pooka * Things to do to update the mount:
475 1.207.4.2 pooka * 1) invalidate all cached meta-data.
476 1.207.4.2 pooka * 2) re-read superblock from disk.
477 1.207.4.2 pooka * 3) re-read summary information from disk.
478 1.207.4.2 pooka * 4) invalidate all inactive vnodes.
479 1.207.4.2 pooka * 5) invalidate all cached file data.
480 1.207.4.2 pooka * 6) re-read inode data for all active vnodes.
481 1.207.4.2 pooka */
482 1.207.4.2 pooka int
483 1.207.4.2 pooka ffs_reload(struct mount *mp, kauth_cred_t cred, struct lwp *l)
484 1.207.4.2 pooka {
485 1.207.4.2 pooka struct vnode *vp, *nvp, *devvp;
486 1.207.4.2 pooka struct inode *ip;
487 1.207.4.2 pooka void *space;
488 1.207.4.2 pooka struct buf *bp;
489 1.207.4.2 pooka struct fs *fs, *newfs;
490 1.207.4.2 pooka struct partinfo dpart;
491 1.207.4.2 pooka int i, blks, size, error;
492 1.207.4.2 pooka int32_t *lp;
493 1.207.4.2 pooka struct ufsmount *ump;
494 1.207.4.2 pooka daddr_t sblockloc;
495 1.207.4.2 pooka
496 1.207.4.2 pooka if ((mp->mnt_flag & MNT_RDONLY) == 0)
497 1.207.4.2 pooka return (EINVAL);
498 1.207.4.2 pooka
499 1.207.4.2 pooka ump = VFSTOUFS(mp);
500 1.207.4.2 pooka /*
501 1.207.4.2 pooka * Step 1: invalidate all cached meta-data.
502 1.207.4.2 pooka */
503 1.207.4.2 pooka devvp = ump->um_devvp;
504 1.207.4.2 pooka vn_lock(devvp, LK_EXCLUSIVE | LK_RETRY);
505 1.207.4.2 pooka error = vinvalbuf(devvp, 0, cred, l, 0, 0);
506 1.207.4.2 pooka VOP_UNLOCK(devvp, 0);
507 1.207.4.2 pooka if (error)
508 1.207.4.2 pooka panic("ffs_reload: dirty1");
509 1.207.4.2 pooka /*
510 1.207.4.2 pooka * Step 2: re-read superblock from disk.
511 1.207.4.2 pooka */
512 1.207.4.2 pooka fs = ump->um_fs;
513 1.207.4.2 pooka if (VOP_IOCTL(devvp, DIOCGPART, &dpart, FREAD, NOCRED, l) != 0)
514 1.207.4.2 pooka size = DEV_BSIZE;
515 1.207.4.2 pooka else
516 1.207.4.2 pooka size = dpart.disklab->d_secsize;
517 1.207.4.2 pooka /* XXX we don't handle possibility that superblock moved. */
518 1.207.4.2 pooka error = bread(devvp, fs->fs_sblockloc / size, fs->fs_sbsize,
519 1.207.4.2 pooka NOCRED, &bp);
520 1.207.4.2 pooka if (error) {
521 1.207.4.2 pooka brelse(bp);
522 1.207.4.2 pooka return (error);
523 1.207.4.2 pooka }
524 1.207.4.2 pooka newfs = malloc(fs->fs_sbsize, M_UFSMNT, M_WAITOK);
525 1.207.4.2 pooka memcpy(newfs, bp->b_data, fs->fs_sbsize);
526 1.207.4.2 pooka #ifdef FFS_EI
527 1.207.4.2 pooka if (ump->um_flags & UFS_NEEDSWAP) {
528 1.207.4.2 pooka ffs_sb_swap((struct fs*)bp->b_data, newfs);
529 1.207.4.2 pooka fs->fs_flags |= FS_SWAPPED;
530 1.207.4.2 pooka } else
531 1.207.4.2 pooka #endif
532 1.207.4.2 pooka fs->fs_flags &= ~FS_SWAPPED;
533 1.207.4.2 pooka if ((newfs->fs_magic != FS_UFS1_MAGIC &&
534 1.207.4.2 pooka newfs->fs_magic != FS_UFS2_MAGIC)||
535 1.207.4.2 pooka newfs->fs_bsize > MAXBSIZE ||
536 1.207.4.2 pooka newfs->fs_bsize < sizeof(struct fs)) {
537 1.207.4.2 pooka brelse(bp);
538 1.207.4.2 pooka free(newfs, M_UFSMNT);
539 1.207.4.2 pooka return (EIO); /* XXX needs translation */
540 1.207.4.2 pooka }
541 1.207.4.2 pooka /* Store off old fs_sblockloc for fs_oldfscompat_read. */
542 1.207.4.2 pooka sblockloc = fs->fs_sblockloc;
543 1.207.4.2 pooka /*
544 1.207.4.2 pooka * Copy pointer fields back into superblock before copying in XXX
545 1.207.4.2 pooka * new superblock. These should really be in the ufsmount. XXX
546 1.207.4.2 pooka * Note that important parameters (eg fs_ncg) are unchanged.
547 1.207.4.2 pooka */
548 1.207.4.2 pooka newfs->fs_csp = fs->fs_csp;
549 1.207.4.2 pooka newfs->fs_maxcluster = fs->fs_maxcluster;
550 1.207.4.2 pooka newfs->fs_contigdirs = fs->fs_contigdirs;
551 1.207.4.2 pooka newfs->fs_ronly = fs->fs_ronly;
552 1.207.4.2 pooka newfs->fs_active = fs->fs_active;
553 1.207.4.2 pooka memcpy(fs, newfs, (u_int)fs->fs_sbsize);
554 1.207.4.2 pooka brelse(bp);
555 1.207.4.2 pooka free(newfs, M_UFSMNT);
556 1.207.4.2 pooka
557 1.207.4.2 pooka /* Recheck for apple UFS filesystem */
558 1.207.4.2 pooka ump->um_flags &= ~UFS_ISAPPLEUFS;
559 1.207.4.2 pooka /* First check to see if this is tagged as an Apple UFS filesystem
560 1.207.4.2 pooka * in the disklabel
561 1.207.4.2 pooka */
562 1.207.4.2 pooka if ((VOP_IOCTL(devvp, DIOCGPART, &dpart, FREAD, cred, l) == 0) &&
563 1.207.4.2 pooka (dpart.part->p_fstype == FS_APPLEUFS)) {
564 1.207.4.2 pooka ump->um_flags |= UFS_ISAPPLEUFS;
565 1.207.4.2 pooka }
566 1.207.4.2 pooka #ifdef APPLE_UFS
567 1.207.4.2 pooka else {
568 1.207.4.2 pooka /* Manually look for an apple ufs label, and if a valid one
569 1.207.4.2 pooka * is found, then treat it like an Apple UFS filesystem anyway
570 1.207.4.2 pooka */
571 1.207.4.2 pooka error = bread(devvp, (daddr_t)(APPLEUFS_LABEL_OFFSET / size),
572 1.207.4.2 pooka APPLEUFS_LABEL_SIZE, cred, &bp);
573 1.207.4.2 pooka if (error) {
574 1.207.4.2 pooka brelse(bp);
575 1.207.4.2 pooka return (error);
576 1.207.4.2 pooka }
577 1.207.4.2 pooka error = ffs_appleufs_validate(fs->fs_fsmnt,
578 1.207.4.2 pooka (struct appleufslabel *)bp->b_data,NULL);
579 1.207.4.2 pooka if (error == 0)
580 1.207.4.2 pooka ump->um_flags |= UFS_ISAPPLEUFS;
581 1.207.4.2 pooka brelse(bp);
582 1.207.4.2 pooka bp = NULL;
583 1.207.4.2 pooka }
584 1.207.4.2 pooka #else
585 1.207.4.2 pooka if (ump->um_flags & UFS_ISAPPLEUFS)
586 1.207.4.2 pooka return (EIO);
587 1.207.4.2 pooka #endif
588 1.207.4.2 pooka
589 1.207.4.2 pooka if (UFS_MPISAPPLEUFS(ump)) {
590 1.207.4.2 pooka /* see comment about NeXT below */
591 1.207.4.2 pooka ump->um_maxsymlinklen = APPLEUFS_MAXSYMLINKLEN;
592 1.207.4.2 pooka ump->um_dirblksiz = APPLEUFS_DIRBLKSIZ;
593 1.207.4.2 pooka mp->mnt_iflag |= IMNT_DTYPE;
594 1.207.4.2 pooka } else {
595 1.207.4.2 pooka ump->um_maxsymlinklen = fs->fs_maxsymlinklen;
596 1.207.4.2 pooka ump->um_dirblksiz = DIRBLKSIZ;
597 1.207.4.2 pooka if (ump->um_maxsymlinklen > 0)
598 1.207.4.2 pooka mp->mnt_iflag |= IMNT_DTYPE;
599 1.207.4.2 pooka else
600 1.207.4.2 pooka mp->mnt_iflag &= ~IMNT_DTYPE;
601 1.207.4.2 pooka }
602 1.207.4.2 pooka ffs_oldfscompat_read(fs, ump, sblockloc);
603 1.207.4.2 pooka ump->um_maxfilesize = fs->fs_maxfilesize;
604 1.207.4.2 pooka if (fs->fs_pendingblocks != 0 || fs->fs_pendinginodes != 0) {
605 1.207.4.2 pooka fs->fs_pendingblocks = 0;
606 1.207.4.2 pooka fs->fs_pendinginodes = 0;
607 1.207.4.2 pooka }
608 1.207.4.2 pooka
609 1.207.4.2 pooka ffs_statvfs(mp, &mp->mnt_stat, l);
610 1.207.4.2 pooka /*
611 1.207.4.2 pooka * Step 3: re-read summary information from disk.
612 1.207.4.2 pooka */
613 1.207.4.2 pooka blks = howmany(fs->fs_cssize, fs->fs_fsize);
614 1.207.4.2 pooka space = fs->fs_csp;
615 1.207.4.2 pooka for (i = 0; i < blks; i += fs->fs_frag) {
616 1.207.4.2 pooka size = fs->fs_bsize;
617 1.207.4.2 pooka if (i + fs->fs_frag > blks)
618 1.207.4.2 pooka size = (blks - i) * fs->fs_fsize;
619 1.207.4.2 pooka error = bread(devvp, fsbtodb(fs, fs->fs_csaddr + i), size,
620 1.207.4.2 pooka NOCRED, &bp);
621 1.207.4.2 pooka if (error) {
622 1.207.4.2 pooka brelse(bp);
623 1.207.4.2 pooka return (error);
624 1.207.4.2 pooka }
625 1.207.4.2 pooka #ifdef FFS_EI
626 1.207.4.2 pooka if (UFS_FSNEEDSWAP(fs))
627 1.207.4.2 pooka ffs_csum_swap((struct csum *)bp->b_data,
628 1.207.4.2 pooka (struct csum *)space, size);
629 1.207.4.2 pooka else
630 1.207.4.2 pooka #endif
631 1.207.4.2 pooka memcpy(space, bp->b_data, (size_t)size);
632 1.207.4.2 pooka space = (char *)space + size;
633 1.207.4.2 pooka brelse(bp);
634 1.207.4.2 pooka }
635 1.207.4.2 pooka if ((fs->fs_flags & FS_DOSOFTDEP))
636 1.207.4.2 pooka softdep_mount(devvp, mp, fs, cred);
637 1.207.4.2 pooka if (fs->fs_snapinum[0] != 0)
638 1.207.4.2 pooka ffs_snapshot_mount(mp);
639 1.207.4.2 pooka /*
640 1.207.4.2 pooka * We no longer know anything about clusters per cylinder group.
641 1.207.4.2 pooka */
642 1.207.4.2 pooka if (fs->fs_contigsumsize > 0) {
643 1.207.4.2 pooka lp = fs->fs_maxcluster;
644 1.207.4.2 pooka for (i = 0; i < fs->fs_ncg; i++)
645 1.207.4.2 pooka *lp++ = fs->fs_contigsumsize;
646 1.207.4.2 pooka }
647 1.207.4.2 pooka
648 1.207.4.2 pooka loop:
649 1.207.4.2 pooka /*
650 1.207.4.2 pooka * NOTE: not using the TAILQ_FOREACH here since in this loop vgone()
651 1.207.4.2 pooka * and vclean() can be called indirectly
652 1.207.4.2 pooka */
653 1.207.4.2 pooka simple_lock(&mntvnode_slock);
654 1.207.4.2 pooka for (vp = TAILQ_FIRST(&mp->mnt_vnodelist); vp; vp = nvp) {
655 1.207.4.2 pooka if (vp->v_mount != mp) {
656 1.207.4.2 pooka simple_unlock(&mntvnode_slock);
657 1.207.4.2 pooka goto loop;
658 1.207.4.2 pooka }
659 1.207.4.2 pooka /*
660 1.207.4.2 pooka * Step 4: invalidate all inactive vnodes.
661 1.207.4.2 pooka */
662 1.207.4.2 pooka if (vrecycle(vp, &mntvnode_slock, l))
663 1.207.4.2 pooka goto loop;
664 1.207.4.2 pooka /*
665 1.207.4.2 pooka * Step 5: invalidate all cached file data.
666 1.207.4.2 pooka */
667 1.207.4.2 pooka simple_lock(&vp->v_interlock);
668 1.207.4.2 pooka nvp = TAILQ_NEXT(vp, v_mntvnodes);
669 1.207.4.2 pooka simple_unlock(&mntvnode_slock);
670 1.207.4.2 pooka if (vget(vp, LK_EXCLUSIVE | LK_INTERLOCK))
671 1.207.4.2 pooka goto loop;
672 1.207.4.2 pooka if (vinvalbuf(vp, 0, cred, l, 0, 0))
673 1.207.4.2 pooka panic("ffs_reload: dirty2");
674 1.207.4.2 pooka /*
675 1.207.4.2 pooka * Step 6: re-read inode data for all active vnodes.
676 1.207.4.2 pooka */
677 1.207.4.2 pooka ip = VTOI(vp);
678 1.207.4.2 pooka error = bread(devvp, fsbtodb(fs, ino_to_fsba(fs, ip->i_number)),
679 1.207.4.2 pooka (int)fs->fs_bsize, NOCRED, &bp);
680 1.207.4.2 pooka if (error) {
681 1.207.4.2 pooka brelse(bp);
682 1.207.4.2 pooka vput(vp);
683 1.207.4.2 pooka return (error);
684 1.207.4.2 pooka }
685 1.207.4.2 pooka ffs_load_inode(bp, ip, fs, ip->i_number);
686 1.207.4.2 pooka ip->i_ffs_effnlink = ip->i_nlink;
687 1.207.4.2 pooka brelse(bp);
688 1.207.4.2 pooka vput(vp);
689 1.207.4.2 pooka simple_lock(&mntvnode_slock);
690 1.207.4.2 pooka }
691 1.207.4.2 pooka simple_unlock(&mntvnode_slock);
692 1.207.4.2 pooka return (0);
693 1.207.4.2 pooka }
694 1.207.4.2 pooka
695 1.207.4.2 pooka /*
696 1.207.4.2 pooka * Possible superblock locations ordered from most to least likely.
697 1.207.4.2 pooka */
698 1.207.4.2 pooka static const int sblock_try[] = SBLOCKSEARCH;
699 1.207.4.2 pooka
700 1.207.4.2 pooka /*
701 1.207.4.2 pooka * Common code for mount and mountroot
702 1.207.4.2 pooka */
703 1.207.4.2 pooka int
704 1.207.4.2 pooka ffs_mountfs(struct vnode *devvp, struct mount *mp, struct lwp *l)
705 1.207.4.2 pooka {
706 1.207.4.2 pooka struct ufsmount *ump;
707 1.207.4.2 pooka struct buf *bp;
708 1.207.4.2 pooka struct fs *fs;
709 1.207.4.2 pooka dev_t dev;
710 1.207.4.2 pooka struct partinfo dpart;
711 1.207.4.2 pooka void *space;
712 1.207.4.2 pooka daddr_t sblockloc, fsblockloc;
713 1.207.4.2 pooka int blks, fstype;
714 1.207.4.2 pooka int error, i, size, ronly;
715 1.207.4.2 pooka #ifdef FFS_EI
716 1.207.4.2 pooka int needswap = 0; /* keep gcc happy */
717 1.207.4.2 pooka #endif
718 1.207.4.2 pooka int32_t *lp;
719 1.207.4.2 pooka kauth_cred_t cred;
720 1.207.4.2 pooka u_int32_t sbsize = 8192; /* keep gcc happy*/
721 1.207.4.2 pooka
722 1.207.4.2 pooka dev = devvp->v_rdev;
723 1.207.4.2 pooka cred = l ? l->l_cred : NOCRED;
724 1.207.4.2 pooka
725 1.207.4.2 pooka /* Flush out any old buffers remaining from a previous use. */
726 1.207.4.2 pooka vn_lock(devvp, LK_EXCLUSIVE | LK_RETRY);
727 1.207.4.2 pooka error = vinvalbuf(devvp, V_SAVE, cred, l, 0, 0);
728 1.207.4.2 pooka VOP_UNLOCK(devvp, 0);
729 1.207.4.2 pooka if (error)
730 1.207.4.2 pooka return (error);
731 1.207.4.2 pooka
732 1.207.4.2 pooka ronly = (mp->mnt_flag & MNT_RDONLY) != 0;
733 1.207.4.2 pooka if (VOP_IOCTL(devvp, DIOCGPART, &dpart, FREAD, cred, l) != 0)
734 1.207.4.2 pooka size = DEV_BSIZE;
735 1.207.4.2 pooka else
736 1.207.4.2 pooka size = dpart.disklab->d_secsize;
737 1.207.4.2 pooka
738 1.207.4.2 pooka bp = NULL;
739 1.207.4.2 pooka ump = NULL;
740 1.207.4.2 pooka fs = NULL;
741 1.207.4.2 pooka sblockloc = 0;
742 1.207.4.2 pooka fstype = 0;
743 1.207.4.2 pooka
744 1.207.4.2 pooka /*
745 1.207.4.2 pooka * Try reading the superblock in each of its possible locations.
746 1.207.4.2 pooka */
747 1.207.4.2 pooka for (i = 0; ; i++) {
748 1.207.4.2 pooka if (bp != NULL) {
749 1.207.4.2 pooka bp->b_flags |= B_NOCACHE;
750 1.207.4.2 pooka brelse(bp);
751 1.207.4.2 pooka bp = NULL;
752 1.207.4.2 pooka }
753 1.207.4.2 pooka if (sblock_try[i] == -1) {
754 1.207.4.2 pooka error = EINVAL;
755 1.207.4.2 pooka fs = NULL;
756 1.207.4.2 pooka goto out;
757 1.207.4.2 pooka }
758 1.207.4.2 pooka error = bread(devvp, sblock_try[i] / size, SBLOCKSIZE, cred,
759 1.207.4.2 pooka &bp);
760 1.207.4.2 pooka if (error) {
761 1.207.4.2 pooka fs = NULL;
762 1.207.4.2 pooka goto out;
763 1.207.4.2 pooka }
764 1.207.4.2 pooka fs = (struct fs*)bp->b_data;
765 1.207.4.2 pooka fsblockloc = sblockloc = sblock_try[i];
766 1.207.4.2 pooka if (fs->fs_magic == FS_UFS1_MAGIC) {
767 1.207.4.2 pooka sbsize = fs->fs_sbsize;
768 1.207.4.2 pooka fstype = UFS1;
769 1.207.4.2 pooka #ifdef FFS_EI
770 1.207.4.2 pooka needswap = 0;
771 1.207.4.2 pooka } else if (fs->fs_magic == bswap32(FS_UFS1_MAGIC)) {
772 1.207.4.2 pooka sbsize = bswap32(fs->fs_sbsize);
773 1.207.4.2 pooka fstype = UFS1;
774 1.207.4.2 pooka needswap = 1;
775 1.207.4.2 pooka #endif
776 1.207.4.2 pooka } else if (fs->fs_magic == FS_UFS2_MAGIC) {
777 1.207.4.2 pooka sbsize = fs->fs_sbsize;
778 1.207.4.2 pooka fstype = UFS2;
779 1.207.4.2 pooka #ifdef FFS_EI
780 1.207.4.2 pooka needswap = 0;
781 1.207.4.2 pooka } else if (fs->fs_magic == bswap32(FS_UFS2_MAGIC)) {
782 1.207.4.2 pooka sbsize = bswap32(fs->fs_sbsize);
783 1.207.4.2 pooka fstype = UFS2;
784 1.207.4.2 pooka needswap = 1;
785 1.207.4.2 pooka #endif
786 1.207.4.2 pooka } else
787 1.207.4.2 pooka continue;
788 1.207.4.2 pooka
789 1.207.4.2 pooka
790 1.207.4.2 pooka /* fs->fs_sblockloc isn't defined for old filesystems */
791 1.207.4.2 pooka if (fstype == UFS1 && !(fs->fs_old_flags & FS_FLAGS_UPDATED)) {
792 1.207.4.2 pooka if (sblockloc == SBLOCK_UFS2)
793 1.207.4.2 pooka /*
794 1.207.4.2 pooka * This is likely to be the first alternate
795 1.207.4.2 pooka * in a filesystem with 64k blocks.
796 1.207.4.2 pooka * Don't use it.
797 1.207.4.2 pooka */
798 1.207.4.2 pooka continue;
799 1.207.4.2 pooka fsblockloc = sblockloc;
800 1.207.4.2 pooka } else {
801 1.207.4.2 pooka fsblockloc = fs->fs_sblockloc;
802 1.207.4.2 pooka #ifdef FFS_EI
803 1.207.4.2 pooka if (needswap)
804 1.207.4.2 pooka fsblockloc = bswap64(fsblockloc);
805 1.207.4.2 pooka #endif
806 1.207.4.2 pooka }
807 1.207.4.2 pooka
808 1.207.4.2 pooka /* Check we haven't found an alternate superblock */
809 1.207.4.2 pooka if (fsblockloc != sblockloc)
810 1.207.4.2 pooka continue;
811 1.207.4.2 pooka
812 1.207.4.2 pooka /* Validate size of superblock */
813 1.207.4.2 pooka if (sbsize > MAXBSIZE || sbsize < sizeof(struct fs))
814 1.207.4.2 pooka continue;
815 1.207.4.2 pooka
816 1.207.4.2 pooka /* Ok seems to be a good superblock */
817 1.207.4.2 pooka break;
818 1.207.4.2 pooka }
819 1.207.4.2 pooka
820 1.207.4.2 pooka fs = malloc((u_long)sbsize, M_UFSMNT, M_WAITOK);
821 1.207.4.2 pooka memcpy(fs, bp->b_data, sbsize);
822 1.207.4.2 pooka
823 1.207.4.2 pooka ump = malloc(sizeof *ump, M_UFSMNT, M_WAITOK);
824 1.207.4.2 pooka memset(ump, 0, sizeof *ump);
825 1.207.4.2 pooka TAILQ_INIT(&ump->um_snapshots);
826 1.207.4.2 pooka ump->um_fs = fs;
827 1.207.4.2 pooka ump->um_ops = &ffs_ufsops;
828 1.207.4.2 pooka
829 1.207.4.2 pooka #ifdef FFS_EI
830 1.207.4.2 pooka if (needswap) {
831 1.207.4.2 pooka ffs_sb_swap((struct fs*)bp->b_data, fs);
832 1.207.4.2 pooka fs->fs_flags |= FS_SWAPPED;
833 1.207.4.2 pooka } else
834 1.207.4.2 pooka #endif
835 1.207.4.2 pooka fs->fs_flags &= ~FS_SWAPPED;
836 1.207.4.2 pooka
837 1.207.4.2 pooka ffs_oldfscompat_read(fs, ump, sblockloc);
838 1.207.4.2 pooka ump->um_maxfilesize = fs->fs_maxfilesize;
839 1.207.4.2 pooka
840 1.207.4.2 pooka if (fs->fs_pendingblocks != 0 || fs->fs_pendinginodes != 0) {
841 1.207.4.2 pooka fs->fs_pendingblocks = 0;
842 1.207.4.2 pooka fs->fs_pendinginodes = 0;
843 1.207.4.2 pooka }
844 1.207.4.2 pooka
845 1.207.4.2 pooka ump->um_fstype = fstype;
846 1.207.4.2 pooka if (fs->fs_sbsize < SBLOCKSIZE)
847 1.207.4.2 pooka bp->b_flags |= B_INVAL;
848 1.207.4.2 pooka brelse(bp);
849 1.207.4.2 pooka bp = NULL;
850 1.207.4.2 pooka
851 1.207.4.2 pooka /* First check to see if this is tagged as an Apple UFS filesystem
852 1.207.4.2 pooka * in the disklabel
853 1.207.4.2 pooka */
854 1.207.4.2 pooka if ((VOP_IOCTL(devvp, DIOCGPART, &dpart, FREAD, cred, l) == 0) &&
855 1.207.4.2 pooka (dpart.part->p_fstype == FS_APPLEUFS)) {
856 1.207.4.2 pooka ump->um_flags |= UFS_ISAPPLEUFS;
857 1.207.4.2 pooka }
858 1.207.4.2 pooka #ifdef APPLE_UFS
859 1.207.4.2 pooka else {
860 1.207.4.2 pooka /* Manually look for an apple ufs label, and if a valid one
861 1.207.4.2 pooka * is found, then treat it like an Apple UFS filesystem anyway
862 1.207.4.2 pooka */
863 1.207.4.2 pooka error = bread(devvp, (daddr_t)(APPLEUFS_LABEL_OFFSET / size),
864 1.207.4.2 pooka APPLEUFS_LABEL_SIZE, cred, &bp);
865 1.207.4.2 pooka if (error)
866 1.207.4.2 pooka goto out;
867 1.207.4.2 pooka error = ffs_appleufs_validate(fs->fs_fsmnt,
868 1.207.4.2 pooka (struct appleufslabel *)bp->b_data,NULL);
869 1.207.4.2 pooka if (error == 0) {
870 1.207.4.2 pooka ump->um_flags |= UFS_ISAPPLEUFS;
871 1.207.4.2 pooka }
872 1.207.4.2 pooka brelse(bp);
873 1.207.4.2 pooka bp = NULL;
874 1.207.4.2 pooka }
875 1.207.4.2 pooka #else
876 1.207.4.2 pooka if (ump->um_flags & UFS_ISAPPLEUFS) {
877 1.207.4.2 pooka error = EINVAL;
878 1.207.4.2 pooka goto out;
879 1.207.4.2 pooka }
880 1.207.4.2 pooka #endif
881 1.207.4.2 pooka
882 1.207.4.2 pooka /*
883 1.207.4.2 pooka * verify that we can access the last block in the fs
884 1.207.4.2 pooka * if we're mounting read/write.
885 1.207.4.2 pooka */
886 1.207.4.2 pooka
887 1.207.4.2 pooka if (!ronly) {
888 1.207.4.2 pooka error = bread(devvp, fsbtodb(fs, fs->fs_size - 1), fs->fs_fsize,
889 1.207.4.2 pooka cred, &bp);
890 1.207.4.2 pooka if (bp->b_bcount != fs->fs_fsize)
891 1.207.4.2 pooka error = EINVAL;
892 1.207.4.2 pooka bp->b_flags |= B_INVAL;
893 1.207.4.2 pooka if (error)
894 1.207.4.2 pooka goto out;
895 1.207.4.2 pooka brelse(bp);
896 1.207.4.2 pooka bp = NULL;
897 1.207.4.2 pooka }
898 1.207.4.2 pooka
899 1.207.4.2 pooka fs->fs_ronly = ronly;
900 1.207.4.2 pooka if (ronly == 0) {
901 1.207.4.2 pooka fs->fs_clean <<= 1;
902 1.207.4.2 pooka fs->fs_fmod = 1;
903 1.207.4.2 pooka }
904 1.207.4.2 pooka size = fs->fs_cssize;
905 1.207.4.2 pooka blks = howmany(size, fs->fs_fsize);
906 1.207.4.2 pooka if (fs->fs_contigsumsize > 0)
907 1.207.4.2 pooka size += fs->fs_ncg * sizeof(int32_t);
908 1.207.4.2 pooka size += fs->fs_ncg * sizeof(*fs->fs_contigdirs);
909 1.207.4.2 pooka space = malloc((u_long)size, M_UFSMNT, M_WAITOK);
910 1.207.4.2 pooka fs->fs_csp = space;
911 1.207.4.2 pooka for (i = 0; i < blks; i += fs->fs_frag) {
912 1.207.4.2 pooka size = fs->fs_bsize;
913 1.207.4.2 pooka if (i + fs->fs_frag > blks)
914 1.207.4.2 pooka size = (blks - i) * fs->fs_fsize;
915 1.207.4.2 pooka error = bread(devvp, fsbtodb(fs, fs->fs_csaddr + i), size,
916 1.207.4.2 pooka cred, &bp);
917 1.207.4.2 pooka if (error) {
918 1.207.4.2 pooka free(fs->fs_csp, M_UFSMNT);
919 1.207.4.2 pooka goto out;
920 1.207.4.2 pooka }
921 1.207.4.2 pooka #ifdef FFS_EI
922 1.207.4.2 pooka if (needswap)
923 1.207.4.2 pooka ffs_csum_swap((struct csum *)bp->b_data,
924 1.207.4.2 pooka (struct csum *)space, size);
925 1.207.4.2 pooka else
926 1.207.4.2 pooka #endif
927 1.207.4.2 pooka memcpy(space, bp->b_data, (u_int)size);
928 1.207.4.2 pooka
929 1.207.4.2 pooka space = (char *)space + size;
930 1.207.4.2 pooka brelse(bp);
931 1.207.4.2 pooka bp = NULL;
932 1.207.4.2 pooka }
933 1.207.4.2 pooka if (fs->fs_contigsumsize > 0) {
934 1.207.4.2 pooka fs->fs_maxcluster = lp = space;
935 1.207.4.2 pooka for (i = 0; i < fs->fs_ncg; i++)
936 1.207.4.2 pooka *lp++ = fs->fs_contigsumsize;
937 1.207.4.2 pooka space = lp;
938 1.207.4.2 pooka }
939 1.207.4.2 pooka size = fs->fs_ncg * sizeof(*fs->fs_contigdirs);
940 1.207.4.2 pooka fs->fs_contigdirs = space;
941 1.207.4.2 pooka space = (char *)space + size;
942 1.207.4.2 pooka memset(fs->fs_contigdirs, 0, size);
943 1.207.4.2 pooka /* Compatibility for old filesystems - XXX */
944 1.207.4.2 pooka if (fs->fs_avgfilesize <= 0)
945 1.207.4.2 pooka fs->fs_avgfilesize = AVFILESIZ;
946 1.207.4.2 pooka if (fs->fs_avgfpdir <= 0)
947 1.207.4.2 pooka fs->fs_avgfpdir = AFPDIR;
948 1.207.4.2 pooka fs->fs_active = NULL;
949 1.207.4.2 pooka mp->mnt_data = ump;
950 1.207.4.2 pooka mp->mnt_stat.f_fsidx.__fsid_val[0] = (long)dev;
951 1.207.4.2 pooka mp->mnt_stat.f_fsidx.__fsid_val[1] = makefstype(MOUNT_FFS);
952 1.207.4.2 pooka mp->mnt_stat.f_fsid = mp->mnt_stat.f_fsidx.__fsid_val[0];
953 1.207.4.2 pooka mp->mnt_stat.f_namemax = FFS_MAXNAMLEN;
954 1.207.4.2 pooka if (UFS_MPISAPPLEUFS(ump)) {
955 1.207.4.2 pooka /* NeXT used to keep short symlinks in the inode even
956 1.207.4.2 pooka * when using FS_42INODEFMT. In that case fs->fs_maxsymlinklen
957 1.207.4.2 pooka * is probably -1, but we still need to be able to identify
958 1.207.4.2 pooka * short symlinks.
959 1.207.4.2 pooka */
960 1.207.4.2 pooka ump->um_maxsymlinklen = APPLEUFS_MAXSYMLINKLEN;
961 1.207.4.2 pooka ump->um_dirblksiz = APPLEUFS_DIRBLKSIZ;
962 1.207.4.2 pooka mp->mnt_iflag |= IMNT_DTYPE;
963 1.207.4.2 pooka } else {
964 1.207.4.2 pooka ump->um_maxsymlinklen = fs->fs_maxsymlinklen;
965 1.207.4.2 pooka ump->um_dirblksiz = DIRBLKSIZ;
966 1.207.4.2 pooka if (ump->um_maxsymlinklen > 0)
967 1.207.4.2 pooka mp->mnt_iflag |= IMNT_DTYPE;
968 1.207.4.2 pooka else
969 1.207.4.2 pooka mp->mnt_iflag &= ~IMNT_DTYPE;
970 1.207.4.2 pooka }
971 1.207.4.2 pooka mp->mnt_fs_bshift = fs->fs_bshift;
972 1.207.4.2 pooka mp->mnt_dev_bshift = DEV_BSHIFT; /* XXX */
973 1.207.4.2 pooka mp->mnt_flag |= MNT_LOCAL;
974 1.207.4.2 pooka mp->mnt_iflag |= IMNT_HAS_TRANS;
975 1.207.4.2 pooka #ifdef FFS_EI
976 1.207.4.2 pooka if (needswap)
977 1.207.4.2 pooka ump->um_flags |= UFS_NEEDSWAP;
978 1.207.4.2 pooka #endif
979 1.207.4.2 pooka ump->um_mountp = mp;
980 1.207.4.2 pooka ump->um_dev = dev;
981 1.207.4.2 pooka ump->um_devvp = devvp;
982 1.207.4.2 pooka ump->um_nindir = fs->fs_nindir;
983 1.207.4.2 pooka ump->um_lognindir = ffs(fs->fs_nindir) - 1;
984 1.207.4.2 pooka ump->um_bptrtodb = fs->fs_fsbtodb;
985 1.207.4.2 pooka ump->um_seqinc = fs->fs_frag;
986 1.207.4.2 pooka for (i = 0; i < MAXQUOTAS; i++)
987 1.207.4.2 pooka ump->um_quotas[i] = NULLVP;
988 1.207.4.2 pooka devvp->v_specmountpoint = mp;
989 1.207.4.2 pooka if (ronly == 0 && (fs->fs_flags & FS_DOSOFTDEP)) {
990 1.207.4.2 pooka error = softdep_mount(devvp, mp, fs, cred);
991 1.207.4.2 pooka if (error) {
992 1.207.4.2 pooka free(fs->fs_csp, M_UFSMNT);
993 1.207.4.2 pooka goto out;
994 1.207.4.2 pooka }
995 1.207.4.2 pooka }
996 1.207.4.2 pooka if (ronly == 0 && fs->fs_snapinum[0] != 0)
997 1.207.4.2 pooka ffs_snapshot_mount(mp);
998 1.207.4.2 pooka #ifdef UFS_EXTATTR
999 1.207.4.2 pooka /*
1000 1.207.4.2 pooka * Initialize file-backed extended attributes on UFS1 file
1001 1.207.4.2 pooka * systems.
1002 1.207.4.2 pooka */
1003 1.207.4.2 pooka if (ump->um_fstype == UFS1) {
1004 1.207.4.2 pooka ufs_extattr_uepm_init(&ump->um_extattr);
1005 1.207.4.2 pooka #ifdef UFS_EXTATTR_AUTOSTART
1006 1.207.4.2 pooka /*
1007 1.207.4.2 pooka * XXX Just ignore errors. Not clear that we should
1008 1.207.4.2 pooka * XXX fail the mount in this case.
1009 1.207.4.2 pooka */
1010 1.207.4.2 pooka (void) ufs_extattr_autostart(mp, l);
1011 1.207.4.2 pooka #endif
1012 1.207.4.2 pooka }
1013 1.207.4.2 pooka #endif /* UFS_EXTATTR */
1014 1.207.4.2 pooka return (0);
1015 1.207.4.2 pooka out:
1016 1.207.4.2 pooka if (fs)
1017 1.207.4.2 pooka free(fs, M_UFSMNT);
1018 1.207.4.2 pooka devvp->v_specmountpoint = NULL;
1019 1.207.4.2 pooka if (bp)
1020 1.207.4.2 pooka brelse(bp);
1021 1.207.4.2 pooka if (ump) {
1022 1.207.4.2 pooka if (ump->um_oldfscompat)
1023 1.207.4.2 pooka free(ump->um_oldfscompat, M_UFSMNT);
1024 1.207.4.2 pooka free(ump, M_UFSMNT);
1025 1.207.4.2 pooka mp->mnt_data = NULL;
1026 1.207.4.2 pooka }
1027 1.207.4.2 pooka return (error);
1028 1.207.4.2 pooka }
1029 1.207.4.2 pooka
1030 1.207.4.2 pooka /*
1031 1.207.4.2 pooka * Sanity checks for loading old filesystem superblocks.
1032 1.207.4.2 pooka * See ffs_oldfscompat_write below for unwound actions.
1033 1.207.4.2 pooka *
1034 1.207.4.2 pooka * XXX - Parts get retired eventually.
1035 1.207.4.2 pooka * Unfortunately new bits get added.
1036 1.207.4.2 pooka */
1037 1.207.4.2 pooka static void
1038 1.207.4.2 pooka ffs_oldfscompat_read(struct fs *fs, struct ufsmount *ump, daddr_t sblockloc)
1039 1.207.4.2 pooka {
1040 1.207.4.2 pooka off_t maxfilesize;
1041 1.207.4.2 pooka int32_t *extrasave;
1042 1.207.4.2 pooka
1043 1.207.4.2 pooka if ((fs->fs_magic != FS_UFS1_MAGIC) ||
1044 1.207.4.2 pooka (fs->fs_old_flags & FS_FLAGS_UPDATED))
1045 1.207.4.2 pooka return;
1046 1.207.4.2 pooka
1047 1.207.4.2 pooka if (!ump->um_oldfscompat)
1048 1.207.4.2 pooka ump->um_oldfscompat = malloc(512 + 3*sizeof(int32_t),
1049 1.207.4.2 pooka M_UFSMNT, M_WAITOK);
1050 1.207.4.2 pooka
1051 1.207.4.2 pooka memcpy(ump->um_oldfscompat, &fs->fs_old_postbl_start, 512);
1052 1.207.4.2 pooka extrasave = ump->um_oldfscompat;
1053 1.207.4.2 pooka extrasave += 512/sizeof(int32_t);
1054 1.207.4.2 pooka extrasave[0] = fs->fs_old_npsect;
1055 1.207.4.2 pooka extrasave[1] = fs->fs_old_interleave;
1056 1.207.4.2 pooka extrasave[2] = fs->fs_old_trackskew;
1057 1.207.4.2 pooka
1058 1.207.4.2 pooka /* These fields will be overwritten by their
1059 1.207.4.2 pooka * original values in fs_oldfscompat_write, so it is harmless
1060 1.207.4.2 pooka * to modify them here.
1061 1.207.4.2 pooka */
1062 1.207.4.2 pooka fs->fs_cstotal.cs_ndir = fs->fs_old_cstotal.cs_ndir;
1063 1.207.4.2 pooka fs->fs_cstotal.cs_nbfree = fs->fs_old_cstotal.cs_nbfree;
1064 1.207.4.2 pooka fs->fs_cstotal.cs_nifree = fs->fs_old_cstotal.cs_nifree;
1065 1.207.4.2 pooka fs->fs_cstotal.cs_nffree = fs->fs_old_cstotal.cs_nffree;
1066 1.207.4.2 pooka
1067 1.207.4.2 pooka fs->fs_maxbsize = fs->fs_bsize;
1068 1.207.4.2 pooka fs->fs_time = fs->fs_old_time;
1069 1.207.4.2 pooka fs->fs_size = fs->fs_old_size;
1070 1.207.4.2 pooka fs->fs_dsize = fs->fs_old_dsize;
1071 1.207.4.2 pooka fs->fs_csaddr = fs->fs_old_csaddr;
1072 1.207.4.2 pooka fs->fs_sblockloc = sblockloc;
1073 1.207.4.2 pooka
1074 1.207.4.2 pooka fs->fs_flags = fs->fs_old_flags | (fs->fs_flags & FS_INTERNAL);
1075 1.207.4.2 pooka
1076 1.207.4.2 pooka if (fs->fs_old_postblformat == FS_42POSTBLFMT) {
1077 1.207.4.2 pooka fs->fs_old_nrpos = 8;
1078 1.207.4.2 pooka fs->fs_old_npsect = fs->fs_old_nsect;
1079 1.207.4.2 pooka fs->fs_old_interleave = 1;
1080 1.207.4.2 pooka fs->fs_old_trackskew = 0;
1081 1.207.4.2 pooka }
1082 1.207.4.2 pooka
1083 1.207.4.2 pooka if (fs->fs_old_inodefmt < FS_44INODEFMT) {
1084 1.207.4.2 pooka fs->fs_maxfilesize = (u_quad_t) 1LL << 39;
1085 1.207.4.2 pooka fs->fs_qbmask = ~fs->fs_bmask;
1086 1.207.4.2 pooka fs->fs_qfmask = ~fs->fs_fmask;
1087 1.207.4.2 pooka }
1088 1.207.4.2 pooka
1089 1.207.4.2 pooka maxfilesize = (u_int64_t)0x80000000 * fs->fs_bsize - 1;
1090 1.207.4.2 pooka if (fs->fs_maxfilesize > maxfilesize)
1091 1.207.4.2 pooka fs->fs_maxfilesize = maxfilesize;
1092 1.207.4.2 pooka
1093 1.207.4.2 pooka /* Compatibility for old filesystems */
1094 1.207.4.2 pooka if (fs->fs_avgfilesize <= 0)
1095 1.207.4.2 pooka fs->fs_avgfilesize = AVFILESIZ;
1096 1.207.4.2 pooka if (fs->fs_avgfpdir <= 0)
1097 1.207.4.2 pooka fs->fs_avgfpdir = AFPDIR;
1098 1.207.4.2 pooka
1099 1.207.4.2 pooka #if 0
1100 1.207.4.2 pooka if (bigcgs) {
1101 1.207.4.2 pooka fs->fs_save_cgsize = fs->fs_cgsize;
1102 1.207.4.2 pooka fs->fs_cgsize = fs->fs_bsize;
1103 1.207.4.2 pooka }
1104 1.207.4.2 pooka #endif
1105 1.207.4.2 pooka }
1106 1.207.4.2 pooka
1107 1.207.4.2 pooka /*
1108 1.207.4.2 pooka * Unwinding superblock updates for old filesystems.
1109 1.207.4.2 pooka * See ffs_oldfscompat_read above for details.
1110 1.207.4.2 pooka *
1111 1.207.4.2 pooka * XXX - Parts get retired eventually.
1112 1.207.4.2 pooka * Unfortunately new bits get added.
1113 1.207.4.2 pooka */
1114 1.207.4.2 pooka static void
1115 1.207.4.2 pooka ffs_oldfscompat_write(struct fs *fs, struct ufsmount *ump)
1116 1.207.4.2 pooka {
1117 1.207.4.2 pooka int32_t *extrasave;
1118 1.207.4.2 pooka
1119 1.207.4.2 pooka if ((fs->fs_magic != FS_UFS1_MAGIC) ||
1120 1.207.4.2 pooka (fs->fs_old_flags & FS_FLAGS_UPDATED))
1121 1.207.4.2 pooka return;
1122 1.207.4.2 pooka
1123 1.207.4.2 pooka fs->fs_old_time = fs->fs_time;
1124 1.207.4.2 pooka fs->fs_old_cstotal.cs_ndir = fs->fs_cstotal.cs_ndir;
1125 1.207.4.2 pooka fs->fs_old_cstotal.cs_nbfree = fs->fs_cstotal.cs_nbfree;
1126 1.207.4.2 pooka fs->fs_old_cstotal.cs_nifree = fs->fs_cstotal.cs_nifree;
1127 1.207.4.2 pooka fs->fs_old_cstotal.cs_nffree = fs->fs_cstotal.cs_nffree;
1128 1.207.4.2 pooka fs->fs_old_flags = fs->fs_flags;
1129 1.207.4.2 pooka
1130 1.207.4.2 pooka #if 0
1131 1.207.4.2 pooka if (bigcgs) {
1132 1.207.4.2 pooka fs->fs_cgsize = fs->fs_save_cgsize;
1133 1.207.4.2 pooka }
1134 1.207.4.2 pooka #endif
1135 1.207.4.2 pooka
1136 1.207.4.2 pooka memcpy(&fs->fs_old_postbl_start, ump->um_oldfscompat, 512);
1137 1.207.4.2 pooka extrasave = ump->um_oldfscompat;
1138 1.207.4.2 pooka extrasave += 512/sizeof(int32_t);
1139 1.207.4.2 pooka fs->fs_old_npsect = extrasave[0];
1140 1.207.4.2 pooka fs->fs_old_interleave = extrasave[1];
1141 1.207.4.2 pooka fs->fs_old_trackskew = extrasave[2];
1142 1.207.4.2 pooka
1143 1.207.4.2 pooka }
1144 1.207.4.2 pooka
1145 1.207.4.2 pooka /*
1146 1.207.4.2 pooka * unmount system call
1147 1.207.4.2 pooka */
1148 1.207.4.2 pooka int
1149 1.207.4.2 pooka ffs_unmount(struct mount *mp, int mntflags, struct lwp *l)
1150 1.207.4.2 pooka {
1151 1.207.4.2 pooka struct ufsmount *ump = VFSTOUFS(mp);
1152 1.207.4.2 pooka struct fs *fs = ump->um_fs;
1153 1.207.4.2 pooka int error, flags, penderr;
1154 1.207.4.2 pooka
1155 1.207.4.2 pooka penderr = 0;
1156 1.207.4.2 pooka flags = 0;
1157 1.207.4.2 pooka if (mntflags & MNT_FORCE)
1158 1.207.4.2 pooka flags |= FORCECLOSE;
1159 1.207.4.2 pooka #ifdef UFS_EXTATTR
1160 1.207.4.2 pooka if (ump->um_fstype == UFS1) {
1161 1.207.4.2 pooka error = ufs_extattr_stop(mp, l);
1162 1.207.4.2 pooka if (error) {
1163 1.207.4.2 pooka if (error != EOPNOTSUPP)
1164 1.207.4.2 pooka printf("%s: ufs_extattr_stop returned %d\n",
1165 1.207.4.2 pooka fs->fs_fsmnt, error);
1166 1.207.4.2 pooka } else
1167 1.207.4.2 pooka ufs_extattr_uepm_destroy(&ump->um_extattr);
1168 1.207.4.2 pooka }
1169 1.207.4.2 pooka #endif /* UFS_EXTATTR */
1170 1.207.4.2 pooka if (mp->mnt_flag & MNT_SOFTDEP) {
1171 1.207.4.2 pooka if ((error = softdep_flushfiles(mp, flags, l)) != 0)
1172 1.207.4.2 pooka return (error);
1173 1.207.4.2 pooka } else {
1174 1.207.4.2 pooka if ((error = ffs_flushfiles(mp, flags, l)) != 0)
1175 1.207.4.2 pooka return (error);
1176 1.207.4.2 pooka }
1177 1.207.4.2 pooka if (fs->fs_pendingblocks != 0 || fs->fs_pendinginodes != 0) {
1178 1.207.4.2 pooka printf("%s: unmount pending error: blocks %" PRId64
1179 1.207.4.2 pooka " files %d\n",
1180 1.207.4.2 pooka fs->fs_fsmnt, fs->fs_pendingblocks, fs->fs_pendinginodes);
1181 1.207.4.2 pooka fs->fs_pendingblocks = 0;
1182 1.207.4.2 pooka fs->fs_pendinginodes = 0;
1183 1.207.4.2 pooka penderr = 1;
1184 1.207.4.2 pooka }
1185 1.207.4.2 pooka if (fs->fs_ronly == 0 &&
1186 1.207.4.2 pooka ffs_cgupdate(ump, MNT_WAIT) == 0 &&
1187 1.207.4.2 pooka fs->fs_clean & FS_WASCLEAN) {
1188 1.207.4.2 pooka /*
1189 1.207.4.2 pooka * XXXX don't mark fs clean in the case of softdep
1190 1.207.4.2 pooka * pending block errors, until they are fixed.
1191 1.207.4.2 pooka */
1192 1.207.4.2 pooka if (penderr == 0) {
1193 1.207.4.2 pooka if (mp->mnt_flag & MNT_SOFTDEP)
1194 1.207.4.2 pooka fs->fs_flags &= ~FS_DOSOFTDEP;
1195 1.207.4.2 pooka fs->fs_clean = FS_ISCLEAN;
1196 1.207.4.2 pooka }
1197 1.207.4.2 pooka fs->fs_fmod = 0;
1198 1.207.4.2 pooka (void) ffs_sbupdate(ump, MNT_WAIT);
1199 1.207.4.2 pooka }
1200 1.207.4.2 pooka if (ump->um_devvp->v_type != VBAD)
1201 1.207.4.2 pooka ump->um_devvp->v_specmountpoint = NULL;
1202 1.207.4.2 pooka vn_lock(ump->um_devvp, LK_EXCLUSIVE | LK_RETRY);
1203 1.207.4.2 pooka (void)VOP_CLOSE(ump->um_devvp, fs->fs_ronly ? FREAD : FREAD|FWRITE,
1204 1.207.4.2 pooka NOCRED, l);
1205 1.207.4.2 pooka vput(ump->um_devvp);
1206 1.207.4.2 pooka free(fs->fs_csp, M_UFSMNT);
1207 1.207.4.2 pooka free(fs, M_UFSMNT);
1208 1.207.4.2 pooka if (ump->um_oldfscompat != NULL)
1209 1.207.4.2 pooka free(ump->um_oldfscompat, M_UFSMNT);
1210 1.207.4.2 pooka free(ump, M_UFSMNT);
1211 1.207.4.2 pooka mp->mnt_data = NULL;
1212 1.207.4.2 pooka mp->mnt_flag &= ~MNT_LOCAL;
1213 1.207.4.2 pooka return (0);
1214 1.207.4.2 pooka }
1215 1.207.4.2 pooka
1216 1.207.4.2 pooka /*
1217 1.207.4.2 pooka * Flush out all the files in a filesystem.
1218 1.207.4.2 pooka */
1219 1.207.4.2 pooka int
1220 1.207.4.2 pooka ffs_flushfiles(struct mount *mp, int flags, struct lwp *l)
1221 1.207.4.2 pooka {
1222 1.207.4.2 pooka extern int doforce;
1223 1.207.4.2 pooka struct ufsmount *ump;
1224 1.207.4.2 pooka int error;
1225 1.207.4.2 pooka
1226 1.207.4.2 pooka if (!doforce)
1227 1.207.4.2 pooka flags &= ~FORCECLOSE;
1228 1.207.4.2 pooka ump = VFSTOUFS(mp);
1229 1.207.4.2 pooka #ifdef QUOTA
1230 1.207.4.2 pooka if (mp->mnt_flag & MNT_QUOTA) {
1231 1.207.4.2 pooka int i;
1232 1.207.4.2 pooka if ((error = vflush(mp, NULLVP, SKIPSYSTEM|flags)) != 0)
1233 1.207.4.2 pooka return (error);
1234 1.207.4.2 pooka for (i = 0; i < MAXQUOTAS; i++) {
1235 1.207.4.2 pooka if (ump->um_quotas[i] == NULLVP)
1236 1.207.4.2 pooka continue;
1237 1.207.4.2 pooka quotaoff(l, mp, i);
1238 1.207.4.2 pooka }
1239 1.207.4.2 pooka /*
1240 1.207.4.2 pooka * Here we fall through to vflush again to ensure
1241 1.207.4.2 pooka * that we have gotten rid of all the system vnodes.
1242 1.207.4.2 pooka */
1243 1.207.4.2 pooka }
1244 1.207.4.2 pooka #endif
1245 1.207.4.2 pooka if ((error = vflush(mp, 0, SKIPSYSTEM | flags)) != 0)
1246 1.207.4.2 pooka return (error);
1247 1.207.4.2 pooka ffs_snapshot_unmount(mp);
1248 1.207.4.2 pooka /*
1249 1.207.4.2 pooka * Flush all the files.
1250 1.207.4.2 pooka */
1251 1.207.4.2 pooka error = vflush(mp, NULLVP, flags);
1252 1.207.4.2 pooka if (error)
1253 1.207.4.2 pooka return (error);
1254 1.207.4.2 pooka /*
1255 1.207.4.2 pooka * Flush filesystem metadata.
1256 1.207.4.2 pooka */
1257 1.207.4.2 pooka vn_lock(ump->um_devvp, LK_EXCLUSIVE | LK_RETRY);
1258 1.207.4.2 pooka error = VOP_FSYNC(ump->um_devvp, l->l_cred, FSYNC_WAIT, 0, 0, l);
1259 1.207.4.2 pooka VOP_UNLOCK(ump->um_devvp, 0);
1260 1.207.4.2 pooka return (error);
1261 1.207.4.2 pooka }
1262 1.207.4.2 pooka
1263 1.207.4.2 pooka /*
1264 1.207.4.2 pooka * Get file system statistics.
1265 1.207.4.2 pooka */
1266 1.207.4.2 pooka int
1267 1.207.4.2 pooka ffs_statvfs(struct mount *mp, struct statvfs *sbp, struct lwp *l)
1268 1.207.4.2 pooka {
1269 1.207.4.2 pooka struct ufsmount *ump;
1270 1.207.4.2 pooka struct fs *fs;
1271 1.207.4.2 pooka
1272 1.207.4.2 pooka ump = VFSTOUFS(mp);
1273 1.207.4.2 pooka fs = ump->um_fs;
1274 1.207.4.2 pooka sbp->f_bsize = fs->fs_bsize;
1275 1.207.4.2 pooka sbp->f_frsize = fs->fs_fsize;
1276 1.207.4.2 pooka sbp->f_iosize = fs->fs_bsize;
1277 1.207.4.2 pooka sbp->f_blocks = fs->fs_dsize;
1278 1.207.4.2 pooka sbp->f_bfree = blkstofrags(fs, fs->fs_cstotal.cs_nbfree) +
1279 1.207.4.2 pooka fs->fs_cstotal.cs_nffree + dbtofsb(fs, fs->fs_pendingblocks);
1280 1.207.4.2 pooka sbp->f_bresvd = ((u_int64_t) fs->fs_dsize * (u_int64_t)
1281 1.207.4.2 pooka fs->fs_minfree) / (u_int64_t) 100;
1282 1.207.4.2 pooka if (sbp->f_bfree > sbp->f_bresvd)
1283 1.207.4.2 pooka sbp->f_bavail = sbp->f_bfree - sbp->f_bresvd;
1284 1.207.4.2 pooka else
1285 1.207.4.2 pooka sbp->f_bavail = 0;
1286 1.207.4.2 pooka sbp->f_files = fs->fs_ncg * fs->fs_ipg - ROOTINO;
1287 1.207.4.2 pooka sbp->f_ffree = fs->fs_cstotal.cs_nifree + fs->fs_pendinginodes;
1288 1.207.4.2 pooka sbp->f_favail = sbp->f_ffree;
1289 1.207.4.2 pooka sbp->f_fresvd = 0;
1290 1.207.4.2 pooka copy_statvfs_info(sbp, mp);
1291 1.207.4.2 pooka return (0);
1292 1.207.4.2 pooka }
1293 1.207.4.2 pooka
1294 1.207.4.2 pooka /*
1295 1.207.4.2 pooka * Go through the disk queues to initiate sandbagged IO;
1296 1.207.4.2 pooka * go through the inodes to write those that have been modified;
1297 1.207.4.2 pooka * initiate the writing of the super block if it has been modified.
1298 1.207.4.2 pooka *
1299 1.207.4.2 pooka * Note: we are always called with the filesystem marked `MPBUSY'.
1300 1.207.4.2 pooka */
1301 1.207.4.2 pooka int
1302 1.207.4.2 pooka ffs_sync(struct mount *mp, int waitfor, kauth_cred_t cred, struct lwp *l)
1303 1.207.4.2 pooka {
1304 1.207.4.2 pooka struct vnode *vp, *nvp;
1305 1.207.4.2 pooka struct inode *ip;
1306 1.207.4.2 pooka struct ufsmount *ump = VFSTOUFS(mp);
1307 1.207.4.2 pooka struct fs *fs;
1308 1.207.4.2 pooka int error, count, allerror = 0;
1309 1.207.4.2 pooka
1310 1.207.4.2 pooka fs = ump->um_fs;
1311 1.207.4.2 pooka if (fs->fs_fmod != 0 && fs->fs_ronly != 0) { /* XXX */
1312 1.207.4.2 pooka printf("fs = %s\n", fs->fs_fsmnt);
1313 1.207.4.2 pooka panic("update: rofs mod");
1314 1.207.4.2 pooka }
1315 1.207.4.2 pooka fstrans_start(mp, FSTRANS_SHARED);
1316 1.207.4.2 pooka /*
1317 1.207.4.2 pooka * Write back each (modified) inode.
1318 1.207.4.2 pooka */
1319 1.207.4.2 pooka simple_lock(&mntvnode_slock);
1320 1.207.4.2 pooka loop:
1321 1.207.4.2 pooka /*
1322 1.207.4.2 pooka * NOTE: not using the TAILQ_FOREACH here since in this loop vgone()
1323 1.207.4.2 pooka * and vclean() can be called indirectly
1324 1.207.4.2 pooka */
1325 1.207.4.2 pooka for (vp = TAILQ_FIRST(&mp->mnt_vnodelist); vp; vp = nvp) {
1326 1.207.4.2 pooka /*
1327 1.207.4.2 pooka * If the vnode that we are about to sync is no longer
1328 1.207.4.2 pooka * associated with this mount point, start over.
1329 1.207.4.2 pooka */
1330 1.207.4.2 pooka if (vp->v_mount != mp)
1331 1.207.4.2 pooka goto loop;
1332 1.207.4.2 pooka simple_lock(&vp->v_interlock);
1333 1.207.4.2 pooka nvp = TAILQ_NEXT(vp, v_mntvnodes);
1334 1.207.4.2 pooka ip = VTOI(vp);
1335 1.207.4.2 pooka if (vp->v_type == VNON ||
1336 1.207.4.2 pooka ((ip->i_flag &
1337 1.207.4.2 pooka (IN_CHANGE | IN_UPDATE | IN_MODIFIED)) == 0 &&
1338 1.207.4.2 pooka LIST_EMPTY(&vp->v_dirtyblkhd) &&
1339 1.207.4.2 pooka UVM_OBJ_IS_CLEAN(&vp->v_uobj)))
1340 1.207.4.2 pooka {
1341 1.207.4.2 pooka simple_unlock(&vp->v_interlock);
1342 1.207.4.2 pooka continue;
1343 1.207.4.2 pooka }
1344 1.207.4.2 pooka if (vp->v_type == VBLK &&
1345 1.207.4.2 pooka fstrans_getstate(mp) == FSTRANS_SUSPENDING) {
1346 1.207.4.2 pooka simple_unlock(&vp->v_interlock);
1347 1.207.4.2 pooka continue;
1348 1.207.4.2 pooka }
1349 1.207.4.2 pooka simple_unlock(&mntvnode_slock);
1350 1.207.4.2 pooka error = vget(vp, LK_EXCLUSIVE | LK_NOWAIT | LK_INTERLOCK);
1351 1.207.4.2 pooka if (error) {
1352 1.207.4.2 pooka simple_lock(&mntvnode_slock);
1353 1.207.4.2 pooka if (error == ENOENT)
1354 1.207.4.2 pooka goto loop;
1355 1.207.4.2 pooka continue;
1356 1.207.4.2 pooka }
1357 1.207.4.2 pooka if (vp->v_type == VREG && waitfor == MNT_LAZY)
1358 1.207.4.2 pooka error = ffs_update(vp, NULL, NULL, 0);
1359 1.207.4.2 pooka else
1360 1.207.4.2 pooka error = VOP_FSYNC(vp, cred,
1361 1.207.4.2 pooka waitfor == MNT_WAIT ? FSYNC_WAIT : 0, 0, 0, l);
1362 1.207.4.2 pooka if (error)
1363 1.207.4.2 pooka allerror = error;
1364 1.207.4.2 pooka vput(vp);
1365 1.207.4.2 pooka simple_lock(&mntvnode_slock);
1366 1.207.4.2 pooka }
1367 1.207.4.2 pooka simple_unlock(&mntvnode_slock);
1368 1.207.4.2 pooka /*
1369 1.207.4.2 pooka * Force stale file system control information to be flushed.
1370 1.207.4.2 pooka */
1371 1.207.4.2 pooka if (waitfor == MNT_WAIT && (ump->um_mountp->mnt_flag & MNT_SOFTDEP)) {
1372 1.207.4.2 pooka if ((error = softdep_flushworklist(ump->um_mountp, &count, l)))
1373 1.207.4.2 pooka allerror = error;
1374 1.207.4.2 pooka /* Flushed work items may create new vnodes to clean */
1375 1.207.4.2 pooka if (allerror == 0 && count) {
1376 1.207.4.2 pooka simple_lock(&mntvnode_slock);
1377 1.207.4.2 pooka goto loop;
1378 1.207.4.2 pooka }
1379 1.207.4.2 pooka }
1380 1.207.4.2 pooka if (waitfor != MNT_LAZY && (ump->um_devvp->v_numoutput > 0 ||
1381 1.207.4.2 pooka !LIST_EMPTY(&ump->um_devvp->v_dirtyblkhd))) {
1382 1.207.4.2 pooka vn_lock(ump->um_devvp, LK_EXCLUSIVE | LK_RETRY);
1383 1.207.4.2 pooka if ((error = VOP_FSYNC(ump->um_devvp, cred,
1384 1.207.4.2 pooka waitfor == MNT_WAIT ? FSYNC_WAIT : 0, 0, 0, l)) != 0)
1385 1.207.4.2 pooka allerror = error;
1386 1.207.4.2 pooka VOP_UNLOCK(ump->um_devvp, 0);
1387 1.207.4.2 pooka if (allerror == 0 && waitfor == MNT_WAIT) {
1388 1.207.4.2 pooka simple_lock(&mntvnode_slock);
1389 1.207.4.2 pooka goto loop;
1390 1.207.4.2 pooka }
1391 1.207.4.2 pooka }
1392 1.207.4.2 pooka #ifdef QUOTA
1393 1.207.4.2 pooka qsync(mp);
1394 1.207.4.2 pooka #endif
1395 1.207.4.2 pooka /*
1396 1.207.4.2 pooka * Write back modified superblock.
1397 1.207.4.2 pooka */
1398 1.207.4.2 pooka if (fs->fs_fmod != 0) {
1399 1.207.4.2 pooka fs->fs_fmod = 0;
1400 1.207.4.2 pooka fs->fs_time = time_second;
1401 1.207.4.2 pooka if ((error = ffs_cgupdate(ump, waitfor)))
1402 1.207.4.2 pooka allerror = error;
1403 1.207.4.2 pooka }
1404 1.207.4.2 pooka fstrans_done(mp);
1405 1.207.4.2 pooka return (allerror);
1406 1.207.4.2 pooka }
1407 1.207.4.2 pooka
1408 1.207.4.2 pooka /*
1409 1.207.4.2 pooka * Look up a FFS dinode number to find its incore vnode, otherwise read it
1410 1.207.4.2 pooka * in from disk. If it is in core, wait for the lock bit to clear, then
1411 1.207.4.2 pooka * return the inode locked. Detection and handling of mount points must be
1412 1.207.4.2 pooka * done by the calling routine.
1413 1.207.4.2 pooka */
1414 1.207.4.2 pooka int
1415 1.207.4.2 pooka ffs_vget(struct mount *mp, ino_t ino, struct vnode **vpp)
1416 1.207.4.2 pooka {
1417 1.207.4.2 pooka struct fs *fs;
1418 1.207.4.2 pooka struct inode *ip;
1419 1.207.4.2 pooka struct ufsmount *ump;
1420 1.207.4.2 pooka struct buf *bp;
1421 1.207.4.2 pooka struct vnode *vp;
1422 1.207.4.2 pooka dev_t dev;
1423 1.207.4.2 pooka int error;
1424 1.207.4.2 pooka
1425 1.207.4.2 pooka ump = VFSTOUFS(mp);
1426 1.207.4.2 pooka dev = ump->um_dev;
1427 1.207.4.2 pooka
1428 1.207.4.2 pooka retry:
1429 1.207.4.2 pooka if ((*vpp = ufs_ihashget(dev, ino, LK_EXCLUSIVE)) != NULL)
1430 1.207.4.2 pooka return (0);
1431 1.207.4.2 pooka
1432 1.207.4.2 pooka /* Allocate a new vnode/inode. */
1433 1.207.4.2 pooka if ((error = getnewvnode(VT_UFS, mp, ffs_vnodeop_p, &vp)) != 0) {
1434 1.207.4.2 pooka *vpp = NULL;
1435 1.207.4.2 pooka return (error);
1436 1.207.4.2 pooka }
1437 1.207.4.2 pooka ip = pool_get(&ffs_inode_pool, PR_WAITOK);
1438 1.207.4.2 pooka
1439 1.207.4.2 pooka /*
1440 1.207.4.2 pooka * If someone beat us to it, put back the freshly allocated
1441 1.207.4.2 pooka * vnode/inode pair and retry.
1442 1.207.4.2 pooka */
1443 1.207.4.2 pooka mutex_enter(&ufs_hashlock);
1444 1.207.4.2 pooka if (ufs_ihashget(dev, ino, 0) != NULL) {
1445 1.207.4.2 pooka mutex_exit(&ufs_hashlock);
1446 1.207.4.2 pooka ungetnewvnode(vp);
1447 1.207.4.2 pooka pool_put(&ffs_inode_pool, ip);
1448 1.207.4.2 pooka goto retry;
1449 1.207.4.2 pooka }
1450 1.207.4.2 pooka
1451 1.207.4.2 pooka vp->v_flag |= VLOCKSWORK;
1452 1.207.4.2 pooka
1453 1.207.4.2 pooka /*
1454 1.207.4.2 pooka * XXX MFS ends up here, too, to allocate an inode. Should we
1455 1.207.4.2 pooka * XXX create another pool for MFS inodes?
1456 1.207.4.2 pooka */
1457 1.207.4.2 pooka
1458 1.207.4.2 pooka memset(ip, 0, sizeof(struct inode));
1459 1.207.4.2 pooka vp->v_data = ip;
1460 1.207.4.2 pooka ip->i_vnode = vp;
1461 1.207.4.2 pooka ip->i_ump = ump;
1462 1.207.4.2 pooka ip->i_fs = fs = ump->um_fs;
1463 1.207.4.2 pooka ip->i_dev = dev;
1464 1.207.4.2 pooka ip->i_number = ino;
1465 1.207.4.2 pooka LIST_INIT(&ip->i_pcbufhd);
1466 1.207.4.2 pooka #ifdef QUOTA
1467 1.207.4.2 pooka ufsquota_init(ip);
1468 1.207.4.2 pooka #endif
1469 1.207.4.2 pooka
1470 1.207.4.2 pooka /*
1471 1.207.4.2 pooka * Put it onto its hash chain and lock it so that other requests for
1472 1.207.4.2 pooka * this inode will block if they arrive while we are sleeping waiting
1473 1.207.4.2 pooka * for old data structures to be purged or for the contents of the
1474 1.207.4.2 pooka * disk portion of this inode to be read.
1475 1.207.4.2 pooka */
1476 1.207.4.2 pooka
1477 1.207.4.2 pooka ufs_ihashins(ip);
1478 1.207.4.2 pooka mutex_exit(&ufs_hashlock);
1479 1.207.4.2 pooka
1480 1.207.4.2 pooka /* Read in the disk contents for the inode, copy into the inode. */
1481 1.207.4.2 pooka error = bread(ump->um_devvp, fsbtodb(fs, ino_to_fsba(fs, ino)),
1482 1.207.4.2 pooka (int)fs->fs_bsize, NOCRED, &bp);
1483 1.207.4.2 pooka if (error) {
1484 1.207.4.2 pooka
1485 1.207.4.2 pooka /*
1486 1.207.4.2 pooka * The inode does not contain anything useful, so it would
1487 1.207.4.2 pooka * be misleading to leave it on its hash chain. With mode
1488 1.207.4.2 pooka * still zero, it will be unlinked and returned to the free
1489 1.207.4.2 pooka * list by vput().
1490 1.207.4.2 pooka */
1491 1.207.4.2 pooka
1492 1.207.4.2 pooka vput(vp);
1493 1.207.4.2 pooka brelse(bp);
1494 1.207.4.2 pooka *vpp = NULL;
1495 1.207.4.2 pooka return (error);
1496 1.207.4.2 pooka }
1497 1.207.4.2 pooka if (ip->i_ump->um_fstype == UFS1)
1498 1.207.4.2 pooka ip->i_din.ffs1_din = pool_get(&ffs_dinode1_pool, PR_WAITOK);
1499 1.207.4.2 pooka else
1500 1.207.4.2 pooka ip->i_din.ffs2_din = pool_get(&ffs_dinode2_pool, PR_WAITOK);
1501 1.207.4.2 pooka ffs_load_inode(bp, ip, fs, ino);
1502 1.207.4.2 pooka if (DOINGSOFTDEP(vp))
1503 1.207.4.2 pooka softdep_load_inodeblock(ip);
1504 1.207.4.2 pooka else
1505 1.207.4.2 pooka ip->i_ffs_effnlink = ip->i_nlink;
1506 1.207.4.2 pooka brelse(bp);
1507 1.207.4.2 pooka
1508 1.207.4.2 pooka /*
1509 1.207.4.2 pooka * Initialize the vnode from the inode, check for aliases.
1510 1.207.4.2 pooka * Note that the underlying vnode may have changed.
1511 1.207.4.2 pooka */
1512 1.207.4.2 pooka
1513 1.207.4.2 pooka ufs_vinit(mp, ffs_specop_p, ffs_fifoop_p, &vp);
1514 1.207.4.2 pooka
1515 1.207.4.2 pooka /*
1516 1.207.4.2 pooka * Finish inode initialization now that aliasing has been resolved.
1517 1.207.4.2 pooka */
1518 1.207.4.2 pooka
1519 1.207.4.2 pooka genfs_node_init(vp, &ffs_genfsops);
1520 1.207.4.2 pooka ip->i_devvp = ump->um_devvp;
1521 1.207.4.2 pooka VREF(ip->i_devvp);
1522 1.207.4.2 pooka
1523 1.207.4.2 pooka /*
1524 1.207.4.2 pooka * Ensure that uid and gid are correct. This is a temporary
1525 1.207.4.2 pooka * fix until fsck has been changed to do the update.
1526 1.207.4.2 pooka */
1527 1.207.4.2 pooka
1528 1.207.4.2 pooka if (fs->fs_old_inodefmt < FS_44INODEFMT) { /* XXX */
1529 1.207.4.2 pooka ip->i_uid = ip->i_ffs1_ouid; /* XXX */
1530 1.207.4.2 pooka ip->i_gid = ip->i_ffs1_ogid; /* XXX */
1531 1.207.4.2 pooka } /* XXX */
1532 1.207.4.2 pooka uvm_vnp_setsize(vp, ip->i_size);
1533 1.207.4.2 pooka *vpp = vp;
1534 1.207.4.2 pooka return (0);
1535 1.207.4.2 pooka }
1536 1.207.4.2 pooka
1537 1.207.4.2 pooka /*
1538 1.207.4.2 pooka * File handle to vnode
1539 1.207.4.2 pooka *
1540 1.207.4.2 pooka * Have to be really careful about stale file handles:
1541 1.207.4.2 pooka * - check that the inode number is valid
1542 1.207.4.2 pooka * - call ffs_vget() to get the locked inode
1543 1.207.4.2 pooka * - check for an unallocated inode (i_mode == 0)
1544 1.207.4.2 pooka * - check that the given client host has export rights and return
1545 1.207.4.2 pooka * those rights via. exflagsp and credanonp
1546 1.207.4.2 pooka */
1547 1.207.4.2 pooka int
1548 1.207.4.2 pooka ffs_fhtovp(struct mount *mp, struct fid *fhp, struct vnode **vpp)
1549 1.207.4.2 pooka {
1550 1.207.4.2 pooka struct ufid ufh;
1551 1.207.4.2 pooka struct fs *fs;
1552 1.207.4.2 pooka
1553 1.207.4.2 pooka if (fhp->fid_len != sizeof(struct ufid))
1554 1.207.4.2 pooka return EINVAL;
1555 1.207.4.2 pooka
1556 1.207.4.2 pooka memcpy(&ufh, fhp, sizeof(ufh));
1557 1.207.4.2 pooka fs = VFSTOUFS(mp)->um_fs;
1558 1.207.4.2 pooka if (ufh.ufid_ino < ROOTINO ||
1559 1.207.4.2 pooka ufh.ufid_ino >= fs->fs_ncg * fs->fs_ipg)
1560 1.207.4.2 pooka return (ESTALE);
1561 1.207.4.2 pooka return (ufs_fhtovp(mp, &ufh, vpp));
1562 1.207.4.2 pooka }
1563 1.207.4.2 pooka
1564 1.207.4.2 pooka /*
1565 1.207.4.2 pooka * Vnode pointer to File handle
1566 1.207.4.2 pooka */
1567 1.207.4.2 pooka /* ARGSUSED */
1568 1.207.4.2 pooka int
1569 1.207.4.2 pooka ffs_vptofh(struct vnode *vp, struct fid *fhp, size_t *fh_size)
1570 1.207.4.2 pooka {
1571 1.207.4.2 pooka struct inode *ip;
1572 1.207.4.2 pooka struct ufid ufh;
1573 1.207.4.2 pooka
1574 1.207.4.2 pooka if (*fh_size < sizeof(struct ufid)) {
1575 1.207.4.2 pooka *fh_size = sizeof(struct ufid);
1576 1.207.4.2 pooka return E2BIG;
1577 1.207.4.2 pooka }
1578 1.207.4.2 pooka ip = VTOI(vp);
1579 1.207.4.2 pooka *fh_size = sizeof(struct ufid);
1580 1.207.4.2 pooka memset(&ufh, 0, sizeof(ufh));
1581 1.207.4.2 pooka ufh.ufid_len = sizeof(struct ufid);
1582 1.207.4.2 pooka ufh.ufid_ino = ip->i_number;
1583 1.207.4.2 pooka ufh.ufid_gen = ip->i_gen;
1584 1.207.4.2 pooka memcpy(fhp, &ufh, sizeof(ufh));
1585 1.207.4.2 pooka return (0);
1586 1.207.4.2 pooka }
1587 1.207.4.2 pooka
1588 1.207.4.2 pooka void
1589 1.207.4.2 pooka ffs_init(void)
1590 1.207.4.2 pooka {
1591 1.207.4.2 pooka if (ffs_initcount++ > 0)
1592 1.207.4.2 pooka return;
1593 1.207.4.2 pooka
1594 1.207.4.2 pooka pool_init(&ffs_inode_pool, sizeof(struct inode), 0, 0, 0,
1595 1.207.4.2 pooka "ffsinopl", &pool_allocator_nointr, IPL_NONE);
1596 1.207.4.2 pooka pool_init(&ffs_dinode1_pool, sizeof(struct ufs1_dinode), 0, 0, 0,
1597 1.207.4.2 pooka "dino1pl", &pool_allocator_nointr, IPL_NONE);
1598 1.207.4.2 pooka pool_init(&ffs_dinode2_pool, sizeof(struct ufs2_dinode), 0, 0, 0,
1599 1.207.4.2 pooka "dino2pl", &pool_allocator_nointr, IPL_NONE);
1600 1.207.4.2 pooka softdep_initialize();
1601 1.207.4.2 pooka ufs_init();
1602 1.207.4.2 pooka }
1603 1.207.4.2 pooka
1604 1.207.4.2 pooka void
1605 1.207.4.2 pooka ffs_reinit(void)
1606 1.207.4.2 pooka {
1607 1.207.4.2 pooka softdep_reinitialize();
1608 1.207.4.2 pooka ufs_reinit();
1609 1.207.4.2 pooka }
1610 1.207.4.2 pooka
1611 1.207.4.2 pooka void
1612 1.207.4.2 pooka ffs_done(void)
1613 1.207.4.2 pooka {
1614 1.207.4.2 pooka if (--ffs_initcount > 0)
1615 1.207.4.2 pooka return;
1616 1.207.4.2 pooka
1617 1.207.4.2 pooka /* XXX softdep cleanup ? */
1618 1.207.4.2 pooka ufs_done();
1619 1.207.4.2 pooka pool_destroy(&ffs_dinode2_pool);
1620 1.207.4.2 pooka pool_destroy(&ffs_dinode1_pool);
1621 1.207.4.2 pooka pool_destroy(&ffs_inode_pool);
1622 1.207.4.2 pooka }
1623 1.207.4.2 pooka
1624 1.207.4.2 pooka SYSCTL_SETUP(sysctl_vfs_ffs_setup, "sysctl vfs.ffs subtree setup")
1625 1.207.4.2 pooka {
1626 1.207.4.2 pooka #if 0
1627 1.207.4.2 pooka extern int doasyncfree;
1628 1.207.4.2 pooka #endif
1629 1.207.4.2 pooka extern int ffs_log_changeopt;
1630 1.207.4.2 pooka
1631 1.207.4.2 pooka sysctl_createv(clog, 0, NULL, NULL,
1632 1.207.4.2 pooka CTLFLAG_PERMANENT,
1633 1.207.4.2 pooka CTLTYPE_NODE, "vfs", NULL,
1634 1.207.4.2 pooka NULL, 0, NULL, 0,
1635 1.207.4.2 pooka CTL_VFS, CTL_EOL);
1636 1.207.4.2 pooka sysctl_createv(clog, 0, NULL, NULL,
1637 1.207.4.2 pooka CTLFLAG_PERMANENT,
1638 1.207.4.2 pooka CTLTYPE_NODE, "ffs",
1639 1.207.4.2 pooka SYSCTL_DESCR("Berkeley Fast File System"),
1640 1.207.4.2 pooka NULL, 0, NULL, 0,
1641 1.207.4.2 pooka CTL_VFS, 1, CTL_EOL);
1642 1.207.4.2 pooka
1643 1.207.4.2 pooka /*
1644 1.207.4.2 pooka * @@@ should we even bother with these first three?
1645 1.207.4.2 pooka */
1646 1.207.4.2 pooka sysctl_createv(clog, 0, NULL, NULL,
1647 1.207.4.2 pooka CTLFLAG_PERMANENT|CTLFLAG_READWRITE,
1648 1.207.4.2 pooka CTLTYPE_INT, "doclusterread", NULL,
1649 1.207.4.2 pooka sysctl_notavail, 0, NULL, 0,
1650 1.207.4.2 pooka CTL_VFS, 1, FFS_CLUSTERREAD, CTL_EOL);
1651 1.207.4.2 pooka sysctl_createv(clog, 0, NULL, NULL,
1652 1.207.4.2 pooka CTLFLAG_PERMANENT|CTLFLAG_READWRITE,
1653 1.207.4.2 pooka CTLTYPE_INT, "doclusterwrite", NULL,
1654 1.207.4.2 pooka sysctl_notavail, 0, NULL, 0,
1655 1.207.4.2 pooka CTL_VFS, 1, FFS_CLUSTERWRITE, CTL_EOL);
1656 1.207.4.2 pooka sysctl_createv(clog, 0, NULL, NULL,
1657 1.207.4.2 pooka CTLFLAG_PERMANENT|CTLFLAG_READWRITE,
1658 1.207.4.2 pooka CTLTYPE_INT, "doreallocblks", NULL,
1659 1.207.4.2 pooka sysctl_notavail, 0, NULL, 0,
1660 1.207.4.2 pooka CTL_VFS, 1, FFS_REALLOCBLKS, CTL_EOL);
1661 1.207.4.2 pooka #if 0
1662 1.207.4.2 pooka sysctl_createv(clog, 0, NULL, NULL,
1663 1.207.4.2 pooka CTLFLAG_PERMANENT|CTLFLAG_READWRITE,
1664 1.207.4.2 pooka CTLTYPE_INT, "doasyncfree",
1665 1.207.4.2 pooka SYSCTL_DESCR("Release dirty blocks asynchronously"),
1666 1.207.4.2 pooka NULL, 0, &doasyncfree, 0,
1667 1.207.4.2 pooka CTL_VFS, 1, FFS_ASYNCFREE, CTL_EOL);
1668 1.207.4.2 pooka #endif
1669 1.207.4.2 pooka sysctl_createv(clog, 0, NULL, NULL,
1670 1.207.4.2 pooka CTLFLAG_PERMANENT|CTLFLAG_READWRITE,
1671 1.207.4.2 pooka CTLTYPE_INT, "log_changeopt",
1672 1.207.4.2 pooka SYSCTL_DESCR("Log changes in optimization strategy"),
1673 1.207.4.2 pooka NULL, 0, &ffs_log_changeopt, 0,
1674 1.207.4.2 pooka CTL_VFS, 1, FFS_LOG_CHANGEOPT, CTL_EOL);
1675 1.207.4.2 pooka }
1676 1.207.4.2 pooka
1677 1.207.4.2 pooka /*
1678 1.207.4.2 pooka * Write a superblock and associated information back to disk.
1679 1.207.4.2 pooka */
1680 1.207.4.2 pooka int
1681 1.207.4.2 pooka ffs_sbupdate(struct ufsmount *mp, int waitfor)
1682 1.207.4.2 pooka {
1683 1.207.4.2 pooka struct fs *fs = mp->um_fs;
1684 1.207.4.2 pooka struct buf *bp;
1685 1.207.4.2 pooka int error = 0;
1686 1.207.4.2 pooka u_int32_t saveflag;
1687 1.207.4.2 pooka
1688 1.207.4.2 pooka bp = getblk(mp->um_devvp,
1689 1.207.4.2 pooka fs->fs_sblockloc >> (fs->fs_fshift - fs->fs_fsbtodb),
1690 1.207.4.2 pooka (int)fs->fs_sbsize, 0, 0);
1691 1.207.4.2 pooka saveflag = fs->fs_flags & FS_INTERNAL;
1692 1.207.4.2 pooka fs->fs_flags &= ~FS_INTERNAL;
1693 1.207.4.2 pooka
1694 1.207.4.2 pooka memcpy(bp->b_data, fs, fs->fs_sbsize);
1695 1.207.4.2 pooka
1696 1.207.4.2 pooka ffs_oldfscompat_write((struct fs *)bp->b_data, mp);
1697 1.207.4.2 pooka #ifdef FFS_EI
1698 1.207.4.2 pooka if (mp->um_flags & UFS_NEEDSWAP)
1699 1.207.4.2 pooka ffs_sb_swap((struct fs *)bp->b_data, (struct fs *)bp->b_data);
1700 1.207.4.2 pooka #endif
1701 1.207.4.2 pooka fs->fs_flags |= saveflag;
1702 1.207.4.2 pooka
1703 1.207.4.2 pooka if (waitfor == MNT_WAIT)
1704 1.207.4.2 pooka error = bwrite(bp);
1705 1.207.4.2 pooka else
1706 1.207.4.2 pooka bawrite(bp);
1707 1.207.4.2 pooka return (error);
1708 1.207.4.2 pooka }
1709 1.207.4.2 pooka
1710 1.207.4.2 pooka int
1711 1.207.4.2 pooka ffs_cgupdate(struct ufsmount *mp, int waitfor)
1712 1.207.4.2 pooka {
1713 1.207.4.2 pooka struct fs *fs = mp->um_fs;
1714 1.207.4.2 pooka struct buf *bp;
1715 1.207.4.2 pooka int blks;
1716 1.207.4.2 pooka void *space;
1717 1.207.4.2 pooka int i, size, error = 0, allerror = 0;
1718 1.207.4.2 pooka
1719 1.207.4.2 pooka allerror = ffs_sbupdate(mp, waitfor);
1720 1.207.4.2 pooka blks = howmany(fs->fs_cssize, fs->fs_fsize);
1721 1.207.4.2 pooka space = fs->fs_csp;
1722 1.207.4.2 pooka for (i = 0; i < blks; i += fs->fs_frag) {
1723 1.207.4.2 pooka size = fs->fs_bsize;
1724 1.207.4.2 pooka if (i + fs->fs_frag > blks)
1725 1.207.4.2 pooka size = (blks - i) * fs->fs_fsize;
1726 1.207.4.2 pooka bp = getblk(mp->um_devvp, fsbtodb(fs, fs->fs_csaddr + i),
1727 1.207.4.2 pooka size, 0, 0);
1728 1.207.4.2 pooka #ifdef FFS_EI
1729 1.207.4.2 pooka if (mp->um_flags & UFS_NEEDSWAP)
1730 1.207.4.2 pooka ffs_csum_swap((struct csum*)space,
1731 1.207.4.2 pooka (struct csum*)bp->b_data, size);
1732 1.207.4.2 pooka else
1733 1.207.4.2 pooka #endif
1734 1.207.4.2 pooka memcpy(bp->b_data, space, (u_int)size);
1735 1.207.4.2 pooka space = (char *)space + size;
1736 1.207.4.2 pooka if (waitfor == MNT_WAIT)
1737 1.207.4.2 pooka error = bwrite(bp);
1738 1.207.4.2 pooka else
1739 1.207.4.2 pooka bawrite(bp);
1740 1.207.4.2 pooka }
1741 1.207.4.2 pooka if (!allerror && error)
1742 1.207.4.2 pooka allerror = error;
1743 1.207.4.2 pooka return (allerror);
1744 1.207.4.2 pooka }
1745 1.207.4.2 pooka
1746 1.207.4.2 pooka int
1747 1.207.4.2 pooka ffs_extattrctl(struct mount *mp, int cmd, struct vnode *vp,
1748 1.207.4.2 pooka int attrnamespace, const char *attrname, struct lwp *l)
1749 1.207.4.2 pooka {
1750 1.207.4.2 pooka #ifdef UFS_EXTATTR
1751 1.207.4.2 pooka /*
1752 1.207.4.2 pooka * File-backed extended attributes are only supported on UFS1.
1753 1.207.4.2 pooka * UFS2 has native extended attributes.
1754 1.207.4.2 pooka */
1755 1.207.4.2 pooka if (VFSTOUFS(mp)->um_fstype == UFS1)
1756 1.207.4.2 pooka return (ufs_extattrctl(mp, cmd, vp, attrnamespace, attrname,
1757 1.207.4.2 pooka l));
1758 1.207.4.2 pooka #endif
1759 1.207.4.2 pooka return (vfs_stdextattrctl(mp, cmd, vp, attrnamespace, attrname, l));
1760 1.207.4.2 pooka }
1761 1.207.4.2 pooka
1762 1.207.4.2 pooka int
1763 1.207.4.2 pooka ffs_suspendctl(struct mount *mp, int cmd)
1764 1.207.4.2 pooka {
1765 1.207.4.2 pooka int error;
1766 1.207.4.2 pooka struct lwp *l = curlwp;
1767 1.207.4.2 pooka
1768 1.207.4.2 pooka switch (cmd) {
1769 1.207.4.2 pooka case SUSPEND_SUSPEND:
1770 1.207.4.2 pooka if ((error = fstrans_setstate(mp, FSTRANS_SUSPENDING)) != 0)
1771 1.207.4.2 pooka return error;
1772 1.207.4.2 pooka error = ffs_sync(mp, MNT_WAIT, l->l_proc->p_cred, l);
1773 1.207.4.2 pooka if (error == 0)
1774 1.207.4.2 pooka error = fstrans_setstate(mp, FSTRANS_SUSPENDED);
1775 1.207.4.2 pooka if (error != 0) {
1776 1.207.4.2 pooka (void) fstrans_setstate(mp, FSTRANS_NORMAL);
1777 1.207.4.2 pooka return error;
1778 1.207.4.2 pooka }
1779 1.207.4.2 pooka return 0;
1780 1.207.4.2 pooka
1781 1.207.4.2 pooka case SUSPEND_RESUME:
1782 1.207.4.2 pooka return fstrans_setstate(mp, FSTRANS_NORMAL);
1783 1.207.4.2 pooka
1784 1.207.4.2 pooka default:
1785 1.207.4.2 pooka return EINVAL;
1786 1.207.4.2 pooka }
1787 1.207.4.2 pooka }
1788