dev_extent_hole_check(device, &search_start, &hole_size,
num_bytes);
- if (hole_size > max_hole_size) {
+ /*
+ * Once we find a hole of sufficient size we
+ * ignore any larger holes that may appear at
+ * higher device offsets. If we later find a
+ * hole that is sufficiently large, but aligned,
+ * we'll use that instead.
+ */
+ if (hole_size > max_hole_size && max_hole_size < num_bytes) {
max_hole_start = search_start;
max_hole_size = hole_size;
}
/*
- * If this free space is greater than which we need,
- * it must be the max free space that we have found
- * until now, so max_hole_start must point to the start
- * of this free space and the length of this free space
- * is stored in max_hole_size. Thus, we return
- * max_hole_start and max_hole_size and go back to the
- * caller.
+ * If we find a hole that is aligned and as large
+ * as we need, then exit early with that hole.
*/
- if (hole_size >= num_bytes) {
+ if (hole_size >= num_bytes && (search_start & (SZ_1G - 1)) == SZ_1M) {
+ max_hole_start = search_start;
+ max_hole_size = hole_size;
ret = 0;
goto out;
}
goto again;
}
- if (hole_size > max_hole_size) {
+ /*
+ * If this is a larger hole it might not be aligned.
+ * Keep the hole we found above if it was large enough.
+ */
+ if (hole_size > max_hole_size && max_hole_size < num_bytes) {
+ max_hole_start = search_start;
+ max_hole_size = hole_size;
+ }
+
+ /*
+ * The last hole may be aligned and longer than any other,
+ * so do the aligned check and exit early again.
+ */
+ if (hole_size >= num_bytes && (search_start & (SZ_1G - 1)) == SZ_1M) {
max_hole_start = search_start;
max_hole_size = hole_size;
+ ret = 0;
+ goto out;
}
}