+ devsize = ldsize >> 9;
+ if (devsize < 24) {
+ *freesize = 0;
+ return 0;
+ }
+
+ /* creating: allow suitable space for bitmap */
+ bmspace = choose_bm_space(devsize);
+
+ if (data_offset == INVALID_SECTORS)
+ data_offset = st->data_offset;
+ if (data_offset == INVALID_SECTORS)
+ switch (st->minor_version) {
+ case 0:
+ data_offset = 0;
+ break;
+ case 1:
+ case 2:
+ /* Choose data offset appropriate for this device
+ * and use as default for whole array.
+ * The data_offset must allow for bitmap space
+ * and base metadata, should allow for some headroom
+ * for reshape, and should be rounded to multiple
+ * of 1M.
+ * Headroom is limited to 128M, but aim for about 0.1%
+ */
+ headroom = 128*1024*2;
+ while ((headroom << 10) > devsize &&
+ (*chunk == 0 ||
+ headroom / 2 >= ((unsigned)(*chunk)*2)*2))
+ headroom >>= 1;
+ data_offset = 12*2 + bmspace + headroom;
+ #define ONE_MEG (2*1024)
+ if (data_offset > ONE_MEG)
+ data_offset = (data_offset / ONE_MEG) * ONE_MEG;
+ break;
+ }
+ if (st->data_offset == INVALID_SECTORS)
+ st->data_offset = data_offset;
+ switch(st->minor_version) {
+ case 0: /* metadata at end. Round down and subtract space to reserve */
+ devsize = (devsize & ~(4ULL*2-1));
+ /* space for metadata, bblog, bitmap */
+ devsize -= 8*2 + 8 + bmspace;
+ break;
+ case 1:
+ case 2:
+ devsize -= data_offset;
+ break;
+ }
+ *freesize = devsize;