d_alloc_anon
Subsystems (3)
PATCH 1/1 d_alloc_anon
Every filesystem that implements methods to convert from a NFS filehandle to a dentry duplicates this code (there are even more out of tree). Factor it out in common code. The function d_alloc_anon() is already present in 2.5 with the same interface but a slightly different implementation.
fs/dcache.c +47 -0
@@ -659,6 +659,53 @@ }/** +* d_alloc_anon - allocate an anonymous dentry +* @inode: inode to allocate the dentry for +* +* This is similar to d_alloc_root. It is used by filesystems when +* creating a dentry for a given inode, often in the process of +* mapping a filehandle to a dentry. The returned dentry may be +* anonymous, or may have a full name (if the inode was already +* in the cache). The file system may need to make further +* efforts to connect this dentry into the dcache properly. +* +* When called on a directory inode, we must ensure that +* the inode only ever has one dentry. If a dentry is +* found, that is returned instead of allocating a new one. +* +* On successful return, the reference to the inode has been transferred +* to the dentry. If %NULL is returned (indicating kmalloc failure), +* the reference on the inode has not been released. +*/ + +struct dentry *d_alloc_anon (struct inode *inode) +{ +struct dentry *dentry; +struct list_head *p; + +/* Try to find a dentry. If possible, get a well-connected one. */ +spin_lock (&dcache_lock); +list_for_each (p, &inode->i_dentry) { + dentry = list_entry(p, struct dentry, d_alias); +if (!(dentry->d_flags &DCACHE_NFSD_DISCONNECTED )) + goto found; + } +spin_unlock (&dcache_lock); + +/* Didn't find dentry. Create anonymous dcache entry. */ + dentry =d_alloc_root (inode); +if (dentry) + dentry->d_flags |=DCACHE_NFSD_DISCONNECTED ; +return dentry; + +found: +dget_locked (dentry); +spin_unlock (&dcache_lock); +iput (inode); +return dentry; +} + +/** * d_alloc_root - allocate root dentry * @root_inode: inode to allocate the root for *
fs/fat/inode.c +3 -23
@@ -430,7 +430,6 @@ int len, int fhtype, int parent) { struct inode *inode = NULL; -struct list_head *lp;struct dentry *result;if (fhtype !=3 )
@@ -477,33 +476,14 @@if (!inode)return ERR_PTR (-ESTALE ); - -/* now to find a dentry. -* If possible, get a well-connected one -* -* Given the way that we found the inode, it *MUST* be -* well-connected, but it is easiest to just copy the -* code. -*/ -spin_lock (&dcache_lock); -for (lp = inode->i_dentry.next; lp != &inode->i_dentry ; lp=lp->next) { - result = list_entry(lp,struct dentry, d_alias); -if (! (result->d_flags &DCACHE_NFSD_DISCONNECTED )) { -dget_locked (result); - result->d_vfs_flags |=DCACHE_REFERENCED ; -spin_unlock (&dcache_lock); -iput (inode); -return result; - } - } -spin_unlock (&dcache_lock); - result =d_alloc_root (inode); + + result =d_alloc_anon (inode);if (result ==NULL ) {iput (inode);return ERR_PTR (-ENOMEM ); } result->d_op = sb->s_root->d_op; - result->d_flags |=DCACHE_NFSD_DISCONNECTED ; + result->d_vfs_flags |=DCACHE_REFERENCED ;return result;
fs/nfsd/nfsfh.c +4 -18
@@ -135,7 +135,6 @@* of 0 means "accept any" */ struct inode *inode; -struct list_head *lp;struct dentry *result;if (ino ==0 )return ERR_PTR (-ESTALE );
@@ -155,27 +154,14 @@iput (inode);return ERR_PTR (-ESTALE ); } -/* now to find a dentry. -* If possible, get a well-connected one -*/ -spin_lock (&dcache_lock); -for (lp = inode->i_dentry.next; lp != &inode->i_dentry ; lp=lp->next) { - result = list_entry(lp,struct dentry, d_alias); -if (! (result->d_flags &DCACHE_NFSD_DISCONNECTED )) { -dget_locked (result); - result->d_vfs_flags |=DCACHE_REFERENCED ; -spin_unlock (&dcache_lock); -iput (inode); -return result; - } - } -spin_unlock (&dcache_lock); - result =d_alloc_root (inode); + + + result =d_alloc_anon (inode);if (result ==NULL ) {iput (inode);return ERR_PTR (-ENOMEM ); } - result->d_flags |=DCACHE_NFSD_DISCONNECTED ; + result->d_vfs_flags |=DCACHE_REFERENCED ;return result; }
fs/reiserfs/inode.c +2 -18
@@ -1249,7 +1249,6 @@ int len, int fhtype, int parent) { struct cpu_key key ;struct inode *inode =NULL ; -struct list_head *lp;struct dentry *result;/* fhtype happens to reflect the number of u32s encoded.
@@ -1301,27 +1300,12 @@if (!inode)return ERR_PTR (-ESTALE ) ; -/* now to find a dentry. -* If possible, get a well-connected one -*/ -spin_lock (&dcache_lock); -for (lp = inode->i_dentry.next; lp != &inode->i_dentry ; lp=lp->next) { - result = list_entry(lp,struct dentry, d_alias); -if (! (result->d_flags &DCACHE_NFSD_DISCONNECTED )) { -dget_locked (result); - result->d_vfs_flags |=DCACHE_REFERENCED ; -spin_unlock (&dcache_lock); -iput (inode); -return result; - } - } -spin_unlock (&dcache_lock); - result =d_alloc_root (inode); + result =d_alloc_anon (inode);if (result ==NULL ) {iput (inode);return ERR_PTR (-ENOMEM ); } - result->d_flags |=DCACHE_NFSD_DISCONNECTED ; + result->d_vfs_flags |=DCACHE_REFERENCED ;return result; }
include/linux/dcache.h +1 -0
@@ -165,6 +165,7 @@/* allocate/de-allocate */ extern struct dentry *d_alloc (struct dentry *,const struct qstr *); +extern struct dentry *d_alloc_anon (struct inode *);extern void shrink_dcache_sb (struct super_block *);extern void shrink_dcache_parent (struct dentry *);extern int d_invalidate (struct dentry *);
kernel/ksyms.c +1 -0
@@ -164,6 +164,7 @@EXPORT_SYMBOL (d_move);EXPORT_SYMBOL (d_instantiate);EXPORT_SYMBOL (d_alloc); +EXPORT_SYMBOL (d_alloc_anon);EXPORT_SYMBOL (d_lookup);EXPORT_SYMBOL (__d_path);EXPORT_SYMBOL (mark_buffer_dirty);