]> git.ipfire.org Git - thirdparty/linux.git/commitdiff
fold fs_struct->{lock,seq} into a seqlock
authorAl Viro <viro@zeniv.linux.org.uk>
Wed, 2 Jul 2025 05:34:37 +0000 (06:34 +0100)
committerChristian Brauner <brauner@kernel.org>
Tue, 8 Jul 2025 08:25:19 +0000 (10:25 +0200)
The combination of spinlock_t lock and seqcount_spinlock_t seq
in struct fs_struct is an open-coded seqlock_t (see linux/seqlock_types.h).
Combine and switch to equivalent seqlock_t primitives.  AFAICS,
that does end up with the same sequence of underlying operations in all
cases.
While we are at it, get_fs_pwd() is open-coded verbatim in
get_path_from_fd(); rather than applying conversion to it, replace with
the call of get_fs_pwd() there.  Not worth splitting the commit for that,
IMO...

A bit of historical background - conversion of seqlock_t to
use of seqcount_spinlock_t happened several months after the same
had been done to struct fs_struct; switching fs_struct to seqlock_t
could've been done immediately after that, but it looks like nobody
had gotten around to that until now.

Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
Link: https://lore.kernel.org/20250702053437.GC1880847@ZenIV
Acked-by: Ahmed S. Darwish <darwi@linutronix.de>
Acked-by: Peter Zijlstra (Intel) <peterz@infradead.org>
Reviewed-by: Christian Brauner <brauner@kernel.org>
Signed-off-by: Christian Brauner <brauner@kernel.org>
fs/d_path.c
fs/exec.c
fs/fhandle.c
fs/fs_struct.c
fs/namei.c
include/linux/fs_struct.h
kernel/fork.c

index 5f4da5c8d5db3e957b1034312e9a2a257b6018c9..bb365511066b21eb447e18858f2dd3bcb351423c 100644 (file)
@@ -241,9 +241,9 @@ static void get_fs_root_rcu(struct fs_struct *fs, struct path *root)
        unsigned seq;
 
        do {
-               seq = read_seqcount_begin(&fs->seq);
+               seq = read_seqbegin(&fs->seq);
                *root = fs->root;
-       } while (read_seqcount_retry(&fs->seq, seq));
+       } while (read_seqretry(&fs->seq, seq));
 }
 
 /**
@@ -385,10 +385,10 @@ static void get_fs_root_and_pwd_rcu(struct fs_struct *fs, struct path *root,
        unsigned seq;
 
        do {
-               seq = read_seqcount_begin(&fs->seq);
+               seq = read_seqbegin(&fs->seq);
                *root = fs->root;
                *pwd = fs->pwd;
-       } while (read_seqcount_retry(&fs->seq, seq));
+       } while (read_seqretry(&fs->seq, seq));
 }
 
 /*
index 1f5fdd2e096e392b342f122d35aba4cf035441c7..871078ddb220d2f05cc073628f9d90b6de2c9b5e 100644 (file)
--- a/fs/exec.c
+++ b/fs/exec.c
@@ -1510,7 +1510,7 @@ static void check_unsafe_exec(struct linux_binprm *bprm)
         * state is protected by cred_guard_mutex we hold.
         */
        n_fs = 1;
-       spin_lock(&p->fs->lock);
+       read_seqlock_excl(&p->fs->seq);
        rcu_read_lock();
        for_other_threads(p, t) {
                if (t->fs == p->fs)
@@ -1523,7 +1523,7 @@ static void check_unsafe_exec(struct linux_binprm *bprm)
                bprm->unsafe |= LSM_UNSAFE_SHARE;
        else
                p->fs->in_exec = 1;
-       spin_unlock(&p->fs->lock);
+       read_sequnlock_excl(&p->fs->seq);
 }
 
 static void bprm_fill_uid(struct linux_binprm *bprm, struct file *file)
index b1363ead6c5ebd492a997abc041a991e149530fa..7c236f64cdeac1d5dc10697d4863b0737a0a7e56 100644 (file)
@@ -180,11 +180,7 @@ static int get_path_anchor(int fd, struct path *root)
        }
 
        if (fd == AT_FDCWD) {
-               struct fs_struct *fs = current->fs;
-               spin_lock(&fs->lock);
-               *root = fs->pwd;
-               path_get(root);
-               spin_unlock(&fs->lock);
+               get_fs_pwd(current->fs, root);
                return 0;
        }
 
