- if (st->minor_version && !may_change &&
- __le64_to_cpu(sb->data_offset) - __le64_to_cpu(sb->super_offset) < 8)
- return 0; /* doesn't fit */
+ switch(st->minor_version) {
+ case 0:
+ /* either 3K after the superblock, or some amount of space
+ * before.
+ */
+ if (may_change) {
+ /* We are creating array, so we *know* how much room has
+ * been left.
+ */
+ offset = 0;
+ if (__le64_to_cpu(sb->size) >= 200*1024*1024*2)
+ room = 128*2;
+ else if (__le64_to_cpu(sb->size) > 8*1024*1024*2)
+ room = 64*2;
+ else {
+ room = 3*2;
+ offset = 2;
+ }
+ } else {
+ room = __le64_to_cpu(sb->super_offset)
+ - __le64_to_cpu(sb->data_offset)
+ - __le64_to_cpu(sb->data_size);
+ /* remove '1 ||' when we can set offset via sysfs */
+ if (1 || (room < 3*2 &&
+ __le32_to_cpu(sb->max_dev) <= 384)) {
+ room = 3*2;
+ offset = 1*2;
+ } else {
+ offset = 0; /* means movable offset */
+ }
+ }
+ break;
+ case 1:
+ case 2: /* between superblock and data */
+ if (may_change) {
+ offset = 4*2;
+ if (__le64_to_cpu(sb->size) >= 200*1024*1024*2)
+ room = 128*2;
+ else if (__le64_to_cpu(sb->size) > 8*1024*1024*2)
+ room = 64*2;
+ else
+ room = 3*2;
+ } else {
+ room = __le64_to_cpu(sb->data_offset)
+ - __le64_to_cpu(sb->super_offset);
+ if (1 || __le32_to_cpu(sb->max_dev) <= 384) {
+ room -= 2;
+ offset = 2;
+ } else {
+ room -= 4*2;
+ offset = 4*2;
+ }
+ }
+ break;
+ }