goto abort;
}
} else {
+ if (s->logical_block_size &&
+ sysfs_set_num(&info, NULL, "logical_block_size",
+ s->logical_block_size)) {
+ pr_err("Failed to set logical_block_size %u\n",
+ s->logical_block_size);
+ goto abort;
+ }
+
/* param is not actually used */
mdu_param_t param;
if (ioctl(mdfd, RUN_ARRAY, ¶m)) {
{"home-cluster", 1, 0, ClusterName},
{"write-journal", 1, 0, WriteJournal},
{"consistency-policy", 1, 0, 'k'},
+ {"logical-block-size", 1, 0, LogicalBlockSize},
/* For assemble */
{"uuid", 1, 0, 'u'},
" --consistency-policy= : Specify the policy that determines how the array\n"
" -k : maintains consistency in case of unexpected shutdown.\n"
" --write-zeroes : Write zeroes to the disks before creating. This will bypass initial sync.\n"
+" --logical-block-size= : Set the logical block size (in Byte) for the RAID.\n"
"\n"
;
in some cases. See CONSISTENCY POLICY CHANGES below.
.RE
+.TP
+.BR \-\-logical\-block\-size=
+The option can only be used in Create mode and metadata version is 1.x. If during
+creation, the member disks have mixed LBS values (512 and 4K), the array will
+default to using 4K as its LBS. However, if the 4K disk is removed and the system
+is rebooted, the array's LBS will fall back to 512. If the array's LBS is 512,
+then a disk with a 4K LBS cannot be added to the array.
+
+In general, choosing a large LBS for the array is beneficial, but it can
+introduce write-amplification. The larger the array's LBS, the larger the write
+size to each member disk. Therefore, users should evaluate their actual workload
+and choose an appropriate LBS accordingly.
+
+The option should be set by the user based on their own usage scenario, choosing
+an LBS value that best matches their needs.
.SH For assemble:
#include "xmalloc.h"
#include <ctype.h>
+#include <limits.h>
/**
* set_bitmap_value() - set bitmap value.
return MDADM_STATUS_ERROR;
}
+/*
+ * Logical block size settings only support metadata 1.x.
+ */
+static mdadm_status_t shape_set_logical_block_size(struct shape *s, char *optarg)
+{
+ char *end;
+ unsigned long size = strtoul(optarg, &end, 10);
+
+ if (end != optarg + strlen(optarg)) {
+ pr_err("logical block size [%s] can't be converted to an integer\n", optarg);
+ return MDADM_STATUS_ERROR;
+ } else if (errno == ERANGE) {
+ pr_err("logical block size [%s] more than ULONG_MAX\n", optarg);
+ return MDADM_STATUS_ERROR;
+ }
+
+ /* Here only perform a simple check, while detailed check will be handled in kernel */
+ if (size == 0 || size > UINT_MAX) {
+ pr_err("The range of logical-block-size is (0, %u], current is %lu\n",
+ UINT_MAX, size);
+ return MDADM_STATUS_ERROR;
+ }
+
+ s->logical_block_size = size;
+ return MDADM_STATUS_SUCCESS;
+}
+
static int scan_assemble(struct supertype *ss,
struct context *c,
struct mddev_ident *ident);
.consistency_policy = CONSISTENCY_POLICY_UNKNOWN,
.data_offset = INVALID_SECTORS,
.btype = BitmapUnknown,
+ .logical_block_size = 0,
};
char sys_hostname[256];
exit(2);
}
continue;
+ case O(CREATE, LogicalBlockSize):
+ if (shape_set_logical_block_size(&s, optarg) != MDADM_STATUS_SUCCESS)
+ exit(2);
+ continue;
}
/* We have now processed all the valid options. Anything else is
* an error
}
+ /* When metadata is not specified using the -e option,
+ * metadata version is 1.2 by default. So the logical
+ * block size can be configured.
+ * When using the -e option, need to check if the
+ * metadata version is 1.x.
+ */
+ if (s.logical_block_size && ss && strcmp(ss->ss->name, "1.x")){
+ pr_err("The logical block size is only supported for metadata 1.x.\n");
+ pr_err("Current metadata version is %s\n", ss->ss->name);
+ exit(2);
+ }
+
if (print_help) {
char *help_text;
if (print_help == 2)
ClusterConfirm,
WriteJournal,
ConsistencyPolicy,
+ LogicalBlockSize,
};
enum update_opt {
unsigned long long data_offset;
int consistency_policy;
change_dir_t direction;
+ unsigned int logical_block_size;
};
/* List of device names - wildcards expanded */