index 64c2d0814ed6889cc12603410e6e9dc44089586f..28be762ac1c637b61fcaeb4921828d16e3644f27 100644 (file)
@@ -17,12 +17,10 @@ void set_fs_root(struct fs_struct *fs, const struct path *path)
        struct path old_root;
 
        path_get(path);
-       spin_lock(&fs->lock);
-       write_seqcount_begin(&fs->seq);
+       write_seqlock(&fs->seq);
        old_root = fs->root;
        fs->root = *path;
-       write_seqcount_end(&fs->seq);
-       spin_unlock(&fs->lock);
+       write_sequnlock(&fs->seq);
        if (old_root.dentry)
                path_put(&old_root);
 }
@@ -36,12 +34,10 @@ void set_fs_pwd(struct fs_struct *fs, const struct path *path)
        struct path old_pwd;
 
        path_get(path);
-       spin_lock(&fs->lock);
-       write_seqcount_begin(&fs->seq);
+       write_seqlock(&fs->seq);
        old_pwd = fs->pwd;
        fs->pwd = *path;
-       write_seqcount_end(&fs->seq);
-       spin_unlock(&fs->lock);
+       write_sequnlock(&fs->seq);
 
        if (old_pwd.dentry)
                path_put(&old_pwd);
@@ -67,16 +63,14 @@ void chroot_fs_refs(const struct path *old_root, const struct path *new_root)
                fs = p->fs;
                if (fs) {
                        int hits = 0;
-                       spin_lock(&fs->lock);
-                       write_seqcount_begin(&fs->seq);
+                       write_seqlock(&fs->seq);
                        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++;
                                path_get(new_root);
                        }
-                       spin_unlock(&fs->lock);
+                       write_sequnlock(&fs->seq);
                }
                task_unlock(p);
        }
@@ -99,10 +93,10 @@ void exit_fs(struct task_struct *tsk)
        if (fs) {
                int kill;
                task_lock(tsk);
-               spin_lock(&fs->lock);
+               read_seqlock_excl(&fs->seq);
                tsk->fs = NULL;
                kill = !--fs->users;
-               spin_unlock(&fs->lock);
+               read_sequnlock_excl(&fs->seq);
                task_unlock(tsk);
                if (kill)
                        free_fs_struct(fs);
@@ -116,16 +110,15 @@ struct fs_struct *copy_fs_struct(struct fs_struct *old)
        if (fs) {
                fs->users = 1;
                fs->in_exec = 0;
-               spin_lock_init(&fs->lock);
-               seqcount_spinlock_init(&fs->seq, &fs->lock);
+               seqlock_init(&fs->seq);
                fs->umask = old->umask;
 
-               spin_lock(&old->lock);
+               read_seqlock_excl(&old->seq);
                fs->root = old->root;
                path_get(&fs->root);
                fs->pwd = old->pwd;
                path_get(&fs->pwd);
-               spin_unlock(&old->lock);
+               read_sequnlock_excl(&old->seq);
        }
        return fs;
 }
@@ -140,10 +133,10 @@ int unshare_fs_struct(void)
                return -ENOMEM;
 
        task_lock(current);
-       spin_lock(&fs->lock);
+       read_seqlock_excl(&fs->seq);
        kill = !--fs->users;
        current->fs = new_fs;
-       spin_unlock(&fs->lock);
+       read_sequnlock_excl(&fs->seq);
        task_unlock(current);
 
        if (kill)
@@ -162,7 +155,6 @@ EXPORT_SYMBOL(current_umask);
 /* to be mentioned only in INIT_TASK */
 struct fs_struct init_fs = {
        .users          = 1,
-       .lock           = __SPIN_LOCK_UNLOCKED(init_fs.lock),
-       .seq            = SEQCNT_SPINLOCK_ZERO(init_fs.seq, &init_fs.lock),
+       .seq            = __SEQLOCK_UNLOCKED(init_fs.seq),
        .umask          = 0022,
 };
