From: NeilBrown <[email protected]> efivarfs() is similar to other filesystems which use d_alloc_name(), but it cannot use d_alloc_name() as it has a ->d_hash function.
The only problem with using ->d_hash if available is that it can return an error, but d_alloc_name() cannot. If we document that d_alloc_name() cannot be used when ->d_hash returns an error, then any filesystem which has a safe ->d_hash can safely use d_alloc_name(). So enhance d_alloc_name() to check for a ->d_hash function and document that this is not permitted if the ->d_hash function can fail( which efivarfs_d_hash() cannot). Also document locking requirements for use. This is a step towards eventually deprecating d_alloc(). Signed-off-by: NeilBrown <[email protected]> --- fs/dcache.c | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/fs/dcache.c b/fs/dcache.c index 2a100c616576..6dfc2c7110ba 100644 --- a/fs/dcache.c +++ b/fs/dcache.c @@ -1878,12 +1878,29 @@ struct dentry *d_alloc_pseudo(struct super_block *sb, const struct qstr *name) return dentry; } +/** + * d_alloc_name: allocate a dentry for use in a dcache-based filesystem. + * @parent: dentry of the parent for the dentry + * @name: name of the dentry + * + * d_alloc_name() allocates a dentry without any protection against races. + * It should only be used in directories that do not support create/rename/link + * inode operations. The result is typically passed to d_make_persistent(). + * + * This must NOT be used by filesystems which provide a d_hash() function + * which can return an error. + */ struct dentry *d_alloc_name(struct dentry *parent, const char *name) { struct qstr q; q.name = name; q.hash_len = hashlen_string(parent, name); + if (parent->d_flags & DCACHE_OP_HASH) { + int err = parent->d_op->d_hash(parent, &q); + if (WARN_ON_ONCE(err)) + return NULL; + } return d_alloc(parent, &q); } EXPORT_SYMBOL(d_alloc_name); -- 2.50.0.107.gf914562f5916.dirty
