diff options
Diffstat (limited to 'daemons/lvmlockd/lvmlockd-dlm.c')
-rw-r--r-- | daemons/lvmlockd/lvmlockd-dlm.c | 97 |
1 files changed, 53 insertions, 44 deletions
diff --git a/daemons/lvmlockd/lvmlockd-dlm.c b/daemons/lvmlockd/lvmlockd-dlm.c index 664082123..7f65abc5c 100644 --- a/daemons/lvmlockd/lvmlockd-dlm.c +++ b/daemons/lvmlockd/lvmlockd-dlm.c @@ -343,7 +343,7 @@ static int to_dlm_mode(int ld_mode) } static int lm_adopt_dlm(struct lockspace *ls, struct resource *r, int ld_mode, - uint32_t *r_version) + struct val_blk *vb_out) { struct lm_dlm *lmd = (struct lm_dlm *)ls->lm_data; struct rd_dlm *rdd = (struct rd_dlm *)r->lm_data; @@ -352,7 +352,7 @@ static int lm_adopt_dlm(struct lockspace *ls, struct resource *r, int ld_mode, int mode; int rv; - *r_version = 0; + memset(vb_out, 0, sizeof(struct val_blk)); if (!r->lm_init) { rv = lm_add_resource_dlm(ls, r, 0); @@ -431,15 +431,13 @@ static int lm_adopt_dlm(struct lockspace *ls, struct resource *r, int ld_mode, */ int lm_lock_dlm(struct lockspace *ls, struct resource *r, int ld_mode, - uint32_t *r_version, int adopt) + struct val_blk *vb_out, int adopt) { struct lm_dlm *lmd = (struct lm_dlm *)ls->lm_data; struct rd_dlm *rdd = (struct rd_dlm *)r->lm_data; struct dlm_lksb *lksb; struct val_blk vb; uint32_t flags = 0; - uint16_t vb_version; - uint16_t vb_flags; int mode; int rv; @@ -447,7 +445,7 @@ int lm_lock_dlm(struct lockspace *ls, struct resource *r, int ld_mode, /* When adopting, we don't follow the normal method of acquiring a NL lock then converting it to the desired mode. */ - return lm_adopt_dlm(ls, r, ld_mode, r_version); + return lm_adopt_dlm(ls, r, ld_mode, vb_out); } if (!r->lm_init) { @@ -475,7 +473,7 @@ int lm_lock_dlm(struct lockspace *ls, struct resource *r, int ld_mode, log_debug("S %s R %s lock_dlm", ls->name, r->name); if (daemon_test) { - *r_version = 0; + memset(vb_out, 0, sizeof(struct val_blk)); return 0; } @@ -513,35 +511,22 @@ lockrv: if (lksb->sb_flags & DLM_SBF_VALNOTVALID) { log_debug("S %s R %s lock_dlm VALNOTVALID", ls->name, r->name); memset(rdd->vb, 0, sizeof(struct val_blk)); - *r_version = 0; + memset(vb_out, 0, sizeof(struct val_blk)); goto out; } + /* + * 'vb' contains disk endian values, not host endian. + * It is copied directly to rdd->vb which is also kept + * in disk endian form. + * vb_out is returned to the caller in host endian form. + */ memcpy(&vb, lksb->sb_lvbptr, sizeof(struct val_blk)); - vb_version = le16_to_cpu(vb.version); - vb_flags = le16_to_cpu(vb.flags); - - if (vb_version && ((vb_version & 0xFF00) > (VAL_BLK_VERSION & 0xFF00))) { - log_error("S %s R %s lock_dlm ignore vb_version %x", - ls->name, r->name, vb_version); - *r_version = 0; - free(rdd->vb); - rdd->vb = NULL; - lksb->sb_lvbptr = NULL; - goto out; - } - - *r_version = le32_to_cpu(vb.r_version); - memcpy(rdd->vb, &vb, sizeof(vb)); /* rdd->vb saved as le */ + memcpy(rdd->vb, &vb, sizeof(vb)); - log_debug("S %s R %s lock_dlm get r_version %u flags %x", - ls->name, r->name, *r_version, vb_flags); - - if (vb_flags & VBF_REMOVED) { - log_debug("S %s R %s lock_dlm VG has been removed", - ls->name, r->name); - return -EREMOVED; - } + vb_out->version = le16_to_cpu(vb.version); + vb_out->flags = le16_to_cpu(vb.flags); + vb_out->r_version = le32_to_cpu(vb.r_version); } out: return 0; @@ -602,12 +587,12 @@ int lm_unlock_dlm(struct lockspace *ls, struct resource *r, struct lm_dlm *lmd = (struct lm_dlm *)ls->lm_data; struct rd_dlm *rdd = (struct rd_dlm *)r->lm_data; struct dlm_lksb *lksb = &rdd->lksb; + struct val_blk vb_prev; + struct val_blk vb_next; uint32_t flags = 0; + int new_vb = 0; int rv; - log_debug("S %s R %s unlock_dlm r_version %u flags %x", - ls->name, r->name, r_version, lmu_flags); - /* * Do not set PERSISTENT, because we don't need an orphan * NL lock to protect anything. @@ -616,22 +601,45 @@ int lm_unlock_dlm(struct lockspace *ls, struct resource *r, flags |= LKF_CONVERT; if (rdd->vb && (r->mode == LD_LK_EX)) { - if (!rdd->vb->version) { - /* first time vb has been written */ - rdd->vb->version = cpu_to_le16(VAL_BLK_VERSION); + + /* vb_prev and vb_next are in disk endian form */ + memcpy(&vb_prev, rdd->vb, sizeof(struct val_blk)); + memcpy(&vb_next, rdd->vb, sizeof(struct val_blk)); + + if (!vb_prev.version) { + vb_next.version = cpu_to_le16(VAL_BLK_VERSION); + new_vb = 1; } - if (r_version) - rdd->vb->r_version = cpu_to_le32(r_version); - if ((lmu_flags & LMUF_FREE_VG) && (r->type == LD_RT_VG)) - rdd->vb->flags = cpu_to_le16(VBF_REMOVED); + if ((lmu_flags & LMUF_FREE_VG) && (r->type == LD_RT_VG)) { + vb_next.flags = cpu_to_le16(VBF_REMOVED); + new_vb = 1; + } - memcpy(lksb->sb_lvbptr, rdd->vb, sizeof(struct val_blk)); + if (r_version) { + vb_next.r_version = cpu_to_le32(r_version); + new_vb = 1; + } - log_debug("S %s R %s unlock_dlm set r_version %u", - ls->name, r->name, r_version); + if (new_vb) { + memcpy(rdd->vb, &vb_next, sizeof(struct val_blk)); + memcpy(lksb->sb_lvbptr, &vb_next, sizeof(struct val_blk)); + + log_debug("S %s R %s unlock_dlm vb old %x %x %u new %x %x %u", + ls->name, r->name, + le16_to_cpu(vb_prev.version), + le16_to_cpu(vb_prev.flags), + le32_to_cpu(vb_prev.r_version), + le16_to_cpu(vb_next.version), + le16_to_cpu(vb_next.flags), + le32_to_cpu(vb_next.r_version)); + } else { + log_debug("S %s R %s unlock_dlm vb unchanged", ls->name, r->name); + } flags |= LKF_VALBLK; + } else { + log_debug("S %s R %s unlock_dlm", ls->name, r->name); } if (daemon_test) @@ -700,3 +708,4 @@ int lm_is_running_dlm(void) return 0; return 1; } + |