index 4bb889fc980b7d44914e11ec38ae3e8fdfbafadd..f2fcaf84e111649038c69d0b1ac77d4dbb51e6c6 100644 (file)
@@ -1012,10 +1012,10 @@ static int set_root(struct nameidata *nd)
                unsigned seq;
 
                do {
-                       seq = read_seqcount_begin(&fs->seq);
+                       seq = read_seqbegin(&fs->seq);
                        nd->root = fs->root;
                        nd->root_seq = __read_seqcount_begin(&nd->root.dentry->d_seq);
-               } while (read_seqcount_retry(&fs->seq, seq));
+               } while (read_seqretry(&fs->seq, seq));
        } else {
                get_fs_root(fs, &nd->root);
                nd->state |= ND_ROOT_GRABBED;
@@ -2580,11 +2580,11 @@ static const char *path_init(struct nameidata *nd, unsigned flags)
                        unsigned seq;
 
                        do {
-                               seq = read_seqcount_begin(&fs->seq);
+                               seq = read_seqbegin(&fs->seq);
                                nd->path = fs->pwd;
                                nd->inode = nd->path.dentry->d_inode;
                                nd->seq = __read_seqcount_begin(&nd->path.dentry->d_seq);
-                       } while (read_seqcount_retry(&fs->seq, seq));
+                       } while (read_seqretry(&fs->seq, seq));
                } else {
                        get_fs_pwd(current->fs, &nd->path);
                        nd->inode = nd->path.dentry->d_inode;
index 783b48dedb723f159a822cd8debcd533d713457f..baf200ab5c7777c2b08c3aa977fd37a413b09c26 100644 (file)
@@ -8,8 +8,7 @@
 
 struct fs_struct {
        int users;
-       spinlock_t lock;
-       seqcount_spinlock_t seq;
+       seqlock_t seq;
        int umask;
        int in_exec;
        struct path root, pwd;
@@ -26,18 +25,18 @@ extern int unshare_fs_struct(void);
 
 static inline void get_fs_root(struct fs_struct *fs, struct path *root)
 {
-       spin_lock(&fs->lock);
+       read_seqlock_excl(&fs->seq);
        *root = fs->root;
        path_get(root);
-       spin_unlock(&fs->lock);
+       read_sequnlock_excl(&fs->seq);
 }
 
 static inline void get_fs_pwd(struct fs_struct *fs, struct path *pwd)
 {
-       spin_lock(&fs->lock);
+       read_seqlock_excl(&fs->seq);
        *pwd = fs->pwd;
        path_get(pwd);
-       spin_unlock(&fs->lock);
+       read_sequnlock_excl(&fs->seq);
 }
 
 extern bool current_chrooted(void);
index 1ee8eb11f38bae1d2eb6de9494aea94b7a19e6c3..6318a25a16baa73f2b379d15b6393b0cb762eee4 100644 (file)
@@ -1542,14 +1542,14 @@ static int copy_fs(unsigned long clone_flags, struct task_struct *tsk)
        struct fs_struct *fs = current->fs;
        if (clone_flags & CLONE_FS) {
                /* tsk->fs is already what we want */
-               spin_lock(&fs->lock);
+               read_seqlock_excl(&fs->seq);
                /* "users" and "in_exec" locked for check_unsafe_exec() */
                if (fs->in_exec) {
-                       spin_unlock(&fs->lock);
+                       read_sequnlock_excl(&fs->seq);
                        return -EAGAIN;
                }
                fs->users++;
-               spin_unlock(&fs->lock);
+               read_sequnlock_excl(&fs->seq);
                return 0;
        }
        tsk->fs = copy_fs_struct(fs);
@@ -3149,13 +3149,13 @@ int ksys_unshare(unsigned long unshare_flags)
 
                if (new_fs) {
                        fs = current->fs;
-                       spin_lock(&fs->lock);
+                       read_seqlock_excl(&fs->seq);
                        current->fs = new_fs;
                        if (--fs->users)
                                new_fs = NULL;
                        else
                                new_fs = fs;
-                       spin_unlock(&fs->lock);
+                       read_sequnlock_excl(&fs->seq);
                }
 
                if (new_fd)