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