aboutsummaryrefslogtreecommitdiffstats
path: root/fs
diff options
context:
space:
mode:
Diffstat (limited to 'fs')
-rw-r--r--fs/nfs/write.c68
1 files changed, 24 insertions, 44 deletions
diff --git a/fs/nfs/write.c b/fs/nfs/write.c
index 74e86601d978..de9a16a8f7e4 100644
--- a/fs/nfs/write.c
+++ b/fs/nfs/write.c
@@ -75,7 +75,6 @@
75 * Local function declarations 75 * Local function declarations
76 */ 76 */
77static struct nfs_page * nfs_update_request(struct nfs_open_context*, 77static struct nfs_page * nfs_update_request(struct nfs_open_context*,
78 struct inode *,
79 struct page *, 78 struct page *,
80 unsigned int, unsigned int); 79 unsigned int, unsigned int);
81static int nfs_wait_on_write_congestion(struct address_space *, int); 80static int nfs_wait_on_write_congestion(struct address_space *, int);
@@ -215,10 +214,10 @@ static void nfs_mark_uptodate(struct page *page, unsigned int base, unsigned int
215 * Write a page synchronously. 214 * Write a page synchronously.
216 * Offset is the data offset within the page. 215 * Offset is the data offset within the page.
217 */ 216 */
218static int nfs_writepage_sync(struct nfs_open_context *ctx, struct inode *inode, 217static int nfs_writepage_sync(struct nfs_open_context *ctx, struct page *page,
219 struct page *page, unsigned int offset, unsigned int count, 218 unsigned int offset, unsigned int count, int how)
220 int how)
221{ 219{
220 struct inode *inode = page->mapping->host;
222 unsigned int wsize = NFS_SERVER(inode)->wsize; 221 unsigned int wsize = NFS_SERVER(inode)->wsize;
223 int result, written = 0; 222 int result, written = 0;
224 struct nfs_write_data *wdata; 223 struct nfs_write_data *wdata;
@@ -283,15 +282,23 @@ io_error:
283 return written ? written : result; 282 return written ? written : result;
284} 283}
285 284
286static int nfs_writepage_async(struct nfs_open_context *ctx, 285static int nfs_writepage_setup(struct nfs_open_context *ctx, struct page *page,
287 struct inode *inode, struct page *page,
288 unsigned int offset, unsigned int count) 286 unsigned int offset, unsigned int count)
289{ 287{
290 struct nfs_page *req; 288 struct nfs_page *req;
289 int ret;
291 290
292 req = nfs_update_request(ctx, inode, page, offset, count); 291 for (;;) {
293 if (IS_ERR(req)) 292 req = nfs_update_request(ctx, page, offset, count);
294 return PTR_ERR(req); 293 if (!IS_ERR(req))
294 break;
295 ret = PTR_ERR(req);
296 if (ret != -EBUSY)
297 return ret;
298 ret = nfs_wb_page(page->mapping->host, page);
299 if (ret != 0)
300 return ret;
301 }
295 /* Update file length */ 302 /* Update file length */
296 nfs_grow_file(page, offset, count); 303 nfs_grow_file(page, offset, count);
297 /* Set the PG_uptodate flag? */ 304 /* Set the PG_uptodate flag? */
@@ -317,14 +324,13 @@ int nfs_writepage(struct page *page, struct writeback_control *wbc)
317 struct nfs_open_context *ctx; 324 struct nfs_open_context *ctx;
318 struct inode *inode = page->mapping->host; 325 struct inode *inode = page->mapping->host;
319 unsigned offset; 326 unsigned offset;
320 int priority = wb_priority(wbc);
321 int err; 327 int err;
322 328
323 nfs_inc_stats(inode, NFSIOS_VFSWRITEPAGE); 329 nfs_inc_stats(inode, NFSIOS_VFSWRITEPAGE);
324 nfs_add_stats(inode, NFSIOS_WRITEPAGES, 1); 330 nfs_add_stats(inode, NFSIOS_WRITEPAGES, 1);
325 331
326 /* Ensure we've flushed out any previous writes */ 332 /* Ensure we've flushed out any previous writes */
327 nfs_wb_page_priority(inode, page, priority); 333 nfs_wb_page_priority(inode, page, wb_priority(wbc));
328 334
329 err = 0; 335 err = 0;
330 offset = nfs_page_length(page); 336 offset = nfs_page_length(page);
@@ -338,12 +344,11 @@ int nfs_writepage(struct page *page, struct writeback_control *wbc)
338 } 344 }
339 lock_kernel(); 345 lock_kernel();
340 if (!IS_SYNC(inode)) { 346 if (!IS_SYNC(inode)) {
341 err = nfs_writepage_async(ctx, inode, page, 0, offset); 347 err = nfs_writepage_setup(ctx, page, 0, offset);
342 if (!wbc->for_writepages) 348 if (!wbc->for_writepages)
343 nfs_flush_mapping(page->mapping, wbc, wb_priority(wbc)); 349 nfs_flush_mapping(page->mapping, wbc, wb_priority(wbc));
344 } else { 350 } else {
345 err = nfs_writepage_sync(ctx, inode, page, 0, 351 err = nfs_writepage_sync(ctx, page, 0, offset, wb_priority(wbc));
346 offset, priority);
347 if (err >= 0) { 352 if (err >= 0) {
348 if (err != offset) 353 if (err != offset)
349 redirty_page_for_writepage(wbc, page); 354 redirty_page_for_writepage(wbc, page);
@@ -643,17 +648,16 @@ static int nfs_wait_on_write_congestion(struct address_space *mapping, int intr)
643 * Note: Should always be called with the Page Lock held! 648 * Note: Should always be called with the Page Lock held!
644 */ 649 */
645static struct nfs_page * nfs_update_request(struct nfs_open_context* ctx, 650static struct nfs_page * nfs_update_request(struct nfs_open_context* ctx,
646 struct inode *inode, struct page *page, 651 struct page *page, unsigned int offset, unsigned int bytes)
647 unsigned int offset, unsigned int bytes)
648{ 652{
649 struct nfs_server *server = NFS_SERVER(inode); 653 struct inode *inode = page->mapping->host;
650 struct nfs_inode *nfsi = NFS_I(inode); 654 struct nfs_inode *nfsi = NFS_I(inode);
651 struct nfs_page *req, *new = NULL; 655 struct nfs_page *req, *new = NULL;
652 unsigned long rqend, end; 656 unsigned long rqend, end;
653 657
654 end = offset + bytes; 658 end = offset + bytes;
655 659
656 if (nfs_wait_on_write_congestion(page->mapping, server->flags & NFS_MOUNT_INTR)) 660 if (nfs_wait_on_write_congestion(page->mapping, NFS_SERVER(inode)->flags & NFS_MOUNT_INTR))
657 return ERR_PTR(-ERESTARTSYS); 661 return ERR_PTR(-ERESTARTSYS);
658 for (;;) { 662 for (;;) {
659 /* Loop over all inode entries and see if we find 663 /* Loop over all inode entries and see if we find
@@ -764,7 +768,6 @@ int nfs_updatepage(struct file *file, struct page *page,
764{ 768{
765 struct nfs_open_context *ctx = (struct nfs_open_context *)file->private_data; 769 struct nfs_open_context *ctx = (struct nfs_open_context *)file->private_data;
766 struct inode *inode = page->mapping->host; 770 struct inode *inode = page->mapping->host;
767 struct nfs_page *req;
768 int status = 0; 771 int status = 0;
769 772
770 nfs_inc_stats(inode, NFSIOS_VFSUPDATEPAGE); 773 nfs_inc_stats(inode, NFSIOS_VFSUPDATEPAGE);
@@ -775,7 +778,7 @@ int nfs_updatepage(struct file *file, struct page *page,
775 (long long)(page_offset(page) +offset)); 778 (long long)(page_offset(page) +offset));
776 779
777 if (IS_SYNC(inode)) { 780 if (IS_SYNC(inode)) {
778 status = nfs_writepage_sync(ctx, inode, page, offset, count, 0); 781 status = nfs_writepage_sync(ctx, page, offset, count, 0);
779 if (status > 0) { 782 if (status > 0) {
780 if (offset == 0 && status == PAGE_CACHE_SIZE) 783 if (offset == 0 && status == PAGE_CACHE_SIZE)
781 SetPageUptodate(page); 784 SetPageUptodate(page);
@@ -793,31 +796,8 @@ int nfs_updatepage(struct file *file, struct page *page,
793 offset = 0; 796 offset = 0;
794 } 797 }
795 798
796 /* 799 status = nfs_writepage_setup(ctx, page, offset, count);
797 * Try to find an NFS request corresponding to this page
798 * and update it.
799 * If the existing request cannot be updated, we must flush
800 * it out now.
801 */
802 do {
803 req = nfs_update_request(ctx, inode, page, offset, count);
804 status = (IS_ERR(req)) ? PTR_ERR(req) : 0;
805 if (status != -EBUSY)
806 break;
807 /* Request could not be updated. Flush it out and try again */
808 status = nfs_wb_page(inode, page);
809 } while (status >= 0);
810 if (status < 0)
811 goto done;
812
813 status = 0;
814 800
815 /* Update file length */
816 nfs_grow_file(page, offset, count);
817 /* Set the PG_uptodate flag? */
818 nfs_mark_uptodate(page, req->wb_pgbase, req->wb_bytes);
819 nfs_unlock_request(req);
820done:
821 dprintk("NFS: nfs_updatepage returns %d (isize %Ld)\n", 801 dprintk("NFS: nfs_updatepage returns %d (isize %Ld)\n",
822 status, (long long)i_size_read(inode)); 802 status, (long long)i_size_read(inode));
823 if (status < 0) 803 if (status < 0)