<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=us-ascii">
</head>
<body style="word-wrap: break-word; -webkit-nbsp-mode: space; line-break: after-white-space;" class="">
On Feb 27, 2023, at 11:57, Grigory Shamov &lt;<a href="mailto:Grigory.Shamov@umanitoba.ca" class="">Grigory.Shamov@umanitoba.ca</a>&gt; wrote:<br class="">
<div>
<blockquote type="cite" class=""><br class="Apple-interchange-newline">
<div class="">
<div class="">Hi All,<br class="">
<br class="">
What happens if a directory on Lustre FS gets moved with a regular CentOS7 mv command, within the same filesystem? On CentOS 7, using mv from the distro, like this, as root:<br class="">
<br class="">
mv /project/TEMP/user &nbsp;/project/XYZ/user<br class="">
<br class="">
It looks like the content gets copied entirely. Which for large data takes a large amount of time.<br class="">
Is there a way to rename the Lustre directories (changing the name of the top directory, only without moving every object in these directories)? &nbsp;Thanks!<br class="">
</div>
</div>
</blockquote>
<br class="">
</div>
<div>Renaming a file or subdirectory tree between &quot;regular&quot; directories in Lustre works as you would expect for a local filesystem, even if the directories are on different MDTs. &nbsp;What you are seeing (full copy of contents between directories) is really a result
 of the implementation/design of project quotas, and not directly a Lustre problem. &nbsp;The same would happen if you have two directories using two different project IDs and the &quot;PROJINHERIT&quot; flag set with ext4 or XFS, since they also return &quot;-EXDEV&quot; if trying
 to move (rename) a file between directories that do not have the same project ID, and that causes &quot;mv&quot; to copy the whole directory tree.</div>
