diff options
-rw-r--r-- | api/src/glfs-handleops.c | 12 | ||||
-rw-r--r-- | api/src/glfs-handles.h | 1 | ||||
-rw-r--r-- | api/src/glfs-internal.h | 1 | ||||
-rw-r--r-- | api/src/glfs.c | 59 | ||||
-rw-r--r-- | libglusterfs/src/common-utils.h | 1 | ||||
-rw-r--r-- | libglusterfs/src/upcall-utils.h | 15 | ||||
-rw-r--r-- | xlators/features/upcall/src/upcall.c | 49 |
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, |