Issue #4579 has been updated by Markus Roberts. Status changed from Unreviewed to Needs more information Assigned to set to Nigel Kersten
Two thoughts here: 1) The most common case (all is good) seems optimal (one lstat) and it progresses fairly uniformly to the least likely case (the symlink exists, and points to a directory) being the most expensive. 2) I'm not sure if there's a general solution to the problem as stated. Some number of calls will need to be done to implement the desired behaviour (even your shell script makes multiple calls) so at best we're talking about reducing the number of calls in specific cases. And some questions: 1) Do you know if any of the calls are purely redundant (same args, no intervening state changes)? 2) Which case(s) is/are problematic, and what would you suggest as a reasonable stat-call limit for them? 3) Which version(s) of puppet are you looking at? ---------------------------------------- Bug #4579: Symlink file type can issue potentially expensive stat calls rather than lstat http://projects.puppetlabs.com/issues/4579 Author: Nigel Kersten Status: Needs more information Priority: Normal Assigned to: Nigel Kersten Category: Target version: Affected version: Keywords: Branch: I've only briefly looked at the relevant Puppet code here, but wanted to get this bug in as it took a little while for us to work out what was triggering this. Given the following simple manifest saved to /tmp/test.pp <pre> file { "/tmp/symlink": ensure => symlink, target => "/tmp/target", force => true, } </pre> There are a bunch of cases that can cause Puppet to stat the symlink rather than lstat'ing it. If the symlink target is on a slow filesystem, this can be very expensive. Shell script to indicate issue: <pre> #!/bin/bash # SYM=/tmp/symlink TAR=/tmp/target touch $TAR if stat $SYM &>/dev/null ; then echo "Symlink exists" # check if target exists if stat -L $SYM &>/dev/null; then # output target stat -c "%N" $SYM # output target type echo "Target is a $(stat -L -c "%F" $SYM)" else echo "Target is missing" fi else echo "Symlink missing" fi strace -e trace=stat,lstat -f /usr/bin/puppet /tmp/test.pp 2>&1 | grep -E "/tmp/(symlink|target)" </pre> Some examples: Symlink doesn't exist, target does. lstat: 1 stat: 1 <pre> nig...@wittgenstein:~ $ rm -f /tmp/{symlink,target} nig...@wittgenstein:~ $ ~/symlink-test.sh Symlink missing [pid 30115] lstat("/tmp/symlink", 0x7fff33457420) = -1 ENOENT (No such file or directory) [pid 30115] stat("/tmp/symlink", 0x7fff334549b0) = -1 ENOENT (No such file or directory) notice: //File[/tmp/symlink]/ensure: created </pre> Symlink exists, points to desired target. lstat: 1 <pre> nig...@wittgenstein:~ $ ~/symlink-test.sh Symlink exists `/tmp/symlink' -> `/tmp/target' Target is a regular empty file [pid 30435] lstat("/tmp/symlink", {st_mode=S_IFLNK|0777, st_size=11, ...}) = 0 </pre> Symlink exists, points to undesired file. lstat: 1 stat: 4 <pre> nig...@wittgenstein:~ $ ~/symlink-test.sh Symlink exists `/tmp/symlink' -> `/etc/fstab' Target is a regular file [pid 30524] lstat("/tmp/symlink", {st_mode=S_IFLNK|0777, st_size=10, ...}) = 0 [pid 30524] stat("/tmp/symlink", {st_mode=S_IFREG|0644, st_size=811, ...}) = 0 [pid 30524] stat("/tmp/symlink", {st_mode=S_IFREG|0644, st_size=811, ...}) = 0 [pid 30524] stat("/tmp/symlink", {st_mode=S_IFREG|0644, st_size=811, ...}) = 0 [pid 30524] stat("/tmp/symlink", 0x7fffb5d1b370) = -1 ENOENT (No such file or directory) notice: //File[/tmp/symlink]/target: target changed '/etc/fstab' to '/tmp/target' </pre> Symlink exists, points to undesired directory. lstat: 2 stat: 5 <pre> nig...@wittgenstein:~ $ ~/symlink-test.sh Symlink exists `/tmp/symlink' -> `/usr' Target is a directory [pid 30790] lstat("/tmp/symlink", {st_mode=S_IFLNK|0777, st_size=4, ...}) = 0 [pid 30790] stat("/tmp/symlink", {st_mode=S_IFDIR|0755, st_size=4096, ...}) = 0 [pid 30790] stat("/tmp/symlink", {st_mode=S_IFDIR|0755, st_size=4096, ...}) = 0 [pid 30790] stat("/tmp/symlink", {st_mode=S_IFDIR|0755, st_size=4096, ...}) = 0 [pid 30790] stat("/tmp/symlink", {st_mode=S_IFDIR|0755, st_size=4096, ...}) = 0 [pid 30790] lstat("/tmp/symlink", {st_mode=S_IFLNK|0777, st_size=4, ...}) = 0 [pid 30790] stat("/tmp/symlink", 0x7fff06901ab0) = -1 ENOENT (No such file or directory) notice: //File[/tmp/symlink]/target: target changed '/usr' to '/tmp/target' </pre> -- You have received this notification because you have either subscribed to it, or are involved in it. To change your notification preferences, please click here: http://projects.puppetlabs.com/my/account -- You received this message because you are subscribed to the Google Groups "Puppet Bugs" group. To post to this group, send email to [email protected]. To unsubscribe from this group, send email to [email protected]. For more options, visit this group at http://groups.google.com/group/puppet-bugs?hl=en.
