static int badnames(const char *n1, const char *n2, const char *n3) { const char *volname; unsigned i, num; struct knowndev *kd; KASSERT(vfs_biglock_do_i_hold()); num = knowndevarray_num(knowndevs); for (i=0; i<num; i++) { kd = knowndevarray_get(knowndevs, i); if (kd->kd_fs) { volname = FSOP_GETVOLNAME(kd->kd_fs); if (samestring3(volname, n1, n2, n3)) { return 1; } } if (samestring3(kd->kd_rawname, n1, n2, n3) || samestring3(kd->kd_name, n1, n2, n3)) { return 1; } } return 0; }
/* * Mount a filesystem. Once we've found the device, call MOUNTFUNC to * set up the filesystem and hand back a struct fs. * * The DATA argument is passed through unchanged to MOUNTFUNC. */ int vfs_mount(const char *devname, void *data, int (*mountfunc)(void *data, struct device *, struct fs **ret)) { const char *volname; struct knowndev *kd; struct fs *fs; int result; vfs_biglock_acquire(); result = findmount(devname, &kd); if (result) { vfs_biglock_release(); return result; } if (kd->kd_fs != NULL) { vfs_biglock_release(); return EBUSY; } KASSERT(kd->kd_rawname != NULL); KASSERT(kd->kd_device != NULL); result = mountfunc(data, kd->kd_device, &fs); if (result) { vfs_biglock_release(); return result; } KASSERT(fs != NULL); kd->kd_fs = fs; volname = FSOP_GETVOLNAME(fs); kprintf("vfs: Mounted %s: on %s\n", volname ? volname : kd->kd_name, kd->kd_name); vfs_biglock_release(); return 0; }
/* * Get current directory, as a pathname. * Use VOP_NAMEFILE to get the pathname and FSOP_GETVOLNAME to get the * volume name. */ int vfs_getcwd(struct uio *uio) { struct vnode *cwd; int result; const char *name; char colon=':'; KASSERT(uio->uio_rw==UIO_READ); result = vfs_getcurdir(&cwd); if (result) { return result; } /* The current dir must be a directory, and thus it is not a device. */ KASSERT(cwd->vn_fs != NULL); name = FSOP_GETVOLNAME(cwd->vn_fs); if (name==NULL) { name = vfs_getdevname(cwd->vn_fs); } KASSERT(name != NULL); result = uiomove((char *)name, strlen(name), uio); if (result) { goto out; } result = uiomove(&colon, 1, uio); if (result) { goto out; } result = VOP_NAMEFILE(cwd, uio); out: VOP_DECREF(cwd); return result; }
/* * Add a new device to the VFS layer's device table. * * If "mountable" is set, the device will be treated as one that expects * to have a filesystem mounted on it, and a raw device will be created * for direct access. */ static int vfs_doadd(const char *dname, int mountable, struct device *dev, struct fs *fs) { char *name=NULL, *rawname=NULL; struct knowndev *kd=NULL; struct vnode *vnode=NULL; const char *volname=NULL; unsigned index; int result; vfs_biglock_acquire(); name = kstrdup(dname); if (name==NULL) { goto nomem; } if (mountable) { rawname = mkrawname(name); if (rawname==NULL) { goto nomem; } } vnode = dev_create_vnode(dev); if (vnode==NULL) { goto nomem; } kd = kmalloc(sizeof(struct knowndev)); if (kd==NULL) { goto nomem; } kd->kd_name = name; kd->kd_rawname = rawname; kd->kd_device = dev; kd->kd_vnode = vnode; kd->kd_fs = fs; if (fs!=NULL) { volname = FSOP_GETVOLNAME(fs); } if (badnames(name, rawname, volname)) { vfs_biglock_release(); return EEXIST; } result = knowndevarray_add(knowndevs, kd, &index); if (result == 0 && dev != NULL) { /* use index+1 as the device number, so 0 is reserved */ dev->d_devnumber = index+1; } vfs_biglock_release(); return result; nomem: if (name) { kfree(name); } if (rawname) { kfree(rawname); } if (vnode) { kfree(vnode); } if (kd) { kfree(kd); } vfs_biglock_release(); return ENOMEM; }
/* * Given a device name (lhd0, emu0, somevolname, null, etc.), hand * back an appropriate vnode. */ int vfs_getroot(const char *devname, struct vnode **ret) { struct knowndev *kd; unsigned i, num; KASSERT(vfs_biglock_do_i_hold()); num = knowndevarray_num(knowndevs); for (i=0; i<num; i++) { kd = knowndevarray_get(knowndevs, i); /* * If this device has a mounted filesystem, and * DEVNAME names either the filesystem or the device, * return the root of the filesystem. * * If it has no mounted filesystem, it's mountable, * and DEVNAME names the device, return ENXIO. */ if (kd->kd_fs!=NULL) { const char *volname; volname = FSOP_GETVOLNAME(kd->kd_fs); if (!strcmp(kd->kd_name, devname) || (volname!=NULL && !strcmp(volname, devname))) { return FSOP_GETROOT(kd->kd_fs, ret); } } else { if (kd->kd_rawname!=NULL && !strcmp(kd->kd_name, devname)) { return ENXIO; } } /* * If DEVNAME names the device, and we get here, it * must have no fs and not be mountable. In this case, * we return the device itself. */ if (!strcmp(kd->kd_name, devname)) { KASSERT(kd->kd_fs==NULL); KASSERT(kd->kd_rawname==NULL); KASSERT(kd->kd_device != NULL); VOP_INCREF(kd->kd_vnode); *ret = kd->kd_vnode; return 0; } /* * If the device has a rawname and DEVNAME names that, * return the device itself. */ if (kd->kd_rawname!=NULL && !strcmp(kd->kd_rawname, devname)) { KASSERT(kd->kd_device != NULL); VOP_INCREF(kd->kd_vnode); *ret = kd->kd_vnode; return 0; } /* * If none of the above tests matched, we didn't name * any of the names of this device, so go on to the * next one. */ } /* * If we got here, the device specified by devname doesn't exist. */ return ENODEV; }