[PATCH v2 16/18] libfs: rename and export scan_positives()

NeilBrown <[email protected]>
Newsgroups org.kernel.vger.linux-fsdevel,org.kernel.vger.autofs,org.kernel.vger.ceph-devel,org.kernel.vger.linux-kernel,org.kernel.vger.linux-nfs
Message-ID <[email protected]>
From: NeilBrown <[email protected]>

autofs has code nearly identical to scan_positives().  To avoid code
duplication, export scan_positives().

Rename it to "d_scan_positives()" to make it more obviously dcache
related.

Change the "count" argument to "skip" which starts from 0 rather than 1.
This makes it a little easier to document the purpose, and makes it less
likely that "0" will be passed when "1" was intended.

For aesthetic consistency, all calls of d_scan_positives() now pass as
the "prev" arg the variable that the result is being assigned to.
This was already the case except when NULL was passed, but in the two
cases where NULL was passed, the target variable already had been
initialised to NULL.

Signed-off-by: NeilBrown <[email protected]>
---
 fs/libfs.c             | 49 ++++++++++++++++++++++++++----------------
 include/linux/dcache.h |  4 ++++
 2 files changed, 34 insertions(+), 19 deletions(-)

diff --git a/fs/libfs.c b/fs/libfs.c
index 15dd470198dd..20cc94b41075 100644
--- a/fs/libfs.c
+++ b/fs/libfs.c
@@ -97,37 +97,48 @@ int dcache_dir_close(struct inode *inode, struct file *file)
 }
 EXPORT_SYMBOL(dcache_dir_close);
 
-/* parent is locked at least shared */
-/*
- * Returns an element of siblings' list.
- * We are looking for <count>th positive after <p>; if
- * found, dentry is grabbed and returned to caller.
- * If no such element exists, NULL is returned.
- * If last has been removed from the d_children list
- * (i.e. last->d_sib is unhashed) then it is treated like
+/**
+ * d_scan_positives - return next positive dentry after skipping some.
+ * @dentry: the parent dentry to scan
+ * @last: the place to start search, or %NULL to begin at start.
+ * @skip: number of positive dentries to skip over
+ *
+ * Returns the next, or first, positive element of siblings list after
+ * skipping over @skip positive elements.
+ * The child dentry is grabbed and returned to caller.
+ * If no such element exists, %NULL is returned.
+ *
+ * Caller must ensure returned dentry cannot be moved from
+ * the parent, possibly by holding i_rwsem.
+ *
+ * If @last has been removed from the d_children list
+ * (i.e. @last->d_sib is unhashed) then it is treated like
  * the last element of the list and %NULL is returned.
+ *
+ * Returns: a counted ref to a dentry, or %NULL
  */
-static struct dentry *scan_positives(struct dentry *dentry,
-				     struct dentry *last,
-				     loff_t count)
+struct dentry *d_scan_positives(struct dentry *dentry,
+				struct dentry *last,
+				loff_t skip)
 {
 	struct dentry *found = NULL;
 	struct dentry *d = last;
 
 	d_for_each_positive_child_continue(d, dentry) {
-		if (simple_positive(d) && !--count) {
+		if (simple_positive(d) && !skip--) {
 			spin_lock_nested(&d->d_lock, DENTRY_D_LOCK_NESTED);
 			if (simple_positive(d))
 				found = dget_dlock(d);
 			spin_unlock(&d->d_lock);
 			if (likely(found))
 				break;
-			count = 1;
+			skip = 0;
 		}
 	}
 	dput(last);
 	return found;
 }
+EXPORT_SYMBOL(d_scan_positives);
 
 loff_t dcache_dir_lseek(struct file *file, loff_t offset, int whence)
 {
@@ -149,8 +160,8 @@ 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(dentry, NULL, offset - 2);
+		if (offset >= 3)
+			to = d_scan_positives(dentry, to, offset - 3);
 		spin_lock(&dentry->d_lock);
 		if (to)
 			hlist_move_behind(&cursor->d_sib, &to->d_sib);
@@ -185,7 +196,7 @@ int dcache_readdir(struct file *file, struct dir_context *ctx)
 	if (ctx->pos > 2)
 		next = dget(cursor);
 
-	while ((next = scan_positives(dentry, next, 1)) != NULL) {
+	while ((next = d_scan_positives(dentry, next, 0)) != 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)))
@@ -440,7 +451,7 @@ offset_dir_lookup(struct dentry *parent, loff_t offset)
 	MA_STATE(mas, &octx->mt, offset, offset);
 
 	if (offset == DIR_OFFSET_FIRST)
-		found = scan_positives(parent, NULL, 1);
+		found = d_scan_positives(parent, found, 0);
 	else {
 		rcu_read_lock();
 		spin_lock(&parent->d_lock);
@@ -462,7 +473,7 @@ offset_dir_lookup(struct dentry *parent, loff_t offset)
 		spin_unlock(&parent->d_lock);
 		rcu_read_unlock();
 		if (found && !simple_positive(found))
-			found = scan_positives(parent, found, 1);
+			found = d_scan_positives(parent, found, 0);
 	}
 	return found;
 }
@@ -488,7 +499,7 @@ static void offset_iterate_dir(struct file *file, struct dir_context *ctx)
 		if (!offset_dir_emit(ctx, dentry))
 			break;
 
-		dentry = scan_positives(dir, dentry, 1);
+		dentry = d_scan_positives(dir, dentry, 0);
 
 		if (!dentry)
 			goto out_eod;
diff --git a/include/linux/dcache.h b/include/linux/dcache.h
index f7d5954c58da..a978d1c4936a 100644
--- a/include/linux/dcache.h
+++ b/include/linux/dcache.h
@@ -723,6 +723,10 @@ static inline struct dentry *d_first_positive(const struct dentry *parent,
 			     child;					\
 			     child = d_next_positive(child))
 
+struct dentry *d_scan_positives(struct dentry *dentry,
+				struct dentry *last,
+				loff_t skip);
+
 void set_default_d_op(struct super_block *, const struct dentry_operations *);
 struct dentry *d_make_persistent(struct dentry *, struct inode *);
 void d_make_discardable(struct dentry *dentry);
-- 
2.50.0.107.gf914562f5916.dirty
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.