summaryrefslogtreecommitdiffstats
path: root/xlators/cluster/dht/src
diff options
context:
space:
mode:
Diffstat (limited to 'xlators/cluster/dht/src')
-rw-r--r--xlators/cluster/dht/src/dht-common.c1338
-rw-r--r--xlators/cluster/dht/src/dht-common.h73
-rw-r--r--xlators/cluster/dht/src/dht-helper.c65
-rw-r--r--xlators/cluster/dht/src/dht-inode-write.c163
-rw-r--r--xlators/cluster/dht/src/dht-messages.h28
-rw-r--r--xlators/cluster/dht/src/dht-selfheal.c519
-rw-r--r--xlators/cluster/dht/src/dht-shared.c2
7 files changed, 2077 insertions, 111 deletions
diff --git a/xlators/cluster/dht/src/dht-common.c b/xlators/cluster/dht/src/dht-common.c
index 185eeb25f5d..1cc2f08abfb 100644
--- a/xlators/cluster/dht/src/dht-common.c
+++ b/xlators/cluster/dht/src/dht-common.c
@@ -18,7 +18,6 @@
#include "dht-lock.h"
#include "defaults.h"
#include "byte-order.h"
-#include "glusterfs-acl.h"
#include "quota-common-utils.h"
#include "upcall-utils.h"
@@ -64,6 +63,24 @@ int32_t dht_set_fixed_dir_stat (struct iatt *stat)
int
dht_rmdir_unlock (call_frame_t *frame, xlator_t *this);
+char *xattrs_to_heal[] = {
+ "user.",
+ POSIX_ACL_ACCESS_XATTR,
+ POSIX_ACL_DEFAULT_XATTR,
+ QUOTA_LIMIT_KEY,
+ QUOTA_LIMIT_OBJECTS_KEY,
+ GF_SELINUX_XATTR_KEY,
+ NULL
+};
+
+/* Return true if key exists in array
+*/
+static gf_boolean_t
+dht_match_xattr (const char *key)
+{
+ return gf_get_index_by_elem (xattrs_to_heal, (char *)key) >= 0;
+}
+
int
dht_aggregate_quota_xattr (dict_t *dst, char *key, data_t *value)
{
@@ -159,7 +176,7 @@ int add_opt(char **optsp, const char *opt)
}
/* Return Choice list from Split brain status */
-char *
+static char *
getChoices (const char *value)
{
int i = 0;
@@ -382,6 +399,74 @@ out:
return;
}
+/* Code to save hashed subvol on inode ctx as a mds subvol
+*/
+int
+dht_inode_ctx_mdsvol_set (inode_t *inode, xlator_t *this, xlator_t *mds_subvol)
+{
+ dht_inode_ctx_t *ctx = NULL;
+ int ret = -1;
+ uint64_t ctx_int = 0;
+ gf_boolean_t ctx_free = _gf_false;
+
+
+ LOCK (&inode->lock);
+ {
+ ret = __inode_ctx_get (inode, this , &ctx_int);
+ if (ctx_int) {
+ ctx = (dht_inode_ctx_t *)ctx_int;
+ ctx->mds_subvol = mds_subvol;
+ } else {
+ ctx = GF_CALLOC (1, sizeof(*ctx), gf_dht_mt_inode_ctx_t);
+ if (!ctx)
+ goto unlock;
+ ctx->mds_subvol = mds_subvol;
+ ctx_free = _gf_true;
+ ctx_int = (long) ctx;
+ ret = __inode_ctx_set (inode, this, &ctx_int);
+ }
+ }
+unlock:
+ UNLOCK (&inode->lock);
+ if (ret && ctx_free)
+ GF_FREE (ctx);
+ return ret;
+}
+
+/*Code to get mds subvol from inode ctx */
+
+int
+dht_inode_ctx_mdsvol_get (inode_t *inode, xlator_t *this, xlator_t **mdsvol)
+{
+ dht_inode_ctx_t *ctx = NULL;
+ int ret = -1;
+
+ if (!mdsvol)
+ return ret;
+
+ if (__is_root_gfid(inode->gfid)) {
+ (*mdsvol) = FIRST_CHILD (this);
+ return 0;
+ }
+
+ ret = dht_inode_ctx_get (inode, this, &ctx);
+
+ if (!ret && ctx) {
+ if (ctx->mds_subvol) {
+ *mdsvol = ctx->mds_subvol;
+ ret = 0;
+ } else {
+ ret = -1;
+ }
+ }
+
+ return ret;
+}
+
+
+
+
+
/* TODO:
- use volumename in xattr instead of "dht"
- use NS locks
@@ -397,6 +482,7 @@ dht_lookup_selfheal_cbk (call_frame_t *frame, void *cookie,
{
dht_local_t *local = NULL;
dht_layout_t *layout = NULL;
+ dht_conf_t *conf = NULL;
int ret = -1;
GF_VALIDATE_OR_GOTO ("dht", frame, out);
@@ -404,6 +490,7 @@ dht_lookup_selfheal_cbk (call_frame_t *frame, void *cookie,
GF_VALIDATE_OR_GOTO ("dht", frame->local, out);
local = frame->local;
+ conf = this->private;
ret = op_ret;
FRAME_SU_UNDO (frame, dht_local_t);
@@ -421,6 +508,8 @@ dht_lookup_selfheal_cbk (call_frame_t *frame, void *cookie,
DHT_STRIP_PHASE1_FLAGS (&local->stbuf);
dht_set_fixed_dir_stat (&local->postparent);
+ /* Delete mds xattr at the time of STACK UNWIND */
+ GF_REMOVE_INTERNAL_XATTR (conf->mds_xattr_key, local->xattr);
DHT_STACK_UNWIND (lookup, frame, ret, local->op_errno, local->inode,
&local->stbuf, local->xattr, &local->postparent);
@@ -446,10 +535,12 @@ dht_discover_complete (xlator_t *this, call_frame_t *discover_frame)
int i = 0;
loc_t loc = {0 };
int8_t is_read_only = 0, layout_anomalies = 0;
+ char gfid_local[GF_UUID_BUF_SIZE] = {0};
local = discover_frame->local;
layout = local->layout;
conf = this->private;
+ gf_uuid_unparse(local->gfid, gfid_local);
LOCK(&discover_frame->lock);
{
@@ -461,6 +552,18 @@ dht_discover_complete (xlator_t *this, call_frame_t *discover_frame)
if (!main_frame)
return 0;
+ /* Code to update all extended attributed from
+ subvol to local->xattr on that internal xattr has found
+ */
+ if (conf->subvolume_cnt == 1)
+ local->need_xattr_heal = 0;
+ if (local->need_xattr_heal && (local->mds_xattr)) {
+ dht_dir_set_heal_xattr (this, local, local->xattr,
+ local->mds_xattr, NULL, NULL);
+ dict_unref (local->mds_xattr);
+ local->mds_xattr = NULL;
+ }
+
ret = dict_get_int8 (local->xattr_req, QUOTA_READ_ONLY_KEY,
&is_read_only);
if (ret < 0)
@@ -529,6 +632,26 @@ dht_discover_complete (xlator_t *this, call_frame_t *discover_frame)
}
}
+ if (IA_ISDIR (local->stbuf.ia_type)) {
+ /* Call function to save hashed subvol on inode ctx if
+ internal mds xattr is not present and all subvols are up
+ */
+ if (!local->op_ret && !__is_root_gfid (local->stbuf.ia_gfid))
+ (void) dht_mark_mds_subvolume (discover_frame, this);
+
+ if (local->need_xattr_heal && !heal_path) {
+ local->need_xattr_heal = 0;
+ ret = dht_dir_xattr_heal (this, local);
+ if (ret)
+ gf_msg (this->name, GF_LOG_ERROR,
+ ret,
+ DHT_MSG_DIR_XATTR_HEAL_FAILED,
+ "xattr heal failed for "
+ "directory gfid is %s ",
+ gfid_local);
+ }
+ }
+
if (source && (heal_path || layout_anomalies)) {
gf_uuid_copy (loc.gfid, local->gfid);
if (gf_uuid_is_null (loc.gfid)) {
@@ -575,10 +698,14 @@ cleanup:
}
done:
dht_set_fixed_dir_stat (&local->postparent);
+ /* Delete mds xattr at the time of STACK UNWIND */
+ GF_REMOVE_INTERNAL_XATTR (conf->mds_xattr_key, local->xattr);
+
DHT_STACK_UNWIND (lookup, main_frame, local->op_ret, local->op_errno,
local->inode, &local->stbuf, local->xattr,
&local->postparent);
return 0;
+
out:
DHT_STACK_UNWIND (lookup, main_frame, -1, op_errno, NULL, NULL, NULL,
NULL);
@@ -587,6 +714,170 @@ out:
}
int
+dht_mds_internal_setxattr_cbk (call_frame_t *frame, void *cookie, xlator_t *this,
+ int op_ret, int op_errno, dict_t *xdata)
+{
+ dht_local_t *local = NULL;
+ xlator_t *hashed_subvol = NULL;
+ dht_conf_t *conf = NULL;
+ int ret = 0;
+
+ GF_VALIDATE_OR_GOTO (this->name, frame, out);
+ GF_VALIDATE_OR_GOTO (this->name, frame->local, out);
+
+ local = frame->local;
+ hashed_subvol = cookie;
+ conf = this->private;
+
+ if (op_ret) {
+ gf_msg_debug (this->name, op_ret,
+ "Failed to set %s on the MDS for path %s. ",
+ conf->mds_xattr_key, local->loc.path);
+ } else {
+ /* Save mds subvol on inode ctx */
+ ret = dht_inode_ctx_mdsvol_set (local->inode, this,
+ hashed_subvol);
+ if (ret) {
+ gf_msg (this->name, GF_LOG_ERROR, 0,
+ DHT_MSG_SET_INODE_CTX_FAILED,
+ "Failed to set mds subvol on inode ctx"
+ " %s for %s", hashed_subvol->name,
+ local->loc.path);
+ }
+ }
+out:
+ DHT_STACK_DESTROY (frame);
+ return 0;
+}
+
+
+
+/* Code to save hashed subvol on inode ctx only while no
+ mds xattr is availble and all subvols are up for fresh
+*/
+int
+dht_mark_mds_subvolume (call_frame_t *frame, xlator_t *this)
+{
+ dht_local_t *local = NULL;
+ xlator_t *hashed_subvol = NULL;
+ int i = 0;
+ gf_boolean_t vol_down = _gf_false;
+ dht_conf_t *conf = 0;
+ int ret = -1;
+ char gfid_local[GF_UUID_BUF_SIZE] = {0};
+ dict_t *xattrs = NULL;
+ dht_local_t *copy_local = NULL;
+ call_frame_t *xattr_frame = NULL;
+ int32_t zero[1] = {0};
+
+
+ GF_VALIDATE_OR_GOTO ("dht", frame, out);
+ GF_VALIDATE_OR_GOTO ("dht", this, out);
+ GF_VALIDATE_OR_GOTO (this->name, frame->local, out);
+ GF_VALIDATE_OR_GOTO (this->name, this->private, out);
+
+ local = frame->local;
+ conf = this->private;
+ gf_uuid_unparse(local->gfid, gfid_local);
+
+
+ /* Code to update hashed subvol consider as a mds subvol
+ and save on inode ctx if all subvols are up and no internal
+ xattr has been set yet
+ */
+ if (!dict_get (local->xattr, conf->mds_xattr_key)) {
+ /* It means no internal MDS xattr has been set yet
+ */
+ /* Check the status of all subvol are up
+ */
+ for (i = 0; i < conf->subvolume_cnt; i++) {
+ if (!conf->subvolume_status[i]) {
+ vol_down = _gf_true;
+ break;
+ }
+ }
+ if (vol_down) {
+ ret = 0;
+ gf_msg_debug (this->name, 0,
+ "subvol %s is down. Unable to "
+ " save mds subvol on inode for "
+ " path %s gfid is %s " ,
+ conf->subvolumes[i]->name, local->loc.path,
+ gfid_local);
+ goto out;
+ }
+ /* Calculate hashed subvol based on inode and
+ parent inode
+ */
+ hashed_subvol = dht_inode_get_hashed_subvol (local->inode,
+ this, &local->loc);
+ if (!hashed_subvol) {
+ gf_msg (this->name, GF_LOG_DEBUG, 0,
+ DHT_MSG_HASHED_SUBVOL_GET_FAILED,
+ "Failed to get hashed subvol for path %s"
+ " gfid is %s ",
+ local->loc.path, gfid_local);
+ } else {
+ xattrs = dict_new ();
+ if (!xattrs) {
+ gf_msg (this->name, GF_LOG_ERROR, ENOMEM,
+ DHT_MSG_NO_MEMORY, "dict_new failed");
+ ret = -1;
+ goto out;
+ }
+ /* Add internal MDS xattr on disk for hashed subvol
+ */
+ ret = dht_dict_set_array (xattrs, conf->mds_xattr_key, zero, 1);
+ if (ret) {
+ gf_msg (this->name, GF_LOG_WARNING, ENOMEM,
+ DHT_MSG_DICT_SET_FAILED,
+ "Failed to set dictionary"
+ " value:key = %s for "
+ "path %s", conf->mds_xattr_key,
+ local->loc.path);
+ ret = -1;
+ goto out;
+ }
+ xattr_frame = create_frame (this, this->ctx->pool);
+ if (!xattr_frame) {
+ ret = -1;
+ goto out;
+ }
+ copy_local = dht_local_init (xattr_frame, &(local->loc),
+ NULL, 0);
+ if (!copy_local) {
+ ret = -1;
+ DHT_STACK_DESTROY (xattr_frame);
+ goto out;
+ }
+ copy_local->stbuf = local->stbuf;
+ if (!copy_local->inode)
+ copy_local->inode = inode_ref (local->inode);
+ gf_uuid_copy (copy_local->loc.gfid, local->gfid);
+ STACK_WIND_COOKIE (xattr_frame, dht_mds_internal_setxattr_cbk,
+ hashed_subvol, hashed_subvol,
+ hashed_subvol->fops->setxattr,
+ &local->loc, xattrs, 0, NULL);
+ ret = 0;
+ }
+ } else {
+ ret = 0;
+ gf_msg_debug (this->name, 0,
+ "internal xattr %s is present on subvol"
+ "on path %s gfid is %s " , conf->mds_xattr_key,
+ local->loc.path, gfid_local);
+ }
+
+
+out:
+ if (xattrs)
+ dict_unref (xattrs);
+ return ret;
+}
+
+
+
+int
dht_discover_cbk (call_frame_t *frame, void *cookie, xlator_t *this,
int op_ret, int op_errno,
inode_t *inode, struct iatt *stbuf, dict_t *xattr,
@@ -598,11 +889,15 @@ dht_discover_cbk (call_frame_t *frame, void *cookie, xlator_t *this,
dht_layout_t *layout = NULL;
int ret = -1;
int is_dir = 0;
+ int32_t check_mds = 0;
int is_linkfile = 0;
int attempt_unwind = 0;
dht_conf_t *conf = 0;
- char gfid_local[GF_UUID_BUF_SIZE] = {0};
- char gfid_node[GF_UUID_BUF_SIZE] = {0};
+ char gfid_local[GF_UUID_BUF_SIZE] = {0};
+ char gfid_node[GF_UUID_BUF_SIZE] = {0};
+ int32_t mds_xattr_val[1] = {0};
+ int errst = 0;
+
GF_VALIDATE_OR_GOTO ("dht", frame, out);
GF_VALIDATE_OR_GOTO ("dht", this, out);
@@ -697,6 +992,41 @@ dht_discover_cbk (call_frame_t *frame, void *cookie, xlator_t *this,
dht_iatt_merge (this, &local->stbuf, stbuf, prev);
dht_iatt_merge (this, &local->postparent, postparent,
prev);
+ if (!dict_get (xattr, conf->mds_xattr_key)) {
+ goto unlock;
+ } else {
+ gf_msg_debug (this->name, 0,
+ "internal xattr %s is present on subvol"
+ "on path %s gfid is %s " ,
+ conf->mds_xattr_key,
+ local->loc.path, gfid_local);
+ }
+ check_mds = dht_dict_get_array (xattr, conf->mds_xattr_key,
+ mds_xattr_val, 1, &errst);
+ /* save mds subvol on inode ctx */
+ ret = dht_inode_ctx_mdsvol_set (local->inode, this,
+ prev);
+ if (ret) {
+ gf_msg (this->name, GF_LOG_ERROR, 0,
+ DHT_MSG_SET_INODE_CTX_FAILED,
+ "Failed to set hashed subvol for %s vol is %s",
+ local->loc.path, prev->name);
+ }
+
+ if ((check_mds < 0) && !errst) {
+ local->mds_xattr = dict_ref (xattr);
+ gf_msg_debug (this->name, 0,
+ "Value of %s is not zero on mds subvol"
+ "so xattr needs to be healed on non mds"
+ " path is %s and vol name is %s "
+ " gfid is %s" ,
+ conf->mds_xattr_key,
+ local->loc.path,
+ prev->name, gfid_local);
+ local->need_xattr_heal = 1;
+ local->mds_subvol = prev;
+ }
+
}
unlock:
UNLOCK (&frame->lock);
@@ -795,6 +1125,99 @@ err:
return 0;
}
+/* Get the value of key from dict in the bytewise and save in array after
+ convert from network byte order to host byte order
+*/
+int32_t
+dht_dict_get_array (dict_t *dict, char *key, int32_t value[], int32_t size, int *errst)
+{
+ void *ptr = NULL;
+ int32_t len = -1;
+ int32_t vindex = -1;
+ int32_t err = -1;
+ int ret = 0;
+
+ if (dict == NULL) {
+ (*errst) = -1;
+ return -EINVAL;
+ }
+ err = dict_get_ptr_and_len(dict, key, &ptr, &len);
+ if (err != 0) {
+ (*errst) = -1;
+ return err;
+ }
+
+ if (len != (size * sizeof (int32_t))) {
+ (*errst) = -1;
+ return -EINVAL;
+ }
+
+ memset (value, 0, size * sizeof(int32_t));
+ for (vindex = 0; vindex < size; vindex++) {
+ value[vindex] = ntoh32(*((int32_t *)ptr + vindex));
+ if (value[vindex] < 0)
+ ret = -1;
+ }
+
+ return ret;
+}
+
+
+/* Code to call syntask to heal custom xattr from hashed subvol
+ to non hashed subvol
+*/
+int
+dht_dir_xattr_heal (xlator_t *this, dht_local_t *local)
+{
+ dht_local_t *copy_local = NULL;
+ call_frame_t *copy = NULL;
+ int ret = -1;
+ char gfid_local[GF_UUID_BUF_SIZE] = {0};
+
+ if (local->gfid) {
+ gf_uuid_unparse(local->gfid, gfid_local);
+ } else {
+ gf_msg (this->name, GF_LOG_ERROR, 0,
+ DHT_MSG_DIR_XATTR_HEAL_FAILED,
+ "No gfid exists for path %s "
+ "so healing xattr is not possible",
+ local->loc.path);
+ goto out;
+ }
+
+ copy = create_frame (this, this->ctx->pool);
+ if (copy) {
+ copy_local = dht_local_init (copy, &(local->loc), NULL, 0);
+ if (!copy_local) {
+ gf_msg (this->name, GF_LOG_ERROR, ENOMEM,
+ DHT_MSG_DIR_XATTR_HEAL_FAILED,
+ "Memory allocation failed "
+ "for path %s gfid %s ",
+ local->loc.path, gfid_local);
+ DHT_STACK_DESTROY (copy);
+ } else {
+ copy_local->stbuf = local->stbuf;
+ gf_uuid_copy (copy_local->loc.gfid, local->gfid);
+ copy_local->mds_subvol = local->mds_subvol;
+ FRAME_SU_DO (copy, dht_local_t);
+ ret = synctask_new (this->ctx->env, dht_dir_heal_xattrs,
+ dht_dir_heal_xattrs_done,
+ copy, copy);
+ if (ret) {
+ gf_msg (this->name, GF_LOG_ERROR, ENOMEM,
+ DHT_MSG_DIR_XATTR_HEAL_FAILED,
+ "Synctask creation failed to heal xattr "
+ "for path %s gfid %s ",
+ local->loc.path, gfid_local);
+ DHT_STACK_DESTROY (copy);
+ }
+ }
+ }
+out:
+ return ret;
+}
+
+
int
dht_lookup_dir_cbk (call_frame_t *frame, void *cookie, xlator_t *this,
@@ -803,13 +1226,17 @@ dht_lookup_dir_cbk (call_frame_t *frame, void *cookie, xlator_t *this,
struct iatt *postparent)
{
dht_local_t *local = NULL;
+ dht_conf_t *conf = NULL;
int this_call_cnt = 0;
xlator_t *prev = NULL;
dht_layout_t *layout = NULL;
int ret = -1;
int is_dir = 0;
- char gfid_local[GF_UUID_BUF_SIZE] = {0};
- char gfid_node[GF_UUID_BUF_SIZE] = {0};
+ int32_t check_mds = 0;
+ int errst = 0;
+ char gfid_local[GF_UUID_BUF_SIZE] = {0};
+ char gfid_node[GF_UUID_BUF_SIZE] = {0};
+ int32_t mds_xattr_val[1] = {0};
GF_VALIDATE_OR_GOTO ("dht", frame, out);
GF_VALIDATE_OR_GOTO ("dht", this, out);
@@ -819,17 +1246,20 @@ dht_lookup_dir_cbk (call_frame_t *frame, void *cookie, xlator_t *this,
local = frame->local;
prev = cookie;
+ conf = this->private;
layout = local->layout;
- if (!op_ret && gf_uuid_is_null (local->gfid))
+ if (!op_ret && gf_uuid_is_null (local->gfid)) {
memcpy (local->gfid, stbuf->ia_gfid, 16);
+ }
+ if (local->gfid)
+ gf_uuid_unparse(local->gfid, gfid_local);
/* Check if the gfid is different for file from other node */
if (!op_ret && gf_uuid_compare (local->gfid, stbuf->ia_gfid)) {
gf_uuid_unparse(stbuf->ia_gfid, gfid_node);
- gf_uuid_unparse(local->gfid, gfid_local);
gf_msg (this->name, GF_LOG_WARNING, 0,
DHT_MSG_GFID_MISMATCH,
@@ -884,6 +1314,41 @@ dht_lookup_dir_cbk (call_frame_t *frame, void *cookie, xlator_t *this,
dht_iatt_merge (this, &local->stbuf, stbuf, prev);
dht_iatt_merge (this, &local->postparent, postparent, prev);
+
+ if (!dict_get (xattr, conf->mds_xattr_key)) {
+ gf_msg_debug (this->name, 0,
+ "Internal xattr %s is not present "
+ " on path %s gfid is %s " ,
+ conf->mds_xattr_key,
+ local->loc.path, gfid_local);
+ goto unlock;
+ } else {
+ /* Save mds subvol on inode ctx */
+ ret = dht_inode_ctx_mdsvol_set (local->inode, this,
+ prev);
+ if (ret) {
+ gf_msg (this->name, GF_LOG_ERROR, 0,
+ DHT_MSG_SET_INODE_CTX_FAILED,
+ "Failed to set hashed subvol for %s vol is %s",
+ local->loc.path, prev->name);
+ }
+ }
+ check_mds = dht_dict_get_array (xattr, conf->mds_xattr_key,
+ mds_xattr_val, 1, &errst);
+ if ((check_mds < 0) && !errst) {
+ local->mds_xattr = dict_ref (xattr);
+ gf_msg_debug (this->name, 0,
+ "Value of %s is not zero on hashed subvol "
+ "so xattr needs to be heal on non hashed"
+ " path is %s and vol name is %s "
+ " gfid is %s" ,
+ conf->mds_xattr_key,
+ local->loc.path,
+ prev->name, gfid_local);
+ local->need_xattr_heal = 1;
+ local->mds_subvol = prev;
+ }
+
}
unlock:
UNLOCK (&frame->lock);
@@ -892,7 +1357,20 @@ unlock:
this_call_cnt = dht_frame_return (frame);
if (is_last_call (this_call_cnt)) {
- gf_uuid_copy (local->loc.gfid, local->gfid);
+ /* No need to call xattr heal code if volume count is 1
+ */
+ if (conf->subvolume_cnt == 1)
+ local->need_xattr_heal = 0;
+
+ /* Code to update all extended attributed from hashed subvol
+ to local->xattr
+ */
+ if (local->need_xattr_heal && (local->mds_xattr)) {
+ dht_dir_set_heal_xattr (this, local, local->xattr,
+ local->mds_xattr, NULL, NULL);
+ dict_unref (local->mds_xattr);
+ local->mds_xattr = NULL;
+ }
if (local->need_selfheal) {
local->need_selfheal = 0;
@@ -911,6 +1389,9 @@ unlock:
}
dht_layout_set (this, local->inode, layout);
+ if (!dict_get (local->xattr, conf->mds_xattr_key) ||
+ local->need_xattr_heal)
+ goto selfheal;
}
if (local->inode) {
@@ -925,6 +1406,8 @@ unlock:
DHT_STRIP_PHASE1_FLAGS (&local->stbuf);
dht_set_fixed_dir_stat (&local->postparent);
+ /* Delete mds xattr at the time of STACK UNWIND */
+ GF_REMOVE_INTERNAL_XATTR (conf->mds_xattr_key, local->xattr);
DHT_STACK_UNWIND (lookup, frame, local->op_ret, local->op_errno,
local->inode, &local->stbuf, local->xattr,
&local->postparent);
@@ -981,6 +1464,9 @@ dht_revalidate_cbk (call_frame_t *frame, void *cookie, xlator_t *this,
char gfid[GF_UUID_BUF_SIZE] = {0};
uint32_t vol_commit_hash = 0;
xlator_t *subvol = NULL;
+ int32_t check_mds = 0;
+ int errst = 0;
+ int32_t mds_xattr_val[1] = {0};
GF_VALIDATE_OR_GOTO ("dht", frame, err);
GF_VALIDATE_OR_GOTO ("dht", this, err);
@@ -1005,6 +1491,9 @@ dht_revalidate_cbk (call_frame_t *frame, void *cookie, xlator_t *this,
LOCK (&frame->lock);
{
+ if (gf_uuid_is_null (local->gfid)) {
+ memcpy (local->gfid, local->loc.gfid, 16);
+ }
gf_msg_debug (this->name, op_errno,
"revalidate lookup of %s "
@@ -1090,6 +1579,7 @@ dht_revalidate_cbk (call_frame_t *frame, void *cookie, xlator_t *this,
local->prebuf.ia_prot = stbuf->ia_prot;
}
}
+
if (local->stbuf.ia_type != IA_INVAL)
{
if ((local->stbuf.ia_gid != stbuf->ia_gid) ||
@@ -1100,6 +1590,44 @@ dht_revalidate_cbk (call_frame_t *frame, void *cookie, xlator_t *this,
local->need_selfheal = 1;
}
}
+ if (!dict_get (xattr, conf->mds_xattr_key)) {
+ gf_msg_debug (this->name, 0,
+ "internal xattr %s is not present"
+ " on path %s gfid is %s " ,
+ conf->mds_xattr_key,
+ local->loc.path, gfid);
+ } else {
+ check_mds = dht_dict_get_array (xattr, conf->mds_xattr_key,
+ mds_xattr_val, 1, &errst);
+ if (local->mds_subvol == prev) {
+ local->mds_stbuf.ia_gid = stbuf->ia_gid;
+ local->mds_stbuf.ia_uid = stbuf->ia_uid;
+ local->mds_stbuf.ia_prot = stbuf->ia_prot;
+ }
+ /* save mds subvol on inode ctx */
+ ret = dht_inode_ctx_mdsvol_set (local->inode, this,
+ prev);
+ if (ret) {
+ gf_msg (this->name, GF_LOG_ERROR, 0,
+ DHT_MSG_SET_INODE_CTX_FAILED,
+ "Failed to set MDS subvol for %s vol is %s",
+ local->loc.path, prev->name);
+ }
+ if ((check_mds < 0) && !errst) {
+ local->mds_xattr = dict_ref (xattr);
+ gf_msg_debug (this->name, 0,
+ "Value of %s is not zero on "
+ "hashed subvol so xattr needs to"
+ " be healed on non hashed"
+ " path is %s and vol name is %s "
+ " gfid is %s" ,
+ conf->mds_xattr_key,
+ local->loc.path,
+ prev->name, gfid);
+ local->need_xattr_heal = 1;
+ local->mds_subvol = prev;
+ }
+ }
ret = dht_layout_dir_mismatch (this, layout,
prev, &local->loc,
xattr);
@@ -1169,13 +1697,52 @@ out:
&& (conf && conf->unhashed_sticky_bit)) {
local->stbuf.ia_prot.sticky = 1;
}
+ /* No need to call heal code if volume count is 1
+ */
+ if (conf->subvolume_cnt == 1)
+ local->need_xattr_heal = 0;
+
+ /* Code to update all extended attributed from hashed subvol
+ to local->xattr
+ */
+ if (local->need_xattr_heal && (local->mds_xattr)) {
+ dht_dir_set_heal_xattr (this, local, local->xattr,
+ local->mds_xattr, NULL, NULL);
+ dict_unref (local->mds_xattr);
+ local->mds_xattr = NULL;
+ }
+ /* Call function to save hashed subvol on inode ctx if
+ internal mds xattr is not present and all subvols are up
+ */
+ if (inode && !__is_root_gfid (inode->gfid) &&
+ (!local->op_ret) && (IA_ISDIR (local->stbuf.ia_type)))
+ (void) dht_mark_mds_subvolume (frame, this);
+
+ if (local->need_xattr_heal) {
+ local->need_xattr_heal = 0;
+ ret = dht_dir_xattr_heal (this, local);
+ if (ret)
+ gf_msg (this->name, GF_LOG_ERROR,
+ ret, DHT_MSG_DIR_XATTR_HEAL_FAILED,
+ "xattr heal failed for directory %s "
+ " gfid %s ", local->loc.path,
+ gfid);
+ }
if (local->need_selfheal) {
local->need_selfheal = 0;
- gf_uuid_copy (local->gfid, local->stbuf.ia_gfid);
- local->stbuf.ia_gid = local->prebuf.ia_gid;
- local->stbuf.ia_uid = local->prebuf.ia_uid;
- if (__is_root_gfid(local->stbuf.ia_gfid))
+ if (!__is_root_gfid (inode->gfid)) {
+ gf_uuid_copy (local->gfid, local->mds_stbuf.ia_gfid);
+ if (local->mds_stbuf.ia_gid || local->mds_stbuf.ia_uid) {
+ local->stbuf.ia_gid = local->mds_stbuf.ia_gid;
+ local->stbuf.ia_uid = local->mds_stbuf.ia_uid;
+ }
+ } else {
+ gf_uuid_copy (local->gfid, local->stbuf.ia_gfid);
+ local->stbuf.ia_gid = local->prebuf.ia_gid;
+ local->stbuf.ia_uid = local->prebuf.ia_uid;
local->stbuf.ia_prot = local->prebuf.ia_prot;
+ }
+
copy = create_frame (this, this->ctx->pool);
if (copy) {
copy_local = dht_local_init (copy, &local->loc,
@@ -1183,6 +1750,8 @@ out:
if (!copy_local)
goto cont;
copy_local->stbuf = local->stbuf;
+ copy_local->mds_stbuf = local->mds_stbuf;
+ copy_local->mds_subvol = local->mds_subvol;
copy->local = copy_local;
FRAME_SU_DO (copy, dht_local_t);
ret = synctask_new (this->ctx->env,
@@ -1237,6 +1806,8 @@ cont:
local->op_ret = -1;
local->op_errno = ESTALE;
}
+ /* Delete mds xattr at the time of STACK UNWIND */
+ GF_REMOVE_INTERNAL_XATTR (conf->mds_xattr_key, local->xattr);
DHT_STACK_UNWIND (lookup, frame, local->op_ret, local->op_errno,
local->inode, &local->stbuf, local->xattr,
@@ -2253,6 +2824,62 @@ out:
}
+/* Code to get hashed subvol based on inode and loc
+ First it check if loc->parent and loc->path exist then it get
+ hashed subvol based on loc.
+*/
+
+xlator_t *
+dht_inode_get_hashed_subvol (inode_t *inode, xlator_t *this, loc_t *loc)
+{
+ char *path = NULL;
+ loc_t populate_loc = {0, };
+ char *name = NULL;
+ xlator_t *hash_subvol = NULL;
+
+ if (!inode)
+ return hash_subvol;
+
+ if (loc && loc->parent && loc->path) {
+ if (!loc->name) {
+ name = strrchr (loc->path, '/');
+ if (name) {
+ loc->name = name + 1;
+ } else {
+ goto out;
+ }
+ }
+ hash_subvol = dht_subvol_get_hashed (this, loc);
+ goto out;
+ }
+
+ if (!gf_uuid_is_null (inode->gfid)) {
+ populate_loc.inode = inode_ref (inode);
+ populate_loc.parent = inode_parent (populate_loc.inode,
+ NULL, NULL);
+ inode_path (populate_loc.inode, NULL, &path);
+
+ if (!path)
+ goto out;
+
+ populate_loc.path = path;
+ if (!populate_loc.name && populate_loc.path) {
+ name = strrchr (populate_loc.path, '/');
+ if (name) {
+ populate_loc.name = name + 1;
+
+ } else {
+ goto out;
+ }
+ }
+ hash_subvol = dht_subvol_get_hashed (this, &populate_loc);
+ }
+out:
+ if (populate_loc.inode)
+ loc_wipe (&populate_loc);
+ return hash_subvol;
+}
+
int
dht_lookup_cbk (call_frame_t *frame, void *cookie, xlator_t *this,
@@ -2481,6 +3108,7 @@ dht_lookup (call_frame_t *frame, xlator_t *this,
{
xlator_t *subvol = NULL;
xlator_t *hashed_subvol = NULL;
+ xlator_t *mds_subvol = NULL;
dht_local_t *local = NULL;
dht_conf_t *conf = NULL;
int ret = -1;
@@ -2531,6 +3159,15 @@ dht_lookup (call_frame_t *frame, xlator_t *this,
local->xattr_req = dict_new ();
}
+ ret = dict_set_uint32 (local->xattr_req, conf->mds_xattr_key, 4);
+
+ if (ret) {
+ gf_msg (this->name, GF_LOG_WARNING, ENOMEM,
+ DHT_MSG_DICT_SET_FAILED,
+ "Failed to set dictionary value:key = %s for "
+ "path %s", conf->mds_xattr_key, loc->path);
+ }
+
if (gf_uuid_is_null (loc->pargfid) && !gf_uuid_is_null (loc->gfid) &&
!__is_root_gfid (loc->inode->gfid)) {
local->cached_subvol = NULL;
@@ -2601,6 +3238,14 @@ dht_lookup (call_frame_t *frame, xlator_t *this,
goto err;
}
if (IA_ISDIR (local->inode->ia_type)) {
+ ret = dht_inode_ctx_mdsvol_get (local->inode, this,
+ &mds_subvol);
+ if (ret || !mds_subvol) {
+ gf_msg_debug (this->name, 0,
+ "Failed to get mds subvol for path %s",
+ local->loc.path);
+ }
+ local->mds_subvol = mds_subvol;
local->call_cnt = call_cnt = conf->subvolume_cnt;
for (i = 0; i < call_cnt; i++) {
STACK_WIND_COOKIE (frame, dht_revalidate_cbk,
@@ -2804,18 +3449,17 @@ unlock:
if (!local->op_ret) {
hashed_subvol = dht_subvol_get_hashed (this, &local->loc);
- if (hashed_subvol &&
- hashed_subvol != local->cached_subvol) {
+ if (hashed_subvol && hashed_subvol != local->cached_subvol) {
/*
* If hashed and cached are different, then we need
* to unlink linkfile from hashed subvol if data
* file is deleted successfully
*/
- STACK_WIND_COOKIE (frame, dht_unlink_linkfile_cbk,
- hashed_subvol, hashed_subvol,
- hashed_subvol->fops->unlink, &local->loc,
- local->flags, xdata);
- return 0;
+ STACK_WIND_COOKIE (frame, dht_unlink_linkfile_cbk,
+ hashed_subvol, hashed_subvol,
+ hashed_subvol->fops->unlink,
+ &local->loc, local->flags, xdata);
+ return 0;
}
}
@@ -2827,6 +3471,17 @@ unlock:
return 0;
}
+static int
+dht_common_setxattr_cbk (call_frame_t *frame, void *cookie,
+ xlator_t *this, int32_t op_ret, int32_t op_errno,
+ dict_t *xdata)
+{
+ DHT_STACK_UNWIND (setxattr, frame, op_ret, op_errno, xdata);
+ return 0;
+}
+
+
+
int
dht_err_cbk (call_frame_t *frame, void *cookie, xlator_t *this,
int op_ret, int op_errno, dict_t *xdata)
@@ -2862,6 +3517,256 @@ unlock:
return 0;
}
+/* Set the value[] of key into dict after convert from
+ host byte order to network byte order
+*/
+int32_t dht_dict_set_array (dict_t *dict, char *key, int32_t value[],
+ int32_t size)
+{
+ int ret = -1;
+ int32_t *ptr = NULL;
+ int32_t vindex;
+
+ if (value == NULL) {
+ return -EINVAL;
+ }
+
+ ptr = GF_MALLOC(sizeof(int32_t) * size, gf_common_mt_char);
+ if (ptr == NULL) {
+ return -ENOMEM;
+ }
+ for (vindex = 0; vindex < size; vindex++) {
+ ptr[vindex] = hton32(value[vindex]);
+ }
+ ret = dict_set_bin(dict, key, ptr, sizeof(int32_t) * size);
+ if (ret)
+ GF_FREE (ptr);
+ return ret;
+}
+
+int
+dht_common_xattrop_cbk (call_frame_t *frame, void *cookie, xlator_t *this,
+ int32_t op_ret, int32_t op_errno, dict_t *dict, dict_t *xdata)
+{
+ dht_local_t *local = NULL;
+ call_frame_t *prev = cookie;
+
+ local = frame->local;
+
+ if (op_ret)
+ gf_msg_debug (this->name, op_errno,
+ "subvolume %s returned -1",
+ prev->this->name);
+
+ DHT_STACK_UNWIND (setxattr, frame, 0, op_errno, local->xdata);
+ return 0;
+}
+
+int
+dht_common_fxattrop_cbk (call_frame_t *frame, void *cookie, xlator_t *this,
+ int32_t op_ret, int32_t op_errno, dict_t *dict, dict_t *xdata)
+{
+ dht_local_t *local = NULL;
+ call_frame_t *prev = cookie;
+
+ local = frame->local;
+
+ if (op_ret)
+ gf_msg_debug (this->name, op_errno,
+ "subvolume %s returned -1",
+ prev->this->name);
+
+ DHT_STACK_UNWIND (fsetxattr, frame, 0, op_errno, local->xdata);
+ return 0;
+}
+
+/* Code to wind a xattrop call to add 1 on current mds internal xattr
+ value
+*/
+int
+dht_setxattr_non_mds_cbk (call_frame_t *frame, void *cookie, xlator_t *this,
+ int op_ret, int op_errno, dict_t *xdata)
+{
+ dht_local_t *local = NULL;
+ int this_call_cnt = 0;
+ int ret = 0;
+ dict_t *xattrop = NULL;
+ int32_t addone[1] = {1};
+ call_frame_t *prev = NULL;
+ dht_conf_t *conf = NULL;
+
+ local = frame->local;
+ prev = cookie;
+ conf = this->private;
+
+ LOCK (&frame->lock);
+ {
+ if (op_ret && !local->op_ret) {
+ local->op_ret = op_ret;
+ local->op_errno = op_errno;
+ gf_msg_debug (this->name, op_errno,
+ "subvolume %s returned -1",
+ prev->this->name);
+ }
+ }
+ UNLOCK (&frame->lock);
+ this_call_cnt = dht_frame_return (frame);
+
+ if (is_last_call (this_call_cnt)) {
+ if (!local->op_ret) {
+ xattrop = dict_new ();
+ if (!xattrop) {
+ gf_msg (this->name, GF_LOG_ERROR,
+ DHT_MSG_NO_MEMORY, 0,
+ "dictionary creation failed");
+ ret = -1;
+ goto out;
+ }
+ ret = dht_dict_set_array (xattrop,
+ conf->mds_xattr_key,
+ addone, 1);
+ if (ret != 0) {
+ gf_msg (this->name, GF_LOG_ERROR, 0,
+ DHT_MSG_DICT_SET_FAILED,
+ "dictionary set array failed ");
+ ret = -1;
+ goto out;
+ }
+ if (local->fop == GF_FOP_SETXATTR) {
+ STACK_WIND (frame, dht_common_xattrop_cbk,
+ local->mds_subvol,
+ local->mds_subvol->fops->xattrop,
+ &local->loc, GF_XATTROP_ADD_ARRAY,
+ xattrop, NULL);
+ } else {
+ STACK_WIND (frame, dht_common_fxattrop_cbk,
+ local->mds_subvol,
+ local->mds_subvol->fops->fxattrop,
+ local->fd, GF_XATTROP_ADD_ARRAY,
+ xattrop, NULL);
+ }
+ } else {
+ if (local->fop == GF_FOP_SETXATTR)
+ DHT_STACK_UNWIND (setxattr, frame, 0, 0, local->xdata);
+ else
+ DHT_STACK_UNWIND (fsetxattr, frame, 0, 0, local->xdata);
+ }
+ }
+out:
+ if (xattrop)
+ dict_unref (xattrop);
+ if (ret) {
+ if (local->fop == GF_FOP_SETXATTR)
+ DHT_STACK_UNWIND (setxattr, frame, 0, 0, local->xdata);
+ else
+ DHT_STACK_UNWIND (fsetxattr, frame, 0, 0, local->xdata);
+ }
+ return 0;
+}
+
+
+int
+dht_setxattr_mds_cbk (call_frame_t *frame, void *cookie, xlator_t *this,
+ int op_ret, int op_errno, dict_t *xdata)
+{
+ dht_local_t *local = NULL;
+ dht_conf_t *conf = NULL;
+ call_frame_t *prev = NULL;
+ xlator_t *mds_subvol = NULL;
+ int i = 0;
+
+ local = frame->local;
+ prev = cookie;
+ conf = this->private;
+ mds_subvol = local->mds_subvol;
+
+ if (op_ret == -1) {
+ local->op_ret = op_ret;
+ local->op_errno = op_errno;
+ gf_msg_debug (this->name, op_errno,
+ "subvolume %s returned -1",
+ prev->this->name);
+ goto out;
+ }
+
+ local->op_ret = 0;
+ local->call_cnt = conf->subvolume_cnt - 1;
+ local->xdata = dict_ref (xdata);
+
+ for (i = 0; i < conf->subvolume_cnt; i++) {
+ if (mds_subvol && (mds_subvol == conf->subvolumes[i]))
+ continue;
+ if (local->fop == GF_FOP_SETXATTR) {
+ STACK_WIND (frame, dht_setxattr_non_mds_cbk,
+ conf->subvolumes[i],
+ conf->subvolumes[i]->fops->setxattr,
+ &local->loc, local->xattr,
+ local->flags, local->xattr_req);
+ } else {
+ STACK_WIND (frame, dht_setxattr_non_mds_cbk,
+ conf->subvolumes[i],
+ conf->subvolumes[i]->fops->fsetxattr,
+ local->fd, local->xattr,
+ local->flags, local->xattr_req);
+ }
+ }
+
+ return 0;
+out:
+ if (local->fop == GF_FOP_SETXATTR) {
+ DHT_STACK_UNWIND (setxattr, frame, local->op_ret,
+ local->op_errno, xdata);
+ } else {
+ DHT_STACK_UNWIND (fsetxattr, frame, local->op_ret,
+ local->op_errno, xdata);
+ }
+
+ return 0;
+}
+
+int
+dht_xattrop_mds_cbk (call_frame_t *frame, void *cookie, xlator_t *this,
+ int op_ret, int op_errno, dict_t *dict, dict_t *xdata)
+{
+ dht_local_t *local = NULL;
+ call_frame_t *prev = NULL;
+
+ local = frame->local;
+ prev = cookie;
+
+ if (op_ret == -1) {
+ local->op_errno = op_errno;
+ local->op_ret = op_ret;
+ gf_msg_debug (this->name, op_errno,
+ "subvolume %s returned -1",
+ prev->this->name);
+ goto out;
+ }
+
+ if (local->fop == GF_FOP_SETXATTR) {
+ STACK_WIND (frame, dht_setxattr_mds_cbk,
+ local->mds_subvol,
+ local->mds_subvol->fops->setxattr,
+ &local->loc, local->xattr,
+ local->flags, local->xattr_req);
+ } else {
+ STACK_WIND (frame, dht_setxattr_mds_cbk,
+ local->mds_subvol,
+ local->mds_subvol->fops->fsetxattr,
+ local->fd, local->xattr,
+ local->flags, local->xattr_req);
+ }
+ return 0;
+out:
+ if (local->fop == GF_FOP_SETXATTR)
+ DHT_STACK_UNWIND (setxattr, frame, local->op_ret,
+ local->op_errno, xdata);
+ else
+ DHT_STACK_UNWIND (fsetxattr, frame, local->op_ret,
+ local->op_errno, xdata);
+ return 0;
+}
+
static void
fill_layout_info (dht_layout_t *layout, char *buf)
{
@@ -3303,6 +4208,41 @@ dht_linkinfo_getxattr_cbk (call_frame_t *frame, void *cookie, xlator_t *this,
return 0;
}
+
+int
+dht_mds_getxattr_cbk (call_frame_t *frame, void *cookie, xlator_t *this,
+ int op_ret, int op_errno, dict_t *xattr, dict_t *xdata)
+{
+ dht_local_t *local = NULL;
+ dht_conf_t *conf = NULL;
+
+ VALIDATE_OR_GOTO (frame, out);
+ VALIDATE_OR_GOTO (frame->local, out);
+ VALIDATE_OR_GOTO (this->private, out);
+
+ conf = this->private;
+ local = frame->local;
+
+ if (!xattr || (op_ret == -1)) {
+ local->op_ret = op_ret;
+ goto out;
+ }
+ if (dict_get (xattr, conf->xattr_name)) {
+ dict_del (xattr, conf->xattr_name);
+ }
+ local->op_ret = 0;
+
+ if (!local->xattr) {
+ local->xattr = dict_copy_with_ref (xattr, NULL);
+ }
+
+out:
+ DHT_STACK_UNWIND (getxattr, frame, local->op_ret, op_errno,
+ local->xattr, xdata);
+ return 0;
+}
+
+
int
dht_getxattr_cbk (call_frame_t *frame, void *cookie, xlator_t *this,
int op_ret, int op_errno, dict_t *xattr, dict_t *xdata)
@@ -3532,6 +4472,7 @@ dht_getxattr (call_frame_t *frame, xlator_t *this,
xlator_t *subvol = NULL;
xlator_t *hashed_subvol = NULL;
+ xlator_t *mds_subvol = NULL;
xlator_t *cached_subvol = NULL;
dht_conf_t *conf = NULL;
dht_local_t *local = NULL;
@@ -3574,6 +4515,12 @@ dht_getxattr (call_frame_t *frame, xlator_t *this,
}
if (key &&
+ (strncmp (key, conf->mds_xattr_key, strlen(key)) == 0)) {
+ op_errno = ENOTSUP;
+ goto err;
+ }
+
+ if (key &&
(strncmp (key, GF_XATTR_GET_REAL_FILENAME_KEY,
strlen (GF_XATTR_GET_REAL_FILENAME_KEY)) == 0)
&& DHT_IS_DIR(layout)) {
@@ -3703,26 +4650,53 @@ dht_getxattr (call_frame_t *frame, xlator_t *this,
return 0;
}
- if (key && (!strcmp (QUOTA_LIMIT_KEY, key) ||
- !strcmp (QUOTA_LIMIT_OBJECTS_KEY, key))) {
- /* quota hardlimit and aggregated size of a directory is stored
- * in inode contexts of each brick. Hence its good enough that
- * we send getxattr for this key to any brick.
- */
- local->call_cnt = 1;
- subvol = dht_first_up_subvol (this);
- STACK_WIND (frame, dht_getxattr_cbk, subvol,
- subvol->fops->getxattr, loc, key, xdata);
- return 0;
- }
-
if (cluster_handle_marker_getxattr (frame, loc, key, conf->vol_uuid,
dht_getxattr_unwind,
dht_marker_populate_args) == 0)
return 0;
if (DHT_IS_DIR(layout)) {
- cnt = local->call_cnt = layout->cnt;
+ local->call_cnt = conf->subvolume_cnt;
+ cnt = conf->subvolume_cnt;
+ ret = dht_inode_ctx_mdsvol_get (loc->inode, this, &mds_subvol);
+ if (!mds_subvol) {
+ gf_msg (this->name, GF_LOG_INFO, 0,
+ DHT_MSG_HASHED_SUBVOL_GET_FAILED,
+ "Cannot determine MDS, fetching xattr %s randomly"
+ " from a subvol for path %s ", key, loc->path);
+ } else {
+ /* TODO need to handle it, As of now we are
+ choosing availability instead of chossing
+ consistencty, in case of mds_subvol is
+ down winding a getxattr call on other subvol
+ and return xattr
+ */
+ local->mds_subvol = mds_subvol;
+ for (i = 0; i < cnt; i++) {
+ if (conf->subvolumes[i] == mds_subvol) {
+ if (!conf->subvolume_status[i]) {
+ gf_msg (this->name,
+ GF_LOG_INFO, 0,
+ DHT_MSG_HASHED_SUBVOL_DOWN,
+ "MDS %s is down for path"
+ " path %s so fetching xattr "
+ "%s randomly from a subvol ",
+ local->mds_subvol->name,
+ loc->path, key);
+ ret = 1;
+ }
+ }
+ }
+ }
+
+ if (!ret && key && local->mds_subvol && dht_match_xattr (key)) {
+ STACK_WIND (frame, dht_mds_getxattr_cbk,
+ local->mds_subvol,
+ local->mds_subvol->fops->getxattr,
+ loc, key, xdata);
+
+ return 0;
+ }
} else {
cnt = local->call_cnt = 1;
}
@@ -3753,6 +4727,10 @@ dht_fgetxattr (call_frame_t *frame, xlator_t *this,
int op_errno = -1;
int i = 0;
int cnt = 0;
+ xlator_t *mds_subvol = NULL;
+ int ret = -1;
+ dht_conf_t *conf = NULL;
+ char gfid[GF_UUID_BUF_SIZE] = {0};
VALIDATE_OR_GOTO (frame, err);
VALIDATE_OR_GOTO (this, err);
@@ -3760,6 +4738,8 @@ dht_fgetxattr (call_frame_t *frame, xlator_t *this,
VALIDATE_OR_GOTO (fd->inode, err);
VALIDATE_OR_GOTO (this->private, err);
+ conf = this->private;
+
local = dht_local_init (frame, NULL, fd, GF_FOP_FGETXATTR);
if (!local) {
op_errno = ENOMEM;
@@ -3784,15 +4764,63 @@ dht_fgetxattr (call_frame_t *frame, xlator_t *this,
}
}
+ if (fd->inode)
+ gf_uuid_unparse(fd->inode->gfid, gfid);
+
if ((fd->inode->ia_type == IA_IFDIR)
&& key
&& (strncmp (key, GF_XATTR_LOCKINFO_KEY,
strlen (GF_XATTR_LOCKINFO_KEY)) != 0)) {
- cnt = local->call_cnt = layout->cnt;
+ local->call_cnt = conf->subvolume_cnt;
+ cnt = conf->subvolume_cnt;
+ ret = dht_inode_ctx_mdsvol_get (fd->inode, this, &mds_subvol);
+
+ if (!mds_subvol) {
+ gf_msg (this->name, GF_LOG_ERROR, 0,
+ DHT_MSG_HASHED_SUBVOL_GET_FAILED,
+ "cannot determine MDS, fetching xattr %s "
+ " randomly from a subvol for gfid %s ",
+ key, gfid);
+ } else {
+ /* TODO need to handle it, As of now we are
+ choosing availability instead of chossing
+ consistencty, in case of hashed_subvol is
+ down winding a getxattr call on other subvol
+ and return xattr
+ */
+ local->mds_subvol = mds_subvol;
+ for (i = 0; i < cnt; i++) {
+ if (conf->subvolumes[i] == mds_subvol) {
+ if (!conf->subvolume_status[i]) {
+ gf_msg (this->name,
+ GF_LOG_WARNING, 0,
+ DHT_MSG_HASHED_SUBVOL_DOWN,
+ "MDS subvolume %s is down"
+ " for gfid %s so fetching xattr "
+ " %s randomly from a subvol ",
+ local->mds_subvol->name,
+ gfid, key);
+ ret = 1;
+ }
+ }
+ }
+ }
+
+ if (!ret && key && local->mds_subvol &&
+ dht_match_xattr (key)) {
+ STACK_WIND (frame, dht_mds_getxattr_cbk,
+ local->mds_subvol,
+ local->mds_subvol->fops->fgetxattr,
+ fd, key, NULL);
+
+ return 0;
+ }
+
} else {
cnt = local->call_cnt = 1;
}
+
for (i = 0; i < cnt; i++) {
subvol = layout->list[i].xlator;
STACK_WIND (frame, dht_getxattr_cbk,
@@ -3888,6 +4916,169 @@ out:
return 0;
}
+/* Function is call by dict_foreach_fnmatch if key is match with
+ user.* and set boolean flag to true
+*/
+static int
+dht_is_user_xattr (dict_t *this, char *key, data_t *value, void *data)
+{
+ gf_boolean_t *user_xattr_found = data;
+ *user_xattr_found = _gf_true;
+ return 0;
+}
+
+
+/* Common code to wind a (f)setxattr call to set xattr on directory
+*/
+int
+dht_dir_common_setxattr (call_frame_t *frame, xlator_t *this, loc_t *loc,
+ fd_t *fd, dict_t *xattr, int flags, dict_t *xdata,
+ int *op_errno)
+
+{
+ dict_t *xattrop = NULL;
+ int32_t subone[1] = {-1};
+ gf_boolean_t uxattr_key_found = _gf_false;
+ xlator_t *mds_subvol = NULL;
+ xlator_t *travvol = NULL;
+ dht_conf_t *conf = NULL;
+ int ret = -1;
+ int i = 0;
+ int call_cnt = 0;
+ dht_local_t *local = NULL;
+ char gfid_local[GF_UUID_BUF_SIZE] = {0};
+
+ conf = this->private;
+ local = frame->local;
+ call_cnt = conf->subvolume_cnt;
+ local->flags = flags;
+
+ if (local->gfid)
+ gf_uuid_unparse(local->gfid, gfid_local);
+
+ /* Check if any user xattr present in xattr
+ */
+ dict_foreach_fnmatch (xattr, "user*", dht_is_user_xattr,
+ &uxattr_key_found);
+
+ /* Check if any custom key xattr present in dict xattr
+ and start index from 1 because user xattr already
+ checked in previous line
+ */
+ for (i = 1; xattrs_to_heal[i]; i++)
+ if (dict_get (xattr, xattrs_to_heal[i]))
+ uxattr_key_found = _gf_true;
+
+ /* If there is no custom key xattr present or gfid is root
+ or call_cnt is 1 then wind a (f)setxattr call on all subvols
+ */
+ if (!uxattr_key_found || __is_root_gfid (local->gfid) || call_cnt == 1) {
+ for (i = 0; i < conf->subvolume_cnt; i++) {
+ travvol = conf->subvolumes[i];
+ if (fd) {
+ STACK_WIND_COOKIE (frame, dht_err_cbk,
+ travvol, travvol,
+ travvol->fops->fsetxattr,
+ fd, xattr, flags, xdata);
+ } else {
+ STACK_WIND_COOKIE (frame, dht_err_cbk,
+ travvol, travvol,
+ travvol->fops->setxattr,
+ loc, xattr, flags, xdata);
+ }
+ }
+
+ return 0;
+ }
+
+ /* Calculate hash subvol based on inode and parent inode
+ */
+ if (fd) {
+ ret = dht_inode_ctx_mdsvol_get (fd->inode, this, &mds_subvol);
+ } else {
+ ret = dht_inode_ctx_mdsvol_get (loc->inode, this, &mds_subvol);
+ }
+ if (ret || !mds_subvol) {
+ if (fd) {
+ gf_msg (this->name, GF_LOG_ERROR, 0,
+ DHT_MSG_HASHED_SUBVOL_GET_FAILED,
+ "Failed to get mds subvol for fd %p"
+ "gfid is %s ", fd, gfid_local);
+ } else {
+ gf_msg (this->name, GF_LOG_ERROR, 0,
+ DHT_MSG_HASHED_SUBVOL_GET_FAILED,
+ "Failed to get mds subvol for path %s"
+ "gfid is %s ", loc->path, gfid_local);
+ }
+ (*op_errno) = ENOENT;
+ goto err;
+ }
+
+ local->mds_subvol = mds_subvol;
+
+ for (i = 0; i < conf->subvolume_cnt; i++) {
+ if (conf->subvolumes[i] == mds_subvol) {
+ if (!conf->subvolume_status[i]) {
+ gf_msg (this->name, GF_LOG_WARNING,
+ 0, DHT_MSG_HASHED_SUBVOL_DOWN,
+ "MDS subvol is down for path "
+ " %s gfid is %s Unable to set xattr " ,
+ local->loc.path, gfid_local);
+ (*op_errno) = ENOTCONN;
+ goto err;
+ }
+ }
+ }
+
+ if (uxattr_key_found) {
+ xattrop = dict_new ();
+ if (!xattrop) {
+ gf_msg (this->name, GF_LOG_ERROR, DHT_MSG_NO_MEMORY,
+ 0, "dictionary creation failed for path %s "
+ "for gfid is %s ", local->loc.path, gfid_local);
+ (*op_errno) = ENOMEM;
+ goto err;
+ }
+ local->xattr = dict_ref (xattr);
+ /* Subtract current MDS xattr value to -1 , value of MDS
+ xattr represents no. of times xattr modification failed
+ on non MDS subvols.
+ */
+ ret = dht_dict_set_array (xattrop, conf->mds_xattr_key, subone, 1);
+ if (ret != 0) {
+ gf_msg (this->name, GF_LOG_ERROR, 0, DHT_MSG_DICT_SET_FAILED,
+ "dictionary set array failed for path %s "
+ "for gfid is %s ", local->loc.path, gfid_local);
+ if (xattrop)
+ dict_unref (xattrop);
+ (*op_errno) = ret;
+ goto err;
+ }
+ /* Wind a xattrop call to use ref counting approach
+ update mds xattr to -1 before update xattr on
+ hashed subvol and update mds xattr to +1 after update
+ xattr on all non hashed subvol
+ */
+ if (fd) {
+ STACK_WIND (frame, dht_xattrop_mds_cbk,
+ local->mds_subvol,
+ local->mds_subvol->fops->fxattrop,
+ fd, GF_XATTROP_ADD_ARRAY, xattrop, NULL);
+ } else {
+ STACK_WIND (frame, dht_xattrop_mds_cbk,
+ local->mds_subvol,
+ local->mds_subvol->fops->xattrop,
+ loc, GF_XATTROP_ADD_ARRAY,
+ xattrop, NULL);
+ }
+ if (xattrop)
+ dict_unref (xattrop);
+ }
+
+ return 0;
+err:
+ return -1;
+}
int
@@ -3901,7 +5092,6 @@ dht_fsetxattr (call_frame_t *frame, xlator_t *this,
dht_layout_t *layout = NULL;
int ret = -1;
int call_cnt = 0;
- int i = 0;
VALIDATE_OR_GOTO (frame, err);
VALIDATE_OR_GOTO (this, err);
@@ -3941,14 +5131,11 @@ dht_fsetxattr (call_frame_t *frame, xlator_t *this,
local->call_cnt = call_cnt = layout->cnt;
if (IA_ISDIR (fd->inode->ia_type)) {
- for (i = 0; i < call_cnt; i++) {
- STACK_WIND_COOKIE (frame, dht_err_cbk,
- layout->list[i].xlator,
- layout->list[i].xlator,
- layout->list[i].xlator->fops->fsetxattr,
- fd, xattr, flags, xdata);
- }
-
+ local->hashed_subvol = NULL;
+ ret = dht_dir_common_setxattr (frame, this, NULL, fd,
+ xattr, flags, xdata, &op_errno);
+ if (ret)
+ goto err;
} else {
local->call_cnt = 1;
@@ -3975,16 +5162,6 @@ err:
return 0;
}
-static int
-dht_common_setxattr_cbk (call_frame_t *frame, void *cookie,
- xlator_t *this, int32_t op_ret, int32_t op_errno,
- dict_t *xdata)
-{
- DHT_STACK_UNWIND (setxattr, frame, op_ret, op_errno, xdata);
-
- return 0;
-}
-
int
dht_checking_pathinfo_cbk (call_frame_t *frame, void *cookie, xlator_t *this,
@@ -4122,6 +5299,7 @@ dht_nuke_dir (call_frame_t *frame, xlator_t *this, loc_t *loc, data_t *tmp)
return 0;
}
+
int
dht_setxattr (call_frame_t *frame, xlator_t *this,
loc_t *loc, dict_t *xattr, int flags, dict_t *xdata)
@@ -4141,6 +5319,7 @@ dht_setxattr (call_frame_t *frame, xlator_t *this,
int call_cnt = 0;
uint32_t new_hash = 0;
+
VALIDATE_OR_GOTO (frame, err);
VALIDATE_OR_GOTO (this, err);
VALIDATE_OR_GOTO (loc, err);
@@ -4180,6 +5359,11 @@ dht_setxattr (call_frame_t *frame, xlator_t *this,
}
local->call_cnt = call_cnt = layout->cnt;
+ tmp = dict_get (xattr, conf->mds_xattr_key);
+ if (tmp) {
+ op_errno = ENOTSUP;
+ goto err;
+ }
tmp = dict_get (xattr, GF_XATTR_FILE_MIGRATE_KEY);
if (tmp) {
@@ -4355,15 +5539,11 @@ dht_setxattr (call_frame_t *frame, xlator_t *this,
local->xattr_req = xdata ? dict_ref (xdata) : dict_new ();
if (IA_ISDIR (loc->inode->ia_type)) {
-
- for (i = 0; i < call_cnt; i++) {
- STACK_WIND_COOKIE (frame, dht_err_cbk,
- layout->list[i].xlator,
- layout->list[i].xlator,
- layout->list[i].xlator->fops->setxattr,
- loc, xattr, flags, xdata);
- }
-
+ local->hashed_subvol = NULL;
+ ret = dht_dir_common_setxattr (frame, this, loc, NULL,
+ xattr, flags, xdata, &op_errno);
+ if (ret)
+ goto err;
} else {
local->rebalance.xattr = dict_ref (xattr);
@@ -4602,6 +5782,12 @@ dht_removexattr (call_frame_t *frame, xlator_t *this,
local->call_cnt = call_cnt = layout->cnt;
local->key = gf_strdup (key);
+ if (key &&
+ (strncmp (key, conf->mds_xattr_key, strlen(key)) == 0)) {
+ op_errno = ENOTSUP;
+ goto err;
+ }
+
if (IA_ISDIR (loc->inode->ia_type)) {
for (i = 0; i < call_cnt; i++) {
STACK_WIND_COOKIE (frame, dht_removexattr_cbk,
@@ -7553,6 +8739,10 @@ dht_mkdir_hashed_cbk (call_frame_t *frame, void *cookie,
dht_iatt_merge (this, &local->postparent, postparent, prev);
local->call_cnt = conf->subvolume_cnt - 1;
+ /* Delete internal mds xattr from params dict to avoid store
+ internal mds xattr on other subvols
+ */
+ dict_del (local->params, conf->mds_xattr_key);
if (gf_uuid_is_null (local->loc.gfid))
gf_uuid_copy (local->loc.gfid, stbuf->ia_gfid);
@@ -7564,6 +8754,14 @@ dht_mkdir_hashed_cbk (call_frame_t *frame, void *cookie,
&local->loc, layout);
}
+ /* Set hashed subvol as a mds subvol on inode ctx */
+ ret = dht_inode_ctx_mdsvol_set (local->inode, this, hashed_subvol);
+ if (ret) {
+ gf_msg (this->name, GF_LOG_ERROR, 0, DHT_MSG_SET_INODE_CTX_FAILED,
+ "Failed to set hashed subvol for %s on inode vol is %s",
+ local->loc.path, hashed_subvol->name);
+ }
+
for (i = 0; i < conf->subvolume_cnt; i++) {
if (conf->subvolumes[i] == hashed_subvol)
continue;
@@ -7573,6 +8771,7 @@ dht_mkdir_hashed_cbk (call_frame_t *frame, void *cookie,
&local->loc, local->mode, local->umask,
local->params);
}
+
return 0;
err:
if (local->op_ret != 0) {
@@ -7594,9 +8793,13 @@ dht_mkdir_guard_parent_layout_cbk (call_frame_t *frame, xlator_t *this,
dict_t *params)
{
dht_local_t *local = NULL;
+ dht_conf_t *conf = 0;
char pgfid[GF_UUID_BUF_SIZE] = {0};
+ int ret = -1;
+ int32_t zero[1] = {0};
local = frame->local;
+ conf = this->private;
gf_uuid_unparse (loc->parent->gfid, pgfid);
@@ -7610,6 +8813,15 @@ dht_mkdir_guard_parent_layout_cbk (call_frame_t *frame, xlator_t *this,
}
local->op_ret = -1;
+ /* Add internal MDS xattr on disk for hashed subvol
+ */
+ ret = dht_dict_set_array (params, conf->mds_xattr_key, zero, 1);
+ if (ret) {
+ gf_msg (this->name, GF_LOG_WARNING, ENOMEM,
+ DHT_MSG_DICT_SET_FAILED,
+ "Failed to set dictionary value:key = %s for "
+ "path %s", conf->mds_xattr_key, loc->path);
+ }
STACK_WIND_COOKIE (frame, dht_mkdir_hashed_cbk, local->hashed_subvol,
local->hashed_subvol,
diff --git a/xlators/cluster/dht/src/dht-common.h b/xlators/cluster/dht/src/dht-common.h
index d06b7314d8b..9b39596f872 100644
--- a/xlators/cluster/dht/src/dht-common.h
+++ b/xlators/cluster/dht/src/dht-common.h
@@ -19,6 +19,7 @@
#include "refcount.h"
#include "timer.h"
#include "protocol-common.h"
+#include "glusterfs-acl.h"
#ifndef _DHT_H
#define _DHT_H
@@ -26,6 +27,7 @@
#define GF_XATTR_FIX_LAYOUT_KEY "distribute.fix.layout"
#define GF_XATTR_TIER_LAYOUT_FIXED_KEY "trusted.tier.fix.layout.complete"
#define GF_XATTR_FILE_MIGRATE_KEY "trusted.distribute.migrate-data"
+#define DHT_MDS_STR "mds"
#define GF_DHT_LOOKUP_UNHASHED_ON 1
#define GF_DHT_LOOKUP_UNHASHED_AUTO 2
#define DHT_PATHINFO_HEADER "DISTRIBUTE:"
@@ -41,6 +43,12 @@
#define DHT_DIR_STAT_BLOCKS 8
#define DHT_DIR_STAT_SIZE 4096
+/* Array to hold custom xattr keys
+*/
+extern char *xattrs_to_heal[];
+
+
+
#include <fnmatch.h>
typedef int (*dht_selfheal_dir_cbk_t) (call_frame_t *frame, void *cookie,
@@ -107,6 +115,7 @@ struct dht_inode_ctx {
dht_layout_t *layout;
dht_stat_time_t time;
xlator_t *lock_subvol;
+ xlator_t *mds_subvol; /* This is only used for directories */
};
typedef struct dht_inode_ctx dht_inode_ctx_t;
@@ -252,6 +261,7 @@ struct dht_local {
/* Use stbuf as the postbuf, when we require both
* pre and post attrs */
struct iatt stbuf;
+ struct iatt mds_stbuf;
struct iatt prebuf;
struct iatt preoldparent;
struct iatt postoldparent;
@@ -263,6 +273,8 @@ struct dht_local {
inode_t *inode;
dict_t *params;
dict_t *xattr;
+ dict_t *mds_xattr;
+ dict_t *xdata; /* dict used to save xdata response by xattr fop */
dict_t *xattr_req;
dht_layout_t *layout;
size_t size;
@@ -271,7 +283,9 @@ struct dht_local {
xlator_t *dst_hashed, *dst_cached;
xlator_t *cached_subvol;
xlator_t *hashed_subvol;
+ xlator_t *mds_subvol; /* This is use for dir only */
char need_selfheal;
+ char need_xattr_heal;
int file_count;
int dir_count;
call_frame_t *main_frame;
@@ -355,6 +369,9 @@ struct dht_local {
/* fd open check */
gf_boolean_t fd_checked;
+ /* This is use only for directory operation */
+ int32_t valid;
+ gf_boolean_t heal_layout;
};
typedef struct dht_local dht_local_t;
@@ -629,6 +646,7 @@ struct dht_conf {
/* Support variable xattr names. */
char *xattr_name;
+ char *mds_xattr_key;
char *link_xattr_name;
char *commithash_xattr_name;
char *wild_xattr_name;
@@ -1311,9 +1329,6 @@ dht_normalize_stats (struct statvfs *buf, unsigned long bsize,
int
add_opt(char **optsp, const char *opt);
-char *
-getChoices (const char *value);
-
int
dht_aggregate_split_brain_xattr (dict_t *dst, char *key, data_t *value);
@@ -1323,18 +1338,12 @@ dht_remove_stale_linkto (void *data);
int
dht_remove_stale_linkto_cbk (int ret, call_frame_t *sync_frame, void *data);
-
int
dht_fd_ctx_set (xlator_t *this, fd_t *fd, xlator_t *subvol);
int
dht_check_and_open_fd_on_subvol (xlator_t *this, call_frame_t *frame);
-
-
-
-
-
/* FD fop callbacks */
int
@@ -1387,13 +1396,55 @@ int
dht_file_attr_cbk (call_frame_t *frame, void *cookie, xlator_t *this,
int op_ret, int op_errno, struct iatt *stbuf, dict_t *xdata);
-
int
dht_file_removexattr_cbk (call_frame_t *frame, void *cookie, xlator_t *this,
int op_ret, int op_errno, dict_t *xdata);
-
int
dht_file_setxattr_cbk (call_frame_t *frame, void *cookie, xlator_t *this,
int op_ret, int op_errno, dict_t *xdata);
+
+/* All custom xattr heal functions */
+int
+dht_dir_heal_xattrs (void *data);
+
+int
+dht_dir_heal_xattrs_done (int ret, call_frame_t *sync_frame, void *data);
+
+void
+dht_aggregate_xattr (dict_t *dst, dict_t *src);
+
+int32_t
+dht_dict_set_array(dict_t *dict, char *key, int32_t value[], int32_t size);
+
+int
+dht_set_user_xattr (dict_t *dict, char *k, data_t *v, void *data);
+
+void
+dht_dir_set_heal_xattr (xlator_t *this, dht_local_t *local, dict_t *dst,
+ dict_t *src, int *uret, int *uflag);
+
+int
+dht_dir_xattr_heal (xlator_t *this, dht_local_t *local);
+
+int32_t
+dht_dict_get_array (dict_t *dict, char *key, int32_t value[], int32_t size, int *errst);
+
+xlator_t *
+dht_inode_get_hashed_subvol (inode_t *inode, xlator_t *this, loc_t *loc);
+
+int
+dht_mark_mds_subvolume (call_frame_t *frame, xlator_t *this);
+
+int
+dht_mds_internal_setxattr_cbk (call_frame_t *frame, void *cookie,
+ xlator_t *this, int op_ret, int op_errno,
+ dict_t *xdata);
+int
+dht_inode_ctx_mdsvol_set (inode_t *inode, xlator_t *this,
+ xlator_t *mds_subvol);
+int
+dht_inode_ctx_mdsvol_get (inode_t *inode, xlator_t *this,
+ xlator_t **mdsvol);
+
#endif/* _DHT_H */
diff --git a/xlators/cluster/dht/src/dht-helper.c b/xlators/cluster/dht/src/dht-helper.c
index 86040705445..ee92a0b9c09 100644
--- a/xlators/cluster/dht/src/dht-helper.c
+++ b/xlators/cluster/dht/src/dht-helper.c
@@ -767,6 +767,10 @@ dht_local_wipe (xlator_t *this, dht_local_t *local)
if (local->xattr_req)
dict_unref (local->xattr_req);
+ if (local->mds_xattr)
+ dict_unref (local->mds_xattr);
+ if (local->xdata)
+ dict_unref (local->xdata);
if (local->selfheal.layout) {
dht_layout_unref (this, local->selfheal.layout);
@@ -2081,12 +2085,24 @@ dht_heal_full_path_done (int op_ret, call_frame_t *heal_frame, void *data)
call_frame_t *main_frame = NULL;
dht_local_t *local = NULL;
+ xlator_t *this = NULL;
+ int ret = -1;
local = heal_frame->local;
main_frame = local->main_frame;
local->main_frame = NULL;
+ this = heal_frame->this;
dht_set_fixed_dir_stat (&local->postparent);
+ if (local->need_xattr_heal) {
+ local->need_xattr_heal = 0;
+ ret = dht_dir_xattr_heal (this, local);
+ if (ret)
+ gf_msg (this->name, GF_LOG_ERROR, ret,
+ DHT_MSG_DIR_XATTR_HEAL_FAILED,
+ "xattr heal failed for directory %s ",
+ local->loc.path);
+ }
DHT_STACK_UNWIND (lookup, main_frame, 0, 0,
local->inode, &local->stbuf, local->xattr,
@@ -2250,3 +2266,52 @@ dht_lk_inode_unref (call_frame_t *frame, int32_t op_ret)
out:
return ret;
}
+
+/* Code to update custom extended attributes from src dict to dst dict
+*/
+void
+dht_dir_set_heal_xattr (xlator_t *this, dht_local_t *local, dict_t *dst,
+ dict_t *src, int *uret, int *uflag)
+{
+ int ret = -1;
+ data_t *keyval = NULL;
+ int luret = -1;
+ int luflag = -1;
+ int i = 0;
+
+ if (!src || !dst) {
+ gf_msg (this->name, GF_LOG_WARNING, EINVAL,
+ DHT_MSG_DICT_SET_FAILED,
+ "src or dst is NULL. Failed to set "
+ " dictionary value for path %s",
+ local->loc.path);
+ return;
+ }
+ /* Check if any user xattr present in src dict and set
+ it to dst dict
+ */
+ luret = dict_foreach_fnmatch (src, "user.*",
+ dht_set_user_xattr, dst);
+ /* Check if any other custom xattr present in src dict
+ and set it to dst dict, here index start from 1 because
+ user xattr already checked in previous statement
+ */
+ for (i = 1; xattrs_to_heal[i]; i++) {
+ keyval = dict_get (src, xattrs_to_heal[i]);
+ if (keyval) {
+ luflag = 1;
+ ret = dict_set (dst, xattrs_to_heal[i], keyval);
+ if (ret)
+ gf_msg (this->name, GF_LOG_WARNING, ENOMEM,
+ DHT_MSG_DICT_SET_FAILED,
+ "Failed to set dictionary value:key = %s for "
+ "path %s", xattrs_to_heal[i],
+ local->loc.path);
+ keyval = NULL;
+ }
+ }
+ if (uret)
+ (*uret) = luret;
+ if (uflag)
+ (*uflag) = luflag;
+}
diff --git a/xlators/cluster/dht/src/dht-inode-write.c b/xlators/cluster/dht/src/dht-inode-write.c
index 9709acfebb7..7c596b1c099 100644
--- a/xlators/cluster/dht/src/dht-inode-write.c
+++ b/xlators/cluster/dht/src/dht-inode-write.c
@@ -1161,6 +1161,7 @@ dht_setattr_cbk (call_frame_t *frame, void *cookie, xlator_t *this,
dht_iatt_merge (this, &local->stbuf, statpost, prev);
local->op_ret = 0;
+ local->op_errno = 0;
}
unlock:
UNLOCK (&frame->lock);
@@ -1178,16 +1179,117 @@ unlock:
}
+/* Keep the existing code same for all the cases other than regular file */
+int
+dht_non_mds_setattr_cbk (call_frame_t *frame, void *cookie, xlator_t *this,
+ int op_ret, int op_errno, struct iatt *statpre,
+ struct iatt *statpost, dict_t *xdata)
+{
+ dht_local_t *local = NULL;
+ int this_call_cnt = 0;
+ xlator_t *prev = NULL;
+
+
+ local = frame->local;
+ prev = cookie;
+
+ LOCK (&frame->lock);
+ {
+ if (op_ret == -1) {
+ gf_msg (this->name, op_errno, 0,
+ 0, "subvolume %s returned -1",
+ prev->name);
+
+ goto unlock;
+ }
+
+ dht_iatt_merge (this, &local->prebuf, statpre, prev);
+ dht_iatt_merge (this, &local->stbuf, statpost, prev);
+
+ local->op_ret = 0;
+ local->op_errno = 0;
+ }
+unlock:
+ UNLOCK (&frame->lock);
+
+ this_call_cnt = dht_frame_return (frame);
+ if (is_last_call (this_call_cnt)) {
+ dht_inode_ctx_time_set (local->loc.inode, this, &local->stbuf);
+ DHT_STACK_UNWIND (setattr, frame, 0, 0,
+ &local->prebuf, &local->stbuf, xdata);
+ }
+
+ return 0;
+}
+
+
+
+
+
+int
+dht_mds_setattr_cbk (call_frame_t *frame, void *cookie, xlator_t *this,
+ int op_ret, int op_errno, struct iatt *statpre,
+ struct iatt *statpost, dict_t *xdata)
+
+{
+ dht_local_t *local = NULL;
+ dht_conf_t *conf = NULL;
+ xlator_t *prev = NULL;
+ xlator_t *mds_subvol = NULL;
+ struct iatt loc_stbuf = {0,};
+ int i = 0;
+
+ local = frame->local;
+ prev = cookie;
+ conf = this->private;
+ mds_subvol = local->mds_subvol;
+
+ if (op_ret == -1) {
+ local->op_ret = op_ret;
+ local->op_errno = op_errno;
+ gf_msg_debug (this->name, op_errno,
+ "subvolume %s returned -1",
+ prev->name);
+ goto out;
+ }
+
+ local->op_ret = 0;
+ loc_stbuf = local->stbuf;
+ dht_iatt_merge (this, &local->prebuf, statpre, prev);
+ dht_iatt_merge (this, &local->stbuf, statpost, prev);
+
+ local->call_cnt = conf->subvolume_cnt - 1;
+ for (i = 0; i < conf->subvolume_cnt; i++) {
+ if (mds_subvol == conf->subvolumes[i])
+ continue;
+ STACK_WIND_COOKIE (frame, dht_non_mds_setattr_cbk,
+ conf->subvolumes[i], conf->subvolumes[i],
+ conf->subvolumes[i]->fops->setattr,
+ &local->loc, &loc_stbuf,
+ local->valid, local->xattr_req);
+ }
+
+ return 0;
+out:
+ DHT_STACK_UNWIND (setattr, frame, local->op_ret, local->op_errno,
+ &local->prebuf, &local->stbuf, xdata);
+
+ return 0;
+}
+
int
dht_setattr (call_frame_t *frame, xlator_t *this, loc_t *loc,
struct iatt *stbuf, int32_t valid, dict_t *xdata)
{
- xlator_t *subvol = NULL;
- dht_layout_t *layout = NULL;
- dht_local_t *local = NULL;
- int op_errno = -1;
- int i = -1;
- int call_cnt = 0;
+ xlator_t *subvol = NULL;
+ xlator_t *mds_subvol = NULL;
+ dht_layout_t *layout = NULL;
+ dht_local_t *local = NULL;
+ int op_errno = -1;
+ int i = -1;
+ int ret = -1;
+ int call_cnt = 0;
+ dht_conf_t *conf = NULL;
VALIDATE_OR_GOTO (frame, err);
VALIDATE_OR_GOTO (this, err);
@@ -1195,6 +1297,7 @@ dht_setattr (call_frame_t *frame, xlator_t *this, loc_t *loc,
VALIDATE_OR_GOTO (loc->inode, err);
VALIDATE_OR_GOTO (loc->path, err);
+ conf = this->private;
local = dht_local_init (frame, loc, NULL, GF_FOP_SETATTR);
if (!local) {
op_errno = ENOMEM;
@@ -1235,12 +1338,50 @@ dht_setattr (call_frame_t *frame, xlator_t *this, loc_t *loc,
local->call_cnt = call_cnt = layout->cnt;
- for (i = 0; i < call_cnt; i++) {
- STACK_WIND_COOKIE (frame, dht_setattr_cbk,
- layout->list[i].xlator,
- layout->list[i].xlator,
- layout->list[i].xlator->fops->setattr,
+ if (IA_ISDIR (loc->inode->ia_type) &&
+ !__is_root_gfid (loc->inode->gfid) && call_cnt != 1) {
+ ret = dht_inode_ctx_mdsvol_get (loc->inode, this, &mds_subvol);
+ if (ret || !mds_subvol) {
+ gf_msg (this->name, GF_LOG_ERROR, 0,
+ DHT_MSG_HASHED_SUBVOL_GET_FAILED,
+ "Failed to get mds subvol for path %s",
+ local->loc.path);
+ op_errno = EINVAL;
+ goto err;
+ }
+
+ local->mds_subvol = mds_subvol;
+ for (i = 0; i < conf->subvolume_cnt; i++) {
+ if (conf->subvolumes[i] == mds_subvol) {
+ if (!conf->subvolume_status[i]) {
+ gf_msg (this->name, GF_LOG_WARNING,
+ layout->list[i].err,
+ DHT_MSG_HASHED_SUBVOL_DOWN,
+ "MDS subvol is down for path "
+ " %s Unable to set attr " ,
+ local->loc.path);
+ op_errno = ENOTCONN;
+ goto err;
+ }
+ }
+ }
+ local->valid = valid;
+ local->stbuf = *stbuf;
+
+ STACK_WIND_COOKIE (frame, dht_mds_setattr_cbk,
+ local->mds_subvol,
+ local->mds_subvol,
+ local->mds_subvol->fops->setattr,
loc, stbuf, valid, xdata);
+ return 0;
+ } else {
+ for (i = 0; i < call_cnt; i++) {
+ STACK_WIND_COOKIE (frame, dht_setattr_cbk,
+ layout->list[i].xlator,
+ layout->list[i].xlator,
+ layout->list[i].xlator->fops->setattr,
+ loc, stbuf, valid, xdata);
+ }
}
return 0;
diff --git a/xlators/cluster/dht/src/dht-messages.h b/xlators/cluster/dht/src/dht-messages.h
index dcfd7478440..ade32e47f4d 100644
--- a/xlators/cluster/dht/src/dht-messages.h
+++ b/xlators/cluster/dht/src/dht-messages.h
@@ -40,7 +40,7 @@
*/
#define GLFS_DHT_BASE GLFS_MSGID_COMP_DHT
-#define GLFS_DHT_NUM_MESSAGES 126
+#define GLFS_DHT_NUM_MESSAGES 129
#define GLFS_MSGID_END (GLFS_DHT_BASE + GLFS_DHT_NUM_MESSAGES + 1)
/* Messages with message IDs */
@@ -1083,6 +1083,7 @@
* @diagnosis
* @recommendedaction None
*/
+
#define DHT_MSG_DIR_LOOKUP_FAILED (GLFS_DHT_BASE + 118)
/*
@@ -1111,6 +1112,7 @@
* @diagnosis
* @recommendedaction None
*/
+
#define DHT_MSG_ENTRYLK_ERROR (GLFS_DHT_BASE + 122)
/*
@@ -1132,7 +1134,7 @@
* @diagnosis
* @recommendedaction None
*/
-#define DHT_MSG_UNKNOWN_FOP (GLFS_DHT_BASE + 125)
+#define DHT_MSG_UNKNOWN_FOP (GLFS_DHT_BASE + 125)
/*
* @messageid 109126
@@ -1141,5 +1143,27 @@
*/
#define DHT_MSG_MIGRATE_FILE_SKIPPED (GLFS_DHT_BASE + 126)
+/*
+ * @messageid 109127
+ * @diagnosis
+ * @recommendedaction None
+ */
+#define DHT_MSG_DIR_XATTR_HEAL_FAILED (GLFS_DHT_BASE + 127)
+
+/*
+ * @messageid 109128
+ * @diagnosis
+ * @recommendedaction None
+ */
+#define DHT_MSG_HASHED_SUBVOL_DOWN (GLFS_DHT_BASE + 128)
+
+/*
+ * @messageid 109129
+ * @diagnosis
+ * @recommendedaction None
+ */
+#define DHT_MSG_NON_HASHED_SUBVOL_DOWN (GLFS_DHT_BASE + 129)
+
+
#define glfs_msg_end_x GLFS_MSGID_END, "Invalid: End of messages"
#endif /* _DHT_MESSAGES_H_ */
diff --git a/xlators/cluster/dht/src/dht-selfheal.c b/xlators/cluster/dht/src/dht-selfheal.c
index 1577d03e728..faf5ddb8aa3 100644
--- a/xlators/cluster/dht/src/dht-selfheal.c
+++ b/xlators/cluster/dht/src/dht-selfheal.c
@@ -704,6 +704,18 @@ dht_selfheal_dir_xattr_cbk (call_frame_t *frame, void *cookie, xlator_t *this,
return 0;
}
+/* Code is required to set user xattr to local->xattr
+*/
+int
+dht_set_user_xattr (dict_t *dict, char *k, data_t *v, void *data)
+{
+ dict_t *set_xattr = data;
+ int ret = -1;
+
+ ret = dict_set (set_xattr, k, v);
+ return ret;
+}
+
int
dht_selfheal_dir_xattr_persubvol (call_frame_t *frame, loc_t *loc,
@@ -831,7 +843,6 @@ dht_selfheal_dir_xattr_persubvol (call_frame_t *frame, loc_t *loc,
err:
if (xattr)
dict_unref (xattr);
-
if (xdata)
dict_unref (xdata);
@@ -1129,6 +1140,14 @@ dht_selfheal_dir_setattr_cbk (call_frame_t *frame, void *cookie, xlator_t *this,
this_call_cnt = dht_frame_return (frame);
if (is_last_call (this_call_cnt)) {
+ if (!local->heal_layout) {
+ gf_msg_trace (this->name, 0,
+ "Skip heal layout for %s gfid = %s ",
+ local->loc.path, uuid_utoa(local->gfid));
+
+ dht_selfheal_dir_finish (frame, this, 0, 1);
+ return 0;
+ }
ret = dht_selfheal_layout_lock (frame, layout, _gf_false,
dht_selfheal_dir_xattr,
dht_should_heal_layout);
@@ -1141,6 +1160,141 @@ dht_selfheal_dir_setattr_cbk (call_frame_t *frame, void *cookie, xlator_t *this,
return 0;
}
+int
+dht_selfheal_dir_check_set_mdsxattr_cbk (call_frame_t *frame, void *cookie, xlator_t *this,
+ int op_ret, int op_errno, dict_t *xdata)
+{
+ dht_local_t *local = NULL;
+ xlator_t *prev = cookie;
+ int ret = -1;
+ dht_conf_t *conf = 0;
+
+ GF_VALIDATE_OR_GOTO (this->name, frame, out);
+ GF_VALIDATE_OR_GOTO (this->name, frame->local, out);
+
+ local = frame->local;
+ conf = this->private;
+
+ if (op_ret) {
+ gf_msg_debug (this->name, op_ret,
+ "internal mds setxattr %s is failed on mds subvol "
+ "at the time of heal on path %s " ,
+ conf->mds_xattr_key, local->loc.path);
+ } else {
+ /* Save mds subvol on inode ctx */
+ ret = dht_inode_ctx_mdsvol_set (local->inode, this, prev);
+ if (ret) {
+ gf_msg (this->name, GF_LOG_ERROR, 0,
+ DHT_MSG_SET_INODE_CTX_FAILED,
+ "Failed to set hashed subvol "
+ " %s for %s ", prev->name,
+ local->loc.path);
+ }
+ }
+
+out:
+ DHT_STACK_DESTROY (frame);
+ return 0;
+}
+
+/* Code to set internal mds xattr if it is not present
+*/
+int
+dht_selfheal_dir_check_set_mdsxattr (call_frame_t *frame, loc_t *loc)
+{
+ dht_local_t *local = NULL;
+ xlator_t *this = NULL;
+ xlator_t *hashed_subvol = NULL;
+ int ret = -1;
+ dict_t *xattrs = NULL;
+ char gfid_local[GF_UUID_BUF_SIZE] = {0,};
+ int32_t zero[1] = {0};
+ call_frame_t *xattr_frame = NULL;
+ dht_local_t *copy_local = NULL;
+ dht_conf_t *conf = 0;
+
+ local = frame->local;
+ this = frame->this;
+ conf = this->private;
+ gf_uuid_unparse(local->gfid, gfid_local);
+
+ if (!dict_get (local->xattr, conf->mds_xattr_key)) {
+ /* It means no internal MDS xattr has been set yet
+ */
+ /* Calculate hashed subvol based on inode and
+ parent inode
+ */
+ hashed_subvol = dht_inode_get_hashed_subvol (local->inode, this,
+ loc);
+ if (!hashed_subvol) {
+ gf_msg (this->name, GF_LOG_DEBUG, 0,
+ DHT_MSG_HASHED_SUBVOL_GET_FAILED,
+ "Failed to get hashed subvol for path %s"
+ "gfid is %s ",
+ local->loc.path, gfid_local);
+ ret = -1;
+ goto out;
+ } else {
+ /* Set internal mds xattr on disk */
+ xattrs = dict_new ();
+ if (!xattrs) {
+ gf_msg (this->name, GF_LOG_ERROR, ENOMEM,
+ DHT_MSG_NO_MEMORY, "dict_new failed");
+ ret = -1;
+ goto out;
+ }
+ /* Add internal MDS xattr on disk for hashed subvol
+ */
+ ret = dht_dict_set_array (xattrs, conf->mds_xattr_key, zero, 1);
+ if (ret) {
+ gf_msg (this->name, GF_LOG_WARNING, ENOMEM,
+ DHT_MSG_DICT_SET_FAILED,
+ "Failed to set dictionary"
+ " value:key = %s for "
+ "path %s", conf->mds_xattr_key,
+ local->loc.path);
+ ret = -1;
+ goto out;
+ }
+
+ xattr_frame = create_frame (this, this->ctx->pool);
+ if (!xattr_frame) {
+ ret = -1;
+ goto out;
+ }
+ copy_local = dht_local_init (xattr_frame, &(local->loc),
+ NULL, 0);
+ if (!copy_local) {
+ ret = -1;
+ DHT_STACK_DESTROY (xattr_frame);
+ goto out;
+ }
+
+ copy_local->stbuf = local->stbuf;
+ copy_local->inode = inode_ref (local->inode);
+ gf_uuid_copy (copy_local->loc.gfid, local->gfid);
+
+ STACK_WIND_COOKIE (xattr_frame,
+ dht_selfheal_dir_check_set_mdsxattr_cbk,
+ (void *)hashed_subvol, hashed_subvol,
+ hashed_subvol->fops->setxattr,
+ loc, xattrs, 0, NULL);
+ ret = 0;
+ }
+ } else {
+ ret = 0;
+ gf_msg_debug (this->name, 0,
+ "internal xattr %s is present on subvol"
+ "on path %s gfid is %s " , conf->mds_xattr_key,
+ local->loc.path, gfid_local);
+ }
+
+out:
+ if (xattrs)
+ dict_unref (xattrs);
+ return ret;
+}
+
int
dht_selfheal_dir_setattr (call_frame_t *frame, loc_t *loc, struct iatt *stbuf,
@@ -1160,7 +1314,40 @@ dht_selfheal_dir_setattr (call_frame_t *frame, loc_t *loc, struct iatt *stbuf,
missing_attr++;
}
+ if (!__is_root_gfid (local->stbuf.ia_gfid)) {
+ if (local->need_xattr_heal) {
+ local->need_xattr_heal = 0;
+ ret = dht_dir_xattr_heal (this, local);
+ if (ret)
+ gf_msg (this->name, GF_LOG_ERROR,
+ ret,
+ DHT_MSG_DIR_XATTR_HEAL_FAILED,
+ "xattr heal failed for "
+ "directory %s gfid %s ",
+ local->loc.path,
+ local->gfid);
+ } else {
+ ret = dht_selfheal_dir_check_set_mdsxattr (frame, loc);
+ if (ret)
+ gf_msg (this->name, GF_LOG_INFO, ret,
+ DHT_MSG_DIR_XATTR_HEAL_FAILED,
+ "set mds internal xattr failed for "
+ "directory %s gfid %s ", local->loc.path,
+ local->gfid);
+ }
+ }
+
+ if (!gf_uuid_is_null (local->gfid))
+ gf_uuid_copy (loc->gfid, local->gfid);
+
if (missing_attr == 0) {
+ if (!local->heal_layout) {
+ gf_msg_trace (this->name, 0,
+ "Skip heal layout for %s gfid = %s ",
+ loc->path, uuid_utoa(loc->gfid));
+ dht_selfheal_dir_finish (frame, this, 0, 1);
+ return 0;
+ }
ret = dht_selfheal_layout_lock (frame, layout, _gf_false,
dht_selfheal_dir_xattr,
dht_should_heal_layout);
@@ -1172,11 +1359,9 @@ dht_selfheal_dir_setattr (call_frame_t *frame, loc_t *loc, struct iatt *stbuf,
return 0;
}
- if (!gf_uuid_is_null (local->gfid))
- gf_uuid_copy (loc->gfid, local->gfid);
-
local->call_cnt = missing_attr;
cnt = layout->cnt;
+
for (i = 0; i < cnt; i++) {
if (layout->list[i].err == -1) {
gf_msg_trace (this->name, 0,
@@ -1292,16 +1477,66 @@ out:
return;
}
+
+void
+dht_selfheal_dir_mkdir_setquota (dict_t *src, dict_t *dst)
+{
+ data_t *quota_limit_key = NULL;
+ data_t *quota_limit_obj_key = NULL;
+ xlator_t *this = NULL;
+ int ret = -1;
+
+ GF_ASSERT (src);
+ GF_ASSERT (dst);
+
+ this = THIS;
+ GF_ASSERT (this);
+
+ quota_limit_key = dict_get (src, QUOTA_LIMIT_KEY);
+ if (!quota_limit_key) {
+ gf_msg_debug (this->name, 0,
+ "QUOTA_LIMIT_KEY xattr not present");
+ goto cont;
+ }
+ ret = dict_set(dst, QUOTA_LIMIT_KEY, quota_limit_key);
+ if (ret)
+ gf_msg (this->name, GF_LOG_WARNING, 0,
+ DHT_MSG_DICT_SET_FAILED,
+ "Failed to set dictionary value.key = %s",
+ QUOTA_LIMIT_KEY);
+
+cont:
+ quota_limit_obj_key = dict_get (src, QUOTA_LIMIT_OBJECTS_KEY);
+ if (!quota_limit_obj_key) {
+ gf_msg_debug (this->name, 0,
+ "QUOTA_LIMIT_OBJECTS_KEY xattr not present");
+ goto out;
+ }
+ ret = dict_set (dst, QUOTA_LIMIT_OBJECTS_KEY, quota_limit_obj_key);
+ if (ret)
+ gf_msg (this->name, GF_LOG_WARNING, 0,
+ DHT_MSG_DICT_SET_FAILED,
+ "Failed to set dictionary value.key = %s",
+ QUOTA_LIMIT_OBJECTS_KEY);
+
+out:
+ return;
+}
+
+
+
+
+
int
dht_selfheal_dir_mkdir_lookup_done (call_frame_t *frame, xlator_t *this)
{
dht_local_t *local = NULL;
int i = 0;
- int ret = -1;
dict_t *dict = NULL;
dht_layout_t *layout = NULL;
loc_t *loc = NULL;
int cnt = 0;
+ int ret = -1;
VALIDATE_OR_GOTO (this->private, err);
@@ -1325,9 +1560,11 @@ dht_selfheal_dir_mkdir_lookup_done (call_frame_t *frame, xlator_t *this)
dict = dict_ref (local->params);
}
- /* Set acls */
- if (local->xattr && dict)
- dht_selfheal_dir_mkdir_setacl (local->xattr, dict);
+ /* Code to update all extended attributed from local->xattr
+ to dict
+ */
+ dht_dir_set_heal_xattr (this, local, dict, local->xattr, NULL,
+ NULL);
if (!dict)
gf_msg (this->name, GF_LOG_WARNING, 0,
@@ -1375,8 +1612,13 @@ dht_selfheal_dir_mkdir_lookup_cbk (call_frame_t *frame, void *cookie,
int this_call_cnt = 0;
int missing_dirs = 0;
dht_layout_t *layout = NULL;
+ dht_conf_t *conf = 0;
loc_t *loc = NULL;
xlator_t *prev = NULL;
+ int check_mds = 0;
+ int errst = 0;
+ int32_t mds_xattr_val[1] = {0};
+ char gfid_local[GF_UUID_BUF_SIZE] = {0};
VALIDATE_OR_GOTO (this->private, err);
@@ -1384,6 +1626,10 @@ dht_selfheal_dir_mkdir_lookup_cbk (call_frame_t *frame, void *cookie,
layout = local->layout;
loc = &local->loc;
prev = cookie;
+ conf = this->private;
+
+ if (local->gfid)
+ gf_uuid_unparse(local->gfid, gfid_local);
this_call_cnt = dht_frame_return (frame);
@@ -1398,6 +1644,12 @@ dht_selfheal_dir_mkdir_lookup_cbk (call_frame_t *frame, void *cookie,
if (!op_ret) {
dht_iatt_merge (this, &local->stbuf, stbuf, prev);
}
+ check_mds = dht_dict_get_array (xattr, conf->mds_xattr_key,
+ mds_xattr_val, 1, &errst);
+ if (dict_get (xattr, conf->mds_xattr_key) && check_mds && !errst) {
+ dict_unref (local->xattr);
+ local->xattr = dict_ref (xattr);
+ }
}
UNLOCK (&frame->lock);
@@ -1446,13 +1698,16 @@ dht_selfheal_dir_mkdir_lock_cbk (call_frame_t *frame, void *cookie,
dht_local_t *local = NULL;
dht_conf_t *conf = NULL;
int i = 0;
+ int ret = -1;
+ xlator_t *mds_subvol = NULL;
VALIDATE_OR_GOTO (this->private, err);
conf = this->private;
local = frame->local;
+ mds_subvol = local->mds_subvol;
- local->call_cnt = conf->subvolume_cnt;
+ local->call_cnt = conf->subvolume_cnt;
if (op_ret < 0) {
@@ -1478,12 +1733,32 @@ dht_selfheal_dir_mkdir_lock_cbk (call_frame_t *frame, void *cookie,
/* After getting locks, perform lookup again to ensure that the
directory was not deleted by a racing rmdir
*/
+ if (!local->xattr_req)
+ local->xattr_req = dict_new ();
+
+ ret = dict_set_int32 (local->xattr_req, "list-xattr", 1);
+ if (ret)
+ gf_msg (this->name, GF_LOG_ERROR, 0,
+ DHT_MSG_DICT_SET_FAILED,
+ "Failed to set dictionary key list-xattr value "
+ " for path %s ", local->loc.path);
for (i = 0; i < conf->subvolume_cnt; i++) {
- STACK_WIND_COOKIE (frame, dht_selfheal_dir_mkdir_lookup_cbk,
- conf->subvolumes[i], conf->subvolumes[i],
- conf->subvolumes[i]->fops->lookup,
- &local->loc, NULL);
+ if (mds_subvol && conf->subvolumes[i] == mds_subvol) {
+ STACK_WIND_COOKIE (frame,
+ dht_selfheal_dir_mkdir_lookup_cbk,
+ conf->subvolumes[i],
+ conf->subvolumes[i],
+ conf->subvolumes[i]->fops->lookup,
+ &local->loc, local->xattr_req);
+ } else {
+ STACK_WIND_COOKIE (frame,
+ dht_selfheal_dir_mkdir_lookup_cbk,
+ conf->subvolumes[i],
+ conf->subvolumes[i],
+ conf->subvolumes[i]->fops->lookup,
+ &local->loc, NULL);
+ }
}
return 0;
@@ -2172,15 +2447,16 @@ dht_selfheal_directory (call_frame_t *frame, dht_selfheal_dir_cbk_t dir_cbk,
}
dht_layout_sort_volname (layout);
+ local->heal_layout = _gf_true;
ret = dht_selfheal_dir_getafix (frame, loc, layout);
if (ret == -1) {
- gf_msg (this->name, GF_LOG_WARNING, 0,
+ gf_msg (this->name, GF_LOG_INFO, 0,
DHT_MSG_DIR_SELFHEAL_FAILED,
"Directory selfheal failed: "
"Unable to form layout for directory %s",
loc->path);
- goto sorry_no_fix;
+ local->heal_layout = _gf_false;
}
dht_selfheal_dir_mkdir (frame, loc, layout, 0);
@@ -2282,23 +2558,196 @@ dht_selfheal_restore (call_frame_t *frame, dht_selfheal_dir_cbk_t dir_cbk,
}
int
+dht_dir_heal_xattrs (void *data)
+{
+ call_frame_t *frame = NULL;
+ dht_local_t *local = NULL;
+ xlator_t *subvol = NULL;
+ xlator_t *mds_subvol = NULL;
+ xlator_t *this = NULL;
+ dht_conf_t *conf = NULL;
+ dict_t *user_xattr = NULL;
+ dict_t *internal_xattr = NULL;
+ dict_t *mds_xattr = NULL;
+ dict_t *xdata = NULL;
+ int call_cnt = 0;
+ int ret = -1;
+ int uret = 0;
+ int uflag = 0;
+ int i = 0;
+ int xattr_hashed = 0;
+ char gfid[GF_UUID_BUF_SIZE] = {0};
+ int32_t allzero[1] = {0};
+
+ GF_VALIDATE_OR_GOTO ("dht", data, out);
+
+ frame = data;
+ local = frame->local;
+ this = frame->this;
+ GF_VALIDATE_OR_GOTO ("dht", this, out);
+ GF_VALIDATE_OR_GOTO (this->name, local, out);
+ mds_subvol = local->mds_subvol;
+ conf = this->private;
+ GF_VALIDATE_OR_GOTO (this->name, conf, out);
+ gf_uuid_unparse(local->loc.gfid, gfid);
+
+ if (!mds_subvol) {
+ gf_msg (this->name, GF_LOG_WARNING, 0,
+ DHT_MSG_DIR_XATTR_HEAL_FAILED,
+ "No mds subvol for %s gfid = %s",
+ local->loc.path, gfid);
+ goto out;
+ }
+
+ if ((local->loc.inode && gf_uuid_is_null (local->loc.inode->gfid)) ||
+ gf_uuid_is_null (local->loc.gfid)) {
+ gf_msg (this->name, GF_LOG_WARNING, 0,
+ DHT_MSG_DIR_XATTR_HEAL_FAILED,
+ "No gfid present so skip heal for path %s gfid = %s",
+ local->loc.path, gfid);
+ goto out;
+ }
+
+ internal_xattr = dict_new ();
+ if (!internal_xattr) {
+ gf_msg (this->name, GF_LOG_ERROR, DHT_MSG_NO_MEMORY, 0,
+ "dictionary creation failed");
+ goto out;
+ }
+ xdata = dict_new ();
+ if (!xdata) {
+ gf_msg (this->name, GF_LOG_ERROR, DHT_MSG_NO_MEMORY, 0,
+ "dictionary creation failed");
+ goto out;
+ }
+
+ call_cnt = conf->subvolume_cnt;
+
+ user_xattr = dict_new ();
+ if (!user_xattr) {
+ gf_msg (this->name, GF_LOG_ERROR, DHT_MSG_NO_MEMORY, 0,
+ "dictionary creation failed");
+ goto out;
+ }
+
+ ret = syncop_listxattr (local->mds_subvol, &local->loc,
+ &mds_xattr, NULL, NULL);
+ if (ret < 0) {
+ gf_msg (this->name, GF_LOG_ERROR, -ret,
+ DHT_MSG_DIR_XATTR_HEAL_FAILED,
+ "failed to list xattrs for "
+ "%s: on %s ",
+ local->loc.path, local->mds_subvol->name);
+ }
+
+ if (!mds_xattr)
+ goto out;
+
+ dht_dir_set_heal_xattr (this, local, user_xattr, mds_xattr,
+ &uret, &uflag);
+
+ /* To set quota related xattr need to set GLUSTERFS_INTERNAL_FOP_KEY
+ * key value to 1
+ */
+ if (dict_get (user_xattr, QUOTA_LIMIT_KEY) ||
+ dict_get (user_xattr, QUOTA_LIMIT_OBJECTS_KEY)) {
+ ret = dict_set_int32 (xdata, GLUSTERFS_INTERNAL_FOP_KEY, 1);
+ if (ret) {
+ gf_msg (this->name, GF_LOG_ERROR, 0,
+ DHT_MSG_DICT_SET_FAILED,
+ "Failed to set dictionary value: key = %s,"
+ " path = %s", GLUSTERFS_INTERNAL_FOP_KEY,
+ local->loc.path);
+ goto out;
+ }
+ }
+ if (uret <= 0 && !uflag)
+ goto out;
+
+ for (i = 0; i < call_cnt; i++) {
+ subvol = conf->subvolumes[i];
+ if (subvol == mds_subvol)
+ continue;
+ if (uret || uflag) {
+ ret = syncop_setxattr (subvol, &local->loc, user_xattr,
+ 0, xdata, NULL);
+ if (ret) {
+ xattr_hashed = 1;
+ gf_msg (this->name, GF_LOG_ERROR, -ret,
+ DHT_MSG_DIR_XATTR_HEAL_FAILED,
+ "Directory xattr heal failed. Failed to set"
+ "user xattr on path %s on "
+ "subvol %s, gfid = %s ",
+ local->loc.path, subvol->name, gfid);
+ }
+ }
+ }
+ /* After heal all custom xattr reset internal MDS xattr to 0 */
+ if (!xattr_hashed) {
+ ret = dht_dict_set_array (internal_xattr,
+ conf->mds_xattr_key,
+ allzero, 1);
+ if (ret) {
+ gf_msg (this->name, GF_LOG_WARNING, ENOMEM,
+ DHT_MSG_DICT_SET_FAILED,
+ "Failed to set dictionary value:key = %s for "
+ "path %s", conf->mds_xattr_key,
+ local->loc.path);
+ goto out;
+ }
+ ret = syncop_setxattr (mds_subvol, &local->loc, internal_xattr,
+ 0, NULL, NULL);
+ if (ret) {
+ gf_msg (this->name, GF_LOG_ERROR, -ret,
+ DHT_MSG_DIR_XATTR_HEAL_FAILED,
+ "Failed to reset internal xattr "
+ "on path %s on subvol %s"
+ "gfid = %s ", local->loc.path,
+ mds_subvol->name, gfid);
+ }
+ }
+
+out:
+ if (user_xattr)
+ dict_unref (user_xattr);
+ if (mds_xattr)
+ dict_unref (mds_xattr);
+ if (internal_xattr)
+ dict_unref (internal_xattr);
+ if (xdata)
+ dict_unref (xdata);
+ return 0;
+}
+
+
+int
+dht_dir_heal_xattrs_done (int ret, call_frame_t *sync_frame, void *data)
+{
+ DHT_STACK_DESTROY (sync_frame);
+ return 0;
+}
+
+
+int
dht_dir_attr_heal (void *data)
{
- call_frame_t *frame = NULL;
- dht_local_t *local = NULL;
- xlator_t *subvol = NULL;
- xlator_t *this = NULL;
+ call_frame_t *frame = NULL;
+ dht_local_t *local = NULL;
+ xlator_t *subvol = NULL;
+ xlator_t *mds_subvol = NULL;
+ xlator_t *this = NULL;
dht_conf_t *conf = NULL;
int call_cnt = 0;
int ret = -1;
int i = 0;
- char gfid[GF_UUID_BUF_SIZE] = {0};
+ char gfid[GF_UUID_BUF_SIZE] = {0};
GF_VALIDATE_OR_GOTO ("dht", data, out);
frame = data;
local = frame->local;
+ mds_subvol = local->mds_subvol;
this = frame->this;
GF_VALIDATE_OR_GOTO ("dht", this, out);
GF_VALIDATE_OR_GOTO ("dht", local, out);
@@ -2307,17 +2756,39 @@ dht_dir_attr_heal (void *data)
call_cnt = conf->subvolume_cnt;
+ if (!__is_root_gfid (local->stbuf.ia_gfid) && (!mds_subvol)) {
+ gf_msg (this->name, GF_LOG_WARNING, 0,
+ DHT_MSG_DIR_ATTR_HEAL_FAILED,
+ "No mds subvol for %s gfid = %s",
+ local->loc.path, gfid);
+ goto out;
+ }
+
+ if (!__is_root_gfid (local->stbuf.ia_gfid)) {
+ for (i = 0; i < conf->subvolume_cnt; i++) {
+ if (conf->subvolumes[i] == mds_subvol) {
+ if (!conf->subvolume_status[i]) {
+ gf_msg (this->name, GF_LOG_ERROR,
+ 0, DHT_MSG_HASHED_SUBVOL_DOWN,
+ "mds subvol is down for path "
+ " %s gfid is %s Unable to set xattr " ,
+ local->loc.path, gfid);
+ goto out;
+ }
+ }
+ }
+ }
+
for (i = 0; i < call_cnt; i++) {
subvol = conf->subvolumes[i];
- if (!subvol)
+ if (!subvol || subvol == mds_subvol)
continue;
-
if (__is_root_gfid (local->stbuf.ia_gfid)) {
ret = syncop_setattr (subvol, &local->loc, &local->stbuf,
(GF_SET_ATTR_UID | GF_SET_ATTR_GID | GF_SET_ATTR_MODE),
NULL, NULL, NULL, NULL);
} else {
- ret = syncop_setattr (subvol, &local->loc, &local->stbuf,
+ ret = syncop_setattr (subvol, &local->loc, &local->mds_stbuf,
(GF_SET_ATTR_UID | GF_SET_ATTR_GID),
NULL, NULL, NULL, NULL);
}
@@ -2325,7 +2796,7 @@ dht_dir_attr_heal (void *data)
if (ret) {
gf_uuid_unparse(local->loc.gfid, gfid);
- gf_msg ("dht", GF_LOG_ERROR, -ret,
+ gf_msg (this->name, GF_LOG_ERROR, -ret,
DHT_MSG_DIR_ATTR_HEAL_FAILED,
"Directory attr heal failed. Failed to set"
" uid/gid on path %s on subvol %s, gfid = %s ",
diff --git a/xlators/cluster/dht/src/dht-shared.c b/xlators/cluster/dht/src/dht-shared.c
index 0373ebffe5a..42daff01489 100644
--- a/xlators/cluster/dht/src/dht-shared.c
+++ b/xlators/cluster/dht/src/dht-shared.c
@@ -868,6 +868,7 @@ dht_init (xlator_t *this)
}
GF_OPTION_INIT ("xattr-name", conf->xattr_name, str, err);
+ gf_asprintf (&conf->mds_xattr_key, "%s."DHT_MDS_STR, conf->xattr_name);
gf_asprintf (&conf->link_xattr_name, "%s."DHT_LINKFILE_STR,
conf->xattr_name);
gf_asprintf (&conf->commithash_xattr_name, "%s."DHT_COMMITHASH_STR,
@@ -917,6 +918,7 @@ err:
GF_FREE (conf->xattr_name);
GF_FREE (conf->link_xattr_name);
GF_FREE (conf->wild_xattr_name);
+ GF_FREE (conf->mds_xattr_key);
if (conf->lock_pool)
mem_pool_destroy (conf->lock_pool);