Setting tag linux-2.6-22-50
[linux-2.6.git] / linux-2.6-910-support_barriers_on_single_device_dm_devices.patch
1 commit 1327d9674e235b4c3004034298ba4863d038ee88
2 Author: S.Çağlar Onur <caglar@cs.princeton.edu>
3 Date:   Fri Mar 19 15:12:59 2010 -0400
4
5     support_barriers_on_single_device_dm_devices.patch
6
7 diff --git a/drivers/md/dm-linear.c b/drivers/md/dm-linear.c
8 index 17753d8..cda44f6 100644
9 --- a/drivers/md/dm-linear.c
10 +++ b/drivers/md/dm-linear.c
11 @@ -123,6 +123,7 @@ static struct target_type linear_target = {
12         .map    = linear_map,
13         .status = linear_status,
14         .ioctl  = linear_ioctl,
15 +       .features = DM_TARGET_SUPPORTS_BARRIERS,
16  };
17  
18  int __init dm_linear_init(void)
19 diff --git a/drivers/md/dm-table.c b/drivers/md/dm-table.c
20 index 2fc199b..e540f57 100644
21 --- a/drivers/md/dm-table.c
22 +++ b/drivers/md/dm-table.c
23 @@ -38,6 +38,8 @@ struct dm_table {
24         sector_t *highs;
25         struct dm_target *targets;
26  
27 +       unsigned barriers_supported:1;
28 +
29         /*
30          * Indicates the rw permissions for the new logical
31          * device.  This should be a combination of FMODE_READ
32 @@ -221,6 +223,7 @@ int dm_table_create(struct dm_table **result, int mode,
33         memset(t, 0, sizeof(*t));
34         INIT_LIST_HEAD(&t->devices);
35         atomic_set(&t->holders, 1);
36 +       t->barriers_supported = 1;
37  
38         if (!num_targets)
39                 num_targets = KEYS_PER_NODE;
40 @@ -765,6 +768,10 @@ int dm_table_add_target(struct dm_table *t, const char *type,
41         /* FIXME: the plan is to combine high here and then have
42          * the merge fn apply the target level restrictions. */
43         combine_restrictions_low(&t->limits, &tgt->limits);
44 +
45 +       if (!(tgt->type->features & DM_TARGET_SUPPORTS_BARRIERS))
46 +               t->barriers_supported = 0;
47 +
48         return 0;
49  
50   bad:
51 @@ -809,6 +816,12 @@ int dm_table_complete(struct dm_table *t)
52  
53         check_for_valid_limits(&t->limits);
54  
55 +       /*
56 +        * We only support barriers if there is exactly one underlying device.
57 +        */
58 +       if (!list_is_singular(&t->devices))
59 +               t->barriers_supported = 0;
60 +
61         /* how many indexes will the btree have ? */
62         leaf_nodes = dm_div_up(t->num_targets, KEYS_PER_NODE);
63         t->depth = 1 + int_log(leaf_nodes, CHILDREN_PER_NODE);
64 @@ -1033,6 +1046,11 @@ struct mapped_device *dm_table_get_md(struct dm_table *t)
65         return t->md;
66  }
67  
68 +int dm_table_barrier_ok(struct dm_table *t)
69 +{
70 +       return t->barriers_supported;
71 +}
72 +EXPORT_SYMBOL(dm_table_barrier_ok);
73  EXPORT_SYMBOL(dm_vcalloc);
74  EXPORT_SYMBOL(dm_get_device);
75  EXPORT_SYMBOL(dm_put_device);
76 diff --git a/drivers/md/dm.c b/drivers/md/dm.c
77 index 12ecab3..bdf5107 100644
78 --- a/drivers/md/dm.c
79 +++ b/drivers/md/dm.c
80 @@ -781,6 +781,12 @@ static void __split_bio(struct mapped_device *md, struct bio *bio)
81                 return;
82         }
83  
84 +       if (unlikely(bio_barrier(bio) && !dm_table_barrier_ok(ci.map))) {
85 +               dm_table_put(ci.map);
86 +               bio_endio(bio, bio->bi_size, -EOPNOTSUPP);
87 +               return;
88 +       }
89 +
90         ci.md = md;
91         ci.bio = bio;
92         ci.io = alloc_io(md);
93 @@ -814,15 +820,6 @@ static int dm_request(request_queue_t *q, struct bio *bio)
94         int rw = bio_data_dir(bio);
95         struct mapped_device *md = q->queuedata;
96  
97 -       /*
98 -        * There is no use in forwarding any barrier request since we can't
99 -        * guarantee it is (or can be) handled by the targets correctly.
100 -        */
101 -       if (unlikely(bio_barrier(bio))) {
102 -               bio_endio(bio, bio->bi_size, -EOPNOTSUPP);
103 -               return 0;
104 -       }
105 -
106         down_read(&md->io_lock);
107  
108         disk_stat_inc(dm_disk(md), ios[rw]);
109 diff --git a/drivers/md/dm.h b/drivers/md/dm.h
110 index e71b22d..a67e8b7 100644
111 --- a/drivers/md/dm.h
112 +++ b/drivers/md/dm.h
113 @@ -80,6 +80,7 @@ int dm_table_resume_targets(struct dm_table *t);
114  int dm_table_any_congested(struct dm_table *t, int bdi_bits);
115  void dm_table_unplug_all(struct dm_table *t);
116  int dm_table_flush_all(struct dm_table *t);
117 +int dm_table_barrier_ok(struct dm_table *t);
118  
119  /*-----------------------------------------------------------------
120   * A registry of target types.
121 diff --git a/include/linux/device-mapper.h b/include/linux/device-mapper.h
122 index 499f537..6bc9120 100644
123 --- a/include/linux/device-mapper.h
124 +++ b/include/linux/device-mapper.h
125 @@ -89,9 +89,15 @@ int dm_get_device(struct dm_target *ti, const char *path, sector_t start,
126  void dm_put_device(struct dm_target *ti, struct dm_dev *d);
127  
128  /*
129 + * Target features
130 + */
131 +#define DM_TARGET_SUPPORTS_BARRIERS 0x00000001
132 +
133 +/*
134   * Information about a target type
135   */
136  struct target_type {
137 +       uint64_t features;
138         const char *name;
139         struct module *module;
140         unsigned version[3];
141 diff --git a/include/linux/list.h b/include/linux/list.h
142 index f29fc9c..55051eb 100644
143 --- a/include/linux/list.h
144 +++ b/include/linux/list.h
145 @@ -319,6 +319,15 @@ static inline int list_empty_careful(const struct list_head *head)
146         return (next == head) && (next == head->prev);
147  }
148  
149 +/**
150 + * list_is_singular - tests whether a list has just one entry.
151 + * @head: the list to test.
152 + */
153 +static inline int list_is_singular(const struct list_head *head)
154 +{
155 +        return !list_empty(head) && (head->next == head->prev);
156 +}
157 +
158  static inline void __list_splice(struct list_head *list,
159                                  struct list_head *head)
160  {