diff options
| author | Pranith Kumar K <pkarampu@redhat.com> | 2015-02-05 21:23:37 +0530 | 
|---|---|---|
| committer | Vijay Bellur <vbellur@redhat.com> | 2015-02-06 14:04:32 -0800 | 
| commit | 2efb36047aa11838b2cde93a3e95741e7ba40bae (patch) | |
| tree | b5a06756058974d9d390b1781f8c920cf28859d4 /libglusterfs | |
| parent | f75bb4a9ca14b50c7f828ee3fe4ba73dd78f094c (diff) | |
syncop: Provide syncop_ftw and syncop_dir_scan utils
ftw provides file tree walk.
dir_scan does just a readdir not readdirp.
Also changed Afr's self-heal-daemon's crawling functions to use this.
These utils will be used by ec in future to do proactive/full healing.
Change-Id: I05715ddb789592c1b79a71e98f1e8cc29aac5c26
BUG: 1177601
Signed-off-by: Pranith Kumar K <pkarampu@redhat.com>
Reviewed-on: http://review.gluster.org/9485
Tested-by: Gluster Build System <jenkins@build.gluster.com>
Reviewed-by: Ravishankar N <ravishankar@redhat.com>
Reviewed-by: Krutika Dhananjay <kdhananj@redhat.com>
Reviewed-by: Vijay Bellur <vbellur@redhat.com>
Diffstat (limited to 'libglusterfs')
| -rw-r--r-- | libglusterfs/src/gf-dirent.c | 32 | ||||
| -rw-r--r-- | libglusterfs/src/gf-dirent.h | 2 | ||||
| -rw-r--r-- | libglusterfs/src/syncop.c | 166 | ||||
| -rw-r--r-- | libglusterfs/src/syncop.h | 12 | 
4 files changed, 200 insertions, 12 deletions
diff --git a/libglusterfs/src/gf-dirent.c b/libglusterfs/src/gf-dirent.c index 3b42a0813d5..f6fd3ab54ee 100644 --- a/libglusterfs/src/gf-dirent.c +++ b/libglusterfs/src/gf-dirent.c @@ -67,6 +67,25 @@ gf_dirent_free (gf_dirent_t *entries)          }  } +void +gf_link_inode_from_dirent (xlator_t *this, inode_t *parent, gf_dirent_t *entry) +{ +        inode_t     *link_inode = NULL; +        inode_t     *tmp        = NULL; + +        if (!entry->inode) +                return; +        link_inode = inode_link (entry->inode, parent, +                                 entry->d_name, &entry->d_stat); +        if (!link_inode) +                return; + +        inode_lookup (link_inode); +        tmp = entry->inode; +        entry->inode = link_inode; +        inode_unref (tmp); +} +  /* TODO: Currently, with this function, we will be breaking the     policy of 1-1 mapping of kernel nlookup refs with our inode_t's     nlookup count. @@ -77,20 +96,9 @@ gf_link_inodes_from_dirent (xlator_t *this, inode_t *parent,                              gf_dirent_t *entries)  {          gf_dirent_t *entry      = NULL; -        inode_t     *link_inode = NULL; -        inode_t     *tmp        = NULL;          list_for_each_entry (entry, &entries->list, list) { -                if (entry->inode) { -                        link_inode = inode_link (entry->inode, parent, -                                                 entry->d_name, &entry->d_stat); -			if (!link_inode) -				continue; -                        inode_lookup (link_inode); -                        tmp = entry->inode; -                        entry->inode = link_inode; -                        inode_unref (tmp); -                } +                gf_link_inode_from_dirent (this, parent, entry);          }          return 0; diff --git a/libglusterfs/src/gf-dirent.h b/libglusterfs/src/gf-dirent.h index 588d522dbcf..4c1ff0b1684 100644 --- a/libglusterfs/src/gf-dirent.h +++ b/libglusterfs/src/gf-dirent.h @@ -55,4 +55,6 @@ void gf_dirent_free (gf_dirent_t *entries);  int gf_link_inodes_from_dirent (xlator_t *this, inode_t *parent,                                  gf_dirent_t *entries); +void +gf_link_inode_from_dirent (xlator_t *this, inode_t *parent, gf_dirent_t *entry);  #endif /* _GF_DIRENT_H */ diff --git a/libglusterfs/src/syncop.c b/libglusterfs/src/syncop.c index c2794732522..56042d6897e 100644 --- a/libglusterfs/src/syncop.c +++ b/libglusterfs/src/syncop.c @@ -2382,3 +2382,169 @@ syncop_inodelk (xlator_t *subvol, const char *volume, loc_t *loc, int32_t cmd,          return args.op_ret;  } + +int +syncop_dirfd (xlator_t *subvol, loc_t *loc, fd_t **fd, int pid) +{ +        int  ret    = 0; +        fd_t *dirfd = NULL; + +        if (!fd) +                return -EINVAL; + +        dirfd = fd_create (loc->inode, pid); +        if (!dirfd) { +                gf_log (subvol->name, GF_LOG_ERROR, +                        "fd_create of %s failed: %s", +                        uuid_utoa (loc->gfid), strerror(errno)); +                ret = -errno; +                goto out; +        } + +        ret = syncop_opendir (subvol, loc, dirfd); +        if (ret) { +        /* +         * On Linux, if the brick was not updated, opendir will +         * fail. We therefore use backward compatible code +         * that violate the standards by reusing offsets +         * in seekdir() from different DIR *, but it works on Linux. +         * +         * On other systems it never worked, hence we do not need +         * to provide backward-compatibility. +         */ +#ifdef GF_LINUX_HOST_OS +                fd_unref (dirfd); +                dirfd = fd_anonymous (loc->inode); +                if (!dirfd) { +                        gf_log(subvol->name, GF_LOG_ERROR, +                               "fd_anonymous of %s failed: %s", +                               uuid_utoa (loc->gfid), strerror(errno)); +                        ret = -errno; +                        goto out; +                } +                ret = 0; +#else /* GF_LINUX_HOST_OS */ +                fd_unref (dirfd); +                gf_log (subvol->name, GF_LOG_ERROR, +                        "opendir of %s failed: %s", +                        uuid_utoa (loc->gfid), strerror(errno)); +                goto out; +#endif /* GF_LINUX_HOST_OS */ +        } +out: +        if (ret == 0) +                *fd = dirfd; +        return ret; +} + +int +syncop_ftw (xlator_t *subvol, loc_t *loc, int pid, void *data, +            int (*fn) (xlator_t *subvol, gf_dirent_t *entry, loc_t *parent, +                       void *data)) +{ +        loc_t       child_loc = {0, }; +        fd_t        *fd       = NULL; +        uint64_t    offset    = 0; +        gf_dirent_t *entry    = NULL; +        int         ret       = 0; +        gf_dirent_t entries; + +        ret = syncop_dirfd (subvol, loc, &fd, pid); +        if (ret) +                goto out; + +        INIT_LIST_HEAD (&entries.list); + +        while ((ret = syncop_readdirp (subvol, fd, 131072, offset, 0, +                                       &entries))) { +                if (ret < 0) +                        break; + +                if (ret > 0) { +                        /* If the entries are only '.', and '..' then ret +                         * value will be non-zero. so set it to zero here. */ +                        ret = 0; +                } +                list_for_each_entry (entry, &entries.list, list) { +                        offset = entry->d_off; + +                        if (!strcmp (entry->d_name, ".") || +                            !strcmp (entry->d_name, "..")) +                                continue; + +                        gf_link_inode_from_dirent (NULL, fd->inode, entry); + +                        ret = fn (subvol, entry, loc, data); +                        if (ret) +                                break; + +                        if (entry->d_stat.ia_type == IA_IFDIR) { +                                child_loc.inode = inode_ref (entry->inode); +                                uuid_copy (child_loc.gfid, entry->inode->gfid); +                                ret = syncop_ftw (subvol, &child_loc, +                                                  pid, data, fn); +                                loc_wipe (&child_loc); +                                if (ret) +                                        break; +                        } +                } + +                gf_dirent_free (&entries); +                if (ret) +                        break; +        } + +out: +        if (fd) +                fd_unref (fd); +        return ret; +} + +int +syncop_dir_scan (xlator_t *subvol, loc_t *loc, int pid, void *data, +                 int (*fn) (xlator_t *subvol, gf_dirent_t *entry, loc_t *parent, +                            void *data)) +{ +        fd_t        *fd    = NULL; +        uint64_t    offset = 0; +        gf_dirent_t *entry = NULL; +        int         ret    = 0; +        gf_dirent_t entries; + +        ret = syncop_dirfd (subvol, loc, &fd, pid); +        if (ret) +                goto out; + +        INIT_LIST_HEAD (&entries.list); + +        while ((ret = syncop_readdir  (subvol, fd, 131072, offset, &entries))) { +                if (ret < 0) +                        break; + +                if (ret > 0) { +                        /* If the entries are only '.', and '..' then ret +                         * value will be non-zero. so set it to zero here. */ +                        ret = 0; +                } + +                list_for_each_entry (entry, &entries.list, list) { +                        offset = entry->d_off; + +                        if (!strcmp (entry->d_name, ".") || +                            !strcmp (entry->d_name, "..")) +                                continue; + +                        ret = fn (subvol, entry, loc, data); +                        if (ret) +                                break; +                } +                gf_dirent_free (&entries); +                if (ret) +                        break; +        } + +out: +        if (fd) +                fd_unref (fd); +        return ret; +} diff --git a/libglusterfs/src/syncop.h b/libglusterfs/src/syncop.h index e95dd6fc33d..40ed0e865e3 100644 --- a/libglusterfs/src/syncop.h +++ b/libglusterfs/src/syncop.h @@ -427,4 +427,16 @@ int  syncop_inodelk (xlator_t *subvol, const char *volume, loc_t *loc, int32_t cmd,                  struct gf_flock *lock, dict_t *xdata_req, dict_t **xdata_rsp); +int +syncop_ftw (xlator_t *subvol, loc_t *loc, int pid, void *data, +            int (*fn) (xlator_t *subvol, gf_dirent_t *entry, loc_t *parent, +                       void *data)); + +int +syncop_dir_scan (xlator_t *subvol, loc_t *loc, int pid, void *data, +                 int (*fn) (xlator_t *subvol, gf_dirent_t *entry, loc_t *parent, +                            void *data)); + +int +syncop_dirfd (xlator_t *subvol, loc_t *loc, fd_t **fd, int pid);  #endif /* _SYNCOP_H */  | 
