diff --git a/fs/libfs.c b/fs/libfs.c index 0fb590d79f30ed78d0626fd79f24cacf9e1a72b8..4abdd7c00cd8433801fd184f11b319e268b4f7bd 100644 --- a/fs/libfs.c +++ b/fs/libfs.c @@ -90,53 +90,31 @@ static struct dentry *next_positive(struct dentry *parent, struct list_head *from, int count) { - unsigned *seq = &parent->d_inode->i_dir_seq, n; - struct dentry *res; + struct dentry *res = NULL; struct list_head *p; - bool skipped; - int i; -retry: - i = count; - skipped = false; - n = smp_load_acquire(seq) & ~1; - res = NULL; - rcu_read_lock(); + spin_lock(&parent->d_lock); for (p = from->next; p != &parent->d_subdirs; p = p->next) { struct dentry *d = list_entry(p, struct dentry, d_child); - if (!simple_positive(d)) { - skipped = true; - } else if (!--i) { + if (simple_positive(d) && !--count) { res = d; break; } } - rcu_read_unlock(); - if (skipped) { - smp_rmb(); - if (unlikely(*seq != n)) - goto retry; - } + spin_unlock(&parent->d_lock); return res; } static void move_cursor(struct dentry *cursor, struct list_head *after) { struct dentry *parent = cursor->d_parent; - unsigned n, *seq = &parent->d_inode->i_dir_seq; + spin_lock(&parent->d_lock); - for (;;) { - n = *seq; - if (!(n & 1) && cmpxchg(seq, n, n + 1) == n) - break; - cpu_relax(); - } __list_del(cursor->d_child.prev, cursor->d_child.next); if (after) list_add(&cursor->d_child, after); else list_add_tail(&cursor->d_child, &parent->d_subdirs); - smp_store_release(seq, n + 2); spin_unlock(&parent->d_lock); }