All of lore.kernel.org
 help / color / mirror / Atom feed
* How to abuse RCU to scan the children of a mount?
@ 2020-03-04 17:45 David Howells
  2020-03-04 19:28 ` Paul E. McKenney
  2020-03-05 12:47 ` David Howells
  0 siblings, 2 replies; 5+ messages in thread
From: David Howells @ 2020-03-04 17:45 UTC (permalink / raw)
  To: Paul E. McKenney; +Cc: dhowells, Al Viro, mszeredi, linux-fsdevel

Hi Paul,

As part of trying to implement a filesystem information querying system call,
I need to be able to return a list of child mounts of a mount.  Children,
however, may be moved with "mount --move", which means that the list can't be
accessed with normal RCU practices.

For reference, I'm dealing with struct mount and mnt_mounts and mnt_child and
struct mount is released via call_rcu().

What does rcu_dereference() guarantee, exactly?  It's just that the next hop
is set up when you follow the pointer, right?

Can I do something like the attached?  The mount 'm' is pinned, but I need to
trawl m->mnt_mounts.  mount_lock is a seqlock that ticks when mount topology
is rearranged.  I *think* it covers ->mnt_mounts.  Whilst trawling in
non-locked mode, I keep an eye on the seq counter and if it changes, the list
may have been altered and I need to get the real lock and restart.

The objects shouldn't disappear or be destroyed, so I think I'm safe.

Thanks,
David
---

int fsinfo_generic_mount_children(struct path *path, struct fsinfo_context *ctx)
{
	struct fsinfo_mount_child record = {};
	struct mount *m, *child;
	int seq = 0;

	m = real_mount(path->mnt);

	rcu_read_lock();
	do {
		ctx->usage = 0;
		read_seqbegin_or_lock(&mount_lock, &seq);
		list_for_each_entry_rcu(child, &m->mnt_mounts, mnt_child) {
			if (need_seqretry(&mount_lock, seq))
				break;
			if (child->mnt_parent != m)
				continue;
			record.mnt_unique_id = child->mnt_unique_id;
			record.mnt_id = child->mnt_id;
			record.notify_sum = 0;
#ifdef CONFIG_SB_NOTIFICATIONS
			record.notify_sum +=
				atomic_read(&child->mnt.mnt_sb->s_change_counter) +
				atomic_read(&child->mnt.mnt_sb->s_notify_counter);
#endif
#ifdef CONFIG_MOUNT_NOTIFICATIONS
			record.notify_sum +=
				atomic_read(&child->mnt_attr_changes) +
				atomic_read(&child->mnt_topology_changes) +
				atomic_read(&child->mnt_subtree_notifications);
#endif
			store_mount_fsinfo(ctx, &record);
		}
	} while (need_seqretry(&mount_lock, seq));
	done_seqretry(&mount_lock, seq);

	rcu_read_unlock();

	/* End the list with a copy of the parameter mount's details so that
	 * userspace can quickly check for changes.
	 */
	record.mnt_unique_id = m->mnt_unique_id;
	record.mnt_id = m->mnt_id;
	record.notify_sum = 0;
#ifdef CONFIG_SB_NOTIFICATIONS
	record.notify_sum +=
		atomic_read(&m->mnt.mnt_sb->s_change_counter) +
		atomic_read(&m->mnt.mnt_sb->s_notify_counter);
#endif
#ifdef CONFIG_MOUNT_NOTIFICATIONS
	record.notify_sum +=
		atomic_read(&m->mnt_attr_changes) +
		atomic_read(&m->mnt_topology_changes) +
		atomic_read(&m->mnt_subtree_notifications);
#endif
	store_mount_fsinfo(ctx, &record);
	return ctx->usage;
}


^ permalink raw reply	[flat|nested] 5+ messages in thread

end of thread, other threads:[~2020-03-08 14:32 UTC | newest]

Thread overview: 5+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2020-03-04 17:45 How to abuse RCU to scan the children of a mount? David Howells
2020-03-04 19:28 ` Paul E. McKenney
2020-03-04 19:44   ` Al Viro
2020-03-08 14:32     ` Paul E. McKenney
2020-03-05 12:47 ` David Howells

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.