aboutsummaryrefslogtreecommitdiffstats
path: root/fs/gfs2/ops_address.c
diff options
context:
space:
mode:
authorSteven Whitehouse <swhiteho@redhat.com>2007-10-16 04:25:07 -0400
committerLinus Torvalds <torvalds@woody.linux-foundation.org>2007-10-16 12:42:55 -0400
commit7765ec26ae1c01bb29bedf910e4efcced8cc81d2 (patch)
tree8ce0e877daf805e5e546f10b389cd1c686ec0365 /fs/gfs2/ops_address.c
parentd79689c7038ea07182e8d7340786f7fcf8c77780 (diff)
gfs2: convert to new aops
Cc: Nick Piggin <nickpiggin@yahoo.com.au> Cc: Steven Whitehouse <swhiteho@redhat.com> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Diffstat (limited to 'fs/gfs2/ops_address.c')
-rw-r--r--fs/gfs2/ops_address.c211
1 files changed, 127 insertions, 84 deletions
diff --git a/fs/gfs2/ops_address.c b/fs/gfs2/ops_address.c
index 873a511ef2be..9679f8b9870d 100644
--- a/fs/gfs2/ops_address.c
+++ b/fs/gfs2/ops_address.c
@@ -17,6 +17,7 @@
17#include <linux/mpage.h> 17#include <linux/mpage.h>
18#include <linux/fs.h> 18#include <linux/fs.h>
19#include <linux/writeback.h> 19#include <linux/writeback.h>
20#include <linux/swap.h>
20#include <linux/gfs2_ondisk.h> 21#include <linux/gfs2_ondisk.h>
21#include <linux/lm_interface.h> 22#include <linux/lm_interface.h>
22 23
@@ -349,45 +350,49 @@ out_unlock:
349} 350}
350 351
351/** 352/**
352 * gfs2_prepare_write - Prepare to write a page to a file 353 * gfs2_write_begin - Begin to write to a file
353 * @file: The file to write to 354 * @file: The file to write to
354 * @page: The page which is to be prepared for writing 355 * @mapping: The mapping in which to write
355 * @from: From (byte range within page) 356 * @pos: The file offset at which to start writing
356 * @to: To (byte range within page) 357 * @len: Length of the write
358 * @flags: Various flags
359 * @pagep: Pointer to return the page
360 * @fsdata: Pointer to return fs data (unused by GFS2)
357 * 361 *
358 * Returns: errno 362 * Returns: errno
359 */ 363 */
360 364
361static int gfs2_prepare_write(struct file *file, struct page *page, 365static int gfs2_write_begin(struct file *file, struct address_space *mapping,
362 unsigned from, unsigned to) 366 loff_t pos, unsigned len, unsigned flags,
367 struct page **pagep, void **fsdata)
363{ 368{
364 struct gfs2_inode *ip = GFS2_I(page->mapping->host); 369 struct gfs2_inode *ip = GFS2_I(mapping->host);
365 struct gfs2_sbd *sdp = GFS2_SB(page->mapping->host); 370 struct gfs2_sbd *sdp = GFS2_SB(mapping->host);
366 unsigned int data_blocks, ind_blocks, rblocks; 371 unsigned int data_blocks, ind_blocks, rblocks;
367 int alloc_required; 372 int alloc_required;
368 int error = 0; 373 int error = 0;
369 loff_t pos = ((loff_t)page->index << PAGE_CACHE_SHIFT) + from;
370 loff_t end = ((loff_t)page->index << PAGE_CACHE_SHIFT) + to;
371 struct gfs2_alloc *al; 374 struct gfs2_alloc *al;
372 unsigned int write_len = to - from; 375 pgoff_t index = pos >> PAGE_CACHE_SHIFT;
376 unsigned from = pos & (PAGE_CACHE_SIZE - 1);
377 unsigned to = from + len;
378 struct page *page;
373 379
374 380 gfs2_holder_init(ip->i_gl, LM_ST_EXCLUSIVE, GL_ATIME, &ip->i_gh);
375 gfs2_holder_init(ip->i_gl, LM_ST_EXCLUSIVE, GL_ATIME|LM_FLAG_TRY_1CB, &ip->i_gh);
376 error = gfs2_glock_nq_atime(&ip->i_gh); 381 error = gfs2_glock_nq_atime(&ip->i_gh);
377 if (unlikely(error)) { 382 if (unlikely(error))
378 if (error == GLR_TRYFAILED) {
379 unlock_page(page);
380 error = AOP_TRUNCATED_PAGE;
381 yield();
382 }
383 goto out_uninit; 383 goto out_uninit;
384 }
385 384
386 gfs2_write_calc_reserv(ip, write_len, &data_blocks, &ind_blocks); 385 error = -ENOMEM;
386 page = __grab_cache_page(mapping, index);
387 *pagep = page;
388 if (!page)
389 goto out_unlock;
390
391 gfs2_write_calc_reserv(ip, len, &data_blocks, &ind_blocks);
387 392
388 error = gfs2_write_alloc_required(ip, pos, write_len, &alloc_required); 393 error = gfs2_write_alloc_required(ip, pos, len, &alloc_required);
389 if (error) 394 if (error)
390 goto out_unlock; 395 goto out_putpage;
391 396
392 397
393 ip->i_alloc.al_requested = 0; 398 ip->i_alloc.al_requested = 0;
@@ -420,7 +425,7 @@ static int gfs2_prepare_write(struct file *file, struct page *page,
420 goto out_trans_fail; 425 goto out_trans_fail;
421 426
422 if (gfs2_is_stuffed(ip)) { 427 if (gfs2_is_stuffed(ip)) {
423 if (end > sdp->sd_sb.sb_bsize - sizeof(struct gfs2_dinode)) { 428 if (pos + len > sdp->sd_sb.sb_bsize - sizeof(struct gfs2_dinode)) {
424 error = gfs2_unstuff_dinode(ip, page); 429 error = gfs2_unstuff_dinode(ip, page);
425 if (error == 0) 430 if (error == 0)
426 goto prepare_write; 431 goto prepare_write;
@@ -443,6 +448,10 @@ out_qunlock:
443out_alloc_put: 448out_alloc_put:
444 gfs2_alloc_put(ip); 449 gfs2_alloc_put(ip);
445 } 450 }
451out_putpage:
452 page_cache_release(page);
453 if (pos + len > ip->i_inode.i_size)
454 vmtruncate(&ip->i_inode, ip->i_inode.i_size);
446out_unlock: 455out_unlock:
447 gfs2_glock_dq_m(1, &ip->i_gh); 456 gfs2_glock_dq_m(1, &ip->i_gh);
448out_uninit: 457out_uninit:
@@ -478,65 +487,117 @@ static void adjust_fs_space(struct inode *inode)
478} 487}
479 488
480/** 489/**
481 * gfs2_commit_write - Commit write to a file 490 * gfs2_stuffed_write_end - Write end for stuffed files
491 * @inode: The inode
492 * @dibh: The buffer_head containing the on-disk inode
493 * @pos: The file position
494 * @len: The length of the write
495 * @copied: How much was actually copied by the VFS
496 * @page: The page
497 *
498 * This copies the data from the page into the inode block after
499 * the inode data structure itself.
500 *
501 * Returns: errno
502 */
503static int gfs2_stuffed_write_end(struct inode *inode, struct buffer_head *dibh,
504 loff_t pos, unsigned len, unsigned copied,
505 struct page *page)
506{
507 struct gfs2_inode *ip = GFS2_I(inode);
508 struct gfs2_sbd *sdp = GFS2_SB(inode);
509 u64 to = pos + copied;
510 void *kaddr;
511 unsigned char *buf = dibh->b_data + sizeof(struct gfs2_dinode);
512 struct gfs2_dinode *di = (struct gfs2_dinode *)dibh->b_data;
513
514 BUG_ON((pos + len) > (dibh->b_size - sizeof(struct gfs2_dinode)));
515 kaddr = kmap_atomic(page, KM_USER0);
516 memcpy(buf + pos, kaddr + pos, copied);
517 memset(kaddr + pos + copied, 0, len - copied);
518 flush_dcache_page(page);
519 kunmap_atomic(kaddr, KM_USER0);
520
521 if (!PageUptodate(page))
522 SetPageUptodate(page);
523 unlock_page(page);
524 page_cache_release(page);
525
526 if (inode->i_size < to) {
527 i_size_write(inode, to);
528 ip->i_di.di_size = inode->i_size;
529 di->di_size = cpu_to_be64(inode->i_size);
530 mark_inode_dirty(inode);
531 }
532
533 if (inode == sdp->sd_rindex)
534 adjust_fs_space(inode);
535
536 brelse(dibh);
537 gfs2_trans_end(sdp);
538 gfs2_glock_dq(&ip->i_gh);
539 gfs2_holder_uninit(&ip->i_gh);
540 return copied;
541}
542
543/**
544 * gfs2_write_end
482 * @file: The file to write to 545 * @file: The file to write to
483 * @page: The page containing the data 546 * @mapping: The address space to write to
484 * @from: From (byte range within page) 547 * @pos: The file position
485 * @to: To (byte range within page) 548 * @len: The length of the data
549 * @copied:
550 * @page: The page that has been written
551 * @fsdata: The fsdata (unused in GFS2)
552 *
553 * The main write_end function for GFS2. We have a separate one for
554 * stuffed files as they are slightly different, otherwise we just
555 * put our locking around the VFS provided functions.
486 * 556 *
487 * Returns: errno 557 * Returns: errno
488 */ 558 */
489 559
490static int gfs2_commit_write(struct file *file, struct page *page, 560static int gfs2_write_end(struct file *file, struct address_space *mapping,
491 unsigned from, unsigned to) 561 loff_t pos, unsigned len, unsigned copied,
562 struct page *page, void *fsdata)
492{ 563{
493 struct inode *inode = page->mapping->host; 564 struct inode *inode = page->mapping->host;
494 struct gfs2_inode *ip = GFS2_I(inode); 565 struct gfs2_inode *ip = GFS2_I(inode);
495 struct gfs2_sbd *sdp = GFS2_SB(inode); 566 struct gfs2_sbd *sdp = GFS2_SB(inode);
496 int error = -EOPNOTSUPP;
497 struct buffer_head *dibh; 567 struct buffer_head *dibh;
498 struct gfs2_alloc *al = &ip->i_alloc; 568 struct gfs2_alloc *al = &ip->i_alloc;
499 struct gfs2_dinode *di; 569 struct gfs2_dinode *di;
570 unsigned int from = pos & (PAGE_CACHE_SIZE - 1);
571 unsigned int to = from + len;
572 int ret;
500 573
501 if (gfs2_assert_withdraw(sdp, gfs2_glock_is_locked_by_me(ip->i_gl))) 574 BUG_ON(gfs2_glock_is_locked_by_me(ip->i_gl) == 0);
502 goto fail_nounlock;
503 575
504 error = gfs2_meta_inode_buffer(ip, &dibh); 576 ret = gfs2_meta_inode_buffer(ip, &dibh);
505 if (error) 577 if (unlikely(ret)) {
506 goto fail_endtrans; 578 unlock_page(page);
579 page_cache_release(page);
580 goto failed;
581 }
507 582
508 gfs2_trans_add_bh(ip->i_gl, dibh, 1); 583 gfs2_trans_add_bh(ip->i_gl, dibh, 1);
509 di = (struct gfs2_dinode *)dibh->b_data;
510
511 if (gfs2_is_stuffed(ip)) {
512 u64 file_size;
513 void *kaddr;
514 584
515 file_size = ((u64)page->index << PAGE_CACHE_SHIFT) + to; 585 if (gfs2_is_stuffed(ip))
586 return gfs2_stuffed_write_end(inode, dibh, pos, len, copied, page);
516 587
517 kaddr = kmap_atomic(page, KM_USER0); 588 if (sdp->sd_args.ar_data == GFS2_DATA_ORDERED || gfs2_is_jdata(ip))
518 memcpy(dibh->b_data + sizeof(struct gfs2_dinode) + from, 589 gfs2_page_add_databufs(ip, page, from, to);
519 kaddr + from, to - from);
520 kunmap_atomic(kaddr, KM_USER0);
521 590
522 SetPageUptodate(page); 591 ret = generic_write_end(file, mapping, pos, len, copied, page, fsdata);
523 592
524 if (inode->i_size < file_size) { 593 if (likely(ret >= 0)) {
525 i_size_write(inode, file_size); 594 copied = ret;
595 if ((pos + copied) > inode->i_size) {
596 di = (struct gfs2_dinode *)dibh->b_data;
597 ip->i_di.di_size = inode->i_size;
598 di->di_size = cpu_to_be64(inode->i_size);
526 mark_inode_dirty(inode); 599 mark_inode_dirty(inode);
527 } 600 }
528 } else {
529 if (sdp->sd_args.ar_data == GFS2_DATA_ORDERED ||
530 gfs2_is_jdata(ip))
531 gfs2_page_add_databufs(ip, page, from, to);
532 error = generic_commit_write(file, page, from, to);
533 if (error)
534 goto fail;
535 }
536
537 if (ip->i_di.di_size < inode->i_size) {
538 ip->i_di.di_size = inode->i_size;
539 di->di_size = cpu_to_be64(inode->i_size);
540 } 601 }
541 602
542 if (inode == sdp->sd_rindex) 603 if (inode == sdp->sd_rindex)
@@ -544,33 +605,15 @@ static int gfs2_commit_write(struct file *file, struct page *page,
544 605
545 brelse(dibh); 606 brelse(dibh);
546 gfs2_trans_end(sdp); 607 gfs2_trans_end(sdp);
608failed:
547 if (al->al_requested) { 609 if (al->al_requested) {
548 gfs2_inplace_release(ip); 610 gfs2_inplace_release(ip);
549 gfs2_quota_unlock(ip); 611 gfs2_quota_unlock(ip);
550 gfs2_alloc_put(ip); 612 gfs2_alloc_put(ip);
551 } 613 }
552 unlock_page(page); 614 gfs2_glock_dq(&ip->i_gh);
553 gfs2_glock_dq_m(1, &ip->i_gh);
554 lock_page(page);
555 gfs2_holder_uninit(&ip->i_gh); 615 gfs2_holder_uninit(&ip->i_gh);
556 return 0; 616 return ret;
557
558fail:
559 brelse(dibh);
560fail_endtrans:
561 gfs2_trans_end(sdp);
562 if (al->al_requested) {
563 gfs2_inplace_release(ip);
564 gfs2_quota_unlock(ip);
565 gfs2_alloc_put(ip);
566 }
567 unlock_page(page);
568 gfs2_glock_dq_m(1, &ip->i_gh);
569 lock_page(page);
570 gfs2_holder_uninit(&ip->i_gh);
571fail_nounlock:
572 ClearPageUptodate(page);
573 return error;
574} 617}
575 618
576/** 619/**
@@ -799,8 +842,8 @@ const struct address_space_operations gfs2_file_aops = {
799 .readpage = gfs2_readpage, 842 .readpage = gfs2_readpage,
800 .readpages = gfs2_readpages, 843 .readpages = gfs2_readpages,
801 .sync_page = block_sync_page, 844 .sync_page = block_sync_page,
802 .prepare_write = gfs2_prepare_write, 845 .write_begin = gfs2_write_begin,
803 .commit_write = gfs2_commit_write, 846 .write_end = gfs2_write_end,
804 .set_page_dirty = gfs2_set_page_dirty, 847 .set_page_dirty = gfs2_set_page_dirty,
805 .bmap = gfs2_bmap, 848 .bmap = gfs2_bmap,
806 .invalidatepage = gfs2_invalidatepage, 849 .invalidatepage = gfs2_invalidatepage,