From 656a0e64e5f465561ed29297421ec150de32f2a1 Mon Sep 17 00:00:00 2001 From: Aravinda VK Date: Tue, 29 Dec 2015 11:20:39 +0530 Subject: geo-rep: Handle ERANGE error during listxattr llistxattr in Geo-rep is two syscall instead of one SIZE = llistxattr(PATH, &BUF, 0); BUF = create_buf(SIZE); _ = llistxattr(PATH, &BUF, SIZE); So if any new xattrs added just after first call by any other worker, second syscall will fail with ERANGE error. Now Geo-rep sends BUF with large size(256*100) and gets value with only one syscall. Raises OSError if fails with ERANGE error even after sending large BUF. Change-Id: I8ade4bbe9a0a8ea908ed9dedcd3f2ff4c6fe6f51 Signed-off-by: Aravinda VK BUG: 1294588 Reviewed-on: http://review.gluster.org/13106 Smoke: Gluster Build System NetBSD-regression: NetBSD Build System CentOS-regression: Gluster Build System Reviewed-by: Kotresh HR --- geo-replication/syncdaemon/libcxattr.py | 28 +++++++++++++++++++++------- 1 file changed, 21 insertions(+), 7 deletions(-) (limited to 'geo-replication') diff --git a/geo-replication/syncdaemon/libcxattr.py b/geo-replication/syncdaemon/libcxattr.py index b69773df469..553d8f13424 100644 --- a/geo-replication/syncdaemon/libcxattr.py +++ b/geo-replication/syncdaemon/libcxattr.py @@ -68,7 +68,8 @@ class Xattr(object): def llistxattr(cls, path, siz=0): ret = cls._query_xattr(path, siz, 'llistxattr') if isinstance(ret, str): - ret = ret.split('\0') + ret = ret.strip('\0') + ret = ret.split('\0') if ret else [] return ret @classmethod @@ -86,9 +87,22 @@ class Xattr(object): @classmethod def llistxattr_buf(cls, path): """listxattr variant with size discovery""" - size = cls.llistxattr(path) - if size == -1: - cls.raise_oserr() - if size == 0: - return [] - return cls.llistxattr(path, size) + try: + # Assuming no more than 100 xattrs in a file/directory and + # each xattr key length will be less than 256 bytes + # llistxattr will be called with bigger size so that + # listxattr will not fail with ERANGE. OSError will be + # raised if fails even with the large size specified. + size = 256 * 100 + return cls.llistxattr(path, size) + except OSError: + # If fixed length failed for getting list of xattrs then + # use the llistxattr call to get the size and use that + # size to get the list of xattrs. + size = cls.llistxattr(path) + if size == -1: + cls.raise_oserr() + if size == 0: + return [] + + return cls.llistxattr(path, size) -- cgit