|
|
1.1 root 1: /*
2: * Copyright (c) 1999 Apple Computer, Inc. All rights reserved.
3: *
4: * @APPLE_LICENSE_HEADER_START@
5: *
6: * Portions Copyright (c) 1999 Apple Computer, Inc. All Rights
7: * Reserved. This file contains Original Code and/or Modifications of
8: * Original Code as defined in and that are subject to the Apple Public
9: * Source License Version 1.1 (the "License"). You may not use this file
10: * except in compliance with the License. Please obtain a copy of the
11: * License at http://www.apple.com/publicsource and read it before using
12: * this file.
13: *
14: * The Original Code and all software distributed under the License are
15: * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER
16: * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
17: * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
18: * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the
19: * License for the specific language governing rights and limitations
20: * under the License.
21: *
22: * @APPLE_LICENSE_HEADER_END@
23: */
24:
25: /* Copyright (c) 1995 NeXT Computer, Inc. All Rights Reserved */
26: /*
27: * Copyright (c) 1989, 1991, 1993, 1994
28: * The Regents of the University of California. All rights reserved.
29: *
30: * Redistribution and use in source and binary forms, with or without
31: * modification, are permitted provided that the following conditions
32: * are met:
33: * 1. Redistributions of source code must retain the above copyright
34: * notice, this list of conditions and the following disclaimer.
35: * 2. Redistributions in binary form must reproduce the above copyright
36: * notice, this list of conditions and the following disclaimer in the
37: * documentation and/or other materials provided with the distribution.
38: * 3. All advertising materials mentioning features or use of this software
39: * must display the following acknowledgement:
40: * This product includes software developed by the University of
41: * California, Berkeley and its contributors.
42: * 4. Neither the name of the University nor the names of its contributors
43: * may be used to endorse or promote products derived from this software
44: * without specific prior written permission.
45: *
46: * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
47: * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
48: * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
49: * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
50: * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
51: * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
52: * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
53: * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
54: * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
55: * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
56: * SUCH DAMAGE.
57: *
58: * @(#)ffs_vfsops.c 8.31 (Berkeley) 5/20/95
59: */
60:
61: #include <rev_endian_fs.h>
62: #include <mach_nbc.h>
63: #include <sys/param.h>
64: #include <sys/systm.h>
65: #include <sys/namei.h>
66: #include <sys/proc.h>
67: #include <sys/kernel.h>
68: #include <sys/vnode.h>
69: #include <sys/socket.h>
70: #include <sys/mount.h>
71: #include <sys/buf.h>
72: #include <sys/mbuf.h>
73: #include <sys/file.h>
74: #ifdef NeXT
75: #include <bsd/dev/disk.h>
76: #else
77: #include <sys/disklabel.h>
78: #endif
79: #include <sys/ioctl.h>
80: #include <sys/errno.h>
81: #include <sys/malloc.h>
82:
83: #include <miscfs/specfs/specdev.h>
84:
85: #include <ufs/ufs/quota.h>
86: #include <ufs/ufs/ufsmount.h>
87: #include <ufs/ufs/inode.h>
88: #include <ufs/ufs/ufs_extern.h>
89:
90: #include <ufs/ffs/fs.h>
91: #include <ufs/ffs/ffs_extern.h>
92: #if REV_ENDIAN_FS
93: #include <ufs/ufs/ufs_byte_order.h>
94: #include <architecture/byte_order.h>
95: #endif /* REV_ENDIAN_FS */
96:
97: int ffs_sbupdate __P((struct ufsmount *, int));
98:
99: struct vfsops ufs_vfsops = {
100: ffs_mount,
101: ufs_start,
102: ffs_unmount,
103: ufs_root,
104: ufs_quotactl,
105: ffs_statfs,
106: ffs_sync,
107: ffs_vget,
108: ffs_fhtovp,
109: ffs_vptofh,
110: ffs_init,
111: ffs_sysctl,
112: };
113:
114: extern u_long nextgennumber;
115:
116: /*
117: * Called by main() when ufs is going to be mounted as root.
118: */
119: ffs_mountroot()
120: {
121: extern struct vnode *rootvp;
122: struct fs *fs;
123: struct mount *mp;
124: struct proc *p = current_proc(); /* XXX */
125: struct ufsmount *ump;
126: u_int size;
127: int error;
128:
129: /*
130: * Get vnode for rootdev.
131: */
132: if (error = bdevvp(rootdev, &rootvp)) {
133: printf("ffs_mountroot: can't setup bdevvp");
134: return (error);
135: }
136: if (error = vfs_rootmountalloc("ufs", "root_device", &mp))
137: return (error);
138: if (error = ffs_mountfs(rootvp, mp, p)) {
139: mp->mnt_vfc->vfc_refcount--;
140: vfs_unbusy(mp, p);
141: _FREE_ZONE(mp, sizeof (struct mount), M_MOUNT);
142: return (error);
143: }
144: simple_lock(&mountlist_slock);
145: CIRCLEQ_INSERT_TAIL(&mountlist, mp, mnt_list);
146: simple_unlock(&mountlist_slock);
147: ump = VFSTOUFS(mp);
148: fs = ump->um_fs;
149: (void) copystr(mp->mnt_stat.f_mntonname, fs->fs_fsmnt, MNAMELEN - 1, 0);
150: (void)ffs_statfs(mp, &mp->mnt_stat, p);
151: vfs_unbusy(mp, p);
152: inittodr(fs->fs_time);
153: return (0);
154: }
155:
156: /*
157: * VFS Operations.
158: *
159: * mount system call
160: */
161: int
162: ffs_mount(mp, path, data, ndp, p)
163: register struct mount *mp;
164: char *path;
165: caddr_t data;
166: struct nameidata *ndp;
167: struct proc *p;
168: {
169: struct vnode *devvp;
170: struct ufs_args args;
171: struct ufsmount *ump;
172: register struct fs *fs;
173: u_int size;
174: int error, flags;
175: mode_t accessmode;
176:
177: if (error = copyin(data, (caddr_t)&args, sizeof (struct ufs_args)))
178: return (error);
179: /*
180: * If updating, check whether changing from read-only to
181: * read/write; if there is no device name, that's all we do.
182: */
183: if (mp->mnt_flag & MNT_UPDATE) {
184: ump = VFSTOUFS(mp);
185: fs = ump->um_fs;
186: if (fs->fs_ronly == 0 && (mp->mnt_flag & MNT_RDONLY)) {
187: flags = WRITECLOSE;
188: if (mp->mnt_flag & MNT_FORCE)
189: flags |= FORCECLOSE;
190: if (error = ffs_flushfiles(mp, flags, p))
191: return (error);
192: fs->fs_clean = 1;
193: fs->fs_ronly = 1;
194: if (error = ffs_sbupdate(ump, MNT_WAIT)) {
195: fs->fs_clean = 0;
196: fs->fs_ronly = 0;
197: return (error);
198: }
199: }
200: if ((mp->mnt_flag & MNT_RELOAD) &&
201: (error = ffs_reload(mp, ndp->ni_cnd.cn_cred, p)))
202: return (error);
203: if (fs->fs_ronly && (mp->mnt_flag & MNT_WANTRDWR)) {
204: /*
205: * If upgrade to read-write by non-root, then verify
206: * that user has necessary permissions on the device.
207: */
208: if (p->p_ucred->cr_uid != 0) {
209: devvp = ump->um_devvp;
210: vn_lock(devvp, LK_EXCLUSIVE | LK_RETRY, p);
211: if (error = VOP_ACCESS(devvp, VREAD | VWRITE,
212: p->p_ucred, p)) {
213: VOP_UNLOCK(devvp, 0, p);
214: return (error);
215: }
216: VOP_UNLOCK(devvp, 0, p);
217: }
218: fs->fs_ronly = 0;
219: fs->fs_clean = 0;
220: (void) ffs_sbupdate(ump, MNT_WAIT);
221: }
222: if (args.fspec == 0) {
223: /*
224: * Process export requests.
225: */
226: return (vfs_export(mp, &ump->um_export, &args.export));
227: }
228: }
229: /*
230: * Not an update, or updating the name: look up the name
231: * and verify that it refers to a sensible block device.
232: */
233: NDINIT(ndp, LOOKUP, FOLLOW, UIO_USERSPACE, args.fspec, p);
234: if (error = namei(ndp))
235: return (error);
236: devvp = ndp->ni_vp;
237:
238: if (devvp->v_type != VBLK) {
239: vrele(devvp);
240: return (ENOTBLK);
241: }
242: if (major(devvp->v_rdev) >= nblkdev) {
243: vrele(devvp);
244: return (ENXIO);
245: }
246: /*
247: * If mount by non-root, then verify that user has necessary
248: * permissions on the device.
249: */
250: if (p->p_ucred->cr_uid != 0) {
251: accessmode = VREAD;
252: if ((mp->mnt_flag & MNT_RDONLY) == 0)
253: accessmode |= VWRITE;
254: vn_lock(devvp, LK_EXCLUSIVE | LK_RETRY, p);
255: if (error = VOP_ACCESS(devvp, accessmode, p->p_ucred, p)) {
256: vput(devvp);
257: return (error);
258: }
259: VOP_UNLOCK(devvp, 0, p);
260: }
261: if ((mp->mnt_flag & MNT_UPDATE) == 0)
262: error = ffs_mountfs(devvp, mp, p);
263: else {
264: if (devvp != ump->um_devvp)
265: error = EINVAL; /* needs translation */
266: else
267: vrele(devvp);
268: }
269: if (error) {
270: vrele(devvp);
271: return (error);
272: }
273: ump = VFSTOUFS(mp);
274: fs = ump->um_fs;
275: (void) copyinstr(path, fs->fs_fsmnt, sizeof(fs->fs_fsmnt) - 1, &size);
276: bzero(fs->fs_fsmnt + size, sizeof(fs->fs_fsmnt) - size);
277: bcopy((caddr_t)fs->fs_fsmnt, (caddr_t)mp->mnt_stat.f_mntonname,
278: MNAMELEN);
279: (void) copyinstr(args.fspec, mp->mnt_stat.f_mntfromname, MNAMELEN - 1,
280: &size);
281: bzero(mp->mnt_stat.f_mntfromname + size, MNAMELEN - size);
282: (void)ffs_statfs(mp, &mp->mnt_stat, p);
283: return (0);
284: }
285:
286: /*
287: * Reload all incore data for a filesystem (used after running fsck on
288: * the root filesystem and finding things to fix). The filesystem must
289: * be mounted read-only.
290: *
291: * Things to do to update the mount:
292: * 1) invalidate all cached meta-data.
293: * 2) re-read superblock from disk.
294: * 3) re-read summary information from disk.
295: * 4) invalidate all inactive vnodes.
296: * 5) invalidate all cached file data.
297: * 6) re-read inode data for all active vnodes.
298: */
299: ffs_reload(mountp, cred, p)
300: register struct mount *mountp;
301: struct ucred *cred;
302: struct proc *p;
303: {
304: register struct vnode *vp, *nvp, *devvp;
305: struct inode *ip;
306: struct csum *space;
307: struct buf *bp;
308: struct fs *fs, *newfs;
309: #ifndef NeXT
310: struct partinfo dpart;
311: #endif /* NeXT */
312: int i, blks, size, error;
313: int32_t *lp;
314: #if REV_ENDIAN_FS
315: int rev_endian = (mountp->mnt_flag & MNT_REVEND);
316: #endif /* REV_ENDIAN_FS */
317:
318: if ((mountp->mnt_flag & MNT_RDONLY) == 0)
319: return (EINVAL);
320: /*
321: * Step 1: invalidate all cached meta-data.
322: */
323: devvp = VFSTOUFS(mountp)->um_devvp;
324: if (vinvalbuf(devvp, 0, cred, p, 0, 0))
325: panic("ffs_reload: dirty1");
326: /*
327: * Step 2: re-read superblock from disk.
328: */
329: #ifdef NeXT
330: VOP_DEVBLOCKSIZE(devvp,&size);
331: #else
332: if (VOP_IOCTL(devvp, DIOCGPART, (caddr_t)&dpart, FREAD, NOCRED, p) != 0)
333: size = DEV_BSIZE;
334: else
335: size = dpart.disklab->d_secsize;
336: #endif
337: if (error = bread(devvp, (ufs_daddr_t)(SBOFF/size), SBSIZE, NOCRED,&bp))
338: return (error);
339: newfs = (struct fs *)bp->b_data;
340: #if REV_ENDIAN_FS
341: if (rev_endian) {
342: byte_swap_sbin(newfs);
343: }
344: #endif /* REV_ENDIAN_FS */
345: if (newfs->fs_magic != FS_MAGIC || newfs->fs_bsize > MAXBSIZE ||
346: newfs->fs_bsize < sizeof(struct fs)) {
347: #if REV_ENDIAN_FS
348: if (rev_endian)
349: byte_swap_sbout(newfs);
350: #endif /* REV_ENDIAN_FS */
351:
352: brelse(bp);
353: return (EIO); /* XXX needs translation */
354: }
355: fs = VFSTOUFS(mountp)->um_fs;
356: /*
357: * Copy pointer fields back into superblock before copying in XXX
358: * new superblock. These should really be in the ufsmount. XXX
359: * Note that important parameters (eg fs_ncg) are unchanged.
360: */
361: bcopy(&fs->fs_csp[0], &newfs->fs_csp[0], sizeof(fs->fs_csp));
362: newfs->fs_maxcluster = fs->fs_maxcluster;
363: bcopy(newfs, fs, (u_int)fs->fs_sbsize);
364: if (fs->fs_sbsize < SBSIZE)
365: bp->b_flags |= B_INVAL;
366: #if REV_ENDIAN_FS
367: if (rev_endian)
368: byte_swap_sbout(newfs);
369: #endif /* REV_ENDIAN_FS */
370: brelse(bp);
371: mountp->mnt_maxsymlinklen = fs->fs_maxsymlinklen;
372: ffs_oldfscompat(fs);
373: /*
374: * Step 3: re-read summary information from disk.
375: */
376: blks = howmany(fs->fs_cssize, fs->fs_fsize);
377: space = fs->fs_csp[0];
378: for (i = 0; i < blks; i += fs->fs_frag) {
379: size = fs->fs_bsize;
380: if (i + fs->fs_frag > blks)
381: size = (blks - i) * fs->fs_fsize;
382: if (error = bread(devvp, fsbtodb(fs, fs->fs_csaddr + i), size,
383: NOCRED, &bp))
384: return (error);
385: #if REV_ENDIAN_FS
386: if (rev_endian) {
387: /* csum swaps */
388: byte_swap_ints((int *)bp->b_data, size / sizeof(int));
389: }
390: #endif /* REV_ENDIAN_FS */
391: bcopy(bp->b_data, fs->fs_csp[fragstoblks(fs, i)], (u_int)size);
392: #if REV_ENDIAN_FS
393: if (rev_endian) {
394: /* csum swaps */
395: byte_swap_ints((int *)bp->b_data, size / sizeof(int));
396: }
397: #endif /* REV_ENDIAN_FS */
398: brelse(bp);
399: }
400: /*
401: * We no longer know anything about clusters per cylinder group.
402: */
403: if (fs->fs_contigsumsize > 0) {
404: lp = fs->fs_maxcluster;
405: for (i = 0; i < fs->fs_ncg; i++)
406: *lp++ = fs->fs_contigsumsize;
407: }
408:
409: loop:
410: simple_lock(&mntvnode_slock);
411: for (vp = mountp->mnt_vnodelist.lh_first; vp != NULL; vp = nvp) {
412: if (vp->v_mount != mountp) {
413: simple_unlock(&mntvnode_slock);
414: goto loop;
415: }
416: nvp = vp->v_mntvnodes.le_next;
417: /*
418: * Step 4: invalidate all inactive vnodes.
419: */
420: if (vrecycle(vp, &mntvnode_slock, p))
421: goto loop;
422: /*
423: * Step 5: invalidate all cached file data.
424: */
425: simple_lock(&vp->v_interlock);
426: simple_unlock(&mntvnode_slock);
427: if (vget(vp, LK_EXCLUSIVE | LK_INTERLOCK, p)) {
428: goto loop;
429: }
430: if (vinvalbuf(vp, 0, cred, p, 0, 0))
431: panic("ffs_reload: dirty2");
432: /*
433: * Step 6: re-read inode data for all active vnodes.
434: */
435: ip = VTOI(vp);
436: if (error =
437: bread(devvp, fsbtodb(fs, ino_to_fsba(fs, ip->i_number)),
438: (int)fs->fs_bsize, NOCRED, &bp)) {
439: vput(vp);
440: return (error);
441: }
442: #if REV_ENDIAN_FS
443: if (rev_endian) {
444: byte_swap_inode_in(((struct dinode *)bp->b_data +
445: ino_to_fsbo(fs, ip->i_number)), ip);
446: } else {
447: #endif /* REV_ENDIAN_FS */
448: ip->i_din = *((struct dinode *)bp->b_data +
449: ino_to_fsbo(fs, ip->i_number));
450: #if REV_ENDIAN_FS
451: }
452: #endif /* REV_ENDIAN_FS */
453: brelse(bp);
454: vput(vp);
455: simple_lock(&mntvnode_slock);
456: }
457: simple_unlock(&mntvnode_slock);
458: return (0);
459: }
460:
461: /*
462: * Common code for mount and mountroot
463: */
464: int
465: ffs_mountfs(devvp, mp, p)
466: register struct vnode *devvp;
467: struct mount *mp;
468: struct proc *p;
469: {
470: register struct ufsmount *ump;
471: struct buf *bp;
472: register struct fs *fs;
473: dev_t dev;
474: #ifdef NeXT
475: struct buf *cgbp;
476: struct cg *cgp;
477: int32_t clustersumoff;
478: #else
479: struct partinfo dpart;
480: #endif /* NeXT */
481: caddr_t base, space;
482: int error, i, blks, size, ronly;
483: int32_t *lp;
484: struct ucred *cred;
485: extern struct vnode *rootvp;
486: u_int64_t maxfilesize; /* XXX */
487: #if REV_ENDIAN_FS
488: int rev_endian=0;
489: #endif /* REV_ENDIAN_FS */
490: dev = devvp->v_rdev;
491: cred = p ? p->p_ucred : NOCRED;
492: /*
493: * Disallow multiple mounts of the same device.
494: * Disallow mounting of a device that is currently in use
495: * (except for root, which might share swap device for miniroot).
496: * Flush out any old buffers remaining from a previous use.
497: */
498: if (error = vfs_mountedon(devvp))
499: return (error);
500: if (vcount(devvp) > 1 && devvp != rootvp)
501: return (EBUSY);
502: if (error = vinvalbuf(devvp, V_SAVE, cred, p, 0, 0))
503: return (error);
504:
505: ronly = (mp->mnt_flag & MNT_RDONLY) != 0;
506: if (error = VOP_OPEN(devvp, ronly ? FREAD : FREAD|FWRITE, FSCRED, p))
507: return (error);
508: #ifdef NeXT
509: VOP_DEVBLOCKSIZE(devvp,&size);
510: #else
511: if (VOP_IOCTL(devvp, DIOCGPART, (caddr_t)&dpart, FREAD, NOCRED, p) != 0)
512: size = DEV_BSIZE;
513: else
514: size = dpart.disklab->d_secsize;
515: #endif
516:
517: bp = NULL;
518: ump = NULL;
519: if (error = bread(devvp, (ufs_daddr_t)(SBOFF/size), SBSIZE, cred, &bp))
520: goto out;
521: fs = (struct fs *)bp->b_data;
522: #if REV_ENDIAN_FS
523: if (fs->fs_magic != FS_MAGIC || fs->fs_bsize > MAXBSIZE ||
524: fs->fs_bsize < sizeof(struct fs)) {
525: byte_swap_sbin(fs);
526: if (fs->fs_magic != FS_MAGIC || fs->fs_bsize > MAXBSIZE ||
527: fs->fs_bsize < sizeof(struct fs)) {
528: byte_swap_sbout(fs);
529: error = EINVAL; /* XXX needs translation */
530: goto out;
531: }
532: rev_endian=1;
533: }
534: #endif /* REV_ENDIAN_FS */
535: if (fs->fs_magic != FS_MAGIC || fs->fs_bsize > MAXBSIZE ||
536: fs->fs_bsize < sizeof(struct fs)) {
537: #if REV_ENDIAN_FS
538: if (rev_endian)
539: byte_swap_sbout(fs);
540: #endif /* REV_ENDIAN_FS */
541: error = EINVAL; /* XXX needs translation */
542: goto out;
543: }
544: /* XXX updating 4.2 FFS superblocks trashes rotational layout tables */
545: if (fs->fs_postblformat == FS_42POSTBLFMT && !ronly) {
546: #if REV_ENDIAN_FS
547: if (rev_endian)
548: byte_swap_sbout(fs);
549: #endif /* REV_ENDIAN_FS */
550: error = EROFS; /* needs translation */
551: goto out;
552: }
553:
554: #ifdef NeXT
555: /* If we are not mounting read only, then check for overlap
556: * condition in cylinder group's free block map.
557: * If overlap exists, then force this into a read only mount
558: * to avoid further corruption. PR#2216969
559: */
560: if (ronly == 0){
561: if (error = bread (devvp, fsbtodb(fs, cgtod(fs, 0)),
562: (int)fs->fs_cgsize, NOCRED, &cgbp)) {
563: brelse(cgbp);
564: goto out;
565: }
566: cgp = (struct cg *)cgbp->b_data;
567: #if REV_ENDIAN_FS
568: if (rev_endian)
569: byte_swap_cgin(cgp,fs);
570: #endif /* REV_ENDIAN_FS */
571: if (!cg_chkmagic(cgp)){
572: #if REV_ENDIAN_FS
573: if (rev_endian)
574: byte_swap_cgout(cgp,fs);
575: #endif /* REV_ENDIAN_FS */
576: brelse(cgbp);
577: goto out;
578: }
579: if (cgp->cg_clustersumoff != 0) {
580: /* Check for overlap */
581: clustersumoff = cgp->cg_freeoff +
582: howmany(fs->fs_cpg * fs->fs_spc / NSPF(fs), NBBY);
583: clustersumoff = roundup(clustersumoff, sizeof(long));
584: if (cgp->cg_clustersumoff < clustersumoff) {
585: /* Overlap exists */
586: mp->mnt_flag |= MNT_RDONLY;
587: ronly = 1;
588: }
589: }
590: #if REV_ENDIAN_FS
591: if (rev_endian)
592: byte_swap_cgout(cgp,fs);
593: #endif /* REV_ENDIAN_FS */
594: brelse(cgbp);
595: }
596: #endif /* NeXT */
597:
598: ump = _MALLOC(sizeof *ump, M_UFSMNT, M_WAITOK);
599: bzero((caddr_t)ump, sizeof *ump);
600: ump->um_fs = _MALLOC((u_long)fs->fs_sbsize, M_UFSMNT,
601: M_WAITOK);
602: bcopy(bp->b_data, ump->um_fs, (u_int)fs->fs_sbsize);
603: if (fs->fs_sbsize < SBSIZE)
604: bp->b_flags |= B_INVAL;
605: #if REV_ENDIAN_FS
606: if (rev_endian)
607: byte_swap_sbout(fs);
608: #endif /* REV_ENDIAN_FS */
609: brelse(bp);
610: bp = NULL;
611: fs = ump->um_fs;
612: fs->fs_ronly = ronly;
613: size = fs->fs_cssize;
614: blks = howmany(size, fs->fs_fsize);
615: if (fs->fs_contigsumsize > 0)
616: size += fs->fs_ncg * sizeof(int32_t);
617: base = space = _MALLOC((u_long)size, M_UFSMNT, M_WAITOK);
618: base = space;
619: for (i = 0; i < blks; i += fs->fs_frag) {
620: size = fs->fs_bsize;
621: if (i + fs->fs_frag > blks)
622: size = (blks - i) * fs->fs_fsize;
623: if (error = bread(devvp, fsbtodb(fs, fs->fs_csaddr + i), size,
624: cred, &bp)) {
625: _FREE(base, M_UFSMNT);
626: goto out;
627: }
628: bcopy(bp->b_data, space, (u_int)size);
629: #if REV_ENDIAN_FS
630: if (rev_endian)
631: byte_swap_ints((int *) space, size / sizeof(int));
632: #endif /* REV_ENDIAN_FS */
633: fs->fs_csp[fragstoblks(fs, i)] = (struct csum *)space;
634: space += size;
635: brelse(bp);
636: bp = NULL;
637: }
638: if (fs->fs_contigsumsize > 0) {
639: fs->fs_maxcluster = lp = (int32_t *)space;
640: for (i = 0; i < fs->fs_ncg; i++)
641: *lp++ = fs->fs_contigsumsize;
642: }
643: mp->mnt_data = (qaddr_t)ump;
644: mp->mnt_stat.f_fsid.val[0] = (long)dev;
645: mp->mnt_stat.f_fsid.val[1] = mp->mnt_vfc->vfc_typenum;
646: #ifdef NeXT
647: #warning hardcoded max symlen
648: mp->mnt_maxsymlinklen = 60;
649: #else
650: mp->mnt_maxsymlinklen = fs->fs_maxsymlinklen;
651: #endif
652: #if REV_ENDIAN_FS
653: if (rev_endian)
654: mp->mnt_flag |= MNT_REVEND;
655: #endif /* REV_ENDIAN_FS */
656: ump->um_mountp = mp;
657: ump->um_dev = dev;
658: ump->um_devvp = devvp;
659: ump->um_nindir = fs->fs_nindir;
660: ump->um_bptrtodb = fs->fs_fsbtodb;
661: ump->um_seqinc = fs->fs_frag;
662: for (i = 0; i < MAXQUOTAS; i++)
663: ump->um_quotas[i] = NULLVP;
664: devvp->v_specflags |= SI_MOUNTEDON;
665: ffs_oldfscompat(fs);
666: ump->um_savedmaxfilesize = fs->fs_maxfilesize; /* XXX */
667: #ifdef NeXT
668: maxfilesize = (u_int64_t)0x100000000; /*4giga */
669: #else
670: maxfilesize = (u_int64_t)0x40000000 * fs->fs_bsize - 1; /* XXX */
671: #endif /* NeXT */
672: if (fs->fs_maxfilesize > maxfilesize) /* XXX */
673: fs->fs_maxfilesize = maxfilesize; /* XXX */
674: if (ronly == 0) {
675: fs->fs_clean = 0;
676: (void) ffs_sbupdate(ump, MNT_WAIT);
677: }
678: return (0);
679: out:
680: if (bp)
681: brelse(bp);
682: (void)VOP_CLOSE(devvp, ronly ? FREAD : FREAD|FWRITE, cred, p);
683: if (ump) {
684: _FREE(ump->um_fs, M_UFSMNT);
685: _FREE(ump, M_UFSMNT);
686: mp->mnt_data = (qaddr_t)0;
687: }
688: return (error);
689: }
690:
691: /*
692: * Sanity checks for old file systems.
693: *
694: * XXX - goes away some day.
695: */
696: ffs_oldfscompat(fs)
697: struct fs *fs;
698: {
699: int i;
700:
701: fs->fs_npsect = max(fs->fs_npsect, fs->fs_nsect); /* XXX */
702: fs->fs_interleave = max(fs->fs_interleave, 1); /* XXX */
703: if (fs->fs_postblformat == FS_42POSTBLFMT) /* XXX */
704: fs->fs_nrpos = 8; /* XXX */
705: if (fs->fs_inodefmt < FS_44INODEFMT) { /* XXX */
706: u_int64_t sizepb = fs->fs_bsize; /* XXX */
707: /* XXX */
708: fs->fs_maxfilesize = fs->fs_bsize * NDADDR - 1; /* XXX */
709: for (i = 0; i < NIADDR; i++) { /* XXX */
710: sizepb *= NINDIR(fs); /* XXX */
711: fs->fs_maxfilesize += sizepb; /* XXX */
712: } /* XXX */
713: fs->fs_qbmask = ~fs->fs_bmask; /* XXX */
714: fs->fs_qfmask = ~fs->fs_fmask; /* XXX */
715: } /* XXX */
716: return (0);
717: }
718:
719: /*
720: * unmount system call
721: */
722: int
723: ffs_unmount(mp, mntflags, p)
724: struct mount *mp;
725: int mntflags;
726: struct proc *p;
727: {
728: register struct ufsmount *ump;
729: register struct fs *fs;
730: int error, flags;
731: flags = 0;
732: if (mntflags & MNT_FORCE)
733: flags |= FORCECLOSE;
734: if (error = ffs_flushfiles(mp, flags, p))
735: return (error);
736: ump = VFSTOUFS(mp);
737: fs = ump->um_fs;
738: if (fs->fs_ronly == 0) {
739: fs->fs_clean = 1;
740: if (error = ffs_sbupdate(ump, MNT_WAIT)) {
741: fs->fs_clean = 0;
742: #ifndef NeXT
743: /* we can atleast cleanup ; as the media could be WP */
744: /* & during mount, we do not check for write failures */
745: /* FIXME LATER : the Correct fix would be to have */
746: /* mount detect the WP media and downgrade to readonly mount */
747: /* For now, here it is */
748: return (error);
749: #endif
750: }
751: }
752: ump->um_devvp->v_specflags &= ~SI_MOUNTEDON;
753: error = VOP_CLOSE(ump->um_devvp, fs->fs_ronly ? FREAD : FREAD|FWRITE,
754: NOCRED, p);
755: vrele(ump->um_devvp);
756:
757: _FREE(fs->fs_csp[0], M_UFSMNT);
758: _FREE(fs, M_UFSMNT);
759: _FREE(ump, M_UFSMNT);
760: mp->mnt_data = (qaddr_t)0;
761: #if REV_ENDIAN_FS
762: mp->mnt_flag &= ~MNT_REVEND;
763: #endif /* REV_ENDIAN_FS */
764: return (error);
765: }
766:
767: /*
768: * Flush out all the files in a filesystem.
769: */
770: ffs_flushfiles(mp, flags, p)
771: register struct mount *mp;
772: int flags;
773: struct proc *p;
774: {
775: register struct ufsmount *ump;
776: int i, error;
777:
778: ump = VFSTOUFS(mp);
779: #if QUOTA
780: if (mp->mnt_flag & MNT_QUOTA) {
781: if (error = vflush(mp, NULLVP, SKIPSYSTEM|flags))
782: return (error);
783: for (i = 0; i < MAXQUOTAS; i++) {
784: if (ump->um_quotas[i] == NULLVP)
785: continue;
786: quotaoff(p, mp, i);
787: }
788: /*
789: * Here we fall through to vflush again to ensure
790: * that we have gotten rid of all the system vnodes.
791: */
792: }
793: #endif
794: error = vflush(mp, NULLVP, flags);
795: return (error);
796: }
797:
798: /*
799: * Get file system statistics.
800: */
801: int
802: ffs_statfs(mp, sbp, p)
803: struct mount *mp;
804: register struct statfs *sbp;
805: struct proc *p;
806: {
807: register struct ufsmount *ump;
808: register struct fs *fs;
809:
810: ump = VFSTOUFS(mp);
811: fs = ump->um_fs;
812: if (fs->fs_magic != FS_MAGIC)
813: panic("ffs_statfs");
814: sbp->f_bsize = fs->fs_fsize;
815: sbp->f_iosize = fs->fs_bsize;
816: sbp->f_blocks = fs->fs_dsize;
817: sbp->f_bfree = fs->fs_cstotal.cs_nbfree * fs->fs_frag +
818: fs->fs_cstotal.cs_nffree;
819: sbp->f_bavail = freespace(fs, fs->fs_minfree);
820: sbp->f_files = fs->fs_ncg * fs->fs_ipg - ROOTINO;
821: sbp->f_ffree = fs->fs_cstotal.cs_nifree;
822: if (sbp != &mp->mnt_stat) {
823: sbp->f_type = mp->mnt_vfc->vfc_typenum;
824: bcopy((caddr_t)mp->mnt_stat.f_mntonname,
825: (caddr_t)&sbp->f_mntonname[0], MNAMELEN);
826: bcopy((caddr_t)mp->mnt_stat.f_mntfromname,
827: (caddr_t)&sbp->f_mntfromname[0], MNAMELEN);
828: }
829: return (0);
830: }
831:
832: /*
833: * Go through the disk queues to initiate sandbagged IO;
834: * go through the inodes to write those that have been modified;
835: * initiate the writing of the super block if it has been modified.
836: *
837: * Note: we are always called with the filesystem marked `MPBUSY'.
838: */
839: int
840: ffs_sync(mp, waitfor, cred, p)
841: struct mount *mp;
842: int waitfor;
843: struct ucred *cred;
844: struct proc *p;
845: {
846: struct vnode *nvp, *vp;
847: struct inode *ip;
848: struct ufsmount *ump = VFSTOUFS(mp);
849: struct fs *fs;
850: int error, allerror = 0;
851:
852: fs = ump->um_fs;
853: if (fs->fs_fmod != 0 && fs->fs_ronly != 0) { /* XXX */
854: printf("fs = %s\n", fs->fs_fsmnt);
855: panic("update: rofs mod");
856: }
857: /*
858: * Write back each (modified) inode.
859: */
860: simple_lock(&mntvnode_slock);
861: loop:
862: for (vp = mp->mnt_vnodelist.lh_first;
863: vp != NULL;
864: vp = nvp) {
865: /*
866: * If the vnode that we are about to sync is no longer
867: * associated with this mount point, start over.
868: */
869: if (vp->v_mount != mp)
870: goto loop;
871: simple_lock(&vp->v_interlock);
872: nvp = vp->v_mntvnodes.le_next;
873: ip = VTOI(vp);
874: if ((ip->i_flag &
875: (IN_ACCESS | IN_CHANGE | IN_MODIFIED | IN_UPDATE)) == 0 &&
876: vp->v_dirtyblkhd.lh_first == NULL) {
877: simple_unlock(&vp->v_interlock);
878: continue;
879: }
880: simple_unlock(&mntvnode_slock);
881: error = vget(vp, LK_EXCLUSIVE | LK_NOWAIT | LK_INTERLOCK, p);
882: if (error) {
883: simple_lock(&mntvnode_slock);
884: if (error == ENOENT)
885: goto loop;
886: continue;
887: }
888: if (error = VOP_FSYNC(vp, cred, waitfor, p))
889: allerror = error;
890: VOP_UNLOCK(vp, 0, p);
891: vrele(vp);
892: simple_lock(&mntvnode_slock);
893: }
894: simple_unlock(&mntvnode_slock);
895: /*
896: * Force stale file system control information to be flushed.
897: */
898: if (error = VOP_FSYNC(ump->um_devvp, cred, waitfor, p))
899: allerror = error;
900: #if QUOTA
901: qsync(mp);
902: #endif
903: /*
904: * Write back modified superblock.
905: */
906: if (fs->fs_fmod != 0) {
907: fs->fs_fmod = 0;
908: fs->fs_time = time.tv_sec;
909: if (error = ffs_sbupdate(ump, waitfor))
910: allerror = error;
911: }
912: return (allerror);
913: }
914:
915: /*
916: * Look up a FFS dinode number to find its incore vnode, otherwise read it
917: * in from disk. If it is in core, wait for the lock bit to clear, then
918: * return the inode locked. Detection and handling of mount points must be
919: * done by the calling routine.
920: */
921: int
922: ffs_vget(mp, ino, vpp)
923: struct mount *mp;
924: ino_t ino;
925: struct vnode **vpp;
926: {
927: struct proc *p = current_proc(); /* XXX */
928: struct fs *fs;
929: struct inode *ip;
930: struct ufsmount *ump;
931: struct buf *bp;
932: struct vnode *vp;
933: dev_t dev;
934: int i, type, error;
935:
936: ump = VFSTOUFS(mp);
937: dev = ump->um_dev;
938: if ((*vpp = ufs_ihashget(dev, ino)) != NULL) {
939: #if MACH_NBC
940: vp = *vpp;
941: if ((vp->v_type == VREG) && !(vp->v_vm_info)){
942: vm_info_init(vp);
943: }
944: #endif /* MACH_NBC */
945: return (0);
946: }
947: /* Allocate a new vnode/inode. */
948: if (error = getnewvnode(VT_UFS, mp, ffs_vnodeop_p, &vp)) {
949: *vpp = NULL;
950: return (error);
951: }
952: type = ump->um_devvp->v_tag == VT_MFS ? M_MFSNODE : M_FFSNODE; /* XXX */
953: MALLOC_ZONE(ip, struct inode *, sizeof(struct inode), type, M_WAITOK);
954: bzero((caddr_t)ip, sizeof(struct inode));
955: lockinit(&ip->i_lock, PINOD, "inode", 0, 0);
956: vp->v_data = ip;
957: ip->i_vnode = vp;
958: ip->i_fs = fs = ump->um_fs;
959: ip->i_dev = dev;
960: ip->i_number = ino;
961: #if QUOTA
962: for (i = 0; i < MAXQUOTAS; i++)
963: ip->i_dquot[i] = NODQUOT;
964: #endif
965: /*
966: * Put it onto its hash chain and lock it so that other requests for
967: * this inode will block if they arrive while we are sleeping waiting
968: * for old data structures to be purged or for the contents of the
969: * disk portion of this inode to be read.
970: */
971: ufs_ihashins(ip);
972:
973: /* Read in the disk contents for the inode, copy into the inode. */
974: if (error = bread(ump->um_devvp, fsbtodb(fs, ino_to_fsba(fs, ino)),
975: (int)fs->fs_bsize, NOCRED, &bp)) {
976: /*
977: * The inode does not contain anything useful, so it would
978: * be misleading to leave it on its hash chain. With mode
979: * still zero, it will be unlinked and returned to the free
980: * list by vput().
981: */
982: vput(vp);
983: brelse(bp);
984: *vpp = NULL;
985: return (error);
986: }
987: #if REV_ENDIAN_FS
988: if (mp->mnt_flag & MNT_REVEND) {
989: byte_swap_inode_in(((struct dinode *)bp->b_data + ino_to_fsbo(fs, ino)),ip);
990: } else {
991: #endif /* REV_ENDIAN_FS */
992: ip->i_din = *((struct dinode *)bp->b_data + ino_to_fsbo(fs, ino));
993: #if REV_ENDIAN_FS
994: }
995: #endif /* REV_ENDIAN_FS */
996: brelse(bp);
997:
998: /*
999: * Initialize the vnode from the inode, check for aliases.
1000: * Note that the underlying vnode may have changed.
1001: */
1002: if (error = ufs_vinit(mp, ffs_specop_p, FFS_FIFOOPS, &vp)) {
1003: vput(vp);
1004: *vpp = NULL;
1005: return (error);
1006: }
1007: /*
1008: * Finish inode initialization now that aliasing has been resolved.
1009: */
1010: ip->i_devvp = ump->um_devvp;
1011: VREF(ip->i_devvp);
1012: /*
1013: * Set up a generation number for this inode if it does not
1014: * already have one. This should only happen on old filesystems.
1015: */
1016: if (ip->i_gen == 0) {
1017: if (++nextgennumber < (u_long)time.tv_sec)
1018: nextgennumber = time.tv_sec;
1019: ip->i_gen = nextgennumber;
1020: if ((vp->v_mount->mnt_flag & MNT_RDONLY) == 0)
1021: ip->i_flag |= IN_MODIFIED;
1022: }
1023: /*
1024: * Ensure that uid and gid are correct. This is a temporary
1025: * fix until fsck has been changed to do the update.
1026: */
1027: if (fs->fs_inodefmt < FS_44INODEFMT) { /* XXX */
1028: ip->i_uid = ip->i_din.di_ouid; /* XXX */
1029: ip->i_gid = ip->i_din.di_ogid; /* XXX */
1030: } /* XXX */
1031:
1032: *vpp = vp;
1033: #if MACH_NBC
1034: if ((vp->v_type == VREG) && !(vp->v_vm_info)){
1035: vm_info_init(vp);
1036: }
1037: #endif /* MACH_NBC */
1038: return (0);
1039: }
1040:
1041: /*
1042: * File handle to vnode
1043: *
1044: * Have to be really careful about stale file handles:
1045: * - check that the inode number is valid
1046: * - call ffs_vget() to get the locked inode
1047: * - check for an unallocated inode (i_mode == 0)
1048: * - check that the given client host has export rights and return
1049: * those rights via. exflagsp and credanonp
1050: */
1051: int
1052: ffs_fhtovp(mp, fhp, nam, vpp, exflagsp, credanonp)
1053: register struct mount *mp;
1054: struct fid *fhp;
1055: struct mbuf *nam;
1056: struct vnode **vpp;
1057: int *exflagsp;
1058: struct ucred **credanonp;
1059: {
1060: register struct ufid *ufhp;
1061: struct fs *fs;
1062:
1063: ufhp = (struct ufid *)fhp;
1064: fs = VFSTOUFS(mp)->um_fs;
1065: if (ufhp->ufid_ino < ROOTINO ||
1066: ufhp->ufid_ino >= fs->fs_ncg * fs->fs_ipg)
1067: return (ESTALE);
1068: return (ufs_check_export(mp, ufhp, nam, vpp, exflagsp, credanonp));
1069: }
1070:
1071: /*
1072: * Vnode pointer to File handle
1073: */
1074: /* ARGSUSED */
1075: ffs_vptofh(vp, fhp)
1076: struct vnode *vp;
1077: struct fid *fhp;
1078: {
1079: register struct inode *ip;
1080: register struct ufid *ufhp;
1081:
1082: ip = VTOI(vp);
1083: ufhp = (struct ufid *)fhp;
1084: ufhp->ufid_len = sizeof(struct ufid);
1085: ufhp->ufid_ino = ip->i_number;
1086: ufhp->ufid_gen = ip->i_gen;
1087: return (0);
1088: }
1089:
1090: /*
1091: * Initialize the filesystem; just use ufs_init.
1092: */
1093: int
1094: ffs_init(vfsp)
1095: struct vfsconf *vfsp;
1096: {
1097:
1098: return (ufs_init(vfsp));
1099: }
1100:
1101: /*
1102: * fast filesystem related variables.
1103: */
1104: ffs_sysctl(name, namelen, oldp, oldlenp, newp, newlen, p)
1105: int *name;
1106: u_int namelen;
1107: void *oldp;
1108: size_t *oldlenp;
1109: void *newp;
1110: size_t newlen;
1111: struct proc *p;
1112: {
1113: extern int doclusterread, doclusterwrite, doreallocblks, doasyncfree;
1114:
1115: /* all sysctl names at this level are terminal */
1116: if (namelen != 1)
1117: return (ENOTDIR); /* overloaded */
1118:
1119: switch (name[0]) {
1120: case FFS_CLUSTERREAD:
1121: return (sysctl_int(oldp, oldlenp, newp, newlen,
1122: &doclusterread));
1123: case FFS_CLUSTERWRITE:
1124: return (sysctl_int(oldp, oldlenp, newp, newlen,
1125: &doclusterwrite));
1126: case FFS_REALLOCBLKS:
1127: return (sysctl_int(oldp, oldlenp, newp, newlen,
1128: &doreallocblks));
1129: case FFS_ASYNCFREE:
1130: return (sysctl_int(oldp, oldlenp, newp, newlen, &doasyncfree));
1131: default:
1132: return (EOPNOTSUPP);
1133: }
1134: /* NOTREACHED */
1135: }
1136:
1137: /*
1138: * Write a superblock and associated information back to disk.
1139: */
1140: int
1141: ffs_sbupdate(mp, waitfor)
1142: struct ufsmount *mp;
1143: int waitfor;
1144: {
1145: register struct fs *dfs, *fs = mp->um_fs;
1146: register struct buf *bp;
1147: int blks;
1148: caddr_t space;
1149: int i, size, error, allerror = 0;
1150: #ifdef NeXT
1151: int devBlockSize=0;
1152: #endif /* NeXT */
1153: #if REV_ENDIAN_FS
1154: int rev_endian=(mp->um_mountp->mnt_flag & MNT_REVEND);
1155: #endif /* REV_ENDIAN_FS */
1156:
1157: /*
1158: * First write back the summary information.
1159: */
1160: blks = howmany(fs->fs_cssize, fs->fs_fsize);
1161: space = (caddr_t)fs->fs_csp[0];
1162: for (i = 0; i < blks; i += fs->fs_frag) {
1163: size = fs->fs_bsize;
1164: if (i + fs->fs_frag > blks)
1165: size = (blks - i) * fs->fs_fsize;
1166: bp = getblk(mp->um_devvp, fsbtodb(fs, fs->fs_csaddr + i),
1167: size, 0, 0);
1168: bcopy(space, bp->b_data, (u_int)size);
1169: #if REV_ENDIAN_FS
1170: if (rev_endian) {
1171: byte_swap_ints((int *)bp->b_data, size / sizeof(int));
1172: }
1173: #endif /* REV_ENDIAN_FS */
1174: space += size;
1175: if (waitfor != MNT_WAIT)
1176: bawrite(bp);
1177: else if (error = bwrite(bp))
1178: allerror = error;
1179: }
1180: /*
1181: * Now write back the superblock itself. If any errors occurred
1182: * up to this point, then fail so that the superblock avoids
1183: * being written out as clean.
1184: */
1185: if (allerror)
1186: return (allerror);
1187: #ifdef NeXT
1188: VOP_DEVBLOCKSIZE(mp->um_devvp,&devBlockSize);
1189: bp = getblk(mp->um_devvp, (SBOFF/devBlockSize), (int)fs->fs_sbsize, 0, 0);
1190: #else
1191: bp = getblk(mp->um_devvp, SBLOCK, (int)fs->fs_sbsize, 0, 0);
1192: #endif
1193: bcopy((caddr_t)fs, bp->b_data, (u_int)fs->fs_sbsize);
1194: /* Restore compatibility to old file systems. XXX */
1195: dfs = (struct fs *)bp->b_data; /* XXX */
1196: if (fs->fs_postblformat == FS_42POSTBLFMT) /* XXX */
1197: dfs->fs_nrpos = -1; /* XXX */
1198: #if REV_ENDIAN_FS
1199: /*
1200: * Swapping bytes here ; so that in case
1201: * of inode format < FS_44INODEFMT appropriate
1202: * fields get moved
1203: */
1204: if (rev_endian) {
1205: byte_swap_sbout((struct fs *)bp->b_data);
1206: }
1207: #endif /* REV_ENDIAN_FS */
1208: if (fs->fs_inodefmt < FS_44INODEFMT) { /* XXX */
1209: int32_t *lp, tmp; /* XXX */
1210: /* XXX */
1211: lp = (int32_t *)&dfs->fs_qbmask; /* XXX */
1212: tmp = lp[4]; /* XXX */
1213: for (i = 4; i > 0; i--) /* XXX */
1214: lp[i] = lp[i-1]; /* XXX */
1215: lp[0] = tmp; /* XXX */
1216: } /* XXX */
1217: #if REV_ENDIAN_FS
1218: /* Note that dfs is already swapped so swap the filesize
1219: * before writing
1220: */
1221: if (rev_endian) {
1222: dfs->fs_maxfilesize = NXSwapLongLong(mp->um_savedmaxfilesize); /* XXX */
1223: } else {
1224: #endif /* REV_ENDIAN_FS */
1225: dfs->fs_maxfilesize = mp->um_savedmaxfilesize; /* XXX */
1226: #if REV_ENDIAN_FS
1227: }
1228: #endif /* REV_ENDIAN_FS */
1229: if (waitfor != MNT_WAIT)
1230: bawrite(bp);
1231: else if (error = bwrite(bp))
1232: allerror = error;
1233:
1234: return (allerror);
1235: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.