|
@@ -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;
|