diff options
Diffstat (limited to 'fs/overlayfs/readdir.c')
-rw-r--r-- | fs/overlayfs/readdir.c | 37 |
1 files changed, 37 insertions, 0 deletions
diff --git a/fs/overlayfs/readdir.c b/fs/overlayfs/readdir.c index fdaf28f..18d0a16 100644 --- a/fs/overlayfs/readdir.c +++ b/fs/overlayfs/readdir.c @@ -43,6 +43,7 @@ struct ovl_readdir_data { struct ovl_cache_entry *first_maybe_whiteout; int count; int err; + bool d_type_supported; }; struct ovl_dir_file { @@ -577,3 +578,39 @@ void ovl_cleanup_whiteouts(struct dentry *upper, struct list_head *list) } inode_unlock(upper->d_inode); } + +static int ovl_check_d_type(struct dir_context *ctx, const char *name, + int namelen, loff_t offset, u64 ino, + unsigned int d_type) +{ + struct ovl_readdir_data *rdd = + container_of(ctx, struct ovl_readdir_data, ctx); + + /* Even if d_type is not supported, DT_DIR is returned for . and .. */ + if (!strncmp(name, ".", namelen) || !strncmp(name, "..", namelen)) + return 0; + + if (d_type != DT_UNKNOWN) + rdd->d_type_supported = true; + + return 0; +} + +/* + * Returns 1 if d_type is supported, 0 not supported/unknown. Negative values + * if error is encountered. + */ +int ovl_check_d_type_supported(struct path *realpath) +{ + int err; + struct ovl_readdir_data rdd = { + .ctx.actor = ovl_check_d_type, + .d_type_supported = false, + }; + + err = ovl_dir_read(realpath, &rdd); + if (err) + return err; + + return rdd.d_type_supported; +} |