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