Skip to content

Commit 1434a65

Browse files
cgxu519Miklos Szeredi
authored andcommitted
ovl: drop negative dentry in upper layer
Negative dentries of upper layer are useless after construction of overlayfs' own dentry and may keep in the memory long time even after unmount of overlayfs instance. This patch tries to drop unnecessary negative dentry of upper layer to effectively reclaim memory. Signed-off-by: Chengguang Xu <[email protected]> Signed-off-by: Miklos Szeredi <[email protected]>
1 parent 05acefb commit 1434a65

File tree

1 file changed

+28
-7
lines changed

1 file changed

+28
-7
lines changed

fs/overlayfs/namei.c

Lines changed: 28 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -191,16 +191,36 @@ static bool ovl_is_opaquedir(struct dentry *dentry)
191191
return ovl_check_dir_xattr(dentry, OVL_XATTR_OPAQUE);
192192
}
193193

194+
static struct dentry *ovl_lookup_positive_unlocked(const char *name,
195+
struct dentry *base, int len,
196+
bool drop_negative)
197+
{
198+
struct dentry *ret = lookup_one_len_unlocked(name, base, len);
199+
200+
if (!IS_ERR(ret) && d_flags_negative(smp_load_acquire(&ret->d_flags))) {
201+
if (drop_negative && ret->d_lockref.count == 1) {
202+
spin_lock(&ret->d_lock);
203+
/* Recheck condition under lock */
204+
if (d_is_negative(ret) && ret->d_lockref.count == 1)
205+
__d_drop(ret);
206+
spin_unlock(&ret->d_lock);
207+
}
208+
dput(ret);
209+
ret = ERR_PTR(-ENOENT);
210+
}
211+
return ret;
212+
}
213+
194214
static int ovl_lookup_single(struct dentry *base, struct ovl_lookup_data *d,
195215
const char *name, unsigned int namelen,
196216
size_t prelen, const char *post,
197-
struct dentry **ret)
217+
struct dentry **ret, bool drop_negative)
198218
{
199219
struct dentry *this;
200220
int err;
201221
bool last_element = !post[0];
202222

203-
this = lookup_positive_unlocked(name, base, namelen);
223+
this = ovl_lookup_positive_unlocked(name, base, namelen, drop_negative);
204224
if (IS_ERR(this)) {
205225
err = PTR_ERR(this);
206226
this = NULL;
@@ -276,7 +296,7 @@ static int ovl_lookup_single(struct dentry *base, struct ovl_lookup_data *d,
276296
}
277297

278298
static int ovl_lookup_layer(struct dentry *base, struct ovl_lookup_data *d,
279-
struct dentry **ret)
299+
struct dentry **ret, bool drop_negative)
280300
{
281301
/* Counting down from the end, since the prefix can change */
282302
size_t rem = d->name.len - 1;
@@ -285,7 +305,7 @@ static int ovl_lookup_layer(struct dentry *base, struct ovl_lookup_data *d,
285305

286306
if (d->name.name[0] != '/')
287307
return ovl_lookup_single(base, d, d->name.name, d->name.len,
288-
0, "", ret);
308+
0, "", ret, drop_negative);
289309

290310
while (!IS_ERR_OR_NULL(base) && d_can_lookup(base)) {
291311
const char *s = d->name.name + d->name.len - rem;
@@ -298,7 +318,8 @@ static int ovl_lookup_layer(struct dentry *base, struct ovl_lookup_data *d,
298318
return -EIO;
299319

300320
err = ovl_lookup_single(base, d, s, thislen,
301-
d->name.len - rem, next, &base);
321+
d->name.len - rem, next, &base,
322+
drop_negative);
302323
dput(dentry);
303324
if (err)
304325
return err;
@@ -830,7 +851,7 @@ struct dentry *ovl_lookup(struct inode *dir, struct dentry *dentry,
830851
old_cred = ovl_override_creds(dentry->d_sb);
831852
upperdir = ovl_dentry_upper(dentry->d_parent);
832853
if (upperdir) {
833-
err = ovl_lookup_layer(upperdir, &d, &upperdentry);
854+
err = ovl_lookup_layer(upperdir, &d, &upperdentry, true);
834855
if (err)
835856
goto out;
836857

@@ -888,7 +909,7 @@ struct dentry *ovl_lookup(struct inode *dir, struct dentry *dentry,
888909
else
889910
d.last = lower.layer->idx == roe->numlower;
890911

891-
err = ovl_lookup_layer(lower.dentry, &d, &this);
912+
err = ovl_lookup_layer(lower.dentry, &d, &this, false);
892913
if (err)
893914
goto out_put;
894915

0 commit comments

Comments
 (0)