Skip to content

Commit 61eb7fe

Browse files
neilbrownbrauner
authored andcommitted
ovl: narrow locking in ovl_workdir_create()
In ovl_workdir_create() don't hold the dir lock for the whole time, but only take it when needed. It now gets taken separately for ovl_workdir_cleanup(). A subsequent patch will move the locking into that function. Signed-off-by: NeilBrown <neil@brown.name> Link: https://lore.kernel.org/20250716004725.1206467-13-neil@brown.name Reviewed-by: Amir Goldstein <amir73il@gmail.com> Signed-off-by: Christian Brauner <brauner@kernel.org>
1 parent 8290fb4 commit 61eb7fe

1 file changed

Lines changed: 14 additions & 11 deletions

File tree

fs/overlayfs/super.c

Lines changed: 14 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -299,8 +299,8 @@ static struct dentry *ovl_workdir_create(struct ovl_fs *ofs,
299299
int err;
300300
bool retried = false;
301301

302-
inode_lock_nested(dir, I_MUTEX_PARENT);
303302
retry:
303+
inode_lock_nested(dir, I_MUTEX_PARENT);
304304
work = ovl_lookup_upper(ofs, name, ofs->workbasedir, strlen(name));
305305

306306
if (!IS_ERR(work)) {
@@ -311,23 +311,28 @@ static struct dentry *ovl_workdir_create(struct ovl_fs *ofs,
311311

312312
if (work->d_inode) {
313313
err = -EEXIST;
314+
inode_unlock(dir);
314315
if (retried)
315316
goto out_dput;
316317

317318
if (persist)
318-
goto out_unlock;
319+
return work;
319320

320321
retried = true;
321-
err = ovl_workdir_cleanup(ofs, dir, mnt, work, 0);
322-
dput(work);
323-
if (err == -EINVAL) {
324-
work = ERR_PTR(err);
325-
goto out_unlock;
322+
err = ovl_parent_lock(ofs->workbasedir, work);
323+
if (!err) {
324+
err = ovl_workdir_cleanup(ofs, dir, mnt, work, 0);
325+
ovl_parent_unlock(ofs->workbasedir);
326326
}
327+
dput(work);
328+
if (err == -EINVAL)
329+
return ERR_PTR(err);
330+
327331
goto retry;
328332
}
329333

330334
work = ovl_do_mkdir(ofs, dir, work, attr.ia_mode);
335+
inode_unlock(dir);
331336
err = PTR_ERR(work);
332337
if (IS_ERR(work))
333338
goto out_err;
@@ -365,20 +370,18 @@ static struct dentry *ovl_workdir_create(struct ovl_fs *ofs,
365370
if (err)
366371
goto out_dput;
367372
} else {
373+
inode_unlock(dir);
368374
err = PTR_ERR(work);
369375
goto out_err;
370376
}
371-
out_unlock:
372-
inode_unlock(dir);
373377
return work;
374378

375379
out_dput:
376380
dput(work);
377381
out_err:
378382
pr_warn("failed to create directory %s/%s (errno: %i); mounting read-only\n",
379383
ofs->config.workdir, name, -err);
380-
work = NULL;
381-
goto out_unlock;
384+
return NULL;
382385
}
383386

384387
static int ovl_check_namelen(const struct path *path, struct ovl_fs *ofs,

0 commit comments

Comments
 (0)