[PATCH v1 05/12] libfs: simplify scan_positives()
NeilBrown <[email protected]> Mon, 3 Aug 2026 11:21:14 +1000
| Newsgroups | gmane.linux.file-systems,gmane.linux.kernel.autofs,gmane.linux.kernel,gmane.comp.file-systems.ceph.devel,gmane.comp.file-systems.coda.general,gmane.linux.nfs |
|---|---|
| Message-ID | <[email protected]> |
From: NeilBrown <[email protected]> This patch removes explicit use of hlist_node from scan_positives() and callers, and consistently uses struct dentry instead. Previously scan_positives() had two args which were closely related: p and last. If last was not NULL, p was precisely &last->d_sib.next. If last WAS NULL, then p was &cursor->d_parent->d_children.first or &cursor->d_sib.next If, for the final case, we pass 'cursor' as 'last', then we only need 'last' not 'p'. For this to work we must dget(cursor) before passing it, as scan_positives() calls dput() on last. So now to scan from the start, pass NULL, to scan from a particular dentry, pass that dentry. Signed-off-by: NeilBrown <[email protected]> --- fs/libfs.c | 29 +++++++++++++---------------- 1 file changed, 13 insertions(+), 16 deletions(-) diff --git a/fs/libfs.c b/fs/libfs.c index fc283e0a7c3a..080ca615593c 100644 --- a/fs/libfs.c +++ b/fs/libfs.c @@ -105,16 +105,18 @@ EXPORT_SYMBOL(dcache_dir_close); * If no such element exists, NULL is returned. */ static struct dentry *scan_positives(struct dentry *cursor, - struct hlist_node **p, - loff_t count, - struct dentry *last) + struct dentry *last, + loff_t count) { struct dentry *dentry = cursor->d_parent, *found = NULL; + struct dentry *next; spin_lock(&dentry->d_lock); - while (*p) { - struct dentry *d = hlist_entry(*p, struct dentry, d_sib); - p = &d->d_sib.next; + next = last ? d_next_sibling(last) : d_first_child(dentry); + while (next) { + struct dentry *d = next; + + next = d_next_sibling(next); // we must at least skip cursors, to avoid livelocks if (d->d_flags & DCACHE_DENTRY_CURSOR) continue; @@ -131,10 +133,10 @@ static struct dentry *scan_positives(struct dentry *cursor, if (!hlist_unhashed(&cursor->d_sib)) __hlist_del(&cursor->d_sib); hlist_add_behind(&cursor->d_sib, &d->d_sib); - p = &cursor->d_sib.next; spin_unlock(&dentry->d_lock); cond_resched(); spin_lock(&dentry->d_lock); + next = d_next_sibling(cursor); } } spin_unlock(&dentry->d_lock); @@ -163,8 +165,7 @@ loff_t dcache_dir_lseek(struct file *file, loff_t offset, int whence) inode_lock_shared(dentry->d_inode); if (offset > 2) - to = scan_positives(cursor, &dentry->d_children.first, - offset - 2, NULL); + to = scan_positives(cursor, NULL, offset - 2); spin_lock(&dentry->d_lock); hlist_del_init(&cursor->d_sib); if (to) @@ -191,23 +192,19 @@ int dcache_readdir(struct file *file, struct dir_context *ctx) struct dentry *dentry = file->f_path.dentry; struct dentry *cursor = file->private_data; struct dentry *next = NULL; - struct hlist_node **p; if (!dir_emit_dots(file, ctx)) return 0; - if (ctx->pos == 2) - p = &dentry->d_children.first; - else - p = &cursor->d_sib.next; + if (ctx->pos > 2) + next = dget(cursor); - while ((next = scan_positives(cursor, p, 1, next)) != NULL) { + while ((next = scan_positives(cursor, next, 1)) != NULL) { if (!dir_emit(ctx, next->d_name.name, next->d_name.len, d_inode(next)->i_ino, fs_umode_to_dtype(d_inode(next)->i_mode))) break; ctx->pos++; - p = &next->d_sib.next; } spin_lock(&dentry->d_lock); hlist_del_init(&cursor->d_sib); -- 2.50.0.107.gf914562f5916.dirty