diff options
Diffstat (limited to 'fs/xfs/xfs_icache.c')
-rw-r--r-- | fs/xfs/xfs_icache.c | 43 |
1 files changed, 37 insertions, 6 deletions
diff --git a/fs/xfs/xfs_icache.c b/fs/xfs/xfs_icache.c index d7a490f24ead..bf2d60749278 100644 --- a/fs/xfs/xfs_icache.c +++ b/fs/xfs/xfs_icache.c | |||
@@ -63,6 +63,9 @@ xfs_inode_alloc( | |||
63 | return NULL; | 63 | return NULL; |
64 | } | 64 | } |
65 | 65 | ||
66 | /* VFS doesn't initialise i_mode! */ | ||
67 | VFS_I(ip)->i_mode = 0; | ||
68 | |||
66 | XFS_STATS_INC(mp, vn_active); | 69 | XFS_STATS_INC(mp, vn_active); |
67 | ASSERT(atomic_read(&ip->i_pincount) == 0); | 70 | ASSERT(atomic_read(&ip->i_pincount) == 0); |
68 | ASSERT(!spin_is_locked(&ip->i_flags_lock)); | 71 | ASSERT(!spin_is_locked(&ip->i_flags_lock)); |
@@ -79,7 +82,7 @@ xfs_inode_alloc( | |||
79 | memset(&ip->i_df, 0, sizeof(xfs_ifork_t)); | 82 | memset(&ip->i_df, 0, sizeof(xfs_ifork_t)); |
80 | ip->i_flags = 0; | 83 | ip->i_flags = 0; |
81 | ip->i_delayed_blks = 0; | 84 | ip->i_delayed_blks = 0; |
82 | memset(&ip->i_d, 0, sizeof(xfs_icdinode_t)); | 85 | memset(&ip->i_d, 0, sizeof(ip->i_d)); |
83 | 86 | ||
84 | return ip; | 87 | return ip; |
85 | } | 88 | } |
@@ -98,7 +101,7 @@ void | |||
98 | xfs_inode_free( | 101 | xfs_inode_free( |
99 | struct xfs_inode *ip) | 102 | struct xfs_inode *ip) |
100 | { | 103 | { |
101 | switch (ip->i_d.di_mode & S_IFMT) { | 104 | switch (VFS_I(ip)->i_mode & S_IFMT) { |
102 | case S_IFREG: | 105 | case S_IFREG: |
103 | case S_IFDIR: | 106 | case S_IFDIR: |
104 | case S_IFLNK: | 107 | case S_IFLNK: |
@@ -135,6 +138,34 @@ xfs_inode_free( | |||
135 | } | 138 | } |
136 | 139 | ||
137 | /* | 140 | /* |
141 | * When we recycle a reclaimable inode, we need to re-initialise the VFS inode | ||
142 | * part of the structure. This is made more complex by the fact we store | ||
143 | * information about the on-disk values in the VFS inode and so we can't just | ||
144 | * overwrite the values unconditionally. Hence we save the parameters we | ||
145 | * need to retain across reinitialisation, and rewrite them into the VFS inode | ||
146 | * after reinitialisation even if it fails. | ||
147 | */ | ||
148 | static int | ||
149 | xfs_reinit_inode( | ||
150 | struct xfs_mount *mp, | ||
151 | struct inode *inode) | ||
152 | { | ||
153 | int error; | ||
154 | uint32_t nlink = inode->i_nlink; | ||
155 | uint32_t generation = inode->i_generation; | ||
156 | uint64_t version = inode->i_version; | ||
157 | umode_t mode = inode->i_mode; | ||
158 | |||
159 | error = inode_init_always(mp->m_super, inode); | ||
160 | |||
161 | set_nlink(inode, nlink); | ||
162 | inode->i_generation = generation; | ||
163 | inode->i_version = version; | ||
164 | inode->i_mode = mode; | ||
165 | return error; | ||
166 | } | ||
167 | |||
168 | /* | ||
138 | * Check the validity of the inode we just found it the cache | 169 | * Check the validity of the inode we just found it the cache |
139 | */ | 170 | */ |
140 | static int | 171 | static int |
@@ -185,7 +216,7 @@ xfs_iget_cache_hit( | |||
185 | /* | 216 | /* |
186 | * If lookup is racing with unlink return an error immediately. | 217 | * If lookup is racing with unlink return an error immediately. |
187 | */ | 218 | */ |
188 | if (ip->i_d.di_mode == 0 && !(flags & XFS_IGET_CREATE)) { | 219 | if (VFS_I(ip)->i_mode == 0 && !(flags & XFS_IGET_CREATE)) { |
189 | error = -ENOENT; | 220 | error = -ENOENT; |
190 | goto out_error; | 221 | goto out_error; |
191 | } | 222 | } |
@@ -208,7 +239,7 @@ xfs_iget_cache_hit( | |||
208 | spin_unlock(&ip->i_flags_lock); | 239 | spin_unlock(&ip->i_flags_lock); |
209 | rcu_read_unlock(); | 240 | rcu_read_unlock(); |
210 | 241 | ||
211 | error = inode_init_always(mp->m_super, inode); | 242 | error = xfs_reinit_inode(mp, inode); |
212 | if (error) { | 243 | if (error) { |
213 | /* | 244 | /* |
214 | * Re-initializing the inode failed, and we are in deep | 245 | * Re-initializing the inode failed, and we are in deep |
@@ -295,7 +326,7 @@ xfs_iget_cache_miss( | |||
295 | 326 | ||
296 | trace_xfs_iget_miss(ip); | 327 | trace_xfs_iget_miss(ip); |
297 | 328 | ||
298 | if ((ip->i_d.di_mode == 0) && !(flags & XFS_IGET_CREATE)) { | 329 | if ((VFS_I(ip)->i_mode == 0) && !(flags & XFS_IGET_CREATE)) { |
299 | error = -ENOENT; | 330 | error = -ENOENT; |
300 | goto out_destroy; | 331 | goto out_destroy; |
301 | } | 332 | } |
@@ -444,7 +475,7 @@ again: | |||
444 | * If we have a real type for an on-disk inode, we can setup the inode | 475 | * If we have a real type for an on-disk inode, we can setup the inode |
445 | * now. If it's a new inode being created, xfs_ialloc will handle it. | 476 | * now. If it's a new inode being created, xfs_ialloc will handle it. |
446 | */ | 477 | */ |
447 | if (xfs_iflags_test(ip, XFS_INEW) && ip->i_d.di_mode != 0) | 478 | if (xfs_iflags_test(ip, XFS_INEW) && VFS_I(ip)->i_mode != 0) |
448 | xfs_setup_existing_inode(ip); | 479 | xfs_setup_existing_inode(ip); |
449 | return 0; | 480 | return 0; |
450 | 481 | ||