Index: device-mapper.1.02.27/lib/libdm-deptree.c =================================================================== --- device-mapper.1.02.27.orig/lib/libdm-deptree.c 2010-03-03 21:04:28.000000000 +0800 +++ device-mapper.1.02.27/lib/libdm-deptree.c 2010-03-03 21:05:05.000000000 +0800 @@ -20,6 +20,7 @@ #include #include +#include #include @@ -1286,102 +1287,153 @@ return 1; } -static int _emit_segment_line(struct dm_task *dmt, struct load_segment *seg, uint64_t *seg_start, char *params, size_t paramsize) +#define EMIT_PARAMS(p, str...)\ +do {\ + int w;\ + if (( w = dm_snprintf(params + p, paramsize - (size_t)p, str)) < 0) {\ + stack; /* Out of space */\ + return -1;\ + }\ + p += w;\ +} while (0) + +static int _mirror_emit_segment_line(struct dm_task *dmt, + uint32_t major, uint32_t minor, + 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; + int r; + int block_on_error = 0; + int handle_errors = 0; + int dm_log_userspace = 0; + struct utsname uts; + unsigned log_parm_count; + int pos = 0; + char logbuf[13]; + const char *logtype; + + r = uname(&uts); + if (r) + return_0; + + if ((seg->flags & DM_BLOCK_ON_ERROR)) { + /* + * Originally, block_on_error was an argument to the log + * portion of the mirror CTR table. It was renamed to + * "handle_errors" and now resides in the 'features' + * section of the mirror CTR table (i.e. at the end). + * + * We can identify whether to use "block_on_error" or + * "handle_errors" by the dm-mirror module's version + * number (>= 1.12) or by the kernel version (>= 2.6.22). + */ + if (strncmp(uts.release, "2.6.22", 6) >= 0) + handle_errors = 1; + else + block_on_error = 1; + } + + if (seg->clustered) { + /* Cluster mirrors require a UUID */ + if (!seg->uuid) + return_0; - switch(seg->type) { - case SEG_ERROR: - case SEG_ZERO: - case SEG_LINEAR: - break; - case SEG_MIRRORED: - log_parm_count = 1; /* Region size */ - log_parm_count += hweight32(seg->flags); /* [no]sync, block_on_error etc. */ + /* + * Cluster mirrors used to have their own log + * types. Now they are accessed through the + * userspace log type. + * + * The dm-log-userspace module was added to the + * 2.6.31 kernel. + */ + if (strncmp(uts.release, "2.6.31", 6) >= 0) + dm_log_userspace = 1; + } + + /* Region size */ + log_parm_count = 1; + + /* [no]sync, block_on_error etc. */ + log_parm_count += hweight32(seg->flags); + + /* "handle_errors" is a feature arg now */ + if (handle_errors) + log_parm_count--; + + /* DM_CORELOG does not count in the param list */ + if (seg->flags & DM_CORELOG) + log_parm_count--; + + if (seg->clustered) { + log_parm_count++; /* For UUID */ + + if (!dm_log_userspace) + EMIT_PARAMS(pos, "clustered-"); + else + log_parm_count++; + } - if (seg->flags & DM_CORELOG) - log_parm_count--; /* DM_CORELOG does not count in the param list */ + if (!seg->log) + logtype = "core"; + else { + logtype = "disk"; + log_parm_count++; + if (!_build_dev_string(logbuf, sizeof(logbuf), seg->log)) + return_0; + } - if (seg->clustered) { - if (seg->uuid) - log_parm_count++; - if ((tw = _dm_snprintf(params + pos, paramsize - pos, "clustered-")) < 0) { - stack; /* Out of space */ - return -1; - } - pos += tw; - } - - if (!seg->log) - logtype = "core"; - else { - logtype = "disk"; - log_parm_count++; - if (!_build_dev_string(logbuf, sizeof(logbuf), seg->log)) - return_0; - } + if (dm_log_userspace) + EMIT_PARAMS(pos, "userspace %u %s clustered-%s", + log_parm_count, seg->uuid, logtype); + else + EMIT_PARAMS(pos, "%s %u", logtype, log_parm_count); - 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) + EMIT_PARAMS(pos, " %s", logbuf); - 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 ", seg->region_size)) < 0) { - stack; /* Out of space */ - return -1; - } - pos += tw; - - if (seg->clustered && seg->uuid) { - if ((tw = _dm_snprintf(params + pos, paramsize - pos, "%s ", seg->uuid)) < 0) { - stack; /* Out of space */ - return -1; - } - pos += tw; - } + EMIT_PARAMS(pos, " %u", seg->region_size); - 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; + if (seg->clustered && !dm_log_userspace) + EMIT_PARAMS(pos, " %s", seg->uuid); + if ((seg->flags & DM_NOSYNC)) + EMIT_PARAMS(pos, " nosync"); + else if ((seg->flags & DM_FORCESYNC)) + EMIT_PARAMS(pos, " sync"); + + if (block_on_error) + EMIT_PARAMS(pos, " block_on_error"); + + EMIT_PARAMS(pos, " %u ", seg->mirror_area_count); + + if ((r = _emit_areas_line(dmt, seg, params, paramsize, &pos)) <= 0) + return_0; + + if (handle_errors) + EMIT_PARAMS(pos, " 1 handle_errors"); + + return 1; +} + +static int _emit_segment_line(struct dm_task *dmt, + uint32_t major, uint32_t minor, + struct load_segment *seg, uint64_t *seg_start, + char *params, size_t paramsize) +{ + int pos = 0; + int r; + char originbuf[13], cowbuf[13]; + + switch(seg->type) { + case SEG_ERROR: + case SEG_ZERO: + case SEG_LINEAR: + break; + case SEG_MIRRORED: + /* Seperate into a standalone function */ + r = _mirror_emit_segment_line(dmt, major, minor, seg, seg_start, params, paramsize); + if (!r) + return_0; break; case SEG_SNAPSHOT: if (!_build_dev_string(originbuf, sizeof(originbuf), seg->origin)) @@ -1422,7 +1474,6 @@ case SEG_ZERO: break; case SEG_LINEAR: - case SEG_MIRRORED: case SEG_STRIPED: if ((r = _emit_areas_line(dmt, seg, params, paramsize, &pos)) <= 0) { stack; @@ -1442,8 +1493,9 @@ return 1; } -static int _emit_segment(struct dm_task *dmt, struct load_segment *seg, - uint64_t *seg_start) +static int _emit_segment(struct dm_task *dmt, + uint32_t major, uint32_t minor, + struct load_segment *seg, uint64_t *seg_start) { char *params; size_t paramsize = 4096; @@ -1456,7 +1508,7 @@ } params[0] = '\0'; - ret = _emit_segment_line(dmt, seg, seg_start, params, paramsize); + ret = _emit_segment_line(dmt, major, minor, seg, seg_start, params, paramsize); dm_free(params); if (!ret) @@ -1504,7 +1556,8 @@ log_error("Failed to disable open_count"); list_iterate_items(seg, &dnode->props.segs) - if (!_emit_segment(dmt, seg, &seg_start)) + if (!_emit_segment(dmt, dnode->info.major, dnode->info.minor, + seg, &seg_start)) goto_out; if (!dm_task_suppress_identical_reload(dmt))