Skip to content

Commit fe032c4

Browse files
tytsoAl Viro
authored andcommitted
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>
1 parent 0ae45f6 commit fe032c4

File tree

2 files changed

+55
-0
lines changed

2 files changed

+55
-0
lines changed

fs/inode.c

Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1284,6 +1284,56 @@ struct inode *ilookup(struct super_block *sb, unsigned long ino)
12841284
}
12851285
EXPORT_SYMBOL(ilookup);
12861286

1287+
/**
1288+
* find_inode_nowait - find an inode in the inode cache
1289+
* @sb: super block of file system to search
1290+
* @hashval: hash value (usually inode number) to search for
1291+
* @match: callback used for comparisons between inodes
1292+
* @data: opaque data pointer to pass to @match
1293+
*
1294+
* Search for the inode specified by @hashval and @data in the inode
1295+
* cache, where the helper function @match will return 0 if the inode
1296+
* does not match, 1 if the inode does match, and -1 if the search
1297+
* should be stopped. The @match function must be responsible for
1298+
* taking the i_lock spin_lock and checking i_state for an inode being
1299+
* freed or being initialized, and incrementing the reference count
1300+
* before returning 1. It also must not sleep, since it is called with
1301+
* the inode_hash_lock spinlock held.
1302+
*
1303+
* This is a even more generalized version of ilookup5() when the
1304+
* function must never block --- find_inode() can block in
1305+
* __wait_on_freeing_inode() --- or when the caller can not increment
1306+
* the reference count because the resulting iput() might cause an
1307+
* inode eviction. The tradeoff is that the @match funtion must be
1308+
* very carefully implemented.
1309+
*/
1310+
struct inode *find_inode_nowait(struct super_block *sb,
1311+
unsigned long hashval,
1312+
int (*match)(struct inode *, unsigned long,
1313+
void *),
1314+
void *data)
1315+
{
1316+
struct hlist_head *head = inode_hashtable + hash(sb, hashval);
1317+
struct inode *inode, *ret_inode = NULL;
1318+
int mval;
1319+
1320+
spin_lock(&inode_hash_lock);
1321+
hlist_for_each_entry(inode, head, i_hash) {
1322+
if (inode->i_sb != sb)
1323+
continue;
1324+
mval = match(inode, hashval, data);
1325+
if (mval == 0)
1326+
continue;
1327+
if (mval == 1)
1328+
ret_inode = inode;
1329+
goto out;
1330+
}
1331+
out:
1332+
spin_unlock(&inode_hash_lock);
1333+
return ret_inode;
1334+
}
1335+
EXPORT_SYMBOL(find_inode_nowait);
1336+
12871337
int insert_inode_locked(struct inode *inode)
12881338
{
12891339
struct super_block *sb = inode->i_sb;

include/linux/fs.h

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2441,6 +2441,11 @@ extern struct inode *ilookup(struct super_block *sb, unsigned long ino);
24412441

24422442
extern struct inode * iget5_locked(struct super_block *, unsigned long, int (*test)(struct inode *, void *), int (*set)(struct inode *, void *), void *);
24432443
extern struct inode * iget_locked(struct super_block *, unsigned long);
2444+
extern struct inode *find_inode_nowait(struct super_block *,
2445+
unsigned long,
2446+
int (*match)(struct inode *,
2447+
unsigned long, void *),
2448+
void *data);
24442449
extern int insert_inode_locked4(struct inode *, unsigned long, int (*test)(struct inode *, void *), void *);
24452450
extern int insert_inode_locked(struct inode *);
24462451
#ifdef CONFIG_DEBUG_LOCK_ALLOC

0 commit comments

Comments
 (0)