|
|
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.