/* * Called for write. Hand off to DEVOP_IO. */ static int dev_write(struct vnode *v, struct uio *uio) { struct device *d = v->vn_data; int result; result = dev_tryseek(d, uio->uio_offset); if (result) { return result; } KASSERT(uio->uio_rw == UIO_WRITE); return DEVOP_IO(d, uio); }
/* * Read or write a block, retrying I/O errors. */ static int sfs_rwblock(struct sfs_fs *sfs, struct uio *uio) { int result; int tries=0; DEBUG(DB_SFS, "sfs: %s %llu\n", uio->uio_rw == UIO_READ ? "read" : "write", uio->uio_offset / SFS_BLOCKSIZE); retry: result = DEVOP_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: DEVOP_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; }