summaryrefslogtreecommitdiffstats
path: root/xlators
diff options
context:
space:
mode:
Diffstat (limited to 'xlators')
-rw-r--r--xlators/cluster/dht/src/dht-common.c143
1 files changed, 124 insertions, 19 deletions
diff --git a/xlators/cluster/dht/src/dht-common.c b/xlators/cluster/dht/src/dht-common.c
index d396c2ee4ab..bc9d04d36f8 100644
--- a/xlators/cluster/dht/src/dht-common.c
+++ b/xlators/cluster/dht/src/dht-common.c
@@ -28,6 +28,8 @@
#include <libgen.h>
#include <signal.h>
+int dht_link2 (xlator_t *this, call_frame_t *frame, int op_ret);
+
int
dht_aggregate (dict_t *this, char *key, data_t *value, void *data)
{
@@ -4490,54 +4492,156 @@ err:
return 0;
}
-
int
dht_link_cbk (call_frame_t *frame, void *cookie, xlator_t *this,
int op_ret, int op_errno,
inode_t *inode, struct iatt *stbuf, struct iatt *preparent,
struct iatt *postparent, dict_t *xdata)
{
- call_frame_t *prev = NULL;
- dht_layout_t *layout = NULL;
dht_local_t *local = NULL;
-
- prev = cookie;
+ int ret = -1;
+ gf_boolean_t stbuf_merged = _gf_false;
+ xlator_t *subvol = NULL;
local = frame->local;
- if (op_ret == -1)
- goto out;
-
- layout = dht_layout_for_subvol (this, prev->this);
- if (!layout) {
- gf_msg_debug (this->name, 0,
- "no pre-set layout for subvolume %s",
- prev->this->name);
- op_ret = -1;
- op_errno = EINVAL;
+ if (op_ret == -1) {
+ /* No continuation on DHT inode missing errors, as we should
+ * then have a good stbuf that states P2 happened. We would
+ * get inode missing if, the file completed migrated between
+ * the lookup and the link call */
goto out;
}
+ /* Update parent on success, even if P1/2 checks are positve.
+ * The second call on success will further update the parent */
if (local->loc.parent) {
dht_inode_ctx_time_update (local->loc.parent, this,
preparent, 0);
dht_inode_ctx_time_update (local->loc.parent, this,
postparent, 1);
}
- if (local->linked == _gf_true) {
- local->stbuf = *stbuf;
+
+ /* Update linkto attrs, if this is the first call and non-P2,
+ * if we detect P2 then we need to trust the attrs from the
+ * second call, not the first */
+ if (local->linked == _gf_true &&
+ ((local->call_cnt == 1 && !IS_DHT_MIGRATION_PHASE2 (stbuf))
+ || (local->call_cnt != 1 &&
+ IS_DHT_MIGRATION_PHASE2 (&local->stbuf)))) {
+ dht_iatt_merge (this, &local->stbuf, stbuf, NULL);
+ stbuf_merged = _gf_true;
dht_linkfile_attr_heal (frame, this);
}
+
+ /* No further P1/2 checks if we are in the second iteration of
+ * the call */
+ if (local->call_cnt != 1) {
+ goto out;
+ } else {
+ /* Preserve the return values, in case the migration decides
+ * to recreate the link on the same subvol that the current
+ * hased for the link was created on. */
+ dht_iatt_merge (this, &local->preparent,
+ preparent, NULL);
+ dht_iatt_merge (this, &local->postparent,
+ postparent, NULL);
+ if (!stbuf_merged) {
+ dht_iatt_merge (this, &local->stbuf,
+ stbuf, NULL);
+ stbuf_merged = _gf_true;
+ }
+
+ local->inode = inode_ref (inode);
+ }
+
+ local->op_errno = op_errno;
+ local->rebalance.target_op_fn = dht_link2;
+ /* Check if the rebalance phase2 is true */
+ if (IS_DHT_MIGRATION_PHASE2 (stbuf)) {
+ ret = dht_inode_ctx_get1 (this, local->loc.inode, &subvol);
+ if (!subvol) {
+ /* Phase 2 of migration */
+ ret = dht_rebalance_complete_check (this, frame);
+ if (!ret)
+ return 0;
+ } else {
+ dht_link2 (this, frame, 0);
+ return 0;
+ }
+ }
+
+ /* Check if the rebalance phase1 is true */
+ if (IS_DHT_MIGRATION_PHASE1 (stbuf)) {
+ ret = dht_inode_ctx_get1 (this, local->loc.inode, &subvol);
+ if (subvol) {
+ dht_link2 (this, frame, 0);
+ return 0;
+ }
+ ret = dht_rebalance_in_progress_check (this, frame);
+ if (!ret)
+ return 0;
+ }
out:
DHT_STRIP_PHASE1_FLAGS (stbuf);
- DHT_STACK_UNWIND (link, frame, op_ret, op_errno, inode, stbuf, preparent,
- postparent, NULL);
+
+ DHT_STACK_UNWIND (link, frame, op_ret, op_errno, inode, stbuf,
+ preparent, postparent, NULL);
return 0;
}
int
+dht_link2 (xlator_t *this, call_frame_t *frame, int op_ret)
+{
+ dht_local_t *local = NULL;
+ xlator_t *subvol = NULL;
+ int op_errno = EINVAL;
+
+ local = frame->local;
+ if (!local)
+ goto err;
+
+ op_errno = local->op_errno;
+ if (op_ret == -1)
+ goto err;
+
+ dht_inode_ctx_get1 (this, local->loc.inode, &subvol);
+ if (!subvol) {
+ subvol = local->cached_subvol;
+ if (!subvol) {
+ op_errno = EINVAL;
+ goto err;
+ }
+ }
+
+ /* Second call to create link file could result in EEXIST as the
+ * first call created the linkto in the currently
+ * migrating subvol, which could be the new hashed subvol */
+ if (local->link_subvol == subvol) {
+ DHT_STRIP_PHASE1_FLAGS (&local->stbuf);
+ DHT_STACK_UNWIND (link, frame, 0, 0, local->inode,
+ &local->stbuf, &local->preparent,
+ &local->postparent, NULL);
+
+ return 0;
+ }
+
+ local->call_cnt = 2;
+
+ STACK_WIND (frame, dht_link_cbk, subvol, subvol->fops->link,
+ &local->loc, &local->loc2, NULL);
+
+ return 0;
+err:
+ DHT_STACK_UNWIND (link, frame, -1, op_errno, NULL, NULL, NULL,
+ NULL, NULL);
+
+ return 0;
+}
+
+int
dht_link_linkfile_cbk (call_frame_t *frame, void *cookie, xlator_t *this,
int op_ret, int op_errno,
inode_t *inode, struct iatt *stbuf,
@@ -4588,6 +4692,7 @@ dht_link (call_frame_t *frame, xlator_t *this,
goto err;
}
+ local->call_cnt = 1;
cached_subvol = local->cached_subvol;
if (!cached_subvol) {