summaryrefslogtreecommitdiffstats
path: root/xlators
diff options
context:
space:
mode:
authorKrutika Dhananjay <kdhananj@redhat.com>2018-10-05 11:32:21 +0530
committerShyamsundar Ranganathan <srangana@redhat.com>2018-10-25 13:11:49 +0000
commit02a05da6989f5cd4283e2e5d62a9cfa6493d65dc (patch)
tree5f36befadd1bac300442086289ac59e5fcdc71b9 /xlators
parentecdc33ada79f155f2bde2860b29872526939e22b (diff)
features/shard: Hold a ref on base inode when adding a shard to lru list
Backport of: > Change-Id: Ic15ca41444dd04684a9458bd4a526b1d3e160499 > Signed-off-by: Krutika Dhananjay <kdhananj@redhat.com> > (cherry picked from commit e627977) > BUG: 1605056 In __shard_update_shards_inode_list(), previously shard translator was not holding a ref on the base inode whenever a shard was added to the lru list. But if the base shard is forgotten and destroyed either by fuse due to memory pressure or due to the file being deleted at some point by a different client with this client still containing stale shards in its lru list, the client would crash at the time of locking lru_base_inode->lock owing to illegal memory access. So now the base shard is ref'd into the inode ctx of every shard that is added to lru list until it gets lru'd out. The patch also handles the case where none of the shards associated with a file that is about to be deleted are part of the LRU list and where an unlink at the beginning of the operation destroys the base inode (because there are no refkeepers) and hence all of the shards that are about to be deleted will be resolved without the existence of a base shard in-memory. This, if not handled properly, could lead to a crash. Change-Id: Ic15ca41444dd04684a9458bd4a526b1d3e160499 updates: bz#1641440 Signed-off-by: Krutika Dhananjay <kdhananj@redhat.com>
Diffstat (limited to 'xlators')
-rw-r--r--xlators/features/shard/src/shard.c48
1 files changed, 34 insertions, 14 deletions
diff --git a/xlators/features/shard/src/shard.c b/xlators/features/shard/src/shard.c
index c2fde028f08..e721526d4bc 100644
--- a/xlators/features/shard/src/shard.c
+++ b/xlators/features/shard/src/shard.c
@@ -650,7 +650,8 @@ out:
inode_t *
__shard_update_shards_inode_list(inode_t *linked_inode, xlator_t *this,
- inode_t *base_inode, int block_num)
+ inode_t *base_inode, int block_num,
+ uuid_t gfid)
{
char block_bname[256] = {
0,
@@ -680,10 +681,13 @@ __shard_update_shards_inode_list(inode_t *linked_inode, xlator_t *this,
inode_ref(linked_inode);
if (base_inode)
gf_uuid_copy(ctx->base_gfid, base_inode->gfid);
+ else
+ gf_uuid_copy(ctx->base_gfid, gfid);
ctx->block_num = block_num;
list_add_tail(&ctx->ilist, &priv->ilist_head);
priv->inode_count++;
- ctx->base_inode = base_inode;
+ if (base_inode)
+ ctx->base_inode = inode_ref(base_inode);
} else {
/*If on the other hand there is no available slot for this inode
* in the list, delete the lru inode from the head of the list,
@@ -701,6 +705,8 @@ __shard_update_shards_inode_list(inode_t *linked_inode, xlator_t *this,
* deleted from fsync list and fsync'd in a new frame,
* and then unlinked in memory and forgotten.
*/
+ if (!lru_base_inode)
+ goto after_fsync_check;
LOCK(&lru_base_inode->lock);
LOCK(&lru_inode->lock);
{
@@ -716,6 +722,7 @@ __shard_update_shards_inode_list(inode_t *linked_inode, xlator_t *this,
UNLOCK(&lru_inode->lock);
UNLOCK(&lru_base_inode->lock);
+ after_fsync_check:
if (!do_fsync) {
shard_make_block_bname(lru_inode_ctx->block_num,
lru_inode_ctx->base_gfid, block_bname,
@@ -728,20 +735,31 @@ __shard_update_shards_inode_list(inode_t *linked_inode, xlator_t *this,
inode_forget(lru_inode, 0);
} else {
fsync_inode = lru_inode;
- inode_unref(lru_base_inode);
+ if (lru_base_inode)
+ inode_unref(lru_base_inode);
}
/* The following unref corresponds to the ref
* held by inode_find() above.
*/
inode_unref(lru_inode);
+
+ /* The following unref corresponds to the ref held on the base shard
+ * at the time of adding shard inode to lru list
+ */
+ if (lru_base_inode)
+ inode_unref(lru_base_inode);
+
/* For as long as an inode is in lru list, we try to
* keep it alive by holding a ref on it.
*/
inode_ref(linked_inode);
if (base_inode)
gf_uuid_copy(ctx->base_gfid, base_inode->gfid);
+ else
+ gf_uuid_copy(ctx->base_gfid, gfid);
ctx->block_num = block_num;
- ctx->base_inode = base_inode;
+ if (base_inode)
+ ctx->base_inode = inode_ref(base_inode);
list_add_tail(&ctx->ilist, &priv->ilist_head);
}
} else {
@@ -1025,7 +1043,7 @@ shard_common_resolve_shards(call_frame_t *frame, xlator_t *this,
LOCK(&priv->lock);
{
fsync_inode = __shard_update_shards_inode_list(
- inode, this, res_inode, shard_idx_iter);
+ inode, this, res_inode, shard_idx_iter, gfid);
}
UNLOCK(&priv->lock);
shard_idx_iter++;
@@ -2167,7 +2185,7 @@ shard_link_block_inode(shard_local_t *local, int block_num, inode_t *inode,
LOCK(&priv->lock);
{
fsync_inode = __shard_update_shards_inode_list(
- linked_inode, this, local->loc.inode, block_num);
+ linked_inode, this, local->loc.inode, block_num, gfid);
}
UNLOCK(&priv->lock);
if (fsync_inode)
@@ -2875,17 +2893,18 @@ shard_unlink_block_inode(shard_local_t *local, int shard_block_num)
shard_inode_ctx_t *ctx = NULL;
shard_inode_ctx_t *base_ictx = NULL;
gf_boolean_t unlink_unref_forget = _gf_false;
+ int unref_base_inode = 0;
this = THIS;
priv = this->private;
inode = local->inode_list[shard_block_num - local->first_block];
- base_inode = local->resolver_base_inode;
+ shard_inode_ctx_get(inode, this, &ctx);
+ base_inode = ctx->base_inode;
if (base_inode)
gf_uuid_copy(gfid, base_inode->gfid);
else
- gf_uuid_copy(gfid, local->base_gfid);
-
+ gf_uuid_copy(gfid, ctx->base_gfid);
shard_make_block_bname(shard_block_num, gfid, block_bname,
sizeof(block_bname));
@@ -2898,17 +2917,16 @@ shard_unlink_block_inode(shard_local_t *local, int shard_block_num)
if (!list_empty(&ctx->ilist)) {
list_del_init(&ctx->ilist);
priv->inode_count--;
+ unref_base_inode++;
GF_ASSERT(priv->inode_count >= 0);
unlink_unref_forget = _gf_true;
}
if (ctx->fsync_needed) {
- if (base_inode)
- inode_unref(base_inode);
+ unref_base_inode++;
list_del_init(&ctx->to_fsync_list);
- if (base_inode) {
+ if (base_inode)
__shard_inode_ctx_get(base_inode, this, &base_ictx);
- base_ictx->fsync_count--;
- }
+ base_ictx->fsync_count--;
}
}
UNLOCK(&inode->lock);
@@ -2919,6 +2937,8 @@ shard_unlink_block_inode(shard_local_t *local, int shard_block_num)
inode_unref(inode);
inode_forget(inode, 0);
}
+ if (base_inode && unref_base_inode)
+ inode_ref_reduce_by_n(base_inode, unref_base_inode);
UNLOCK(&priv->lock);
}