summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorKrutika Dhananjay <kdhananj@redhat.com>2016-06-22 14:52:58 +0530
committerPranith Kumar Karampuri <pkarampu@redhat.com>2016-06-28 01:13:57 -0700
commit2ca5388692e70e079c99771d8c66a06bd90d5268 (patch)
treeda9ff1435f6ba04267537d25bebaa9f0a4f01f21
parent888de8851e718d8e3117e47fa35cfc075b998f62 (diff)
features/index: Delete parent dir indices when heal on it is complete
In this patch, the state information about whether a directory gfid index is present or not is stored in the inode ctx with values IN and NOTIN. This saves index xl the need to perform stat() everytime an index_entry_create() is called. When a brick is restarted these in-memory inode ctx records will be gone. So when granular entry heal happens after a brick is restarted, and a post-op is done on the parent, if the state gotten from inode ctx is UNKNOWN, then index xl does a stat to initialize the state as IN or NOTIN. Note that this is a one-time operation for the lifetime of the brick. Such a change also helps avoid calling index_del() in xattrop_index_action() periodically even when granular self-heal is disabled or when the volume type is disperse. Change-Id: Ib92c17350e6531b91ab81477410fe1e7a5856207 BUG: 1331323 Signed-off-by: Krutika Dhananjay <kdhananj@redhat.com> Reviewed-on: http://review.gluster.org/14781 Smoke: Gluster Build System <jenkins@build.gluster.org> CentOS-regression: Gluster Build System <jenkins@build.gluster.org> NetBSD-regression: NetBSD Build System <jenkins@build.gluster.org> Reviewed-by: Pranith Kumar Karampuri <pkarampu@redhat.com>
-rw-r--r--tests/basic/afr/granular-esh/conservative-merge.t17
-rw-r--r--tests/basic/afr/granular-esh/granular-esh.t17
-rw-r--r--xlators/features/index/src/index.c123
3 files changed, 106 insertions, 51 deletions
diff --git a/tests/basic/afr/granular-esh/conservative-merge.t b/tests/basic/afr/granular-esh/conservative-merge.t
index 194c0fcc2de..b566a0ea4d3 100644
--- a/tests/basic/afr/granular-esh/conservative-merge.t
+++ b/tests/basic/afr/granular-esh/conservative-merge.t
@@ -126,14 +126,13 @@ TEST ! stat $B0/${V0}1/.glusterfs/indices/entry-changes/$gfid_subdir/f1
TEST ! stat $B0/${V0}1/.glusterfs/indices/entry-changes/$gfid_dir3/f1
TEST ! stat $B0/${V0}1/.glusterfs/indices/entry-changes/$gfid_subdir2/f1
-# To be uncommented once index xl is made to purge the parent gfid dir
-#TEST ! stat $B0/${V0}1/.glusterfs/indices/entry-changes/$ROOT_GFID
-#TEST ! stat $B0/${V0}0/.glusterfs/indices/entry-changes/$ROOT_GFID
-#TEST ! stat $B0/${V0}1/.glusterfs/indices/entry-changes/$gfid_dir
-#TEST ! stat $B0/${V0}0/.glusterfs/indices/entry-changes/$gfid_dir
-#TEST ! stat $B0/${V0}1/.glusterfs/indices/entry-changes/$gfid_dir2
-#TEST ! stat $B0/${V0}1/.glusterfs/indices/entry-changes/$gfid_subdir
-#TEST ! stat $B0/${V0}1/.glusterfs/indices/entry-changes/$gfid_dir3
-#TEST ! stat $B0/${V0}1/.glusterfs/indices/entry-changes/$gfid_subdir2
+TEST ! stat $B0/${V0}1/.glusterfs/indices/entry-changes/$ROOT_GFID
+TEST ! stat $B0/${V0}0/.glusterfs/indices/entry-changes/$ROOT_GFID
+TEST ! stat $B0/${V0}1/.glusterfs/indices/entry-changes/$gfid_dir
+TEST ! stat $B0/${V0}0/.glusterfs/indices/entry-changes/$gfid_dir
+TEST ! stat $B0/${V0}1/.glusterfs/indices/entry-changes/$gfid_dir2
+TEST ! stat $B0/${V0}1/.glusterfs/indices/entry-changes/$gfid_subdir
+TEST ! stat $B0/${V0}1/.glusterfs/indices/entry-changes/$gfid_dir3
+TEST ! stat $B0/${V0}1/.glusterfs/indices/entry-changes/$gfid_subdir2
cleanup
diff --git a/tests/basic/afr/granular-esh/granular-esh.t b/tests/basic/afr/granular-esh/granular-esh.t
index 9aa4505a3c2..4adcfc7456a 100644
--- a/tests/basic/afr/granular-esh/granular-esh.t
+++ b/tests/basic/afr/granular-esh/granular-esh.t
@@ -149,9 +149,10 @@ TEST ! stat $B0/${V0}1/.glusterfs/indices/entry-changes/$ROOT_GFID/dir
TEST ! stat $B0/${V0}1/.glusterfs/indices/entry-changes/$ROOT_GFID/newdir
TEST ! stat $B0/${V0}1/.glusterfs/indices/entry-changes/$ROOT_GFID/file_stale
-TEST ! stat $B0/${V0}1/.glusterfs/indices/entry-changesi/$gfid_dir/f1
-TEST ! stat $B0/${V0}1/.glusterfs/indices/entry-changesi/$gfid_dir/f2
-TEST ! stat $B0/${V0}1/.glusterfs/indices/entry-changesi/$gfid_dir/f3
+# To be uncommented once index xl is made to purge the parent gfid dir on rm -rf
+#TEST ! stat $B0/${V0}1/.glusterfs/indices/entry-changes/$gfid_dir/f1
+#TEST ! stat $B0/${V0}1/.glusterfs/indices/entry-changes/$gfid_dir/f2
+#TEST ! stat $B0/${V0}1/.glusterfs/indices/entry-changes/$gfid_dir/f3
TEST ! stat $B0/${V0}1/.glusterfs/indices/entry-changes/$gfid_newdir/f1
TEST ! stat $B0/${V0}1/.glusterfs/indices/entry-changes/$gfid_newdir/f2
@@ -160,10 +161,10 @@ TEST ! stat $B0/${V0}1/.glusterfs/indices/entry-changes/$gfid_newsubdir/f1
TEST ! stat $B0/${V0}1/.glusterfs/indices/entry-changes/$gfid_newsubdir/f2
TEST ! stat $B0/${V0}1/.glusterfs/indices/entry-changes/$gfid_newsubdir/f3
-# To be uncommented once index xl is made to purge the parent gfid dir
-# TEST ! stat $B0/${V0}1/.glusterfs/indices/entry-changes/$ROOT_GFID
-# TEST ! stat $B0/${V0}1/.glusterfs/indices/entry-changes/$gfid_newdir
-# TEST ! stat $B0/${V0}1/.glusterfs/indices/entry-changes/$newsubdir
-# TEST ! stat $B0/${V0}1/.glusterfs/indices/entry-changes/$dir
+TEST ! stat $B0/${V0}1/.glusterfs/indices/entry-changes/$ROOT_GFID
+TEST ! stat $B0/${V0}1/.glusterfs/indices/entry-changes/$gfid_newdir
+TEST ! stat $B0/${V0}1/.glusterfs/indices/entry-changes/$gfid_newsubdir
+# To be uncommented once index xl is made to purge the parent gfid dir on rm -rf
+#TEST ! stat $B0/${V0}1/.glusterfs/indices/entry-changes/$gfid_dir
cleanup
diff --git a/xlators/features/index/src/index.c b/xlators/features/index/src/index.c
index b6bd5e87b73..cd40f2587b2 100644
--- a/xlators/features/index/src/index.c
+++ b/xlators/features/index/src/index.c
@@ -652,14 +652,19 @@ index_del (xlator_t *this, uuid_t gfid, const char *subdir, int type)
out, op_errno, EINVAL);
make_gfid_path (priv->index_basepath, subdir, gfid,
gfid_path, sizeof (gfid_path));
- ret = sys_unlink (gfid_path);
+
+ if ((strcmp (subdir, ENTRY_CHANGES_SUBDIR)) == 0)
+ ret = sys_rmdir (gfid_path);
+ else
+ ret = sys_unlink (gfid_path);
+
if (ret && (errno != ENOENT)) {
- gf_log (this->name, GF_LOG_ERROR,
- "%s: failed to delete from index (%s)",
- gfid_path, strerror (errno));
+ gf_log (this->name, GF_LOG_ERROR, "%s: failed to delete"
+ " from index (%s)", gfid_path, strerror (errno));
ret = -errno;
goto out;
}
+
index_dec_link_count (priv, type);
ret = 0;
out:
@@ -758,37 +763,47 @@ _check_key_is_zero_filled (dict_t *d, char *k, data_t *v,
}
int
-index_entry_create (xlator_t *this, uuid_t gfid, char *filename)
-{
- char entry_base_index_path[PATH_MAX] = {0};
- char pgfid_path[PATH_MAX] = {0};
- char entry_path[PATH_MAX] = {0};
- struct stat st = {0};
- uuid_t index = {0};
- index_priv_t *priv = NULL;
- int ret = -1;
- int op_errno = 0;
- int fd = 0;
+index_entry_create (xlator_t *this, inode_t *inode, char *filename)
+{
+ int fd = 0;
+ int ret = -1;
+ int op_errno = 0;
+ char *subdir = NULL;
+ char pgfid_path[PATH_MAX] = {0};
+ char entry_path[PATH_MAX] = {0};
+ char entry_base_index_path[PATH_MAX] = {0};
+ uuid_t index = {0};
+ struct stat st = {0};
+ index_priv_t *priv = NULL;
+ index_inode_ctx_t *ctx = NULL;
- GF_ASSERT_AND_GOTO_WITH_ERROR (this->name, !gf_uuid_is_null (gfid),
- out, op_errno, EINVAL);
+ priv = this->private;
+
+ GF_ASSERT_AND_GOTO_WITH_ERROR (this->name,
+ !gf_uuid_is_null (inode->gfid), out,
+ op_errno, EINVAL);
GF_ASSERT_AND_GOTO_WITH_ERROR (this->name, filename, out, op_errno,
EINVAL);
- priv = this->private;
- make_gfid_path (priv->index_basepath, ENTRY_CHANGES_SUBDIR, gfid,
- pgfid_path, sizeof (pgfid_path));
+ ret = index_inode_ctx_get (inode, this, &ctx);
+ if (ret) {
+ gf_log (this->name, GF_LOG_ERROR, "Not able to get inode ctx "
+ "for %s", uuid_utoa (inode->gfid));
+ op_errno = ENOMEM;
+ goto out;
+ }
- ret = stat (pgfid_path, &st);
- if (ret != 0) {
- op_errno = errno;
- if (op_errno != ENOENT)
- goto out;
+ make_gfid_path (priv->index_basepath, ENTRY_CHANGES_SUBDIR,
+ inode->gfid, pgfid_path, sizeof (pgfid_path));
+ subdir = index_get_subdir_from_type (ENTRY_CHANGES);
+
+ if (ctx->state[ENTRY_CHANGES] != IN) {
ret = sys_mkdir (pgfid_path, 0600);
if (ret != 0 && errno != EEXIST) {
op_errno = errno;
goto out;
}
+ ctx->state[ENTRY_CHANGES] = IN;
}
op_errno = 0;
@@ -810,22 +825,25 @@ out:
int
index_entry_delete (xlator_t *this, uuid_t pgfid, char *filename)
{
- char entry_base_index_path[PATH_MAX] = {0};
- char pgfid_path[PATH_MAX] = {0};
- char entry_path[PATH_MAX] = {0};
- index_priv_t *priv = NULL;
- int op_errno = 0;
- int ret = 0;
+ int ret = 0;
+ int op_errno = 0;
+ char entry_base_index_path[PATH_MAX] = {0};
+ char pgfid_path[PATH_MAX] = {0};
+ char entry_path[PATH_MAX] = {0};
+ index_priv_t *priv = NULL;
+
+ priv = this->private;
GF_ASSERT_AND_GOTO_WITH_ERROR (this->name, !gf_uuid_is_null (pgfid),
out, op_errno, EINVAL);
GF_ASSERT_AND_GOTO_WITH_ERROR (this->name, filename, out, op_errno,
EINVAL);
- priv = this->private;
+
make_gfid_path (priv->index_basepath, ENTRY_CHANGES_SUBDIR, pgfid,
pgfid_path, sizeof (pgfid_path));
snprintf (entry_path, sizeof(entry_path), "%s/%s", pgfid_path,
filename);
+
ret = sys_unlink (entry_path);
if (ret && (errno != ENOENT)) {
op_errno = errno;
@@ -836,7 +854,6 @@ index_entry_delete (xlator_t *this, uuid_t pgfid, char *filename)
out:
return -op_errno;
-
}
int
@@ -853,7 +870,7 @@ index_entry_action (xlator_t *this, inode_t *inode, dict_t *xdata, char *key)
}
if (strcmp (key, GF_XATTROP_ENTRY_IN_KEY) == 0)
- ret = index_entry_create (this, inode->gfid, filename);
+ ret = index_entry_create (this, inode, filename);
else if (strcmp (key, GF_XATTROP_ENTRY_OUT_KEY) == 0)
ret = index_entry_delete (this, inode->gfid, filename);
@@ -896,6 +913,29 @@ out:
return;
}
+static void
+index_init_state (xlator_t *this, inode_t *inode, index_inode_ctx_t *ctx,
+ char *subdir)
+{
+ int ret = -1;
+ char pgfid_path[PATH_MAX] = {0};
+ struct stat st = {0};
+ index_priv_t *priv = NULL;
+
+ priv = this->private;
+
+ make_gfid_path (priv->index_basepath, subdir, inode->gfid, pgfid_path,
+ sizeof (pgfid_path));
+
+ ret = sys_stat (pgfid_path, &st);
+ if (ret == 0)
+ ctx->state[ENTRY_CHANGES] = IN;
+ else if (ret != 0 && errno == ENOENT)
+ ctx->state[ENTRY_CHANGES] = NOTIN;
+
+ return;
+}
+
void
xattrop_index_action (xlator_t *this, index_local_t *local, dict_t *xattr,
dict_match_t match, void *match_data)
@@ -903,9 +943,11 @@ xattrop_index_action (xlator_t *this, index_local_t *local, dict_t *xattr,
int i = 0;
int ret = 0;
int zfilled[XATTROP_TYPE_END] = {0,};
+ char *subdir = NULL;
dict_t *req_xdata = NULL;
inode_t *inode = NULL;
gf_boolean_t zero_xattr = _gf_true;
+ index_inode_ctx_t *ctx = NULL;
inode = local->inode;
req_xdata = local->xdata;
@@ -918,6 +960,19 @@ xattrop_index_action (xlator_t *this, index_local_t *local, dict_t *xattr,
if (req_xdata)
ret = index_entry_action (this, inode, req_xdata,
GF_XATTROP_ENTRY_OUT_KEY);
+
+ if (zfilled[XATTROP] == 1) {
+ subdir = index_get_subdir_from_type (ENTRY_CHANGES);
+ ret = index_inode_ctx_get (inode, this, &ctx);
+ if (ctx->state[ENTRY_CHANGES] == UNKNOWN)
+ index_init_state (this, inode, ctx, subdir);
+ if (ctx->state[ENTRY_CHANGES] == IN) {
+ ret = index_del (this, inode->gfid, subdir,
+ ENTRY_CHANGES);
+ ctx->state[ENTRY_CHANGES] = NOTIN;
+ }
+ }
+
return;
}