|
@@ -102,6 +102,7 @@
|
|
|
#define OCFS2_TEXT_UUID_LEN 32
|
|
|
#define OCFS2_CONTROL_MESSAGE_VERNUM_LEN 2
|
|
|
#define OCFS2_CONTROL_MESSAGE_NODENUM_LEN 8
|
|
|
+#define VERSION_LOCK "version_lock"
|
|
|
|
|
|
enum ocfs2_connection_type {
|
|
|
WITH_CONTROLD,
|
|
@@ -118,6 +119,9 @@ struct ocfs2_live_connection {
|
|
|
enum ocfs2_connection_type oc_type;
|
|
|
atomic_t oc_this_node;
|
|
|
int oc_our_slot;
|
|
|
+ struct dlm_lksb oc_version_lksb;
|
|
|
+ char oc_lvb[DLM_LVB_LEN];
|
|
|
+ struct completion oc_sync_wait;
|
|
|
};
|
|
|
|
|
|
struct ocfs2_control_private {
|
|
@@ -796,6 +800,103 @@ static int fs_protocol_compare(struct ocfs2_protocol_version *existing,
|
|
|
return 0;
|
|
|
}
|
|
|
|
|
|
+static void lvb_to_version(char *lvb, struct ocfs2_protocol_version *ver)
|
|
|
+{
|
|
|
+ struct ocfs2_protocol_version *pv =
|
|
|
+ (struct ocfs2_protocol_version *)lvb;
|
|
|
+ /*
|
|
|
+ * ocfs2_protocol_version has two u8 variables, so we don't
|
|
|
+ * need any endian conversion.
|
|
|
+ */
|
|
|
+ ver->pv_major = pv->pv_major;
|
|
|
+ ver->pv_minor = pv->pv_minor;
|
|
|
+}
|
|
|
+
|
|
|
+static void version_to_lvb(struct ocfs2_protocol_version *ver, char *lvb)
|
|
|
+{
|
|
|
+ struct ocfs2_protocol_version *pv =
|
|
|
+ (struct ocfs2_protocol_version *)lvb;
|
|
|
+ /*
|
|
|
+ * ocfs2_protocol_version has two u8 variables, so we don't
|
|
|
+ * need any endian conversion.
|
|
|
+ */
|
|
|
+ pv->pv_major = ver->pv_major;
|
|
|
+ pv->pv_minor = ver->pv_minor;
|
|
|
+}
|
|
|
+
|
|
|
+static void sync_wait_cb(void *arg)
|
|
|
+{
|
|
|
+ struct ocfs2_cluster_connection *conn = arg;
|
|
|
+ struct ocfs2_live_connection *lc = conn->cc_private;
|
|
|
+ complete(&lc->oc_sync_wait);
|
|
|
+}
|
|
|
+
|
|
|
+static int sync_unlock(struct ocfs2_cluster_connection *conn,
|
|
|
+ struct dlm_lksb *lksb, char *name)
|
|
|
+{
|
|
|
+ int error;
|
|
|
+ struct ocfs2_live_connection *lc = conn->cc_private;
|
|
|
+
|
|
|
+ error = dlm_unlock(conn->cc_lockspace, lksb->sb_lkid, 0, lksb, conn);
|
|
|
+ if (error) {
|
|
|
+ printk(KERN_ERR "%s lkid %x error %d\n",
|
|
|
+ name, lksb->sb_lkid, error);
|
|
|
+ return error;
|
|
|
+ }
|
|
|
+
|
|
|
+ wait_for_completion(&lc->oc_sync_wait);
|
|
|
+
|
|
|
+ if (lksb->sb_status != -DLM_EUNLOCK) {
|
|
|
+ printk(KERN_ERR "%s lkid %x status %d\n",
|
|
|
+ name, lksb->sb_lkid, lksb->sb_status);
|
|
|
+ return -1;
|
|
|
+ }
|
|
|
+ return 0;
|
|
|
+}
|
|
|
+
|
|
|
+static int sync_lock(struct ocfs2_cluster_connection *conn,
|
|
|
+ int mode, uint32_t flags,
|
|
|
+ struct dlm_lksb *lksb, char *name)
|
|
|
+{
|
|
|
+ int error, status;
|
|
|
+ struct ocfs2_live_connection *lc = conn->cc_private;
|
|
|
+
|
|
|
+ error = dlm_lock(conn->cc_lockspace, mode, lksb, flags,
|
|
|
+ name, strlen(name),
|
|
|
+ 0, sync_wait_cb, conn, NULL);
|
|
|
+ if (error) {
|
|
|
+ printk(KERN_ERR "%s lkid %x flags %x mode %d error %d\n",
|
|
|
+ name, lksb->sb_lkid, flags, mode, error);
|
|
|
+ return error;
|
|
|
+ }
|
|
|
+
|
|
|
+ wait_for_completion(&lc->oc_sync_wait);
|
|
|
+
|
|
|
+ status = lksb->sb_status;
|
|
|
+
|
|
|
+ if (status && status != -EAGAIN) {
|
|
|
+ printk(KERN_ERR "%s lkid %x flags %x mode %d status %d\n",
|
|
|
+ name, lksb->sb_lkid, flags, mode, status);
|
|
|
+ }
|
|
|
+
|
|
|
+ return status;
|
|
|
+}
|
|
|
+
|
|
|
+
|
|
|
+static int version_lock(struct ocfs2_cluster_connection *conn, int mode,
|
|
|
+ int flags)
|
|
|
+{
|
|
|
+ struct ocfs2_live_connection *lc = conn->cc_private;
|
|
|
+ return sync_lock(conn, mode, flags,
|
|
|
+ &lc->oc_version_lksb, VERSION_LOCK);
|
|
|
+}
|
|
|
+
|
|
|
+static int version_unlock(struct ocfs2_cluster_connection *conn)
|
|
|
+{
|
|
|
+ struct ocfs2_live_connection *lc = conn->cc_private;
|
|
|
+ return sync_unlock(conn, &lc->oc_version_lksb, VERSION_LOCK);
|
|
|
+}
|
|
|
+
|
|
|
static void user_recover_prep(void *arg)
|
|
|
{
|
|
|
}
|