main: avoid a stat when possible

Signed-off-by: Giuseppe Scrivano <gscrivan@redhat.com>
This commit is contained in:
Giuseppe Scrivano 2019-07-13 22:18:19 +02:00
parent 4056a2a84a
commit d9c5215e33
No known key found for this signature in database
GPG Key ID: E4730F97F60286ED

26
main.c
View File

@ -1050,7 +1050,8 @@ get_whiteout_name (const char *name, struct stat *st)
{ {
if (has_prefix (name, ".wh.")) if (has_prefix (name, ".wh."))
return name + 4; return name + 4;
if ((st->st_mode & S_IFMT) == S_IFCHR if (st
&& (st->st_mode & S_IFMT) == S_IFCHR
&& major (st->st_rdev) == 0 && major (st->st_rdev) == 0
&& minor (st->st_rdev) == 0) && minor (st->st_rdev) == 0)
return name; return name;
@ -1061,7 +1062,6 @@ static struct ovl_node *
load_dir (struct ovl_data *lo, struct ovl_node *n, struct ovl_layer *layer, char *path, char *name) load_dir (struct ovl_data *lo, struct ovl_node *n, struct ovl_layer *layer, char *path, char *name)
{ {
struct dirent *dent; struct dirent *dent;
struct stat st;
struct ovl_layer *it, *upper_layer = get_upper_layer (lo); struct ovl_layer *it, *upper_layer = get_upper_layer (lo);
if (!n) if (!n)
@ -1093,7 +1093,6 @@ load_dir (struct ovl_data *lo, struct ovl_node *n, struct ovl_layer *layer, char
{ {
int ret; int ret;
struct ovl_node key; struct ovl_node key;
const char *wh;
struct ovl_node *child = NULL; struct ovl_node *child = NULL;
char node_path[PATH_MAX]; char node_path[PATH_MAX];
char whiteout_path[PATH_MAX]; char whiteout_path[PATH_MAX];
@ -1113,9 +1112,6 @@ load_dir (struct ovl_data *lo, struct ovl_node *n, struct ovl_layer *layer, char
if ((strcmp (dent->d_name, ".") == 0) || strcmp (dent->d_name, "..") == 0) if ((strcmp (dent->d_name, ".") == 0) || strcmp (dent->d_name, "..") == 0)
continue; continue;
if (TEMP_FAILURE_RETRY (fstatat (fd, dent->d_name, &st, AT_SYMLINK_NOFOLLOW)) < 0)
return NULL;
child = hash_lookup (n->children, &key); child = hash_lookup (n->children, &key);
if (child) if (child)
{ {
@ -1152,7 +1148,24 @@ load_dir (struct ovl_data *lo, struct ovl_node *n, struct ovl_layer *layer, char
} }
else else
{ {
const char *wh = NULL;
bool dirp = dent->d_type == DT_DIR;
if ((dent->d_type != DT_CHR) && (dent->d_type != DT_UNKNOWN))
wh = get_whiteout_name (dent->d_name, NULL);
else
{
/* A stat is required either if the type is not known, or if it is a character device as it could be
a whiteout file. */
struct stat st;
if (TEMP_FAILURE_RETRY (fstatat (fd, dent->d_name, &st, AT_SYMLINK_NOFOLLOW)) < 0)
return NULL;
dirp = st.st_mode & S_IFDIR;
wh = get_whiteout_name (dent->d_name, &st); wh = get_whiteout_name (dent->d_name, &st);
}
if (wh) if (wh)
{ {
child = make_whiteout_node (node_path, wh); child = make_whiteout_node (node_path, wh);
@ -1164,7 +1177,6 @@ load_dir (struct ovl_data *lo, struct ovl_node *n, struct ovl_layer *layer, char
} }
else else
{ {
bool dirp = st.st_mode & S_IFDIR;
child = make_ovl_node (node_path, it, dent->d_name, 0, dirp, n); child = make_ovl_node (node_path, it, dent->d_name, 0, dirp, n);
if (child == NULL) if (child == NULL)