diff options
-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 b46a7b2fde4..6f224833bf9 100644 --- a/tests/include.rc +++ b/tests/include.rc @@ -1137,3 +1137,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 38ca7ae6342..dd2e891a849 100644 --- a/xlators/features/snapview-server/src/snapview-server-helpers.c +++ b/xlators/features/snapview-server/src/snapview-server-helpers.c @@ -330,6 +330,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 f209edd2e94..338d5bd2f75 100644 --- a/xlators/features/snapview-server/src/snapview-server.c +++ b/xlators/features/snapview-server/src/snapview-server.c @@ -256,9 +256,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; } @@ -274,7 +288,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); @@ -298,6 +312,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 " @@ -309,7 +331,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); @@ -326,9 +348,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; } @@ -807,9 +846,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; @@ -1153,9 +1193,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); @@ -1353,38 +1395,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 a682aeed33e..a12319fa9b2 100644 --- a/xlators/features/snapview-server/src/snapview-server.h +++ b/xlators/features/snapview-server/src/snapview-server.h @@ -100,6 +100,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, @@ -128,6 +139,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; @@ -189,6 +205,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 |