[PATCH] Make sure update_super returns correct value.
For 'force' and 'assemble', update_super must return true if anything was changed. Also fix a bug with wonly handling in super0. Signed-off-by: Neil Brown <neilb@suse.de> ### Diffstat output ./super0.c | 18 ++++++++++++++---- ./super1.c | 7 +++++++ 2 files changed, 21 insertions(+), 4 deletions(-) diff ./super0.c~current~ ./super0.c
This commit is contained in:
parent
7fa42a0b5e
commit
c4d831e164
18
super0.c
18
super0.c
|
@ -317,6 +317,9 @@ static void getinfo_super0(struct mdinfo *info, void *sbv)
|
||||||
|
|
||||||
static int update_super0(struct mdinfo *info, void *sbv, char *update, char *devname, int verbose)
|
static int update_super0(struct mdinfo *info, void *sbv, char *update, char *devname, int verbose)
|
||||||
{
|
{
|
||||||
|
/* NOTE: for 'assemble' and 'force' we need to return non-zero if any change was made.
|
||||||
|
* For others, the return value is ignored.
|
||||||
|
*/
|
||||||
int rv = 0;
|
int rv = 0;
|
||||||
mdp_super_t *sb = sbv;
|
mdp_super_t *sb = sbv;
|
||||||
if (strcmp(update, "sparc2.2")==0 ) {
|
if (strcmp(update, "sparc2.2")==0 ) {
|
||||||
|
@ -367,18 +370,25 @@ static int update_super0(struct mdinfo *info, void *sbv, char *update, char *dev
|
||||||
sb->disks[i].state = 0;
|
sb->disks[i].state = 0;
|
||||||
}
|
}
|
||||||
if (strcmp(update, "force")==0) {
|
if (strcmp(update, "force")==0) {
|
||||||
|
__u32 ehi = sb->events_hi, elo = sb->events_lo;
|
||||||
sb->events_hi = (info->events>>32) & 0xFFFFFFFF;
|
sb->events_hi = (info->events>>32) & 0xFFFFFFFF;
|
||||||
sb->events_lo = (info->events) & 0xFFFFFFFF;
|
sb->events_lo = (info->events) & 0xFFFFFFFF;
|
||||||
if (sb->level == 5 || sb->level == 4 || sb->level == 6)
|
if (sb->events_hi != ehi ||
|
||||||
|
sb->events_lo != elo)
|
||||||
|
rv = 1;
|
||||||
|
if ((sb->level == 5 || sb->level == 4 || sb->level == 6) &&
|
||||||
|
(sb->state & (1 << MD_SB_CLEAN)) == 0) {
|
||||||
/* need to force clean */
|
/* need to force clean */
|
||||||
sb->state |= (1 << MD_SB_CLEAN);
|
sb->state |= (1 << MD_SB_CLEAN);
|
||||||
|
rv = 1;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
if (strcmp(update, "assemble")==0) {
|
if (strcmp(update, "assemble")==0) {
|
||||||
int d = info->disk.number;
|
int d = info->disk.number;
|
||||||
int wonly = sb->disks[d].state & (1<<MD_DISK_WRITEMOSTLY);
|
int wonly = sb->disks[d].state & (1<<MD_DISK_WRITEMOSTLY);
|
||||||
sb->disks[d].state &= ~(1<<MD_DISK_WRITEMOSTLY);
|
if ((sb->disks[d].state & ~(1<<MD_DISK_WRITEMOSTLY))
|
||||||
if (sb->disks[d].state != info->disk.state) {
|
!= info->disk.state) {
|
||||||
sb->disks[d].state = info->disk.state & wonly;
|
sb->disks[d].state = info->disk.state | wonly;
|
||||||
rv = 1;
|
rv = 1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
7
super1.c
7
super1.c
|
@ -423,14 +423,21 @@ static void getinfo_super1(struct mdinfo *info, void *sbv)
|
||||||
|
|
||||||
static int update_super1(struct mdinfo *info, void *sbv, char *update, char *devname, int verbose)
|
static int update_super1(struct mdinfo *info, void *sbv, char *update, char *devname, int verbose)
|
||||||
{
|
{
|
||||||
|
/* NOTE: for 'assemble' and 'force' we need to return non-zero if any change was made.
|
||||||
|
* For others, the return value is ignored.
|
||||||
|
*/
|
||||||
int rv = 0;
|
int rv = 0;
|
||||||
struct mdp_superblock_1 *sb = sbv;
|
struct mdp_superblock_1 *sb = sbv;
|
||||||
|
|
||||||
if (strcmp(update, "force")==0) {
|
if (strcmp(update, "force")==0) {
|
||||||
|
if (sb->events != __cpu_to_le64(info->events))
|
||||||
|
rv = 1;
|
||||||
sb->events = __cpu_to_le64(info->events);
|
sb->events = __cpu_to_le64(info->events);
|
||||||
switch(__le32_to_cpu(sb->level)) {
|
switch(__le32_to_cpu(sb->level)) {
|
||||||
case 5: case 4: case 6:
|
case 5: case 4: case 6:
|
||||||
/* need to force clean */
|
/* need to force clean */
|
||||||
|
if (sb->resync_offset != ~0ULL)
|
||||||
|
rv = 1;
|
||||||
sb->resync_offset = ~0ULL;
|
sb->resync_offset = ~0ULL;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue