add patch fix-mmap-data-corruption-in-nodelalloc-mode-when-blocksize-lt-pagesize
[ext4-patch-queue.git] / add-find-active-inode-nowait
blob8a6f437636454ceac756f5665688ba8c5419e17d
1 vfs: add find_inode_nowait() function
3 Add a new function find_inode_nowait() which is an even more general
4 version of ilookup5_nowait().  It is designed for callers which need
5 very fine grained control over when the function is allowed to block
6 or increment the inode's reference count.
8 Signed-off-by: Theodore Ts'o <tytso@mit.edu>
9 ---
10  fs/inode.c         | 50 ++++++++++++++++++++++++++++++++++++++++++++++++++
11  include/linux/fs.h |  5 +++++
12  2 files changed, 55 insertions(+)
14 diff --git a/fs/inode.c b/fs/inode.c
15 index dc48a23..09a57f2 100644
16 --- a/fs/inode.c
17 +++ b/fs/inode.c
18 @@ -1282,6 +1282,56 @@ struct inode *ilookup(struct super_block *sb, unsigned long ino)
19  }
20  EXPORT_SYMBOL(ilookup);
22 +/**
23 + * find_inode_nowait - find an inode in the inode cache
24 + * @sb:                super block of file system to search
25 + * @hashval:   hash value (usually inode number) to search for
26 + * @match:     callback used for comparisons between inodes
27 + * @data:      opaque data pointer to pass to @match
28 + *
29 + * Search for the inode specified by @hashval and @data in the inode
30 + * cache, where the helper function @match will return 0 if the inode
31 + * does not match, 1 if the inode does match, and -1 if the search
32 + * should be stopped.  The @match function must be responsible for
33 + * taking the i_lock spin_lock and checking i_state for an inode being
34 + * freed or being initialized, and incrementing the reference count
35 + * before returning 1.  It also must not sleep, since it is called with
36 + * the inode_hash_lock spinlock held.
37 + *
38 + * This is a even more generalized version of ilookup5() when the
39 + * function must never block --- find_inode() can block in
40 + * __wait_on_freeing_inode() --- or when the caller can not increment
41 + * the reference count because the resulting iput() might cause an
42 + * inode eviction.  The tradeoff is that the @match funtion must be
43 + * very carefully implemented.
44 + */
45 +struct inode *find_inode_nowait(struct super_block *sb,
46 +                               unsigned long hashval,
47 +                               int (*match)(struct inode *, unsigned long,
48 +                                            void *),
49 +                               void *data)
51 +       struct hlist_head *head = inode_hashtable + hash(sb, hashval);
52 +       struct inode *inode, *ret_inode = NULL;
53 +       int mval;
55 +       spin_lock(&inode_hash_lock);
56 +       hlist_for_each_entry(inode, head, i_hash) {
57 +               if (inode->i_sb != sb)
58 +                       continue;
59 +               mval = match(inode, hashval, data);
60 +               if (mval == 0)
61 +                       continue;
62 +               if (mval == 1)
63 +                       ret_inode = inode;
64 +               goto out;
65 +       }
66 +out:
67 +       spin_unlock(&inode_hash_lock);
68 +       return ret_inode;
70 +EXPORT_SYMBOL(find_inode_nowait);
72  int insert_inode_locked(struct inode *inode)
73  {
74         struct super_block *sb = inode->i_sb;
75 diff --git a/include/linux/fs.h b/include/linux/fs.h
76 index bf00e98..dfbba90 100644
77 --- a/include/linux/fs.h
78 +++ b/include/linux/fs.h
79 @@ -2415,6 +2415,11 @@ extern struct inode *ilookup(struct super_block *sb, unsigned long ino);
81  extern struct inode * iget5_locked(struct super_block *, unsigned long, int (*test)(struct inode *, void *), int (*set)(struct inode *, void *), void *);
82  extern struct inode * iget_locked(struct super_block *, unsigned long);
83 +extern struct inode *find_inode_nowait(struct super_block *,
84 +                                      unsigned long,
85 +                                      int (*match)(struct inode *,
86 +                                                   unsigned long, void *),
87 +                                      void *data);
88  extern int insert_inode_locked4(struct inode *, unsigned long, int (*test)(struct inode *, void *), void *);
89  extern int insert_inode_locked(struct inode *);
90  #ifdef CONFIG_DEBUG_LOCK_ALLOC