summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--api/src/glfs-handleops.c12
-rw-r--r--api/src/glfs-handles.h1
-rw-r--r--api/src/glfs-internal.h1
-rw-r--r--api/src/glfs.c59
-rw-r--r--libglusterfs/src/common-utils.h1
-rw-r--r--libglusterfs/src/upcall-utils.h15
-rw-r--r--xlators/features/upcall/src/upcall.c49
7 files changed, 135 insertions, 3 deletions
diff --git a/api/src/glfs-handleops.c b/api/src/glfs-handleops.c
index c010f0c9a0f..f458cb4bd58 100644
--- a/api/src/glfs-handleops.c
+++ b/api/src/glfs-handleops.c
@@ -1881,6 +1881,18 @@ pub_glfs_h_poll_upcall (struct glfs *fs, struct callback_arg *up_arg)
__GLFS_ENTRY_VALIDATE_FS (fs, err);
+ /* check if upcalls are enabled */
+ if (!fs->upcall_features) {
+ errno = ENOTSUP;
+ goto restore;
+ }
+
+ /* check if GF_UPCALL_CACHE_INVALIDATION is supported */
+ if (!(fs->upcall_features & (1 << GF_UPCALL_CACHE_INVALIDATION))) {
+ errno = ENOTSUP;
+ goto restore;
+ }
+
/* get the active volume */
subvol = glfs_active_subvol (fs);
diff --git a/api/src/glfs-handles.h b/api/src/glfs-handles.h
index 19c4e8f7a62..ddb11bf0bd5 100644
--- a/api/src/glfs-handles.h
+++ b/api/src/glfs-handles.h
@@ -293,6 +293,7 @@ glfs_h_access (struct glfs *fs, struct glfs_object *object, int mask) __THROW
0 : Success.
-1 : Error condition, mostly due to out of memory.
+ 'errno' is set to ENOTSUP if upcall feature is not enabled.
*/
diff --git a/api/src/glfs-internal.h b/api/src/glfs-internal.h
index 71c83755ec3..5eb57d4b8e4 100644
--- a/api/src/glfs-internal.h
+++ b/api/src/glfs-internal.h
@@ -199,6 +199,7 @@ struct glfs {
gf_boolean_t migration_in_progress;
+ uint32_t upcall_features; /* supported upcall events */
struct list_head upcall_list;
pthread_mutex_t upcall_list_mutex; /* mutex for upcall entry list */
diff --git a/api/src/glfs.c b/api/src/glfs.c
index fc392947e1e..7b9f1ed6d01 100644
--- a/api/src/glfs.c
+++ b/api/src/glfs.c
@@ -253,6 +253,58 @@ get_volfp (struct glfs *fs)
}
+static int
+detect_upcall_features (struct glfs *fs)
+{
+ xlator_t *subvol = NULL;
+ int ret = -1;
+ dict_t *dict = NULL;
+ uint32_t features = 0;
+
+ DECLARE_OLD_THIS;
+ __GLFS_ENTRY_VALIDATE_FS (fs, invalid_fs);
+
+ subvol = glfs_active_subvol (fs);
+ if (!subvol) {
+ ret = -1;
+ errno = EIO;
+ goto out;
+ }
+
+ ret = syncop_ipc (subvol, GF_IPC_UPCALL_FEATURES, NULL, &dict);
+ DECODE_SYNCOP_ERR (ret);
+
+ if (ret)
+ /* some real error occured */
+ goto out;
+
+ if (!dict) {
+ /* unavailable upcalls should not be an error */
+ ret = 0;
+ goto out;
+ }
+
+ ret = dict_get_uint32 (dict, GF_UPCALL_FEATURES, &features);
+ if (ret) {
+ /* unavailable upcalls should not be an error */
+ ret = 0;
+ goto out;
+ }
+
+ fs->upcall_features = features;
+
+out:
+ if (dict)
+ dict_unref (dict);
+
+ glfs_subvol_done (fs, subvol);
+ __GLFS_EXIT_FS;
+
+invalid_fs:
+ return ret;
+}
+
+
int
glfs_volumes_init (struct glfs *fs)
{
@@ -267,7 +319,7 @@ glfs_volumes_init (struct glfs *fs)
if (cmd_args->volfile_server) {
ret = glfs_mgmt_init (fs);
- goto out;
+ goto finish;
}
fp = get_volfp (fs);
@@ -284,6 +336,11 @@ glfs_volumes_init (struct glfs *fs)
if (ret)
goto out;
+finish:
+ ret = detect_upcall_features (fs);
+ if (ret)
+ goto out;
+
out:
return ret;
}
diff --git a/libglusterfs/src/common-utils.h b/libglusterfs/src/common-utils.h
index 86ea42ee849..9b07e8c7565 100644
--- a/libglusterfs/src/common-utils.h
+++ b/libglusterfs/src/common-utils.h
@@ -125,6 +125,7 @@ enum _gf_client_pid
enum _gf_xlator_ipc_targets {
GF_IPC_TARGET_CHANGELOG = 0,
+ GF_IPC_UPCALL_FEATURES = 1,
};
typedef enum _gf_boolean gf_boolean_t;
diff --git a/libglusterfs/src/upcall-utils.h b/libglusterfs/src/upcall-utils.h
index 001566fd85e..5f6970fe7e1 100644
--- a/libglusterfs/src/upcall-utils.h
+++ b/libglusterfs/src/upcall-utils.h
@@ -15,9 +15,20 @@
#include "compat-uuid.h"
#include "compat.h"
+/* Used by GF_IPC_UPCALL_FEATURES in the ipc() FOP.
+ *
+ * Each feature is a bit in the uint32_t, this likely will match all the events
+ * from the gf_upcall_event_t enum.
+ *
+ * When the bit for GF_UPCALL_EVENT_NULL is not set, upcall is loaded, but
+ * disabled.
+ */
+#define GF_UPCALL_FEATURES "gluster.upcall.features"
+
typedef enum {
- GF_UPCALL_EVENT_NULL,
- GF_UPCALL_CACHE_INVALIDATION,
+ GF_UPCALL_EVENT_NULL = 0,
+ GF_UPCALL_CACHE_INVALIDATION = 1,
+ /* add new events to the feature mask in up_ipc() */
} gf_upcall_event_t;
struct gf_upcall {
diff --git a/xlators/features/upcall/src/upcall.c b/xlators/features/upcall/src/upcall.c
index 4954d43db07..bb29866543b 100644
--- a/xlators/features/upcall/src/upcall.c
+++ b/xlators/features/upcall/src/upcall.c
@@ -1552,6 +1552,52 @@ err:
}
int32_t
+up_ipc (call_frame_t *frame, xlator_t *this, int32_t op, dict_t *xdata)
+{
+ int ret = 0;
+ uint32_t features = 0;
+
+ /* upcall only has one IPC operation */
+ if (op != GF_IPC_UPCALL_FEATURES)
+ goto wind;
+
+ if (!xdata) {
+ xdata = dict_new();
+ if (!xdata) {
+ ret = -1;
+ goto unwind;
+ }
+ } else {
+ /* take an extra reference so that we can unconditionally unref
+ * it later */
+ dict_ref (xdata);
+ }
+
+ /* build the feature bitmask */
+ if (is_upcall_enabled(this))
+ features |= (1 << GF_UPCALL_EVENT_NULL);
+
+ /* check if 'GF_UPCALL_CACHE_INVALIDATION' is available */
+ if (is_cache_invalidation_enabled(this))
+ features |= (1 << GF_UPCALL_CACHE_INVALIDATION);
+
+ ret = dict_set_uint32 (xdata, GF_UPCALL_FEATURES, features);
+
+unwind:
+ UPCALL_STACK_UNWIND (ipc, frame, ret, errno, xdata);
+
+ dict_unref (xdata);
+
+ return 0;
+
+wind:
+ STACK_WIND (frame, default_ipc_cbk, FIRST_CHILD(this),
+ FIRST_CHILD(this)->fops->ipc, op, xdata);
+
+ return 0;
+}
+
+int32_t
mem_acct_init (xlator_t *this)
{
int ret = -1;
@@ -1813,6 +1859,9 @@ struct xlator_fops fops = {
.rmdir = up_rmdir,
.rename = up_rename,
+ /* xlator internal communication */
+ .ipc = up_ipc,
+
#ifdef NOT_SUPPORTED
/* internal lk fops */
.inodelk = up_inodelk,