Exemple #1
0
int
sfs_wblock(struct sfs_fs *sfs, void *data, u_int32_t block)
{
	struct uio ku;
	SFSUIO(&ku, data, block, UIO_WRITE);
	return sfs_rwblock(sfs, &ku);
}
Exemple #2
0
int
sfs_rblock(struct sfs_fs *sfs, void *data, uint32_t block)
{
	struct iovec iov;
	struct uio ku;

	SFSUIO(&iov, &ku, data, block, UIO_READ);
	return sfs_rwblock(sfs, &ku);
}
Exemple #3
0
/*
 * Read a block.
 */
int
sfs_readblock(struct fs *fs, daddr_t block, void *data, size_t len)
{
	struct sfs_fs *sfs = fs->fs_data;
	struct iovec iov;
	struct uio ku;

	KASSERT(len == SFS_BLOCKSIZE);

	SFSUIO(&iov, &ku, data, block, UIO_READ);
	return sfs_rwblock(sfs, &ku);
}
Exemple #4
0
/*
 * Do I/O (either read or write) of a single whole block.
 */
static
int
sfs_blockio(struct sfs_vnode *sv, struct uio *uio)
{
	struct sfs_fs *sfs = sv->sv_v.vn_fs->fs_data;
	u_int32_t diskblock;
	u_int32_t fileblock;
	int result;
	int doalloc = (uio->uio_rw==UIO_WRITE);
	off_t saveoff;
	off_t diskoff;
	off_t saveres;
	off_t diskres;

	/* Get the block number within the file */
	fileblock = uio->uio_offset / SFS_BLOCKSIZE;

	/* Look up the disk block number */
	result = sfs_bmap(sv, fileblock, doalloc, &diskblock);
	if (result) {
		return result;
	}

	if (diskblock == 0) {
		/*
		 * No block - fill with zeros.
		 *
		 * We must be reading, or sfs_bmap would have
		 * allocated a block for us.
		 */
		assert(uio->uio_rw == UIO_READ);
		return uiomovezeros(SFS_BLOCKSIZE, uio);
	}

	/*
	 * Do the I/O directly to the uio region. Save the uio_offset,
	 * and substitute one that makes sense to the device.
	 */
	saveoff = uio->uio_offset;
	diskoff = diskblock * SFS_BLOCKSIZE;
	uio->uio_offset = diskoff;

	/*
	 * Temporarily set the residue to be one block size.
	 */
	assert(uio->uio_resid >= SFS_BLOCKSIZE);
	saveres = uio->uio_resid;
	diskres = SFS_BLOCKSIZE;
	uio->uio_resid = diskres;
	
	result = sfs_rwblock(sfs, uio);

	/*
	 * Now, restore the original uio_offset and uio_resid and update 
	 * them by the amount of I/O done.
	 */
	uio->uio_offset = (uio->uio_offset - diskoff) + saveoff;
	uio->uio_resid = (uio->uio_resid - diskres) + saveres;

	return result;
}
Exemple #5
0
/*
 * Write a block.
 */
int
sfs_writeblock(struct fs *fs, daddr_t block, void *fsbufdata,
	       void *data, size_t len)
{
	struct sfs_fs *sfs = fs->fs_data;
	struct iovec iov;
	struct uio ku;
	bool isjournal;
	int result;
	struct b_fsdata* b_fsdata = (struct b_fsdata*)fsbufdata;

	KASSERT(len == SFS_BLOCKSIZE);

	isjournal = sfs_block_is_journal(sfs, block);
	//kprintf("Writeblock metadata: %p\n", fsbufdata);

	if (isjournal) {
		/*
		 * We're writing a journal buffer; the journal must be
		 * written in order, so all earlier journal buffers
		 * must be written first.
		 *
		 * One might think that a good and simple way to flush
		 * the journal in order is to have each journal buffer
		 * record that the previous journal buffer must be
		 * written out before it. Then writing a journal
		 * buffer will come here to write the previous one,
		 * which will come here to write the previous one, and
		 * so on until we get to the first remaining unwritten
		 * journal buffer. This doesn't work: it runs off the
		 * kernel stack. Also, it's likely to deadlock.
		 *
		 * Instead, we use special-case logic in the journal
		 * code for this situation.
		 */
		//kprintf("Writing journal blocks\n");
		result = sfs_jphys_flushforjournalblock(sfs, block);
		if (result) {
			return result;
		}
	} else if (b_fsdata != NULL) {
		//kprintf("\n\nBuffer %p is being written", b_fsdata->buf); 
		// This is a standard non-journal block
		// Enforce write-ahead logging. Flush up to the most recent lsn to touch
		//  this buffer
		KASSERT(b_fsdata->newest_lsn != 0);
		//kprintf("FLUSH (daddr %d): lsn %lld", b_fsdata->diskblock, b_fsdata->newest_lsn);
		sfs_jphys_flush(sfs, b_fsdata->newest_lsn);
		//kprintf("...Done.\n\n");
		b_fsdata->newest_lsn = 0;
		b_fsdata->oldest_lsn = 0;
	}

	SFSUIO(&iov, &ku, data, block, UIO_WRITE);
	result = sfs_rwblock(sfs, &ku);
	if (result) {
		return result;
	}

	if (isjournal) {
		sfs_wrote_journal_block(sfs, block);
	}

	return 0;
}