From 05cc50945f8216f679f601f7ea2b53aa2b95c3a4 Mon Sep 17 00:00:00 2001 From: Dmitrii Kuvaiskii Date: Tue, 10 Dec 2019 20:09:01 -0800 Subject: [PATCH] [LibOS] Allow inaccessible files during getdents() Previously, if user performed getdents() on a directory containing inaccessible files (because user doesn't have permission), whole getdents failed with -EACCES. This is incorrect behavior: files must still be listed. This commit fixes the root cause of this bug by marking inaccessible files as DENTRY_NEGATIVE. --- LibOS/shim/include/shim_fs.h | 2 +- LibOS/shim/src/fs/shim_namei.c | 15 ++++++++++----- 2 files changed, 11 insertions(+), 6 deletions(-) diff --git a/LibOS/shim/include/shim_fs.h b/LibOS/shim/include/shim_fs.h index 23006d0d..f1ef4323 100644 --- a/LibOS/shim/include/shim_fs.h +++ b/LibOS/shim/include/shim_fs.h @@ -104,7 +104,7 @@ struct shim_fs_ops { }; #define DENTRY_VALID 0x0001 /* this dentry is verified to be valid */ -#define DENTRY_NEGATIVE 0x0002 /* negative, recently deleted */ +#define DENTRY_NEGATIVE 0x0002 /* recently deleted or inaccessible */ #define DENTRY_RECENTLY 0x0004 /* recently used */ #define DENTRY_PERSIST 0x0008 /* added as a persistent dentry */ #define DENTRY_HASHED 0x0010 /* added in the dcache */ diff --git a/LibOS/shim/src/fs/shim_namei.c b/LibOS/shim/src/fs/shim_namei.c index 9186c318..483e93b5 100644 --- a/LibOS/shim/src/fs/shim_namei.c +++ b/LibOS/shim/src/fs/shim_namei.c @@ -198,9 +198,9 @@ int lookup_dentry (struct shim_dentry * parent, const char * name, int namelen, * Not done in original code, so leaving for now. */ if (err) { - if (err == -ENOENT) { - // Let ENOENT fall through so we can get negative dentries in - // the cache + if (err == -ENOENT || err == -EACCES) { + /* Non-existing files and inaccessible files are marked as + * negative dentries, so they can still be cached */ dent->state |= DENTRY_NEGATIVE; } else { @@ -759,8 +759,12 @@ int list_directory_dentry (struct shim_dentry *dent) { for ( ; d ; d = d->next) { struct shim_dentry * child; if ((ret = lookup_dentry(dent, d->name, strlen(d->name), - &child, fs)) < 0) - goto done_read; + &child, fs)) < 0) { + if (ret != -ENOENT) { + /* if the file is recently deleted or inaccessible, ignore it */ + goto done_read; + } + } if (child->state & DENTRY_NEGATIVE) continue; @@ -774,6 +778,7 @@ int list_directory_dentry (struct shim_dentry *dent) { } dent->state |= DENTRY_LISTED; + ret = 0; done_read: unlock(&dcache_lock);