diff options
author | Pranith Kumar K <pkarampu@redhat.com> | 2015-03-30 13:50:11 +0530 |
---|---|---|
committer | Vijay Bellur <vbellur@redhat.com> | 2015-04-13 11:01:39 +0000 |
commit | 0333ac8abf9d5d1cc95fea80fba098c7d2c4c8c3 (patch) | |
tree | 03a96b524cd25dc07189501665f579ed8d2a7dee | |
parent | fac4ab30f3076ba1147e652bd3ac8288d0d7f8b6 (diff) |
cluster/ec: Entry self-heal fixes
- Directory deletion should always happen with 'rm -rf' flag, otherwise the
call may fail with ENOTEMPTY.
- Instead of doing an explicit 'link' call, perform mknod call with
GLUSTERFS_INTERNAL_FOP_KEY which acts as 'link' if the
gfid already exists.
Change-Id: I8826f92170421db37efb67dfc00afad4ab695907
BUG: 1207085
Signed-off-by: Pranith Kumar K <pkarampu@redhat.com>
Reviewed-on: http://review.gluster.org/10045
Tested-by: NetBSD Build System
Tested-by: Gluster Build System <jenkins@build.gluster.com>
Reviewed-by: Xavier Hernandez <xhernandez@datalab.es>
-rw-r--r-- | xlators/cluster/ec/src/ec-heal.c | 106 |
1 files changed, 27 insertions, 79 deletions
diff --git a/xlators/cluster/ec/src/ec-heal.c b/xlators/cluster/ec/src/ec-heal.c index d82592d666e..b8560005b94 100644 --- a/xlators/cluster/ec/src/ec-heal.c +++ b/xlators/cluster/ec/src/ec-heal.c @@ -222,17 +222,6 @@ int32_t ec_heal_symlink_cbk(call_frame_t * frame, void * cookie, return 0; } -int32_t ec_heal_create_cbk(call_frame_t * frame, void * cookie, - xlator_t * this, int32_t op_ret, int32_t op_errno, - fd_t * fd, inode_t * inode, struct iatt * buf, - struct iatt * preparent, struct iatt * postparent, - dict_t * xdata) -{ - ec_heal_update(cookie, 1); - - 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, @@ -262,34 +251,6 @@ int32_t ec_heal_removexattr_cbk(call_frame_t * frame, void * cookie, return 0; } -int32_t ec_heal_link_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_fop_data_t * fop = cookie; - ec_heal_t * heal = fop->data; - uintptr_t good, bad; - - bad = ec_heal_check(fop, &good); - ec_heal_exclude(heal, good); - - if (bad != 0) - { - fop->error = 0; - - xdata = fop->xdata; - fop = fop->parent; - - ec_create(fop->frame, fop->xl, bad, EC_MINIMUM_ONE, - ec_heal_create_cbk, heal, &heal->loc, 0, - st_mode_from_ia(heal->iatt.ia_prot, IA_INVAL), - 0, heal->fd, xdata); - } - - 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) @@ -334,37 +295,19 @@ int32_t ec_heal_reopen_cbk(call_frame_t * frame, void * cookie, return 0; } -int32_t ec_heal_create(ec_heal_t * heal, uintptr_t mask, int32_t try_link) +int32_t ec_heal_create (ec_heal_t *heal, uintptr_t mask) { - loc_t loc; 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)) != 0) - { - dict_unref(xdata); - - return ENOMEM; - } - - if ((heal->iatt.ia_type == IA_IFREG) && try_link) - { - memset(&loc, 0, sizeof(loc)); - loc.inode = heal->loc.inode; - gf_uuid_copy(loc.gfid, heal->iatt.ia_gfid); - - ec_link(heal->fop->frame, heal->xl, mask, EC_MINIMUM_ONE, - ec_heal_link_cbk, heal, &loc, &heal->loc, xdata); - - dict_unref(xdata); - - return 0; + sizeof(uuid_t))) { + error = ENOMEM; + goto out; } switch (heal->iatt.ia_type) @@ -372,7 +315,7 @@ int32_t ec_heal_create(ec_heal_t * heal, uintptr_t mask, int32_t try_link) 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, IA_INVAL), + st_mode_from_ia(heal->iatt.ia_prot, heal->iatt.ia_type), 0, xdata); break; @@ -384,26 +327,32 @@ int32_t ec_heal_create(ec_heal_t * heal, uintptr_t mask, int32_t try_link) break; - case IA_IFREG: - ec_create(heal->fop->frame, heal->xl, mask, EC_MINIMUM_ONE, - ec_heal_create_cbk, heal, &heal->loc, 0, - st_mode_from_ia(heal->iatt.ia_prot, IA_INVAL), - 0, heal->fd, 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, IA_INVAL), + st_mode_from_ia(heal->iatt.ia_prot, heal->iatt.ia_type), heal->iatt.ia_rdev, 0, xdata); break; } + error = 0; - dict_unref(xdata); +out: + if (xdata) + dict_unref(xdata); - return 0; + return error; } int32_t ec_heal_parent_cbk(call_frame_t *frame, void *cookie, xlator_t *xl, @@ -414,7 +363,7 @@ int32_t ec_heal_parent_cbk(call_frame_t *frame, void *cookie, xlator_t *xl, 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, 0); + ec_heal_create(heal, fop->mask); return 0; } @@ -437,7 +386,7 @@ void ec_heal_parent(ec_heal_t *heal, uintptr_t mask) } if (!healing) { - ec_heal_create(heal, mask, 0); + ec_heal_create(heal, mask); } } @@ -646,9 +595,8 @@ void ec_heal_remove(ec_heal_t * heal, ec_cbk_data_t * cbk) { if (cbk->iatt[0].ia_type == IA_IFDIR) { - // TODO: Remove directory recursively ? ec_rmdir(heal->fop->frame, heal->xl, cbk->mask, EC_MINIMUM_ONE, - ec_heal_rmdir_cbk, heal, &heal->loc, 0, NULL); + ec_heal_rmdir_cbk, heal, &heal->loc, 1, NULL); } else { @@ -703,7 +651,7 @@ void ec_heal_prepare_others(ec_heal_t * heal) { if ((cbk->op_errno == ENOENT) || (cbk->op_errno == ESTALE)) { - ec_heal_create(heal, cbk->mask, 1); + ec_heal_create(heal, cbk->mask); } else { |