summaryrefslogtreecommitdiff
path: root/fs/overlayfs/util.c
diff options
context:
space:
mode:
authorAmir Goldstein <amir73il@gmail.com>2023-08-16 12:42:18 +0300
committerAmir Goldstein <amir73il@gmail.com>2023-10-31 00:12:57 +0200
commitc63e56a4a6523fcb1358e1878607d77a40b534bb (patch)
tree2c8b9e0f4c23495df940722abfb6eaf1133ad482 /fs/overlayfs/util.c
parent162d06444070c12827d604a2cb6b6bd98d48cbb0 (diff)
ovl: do not open/llseek lower file with upper sb_writers held
overlayfs file open (ovl_maybe_lookup_lowerdata) and overlay file llseek take the ovl_inode_lock, without holding upper sb_writers. In case of nested lower overlay that uses same upper fs as this overlay, lockdep will warn about (possibly false positive) circular lock dependency when doing open/llseek of lower ovl file during copy up with our upper sb_writers held, because the locking ordering seems reverse to the locking order in ovl_copy_up_start(): - lower ovl_inode_lock - upper sb_writers Let the copy up "transaction" keeps an elevated mnt write count on upper mnt, but leaves taking upper sb_writers to lower level helpers only when they actually need it. This allows to avoid holding upper sb_writers during lower file open/llseek and prevents the lockdep warning. Minimizing the scope of upper sb_writers during copy up is also needed for fixing another possible deadlocks by a following patch. Signed-off-by: Amir Goldstein <amir73il@gmail.com>
Diffstat (limited to 'fs/overlayfs/util.c')
-rw-r--r--fs/overlayfs/util.c8
1 files changed, 6 insertions, 2 deletions
diff --git a/fs/overlayfs/util.c b/fs/overlayfs/util.c
index af11c83b7a25..12156e2091ad 100644
--- a/fs/overlayfs/util.c
+++ b/fs/overlayfs/util.c
@@ -670,6 +670,10 @@ bool ovl_already_copied_up(struct dentry *dentry, int flags)
return false;
}
+/*
+ * The copy up "transaction" keeps an elevated mnt write count on upper mnt,
+ * but leaves taking freeze protection on upper sb to lower level helpers.
+ */
int ovl_copy_up_start(struct dentry *dentry, int flags)
{
struct inode *inode = d_inode(dentry);
@@ -682,7 +686,7 @@ int ovl_copy_up_start(struct dentry *dentry, int flags)
if (ovl_already_copied_up_locked(dentry, flags))
err = 1; /* Already copied up */
else
- err = ovl_want_write(dentry);
+ err = ovl_get_write_access(dentry);
if (err)
goto out_unlock;
@@ -695,7 +699,7 @@ out_unlock:
void ovl_copy_up_end(struct dentry *dentry)
{
- ovl_drop_write(dentry);
+ ovl_put_write_access(dentry);
ovl_inode_unlock(d_inode(dentry));
}