summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--libglusterfs/src/common-utils.h25
-rw-r--r--libglusterfs/src/glusterfs.h1
-rw-r--r--xlators/cluster/dht/src/dht-rename.c82
3 files changed, 108 insertions, 0 deletions
diff --git a/libglusterfs/src/common-utils.h b/libglusterfs/src/common-utils.h
index e8b5fc83591..c361405d5eb 100644
--- a/libglusterfs/src/common-utils.h
+++ b/libglusterfs/src/common-utils.h
@@ -130,6 +130,31 @@ enum _gf_xlator_ipc_targets {
typedef enum _gf_boolean gf_boolean_t;
typedef enum _gf_client_pid gf_client_pid_t;
typedef enum _gf_xlator_ipc_targets _gf_xlator_ipc_targets_t;
+
+/* The DHT file rename operation is not a straightforward rename.
+ * It involves creating linkto and linkfiles, and can unlink or rename the
+ * source file depending on the hashed and cached subvols for the source
+ * and target files. this makes it difficult for geo-rep to figure out that
+ * a rename operation has taken place.
+ *
+ * We now send a special key and the values of the source and target pargfids
+ * and basenames to indicate to changelog that the operation in question
+ * should be treated as a rename. We are explicitly filling and sending this
+ * as a binary value in the dictionary as the unlink op will not have the
+ * source file information. The lengths of the src and target basenames
+ * are used to calculate where to start reading the names in the structure.
+ * XFS allows a max of 255 chars for filenames but other file systems might
+ * not have such restrictions
+ */
+typedef struct dht_changelog_rename_info {
+ uuid_t old_pargfid;
+ uuid_t new_pargfid;
+ int32_t oldname_len;
+ int32_t newname_len;
+ char buffer[1];
+ } dht_changelog_rename_info_t;
+
+
typedef int (*gf_cmp) (void *, void *);
void gf_global_variable_init(void);
diff --git a/libglusterfs/src/glusterfs.h b/libglusterfs/src/glusterfs.h
index ba59e4d54db..3373ef6f7b8 100644
--- a/libglusterfs/src/glusterfs.h
+++ b/libglusterfs/src/glusterfs.h
@@ -140,6 +140,7 @@
#define GLUSTERFS_VERSION_XCHG_KEY "glusterfs.version.xchg"
#define GLUSTERFS_INTERNAL_FOP_KEY "glusterfs-internal-fop"
+#define DHT_CHANGELOG_RENAME_OP_KEY "changelog.rename-op"
#define ZR_FILE_CONTENT_STR "glusterfs.file."
#define ZR_FILE_CONTENT_STRLEN 15
diff --git a/xlators/cluster/dht/src/dht-rename.c b/xlators/cluster/dht/src/dht-rename.c
index 0594945203e..4e4e9869685 100644
--- a/xlators/cluster/dht/src/dht-rename.c
+++ b/xlators/cluster/dht/src/dht-rename.c
@@ -319,6 +319,56 @@ err:
NULL, NULL);
return 0;
}
+
+
+
+static int
+dht_rename_track_for_changelog (xlator_t *this, dict_t *xattr,
+ loc_t *oldloc, loc_t *newloc)
+{
+ int ret = -1;
+ dht_changelog_rename_info_t *info = NULL;
+ char *name = NULL;
+ int len1 = 0;
+ int len2 = 0;
+ int size = 0;
+
+ if (!xattr || !oldloc || !newloc || !this)
+ return ret;
+
+ len1 = strlen (oldloc->name) + 1;
+ len2 = strlen (newloc->name) + 1;
+ size = sizeof (dht_changelog_rename_info_t) + len1 + len2;
+
+ info = GF_CALLOC (size, sizeof(char), gf_common_mt_char);
+ if (!info) {
+ gf_msg (this->name, GF_LOG_ERROR, 0,
+ DHT_MSG_DICT_SET_FAILED,
+ "Failed to calloc memory");
+ return ret;
+ }
+
+ gf_uuid_copy (info->old_pargfid, oldloc->pargfid);
+ gf_uuid_copy (info->new_pargfid, newloc->pargfid);
+
+ info->oldname_len = len1;
+ info->newname_len = len2;
+ strncpy (info->buffer, oldloc->name, len1);
+ name = info->buffer + len1;
+ strncpy (name, newloc->name, len2);
+
+ ret = dict_set_bin (xattr, DHT_CHANGELOG_RENAME_OP_KEY,
+ info, size);
+ if (ret) {
+ gf_msg (this->name, GF_LOG_ERROR, 0, DHT_MSG_DICT_SET_FAILED,
+ "Failed to set dictionary value: key = %s,"
+ " path = %s", DHT_CHANGELOG_RENAME_OP_KEY,
+ oldloc->name);
+ }
+ return ret;
+}
+
+
#define DHT_MARK_FOP_INTERNAL(xattr) do { \
int tmp = -1; \
if (!xattr) { \
@@ -354,6 +404,32 @@ err:
} \
}while (0)
+
+#define DHT_CHANGELOG_TRACK_AS_RENAME(xattr, oldloc, newloc) do { \
+ int tmp = -1; \
+ if (!xattr) { \
+ xattr = dict_new (); \
+ if (!xattr) { \
+ gf_msg (this->name, GF_LOG_ERROR, 0, \
+ DHT_MSG_DICT_SET_FAILED, \
+ "Failed to create dictionary to " \
+ "track rename"); \
+ break; \
+ } \
+ } \
+ \
+ tmp = dht_rename_track_for_changelog (this, xattr, \
+ oldloc, newloc); \
+ \
+ if (tmp) { \
+ gf_msg (this->name, GF_LOG_ERROR, 0, \
+ DHT_MSG_DICT_SET_FAILED, \
+ "Failed to set dictionary value: key = %s," \
+ " path = %s", DHT_CHANGELOG_RENAME_OP_KEY, \
+ (oldloc)->path); \
+ } \
+ } while (0)
+
int
dht_rename_unlock_cbk (call_frame_t *frame, void *cookie,
xlator_t *this, int32_t op_ret, int32_t op_errno,
@@ -745,6 +821,8 @@ err:
DHT_MARKER_DONT_ACCOUNT(xattr_new);
}
+ DHT_CHANGELOG_TRACK_AS_RENAME(xattr_new, &local->loc,
+ &local->loc2);
STACK_WIND (frame, dht_rename_unlink_cbk,
src_cached, src_cached->fops->unlink,
&local->loc, 0, xattr_new);
@@ -831,6 +909,10 @@ dht_do_rename (call_frame_t *frame)
DHT_MARKER_DONT_ACCOUNT(dict);
}
+ if (rename_subvol == src_cached) {
+ DHT_CHANGELOG_TRACK_AS_RENAME(dict, &local->loc, &local->loc2);
+ }
+
gf_msg_trace (this->name, 0,
"renaming %s => %s (%s)",
local->loc.path, local->loc2.path, rename_subvol->name);