ffs_vfsops.c revision 1.369 1 /* $NetBSD: ffs_vfsops.c,v 1.369 2020/05/16 18:31:53 christos Exp $ */
2
3 /*-
4 * Copyright (c) 2008, 2009 The NetBSD Foundation, Inc.
5 * All rights reserved.
6 *
7 * This code is derived from software contributed to The NetBSD Foundation
8 * by Wasabi Systems, Inc, and by Andrew Doran.
9 *
10 * Redistribution and use in source and binary forms, with or without
11 * modification, are permitted provided that the following conditions
12 * are met:
13 * 1. Redistributions of source code must retain the above copyright
14 * notice, this list of conditions and the following disclaimer.
15 * 2. Redistributions in binary form must reproduce the above copyright
16 * notice, this list of conditions and the following disclaimer in the
17 * documentation and/or other materials provided with the distribution.
18 *
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
21 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
22 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
23 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
24 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
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
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
29 * POSSIBILITY OF SUCH DAMAGE.
30 */
31
32 /*
33 * Copyright (c) 1989, 1991, 1993, 1994
34 * The Regents of the University of California. All rights reserved.
35 *
36 * Redistribution and use in source and binary forms, with or without
37 * modification, are permitted provided that the following conditions
38 * are met:
39 * 1. Redistributions of source code must retain the above copyright
40 * notice, this list of conditions and the following disclaimer.
41 * 2. Redistributions in binary form must reproduce the above copyright
42 * notice, this list of conditions and the following disclaimer in the
43 * documentation and/or other materials provided with the distribution.
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
46 * without specific prior written permission.
47 *
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
50 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
51 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
52 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
53 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
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
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
58 * SUCH DAMAGE.
59 *
60 * @(#)ffs_vfsops.c 8.31 (Berkeley) 5/20/95
61 */
62
63 #include <sys/cdefs.h>
64 __KERNEL_RCSID(0, "$NetBSD: ffs_vfsops.c,v 1.369 2020/05/16 18:31:53 christos Exp $");
65
66 #if defined(_KERNEL_OPT)
67 #include "opt_ffs.h"
68 #include "opt_quota.h"
69 #include "opt_wapbl.h"
70 #endif
71
72 #include <sys/param.h>
73 #include <sys/systm.h>
74 #include <sys/namei.h>
75 #include <sys/proc.h>
76 #include <sys/kernel.h>
77 #include <sys/vnode.h>
78 #include <sys/socket.h>
79 #include <sys/mount.h>
80 #include <sys/buf.h>
81 #include <sys/device.h>
82 #include <sys/disk.h>
83 #include <sys/file.h>
84 #include <sys/disklabel.h>
85 #include <sys/ioctl.h>
86 #include <sys/errno.h>
87 #include <sys/kmem.h>
88 #include <sys/pool.h>
89 #include <sys/lock.h>
90 #include <sys/sysctl.h>
91 #include <sys/conf.h>
92 #include <sys/kauth.h>
93 #include <sys/wapbl.h>
94 #include <sys/module.h>
95
96 #include <miscfs/genfs/genfs.h>
97 #include <miscfs/specfs/specdev.h>
98
99 #include <ufs/ufs/quota.h>
100 #include <ufs/ufs/ufsmount.h>
101 #include <ufs/ufs/inode.h>
102 #include <ufs/ufs/dir.h>
103 #include <ufs/ufs/ufs_extern.h>
104 #include <ufs/ufs/ufs_bswap.h>
105 #include <ufs/ufs/ufs_wapbl.h>
106
107 #include <ufs/ffs/fs.h>
108 #include <ufs/ffs/ffs_extern.h>
109
110 #ifdef WAPBL
111 MODULE(MODULE_CLASS_VFS, ffs, "ufs,wapbl");
112 #else
113 MODULE(MODULE_CLASS_VFS, ffs, "ufs");
114 #endif
115
116 static int ffs_vfs_fsync(vnode_t *, int);
117 static int ffs_superblock_validate(struct fs *);
118 static int ffs_is_appleufs(struct vnode *, struct fs *);
119
120 static int ffs_init_vnode(struct ufsmount *, struct vnode *, ino_t);
121 static void ffs_deinit_vnode(struct ufsmount *, struct vnode *);
122
123 static kauth_listener_t ffs_snapshot_listener;
124
125 /* how many times ffs_init() was called */
126 int ffs_initcount = 0;
127
128 #ifdef DEBUG_FFS_MOUNT
129 #define DPRINTF(_fmt, args...) printf("%s: " _fmt "\n", __func__, ##args)
130 #else
131 #define DPRINTF(_fmt, args...) do {} while (/*CONSTCOND*/0)
132 #endif
133
134 extern const struct vnodeopv_desc ffs_vnodeop_opv_desc;
135 extern const struct vnodeopv_desc ffs_specop_opv_desc;
136 extern const struct vnodeopv_desc ffs_fifoop_opv_desc;
137
138 const struct vnodeopv_desc * const ffs_vnodeopv_descs[] = {
139 &ffs_vnodeop_opv_desc,
140 &ffs_specop_opv_desc,
141 &ffs_fifoop_opv_desc,
142 NULL,
143 };
144
145 struct vfsops ffs_vfsops = {
146 .vfs_name = MOUNT_FFS,
147 .vfs_min_mount_data = sizeof (struct ufs_args),
148 .vfs_mount = ffs_mount,
149 .vfs_start = ufs_start,
150 .vfs_unmount = ffs_unmount,
151 .vfs_root = ufs_root,
152 .vfs_quotactl = ufs_quotactl,
153 .vfs_statvfs = ffs_statvfs,
154 .vfs_sync = ffs_sync,
155 .vfs_vget = ufs_vget,
156 .vfs_loadvnode = ffs_loadvnode,
157 .vfs_newvnode = ffs_newvnode,
158 .vfs_fhtovp = ffs_fhtovp,
159 .vfs_vptofh = ffs_vptofh,
160 .vfs_init = ffs_init,
161 .vfs_reinit = ffs_reinit,
162 .vfs_done = ffs_done,
163 .vfs_mountroot = ffs_mountroot,
164 .vfs_snapshot = ffs_snapshot,
165 .vfs_extattrctl = ffs_extattrctl,
166 .vfs_suspendctl = genfs_suspendctl,
167 .vfs_renamelock_enter = genfs_renamelock_enter,
168 .vfs_renamelock_exit = genfs_renamelock_exit,
169 .vfs_fsync = ffs_vfs_fsync,
170 .vfs_opv_descs = ffs_vnodeopv_descs
171 };
172
173 static const struct genfs_ops ffs_genfsops = {
174 .gop_size = ffs_gop_size,
175 .gop_alloc = ufs_gop_alloc,
176 .gop_write = genfs_gop_write,
177 .gop_markupdate = ufs_gop_markupdate,
178 .gop_putrange = genfs_gop_putrange,
179 };
180
181 static const struct ufs_ops ffs_ufsops = {
182 .uo_itimes = ffs_itimes,
183 .uo_update = ffs_update,
184 .uo_truncate = ffs_truncate,
185 .uo_balloc = ffs_balloc,
186 .uo_snapgone = ffs_snapgone,
187 .uo_bufrd = ffs_bufrd,
188 .uo_bufwr = ffs_bufwr,
189 };
190
191 static int
192 ffs_checkrange(struct mount *mp, uint32_t ino)
193 {
194 struct fs *fs = VFSTOUFS(mp)->um_fs;
195
196 if (ino < UFS_ROOTINO || ino >= fs->fs_ncg * fs->fs_ipg) {
197 DPRINTF("out of range %u\n", ino);
198 return ESTALE;
199 }
200
201 /*
202 * Need to check if inode is initialized because ffsv2 does
203 * lazy initialization and we can get here from nfs_fhtovp
204 */
205 if (fs->fs_magic != FS_UFS2_MAGIC)
206 return 0;
207
208 struct buf *bp;
209 int cg = ino_to_cg(fs, ino);
210 struct ufsmount *ump = VFSTOUFS(mp);
211
212 int error = bread(ump->um_devvp, FFS_FSBTODB(fs, cgtod(fs, cg)),
213 (int)fs->fs_cgsize, B_MODIFY, &bp);
214 if (error) {
215 DPRINTF("error %d reading cg %d ino %u\n", error, cg, ino);
216 return error;
217 }
218
219 const int needswap = UFS_FSNEEDSWAP(fs);
220
221 struct cg *cgp = (struct cg *)bp->b_data;
222 if (!cg_chkmagic(cgp, needswap)) {
223 brelse(bp, 0);
224 DPRINTF("bad cylinder group magic cg %d ino %u\n", cg, ino);
225 return ESTALE;
226 }
227
228 int32_t initediblk = ufs_rw32(cgp->cg_initediblk, needswap);
229 brelse(bp, 0);
230
231 if (cg * fs->fs_ipg + initediblk < ino) {
232 DPRINTF("cg=%d fs->fs_ipg=%d initediblk=%d ino=%u\n",
233 cg, fs->fs_ipg, initediblk, ino);
234 return ESTALE;
235 }
236 return 0;
237 }
238
239 static int
240 ffs_snapshot_cb(kauth_cred_t cred, kauth_action_t action, void *cookie,
241 void *arg0, void *arg1, void *arg2, void *arg3)
242 {
243 vnode_t *vp = arg2;
244 int result = KAUTH_RESULT_DEFER;
245
246 if (action != KAUTH_SYSTEM_FS_SNAPSHOT)
247 return result;
248
249 if (VTOI(vp)->i_uid == kauth_cred_geteuid(cred))
250 result = KAUTH_RESULT_ALLOW;
251
252 return result;
253 }
254
255 SYSCTL_SETUP(ffs_sysctl_setup, "ffs sysctls")
256 {
257 #ifdef UFS_EXTATTR
258 extern int ufs_extattr_autocreate;
259 #endif
260 extern int ffs_log_changeopt;
261
262 sysctl_createv(clog, 0, NULL, NULL,
263 CTLFLAG_PERMANENT,
264 CTLTYPE_NODE, "ffs",
265 SYSCTL_DESCR("Berkeley Fast File System"),
266 NULL, 0, NULL, 0,
267 CTL_VFS, 1, CTL_EOL);
268 /*
269 * @@@ should we even bother with these first three?
270 */
271 sysctl_createv(clog, 0, NULL, NULL,
272 CTLFLAG_PERMANENT|CTLFLAG_READWRITE,
273 CTLTYPE_INT, "doclusterread", NULL,
274 sysctl_notavail, 0, NULL, 0,
275 CTL_VFS, 1, FFS_CLUSTERREAD, CTL_EOL);
276 sysctl_createv(clog, 0, NULL, NULL,
277 CTLFLAG_PERMANENT|CTLFLAG_READWRITE,
278 CTLTYPE_INT, "doclusterwrite", NULL,
279 sysctl_notavail, 0, NULL, 0,
280 CTL_VFS, 1, FFS_CLUSTERWRITE, CTL_EOL);
281 sysctl_createv(clog, 0, NULL, NULL,
282 CTLFLAG_PERMANENT|CTLFLAG_READWRITE,
283 CTLTYPE_INT, "doreallocblks", NULL,
284 sysctl_notavail, 0, NULL, 0,
285 CTL_VFS, 1, FFS_REALLOCBLKS, CTL_EOL);
286 #if 0
287 sysctl_createv(clog, 0, NULL, NULL,
288 CTLFLAG_PERMANENT|CTLFLAG_READWRITE,
289 CTLTYPE_INT, "doasyncfree",
290 SYSCTL_DESCR("Release dirty blocks asynchronously"),
291 NULL, 0, &doasyncfree, 0,
292 CTL_VFS, 1, FFS_ASYNCFREE, CTL_EOL);
293 #endif
294 sysctl_createv(clog, 0, NULL, NULL,
295 CTLFLAG_PERMANENT|CTLFLAG_READWRITE,
296 CTLTYPE_INT, "log_changeopt",
297 SYSCTL_DESCR("Log changes in optimization strategy"),
298 NULL, 0, &ffs_log_changeopt, 0,
299 CTL_VFS, 1, FFS_LOG_CHANGEOPT, CTL_EOL);
300 #ifdef UFS_EXTATTR
301 sysctl_createv(clog, 0, NULL, NULL,
302 CTLFLAG_PERMANENT|CTLFLAG_READWRITE,
303 CTLTYPE_INT, "extattr_autocreate",
304 SYSCTL_DESCR("Size of attribute for "
305 "backing file autocreation"),
306 NULL, 0, &ufs_extattr_autocreate, 0,
307 CTL_VFS, 1, FFS_EXTATTR_AUTOCREATE, CTL_EOL);
308
309 #endif /* UFS_EXTATTR */
310 }
311
312 static int
313 ffs_modcmd(modcmd_t cmd, void *arg)
314 {
315 int error;
316
317 #if 0
318 extern int doasyncfree;
319 #endif
320
321 switch (cmd) {
322 case MODULE_CMD_INIT:
323 error = vfs_attach(&ffs_vfsops);
324 if (error != 0)
325 break;
326
327 ffs_snapshot_listener = kauth_listen_scope(KAUTH_SCOPE_SYSTEM,
328 ffs_snapshot_cb, NULL);
329 if (ffs_snapshot_listener == NULL)
330 printf("ffs_modcmd: can't listen on system scope.\n");
331
332 break;
333 case MODULE_CMD_FINI:
334 error = vfs_detach(&ffs_vfsops);
335 if (error != 0)
336 break;
337 if (ffs_snapshot_listener != NULL)
338 kauth_unlisten_scope(ffs_snapshot_listener);
339 break;
340 default:
341 error = ENOTTY;
342 break;
343 }
344
345 return (error);
346 }
347
348 pool_cache_t ffs_inode_cache;
349 pool_cache_t ffs_dinode1_cache;
350 pool_cache_t ffs_dinode2_cache;
351
352 static void ffs_oldfscompat_read(struct fs *, struct ufsmount *, daddr_t);
353 static void ffs_oldfscompat_write(struct fs *, struct ufsmount *);
354
355 /*
356 * Called by main() when ffs is going to be mounted as root.
357 */
358
359 int
360 ffs_mountroot(void)
361 {
362 struct fs *fs;
363 struct mount *mp;
364 struct lwp *l = curlwp; /* XXX */
365 struct ufsmount *ump;
366 int error;
367
368 if (device_class(root_device) != DV_DISK)
369 return (ENODEV);
370
371 if ((error = vfs_rootmountalloc(MOUNT_FFS, "root_device", &mp))) {
372 vrele(rootvp);
373 return (error);
374 }
375
376 /*
377 * We always need to be able to mount the root file system.
378 */
379 mp->mnt_flag |= MNT_FORCE;
380 if ((error = ffs_mountfs(rootvp, mp, l)) != 0) {
381 vfs_unbusy(mp);
382 vfs_rele(mp);
383 return (error);
384 }
385 mp->mnt_flag &= ~MNT_FORCE;
386 mountlist_append(mp);
387 ump = VFSTOUFS(mp);
388 fs = ump->um_fs;
389 memset(fs->fs_fsmnt, 0, sizeof(fs->fs_fsmnt));
390 (void)copystr(mp->mnt_stat.f_mntonname, fs->fs_fsmnt, MNAMELEN - 1, 0);
391 (void)ffs_statvfs(mp, &mp->mnt_stat);
392 vfs_unbusy(mp);
393 setrootfstime((time_t)fs->fs_time);
394 return (0);
395 }
396
397 static void
398 ffs_acls(struct mount *mp, int fs_flags)
399 {
400 if ((fs_flags & FS_ACLS) != 0) {
401 #ifdef UFS_ACL
402 if (mp->mnt_flag & MNT_POSIX1EACLS)
403 printf("WARNING: %s: ACLs flag on fs conflicts with "
404 "\"posix1eacls\" mount option; option ignored\n",
405 mp->mnt_stat.f_mntonname);
406 mp->mnt_flag &= ~MNT_ACLS;
407 mp->mnt_flag |= MNT_POSIX1EACLS;
408
409 #else
410 printf("WARNING: %s: ACLs flag on fs but no ACLs support\n",
411 mp->mnt_stat.f_mntonname);
412 #endif
413 }
414 if ((fs_flags & FS_POSIX1EACLS) != 0) {
415 #ifdef UFS_ACL
416 if (mp->mnt_flag & MNT_ACLS)
417 printf("WARNING: %s: NFSv4 ACLs flag on fs conflicts "
418 "with \"acls\" mount option; option ignored\n",
419 mp->mnt_stat.f_mntonname);
420 mp->mnt_flag &= ~MNT_POSIX1EACLS;
421 mp->mnt_flag |= MNT_ACLS;
422 #else
423 printf("WARNING: %s: POSIX.1e ACLs flag on fs but no "
424 "ACLs support\n", mp->mnt_stat.f_mntonname);
425 #endif
426 }
427
428 if ((mp->mnt_flag & (MNT_ACLS | MNT_POSIX1EACLS))
429 == (MNT_ACLS | MNT_POSIX1EACLS))
430 {
431 printf("WARNING: %s: posix1eacl conflicts "
432 "with \"acls\" mount option; option ignored\n",
433 mp->mnt_stat.f_mntonname);
434 mp->mnt_flag &= ~MNT_POSIX1EACLS;
435 }
436
437 if (mp->mnt_flag & (MNT_ACLS | MNT_POSIX1EACLS))
438 mp->mnt_iflag &= ~(IMNT_SHRLOOKUP|IMNT_NCLOOKUP);
439 else
440 mp->mnt_iflag |= IMNT_SHRLOOKUP|IMNT_NCLOOKUP;
441 }
442
443 /*
444 * VFS Operations.
445 *
446 * mount system call
447 */
448 int
449 ffs_mount(struct mount *mp, const char *path, void *data, size_t *data_len)
450 {
451 struct lwp *l = curlwp;
452 struct vnode *devvp = NULL;
453 struct ufs_args *args = data;
454 struct ufsmount *ump = NULL;
455 struct fs *fs;
456 int error = 0, flags, update;
457 mode_t accessmode;
458
459 if (args == NULL) {
460 DPRINTF("NULL args");
461 return EINVAL;
462 }
463 if (*data_len < sizeof(*args)) {
464 DPRINTF("bad size args %zu != %zu", *data_len, sizeof(*args));
465 return EINVAL;
466 }
467
468 ump = VFSTOUFS(mp);
469 if ((mp->mnt_flag & (MNT_GETARGS|MNT_UPDATE)) && ump == NULL) {
470 DPRINTF("no ump");
471 return EIO;
472 }
473
474 if (mp->mnt_flag & MNT_GETARGS) {
475 args->fspec = NULL;
476 *data_len = sizeof *args;
477 return 0;
478 }
479
480 update = mp->mnt_flag & MNT_UPDATE;
481
482 /* Check arguments */
483 if (args->fspec == NULL) {
484 if (!update) {
485 /* New mounts must have a filename for the device */
486 DPRINTF("no filename for mount");
487 return EINVAL;
488 }
489 } else {
490 /*
491 * Look up the name and verify that it's sane.
492 */
493 error = namei_simple_user(args->fspec,
494 NSM_FOLLOW_NOEMULROOT, &devvp);
495 if (error != 0) {
496 DPRINTF("namei_simple_user returned %d", error);
497 return error;
498 }
499
500 /*
501 * Be sure this is a valid block device
502 */
503 if (devvp->v_type != VBLK) {
504 DPRINTF("non block device %d", devvp->v_type);
505 error = ENOTBLK;
506 goto fail;
507 }
508
509 if (bdevsw_lookup(devvp->v_rdev) == NULL) {
510 DPRINTF("can't find block device 0x%jx",
511 devvp->v_rdev);
512 error = ENXIO;
513 goto fail;
514 }
515
516 if (update) {
517 /*
518 * Be sure we're still naming the same device
519 * used for our initial mount
520 */
521 if (devvp != ump->um_devvp &&
522 devvp->v_rdev != ump->um_devvp->v_rdev) {
523 DPRINTF("wrong device 0x%jx != 0x%jx",
524 (uintmax_t)devvp->v_rdev,
525 (uintmax_t)ump->um_devvp->v_rdev);
526 error = EINVAL;
527 goto fail;
528 }
529 vrele(devvp);
530 devvp = NULL;
531 }
532 }
533
534 if (devvp == NULL) {
535 devvp = ump->um_devvp;
536 vref(devvp);
537 }
538
539 /*
540 * If mount by non-root, then verify that user has necessary
541 * permissions on the device.
542 *
543 * Permission to update a mount is checked higher, so here we presume
544 * updating the mount is okay (for example, as far as securelevel goes)
545 * which leaves us with the normal check.
546 */
547 accessmode = VREAD;
548 if (update ? (mp->mnt_iflag & IMNT_WANTRDWR) != 0 :
549 (mp->mnt_flag & MNT_RDONLY) == 0)
550 accessmode |= VWRITE;
551 vn_lock(devvp, LK_EXCLUSIVE | LK_RETRY);
552 error = kauth_authorize_system(l->l_cred, KAUTH_SYSTEM_MOUNT,
553 KAUTH_REQ_SYSTEM_MOUNT_DEVICE, mp, devvp, KAUTH_ARG(accessmode));
554 VOP_UNLOCK(devvp);
555 if (error) {
556 DPRINTF("kauth returned %d", error);
557 goto fail;
558 }
559
560 #ifdef WAPBL
561 /* WAPBL can only be enabled on a r/w mount. */
562 if (((mp->mnt_flag & MNT_RDONLY) && !(mp->mnt_iflag & IMNT_WANTRDWR)) ||
563 (mp->mnt_iflag & IMNT_WANTRDONLY)) {
564 mp->mnt_flag &= ~MNT_LOG;
565 }
566 #else /* !WAPBL */
567 mp->mnt_flag &= ~MNT_LOG;
568 #endif /* !WAPBL */
569
570 if (!update) {
571 int xflags;
572
573 if (mp->mnt_flag & MNT_RDONLY)
574 xflags = FREAD;
575 else
576 xflags = FREAD | FWRITE;
577 vn_lock(devvp, LK_EXCLUSIVE | LK_RETRY);
578 error = VOP_OPEN(devvp, xflags, FSCRED);
579 VOP_UNLOCK(devvp);
580 if (error) {
581 DPRINTF("VOP_OPEN returned %d", error);
582 goto fail;
583 }
584 error = ffs_mountfs(devvp, mp, l);
585 if (error) {
586 DPRINTF("ffs_mountfs returned %d", error);
587 vn_lock(devvp, LK_EXCLUSIVE | LK_RETRY);
588 (void)VOP_CLOSE(devvp, xflags, NOCRED);
589 VOP_UNLOCK(devvp);
590 goto fail;
591 }
592
593 ump = VFSTOUFS(mp);
594 fs = ump->um_fs;
595 } else {
596 /*
597 * Update the mount.
598 */
599
600 /*
601 * The initial mount got a reference on this
602 * device, so drop the one obtained via
603 * namei(), above.
604 */
605 vrele(devvp);
606
607 ump = VFSTOUFS(mp);
608 fs = ump->um_fs;
609 if (fs->fs_ronly == 0 && (mp->mnt_iflag & IMNT_WANTRDONLY)) {
610 /*
611 * Changing from r/w to r/o
612 */
613 flags = WRITECLOSE;
614 if (mp->mnt_flag & MNT_FORCE)
615 flags |= FORCECLOSE;
616 error = ffs_flushfiles(mp, flags, l);
617 if (error)
618 return error;
619
620 error = UFS_WAPBL_BEGIN(mp);
621 if (error) {
622 DPRINTF("wapbl %d", error);
623 return error;
624 }
625
626 if (ffs_cgupdate(ump, MNT_WAIT) == 0 &&
627 fs->fs_clean & FS_WASCLEAN) {
628 if (mp->mnt_flag & MNT_SOFTDEP)
629 fs->fs_flags &= ~FS_DOSOFTDEP;
630 fs->fs_clean = FS_ISCLEAN;
631 (void) ffs_sbupdate(ump, MNT_WAIT);
632 }
633
634 UFS_WAPBL_END(mp);
635 }
636
637 #ifdef WAPBL
638 if ((mp->mnt_flag & MNT_LOG) == 0) {
639 error = ffs_wapbl_stop(mp, mp->mnt_flag & MNT_FORCE);
640 if (error) {
641 DPRINTF("ffs_wapbl_stop returned %d", error);
642 return error;
643 }
644 }
645 #endif /* WAPBL */
646
647 if (fs->fs_ronly == 0 && (mp->mnt_iflag & IMNT_WANTRDONLY)) {
648 /*
649 * Finish change from r/w to r/o
650 */
651 fs->fs_ronly = 1;
652 fs->fs_fmod = 0;
653 }
654
655 if (mp->mnt_flag & MNT_RELOAD) {
656 error = ffs_reload(mp, l->l_cred, l);
657 if (error) {
658 DPRINTF("ffs_reload returned %d", error);
659 return error;
660 }
661 } else {
662 ffs_acls(mp, 0);
663 }
664
665 if (fs->fs_ronly && (mp->mnt_iflag & IMNT_WANTRDWR)) {
666 /*
667 * Changing from read-only to read/write
668 */
669 #ifndef QUOTA2
670 if (fs->fs_flags & FS_DOQUOTA2) {
671 ump->um_flags |= UFS_QUOTA2;
672 uprintf("%s: options QUOTA2 not enabled%s\n",
673 mp->mnt_stat.f_mntonname,
674 (mp->mnt_flag & MNT_FORCE) ? "" :
675 ", not mounting");
676 DPRINTF("ffs_quota2 %d", EINVAL);
677 return EINVAL;
678 }
679 #endif
680 fs->fs_ronly = 0;
681 fs->fs_clean <<= 1;
682 fs->fs_fmod = 1;
683 #ifdef WAPBL
684 if (fs->fs_flags & FS_DOWAPBL) {
685 const char *nm = mp->mnt_stat.f_mntonname;
686 if (!mp->mnt_wapbl_replay) {
687 printf("%s: log corrupted;"
688 " replay cancelled\n", nm);
689 return EFTYPE;
690 }
691 printf("%s: replaying log to disk\n", nm);
692 error = wapbl_replay_write(mp->mnt_wapbl_replay,
693 devvp);
694 if (error) {
695 DPRINTF("%s: wapbl_replay_write %d",
696 nm, error);
697 return error;
698 }
699 wapbl_replay_stop(mp->mnt_wapbl_replay);
700 fs->fs_clean = FS_WASCLEAN;
701 }
702 #endif /* WAPBL */
703 if (fs->fs_snapinum[0] != 0)
704 ffs_snapshot_mount(mp);
705 }
706
707 #ifdef WAPBL
708 error = ffs_wapbl_start(mp);
709 if (error) {
710 DPRINTF("ffs_wapbl_start returned %d", error);
711 return error;
712 }
713 #endif /* WAPBL */
714
715 #ifdef QUOTA2
716 if (!fs->fs_ronly) {
717 error = ffs_quota2_mount(mp);
718 if (error) {
719 DPRINTF("ffs_quota2_mount returned %d", error);
720 return error;
721 }
722 }
723 #endif
724
725 if ((mp->mnt_flag & MNT_DISCARD) && !(ump->um_discarddata))
726 ump->um_discarddata = ffs_discard_init(devvp, fs);
727
728 if (args->fspec == NULL)
729 return 0;
730 }
731
732 error = set_statvfs_info(path, UIO_USERSPACE, args->fspec,
733 UIO_USERSPACE, mp->mnt_op->vfs_name, mp, l);
734 if (error == 0)
735 (void)strncpy(fs->fs_fsmnt, mp->mnt_stat.f_mntonname,
736 sizeof(fs->fs_fsmnt));
737 else {
738 DPRINTF("set_statvfs_info returned %d", error);
739 }
740 fs->fs_flags &= ~FS_DOSOFTDEP;
741 if (fs->fs_fmod != 0) { /* XXX */
742 int err;
743
744 fs->fs_fmod = 0;
745 if (fs->fs_clean & FS_WASCLEAN)
746 fs->fs_time = time_second;
747 else {
748 printf("%s: file system not clean (fs_clean=%#x); "
749 "please fsck(8)\n", mp->mnt_stat.f_mntfromname,
750 fs->fs_clean);
751 printf("%s: lost blocks %" PRId64 " files %d\n",
752 mp->mnt_stat.f_mntfromname, fs->fs_pendingblocks,
753 fs->fs_pendinginodes);
754 }
755 err = UFS_WAPBL_BEGIN(mp);
756 if (err == 0) {
757 (void) ffs_cgupdate(ump, MNT_WAIT);
758 UFS_WAPBL_END(mp);
759 }
760 }
761 if ((mp->mnt_flag & MNT_SOFTDEP) != 0) {
762 printf("%s: `-o softdep' is no longer supported, "
763 "consider `-o log'\n", mp->mnt_stat.f_mntfromname);
764 mp->mnt_flag &= ~MNT_SOFTDEP;
765 }
766
767 return (error);
768
769 fail:
770 vrele(devvp);
771 return (error);
772 }
773
774 /*
775 * Reload all incore data for a filesystem (used after running fsck on
776 * the root filesystem and finding things to fix). The filesystem must
777 * be mounted read-only.
778 *
779 * Things to do to update the mount:
780 * 1) invalidate all cached meta-data.
781 * 2) re-read superblock from disk.
782 * 3) re-read summary information from disk.
783 * 4) invalidate all inactive vnodes.
784 * 5) invalidate all cached file data.
785 * 6) re-read inode data for all active vnodes.
786 */
787 int
788 ffs_reload(struct mount *mp, kauth_cred_t cred, struct lwp *l)
789 {
790 struct vnode *vp, *devvp;
791 struct inode *ip;
792 void *space;
793 struct buf *bp;
794 struct fs *fs, *newfs;
795 int i, bsize, blks, error;
796 int32_t *lp, fs_sbsize;
797 struct ufsmount *ump;
798 daddr_t sblockloc;
799 struct vnode_iterator *marker;
800
801 if ((mp->mnt_flag & MNT_RDONLY) == 0)
802 return (EINVAL);
803
804 ump = VFSTOUFS(mp);
805
806 /*
807 * Step 1: invalidate all cached meta-data.
808 */
809 devvp = ump->um_devvp;
810 vn_lock(devvp, LK_EXCLUSIVE | LK_RETRY);
811 error = vinvalbuf(devvp, 0, cred, l, 0, 0);
812 VOP_UNLOCK(devvp);
813 if (error)
814 panic("%s: dirty1", __func__);
815
816 /*
817 * Step 2: re-read superblock from disk. XXX: We don't handle
818 * possibility that superblock moved. Which implies that we don't
819 * want its size to change either.
820 */
821 fs = ump->um_fs;
822 fs_sbsize = fs->fs_sbsize;
823 error = bread(devvp, fs->fs_sblockloc / DEV_BSIZE, fs_sbsize,
824 0, &bp);
825 if (error)
826 return (error);
827 newfs = kmem_alloc(fs_sbsize, KM_SLEEP);
828 memcpy(newfs, bp->b_data, fs_sbsize);
829
830 #ifdef FFS_EI
831 if (ump->um_flags & UFS_NEEDSWAP) {
832 ffs_sb_swap((struct fs *)bp->b_data, newfs);
833 newfs->fs_flags |= FS_SWAPPED;
834 } else
835 #endif
836 newfs->fs_flags &= ~FS_SWAPPED;
837
838 brelse(bp, 0);
839
840 if ((newfs->fs_magic != FS_UFS1_MAGIC) &&
841 (newfs->fs_magic != FS_UFS2_MAGIC)) {
842 kmem_free(newfs, fs_sbsize);
843 return (EIO); /* XXX needs translation */
844 }
845 if (!ffs_superblock_validate(newfs)) {
846 kmem_free(newfs, fs_sbsize);
847 return (EINVAL);
848 }
849
850 /*
851 * The current implementation doesn't handle the possibility that
852 * these values may have changed.
853 */
854 if ((newfs->fs_sbsize != fs_sbsize) ||
855 (newfs->fs_cssize != fs->fs_cssize) ||
856 (newfs->fs_contigsumsize != fs->fs_contigsumsize) ||
857 (newfs->fs_ncg != fs->fs_ncg)) {
858 kmem_free(newfs, fs_sbsize);
859 return (EINVAL);
860 }
861
862 /* Store off old fs_sblockloc for fs_oldfscompat_read. */
863 sblockloc = fs->fs_sblockloc;
864 /*
865 * Copy pointer fields back into superblock before copying in XXX
866 * new superblock. These should really be in the ufsmount. XXX
867 * Note that important parameters (eg fs_ncg) are unchanged.
868 */
869 newfs->fs_csp = fs->fs_csp;
870 newfs->fs_maxcluster = fs->fs_maxcluster;
871 newfs->fs_contigdirs = fs->fs_contigdirs;
872 newfs->fs_ronly = fs->fs_ronly;
873 newfs->fs_active = fs->fs_active;
874 memcpy(fs, newfs, (u_int)fs_sbsize);
875 kmem_free(newfs, fs_sbsize);
876
877 /*
878 * Recheck for Apple UFS filesystem.
879 */
880 ump->um_flags &= ~UFS_ISAPPLEUFS;
881 if (ffs_is_appleufs(devvp, fs)) {
882 #ifdef APPLE_UFS
883 ump->um_flags |= UFS_ISAPPLEUFS;
884 #else
885 DPRINTF("AppleUFS not supported");
886 return (EIO); /* XXX: really? */
887 #endif
888 }
889
890 if (UFS_MPISAPPLEUFS(ump)) {
891 /* see comment about NeXT below */
892 ump->um_maxsymlinklen = APPLEUFS_MAXSYMLINKLEN;
893 ump->um_dirblksiz = APPLEUFS_DIRBLKSIZ;
894 mp->mnt_iflag |= IMNT_DTYPE;
895 } else {
896 ump->um_maxsymlinklen = fs->fs_maxsymlinklen;
897 ump->um_dirblksiz = UFS_DIRBLKSIZ;
898 if (ump->um_maxsymlinklen > 0)
899 mp->mnt_iflag |= IMNT_DTYPE;
900 else
901 mp->mnt_iflag &= ~IMNT_DTYPE;
902 }
903 ffs_oldfscompat_read(fs, ump, sblockloc);
904
905 ffs_acls(mp, 0);
906
907 mutex_enter(&ump->um_lock);
908 ump->um_maxfilesize = fs->fs_maxfilesize;
909 if (fs->fs_flags & ~(FS_KNOWN_FLAGS | FS_INTERNAL)) {
910 uprintf("%s: unknown ufs flags: 0x%08"PRIx32"%s\n",
911 mp->mnt_stat.f_mntonname, fs->fs_flags,
912 (mp->mnt_flag & MNT_FORCE) ? "" : ", not mounting");
913 if ((mp->mnt_flag & MNT_FORCE) == 0) {
914 mutex_exit(&ump->um_lock);
915 return (EINVAL);
916 }
917 }
918
919 if (fs->fs_pendingblocks != 0 || fs->fs_pendinginodes != 0) {
920 fs->fs_pendingblocks = 0;
921 fs->fs_pendinginodes = 0;
922 }
923 mutex_exit(&ump->um_lock);
924
925 ffs_statvfs(mp, &mp->mnt_stat);
926 /*
927 * Step 3: re-read summary information from disk.
928 */
929 blks = howmany(fs->fs_cssize, fs->fs_fsize);
930 space = fs->fs_csp;
931 for (i = 0; i < blks; i += fs->fs_frag) {
932 bsize = fs->fs_bsize;
933 if (i + fs->fs_frag > blks)
934 bsize = (blks - i) * fs->fs_fsize;
935 error = bread(devvp, FFS_FSBTODB(fs, fs->fs_csaddr + i), bsize,
936 0, &bp);
937 if (error) {
938 return (error);
939 }
940 #ifdef FFS_EI
941 if (UFS_FSNEEDSWAP(fs))
942 ffs_csum_swap((struct csum *)bp->b_data,
943 (struct csum *)space, bsize);
944 else
945 #endif
946 memcpy(space, bp->b_data, (size_t)bsize);
947 space = (char *)space + bsize;
948 brelse(bp, 0);
949 }
950 /*
951 * We no longer know anything about clusters per cylinder group.
952 */
953 if (fs->fs_contigsumsize > 0) {
954 lp = fs->fs_maxcluster;
955 for (i = 0; i < fs->fs_ncg; i++)
956 *lp++ = fs->fs_contigsumsize;
957 }
958
959 vfs_vnode_iterator_init(mp, &marker);
960 while ((vp = vfs_vnode_iterator_next(marker, NULL, NULL))) {
961 /*
962 * Step 4: invalidate all inactive vnodes.
963 */
964 if (vrecycle(vp))
965 continue;
966 /*
967 * Step 5: invalidate all cached file data.
968 */
969 if (vn_lock(vp, LK_EXCLUSIVE)) {
970 vrele(vp);
971 continue;
972 }
973 if (vinvalbuf(vp, 0, cred, l, 0, 0))
974 panic("%s: dirty2", __func__);
975 /*
976 * Step 6: re-read inode data for all active vnodes.
977 */
978 ip = VTOI(vp);
979 error = bread(devvp, FFS_FSBTODB(fs, ino_to_fsba(fs, ip->i_number)),
980 (int)fs->fs_bsize, 0, &bp);
981 if (error) {
982 vput(vp);
983 break;
984 }
985 ffs_load_inode(bp, ip, fs, ip->i_number);
986 brelse(bp, 0);
987 vput(vp);
988 }
989 vfs_vnode_iterator_destroy(marker);
990 return (error);
991 }
992
993 /*
994 * Possible superblock locations ordered from most to least likely.
995 */
996 static const int sblock_try[] = SBLOCKSEARCH;
997
998
999 static int
1000 ffs_superblock_validate(struct fs *fs)
1001 {
1002 int32_t i, fs_bshift = 0, fs_fshift = 0, fs_fragshift = 0, fs_frag;
1003 int32_t fs_inopb;
1004
1005 /* Check the superblock size */
1006 if (fs->fs_sbsize > SBLOCKSIZE || fs->fs_sbsize < sizeof(struct fs))
1007 return 0;
1008
1009 /* Check the file system blocksize */
1010 if (fs->fs_bsize > MAXBSIZE || fs->fs_bsize < MINBSIZE)
1011 return 0;
1012 if (!powerof2(fs->fs_bsize))
1013 return 0;
1014
1015 /* Check the size of frag blocks */
1016 if (!powerof2(fs->fs_fsize))
1017 return 0;
1018 if (fs->fs_fsize == 0)
1019 return 0;
1020
1021 /*
1022 * XXX: these values are just zero-checked to prevent obvious
1023 * bugs. We need more strict checks.
1024 */
1025 if (fs->fs_size == 0 && fs->fs_old_size == 0)
1026 return 0;
1027 if (fs->fs_cssize == 0)
1028 return 0;
1029 if (fs->fs_ipg == 0)
1030 return 0;
1031 if (fs->fs_fpg == 0)
1032 return 0;
1033 if (fs->fs_ncg == 0)
1034 return 0;
1035 if (fs->fs_maxbpg == 0)
1036 return 0;
1037
1038 /* Check the number of inodes per block */
1039 if (fs->fs_magic == FS_UFS1_MAGIC)
1040 fs_inopb = fs->fs_bsize / sizeof(struct ufs1_dinode);
1041 else /* fs->fs_magic == FS_UFS2_MAGIC */
1042 fs_inopb = fs->fs_bsize / sizeof(struct ufs2_dinode);
1043 if (fs->fs_inopb != fs_inopb)
1044 return 0;
1045
1046 /* Block size cannot be smaller than fragment size */
1047 if (fs->fs_bsize < fs->fs_fsize)
1048 return 0;
1049
1050 /* Compute fs_bshift and ensure it is consistent */
1051 for (i = fs->fs_bsize; i > 1; i >>= 1)
1052 fs_bshift++;
1053 if (fs->fs_bshift != fs_bshift)
1054 return 0;
1055
1056 /* Compute fs_fshift and ensure it is consistent */
1057 for (i = fs->fs_fsize; i > 1; i >>= 1)
1058 fs_fshift++;
1059 if (fs->fs_fshift != fs_fshift)
1060 return 0;
1061
1062 /* Compute fs_fragshift and ensure it is consistent */
1063 for (i = fs->fs_frag; i > 1; i >>= 1)
1064 fs_fragshift++;
1065 if (fs->fs_fragshift != fs_fragshift)
1066 return 0;
1067
1068 /* Check the masks */
1069 if (fs->fs_bmask != ~(fs->fs_bsize - 1))
1070 return 0;
1071 if (fs->fs_fmask != ~(fs->fs_fsize - 1))
1072 return 0;
1073
1074 /*
1075 * Now that the shifts and masks are sanitized, we can use the ffs_ API.
1076 */
1077
1078 /* Check the number of frag blocks */
1079 if ((fs_frag = ffs_numfrags(fs, fs->fs_bsize)) > MAXFRAG)
1080 return 0;
1081 if (fs->fs_frag != fs_frag)
1082 return 0;
1083
1084 /* Check the size of cylinder groups */
1085 if ((fs->fs_cgsize < sizeof(struct cg)) ||
1086 (fs->fs_cgsize > fs->fs_bsize))
1087 return 0;
1088
1089 return 1;
1090 }
1091
1092 static int
1093 ffs_is_appleufs(struct vnode *devvp, struct fs *fs)
1094 {
1095 struct dkwedge_info dkw;
1096 int ret = 0;
1097
1098 /*
1099 * First check to see if this is tagged as an Apple UFS filesystem
1100 * in the disklabel.
1101 */
1102 if (getdiskinfo(devvp, &dkw) == 0 &&
1103 strcmp(dkw.dkw_ptype, DKW_PTYPE_APPLEUFS) == 0)
1104 ret = 1;
1105 #ifdef APPLE_UFS
1106 else {
1107 struct appleufslabel *applefs;
1108 struct buf *bp;
1109 daddr_t blkno = APPLEUFS_LABEL_OFFSET / DEV_BSIZE;
1110 int error;
1111
1112 /*
1113 * Manually look for an Apple UFS label, and if a valid one
1114 * is found, then treat it like an Apple UFS filesystem anyway.
1115 */
1116 error = bread(devvp, blkno, APPLEUFS_LABEL_SIZE, 0, &bp);
1117 if (error) {
1118 DPRINTF("bread@0x%jx returned %d", (intmax_t)blkno, error);
1119 return 0;
1120 }
1121 applefs = (struct appleufslabel *)bp->b_data;
1122 error = ffs_appleufs_validate(fs->fs_fsmnt, applefs, NULL);
1123 if (error == 0)
1124 ret = 1;
1125 brelse(bp, 0);
1126 }
1127 #endif
1128
1129 return ret;
1130 }
1131
1132 /*
1133 * Common code for mount and mountroot
1134 */
1135 int
1136 ffs_mountfs(struct vnode *devvp, struct mount *mp, struct lwp *l)
1137 {
1138 struct ufsmount *ump = NULL;
1139 struct buf *bp = NULL;
1140 struct fs *fs = NULL;
1141 dev_t dev;
1142 void *space;
1143 daddr_t sblockloc = 0;
1144 int blks, fstype = 0;
1145 int error, i, bsize, ronly, bset = 0;
1146 #ifdef FFS_EI
1147 int needswap = 0; /* keep gcc happy */
1148 #endif
1149 int32_t *lp;
1150 kauth_cred_t cred;
1151 u_int32_t allocsbsize, fs_sbsize = 0;
1152
1153 dev = devvp->v_rdev;
1154 cred = l ? l->l_cred : NOCRED;
1155
1156 /* Flush out any old buffers remaining from a previous use. */
1157 vn_lock(devvp, LK_EXCLUSIVE | LK_RETRY);
1158 error = vinvalbuf(devvp, V_SAVE, cred, l, 0, 0);
1159 VOP_UNLOCK(devvp);
1160 if (error) {
1161 DPRINTF("vinvalbuf returned %d", error);
1162 return error;
1163 }
1164
1165 ronly = (mp->mnt_flag & MNT_RDONLY) != 0;
1166
1167 ump = kmem_zalloc(sizeof(*ump), KM_SLEEP);
1168 mutex_init(&ump->um_lock, MUTEX_DEFAULT, IPL_NONE);
1169 error = ffs_snapshot_init(ump);
1170 if (error) {
1171 DPRINTF("ffs_snapshot_init returned %d", error);
1172 goto out;
1173 }
1174 ump->um_ops = &ffs_ufsops;
1175
1176 #ifdef WAPBL
1177 sbagain:
1178 #endif
1179 /*
1180 * Try reading the superblock in each of its possible locations.
1181 */
1182 for (i = 0; ; i++) {
1183 daddr_t fs_sblockloc;
1184
1185 if (bp != NULL) {
1186 brelse(bp, BC_NOCACHE);
1187 bp = NULL;
1188 }
1189 if (sblock_try[i] == -1) {
1190 DPRINTF("no superblock found");
1191 error = EINVAL;
1192 fs = NULL;
1193 goto out;
1194 }
1195
1196 error = bread(devvp, sblock_try[i] / DEV_BSIZE, SBLOCKSIZE,
1197 0, &bp);
1198 if (error) {
1199 DPRINTF("bread@0x%x returned %d",
1200 sblock_try[i] / DEV_BSIZE, error);
1201 fs = NULL;
1202 goto out;
1203 }
1204 fs = (struct fs *)bp->b_data;
1205
1206 sblockloc = sblock_try[i];
1207 DPRINTF("fs_magic 0x%x", fs->fs_magic);
1208
1209 /*
1210 * Swap: here, we swap fs->fs_sbsize in order to get the correct
1211 * size to read the superblock. Once read, we swap the whole
1212 * superblock structure.
1213 */
1214 if (fs->fs_magic == FS_UFS1_MAGIC) {
1215 fs_sbsize = fs->fs_sbsize;
1216 fstype = UFS1;
1217 #ifdef FFS_EI
1218 needswap = 0;
1219 } else if (fs->fs_magic == FS_UFS1_MAGIC_SWAPPED) {
1220 fs_sbsize = bswap32(fs->fs_sbsize);
1221 fstype = UFS1;
1222 needswap = 1;
1223 #endif
1224 } else if (fs->fs_magic == FS_UFS2_MAGIC) {
1225 fs_sbsize = fs->fs_sbsize;
1226 fstype = UFS2;
1227 #ifdef FFS_EI
1228 needswap = 0;
1229 } else if (fs->fs_magic == FS_UFS2_MAGIC_SWAPPED) {
1230 fs_sbsize = bswap32(fs->fs_sbsize);
1231 fstype = UFS2;
1232 needswap = 1;
1233 #endif
1234 } else
1235 continue;
1236
1237 /* fs->fs_sblockloc isn't defined for old filesystems */
1238 if (fstype == UFS1 && !(fs->fs_old_flags & FS_FLAGS_UPDATED)) {
1239 if (sblockloc == SBLOCK_UFS2)
1240 /*
1241 * This is likely to be the first alternate
1242 * in a filesystem with 64k blocks.
1243 * Don't use it.
1244 */
1245 continue;
1246 fs_sblockloc = sblockloc;
1247 } else {
1248 fs_sblockloc = fs->fs_sblockloc;
1249 #ifdef FFS_EI
1250 if (needswap)
1251 fs_sblockloc = bswap64(fs_sblockloc);
1252 #endif
1253 }
1254
1255 /* Check we haven't found an alternate superblock */
1256 if (fs_sblockloc != sblockloc)
1257 continue;
1258
1259 /* Check the superblock size */
1260 if (fs_sbsize > SBLOCKSIZE || fs_sbsize < sizeof(struct fs))
1261 continue;
1262 fs = kmem_alloc((u_long)fs_sbsize, KM_SLEEP);
1263 memcpy(fs, bp->b_data, fs_sbsize);
1264
1265 /* Swap the whole superblock structure, if necessary. */
1266 #ifdef FFS_EI
1267 if (needswap) {
1268 ffs_sb_swap((struct fs*)bp->b_data, fs);
1269 fs->fs_flags |= FS_SWAPPED;
1270 } else
1271 #endif
1272 fs->fs_flags &= ~FS_SWAPPED;
1273
1274 /*
1275 * Now that everything is swapped, the superblock is ready to
1276 * be sanitized.
1277 */
1278 if (!ffs_superblock_validate(fs)) {
1279 kmem_free(fs, fs_sbsize);
1280 continue;
1281 }
1282
1283 /* Ok seems to be a good superblock */
1284 break;
1285 }
1286
1287 ump->um_fs = fs;
1288
1289 #ifdef WAPBL
1290 if ((mp->mnt_wapbl_replay == 0) && (fs->fs_flags & FS_DOWAPBL)) {
1291 error = ffs_wapbl_replay_start(mp, fs, devvp);
1292 if (error && (mp->mnt_flag & MNT_FORCE) == 0) {
1293 DPRINTF("ffs_wapbl_replay_start returned %d", error);
1294 goto out;
1295 }
1296 if (!error) {
1297 if (!ronly) {
1298 /* XXX fsmnt may be stale. */
1299 printf("%s: replaying log to disk\n",
1300 fs->fs_fsmnt);
1301 error = wapbl_replay_write(mp->mnt_wapbl_replay,
1302 devvp);
1303 if (error) {
1304 DPRINTF("wapbl_replay_write returned %d",
1305 error);
1306 goto out;
1307 }
1308 wapbl_replay_stop(mp->mnt_wapbl_replay);
1309 fs->fs_clean = FS_WASCLEAN;
1310 } else {
1311 /* XXX fsmnt may be stale */
1312 printf("%s: replaying log to memory\n",
1313 fs->fs_fsmnt);
1314 }
1315
1316 /* Force a re-read of the superblock */
1317 brelse(bp, BC_INVAL);
1318 bp = NULL;
1319 kmem_free(fs, fs_sbsize);
1320 fs = NULL;
1321 goto sbagain;
1322 }
1323 }
1324 #else /* !WAPBL */
1325 if ((fs->fs_flags & FS_DOWAPBL) && (mp->mnt_flag & MNT_FORCE) == 0) {
1326 error = EPERM;
1327 DPRINTF("no force %d", error);
1328 goto out;
1329 }
1330 #endif /* !WAPBL */
1331
1332 ffs_oldfscompat_read(fs, ump, sblockloc);
1333 ump->um_maxfilesize = fs->fs_maxfilesize;
1334
1335 if (fs->fs_flags & ~(FS_KNOWN_FLAGS | FS_INTERNAL)) {
1336 uprintf("%s: unknown ufs flags: 0x%08"PRIx32"%s\n",
1337 mp->mnt_stat.f_mntonname, fs->fs_flags,
1338 (mp->mnt_flag & MNT_FORCE) ? "" : ", not mounting");
1339 if ((mp->mnt_flag & MNT_FORCE) == 0) {
1340 error = EINVAL;
1341 DPRINTF("no force %d", error);
1342 goto out;
1343 }
1344 }
1345
1346 if (fs->fs_pendingblocks != 0 || fs->fs_pendinginodes != 0) {
1347 fs->fs_pendingblocks = 0;
1348 fs->fs_pendinginodes = 0;
1349 }
1350
1351 ump->um_fstype = fstype;
1352 if (fs->fs_sbsize < SBLOCKSIZE)
1353 brelse(bp, BC_INVAL);
1354 else
1355 brelse(bp, 0);
1356 bp = NULL;
1357
1358 if (ffs_is_appleufs(devvp, fs)) {
1359 #ifdef APPLE_UFS
1360 ump->um_flags |= UFS_ISAPPLEUFS;
1361 #else
1362 DPRINTF("AppleUFS not supported");
1363 error = EINVAL;
1364 goto out;
1365 #endif
1366 }
1367
1368 #if 0
1369 /*
1370 * XXX This code changes the behaviour of mounting dirty filesystems, to
1371 * XXX require "mount -f ..." to mount them. This doesn't match what
1372 * XXX mount(8) describes and is disabled for now.
1373 */
1374 /*
1375 * If the file system is not clean, don't allow it to be mounted
1376 * unless MNT_FORCE is specified. (Note: MNT_FORCE is always set
1377 * for the root file system.)
1378 */
1379 if (fs->fs_flags & FS_DOWAPBL) {
1380 /*
1381 * wapbl normally expects to be FS_WASCLEAN when the FS_DOWAPBL
1382 * bit is set, although there's a window in unmount where it
1383 * could be FS_ISCLEAN
1384 */
1385 if ((mp->mnt_flag & MNT_FORCE) == 0 &&
1386 (fs->fs_clean & (FS_WASCLEAN | FS_ISCLEAN)) == 0) {
1387 error = EPERM;
1388 goto out;
1389 }
1390 } else
1391 if ((fs->fs_clean & FS_ISCLEAN) == 0 &&
1392 (mp->mnt_flag & MNT_FORCE) == 0) {
1393 error = EPERM;
1394 goto out;
1395 }
1396 #endif
1397
1398 /*
1399 * Verify that we can access the last block in the fs
1400 * if we're mounting read/write.
1401 */
1402 if (!ronly) {
1403 error = bread(devvp, FFS_FSBTODB(fs, fs->fs_size - 1),
1404 fs->fs_fsize, 0, &bp);
1405 if (error) {
1406 DPRINTF("bread@0x%jx returned %d",
1407 (intmax_t)FFS_FSBTODB(fs, fs->fs_size - 1),
1408 error);
1409 bset = BC_INVAL;
1410 goto out;
1411 }
1412 if (bp->b_bcount != fs->fs_fsize) {
1413 DPRINTF("bcount %x != fsize %x", bp->b_bcount,
1414 fs->fs_fsize);
1415 error = EINVAL;
1416 bset = BC_INVAL;
1417 goto out;
1418 }
1419 brelse(bp, BC_INVAL);
1420 bp = NULL;
1421 }
1422
1423 fs->fs_ronly = ronly;
1424 /* Don't bump fs_clean if we're replaying journal */
1425 if (!((fs->fs_flags & FS_DOWAPBL) && (fs->fs_clean & FS_WASCLEAN))) {
1426 if (ronly == 0) {
1427 fs->fs_clean <<= 1;
1428 fs->fs_fmod = 1;
1429 }
1430 }
1431
1432 bsize = fs->fs_cssize;
1433 blks = howmany(bsize, fs->fs_fsize);
1434 if (fs->fs_contigsumsize > 0)
1435 bsize += fs->fs_ncg * sizeof(int32_t);
1436 bsize += fs->fs_ncg * sizeof(*fs->fs_contigdirs);
1437 allocsbsize = bsize;
1438 space = kmem_alloc((u_long)allocsbsize, KM_SLEEP);
1439 fs->fs_csp = space;
1440
1441 for (i = 0; i < blks; i += fs->fs_frag) {
1442 bsize = fs->fs_bsize;
1443 if (i + fs->fs_frag > blks)
1444 bsize = (blks - i) * fs->fs_fsize;
1445 error = bread(devvp, FFS_FSBTODB(fs, fs->fs_csaddr + i), bsize,
1446 0, &bp);
1447 if (error) {
1448 DPRINTF("bread@0x%jx %d",
1449 (intmax_t)FFS_FSBTODB(fs, fs->fs_csaddr + i),
1450 error);
1451 goto out1;
1452 }
1453 #ifdef FFS_EI
1454 if (needswap)
1455 ffs_csum_swap((struct csum *)bp->b_data,
1456 (struct csum *)space, bsize);
1457 else
1458 #endif
1459 memcpy(space, bp->b_data, (u_int)bsize);
1460
1461 space = (char *)space + bsize;
1462 brelse(bp, 0);
1463 bp = NULL;
1464 }
1465 if (fs->fs_contigsumsize > 0) {
1466 fs->fs_maxcluster = lp = space;
1467 for (i = 0; i < fs->fs_ncg; i++)
1468 *lp++ = fs->fs_contigsumsize;
1469 space = lp;
1470 }
1471 bsize = fs->fs_ncg * sizeof(*fs->fs_contigdirs);
1472 fs->fs_contigdirs = space;
1473 space = (char *)space + bsize;
1474 memset(fs->fs_contigdirs, 0, bsize);
1475
1476 /* Compatibility for old filesystems - XXX */
1477 if (fs->fs_avgfilesize <= 0)
1478 fs->fs_avgfilesize = AVFILESIZ;
1479 if (fs->fs_avgfpdir <= 0)
1480 fs->fs_avgfpdir = AFPDIR;
1481 fs->fs_active = NULL;
1482
1483 mp->mnt_data = ump;
1484 mp->mnt_stat.f_fsidx.__fsid_val[0] = (long)dev;
1485 mp->mnt_stat.f_fsidx.__fsid_val[1] = makefstype(MOUNT_FFS);
1486 mp->mnt_stat.f_fsid = mp->mnt_stat.f_fsidx.__fsid_val[0];
1487 mp->mnt_stat.f_namemax = FFS_MAXNAMLEN;
1488 if (UFS_MPISAPPLEUFS(ump)) {
1489 /* NeXT used to keep short symlinks in the inode even
1490 * when using FS_42INODEFMT. In that case fs->fs_maxsymlinklen
1491 * is probably -1, but we still need to be able to identify
1492 * short symlinks.
1493 */
1494 ump->um_maxsymlinklen = APPLEUFS_MAXSYMLINKLEN;
1495 ump->um_dirblksiz = APPLEUFS_DIRBLKSIZ;
1496 mp->mnt_iflag |= IMNT_DTYPE;
1497 } else {
1498 ump->um_maxsymlinklen = fs->fs_maxsymlinklen;
1499 ump->um_dirblksiz = UFS_DIRBLKSIZ;
1500 if (ump->um_maxsymlinklen > 0)
1501 mp->mnt_iflag |= IMNT_DTYPE;
1502 else
1503 mp->mnt_iflag &= ~IMNT_DTYPE;
1504 }
1505 mp->mnt_fs_bshift = fs->fs_bshift;
1506 mp->mnt_dev_bshift = DEV_BSHIFT; /* XXX */
1507 mp->mnt_flag |= MNT_LOCAL;
1508 mp->mnt_iflag |= IMNT_MPSAFE | IMNT_CAN_RWTORO | IMNT_SHRLOOKUP |
1509 IMNT_NCLOOKUP;
1510 #ifdef FFS_EI
1511 if (needswap)
1512 ump->um_flags |= UFS_NEEDSWAP;
1513 #endif
1514 ffs_acls(mp, fs->fs_flags);
1515 ump->um_mountp = mp;
1516 ump->um_dev = dev;
1517 ump->um_devvp = devvp;
1518 ump->um_nindir = fs->fs_nindir;
1519 ump->um_lognindir = ffs(fs->fs_nindir) - 1;
1520 ump->um_bptrtodb = fs->fs_fshift - DEV_BSHIFT;
1521 ump->um_seqinc = fs->fs_frag;
1522 for (i = 0; i < MAXQUOTAS; i++)
1523 ump->um_quotas[i] = NULLVP;
1524 spec_node_setmountedfs(devvp, mp);
1525 if (ronly == 0 && fs->fs_snapinum[0] != 0)
1526 ffs_snapshot_mount(mp);
1527 #ifdef WAPBL
1528 if (!ronly) {
1529 KDASSERT(fs->fs_ronly == 0);
1530 /*
1531 * ffs_wapbl_start() needs mp->mnt_stat initialised if it
1532 * needs to create a new log file in-filesystem.
1533 */
1534 error = ffs_statvfs(mp, &mp->mnt_stat);
1535 if (error) {
1536 DPRINTF("ffs_statvfs returned %d", error);
1537 goto out1;
1538 }
1539
1540 error = ffs_wapbl_start(mp);
1541 if (error) {
1542 DPRINTF("ffs_wapbl_start returned %d", error);
1543 goto out1;
1544 }
1545 }
1546 #endif /* WAPBL */
1547 if (ronly == 0) {
1548 #ifdef QUOTA2
1549 error = ffs_quota2_mount(mp);
1550 if (error) {
1551 DPRINTF("ffs_quota2_mount returned %d", error);
1552 goto out1;
1553 }
1554 #else
1555 if (fs->fs_flags & FS_DOQUOTA2) {
1556 ump->um_flags |= UFS_QUOTA2;
1557 uprintf("%s: options QUOTA2 not enabled%s\n",
1558 mp->mnt_stat.f_mntonname,
1559 (mp->mnt_flag & MNT_FORCE) ? "" : ", not mounting");
1560 if ((mp->mnt_flag & MNT_FORCE) == 0) {
1561 error = EINVAL;
1562 DPRINTF("quota disabled %d", error);
1563 goto out1;
1564 }
1565 }
1566 #endif
1567 }
1568
1569 if (mp->mnt_flag & MNT_DISCARD)
1570 ump->um_discarddata = ffs_discard_init(devvp, fs);
1571
1572 return (0);
1573 out1:
1574 kmem_free(fs->fs_csp, allocsbsize);
1575 out:
1576 #ifdef WAPBL
1577 if (mp->mnt_wapbl_replay) {
1578 wapbl_replay_stop(mp->mnt_wapbl_replay);
1579 wapbl_replay_free(mp->mnt_wapbl_replay);
1580 mp->mnt_wapbl_replay = 0;
1581 }
1582 #endif
1583
1584 if (fs)
1585 kmem_free(fs, fs->fs_sbsize);
1586 spec_node_setmountedfs(devvp, NULL);
1587 if (bp)
1588 brelse(bp, bset);
1589 if (ump) {
1590 if (ump->um_oldfscompat)
1591 kmem_free(ump->um_oldfscompat, 512 + 3*sizeof(int32_t));
1592 mutex_destroy(&ump->um_lock);
1593 kmem_free(ump, sizeof(*ump));
1594 mp->mnt_data = NULL;
1595 }
1596 return (error);
1597 }
1598
1599 /*
1600 * Sanity checks for loading old filesystem superblocks.
1601 * See ffs_oldfscompat_write below for unwound actions.
1602 *
1603 * XXX - Parts get retired eventually.
1604 * Unfortunately new bits get added.
1605 */
1606 static void
1607 ffs_oldfscompat_read(struct fs *fs, struct ufsmount *ump, daddr_t sblockloc)
1608 {
1609 off_t maxfilesize;
1610 int32_t *extrasave;
1611
1612 if ((fs->fs_magic != FS_UFS1_MAGIC) ||
1613 (fs->fs_old_flags & FS_FLAGS_UPDATED))
1614 return;
1615
1616 if (!ump->um_oldfscompat)
1617 ump->um_oldfscompat = kmem_alloc(512 + 3*sizeof(int32_t),
1618 KM_SLEEP);
1619
1620 memcpy(ump->um_oldfscompat, &fs->fs_old_postbl_start, 512);
1621 extrasave = ump->um_oldfscompat;
1622 extrasave += 512/sizeof(int32_t);
1623 extrasave[0] = fs->fs_old_npsect;
1624 extrasave[1] = fs->fs_old_interleave;
1625 extrasave[2] = fs->fs_old_trackskew;
1626
1627 /* These fields will be overwritten by their
1628 * original values in fs_oldfscompat_write, so it is harmless
1629 * to modify them here.
1630 */
1631 fs->fs_cstotal.cs_ndir = fs->fs_old_cstotal.cs_ndir;
1632 fs->fs_cstotal.cs_nbfree = fs->fs_old_cstotal.cs_nbfree;
1633 fs->fs_cstotal.cs_nifree = fs->fs_old_cstotal.cs_nifree;
1634 fs->fs_cstotal.cs_nffree = fs->fs_old_cstotal.cs_nffree;
1635
1636 fs->fs_maxbsize = fs->fs_bsize;
1637 fs->fs_time = fs->fs_old_time;
1638 fs->fs_size = fs->fs_old_size;
1639 fs->fs_dsize = fs->fs_old_dsize;
1640 fs->fs_csaddr = fs->fs_old_csaddr;
1641 fs->fs_sblockloc = sblockloc;
1642
1643 fs->fs_flags = fs->fs_old_flags | (fs->fs_flags & FS_INTERNAL);
1644
1645 if (fs->fs_old_postblformat == FS_42POSTBLFMT) {
1646 fs->fs_old_nrpos = 8;
1647 fs->fs_old_npsect = fs->fs_old_nsect;
1648 fs->fs_old_interleave = 1;
1649 fs->fs_old_trackskew = 0;
1650 }
1651
1652 if (fs->fs_magic == FS_UFS1_MAGIC &&
1653 fs->fs_old_inodefmt < FS_44INODEFMT) {
1654 fs->fs_maxfilesize = (u_quad_t) 1LL << 39;
1655 fs->fs_qbmask = ~fs->fs_bmask;
1656 fs->fs_qfmask = ~fs->fs_fmask;
1657 }
1658
1659 maxfilesize = (u_int64_t)0x80000000 * fs->fs_bsize - 1;
1660 if (fs->fs_maxfilesize > maxfilesize)
1661 fs->fs_maxfilesize = maxfilesize;
1662
1663 /* Compatibility for old filesystems */
1664 if (fs->fs_avgfilesize <= 0)
1665 fs->fs_avgfilesize = AVFILESIZ;
1666 if (fs->fs_avgfpdir <= 0)
1667 fs->fs_avgfpdir = AFPDIR;
1668
1669 #if 0
1670 if (bigcgs) {
1671 fs->fs_save_cgsize = fs->fs_cgsize;
1672 fs->fs_cgsize = fs->fs_bsize;
1673 }
1674 #endif
1675 }
1676
1677 /*
1678 * Unwinding superblock updates for old filesystems.
1679 * See ffs_oldfscompat_read above for details.
1680 *
1681 * XXX - Parts get retired eventually.
1682 * Unfortunately new bits get added.
1683 */
1684 static void
1685 ffs_oldfscompat_write(struct fs *fs, struct ufsmount *ump)
1686 {
1687 int32_t *extrasave;
1688
1689 if ((fs->fs_magic != FS_UFS1_MAGIC) ||
1690 (fs->fs_old_flags & FS_FLAGS_UPDATED))
1691 return;
1692
1693 fs->fs_old_time = fs->fs_time;
1694 fs->fs_old_cstotal.cs_ndir = fs->fs_cstotal.cs_ndir;
1695 fs->fs_old_cstotal.cs_nbfree = fs->fs_cstotal.cs_nbfree;
1696 fs->fs_old_cstotal.cs_nifree = fs->fs_cstotal.cs_nifree;
1697 fs->fs_old_cstotal.cs_nffree = fs->fs_cstotal.cs_nffree;
1698 fs->fs_old_flags = fs->fs_flags;
1699
1700 #if 0
1701 if (bigcgs) {
1702 fs->fs_cgsize = fs->fs_save_cgsize;
1703 }
1704 #endif
1705
1706 memcpy(&fs->fs_old_postbl_start, ump->um_oldfscompat, 512);
1707 extrasave = ump->um_oldfscompat;
1708 extrasave += 512/sizeof(int32_t);
1709 fs->fs_old_npsect = extrasave[0];
1710 fs->fs_old_interleave = extrasave[1];
1711 fs->fs_old_trackskew = extrasave[2];
1712
1713 }
1714
1715 /*
1716 * unmount vfs operation
1717 */
1718 int
1719 ffs_unmount(struct mount *mp, int mntflags)
1720 {
1721 struct lwp *l = curlwp;
1722 struct ufsmount *ump = VFSTOUFS(mp);
1723 struct fs *fs = ump->um_fs;
1724 int error, flags;
1725 u_int32_t bsize;
1726 #ifdef WAPBL
1727 extern int doforce;
1728 #endif
1729
1730 if (ump->um_discarddata) {
1731 ffs_discard_finish(ump->um_discarddata, mntflags);
1732 ump->um_discarddata = NULL;
1733 }
1734
1735 flags = 0;
1736 if (mntflags & MNT_FORCE)
1737 flags |= FORCECLOSE;
1738 if ((error = ffs_flushfiles(mp, flags, l)) != 0)
1739 return (error);
1740 error = UFS_WAPBL_BEGIN(mp);
1741 if (error == 0)
1742 if (fs->fs_ronly == 0 &&
1743 ffs_cgupdate(ump, MNT_WAIT) == 0 &&
1744 fs->fs_clean & FS_WASCLEAN) {
1745 fs->fs_clean = FS_ISCLEAN;
1746 fs->fs_fmod = 0;
1747 (void) ffs_sbupdate(ump, MNT_WAIT);
1748 }
1749 if (error == 0)
1750 UFS_WAPBL_END(mp);
1751 #ifdef WAPBL
1752 KASSERT(!(mp->mnt_wapbl_replay && mp->mnt_wapbl));
1753 if (mp->mnt_wapbl_replay) {
1754 KDASSERT(fs->fs_ronly);
1755 wapbl_replay_stop(mp->mnt_wapbl_replay);
1756 wapbl_replay_free(mp->mnt_wapbl_replay);
1757 mp->mnt_wapbl_replay = 0;
1758 }
1759 error = ffs_wapbl_stop(mp, doforce && (mntflags & MNT_FORCE));
1760 if (error) {
1761 return error;
1762 }
1763 #endif /* WAPBL */
1764
1765 if (ump->um_devvp->v_type != VBAD)
1766 spec_node_setmountedfs(ump->um_devvp, NULL);
1767 vn_lock(ump->um_devvp, LK_EXCLUSIVE | LK_RETRY);
1768 (void)VOP_CLOSE(ump->um_devvp, fs->fs_ronly ? FREAD : FREAD | FWRITE,
1769 NOCRED);
1770 vput(ump->um_devvp);
1771
1772 bsize = fs->fs_cssize;
1773 if (fs->fs_contigsumsize > 0)
1774 bsize += fs->fs_ncg * sizeof(int32_t);
1775 bsize += fs->fs_ncg * sizeof(*fs->fs_contigdirs);
1776 kmem_free(fs->fs_csp, bsize);
1777
1778 kmem_free(fs, fs->fs_sbsize);
1779 if (ump->um_oldfscompat != NULL)
1780 kmem_free(ump->um_oldfscompat, 512 + 3*sizeof(int32_t));
1781 mutex_destroy(&ump->um_lock);
1782 ffs_snapshot_fini(ump);
1783 kmem_free(ump, sizeof(*ump));
1784 mp->mnt_data = NULL;
1785 mp->mnt_flag &= ~MNT_LOCAL;
1786 return (0);
1787 }
1788
1789 /*
1790 * Flush out all the files in a filesystem.
1791 */
1792 int
1793 ffs_flushfiles(struct mount *mp, int flags, struct lwp *l)
1794 {
1795 extern int doforce;
1796 struct ufsmount *ump;
1797 int error;
1798
1799 if (!doforce)
1800 flags &= ~FORCECLOSE;
1801 ump = VFSTOUFS(mp);
1802 #ifdef QUOTA
1803 if ((error = quota1_umount(mp, flags)) != 0)
1804 return (error);
1805 #endif
1806 #ifdef QUOTA2
1807 if ((error = quota2_umount(mp, flags)) != 0)
1808 return (error);
1809 #endif
1810 #ifdef UFS_EXTATTR
1811 if (ump->um_fstype == UFS1) {
1812 if (ump->um_extattr.uepm_flags & UFS_EXTATTR_UEPM_STARTED)
1813 ufs_extattr_stop(mp, l);
1814 if (ump->um_extattr.uepm_flags & UFS_EXTATTR_UEPM_INITIALIZED)
1815 ufs_extattr_uepm_destroy(&ump->um_extattr);
1816 mp->mnt_flag &= ~MNT_EXTATTR;
1817 }
1818 #endif
1819 if ((error = vflush(mp, 0, SKIPSYSTEM | flags)) != 0)
1820 return (error);
1821 ffs_snapshot_unmount(mp);
1822 /*
1823 * Flush all the files.
1824 */
1825 error = vflush(mp, NULLVP, flags);
1826 if (error)
1827 return (error);
1828 /*
1829 * Flush filesystem metadata.
1830 */
1831 vn_lock(ump->um_devvp, LK_EXCLUSIVE | LK_RETRY);
1832 error = VOP_FSYNC(ump->um_devvp, l->l_cred, FSYNC_WAIT, 0, 0);
1833 VOP_UNLOCK(ump->um_devvp);
1834 if (flags & FORCECLOSE) /* XXXDBJ */
1835 error = 0;
1836
1837 #ifdef WAPBL
1838 if (error)
1839 return error;
1840 if (mp->mnt_wapbl) {
1841 error = wapbl_flush(mp->mnt_wapbl, 1);
1842 if (flags & FORCECLOSE)
1843 error = 0;
1844 }
1845 #endif
1846
1847 return (error);
1848 }
1849
1850 /*
1851 * Get file system statistics.
1852 */
1853 int
1854 ffs_statvfs(struct mount *mp, struct statvfs *sbp)
1855 {
1856 struct ufsmount *ump;
1857 struct fs *fs;
1858
1859 ump = VFSTOUFS(mp);
1860 fs = ump->um_fs;
1861 mutex_enter(&ump->um_lock);
1862 sbp->f_bsize = fs->fs_bsize;
1863 sbp->f_frsize = fs->fs_fsize;
1864 sbp->f_iosize = fs->fs_bsize;
1865 sbp->f_blocks = fs->fs_dsize;
1866 sbp->f_bfree = ffs_blkstofrags(fs, fs->fs_cstotal.cs_nbfree) +
1867 fs->fs_cstotal.cs_nffree + FFS_DBTOFSB(fs, fs->fs_pendingblocks);
1868 sbp->f_bresvd = ((u_int64_t) fs->fs_dsize * (u_int64_t)
1869 fs->fs_minfree) / (u_int64_t) 100;
1870 if (sbp->f_bfree > sbp->f_bresvd)
1871 sbp->f_bavail = sbp->f_bfree - sbp->f_bresvd;
1872 else
1873 sbp->f_bavail = 0;
1874 sbp->f_files = fs->fs_ncg * fs->fs_ipg - UFS_ROOTINO;
1875 sbp->f_ffree = fs->fs_cstotal.cs_nifree + fs->fs_pendinginodes;
1876 sbp->f_favail = sbp->f_ffree;
1877 sbp->f_fresvd = 0;
1878 mutex_exit(&ump->um_lock);
1879 copy_statvfs_info(sbp, mp);
1880
1881 return (0);
1882 }
1883
1884 struct ffs_sync_ctx {
1885 int waitfor;
1886 };
1887
1888 static bool
1889 ffs_sync_selector(void *cl, struct vnode *vp)
1890 {
1891 struct ffs_sync_ctx *c = cl;
1892 struct inode *ip;
1893
1894 KASSERT(mutex_owned(vp->v_interlock));
1895
1896 ip = VTOI(vp);
1897 /*
1898 * Skip the vnode/inode if inaccessible.
1899 */
1900 if (ip == NULL || vp->v_type == VNON)
1901 return false;
1902
1903 /*
1904 * We deliberately update inode times here. This will
1905 * prevent a massive queue of updates accumulating, only
1906 * to be handled by a call to unmount.
1907 *
1908 * XXX It would be better to have the syncer trickle these
1909 * out. Adjustment needed to allow registering vnodes for
1910 * sync when the vnode is clean, but the inode dirty. Or
1911 * have ufs itself trickle out inode updates.
1912 *
1913 * If doing a lazy sync, we don't care about metadata or
1914 * data updates, because they are handled by each vnode's
1915 * synclist entry. In this case we are only interested in
1916 * writing back modified inodes.
1917 */
1918 if ((ip->i_flag & (IN_ACCESS | IN_CHANGE | IN_UPDATE |
1919 IN_MODIFY | IN_MODIFIED | IN_ACCESSED)) == 0 &&
1920 (c->waitfor == MNT_LAZY || (LIST_EMPTY(&vp->v_dirtyblkhd) &&
1921 (vp->v_iflag & VI_ONWORKLST) == 0)))
1922 return false;
1923
1924 return true;
1925 }
1926
1927 /*
1928 * Go through the disk queues to initiate sandbagged IO;
1929 * go through the inodes to write those that have been modified;
1930 * initiate the writing of the super block if it has been modified.
1931 *
1932 * Note: we are always called with the filesystem marked `MPBUSY'.
1933 */
1934 int
1935 ffs_sync(struct mount *mp, int waitfor, kauth_cred_t cred)
1936 {
1937 struct vnode *vp;
1938 struct ufsmount *ump = VFSTOUFS(mp);
1939 struct fs *fs;
1940 struct vnode_iterator *marker;
1941 int error, allerror = 0;
1942 struct ffs_sync_ctx ctx;
1943
1944 fs = ump->um_fs;
1945 if (fs->fs_fmod != 0 && fs->fs_ronly != 0) { /* XXX */
1946 panic("%s: rofs mod, fs=%s", __func__, fs->fs_fsmnt);
1947 }
1948
1949 /*
1950 * Write back each (modified) inode.
1951 */
1952 vfs_vnode_iterator_init(mp, &marker);
1953
1954 ctx.waitfor = waitfor;
1955 while ((vp = vfs_vnode_iterator_next(marker, ffs_sync_selector, &ctx)))
1956 {
1957 error = vn_lock(vp,
1958 LK_EXCLUSIVE | (waitfor == MNT_LAZY ? LK_NOWAIT : 0));
1959 if (error) {
1960 vrele(vp);
1961 continue;
1962 }
1963 if (waitfor == MNT_LAZY) {
1964 error = UFS_WAPBL_BEGIN(vp->v_mount);
1965 if (!error) {
1966 error = ffs_update(vp, NULL, NULL,
1967 UPDATE_CLOSE);
1968 UFS_WAPBL_END(vp->v_mount);
1969 }
1970 } else {
1971 error = VOP_FSYNC(vp, cred, FSYNC_NOLOG |
1972 (waitfor == MNT_WAIT ? FSYNC_WAIT : 0), 0, 0);
1973 }
1974 if (error)
1975 allerror = error;
1976 vput(vp);
1977 }
1978 vfs_vnode_iterator_destroy(marker);
1979
1980 /*
1981 * Force stale file system control information to be flushed.
1982 */
1983 if (waitfor != MNT_LAZY && (ump->um_devvp->v_numoutput > 0 ||
1984 !LIST_EMPTY(&ump->um_devvp->v_dirtyblkhd))) {
1985 vn_lock(ump->um_devvp, LK_EXCLUSIVE | LK_RETRY);
1986 if ((error = VOP_FSYNC(ump->um_devvp, cred,
1987 (waitfor == MNT_WAIT ? FSYNC_WAIT : 0) | FSYNC_NOLOG,
1988 0, 0)) != 0)
1989 allerror = error;
1990 VOP_UNLOCK(ump->um_devvp);
1991 }
1992 #if defined(QUOTA) || defined(QUOTA2)
1993 qsync(mp);
1994 #endif
1995 /*
1996 * Write back modified superblock.
1997 */
1998 if (fs->fs_fmod != 0) {
1999 fs->fs_fmod = 0;
2000 fs->fs_time = time_second;
2001 error = UFS_WAPBL_BEGIN(mp);
2002 if (error)
2003 allerror = error;
2004 else {
2005 if ((error = ffs_cgupdate(ump, waitfor)))
2006 allerror = error;
2007 UFS_WAPBL_END(mp);
2008 }
2009 }
2010
2011 #ifdef WAPBL
2012 if (mp->mnt_wapbl) {
2013 error = wapbl_flush(mp->mnt_wapbl, (waitfor == MNT_WAIT));
2014 if (error)
2015 allerror = error;
2016 }
2017 #endif
2018
2019 return (allerror);
2020 }
2021
2022 /*
2023 * Load inode from disk and initialize vnode.
2024 */
2025 static int
2026 ffs_init_vnode(struct ufsmount *ump, struct vnode *vp, ino_t ino)
2027 {
2028 struct fs *fs;
2029 struct inode *ip;
2030 struct buf *bp;
2031 int error;
2032
2033 fs = ump->um_fs;
2034
2035 /* Read in the disk contents for the inode. */
2036 error = bread(ump->um_devvp, FFS_FSBTODB(fs, ino_to_fsba(fs, ino)),
2037 (int)fs->fs_bsize, 0, &bp);
2038 if (error)
2039 return error;
2040
2041 /* Allocate and initialize inode. */
2042 ip = pool_cache_get(ffs_inode_cache, PR_WAITOK);
2043 memset(ip, 0, sizeof(struct inode));
2044 ip->i_ump = ump;
2045 ip->i_fs = fs;
2046 ip->i_dev = ump->um_dev;
2047 ip->i_number = ino;
2048 if (ump->um_fstype == UFS1)
2049 ip->i_din.ffs1_din = pool_cache_get(ffs_dinode1_cache,
2050 PR_WAITOK);
2051 else
2052 ip->i_din.ffs2_din = pool_cache_get(ffs_dinode2_cache,
2053 PR_WAITOK);
2054 ffs_load_inode(bp, ip, fs, ino);
2055 brelse(bp, 0);
2056 ip->i_vnode = vp;
2057 #if defined(QUOTA) || defined(QUOTA2)
2058 ufsquota_init(ip);
2059 #endif
2060
2061 /* Initialise vnode with this inode. */
2062 vp->v_tag = VT_UFS;
2063 vp->v_op = ffs_vnodeop_p;
2064 vp->v_vflag |= VV_LOCKSWORK;
2065 vp->v_data = ip;
2066
2067 /* Initialize genfs node. */
2068 genfs_node_init(vp, &ffs_genfsops);
2069
2070 return 0;
2071 }
2072
2073 /*
2074 * Undo ffs_init_vnode().
2075 */
2076 static void
2077 ffs_deinit_vnode(struct ufsmount *ump, struct vnode *vp)
2078 {
2079 struct inode *ip = VTOI(vp);
2080
2081 genfs_node_destroy(vp);
2082 vp->v_data = NULL;
2083
2084 if (ump->um_fstype == UFS1)
2085 pool_cache_put(ffs_dinode1_cache, ip->i_din.ffs1_din);
2086 else
2087 pool_cache_put(ffs_dinode2_cache, ip->i_din.ffs2_din);
2088 pool_cache_put(ffs_inode_cache, ip);
2089 }
2090
2091 /*
2092 * Read an inode from disk and initialize this vnode / inode pair.
2093 * Caller assures no other thread will try to load this inode.
2094 */
2095 int
2096 ffs_loadvnode(struct mount *mp, struct vnode *vp,
2097 const void *key, size_t key_len, const void **new_key)
2098 {
2099 ino_t ino;
2100 struct fs *fs;
2101 struct inode *ip;
2102 struct ufsmount *ump;
2103 int error;
2104
2105 KASSERT(key_len == sizeof(ino));
2106 memcpy(&ino, key, key_len);
2107 ump = VFSTOUFS(mp);
2108 fs = ump->um_fs;
2109
2110 error = ffs_init_vnode(ump, vp, ino);
2111 if (error)
2112 return error;
2113
2114 ip = VTOI(vp);
2115 if (ip->i_mode == 0) {
2116 ffs_deinit_vnode(ump, vp);
2117
2118 return ENOENT;
2119 }
2120
2121 /* Initialize the vnode from the inode. */
2122 ufs_vinit(mp, ffs_specop_p, ffs_fifoop_p, &vp);
2123
2124 /* Finish inode initialization. */
2125 ip->i_devvp = ump->um_devvp;
2126 vref(ip->i_devvp);
2127
2128 /*
2129 * Ensure that uid and gid are correct. This is a temporary
2130 * fix until fsck has been changed to do the update.
2131 */
2132
2133 if (fs->fs_magic == FS_UFS1_MAGIC && /* XXX */
2134 fs->fs_old_inodefmt < FS_44INODEFMT) { /* XXX */
2135 ip->i_uid = ip->i_ffs1_ouid; /* XXX */
2136 ip->i_gid = ip->i_ffs1_ogid; /* XXX */
2137 } /* XXX */
2138 uvm_vnp_setsize(vp, ip->i_size);
2139 cache_enter_id(vp, ip->i_mode, ip->i_uid, ip->i_gid, true);
2140 *new_key = &ip->i_number;
2141 return 0;
2142 }
2143
2144 /*
2145 * Create a new inode on disk and initialize this vnode / inode pair.
2146 */
2147 int
2148 ffs_newvnode(struct mount *mp, struct vnode *dvp, struct vnode *vp,
2149 struct vattr *vap, kauth_cred_t cred, void *extra,
2150 size_t *key_len, const void **new_key)
2151 {
2152 ino_t ino;
2153 struct fs *fs;
2154 struct inode *ip;
2155 struct timespec ts;
2156 struct ufsmount *ump;
2157 int error, mode;
2158
2159 KASSERT(dvp->v_mount == mp);
2160 KASSERT(vap->va_type != VNON);
2161
2162 *key_len = sizeof(ino);
2163 ump = VFSTOUFS(mp);
2164 fs = ump->um_fs;
2165 mode = MAKEIMODE(vap->va_type, vap->va_mode);
2166
2167 /* Allocate fresh inode. */
2168 error = ffs_valloc(dvp, mode, cred, &ino);
2169 if (error)
2170 return error;
2171
2172 /* Attach inode to vnode. */
2173 error = ffs_init_vnode(ump, vp, ino);
2174 if (error) {
2175 if (UFS_WAPBL_BEGIN(mp) == 0) {
2176 ffs_vfree(dvp, ino, mode);
2177 UFS_WAPBL_END(mp);
2178 }
2179 return error;
2180 }
2181
2182 ip = VTOI(vp);
2183 if (ip->i_mode) {
2184 panic("%s: dup alloc ino=%" PRId64 " on %s: mode %o/%o "
2185 "gen %x/%x size %" PRIx64 " blocks %" PRIx64,
2186 __func__, ino, fs->fs_fsmnt, DIP(ip, mode), ip->i_mode,
2187 DIP(ip, gen), ip->i_gen, DIP(ip, size), DIP(ip, blocks));
2188 }
2189 if (DIP(ip, size) || DIP(ip, blocks)) {
2190 printf("%s: ino=%" PRId64 " on %s: "
2191 "gen %x/%x has non zero blocks %" PRIx64 " or size %"
2192 PRIx64 "\n",
2193 __func__, ino, fs->fs_fsmnt, DIP(ip, gen), ip->i_gen,
2194 DIP(ip, blocks), DIP(ip, size));
2195 if ((ip)->i_ump->um_fstype == UFS1)
2196 panic("%s: dirty filesystem?", __func__);
2197 DIP_ASSIGN(ip, blocks, 0);
2198 DIP_ASSIGN(ip, size, 0);
2199 }
2200
2201 /* Set uid / gid. */
2202 if (cred == NOCRED || cred == FSCRED) {
2203 ip->i_gid = 0;
2204 ip->i_uid = 0;
2205 } else {
2206 ip->i_gid = VTOI(dvp)->i_gid;
2207 ip->i_uid = kauth_cred_geteuid(cred);
2208 }
2209 DIP_ASSIGN(ip, gid, ip->i_gid);
2210 DIP_ASSIGN(ip, uid, ip->i_uid);
2211
2212 #if defined(QUOTA) || defined(QUOTA2)
2213 error = UFS_WAPBL_BEGIN(mp);
2214 if (error) {
2215 ffs_deinit_vnode(ump, vp);
2216
2217 return error;
2218 }
2219 error = chkiq(ip, 1, cred, 0);
2220 if (error) {
2221 ffs_vfree(dvp, ino, mode);
2222 UFS_WAPBL_END(mp);
2223 ffs_deinit_vnode(ump, vp);
2224
2225 return error;
2226 }
2227 UFS_WAPBL_END(mp);
2228 #endif
2229
2230 /* Set type and finalize. */
2231 ip->i_flags = 0;
2232 DIP_ASSIGN(ip, flags, 0);
2233 ip->i_mode = mode;
2234 DIP_ASSIGN(ip, mode, mode);
2235 if (vap->va_rdev != VNOVAL) {
2236 /*
2237 * Want to be able to use this to make badblock
2238 * inodes, so don't truncate the dev number.
2239 */
2240 if (ump->um_fstype == UFS1)
2241 ip->i_ffs1_rdev = ufs_rw32(vap->va_rdev,
2242 UFS_MPNEEDSWAP(ump));
2243 else
2244 ip->i_ffs2_rdev = ufs_rw64(vap->va_rdev,
2245 UFS_MPNEEDSWAP(ump));
2246 }
2247 ufs_vinit(mp, ffs_specop_p, ffs_fifoop_p, &vp);
2248 ip->i_devvp = ump->um_devvp;
2249 vref(ip->i_devvp);
2250
2251 /* Set up a new generation number for this inode. */
2252 ip->i_gen++;
2253 DIP_ASSIGN(ip, gen, ip->i_gen);
2254 if (fs->fs_magic == FS_UFS2_MAGIC) {
2255 vfs_timestamp(&ts);
2256 ip->i_ffs2_birthtime = ts.tv_sec;
2257 ip->i_ffs2_birthnsec = ts.tv_nsec;
2258 }
2259
2260 uvm_vnp_setsize(vp, ip->i_size);
2261 cache_enter_id(vp, ip->i_mode, ip->i_uid, ip->i_gid, true);
2262 *new_key = &ip->i_number;
2263 return 0;
2264 }
2265
2266 /*
2267 * File handle to vnode
2268 *
2269 * Have to be really careful about stale file handles:
2270 * - check that the inode number is valid
2271 * - call ffs_vget() to get the locked inode
2272 * - check for an unallocated inode (i_mode == 0)
2273 * - check that the given client host has export rights and return
2274 * those rights via. exflagsp and credanonp
2275 */
2276 int
2277 ffs_fhtovp(struct mount *mp, struct fid *fhp, int lktype, struct vnode **vpp)
2278 {
2279 struct ufid ufh;
2280 int error;
2281
2282 if (fhp->fid_len != sizeof(struct ufid))
2283 return EINVAL;
2284
2285 memcpy(&ufh, fhp, sizeof(ufh));
2286 if ((error = ffs_checkrange(mp, ufh.ufid_ino)) != 0)
2287 return error;
2288
2289 return (ufs_fhtovp(mp, &ufh, lktype, vpp));
2290 }
2291
2292 /*
2293 * Vnode pointer to File handle
2294 */
2295 /* ARGSUSED */
2296 int
2297 ffs_vptofh(struct vnode *vp, struct fid *fhp, size_t *fh_size)
2298 {
2299 struct inode *ip;
2300 struct ufid ufh;
2301
2302 if (*fh_size < sizeof(struct ufid)) {
2303 *fh_size = sizeof(struct ufid);
2304 return E2BIG;
2305 }
2306 ip = VTOI(vp);
2307 *fh_size = sizeof(struct ufid);
2308 memset(&ufh, 0, sizeof(ufh));
2309 ufh.ufid_len = sizeof(struct ufid);
2310 ufh.ufid_ino = ip->i_number;
2311 ufh.ufid_gen = ip->i_gen;
2312 memcpy(fhp, &ufh, sizeof(ufh));
2313 return (0);
2314 }
2315
2316 void
2317 ffs_init(void)
2318 {
2319 if (ffs_initcount++ > 0)
2320 return;
2321
2322 ffs_inode_cache = pool_cache_init(sizeof(struct inode), 0, 0, 0,
2323 "ffsino", NULL, IPL_NONE, NULL, NULL, NULL);
2324 ffs_dinode1_cache = pool_cache_init(sizeof(struct ufs1_dinode), 0, 0, 0,
2325 "ffsdino1", NULL, IPL_NONE, NULL, NULL, NULL);
2326 ffs_dinode2_cache = pool_cache_init(sizeof(struct ufs2_dinode), 0, 0, 0,
2327 "ffsdino2", NULL, IPL_NONE, NULL, NULL, NULL);
2328 ufs_init();
2329 }
2330
2331 void
2332 ffs_reinit(void)
2333 {
2334 ufs_reinit();
2335 }
2336
2337 void
2338 ffs_done(void)
2339 {
2340 if (--ffs_initcount > 0)
2341 return;
2342
2343 ufs_done();
2344 pool_cache_destroy(ffs_dinode2_cache);
2345 pool_cache_destroy(ffs_dinode1_cache);
2346 pool_cache_destroy(ffs_inode_cache);
2347 }
2348
2349 /*
2350 * Write a superblock and associated information back to disk.
2351 */
2352 int
2353 ffs_sbupdate(struct ufsmount *mp, int waitfor)
2354 {
2355 struct fs *fs = mp->um_fs;
2356 struct buf *bp;
2357 int error;
2358 u_int32_t saveflag;
2359
2360 error = ffs_getblk(mp->um_devvp,
2361 fs->fs_sblockloc / DEV_BSIZE, FFS_NOBLK,
2362 fs->fs_sbsize, false, &bp);
2363 if (error)
2364 return error;
2365 saveflag = fs->fs_flags & FS_INTERNAL;
2366 fs->fs_flags &= ~FS_INTERNAL;
2367
2368 memcpy(bp->b_data, fs, fs->fs_sbsize);
2369
2370 ffs_oldfscompat_write((struct fs *)bp->b_data, mp);
2371 #ifdef FFS_EI
2372 if (mp->um_flags & UFS_NEEDSWAP)
2373 ffs_sb_swap((struct fs *)bp->b_data, (struct fs *)bp->b_data);
2374 #endif
2375 fs->fs_flags |= saveflag;
2376
2377 if (waitfor == MNT_WAIT)
2378 error = bwrite(bp);
2379 else
2380 bawrite(bp);
2381 return (error);
2382 }
2383
2384 int
2385 ffs_cgupdate(struct ufsmount *mp, int waitfor)
2386 {
2387 struct fs *fs = mp->um_fs;
2388 struct buf *bp;
2389 int blks;
2390 void *space;
2391 int i, size, error = 0, allerror = 0;
2392
2393 UFS_WAPBL_JLOCK_ASSERT(mp->um_mountp);
2394
2395 allerror = ffs_sbupdate(mp, waitfor);
2396 blks = howmany(fs->fs_cssize, fs->fs_fsize);
2397 space = fs->fs_csp;
2398 for (i = 0; i < blks; i += fs->fs_frag) {
2399 size = fs->fs_bsize;
2400 if (i + fs->fs_frag > blks)
2401 size = (blks - i) * fs->fs_fsize;
2402 error = ffs_getblk(mp->um_devvp, FFS_FSBTODB(fs, fs->fs_csaddr + i),
2403 FFS_NOBLK, size, false, &bp);
2404 if (error)
2405 break;
2406 #ifdef FFS_EI
2407 if (mp->um_flags & UFS_NEEDSWAP)
2408 ffs_csum_swap((struct csum*)space,
2409 (struct csum*)bp->b_data, size);
2410 else
2411 #endif
2412 memcpy(bp->b_data, space, (u_int)size);
2413 space = (char *)space + size;
2414 if (waitfor == MNT_WAIT)
2415 error = bwrite(bp);
2416 else
2417 bawrite(bp);
2418 }
2419 if (!allerror && error)
2420 allerror = error;
2421 return (allerror);
2422 }
2423
2424 int
2425 ffs_extattrctl(struct mount *mp, int cmd, struct vnode *vp,
2426 int attrnamespace, const char *attrname)
2427 {
2428 #ifdef UFS_EXTATTR
2429 /*
2430 * File-backed extended attributes are only supported on UFS1.
2431 * UFS2 has native extended attributes.
2432 */
2433 if (VFSTOUFS(mp)->um_fstype == UFS1)
2434 return (ufs_extattrctl(mp, cmd, vp, attrnamespace, attrname));
2435 #endif
2436 return (vfs_stdextattrctl(mp, cmd, vp, attrnamespace, attrname));
2437 }
2438
2439 /*
2440 * Synch vnode for a mounted file system.
2441 */
2442 static int
2443 ffs_vfs_fsync(vnode_t *vp, int flags)
2444 {
2445 int error, i, pflags;
2446 #ifdef WAPBL
2447 struct mount *mp;
2448 #endif
2449
2450 KASSERT(vp->v_type == VBLK);
2451 KASSERT(spec_node_getmountedfs(vp) != NULL);
2452
2453 /*
2454 * Flush all dirty data associated with the vnode.
2455 */
2456 pflags = PGO_ALLPAGES | PGO_CLEANIT;
2457 if ((flags & FSYNC_WAIT) != 0)
2458 pflags |= PGO_SYNCIO;
2459 rw_enter(vp->v_uobj.vmobjlock, RW_WRITER);
2460 error = VOP_PUTPAGES(vp, 0, 0, pflags);
2461 if (error)
2462 return error;
2463
2464 #ifdef WAPBL
2465 mp = spec_node_getmountedfs(vp);
2466 if (mp && mp->mnt_wapbl) {
2467 /*
2468 * Don't bother writing out metadata if the syncer is
2469 * making the request. We will let the sync vnode
2470 * write it out in a single burst through a call to
2471 * VFS_SYNC().
2472 */
2473 if ((flags & (FSYNC_DATAONLY | FSYNC_LAZY | FSYNC_NOLOG)) != 0)
2474 return 0;
2475
2476 /*
2477 * Don't flush the log if the vnode being flushed
2478 * contains no dirty buffers that could be in the log.
2479 */
2480 if (!LIST_EMPTY(&vp->v_dirtyblkhd)) {
2481 error = wapbl_flush(mp->mnt_wapbl, 0);
2482 if (error)
2483 return error;
2484 }
2485
2486 if ((flags & FSYNC_WAIT) != 0) {
2487 mutex_enter(vp->v_interlock);
2488 while (vp->v_numoutput)
2489 cv_wait(&vp->v_cv, vp->v_interlock);
2490 mutex_exit(vp->v_interlock);
2491 }
2492
2493 return 0;
2494 }
2495 #endif /* WAPBL */
2496
2497 error = vflushbuf(vp, flags);
2498 if (error == 0 && (flags & FSYNC_CACHE) != 0) {
2499 i = 1;
2500 (void)VOP_IOCTL(vp, DIOCCACHESYNC, &i, FWRITE,
2501 kauth_cred_get());
2502 }
2503
2504 return error;
2505 }
2506