aboutsummaryrefslogtreecommitdiffstats
path: root/fs/nfs/file.c
diff options
context:
space:
mode:
authorNick Piggin <npiggin@suse.de>2007-10-16 04:25:16 -0400
committerLinus Torvalds <torvalds@woody.linux-foundation.org>2007-10-16 12:42:57 -0400
commit4899f9c852564ce7b6d0ca932ac6674bf471fd28 (patch)
tree4248794207b9b82077f48ce08655a018d89d2683 /fs/nfs/file.c
parenta20fa20c549ed569885d871f689a59cfd2f6ff77 (diff)
nfs: convert to new aops
[akpm@linux-foundation.org: fix against git-nfs] [peterz@infradead.org: fix against git-nfs] Signed-off-by: Nick Piggin <npiggin@suse.de> Acked-by: Trond Myklebust <Trond.Myklebust@netapp.com> Cc: "J. Bruce Fields" <bfields@fieldses.org> Cc: Peter Zijlstra <a.p.zijlstra@chello.nl> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Diffstat (limited to 'fs/nfs/file.c')
-rw-r--r--fs/nfs/file.c80
1 files changed, 60 insertions, 20 deletions
diff --git a/fs/nfs/file.c b/fs/nfs/file.c
index 08c7c7387fce..d29f90d00aa2 100644
--- a/fs/nfs/file.c
+++ b/fs/nfs/file.c
@@ -306,27 +306,50 @@ nfs_fsync(struct file *file, struct dentry *dentry, int datasync)
306} 306}
307 307
308/* 308/*
309 * This does the "real" work of the write. The generic routine has 309 * This does the "real" work of the write. We must allocate and lock the
310 * allocated the page, locked it, done all the page alignment stuff 310 * page to be sent back to the generic routine, which then copies the
311 * calculations etc. Now we should just copy the data from user 311 * data from user space.
312 * space and write it back to the real medium..
313 * 312 *
314 * If the writer ends up delaying the write, the writer needs to 313 * If the writer ends up delaying the write, the writer needs to
315 * increment the page use counts until he is done with the page. 314 * increment the page use counts until he is done with the page.
316 */ 315 */
317static int nfs_prepare_write(struct file *file, struct page *page, unsigned offset, unsigned to) 316static int nfs_write_begin(struct file *file, struct address_space *mapping,
317 loff_t pos, unsigned len, unsigned flags,
318 struct page **pagep, void **fsdata)
318{ 319{
319 return nfs_flush_incompatible(file, page); 320 int ret;
321 pgoff_t index;
322 struct page *page;
323 index = pos >> PAGE_CACHE_SHIFT;
324
325 page = __grab_cache_page(mapping, index);
326 if (!page)
327 return -ENOMEM;
328 *pagep = page;
329
330 ret = nfs_flush_incompatible(file, page);
331 if (ret) {
332 unlock_page(page);
333 page_cache_release(page);
334 }
335 return ret;
320} 336}
321 337
322static int nfs_commit_write(struct file *file, struct page *page, unsigned offset, unsigned to) 338static int nfs_write_end(struct file *file, struct address_space *mapping,
339 loff_t pos, unsigned len, unsigned copied,
340 struct page *page, void *fsdata)
323{ 341{
324 long status; 342 unsigned offset = pos & (PAGE_CACHE_SIZE - 1);
343 int status;
325 344
326 lock_kernel(); 345 lock_kernel();
327 status = nfs_updatepage(file, page, offset, to-offset); 346 status = nfs_updatepage(file, page, offset, copied);
328 unlock_kernel(); 347 unlock_kernel();
329 return status; 348
349 unlock_page(page);
350 page_cache_release(page);
351
352 return status < 0 ? status : copied;
330} 353}
331 354
332static void nfs_invalidate_page(struct page *page, unsigned long offset) 355static void nfs_invalidate_page(struct page *page, unsigned long offset)
@@ -354,8 +377,8 @@ const struct address_space_operations nfs_file_aops = {
354 .set_page_dirty = __set_page_dirty_nobuffers, 377 .set_page_dirty = __set_page_dirty_nobuffers,
355 .writepage = nfs_writepage, 378 .writepage = nfs_writepage,
356 .writepages = nfs_writepages, 379 .writepages = nfs_writepages,
357 .prepare_write = nfs_prepare_write, 380 .write_begin = nfs_write_begin,
358 .commit_write = nfs_commit_write, 381 .write_end = nfs_write_end,
359 .invalidatepage = nfs_invalidate_page, 382 .invalidatepage = nfs_invalidate_page,
360 .releasepage = nfs_release_page, 383 .releasepage = nfs_release_page,
361#ifdef CONFIG_NFS_DIRECTIO 384#ifdef CONFIG_NFS_DIRECTIO
@@ -369,18 +392,35 @@ static int nfs_vm_page_mkwrite(struct vm_area_struct *vma, struct page *page)
369 struct file *filp = vma->vm_file; 392 struct file *filp = vma->vm_file;
370 unsigned pagelen; 393 unsigned pagelen;
371 int ret = -EINVAL; 394 int ret = -EINVAL;
395 void *fsdata;
396 struct address_space *mapping;
397 loff_t offset;
372 398
373 lock_page(page); 399 lock_page(page);
374 if (page->mapping != vma->vm_file->f_path.dentry->d_inode->i_mapping) 400 mapping = page->mapping;
375 goto out_unlock; 401 if (mapping != vma->vm_file->f_path.dentry->d_inode->i_mapping) {
402 unlock_page(page);
403 return -EINVAL;
404 }
376 pagelen = nfs_page_length(page); 405 pagelen = nfs_page_length(page);
377 if (pagelen == 0) 406 offset = (loff_t)page->index << PAGE_CACHE_SHIFT;
378 goto out_unlock;
379 ret = nfs_prepare_write(filp, page, 0, pagelen);
380 if (!ret)
381 ret = nfs_commit_write(filp, page, 0, pagelen);
382out_unlock:
383 unlock_page(page); 407 unlock_page(page);
408
409 /*
410 * we can use mapping after releasing the page lock, because:
411 * we hold mmap_sem on the fault path, which should pin the vma
412 * which should pin the file, which pins the dentry which should
413 * hold a reference on inode.
414 */
415
416 if (pagelen) {
417 struct page *page2 = NULL;
418 ret = nfs_write_begin(filp, mapping, offset, pagelen,
419 0, &page2, &fsdata);
420 if (!ret)
421 ret = nfs_write_end(filp, mapping, offset, pagelen,
422 pagelen, page2, fsdata);
423 }
384 return ret; 424 return ret;
385} 425}
386 426