Blame view
fs/nfs/write.c
44.1 KB
1da177e4c Linux-2.6.12-rc2 |
1 2 3 |
/* * linux/fs/nfs/write.c * |
7c85d9007 NFS: Fixup some o... |
4 |
* Write file data over NFS. |
1da177e4c Linux-2.6.12-rc2 |
5 6 7 |
* * Copyright (C) 1996, 1997, Olaf Kirch <okir@monad.swb.de> */ |
1da177e4c Linux-2.6.12-rc2 |
8 9 10 11 12 |
#include <linux/types.h> #include <linux/slab.h> #include <linux/mm.h> #include <linux/pagemap.h> #include <linux/file.h> |
1da177e4c Linux-2.6.12-rc2 |
13 |
#include <linux/writeback.h> |
89a09141d [PATCH] nfs: fix ... |
14 |
#include <linux/swap.h> |
074cc1dee NFS: Add a ->migr... |
15 |
#include <linux/migrate.h> |
1da177e4c Linux-2.6.12-rc2 |
16 17 18 19 20 |
#include <linux/sunrpc/clnt.h> #include <linux/nfs_fs.h> #include <linux/nfs_mount.h> #include <linux/nfs_page.h> |
3fcfab16c [PATCH] separate ... |
21 |
#include <linux/backing-dev.h> |
afeacc8c1 fs: add export.h ... |
22 |
#include <linux/export.h> |
3fcfab16c [PATCH] separate ... |
23 |
|
1da177e4c Linux-2.6.12-rc2 |
24 |
#include <asm/uaccess.h> |
1da177e4c Linux-2.6.12-rc2 |
25 26 |
#include "delegation.h" |
49a70f278 NFS: Cleanup: add... |
27 |
#include "internal.h" |
91d5b4702 NFS: add I/O perf... |
28 |
#include "iostat.h" |
def6ed7ef nfs41 write seque... |
29 |
#include "nfs4_fs.h" |
074cc1dee NFS: Add a ->migr... |
30 |
#include "fscache.h" |
94ad1c80e NFSv4.1: coelesce... |
31 |
#include "pnfs.h" |
1da177e4c Linux-2.6.12-rc2 |
32 33 34 35 36 37 38 39 40 |
#define NFSDBG_FACILITY NFSDBG_PAGECACHE #define MIN_POOL_WRITE (32) #define MIN_POOL_COMMIT (4) /* * Local function declarations */ |
c63c7b051 NFS: Fix a race w... |
41 42 |
static void nfs_pageio_init_write(struct nfs_pageio_descriptor *desc, struct inode *inode, int ioflags); |
f8512ad0d nfs: don't ignore... |
43 |
static void nfs_redirty_request(struct nfs_page *req); |
788e7a89a NFS: Cleanup of N... |
44 45 46 |
static const struct rpc_call_ops nfs_write_partial_ops; static const struct rpc_call_ops nfs_write_full_ops; static const struct rpc_call_ops nfs_commit_ops; |
1da177e4c Linux-2.6.12-rc2 |
47 |
|
e18b890bb [PATCH] slab: rem... |
48 |
static struct kmem_cache *nfs_wdata_cachep; |
3feb2d493 NFS: Uninline nfs... |
49 |
static mempool_t *nfs_wdata_mempool; |
1da177e4c Linux-2.6.12-rc2 |
50 |
static mempool_t *nfs_commit_mempool; |
c9d8f89d9 NFS: Ensure that ... |
51 |
struct nfs_write_data *nfs_commitdata_alloc(void) |
1da177e4c Linux-2.6.12-rc2 |
52 |
{ |
e6b4f8da3 [PATCH] slab: rem... |
53 |
struct nfs_write_data *p = mempool_alloc(nfs_commit_mempool, GFP_NOFS); |
40859d7ee NFS: support larg... |
54 |
|
1da177e4c Linux-2.6.12-rc2 |
55 56 57 58 59 60 |
if (p) { memset(p, 0, sizeof(*p)); INIT_LIST_HEAD(&p->pages); } return p; } |
e0c2b3801 NFSv4.1: filelayo... |
61 |
EXPORT_SYMBOL_GPL(nfs_commitdata_alloc); |
1da177e4c Linux-2.6.12-rc2 |
62 |
|
5e4424af9 SUNRPC: Remove no... |
63 |
void nfs_commit_free(struct nfs_write_data *p) |
1da177e4c Linux-2.6.12-rc2 |
64 |
{ |
40859d7ee NFS: support larg... |
65 66 |
if (p && (p->pagevec != &p->page_array[0])) kfree(p->pagevec); |
1da177e4c Linux-2.6.12-rc2 |
67 68 |
mempool_free(p, nfs_commit_mempool); } |
e0c2b3801 NFSv4.1: filelayo... |
69 |
EXPORT_SYMBOL_GPL(nfs_commit_free); |
1da177e4c Linux-2.6.12-rc2 |
70 |
|
8d5658c94 NFS: Fix a buffer... |
71 |
struct nfs_write_data *nfs_writedata_alloc(unsigned int pagecount) |
3feb2d493 NFS: Uninline nfs... |
72 |
{ |
e6b4f8da3 [PATCH] slab: rem... |
73 |
struct nfs_write_data *p = mempool_alloc(nfs_wdata_mempool, GFP_NOFS); |
3feb2d493 NFS: Uninline nfs... |
74 75 76 77 |
if (p) { memset(p, 0, sizeof(*p)); INIT_LIST_HEAD(&p->pages); |
e9f7bee1d [PATCH] NFS: larg... |
78 |
p->npages = pagecount; |
0d0b5cb36 NFS: Optimize all... |
79 80 |
if (pagecount <= ARRAY_SIZE(p->page_array)) p->pagevec = p->page_array; |
3feb2d493 NFS: Uninline nfs... |
81 |
else { |
0d0b5cb36 NFS: Optimize all... |
82 83 |
p->pagevec = kcalloc(pagecount, sizeof(struct page *), GFP_NOFS); if (!p->pagevec) { |
3feb2d493 NFS: Uninline nfs... |
84 85 86 87 88 89 90 |
mempool_free(p, nfs_wdata_mempool); p = NULL; } } } return p; } |
1ae88b2e4 NFS: Fix an O_DIR... |
91 |
void nfs_writedata_free(struct nfs_write_data *p) |
3feb2d493 NFS: Uninline nfs... |
92 93 94 95 96 |
{ if (p && (p->pagevec != &p->page_array[0])) kfree(p->pagevec); mempool_free(p, nfs_wdata_mempool); } |
dce81290e NFS: Move the pnf... |
97 |
void nfs_writedata_release(struct nfs_write_data *wdata) |
1da177e4c Linux-2.6.12-rc2 |
98 |
{ |
5053aa568 NFSv4.1: Send lse... |
99 |
put_lseg(wdata->lseg); |
383ba7193 NFS: Fix a deadlo... |
100 |
put_nfs_open_context(wdata->args.context); |
1da177e4c Linux-2.6.12-rc2 |
101 102 |
nfs_writedata_free(wdata); } |
7b159fc18 NFS: Fall back to... |
103 104 105 106 107 108 |
static void nfs_context_set_write_error(struct nfs_open_context *ctx, int error) { ctx->error = error; smp_wmb(); set_bit(NFS_CONTEXT_ERROR_WRITE, &ctx->flags); } |
277459d2e NFS: Store pointe... |
109 110 111 112 113 114 115 |
static struct nfs_page *nfs_page_find_request_locked(struct page *page) { struct nfs_page *req = NULL; if (PagePrivate(page)) { req = (struct nfs_page *)page_private(page); if (req != NULL) |
c03b40246 NFS: Convert stru... |
116 |
kref_get(&req->wb_kref); |
277459d2e NFS: Store pointe... |
117 118 119 120 121 122 |
} return req; } static struct nfs_page *nfs_page_find_request(struct page *page) { |
587142f85 NFS: Replace NFS_... |
123 |
struct inode *inode = page->mapping->host; |
277459d2e NFS: Store pointe... |
124 |
struct nfs_page *req = NULL; |
277459d2e NFS: Store pointe... |
125 |
|
587142f85 NFS: Replace NFS_... |
126 |
spin_lock(&inode->i_lock); |
277459d2e NFS: Store pointe... |
127 |
req = nfs_page_find_request_locked(page); |
587142f85 NFS: Replace NFS_... |
128 |
spin_unlock(&inode->i_lock); |
277459d2e NFS: Store pointe... |
129 130 |
return req; } |
1da177e4c Linux-2.6.12-rc2 |
131 132 133 134 |
/* Adjust the file length if we're writing beyond the end */ static void nfs_grow_file(struct page *page, unsigned int offset, unsigned int count) { struct inode *inode = page->mapping->host; |
a3d01454b NFS: Remove BKL r... |
135 136 |
loff_t end, i_size; pgoff_t end_index; |
1da177e4c Linux-2.6.12-rc2 |
137 |
|
a3d01454b NFS: Remove BKL r... |
138 139 140 |
spin_lock(&inode->i_lock); i_size = i_size_read(inode); end_index = (i_size - 1) >> PAGE_CACHE_SHIFT; |
1da177e4c Linux-2.6.12-rc2 |
141 |
if (i_size > 0 && page->index < end_index) |
a3d01454b NFS: Remove BKL r... |
142 |
goto out; |
1da177e4c Linux-2.6.12-rc2 |
143 144 |
end = ((loff_t)page->index << PAGE_CACHE_SHIFT) + ((loff_t)offset+count); if (i_size >= end) |
a3d01454b NFS: Remove BKL r... |
145 |
goto out; |
1da177e4c Linux-2.6.12-rc2 |
146 |
i_size_write(inode, end); |
a3d01454b NFS: Remove BKL r... |
147 148 149 |
nfs_inc_stats(inode, NFSIOS_EXTENDWRITE); out: spin_unlock(&inode->i_lock); |
1da177e4c Linux-2.6.12-rc2 |
150 |
} |
a301b7777 NFS: Don't use Cl... |
151 152 153 154 155 156 |
/* A writeback failed: mark the page as bad, and invalidate the page cache */ static void nfs_set_pageerror(struct page *page) { SetPageError(page); nfs_zap_mapping(page->mapping->host, page->mapping); } |
1da177e4c Linux-2.6.12-rc2 |
157 158 159 160 161 |
/* We can set the PG_uptodate flag if we see that a write request * covers the full page. */ static void nfs_mark_uptodate(struct page *page, unsigned int base, unsigned int count) { |
1da177e4c Linux-2.6.12-rc2 |
162 163 164 165 |
if (PageUptodate(page)) return; if (base != 0) return; |
49a70f278 NFS: Cleanup: add... |
166 |
if (count != nfs_page_length(page)) |
1da177e4c Linux-2.6.12-rc2 |
167 |
return; |
49a70f278 NFS: Cleanup: add... |
168 |
SetPageUptodate(page); |
1da177e4c Linux-2.6.12-rc2 |
169 |
} |
1da177e4c Linux-2.6.12-rc2 |
170 171 172 |
static int wb_priority(struct writeback_control *wbc) { if (wbc->for_reclaim) |
c63c7b051 NFS: Fix a race w... |
173 |
return FLUSH_HIGHPRI | FLUSH_STABLE; |
b17621fed writeback: introd... |
174 |
if (wbc->for_kupdate || wbc->for_background) |
b31268ac7 FS: Use stable wr... |
175 176 |
return FLUSH_LOWPRI | FLUSH_COND_STABLE; return FLUSH_COND_STABLE; |
1da177e4c Linux-2.6.12-rc2 |
177 178 179 |
} /* |
89a09141d [PATCH] nfs: fix ... |
180 181 182 183 184 185 186 187 |
* NFS congestion control */ int nfs_congestion_kb; #define NFS_CONGESTION_ON_THRESH (nfs_congestion_kb >> (PAGE_SHIFT-10)) #define NFS_CONGESTION_OFF_THRESH \ (NFS_CONGESTION_ON_THRESH - (NFS_CONGESTION_ON_THRESH >> 2)) |
5a6d41b32 NFS: Ensure PG_wr... |
188 |
static int nfs_set_page_writeback(struct page *page) |
89a09141d [PATCH] nfs: fix ... |
189 |
{ |
5a6d41b32 NFS: Ensure PG_wr... |
190 191 192 |
int ret = test_set_page_writeback(page); if (!ret) { |
89a09141d [PATCH] nfs: fix ... |
193 194 |
struct inode *inode = page->mapping->host; struct nfs_server *nfss = NFS_SERVER(inode); |
a6305ddb0 NFS: Fix a race w... |
195 |
page_cache_get(page); |
277866a0e nfs: fix congesti... |
196 |
if (atomic_long_inc_return(&nfss->writeback) > |
8aa7e847d Fix congestion_wa... |
197 198 199 200 |
NFS_CONGESTION_ON_THRESH) { set_bdi_congested(&nfss->backing_dev_info, BLK_RW_ASYNC); } |
89a09141d [PATCH] nfs: fix ... |
201 |
} |
5a6d41b32 NFS: Ensure PG_wr... |
202 |
return ret; |
89a09141d [PATCH] nfs: fix ... |
203 204 205 206 207 208 209 210 |
} static void nfs_end_page_writeback(struct page *page) { struct inode *inode = page->mapping->host; struct nfs_server *nfss = NFS_SERVER(inode); end_page_writeback(page); |
a6305ddb0 NFS: Fix a race w... |
211 |
page_cache_release(page); |
c4dc4beed nfs: remove conge... |
212 |
if (atomic_long_dec_return(&nfss->writeback) < NFS_CONGESTION_OFF_THRESH) |
8aa7e847d Fix congestion_wa... |
213 |
clear_bdi_congested(&nfss->backing_dev_info, BLK_RW_ASYNC); |
89a09141d [PATCH] nfs: fix ... |
214 |
} |
cfb506e1d NFS: Ensure that ... |
215 |
static struct nfs_page *nfs_find_and_lock_request(struct page *page, bool nonblock) |
e261f51f2 NFS: Make nfs_upd... |
216 |
{ |
587142f85 NFS: Replace NFS_... |
217 |
struct inode *inode = page->mapping->host; |
e261f51f2 NFS: Make nfs_upd... |
218 |
struct nfs_page *req; |
e261f51f2 NFS: Make nfs_upd... |
219 |
int ret; |
587142f85 NFS: Replace NFS_... |
220 |
spin_lock(&inode->i_lock); |
074cc1dee NFS: Add a ->migr... |
221 |
for (;;) { |
e261f51f2 NFS: Make nfs_upd... |
222 |
req = nfs_page_find_request_locked(page); |
074cc1dee NFS: Add a ->migr... |
223 224 |
if (req == NULL) break; |
acee478af NFS: Clean up the... |
225 |
if (nfs_set_page_tag_locked(req)) |
e261f51f2 NFS: Make nfs_upd... |
226 227 |
break; /* Note: If we hold the page lock, as is the case in nfs_writepage, |
acee478af NFS: Clean up the... |
228 |
* then the call to nfs_set_page_tag_locked() will always |
e261f51f2 NFS: Make nfs_upd... |
229 230 231 |
* succeed provided that someone hasn't already marked the * request as dirty (in which case we don't care). */ |
587142f85 NFS: Replace NFS_... |
232 |
spin_unlock(&inode->i_lock); |
cfb506e1d NFS: Ensure that ... |
233 234 235 236 |
if (!nonblock) ret = nfs_wait_on_request(req); else ret = -EAGAIN; |
e261f51f2 NFS: Make nfs_upd... |
237 238 |
nfs_release_request(req); if (ret != 0) |
074cc1dee NFS: Add a ->migr... |
239 |
return ERR_PTR(ret); |
587142f85 NFS: Replace NFS_... |
240 |
spin_lock(&inode->i_lock); |
e261f51f2 NFS: Make nfs_upd... |
241 |
} |
587142f85 NFS: Replace NFS_... |
242 |
spin_unlock(&inode->i_lock); |
074cc1dee NFS: Add a ->migr... |
243 244 245 246 247 248 249 250 |
return req; } /* * Find an associated nfs write request, and prepare to flush it out * May return an error if the user signalled nfs_wait_on_request(). */ static int nfs_page_async_flush(struct nfs_pageio_descriptor *pgio, |
cfb506e1d NFS: Ensure that ... |
251 |
struct page *page, bool nonblock) |
074cc1dee NFS: Add a ->migr... |
252 253 254 |
{ struct nfs_page *req; int ret = 0; |
cfb506e1d NFS: Ensure that ... |
255 |
req = nfs_find_and_lock_request(page, nonblock); |
074cc1dee NFS: Add a ->migr... |
256 257 258 259 260 261 262 263 264 |
if (!req) goto out; ret = PTR_ERR(req); if (IS_ERR(req)) goto out; ret = nfs_set_page_writeback(page); BUG_ON(ret != 0); BUG_ON(test_bit(PG_CLEAN, &req->wb_flags)); |
f8512ad0d nfs: don't ignore... |
265 266 |
if (!nfs_pageio_add_request(pgio, req)) { nfs_redirty_request(req); |
074cc1dee NFS: Add a ->migr... |
267 |
ret = pgio->pg_error; |
f8512ad0d nfs: don't ignore... |
268 |
} |
074cc1dee NFS: Add a ->migr... |
269 270 |
out: return ret; |
e261f51f2 NFS: Make nfs_upd... |
271 |
} |
f758c8851 NFS: Clean up nfs... |
272 |
static int nfs_do_writepage(struct page *page, struct writeback_control *wbc, struct nfs_pageio_descriptor *pgio) |
1da177e4c Linux-2.6.12-rc2 |
273 |
{ |
1da177e4c Linux-2.6.12-rc2 |
274 |
struct inode *inode = page->mapping->host; |
cfb506e1d NFS: Ensure that ... |
275 |
int ret; |
1da177e4c Linux-2.6.12-rc2 |
276 |
|
91d5b4702 NFS: add I/O perf... |
277 278 |
nfs_inc_stats(inode, NFSIOS_VFSWRITEPAGE); nfs_add_stats(inode, NFSIOS_WRITEPAGES, 1); |
7fe7f8487 NFS: Avoid a dead... |
279 |
nfs_pageio_cond_complete(pgio, page->index); |
1b430beee writeback: remove... |
280 |
ret = nfs_page_async_flush(pgio, page, wbc->sync_mode == WB_SYNC_NONE); |
cfb506e1d NFS: Ensure that ... |
281 282 283 284 285 |
if (ret == -EAGAIN) { redirty_page_for_writepage(wbc, page); ret = 0; } return ret; |
f758c8851 NFS: Clean up nfs... |
286 |
} |
7fe7f8487 NFS: Avoid a dead... |
287 |
|
f758c8851 NFS: Clean up nfs... |
288 289 290 291 292 293 294 |
/* * Write an mmapped page to the server. */ static int nfs_writepage_locked(struct page *page, struct writeback_control *wbc) { struct nfs_pageio_descriptor pgio; int err; |
49a70f278 NFS: Cleanup: add... |
295 |
|
f758c8851 NFS: Clean up nfs... |
296 297 298 299 300 301 302 303 |
nfs_pageio_init_write(&pgio, page->mapping->host, wb_priority(wbc)); err = nfs_do_writepage(page, wbc, &pgio); nfs_pageio_complete(&pgio); if (err < 0) return err; if (pgio.pg_error < 0) return pgio.pg_error; return 0; |
4d770ccf4 NFS: Ensure that ... |
304 305 306 307 |
} int nfs_writepage(struct page *page, struct writeback_control *wbc) { |
f758c8851 NFS: Clean up nfs... |
308 |
int ret; |
4d770ccf4 NFS: Ensure that ... |
309 |
|
f758c8851 NFS: Clean up nfs... |
310 |
ret = nfs_writepage_locked(page, wbc); |
1da177e4c Linux-2.6.12-rc2 |
311 |
unlock_page(page); |
f758c8851 NFS: Clean up nfs... |
312 313 314 315 316 317 318 319 320 321 |
return ret; } static int nfs_writepages_callback(struct page *page, struct writeback_control *wbc, void *data) { int ret; ret = nfs_do_writepage(page, wbc, data); unlock_page(page); return ret; |
1da177e4c Linux-2.6.12-rc2 |
322 |
} |
1da177e4c Linux-2.6.12-rc2 |
323 324 |
int nfs_writepages(struct address_space *mapping, struct writeback_control *wbc) { |
1da177e4c Linux-2.6.12-rc2 |
325 |
struct inode *inode = mapping->host; |
72cb77f4a NFS: Throttle pag... |
326 |
unsigned long *bitlock = &NFS_I(inode)->flags; |
c63c7b051 NFS: Fix a race w... |
327 |
struct nfs_pageio_descriptor pgio; |
1da177e4c Linux-2.6.12-rc2 |
328 |
int err; |
72cb77f4a NFS: Throttle pag... |
329 330 331 332 333 |
/* Stop dirtying of new pages while we sync */ err = wait_on_bit_lock(bitlock, NFS_INO_FLUSHING, nfs_wait_bit_killable, TASK_KILLABLE); if (err) goto out_err; |
91d5b4702 NFS: add I/O perf... |
334 |
nfs_inc_stats(inode, NFSIOS_VFSWRITEPAGES); |
c63c7b051 NFS: Fix a race w... |
335 |
nfs_pageio_init_write(&pgio, inode, wb_priority(wbc)); |
f758c8851 NFS: Clean up nfs... |
336 |
err = write_cache_pages(mapping, wbc, nfs_writepages_callback, &pgio); |
c63c7b051 NFS: Fix a race w... |
337 |
nfs_pageio_complete(&pgio); |
72cb77f4a NFS: Throttle pag... |
338 339 340 341 |
clear_bit_unlock(NFS_INO_FLUSHING, bitlock); smp_mb__after_clear_bit(); wake_up_bit(bitlock, NFS_INO_FLUSHING); |
f758c8851 NFS: Clean up nfs... |
342 |
if (err < 0) |
72cb77f4a NFS: Throttle pag... |
343 344 345 346 |
goto out_err; err = pgio.pg_error; if (err < 0) goto out_err; |
c63c7b051 NFS: Fix a race w... |
347 |
return 0; |
72cb77f4a NFS: Throttle pag... |
348 349 |
out_err: return err; |
1da177e4c Linux-2.6.12-rc2 |
350 351 352 353 354 |
} /* * Insert a write request into an inode */ |
e7d39069e NFS: Clean up nfs... |
355 |
static int nfs_inode_add_request(struct inode *inode, struct nfs_page *req) |
1da177e4c Linux-2.6.12-rc2 |
356 357 358 |
{ struct nfs_inode *nfsi = NFS_I(inode); int error; |
e7d39069e NFS: Clean up nfs... |
359 360 361 362 363 364 365 366 |
error = radix_tree_preload(GFP_NOFS); if (error != 0) goto out; /* Lock the request! */ nfs_lock_request_dontget(req); spin_lock(&inode->i_lock); |
1da177e4c Linux-2.6.12-rc2 |
367 |
error = radix_tree_insert(&nfsi->nfs_page_tree, req->wb_index, req); |
278525963 nfs: use GFP_NOFS... |
368 |
BUG_ON(error); |
4d65c520f NFS: Fix a hang i... |
369 |
if (!nfsi->npages && nfs_have_delegation(inode, FMODE_WRITE)) |
a9a4a87a5 NFS: Use the inod... |
370 |
inode->i_version++; |
2df485a77 nfs: remove extra... |
371 |
set_bit(PG_MAPPED, &req->wb_flags); |
deb7d6382 NFS: Fix a race w... |
372 |
SetPagePrivate(req->wb_page); |
277459d2e NFS: Store pointe... |
373 |
set_page_private(req->wb_page, (unsigned long)req); |
1da177e4c Linux-2.6.12-rc2 |
374 |
nfsi->npages++; |
c03b40246 NFS: Convert stru... |
375 |
kref_get(&req->wb_kref); |
278525963 nfs: use GFP_NOFS... |
376 377 |
radix_tree_tag_set(&nfsi->nfs_page_tree, req->wb_index, NFS_PAGE_TAG_LOCKED); |
e7d39069e NFS: Clean up nfs... |
378 379 380 381 |
spin_unlock(&inode->i_lock); radix_tree_preload_end(); out: return error; |
1da177e4c Linux-2.6.12-rc2 |
382 383 384 |
} /* |
89a09141d [PATCH] nfs: fix ... |
385 |
* Remove a write request from an inode |
1da177e4c Linux-2.6.12-rc2 |
386 387 388 |
*/ static void nfs_inode_remove_request(struct nfs_page *req) { |
3d4ff43d8 nfs_open_context ... |
389 |
struct inode *inode = req->wb_context->dentry->d_inode; |
1da177e4c Linux-2.6.12-rc2 |
390 391 392 |
struct nfs_inode *nfsi = NFS_I(inode); BUG_ON (!NFS_WBACK_BUSY(req)); |
587142f85 NFS: Replace NFS_... |
393 |
spin_lock(&inode->i_lock); |
277459d2e NFS: Store pointe... |
394 |
set_page_private(req->wb_page, 0); |
deb7d6382 NFS: Fix a race w... |
395 |
ClearPagePrivate(req->wb_page); |
2df485a77 nfs: remove extra... |
396 |
clear_bit(PG_MAPPED, &req->wb_flags); |
1da177e4c Linux-2.6.12-rc2 |
397 398 |
radix_tree_delete(&nfsi->nfs_page_tree, req->wb_index); nfsi->npages--; |
4d65c520f NFS: Fix a hang i... |
399 |
spin_unlock(&inode->i_lock); |
1da177e4c Linux-2.6.12-rc2 |
400 401 |
nfs_release_request(req); } |
61822ab5e NFS: Ensure we on... |
402 |
static void |
6d884e8fc nfs: nfs_redirty_... |
403 |
nfs_mark_request_dirty(struct nfs_page *req) |
61822ab5e NFS: Ensure we on... |
404 |
{ |
61822ab5e NFS: Ensure we on... |
405 406 |
__set_page_dirty_nobuffers(req->wb_page); } |
1da177e4c Linux-2.6.12-rc2 |
407 408 409 410 411 |
#if defined(CONFIG_NFS_V3) || defined(CONFIG_NFS_V4) /* * Add a request to the inode's commit list. */ static void |
a861a1e1c NFSv4.1: add gene... |
412 |
nfs_mark_request_commit(struct nfs_page *req, struct pnfs_layout_segment *lseg) |
1da177e4c Linux-2.6.12-rc2 |
413 |
{ |
3d4ff43d8 nfs_open_context ... |
414 |
struct inode *inode = req->wb_context->dentry->d_inode; |
1da177e4c Linux-2.6.12-rc2 |
415 |
struct nfs_inode *nfsi = NFS_I(inode); |
587142f85 NFS: Replace NFS_... |
416 |
spin_lock(&inode->i_lock); |
e468bae97 NFS: Allow redirt... |
417 |
set_bit(PG_CLEAN, &(req)->wb_flags); |
5c3696834 NFS cleanup: spee... |
418 419 420 |
radix_tree_tag_set(&nfsi->nfs_page_tree, req->wb_index, NFS_PAGE_TAG_COMMIT); |
ff778d02b NFS: Add a count ... |
421 |
nfsi->ncommit++; |
587142f85 NFS: Replace NFS_... |
422 |
spin_unlock(&inode->i_lock); |
a861a1e1c NFSv4.1: add gene... |
423 |
pnfs_mark_request_commit(req, lseg); |
fd39fc856 [PATCH] zoned vm ... |
424 |
inc_zone_page_state(req->wb_page, NR_UNSTABLE_NFS); |
c9e51e418 mm: count reclaim... |
425 |
inc_bdi_stat(req->wb_page->mapping->backing_dev_info, BDI_RECLAIMABLE); |
a18030445 NFS: Clean up cal... |
426 |
__mark_inode_dirty(inode, I_DIRTY_DATASYNC); |
1da177e4c Linux-2.6.12-rc2 |
427 |
} |
8e821cad1 NFS: clean up the... |
428 |
|
e468bae97 NFS: Allow redirt... |
429 430 431 432 433 434 435 436 437 438 439 440 |
static int nfs_clear_request_commit(struct nfs_page *req) { struct page *page = req->wb_page; if (test_and_clear_bit(PG_CLEAN, &(req)->wb_flags)) { dec_zone_page_state(page, NR_UNSTABLE_NFS); dec_bdi_stat(page->mapping->backing_dev_info, BDI_RECLAIMABLE); return 1; } return 0; } |
8e821cad1 NFS: clean up the... |
441 442 443 |
static inline int nfs_write_need_commit(struct nfs_write_data *data) { |
465d52437 NFSv4.1: don't se... |
444 445 446 447 |
if (data->verf.committed == NFS_DATA_SYNC) return data->lseg == NULL; else return data->verf.committed != NFS_FILE_SYNC; |
8e821cad1 NFS: clean up the... |
448 449 450 |
} static inline |
a861a1e1c NFSv4.1: add gene... |
451 452 |
int nfs_reschedule_unstable_write(struct nfs_page *req, struct nfs_write_data *data) |
8e821cad1 NFS: clean up the... |
453 |
{ |
e468bae97 NFS: Allow redirt... |
454 |
if (test_and_clear_bit(PG_NEED_COMMIT, &req->wb_flags)) { |
a861a1e1c NFSv4.1: add gene... |
455 |
nfs_mark_request_commit(req, data->lseg); |
8e821cad1 NFS: clean up the... |
456 457 458 |
return 1; } if (test_and_clear_bit(PG_NEED_RESCHED, &req->wb_flags)) { |
6d884e8fc nfs: nfs_redirty_... |
459 |
nfs_mark_request_dirty(req); |
8e821cad1 NFS: clean up the... |
460 461 462 463 464 465 |
return 1; } return 0; } #else static inline void |
a861a1e1c NFSv4.1: add gene... |
466 |
nfs_mark_request_commit(struct nfs_page *req, struct pnfs_layout_segment *lseg) |
8e821cad1 NFS: clean up the... |
467 468 |
{ } |
e468bae97 NFS: Allow redirt... |
469 470 471 472 473 |
static inline int nfs_clear_request_commit(struct nfs_page *req) { return 0; } |
8e821cad1 NFS: clean up the... |
474 475 476 477 478 479 480 |
static inline int nfs_write_need_commit(struct nfs_write_data *data) { return 0; } static inline |
a861a1e1c NFSv4.1: add gene... |
481 482 |
int nfs_reschedule_unstable_write(struct nfs_page *req, struct nfs_write_data *data) |
8e821cad1 NFS: clean up the... |
483 484 485 |
{ return 0; } |
1da177e4c Linux-2.6.12-rc2 |
486 |
#endif |
47c625642 NFS: Fix up a mis... |
487 |
#if defined(CONFIG_NFS_V3) || defined(CONFIG_NFS_V4) |
fb8a1f11b NFS: cleanup - re... |
488 489 490 491 492 |
static int nfs_need_commit(struct nfs_inode *nfsi) { return radix_tree_tagged(&nfsi->nfs_page_tree, NFS_PAGE_TAG_COMMIT); } |
1da177e4c Linux-2.6.12-rc2 |
493 494 495 496 497 498 499 500 501 502 503 |
/* * nfs_scan_commit - Scan an inode for commit requests * @inode: NFS inode to scan * @dst: destination list * @idx_start: lower bound of page->index to scan. * @npages: idx_start + npages sets the upper bound to scan. * * Moves requests from the inode's 'commit' request list. * The requests are *not* checked to ensure that they form a contiguous set. */ static int |
ca52fec15 NFS: Use pgoff_t ... |
504 |
nfs_scan_commit(struct inode *inode, struct list_head *dst, pgoff_t idx_start, unsigned int npages) |
1da177e4c Linux-2.6.12-rc2 |
505 506 |
{ struct nfs_inode *nfsi = NFS_I(inode); |
ff778d02b NFS: Add a count ... |
507 |
int ret; |
3da28eb1c [PATCH] NFS: Repl... |
508 |
|
fb8a1f11b NFS: cleanup - re... |
509 510 |
if (!nfs_need_commit(nfsi)) return 0; |
0d88f6e80 nfs: don't call _... |
511 |
spin_lock(&inode->i_lock); |
ff778d02b NFS: Add a count ... |
512 513 514 |
ret = nfs_scan_list(nfsi, dst, idx_start, npages, NFS_PAGE_TAG_COMMIT); if (ret > 0) nfsi->ncommit -= ret; |
0d88f6e80 nfs: don't call _... |
515 |
spin_unlock(&inode->i_lock); |
2928db1ff NFS: Ensure inode... |
516 517 |
if (nfs_need_commit(NFS_I(inode))) __mark_inode_dirty(inode, I_DIRTY_DATASYNC); |
0d88f6e80 nfs: don't call _... |
518 |
|
ff778d02b NFS: Add a count ... |
519 |
return ret; |
1da177e4c Linux-2.6.12-rc2 |
520 |
} |
c42de9dd6 NFS: Fix a race i... |
521 |
#else |
fb8a1f11b NFS: cleanup - re... |
522 523 524 525 |
static inline int nfs_need_commit(struct nfs_inode *nfsi) { return 0; } |
ca52fec15 NFS: Use pgoff_t ... |
526 |
static inline int nfs_scan_commit(struct inode *inode, struct list_head *dst, pgoff_t idx_start, unsigned int npages) |
c42de9dd6 NFS: Fix a race i... |
527 528 529 |
{ return 0; } |
1da177e4c Linux-2.6.12-rc2 |
530 |
#endif |
1da177e4c Linux-2.6.12-rc2 |
531 |
/* |
e7d39069e NFS: Clean up nfs... |
532 533 |
* Search for an existing write request, and attempt to update * it to reflect a new dirty region on a given page. |
1da177e4c Linux-2.6.12-rc2 |
534 |
* |
e7d39069e NFS: Clean up nfs... |
535 536 |
* If the attempt fails, then the existing request is flushed out * to disk. |
1da177e4c Linux-2.6.12-rc2 |
537 |
*/ |
e7d39069e NFS: Clean up nfs... |
538 539 540 541 |
static struct nfs_page *nfs_try_to_update_request(struct inode *inode, struct page *page, unsigned int offset, unsigned int bytes) |
1da177e4c Linux-2.6.12-rc2 |
542 |
{ |
e7d39069e NFS: Clean up nfs... |
543 544 545 546 547 548 549 |
struct nfs_page *req; unsigned int rqend; unsigned int end; int error; if (!PagePrivate(page)) return NULL; |
1da177e4c Linux-2.6.12-rc2 |
550 551 |
end = offset + bytes; |
e7d39069e NFS: Clean up nfs... |
552 |
spin_lock(&inode->i_lock); |
1da177e4c Linux-2.6.12-rc2 |
553 |
|
1da177e4c Linux-2.6.12-rc2 |
554 |
for (;;) { |
277459d2e NFS: Store pointe... |
555 |
req = nfs_page_find_request_locked(page); |
e7d39069e NFS: Clean up nfs... |
556 557 558 559 560 561 562 563 564 565 |
if (req == NULL) goto out_unlock; rqend = req->wb_offset + req->wb_bytes; /* * Tell the caller to flush out the request if * the offsets are non-contiguous. * Note: nfs_flush_incompatible() will already * have flushed out requests having wrong owners. */ |
e468bae97 NFS: Allow redirt... |
566 |
if (offset > rqend |
e7d39069e NFS: Clean up nfs... |
567 568 569 570 |
|| end < req->wb_offset) goto out_flushme; if (nfs_set_page_tag_locked(req)) |
1da177e4c Linux-2.6.12-rc2 |
571 |
break; |
1da177e4c Linux-2.6.12-rc2 |
572 |
|
e7d39069e NFS: Clean up nfs... |
573 |
/* The request is locked, so wait and then retry */ |
587142f85 NFS: Replace NFS_... |
574 |
spin_unlock(&inode->i_lock); |
e7d39069e NFS: Clean up nfs... |
575 576 577 578 579 |
error = nfs_wait_on_request(req); nfs_release_request(req); if (error != 0) goto out_err; spin_lock(&inode->i_lock); |
1da177e4c Linux-2.6.12-rc2 |
580 |
} |
ff778d02b NFS: Add a count ... |
581 |
if (nfs_clear_request_commit(req) && |
a861a1e1c NFSv4.1: add gene... |
582 583 |
radix_tree_tag_clear(&NFS_I(inode)->nfs_page_tree, req->wb_index, NFS_PAGE_TAG_COMMIT) != NULL) { |
ff778d02b NFS: Add a count ... |
584 |
NFS_I(inode)->ncommit--; |
a861a1e1c NFSv4.1: add gene... |
585 586 |
pnfs_clear_request_commit(req); } |
e468bae97 NFS: Allow redirt... |
587 |
|
1da177e4c Linux-2.6.12-rc2 |
588 589 590 591 |
/* Okay, the request matches. Update the region */ if (offset < req->wb_offset) { req->wb_offset = offset; req->wb_pgbase = offset; |
1da177e4c Linux-2.6.12-rc2 |
592 |
} |
1da177e4c Linux-2.6.12-rc2 |
593 594 |
if (end > rqend) req->wb_bytes = end - req->wb_offset; |
e7d39069e NFS: Clean up nfs... |
595 596 597 598 599 600 601 602 603 604 605 606 607 608 609 610 611 612 613 614 615 616 617 618 619 620 |
else req->wb_bytes = rqend - req->wb_offset; out_unlock: spin_unlock(&inode->i_lock); return req; out_flushme: spin_unlock(&inode->i_lock); nfs_release_request(req); error = nfs_wb_page(inode, page); out_err: return ERR_PTR(error); } /* * Try to update an existing write request, or create one if there is none. * * Note: Should always be called with the Page Lock held to prevent races * if we have to add a new request. Also assumes that the caller has * already called nfs_flush_incompatible() if necessary. */ static struct nfs_page * nfs_setup_write_request(struct nfs_open_context* ctx, struct page *page, unsigned int offset, unsigned int bytes) { struct inode *inode = page->mapping->host; struct nfs_page *req; int error; |
1da177e4c Linux-2.6.12-rc2 |
621 |
|
e7d39069e NFS: Clean up nfs... |
622 623 624 625 626 627 628 629 630 631 632 |
req = nfs_try_to_update_request(inode, page, offset, bytes); if (req != NULL) goto out; req = nfs_create_request(ctx, inode, page, offset, bytes); if (IS_ERR(req)) goto out; error = nfs_inode_add_request(inode, req); if (error != 0) { nfs_release_request(req); req = ERR_PTR(error); } |
efc91ed01 NFS: Optimise app... |
633 |
out: |
61e930a90 NFS: Fix a writeb... |
634 |
return req; |
1da177e4c Linux-2.6.12-rc2 |
635 |
} |
e7d39069e NFS: Clean up nfs... |
636 637 638 639 640 641 642 643 644 645 646 |
static int nfs_writepage_setup(struct nfs_open_context *ctx, struct page *page, unsigned int offset, unsigned int count) { struct nfs_page *req; req = nfs_setup_write_request(ctx, page, offset, count); if (IS_ERR(req)) return PTR_ERR(req); /* Update file length */ nfs_grow_file(page, offset, count); nfs_mark_uptodate(page, req->wb_pgbase, req->wb_bytes); |
a6305ddb0 NFS: Fix a race w... |
647 |
nfs_mark_request_dirty(req); |
e7d39069e NFS: Clean up nfs... |
648 649 650 |
nfs_clear_page_tag_locked(req); return 0; } |
1da177e4c Linux-2.6.12-rc2 |
651 652 |
int nfs_flush_incompatible(struct file *file, struct page *page) { |
cd3758e37 NFS: Replace file... |
653 |
struct nfs_open_context *ctx = nfs_file_open_context(file); |
1da177e4c Linux-2.6.12-rc2 |
654 |
struct nfs_page *req; |
1a54533ec NFS: Add nfs_set_... |
655 |
int do_flush, status; |
1da177e4c Linux-2.6.12-rc2 |
656 657 658 659 660 661 662 663 |
/* * Look for a request corresponding to this page. If there * is one, and it belongs to another file, we flush it out * before we try to copy anything into the page. Do this * due to the lack of an ACCESS-type call in NFSv2. * Also do the same if we find a request from an existing * dropped page. */ |
1a54533ec NFS: Add nfs_set_... |
664 665 666 667 |
do { req = nfs_page_find_request(page); if (req == NULL) return 0; |
f11ac8db5 NFSv4: Ensure tha... |
668 669 670 |
do_flush = req->wb_page != page || req->wb_context != ctx || req->wb_lock_context->lockowner != current->files || req->wb_lock_context->pid != current->tgid; |
1da177e4c Linux-2.6.12-rc2 |
671 |
nfs_release_request(req); |
1a54533ec NFS: Add nfs_set_... |
672 673 674 675 676 |
if (!do_flush) return 0; status = nfs_wb_page(page->mapping->host, page); } while (status == 0); return status; |
1da177e4c Linux-2.6.12-rc2 |
677 678 679 |
} /* |
5d47a3560 NFS: Fix a potent... |
680 681 682 683 684 685 686 687 688 689 690 |
* If the page cache is marked as unsafe or invalid, then we can't rely on * the PageUptodate() flag. In this case, we will need to turn off * write optimisations that depend on the page contents being correct. */ static int nfs_write_pageuptodate(struct page *page, struct inode *inode) { return PageUptodate(page) && !(NFS_I(inode)->cache_validity & (NFS_INO_REVAL_PAGECACHE|NFS_INO_INVALID_DATA)); } /* |
1da177e4c Linux-2.6.12-rc2 |
691 692 693 694 695 696 697 698 |
* Update and possibly write a cached page of an NFS file. * * XXX: Keep an eye on generic_file_read to make sure it doesn't do bad * things with a page scheduled for an RPC call (e.g. invalidate it). */ int nfs_updatepage(struct file *file, struct page *page, unsigned int offset, unsigned int count) { |
cd3758e37 NFS: Replace file... |
699 |
struct nfs_open_context *ctx = nfs_file_open_context(file); |
1da177e4c Linux-2.6.12-rc2 |
700 |
struct inode *inode = page->mapping->host; |
1da177e4c Linux-2.6.12-rc2 |
701 |
int status = 0; |
91d5b4702 NFS: add I/O perf... |
702 |
nfs_inc_stats(inode, NFSIOS_VFSUPDATEPAGE); |
48186c7d5 NFS: Fix trace de... |
703 704 |
dprintk("NFS: nfs_updatepage(%s/%s %d@%lld) ", |
01cce933d [PATCH] nfs: chan... |
705 706 |
file->f_path.dentry->d_parent->d_name.name, file->f_path.dentry->d_name.name, count, |
48186c7d5 NFS: Fix trace de... |
707 |
(long long)(page_offset(page) + offset)); |
1da177e4c Linux-2.6.12-rc2 |
708 |
|
1da177e4c Linux-2.6.12-rc2 |
709 |
/* If we're not using byte range locks, and we know the page |
5d47a3560 NFS: Fix a potent... |
710 711 712 |
* is up to date, it may be more efficient to extend the write * to cover the entire page in order to avoid fragmentation * inefficiencies. |
1da177e4c Linux-2.6.12-rc2 |
713 |
*/ |
5d47a3560 NFS: Fix a potent... |
714 715 |
if (nfs_write_pageuptodate(page, inode) && inode->i_flock == NULL && |
6b2f3d1f7 vfs: Implement pr... |
716 |
!(file->f_flags & O_DSYNC)) { |
49a70f278 NFS: Cleanup: add... |
717 |
count = max(count + offset, nfs_page_length(page)); |
1da177e4c Linux-2.6.12-rc2 |
718 |
offset = 0; |
1da177e4c Linux-2.6.12-rc2 |
719 |
} |
e21195a74 NFS: More cleanup... |
720 |
status = nfs_writepage_setup(ctx, page, offset, count); |
03fa9e84e NFS: nfs_updatepa... |
721 722 |
if (status < 0) nfs_set_pageerror(page); |
59b7c05ff Revert "NFS: Ensu... |
723 724 |
else __set_page_dirty_nobuffers(page); |
1da177e4c Linux-2.6.12-rc2 |
725 |
|
48186c7d5 NFS: Fix trace de... |
726 727 |
dprintk("NFS: nfs_updatepage returns %d (isize %lld) ", |
1da177e4c Linux-2.6.12-rc2 |
728 |
status, (long long)i_size_read(inode)); |
1da177e4c Linux-2.6.12-rc2 |
729 730 |
return status; } |
a861a1e1c NFSv4.1: add gene... |
731 732 |
static void nfs_writepage_release(struct nfs_page *req, struct nfs_write_data *data) |
1da177e4c Linux-2.6.12-rc2 |
733 |
{ |
a6305ddb0 NFS: Fix a race w... |
734 |
struct page *page = req->wb_page; |
1da177e4c Linux-2.6.12-rc2 |
735 |
|
a861a1e1c NFSv4.1: add gene... |
736 |
if (PageError(req->wb_page) || !nfs_reschedule_unstable_write(req, data)) |
8e821cad1 NFS: clean up the... |
737 |
nfs_inode_remove_request(req); |
9fd367f0f NFS cleanup: Rena... |
738 |
nfs_clear_page_tag_locked(req); |
a6305ddb0 NFS: Fix a race w... |
739 |
nfs_end_page_writeback(page); |
1da177e4c Linux-2.6.12-rc2 |
740 |
} |
3ff7576dd SUNRPC: Clean up ... |
741 |
static int flush_task_priority(int how) |
1da177e4c Linux-2.6.12-rc2 |
742 743 744 745 746 747 748 749 750 |
{ switch (how & (FLUSH_HIGHPRI|FLUSH_LOWPRI)) { case FLUSH_HIGHPRI: return RPC_PRIORITY_HIGH; case FLUSH_LOWPRI: return RPC_PRIORITY_LOW; } return RPC_PRIORITY_NORMAL; } |
a69aef149 NFSv4.1: pnfs fil... |
751 |
int nfs_initiate_write(struct nfs_write_data *data, |
d138d5d17 NFSv4.1: rearrang... |
752 753 754 |
struct rpc_clnt *clnt, const struct rpc_call_ops *call_ops, int how) |
1da177e4c Linux-2.6.12-rc2 |
755 |
{ |
d138d5d17 NFSv4.1: rearrang... |
756 |
struct inode *inode = data->inode; |
3ff7576dd SUNRPC: Clean up ... |
757 |
int priority = flush_task_priority(how); |
077376919 NFS/SUNRPC: Conve... |
758 |
struct rpc_task *task; |
bdc7f021f NFS: Clean up the... |
759 760 761 |
struct rpc_message msg = { .rpc_argp = &data->args, .rpc_resp = &data->res, |
d138d5d17 NFSv4.1: rearrang... |
762 |
.rpc_cred = data->cred, |
bdc7f021f NFS: Clean up the... |
763 |
}; |
84115e1cd SUNRPC: Cleanup o... |
764 |
struct rpc_task_setup task_setup_data = { |
d138d5d17 NFSv4.1: rearrang... |
765 |
.rpc_client = clnt, |
077376919 NFS/SUNRPC: Conve... |
766 |
.task = &data->task, |
bdc7f021f NFS: Clean up the... |
767 |
.rpc_message = &msg, |
84115e1cd SUNRPC: Cleanup o... |
768 769 |
.callback_ops = call_ops, .callback_data = data, |
101070ca2 NFS: Ensure that ... |
770 |
.workqueue = nfsiod_workqueue, |
2c61be0a9 NFS: Ensure that ... |
771 |
.flags = RPC_TASK_ASYNC, |
3ff7576dd SUNRPC: Clean up ... |
772 |
.priority = priority, |
84115e1cd SUNRPC: Cleanup o... |
773 |
}; |
2c61be0a9 NFS: Ensure that ... |
774 |
int ret = 0; |
1da177e4c Linux-2.6.12-rc2 |
775 |
|
d138d5d17 NFSv4.1: rearrang... |
776 777 778 779 780 781 782 783 784 785 786 787 788 789 790 791 792 793 794 795 796 797 798 799 800 801 |
/* Set up the initial task struct. */ NFS_PROTO(inode)->write_setup(data, &msg); dprintk("NFS: %5u initiated write call " "(req %s/%lld, %u bytes @ offset %llu) ", data->task.tk_pid, inode->i_sb->s_id, (long long)NFS_FILEID(inode), data->args.count, (unsigned long long)data->args.offset); task = rpc_run_task(&task_setup_data); if (IS_ERR(task)) { ret = PTR_ERR(task); goto out; } if (how & FLUSH_SYNC) { ret = rpc_wait_for_completion_task(task); if (ret == 0) ret = task->tk_status; } rpc_put_task(task); out: return ret; } |
a69aef149 NFSv4.1: pnfs fil... |
802 |
EXPORT_SYMBOL_GPL(nfs_initiate_write); |
d138d5d17 NFSv4.1: rearrang... |
803 804 805 806 |
/* * Set up the argument/result storage required for the RPC call. */ |
6e4efd568 NFS: Clean up nfs... |
807 |
static void nfs_write_rpcsetup(struct nfs_page *req, |
d138d5d17 NFSv4.1: rearrang... |
808 |
struct nfs_write_data *data, |
d138d5d17 NFSv4.1: rearrang... |
809 810 811 |
unsigned int count, unsigned int offset, int how) { |
3d4ff43d8 nfs_open_context ... |
812 |
struct inode *inode = req->wb_context->dentry->d_inode; |
d138d5d17 NFSv4.1: rearrang... |
813 |
|
1da177e4c Linux-2.6.12-rc2 |
814 815 816 817 |
/* Set up the RPC argument and reply structs * NB: take care not to mess about with data->commit et al. */ data->req = req; |
3d4ff43d8 nfs_open_context ... |
818 |
data->inode = inode = req->wb_context->dentry->d_inode; |
d138d5d17 NFSv4.1: rearrang... |
819 |
data->cred = req->wb_context->cred; |
1da177e4c Linux-2.6.12-rc2 |
820 821 822 |
data->args.fh = NFS_FH(inode); data->args.offset = req_offset(req) + offset; |
2bea038c5 pnfs: write: Set ... |
823 824 |
/* pnfs_set_layoutcommit needs this */ data->mds_offset = data->args.offset; |
1da177e4c Linux-2.6.12-rc2 |
825 826 827 |
data->args.pgbase = req->wb_pgbase + offset; data->args.pages = data->pagevec; data->args.count = count; |
383ba7193 NFS: Fix a deadlo... |
828 |
data->args.context = get_nfs_open_context(req->wb_context); |
f11ac8db5 NFSv4: Ensure tha... |
829 |
data->args.lock_context = req->wb_lock_context; |
bdc7f021f NFS: Clean up the... |
830 |
data->args.stable = NFS_UNSTABLE; |
87ed5eb44 NFS: Don't use DA... |
831 832 833 834 835 836 837 838 |
switch (how & (FLUSH_STABLE | FLUSH_COND_STABLE)) { case 0: break; case FLUSH_COND_STABLE: if (nfs_need_commit(NFS_I(inode))) break; default: data->args.stable = NFS_FILE_SYNC; |
bdc7f021f NFS: Clean up the... |
839 |
} |
1da177e4c Linux-2.6.12-rc2 |
840 841 842 843 |
data->res.fattr = &data->fattr; data->res.count = count; data->res.verf = &data->verf; |
0e574af1b NFS: Cleanup init... |
844 |
nfs_fattr_init(&data->fattr); |
6e4efd568 NFS: Clean up nfs... |
845 |
} |
1da177e4c Linux-2.6.12-rc2 |
846 |
|
6e4efd568 NFS: Clean up nfs... |
847 848 |
static int nfs_do_write(struct nfs_write_data *data, const struct rpc_call_ops *call_ops, |
6e4efd568 NFS: Clean up nfs... |
849 850 |
int how) { |
5f00bcb38 Merge branch 'mas... |
851 |
struct inode *inode = data->args.context->dentry->d_inode; |
0382b7440 NFSv4.1: implemen... |
852 |
|
d138d5d17 NFSv4.1: rearrang... |
853 |
return nfs_initiate_write(data, NFS_CLIENT(inode), call_ops, how); |
1da177e4c Linux-2.6.12-rc2 |
854 |
} |
275acaafd NFS: Clean up: sp... |
855 856 |
static int nfs_do_multiple_writes(struct list_head *head, const struct rpc_call_ops *call_ops, |
275acaafd NFS: Clean up: sp... |
857 858 859 860 861 862 863 864 865 866 867 |
int how) { struct nfs_write_data *data; int ret = 0; while (!list_empty(head)) { int ret2; data = list_entry(head->next, struct nfs_write_data, list); list_del_init(&data->list); |
dce81290e NFS: Move the pnf... |
868 |
ret2 = nfs_do_write(data, call_ops, how); |
275acaafd NFS: Clean up: sp... |
869 870 871 872 873 |
if (ret == 0) ret = ret2; } return ret; } |
6d884e8fc nfs: nfs_redirty_... |
874 875 876 877 878 879 |
/* If a nfs_flush_* function fails, it should remove reqs from @head and * call this on each, which will prepare them to be retried on next * writeback using standard nfs. */ static void nfs_redirty_request(struct nfs_page *req) { |
a6305ddb0 NFS: Fix a race w... |
880 |
struct page *page = req->wb_page; |
6d884e8fc nfs: nfs_redirty_... |
881 |
nfs_mark_request_dirty(req); |
6d884e8fc nfs: nfs_redirty_... |
882 |
nfs_clear_page_tag_locked(req); |
a6305ddb0 NFS: Fix a race w... |
883 |
nfs_end_page_writeback(page); |
6d884e8fc nfs: nfs_redirty_... |
884 |
} |
1da177e4c Linux-2.6.12-rc2 |
885 886 887 888 |
/* * Generate multiple small requests to write out a single * contiguous dirty area on one page. */ |
275acaafd NFS: Clean up: sp... |
889 |
static int nfs_flush_multi(struct nfs_pageio_descriptor *desc, struct list_head *res) |
1da177e4c Linux-2.6.12-rc2 |
890 |
{ |
c76069bda NFSv4.1: rearrang... |
891 |
struct nfs_page *req = nfs_list_entry(desc->pg_list.next); |
1da177e4c Linux-2.6.12-rc2 |
892 893 |
struct page *page = req->wb_page; struct nfs_write_data *data; |
d097971d8 NFS: Use the nfs_... |
894 |
size_t wsize = desc->pg_bsize, nbytes; |
e9f7bee1d [PATCH] NFS: larg... |
895 |
unsigned int offset; |
1da177e4c Linux-2.6.12-rc2 |
896 |
int requests = 0; |
dbae4c73f NFS: Ensure that ... |
897 |
int ret = 0; |
1da177e4c Linux-2.6.12-rc2 |
898 899 |
nfs_list_remove_request(req); |
b31268ac7 FS: Use stable wr... |
900 901 902 903 |
if ((desc->pg_ioflags & FLUSH_COND_STABLE) && (desc->pg_moreio || NFS_I(desc->pg_inode)->ncommit || desc->pg_count > wsize)) desc->pg_ioflags &= ~FLUSH_COND_STABLE; |
275acaafd NFS: Clean up: sp... |
904 |
offset = 0; |
c76069bda NFSv4.1: rearrang... |
905 |
nbytes = desc->pg_count; |
e9f7bee1d [PATCH] NFS: larg... |
906 907 |
do { size_t len = min(nbytes, wsize); |
8d5658c94 NFS: Fix a buffer... |
908 |
data = nfs_writedata_alloc(1); |
1da177e4c Linux-2.6.12-rc2 |
909 910 |
if (!data) goto out_bad; |
275acaafd NFS: Clean up: sp... |
911 |
data->pagevec[0] = page; |
f13c3620a NFS: Fix a typo i... |
912 |
nfs_write_rpcsetup(req, data, len, offset, desc->pg_ioflags); |
275acaafd NFS: Clean up: sp... |
913 |
list_add(&data->list, res); |
1da177e4c Linux-2.6.12-rc2 |
914 |
requests++; |
e9f7bee1d [PATCH] NFS: larg... |
915 |
nbytes -= len; |
275acaafd NFS: Clean up: sp... |
916 |
offset += len; |
e9f7bee1d [PATCH] NFS: larg... |
917 |
} while (nbytes != 0); |
1da177e4c Linux-2.6.12-rc2 |
918 |
atomic_set(&req->wb_complete, requests); |
50828d7e6 NFS: Cache rpc_op... |
919 |
desc->pg_rpc_callops = &nfs_write_partial_ops; |
dbae4c73f NFS: Ensure that ... |
920 |
return ret; |
1da177e4c Linux-2.6.12-rc2 |
921 922 |
out_bad: |
275acaafd NFS: Clean up: sp... |
923 924 |
while (!list_empty(res)) { data = list_entry(res->next, struct nfs_write_data, list); |
6e4efd568 NFS: Clean up nfs... |
925 |
list_del(&data->list); |
0da2a4ac3 NFS: fix handling... |
926 |
nfs_writedata_free(data); |
1da177e4c Linux-2.6.12-rc2 |
927 |
} |
61822ab5e NFS: Ensure we on... |
928 |
nfs_redirty_request(req); |
1da177e4c Linux-2.6.12-rc2 |
929 930 931 932 933 934 935 936 937 938 939 |
return -ENOMEM; } /* * Create an RPC task for the given write request and kick it. * The page must have been locked by the caller. * * It may happen that the page we're passed is not marked dirty. * This is the case if nfs_updatepage detects a conflicting request * that has been written but not committed. */ |
275acaafd NFS: Clean up: sp... |
940 |
static int nfs_flush_one(struct nfs_pageio_descriptor *desc, struct list_head *res) |
1da177e4c Linux-2.6.12-rc2 |
941 942 943 944 |
{ struct nfs_page *req; struct page **pages; struct nfs_write_data *data; |
c76069bda NFSv4.1: rearrang... |
945 |
struct list_head *head = &desc->pg_list; |
3b6091846 NFS: fix return v... |
946 |
int ret = 0; |
1da177e4c Linux-2.6.12-rc2 |
947 |
|
c76069bda NFSv4.1: rearrang... |
948 949 |
data = nfs_writedata_alloc(nfs_page_array_len(desc->pg_base, desc->pg_count)); |
44b83799a NFSv4.1: trigger ... |
950 951 952 953 954 955 956 957 958 |
if (!data) { while (!list_empty(head)) { req = nfs_list_entry(head->next); nfs_list_remove_request(req); nfs_redirty_request(req); } ret = -ENOMEM; goto out; } |
1da177e4c Linux-2.6.12-rc2 |
959 |
pages = data->pagevec; |
1da177e4c Linux-2.6.12-rc2 |
960 961 962 963 |
while (!list_empty(head)) { req = nfs_list_entry(head->next); nfs_list_remove_request(req); nfs_list_add_request(req, &data->pages); |
1da177e4c Linux-2.6.12-rc2 |
964 |
*pages++ = req->wb_page; |
1da177e4c Linux-2.6.12-rc2 |
965 966 |
} req = nfs_list_entry(data->pages.next); |
b31268ac7 FS: Use stable wr... |
967 968 969 |
if ((desc->pg_ioflags & FLUSH_COND_STABLE) && (desc->pg_moreio || NFS_I(desc->pg_inode)->ncommit)) desc->pg_ioflags &= ~FLUSH_COND_STABLE; |
1da177e4c Linux-2.6.12-rc2 |
970 |
/* Set up the argument struct */ |
6e4efd568 NFS: Clean up nfs... |
971 |
nfs_write_rpcsetup(req, data, desc->pg_count, 0, desc->pg_ioflags); |
275acaafd NFS: Clean up: sp... |
972 |
list_add(&data->list, res); |
50828d7e6 NFS: Cache rpc_op... |
973 |
desc->pg_rpc_callops = &nfs_write_full_ops; |
44b83799a NFSv4.1: trigger ... |
974 |
out: |
44b83799a NFSv4.1: trigger ... |
975 |
return ret; |
1da177e4c Linux-2.6.12-rc2 |
976 |
} |
dce81290e NFS: Move the pnf... |
977 978 979 980 981 982 983 984 |
int nfs_generic_flush(struct nfs_pageio_descriptor *desc, struct list_head *head) { if (desc->pg_bsize < PAGE_CACHE_SIZE) return nfs_flush_multi(desc, head); return nfs_flush_one(desc, head); } static int nfs_generic_pg_writepages(struct nfs_pageio_descriptor *desc) |
1751c3638 NFS: Cleanup of t... |
985 |
{ |
275acaafd NFS: Clean up: sp... |
986 987 |
LIST_HEAD(head); int ret; |
dce81290e NFS: Move the pnf... |
988 |
ret = nfs_generic_flush(desc, &head); |
50828d7e6 NFS: Cache rpc_op... |
989 990 |
if (ret == 0) ret = nfs_do_multiple_writes(&head, desc->pg_rpc_callops, |
dce81290e NFS: Move the pnf... |
991 |
desc->pg_ioflags); |
275acaafd NFS: Clean up: sp... |
992 |
return ret; |
1751c3638 NFS: Cleanup of t... |
993 |
} |
1751c3638 NFS: Cleanup of t... |
994 995 996 997 998 |
static const struct nfs_pageio_ops nfs_pageio_write_ops = { .pg_test = nfs_generic_pg_test, .pg_doio = nfs_generic_pg_writepages, }; |
e2fecb215 NFS: Remove pNFS ... |
999 |
void nfs_pageio_init_write_mds(struct nfs_pageio_descriptor *pgio, |
c63c7b051 NFS: Fix a race w... |
1000 |
struct inode *inode, int ioflags) |
1da177e4c Linux-2.6.12-rc2 |
1001 |
{ |
1751c3638 NFS: Cleanup of t... |
1002 1003 1004 |
nfs_pageio_init(pgio, inode, &nfs_pageio_write_ops, NFS_SERVER(inode)->wsize, ioflags); } |
1da177e4c Linux-2.6.12-rc2 |
1005 |
|
dce81290e NFS: Move the pnf... |
1006 1007 1008 1009 1010 |
void nfs_pageio_reset_write_mds(struct nfs_pageio_descriptor *pgio) { pgio->pg_ops = &nfs_pageio_write_ops; pgio->pg_bsize = NFS_SERVER(pgio->pg_inode)->wsize; } |
1f9453578 NFS: Clean up - s... |
1011 |
EXPORT_SYMBOL_GPL(nfs_pageio_reset_write_mds); |
dce81290e NFS: Move the pnf... |
1012 |
|
1751c3638 NFS: Cleanup of t... |
1013 1014 1015 1016 1017 |
static void nfs_pageio_init_write(struct nfs_pageio_descriptor *pgio, struct inode *inode, int ioflags) { if (!pnfs_pageio_init_write(pgio, inode, ioflags)) nfs_pageio_init_write_mds(pgio, inode, ioflags); |
1da177e4c Linux-2.6.12-rc2 |
1018 1019 1020 1021 1022 |
} /* * Handle a write reply that flushed part of a page. */ |
788e7a89a NFS: Cleanup of N... |
1023 |
static void nfs_writeback_done_partial(struct rpc_task *task, void *calldata) |
1da177e4c Linux-2.6.12-rc2 |
1024 |
{ |
788e7a89a NFS: Cleanup of N... |
1025 |
struct nfs_write_data *data = calldata; |
1da177e4c Linux-2.6.12-rc2 |
1026 |
|
48186c7d5 NFS: Fix trace de... |
1027 1028 |
dprintk("NFS: %5u write(%s/%lld %d@%lld)", task->tk_pid, |
3d4ff43d8 nfs_open_context ... |
1029 |
data->req->wb_context->dentry->d_inode->i_sb->s_id, |
48186c7d5 NFS: Fix trace de... |
1030 |
(long long) |
3d4ff43d8 nfs_open_context ... |
1031 |
NFS_FILEID(data->req->wb_context->dentry->d_inode), |
48186c7d5 NFS: Fix trace de... |
1032 |
data->req->wb_bytes, (long long)req_offset(data->req)); |
1da177e4c Linux-2.6.12-rc2 |
1033 |
|
c9d8f89d9 NFS: Ensure that ... |
1034 1035 |
nfs_writeback_done(task, data); } |
788e7a89a NFS: Cleanup of N... |
1036 |
|
c9d8f89d9 NFS: Ensure that ... |
1037 1038 1039 1040 1041 1042 1043 1044 |
static void nfs_writeback_release_partial(void *calldata) { struct nfs_write_data *data = calldata; struct nfs_page *req = data->req; struct page *page = req->wb_page; int status = data->task.tk_status; if (status < 0) { |
a301b7777 NFS: Don't use Cl... |
1045 |
nfs_set_pageerror(page); |
c9d8f89d9 NFS: Ensure that ... |
1046 1047 1048 |
nfs_context_set_write_error(req->wb_context, status); dprintk(", error = %d ", status); |
8e821cad1 NFS: clean up the... |
1049 |
goto out; |
1da177e4c Linux-2.6.12-rc2 |
1050 |
} |
8e821cad1 NFS: clean up the... |
1051 |
if (nfs_write_need_commit(data)) { |
587142f85 NFS: Replace NFS_... |
1052 |
struct inode *inode = page->mapping->host; |
8e821cad1 NFS: clean up the... |
1053 |
|
587142f85 NFS: Replace NFS_... |
1054 |
spin_lock(&inode->i_lock); |
8e821cad1 NFS: clean up the... |
1055 1056 1057 1058 1059 1060 1061 1062 1063 1064 1065 1066 |
if (test_bit(PG_NEED_RESCHED, &req->wb_flags)) { /* Do nothing we need to resend the writes */ } else if (!test_and_set_bit(PG_NEED_COMMIT, &req->wb_flags)) { memcpy(&req->wb_verf, &data->verf, sizeof(req->wb_verf)); dprintk(" defer commit "); } else if (memcmp(&req->wb_verf, &data->verf, sizeof(req->wb_verf))) { set_bit(PG_NEED_RESCHED, &req->wb_flags); clear_bit(PG_NEED_COMMIT, &req->wb_flags); dprintk(" server reboot detected "); } |
587142f85 NFS: Replace NFS_... |
1067 |
spin_unlock(&inode->i_lock); |
8e821cad1 NFS: clean up the... |
1068 1069 1070 1071 1072 |
} else dprintk(" OK "); out: |
1da177e4c Linux-2.6.12-rc2 |
1073 |
if (atomic_dec_and_test(&req->wb_complete)) |
a861a1e1c NFSv4.1: add gene... |
1074 |
nfs_writepage_release(req, data); |
c9d8f89d9 NFS: Ensure that ... |
1075 |
nfs_writedata_release(calldata); |
1da177e4c Linux-2.6.12-rc2 |
1076 |
} |
def6ed7ef nfs41 write seque... |
1077 1078 1079 1080 |
#if defined(CONFIG_NFS_V4_1) void nfs_write_prepare(struct rpc_task *task, void *calldata) { struct nfs_write_data *data = calldata; |
def6ed7ef nfs41 write seque... |
1081 |
|
035168ab3 NFSv4.1: Make nfs... |
1082 1083 |
if (nfs4_setup_sequence(NFS_SERVER(data->inode), &data->args.seq_args, |
def6ed7ef nfs41 write seque... |
1084 1085 1086 1087 1088 |
&data->res.seq_res, 1, task)) return; rpc_call_start(task); } #endif /* CONFIG_NFS_V4_1 */ |
788e7a89a NFS: Cleanup of N... |
1089 |
static const struct rpc_call_ops nfs_write_partial_ops = { |
def6ed7ef nfs41 write seque... |
1090 1091 1092 |
#if defined(CONFIG_NFS_V4_1) .rpc_call_prepare = nfs_write_prepare, #endif /* CONFIG_NFS_V4_1 */ |
788e7a89a NFS: Cleanup of N... |
1093 |
.rpc_call_done = nfs_writeback_done_partial, |
c9d8f89d9 NFS: Ensure that ... |
1094 |
.rpc_release = nfs_writeback_release_partial, |
788e7a89a NFS: Cleanup of N... |
1095 |
}; |
1da177e4c Linux-2.6.12-rc2 |
1096 1097 1098 1099 1100 1101 1102 |
/* * Handle a write reply that flushes a whole page. * * FIXME: There is an inherent race with invalidate_inode_pages and * writebacks since the page->count is kept > 1 for as long * as the page has a write request pending. */ |
788e7a89a NFS: Cleanup of N... |
1103 |
static void nfs_writeback_done_full(struct rpc_task *task, void *calldata) |
1da177e4c Linux-2.6.12-rc2 |
1104 |
{ |
788e7a89a NFS: Cleanup of N... |
1105 |
struct nfs_write_data *data = calldata; |
1da177e4c Linux-2.6.12-rc2 |
1106 |
|
c9d8f89d9 NFS: Ensure that ... |
1107 1108 1109 1110 1111 1112 |
nfs_writeback_done(task, data); } static void nfs_writeback_release_full(void *calldata) { struct nfs_write_data *data = calldata; |
e2fecb215 NFS: Remove pNFS ... |
1113 |
int status = data->task.tk_status; |
788e7a89a NFS: Cleanup of N... |
1114 |
|
1da177e4c Linux-2.6.12-rc2 |
1115 1116 |
/* Update attributes as result of writeback. */ while (!list_empty(&data->pages)) { |
c9d8f89d9 NFS: Ensure that ... |
1117 1118 |
struct nfs_page *req = nfs_list_entry(data->pages.next); struct page *page = req->wb_page; |
1da177e4c Linux-2.6.12-rc2 |
1119 |
nfs_list_remove_request(req); |
1da177e4c Linux-2.6.12-rc2 |
1120 |
|
48186c7d5 NFS: Fix trace de... |
1121 1122 |
dprintk("NFS: %5u write (%s/%lld %d@%lld)", data->task.tk_pid, |
3d4ff43d8 nfs_open_context ... |
1123 1124 |
req->wb_context->dentry->d_inode->i_sb->s_id, (long long)NFS_FILEID(req->wb_context->dentry->d_inode), |
1da177e4c Linux-2.6.12-rc2 |
1125 1126 |
req->wb_bytes, (long long)req_offset(req)); |
c9d8f89d9 NFS: Ensure that ... |
1127 |
if (status < 0) { |
a301b7777 NFS: Don't use Cl... |
1128 |
nfs_set_pageerror(page); |
c9d8f89d9 NFS: Ensure that ... |
1129 1130 1131 |
nfs_context_set_write_error(req->wb_context, status); dprintk(", error = %d ", status); |
8e821cad1 NFS: clean up the... |
1132 |
goto remove_request; |
1da177e4c Linux-2.6.12-rc2 |
1133 |
} |
1da177e4c Linux-2.6.12-rc2 |
1134 |
|
8e821cad1 NFS: clean up the... |
1135 1136 |
if (nfs_write_need_commit(data)) { memcpy(&req->wb_verf, &data->verf, sizeof(req->wb_verf)); |
a861a1e1c NFSv4.1: add gene... |
1137 |
nfs_mark_request_commit(req, data->lseg); |
8e821cad1 NFS: clean up the... |
1138 1139 |
dprintk(" marked for commit "); |
1da177e4c Linux-2.6.12-rc2 |
1140 1141 |
goto next; } |
8e821cad1 NFS: clean up the... |
1142 1143 1144 |
dprintk(" OK "); remove_request: |
1da177e4c Linux-2.6.12-rc2 |
1145 |
nfs_inode_remove_request(req); |
1da177e4c Linux-2.6.12-rc2 |
1146 |
next: |
9fd367f0f NFS cleanup: Rena... |
1147 |
nfs_clear_page_tag_locked(req); |
a6305ddb0 NFS: Fix a race w... |
1148 |
nfs_end_page_writeback(page); |
1da177e4c Linux-2.6.12-rc2 |
1149 |
} |
c9d8f89d9 NFS: Ensure that ... |
1150 |
nfs_writedata_release(calldata); |
1da177e4c Linux-2.6.12-rc2 |
1151 |
} |
788e7a89a NFS: Cleanup of N... |
1152 |
static const struct rpc_call_ops nfs_write_full_ops = { |
def6ed7ef nfs41 write seque... |
1153 1154 1155 |
#if defined(CONFIG_NFS_V4_1) .rpc_call_prepare = nfs_write_prepare, #endif /* CONFIG_NFS_V4_1 */ |
788e7a89a NFS: Cleanup of N... |
1156 |
.rpc_call_done = nfs_writeback_done_full, |
c9d8f89d9 NFS: Ensure that ... |
1157 |
.rpc_release = nfs_writeback_release_full, |
788e7a89a NFS: Cleanup of N... |
1158 |
}; |
1da177e4c Linux-2.6.12-rc2 |
1159 1160 1161 |
/* * This function is called when the WRITE call is complete. */ |
136028967 NFS: change nfs_w... |
1162 |
void nfs_writeback_done(struct rpc_task *task, struct nfs_write_data *data) |
1da177e4c Linux-2.6.12-rc2 |
1163 |
{ |
1da177e4c Linux-2.6.12-rc2 |
1164 1165 |
struct nfs_writeargs *argp = &data->args; struct nfs_writeres *resp = &data->res; |
788e7a89a NFS: Cleanup of N... |
1166 |
int status; |
1da177e4c Linux-2.6.12-rc2 |
1167 |
|
a3f565b1e NFS: fix print fo... |
1168 1169 |
dprintk("NFS: %5u nfs_writeback_done (status %d) ", |
1da177e4c Linux-2.6.12-rc2 |
1170 |
task->tk_pid, task->tk_status); |
f551e44ff NFS: add comments... |
1171 1172 1173 1174 1175 1176 1177 |
/* * ->write_done will attempt to use post-op attributes to detect * conflicting writes by other clients. A strict interpretation * of close-to-open would allow us to continue caching even if * another writer had changed the file, but some applications * depend on tighter cache coherency when writing. */ |
788e7a89a NFS: Cleanup of N... |
1178 1179 |
status = NFS_PROTO(data->inode)->write_done(task, data); if (status != 0) |
136028967 NFS: change nfs_w... |
1180 |
return; |
91d5b4702 NFS: add I/O perf... |
1181 |
nfs_add_stats(data->inode, NFSIOS_SERVERWRITTENBYTES, resp->count); |
1da177e4c Linux-2.6.12-rc2 |
1182 1183 1184 1185 1186 1187 1188 1189 1190 1191 1192 |
#if defined(CONFIG_NFS_V3) || defined(CONFIG_NFS_V4) if (resp->verf->committed < argp->stable && task->tk_status >= 0) { /* We tried a write call, but the server did not * commit data to stable storage even though we * requested it. * Note: There is a known bug in Tru64 < 5.0 in which * the server reports NFS_DATA_SYNC, but performs * NFS_FILE_SYNC. We therefore implement this checking * as a dprintk() in order to avoid filling syslog. */ static unsigned long complain; |
a69aef149 NFSv4.1: pnfs fil... |
1193 |
/* Note this will print the MDS for a DS write */ |
1da177e4c Linux-2.6.12-rc2 |
1194 |
if (time_before(complain, jiffies)) { |
48186c7d5 NFS: Fix trace de... |
1195 |
dprintk("NFS: faulty NFS server %s:" |
1da177e4c Linux-2.6.12-rc2 |
1196 1197 |
" (committed = %d) != (stable = %d) ", |
2b72c9ccd nfs: Remove unuse... |
1198 |
NFS_SERVER(data->inode)->nfs_client->cl_hostname, |
1da177e4c Linux-2.6.12-rc2 |
1199 1200 1201 1202 1203 1204 1205 1206 |
resp->verf->committed, argp->stable); complain = jiffies + 300 * HZ; } } #endif /* Is this a short write? */ if (task->tk_status >= 0 && resp->count < argp->count) { static unsigned long complain; |
91d5b4702 NFS: add I/O perf... |
1207 |
nfs_inc_stats(data->inode, NFSIOS_SHORTWRITE); |
1da177e4c Linux-2.6.12-rc2 |
1208 1209 1210 1211 1212 |
/* Has the server at least made some progress? */ if (resp->count != 0) { /* Was this an NFSv2 write or an NFSv3 stable write? */ if (resp->verf->committed != NFS_UNSTABLE) { /* Resend from where the server left off */ |
a69aef149 NFSv4.1: pnfs fil... |
1213 |
data->mds_offset += resp->count; |
1da177e4c Linux-2.6.12-rc2 |
1214 1215 1216 1217 1218 1219 1220 1221 1222 |
argp->offset += resp->count; argp->pgbase += resp->count; argp->count -= resp->count; } else { /* Resend as a stable write in order to avoid * headaches in the case of a server crash. */ argp->stable = NFS_FILE_SYNC; } |
d00c5d438 NFS: Get rid of n... |
1223 |
rpc_restart_call_prepare(task); |
136028967 NFS: change nfs_w... |
1224 |
return; |
1da177e4c Linux-2.6.12-rc2 |
1225 1226 1227 1228 1229 1230 1231 1232 1233 1234 1235 |
} if (time_before(complain, jiffies)) { printk(KERN_WARNING "NFS: Server wrote zero bytes, expected %u. ", argp->count); complain = jiffies + 300 * HZ; } /* Can't do anything about it except throw an error. */ task->tk_status = -EIO; } |
136028967 NFS: change nfs_w... |
1236 |
return; |
1da177e4c Linux-2.6.12-rc2 |
1237 1238 1239 1240 |
} #if defined(CONFIG_NFS_V3) || defined(CONFIG_NFS_V4) |
71d0a6112 NFS: Fix an unsta... |
1241 1242 |
static int nfs_commit_set_lock(struct nfs_inode *nfsi, int may_wait) { |
b8413f98f NFS: Fix a hang/i... |
1243 |
int ret; |
71d0a6112 NFS: Fix an unsta... |
1244 1245 |
if (!test_and_set_bit(NFS_INO_COMMIT, &nfsi->flags)) return 1; |
b8413f98f NFS: Fix a hang/i... |
1246 1247 1248 1249 1250 1251 1252 |
if (!may_wait) return 0; ret = out_of_line_wait_on_bit_lock(&nfsi->flags, NFS_INO_COMMIT, nfs_wait_bit_killable, TASK_KILLABLE); return (ret < 0) ? ret : 1; |
71d0a6112 NFS: Fix an unsta... |
1253 |
} |
e0c2b3801 NFSv4.1: filelayo... |
1254 |
void nfs_commit_clear_lock(struct nfs_inode *nfsi) |
71d0a6112 NFS: Fix an unsta... |
1255 1256 1257 1258 1259 |
{ clear_bit(NFS_INO_COMMIT, &nfsi->flags); smp_mb__after_clear_bit(); wake_up_bit(&nfsi->flags, NFS_INO_COMMIT); } |
e0c2b3801 NFSv4.1: filelayo... |
1260 |
EXPORT_SYMBOL_GPL(nfs_commit_clear_lock); |
71d0a6112 NFS: Fix an unsta... |
1261 |
|
e0c2b3801 NFSv4.1: filelayo... |
1262 |
void nfs_commitdata_release(void *data) |
1da177e4c Linux-2.6.12-rc2 |
1263 |
{ |
383ba7193 NFS: Fix a deadlo... |
1264 |
struct nfs_write_data *wdata = data; |
988b6dceb NFSv4.1: remove G... |
1265 |
put_lseg(wdata->lseg); |
383ba7193 NFS: Fix a deadlo... |
1266 |
put_nfs_open_context(wdata->args.context); |
1da177e4c Linux-2.6.12-rc2 |
1267 1268 |
nfs_commit_free(wdata); } |
e0c2b3801 NFSv4.1: filelayo... |
1269 |
EXPORT_SYMBOL_GPL(nfs_commitdata_release); |
1da177e4c Linux-2.6.12-rc2 |
1270 |
|
e0c2b3801 NFSv4.1: filelayo... |
1271 |
int nfs_initiate_commit(struct nfs_write_data *data, struct rpc_clnt *clnt, |
9ace33cdc NFSv4.1: rearrang... |
1272 1273 |
const struct rpc_call_ops *call_ops, int how) |
1da177e4c Linux-2.6.12-rc2 |
1274 |
{ |
077376919 NFS/SUNRPC: Conve... |
1275 |
struct rpc_task *task; |
9ace33cdc NFSv4.1: rearrang... |
1276 |
int priority = flush_task_priority(how); |
bdc7f021f NFS: Clean up the... |
1277 1278 1279 |
struct rpc_message msg = { .rpc_argp = &data->args, .rpc_resp = &data->res, |
9ace33cdc NFSv4.1: rearrang... |
1280 |
.rpc_cred = data->cred, |
bdc7f021f NFS: Clean up the... |
1281 |
}; |
84115e1cd SUNRPC: Cleanup o... |
1282 |
struct rpc_task_setup task_setup_data = { |
077376919 NFS/SUNRPC: Conve... |
1283 |
.task = &data->task, |
9ace33cdc NFSv4.1: rearrang... |
1284 |
.rpc_client = clnt, |
bdc7f021f NFS: Clean up the... |
1285 |
.rpc_message = &msg, |
9ace33cdc NFSv4.1: rearrang... |
1286 |
.callback_ops = call_ops, |
84115e1cd SUNRPC: Cleanup o... |
1287 |
.callback_data = data, |
101070ca2 NFS: Ensure that ... |
1288 |
.workqueue = nfsiod_workqueue, |
2c61be0a9 NFS: Ensure that ... |
1289 |
.flags = RPC_TASK_ASYNC, |
3ff7576dd SUNRPC: Clean up ... |
1290 |
.priority = priority, |
84115e1cd SUNRPC: Cleanup o... |
1291 |
}; |
9ace33cdc NFSv4.1: rearrang... |
1292 1293 1294 1295 1296 1297 1298 1299 1300 1301 1302 1303 1304 1305 |
/* Set up the initial task struct. */ NFS_PROTO(data->inode)->commit_setup(data, &msg); dprintk("NFS: %5u initiated commit call ", data->task.tk_pid); task = rpc_run_task(&task_setup_data); if (IS_ERR(task)) return PTR_ERR(task); if (how & FLUSH_SYNC) rpc_wait_for_completion_task(task); rpc_put_task(task); return 0; } |
e0c2b3801 NFSv4.1: filelayo... |
1306 |
EXPORT_SYMBOL_GPL(nfs_initiate_commit); |
9ace33cdc NFSv4.1: rearrang... |
1307 1308 1309 1310 |
/* * Set up the argument/result storage required for the RPC call. */ |
e0c2b3801 NFSv4.1: filelayo... |
1311 |
void nfs_init_commit(struct nfs_write_data *data, |
988b6dceb NFSv4.1: remove G... |
1312 1313 |
struct list_head *head, struct pnfs_layout_segment *lseg) |
9ace33cdc NFSv4.1: rearrang... |
1314 1315 |
{ struct nfs_page *first = nfs_list_entry(head->next); |
3d4ff43d8 nfs_open_context ... |
1316 |
struct inode *inode = first->wb_context->dentry->d_inode; |
1da177e4c Linux-2.6.12-rc2 |
1317 1318 1319 1320 1321 |
/* Set up the RPC argument and reply structs * NB: take care not to mess about with data->commit et al. */ list_splice_init(head, &data->pages); |
1da177e4c Linux-2.6.12-rc2 |
1322 |
|
1da177e4c Linux-2.6.12-rc2 |
1323 |
data->inode = inode; |
9ace33cdc NFSv4.1: rearrang... |
1324 |
data->cred = first->wb_context->cred; |
988b6dceb NFSv4.1: remove G... |
1325 |
data->lseg = lseg; /* reference transferred */ |
9ace33cdc NFSv4.1: rearrang... |
1326 |
data->mds_ops = &nfs_commit_ops; |
1da177e4c Linux-2.6.12-rc2 |
1327 1328 |
data->args.fh = NFS_FH(data->inode); |
3da28eb1c [PATCH] NFS: Repl... |
1329 1330 1331 |
/* Note: we always request a commit of the entire inode */ data->args.offset = 0; data->args.count = 0; |
383ba7193 NFS: Fix a deadlo... |
1332 |
data->args.context = get_nfs_open_context(first->wb_context); |
3da28eb1c [PATCH] NFS: Repl... |
1333 |
data->res.count = 0; |
1da177e4c Linux-2.6.12-rc2 |
1334 1335 |
data->res.fattr = &data->fattr; data->res.verf = &data->verf; |
0e574af1b NFS: Cleanup init... |
1336 |
nfs_fattr_init(&data->fattr); |
1da177e4c Linux-2.6.12-rc2 |
1337 |
} |
e0c2b3801 NFSv4.1: filelayo... |
1338 |
EXPORT_SYMBOL_GPL(nfs_init_commit); |
1da177e4c Linux-2.6.12-rc2 |
1339 |
|
e0c2b3801 NFSv4.1: filelayo... |
1340 |
void nfs_retry_commit(struct list_head *page_list, |
a861a1e1c NFSv4.1: add gene... |
1341 |
struct pnfs_layout_segment *lseg) |
64bfeb49b NFSv4.1: pull err... |
1342 1343 1344 1345 1346 1347 |
{ struct nfs_page *req; while (!list_empty(page_list)) { req = nfs_list_entry(page_list->next); nfs_list_remove_request(req); |
a861a1e1c NFSv4.1: add gene... |
1348 |
nfs_mark_request_commit(req, lseg); |
64bfeb49b NFSv4.1: pull err... |
1349 1350 1351 1352 1353 1354 |
dec_zone_page_state(req->wb_page, NR_UNSTABLE_NFS); dec_bdi_stat(req->wb_page->mapping->backing_dev_info, BDI_RECLAIMABLE); nfs_clear_page_tag_locked(req); } } |
e0c2b3801 NFSv4.1: filelayo... |
1355 |
EXPORT_SYMBOL_GPL(nfs_retry_commit); |
64bfeb49b NFSv4.1: pull err... |
1356 |
|
1da177e4c Linux-2.6.12-rc2 |
1357 1358 1359 1360 |
/* * Commit dirty pages */ static int |
40859d7ee NFS: support larg... |
1361 |
nfs_commit_list(struct inode *inode, struct list_head *head, int how) |
1da177e4c Linux-2.6.12-rc2 |
1362 1363 |
{ struct nfs_write_data *data; |
1da177e4c Linux-2.6.12-rc2 |
1364 |
|
c9d8f89d9 NFS: Ensure that ... |
1365 |
data = nfs_commitdata_alloc(); |
1da177e4c Linux-2.6.12-rc2 |
1366 1367 1368 1369 1370 |
if (!data) goto out_bad; /* Set up the argument struct */ |
988b6dceb NFSv4.1: remove G... |
1371 |
nfs_init_commit(data, head, NULL); |
9ace33cdc NFSv4.1: rearrang... |
1372 |
return nfs_initiate_commit(data, NFS_CLIENT(inode), data->mds_ops, how); |
1da177e4c Linux-2.6.12-rc2 |
1373 |
out_bad: |
a861a1e1c NFSv4.1: add gene... |
1374 |
nfs_retry_commit(head, NULL); |
71d0a6112 NFS: Fix an unsta... |
1375 |
nfs_commit_clear_lock(NFS_I(inode)); |
1da177e4c Linux-2.6.12-rc2 |
1376 1377 1378 1379 1380 1381 |
return -ENOMEM; } /* * COMMIT call returned */ |
788e7a89a NFS: Cleanup of N... |
1382 |
static void nfs_commit_done(struct rpc_task *task, void *calldata) |
1da177e4c Linux-2.6.12-rc2 |
1383 |
{ |
963d8fe53 RPC: Clean up RPC... |
1384 |
struct nfs_write_data *data = calldata; |
1da177e4c Linux-2.6.12-rc2 |
1385 |
|
a3f565b1e NFS: fix print fo... |
1386 1387 |
dprintk("NFS: %5u nfs_commit_done (status %d) ", |
1da177e4c Linux-2.6.12-rc2 |
1388 |
task->tk_pid, task->tk_status); |
788e7a89a NFS: Cleanup of N... |
1389 |
/* Call the NFS version-specific code */ |
c0d0e96b8 NFS: Get rid of p... |
1390 |
NFS_PROTO(data->inode)->commit_done(task, data); |
c9d8f89d9 NFS: Ensure that ... |
1391 |
} |
e0c2b3801 NFSv4.1: filelayo... |
1392 |
void nfs_commit_release_pages(struct nfs_write_data *data) |
c9d8f89d9 NFS: Ensure that ... |
1393 |
{ |
5917ce844 NFSv4.1: pull out... |
1394 |
struct nfs_page *req; |
c9d8f89d9 NFS: Ensure that ... |
1395 |
int status = data->task.tk_status; |
788e7a89a NFS: Cleanup of N... |
1396 |
|
1da177e4c Linux-2.6.12-rc2 |
1397 1398 1399 |
while (!list_empty(&data->pages)) { req = nfs_list_entry(data->pages.next); nfs_list_remove_request(req); |
e468bae97 NFS: Allow redirt... |
1400 |
nfs_clear_request_commit(req); |
1da177e4c Linux-2.6.12-rc2 |
1401 |
|
48186c7d5 NFS: Fix trace de... |
1402 |
dprintk("NFS: commit (%s/%lld %d@%lld)", |
3d4ff43d8 nfs_open_context ... |
1403 1404 |
req->wb_context->dentry->d_sb->s_id, (long long)NFS_FILEID(req->wb_context->dentry->d_inode), |
1da177e4c Linux-2.6.12-rc2 |
1405 1406 |
req->wb_bytes, (long long)req_offset(req)); |
c9d8f89d9 NFS: Ensure that ... |
1407 1408 |
if (status < 0) { nfs_context_set_write_error(req->wb_context, status); |
1da177e4c Linux-2.6.12-rc2 |
1409 |
nfs_inode_remove_request(req); |
c9d8f89d9 NFS: Ensure that ... |
1410 1411 |
dprintk(", error = %d ", status); |
1da177e4c Linux-2.6.12-rc2 |
1412 1413 1414 1415 1416 1417 1418 1419 1420 1421 1422 1423 1424 1425 1426 |
goto next; } /* Okay, COMMIT succeeded, apparently. Check the verifier * returned by the server against all stored verfs. */ if (!memcmp(req->wb_verf.verifier, data->verf.verifier, sizeof(data->verf.verifier))) { /* We have a match */ nfs_inode_remove_request(req); dprintk(" OK "); goto next; } /* We have a mismatch. Write the page again */ dprintk(" mismatch "); |
6d884e8fc nfs: nfs_redirty_... |
1427 |
nfs_mark_request_dirty(req); |
1da177e4c Linux-2.6.12-rc2 |
1428 |
next: |
9fd367f0f NFS cleanup: Rena... |
1429 |
nfs_clear_page_tag_locked(req); |
1da177e4c Linux-2.6.12-rc2 |
1430 |
} |
5917ce844 NFSv4.1: pull out... |
1431 |
} |
e0c2b3801 NFSv4.1: filelayo... |
1432 |
EXPORT_SYMBOL_GPL(nfs_commit_release_pages); |
5917ce844 NFSv4.1: pull out... |
1433 1434 1435 1436 1437 1438 |
static void nfs_commit_release(void *calldata) { struct nfs_write_data *data = calldata; nfs_commit_release_pages(data); |
71d0a6112 NFS: Fix an unsta... |
1439 |
nfs_commit_clear_lock(NFS_I(data->inode)); |
c9d8f89d9 NFS: Ensure that ... |
1440 |
nfs_commitdata_release(calldata); |
1da177e4c Linux-2.6.12-rc2 |
1441 |
} |
788e7a89a NFS: Cleanup of N... |
1442 1443 |
static const struct rpc_call_ops nfs_commit_ops = { |
21d9a851a nfs41 commit sequ... |
1444 1445 1446 |
#if defined(CONFIG_NFS_V4_1) .rpc_call_prepare = nfs_write_prepare, #endif /* CONFIG_NFS_V4_1 */ |
788e7a89a NFS: Cleanup of N... |
1447 1448 1449 |
.rpc_call_done = nfs_commit_done, .rpc_release = nfs_commit_release, }; |
1da177e4c Linux-2.6.12-rc2 |
1450 |
|
b608b283a NFS: kswapd must ... |
1451 |
int nfs_commit_inode(struct inode *inode, int how) |
1da177e4c Linux-2.6.12-rc2 |
1452 |
{ |
1da177e4c Linux-2.6.12-rc2 |
1453 |
LIST_HEAD(head); |
71d0a6112 NFS: Fix an unsta... |
1454 |
int may_wait = how & FLUSH_SYNC; |
b8413f98f NFS: Fix a hang/i... |
1455 |
int res; |
1da177e4c Linux-2.6.12-rc2 |
1456 |
|
b8413f98f NFS: Fix a hang/i... |
1457 1458 |
res = nfs_commit_set_lock(NFS_I(inode), may_wait); if (res <= 0) |
c5efa5fc9 NFS: Ensure that ... |
1459 |
goto out_mark_dirty; |
3da28eb1c [PATCH] NFS: Repl... |
1460 |
res = nfs_scan_commit(inode, &head, 0, 0); |
1da177e4c Linux-2.6.12-rc2 |
1461 |
if (res) { |
a861a1e1c NFSv4.1: add gene... |
1462 1463 1464 1465 1466 |
int error; error = pnfs_commit_list(inode, &head, how); if (error == PNFS_NOT_ATTEMPTED) error = nfs_commit_list(inode, &head, how); |
3da28eb1c [PATCH] NFS: Repl... |
1467 1468 |
if (error < 0) return error; |
b8413f98f NFS: Fix a hang/i... |
1469 |
if (!may_wait) |
c5efa5fc9 NFS: Ensure that ... |
1470 |
goto out_mark_dirty; |
b8413f98f NFS: Fix a hang/i... |
1471 1472 1473 1474 1475 1476 |
error = wait_on_bit(&NFS_I(inode)->flags, NFS_INO_COMMIT, nfs_wait_bit_killable, TASK_KILLABLE); if (error < 0) return error; |
71d0a6112 NFS: Fix an unsta... |
1477 1478 |
} else nfs_commit_clear_lock(NFS_I(inode)); |
c5efa5fc9 NFS: Ensure that ... |
1479 1480 1481 1482 1483 1484 1485 1486 |
return res; /* Note: If we exit without ensuring that the commit is complete, * we must mark the inode as dirty. Otherwise, future calls to * sync_inode() with the WB_SYNC_ALL flag set will fail to ensure * that the data is on the disk. */ out_mark_dirty: __mark_inode_dirty(inode, I_DIRTY_DATASYNC); |
1da177e4c Linux-2.6.12-rc2 |
1487 1488 |
return res; } |
8fc795f70 NFS: Cleanup - mo... |
1489 1490 1491 |
static int nfs_commit_unstable_pages(struct inode *inode, struct writeback_control *wbc) { |
420e3646b NFS: Reduce the n... |
1492 1493 1494 |
struct nfs_inode *nfsi = NFS_I(inode); int flags = FLUSH_SYNC; int ret = 0; |
8fc795f70 NFS: Cleanup - mo... |
1495 |
|
3236c3e1a nfs: don't redirt... |
1496 1497 1498 |
/* no commits means nothing needs to be done */ if (!nfsi->ncommit) return ret; |
a00dd6c03 NFS: don't use FL... |
1499 1500 1501 1502 1503 1504 |
if (wbc->sync_mode == WB_SYNC_NONE) { /* Don't commit yet if this is a non-blocking flush and there * are a lot of outstanding writes for this mapping. */ if (nfsi->ncommit <= (nfsi->npages >> 1)) goto out_mark_dirty; |
420e3646b NFS: Reduce the n... |
1505 |
|
a00dd6c03 NFS: don't use FL... |
1506 |
/* don't wait for the COMMIT response */ |
420e3646b NFS: Reduce the n... |
1507 |
flags = 0; |
a00dd6c03 NFS: don't use FL... |
1508 |
} |
420e3646b NFS: Reduce the n... |
1509 1510 1511 1512 1513 1514 1515 1516 |
ret = nfs_commit_inode(inode, flags); if (ret >= 0) { if (wbc->sync_mode == WB_SYNC_NONE) { if (ret < wbc->nr_to_write) wbc->nr_to_write -= ret; else wbc->nr_to_write = 0; } |
8fc795f70 NFS: Cleanup - mo... |
1517 |
return 0; |
420e3646b NFS: Reduce the n... |
1518 1519 |
} out_mark_dirty: |
8fc795f70 NFS: Cleanup - mo... |
1520 1521 1522 |
__mark_inode_dirty(inode, I_DIRTY_DATASYNC); return ret; } |
c63c7b051 NFS: Fix a race w... |
1523 |
#else |
8fc795f70 NFS: Cleanup - mo... |
1524 1525 1526 1527 |
static int nfs_commit_unstable_pages(struct inode *inode, struct writeback_control *wbc) { return 0; } |
1da177e4c Linux-2.6.12-rc2 |
1528 |
#endif |
8fc795f70 NFS: Cleanup - mo... |
1529 1530 |
int nfs_write_inode(struct inode *inode, struct writeback_control *wbc) { |
863a3c6c6 NFSv4.1: layoutco... |
1531 1532 1533 1534 |
int ret; ret = nfs_commit_unstable_pages(inode, wbc); if (ret >= 0 && test_bit(NFS_INO_LAYOUTCOMMIT, &NFS_I(inode)->flags)) { |
ef3115378 NFSv4.1 convert l... |
1535 1536 |
int status; bool sync = true; |
863a3c6c6 NFSv4.1: layoutco... |
1537 |
|
846d5a091 writeback: remove... |
1538 |
if (wbc->sync_mode == WB_SYNC_NONE) |
ef3115378 NFSv4.1 convert l... |
1539 |
sync = false; |
863a3c6c6 NFSv4.1: layoutco... |
1540 1541 1542 1543 1544 1545 |
status = pnfs_layoutcommit_inode(inode, sync); if (status < 0) return status; } return ret; |
8fc795f70 NFS: Cleanup - mo... |
1546 |
} |
acdc53b21 NFS: Replace __nf... |
1547 1548 1549 1550 |
/* * flush the inode to disk. */ int nfs_wb_all(struct inode *inode) |
34901f70d NFS: Writeback op... |
1551 1552 |
{ struct writeback_control wbc = { |
72cb77f4a NFS: Throttle pag... |
1553 |
.sync_mode = WB_SYNC_ALL, |
34901f70d NFS: Writeback op... |
1554 |
.nr_to_write = LONG_MAX, |
d7fb12077 NFS: Don't use ra... |
1555 1556 |
.range_start = 0, .range_end = LLONG_MAX, |
34901f70d NFS: Writeback op... |
1557 |
}; |
34901f70d NFS: Writeback op... |
1558 |
|
acdc53b21 NFS: Replace __nf... |
1559 |
return sync_inode(inode, &wbc); |
1c75950b9 NFS: cleanup of n... |
1560 |
} |
1b3b4a1a2 NFS: Fix a write ... |
1561 1562 1563 |
int nfs_wb_page_cancel(struct inode *inode, struct page *page) { struct nfs_page *req; |
1b3b4a1a2 NFS: Fix a write ... |
1564 1565 1566 1567 |
int ret = 0; BUG_ON(!PageLocked(page)); for (;;) { |
ba8b06e67 NFS: Ensure that ... |
1568 |
wait_on_page_writeback(page); |
1b3b4a1a2 NFS: Fix a write ... |
1569 1570 |
req = nfs_page_find_request(page); if (req == NULL) |
1b3b4a1a2 NFS: Fix a write ... |
1571 |
break; |
1b3b4a1a2 NFS: Fix a write ... |
1572 1573 1574 1575 1576 1577 1578 1579 1580 1581 1582 |
if (nfs_lock_request_dontget(req)) { nfs_inode_remove_request(req); /* * In case nfs_inode_remove_request has marked the * page as being dirty */ cancel_dirty_page(page, PAGE_CACHE_SIZE); nfs_unlock_request(req); break; } ret = nfs_wait_on_request(req); |
c9edda714 NFS: Fix a refere... |
1583 |
nfs_release_request(req); |
1b3b4a1a2 NFS: Fix a write ... |
1584 |
if (ret < 0) |
c988950eb NFS: Simplify nfs... |
1585 |
break; |
1b3b4a1a2 NFS: Fix a write ... |
1586 |
} |
1b3b4a1a2 NFS: Fix a write ... |
1587 1588 |
return ret; } |
7f2f12d96 NFS: Simplify nfs... |
1589 1590 1591 1592 |
/* * Write back all requests on one page - we do this before reading it. */ int nfs_wb_page(struct inode *inode, struct page *page) |
1c75950b9 NFS: cleanup of n... |
1593 1594 1595 |
{ loff_t range_start = page_offset(page); loff_t range_end = range_start + (loff_t)(PAGE_CACHE_SIZE - 1); |
4d770ccf4 NFS: Ensure that ... |
1596 |
struct writeback_control wbc = { |
4d770ccf4 NFS: Ensure that ... |
1597 |
.sync_mode = WB_SYNC_ALL, |
7f2f12d96 NFS: Simplify nfs... |
1598 |
.nr_to_write = 0, |
4d770ccf4 NFS: Ensure that ... |
1599 1600 1601 1602 |
.range_start = range_start, .range_end = range_end, }; int ret; |
1c75950b9 NFS: cleanup of n... |
1603 |
|
0522f6ade NFS: Fix another ... |
1604 |
for (;;) { |
ba8b06e67 NFS: Ensure that ... |
1605 |
wait_on_page_writeback(page); |
73e3302f6 NFS: Fix nfs_wb_p... |
1606 1607 1608 1609 |
if (clear_page_dirty_for_io(page)) { ret = nfs_writepage_locked(page, &wbc); if (ret < 0) goto out_error; |
0522f6ade NFS: Fix another ... |
1610 |
continue; |
7f2f12d96 NFS: Simplify nfs... |
1611 |
} |
0522f6ade NFS: Fix another ... |
1612 1613 1614 |
if (!PagePrivate(page)) break; ret = nfs_commit_inode(inode, FLUSH_SYNC); |
ba8b06e67 NFS: Ensure that ... |
1615 |
if (ret < 0) |
73e3302f6 NFS: Fix nfs_wb_p... |
1616 |
goto out_error; |
7f2f12d96 NFS: Simplify nfs... |
1617 |
} |
73e3302f6 NFS: Fix nfs_wb_p... |
1618 1619 |
return 0; out_error: |
4d770ccf4 NFS: Ensure that ... |
1620 |
return ret; |
1c75950b9 NFS: cleanup of n... |
1621 |
} |
074cc1dee NFS: Add a ->migr... |
1622 1623 |
#ifdef CONFIG_MIGRATION int nfs_migrate_page(struct address_space *mapping, struct page *newpage, |
a6bc32b89 mm: compaction: i... |
1624 |
struct page *page, enum migrate_mode mode) |
074cc1dee NFS: Add a ->migr... |
1625 |
{ |
2da956523 nfs: don't try to... |
1626 1627 1628 1629 1630 1631 1632 1633 1634 1635 |
/* * If PagePrivate is set, then the page is currently associated with * an in-progress read or write request. Don't try to migrate it. * * FIXME: we could do this in principle, but we'll need a way to ensure * that we can safely release the inode reference while holding * the page lock. */ if (PagePrivate(page)) return -EBUSY; |
074cc1dee NFS: Add a ->migr... |
1636 |
|
7549ad5f9 NFS: Remove a red... |
1637 |
nfs_fscache_release_page(page, GFP_KERNEL); |
074cc1dee NFS: Add a ->migr... |
1638 |
|
a6bc32b89 mm: compaction: i... |
1639 |
return migrate_page(mapping, newpage, page, mode); |
074cc1dee NFS: Add a ->migr... |
1640 1641 |
} #endif |
f7b422b17 NFS: Split fs/nfs... |
1642 |
int __init nfs_init_writepagecache(void) |
1da177e4c Linux-2.6.12-rc2 |
1643 1644 1645 1646 |
{ nfs_wdata_cachep = kmem_cache_create("nfs_write_data", sizeof(struct nfs_write_data), 0, SLAB_HWCACHE_ALIGN, |
20c2df83d mm: Remove slab d... |
1647 |
NULL); |
1da177e4c Linux-2.6.12-rc2 |
1648 1649 |
if (nfs_wdata_cachep == NULL) return -ENOMEM; |
93d2341c7 [PATCH] mempool: ... |
1650 1651 |
nfs_wdata_mempool = mempool_create_slab_pool(MIN_POOL_WRITE, nfs_wdata_cachep); |
1da177e4c Linux-2.6.12-rc2 |
1652 1653 |
if (nfs_wdata_mempool == NULL) return -ENOMEM; |
93d2341c7 [PATCH] mempool: ... |
1654 1655 |
nfs_commit_mempool = mempool_create_slab_pool(MIN_POOL_COMMIT, nfs_wdata_cachep); |
1da177e4c Linux-2.6.12-rc2 |
1656 1657 |
if (nfs_commit_mempool == NULL) return -ENOMEM; |
89a09141d [PATCH] nfs: fix ... |
1658 1659 1660 1661 1662 1663 1664 1665 1666 1667 1668 1669 1670 1671 1672 1673 1674 1675 1676 |
/* * NFS congestion size, scale with available memory. * * 64MB: 8192k * 128MB: 11585k * 256MB: 16384k * 512MB: 23170k * 1GB: 32768k * 2GB: 46340k * 4GB: 65536k * 8GB: 92681k * 16GB: 131072k * * This allows larger machines to have larger/more transfers. * Limit the default to 256M */ nfs_congestion_kb = (16*int_sqrt(totalram_pages)) << (PAGE_SHIFT-10); if (nfs_congestion_kb > 256*1024) nfs_congestion_kb = 256*1024; |
1da177e4c Linux-2.6.12-rc2 |
1677 1678 |
return 0; } |
266bee886 [PATCH] fix stati... |
1679 |
void nfs_destroy_writepagecache(void) |
1da177e4c Linux-2.6.12-rc2 |
1680 1681 1682 |
{ mempool_destroy(nfs_commit_mempool); mempool_destroy(nfs_wdata_mempool); |
1a1d92c10 [PATCH] Really ig... |
1683 |
kmem_cache_destroy(nfs_wdata_cachep); |
1da177e4c Linux-2.6.12-rc2 |
1684 |
} |