Annotation of src/sys/ufs/ffs/ffs_vfsops.c, Revision 1.239
1.239 ! joerg 1: /* $NetBSD: ffs_vfsops.c,v 1.238 2008/10/10 09:21:58 hannken Exp $ */
1.231 simonb 2:
3: /*-
4: * Copyright (c) 2008 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.
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: */
1.4 cgd 31:
1.1 mycroft 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.
1.119 agc 44: * 3. Neither the name of the University nor the names of its contributors
1.1 mycroft 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: *
1.33 fvdl 60: * @(#)ffs_vfsops.c 8.31 (Berkeley) 5/20/95
1.1 mycroft 61: */
1.88 lukem 62:
63: #include <sys/cdefs.h>
1.239 ! joerg 64: __KERNEL_RCSID(0, "$NetBSD: ffs_vfsops.c,v 1.238 2008/10/10 09:21:58 hannken Exp $");
1.36 scottr 65:
1.81 mrg 66: #if defined(_KERNEL_OPT)
1.45 thorpej 67: #include "opt_ffs.h"
1.36 scottr 68: #include "opt_quota.h"
1.66 matt 69: #include "opt_softdep.h"
1.231 simonb 70: #include "opt_wapbl.h"
1.37 scottr 71: #endif
1.1 mycroft 72:
73: #include <sys/param.h>
74: #include <sys/systm.h>
75: #include <sys/namei.h>
76: #include <sys/proc.h>
77: #include <sys/kernel.h>
78: #include <sys/vnode.h>
79: #include <sys/socket.h>
80: #include <sys/mount.h>
81: #include <sys/buf.h>
1.23 thorpej 82: #include <sys/device.h>
1.1 mycroft 83: #include <sys/mbuf.h>
84: #include <sys/file.h>
85: #include <sys/disklabel.h>
86: #include <sys/ioctl.h>
87: #include <sys/errno.h>
88: #include <sys/malloc.h>
1.43 thorpej 89: #include <sys/pool.h>
1.29 fvdl 90: #include <sys/lock.h>
1.33 fvdl 91: #include <sys/sysctl.h>
1.101 gehenna 92: #include <sys/conf.h>
1.181 elad 93: #include <sys/kauth.h>
1.231 simonb 94: #include <sys/wapbl.h>
1.193 hannken 95: #include <sys/fstrans.h>
1.227 rumble 96: #include <sys/module.h>
1.1 mycroft 97:
1.221 dholland 98: #include <miscfs/genfs/genfs.h>
1.1 mycroft 99: #include <miscfs/specfs/specdev.h>
100:
101: #include <ufs/ufs/quota.h>
102: #include <ufs/ufs/ufsmount.h>
103: #include <ufs/ufs/inode.h>
1.25 bouyer 104: #include <ufs/ufs/dir.h>
1.1 mycroft 105: #include <ufs/ufs/ufs_extern.h>
1.34 bouyer 106: #include <ufs/ufs/ufs_bswap.h>
1.231 simonb 107: #include <ufs/ufs/ufs_wapbl.h>
1.1 mycroft 108:
109: #include <ufs/ffs/fs.h>
110: #include <ufs/ffs/ffs_extern.h>
111:
1.227 rumble 112: MODULE(MODULE_CLASS_VFS, ffs, NULL);
113:
1.230 rumble 114: static struct sysctllog *ffs_sysctl_log;
115:
1.59 jdolecek 116: /* how many times ffs_init() was called */
117: int ffs_initcount = 0;
118:
1.195 ad 119: extern kmutex_t ufs_hashlock;
1.29 fvdl 120:
1.105 matt 121: extern const struct vnodeopv_desc ffs_vnodeop_opv_desc;
122: extern const struct vnodeopv_desc ffs_specop_opv_desc;
123: extern const struct vnodeopv_desc ffs_fifoop_opv_desc;
1.32 thorpej 124:
1.79 jdolecek 125: const struct vnodeopv_desc * const ffs_vnodeopv_descs[] = {
1.32 thorpej 126: &ffs_vnodeop_opv_desc,
127: &ffs_specop_opv_desc,
128: &ffs_fifoop_opv_desc,
129: NULL,
130: };
131:
1.17 mycroft 132: struct vfsops ffs_vfsops = {
133: MOUNT_FFS,
1.204 dsl 134: sizeof (struct ufs_args),
1.1 mycroft 135: ffs_mount,
136: ufs_start,
137: ffs_unmount,
138: ufs_root,
139: ufs_quotactl,
1.143 christos 140: ffs_statvfs,
1.1 mycroft 141: ffs_sync,
142: ffs_vget,
143: ffs_fhtovp,
144: ffs_vptofh,
145: ffs_init,
1.86 chs 146: ffs_reinit,
1.59 jdolecek 147: ffs_done,
1.23 thorpej 148: ffs_mountroot,
1.149 hannken 149: ffs_snapshot,
1.170 thorpej 150: ffs_extattrctl,
1.193 hannken 151: ffs_suspendctl,
1.221 dholland 152: genfs_renamelock_enter,
153: genfs_renamelock_exit,
1.224 ad 154: ffs_full_fsync,
1.32 thorpej 155: ffs_vnodeopv_descs,
1.185 christos 156: 0,
157: { NULL, NULL },
1.1 mycroft 158: };
159:
1.165 yamt 160: static const struct genfs_ops ffs_genfsops = {
161: .gop_size = ffs_gop_size,
162: .gop_alloc = ufs_gop_alloc,
1.238 hannken 163: .gop_write = genfs_gop_write,
1.167 yamt 164: .gop_markupdate = ufs_gop_markupdate,
1.87 chs 165: };
166:
1.175 yamt 167: static const struct ufs_ops ffs_ufsops = {
168: .uo_itimes = ffs_itimes,
1.176 yamt 169: .uo_update = ffs_update,
170: .uo_truncate = ffs_truncate,
171: .uo_valloc = ffs_valloc,
172: .uo_vfree = ffs_vfree,
173: .uo_balloc = ffs_balloc,
1.175 yamt 174: };
175:
1.227 rumble 176: static int
177: ffs_modcmd(modcmd_t cmd, void *arg)
178: {
1.230 rumble 179: int error;
180:
181: #if 0
182: extern int doasyncfree;
183: #endif
184: extern int ffs_log_changeopt;
1.227 rumble 185:
186: switch (cmd) {
187: case MODULE_CMD_INIT:
1.230 rumble 188: error = vfs_attach(&ffs_vfsops);
189: if (error != 0)
190: break;
191:
192: sysctl_createv(&ffs_sysctl_log, 0, NULL, NULL,
193: CTLFLAG_PERMANENT,
194: CTLTYPE_NODE, "vfs", NULL,
195: NULL, 0, NULL, 0,
196: CTL_VFS, CTL_EOL);
197: sysctl_createv(&ffs_sysctl_log, 0, NULL, NULL,
198: CTLFLAG_PERMANENT,
199: CTLTYPE_NODE, "ffs",
200: SYSCTL_DESCR("Berkeley Fast File System"),
201: NULL, 0, NULL, 0,
202: CTL_VFS, 1, CTL_EOL);
203:
204: /*
205: * @@@ should we even bother with these first three?
206: */
207: sysctl_createv(&ffs_sysctl_log, 0, NULL, NULL,
208: CTLFLAG_PERMANENT|CTLFLAG_READWRITE,
209: CTLTYPE_INT, "doclusterread", NULL,
210: sysctl_notavail, 0, NULL, 0,
211: CTL_VFS, 1, FFS_CLUSTERREAD, CTL_EOL);
212: sysctl_createv(&ffs_sysctl_log, 0, NULL, NULL,
213: CTLFLAG_PERMANENT|CTLFLAG_READWRITE,
214: CTLTYPE_INT, "doclusterwrite", NULL,
215: sysctl_notavail, 0, NULL, 0,
216: CTL_VFS, 1, FFS_CLUSTERWRITE, CTL_EOL);
217: sysctl_createv(&ffs_sysctl_log, 0, NULL, NULL,
218: CTLFLAG_PERMANENT|CTLFLAG_READWRITE,
219: CTLTYPE_INT, "doreallocblks", NULL,
220: sysctl_notavail, 0, NULL, 0,
221: CTL_VFS, 1, FFS_REALLOCBLKS, CTL_EOL);
222: #if 0
223: sysctl_createv(&ffs_sysctl_log, 0, NULL, NULL,
224: CTLFLAG_PERMANENT|CTLFLAG_READWRITE,
225: CTLTYPE_INT, "doasyncfree",
226: SYSCTL_DESCR("Release dirty blocks asynchronously"),
227: NULL, 0, &doasyncfree, 0,
228: CTL_VFS, 1, FFS_ASYNCFREE, CTL_EOL);
229: #endif
230: sysctl_createv(&ffs_sysctl_log, 0, NULL, NULL,
231: CTLFLAG_PERMANENT|CTLFLAG_READWRITE,
232: CTLTYPE_INT, "log_changeopt",
233: SYSCTL_DESCR("Log changes in optimization strategy"),
234: NULL, 0, &ffs_log_changeopt, 0,
235: CTL_VFS, 1, FFS_LOG_CHANGEOPT, CTL_EOL);
236: break;
1.227 rumble 237: case MODULE_CMD_FINI:
1.230 rumble 238: error = vfs_detach(&ffs_vfsops);
239: if (error != 0)
240: break;
241: sysctl_teardown(&ffs_sysctl_log);
242: break;
1.227 rumble 243: default:
1.230 rumble 244: error = ENOTTY;
245: break;
1.227 rumble 246: }
1.230 rumble 247:
248: return (error);
1.227 rumble 249: }
250:
1.216 ad 251: pool_cache_t ffs_inode_cache;
252: pool_cache_t ffs_dinode1_cache;
253: pool_cache_t ffs_dinode2_cache;
1.110 fvdl 254:
1.146 simonb 255: static void ffs_oldfscompat_read(struct fs *, struct ufsmount *, daddr_t);
1.110 fvdl 256: static void ffs_oldfscompat_write(struct fs *, struct ufsmount *);
1.43 thorpej 257:
1.1 mycroft 258: /*
1.33 fvdl 259: * Called by main() when ffs is going to be mounted as root.
1.1 mycroft 260: */
261:
1.19 christos 262: int
1.166 thorpej 263: ffs_mountroot(void)
1.1 mycroft 264: {
1.33 fvdl 265: struct fs *fs;
266: struct mount *mp;
1.177 christos 267: struct lwp *l = curlwp; /* XXX */
1.1 mycroft 268: struct ufsmount *ump;
269: int error;
1.23 thorpej 270:
1.180 thorpej 271: if (device_class(root_device) != DV_DISK)
1.23 thorpej 272: return (ENODEV);
273:
1.51 wrstuden 274: if ((error = vfs_rootmountalloc(MOUNT_FFS, "root_device", &mp))) {
275: vrele(rootvp);
1.33 fvdl 276: return (error);
1.51 wrstuden 277: }
1.231 simonb 278:
279: /*
280: * We always need to be able to mount the root file system.
281: */
282: mp->mnt_flag |= MNT_FORCE;
1.177 christos 283: if ((error = ffs_mountfs(rootvp, mp, l)) != 0) {
1.225 ad 284: vfs_unbusy(mp, false, NULL);
1.226 ad 285: vfs_destroy(mp);
1.1 mycroft 286: return (error);
287: }
1.231 simonb 288: mp->mnt_flag &= ~MNT_FORCE;
1.210 ad 289: mutex_enter(&mountlist_lock);
1.11 mycroft 290: CIRCLEQ_INSERT_TAIL(&mountlist, mp, mnt_list);
1.210 ad 291: mutex_exit(&mountlist_lock);
1.1 mycroft 292: ump = VFSTOUFS(mp);
293: fs = ump->um_fs;
1.42 perry 294: memset(fs->fs_fsmnt, 0, sizeof(fs->fs_fsmnt));
1.33 fvdl 295: (void)copystr(mp->mnt_stat.f_mntonname, fs->fs_fsmnt, MNAMELEN - 1, 0);
1.211 pooka 296: (void)ffs_statvfs(mp, &mp->mnt_stat);
1.225 ad 297: vfs_unbusy(mp, false, NULL);
1.151 pk 298: setrootfstime((time_t)fs->fs_time);
1.1 mycroft 299: return (0);
300: }
301:
302: /*
303: * VFS Operations.
304: *
305: * mount system call
306: */
307: int
1.211 pooka 308: ffs_mount(struct mount *mp, const char *path, void *data, size_t *data_len)
1.1 mycroft 309: {
1.211 pooka 310: struct lwp *l = curlwp;
1.207 pooka 311: struct nameidata nd;
1.218 ad 312: struct vnode *vp, *devvp = NULL;
1.204 dsl 313: struct ufs_args *args = data;
1.19 christos 314: struct ufsmount *ump = NULL;
1.61 augustss 315: struct fs *fs;
1.204 dsl 316: int error = 0, flags, update;
1.9 mycroft 317: mode_t accessmode;
1.1 mycroft 318:
1.204 dsl 319: if (*data_len < sizeof *args)
320: return EINVAL;
321:
1.102 christos 322: if (mp->mnt_flag & MNT_GETARGS) {
323: ump = VFSTOUFS(mp);
324: if (ump == NULL)
325: return EIO;
1.204 dsl 326: args->fspec = NULL;
327: *data_len = sizeof *args;
328: return 0;
1.102 christos 329: }
1.66 matt 330:
331: #if !defined(SOFTDEP)
1.67 perseant 332: mp->mnt_flag &= ~MNT_SOFTDEP;
1.66 matt 333: #endif
334:
1.95 christos 335: update = mp->mnt_flag & MNT_UPDATE;
336:
337: /* Check arguments */
1.204 dsl 338: if (args->fspec != NULL) {
1.95 christos 339: /*
340: * Look up the name and verify that it's sane.
341: */
1.212 pooka 342: NDINIT(&nd, LOOKUP, FOLLOW, UIO_USERSPACE, args->fspec);
1.207 pooka 343: if ((error = namei(&nd)) != 0)
1.95 christos 344: return (error);
1.207 pooka 345: devvp = nd.ni_vp;
1.95 christos 346:
347: if (!update) {
348: /*
349: * Be sure this is a valid block device
350: */
351: if (devvp->v_type != VBLK)
352: error = ENOTBLK;
1.101 gehenna 353: else if (bdevsw_lookup(devvp->v_rdev) == NULL)
1.95 christos 354: error = ENXIO;
355: } else {
356: /*
357: * Be sure we're still naming the same device
358: * used for our initial mount
359: */
1.160 mycroft 360: ump = VFSTOUFS(mp);
1.186 jld 361: if (devvp != ump->um_devvp) {
362: if (devvp->v_rdev != ump->um_devvp->v_rdev)
363: error = EINVAL;
364: else {
365: vrele(devvp);
366: devvp = ump->um_devvp;
367: vref(devvp);
368: }
369: }
1.95 christos 370: }
1.160 mycroft 371: } else {
372: if (!update) {
373: /* New mounts must have a filename for the device */
374: return (EINVAL);
375: } else {
376: /* Use the extant mount */
377: ump = VFSTOUFS(mp);
378: devvp = ump->um_devvp;
379: vref(devvp);
380: }
1.95 christos 381: }
1.218 ad 382:
383: /*
384: * Mark the device and any existing vnodes as involved in
385: * softdep processing.
386: */
387: if ((mp->mnt_flag & MNT_SOFTDEP) != 0) {
1.217 ad 388: devvp->v_uflag |= VU_SOFTDEP;
1.218 ad 389: mutex_enter(&mntvnode_lock);
390: TAILQ_FOREACH(vp, &mp->mnt_vnodelist, v_mntvnodes) {
391: if (vp->v_mount != mp || vismarker(vp))
392: continue;
393: vp->v_uflag |= VU_SOFTDEP;
394: }
395: mutex_exit(&mntvnode_lock);
396: }
1.95 christos 397:
1.1 mycroft 398: /*
1.95 christos 399: * If mount by non-root, then verify that user has necessary
400: * permissions on the device.
1.1 mycroft 401: */
1.191 elad 402: if (error == 0 && kauth_authorize_generic(l->l_cred,
403: KAUTH_GENERIC_ISSUSER, NULL) != 0) {
1.95 christos 404: accessmode = VREAD;
1.96 christos 405: if (update ?
1.124 dbj 406: (mp->mnt_iflag & IMNT_WANTRDWR) != 0 :
1.96 christos 407: (mp->mnt_flag & MNT_RDONLY) == 0)
1.95 christos 408: accessmode |= VWRITE;
409: vn_lock(devvp, LK_EXCLUSIVE | LK_RETRY);
1.211 pooka 410: error = VOP_ACCESS(devvp, accessmode, l->l_cred);
1.95 christos 411: VOP_UNLOCK(devvp, 0);
412: }
413:
414: if (error) {
415: vrele(devvp);
416: return (error);
417: }
418:
1.231 simonb 419: #ifdef WAPBL
420: /*
421: * WAPBL can only be enabled on a r/w mount
422: * that does not use softdep.
423: */
424: if ((mp->mnt_flag & MNT_RDONLY) && !(mp->mnt_iflag & IMNT_WANTRDWR)) {
425: mp->mnt_flag &= ~MNT_LOG;
426: }
427: if ((mp->mnt_flag & (MNT_SOFTDEP | MNT_LOG)) ==
428: (MNT_SOFTDEP | MNT_LOG)) {
429: printf("%s fs is journalled, ignoring soft update mode\n",
430: VFSTOUFS(mp)->um_fs->fs_fsmnt);
431: mp->mnt_flag &= ~MNT_SOFTDEP;
432: }
433: #else /* !WAPBL */
434: mp->mnt_flag &= ~MNT_LOG;
435: #endif /* !WAPBL */
436:
1.95 christos 437: if (!update) {
1.164 christos 438: int xflags;
1.159 mycroft 439:
440: if (mp->mnt_flag & MNT_RDONLY)
1.164 christos 441: xflags = FREAD;
1.159 mycroft 442: else
1.231 simonb 443: xflags = FREAD | FWRITE;
1.211 pooka 444: error = VOP_OPEN(devvp, xflags, FSCRED);
1.159 mycroft 445: if (error)
446: goto fail;
1.177 christos 447: error = ffs_mountfs(devvp, mp, l);
1.95 christos 448: if (error) {
1.159 mycroft 449: vn_lock(devvp, LK_EXCLUSIVE | LK_RETRY);
1.211 pooka 450: (void)VOP_CLOSE(devvp, xflags, NOCRED);
1.159 mycroft 451: VOP_UNLOCK(devvp, 0);
452: goto fail;
1.95 christos 453: }
454:
1.1 mycroft 455: ump = VFSTOUFS(mp);
456: fs = ump->um_fs;
1.95 christos 457: if ((mp->mnt_flag & (MNT_SOFTDEP | MNT_ASYNC)) ==
458: (MNT_SOFTDEP | MNT_ASYNC)) {
459: printf("%s fs uses soft updates, "
1.96 christos 460: "ignoring async mode\n",
461: fs->fs_fsmnt);
1.95 christos 462: mp->mnt_flag &= ~MNT_ASYNC;
463: }
464: } else {
465: /*
1.96 christos 466: * Update the mount.
467: */
468:
469: /*
470: * The initial mount got a reference on this
471: * device, so drop the one obtained via
472: * namei(), above.
1.95 christos 473: */
1.96 christos 474: vrele(devvp);
475:
1.160 mycroft 476: ump = VFSTOUFS(mp);
1.95 christos 477: fs = ump->um_fs;
1.1 mycroft 478: if (fs->fs_ronly == 0 && (mp->mnt_flag & MNT_RDONLY)) {
1.95 christos 479: /*
480: * Changing from r/w to r/o
481: */
1.1 mycroft 482: flags = WRITECLOSE;
483: if (mp->mnt_flag & MNT_FORCE)
484: flags |= FORCECLOSE;
1.55 fvdl 485: if (mp->mnt_flag & MNT_SOFTDEP)
1.177 christos 486: error = softdep_flushfiles(mp, flags, l);
1.55 fvdl 487: else
1.177 christos 488: error = ffs_flushfiles(mp, flags, l);
1.89 fvdl 489: if (fs->fs_pendingblocks != 0 ||
490: fs->fs_pendinginodes != 0) {
1.110 fvdl 491: printf("%s: update error: blocks %" PRId64
492: " files %d\n",
1.89 fvdl 493: fs->fs_fsmnt, fs->fs_pendingblocks,
494: fs->fs_pendinginodes);
495: fs->fs_pendingblocks = 0;
496: fs->fs_pendinginodes = 0;
497: }
1.231 simonb 498: if (error == 0)
499: error = UFS_WAPBL_BEGIN(mp);
1.15 mycroft 500: if (error == 0 &&
501: ffs_cgupdate(ump, MNT_WAIT) == 0 &&
502: fs->fs_clean & FS_WASCLEAN) {
1.65 fvdl 503: if (mp->mnt_flag & MNT_SOFTDEP)
504: fs->fs_flags &= ~FS_DOSOFTDEP;
1.15 mycroft 505: fs->fs_clean = FS_ISCLEAN;
506: (void) ffs_sbupdate(ump, MNT_WAIT);
507: }
1.231 simonb 508: if (error == 0)
509: UFS_WAPBL_END(mp);
1.15 mycroft 510: if (error)
511: return (error);
1.231 simonb 512: }
513:
514: #ifdef WAPBL
515: if ((mp->mnt_flag & MNT_LOG) == 0) {
516: error = ffs_wapbl_stop(mp, mp->mnt_flag & MNT_FORCE);
517: if (error)
518: return error;
519: }
520: #endif /* WAPBL */
521:
522: if (fs->fs_ronly == 0 && (mp->mnt_flag & MNT_RDONLY)) {
523: /*
524: * Finish change from r/w to r/o
525: */
1.15 mycroft 526: fs->fs_ronly = 1;
1.78 mycroft 527: fs->fs_fmod = 0;
1.1 mycroft 528: }
1.65 fvdl 529:
530: /*
531: * Flush soft dependencies if disabling it via an update
532: * mount. This may leave some items to be processed,
533: * so don't do this yet XXX.
534: */
535: if ((fs->fs_flags & FS_DOSOFTDEP) &&
536: !(mp->mnt_flag & MNT_SOFTDEP) && fs->fs_ronly == 0) {
537: #ifdef notyet
538: flags = WRITECLOSE;
539: if (mp->mnt_flag & MNT_FORCE)
540: flags |= FORCECLOSE;
1.177 christos 541: error = softdep_flushfiles(mp, flags, l);
1.65 fvdl 542: if (error == 0 && ffs_cgupdate(ump, MNT_WAIT) == 0)
543: fs->fs_flags &= ~FS_DOSOFTDEP;
544: (void) ffs_sbupdate(ump, MNT_WAIT);
1.66 matt 545: #elif defined(SOFTDEP)
1.65 fvdl 546: mp->mnt_flag |= MNT_SOFTDEP;
547: #endif
548: }
549:
550: /*
551: * When upgrading to a softdep mount, we must first flush
552: * all vnodes. (not done yet -- see above)
553: */
554: if (!(fs->fs_flags & FS_DOSOFTDEP) &&
555: (mp->mnt_flag & MNT_SOFTDEP) && fs->fs_ronly == 0) {
556: #ifdef notyet
557: flags = WRITECLOSE;
558: if (mp->mnt_flag & MNT_FORCE)
559: flags |= FORCECLOSE;
1.177 christos 560: error = ffs_flushfiles(mp, flags, l);
1.65 fvdl 561: #else
562: mp->mnt_flag &= ~MNT_SOFTDEP;
563: #endif
564: }
565:
1.15 mycroft 566: if (mp->mnt_flag & MNT_RELOAD) {
1.184 ad 567: error = ffs_reload(mp, l->l_cred, l);
1.15 mycroft 568: if (error)
569: return (error);
570: }
1.95 christos 571:
1.124 dbj 572: if (fs->fs_ronly && (mp->mnt_iflag & IMNT_WANTRDWR)) {
1.9 mycroft 573: /*
1.95 christos 574: * Changing from read-only to read/write
1.9 mycroft 575: */
1.1 mycroft 576: fs->fs_ronly = 0;
1.15 mycroft 577: fs->fs_clean <<= 1;
578: fs->fs_fmod = 1;
1.55 fvdl 579: if ((fs->fs_flags & FS_DOSOFTDEP)) {
580: error = softdep_mount(devvp, mp, fs,
1.184 ad 581: l->l_cred);
1.55 fvdl 582: if (error)
583: return (error);
1.65 fvdl 584: }
1.231 simonb 585: #ifdef WAPBL
586: if (fs->fs_flags & FS_DOWAPBL) {
587: printf("%s: replaying log to disk\n",
1.236 freza 588: fs->fs_fsmnt);
1.231 simonb 589: KDASSERT(mp->mnt_wapbl_replay);
590: error = wapbl_replay_write(mp->mnt_wapbl_replay,
591: devvp);
592: if (error) {
593: return error;
594: }
595: wapbl_replay_stop(mp->mnt_wapbl_replay);
596: fs->fs_clean = FS_WASCLEAN;
597: }
598: #endif /* WAPBL */
1.149 hannken 599: if (fs->fs_snapinum[0] != 0)
600: ffs_snapshot_mount(mp);
1.9 mycroft 601: }
1.231 simonb 602:
603: #ifdef WAPBL
604: error = ffs_wapbl_start(mp);
605: if (error)
606: return error;
607: #endif /* WAPBL */
608:
1.204 dsl 609: if (args->fspec == NULL)
1.174 jmmv 610: return EINVAL;
1.55 fvdl 611: if ((mp->mnt_flag & (MNT_SOFTDEP | MNT_ASYNC)) ==
612: (MNT_SOFTDEP | MNT_ASYNC)) {
613: printf("%s fs uses soft updates, ignoring async mode\n",
614: fs->fs_fsmnt);
615: mp->mnt_flag &= ~MNT_ASYNC;
616: }
1.1 mycroft 617: }
618:
1.204 dsl 619: error = set_statvfs_info(path, UIO_USERSPACE, args->fspec,
1.205 pooka 620: UIO_USERSPACE, mp->mnt_op->vfs_name, mp, l);
1.114 christos 621: if (error == 0)
622: (void)strncpy(fs->fs_fsmnt, mp->mnt_stat.f_mntonname,
623: sizeof(fs->fs_fsmnt));
1.65 fvdl 624: if (mp->mnt_flag & MNT_SOFTDEP)
625: fs->fs_flags |= FS_DOSOFTDEP;
1.74 fvdl 626: else
627: fs->fs_flags &= ~FS_DOSOFTDEP;
1.15 mycroft 628: if (fs->fs_fmod != 0) { /* XXX */
1.231 simonb 629: int err;
630:
1.15 mycroft 631: fs->fs_fmod = 0;
632: if (fs->fs_clean & FS_WASCLEAN)
1.182 kardel 633: fs->fs_time = time_second;
1.89 fvdl 634: else {
1.231 simonb 635: printf("%s: file system not clean (fs_clean=%#x); "
636: "please fsck(8)\n", mp->mnt_stat.f_mntfromname,
637: fs->fs_clean);
1.110 fvdl 638: printf("%s: lost blocks %" PRId64 " files %d\n",
1.89 fvdl 639: mp->mnt_stat.f_mntfromname, fs->fs_pendingblocks,
640: fs->fs_pendinginodes);
641: }
1.231 simonb 642: err = UFS_WAPBL_BEGIN(mp);
643: if (err == 0) {
644: (void) ffs_cgupdate(ump, MNT_WAIT);
645: UFS_WAPBL_END(mp);
646: }
1.15 mycroft 647: }
1.159 mycroft 648: return (error);
649:
650: fail:
651: vrele(devvp);
652: return (error);
1.1 mycroft 653: }
654:
655: /*
656: * Reload all incore data for a filesystem (used after running fsck on
657: * the root filesystem and finding things to fix). The filesystem must
658: * be mounted read-only.
659: *
660: * Things to do to update the mount:
661: * 1) invalidate all cached meta-data.
662: * 2) re-read superblock from disk.
663: * 3) re-read summary information from disk.
664: * 4) invalidate all inactive vnodes.
665: * 5) invalidate all cached file data.
666: * 6) re-read inode data for all active vnodes.
667: */
1.19 christos 668: int
1.181 elad 669: ffs_reload(struct mount *mp, kauth_cred_t cred, struct lwp *l)
1.1 mycroft 670: {
1.214 ad 671: struct vnode *vp, *mvp, *devvp;
1.1 mycroft 672: struct inode *ip;
1.84 lukem 673: void *space;
1.1 mycroft 674: struct buf *bp;
1.18 cgd 675: struct fs *fs, *newfs;
1.1 mycroft 676: struct partinfo dpart;
677: int i, blks, size, error;
1.18 cgd 678: int32_t *lp;
1.111 fvdl 679: struct ufsmount *ump;
1.141 dbj 680: daddr_t sblockloc;
1.1 mycroft 681:
1.153 mycroft 682: if ((mp->mnt_flag & MNT_RDONLY) == 0)
1.1 mycroft 683: return (EINVAL);
1.111 fvdl 684:
1.153 mycroft 685: ump = VFSTOUFS(mp);
1.1 mycroft 686: /*
687: * Step 1: invalidate all cached meta-data.
688: */
1.111 fvdl 689: devvp = ump->um_devvp;
1.55 fvdl 690: vn_lock(devvp, LK_EXCLUSIVE | LK_RETRY);
1.177 christos 691: error = vinvalbuf(devvp, 0, cred, l, 0, 0);
1.55 fvdl 692: VOP_UNLOCK(devvp, 0);
693: if (error)
1.1 mycroft 694: panic("ffs_reload: dirty1");
695: /*
696: * Step 2: re-read superblock from disk.
697: */
1.111 fvdl 698: fs = ump->um_fs;
1.211 pooka 699: if (VOP_IOCTL(devvp, DIOCGPART, &dpart, FREAD, NOCRED) != 0)
1.1 mycroft 700: size = DEV_BSIZE;
701: else
702: size = dpart.disklab->d_secsize;
1.141 dbj 703: /* XXX we don't handle possibility that superblock moved. */
1.110 fvdl 704: error = bread(devvp, fs->fs_sblockloc / size, fs->fs_sbsize,
1.228 hannken 705: NOCRED, 0, &bp);
1.47 bouyer 706: if (error) {
1.209 ad 707: brelse(bp, 0);
1.1 mycroft 708: return (error);
1.47 bouyer 709: }
1.34 bouyer 710: newfs = malloc(fs->fs_sbsize, M_UFSMNT, M_WAITOK);
1.42 perry 711: memcpy(newfs, bp->b_data, fs->fs_sbsize);
1.34 bouyer 712: #ifdef FFS_EI
1.111 fvdl 713: if (ump->um_flags & UFS_NEEDSWAP) {
1.83 lukem 714: ffs_sb_swap((struct fs*)bp->b_data, newfs);
1.55 fvdl 715: fs->fs_flags |= FS_SWAPPED;
1.121 bouyer 716: } else
1.34 bouyer 717: #endif
1.121 bouyer 718: fs->fs_flags &= ~FS_SWAPPED;
1.161 perry 719: if ((newfs->fs_magic != FS_UFS1_MAGIC &&
1.110 fvdl 720: newfs->fs_magic != FS_UFS2_MAGIC)||
721: newfs->fs_bsize > MAXBSIZE ||
722: newfs->fs_bsize < sizeof(struct fs)) {
1.209 ad 723: brelse(bp, 0);
1.34 bouyer 724: free(newfs, M_UFSMNT);
1.1 mycroft 725: return (EIO); /* XXX needs translation */
726: }
1.141 dbj 727: /* Store off old fs_sblockloc for fs_oldfscompat_read. */
728: sblockloc = fs->fs_sblockloc;
1.161 perry 729: /*
1.18 cgd 730: * Copy pointer fields back into superblock before copying in XXX
731: * new superblock. These should really be in the ufsmount. XXX
732: * Note that important parameters (eg fs_ncg) are unchanged.
733: */
1.84 lukem 734: newfs->fs_csp = fs->fs_csp;
1.18 cgd 735: newfs->fs_maxcluster = fs->fs_maxcluster;
1.85 lukem 736: newfs->fs_contigdirs = fs->fs_contigdirs;
1.76 mycroft 737: newfs->fs_ronly = fs->fs_ronly;
1.110 fvdl 738: newfs->fs_active = fs->fs_active;
1.42 perry 739: memcpy(fs, newfs, (u_int)fs->fs_sbsize);
1.209 ad 740: brelse(bp, 0);
1.34 bouyer 741: free(newfs, M_UFSMNT);
1.103 dbj 742:
743: /* Recheck for apple UFS filesystem */
1.153 mycroft 744: ump->um_flags &= ~UFS_ISAPPLEUFS;
1.103 dbj 745: /* First check to see if this is tagged as an Apple UFS filesystem
746: * in the disklabel
747: */
1.211 pooka 748: if ((VOP_IOCTL(devvp, DIOCGPART, &dpart, FREAD, cred) == 0) &&
1.103 dbj 749: (dpart.part->p_fstype == FS_APPLEUFS)) {
1.153 mycroft 750: ump->um_flags |= UFS_ISAPPLEUFS;
1.103 dbj 751: }
752: #ifdef APPLE_UFS
753: else {
754: /* Manually look for an apple ufs label, and if a valid one
755: * is found, then treat it like an Apple UFS filesystem anyway
756: */
1.106 fvdl 757: error = bread(devvp, (daddr_t)(APPLEUFS_LABEL_OFFSET / size),
1.228 hannken 758: APPLEUFS_LABEL_SIZE, cred, 0, &bp);
1.103 dbj 759: if (error) {
1.209 ad 760: brelse(bp, 0);
1.103 dbj 761: return (error);
762: }
763: error = ffs_appleufs_validate(fs->fs_fsmnt,
1.231 simonb 764: (struct appleufslabel *)bp->b_data, NULL);
1.153 mycroft 765: if (error == 0)
766: ump->um_flags |= UFS_ISAPPLEUFS;
1.209 ad 767: brelse(bp, 0);
1.103 dbj 768: bp = NULL;
769: }
770: #else
1.153 mycroft 771: if (ump->um_flags & UFS_ISAPPLEUFS)
1.103 dbj 772: return (EIO);
773: #endif
774:
1.153 mycroft 775: if (UFS_MPISAPPLEUFS(ump)) {
1.103 dbj 776: /* see comment about NeXT below */
1.153 mycroft 777: ump->um_maxsymlinklen = APPLEUFS_MAXSYMLINKLEN;
778: ump->um_dirblksiz = APPLEUFS_DIRBLKSIZ;
779: mp->mnt_iflag |= IMNT_DTYPE;
780: } else {
781: ump->um_maxsymlinklen = fs->fs_maxsymlinklen;
782: ump->um_dirblksiz = DIRBLKSIZ;
783: if (ump->um_maxsymlinklen > 0)
784: mp->mnt_iflag |= IMNT_DTYPE;
785: else
786: mp->mnt_iflag &= ~IMNT_DTYPE;
1.103 dbj 787: }
1.154 yamt 788: ffs_oldfscompat_read(fs, ump, sblockloc);
1.209 ad 789: mutex_enter(&ump->um_lock);
1.153 mycroft 790: ump->um_maxfilesize = fs->fs_maxfilesize;
1.231 simonb 791:
792: if (fs->fs_flags & ~(FS_KNOWN_FLAGS | FS_INTERNAL)) {
793: uprintf("%s: unknown ufs flags: 0x%08"PRIx32"%s\n",
794: mp->mnt_stat.f_mntonname, fs->fs_flags,
795: (mp->mnt_flag & MNT_FORCE) ? "" : ", not mounting");
796: if ((mp->mnt_flag & MNT_FORCE) == 0) {
797: mutex_exit(&ump->um_lock);
798: return (EINVAL);
799: }
800: }
801:
1.89 fvdl 802: if (fs->fs_pendingblocks != 0 || fs->fs_pendinginodes != 0) {
803: fs->fs_pendingblocks = 0;
804: fs->fs_pendinginodes = 0;
805: }
1.209 ad 806: mutex_exit(&ump->um_lock);
1.85 lukem 807:
1.211 pooka 808: ffs_statvfs(mp, &mp->mnt_stat);
1.1 mycroft 809: /*
810: * Step 3: re-read summary information from disk.
811: */
812: blks = howmany(fs->fs_cssize, fs->fs_fsize);
1.84 lukem 813: space = fs->fs_csp;
1.1 mycroft 814: for (i = 0; i < blks; i += fs->fs_frag) {
815: size = fs->fs_bsize;
816: if (i + fs->fs_frag > blks)
817: size = (blks - i) * fs->fs_fsize;
1.19 christos 818: error = bread(devvp, fsbtodb(fs, fs->fs_csaddr + i), size,
1.228 hannken 819: NOCRED, 0, &bp);
1.47 bouyer 820: if (error) {
1.209 ad 821: brelse(bp, 0);
1.1 mycroft 822: return (error);
1.47 bouyer 823: }
1.34 bouyer 824: #ifdef FFS_EI
1.55 fvdl 825: if (UFS_FSNEEDSWAP(fs))
1.84 lukem 826: ffs_csum_swap((struct csum *)bp->b_data,
827: (struct csum *)space, size);
1.34 bouyer 828: else
829: #endif
1.84 lukem 830: memcpy(space, bp->b_data, (size_t)size);
831: space = (char *)space + size;
1.209 ad 832: brelse(bp, 0);
1.1 mycroft 833: }
1.55 fvdl 834: if ((fs->fs_flags & FS_DOSOFTDEP))
1.153 mycroft 835: softdep_mount(devvp, mp, fs, cred);
1.149 hannken 836: if (fs->fs_snapinum[0] != 0)
1.153 mycroft 837: ffs_snapshot_mount(mp);
1.18 cgd 838: /*
839: * We no longer know anything about clusters per cylinder group.
840: */
841: if (fs->fs_contigsumsize > 0) {
842: lp = fs->fs_maxcluster;
843: for (i = 0; i < fs->fs_ncg; i++)
844: *lp++ = fs->fs_contigsumsize;
845: }
846:
1.214 ad 847: /* Allocate a marker vnode. */
1.215 pooka 848: if ((mvp = vnalloc(mp)) == NULL)
1.214 ad 849: return ENOMEM;
1.189 reinoud 850: /*
851: * NOTE: not using the TAILQ_FOREACH here since in this loop vgone()
852: * and vclean() can be called indirectly
853: */
1.214 ad 854: mutex_enter(&mntvnode_lock);
855: loop:
856: for (vp = TAILQ_FIRST(&mp->mnt_vnodelist); vp; vp = vunmark(mvp)) {
857: vmark(mvp, vp);
858: if (vp->v_mount != mp || vismarker(vp))
859: continue;
1.1 mycroft 860: /*
861: * Step 4: invalidate all inactive vnodes.
862: */
1.214 ad 863: if (vrecycle(vp, &mntvnode_lock, l)) {
864: mutex_enter(&mntvnode_lock);
865: (void)vunmark(mvp);
1.33 fvdl 866: goto loop;
1.214 ad 867: }
1.1 mycroft 868: /*
869: * Step 5: invalidate all cached file data.
870: */
1.214 ad 871: mutex_enter(&vp->v_interlock);
872: mutex_exit(&mntvnode_lock);
873: if (vget(vp, LK_EXCLUSIVE | LK_INTERLOCK)) {
874: (void)vunmark(mvp);
1.1 mycroft 875: goto loop;
1.214 ad 876: }
1.177 christos 877: if (vinvalbuf(vp, 0, cred, l, 0, 0))
1.1 mycroft 878: panic("ffs_reload: dirty2");
879: /*
880: * Step 6: re-read inode data for all active vnodes.
881: */
882: ip = VTOI(vp);
1.19 christos 883: error = bread(devvp, fsbtodb(fs, ino_to_fsba(fs, ip->i_number)),
1.228 hannken 884: (int)fs->fs_bsize, NOCRED, 0, &bp);
1.19 christos 885: if (error) {
1.209 ad 886: brelse(bp, 0);
1.1 mycroft 887: vput(vp);
1.214 ad 888: (void)vunmark(mvp);
889: break;
1.1 mycroft 890: }
1.110 fvdl 891: ffs_load_inode(bp, ip, fs, ip->i_number);
892: ip->i_ffs_effnlink = ip->i_nlink;
1.209 ad 893: brelse(bp, 0);
1.1 mycroft 894: vput(vp);
1.214 ad 895: mutex_enter(&mntvnode_lock);
1.1 mycroft 896: }
1.214 ad 897: mutex_exit(&mntvnode_lock);
1.215 pooka 898: vnfree(mvp);
1.214 ad 899: return (error);
1.1 mycroft 900: }
901:
902: /*
1.110 fvdl 903: * Possible superblock locations ordered from most to least likely.
904: */
1.135 jdolecek 905: static const int sblock_try[] = SBLOCKSEARCH;
1.110 fvdl 906:
907: /*
1.1 mycroft 908: * Common code for mount and mountroot
909: */
910: int
1.177 christos 911: ffs_mountfs(struct vnode *devvp, struct mount *mp, struct lwp *l)
1.1 mycroft 912: {
1.34 bouyer 913: struct ufsmount *ump;
1.1 mycroft 914: struct buf *bp;
1.34 bouyer 915: struct fs *fs;
1.9 mycroft 916: dev_t dev;
1.1 mycroft 917: struct partinfo dpart;
1.84 lukem 918: void *space;
1.110 fvdl 919: daddr_t sblockloc, fsblockloc;
920: int blks, fstype;
1.209 ad 921: int error, i, size, ronly, bset = 0;
1.52 drochner 922: #ifdef FFS_EI
1.110 fvdl 923: int needswap = 0; /* keep gcc happy */
1.52 drochner 924: #endif
1.9 mycroft 925: int32_t *lp;
1.181 elad 926: kauth_cred_t cred;
1.110 fvdl 927: u_int32_t sbsize = 8192; /* keep gcc happy*/
1.1 mycroft 928:
1.9 mycroft 929: dev = devvp->v_rdev;
1.184 ad 930: cred = l ? l->l_cred : NOCRED;
1.159 mycroft 931:
932: /* Flush out any old buffers remaining from a previous use. */
1.55 fvdl 933: vn_lock(devvp, LK_EXCLUSIVE | LK_RETRY);
1.177 christos 934: error = vinvalbuf(devvp, V_SAVE, cred, l, 0, 0);
1.55 fvdl 935: VOP_UNLOCK(devvp, 0);
936: if (error)
1.1 mycroft 937: return (error);
938:
939: ronly = (mp->mnt_flag & MNT_RDONLY) != 0;
1.211 pooka 940: if (VOP_IOCTL(devvp, DIOCGPART, &dpart, FREAD, cred) != 0)
1.1 mycroft 941: size = DEV_BSIZE;
942: else
943: size = dpart.disklab->d_secsize;
944:
945: bp = NULL;
946: ump = NULL;
1.110 fvdl 947: fs = NULL;
1.138 dsl 948: sblockloc = 0;
1.110 fvdl 949: fstype = 0;
1.34 bouyer 950:
1.214 ad 951: error = fstrans_mount(mp);
952: if (error)
953: return error;
954:
1.231 simonb 955: ump = malloc(sizeof *ump, M_UFSMNT, M_WAITOK);
956: memset(ump, 0, sizeof *ump);
957: mutex_init(&ump->um_lock, MUTEX_DEFAULT, IPL_NONE);
958: error = ffs_snapshot_init(ump);
959: if (error)
960: goto out;
961: ump->um_ops = &ffs_ufsops;
962:
963: #ifdef WAPBL
964: sbagain:
965: #endif
1.110 fvdl 966: /*
1.192 isaki 967: * Try reading the superblock in each of its possible locations.
968: */
1.138 dsl 969: for (i = 0; ; i++) {
970: if (bp != NULL) {
1.209 ad 971: brelse(bp, BC_NOCACHE);
1.138 dsl 972: bp = NULL;
973: }
974: if (sblock_try[i] == -1) {
975: error = EINVAL;
976: fs = NULL;
977: goto out;
978: }
1.110 fvdl 979: error = bread(devvp, sblock_try[i] / size, SBLOCKSIZE, cred,
1.228 hannken 980: 0, &bp);
1.168 drochner 981: if (error) {
982: fs = NULL;
1.110 fvdl 983: goto out;
1.168 drochner 984: }
1.110 fvdl 985: fs = (struct fs*)bp->b_data;
986: fsblockloc = sblockloc = sblock_try[i];
987: if (fs->fs_magic == FS_UFS1_MAGIC) {
988: sbsize = fs->fs_sbsize;
989: fstype = UFS1;
1.34 bouyer 990: #ifdef FFS_EI
1.110 fvdl 991: needswap = 0;
992: } else if (fs->fs_magic == bswap32(FS_UFS1_MAGIC)) {
993: sbsize = bswap32(fs->fs_sbsize);
994: fstype = UFS1;
995: needswap = 1;
1.34 bouyer 996: #endif
1.110 fvdl 997: } else if (fs->fs_magic == FS_UFS2_MAGIC) {
998: sbsize = fs->fs_sbsize;
999: fstype = UFS2;
1000: #ifdef FFS_EI
1001: needswap = 0;
1002: } else if (fs->fs_magic == bswap32(FS_UFS2_MAGIC)) {
1003: sbsize = bswap32(fs->fs_sbsize);
1004: fstype = UFS2;
1005: needswap = 1;
1006: #endif
1.112 fvdl 1007: } else
1.138 dsl 1008: continue;
1009:
1010:
1011: /* fs->fs_sblockloc isn't defined for old filesystems */
1.140 dsl 1012: if (fstype == UFS1 && !(fs->fs_old_flags & FS_FLAGS_UPDATED)) {
1013: if (sblockloc == SBLOCK_UFS2)
1.138 dsl 1014: /*
1015: * This is likely to be the first alternate
1016: * in a filesystem with 64k blocks.
1017: * Don't use it.
1018: */
1019: continue;
1020: fsblockloc = sblockloc;
1021: } else {
1022: fsblockloc = fs->fs_sblockloc;
1023: #ifdef FFS_EI
1024: if (needswap)
1025: fsblockloc = bswap64(fsblockloc);
1026: #endif
1027: }
1.110 fvdl 1028:
1.138 dsl 1029: /* Check we haven't found an alternate superblock */
1030: if (fsblockloc != sblockloc)
1031: continue;
1.112 fvdl 1032:
1.138 dsl 1033: /* Validate size of superblock */
1034: if (sbsize > MAXBSIZE || sbsize < sizeof(struct fs))
1035: continue;
1.110 fvdl 1036:
1.138 dsl 1037: /* Ok seems to be a good superblock */
1038: break;
1.34 bouyer 1039: }
1040:
1041: fs = malloc((u_long)sbsize, M_UFSMNT, M_WAITOK);
1.42 perry 1042: memcpy(fs, bp->b_data, sbsize);
1.111 fvdl 1043: ump->um_fs = fs;
1044:
1.34 bouyer 1045: #ifdef FFS_EI
1.55 fvdl 1046: if (needswap) {
1.83 lukem 1047: ffs_sb_swap((struct fs*)bp->b_data, fs);
1.55 fvdl 1048: fs->fs_flags |= FS_SWAPPED;
1.121 bouyer 1049: } else
1.34 bouyer 1050: #endif
1.121 bouyer 1051: fs->fs_flags &= ~FS_SWAPPED;
1.56 drochner 1052:
1.231 simonb 1053: #ifdef WAPBL
1054: if ((mp->mnt_wapbl_replay == 0) && (fs->fs_flags & FS_DOWAPBL)) {
1055: error = ffs_wapbl_replay_start(mp, fs, devvp);
1056: if (error)
1057: goto out;
1058:
1059: if (!ronly) {
1.236 freza 1060: /* XXX fsmnt may be stale. */
1061: printf("%s: replaying log to disk\n", fs->fs_fsmnt);
1.231 simonb 1062: error = wapbl_replay_write(mp->mnt_wapbl_replay, devvp);
1063: if (error)
1064: goto out;
1065: wapbl_replay_stop(mp->mnt_wapbl_replay);
1066: fs->fs_clean = FS_WASCLEAN;
1067: } else {
1.236 freza 1068: /* XXX fsmnt may be stale */
1069: printf("%s: replaying log to memory\n", fs->fs_fsmnt);
1.231 simonb 1070: }
1071:
1072: /* Force a re-read of the superblock */
1073: brelse(bp, BC_INVAL);
1074: bp = NULL;
1075: free(fs, M_UFSMNT);
1076: fs = NULL;
1077: goto sbagain;
1078: }
1079: #else /* !WAPBL */
1080: if ((fs->fs_flags & FS_DOWAPBL) && (mp->mnt_flag & MNT_FORCE) == 0) {
1081: error = EPERM;
1082: goto out;
1083: }
1084: #endif /* !WAPBL */
1085:
1.154 yamt 1086: ffs_oldfscompat_read(fs, ump, sblockloc);
1.153 mycroft 1087: ump->um_maxfilesize = fs->fs_maxfilesize;
1.131 dbj 1088:
1.231 simonb 1089: if (fs->fs_flags & ~(FS_KNOWN_FLAGS | FS_INTERNAL)) {
1090: uprintf("%s: unknown ufs flags: 0x%08"PRIx32"%s\n",
1091: mp->mnt_stat.f_mntonname, fs->fs_flags,
1092: (mp->mnt_flag & MNT_FORCE) ? "" : ", not mounting");
1093: if ((mp->mnt_flag & MNT_FORCE) == 0) {
1094: error = EINVAL;
1095: goto out;
1096: }
1097: }
1098:
1.89 fvdl 1099: if (fs->fs_pendingblocks != 0 || fs->fs_pendinginodes != 0) {
1100: fs->fs_pendingblocks = 0;
1101: fs->fs_pendinginodes = 0;
1102: }
1.56 drochner 1103:
1.110 fvdl 1104: ump->um_fstype = fstype;
1105: if (fs->fs_sbsize < SBLOCKSIZE)
1.209 ad 1106: brelse(bp, BC_INVAL);
1107: else
1108: brelse(bp, 0);
1.1 mycroft 1109: bp = NULL;
1.94 chs 1110:
1.103 dbj 1111: /* First check to see if this is tagged as an Apple UFS filesystem
1112: * in the disklabel
1113: */
1.211 pooka 1114: if ((VOP_IOCTL(devvp, DIOCGPART, &dpart, FREAD, cred) == 0) &&
1.103 dbj 1115: (dpart.part->p_fstype == FS_APPLEUFS)) {
1116: ump->um_flags |= UFS_ISAPPLEUFS;
1117: }
1118: #ifdef APPLE_UFS
1119: else {
1120: /* Manually look for an apple ufs label, and if a valid one
1121: * is found, then treat it like an Apple UFS filesystem anyway
1122: */
1.106 fvdl 1123: error = bread(devvp, (daddr_t)(APPLEUFS_LABEL_OFFSET / size),
1.228 hannken 1124: APPLEUFS_LABEL_SIZE, cred, 0, &bp);
1.103 dbj 1125: if (error)
1126: goto out;
1127: error = ffs_appleufs_validate(fs->fs_fsmnt,
1.231 simonb 1128: (struct appleufslabel *)bp->b_data, NULL);
1.103 dbj 1129: if (error == 0) {
1130: ump->um_flags |= UFS_ISAPPLEUFS;
1131: }
1.209 ad 1132: brelse(bp, 0);
1.103 dbj 1133: bp = NULL;
1134: }
1135: #else
1136: if (ump->um_flags & UFS_ISAPPLEUFS) {
1137: error = EINVAL;
1138: goto out;
1139: }
1140: #endif
1141:
1.231 simonb 1142: #if 0
1143: /*
1144: * XXX This code changes the behaviour of mounting dirty filesystems, to
1145: * XXX require "mount -f ..." to mount them. This doesn't match what
1146: * XXX mount(8) describes and is disabled for now.
1147: */
1148: /*
1149: * If the file system is not clean, don't allow it to be mounted
1150: * unless MNT_FORCE is specified. (Note: MNT_FORCE is always set
1151: * for the root file system.)
1152: */
1153: if (fs->fs_flags & FS_DOWAPBL) {
1154: /*
1155: * wapbl normally expects to be FS_WASCLEAN when the FS_DOWAPBL
1156: * bit is set, although there's a window in unmount where it
1157: * could be FS_ISCLEAN
1158: */
1159: if ((mp->mnt_flag & MNT_FORCE) == 0 &&
1160: (fs->fs_clean & (FS_WASCLEAN | FS_ISCLEAN)) == 0) {
1161: error = EPERM;
1162: goto out;
1163: }
1164: } else
1165: if ((fs->fs_clean & FS_ISCLEAN) == 0 &&
1166: (mp->mnt_flag & MNT_FORCE) == 0) {
1167: error = EPERM;
1168: goto out;
1169: }
1170: #endif
1171:
1.94 chs 1172: /*
1.99 chs 1173: * verify that we can access the last block in the fs
1174: * if we're mounting read/write.
1.94 chs 1175: */
1176:
1.99 chs 1177: if (!ronly) {
1178: error = bread(devvp, fsbtodb(fs, fs->fs_size - 1), fs->fs_fsize,
1.228 hannken 1179: cred, 0, &bp);
1.99 chs 1180: if (bp->b_bcount != fs->fs_fsize)
1181: error = EINVAL;
1.209 ad 1182: if (error) {
1183: bset = BC_INVAL;
1.99 chs 1184: goto out;
1.209 ad 1185: }
1186: brelse(bp, BC_INVAL);
1.99 chs 1187: bp = NULL;
1188: }
1.94 chs 1189:
1.1 mycroft 1190: fs->fs_ronly = ronly;
1.231 simonb 1191: /* Don't bump fs_clean if we're replaying journal */
1192: if (!((fs->fs_flags & FS_DOWAPBL) && (fs->fs_clean & FS_WASCLEAN)))
1193: if (ronly == 0) {
1194: fs->fs_clean <<= 1;
1195: fs->fs_fmod = 1;
1196: }
1.9 mycroft 1197: size = fs->fs_cssize;
1198: blks = howmany(size, fs->fs_fsize);
1199: if (fs->fs_contigsumsize > 0)
1200: size += fs->fs_ncg * sizeof(int32_t);
1.85 lukem 1201: size += fs->fs_ncg * sizeof(*fs->fs_contigdirs);
1.84 lukem 1202: space = malloc((u_long)size, M_UFSMNT, M_WAITOK);
1203: fs->fs_csp = space;
1.1 mycroft 1204: for (i = 0; i < blks; i += fs->fs_frag) {
1205: size = fs->fs_bsize;
1206: if (i + fs->fs_frag > blks)
1207: size = (blks - i) * fs->fs_fsize;
1.19 christos 1208: error = bread(devvp, fsbtodb(fs, fs->fs_csaddr + i), size,
1.228 hannken 1209: cred, 0, &bp);
1.19 christos 1210: if (error) {
1.84 lukem 1211: free(fs->fs_csp, M_UFSMNT);
1.128 dbj 1212: goto out;
1.1 mycroft 1213: }
1.34 bouyer 1214: #ifdef FFS_EI
1215: if (needswap)
1.84 lukem 1216: ffs_csum_swap((struct csum *)bp->b_data,
1217: (struct csum *)space, size);
1.34 bouyer 1218: else
1219: #endif
1.42 perry 1220: memcpy(space, bp->b_data, (u_int)size);
1.161 perry 1221:
1.84 lukem 1222: space = (char *)space + size;
1.209 ad 1223: brelse(bp, 0);
1.1 mycroft 1224: bp = NULL;
1225: }
1.9 mycroft 1226: if (fs->fs_contigsumsize > 0) {
1.85 lukem 1227: fs->fs_maxcluster = lp = space;
1.9 mycroft 1228: for (i = 0; i < fs->fs_ncg; i++)
1229: *lp++ = fs->fs_contigsumsize;
1.85 lukem 1230: space = lp;
1.9 mycroft 1231: }
1.85 lukem 1232: size = fs->fs_ncg * sizeof(*fs->fs_contigdirs);
1233: fs->fs_contigdirs = space;
1234: space = (char *)space + size;
1235: memset(fs->fs_contigdirs, 0, size);
1236: /* Compatibility for old filesystems - XXX */
1237: if (fs->fs_avgfilesize <= 0)
1238: fs->fs_avgfilesize = AVFILESIZ;
1239: if (fs->fs_avgfpdir <= 0)
1240: fs->fs_avgfpdir = AFPDIR;
1.150 hannken 1241: fs->fs_active = NULL;
1.100 soren 1242: mp->mnt_data = ump;
1.143 christos 1243: mp->mnt_stat.f_fsidx.__fsid_val[0] = (long)dev;
1244: mp->mnt_stat.f_fsidx.__fsid_val[1] = makefstype(MOUNT_FFS);
1245: mp->mnt_stat.f_fsid = mp->mnt_stat.f_fsidx.__fsid_val[0];
1.169 christos 1246: mp->mnt_stat.f_namemax = FFS_MAXNAMLEN;
1.153 mycroft 1247: if (UFS_MPISAPPLEUFS(ump)) {
1.103 dbj 1248: /* NeXT used to keep short symlinks in the inode even
1249: * when using FS_42INODEFMT. In that case fs->fs_maxsymlinklen
1250: * is probably -1, but we still need to be able to identify
1251: * short symlinks.
1252: */
1.153 mycroft 1253: ump->um_maxsymlinklen = APPLEUFS_MAXSYMLINKLEN;
1254: ump->um_dirblksiz = APPLEUFS_DIRBLKSIZ;
1255: mp->mnt_iflag |= IMNT_DTYPE;
1256: } else {
1257: ump->um_maxsymlinklen = fs->fs_maxsymlinklen;
1258: ump->um_dirblksiz = DIRBLKSIZ;
1259: if (ump->um_maxsymlinklen > 0)
1260: mp->mnt_iflag |= IMNT_DTYPE;
1261: else
1262: mp->mnt_iflag &= ~IMNT_DTYPE;
1.103 dbj 1263: }
1.73 chs 1264: mp->mnt_fs_bshift = fs->fs_bshift;
1265: mp->mnt_dev_bshift = DEV_BSHIFT; /* XXX */
1.1 mycroft 1266: mp->mnt_flag |= MNT_LOCAL;
1.214 ad 1267: mp->mnt_iflag |= IMNT_MPSAFE;
1.34 bouyer 1268: #ifdef FFS_EI
1269: if (needswap)
1270: ump->um_flags |= UFS_NEEDSWAP;
1271: #endif
1.1 mycroft 1272: ump->um_mountp = mp;
1273: ump->um_dev = dev;
1274: ump->um_devvp = devvp;
1275: ump->um_nindir = fs->fs_nindir;
1.73 chs 1276: ump->um_lognindir = ffs(fs->fs_nindir) - 1;
1.1 mycroft 1277: ump->um_bptrtodb = fs->fs_fsbtodb;
1278: ump->um_seqinc = fs->fs_frag;
1279: for (i = 0; i < MAXQUOTAS; i++)
1280: ump->um_quotas[i] = NULLVP;
1.55 fvdl 1281: devvp->v_specmountpoint = mp;
1282: if (ronly == 0 && (fs->fs_flags & FS_DOSOFTDEP)) {
1283: error = softdep_mount(devvp, mp, fs, cred);
1284: if (error) {
1.84 lukem 1285: free(fs->fs_csp, M_UFSMNT);
1.55 fvdl 1286: goto out;
1287: }
1288: }
1.232 hannken 1289: if (ronly == 0 && fs->fs_snapinum[0] != 0)
1290: ffs_snapshot_mount(mp);
1.231 simonb 1291:
1292: #ifdef WAPBL
1293: if (!ronly) {
1294: KDASSERT(fs->fs_ronly == 0);
1295: /*
1296: * ffs_wapbl_start() needs mp->mnt_stat initialised if it
1297: * needs to create a new log file in-filesystem.
1298: */
1299: ffs_statvfs(mp, &mp->mnt_stat);
1300:
1301: error = ffs_wapbl_start(mp);
1302: if (error) {
1303: free(fs->fs_csp, M_UFSMNT);
1304: goto out;
1305: }
1306: }
1307: #endif /* WAPBL */
1.170 thorpej 1308: #ifdef UFS_EXTATTR
1309: /*
1310: * Initialize file-backed extended attributes on UFS1 file
1311: * systems.
1312: */
1313: if (ump->um_fstype == UFS1) {
1314: ufs_extattr_uepm_init(&ump->um_extattr);
1315: #ifdef UFS_EXTATTR_AUTOSTART
1316: /*
1317: * XXX Just ignore errors. Not clear that we should
1318: * XXX fail the mount in this case.
1319: */
1.178 rpaulo 1320: (void) ufs_extattr_autostart(mp, l);
1.170 thorpej 1321: #endif
1322: }
1323: #endif /* UFS_EXTATTR */
1.1 mycroft 1324: return (0);
1325: out:
1.231 simonb 1326: #ifdef WAPBL
1327: if (mp->mnt_wapbl_replay) {
1328: if (wapbl_replay_isopen(mp->mnt_wapbl_replay))
1329: wapbl_replay_stop(mp->mnt_wapbl_replay);
1330: wapbl_replay_free(mp->mnt_wapbl_replay);
1331: mp->mnt_wapbl_replay = 0;
1332: }
1333: #endif
1334:
1.214 ad 1335: fstrans_unmount(mp);
1.128 dbj 1336: if (fs)
1337: free(fs, M_UFSMNT);
1.55 fvdl 1338: devvp->v_specmountpoint = NULL;
1.1 mycroft 1339: if (bp)
1.209 ad 1340: brelse(bp, bset);
1.1 mycroft 1341: if (ump) {
1.131 dbj 1342: if (ump->um_oldfscompat)
1343: free(ump->um_oldfscompat, M_UFSMNT);
1.209 ad 1344: mutex_destroy(&ump->um_lock);
1.1 mycroft 1345: free(ump, M_UFSMNT);
1.100 soren 1346: mp->mnt_data = NULL;
1.1 mycroft 1347: }
1348: return (error);
1349: }
1350:
1351: /*
1.110 fvdl 1352: * Sanity checks for loading old filesystem superblocks.
1353: * See ffs_oldfscompat_write below for unwound actions.
1.1 mycroft 1354: *
1.110 fvdl 1355: * XXX - Parts get retired eventually.
1356: * Unfortunately new bits get added.
1.1 mycroft 1357: */
1.110 fvdl 1358: static void
1.166 thorpej 1359: ffs_oldfscompat_read(struct fs *fs, struct ufsmount *ump, daddr_t sblockloc)
1.110 fvdl 1360: {
1361: off_t maxfilesize;
1.131 dbj 1362: int32_t *extrasave;
1.110 fvdl 1363:
1.131 dbj 1364: if ((fs->fs_magic != FS_UFS1_MAGIC) ||
1365: (fs->fs_old_flags & FS_FLAGS_UPDATED))
1.111 fvdl 1366: return;
1367:
1.131 dbj 1368: if (!ump->um_oldfscompat)
1369: ump->um_oldfscompat = malloc(512 + 3*sizeof(int32_t),
1370: M_UFSMNT, M_WAITOK);
1371:
1372: memcpy(ump->um_oldfscompat, &fs->fs_old_postbl_start, 512);
1373: extrasave = ump->um_oldfscompat;
1374: extrasave += 512/sizeof(int32_t);
1375: extrasave[0] = fs->fs_old_npsect;
1376: extrasave[1] = fs->fs_old_interleave;
1377: extrasave[2] = fs->fs_old_trackskew;
1378:
1379: /* These fields will be overwritten by their
1380: * original values in fs_oldfscompat_write, so it is harmless
1381: * to modify them here.
1382: */
1383: fs->fs_cstotal.cs_ndir = fs->fs_old_cstotal.cs_ndir;
1384: fs->fs_cstotal.cs_nbfree = fs->fs_old_cstotal.cs_nbfree;
1385: fs->fs_cstotal.cs_nifree = fs->fs_old_cstotal.cs_nifree;
1386: fs->fs_cstotal.cs_nffree = fs->fs_old_cstotal.cs_nffree;
1387:
1388: fs->fs_maxbsize = fs->fs_bsize;
1389: fs->fs_time = fs->fs_old_time;
1390: fs->fs_size = fs->fs_old_size;
1391: fs->fs_dsize = fs->fs_old_dsize;
1392: fs->fs_csaddr = fs->fs_old_csaddr;
1393: fs->fs_sblockloc = sblockloc;
1394:
1.231 simonb 1395: fs->fs_flags = fs->fs_old_flags | (fs->fs_flags & FS_INTERNAL);
1.122 enami 1396:
1.131 dbj 1397: if (fs->fs_old_postblformat == FS_42POSTBLFMT) {
1398: fs->fs_old_nrpos = 8;
1399: fs->fs_old_npsect = fs->fs_old_nsect;
1400: fs->fs_old_interleave = 1;
1401: fs->fs_old_trackskew = 0;
1.111 fvdl 1402: }
1403:
1404: if (fs->fs_old_inodefmt < FS_44INODEFMT) {
1.201 tsutsui 1405: fs->fs_maxfilesize = (u_quad_t) 1LL << 39;
1.110 fvdl 1406: fs->fs_qbmask = ~fs->fs_bmask;
1407: fs->fs_qfmask = ~fs->fs_fmask;
1408: }
1.111 fvdl 1409:
1410: maxfilesize = (u_int64_t)0x80000000 * fs->fs_bsize - 1;
1.201 tsutsui 1411: if (fs->fs_maxfilesize > maxfilesize)
1412: fs->fs_maxfilesize = maxfilesize;
1.111 fvdl 1413:
1.110 fvdl 1414: /* Compatibility for old filesystems */
1415: if (fs->fs_avgfilesize <= 0)
1416: fs->fs_avgfilesize = AVFILESIZ;
1417: if (fs->fs_avgfpdir <= 0)
1418: fs->fs_avgfpdir = AFPDIR;
1.131 dbj 1419:
1.110 fvdl 1420: #if 0
1421: if (bigcgs) {
1422: fs->fs_save_cgsize = fs->fs_cgsize;
1423: fs->fs_cgsize = fs->fs_bsize;
1424: }
1425: #endif
1426: }
1427:
1428: /*
1429: * Unwinding superblock updates for old filesystems.
1430: * See ffs_oldfscompat_read above for details.
1431: *
1432: * XXX - Parts get retired eventually.
1433: * Unfortunately new bits get added.
1434: */
1435: static void
1.166 thorpej 1436: ffs_oldfscompat_write(struct fs *fs, struct ufsmount *ump)
1.1 mycroft 1437: {
1.131 dbj 1438: int32_t *extrasave;
1439:
1440: if ((fs->fs_magic != FS_UFS1_MAGIC) ||
1441: (fs->fs_old_flags & FS_FLAGS_UPDATED))
1.111 fvdl 1442: return;
1.115 fvdl 1443:
1.111 fvdl 1444: fs->fs_old_time = fs->fs_time;
1445: fs->fs_old_cstotal.cs_ndir = fs->fs_cstotal.cs_ndir;
1446: fs->fs_old_cstotal.cs_nbfree = fs->fs_cstotal.cs_nbfree;
1447: fs->fs_old_cstotal.cs_nifree = fs->fs_cstotal.cs_nifree;
1448: fs->fs_old_cstotal.cs_nffree = fs->fs_cstotal.cs_nffree;
1.131 dbj 1449: fs->fs_old_flags = fs->fs_flags;
1.111 fvdl 1450:
1.110 fvdl 1451: #if 0
1452: if (bigcgs) {
1453: fs->fs_cgsize = fs->fs_save_cgsize;
1454: }
1455: #endif
1.131 dbj 1456:
1457: memcpy(&fs->fs_old_postbl_start, ump->um_oldfscompat, 512);
1458: extrasave = ump->um_oldfscompat;
1459: extrasave += 512/sizeof(int32_t);
1460: fs->fs_old_npsect = extrasave[0];
1461: fs->fs_old_interleave = extrasave[1];
1462: fs->fs_old_trackskew = extrasave[2];
1463:
1.1 mycroft 1464: }
1465:
1466: /*
1467: * unmount system call
1468: */
1469: int
1.211 pooka 1470: ffs_unmount(struct mount *mp, int mntflags)
1.1 mycroft 1471: {
1.211 pooka 1472: struct lwp *l = curlwp;
1.170 thorpej 1473: struct ufsmount *ump = VFSTOUFS(mp);
1474: struct fs *fs = ump->um_fs;
1.91 fvdl 1475: int error, flags, penderr;
1.231 simonb 1476: #ifdef WAPBL
1477: extern int doforce;
1478: #endif
1.1 mycroft 1479:
1.91 fvdl 1480: penderr = 0;
1.1 mycroft 1481: flags = 0;
1.11 mycroft 1482: if (mntflags & MNT_FORCE)
1.1 mycroft 1483: flags |= FORCECLOSE;
1.170 thorpej 1484: #ifdef UFS_EXTATTR
1485: if (ump->um_fstype == UFS1) {
1.220 pooka 1486: ufs_extattr_stop(mp, l);
1487: ufs_extattr_uepm_destroy(&ump->um_extattr);
1.170 thorpej 1488: }
1489: #endif /* UFS_EXTATTR */
1.55 fvdl 1490: if (mp->mnt_flag & MNT_SOFTDEP) {
1.177 christos 1491: if ((error = softdep_flushfiles(mp, flags, l)) != 0)
1.55 fvdl 1492: return (error);
1493: } else {
1.177 christos 1494: if ((error = ffs_flushfiles(mp, flags, l)) != 0)
1.55 fvdl 1495: return (error);
1496: }
1.209 ad 1497: mutex_enter(&ump->um_lock);
1.89 fvdl 1498: if (fs->fs_pendingblocks != 0 || fs->fs_pendinginodes != 0) {
1.110 fvdl 1499: printf("%s: unmount pending error: blocks %" PRId64
1500: " files %d\n",
1.89 fvdl 1501: fs->fs_fsmnt, fs->fs_pendingblocks, fs->fs_pendinginodes);
1502: fs->fs_pendingblocks = 0;
1503: fs->fs_pendinginodes = 0;
1.91 fvdl 1504: penderr = 1;
1.89 fvdl 1505: }
1.209 ad 1506: mutex_exit(&ump->um_lock);
1.231 simonb 1507: error = UFS_WAPBL_BEGIN(mp);
1508: if (error == 0)
1509: if (fs->fs_ronly == 0 &&
1510: ffs_cgupdate(ump, MNT_WAIT) == 0 &&
1511: fs->fs_clean & FS_WASCLEAN) {
1512: /*
1513: * XXXX don't mark fs clean in the case of softdep
1514: * pending block errors, until they are fixed.
1515: */
1516: if (penderr == 0) {
1517: if (mp->mnt_flag & MNT_SOFTDEP)
1518: fs->fs_flags &= ~FS_DOSOFTDEP;
1519: fs->fs_clean = FS_ISCLEAN;
1520: }
1521: fs->fs_fmod = 0;
1522: (void) ffs_sbupdate(ump, MNT_WAIT);
1.91 fvdl 1523: }
1.231 simonb 1524: if (error == 0)
1525: UFS_WAPBL_END(mp);
1526: #ifdef WAPBL
1527: KASSERT(!(mp->mnt_wapbl_replay && mp->mnt_wapbl));
1528: if (mp->mnt_wapbl_replay) {
1529: KDASSERT(fs->fs_ronly);
1530: wapbl_replay_stop(mp->mnt_wapbl_replay);
1531: wapbl_replay_free(mp->mnt_wapbl_replay);
1532: mp->mnt_wapbl_replay = 0;
1533: }
1534: error = ffs_wapbl_stop(mp, doforce && (mntflags & MNT_FORCE));
1535: if (error) {
1536: return error;
1.15 mycroft 1537: }
1.231 simonb 1538: #endif /* WAPBL */
1.54 enami 1539: if (ump->um_devvp->v_type != VBAD)
1.55 fvdl 1540: ump->um_devvp->v_specmountpoint = NULL;
1.53 wrstuden 1541: vn_lock(ump->um_devvp, LK_EXCLUSIVE | LK_RETRY);
1.231 simonb 1542: (void)VOP_CLOSE(ump->um_devvp, fs->fs_ronly ? FREAD : FREAD | FWRITE,
1.211 pooka 1543: NOCRED);
1.53 wrstuden 1544: vput(ump->um_devvp);
1.84 lukem 1545: free(fs->fs_csp, M_UFSMNT);
1.1 mycroft 1546: free(fs, M_UFSMNT);
1.131 dbj 1547: if (ump->um_oldfscompat != NULL)
1548: free(ump->um_oldfscompat, M_UFSMNT);
1.214 ad 1549: softdep_unmount(mp);
1.209 ad 1550: mutex_destroy(&ump->um_lock);
1.223 hannken 1551: ffs_snapshot_fini(ump);
1.1 mycroft 1552: free(ump, M_UFSMNT);
1.100 soren 1553: mp->mnt_data = NULL;
1.1 mycroft 1554: mp->mnt_flag &= ~MNT_LOCAL;
1.214 ad 1555: fstrans_unmount(mp);
1.129 dbj 1556: return (0);
1.1 mycroft 1557: }
1558:
1559: /*
1560: * Flush out all the files in a filesystem.
1561: */
1.19 christos 1562: int
1.177 christos 1563: ffs_flushfiles(struct mount *mp, int flags, struct lwp *l)
1.1 mycroft 1564: {
1565: extern int doforce;
1.61 augustss 1566: struct ufsmount *ump;
1.19 christos 1567: int error;
1.1 mycroft 1568:
1569: if (!doforce)
1570: flags &= ~FORCECLOSE;
1571: ump = VFSTOUFS(mp);
1572: #ifdef QUOTA
1573: if (mp->mnt_flag & MNT_QUOTA) {
1.19 christos 1574: int i;
1.231 simonb 1575: if ((error = vflush(mp, NULLVP, SKIPSYSTEM | flags)) != 0)
1.1 mycroft 1576: return (error);
1577: for (i = 0; i < MAXQUOTAS; i++) {
1578: if (ump->um_quotas[i] == NULLVP)
1579: continue;
1.177 christos 1580: quotaoff(l, mp, i);
1.1 mycroft 1581: }
1582: /*
1583: * Here we fall through to vflush again to ensure
1584: * that we have gotten rid of all the system vnodes.
1585: */
1586: }
1587: #endif
1.149 hannken 1588: if ((error = vflush(mp, 0, SKIPSYSTEM | flags)) != 0)
1589: return (error);
1590: ffs_snapshot_unmount(mp);
1.55 fvdl 1591: /*
1592: * Flush all the files.
1593: */
1.1 mycroft 1594: error = vflush(mp, NULLVP, flags);
1.55 fvdl 1595: if (error)
1596: return (error);
1597: /*
1598: * Flush filesystem metadata.
1599: */
1600: vn_lock(ump->um_devvp, LK_EXCLUSIVE | LK_RETRY);
1.211 pooka 1601: error = VOP_FSYNC(ump->um_devvp, l->l_cred, FSYNC_WAIT, 0, 0);
1.55 fvdl 1602: VOP_UNLOCK(ump->um_devvp, 0);
1.231 simonb 1603: if (flags & FORCECLOSE) /* XXXDBJ */
1604: error = 0;
1605:
1606: #ifdef WAPBL
1607: if (error)
1608: return error;
1609: if (mp->mnt_wapbl) {
1610: error = wapbl_flush(mp->mnt_wapbl, 1);
1611: if (flags & FORCECLOSE)
1612: error = 0;
1613: }
1614: #endif
1615:
1.1 mycroft 1616: return (error);
1617: }
1618:
1619: /*
1620: * Get file system statistics.
1621: */
1622: int
1.211 pooka 1623: ffs_statvfs(struct mount *mp, struct statvfs *sbp)
1.1 mycroft 1624: {
1.61 augustss 1625: struct ufsmount *ump;
1626: struct fs *fs;
1.1 mycroft 1627:
1628: ump = VFSTOUFS(mp);
1629: fs = ump->um_fs;
1.209 ad 1630: mutex_enter(&ump->um_lock);
1.143 christos 1631: sbp->f_bsize = fs->fs_bsize;
1632: sbp->f_frsize = fs->fs_fsize;
1.1 mycroft 1633: sbp->f_iosize = fs->fs_bsize;
1634: sbp->f_blocks = fs->fs_dsize;
1.98 mycroft 1635: sbp->f_bfree = blkstofrags(fs, fs->fs_cstotal.cs_nbfree) +
1.89 fvdl 1636: fs->fs_cstotal.cs_nffree + dbtofsb(fs, fs->fs_pendingblocks);
1.143 christos 1637: sbp->f_bresvd = ((u_int64_t) fs->fs_dsize * (u_int64_t)
1638: fs->fs_minfree) / (u_int64_t) 100;
1639: if (sbp->f_bfree > sbp->f_bresvd)
1640: sbp->f_bavail = sbp->f_bfree - sbp->f_bresvd;
1641: else
1642: sbp->f_bavail = 0;
1.1 mycroft 1643: sbp->f_files = fs->fs_ncg * fs->fs_ipg - ROOTINO;
1.89 fvdl 1644: sbp->f_ffree = fs->fs_cstotal.cs_nifree + fs->fs_pendinginodes;
1.143 christos 1645: sbp->f_favail = sbp->f_ffree;
1646: sbp->f_fresvd = 0;
1.209 ad 1647: mutex_exit(&ump->um_lock);
1.143 christos 1648: copy_statvfs_info(sbp, mp);
1.209 ad 1649:
1.1 mycroft 1650: return (0);
1651: }
1652:
1653: /*
1654: * Go through the disk queues to initiate sandbagged IO;
1655: * go through the inodes to write those that have been modified;
1656: * initiate the writing of the super block if it has been modified.
1657: *
1658: * Note: we are always called with the filesystem marked `MPBUSY'.
1659: */
1660: int
1.211 pooka 1661: ffs_sync(struct mount *mp, int waitfor, kauth_cred_t cred)
1.1 mycroft 1662: {
1.211 pooka 1663: struct lwp *l = curlwp;
1.214 ad 1664: struct vnode *vp, *mvp;
1.33 fvdl 1665: struct inode *ip;
1666: struct ufsmount *ump = VFSTOUFS(mp);
1667: struct fs *fs;
1.132 hannken 1668: int error, count, allerror = 0;
1.1 mycroft 1669:
1670: fs = ump->um_fs;
1.33 fvdl 1671: if (fs->fs_fmod != 0 && fs->fs_ronly != 0) { /* XXX */
1672: printf("fs = %s\n", fs->fs_fsmnt);
1673: panic("update: rofs mod");
1.1 mycroft 1674: }
1.214 ad 1675:
1676: /* Allocate a marker vnode. */
1.215 pooka 1677: if ((mvp = vnalloc(mp)) == NULL)
1.214 ad 1678: return (ENOMEM);
1679:
1.199 hannken 1680: fstrans_start(mp, FSTRANS_SHARED);
1.1 mycroft 1681: /*
1682: * Write back each (modified) inode.
1683: */
1.214 ad 1684: mutex_enter(&mntvnode_lock);
1.1 mycroft 1685: loop:
1.189 reinoud 1686: /*
1687: * NOTE: not using the TAILQ_FOREACH here since in this loop vgone()
1688: * and vclean() can be called indirectly
1689: */
1.214 ad 1690: for (vp = TAILQ_FIRST(&mp->mnt_vnodelist); vp; vp = vunmark(mvp)) {
1691: vmark(mvp, vp);
1.1 mycroft 1692: /*
1693: * If the vnode that we are about to sync is no longer
1694: * associated with this mount point, start over.
1695: */
1.214 ad 1696: if (vp->v_mount != mp || vismarker(vp))
1697: continue;
1698: mutex_enter(&vp->v_interlock);
1.1 mycroft 1699: ip = VTOI(vp);
1.231 simonb 1700: /* XXXpooka: why wapbl check? */
1701: if (ip == NULL || (vp->v_iflag & (VI_XLOCK | VI_CLEAN)) != 0 ||
1.214 ad 1702: vp->v_type == VNON || ((ip->i_flag &
1703: (IN_CHANGE | IN_UPDATE | IN_MODIFIED)) == 0 &&
1.231 simonb 1704: (LIST_EMPTY(&vp->v_dirtyblkhd) || (mp->mnt_wapbl)) &&
1.214 ad 1705: UVM_OBJ_IS_CLEAN(&vp->v_uobj)))
1.57 fvdl 1706: {
1.214 ad 1707: mutex_exit(&vp->v_interlock);
1.33 fvdl 1708: continue;
1709: }
1.193 hannken 1710: if (vp->v_type == VBLK &&
1.194 hannken 1711: fstrans_getstate(mp) == FSTRANS_SUSPENDING) {
1.214 ad 1712: mutex_exit(&vp->v_interlock);
1.193 hannken 1713: continue;
1714: }
1.214 ad 1715: mutex_exit(&mntvnode_lock);
1.117 thorpej 1716: error = vget(vp, LK_EXCLUSIVE | LK_NOWAIT | LK_INTERLOCK);
1.33 fvdl 1717: if (error) {
1.214 ad 1718: mutex_enter(&mntvnode_lock);
1719: if (error == ENOENT) {
1720: (void)vunmark(mvp);
1.33 fvdl 1721: goto loop;
1.214 ad 1722: }
1.1 mycroft 1723: continue;
1.33 fvdl 1724: }
1.231 simonb 1725: if (vp->v_type == VREG && waitfor == MNT_LAZY) {
1726: error = UFS_WAPBL_BEGIN(vp->v_mount);
1727: if (!error) {
1728: error = ffs_update(vp, NULL, NULL, 0);
1729: UFS_WAPBL_END(vp->v_mount);
1730: }
1731: } else {
1732: error = VOP_FSYNC(vp, cred, FSYNC_NOLOG |
1733: (waitfor == MNT_WAIT ? FSYNC_WAIT : 0), 0, 0);
1734: }
1.152 mycroft 1735: if (error)
1.1 mycroft 1736: allerror = error;
1737: vput(vp);
1.214 ad 1738: mutex_enter(&mntvnode_lock);
1.1 mycroft 1739: }
1.214 ad 1740: mutex_exit(&mntvnode_lock);
1.1 mycroft 1741: /*
1742: * Force stale file system control information to be flushed.
1743: */
1.132 hannken 1744: if (waitfor == MNT_WAIT && (ump->um_mountp->mnt_flag & MNT_SOFTDEP)) {
1.177 christos 1745: if ((error = softdep_flushworklist(ump->um_mountp, &count, l)))
1.132 hannken 1746: allerror = error;
1747: /* Flushed work items may create new vnodes to clean */
1748: if (allerror == 0 && count) {
1.214 ad 1749: mutex_enter(&mntvnode_lock);
1.132 hannken 1750: goto loop;
1751: }
1752: }
1753: if (waitfor != MNT_LAZY && (ump->um_devvp->v_numoutput > 0 ||
1754: !LIST_EMPTY(&ump->um_devvp->v_dirtyblkhd))) {
1.55 fvdl 1755: vn_lock(ump->um_devvp, LK_EXCLUSIVE | LK_RETRY);
1756: if ((error = VOP_FSYNC(ump->um_devvp, cred,
1.231 simonb 1757: (waitfor == MNT_WAIT ? FSYNC_WAIT : 0) | FSYNC_NOLOG,
1758: 0, 0)) != 0)
1.55 fvdl 1759: allerror = error;
1760: VOP_UNLOCK(ump->um_devvp, 0);
1.231 simonb 1761: if (allerror == 0 && waitfor == MNT_WAIT && !mp->mnt_wapbl) {
1.214 ad 1762: mutex_enter(&mntvnode_lock);
1.132 hannken 1763: goto loop;
1764: }
1.55 fvdl 1765: }
1.1 mycroft 1766: #ifdef QUOTA
1.118 fvdl 1767: qsync(mp);
1.1 mycroft 1768: #endif
1.33 fvdl 1769: /*
1770: * Write back modified superblock.
1771: */
1772: if (fs->fs_fmod != 0) {
1773: fs->fs_fmod = 0;
1.182 kardel 1774: fs->fs_time = time_second;
1.231 simonb 1775: error = UFS_WAPBL_BEGIN(mp);
1776: if (error)
1.64 mycroft 1777: allerror = error;
1.231 simonb 1778: else {
1779: if ((error = ffs_cgupdate(ump, waitfor)))
1780: allerror = error;
1.239 ! joerg 1781: UFS_WAPBL_END(mp);
1.231 simonb 1782: }
1.33 fvdl 1783: }
1.231 simonb 1784:
1785: #ifdef WAPBL
1786: if (mp->mnt_wapbl) {
1787: error = wapbl_flush(mp->mnt_wapbl, 0);
1788: if (error)
1789: allerror = error;
1790: }
1791: #endif
1792:
1.193 hannken 1793: fstrans_done(mp);
1.215 pooka 1794: vnfree(mvp);
1.1 mycroft 1795: return (allerror);
1796: }
1797:
1798: /*
1799: * Look up a FFS dinode number to find its incore vnode, otherwise read it
1800: * in from disk. If it is in core, wait for the lock bit to clear, then
1801: * return the inode locked. Detection and handling of mount points must be
1802: * done by the calling routine.
1803: */
1804: int
1.166 thorpej 1805: ffs_vget(struct mount *mp, ino_t ino, struct vnode **vpp)
1.1 mycroft 1806: {
1.33 fvdl 1807: struct fs *fs;
1808: struct inode *ip;
1.1 mycroft 1809: struct ufsmount *ump;
1810: struct buf *bp;
1811: struct vnode *vp;
1812: dev_t dev;
1.43 thorpej 1813: int error;
1.1 mycroft 1814:
1815: ump = VFSTOUFS(mp);
1816: dev = ump->um_dev;
1.68 fvdl 1817:
1.200 ad 1818: retry:
1.117 thorpej 1819: if ((*vpp = ufs_ihashget(dev, ino, LK_EXCLUSIVE)) != NULL)
1.68 fvdl 1820: return (0);
1.1 mycroft 1821:
1822: /* Allocate a new vnode/inode. */
1.19 christos 1823: if ((error = getnewvnode(VT_UFS, mp, ffs_vnodeop_p, &vp)) != 0) {
1.1 mycroft 1824: *vpp = NULL;
1825: return (error);
1826: }
1.216 ad 1827: ip = pool_cache_get(ffs_inode_cache, PR_WAITOK);
1.68 fvdl 1828:
1829: /*
1.200 ad 1830: * If someone beat us to it, put back the freshly allocated
1831: * vnode/inode pair and retry.
1.68 fvdl 1832: */
1.195 ad 1833: mutex_enter(&ufs_hashlock);
1.200 ad 1834: if (ufs_ihashget(dev, ino, 0) != NULL) {
1.195 ad 1835: mutex_exit(&ufs_hashlock);
1836: ungetnewvnode(vp);
1.216 ad 1837: pool_cache_put(ffs_inode_cache, ip);
1.200 ad 1838: goto retry;
1.195 ad 1839: }
1.68 fvdl 1840:
1.210 ad 1841: vp->v_vflag |= VV_LOCKSWORK;
1.217 ad 1842: if ((mp->mnt_flag & MNT_SOFTDEP) != 0)
1843: vp->v_uflag |= VU_SOFTDEP;
1.155 thorpej 1844:
1.43 thorpej 1845: /*
1846: * XXX MFS ends up here, too, to allocate an inode. Should we
1847: * XXX create another pool for MFS inodes?
1848: */
1.87 chs 1849:
1850: memset(ip, 0, sizeof(struct inode));
1.1 mycroft 1851: vp->v_data = ip;
1852: ip->i_vnode = vp;
1.110 fvdl 1853: ip->i_ump = ump;
1.1 mycroft 1854: ip->i_fs = fs = ump->um_fs;
1855: ip->i_dev = dev;
1856: ip->i_number = ino;
1.77 chs 1857: LIST_INIT(&ip->i_pcbufhd);
1.1 mycroft 1858: #ifdef QUOTA
1.203 hannken 1859: ufsquota_init(ip);
1.1 mycroft 1860: #endif
1.86 chs 1861:
1.1 mycroft 1862: /*
1.213 dyoung 1863: * Initialize genfs node, we might proceed to destroy it in
1864: * error branches.
1865: */
1866: genfs_node_init(vp, &ffs_genfsops);
1867:
1868: /*
1.1 mycroft 1869: * Put it onto its hash chain and lock it so that other requests for
1870: * this inode will block if they arrive while we are sleeping waiting
1871: * for old data structures to be purged or for the contents of the
1872: * disk portion of this inode to be read.
1873: */
1.87 chs 1874:
1.1 mycroft 1875: ufs_ihashins(ip);
1.195 ad 1876: mutex_exit(&ufs_hashlock);
1.1 mycroft 1877:
1878: /* Read in the disk contents for the inode, copy into the inode. */
1.19 christos 1879: error = bread(ump->um_devvp, fsbtodb(fs, ino_to_fsba(fs, ino)),
1.228 hannken 1880: (int)fs->fs_bsize, NOCRED, 0, &bp);
1.19 christos 1881: if (error) {
1.87 chs 1882:
1.1 mycroft 1883: /*
1884: * The inode does not contain anything useful, so it would
1885: * be misleading to leave it on its hash chain. With mode
1886: * still zero, it will be unlinked and returned to the free
1887: * list by vput().
1888: */
1.87 chs 1889:
1.1 mycroft 1890: vput(vp);
1.209 ad 1891: brelse(bp, 0);
1.1 mycroft 1892: *vpp = NULL;
1893: return (error);
1894: }
1.110 fvdl 1895: if (ip->i_ump->um_fstype == UFS1)
1.216 ad 1896: ip->i_din.ffs1_din = pool_cache_get(ffs_dinode1_cache,
1897: PR_WAITOK);
1.110 fvdl 1898: else
1.216 ad 1899: ip->i_din.ffs2_din = pool_cache_get(ffs_dinode2_cache,
1900: PR_WAITOK);
1.110 fvdl 1901: ffs_load_inode(bp, ip, fs, ino);
1.55 fvdl 1902: if (DOINGSOFTDEP(vp))
1903: softdep_load_inodeblock(ip);
1904: else
1.110 fvdl 1905: ip->i_ffs_effnlink = ip->i_nlink;
1.209 ad 1906: brelse(bp, 0);
1.1 mycroft 1907:
1908: /*
1909: * Initialize the vnode from the inode, check for aliases.
1910: * Note that the underlying vnode may have changed.
1911: */
1.87 chs 1912:
1913: ufs_vinit(mp, ffs_specop_p, ffs_fifoop_p, &vp);
1914:
1.1 mycroft 1915: /*
1916: * Finish inode initialization now that aliasing has been resolved.
1917: */
1.87 chs 1918:
1.1 mycroft 1919: ip->i_devvp = ump->um_devvp;
1920: VREF(ip->i_devvp);
1.87 chs 1921:
1.1 mycroft 1922: /*
1923: * Ensure that uid and gid are correct. This is a temporary
1924: * fix until fsck has been changed to do the update.
1925: */
1.87 chs 1926:
1.110 fvdl 1927: if (fs->fs_old_inodefmt < FS_44INODEFMT) { /* XXX */
1928: ip->i_uid = ip->i_ffs1_ouid; /* XXX */
1929: ip->i_gid = ip->i_ffs1_ogid; /* XXX */
1.38 kleink 1930: } /* XXX */
1.110 fvdl 1931: uvm_vnp_setsize(vp, ip->i_size);
1.1 mycroft 1932: *vpp = vp;
1933: return (0);
1934: }
1935:
1936: /*
1937: * File handle to vnode
1938: *
1939: * Have to be really careful about stale file handles:
1940: * - check that the inode number is valid
1941: * - call ffs_vget() to get the locked inode
1942: * - check for an unallocated inode (i_mode == 0)
1943: * - check that the given client host has export rights and return
1944: * those rights via. exflagsp and credanonp
1945: */
1946: int
1.166 thorpej 1947: ffs_fhtovp(struct mount *mp, struct fid *fhp, struct vnode **vpp)
1.1 mycroft 1948: {
1.183 martin 1949: struct ufid ufh;
1.1 mycroft 1950: struct fs *fs;
1951:
1.183 martin 1952: if (fhp->fid_len != sizeof(struct ufid))
1953: return EINVAL;
1954:
1955: memcpy(&ufh, fhp, sizeof(ufh));
1.1 mycroft 1956: fs = VFSTOUFS(mp)->um_fs;
1.183 martin 1957: if (ufh.ufid_ino < ROOTINO ||
1958: ufh.ufid_ino >= fs->fs_ncg * fs->fs_ipg)
1.1 mycroft 1959: return (ESTALE);
1.183 martin 1960: return (ufs_fhtovp(mp, &ufh, vpp));
1.1 mycroft 1961: }
1962:
1963: /*
1964: * Vnode pointer to File handle
1965: */
1966: /* ARGSUSED */
1.19 christos 1967: int
1.183 martin 1968: ffs_vptofh(struct vnode *vp, struct fid *fhp, size_t *fh_size)
1.1 mycroft 1969: {
1.61 augustss 1970: struct inode *ip;
1.183 martin 1971: struct ufid ufh;
1.1 mycroft 1972:
1.183 martin 1973: if (*fh_size < sizeof(struct ufid)) {
1974: *fh_size = sizeof(struct ufid);
1975: return E2BIG;
1976: }
1.1 mycroft 1977: ip = VTOI(vp);
1.183 martin 1978: *fh_size = sizeof(struct ufid);
1979: memset(&ufh, 0, sizeof(ufh));
1980: ufh.ufid_len = sizeof(struct ufid);
1981: ufh.ufid_ino = ip->i_number;
1982: ufh.ufid_gen = ip->i_gen;
1983: memcpy(fhp, &ufh, sizeof(ufh));
1.1 mycroft 1984: return (0);
1.33 fvdl 1985: }
1986:
1987: void
1.166 thorpej 1988: ffs_init(void)
1.33 fvdl 1989: {
1.59 jdolecek 1990: if (ffs_initcount++ > 0)
1991: return;
1992:
1.216 ad 1993: ffs_inode_cache = pool_cache_init(sizeof(struct inode), 0, 0, 0,
1994: "ffsino", NULL, IPL_NONE, NULL, NULL, NULL);
1995: ffs_dinode1_cache = pool_cache_init(sizeof(struct ufs1_dinode), 0, 0, 0,
1996: "ffsdino1", NULL, IPL_NONE, NULL, NULL, NULL);
1997: ffs_dinode2_cache = pool_cache_init(sizeof(struct ufs2_dinode), 0, 0, 0,
1998: "ffsdino2", NULL, IPL_NONE, NULL, NULL, NULL);
1.55 fvdl 1999: softdep_initialize();
1.33 fvdl 2000: ufs_init();
1.86 chs 2001: }
2002:
2003: void
1.166 thorpej 2004: ffs_reinit(void)
1.86 chs 2005: {
2006: softdep_reinitialize();
2007: ufs_reinit();
1.59 jdolecek 2008: }
2009:
2010: void
1.166 thorpej 2011: ffs_done(void)
1.59 jdolecek 2012: {
2013: if (--ffs_initcount > 0)
2014: return;
2015:
2016: /* XXX softdep cleanup ? */
2017: ufs_done();
1.216 ad 2018: pool_cache_destroy(ffs_dinode2_cache);
2019: pool_cache_destroy(ffs_dinode1_cache);
2020: pool_cache_destroy(ffs_inode_cache);
1.33 fvdl 2021: }
2022:
1.1 mycroft 2023: /*
2024: * Write a superblock and associated information back to disk.
2025: */
2026: int
1.166 thorpej 2027: ffs_sbupdate(struct ufsmount *mp, int waitfor)
1.1 mycroft 2028: {
1.61 augustss 2029: struct fs *fs = mp->um_fs;
2030: struct buf *bp;
1.110 fvdl 2031: int error = 0;
2032: u_int32_t saveflag;
1.34 bouyer 2033:
1.229 hannken 2034: error = ffs_getblk(mp->um_devvp,
2035: fs->fs_sblockloc >> (fs->fs_fshift - fs->fs_fsbtodb), FFS_NOBLK,
2036: fs->fs_sbsize, false, &bp);
2037: if (error)
2038: return error;
1.55 fvdl 2039: saveflag = fs->fs_flags & FS_INTERNAL;
2040: fs->fs_flags &= ~FS_INTERNAL;
1.161 perry 2041:
1.42 perry 2042: memcpy(bp->b_data, fs, fs->fs_sbsize);
1.110 fvdl 2043:
2044: ffs_oldfscompat_write((struct fs *)bp->b_data, mp);
1.34 bouyer 2045: #ifdef FFS_EI
2046: if (mp->um_flags & UFS_NEEDSWAP)
1.123 enami 2047: ffs_sb_swap((struct fs *)bp->b_data, (struct fs *)bp->b_data);
1.111 fvdl 2048: #endif
1.55 fvdl 2049: fs->fs_flags |= saveflag;
1.34 bouyer 2050:
1.1 mycroft 2051: if (waitfor == MNT_WAIT)
2052: error = bwrite(bp);
2053: else
2054: bawrite(bp);
1.15 mycroft 2055: return (error);
2056: }
2057:
2058: int
1.166 thorpej 2059: ffs_cgupdate(struct ufsmount *mp, int waitfor)
1.15 mycroft 2060: {
1.61 augustss 2061: struct fs *fs = mp->um_fs;
2062: struct buf *bp;
1.15 mycroft 2063: int blks;
1.84 lukem 2064: void *space;
1.15 mycroft 2065: int i, size, error = 0, allerror = 0;
2066:
2067: allerror = ffs_sbupdate(mp, waitfor);
1.1 mycroft 2068: blks = howmany(fs->fs_cssize, fs->fs_fsize);
1.84 lukem 2069: space = fs->fs_csp;
1.1 mycroft 2070: for (i = 0; i < blks; i += fs->fs_frag) {
2071: size = fs->fs_bsize;
2072: if (i + fs->fs_frag > blks)
2073: size = (blks - i) * fs->fs_fsize;
1.229 hannken 2074: error = ffs_getblk(mp->um_devvp, fsbtodb(fs, fs->fs_csaddr + i),
2075: FFS_NOBLK, size, false, &bp);
2076: if (error)
2077: break;
1.34 bouyer 2078: #ifdef FFS_EI
2079: if (mp->um_flags & UFS_NEEDSWAP)
2080: ffs_csum_swap((struct csum*)space,
1.38 kleink 2081: (struct csum*)bp->b_data, size);
1.34 bouyer 2082: else
2083: #endif
1.42 perry 2084: memcpy(bp->b_data, space, (u_int)size);
1.84 lukem 2085: space = (char *)space + size;
1.1 mycroft 2086: if (waitfor == MNT_WAIT)
2087: error = bwrite(bp);
2088: else
2089: bawrite(bp);
2090: }
1.15 mycroft 2091: if (!allerror && error)
2092: allerror = error;
2093: return (allerror);
1.1 mycroft 2094: }
1.170 thorpej 2095:
2096: int
2097: ffs_extattrctl(struct mount *mp, int cmd, struct vnode *vp,
1.211 pooka 2098: int attrnamespace, const char *attrname)
1.170 thorpej 2099: {
2100: #ifdef UFS_EXTATTR
2101: /*
2102: * File-backed extended attributes are only supported on UFS1.
2103: * UFS2 has native extended attributes.
2104: */
2105: if (VFSTOUFS(mp)->um_fstype == UFS1)
1.211 pooka 2106: return (ufs_extattrctl(mp, cmd, vp, attrnamespace, attrname));
1.170 thorpej 2107: #endif
1.211 pooka 2108: return (vfs_stdextattrctl(mp, cmd, vp, attrnamespace, attrname));
1.170 thorpej 2109: }
1.193 hannken 2110:
2111: int
2112: ffs_suspendctl(struct mount *mp, int cmd)
2113: {
2114: int error;
2115: struct lwp *l = curlwp;
2116:
2117: switch (cmd) {
2118: case SUSPEND_SUSPEND:
1.194 hannken 2119: if ((error = fstrans_setstate(mp, FSTRANS_SUSPENDING)) != 0)
1.193 hannken 2120: return error;
1.211 pooka 2121: error = ffs_sync(mp, MNT_WAIT, l->l_proc->p_cred);
1.193 hannken 2122: if (error == 0)
1.194 hannken 2123: error = fstrans_setstate(mp, FSTRANS_SUSPENDED);
1.233 hannken 2124: #ifdef WAPBL
2125: if (error == 0 && mp->mnt_wapbl)
2126: error = wapbl_flush(mp->mnt_wapbl, 1);
2127: #endif
1.193 hannken 2128: if (error != 0) {
1.194 hannken 2129: (void) fstrans_setstate(mp, FSTRANS_NORMAL);
1.193 hannken 2130: return error;
2131: }
2132: return 0;
2133:
2134: case SUSPEND_RESUME:
1.194 hannken 2135: return fstrans_setstate(mp, FSTRANS_NORMAL);
1.193 hannken 2136:
2137: default:
2138: return EINVAL;
2139: }
2140: }
CVSweb <webmaster@jp.NetBSD.org>