1
0
mirror of https://github.com/schoebel/mars synced 2025-03-22 19:16:59 +00:00

import mars-07.tgz

This commit is contained in:
Thomas Schoebel-Theuer 2010-06-18 12:44:14 +01:00
parent 89d03b5fe1
commit d4d6d80fb5
5 changed files with 198 additions and 62 deletions

View File

@ -10,6 +10,7 @@
#include <linux/kthread.h>
#include <linux/spinlock.h>
#include <linux/wait.h>
#include <linux/splice.h>
#include "mars.h"
@ -19,6 +20,8 @@
////////////////// own brick / input / output operations //////////////////
// some code borrowed from the loopback driver
static int transfer_none(int cmd,
struct page *raw_page, unsigned raw_off,
struct page *loop_page, unsigned loop_off,
@ -38,7 +41,7 @@ static int transfer_none(int cmd,
return 0;
}
static int device_sio_write_aops(struct device_sio_output *output, struct mars_io *mio)
static int write_aops(struct device_sio_output *output, struct mars_io *mio)
{
struct bio *bio = mio->orig_bio;
loff_t pos = ((loff_t)bio->bi_sector << 9);
@ -110,42 +113,145 @@ static int device_sio_write_aops(struct device_sio_output *output, struct mars_i
mio->mars_endio(mio);
#if 1
blk_run_address_space(mapping);
#endif
return ret;
}
struct cookie_data {
struct device_sio_output *output;
struct mars_io *mio;
struct bio_vec *bvec;
unsigned int offset;
};
static int
device_sio_splice_actor(struct pipe_inode_info *pipe,
struct pipe_buffer *buf,
struct splice_desc *sd)
{
struct cookie_data *p = sd->u.data;
//struct device_sio_output *output = p->output;
//struct mars_io *mio = p->mio;
struct page *page = buf->page;
sector_t IV;
int size, ret;
MARS_DBG("now splice %p %p %p %p\n", output, mio, mio->orig_bio, p->bvec);
ret = buf->ops->confirm(pipe, buf);
if (unlikely(ret))
return ret;
IV = ((sector_t) page->index << (PAGE_CACHE_SHIFT - 9)) +
(buf->offset >> 9);
size = sd->len;
if (size > p->bvec->bv_len)
size = p->bvec->bv_len;
if (transfer_none(READ, page, buf->offset, p->bvec->bv_page, p->offset, size)) {
MARS_ERR("transfer error block %ld\n", p->bvec->bv_page->index);
size = -EINVAL;
}
flush_dcache_page(p->bvec->bv_page);
if (size > 0)
p->offset += size;
return size;
}
static int
device_sio_direct_splice_actor(struct pipe_inode_info *pipe, struct splice_desc *sd)
{
return __splice_from_pipe(pipe, sd, device_sio_splice_actor);
}
static int read_aops(struct device_sio_output *output, struct mars_io *mio)
{
struct bio *bio = mio->orig_bio;
loff_t pos = ((loff_t)bio->bi_sector << 9);
struct bio_vec *bvec;
int i;
int ret = -EIO;
bio_for_each_segment(bvec, bio, i) {
struct cookie_data cookie = {
.output = output,
.mio = mio,
.bvec = bvec,
.offset = bvec->bv_offset,
};
struct splice_desc sd = {
.len = 0,
.total_len = bvec->bv_len,
.flags = 0,
.pos = pos,
.u.data = &cookie,
};
MARS_DBG("start splice %p %p %p %p\n", output, mio, bio, bvec);
ret = 0;
ret = splice_direct_to_actor(output->filp, &sd, device_sio_direct_splice_actor);
if (ret < 0) {
MARS_ERR("splice %p %p %p %p status=%d\n", output, mio, bio, bvec, ret);
break;
}
pos += bvec->bv_len;
bio->bi_size -= bvec->bv_len;
}
mio->mars_endio(mio);
return ret;
}
static void sync_file(struct device_sio_output *output)
{
struct file *file = output->filp;
int ret;
#if 1
ret = vfs_fsync(file, file->f_path.dentry, 0);
if (unlikely(ret)) {
MARS_ERR("syncing pages failed: %d\n", ret);
}
return;
#endif
}
static int device_sio_mars_io(struct device_sio_output *output, struct mars_io *mio)
{
struct bio *bio = mio->orig_bio;
int direction = bio->bi_rw & 1;
unsigned long sector = bio->bi_sector;
unsigned long long pos = sector << 9; //TODO: allow different sector sizes
bool barrier = (direction != READ && bio_rw_flagged(bio, BIO_RW_BARRIER));
#if 0
unsigned long sector = bio->bi_sector;
loff_t pos = sector << 9; //TODO: allow different sector sizes
struct bio_vec *bvec;
int i;
#endif
int ret = -EIO;
if (barrier) {
MARS_INF("got barrier request\n");
sync_file(output);
}
#if 1
if (direction == READ) {
bio->bi_size = 0;
mio->mars_endio(mio);
return 0;
}
#endif
if (!output->filp)
goto done;
#if 1
if (direction == WRITE) {
return device_sio_write_aops(output, mio);
if (direction == READ) {
return read_aops(output, mio);
} else {
ret = write_aops(output, mio);
if (barrier)
sync_file(output);
return ret;
}
#endif
#else // toter code, war ein erster versuch
bio_for_each_segment(bvec, bio, i) {
mm_segment_t oldfs;
unsigned long long ppos = pos;
@ -176,27 +282,19 @@ static int device_sio_mars_io(struct device_sio_output *output, struct mars_io *
goto done;
}
#if 0
if (direction == WRITE) {
struct inode *inode = output->filp->f_dentry->d_inode;
struct address_space *mapping = inode->i_mapping;
int res;
res = sync_page_range(inode, mapping, pos, len);
if (res) {
MARS_ERR("syncing pages failed: %d\n", res);
}
}
#endif
pos += len;
ret = 0;
}
#endif
done:
if (!ret)
if (!ret) {
bio->bi_size = 0;
if (direction == WRITE && barrier) {
sync_file(output);
}
}
mio->mars_endio(mio);
return ret;
}
@ -204,37 +302,51 @@ done:
#ifdef WITH_THREAD
static int device_sio_mars_queue(struct device_sio_output *output, struct mars_io *mio)
{
MARS_DBG("queue %p\n", mio);
spin_lock_irq(&output->lock);
list_add_tail(&mio->io_head, &output->mio_list);
spin_unlock_irq(&output->lock);
int index = 0;
struct sio_threadinfo *tinfo;
int direction = mio->orig_bio->bi_rw & 1;
if (direction == READ) {
spin_lock_irq(&output->g_lock);
index = output->index++;
spin_unlock_irq(&output->g_lock);
index = (index % WITH_THREAD) + 1;
}
tinfo = &output->tinfo[index];
MARS_DBG("queueing %p on %d\n", mio, index);
spin_lock_irq(&tinfo->lock);
list_add_tail(&mio->io_head, &tinfo->mio_list);
spin_unlock_irq(&tinfo->lock);
wake_up(&output->event);
wake_up(&tinfo->event);
return 0;
}
static int device_sio_thread(void *data)
{
struct device_sio_output *output = data;
struct sio_threadinfo *tinfo = data;
struct device_sio_output *output = tinfo->output;
MARS_INF("kthread has started.\n");
//set_user_nice(current, -20);
while (!kthread_should_stop()) {
struct list_head *tmp;
struct mars_io *mio;
wait_event_interruptible(output->event,
!list_empty(&output->mio_list) ||
wait_event_interruptible(tinfo->event,
!list_empty(&tinfo->mio_list) ||
kthread_should_stop());
if (list_empty(&output->mio_list))
if (list_empty(&tinfo->mio_list))
continue;
spin_lock_irq(&output->lock);
mio = container_of(output->mio_list.next, struct mars_io, io_head);
spin_unlock_irq(&output->lock);
spin_lock_irq(&tinfo->lock);
tmp = tinfo->mio_list.next;
list_del_init(tmp);
spin_unlock_irq(&tinfo->lock);
mio = container_of(tmp, struct mars_io, io_head);
MARS_DBG("got %p\n", mio);
device_sio_mars_io(output, mio);
}
@ -257,6 +369,7 @@ static int device_sio_output_construct(struct device_sio_output *output)
int flags = O_CREAT | O_RDWR | O_LARGEFILE;
int prot = 0600;
char *path = "/tmp/testfile.img";
int index;
oldfs = get_fs();
set_fs(get_ds());
@ -279,17 +392,23 @@ static int device_sio_output_construct(struct device_sio_output *output)
#endif
#ifdef WITH_THREAD
spin_lock_init(&output->lock);
init_waitqueue_head(&output->event);
INIT_LIST_HEAD(&output->mio_list);
output->thread = kthread_create(device_sio_thread, output, "mars_sio%d", 0);
if (IS_ERR(output->thread)) {
int error = PTR_ERR(output->thread);
MARS_ERR("cannot create thread, status=%d\n", error);
filp_close(output->filp, NULL);
return error;
spin_lock_init(&output->g_lock);
output->index = 0;
for (index = 0; index <= WITH_THREAD; index++) {
struct sio_threadinfo *tinfo = &output->tinfo[index];
tinfo->output = output;
spin_lock_init(&tinfo->lock);
init_waitqueue_head(&tinfo->event);
INIT_LIST_HEAD(&tinfo->mio_list);
tinfo->thread = kthread_create(device_sio_thread, tinfo, "mars_sio%d", index);
if (IS_ERR(tinfo->thread)) {
int error = PTR_ERR(tinfo->thread);
MARS_ERR("cannot create thread, status=%d\n", error);
filp_close(output->filp, NULL);
return error;
}
wake_up_process(tinfo->thread);
}
wake_up_process(output->thread);
#endif
return 0;
@ -298,8 +417,11 @@ static int device_sio_output_construct(struct device_sio_output *output)
static int device_sio_output_destruct(struct device_sio_output *output)
{
#ifdef WITH_THREAD
kthread_stop(output->thread);
output->thread = NULL;
int index;
for (index = 0; index <= WITH_THREAD; index++) {
kthread_stop(output->tinfo[index].thread);
output->tinfo[index].thread = NULL;
}
#endif
if (output->filp) {
filp_close(output->filp, NULL);
@ -349,13 +471,13 @@ EXPORT_SYMBOL_GPL(device_sio_brick_type);
static int __init init_device_sio(void)
{
printk(MARS_INFO "init_device_sio()\n");
MARS_INF("init_device_sio()\n");
return device_sio_register_brick_type();
}
static void __exit exit_device_sio(void)
{
printk(MARS_INFO "exit_device_sio()\n");
MARS_INF("exit_device_sio()\n");
device_sio_unregister_brick_type();
}

View File

@ -1,5 +1,5 @@
// (c) 2010 Thomas Schoebel-Theuer / 1&1 Internet AG
//#define WITH_THREAD
#define WITH_THREAD 16
struct device_sio_brick {
MARS_BRICK(device_sio);
@ -9,14 +9,24 @@ struct device_sio_input {
MARS_INPUT(device_sio);
};
struct device_sio_output {
MARS_OUTPUT(device_sio);
struct file *filp;
#ifdef WITH_THREAD
struct sio_threadinfo {
struct device_sio_output *output;
struct list_head mio_list;
struct task_struct *thread;
wait_queue_head_t event;
spinlock_t lock;
};
#endif
struct device_sio_output {
MARS_OUTPUT(device_sio);
struct file *filp;
#ifdef WITH_THREAD
struct sio_threadinfo tinfo[WITH_THREAD+1];
spinlock_t g_lock;
int index;
#endif
};

View File

@ -30,6 +30,7 @@ static int if_device_endio(struct mars_io *mio)
{
struct bio *bio = mio->orig_bio;
if (bio) {
mio->orig_bio = NULL;
if (!bio->bi_size) {
bio_endio(bio, 0);
} else {
@ -166,6 +167,8 @@ static int if_device_input_construct(struct if_device_input *input)
blk_queue_max_segment_size(q, MARS_MAX_SEGMENT_SIZE);
blk_queue_bounce_limit(q, BLK_BOUNCE_ANY);
q->unplug_fn = if_device_unplug;
spin_lock_init(&input->req_lock);
q->queue_lock = &input->req_lock; // needed!
//blk_queue_ordered(q, QUEUE_ORDERED_DRAIN, NULL);//???
MARS_DBG("4\n");
@ -180,13 +183,13 @@ static int if_device_input_construct(struct if_device_input *input)
#if 0 // ???
blk_queue_merge_bvec(q, mars_merge_bvec);
q->queue_lock = &input->req_lock; /* needed since we use */
/* plugging on a queue, that actually has no requests! */
#endif
// point of no return
MARS_DBG("99999\n");
add_disk(disk);
input->disk = disk;
//set_device_ro(input->bdev, 0); // TODO: implement modes
input->mio_size = 1024; //TODO: make this dynamic
return 0;
}

View File

@ -8,6 +8,7 @@ struct if_device_input {
struct request_queue *q;
struct gendisk *disk;
struct block_device *bdev;
spinlock_t req_lock;
int mio_size;
};

View File

@ -22,7 +22,7 @@ static struct device_sio_brick *device_brick = NULL;
void make_test_instance(void)
{
static char *names[] = { "brick" };
int size = 1024;
int size = 4096;
int status;
void *mem = kzalloc(size, GFP_KERNEL);
if (!mem) {