aboutsummaryrefslogtreecommitdiffstats
path: root/fs/xfs/xfs_icache.c
diff options
context:
space:
mode:
Diffstat (limited to 'fs/xfs/xfs_icache.c')
-rw-r--r--fs/xfs/xfs_icache.c43
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
98xfs_inode_free( 101xfs_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 */
148static int
149xfs_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 */
140static int 171static 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