On Wed, Sep 04, 2013 at 04:05:48PM +0200, Miklos Szeredi wrote: > +static void check_and_drop(void *_data, struct dentry *dentry) > +{ > + struct select_data *data = _data; > + > + /* We're only interested in the root of this subtree */ > + if (data->start == dentry) { > + if (d_mountpoint(dentry)) > + data->found = -EBUSY; > + if (!data->found) > + __d_drop(dentry); > + } > +} Wouldn't it be better to do that in caller? Granted, it's not a hot path, but... why bother calling it for each dentry in a subtree, only to return immediately on all calls but the last one? > +static int __check_submounts_and_drop(struct dentry *parent, > + struct list_head *dispose) > +{ > + struct select_data data = { > + .start = parent, > + .dispose = dispose, > + .found = 0, > + }; > + > + d_walk(parent, &data, check_and_collect, check_and_drop); > + > + return data.found; > +} Incidentally, I would rather expand that in the only caller... > +/** > + * check_submounts_and_drop - prune dcache, check for submounts and drop > + * > + * All done as a single atomic operation relative to has_unlinked_ancestor(). > + * Returns 0 if successfully unhashed @parent. If there were submounts then > + * return -EBUSY. > + * > + * @dentry: dentry to prune and drop > + */ > +int check_submounts_and_drop(struct dentry *dentry) > +{ > + int ret = 0; > + > + /* Negative dentries can be dropped without further checks */ > + if (!dentry->d_inode) { > + d_drop(dentry); > + goto out; > + } > + > + spin_lock(&dentry->d_lock); > + if (d_unhashed(dentry)) > + goto out_unlock; > + if (list_empty(&dentry->d_subdirs)) { > + if (d_mountpoint(dentry)) { > + ret = -EBUSY; > + goto out_unlock; > + } > + __d_drop(dentry); > + goto out_unlock; > + } > + spin_unlock(&dentry->d_lock); > + > + for (;;) { > + LIST_HEAD(dispose); > + ret = __check_submounts_and_drop(dentry, &dispose); > + if (!list_empty(&dispose)) > + shrink_dentry_list(&dispose); > + > + if (ret <= 0) > + break; > + > + cond_resched(); > + } > + > +out: > + return ret; > + > +out_unlock: > + spin_unlock(&dentry->d_lock); > + goto out; > +} > +EXPORT_SYMBOL(check_submounts_and_drop); -- To unsubscribe from this list: send the line "unsubscribe linux-fsdevel" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html