Index: sanlock-3.6.0/python/sanlock.c
===================================================================
--- sanlock-3.6.0.orig/python/sanlock.c
+++ sanlock-3.6.0/python/sanlock.c
@@ -12,6 +12,10 @@
 #include <sanlock_admin.h>
 #include <sanlock_direct.h>
 
+#if PY_MAJOR_VERSION >= 3
+#define IS_PY3K
+#endif
+
 #ifndef __unused
 #define __unused __attribute__ ((unused))
 #endif
@@ -30,6 +34,17 @@
 #define __neg_sets_exception
 #endif
 
+struct module_state {
+    PyObject *error;
+};
+
+#ifdef IS_PY3K
+#define GETSTATE(m) ((struct module_state*)PyModule_GetState(m))
+#else
+#define GETSTATE(m) (&_state)
+static struct module_state _state;
+#endif
+
 /* Functions prototypes */
 static void __set_exception(int en, char *msg) __sets_exception;
 static int __parse_resource(PyObject *obj, struct sanlk_resource **res_ret) __neg_sets_exception;
@@ -102,14 +117,27 @@ __parse_resource(PyObject *obj, struct s
             path = PyTuple_GetItem(tuple, 0);
             offset = PyTuple_GetItem(tuple, 1);
 
+#ifdef IS_PY3K
+            p = PyBytes_AsString(path);
+#else
             p = PyString_AsString(path);
+#endif
 
+#ifdef IS_PY3K
+            if (!PyLong_Check(offset)) {
+#else
             if (!PyInt_Check(offset)) {
+#endif
                 __set_exception(EINVAL, "Invalid resource offset");
                 goto exit_fail;
             }
+#ifdef IS_PY3K
+        } else if (PyBytes_Check(tuple)) {
+            p = PyBytes_AsString(tuple);
+#else
         } else if (PyString_Check(tuple)) {
             p = PyString_AsString(tuple);
+#endif
         }
 
         if (p == NULL) {
@@ -122,7 +150,11 @@ __parse_resource(PyObject *obj, struct s
         if (offset == NULL) {
             res->disks[i].offset = 0;
         } else {
+#ifdef IS_PY3K
+            res->disks[i].offset = PyLong_AsLong(offset);
+#else
             res->disks[i].offset = PyInt_AsLong(offset);
+#endif
         }
     }
 
@@ -149,7 +181,11 @@ __hosts_to_list(struct sanlk_host *hss,
             goto exit_fail;
 
         /* fill the dictionary information: host_id */
+#ifdef IS_PY3K
+        if ((ls_value = PyLong_FromLong(hss[i].host_id)) == NULL)
+#else
         if ((ls_value = PyInt_FromLong(hss[i].host_id)) == NULL)
+#endif
             goto exit_fail;
         rv = PyDict_SetItemString(ls_entry, "host_id", ls_value);
         Py_DECREF(ls_value);
@@ -157,7 +193,11 @@ __hosts_to_list(struct sanlk_host *hss,
             goto exit_fail;
 
         /* fill the dictionary information: generation */
+#ifdef IS_PY3K
+        if ((ls_value = PyLong_FromLong(hss[i].generation)) == NULL)
+#else
         if ((ls_value = PyInt_FromLong(hss[i].generation)) == NULL)
+#endif
             goto exit_fail;
         rv = PyDict_SetItemString(ls_entry, "generation", ls_value);
         Py_DECREF(ls_value);
@@ -165,7 +205,11 @@ __hosts_to_list(struct sanlk_host *hss,
             goto exit_fail;
 
         /* fill the dictionary information: timestamp */
+#ifdef IS_PY3K
+        if ((ls_value = PyLong_FromLong(hss[i].timestamp)) == NULL)
+#else
         if ((ls_value = PyInt_FromLong(hss[i].timestamp)) == NULL)
+#endif
             goto exit_fail;
         rv = PyDict_SetItemString(ls_entry, "timestamp", ls_value);
         Py_DECREF(ls_value);
@@ -173,7 +217,11 @@ __hosts_to_list(struct sanlk_host *hss,
             goto exit_fail;
 
         /* fill the dictionary information: io_timeout */
+#ifdef IS_PY3K
+        if ((ls_value = PyLong_FromLong(hss[i].io_timeout)) == NULL)
+#else
         if ((ls_value = PyInt_FromLong(hss[i].io_timeout)) == NULL)
+#endif
             goto exit_fail;
         rv = PyDict_SetItemString(ls_entry, "io_timeout", ls_value);
         Py_DECREF(ls_value);
@@ -181,7 +229,11 @@ __hosts_to_list(struct sanlk_host *hss,
             goto exit_fail;
 
         /* fill the dictionary information: flags */
+#ifdef IS_PY3K
+        if ((ls_value = PyLong_FromLong(hss[i].flags)) == NULL)
+#else
         if ((ls_value = PyInt_FromLong(hss[i].flags)) == NULL)
+#endif
             goto exit_fail;
         rv = PyDict_SetItemString(ls_entry, "flags", ls_value);
         Py_DECREF(ls_value);
@@ -220,7 +272,11 @@ py_register(PyObject *self __unused, PyO
         return NULL;
     }
 
+#ifdef IS_PY3K
+    return PyLong_FromLong(sanlockfd);
+#else
     return PyInt_FromLong(sanlockfd);
+#endif
 }
 
 /* get_alignment */
@@ -253,7 +309,11 @@ py_get_alignment(PyObject *self __unused
         return NULL;
     }
 
+#ifdef IS_PY3K
+    return PyLong_FromLong(rv);
+#else
     return PyInt_FromLong(rv);
+#endif
 }
 
 /* init_lockspace */
@@ -439,7 +499,11 @@ py_read_lockspace(PyObject *self __unuse
         goto exit_fail;
 
     /* fill the dictionary information: lockspace */
+#ifdef IS_PY3K
+    if ((ls_entry = PyBytes_FromString(ls.name)) == NULL)
+#else
     if ((ls_entry = PyString_FromString(ls.name)) == NULL)
+#endif
         goto exit_fail;
     rv = PyDict_SetItemString(ls_info, "lockspace", ls_entry);
     Py_DECREF(ls_entry);
@@ -447,7 +511,11 @@ py_read_lockspace(PyObject *self __unuse
         goto exit_fail;
 
     /* fill the dictionary information: iotimeout */
+#ifdef IS_PY3K
+    if ((ls_entry = PyLong_FromLong(io_timeout)) == NULL)
+#else
     if ((ls_entry = PyInt_FromLong(io_timeout)) == NULL)
+#endif
         goto exit_fail;
     rv = PyDict_SetItemString(ls_info, "iotimeout", ls_entry);
     Py_DECREF(ls_entry);
@@ -515,7 +583,11 @@ py_read_resource(PyObject *self __unused
         goto exit_fail;
 
     /* fill the dictionary information: lockspace */
+#ifdef IS_PY3K
+    if ((rs_entry = PyBytes_FromString(rs->lockspace_name)) == NULL)
+#else
     if ((rs_entry = PyString_FromString(rs->lockspace_name)) == NULL)
+#endif
         goto exit_fail;
     rv = PyDict_SetItemString(rs_info, "lockspace", rs_entry);
     Py_DECREF(rs_entry);
@@ -523,7 +595,11 @@ py_read_resource(PyObject *self __unused
         goto exit_fail;
 
     /* fill the dictionary information: resource */
+#ifdef IS_PY3K
+    if ((rs_entry = PyBytes_FromString(rs->name)) == NULL)
+#else
     if ((rs_entry = PyString_FromString(rs->name)) == NULL)
+#endif
         goto exit_fail;
     rv = PyDict_SetItemString(rs_info, "resource", rs_entry);
     Py_DECREF(rs_entry);
@@ -804,7 +880,11 @@ py_get_lockspaces(PyObject *self __unuse
             goto exit_fail;
 
         /* fill the dictionary information: lockspace */
+#ifdef IS_PY3K
+        if ((ls_value = PyBytes_FromString(lss[i].name)) == NULL)
+#else
         if ((ls_value = PyString_FromString(lss[i].name)) == NULL)
+#endif
             goto exit_fail;
         rv = PyDict_SetItemString(ls_entry, "lockspace", ls_value);
         Py_DECREF(ls_value);
@@ -812,7 +892,11 @@ py_get_lockspaces(PyObject *self __unuse
             goto exit_fail;
 
         /* fill the dictionary information: host_id */
+#ifdef IS_PY3K
+        if ((ls_value = PyLong_FromLong(lss[i].host_id)) == NULL)
+#else
         if ((ls_value = PyInt_FromLong(lss[i].host_id)) == NULL)
+#endif
             goto exit_fail;
         rv = PyDict_SetItemString(ls_entry, "host_id", ls_value);
         Py_DECREF(ls_value);
@@ -820,7 +904,11 @@ py_get_lockspaces(PyObject *self __unuse
             goto exit_fail;
 
         /* fill the dictionary information: path */
+#ifdef IS_PY3K
+        if ((ls_value = PyBytes_FromString(lss[i].host_id_disk.path)) == NULL)
+#else
         if ((ls_value = PyString_FromString(lss[i].host_id_disk.path)) == NULL)
+#endif
             goto exit_fail;
         rv = PyDict_SetItemString(ls_entry, "path", ls_value);
         Py_DECREF(ls_value);
@@ -828,7 +916,11 @@ py_get_lockspaces(PyObject *self __unuse
             goto exit_fail;
 
         /* fill the dictionary information: offset */
+#ifdef IS_PY3K
+        if ((ls_value = PyLong_FromLong(lss[i].host_id_disk.offset)) == NULL)
+#else
         if ((ls_value = PyInt_FromLong(lss[i].host_id_disk.offset)) == NULL)
+#endif
             goto exit_fail;
         rv = PyDict_SetItemString(ls_entry, "offset", ls_value);
         Py_DECREF(ls_value);
@@ -836,7 +928,11 @@ py_get_lockspaces(PyObject *self __unuse
             goto exit_fail;
 
         /* fill the dictionary information: flags */
+#ifdef IS_PY3K
+        if ((ls_value = PyLong_FromLong(lss[i].flags)) == NULL)
+#else
         if ((ls_value = PyInt_FromLong(lss[i].flags)) == NULL)
+#endif
             goto exit_fail;
         rv = PyDict_SetItemString(ls_entry, "flags", ls_value);
         Py_DECREF(ls_value);
@@ -958,7 +1054,11 @@ py_acquire(PyObject *self __unused, PyOb
     /* prepare the resource version */
     if (version != Py_None) {
         res->flags |= SANLK_RES_LVER;
+#ifdef IS_PY3K
+        res->lver = PyLong_AsUnsignedLongMask(version);
+#else
         res->lver = PyInt_AsUnsignedLongMask(version);
+#endif
         if (res->lver == -1) {
             __set_exception(EINVAL, "Unable to convert the version value");
             goto exit_fail;
@@ -1074,7 +1174,11 @@ py_request(PyObject *self __unused, PyOb
         flags = SANLK_REQUEST_NEXT_LVER;
     } else {
         res->flags |= SANLK_RES_LVER;
+#ifdef IS_PY3K
+        res->lver = PyLong_AsUnsignedLongMask(version);
+#else
         res->lver = PyInt_AsUnsignedLongMask(version);
+#endif
         if (res->lver == -1) {
             __set_exception(EINVAL, "Unable to convert the version value");
             goto exit_fail;
@@ -1189,7 +1293,11 @@ py_killpath(PyObject *self __unused, PyO
         size_t arg_len;
 
         item = PyList_GetItem(argslist, i);
+#ifdef IS_PY3K
+        p = PyBytes_AsString(item);
+#else
         p = PyString_AsString(item);
+#endif
 
         if (p == NULL) {
             __set_exception(EINVAL, "Killpath argument not a string");
@@ -1578,32 +1686,83 @@ exit_fail:
     return excp;
 }
 
+#ifdef IS_PY3K
+static int sanlock_traverse(PyObject *m, visitproc visit, void *arg) {
+    Py_VISIT(GETSTATE(m)->error);
+    return 0;
+}
+
+static int sanlock_clear(PyObject *m) {
+    Py_CLEAR(GETSTATE(m)->error);
+    return 0;
+}
+
+static struct PyModuleDef moduledef = {
+        PyModuleDef_HEAD_INIT,
+        "sanlock",
+        pydoc_sanlock,
+        sizeof(struct module_state),
+        sanlock_methods,
+        NULL,
+        sanlock_traverse,
+        sanlock_clear,
+        NULL
+};
+
+#define INITERROR return NULL
+
+PyMODINIT_FUNC
+PyInit_sanlock(void)
+
+#else
+#define INITERROR return
+
 PyMODINIT_FUNC
 initsanlock(void)
+#endif
 {
     PyObject *py_module, *sk_constant;
+    struct module_state *st;
 
+#ifdef IS_PY3K
+    py_module = PyModule_Create(&moduledef);
+#else
     py_module = Py_InitModule4("sanlock",
                 sanlock_methods, pydoc_sanlock, NULL, PYTHON_API_VERSION);
+#endif
 
     if (py_module == NULL)
-        return;
+        INITERROR;
 
     py_exception = initexception();
 
-    if (py_exception == NULL)
-        return;
+    if (py_exception == NULL) {
+        Py_DECREF(py_module);
+        INITERROR;
+    }
+
+    st = GETSTATE(py_module);
+    st->error = py_exception;
 
     if (PyModule_AddObject(py_module, "SanlockException", py_exception) == 0) {
         Py_INCREF(py_exception);
     }
 
+#ifdef IS_PY3K
+#define PYSNLK_INIT_ADD_CONSTANT(x, y) \
+    if ((sk_constant = PyLong_FromLong(x)) != NULL) { \
+        if (PyModule_AddObject(py_module, y, sk_constant)) { \
+            Py_DECREF(sk_constant); \
+        } \
+    }
+#else
 #define PYSNLK_INIT_ADD_CONSTANT(x, y) \
     if ((sk_constant = PyInt_FromLong(x)) != NULL) { \
         if (PyModule_AddObject(py_module, y, sk_constant)) { \
             Py_DECREF(sk_constant); \
         } \
     }
+#endif
 
     /* lockspaces list flags */
     PYSNLK_INIT_ADD_CONSTANT(SANLK_LSF_ADD, "LSFLAG_ADD");
@@ -1628,4 +1787,8 @@ initsanlock(void)
     PYSNLK_INIT_ADD_CONSTANT(SANLK_SETEV_ALL_HOSTS,      "SETEV_ALL_HOSTS");
 
 #undef PYSNLK_INIT_ADD_CONSTANT
+
+#ifdef IS_PY3K
+    return py_module;
+#endif
 }
