]> git.ipfire.org Git - people/teissler/ipfire-2.x.git/blob - src/patches/suse-2.6.27.31/patches.fixes/0017A-md-array_size-sysfs-arrtibute.patch
Merge branch 'master' of git://git.ipfire.org/ipfire-2.x
[people/teissler/ipfire-2.x.git] / src / patches / suse-2.6.27.31 / patches.fixes / 0017A-md-array_size-sysfs-arrtibute.patch
1 From: NeilBrown <neilb@suse.de>
2 Subject: [PATCH] md: 'array_size' sysfs attribute
3 References: bnc#498358
4
5 Allow userspace to set the size of the array according to the following
6 semantics:
7
8 1/ size must be <= to the size stored in mddev->array_size
9 a) If size is set before the array is running, do_md_run will fail
10 if size is greater than the default size
11 b) A reshape attempt that reduces the default size to less than the set
12 array size should be blocked
13 2/ once userspace sets the size the kernel will not change it
14 3/ writing 'default' to this attribute returns control of the size to the
15 kernel and reverts to the size reported by the personality
16
17 To avoid kabi break we store the user-specified size in ->queue->end_sector
18 which is otherwise unused by md devices.
19
20 (based on a patch which was)
21 Signed-off-by: Dan Williams <dan.j.williams@intel.com>
22 Signed-off-by: NeilBrown <neilb@suse.de>
23 Acked-by: NeilBrown <neilb@suse.de>
24 ---
25 drivers/md/linear.c | 3 +
26 drivers/md/md.c | 85 ++++++++++++++++++++++++++++++++++++++++++++++++++--
27 drivers/md/raid1.c | 14 ++++----
28 drivers/md/raid5.c | 9 +++--
29 4 files changed, 99 insertions(+), 12 deletions(-)
30
31 --- linux-2.6.27-SLE11_BRANCH.orig/drivers/md/linear.c
32 +++ linux-2.6.27-SLE11_BRANCH/drivers/md/linear.c
33 @@ -295,7 +295,8 @@ static int linear_add(mddev_t *mddev, md
34 mddev->private = newconf;
35 mddev->raid_disks++;
36 mddev->array_sectors = newconf->array_sectors;
37 - set_capacity(mddev->gendisk, mddev->array_sectors);
38 + if (mddev->queue->end_sector == 0)
39 + set_capacity(mddev->gendisk, mddev->array_sectors);
40 return 0;
41 }
42
43 --- linux-2.6.27-SLE11_BRANCH.orig/drivers/md/md.c
44 +++ linux-2.6.27-SLE11_BRANCH/drivers/md/md.c
45 @@ -287,6 +287,7 @@ static mddev_t * mddev_find(dev_t unit)
46 kfree(new);
47 return NULL;
48 }
49 + new->queue->end_sector = 0;
50 /* Can be unlocked because the queue is new: no concurrency */
51 queue_flag_set_unlocked(QUEUE_FLAG_CLUSTER, new->queue);
52
53 @@ -2136,6 +2137,25 @@ rdev_size_show(mdk_rdev_t *rdev, char *p
54 return sprintf(page, "%llu\n", (unsigned long long)rdev->size);
55 }
56
57 +static int strict_blocks_to_sectors(const char *buf, sector_t *sectors)
58 +{
59 + unsigned long long blocks;
60 + sector_t new;
61 +
62 + if (strict_strtoull(buf, 10, &blocks) < 0)
63 + return -EINVAL;
64 +
65 + if (blocks & 1ULL << (8 * sizeof(blocks) - 1))
66 + return -EINVAL; /* sector conversion overflow */
67 +
68 + new = blocks * 2;
69 + if (new != blocks * 2)
70 + return -EINVAL; /* unsigned long long to sector_t overflow */
71 +
72 + *sectors = new;
73 + return 0;
74 +}
75 +
76 static int overlaps(sector_t s1, sector_t l1, sector_t s2, sector_t l2)
77 {
78 /* check if two start/length pairs overlap */
79 @@ -3397,6 +3417,55 @@ static struct md_sysfs_entry md_reshape_
80 __ATTR(reshape_position, S_IRUGO|S_IWUSR, reshape_position_show,
81 reshape_position_store);
82
83 +static ssize_t
84 +array_size_show(mddev_t *mddev, char *page)
85 +{
86 + if (mddev->queue->end_sector)
87 + return sprintf(page, "%llu\n",
88 + (unsigned long long)mddev->queue->end_sector/2);
89 + else
90 + return sprintf(page, "default\n");
91 +}
92 +
93 +static ssize_t
94 +array_size_store(mddev_t *mddev, const char *buf, size_t len)
95 +{
96 + sector_t sectors;
97 +
98 + if (strncmp(buf, "default", 7) == 0) {
99 + sectors = mddev->array_sectors;
100 +
101 + mddev->queue->end_sector = 0;
102 + } else {
103 + if (strict_blocks_to_sectors(buf, &sectors) < 0)
104 + return -EINVAL;
105 + if (sectors < 2)
106 + return -EINVAL;
107 + if (mddev->pers && mddev->array_sectors < sectors)
108 + return -E2BIG;
109 +
110 + mddev->queue->end_sector = sectors;
111 + }
112 +
113 + set_capacity(mddev->gendisk, sectors);
114 + if (mddev->pers) {
115 + struct block_device *bdev = bdget_disk(mddev->gendisk, 0);
116 +
117 + if (bdev) {
118 + mutex_lock(&bdev->bd_inode->i_mutex);
119 + i_size_write(bdev->bd_inode,
120 + (loff_t)sectors << 9);
121 + mutex_unlock(&bdev->bd_inode->i_mutex);
122 + bdput(bdev);
123 + }
124 + }
125 +
126 + return len;
127 +}
128 +
129 +static struct md_sysfs_entry md_array_size =
130 +__ATTR(array_size, S_IRUGO|S_IWUSR, array_size_show,
131 + array_size_store);
132
133 static struct attribute *md_default_attrs[] = {
134 &md_level.attr,
135 @@ -3410,6 +3479,7 @@ static struct attribute *md_default_attr
136 &md_safe_delay.attr,
137 &md_array_state.attr,
138 &md_reshape_position.attr,
139 + &md_array_size.attr,
140 NULL,
141 };
142
143 @@ -3721,7 +3791,15 @@ static int do_md_run(mddev_t * mddev)
144 err = mddev->pers->run(mddev);
145 if (err)
146 printk(KERN_ERR "md: pers->run() failed ...\n");
147 - else if (mddev->pers->sync_request) {
148 + else if (mddev->queue->end_sector &&
149 + mddev->queue->end_sector > mddev->array_sectors) {
150 + printk(KERN_ERR
151 + "md: invalid array_size %llu > default size %llu\n",
152 + (unsigned long long)mddev->queue->end_sector / 2,
153 + (unsigned long long)mddev->array_sectors / 2);
154 + err = -EINVAL;
155 + mddev->pers->stop(mddev);
156 + } else if (mddev->pers->sync_request) {
157 err = bitmap_create(mddev);
158 if (err) {
159 printk(KERN_ERR "%s: failed to create bitmap (%d)\n",
160 @@ -3764,7 +3842,10 @@ static int do_md_run(mddev_t * mddev)
161 if (mddev->flags)
162 md_update_sb(mddev, 0);
163
164 - set_capacity(disk, mddev->array_sectors);
165 + if (mddev->queue->end_sector)
166 + set_capacity(disk, mddev->queue->end_sector);
167 + else
168 + set_capacity(disk, mddev->array_sectors);
169
170 /* If we call blk_queue_make_request here, it will
171 * re-initialise max_sectors etc which may have been
172 --- linux-2.6.27-SLE11_BRANCH.orig/drivers/md/raid1.c
173 +++ linux-2.6.27-SLE11_BRANCH/drivers/md/raid1.c
174 @@ -2108,12 +2108,14 @@ static int raid1_resize(mddev_t *mddev,
175 * worth it.
176 */
177 mddev->array_sectors = sectors;
178 - set_capacity(mddev->gendisk, mddev->array_sectors);
179 - mddev->changed = 1;
180 - if (mddev->array_sectors / 2 > mddev->size &&
181 - mddev->recovery_cp == MaxSector) {
182 - mddev->recovery_cp = mddev->size << 1;
183 - set_bit(MD_RECOVERY_NEEDED, &mddev->recovery);
184 + if (mddev->queue->end_sector == 0) {
185 + set_capacity(mddev->gendisk, mddev->array_sectors);
186 + mddev->changed = 1;
187 + if (mddev->array_sectors / 2 > mddev->size &&
188 + mddev->recovery_cp == MaxSector) {
189 + mddev->recovery_cp = mddev->size << 1;
190 + set_bit(MD_RECOVERY_NEEDED, &mddev->recovery);
191 + }
192 }
193 mddev->size = mddev->array_sectors / 2;
194 mddev->resync_max_sectors = sectors;
195 --- linux-2.6.27-SLE11_BRANCH.orig/drivers/md/raid5.c
196 +++ linux-2.6.27-SLE11_BRANCH/drivers/md/raid5.c
197 @@ -4650,7 +4650,8 @@ static int raid5_resize(mddev_t *mddev,
198 sectors &= ~((sector_t)mddev->chunk_size/512 - 1);
199 mddev->array_sectors = sectors * (mddev->raid_disks
200 - conf->max_degraded);
201 - set_capacity(mddev->gendisk, mddev->array_sectors);
202 + if (mddev->queue->end_sector == 0)
203 + set_capacity(mddev->gendisk, mddev->array_sectors);
204 mddev->changed = 1;
205 if (sectors/2 > mddev->size && mddev->recovery_cp == MaxSector) {
206 mddev->recovery_cp = mddev->size << 1;
207 @@ -4788,11 +4789,13 @@ static void end_reshape(raid5_conf_t *co
208 if (!test_bit(MD_RECOVERY_INTR, &conf->mddev->recovery)) {
209 conf->mddev->array_sectors = 2 * conf->mddev->size *
210 (conf->raid_disks - conf->max_degraded);
211 - set_capacity(conf->mddev->gendisk, conf->mddev->array_sectors);
212 + if (conf->mddev->queue->end_sector == 0)
213 + set_capacity(conf->mddev->gendisk,
214 + conf->mddev->array_sectors);
215 conf->mddev->changed = 1;
216
217 bdev = bdget_disk(conf->mddev->gendisk, 0);
218 - if (bdev) {
219 + if (bdev && conf->mddev->queue->end_sector == 0) {
220 mutex_lock(&bdev->bd_inode->i_mutex);
221 i_size_write(bdev->bd_inode,
222 (loff_t)conf->mddev->array_sectors << 9);