<div><br class="">
</div>
<div>Running the ext4 &quot;mv&quot; under strace shows this:</div>
<div><br class="">
</div>
<div>&nbsp; &nbsp; # df -T /mnt/tmp</div>
&nbsp; &nbsp; Filesystem&nbsp;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;&nbsp;Type 1K-blocks&nbsp;&nbsp;Used Available Use% Mounted on<br class="">
&nbsp; &nbsp; /dev/mapper/vg_test-lvtest ext4&nbsp;&nbsp;16337788&nbsp; &nbsp;&nbsp;52&nbsp;&nbsp;15482492&nbsp;&nbsp;&nbsp;1% /mnt/tmp
<div class="">&nbsp; &nbsp; # mkdir /mnt/tmp/{dir1,dir2}</div>
<div class="">&nbsp; &nbsp; # chattr -P -p 1000 /mnt/tmp/dir1</div>
<div class="">&nbsp; &nbsp; # chattr -P -p 2000 /mnt/tmp/dir2</div>
<div class="">&nbsp; &nbsp; # cp /etc/hosts /mnt/tmp/dir1</div>
<div class="">&nbsp; &nbsp; # lsattr /mnt/tmp/dir1<br class="">
&nbsp; &nbsp; --------------e----P-- /mnt/tmp/dir1/hosts</div>
<div class="">&nbsp; &nbsp; # ls -li /mnt/tmp/dir1<br class="">
&nbsp; &nbsp; total 8<br class="">
&nbsp; &nbsp; 655365 8 -rw-r--r--. 1 root root 7424 Oct 18 22:42 hosts</div>
<div class="">&nbsp; &nbsp; # strace mv /mnt/tmp/dir1/hosts /mnt/tmp/dir2/hosts</div>
<div class="">&nbsp; &nbsp; :<br class="">
<div>&nbsp; &nbsp; renameat2(AT_FDCWD, &quot;/mnt/tmp/dir1/hosts&quot;, AT_FDCWD, &quot;/mnt/tmp/dir2/hosts&quot;, RENAME_NOREPLACE) = -1&nbsp;EXDEV (Invalid cross-device link)<br class="">
&nbsp; &nbsp; stat(&quot;/mnt/tmp/dir2/hosts&quot;, 0x7ffff8a6c2b0) = -1 ENOENT (No such file or directory)<br class="">
&nbsp; &nbsp; lstat(&quot;/mnt/tmp/dir1/hosts&quot;, {st_mode=S_IFREG|0644, st_size=7424, ...}) = 0<br class="">
&nbsp; &nbsp; newfstatat(AT_FDCWD, &quot;/mnt/tmp/dir2/hosts&quot;, 0x7ffff8a6bf90, AT_SYMLINK_NOFOLLOW) = -1 ENOENT (No such&nbsp;file or directory)<br class="">
&nbsp; &nbsp; unlink(&quot;/mnt/tmp/dir2/hosts&quot;)&nbsp;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;&nbsp;= -1 ENOENT (No such file or directory)<br class="">
&nbsp; &nbsp; openat(AT_FDCWD, &quot;/mnt/tmp/dir1/hosts&quot;, O_RDONLY|O_NOFOLLOW) = 3<br class="">
&nbsp; &nbsp; openat(AT_FDCWD, &quot;/mnt/tmp/dir2/hosts&quot;, O_WRONLY|O_CREAT|O_EXCL, 0600) = 4<br class="">
&nbsp; &nbsp; read(3, &quot;##\n# Host Database\n#\n# Do not re&quot;..., 131072) = 7424<br class="">
&nbsp; &nbsp; write(4, &quot;##\n# Host Database\n#\n# Do not re&quot;..., 7424) = 7424</div>
<div>&nbsp; &nbsp; :</div>
<div>&nbsp; &nbsp; # lsattr -p /mnt/tmp/dir2</div>
<div>&nbsp; &nbsp; 2000 --------------e----P-- /mnt/tmp/dir2/hosts</div>
<div>&nbsp; &nbsp; # ls -li /mnt/tmp/dir2</div>
&nbsp; &nbsp; total 8</div>
<div class="">&nbsp; &nbsp; 786435 8 -rw-r--r--. 1 root root 7424 Oct 18 22:42 hosts
<div><br class="">
</div>
<div>The reason for this limitation is that there is no way to atomically update the quota between the two project IDs when a whole subdirectory tree is being moved between projects. &nbsp;There might be thousands of subdirectories and millions of files that are
 being moved, and the project ID needs to be updated on all of those files and directories. &nbsp;This is too large to do atomically in a single filesystem transaction. &nbsp;Rather than try to solve this directly in the kernel, the decision of the XFS developers (copied
 by ext4) is that cross-project renames will not be done by the kernel and instead be handled in userspace by the &quot;mv&quot; utility, the same way that renames across different filesystems are handled.</div>
<div><br class="">
</div>
<div><br class="">
</div>
<div>In Lustre 2.15.0 and later, this cross-project rename constraint has been removed for *regular file* renames between directories with different project IDs. &nbsp;This means the file is moved between directories and the project ID and associated quota accounting
 is updated in a single transaction without doing a data copy. &nbsp;However, *directory* renames with PROJINHERIT still have this issue.</div>
<div><br class="">
</div>
<div>To work around this behavior, it is possible to use &quot;chattr - p&quot; (or &quot;lfs project -p&quot;, they do the same thing) to change the project ID of the source files and directories *before* they are renamed so that the file data copy does not need to be done, and
 just the filenames can be moved.</div>
<div><br class="">
</div>
<div>It might be possible to patch &quot;mv&quot; so that instead of bailing on &quot;rename()&quot; after the first EXDEV return, it creates the target directory and then tries to rename the files within the source directory to the target, before it does the file copy. &nbsp;It is
 likely that ext4 could also be patched to allow regular file renames without returning EXDEV.</div>
<div><br class="">
</div>
<div class="">
<div dir="auto" style="caret-color: rgb(0, 0, 0); color: rgb(0, 0, 0); letter-spacing: normal; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; word-spacing: 0px; -webkit-text-stroke-width: 0px; text-decoration: none; word-wrap: break-word; -webkit-nbsp-mode: space; line-break: after-white-space;" class="">
<div dir="auto" style="caret-color: rgb(0, 0, 0); color: rgb(0, 0, 0); letter-spacing: normal; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; word-spacing: 0px; -webkit-text-stroke-width: 0px; text-decoration: none; word-wrap: break-word; -webkit-nbsp-mode: space; line-break: after-white-space;" class="">
<div dir="auto" style="caret-color: rgb(0, 0, 0); color: rgb(0, 0, 0); letter-spacing: normal; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; word-spacing: 0px; -webkit-text-stroke-width: 0px; text-decoration: none; word-wrap: break-word; -webkit-nbsp-mode: space; line-break: after-white-space;" class="">
<div dir="auto" style="caret-color: rgb(0, 0, 0); color: rgb(0, 0, 0); letter-spacing: normal; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; word-spacing: 0px; -webkit-text-stroke-width: 0px; text-decoration: none; word-wrap: break-word; -webkit-nbsp-mode: space; line-break: after-white-space;" class="">
<div dir="auto" style="caret-color: rgb(0, 0, 0); color: rgb(0, 0, 0); letter-spacing: normal; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; word-spacing: 0px; -webkit-text-stroke-width: 0px; text-decoration: none; word-wrap: break-word; -webkit-nbsp-mode: space; line-break: after-white-space;" class="">
<div dir="auto" style="caret-color: rgb(0, 0, 0); color: rgb(0, 0, 0); letter-spacing: normal; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; word-spacing: 0px; -webkit-text-stroke-width: 0px; text-decoration: none; word-wrap: break-word; -webkit-nbsp-mode: space; line-break: after-white-space;" class="">
<div>Cheers, Andreas</div>
<div>--</div>
<div>Andreas Dilger</div>
<div>Lustre&nbsp;Principal Architect</div>
<div>Whamcloud</div>
<div><br class="">
</div>
<div><br class="">
</div>
<div><br class="">
</div>
</div>
</div>
</div>
</div>
</div>
<br class="Apple-interchange-newline">
</div>
<br class="Apple-interchange-newline">
<br class="Apple-interchange-newline">
</div>
<br class="">
</div>
</body>
</html>