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