summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--api/src/glfs-fops.c10
-rw-r--r--api/src/glfs-handleops.c9
-rw-r--r--tests/basic/uss.t50
-rw-r--r--xlators/features/snapview-client/src/snapview-client.c1
-rw-r--r--xlators/features/snapview-server/src/snapview-server.c282
-rw-r--r--xlators/nfs/server/src/nfs3.c4
-rw-r--r--xlators/performance/md-cache/src/md-cache.c19
7 files changed, 268 insertions, 107 deletions
diff --git a/api/src/glfs-fops.c b/api/src/glfs-fops.c
index 535dad3fea1..bc9c758a9c9 100644
--- a/api/src/glfs-fops.c
+++ b/api/src/glfs-fops.c
@@ -2568,11 +2568,14 @@ glfs_listxattr_process (void *value, size_t size, dict_t *xattr)
{
int ret = -1;
- if (!value || !size || !xattr)
+ if (!xattr)
goto out;
ret = dict_keys_join (NULL, 0, xattr, NULL);
+ if (!value || !size)
+ goto out;
+
if (size < ret) {
ret = -1;
errno = ERANGE;
@@ -2580,9 +2583,10 @@ glfs_listxattr_process (void *value, size_t size, dict_t *xattr)
dict_keys_join (value, size, xattr, NULL);
}
- dict_unref (xattr);
-
out:
+ if (xattr)
+ dict_unref (xattr);
+
return ret;
}
diff --git a/api/src/glfs-handleops.c b/api/src/glfs-handleops.c
index e3df8c00b1a..ba468382077 100644
--- a/api/src/glfs-handleops.c
+++ b/api/src/glfs-handleops.c
@@ -15,6 +15,9 @@
#include "glfs.h"
#include "glfs-handles.h"
+int
+glfs_listxattr_process (void *value, size_t size, dict_t *xattr);
+
static void
glfs_iatt_from_stat (struct stat *stat, int valid, struct iatt *iatt,
int *glvalid)
@@ -259,7 +262,11 @@ glfs_h_getxattrs (struct glfs *fs, struct glfs_object *object, const char *name,
if (ret)
goto out;
- ret = glfs_getxattr_process (value, size, xattr, name);
+ /* If @name is NULL, means get all the xattrs (i.e listxattr). */
+ if (name)
+ ret = glfs_getxattr_process (value, size, xattr, name);
+ else
+ ret = glfs_listxattr_process (value, size, xattr);
out:
loc_wipe (&loc);
diff --git a/tests/basic/uss.t b/tests/basic/uss.t
index 004395660b5..8c6a8982eea 100644
--- a/tests/basic/uss.t
+++ b/tests/basic/uss.t
@@ -101,27 +101,27 @@ TEST fd_close $fd3
# test 44
TEST mount_nfs $H0:/$V0 $N0 nolock;
-TEST ls $N0/.snaps;
+TEST ls -l $N0/.snaps;
NUM_SNAPS=$(ls $N0/.snaps | wc -l);
TEST [ $NUM_SNAPS == 4 ];
-TEST ls $N0/.snaps/snap1;
-TEST ls $N0/.snaps/snap2;
-TEST ls $N0/.snaps/snap3;
-TEST ls $N0/.snaps/snap4;
+TEST ls -l $N0/.snaps/snap1;
+TEST ls -l $N0/.snaps/snap2;
+TEST ls -l $N0/.snaps/snap3;
+TEST ls -l $N0/.snaps/snap4;
-TEST ls $N0/.snaps/snap3/dir1;
-TEST ls $N0/.snaps/snap3/dir2;
+TEST ls -l $N0/.snaps/snap3/dir1;
+TEST ls -l $N0/.snaps/snap3/dir2;
-TEST ls $N0/.snaps/snap4/dir1;
-TEST ls $N0/.snaps/snap4/dir2;
+TEST ls -l $N0/.snaps/snap4/dir1;
+TEST ls -l $N0/.snaps/snap4/dir2;
-TEST ! ls $N0/dir1/.snaps/snap1;
-TEST ! ls $N0/dir2/.snaps/snap2;
-TEST ls $N0/dir1/.snaps/snap3;
-TEST ls $N0/dir2/.snaps/snap4;
+TEST ! ls -l $N0/dir1/.snaps/snap1;
+TEST ! ls -l $N0/dir2/.snaps/snap2;
+TEST ls -l $N0/dir1/.snaps/snap3;
+TEST ls -l $N0/dir2/.snaps/snap4;
TEST fd1=`fd_available`
TEST fd_open $fd1 'r' $N0/.snaps/snap1/file1;
@@ -205,21 +205,21 @@ NUM_SNAPS=$(ls $N0/.history | wc -l);
TEST [ $NUM_SNAPS == 4 ];
-TEST ls $N0/.history/snap1;
-TEST ls $N0/.history/snap2;
-TEST ls $N0/.history/snap3;
-TEST ls $N0/.history/snap4;
+TEST ls -l $N0/.history/snap1;
+TEST ls -l $N0/.history/snap2;
+TEST ls -l $N0/.history/snap3;
+TEST ls -l $N0/.history/snap4;
-TEST ls $N0/.history/snap3/dir1;
-TEST ls $N0/.history/snap3/dir2;
+TEST ls -l $N0/.history/snap3/dir1;
+TEST ls -l $N0/.history/snap3/dir2;
-TEST ls $N0/.history/snap4/dir1;
-TEST ls $N0/.history/snap4/dir2;
+TEST ls -l $N0/.history/snap4/dir1;
+TEST ls -l $N0/.history/snap4/dir2;
-TEST ! ls $N0/dir1/.history/snap1;
-TEST ! ls $N0/dir2/.history/snap2;
-TEST ls $N0/dir1/.history/snap3;
-TEST ls $N0/dir2/.history/snap4;
+TEST ! ls -l $N0/dir1/.history/snap1;
+TEST ! ls -l $N0/dir2/.history/snap2;
+TEST ls -l $N0/dir1/.history/snap3;
+TEST ls -l $N0/dir2/.history/snap4;
TEST fd1=`fd_available`
TEST fd_open $fd1 'r' $N0/.history/snap1/file1;
diff --git a/xlators/features/snapview-client/src/snapview-client.c b/xlators/features/snapview-client/src/snapview-client.c
index 344a8c9562a..ad022101715 100644
--- a/xlators/features/snapview-client/src/snapview-client.c
+++ b/xlators/features/snapview-client/src/snapview-client.c
@@ -161,6 +161,7 @@ svc_lookup_cbk (call_frame_t *frame, void *cookie, xlator_t *this,
do_unwind = _gf_false;
}
}
+
gf_log (this->name, GF_LOG_WARNING,
"Lookup on normal graph failed");
goto out;
diff --git a/xlators/features/snapview-server/src/snapview-server.c b/xlators/features/snapview-server/src/snapview-server.c
index 47344113406..99965a4ccef 100644
--- a/xlators/features/snapview-server/src/snapview-server.c
+++ b/xlators/features/snapview-server/src/snapview-server.c
@@ -1627,18 +1627,73 @@ out:
return 0;
}
+/*
+ * This function adds the xattr keys present in the list (@list) to the dict.
+ * But the list contains only the names of the xattrs (and no value, as
+ * the gfapi functions for the listxattr operations would return only the
+ * names of the xattrs in the buffer provided by the caller, though they had
+ * got the values of those xattrs from posix) as described in the man page of
+ * listxattr. But before unwinding snapview-server has to put those names
+ * back into the dict. But to get the values for those xattrs it has to do the
+ * getxattr operation on each xattr which might turn out to be a costly
+ * operation. So for each of the xattrs present in the list, a 0 byte value
+ * ("") is set into the dict before unwinding. This can be treated as an
+ * indicator to other xlators which want to cache the xattrs (as of now,
+ * md-cache which caches acl and selinux related xattrs) to not to cache the
+ * values of the xattrs present in the dict.
+ */
+int32_t
+svs_add_xattrs_to_dict (xlator_t *this, dict_t *dict, char *list, ssize_t size)
+{
+ char keybuffer[4096] = {0,};
+ size_t remaining_size = 0;
+ int32_t list_offset = 0;
+ int32_t ret = -1;
+
+ GF_VALIDATE_OR_GOTO ("snapview-daemon", this, out);
+ GF_VALIDATE_OR_GOTO (this->name, dict, out);
+ GF_VALIDATE_OR_GOTO (this->name, list, out);
+
+ remaining_size = size;
+ list_offset = 0;
+ while (remaining_size > 0) {
+ strcpy (keybuffer, list + list_offset);
+#ifdef GF_DARWIN_HOST_OS
+ /* The protocol expect namespace for now */
+ char *newkey = NULL;
+ gf_add_prefix (XATTR_USER_PREFIX, keybuffer, &newkey);
+ strcpy (keybuffer, newkey);
+ GF_FREE (newkey);
+#endif
+ ret = dict_set_str (dict, keybuffer, "");
+ if (ret < 0) {
+ gf_log (this->name, GF_LOG_ERROR, "dict set operation "
+ "for the key %s failed.", keybuffer);
+ goto out;
+ }
+
+ remaining_size -= strlen (keybuffer) + 1;
+ list_offset += strlen (keybuffer) + 1;
+ } /* while (remaining_size > 0) */
+
+ ret = 0;
+
+out:
+ return ret;
+}
+
int32_t
svs_getxattr (call_frame_t *frame, xlator_t *this, loc_t *loc, const char *name,
dict_t *xdata)
{
- svs_inode_t *inode_ctx = NULL;
- int32_t op_ret = -1;
- int32_t op_errno = EINVAL;
- glfs_t *fs = NULL;
- glfs_object_t *object = NULL;
- char *value = 0;
- ssize_t size = 0;
- dict_t *dict = NULL;
+ svs_inode_t *inode_ctx = NULL;
+ int32_t op_ret = -1;
+ int32_t op_errno = EINVAL;
+ glfs_t *fs = NULL;
+ glfs_object_t *object = NULL;
+ char *value = 0;
+ ssize_t size = 0;
+ dict_t *dict = NULL;
GF_VALIDATE_OR_GOTO ("snap-view-daemon", this, out);
GF_VALIDATE_OR_GOTO ("snap-view-daemon", frame, out);
@@ -1654,8 +1709,11 @@ svs_getxattr (call_frame_t *frame, xlator_t *this, loc_t *loc, const char *name,
goto out;
}
- /* Fake success is sent if the getxattr is on entry point directory
- or the inode is SNAP_VIEW_ENTRY_POINT_INODE
+ /* EINVAL is sent if the getxattr is on entry point directory
+ or the inode is SNAP_VIEW_ENTRY_POINT_INODE. Entry point is
+ a virtual directory on which setxattr operations are not
+ allowed. If getxattr has to be faked as success, then a value
+ for the name of the xattr has to be sent which we dont have.
*/
if (inode_ctx->type == SNAP_VIEW_ENTRY_POINT_INODE) {
op_ret = -1;
@@ -1664,19 +1722,30 @@ svs_getxattr (call_frame_t *frame, xlator_t *this, loc_t *loc, const char *name,
} else if (inode_ctx->type == SNAP_VIEW_VIRTUAL_INODE) {
fs = inode_ctx->fs;
object = inode_ctx->object;
+ dict = dict_new ();
+ if (!dict) {
+ gf_log (this->name, GF_LOG_ERROR, "failed to "
+ "allocate dict");
+ op_ret = -1;
+ op_errno = ENOMEM;
+ goto out;
+ }
+
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, GF_LOG_ERROR, "getxattr "
+ "on %s failed (key: %s)", loc->name,
+ name);
op_ret = -1;
op_errno = errno;
goto out;
}
- value = GF_CALLOC (size + 1, sizeof (char), gf_common_mt_char);
+ value = GF_CALLOC (size + 1, sizeof (char),
+ gf_common_mt_char);
if (!value) {
- gf_log (this->name, GF_LOG_ERROR, "failed to allocate "
- "memory for getxattr on %s (key: %s)",
- loc->name, name);
+ gf_log (this->name, GF_LOG_ERROR, "failed to "
+ "allocate memory for getxattr on %s "
+ "(key: %s)", loc->name, name);
op_ret = -1;
op_errno = ENOMEM;
goto out;
@@ -1684,35 +1753,38 @@ svs_getxattr (call_frame_t *frame, xlator_t *this, loc_t *loc, const char *name,
size = glfs_h_getxattrs (fs, object, name, value, size);
if (size == -1) {
- gf_log (this->name, GF_LOG_ERROR, "failed to get the "
- "xattr %s for entry %s", name, loc->name);
+ gf_log (this->name, GF_LOG_ERROR, "failed to "
+ "get the xattr %s for entry %s", name,
+ loc->name);
op_ret = -1;
op_errno = errno;
goto out;
}
value[size] = '\0';
- dict = dict_new ();
- if (!dict) {
- gf_log (this->name, GF_LOG_ERROR, "failed to allocate "
- "dict");
- op_ret = -1;
- op_errno = ENOMEM;
- goto out;
- }
-
- op_ret = dict_set_dynptr (dict, (char *)name, value, size);
- if (op_ret < 0) {
- op_errno = -op_ret;
- gf_log (this->name, GF_LOG_ERROR, "dict set operation "
- "for %s for the key %s failed.", loc->path,
- name);
+ if (name) {
+ op_ret = dict_set_dynptr (dict, (char *)name, value,
+ size);
+ if (op_ret < 0) {
+ op_errno = -op_ret;
+ gf_log (this->name, GF_LOG_ERROR, "dict set "
+ "operation for %s for the key %s "
+ "failed.", loc->path, name);
+ GF_FREE (value);
+ value = NULL;
+ goto out;
+ }
+ } else {
+ op_ret = svs_add_xattrs_to_dict (this, dict, value,
+ size);
+ if (op_ret == -1) {
+ gf_log (this->name, GF_LOG_ERROR, "failed to "
+ "add the xattrs from the list to dict");
+ op_errno = ENOMEM;
+ goto out;
+ }
GF_FREE (value);
- goto out;
}
-
- op_ret = 0;
- op_errno = 0;
}
out:
@@ -1721,6 +1793,9 @@ out:
STACK_UNWIND_STRICT (getxattr, frame, op_ret, op_errno, dict, NULL);
+ if (dict)
+ dict_unref (dict);
+
return 0;
}
@@ -1761,8 +1836,11 @@ svs_fgetxattr (call_frame_t *frame, xlator_t *this, fd_t *fd, const char *name,
}
glfd = sfd->fd;
- /* Fake success is sent if the getxattr is on entry point directory
- or the inode is SNAP_VIEW_ENTRY_POINT_INODE
+ /* EINVAL is sent if the getxattr is on entry point directory
+ or the inode is SNAP_VIEW_ENTRY_POINT_INODE. Entry point is
+ a virtual directory on which setxattr operations are not
+ allowed. If getxattr has to be faked as success, then a value
+ for the name of the xattr has to be sent which we dont have.
*/
if (inode_ctx->type == SNAP_VIEW_ENTRY_POINT_INODE) {
op_ret = -1;
@@ -1771,53 +1849,98 @@ svs_fgetxattr (call_frame_t *frame, xlator_t *this, fd_t *fd, const char *name,
}
if (inode_ctx->type == SNAP_VIEW_VIRTUAL_INODE) {
- size = glfs_fgetxattr (glfd, name, NULL, 0);
- if (size == -1) {
- gf_log (this->name, GF_LOG_ERROR, "getxattr on %s "
- "failed (key: %s)", uuid_utoa (fd->inode->gfid),
- name);
- op_ret = -1;
- op_errno = errno;
- goto out;
- }
- value = GF_CALLOC (size + 1, sizeof (char), gf_common_mt_char);
- if (!value) {
- gf_log (this->name, GF_LOG_ERROR, "failed to allocate "
- "memory for getxattr on %s (key: %s)",
- uuid_utoa (fd->inode->gfid), name);
- op_ret = -1;
- op_errno = ENOMEM;
- goto out;
- }
-
- size = glfs_fgetxattr (glfd, name, value, size);
- if (size == -1) {
- gf_log (this->name, GF_LOG_ERROR, "failed to get the "
- "xattr %s for inode %s", name,
- uuid_utoa (fd->inode->gfid));
- op_ret = -1;
- op_errno = errno;
- goto out;
- }
- value[size] = '\0';
-
dict = dict_new ();
if (!dict) {
- gf_log (this->name, GF_LOG_ERROR, "failed to allocate "
- "dict");
+ gf_log (this->name, GF_LOG_ERROR, "failed to "
+ "allocate dict");
op_ret = -1;
op_errno = ENOMEM;
goto out;
}
- op_ret = dict_set_dynptr (dict, (char *)name, value, size);
- if (op_ret < 0) {
- op_errno = -op_ret;
- gf_log (this->name, GF_LOG_ERROR, "dict set operation "
- "for gfid %s for the key %s failed.",
- uuid_utoa (fd->inode->gfid), name);
+ if (name) {
+ size = glfs_fgetxattr (glfd, name, NULL, 0);
+ if (size == -1) {
+ gf_log (this->name, GF_LOG_ERROR, "getxattr on "
+ "%s failed (key: %s)",
+ uuid_utoa (fd->inode->gfid), name);
+ op_ret = -1;
+ op_errno = errno;
+ goto out;
+ }
+ value = GF_CALLOC (size + 1, sizeof (char),
+ gf_common_mt_char);
+ if (!value) {
+ gf_log (this->name, GF_LOG_ERROR, "failed to "
+ "allocate memory for getxattr on %s "
+ "(key: %s)",
+ uuid_utoa (fd->inode->gfid), name);
+ op_ret = -1;
+ op_errno = ENOMEM;
+ goto out;
+ }
+
+ size = glfs_fgetxattr (glfd, name, value, size);
+ if (size == -1) {
+ gf_log (this->name, GF_LOG_ERROR, "failed to "
+ "get the xattr %s for inode %s", name,
+ uuid_utoa (fd->inode->gfid));
+ op_ret = -1;
+ op_errno = errno;
+ goto out;
+ }
+ value[size] = '\0';
+
+ op_ret = dict_set_dynptr (dict, (char *)name, value,
+ size);
+ if (op_ret < 0) {
+ op_errno = -op_ret;
+ gf_log (this->name, GF_LOG_ERROR, "dict set "
+ "operation for gfid %s for the key %s "
+ "failed.",
+ uuid_utoa (fd->inode->gfid), name);
+ GF_FREE (value);
+ goto out;
+ }
+ } else {
+ size = glfs_flistxattr (glfd, NULL, 0);
+ if (size == -1) {
+ gf_log (this->name, GF_LOG_ERROR, "listxattr "
+ "on %s failed",
+ uuid_utoa (fd->inode->gfid));
+ goto out;
+ }
+
+ value = GF_CALLOC (size + 1, sizeof (char),
+ gf_common_mt_char);
+ if (!value) {
+ op_ret = -1;
+ op_errno = ENOMEM;
+ gf_log (this->name, GF_LOG_ERROR, "failed to "
+ "allocate buffer for xattr list (%s)",
+ uuid_utoa (fd->inode->gfid));
+ goto out;
+ }
+
+ size = glfs_flistxattr (glfd, value, size);
+ if (size == -1) {
+ op_ret = -1;
+ op_errno = errno;
+ gf_log (this->name, GF_LOG_ERROR, "listxattr "
+ "on %s failed",
+ uuid_utoa (fd->inode->gfid));
+ goto out;
+ }
+
+ op_ret = svs_add_xattrs_to_dict (this, dict, value,
+ size);
+ if (op_ret == -1) {
+ gf_log (this->name, GF_LOG_ERROR, "failed to "
+ "add the xattrs from the list to dict");
+ op_errno = ENOMEM;
+ goto out;
+ }
GF_FREE (value);
- goto out;
}
op_ret = 0;
@@ -1830,6 +1953,9 @@ out:
STACK_UNWIND_STRICT (fgetxattr, frame, op_ret, op_errno, dict, NULL);
+ if (dict)
+ dict_unref (dict);
+
return 0;
}
diff --git a/xlators/nfs/server/src/nfs3.c b/xlators/nfs/server/src/nfs3.c
index 6361f9e20aa..7ecfc675b61 100644
--- a/xlators/nfs/server/src/nfs3.c
+++ b/xlators/nfs/server/src/nfs3.c
@@ -4099,6 +4099,10 @@ nfs3svc_readdir_fstat_cbk (call_frame_t *frame, void *cookie, xlator_t *this,
}
stat = NFS3_OK;
+
+ /* do inode linking here */
+ gf_link_inodes_from_dirent (this, cs->fd->inode, &cs->entries);
+
nfs3err:
if (cs->maxcount == 0) {
nfs3_log_readdir_res (rpcsvc_request_xid (cs->req), stat,
diff --git a/xlators/performance/md-cache/src/md-cache.c b/xlators/performance/md-cache/src/md-cache.c
index 7588463b891..782d258f47c 100644
--- a/xlators/performance/md-cache/src/md-cache.c
+++ b/xlators/performance/md-cache/src/md-cache.c
@@ -486,6 +486,25 @@ updatefn(dict_t *dict, char *key, data_t *value, void *data)
}
}
+ /* posix xlator as part of listxattr will send both names
+ * and values of the xattrs in the dict. But as per man page
+ * listxattr is mainly supposed to send names of the all the
+ * xattrs. gfapi, as of now will put all the keys it obtained
+ * in the dict (sent by posix) into a buffer provided by the
+ * caller (thus the values of those xattrs are lost). If some
+ * xlator makes gfapi based calls (ex: snapview-server), then
+ * it has to unwind the calls by putting those names it got
+ * in the buffer again into the dict. But now it would not be
+ * having the values for those xattrs. So it might just put
+ * a 0 byte value ("") into the dict for each xattr and unwind
+ * the call. So the xlators which cache the xattrs (as of now
+ * md-cache caches the acl and selinux related xattrs), should
+ * not update their cache if the value of a xattr is a 0 byte
+ * data (i.e. "").
+ */
+ if (!strcmp (value->data, ""))
+ continue;
+
if (dict_set(u->dict, key, value) < 0) {
u->ret = -1;
return -1;