]> git-server-git.apps.pok.os.sepia.ceph.com Git - ceph.git/commitdiff
client: fix d_reclen for readdir 61519/head
authorXavi Hernandez <xhernandez@gmail.com>
Tue, 9 Apr 2024 08:26:59 +0000 (10:26 +0200)
committerMilind Changire <mchangir@redhat.com>
Sat, 25 Jan 2025 02:24:48 +0000 (07:54 +0530)
Based on the man page of readdir(3), the d_reclen field should contain
the total size of the record, which varies depending on the length of
the returned name. However, the previous implementation was returning a
hardcoded '1' in all cases.

This patch computes the right size of the record and returns it.

Fixes: https://tracker.ceph.com/issues/65389
Signed-off-by: Xavi Hernandez <xhernandez@gmail.com>
(cherry picked from commit 5ac01659cf8f33457c78546731d694d1e99fcc91)

src/client/Client.cc

index a84e69f38f2fdcca7691a0c805b6d27a0398a924..bcc6cd201406fdc2dd8a4b0fa51a30d5a0c13e7a 100644 (file)
@@ -14,6 +14,7 @@
 
 
 // unix-ey fs stuff
+#include <algorithm>
 #include <unistd.h>
 #include <sys/types.h>
 #include <time.h>
@@ -9226,14 +9227,19 @@ void Client::seekdir(dir_result_t *dirp, loff_t offset)
 //};
 void Client::fill_dirent(struct dirent *de, const char *name, int type, uint64_t ino, loff_t next_off)
 {
-  strncpy(de->d_name, name, 255);
-  de->d_name[255] = '\0';
+  size_t len = strlen(name);
+  len = std::min(len, (size_t)255);
+  memcpy(de->d_name, name, len);
+  de->d_name[len] = '\0';
 #if !defined(__CYGWIN__) && !(defined(_WIN32))
   de->d_ino = ino;
 #if !defined(__APPLE__) && !defined(__FreeBSD__)
   de->d_off = next_off;
 #endif
-  de->d_reclen = 1;
+  // Calculate the real used size of the record
+  len = (uintptr_t)&de->d_name[len] - (uintptr_t)de + 1;
+  // The record size must be a multiple of the alignment of 'struct dirent'
+  de->d_reclen = (len + alignof(struct dirent) - 1) & ~(alignof(struct dirent) - 1);
   de->d_type = IFTODT(type);
   ldout(cct, 10) << __func__ << " '" << de->d_name << "' -> " << inodeno_t(de->d_ino)
           << " type " << (int)de->d_type << " w/ next_off " << hex << next_off << dec << dendl;