From ed4feadc8c60fce1d8d99e0732351b92230d6321 Mon Sep 17 00:00:00 2001 From: vmallika Date: Wed, 10 Feb 2016 06:39:22 +0530 Subject: 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 Change-Id: I917b2fe2915d88f69700bc8c3283e9c613e13bb8 BUG: 1316099 Signed-off-by: vmallika Reviewed-on: http://review.gluster.org/13656 Smoke: Gluster Build System NetBSD-regression: NetBSD Build System CentOS-regression: Gluster Build System Reviewed-by: Rajesh Joseph --- .../snapview-server/src/snapview-server-helpers.c | 15 +++ .../features/snapview-server/src/snapview-server.c | 121 +++++++++++++++------ .../features/snapview-server/src/snapview-server.h | 19 ++++ 3 files changed, 122 insertions(+), 33 deletions(-) (limited to 'xlators/features/snapview-server') 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 @@ -334,6 +334,21 @@ out: return svs_fd; } +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) { 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; @@ -193,6 +209,9 @@ __svs_fd_ctx_get_or_new (xlator_t *this, fd_t *fd); 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); -- cgit