diff options
| author | Felix Blyakher <felixb@sgi.com> | 2009-04-09 15:12:07 -0400 |
|---|---|---|
| committer | Felix Blyakher <felixb@sgi.com> | 2009-04-09 15:12:07 -0400 |
| commit | dc2a5536d633dd2318f82f3d5ad3c9e43cfc21d7 (patch) | |
| tree | 20b68d90d175eb9f07cf19b2e8be4011a8e8e6e5 /fs | |
| parent | f36345ff9a4a77f2cc576a2777b6256d5c8798fa (diff) | |
| parent | 8de2bf937a6bea8f0f775fd5399ba20c1a0c3d77 (diff) | |
Merge branch 'master' into for-linus
Diffstat (limited to 'fs')
| -rw-r--r-- | fs/xfs/linux-2.6/xfs_aops.c | 38 | ||||
| -rw-r--r-- | fs/xfs/linux-2.6/xfs_aops.h | 1 | ||||
| -rw-r--r-- | fs/xfs/linux-2.6/xfs_buf.c | 9 | ||||
| -rw-r--r-- | fs/xfs/linux-2.6/xfs_fs_subr.c | 14 | ||||
| -rw-r--r-- | fs/xfs/linux-2.6/xfs_lrw.c | 18 | ||||
| -rw-r--r-- | fs/xfs/linux-2.6/xfs_sync.c | 78 | ||||
| -rw-r--r-- | fs/xfs/linux-2.6/xfs_sync.h | 9 | ||||
| -rw-r--r-- | fs/xfs/xfs_iget.c | 23 | ||||
| -rw-r--r-- | fs/xfs/xfs_iomap.c | 61 | ||||
| -rw-r--r-- | fs/xfs/xfs_iomap.h | 3 | ||||
| -rw-r--r-- | fs/xfs/xfs_log.c | 78 | ||||
| -rw-r--r-- | fs/xfs/xfs_mount.h | 2 | ||||
| -rw-r--r-- | fs/xfs/xfs_vnodeops.c | 7 |
13 files changed, 180 insertions, 161 deletions
diff --git a/fs/xfs/linux-2.6/xfs_aops.c b/fs/xfs/linux-2.6/xfs_aops.c index c13f67300fe7..7ec89fc05b2b 100644 --- a/fs/xfs/linux-2.6/xfs_aops.c +++ b/fs/xfs/linux-2.6/xfs_aops.c | |||
| @@ -153,23 +153,6 @@ xfs_find_bdev_for_inode( | |||
| 153 | } | 153 | } |
| 154 | 154 | ||
| 155 | /* | 155 | /* |
| 156 | * Schedule IO completion handling on a xfsdatad if this was | ||
| 157 | * the final hold on this ioend. If we are asked to wait, | ||
| 158 | * flush the workqueue. | ||
| 159 | */ | ||
| 160 | STATIC void | ||
| 161 | xfs_finish_ioend( | ||
| 162 | xfs_ioend_t *ioend, | ||
| 163 | int wait) | ||
| 164 | { | ||
| 165 | if (atomic_dec_and_test(&ioend->io_remaining)) { | ||
| 166 | queue_work(xfsdatad_workqueue, &ioend->io_work); | ||
| 167 | if (wait) | ||
| 168 | flush_workqueue(xfsdatad_workqueue); | ||
| 169 | } | ||
| 170 | } | ||
| 171 | |||
| 172 | /* | ||
| 173 | * We're now finished for good with this ioend structure. | 156 | * We're now finished for good with this ioend structure. |
| 174 | * Update the page state via the associated buffer_heads, | 157 | * Update the page state via the associated buffer_heads, |
| 175 | * release holds on the inode and bio, and finally free | 158 | * release holds on the inode and bio, and finally free |
| @@ -310,6 +293,27 @@ xfs_end_bio_read( | |||
| 310 | } | 293 | } |
| 311 | 294 | ||
| 312 | /* | 295 | /* |
| 296 | * Schedule IO completion handling on a xfsdatad if this was | ||
| 297 | * the final hold on this ioend. If we are asked to wait, | ||
| 298 | * flush the workqueue. | ||
| 299 | */ | ||
| 300 | STATIC void | ||
| 301 | xfs_finish_ioend( | ||
| 302 | xfs_ioend_t *ioend, | ||
| 303 | int wait) | ||
| 304 | { | ||
| 305 | if (atomic_dec_and_test(&ioend->io_remaining)) { | ||
| 306 | struct workqueue_struct *wq = xfsdatad_workqueue; | ||
| 307 | if (ioend->io_work.func == xfs_end_bio_unwritten) | ||
| 308 | wq = xfsconvertd_workqueue; | ||
| 309 | |||
| 310 | queue_work(wq, &ioend->io_work); | ||
| 311 | if (wait) | ||
| 312 | flush_workqueue(wq); | ||
| 313 | } | ||
| 314 | } | ||
| 315 | |||
| 316 | /* | ||
| 313 | * Allocate and initialise an IO completion structure. | 317 | * Allocate and initialise an IO completion structure. |
| 314 | * We need to track unwritten extent write completion here initially. | 318 | * We need to track unwritten extent write completion here initially. |
| 315 | * We'll need to extend this for updating the ondisk inode size later | 319 | * We'll need to extend this for updating the ondisk inode size later |
diff --git a/fs/xfs/linux-2.6/xfs_aops.h b/fs/xfs/linux-2.6/xfs_aops.h index 1dd528849755..221b3e66ceef 100644 --- a/fs/xfs/linux-2.6/xfs_aops.h +++ b/fs/xfs/linux-2.6/xfs_aops.h | |||
| @@ -19,6 +19,7 @@ | |||
| 19 | #define __XFS_AOPS_H__ | 19 | #define __XFS_AOPS_H__ |
| 20 | 20 | ||
| 21 | extern struct workqueue_struct *xfsdatad_workqueue; | 21 | extern struct workqueue_struct *xfsdatad_workqueue; |
| 22 | extern struct workqueue_struct *xfsconvertd_workqueue; | ||
| 22 | extern mempool_t *xfs_ioend_pool; | 23 | extern mempool_t *xfs_ioend_pool; |
| 23 | 24 | ||
| 24 | /* | 25 | /* |
diff --git a/fs/xfs/linux-2.6/xfs_buf.c b/fs/xfs/linux-2.6/xfs_buf.c index aa1016bb9134..e28800a9f2b5 100644 --- a/fs/xfs/linux-2.6/xfs_buf.c +++ b/fs/xfs/linux-2.6/xfs_buf.c | |||
| @@ -51,6 +51,7 @@ static struct shrinker xfs_buf_shake = { | |||
| 51 | 51 | ||
| 52 | static struct workqueue_struct *xfslogd_workqueue; | 52 | static struct workqueue_struct *xfslogd_workqueue; |
| 53 | struct workqueue_struct *xfsdatad_workqueue; | 53 | struct workqueue_struct *xfsdatad_workqueue; |
| 54 | struct workqueue_struct *xfsconvertd_workqueue; | ||
| 54 | 55 | ||
| 55 | #ifdef XFS_BUF_TRACE | 56 | #ifdef XFS_BUF_TRACE |
| 56 | void | 57 | void |
| @@ -1775,6 +1776,7 @@ xfs_flush_buftarg( | |||
| 1775 | xfs_buf_t *bp, *n; | 1776 | xfs_buf_t *bp, *n; |
| 1776 | int pincount = 0; | 1777 | int pincount = 0; |
| 1777 | 1778 | ||
| 1779 | xfs_buf_runall_queues(xfsconvertd_workqueue); | ||
| 1778 | xfs_buf_runall_queues(xfsdatad_workqueue); | 1780 | xfs_buf_runall_queues(xfsdatad_workqueue); |
| 1779 | xfs_buf_runall_queues(xfslogd_workqueue); | 1781 | xfs_buf_runall_queues(xfslogd_workqueue); |
| 1780 | 1782 | ||
| @@ -1831,9 +1833,15 @@ xfs_buf_init(void) | |||
| 1831 | if (!xfsdatad_workqueue) | 1833 | if (!xfsdatad_workqueue) |
| 1832 | goto out_destroy_xfslogd_workqueue; | 1834 | goto out_destroy_xfslogd_workqueue; |
| 1833 | 1835 | ||
| 1836 | xfsconvertd_workqueue = create_workqueue("xfsconvertd"); | ||
| 1837 | if (!xfsconvertd_workqueue) | ||
| 1838 | goto out_destroy_xfsdatad_workqueue; | ||
| 1839 | |||
| 1834 | register_shrinker(&xfs_buf_shake); | 1840 | register_shrinker(&xfs_buf_shake); |
| 1835 | return 0; | 1841 | return 0; |
| 1836 | 1842 | ||
| 1843 | out_destroy_xfsdatad_workqueue: | ||
| 1844 | destroy_workqueue(xfsdatad_workqueue); | ||
| 1837 | out_destroy_xfslogd_workqueue: | 1845 | out_destroy_xfslogd_workqueue: |
| 1838 | destroy_workqueue(xfslogd_workqueue); | 1846 | destroy_workqueue(xfslogd_workqueue); |
| 1839 | out_free_buf_zone: | 1847 | out_free_buf_zone: |
| @@ -1849,6 +1857,7 @@ void | |||
| 1849 | xfs_buf_terminate(void) | 1857 | xfs_buf_terminate(void) |
| 1850 | { | 1858 | { |
| 1851 | unregister_shrinker(&xfs_buf_shake); | 1859 | unregister_shrinker(&xfs_buf_shake); |
| 1860 | destroy_workqueue(xfsconvertd_workqueue); | ||
| 1852 | destroy_workqueue(xfsdatad_workqueue); | 1861 | destroy_workqueue(xfsdatad_workqueue); |
| 1853 | destroy_workqueue(xfslogd_workqueue); | 1862 | destroy_workqueue(xfslogd_workqueue); |
| 1854 | kmem_zone_destroy(xfs_buf_zone); | 1863 | kmem_zone_destroy(xfs_buf_zone); |
diff --git a/fs/xfs/linux-2.6/xfs_fs_subr.c b/fs/xfs/linux-2.6/xfs_fs_subr.c index 5aeb77776961..08be36d7326c 100644 --- a/fs/xfs/linux-2.6/xfs_fs_subr.c +++ b/fs/xfs/linux-2.6/xfs_fs_subr.c | |||
| @@ -74,14 +74,14 @@ xfs_flush_pages( | |||
| 74 | 74 | ||
| 75 | if (mapping_tagged(mapping, PAGECACHE_TAG_DIRTY)) { | 75 | if (mapping_tagged(mapping, PAGECACHE_TAG_DIRTY)) { |
| 76 | xfs_iflags_clear(ip, XFS_ITRUNCATED); | 76 | xfs_iflags_clear(ip, XFS_ITRUNCATED); |
| 77 | ret = filemap_fdatawrite(mapping); | 77 | ret = -filemap_fdatawrite(mapping); |
| 78 | if (flags & XFS_B_ASYNC) | ||
| 79 | return -ret; | ||
| 80 | ret2 = filemap_fdatawait(mapping); | ||
| 81 | if (!ret) | ||
| 82 | ret = ret2; | ||
| 83 | } | 78 | } |
| 84 | return -ret; | 79 | if (flags & XFS_B_ASYNC) |
| 80 | return ret; | ||
| 81 | ret2 = xfs_wait_on_pages(ip, first, last); | ||
| 82 | if (!ret) | ||
| 83 | ret = ret2; | ||
| 84 | return ret; | ||
| 85 | } | 85 | } |
| 86 | 86 | ||
| 87 | int | 87 | int |
diff --git a/fs/xfs/linux-2.6/xfs_lrw.c b/fs/xfs/linux-2.6/xfs_lrw.c index 7e90daa0d1d1..9142192ccbe6 100644 --- a/fs/xfs/linux-2.6/xfs_lrw.c +++ b/fs/xfs/linux-2.6/xfs_lrw.c | |||
| @@ -751,10 +751,26 @@ start: | |||
| 751 | goto relock; | 751 | goto relock; |
| 752 | } | 752 | } |
| 753 | } else { | 753 | } else { |
| 754 | int enospc = 0; | ||
| 755 | ssize_t ret2 = 0; | ||
| 756 | |||
| 757 | write_retry: | ||
| 754 | xfs_rw_enter_trace(XFS_WRITE_ENTER, xip, (void *)iovp, segs, | 758 | xfs_rw_enter_trace(XFS_WRITE_ENTER, xip, (void *)iovp, segs, |
| 755 | *offset, ioflags); | 759 | *offset, ioflags); |
| 756 | ret = generic_file_buffered_write(iocb, iovp, segs, | 760 | ret2 = generic_file_buffered_write(iocb, iovp, segs, |
| 757 | pos, offset, count, ret); | 761 | pos, offset, count, ret); |
| 762 | /* | ||
| 763 | * if we just got an ENOSPC, flush the inode now we | ||
| 764 | * aren't holding any page locks and retry *once* | ||
| 765 | */ | ||
| 766 | if (ret2 == -ENOSPC && !enospc) { | ||
| 767 | error = xfs_flush_pages(xip, 0, -1, 0, FI_NONE); | ||
| 768 | if (error) | ||
| 769 | goto out_unlock_internal; | ||
| 770 | enospc = 1; | ||
| 771 | goto write_retry; | ||
| 772 | } | ||
| 773 | ret = ret2; | ||
| 758 | } | 774 | } |
| 759 | 775 | ||
| 760 | current->backing_dev_info = NULL; | 776 | current->backing_dev_info = NULL; |
diff --git a/fs/xfs/linux-2.6/xfs_sync.c b/fs/xfs/linux-2.6/xfs_sync.c index a608e72fa405..f7ba76633c29 100644 --- a/fs/xfs/linux-2.6/xfs_sync.c +++ b/fs/xfs/linux-2.6/xfs_sync.c | |||
| @@ -62,12 +62,6 @@ xfs_sync_inodes_ag( | |||
| 62 | uint32_t first_index = 0; | 62 | uint32_t first_index = 0; |
| 63 | int error = 0; | 63 | int error = 0; |
| 64 | int last_error = 0; | 64 | int last_error = 0; |
| 65 | int fflag = XFS_B_ASYNC; | ||
| 66 | |||
| 67 | if (flags & SYNC_DELWRI) | ||
| 68 | fflag = XFS_B_DELWRI; | ||
| 69 | if (flags & SYNC_WAIT) | ||
| 70 | fflag = 0; /* synchronous overrides all */ | ||
| 71 | 65 | ||
| 72 | do { | 66 | do { |
| 73 | struct inode *inode; | 67 | struct inode *inode; |
| @@ -128,11 +122,23 @@ xfs_sync_inodes_ag( | |||
| 128 | * If we have to flush data or wait for I/O completion | 122 | * If we have to flush data or wait for I/O completion |
| 129 | * we need to hold the iolock. | 123 | * we need to hold the iolock. |
| 130 | */ | 124 | */ |
| 131 | if ((flags & SYNC_DELWRI) && VN_DIRTY(inode)) { | 125 | if (flags & SYNC_DELWRI) { |
| 132 | xfs_ilock(ip, XFS_IOLOCK_SHARED); | 126 | if (VN_DIRTY(inode)) { |
| 133 | lock_flags |= XFS_IOLOCK_SHARED; | 127 | if (flags & SYNC_TRYLOCK) { |
| 134 | error = xfs_flush_pages(ip, 0, -1, fflag, FI_NONE); | 128 | if (xfs_ilock_nowait(ip, XFS_IOLOCK_SHARED)) |
| 135 | if (flags & SYNC_IOWAIT) | 129 | lock_flags |= XFS_IOLOCK_SHARED; |
| 130 | } else { | ||
| 131 | xfs_ilock(ip, XFS_IOLOCK_SHARED); | ||
| 132 | lock_flags |= XFS_IOLOCK_SHARED; | ||
| 133 | } | ||
| 134 | if (lock_flags & XFS_IOLOCK_SHARED) { | ||
| 135 | error = xfs_flush_pages(ip, 0, -1, | ||
| 136 | (flags & SYNC_WAIT) ? 0 | ||
| 137 | : XFS_B_ASYNC, | ||
| 138 | FI_NONE); | ||
| 139 | } | ||
| 140 | } | ||
| 141 | if (VN_CACHED(inode) && (flags & SYNC_IOWAIT)) | ||
| 136 | xfs_ioend_wait(ip); | 142 | xfs_ioend_wait(ip); |
| 137 | } | 143 | } |
| 138 | xfs_ilock(ip, XFS_ILOCK_SHARED); | 144 | xfs_ilock(ip, XFS_ILOCK_SHARED); |
| @@ -398,15 +404,17 @@ STATIC void | |||
| 398 | xfs_syncd_queue_work( | 404 | xfs_syncd_queue_work( |
| 399 | struct xfs_mount *mp, | 405 | struct xfs_mount *mp, |
| 400 | void *data, | 406 | void *data, |
| 401 | void (*syncer)(struct xfs_mount *, void *)) | 407 | void (*syncer)(struct xfs_mount *, void *), |
| 408 | struct completion *completion) | ||
| 402 | { | 409 | { |
| 403 | struct bhv_vfs_sync_work *work; | 410 | struct xfs_sync_work *work; |
| 404 | 411 | ||
| 405 | work = kmem_alloc(sizeof(struct bhv_vfs_sync_work), KM_SLEEP); | 412 | work = kmem_alloc(sizeof(struct xfs_sync_work), KM_SLEEP); |
| 406 | INIT_LIST_HEAD(&work->w_list); | 413 | INIT_LIST_HEAD(&work->w_list); |
| 407 | work->w_syncer = syncer; | 414 | work->w_syncer = syncer; |
| 408 | work->w_data = data; | 415 | work->w_data = data; |
| 409 | work->w_mount = mp; | 416 | work->w_mount = mp; |
| 417 | work->w_completion = completion; | ||
| 410 | spin_lock(&mp->m_sync_lock); | 418 | spin_lock(&mp->m_sync_lock); |
| 411 | list_add_tail(&work->w_list, &mp->m_sync_list); | 419 | list_add_tail(&work->w_list, &mp->m_sync_list); |
| 412 | spin_unlock(&mp->m_sync_lock); | 420 | spin_unlock(&mp->m_sync_lock); |
| @@ -420,49 +428,26 @@ xfs_syncd_queue_work( | |||
| 420 | * heads, looking about for more room... | 428 | * heads, looking about for more room... |
| 421 | */ | 429 | */ |
| 422 | STATIC void | 430 | STATIC void |
| 423 | xfs_flush_inode_work( | 431 | xfs_flush_inodes_work( |
| 424 | struct xfs_mount *mp, | ||
| 425 | void *arg) | ||
| 426 | { | ||
| 427 | struct inode *inode = arg; | ||
| 428 | filemap_flush(inode->i_mapping); | ||
| 429 | iput(inode); | ||
| 430 | } | ||
| 431 | |||
| 432 | void | ||
| 433 | xfs_flush_inode( | ||
| 434 | xfs_inode_t *ip) | ||
| 435 | { | ||
| 436 | struct inode *inode = VFS_I(ip); | ||
| 437 | |||
| 438 | igrab(inode); | ||
| 439 | xfs_syncd_queue_work(ip->i_mount, inode, xfs_flush_inode_work); | ||
| 440 | delay(msecs_to_jiffies(500)); | ||
| 441 | } | ||
| 442 | |||
| 443 | /* | ||
| 444 | * This is the "bigger hammer" version of xfs_flush_inode_work... | ||
| 445 | * (IOW, "If at first you don't succeed, use a Bigger Hammer"). | ||
| 446 | */ | ||
| 447 | STATIC void | ||
| 448 | xfs_flush_device_work( | ||
| 449 | struct xfs_mount *mp, | 432 | struct xfs_mount *mp, |
| 450 | void *arg) | 433 | void *arg) |
| 451 | { | 434 | { |
| 452 | struct inode *inode = arg; | 435 | struct inode *inode = arg; |
| 453 | sync_blockdev(mp->m_super->s_bdev); | 436 | xfs_sync_inodes(mp, SYNC_DELWRI | SYNC_TRYLOCK); |
| 437 | xfs_sync_inodes(mp, SYNC_DELWRI | SYNC_TRYLOCK | SYNC_IOWAIT); | ||
| 454 | iput(inode); | 438 | iput(inode); |
| 455 | } | 439 | } |
| 456 | 440 | ||
| 457 | void | 441 | void |
| 458 | xfs_flush_device( | 442 | xfs_flush_inodes( |
| 459 | xfs_inode_t *ip) | 443 | xfs_inode_t *ip) |
| 460 | { | 444 | { |
| 461 | struct inode *inode = VFS_I(ip); | 445 | struct inode *inode = VFS_I(ip); |
| 446 | DECLARE_COMPLETION_ONSTACK(completion); | ||
| 462 | 447 | ||
| 463 | igrab(inode); | 448 | igrab(inode); |
| 464 | xfs_syncd_queue_work(ip->i_mount, inode, xfs_flush_device_work); | 449 | xfs_syncd_queue_work(ip->i_mount, inode, xfs_flush_inodes_work, &completion); |
| 465 | delay(msecs_to_jiffies(500)); | 450 | wait_for_completion(&completion); |
| 466 | xfs_log_force(ip->i_mount, (xfs_lsn_t)0, XFS_LOG_FORCE|XFS_LOG_SYNC); | 451 | xfs_log_force(ip->i_mount, (xfs_lsn_t)0, XFS_LOG_FORCE|XFS_LOG_SYNC); |
| 467 | } | 452 | } |
| 468 | 453 | ||
| @@ -497,7 +482,7 @@ xfssyncd( | |||
| 497 | { | 482 | { |
| 498 | struct xfs_mount *mp = arg; | 483 | struct xfs_mount *mp = arg; |
| 499 | long timeleft; | 484 | long timeleft; |
| 500 | bhv_vfs_sync_work_t *work, *n; | 485 | xfs_sync_work_t *work, *n; |
| 501 | LIST_HEAD (tmp); | 486 | LIST_HEAD (tmp); |
| 502 | 487 | ||
| 503 | set_freezable(); | 488 | set_freezable(); |
| @@ -532,6 +517,8 @@ xfssyncd( | |||
| 532 | list_del(&work->w_list); | 517 | list_del(&work->w_list); |
| 533 | if (work == &mp->m_sync_work) | 518 | if (work == &mp->m_sync_work) |
| 534 | continue; | 519 | continue; |
| 520 | if (work->w_completion) | ||
| 521 | complete(work->w_completion); | ||
| 535 | kmem_free(work); | 522 | kmem_free(work); |
| 536 | } | 523 | } |
| 537 | } | 524 | } |
| @@ -545,6 +532,7 @@ xfs_syncd_init( | |||
| 545 | { | 532 | { |
| 546 | mp->m_sync_work.w_syncer = xfs_sync_worker; | 533 | mp->m_sync_work.w_syncer = xfs_sync_worker; |
| 547 | mp->m_sync_work.w_mount = mp; | 534 | mp->m_sync_work.w_mount = mp; |
| 535 | mp->m_sync_work.w_completion = NULL; | ||
| 548 | mp->m_sync_task = kthread_run(xfssyncd, mp, "xfssyncd"); | 536 | mp->m_sync_task = kthread_run(xfssyncd, mp, "xfssyncd"); |
| 549 | if (IS_ERR(mp->m_sync_task)) | 537 | if (IS_ERR(mp->m_sync_task)) |
| 550 | return -PTR_ERR(mp->m_sync_task); | 538 | return -PTR_ERR(mp->m_sync_task); |
diff --git a/fs/xfs/linux-2.6/xfs_sync.h b/fs/xfs/linux-2.6/xfs_sync.h index 04f058c848ae..308d5bf6dfbd 100644 --- a/fs/xfs/linux-2.6/xfs_sync.h +++ b/fs/xfs/linux-2.6/xfs_sync.h | |||
| @@ -21,18 +21,20 @@ | |||
| 21 | struct xfs_mount; | 21 | struct xfs_mount; |
| 22 | struct xfs_perag; | 22 | struct xfs_perag; |
| 23 | 23 | ||
| 24 | typedef struct bhv_vfs_sync_work { | 24 | typedef struct xfs_sync_work { |
| 25 | struct list_head w_list; | 25 | struct list_head w_list; |
| 26 | struct xfs_mount *w_mount; | 26 | struct xfs_mount *w_mount; |
| 27 | void *w_data; /* syncer routine argument */ | 27 | void *w_data; /* syncer routine argument */ |
| 28 | void (*w_syncer)(struct xfs_mount *, void *); | 28 | void (*w_syncer)(struct xfs_mount *, void *); |
| 29 | } bhv_vfs_sync_work_t; | 29 | struct completion *w_completion; |
| 30 | } xfs_sync_work_t; | ||
| 30 | 31 | ||
| 31 | #define SYNC_ATTR 0x0001 /* sync attributes */ | 32 | #define SYNC_ATTR 0x0001 /* sync attributes */ |
| 32 | #define SYNC_DELWRI 0x0002 /* look at delayed writes */ | 33 | #define SYNC_DELWRI 0x0002 /* look at delayed writes */ |
| 33 | #define SYNC_WAIT 0x0004 /* wait for i/o to complete */ | 34 | #define SYNC_WAIT 0x0004 /* wait for i/o to complete */ |
| 34 | #define SYNC_BDFLUSH 0x0008 /* BDFLUSH is calling -- don't block */ | 35 | #define SYNC_BDFLUSH 0x0008 /* BDFLUSH is calling -- don't block */ |
| 35 | #define SYNC_IOWAIT 0x0010 /* wait for all I/O to complete */ | 36 | #define SYNC_IOWAIT 0x0010 /* wait for all I/O to complete */ |
| 37 | #define SYNC_TRYLOCK 0x0020 /* only try to lock inodes */ | ||
| 36 | 38 | ||
| 37 | int xfs_syncd_init(struct xfs_mount *mp); | 39 | int xfs_syncd_init(struct xfs_mount *mp); |
| 38 | void xfs_syncd_stop(struct xfs_mount *mp); | 40 | void xfs_syncd_stop(struct xfs_mount *mp); |
| @@ -43,8 +45,7 @@ int xfs_sync_fsdata(struct xfs_mount *mp, int flags); | |||
| 43 | int xfs_quiesce_data(struct xfs_mount *mp); | 45 | int xfs_quiesce_data(struct xfs_mount *mp); |
| 44 | void xfs_quiesce_attr(struct xfs_mount *mp); | 46 | void xfs_quiesce_attr(struct xfs_mount *mp); |
| 45 | 47 | ||
| 46 | void xfs_flush_inode(struct xfs_inode *ip); | 48 | void xfs_flush_inodes(struct xfs_inode *ip); |
| 47 | void xfs_flush_device(struct xfs_inode *ip); | ||
| 48 | 49 | ||
| 49 | int xfs_reclaim_inode(struct xfs_inode *ip, int locked, int sync_mode); | 50 | int xfs_reclaim_inode(struct xfs_inode *ip, int locked, int sync_mode); |
| 50 | int xfs_reclaim_inodes(struct xfs_mount *mp, int noblock, int mode); | 51 | int xfs_reclaim_inodes(struct xfs_mount *mp, int noblock, int mode); |
diff --git a/fs/xfs/xfs_iget.c b/fs/xfs/xfs_iget.c index 478e587087fe..89b81eedce6a 100644 --- a/fs/xfs/xfs_iget.c +++ b/fs/xfs/xfs_iget.c | |||
| @@ -69,15 +69,6 @@ xfs_inode_alloc( | |||
| 69 | ASSERT(!spin_is_locked(&ip->i_flags_lock)); | 69 | ASSERT(!spin_is_locked(&ip->i_flags_lock)); |
| 70 | ASSERT(completion_done(&ip->i_flush)); | 70 | ASSERT(completion_done(&ip->i_flush)); |
| 71 | 71 | ||
| 72 | /* | ||
| 73 | * initialise the VFS inode here to get failures | ||
| 74 | * out of the way early. | ||
| 75 | */ | ||
| 76 | if (!inode_init_always(mp->m_super, VFS_I(ip))) { | ||
| 77 | kmem_zone_free(xfs_inode_zone, ip); | ||
| 78 | return NULL; | ||
| 79 | } | ||
| 80 | |||
| 81 | /* initialise the xfs inode */ | 72 | /* initialise the xfs inode */ |
| 82 | ip->i_ino = ino; | 73 | ip->i_ino = ino; |
| 83 | ip->i_mount = mp; | 74 | ip->i_mount = mp; |
| @@ -113,6 +104,20 @@ xfs_inode_alloc( | |||
| 113 | #ifdef XFS_DIR2_TRACE | 104 | #ifdef XFS_DIR2_TRACE |
| 114 | ip->i_dir_trace = ktrace_alloc(XFS_DIR2_KTRACE_SIZE, KM_NOFS); | 105 | ip->i_dir_trace = ktrace_alloc(XFS_DIR2_KTRACE_SIZE, KM_NOFS); |
| 115 | #endif | 106 | #endif |
| 107 | /* | ||
| 108 | * Now initialise the VFS inode. We do this after the xfs_inode | ||
| 109 | * initialisation as internal failures will result in ->destroy_inode | ||
| 110 | * being called and that will pass down through the reclaim path and | ||
| 111 | * free the XFS inode. This path requires the XFS inode to already be | ||
| 112 | * initialised. Hence if this call fails, the xfs_inode has already | ||
| 113 | * been freed and we should not reference it at all in the error | ||
| 114 | * handling. | ||
| 115 | */ | ||
| 116 | if (!inode_init_always(mp->m_super, VFS_I(ip))) | ||
| 117 | return NULL; | ||
| 118 | |||
| 119 | /* prevent anyone from using this yet */ | ||
| 120 | VFS_I(ip)->i_state = I_NEW|I_LOCK; | ||
| 116 | 121 | ||
| 117 | return ip; | 122 | return ip; |
| 118 | } | 123 | } |
diff --git a/fs/xfs/xfs_iomap.c b/fs/xfs/xfs_iomap.c index 08ce72316bfe..5aaa2d7ec155 100644 --- a/fs/xfs/xfs_iomap.c +++ b/fs/xfs/xfs_iomap.c | |||
| @@ -338,38 +338,6 @@ xfs_iomap_eof_align_last_fsb( | |||
| 338 | } | 338 | } |
| 339 | 339 | ||
| 340 | STATIC int | 340 | STATIC int |
| 341 | xfs_flush_space( | ||
| 342 | xfs_inode_t *ip, | ||
| 343 | int *fsynced, | ||
| 344 | int *ioflags) | ||
| 345 | { | ||
| 346 | switch (*fsynced) { | ||
| 347 | case 0: | ||
| 348 | if (ip->i_delayed_blks) { | ||
| 349 | xfs_iunlock(ip, XFS_ILOCK_EXCL); | ||
| 350 | xfs_flush_inode(ip); | ||
| 351 | xfs_ilock(ip, XFS_ILOCK_EXCL); | ||
| 352 | *fsynced = 1; | ||
| 353 | } else { | ||
| 354 | *ioflags |= BMAPI_SYNC; | ||
| 355 | *fsynced = 2; | ||
| 356 | } | ||
| 357 | return 0; | ||
| 358 | case 1: | ||
| 359 | *fsynced = 2; | ||
| 360 | *ioflags |= BMAPI_SYNC; | ||
| 361 | return 0; | ||
| 362 | case 2: | ||
| 363 | xfs_iunlock(ip, XFS_ILOCK_EXCL); | ||
| 364 | xfs_flush_device(ip); | ||
| 365 | xfs_ilock(ip, XFS_ILOCK_EXCL); | ||
| 366 | *fsynced = 3; | ||
| 367 | return 0; | ||
| 368 | } | ||
| 369 | return 1; | ||
| 370 | } | ||
| 371 | |||
| 372 | STATIC int | ||
| 373 | xfs_cmn_err_fsblock_zero( | 341 | xfs_cmn_err_fsblock_zero( |
| 374 | xfs_inode_t *ip, | 342 | xfs_inode_t *ip, |
| 375 | xfs_bmbt_irec_t *imap) | 343 | xfs_bmbt_irec_t *imap) |
| @@ -538,15 +506,9 @@ error_out: | |||
| 538 | } | 506 | } |
| 539 | 507 | ||
| 540 | /* | 508 | /* |
| 541 | * If the caller is doing a write at the end of the file, | 509 | * If the caller is doing a write at the end of the file, then extend the |
| 542 | * then extend the allocation out to the file system's write | 510 | * allocation out to the file system's write iosize. We clean up any extra |
| 543 | * iosize. We clean up any extra space left over when the | 511 | * space left over when the file is closed in xfs_inactive(). |
| 544 | * file is closed in xfs_inactive(). | ||
| 545 | * | ||
| 546 | * For sync writes, we are flushing delayed allocate space to | ||
| 547 | * try to make additional space available for allocation near | ||
| 548 | * the filesystem full boundary - preallocation hurts in that | ||
| 549 | * situation, of course. | ||
| 550 | */ | 512 | */ |
| 551 | STATIC int | 513 | STATIC int |
| 552 | xfs_iomap_eof_want_preallocate( | 514 | xfs_iomap_eof_want_preallocate( |
| @@ -565,7 +527,7 @@ xfs_iomap_eof_want_preallocate( | |||
| 565 | int n, error, imaps; | 527 | int n, error, imaps; |
| 566 | 528 | ||
| 567 | *prealloc = 0; | 529 | *prealloc = 0; |
| 568 | if ((ioflag & BMAPI_SYNC) || (offset + count) <= ip->i_size) | 530 | if ((offset + count) <= ip->i_size) |
| 569 | return 0; | 531 | return 0; |
| 570 | 532 | ||
| 571 | /* | 533 | /* |
| @@ -611,7 +573,7 @@ xfs_iomap_write_delay( | |||
| 611 | xfs_extlen_t extsz; | 573 | xfs_extlen_t extsz; |
| 612 | int nimaps; | 574 | int nimaps; |
| 613 | xfs_bmbt_irec_t imap[XFS_WRITE_IMAPS]; | 575 | xfs_bmbt_irec_t imap[XFS_WRITE_IMAPS]; |
| 614 | int prealloc, fsynced = 0; | 576 | int prealloc, flushed = 0; |
| 615 | int error; | 577 | int error; |
| 616 | 578 | ||
| 617 | ASSERT(xfs_isilocked(ip, XFS_ILOCK_EXCL)); | 579 | ASSERT(xfs_isilocked(ip, XFS_ILOCK_EXCL)); |
| @@ -627,12 +589,12 @@ xfs_iomap_write_delay( | |||
| 627 | extsz = xfs_get_extsz_hint(ip); | 589 | extsz = xfs_get_extsz_hint(ip); |
| 628 | offset_fsb = XFS_B_TO_FSBT(mp, offset); | 590 | offset_fsb = XFS_B_TO_FSBT(mp, offset); |
| 629 | 591 | ||
| 630 | retry: | ||
| 631 | error = xfs_iomap_eof_want_preallocate(mp, ip, offset, count, | 592 | error = xfs_iomap_eof_want_preallocate(mp, ip, offset, count, |
| 632 | ioflag, imap, XFS_WRITE_IMAPS, &prealloc); | 593 | ioflag, imap, XFS_WRITE_IMAPS, &prealloc); |
| 633 | if (error) | 594 | if (error) |
| 634 | return error; | 595 | return error; |
| 635 | 596 | ||
| 597 | retry: | ||
| 636 | if (prealloc) { | 598 | if (prealloc) { |
| 637 | aligned_offset = XFS_WRITEIO_ALIGN(mp, (offset + count - 1)); | 599 | aligned_offset = XFS_WRITEIO_ALIGN(mp, (offset + count - 1)); |
| 638 | ioalign = XFS_B_TO_FSBT(mp, aligned_offset); | 600 | ioalign = XFS_B_TO_FSBT(mp, aligned_offset); |
| @@ -659,15 +621,22 @@ retry: | |||
| 659 | 621 | ||
| 660 | /* | 622 | /* |
| 661 | * If bmapi returned us nothing, and if we didn't get back EDQUOT, | 623 | * If bmapi returned us nothing, and if we didn't get back EDQUOT, |
| 662 | * then we must have run out of space - flush delalloc, and retry.. | 624 | * then we must have run out of space - flush all other inodes with |
| 625 | * delalloc blocks and retry without EOF preallocation. | ||
| 663 | */ | 626 | */ |
| 664 | if (nimaps == 0) { | 627 | if (nimaps == 0) { |
| 665 | xfs_iomap_enter_trace(XFS_IOMAP_WRITE_NOSPACE, | 628 | xfs_iomap_enter_trace(XFS_IOMAP_WRITE_NOSPACE, |
| 666 | ip, offset, count); | 629 | ip, offset, count); |
| 667 | if (xfs_flush_space(ip, &fsynced, &ioflag)) | 630 | if (flushed) |
| 668 | return XFS_ERROR(ENOSPC); | 631 | return XFS_ERROR(ENOSPC); |
| 669 | 632 | ||
| 633 | xfs_iunlock(ip, XFS_ILOCK_EXCL); | ||
| 634 | xfs_flush_inodes(ip); | ||
| 635 | xfs_ilock(ip, XFS_ILOCK_EXCL); | ||
| 636 | |||
| 637 | flushed = 1; | ||
| 670 | error = 0; | 638 | error = 0; |
| 639 | prealloc = 0; | ||
| 671 | goto retry; | 640 | goto retry; |
| 672 | } | 641 | } |
| 673 | 642 | ||
diff --git a/fs/xfs/xfs_iomap.h b/fs/xfs/xfs_iomap.h index a1cc1322fc0f..fdcf7b82747f 100644 --- a/fs/xfs/xfs_iomap.h +++ b/fs/xfs/xfs_iomap.h | |||
| @@ -40,8 +40,7 @@ typedef enum { | |||
| 40 | BMAPI_IGNSTATE = (1 << 4), /* ignore unwritten state on read */ | 40 | BMAPI_IGNSTATE = (1 << 4), /* ignore unwritten state on read */ |
| 41 | BMAPI_DIRECT = (1 << 5), /* direct instead of buffered write */ | 41 | BMAPI_DIRECT = (1 << 5), /* direct instead of buffered write */ |
| 42 | BMAPI_MMAP = (1 << 6), /* allocate for mmap write */ | 42 | BMAPI_MMAP = (1 << 6), /* allocate for mmap write */ |
| 43 | BMAPI_SYNC = (1 << 7), /* sync write to flush delalloc space */ | 43 | BMAPI_TRYLOCK = (1 << 7), /* non-blocking request */ |
| 44 | BMAPI_TRYLOCK = (1 << 8), /* non-blocking request */ | ||
| 45 | } bmapi_flags_t; | 44 | } bmapi_flags_t; |
| 46 | 45 | ||
| 47 | 46 | ||
diff --git a/fs/xfs/xfs_log.c b/fs/xfs/xfs_log.c index f76c6d7cea21..3750f04ede0b 100644 --- a/fs/xfs/xfs_log.c +++ b/fs/xfs/xfs_log.c | |||
| @@ -562,9 +562,8 @@ xfs_log_mount( | |||
| 562 | } | 562 | } |
| 563 | 563 | ||
| 564 | mp->m_log = xlog_alloc_log(mp, log_target, blk_offset, num_bblks); | 564 | mp->m_log = xlog_alloc_log(mp, log_target, blk_offset, num_bblks); |
| 565 | if (!mp->m_log) { | 565 | if (IS_ERR(mp->m_log)) { |
| 566 | cmn_err(CE_WARN, "XFS: Log allocation failed: No memory!"); | 566 | error = -PTR_ERR(mp->m_log); |
| 567 | error = ENOMEM; | ||
| 568 | goto out; | 567 | goto out; |
| 569 | } | 568 | } |
| 570 | 569 | ||
| @@ -1180,10 +1179,13 @@ xlog_alloc_log(xfs_mount_t *mp, | |||
| 1180 | xfs_buf_t *bp; | 1179 | xfs_buf_t *bp; |
| 1181 | int i; | 1180 | int i; |
| 1182 | int iclogsize; | 1181 | int iclogsize; |
| 1182 | int error = ENOMEM; | ||
| 1183 | 1183 | ||
| 1184 | log = kmem_zalloc(sizeof(xlog_t), KM_MAYFAIL); | 1184 | log = kmem_zalloc(sizeof(xlog_t), KM_MAYFAIL); |
| 1185 | if (!log) | 1185 | if (!log) { |
| 1186 | return NULL; | 1186 | xlog_warn("XFS: Log allocation failed: No memory!"); |
| 1187 | goto out; | ||
| 1188 | } | ||
| 1187 | 1189 | ||
| 1188 | log->l_mp = mp; | 1190 | log->l_mp = mp; |
| 1189 | log->l_targ = log_target; | 1191 | log->l_targ = log_target; |
| @@ -1201,19 +1203,35 @@ xlog_alloc_log(xfs_mount_t *mp, | |||
| 1201 | log->l_grant_reserve_cycle = 1; | 1203 | log->l_grant_reserve_cycle = 1; |
| 1202 | log->l_grant_write_cycle = 1; | 1204 | log->l_grant_write_cycle = 1; |
| 1203 | 1205 | ||
| 1206 | error = EFSCORRUPTED; | ||
| 1204 | if (xfs_sb_version_hassector(&mp->m_sb)) { | 1207 | if (xfs_sb_version_hassector(&mp->m_sb)) { |
| 1205 | log->l_sectbb_log = mp->m_sb.sb_logsectlog - BBSHIFT; | 1208 | log->l_sectbb_log = mp->m_sb.sb_logsectlog - BBSHIFT; |
| 1206 | ASSERT(log->l_sectbb_log <= mp->m_sectbb_log); | 1209 | if (log->l_sectbb_log < 0 || |
| 1210 | log->l_sectbb_log > mp->m_sectbb_log) { | ||
| 1211 | xlog_warn("XFS: Log sector size (0x%x) out of range.", | ||
| 1212 | log->l_sectbb_log); | ||
| 1213 | goto out_free_log; | ||
| 1214 | } | ||
| 1215 | |||
| 1207 | /* for larger sector sizes, must have v2 or external log */ | 1216 | /* for larger sector sizes, must have v2 or external log */ |
| 1208 | ASSERT(log->l_sectbb_log == 0 || | 1217 | if (log->l_sectbb_log != 0 && |
| 1209 | log->l_logBBstart == 0 || | 1218 | (log->l_logBBstart != 0 && |
| 1210 | xfs_sb_version_haslogv2(&mp->m_sb)); | 1219 | !xfs_sb_version_haslogv2(&mp->m_sb))) { |
| 1211 | ASSERT(mp->m_sb.sb_logsectlog >= BBSHIFT); | 1220 | xlog_warn("XFS: log sector size (0x%x) invalid " |
| 1221 | "for configuration.", log->l_sectbb_log); | ||
| 1222 | goto out_free_log; | ||
| 1223 | } | ||
| 1224 | if (mp->m_sb.sb_logsectlog < BBSHIFT) { | ||
| 1225 | xlog_warn("XFS: Log sector log (0x%x) too small.", | ||
| 1226 | mp->m_sb.sb_logsectlog); | ||
| 1227 | goto out_free_log; | ||
| 1228 | } | ||
| 1212 | } | 1229 | } |
| 1213 | log->l_sectbb_mask = (1 << log->l_sectbb_log) - 1; | 1230 | log->l_sectbb_mask = (1 << log->l_sectbb_log) - 1; |
| 1214 | 1231 | ||
| 1215 | xlog_get_iclog_buffer_size(mp, log); | 1232 | xlog_get_iclog_buffer_size(mp, log); |
| 1216 | 1233 | ||
| 1234 | error = ENOMEM; | ||
| 1217 | bp = xfs_buf_get_empty(log->l_iclog_size, mp->m_logdev_targp); | 1235 | bp = xfs_buf_get_empty(log->l_iclog_size, mp->m_logdev_targp); |
| 1218 | if (!bp) | 1236 | if (!bp) |
| 1219 | goto out_free_log; | 1237 | goto out_free_log; |
| @@ -1313,7 +1331,8 @@ out_free_iclog: | |||
| 1313 | xfs_buf_free(log->l_xbuf); | 1331 | xfs_buf_free(log->l_xbuf); |
| 1314 | out_free_log: | 1332 | out_free_log: |
| 1315 | kmem_free(log); | 1333 | kmem_free(log); |
| 1316 | return NULL; | 1334 | out: |
| 1335 | return ERR_PTR(-error); | ||
| 1317 | } /* xlog_alloc_log */ | 1336 | } /* xlog_alloc_log */ |
| 1318 | 1337 | ||
| 1319 | 1338 | ||
| @@ -2541,18 +2560,19 @@ redo: | |||
| 2541 | xlog_ins_ticketq(&log->l_reserve_headq, tic); | 2560 | xlog_ins_ticketq(&log->l_reserve_headq, tic); |
| 2542 | xlog_trace_loggrant(log, tic, | 2561 | xlog_trace_loggrant(log, tic, |
| 2543 | "xlog_grant_log_space: sleep 2"); | 2562 | "xlog_grant_log_space: sleep 2"); |
| 2563 | spin_unlock(&log->l_grant_lock); | ||
| 2564 | xlog_grant_push_ail(log->l_mp, need_bytes); | ||
| 2565 | spin_lock(&log->l_grant_lock); | ||
| 2566 | |||
| 2544 | XFS_STATS_INC(xs_sleep_logspace); | 2567 | XFS_STATS_INC(xs_sleep_logspace); |
| 2545 | sv_wait(&tic->t_wait, PINOD|PLTWAIT, &log->l_grant_lock, s); | 2568 | sv_wait(&tic->t_wait, PINOD|PLTWAIT, &log->l_grant_lock, s); |
| 2546 | 2569 | ||
| 2547 | if (XLOG_FORCED_SHUTDOWN(log)) { | 2570 | spin_lock(&log->l_grant_lock); |
| 2548 | spin_lock(&log->l_grant_lock); | 2571 | if (XLOG_FORCED_SHUTDOWN(log)) |
| 2549 | goto error_return; | 2572 | goto error_return; |
| 2550 | } | ||
| 2551 | 2573 | ||
| 2552 | xlog_trace_loggrant(log, tic, | 2574 | xlog_trace_loggrant(log, tic, |
| 2553 | "xlog_grant_log_space: wake 2"); | 2575 | "xlog_grant_log_space: wake 2"); |
| 2554 | xlog_grant_push_ail(log->l_mp, need_bytes); | ||
| 2555 | spin_lock(&log->l_grant_lock); | ||
| 2556 | goto redo; | 2576 | goto redo; |
| 2557 | } else if (tic->t_flags & XLOG_TIC_IN_Q) | 2577 | } else if (tic->t_flags & XLOG_TIC_IN_Q) |
| 2558 | xlog_del_ticketq(&log->l_reserve_headq, tic); | 2578 | xlog_del_ticketq(&log->l_reserve_headq, tic); |
| @@ -2631,7 +2651,7 @@ xlog_regrant_write_log_space(xlog_t *log, | |||
| 2631 | * for more free space, otherwise try to get some space for | 2651 | * for more free space, otherwise try to get some space for |
| 2632 | * this transaction. | 2652 | * this transaction. |
| 2633 | */ | 2653 | */ |
| 2634 | 2654 | need_bytes = tic->t_unit_res; | |
| 2635 | if ((ntic = log->l_write_headq)) { | 2655 | if ((ntic = log->l_write_headq)) { |
| 2636 | free_bytes = xlog_space_left(log, log->l_grant_write_cycle, | 2656 | free_bytes = xlog_space_left(log, log->l_grant_write_cycle, |
| 2637 | log->l_grant_write_bytes); | 2657 | log->l_grant_write_bytes); |
| @@ -2651,26 +2671,25 @@ xlog_regrant_write_log_space(xlog_t *log, | |||
| 2651 | 2671 | ||
| 2652 | xlog_trace_loggrant(log, tic, | 2672 | xlog_trace_loggrant(log, tic, |
| 2653 | "xlog_regrant_write_log_space: sleep 1"); | 2673 | "xlog_regrant_write_log_space: sleep 1"); |
| 2674 | spin_unlock(&log->l_grant_lock); | ||
| 2675 | xlog_grant_push_ail(log->l_mp, need_bytes); | ||
| 2676 | spin_lock(&log->l_grant_lock); | ||
| 2677 | |||
| 2654 | XFS_STATS_INC(xs_sleep_logspace); | 2678 | XFS_STATS_INC(xs_sleep_logspace); |
| 2655 | sv_wait(&tic->t_wait, PINOD|PLTWAIT, | 2679 | sv_wait(&tic->t_wait, PINOD|PLTWAIT, |
| 2656 | &log->l_grant_lock, s); | 2680 | &log->l_grant_lock, s); |
| 2657 | 2681 | ||
| 2658 | /* If we're shutting down, this tic is already | 2682 | /* If we're shutting down, this tic is already |
| 2659 | * off the queue */ | 2683 | * off the queue */ |
| 2660 | if (XLOG_FORCED_SHUTDOWN(log)) { | 2684 | spin_lock(&log->l_grant_lock); |
| 2661 | spin_lock(&log->l_grant_lock); | 2685 | if (XLOG_FORCED_SHUTDOWN(log)) |
| 2662 | goto error_return; | 2686 | goto error_return; |
| 2663 | } | ||
| 2664 | 2687 | ||
| 2665 | xlog_trace_loggrant(log, tic, | 2688 | xlog_trace_loggrant(log, tic, |
| 2666 | "xlog_regrant_write_log_space: wake 1"); | 2689 | "xlog_regrant_write_log_space: wake 1"); |
| 2667 | xlog_grant_push_ail(log->l_mp, tic->t_unit_res); | ||
| 2668 | spin_lock(&log->l_grant_lock); | ||
| 2669 | } | 2690 | } |
| 2670 | } | 2691 | } |
| 2671 | 2692 | ||
| 2672 | need_bytes = tic->t_unit_res; | ||
| 2673 | |||
| 2674 | redo: | 2693 | redo: |
| 2675 | if (XLOG_FORCED_SHUTDOWN(log)) | 2694 | if (XLOG_FORCED_SHUTDOWN(log)) |
| 2676 | goto error_return; | 2695 | goto error_return; |
| @@ -2680,19 +2699,20 @@ redo: | |||
| 2680 | if (free_bytes < need_bytes) { | 2699 | if (free_bytes < need_bytes) { |
| 2681 | if ((tic->t_flags & XLOG_TIC_IN_Q) == 0) | 2700 | if ((tic->t_flags & XLOG_TIC_IN_Q) == 0) |
| 2682 | xlog_ins_ticketq(&log->l_write_headq, tic); | 2701 | xlog_ins_ticketq(&log->l_write_headq, tic); |
| 2702 | spin_unlock(&log->l_grant_lock); | ||
| 2703 | xlog_grant_push_ail(log->l_mp, need_bytes); | ||
| 2704 | spin_lock(&log->l_grant_lock); | ||
| 2705 | |||
| 2683 | XFS_STATS_INC(xs_sleep_logspace); | 2706 | XFS_STATS_INC(xs_sleep_logspace); |
| 2684 | sv_wait(&tic->t_wait, PINOD|PLTWAIT, &log->l_grant_lock, s); | 2707 | sv_wait(&tic->t_wait, PINOD|PLTWAIT, &log->l_grant_lock, s); |
| 2685 | 2708 | ||
| 2686 | /* If we're shutting down, this tic is already off the queue */ | 2709 | /* If we're shutting down, this tic is already off the queue */ |
| 2687 | if (XLOG_FORCED_SHUTDOWN(log)) { | 2710 | spin_lock(&log->l_grant_lock); |
| 2688 | spin_lock(&log->l_grant_lock); | 2711 | if (XLOG_FORCED_SHUTDOWN(log)) |
| 2689 | goto error_return; | 2712 | goto error_return; |
| 2690 | } | ||
| 2691 | 2713 | ||
| 2692 | xlog_trace_loggrant(log, tic, | 2714 | xlog_trace_loggrant(log, tic, |
| 2693 | "xlog_regrant_write_log_space: wake 2"); | 2715 | "xlog_regrant_write_log_space: wake 2"); |
| 2694 | xlog_grant_push_ail(log->l_mp, need_bytes); | ||
| 2695 | spin_lock(&log->l_grant_lock); | ||
| 2696 | goto redo; | 2716 | goto redo; |
| 2697 | } else if (tic->t_flags & XLOG_TIC_IN_Q) | 2717 | } else if (tic->t_flags & XLOG_TIC_IN_Q) |
| 2698 | xlog_del_ticketq(&log->l_write_headq, tic); | 2718 | xlog_del_ticketq(&log->l_write_headq, tic); |
diff --git a/fs/xfs/xfs_mount.h b/fs/xfs/xfs_mount.h index 7af44adffc8f..d6a64392f983 100644 --- a/fs/xfs/xfs_mount.h +++ b/fs/xfs/xfs_mount.h | |||
| @@ -313,7 +313,7 @@ typedef struct xfs_mount { | |||
| 313 | #endif | 313 | #endif |
| 314 | struct xfs_mru_cache *m_filestream; /* per-mount filestream data */ | 314 | struct xfs_mru_cache *m_filestream; /* per-mount filestream data */ |
| 315 | struct task_struct *m_sync_task; /* generalised sync thread */ | 315 | struct task_struct *m_sync_task; /* generalised sync thread */ |
| 316 | bhv_vfs_sync_work_t m_sync_work; /* work item for VFS_SYNC */ | 316 | xfs_sync_work_t m_sync_work; /* work item for VFS_SYNC */ |
| 317 | struct list_head m_sync_list; /* sync thread work item list */ | 317 | struct list_head m_sync_list; /* sync thread work item list */ |
| 318 | spinlock_t m_sync_lock; /* work item list lock */ | 318 | spinlock_t m_sync_lock; /* work item list lock */ |
| 319 | int m_sync_seq; /* sync thread generation no. */ | 319 | int m_sync_seq; /* sync thread generation no. */ |
diff --git a/fs/xfs/xfs_vnodeops.c b/fs/xfs/xfs_vnodeops.c index 7394c7af5de5..19cf90a9c762 100644 --- a/fs/xfs/xfs_vnodeops.c +++ b/fs/xfs/xfs_vnodeops.c | |||
| @@ -1457,6 +1457,13 @@ xfs_create( | |||
| 1457 | error = xfs_trans_reserve(tp, resblks, log_res, 0, | 1457 | error = xfs_trans_reserve(tp, resblks, log_res, 0, |
| 1458 | XFS_TRANS_PERM_LOG_RES, log_count); | 1458 | XFS_TRANS_PERM_LOG_RES, log_count); |
| 1459 | if (error == ENOSPC) { | 1459 | if (error == ENOSPC) { |
| 1460 | /* flush outstanding delalloc blocks and retry */ | ||
| 1461 | xfs_flush_inodes(dp); | ||
| 1462 | error = xfs_trans_reserve(tp, resblks, XFS_CREATE_LOG_RES(mp), 0, | ||
| 1463 | XFS_TRANS_PERM_LOG_RES, XFS_CREATE_LOG_COUNT); | ||
| 1464 | } | ||
| 1465 | if (error == ENOSPC) { | ||
| 1466 | /* No space at all so try a "no-allocation" reservation */ | ||
| 1460 | resblks = 0; | 1467 | resblks = 0; |
| 1461 | error = xfs_trans_reserve(tp, 0, log_res, 0, | 1468 | error = xfs_trans_reserve(tp, 0, log_res, 0, |
| 1462 | XFS_TRANS_PERM_LOG_RES, log_count); | 1469 | XFS_TRANS_PERM_LOG_RES, log_count); |
