From ceac3b4172e7c689941ec3e734eca6c537e69368 Mon Sep 17 00:00:00 2001 From: Krutika Dhananjay Date: Mon, 27 Jun 2016 15:21:26 +0530 Subject: afr, index: Clean up stale directory and file indices in granular entry sh Specifically when a directory tree is removed (rm -rf) while a brick is down, both the directory index and the name indices of the files and subdirs under it will remain. Self-heal will need to pick up these and remove them. Towards this, afr sh will now also crawl indices/entry-changes and call an rmdir on the dir if the directory index is stale. On the brick side, rmdir fop has been implemented for index xl, which would delete the directory index and its contents if present in a synctask. Change-Id: I8b527331c2547e6c141db6c57c14055ad1198a7e BUG: 1331323 Signed-off-by: Krutika Dhananjay Reviewed-on: http://review.gluster.org/14832 Reviewed-by: Ravishankar N Smoke: Gluster Build System NetBSD-regression: NetBSD Build System Reviewed-by: Pranith Kumar Karampuri CentOS-regression: Gluster Build System --- xlators/features/index/src/index.c | 184 ++++++++++++++++++++++++++++++++----- 1 file changed, 163 insertions(+), 21 deletions(-) (limited to 'xlators/features/index/src/index.c') diff --git a/xlators/features/index/src/index.c b/xlators/features/index/src/index.c index cd40f2587b2..4f431648913 100644 --- a/xlators/features/index/src/index.c +++ b/xlators/features/index/src/index.c @@ -13,6 +13,7 @@ #include "syscall.h" #include "syncop.h" #include "common-utils.h" +#include #define XATTROP_SUBDIR "xattrop" #define DIRTY_SUBDIR "dirty" @@ -21,6 +22,7 @@ struct index_syncop_args { inode_t *parent; gf_dirent_t *entries; + char *path; }; static char *index_vgfid_xattrs[XATTROP_TYPE_END] = { @@ -1482,6 +1484,7 @@ index_lookup_wrapper (call_frame_t *frame, xlator_t *this, int ret = 0; int32_t op_errno = EINVAL; int32_t op_ret = -1; + uint64_t val = IA_INVAL; char path[PATH_MAX] = {0}; struct iatt stbuf = {0, }; struct iatt postparent = {0,}; @@ -1509,6 +1512,15 @@ index_lookup_wrapper (call_frame_t *frame, xlator_t *this, make_index_dir_path (priv->index_basepath, subdir, path, sizeof (path)); is_dir = _gf_true; + + if ((xattr_req) && + (dict_get (xattr_req, GF_INDEX_IA_TYPE_GET_REQ))) { + if (0 == strcmp (subdir, + index_get_subdir_from_type(ENTRY_CHANGES))) + val = IA_IFDIR; + else + val = IA_IFREG; + } } else { if (!inode_is_linked (loc->inode)) { inode_unref (iloc.inode); @@ -1524,12 +1536,12 @@ index_lookup_wrapper (call_frame_t *frame, xlator_t *this, ret = sys_lstat (path, &lstatbuf); if (ret) { gf_log (this->name, GF_LOG_DEBUG, "Stat failed on %s dir " - "(%s)", subdir, strerror (errno)); + "(%s)", path, strerror (errno)); op_errno = errno; goto done; } else if (!S_ISDIR (lstatbuf.st_mode) && is_dir) { gf_log (this->name, GF_LOG_DEBUG, "Stat failed on %s dir, " - "not a directory", subdir); + "not a directory", path); op_errno = ENOENT; goto done; } @@ -1539,6 +1551,15 @@ index_lookup_wrapper (call_frame_t *frame, xlator_t *this, goto done; } + if (val != IA_INVAL) { + ret = dict_set_uint64 (xattr, GF_INDEX_IA_TYPE_GET_RSP, val); + if (ret) { + op_ret = -1; + op_errno = -ret; + goto done; + } + } + iatt_from_stat (&stbuf, &lstatbuf); if (is_dir || inode_is_linked (iloc.inode)) loc_gfid (&iloc, stbuf.ia_gfid); @@ -1653,6 +1674,116 @@ done: return 0; } +int +deletion_handler (const char *fpath, const struct stat *sb, int typeflag, + struct FTW *ftwbuf) +{ + int ret = -1; + ia_type_t type = IA_INVAL; + + switch (sb->st_mode & S_IFMT) { + case S_IFREG: + sys_unlink (fpath); + break; + + case S_IFDIR: + sys_rmdir (fpath); + break; + default: + type = ia_type_from_st_mode (sb->st_mode); + gf_log (THIS->name, GF_LOG_WARNING, "%s neither a regular file " + "nor a directory - type:%s", fpath, + gf_inode_type_to_str (type)); + break; + } + return 0; +} + +static int +index_wipe_index_subdir (void *opaque) +{ + struct index_syncop_args *args = opaque; + + nftw (args->path, deletion_handler, 1, FTW_DEPTH | FTW_PHYS); + return 0; +} + +static void +index_get_parent_iatt (struct iatt *parent, char *path, loc_t *loc, + int32_t *op_ret, int32_t *op_errno) +{ + int ret = -1; + struct stat lstatbuf = {0,}; + + ret = sys_lstat (path, &lstatbuf); + if (ret < 0) { + *op_ret = -1; + *op_errno = errno; + return; + } + + iatt_from_stat (parent, &lstatbuf); + gf_uuid_copy (parent->ia_gfid, loc->pargfid); + parent->ia_ino = -1; + + return; +} + +int +index_rmdir_wrapper (call_frame_t *frame, xlator_t *this, loc_t *loc, int flag, + dict_t *xdata) +{ + int ret = 0; + int32_t op_ret = 0; + int32_t op_errno = 0; + char *subdir = NULL; + char index_dir[PATH_MAX] = {0}; + char index_subdir[PATH_MAX] = {0}; + uuid_t gfid = {0}; + struct iatt preparent = {0}; + struct iatt postparent = {0}; + index_priv_t *priv = NULL; + index_xattrop_type_t type = XATTROP_TYPE_UNSET; + struct index_syncop_args args = {0,}; + + priv = this->private; + + type = index_get_type_from_vgfid (priv, loc->pargfid); + subdir = index_get_subdir_from_vgfid (priv, loc->pargfid); + make_index_dir_path (priv->index_basepath, subdir, + index_dir, sizeof (index_dir)); + + index_get_parent_iatt (&preparent, index_dir, loc, &op_ret, &op_errno); + if (op_ret < 0) + goto done; + + gf_uuid_parse (loc->name, gfid); + make_gfid_path (priv->index_basepath, subdir, gfid, index_subdir, + sizeof (index_subdir)); + + if (flag == 0) { + ret = index_del (this, gfid, subdir, type); + if (ret < 0) { + op_ret = -1; + op_errno = -ret; + goto done; + } + } else { + args.path = index_subdir; + ret = synctask_new (this->ctx->env, index_wipe_index_subdir, + NULL, NULL, &args); + } + + index_get_parent_iatt (&postparent, index_dir, loc, &op_ret, &op_errno); + if (op_ret < 0) + goto done; + +done: + INDEX_STACK_UNWIND (rmdir, frame, op_ret, op_errno, &preparent, + &postparent, xdata); + return 0; +} + int index_unlink_wrapper (call_frame_t *frame, xlator_t *this, loc_t *loc, int flag, dict_t *xdata) @@ -1667,7 +1798,6 @@ index_unlink_wrapper (call_frame_t *frame, xlator_t *this, loc_t *loc, int flag, struct iatt postparent = {0}; char index_dir[PATH_MAX] = {0}; char filepath[PATH_MAX] = {0}; - struct stat lstatbuf = {0}; uuid_t gfid = {0}; char *subdir = NULL; @@ -1681,16 +1811,9 @@ index_unlink_wrapper (call_frame_t *frame, xlator_t *this, loc_t *loc, int flag, goto done; } - ret = sys_lstat (index_dir, &lstatbuf); - if (ret < 0) { - op_ret = -1; - op_errno = errno; + index_get_parent_iatt (&preparent, index_dir, loc, &op_ret, &op_errno); + if (op_ret < 0) goto done; - } - - iatt_from_stat (&preparent, &lstatbuf); - gf_uuid_copy (preparent.ia_gfid, loc->pargfid); - preparent.ia_ino = -1; if (type <= XATTROP_TYPE_UNSET) { ret = index_inode_ctx_get (loc->parent, this, &ictx); @@ -1716,16 +1839,9 @@ index_unlink_wrapper (call_frame_t *frame, xlator_t *this, loc_t *loc, int flag, goto done; } - memset (&lstatbuf, 0, sizeof (lstatbuf)); - ret = sys_lstat (index_dir, &lstatbuf); - if (ret < 0) { - op_ret = -1; - op_errno = errno; + index_get_parent_iatt (&postparent, index_dir, loc, &op_ret, &op_errno); + if (op_ret < 0) goto done; - } - iatt_from_stat (&postparent, &lstatbuf); - gf_uuid_copy (postparent.ia_gfid, loc->pargfid); - postparent.ia_ino = -1; done: INDEX_STACK_UNWIND (unlink, frame, op_ret, op_errno, &preparent, &postparent, xdata); @@ -2009,6 +2125,31 @@ out: return 0; } +int +index_rmdir (call_frame_t *frame, xlator_t *this, loc_t *loc, int32_t flags, + dict_t *xdata) +{ + call_stub_t *stub = NULL; + index_priv_t *priv = NULL; + + priv = this->private; + if (!index_is_fop_on_internal_inode (this, loc->parent, NULL)) + goto out; + + stub = fop_rmdir_stub (frame, index_rmdir_wrapper, loc, flags, xdata); + if (!stub) { + STACK_UNWIND_STRICT (rmdir, frame, -1, ENOMEM, NULL, NULL, + NULL); + return 0; + } + worker_enqueue (this, stub); + return 0; +out: + STACK_WIND_TAIL (frame, FIRST_CHILD(this), + FIRST_CHILD(this)->fops->rmdir, loc, flags, xdata); + return 0; +} + int index_make_xattrop_watchlist (xlator_t *this, index_priv_t *priv, char *watchlist, index_xattrop_type_t type) @@ -2333,6 +2474,7 @@ struct xlator_fops fops = { .opendir = index_opendir, .readdir = index_readdir, .unlink = index_unlink, + .rmdir = index_rmdir, .fstat = index_fstat, }; -- cgit