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.c185
1 files changed, 73 insertions, 112 deletions
diff --git a/fs/xfs/xfs_iget.c b/fs/xfs/xfs_iget.c
index fb69ef180b2..f01b07687fa 100644
--- a/fs/xfs/xfs_iget.c
+++ b/fs/xfs/xfs_iget.c
@@ -65,7 +65,7 @@
65 */ 65 */
66STATIC int 66STATIC int
67xfs_iget_core( 67xfs_iget_core(
68 bhv_vnode_t *vp, 68 struct inode *inode,
69 xfs_mount_t *mp, 69 xfs_mount_t *mp,
70 xfs_trans_t *tp, 70 xfs_trans_t *tp,
71 xfs_ino_t ino, 71 xfs_ino_t ino,
@@ -74,9 +74,9 @@ xfs_iget_core(
74 xfs_inode_t **ipp, 74 xfs_inode_t **ipp,
75 xfs_daddr_t bno) 75 xfs_daddr_t bno)
76{ 76{
77 struct inode *old_inode;
77 xfs_inode_t *ip; 78 xfs_inode_t *ip;
78 xfs_inode_t *iq; 79 xfs_inode_t *iq;
79 bhv_vnode_t *inode_vp;
80 int error; 80 int error;
81 xfs_icluster_t *icl, *new_icl = NULL; 81 xfs_icluster_t *icl, *new_icl = NULL;
82 unsigned long first_index, mask; 82 unsigned long first_index, mask;
@@ -111,8 +111,8 @@ again:
111 goto again; 111 goto again;
112 } 112 }
113 113
114 inode_vp = XFS_ITOV_NULL(ip); 114 old_inode = ip->i_vnode;
115 if (inode_vp == NULL) { 115 if (old_inode == NULL) {
116 /* 116 /*
117 * If IRECLAIM is set this inode is 117 * If IRECLAIM is set this inode is
118 * on its way out of the system, 118 * on its way out of the system,
@@ -140,28 +140,9 @@ again:
140 return ENOENT; 140 return ENOENT;
141 } 141 }
142 142
143 /* 143 xfs_itrace_exit_tag(ip, "xfs_iget.alloc");
144 * There may be transactions sitting in the
145 * incore log buffers or being flushed to disk
146 * at this time. We can't clear the
147 * XFS_IRECLAIMABLE flag until these
148 * transactions have hit the disk, otherwise we
149 * will void the guarantee the flag provides
150 * xfs_iunpin()
151 */
152 if (xfs_ipincount(ip)) {
153 read_unlock(&pag->pag_ici_lock);
154 xfs_log_force(mp, 0,
155 XFS_LOG_FORCE|XFS_LOG_SYNC);
156 XFS_STATS_INC(xs_ig_frecycle);
157 goto again;
158 }
159
160 vn_trace_exit(ip, "xfs_iget.alloc",
161 (inst_t *)__return_address);
162 144
163 XFS_STATS_INC(xs_ig_found); 145 XFS_STATS_INC(xs_ig_found);
164
165 xfs_iflags_clear(ip, XFS_IRECLAIMABLE); 146 xfs_iflags_clear(ip, XFS_IRECLAIMABLE);
166 read_unlock(&pag->pag_ici_lock); 147 read_unlock(&pag->pag_ici_lock);
167 148
@@ -171,13 +152,11 @@ again:
171 152
172 goto finish_inode; 153 goto finish_inode;
173 154
174 } else if (vp != inode_vp) { 155 } else if (inode != old_inode) {
175 struct inode *inode = vn_to_inode(inode_vp);
176
177 /* The inode is being torn down, pause and 156 /* The inode is being torn down, pause and
178 * try again. 157 * try again.
179 */ 158 */
180 if (inode->i_state & (I_FREEING | I_CLEAR)) { 159 if (old_inode->i_state & (I_FREEING | I_CLEAR)) {
181 read_unlock(&pag->pag_ici_lock); 160 read_unlock(&pag->pag_ici_lock);
182 delay(1); 161 delay(1);
183 XFS_STATS_INC(xs_ig_frecycle); 162 XFS_STATS_INC(xs_ig_frecycle);
@@ -190,7 +169,7 @@ again:
190*/ 169*/
191 cmn_err(CE_PANIC, 170 cmn_err(CE_PANIC,
192 "xfs_iget_core: ambiguous vns: vp/0x%p, invp/0x%p", 171 "xfs_iget_core: ambiguous vns: vp/0x%p, invp/0x%p",
193 inode_vp, vp); 172 old_inode, inode);
194 } 173 }
195 174
196 /* 175 /*
@@ -200,20 +179,16 @@ again:
200 XFS_STATS_INC(xs_ig_found); 179 XFS_STATS_INC(xs_ig_found);
201 180
202finish_inode: 181finish_inode:
203 if (ip->i_d.di_mode == 0) { 182 if (ip->i_d.di_mode == 0 && !(flags & XFS_IGET_CREATE)) {
204 if (!(flags & XFS_IGET_CREATE)) { 183 xfs_put_perag(mp, pag);
205 xfs_put_perag(mp, pag); 184 return ENOENT;
206 return ENOENT;
207 }
208 xfs_iocore_inode_reinit(ip);
209 } 185 }
210 186
211 if (lock_flags != 0) 187 if (lock_flags != 0)
212 xfs_ilock(ip, lock_flags); 188 xfs_ilock(ip, lock_flags);
213 189
214 xfs_iflags_clear(ip, XFS_ISTALE); 190 xfs_iflags_clear(ip, XFS_ISTALE);
215 vn_trace_exit(ip, "xfs_iget.found", 191 xfs_itrace_exit_tag(ip, "xfs_iget.found");
216 (inst_t *)__return_address);
217 goto return_ip; 192 goto return_ip;
218 } 193 }
219 194
@@ -234,10 +209,16 @@ finish_inode:
234 return error; 209 return error;
235 } 210 }
236 211
237 vn_trace_exit(ip, "xfs_iget.alloc", (inst_t *)__return_address); 212 xfs_itrace_exit_tag(ip, "xfs_iget.alloc");
213
214
215 mrlock_init(&ip->i_lock, MRLOCK_ALLOW_EQUAL_PRI|MRLOCK_BARRIER,
216 "xfsino", ip->i_ino);
217 mrlock_init(&ip->i_iolock, MRLOCK_BARRIER, "xfsio", ip->i_ino);
218 init_waitqueue_head(&ip->i_ipin_wait);
219 atomic_set(&ip->i_pincount, 0);
220 initnsema(&ip->i_flock, 1, "xfsfino");
238 221
239 xfs_inode_lock_init(ip, vp);
240 xfs_iocore_inode_init(ip);
241 if (lock_flags) 222 if (lock_flags)
242 xfs_ilock(ip, lock_flags); 223 xfs_ilock(ip, lock_flags);
243 224
@@ -333,9 +314,6 @@ finish_inode:
333 ASSERT(ip->i_df.if_ext_max == 314 ASSERT(ip->i_df.if_ext_max ==
334 XFS_IFORK_DSIZE(ip) / sizeof(xfs_bmbt_rec_t)); 315 XFS_IFORK_DSIZE(ip) / sizeof(xfs_bmbt_rec_t));
335 316
336 ASSERT(((ip->i_d.di_flags & XFS_DIFLAG_REALTIME) != 0) ==
337 ((ip->i_iocore.io_flags & XFS_IOCORE_RT) != 0));
338
339 xfs_iflags_set(ip, XFS_IMODIFIED); 317 xfs_iflags_set(ip, XFS_IMODIFIED);
340 *ipp = ip; 318 *ipp = ip;
341 319
@@ -343,7 +321,7 @@ finish_inode:
343 * If we have a real type for an on-disk inode, we can set ops(&unlock) 321 * If we have a real type for an on-disk inode, we can set ops(&unlock)
344 * now. If it's a new inode being created, xfs_ialloc will handle it. 322 * now. If it's a new inode being created, xfs_ialloc will handle it.
345 */ 323 */
346 xfs_initialize_vnode(mp, vp, ip); 324 xfs_initialize_vnode(mp, inode, ip);
347 return 0; 325 return 0;
348} 326}
349 327
@@ -363,69 +341,58 @@ xfs_iget(
363 xfs_daddr_t bno) 341 xfs_daddr_t bno)
364{ 342{
365 struct inode *inode; 343 struct inode *inode;
366 bhv_vnode_t *vp = NULL; 344 xfs_inode_t *ip;
367 int error; 345 int error;
368 346
369 XFS_STATS_INC(xs_ig_attempts); 347 XFS_STATS_INC(xs_ig_attempts);
370 348
371retry: 349retry:
372 inode = iget_locked(mp->m_super, ino); 350 inode = iget_locked(mp->m_super, ino);
373 if (inode) { 351 if (!inode)
374 xfs_inode_t *ip; 352 /* If we got no inode we are out of memory */
375 353 return ENOMEM;
376 vp = vn_from_inode(inode); 354
377 if (inode->i_state & I_NEW) { 355 if (inode->i_state & I_NEW) {
378 vn_initialize(inode); 356 XFS_STATS_INC(vn_active);
379 error = xfs_iget_core(vp, mp, tp, ino, flags, 357 XFS_STATS_INC(vn_alloc);
380 lock_flags, ipp, bno); 358
381 if (error) { 359 error = xfs_iget_core(inode, mp, tp, ino, flags,
382 vn_mark_bad(vp); 360 lock_flags, ipp, bno);
383 if (inode->i_state & I_NEW) 361 if (error) {
384 unlock_new_inode(inode); 362 make_bad_inode(inode);
385 iput(inode); 363 if (inode->i_state & I_NEW)
386 } 364 unlock_new_inode(inode);
387 } else { 365 iput(inode);
388 /*
389 * If the inode is not fully constructed due to
390 * filehandle mismatches wait for the inode to go
391 * away and try again.
392 *
393 * iget_locked will call __wait_on_freeing_inode
394 * to wait for the inode to go away.
395 */
396 if (is_bad_inode(inode) ||
397 ((ip = xfs_vtoi(vp)) == NULL)) {
398 iput(inode);
399 delay(1);
400 goto retry;
401 }
402
403 if (lock_flags != 0)
404 xfs_ilock(ip, lock_flags);
405 XFS_STATS_INC(xs_ig_found);
406 *ipp = ip;
407 error = 0;
408 } 366 }
409 } else 367 return error;
410 error = ENOMEM; /* If we got no inode we are out of memory */ 368 }
411 369
412 return error; 370 /*
413} 371 * If the inode is not fully constructed due to
372 * filehandle mismatches wait for the inode to go
373 * away and try again.
374 *
375 * iget_locked will call __wait_on_freeing_inode
376 * to wait for the inode to go away.
377 */
378 if (is_bad_inode(inode)) {
379 iput(inode);
380 delay(1);
381 goto retry;
382 }
414 383
415/* 384 ip = XFS_I(inode);
416 * Do the setup for the various locks within the incore inode. 385 if (!ip) {
417 */ 386 iput(inode);
418void 387 delay(1);
419xfs_inode_lock_init( 388 goto retry;
420 xfs_inode_t *ip, 389 }
421 bhv_vnode_t *vp) 390
422{ 391 if (lock_flags != 0)
423 mrlock_init(&ip->i_lock, MRLOCK_ALLOW_EQUAL_PRI|MRLOCK_BARRIER, 392 xfs_ilock(ip, lock_flags);
424 "xfsino", ip->i_ino); 393 XFS_STATS_INC(xs_ig_found);
425 mrlock_init(&ip->i_iolock, MRLOCK_BARRIER, "xfsio", ip->i_ino); 394 *ipp = ip;
426 init_waitqueue_head(&ip->i_ipin_wait); 395 return 0;
427 atomic_set(&ip->i_pincount, 0);
428 initnsema(&ip->i_flock, 1, "xfsfino");
429} 396}
430 397
431/* 398/*
@@ -465,11 +432,9 @@ void
465xfs_iput(xfs_inode_t *ip, 432xfs_iput(xfs_inode_t *ip,
466 uint lock_flags) 433 uint lock_flags)
467{ 434{
468 bhv_vnode_t *vp = XFS_ITOV(ip); 435 xfs_itrace_entry(ip);
469
470 vn_trace_entry(ip, "xfs_iput", (inst_t *)__return_address);
471 xfs_iunlock(ip, lock_flags); 436 xfs_iunlock(ip, lock_flags);
472 VN_RELE(vp); 437 IRELE(ip);
473} 438}
474 439
475/* 440/*
@@ -479,20 +444,19 @@ void
479xfs_iput_new(xfs_inode_t *ip, 444xfs_iput_new(xfs_inode_t *ip,
480 uint lock_flags) 445 uint lock_flags)
481{ 446{
482 bhv_vnode_t *vp = XFS_ITOV(ip); 447 struct inode *inode = ip->i_vnode;
483 struct inode *inode = vn_to_inode(vp);
484 448
485 vn_trace_entry(ip, "xfs_iput_new", (inst_t *)__return_address); 449 xfs_itrace_entry(ip);
486 450
487 if ((ip->i_d.di_mode == 0)) { 451 if ((ip->i_d.di_mode == 0)) {
488 ASSERT(!xfs_iflags_test(ip, XFS_IRECLAIMABLE)); 452 ASSERT(!xfs_iflags_test(ip, XFS_IRECLAIMABLE));
489 vn_mark_bad(vp); 453 make_bad_inode(inode);
490 } 454 }
491 if (inode->i_state & I_NEW) 455 if (inode->i_state & I_NEW)
492 unlock_new_inode(inode); 456 unlock_new_inode(inode);
493 if (lock_flags) 457 if (lock_flags)
494 xfs_iunlock(ip, lock_flags); 458 xfs_iunlock(ip, lock_flags);
495 VN_RELE(vp); 459 IRELE(ip);
496} 460}
497 461
498 462
@@ -505,8 +469,6 @@ xfs_iput_new(xfs_inode_t *ip,
505void 469void
506xfs_ireclaim(xfs_inode_t *ip) 470xfs_ireclaim(xfs_inode_t *ip)
507{ 471{
508 bhv_vnode_t *vp;
509
510 /* 472 /*
511 * Remove from old hash list and mount list. 473 * Remove from old hash list and mount list.
512 */ 474 */
@@ -535,9 +497,8 @@ xfs_ireclaim(xfs_inode_t *ip)
535 /* 497 /*
536 * Pull our behavior descriptor from the vnode chain. 498 * Pull our behavior descriptor from the vnode chain.
537 */ 499 */
538 vp = XFS_ITOV_NULL(ip); 500 if (ip->i_vnode) {
539 if (vp) { 501 ip->i_vnode->i_private = NULL;
540 vn_to_inode(vp)->i_private = NULL;
541 ip->i_vnode = NULL; 502 ip->i_vnode = NULL;
542 } 503 }
543 504