From ffa6376d01fc83daeb1d703752d1b9d097a6734f Mon Sep 17 00:00:00 2001 From: Krzysztof Mazur Date: Thu, 16 Dec 2010 21:04:35 +0100 Subject: [PATCH 05/84] lsbd: write partition table after modification --- drivers/block/lsbd.c | 60 ++++++++++++++++++++++++++++++++++++++++++++-------- 1 file changed, 51 insertions(+), 9 deletions(-) diff --git a/drivers/block/lsbd.c b/drivers/block/lsbd.c index e5197ae..b7c88b9 100644 --- a/drivers/block/lsbd.c +++ b/drivers/block/lsbd.c @@ -81,6 +81,7 @@ struct lsbd { struct list_head wqueue[LSBD_QUEUE_COUNT]; wait_queue_head_t wqueue_wait; unsigned int wqueue_len; + unsigned int blocks_to_write; struct semaphore req_sem; struct lsbd_partition part[16]; @@ -97,7 +98,7 @@ struct lsbd_request { int move; }; -#if 1 +#if 0 #define lsbd_debug(c, fmt, ...) \ printk(KERN_DEBUG "lsbd%d: "fmt, (c)->id, ## __VA_ARGS__) #else @@ -551,6 +552,8 @@ static int lsbd_load_params(struct lsbd *p) p->blocks * p->sectors_per_block * (p->sector_size >> 10)); lsbd_sizes[p->id] = p->lsectors * (p->sector_size >> 10); + + p->blocks_to_write = 0; lsbd_load_partitions(p, b); brelse(bh); @@ -640,6 +643,24 @@ static int lsbd_set_dev(struct lsbd *p, int major, int minor) return lsbd_mount(p); } + +static int lsbd_write_blocks(struct lsbd *p, unsigned int num) +{ + unsigned long flags; + + /* + * increase number of block for redundancy + */ + num *= 2; + + spin_lock_irqsave(&p->wqueue_lock, flags); + if (p->blocks_to_write < num) + p->blocks_to_write = num; + spin_unlock_irqrestore(&p->wqueue_lock, flags); + wake_up_interruptible(&p->wqueue_wait); + + return 0; +} static int lsbd_partition(struct lsbd *p, struct lsbd_part_info *part) { @@ -669,6 +690,7 @@ static int lsbd_partition(struct lsbd *p, struct lsbd_part_info *part) lsbd_lcache_t *l; lsbd_lcache_t *ol; unsigned int i; + unsigned int chunk; l = vmalloc(part->size * sizeof(l[0])); if (l == NULL) @@ -678,6 +700,11 @@ static int lsbd_partition(struct lsbd *p, struct lsbd_part_info *part) ol = p->lcache; p->lcache = l; + p->lsectors = part->size; + + chunk = (p->sector_size - 0x800) / sizeof(*l); + lsbd_write_blocks(p, p->lsectors / chunk); + /* * FIXME: implement lcache locking */ @@ -701,6 +728,9 @@ static int lsbd_partition(struct lsbd *p, struct lsbd_part_info *part) p->part[part->num].start = part->start; p->part[part->num].size = part->size; lsbd_update_part(p, part->num); + + /* write partition */ + lsbd_write_blocks(p, 1); return 0; } @@ -1156,6 +1186,9 @@ int lsbd_write_block(struct lsbd *p) static int lsbd_thread(void *data) { struct lsbd *p = data; + int ret; + int want_write; + int want_clean; lock_kernel(); daemonize(); @@ -1178,14 +1211,19 @@ static int lsbd_thread(void *data) complete(p->event); for (;;) { DECLARE_WAITQUEUE(wait, current); - unsigned int len; + + want_write = 0; + want_clean = 0; add_wait_queue(&p->wqueue_wait, &wait); set_task_state(current, TASK_INTERRUPTIBLE); spin_lock_irq(&p->wqueue_lock); - len = p->wqueue_len; + + if (p->wqueue_len || p->blocks_to_write) + want_write = 1; spin_unlock_irq(&p->wqueue_lock); - if (!len && (block_diff(p, p->clean_block, p->cur_block) >= 16)) + want_clean = (block_diff(p, p->clean_block, p->cur_block) < 16); + if (!(want_write || want_clean)) schedule(); current->state = TASK_RUNNING; remove_wait_queue(&p->wqueue_wait, &wait); @@ -1201,14 +1239,18 @@ static int lsbd_thread(void *data) if (p->stop) break; - if (block_diff(p, p->clean_block, p->cur_block) < 16) + if (want_clean) lsbd_clean_block(p); - while (len && (block_diff(p, p->clean_block, p->cur_block) - > 1)) { - lsbd_write_block(p); + while (want_write && (block_diff(p, p->clean_block, + p->cur_block) > 1)) { + ret = lsbd_write_block(p); spin_lock_irq(&p->wqueue_lock); - len = p->wqueue_len; + if (!ret && p->blocks_to_write) + p->blocks_to_write--; + want_write = 0; + if (p->wqueue_len || p->blocks_to_write) + want_write = 1; spin_unlock_irq(&p->wqueue_lock); } } -- 1.8.4.652.g0d6e0ce