diff options
Diffstat (limited to 'fs/gfs2/file.c')
-rw-r--r-- | fs/gfs2/file.c | 77 |
1 files changed, 45 insertions, 32 deletions
diff --git a/fs/gfs2/file.c b/fs/gfs2/file.c index 7cfdcb913363..4074b952b059 100644 --- a/fs/gfs2/file.c +++ b/fs/gfs2/file.c | |||
@@ -448,15 +448,20 @@ static int gfs2_mmap(struct file *file, struct vm_area_struct *vma) | |||
448 | { | 448 | { |
449 | struct gfs2_inode *ip = GFS2_I(file->f_mapping->host); | 449 | struct gfs2_inode *ip = GFS2_I(file->f_mapping->host); |
450 | 450 | ||
451 | if (!(file->f_flags & O_NOATIME)) { | 451 | if (!(file->f_flags & O_NOATIME) && |
452 | !IS_NOATIME(&ip->i_inode)) { | ||
452 | struct gfs2_holder i_gh; | 453 | struct gfs2_holder i_gh; |
453 | int error; | 454 | int error; |
454 | 455 | ||
455 | gfs2_holder_init(ip->i_gl, LM_ST_EXCLUSIVE, 0, &i_gh); | 456 | gfs2_holder_init(ip->i_gl, LM_ST_SHARED, LM_FLAG_ANY, &i_gh); |
456 | error = gfs2_glock_nq(&i_gh); | 457 | error = gfs2_glock_nq(&i_gh); |
457 | file_accessed(file); | 458 | if (error == 0) { |
458 | if (error == 0) | 459 | file_accessed(file); |
459 | gfs2_glock_dq_uninit(&i_gh); | 460 | gfs2_glock_dq(&i_gh); |
461 | } | ||
462 | gfs2_holder_uninit(&i_gh); | ||
463 | if (error) | ||
464 | return error; | ||
460 | } | 465 | } |
461 | vma->vm_ops = &gfs2_vm_ops; | 466 | vma->vm_ops = &gfs2_vm_ops; |
462 | vma->vm_flags |= VM_CAN_NONLINEAR; | 467 | vma->vm_flags |= VM_CAN_NONLINEAR; |
@@ -617,8 +622,7 @@ static void empty_write_end(struct page *page, unsigned from, | |||
617 | { | 622 | { |
618 | struct gfs2_inode *ip = GFS2_I(page->mapping->host); | 623 | struct gfs2_inode *ip = GFS2_I(page->mapping->host); |
619 | 624 | ||
620 | page_zero_new_buffers(page, from, to); | 625 | zero_user(page, from, to-from); |
621 | flush_dcache_page(page); | ||
622 | mark_page_accessed(page); | 626 | mark_page_accessed(page); |
623 | 627 | ||
624 | if (!gfs2_is_writeback(ip)) | 628 | if (!gfs2_is_writeback(ip)) |
@@ -627,36 +631,43 @@ static void empty_write_end(struct page *page, unsigned from, | |||
627 | block_commit_write(page, from, to); | 631 | block_commit_write(page, from, to); |
628 | } | 632 | } |
629 | 633 | ||
630 | static int write_empty_blocks(struct page *page, unsigned from, unsigned to) | 634 | static int needs_empty_write(sector_t block, struct inode *inode) |
631 | { | 635 | { |
632 | unsigned start, end, next; | ||
633 | struct buffer_head *bh, *head; | ||
634 | int error; | 636 | int error; |
637 | struct buffer_head bh_map = { .b_state = 0, .b_blocknr = 0 }; | ||
635 | 638 | ||
636 | if (!page_has_buffers(page)) { | 639 | bh_map.b_size = 1 << inode->i_blkbits; |
637 | error = __block_write_begin(page, from, to - from, gfs2_block_map); | 640 | error = gfs2_block_map(inode, block, &bh_map, 0); |
638 | if (unlikely(error)) | 641 | if (unlikely(error)) |
639 | return error; | 642 | return error; |
643 | return !buffer_mapped(&bh_map); | ||
644 | } | ||
640 | 645 | ||
641 | empty_write_end(page, from, to); | 646 | static int write_empty_blocks(struct page *page, unsigned from, unsigned to) |
642 | return 0; | 647 | { |
643 | } | 648 | struct inode *inode = page->mapping->host; |
649 | unsigned start, end, next, blksize; | ||
650 | sector_t block = page->index << (PAGE_CACHE_SHIFT - inode->i_blkbits); | ||
651 | int ret; | ||
644 | 652 | ||
645 | bh = head = page_buffers(page); | 653 | blksize = 1 << inode->i_blkbits; |
646 | next = end = 0; | 654 | next = end = 0; |
647 | while (next < from) { | 655 | while (next < from) { |
648 | next += bh->b_size; | 656 | next += blksize; |
649 | bh = bh->b_this_page; | 657 | block++; |
650 | } | 658 | } |
651 | start = next; | 659 | start = next; |
652 | do { | 660 | do { |
653 | next += bh->b_size; | 661 | next += blksize; |
654 | if (buffer_mapped(bh)) { | 662 | ret = needs_empty_write(block, inode); |
663 | if (unlikely(ret < 0)) | ||
664 | return ret; | ||
665 | if (ret == 0) { | ||
655 | if (end) { | 666 | if (end) { |
656 | error = __block_write_begin(page, start, end - start, | 667 | ret = __block_write_begin(page, start, end - start, |
657 | gfs2_block_map); | 668 | gfs2_block_map); |
658 | if (unlikely(error)) | 669 | if (unlikely(ret)) |
659 | return error; | 670 | return ret; |
660 | empty_write_end(page, start, end); | 671 | empty_write_end(page, start, end); |
661 | end = 0; | 672 | end = 0; |
662 | } | 673 | } |
@@ -664,13 +675,13 @@ static int write_empty_blocks(struct page *page, unsigned from, unsigned to) | |||
664 | } | 675 | } |
665 | else | 676 | else |
666 | end = next; | 677 | end = next; |
667 | bh = bh->b_this_page; | 678 | block++; |
668 | } while (next < to); | 679 | } while (next < to); |
669 | 680 | ||
670 | if (end) { | 681 | if (end) { |
671 | error = __block_write_begin(page, start, end - start, gfs2_block_map); | 682 | ret = __block_write_begin(page, start, end - start, gfs2_block_map); |
672 | if (unlikely(error)) | 683 | if (unlikely(ret)) |
673 | return error; | 684 | return ret; |
674 | empty_write_end(page, start, end); | 685 | empty_write_end(page, start, end); |
675 | } | 686 | } |
676 | 687 | ||
@@ -976,8 +987,10 @@ static void do_unflock(struct file *file, struct file_lock *fl) | |||
976 | 987 | ||
977 | mutex_lock(&fp->f_fl_mutex); | 988 | mutex_lock(&fp->f_fl_mutex); |
978 | flock_lock_file_wait(file, fl); | 989 | flock_lock_file_wait(file, fl); |
979 | if (fl_gh->gh_gl) | 990 | if (fl_gh->gh_gl) { |
980 | gfs2_glock_dq_uninit(fl_gh); | 991 | gfs2_glock_dq_wait(fl_gh); |
992 | gfs2_holder_uninit(fl_gh); | ||
993 | } | ||
981 | mutex_unlock(&fp->f_fl_mutex); | 994 | mutex_unlock(&fp->f_fl_mutex); |
982 | } | 995 | } |
983 | 996 | ||