summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--libglusterfs/src/xlator.c6
-rw-r--r--xlators/cluster/dht/src/dht-rename.c67
2 files changed, 63 insertions, 10 deletions
diff --git a/libglusterfs/src/xlator.c b/libglusterfs/src/xlator.c
index b1ed094e0ae..ec7cbe08ad3 100644
--- a/libglusterfs/src/xlator.c
+++ b/libglusterfs/src/xlator.c
@@ -939,7 +939,11 @@ loc_copy (loc_t *dst, loc_t *src)
GF_VALIDATE_OR_GOTO ("xlator", dst, err);
GF_VALIDATE_OR_GOTO ("xlator", src, err);
- gf_uuid_copy (dst->gfid, src->gfid);
+ if (!gf_uuid_is_null (src->gfid))
+ gf_uuid_copy (dst->gfid, src->gfid);
+ else if (src->inode && !gf_uuid_is_null (src->inode->gfid))
+ gf_uuid_copy (dst->gfid, src->inode->gfid);
+
gf_uuid_copy (dst->pargfid, src->pargfid);
if (src->inode)
diff --git a/xlators/cluster/dht/src/dht-rename.c b/xlators/cluster/dht/src/dht-rename.c
index c24e6ea7aca..32806e911bb 100644
--- a/xlators/cluster/dht/src/dht-rename.c
+++ b/xlators/cluster/dht/src/dht-rename.c
@@ -1435,9 +1435,15 @@ dht_rename_lookup_cbk (call_frame_t *frame, void *cookie, xlator_t *this,
inode_t *inode, struct iatt *stbuf, dict_t *xattr,
struct iatt *postparent)
{
- dht_local_t *local = NULL;
- int call_cnt = 0;
- dht_conf_t *conf = NULL;
+ dht_local_t *local = NULL;
+ int call_cnt = 0;
+ dht_conf_t *conf = NULL;
+ char gfid_local[GF_UUID_BUF_SIZE] = {0};
+ char gfid_server[GF_UUID_BUF_SIZE] = {0};
+ int child_index = -1;
+
+
+ child_index = (long)cookie;
local = frame->local;
conf = this->private;
@@ -1456,16 +1462,40 @@ dht_rename_lookup_cbk (call_frame_t *frame, void *cookie, xlator_t *this,
* that this is a linkfile and fail the rename operation.
*/
local->is_linkfile = _gf_true;
+ local->op_errno = op_errno;
} else if (xattr && check_is_linkfile (inode, stbuf, xattr,
conf->link_xattr_name)) {
local->is_linkfile = _gf_true;
+ /* Found linkto file instead of data file, passdown ENOENT
+ * based on the above comment */
+ local->op_errno = ENOENT;
+ }
+
+ if (!local->is_linkfile &&
+ gf_uuid_compare (local->lock[0].layout.parent_layout.locks[child_index]->loc.gfid,
+ stbuf->ia_gfid)) {
+ gf_uuid_unparse (local->lock[0].layout.parent_layout.locks[child_index]->loc.gfid,
+ gfid_local);
+ gf_uuid_unparse (stbuf->ia_gfid, gfid_server);
+
+ gf_msg (this->name, GF_LOG_WARNING, 0,
+ DHT_MSG_GFID_MISMATCH,
+ "path:%s, received a different gfid, local_gfid= %s"
+ " server_gfid: %s",
+ local->loc.path, gfid_local, gfid_server);
+
+ /* Will passdown ENOENT anyway since the file we sent on
+ * rename is replaced with a different file */
+ local->op_errno = ENOENT;
+ /* Since local->is_linkfile is used here to detect failure,
+ * marking this to true */
+ local->is_linkfile = _gf_true;
}
call_cnt = dht_frame_return (frame);
if (is_last_call (call_cnt)) {
if (local->is_linkfile) {
local->op_ret = -1;
- local->op_errno = op_errno;
goto fail;
}
@@ -1529,12 +1559,31 @@ dht_rename_lock_cbk (call_frame_t *frame, void *cookie, xlator_t *this,
local->call_cnt = local->lock[0].layout.parent_layout.lk_count;
+ /* Why not use local->lock.locks[?].loc for lookup post lock phase
+ * ---------------------------------------------------------------
+ * "layout.parent_layout.locks[?].loc" does not have the name and pargfid
+ * populated.
+ * Reason: If we had populated the name and pargfid, server might
+ * resolve to a successful lookup even if there is a file with same name
+ * with a different gfid(unlink & create) as server does name based
+ * resolution on first priority. And this can result in operating on a
+ * different inode entirely.
+ *
+ * Now consider a scenario where source file was renamed by some other
+ * client to a new name just before this lock was granted. So if a
+ * lookup would be done on local->lock[0].layout.parent_layout.locks[?].loc,
+ * server will send success even if the entry was renamed (since server will
+ * do a gfid based resolution). So once a lock is granted, make sure the file
+ * exists with the name that the client requested with.
+ * */
+
for (i = 0; i < local->lock[0].layout.parent_layout.lk_count; i++) {
- STACK_WIND (frame, dht_rename_lookup_cbk,
- local->lock[0].layout.parent_layout.locks[i]->xl,
- local->lock[0].layout.parent_layout.locks[i]->xl->fops->lookup,
- &local->lock[0].layout.parent_layout.locks[i]->loc,
- xattr_req);
+ STACK_WIND_COOKIE (frame, dht_rename_lookup_cbk, (void *)(long)i,
+ local->lock[0].layout.parent_layout.locks[i]->xl,
+ local->lock[0].layout.parent_layout.locks[i]->xl->fops->lookup,
+ ((gf_uuid_compare (local->loc.gfid, \
+ local->lock[0].layout.parent_layout.locks[i]->loc.gfid) == 0) ?
+ &local->loc : &local->loc2), xattr_req);
}
dict_unref (xattr_req);