summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--tests/basic/uss.t32
-rw-r--r--tests/include.rc10
-rw-r--r--xlators/features/snapview-server/src/snapview-server-helpers.c15
-rw-r--r--xlators/features/snapview-server/src/snapview-server.c121
-rw-r--r--xlators/features/snapview-server/src/snapview-server.h19
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