diff options
author | Al Viro <viro@ZenIV.linux.org.uk> | 2012-03-15 18:39:40 +0000 |
---|---|---|
committer | Clark Williams <williams@redhat.com> | 2012-04-10 16:36:28 -0500 |
commit | d7df56f2c4e3fab0133d4c9b924a7b7313f8c455 (patch) | |
tree | 1b9d89b7b30506c56c71d1f84322d1385f9c65fe /fs | |
parent | dbff4c8b6336ecee1d8b934bf2046ce2bc809562 (diff) |
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>
Diffstat (limited to 'fs')
-rw-r--r-- | fs/fs_struct.c | 27 |
1 files changed, 15 insertions, 12 deletions
diff --git a/fs/fs_struct.c b/fs/fs_struct.c index 78b519c13536..f5818c41f143 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); |