summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--xlators/features/shard/src/shard.c148
-rw-r--r--xlators/features/shard/src/shard.h11
2 files changed, 141 insertions, 18 deletions
diff --git a/xlators/features/shard/src/shard.c b/xlators/features/shard/src/shard.c
index aee6ed3ce45..2c33faf6a5f 100644
--- a/xlators/features/shard/src/shard.c
+++ b/xlators/features/shard/src/shard.c
@@ -63,6 +63,8 @@ __shard_inode_ctx_get (inode_t *inode, xlator_t *this, shard_inode_ctx_t **ctx)
if (!ctx_p)
return ret;
+ INIT_LIST_HEAD (&ctx_p->ilist);
+
ret = __inode_ctx_set (inode, this, (uint64_t *)&ctx_p);
if (ret < 0) {
GF_FREE (ctx_p);
@@ -75,6 +77,20 @@ __shard_inode_ctx_get (inode_t *inode, xlator_t *this, shard_inode_ctx_t **ctx)
}
int
+shard_inode_ctx_get (inode_t *inode, xlator_t *this, shard_inode_ctx_t **ctx)
+{
+ int ret = 0;
+
+ LOCK(&inode->lock);
+ {
+ ret = __shard_inode_ctx_get (inode, this, ctx);
+ }
+ UNLOCK(&inode->lock);
+
+ return ret;
+}
+
+int
__shard_inode_ctx_set (inode_t *inode, xlator_t *this, struct iatt *stbuf,
uint64_t block_size, int32_t valid)
{
@@ -323,17 +339,78 @@ out:
return ret;
}
+void
+__shard_update_shards_inode_list (inode_t *linked_inode, xlator_t *this,
+ inode_t *base_inode, int block_num)
+{
+ char block_bname[256] = {0,};
+ inode_t *lru_inode = NULL;
+ shard_priv_t *priv = NULL;
+ shard_inode_ctx_t *ctx = NULL;
+ shard_inode_ctx_t *lru_inode_ctx = NULL;
+
+ priv = this->private;
+
+ shard_inode_ctx_get (linked_inode, this, &ctx);
+
+ if (list_empty (&ctx->ilist)) {
+ if (priv->inode_count + 1 <= SHARD_MAX_INODES) {
+ /* If this inode was linked here for the first time (indicated
+ * by empty list), and if there is still space in the priv list,
+ * add this ctx to the tail of the list.
+ */
+ gf_uuid_copy (ctx->base_gfid, base_inode->gfid);
+ ctx->block_num = block_num;
+ list_add_tail (&ctx->ilist, &priv->ilist_head);
+ priv->inode_count++;
+ } 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,
+ * unlink it. And in its place add this new inode into the list.
+ */
+ lru_inode_ctx = list_first_entry (&priv->ilist_head,
+ shard_inode_ctx_t,
+ ilist);
+ GF_ASSERT (lru_inode_ctx->block_num > 0);
+ list_del_init (&lru_inode_ctx->ilist);
+ lru_inode = inode_find (linked_inode->table,
+ lru_inode_ctx->stat.ia_gfid);
+ shard_make_block_bname (lru_inode_ctx->block_num,
+ lru_inode_ctx->base_gfid,
+ block_bname,
+ sizeof (block_bname));
+ inode_unlink (lru_inode, priv->dot_shard_inode,
+ block_bname);
+ /* The following unref corresponds to the ref held by
+ * inode_find() above.
+ */
+ inode_forget (lru_inode, 0);
+ inode_unref (lru_inode);
+ gf_uuid_copy (ctx->base_gfid, base_inode->gfid);
+ ctx->block_num = block_num;
+ list_add_tail (&ctx->ilist, &priv->ilist_head);
+ }
+ } else {
+ /* If this is not the first time this inode is being operated on, move
+ * it to the most recently used end of the list.
+ */
+ list_move_tail (&ctx->ilist, &priv->ilist_head);
+ }
+}
+
int
shard_common_resolve_shards (call_frame_t *frame, xlator_t *this,
inode_t *res_inode,
shard_post_resolve_fop_handler_t post_res_handler)
{
- int i = -1;
- uint32_t shard_idx_iter = 0;
- char path[PATH_MAX] = {0,};
- inode_t *inode = NULL;
- shard_local_t *local = NULL;
+ int i = -1;
+ uint32_t shard_idx_iter = 0;
+ char path[PATH_MAX] = {0,};
+ inode_t *inode = NULL;
+ shard_priv_t *priv = NULL;
+ shard_local_t *local = NULL;
+ priv = this->private;
local = frame->local;
shard_idx_iter = local->first_block;
@@ -361,6 +438,14 @@ shard_common_resolve_shards (call_frame_t *frame, xlator_t *this,
* forgotten by the time the fop reaches the actual
* write stage.
*/
+ LOCK(&priv->lock);
+ {
+ __shard_update_shards_inode_list (inode, this,
+ res_inode,
+ shard_idx_iter);
+ }
+ UNLOCK(&priv->lock);
+
continue;
} else {
local->call_count++;
@@ -1266,23 +1351,36 @@ void
shard_link_block_inode (shard_local_t *local, int block_num, inode_t *inode,
struct iatt *buf)
{
+ int list_index = 0;
char block_bname[256] = {0,};
inode_t *linked_inode = NULL;
+ xlator_t *this = NULL;
shard_priv_t *priv = NULL;
- priv = THIS->private;
+ this = THIS;
+ priv = this->private;
shard_make_block_bname (block_num, (local->loc.inode)->gfid,
block_bname, sizeof (block_bname));
+ shard_inode_ctx_set (inode, this, buf, 0, SHARD_LOOKUP_MASK);
linked_inode = inode_link (inode, priv->dot_shard_inode, block_bname,
buf);
inode_lookup (linked_inode);
- local->inode_list[block_num - local->first_block] = linked_inode;
- /* Defer unref'ing the inodes until write is complete to prevent
- * them from getting purged. These inodes are unref'd in the event of
- * a failure or after successful fop completion in shard_local_wipe().
+ list_index = block_num - local->first_block;
+
+ /* Defer unref'ing the inodes until write is complete. These inodes are
+ * unref'd in the event of a failure or after successful fop completion
+ * in shard_local_wipe().
*/
+ local->inode_list[list_index] = linked_inode;
+
+ LOCK(&priv->lock);
+ {
+ __shard_update_shards_inode_list (linked_inode, this,
+ local->loc.inode, block_num);
+ }
+ UNLOCK(&priv->lock);
}
int
@@ -1897,19 +1995,33 @@ shard_unlink_base_file (call_frame_t *frame, xlator_t *this)
void
shard_unlink_block_inode (shard_local_t *local, int shard_block_num)
{
- char block_bname[256] = {0,};
- inode_t *inode = NULL;
- shard_priv_t *priv = NULL;
+ char block_bname[256] = {0,};
+ inode_t *inode = NULL;
+ xlator_t *this = NULL;
+ shard_priv_t *priv = NULL;
+ shard_inode_ctx_t *ctx = NULL;
- priv = THIS->private;
+ this = THIS;
+ priv = this->private;
inode = local->inode_list[shard_block_num - local->first_block];
shard_make_block_bname (shard_block_num, (local->loc.inode)->gfid,
block_bname, sizeof (block_bname));
- inode_unlink (inode, priv->dot_shard_inode, block_bname);
- inode_forget (inode, 0);
+ LOCK(&priv->lock);
+ {
+ shard_inode_ctx_get (inode, this, &ctx);
+ if (!list_empty (&ctx->ilist)) {
+ list_del_init (&ctx->ilist);
+ priv->inode_count--;
+ }
+ GF_ASSERT (priv->inode_count >= 0);
+ inode_unlink (inode, priv->dot_shard_inode, block_bname);
+ inode_forget (inode, 0);
+ }
+ UNLOCK(&priv->lock);
+
}
int
@@ -4259,6 +4371,8 @@ init (xlator_t *this)
gf_uuid_parse (SHARD_ROOT_GFID, priv->dot_shard_gfid);
this->private = priv;
+ LOCK_INIT (&priv->lock);
+ INIT_LIST_HEAD (&priv->ilist_head);
ret = 0;
out:
if (ret) {
@@ -4285,6 +4399,7 @@ fini (xlator_t *this)
goto out;
this->private = NULL;
+ LOCK_DESTROY (&priv->lock);
GF_FREE (priv);
out:
@@ -4320,7 +4435,6 @@ shard_forget (xlator_t *this, inode_t *inode)
ctx = (shard_inode_ctx_t *)ctx_uint;
- /* To-Do: Delete all the shards associated with this inode. */
GF_FREE (ctx);
return 0;
diff --git a/xlators/features/shard/src/shard.h b/xlators/features/shard/src/shard.h
index 69414bfe1b5..b3d9b795957 100644
--- a/xlators/features/shard/src/shard.h
+++ b/xlators/features/shard/src/shard.h
@@ -24,7 +24,7 @@
#define GF_XATTR_SHARD_FILE_SIZE "trusted.glusterfs.shard.file-size"
#define SHARD_ROOT_GFID "be318638-e8a0-4c6d-977d-7a937aa84806"
#define SHARD_INODE_LRU_LIMIT 4096
-
+#define SHARD_MAX_INODES 16384
/**
* Bit masks for the valid flag, which is used while updating ctx
**/
@@ -177,6 +177,9 @@ typedef struct shard_priv {
uint64_t block_size;
uuid_t dot_shard_gfid;
inode_t *dot_shard_inode;
+ gf_lock_t lock;
+ int inode_count;
+ struct list_head ilist_head;
} shard_priv_t;
typedef struct {
@@ -258,6 +261,12 @@ typedef struct shard_inode_ctx {
uint64_t block_size; /* The block size with which this inode is
sharded */
struct iatt stat;
+ /* The following members of inode ctx will be applicable only to the
+ * individual shards' ctx and never the base file ctx.
+ */
+ struct list_head ilist;
+ uuid_t base_gfid;
+ int block_num;
} shard_inode_ctx_t;
#endif /* __SHARD_H__ */