Skip to content

Commit 694887a

Browse files
committed
ext/standard/filestat: omit access()/stat() system calls for cached scripts
1 parent 51f195a commit 694887a

File tree

3 files changed

+43
-0
lines changed

3 files changed

+43
-0
lines changed

ext/opcache/ZendAccelerator.c

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -235,6 +235,29 @@ static bool check_validate_timestamps_fh(const zend_file_handle *file_handle)
235235
return check_validate_timestamps_zstr(path);
236236
}
237237

238+
bool is_persistent_script(const zend_string *filename)
239+
{
240+
if (!IS_ABSOLUTE_PATH(ZSTR_VAL(filename), ZSTR_LEN(filename)))
241+
return false;
242+
243+
zend_string *key = normalize_path(filename);
244+
const zend_persistent_script *const persistent_script = zend_accel_hash_find(&ZCSG(hash), key);
245+
zend_string_efree(key);
246+
if (persistent_script == NULL || persistent_script->corrupted)
247+
return false;
248+
249+
if (persistent_script->timestamp == 0)
250+
/* preloaded, no validation */
251+
return true;
252+
253+
if (check_validate_timestamps_zstr(filename) &&
254+
(ZCG(accel_directives).revalidate_freq == 0 ||
255+
persistent_script->dynamic_members.revalidate < ZCG(request_time)))
256+
return false;
257+
258+
return true;
259+
}
260+
238261
/* O+ overrides PHP chdir() function and remembers the current working directory
239262
* in ZCG(cwd) and ZCG(cwd_len). Later accel_getcwd() can use stored value and
240263
* avoid getcwd() call.

ext/opcache/ZendAccelerator.h

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -334,6 +334,12 @@ BEGIN_EXTERN_C()
334334

335335
bool check_validate_timestamps_zstr(const zend_string *filename);
336336

337+
/**
338+
* Is the specified filename a cached script whose time stamp does not
339+
* need to be revalidated currently?
340+
*/
341+
bool is_persistent_script(const zend_string *filename);
342+
337343
void accel_shutdown(void);
338344
zend_result accel_activate(INIT_FUNC_ARGS);
339345
zend_result accel_post_deactivate(void);

ext/standard/filestat.c

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,8 @@
1818
#include "fopen_wrappers.h"
1919
#include "php_globals.h"
2020

21+
#include "ext/opcache/ZendAccelerator.h" // for is_persistent_script()
22+
2123
#include <stdlib.h>
2224
#include <sys/stat.h>
2325
#include <string.h>
@@ -746,6 +748,18 @@ PHPAPI void php_stat(zend_string *filename, int type, zval *return_value)
746748
const char *local = NULL;
747749
php_stream_wrapper *wrapper = NULL;
748750

751+
if ((type == FS_EXISTS || type == FS_IS_R || type == FS_IS_FILE) &&
752+
/* is an absolute path that ends with ".php" */
753+
ZSTR_LEN(filename) >= 6 &&
754+
ZSTR_VAL(filename)[0] == '/' &&
755+
memcmp(ZSTR_VAL(filename) + ZSTR_LEN(filename) - 4, ".php", 4) == 0 &&
756+
is_persistent_script(filename)) {
757+
/* this is a cached script and its time stamp does not
758+
* need revalidation - we can safely pretend it exists
759+
* and it is a regular file */
760+
RETURN_TRUE;
761+
}
762+
749763
if (IS_ACCESS_CHECK(type)) {
750764
if (!ZSTR_LEN(filename) || CHECK_NULL_PATH(ZSTR_VAL(filename), ZSTR_LEN(filename))) {
751765
if (ZSTR_LEN(filename) && !IS_EXISTS_CHECK(type)) {

0 commit comments

Comments
 (0)