--- /dev/null
+commit 79eb79ed8e042e446accad244073af0f9bf4f35d
+Author: S.Çağlar Onur <caglar@cs.princeton.edu>
+Date: Fri Mar 19 10:17:24 2010 -0400
+
+ make_ext3_mount_default_to_barrier=1
+
+diff --git a/fs/ext3/fsync.c b/fs/ext3/fsync.c
+index 00c9597..841f0f7 100644
+--- a/fs/ext3/fsync.c
++++ b/fs/ext3/fsync.c
+@@ -27,6 +27,7 @@
+ #include <linux/sched.h>
+ #include <linux/writeback.h>
+ #include <linux/jbd.h>
++#include <linux/blkdev.h>
+ #include <linux/ext3_fs.h>
+ #include <linux/ext3_jbd.h>
+
+@@ -84,7 +85,10 @@ int ext3_sync_file(struct file * file, struct dentry *dentry, int datasync)
+ .sync_mode = WB_SYNC_ALL,
+ .nr_to_write = 0, /* sys_fsync did this */
+ };
++ journal_t *journal = EXT3_SB(inode->i_sb)->s_journal;
+ ret = sync_inode(inode, &wbc);
++ if (journal && (journal->j_flags & JFS_BARRIER))
++ blkdev_issue_flush(inode->i_sb->s_bdev, NULL);
+ }
+ out:
+ return ret;
+diff --git a/fs/ext3/super.c b/fs/ext3/super.c
+index 7facb78..ce186bc 100644
+--- a/fs/ext3/super.c
++++ b/fs/ext3/super.c
+@@ -1504,6 +1504,8 @@ static int ext3_fill_super (struct super_block *sb, void *data, int silent)
+ sbi->s_resuid = le16_to_cpu(es->s_def_resuid);
+ sbi->s_resgid = le16_to_cpu(es->s_def_resgid);
+
++ /* enable barriers by default */
++ set_opt(sbi->s_mount_opt, BARRIER);
+ set_opt(sbi->s_mount_opt, RESERVATION);
+
+ if (!parse_options ((char *) data, sb, &journal_inum, &journal_devnum,
--- /dev/null
+commit 1327d9674e235b4c3004034298ba4863d038ee88
+Author: S.Çağlar Onur <caglar@cs.princeton.edu>
+Date: Fri Mar 19 15:12:59 2010 -0400
+
+ support_barriers_on_single_device_dm_devices.patch
+
+diff --git a/drivers/md/dm-linear.c b/drivers/md/dm-linear.c
+index 17753d8..cda44f6 100644
+--- a/drivers/md/dm-linear.c
++++ b/drivers/md/dm-linear.c
+@@ -123,6 +123,7 @@ static struct target_type linear_target = {
+ .map = linear_map,
+ .status = linear_status,
+ .ioctl = linear_ioctl,
++ .features = DM_TARGET_SUPPORTS_BARRIERS,
+ };
+
+ int __init dm_linear_init(void)
+diff --git a/drivers/md/dm-table.c b/drivers/md/dm-table.c
+index 2fc199b..e540f57 100644
+--- a/drivers/md/dm-table.c
++++ b/drivers/md/dm-table.c
+@@ -38,6 +38,8 @@ struct dm_table {
+ sector_t *highs;
+ struct dm_target *targets;
+
++ unsigned barriers_supported:1;
++
+ /*
+ * Indicates the rw permissions for the new logical
+ * device. This should be a combination of FMODE_READ
+@@ -221,6 +223,7 @@ int dm_table_create(struct dm_table **result, int mode,
+ memset(t, 0, sizeof(*t));
+ INIT_LIST_HEAD(&t->devices);
+ atomic_set(&t->holders, 1);
++ t->barriers_supported = 1;
+
+ if (!num_targets)
+ num_targets = KEYS_PER_NODE;
+@@ -765,6 +768,10 @@ int dm_table_add_target(struct dm_table *t, const char *type,
+ /* FIXME: the plan is to combine high here and then have
+ * the merge fn apply the target level restrictions. */
+ combine_restrictions_low(&t->limits, &tgt->limits);
++
++ if (!(tgt->type->features & DM_TARGET_SUPPORTS_BARRIERS))
++ t->barriers_supported = 0;
++
+ return 0;
+
+ bad:
+@@ -809,6 +816,12 @@ int dm_table_complete(struct dm_table *t)
+
+ check_for_valid_limits(&t->limits);
+
++ /*
++ * We only support barriers if there is exactly one underlying device.
++ */
++ if (!list_is_singular(&t->devices))
++ t->barriers_supported = 0;
++
+ /* how many indexes will the btree have ? */
+ leaf_nodes = dm_div_up(t->num_targets, KEYS_PER_NODE);
+ t->depth = 1 + int_log(leaf_nodes, CHILDREN_PER_NODE);
+@@ -1033,6 +1046,11 @@ struct mapped_device *dm_table_get_md(struct dm_table *t)
+ return t->md;
+ }
+
++int dm_table_barrier_ok(struct dm_table *t)
++{
++ return t->barriers_supported;
++}
++EXPORT_SYMBOL(dm_table_barrier_ok);
+ EXPORT_SYMBOL(dm_vcalloc);
+ EXPORT_SYMBOL(dm_get_device);
+ EXPORT_SYMBOL(dm_put_device);
+diff --git a/drivers/md/dm.c b/drivers/md/dm.c
+index 12ecab3..bdf5107 100644
+--- a/drivers/md/dm.c
++++ b/drivers/md/dm.c
+@@ -781,6 +781,12 @@ static void __split_bio(struct mapped_device *md, struct bio *bio)
+ return;
+ }
+
++ if (unlikely(bio_barrier(bio) && !dm_table_barrier_ok(ci.map))) {
++ dm_table_put(ci.map);
++ bio_endio(bio, bio->bi_size, -EOPNOTSUPP);
++ return;
++ }
++
+ ci.md = md;
+ ci.bio = bio;
+ ci.io = alloc_io(md);
+@@ -814,15 +820,6 @@ static int dm_request(request_queue_t *q, struct bio *bio)
+ int rw = bio_data_dir(bio);
+ struct mapped_device *md = q->queuedata;
+
+- /*
+- * There is no use in forwarding any barrier request since we can't
+- * guarantee it is (or can be) handled by the targets correctly.
+- */
+- if (unlikely(bio_barrier(bio))) {
+- bio_endio(bio, bio->bi_size, -EOPNOTSUPP);
+- return 0;
+- }
+-
+ down_read(&md->io_lock);
+
+ disk_stat_inc(dm_disk(md), ios[rw]);
+diff --git a/drivers/md/dm.h b/drivers/md/dm.h
+index e71b22d..a67e8b7 100644
+--- a/drivers/md/dm.h
++++ b/drivers/md/dm.h
+@@ -80,6 +80,7 @@ int dm_table_resume_targets(struct dm_table *t);
+ int dm_table_any_congested(struct dm_table *t, int bdi_bits);
+ void dm_table_unplug_all(struct dm_table *t);
+ int dm_table_flush_all(struct dm_table *t);
++int dm_table_barrier_ok(struct dm_table *t);
+
+ /*-----------------------------------------------------------------
+ * A registry of target types.
+diff --git a/include/linux/device-mapper.h b/include/linux/device-mapper.h
+index 499f537..6bc9120 100644
+--- a/include/linux/device-mapper.h
++++ b/include/linux/device-mapper.h
+@@ -89,9 +89,15 @@ int dm_get_device(struct dm_target *ti, const char *path, sector_t start,
+ void dm_put_device(struct dm_target *ti, struct dm_dev *d);
+
+ /*
++ * Target features
++ */
++#define DM_TARGET_SUPPORTS_BARRIERS 0x00000001
++
++/*
+ * Information about a target type
+ */
+ struct target_type {
++ uint64_t features;
+ const char *name;
+ struct module *module;
+ unsigned version[3];
+diff --git a/include/linux/list.h b/include/linux/list.h
+index f29fc9c..55051eb 100644
+--- a/include/linux/list.h
++++ b/include/linux/list.h
+@@ -319,6 +319,15 @@ static inline int list_empty_careful(const struct list_head *head)
+ return (next == head) && (next == head->prev);
+ }
+
++/**
++ * list_is_singular - tests whether a list has just one entry.
++ * @head: the list to test.
++ */
++static inline int list_is_singular(const struct list_head *head)
++{
++ return !list_empty(head) && (head->next == head->prev);
++}
++
+ static inline void __list_splice(struct list_head *list,
+ struct list_head *head)
+ {