/* * Look for a mountable device named DEVNAME. * Should already hold knowndevs_lock. */ static int findmount(const char *devname, struct knowndev **result) { struct knowndev *dev; unsigned i, num; bool found = false; KASSERT(vfs_biglock_do_i_hold()); num = knowndevarray_num(knowndevs); for (i=0; !found && i<num; i++) { dev = knowndevarray_get(knowndevs, i); if (dev->kd_rawname==NULL) { /* not mountable/unmountable */ continue; } if (!strcmp(devname, dev->kd_name)) { *result = dev; found = true; } } return found ? 0 : ENODEV; }
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; }
/* * Given a filesystem, hand back the name of the device it's mounted on. */ const char * vfs_getdevname(struct fs *fs) { struct knowndev *kd; unsigned i, num; KASSERT(fs != NULL); 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 == fs) { /* * This is not a race condition: as long as the * guy calling us holds a reference to the fs, * the fs cannot go away, and the device can't * go away until the fs goes away. */ return kd->kd_name; } } return NULL; }
int sfs_rwblock(struct sfs_fs *sfs, struct uio *uio) { int result; int tries=0; KASSERT(vfs_biglock_do_i_hold()); DEBUG(DB_SFS, "sfs: %s %llu\n", uio->uio_rw == UIO_READ ? "read" : "write", uio->uio_offset / SFS_BLOCKSIZE); retry: result = sfs->sfs_device->d_io(sfs->sfs_device, uio); if (result == EINVAL) { /* * This means the sector we requested was out of range, * or the seek address we gave wasn't sector-aligned, * or a couple of other things that are our fault. */ panic("sfs: d_io returned EINVAL\n"); } if (result == EIO) { if (tries == 0) { tries++; kprintf("sfs: block %llu I/O error, retrying\n", uio->uio_offset / SFS_BLOCKSIZE); goto retry; } else if (tries < 10) { tries++; goto retry; } else { kprintf("sfs: block %llu I/O error, giving up after " "%d retries\n", uio->uio_offset / SFS_BLOCKSIZE, tries); } } return result; }
/* * 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; }