New open modes FNODE_DM_NOFLUSH and FMODE_DM_FLUSH_IGN_ERR. FNODE_DM_NOFLUSH indicates that the device hardware cache doesn't have to be flushed when processing a barrier (used for mirror log, it is already flushed explicitly). FMODE_DM_FLUSH_IGN_ERR indicated that the hardware cache should be flushed but the error code should be ignored (used for raid1 legs and multipath, where failing devices are acceptable). Signed-off-by: Mikulas Patocka --- drivers/md/dm-log.c | 2 +- drivers/md/dm-mpath.c | 3 ++- drivers/md/dm-raid1.c | 2 +- drivers/md/dm-table.c | 18 ++++++++++++++---- include/linux/fs.h | 14 ++++++++++++++ 5 files changed, 32 insertions(+), 7 deletions(-) Index: linux-2.6.29-rc3-devel/drivers/md/dm-log.c =================================================================== --- linux-2.6.29-rc3-devel.orig/drivers/md/dm-log.c 2009-01-29 05:27:21.000000000 +0100 +++ linux-2.6.29-rc3-devel/drivers/md/dm-log.c 2009-01-29 05:27:22.000000000 +0100 @@ -564,7 +564,7 @@ static int disk_ctr(struct dm_dirty_log } r = dm_get_device(ti, argv[0], 0, 0 /* FIXME */, - FMODE_READ | FMODE_WRITE, &dev); + FMODE_READ | FMODE_WRITE | FMODE_DM_NOFLUSH, &dev); if (r) return r; Index: linux-2.6.29-rc3-devel/drivers/md/dm-mpath.c =================================================================== --- linux-2.6.29-rc3-devel.orig/drivers/md/dm-mpath.c 2009-01-29 05:26:28.000000000 +0100 +++ linux-2.6.29-rc3-devel/drivers/md/dm-mpath.c 2009-01-29 05:27:22.000000000 +0100 @@ -586,7 +586,8 @@ static struct pgpath *parse_path(struct return ERR_PTR(-ENOMEM); r = dm_get_device(ti, shift(as), ti->begin, ti->len, - dm_table_get_mode(ti->table), &p->path.dev); + dm_table_get_mode(ti->table) | FMODE_DM_FLUSH_IGN_ERR, + &p->path.dev); if (r) { ti->error = "error getting device"; goto bad; Index: linux-2.6.29-rc3-devel/include/linux/fs.h =================================================================== --- linux-2.6.29-rc3-devel.orig/include/linux/fs.h 2009-01-29 05:23:16.000000000 +0100 +++ linux-2.6.29-rc3-devel/include/linux/fs.h 2009-01-29 05:27:22.000000000 +0100 @@ -81,6 +81,20 @@ struct inodes_stat_t { */ #define FMODE_NOCMTIME ((__force fmode_t)2048) +/* + * Useable only inside device mapper with dm_get_device(). + * Inform the dm core that the device cache should not be flushed when + * barrier is processed. + */ +#define FMODE_DM_NOFLUSH ((__force fmode_t)4096) + +/* + * Useable only inside device mapper with dm_get_device(). + * Inform the dm core that flush errors should be ignored when barrier + * is processed. + */ +#define FMODE_DM_FLUSH_IGN_ERR ((__force fmode_t)8192) + #define RW_MASK 1 #define RWA_MASK 2 #define READ 0 Index: linux-2.6.29-rc3-devel/drivers/md/dm-table.c =================================================================== --- linux-2.6.29-rc3-devel.orig/drivers/md/dm-table.c 2009-01-29 05:27:17.000000000 +0100 +++ linux-2.6.29-rc3-devel/drivers/md/dm-table.c 2009-01-29 05:27:22.000000000 +0100 @@ -994,17 +994,24 @@ struct flush_completion { atomic_t error; }; -static void bio_end_flush(struct bio *bio, int error) +static void bio_end_flush_ign_err(struct bio *bio, int error) { struct flush_completion *completion = bio->bi_private; bio_put(bio); + if (atomic_dec_and_test(&completion->count)) + wake_up_process(completion->sleeper); +} + +static void bio_end_flush(struct bio *bio, int error) +{ + struct flush_completion *completion = bio->bi_private; + if (unlikely(error) && unlikely(error != -EOPNOTSUPP)) atomic_cmpxchg(&completion->error, 0, error); - if (atomic_dec_and_test(&completion->count)) - wake_up_process(completion->sleeper); + bio_end_flush_ign_err(bio, error); } static void wait_for_flush_completion(struct flush_completion *completion) @@ -1040,6 +1047,9 @@ int dm_table_flush_all(struct dm_table * list_for_each_entry(dd, devices, list) { struct bio *bio; + if (unlikely(dd->dm_dev.mode & FMODE_DM_NOFLUSH)) + continue; + atomic_inc(&completion.count); bio = bio_kmalloc(GFP_ATOMIC, 0); @@ -1053,7 +1063,7 @@ int dm_table_flush_all(struct dm_table * bio_init(&reserved_bio); reserved_bio.bi_destructor = bio_null_destructor; } - bio->bi_end_io = bio_end_flush; + bio->bi_end_io = dd->dm_dev.mode & FMODE_DM_FLUSH_IGN_ERR ? bio_end_flush_ign_err : bio_end_flush; bio->bi_private = &completion; bio->bi_bdev = dd->dm_dev.bdev; Index: linux-2.6.29-rc3-devel/drivers/md/dm-raid1.c =================================================================== --- linux-2.6.29-rc3-devel.orig/drivers/md/dm-raid1.c 2009-01-29 05:38:15.000000000 +0100 +++ linux-2.6.29-rc3-devel/drivers/md/dm-raid1.c 2009-01-29 04:03:00.000000000 +0100 @@ -819,7 +819,7 @@ static int get_mirror(struct mirror_set } if (dm_get_device(ti, argv[0], offset, ti->len, - dm_table_get_mode(ti->table), + dm_table_get_mode(ti->table) | FMODE_DM_FLUSH_IGN_ERR, &ms->mirror[mirror].dev)) { ti->error = "Device lookup failure"; return -ENXIO;