V4 version of the lazytime patches
[ext4-patch-queue.git] / add-find-active-inode-nowait
blobf0bf1a9047c38ec5a683a68767c69d16fb7b5a0d
1 vfs: add find_active_inode_nowait() function
3 Add a new function find_active_inode_nowait() which will never block.
4 If there is an inode being freed or is still being initialized, this
5 function will return NULL instead of blocking waiting for an inode to
6 be freed or to finish initializing.  Hence, a negative return from
7 this function does not mean that inode number is free for use.  It is
8 useful for callers that want to opportunistically do some work on an
9 inode only if it is present and available in the cache, and where
10 blocking is not an option.
12 Signed-off-by: Theodore Ts'o <tytso@mit.edu>
13 ---
14 diff --git a/fs/inode.c b/fs/inode.c
15 index 8ceaa09..f9ad3fa 100644
16 --- a/fs/inode.c
17 +++ b/fs/inode.c
18 @@ -1283,6 +1283,42 @@ struct inode *ilookup(struct super_block *sb, unsigned long ino)
19  }
20  EXPORT_SYMBOL(ilookup);
22 +/**
23 + * find_active_inode_nowait - find an active inode in the inode cache
24 + * @sb:                super block of file system to search
25 + * @ino:       inode number to search for
26 + *
27 + * Search for an active inode @ino in the inode cache, and if the
28 + * inode is in the cache, the inode is returned with an incremented
29 + * reference count.  If the inode is being freed or is newly
30 + * initialized, return nothing instead of trying to wait for the inode
31 + * initialization or destruction to be complete.
32 + */
33 +struct inode *find_active_inode_nowait(struct super_block *sb,
34 +                                      unsigned long ino)
36 +       struct hlist_head *head = inode_hashtable + hash(sb, ino);
37 +       struct inode *inode, *ret_inode = NULL;
39 +       spin_lock(&inode_hash_lock);
40 +       hlist_for_each_entry(inode, head, i_hash) {
41 +               if ((inode->i_ino != ino) ||
42 +                   (inode->i_sb != sb))
43 +                       continue;
44 +               spin_lock(&inode->i_lock);
45 +               if ((inode->i_state & (I_FREEING | I_WILL_FREE | I_NEW)) == 0) {
46 +                       __iget(inode);
47 +                       ret_inode = inode;
48 +               }
49 +               spin_unlock(&inode->i_lock);
50 +               goto out;
51 +       }
52 +out:
53 +       spin_unlock(&inode_hash_lock);
54 +       return ret_inode;
56 +EXPORT_SYMBOL(find_active_inode_nowait);
58  int insert_inode_locked(struct inode *inode)
59  {
60         struct super_block *sb = inode->i_sb;
61 diff --git a/include/linux/fs.h b/include/linux/fs.h
62 index ff252cb..b24ad99 100644
63 --- a/include/linux/fs.h
64 +++ b/include/linux/fs.h
65 @@ -2414,6 +2414,8 @@ extern struct inode *ilookup(struct super_block *sb, unsigned long ino);
67  extern struct inode * iget5_locked(struct super_block *, unsigned long, int (*test)(struct inode *, void *), int (*set)(struct inode *, void *), void *);
68  extern struct inode * iget_locked(struct super_block *, unsigned long);
69 +extern struct inode *find_active_inode_nowait(struct super_block *,
70 +                                             unsigned long);
71  extern int insert_inode_locked4(struct inode *, unsigned long, int (*test)(struct inode *, void *), void *);
72  extern int insert_inode_locked(struct inode *);
73  #ifdef CONFIG_DEBUG_LOCK_ALLOC