summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--xlators/cluster/dht/src/dht-rename.c201
1 files changed, 158 insertions, 43 deletions
diff --git a/xlators/cluster/dht/src/dht-rename.c b/xlators/cluster/dht/src/dht-rename.c
index ed07be73ea7..0f90f433180 100644
--- a/xlators/cluster/dht/src/dht-rename.c
+++ b/xlators/cluster/dht/src/dht-rename.c
@@ -16,6 +16,7 @@
#include "dht-common.h"
#include "defaults.h"
+int dht_rename_unlock (call_frame_t *frame, xlator_t *this);
int
dht_rename_dir_cbk (call_frame_t *frame, void *cookie, xlator_t *this,
@@ -71,11 +72,7 @@ unwind:
WIPE (&local->preparent);
WIPE (&local->postparent);
- DHT_STRIP_PHASE1_FLAGS (&local->stbuf);
- DHT_STACK_UNWIND (rename, frame, local->op_ret, local->op_errno,
- &local->stbuf, &local->preoldparent,
- &local->postoldparent,
- &local->preparent, &local->postparent, xdata);
+ dht_rename_unlock (frame, this);
}
return 0;
@@ -156,13 +153,7 @@ unwind:
WIPE (&local->preparent);
WIPE (&local->postparent);
- DHT_STRIP_PHASE1_FLAGS (&local->stbuf);
-
- DHT_STACK_UNWIND (rename, frame, local->op_ret, local->op_errno,
- &local->stbuf, &local->preoldparent,
- &local->postoldparent,
- &local->preparent, &local->postparent, NULL);
-
+ dht_rename_unlock (frame, this);
return 0;
}
@@ -186,8 +177,7 @@ dht_rename_dir_do (call_frame_t *frame, xlator_t *this)
return 0;
err:
- DHT_STACK_UNWIND (rename, frame, local->op_ret, local->op_errno, NULL, NULL,
- NULL, NULL, NULL, NULL);
+ dht_rename_unlock (frame, this);
return 0;
}
@@ -264,28 +254,35 @@ err:
int
-dht_rename_dir (call_frame_t *frame, xlator_t *this)
+dht_rename_dir_lock_cbk (call_frame_t *frame, void *cookie, xlator_t *this,
+ int32_t op_ret, int32_t op_errno, dict_t *xdata)
{
- dht_conf_t *conf = NULL;
- dht_local_t *local = NULL;
- int i = 0;
- int op_errno = -1;
-
+ dht_local_t *local = NULL;
+ char src_gfid[GF_UUID_BUF_SIZE] = {0};
+ char dst_gfid[GF_UUID_BUF_SIZE] = {0};
+ dht_conf_t *conf = NULL;
+ int i = 0;
- conf = frame->this->private;
local = frame->local;
+ conf = this->private;
- local->call_cnt = conf->subvolume_cnt;
+ if (op_ret < 0) {
+ uuid_utoa_r (local->loc.inode->gfid, src_gfid);
- for (i = 0; i < conf->subvolume_cnt; i++) {
- if (!conf->subvolume_status[i]) {
- gf_msg (this->name, GF_LOG_INFO, 0,
- DHT_MSG_RENAME_FAILED,
- "Rename dir failed: subvolume down (%s)",
- conf->subvolumes[i]->name);
- op_errno = ENOTCONN;
- goto err;
- }
+ if (local->loc2.inode)
+ uuid_utoa_r (local->loc2.inode->gfid, dst_gfid);
+
+ gf_msg (this->name, GF_LOG_WARNING, op_errno,
+ DHT_MSG_INODE_LK_ERROR,
+ "acquiring inodelk failed "
+ "rename (%s:%s:%s %s:%s:%s)",
+ local->loc.path, src_gfid, local->src_cached->name,
+ local->loc2.path, dst_gfid,
+ local->dst_cached ? local->dst_cached->name : NULL);
+
+ local->op_ret = -1;
+ local->op_errno = op_errno;
+ goto err;
}
local->fd = fd_create (local->loc.inode, frame->root->pid);
@@ -311,14 +308,120 @@ dht_rename_dir (call_frame_t *frame, xlator_t *this)
return 0;
err:
+ /* No harm in calling an extra unlock */
+ dht_rename_unlock (frame, this);
+ return 0;
+}
+
+int
+dht_rename_dir (call_frame_t *frame, xlator_t *this)
+{
+ dht_conf_t *conf = NULL;
+ dht_local_t *local = NULL;
+ dht_lock_t **lk_array = NULL;
+ dht_layout_t *dst_layout = NULL;
+ xlator_t *first_subvol = NULL;
+ int count = 1;
+ int i = 0;
+ int j = 0;
+ int ret = 0;
+ int op_errno = -1;
+
+ conf = frame->this->private;
+ local = frame->local;
+
+ /* We must take a lock on all the subvols with src gfid.
+ * Along with this if dst exists we must take lock on
+ * any one subvol with dst gfid.
+ */
+ count = local->call_cnt = conf->subvolume_cnt;
+ if (local->loc2.inode) {
+ dst_layout = dht_layout_get (this, local->loc2.inode);
+ if (dst_layout)
+ ++count;
+ }
+
+ for (i = 0; i < conf->subvolume_cnt; i++) {
+ if (!conf->subvolume_status[i]) {
+ gf_msg (this->name, GF_LOG_INFO, 0,
+ DHT_MSG_RENAME_FAILED,
+ "Rename dir failed: subvolume down (%s)",
+ conf->subvolumes[i]->name);
+ op_errno = ENOTCONN;
+ goto err;
+ }
+ }
+
+ lk_array = GF_CALLOC (count, sizeof (*lk_array), gf_common_mt_char);
+ if (lk_array == NULL) {
+ op_errno = ENOMEM;
+ goto err;
+ }
+
+ /* Rename must take locks on src to avoid lookup selfheal from
+ * recreating src on those subvols where the rename was successful.
+ * Rename must take locks on all subvols with src because selfheal
+ * in entry creation phase may not have acquired lock on all subvols.
+ */
+ for (i = 0; i < local->call_cnt; i++) {
+ lk_array[i] = dht_lock_new (frame->this,
+ conf->subvolumes[i],
+ &local->loc, F_WRLCK,
+ DHT_LAYOUT_HEAL_DOMAIN);
+ if (lk_array[i] == NULL) {
+ op_errno = ENOMEM;
+ goto err;
+ }
+ }
+
+ /* If the dst exists, we are going to replace dst layout range with
+ * that of src. This will lead to anomalies in dst layout until the
+ * rename completes. To avoid a lookup selfheal to change dst layout
+ * during this interval we take a lock on one subvol of dst.
+ */
+ if (dst_layout) {
+ for (j = 0; (j < dst_layout->cnt) &&
+ (dst_layout->list[j].err == 0); j++) {
+
+ first_subvol = dst_layout->list[j].xlator;
+ lk_array[i] = dht_lock_new (frame->this, first_subvol,
+ &local->loc2, F_WRLCK,
+ DHT_LAYOUT_HEAL_DOMAIN);
+ if (lk_array[i] == NULL) {
+ op_errno = ENOMEM;
+ goto err;
+ }
+ break;
+ }
+ }
+
+ local->lock.locks = lk_array;
+ local->lock.lk_count = count;
+
+ ret = dht_blocking_inodelk (frame, lk_array, count,
+ IGNORE_ENOENT_ESTALE,
+ dht_rename_dir_lock_cbk);
+ if (ret < 0) {
+ local->lock.locks = NULL;
+ local->lock.lk_count = 0;
+ op_errno = EINVAL;
+ goto err;
+ }
+
+ return 0;
+
+err:
+ if (lk_array != NULL) {
+ dht_lock_array_free (lk_array, count);
+ GF_FREE (lk_array);
+ }
+
op_errno = (op_errno == -1) ? errno : op_errno;
DHT_STACK_UNWIND (rename, frame, -1, op_errno, NULL, NULL, NULL, NULL,
NULL, NULL);
return 0;
}
-
-
static int
dht_rename_track_for_changelog (xlator_t *this, dict_t *xattr,
loc_t *oldloc, loc_t *newloc)
@@ -422,12 +525,14 @@ dht_rename_unlock_cbk (call_frame_t *frame, void *cookie,
local = frame->local;
- DHT_STRIP_PHASE1_FLAGS (&local->stbuf);
dht_set_fixed_dir_stat (&local->preoldparent);
dht_set_fixed_dir_stat (&local->postoldparent);
dht_set_fixed_dir_stat (&local->preparent);
dht_set_fixed_dir_stat (&local->postparent);
+ if (IA_ISREG (local->stbuf.ia_type))
+ DHT_STRIP_PHASE1_FLAGS (&local->stbuf);
+
DHT_STACK_UNWIND (rename, frame, local->op_ret, local->op_errno,
&local->stbuf, &local->preoldparent,
&local->postoldparent, &local->preparent,
@@ -444,7 +549,6 @@ dht_rename_unlock (call_frame_t *frame, xlator_t *this)
char dst_gfid[GF_UUID_BUF_SIZE] = {0};
local = frame->local;
-
op_ret = dht_unlock_inodelk (frame, local->lock.locks,
local->lock.lk_count,
dht_rename_unlock_cbk);
@@ -454,14 +558,25 @@ dht_rename_unlock (call_frame_t *frame, xlator_t *this)
if (local->loc2.inode)
uuid_utoa_r (local->loc2.inode->gfid, dst_gfid);
- gf_msg (this->name, GF_LOG_WARNING, 0,
- DHT_MSG_UNLOCKING_FAILED,
- "winding unlock inodelk failed "
- "rename (%s:%s:%s %s:%s:%s), "
- "stale locks left on bricks",
- local->loc.path, src_gfid, local->src_cached->name,
- local->loc2.path, dst_gfid,
- local->dst_cached ? local->dst_cached->name : NULL);
+ if (IA_ISREG (local->stbuf.ia_type))
+ gf_msg (this->name, GF_LOG_WARNING, 0,
+ DHT_MSG_UNLOCKING_FAILED,
+ "winding unlock inodelk failed "
+ "rename (%s:%s:%s %s:%s:%s), "
+ "stale locks left on bricks",
+ local->loc.path, src_gfid,
+ local->src_cached->name,
+ local->loc2.path, dst_gfid,
+ local->dst_cached ?
+ local->dst_cached->name : NULL);
+ else
+ gf_msg (this->name, GF_LOG_WARNING, 0,
+ DHT_MSG_UNLOCKING_FAILED,
+ "winding unlock inodelk failed "
+ "rename (%s:%s %s:%s), "
+ "stale locks left on bricks",
+ local->loc.path, src_gfid,
+ local->loc2.path, dst_gfid);
dht_rename_unlock_cbk (frame, NULL, this, 0, 0, NULL);
}