Uploaded image for project: 'RHEL'
  1. RHEL
  2. RHEL-16285

Convert the NFS_READDIR_CACHE_USAGE_THRESHOLD define to a sysfs tunable

    • sst_filesystems
    • ssg_filesystems_storage_and_HA
    • 2
    • QE ack
    • False
    • Hide

      None

      Show
      None
    • None
    • Red Hat Enterprise Linux
    • None
    • None

      What were you trying to do that didn't work?

      NFS now uses a heuristic to determine whether to get directory listings using READDIR or READDIRPLUS, depending on whether the userspace program has called stat() a specific number of times.  The getdents() syscall returns the directory entry type (d_type) for each entry returned, but the entry's type is only known if READDIRPLUS is used, otherwise DT_UNKNOWN is returned.

      This behavior means that programs which only need the entry name and entry type (but not the additional information provided by stat()) will no longer get the d_type, which will require them to start making stat() calls for each entry which did not return a known d_type.  As a result, the program will experience a performance hit, now having to make stat() calls to obtain the type, when not required previously.

      As shown below, this is not academic

      Please provide the package NVR for which bug is seen:

      RHEL 9 kernels

      RHEL 8 kernels, beginning mid-RHEL8

      upstream kernel

       

      How reproducible:

      easy

      Steps to reproduce

      1. mount server:/export /mnt/tmp
      2. for i in {1..1000} ; do touch /mnt/tmp/file$i ; done
      3. sysctl vm.drop_caches=3
      4. strace -vo /tmp/trace.out -etrace=file,desc -s 10240 find /mnt/tmp -type f >/dev/null
      5. examine /tmp/trace.out for getdents() calls with DT_UNKNOWN d_type

      Expected results

      programs which require d_type information but do not call stat() on the entries themselves continue to get known d_type

      Actual results

      If stat() is not called at least 8 times on entries returned in the first getdents() call, the second and subsequent getdents() calls will begin returning entries with d_type of DT_UNKNOWN

      from the strace:

      getdents64(4, [{d_ino=137256816, d_off=10, d_reclen=24, d_type=DT_DIR, d_name="."}, {d_ino=71089655, d_off=12, d_reclen=24, d_type=DT_DIR, d_name=".."}, {d_ino=137256803, d_off=15, d_reclen=32, d_type=DT_REG, d_name="file1"}, {d_ino=137256822, d_off=18, d_reclen=32, d_type=DT_REG, d_name="file2"}, {d_ino=137256825, d_off=21, d_reclen=32, d_type=DT_REG, d_name="file3"}, {d_ino=137256827, d_off=24, d_reclen=32, d_type=DT_REG, d_name="file4"}, ... {d_ino=136763055, d_off=63, d_reclen=32, d_type=DT_REG, d_name="file17"}], 32768) = 592
      
      getdents64(4, [{d_ino=136763056, d_off=66, d_reclen=32, d_type=DT_REG, d_name="file18"}, ... , {d_ino=136763062, d_off=84, d_reclen=32, d_type=DT_REG, d_name="file24"}, {d_ino=136763063, d_off=87, d_reclen=32, d_type=DT_REG, d_name="file25"}, {d_ino=136763064, d_off=90, d_reclen=32, d_type=DT_UNKNOWN, d_name="file26"}, {d_ino=136763065, d_off=93, d_reclen=32, d_type=DT_UNKNOWN, d_name="file27"}, ...
      ...
      
      newfstatat(5, "file26", {st_dev=makedev(0, 0x2a), st_ino=136763064, st_mode=S_IFREG|0644, st_nlink=1, st_uid=0, st_gid=0, st_blksize=262144, st_blocks=0, st_size=0, st_atime=1699392520 /* 2023-11-07T15:28:40.741965897-0600 */, st_atime_nsec=741965897, st_mtime=1699392520 /* 2023-11-07T15:28:40.741965897-0600 */, st_mtime_nsec=741965897, st_ctime=1699392520 /* 2023-11-07T15:28:40.741965897-0600 */, st_ctime_nsec=741965897}, AT_SYMLINK_NOFOLLOW) = 0
      
      newfstatat(5, "file27", {st_dev=makedev(0, 0x2a), st_ino=136763065, st_mode=S_IFREG|0644, st_nlink=1, st_uid=0, st_gid=0, st_blksize=262144, st_blocks=0, st_size=0, st_atime=1699392520 /* 2023-11-07T15:28:40.798966528-0600 */, st_atime_nsec=798966528, st_mtime=1699392520 /* 2023-11-07T15:28:40.798966528-0600 */, st_mtime_nsec=798966528, st_ctime=1699392520 /* 2023-11-07T15:28:40.798966528-0600 */, st_ctime_nsec=798966528}, AT_SYMLINK_NOFOLLOW) = 0
        

      (in other words, 'find -type' will only make stat() calls if d_type is DT_UNKNOWN)

            bcodding@redhat.com Benjamin Coddington
            rhn-support-fsorenso Frank Sorenson
            NFS Team NFS Team
            Zhi Li Zhi Li
            Votes:
            0 Vote for this issue
            Watchers:
            7 Start watching this issue

              Created:
              Updated: