You are viewing a plain text version of this content. The canonical link for it is here.
Posted to dev@httpd.apache.org by Martin Kraemer <Ma...@Fujitsu-Siemens.com> on 2001/11/07 10:11:43 UTC

[2.0] lstat's in spite of AllowOverride None

When I do a grep for "AllowOverride" in my current config, I get:
312:    AllowOverride None
341:    AllowOverride None
371:#    AllowOverride FileInfo AuthConfig Limit
523:    AllowOverride None
537:    AllowOverride None
569:    AllowOverride None
897:        AllowOverride None

In spite of this, when tracing an access to a read-only file, I see:
 ...
 lstat("/home",0xbfbff890)                        = 0 (0x0)
 lstat("/home/www",0xbfbff890)                    = 0 (0x0)
 lstat("/home/www/SERVER",0xbfbff890)             = 0 (0x0)
 lstat("/home/www/SERVER/apa20",0xbfbff890)       = 0 (0x0)
 lstat("/home/www/SERVER/apa20/htdocs",0xbfbff890) = 0 (0x0)
 lstat("/home/www/SERVER/apa20/htdocs/noread.html",0xbfbff890) = 0 (0x0)
 open("/home/www/SERVER/apa20/htdocs/noread.html",0,00) ERR#13 'Permission denied'
 gettimeofday(0xbfbfb874,0x0)                     = 0 (0x0)
 write(2,0xbfbfb920,161)                          = 161 (0xa1)
 lstat("/home",0xbfbff800)                        = 0 (0x0)
 lstat("/home/www",0xbfbff800)                    = 0 (0x0)
 lstat("/home/www/SERVER",0xbfbff800)             = 0 (0x0)
 lstat("/home/www/SERVER/apa20",0xbfbff800)       = 0 (0x0)
 lstat("/home/www/SERVER/apa20/error",0xbfbff800) = 0 (0x0)
 lstat("/home/www/SERVER/apa20/error/HTTP_FORBIDDEN.html.var",0xbfbff800) = 0 (0x0)
 open("/home/www/SERVER/apa20/error/HTTP_FORBIDDEN.html.var",0,0666) = 17 (0x11)
 ....

Where do all the lstats() come from, and *WHY* do they happen at all?

  Martin
-- 
<Ma...@Fujitsu-Siemens.com>         |     Fujitsu Siemens
Fon: +49-89-636-46021, FAX: +49-89-636-47655 | 81730  Munich,  Germany

Re: [2.0] lstat's in spite of AllowOverride None

Posted by Martin Kraemer <Ma...@Fujitsu-Siemens.com>.
On Wed, Nov 07, 2001 at 09:32:37AM +0000, James A Sutherland wrote:
> 
> (lstat() on each pathname component for each request)
> 
> > Where do all the lstats() come from, and *WHY* do they happen at all?
> 
> Checking for symlinks, I think? Check for Options FollowSymLinks.

It is set for the dir in question (and everywhere above it), so it needn't
(shouldn't) do any lstat()s IMHO.

> And think 
> what would happen otherwise if I put a symlink in my personal WWW area which 
> pointed to an otherwise-prohibited file the webserver can read - like an 
> htpasswd file somewhere...

I know about that, and that the server doesn't (shouldn't) care as long
as FollowSymLinks is in effect.

   Martin
-- 
<Ma...@Fujitsu-Siemens.com>         |     Fujitsu Siemens
Fon: +49-89-636-46021, FAX: +49-89-636-47655 | 81730  Munich,  Germany

Re: [2.0] lstat's in spite of AllowOverride None

Posted by James A Sutherland <ja...@cam.ac.uk>.
On Wednesday 07 November 2001 9:11 am, Martin Kraemer wrote:
> When I do a grep for "AllowOverride" in my current config, I get:
> 312:    AllowOverride None
> 341:    AllowOverride None
> 371:#    AllowOverride FileInfo AuthConfig Limit
> 523:    AllowOverride None
> 537:    AllowOverride None
> 569:    AllowOverride None
> 897:        AllowOverride None
>
> In spite of this, when tracing an access to a read-only file, I see:

(lstat() on each pathname component for each request)

> Where do all the lstats() come from, and *WHY* do they happen at all?

Checking for symlinks, I think? Check for Options FollowSymLinks. And think 
what would happen otherwise if I put a symlink in my personal WWW area which 
pointed to an otherwise-prohibited file the webserver can read - like an 
htpasswd file somewhere...


James.

Re: [2.0] lstat's in spite of AllowOverride None

Posted by Ryan Bloom <rb...@covalent.net>.
On Friday 09 November 2001 12:11 pm, Michael Douglass wrote:
> > > As FirstBill suggests, there are other means for caching the (l)stat
> > > results, at least for the request duration, which need to be deployed. 
> > > But dropping the path_info walk-backwards logic was step one.  Any
> > > optimization patches are entertianed to speed up the server, if we
> > > don't lose stability.
> >
> > Caching the lstat() results should help, but reducing to a single stat()
> > as I suggest would seem better still?
>
> I'd be weary of caching the lstat() information for more than the current
> connection; you don't want someone to abuse that cache by creating a
> symlink AFTER letting apache cache the information.
>
> Anyone think about using resolvepath() as an initial check?  resolvepath()
> is a single system call to take a path to a file and convert it to the
> resultant path after following all symlinks.  Thus you could have a single
> call to resolvepath() and strcmp() to see if there were any symlinks in
> the path--if there were then you either "deny" it if symlinks are not
> allowed at all; or you proceed with the lstat() scheme otherwise.
>
> This would seem to circumvent alot of lstat() calls on the (hopefully)
> normal case that there are no symlinks involved anywhere. :)

The problem is that you can deny SymLinks at any point in the path.  We
could use resolvepath(), but then we would need to walk the path anyway to
make sure that Symlinks are allowed all the way down.

Ryan

______________________________________________________________
Ryan Bloom				rbb@apache.org
Covalent Technologies			rbb@covalent.net
--------------------------------------------------------------

Re: [2.0] lstat's in spite of AllowOverride None

Posted by Dirk-Willem van Gulik <di...@covalent.net>.
On Fri, 9 Nov 2001, Martin Kraemer wrote:

> Looks good (though xv could not display it -- but xpaint could).
> Isn't mrtg the right tool to visualize that? (I would have done it in
> php, probably). The drop between Jul and Nov is clearly visible (although
> two series are mixed, one with dates dd-mmm-yy and one with YYYY-mmm-dd).

I have to admit (showings sings of age here; that IDL, Mathematica and
gnuplot (with a bit of awk) are my usual tools).

Dw


Re: [2.0] lstat's in spite of AllowOverride None

Posted by Martin Kraemer <Ma...@Fujitsu-Siemens.com>.
On Thu, Nov 08, 2001 at 02:31:20PM -0500, Dirk-Willem van Gulik wrote:
> 
> For those who, like me, are a bit nummerically challenges; see attached
> graph of the same data (I hope).
> 
> Martin - if you want to - I've got some automated graphing set up from
> an earlier profiling thing we did. If you want we could do some automation
> in this area.

Looks good (though xv could not display it -- but xpaint could).
Isn't mrtg the right tool to visualize that? (I would have done it in
php, probably). The drop between Jul and Nov is clearly visible (although
two series are mixed, one with dates dd-mmm-yy and one with YYYY-mmm-dd).

  Martin
-- 
<Ma...@Fujitsu-Siemens.com>         |     Fujitsu Siemens
Fon: +49-89-636-46021, FAX: +49-89-636-47655 | 81730  Munich,  Germany

Re: [2.0] lstat's in spite of AllowOverride None

Posted by "William A. Rowe, Jr." <wr...@covalent.net>.
Dirk, would you run this benchmark again against cvs HEAD so we can see the
impact of the 'one stat dir_walk' patch introduced today?


----- Original Message ----- 
From: "Dirk-Willem van Gulik" <di...@covalent.net>
To: <de...@httpd.apache.org>
Sent: Thursday, November 08, 2001 1:31 PM
Subject: Re: [2.0] lstat's in spite of AllowOverride None


> 
> For those who, like me, are a bit nummerically challenges; see attached
> graph of the same data (I hope).
> 
> Martin - if you want to - I've got some automated graphing set up from
> an earlier profiling thing we did. If you want we could do some automation
> in this area.
> 
> Dw
> 


RE: [2.0] lstat's in spite of AllowOverride None

Posted by "Benjamin W. Ritcey" <be...@ritcey.com>.
Do you realize that your graph shows the months as "Apr, Jun, Jul, Aug, Sep,
Nov, May, Oct" ?  Not quite so spikey if the data are in the right order.

-----Original Message-----
From: Dirk-Willem van Gulik [mailto:dirkx@covalent.net]
Sent: Thursday, November 08, 2001 2:31 PM
To: dev@httpd.apache.org
Subject: Re: [2.0] lstat's in spite of AllowOverride None



For those who, like me, are a bit nummerically challenges; see attached
graph of the same data (I hope).

Martin - if you want to - I've got some automated graphing set up from
an earlier profiling thing we did. If you want we could do some automation
in this area.

Dw


Re: [2.0] lstat's in spite of AllowOverride None

Posted by Dirk-Willem van Gulik <di...@covalent.net>.
For those who, like me, are a bit nummerically challenges; see attached
graph of the same data (I hope).

Martin - if you want to - I've got some automated graphing set up from
an earlier profiling thing we did. If you want we could do some automation
in this area.

Dw

Re: [2.0] lstat's in spite of AllowOverride None

Posted by Martin Kraemer <Ma...@Fujitsu-Siemens.com>.
On Wed, Nov 07, 2001 at 10:43:35AM -0600, William A. Rowe, Jr. wrote:
> > Right. "Current modern OS's" aren't always as optimized as they could be
> > (someone measured 1000 cps before the forward walk change against around
> > 330 cps after this change, on win2k). And a system call always means
> > (on unix, at least) much higher overhead than a function call.
> 
> The direct-hit method should clear up much of this confusion, since I rather suspect
> that we are also seeing side effects of the recent filtering changes.

I have a nightly regression build and do a final "ab -k -c6 -t10 .../tenkb.txt"
which is logged. On FreeBSD at least, there has been some ups and downs in
the req/sec on my 266MHz box. The cron job runs at 4am after a full build,
and my (intranet) machine should have little load at that time.

You can see that around Aug 7th, the typical performance went
down from ~350 to ~270 req/s at which it is now performing.

   Martin

2001-Nov-07@04:13: 266.39 [#/sec] (mean)
2001-Nov-06@04:13: 266.01 [#/sec] (mean)
2001-Nov-05@04:14: 263.04 [#/sec] (mean)
2001-Nov-04@04:14: 256.22 [#/sec] (mean)
2001-Nov-03@04:13: 262.64 [#/sec] (mean)
2001-Nov-02@04:13: 262.33 [#/sec] (mean)
2001-Nov-01@04:13: 253.40 [#/sec] (mean)
2001-Oct-31@04:14: 262.75 [#/sec] (mean)
2001-Oct-30@04:15: 164.72 [#/sec] (mean)
2001-Oct-29@04:14: 258.96 [#/sec] (mean)
2001-Oct-28@04:14: 265.42 [#/sec] (mean)
2001-Oct-27@04:15: 205.35 [#/sec] (mean)
2001-Oct-26@04:14: 246.84 [#/sec] (mean)
2001-Oct-25@04:24: 203.05 [#/sec] (mean)
2001-Oct-24@04:17: 211.92 [#/sec] (mean)
2001-Oct-23@04:17: 240.40 [#/sec] (mean)
2001-Oct-22@04:14: 263.80 [#/sec] (mean)
2001-Oct-21@04:14: 257.92 [#/sec] (mean)
2001-Oct-20@04:14: 260.04 [#/sec] (mean)
2001-Oct-19@04:15: 231.10 [#/sec] (mean)
2001-Oct-18@04:15: 258.39 [#/sec] (mean)
2001-Oct-17@04:14: 255.94 [#/sec] (mean)
2001-Oct-16@04:14: 261.11 [#/sec] (mean)
2001-Oct-15@04:14: 262.49 [#/sec] (mean)
2001-Oct-14@04:13: 241.58 [#/sec] (mean)
2001-Oct-13@04:14: 252.27 [#/sec] (mean)
2001-Oct-12@04:14: 259.50 [#/sec] (mean)
2001-Oct-11@04:14: 264.81 [#/sec] (mean)
2001-Oct-10@04:14: 144.68 [#/sec] (mean)
2001-Oct-09@04:13: 253.88 [#/sec] (mean)
2001-Okt-08@17:50: 209.04 [#/sec] (mean)
2001-Okt-08@12:34: 220.53 [#/sec] (mean)
2001-Oct-04@04:13: 279.42 [#/sec] (mean)
2001-Oct-03@04:13: 277.56 [#/sec] (mean)
2001-Oct-02@04:13: 286.53 [#/sec] (mean)
2001-Oct-01@04:13: 282.10 [#/sec] (mean)
2001-Sep-30@04:13: 278.94 [#/sec] (mean)
2001-Sep-29@04:13: 282.28 [#/sec] (mean)
2001-Sep-28@04:14: 277.46 [#/sec] (mean)
2001-Sep-27@04:22: 205.33 [#/sec] (mean)
2001-Sep-26@04:22: 207.24 [#/sec] (mean)
2001-Sep-25@04:22: 204.49 [#/sec] (mean)
2001-Sep-24@04:13: 279.61 [#/sec] (mean)
2001-Sep-23@04:13: 278.75 [#/sec] (mean)
2001-Sep-22@04:13: 271.08 [#/sec] (mean)
2001-Sep-21@04:14: 270.24 [#/sec] (mean)
2001-Sep-20@04:13: 262.89 [#/sec] (mean)
2001-Sep-19@04:13: 276.16 [#/sec] (mean)
2001-Sep-18@04:13: 276.62 [#/sec] (mean)
2001-Sep-17@04:13: 279.11 [#/sec] (mean)
2001-Sep-16@04:13: 275.71 [#/sec] (mean)
2001-Sep-15@04:13: 272.84 [#/sec] (mean)
2001-Sep-14@04:13: 268.42 [#/sec] (mean)
2001-Sep-13@04:13: 276.51 [#/sec] (mean)
2001-Sep-12@04:13: 244.00 [#/sec] (mean)
2001-Sep-11@04:13: 265.73 [#/sec] (mean)
2001-Sep-10@04:13: 277.21 [#/sec] (mean)
2001-Sep-09@04:13: 277.60 [#/sec] (mean)
2001-Sep-08@04:13: 262.30 [#/sec] (mean)
2001-Sep-07@04:13: 271.81 [#/sec] (mean)
2001-Sep-06@04:13: 274.18 [#/sec] (mean)
2001-Sep-04@04:13: 264.56 [#/sec] (mean)
2001-Sep-03@04:13: 272.68 [#/sec] (mean)
2001-Sep-02@04:13: 270.56 [#/sec] (mean)
2001-Sep-01@04:13: 265.26 [#/sec] (mean)
2001-Aug-31@10:16: 235.50 [#/sec] (mean)
2001-Aug-31@04:13: 262.45 [#/sec] (mean)
2001-Aug-30@04:13: 271.16 [#/sec] (mean)
2001-Aug-29@09:56: 207.02 [#/sec] (mean)
2001-Aug-23@04:14: 230.47 [#/sec] (mean)
2001-Aug-21@04:09: 240.24 [#/sec] (mean)
2001-Aug-20@09:08: 224.25 [#/sec] (mean)
2001-Aug-19@04:07: 251.92 [#/sec] (mean)
2001-Aug-18@04:07: 251.67 [#/sec] (mean)
2001-Aug-17@04:07: 252.87 [#/sec] (mean)
2001-Aug-16@04:07: 259.31 [#/sec] (mean)
2001-Aug-15@04:07: 262.95 [#/sec] (mean)
2001-Aug-14@04:07: 263.60 [#/sec] (mean)
2001-Aug-13@04:08: 270.58 [#/sec] (mean)
2001-Aug-12@04:08: 274.03 [#/sec] (mean)
2001-Aug-11@04:08: 273.91 [#/sec] (mean)
2001-Aug-10@04:08: 286.18 [#/sec] (mean)
2001-Aug-09@04:08: 283.02 [#/sec] (mean)
2001-Aug-08@04:08: 283.83 [#/sec] (mean)
2001-Aug-07@04:08: 313.70 [#/sec] (mean)
2001-Aug-03@04:12: 236.83 [#/sec] (mean)
2001-Aug-02@04:08: 317.51 [#/sec] (mean)
2001-Aug-01@10:56: 301.76 [#/sec] (mean)
2001-Jul-30@04:08: 315.10 [#/sec] (mean)
2001-Jul-29@04:08: 303.78 [#/sec] (mean)
2001-Jul-28@04:10: 309.15 [#/sec] (mean)
2001-Jul-27@04:08: 298.39 [#/sec] (mean)
2001-Jul-26@04:08: 305.02 [#/sec] (mean)
2001-Jul-25@09:15: 311.89 [#/sec] (mean)
2001-Jul-24@04:08: 314.53 [#/sec] (mean)
2001-Jul-23@04:08: 311.75 [#/sec] (mean)
2001-Jul-22@04:08: 306.19 [#/sec] (mean)
2001-Jul-21@04:08: 311.54 [#/sec] (mean)
2001-Jul-20@09:18: 310.07 [#/sec] (mean)
2001-Jul-19@04:08: 314.56 [#/sec] (mean)
2001-Jul-18@04:08: 311.96 [#/sec] (mean)
2001-Jul-17@04:08: 310.91 [#/sec] (mean)
2001-Jul-16@12:12: 373.00 [#/sec] (mean)
2001-Jul-16@04:08: 360.58 [#/sec] (mean)
2001-Jul-15@04:08: 351.41 [#/sec] (mean)
2001-Jul-14@04:08: 349.12 [#/sec] (mean)
2001-Jul-13@04:08: 357.30 [#/sec] (mean)
2001-Jul-12@04:08: 366.05 [#/sec] (mean)
2001-Jul-11@04:12: 279.67 [#/sec] (mean)
2001-Jul-10@04:07: 352.86 [#/sec] (mean)
2001-Jul-09@04:07: 383.99 [#/sec] (mean)
2001-Jul-08@04:07: 344.48 [#/sec] (mean)
2001-Jul-07@04:07: 378.27 [#/sec] (mean)
2001-Jul-06@09:11: 372.70 [#/sec] (mean)
2001-Jul-06@04:07: 386.24 [#/sec] (mean)
2001-Jul-05@04:07: 380.36 [#/sec] (mean)
2001-Jul-04@04:07: 385.14 [#/sec] (mean)
2001-Jul-03@04:07: 348.65 [#/sec] (mean)
2001-Jul-02@04:12: 283.10 [#/sec] (mean)
2001-Jul-01@04:12: 286.06 [#/sec] (mean)
2001-Jun-30@04:12: 271.25 [#/sec] (mean)
2001-Jun-29@04:07: 384.02 [#/sec] (mean)
2001-Jun-27@04:10: 345.72 [#/sec] (mean)
2001-Jun-26@04:09: 350.25 [#/sec] (mean)
2001-Jun-25@04:08: 372.60 [#/sec] (mean)
2001-Jun-24@04:09: 342.52 [#/sec] (mean)
2001-Jun-23@04:09: 372.38 [#/sec] (mean)
2001-Jun-22@04:09: 368.48 [#/sec] (mean)
2001-Jun-21@04:09: 358.25 [#/sec] (mean)
2001-Jun-20@04:09: 322.48 [#/sec] (mean)
2001-Jun-19@04:08: 365.27 [#/sec] (mean)
2001-Jun-18@04:09: 377.11 [#/sec] (mean)
2001-Jun-17@04:09: 347.22 [#/sec] (mean)
2001-Jun-16@04:09: 366.59 [#/sec] (mean)
2001-Jun-15@04:09: 353.81 [#/sec] (mean)
2001-Jun-14@04:08: 339.89 [#/sec] (mean)
2001-Jun-13@04:08: 342.75 [#/sec] (mean)
2001-Jun-11@04:07: 341.23 [#/sec] (mean)
2001-Jun-10@04:07: 361.03 [#/sec] (mean)
2001-Jun-09@04:07: 325.13 [#/sec] (mean)
2001-Jun-07@04:07: 371.47 [#/sec] (mean)
2001-Jun-06@04:07: 344.66 [#/sec] (mean)
2001-Jun-05@04:07: 374.36 [#/sec] (mean)
2001-Jun-04@04:07: 348.02 [#/sec] (mean)
2001-Jun-02@04:07: 352.77 [#/sec] (mean)
2001-May-22@04:09: 342.93 [#/sec] (mean)
2001-May-21@04:07: 377.91 [#/sec] (mean)
2001-May-20@04:07: 380.31 [#/sec] (mean)
2001-May-18@04:07: 374.76 [#/sec] (mean)
2001-May-17@04:07: 363.35 [#/sec] (mean)
2001-May-16@04:07: 373.13 [#/sec] (mean)
2001-May-15@04:16: 250.52 [#/sec] (mean)
2001-May-14@04:11: 344.79 [#/sec] (mean)
2001-May-13@04:09: 272.12 [#/sec] (mean)
2001-May-12@04:10: 359.66 [#/sec] (mean)
2001-May-11@04:12: 272.74 [#/sec] (mean)
2001-May-10@04:08: 353.87 [#/sec] (mean)
2001-May-09@04:07: 374.69 [#/sec] (mean)
2001-May-05@04:09: 279.85 [#/sec] (mean)
2001-May-04@04:09: 338.06 [#/sec] (mean)
2001-May-03@04:08: 381.10 [#/sec] (mean)
2001-May-02@04:08: 342.55 [#/sec] (mean)
2001-May-01@04:07: 352.05 [#/sec] (mean)
2001-Apr-30@04:07: 358.79 [#/sec] (mean)
2001-Apr-29@04:06: 328.37 [#/sec] (mean)
2001-Apr-28@04:06: 320.71 [#/sec] (mean)
2001-Apr-27@04:10: 261.01 [#/sec] (mean)
2001-Apr-22@04:06: 357.16 [#/sec] (mean)
2001-Apr-18@04:06: 308.69 [#/sec] (mean)
2001-Apr-17@04:06: 358.33 [#/sec] (mean)
2001-Apr-15@04:06: 352.85 [#/sec] (mean)
2001-Apr-14@04:06: 361.32 [#/sec] (mean)
2001-Apr-13@04:06: 338.66 [#/sec] (mean)
2001-Apr-12@09:26: 354.10 [#/sec] (mean)

-- 
<Ma...@Fujitsu-Siemens.com>         |     Fujitsu Siemens
Fon: +49-89-636-46021, FAX: +49-89-636-47655 | 81730  Munich,  Germany

Re: [2.0] lstat's in spite of AllowOverride None

Posted by Bill Stoddard <bi...@wstoddard.com>.
> From: "Martin Kraemer" <Ma...@Fujitsu-Siemens.com>
> Sent: Wednesday, November 07, 2001 10:23 AM
> 
> 
> > On Wed, Nov 07, 2001 at 09:31:03AM -0600, William A. Rowe, Jr. wrote:
> > > > Yep, of course. Also, the SHMHT (shared memory hash table) might help us
> > > > avoid redundant l?stat()s overall.
> > > 
> > > I'm wondering what the buy will be compared with OS caching?  I'm certain we will
> > > see significantly different improvements depending on the underlying kernel cache.
> > 
> > Right. "Current modern OS's" aren't always as optimized as they could be
> > (someone measured 1000 cps before the forward walk change against around
> > 330 cps after this change, on win2k). And a system call always means
> > (on unix, at least) much higher overhead than a function call.
> 
> The direct-hit method should clear up much of this confusion, since I rather suspect
> that we are also seeing side effects of the recent filtering changes.
> 

The performance hit I am seeing is -definitely- due to the extra stats. No question.

Bill


Re: [2.0] lstat's in spite of AllowOverride None

Posted by "William A. Rowe, Jr." <wr...@covalent.net>.
From: "Martin Kraemer" <Ma...@Fujitsu-Siemens.com>
Sent: Wednesday, November 07, 2001 10:23 AM


> On Wed, Nov 07, 2001 at 09:31:03AM -0600, William A. Rowe, Jr. wrote:
> > > Yep, of course. Also, the SHMHT (shared memory hash table) might help us
> > > avoid redundant l?stat()s overall.
> > 
> > I'm wondering what the buy will be compared with OS caching?  I'm certain we will
> > see significantly different improvements depending on the underlying kernel cache.
> 
> Right. "Current modern OS's" aren't always as optimized as they could be
> (someone measured 1000 cps before the forward walk change against around
> 330 cps after this change, on win2k). And a system call always means
> (on unix, at least) much higher overhead than a function call.

The direct-hit method should clear up much of this confusion, since I rather suspect
that we are also seeing side effects of the recent filtering changes.


Re: [2.0] lstat's in spite of AllowOverride None

Posted by Martin Kraemer <Ma...@Fujitsu-Siemens.com>.
On Wed, Nov 07, 2001 at 09:31:03AM -0600, William A. Rowe, Jr. wrote:
> > Yep, of course. Also, the SHMHT (shared memory hash table) might help us
> > avoid redundant l?stat()s overall.
> 
> I'm wondering what the buy will be compared with OS caching?  I'm certain we will
> see significantly different improvements depending on the underlying kernel cache.

Right. "Current modern OS's" aren't always as optimized as they could be
(someone measured 1000 cps before the forward walk change against around
330 cps after this change, on win2k). And a system call always means
(on unix, at least) much higher overhead than a function call.

  Martin
-- 
<Ma...@Fujitsu-Siemens.com>         |     Fujitsu Siemens
Fon: +49-89-636-46021, FAX: +49-89-636-47655 | 81730  Munich,  Germany

Re: [2.0] lstat's in spite of AllowOverride None

Posted by "William A. Rowe, Jr." <wr...@covalent.net>.
From: "Martin Kraemer" <Ma...@Fujitsu-Siemens.com>
Sent: Wednesday, November 07, 2001 8:43 AM


> On Wed, Nov 07, 2001 at 02:14:03PM +0000, James A Sutherland wrote:
> > So how about:
> > 
> > 1. stat() the full path (as was done before).
> > 2. IF this fails, stat "forwards" component by component, as is done now.
> > 
> > This avoids the DoS of sending /a/a/a/a/a/a/a... - you do a single stat() on 
> > the full path, which fails, then stat() "forwards" as now.
> 
> Or how is this:
> 
>   2. IF the full path l?stat() failed, AND errno == ENOTDIR, THEN:
>      do a binary-search approach (locate the mid-'/'-component's path,
>      try l?stat(), if it also returns errno == ENOTDIR, repeat cutting the
>      path in half, until some hit is found. This hit is the valid resource,
>      or the resource's directory, and the reminder is the PATH_INFO
>      to be pased to it.
>      Example:
>        /a/b/c/d/e/f/g/h     -> ENOTDIR
>        /a/b/c/d             -> ENOTDIR
>        /a/b                 -> ENOENT
>        => filename="/a/index.html" PATH_INFO="/b"

actually... that's => filename="/a/b" PATH_INFO="/c/d/e/f/g/h", not found 

I considered that approach - and decided some time back that I'm ardently against
proliferating the old path_info approach, in spite of some obvious optimizations.
It's a lose-lose approach.

Consider any case-ambigious filesystem.  We already have to walk forward and fix
the paths.  Consider symlinks, we have to walk forward.  Consider check_safe_file,
we have to walk forward.  And consider directory sections, we have to apply them
forward.

Given the weight of these, and the duplication of effort in 1.3, this is far more
optimal.  Now the real question, what, walking forwards, can we optimize away?

Once we lose on the 'try a direct hit' optimization, walking forwards make a
tremendous amount of sense.  You are forgetting the caching in all modern file
systems, stating some remote branch is highly inefficient, while stating the root
should be far more optimal since it's much more likely to reside in the os cache.


>   3. IF the full path l?stat() failed, BUT errno != ENOTDIR, THEN
>      stat "forwards" component by component, as is done now.

That's what I'm getting at.  But we can optimize that further, if we insist to
admins that something declared <Directory > will be treated as a directory, and
if that wasn't the desired behavior, why did they add that <Directory > section
in the first place?  But I'm getting ahead of myself.


> > The common case should be that there is a normal file at the end of that 
> > path, so we should skip straight to the final stat() where possible IMO...
> 
> This is true for the majority of cases, and should therefore be
> the most optimized code path.

Agreed... that's the patch I'm writing right now.  But I need to think through if
we want a first-try for an lstat or a stat.  Realize we lose nothing unless it is
a symlink, and if it is a symlink, I need to think through the consiquences.

We already enjoy this case from sub_req_lookup_dirent, which already gave us our
lstat() result.  So that's the case I'm optimizing first, so that lookup_dirent's
will be zero additional stats, and lookup_file and most properly configured requests
will be single stat.


> > Caching the lstat() results should help, but reducing to a single stat() as I 
> > suggest would seem better still?
> 
> Yep, of course. Also, the SHMHT (shared memory hash table) might help us
> avoid redundant l?stat()s overall.

I'm wondering what the buy will be compared with OS caching?  I'm certain we will
see significantly different improvements depending on the underlying kernel cache.




Re: [2.0] lstat's in spite of AllowOverride None

Posted by Martin Kraemer <Ma...@Fujitsu-Siemens.com>.
On Wed, Nov 07, 2001 at 03:43:52PM +0100, Kraemer, Martin wrote:
>   3. IF the full path l?stat() failed, BUT errno != ENOTDIR, THEN
>      stat "forwards" component by component, as is done now.

Or use the same cut-in-half-and-retry strategy for 3. as well?

  Martin
-- 
<Ma...@Fujitsu-Siemens.com>         |     Fujitsu Siemens
Fon: +49-89-636-46021, FAX: +49-89-636-47655 | 81730  Munich,  Germany

Re: [2.0] lstat's in spite of AllowOverride None

Posted by Martin Kraemer <Ma...@Fujitsu-Siemens.com>.
On Wed, Nov 07, 2001 at 02:14:03PM +0000, James A Sutherland wrote:
> So how about:
> 
> 1. stat() the full path (as was done before).
> 2. IF this fails, stat "forwards" component by component, as is done now.
> 
> This avoids the DoS of sending /a/a/a/a/a/a/a... - you do a single stat() on 
> the full path, which fails, then stat() "forwards" as now.

Or how is this:

  2. IF the full path l?stat() failed, AND errno == ENOTDIR, THEN:
     do a binary-search approach (locate the mid-'/'-component's path,
     try l?stat(), if it also returns errno == ENOTDIR, repeat cutting the
     path in half, until some hit is found. This hit is the valid resource,
     or the resource's directory, and the reminder is the PATH_INFO
     to be pased to it.
     Example:
       /a/b/c/d/e/f/g/h     -> ENOTDIR
       /a/b/c/d             -> ENOTDIR
       /a/b                 -> ENOENT
       => filename="/a/index.html" PATH_INFO="/b"

  3. IF the full path l?stat() failed, BUT errno != ENOTDIR, THEN
     stat "forwards" component by component, as is done now.

> The common case should be that there is a normal file at the end of that 
> path, so we should skip straight to the final stat() where possible IMO...

This is true for the majority of cases, and should therefore be
the most optimized code path.

> Caching the lstat() results should help, but reducing to a single stat() as I 
> suggest would seem better still?

Yep, of course. Also, the SHMHT (shared memory hash table) might help us
avoid redundant l?stat()s overall.

   Martin
-- 
<Ma...@Fujitsu-Siemens.com>         |     Fujitsu Siemens
Fon: +49-89-636-46021, FAX: +49-89-636-47655 | 81730  Munich,  Germany

Re: [2.0] lstat's in spite of AllowOverride None

Posted by dean gaudet <de...@arctic.org>.
On Fri, 9 Nov 2001, Michael Douglass wrote:

> I'd be weary of caching the lstat() information for more than the
> current connection; you don't want someone to abuse that cache by
> creating a symlink AFTER letting apache cache the information.

if an attacker can create symlinks they can just as easily copy
/etc/passwd or other sensitive world-readable data.

!FollowSymLinks is stupid anyhow, it should die.  who even pretends that
it helps system security?  for perf reasons we changed httpd.conf ages ago
to default to FollowSymLinks, and i bet 99% of the apaches out there run
this way.

years ago i suggested something such as
<http://arctic.org/~dean/apache/1.3/mod_allowdev.c>.  if you really think
FollowSymLinks is useful then mod_allowdev probably makes even more sense.

-dean


Re: [2.0] lstat's in spite of AllowOverride None

Posted by Michael Douglass <mi...@staff.texas.net>.
> > As FirstBill suggests, there are other means for caching the (l)stat
> > results, at least for the request duration, which need to be deployed.  But
> > dropping the path_info walk-backwards logic was step one.  Any optimization
> > patches are entertianed to speed up the server, if we don't lose stability.
> 
> Caching the lstat() results should help, but reducing to a single stat() as I 
> suggest would seem better still?

I'd be weary of caching the lstat() information for more than the current
connection; you don't want someone to abuse that cache by creating a
symlink AFTER letting apache cache the information.

Anyone think about using resolvepath() as an initial check?  resolvepath()
is a single system call to take a path to a file and convert it to the
resultant path after following all symlinks.  Thus you could have a single
call to resolvepath() and strcmp() to see if there were any symlinks in
the path--if there were then you either "deny" it if symlinks are not
allowed at all; or you proceed with the lstat() scheme otherwise.

This would seem to circumvent alot of lstat() calls on the (hopefully)
normal case that there are no symlinks involved anywhere. :)

-- 
Michael Douglass
Chief System Engineer
Texas Networking, Inc.  (512-794-7123)

Re: [2.0] lstat's in spite of AllowOverride None

Posted by James A Sutherland <ja...@cam.ac.uk>.
On Wednesday 07 November 2001 2:02 pm, you wrote:
> From: "Martin Kraemer" <Ma...@Fujitsu-Siemens.com>
> Sent: Wednesday, November 07, 2001 3:11 AM
>
> > When I do a grep for "AllowOverride" in my current config, I get:
> > 312:    AllowOverride None
> > [...]
> >
> > In spite of this, when tracing an access to a read-only file, I see:
> >  ...
> >  lstat("/home",0xbfbff890)                        = 0 (0x0)
> >  lstat("/home/www",0xbfbff890)                    = 0 (0x0)
> >  lstat("/home/www/SERVER",0xbfbff890)             = 0 (0x0)
> >  lstat("/home/www/SERVER/apa20",0xbfbff890)       = 0 (0x0)
> >  lstat("/home/www/SERVER/apa20/htdocs",0xbfbff890) = 0 (0x0)
> >  lstat("/home/www/SERVER/apa20/htdocs/noread.html",0xbfbff890) = 0 (0x0)
> >
> > Where do all the lstats() come from, and *WHY* do they happen at all?
> >
> > On Wed, Nov 07, 2001 at 09:32:37AM +0000, James A Sutherland wrote:
> > > Checking for symlinks, I think? Check for Options FollowSymLinks.
> >
> > It is set for the dir in question (and everywhere above it), so it
> > needn't (shouldn't) do any lstat()s IMHO.
>
> Before the rewrite of dir_walk, a request for /noread.html/some/path/info
> would do the following;
>
> stat("/home/www/SERVER/apa20/htdocs/noread.html/some/path/info") = ENOTDIR
> stat("/home/www/SERVER/apa20/htdocs/noread.html/some/path") = ENOTDIR
> stat("/home/www/SERVER/apa20/htdocs/noread.html/some") = ENOTDIR
> stat("/home/www/SERVER/apa20/htdocs/noread.html") = 0
>
> With a very long path, this actually amounted to a rather nasty denial of
> service.  Then we stat'ed forward, followed by an lstat, for each directory
> where FollowSymLinks was set to owner.
>
> Now that we run the path forward, a request like /a/a/a/a/a... won't
> generate hundreds (thousands) of stat calls.  It will die as soon as a file
> is found/not found.  The rewrite of dir_walk first eliminated the
> get_path_info function and folded that code back into dir_walk.

Which avoids the DoS risk, but adds lots of stat() calls to the common case...

> The advantage to lstat() was trivial; we don't waste time checking symlinks
> where there are no symlinks.  Even symlinking to an evil entity (char/block
> device) won't succeed, because we only permit symlinks to regular files and
> directories.  Any non-symlink simply returns it's actual identity and the
> 'symlink check' is not required.

So how about:

1. stat() the full path (as was done before).
2. IF this fails, stat "forwards" component by component, as is done now.

This avoids the DoS of sending /a/a/a/a/a/a/a... - you do a single stat() on 
the full path, which fails, then stat() "forwards" as now.

> Now the question becomes, if walking the path backwards is (generally) not
> a good answer, what is?  I've suggested (in comments within the code) that
> we walk the path forward, and if we enounter a <Directory > block that
> identifies the path thus far and has followsymlinks set, we skip all stats
> (until we have no path info, then we must stat the final target, even as a
> directory).  Go on to the next element and then, if we get ENOTDIR,
> consider the result a misconfiguration, since the admin purported that
> /some/path is a <Directory >.

The common case should be that there is a normal file at the end of that 
path, so we should skip straight to the final stat() where possible IMO...

> As FirstBill suggests, there are other means for caching the (l)stat
> results, at least for the request duration, which need to be deployed.  But
> dropping the path_info walk-backwards logic was step one.  Any optimization
> patches are entertianed to speed up the server, if we don't lose stability.

Caching the lstat() results should help, but reducing to a single stat() as I 
suggest would seem better still?


James.

Re: [2.0] lstat's in spite of AllowOverride None

Posted by "William A. Rowe, Jr." <wr...@covalent.net>.
From: "Martin Kraemer" <Ma...@Fujitsu-Siemens.com>
Sent: Wednesday, November 07, 2001 3:11 AM


> When I do a grep for "AllowOverride" in my current config, I get:
> 312:    AllowOverride None
> [...]
> 
> In spite of this, when tracing an access to a read-only file, I see:
>  ...
>  lstat("/home",0xbfbff890)                        = 0 (0x0)
>  lstat("/home/www",0xbfbff890)                    = 0 (0x0)
>  lstat("/home/www/SERVER",0xbfbff890)             = 0 (0x0)
>  lstat("/home/www/SERVER/apa20",0xbfbff890)       = 0 (0x0)
>  lstat("/home/www/SERVER/apa20/htdocs",0xbfbff890) = 0 (0x0)
>  lstat("/home/www/SERVER/apa20/htdocs/noread.html",0xbfbff890) = 0 (0x0)
> 
> Where do all the lstats() come from, and *WHY* do they happen at all?

> On Wed, Nov 07, 2001 at 09:32:37AM +0000, James A Sutherland wrote:
> > 
> > Checking for symlinks, I think? Check for Options FollowSymLinks.
> 
> It is set for the dir in question (and everywhere above it), so it needn't
> (shouldn't) do any lstat()s IMHO.

Before the rewrite of dir_walk, a request for /noread.html/some/path/info 
would do the following;

stat("/home/www/SERVER/apa20/htdocs/noread.html/some/path/info") = ENOTDIR
stat("/home/www/SERVER/apa20/htdocs/noread.html/some/path") = ENOTDIR
stat("/home/www/SERVER/apa20/htdocs/noread.html/some") = ENOTDIR
stat("/home/www/SERVER/apa20/htdocs/noread.html") = 0

With a very long path, this actually amounted to a rather nasty denial of 
service.  Then we stat'ed forward, followed by an lstat, for each directory 
where FollowSymLinks was set to owner.

Now that we run the path forward, a request like /a/a/a/a/a... won't generate 
hundreds (thousands) of stat calls.  It will die as soon as a file is found/not 
found.  The rewrite of dir_walk first eliminated the get_path_info function and 
folded that code back into dir_walk.

The advantage to lstat() was trivial; we don't waste time checking symlinks 
where there are no symlinks.  Even symlinking to an evil entity (char/block 
device) won't succeed, because we only permit symlinks to regular files and 
directories.  Any non-symlink simply returns it's actual identity and the
'symlink check' is not required.

Now the question becomes, if walking the path backwards is (generally) not a 
good answer, what is?  I've suggested (in comments within the code) that we 
walk the path forward, and if we enounter a <Directory > block that identifies 
the path thus far and has followsymlinks set, we skip all stats (until we have 
no path info, then we must stat the final target, even as a directory).  Go on 
to the next element and then, if we get ENOTDIR, consider the result a 
misconfiguration, since the admin purported that /some/path is a <Directory >.

As FirstBill suggests, there are other means for caching the (l)stat results,
at least for the request duration, which need to be deployed.  But dropping the
path_info walk-backwards logic was step one.  Any optimization patches are
entertianed to speed up the server, if we don't lose stability.

Bill





Re: [2.0] lstat's in spite of AllowOverride None

Posted by Stas Bekman <st...@stason.org>.
William A. Rowe, Jr. wrote:

> From: "Stas Bekman" <st...@stason.org>
> Sent: Wednesday, November 07, 2001 10:49 PM
> 
> 
> 
>>If we end up still having stat() calls in the default setup, have you 
>>considered to have some config option to skip all stat() calls if the 
>>user knows what he does.
>>
>>Some people use path info as CGI arguments. Consider the following request:
>>
>>   /service/news/apache/httpd/dev
>>
>>and config:
>>
>><Location /service>
>>...
>>
> 
> I will presume that this not a physical file for sake of discussion...


I suppose it doesn't matter if the walk is implemented backwards. If 
it's implemented as walk forward, then yes, this is only relevant if the 
entry is virtual.


>>This request will generate at least 5 stat() calls until it hits 
>>/service. In mod_perl things are easy, we just write a custom 
>>transhandler which runs "instead" of the default one and doesn't do the 
>>stats if path_info starts with /service. You cannot do this with plain 
>>httpd configuration.
>>
> 
> Err... let me clarify [and yes - I think we could introduce such a feature
> for the simple API.]
> 
> The map_to_storage hook was designed for just your argument - a URI that
> doesn't correspond to a traditional 'file'.  While most modules have yet
> to take advantage of it, mod_proxy is a good example of it's use.  Rather
> than overload 'proxy:' cruft onto Directories, mod_proxy for 2.0 uses the
> map_to_storage hook to replace the dir/file walks with a proxy_walk that
> more closely maps to proxied content.
> 
> Of course, a mod_perl user could simply create such a hook handler, 
> registered as HOOK_MIDDLE, and return OK to convice the system not to
> treat the request as a file-request.


yes, a mod_perl user has an almost complete power over overriding 
httpd's defaults. I just gave it as counter-example for non-mod_perl 
user, who cannot do it via config directives.


> A CGI app, as you point out, isn't the same beast.  Perhaps that would be
> a very worthwhile idea, to allow the user to (intellegently) override that
> file/dir walk.  Of course, once they do that, they cannot use r->filename
> to serve such a request from the default handler, since the default handler
> only deals with files.
> 
> With appropriate protection, this is worthwhile to consider.


Great!


>>I could think of an optimization, where if a special option is set and 
>>httpd sees a path info which matches an entry in a special table that 
>>can be populated by some config option called from Location/Directory 
>>entries, it'll complete the transhandler stage immediately. Something like:
>>
>><Location /service>
>>TransHandler Shortcut
>>....
>>
>>and the special lookup table will store:
>>
>>/service
>>
>>and the code will first check this table to see if there is a match, 
>>before doing stat()s.
>>
>>Of course there can be a different location:
>>
>><Location /service/new>
>>which will then break, unless this Location registers itself into the 
>>table as well. But that's up to user to figure that out.
>>
>>The point is to let users improve performance in special cases, without 
>>doing special coding.
>>
>>I hope you understand what I mean.
>>
> 
> I believe I do.  I actually contemplated an alternative to DocumentRoot
> that might leave the URI entirely 'unrooted'.  I actually wish to see the
> user able to change the DocumentRoot at any <Location > point.  But that is
> all for 2.1 at this point, I expect, since so many are anxious to see a real,
> finished 2.0 release :)

That's fine with me. Alternatively those who need to mess with default behavior 

to improve performance can run mod_perl :)


Thanks Bill.

-- 


_____________________________________________________________________
Stas Bekman             JAm_pH      --   Just Another mod_perl Hacker
http://stason.org/      mod_perl Guide   http://perl.apache.org/guide
mailto:stas@stason.org  http://ticketmaster.com http://apacheweek.com
http://singlesheaven.com http://perl.apache.org http://perlmonth.com/


Re: [2.0] lstat's in spite of AllowOverride None

Posted by "William A. Rowe, Jr." <wr...@covalent.net>.
From: "Stas Bekman" <st...@stason.org>
Sent: Wednesday, November 07, 2001 10:49 PM


> If we end up still having stat() calls in the default setup, have you 
> considered to have some config option to skip all stat() calls if the 
> user knows what he does.
> 
> Some people use path info as CGI arguments. Consider the following request:
> 
>    /service/news/apache/httpd/dev
> 
> and config:
> 
> <Location /service>
> ...

I will presume that this not a physical file for sake of discussion...

> This request will generate at least 5 stat() calls until it hits 
> /service. In mod_perl things are easy, we just write a custom 
> transhandler which runs "instead" of the default one and doesn't do the 
> stats if path_info starts with /service. You cannot do this with plain 
> httpd configuration.

Err... let me clarify [and yes - I think we could introduce such a feature
for the simple API.]

The map_to_storage hook was designed for just your argument - a URI that
doesn't correspond to a traditional 'file'.  While most modules have yet
to take advantage of it, mod_proxy is a good example of it's use.  Rather
than overload 'proxy:' cruft onto Directories, mod_proxy for 2.0 uses the
map_to_storage hook to replace the dir/file walks with a proxy_walk that
more closely maps to proxied content.

Of course, a mod_perl user could simply create such a hook handler, 
registered as HOOK_MIDDLE, and return OK to convice the system not to
treat the request as a file-request.

A CGI app, as you point out, isn't the same beast.  Perhaps that would be
a very worthwhile idea, to allow the user to (intellegently) override that
file/dir walk.  Of course, once they do that, they cannot use r->filename
to serve such a request from the default handler, since the default handler
only deals with files.

With appropriate protection, this is worthwhile to consider.

> I could think of an optimization, where if a special option is set and 
> httpd sees a path info which matches an entry in a special table that 
> can be populated by some config option called from Location/Directory 
> entries, it'll complete the transhandler stage immediately. Something like:
> 
> <Location /service>
> TransHandler Shortcut
> ....
> 
> and the special lookup table will store:
> 
> /service
> 
> and the code will first check this table to see if there is a match, 
> before doing stat()s.
> 
> Of course there can be a different location:
> 
> <Location /service/new>
> which will then break, unless this Location registers itself into the 
> table as well. But that's up to user to figure that out.
> 
> The point is to let users improve performance in special cases, without 
> doing special coding.
> 
> I hope you understand what I mean.

I believe I do.  I actually contemplated an alternative to DocumentRoot
that might leave the URI entirely 'unrooted'.  I actually wish to see the
user able to change the DocumentRoot at any <Location > point.  But that is
all for 2.1 at this point, I expect, since so many are anxious to see a real,
finished 2.0 release :)

Bill


Re: [2.0] lstat's in spite of AllowOverride None

Posted by Stas Bekman <st...@stason.org>.
If we end up still having stat() calls in the default setup, have you 
considered to have some config option to skip all stat() calls if the 
user knows what he does.

Some people use path info as CGI arguments. Consider the following request:

   /service/news/apache/httpd/dev

and config:

<Location /service>
...

This request will generate at least 5 stat() calls until it hits 
/service. In mod_perl things are easy, we just write a custom 
transhandler which runs "instead" of the default one and doesn't do the 
stats if path_info starts with /service. You cannot do this with plain 
httpd configuration.

I could think of an optimization, where if a special option is set and 
httpd sees a path info which matches an entry in a special table that 
can be populated by some config option called from Location/Directory 
entries, it'll complete the transhandler stage immediately. Something like:

<Location /service>
TransHandler Shortcut
....

and the special lookup table will store:

/service

and the code will first check this table to see if there is a match, 
before doing stat()s.

Of course there can be a different location:

<Location /service/new>
which will then break, unless this Location registers itself into the 
table as well. But that's up to user to figure that out.

The point is to let users improve performance in special cases, without 
doing special coding.

I hope you understand what I mean.

_____________________________________________________________________
Stas Bekman             JAm_pH      --   Just Another mod_perl Hacker
http://stason.org/      mod_perl Guide   http://perl.apache.org/guide
mailto:stas@stason.org  http://ticketmaster.com http://apacheweek.com
http://singlesheaven.com http://perl.apache.org http://perlmonth.com/


Re: [2.0] lstat's in spite of AllowOverride None

Posted by Brian Pane <bp...@pacbell.net>.
Bill Stoddard wrote:
[...]

>Apache will always be dead last in performance comparisions, and by a wide embarassing
>margin, until we get rid of these stats.
>

s/embarassing/expensive/g for people using NFS, where those stats increase
the number of NFS ops per second required to support a given level of HTTP
traffic.

--Brian



Re: [2.0] lstat's in spite of AllowOverride None

Posted by Bill Stoddard <bi...@wstoddard.com>.
The stat()s are a result of Bill Rowe's rewrite of directory_walk. The additional stats
are intentional and by design.  And we desperately need to eliminate them (perhaps by
caching directory_walk results for some time period).

Apache will always be dead last in performance comparisions, and by a wide embarassing
margin, until we get rid of these stats. The rest of the server can be tuned to take 0 CPU
cycles and we will still be last in the performance race with these stats hanging around.

Bill

----- Original Message -----
From: "Martin Kraemer" <Ma...@Fujitsu-Siemens.com>
To: <de...@httpd.apache.org>
Sent: Wednesday, November 07, 2001 4:11 AM
Subject: [2.0] lstat's in spite of AllowOverride None


> When I do a grep for "AllowOverride" in my current config, I get:
> 312:    AllowOverride None
> 341:    AllowOverride None
> 371:#    AllowOverride FileInfo AuthConfig Limit
> 523:    AllowOverride None
> 537:    AllowOverride None
> 569:    AllowOverride None
> 897:        AllowOverride None
>
> In spite of this, when tracing an access to a read-only file, I see:
>  ...
>  lstat("/home",0xbfbff890)                        = 0 (0x0)
>  lstat("/home/www",0xbfbff890)                    = 0 (0x0)
>  lstat("/home/www/SERVER",0xbfbff890)             = 0 (0x0)
>  lstat("/home/www/SERVER/apa20",0xbfbff890)       = 0 (0x0)
>  lstat("/home/www/SERVER/apa20/htdocs",0xbfbff890) = 0 (0x0)
>  lstat("/home/www/SERVER/apa20/htdocs/noread.html",0xbfbff890) = 0 (0x0)
>  open("/home/www/SERVER/apa20/htdocs/noread.html",0,00) ERR#13 'Permission denied'
>  gettimeofday(0xbfbfb874,0x0)                     = 0 (0x0)
>  write(2,0xbfbfb920,161)                          = 161 (0xa1)
>  lstat("/home",0xbfbff800)                        = 0 (0x0)
>  lstat("/home/www",0xbfbff800)                    = 0 (0x0)
>  lstat("/home/www/SERVER",0xbfbff800)             = 0 (0x0)
>  lstat("/home/www/SERVER/apa20",0xbfbff800)       = 0 (0x0)
>  lstat("/home/www/SERVER/apa20/error",0xbfbff800) = 0 (0x0)
>  lstat("/home/www/SERVER/apa20/error/HTTP_FORBIDDEN.html.var",0xbfbff800) = 0 (0x0)
>  open("/home/www/SERVER/apa20/error/HTTP_FORBIDDEN.html.var",0,0666) = 17 (0x11)
>  ....
>
> Where do all the lstats() come from, and *WHY* do they happen at all?
>
>   Martin
> --
> <Ma...@Fujitsu-Siemens.com>         |     Fujitsu Siemens
> Fon: +49-89-636-46021, FAX: +49-89-636-47655 | 81730  Munich,  Germany
>