linux/debian/patches/features/all/rt/0022-vfs-fs_struct-Move-cod...

89 lines
2.5 KiB
Diff

From 47a3a34ec251a566d97646774193e1789eb20220 Mon Sep 17 00:00:00 2001
From: Al Viro <viro@ZenIV.linux.org.uk>
Date: Thu, 15 Mar 2012 18:39:40 +0000
Subject: [PATCH 022/304] vfs: fs_struct: Move code out of seqcount write
sections
RT cannot disable preemption in the seqcount write sections due to
functions called which take "sleeping" spinlocks.
Move the code out of those sections. It does not need to be there.
Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
---
fs/fs_struct.c | 27 +++++++++++++++------------
1 file changed, 15 insertions(+), 12 deletions(-)
diff --git a/fs/fs_struct.c b/fs/fs_struct.c
index 78b519c..f5818c4 100644
--- a/fs/fs_struct.c
+++ b/fs/fs_struct.c
@@ -26,11 +26,11 @@ void set_fs_root(struct fs_struct *fs, struct path *path)
{
struct path old_root;
+ path_get_longterm(path);
spin_lock(&fs->lock);
write_seqcount_begin(&fs->seq);
old_root = fs->root;
fs->root = *path;
- path_get_longterm(path);
write_seqcount_end(&fs->seq);
spin_unlock(&fs->lock);
if (old_root.dentry)
@@ -45,11 +45,11 @@ void set_fs_pwd(struct fs_struct *fs, struct path *path)
{
struct path old_pwd;
+ path_get_longterm(path);
spin_lock(&fs->lock);
write_seqcount_begin(&fs->seq);
old_pwd = fs->pwd;
fs->pwd = *path;
- path_get_longterm(path);
write_seqcount_end(&fs->seq);
spin_unlock(&fs->lock);
@@ -57,6 +57,14 @@ void set_fs_pwd(struct fs_struct *fs, struct path *path)
path_put_longterm(&old_pwd);
}
+static inline int replace_path(struct path *p, const struct path *old, const struct path *new)
+{
+ if (likely(p->dentry != old->dentry || p->mnt != old->mnt))
+ return 0;
+ *p = *new;
+ return 1;
+}
+
void chroot_fs_refs(struct path *old_root, struct path *new_root)
{
struct task_struct *g, *p;
@@ -68,21 +76,16 @@ void chroot_fs_refs(struct path *old_root, struct path *new_root)
task_lock(p);
fs = p->fs;
if (fs) {
+ int hits = 0;
spin_lock(&fs->lock);
write_seqcount_begin(&fs->seq);
- if (fs->root.dentry == old_root->dentry
- && fs->root.mnt == old_root->mnt) {
- path_get_longterm(new_root);
- fs->root = *new_root;
+ hits += replace_path(&fs->root, old_root, new_root);
+ hits += replace_path(&fs->pwd, old_root, new_root);
+ write_seqcount_end(&fs->seq);
+ while (hits--) {
count++;
- }
- if (fs->pwd.dentry == old_root->dentry
- && fs->pwd.mnt == old_root->mnt) {
path_get_longterm(new_root);
- fs->pwd = *new_root;
- count++;
}
- write_seqcount_end(&fs->seq);
spin_unlock(&fs->lock);
}
task_unlock(p);