summaryrefslogtreecommitdiffstats
path: root/xlators/cluster/afr/src/afr-self-heal-entry.c
diff options
context:
space:
mode:
Diffstat (limited to 'xlators/cluster/afr/src/afr-self-heal-entry.c')
-rw-r--r--xlators/cluster/afr/src/afr-self-heal-entry.c489
1 files changed, 302 insertions, 187 deletions
diff --git a/xlators/cluster/afr/src/afr-self-heal-entry.c b/xlators/cluster/afr/src/afr-self-heal-entry.c
index 570c7080f..53491a1d7 100644
--- a/xlators/cluster/afr/src/afr-self-heal-entry.c
+++ b/xlators/cluster/afr/src/afr-self-heal-entry.c
@@ -1,20 +1,11 @@
/*
- Copyright (c) 2008-2011 Gluster, Inc. <http://www.gluster.com>
+ Copyright (c) 2008-2012 Red Hat, Inc. <http://www.redhat.com>
This file is part of GlusterFS.
- GlusterFS is free software; you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published
- by the Free Software Foundation; either version 3 of the License,
- or (at your option) any later version.
-
- GlusterFS is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- General Public License for more details.
-
- You should have received a copy of the GNU General Public License
- along with this program. If not, see
- <http://www.gnu.org/licenses/>.
+ This file is licensed to you under your choice of the GNU Lesser
+ General Public License, version 3 or any later version (LGPLv3 or
+ later), or the GNU General Public License, version 2 (GPLv2), in all
+ cases as published by the Free Software Foundation.
*/
#include <libgen.h>
@@ -59,6 +50,9 @@
} while (0);
int
+afr_sh_entry_impunge_create_file (call_frame_t *impunge_frame, xlator_t *this,
+ int child_index);
+int
afr_sh_entry_done (call_frame_t *frame, xlator_t *this)
{
afr_local_t *local = NULL;
@@ -67,10 +61,6 @@ afr_sh_entry_done (call_frame_t *frame, xlator_t *this)
local = frame->local;
sh = &local->self_heal;
- if (sh->healing_fd)
- fd_unref (sh->healing_fd);
- sh->healing_fd = NULL;
-
sh->completion_cbk (frame, this);
return 0;
@@ -112,7 +102,7 @@ afr_sh_entry_finish (call_frame_t *frame, xlator_t *this)
int
afr_sh_entry_erase_pending_cbk (call_frame_t *frame, void *cookie,
xlator_t *this, int32_t op_ret,
- int32_t op_errno, dict_t *xattr)
+ int32_t op_errno, dict_t *xattr, dict_t *xdata)
{
long i = 0;
int call_count = 0;
@@ -167,72 +157,20 @@ afr_sh_entry_erase_pending (call_frame_t *frame, xlator_t *this)
{
afr_local_t *local = NULL;
afr_self_heal_t *sh = NULL;
- afr_private_t *priv = NULL;
- int call_count = 0;
- int i = 0;
- dict_t **erase_xattr = NULL;
- int need_unwind = 0;
local = frame->local;
sh = &local->self_heal;
- priv = this->private;
if (sh->entries_skipped) {
- need_unwind = 1;
- sh->op_failed = _gf_true;
+ afr_set_self_heal_status (sh, AFR_SELF_HEAL_FAILED);
goto out;
}
- afr_sh_pending_to_delta (priv, sh->xattr, sh->delta_matrix, sh->success,
- priv->child_count, AFR_ENTRY_TRANSACTION);
-
- erase_xattr = GF_CALLOC (sizeof (*erase_xattr), priv->child_count,
- gf_afr_mt_dict_t);
-
- for (i = 0; i < priv->child_count; i++) {
- if (sh->xattr[i]) {
- call_count++;
-
- erase_xattr[i] = get_new_dict();
- dict_ref (erase_xattr[i]);
- }
- }
-
- if (call_count == 0)
- need_unwind = 1;
-
- afr_sh_delta_to_xattr (priv, sh->delta_matrix, erase_xattr,
- priv->child_count, AFR_ENTRY_TRANSACTION);
-
- local->call_count = call_count;
- for (i = 0; i < priv->child_count; i++) {
- if (!erase_xattr[i])
- continue;
-
- gf_log (this->name, GF_LOG_TRACE,
- "erasing pending flags from %s on %s",
- local->loc.path, priv->children[i]->name);
-
- STACK_WIND_COOKIE (frame, afr_sh_entry_erase_pending_cbk,
- (void *) (long) i,
- priv->children[i],
- priv->children[i]->fops->xattrop,
- &local->loc,
- GF_XATTROP_ADD_ARRAY, erase_xattr[i]);
- if (!--call_count)
- break;
- }
-
- for (i = 0; i < priv->child_count; i++) {
- if (erase_xattr[i]) {
- dict_unref (erase_xattr[i]);
- }
- }
- GF_FREE (erase_xattr);
-
+ afr_sh_erase_pending (frame, this, AFR_ENTRY_TRANSACTION,
+ afr_sh_entry_erase_pending_cbk,
+ afr_sh_entry_finish);
+ return 0;
out:
- if (need_unwind)
- afr_sh_entry_finish (frame, this);
-
+ afr_sh_entry_finish (frame, this);
return 0;
}
@@ -345,7 +283,8 @@ int
afr_sh_entry_expunge_parent_setattr_cbk (call_frame_t *expunge_frame,
void *cookie, xlator_t *this,
int32_t op_ret, int32_t op_errno,
- struct iatt *preop, struct iatt *postop)
+ struct iatt *preop, struct iatt *postop,
+ dict_t *xdata)
{
afr_private_t *priv = NULL;
afr_local_t *expunge_local = NULL;
@@ -381,7 +320,7 @@ afr_sh_entry_expunge_remove_cbk (call_frame_t *expunge_frame, void *cookie,
xlator_t *this,
int32_t op_ret, int32_t op_errno,
struct iatt *preparent,
- struct iatt *postparent)
+ struct iatt *postparent, dict_t *xdata)
{
afr_private_t *priv = NULL;
afr_local_t *expunge_local = NULL;
@@ -409,7 +348,6 @@ afr_sh_entry_expunge_remove_cbk (call_frame_t *expunge_frame, void *cookie,
}
valid = GF_SET_ATTR_ATIME | GF_SET_ATTR_MTIME;
- afr_build_parent_loc (&expunge_sh->parent_loc, &expunge_local->loc);
STACK_WIND_COOKIE (expunge_frame, afr_sh_entry_expunge_parent_setattr_cbk,
(void *) (long) active_src,
@@ -417,7 +355,7 @@ afr_sh_entry_expunge_remove_cbk (call_frame_t *expunge_frame, void *cookie,
priv->children[active_src]->fops->setattr,
&expunge_sh->parent_loc,
&expunge_sh->parentbuf,
- valid);
+ valid, NULL);
return 0;
}
@@ -441,7 +379,7 @@ afr_sh_entry_expunge_unlink (call_frame_t *expunge_frame, xlator_t *this,
(void *) (long) active_src,
priv->children[active_src],
priv->children[active_src]->fops->unlink,
- &expunge_local->loc);
+ &expunge_local->loc, 0, NULL);
return 0;
}
@@ -466,7 +404,7 @@ afr_sh_entry_expunge_rmdir (call_frame_t *expunge_frame, xlator_t *this,
(void *) (long) active_src,
priv->children[active_src],
priv->children[active_src]->fops->rmdir,
- &expunge_local->loc, 1);
+ &expunge_local->loc, 1, NULL);
return 0;
}
@@ -590,7 +528,7 @@ afr_sh_entry_expunge_purge (call_frame_t *expunge_frame, xlator_t *this,
(void *) (long) active_src,
priv->children[active_src],
priv->children[active_src]->fops->lookup,
- &expunge_local->loc, 0);
+ &expunge_local->loc, NULL);
return 0;
}
@@ -642,7 +580,8 @@ afr_sh_entry_expunge_entry_cbk (call_frame_t *expunge_frame, void *cookie,
if (need_expunge) {
gf_log (this->name, GF_LOG_INFO,
- "missing entry %s on %s",
+ "Entry %s is missing on %s and deleting from "
+ "replica's other bricks",
expunge_local->loc.path,
priv->children[source]->name);
@@ -674,6 +613,19 @@ out:
return 0;
}
+static gf_boolean_t
+can_skip_entry_self_heal (char *name, loc_t *parent_loc)
+{
+ if (strcmp (name, ".") == 0) {
+ return _gf_true;
+ } else if (strcmp (name, "..") == 0) {
+ return _gf_true;
+ } else if (loc_is_root (parent_loc) &&
+ (strcmp (name, GF_REPLICATE_TRASH_DIR) == 0)) {
+ return _gf_true;
+ }
+ return _gf_false;
+}
int
afr_sh_entry_expunge_entry (call_frame_t *frame, xlator_t *this,
@@ -701,15 +653,7 @@ afr_sh_entry_expunge_entry (call_frame_t *frame, xlator_t *this,
sh->expunge_done = afr_sh_entry_expunge_entry_done;
name = entry->d_name;
-
- if ((strcmp (name, ".") == 0)
- || (strcmp (name, "..") == 0)
- || ((strcmp (local->loc.path, "/") == 0)
- && (strcmp (name, GF_REPLICATE_TRASH_DIR) == 0))) {
-
- gf_log (this->name, GF_LOG_TRACE,
- "skipping inspection of %s under %s",
- name, local->loc.path);
+ if (can_skip_entry_self_heal (name, &local->loc)) {
op_ret = 0;
goto out;
}
@@ -724,16 +668,17 @@ afr_sh_entry_expunge_entry (call_frame_t *frame, xlator_t *this,
goto out;
}
- ALLOC_OR_GOTO (expunge_local, afr_local_t, out);
+ AFR_LOCAL_ALLOC_OR_GOTO (expunge_local, out);
expunge_frame->local = expunge_local;
expunge_sh = &expunge_local->self_heal;
expunge_sh->sh_frame = frame;
expunge_sh->active_source = active_src;
expunge_sh->entrybuf = entry->d_stat;
+ loc_copy (&expunge_sh->parent_loc, &local->loc);
ret = afr_build_child_loc (this, &expunge_local->loc, &local->loc,
- name, entry->d_stat.ia_gfid);
+ name);
if (ret != 0) {
op_errno = EINVAL;
goto out;
@@ -748,7 +693,7 @@ afr_sh_entry_expunge_entry (call_frame_t *frame, xlator_t *this,
(void *) (long) source,
priv->children[source],
priv->children[source]->fops->lookup,
- &expunge_local->loc, 0);
+ &expunge_local->loc, NULL);
ret = 0;
out:
@@ -763,7 +708,7 @@ int
afr_sh_entry_expunge_readdir_cbk (call_frame_t *frame, void *cookie,
xlator_t *this,
int32_t op_ret, int32_t op_errno,
- gf_dirent_t *entries)
+ gf_dirent_t *entries, dict_t *xdata)
{
afr_private_t *priv = NULL;
afr_local_t *local = NULL;
@@ -861,7 +806,7 @@ afr_sh_entry_expunge_all (call_frame_t *frame, xlator_t *this)
active_src = next_active_sink (frame, this, sh->active_source);
sh->active_source = active_src;
- if (sh->op_failed) {
+ if (is_self_heal_failed (sh, AFR_CHECK_SPECIFIC)) {
goto out;
}
@@ -924,7 +869,8 @@ int
afr_sh_entry_impunge_setattr_cbk (call_frame_t *impunge_frame, void *cookie,
xlator_t *this,
int32_t op_ret, int32_t op_errno,
- struct iatt *preop, struct iatt *postop)
+ struct iatt *preop, struct iatt *postop,
+ dict_t *xdata)
{
int call_count = 0;
afr_private_t *priv = NULL;
@@ -961,7 +907,8 @@ int
afr_sh_entry_impunge_parent_setattr_cbk (call_frame_t *setattr_frame,
void *cookie, xlator_t *this,
int32_t op_ret, int32_t op_errno,
- struct iatt *preop, struct iatt *postop)
+ struct iatt *preop, struct iatt *postop,
+ dict_t *xdata)
{
int call_count = 0;
afr_local_t *setattr_local = NULL;
@@ -1009,7 +956,7 @@ afr_sh_entry_impunge_setattr (call_frame_t *impunge_frame, xlator_t *this)
op_errno = ENOMEM;
goto out;
}
- ALLOC_OR_GOTO (setattr_frame->local, afr_local_t, out);
+ AFR_LOCAL_ALLOC_OR_GOTO (setattr_frame->local, out);
setattr_local = setattr_frame->local;
call_count = afr_errno_count (NULL, impunge_sh->child_errno,
priv->child_count, 0);
@@ -1025,7 +972,7 @@ afr_sh_entry_impunge_setattr (call_frame_t *impunge_frame, xlator_t *this)
(void *) (long) i, priv->children[i],
priv->children[i]->fops->setattr,
&setattr_local->loc,
- &impunge_sh->parentbuf, valid);
+ &impunge_sh->parentbuf, valid, NULL);
valid = GF_SET_ATTR_UID | GF_SET_ATTR_GID |
GF_SET_ATTR_ATIME | GF_SET_ATTR_MTIME;
@@ -1034,7 +981,7 @@ afr_sh_entry_impunge_setattr (call_frame_t *impunge_frame, xlator_t *this)
(void *) (long) i, priv->children[i],
priv->children[i]->fops->setattr,
&impunge_local->loc,
- &impunge_sh->entrybuf, valid);
+ &impunge_sh->entrybuf, valid, NULL);
call_count--;
}
GF_ASSERT (!call_count);
@@ -1050,7 +997,7 @@ int
afr_sh_entry_impunge_xattrop_cbk (call_frame_t *impunge_frame, void *cookie,
xlator_t *this,
int32_t op_ret, int32_t op_errno,
- dict_t *xattr)
+ dict_t *xattr, dict_t *xdata)
{
afr_private_t *priv = NULL;
afr_local_t *impunge_local = NULL;
@@ -1078,33 +1025,6 @@ out:
return 0;
}
-void
-afr_sh_prepare_new_entry_pending_matrix (int32_t **pending,
- int *child_errno,
- struct iatt *buf,
- unsigned int child_count)
-{
- int midx = 0;
- int idx = 0;
- int i = 0;
-
- midx = afr_index_for_transaction_type (AFR_METADATA_TRANSACTION);
- if (IA_ISDIR (buf->ia_type))
- idx = afr_index_for_transaction_type (AFR_ENTRY_TRANSACTION);
- else if (IA_ISREG (buf->ia_type))
- idx = afr_index_for_transaction_type (AFR_DATA_TRANSACTION);
- else
- idx = -1;
- for (i = 0; i < child_count; i++) {
- if (child_errno[i])
- continue;
- pending[i][midx] = hton32 (1);
- if (idx == -1)
- continue;
- pending[i][idx] = hton32 (1);
- }
-}
-
int
afr_sh_entry_impunge_perform_xattrop (call_frame_t *impunge_frame,
xlator_t *this)
@@ -1121,23 +1041,25 @@ afr_sh_entry_impunge_perform_xattrop (call_frame_t *impunge_frame,
impunge_sh = &impunge_local->self_heal;
active_src = impunge_sh->active_source;
- afr_sh_prepare_new_entry_pending_matrix (impunge_local->pending,
- impunge_sh->child_errno,
- &impunge_sh->entrybuf,
- priv->child_count);
+ afr_prepare_new_entry_pending_matrix (impunge_local->pending,
+ afr_is_errno_unset,
+ impunge_sh->child_errno,
+ &impunge_sh->entrybuf,
+ priv->child_count);
xattr = dict_new ();
if (!xattr) {
op_errno = ENOMEM;
goto out;
}
- afr_set_pending_dict (priv, xattr, impunge_local->pending);
+ afr_set_pending_dict (priv, xattr, impunge_local->pending, active_src,
+ LOCAL_LAST);
STACK_WIND_COOKIE (impunge_frame, afr_sh_entry_impunge_xattrop_cbk,
(void *) (long) active_src,
priv->children[active_src],
priv->children[active_src]->fops->xattrop,
- &impunge_local->loc, GF_XATTROP_ADD_ARRAY, xattr);
+ &impunge_local->loc, GF_XATTROP_ADD_ARRAY, xattr, NULL);
if (xattr)
dict_unref (xattr);
@@ -1154,7 +1076,7 @@ afr_sh_entry_impunge_newfile_cbk (call_frame_t *impunge_frame, void *cookie,
int32_t op_ret, int32_t op_errno,
inode_t *inode, struct iatt *stbuf,
struct iatt *preparent,
- struct iatt *postparent)
+ struct iatt *postparent, dict_t *xdata)
{
int call_count = 0;
afr_private_t *priv = NULL;
@@ -1194,6 +1116,125 @@ out:
return 0;
}
+int
+afr_sh_entry_impunge_hardlink_cbk (call_frame_t *impunge_frame, void *cookie,
+ xlator_t *this, int32_t op_ret,
+ int32_t op_errno, inode_t *inode,
+ struct iatt *buf, struct iatt *preparent,
+ struct iatt *postparent, dict_t *xdata)
+{
+ int call_count = 0;
+ afr_local_t *impunge_local = NULL;
+ afr_self_heal_t *impunge_sh = NULL;
+
+ impunge_local = impunge_frame->local;
+ impunge_sh = &impunge_local->self_heal;
+
+ if (IA_IFLNK == impunge_sh->entrybuf.ia_type) {
+ //For symlinks impunge is attempted un-conditionally
+ //So the file can already exist.
+ if ((op_ret < 0) && (op_errno == EEXIST))
+ op_ret = 0;
+ }
+
+ call_count = afr_frame_return (impunge_frame);
+ if (call_count == 0)
+ afr_sh_entry_call_impunge_done (impunge_frame, this,
+ op_ret, op_errno);
+
+ return 0;
+}
+
+int
+afr_sh_entry_impunge_hardlink (call_frame_t *impunge_frame, xlator_t *this,
+ int child_index)
+{
+ afr_private_t *priv = NULL;
+ afr_local_t *impunge_local = NULL;
+ afr_self_heal_t *impunge_sh = NULL;
+ loc_t *loc = NULL;
+ struct iatt *buf = NULL;
+ loc_t oldloc = {0};
+
+ priv = this->private;
+ impunge_local = impunge_frame->local;
+ impunge_sh = &impunge_local->self_heal;
+ loc = &impunge_local->loc;
+ buf = &impunge_sh->entrybuf;
+
+ oldloc.inode = inode_ref (loc->inode);
+ uuid_copy (oldloc.gfid, buf->ia_gfid);
+ gf_log (this->name, GF_LOG_DEBUG, "linking missing file %s on %s",
+ loc->path, priv->children[child_index]->name);
+
+ STACK_WIND_COOKIE (impunge_frame, afr_sh_entry_impunge_hardlink_cbk,
+ (void *) (long) child_index,
+ priv->children[child_index],
+ priv->children[child_index]->fops->link,
+ &oldloc, loc, NULL);
+ loc_wipe (&oldloc);
+
+ return 0;
+}
+
+int
+afr_sh_nameless_lookup_cbk (call_frame_t *impunge_frame, void *cookie,
+ xlator_t *this,
+ int32_t op_ret, int32_t op_errno, inode_t *inode,
+ struct iatt *buf, dict_t *xattr,
+ struct iatt *postparent)
+{
+ if (op_ret < 0) {
+ afr_sh_entry_impunge_create_file (impunge_frame, this,
+ (long)cookie);
+ } else {
+ afr_sh_entry_impunge_hardlink (impunge_frame, this,
+ (long)cookie);
+ }
+ return 0;
+}
+
+int
+afr_sh_entry_impunge_check_hardlink (call_frame_t *impunge_frame,
+ xlator_t *this,
+ int child_index, struct iatt *stbuf)
+{
+ afr_private_t *priv = NULL;
+ call_frame_t *frame = NULL;
+ afr_local_t *impunge_local = NULL;
+ afr_local_t *local = NULL;
+ afr_self_heal_t *impunge_sh = NULL;
+ afr_self_heal_t *sh = NULL;
+ loc_t *loc = NULL;
+ dict_t *xattr_req = NULL;
+ loc_t oldloc = {0};
+ int ret = -1;
+
+ priv = this->private;
+ AFR_INIT_SH_FRAME_VALS (impunge_frame, impunge_local, impunge_sh,
+ frame, local, sh);
+ loc = &impunge_local->loc;
+
+ xattr_req = dict_new ();
+ if (!xattr_req)
+ goto out;
+ oldloc.inode = inode_ref (loc->inode);
+ uuid_copy (oldloc.gfid, stbuf->ia_gfid);
+
+ STACK_WIND_COOKIE (impunge_frame, afr_sh_nameless_lookup_cbk,
+ (void *) (long) child_index,
+ priv->children[child_index],
+ priv->children[child_index]->fops->lookup,
+ &oldloc, xattr_req);
+ ret = 0;
+out:
+ if (xattr_req)
+ dict_unref (xattr_req);
+ loc_wipe (&oldloc);
+ if (ret)
+ sh->impunge_done (frame, this, -1, ENOMEM);
+ return 0;
+}
int
afr_sh_entry_impunge_mknod (call_frame_t *impunge_frame, xlator_t *this,
@@ -1222,6 +1263,35 @@ afr_sh_entry_impunge_mknod (call_frame_t *impunge_frame, xlator_t *this,
gf_log (this->name, GF_LOG_INFO, "%s: gfid set failed",
impunge_local->loc.path);
+ /*
+ * Reason for adding GLUSTERFS_INTERNAL_FOP_KEY :
+ *
+ * Problem:
+ * While a brick is down in a replica pair, lets say the user creates
+ * one file(file-A) and a hard link to that file(h-file-A). After the
+ * brick comes back up, entry self-heal is attempted on parent dir of
+ * these two files. As part of readdir in self-heal it reads both the
+ * entries file-A and h-file-A for both of them it does name less lookup
+ * to check if there are any hardlinks already present in the
+ * destination brick. It finds that there are no hard links already
+ * present for files file-A, h-file-A. Self-heal does mknods for both
+ * file-A and h-file-A. This leads to file-A and h-file-A not being
+ * hardlinks anymore.
+ *
+ * Fix: (More like shrinking of race-window, the race itself is still
+ * present in posix-mknod).
+ * If mknod comes with the presence of GLUSTERFS_INTERNAL_FOP_KEY then
+ * posix_mknod checks if there are already any gfid-links and does
+ * link() instead of mknod. There still can be a race where two
+ * posix_mknods same gfid see that
+ * gfid-link file is not present and proceeds with mknods and result in
+ * two different files with same gfid.
+ */
+ ret = dict_set_str (dict, GLUSTERFS_INTERNAL_FOP_KEY, "yes");
+ if (ret)
+ gf_log (this->name, GF_LOG_INFO, "%s: %s set failed",
+ impunge_local->loc.path, GLUSTERFS_INTERNAL_FOP_KEY);
+
STACK_WIND_COOKIE (impunge_frame, afr_sh_entry_impunge_newfile_cbk,
(void *) (long) child_index,
priv->children[child_index],
@@ -1229,7 +1299,7 @@ afr_sh_entry_impunge_mknod (call_frame_t *impunge_frame, xlator_t *this,
&impunge_local->loc,
st_mode_from_ia (stbuf->ia_prot, stbuf->ia_type),
makedev (ia_major (stbuf->ia_rdev),
- ia_minor (stbuf->ia_rdev)), dict);
+ ia_minor (stbuf->ia_rdev)), 0, dict);
if (dict)
dict_unref (dict);
@@ -1276,7 +1346,7 @@ afr_sh_entry_impunge_mkdir (call_frame_t *impunge_frame, xlator_t *this,
priv->children[child_index]->fops->mkdir,
&impunge_local->loc,
st_mode_from_ia (stbuf->ia_prot, stbuf->ia_type),
- dict);
+ 0, dict);
if (dict)
dict_unref (dict);
@@ -1298,7 +1368,7 @@ afr_sh_entry_impunge_symlink (call_frame_t *impunge_frame, xlator_t *this,
priv = this->private;
impunge_local = impunge_frame->local;
- buf = &impunge_local->cont.symlink.buf;
+ buf = &impunge_local->cont.dir_fop.buf;
dict = dict_new ();
if (!dict) {
@@ -1323,7 +1393,7 @@ afr_sh_entry_impunge_symlink (call_frame_t *impunge_frame, xlator_t *this,
(void *) (long) child_index,
priv->children[child_index],
priv->children[child_index]->fops->symlink,
- linkname, &impunge_local->loc, dict);
+ linkname, &impunge_local->loc, 0, dict);
if (dict)
dict_unref (dict);
@@ -1337,7 +1407,7 @@ afr_sh_entry_impunge_symlink_unlink_cbk (call_frame_t *impunge_frame,
void *cookie, xlator_t *this,
int32_t op_ret, int32_t op_errno,
struct iatt *preparent,
- struct iatt *postparent)
+ struct iatt *postparent, dict_t *xdata)
{
afr_private_t *priv = NULL;
afr_local_t *impunge_local = NULL;
@@ -1398,7 +1468,7 @@ afr_sh_entry_impunge_symlink_unlink (call_frame_t *impunge_frame, xlator_t *this
(void *) (long) child_index,
priv->children[child_index],
priv->children[child_index]->fops->unlink,
- &impunge_local->loc);
+ &impunge_local->loc, 0, NULL);
return 0;
}
@@ -1408,7 +1478,7 @@ int
afr_sh_entry_impunge_readlink_sink_cbk (call_frame_t *impunge_frame, void *cookie,
xlator_t *this,
int32_t op_ret, int32_t op_errno,
- const char *linkname, struct iatt *sbuf)
+ const char *linkname, struct iatt *sbuf, dict_t *xdata)
{
afr_private_t *priv = NULL;
afr_local_t *impunge_local = NULL;
@@ -1490,7 +1560,7 @@ afr_sh_entry_impunge_readlink_sink (call_frame_t *impunge_frame, xlator_t *this,
(void *) (long) child_index,
priv->children[child_index],
priv->children[child_index]->fops->readlink,
- &impunge_local->loc, 4096);
+ &impunge_local->loc, 4096, NULL);
return 0;
}
@@ -1500,7 +1570,7 @@ int
afr_sh_entry_impunge_readlink_cbk (call_frame_t *impunge_frame, void *cookie,
xlator_t *this,
int32_t op_ret, int32_t op_errno,
- const char *linkname, struct iatt *sbuf)
+ const char *linkname, struct iatt *sbuf, dict_t *xdata)
{
afr_private_t *priv = NULL;
afr_local_t *impunge_local = NULL;
@@ -1558,13 +1628,13 @@ afr_sh_entry_impunge_readlink (call_frame_t *impunge_frame, xlator_t *this,
impunge_local = impunge_frame->local;
impunge_sh = &impunge_local->self_heal;
active_src = impunge_sh->active_source;
- impunge_local->cont.symlink.buf = *stbuf;
+ impunge_local->cont.dir_fop.buf = *stbuf;
STACK_WIND_COOKIE (impunge_frame, afr_sh_entry_impunge_readlink_cbk,
(void *) (long) child_index,
priv->children[active_src],
priv->children[active_src]->fops->readlink,
- &impunge_local->loc, 4096);
+ &impunge_local->loc, 4096, NULL);
return 0;
}
@@ -1573,16 +1643,18 @@ int
afr_sh_entry_impunge_create (call_frame_t *impunge_frame, xlator_t *this,
int child_index)
{
- afr_local_t *impunge_local = NULL;
- afr_self_heal_t *impunge_sh = NULL;
+ call_frame_t *frame = NULL;
+ afr_local_t *impunge_local = NULL;
+ afr_local_t *local = NULL;
+ afr_self_heal_t *impunge_sh = NULL;
+ afr_self_heal_t *sh = NULL;
afr_private_t *priv = NULL;
ia_type_t type = IA_INVAL;
- int ret = 0;
int active_src = 0;
struct iatt *buf = NULL;
- impunge_local = impunge_frame->local;
- impunge_sh = &impunge_local->self_heal;
+ AFR_INIT_SH_FRAME_VALS (impunge_frame, impunge_local, impunge_sh,
+ frame, local, sh);
active_src = impunge_sh->active_source;
afr_update_loc_gfids (&impunge_local->loc, &impunge_sh->entrybuf,
&impunge_sh->parentbuf);
@@ -1596,6 +1668,52 @@ afr_sh_entry_impunge_create (call_frame_t *impunge_frame, xlator_t *this,
case IA_IFBLK:
case IA_IFCHR:
case IA_IFIFO:
+ case IA_IFLNK:
+ afr_sh_entry_impunge_check_hardlink (impunge_frame, this,
+ child_index, buf);
+ break;
+ case IA_IFDIR:
+ afr_sh_entry_impunge_mkdir (impunge_frame, this,
+ child_index, buf);
+ break;
+ default:
+ gf_log (this->name, GF_LOG_ERROR,
+ "%s has unknown file type on %s: 0%o",
+ impunge_local->loc.path,
+ priv->children[active_src]->name, type);
+ sh->impunge_done (frame, this, -1, EINVAL);
+ break;
+ }
+
+ return 0;
+}
+
+int
+afr_sh_entry_impunge_create_file (call_frame_t *impunge_frame, xlator_t *this,
+ int child_index)
+{
+ call_frame_t *frame = NULL;
+ afr_local_t *impunge_local = NULL;
+ afr_local_t *local = NULL;
+ afr_self_heal_t *impunge_sh = NULL;
+ afr_self_heal_t *sh = NULL;
+ afr_private_t *priv = NULL;
+ ia_type_t type = IA_INVAL;
+ int active_src = 0;
+ struct iatt *buf = NULL;
+
+ AFR_INIT_SH_FRAME_VALS (impunge_frame, impunge_local, impunge_sh,
+ frame, local, sh);
+ active_src = impunge_sh->active_source;
+ buf = &impunge_sh->entrybuf;
+ type = buf->ia_type;
+
+ switch (type) {
+ case IA_IFSOCK:
+ case IA_IFREG:
+ case IA_IFBLK:
+ case IA_IFCHR:
+ case IA_IFIFO:
afr_sh_entry_impunge_mknod (impunge_frame, this,
child_index, buf);
break;
@@ -1603,20 +1721,16 @@ afr_sh_entry_impunge_create (call_frame_t *impunge_frame, xlator_t *this,
afr_sh_entry_impunge_readlink (impunge_frame, this,
child_index, buf);
break;
- case IA_IFDIR:
- afr_sh_entry_impunge_mkdir (impunge_frame, this,
- child_index, buf);
- break;
default:
gf_log (this->name, GF_LOG_ERROR,
"%s has unknown file type on %s: 0%o",
impunge_local->loc.path,
priv->children[active_src]->name, type);
- ret = -1;
+ sh->impunge_done (frame, this, -1, EINVAL);
break;
}
- return ret;
+ return 0;
}
gf_boolean_t
@@ -1762,7 +1876,8 @@ afr_sh_entry_common_lookup_done (call_frame_t *impunge_frame, xlator_t *this,
afr_sh_common_lookup (impunge_frame, this, &impunge_local->loc,
afr_sh_entry_common_lookup_done, gfid,
AFR_LOOKUP_FAIL_CONFLICTS |
- AFR_LOOKUP_FAIL_MISSING_GFIDS);
+ AFR_LOOKUP_FAIL_MISSING_GFIDS,
+ NULL);
} else {
afr_sh_entry_call_impunge_recreate (impunge_frame, this);
}
@@ -1793,14 +1908,7 @@ afr_sh_entry_impunge_entry (call_frame_t *frame, xlator_t *this,
active_src = sh->active_source;
sh->impunge_done = afr_sh_entry_impunge_entry_done;
- if ((strcmp (entry->d_name, ".") == 0)
- || (strcmp (entry->d_name, "..") == 0)
- || ((strcmp (local->loc.path, "/") == 0)
- && (strcmp (entry->d_name, GF_REPLICATE_TRASH_DIR) == 0))) {
-
- gf_log (this->name, GF_LOG_TRACE,
- "skipping inspection of %s under %s",
- entry->d_name, local->loc.path);
+ if (can_skip_entry_self_heal (entry->d_name, &local->loc)) {
op_ret = 0;
goto out;
}
@@ -1819,7 +1927,7 @@ afr_sh_entry_impunge_entry (call_frame_t *frame, xlator_t *this,
impunge_local = impunge_frame->local;
impunge_sh = &impunge_local->self_heal;
ret = afr_build_child_loc (this, &impunge_local->loc, &local->loc,
- entry->d_name, entry->d_stat.ia_gfid);
+ entry->d_name);
loc_copy (&impunge_sh->parent_loc, &local->loc);
if (ret != 0) {
op_errno = ENOMEM;
@@ -1828,7 +1936,7 @@ afr_sh_entry_impunge_entry (call_frame_t *frame, xlator_t *this,
afr_sh_common_lookup (impunge_frame, this, &impunge_local->loc,
afr_sh_entry_common_lookup_done, NULL,
- AFR_LOOKUP_FAIL_CONFLICTS);
+ AFR_LOOKUP_FAIL_CONFLICTS, NULL);
op_ret = 0;
out:
@@ -1846,7 +1954,7 @@ int
afr_sh_entry_impunge_readdir_cbk (call_frame_t *frame, void *cookie,
xlator_t *this,
int32_t op_ret, int32_t op_errno,
- gf_dirent_t *entries)
+ gf_dirent_t *entries, dict_t *xdata)
{
afr_private_t *priv = NULL;
afr_local_t *local = NULL;
@@ -1869,7 +1977,7 @@ afr_sh_entry_impunge_readdir_cbk (call_frame_t *frame, void *cookie,
local->loc.path,
priv->children[active_src]->name,
strerror (op_errno));
- sh->op_failed = 1;
+ afr_set_self_heal_status (sh, AFR_SELF_HEAL_FAILED);
} else {
gf_log (this->name, GF_LOG_TRACE,
"readdir of %s on subvolume %s complete",
@@ -1919,7 +2027,7 @@ afr_sh_entry_impunge_subvol (call_frame_t *frame, xlator_t *this)
STACK_WIND (frame, afr_sh_entry_impunge_readdir_cbk,
priv->children[active_src],
priv->children[active_src]->fops->readdirp,
- sh->healing_fd, sh->block_size, sh->offset, 0);
+ sh->healing_fd, sh->block_size, sh->offset, NULL);
return 0;
}
@@ -1942,7 +2050,7 @@ afr_sh_entry_impunge_all (call_frame_t *frame, xlator_t *this)
active_src = next_active_source (frame, this, sh->active_source);
sh->active_source = active_src;
- if (sh->op_failed) {
+ if (is_self_heal_failed (sh, AFR_CHECK_SPECIFIC)) {
afr_sh_entry_finish (frame, this);
return 0;
}
@@ -1965,7 +2073,7 @@ afr_sh_entry_impunge_all (call_frame_t *frame, xlator_t *this)
int
afr_sh_entry_opendir_cbk (call_frame_t *frame, void *cookie, xlator_t *this,
- int32_t op_ret, int32_t op_errno, fd_t *fd)
+ int32_t op_ret, int32_t op_errno, fd_t *fd, dict_t *xdata)
{
afr_local_t *local = NULL;
afr_self_heal_t *sh = NULL;
@@ -1991,7 +2099,7 @@ afr_sh_entry_opendir_cbk (call_frame_t *frame, void *cookie, xlator_t *this,
local->loc.path,
priv->children[child_index]->name,
strerror (op_errno));
- sh->op_failed = 1;
+ afr_set_self_heal_status (sh, AFR_SELF_HEAL_FAILED);
}
}
UNLOCK (&frame->lock);
@@ -1999,7 +2107,7 @@ afr_sh_entry_opendir_cbk (call_frame_t *frame, void *cookie, xlator_t *this,
call_count = afr_frame_return (frame);
if (call_count == 0) {
- if (sh->op_failed) {
+ if (is_self_heal_failed (sh, AFR_CHECK_SPECIFIC)) {
afr_sh_entry_finish (frame, this);
return 0;
}
@@ -2037,7 +2145,7 @@ afr_sh_entry_open (call_frame_t *frame, xlator_t *this)
source = local->self_heal.source;
sources = local->self_heal.sources;
- sh->block_size = 65536; //131072
+ sh->block_size = priv->sh_readdir_size;
sh->offset = 0;
call_count = sh->active_sinks;
@@ -2059,7 +2167,7 @@ afr_sh_entry_open (call_frame_t *frame, xlator_t *this)
(void *) (long) source,
priv->children[source],
priv->children[source]->fops->opendir,
- &local->loc, fd);
+ &local->loc, fd, NULL);
call_count--;
}
@@ -2076,7 +2184,7 @@ afr_sh_entry_open (call_frame_t *frame, xlator_t *this)
(void *) (long) i,
priv->children[i],
priv->children[i]->fops->opendir,
- &local->loc, fd);
+ &local->loc, fd, NULL);
if (!--call_count)
break;
@@ -2131,6 +2239,8 @@ afr_sh_entry_sync_prepare (call_frame_t *frame, xlator_t *this)
"merging all entries as a conservative decision",
local->loc.path);
+ sh->actual_sh_started = _gf_true;
+ afr_set_self_heal_status (sh, AFR_SELF_HEAL_SYNC_BEGIN);
afr_sh_entry_open (frame, this);
return 0;
@@ -2153,7 +2263,7 @@ afr_sh_entry_fix (call_frame_t *frame, xlator_t *this,
priv = this->private;
if (op_ret < 0) {
- sh->op_failed = 1;
+ afr_set_self_heal_status (sh, AFR_SELF_HEAL_FAILED);
afr_sh_set_error (sh, op_errno);
afr_sh_entry_finish (frame, this);
goto out;
@@ -2216,7 +2326,7 @@ afr_sh_post_nonblocking_entry_cbk (call_frame_t *frame, xlator_t *this)
if (int_lock->lock_op_ret < 0) {
gf_log (this->name, GF_LOG_ERROR, "Non Blocking entrylks "
"failed for %s.", local->loc.path);
- sh->op_failed = 1;
+ afr_set_self_heal_status (sh, AFR_SELF_HEAL_FAILED);
afr_sh_entry_done (frame, this);
} else {
@@ -2225,7 +2335,8 @@ afr_sh_post_nonblocking_entry_cbk (call_frame_t *frame, xlator_t *this)
afr_sh_common_lookup (frame, this, &local->loc,
afr_sh_entry_fix, NULL,
AFR_LOOKUP_FAIL_CONFLICTS |
- AFR_LOOKUP_FAIL_MISSING_GFIDS);
+ AFR_LOOKUP_FAIL_MISSING_GFIDS,
+ NULL);
}
return 0;
@@ -2234,14 +2345,18 @@ afr_sh_post_nonblocking_entry_cbk (call_frame_t *frame, xlator_t *this)
int
afr_self_heal_entry (call_frame_t *frame, xlator_t *this)
{
- afr_local_t *local = NULL;
+ afr_local_t *local = NULL;
afr_private_t *priv = NULL;
-
+ afr_self_heal_t *sh = NULL;
priv = this->private;
local = frame->local;
+ sh = &local->self_heal;
+
+ sh->sh_type_in_action = AFR_SELF_HEAL_ENTRY;
if (local->self_heal.do_entry_self_heal && priv->entry_self_heal) {
+ afr_set_self_heal_status (sh, AFR_SELF_HEAL_STARTED);
afr_sh_entrylk (frame, this, &local->loc, NULL,
afr_sh_post_nonblocking_entry_cbk);
} else {