uint32_t stripe_size);
int dm_tree_node_add_mirror_target(struct dm_tree_node *node,
uint64_t size);
+
+/* Mirror log flags */
+#define DM_NOSYNC 0x00000001 /* Known already in sync */
+#define DM_FORCESYNC 0x00000002 /* Force resync */
+#define DM_BLOCK_ON_ERROR 0x00000004 /* On error, suspend I/O */
+
int dm_tree_node_add_mirror_target_log(struct dm_tree_node *node,
uint32_t region_size,
unsigned clustered,
+ uint32_t flags,
const char *log_uuid,
unsigned area_count);
int dm_tree_node_add_target_area(struct dm_tree_node *node,
#define dm_bit_copy(bs1, bs2) \
memcpy(bs1 + 1, bs2 + 1, ((*bs1 / DM_BITS_PER_INT) + 1) * sizeof(int))
+/* Returns number of set bits */
+static inline unsigned hweight32(uint32_t i)
+{
+ unsigned r = (i & 0x55555555) + ((i >> 1) & 0x55555555);
+
+ r = (r & 0x33333333) + ((r >> 2) & 0x33333333);
+ r = (r & 0x0F0F0F0F) + ((r >> 4) & 0x0F0F0F0F);
+ r = (r & 0x00FF00FF) + ((r >> 8) & 0x00FF00FF);
+ return (r & 0x0000FFFF) + ((r >> 16) & 0x0000FFFF);
+}
+
/****************
* hash functions
****************/
uint32_t region_size; /* Mirror */
unsigned clustered; /* Mirror */
unsigned mirror_area_count; /* Mirror */
+ uint32_t flags; /* Mirror log */
};
/* Per-device properties */
static int _emit_segment_line(struct dm_task *dmt, struct load_segment *seg, uint64_t *seg_start, char *params, size_t paramsize)
{
+ unsigned log_parm_count;
int pos = 0;
int tw;
int r;
char originbuf[10], cowbuf[10], logbuf[10];
+ const char *logtype;
switch(seg->type) {
case SEG_ERROR:
}
pos += tw;
}
- if (!seg->log) {
- if ((tw = _dm_snprintf(params + pos, paramsize - pos, "core 1 ")) < 0) {
- stack; /* Out of space */
- return -1;
- }
- pos += tw;
- } else {
+
+ log_parm_count = hweight32(seg->flags) + 1;
+
+ if (!seg->log)
+ logtype = "core";
+ else {
+ logtype = "disk";
+ log_parm_count++;
if (!_build_dev_string(logbuf, sizeof(logbuf), seg->log))
return_0;
- if ((tw = _dm_snprintf(params + pos, paramsize - pos, "disk 2 %s ", logbuf)) < 0) {
+ }
+
+ if ((tw = _dm_snprintf(params + pos, paramsize - pos, "%s %u ", logtype, log_parm_count)) < 0) {
+ stack; /* Out of space */
+ return -1;
+ }
+ pos += tw;
+
+ if (seg->log) {
+ if ((tw = _dm_snprintf(params + pos, paramsize - pos, "%s ", logbuf)) < 0) {
stack; /* Out of space */
return -1;
}
pos += tw;
}
- if ((tw = _dm_snprintf(params + pos, paramsize - pos, "%u %u ", seg->region_size, seg->mirror_area_count)) < 0) {
+
+ if ((tw = _dm_snprintf(params + pos, paramsize - pos, "%u ", seg->region_size)) < 0) {
stack; /* Out of space */
return -1;
}
pos += tw;
+
+ if ((seg->flags & DM_NOSYNC)) {
+ if ((tw = _dm_snprintf(params + pos, paramsize - pos, "nosync ")) < 0) {
+ stack; /* Out of space */
+ return -1;
+ }
+ pos += tw;
+ } else if ((seg->flags & DM_FORCESYNC)) {
+ if ((tw = _dm_snprintf(params + pos, paramsize - pos, "sync ")) < 0) {
+ stack; /* Out of space */
+ return -1;
+ }
+ pos += tw;
+ }
+
+ if ((seg->flags & DM_BLOCK_ON_ERROR)) {
+ if ((tw = _dm_snprintf(params + pos, paramsize - pos, "block_on_error ")) < 0) {
+ stack; /* Out of space */
+ return -1;
+ }
+ pos += tw;
+ }
+
+ if ((tw = _dm_snprintf(params + pos, paramsize - pos, "%u ", seg->mirror_area_count)) < 0) {
+ stack; /* Out of space */
+ return -1;
+ }
+ pos += tw;
+
break;
case SEG_SNAPSHOT:
if (!_build_dev_string(originbuf, sizeof(originbuf), seg->origin))
int dm_tree_node_add_mirror_target_log(struct dm_tree_node *node,
uint32_t region_size,
unsigned clustered,
+ uint32_t flags,
const char *log_uuid,
unsigned area_count)
{
seg->region_size = region_size;
seg->clustered = clustered;
seg->mirror_area_count = area_count;
+ seg->flags = flags;
return 1;
}