diff options
author | Christoph Hellwig <hch@infradead.org> | 2008-10-30 02:14:53 -0400 |
---|---|---|
committer | Lachlan McIlroy <lachlan@sgi.com> | 2008-10-30 02:14:53 -0400 |
commit | 2af75df7be7ca86965bf73766f827575d1c26fbd (patch) | |
tree | 59a7acdf30d8f6088ebe4d88ce0f8d43be966671 /fs/xfs/linux-2.6/xfs_sync.c | |
parent | 4e8938feba770b583fb13d249c17943961731a3e (diff) |
[XFS] split out two helpers from xfs_syncsub
Split out two helpers from xfs_syncsub for the dummy log commit and the
superblock writeout.
SGI-PV: 988140
SGI-Modid: xfs-linux-melb:xfs-kern:32303a
Signed-off-by: Christoph Hellwig <hch@infradead.org>
Signed-off-by: David Chinner <david@fromorbit.com>
Signed-off-by: Lachlan McIlroy <lachlan@sgi.com>
Diffstat (limited to 'fs/xfs/linux-2.6/xfs_sync.c')
-rw-r--r-- | fs/xfs/linux-2.6/xfs_sync.c | 162 |
1 files changed, 93 insertions, 69 deletions
diff --git a/fs/xfs/linux-2.6/xfs_sync.c b/fs/xfs/linux-2.6/xfs_sync.c index 53d85ecb1d50..59da3327a6b5 100644 --- a/fs/xfs/linux-2.6/xfs_sync.c +++ b/fs/xfs/linux-2.6/xfs_sync.c | |||
@@ -315,6 +315,93 @@ xfs_sync_inodes( | |||
315 | return XFS_ERROR(last_error); | 315 | return XFS_ERROR(last_error); |
316 | } | 316 | } |
317 | 317 | ||
318 | STATIC int | ||
319 | xfs_commit_dummy_trans( | ||
320 | struct xfs_mount *mp, | ||
321 | uint log_flags) | ||
322 | { | ||
323 | struct xfs_inode *ip = mp->m_rootip; | ||
324 | struct xfs_trans *tp; | ||
325 | int error; | ||
326 | |||
327 | /* | ||
328 | * Put a dummy transaction in the log to tell recovery | ||
329 | * that all others are OK. | ||
330 | */ | ||
331 | tp = xfs_trans_alloc(mp, XFS_TRANS_DUMMY1); | ||
332 | error = xfs_trans_reserve(tp, 0, XFS_ICHANGE_LOG_RES(mp), 0, 0, 0); | ||
333 | if (error) { | ||
334 | xfs_trans_cancel(tp, 0); | ||
335 | return error; | ||
336 | } | ||
337 | |||
338 | xfs_ilock(ip, XFS_ILOCK_EXCL); | ||
339 | |||
340 | xfs_trans_ijoin(tp, ip, XFS_ILOCK_EXCL); | ||
341 | xfs_trans_ihold(tp, ip); | ||
342 | xfs_trans_log_inode(tp, ip, XFS_ILOG_CORE); | ||
343 | /* XXX(hch): ignoring the error here.. */ | ||
344 | error = xfs_trans_commit(tp, 0); | ||
345 | |||
346 | xfs_iunlock(ip, XFS_ILOCK_EXCL); | ||
347 | |||
348 | xfs_log_force(mp, 0, log_flags); | ||
349 | return 0; | ||
350 | } | ||
351 | |||
352 | STATIC int | ||
353 | xfs_sync_fsdata( | ||
354 | struct xfs_mount *mp, | ||
355 | int flags) | ||
356 | { | ||
357 | struct xfs_buf *bp; | ||
358 | struct xfs_buf_log_item *bip; | ||
359 | int error = 0; | ||
360 | |||
361 | /* | ||
362 | * If this is xfssyncd() then only sync the superblock if we can | ||
363 | * lock it without sleeping and it is not pinned. | ||
364 | */ | ||
365 | if (flags & SYNC_BDFLUSH) { | ||
366 | ASSERT(!(flags & SYNC_WAIT)); | ||
367 | |||
368 | bp = xfs_getsb(mp, XFS_BUF_TRYLOCK); | ||
369 | if (!bp) | ||
370 | goto out; | ||
371 | |||
372 | bip = XFS_BUF_FSPRIVATE(bp, struct xfs_buf_log_item *); | ||
373 | if (!bip || !xfs_buf_item_dirty(bip) || XFS_BUF_ISPINNED(bp)) | ||
374 | goto out_brelse; | ||
375 | } else { | ||
376 | bp = xfs_getsb(mp, 0); | ||
377 | |||
378 | /* | ||
379 | * If the buffer is pinned then push on the log so we won't | ||
380 | * get stuck waiting in the write for someone, maybe | ||
381 | * ourselves, to flush the log. | ||
382 | * | ||
383 | * Even though we just pushed the log above, we did not have | ||
384 | * the superblock buffer locked at that point so it can | ||
385 | * become pinned in between there and here. | ||
386 | */ | ||
387 | if (XFS_BUF_ISPINNED(bp)) | ||
388 | xfs_log_force(mp, 0, XFS_LOG_FORCE); | ||
389 | } | ||
390 | |||
391 | |||
392 | if (flags & SYNC_WAIT) | ||
393 | XFS_BUF_UNASYNC(bp); | ||
394 | else | ||
395 | XFS_BUF_ASYNC(bp); | ||
396 | |||
397 | return xfs_bwrite(mp, bp); | ||
398 | |||
399 | out_brelse: | ||
400 | xfs_buf_relse(bp); | ||
401 | out: | ||
402 | return error; | ||
403 | } | ||
404 | |||
318 | /* | 405 | /* |
319 | * xfs sync routine for internal use | 406 | * xfs sync routine for internal use |
320 | * | 407 | * |
@@ -331,8 +418,6 @@ xfs_syncsub( | |||
331 | int error = 0; | 418 | int error = 0; |
332 | int last_error = 0; | 419 | int last_error = 0; |
333 | uint log_flags = XFS_LOG_FORCE; | 420 | uint log_flags = XFS_LOG_FORCE; |
334 | xfs_buf_t *bp; | ||
335 | xfs_buf_log_item_t *bip; | ||
336 | 421 | ||
337 | /* | 422 | /* |
338 | * Sync out the log. This ensures that the log is periodically | 423 | * Sync out the log. This ensures that the log is periodically |
@@ -355,83 +440,22 @@ xfs_syncsub( | |||
355 | * log activity, so if this isn't vfs_sync() then flush | 440 | * log activity, so if this isn't vfs_sync() then flush |
356 | * the log again. | 441 | * the log again. |
357 | */ | 442 | */ |
358 | if (flags & SYNC_DELWRI) { | 443 | if (flags & SYNC_DELWRI) |
359 | xfs_log_force(mp, (xfs_lsn_t)0, log_flags); | 444 | xfs_log_force(mp, 0, log_flags); |
360 | } | ||
361 | 445 | ||
362 | if (flags & SYNC_FSDATA) { | 446 | if (flags & SYNC_FSDATA) { |
363 | /* | 447 | error = xfs_sync_fsdata(mp, flags); |
364 | * If this is vfs_sync() then only sync the superblock | 448 | if (error) |
365 | * if we can lock it without sleeping and it is not pinned. | ||
366 | */ | ||
367 | if (flags & SYNC_BDFLUSH) { | ||
368 | bp = xfs_getsb(mp, XFS_BUF_TRYLOCK); | ||
369 | if (bp != NULL) { | ||
370 | bip = XFS_BUF_FSPRIVATE(bp,xfs_buf_log_item_t*); | ||
371 | if ((bip != NULL) && | ||
372 | xfs_buf_item_dirty(bip)) { | ||
373 | if (!(XFS_BUF_ISPINNED(bp))) { | ||
374 | XFS_BUF_ASYNC(bp); | ||
375 | error = xfs_bwrite(mp, bp); | ||
376 | } else { | ||
377 | xfs_buf_relse(bp); | ||
378 | } | ||
379 | } else { | ||
380 | xfs_buf_relse(bp); | ||
381 | } | ||
382 | } | ||
383 | } else { | ||
384 | bp = xfs_getsb(mp, 0); | ||
385 | /* | ||
386 | * If the buffer is pinned then push on the log so | ||
387 | * we won't get stuck waiting in the write for | ||
388 | * someone, maybe ourselves, to flush the log. | ||
389 | * Even though we just pushed the log above, we | ||
390 | * did not have the superblock buffer locked at | ||
391 | * that point so it can become pinned in between | ||
392 | * there and here. | ||
393 | */ | ||
394 | if (XFS_BUF_ISPINNED(bp)) | ||
395 | xfs_log_force(mp, (xfs_lsn_t)0, XFS_LOG_FORCE); | ||
396 | if (flags & SYNC_WAIT) | ||
397 | XFS_BUF_UNASYNC(bp); | ||
398 | else | ||
399 | XFS_BUF_ASYNC(bp); | ||
400 | error = xfs_bwrite(mp, bp); | ||
401 | } | ||
402 | if (error) { | ||
403 | last_error = error; | 449 | last_error = error; |
404 | } | ||
405 | } | 450 | } |
406 | 451 | ||
407 | /* | 452 | /* |
408 | * Now check to see if the log needs a "dummy" transaction. | 453 | * Now check to see if the log needs a "dummy" transaction. |
409 | */ | 454 | */ |
410 | if (!(flags & SYNC_REMOUNT) && xfs_log_need_covered(mp)) { | 455 | if (!(flags & SYNC_REMOUNT) && xfs_log_need_covered(mp)) { |
411 | xfs_trans_t *tp; | 456 | error = xfs_commit_dummy_trans(mp, log_flags); |
412 | xfs_inode_t *ip; | 457 | if (error) |
413 | |||
414 | /* | ||
415 | * Put a dummy transaction in the log to tell | ||
416 | * recovery that all others are OK. | ||
417 | */ | ||
418 | tp = xfs_trans_alloc(mp, XFS_TRANS_DUMMY1); | ||
419 | if ((error = xfs_trans_reserve(tp, 0, | ||
420 | XFS_ICHANGE_LOG_RES(mp), | ||
421 | 0, 0, 0))) { | ||
422 | xfs_trans_cancel(tp, 0); | ||
423 | return error; | 458 | return error; |
424 | } | ||
425 | |||
426 | ip = mp->m_rootip; | ||
427 | xfs_ilock(ip, XFS_ILOCK_EXCL); | ||
428 | |||
429 | xfs_trans_ijoin(tp, ip, XFS_ILOCK_EXCL); | ||
430 | xfs_trans_ihold(tp, ip); | ||
431 | xfs_trans_log_inode(tp, ip, XFS_ILOG_CORE); | ||
432 | error = xfs_trans_commit(tp, 0); | ||
433 | xfs_iunlock(ip, XFS_ILOCK_EXCL); | ||
434 | xfs_log_force(mp, (xfs_lsn_t)0, log_flags); | ||
435 | } | 459 | } |
436 | 460 | ||
437 | /* | 461 | /* |