]>
Commit | Line | Data |
---|---|---|
00e5a55c BS |
1 | From: ffilz@us.ibm.com |
2 | Subject: Revert "NFS: Allow redirtying of a completed unstable write." | |
3 | Patch-mainline: REVERT patch from 2.6.27 | |
4 | References: 442267 | |
5 | ||
6 | mainline commit e468bae97d243fe0e1515abaa1f7d0edf1476ad0 | |
7 | introduces a BUG() that is apprently fairly easy to trigger. | |
8 | As it is just making a minor performance enhancement, it is best to | |
9 | revert the patch until the issue is better understood. | |
10 | ||
11 | Acked-by: NeilBrown <neilb@suse.de> | |
12 | Signed-off-by: Neil Brown <neilb@suse.de> | |
13 | ||
14 | --- | |
15 | fs/nfs/write.c | 65 ++++++++++++++++++++++++++++----------------------------- | |
16 | 1 file changed, 33 insertions(+), 32 deletions(-) | |
17 | ||
18 | --- a/fs/nfs/write.c | |
19 | +++ b/fs/nfs/write.c | |
20 | @@ -284,9 +284,12 @@ static int nfs_page_async_flush(struct n | |
21 | return ret; | |
22 | spin_lock(&inode->i_lock); | |
23 | } | |
24 | - if (test_bit(PG_CLEAN, &req->wb_flags)) { | |
25 | + if (test_bit(PG_NEED_COMMIT, &req->wb_flags)) { | |
26 | + /* This request is marked for commit */ | |
27 | spin_unlock(&inode->i_lock); | |
28 | - BUG(); | |
29 | + nfs_clear_page_tag_locked(req); | |
30 | + nfs_pageio_complete(pgio); | |
31 | + return 0; | |
32 | } | |
33 | if (nfs_set_page_writeback(page) != 0) { | |
34 | spin_unlock(&inode->i_lock); | |
35 | @@ -460,6 +463,19 @@ nfs_mark_request_dirty(struct nfs_page * | |
36 | __set_page_dirty_nobuffers(req->wb_page); | |
37 | } | |
38 | ||
39 | +/* | |
40 | + * Check if a request is dirty | |
41 | + */ | |
42 | +static inline int | |
43 | +nfs_dirty_request(struct nfs_page *req) | |
44 | +{ | |
45 | + struct page *page = req->wb_page; | |
46 | + | |
47 | + if (page == NULL || test_bit(PG_NEED_COMMIT, &req->wb_flags)) | |
48 | + return 0; | |
49 | + return !PageWriteback(page); | |
50 | +} | |
51 | + | |
52 | #if defined(CONFIG_NFS_V3) || defined(CONFIG_NFS_V4) | |
53 | /* | |
54 | * Add a request to the inode's commit list. | |
55 | @@ -472,7 +488,7 @@ nfs_mark_request_commit(struct nfs_page | |
56 | ||
57 | spin_lock(&inode->i_lock); | |
58 | nfsi->ncommit++; | |
59 | - set_bit(PG_CLEAN, &(req)->wb_flags); | |
60 | + set_bit(PG_NEED_COMMIT, &(req)->wb_flags); | |
61 | radix_tree_tag_set(&nfsi->nfs_page_tree, | |
62 | req->wb_index, | |
63 | NFS_PAGE_TAG_COMMIT); | |
64 | @@ -483,19 +499,6 @@ nfs_mark_request_commit(struct nfs_page | |
65 | __mark_inode_dirty(inode, I_DIRTY_DATASYNC); | |
66 | } | |
67 | ||
68 | -static int | |
69 | -nfs_clear_request_commit(struct nfs_page *req) | |
70 | -{ | |
71 | - struct page *page = req->wb_page; | |
72 | - | |
73 | - if (test_and_clear_bit(PG_CLEAN, &(req)->wb_flags)) { | |
74 | - dec_zone_page_state(page, NR_UNSTABLE_NFS); | |
75 | - dec_bdi_stat(page_file_mapping(page)->backing_dev_info, BDI_RECLAIMABLE); | |
76 | - return 1; | |
77 | - } | |
78 | - return 0; | |
79 | -} | |
80 | - | |
81 | static inline | |
82 | int nfs_write_need_commit(struct nfs_write_data *data) | |
83 | { | |
84 | @@ -505,7 +508,7 @@ int nfs_write_need_commit(struct nfs_wri | |
85 | static inline | |
86 | int nfs_reschedule_unstable_write(struct nfs_page *req) | |
87 | { | |
88 | - if (test_and_clear_bit(PG_NEED_COMMIT, &req->wb_flags)) { | |
89 | + if (test_bit(PG_NEED_COMMIT, &req->wb_flags)) { | |
90 | nfs_mark_request_commit(req); | |
91 | return 1; | |
92 | } | |
93 | @@ -521,12 +524,6 @@ nfs_mark_request_commit(struct nfs_page | |
94 | { | |
95 | } | |
96 | ||
97 | -static inline int | |
98 | -nfs_clear_request_commit(struct nfs_page *req) | |
99 | -{ | |
100 | - return 0; | |
101 | -} | |
102 | - | |
103 | static inline | |
104 | int nfs_write_need_commit(struct nfs_write_data *data) | |
105 | { | |
106 | @@ -584,8 +581,11 @@ static void nfs_cancel_commit_list(struc | |
107 | ||
108 | while(!list_empty(head)) { | |
109 | req = nfs_list_entry(head->next); | |
110 | + dec_zone_page_state(req->wb_page, NR_UNSTABLE_NFS); | |
111 | + dec_bdi_stat(req->wb_page->mapping->backing_dev_info, | |
112 | + BDI_RECLAIMABLE); | |
113 | nfs_list_remove_request(req); | |
114 | - nfs_clear_request_commit(req); | |
115 | + clear_bit(PG_NEED_COMMIT, &(req)->wb_flags); | |
116 | nfs_inode_remove_request(req); | |
117 | nfs_unlock_request(req); | |
118 | } | |
119 | @@ -657,7 +657,8 @@ static struct nfs_page *nfs_try_to_updat | |
120 | * Note: nfs_flush_incompatible() will already | |
121 | * have flushed out requests having wrong owners. | |
122 | */ | |
123 | - if (offset > rqend | |
124 | + if (!nfs_dirty_request(req) | |
125 | + || offset > rqend | |
126 | || end < req->wb_offset) | |
127 | goto out_flushme; | |
128 | ||
129 | @@ -673,10 +674,6 @@ static struct nfs_page *nfs_try_to_updat | |
130 | spin_lock(&inode->i_lock); | |
131 | } | |
132 | ||
133 | - if (nfs_clear_request_commit(req)) | |
134 | - radix_tree_tag_clear(&NFS_I(inode)->nfs_page_tree, | |
135 | - req->wb_index, NFS_PAGE_TAG_COMMIT); | |
136 | - | |
137 | /* Okay, the request matches. Update the region */ | |
138 | if (offset < req->wb_offset) { | |
139 | req->wb_offset = offset; | |
140 | @@ -758,7 +755,8 @@ int nfs_flush_incompatible(struct file * | |
141 | req = nfs_page_find_request(page); | |
142 | if (req == NULL) | |
143 | return 0; | |
144 | - do_flush = req->wb_page != page || req->wb_context != ctx; | |
145 | + do_flush = req->wb_page != page || req->wb_context != ctx | |
146 | + || !nfs_dirty_request(req); | |
147 | nfs_release_request(req); | |
148 | if (!do_flush) | |
149 | return 0; | |
150 | @@ -1363,7 +1361,10 @@ static void nfs_commit_release(void *cal | |
151 | while (!list_empty(&data->pages)) { | |
152 | req = nfs_list_entry(data->pages.next); | |
153 | nfs_list_remove_request(req); | |
154 | - nfs_clear_request_commit(req); | |
155 | + clear_bit(PG_NEED_COMMIT, &(req)->wb_flags); | |
156 | + dec_zone_page_state(req->wb_page, NR_UNSTABLE_NFS); | |
157 | + dec_bdi_stat(req->wb_page->mapping->backing_dev_info, | |
158 | + BDI_RECLAIMABLE); | |
159 | ||
160 | dprintk("NFS: commit (%s/%lld %d@%lld)", | |
161 | req->wb_context->path.dentry->d_inode->i_sb->s_id, | |
162 | @@ -1539,7 +1540,7 @@ int nfs_wb_page_cancel(struct inode *ino | |
163 | req = nfs_page_find_request(page); | |
164 | if (req == NULL) | |
165 | goto out; | |
166 | - if (test_bit(PG_CLEAN, &req->wb_flags)) { | |
167 | + if (test_bit(PG_NEED_COMMIT, &req->wb_flags)) { | |
168 | nfs_release_request(req); | |
169 | break; | |
170 | } |