int lm_convert_dlm(struct lockspace *ls, struct resource *r, int ld_mode, uint32_t r_version) { 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; uint32_t mode; uint32_t flags = 0; int rv; log_debug("S %s R %s convert_dlm", ls->name, r->name); flags |= LKF_CONVERT; flags |= LKF_NOQUEUE; flags |= LKF_PERSISTENT; if (rdd->vb && r_version && (r->mode == LD_LK_EX)) { if (!rdd->vb->version) { /* first time vb has been written */ rdd->vb->version = cpu_to_le16(VAL_BLK_VERSION); } rdd->vb->r_version = cpu_to_le32(r_version); memcpy(lksb->sb_lvbptr, rdd->vb, sizeof(struct val_blk)); log_debug("S %s R %s convert_dlm set r_version %u", ls->name, r->name, r_version); flags |= LKF_VALBLK; } mode = to_dlm_mode(ld_mode); if (daemon_test) return 0; rv = dlm_ls_lock_wait(lmd->dh, mode, lksb, flags, r->name, strlen(r->name), 0, NULL, NULL, NULL); if (rv == -1 && errno == EAGAIN) { /* FIXME: When does this happen? Should something different be done? */ log_error("S %s R %s convert_dlm mode %d rv EAGAIN", ls->name, r->name, mode); return -EAGAIN; } if (rv < 0) { log_error("S %s R %s convert_dlm error %d", ls->name, r->name, rv); } return rv; }
static void lock_sync(int i, int mode) { char name[DLM_RESNAME_MAXLEN]; int flags = 0; int rv; struct lk *lk; lk = get_lock(i); if (!lk) return; if (noqueue) flags |= LKF_NOQUEUE; if (persistent) flags |= LKF_PERSISTENT; if (lk->lksb.sb_lkid) flags |= LKF_CONVERT; memset(name, 0, sizeof(name)); snprintf(name, sizeof(name), "test%d", (i % maxr)); log_verbose("lock_sync: %d rqmode %d flags %x lkid %x %s\n", i, mode, flags, lk->lksb.sb_lkid, name); rv = dlm_ls_lock_wait(dh, mode, &lk->lksb, flags, name, strlen(name), 0, (void *) lk, bastfn, NULL); log_verbose("lock_sync: %d rv %d sb_lkid %x sb_status %x\n", i, rv, lk->lksb.sb_lkid, lk->lksb.sb_status); if (!rv) { lk->grmode = mode; lk->rqmode = -1; } else if (rv == EAGAIN) { if (lk->grmode == -1) memset(&lk->lksb, 0, sizeof(struct dlm_lksb)); } else { printf("unknown rv %d\n", rv); exit(-1); } }
static int lm_add_resource_dlm(struct lockspace *ls, struct resource *r, int with_lock_nl) { struct lm_dlm *lmd = (struct lm_dlm *)ls->lm_data; struct rd_dlm *rdd = (struct rd_dlm *)r->lm_data; uint32_t flags = 0; char *buf; int rv; if (r->type == LD_RT_GL || r->type == LD_RT_VG) { buf = malloc(sizeof(struct val_blk) + DLM_LVB_LEN); if (!buf) return -ENOMEM; memset(buf, 0, sizeof(struct val_blk) + DLM_LVB_LEN); rdd->vb = (struct val_blk *)buf; rdd->lksb.sb_lvbptr = buf + sizeof(struct val_blk); flags |= LKF_VALBLK; } if (!with_lock_nl) goto out; /* because this is a new NL lock request */ flags |= LKF_EXPEDITE; if (daemon_test) goto out; rv = dlm_ls_lock_wait(lmd->dh, LKM_NLMODE, &rdd->lksb, flags, r->name, strlen(r->name), 0, NULL, NULL, NULL); if (rv < 0) { log_error("S %s R %s add_resource_dlm lock error %d", ls->name, r->name, rv); return rv; } out: return 0; }
int lm_unlock_dlm(struct lockspace *ls, struct resource *r, uint32_t r_version, uint32_t lmu_flags) { 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; /* * Do not set PERSISTENT, because we don't need an orphan * NL lock to protect anything. */ flags |= LKF_CONVERT; if (rdd->vb && (r->mode == LD_LK_EX)) { /* 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 ((lmu_flags & LMUF_FREE_VG) && (r->type == LD_RT_VG)) { vb_next.flags = cpu_to_le16(VBF_REMOVED); new_vb = 1; } if (r_version) { vb_next.r_version = cpu_to_le32(r_version); new_vb = 1; } 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) return 0; rv = dlm_ls_lock_wait(lmd->dh, LKM_NLMODE, lksb, flags, r->name, strlen(r->name), 0, NULL, NULL, NULL); if (rv < 0) { log_error("S %s R %s unlock_dlm error %d", ls->name, r->name, rv); } return rv; }
int lm_lock_dlm(struct lockspace *ls, struct resource *r, int ld_mode, 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; int mode; int rv; if (adopt) { /* 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, vb_out); } if (!r->lm_init) { rv = lm_add_resource_dlm(ls, r, 1); if (rv < 0) return rv; r->lm_init = 1; } lksb = &rdd->lksb; flags |= LKF_CONVERT; flags |= LKF_NOQUEUE; flags |= LKF_PERSISTENT; if (rdd->vb) flags |= LKF_VALBLK; mode = to_dlm_mode(ld_mode); if (mode < 0) { log_error("lock_dlm invalid mode %d", ld_mode); return -EINVAL; } log_debug("S %s R %s lock_dlm", ls->name, r->name); if (daemon_test) { memset(vb_out, 0, sizeof(struct val_blk)); return 0; } /* * The dlm lvb bug means that converting NL->EX will not return * the latest lvb, so we have to convert NL->PR->EX to reread it. */ if (dlm_has_lvb_bug && (ld_mode == LD_LK_EX)) { rv = dlm_ls_lock_wait(lmd->dh, LKM_PRMODE, lksb, flags, r->name, strlen(r->name), 0, NULL, NULL, NULL); if (rv == -1) { log_debug("S %s R %s lock_dlm acquire mode PR for %d rv %d", ls->name, r->name, mode, rv); goto lockrv; } /* Fall through to request EX. */ } rv = dlm_ls_lock_wait(lmd->dh, mode, lksb, flags, r->name, strlen(r->name), 0, NULL, NULL, NULL); lockrv: if (rv == -1 && errno == EAGAIN) { log_debug("S %s R %s lock_dlm acquire mode %d rv EAGAIN", ls->name, r->name, mode); return -EAGAIN; } if (rv < 0) { log_error("S %s R %s lock_dlm acquire error %d errno %d", ls->name, r->name, rv, errno); return rv; } if (rdd->vb) { 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)); 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)); memcpy(rdd->vb, &vb, sizeof(vb)); 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; }