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