[PATCH v13 15/28] ovl: Move some of ovl_nlink_start() functionality in ovl_nlink_prep()

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



Soon I want to write patches to enable redirects on non-dir files. That means
it is possible that we have to deal with the case where multiple dentries
might be sharing inode and ovl_inode->redirect field setting/resetting
will need to be protected by taking ovl_inode->lock. Current dentry based
locking alone will not be sufficient for this case.

As of now, nlink based code takes ovl_inode->lock in some cases. For redirect
case, during ovl_rename() I might have to take ovl_inode->lock both on
old as well as new ovl_inode. And that means that I need to make sure
there are no deadlocks.

I want to separate out logic for taking lock in a new function. Hence will
need to break down ovl_nlink_start() a bit.

ovl_nlink_start() does the copy up and then takes ovl_inode->lock. Move
copy up related portions in a separate function called ovl_nlink_prep().

This patch is just code reorganization and no funcitonal change.

Signed-off-by: Vivek Goyal <vgoyal@xxxxxxxxxx>
---
 fs/overlayfs/dir.c       | 14 ++++++++++++++
 fs/overlayfs/overlayfs.h |  1 +
 fs/overlayfs/util.c      | 26 ++++++++++++++++++--------
 3 files changed, 33 insertions(+), 8 deletions(-)

diff --git a/fs/overlayfs/dir.c b/fs/overlayfs/dir.c
index 7617a03acc30..1f003be4a19e 100644
--- a/fs/overlayfs/dir.c
+++ b/fs/overlayfs/dir.c
@@ -595,6 +595,10 @@ static int ovl_link(struct dentry *old, struct inode *newdir,
 	if (err)
 		goto out_drop_write;
 
+	err = ovl_nlink_prep(old);
+	if (err)
+		goto out_drop_write;
+
 	err = ovl_nlink_start(old, &locked);
 	if (err)
 		goto out_drop_write;
@@ -752,6 +756,10 @@ static int ovl_do_remove(struct dentry *dentry, bool is_dir)
 	if (err)
 		goto out_drop_write;
 
+	err = ovl_nlink_prep(dentry);
+	if (err)
+		goto out_drop_write;
+
 	err = ovl_nlink_start(dentry, &locked);
 	if (err)
 		goto out_drop_write;
@@ -960,6 +968,12 @@ static int ovl_rename(struct inode *olddir, struct dentry *old,
 		if (err)
 			goto out_drop_write;
 	} else {
+		err = ovl_nlink_prep(new);
+		if (err)
+			goto out_drop_write;
+	}
+
+	if (overwrite) {
 		err = ovl_nlink_start(new, &new_locked);
 		if (err)
 			goto out_drop_write;
diff --git a/fs/overlayfs/overlayfs.h b/fs/overlayfs/overlayfs.h
index 214d9f08c574..aa5b0c121fc7 100644
--- a/fs/overlayfs/overlayfs.h
+++ b/fs/overlayfs/overlayfs.h
@@ -271,6 +271,7 @@ bool ovl_test_flag(unsigned long flag, struct inode *inode);
 bool ovl_inuse_trylock(struct dentry *dentry);
 void ovl_inuse_unlock(struct dentry *dentry);
 bool ovl_need_index(struct dentry *dentry);
+int ovl_nlink_prep(struct dentry *dentry);
 int ovl_nlink_start(struct dentry *dentry, bool *locked);
 void ovl_nlink_end(struct dentry *dentry, bool locked);
 int ovl_lock_rename_workdir(struct dentry *workdir, struct dentry *upperdir);
diff --git a/fs/overlayfs/util.c b/fs/overlayfs/util.c
index 394674c4c820..ed93e233894f 100644
--- a/fs/overlayfs/util.c
+++ b/fs/overlayfs/util.c
@@ -675,15 +675,9 @@ static void ovl_cleanup_index(struct dentry *dentry)
 	goto out;
 }
 
-/*
- * Operations that change overlay inode and upper inode nlink need to be
- * synchronized with copy up for persistent nlink accounting.
- */
-int ovl_nlink_start(struct dentry *dentry, bool *locked)
+int ovl_nlink_prep(struct dentry *dentry)
 {
-	struct ovl_inode *oi = OVL_I(d_inode(dentry));
-	const struct cred *old_cred;
-	int err;
+	int err = 0;
 
 	if (!d_inode(dentry))
 		return 0;
@@ -708,6 +702,22 @@ int ovl_nlink_start(struct dentry *dentry, bool *locked)
 			return err;
 	}
 
+	return err;
+}
+
+/*
+ * Operations that change overlay inode and upper inode nlink need to be
+ * synchronized with copy up for persistent nlink accounting.
+ */
+int ovl_nlink_start(struct dentry *dentry, bool *locked)
+{
+	struct ovl_inode *oi = OVL_I(d_inode(dentry));
+	const struct cred *old_cred;
+	int err;
+
+	if (!d_inode(dentry))
+		return 0;
+
 	err = mutex_lock_interruptible(&oi->lock);
 	if (err)
 		return err;
-- 
2.13.6

--
To unsubscribe from this list: send the line "unsubscribe linux-unionfs" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at  http://vger.kernel.org/majordomo-info.html



[Index of Archives]     [Linux Filesystems Devel]     [Linux NFS]     [Linux NILFS]     [Linux USB Devel]     [Linux Audio Users]     [Yosemite News]     [Linux Kernel]     [Linux SCSI]

  Powered by Linux