NFS: Fix an Oops when truncating a file

The VM/VFS does not allow mapping->a_ops->invalidatepage() to fail.
Unfortunately, nfs_wb_page_cancel() may fail if a fatal signal occurs.
Since the NFS code assumes that the page stays mapped for as long as the
writeback is active, we can end up Oopsing (among other things).

The only safe fix here is to convert nfs_wait_on_request(), so as to make
it uninterruptible (as is already the case with wait_on_page_writeback()).


Signed-off-by: Trond Myklebust <Trond.Myklebust@netapp.com>
Cc: stable@kernel.org

+9 -8
+9 -8
fs/nfs/pagelist.c
··· 176 kref_put(&req->wb_kref, nfs_free_request); 177 } 178 179 /** 180 * nfs_wait_on_request - Wait for a request to complete. 181 * @req: request to wait upon. ··· 192 int 193 nfs_wait_on_request(struct nfs_page *req) 194 { 195 - int ret = 0; 196 - 197 - if (!test_bit(PG_BUSY, &req->wb_flags)) 198 - goto out; 199 - ret = out_of_line_wait_on_bit(&req->wb_flags, PG_BUSY, 200 - nfs_wait_bit_killable, TASK_KILLABLE); 201 - out: 202 - return ret; 203 } 204 205 /**
··· 176 kref_put(&req->wb_kref, nfs_free_request); 177 } 178 179 + static int nfs_wait_bit_uninterruptible(void *word) 180 + { 181 + io_schedule(); 182 + return 0; 183 + } 184 + 185 /** 186 * nfs_wait_on_request - Wait for a request to complete. 187 * @req: request to wait upon. ··· 186 int 187 nfs_wait_on_request(struct nfs_page *req) 188 { 189 + return wait_on_bit(&req->wb_flags, PG_BUSY, 190 + nfs_wait_bit_uninterruptible, 191 + TASK_UNINTERRUPTIBLE); 192 } 193 194 /**