Message ID | 1422855422-7444-3-git-send-email-tytso@mit.edu (mailing list archive) |
---|---|
State | New, archived |
Headers | show |
[CC += linux-api@] On Mon, Feb 2, 2015 at 6:37 AM, Theodore Ts'o <tytso@mit.edu> wrote: > 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> > --- > fs/inode.c | 50 ++++++++++++++++++++++++++++++++++++++++++++++++++ > include/linux/fs.h | 5 +++++ > 2 files changed, 55 insertions(+) > > diff --git a/fs/inode.c b/fs/inode.c > index 4feb85c..740cba7 100644 > --- a/fs/inode.c > +++ b/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; > diff --git a/include/linux/fs.h b/include/linux/fs.h > index 5ca285f..af810cc 100644 > --- a/include/linux/fs.h > +++ b/include/linux/fs.h > @@ -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 > -- > 2.1.0 > > -- > To unsubscribe from this list: send the line "unsubscribe linux-fsdevel" in > the body of a message to majordomo@vger.kernel.org > More majordomo info at http://vger.kernel.org/majordomo-info.html
diff --git a/fs/inode.c b/fs/inode.c index 4feb85c..740cba7 100644 --- a/fs/inode.c +++ b/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; diff --git a/include/linux/fs.h b/include/linux/fs.h index 5ca285f..af810cc 100644 --- a/include/linux/fs.h +++ b/include/linux/fs.h @@ -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
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> --- fs/inode.c | 50 ++++++++++++++++++++++++++++++++++++++++++++++++++ include/linux/fs.h | 5 +++++ 2 files changed, 55 insertions(+)