diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2013-09-09 12:16:51 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2013-09-09 12:16:51 -0400 |
commit | 6c337ad6cccf3365c89152896217be9d953121c6 (patch) | |
tree | 9f679575b0025c9b279d733f77982cc4cb74b8ed /fs/gfs2 | |
parent | 6cccc7d3012344371a897ecdd1a1398286a6ee8a (diff) | |
parent | 0c9018097fe2966d80fe39e5c9ca94bb436ec369 (diff) |
Merge tag 'gfs2-merge-window' of git://git.kernel.org/pub/scm/linux/kernel/git/steve/gfs2-3.0-nmw
Pull GFS2 updates from Steven Whitehouse:
"This is possibly the smallest ever set of GFS2 patches for a merge
window. Also, most of them are bug fixes this time.
Two of my three patches (moving gfs2_sync_meta and merging the two
writepage implementations) are clean ups with the third (taking the
glock ref in examine_bucket) being a fix for a difficult to hit race
condition.
The removal of an unused memory barrier is a clean up from Bob
Peterson, and the "spectator" relates to a rarely used mount option.
Ben Marzinski's patch fixes a corner case where the incorrect inode
flags were being set, resulting in incorrect behaviour on fsync"
* tag 'gfs2-merge-window' of git://git.kernel.org/pub/scm/linux/kernel/git/steve/gfs2-3.0-nmw:
GFS2: dirty inode correctly in gfs2_write_end
GFS2: Don't flag consistency error if first mounter is a spectator
GFS2: Remove unnecessary memory barrier
GFS2: Merge ordered and writeback writepage
GFS2: Take glock reference in examine_bucket()
GFS2: Move gfs2_sync_meta to lops.c
Diffstat (limited to 'fs/gfs2')
-rw-r--r-- | fs/gfs2/aops.c | 44 | ||||
-rw-r--r-- | fs/gfs2/file.c | 4 | ||||
-rw-r--r-- | fs/gfs2/glock.c | 13 | ||||
-rw-r--r-- | fs/gfs2/lops.c | 18 | ||||
-rw-r--r-- | fs/gfs2/meta_io.c | 18 | ||||
-rw-r--r-- | fs/gfs2/meta_io.h | 26 | ||||
-rw-r--r-- | fs/gfs2/ops_fstype.c | 53 |
7 files changed, 99 insertions, 77 deletions
diff --git a/fs/gfs2/aops.c b/fs/gfs2/aops.c index ee48ad37d9c0..1f7d8057ea68 100644 --- a/fs/gfs2/aops.c +++ b/fs/gfs2/aops.c | |||
@@ -122,14 +122,13 @@ out: | |||
122 | } | 122 | } |
123 | 123 | ||
124 | /** | 124 | /** |
125 | * gfs2_writeback_writepage - Write page for writeback mappings | 125 | * gfs2_writepage - Write page for writeback mappings |
126 | * @page: The page | 126 | * @page: The page |
127 | * @wbc: The writeback control | 127 | * @wbc: The writeback control |
128 | * | 128 | * |
129 | */ | 129 | */ |
130 | 130 | ||
131 | static int gfs2_writeback_writepage(struct page *page, | 131 | static int gfs2_writepage(struct page *page, struct writeback_control *wbc) |
132 | struct writeback_control *wbc) | ||
133 | { | 132 | { |
134 | int ret; | 133 | int ret; |
135 | 134 | ||
@@ -141,32 +140,6 @@ static int gfs2_writeback_writepage(struct page *page, | |||
141 | } | 140 | } |
142 | 141 | ||
143 | /** | 142 | /** |
144 | * gfs2_ordered_writepage - Write page for ordered data files | ||
145 | * @page: The page to write | ||
146 | * @wbc: The writeback control | ||
147 | * | ||
148 | */ | ||
149 | |||
150 | static int gfs2_ordered_writepage(struct page *page, | ||
151 | struct writeback_control *wbc) | ||
152 | { | ||
153 | struct inode *inode = page->mapping->host; | ||
154 | struct gfs2_inode *ip = GFS2_I(inode); | ||
155 | int ret; | ||
156 | |||
157 | ret = gfs2_writepage_common(page, wbc); | ||
158 | if (ret <= 0) | ||
159 | return ret; | ||
160 | |||
161 | if (!page_has_buffers(page)) { | ||
162 | create_empty_buffers(page, inode->i_sb->s_blocksize, | ||
163 | (1 << BH_Dirty)|(1 << BH_Uptodate)); | ||
164 | } | ||
165 | gfs2_page_add_databufs(ip, page, 0, inode->i_sb->s_blocksize-1); | ||
166 | return block_write_full_page(page, gfs2_get_block_noalloc, wbc); | ||
167 | } | ||
168 | |||
169 | /** | ||
170 | * __gfs2_jdata_writepage - The core of jdata writepage | 143 | * __gfs2_jdata_writepage - The core of jdata writepage |
171 | * @page: The page to write | 144 | * @page: The page to write |
172 | * @wbc: The writeback control | 145 | * @wbc: The writeback control |
@@ -842,6 +815,8 @@ static int gfs2_write_end(struct file *file, struct address_space *mapping, | |||
842 | unsigned int from = pos & (PAGE_CACHE_SIZE - 1); | 815 | unsigned int from = pos & (PAGE_CACHE_SIZE - 1); |
843 | unsigned int to = from + len; | 816 | unsigned int to = from + len; |
844 | int ret; | 817 | int ret; |
818 | struct gfs2_trans *tr = current->journal_info; | ||
819 | BUG_ON(!tr); | ||
845 | 820 | ||
846 | BUG_ON(gfs2_glock_is_locked_by_me(ip->i_gl) == NULL); | 821 | BUG_ON(gfs2_glock_is_locked_by_me(ip->i_gl) == NULL); |
847 | 822 | ||
@@ -852,8 +827,6 @@ static int gfs2_write_end(struct file *file, struct address_space *mapping, | |||
852 | goto failed; | 827 | goto failed; |
853 | } | 828 | } |
854 | 829 | ||
855 | gfs2_trans_add_meta(ip->i_gl, dibh); | ||
856 | |||
857 | if (gfs2_is_stuffed(ip)) | 830 | if (gfs2_is_stuffed(ip)) |
858 | return gfs2_stuffed_write_end(inode, dibh, pos, len, copied, page); | 831 | return gfs2_stuffed_write_end(inode, dibh, pos, len, copied, page); |
859 | 832 | ||
@@ -861,6 +834,11 @@ static int gfs2_write_end(struct file *file, struct address_space *mapping, | |||
861 | gfs2_page_add_databufs(ip, page, from, to); | 834 | gfs2_page_add_databufs(ip, page, from, to); |
862 | 835 | ||
863 | ret = generic_write_end(file, mapping, pos, len, copied, page, fsdata); | 836 | ret = generic_write_end(file, mapping, pos, len, copied, page, fsdata); |
837 | if (tr->tr_num_buf_new) | ||
838 | __mark_inode_dirty(inode, I_DIRTY_DATASYNC); | ||
839 | else | ||
840 | gfs2_trans_add_meta(ip->i_gl, dibh); | ||
841 | |||
864 | 842 | ||
865 | if (inode == sdp->sd_rindex) { | 843 | if (inode == sdp->sd_rindex) { |
866 | adjust_fs_space(inode); | 844 | adjust_fs_space(inode); |
@@ -1107,7 +1085,7 @@ cannot_release: | |||
1107 | } | 1085 | } |
1108 | 1086 | ||
1109 | static const struct address_space_operations gfs2_writeback_aops = { | 1087 | static const struct address_space_operations gfs2_writeback_aops = { |
1110 | .writepage = gfs2_writeback_writepage, | 1088 | .writepage = gfs2_writepage, |
1111 | .writepages = gfs2_writepages, | 1089 | .writepages = gfs2_writepages, |
1112 | .readpage = gfs2_readpage, | 1090 | .readpage = gfs2_readpage, |
1113 | .readpages = gfs2_readpages, | 1091 | .readpages = gfs2_readpages, |
@@ -1123,7 +1101,7 @@ static const struct address_space_operations gfs2_writeback_aops = { | |||
1123 | }; | 1101 | }; |
1124 | 1102 | ||
1125 | static const struct address_space_operations gfs2_ordered_aops = { | 1103 | static const struct address_space_operations gfs2_ordered_aops = { |
1126 | .writepage = gfs2_ordered_writepage, | 1104 | .writepage = gfs2_writepage, |
1127 | .writepages = gfs2_writepages, | 1105 | .writepages = gfs2_writepages, |
1128 | .readpage = gfs2_readpage, | 1106 | .readpage = gfs2_readpage, |
1129 | .readpages = gfs2_readpages, | 1107 | .readpages = gfs2_readpages, |
diff --git a/fs/gfs2/file.c b/fs/gfs2/file.c index 72c3866a7320..0621b46d474d 100644 --- a/fs/gfs2/file.c +++ b/fs/gfs2/file.c | |||
@@ -650,7 +650,7 @@ static int gfs2_fsync(struct file *file, loff_t start, loff_t end, | |||
650 | { | 650 | { |
651 | struct address_space *mapping = file->f_mapping; | 651 | struct address_space *mapping = file->f_mapping; |
652 | struct inode *inode = mapping->host; | 652 | struct inode *inode = mapping->host; |
653 | int sync_state = inode->i_state & (I_DIRTY_SYNC|I_DIRTY_DATASYNC); | 653 | int sync_state = inode->i_state & I_DIRTY; |
654 | struct gfs2_inode *ip = GFS2_I(inode); | 654 | struct gfs2_inode *ip = GFS2_I(inode); |
655 | int ret = 0, ret1 = 0; | 655 | int ret = 0, ret1 = 0; |
656 | 656 | ||
@@ -660,6 +660,8 @@ static int gfs2_fsync(struct file *file, loff_t start, loff_t end, | |||
660 | return ret1; | 660 | return ret1; |
661 | } | 661 | } |
662 | 662 | ||
663 | if (!gfs2_is_jdata(ip)) | ||
664 | sync_state &= ~I_DIRTY_PAGES; | ||
663 | if (datasync) | 665 | if (datasync) |
664 | sync_state &= ~I_DIRTY_SYNC; | 666 | sync_state &= ~I_DIRTY_SYNC; |
665 | 667 | ||
diff --git a/fs/gfs2/glock.c b/fs/gfs2/glock.c index 544a809819c3..722329cac98f 100644 --- a/fs/gfs2/glock.c +++ b/fs/gfs2/glock.c | |||
@@ -1411,7 +1411,6 @@ __acquires(&lru_lock) | |||
1411 | if (demote_ok(gl)) | 1411 | if (demote_ok(gl)) |
1412 | handle_callback(gl, LM_ST_UNLOCKED, 0, false); | 1412 | handle_callback(gl, LM_ST_UNLOCKED, 0, false); |
1413 | WARN_ON(!test_and_clear_bit(GLF_LOCK, &gl->gl_flags)); | 1413 | WARN_ON(!test_and_clear_bit(GLF_LOCK, &gl->gl_flags)); |
1414 | smp_mb__after_clear_bit(); | ||
1415 | if (queue_delayed_work(glock_workqueue, &gl->gl_work, 0) == 0) | 1414 | if (queue_delayed_work(glock_workqueue, &gl->gl_work, 0) == 0) |
1416 | gfs2_glock_put_nolock(gl); | 1415 | gfs2_glock_put_nolock(gl); |
1417 | spin_unlock(&gl->gl_spin); | 1416 | spin_unlock(&gl->gl_spin); |
@@ -1488,7 +1487,7 @@ static void examine_bucket(glock_examiner examiner, const struct gfs2_sbd *sdp, | |||
1488 | 1487 | ||
1489 | rcu_read_lock(); | 1488 | rcu_read_lock(); |
1490 | hlist_bl_for_each_entry_rcu(gl, pos, head, gl_list) { | 1489 | hlist_bl_for_each_entry_rcu(gl, pos, head, gl_list) { |
1491 | if ((gl->gl_sbd == sdp) && atomic_read(&gl->gl_ref)) | 1490 | if ((gl->gl_sbd == sdp) && atomic_inc_not_zero(&gl->gl_ref)) |
1492 | examiner(gl); | 1491 | examiner(gl); |
1493 | } | 1492 | } |
1494 | rcu_read_unlock(); | 1493 | rcu_read_unlock(); |
@@ -1508,18 +1507,17 @@ static void glock_hash_walk(glock_examiner examiner, const struct gfs2_sbd *sdp) | |||
1508 | * thaw_glock - thaw out a glock which has an unprocessed reply waiting | 1507 | * thaw_glock - thaw out a glock which has an unprocessed reply waiting |
1509 | * @gl: The glock to thaw | 1508 | * @gl: The glock to thaw |
1510 | * | 1509 | * |
1511 | * N.B. When we freeze a glock, we leave a ref to the glock outstanding, | ||
1512 | * so this has to result in the ref count being dropped by one. | ||
1513 | */ | 1510 | */ |
1514 | 1511 | ||
1515 | static void thaw_glock(struct gfs2_glock *gl) | 1512 | static void thaw_glock(struct gfs2_glock *gl) |
1516 | { | 1513 | { |
1517 | if (!test_and_clear_bit(GLF_FROZEN, &gl->gl_flags)) | 1514 | if (!test_and_clear_bit(GLF_FROZEN, &gl->gl_flags)) |
1518 | return; | 1515 | goto out; |
1519 | set_bit(GLF_REPLY_PENDING, &gl->gl_flags); | 1516 | set_bit(GLF_REPLY_PENDING, &gl->gl_flags); |
1520 | gfs2_glock_hold(gl); | 1517 | if (queue_delayed_work(glock_workqueue, &gl->gl_work, 0) == 0) { |
1521 | if (queue_delayed_work(glock_workqueue, &gl->gl_work, 0) == 0) | 1518 | out: |
1522 | gfs2_glock_put(gl); | 1519 | gfs2_glock_put(gl); |
1520 | } | ||
1523 | } | 1521 | } |
1524 | 1522 | ||
1525 | /** | 1523 | /** |
@@ -1536,7 +1534,6 @@ static void clear_glock(struct gfs2_glock *gl) | |||
1536 | if (gl->gl_state != LM_ST_UNLOCKED) | 1534 | if (gl->gl_state != LM_ST_UNLOCKED) |
1537 | handle_callback(gl, LM_ST_UNLOCKED, 0, false); | 1535 | handle_callback(gl, LM_ST_UNLOCKED, 0, false); |
1538 | spin_unlock(&gl->gl_spin); | 1536 | spin_unlock(&gl->gl_spin); |
1539 | gfs2_glock_hold(gl); | ||
1540 | if (queue_delayed_work(glock_workqueue, &gl->gl_work, 0) == 0) | 1537 | if (queue_delayed_work(glock_workqueue, &gl->gl_work, 0) == 0) |
1541 | gfs2_glock_put(gl); | 1538 | gfs2_glock_put(gl); |
1542 | } | 1539 | } |
diff --git a/fs/gfs2/lops.c b/fs/gfs2/lops.c index 17c5b5d7dc88..010b9fb9fec6 100644 --- a/fs/gfs2/lops.c +++ b/fs/gfs2/lops.c | |||
@@ -579,6 +579,24 @@ static int buf_lo_scan_elements(struct gfs2_jdesc *jd, unsigned int start, | |||
579 | return error; | 579 | return error; |
580 | } | 580 | } |
581 | 581 | ||
582 | /** | ||
583 | * gfs2_meta_sync - Sync all buffers associated with a glock | ||
584 | * @gl: The glock | ||
585 | * | ||
586 | */ | ||
587 | |||
588 | static void gfs2_meta_sync(struct gfs2_glock *gl) | ||
589 | { | ||
590 | struct address_space *mapping = gfs2_glock2aspace(gl); | ||
591 | int error; | ||
592 | |||
593 | filemap_fdatawrite(mapping); | ||
594 | error = filemap_fdatawait(mapping); | ||
595 | |||
596 | if (error) | ||
597 | gfs2_io_error(gl->gl_sbd); | ||
598 | } | ||
599 | |||
582 | static void buf_lo_after_scan(struct gfs2_jdesc *jd, int error, int pass) | 600 | static void buf_lo_after_scan(struct gfs2_jdesc *jd, int error, int pass) |
583 | { | 601 | { |
584 | struct gfs2_inode *ip = GFS2_I(jd->jd_inode); | 602 | struct gfs2_inode *ip = GFS2_I(jd->jd_inode); |
diff --git a/fs/gfs2/meta_io.c b/fs/gfs2/meta_io.c index 0da390686c08..932415050540 100644 --- a/fs/gfs2/meta_io.c +++ b/fs/gfs2/meta_io.c | |||
@@ -98,24 +98,6 @@ const struct address_space_operations gfs2_meta_aops = { | |||
98 | }; | 98 | }; |
99 | 99 | ||
100 | /** | 100 | /** |
101 | * gfs2_meta_sync - Sync all buffers associated with a glock | ||
102 | * @gl: The glock | ||
103 | * | ||
104 | */ | ||
105 | |||
106 | void gfs2_meta_sync(struct gfs2_glock *gl) | ||
107 | { | ||
108 | struct address_space *mapping = gfs2_glock2aspace(gl); | ||
109 | int error; | ||
110 | |||
111 | filemap_fdatawrite(mapping); | ||
112 | error = filemap_fdatawait(mapping); | ||
113 | |||
114 | if (error) | ||
115 | gfs2_io_error(gl->gl_sbd); | ||
116 | } | ||
117 | |||
118 | /** | ||
119 | * gfs2_getbuf - Get a buffer with a given address space | 101 | * gfs2_getbuf - Get a buffer with a given address space |
120 | * @gl: the glock | 102 | * @gl: the glock |
121 | * @blkno: the block number (filesystem scope) | 103 | * @blkno: the block number (filesystem scope) |
diff --git a/fs/gfs2/meta_io.h b/fs/gfs2/meta_io.h index 0d4c843b6f8e..4823b934208a 100644 --- a/fs/gfs2/meta_io.h +++ b/fs/gfs2/meta_io.h | |||
@@ -48,21 +48,17 @@ static inline struct gfs2_sbd *gfs2_mapping2sbd(struct address_space *mapping) | |||
48 | return inode->i_sb->s_fs_info; | 48 | return inode->i_sb->s_fs_info; |
49 | } | 49 | } |
50 | 50 | ||
51 | void gfs2_meta_sync(struct gfs2_glock *gl); | 51 | extern struct buffer_head *gfs2_meta_new(struct gfs2_glock *gl, u64 blkno); |
52 | 52 | extern int gfs2_meta_read(struct gfs2_glock *gl, u64 blkno, int flags, | |
53 | struct buffer_head *gfs2_meta_new(struct gfs2_glock *gl, u64 blkno); | 53 | struct buffer_head **bhp); |
54 | int gfs2_meta_read(struct gfs2_glock *gl, u64 blkno, | 54 | extern int gfs2_meta_wait(struct gfs2_sbd *sdp, struct buffer_head *bh); |
55 | int flags, struct buffer_head **bhp); | 55 | extern struct buffer_head *gfs2_getbuf(struct gfs2_glock *gl, u64 blkno, |
56 | int gfs2_meta_wait(struct gfs2_sbd *sdp, struct buffer_head *bh); | 56 | int create); |
57 | struct buffer_head *gfs2_getbuf(struct gfs2_glock *gl, u64 blkno, int create); | 57 | extern void gfs2_remove_from_journal(struct buffer_head *bh, |
58 | 58 | struct gfs2_trans *tr, int meta); | |
59 | void gfs2_remove_from_journal(struct buffer_head *bh, struct gfs2_trans *tr, | 59 | extern void gfs2_meta_wipe(struct gfs2_inode *ip, u64 bstart, u32 blen); |
60 | int meta); | 60 | extern int gfs2_meta_indirect_buffer(struct gfs2_inode *ip, int height, u64 num, |
61 | 61 | struct buffer_head **bhp); | |
62 | void gfs2_meta_wipe(struct gfs2_inode *ip, u64 bstart, u32 blen); | ||
63 | |||
64 | int gfs2_meta_indirect_buffer(struct gfs2_inode *ip, int height, u64 num, | ||
65 | struct buffer_head **bhp); | ||
66 | 62 | ||
67 | static inline int gfs2_meta_inode_buffer(struct gfs2_inode *ip, | 63 | static inline int gfs2_meta_inode_buffer(struct gfs2_inode *ip, |
68 | struct buffer_head **bhp) | 64 | struct buffer_head **bhp) |
diff --git a/fs/gfs2/ops_fstype.c b/fs/gfs2/ops_fstype.c index 0262c190b6f9..19ff5e8c285c 100644 --- a/fs/gfs2/ops_fstype.c +++ b/fs/gfs2/ops_fstype.c | |||
@@ -646,6 +646,48 @@ static int gfs2_jindex_hold(struct gfs2_sbd *sdp, struct gfs2_holder *ji_gh) | |||
646 | return error; | 646 | return error; |
647 | } | 647 | } |
648 | 648 | ||
649 | /** | ||
650 | * check_journal_clean - Make sure a journal is clean for a spectator mount | ||
651 | * @sdp: The GFS2 superblock | ||
652 | * @jd: The journal descriptor | ||
653 | * | ||
654 | * Returns: 0 if the journal is clean or locked, else an error | ||
655 | */ | ||
656 | static int check_journal_clean(struct gfs2_sbd *sdp, struct gfs2_jdesc *jd) | ||
657 | { | ||
658 | int error; | ||
659 | struct gfs2_holder j_gh; | ||
660 | struct gfs2_log_header_host head; | ||
661 | struct gfs2_inode *ip; | ||
662 | |||
663 | ip = GFS2_I(jd->jd_inode); | ||
664 | error = gfs2_glock_nq_init(ip->i_gl, LM_ST_SHARED, LM_FLAG_NOEXP | | ||
665 | GL_EXACT | GL_NOCACHE, &j_gh); | ||
666 | if (error) { | ||
667 | fs_err(sdp, "Error locking journal for spectator mount.\n"); | ||
668 | return -EPERM; | ||
669 | } | ||
670 | error = gfs2_jdesc_check(jd); | ||
671 | if (error) { | ||
672 | fs_err(sdp, "Error checking journal for spectator mount.\n"); | ||
673 | goto out_unlock; | ||
674 | } | ||
675 | error = gfs2_find_jhead(jd, &head); | ||
676 | if (error) { | ||
677 | fs_err(sdp, "Error parsing journal for spectator mount.\n"); | ||
678 | goto out_unlock; | ||
679 | } | ||
680 | if (!(head.lh_flags & GFS2_LOG_HEAD_UNMOUNT)) { | ||
681 | error = -EPERM; | ||
682 | fs_err(sdp, "jid=%u: Journal is dirty, so the first mounter " | ||
683 | "must not be a spectator.\n", jd->jd_jid); | ||
684 | } | ||
685 | |||
686 | out_unlock: | ||
687 | gfs2_glock_dq_uninit(&j_gh); | ||
688 | return error; | ||
689 | } | ||
690 | |||
649 | static int init_journal(struct gfs2_sbd *sdp, int undo) | 691 | static int init_journal(struct gfs2_sbd *sdp, int undo) |
650 | { | 692 | { |
651 | struct inode *master = sdp->sd_master_dir->d_inode; | 693 | struct inode *master = sdp->sd_master_dir->d_inode; |
@@ -732,8 +774,15 @@ static int init_journal(struct gfs2_sbd *sdp, int undo) | |||
732 | if (sdp->sd_lockstruct.ls_first) { | 774 | if (sdp->sd_lockstruct.ls_first) { |
733 | unsigned int x; | 775 | unsigned int x; |
734 | for (x = 0; x < sdp->sd_journals; x++) { | 776 | for (x = 0; x < sdp->sd_journals; x++) { |
735 | error = gfs2_recover_journal(gfs2_jdesc_find(sdp, x), | 777 | struct gfs2_jdesc *jd = gfs2_jdesc_find(sdp, x); |
736 | true); | 778 | |
779 | if (sdp->sd_args.ar_spectator) { | ||
780 | error = check_journal_clean(sdp, jd); | ||
781 | if (error) | ||
782 | goto fail_jinode_gh; | ||
783 | continue; | ||
784 | } | ||
785 | error = gfs2_recover_journal(jd, true); | ||
737 | if (error) { | 786 | if (error) { |
738 | fs_err(sdp, "error recovering journal %u: %d\n", | 787 | fs_err(sdp, "error recovering journal %u: %d\n", |
739 | x, error); | 788 | x, error); |