From 54ebd47e4154c8b37680b2bac43775fc92ced153 Mon Sep 17 00:00:00 2001 From: Kotresh HR Date: Sat, 17 Nov 2018 13:14:24 +0530 Subject: geo-rep: Fix syncing of files with non-ascii filenames Problem: Creation of files/directories with non-ascii names fails to sync to the slave. It crashes with below traceback on slave. ... File "/usr/lib/x86_64-linux-gnu/glusterfs/python/syncdaemon/repce.py", line 118, in worker res = getattr(self.obj, rmeth)(*in_data[2:]) File "/usr/lib/x86_64-linux-gnu/glusterfs/python/syncdaemon/resource.py", line 709, in entry_ops [ESTALE, EINVAL, EBUSY]) File "/usr/lib/x86_64-linux-gnu/glusterfs/python/syncdaemon/syncdutils.py", line 546, in errno_wrap return call(*arg) File "/usr/lib/x86_64-linux-gnu/glusterfs/python/syncdaemon/libcxattr.py", line 83, in lsetxattr cls.raise_oserr() File "/usr/lib/x86_64-linux-gnu/glusterfs/python/syncdaemon/libcxattr.py", line 38, in raise_oserr raise OSError(errn, os.strerror(errn)) OSError: [Errno 12] Cannot allocate memory Cause: The length calculation arguments passed to blob creation was done before encoding. Hence was failing in gfid-access layer. Fix: It appears that the calculating lenght properly fixes this issue. But it will cause issues in other places in 'python2' and not in 'python3'. So encoding and decoding each required string to make geo-rep compatible with both 'python2' and 'python3' is a nightmare and is not fool proof. Hence kept 'python2' code as is with out encode/decode and applied encode/decode only to 'python3' Added non-ascii filename tests to regression fixes: bz#1650893 Change-Id: I35cfaf848e07b1a0b5cb93c01b98b472f08271a6 Signed-off-by: Kotresh HR --- geo-replication/syncdaemon/libgfchangelog.py | 30 +++++++++++++++------------- 1 file changed, 16 insertions(+), 14 deletions(-) (limited to 'geo-replication/syncdaemon/libgfchangelog.py') diff --git a/geo-replication/syncdaemon/libgfchangelog.py b/geo-replication/syncdaemon/libgfchangelog.py index cc40fd5475d..fff9d24e54f 100644 --- a/geo-replication/syncdaemon/libgfchangelog.py +++ b/geo-replication/syncdaemon/libgfchangelog.py @@ -9,9 +9,10 @@ # import os -from ctypes import CDLL, RTLD_GLOBAL, create_string_buffer, \ - get_errno, byref, c_ulong +from ctypes import CDLL, RTLD_GLOBAL, get_errno, byref, c_ulong from syncdutils import ChangelogException, ChangelogHistoryNotAvailable +from py2py3 import gr_cl_history_changelog, gr_cl_done, gr_create_string_buffer +from py2py3 import gr_cl_register, gr_cl_history_done, bytearray_to_str class Changes(object): @@ -39,9 +40,7 @@ class Changes(object): @classmethod def cl_register(cls, brick, path, log_file, log_level, retries=0): - ret = cls._get_api('gf_changelog_register')(brick.encode(), path.encode(), - log_file.encode(), - log_level, retries) + ret = gr_cl_register(cls, brick, path, log_file, log_level, retries) if ret == -1: cls.raise_changelog_err() @@ -63,14 +62,16 @@ class Changes(object): def clsort(f): return f.split('.')[-1] changes = [] - buf = create_string_buffer(b'\0' * 4096) + buf = gr_create_string_buffer(4096) call = cls._get_api('gf_changelog_next_change') while True: ret = call(buf, 4096) if ret in (0, -1): break - changes.append(buf.raw[:ret - 1].decode()) + # py2 and py3 compatibility + result = bytearray_to_str(buf.raw[:ret - 1]) + changes.append(result) if ret == -1: cls.raise_changelog_err() # cleanup tracker @@ -79,7 +80,7 @@ class Changes(object): @classmethod def cl_done(cls, clfile): - ret = cls._get_api('gf_changelog_done')(clfile.encode()) + ret = gr_cl_done(cls, clfile) if ret == -1: cls.raise_changelog_err() @@ -94,9 +95,8 @@ class Changes(object): @classmethod def cl_history_changelog(cls, changelog_path, start, end, num_parallel): actual_end = c_ulong() - ret = cls._get_api('gf_history_changelog')(changelog_path.encode(), start, end, - num_parallel, - byref(actual_end)) + ret = gr_cl_history_changelog(cls, changelog_path, start, end, + num_parallel, byref(actual_end)) if ret == -1: cls.raise_changelog_err() @@ -118,14 +118,16 @@ class Changes(object): return f.split('.')[-1] changes = [] - buf = create_string_buffer(b'\0' * 4096) + buf = gr_create_string_buffer(4096) call = cls._get_api('gf_history_changelog_next_change') while True: ret = call(buf, 4096) if ret in (0, -1): break - changes.append(buf.raw[:ret - 1].decode()) + # py2 and py3 compatibility + result = bytearray_to_str(buf.raw[:ret - 1]) + changes.append(result) if ret == -1: cls.raise_changelog_err() @@ -133,6 +135,6 @@ class Changes(object): @classmethod def cl_history_done(cls, clfile): - ret = cls._get_api('gf_history_changelog_done')(clfile.encode()) + ret = gr_cl_history_done(cls, clfile) if ret == -1: cls.raise_changelog_err() -- cgit