summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--xlators/cluster/ec/src/ec-heal.c1378
1 files changed, 2 insertions, 1376 deletions
diff --git a/xlators/cluster/ec/src/ec-heal.c b/xlators/cluster/ec/src/ec-heal.c
index 7067ed95306..b014df25b94 100644
--- a/xlators/cluster/ec/src/ec-heal.c
+++ b/xlators/cluster/ec/src/ec-heal.c
@@ -84,99 +84,6 @@ ec_sh_key_match (dict_t *dict, char *key, data_t *val, void *mdata)
}
/* FOP: heal */
-void ec_heal_exclude(ec_heal_t * heal, uintptr_t mask)
-{
- LOCK(&heal->lock);
-
- heal->bad &= ~mask;
-
- UNLOCK(&heal->lock);
-}
-
-void ec_heal_lookup_resume(ec_fop_data_t * fop)
-{
- ec_heal_t * heal = fop->data;
- ec_cbk_data_t * cbk;
- uintptr_t good = 0, bad = 0;
-
- if (heal->lookup != NULL)
- {
- ec_fop_data_release(heal->lookup);
- }
- ec_fop_data_acquire(fop);
-
- list_for_each_entry(cbk, &fop->cbk_list, list)
- {
- if ((cbk->op_ret < 0) && (cbk->op_errno == ENOTCONN))
- {
- continue;
- }
-
- if (cbk == fop->answer)
- {
- if (cbk->op_ret >= 0)
- {
- heal->iatt = cbk->iatt[0];
- heal->version[0] = cbk->version[0];
- heal->version[1] = cbk->version[1];
- heal->raw_size = cbk->size;
-
- GF_ASSERT(ec_set_inode_size(fop, cbk->inode, cbk->size));
-
- if (ec_loc_update(heal->xl, &heal->loc, cbk->inode,
- &cbk->iatt[0]) != 0)
- {
- fop->answer = NULL;
- fop->error = EIO;
-
- bad |= cbk->mask;
-
- continue;
- }
- }
-
- good |= cbk->mask;
- }
- else
- {
- bad |= cbk->mask;
- }
- }
-
- /* Heal lookups are not executed concurrently with anything else. So, when
- * a lookup finishes, it's safe to access heal->good and heal->bad without
- * acquiring any lock.
- */
- heal->good = good;
- heal->bad = bad;
-
- heal->lookup = fop;
-
- ec_resume_parent(fop, fop->answer != NULL ? 0 : fop->error);
-}
-
-int32_t ec_heal_entry_lookup_cbk(call_frame_t * frame, void * cookie,
- xlator_t * this, int32_t op_ret,
- int32_t op_errno, inode_t * inode,
- struct iatt * buf, dict_t * xdata,
- struct iatt * postparent)
-{
- ec_heal_lookup_resume(cookie);
-
- return 0;
-}
-
-int32_t ec_heal_inode_lookup_cbk(call_frame_t * frame, void * cookie,
- xlator_t * this, int32_t op_ret,
- int32_t op_errno, inode_t * inode,
- struct iatt * buf, dict_t * xdata,
- struct iatt * postparent)
-{
- ec_heal_lookup_resume(cookie);
-
- return 0;
-}
-
uintptr_t ec_heal_check(ec_fop_data_t * fop, uintptr_t * pgood)
{
ec_cbk_data_t * cbk;
@@ -229,326 +136,6 @@ void ec_heal_avoid(ec_fop_data_t * fop)
UNLOCK(&heal->lock);
}
-int32_t ec_heal_mkdir_cbk(call_frame_t * 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)
-{
- ec_heal_update(cookie, 0);
-
- return 0;
-}
-
-int32_t ec_heal_mknod_cbk(call_frame_t * 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)
-{
- ec_heal_update(cookie, 0);
-
- return 0;
-}
-
-int32_t ec_heal_symlink_cbk(call_frame_t * 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)
-{
- ec_heal_update(cookie, 0);
-
- return 0;
-}
-
-int32_t ec_heal_setattr_cbk(call_frame_t * frame, void * cookie,
- xlator_t * this, int32_t op_ret, int32_t op_errno,
- struct iatt * preop_stbuf,
- struct iatt * postop_stbuf,
- dict_t * xdata)
-{
- ec_heal_update(cookie, 0);
-
- return 0;
-}
-
-int32_t ec_heal_setxattr_cbk(call_frame_t * frame, void * cookie,
- xlator_t * this, int32_t op_ret, int32_t op_errno,
- dict_t * xdata)
-{
- ec_heal_update(cookie, 0);
-
- return 0;
-}
-
-int32_t ec_heal_removexattr_cbk(call_frame_t * frame, void * cookie,
- xlator_t * this, int32_t op_ret,
- int32_t op_errno, dict_t * xdata)
-{
- ec_heal_update(cookie, 0);
-
- return 0;
-}
-
-int32_t ec_heal_target_open_cbk(call_frame_t * frame, void * cookie,
- xlator_t * this, int32_t op_ret,
- int32_t op_errno, fd_t * fd, dict_t * xdata)
-{
- ec_heal_update(cookie, 1);
-
- return 0;
-}
-
-int32_t ec_heal_source_open_cbk(call_frame_t * frame, void * cookie,
- xlator_t * this, int32_t op_ret,
- int32_t op_errno, fd_t * fd, dict_t * xdata)
-{
- ec_heal_avoid(cookie);
-
- return 0;
-}
-
-int32_t ec_heal_reopen_cbk(call_frame_t * frame, void * cookie,
- xlator_t * this, int32_t op_ret, int32_t op_errno,
- fd_t * fd, dict_t * xdata)
-{
- ec_fop_data_t * fop = cookie;
- ec_fd_t * ctx;
- uintptr_t good;
-
- ec_heal_check(fop, &good);
-
- if (good != 0)
- {
- LOCK(&fd->lock);
-
- ctx = __ec_fd_get(fd, fop->xl);
- if (ctx != NULL) {
- ctx->bad &= ~good;
- ctx->open |= good;
- }
-
- UNLOCK(&fd->lock);
- }
-
- return 0;
-}
-
-int32_t ec_heal_create (ec_heal_t *heal, uintptr_t mask)
-{
- dict_t * xdata;
- int error = 0;
-
- xdata = dict_new();
- if (xdata == NULL)
- return ENOMEM;
-
- if (dict_set_static_bin(xdata, "gfid-req", heal->iatt.ia_gfid,
- sizeof(uuid_t))) {
- error = ENOMEM;
- goto out;
- }
-
- switch (heal->iatt.ia_type)
- {
- case IA_IFDIR:
- ec_mkdir(heal->fop->frame, heal->xl, mask, EC_MINIMUM_ONE,
- ec_heal_mkdir_cbk, heal, &heal->loc,
- st_mode_from_ia(heal->iatt.ia_prot, heal->iatt.ia_type),
- 0, xdata);
-
- break;
-
- case IA_IFLNK:
- ec_symlink(heal->fop->frame, heal->xl, mask, EC_MINIMUM_ONE,
- ec_heal_symlink_cbk, heal, heal->symlink, &heal->loc,
- 0, xdata);
-
- break;
-
- default:
- /* 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 with same gfid see that gfid-link file is not
- * present and proceeds with mknods and result in two different
- * files with same gfid. which is yet to be fixed in posix.*/
- if (dict_set_int32 (xdata, GLUSTERFS_INTERNAL_FOP_KEY, 1)) {
- error = ENOMEM;
- goto out;
- }
-
- ec_mknod(heal->fop->frame, heal->xl, mask, EC_MINIMUM_ONE,
- ec_heal_mknod_cbk, heal, &heal->loc,
- st_mode_from_ia(heal->iatt.ia_prot, heal->iatt.ia_type),
- heal->iatt.ia_rdev, 0, xdata);
-
- break;
- }
- error = 0;
-
-out:
- if (xdata)
- dict_unref(xdata);
-
- return error;
-}
-
-int32_t ec_heal_parent_cbk(call_frame_t *frame, void *cookie, xlator_t *xl,
- int32_t op_ret, int32_t op_errno, uintptr_t mask,
- uintptr_t good, uintptr_t bad, dict_t *xdata)
-{
- ec_fop_data_t *fop = cookie;
- ec_heal_t *heal = fop->data;
-
- /* Even if parent self-heal has failed, we try to heal the current entry */
- ec_heal_create(heal, fop->mask);
-
- return 0;
-}
-
-void ec_heal_parent(ec_heal_t *heal, uintptr_t mask)
-{
- loc_t parent;
- int32_t healing = 0;
-
- /* First we try to do a partial heal of the parent directory to avoid
- * ENOENT/ENOTDIR errors caused by missing parents */
- if (ec_loc_parent(heal->xl, &heal->loc, &parent) == 0) {
- if (!__is_root_gfid(parent.gfid)) {
- ec_heal(heal->fop->frame, heal->xl, mask, EC_MINIMUM_ONE,
- ec_heal_parent_cbk, heal, &parent, 1, NULL);
-
- healing = 1;
- }
- loc_wipe(&parent);
- }
-
- if (!healing) {
- ec_heal_create(heal, mask);
- }
-}
-
-void ec_heal_recreate(ec_fop_data_t * fop)
-{
- ec_cbk_data_t * cbk;
- ec_heal_t * heal = fop->data;
- uintptr_t mask = 0;
-
- if (heal->iatt.ia_type == IA_INVAL)
- {
- return;
- }
-
- list_for_each_entry(cbk, &fop->cbk_list, list)
- {
- if ((cbk->op_ret >= 0) || (cbk->op_errno == ENOENT) ||
- (cbk->op_errno == ENOTDIR))
- {
- mask |= cbk->mask;
- }
- }
-
- if (mask != 0)
- {
- ec_heal_parent(heal, mask);
- }
-}
-
-int32_t ec_heal_rmdir_cbk(call_frame_t * frame, void * cookie, xlator_t * this,
- int32_t op_ret, int32_t op_errno,
- struct iatt * preparent, struct iatt * postparent,
- dict_t * xdata)
-{
- ec_heal_update(cookie, 0);
- ec_heal_recreate(cookie);
-
- return 0;
-}
-
-int32_t ec_heal_unlink_cbk(call_frame_t * frame, void * cookie,
- xlator_t * this, int32_t op_ret, int32_t op_errno,
- struct iatt * preparent, struct iatt * postparent,
- dict_t * xdata)
-{
- ec_heal_update(cookie, 0);
- ec_heal_recreate(cookie);
-
- return 0;
-}
-
-int32_t
-ec_heal_init (ec_fop_data_t * fop)
-{
- ec_t * ec = fop->xl->private;
- struct iobuf_pool * pool;
- inode_t * inode;
- ec_inode_t * ctx;
- ec_heal_t * heal = NULL;
- int32_t error = 0;
-
- heal = GF_MALLOC(sizeof(ec_heal_t), ec_mt_ec_heal_t);
- if (heal == NULL)
- {
- return ENOMEM;
- }
-
- memset(heal, 0, sizeof(ec_heal_t));
-
- if (ec_loc_from_loc(fop->xl, &heal->loc, &fop->loc[0]) != 0) {
- error = ENOMEM;
- goto out;
- }
-
- inode = heal->loc.inode;
- if (inode == NULL) {
- gf_msg (fop->xl->name, GF_LOG_WARNING, ENODATA,
- EC_MSG_DATA_UNAVAILABLE, "Unable to start inode healing "
- "because there is not enough information");
-
- error = ENODATA;
- goto out;
- }
-
- LOCK_INIT(&heal->lock);
-
- heal->xl = fop->xl;
- heal->fop = fop;
- pool = fop->xl->ctx->iobuf_pool;
- heal->size = iobpool_default_pagesize(pool) * ec->fragments;
- heal->partial = fop->int32;
- fop->heal = heal;
-
- LOCK(&inode->lock);
-
- ctx = __ec_inode_get(inode, fop->xl);
- if (ctx == NULL)
- {
- error = EIO;
-
- goto unlock;
- }
-
- if (list_empty(&ctx->heal)) {
- gf_msg ("ec", GF_LOG_INFO, 0,
- EC_MSG_HEALING_INFO,
- "Healing '%s', gfid %s", heal->loc.path,
- uuid_utoa(heal->loc.gfid));
- } else {
- ec_sleep(fop);
- }
-
- list_add_tail(&heal->list, &ctx->heal);
- heal = NULL;
-
-unlock:
- UNLOCK(&inode->lock);
-
-out:
- GF_FREE(heal);
-
- return error;
-}
-
int32_t ec_heal_lock_cbk(call_frame_t *frame, void *cookie, xlator_t *this,
int32_t op_ret, int32_t op_errno, dict_t *xdata)
{
@@ -601,21 +188,6 @@ void ec_heal_lock(ec_heal_t *heal, int32_t type, fd_t *fd, loc_t *loc,
}
}
-void ec_heal_entrylk(ec_heal_t *heal, int32_t type)
-{
- loc_t loc;
-
- if (ec_loc_parent(heal->xl, &heal->loc, &loc) != 0) {
- ec_fop_set_error(heal->fop, EIO);
-
- return;
- }
-
- ec_heal_lock(heal, type, NULL, &loc, 0, 0);
-
- loc_wipe(&loc);
-}
-
void ec_heal_inodelk(ec_heal_t *heal, int32_t type, int32_t use_fd,
off_t offset, size_t size)
{
@@ -623,327 +195,6 @@ void ec_heal_inodelk(ec_heal_t *heal, int32_t type, int32_t use_fd,
size);
}
-void ec_heal_lookup(ec_heal_t *heal, uintptr_t mask)
-{
- dict_t * xdata;
- int32_t error = ENOMEM;
-
- xdata = dict_new();
- if (xdata == NULL)
- {
- goto out;
- }
- if (dict_set_uint64(xdata, "list-xattr", 0) != 0)
- {
- goto out;
- }
-
- ec_lookup(heal->fop->frame, heal->xl, mask, EC_MINIMUM_MIN,
- ec_heal_inode_lookup_cbk, heal, &heal->loc, xdata);
-
- error = 0;
-
-out:
- if (xdata != NULL)
- {
- dict_unref(xdata);
- }
-
- ec_fop_set_error(heal->fop, error);
-}
-
-void ec_heal_remove(ec_heal_t * heal, ec_cbk_data_t * cbk)
-{
- if (cbk->iatt[0].ia_type == IA_IFDIR)
- {
- ec_rmdir(heal->fop->frame, heal->xl, cbk->mask, EC_MINIMUM_ONE,
- ec_heal_rmdir_cbk, heal, &heal->loc, 1, NULL);
- }
- else
- {
- ec_unlink(heal->fop->frame, heal->xl, cbk->mask, EC_MINIMUM_ONE,
- ec_heal_unlink_cbk, heal, &heal->loc, 0, NULL);
- }
-}
-
-void ec_heal_remove_others(ec_heal_t * heal)
-{
- struct list_head * item;
- ec_cbk_data_t * cbk;
-
- item = heal->lookup->cbk_list.next;
- do
- {
- item = item->next;
- cbk = list_entry(item, ec_cbk_data_t, list);
-
- if (cbk->op_ret < 0)
- {
- if ((cbk->op_errno != ENOENT) && (cbk->op_errno != ENOTDIR) &&
- (cbk->op_errno != ESTALE))
- {
- gf_msg (heal->xl->name, GF_LOG_WARNING, cbk->op_errno,
- EC_MSG_INODE_REMOVE_FAIL, "Don't know how to "
- "remove inode");
- }
-
- ec_heal_exclude(heal, cbk->mask);
-
- continue;
- }
-
- ec_heal_remove(heal, cbk);
- } while (item->next != &heal->lookup->cbk_list);
-}
-
-void ec_heal_prepare_others(ec_heal_t * heal)
-{
- struct list_head * item;
- ec_cbk_data_t * cbk;
-
- item = heal->lookup->cbk_list.next;
- while (item->next != &heal->lookup->cbk_list)
- {
- item = item->next;
- cbk = list_entry(item, ec_cbk_data_t, list);
-
- if (cbk->op_ret < 0)
- {
- if ((cbk->op_errno == ENOENT) || (cbk->op_errno == ESTALE))
- {
- ec_heal_create(heal, cbk->mask);
- }
- else
- {
- gf_msg (heal->xl->name, GF_LOG_ERROR, cbk->op_errno,
- EC_MSG_HEAL_FAIL, "Don't know how to "
- "heal");
-
- ec_heal_exclude(heal, cbk->mask);
- }
- }
- else
- {
- if ((heal->iatt.ia_type != cbk->iatt[0].ia_type) ||
- (gf_uuid_compare(heal->iatt.ia_gfid, cbk->iatt[0].ia_gfid) != 0))
- {
- ec_heal_remove(heal, cbk);
- }
- }
- }
-}
-
-int32_t ec_heal_readlink_cbk(call_frame_t * frame, void * cookie,
- xlator_t * this, int32_t op_ret, int32_t op_errno,
- const char * path, struct iatt * buf,
- dict_t * xdata)
-{
- ec_fop_data_t * fop = cookie;
- ec_heal_t * heal = fop->data;
-
- if (op_ret >= 0)
- {
- heal->symlink = gf_strdup(path);
- if (heal->symlink != NULL)
- {
- ec_heal_prepare_others(heal);
- }
- else
- {
- ec_fop_set_error(fop, EIO);
- }
- }
-
- return 0;
-}
-
-ec_cbk_data_t * ec_heal_lookup_check(ec_heal_t * heal, uintptr_t * pgood,
- uintptr_t * pbad)
-{
- ec_fop_data_t * fop = heal->lookup;
- ec_cbk_data_t * cbk = NULL, * ans = NULL;
- uintptr_t good = 0, bad = 0;
-
- list_for_each_entry(ans, &fop->cbk_list, list)
- {
- if ((ans->op_ret < 0) && (ans->op_errno == ENOTCONN))
- {
- continue;
- }
-
- if (ans == fop->answer)
- {
- good |= ans->mask;
- cbk = ans;
- }
- else
- {
- bad |= ans->mask;
- }
- }
-
- *pgood = good;
- *pbad = bad;
-
- return cbk;
-}
-
-void ec_heal_prepare(ec_heal_t * heal)
-{
- ec_cbk_data_t * cbk;
- int32_t error = ENOMEM;
-
- heal->available = heal->good;
-
- cbk = heal->lookup->answer;
- if (cbk->op_ret < 0)
- {
- if ((cbk->op_errno == ENOENT) || (cbk->op_errno == ENOTDIR))
- {
- ec_heal_remove_others(heal);
- }
- else
- {
- gf_msg (heal->xl->name, GF_LOG_ERROR, cbk->op_errno,
- EC_MSG_HEAL_FAIL, "Don't know how to heal ");
- }
- }
- else
- {
- if (heal->iatt.ia_type == IA_IFREG)
- {
- heal->fd = fd_create(heal->loc.inode, heal->fop->frame->root->pid);
- if (heal->fd == NULL)
- {
- gf_msg (heal->xl->name, GF_LOG_ERROR, errno,
- EC_MSG_FD_CREATE_FAIL, "Unable to create a new "
- "file descriptor");
-
- goto out;
- }
- }
-
- if (heal->iatt.ia_type == IA_IFLNK)
- {
- ec_readlink(heal->fop->frame, heal->xl, cbk->mask, EC_MINIMUM_ONE,
- ec_heal_readlink_cbk, heal, &heal->loc,
- heal->iatt.ia_size, NULL);
- }
- else
- {
- ec_heal_prepare_others(heal);
- }
- }
-
- error = 0;
-
-out:
- ec_fop_set_error(heal->fop, error);
-}
-
-int32_t ec_heal_open_others(ec_heal_t * heal)
-{
- struct list_head * item;
- ec_cbk_data_t * cbk;
- uintptr_t mask = 0, open = heal->open;
-
- item = heal->lookup->cbk_list.next;
- while (item->next != &heal->lookup->cbk_list)
- {
- item = item->next;
- cbk = list_entry(item, ec_cbk_data_t, list);
-
- if ((cbk->op_ret < 0) || (cbk->iatt[0].ia_type != IA_IFREG) ||
- (gf_uuid_compare(heal->iatt.ia_gfid, cbk->iatt[0].ia_gfid) != 0))
- {
- ec_heal_exclude(heal, cbk->mask);
- }
- else
- {
- mask |= cbk->mask & ~heal->open;
- }
- }
-
- if (mask != 0)
- {
- ec_open(heal->fop->frame, heal->xl, mask, EC_MINIMUM_ONE,
- ec_heal_target_open_cbk, heal, &heal->loc, O_RDWR | O_TRUNC,
- heal->fd, NULL);
-
- open |= mask;
- }
-
- return (open != 0);
-}
-
-uintptr_t ec_heal_needs_data_rebuild(ec_heal_t *heal)
-{
- ec_fop_data_t *fop = heal->lookup;
- ec_cbk_data_t *cbk = NULL;
- uintptr_t bad = 0;
-
- if ((heal->fop->error != 0) || (heal->good == 0) ||
- (heal->iatt.ia_type != IA_IFREG)) {
- return 0;
- }
-
- list_for_each_entry(cbk, &fop->cbk_list, list) {
- if ((cbk->op_ret >= 0) &&
- ((cbk->size != heal->raw_size) ||
- (cbk->version != heal->version))) {
- bad |= cbk->mask;
- }
- }
-
- return bad;
-}
-
-void ec_heal_setxattr_others(ec_heal_t * heal)
-{
- ec_cbk_data_t * cbk;
- dict_t * xdata;
- int32_t error = ENOMEM;
-
- if ((heal->good != 0) && (heal->bad != 0))
- {
- cbk = heal->lookup->answer;
- xdata = cbk->xdata;
-
- if (dict_foreach_match (xdata, ec_ignorable_key_match, NULL,
- dict_remove_foreach_fn, NULL) == -1)
- goto out;
-
- if ((cbk->iatt[0].ia_type == IA_IFREG) ||
- (cbk->iatt[0].ia_type == IA_IFDIR))
- {
- if (ec_dict_set_array(xdata, EC_XATTR_VERSION,
- cbk->version, EC_VERSION_SIZE) != 0)
- {
- goto out;
- }
- if (cbk->iatt[0].ia_type == IA_IFREG)
- {
- uint64_t dirty;
-
- dirty = ec_heal_needs_data_rebuild(heal) != 0;
- if ((ec_dict_set_number(xdata, EC_XATTR_SIZE,
- cbk->iatt[0].ia_size) != 0) ||
- (ec_dict_set_number(xdata, EC_XATTR_DIRTY, dirty) != 0)) {
- goto out;
- }
- }
- }
-
- ec_setxattr(heal->fop->frame, heal->xl, heal->bad, EC_MINIMUM_ONE,
- ec_heal_setxattr_cbk, heal, &heal->loc, xdata, 0, NULL);
- }
-
- error = 0;
-
-out:
- ec_fop_set_error(heal->fop, error);
-}
-
int32_t
ec_heal_xattr_clean (dict_t *dict, char *key, data_t *data,
void *arg)
@@ -961,124 +212,6 @@ ec_heal_xattr_clean (dict_t *dict, char *key, data_t *data,
return 0;
}
-void ec_heal_removexattr_others(ec_heal_t * heal)
-{
- struct list_head * item;
- ec_cbk_data_t * cbk;
- dict_t * xdata;
-
- if ((heal->good == 0) || (heal->bad == 0))
- {
- return;
- }
-
- xdata = heal->lookup->answer->xdata;
- item = heal->lookup->cbk_list.next;
- while (item->next != &heal->lookup->cbk_list)
- {
- item = item->next;
- cbk = list_entry(item, ec_cbk_data_t, list);
-
- if (cbk->op_ret >= 0)
- {
- if (dict_foreach(cbk->xdata, ec_heal_xattr_clean, xdata) == 0)
- {
- ec_removexattr(heal->fop->frame, heal->xl, cbk->mask,
- EC_MINIMUM_ONE, ec_heal_removexattr_cbk, heal,
- &heal->loc, "", cbk->xdata);
- }
- }
- }
-}
-
-void ec_heal_attr(ec_heal_t * heal)
-{
- if ((heal->good != 0) && (heal->bad != 0))
- {
- ec_setattr(heal->fop->frame, heal->xl, heal->bad, EC_MINIMUM_ONE,
- ec_heal_setattr_cbk, heal, &heal->loc, &heal->iatt,
- GF_SET_ATTR_MODE | GF_SET_ATTR_UID | GF_SET_ATTR_GID |
- GF_SET_ATTR_ATIME | GF_SET_ATTR_MTIME, NULL);
- }
-}
-
-void
-ec_heal_open (ec_heal_t * heal)
-{
- heal->bad = ec_heal_needs_data_rebuild(heal);
- if (heal->bad == 0) {
- return;
- }
-
- if (!heal->fd) {
- /* name-less loc heal */
- heal->fd = fd_create (heal->loc.inode,
- heal->fop->frame->root->pid);
- }
-
- if (!heal->fd) {
- ec_fop_set_error(heal->fop, ENOMEM);
- return;
- }
-
- if (ec_heal_open_others(heal))
- {
- ec_open(heal->fop->frame, heal->xl, heal->good, EC_MINIMUM_MIN,
- ec_heal_source_open_cbk, heal, &heal->loc, O_RDONLY, heal->fd,
- NULL);
- }
-}
-
-void ec_heal_reopen_fd(ec_heal_t * heal)
-{
- inode_t * inode;
- fd_t * fd;
- ec_fd_t *ctx_fd;
- ec_inode_t *ctx_inode;
- uintptr_t mask;
- int32_t flags;
-
- inode = heal->loc.inode;
-
- LOCK(&inode->lock);
-
- ctx_inode = __ec_inode_get(inode, heal->xl);
- if (ctx_inode != NULL) {
- ctx_inode->bad &= ~(heal->good | heal->bad);
- }
-
- list_for_each_entry(fd, &inode->fd_list, inode_list)
- {
- ctx_fd = ec_fd_get(fd, heal->xl);
- if (ctx_fd != NULL) {
- mask = heal->bad & ~ctx_fd->open;
- if (mask != 0)
- {
- UNLOCK(&inode->lock);
-
- if (heal->iatt.ia_type == IA_IFDIR)
- {
- ec_opendir(heal->fop->frame, heal->xl, mask,
- EC_MINIMUM_ONE, ec_heal_reopen_cbk, NULL,
- &heal->loc, fd, NULL);
- }
- else
- {
- flags = ctx_fd->flags & ~(O_TRUNC | O_APPEND);
-
- ec_open(heal->fop->frame, heal->xl, mask, EC_MINIMUM_ONE,
- ec_heal_reopen_cbk, NULL, &heal->loc, flags, fd,
- NULL);
- }
-
- LOCK(&inode->lock);
- }
- }
- }
-
- UNLOCK(&inode->lock);
-}
-
int32_t
ec_heal_writev_cbk (call_frame_t *frame, void *cookie,
xlator_t *this, int32_t op_ret, int32_t op_errno,
@@ -1146,515 +279,8 @@ void ec_heal_data_block(ec_heal_t *heal)
}
}
-void ec_heal_update_dirty(ec_heal_t *heal, uintptr_t mask)
-{
- dict_t *dict;
-
- dict = dict_new();
- if (dict == NULL) {
- ec_fop_set_error(heal->fop, EIO);
-
- return;
- }
-
- if (ec_dict_set_number(dict, EC_XATTR_DIRTY, -1) != 0) {
- dict_unref(dict);
- ec_fop_set_error(heal->fop, EIO);
-
- return;
- }
-
- ec_fxattrop(heal->fop->frame, heal->xl, mask, EC_MINIMUM_ONE, NULL, NULL,
- heal->fd, GF_XATTROP_ADD_ARRAY64, dict, NULL);
-
- dict_unref(dict);
-}
-
-void ec_heal_dispatch(ec_heal_t *heal)
-{
- ec_fop_data_t *fop;
- ec_cbk_data_t *cbk;
- inode_t *inode;
- ec_inode_t *ctx;
- ec_heal_t *next = NULL;
- struct list_head list;
- int32_t error;
-
- inode = heal->loc.inode;
-
- INIT_LIST_HEAD(&list);
-
- LOCK(&inode->lock);
-
- /* done == 0 means that self-heal is still running (it shouldn't happen)
- * done == 1 means that self-heal has just completed
- * done == 2 means that self-heal has completed and reported */
- if (heal->done == 1) {
- heal->done = 2;
- list_del_init(&heal->list);
- ctx = __ec_inode_get(inode, heal->xl);
- if (ctx != NULL) {
- ctx->bad &= ~heal->good;
-
- if (heal->partial) {
- /* Collect all partial heal requests. All of them will receive
- * the same answer. 'next' will contain a pointer to the first
- * full request (if any) after this partial heal request.*/
- while (!list_empty(&ctx->heal)) {
- next = list_entry(ctx->heal.next, ec_heal_t, list);
- if (!next->partial) {
- break;
- }
-
- /* Setting 'done' to 2 avoids executing all heal logic and
- * directly reports the result to the caller. */
- next->done = 2;
-
- list_move_tail(&next->list, &list);
- }
- if (list_empty(&ctx->heal)) {
- next = NULL;
- }
- } else {
- /* This is a full heal request, so take all received heal
- * requests to answer them now. */
- list_splice_init(&ctx->heal, &list);
- }
- }
- }
-
- UNLOCK(&inode->lock);
-
- fop = heal->fop;
- error = fop->error;
-
- cbk = ec_cbk_data_allocate(fop->frame, heal->xl, fop, fop->id, 0,
- error == 0 ? 0 : -1, error);
- if (cbk != NULL) {
- cbk->uintptr[0] = heal->available;
- cbk->uintptr[1] = heal->good;
- cbk->uintptr[2] = heal->fixed;
-
- ec_combine(cbk, NULL);
-
- fop->answer = cbk;
- } else if (error == 0) {
- error = ENOMEM;
- }
-
- if (heal->lookup != NULL)
- {
- ec_fop_data_release(heal->lookup);
- }
- if (heal->fd != NULL)
- {
- fd_unref(heal->fd);
- }
- GF_FREE(heal->symlink);
- loc_wipe(&heal->loc);
-
- LOCK_DESTROY(&heal->lock);
-
- GF_FREE(heal);
-
- ec_fop_set_error(fop, error);
-
- /* Resume all pending heal requests, setting the same data obtained by
- * this heal execution. */
- while (!list_empty(&list)) {
- heal = list_entry(list.next, ec_heal_t, list);
- list_del_init(&heal->list);
-
- heal->available = cbk->uintptr[0];
- heal->good = cbk->uintptr[1];
- heal->fixed = cbk->uintptr[2];
-
- ec_resume(heal->fop, error);
- }
-
- /* If there is a pending full request, resume it. */
- if (next != NULL) {
- ec_resume(next->fop, 0);
- }
-}
-
-void ec_wind_heal(ec_t * ec, ec_fop_data_t * fop, int32_t idx)
-{
- ec_cbk_data_t * cbk;
- ec_heal_t *heal = fop->heal;
-
- ec_trace("WIND", fop, "idx=%d", idx);
-
- cbk = ec_cbk_data_allocate(fop->frame, fop->xl, fop, EC_FOP_HEAL, idx,
- fop->error == 0 ? 0 : -1, fop->error);
- if (cbk != NULL)
- {
- cbk->uintptr[0] = heal->available;
- cbk->uintptr[1] = heal->good;
- cbk->uintptr[2] = heal->bad;
-
- ec_combine(cbk, NULL);
- }
-
- ec_complete(fop);
-}
-
-int32_t
-ec_manager_heal (ec_fop_data_t * fop, int32_t state)
-{
- ec_cbk_data_t * cbk;
- ec_heal_t *heal = fop->heal;
-
- switch (state)
- {
- case EC_STATE_INIT:
- ec_owner_set(fop->frame, fop->frame->root);
-
- fop->error = ec_heal_init(fop);
- if (fop->error != 0)
- {
- return EC_STATE_REPORT;
- }
-
- heal = fop->heal;
- /* root loc doesn't have pargfid/parent */
- if (loc_is_root (&heal->loc) ||
- !gf_uuid_is_null(heal->loc.pargfid) || heal->loc.parent) {
- heal->nameheal = _gf_true;
- return EC_STATE_DISPATCH;
- } else {
- /* No need to perform 'name' heal.*/
- return EC_STATE_HEAL_PRE_INODELK_LOCK;
- }
-
- case EC_STATE_DISPATCH:
- if (heal->done != 0) {
- return EC_STATE_HEAL_DISPATCH;
- }
-
- ec_heal_entrylk(heal, F_WRLCK);
-
- return EC_STATE_HEAL_ENTRY_LOOKUP;
-
- case EC_STATE_HEAL_ENTRY_LOOKUP:
- ec_lookup(fop->frame, heal->xl, fop->mask, EC_MINIMUM_MIN,
- ec_heal_entry_lookup_cbk, heal, &heal->loc, NULL);
-
- return EC_STATE_HEAL_ENTRY_PREPARE;
-
- case EC_STATE_HEAL_ENTRY_PREPARE:
- if (!heal->partial || (heal->iatt.ia_type == IA_IFDIR)) {
- ec_heal_prepare(heal);
- }
-
- if (heal->partial) {
- return EC_STATE_HEAL_UNLOCK_ENTRY;
- }
-
- return EC_STATE_HEAL_PRE_INODELK_LOCK;
-
- case EC_STATE_HEAL_PRE_INODELK_LOCK:
- if (heal->done)
- return EC_STATE_HEAL_DISPATCH;
-
- /* Only heal data/metadata if enough information is supplied. */
- if (gf_uuid_is_null(heal->loc.gfid))
- {
- ec_heal_entrylk(heal, F_UNLCK);
-
- return EC_STATE_HEAL_DISPATCH;
- }
-
- ec_heal_inodelk(heal, F_WRLCK, 0, 0, 0);
-
- return EC_STATE_HEAL_PRE_INODE_LOOKUP;
-
- case EC_STATE_HEAL_PRE_INODE_LOOKUP:
- ec_heal_lookup(heal, heal->fop->mask);
-
- return EC_STATE_HEAL_XATTRIBUTES_REMOVE;
-
- case EC_STATE_HEAL_XATTRIBUTES_REMOVE:
- ec_heal_removexattr_others(heal);
-
- return EC_STATE_HEAL_XATTRIBUTES_SET;
-
- case EC_STATE_HEAL_XATTRIBUTES_SET:
- ec_heal_setxattr_others(heal);
-
- return EC_STATE_HEAL_ATTRIBUTES;
-
- case EC_STATE_HEAL_ATTRIBUTES:
- ec_heal_attr(heal);
-
- return EC_STATE_HEAL_OPEN;
-
- case EC_STATE_HEAL_OPEN:
- ec_heal_open(heal);
-
- return EC_STATE_HEAL_REOPEN_FD;
-
- case EC_STATE_HEAL_REOPEN_FD:
- ec_heal_reopen_fd(heal);
-
- return EC_STATE_HEAL_UNLOCK;
-
- case -EC_STATE_HEAL_XATTRIBUTES_REMOVE:
- case -EC_STATE_HEAL_XATTRIBUTES_SET:
- case -EC_STATE_HEAL_ATTRIBUTES:
- case -EC_STATE_HEAL_OPEN:
- case -EC_STATE_HEAL_REOPEN_FD:
- case -EC_STATE_HEAL_UNLOCK:
- case EC_STATE_HEAL_UNLOCK:
- ec_heal_inodelk(heal, F_UNLCK, 0, 0, 0);
-
- /* Fall through */
-
- case -EC_STATE_HEAL_ENTRY_PREPARE:
- case -EC_STATE_HEAL_PRE_INODELK_LOCK:
- case -EC_STATE_HEAL_PRE_INODE_LOOKUP:
- case -EC_STATE_HEAL_UNLOCK_ENTRY:
- case EC_STATE_HEAL_UNLOCK_ENTRY:
- if (heal->nameheal)
- ec_heal_entrylk(heal, F_UNLCK);
-
- heal->bad = ec_heal_needs_data_rebuild(heal);
- if (heal->bad != 0)
- {
- return EC_STATE_HEAL_DATA_LOCK;
- }
-
- return EC_STATE_HEAL_DISPATCH;
-
- case EC_STATE_HEAL_DATA_LOCK:
- if (heal->done != 0)
- {
- return EC_STATE_HEAL_POST_INODELK_LOCK;
- }
-
- ec_heal_inodelk(heal, F_WRLCK, 1, heal->offset, heal->size);
-
- return EC_STATE_HEAL_DATA_COPY;
-
- case EC_STATE_HEAL_DATA_COPY:
- ec_heal_data_block(heal);
-
- return EC_STATE_HEAL_DATA_UNLOCK;
-
- case -EC_STATE_HEAL_DATA_COPY:
- case -EC_STATE_HEAL_DATA_UNLOCK:
- case EC_STATE_HEAL_DATA_UNLOCK:
- ec_heal_inodelk(heal, F_UNLCK, 1, heal->offset, heal->size);
-
- heal->offset += heal->size;
-
- return EC_STATE_HEAL_DATA_LOCK;
-
- case EC_STATE_HEAL_POST_INODELK_LOCK:
- ec_heal_inodelk(heal, F_WRLCK, 1, 0, 0);
-
- return EC_STATE_HEAL_POST_INODE_LOOKUP;
-
- case EC_STATE_HEAL_POST_INODE_LOOKUP:
- heal->fixed = heal->bad;
- ec_heal_update_dirty(heal, heal->bad);
- ec_heal_lookup(heal, heal->good);
-
- return EC_STATE_HEAL_SETATTR;
-
- case EC_STATE_HEAL_SETATTR:
- ec_setattr(heal->fop->frame, heal->xl, heal->fixed, EC_MINIMUM_ONE,
- ec_heal_setattr_cbk, heal, &heal->loc, &heal->iatt,
- GF_SET_ATTR_MODE | GF_SET_ATTR_UID | GF_SET_ATTR_GID |
- GF_SET_ATTR_ATIME | GF_SET_ATTR_MTIME, NULL);
-
- return EC_STATE_HEAL_POST_INODELK_UNLOCK;
-
- case -EC_STATE_HEAL_SETATTR:
- case -EC_STATE_HEAL_POST_INODELK_UNLOCK:
- case EC_STATE_HEAL_POST_INODELK_UNLOCK:
- ec_heal_inodelk(heal, F_UNLCK, 1, 0, 0);
-
- return EC_STATE_HEAL_DISPATCH;
-
- case -EC_STATE_HEAL_POST_INODELK_LOCK:
- case -EC_STATE_HEAL_POST_INODE_LOOKUP:
- case -EC_STATE_HEAL_ENTRY_LOOKUP:
- case -EC_STATE_HEAL_DATA_LOCK:
- case -EC_STATE_HEAL_DISPATCH:
- case EC_STATE_HEAL_DISPATCH:
- ec_heal_dispatch(heal);
-
- return EC_STATE_PREPARE_ANSWER;
-
- case EC_STATE_PREPARE_ANSWER:
- cbk = fop->answer;
- if (cbk != NULL)
- {
- if (!ec_dict_combine(cbk, EC_COMBINE_XDATA))
- {
- if (cbk->op_ret >= 0)
- {
- cbk->op_ret = -1;
- cbk->op_errno = EIO;
- }
- }
- if (cbk->op_ret < 0)
- {
- ec_fop_set_error(fop, cbk->op_errno);
- }
- }
- else
- {
- ec_fop_set_error(fop, EIO);
- }
-
- return EC_STATE_REPORT;
-
- case EC_STATE_REPORT:
- cbk = fop->answer;
-
- GF_ASSERT(cbk != NULL);
-
- if (fop->id == EC_FOP_HEAL)
- {
- if (fop->cbks.heal != NULL)
- {
- fop->cbks.heal(fop->req_frame, fop, fop->xl, cbk->op_ret,
- cbk->op_errno, cbk->uintptr[0],
- cbk->uintptr[1], cbk->uintptr[2],
- cbk->xdata);
- }
- }
- else
- {
- if (fop->cbks.fheal != NULL)
- {
- fop->cbks.fheal(fop->req_frame, fop, fop->xl, cbk->op_ret,
- cbk->op_errno, cbk->uintptr[0],
- cbk->uintptr[1], cbk->uintptr[2],
- cbk->xdata);
- }
- }
-
- return EC_STATE_END;
-
- case -EC_STATE_INIT:
- case -EC_STATE_DISPATCH:
- case -EC_STATE_PREPARE_ANSWER:
- case -EC_STATE_REPORT:
- GF_ASSERT(fop->error != 0);
-
- if (fop->id == EC_FOP_HEAL)
- {
- if (fop->cbks.heal != NULL)
- {
- fop->cbks.heal(fop->req_frame, fop, fop->xl, -1,
- fop->error, 0, 0, 0, NULL);
- }
- }
- else
- {
- if (fop->cbks.fheal != NULL)
- {
- fop->cbks.fheal(fop->req_frame, fop, fop->xl, -1,
- fop->error, 0, 0, 0, NULL);
- }
- }
-
- return EC_STATE_END;
-
- default:
- gf_msg (fop->xl->name, GF_LOG_ERROR, 0,
- EC_MSG_UNHANDLED_STATE, "Unhandled state %d for %s",
- state, ec_fop_name(fop->id));
-
- return EC_STATE_END;
- }
-}
-
-void ec_heal2(call_frame_t *frame, xlator_t *this, uintptr_t target,
- int32_t minimum, fop_heal_cbk_t func, void *data, loc_t *loc,
- int32_t partial, dict_t *xdata)
-{
- ec_cbk_t callback = { .heal = func };
- ec_fop_data_t * fop = NULL;
- int32_t error = EIO;
-
- gf_msg_trace ("ec", 0, "EC(HEAL) %p", frame);
-
- VALIDATE_OR_GOTO(this, out);
- GF_VALIDATE_OR_GOTO(this->name, this->private, out);
-
- fop = ec_fop_data_allocate(frame, this, EC_FOP_HEAL,
- EC_FLAG_UPDATE_LOC_INODE, target, minimum,
- ec_wind_heal, ec_manager_heal, callback, data);
- if (fop == NULL)
- {
- goto out;
- }
-
- fop->int32 = partial;
-
- if (loc != NULL)
- {
- if (loc_copy(&fop->loc[0], loc) != 0)
- {
- gf_msg (this->name, GF_LOG_ERROR, 0,
- EC_MSG_LOC_COPY_FAIL, "Failed to copy a location.");
-
- goto out;
- }
- }
- if (xdata != NULL)
- {
- fop->xdata = dict_ref(xdata);
- if (fop->xdata == NULL)
- {
- gf_msg (this->name, GF_LOG_ERROR, 0,
- EC_MSG_DICT_REF_FAIL, "Failed to reference a "
- "dictionary.");
-
- goto out;
- }
- }
-
- error = 0;
-
-out:
- if (fop != NULL)
- {
- ec_manager(fop, error);
- }
- else
- {
- func(frame, NULL, this, -1, EIO, 0, 0, 0, NULL);
- }
-}
-
/* FOP: fheal */
-void ec_wind_fheal(ec_t * ec, ec_fop_data_t * fop, int32_t idx)
-{
- ec_cbk_data_t * cbk;
- ec_heal_t *heal = fop->heal;
-
- ec_trace("WIND", fop, "idx=%d", idx);
-
- cbk = ec_cbk_data_allocate(fop->frame, fop->xl, fop, EC_FOP_FHEAL, idx,
- fop->error == 0 ? 0 : -1, fop->error);
- if (cbk != NULL)
- {
- cbk->uintptr[0] = heal->available;
- cbk->uintptr[1] = heal->good;
- cbk->uintptr[2] = heal->bad;
-
- ec_combine(cbk, NULL);
- }
-
- ec_complete(fop);
-}
-
void ec_fheal(call_frame_t * frame, xlator_t * this, uintptr_t target,
int32_t minimum, fop_fheal_cbk_t func, void * data, fd_t * fd,
int32_t partial, dict_t *xdata)
@@ -3123,7 +1749,7 @@ ec_heal_block (call_frame_t *frame, xlator_t *this, uintptr_t target,
fop = ec_fop_data_allocate (frame, this, EC_FOP_HEAL,
EC_FLAG_UPDATE_LOC_INODE, target, minimum,
- ec_wind_heal, ec_manager_heal_block, callback,
+ NULL, ec_manager_heal_block, callback,
heal);
if (fop == NULL)
goto out;
@@ -3713,7 +2339,7 @@ ec_heal (call_frame_t *frame, xlator_t *this, uintptr_t target,
goto fail;
fop = ec_fop_data_allocate (frame, this, EC_FOP_HEAL,
EC_FLAG_UPDATE_LOC_INODE, target, minimum,
- ec_wind_heal, ec_manager_heal, callback, data);
+ NULL, NULL, callback, data);
if (fop == NULL)
goto fail;