diff options
| author | vmallika <vmallika@redhat.com> | 2016-02-10 06:39:22 +0530 | 
|---|---|---|
| committer | Rajesh Joseph <rjoseph@redhat.com> | 2016-03-23 04:03:52 -0700 | 
| commit | ed4feadc8c60fce1d8d99e0732351b92230d6321 (patch) | |
| tree | a075150b6867a32c702939bb08728ca878fa0d48 | |
| parent | f5f43424994859f263165f0cdebedffd5f08fdcc (diff) | |
uss/gluster: generate gfid for snapshot files from snapname and gfid
This is a backport of http://review.gluster.org/#/c/9255/
If 'a' and 'b' are hardlinks, we need to generate a virtual
gfid for these files so that the inode number for 'a' and 'b'
are same.
Generate gfid as below:
gfid_of_a = MD5(snapname + back_end_gfid(a))
if '/dir1/a' and '/dir2/b' are hardlinks, then inode number should be
same for
all below files:
/mnt/.snaps/snap1/dir1/a
/mnt/.snaps/snap1/dir2/b
/mnt/dir1/.snaps/snap1/a
/mnt/dir2/.snaps/snap1/b
> Change-Id: Ifda793455610e554f3f1e4cbb90d44c02cda4b0f
> BUG: 1171703
> Signed-off-by: vmallika <vmallika@redhat.com>
Change-Id: I917b2fe2915d88f69700bc8c3283e9c613e13bb8
BUG: 1316099
Signed-off-by: vmallika <vmallika@redhat.com>
Reviewed-on: http://review.gluster.org/13656
Smoke: Gluster Build System <jenkins@build.gluster.com>
NetBSD-regression: NetBSD Build System <jenkins@build.gluster.org>
CentOS-regression: Gluster Build System <jenkins@build.gluster.com>
Reviewed-by: Rajesh Joseph <rjoseph@redhat.com>
| -rw-r--r-- | tests/basic/uss.t | 32 | ||||
| -rw-r--r-- | tests/include.rc | 10 | ||||
| -rw-r--r-- | xlators/features/snapview-server/src/snapview-server-helpers.c | 15 | ||||
| -rw-r--r-- | xlators/features/snapview-server/src/snapview-server.c | 121 | ||||
| -rw-r--r-- | xlators/features/snapview-server/src/snapview-server.h | 19 | 
5 files changed, 162 insertions, 35 deletions
diff --git a/tests/basic/uss.t b/tests/basic/uss.t index 7a4f043d260..55fab660aa2 100644 --- a/tests/basic/uss.t +++ b/tests/basic/uss.t @@ -41,7 +41,14 @@ TEST $GFS --volfile-server=$H0 --volfile-id=$V0 $M0;  for i in {1..10} ; do echo "file" > $M0/file$i ; done +# Create file and hard-links +TEST touch $M0/f1 +TEST mkdir $M0/dir +TEST ln $M0/f1 $M0/f2 +TEST ln $M0/f1 $M0/dir/f3 +  TEST $CLI snapshot config activate-on-create enable +TEST $CLI volume set $V0 features.uss enable;  TEST $CLI snapshot create snap1 $V0 no-timestamp; @@ -49,6 +56,29 @@ for i in {11..20} ; do echo "file" > $M0/file$i ; done  TEST $CLI snapshot create snap2 $V0 no-timestamp; +########### Test inode numbers ########### +s1_f1_ino=$(STAT_INO $M0/.snaps/snap1/f1) +TEST [ $s1_f1_ino != 0 ] + +# Inode number of f1 should be same as f2 f3 within snapshot +EXPECT $s1_f1_ino STAT_INO $M0/.snaps/snap1/f2 +EXPECT $s1_f1_ino STAT_INO $M0/.snaps/snap1/dir/f3 +EXPECT $s1_f1_ino STAT_INO $M0/dir/.snaps/snap1/f3 + +# Inode number of f1 in snap1 should be different from f1 in snap2 +tmp_ino=$(STAT_INO $M0/.snaps/snap2/f1) +TEST [ $s1_f1_ino != $tmp_ino ] + +# Inode number of f1 in snap1 should be different from f1 in regular volume +tmp_ino=$(STAT_INO $M0/f1) +TEST [ $s1_f1_ino != $tmp_ino ] + +# Directory inode of snap1 should be different in each sub-dir +s1_ino=$(STAT_INO $M0/.snaps/snap1) +tmp_ino=$(STAT_INO $M0/dir/.snaps/snap1) +TEST [ $s1_ino != $tmp_ino ] +########################################## +  mkdir $M0/dir1;  mkdir $M0/dir2; @@ -80,8 +110,6 @@ TEST ! $CLI volume set $V0 features.snapshot-directory .  TEST ! $CLI volume set $V0 features.snapshot-directory ..  TEST ! $CLI volume set $V0 features.snapshot-directory .123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345 -TEST $CLI volume set $V0 features.uss enable; -  EXPECT_WITHIN $UMOUNT_TIMEOUT "Y" force_umount $M0  TEST $GFS --volfile-server=$H0 --volfile-id=$V0 $M0; diff --git a/tests/include.rc b/tests/include.rc index 495db1b0ca6..03c9f444361 100644 --- a/tests/include.rc +++ b/tests/include.rc @@ -1068,3 +1068,13 @@ function STAT()          stat $1          echo $?  } + +function STAT_INO() +{ +        local ino=$(stat -c '%i' $1) +        if [ $? -eq 0 ]; then +                echo $ino +        else +                echo 0 +        fi +} diff --git a/xlators/features/snapview-server/src/snapview-server-helpers.c b/xlators/features/snapview-server/src/snapview-server-helpers.c index 92ffdf512ef..0303f4d6df6 100644 --- a/xlators/features/snapview-server/src/snapview-server-helpers.c +++ b/xlators/features/snapview-server/src/snapview-server-helpers.c @@ -335,6 +335,21 @@ out:  }  void +svs_uuid_generate (uuid_t gfid, char *snapname, uuid_t origin_gfid) +{ +        unsigned char md5_sum[MD5_DIGEST_LENGTH] = {0}; +        char          ino_string[NAME_MAX + 32]  = ""; +        int           ret                        = 0; + +        GF_ASSERT (snapname); + +        ret = snprintf (ino_string, sizeof (ino_string), "%s%s", +                        snapname, uuid_utoa(origin_gfid)); +        MD5((unsigned char *)ino_string, strlen(ino_string), md5_sum); +        gf_uuid_copy (gfid, md5_sum); +} + +void  svs_fill_ino_from_gfid (struct iatt *buf)  {          uint64_t  temp_ino = 0; diff --git a/xlators/features/snapview-server/src/snapview-server.c b/xlators/features/snapview-server/src/snapview-server.c index ed30cb8e09d..95e8d3ca5f4 100644 --- a/xlators/features/snapview-server/src/snapview-server.c +++ b/xlators/features/snapview-server/src/snapview-server.c @@ -261,9 +261,23 @@ svs_lookup_snapshot (xlator_t *this, loc_t *loc, struct iatt *buf,          memcpy (&inode_ctx->buf, buf, sizeof (*buf));          svs_iatt_fill (parent->gfid, postparent); +        SVS_STRDUP (inode_ctx->snapname, loc->name); +        if (!inode_ctx->snapname) { +                op_ret = -1; +                *op_errno = ENOMEM; +                goto out; +        }          op_ret = 0;  out: +        if (op_ret) { +                if (object) +                        glfs_h_close (object); + +                if (inode_ctx) +                        inode_ctx->object = NULL; +        } +          return op_ret;  } @@ -279,7 +293,7 @@ svs_lookup_entry (xlator_t *this, loc_t *loc, struct iatt *buf,          struct stat     statbuf                         = {0, };          svs_inode_t    *inode_ctx                       = NULL;          glfs_object_t  *parent_object                   = NULL; -        uuid_t          gfid; +        uuid_t          gfid                            = {0, };          GF_VALIDATE_OR_GOTO ("snapview-server", this, out);          GF_VALIDATE_OR_GOTO (this->name, loc, out); @@ -303,6 +317,14 @@ svs_lookup_entry (xlator_t *this, loc_t *loc, struct iatt *buf,                  goto out;          } +        if (gf_uuid_is_null(object->gfid)) { +                gf_log (this->name, GF_LOG_DEBUG, "gfid from glfs handle is " +                        "NULL for entry %s (path: %s)", loc->name, loc->path); +                op_ret = -1; +                *op_errno = errno; +                goto out; +        } +          inode_ctx = svs_inode_ctx_get_or_new (this, loc->inode);          if (!inode_ctx) {                  gf_log (this->name, GF_LOG_ERROR, "failed to " @@ -314,7 +336,7 @@ svs_lookup_entry (xlator_t *this, loc_t *loc, struct iatt *buf,          if (gf_uuid_is_null (loc->gfid) &&              gf_uuid_is_null (loc->inode->gfid)) -                gf_uuid_generate (gfid); +                svs_uuid_generate (gfid, parent_ctx->snapname, object->gfid);          else {                  if (!gf_uuid_is_null (loc->inode->gfid))                          gf_uuid_copy (gfid, loc->inode->gfid); @@ -331,9 +353,26 @@ svs_lookup_entry (xlator_t *this, loc_t *loc, struct iatt *buf,          memcpy (&inode_ctx->buf, buf, sizeof (*buf));          svs_iatt_fill (parent->gfid, postparent); +        if (IA_ISDIR (buf->ia_type)) { +                SVS_STRDUP (inode_ctx->snapname, parent_ctx->snapname); +                if (!inode_ctx->snapname) { +                        op_ret = -1; +                        *op_errno = ENOMEM; +                        goto out; +                } +        } +          op_ret = 0;  out: +        if (op_ret) { +                if (object) +                        glfs_h_close (object); + +                if (inode_ctx) +                        inode_ctx->object = NULL; +        } +          return op_ret;  } @@ -812,9 +851,10 @@ svs_getxattr (call_frame_t *frame, xlator_t *this, loc_t *loc, const char *name,                  size = glfs_h_getxattrs (fs, object, name, NULL, 0);                  if (size == -1) { -                        gf_log (this->name, GF_LOG_ERROR, "getxattr " -                                "on %s failed (key: %s)", loc->name, -                                name); +                        gf_log (this->name, +                                errno == ENODATA?GF_LOG_DEBUG:GF_LOG_ERROR, +                                "getxattr on %s failed (key: %s) with %s", +                                loc->path, name, strerror(errno));                          op_ret = -1;                          op_errno = errno;                          goto out; @@ -1158,9 +1198,11 @@ svs_forget  (xlator_t *this, inode_t *inode)          }          inode_ctx = (svs_inode_t *)value; +        if (!inode_ctx) +                goto out; -        if (inode_ctx->object) -                glfs_h_close (inode_ctx->object); +        if (inode_ctx->snapname) +                GF_FREE (inode_ctx->snapname);          GF_FREE (inode_ctx); @@ -1358,38 +1400,51 @@ svs_readdirp_fill (xlator_t *this, inode_t *parent, svs_inode_t *parent_ctx,                          gf_uuid_copy (entry->d_stat.ia_gfid, buf.ia_gfid);                  }          } else { -                inode = inode_new (parent->table); -                entry->inode = inode; -                gf_uuid_generate (random_gfid); -                gf_uuid_copy (buf.ia_gfid, random_gfid); -                svs_fill_ino_from_gfid (&buf); -                entry->d_ino = buf.ia_ino; - -                /* If inode context allocation fails, then do not send the -                   inode for that particular entry as part of readdirp -                   response. Fuse and protocol/server will link the inodes -                   in readdirp only if the entry contains inode in it. -                */ -                inode_ctx = svs_inode_ctx_get_or_new (this, inode); -                if (!inode_ctx) { -                        gf_log (this->name, GF_LOG_ERROR, "failed to allocate " -                                "inode context for %s", entry->d_name); -                        inode_unref (entry->inode); -                        entry->inode = NULL; -                        goto out; -                } -                  if (parent_ctx->type == SNAP_VIEW_ENTRY_POINT_INODE) { +                        inode = inode_new (parent->table); +                        entry->inode = inode; + +                        /* If inode context allocation fails, then do not send +                         * the inode for that particular entry as part of +                         * readdirp response. Fuse and protocol/server will link +                         * the inodes in readdirp only if the entry contains +                         * inode in it. +                         */ +                        inode_ctx = svs_inode_ctx_get_or_new (this, inode); +                        if (!inode_ctx) { +                                gf_log (this->name, GF_LOG_ERROR, "failed to " +                                        "allocate inode context for %s", +                                        entry->d_name); +                                inode_unref (entry->inode); +                                entry->inode = NULL; +                                goto out; +                        } + +                        /* Generate virtual gfid for SNAPSHOT dir and +                         * update the statbuf +                         */ +                        gf_uuid_generate (random_gfid); +                        gf_uuid_copy (buf.ia_gfid, random_gfid); +                        svs_fill_ino_from_gfid (&buf);                          buf.ia_type = IA_IFDIR; -                        inode_ctx->buf = buf; +                        entry->d_ino = buf.ia_ino;                          entry->d_stat = buf; +                        inode_ctx->buf = buf;                          inode_ctx->type = SNAP_VIEW_SNAPSHOT_INODE;                  } else { -                        gf_uuid_copy (entry->d_stat.ia_gfid, buf.ia_gfid); -                        entry->d_stat.ia_ino = buf.ia_ino; -                        inode_ctx->buf = entry->d_stat; -                        inode_ctx->type = SNAP_VIEW_VIRTUAL_INODE; +                        /* For files under snapshot world do not set +                         * entry->inode and reset statbuf (except ia_ino), +                         * so that FUSE/Kernel will send an explicit lookup. +                         * entry->d_stat contains the statbuf information +                         * of original file, so for NFS not to cache this +                         * information and to send explicit lookup, it is +                         * required to reset the statbuf. +                         * Virtual gfid for these files will be generated in the +                         * first lookup. +                         */ +                        buf.ia_ino = entry->d_ino; +                        entry->d_stat = buf;                  }          } diff --git a/xlators/features/snapview-server/src/snapview-server.h b/xlators/features/snapview-server/src/snapview-server.h index c80d3456c30..f9249f9d828 100644 --- a/xlators/features/snapview-server/src/snapview-server.h +++ b/xlators/features/snapview-server/src/snapview-server.h @@ -105,6 +105,17 @@                  }                                                       \          } while(0); +#define SVS_STRDUP(dst, src)                                            \ +        do {                                                            \ +                if (dst && strcmp (src, dst)) {                         \ +                        GF_FREE (dst);                                  \ +                        dst = NULL;                                     \ +                }                                                       \ +                                                                        \ +                if (!dst)                                               \ +                        dst = gf_strdup (src);                          \ +        } while (0) +  int  svs_mgmt_submit_request (void *req, call_frame_t *frame,                           glusterfs_ctx_t *ctx, @@ -133,6 +144,11 @@ struct svs_inode {             from where the entry point was entered is saved.          */          uuid_t pargfid; + +        /* This is used to generate gfid for all sub files/dirs under this +         * snapshot +         */ +        char *snapname;          struct iatt buf;  };  typedef struct svs_inode svs_inode_t; @@ -194,6 +210,9 @@ svs_fd_t *  svs_fd_ctx_get_or_new (xlator_t *this, fd_t *fd);  void +svs_uuid_generate (uuid_t gfid, char *snapname, uuid_t origin_gfid); + +void  svs_fill_ino_from_gfid (struct iatt *buf);  void  | 
