diff options
| author | Raghavendra G <rgowdapp@redhat.com> | 2013-09-16 17:50:25 +0530 | 
|---|---|---|
| committer | Anand Avati <avati@redhat.com> | 2013-11-26 10:22:40 -0800 | 
| commit | d6dc8d0e9e2052818c9858f6b073a8bacc3fca88 (patch) | |
| tree | 8226967de497a4ff75c5ba5e509b465322dd5fd5 /xlators/storage | |
| parent | 1d554b179f63a5a56ae447f2a5b0044c49ae2642 (diff) | |
posix: placeholders for GFID to path conversion
what?
=====
    The following is an attempt to generate the paths of a file when
    only its gfid is known.
    To find the path of a directory, the symlink handle to the
    directory maintained in  the ".glusterfs" backend directory is
    read. The symlink handle is generated using the gfid of the
    directory. It (handle) contains the directory's name and parent
    gfid, which are used to recursively construct the absolute path as
    seen by the user from the mount point.
    A similar approach cannot be used for a regular file or a symbolic
    link since its hardlink handle, generated using its gfid, doesn't
    contain its parent gfid and basename. So xattrs are set to store
    the parent gfids and the number of hardlinks to a file or a
    symlink having the same parent gfid.  When an user/application
    requests for the paths of a regular file or a symlink with
    multiple hardlinks, using the parent gfids stored in the xattrs,
    the paths of the parent directories are generated as mentioned
    earlier. The base names of the hardlinks (with the same parent
    gfid) are determined by matching the actual backend inode numbers
    of each entry in the parent directory with that of the hardlink
    handle.
    Xattr is set on a regular file, link, and symbolic link as
    follows, Xattr name : trusted.pgfid.<pargfidstr> Xattr value :
    <number of hardlinks to a regular file/symlink with the same
    parentgfid>
    If a regular file, hard link, symbolic link is created then an
    xattr in the above format is set in the backend.
how to use?
===========
    This functionality can be used through getxattr interface. Two
    keys - glusterfs.ancestry.dentry and glusterfs.ancestry.path - enable
    usage of this functionality. A successful getxattr will have the
    result stored under same keys. Values will be,
    glusterfs.ancestry.dentry:
    --------------------------
    A linked list of gf-dirent structures for all possible paths from
    root to this gfid. If there are multiple paths, the linked-list
    will be a series of paths one after another. Each path will be a
    series of dentries representing all components of the path. This
    key is primarily for internal usage within glusterfs.
    glusterfs.ancestry.path:
    ------------------------
    A string containing all possible paths from root to this gfid.
    Multiple hardlinks of a file or a symlink are displayed as a colon
    seperated list (this could interfere with path components
    containing ':').
    e.g. If there is a file "file1" in root directory with two hardlinks,
         "/dir2/link2tofile1" and "/dir1/link1tofile1", then
         [root@alpha gfsmntpt]# getfattr -n glusterfs.ancestry.path -e text
          file1
          glusterfs.ancestry.path="/file1:/dir2/link2tofile1:/dir1/link1tofile1"
    Thanks Amar, Avati and Venky for the inputs.
