vfs: add find_inode_nowait() function
Add a new function find_inode_nowait() which is an even more general version of ilookup5_nowait(). It is designed for callers which need very fine grained control over when the function is allowed to block or increment the inode's reference count. Signed-off-by: Theodore Ts'o <tytso@mit.edu> Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
This commit is contained in:
parent
0ae45f63d4
commit
fe032c422c
50
fs/inode.c
50
fs/inode.c
|
@ -1284,6 +1284,56 @@ struct inode *ilookup(struct super_block *sb, unsigned long ino)
|
|||
}
|
||||
EXPORT_SYMBOL(ilookup);
|
||||
|
||||
/**
|
||||
* find_inode_nowait - find an inode in the inode cache
|
||||
* @sb: super block of file system to search
|
||||
* @hashval: hash value (usually inode number) to search for
|
||||
* @match: callback used for comparisons between inodes
|
||||
* @data: opaque data pointer to pass to @match
|
||||
*
|
||||
* Search for the inode specified by @hashval and @data in the inode
|
||||
* cache, where the helper function @match will return 0 if the inode
|
||||
* does not match, 1 if the inode does match, and -1 if the search
|
||||
* should be stopped. The @match function must be responsible for
|
||||
* taking the i_lock spin_lock and checking i_state for an inode being
|
||||
* freed or being initialized, and incrementing the reference count
|
||||
* before returning 1. It also must not sleep, since it is called with
|
||||
* the inode_hash_lock spinlock held.
|
||||
*
|
||||
* This is a even more generalized version of ilookup5() when the
|
||||
* function must never block --- find_inode() can block in
|
||||
* __wait_on_freeing_inode() --- or when the caller can not increment
|
||||
* the reference count because the resulting iput() might cause an
|
||||
* inode eviction. The tradeoff is that the @match funtion must be
|
||||
* very carefully implemented.
|
||||
*/
|
||||
struct inode *find_inode_nowait(struct super_block *sb,
|
||||
unsigned long hashval,
|
||||
int (*match)(struct inode *, unsigned long,
|
||||
void *),
|
||||
void *data)
|
||||
{
|
||||
struct hlist_head *head = inode_hashtable + hash(sb, hashval);
|
||||
struct inode *inode, *ret_inode = NULL;
|
||||
int mval;
|
||||
|
||||
spin_lock(&inode_hash_lock);
|
||||
hlist_for_each_entry(inode, head, i_hash) {
|
||||
if (inode->i_sb != sb)
|
||||
continue;
|
||||
mval = match(inode, hashval, data);
|
||||
if (mval == 0)
|
||||
continue;
|
||||
if (mval == 1)
|
||||
ret_inode = inode;
|
||||
goto out;
|
||||
}
|
||||
out:
|
||||
spin_unlock(&inode_hash_lock);
|
||||
return ret_inode;
|
||||
}
|
||||
EXPORT_SYMBOL(find_inode_nowait);
|
||||
|
||||
int insert_inode_locked(struct inode *inode)
|
||||
{
|
||||
struct super_block *sb = inode->i_sb;
|
||||
|
|
|
@ -2441,6 +2441,11 @@ extern struct inode *ilookup(struct super_block *sb, unsigned long ino);
|
|||
|
||||
extern struct inode * iget5_locked(struct super_block *, unsigned long, int (*test)(struct inode *, void *), int (*set)(struct inode *, void *), void *);
|
||||
extern struct inode * iget_locked(struct super_block *, unsigned long);
|
||||
extern struct inode *find_inode_nowait(struct super_block *,
|
||||
unsigned long,
|
||||
int (*match)(struct inode *,
|
||||
unsigned long, void *),
|
||||
void *data);
|
||||
extern int insert_inode_locked4(struct inode *, unsigned long, int (*test)(struct inode *, void *), void *);
|
||||
extern int insert_inode_locked(struct inode *);
|
||||
#ifdef CONFIG_DEBUG_LOCK_ALLOC
|
||||
|
|
Loading…
Reference in New Issue