]>
Commit | Line | Data |
---|---|---|
2cb7cef9 BS |
1 | Subject: Re-dirty pages on ENOSPC when converting delayed allocations |
2 | From: Lachlan McIlroy <lachlan@sgi.com> | |
3 | References: 433112 - LTC48749 | |
4 | ||
5 | http://oss.sgi.com/archives/xfs/2008-10/msg00058.html | |
6 | ||
7 | If we get an error in xfs_page_state_convert() - and it's not EAGAIN - then | |
8 | we throw away the dirty page without converting the delayed allocation. This | |
9 | leaves delayed allocations that can never be removed and confuses code that | |
10 | expects a flush of the file to clear them. We need to re-dirty the page on | |
11 | error so we can try again later or report that the flush failed. | |
12 | ||
13 | ||
14 | This change is needed to handle the condition where we are at ENOSPC and we | |
15 | exhaust the reserved block pool (because many transactions are executing | |
16 | concurrently) and calls to xfs_trans_reserve() start failing with ENOSPC | |
17 | errors. | |
18 | ||
19 | ||
20 | Version 2 wont return EAGAIN from xfs_vm_writepage() and also converts an | |
21 | ENOSPC error to an EAGAIN for asynchronous writeback to avoid setting an | |
22 | error in the inode mapping when we don't need to. | |
23 | ||
24 | Signed-off-by: Olaf Hering <olh@suse.de> | |
25 | --- | |
26 | fs/xfs/linux-2.6/xfs_aops.c | 21 ++++----------------- | |
27 | 1 file changed, 4 insertions(+), 17 deletions(-) | |
28 | ||
29 | --- a/fs/xfs/linux-2.6/xfs_aops.c | |
30 | +++ b/fs/xfs/linux-2.6/xfs_aops.c | |
31 | @@ -1147,16 +1147,6 @@ error: | |
32 | if (iohead) | |
33 | xfs_cancel_ioend(iohead); | |
34 | ||
35 | - /* | |
36 | - * If it's delalloc and we have nowhere to put it, | |
37 | - * throw it away, unless the lower layers told | |
38 | - * us to try again. | |
39 | - */ | |
40 | - if (err != -EAGAIN) { | |
41 | - if (!unmapped) | |
42 | - block_invalidatepage(page, 0); | |
43 | - ClearPageUptodate(page); | |
44 | - } | |
45 | return err; | |
46 | } | |
47 | ||
48 | @@ -1185,7 +1175,7 @@ xfs_vm_writepage( | |
49 | struct page *page, | |
50 | struct writeback_control *wbc) | |
51 | { | |
52 | - int error; | |
53 | + int error = 0; | |
54 | int need_trans; | |
55 | int delalloc, unmapped, unwritten; | |
56 | struct inode *inode = page->mapping->host; | |
57 | @@ -1231,19 +1221,16 @@ xfs_vm_writepage( | |
58 | * to real space and flush out to disk. | |
59 | */ | |
60 | error = xfs_page_state_convert(inode, page, wbc, 1, unmapped); | |
61 | - if (error == -EAGAIN) | |
62 | - goto out_fail; | |
63 | if (unlikely(error < 0)) | |
64 | - goto out_unlock; | |
65 | + goto out_fail; | |
66 | ||
67 | return 0; | |
68 | ||
69 | out_fail: | |
70 | redirty_page_for_writepage(wbc, page); | |
71 | unlock_page(page); | |
72 | - return 0; | |
73 | -out_unlock: | |
74 | - unlock_page(page); | |
75 | + if (error == -EAGAIN) | |
76 | + error = 0; | |
77 | return error; | |
78 | } | |
79 |