Original Author: Ramana Raja <rraja@redhat.com>
BUG: 990028
Signed-off-by: Raghavendra G <rgowdapp@redhat.com>
Change-Id: I0eaa9101e333e0c1f66ccefd9e95944dd4a27497
Reviewed-on: http://review.gluster.org/5951
Tested-by: Gluster Build System <jenkins@build.gluster.com>
Reviewed-by: Anand Avati <avati@redhat.com>
Diffstat (limited to 'xlators/storage')
| -rw-r--r-- | xlators/storage/posix/src/posix-handle.c | 162 | ||||
| -rw-r--r-- | xlators/storage/posix/src/posix-handle.h | 96 | ||||
| -rw-r--r-- | xlators/storage/posix/src/posix-helpers.c | 87 | ||||
| -rw-r--r-- | xlators/storage/posix/src/posix.c | 759 | ||||
| -rw-r--r-- | xlators/storage/posix/src/posix.h | 11 | 
5 files changed, 963 insertions, 152 deletions
diff --git a/xlators/storage/posix/src/posix-handle.c b/xlators/storage/posix/src/posix-handle.c index 219a582c9f7..1d8e986314f 100644 --- a/xlators/storage/posix/src/posix-handle.c +++ b/xlators/storage/posix/src/posix-handle.c @@ -26,13 +26,167 @@  #include "xlator.h"  #include "syscall.h" +inode_t * +posix_resolve (xlator_t *this, inode_table_t *itable, inode_t *parent, +               char *bname, struct iatt *iabuf) +{ +        inode_t     *inode = NULL, *linked_inode = NULL; +        int          ret   = -1; + +        ret = posix_istat (this, parent->gfid, bname, iabuf); +        if (ret < 0) +                goto out; + +        inode = inode_find (itable, iabuf->ia_gfid); +        if (inode == NULL) { +                inode = inode_new (itable); +        } + +        linked_inode = inode_link (inode, parent, bname, iabuf); + +        inode_unref (inode); + +out: +        return linked_inode; +} + +int +posix_make_ancestral_node (const char *priv_base_path, char *path, int pathsize, +                           gf_dirent_t *head, +                           char *dir_name, struct iatt *iabuf, inode_t *inode, +                           int type, dict_t *xdata) +{ +        gf_dirent_t *entry           = NULL; +        char real_path[PATH_MAX + 1] = {0, }, len = 0; +        loc_t        loc             = {0, }; +        int          ret             = -1; + +        len = strlen (path) + strlen (dir_name) + 1; +        if (len > pathsize) { +                goto out; +        } + +        strcat (path, dir_name); + +        if (type & POSIX_ANCESTRY_DENTRY) { +                entry = gf_dirent_for_name (dir_name); +                if (!entry) { +                        gf_log (THIS->name, GF_LOG_ERROR, +                                "could not create gf_dirent for entry %s: (%s)", +                                dir_name, strerror (errno)); +                        goto out; +                } + +                entry->d_stat = *iabuf; +                entry->inode = inode_ref (inode); + +                list_add_tail (&entry->list, &head->list); +                strcpy (real_path, priv_base_path); +                strcat (real_path, "/"); +                strcat (real_path, path); +                loc.inode = inode_ref (inode); +                uuid_copy (loc.gfid, inode->gfid); + +                entry->dict = posix_lookup_xattr_fill (THIS, real_path, &loc, +                                                       xdata, iabuf); +                loc_wipe (&loc); +        } + +        ret = 0; + +out: +        return ret; +} + +int +posix_make_ancestryfromgfid (xlator_t *this, char *path, int pathsize, +                             gf_dirent_t *head, int type, uuid_t gfid, +                             const size_t handle_size, +                             const char *priv_base_path, inode_table_t *itable, +                             inode_t **parent, dict_t *xdata) +{ +        char        *linkname   = NULL; /* "../../<gfid[0]>/<gfid[1]/" +                                         "<gfidstr>/<NAME_MAX>" */ +        char        *dir_handle = NULL; +        char        *dir_name   = NULL; +        char        *pgfidstr   = NULL; +        char        *saveptr    = NULL; +        ssize_t       len        = 0; +        inode_t     *inode      = NULL; +        struct iatt  iabuf      = {0, }; +        int          ret        = -1; +        uuid_t       tmp_gfid   = {0, }; + +        if (!path || !parent || !priv_base_path || uuid_is_null (gfid)) { +                goto out; +        } + +        if (__is_root_gfid (gfid)) { +                if (parent) { +                        if (*parent) { +                                inode_unref (*parent); +                        } + +                        *parent = inode_ref (itable->root); +                } + +                inode = itable->root; + +                memset (&iabuf, 0, sizeof (iabuf)); +                uuid_copy (iabuf.ia_gfid, inode->gfid); +                iabuf.ia_type = inode->ia_type; + +                ret = posix_make_ancestral_node (priv_base_path, path, pathsize, +                                                 head, "/", &iabuf, inode, type, +                                                 xdata); +                return ret; +        } + +        dir_handle = alloca (handle_size); +        linkname   = alloca (PATH_MAX); +        snprintf (dir_handle, handle_size, "%s/%s/%02x/%02x/%s", +                  priv_base_path, HANDLE_PFX, gfid[0], gfid[1], +                  uuid_utoa (gfid)); + +        len = readlink (dir_handle, linkname, PATH_MAX); +        if (len < 0) { +                gf_log (this->name, GF_LOG_ERROR, "could not read the link " +                        "from the gfid handle %s (%s)", dir_handle, +                        strerror (errno)); +                goto out; +        } + +        linkname[len] = '\0'; + +        pgfidstr = strtok_r (linkname + SLEN("../../00/00/"), "/", &saveptr); +        dir_name = strtok_r (NULL, "/", &saveptr); +        strcat (dir_name, "/"); -#define HANDLE_PFX ".glusterfs" -#define TRASH_DIR "landfill" +        uuid_parse (pgfidstr, tmp_gfid); + +        ret = posix_make_ancestryfromgfid (this, path, pathsize, head, type, +                                           tmp_gfid, handle_size, +                                           priv_base_path, itable, parent, +                                           xdata); +        if (ret < 0) { +                goto out; +        } -#define UUID0_STR "00000000-0000-0000-0000-000000000000" -#define SLEN(str) (sizeof(str) - 1) +        memset (&iabuf, 0, sizeof (iabuf)); +        inode = posix_resolve (this, itable, *parent, dir_name, &iabuf); + +        ret = posix_make_ancestral_node (priv_base_path, path, pathsize, head, +                                         dir_name, &iabuf, inode, type, xdata); +        if (*parent != NULL) { +                inode_unref (*parent); +        } + +        *parent = inode; + +out: +        return ret; +}  int  posix_handle_relpath (xlator_t *this, uuid_t gfid, const char *basename, diff --git a/xlators/storage/posix/src/posix-handle.h b/xlators/storage/posix/src/posix-handle.h index f1163b72795..8874ca2655f 100644 --- a/xlators/storage/posix/src/posix-handle.h +++ b/xlators/storage/posix/src/posix-handle.h @@ -17,9 +17,86 @@  #include <sys/types.h>  #include "xlator.h" +#include "gf-dirent.h" +#define HANDLE_PFX ".glusterfs" +#define TRASH_DIR "landfill" -#define LOC_HAS_ABSPATH(loc) ((loc) && (loc->path) && (loc->path[0] == '/')) +#define UUID0_STR "00000000-0000-0000-0000-000000000000" +#define SLEN(str) (sizeof(str) - 1) + +#define LOC_HAS_ABSPATH(loc) (loc && (loc->path) && (loc->path[0] == '/')) + +#define MAKE_PGFID_XATTR_KEY(var, prefix, pgfid) do {                   \ +        var = alloca (strlen (prefix) + UUID_CANONICAL_FORM_LEN + 1);   \ +        strcpy (var, prefix);                                           \ +        strcat (var, uuid_utoa (pgfid));                                \ +        } while (0) + +#define SET_PGFID_XATTR(path, key, value, flags, op_ret, this, label) do {    \ +        value = hton32 (value);                                         \ +        op_ret = sys_lsetxattr (path, key, &value, sizeof (value),      \ +                                flags);                                 \ +        if (op_ret == -1) {                                             \ +                op_errno = errno;                                       \ +                gf_log (this->name, GF_LOG_WARNING,                     \ +                        "setting xattr failed on %s: key = %s (%s)",    \ +                        path, key, strerror (op_errno));                \ +                goto label;                                             \ +        }                                                               \ +        } while (0) + + +#define REMOVE_PGFID_XATTR(path, key, op_ret, this, label) do {               \ +       op_ret = sys_lremovexattr (path, key);                           \ +       if (op_ret == -1) {                                              \ +               op_errno = errno;                                        \ +               gf_log (this->name, GF_LOG_WARNING, "removing xattr "    \ +                       "failed on %s: key = %s (%s)", path, key,        \ +                       strerror (op_errno));                            \ +               goto label;                                              \ +       }                                                                \ +       } while (0) + +/* should be invoked holding a lock */ +#define LINK_MODIFY_PGFID_XATTR(path, key, value, flags, op_ret, this, label) do { \ +       op_ret = sys_lgetxattr (path, key, &value, sizeof (value));  \ +       if (op_ret == -1) {                                              \ +               op_errno = errno;                                        \ +               if (op_errno == ENOATTR) {                               \ +                       value = 1;                                       \ +               } else {                                                 \ +                       gf_log (this->name, GF_LOG_WARNING,"getting xattr " \ +                               "failed on %s: key = %s (%s)", path, key, \ +                               strerror (op_errno));                    \ +                       goto label;                                      \ +               }                                                        \ +       } else {                                                         \ +               value = ntoh32 (value);                                  \ +               value++;                                                 \ +       }                                                                \ +       SET_PGFID_XATTR (path, key, value, flags, op_ret, this, label);  \ +       } while (0) + +/* should be invoked holding a lock */ +#define UNLINK_MODIFY_PGFID_XATTR(path, key, value, flags, op_ret, this, label) do { \ +       op_ret = sys_lgetxattr (path, key, &value, sizeof (value));  \ +       if (op_ret == -1) {                                              \ +               op_errno = errno;                                        \ +               gf_log (this->name, GF_LOG_WARNING, "getting xattr failed on " \ +                       "%s: key = %s (%s)", path, key, strerror (op_errno)); \ +               goto label;                                              \ +       } else {                                                         \ +               value = ntoh32 (value);                                  \ +               value--;                                                 \ +               if (value > 0) {                                         \ +                       SET_PGFID_XATTR (path, key, value, flags, op_ret, \ +                                        this, label);                   \ +               } else {                                                 \ +                       REMOVE_PGFID_XATTR (path, key, op_ret, this, label); \ +               }                                                        \ +       }                                                                \ +    } while (0)  #define MAKE_REAL_PATH(var, this, path) do {                            \          var = alloca (strlen (path) + POSIX_BASE_PATH_LEN(this) + 2);   \ @@ -27,7 +104,6 @@          strcpy (&var[POSIX_BASE_PATH_LEN(this)], path);                 \          } while (0) -  #define MAKE_HANDLE_PATH(var, this, gfid, base) do {                    \          int __len;                                                      \          __len = posix_handle_path (this, gfid, base, NULL, 0);          \ @@ -61,12 +137,12 @@  #define MAKE_INODE_HANDLE(rpath, this, loc, iatt_p) do {                \          if (uuid_is_null (loc->gfid)) {                                 \                  gf_log (this->name, GF_LOG_ERROR,                       \ -                        "null gfid for path %s", loc->path);            \ +                        "null gfid for path %s", (loc)->path);          \                  break;                                                  \          }                                                               \          if (LOC_HAS_ABSPATH (loc)) {                                    \ -                MAKE_REAL_PATH (rpath, this, loc->path);                \ -                op_ret = posix_pstat (this, loc->gfid, rpath, iatt_p);  \ +                MAKE_REAL_PATH (rpath, this, (loc)->path);              \ +                op_ret = posix_pstat (this, (loc)->gfid, rpath, iatt_p); \                  break;                                                  \          }                                                               \          errno = 0;                                                      \ @@ -107,10 +183,20 @@          } while (0) +#define POSIX_ANCESTRY_PATH (1 << 0) +#define POSIX_ANCESTRY_DENTRY (1 << 1)  int  posix_handle_path (xlator_t *this, uuid_t gfid, const char *basename, char *buf,                     size_t len); + +int +posix_make_ancestryfromgfid (xlator_t *this, char *path, int pathsize, +                             gf_dirent_t *head, int type, uuid_t gfid, +                             const size_t handle_size, +                             const char *priv_base_path, +                             inode_table_t *table, inode_t **parent, +                             dict_t *xdata);  int  posix_handle_path_safe (xlator_t *this, uuid_t gfid, const char *basename,                          char *buf, size_t len); diff --git a/xlators/storage/posix/src/posix-helpers.c b/xlators/storage/posix/src/posix-helpers.c index e295f8850b4..4db15bf571c 100644 --- a/xlators/storage/posix/src/posix-helpers.c +++ b/xlators/storage/posix/src/posix-helpers.c @@ -102,14 +102,54 @@ out:  }  static int +_posix_xattr_get_set_from_backend (posix_xattr_filler_t *filler, char *key) +{ +        ssize_t  xattr_size = -1; +        int      ret        = 0; +        char    *value      = NULL; + +        xattr_size = sys_lgetxattr (filler->real_path, key, NULL, 0); + +        if (xattr_size > 0) { +                value = GF_CALLOC (1, xattr_size + 1, +                                   gf_posix_mt_char); +                if (!value) +                        goto out; + +                xattr_size = sys_lgetxattr (filler->real_path, key, value, +                                            xattr_size); +                if (xattr_size <= 0) { +                        gf_log (filler->this->name, GF_LOG_WARNING, +                                "getxattr failed. path: %s, key: %s", +                                filler->real_path, key); +                        GF_FREE (value); +                        goto out; +                } + +                value[xattr_size] = '\0'; +                ret = dict_set_bin (filler->xattr, key, +                                    value, xattr_size); +                if (ret < 0) { +                        gf_log (filler->this->name, GF_LOG_DEBUG, +                                "dict set failed. path: %s, key: %s", +                                filler->real_path, key); +                        GF_FREE (value); +                        goto out; +                } +        } +        ret = 0; +out: +        return ret; +} + + +static int  _posix_xattr_get_set (dict_t *xattr_req,                        char *key,                        data_t *data,                        void *xattrargs)  {          posix_xattr_filler_t *filler = xattrargs; -        char     *value      = NULL; -        ssize_t   xattr_size = -1;          int       ret      = -1;          char     *databuf  = NULL;          int       _fd      = -1; @@ -183,35 +223,24 @@ _posix_xattr_get_set (dict_t *xattr_req,                                          "Failed to set dictionary value for %s",                                          key);                  } -        } else { -                xattr_size = sys_lgetxattr (filler->real_path, key, NULL, 0); - -                if (xattr_size > 0) { -                        value = GF_CALLOC (1, xattr_size + 1, -                                           gf_posix_mt_char); -                        if (!value) -                                return -1; - -                        xattr_size = sys_lgetxattr (filler->real_path, key, value, -                                                    xattr_size); -                        if (xattr_size <= 0) { -                                gf_log (filler->this->name, GF_LOG_WARNING, -                                        "getxattr failed. path: %s, key: %s", -                                        filler->real_path, key); -                                GF_FREE (value); -                                return -1; -                        } +        } else if (!strcmp (key, GET_ANCESTRY_PATH_KEY)) { +                char *path = NULL; +                ret = posix_get_ancestry (filler->this, filler->loc->inode, +                                          NULL, &path, POSIX_ANCESTRY_PATH, +                                          &filler->op_errno, xattr_req); +                if (ret < 0) { +                        goto out; +                } -                        value[xattr_size] = '\0'; -                        ret = dict_set_bin (filler->xattr, key, -                                            value, xattr_size); -                        if (ret < 0) { -                                gf_log (filler->this->name, GF_LOG_DEBUG, -                                        "dict set failed. path: %s, key: %s", -                                        filler->real_path, key); -                                GF_FREE (value); -                        } +                ret = dict_set_dynstr (filler->xattr, GET_ANCESTRY_PATH_KEY, +                                       path); +                if (ret < 0) { +                        GF_FREE (path); +                        goto out;                  } + +        } else { +                ret = _posix_xattr_get_set_from_backend (filler, key);          }  out:          return 0; diff --git a/xlators/storage/posix/src/posix.c b/xlators/storage/posix/src/posix.c index 1a344acbb5a..65b52a07cd5 100644 --- a/xlators/storage/posix/src/posix.c +++ b/xlators/storage/posix/src/posix.c @@ -79,7 +79,6 @@ extern char *marker_xattrs[];  #define SET_TO_OLD_FS_ID()  #endif -  int  posix_forget (xlator_t *this, inode_t *inode)  { @@ -105,15 +104,18 @@ posix_lookup (call_frame_t *frame, xlator_t *this,          char *      par_path           = NULL;          struct iatt postparent         = {0,};          int32_t     gfidless           = 0; +        struct  posix_private *priv    = NULL;          VALIDATE_OR_GOTO (frame, out);          VALIDATE_OR_GOTO (this, out);          VALIDATE_OR_GOTO (loc, out); +        priv = this->private; +          /* The Hidden directory should be for housekeeping purpose and it             should not get any gfid on it */ -        if (__is_root_gfid (loc->pargfid) && -            (strcmp (loc->name, GF_HIDDEN_PATH) == 0)) { +        if (__is_root_gfid (loc->pargfid) && loc->name +            && (strcmp (loc->name, GF_HIDDEN_PATH) == 0)) {                  gf_log (this->name, GF_LOG_WARNING,                          "Lookup issued on %s, which is not permitted",                          GF_HIDDEN_PATH); @@ -124,7 +126,7 @@ posix_lookup (call_frame_t *frame, xlator_t *this,          op_ret = dict_get_int32 (xdata, GF_GFIDLESS_LOOKUP, &gfidless);          op_ret = -1; -        if (uuid_is_null (loc->pargfid)) { +        if (uuid_is_null (loc->pargfid) || (loc->name == NULL)) {                  /* nameless lookup */                  MAKE_INODE_HANDLE (real_path, this, loc, &buf);          } else { @@ -1029,18 +1031,20 @@ int  posix_mknod (call_frame_t *frame, xlator_t *this,               loc_t *loc, mode_t mode, dev_t dev, mode_t umask, dict_t *xdata)  { -        int                   tmp_fd      = 0; -        int32_t               op_ret      = -1; -        int32_t               op_errno    = 0; -        char                 *real_path   = 0; -        char                 *par_path    = 0; -        struct iatt           stbuf       = { 0, }; -        char                  was_present = 1; -        struct posix_private *priv        = NULL; -        gid_t                 gid         = 0; -        struct iatt           preparent = {0,}; -        struct iatt           postparent = {0,}; -        void *                uuid_req  = NULL; +        int                   tmp_fd          = 0; +        int32_t               op_ret          = -1; +        int32_t               op_errno        = 0; +        char                 *real_path       = 0; +        char                 *par_path        = 0; +        struct iatt           stbuf           = { 0, }; +        char                  was_present     = 1; +        struct posix_private *priv            = NULL; +        gid_t                 gid             = 0; +        struct iatt           preparent       = {0,}; +        struct iatt           postparent      = {0,}; +        void *                uuid_req        = NULL; +        int32_t               nlink_samepgfid = 0; +        char                 *pgfid_xattr_key = NULL;          DECLARE_OLD_FS_ID_VAR; @@ -1143,6 +1147,16 @@ post_op:                          strerror (errno));          } +        if (priv->update_pgfid_nlinks) { +                MAKE_PGFID_XATTR_KEY (pgfid_xattr_key, PGFID_XATTR_KEY_PREFIX, +                                      loc->pargfid); +                nlink_samepgfid = 1; + +                SET_PGFID_XATTR (real_path, pgfid_xattr_key, nlink_samepgfid, +                                 XATTR_CREATE, op_ret, this, ignore); +        } + +ignore:          op_ret = posix_entry_create_xattr_set (this, real_path, xdata);          if (op_ret) {                  gf_log (this->name, GF_LOG_ERROR, @@ -1271,7 +1285,6 @@ posix_mkdir (call_frame_t *frame, xlator_t *this,                  goto out;          }  #endif -          op_ret = posix_acl_xattr_set (this, real_path, xdata);          if (op_ret) {                  gf_log (this->name, GF_LOG_ERROR, @@ -1325,15 +1338,17 @@ int32_t  posix_unlink (call_frame_t *frame, xlator_t *this,                loc_t *loc, int xflag, dict_t *xdata)  { -        int32_t               op_ret     = -1; -        int32_t               op_errno   = 0; -        char                 *real_path  = NULL; -        char                 *par_path   = NULL; -        int32_t               fd         = -1; -        struct iatt           stbuf      = {0,}; -        struct posix_private *priv       = NULL; -        struct iatt           preparent  = {0,}; -        struct iatt           postparent = {0,}; +        int32_t               op_ret          = -1; +        int32_t               op_errno        = 0; +        char                 *real_path       = NULL; +        char                 *par_path        = NULL; +        int32_t               fd              = -1; +        struct iatt           stbuf           = {0,}; +        struct posix_private *priv            = NULL; +        struct iatt           preparent       = {0,}; +        struct iatt           postparent      = {0,}; +        char                 *pgfid_xattr_key = NULL; +        int32_t               nlink_samepgfid = 0;          DECLARE_OLD_FS_ID_VAR; @@ -1371,6 +1386,26 @@ posix_unlink (call_frame_t *frame, xlator_t *this,                  }          } +        if (priv->update_pgfid_nlinks && (stbuf.ia_nlink > 1)) { +                MAKE_PGFID_XATTR_KEY (pgfid_xattr_key, PGFID_XATTR_KEY_PREFIX, +                                      loc->pargfid); +                LOCK (&loc->inode->lock); +                { +                        UNLINK_MODIFY_PGFID_XATTR (real_path, pgfid_xattr_key, +                                                   nlink_samepgfid, 0, op_ret, +                                                   this, unlock); +                } +        unlock: +                UNLOCK (&loc->inode->lock); + +                if (op_ret < 0) { +                        gf_log (this->name, GF_LOG_WARNING, "modification of " +                                "parent gfid xattr failed (path:%s gfid:%s)", +                                real_path, uuid_utoa (loc->inode->gfid)); +                        goto out; +                } +        } +          op_ret = sys_unlink (real_path);          if (op_ret == -1) {                  op_errno = errno; @@ -1512,16 +1547,18 @@ int  posix_symlink (call_frame_t *frame, xlator_t *this,                 const char *linkname, loc_t *loc, mode_t umask, dict_t *xdata)  { -        int32_t               op_ret      = -1; -        int32_t               op_errno    = 0; -        char *                real_path   = 0; -        char *                par_path   = 0; -        struct iatt           stbuf       = { 0, }; -        struct posix_private *priv        = NULL; -        gid_t                 gid         = 0; -        char                  was_present = 1; -        struct iatt           preparent = {0,}; -        struct iatt           postparent = {0,}; +        int32_t               op_ret          = -1; +        int32_t               op_errno        = 0; +        char *                real_path       = 0; +        char *                par_path        = 0; +        struct iatt           stbuf           = { 0, }; +        struct posix_private *priv            = NULL; +        gid_t                 gid             = 0; +        char                  was_present     = 1; +        struct iatt           preparent       = {0,}; +        struct iatt           postparent      = {0,}; +        char                 *pgfid_xattr_key = NULL; +        int32_t               nlink_samepgfid = 0;          DECLARE_OLD_FS_ID_VAR; @@ -1582,7 +1619,6 @@ posix_symlink (call_frame_t *frame, xlator_t *this,                  goto out;          }  #endif -          op_ret = posix_acl_xattr_set (this, real_path, xdata);          if (op_ret) {                  gf_log (this->name, GF_LOG_ERROR, @@ -1590,6 +1626,14 @@ posix_symlink (call_frame_t *frame, xlator_t *this,                          strerror (errno));          } +        if (priv->update_pgfid_nlinks) { +                MAKE_PGFID_XATTR_KEY (pgfid_xattr_key, PGFID_XATTR_KEY_PREFIX, +                                      loc->pargfid); +                nlink_samepgfid = 1; +                SET_PGFID_XATTR (real_path, pgfid_xattr_key, nlink_samepgfid, +                                 XATTR_CREATE, op_ret, this, ignore); +        } +ignore:          op_ret = posix_entry_create_xattr_set (this, real_path, xdata);          if (op_ret) {                  gf_log (this->name, GF_LOG_ERROR, @@ -1636,24 +1680,26 @@ int  posix_rename (call_frame_t *frame, xlator_t *this,                loc_t *oldloc, loc_t *newloc, dict_t *xdata)  { -        int32_t               op_ret       = -1; -        int32_t               op_errno     = 0; -        char                 *real_oldpath = NULL; -        char                 *real_newpath = NULL; -        char                 *par_oldpath = NULL; -        char                 *par_newpath = NULL; -        struct iatt           stbuf        = {0, }; -        struct posix_private *priv         = NULL; -        char                  was_present  = 1; -        struct iatt           preoldparent  = {0, }; -        struct iatt           postoldparent = {0, }; -        struct iatt           prenewparent  = {0, }; -        struct iatt           postnewparent = {0, }; +        int32_t               op_ret          = -1; +        int32_t               op_errno        = 0; +        char                 *real_oldpath    = NULL; +        char                 *real_newpath    = NULL; +        char                 *par_oldpath     = NULL; +        char                 *par_newpath     = NULL; +        struct iatt           stbuf           = {0, }; +        struct posix_private *priv            = NULL; +        char                  was_present     = 1; +        struct iatt           preoldparent    = {0, }; +        struct iatt           postoldparent   = {0, }; +        struct iatt           prenewparent    = {0, }; +        struct iatt           postnewparent   = {0, };          char                  olddirid[64];          char                  newdirid[64]; -        uuid_t                victim = {0}; -        int                   was_dir = 0; -        int                   nlink = 0; +        uuid_t                victim          = {0}; +        int                   was_dir         = 0; +        int                   nlink           = 0; +        char                 *pgfid_xattr_key = NULL; +        int32_t               nlink_samepgfid = 0;          DECLARE_OLD_FS_ID_VAR; @@ -1718,17 +1764,64 @@ posix_rename (call_frame_t *frame, xlator_t *this,                  goto out;          } -        if (IA_ISDIR (oldloc->inode->ia_type)) { +        if (IA_ISDIR (oldloc->inode->ia_type))                  posix_handle_unset (this, oldloc->inode->gfid, NULL); + +        LOCK (&oldloc->inode->lock); +        { +                if (!IA_ISDIR (oldloc->inode->ia_type) +                    && priv->update_pgfid_nlinks) { +                        MAKE_PGFID_XATTR_KEY (pgfid_xattr_key, +                                              PGFID_XATTR_KEY_PREFIX, +                                              oldloc->pargfid); +                        UNLINK_MODIFY_PGFID_XATTR (real_oldpath, +                                                   pgfid_xattr_key, +                                                   nlink_samepgfid, 0, +                                                   op_ret, +                                                   this, unlock); +                } + +                op_ret = sys_rename (real_oldpath, real_newpath); +                if (op_ret == -1) { +                        op_errno = errno; +                        gf_log (this->name, +                                (op_errno == ENOTEMPTY ? GF_LOG_DEBUG +                                 : GF_LOG_ERROR), +                                "rename of %s to %s failed: %s", +                                real_oldpath, real_newpath, +                                strerror (op_errno)); + +                        if (priv->update_pgfid_nlinks +                            && !IA_ISDIR (oldloc->inode->ia_type)) { +                                LINK_MODIFY_PGFID_XATTR (real_oldpath, +                                                         pgfid_xattr_key, +                                                         nlink_samepgfid, 0, +                                                         op_ret, +                                                         this, unlock); +                        } + +                        goto unlock; +                } + +                if (!IA_ISDIR (oldloc->inode->ia_type) +                    && priv->update_pgfid_nlinks) { +                        MAKE_PGFID_XATTR_KEY (pgfid_xattr_key, +                                              PGFID_XATTR_KEY_PREFIX, +                                              newloc->pargfid); +                        LINK_MODIFY_PGFID_XATTR (real_newpath, +                                                 pgfid_xattr_key, +                                                 nlink_samepgfid, 0, +                                                 op_ret, +                                                 this, unlock); +                }          } +unlock: +        UNLOCK (&oldloc->inode->lock); -        op_ret = sys_rename (real_oldpath, real_newpath); -        if (op_ret == -1) { -                op_errno = errno; -                gf_log (this->name, -                        (op_errno == ENOTEMPTY ? GF_LOG_DEBUG : GF_LOG_ERROR), -                        "rename of %s to %s failed: %s", -                        real_oldpath, real_newpath, strerror (op_errno)); +        if (op_ret < 0) { +                gf_log (this->name, GF_LOG_WARNING, "modification of " +                        "parent gfid xattr failed (gfid:%s)", +                        uuid_utoa (oldloc->inode->gfid));                  goto out;          } @@ -1792,16 +1885,18 @@ int  posix_link (call_frame_t *frame, xlator_t *this,              loc_t *oldloc, loc_t *newloc, dict_t *xdata)  { -        int32_t               op_ret       = -1; -        int32_t               op_errno     = 0; -        char                 *real_oldpath = 0; -        char                 *real_newpath = 0; -        char                 *par_newpath = 0; -        struct iatt           stbuf        = {0, }; -        struct posix_private *priv         = NULL; -        char                  was_present  = 1; -        struct iatt           preparent = {0,}; -        struct iatt           postparent = {0,}; +        int32_t               op_ret          = -1; +        int32_t               op_errno        = 0; +        char                 *real_oldpath    = 0; +        char                 *real_newpath    = 0; +        char                 *par_newpath     = 0; +        struct iatt           stbuf           = {0, }; +        struct posix_private *priv            = NULL; +        char                  was_present     = 1; +        struct iatt           preparent       = {0,}; +        struct iatt           postparent      = {0,}; +        int32_t               nlink_samepgfid = 0; +        char                 *pgfid_xattr_key = NULL;          DECLARE_OLD_FS_ID_VAR; @@ -1866,6 +1961,27 @@ posix_link (call_frame_t *frame, xlator_t *this,                  goto out;          } +        if (priv->update_pgfid_nlinks) { +                MAKE_PGFID_XATTR_KEY (pgfid_xattr_key, PGFID_XATTR_KEY_PREFIX, +                                      newloc->pargfid); + +                LOCK (&newloc->inode->lock); +                { +                        LINK_MODIFY_PGFID_XATTR (real_newpath, pgfid_xattr_key, +                                                 nlink_samepgfid, 0, op_ret, +                                                 this, unlock); +                } +        unlock: +                UNLOCK (&newloc->inode->lock); + +                if (op_ret < 0) { +                        gf_log (this->name, GF_LOG_WARNING, "modification of " +                                "parent gfid xattr failed (path:%s gfid:%s)", +                                real_newpath, uuid_utoa (newloc->inode->gfid)); +                        goto out; +                } +        } +          op_ret = 0;  out: @@ -1932,7 +2048,6 @@ posix_truncate (call_frame_t *frame, xlator_t *this, loc_t *loc, off_t offset,          }          op_ret = 0; -  out:          SET_TO_OLD_FS_ID (); @@ -1948,20 +2063,23 @@ posix_create (call_frame_t *frame, xlator_t *this,                loc_t *loc, int32_t flags, mode_t mode,                mode_t umask, fd_t *fd, dict_t *xdata)  { -        int32_t                op_ret      = -1; -        int32_t                op_errno    = 0; -        int32_t                _fd         = -1; -        int                    _flags      = 0; -        char *                 real_path   = NULL; -        char *                 par_path   = NULL; -        struct iatt            stbuf       = {0, }; -        struct posix_fd *      pfd         = NULL; -        struct posix_private * priv        = NULL; -        char                   was_present = 1; - -        gid_t                  gid         = 0; -        struct iatt            preparent = {0,}; -        struct iatt            postparent = {0,}; +        int32_t                op_ret          = -1; +        int32_t                op_errno        = 0; +        int32_t                _fd             = -1; +        int                    _flags          = 0; +        char *                 real_path       = NULL; +        char *                 par_path        = NULL; +        struct iatt            stbuf           = {0, }; +        struct posix_fd *      pfd             = NULL; +        struct posix_private * priv            = NULL; +        char                   was_present     = 1; + +        gid_t                  gid             = 0; +        struct iatt            preparent       = {0,}; +        struct iatt            postparent      = {0,}; + +        int                    nlink_samepgfid = 0; +        char *                 pgfid_xattr_key = NULL;          DECLARE_OLD_FS_ID_VAR; @@ -2037,7 +2155,6 @@ posix_create (call_frame_t *frame, xlator_t *this,                          real_path, strerror (op_errno));          }  #endif -          op_ret = posix_acl_xattr_set (this, real_path, xdata);          if (op_ret) {                  gf_log (this->name, GF_LOG_ERROR, @@ -2045,6 +2162,14 @@ posix_create (call_frame_t *frame, xlator_t *this,                          strerror (errno));          } +        if (priv->update_pgfid_nlinks) { +                MAKE_PGFID_XATTR_KEY (pgfid_xattr_key, PGFID_XATTR_KEY_PREFIX, +                                      loc->pargfid); +                nlink_samepgfid = 1; +                SET_PGFID_XATTR (real_path, pgfid_xattr_key, nlink_samepgfid, +                                 XATTR_CREATE, op_ret, this, ignore); +        } +ignore:          op_ret = posix_entry_create_xattr_set (this, real_path, xdata);          if (op_ret) {                  gf_log (this->name, GF_LOG_ERROR, @@ -2876,6 +3001,335 @@ posix_xattr_get_real_filename (call_frame_t *frame, xlator_t *this, loc_t *loc,  	return ret;  } +int +posix_get_ancestry_directory (xlator_t *this, inode_t *leaf_inode, +                              gf_dirent_t *head, char **path, int type, +                              int32_t *op_errno, dict_t *xdata) +{ +        ssize_t               handle_size = 0; +        struct posix_private *priv        = NULL; +        char    dirpath[PATH_MAX+1]       = {0,}; +        inode_t              *inode       = NULL; +        int                   ret         = -1; + +        priv = this->private; + +        handle_size = POSIX_GFID_HANDLE_SIZE(priv->base_path_length); + +        ret = posix_make_ancestryfromgfid (this, dirpath, PATH_MAX + 1, head, +                                           type | POSIX_ANCESTRY_PATH, +                                           leaf_inode->gfid, +                                           handle_size, priv->base_path, +                                           leaf_inode->table, &inode, xdata); +        if (ret < 0) +                goto out; + + +        /* there is already a reference in loc->inode */ +        inode_unref (inode); + +        if ((type & POSIX_ANCESTRY_PATH) && (path != NULL)) { +                if (strcmp (dirpath, "/")) +                        dirpath[strlen (dirpath) - 1] = '\0'; + +                *path = gf_strdup (dirpath); +        } + +out: +        return ret; +} + +int32_t +posix_links_in_same_directory (char *dirpath, int count, inode_t *leaf_inode, +                               inode_t *parent, uint64_t ino, +                               gf_dirent_t *head, char **path, +                               int type, dict_t *xdata, int32_t *op_errno) +{ +        DIR                  *dirp         = NULL; +        int                   op_ret       = -1; +        struct dirent        *entry        = NULL; +        struct dirent        *result       = NULL; +        inode_t              *linked_inode = NULL; +        gf_dirent_t          *gf_entry     = NULL; +        char    temppath[PATH_MAX+1]       = {0,}; +        xlator_t             *this         = NULL; +        struct posix_private *priv         = NULL; +        char                 *tempv        = NULL; + +        this = THIS; + +        priv = this->private; + +        dirp = opendir (dirpath); +        if (!dirp) { +                *op_errno = errno; +                gf_log (this->name, GF_LOG_WARNING, +                        "could not opendir %s: %s", dirpath, +                        strerror (*op_errno)); +                goto out; +        } + +        entry = alloca (offsetof(struct dirent, d_name) + NAME_MAX + 1); +        if (entry == NULL) +                goto out; + +        while (count > 0) { +                *op_errno = readdir_r (dirp, entry, &result); +                if ((result == NULL) || *op_errno) +                        break; + +                if (entry->d_ino != ino) +                        continue; + +                linked_inode = inode_link (leaf_inode, parent, +                                           entry->d_name, NULL); + +                GF_ASSERT (linked_inode == leaf_inode); +                inode_unref (linked_inode); + +                if (type & POSIX_ANCESTRY_DENTRY) { +                        loc_t loc = {0, }; + +                        loc.inode = inode_ref (leaf_inode); +                        uuid_copy (loc.gfid, leaf_inode->gfid); + +                        strcpy (temppath, dirpath); +                        strcat (temppath, "/"); +                        strcat (temppath, entry->d_name); + +                        gf_entry = gf_dirent_for_name (entry->d_name); +                        gf_entry->inode = inode_ref (leaf_inode); +                        gf_entry->dict +                                = posix_lookup_xattr_fill (this, +                                                           temppath, +                                                           &loc, xdata, +                                                           NULL); +                        list_add_tail (&gf_entry->list, &head->list); +                        loc_wipe (&loc); +                } + +                if (type & POSIX_ANCESTRY_PATH) { +                        strcpy (temppath, +                                &dirpath[priv->base_path_length]); +                        strcat (temppath, "/"); +                        strcat (temppath, entry->d_name); +                        if (!*path) { +                                *path = gf_strdup (temppath); +                        } else { +                                /* creating a colon separated */ +                                /* list of hard links */ +                                tempv  = GF_REALLOC (*path, strlen (*path) +                                                     + 1  // ':' +                                                     + strlen (temppath) + 1 ); +                                if (!tempv) { +                                        gf_log (this->name, GF_LOG_WARNING, +                                                "realloc failed on path"); +                                        GF_FREE (*path); +                                        op_ret = -1; +                                        *op_errno = ENOMEM; +                                        goto out; +                                } + +                                *path = tempv; +                                strcat (*path, ":"); +                                strcat (*path, temppath); +                        } +                } + +                count--; +        } + +out: +        if (dirp) { +                op_ret = closedir (dirp); +                if (op_ret == -1) { +                        *op_errno = errno; +                        gf_log (this->name, GF_LOG_WARNING, +                                "closedir failed: %s", +                                strerror (*op_errno)); +                } +        } + +        return op_ret; +} + +int +posix_get_ancestry_non_directory (xlator_t *this, inode_t *leaf_inode, +                                  gf_dirent_t *head, char **path, int type, +                                  int32_t *op_errno, dict_t *xdata) +{ +        size_t                remaining_size        = 0; +        char    dirpath[PATH_MAX+1]                 = {0,}, *leaf_path = NULL; +        int                   op_ret                = -1, pathlen = -1; +        ssize_t               handle_size           = 0; +        char    pgfidstr[UUID_CANONICAL_FORM_LEN+1] = {0,}; +        uuid_t                pgfid                 = {0, }; +        int                   nlink_samepgfid       = 0; +        struct stat           stbuf                 = {0,}; +        char                 *list                  = NULL; +        int32_t               list_offset           = 0; +        char     key[4096]                          = {0,}; +        struct posix_private *priv                  = NULL; +        ssize_t               size                  = 0; +        inode_t              *parent                = NULL; +        loc_t                *loc                   = NULL; + +        priv = this->private; + +        loc = GF_CALLOC (1, sizeof (*loc), gf_posix_mt_char); +        if (loc == NULL) { +                op_ret = -1; +                *op_errno = ENOMEM; +                goto out; +        } + +        uuid_copy (loc->gfid, leaf_inode->gfid); + +        MAKE_INODE_HANDLE (leaf_path, this, loc, NULL); + +        GF_FREE (loc); + +        size = sys_llistxattr (leaf_path, NULL, 0); +        if (size == -1) { +                *op_errno = errno; +                if ((errno == ENOTSUP) || (errno == ENOSYS)) { +                        GF_LOG_OCCASIONALLY (gf_posix_xattr_enotsup_log, +                                             this->name, GF_LOG_WARNING, +                                             "Extended attributes not " +                                             "supported (try remounting brick" +                                             " with 'user_xattr' flag)"); + +                } else { +                        gf_log (this->name, GF_LOG_WARNING, +                                "listxattr failed on %s: %s", +                                leaf_path, strerror (*op_errno)); + +                } + +                goto out; +        } + +        if (size == 0) { +                op_ret = 0; +                goto out; +        } + +        list = alloca (size + 1); +        if (!list) { +                *op_errno = errno; +                goto out; +        } + +        size = sys_llistxattr (leaf_path, list, size); +        remaining_size = size; +        list_offset = 0; + +        op_ret = sys_lstat (leaf_path, &stbuf); +        if (op_ret == -1) { +                *op_errno = errno; +                gf_log (this->name, GF_LOG_WARNING, "lstat failed" +                        " on %s: %s", leaf_path, +                        strerror (*op_errno)); +                goto out; +        } + +        while (remaining_size > 0) { +                if (*(list + list_offset) == '\0') +                        break; +                strcpy (key, list + list_offset); +                if (strncmp (key, PGFID_XATTR_KEY_PREFIX, +                             strlen (PGFID_XATTR_KEY_PREFIX)) != 0) +                        goto next; + +                op_ret = sys_lgetxattr (leaf_path, key, +                                        &nlink_samepgfid, +                                        sizeof(nlink_samepgfid)); +                if (op_ret == -1) { +                        *op_errno = errno; +                        gf_log (this->name, GF_LOG_ERROR, +                                "getxattr failed on " +                                "%s: key = %s (%s)", +                                leaf_path, +                                key, +                                strerror (*op_errno)); +                        goto out; +                } + +                nlink_samepgfid = ntoh32 (nlink_samepgfid); + +                strcpy (pgfidstr, key + strlen(PGFID_XATTR_KEY_PREFIX)); +                uuid_parse (pgfidstr, pgfid); + +                handle_size = POSIX_GFID_HANDLE_SIZE(priv->base_path_length); + +                /* constructing the absolute real path of parent dir */ +                strcpy (dirpath, priv->base_path); +                pathlen = PATH_MAX + 1 - priv->base_path_length; + +                op_ret = posix_make_ancestryfromgfid (this, +                                                      dirpath + priv->base_path_length, +                                                      pathlen, +                                                      head, +                                                      POSIX_ANCESTRY_PATH | POSIX_ANCESTRY_DENTRY, +                                                      pgfid, +                                                      handle_size, +                                                      priv->base_path, +                                                      leaf_inode->table, +                                                      &parent, xdata); +                if (op_ret < 0) { +                        goto next; +                } + +                dirpath[strlen (dirpath) - 1] = '\0'; + +                posix_links_in_same_directory (dirpath, nlink_samepgfid, +                                               leaf_inode, +                                               parent, stbuf.st_ino, head, +                                               path, type, xdata, op_errno); + +                if (parent != NULL) { +                        inode_unref (parent); +                        parent = NULL; +                } + +        next: +                remaining_size -= strlen (key) + 1; +                list_offset += strlen (key) + 1; +        } /* while (remaining_size > 0) */ + +        op_ret = 0; + +out: +        return op_ret; +} + +int +posix_get_ancestry (xlator_t *this, inode_t *leaf_inode, +                    gf_dirent_t *head, char **path, int type, int32_t *op_errno, +                    dict_t *xdata) +{ +        int                   ret  = -1; +        struct posix_private *priv = NULL; + +        priv = this->private; + +        if (!priv->update_pgfid_nlinks) +                goto out; + +        if (IA_ISDIR (leaf_inode->ia_type)) { +                ret = posix_get_ancestry_directory (this, leaf_inode, +                                                    head, path, type, op_errno, +                                                    xdata); +        } else  { +                ret = posix_get_ancestry_non_directory (this, leaf_inode, +                                                        head, path, type, +                                                        op_errno, xdata); +        } + +out: +        return ret; +} +  /**   * posix_getxattr - this function returns a dictionary with all the   *                  key:value pair present as xattr. used for @@ -2885,23 +3339,23 @@ int32_t  posix_getxattr (call_frame_t *frame, xlator_t *this,                  loc_t *loc, const char *name, dict_t *xdata)  { -        struct posix_private *priv           = NULL; -        int32_t               op_ret         = -1; -        int32_t               op_errno       = 0; -        int32_t               list_offset    = 0; -        ssize_t               size           = 0; -        size_t                remaining_size = 0; -        char     key[4096]                   = {0,}; -        char     host_buf[1024]              = {0,}; -        char                 *value          = NULL; -        char                 *list           = NULL; -        char                 *real_path      = NULL; -        dict_t               *dict           = NULL; -        char                 *file_contents  = NULL; -        int                   ret            = -1; -        char                 *path           = NULL; -        char                 *rpath          = NULL; -        char                 *dyn_rpath      = NULL; +        struct posix_private *priv                  = NULL; +        int32_t               op_ret                = -1; +        int32_t               op_errno              = 0; +        char     host_buf[1024]                     = {0,}; +        char                 *value                 = NULL; +        char                 *real_path             = NULL; +        dict_t               *dict                  = NULL; +        char                 *file_contents         = NULL; +        int                   ret                   = -1; +        char                 *path                  = NULL; +        char                 *rpath                 = NULL; +        char                 *dyn_rpath             = NULL; +        ssize_t               size                  = 0; +        char                 *list                  = NULL; +        int32_t               list_offset           = 0; +        size_t                remaining_size        = 0; +        char     key[4096]                          = {0,};          DECLARE_OLD_FS_ID_VAR; @@ -3045,6 +3499,31 @@ posix_getxattr (call_frame_t *frame, xlator_t *this,                  goto done;          } +        if (loc->inode && name +            && (strcmp (name, GET_ANCESTRY_PATH_KEY) == 0)) { +                int type = POSIX_ANCESTRY_PATH; + +                op_ret = posix_get_ancestry (this, loc->inode, NULL, +                                             &path, type, &op_errno, +                                             xdata); +                if (op_ret < 0) { +                        op_ret = -1; +                        op_errno = ENODATA; +                        goto out; +                } + +                op_ret = dict_set_dynstr (dict, GET_ANCESTRY_PATH_KEY, path); +                if (op_ret < 0) { +                        gf_log (this->name, GF_LOG_WARNING, "could not get " +                                "value for key (%s)", GET_ANCESTRY_PATH_KEY); +                        GF_FREE (path); +                        op_errno = -op_ret; +                        op_ret = -1; +                } + +                goto done; +        } +          if (name) {                  strcpy (key, name); @@ -3189,8 +3668,9 @@ out:          STACK_UNWIND_STRICT (getxattr, frame, op_ret, op_errno, dict, NULL); -        if (dict) +        if (dict) {                  dict_unref (dict); +        }          return 0;  } @@ -4322,15 +4802,14 @@ int32_t  posix_do_readdir (call_frame_t *frame, xlator_t *this,                    fd_t *fd, size_t size, off_t off, int whichop, dict_t *dict)  { -        struct posix_fd      *pfd            = NULL; -        DIR                  *dir            = NULL; -        int                   ret            = -1; -        int                   count          = 0; -        int32_t               op_ret         = -1; -        int32_t               op_errno       = 0; -        gf_dirent_t           entries; -        int32_t               skip_dirs      = 0; - +        struct posix_fd *pfd       = NULL; +        DIR             *dir       = NULL; +        int              ret       = -1; +        int              count     = 0; +        int32_t          op_ret    = -1; +        int32_t          op_errno  = 0; +        gf_dirent_t      entries; +        int32_t          skip_dirs = 0;          VALIDATE_OR_GOTO (frame, out);          VALIDATE_OR_GOTO (this, out); @@ -4409,6 +4888,32 @@ int32_t  posix_readdirp (call_frame_t *frame, xlator_t *this,                  fd_t *fd, size_t size, off_t off, dict_t *dict)  { +        gf_dirent_t entries; +        int32_t     op_ret = -1, op_errno = 0; +        gf_dirent_t     *entry     = NULL; + + +        if ((dict != NULL) && (dict_get (dict, GET_ANCESTRY_DENTRY_KEY))) { +                INIT_LIST_HEAD (&entries.list); + +                op_ret = posix_get_ancestry (this, fd->inode, &entries, NULL, +                                             POSIX_ANCESTRY_DENTRY, +                                             &op_errno, dict); +                if (op_ret >= 0) { +                        op_ret = 0; + +                        list_for_each_entry (entry, &entries.list, list) { +                                op_ret++; +                        } +                } + +                STACK_UNWIND_STRICT (readdir, frame, op_ret, op_errno, &entries, +                                     NULL); + +                gf_dirent_free (&entries); +                return 0; +        } +          posix_do_readdir (frame, this, fd, size, off, GF_FOP_READDIRP, dict);          return 0;  } @@ -4635,6 +5140,9 @@ reconfigure (xlator_t *this, dict_t *options)  	else  		posix_aio_off (this); +        GF_OPTION_RECONF ("update-link-count-parent", priv->update_pgfid_nlinks, +                          options, bool, out); +          GF_OPTION_RECONF ("node-uuid-pathinfo", priv->node_uuid_pathinfo,                            options, bool, out); @@ -4912,6 +5420,24 @@ init (xlator_t *this)                                  "for every open)");          } +        tmp_data = dict_get (this->options, "update-link-count-parent"); +        if (tmp_data) { +                if (gf_string2boolean (tmp_data->data, +                                       &_private->update_pgfid_nlinks) == -1) { +                        ret = -1; +                        gf_log (this->name, GF_LOG_ERROR, +                                "wrong value provided for " +                                "'update-link-count-parent'"); +                        goto out; +                } +                if (_private->update_pgfid_nlinks) +                        gf_log (this->name, GF_LOG_DEBUG, +                                "update-link-count-parent is enabled. Thus for each " +                                "file an extended attribute representing the " +                                "number of hardlinks for that file within the " +                                "same parent directory is set."); +        } +          ret = dict_get_str (this->options, "glusterd-uuid", &guuid);          if (!ret) {                  if (uuid_parse (guuid, _private->glusterd_uuid)) @@ -5203,5 +5729,10 @@ struct volume_options options[] = {  	  .description = "Num of usecs to wait for aggregating fsync"  	  " requests",  	}, +        { .key = {"update-link-count-parent"}, +          .type = GF_OPTION_TYPE_BOOL, +          .default_value = "false", +          .description = "Enable placeholders for gfid to path conversion" +        },          { .key  = {NULL} }  }; diff --git a/xlators/storage/posix/src/posix.h b/xlators/storage/posix/src/posix.h index 3121db2717e..d579bf673db 100644 --- a/xlators/storage/posix/src/posix.h +++ b/xlators/storage/posix/src/posix.h @@ -52,6 +52,12 @@  #define VECTOR_SIZE 64 * 1024 /* vector size 64KB*/  #define MAX_NO_VECT 1024 + +#define POSIX_GFID_HANDLE_SIZE(base_path_len) (base_path_len + SLEN("/") \ +                                               + SLEN(HANDLE_PFX) + SLEN("/") \ +                                               + SLEN("00/")            \ +                                               + SLEN("00/") + SLEN(UUID0_STR) + 1) /* '\0' */; +  /**   * posix_fd - internal structure common to file and directory fd's   */ @@ -146,6 +152,7 @@ struct posix_private {  	}               batch_fsync_mode;  	uint32_t        batch_fsync_delay_usec; +        gf_boolean_t    update_pgfid_nlinks;          /* seconds to sleep between health checks */          uint32_t        health_check_interval; @@ -205,4 +212,8 @@ __posix_fd_set_odirect (fd_t *fd, struct posix_fd *pfd, int opflags,  void posix_spawn_health_check_thread (xlator_t *this);  void *posix_fsyncer (void *); +int +posix_get_ancestry (xlator_t *this, inode_t *leaf_inode, +                    gf_dirent_t *head, char **path, int type, int32_t *op_errno, +                    dict_t *xdata);  #endif /* _POSIX_H */  | 
