|
|
1.1 root 1: #include "param.h"
2: #include "systm.h"
3: #include "namei.h"
4: #include "proc.h"
5: #include "kernel.h"
6: #include "vnode.h"
7: #include "specdev.h"
8: #include "mount.h"
9: #include "buf.h"
10: #include "file.h"
11: #include "dkbad.h"
12: #include "disklabel.h"
13: #include "ioctl.h"
14: #include "errno.h"
15: #include "malloc.h"
16:
17: #include "iso.h"
18: #include "isofs_node.h"
19:
20: extern int enodev ();
21:
22: struct vfsops isofs_vfsops = {
23: isofs_mount,
24: isofs_start,
25: isofs_unmount,
26: isofs_root,
27: (void *)enodev, /* quotactl */
28: isofs_statfs,
29: isofs_sync,
30: isofs_fhtovp,
31: isofs_vptofh,
32: isofs_init
33: };
34:
35: /*
36: * Called by vfs_mountroot when ufs is going to be mounted as root.
37: *
38: * Name is updated by mount(8) after booting.
39: */
40: #define ROOTNAME "root_device"
41:
42: isofs_mountroot()
43: {
44: register struct mount *mp;
45: extern struct vnode *rootvp;
46: struct proc *p = curproc; /* XXX */
47: struct iso_mnt *imp;
48: register struct fs *fs;
49: u_int size;
50: int error;
51:
52: mp = (struct mount *)malloc((u_long)sizeof(struct mount),
53: M_MOUNT, M_WAITOK);
54: mp->mnt_op = &isofs_vfsops;
55: mp->mnt_flag = MNT_RDONLY;
56: mp->mnt_exroot = 0;
57: mp->mnt_mounth = NULLVP;
58: error = iso_mountfs(rootvp, mp, p);
59: if (error) {
60: free((caddr_t)mp, M_MOUNT);
61: return (error);
62: }
63: if (error = vfs_lock(mp)) {
64: (void)isofs_unmount(mp, 0, p);
65: free((caddr_t)mp, M_MOUNT);
66: return (error);
67: }
68: rootfs = mp;
69: mp->mnt_next = mp;
70: mp->mnt_prev = mp;
71: mp->mnt_vnodecovered = NULLVP;
72: imp = VFSTOISOFS(mp);
73: bzero(imp->im_fsmnt, sizeof(imp->im_fsmnt));
74: imp->im_fsmnt[0] = '/';
75: bcopy((caddr_t)imp->im_fsmnt, (caddr_t)mp->mnt_stat.f_mntonname,
76: MNAMELEN);
77: (void) copystr(ROOTNAME, mp->mnt_stat.f_mntfromname, MNAMELEN - 1,
78: &size);
79: bzero(mp->mnt_stat.f_mntfromname + size, MNAMELEN - size);
80: (void) isofs_statfs(mp, &mp->mnt_stat, p);
81: vfs_unlock(mp);
82: return (0);
83: }
84:
85: /*
86: * Flag to allow forcible unmounting.
87: */
88: int iso_doforce = 1;
89:
90: /*
91: * VFS Operations.
92: *
93: * mount system call
94: */
95: isofs_mount(mp, path, data, ndp, p)
96: register struct mount *mp;
97: char *path;
98: caddr_t data;
99: struct nameidata *ndp;
100: struct proc *p;
101: {
102: struct vnode *devvp;
103: struct ufs_args args;
104: u_int size;
105: int error;
106: struct iso_mnt *imp;
107:
108: if (error = copyin(data, (caddr_t)&args, sizeof (struct ufs_args)))
109: return (error);
110:
111: if ((mp->mnt_flag & MNT_RDONLY) == 0)
112: return (EROFS);
113:
114: /*
115: * Process export requests.
116: */
117: if ((args.exflags & MNT_EXPORTED) || (mp->mnt_flag & MNT_EXPORTED)) {
118: if (args.exflags & MNT_EXPORTED)
119: mp->mnt_flag |= MNT_EXPORTED;
120: else
121: mp->mnt_flag &= ~MNT_EXPORTED;
122: if (args.exflags & MNT_EXRDONLY)
123: mp->mnt_flag |= MNT_EXRDONLY;
124: else
125: mp->mnt_flag &= ~MNT_EXRDONLY;
126: mp->mnt_exroot = args.exroot;
127: }
128: /*
129: * If updating, check whether changing from read-only to
130: * read/write; if there is no device name, that's all we do.
131: */
132: if (mp->mnt_flag & MNT_UPDATE) {
133: imp = VFSTOISOFS(mp);
134: if (args.fspec == 0)
135: return (0);
136: }
137: /*
138: * Not an update, or updating the name: look up the name
139: * and verify that it refers to a sensible block device.
140: */
141: ndp->ni_nameiop = LOOKUP | FOLLOW;
142: ndp->ni_segflg = UIO_USERSPACE;
143: ndp->ni_dirp = args.fspec;
144: if (error = namei(ndp, p))
145: return (error);
146: devvp = ndp->ni_vp;
147: if (devvp->v_type != VBLK) {
148: vrele(devvp);
149: return (ENOTBLK);
150: }
151: if (major(devvp->v_rdev) >= nblkdev) {
152: vrele(devvp);
153: return (ENXIO);
154: }
155:
156: if ((mp->mnt_flag & MNT_UPDATE) == 0)
157: error = iso_mountfs(devvp, mp, p);
158: else {
159: if (devvp != imp->im_devvp)
160: error = EINVAL; /* needs translation */
161: else
162: vrele(devvp);
163: }
164: if (error) {
165: vrele(devvp);
166: return (error);
167: }
168: imp = VFSTOISOFS(mp);
169: (void) copyinstr(path, imp->im_fsmnt, sizeof(imp->im_fsmnt)-1, &size);
170: bzero(imp->im_fsmnt + size, sizeof(imp->im_fsmnt) - size);
171: bcopy((caddr_t)imp->im_fsmnt, (caddr_t)mp->mnt_stat.f_mntonname,
172: MNAMELEN);
173: (void) copyinstr(args.fspec, mp->mnt_stat.f_mntfromname, MNAMELEN - 1,
174: &size);
175: bzero(mp->mnt_stat.f_mntfromname + size, MNAMELEN - size);
176: (void) isofs_statfs(mp, &mp->mnt_stat, p);
177: return (0);
178: }
179:
180: /*
181: * Common code for mount and mountroot
182: */
183: iso_mountfs(devvp, mp, p)
184: register struct vnode *devvp;
185: struct mount *mp;
186: struct proc *p;
187: {
188: register struct iso_mnt *isomp = (struct iso_mnt *)0;
189: struct buf *bp = NULL;
190: dev_t dev = devvp->v_rdev;
191: caddr_t base, space;
192: int havepart = 0, blks;
193: int error = EINVAL, i, size;
194: int needclose = 0;
195: int ronly = (mp->mnt_flag & MNT_RDONLY) != 0;
196: extern struct vnode *rootvp;
197: int j;
198: int iso_bsize;
199: int iso_blknum;
200: struct iso_volume_descriptor *vdp;
201: struct iso_primary_descriptor *pri;
202: struct iso_directory_record *rootp;
203: int logical_block_size;
204:
205: if (!ronly)
206: return (EROFS);
207:
208: /*
209: * Disallow multiple mounts of the same device.
210: * Disallow mounting of a device that is currently in use
211: * (except for root, which might share swap device for miniroot).
212: * Flush out any old buffers remaining from a previous use.
213: */
214: if (error = iso_mountedon(devvp))
215: return (error);
216: if (vcount(devvp) > 1 && devvp != rootvp)
217: return (EBUSY);
218: vinvalbuf(devvp, 1);
219: if (error = VOP_OPEN(devvp, ronly ? FREAD : FREAD|FWRITE, NOCRED, p))
220: return (error);
221: needclose = 1;
222:
223: /* This is the "logical sector size". The standard says this
224: * should be 2048 or the physical sector size on the device,
225: * whichever is greater. For now, we'll just use a constant.
226: */
227: iso_bsize = 2048;
228:
229: for (iso_blknum = 16; iso_blknum < 100; iso_blknum++) {
230: if (error = bread (devvp, iso_blknum * iso_bsize / DEV_BSIZE,
231: iso_bsize, NOCRED, &bp))
232: goto out;
233:
234: vdp = (struct iso_volume_descriptor *)bp->b_un.b_addr;
235: if (bcmp (vdp->id, ISO_STANDARD_ID, sizeof vdp->id) != 0) {
236: error = EINVAL;
237: goto out;
238: }
239:
240: if (isonum_711 (vdp->type) == ISO_VD_END) {
241: error = EINVAL;
242: goto out;
243: }
244:
245: if (isonum_711 (vdp->type) == ISO_VD_PRIMARY)
246: break;
247: brelse(bp);
248: }
249:
250: if (isonum_711 (vdp->type) != ISO_VD_PRIMARY) {
251: error = EINVAL;
252: goto out;
253: }
254:
255: pri = (struct iso_primary_descriptor *)vdp;
256:
257: logical_block_size = isonum_723 (pri->logical_block_size);
258:
259: if (logical_block_size < DEV_BSIZE
260: || logical_block_size >= MAXBSIZE
261: || (logical_block_size & (logical_block_size - 1)) != 0) {
262: error = EINVAL;
263: goto out;
264: }
265:
266: rootp = (struct iso_directory_record *)pri->root_directory_record;
267:
268: isomp = (struct iso_mnt *)malloc(sizeof *isomp,M_UFSMNT,M_WAITOK);
269: isomp->logical_block_size = logical_block_size;
270: isomp->volume_space_size = isonum_733 (pri->volume_space_size);
271: bcopy (rootp, isomp->root, sizeof isomp->root);
272: isomp->root_extent = isonum_733 (rootp->extent);
273: isomp->root_size = isonum_733 (rootp->size);
274:
275: isomp->im_bsize = logical_block_size;
276: isomp->im_bmask = ~(isomp->im_bsize - 1);
277: isomp->im_bshift = 0;
278: while ((1 << isomp->im_bshift) < isomp->im_bsize)
279: isomp->im_bshift++;
280:
281: bp->b_flags |= B_INVAL;
282: brelse(bp);
283: bp = NULL;
284:
285: isomp->im_ronly = ronly;
286: if (ronly == 0)
287: isomp->im_fmod = 1;
288:
289: mp->mnt_data = (qaddr_t)isomp;
290: mp->mnt_stat.f_fsid.val[0] = (long)dev;
291: mp->mnt_stat.f_fsid.val[1] = MOUNT_ISOFS;
292: mp->mnt_flag |= MNT_LOCAL;
293: isomp->im_mountp = mp;
294: isomp->im_dev = dev;
295: isomp->im_devvp = devvp;
296:
297: devvp->v_specflags |= SI_MOUNTEDON;
298:
299: return (0);
300: out:
301: if (bp)
302: brelse(bp);
303: if (needclose)
304: (void)VOP_CLOSE(devvp, ronly ? FREAD : FREAD|FWRITE, NOCRED, p);
305: if (isomp) {
306: free((caddr_t)isomp, M_UFSMNT);
307: mp->mnt_data = (qaddr_t)0;
308: }
309: return (error);
310: }
311:
312: /*
313: * Make a filesystem operational.
314: * Nothing to do at the moment.
315: */
316: /* ARGSUSED */
317: isofs_start(mp, flags, p)
318: struct mount *mp;
319: int flags;
320: struct proc *p;
321: {
322:
323: return (0);
324: }
325:
326: /*
327: * unmount system call
328: */
329: isofs_unmount(mp, mntflags, p)
330: struct mount *mp;
331: int mntflags;
332: struct proc *p;
333: {
334: register struct iso_mnt *isomp;
335: int i, error, ronly, flags = 0;
336:
337: if (mntflags & MNT_FORCE) {
338: if (!iso_doforce || mp == rootfs)
339: return (EINVAL);
340: flags |= FORCECLOSE;
341: }
342: mntflushbuf(mp, 0);
343: if (mntinvalbuf(mp))
344: return (EBUSY);
345: isomp = VFSTOISOFS(mp);
346:
347: if (error = vflush(mp, NULLVP, flags))
348: return (error);
349: ronly = !isomp->im_ronly;
350: isomp->im_devvp->v_specflags &= ~SI_MOUNTEDON;
351: error = VOP_CLOSE(isomp->im_devvp, ronly ? FREAD : FREAD|FWRITE,
352: NOCRED, p);
353: vrele(isomp->im_devvp);
354: free((caddr_t)isomp, M_UFSMNT);
355: mp->mnt_data = (qaddr_t)0;
356: mp->mnt_flag &= ~MNT_LOCAL;
357: return (error);
358: }
359:
360: /*
361: * Check to see if a filesystem is mounted on a block device.
362: */
363: iso_mountedon(vp)
364: register struct vnode *vp;
365: {
366: register struct vnode *vq;
367:
368: if (vp->v_specflags & SI_MOUNTEDON)
369: return (EBUSY);
370: if (vp->v_flag & VALIASED) {
371: for (vq = *vp->v_hashchain; vq; vq = vq->v_specnext) {
372: if (vq->v_rdev != vp->v_rdev ||
373: vq->v_type != vp->v_type)
374: continue;
375: if (vq->v_specflags & SI_MOUNTEDON)
376: return (EBUSY);
377: }
378: }
379: return (0);
380: }
381:
382: /*
383: * Return root of a filesystem
384: */
385: isofs_root(mp, vpp)
386: struct mount *mp;
387: struct vnode **vpp;
388: {
389: register struct iso_node *ip;
390: struct iso_node *nip;
391: struct vnode tvp;
392: int error;
393: struct iso_mnt *imp = VFSTOISOFS (mp);
394:
395: tvp.v_mount = mp;
396: ip = VTOI(&tvp);
397: ip->i_vnode = &tvp;
398: ip->i_dev = imp->im_dev;
399: error = iso_iget(ip, imp->root_extent, &nip,
400: (struct iso_directory_record *) imp->root);
401: if (error)
402: return (error);
403: *vpp = ITOV(nip);
404: return (0);
405: }
406:
407: /*
408: * Get file system statistics.
409: */
410: isofs_statfs(mp, sbp, p)
411: struct mount *mp;
412: register struct statfs *sbp;
413: struct proc *p;
414: {
415: register struct iso_mnt *isomp;
416: register struct fs *fs;
417:
418: isomp = VFSTOISOFS(mp);
419:
420: sbp->f_type = MOUNT_ISOFS;
421: sbp->f_fsize = isomp->logical_block_size;
422: sbp->f_bsize = sbp->f_fsize;
423: sbp->f_blocks = isomp->volume_space_size;
424: sbp->f_bfree = 0; /* total free blocks */
425: sbp->f_bavail = 0; /* blocks free for non superuser */
426: sbp->f_files = 0; /* total files */
427: sbp->f_ffree = 0; /* free file nodes */
428: if (sbp != &mp->mnt_stat) {
429: bcopy((caddr_t)mp->mnt_stat.f_mntonname,
430: (caddr_t)&sbp->f_mntonname[0], MNAMELEN);
431: bcopy((caddr_t)mp->mnt_stat.f_mntfromname,
432: (caddr_t)&sbp->f_mntfromname[0], MNAMELEN);
433: }
434: return (0);
435: }
436:
437: isofs_sync(mp, waitfor)
438: struct mount *mp;
439: int waitfor;
440: {
441: return (0);
442: }
443:
444: /*
445: * File handle to vnode
446: *
447: * Have to be really careful about stale file handles:
448: * - check that the inode number is in range
449: * - call iget() to get the locked inode
450: * - check for an unallocated inode (i_mode == 0)
451: * - check that the generation number matches
452: */
453: isofs_fhtovp(mp, fhp, vpp)
454: register struct mount *mp;
455: struct fid *fhp;
456: struct vnode **vpp;
457: {
458: return (EINVAL);
459: #if 0
460: /* here's a guess at what we need here */
461: struct vnode tvp;
462: int error;
463:
464: ifhp = (struct ifid *)fhp;
465: imp = VFSTOISOFS (mp);
466:
467: if (ifhp->ifid_lbn >= imp->volume_space_size)
468: return (EINVAL);
469:
470: if (ifhp->ifid_offset + sizeof (struct iso_directory_record)
471: >= imp->im_bsize)
472: return (EINVAL);
473:
474: bread (isomp->im_devvp, ifhp->ifid_lbn, imp->im_bsize, NOCRED, &bp);
475:
476: dirp = bp->b_un.b_addr + ifhp->ifid_offset;
477:
478: if (ifhp->ifid_offset + isonum_711 (dirp) >= imp->im_bsize) {
479: brelse (bp);
480: return (EINVAL);
481: }
482:
483: tvp.v_mount = mp;
484: ip = VTOI(&tvp);
485: ip->i_vnode = &tvp;
486: ip->i_dev = imp->im_dev;
487: if (error = iso_iget(ip, ifhp->ifid_ino, &nip, dirp)) {
488: *vpp = NULLVP;
489: brelse (bp);
490: return (error);
491: }
492: ip = nip;
493: *vpp = ITOV(ip);
494: brelse (bp);
495: return (0);
496: #endif
497: }
498:
499: /*
500: * Vnode pointer to File handle
501: */
502: /* ARGSUSED */
503: isofs_vptofh(vp, fhp)
504: struct vnode *vp;
505: struct fid *fhp;
506: {
507: return (EINVAL);
508: #if 0
509: register struct inode *ip = VTOI(vp);
510: register struct ufid *ufhp;
511:
512: ufhp = (struct ufid *)fhp;
513: ufhp->ufid_len = sizeof(struct ufid);
514: ufhp->ufid_ino = ip->i_number;
515: ufhp->ufid_gen = ip->i_gen;
516: return (0);
517: #endif
518: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.