diff options
-rw-r--r-- | api/src/glfs-fops.c | 10 | ||||
-rw-r--r-- | api/src/glfs-handleops.c | 9 | ||||
-rw-r--r-- | tests/basic/uss.t | 50 | ||||
-rw-r--r-- | xlators/features/snapview-client/src/snapview-client.c | 1 | ||||
-rw-r--r-- | xlators/features/snapview-server/src/snapview-server.c | 282 | ||||
-rw-r--r-- | xlators/nfs/server/src/nfs3.c | 4 | ||||
-rw-r--r-- | xlators/performance/md-cache/src/md-cache.c | 19 |
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; |