|
|
1.1 root 1: /*
2: * Copyright (c) 2000 Apple Computer, Inc. All rights reserved.
3: *
4: * @APPLE_LICENSE_HEADER_START@
5: *
6: * The contents of this file constitute Original Code as defined in and
7: * are subject to the Apple Public Source License Version 1.1 (the
8: * "License"). You may not use this file except in compliance with the
9: * License. Please obtain a copy of the License at
10: * http://www.apple.com/publicsource and read it before using this file.
11: *
12: * This Original Code and all software distributed under the License are
13: * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER
14: * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
15: * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
16: * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the
17: * License for the specific language governing rights and limitations
18: * under the License.
19: *
20: * @APPLE_LICENSE_HEADER_END@
21: */
22: /* $NetBSD: lfs_vfsops.c,v 1.8 1995/03/09 12:06:10 mycroft Exp $ */
23:
24: /*
25: * Copyright (c) 1989, 1991, 1993, 1994
26: * The Regents of the University of California. All rights reserved.
27: *
28: * Redistribution and use in source and binary forms, with or without
29: * modification, are permitted provided that the following conditions
30: * are met:
31: * 1. Redistributions of source code must retain the above copyright
32: * notice, this list of conditions and the following disclaimer.
33: * 2. Redistributions in binary form must reproduce the above copyright
34: * notice, this list of conditions and the following disclaimer in the
35: * documentation and/or other materials provided with the distribution.
36: * 3. All advertising materials mentioning features or use of this software
37: * must display the following acknowledgement:
38: * This product includes software developed by the University of
39: * California, Berkeley and its contributors.
40: * 4. Neither the name of the University nor the names of its contributors
41: * may be used to endorse or promote products derived from this software
42: * without specific prior written permission.
43: *
44: * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
45: * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
46: * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
47: * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
48: * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
49: * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
50: * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
51: * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
52: * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
53: * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
54: * SUCH DAMAGE.
55: *
56: * @(#)lfs_vfsops.c 8.10 (Berkeley) 11/21/94
57: */
58:
59: #include <sys/param.h>
60: #include <sys/systm.h>
61: #include <sys/namei.h>
62: #include <sys/proc.h>
63: #include <sys/kernel.h>
64: #include <sys/vnode.h>
65: #include <sys/mount.h>
66: #include <sys/buf.h>
67: #include <sys/mbuf.h>
68: #include <sys/file.h>
69: #include <sys/disklabel.h>
70: #include <sys/ioctl.h>
71: #include <sys/errno.h>
72: #include <sys/malloc.h>
73: #include <sys/socket.h>
74:
75: #include <miscfs/specfs/specdev.h>
76:
77: #include <ufs/ufs/quota.h>
78: #include <ufs/ufs/inode.h>
79: #include <ufs/ufs/ufsmount.h>
80: #include <ufs/ufs/ufs_extern.h>
81:
82: #include <ufs/lfs/lfs.h>
83: #include <ufs/lfs/lfs_extern.h>
84:
85: int lfs_mountfs __P((struct vnode *, struct mount *, struct proc *));
86:
87: struct vfsops lfs_vfsops = {
88: MOUNT_LFS,
89: lfs_mount,
90: ufs_start,
91: lfs_unmount,
92: ufs_root,
93: ufs_quotactl,
94: lfs_statfs,
95: lfs_sync,
96: lfs_vget,
97: lfs_fhtovp,
98: lfs_vptofh,
99: lfs_init,
100: };
101:
102: int
103: lfs_mountroot()
104: {
105: panic("lfs_mountroot"); /* XXX -- implement */
106: }
107:
108: /*
109: * VFS Operations.
110: *
111: * mount system call
112: */
113: lfs_mount(mp, path, data, ndp, p)
114: register struct mount *mp;
115: char *path;
116: caddr_t data;
117: struct nameidata *ndp;
118: struct proc *p;
119: {
120: struct vnode *devvp;
121: struct ufs_args args;
122: struct ufsmount *ump;
123: register struct lfs *fs; /* LFS */
124: size_t size;
125: int error;
126: mode_t accessmode;
127:
128: if (error = copyin(data, (caddr_t)&args, sizeof (struct ufs_args)))
129: return (error);
130:
131: /* Until LFS can do NFS right. XXX */
132: if (args.export.ex_flags & MNT_EXPORTED)
133: return (EINVAL);
134:
135: /*
136: * If updating, check whether changing from read-only to
137: * read/write; if there is no device name, that's all we do.
138: */
139: if (mp->mnt_flag & MNT_UPDATE) {
140: ump = VFSTOUFS(mp);
141: if (fs->lfs_ronly && (mp->mnt_flag & MNT_WANTRDWR)) {
142: /*
143: * If upgrade to read-write by non-root, then verify
144: * that user has necessary permissions on the device.
145: */
146: if (p->p_ucred->cr_uid != 0) {
147: VOP_LOCK(ump->um_devvp);
148: if (error = VOP_ACCESS(ump->um_devvp,
149: VREAD | VWRITE, p->p_ucred, p)) {
150: VOP_UNLOCK(ump->um_devvp);
151: return (error);
152: }
153: VOP_UNLOCK(ump->um_devvp);
154: }
155: fs->lfs_ronly = 0;
156: }
157: if (args.fspec == 0) {
158: /*
159: * Process export requests.
160: */
161: return (vfs_export(mp, &ump->um_export, &args.export));
162: }
163: }
164: /*
165: * Not an update, or updating the name: look up the name
166: * and verify that it refers to a sensible block device.
167: */
168: NDINIT(ndp, LOOKUP, FOLLOW, UIO_USERSPACE, args.fspec, p);
169: if (error = namei(ndp))
170: return (error);
171: devvp = ndp->ni_vp;
172: if (devvp->v_type != VBLK) {
173: vrele(devvp);
174: return (ENOTBLK);
175: }
176: if (major(devvp->v_rdev) >= nblkdev) {
177: vrele(devvp);
178: return (ENXIO);
179: }
180: /*
181: * If mount by non-root, then verify that user has necessary
182: * permissions on the device.
183: */
184: if (p->p_ucred->cr_uid != 0) {
185: accessmode = VREAD;
186: if ((mp->mnt_flag & MNT_RDONLY) == 0)
187: accessmode |= VWRITE;
188: VOP_LOCK(devvp);
189: if (error = VOP_ACCESS(devvp, accessmode, p->p_ucred, p)) {
190: vput(devvp);
191: return (error);
192: }
193: VOP_UNLOCK(devvp);
194: }
195: if ((mp->mnt_flag & MNT_UPDATE) == 0)
196: error = lfs_mountfs(devvp, mp, p); /* LFS */
197: else {
198: if (devvp != ump->um_devvp)
199: error = EINVAL; /* needs translation */
200: else
201: vrele(devvp);
202: }
203: if (error) {
204: vrele(devvp);
205: return (error);
206: }
207: ump = VFSTOUFS(mp);
208: fs = ump->um_lfs; /* LFS */
209: #ifdef NOTLFS /* LFS */
210: (void) copyinstr(path, fs->fs_fsmnt, sizeof(fs->fs_fsmnt) - 1, &size);
211: bzero(fs->fs_fsmnt + size, sizeof(fs->fs_fsmnt) - size);
212: bcopy(fs->fs_fsmnt, mp->mnt_stat.f_mntonname, MNAMELEN);
213: #else
214: (void)copyinstr(path, fs->lfs_fsmnt, sizeof(fs->lfs_fsmnt) - 1, &size);
215: bzero(fs->lfs_fsmnt + size, sizeof(fs->lfs_fsmnt) - size);
216: bcopy(fs->lfs_fsmnt, mp->mnt_stat.f_mntonname, MNAMELEN);
217: #endif
218: (void) copyinstr(args.fspec, mp->mnt_stat.f_mntfromname, MNAMELEN - 1,
219: &size);
220: bzero(mp->mnt_stat.f_mntfromname + size, MNAMELEN - size);
221: return (0);
222: }
223:
224: /*
225: * Common code for mount and mountroot
226: * LFS specific
227: */
228: int
229: lfs_mountfs(devvp, mp, p)
230: register struct vnode *devvp;
231: struct mount *mp;
232: struct proc *p;
233: {
234: extern struct vnode *rootvp;
235: register struct lfs *fs;
236: register struct ufsmount *ump;
237: struct vnode *vp;
238: struct buf *bp;
239: struct partinfo dpart;
240: dev_t dev;
241: int error, i, ronly, size;
242: struct ucred *cred;
243:
244: cred = p ? p->p_ucred : NOCRED;
245: /*
246: * Disallow multiple mounts of the same device.
247: * Disallow mounting of a device that is currently in use
248: * (except for root, which might share swap device for miniroot).
249: * Flush out any old buffers remaining from a previous use.
250: */
251: if (error = vfs_mountedon(devvp))
252: return (error);
253: if (vcount(devvp) > 1 && devvp != rootvp)
254: return (EBUSY);
255: if (error = vinvalbuf(devvp, V_SAVE, cred, p, 0, 0))
256: return (error);
257:
258: ronly = (mp->mnt_flag & MNT_RDONLY) != 0;
259: if (error = VOP_OPEN(devvp, ronly ? FREAD : FREAD|FWRITE, FSCRED, p))
260: return (error);
261:
262: if (VOP_IOCTL(devvp, DIOCGPART, (caddr_t)&dpart, FREAD, cred, p) != 0)
263: size = DEV_BSIZE;
264: else {
265: size = dpart.disklab->d_secsize;
266: #ifdef NEVER_USED
267: dpart.part->p_fstype = FS_LFS;
268: dpart.part->p_fsize = fs->lfs_fsize; /* frag size */
269: dpart.part->p_frag = fs->lfs_frag; /* frags per block */
270: dpart.part->p_cpg = fs->lfs_segshift; /* segment shift */
271: #endif
272: }
273:
274: /* Don't free random space on error. */
275: bp = NULL;
276: ump = NULL;
277:
278: /* Read in the superblock. */
279: if (error = bread(devvp, LFS_LABELPAD / size, LFS_SBPAD, cred, &bp))
280: goto out;
281: fs = (struct lfs *)bp->b_data;
282:
283: /* Check the basics. */
284: if (fs->lfs_magic != LFS_MAGIC || fs->lfs_bsize > MAXBSIZE ||
285: fs->lfs_bsize < sizeof(struct lfs)) {
286: error = EINVAL; /* XXX needs translation */
287: goto out;
288: }
289:
290: /* Allocate the mount structure, copy the superblock into it. */
291: // ump = (struct ufsmount *)malloc(sizeof *ump, M_UFSMNT, M_WAITOK);
292: // fs = ump->um_lfs = malloc(sizeof(struct lfs), M_UFSMNT, M_WAITOK);
293: MALLOC(ump, struct ufsmount *, sizeof(struct ufsmount), M_UFSMNT, M_WAITOK);
294: MALLOC(ump->um_lfs, struct lfs *, sizeof(struct lfs), M_UFSMNT, M_WAITOK);
295: fs = ump->um_lfs;
296: bcopy(bp->b_data, fs, sizeof(struct lfs));
297: if (sizeof(struct lfs) < LFS_SBPAD) /* XXX why? */
298: bp->b_flags |= B_INVAL;
299: brelse(bp);
300: bp = NULL;
301:
302: /* Set up the I/O information */
303: fs->lfs_iocount = 0;
304:
305: /* Set up the ifile and lock aflags */
306: fs->lfs_doifile = 0;
307: fs->lfs_writer = 0;
308: fs->lfs_dirops = 0;
309: fs->lfs_seglock = 0;
310:
311: /* Set the file system readonly/modify bits. */
312: fs->lfs_ronly = ronly;
313: if (ronly == 0)
314: fs->lfs_fmod = 1;
315:
316: /* Initialize the mount structure. */
317: dev = devvp->v_rdev;
318: mp->mnt_data = (qaddr_t)ump;
319: mp->mnt_stat.f_fsid.val[0] = (long)dev;
320: mp->mnt_stat.f_fsid.val[1] = makefstype(MOUNT_LFS);
321: mp->mnt_maxsymlinklen = fs->lfs_maxsymlinklen;
322: mp->mnt_flag |= MNT_LOCAL;
323: ump->um_mountp = mp;
324: ump->um_dev = dev;
325: ump->um_devvp = devvp;
326: ump->um_bptrtodb = 0;
327: ump->um_seqinc = 1 << fs->lfs_fsbtodb;
328: ump->um_nindir = fs->lfs_nindir;
329: for (i = 0; i < MAXQUOTAS; i++)
330: ump->um_quotas[i] = NULLVP;
331: devvp->v_specflags |= SI_MOUNTEDON;
332:
333: /*
334: * We use the ifile vnode for almost every operation. Instead of
335: * retrieving it from the hash table each time we retrieve it here,
336: * artificially increment the reference count and keep a pointer
337: * to it in the incore copy of the superblock.
338: */
339: if (error = VFS_VGET(mp, LFS_IFILE_INUM, &vp))
340: goto out;
341: fs->lfs_ivnode = vp;
342: VREF(vp);
343: vput(vp);
344:
345: return (0);
346: out:
347: if (bp)
348: brelse(bp);
349: (void)VOP_CLOSE(devvp, ronly ? FREAD : FREAD|FWRITE, cred, p);
350: if (ump) {
351: free(ump->um_lfs, M_UFSMNT);
352: free(ump, M_UFSMNT);
353: mp->mnt_data = (qaddr_t)0;
354: }
355: return (error);
356: }
357:
358: /*
359: * unmount system call
360: */
361: lfs_unmount(mp, mntflags, p)
362: struct mount *mp;
363: int mntflags;
364: struct proc *p;
365: {
366: extern int doforce;
367: register struct ufsmount *ump;
368: register struct lfs *fs;
369: int i, error, flags, ronly;
370:
371: flags = 0;
372: if (mntflags & MNT_FORCE)
373: flags |= FORCECLOSE;
374:
375: ump = VFSTOUFS(mp);
376: fs = ump->um_lfs;
377: #if QUOTA
378: if (mp->mnt_flag & MNT_QUOTA) {
379: if (error = vflush(mp, fs->lfs_ivnode, SKIPSYSTEM|flags))
380: return (error);
381: for (i = 0; i < MAXQUOTAS; i++) {
382: if (ump->um_quotas[i] == NULLVP)
383: continue;
384: quotaoff(p, mp, i);
385: }
386: /*
387: * Here we fall through to vflush again to ensure
388: * that we have gotten rid of all the system vnodes.
389: */
390: }
391: #endif
392: if (error = vflush(mp, fs->lfs_ivnode, flags))
393: return (error);
394: fs->lfs_clean = 1;
395: if (error = VFS_SYNC(mp, 1, p->p_ucred, p))
396: return (error);
397: if (fs->lfs_ivnode->v_dirtyblkhd.lh_first)
398: panic("lfs_unmount: still dirty blocks on ifile vnode\n");
399: vrele(fs->lfs_ivnode);
400: vgone(fs->lfs_ivnode);
401:
402: ronly = !fs->lfs_ronly;
403: ump->um_devvp->v_specflags &= ~SI_MOUNTEDON;
404: error = VOP_CLOSE(ump->um_devvp,
405: ronly ? FREAD : FREAD|FWRITE, NOCRED, p);
406: vrele(ump->um_devvp);
407: free(fs, M_UFSMNT);
408: free(ump, M_UFSMNT);
409: mp->mnt_data = (qaddr_t)0;
410: mp->mnt_flag &= ~MNT_LOCAL;
411: return (error);
412: }
413:
414: /*
415: * Get file system statistics.
416: */
417: lfs_statfs(mp, sbp, p)
418: struct mount *mp;
419: register struct statfs *sbp;
420: struct proc *p;
421: {
422: register struct lfs *fs;
423: register struct ufsmount *ump;
424:
425: ump = VFSTOUFS(mp);
426: fs = ump->um_lfs;
427: if (fs->lfs_magic != LFS_MAGIC)
428: panic("lfs_statfs: magic");
429: sbp->f_type = 0;
430: sbp->f_bsize = fs->lfs_bsize;
431: sbp->f_iosize = fs->lfs_bsize;
432: sbp->f_blocks = dbtofsb(fs,fs->lfs_dsize);
433: sbp->f_bfree = dbtofsb(fs, fs->lfs_bfree);
434: sbp->f_bavail = (fs->lfs_dsize * (100 - fs->lfs_minfree) / 100) -
435: (fs->lfs_dsize - fs->lfs_bfree);
436: sbp->f_bavail = dbtofsb(fs, sbp->f_bavail);
437: sbp->f_files = fs->lfs_nfiles;
438: sbp->f_ffree = sbp->f_bfree * INOPB(fs);
439: if (sbp != &mp->mnt_stat) {
440: bcopy(mp->mnt_stat.f_mntonname, sbp->f_mntonname, MNAMELEN);
441: bcopy(mp->mnt_stat.f_mntfromname, sbp->f_mntfromname, MNAMELEN);
442: }
443: strncpy(sbp->f_fstypename, mp->mnt_op->vfs_name, MFSNAMELEN);
444: sbp->f_fstypename[MFSNAMELEN] = '\0';
445: return (0);
446: }
447:
448: /*
449: * Go through the disk queues to initiate sandbagged IO;
450: * go through the inodes to write those that have been modified;
451: * initiate the writing of the super block if it has been modified.
452: *
453: * Note: we are always called with the filesystem marked `MPBUSY'.
454: */
455: lfs_sync(mp, waitfor, cred, p)
456: struct mount *mp;
457: int waitfor;
458: struct ucred *cred;
459: struct proc *p;
460: {
461: int error;
462:
463: /* All syncs must be checkpoints until roll-forward is implemented. */
464: error = lfs_segwrite(mp, SEGM_CKP | (waitfor ? SEGM_SYNC : 0));
465: #if QUOTA
466: qsync(mp);
467: #endif
468: return (error);
469: }
470:
471: /*
472: * Look up an LFS dinode number to find its incore vnode. If not already
473: * in core, read it in from the specified device. Return the inode locked.
474: * Detection and handling of mount points must be done by the calling routine.
475: */
476: int
477: lfs_vget(mp, ino, vpp)
478: struct mount *mp;
479: ino_t ino;
480: struct vnode **vpp;
481: {
482: register struct lfs *fs;
483: register struct inode *ip;
484: struct buf *bp;
485: struct ifile *ifp;
486: struct vnode *vp;
487: struct ufsmount *ump;
488: daddr_t daddr;
489: dev_t dev;
490: int error;
491:
492: ump = VFSTOUFS(mp);
493: dev = ump->um_dev;
494: if ((*vpp = ufs_ihashget(dev, ino)) != NULL)
495: return (0);
496:
497: /* Translate the inode number to a disk address. */
498: fs = ump->um_lfs;
499: if (ino == LFS_IFILE_INUM)
500: daddr = fs->lfs_idaddr;
501: else {
502: LFS_IENTRY(ifp, fs, ino, bp);
503: daddr = ifp->if_daddr;
504: brelse(bp);
505: if (daddr == LFS_UNUSED_DADDR)
506: return (ENOENT);
507: }
508:
509: /* Allocate new vnode/inode. */
510: if (error = lfs_vcreate(mp, ino, &vp)) {
511: *vpp = NULL;
512: return (error);
513: }
514:
515: /*
516: * Put it onto its hash chain and lock it so that other requests for
517: * this inode will block if they arrive while we are sleeping waiting
518: * for old data structures to be purged or for the contents of the
519: * disk portion of this inode to be read.
520: */
521: ip = VTOI(vp);
522: ufs_ihashins(ip);
523:
524: /*
525: * XXX
526: * This may not need to be here, logically it should go down with
527: * the i_devvp initialization.
528: * Ask Kirk.
529: */
530: ip->i_lfs = ump->um_lfs;
531:
532: /* Read in the disk contents for the inode, copy into the inode. */
533: if (error =
534: bread(ump->um_devvp, daddr, (int)fs->lfs_bsize, NOCRED, &bp)) {
535: /*
536: * The inode does not contain anything useful, so it would
537: * be misleading to leave it on its hash chain. With mode
538: * still zero, it will be unlinked and returned to the free
539: * list by vput().
540: */
541: vput(vp);
542: brelse(bp);
543: *vpp = NULL;
544: return (error);
545: }
546: ip->i_din = *lfs_ifind(fs, ino, (struct dinode *)bp->b_data);
547: brelse(bp);
548:
549: /*
550: * Initialize the vnode from the inode, check for aliases. In all
551: * cases re-init ip, the underlying vnode/inode may have changed.
552: */
553: if (error = ufs_vinit(mp, lfs_specop_p, LFS_FIFOOPS, &vp)) {
554: vput(vp);
555: *vpp = NULL;
556: return (error);
557: }
558: /*
559: * Finish inode initialization now that aliasing has been resolved.
560: */
561: ip->i_devvp = ump->um_devvp;
562: VREF(ip->i_devvp);
563: *vpp = vp;
564: return (0);
565: }
566:
567: /*
568: * File handle to vnode
569: *
570: * Have to be really careful about stale file handles:
571: * - check that the inode number is valid
572: * - call lfs_vget() to get the locked inode
573: * - check for an unallocated inode (i_mode == 0)
574: * - check that the given client host has export rights and return
575: * those rights via. exflagsp and credanonp
576: *
577: * XXX
578: * use ifile to see if inode is allocated instead of reading off disk
579: * what is the relationship between my generational number and the NFS
580: * generational number.
581: */
582: int
583: lfs_fhtovp(mp, fhp, nam, vpp, exflagsp, credanonp)
584: register struct mount *mp;
585: struct fid *fhp;
586: struct mbuf *nam;
587: struct vnode **vpp;
588: int *exflagsp;
589: struct ucred **credanonp;
590: {
591: register struct ufid *ufhp;
592:
593: ufhp = (struct ufid *)fhp;
594: if (ufhp->ufid_ino < ROOTINO)
595: return (ESTALE);
596: return (ufs_check_export(mp, ufhp, nam, vpp, exflagsp, credanonp));
597: }
598:
599: /*
600: * Vnode pointer to File handle
601: */
602: /* ARGSUSED */
603: lfs_vptofh(vp, fhp)
604: struct vnode *vp;
605: struct fid *fhp;
606: {
607: register struct inode *ip;
608: register struct ufid *ufhp;
609:
610: ip = VTOI(vp);
611: ufhp = (struct ufid *)fhp;
612: ufhp->ufid_len = sizeof(struct ufid);
613: ufhp->ufid_ino = ip->i_number;
614: ufhp->ufid_gen = ip->i_gen;
615: return (0);
616: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.