aboutsummaryrefslogtreecommitdiffstats
path: root/fs/xfs/xfs_iget.c
diff options
context:
space:
mode:
Diffstat (limited to 'fs/xfs/xfs_iget.c')
-rw-r--r--fs/xfs/xfs_iget.c167
1 files changed, 35 insertions, 132 deletions
diff --git a/fs/xfs/xfs_iget.c b/fs/xfs/xfs_iget.c
index b2539b17c954..c4414e8bce8d 100644
--- a/fs/xfs/xfs_iget.c
+++ b/fs/xfs/xfs_iget.c
@@ -44,77 +44,65 @@
44 */ 44 */
45static int 45static int
46xfs_iget_cache_hit( 46xfs_iget_cache_hit(
47 struct inode *inode,
48 struct xfs_perag *pag, 47 struct xfs_perag *pag,
49 struct xfs_inode *ip, 48 struct xfs_inode *ip,
50 int flags, 49 int flags,
51 int lock_flags) __releases(pag->pag_ici_lock) 50 int lock_flags) __releases(pag->pag_ici_lock)
52{ 51{
53 struct xfs_mount *mp = ip->i_mount; 52 struct xfs_mount *mp = ip->i_mount;
54 struct inode *old_inode;
55 int error = 0; 53 int error = 0;
56 54
57 /* 55 /*
58 * If INEW is set this inode is being set up 56 * If INEW is set this inode is being set up
57 * If IRECLAIM is set this inode is being torn down
59 * Pause and try again. 58 * Pause and try again.
60 */ 59 */
61 if (xfs_iflags_test(ip, XFS_INEW)) { 60 if (xfs_iflags_test(ip, (XFS_INEW|XFS_IRECLAIM))) {
62 error = EAGAIN; 61 error = EAGAIN;
63 XFS_STATS_INC(xs_ig_frecycle); 62 XFS_STATS_INC(xs_ig_frecycle);
64 goto out_error; 63 goto out_error;
65 } 64 }
66 65
67 old_inode = ip->i_vnode; 66 /* If IRECLAIMABLE is set, we've torn down the vfs inode part */
68 if (old_inode == NULL) { 67 if (xfs_iflags_test(ip, XFS_IRECLAIMABLE)) {
68
69 /* 69 /*
70 * If IRECLAIM is set this inode is 70 * If lookup is racing with unlink, then we should return an
71 * on its way out of the system, 71 * error immediately so we don't remove it from the reclaim
72 * we need to pause and try again. 72 * list and potentially leak the inode.
73 */ 73 */
74 if (xfs_iflags_test(ip, XFS_IRECLAIM)) { 74
75 error = EAGAIN; 75 if ((ip->i_d.di_mode == 0) && !(flags & XFS_IGET_CREATE)) {
76 XFS_STATS_INC(xs_ig_frecycle); 76 error = ENOENT;
77 goto out_error; 77 goto out_error;
78 } 78 }
79 ASSERT(xfs_iflags_test(ip, XFS_IRECLAIMABLE)); 79
80 xfs_itrace_exit_tag(ip, "xfs_iget.alloc");
80 81
81 /* 82 /*
82 * If lookup is racing with unlink, then we 83 * We need to re-initialise the VFS inode as it has been
83 * should return an error immediately so we 84 * 'freed' by the VFS. Do this here so we can deal with
84 * don't remove it from the reclaim list and 85 * errors cleanly, then tag it so it can be set up correctly
85 * potentially leak the inode. 86 * later.
86 */ 87 */
87 if ((ip->i_d.di_mode == 0) && 88 if (!inode_init_always(mp->m_super, VFS_I(ip))) {
88 !(flags & XFS_IGET_CREATE)) { 89 error = ENOMEM;
89 error = ENOENT;
90 goto out_error; 90 goto out_error;
91 } 91 }
92 xfs_itrace_exit_tag(ip, "xfs_iget.alloc"); 92 xfs_iflags_set(ip, XFS_INEW);
93
94 xfs_iflags_clear(ip, XFS_IRECLAIMABLE); 93 xfs_iflags_clear(ip, XFS_IRECLAIMABLE);
95 read_unlock(&pag->pag_ici_lock); 94 read_unlock(&pag->pag_ici_lock);
96 95
97 XFS_MOUNT_ILOCK(mp); 96 XFS_MOUNT_ILOCK(mp);
98 list_del_init(&ip->i_reclaim); 97 list_del_init(&ip->i_reclaim);
99 XFS_MOUNT_IUNLOCK(mp); 98 XFS_MOUNT_IUNLOCK(mp);
100 99 } else if (!igrab(VFS_I(ip))) {
101 } else if (inode != old_inode) { 100 /* If the VFS inode is being torn down, pause and try again. */
102 /* The inode is being torn down, pause and 101 error = EAGAIN;
103 * try again. 102 XFS_STATS_INC(xs_ig_frecycle);
104 */ 103 goto out_error;
105 if (old_inode->i_state & (I_FREEING | I_CLEAR)) {
106 error = EAGAIN;
107 XFS_STATS_INC(xs_ig_frecycle);
108 goto out_error;
109 }
110/* Chances are the other vnode (the one in the inode) is being torn
111* down right now, and we landed on top of it. Question is, what do
112* we do? Unhook the old inode and hook up the new one?
113*/
114 cmn_err(CE_PANIC,
115 "xfs_iget_core: ambiguous vns: vp/0x%p, invp/0x%p",
116 old_inode, inode);
117 } else { 104 } else {
105 /* we've got a live one */
118 read_unlock(&pag->pag_ici_lock); 106 read_unlock(&pag->pag_ici_lock);
119 } 107 }
120 108
@@ -215,11 +203,11 @@ out_destroy:
215/* 203/*
216 * Look up an inode by number in the given file system. 204 * Look up an inode by number in the given file system.
217 * The inode is looked up in the cache held in each AG. 205 * The inode is looked up in the cache held in each AG.
218 * If the inode is found in the cache, attach it to the provided 206 * If the inode is found in the cache, initialise the vfs inode
219 * vnode. 207 * if necessary.
220 * 208 *
221 * If it is not in core, read it in from the file system's device, 209 * If it is not in core, read it in from the file system's device,
222 * add it to the cache and attach the provided vnode. 210 * add it to the cache and initialise the vfs inode.
223 * 211 *
224 * The inode is locked according to the value of the lock_flags parameter. 212 * The inode is locked according to the value of the lock_flags parameter.
225 * This flag parameter indicates how and if the inode's IO lock and inode lock 213 * This flag parameter indicates how and if the inode's IO lock and inode lock
@@ -236,9 +224,8 @@ out_destroy:
236 * bno -- the block number starting the buffer containing the inode, 224 * bno -- the block number starting the buffer containing the inode,
237 * if known (as by bulkstat), else 0. 225 * if known (as by bulkstat), else 0.
238 */ 226 */
239STATIC int 227int
240xfs_iget_core( 228xfs_iget(
241 struct inode *inode,
242 xfs_mount_t *mp, 229 xfs_mount_t *mp,
243 xfs_trans_t *tp, 230 xfs_trans_t *tp,
244 xfs_ino_t ino, 231 xfs_ino_t ino,
@@ -269,7 +256,7 @@ again:
269 ip = radix_tree_lookup(&pag->pag_ici_root, agino); 256 ip = radix_tree_lookup(&pag->pag_ici_root, agino);
270 257
271 if (ip) { 258 if (ip) {
272 error = xfs_iget_cache_hit(inode, pag, ip, flags, lock_flags); 259 error = xfs_iget_cache_hit(pag, ip, flags, lock_flags);
273 if (error) 260 if (error)
274 goto out_error_or_again; 261 goto out_error_or_again;
275 } else { 262 } else {
@@ -283,23 +270,16 @@ again:
283 } 270 }
284 xfs_put_perag(mp, pag); 271 xfs_put_perag(mp, pag);
285 272
286 ASSERT(ip->i_df.if_ext_max ==
287 XFS_IFORK_DSIZE(ip) / sizeof(xfs_bmbt_rec_t));
288
289 xfs_iflags_set(ip, XFS_IMODIFIED); 273 xfs_iflags_set(ip, XFS_IMODIFIED);
290 *ipp = ip; 274 *ipp = ip;
291 275
292 /* 276 ASSERT(ip->i_df.if_ext_max ==
293 * Set up the Linux with the Linux inode. 277 XFS_IFORK_DSIZE(ip) / sizeof(xfs_bmbt_rec_t));
294 */
295 ip->i_vnode = inode;
296 inode->i_private = ip;
297
298 /* 278 /*
299 * If we have a real type for an on-disk inode, we can set ops(&unlock) 279 * If we have a real type for an on-disk inode, we can set ops(&unlock)
300 * now. If it's a new inode being created, xfs_ialloc will handle it. 280 * now. If it's a new inode being created, xfs_ialloc will handle it.
301 */ 281 */
302 if (ip->i_d.di_mode != 0) 282 if (xfs_iflags_test(ip, XFS_INEW) && ip->i_d.di_mode != 0)
303 xfs_setup_inode(ip); 283 xfs_setup_inode(ip);
304 return 0; 284 return 0;
305 285
@@ -314,75 +294,6 @@ out_error_or_again:
314 294
315 295
316/* 296/*
317 * The 'normal' internal xfs_iget, if needed it will
318 * 'allocate', or 'get', the vnode.
319 */
320int
321xfs_iget(
322 xfs_mount_t *mp,
323 xfs_trans_t *tp,
324 xfs_ino_t ino,
325 uint flags,
326 uint lock_flags,
327 xfs_inode_t **ipp,
328 xfs_daddr_t bno)
329{
330 struct inode *inode;
331 xfs_inode_t *ip;
332 int error;
333
334 XFS_STATS_INC(xs_ig_attempts);
335
336retry:
337 inode = iget_locked(mp->m_super, ino);
338 if (!inode)
339 /* If we got no inode we are out of memory */
340 return ENOMEM;
341
342 if (inode->i_state & I_NEW) {
343 XFS_STATS_INC(vn_active);
344 XFS_STATS_INC(vn_alloc);
345
346 error = xfs_iget_core(inode, mp, tp, ino, flags,
347 lock_flags, ipp, bno);
348 if (error) {
349 make_bad_inode(inode);
350 if (inode->i_state & I_NEW)
351 unlock_new_inode(inode);
352 iput(inode);
353 }
354 return error;
355 }
356
357 /*
358 * If the inode is not fully constructed due to
359 * filehandle mismatches wait for the inode to go
360 * away and try again.
361 *
362 * iget_locked will call __wait_on_freeing_inode
363 * to wait for the inode to go away.
364 */
365 if (is_bad_inode(inode)) {
366 iput(inode);
367 delay(1);
368 goto retry;
369 }
370
371 ip = XFS_I(inode);
372 if (!ip) {
373 iput(inode);
374 delay(1);
375 goto retry;
376 }
377
378 if (lock_flags != 0)
379 xfs_ilock(ip, lock_flags);
380 XFS_STATS_INC(xs_ig_found);
381 *ipp = ip;
382 return 0;
383}
384
385/*
386 * Look for the inode corresponding to the given ino in the hash table. 297 * Look for the inode corresponding to the given ino in the hash table.
387 * If it is there and its i_transp pointer matches tp, return it. 298 * If it is there and its i_transp pointer matches tp, return it.
388 * Otherwise, return NULL. 299 * Otherwise, return NULL.
@@ -482,14 +393,6 @@ xfs_ireclaim(xfs_inode_t *ip)
482 XFS_QM_DQDETACH(ip->i_mount, ip); 393 XFS_QM_DQDETACH(ip->i_mount, ip);
483 394
484 /* 395 /*
485 * Pull our behavior descriptor from the vnode chain.
486 */
487 if (ip->i_vnode) {
488 ip->i_vnode->i_private = NULL;
489 ip->i_vnode = NULL;
490 }
491
492 /*
493 * Free all memory associated with the inode. 396 * Free all memory associated with the inode.
494 */ 397 */
495 xfs_iunlock(ip, XFS_ILOCK_EXCL | XFS_IOLOCK_EXCL); 398 xfs_iunlock(ip, XFS_ILOCK_EXCL | XFS_IOLOCK_EXCL);