|
|
1.1 root 1: /*
2: * Copyright (c) 1989 The Regents of the University of California.
3: * All rights reserved.
4: *
5: * Redistribution and use in source and binary forms are permitted provided
6: * that: (1) source distributions retain this entire copyright notice and
7: * comment, and (2) distributions including binaries display the following
8: * acknowledgement: ``This product includes software developed by the
9: * University of California, Berkeley and its contributors'' in the
10: * documentation or other materials provided with the distribution and in
11: * all advertising materials mentioning features or use of this software.
12: * Neither the name of the University nor the names of its contributors may
13: * be used to endorse or promote products derived from this software without
14: * specific prior written permission.
15: * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
16: * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
17: * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
18: *
19: * @(#)ufs_vfsops.c 7.50 (Berkeley) 11/28/90
20: */
21:
22: #include "param.h"
23: #include "systm.h"
24: #include "user.h"
25: #include "proc.h"
26: #include "kernel.h"
27: #include "vnode.h"
28: #include "specdev.h"
29: #include "mount.h"
30: #include "buf.h"
31: #include "file.h"
32: #include "disklabel.h"
33: #include "ioctl.h"
34: #include "errno.h"
35: #include "malloc.h"
36: #include "../ufs/quota.h"
37: #include "../ufs/fs.h"
38: #include "../ufs/ufsmount.h"
39: #include "../ufs/inode.h"
40:
41: /*
42: * ufs vfs operations.
43: */
44: int ufs_mount();
45: int ufs_start();
46: int ufs_unmount();
47: int ufs_root();
48: int ufs_quotactl();
49: int ufs_statfs();
50: int ufs_sync();
51: int ufs_fhtovp();
52: int ufs_vptofh();
53: int ufs_init();
54:
55: struct vfsops ufs_vfsops = {
56: ufs_mount,
57: ufs_start,
58: ufs_unmount,
59: ufs_root,
60: ufs_quotactl,
61: ufs_statfs,
62: ufs_sync,
63: ufs_fhtovp,
64: ufs_vptofh,
65: ufs_init
66: };
67:
68: /*
69: * Called by vfs_mountroot when ufs is going to be mounted as root.
70: *
71: * Name is updated by mount(8) after booting.
72: */
73: #define ROOTNAME "root_device"
74:
75: ufs_mountroot()
76: {
77: register struct mount *mp;
78: extern struct vnode *rootvp;
79: struct ufsmount *ump;
80: register struct fs *fs;
81: u_int size;
82: int error;
83:
84: mp = (struct mount *)malloc((u_long)sizeof(struct mount),
85: M_MOUNT, M_WAITOK);
86: mp->mnt_op = &ufs_vfsops;
87: mp->mnt_flag = MNT_RDONLY;
88: mp->mnt_exroot = 0;
89: mp->mnt_mounth = NULLVP;
90: error = mountfs(rootvp, mp);
91: if (error) {
92: free((caddr_t)mp, M_MOUNT);
93: return (error);
94: }
95: if (error = vfs_lock(mp)) {
96: (void)ufs_unmount(mp, 0);
97: free((caddr_t)mp, M_MOUNT);
98: return (error);
99: }
100: rootfs = mp;
101: mp->mnt_next = mp;
102: mp->mnt_prev = mp;
103: mp->mnt_vnodecovered = NULLVP;
104: ump = VFSTOUFS(mp);
105: fs = ump->um_fs;
106: bzero(fs->fs_fsmnt, sizeof(fs->fs_fsmnt));
107: fs->fs_fsmnt[0] = '/';
108: bcopy((caddr_t)fs->fs_fsmnt, (caddr_t)mp->mnt_stat.f_mntonname,
109: MNAMELEN);
110: (void) copystr(ROOTNAME, mp->mnt_stat.f_mntfromname, MNAMELEN - 1,
111: &size);
112: bzero(mp->mnt_stat.f_mntfromname + size, MNAMELEN - size);
113: (void) ufs_statfs(mp, &mp->mnt_stat);
114: vfs_unlock(mp);
115: inittodr(fs->fs_time);
116: return (0);
117: }
118:
119: /*
120: * VFS Operations.
121: *
122: * mount system call
123: */
124: ufs_mount(mp, path, data, ndp)
125: register struct mount *mp;
126: char *path;
127: caddr_t data;
128: struct nameidata *ndp;
129: {
130: struct vnode *devvp;
131: struct ufs_args args;
132: struct ufsmount *ump;
133: register struct fs *fs;
134: u_int size;
135: int error;
136:
137: if (error = copyin(data, (caddr_t)&args, sizeof (struct ufs_args)))
138: return (error);
139: /*
140: * Process export requests.
141: */
142: if ((args.exflags & MNT_EXPORTED) || (mp->mnt_flag & MNT_EXPORTED)) {
143: if (args.exflags & MNT_EXPORTED)
144: mp->mnt_flag |= MNT_EXPORTED;
145: else
146: mp->mnt_flag &= ~MNT_EXPORTED;
147: if (args.exflags & MNT_EXRDONLY)
148: mp->mnt_flag |= MNT_EXRDONLY;
149: else
150: mp->mnt_flag &= ~MNT_EXRDONLY;
151: mp->mnt_exroot = args.exroot;
152: }
153: if ((mp->mnt_flag & MNT_UPDATE) == 0) {
154: if ((error = getmdev(&devvp, args.fspec, ndp)) != 0)
155: return (error);
156: error = mountfs(devvp, mp);
157: } else {
158: ump = VFSTOUFS(mp);
159: fs = ump->um_fs;
160: if (fs->fs_ronly && (mp->mnt_flag & MNT_RDONLY) == 0)
161: fs->fs_ronly = 0;
162: /*
163: * Verify that the specified device is the one that
164: * is really being used for the root file system.
165: */
166: if (args.fspec == 0)
167: return (0);
168: if ((error = getmdev(&devvp, args.fspec, ndp)) != 0)
169: return (error);
170: if (devvp != ump->um_devvp)
171: error = EINVAL; /* needs translation */
172: else
173: vrele(devvp);
174: }
175: if (error) {
176: vrele(devvp);
177: return (error);
178: }
179: ump = VFSTOUFS(mp);
180: fs = ump->um_fs;
181: (void) copyinstr(path, fs->fs_fsmnt, sizeof(fs->fs_fsmnt) - 1, &size);
182: bzero(fs->fs_fsmnt + size, sizeof(fs->fs_fsmnt) - size);
183: bcopy((caddr_t)fs->fs_fsmnt, (caddr_t)mp->mnt_stat.f_mntonname,
184: MNAMELEN);
185: (void) copyinstr(args.fspec, mp->mnt_stat.f_mntfromname, MNAMELEN - 1,
186: &size);
187: bzero(mp->mnt_stat.f_mntfromname + size, MNAMELEN - size);
188: (void) ufs_statfs(mp, &mp->mnt_stat);
189: return (0);
190: }
191:
192: /*
193: * Common code for mount and mountroot
194: */
195: mountfs(devvp, mp)
196: register struct vnode *devvp;
197: struct mount *mp;
198: {
199: register struct ufsmount *ump = (struct ufsmount *)0;
200: struct buf *bp = NULL;
201: register struct fs *fs;
202: dev_t dev = devvp->v_rdev;
203: struct partinfo dpart;
204: caddr_t base, space;
205: int havepart = 0, blks;
206: int error, i, size;
207: int needclose = 0;
208: int ronly = (mp->mnt_flag & MNT_RDONLY) != 0;
209: extern struct vnode *rootvp;
210:
211: /*
212: * Disallow multiple mounts of the same device.
213: * Disallow mounting of a device that is currently in use
214: * (except for root, which might share swap device for miniroot).
215: * Flush out any old buffers remaining from a previous use.
216: */
217: if (error = mountedon(devvp))
218: return (error);
219: if (vcount(devvp) > 1 && devvp != rootvp)
220: return (EBUSY);
221: vinvalbuf(devvp, 1);
222: if (error = VOP_OPEN(devvp, ronly ? FREAD : FREAD|FWRITE, NOCRED))
223: return (error);
224: needclose = 1;
225: if (VOP_IOCTL(devvp, DIOCGPART, (caddr_t)&dpart, FREAD, NOCRED) != 0) {
226: size = DEV_BSIZE;
227: } else {
228: havepart = 1;
229: size = dpart.disklab->d_secsize;
230: }
231: if (error = bread(devvp, SBLOCK, SBSIZE, NOCRED, &bp))
232: goto out;
233: fs = bp->b_un.b_fs;
234: if (fs->fs_magic != FS_MAGIC || fs->fs_bsize > MAXBSIZE ||
235: fs->fs_bsize < sizeof(struct fs)) {
236: error = EINVAL; /* XXX needs translation */
237: goto out;
238: }
239: ump = (struct ufsmount *)malloc(sizeof *ump, M_UFSMNT, M_WAITOK);
240: ump->um_fs = (struct fs *)malloc((u_long)fs->fs_sbsize, M_SUPERBLK,
241: M_WAITOK);
242: bcopy((caddr_t)bp->b_un.b_addr, (caddr_t)ump->um_fs,
243: (u_int)fs->fs_sbsize);
244: if (fs->fs_sbsize < SBSIZE)
245: bp->b_flags |= B_INVAL;
246: brelse(bp);
247: bp = NULL;
248: fs = ump->um_fs;
249: fs->fs_ronly = ronly;
250: if (ronly == 0)
251: fs->fs_fmod = 1;
252: if (havepart) {
253: dpart.part->p_fstype = FS_BSDFFS;
254: dpart.part->p_fsize = fs->fs_fsize;
255: dpart.part->p_frag = fs->fs_frag;
256: dpart.part->p_cpg = fs->fs_cpg;
257: }
258: blks = howmany(fs->fs_cssize, fs->fs_fsize);
259: base = space = (caddr_t)malloc((u_long)fs->fs_cssize, M_SUPERBLK,
260: M_WAITOK);
261: for (i = 0; i < blks; i += fs->fs_frag) {
262: size = fs->fs_bsize;
263: if (i + fs->fs_frag > blks)
264: size = (blks - i) * fs->fs_fsize;
265: error = bread(devvp, fsbtodb(fs, fs->fs_csaddr + i), size,
266: NOCRED, &bp);
267: if (error) {
268: free((caddr_t)base, M_SUPERBLK);
269: goto out;
270: }
271: bcopy((caddr_t)bp->b_un.b_addr, space, (u_int)size);
272: fs->fs_csp[fragstoblks(fs, i)] = (struct csum *)space;
273: space += size;
274: brelse(bp);
275: bp = NULL;
276: }
277: mp->mnt_data = (qaddr_t)ump;
278: mp->mnt_stat.f_fsid.val[0] = (long)dev;
279: mp->mnt_stat.f_fsid.val[1] = MOUNT_UFS;
280: mp->mnt_flag |= MNT_LOCAL;
281: ump->um_mountp = mp;
282: ump->um_dev = dev;
283: ump->um_devvp = devvp;
284: for (i = 0; i < MAXQUOTAS; i++)
285: ump->um_quotas[i] = NULLVP;
286: devvp->v_specflags |= SI_MOUNTEDON;
287:
288: /* Sanity checks for old file systems. XXX */
289: fs->fs_npsect = MAX(fs->fs_npsect, fs->fs_nsect); /* XXX */
290: fs->fs_interleave = MAX(fs->fs_interleave, 1); /* XXX */
291: if (fs->fs_postblformat == FS_42POSTBLFMT) /* XXX */
292: fs->fs_nrpos = 8; /* XXX */
293: return (0);
294: out:
295: if (bp)
296: brelse(bp);
297: if (needclose)
298: (void) VOP_CLOSE(devvp, ronly ? FREAD : FREAD|FWRITE, NOCRED);
299: if (ump) {
300: free((caddr_t)ump->um_fs, M_SUPERBLK);
301: free((caddr_t)ump, M_UFSMNT);
302: mp->mnt_data = (qaddr_t)0;
303: }
304: return (error);
305: }
306:
307: /*
308: * Make a filesystem operational.
309: * Nothing to do at the moment.
310: */
311: /* ARGSUSED */
312: ufs_start(mp, flags)
313: struct mount *mp;
314: int flags;
315: {
316:
317: return (0);
318: }
319:
320: /*
321: * unmount system call
322: */
323: ufs_unmount(mp, mntflags)
324: struct mount *mp;
325: int mntflags;
326: {
327: register struct ufsmount *ump;
328: register struct fs *fs;
329: int i, error, ronly, flags = 0;
330:
331: if (mntflags & MNT_FORCE)
332: return (EINVAL);
333: if (mntflags & MNT_FORCE)
334: flags |= FORCECLOSE;
335: mntflushbuf(mp, 0);
336: if (mntinvalbuf(mp))
337: return (EBUSY);
338: ump = VFSTOUFS(mp);
339: #ifdef QUOTA
340: if (mp->mnt_flag & MNT_QUOTA) {
341: if (error = vflush(mp, NULLVP, SKIPSYSTEM|flags))
342: return (error);
343: for (i = 0; i < MAXQUOTAS; i++) {
344: if (ump->um_quotas[i] == NULLVP)
345: continue;
346: quotaoff(mp, i);
347: }
348: /*
349: * Here we fall through to vflush again to ensure
350: * that we have gotten rid of all the system vnodes.
351: */
352: }
353: #endif
354: if (error = vflush(mp, NULLVP, flags))
355: return (error);
356: fs = ump->um_fs;
357: ronly = !fs->fs_ronly;
358: ump->um_devvp->v_specflags &= ~SI_MOUNTEDON;
359: error = VOP_CLOSE(ump->um_devvp, ronly ? FREAD : FREAD|FWRITE, NOCRED);
360: vrele(ump->um_devvp);
361: free((caddr_t)fs->fs_csp[0], M_SUPERBLK);
362: free((caddr_t)fs, M_SUPERBLK);
363: free((caddr_t)ump, M_UFSMNT);
364: mp->mnt_data = (qaddr_t)0;
365: mp->mnt_flag &= ~MNT_LOCAL;
366: return (error);
367: }
368:
369: /*
370: * Check to see if a filesystem is mounted on a block device.
371: */
372: mountedon(vp)
373: register struct vnode *vp;
374: {
375: register struct vnode *vq;
376:
377: if (vp->v_specflags & SI_MOUNTEDON)
378: return (EBUSY);
379: if (vp->v_flag & VALIASED) {
380: for (vq = *vp->v_hashchain; vq; vq = vq->v_specnext) {
381: if (vq->v_rdev != vp->v_rdev ||
382: vq->v_type != vp->v_type)
383: continue;
384: if (vq->v_specflags & SI_MOUNTEDON)
385: return (EBUSY);
386: }
387: }
388: return (0);
389: }
390:
391: /*
392: * Return root of a filesystem
393: */
394: ufs_root(mp, vpp)
395: struct mount *mp;
396: struct vnode **vpp;
397: {
398: register struct inode *ip;
399: struct inode *nip;
400: struct vnode tvp;
401: int error;
402:
403: tvp.v_mount = mp;
404: ip = VTOI(&tvp);
405: ip->i_vnode = &tvp;
406: ip->i_dev = VFSTOUFS(mp)->um_dev;
407: error = iget(ip, (ino_t)ROOTINO, &nip);
408: if (error)
409: return (error);
410: *vpp = ITOV(nip);
411: return (0);
412: }
413:
414: /*
415: * Do operations associated with quotas
416: */
417: ufs_quotactl(mp, cmds, uid, arg)
418: struct mount *mp;
419: int cmds;
420: uid_t uid;
421: caddr_t arg;
422: {
423: register struct nameidata *ndp = &u.u_nd;
424: struct ufsmount *ump = VFSTOUFS(mp);
425: struct proc *p = u.u_procp; /* XXX */
426: int cmd, type, error;
427:
428: #ifndef QUOTA
429: return (EOPNOTSUPP);
430: #else
431: if (uid == -1)
432: uid = p->p_ruid;
433: cmd = cmds >> SUBCMDSHIFT;
434:
435: switch (cmd) {
436: case Q_GETQUOTA:
437: case Q_SYNC:
438: if (uid == p->p_ruid)
439: break;
440: /* fall through */
441: default:
442: if (error = suser(ndp->ni_cred, &u.u_acflag))
443: return (error);
444: }
445:
446: type = cmd & SUBCMDMASK;
447: if ((u_int)type >= MAXQUOTAS)
448: return (EINVAL);
449:
450: switch (cmd) {
451:
452: case Q_QUOTAON:
453: return (quotaon(ndp, mp, type, arg));
454:
455: case Q_QUOTAOFF:
456: if (vfs_busy(mp))
457: return (0);
458: error = quotaoff(mp, type);
459: vfs_unbusy(mp);
460: return (error);
461:
462: case Q_SETQUOTA:
463: return (setquota(mp, uid, type, arg));
464:
465: case Q_SETUSE:
466: return (setuse(mp, uid, type, arg));
467:
468: case Q_GETQUOTA:
469: return (getquota(mp, uid, type, arg));
470:
471: case Q_SYNC:
472: if (vfs_busy(mp))
473: return (0);
474: error = qsync(mp);
475: vfs_unbusy(mp);
476: return (error);
477:
478: default:
479: return (EINVAL);
480: }
481: /* NOTREACHED */
482: #endif
483: }
484:
485: /*
486: * Get file system statistics.
487: */
488: ufs_statfs(mp, sbp)
489: struct mount *mp;
490: register struct statfs *sbp;
491: {
492: register struct ufsmount *ump;
493: register struct fs *fs;
494:
495: ump = VFSTOUFS(mp);
496: fs = ump->um_fs;
497: if (fs->fs_magic != FS_MAGIC)
498: panic("ufs_statfs");
499: sbp->f_type = MOUNT_UFS;
500: sbp->f_fsize = fs->fs_fsize;
501: sbp->f_bsize = fs->fs_bsize;
502: sbp->f_blocks = fs->fs_dsize;
503: sbp->f_bfree = fs->fs_cstotal.cs_nbfree * fs->fs_frag +
504: fs->fs_cstotal.cs_nffree;
505: sbp->f_bavail = (fs->fs_dsize * (100 - fs->fs_minfree) / 100) -
506: (fs->fs_dsize - sbp->f_bfree);
507: sbp->f_files = fs->fs_ncg * fs->fs_ipg - ROOTINO;
508: sbp->f_ffree = fs->fs_cstotal.cs_nifree;
509: if (sbp != &mp->mnt_stat) {
510: bcopy((caddr_t)mp->mnt_stat.f_mntonname,
511: (caddr_t)&sbp->f_mntonname[0], MNAMELEN);
512: bcopy((caddr_t)mp->mnt_stat.f_mntfromname,
513: (caddr_t)&sbp->f_mntfromname[0], MNAMELEN);
514: }
515: return (0);
516: }
517:
518: int syncprt = 0;
519:
520: /*
521: * Go through the disk queues to initiate sandbagged IO;
522: * go through the inodes to write those that have been modified;
523: * initiate the writing of the super block if it has been modified.
524: *
525: * Note: we are always called with the filesystem marked `MPBUSY'.
526: */
527: ufs_sync(mp, waitfor)
528: struct mount *mp;
529: int waitfor;
530: {
531: register struct vnode *vp;
532: register struct inode *ip;
533: register struct ufsmount *ump = VFSTOUFS(mp);
534: register struct fs *fs;
535: int error, allerror = 0;
536:
537: if (syncprt)
538: bufstats();
539: fs = ump->um_fs;
540: /*
541: * Write back modified superblock.
542: * Consistency check that the superblock
543: * is still in the buffer cache.
544: */
545: if (fs->fs_fmod != 0) {
546: if (fs->fs_ronly != 0) { /* XXX */
547: printf("fs = %s\n", fs->fs_fsmnt);
548: panic("update: rofs mod");
549: }
550: fs->fs_fmod = 0;
551: fs->fs_time = time.tv_sec;
552: allerror = sbupdate(ump, waitfor);
553: }
554: /*
555: * Write back each (modified) inode.
556: */
557: loop:
558: for (vp = mp->mnt_mounth; vp; vp = vp->v_mountf) {
559: /*
560: * If the vnode that we are about to sync is no longer
561: * associated with this mount point, start over.
562: */
563: if (vp->v_mount != mp)
564: goto loop;
565: ip = VTOI(vp);
566: if ((ip->i_flag & (IMOD|IACC|IUPD|ICHG)) == 0 &&
567: vp->v_dirtyblkhd == NULL)
568: continue;
569: if (vget(vp))
570: goto loop;
571: if (vp->v_dirtyblkhd)
572: vflushbuf(vp, 0);
573: if ((ip->i_flag & (IMOD|IACC|IUPD|ICHG)) &&
574: (error = iupdat(ip, &time, &time, 0)))
575: allerror = error;
576: vput(vp);
577: }
578: /*
579: * Force stale file system control information to be flushed.
580: */
581: vflushbuf(ump->um_devvp, waitfor == MNT_WAIT ? B_SYNC : 0);
582: #ifdef QUOTA
583: qsync(mp);
584: #endif
585: return (allerror);
586: }
587:
588: /*
589: * Write a superblock and associated information back to disk.
590: */
591: sbupdate(mp, waitfor)
592: struct ufsmount *mp;
593: int waitfor;
594: {
595: register struct fs *fs = mp->um_fs;
596: register struct buf *bp;
597: int blks;
598: caddr_t space;
599: int i, size, error = 0;
600:
601: bp = getblk(mp->um_devvp, SBLOCK, (int)fs->fs_sbsize);
602: bcopy((caddr_t)fs, bp->b_un.b_addr, (u_int)fs->fs_sbsize);
603: /* Restore compatibility to old file systems. XXX */
604: if (fs->fs_postblformat == FS_42POSTBLFMT) /* XXX */
605: bp->b_un.b_fs->fs_nrpos = -1; /* XXX */
606: if (waitfor == MNT_WAIT)
607: error = bwrite(bp);
608: else
609: bawrite(bp);
610: blks = howmany(fs->fs_cssize, fs->fs_fsize);
611: space = (caddr_t)fs->fs_csp[0];
612: for (i = 0; i < blks; i += fs->fs_frag) {
613: size = fs->fs_bsize;
614: if (i + fs->fs_frag > blks)
615: size = (blks - i) * fs->fs_fsize;
616: bp = getblk(mp->um_devvp, fsbtodb(fs, fs->fs_csaddr + i), size);
617: bcopy(space, bp->b_un.b_addr, (u_int)size);
618: space += size;
619: if (waitfor == MNT_WAIT)
620: error = bwrite(bp);
621: else
622: bawrite(bp);
623: }
624: return (error);
625: }
626:
627: /*
628: * Print out statistics on the current allocation of the buffer pool.
629: * Can be enabled to print out on every ``sync'' by setting "syncprt"
630: * above.
631: */
632: bufstats()
633: {
634: int s, i, j, count;
635: register struct buf *bp, *dp;
636: int counts[MAXBSIZE/CLBYTES+1];
637: static char *bname[BQUEUES] = { "LOCKED", "LRU", "AGE", "EMPTY" };
638:
639: for (bp = bfreelist, i = 0; bp < &bfreelist[BQUEUES]; bp++, i++) {
640: count = 0;
641: for (j = 0; j <= MAXBSIZE/CLBYTES; j++)
642: counts[j] = 0;
643: s = splbio();
644: for (dp = bp->av_forw; dp != bp; dp = dp->av_forw) {
645: counts[dp->b_bufsize/CLBYTES]++;
646: count++;
647: }
648: splx(s);
649: printf("%s: total-%d", bname[i], count);
650: for (j = 0; j <= MAXBSIZE/CLBYTES; j++)
651: if (counts[j] != 0)
652: printf(", %d-%d", j * CLBYTES, counts[j]);
653: printf("\n");
654: }
655: }
656:
657: /*
658: * File handle to vnode
659: *
660: * Have to be really careful about stale file handles:
661: * - check that the inode number is in range
662: * - call iget() to get the locked inode
663: * - check for an unallocated inode (i_mode == 0)
664: * - check that the generation number matches
665: */
666: ufs_fhtovp(mp, fhp, vpp)
667: register struct mount *mp;
668: struct fid *fhp;
669: struct vnode **vpp;
670: {
671: register struct ufid *ufhp;
672: register struct fs *fs;
673: register struct inode *ip;
674: struct inode *nip;
675: struct vnode tvp;
676: int error;
677:
678: ufhp = (struct ufid *)fhp;
679: fs = VFSTOUFS(mp)->um_fs;
680: if (ufhp->ufid_ino < ROOTINO ||
681: ufhp->ufid_ino >= fs->fs_ncg * fs->fs_ipg) {
682: *vpp = NULLVP;
683: return (EINVAL);
684: }
685: tvp.v_mount = mp;
686: ip = VTOI(&tvp);
687: ip->i_vnode = &tvp;
688: ip->i_dev = VFSTOUFS(mp)->um_dev;
689: if (error = iget(ip, ufhp->ufid_ino, &nip)) {
690: *vpp = NULLVP;
691: return (error);
692: }
693: ip = nip;
694: if (ip->i_mode == 0) {
695: iput(ip);
696: *vpp = NULLVP;
697: return (EINVAL);
698: }
699: if (ip->i_gen != ufhp->ufid_gen) {
700: iput(ip);
701: *vpp = NULLVP;
702: return (EINVAL);
703: }
704: *vpp = ITOV(ip);
705: return (0);
706: }
707:
708: /*
709: * Vnode pointer to File handle
710: */
711: /* ARGSUSED */
712: ufs_vptofh(vp, fhp)
713: struct vnode *vp;
714: struct fid *fhp;
715: {
716: register struct inode *ip = VTOI(vp);
717: register struct ufid *ufhp;
718:
719: ufhp = (struct ufid *)fhp;
720: ufhp->ufid_len = sizeof(struct ufid);
721: ufhp->ufid_ino = ip->i_number;
722: ufhp->ufid_gen = ip->i_gen;
723: return (0);
724: }
725:
726: /*
727: * Check that the user's argument is a reasonable
728: * thing on which to mount, and return the device number if so.
729: */
730: getmdev(devvpp, fname, ndp)
731: struct vnode **devvpp;
732: caddr_t fname;
733: register struct nameidata *ndp;
734: {
735: register struct vnode *vp;
736: int error;
737:
738: ndp->ni_nameiop = LOOKUP | FOLLOW;
739: ndp->ni_segflg = UIO_USERSPACE;
740: ndp->ni_dirp = fname;
741: if (error = namei(ndp))
742: return (error);
743: vp = ndp->ni_vp;
744: if (vp->v_type != VBLK) {
745: vrele(vp);
746: return (ENOTBLK);
747: }
748: if (major(vp->v_rdev) >= nblkdev) {
749: vrele(vp);
750: return (ENXIO);
751: }
752: *devvpp = vp;
753: return (0);
754: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.