coreutils
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: "ls -l": Avoid unnecessary getxattr() overhead


From: Jim Meyering
Subject: Re: "ls -l": Avoid unnecessary getxattr() overhead
Date: Fri, 17 Feb 2012 11:35:14 +0100

Bernhard Voelker wrote:
> Alternatively, it could write a certain line to stdout or stderr,
> and for comparison, this pattern would have to be counted.
> There's a raw patch attached to demonstrate it.
>
> diff --git a/tests/ls/getxattr-speedup b/tests/ls/getxattr-speedup
> index f3dc5bb..9127a28 100755
> --- a/tests/ls/getxattr-speedup
> +++ b/tests/ls/getxattr-speedup
> @@ -21,7 +21,8 @@
>  . "${srcdir=.}/init.sh"; path_prepend_ ../src
>  print_ver_ ls
>
> -fd=33
> +speeduptext="__SPEEDUP__"
> +speeduptextlen=$( echo "$speeduptext" | wc -c )  # also count newline.
...

Thanks for the patch.
However, while I don't particularly like using fd 33, and might
use stderr instead, I do want to avoid stdout.  With it, there seems
to be too much risk that mixing wrapper-induced output with ls's normal
output would cause trouble, e.g., if your __SPEEDUP__ token were not
written right after a newline.

Instead, I've realized that I can eliminate the need for the wc post-
processing by using the fact that our contrived output file is seekable:
rather than simply writing to fd, first seek to position 0 each time,
and write the count:

Here's a stand-alone test script.
When it completes, the output file, "x"
contains either nothing or a count of the number of calls.

  # Pretend *getxattr always fails with ENOTSUP
  fd=33

  cat > k.c <<'EOF' || exit 1
  #include <errno.h>
  #include <unistd.h>
  #include <stdio.h>
  #include <string.h>
  static unsigned long int n_calls;

  static void
  write_1 (void)
  {
    ++n_calls;
    int fd = @FD@;
    if (lseek (fd, 0, SEEK_SET) < 0)
      return;
    char buf[30];
    sprintf (buf, "%lu\n", n_calls);
    write (fd, buf, strlen (buf));
  }
  ssize_t getxattr (const char *path, const char *name, void *value, size_t 
size)
  { write_1 (); errno = ENOTSUP; return -1; }
  ssize_t lgetxattr(const char *path, const char *name, void *value, size_t 
size)
  { write_1 (); errno = ENOTSUP; return -1; }
EOF
  sed "s/@FD@/$fd/" k.c > k || exit 1
  mv k k.c || exit 1

  # Then compile/link it:
  gcc -Wall -fPIC -O2 -c k.c && ld -G k.o -o k.so

  # Finally, to test it, do this:
  eval "LD_PRELOAD=$PWD/k.so ls --color=always -l . $fd>x" || exit 1

Hmm... that means the case of no getxattr calls would still
require a little special handling to map "empty file" to "0".
With that, I still prefer the simpler, original write_1 function.



reply via email to

[Prev in Thread] Current Thread [Next in Thread]