|
|
12a457 |
From 1b8f8135c1037b13691ca55da1ebfad8c5bd4a05 Mon Sep 17 00:00:00 2001
|
|
|
12a457 |
From: vmallika <vmallika@redhat.com>
|
|
|
12a457 |
Date: Wed, 30 Mar 2016 20:16:32 +0530
|
|
|
12a457 |
Subject: [PATCH 54/80] marker: build_ancestry in marker
|
|
|
12a457 |
|
|
|
12a457 |
This is a backport of http://review.gluster.org/13857
|
|
|
12a457 |
|
|
|
12a457 |
* quota-enforcer doesn't execute build_ancestry in the below
|
|
|
12a457 |
code path
|
|
|
12a457 |
1) Special client (PID < 0)
|
|
|
12a457 |
2) unlink
|
|
|
12a457 |
3) rename within the same directory
|
|
|
12a457 |
4) link within the same directory
|
|
|
12a457 |
|
|
|
12a457 |
In these cases, marker accounting can fail as parent not found.
|
|
|
12a457 |
We need to build_ancestry in marker if it doesn't find parent
|
|
|
12a457 |
during update txn
|
|
|
12a457 |
|
|
|
12a457 |
> Change-Id: Idb7a2906500647baa6d183ba859b15e34769029c
|
|
|
12a457 |
> BUG: 1320818
|
|
|
12a457 |
> Signed-off-by: vmallika <vmallika@redhat.com>
|
|
|
12a457 |
> Reviewed-on: http://review.gluster.org/13857
|
|
|
12a457 |
> CentOS-regression: Gluster Build System <jenkins@build.gluster.com>
|
|
|
12a457 |
> Reviewed-by: Raghavendra G <rgowdapp@redhat.com>
|
|
|
12a457 |
> Tested-by: Raghavendra G <rgowdapp@redhat.com>
|
|
|
12a457 |
> NetBSD-regression: NetBSD Build System <jenkins@build.gluster.org>
|
|
|
12a457 |
> Smoke: Gluster Build System <jenkins@build.gluster.com>
|
|
|
12a457 |
|
|
|
12a457 |
Change-Id: I582d0b0e42f8b7a7e52e43f502d6e5c8e97f849e
|
|
|
12a457 |
BUG: 1318170
|
|
|
12a457 |
Signed-off-by: vmallika <vmallika@redhat.com>
|
|
|
12a457 |
Reviewed-on: https://code.engineering.redhat.com/gerrit/71537
|
|
|
12a457 |
Reviewed-by: Raghavendra Gowdappa <rgowdapp@redhat.com>
|
|
|
12a457 |
Tested-by: Raghavendra Gowdappa <rgowdapp@redhat.com>
|
|
|
12a457 |
---
|
|
|
12a457 |
xlators/features/marker/src/marker-quota-helper.c | 8 +-
|
|
|
12a457 |
xlators/features/marker/src/marker-quota.c | 168 ++++++++++++++++++--
|
|
|
12a457 |
xlators/features/quota/src/quota.c | 5 +-
|
|
|
12a457 |
3 files changed, 162 insertions(+), 19 deletions(-)
|
|
|
12a457 |
|
|
|
12a457 |
diff --git a/xlators/features/marker/src/marker-quota-helper.c b/xlators/features/marker/src/marker-quota-helper.c
|
|
|
12a457 |
index c2268bf..82d45ef 100644
|
|
|
12a457 |
--- a/xlators/features/marker/src/marker-quota-helper.c
|
|
|
12a457 |
+++ b/xlators/features/marker/src/marker-quota-helper.c
|
|
|
12a457 |
@@ -73,7 +73,13 @@ mq_inode_loc_fill (const char *parent_gfid, inode_t *inode, loc_t *loc)
|
|
|
12a457 |
|
|
|
12a457 |
this = THIS;
|
|
|
12a457 |
|
|
|
12a457 |
- if ((!inode) || (!loc))
|
|
|
12a457 |
+ if (inode == NULL) {
|
|
|
12a457 |
+ gf_log_callingfn ("marker", GF_LOG_ERROR, "loc fill failed, "
|
|
|
12a457 |
+ "inode is NULL");
|
|
|
12a457 |
+ return ret;
|
|
|
12a457 |
+ }
|
|
|
12a457 |
+
|
|
|
12a457 |
+ if (loc == NULL)
|
|
|
12a457 |
return ret;
|
|
|
12a457 |
|
|
|
12a457 |
if ((inode) && __is_root_gfid (inode->gfid)) {
|
|
|
12a457 |
diff --git a/xlators/features/marker/src/marker-quota.c b/xlators/features/marker/src/marker-quota.c
|
|
|
12a457 |
index 5343a94..d6545da 100644
|
|
|
12a457 |
--- a/xlators/features/marker/src/marker-quota.c
|
|
|
12a457 |
+++ b/xlators/features/marker/src/marker-quota.c
|
|
|
12a457 |
@@ -169,6 +169,109 @@ out:
|
|
|
12a457 |
return -1;
|
|
|
12a457 |
}
|
|
|
12a457 |
|
|
|
12a457 |
+int
|
|
|
12a457 |
+mq_build_ancestry (xlator_t *this, loc_t *loc)
|
|
|
12a457 |
+{
|
|
|
12a457 |
+ int32_t ret = -1;
|
|
|
12a457 |
+ fd_t *fd = NULL;
|
|
|
12a457 |
+ gf_dirent_t entries;
|
|
|
12a457 |
+ gf_dirent_t *entry = NULL;
|
|
|
12a457 |
+ dict_t *xdata = NULL;
|
|
|
12a457 |
+ inode_t *tmp_parent = NULL;
|
|
|
12a457 |
+ inode_t *tmp_inode = NULL;
|
|
|
12a457 |
+ inode_t *linked_inode = NULL;
|
|
|
12a457 |
+ quota_inode_ctx_t *ctx = NULL;
|
|
|
12a457 |
+
|
|
|
12a457 |
+ INIT_LIST_HEAD (&entries.list);
|
|
|
12a457 |
+
|
|
|
12a457 |
+ xdata = dict_new ();
|
|
|
12a457 |
+ if (xdata == NULL) {
|
|
|
12a457 |
+ gf_log (this->name, GF_LOG_ERROR, "dict_new failed");
|
|
|
12a457 |
+ ret = -ENOMEM;
|
|
|
12a457 |
+ goto out;
|
|
|
12a457 |
+ }
|
|
|
12a457 |
+
|
|
|
12a457 |
+ ret = dict_set_int8 (xdata, GET_ANCESTRY_DENTRY_KEY, 1);
|
|
|
12a457 |
+ if (ret < 0)
|
|
|
12a457 |
+ goto out;
|
|
|
12a457 |
+
|
|
|
12a457 |
+ fd = fd_anonymous (loc->inode);
|
|
|
12a457 |
+ if (fd == NULL) {
|
|
|
12a457 |
+ gf_log (this->name, GF_LOG_ERROR, "fd creation failed");
|
|
|
12a457 |
+ ret = -ENOMEM;
|
|
|
12a457 |
+ goto out;
|
|
|
12a457 |
+ }
|
|
|
12a457 |
+
|
|
|
12a457 |
+ fd_bind (fd);
|
|
|
12a457 |
+
|
|
|
12a457 |
+ ret = syncop_readdirp (this, fd, 131072, 0, &entries, xdata, NULL);
|
|
|
12a457 |
+ if (ret < 0) {
|
|
|
12a457 |
+ gf_log (this->name, (-ret == ENOENT || -ret == ESTALE)
|
|
|
12a457 |
+ ? GF_LOG_DEBUG:GF_LOG_ERROR, "readdirp failed "
|
|
|
12a457 |
+ "for %s: %s", loc->path, strerror (-ret));
|
|
|
12a457 |
+ goto out;
|
|
|
12a457 |
+ }
|
|
|
12a457 |
+
|
|
|
12a457 |
+ if (list_empty (&entries.list)) {
|
|
|
12a457 |
+ ret = -1;
|
|
|
12a457 |
+ goto out;
|
|
|
12a457 |
+ }
|
|
|
12a457 |
+
|
|
|
12a457 |
+ list_for_each_entry (entry, &entries.list, list) {
|
|
|
12a457 |
+ if (__is_root_gfid (entry->inode->gfid)) {
|
|
|
12a457 |
+ tmp_parent = NULL;
|
|
|
12a457 |
+ } else {
|
|
|
12a457 |
+ linked_inode = inode_link (entry->inode, tmp_parent,
|
|
|
12a457 |
+ entry->d_name,
|
|
|
12a457 |
+ &entry->d_stat);
|
|
|
12a457 |
+ if (linked_inode) {
|
|
|
12a457 |
+ tmp_inode = entry->inode;
|
|
|
12a457 |
+ entry->inode = linked_inode;
|
|
|
12a457 |
+ inode_unref (tmp_inode);
|
|
|
12a457 |
+ } else {
|
|
|
12a457 |
+ gf_log (this->name, GF_LOG_ERROR,
|
|
|
12a457 |
+ "inode link failed");
|
|
|
12a457 |
+ ret = -EINVAL;
|
|
|
12a457 |
+ goto out;
|
|
|
12a457 |
+ }
|
|
|
12a457 |
+ }
|
|
|
12a457 |
+
|
|
|
12a457 |
+ ctx = mq_inode_ctx_new (entry->inode, this);
|
|
|
12a457 |
+ if (ctx == NULL) {
|
|
|
12a457 |
+ gf_log (this->name, GF_LOG_WARNING, "mq_inode_ctx_new "
|
|
|
12a457 |
+ "failed for %s",
|
|
|
12a457 |
+ uuid_utoa (entry->inode->gfid));
|
|
|
12a457 |
+ ret = -ENOMEM;
|
|
|
12a457 |
+ goto out;
|
|
|
12a457 |
+ }
|
|
|
12a457 |
+
|
|
|
12a457 |
+ tmp_parent = entry->inode;
|
|
|
12a457 |
+ }
|
|
|
12a457 |
+
|
|
|
12a457 |
+ if (loc->parent)
|
|
|
12a457 |
+ inode_unref (loc->parent);
|
|
|
12a457 |
+
|
|
|
12a457 |
+ loc->parent = inode_parent (loc->inode, 0, NULL);
|
|
|
12a457 |
+ if (loc->parent == NULL) {
|
|
|
12a457 |
+ ret = -1;
|
|
|
12a457 |
+ goto out;
|
|
|
12a457 |
+ }
|
|
|
12a457 |
+
|
|
|
12a457 |
+ ret = 0;
|
|
|
12a457 |
+
|
|
|
12a457 |
+out:
|
|
|
12a457 |
+ gf_dirent_free (&entries);
|
|
|
12a457 |
+
|
|
|
12a457 |
+ if (fd)
|
|
|
12a457 |
+ fd_unref (fd);
|
|
|
12a457 |
+
|
|
|
12a457 |
+ if (xdata)
|
|
|
12a457 |
+ dict_unref (xdata);
|
|
|
12a457 |
+
|
|
|
12a457 |
+ return ret;
|
|
|
12a457 |
+}
|
|
|
12a457 |
+
|
|
|
12a457 |
+
|
|
|
12a457 |
/* This function should be used only in inspect_directory and inspect_file
|
|
|
12a457 |
* function to heal quota xattrs.
|
|
|
12a457 |
* Inode quota feature is introduced in 3.7.
|
|
|
12a457 |
@@ -1030,13 +1133,8 @@ mq_prevalidate_txn (xlator_t *this, loc_t *origin_loc, loc_t *loc,
|
|
|
12a457 |
if (gf_uuid_is_null (loc->gfid))
|
|
|
12a457 |
gf_uuid_copy (loc->gfid, loc->inode->gfid);
|
|
|
12a457 |
|
|
|
12a457 |
- if (!loc_is_root(loc) && loc->parent == NULL) {
|
|
|
12a457 |
+ if (!loc_is_root(loc) && loc->parent == NULL)
|
|
|
12a457 |
loc->parent = inode_parent (loc->inode, 0, NULL);
|
|
|
12a457 |
- if (loc->parent == NULL) {
|
|
|
12a457 |
- ret = -1;
|
|
|
12a457 |
- goto out;
|
|
|
12a457 |
- }
|
|
|
12a457 |
- }
|
|
|
12a457 |
|
|
|
12a457 |
ret = mq_inode_ctx_get (loc->inode, this, &ctxtmp);
|
|
|
12a457 |
if (ret < 0) {
|
|
|
12a457 |
@@ -1133,7 +1231,7 @@ _mq_create_xattrs_txn (xlator_t *this, loc_t *origin_loc, struct iatt *buf,
|
|
|
12a457 |
if (ret < 0 || status == _gf_true)
|
|
|
12a457 |
goto out;
|
|
|
12a457 |
|
|
|
12a457 |
- if (!loc_is_root(&loc)) {
|
|
|
12a457 |
+ if (!loc_is_root(&loc) && loc.parent) {
|
|
|
12a457 |
contribution = mq_add_new_contribution_node (this, ctx, &loc;;
|
|
|
12a457 |
if (contribution == NULL) {
|
|
|
12a457 |
gf_log (this->name, GF_LOG_WARNING,
|
|
|
12a457 |
@@ -1211,7 +1309,8 @@ mq_reduce_parent_size_task (void *opaque)
|
|
|
12a457 |
|
|
|
12a457 |
ret = mq_inode_loc_fill (NULL, loc->parent, &parent_loc);
|
|
|
12a457 |
if (ret < 0) {
|
|
|
12a457 |
- gf_log (this->name, GF_LOG_ERROR, "loc fill failed");
|
|
|
12a457 |
+ gf_log (this->name, GF_LOG_ERROR, "parent_loc fill failed for "
|
|
|
12a457 |
+ "child inode %s: ", uuid_utoa (loc->inode->gfid));
|
|
|
12a457 |
goto out;
|
|
|
12a457 |
}
|
|
|
12a457 |
|
|
|
12a457 |
@@ -1290,7 +1389,8 @@ out:
|
|
|
12a457 |
*/
|
|
|
12a457 |
ret = mq_inode_ctx_get (parent_loc.inode, this,
|
|
|
12a457 |
&parent_ctx);
|
|
|
12a457 |
- mq_set_ctx_dirty_status (parent_ctx, _gf_false);
|
|
|
12a457 |
+ if (ret == 0)
|
|
|
12a457 |
+ mq_set_ctx_dirty_status (parent_ctx, _gf_false);
|
|
|
12a457 |
} else {
|
|
|
12a457 |
ret = mq_mark_dirty (this, &parent_loc, 0);
|
|
|
12a457 |
}
|
|
|
12a457 |
@@ -1333,6 +1433,7 @@ mq_reduce_parent_size_txn (xlator_t *this, loc_t *origin_loc,
|
|
|
12a457 |
contri, nlink);
|
|
|
12a457 |
out:
|
|
|
12a457 |
loc_wipe (&loc;;
|
|
|
12a457 |
+
|
|
|
12a457 |
return ret;
|
|
|
12a457 |
}
|
|
|
12a457 |
|
|
|
12a457 |
@@ -1387,7 +1488,7 @@ mq_initiate_quota_task (void *opaque)
|
|
|
12a457 |
* if one is already in progress for same inode
|
|
|
12a457 |
*/
|
|
|
12a457 |
if (status == _gf_true) {
|
|
|
12a457 |
- /* status will alreday set before txn start,
|
|
|
12a457 |
+ /* status will already set before txn start,
|
|
|
12a457 |
* so it should not be set in first
|
|
|
12a457 |
* loop iteration
|
|
|
12a457 |
*/
|
|
|
12a457 |
@@ -1397,9 +1498,28 @@ mq_initiate_quota_task (void *opaque)
|
|
|
12a457 |
goto out;
|
|
|
12a457 |
}
|
|
|
12a457 |
|
|
|
12a457 |
+ if (child_loc.parent == NULL) {
|
|
|
12a457 |
+ ret = mq_build_ancestry (this, &child_loc);
|
|
|
12a457 |
+ if (ret < 0 || child_loc.parent == NULL) {
|
|
|
12a457 |
+ /* If application performs parallel remove
|
|
|
12a457 |
+ * operations on same set of files/directories
|
|
|
12a457 |
+ * then we may get ENOENT/ESTALE
|
|
|
12a457 |
+ */
|
|
|
12a457 |
+ gf_log (this->name,
|
|
|
12a457 |
+ (-ret == ENOENT || -ret == ESTALE)
|
|
|
12a457 |
+ ? GF_LOG_DEBUG:GF_LOG_ERROR,
|
|
|
12a457 |
+ "build ancestry failed for inode %s",
|
|
|
12a457 |
+ uuid_utoa (child_loc.inode->gfid));
|
|
|
12a457 |
+ ret = -1;
|
|
|
12a457 |
+ goto out;
|
|
|
12a457 |
+ }
|
|
|
12a457 |
+ }
|
|
|
12a457 |
+
|
|
|
12a457 |
ret = mq_inode_loc_fill (NULL, child_loc.parent, &parent_loc);
|
|
|
12a457 |
if (ret < 0) {
|
|
|
12a457 |
- gf_log (this->name, GF_LOG_ERROR, "loc fill failed");
|
|
|
12a457 |
+ gf_log (this->name, GF_LOG_ERROR, "parent_loc fill "
|
|
|
12a457 |
+ "failed for child inode %s: ",
|
|
|
12a457 |
+ uuid_utoa (child_loc.inode->gfid));
|
|
|
12a457 |
goto out;
|
|
|
12a457 |
}
|
|
|
12a457 |
|
|
|
12a457 |
@@ -1443,13 +1563,20 @@ mq_initiate_quota_task (void *opaque)
|
|
|
12a457 |
wrong parent as it was holding lock on old parent
|
|
|
12a457 |
so validate parent once the lock is acquired
|
|
|
12a457 |
|
|
|
12a457 |
- For more information on thsi problem, please see
|
|
|
12a457 |
+ For more information on this problem, please see
|
|
|
12a457 |
doc for marker_rename in file marker.c
|
|
|
12a457 |
*/
|
|
|
12a457 |
contri = mq_get_contribution_node (child_loc.parent, ctx);
|
|
|
12a457 |
if (contri == NULL) {
|
|
|
12a457 |
tmp_parent = inode_parent (child_loc.inode, 0, NULL);
|
|
|
12a457 |
if (tmp_parent == NULL) {
|
|
|
12a457 |
+ /* This can happen if application performs
|
|
|
12a457 |
+ * parallel remove operations on same set
|
|
|
12a457 |
+ * of files/directories
|
|
|
12a457 |
+ */
|
|
|
12a457 |
+ gf_log (this->name, GF_LOG_WARNING, "parent is "
|
|
|
12a457 |
+ "NULL for inode %s",
|
|
|
12a457 |
+ uuid_utoa (child_loc.inode->gfid));
|
|
|
12a457 |
ret = -1;
|
|
|
12a457 |
goto out;
|
|
|
12a457 |
}
|
|
|
12a457 |
@@ -1481,7 +1608,6 @@ mq_initiate_quota_task (void *opaque)
|
|
|
12a457 |
if (quota_meta_is_null (&delta))
|
|
|
12a457 |
goto out;
|
|
|
12a457 |
|
|
|
12a457 |
- prev_dirty = 0;
|
|
|
12a457 |
ret = mq_get_set_dirty (this, &parent_loc, 1, &prev_dirty);
|
|
|
12a457 |
if (ret < 0)
|
|
|
12a457 |
goto out;
|
|
|
12a457 |
@@ -1502,8 +1628,14 @@ mq_initiate_quota_task (void *opaque)
|
|
|
12a457 |
|
|
|
12a457 |
if (prev_dirty == 0) {
|
|
|
12a457 |
ret = mq_mark_dirty (this, &parent_loc, 0);
|
|
|
12a457 |
- dirty = _gf_false;
|
|
|
12a457 |
+ } else {
|
|
|
12a457 |
+ ret = mq_inode_ctx_get (parent_loc.inode, this,
|
|
|
12a457 |
+ &parent_ctx);
|
|
|
12a457 |
+ if (ret == 0)
|
|
|
12a457 |
+ mq_set_ctx_dirty_status (parent_ctx, _gf_false);
|
|
|
12a457 |
}
|
|
|
12a457 |
+ dirty = _gf_false;
|
|
|
12a457 |
+ prev_dirty = 0;
|
|
|
12a457 |
|
|
|
12a457 |
ret = mq_lock (this, &parent_loc, F_UNLCK);
|
|
|
12a457 |
locked = _gf_false;
|
|
|
12a457 |
@@ -1534,7 +1666,8 @@ out:
|
|
|
12a457 |
*/
|
|
|
12a457 |
ret = mq_inode_ctx_get (parent_loc.inode, this,
|
|
|
12a457 |
&parent_ctx);
|
|
|
12a457 |
- mq_set_ctx_dirty_status (parent_ctx, _gf_false);
|
|
|
12a457 |
+ if (ret == 0)
|
|
|
12a457 |
+ mq_set_ctx_dirty_status (parent_ctx, _gf_false);
|
|
|
12a457 |
} else {
|
|
|
12a457 |
ret = mq_mark_dirty (this, &parent_loc, 0);
|
|
|
12a457 |
}
|
|
|
12a457 |
@@ -1767,7 +1900,8 @@ out:
|
|
|
12a457 |
* can set the status flag and fix the
|
|
|
12a457 |
* dirty directory
|
|
|
12a457 |
*/
|
|
|
12a457 |
- mq_set_ctx_dirty_status (ctx, _gf_false);
|
|
|
12a457 |
+ if (ctx)
|
|
|
12a457 |
+ mq_set_ctx_dirty_status (ctx, _gf_false);
|
|
|
12a457 |
} else if (dirty) {
|
|
|
12a457 |
mq_mark_dirty (this, loc, 0);
|
|
|
12a457 |
}
|
|
|
12a457 |
@@ -1960,7 +2094,7 @@ mq_xattr_state (xlator_t *this, loc_t *origin_loc, dict_t *dict,
|
|
|
12a457 |
inode_contribution_t *contribution = NULL;
|
|
|
12a457 |
|
|
|
12a457 |
ret = mq_prevalidate_txn (this, origin_loc, &loc, &ctx, &buf;;
|
|
|
12a457 |
- if (ret < 0)
|
|
|
12a457 |
+ if (ret < 0 || loc.parent == NULL)
|
|
|
12a457 |
goto out;
|
|
|
12a457 |
|
|
|
12a457 |
if (!loc_is_root(&loc)) {
|
|
|
12a457 |
diff --git a/xlators/features/quota/src/quota.c b/xlators/features/quota/src/quota.c
|
|
|
12a457 |
index aaf9cf8..3dcb021 100644
|
|
|
12a457 |
--- a/xlators/features/quota/src/quota.c
|
|
|
12a457 |
+++ b/xlators/features/quota/src/quota.c
|
|
|
12a457 |
@@ -825,7 +825,10 @@ quota_build_ancestry_cbk (call_frame_t *frame, void *cookie, xlator_t *this,
|
|
|
12a457 |
break;
|
|
|
12a457 |
}
|
|
|
12a457 |
|
|
|
12a457 |
- GF_ASSERT (&entry->list != &entries->list);
|
|
|
12a457 |
+ /* Getting assertion here, need to investigate
|
|
|
12a457 |
+ comment for now
|
|
|
12a457 |
+ GF_ASSERT (&entry->list != &entries->list);
|
|
|
12a457 |
+ */
|
|
|
12a457 |
|
|
|
12a457 |
quota_add_parent (&parents, entry->d_name, parent->gfid);
|
|
|
12a457 |
}
|
|
|
12a457 |
--
|
|
|
12a457 |
1.7.1
|
|
|
12a457 |
|