|
|
887953 |
From adc074704603822bed91e2714d93501e926c05a3 Mon Sep 17 00:00:00 2001
|
|
|
887953 |
From: Raghavendra Bhat <raghavendra@redhat.com>
|
|
|
887953 |
Date: Fri, 21 Sep 2018 11:25:08 -0400
|
|
|
887953 |
Subject: [PATCH 384/385] features/uss: Use xxh64 to generate gfid instead of
|
|
|
887953 |
md5sum
|
|
|
887953 |
|
|
|
887953 |
* This is to ensure FIPS support
|
|
|
887953 |
* Also changed the signature of svs_uuid_generate to
|
|
|
887953 |
get xlator argument
|
|
|
887953 |
* Added xxh64 wrapper functions in common-utils to
|
|
|
887953 |
generate gfid using xxh64
|
|
|
887953 |
- Those wrapper functions can be used by other xlators
|
|
|
887953 |
as well to generate gfids using xxh64. But as of now
|
|
|
887953 |
snapview-server is going to be the only consumer.
|
|
|
887953 |
|
|
|
887953 |
backport of following 2 patches from upstream:
|
|
|
887953 |
https://review.gluster.org/#/c/glusterfs/+/21122/
|
|
|
887953 |
https://review.gluster.org/#/c/glusterfs/+/20983/
|
|
|
887953 |
|
|
|
887953 |
Change-Id: I35047cd1911d7a6ebe036d699d57fbdcd364ec8f
|
|
|
887953 |
BUG: 1459709
|
|
|
887953 |
Signed-off-by: Raghavendra Bhat <raghavendra@redhat.com>
|
|
|
887953 |
Reviewed-on: https://code.engineering.redhat.com/gerrit/150759
|
|
|
887953 |
Reviewed-by: Rafi Kavungal Chundattu Parambil <rkavunga@redhat.com>
|
|
|
887953 |
Tested-by: RHGS Build Bot <nigelb@redhat.com>
|
|
|
887953 |
Reviewed-by: Sunil Kumar Heggodu Gopala Acharya <sheggodu@redhat.com>
|
|
|
887953 |
---
|
|
|
887953 |
libglusterfs/src/common-utils.c | 172 +++++++++++++++++++++
|
|
|
887953 |
libglusterfs/src/common-utils.h | 1 +
|
|
|
887953 |
libglusterfs/src/libglusterfs-messages.h | 11 +-
|
|
|
887953 |
.../snapview-server/src/snapview-server-helpers.c | 38 +++--
|
|
|
887953 |
.../features/snapview-server/src/snapview-server.c | 15 +-
|
|
|
887953 |
.../features/snapview-server/src/snapview-server.h | 5 +-
|
|
|
887953 |
6 files changed, 227 insertions(+), 15 deletions(-)
|
|
|
887953 |
|
|
|
887953 |
diff --git a/libglusterfs/src/common-utils.c b/libglusterfs/src/common-utils.c
|
|
|
887953 |
index f632e78..54ef875 100644
|
|
|
887953 |
--- a/libglusterfs/src/common-utils.c
|
|
|
887953 |
+++ b/libglusterfs/src/common-utils.c
|
|
|
887953 |
@@ -91,6 +91,178 @@ gf_xxh64_wrapper(const unsigned char *data, size_t len, unsigned long long seed,
|
|
|
887953 |
snprintf(xxh64 + i * 2, lim-i*2, "%02x", p[i]);
|
|
|
887953 |
}
|
|
|
887953 |
|
|
|
887953 |
+/**
|
|
|
887953 |
+ * This function takes following arguments
|
|
|
887953 |
+ * @this: xlator
|
|
|
887953 |
+ * @gfid: The gfid which has to be filled
|
|
|
887953 |
+ * @hash: the 8 byte hash which has to be filled inside the gfid
|
|
|
887953 |
+ * @index: the array element of the uuid_t structure (which is
|
|
|
887953 |
+ * a array of unsigned char) from where the 8 bytes of
|
|
|
887953 |
+ * the hash has to be filled. Since uuid_t contains 16
|
|
|
887953 |
+ * char elements in the array, each byte of the hash has
|
|
|
887953 |
+ * to be filled in one array element.
|
|
|
887953 |
+ *
|
|
|
887953 |
+ * This function is called twice for 2 hashes (of 8 byte each) to
|
|
|
887953 |
+ * be filled in the gfid.
|
|
|
887953 |
+ *
|
|
|
887953 |
+ * The for loop in this function actually is doing these 2 things
|
|
|
887953 |
+ * for each hash
|
|
|
887953 |
+ *
|
|
|
887953 |
+ * 1) One of the hashes
|
|
|
887953 |
+ * tmp[0] = (hash_2 >> 56) & 0xff;
|
|
|
887953 |
+ * tmp[1] = (hash_2 >> 48) & 0xff;
|
|
|
887953 |
+ * tmp[2] = (hash_2 >> 40) & 0xff;
|
|
|
887953 |
+ * tmp[3] = (hash_2 >> 32) & 0xff;
|
|
|
887953 |
+ * tmp[4] = (hash_2 >> 24) & 0xff;
|
|
|
887953 |
+ * tmp[5] = (hash_2 >> 16) & 0xff;
|
|
|
887953 |
+ * tmp[6] = (hash_2 >> 8) & 0xff;
|
|
|
887953 |
+ * tmp[7] = (hash_2) & 0xff;
|
|
|
887953 |
+ *
|
|
|
887953 |
+ * 2) The other hash:
|
|
|
887953 |
+ * tmp[8] = (hash_1 >> 56) & 0xff;
|
|
|
887953 |
+ * tmp[9] = (hash_1 >> 48) & 0xff;
|
|
|
887953 |
+ * tmp[10] = (hash_1 >> 40) & 0xff;
|
|
|
887953 |
+ * tmp[11] = (hash_1 >> 32) & 0xff;
|
|
|
887953 |
+ * tmp[12] = (hash_1 >> 24) & 0xff;
|
|
|
887953 |
+ * tmp[13] = (hash_1 >> 16) & 0xff;
|
|
|
887953 |
+ * tmp[14] = (hash_1 >> 8) & 0xff;
|
|
|
887953 |
+ * tmp[15] = (hash_1) & 0xff;
|
|
|
887953 |
+ **/
|
|
|
887953 |
+static int
|
|
|
887953 |
+gf_gfid_from_xxh64 (xlator_t *this, uuid_t gfid, GF_XXH64_hash_t hash,
|
|
|
887953 |
+ unsigned short index)
|
|
|
887953 |
+{
|
|
|
887953 |
+ int ret = -1;
|
|
|
887953 |
+ int i = -1;
|
|
|
887953 |
+
|
|
|
887953 |
+ if ((index != 0) && (index != 8)) {
|
|
|
887953 |
+ gf_msg_callingfn ("gfid-from-xxh64", GF_LOG_WARNING, 0,
|
|
|
887953 |
+ LG_MSG_INDEX_NOT_FOUND,
|
|
|
887953 |
+ "index can only be either 0 or 8, as this"
|
|
|
887953 |
+ "function's purpose is to encode a 8 byte "
|
|
|
887953 |
+ "hash inside the gfid (index: %d)",
|
|
|
887953 |
+ index);
|
|
|
887953 |
+ goto out;
|
|
|
887953 |
+ }
|
|
|
887953 |
+
|
|
|
887953 |
+ for (i = 0; i < sizeof(hash); i++) {
|
|
|
887953 |
+ /*
|
|
|
887953 |
+ * As of now the below statement is equivalent of this.
|
|
|
887953 |
+ * gfid[index+i] = (hash >> (64 - (8 * (i+1)))) & 0xff;
|
|
|
887953 |
+ */
|
|
|
887953 |
+ gfid[index + i] = (hash >> ((sizeof(hash) * 8) - (8 * (i + 1)))) &
|
|
|
887953 |
+ (0xff);
|
|
|
887953 |
+ }
|
|
|
887953 |
+
|
|
|
887953 |
+ ret = 0;
|
|
|
887953 |
+
|
|
|
887953 |
+out:
|
|
|
887953 |
+ return ret;
|
|
|
887953 |
+}
|
|
|
887953 |
+
|
|
|
887953 |
+/**
|
|
|
887953 |
+ * This function does the same thing as gf_xxh64_wrapper. But gf_xxh64_wrapper
|
|
|
887953 |
+ * does not return anything and in this xlator there is a need for both the
|
|
|
887953 |
+ * actual hash and the canonicalized form of the hash.
|
|
|
887953 |
+ *
|
|
|
887953 |
+ * To summarize:
|
|
|
887953 |
+ * - XXH64_hash_t is needed as return because, those bytes which contain the
|
|
|
887953 |
+ * hash can be used for different purposes as needed. One example is
|
|
|
887953 |
+ * to have those bytes copied into the uuid_t structure to be used as gfid
|
|
|
887953 |
+ * - xxh64 string is needed because, it can be used as the key for generating
|
|
|
887953 |
+ * the next hash (and any other purpose which might require canonical form
|
|
|
887953 |
+ * of the hash).
|
|
|
887953 |
+ **/
|
|
|
887953 |
+GF_XXH64_hash_t
|
|
|
887953 |
+gf_xxh64_hash_wrapper (const unsigned char *data, size_t const len,
|
|
|
887953 |
+ unsigned long long const seed, char *xxh64)
|
|
|
887953 |
+{
|
|
|
887953 |
+ unsigned short i = 0;
|
|
|
887953 |
+ const unsigned short lim = GF_XXH64_DIGEST_LENGTH * 2 + 1;
|
|
|
887953 |
+ GF_XXH64_hash_t hash = 0;
|
|
|
887953 |
+ GF_XXH64_canonical_t c_hash = {{0,},};
|
|
|
887953 |
+ const uint8_t *p = (const uint8_t *)&c_hash;
|
|
|
887953 |
+
|
|
|
887953 |
+ hash = GF_XXH64 (data, len, seed);
|
|
|
887953 |
+ GF_XXH64_canonicalFromHash (&c_hash, hash);
|
|
|
887953 |
+
|
|
|
887953 |
+ for (i = 0; i < GF_XXH64_DIGEST_LENGTH; i++)
|
|
|
887953 |
+ snprintf (xxh64 + i * 2, lim - i * 2, "%02x", p[i]);
|
|
|
887953 |
+
|
|
|
887953 |
+ return hash;
|
|
|
887953 |
+}
|
|
|
887953 |
+
|
|
|
887953 |
+/**
|
|
|
887953 |
+ * This is the algorithm followed for generating new gfid
|
|
|
887953 |
+ * 1) generate xxh64 hash using snapname and original gfid of the object
|
|
|
887953 |
+ * 2) Using the canonicalized form of above hash as the key, generate
|
|
|
887953 |
+ * another hash
|
|
|
887953 |
+ * 3) Combine both of the 8 byte hashes to generate a 16 byte uuid_t type
|
|
|
887953 |
+ * 4) Use the above uuid as the gfid
|
|
|
887953 |
+ *
|
|
|
887953 |
+ * Each byte of the hash is stored separately in different elements of the
|
|
|
887953 |
+ * character array represented by uuid_t
|
|
|
887953 |
+ * Ex: tmp[0] = (hash_2 >> 56) & 0xFF
|
|
|
887953 |
+ * This saves the most significant byte of hash_2 in tmp[0]
|
|
|
887953 |
+ * tmp[1] = (hash_2 >> 48) & 0xFF
|
|
|
887953 |
+ * This saves next most significant byte of hash_2 in tmp[1]
|
|
|
887953 |
+ * .
|
|
|
887953 |
+ * .
|
|
|
887953 |
+ * So on.
|
|
|
887953 |
+ * tmp[0] - tmp[7] holds the contents of hash_2
|
|
|
887953 |
+ * tmp[8] - tmp[15] hold the conents of hash_1
|
|
|
887953 |
+ *
|
|
|
887953 |
+ * The hash generated (i.e. of type XXH64_hash_t) is 8 bytes long. And for
|
|
|
887953 |
+ * gfid 16 byte uuid is needed. Hecne the 2 hashes are combined to form
|
|
|
887953 |
+ * one 16 byte entity.
|
|
|
887953 |
+ **/
|
|
|
887953 |
+int
|
|
|
887953 |
+gf_gfid_generate_from_xxh64(uuid_t gfid, char *key)
|
|
|
887953 |
+{
|
|
|
887953 |
+ char xxh64_1[GF_XXH64_DIGEST_LENGTH * 2 + 1] = {0,};
|
|
|
887953 |
+ char xxh64_2[GF_XXH64_DIGEST_LENGTH * 2 + 1] = {0};
|
|
|
887953 |
+ GF_XXH64_hash_t hash_1 = 0;
|
|
|
887953 |
+ GF_XXH64_hash_t hash_2 = 0;
|
|
|
887953 |
+ int ret = -1;
|
|
|
887953 |
+ xlator_t *this = THIS;
|
|
|
887953 |
+
|
|
|
887953 |
+ hash_1 = gf_xxh64_hash_wrapper ((unsigned char *)key, strlen (key),
|
|
|
887953 |
+ GF_XXHSUM64_DEFAULT_SEED, xxh64_1);
|
|
|
887953 |
+
|
|
|
887953 |
+ hash_2 = gf_xxh64_hash_wrapper ((unsigned char *)xxh64_1, strlen (xxh64_1),
|
|
|
887953 |
+ GF_XXHSUM64_DEFAULT_SEED, xxh64_2);
|
|
|
887953 |
+
|
|
|
887953 |
+ /* hash_2 is saved in 1st 8 elements of uuid_t char array */
|
|
|
887953 |
+ if (gf_gfid_from_xxh64 (this, gfid, hash_2, 0)) {
|
|
|
887953 |
+ gf_msg_callingfn (this->name, GF_LOG_WARNING, 0,
|
|
|
887953 |
+ LG_MSG_XXH64_TO_GFID_FAILED,
|
|
|
887953 |
+ "failed to encode the hash %llx into the 1st"
|
|
|
887953 |
+ "half of gfid",
|
|
|
887953 |
+ hash_2);
|
|
|
887953 |
+ goto out;
|
|
|
887953 |
+ }
|
|
|
887953 |
+
|
|
|
887953 |
+ /* hash_1 is saved in the remaining 8 elements of uuid_t */
|
|
|
887953 |
+ if (gf_gfid_from_xxh64 (this, gfid, hash_1, 8)) {
|
|
|
887953 |
+ gf_msg_callingfn (this->name, GF_LOG_WARNING, 0,
|
|
|
887953 |
+ LG_MSG_XXH64_TO_GFID_FAILED,
|
|
|
887953 |
+ "failed to encode the hash %llx into the 2nd"
|
|
|
887953 |
+ "half of gfid",
|
|
|
887953 |
+ hash_1);
|
|
|
887953 |
+ goto out;
|
|
|
887953 |
+ }
|
|
|
887953 |
+
|
|
|
887953 |
+ gf_msg_debug (this->name, 0,
|
|
|
887953 |
+ "gfid generated is %s (hash1: %llx) "
|
|
|
887953 |
+ "hash2: %llx, xxh64_1: %s xxh64_2: %s",
|
|
|
887953 |
+ uuid_utoa (gfid), hash_1, hash_2, xxh64_1, xxh64_2);
|
|
|
887953 |
+
|
|
|
887953 |
+ ret = 0;
|
|
|
887953 |
+
|
|
|
887953 |
+out:
|
|
|
887953 |
+ return ret;
|
|
|
887953 |
+}
|
|
|
887953 |
+
|
|
|
887953 |
/* works similar to mkdir(1) -p.
|
|
|
887953 |
*/
|
|
|
887953 |
int
|
|
|
887953 |
diff --git a/libglusterfs/src/common-utils.h b/libglusterfs/src/common-utils.h
|
|
|
887953 |
index da943f4..e64dea3 100644
|
|
|
887953 |
--- a/libglusterfs/src/common-utils.h
|
|
|
887953 |
+++ b/libglusterfs/src/common-utils.h
|
|
|
887953 |
@@ -837,6 +837,7 @@ gf_boolean_t gf_is_local_addr (char *hostname);
|
|
|
887953 |
gf_boolean_t gf_is_same_address (char *host1, char *host2);
|
|
|
887953 |
void gf_xxh64_wrapper(const unsigned char *data, size_t len,
|
|
|
887953 |
unsigned long long seed, char *xxh64);
|
|
|
887953 |
+int gf_gfid_generate_from_xxh64(uuid_t gfid, char *key);
|
|
|
887953 |
int gf_set_timestamp (const char *src, const char* dest);
|
|
|
887953 |
|
|
|
887953 |
int gf_thread_create (pthread_t *thread, const pthread_attr_t *attr,
|
|
|
887953 |
diff --git a/libglusterfs/src/libglusterfs-messages.h b/libglusterfs/src/libglusterfs-messages.h
|
|
|
887953 |
index dd65701..9e35897 100644
|
|
|
887953 |
--- a/libglusterfs/src/libglusterfs-messages.h
|
|
|
887953 |
+++ b/libglusterfs/src/libglusterfs-messages.h
|
|
|
887953 |
@@ -37,7 +37,7 @@
|
|
|
887953 |
|
|
|
887953 |
#define GLFS_LG_BASE GLFS_MSGID_COMP_LIBGLUSTERFS
|
|
|
887953 |
|
|
|
887953 |
-#define GLFS_LG_NUM_MESSAGES 211
|
|
|
887953 |
+#define GLFS_LG_NUM_MESSAGES 212
|
|
|
887953 |
|
|
|
887953 |
#define GLFS_LG_MSGID_END (GLFS_LG_BASE + GLFS_LG_NUM_MESSAGES + 1)
|
|
|
887953 |
/* Messaged with message IDs */
|
|
|
887953 |
@@ -1809,6 +1809,15 @@
|
|
|
887953 |
* @recommendedaction
|
|
|
887953 |
*
|
|
|
887953 |
*/
|
|
|
887953 |
+
|
|
|
887953 |
+#define LG_MSG_XXH64_TO_GFID_FAILED (GLFS_LG_BASE + 212)
|
|
|
887953 |
+
|
|
|
887953 |
+/*!
|
|
|
887953 |
+ * @messageid
|
|
|
887953 |
+ * @diagnosis
|
|
|
887953 |
+ * @recommendedaction
|
|
|
887953 |
+ *
|
|
|
887953 |
+ */
|
|
|
887953 |
/*------------*/
|
|
|
887953 |
|
|
|
887953 |
#define glfs_msg_end_lg GLFS_LG_MSGID_END, "Invalid: End of messages"
|
|
|
887953 |
diff --git a/xlators/features/snapview-server/src/snapview-server-helpers.c b/xlators/features/snapview-server/src/snapview-server-helpers.c
|
|
|
887953 |
index 6f305db..2ad74ef 100644
|
|
|
887953 |
--- a/xlators/features/snapview-server/src/snapview-server-helpers.c
|
|
|
887953 |
+++ b/xlators/features/snapview-server/src/snapview-server-helpers.c
|
|
|
887953 |
@@ -329,18 +329,38 @@ out:
|
|
|
887953 |
return svs_fd;
|
|
|
887953 |
}
|
|
|
887953 |
|
|
|
887953 |
-void
|
|
|
887953 |
-svs_uuid_generate (uuid_t gfid, char *snapname, uuid_t origin_gfid)
|
|
|
887953 |
+int
|
|
|
887953 |
+svs_uuid_generate (xlator_t *this, uuid_t gfid, char *snapname,
|
|
|
887953 |
+ uuid_t origin_gfid)
|
|
|
887953 |
{
|
|
|
887953 |
- unsigned char md5_sum[MD5_DIGEST_LENGTH] = {0};
|
|
|
887953 |
- char ino_string[NAME_MAX + 32] = "";
|
|
|
887953 |
+ char ino_string[NAME_MAX + 32] = "";
|
|
|
887953 |
+ uuid_t tmp = {0,};
|
|
|
887953 |
+ int ret = -1;
|
|
|
887953 |
+
|
|
|
887953 |
+ GF_VALIDATE_OR_GOTO ("snapview-server", this, out);
|
|
|
887953 |
+ GF_VALIDATE_OR_GOTO (this->name, snapname, out);
|
|
|
887953 |
+
|
|
|
887953 |
+ (void)snprintf (ino_string, sizeof (ino_string), "%s%s", snapname,
|
|
|
887953 |
+ uuid_utoa (origin_gfid));
|
|
|
887953 |
+
|
|
|
887953 |
+ if (gf_gfid_generate_from_xxh64 (tmp, ino_string)) {
|
|
|
887953 |
+ gf_log (this->name, GF_LOG_WARNING,
|
|
|
887953 |
+ "failed to generate "
|
|
|
887953 |
+ "gfid for object with actual gfid of %s "
|
|
|
887953 |
+ "(snapname: %s, key: %s)",
|
|
|
887953 |
+ uuid_utoa (origin_gfid), snapname, ino_string);
|
|
|
887953 |
+ goto out;
|
|
|
887953 |
+ }
|
|
|
887953 |
+
|
|
|
887953 |
+ gf_uuid_copy (gfid, tmp);
|
|
|
887953 |
|
|
|
887953 |
- GF_ASSERT (snapname);
|
|
|
887953 |
+ ret = 0;
|
|
|
887953 |
+
|
|
|
887953 |
+ gf_log (this->name, GF_LOG_DEBUG, "gfid generated is %s ",
|
|
|
887953 |
+ uuid_utoa(gfid));
|
|
|
887953 |
|
|
|
887953 |
- (void) snprintf (ino_string, sizeof (ino_string), "%s%s",
|
|
|
887953 |
- snapname, uuid_utoa(origin_gfid));
|
|
|
887953 |
- MD5((unsigned char *)ino_string, strlen(ino_string), md5_sum);
|
|
|
887953 |
- gf_uuid_copy (gfid, md5_sum);
|
|
|
887953 |
+out:
|
|
|
887953 |
+ return ret;
|
|
|
887953 |
}
|
|
|
887953 |
|
|
|
887953 |
void
|
|
|
887953 |
diff --git a/xlators/features/snapview-server/src/snapview-server.c b/xlators/features/snapview-server/src/snapview-server.c
|
|
|
887953 |
index 22b0e1c..7068c5a 100644
|
|
|
887953 |
--- a/xlators/features/snapview-server/src/snapview-server.c
|
|
|
887953 |
+++ b/xlators/features/snapview-server/src/snapview-server.c
|
|
|
887953 |
@@ -330,9 +330,18 @@ svs_lookup_entry (xlator_t *this, loc_t *loc, struct iatt *buf,
|
|
|
887953 |
}
|
|
|
887953 |
|
|
|
887953 |
if (gf_uuid_is_null (loc->gfid) &&
|
|
|
887953 |
- gf_uuid_is_null (loc->inode->gfid))
|
|
|
887953 |
- svs_uuid_generate (gfid, parent_ctx->snapname, object->gfid);
|
|
|
887953 |
- else {
|
|
|
887953 |
+ gf_uuid_is_null (loc->inode->gfid)) {
|
|
|
887953 |
+ if (svs_uuid_generate (this, gfid, parent_ctx->snapname,
|
|
|
887953 |
+ object->gfid)) {
|
|
|
887953 |
+ /*
|
|
|
887953 |
+ * should op_errno be something else such as
|
|
|
887953 |
+ * EINVAL or ESTALE?
|
|
|
887953 |
+ */
|
|
|
887953 |
+ op_ret = -1;
|
|
|
887953 |
+ *op_errno = EIO;
|
|
|
887953 |
+ goto out;
|
|
|
887953 |
+ }
|
|
|
887953 |
+ } else {
|
|
|
887953 |
if (!gf_uuid_is_null (loc->inode->gfid))
|
|
|
887953 |
gf_uuid_copy (gfid, loc->inode->gfid);
|
|
|
887953 |
else
|
|
|
887953 |
diff --git a/xlators/features/snapview-server/src/snapview-server.h b/xlators/features/snapview-server/src/snapview-server.h
|
|
|
887953 |
index a12319f..73524a5 100644
|
|
|
887953 |
--- a/xlators/features/snapview-server/src/snapview-server.h
|
|
|
887953 |
+++ b/xlators/features/snapview-server/src/snapview-server.h
|
|
|
887953 |
@@ -204,8 +204,9 @@ __svs_fd_ctx_get_or_new (xlator_t *this, fd_t *fd);
|
|
|
887953 |
svs_fd_t *
|
|
|
887953 |
svs_fd_ctx_get_or_new (xlator_t *this, fd_t *fd);
|
|
|
887953 |
|
|
|
887953 |
-void
|
|
|
887953 |
-svs_uuid_generate (uuid_t gfid, char *snapname, uuid_t origin_gfid);
|
|
|
887953 |
+int
|
|
|
887953 |
+svs_uuid_generate (xlator_t *this, uuid_t gfid, char *snapname,
|
|
|
887953 |
+ uuid_t origin_gfid);
|
|
|
887953 |
|
|
|
887953 |
void
|
|
|
887953 |
svs_fill_ino_from_gfid (struct iatt *buf);
|
|
|
887953 |
--
|
|
|
887953 |
1.8.3.1
|
|
|
887953 |
|