]> git.apps.os.sepia.ceph.com Git - ceph.git/commitdiff
mgr/volumes: synchronize inode attributes for cloned subvolumes
authorVenky Shankar <vshankar@redhat.com>
Fri, 7 Feb 2020 05:26:03 +0000 (00:26 -0500)
committerRamana Raja <rraja@redhat.com>
Mon, 16 Mar 2020 09:47:52 +0000 (15:17 +0530)
Synchronize ownership, permission and inode timestamp (access and
modification times) for all supported inode types. Note that inode
timestamps are synchronized upto seconds granularity.

Signed-off-by: Venky Shankar <vshankar@redhat.com>
(cherry picked from commit aac6b5f1cef7d055bdde797519aece779d06fb41)

 Conflicts:
src/pybind/mgr/volumes/fs/async_cloner.py
        - uid and gid arguments of chown() and copy_file() were
          type converted to `int` for nautilus.

src/pybind/mgr/volumes/fs/async_cloner.py
src/pybind/mgr/volumes/fs/fs_util.py

index 88dac61b74be51da75bce1c1edb3dece3b4d367d..6d25ebae53001e108aaebc838efb63da4c9e9dff 100644 (file)
@@ -72,6 +72,15 @@ def handle_clone_pending(volume_client, volname, index, groupname, subvolname, s
         raise VolumeException(oe.error, oe.error_str)
     return (next_state, False)
 
+def sync_attrs(fs_handle, target_path, source_statx):
+    try:
+        fs_handle.lchown(target_path, source_statx["uid"], source_statx["gid"])
+        fs_handle.lutimes(target_path, (time.mktime(source_statx["atime"].timetuple()),
+                                        time.mktime(source_statx["mtime"].timetuple())))
+    except cephfs.Error as e:
+        log.warn("error synchronizing attrs for {0} ({1})".format(target_path, e))
+        raise e
+
 def bulk_copy(fs_handle, source_path, dst_path, should_cancel):
     """
     bulk copy data from source to destination -- only directories, symlinks
@@ -90,31 +99,45 @@ def bulk_copy(fs_handle, source_path, dst_path, should_cancel):
                         log.debug("d={0}".format(d))
                         d_full_src = os.path.join(src_root_path, d.d_name)
                         d_full_dst = os.path.join(dst_root_path, d.d_name)
-                        st = fs_handle.lstat(d_full_src)
-                        mo = st.st_mode & ~stat.S_IFMT(st.st_mode)
-                        if stat.S_ISDIR(st.st_mode):
+                        stx = fs_handle.statx(d_full_src, cephfs.CEPH_STATX_MODE  |
+                                                          cephfs.CEPH_STATX_UID   |
+                                                          cephfs.CEPH_STATX_GID   |
+                                                          cephfs.CEPH_STATX_ATIME |
+                                                          cephfs.CEPH_STATX_MTIME |
+                                                          cephfs.CEPH_STATX_SIZE,
+                                                          cephfs.AT_SYMLINK_NOFOLLOW)
+                        handled = True
+                        mo = stx["mode"] & ~stat.S_IFMT(stx["mode"])
+                        if stat.S_ISDIR(stx["mode"]):
                             log.debug("cptree: (DIR) {0}".format(d_full_src))
                             try:
                                 fs_handle.mkdir(d_full_dst, mo)
-                                fs_handle.chown(d_full_dst, int(st.st_uid), int(st.st_gid))
                             except cephfs.Error as e:
                                 if not e.args[0] == errno.EEXIST:
                                     raise
                             cptree(d_full_src, d_full_dst)
-                        elif stat.S_ISLNK(st.st_mode):
+                        elif stat.S_ISLNK(stx["mode"]):
                             log.debug("cptree: (SYMLINK) {0}".format(d_full_src))
                             target = fs_handle.readlink(d_full_src, 4096)
                             try:
-                                fs_handle.symlink(target[:st.st_size], d_full_dst)
+                                fs_handle.symlink(target[:stx["size"]], d_full_dst)
                             except cephfs.Error as e:
                                 if not e.args[0] == errno.EEXIST:
                                     raise
-                        elif stat.S_ISREG(st.st_mode):
+                        elif stat.S_ISREG(stx["mode"]):
                             log.debug("cptree: (REG) {0}".format(d_full_src))
-                            copy_file(fs_handle, d_full_src, d_full_dst, mo, int(st.st_uid), int(st.st_gid))
+                            copy_file(fs_handle, d_full_src, d_full_dst, mo)
                         else:
+                            handled = False
                             log.warn("cptree: (IGNORE) {0}".format(d_full_src))
+                        if handled:
+                            sync_attrs(fs_handle, d_full_dst, stx)
                     d = fs_handle.readdir(dir_handle)
+                stx_root = fs_handle.statx(src_root_path, cephfs.CEPH_STATX_ATIME |
+                                                          cephfs.CEPH_STATX_MTIME,
+                                                          cephfs.AT_SYMLINK_NOFOLLOW)
+                fs_handle.lutimes(dst_root_path, (time.mktime(stx_root["atime"].timetuple()),
+                                                  time.mktime(stx_root["mtime"].timetuple())))
         except cephfs.Error as e:
             if not e.args[0] == errno.ENOENT:
                 raise VolumeException(-e.args[0], e.args[1])
index 7dd116e5fb3581477a25cab67ba321748391ea69..524f56a2ab0f24bccefae5917ab86403013425fd 100644 (file)
@@ -86,7 +86,7 @@ def list_one_entry_at_a_time(fs, dirpath):
     except cephfs.Error as e:
         raise VolumeException(-e.args[0], e.args[1])
 
-def copy_file(fs, src, dst, mode, uid, gid):
+def copy_file(fs, src, dst, mode):
     """
     Copy a regular file from @src to @dst. @dst is overwritten if it exists.
     """
@@ -94,7 +94,6 @@ def copy_file(fs, src, dst, mode, uid, gid):
     try:
         src_fd = fs.open(src, os.O_RDONLY);
         dst_fd = fs.open(dst, os.O_CREAT | os.O_TRUNC | os.O_WRONLY, mode)
-        fs.chown(dst, uid, gid)
     except cephfs.Error as e:
         if src_fd is not None:
             fs.close(src_fd)