/* Handle I/O for a BIO component. */
int file_do_bvec(struct file *file, struct bio_vec *bvec, loff_t pos, int rw)
{
u8 *buf;
ssize_t bw;
mm_segment_t old_fs = get_fs();
buf = kmap_atomic(bvec->bv_page, KM_USER0) + bvec->bv_offset;
set_fs(get_ds());
if (rw == WRITE)
bw = vfs_write(file, buf, bvec->bv_len, &pos);
else
bw = vfs_read(file, buf, bvec->bv_len, &pos);
set_fs(old_fs);
kunmap_atomic(buf, KM_USER0);
cond_resched();
if (likely(bw == len))
return 0;
printk(KERN_ERR "Error at byte offset %llu, length %i.\n",
(unsigned long long)pos, len);
if (bw >= 0)
bw = -EIO;
return bw;
}
/* Handle I/O for a BIO. */
int file_do_bio(struct file *file, struct bio *bio, loff_t pos)
{
struct bio_vec *bvec;
struct page *page = NULL;
int i, ret = 0;
/* Should have read-only check here, BIOs other than READ/WRITE. */
bio_for_each_segment(bvec, bio, i) {
ret = file_do_bvec(file, bvec, pos, bio_rw(bio));
if (ret < 0)
break;
pos += bvec->bv_len;
}
/*
* At some point we need to fsync. In this simple example - I'll do it here.
* TBD: should check error.
*/
vfs_fsync(file, 0);
return ret;
}
Saturday, October 20, 2012
Linux kernel file I/O from a block driver
This code shows how a hypothetical block driver might handle submitted BIOs, servicing them with a file.
Subscribe to:
Post Comments (Atom)
No comments:
Post a Comment